Belle II Software development
DQMHistAnalysisARICH.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 <dqm/analysis/modules/DQMHistAnalysisARICH.h>
11
12#include <TH1F.h>
13#include <TH2F.h>
14#include <TCanvas.h>
15#include <TLine.h>
16#include <TClass.h>
17#include <TROOT.h>
18
19#include <fstream>
20#include <vector>
21#include <algorithm>
22
23using namespace std;
24using namespace Belle2;
25
26//-----------------------------------------------------------------
27// Register module
28//-----------------------------------------------------------------
29
30REG_MODULE(DQMHistAnalysisARICH);
31
34{
35 // set module description (e.g. insert text)
36 setDescription("Modify and analyze the data quality histograms of ARICH");
38 addParam("debug", m_debug, "debug mode", false);
39 addParam("alert", m_enableAlert, "Enable color alert", true);
40 addParam("hotLimit", m_hotLimit, "Occupancy limit for hot channels", 0.005);
41 addParam("badApdOccLimit", m_badApdOccLimit, "Occupancy limit for bad APDs (in fraction of average occupancy)", 0.3);
42
43}
44
46{
47}
48
50{
51 gROOT->cd();
52
53 //definition of new TObjects for modification and analysis
54 for (int i = 0; i < 5; i++) {
55 m_LineForMB[i] = new TLine();
56 m_LineForMB[i]->SetLineStyle(3);
57 m_LineForMB[i]->SetLineWidth(1);
58 m_LineForMB[i]->SetLineColor(kBlack);
59 }
60
61 m_apdHist = new ARICHChannelHist("tmpChHist", "tmpChHist", 2);
62 m_apdPoly = new TH2Poly();
63 m_apdPoly->SetName("ARICH/apdHitMap");
64 m_apdPoly->SetTitle("# of hits/APD/event");
65 m_apdPoly->SetOption("colz");
66 m_c_apdHist = new TCanvas("ARICH/c_apdHist");
67
68 addDeltaPar("ARICH", "bitsPerChannel", HistDelta::c_Events,
69 1000000, 1); // update each 1M events (from daq histogram)
70
71 addDeltaPar("ARICH", "theta", HistDelta::c_Events,
72 100000, 1); // update each 100k events (from daq histogram)
73
74 // addDeltaPar(m_histogramDirectoryName, m_histogramName, HistDelta::c_Entries, 10000, 1); // update each 10000 entries
75
76 registerEpicsPV("ARI:badAPDs", "badAPDs");
77 registerEpicsPV("ARI:deadHAPDs", "deadHAPDs");
78 registerEpicsPV("ARI:hotChannels", "hotChannels");
79
80 registerEpicsPV("ARI:hotLimit", "hotLimit");
81 registerEpicsPV("ARI:badApdOccLimit", "badApdOccLimit");
82 registerEpicsPV("ARI:sigBitFracLimit", "sigBitFracLimit");
83
84 B2DEBUG(20, "DQMHistAnalysisARICH: initialized.");
85}
86
88{
89
90 // read the alarm limits
91 double unused = NAN;
94 requestLimitsFromEpicsPVs("sigBitFracLimit", m_sigBitFracLowAlarm, m_sigBitFracLowWarn, unused, unused);
95
96 double hot = getEpicsPV("hotLimit");
97 if (hot != NAN) m_hotLimit = hot;
98
99 double bad = getEpicsPV("badApdOccLimit");
100 if (bad != NAN) m_badApdOccLimit = bad;
101
102}
103
105{
106
107 //Show alert by empty bins = red and strange entries = yellow
108 //Draw lines on mergerHits histogram for shifters to divide sectors
109 TH1* m_h_mergerHit = findHist("ARICH/mergerHit");
110 m_c_mergerHit = findCanvas("ARICH/c_mergerHit");
111 if (m_h_mergerHit != NULL && m_c_mergerHit != NULL) {
112 m_c_mergerHit->Clear();
113 m_c_mergerHit->cd();
114 m_h_mergerHit->SetMinimum(0);
115 m_h_mergerHit->Draw("hist");
116 gPad->Update();
117
118 int alertMerger = 0;
119 double mean = m_h_mergerHit->Integral() / 72;
120 for (int i = 0; i < 72; i++) {
121 int hit = m_h_mergerHit->GetBinContent(i + 1);
122 if ((bool)hit ^ (bool)m_h_mergerHit->GetEntries()) {
123 //only if the empty bin is not a masked merger, show alert.
124 auto itr = std::find(maskedMergers.begin(), maskedMergers.end(), i + 1);
125 if (itr == maskedMergers.end()) {
126 alertMerger = 2;
127 break;
128 }
129 }
130 if (hit > mean * 100 && alertMerger < 1) alertMerger = 1;
131 }
132 if (m_enableAlert && m_minStats < m_h_mergerHit->GetEntries()) m_c_mergerHit->SetFillColor(alertColor[alertMerger]);
133
134 //Draw lines divide the sectors
135 for (int i = 0; i < 5; i++) {
136 m_LineForMB[i]->DrawLine(12 * (i + 1) + 0.5, 0, 12 * (i + 1) + 0.5, gPad->GetUymax());
137 }
138
139 m_c_mergerHit->Modified();
140 } else {
141 B2INFO("Histogram/canvas named mergerHit is not found.");
142 }
143
144
145 //Show alert by the ratio of center 2 bins to side 2bins. <1.5 = red, <2 = yellow
146 TH1* m_h_bits = findHist("ARICH/bits");
147 m_c_bits = findCanvas("ARICH/c_bits");
148 if (m_h_bits != NULL && m_c_bits != NULL) {
149 m_c_bits->Clear();
150 m_c_bits->cd();
151 m_h_bits->SetMinimum(0);
152 m_h_bits->Draw("hist");
153 gPad->Update();
154
155 double side = m_h_bits->GetBinContent(2) + m_h_bits->GetBinContent(5);
156 double center = m_h_bits->GetBinContent(3) + m_h_bits->GetBinContent(4);
157 EStatus status = c_StatusGood;
158 if (center / side < m_sigBitFracLowWarn) status = c_StatusWarning;
159 if (center / side < m_sigBitFracLowAlarm) status = c_StatusError;
160 if (m_enableAlert && m_minStats < m_h_bits->GetEntries()) colorizeCanvas(m_c_bits, status);
161
162 m_c_bits->Modified();
163 } else {
164 B2INFO("Histogram/canvas named bits is not found.");
165 }
166
167 //Show alert by no entry = red and 0 peak = yellow
168 TH1* m_h_hitsPerEvent = findHist("ARICH/hitsPerEvent");
169 m_c_hitsPerEvent = findCanvas("ARICH/c_hitsPerEvent");
170 int nEvents = 0;
171 if (m_h_hitsPerEvent != NULL && m_c_hitsPerEvent != NULL) {
172 m_c_hitsPerEvent->Clear();
173 m_c_hitsPerEvent->cd();
174 m_h_hitsPerEvent->SetMinimum(0);
175 m_h_hitsPerEvent->Draw("hist");
176 gPad->Update();
177 nEvents = m_h_hitsPerEvent->GetEntries();
178 int alertHitsPerEvent = 0;
179 double mean = m_h_hitsPerEvent->GetMean();
180 if (mean < 1) alertHitsPerEvent = 1;
181 double entry = m_h_hitsPerEvent->GetEntries();
182 if (entry == 0) alertHitsPerEvent = 2;
183 if (m_enableAlert) m_c_hitsPerEvent->SetFillColor(alertColor[alertHitsPerEvent]);
184
185 m_c_hitsPerEvent->Modified();
186 } else {
187 B2INFO("Histogram/canvas named hitsPerEvent is not found.");
188 }
189
190 //Draw 2D hit map of channels and APDs
191 TH1* m_h_chHit = findHist("ARICH/chipHit");
192 if (m_h_chHit != NULL) {
193 int nevt = 0;
194 TH1* htmp = findHist("ARICH/hitsPerEvent");
195 if (htmp) nevt = htmp->GetEntries();
196 m_apdHist->fillFromTH1(m_h_chHit);
197 if (nevt) m_apdHist->Scale(1. / float(nevt));
198 m_apdPoly->SetMaximum(0.1);
200 m_apdPoly->SetMinimum(0.0001);
201 m_c_apdHist->Clear();
202 m_c_apdHist->cd();
203 m_apdPoly->Draw("colz");
204 m_apdPoly->GetXaxis()->SetTickLength(0);
205 m_apdPoly->GetYaxis()->SetTickLength(0);
206 gPad->SetLogz();
207 m_c_apdHist->Update();
208 } else {
209 B2INFO("Histogram named chipHit is not found.");
210 }
211
212 TH1F* chDigit = (TH1F*)findHist("ARICH/chDigit");
213 int nhot = 0;
214 double avgOcc = 0;
215 if (chDigit != NULL && nEvents != 0) {
216 avgOcc = chDigit->GetEntries() / 60480.;
217 if (avgOcc > 100.) {
218 for (int i = 0; i < chDigit->GetNbinsX(); i++) {
219 int nhit = chDigit->GetBinContent(i + 1);
220 if ((nhit - 3. * sqrt(nhit)) / float(nEvents) > m_hotLimit) nhot++;
221 }
222 }
223 }
224 setEpicsPV("hotChannels", nhot);
225
226 int ndeadHapd = 0;
227 TH1F* hapdDigit = (TH1F*)findHist("ARICH/hapdDigit");
228 if (hapdDigit != NULL && avgOcc * 144. > 100.) {
229 for (int i = 0; i < hapdDigit->GetNbinsX(); i++) {
230 if (hapdDigit->GetBinContent(i + 1) == 0) ndeadHapd++;
231 }
232 }
233 setEpicsPV("deadHAPDs", ndeadHapd);
234
235 auto h_theta = getDelta("ARICH", "theta", 0, false); // change this to false
236 auto c_theta = findCanvas("ARICH/c_theta");
237 auto h_thetaInt = (TH1F*)findHist("ARICH/theta");
238 if (h_theta != NULL && c_theta != NULL && h_thetaInt != NULL) {
239 int binmax = h_theta->GetMaximumBin();
240 double x = h_theta->GetXaxis()->GetBinCenter(binmax);
241 EStatus status = c_StatusGood;
242 if (x < 0.3 || x > 0.35) status = c_StatusError;
243 c_theta->Clear();
244 c_theta->cd();
245 h_theta->Scale(h_thetaInt->GetEntries() / double(h_theta->GetEntries()));
246 h_thetaInt->Draw();
247 h_theta->Draw("same");
248 if (m_enableAlert && h_theta->GetEntries() > 10000) colorizeCanvas(c_theta, status);
249 c_theta->Modified();
250 }
251
252
253 if (avgOcc * 36. < 100.) {
254 setEpicsPV("badAPDs", 0);
255 return;
256 }
257
258 auto h_bitsPerChannel = getDelta("ARICH", "bitsPerChannel", 0, true);
259 if (h_bitsPerChannel == NULL) return;
260 TH1F* apdHits = new TH1F("apdHits", "nSigHits/nevt for all apds", 1680, -0.5, 1679.5);
261 double avg = 0.;
262 for (int i = 1; i < 60481; i++) {
263 int nnoise = h_bitsPerChannel->GetBinContent(1, i) + h_bitsPerChannel->GetBinContent(4, i);
264 int nsig = h_bitsPerChannel->GetBinContent(2, i) + h_bitsPerChannel->GetBinContent(3, i) - nnoise;
265 double sig2noise = float(nsig) / float(nsig + nnoise);
266 if (sig2noise > 0.2) avg += nsig;
267 if (i % 36 == 0 && i > 1) {
268 apdHits->SetBinContent(i / 36 + 1, avg);
269 avg = 0;
270 }
271 }
272
273 // for convenience I make this independent of the DB payloads... (it will never change)
274 double ringApdAvg[7] = {0.};
275
276 const int hapdInRing[7] = {42, 48, 54, 60, 66, 72, 78};
277
278 // average in hapd ring
279 for (int i = 1; i < 1681; i++) {
280 int hapd = (i - 1) / 4 + 1;
281 ringApdAvg[getRing(hapd)] += apdHits->GetBinContent(i);
282 }
283
284 for (int i = 0; i < 7; i++) {
285 ringApdAvg[i] /= float(4.*hapdInRing[i]);
286 }
287 int nbadApd = 0;
288 for (int i = 0; i < 1680; i++) {
289 int ring = getRing(i / 4 + 1);
290 int nhits = apdHits->GetBinContent(i + 1);
291 if (nhits + 3. * sqrt(nhits) < ringApdAvg[ring] * m_badApdOccLimit) nbadApd++;
292 }
293 setEpicsPV("badAPDs", nbadApd);
294
295 delete apdHits;
296
297}
298
299
301{
302 if (modID <= 42) return 0;
303 if (modID <= 90) return 1;
304 if (modID <= 144) return 2;
305 if (modID <= 204) return 3;
306 if (modID <= 270) return 4;
307 if (modID <= 342) return 5;
308 if (modID <= 420) return 6;
309 return -1; // -1 if invalid input
310}
311
313{
314 B2DEBUG(20, "DQMHistAnalysisARICH : endRun called");
315}
316
318{
319
320 B2DEBUG(20, "terminate called");
321}
ARICH histogram with HAPD plane 3 options for bin segmentation are available type 0 - one bin per HAP...
void fillFromTH1(TH1 *hist)
Fill the channelHist from the histogram Type 0 channelHist has to be filled with 420*144bin TH1 (each...
void setPoly(TH2Poly *poly)
Fill pure TH2Poly from ARICHChannelHist, makes bins and fills content.
double m_hotLimit
Occupancy limit for hot channels.
double m_badApdOccLimit
Occupancy threshold for bad APDs, in units of average APD occupancy.
void initialize() override final
Initialize the Module.
TCanvas * m_c_apdHist
Canvas for 2D hit map of APDs.
TH2Poly * m_apdPoly
hit map for each APD
TLine * m_LineForMB[5]
Lines to divide the sectors on mergerHit histogram.
TCanvas * m_c_mergerHit
Canvas for modified mergerHit histogram.
int getRing(int modID)
Returns ring number of HAPD with given moduleID.
bool m_enableAlert
Enable alert by base color of canvases.
Belle2::ARICHChannelHist * m_apdHist
ARICH TObject to draw hit map for each APD.
void terminate() override final
Termination action.
void event() override final
Event processor.
double m_sigBitFracLowAlarm
Alarm limit for overall signal/background fraction.
void endRun() override final
End-of-run action.
TCanvas * m_c_bits
Canvas for modified bits histogram.
std::vector< int > maskedMergers
The id numbers of masked merger boards to avoid unnecessary alert.
void beginRun() override final
begin-of-run action.
TCanvas * m_c_hitsPerEvent
Canvas for modified hitsPerTrack histogram.
double m_sigBitFracLowWarn
Warning limit for overall signal/background fraction.
int alertColor[3]
Alert color of canvases.
The base class for the histogram analysis module.
TCanvas * findCanvas(TString cname)
Find canvas by name.
void addDeltaPar(const std::string &dirname, const std::string &histname, HistDelta::EDeltaType t, int p, unsigned int a=1)
Add Delta histogram parameters.
void colorizeCanvas(TCanvas *canvas, EStatus status)
Helper function for Canvas colorization.
static TH1 * findHist(const std::string &histname, bool onlyIfUpdated=false)
Get histogram from list (no other search).
double getEpicsPV(std::string keyname)
Read value from a EPICS PV.
TH1 * getDelta(const std::string &fullname, int n=0, bool onlyIfUpdated=true)
Get Delta histogram.
void setEpicsPV(std::string keyname, double value)
Write value to a EPICS PV.
EStatus
Status flag of histogram/canvas.
@ c_StatusError
Analysis result: Severe issue found.
@ c_StatusWarning
Analysis result: Warning, there may be minor issues.
@ c_StatusGood
Analysis result: Good.
int registerEpicsPV(std::string pvname, std::string keyname="")
EPICS related Functions.
bool requestLimitsFromEpicsPVs(chid id, double &lowerAlarm, double &lowerWarn, double &upperWarn, double &upperAlarm)
Get Alarm Limits from EPICS PV.
void setDescription(const std::string &description)
Sets the description of the module.
Definition: Module.cc:214
void setPropertyFlags(unsigned int propertyFlags)
Sets the flags for the module properties.
Definition: Module.cc:208
@ c_ParallelProcessingCertified
This module can be run in parallel processing mode safely (All I/O must be done through the data stor...
Definition: Module.h:80
TH1F * hapd[6]
histogram of hits for each hapd
void addParam(const std::string &name, T &paramVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module.
Definition: Module.h:559
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:649
double sqrt(double a)
sqrt for double
Definition: beamHelpers.h:28
Abstract base class for different kinds of events.
STL namespace.