ATLAS Offline Software
Loading...
Searching...
No Matches
TileRODMonitorAlgorithm.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
8
11
13
14 ATH_MSG_DEBUG("in initialize()");
15
16 // initialize superclass
18
20
21 ATH_CHECK( detStore()->retrieve(m_tileHWID) );
22
23 ATH_CHECK( m_cablingSvc.retrieve() );
24 m_cabling = m_cablingSvc->cablingService();
25
26 ATH_CHECK( m_rawChannelContainerKey.initialize() );
28 ATH_CHECK( m_DQstatusKey.initialize() );
29 ATH_CHECK( m_badChannelsKey.initialize() );
30 ATH_CHECK( m_emScaleKey.initialize() );
31 ATH_CHECK( m_DCSStateKey.initialize(m_checkDCS) );
32
35 }
36
37 if (m_timeRange.size() != 2) {
38 ATH_MSG_FATAL( "Size of TimeRange should be 2 (from,to), but is " << m_timeRange.size() );
39 return StatusCode::FAILURE;
40 }
41
42 using namespace Monitored;
43 using Tile = TileCalibUtils;
44
45 int nL1Triggers = getNumberOfL1Triggers();
46
48 Tile::MAX_ROS - 1, nL1Triggers);
49
51 Tile::MAX_ROS - 1, nL1Triggers);
52
54 Tile::MAX_ROS - 1, nL1Triggers);
55
57 Tile::MAX_ROS - 1, nL1Triggers);
58
60 Tile::MAX_ROS - 1, nL1Triggers);
61
63 Tile::MAX_ROS - 1, nL1Triggers);
64
66 Tile::MAX_ROS - 1, nL1Triggers);
67
69 ATH_CHECK( m_robSvc.retrieve() );
70
71 if (m_nROBs > MAX_TILE_ROBS) {
72 int nROBsSetUp = m_nROBs;
74 ATH_MSG_INFO( "Decreasing number of ROBs from " << nROBsSetUp << " to " << m_nROBs );
75 }
76
77 m_tileRobIds.reserve((Tile::MAX_ROS - 1) * m_nROBs); // Partitions * fragments
78 for (unsigned int rodId : {0x510000, 0x520000, 0x530000, 0x540000}) {
79 for (unsigned int fragment = 0; fragment < m_nROBs; ++fragment) {
80 m_tileRobIds.push_back(rodId + fragment);
81 }
82 }
83
84 m_rodFragSizeMapGroups = buildToolMap<int>(m_tools, "TileRodFragmentMapSize", nL1Triggers);
85 m_rodFragSizeLBGroups = buildToolMap<int>(m_tools, "TileRodFragmentSizeLB", nL1Triggers);
86 }
87
88 return StatusCode::SUCCESS;
89}
90
91
92StatusCode TileRODMonitorAlgorithm::fillHistograms( const EventContext& ctx ) const {
93
94 using Tile = TileCalibUtils;
95
96 // In case you want to measure the execution time
97 auto timer = Monitored::Timer("TIME_execute");
98
99 const xAOD::EventInfo* eventInfo = GetEventInfo(ctx).get();
100
101 ATH_MSG_DEBUG(*eventInfo);
102
103 const TileDQstatus* dqStatus = SG::makeHandle(m_DQstatusKey, ctx).get();
104 const TileDCSState* dcsState = m_checkDCS ? SG::ReadCondHandle(m_DCSStateKey, ctx).cptr() : nullptr;
105
108
110 ATH_CHECK( rawChannelContainer.isValid() );
111
112 TileRawChannelUnit::UNIT rawChannelUnit = rawChannelContainer->get_unit();
113
114 //coverity[STACK_USE]
115 float referenceTimes[Tile::MAX_ROS - 1][Tile::MAX_DRAWER][Tile::MAX_CHAN] = {{{0}}};
116 //coverity[STACK_USE]
117 float referenceEnergies[Tile::MAX_ROS - 1][Tile::MAX_DRAWER][Tile::MAX_CHAN] = {{{0}}};
118
119 for (const TileRawChannelCollection* rawChannelCollection : *rawChannelContainer) {
120 if (rawChannelCollection->empty() ) continue;
121
122 HWIdentifier adc_id = rawChannelCollection->front()->adc_HWID();
123 int ros = m_tileHWID->ros(adc_id);
124 int drawer = m_tileHWID->drawer(adc_id);
125 unsigned int drawerIdx = TileCalibUtils::getDrawerIdx(ros, drawer);
126 int partition = ros - 1;
127
128 bool checkDQ = true;
129
130 int fragId = rawChannelCollection->identify();
131 if (std::binary_search(m_fragIDsToIgnoreDMUerrors.begin(), m_fragIDsToIgnoreDMUerrors.end(), fragId)) {
132 checkDQ = false;
133 }
134
135 for (const TileRawChannel* rawChannel : *rawChannelCollection) {
136
137 adc_id = rawChannel->adc_HWID();
138 int channel = m_tileHWID->channel(adc_id);
139 int adc = m_tileHWID->adc(adc_id);
140
141 if (m_cabling->isDisconnected(ros, drawer, channel)) {
142 ATH_MSG_VERBOSE(m_tileHWID->to_string(adc_id) << ": channlel is disconnected => skipping!");
143 continue;
144 }
145
146 if (checkDQ && !(dqStatus->isAdcDQgood(ros, drawer, channel, adc))) {
147 ATH_MSG_VERBOSE(m_tileHWID->to_string(adc_id) << ": DQ is BAD => skipping!");
148 continue;
149 }
150
151 if (m_checkDCS && dcsState->isStatusBad(ros, drawer, channel)) {
152 ATH_MSG_VERBOSE(m_tileHWID->to_string(adc_id) << ": DCS is Bad => skipping!");
153 continue;
154 }
155
156 if (badChannels->getAdcStatus(adc_id).isBad()) {
157 ATH_MSG_VERBOSE(m_tileHWID->to_string(adc_id) << ": Status is BAD => skipping!");
158 continue;
159 }
160
161 if (ros > 2) { // Check if channel is MBTS, no MBTS in LB
162 int pmt;
163 int index;
164 m_cabling->h2s_cell_id_index(adc_id, index, pmt);
165 if (index < -1) {
166 ATH_MSG_VERBOSE(m_tileHWID->to_string(adc_id) << ": MBTS => skipping!");
167 continue;
168 }
169 }
170
171 float amplitude = rawChannel->amplitude();
172 if (rawChannelUnit != m_comparisonUnit) {
173 amplitude = emScale->calibrateChannel(drawerIdx, channel, adc, amplitude, rawChannelUnit, m_finalRawChannelUnit);
174 }
175
176 float time = rawChannel->uncorrTime();
177 if (amplitude > m_energyThreshold && time > m_timeRange[0] && time < m_timeRange[1]) {
178 referenceEnergies[partition][drawer][channel] = amplitude;
179 referenceTimes[partition][drawer][channel] = time;
180 }
181 }
182 }
183
184 std::vector<float> timeDiffs[Tile::MAX_ROS - 1];
185 std::vector<float> energyDiffs[Tile::MAX_ROS - 1];
186 std::vector<float> offlineEnergies[Tile::MAX_ROS - 1];
187 std::vector<float> offlineTimes[Tile::MAX_ROS - 1];
188
189 std::vector<float> dspTimes[Tile::MAX_ROS - 1];
190 std::vector<float> dspTimesChannels[Tile::MAX_ROS - 1];
191 std::vector<float> dspTimesDrawers[Tile::MAX_ROS - 1];
192
194 ATH_CHECK( dspRawChannelContainer.isValid() );
195
196 TileRawChannelUnit::UNIT dspRawChannelUnit = dspRawChannelContainer->get_unit();
197 for (const TileRawChannelCollection* rawChannelCollection : *dspRawChannelContainer) {
198 if (rawChannelCollection->empty() ) continue;
199
200 HWIdentifier adc_id = rawChannelCollection->front()->adc_HWID();
201 int ros = m_tileHWID->ros(adc_id);
202 int drawer = m_tileHWID->drawer(adc_id);
203 unsigned int drawerIdx = TileCalibUtils::getDrawerIdx(ros, drawer);
204 int partition = ros - 1;
205
206 for (const TileRawChannel* rawChannel : *rawChannelCollection) {
207 adc_id = rawChannel->adc_HWID();
208 int channel = m_tileHWID->channel(adc_id);
209 int adc = m_tileHWID->adc(adc_id);
210
211 float offlineEnergy = referenceEnergies[partition][drawer][channel];
212 if (offlineEnergy > m_energyThreshold) {
213 offlineEnergies[partition].push_back(offlineEnergy);
214
215 float offlineTime = referenceTimes[partition][drawer][channel];
216 offlineTimes[partition].push_back(offlineTime);
217
218 float dspEnergy = rawChannel->amplitude();
219 float dspTime = rawChannel->uncorrTime();
220 dspTimes[partition].push_back(dspTime);
221 dspTimesDrawers[partition].push_back(drawer);
222 dspTimesChannels[partition].push_back(channel);
223
224 if (dspRawChannelUnit != m_finalRawChannelUnit) {
225 dspEnergy = emScale->calibrateChannel(drawerIdx, channel, adc, dspEnergy, dspRawChannelUnit, m_finalRawChannelUnit);
226 }
227
228 float energyDiff = (dspEnergy - offlineEnergy) / offlineEnergy;
229 energyDiffs[partition].push_back(energyDiff);
230
231 float timeDiff = dspTime - offlineTime;
232 timeDiffs[partition].push_back(timeDiff);
233
234 ATH_MSG_VERBOSE(m_tileHWID->to_string(adc_id) << ": (DSP/OFFLINE)"
235 << ", energy " << dspEnergy << "/" << offlineEnergy
236 << ", time " << dspTime << "/" << offlineTime);
237 }
238 }
239 }
240
241 // Indices of L1 trigger histograms to be filled in the current event
242 std::vector<int> l1TriggersIndices = getL1TriggerIndices(eventInfo->level1TriggerType());
243
244 for (unsigned int partition = 0; partition < Tile::MAX_ROS - 1; ++partition) {
245 if (!energyDiffs[partition].empty()) {
246 auto monTime = Monitored::Collection("time", offlineTimes[partition]);
247 auto monEnergy = Monitored::Collection("energy", offlineEnergies[partition]);
248 auto monEnergyDiff = Monitored::Collection("energyDiff", energyDiffs[partition]);
249 for (int l1TriggerIdx : l1TriggersIndices) {
250 fill(m_tools[m_energyDiffGroups[partition][l1TriggerIdx]], monEnergyDiff);
251 fill(m_tools[m_energyDiffVsTimeGroups[partition][l1TriggerIdx]], monTime, monEnergyDiff);
252 fill(m_tools[m_energyDiffVsEnergyGroups[partition][l1TriggerIdx]], monEnergy, monEnergyDiff);
253 }
254 }
255
256 if (!timeDiffs[partition].empty()) {
257 auto monTime = Monitored::Collection("time", offlineTimes[partition]);
258 auto monEnergy = Monitored::Collection("energy", offlineEnergies[partition]);
259 auto monTimeDiff = Monitored::Collection("timeDiff", timeDiffs[partition]);
260 for (int l1TriggerIdx : l1TriggersIndices) {
261 fill(m_tools[m_timeDiffGroups[partition][l1TriggerIdx]], monTimeDiff);
262 fill(m_tools[m_timeDiffVsTimeGroups[partition][l1TriggerIdx]], monTime, monTimeDiff);
263 fill(m_tools[m_timeDiffVsEnergyGroups[partition][l1TriggerIdx]], monEnergy, monTimeDiff);
264 }
265 }
266 if (!timeDiffs[partition].empty()) {
267 auto monTime = Monitored::Collection("time", offlineTimes[partition]);
268 auto monEnergy = Monitored::Collection("energy", offlineEnergies[partition]);
269 auto monTimeDiff = Monitored::Collection("timeDiff", timeDiffs[partition]);
270 for (int l1TriggerIdx : l1TriggersIndices) {
271 fill(m_tools[m_timeDiffGroups[partition][l1TriggerIdx]], monTimeDiff);
272 fill(m_tools[m_timeDiffVsTimeGroups[partition][l1TriggerIdx]], monTime, monTimeDiff);
273 fill(m_tools[m_timeDiffVsEnergyGroups[partition][l1TriggerIdx]], monEnergy, monTimeDiff);
274 }
275 }
276
277 if (!dspTimes[partition].empty()) {
278 auto monTime = Monitored::Collection("time", dspTimes[partition]);
279 auto monModule = Monitored::Collection("module", dspTimesDrawers[partition]);
280 auto monChannel = Monitored::Collection("channel", dspTimesChannels[partition]);
281 for (int l1TriggerIdx : l1TriggersIndices) {
282 fill(m_tools[m_dspChanTimeGroups[partition][l1TriggerIdx]], monModule, monChannel, monTime);
283 }
284 }
285
286 }
287
288
290 int allTileRodFragsSize = 0;
291 std::vector<int> roses;
292 std::vector<int> fragments;
293 std::vector<int> fragmentSizes;
294
295 std::vector<const OFFLINE_FRAGMENTS_NAMESPACE::ROBFragment*> robFragments;
296 m_robSvc->getROBData(ctx, m_tileRobIds, robFragments);
297
298 for (const OFFLINE_FRAGMENTS_NAMESPACE::ROBFragment* robFragment : robFragments) {
299 uint32_t rodSourceId = robFragment->rod_source_id();
300 unsigned int ros = (rodSourceId & 0x0F0000) >> 16;
301 unsigned int fragment = rodSourceId & 0x0000FF;
302 int rodFragmentSize = robFragment->rod_fragment_size_word();
303
304 allTileRodFragsSize += rodFragmentSize;
305 if (ros > 0 && ros < Tile::MAX_ROS && fragment < m_nROBs) {
306 roses.push_back(ros);
307 fragments.push_back(fragment);
308 fragmentSizes.push_back(rodFragmentSize);
309 ATH_MSG_VERBOSE("ROS = " << ros << ", ROD fragment = " << fragment << ", size = " << rodFragmentSize);
310 }
311 }
312
313 ATH_MSG_DEBUG( "All Tile ROD fragemsts size: " << allTileRodFragsSize << " in LB " << eventInfo->lumiBlock());
314
315 auto lumiBlock = Monitored::Scalar<int>("lumiBlock", eventInfo->lumiBlock());
316 auto monRodFragsSize = Monitored::Scalar<int>("allRodFragsSize", allTileRodFragsSize);
317 for (int l1TriggerIdx : l1TriggersIndices) {
318 fill(m_tools[m_rodFragSizeLBGroups[l1TriggerIdx]], lumiBlock, monRodFragsSize);
319 }
320
321 if (!fragmentSizes.empty()) {
322 auto monPartition = Monitored::Collection("partition", roses);
323 auto monFragment = Monitored::Collection("fragment", fragments);
324 auto monFragmentSize = Monitored::Collection("rodFragSize", fragmentSizes);
325 for (int l1TriggerIdx : l1TriggersIndices) {
326 fill(m_tools[m_rodFragSizeMapGroups[l1TriggerIdx]], monFragment, monPartition, monFragmentSize);
327 }
328 }
329 }
330
331
332 fill("TileRODMonExecuteTime", timer);
333
334 return StatusCode::SUCCESS;
335}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_FATAL(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_DEBUG(x)
Handle class for reading from StoreGate.
static const Attributes_t empty
const ServiceHandle< StoreGateSvc > & detStore() const
SG::ReadHandle< xAOD::EventInfo > GetEventInfo(const EventContext &) const
Return a ReadHandle for an EventInfo object (get run/event numbers, etc.)
ToolHandleArray< GenericMonitoringTool > m_tools
Array of Generic Monitoring Tools.
Declare a monitored scalar variable.
A monitored timer.
const_pointer_type cptr()
virtual bool isValid() override final
Can the handle be successfully dereferenced?
Static class providing several utility functions and constants.
static unsigned int getDrawerIdx(unsigned int ros, unsigned int drawer)
Returns a drawer hash.
Condition object to keep Tile DCS status from DB.
bool isStatusBad(unsigned int ros, unsigned int drawer) const
Return true if given Tile drawer considered as bad by summary drawer states per LVPS otherwise return...
Class that holds Data Quality fragment information and provides functions to extract the data quality...
bool isAdcDQgood(int partition, int drawer, int ch, int gain) const
returns status of single ADC returns False if there are any errors
int getNumberOfL1Triggers(void) const
Return number of L1 triggers for which histograms should be filled.
virtual StatusCode initialize() override
initialize
std::vector< int > getL1TriggerIndices(uint32_t lvl1TriggerType) const
Return indices of histograms to be filled according fired L1 trigger type.
ServiceHandle< TileCablingSvc > m_cablingSvc
Name of Tile cabling service.
std::vector< int > m_rodFragSizeMapGroups
std::vector< uint32_t > m_tileRobIds
SG::ReadHandleKey< TileRawChannelContainer > m_rawChannelContainerKey
std::vector< std::vector< int > > m_timeDiffVsTimeGroups
TileRawChannelUnit::UNIT m_finalRawChannelUnit
ServiceHandle< IROBDataProviderSvc > m_robSvc
Name of ROB data provider service.
std::vector< std::vector< int > > m_timeDiffVsEnergyGroups
static constexpr int MAX_TILE_ROBS
Gaudi::Property< bool > m_checkDCS
std::vector< std::vector< int > > m_timeDiffGroups
std::vector< std::vector< int > > m_energyDiffVsEnergyGroups
virtual StatusCode initialize() override
initialize
SG::ReadCondHandleKey< TileEMScale > m_emScaleKey
Name of TileEMScale in condition store.
Gaudi::Property< unsigned int > m_nROBs
Gaudi::Property< float > m_energyThreshold
std::vector< int > m_rodFragSizeLBGroups
SG::ReadHandleKey< TileDQstatus > m_DQstatusKey
SG::ReadCondHandleKey< TileBadChannels > m_badChannelsKey
Name of TileBadChannels in condition store.
Gaudi::Property< std::vector< float > > m_timeRange
Gaudi::Property< std::vector< int > > m_fragIDsToIgnoreDMUerrors
const TileCablingService * m_cabling
Gaudi::Property< unsigned int > m_comparisonUnit
Gaudi::Property< bool > m_fillRODfragSizeHistograms
SG::ReadCondHandleKey< TileDCSState > m_DCSStateKey
Name of TileDCSState object in condition store.
std::vector< std::vector< int > > m_energyDiffGroups
SG::ReadHandleKey< TileRawChannelContainer > m_dspRawChannelContainerKey
virtual StatusCode fillHistograms(const EventContext &ctx) const override
adds event to the monitoring histograms
std::vector< std::vector< int > > m_energyDiffVsTimeGroups
std::vector< std::vector< int > > m_dspChanTimeGroups
uint32_t lumiBlock() const
The current event's luminosity block number.
uint16_t level1TriggerType() const
The Level-1 trigger type.
Generic monitoring tool for athena components.
std::vector< V > buildToolMap(const ToolHandleArray< GenericMonitoringTool > &tools, const std::string &baseName, int nHist)
Builds an array of indices (base case)
ValuesCollection< T > Collection(std::string name, const T &collection)
Declare a monitored (double-convertible) collection.
eformat::ROBFragment< PointerType > ROBFragment
Definition RawEvent.h:27
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())
Definition index.py:1
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
EventInfo_v1 EventInfo
Definition of the latest event info version.
void fill(H5::Group &out_file, size_t iterations)