Belle II Software development
DQMHistAnalysisDeltaEpicsMonObjExample.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// File : DQMHistAnalysisDeltaEpicsMonObjExample.cc
10// Description : Test Module for Delta Histogram Access
11//-
12
13
14#include <dqm/analysis/modules/DQMHistAnalysisDeltaEpicsMonObjExample.h>
15#include <TROOT.h>
16
17using namespace Belle2;
18
19//-----------------------------------------------------------------
20// Register the Module
21//-----------------------------------------------------------------
22REG_MODULE(DQMHistAnalysisDeltaEpicsMonObjExample);
23
24//-----------------------------------------------------------------
25// Implementation
26//-----------------------------------------------------------------
27
30{
31 // This module CAN NOT be run in parallel!
32 setDescription("Example module for using delta histogramming and sending values to EPICS");
33
34 // Parameter definition
35 addParam("histogramDirectoryName", m_histogramDirectoryName, "Name of Histogram dir", std::string("test"));
36 addParam("histogramName", m_histogramName, "Name of Histogram", std::string("testHist"));
37 addParam("PVPrefix", m_pvPrefix, "PV Prefix", std::string("DQM:TEST:"));
38 B2DEBUG(1, "DQMHistAnalysisDeltaEpicsMonObjExample: Constructor done.");
39
40}
41
43{
44 B2DEBUG(1, "DQMHistAnalysisDeltaEpicsMonObjExample: initialized.");
45
46 gROOT->cd(); // this seems to be important before creating new Canvas, or strange things happen
47 m_canvas = new TCanvas((m_histogramDirectoryName + "/c_Test").data());
48
50 m_monObj->addCanvas(m_canvas);
51
52 // delta parameters, two examples:
54 100000, 1); // update each 100k events (from daq histogram)
55 // addDeltaPar(m_histogramDirectoryName, m_histogramName, HistDelta::c_Entries, 10000, 1); // update each 10000 entries
56
57 registerEpicsPV(m_pvPrefix + "mean", "mean");
58 registerEpicsPV(m_pvPrefix + "width", "width");
59 registerEpicsPV(m_pvPrefix + "alarm", "alarm");
60
61 m_meanLowerAlarmLine = new TLine();
62 m_meanLowerAlarmLine->SetLineColor(kRed + 3);
63 m_meanLowerAlarmLine->SetLineWidth(3);
64 m_meanLowerAlarmLine->SetVertical(true);
65 m_meanLowerWarnLine = new TLine();
66 m_meanLowerWarnLine->SetLineColor(kOrange - 3);
67 m_meanLowerWarnLine->SetLineWidth(3);
68 m_meanLowerWarnLine->SetVertical(true);
69 m_meanUpperWarnLine = new TLine();
70 m_meanUpperWarnLine->SetLineColor(kOrange - 3);
71 m_meanUpperWarnLine->SetLineWidth(3);
72 m_meanUpperWarnLine->SetVertical(true);
73 m_meanUpperAlarmLine = new TLine();
74 m_meanUpperAlarmLine->SetLineColor(kRed + 3);
75 m_meanUpperAlarmLine->SetLineWidth(3);
76 m_meanUpperAlarmLine->SetVertical(true);
77}
78
80{
81 B2DEBUG(1, "DQMHistAnalysisDeltaEpicsMonObjExample: beginRun called.");
82
83 double unused = NAN;
84 m_meanLowerAlarm = -1.0; // this is some way to set default values, which are used
85 m_meanLowerWarn = -0.9; // when none are set in epics PV directly.
86 m_meanUpperWarn = 0.9;
87 m_meanUpperAlarm = 1.0;
89
90 if (!std::isnan(m_meanLowerAlarm)) {
93 }
94 if (!std::isnan(m_meanLowerWarn)) {
97 }
98 if (!std::isnan(m_meanUpperWarn)) {
101 }
102 if (!std::isnan(m_meanUpperAlarm)) {
105 }
106
108}
109
111{
112 B2DEBUG(1, "DQMHistAnalysisDeltaEpicsMonObjExample: endRun called.");
113 // MiraBelle export code should run at end of Run
114 // but it still "remembers" the state from last event call.
115 doHistAnalysis(true);
116}
117
119{
120 B2DEBUG(1, "DQMHistAnalysisDeltaEpicsMonObjExample: event called.");
121 doHistAnalysis(false);
122}
123
125{
126 double data_mean = 0.0;
127 double data_width = 0.0;
128 EStatus status = c_StatusDefault;
129
130 m_canvas->Clear();
131 m_canvas->cd(0);
132
133 // more handy to have it as a full name, but find/get functions
134 // can work with one or two parameters
135 // std::string fullname = m_histogramDirectoryName + "/" + m_histogramName;
136
137 // In the following, enable one
138
139 // get most recent delta, but only if updated since last call, nullptr otherwise
141 // get basic histogram (run integrated up) but only if updated since last call
142 // auto hist = findHist(m_histogramDirectoryName, m_histogramName, true);// only if updated
143
144 // the following cases do not make sense, unless you want to achieve something special.
145 // get most recent delta even if not updated
146 // auto hist = getDelta(m_histogramDirectoryName, m_histogramName,false);// even if no update
147 // get basic histogram (run integrated up) even if not updated
148 // auto hist = findHist(m_histogramDirectoryName, m_histogramName, false);// even if no update
149
150 if (hist != nullptr) {
151 data_mean = hist->GetMean();
152 data_width = hist->GetRMS();
153
154 // your conditions for warn and alarm
155 // here we would have to check against NaN, too ... just too lazy to write the code in this example
156 // maybe other condition, e.g. too low to judge -> 0
157 status = makeStatus(true,
158 data_mean > m_meanUpperWarn || data_mean < m_meanLowerWarn || data_width > m_widthUpperWarn,
159 data_mean > m_meanUpperAlarm || data_mean < m_meanLowerAlarm || data_width > m_widthUpperAlarm);
160
161 hist->Draw("hist");
162
163 // line position need to be adjusted to histogram content
164 double y1 = hist->GetMaximum();
165 double y2 = hist->GetMinimum();
166 auto ym = y1 + (y1 - y2) * 0.05;
167 m_meanLowerAlarmLine->SetY1(ym);
168 m_meanLowerWarnLine->SetY1(ym);
169 m_meanUpperWarnLine->SetY1(ym);
170 m_meanUpperAlarmLine->SetY1(ym);
171 auto yn = y2 + (y1 - y2) * 0.05;
172 m_meanLowerAlarmLine->SetY2(yn);
173 m_meanLowerWarnLine->SetY2(yn);
174 m_meanUpperWarnLine->SetY2(yn);
175 m_meanUpperAlarmLine->SetY2(yn);
176
177 if (!std::isnan(m_meanLowerAlarm)) m_meanLowerAlarmLine->Draw();
178 if (!std::isnan(m_meanLowerWarn)) m_meanLowerWarnLine->Draw();
179 if (!std::isnan(m_meanUpperWarn)) m_meanUpperWarnLine->Draw();
180 if (!std::isnan(m_meanUpperAlarm)) m_meanUpperAlarmLine->Draw();
181
182 colorizeCanvas(m_canvas, status);
183 }
184
185 // Tag canvas as updated ONLY if things have changed.
186 UpdateCanvas(m_canvas->GetName(), hist != nullptr);
187 // Remark: if you do not tag, you may have an empty Canvas (as it is cleared above)
188
189 // this if left over from jsroot, may not be needed anymore (to check)
190 m_canvas->Update();
191
192 // actually, we would prefer to only update the epics variable
193 // if the main histogram or delta~ has changed.
194
195 if (hist) {
196 if (forMiraBelle) {
197 // currently, monObj are only used at end of run, thus this is not necessary
198 // but, if in the future we want to use finer granularity, this code needs change.
199 m_monObj->setVariable("mean", data_mean);
200 m_monObj->setVariable("width", data_width);
201 } else {
202 // we do not want to fill epics again at end of run, as this would be identical to the last event called before.
203 setEpicsPV("mean", data_mean);
204 setEpicsPV("width", data_width);
205 setEpicsPV("alarm", int(status));
206 // until now, changes are buffered only locally, not waiting for them being written out to performance reason
207 // framework will take care after all analysis modules are done
208 }
209 }
210}
211
213{
214 B2DEBUG(1, "DQMHistAnalysisDeltaEpicsMonObjExample: terminate called");
215}
216
void terminate(void) override final
This method is called at the end of the event processing.
void beginRun(void) override final
Called when entering a new run.
void event(void) override final
This method is called for each event.
void doHistAnalysis(bool forMiraBelle=false)
Do the actual processing.
int registerEpicsPV(const std::string &pvname, const std::string &keyname="")
EPICS related Functions.
static MonitoringObject * getMonitoringObject(const std::string &name)
Get MonitoringObject with given name (new object is created if non-existing)
TH1 * getDelta(const std::string &dirname, const std::string &histname="", bool onlyIfUpdated=true, int n=0)
Get Delta histogram.
static void addDeltaPar(const std::string &dirname, const std::string &histname, HistDelta::EDeltaType t, int p, unsigned int a=1)
Add Delta histogram parameters.
static void colorizeCanvas(TCanvas *canvas, EStatus status)
Helper function for Canvas colorization.
static void UpdateCanvas(const std::string &name, bool updated=true)
Mark canvas as updated (or not)
DQMHistAnalysisModule()
Constructor / Destructor.
EStatus
Status flag of histogram/canvas.
@ c_StatusDefault
default for non-coloring
static EStatus makeStatus(bool enough, bool warn_flag, bool error_flag)
Helper function to judge the status for coloring and EPICS.
bool requestLimitsFromEpicsPVs(chid id, double &lowerAlarm, double &lowerWarn, double &upperWarn, double &upperAlarm)
Get Alarm Limits from EPICS PV.
void setEpicsPV(const std::string &keyname, double value)
Write value to a EPICS PV.
void setDescription(const std::string &description)
Sets the description of the module.
Definition Module.cc:214
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
Abstract base class for different kinds of events.