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