4 Minimal python module for CTP fragment access/modification
6 For C++ implementation see:
7 https://gitlab.cern.ch/atlas-tdaq-software/CTPfragment
14 from PyUtils.Helpers
import ROOT6Setup
17 cppyy.load_library(
'libTrigByteStreamToolsDict')
18 cppyy.load_library(
'libCTPfragment')
19 from ROOT
import CTPdataformat
20 from ROOT
import CTPfragment
as _CTPfragment
21 from ROOT.CTPfragment
import getFolderUpdates
24 FolderEntry = _CTPfragment.FolderEntry
25 ExtraPayload = _CTPfragment.ExtraPayload
28 """Helper to return versioned members of CTPdataformat"""
32 attr =
'%s_v%d' % (name, v)
36 return getattr(obj,attr)
39 """Set value in bitset using mask and shifting n bits to the left"""
40 v = bitset & (0xffffffff ^ (mask << shift))
41 v = v | (value << shift)
45 """Return list of bits [0,1,1,0,...] from list of 32-bit trigger words"""
58 """Return list of trigger words from list of bits"""
61 words[bit//32] |= 1<<(bit%32)
65 """Get CTP fragment format version"""
66 v = (rob.rod_minor_version() >> CTPdataformat.CTPFormatVersionShift) & CTPdataformat.CTPFormatVersionMask
70 """Set CTP fragment format version"""
71 V =
_setBits32(rob.rod_minor_version(), version,
72 CTPdataformat.CTPFormatVersionShift, CTPdataformat.CTPFormatVersionMask)
73 rob.rod_minor_version(V)
78 return (rob.rod_detev_type() >>
_versioned(CTPdataformat,
'HltCounterShift',v) &
_versioned(CTPdataformat,
'HltCounterMask',v))
87 return (rob.rod_detev_type() >> CTPdataformat.LumiBlockShift & CTPdataformat.LumiBlockMask)
90 lbits =
_setBits32(rob.rod_detev_type(), lb, CTPdataformat.LumiBlockShift, CTPdataformat.LumiBlockMask)
91 rob.rod_detev_type(lbits)
94 """Number extra payload words (this includes the time since last L1A)"""
99 return ((rob.rod_minor_version() >>
_versioned(CTPdataformat,
'ProgrammableExtraWordsShift',v)
100 &
_versioned(CTPdataformat,
'ProgrammableExtraWordsMask',v)))
103 """Number extra payload words (this does NOT include the time since last L1A)"""
114 """Return CTPfragment::ExtraPayload object created from CTP ROB"""
115 v = cppyy.gbl.std.vector(
'unsigned int')()
119 x = _CTPfragment.ExtraPayload(v)
125 wrob = eformat.write.ROBFragment(rob)
127 data = [d
for d
in wrob.rod_data()]
136 data.extend(extraWords)
143 V =
_setBits32(wrob.rod_minor_version(), len(extraWords)+ctp_extras,
144 _versioned(CTPdataformat,
'ProgrammableExtraWordsShift',v),
145 _versioned(CTPdataformat,
'ProgrammableExtraWordsMask',v))
146 wrob.rod_minor_version(V)
148 return wrob.readonly()
151 """Get position of LVL1-Accept Bunch from ROD Fragment"""
154 shift =
_versioned(CTPdataformat,
'L1APositionShift',v)
156 return (rob.rod_detev_type() >> shift) & CTPdataformat.L1APositionMask
158 return (rob.rod_minor_version() >> shift) & CTPdataformat.L1APositionMask
161 """Get trigger words"""
168 if v>4
and rob.source_id().module_id()==1:
173 l1abunch = 0
if rob.source_id().module_id()==1
else lvl1AcceptBunch(rob)
175 data = [d
for d
in rob.rod_data()]
176 pos = l1abunch*
_versioned(CTPdataformat,
'DAQwordsPerBunch',v) + pos
177 return data[pos:pos+words]
184 from optparse
import OptionParser
187 parser = OptionParser(usage=
'%prog FILE')
188 parser.add_option(
'-m',
'--moduleid', type=
'int', action=
'store', default=0,
189 help=
'Module ID of CTP fragment [%default]')
191 (opt, args) = parser.parse_args()
196 for event
in eformat.istream(args[0]):
197 ctp_robs = [rob
for rob
in event.children()
198 if rob.source_id().subdetector_id() == eformat.helper.SubDetector.TDAQ_CTP
199 and rob.source_id().module_id() == opt.moduleid]
202 print(
"Cannot find CTP ROB with module ID %d" % opt.moduleid)
206 fe = _CTPfragment.FolderEntry()
210 fe2 = _CTPfragment.FolderEntry()
215 x = _CTPfragment.ExtraPayload()
220 new_event = eformat.write.FullEventFragment()
221 new_event.copy_header(event)
222 for r
in event.children():
223 if r.source_id().subdetector_id() != eformat.helper.SubDetector.TDAQ_CTP:
224 new_event.append(eformat.write.ROBFragment(r))
226 new_event.append(eformat.write.ROBFragment(new_ctp_rob))
228 event = new_event.readonly()
234 folderUpdates = _CTPfragment.getFolderUpdates(x)
236 for f
in folderUpdates:
237 upd += (
'[%d,%d]' % (f.second.folderIndex,f.second.lumiBlock))
239 print(
"L1ID %10d, LB %4d, Version %d, Bunch %d, HLT counter: %3d, Payload #%d %s L1PSK %d BGK %d COOLUPD %s" % (
252 if __name__ ==
"__main__":