ATLAS Offline Software
Loading...
Searching...
No Matches
BunchGroupSet.py
Go to the documentation of this file.
1# Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
2
3from itertools import groupby
4
5from AthenaCommon.Logging import logging
6from AthenaConfiguration.Enums import BeamType
7
8from .Limits import Limits
9from .L1MenuFlags import L1MenuFlags
10
11
12log = logging.getLogger(__name__)
13
15 """
16 create BunchGroupSet for simulation
17
18 This BGS is independent from the menu, and contains only BG0 (BCRVeto) and BG1 (Paired)
19 """
20 bgs = BunchGroupSet("MC")
21 bgs.addBunchGroup( BunchGroupSet.BunchGroup(name = 'BCRVeto', internalNumber = 0).addRange(0,3539).addRange(3561,3563).normalize() )\
22 .addBunchGroup( BunchGroupSet.BunchGroup(name = 'Paired', internalNumber = 1).addTrain(0,3564).normalize() )
23 return bgs
24
25
27 """
28 sets default bunchgroups for all menus, needed for simulation.
29 """
30 if hasattr(L1MenuFlags, "BunchGroupNames"): # if flag has been set
31 # if menu defines bunchgroup names, then we generate a bunchgroup set from that
32 name = L1MenuFlags.MenuSetup().partition('_')[0]
33 bgs = BunchGroupSet(name)
34 bgs.addBunchGroup( BunchGroupSet.BunchGroup(name = 'BCRVeto', internalNumber = 0).addRange(0,3539).addRange(3561,3563).normalize() )\
35 .addBunchGroup( BunchGroupSet.BunchGroup(name = 'Paired', internalNumber = 1).addTrain(0,3445).addTrain(3536,4).addTrain(3561,3).normalize() )
36 if flags.Beam.Type is BeamType.Cosmics:
37 bgs.addBunchGroup( BunchGroupSet.BunchGroup(name = 'EMPTY', internalNumber = 3).addTrain(0,3564).normalize() )
38
39 bunchgroupnames = L1MenuFlags.BunchGroupNames()[:Limits.NumBunchgroups]
40 bunchgroupnames += ['NotUsed'] * (Limits.NumBunchgroups - len(bunchgroupnames))
41 for i,bgname in enumerate(bunchgroupnames):
42 bgs.bunchGroups[i].name = bgname
43 else:
45
46 return bgs
47
48
50
52 nameUndefBG = "NotUsed"
53 def __init__(self, internalNumber, name = nameUndefBG, partition=0, bunches=None):
54 # check if internalNumber is within limits
55 if internalNumber<0 or internalNumber >= Limits.NumBunchgroups:
56 raise RuntimeError('Cannot create bunchgroup with internal number %i (must be between 0 and %i)' % (internalNumber, Limits.NumBunchgroups-1))
57 self.name = name # name of the bunchgroup
58 self.internalNumber = internalNumber # number between 0 and 15
59 self.menuPartition = partition # CTP partition that the bunchgroup belongs to
60 self.bunches = bunches if bunches else [] # list of bcids
61 self.normalized = [] # list of trains (filled in normalized())
62 def __str__(self):
63 return "bunchgroup %s(%i) with %i bunches" % (self.name, self.internalNumber, len(self))
64 def __len__(self):
65 return len(self.bunches)
66 def addBunch(self, bcid):
67 self.bunches += [ bcid ]
68 return self
69 def addRange(self, firstbcid, lastbcid):
70 self.bunches += list(range(firstbcid, lastbcid+1))
71 return self
72 def addTrain(self, firstbcid, length):
73 self.bunches += list(range(firstbcid, firstbcid+length))
74 return self
75 def normalize(self):
76 """ turn list of bunches into trains """
77 self.normalized = []
78 self.bunches = sorted(list(set(self.bunches))) # uniq and sort
79 if any(map(lambda bcid : bcid<0 or bcid >= 3564, self.bunches)):
80 raise RuntimeError("Found bcid outside range 0..3563 in bunchgroup %s" % self.name)
81 for k,g in groupby(enumerate(self.bunches), lambda x : x[1]-x[0]):
82 train = list(g)
83 self.normalized += [ (train[0][1], len(train)) ]
84 return self
85 def json(self):
86 confObj = {
87 "name": self.name,
88 "id": self.internalNumber,
89 "info": f"{len(self)} bunches, {len(self.normalized)} groups",
90 "bcids": [ {"first": first, "length": length} for first, length in self.normalized ]
91 }
92 return confObj
93
94
95 def __init__(self, name='', menuPartition=0):
96 self.name = name
97 self.menuPartition = menuPartition
98 self.bunchGroups = [ BunchGroupSet.BunchGroup(i) for i in range(0,Limits.NumBunchgroups) ] # initialize all BunchGroups
99
100 def __len__(self):
101 return len(self.bunchGroups)
102
103
104 @classmethod
105 def partitioning(cls):
106 first = L1MenuFlags.BunchGroupPartitioning()
107 last = first[1:] + [ Limits.NumBunchgroups ]
108 partitioning = dict( zip([1,2,3],zip(first,last)) )
109 return partitioning
110
111
112 def resize(self, newsize):
113 if type(self.bunchGroups) is not list:
114 self.bunchGroups = []
115 self.bunchGroups += newsize * [None]
116 self.bunchGroups = self.bunchGroups[:newsize]
117
118
119 def addBunchGroup(self, bunchGroup):
120 # check if one already exists with this number
121 doesExist = self.bunchGroups[bunchGroup.internalNumber].name != BunchGroupSet.BunchGroup.nameUndefBG
122 if doesExist:
123 raise RuntimeError("Adding bunchgroup with internal number %i, which already exists" % bunchGroup.internalNumber)
124
125 partition=0
126 if hasattr(L1MenuFlags, "BunchGroupPartitioning"):
127 for lowestBG in L1MenuFlags.BunchGroupPartitioning():
128 if bunchGroup.internalNumber >= lowestBG:
129 partition += 1
130 bunchGroup.partition = partition
131 self.bunchGroups[bunchGroup.internalNumber] = bunchGroup
132 return self
133
134
135 def json(self):
136 confObj = {f"BGRP{bg.internalNumber}": bg.json() for bg in self.bunchGroups}
137 return confObj
138
139 def writeJSON(self, outputFile, destdir="./", pretty=True):
140 outputFile = destdir.rstrip('/') + '/' + outputFile
141 confObj = {
142 "name": self.name,
143 "filetype": "bunchgroupset",
144 "bunchGroups": self.json()
145 }
146 with open( outputFile, mode="wt" ) as fh:
147 import json
148 json.dump(confObj, fh, indent = 4 if pretty else None, separators=(',', ': '))
149 log.info("Wrote %s", outputFile)
150 return outputFile
nlohmann::json json
Double_t normalize(TF1 *func, Double_t *rampl=NULL, Double_t from=0., Double_t to=0., Double_t step=1.)
STL class.
__init__(self, internalNumber, name=nameUndefBG, partition=0, bunches=None)
writeJSON(self, outputFile, destdir="./", pretty=True)
__init__(self, name='', menuPartition=0)
STL class.