9 #include <dqm/analysis/modules/DQMHistAnalysisTOP.h>
10 #include <boost/format.hpp>
11 #include <boost/algorithm/string.hpp>
54 "boarstacks to be excluded from alarming. Names are given like '5c', '13d' etc.",
m_excludedBoardstacks);
57 B2DEBUG(20,
"DQMHistAnalysisTOP: Constructor done.");
69 if (
m_asicWindowsBand.size() != 2) B2ERROR(
"Parameter list 'asicWindowsBand' must contain two numbers");
70 if (
m_asicWindowsAlarmLevels.size() != 2) B2ERROR(
"Parameter list 'asicWindowsAlarmLevels' must contain two numbers");
72 if (
m_junkHitsAlarmLevels.size() != 2) B2ERROR(
"Parameter list 'junkHitsAlarmLevels' must contain two numbers");
74 if (
m_backgroundAlarmLevels.size() != 2) B2ERROR(
"Parameter list 'backgroundAlarmLevels' must contain two numbers");
80 for (
int slot = 1; slot <= 16; slot++) {
81 string slotstr = to_string(slot);
82 for (std::string bs : {
"a",
"b",
"c",
"d"}) {
124 m_deadFraction =
new TH1F(
"TOP/deadFraction",
"Fraction of dead channels", 16, 0.5, 16.5);
127 m_hotFraction =
new TH1F(
"TOP/hotFraction",
"Fraction of hot channels", 16, 0.5, 16.5);
130 m_activeFraction =
new TH1F(
"TOP/activeFraction",
"Fraction of active channels", 16, 0.5, 16.5);
133 m_c_deadAndHot =
new TCanvas(
"TOP/c_deadAndHotChannels",
"c_deadAndHotChannels");
135 m_junkFraction =
new TH1F(
"TOP/junkFraction",
"Fraction of junk hits per boardstack", 64, 0.5, 16.5);
140 m_text1 =
new TPaveText(1, 435, 12, 500,
"NB");
141 m_text1->SetFillColorAlpha(kWhite, 0);
143 m_text2 =
new TPaveText(0.55, 0.8, 0.85, 0.89,
"NDC");
144 m_text2->SetFillColorAlpha(kWhite, 0);
146 m_text3 =
new TPaveText(0.47, 0.8, 0.85, 0.89,
"NDC");
147 m_text3->SetFillColorAlpha(kWhite, 0);
150 for (
int slot = 1; slot < 16; slot++) {
151 auto* line =
new TLine(slot + 0.5, 0, slot + 0.5, 1);
152 line->SetLineWidth(1);
153 line->SetLineStyle(2);
159 B2DEBUG(20,
"DQMHistAnalysisTOP: initialized.");
165 auto* h =
findHist(
"DQMInfo/rtype");
166 std::string title = h ? h->GetTitle() :
"";
171 B2DEBUG(20,
"DQMHistAnalysisTOP: beginRun called.");
177 bool zeroSupp = gStyle->GetHistMinimumZero();
178 gStyle->SetHistMinimumZero(
true);
203 for (
int slot = 1; slot <= 16; slot++) {
210 gStyle->SetHistMinimumZero(zeroSupp);
224 B2DEBUG(20,
"DQMHistAnalysisTOP : endRun called");
230 B2DEBUG(20,
"terminate called");
238 int alarmState = c_Gray;
241 auto* hraw = (TH2F*)
findHist(
"TOP/window_vs_slot");
243 auto* px = hraw->ProjectionX(
"tmp_px");
245 band->Add(px, band, 1, -1);
246 double total = px->Integral();
248 band->Divide(band, px);
257 auto* canvas =
findCanvas(
"TOP/c_window_vs_slot");
262 canvas->Pad()->SetFrameFillColor(10);
271 int alarmState = c_Gray;
274 auto* evtMonitor = (TH1F*)
findHist(
"TOP/BoolEvtMonitor");
276 double totalEvts = evtMonitor->Integral();
277 double badEvts = evtMonitor->GetBinContent(2);
279 double badRatio = badEvts / totalEvts;
281 m_text2->AddText(Form(
"Fraction: %.4f %%", badRatio * 100.0));
285 auto* canvas =
findCanvas(
"TOP/c_BoolEvtMonitor");
289 canvas->Pad()->SetFrameFillColor(10);
301 double inactiveFract = 0;
303 for (
int slot = 1; slot <= 16; slot++) {
304 auto* h = (TH1F*)
findHist(
"TOP/good_channel_hits_" + std::to_string(slot));
308 for (
int chan = 0; chan < h->GetNbinsX(); chan++) {
309 double y = h->GetBinContent(chan + 1);
315 if (n > 0) mean /= n;
316 double deadCut = mean / 10;
317 double hotCut = mean * 10;
318 double deadFract = 0;
320 double deadFractIncl = 0;
321 double hotFractIncl = 0;
322 for (
int chan = 0; chan < h->GetNbinsX(); chan++) {
323 double y = h->GetBinContent(chan + 1);
324 int bs = chan / 128 + (slot - 1) * 4;
328 if (included) deadFractIncl += 1;
329 }
else if (y > hotCut) {
331 if (included) hotFractIncl += 1;
334 deadFract /= h->GetNbinsX();
335 hotFract /= h->GetNbinsX();
339 inactiveFract = std::max(inactiveFract, (deadFractIncl + hotFractIncl) / h->GetNbinsX());
342 int alarmState = c_Gray;
360 canvas->Pad()->SetFrameFillColor(10);
362 m_stack =
new THStack(
"TOP/stack",
"Fraction of dead and hot channels");
372 m_legend =
new TLegend(0.8, 0.87, 0.99, 0.99);
389 canvas->Pad()->SetFrameFillColor(10);
394 auto* signalHits = (TProfile*)
findHist(
"TOP/signalHits");
395 if (not signalHits)
return;
397 auto* backgroundHits = (TProfile*)
findHist(
"TOP/backgroundHits");
398 if (not backgroundHits)
return;
402 auto* activeFract = (TH1F*) activeFraction->Clone(
"tmp");
403 for (
int i = 1; i <= activeFract->GetNbinsX(); i++) activeFract->SetBinError(i, 0);
408 int alarmState = c_Gray;
409 if (signalHits->GetEntries() > 0 and activeFraction->Integral() > 0) {
435 if (backgroundHits->GetEntries() > 0 and activeFraction->Integral() > 0) {
440 double average = fun->GetParameter(0);
441 double error = fun->GetParError(0);
443 m_text3->AddText(Form(
"Average: %.2f MHz/PMT", average));
470 for (
int slot = 1; slot <= 16; slot++) {
471 auto* good = (TH1F*)
findHist(
"TOP/good_channel_hits_" + std::to_string(slot));
472 if (not good)
continue;
473 auto* bad = (TH1F*)
findHist(
"TOP/bad_channel_hits_" + std::to_string(slot));
474 if (not bad)
continue;
475 for (
int i = 0; i < 512; i++) {
477 allHits->Fill(slot + bs / 4. - 0.5, good->GetBinContent(i + 1) + bad->GetBinContent(i + 1));
478 m_junkFraction->Fill(slot + bs / 4. - 0.5, bad->GetBinContent(i + 1));
484 int alarmState = c_Gray;
485 if (allHits->Integral() > 0) {
487 if (alarmState == 3) {
500 canvas->Pad()->SetFrameFillColor(10);
514 double totalHits = 0;
515 std::vector<TH2F*> histos;
516 for (
int slot = 1; slot <= 16; slot++) {
517 TH2F* h = (TH2F*)
findHist(name + std::to_string(slot));
520 totalHits += h->Integral();
522 if (histos.empty())
return;
523 double average = totalHits / 512 / histos.size();
525 for (
auto* h : histos) h->GetZaxis()->SetRangeUser(0, std::max(average * scale, 1.0));
532 if (not canvas)
return;
534 auto* h = (TH1F*)
findHist(
"TOP/" + name);
537 auto* hb = (TH1F*)
findHist(
"TOP/" + name +
"BG");
542 int i0 = h->GetXaxis()->FindBin(0.);
543 double s = h->Integral(1, i0);
545 double sb = hb->Integral(1, i0);
547 h->Add(h, hb, 1, -s / sb);
548 TString title = TString(h->GetTitle()) +
" (BG subtracted)";
560 for (
int slot = 1; slot <= 16; slot++) {
561 auto vname = variableName + std::to_string(slot);
562 double value = histogram ? histogram->GetBinContent(slot) : 0;
565 B2DEBUG(20, vname <<
" " << value);
575 if (value < alarmLevels[0])
return c_Green;
576 else if (value < alarmLevels[1])
return c_Yellow;
579 if (value < alarmLevels[0])
return c_Red;
580 else if (value < alarmLevels[1])
return c_Yellow;
587 std::vector<TLine*>& alarmLines,
bool bigRed)
589 std::vector<int> colors = {kOrange, kRed};
590 if (not bigRed) std::reverse(colors.begin(), colors.end());
591 for (
size_t i = 0; i < std::min(colors.size(), alarmLevels.size()); i++) {
592 if (i < alarmLines.size()) {
593 auto* line = alarmLines[i];
596 line->SetY1(alarmLevels[i]);
597 line->SetY2(alarmLevels[i]);
599 auto* line =
new TLine(xmin, alarmLevels[i], xmax, alarmLevels[i]);
600 line->SetLineWidth(2);
601 line->SetLineStyle(2);
602 line->SetLineColor(colors[i]);
603 alarmLines.push_back(line);
612 auto* line =
new TLine(0.5, y, 16.5, y);
613 line->SetLineWidth(2);
614 line->SetLineColor(kRed);
629 for (
int col = 1; col <= h->GetNbinsX(); col++) {
630 for (
int row = 1; row <= h->GetNbinsY(); row++) {
631 double y = h->GetBinContent(col, row);
638 if (n > 0) mean /= n;
645 int badBoardstacks = 0;
648 for (
int slot = 1; slot <= 16; slot++) {
649 std::string hname =
"TOP/good_hits_asics_" + to_string(slot);
654 double deadCut = mean / 10;
655 double hotCut = mean * 10;
656 std::vector<int> asics(64, 0);
657 std::vector<int> carriers(16, 0);
658 std::vector<int> boardstacks(4, 0);
659 for (
int asic = 0; asic < 64; asic++) {
660 int carrier = asic / 4;
661 int boardstack = carrier / 4;
662 for (
int chan = 0; chan < 8; chan++) {
663 double y = h->GetBinContent(asic + 1, chan + 1);
664 if (y > deadCut and y < hotCut) {
667 boardstacks[boardstack]++;
671 for (
int n : asics)
if (n == 0) badAsics++;
672 for (
int n : carriers)
if (n == 0) badCarriers++;
673 for (
int n : boardstacks)
if (n == 0) badBoardstacks++;
675 badAsics -= badCarriers * 4;
676 badCarriers -= badBoardstacks * 4;
679 for (
int slot = 1; slot <= 16; slot++) {
680 std::string hname =
"TOP/good_hits_xy_" + to_string(slot);
685 double deadCut = mean / 10;
686 double hotCut = mean * 10;
687 std::vector<int> pmts(32, 0);
688 for (
int row = 0; row < 8; row++) {
689 for (
int col = 0; col < 64; col++) {
690 int pmt = col / 4 + (row / 4) * 16;
691 double y = h->GetBinContent(col + 1, row + 1);
692 if (y > deadCut and y < hotCut) pmts[pmt]++;
695 for (
int n : pmts)
if (n == 0) badPMTs++;
697 badPMTs -= badBoardstacks * 8;
708 B2DEBUG(20,
"badBoardstacks: " << badBoardstacks);
709 B2DEBUG(20,
"badCarriers: " << badCarriers);
710 B2DEBUG(20,
"badAsics: " << badAsics);
711 B2DEBUG(20,
"badPMTs: " << badPMTs);
712 B2DEBUG(20,
"excludedBS: " << numBS);
740 for (
auto c : excludedBS) {
741 if (isspace(c))
continue;
742 else if (ispunct(c)) {
743 if (not name.empty()) {
747 }
else name.push_back(c);
749 if (not name.empty()) {
764 if (ss.size() > 2) {ss.pop_back(); ss.pop_back();}
765 B2DEBUG(20,
"excludedBoardstacks: [" << ss <<
"]");
774 for (
const auto& bsname : excludedBoardstacks) {
777 else B2ERROR(
"Invalid boardstack name: " << bsname);
The base class for the histogram analysis module.
TCanvas * findCanvas(TString cname)
Find canvas by name.
void updateEpicsPVs(float timeout)
Update all EPICS PV (flush to network)
int registerEpicsPV(std::string pvname, std::string keyname="", bool update_pvs=true)
EPICS related Functions.
static TH1 * findHist(const std::string &histname, bool onlyIfUpdated=false)
Get histogram from list (no other search).
std::string getEpicsStringPV(std::string keyname, bool &status)
Read value from a EPICS PV.
void setEpicsPV(std::string keyname, double value)
Write value to a EPICS PV.
static MonitoringObject * getMonitoringObject(const std::string &histname)
Get MonitoringObject with given name (new object is created if non-existing)
bool requestLimitsFromEpicsPVs(chid id, double &lowerAlarm, double &lowerWarn, double &upperWarn, double &upperAlarm)
Get Alarm Limits from EPICS PV.
void updateEventMonitorCanvas()
Updates canvas of event desynchronization monitor w/ alarming.
std::vector< int > m_asicWindowsBand
lower and upper bin of a band denoting good windows
void setZAxisRange(const std::string &name, double scale)
Sets z-axis range of 2D histograms.
TCanvas * m_c_photonYields
Canvas: photon yields per slot.
void initialize() override final
Initializer.
std::vector< double > m_deadChannelsAlarmLevels
alarm levels for the fraction of dead + hot channels
std::vector< double > m_asicWindowsAlarmLevels
alarm levels for fraction of windows outside the band
TPaveText * m_text2
text to be written to event desynchonization monitor
TCanvas * m_c_junkFraction
Canvas: fraction of junk hits per boardstack.
THStack * m_stack
stack for drawing dead, hot and active channel fractions
const TH1F * makeDeadAndHotFractionsPlot()
Makes a plot of dead and hot channel fractions per slot.
TPaveText * m_text3
text to be written to background rates
~DQMHistAnalysisTOPModule()
Destructor.
std::vector< TLine * > m_deadChannelsAlarmLines
lines representing alarm levels
TPaveText * m_text1
text to be written to window_vs_slot
std::vector< TLine * > m_photonYieldsAlarmLines
lines representing alarm levels
std::vector< bool > m_includedBoardstacks
boardstacks included in alarming
std::vector< TLine * > m_verticalLines
vertical lines splitting slots
std::string m_pvPrefix
Epics PV prefix.
TH1D * m_photonYields
photon yields per slot (corrected for active channels)
TH1D * m_backgroundRates
background rates per slot
MonitoringObject * m_monObj
MiraBelle monitoring object.
TCanvas * m_c_backgroundRates
Canvas: background rates per slot.
std::vector< double > m_eventMonitorAlarmLevels
alarm levels for fraction of desynchronized digits
void terminate() override final
This method is called at the end of the event processing.
void setAlarmLines()
Sets all alarm lines.
TH1F * m_activeFraction
fraction of active channels per slot
int getAlarmColor(unsigned alarmState) const
Converts alarm state to color.
void event() override final
This method is called for each event.
std::vector< double > m_photonYieldsAlarmLevels
alarm levels for the number of photons per track
std::vector< TLine * > m_junkHitsAlarmLines
lines representing alarm levels
void setIncludedBoardstacks(const std::vector< std::string > &excludedBoardstacks)
Sets flags for boardstacks to be included in alarming.
TH1F * m_deadFraction
fraction of dead channels per slot
TH1F * m_hotFraction
fraction of hot channels per slot
void makeBGSubtractedTimimgPlot(const std::string &name)
Makes background subtracted time distribution plot.
std::vector< std::string > m_excludedBoardstacks
list of boarstacks to be excluded from alarming
void makePhotonYieldsAndBGRatePlots(const TH1F *activeFraction)
Make plots of dead-and-hot-channel corrected photon yields and BG rates per slot.
TH1F * m_junkFraction
fraction of junk hits per boardstack
double getMean(const TH2 *h)
Returns histogram mean by excluding bins with zero content.
void endRun() override final
This method is called if the current run ends.
int getAlarmState(double value, const std::vector< double > &alarmLevels, bool bigRed=true) const
Returns alarm state.
std::vector< TLine * > m_asicWindowsBandLines
lines denoting a band of good windows
void makeJunkFractionPlot()
Makes a plot of fractions of junk hits per boardstack.
double m_totalWindowFraction
total fraction of windows outside the band
void beginRun() override final
Called when entering a new run.
TLegend * m_legend
legend for dead and hot channels
TCanvas * m_c_deadAndHot
Canvas: fractin of dead and hot channels.
std::vector< TLine * > m_backgroundAlarmLines
lines representing alarm levels
void updateWindowVsSlotCanvas()
Updates canvas of window_vs_slot w/ alarming.
std::map< std::string, int > m_bsmap
a map of boardstack names to ID's
std::vector< double > m_backgroundAlarmLevels
alarm levels for background rates [MHz/PMT]
void setEpicsVariables()
Calculates and sets epics variables.
std::vector< double > m_junkHitsAlarmLevels
alarm levels for the fraction of junk hits
TH1D * m_windowFractions
fraction of windows outside the band denoting good windows, per slot
bool m_IsNullRun
Run type flag for null runs.
void updateLimits()
Updates limits defined by module parameters using EpicsPVs.
void setMiraBelleVariables(const std::string &variableName, const TH1 *histogram)
Sets MiraBelle variables from the histogram with bins corresponding to slot numbers.
void setDescription(const std::string &description)
Sets the description of the module.
void setVariable(const std::string &var, float val, float upErr=-1., float dwErr=-1)
set value to float variable (new variable is made if not yet existing)
void addParam(const std::string &name, T ¶mVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module.
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Abstract base class for different kinds of events.