ATLAS Offline Software
Loading...
Searching...
No Matches
TileTBPulseMonitorAlgorithm.py
Go to the documentation of this file.
2# Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3#
4'''
5@file TileTBPulseMonitorAlgorithm.py
6@brief Python configuration of TileTBPulseMonitorAlgorithm algorithm for the Run III
7'''
8
9from AthenaConfiguration.Enums import Format
10from TileMonitoring.TileMonitoringCfgHelper import getLegacyChannelForDemonstrator
11
12
13def getPMT(partition, channel):
14 ''' Function to get PMT number: 0,1 '''
15
16 channelToPMT = [
17 # LBA,LBC:
18 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
19 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
20 0, 1, 0, 1, 0, 1, -1, -1, 0, 1, 0, 1,
21 0, 1, 0, 1, 0, 1, 0, -1, 0, 1, 0, 1,
22 # EBA,EBC:
23 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
24 0, 0, 0, 1, 0, 1, -1, -1, 0, 1, 0, 1,
25 -1, -1, -1, -1, -1, -1, 0, 0, 1, -1, -1, 1,
26 1, 1, 0, 0, 1, 0, -1, -1, -1, -1, -1, -1 ]
27
28 # In gap scintillators (E3,E4,E1,E2) there is only one pmt per cell
29 if partition in ['EBA', 'EBC'] and channel in [0, 1, 12, 13]:
30 pmt = 0
31 else:
32 pmt = channelToPMT[channel+48] if partition in ['EBA', 'EBC'] else channelToPMT[channel]
33
34 # Mirroring of odd/even numbers in negative side
35 # (central symmetry of negative/positive drawers)
36 if (pmt != -1 and partition in ['LBC', 'EBC']):
37 pmt = 1 - pmt
38
39 return pmt
40
41
42def TileTBPulseMonitoringConfig(flags, timeRange=[-100, 100], fragIDs=[0x100, 0x101, 0x200, 0x201, 0x402], useDemoCabling=2018, useFELIX=False, **kwargs):
43
44 ''' Function to configure TileTBPulseMonitorAlgorithm algorithm in the monitoring system.'''
45
46 suffix = "Flx" if useFELIX else ""
47 topPath = 'TestBeam/' + ('Felix' if useFELIX else 'Legacy')
48
49 from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
50 result = ComponentAccumulator()
51
52 from TileGeoModel.TileGMConfig import TileGMCfg
53 result.merge(TileGMCfg(flags))
54
55 from TileConditions.TileCablingSvcConfig import TileCablingSvcCfg
56 result.merge(TileCablingSvcCfg(flags))
57
58 from TileConditions.TileInfoLoaderConfig import TileInfoLoaderCfg
59 result.merge(TileInfoLoaderCfg(flags))
60
61 from AthenaMonitoring import AthMonitorCfgHelper
62 helper = AthMonitorCfgHelper(flags, f'TileTBPulse{suffix}Monitoring')
63
64 from AthenaConfiguration.ComponentFactory import CompFactory
65 tileTBPulseMonAlg = helper.addAlgorithm(CompFactory.TileTBPulseMonitorAlgorithm, f'TileTBPulse{suffix}MonAlg')
66
67 tileTBPulseMonAlg.TriggerChain = ''
68
69 from TileCalibBlobObjs.Classes import TileCalibUtils as Tile
70
71 modules = []
72 if fragIDs:
73 for fragID in fragIDs:
74 ros = fragID >> 8
75 drawer = fragID & 0x3F
76 modules += [Tile.getDrawerString(ros, drawer)]
77 else:
78 for ros in range(1, Tile.MAX_ROS):
79 for drawer in range(0, Tile.MAX_DRAWER):
80 fragIDs += [(ros << 8) | drawer]
81 modules += [Tile.getDrawerString(ros, drawer)]
82
83 tileTBPulseMonAlg.TileFragIDs = fragIDs
84
85 kwargs.setdefault('TileDigitsContainer', f'TileDigits{suffix}Cnt')
86 kwargs.setdefault('TileRawChannelContainer', flags.Tile.RawChannelContainer.replace('TileRawChannel', f'TileRawChannel{suffix}'))
87 for k, v in kwargs.items():
88 setattr(tileTBPulseMonAlg, k, v)
89
90 run = str(flags.Input.RunNumbers[0])
91
92 # Configure histogram with TileTBPulseMonAlg algorithm execution time
93 executeTimeGroup = helper.addGroup(tileTBPulseMonAlg, 'TileTBPulseMonExecuteTime', topPath)
94 executeTimeGroup.defineHistogram('TIME_execute', path='PulseShape', type='TH1F',
95 title='Time for execute TileTBPulseMonAlg algorithm;time [#mus]',
96 xbins=100, xmin=0, xmax=10000)
97
98 from TileMonitoring.TileMonitoringCfgHelper import getCellName
99
100 def addPulseShapeHistogramsArray(helper, modules, algorithm, name, title, path, type='TH2D',
101 xbins=100, xmin=-100, xmax=100, ybins=100, ymin=-0.2, ymax=1.5,
102 run='', value='', aliasPrefix='', useDemoCabling=2018):
103 ''' This function configures 2D (or 1D Profile) histograms with Tile pulse shape per module, channel, gain '''
104
105 pulseShapeArray = helper.addArray([modules], algorithm, name, topPath=path)
106 for postfix, tool in pulseShapeArray.Tools.items():
107 moduleName = postfix[1:]
108 partition = moduleName[:3]
109 module = int(moduleName[3:]) - 1
110 for channel in range(0, Tile.MAX_CHAN):
111 legacyChannel = getLegacyChannelForDemonstrator(useDemoCabling, partition, module, channel)
112 pmt = getPMT(partition, legacyChannel)
113 pmtName = f'Channel_{channel}' if pmt < 0 else {0 : 'PMT_Up', 1 : 'PMT_Down'}[pmt]
114 cell = getCellName(partition, legacyChannel)
115 cellName = cell.replace('B', 'BC') if (partition in ['LBA','LBC'] and cell and cell[0] == 'B' and cell != 'B9') else cell
116 for gain in range(0, Tile.MAX_GAIN):
117 gainName = {0 : 'lo', 1 : 'hi'}[gain]
118 fullPath = f'{partition}/{moduleName}'
119 name = f'time_{channel}_{gain},amplitude_{channel}_{gain};{aliasPrefix}{cellName}_{moduleName}_{pmtName}_{gainName}'
120 fullTitle = f'Run {run} {moduleName} Channel {channel} Gain {gainName}: {title};time [ns];Normalized Units'
121 tool.defineHistogram(name, title=fullTitle, path=fullPath, type=type,
122 xbins=xbins, xmin=xmin, xmax=xmax, ybins=ybins, ymin=ymin, ymax=ymax)
123 return pulseShapeArray
124
125 addPulseShapeHistogramsArray(helper, modules, tileTBPulseMonAlg, name='TilePulseShape', title='Pulse shape',
126 path=f'{topPath}/PulseShape', xbins=abs(timeRange[1]), xmin=timeRange[0], xmax=timeRange[1],
127 run=run, aliasPrefix='pulseShape_', useDemoCabling=useDemoCabling)
128
129 addPulseShapeHistogramsArray(helper, modules, tileTBPulseMonAlg, name='TilePulseShapeProfile',
130 title='Pulse shape profile', path=f'{topPath}/PulseShape', type='TProfile',
131 xbins=abs(timeRange[1]), xmin=timeRange[0], xmax=timeRange[1],
132 ybins=None, ymin=None, ymax=None, run=run, aliasPrefix='pulseShapeProfile_',
133 useDemoCabling=useDemoCabling)
134
135 accumalator = helper.result()
136 result.merge(accumalator)
137 return result
138
139
140if __name__=='__main__':
141
142 # Setup logs
143 from AthenaCommon.Logging import log
144 from AthenaCommon.Constants import INFO
145 log.setLevel(INFO)
146
147 # Set the Athena configuration flags
148 from AthenaConfiguration.AllConfigFlags import initConfigFlags
149 from AthenaConfiguration.TestDefaults import defaultGeometryTags, defaultTestFiles
150
151 flags = initConfigFlags()
152 parser = flags.getArgumentParser()
153 parser.add_argument('--postExec', help='Code to execute after setup')
154 parser.add_argument('--digits', default="TileDigitsCnt", help='Tile digits container')
155 parser.add_argument('--channels', default="TileRawChannelCnt",
156 help='Tile raw channel container, if empty they will be reconstructed from digits')
157 parser.add_argument('--time-range', dest='timeRange', nargs=2, default=[-200, 200], help='Time range for pulse shape histograms')
158 parser.add_argument('--frag-ids', dest='fragIDs', nargs="*", default=['0x100', '0x101', '0x200', '0x201', '0x402'],
159 help='Tile Frag IDs of modules to be monitored. Empty=ALL')
160 parser.add_argument('--demo-cabling', dest='demoCabling', type=int, default=2018, help='Time Demonatrator cabling to be used')
161 parser.add_argument('--nsamples', type=int, default=15, help='Number of samples')
162 parser.add_argument('--use-sqlite', dest='useSqlite', default='/afs/cern.ch/user/t/tiledemo/public/efmon/condb/tileSqlite.db',
163 help='Providing local SQlite file, conditions constants will be used from it')
164 args, _ = parser.parse_known_args()
165
166 fragIDs = [int(fragID, base=16) for fragID in args.fragIDs]
167 timeRange = [int(time) for time in args.timeRange]
168
169 flags.Input.Files = defaultTestFiles.RAW_RUN2
170 flags.GeoModel.AtlasVersion = defaultGeometryTags.RUN2
171 flags.Output.HISTFileName = 'TileTBPulseMonitorOutput.root'
172 flags.DQ.useTrigger = False
173 flags.DQ.enableLumiAccess = False
174 flags.Exec.MaxEvents = 3
175 flags.Common.isOnline = True
176
177 flags.Tile.doFit = True
178 flags.Tile.useDCS = False
179 flags.Tile.NoiseFilter = 0
180 flags.Tile.correctTime = False
181 flags.Tile.correctTimeJumps = False
182 flags.Tile.BestPhaseFromCOOL = False
183 flags.Tile.doOverflowFit = False
184
185 if args.channels:
186 flags.Tile.RawChannelContainer = args.channels
187
188 flags.fillFromArgs(parser=parser)
189 flags.lock()
190
191 flags.dump(pattern='Tile.*|Input.*|Exec.*|IOVDb.[D|G].*', evaluate=True)
192
193 # Initialize configuration object, add accumulator, merge, and run.
194 from AthenaConfiguration.MainServicesConfig import MainServicesCfg
195 cfg = MainServicesCfg(flags)
196
197 rawChannels = args.channels
198 if flags.Input.Format is Format.BS:
199 readDigitsFlx = 'Flx' in args.digits
200 from TileByteStream.TileByteStreamConfig import TileRawDataReadingCfg
201 cfg.merge( TileRawDataReadingCfg(flags, readMuRcv=False,
202 readDigits=(not readDigitsFlx),
203 readDigitsFlx=readDigitsFlx) )
204
205 else:
206 from AthenaPoolCnvSvc.PoolReadConfig import PoolReadCfg
207 cfg.merge(PoolReadCfg(flags))
208
209 if not rawChannels:
210 # Run reconstruction to produce Tile raw channels
211 rawChannels = flags.Tile.RawChannelContainer
212
213 from TileRecUtils.TileRawChannelMakerConfig import TileRawChannelMakerCfg
214 cfg.merge( TileRawChannelMakerCfg(flags) )
215 if args.threads and (args.threads > 1):
216 rawChMaker = cfg.getEventAlgo('TileRChMaker')
217 rawChMaker.Cardinality = args.threads
218
219 if args.useSqlite:
220 cfg.getService('IOVDbSvc').overrideTags += [
221 f'<prefix>/TILE</prefix> <db>sqlite://;schema={args.useSqlite};dbname={flags.IOVDb.DatabaseInstance}</db>'
222 ]
223
224 cfg.merge(TileTBPulseMonitoringConfig(flags,
225 fragIDs=fragIDs,
226 timeRange=timeRange,
227 useDemoCabling=args.demoCabling,
228 TileRawChannelContainer=rawChannels,
229 TileDigitsContainer=args.digits))
230
231 tileInfoLoader = cfg.getService('TileInfoLoader')
232 tileInfoLoader.NSamples = args.nsamples
233 tileInfoLoader.TrigSample = (args.nsamples - 1) // 2 # Floor division
234
235 # Any last things to do?
236 if args.postExec:
237 log.info('Executing postExec: %s', args.postExec)
238 exec(args.postExec)
239
240 cfg.printConfig(withDetails=True, summariseProps=True)
241
242 cfg.store(open('TileTBPulseMonitorAlgorithm.pkl', 'wb'))
243
244 sc = cfg.run()
245
246 import sys
247 # Success should be 0
248 sys.exit(not sc.isSuccess())
TileTBPulseMonitoringConfig(flags, timeRange=[-100, 100], fragIDs=[0x100, 0x101, 0x200, 0x201, 0x402], useDemoCabling=2018, useFELIX=False, **kwargs)