Belle II Software  release-06-02-00
DQMHistAnalysisIP.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 : DQMHistAnalysisIP.cc
10 // Description : Mean for IP position with delta histogramming
11 //-
12 
13 
14 #include <dqm/analysis/modules/DQMHistAnalysisIP.h>
15 #include <TROOT.h>
16 #include <TClass.h>
17 
18 using namespace std;
19 using namespace Belle2;
20 
21 //-----------------------------------------------------------------
22 // Register the Module
23 //-----------------------------------------------------------------
24 REG_MODULE(DQMHistAnalysisIP)
25 
26 //-----------------------------------------------------------------
27 // Implementation
28 //-----------------------------------------------------------------
29 
32 {
33  // This module CAN NOT be run in parallel!
34 
35  //Parameter definition
36  addParam("HistoName", m_histoname, "Name of Histogram (incl dir)", std::string(""));
37  addParam("PVName", m_pvPrefix, "PV Prefix", std::string("DQM:TEST:hist:"));
38  addParam("MonitorPrefix", m_monPrefix, "Monitor Prefix");// force to be set!
39  addParam("useEpics", m_useEpics, "Whether to update EPICS PVs.", false);
40  addParam("minEntries", m_minEntries, "minimum number of new Entries for a fit", 1000);
41  B2DEBUG(20, "DQMHistAnalysisIP: Constructor done.");
42 }
43 
44 
45 DQMHistAnalysisIPModule::~DQMHistAnalysisIPModule()
46 {
47 #ifdef _BELLE2_EPICS
48  if (m_useEpics) {
49  if (ca_current_context()) ca_context_destroy();
50  }
51 #endif
52 }
53 
54 void DQMHistAnalysisIPModule::initialize()
55 {
56  B2DEBUG(20, "DQMHistAnalysisIP: initialized.");
57 
58  m_monObj = getMonitoringObject("ip");
59 
60  TString a;
61  a = m_histoname;
62  m_c1 = new TCanvas(a + "_fit"); // prefer to change canvas name to monitorPrefix, but then chnages on the web gui are needed :-(
63 
64  m_line = new TLine(0, 10, 0, 0);
65  m_line->SetVertical(true);
66  m_line->SetLineColor(8);
67  m_line->SetLineWidth(3);
68  m_line2 = new TLine(0, 10, 0, 0);
69  m_line2->SetVertical(true);
70  m_line2->SetLineColor(9);
71  m_line2->SetLineWidth(3);
72 
73  m_monObj->addCanvas(m_c1);
74 
75  // need the function to get parameter names
76 #ifdef _BELLE2_EPICS
77  if (m_useEpics) {
78  if (!ca_current_context()) SEVCHK(ca_context_create(ca_disable_preemptive_callback), "ca_context_create");
79  std::string aa;
80  aa = m_pvPrefix + "Mean";
81  SEVCHK(ca_create_channel(aa.c_str(), NULL, NULL, 10, &mychid[0]), "ca_create_channel failure");
82  aa = m_pvPrefix + "RMS";
83  SEVCHK(ca_create_channel(aa.c_str(), NULL, NULL, 10, &mychid[1]), "ca_create_channel failure");
84  aa = m_pvPrefix + "Median";
85  SEVCHK(ca_create_channel(aa.c_str(), NULL, NULL, 10, &mychid[2]), "ca_create_channel failure");
86  // Read LO and HI limits from EPICS, seems this needs additional channels?
87  // SEVCHK(ca_get(DBR_DOUBLE,mychid[i],(void*)&data),"ca_get failure"); // data is only valid after ca_pend_io!!
88  SEVCHK(ca_pend_io(5.0), "ca_pend_io failure");
89  }
90 #endif
91 }
92 
93 
94 void DQMHistAnalysisIPModule::beginRun()
95 {
96  //m_serv->SetTimer(100, kFALSE);
97  B2DEBUG(20, "DQMHistAnalysisIP: beginRun called.");
98  m_c1->Clear();
99 
100  TH1* hh1;
101  hh1 = findHist(m_histoname.c_str());
102 
103  if (hh1 == NULL) {
104  B2DEBUG(20, "Histo " << m_histoname << " not in memfile");
105  TDirectory* d = gROOT;
106  TString myl = m_histoname;
107  TString tok;
108  Ssiz_t from = 0;
109  while (myl.Tokenize(tok, from, "/")) {
110  TString dummy;
111  Ssiz_t f;
112  f = from;
113  if (myl.Tokenize(dummy, f, "/")) { // check if its the last one
114  auto e = d->GetDirectory(tok);
115  if (e) {
116  B2DEBUG(20, "Cd Dir " << tok);
117  d = e;
118  }
119  d->cd();
120  } else {
121  break;
122  }
123  }
124  TObject* obj = d->FindObject(tok);
125  if (obj != NULL) {
126  if (obj->IsA()->InheritsFrom("TH1")) {
127  B2DEBUG(20, "Histo " << m_histoname << " found in mem");
128  hh1 = (TH1*)obj;
129  }
130  } else {
131  B2DEBUG(20, "Histo " << m_histoname << " NOT found in mem");
132  }
133  }
134 
135  if (hh1 != NULL) {
136  m_c1->cd();
137  hh1->Draw();
138  m_line->Draw();
139  m_line2->Draw();
140  } else {
141  B2DEBUG(20, "Histo " << m_histoname << " not found");
142  }
143 
144  if (m_h_last) m_h_last->Reset();
145 }
146 
147 void DQMHistAnalysisIPModule::event()
148 {
149  TH1* hh1;
150  bool flag = false;
151 
152  hh1 = findHist(m_histoname.c_str());
153  if (hh1 == NULL) {
154  B2DEBUG(20, "Histo " << m_histoname << " not in memfile");
155  TDirectory* d = gROOT;
156  TString myl = m_histoname;
157  TString tok;
158  Ssiz_t from = 0;
159  while (myl.Tokenize(tok, from, "/")) {
160  TString dummy;
161  Ssiz_t f;
162  f = from;
163  if (myl.Tokenize(dummy, f, "/")) { // check if its the last one
164  auto e = d->GetDirectory(tok);
165  if (e) {
166  B2DEBUG(20, "Cd Dir " << tok);
167  d = e;
168  }
169  d->cd();
170  } else {
171  break;
172  }
173  }
174  TObject* obj = d->FindObject(tok);
175  if (obj != NULL) {
176  if (obj->IsA()->InheritsFrom("TH1")) {
177  B2DEBUG(20, "Histo " << m_histoname << " found in mem");
178  hh1 = (TH1*)obj;
179  flag = true;
180  }
181  } else {
182  B2DEBUG(20, "Histo " << m_histoname << " NOT found in mem");
183  }
184  }
185  if (hh1 != NULL) {
186 
187  if (!m_h_last) {
188  B2DEBUG(20, "Initial Clone");
189  gROOT->cd();
190  m_h_last = (TH1*)hh1->Clone();
191  m_h_last->SetName(TString(hh1->GetName()) + "_last");
192  m_h_last->Reset();
193  }
194 
195  double last = m_h_last->GetEntries();
196  double current = hh1->GetEntries();
197  B2DEBUG(20, "Entries: " << last << "," << current);
198  if (current - last >= m_minEntries) {
199  B2DEBUG(20, "Update Delta & Fit");
200  gROOT->cd();
201  TH1* delta = (TH1*)hh1->Clone();
202  delta->Add(m_h_last, -1.);
203 
204  m_c1->Clear();
205  m_c1->cd();// necessary!
206  delta->Draw("hist");
207  m_h_last->Reset();
208  m_h_last->Add(hh1);
209 
210  delta->ResetStats(); // kills the Mean from filling, now only use bin values excl over/underflow
211  double x = delta->GetMean();// must be double bc of EPICS below
212  double w = delta->GetRMS();// must be double bc of EPICS below
213  double q = 0.5; // array size one for quantiles
214  double m = 0; // array of size 1 for result = median
215  delta->ComputeIntegral(); // precaution
216  delta->GetQuantiles(1, &m, &q);
217  double y1 = delta->GetMaximum();
218  double y2 = delta->GetMinimum();
219  B2DEBUG(20, "Fit " << x << "," << w << "," << y1 << "," << y2);
220  m_line->SetY1(y1 + (y1 - y2) * 0.05);
221  m_line->SetX1(x);
222  m_line->SetX2(x);
223  m_line2->SetY1(y1 + (y1 - y2) * 0.05);
224  m_line2->SetX1(m);
225  m_line2->SetX2(m);
226  delta->GetXaxis()->SetRangeUser(x - 3 * w, x + 3 * w);
227  if (!flag) {
228  // dont add another line...
229  m_line->Draw();
230  m_line2->Draw();
231  }
232  m_c1->Modified();
233  m_c1->Update();
234 
235  m_monObj->setVariable(m_monPrefix + "_median", m);
236  m_monObj->setVariable(m_monPrefix + "_mean", x);
237  m_monObj->setVariable(m_monPrefix + "_width", w);
238 
239 #ifdef _BELLE2_EPICS
240  if (m_useEpics) {
241  B2INFO("Update EPICS");
242  if (mychid[0]) SEVCHK(ca_put(DBR_DOUBLE, mychid[0], (void*)&x), "ca_set failure");
243  if (mychid[1]) SEVCHK(ca_put(DBR_DOUBLE, mychid[1], (void*)&w), "ca_set failure");
244  if (mychid[2]) SEVCHK(ca_put(DBR_DOUBLE, mychid[2], (void*)&m), "ca_set failure");
245  SEVCHK(ca_pend_io(5.0), "ca_pend_io failure");
246  }
247 #endif
248  }
249  } else {
250  B2DEBUG(20, "Histo " << m_histoname << " not found");
251  }
252 
253 }
254 
255 void DQMHistAnalysisIPModule::terminate()
256 {
257 #ifdef _BELLE2_EPICS
258  if (m_useEpics) {
259  for (auto i = 0; i < m_parameters; i++) {
260  if (mychid[i]) SEVCHK(ca_clear_channel(mychid[i]), "ca_clear_channel failure");
261  }
262  SEVCHK(ca_pend_io(5.0), "ca_pend_io failure");
263  }
264 #endif
265  B2DEBUG(20, "DQMHistAnalysisIP: terminate called");
266 }
267 
Class definition for the output module of Sequential ROOT I/O.
The base class for the histogram analysis module.
#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.