Belle II Software development
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
18using 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"),
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))
84 else
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();
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();
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;
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();
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;
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 {
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) {
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 successfully =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 status 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.