Skip to content

Commit 81b4147

Browse files
committed
Merge branch 'feature/add_string_pv_interface_rel08' into 'release/08-00'
Feature/add string pv interface rel08 See merge request belle2/software/basf2!2506
2 parents 2cc4cfa + e2eb320 commit 81b4147

File tree

4 files changed

+170
-34
lines changed

4 files changed

+170
-34
lines changed

dqm/analysis/modules/include/DQMHistAnalysisTOP.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,12 @@ namespace Belle2 {
179179
*/
180180
void updateLimits();
181181

182+
/**
183+
* Sets flags for boardstacks to be included in alarming
184+
* @param excludedBoardstacks list of boarstacks to be excluded from alarming
185+
*/
186+
void setIncludedBoardstacks(const std::vector<std::string>& excludedBoardstacks);
187+
182188
// module parameters
183189

184190
std::vector<int> m_asicWindowsBand = {215, 235}; /**< lower and upper bin of a band denoting good windows */
@@ -195,6 +201,7 @@ namespace Belle2 {
195201

196202
std::vector<int> m_alarmColors = {kGray, kGreen, kYellow, kRed}; /**< alarm colors */
197203
std::vector<bool> m_includedBoardstacks; /**< boardstacks included in alarming */
204+
std::map<std::string, int> m_bsmap; /**< a map of boardstack names to ID's */
198205

199206
bool m_IsNullRun = false; /**< Run type flag for null runs. */
200207

dqm/analysis/modules/src/DQMHistAnalysisTOP.cc

Lines changed: 52 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -74,26 +74,21 @@ void DQMHistAnalysisTOPModule::initialize()
7474
if (m_backgroundAlarmLevels.size() != 2) B2ERROR("Parameter list 'backgroundAlarmLevels' must contain two numbers");
7575
if (m_photonYieldsAlarmLevels.size() != 2) B2ERROR("Parameter list 'photonYieldsAlarmLevels' must contain two numbers");
7676

77-
// parse excluded boardstacks
77+
// make a map of boardstack names to ID's
7878

79-
m_includedBoardstacks.resize(64, true);
80-
if (not m_excludedBoardstacks.empty()) {
81-
std::map<std::string, int> bsmap;
82-
int id = 1;
83-
for (int slot = 1; slot <= 16; slot++) {
84-
string slotstr = to_string(slot);
85-
for (std::string bs : {"a", "b", "c", "d"}) {
86-
bsmap[slotstr + bs] = id;
87-
id++;
88-
}
89-
}
90-
for (const auto& bsname : m_excludedBoardstacks) {
91-
id = bsmap[bsname];
92-
if (id > 0) m_includedBoardstacks[id - 1] = false;
93-
else B2ERROR("Invalid boardstack name: " << bsname);
79+
int id = 1;
80+
for (int slot = 1; slot <= 16; slot++) {
81+
string slotstr = to_string(slot);
82+
for (std::string bs : {"a", "b", "c", "d"}) {
83+
m_bsmap[slotstr + bs] = id;
84+
id++;
9485
}
9586
}
9687

88+
// parse excluded boardstacks
89+
90+
setIncludedBoardstacks(m_excludedBoardstacks);
91+
9792
// MiraBelle monitoring
9893

9994
m_monObj = getMonitoringObject("top");
@@ -104,6 +99,7 @@ void DQMHistAnalysisTOPModule::initialize()
10499
registerEpicsPV(m_pvPrefix + "badCarriers", "badCarriers");
105100
registerEpicsPV(m_pvPrefix + "badAsics", "badAsics");
106101
registerEpicsPV(m_pvPrefix + "badPMTs", "badPMTs");
102+
registerEpicsPV(m_pvPrefix + "numExcludedBS", "numExcludedBS");
107103

108104
// Epics used to get limits from configuration file - override module parameters (input only)
109105

@@ -114,10 +110,7 @@ void DQMHistAnalysisTOPModule::initialize()
114110
registerEpicsPV(m_pvPrefix + "deadChannelsAlarmLevels", "deadChannelsAlarmLevels");
115111
registerEpicsPV(m_pvPrefix + "backgroundAlarmLevels", "backgroundAlarmLevels");
116112
registerEpicsPV(m_pvPrefix + "photonYieldsAlarmLevels", "photonYieldsAlarmLevels");
117-
for (int slot = 1; slot <= 16; slot++) {
118-
std::string varName = "slot" + to_string(slot);
119-
registerEpicsPV(m_pvPrefix + varName, varName); // excludedBoardstacks (lolo = BS0, low = BS1, high = BS2, hihi = BS3)
120-
}
113+
registerEpicsPV(m_pvPrefix + "excludedBoardstacks", "excludedBoardstacks");
121114

122115
updateEpicsPVs(5.0);
123116

@@ -266,6 +259,7 @@ void DQMHistAnalysisTOPModule::updateWindowVsSlotCanvas()
266259
canvas->cd();
267260
m_text1->Draw();
268261
for (auto* line : m_asicWindowsBandLines) line->Draw();
262+
canvas->Pad()->SetFrameFillColor(10);
269263
canvas->Pad()->SetFillColor(getAlarmColor(alarmState));
270264
canvas->Modified();
271265
}
@@ -292,6 +286,7 @@ void DQMHistAnalysisTOPModule::updateEventMonitorCanvas()
292286
if (canvas) {
293287
canvas->cd();
294288
m_text2->Draw();
289+
canvas->Pad()->SetFrameFillColor(10);
295290
canvas->Pad()->SetFillColor(getAlarmColor(alarmState));
296291
canvas->Modified();
297292
}
@@ -705,12 +700,16 @@ void DQMHistAnalysisTOPModule::setEpicsVariables()
705700
setEpicsPV("badCarriers", badCarriers);
706701
setEpicsPV("badAsics", badAsics);
707702
setEpicsPV("badPMTs", badPMTs);
703+
int numBS = 0;
704+
for (auto included : m_includedBoardstacks) if (not included) numBS++;
705+
setEpicsPV("numExcludedBS", numBS);
708706
updateEpicsPVs(5.0);
709707

710708
B2DEBUG(20, "badBoardstacks: " << badBoardstacks);
711709
B2DEBUG(20, "badCarriers: " << badCarriers);
712710
B2DEBUG(20, "badAsics: " << badAsics);
713711
B2DEBUG(20, "badPMTs: " << badPMTs);
712+
B2DEBUG(20, "excludedBS: " << numBS);
714713
}
715714

716715
void DQMHistAnalysisTOPModule::updateLimits()
@@ -732,30 +731,49 @@ void DQMHistAnalysisTOPModule::updateLimits()
732731

733732
setAlarmLines();
734733

735-
m_excludedBoardstacks.clear();
736-
std::vector<std::string> bsLabels = {"a", "b", "c", "d"};
737-
for (int slot = 1; slot <= 16; slot++) {
738-
std::vector<double> includedBS(4);
739-
for (int bs = 0; bs < 4; bs++) includedBS[bs] = m_includedBoardstacks[(slot - 1) * 4 + bs];
740-
std::string varName = "slot" + to_string(slot);
741-
requestLimitsFromEpicsPVs(varName, includedBS[0], includedBS[1], includedBS[2], includedBS[3]);
742-
for (int bs = 0; bs < 4; bs++) {
743-
int index = (slot - 1) * 4 + bs;
744-
m_includedBoardstacks[index] = (includedBS[bs] != 0);
745-
if (not m_includedBoardstacks[index]) m_excludedBoardstacks.push_back(to_string(slot) + bsLabels[bs]);
734+
bool status = false;
735+
std::string excludedBS = getEpicsStringPV("excludedBoardstacks", status);
736+
737+
if (status) {
738+
m_excludedBoardstacks.clear();
739+
std::string name;
740+
for (auto c : excludedBS) {
741+
if (isspace(c)) continue;
742+
else if (ispunct(c)) {
743+
if (not name.empty()) {
744+
m_excludedBoardstacks.push_back(name);
745+
name.clear();
746+
}
747+
} else name.push_back(c);
746748
}
749+
if (not name.empty()) {
750+
m_excludedBoardstacks.push_back(name);
751+
}
752+
setIncludedBoardstacks(m_excludedBoardstacks);
747753
}
748754

749-
B2DEBUG(20, "asicWindowsBand: [" << m_asicWindowsBand[0] << ", " << m_asicWindowsBand[1] << "]");
750-
B2DEBUG(20, "asicWindowsAlarmLevels: [" << m_asicWindowsAlarmLevels[0] << ", " << m_asicWindowsAlarmLevels[1] << "]");
755+
B2DEBUG(20, "asicWindowsBand: [" << m_asicWindowsBand[0] << ", " << m_asicWindowsBand[1] << "]");
756+
B2DEBUG(20, "asicWindowsAlarmLevels: [" << m_asicWindowsAlarmLevels[0] << ", " << m_asicWindowsAlarmLevels[1] << "]");
751757
B2DEBUG(20, "eventMonitorAlarmLevels: [" << m_eventMonitorAlarmLevels[0] << ", " << m_eventMonitorAlarmLevels[1] << "]");
752-
B2DEBUG(20, "junkHitsAlarmLevels: [" << m_junkHitsAlarmLevels[0] << ", " << m_junkHitsAlarmLevels[1] << "]");
758+
B2DEBUG(20, "junkHitsAlarmLevels: [" << m_junkHitsAlarmLevels[0] << ", " << m_junkHitsAlarmLevels[1] << "]");
753759
B2DEBUG(20, "deadChannelsAlarmLevels: [" << m_deadChannelsAlarmLevels[0] << ", " << m_deadChannelsAlarmLevels[1] << "]");
754760
B2DEBUG(20, "backgroundAlarmLevels: [" << m_backgroundAlarmLevels[0] << ", " << m_backgroundAlarmLevels[1] << "]");
755761
B2DEBUG(20, "photonYieldsAlarmLevels: [" << m_photonYieldsAlarmLevels[0] << ", " << m_photonYieldsAlarmLevels[1] << "]");
756762
std::string ss;
757763
for (const auto& s : m_excludedBoardstacks) ss += "'" + s + "', ";
758764
if (ss.size() > 2) {ss.pop_back(); ss.pop_back();}
759765
B2DEBUG(20, "excludedBoardstacks: [" << ss << "]");
766+
760767
}
761768

769+
void DQMHistAnalysisTOPModule::setIncludedBoardstacks(const std::vector<std::string>& excludedBoardstacks)
770+
{
771+
m_includedBoardstacks.clear();
772+
m_includedBoardstacks.resize(64, true);
773+
774+
for (const auto& bsname : excludedBoardstacks) {
775+
int id = m_bsmap[bsname];
776+
if (id > 0) m_includedBoardstacks[id - 1] = false;
777+
else B2ERROR("Invalid boardstack name: " << bsname);
778+
}
779+
}

dqm/core/include/DQMHistAnalysis.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,13 @@ namespace Belle2 {
335335
*/
336336
void setEpicsPV(std::string keyname, int value);
337337

338+
/**
339+
* Write string to a EPICS PV
340+
* @param keyname key name (or full PV name) of PV
341+
* @param value string to write
342+
*/
343+
void setEpicsStringPV(std::string keyname, std::string value);
344+
338345
/**
339346
* Write value to a EPICS PV
340347
* @param index index of PV
@@ -349,6 +356,13 @@ namespace Belle2 {
349356
*/
350357
void setEpicsPV(int index, int value);
351358

359+
/**
360+
* Write string to a EPICS PV
361+
* @param index index of PV
362+
* @param value string to write
363+
*/
364+
void setEpicsStringPV(int index, std::string value);
365+
352366
/**
353367
* Read value from a EPICS PV
354368
* @param keyname key name (or full PV name) of PV
@@ -363,6 +377,22 @@ namespace Belle2 {
363377
*/
364378
double getEpicsPV(int index);
365379

380+
/**
381+
* Read value from a EPICS PV
382+
* @param keyname key name (or full PV name) of PV
383+
* @param status return status (true on success)
384+
* @return string value (empty string if non existing)
385+
*/
386+
std::string getEpicsStringPV(std::string keyname, bool& status);
387+
388+
/**
389+
* Read value from a EPICS PV
390+
* @param index index of PV
391+
* @param status return status (true on success)
392+
* @return string value (empty string if non existing)
393+
*/
394+
std::string getEpicsStringPV(int index, bool& status);
395+
366396
/**
367397
* Update all EPICS PV (flush to network)
368398
* @param timeout maximum time until timeout in s

dqm/core/src/DQMHistAnalysis.cc

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,24 @@ void DQMHistAnalysisModule::setEpicsPV(std::string keyname, int value)
344344
#endif
345345
}
346346

347+
void DQMHistAnalysisModule::setEpicsStringPV(std::string keyname, std::string value)
348+
{
349+
if (!m_useEpics || m_epicsReadOnly) return;
350+
#ifdef _BELLE2_EPICS
351+
if (m_epicsNameToChID[keyname] == nullptr) {
352+
B2ERROR("Epics PV " << keyname << " not registered!");
353+
return;
354+
}
355+
if (value.length() > 40) {
356+
B2ERROR("Epics string PV " << keyname << " too long (>40 characters)!");
357+
return;
358+
}
359+
char text[40];
360+
strcpy(text, value.c_str());
361+
SEVCHK(ca_put(DBR_STRING, m_epicsNameToChID[keyname], text), "ca_set failure");
362+
#endif
363+
}
364+
347365
void DQMHistAnalysisModule::setEpicsPV(int index, double value)
348366
{
349367
if (!m_useEpics || m_epicsReadOnly) return;
@@ -368,6 +386,20 @@ void DQMHistAnalysisModule::setEpicsPV(int index, int value)
368386
#endif
369387
}
370388

389+
void DQMHistAnalysisModule::setEpicsStringPV(int index, std::string value)
390+
{
391+
if (!m_useEpics || m_epicsReadOnly) return;
392+
#ifdef _BELLE2_EPICS
393+
if (index < 0 || index >= (int)m_epicsChID.size()) {
394+
B2ERROR("Epics PV with " << index << " not registered!");
395+
return;
396+
}
397+
char text[40];
398+
strcpy(text, value.c_str());
399+
SEVCHK(ca_put(DBR_STRING, m_epicsChID[index], text), "ca_set failure");
400+
#endif
401+
}
402+
371403
double DQMHistAnalysisModule::getEpicsPV(std::string keyname)
372404
{
373405
double value{NAN};
@@ -414,6 +446,55 @@ double DQMHistAnalysisModule::getEpicsPV(int index)
414446
return NAN;
415447
}
416448

449+
std::string DQMHistAnalysisModule::getEpicsStringPV(std::string keyname, bool& status)
450+
{
451+
status = false;
452+
char value[40] = "";
453+
if (!m_useEpics) return std::string(value);
454+
#ifdef _BELLE2_EPICS
455+
if (m_epicsNameToChID[keyname] == nullptr) {
456+
B2ERROR("Epics PV " << keyname << " not registered!");
457+
return std::string(value);
458+
}
459+
// From EPICS doc. When ca_get or ca_array_get are invoked the returned channel value cant be assumed to be stable
460+
// in the application supplied buffer until after ECA_NORMAL is returned from ca_pend_io. If a connection is lost
461+
// outstanding get requests are not automatically reissued following reconnect.
462+
auto r = ca_get(DBR_STRING, m_epicsNameToChID[keyname], value);
463+
if (r == ECA_NORMAL) r = ca_pend_io(5.0); // this is needed!
464+
if (r == ECA_NORMAL) {
465+
status = true;
466+
return std::string(value);
467+
} else {
468+
SEVCHK(r, "ca_get or ca_pend_io failure");
469+
}
470+
#endif
471+
return std::string(value);
472+
}
473+
474+
std::string DQMHistAnalysisModule::getEpicsStringPV(int index, bool& status)
475+
{
476+
status = false;
477+
char value[40] = "";
478+
if (!m_useEpics) return std::string(value);
479+
#ifdef _BELLE2_EPICS
480+
if (index < 0 || index >= (int)m_epicsChID.size()) {
481+
B2ERROR("Epics PV with " << index << " not registered!");
482+
return std::string(value);
483+
}
484+
// From EPICS doc. When ca_get or ca_array_get are invoked the returned channel value cant be assumed to be stable
485+
// in the application supplied buffer until after ECA_NORMAL is returned from ca_pend_io. If a connection is lost
486+
// outstanding get requests are not automatically reissued following reconnect.
487+
auto r = ca_get(DBR_DOUBLE, m_epicsChID[index], value);
488+
if (r == ECA_NORMAL) r = ca_pend_io(5.0); // this is needed!
489+
if (r == ECA_NORMAL) {
490+
status = true;
491+
return std::string(value);
492+
} else {
493+
SEVCHK(r, "ca_get or ca_pend_io failure");
494+
}
495+
#endif
496+
return std::string(value);
497+
}
417498

418499
chid DQMHistAnalysisModule::getEpicsPVChID(std::string keyname)
419500
{

0 commit comments

Comments
 (0)