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
18/* C++ headers. */
19#include <memory>
20
21using namespace Belle2;
22
26
28{
29 if (results.m_ModuleStatus != nullptr)
30 m_ModuleStatus = new KLMChannelStatus(*results.m_ModuleStatus);
31 if (results.m_ChannelStatus != nullptr)
32 m_ChannelStatus = new KLMChannelStatus(*results.m_ChannelStatus);
33 m_HitMapChannel = results.m_HitMapChannel;
34 m_HitMapModule = results.m_HitMapModule;
35 m_HitMapSector = results.m_HitMapSector;
36 m_HitMapModuleNoHot = results.m_HitMapModuleNoHot;
37 m_HitMapSectorNoHot = results.m_HitMapSectorNoHot;
38 m_ModuleActiveChannelMap = results.m_ModuleActiveChannelMap;
39 m_TotalHitNumber = results.m_TotalHitNumber;
40 m_HitNumberBKLM = results.m_HitNumberBKLM;
41 m_HitNumberEKLM = results.m_HitNumberEKLM;
42 m_HitNumberBKLMNoHot = results.m_HitNumberBKLMNoHot;
43 m_HitNumberEKLMNoHot = results.m_HitNumberEKLMNoHot;
44}
45
48{
49 if (this == &results)
50 return *this;
51 /* Copy the owned payloads first: if an allocation fails, *this is unchanged. */
52 std::unique_ptr<KLMChannelStatus> moduleStatus;
53 std::unique_ptr<KLMChannelStatus> channelStatus;
54 if (results.m_ModuleStatus != nullptr)
55 moduleStatus = std::make_unique<KLMChannelStatus>(*results.m_ModuleStatus);
56 if (results.m_ChannelStatus != nullptr)
57 channelStatus = std::make_unique<KLMChannelStatus>(*results.m_ChannelStatus);
58 delete m_ModuleStatus;
59 delete m_ChannelStatus;
60 m_ModuleStatus = moduleStatus.release();
61 m_ChannelStatus = channelStatus.release();
62 m_HitMapChannel = results.m_HitMapChannel;
63 m_HitMapModule = results.m_HitMapModule;
64 m_HitMapSector = results.m_HitMapSector;
65 m_HitMapModuleNoHot = results.m_HitMapModuleNoHot;
66 m_HitMapSectorNoHot = results.m_HitMapSectorNoHot;
67 m_ModuleActiveChannelMap = results.m_ModuleActiveChannelMap;
68 m_TotalHitNumber = results.m_TotalHitNumber;
69 m_HitNumberBKLM = results.m_HitNumberBKLM;
70 m_HitNumberEKLM = results.m_HitNumberEKLM;
71 m_HitNumberBKLMNoHot = results.m_HitNumberBKLMNoHot;
72 m_HitNumberEKLMNoHot = results.m_HitNumberEKLMNoHot;
73 return *this;
74}
75
77{
78 if (m_ModuleStatus != nullptr)
79 delete m_ModuleStatus;
80 if (m_ChannelStatus != nullptr)
81 delete m_ChannelStatus;
82}
83
89
93
95{
96 KLMChannelNumber channel, module, sector;
97 unsigned int hits, moduleHits, maxHits;
98 /*
99 * Fill channel hit map. Note that more than one entry can exist for the same
100 * channel due to merging of collected data for several runs. Thus, the
101 * number of hits is summed.
102 */
103 std::shared_ptr<TTree> calibrationData;
104 calibrationData = getObjectPtr<TTree>("calibration_data");
105 calibrationData->SetBranchAddress("channel", &channel);
106 calibrationData->SetBranchAddress("hits", &hits);
107 int n = calibrationData->GetEntries();
108 m_Results.m_HitMapChannel.setDataAllChannels(0);
109 m_Results.m_TotalHitNumber = 0;
110 m_Results.m_HitNumberBKLM = 0;
111 m_Results.m_HitNumberEKLM = 0;
112 for (int i = 0; i < n; ++i) {
113 calibrationData->GetEntry(i);
114 m_Results.m_HitMapChannel.setChannelData(
115 channel, m_Results.m_HitMapChannel.getChannelData(channel) + hits);
116 m_Results.m_TotalHitNumber += hits;
117 if (m_ElementNumbers->isBKLMChannel(channel))
118 m_Results.m_HitNumberBKLM += hits;
119 else
120 m_Results.m_HitNumberEKLM += hits;
121 }
123 /*
124 * A new object is created, because saveCalibration() stores a pointer
125 * to KLMChannelStatus, and it is necessary to save the payloads to commit
126 * them at the end of calibration.
127 */
128 m_Results.m_ChannelStatus = new KLMChannelStatus();
129 m_Results.m_ChannelStatus->setStatusAllChannels(KLMChannelStatus::c_Undetermined);
130 /* If there are no hits, then mark all channels as dead. */
131 KLMChannelIndex klmChannels;
132 if (m_Results.m_TotalHitNumber == 0) {
133 for (const KLMChannelIndex& klmChannel : klmChannels) {
134 channel = klmChannel.getKLMChannelNumber();
135 m_Results.m_ChannelStatus->setChannelStatus(channel, KLMChannelStatus::c_Dead);
136 }
137 saveCalibration(m_Results.m_ChannelStatus, "KLMChannelStatus");
139 }
140 /* Fill module and sector hit maps. */
142 for (const KLMChannelIndex& klmModule : klmModules)
143 m_Results.m_HitMapModule.setChannelData(klmModule.getKLMModuleNumber(), 0);
145 for (const KLMChannelIndex& klmSector : klmSectors)
146 m_Results.m_HitMapSector.setChannelData(klmSector.getKLMSectorNumber(), 0);
147 for (const KLMChannelIndex& klmChannel : klmChannels) {
148 channel = klmChannel.getKLMChannelNumber();
149 module = klmChannel.getKLMModuleNumber();
150 sector = klmChannel.getKLMSectorNumber();
151 hits = m_Results.m_HitMapChannel.getChannelData(channel);
152 m_Results.m_HitMapModule.setChannelData(
153 module, m_Results.m_HitMapModule.getChannelData(module) + hits);
154 m_Results.m_HitMapSector.setChannelData(
155 sector, m_Results.m_HitMapSector.getChannelData(sector) + hits);
156 }
157 /*
158 * Mark all channels in modules without hits as dead.
159 * Search for hot channels.
160 */
161 for (const KLMChannelIndex& klmModule : klmModules) {
162 module = klmModule.getKLMModuleNumber();
163 moduleHits = m_Results.m_HitMapModule.getChannelData(module);
164 KLMChannelIndex klmNextModule(klmModule);
165 ++klmNextModule;
166 KLMChannelIndex klmChannel(klmModule);
168 if (moduleHits == 0) {
169 for (; klmChannel != klmNextModule; ++klmChannel) {
170 channel = klmChannel.getKLMChannelNumber();
171 m_Results.m_ChannelStatus->setChannelStatus(channel, KLMChannelStatus::c_Dead);
172 }
173 m_Results.m_ModuleActiveChannelMap.setChannelData(module, 0);
174 continue;
175 }
176 unsigned int activeChannels = 0;
177 for (; klmChannel != klmNextModule; ++klmChannel) {
178 channel = klmChannel.getKLMChannelNumber();
179 hits = m_Results.m_HitMapChannel.getChannelData(channel);
180 if (hits > 0)
181 activeChannels++;
182 }
183 m_Results.m_ModuleActiveChannelMap.setChannelData(module, activeChannels);
184 KLMChannelIndex klmChannelMaxHits;
185 while (1) {
186 klmChannel = klmModule;
188 maxHits = 0;
189 for (; klmChannel != klmNextModule; ++klmChannel) {
190 channel = klmChannel.getKLMChannelNumber();
191 if (m_Results.m_ChannelStatus->getChannelStatus(channel) ==
193 continue;
194 hits = m_Results.m_HitMapChannel.getChannelData(channel);
195 if (hits > maxHits) {
196 klmChannelMaxHits = klmChannel;
197 maxHits = hits;
198 }
199 }
200 if (maxHits == 0)
201 break;
202 if (!markHotChannel(klmChannelMaxHits.getKLMChannelNumber(),
203 moduleHits, activeChannels))
204 break;
205 moduleHits -= maxHits;
206 activeChannels--;
207 }
208 }
209 /* Fill module and sector hit maps with hot channels subtracted. */
210 for (const KLMChannelIndex& klmModule : klmModules)
211 m_Results.m_HitMapModuleNoHot.setChannelData(klmModule.getKLMModuleNumber(), 0);
212 for (const KLMChannelIndex& klmSector : klmSectors)
213 m_Results.m_HitMapSectorNoHot.setChannelData(klmSector.getKLMSectorNumber(), 0);
214 m_Results.m_HitNumberBKLMNoHot = 0;
215 m_Results.m_HitNumberEKLMNoHot = 0;
216 for (const KLMChannelIndex& klmChannel : klmChannels) {
217 channel = klmChannel.getKLMChannelNumber();
218 if (m_Results.m_ChannelStatus->getChannelStatus(channel) == KLMChannelStatus::c_Hot)
219 continue;
220 module = klmChannel.getKLMModuleNumber();
221 sector = klmChannel.getKLMSectorNumber();
222 hits = m_Results.m_HitMapChannel.getChannelData(channel);
223 m_Results.m_HitMapModuleNoHot.setChannelData(
224 module, m_Results.m_HitMapModuleNoHot.getChannelData(module) + hits);
225 m_Results.m_HitMapSectorNoHot.setChannelData(
226 sector, m_Results.m_HitMapSectorNoHot.getChannelData(sector) + hits);
227 if (m_ElementNumbers->isBKLMChannel(channel))
228 m_Results.m_HitNumberBKLMNoHot += hits;
229 else
230 m_Results.m_HitNumberEKLMNoHot += hits;
231 }
232 /* Sector status. */
233 int activeSectorsBKLM = 0;
234 int activeSectorsEKLM = 0;
235 for (const KLMChannelIndex& klmSector : klmSectors) {
236 sector = klmSector.getKLMSectorNumber();
237 hits = m_Results.m_HitMapSectorNoHot.getChannelData(sector);
238 if (hits > 0) {
239 if (m_ElementNumbers->isBKLMChannel(sector))
240 activeSectorsBKLM++;
241 else
242 activeSectorsEKLM++;
243 }
244 }
245 double averageHitsActiveSector = 0;
246 if (activeSectorsBKLM > 0) {
247 averageHitsActiveSector = double(m_Results.m_HitNumberBKLMNoHot) /
248 activeSectorsBKLM;
249 }
250 for (KLMChannelIndex bklmSector = klmSectors.beginBKLM();
251 bklmSector != klmSectors.endBKLM(); ++bklmSector) {
252 sector = bklmSector.getKLMSectorNumber();
253 calibrateSector(sector, averageHitsActiveSector);
254 }
255 if (activeSectorsEKLM > 0) {
256 averageHitsActiveSector = double(m_Results.m_HitNumberEKLMNoHot) /
257 activeSectorsBKLM;
258 }
259 for (KLMChannelIndex eklmSector = klmSectors.beginEKLM();
260 eklmSector != klmSectors.endEKLM(); ++eklmSector) {
261 sector = eklmSector.getKLMSectorNumber();
262 calibrateSector(sector, averageHitsActiveSector);
263 }
264 /* Module status. */
265 if (m_Results.m_ModuleStatus == nullptr)
266 m_Results.m_ModuleStatus = new KLMChannelStatus();
267 for (const KLMChannelIndex& klmModule : klmModules)
268 calibrateModule(klmModule.getKLMModuleNumber());
269 /* Channel-based calibration. */
270 bool notEnoughData = false;
271 for (const KLMChannelIndex& klmModule : klmModules) {
272 module = klmModule.getKLMModuleNumber();
273 moduleHits = m_Results.m_HitMapModuleNoHot.getChannelData(module);
274 KLMChannelIndex klmNextModule(klmModule);
275 ++klmNextModule;
276 KLMChannelIndex klmChannel(klmModule);
278 if (moduleHits == 0)
279 continue;
280 unsigned int activeChannels = 0;
281 for (; klmChannel != klmNextModule; ++klmChannel) {
282 channel = klmChannel.getKLMChannelNumber();
283 if (m_Results.m_ChannelStatus->getChannelStatus(channel) == KLMChannelStatus::c_Hot)
284 continue;
285 hits = m_Results.m_HitMapChannel.getChannelData(channel);
286 if (hits > 0)
287 activeChannels++;
288 }
289 double averageHits = double(moduleHits) / activeChannels;
290 if (averageHits < m_MinimalAverageHitNumber && !m_ForcedCalibration) {
291 if (!notEnoughData) {
292 B2INFO("KLM module " << klmModule.getKLMModuleNumber() <<
293 " (subdetector " << klmModule.getSubdetector() <<
294 ", section " << klmModule.getSection() <<
295 ", sector " << klmModule.getSector() <<
296 ", layer " << klmModule.getLayer() <<
297 "): " << moduleHits << " hits, average: " << averageHits << ".");
298 }
299 notEnoughData = true;
300 continue;
301 }
302 klmChannel = klmModule;
304 for (; klmChannel != klmNextModule; ++klmChannel)
306 }
307 if (notEnoughData)
309 saveCalibration(m_Results.m_ChannelStatus, "KLMChannelStatus");
311}
312
314 KLMSectorNumber sector, double averageHitsActiveSector)
315{
316 unsigned int hits = m_Results.m_HitMapSectorNoHot.getChannelData(sector);
317 if (hits == 0)
318 return;
319 double r = log(hits / averageHitsActiveSector) / log(10.);
320 if (fabs(r) > m_MaximalLogSectorHitsRatio) {
321 B2WARNING("Number of hits in sector " << sector << " (" << hits <<
322 ") strongly deviates from the average (" <<
323 averageHitsActiveSector <<
324 "), the 10-based logarithm of the ratio is " << r << ".");
325 }
326}
327
329{
330 unsigned int hits = m_Results.m_HitMapModule.getChannelData(module);
331 if (hits >= m_MinimalModuleHitNumber) {
332 m_Results.m_ModuleStatus->setChannelStatus(
334 } else {
335 m_Results.m_ModuleStatus->setChannelStatus(
337 }
338}
339
341 KLMChannelNumber channel, unsigned int moduleHits, int activeChannels)
342{
343 unsigned int hits = m_Results.m_HitMapChannel.getChannelData(channel);
344 if (activeChannels == 1) {
346 m_Results.m_ChannelStatus->setChannelStatus(
347 channel, KLMChannelStatus::c_Hot);
348 return true;
349 }
350 } else {
351 double r = hits / (double(moduleHits - hits) / (activeChannels - 1));
352 if (hits >= m_MinimalHitNumberHotChannel &&
354 m_Results.m_ChannelStatus->setChannelStatus(
355 channel, KLMChannelStatus::c_Hot);
356 return true;
357 }
358 }
359 return false;
360}
361
363{
364 unsigned int hits = m_Results.m_HitMapChannel.getChannelData(channel);
365 if (m_Results.m_ChannelStatus->getChannelStatus(channel) ==
367 return;
368 if (hits > 0) {
369 m_Results.m_ChannelStatus->setChannelStatus(
371 } else {
372 m_Results.m_ChannelStatus->setChannelStatus(
373 channel, KLMChannelStatus::c_Dead);
374 }
375}
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.
static 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.
static 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.
Results & operator=(const Results &results)
Assignment operator.
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.