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
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
54
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();
73 m_Results.m_HitMapChannel.setDataAllChannels(0);
74 m_Results.m_TotalHitNumber = 0;
75 m_Results.m_HitNumberBKLM = 0;
76 m_Results.m_HitNumberEKLM = 0;
77 for (int i = 0; i < n; ++i) {
78 calibrationData->GetEntry(i);
79 m_Results.m_HitMapChannel.setChannelData(
80 channel, m_Results.m_HitMapChannel.getChannelData(channel) + hits);
81 m_Results.m_TotalHitNumber += 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 */
93 m_Results.m_ChannelStatus = new KLMChannelStatus();
94 m_Results.m_ChannelStatus->setStatusAllChannels(KLMChannelStatus::c_Undetermined);
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();
100 m_Results.m_ChannelStatus->setChannelStatus(channel, KLMChannelStatus::c_Dead);
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);
117 m_Results.m_HitMapModule.setChannelData(
118 module, m_Results.m_HitMapModule.getChannelData(module) + hits);
119 m_Results.m_HitMapSector.setChannelData(
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();
136 m_Results.m_ChannelStatus->setChannelStatus(channel, KLMChannelStatus::c_Dead);
137 }
138 m_Results.m_ModuleActiveChannelMap.setChannelData(module, 0);
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();
156 if (m_Results.m_ChannelStatus->getChannelStatus(channel) ==
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);
179 m_Results.m_HitNumberBKLMNoHot = 0;
180 m_Results.m_HitNumberEKLMNoHot = 0;
181 for (KLMChannelIndex& klmChannel : klmChannels) {
182 channel = klmChannel.getKLMChannelNumber();
183 if (m_Results.m_ChannelStatus->getChannelStatus(channel) == KLMChannelStatus::c_Hot)
184 continue;
185 module = klmChannel.getKLMModuleNumber();
186 sector = klmChannel.getKLMSectorNumber();
187 hits = m_Results.m_HitMapChannel.getChannelData(channel);
188 m_Results.m_HitMapModuleNoHot.setChannelData(
189 module, m_Results.m_HitMapModuleNoHot.getChannelData(module) + hits);
190 m_Results.m_HitMapSectorNoHot.setChannelData(
191 sector, m_Results.m_HitMapSectorNoHot.getChannelData(sector) + hits);
192 if (m_ElementNumbers->isBKLMChannel(channel))
193 m_Results.m_HitNumberBKLMNoHot += hits;
194 else
195 m_Results.m_HitNumberEKLMNoHot += hits;
196 }
197 /* Sector status. */
198 int activeSectorsBKLM = 0;
199 int activeSectorsEKLM = 0;
200 for (KLMChannelIndex& klmSector : klmSectors) {
201 sector = klmSector.getKLMSectorNumber();
202 hits = m_Results.m_HitMapSectorNoHot.getChannelData(sector);
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)
231 m_Results.m_ModuleStatus = new KLMChannelStatus();
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();
248 if (m_Results.m_ChannelStatus->getChannelStatus(channel) == KLMChannelStatus::c_Hot)
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) {
297 m_Results.m_ModuleStatus->setChannelStatus(
299 } else {
300 m_Results.m_ModuleStatus->setChannelStatus(
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) {
311 m_Results.m_ChannelStatus->setChannelStatus(
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 &&
319 m_Results.m_ChannelStatus->setChannelStatus(
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);
330 if (m_Results.m_ChannelStatus->getChannelStatus(channel) ==
332 return;
333 if (hits > 0) {
334 m_Results.m_ChannelStatus->setChannelStatus(
336 } else {
337 m_Results.m_ChannelStatus->setChannelStatus(
338 channel, KLMChannelStatus::c_Dead);
339 }
340}
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.
CalibrationAlgorithm(const std::string &collectorModuleName)
Constructor - sets the prefix for collected objects (won't be accesses until execute(....
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.
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.
@ c_Hot
Hot channel (large background).
@ c_Undetermined
Undetermined (used during calibration).
@ c_Normal
Normally operating channel.
@ c_Dead
Dead channel (no signal).
std::shared_ptr< T > getObjectPtr(const std::string &name, const std::vector< Calibration::ExpRun > &requestedRuns)
Get calibration data object by name and list of runs, the Merge function will be called to generate t...
uint16_t KLMSectorNumber
Sector number.
uint16_t KLMChannelNumber
Channel number.
uint16_t KLMModuleNumber
Module number.
Abstract base class for different kinds of events.