Belle II Software development
TOPChannelMaskAlgorithm.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#include <top/calibration/TOPChannelMaskAlgorithm.h>
10#include <framework/logging/Logger.h>
11#include "TROOT.h"
12#include <TH1F.h>
13#include <TH2F.h>
14#include <string>
15#include <vector>
16#include <algorithm>
17#include <cmath>
18
19using namespace std;
20
21namespace Belle2 {
26 namespace TOP {
27
29 CalibrationAlgorithm("TOPChannelMaskCollector")
30 {
31 setDescription("Calibration algorithm for masking of dead and hot channels");
32 }
33
35 {
36 gROOT->SetBatch();
37
38 // check if the statistics is sufficient
39
40 auto nhits = getObjectPtr<TH1F>("nhits");
41 if (not nhits) return c_NotEnoughData;
42 double averageChannelHits = nhits->GetEntries() * nhits->GetMean() / 16 / 512;
43 B2INFO("Average number of good hits per channel: " << averageChannelHits);
44 if (averageChannelHits < m_minHits) return c_NotEnoughData;
45
46 // construct file name and open output root file
47
48 const auto& expRun = getRunList();
49 string expNo = to_string(expRun[0].first);
50 while (expNo.length() < 4) expNo.insert(0, "0");
51 string runNo = to_string(expRun[0].second);
52 while (runNo.length() < 5) runNo.insert(0, "0");
53 string outputFileName = "channelMask-e" + expNo + "-r" + runNo + ".root";
54 m_file = TFile::Open(outputFileName.c_str(), "recreate");
55
56 nhits->Write();
57
58 // create payload
59
61
62 // dead and hot channels
63
64 auto meanHits = new TH1F("meanHits", "Average number of hits per channel; slot number; average", 16, 0.5, 16.5);
65 auto rmsHits = new TH1F("rmsHits", "r.m.s of number of hits per channel; slot number; r.m.s", 16, 0.5, 16.5);
66 for (int slot = 1; slot <= 16; slot++) {
67 string name = "hits_" + to_string(slot);
68 auto h = getObjectPtr<TH1F>(name);
69 if (not h) continue;
70 h->Write();
71
72 double mean = 0;
73 double rms = h->GetMaximum();
74 for (int iter = 0; iter < 5; iter++) {
75 double sumy = 0;
76 double sumyy = 0;
77 int n = 0;
78 for (int chan = 0; chan < h->GetNbinsX(); chan++) {
79 double y = h->GetBinContent(chan + 1);
80 if (y == 0 or fabs(y - mean) > 3 * rms) continue;
81 sumy += y;
82 sumyy += y * y;
83 n++;
84 }
85 if (n == 0) break;
86 mean = sumy / n;
87 rms = sqrt(sumyy / n - mean * mean);
88 }
89 meanHits->SetBinContent(slot, mean);
90 rmsHits->SetBinContent(slot, rms);
91 double deadCut = mean / 5;
92 double hotCut = std::max(mean * 2, mean + 6 * rms);
93
94 for (int chan = 0; chan < h->GetNbinsX(); chan++) {
95 double y = h->GetBinContent(chan + 1);
96 if (y <= deadCut) {
97 m_channelMask->setDead(slot, chan);
98 } else if (y > hotCut) {
99 m_channelMask->setNoisy(slot, chan);
100 }
101 }
102 }
103
104 // ASICs with window corruption
105
106 for (int slot = 1; slot <= 16; slot++) {
107 string name = "window_vs_asic_" + to_string(slot);
108 auto h = getObjectPtr<TH2F>(name);
109 if (not h) continue;
110 h->Write();
111 auto h0 = h->ProjectionX();
112 auto h1 = h->ProjectionX("_tmp", m_minWindow, m_maxWindow);
113 for (int asic = 0; asic < h->GetNbinsX(); asic++) {
114 double r = 1 - h1->GetBinContent(asic + 1) / h0->GetBinContent(asic + 1);
115 if (r > 0.20) {
116 for (int chan = 0; chan < 8; chan++) m_channelMask->setNoisy(slot, chan + asic * 8);
117 }
118 }
119 delete h0;
120 delete h1;
121 }
122
123 // write the results and close the file
124
125 auto dead = new TH1F("numDead", "Number of dead channels; slot number; dead channels", 16, 0.5, 16.5);
126 auto hot = new TH1F("numHot", "Number of noisy channels; slot number; noisy channels", 16, 0.5, 16.5);
127 auto active = new TH1F("activeFract", "Fraction of active channels; slot number; active fraction", 16, 0.5, 16.5);
128 for (int slot = 1; slot <= 16; slot++) {
129 dead->SetBinContent(slot, m_channelMask->getNumOfDeadChannels(slot));
130 hot->SetBinContent(slot, m_channelMask->getNumOfNoisyChannels(slot));
131 active->SetBinContent(slot, m_channelMask->getActiveFraction(slot));
132 }
133 m_file->Write();
134 m_file->Close();
135
136 // import payload to DB
137
139
140 return c_OK;
141 }
142
143
144 } // end namespace TOP
146} // end namespace Belle2
147
Base class for calibration algorithms.
void saveCalibration(TClonesArray *data, const std::string &name)
Store DBArray payload with given name with default IOV.
void setDescription(const std::string &description)
Set algorithm description (in constructor)
const std::vector< Calibration::ExpRun > & getRunList() const
Get the list of runs for which calibration is called.
EResult
The result of calibration.
@ c_OK
Finished successfully =0 in Python.
@ c_NotEnoughData
Needs more data =2 in Python.
Channel status for all 512 channels of 16 modules.
int getNumOfDeadChannels() const
Returns number of dead channels.
int getNumOfNoisyChannels() const
Returns number of noisy channels.
double getActiveFraction() const
Returns fraction of active channels.
double m_minHits
minimal number of hits per channel needed for calibration
virtual EResult calibrate() final
algorithm implementation
int m_maxWindow
band upper limit in window_vs_asic
TOPCalChannelMask * m_channelMask
masks of dead and hot channels
int m_minWindow
band lower limit in window_vs_asic
double sqrt(double a)
sqrt for double
Definition: beamHelpers.h:28
void setNoisy(int moduleID, unsigned channel)
Sets a specific channel as noisy.
void setDead(int moduleID, unsigned channel)
Sets a specific channel as dead.
Abstract base class for different kinds of events.
STL namespace.