Belle II Software  release-08-01-10
KLMChannelStatusAlgorithm.cc
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 
9 /* Own header. */
10 #include <klm/calibration/KLMChannelStatusAlgorithm.h>
11 
12 /* Basf2 headers. */
13 #include <framework/logging/Logger.h>
14 
15 /* ROOT headers. */
16 #include <TTree.h>
17 
18 using namespace Belle2;
19 
21 {
22 }
23 
25 {
26  m_ModuleStatus = new KLMChannelStatus(*results.m_ModuleStatus);
27  m_ChannelStatus = new KLMChannelStatus(*results.m_ChannelStatus);
28  m_HitMapChannel = results.m_HitMapChannel;
29  m_HitMapModule = results.m_HitMapModule;
30  m_HitMapSector = results.m_HitMapSector;
31  m_HitMapModuleNoHot = results.m_HitMapModuleNoHot;
32  m_HitMapSectorNoHot = results.m_HitMapSectorNoHot;
33  m_ModuleActiveChannelMap = results.m_ModuleActiveChannelMap;
34  m_TotalHitNumber = results.m_TotalHitNumber;
35  m_HitNumberBKLM = results.m_HitNumberBKLM;
36  m_HitNumberEKLM = results.m_HitNumberEKLM;
37  m_HitNumberBKLMNoHot = results.m_HitNumberBKLMNoHot;
38  m_HitNumberEKLMNoHot = results.m_HitNumberEKLMNoHot;
39 }
40 
42 {
43  if (m_ModuleStatus != nullptr)
44  delete m_ModuleStatus;
45  if (m_ChannelStatus != nullptr)
46  delete m_ChannelStatus;
47 }
48 
50  CalibrationAlgorithm("KLMChannelStatusCollector"),
51  m_ElementNumbers(&(KLMElementNumbers::Instance()))
52 {
53 }
54 
56 {
57 }
58 
60 {
61  KLMChannelNumber channel, module, sector;
62  unsigned int hits, moduleHits, maxHits;
63  /*
64  * Fill channel hit map. Note that more than one entry can exist for the same
65  * channel due to merging of collected data for several runs. Thus, the
66  * number of hits is summed.
67  */
68  std::shared_ptr<TTree> calibrationData;
69  calibrationData = getObjectPtr<TTree>("calibration_data");
70  calibrationData->SetBranchAddress("channel", &channel);
71  calibrationData->SetBranchAddress("hits", &hits);
72  int n = calibrationData->GetEntries();
77  for (int i = 0; i < n; ++i) {
78  calibrationData->GetEntry(i);
80  channel, m_Results.m_HitMapChannel.getChannelData(channel) + hits);
82  if (m_ElementNumbers->isBKLMChannel(channel))
83  m_Results.m_HitNumberBKLM += hits;
84  else
85  m_Results.m_HitNumberEKLM += hits;
86  }
88  /*
89  * A new object is created, because saveCalibration() stores a pointer
90  * to KLMChannelStatus, and it is necessary to save the payloads to commit
91  * them at the end of calibration.
92  */
95  /* If there are no hits, then mark all channels as dead. */
96  KLMChannelIndex klmChannels;
97  if (m_Results.m_TotalHitNumber == 0) {
98  for (KLMChannelIndex& klmChannel : klmChannels) {
99  channel = klmChannel.getKLMChannelNumber();
101  }
102  saveCalibration(m_Results.m_ChannelStatus, "KLMChannelStatus");
104  }
105  /* Fill module and sector hit maps. */
107  for (KLMChannelIndex& klmModule : klmModules)
108  m_Results.m_HitMapModule.setChannelData(klmModule.getKLMModuleNumber(), 0);
110  for (KLMChannelIndex& klmSector : klmSectors)
111  m_Results.m_HitMapSector.setChannelData(klmSector.getKLMSectorNumber(), 0);
112  for (KLMChannelIndex& klmChannel : klmChannels) {
113  channel = klmChannel.getKLMChannelNumber();
114  module = klmChannel.getKLMModuleNumber();
115  sector = klmChannel.getKLMSectorNumber();
116  hits = m_Results.m_HitMapChannel.getChannelData(channel);
118  module, m_Results.m_HitMapModule.getChannelData(module) + hits);
120  sector, m_Results.m_HitMapSector.getChannelData(sector) + hits);
121  }
122  /*
123  * Mark all channels in modules without hits as dead.
124  * Search for hot channels.
125  */
126  for (KLMChannelIndex& klmModule : klmModules) {
127  module = klmModule.getKLMModuleNumber();
128  moduleHits = m_Results.m_HitMapModule.getChannelData(module);
129  KLMChannelIndex klmNextModule(klmModule);
130  ++klmNextModule;
131  KLMChannelIndex klmChannel(klmModule);
133  if (moduleHits == 0) {
134  for (; klmChannel != klmNextModule; ++klmChannel) {
135  channel = klmChannel.getKLMChannelNumber();
137  }
139  continue;
140  }
141  unsigned int activeChannels = 0;
142  for (; klmChannel != klmNextModule; ++klmChannel) {
143  channel = klmChannel.getKLMChannelNumber();
144  hits = m_Results.m_HitMapChannel.getChannelData(channel);
145  if (hits > 0)
146  activeChannels++;
147  }
148  m_Results.m_ModuleActiveChannelMap.setChannelData(module, activeChannels);
149  KLMChannelIndex klmChannelMaxHits;
150  while (1) {
151  klmChannel = klmModule;
153  maxHits = 0;
154  for (; klmChannel != klmNextModule; ++klmChannel) {
155  channel = klmChannel.getKLMChannelNumber();
158  continue;
159  hits = m_Results.m_HitMapChannel.getChannelData(channel);
160  if (hits > maxHits) {
161  klmChannelMaxHits = klmChannel;
162  maxHits = hits;
163  }
164  }
165  if (maxHits == 0)
166  break;
167  if (!markHotChannel(klmChannelMaxHits.getKLMChannelNumber(),
168  moduleHits, activeChannels))
169  break;
170  moduleHits -= maxHits;
171  activeChannels--;
172  }
173  }
174  /* Fill module and sector hit maps with hot channels subtracted. */
175  for (KLMChannelIndex& klmModule : klmModules)
176  m_Results.m_HitMapModuleNoHot.setChannelData(klmModule.getKLMModuleNumber(), 0);
177  for (KLMChannelIndex& klmSector : klmSectors)
178  m_Results.m_HitMapSectorNoHot.setChannelData(klmSector.getKLMSectorNumber(), 0);
181  for (KLMChannelIndex& klmChannel : klmChannels) {
182  channel = klmChannel.getKLMChannelNumber();
184  continue;
185  module = klmChannel.getKLMModuleNumber();
186  sector = klmChannel.getKLMSectorNumber();
187  hits = m_Results.m_HitMapChannel.getChannelData(channel);
189  module, m_Results.m_HitMapModuleNoHot.getChannelData(module) + hits);
191  sector, m_Results.m_HitMapSectorNoHot.getChannelData(sector) + hits);
192  if (m_ElementNumbers->isBKLMChannel(channel))
194  else
196  }
197  /* Sector status. */
198  int activeSectorsBKLM = 0;
199  int activeSectorsEKLM = 0;
200  for (KLMChannelIndex& klmSector : klmSectors) {
201  sector = klmSector.getKLMSectorNumber();
203  if (hits > 0) {
204  if (m_ElementNumbers->isBKLMChannel(sector))
205  activeSectorsBKLM++;
206  else
207  activeSectorsEKLM++;
208  }
209  }
210  double averageHitsActiveSector = 0;
211  if (activeSectorsBKLM > 0) {
212  averageHitsActiveSector = double(m_Results.m_HitNumberBKLMNoHot) /
213  activeSectorsBKLM;
214  }
215  for (KLMChannelIndex bklmSector = klmSectors.beginBKLM();
216  bklmSector != klmSectors.endBKLM(); ++bklmSector) {
217  sector = bklmSector.getKLMSectorNumber();
218  calibrateSector(sector, averageHitsActiveSector);
219  }
220  if (activeSectorsEKLM > 0) {
221  averageHitsActiveSector = double(m_Results.m_HitNumberEKLMNoHot) /
222  activeSectorsBKLM;
223  }
224  for (KLMChannelIndex eklmSector = klmSectors.beginEKLM();
225  eklmSector != klmSectors.endEKLM(); ++eklmSector) {
226  sector = eklmSector.getKLMSectorNumber();
227  calibrateSector(sector, averageHitsActiveSector);
228  }
229  /* Module status. */
230  if (m_Results.m_ModuleStatus == nullptr)
232  for (KLMChannelIndex& klmModule : klmModules)
233  calibrateModule(klmModule.getKLMModuleNumber());
234  /* Channel-based calibration. */
235  bool notEnoughData = false;
236  for (KLMChannelIndex& klmModule : klmModules) {
237  module = klmModule.getKLMModuleNumber();
238  moduleHits = m_Results.m_HitMapModuleNoHot.getChannelData(module);
239  KLMChannelIndex klmNextModule(klmModule);
240  ++klmNextModule;
241  KLMChannelIndex klmChannel(klmModule);
243  if (moduleHits == 0)
244  continue;
245  unsigned int activeChannels = 0;
246  for (; klmChannel != klmNextModule; ++klmChannel) {
247  channel = klmChannel.getKLMChannelNumber();
249  continue;
250  hits = m_Results.m_HitMapChannel.getChannelData(channel);
251  if (hits > 0)
252  activeChannels++;
253  }
254  double averageHits = double(moduleHits) / activeChannels;
255  if (averageHits < m_MinimalAverageHitNumber && !m_ForcedCalibration) {
256  if (!notEnoughData) {
257  B2INFO("KLM module " << klmModule.getKLMModuleNumber() <<
258  " (subdetector " << klmModule.getSubdetector() <<
259  ", section " << klmModule.getSection() <<
260  ", sector " << klmModule.getSector() <<
261  ", layer " << klmModule.getLayer() <<
262  "): " << moduleHits << " hits, average: " << averageHits << ".");
263  }
264  notEnoughData = true;
265  continue;
266  }
267  klmChannel = klmModule;
269  for (; klmChannel != klmNextModule; ++klmChannel)
271  }
272  if (notEnoughData)
274  saveCalibration(m_Results.m_ChannelStatus, "KLMChannelStatus");
276 }
277 
279  KLMSectorNumber sector, double averageHitsActiveSector)
280 {
281  unsigned int hits = m_Results.m_HitMapSectorNoHot.getChannelData(sector);
282  if (hits == 0)
283  return;
284  double r = log(hits / averageHitsActiveSector) / log(10.);
285  if (fabs(r) > m_MaximalLogSectorHitsRatio) {
286  B2WARNING("Number of hits in sector " << sector << " (" << hits <<
287  ") strongly deviates from the average (" <<
288  averageHitsActiveSector <<
289  "), the 10-based logarithm of the ratio is " << r << ".");
290  }
291 }
292 
294 {
295  unsigned int hits = m_Results.m_HitMapModule.getChannelData(module);
296  if (hits >= m_MinimalModuleHitNumber) {
299  } else {
301  module, KLMChannelStatus::c_Dead);
302  }
303 }
304 
306  KLMChannelNumber channel, unsigned int moduleHits, int activeChannels)
307 {
308  unsigned int hits = m_Results.m_HitMapChannel.getChannelData(channel);
309  if (activeChannels == 1) {
312  channel, KLMChannelStatus::c_Hot);
313  return true;
314  }
315  } else {
316  double r = hits / (double(moduleHits - hits) / (activeChannels - 1));
317  if (hits >= m_MinimalHitNumberHotChannel &&
320  channel, KLMChannelStatus::c_Hot);
321  return true;
322  }
323  }
324  return false;
325 }
326 
328 {
329  unsigned int hits = m_Results.m_HitMapChannel.getChannelData(channel);
332  return;
333  if (hits > 0) {
335  channel, KLMChannelStatus::c_Normal);
336  } else {
338  channel, KLMChannelStatus::c_Dead);
339  }
340 }
Base class for calibration algorithms.
void saveCalibration(TClonesArray *data, const std::string &name)
Store DBArray payload with given name with default IOV.
EResult
The result of calibration.
@ c_OK
Finished successfuly =0 in Python.
@ c_NotEnoughData
Needs more data =2 in Python.
void clearCalibrationData()
Clear calibration data.
KLM channel index.
KLMChannelIndex & endEKLM()
Last channel for EKLM.
KLMChannelIndex beginBKLM()
First channel for BKLM.
KLMChannelNumber getKLMChannelNumber() const
Get KLM channel number.
void setIndexLevel(enum IndexLevel indexLevel)
Set index level.
KLMChannelIndex & endBKLM()
Last channel for BKLM.
KLMChannelIndex beginEKLM()
First channel for EKLM.
void setChannelData(KLMChannelNumber channel, const T data)
Set channel data.
const T getChannelData(KLMChannelNumber channel) const
Get channel data.
void setDataAllChannels(const T data)
Set data for all channels.
unsigned int m_HitNumberEKLM
Number of hits in EKLM.
KLMChannelStatus * m_ChannelStatus
Channel status.
KLMChannelMapValue< unsigned int > m_HitMapModuleNoHot
Module hit map (no hit channels).
KLMChannelMapValue< unsigned int > m_HitMapSectorNoHot
Sector hit map (no hot channels).
KLMChannelMapValue< unsigned int > m_HitMapChannel
Channel hit map.
KLMChannelMapValue< unsigned int > m_ModuleActiveChannelMap
Module active-channel map (number of active channels in module).
unsigned int m_HitNumberBKLM
Number of hits in BKLM.
KLMChannelMapValue< unsigned int > m_HitMapModule
Module hit map.
KLMChannelMapValue< unsigned int > m_HitMapSector
Sector hit map.
unsigned int m_HitNumberBKLMNoHot
Number of hits in BKLM (no hot channels).
unsigned int m_HitNumberEKLMNoHot
Number of hits in EKLM (no hot channels).
bool markHotChannel(KLMChannelNumber channel, unsigned int moduleHits, int activeChannels)
Mark hot channel.
double m_MinimalAverageHitNumber
Minimal average number of hits per channel required for calibration.
bool m_ForcedCalibration
Whether the calibration is forced (calibrate even for insufficient average number of hits).
const KLMElementNumbers * m_ElementNumbers
Element numbers.
unsigned int m_MinimalModuleHitNumber
Minimal module hit number for module-based calibration.
void calibrateChannel(KLMChannelNumber channel)
Calibrate channel.
double m_MinimalHitNumberRatioHotChannel
Minimal ratio of number of hits in this channel and average over other channels in this module to mar...
unsigned int m_MinimalHitNumberHotChannel
Minimal number of hits to mark to mark the channel as hot.
void calibrateSector(KLMSectorNumber sector, double averageHitsActiveSector)
Caliobrate sector.
void calibrateModule(KLMModuleNumber module)
Calibrate module.
double m_MaximalLogSectorHitsRatio
Maximal absolute value of the logarithm (base 10) of the ratio of the number of hits in this sector a...
CalibrationAlgorithm::EResult calibrate() override
Calibration.
unsigned int m_MinimalHitNumberSingleHotChannel
Minimal number of hits in a single channel to mark it as hot.
KLM channel status.
void setChannelStatus(KLMChannelNumber channel, enum ChannelStatus status)
Set channel status.
enum ChannelStatus getChannelStatus(KLMChannelNumber channel) const
Get channel status.
void setStatusAllChannels(enum ChannelStatus status)
Set staus for all channels.
@ c_Hot
Hot channel (large background).
@ c_Undetermined
Undetermined (used during calibration).
@ c_Normal
Normally operating channel.
@ c_Dead
Dead channel (no signal).
KLM element numbers.
bool isBKLMChannel(KLMChannelNumber channel) const
Determine whether a given channel is in BKLM.
uint16_t KLMSectorNumber
Sector number.
uint16_t KLMChannelNumber
Channel number.
uint16_t KLMModuleNumber
Module number.
Abstract base class for different kinds of events.