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"}) {
125 m_deadFraction =
new TH1F(
"TOP/deadFraction",
"Fraction of dead channels", 16, 0.5, 16.5);
128 m_hotFraction =
new TH1F(
"TOP/hotFraction",
"Fraction of hot channels", 16, 0.5, 16.5);
131 m_activeFraction =
new TH1F(
"TOP/activeFraction",
"Fraction of active channels", 16, 0.5, 16.5);
134 m_c_deadAndHot =
new TCanvas(
"TOP/c_deadAndHotChannels",
"c_deadAndHotChannels");
136 m_junkFraction =
new TH1F(
"TOP/junkFraction",
"Fraction of junk hits per boardstack", 64, 0.5, 16.5);
141 m_text1 =
new TPaveText(1, 435, 12, 500,
"NB");
142 m_text1->SetFillColorAlpha(kWhite, 0);
144 m_text2 =
new TPaveText(0.55, 0.8, 0.85, 0.89,
"NDC");
145 m_text2->SetFillColorAlpha(kWhite, 0);
147 m_text3 =
new TPaveText(0.47, 0.8, 0.85, 0.89,
"NDC");
148 m_text3->SetFillColorAlpha(kWhite, 0);
151 for (
int slot = 1; slot < 16; slot++) {
152 auto* line =
new TLine(slot + 0.5, 0, slot + 0.5, 1);
153 line->SetLineWidth(1);
154 line->SetLineStyle(2);
160 B2DEBUG(20,
"DQMHistAnalysisTOP: initialized.");
166 auto* h =
findHist(
"DQMInfo/rtype");
167 std::string title = h ? h->GetTitle() :
"";
170 B2DEBUG(20,
"DQMHistAnalysisTOP: beginRun called.");
176 bool zeroSupp = gStyle->GetHistMinimumZero();
177 gStyle->SetHistMinimumZero(
true);
207 auto* trackHits = (TH2F*)
findHist(
"TOP/trackHits");
209 for (
int slot = 1; slot <= 16; slot++) {
216 gStyle->SetHistMinimumZero(zeroSupp);
230 B2DEBUG(20,
"DQMHistAnalysisTOP : endRun called");
236 B2DEBUG(20,
"terminate called");
244 int alarmState = c_Gray;
247 auto* hraw = (TH2F*)
findHist(
"TOP/window_vs_slot");
249 auto* px = hraw->ProjectionX(
"tmp_px");
251 band->Add(px, band, 1, -1);
252 double total = px->Integral();
254 band->Divide(band, px);
265 auto* canvas =
findCanvas(
"TOP/c_window_vs_slot");
270 canvas->Pad()->SetFrameFillColor(10);
279 int alarmState = c_Gray;
282 auto* evtMonitor = (TH1F*)
findHist(
"TOP/BoolEvtMonitor");
284 double totalEvts = evtMonitor->Integral();
285 double badEvts = evtMonitor->GetBinContent(2);
287 double badRatio = badEvts / totalEvts;
289 m_text2->AddText(Form(
"Fraction: %.4f %%", badRatio * 100.0));
295 auto* canvas =
findCanvas(
"TOP/c_BoolEvtMonitor");
299 canvas->Pad()->SetFrameFillColor(10);
311 double inactiveFract = 0;
313 for (
int slot = 1; slot <= 16; slot++) {
314 auto* h = (TH1F*)
findHist(
"TOP/good_channel_hits_" + std::to_string(slot));
318 for (
int chan = 0; chan < h->GetNbinsX(); chan++) {
319 double y = h->GetBinContent(chan + 1);
325 if (n > 0) mean /= n;
326 double deadCut = mean / 10;
327 double hotCut = mean * 10;
328 double deadFract = 0;
330 double deadFractIncl = 0;
331 double hotFractIncl = 0;
332 for (
int chan = 0; chan < h->GetNbinsX(); chan++) {
333 double y = h->GetBinContent(chan + 1);
334 int bs = chan / 128 + (slot - 1) * 4;
338 if (included) deadFractIncl += 1;
339 }
else if (y > hotCut) {
341 if (included) hotFractIncl += 1;
344 deadFract /= h->GetNbinsX();
345 hotFract /= h->GetNbinsX();
349 inactiveFract = std::max(inactiveFract, (deadFractIncl + hotFractIncl) / h->GetNbinsX());
352 int alarmState = c_Gray;
372 canvas->Pad()->SetFrameFillColor(10);
374 m_stack =
new THStack(
"TOP/stack",
"Fraction of dead and hot channels");
384 m_legend =
new TLegend(0.8, 0.87, 0.99, 0.99);
401 canvas->Pad()->SetFrameFillColor(10);
406 auto* signalHits = (TProfile*)
findHist(
"TOP/signalHits");
407 if (not signalHits)
return;
409 auto* backgroundHits = (TProfile*)
findHist(
"TOP/backgroundHits");
410 if (not backgroundHits)
return;
414 auto* activeFract = (TH1F*) activeFraction->Clone(
"tmp");
415 for (
int i = 1; i <= activeFract->GetNbinsX(); i++) activeFract->SetBinError(i, 0);
420 int alarmState = c_Gray;
421 if (signalHits->GetEntries() > 0 and activeFraction->Integral() > 0) {
424 if (signalHits->GetBinEntries(i) < 10)
continue;
449 if (backgroundHits->GetEntries() > 100 and activeFraction->Integral() > 0) {
454 double average = fun->GetParameter(0);
455 double error = fun->GetParError(0);
457 m_text3->AddText(Form(
"Average: %.2f MHz/PMT", average));
485 for (
int slot = 1; slot <= 16; slot++) {
486 auto* good = (TH1F*)
findHist(
"TOP/good_channel_hits_" + std::to_string(slot));
487 if (not good)
continue;
488 auto* bad = (TH1F*)
findHist(
"TOP/bad_channel_hits_" + std::to_string(slot));
489 if (not bad)
continue;
490 for (
int i = 0; i < 512; i++) {
492 allHits->Fill(slot + bs / 4. - 0.5, good->GetBinContent(i + 1) + bad->GetBinContent(i + 1));
493 m_junkFraction->Fill(slot + bs / 4. - 0.5, bad->GetBinContent(i + 1));
499 int alarmState = c_Gray;
500 if (allHits->Integral() > 0) {
502 if (alarmState == c_Red) {
516 canvas->Pad()->SetFrameFillColor(10);
530 double totalHits = 0;
531 std::vector<TH2F*> histos;
532 for (
int slot = 1; slot <= 16; slot++) {
533 TH2F* h = (TH2F*)
findHist(name + std::to_string(slot));
536 totalHits += h->Integral();
538 if (histos.empty())
return;
539 double average = totalHits / 512 / histos.size();
541 for (
auto* h : histos) h->GetZaxis()->SetRangeUser(0, std::max(average * scale, 1.0));
548 if (not canvas)
return;
550 auto* h = (TH1F*)
findHist(
"TOP/" + name);
553 auto* hb = (TH1F*)
findHist(
"TOP/" + name +
"BG");
558 double s = (slot == 0) ? trackHits->Integral(1, 16, 2, 2) : trackHits->GetBinContent(slot, 2);
560 double sb = (slot == 0) ? trackHits->Integral(1, 16, 1, 1) : trackHits->GetBinContent(slot, 1);
562 h->Add(h, hb, 1, -s / sb);
565 int i0 = h->GetXaxis()->FindBin(0.);
566 double s = h->Integral(1, i0);
568 double sb = hb->Integral(1, i0);
570 if (s / sb > 1)
return;
571 h->Add(h, hb, 1, -s / sb);
574 TString title = TString(h->GetTitle()) +
" (BG subtracted)";
586 for (
int slot = 1; slot <= 16; slot++) {
587 auto vname = variableName + std::to_string(slot);
588 double value = histogram ? histogram->GetBinContent(slot) : 0;
591 B2DEBUG(20, vname <<
" " << value);
601 if (value < alarmLevels[0])
return c_Green;
602 else if (value < alarmLevels[1])
return c_Yellow;
605 if (value < alarmLevels[0])
return c_Red;
606 else if (value < alarmLevels[1])
return c_Yellow;
613 std::vector<TLine*>& alarmLines,
bool bigRed)
615 std::vector<int> colors = {kOrange, kRed};
616 if (not bigRed) std::reverse(colors.begin(), colors.end());
617 for (
size_t i = 0; i < std::min(colors.size(), alarmLevels.size()); i++) {
618 if (i < alarmLines.size()) {
619 auto* line = alarmLines[i];
622 line->SetY1(alarmLevels[i]);
623 line->SetY2(alarmLevels[i]);
625 auto* line =
new TLine(xmin, alarmLevels[i], xmax, alarmLevels[i]);
626 line->SetLineWidth(2);
627 line->SetLineStyle(2);
628 line->SetLineColor(colors[i]);
629 alarmLines.push_back(line);
638 auto* line =
new TLine(0.5, y, 16.5, y);
639 line->SetLineWidth(2);
640 line->SetLineColor(kRed);
655 for (
int col = 1; col <= h->GetNbinsX(); col++) {
656 for (
int row = 1; row <= h->GetNbinsY(); row++) {
657 double y = h->GetBinContent(col, row);
664 if (n > 0) mean /= n;
671 int badBoardstacks = 0;
674 for (
int slot = 1; slot <= 16; slot++) {
675 std::string hname =
"TOP/good_hits_asics_" + to_string(slot);
680 double deadCut = mean / 10;
681 double hotCut = mean * 10;
682 std::vector<int> asics(64, 0);
683 std::vector<int> carriers(16, 0);
684 std::vector<int> boardstacks(4, 0);
685 for (
int asic = 0; asic < 64; asic++) {
686 int carrier = asic / 4;
687 int boardstack = carrier / 4;
688 for (
int chan = 0; chan < 8; chan++) {
689 double y = h->GetBinContent(asic + 1, chan + 1);
690 if (y > deadCut and y < hotCut) {
693 boardstacks[boardstack]++;
697 for (
int n : asics)
if (n == 0) badAsics++;
698 for (
int n : carriers)
if (n == 0) badCarriers++;
699 for (
int n : boardstacks)
if (n == 0) badBoardstacks++;
701 badAsics -= badCarriers * 4;
702 badCarriers -= badBoardstacks * 4;
705 for (
int slot = 1; slot <= 16; slot++) {
706 std::string hname =
"TOP/good_hits_xy_" + to_string(slot);
711 double deadCut = mean / 10;
712 double hotCut = mean * 10;
713 std::vector<int> pmts(32, 0);
714 for (
int row = 0; row < 8; row++) {
715 for (
int col = 0; col < 64; col++) {
716 int pmt = col / 4 + (row / 4) * 16;
717 double y = h->GetBinContent(col + 1, row + 1);
718 if (y > deadCut and y < hotCut) pmts[pmt]++;
721 for (
int n : pmts)
if (n == 0) badPMTs++;
723 badPMTs -= badBoardstacks * 8;
735 B2DEBUG(20,
"badBoardstacks: " << badBoardstacks);
736 B2DEBUG(20,
"badCarriers: " << badCarriers);
737 B2DEBUG(20,
"badAsics: " << badAsics);
738 B2DEBUG(20,
"badPMTs: " << badPMTs);
739 B2DEBUG(20,
"excludedBS: " << numBS);
768 for (
auto c : excludedBS) {
769 if (isspace(c))
continue;
770 else if (ispunct(c)) {
771 if (not name.empty()) {
775 }
else name.push_back(c);
777 if (not name.empty()) {
792 if (ss.size() > 2) {ss.pop_back(); ss.pop_back();}
793 B2DEBUG(20,
"excludedBoardstacks: [" << ss <<
"]");
802 for (
const auto& bsname : excludedBoardstacks) {
805 else B2ERROR(
"Invalid boardstack name: " << bsname);
The base class for the histogram analysis module.
TCanvas * findCanvas(TString cname)
Find canvas by name.
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.
int updateEpicsPVs(float timeout)
Update all EPICS PV (flush to network)
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
int m_alarmStateOverall
overall alarm state of histograms to be sent by EpicsPV
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
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.
void makeBGSubtractedTimimgPlot(const std::string &name, const TH2F *trackHits, int slot)
Makes background subtracted time distribution plot.
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.
int getOffcialAlarmStatus(unsigned alarmState) const
Converts alarm state to official status (see EStatus of the base class)
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.