Belle II Software  release-08-01-10
DQMHistOutputToEPICS.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 : DQMHistOutputToEPICS.cc
10 // Description : Write Histogram Content to EPICS Arrays
11 //-
12 
13 
14 #include <dqm/analysis/modules/DQMHistOutputToEPICS.h>
15 #include <framework/core/ModuleParam.templateDetails.h>
16 
17 using namespace std;
18 using namespace Belle2;
19 
20 //-----------------------------------------------------------------
21 // Register the Module
22 //-----------------------------------------------------------------
23 REG_MODULE(DQMHistOutputToEPICS);
24 
25 //-----------------------------------------------------------------
26 // Implementation
27 //-----------------------------------------------------------------
28 
29 DQMHistOutputToEPICSModule::DQMHistOutputToEPICSModule()
31 {
32  // This module CAN NOT be run in parallel!
33 
34  //Parameter definition
35  addParam("HistoList", m_histlist, "histname, pvname");
36  B2DEBUG(99, "DQMHistOutputToEPICS: Constructor done.");
37 }
38 
40 {
41 #ifdef _BELLE2_EPICS
42  if (ca_current_context()) ca_context_destroy();
43 #endif
44 }
45 
47 {
48 #ifdef _BELLE2_EPICS
49  if (!ca_current_context()) SEVCHK(ca_context_create(ca_disable_preemptive_callback), "ca_context_create");
50 #endif
51  for (auto& it : m_histlist) {
52  if (it.size() < 2) {
53  B2WARNING("Histolist with wrong nr of parameters " << it.size());
54  continue;
55  }
56 #ifdef _BELLE2_EPICS
57  auto n = new MYNODE;
58  n->histoname = it.at(0);
59  SEVCHK(ca_create_channel(it.at(1).c_str(), NULL, NULL, 10, &n->mychid), "ca_create_channel failure");
60  if (it.size() >= 3) {
61  SEVCHK(ca_create_channel(it.at(2).c_str(), NULL, NULL, 10, &n->mychid_last), "ca_create_channel failure");
62  } else {
63  n->mychid_last = 0;
64  }
65  pmynode.push_back(n);
66 #endif
67  }
68 
69 #ifdef _BELLE2_EPICS
70  SEVCHK(ca_pend_io(5.0), "ca_pend_io failure");
71 #endif
72  B2DEBUG(99, "DQMHistOutputToEPICS: initialized.");
73 }
74 
76 {
77 #ifdef _BELLE2_EPICS
78  for (auto* it : pmynode) {
79  if (!it->mychid) continue;
80  int length = int(ca_element_count(it->mychid));
81  if (length > 0) {
82  it->data.resize(length, 0.0);
83  SEVCHK(ca_array_put(DBR_DOUBLE, length, it->mychid, (void*)(it->data.data())), "ca_put failure");
84  if (it->mychid_last) {
85  if (length == int(ca_element_count(it->mychid_last))) {
86  SEVCHK(ca_array_put(DBR_DOUBLE, length, it->mychid_last, (void*)(it->data.data())), "ca_put failure");
87  }
88  }
89  }
90  }
91 #endif
92 }
93 
95 {
96  B2DEBUG(99, "DQMHistOutputToEPICS: beginRun called.");
97  cleanPVs();
98  m_dirty = true;
99 }
100 
102 {
103 #ifdef _BELLE2_EPICS
104  for (auto& it : pmynode) {
105  if (!it->mychid) continue;
106  int length = it->data.size();
107  TH1* hh1 = findHist(it->histoname);
108  if (hh1 && hh1->GetNcells() > 2 && length > 0 && length == int(ca_element_count(it->mychid))) {
109  // If bin count doesnt match, we loose bins but otherwise ca_array_put will complain
110  // We fill up the array with ZEROs otherwise
111  if (hh1->GetDimension() == 1) {
112  int i = 0;
113  int nx = hh1->GetNbinsX() + 1;
114  for (int x = 1; x < nx && i < length ; x++) {
115  it->data[i++] = hh1->GetBinContent(x);
116  }
117 
118  } else if (hh1->GetDimension() == 2) {
119  int i = 0;
120  int nx = hh1->GetNbinsX() + 1;
121  int ny = hh1->GetNbinsY() + 1;
122  for (int y = 1; y < ny && i < length; y++) {
123  for (int x = 1; x < nx && i < length ; x++) {
124  it->data[i++] = hh1->GetBinContent(x, y);
125  }
126  }
127  }
128 
129  SEVCHK(ca_array_put(DBR_DOUBLE, length, it->mychid, (void*)it->data.data()), "ca_set failure");
130  }
131  }
132  SEVCHK(ca_pend_io(5.0), "ca_pend_io failure");
133 #endif
134 }
135 
137 {
138  if (!m_dirty) return;
139 #ifdef _BELLE2_EPICS
140  for (auto* it : pmynode) {
141  if (it->mychid && it->mychid_last) {
142  // copy PVs to last-run-PV if existing
143  int length = it->data.size();
144  if (length > 0 && length == int(ca_element_count(it->mychid_last))) {
145  SEVCHK(ca_array_put(DBR_DOUBLE, length, it->mychid_last, (void*)it->data.data()), "ca_put failure");
146  }
147  }
148  }
149  SEVCHK(ca_pend_io(5.0), "ca_pend_io failure");
150 #endif
151 
152  m_dirty = false;
153 }
154 
156 {
157  B2DEBUG(99, "DQMHistOutputToEPICS: endRun called");
158  copyToLast();
159 }
160 
162 {
163  B2DEBUG(99, "DQMHistOutputToEPICS: terminate called");
164  copyToLast();
165  // the following belongs to terminate
166 #ifdef _BELLE2_EPICS
167  for (auto* it : pmynode) {
168  if (it->mychid) SEVCHK(ca_clear_channel(it->mychid), "ca_clear_channel failure");
169  if (it->mychid_last) SEVCHK(ca_clear_channel(it->mychid_last), "ca_clear_channel failure");
170  }
171  SEVCHK(ca_pend_io(5.0), "ca_pend_io failure");
172 #endif
173 }
174 
The base class for the histogram analysis module.
static TH1 * findHist(const std::string &histname, bool onlyIfUpdated=false)
Get histogram from list (no other search).
void terminate(void) override final
This method is called at the end of the event processing.
void initialize(void) override final
Initializer.
void endRun(void) override final
This method is called for each event.
void cleanPVs(void)
set PVs to zero content (at run start)
std::vector< std::vector< std::string > > m_histlist
Parameter list for histograms.
void copyToLast(void)
copy over to "last" PV
bool m_dirty
Flag to mark that a new runs as started and data not copied to last PV.
void beginRun(void) override final
Called when entering a new run.
void event(void) override final
This method is called if the current run ends.
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.