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