Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Slow controls unit transformations #151

Merged
merged 12 commits into from
Apr 10, 2024
Merged
1 change: 1 addition & 0 deletions data-core/TableInfo/ConfigCore/FESlowControlsTableInfo.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<COLUMN Type="Data" Name="Units" StorageName="UNITS" DataType="VARCHAR2" DataChoices=""/>
<COLUMN Type="Data" Name="UniversalInterfaceAddress" StorageName="UNIVERSAL_INTERFACE_ADDRESS" DataType="VARCHAR2" DataChoices=""/>
<COLUMN Type="Data" Name="UniversalDataBitOffset" StorageName="UNIVERSAL_DATA_BIT_OFFSET" DataType="NUMBER" DataChoices=""/>
<COLUMN Type="Data" Name="Transformation" StorageName="TRANSFORMATION" DataType="STRING" DefaultValue="x" DataChoices=""/>
<COLUMN Type="YesNo" Name="ReadAccess" StorageName="READ_ACCESS" DataType="VARCHAR2" DataChoices=""/>
<COLUMN Type="YesNo" Name="WriteAccess" StorageName="WRITE_ACCESS" DataType="VARCHAR2" DataChoices=""/>
<COLUMN Type="TrueFalse" Name="RecordChangesOnly" StorageName="RECORD_CHANGES_ONLY" DataType="VARCHAR2" DataChoices=""/>
Expand Down
1 change: 1 addition & 0 deletions otsdaq/FECore/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ cet_make_library(LIBRARY_NAME FECore
otsdaq::NetworkUtilities
otsdaq::ConfigurationInterface
otsdaq::SOAPUtilities
ROOT::Hist
)


Expand Down
5 changes: 5 additions & 0 deletions otsdaq/FECore/FESlowControlsChannel.cc
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ FESlowControlsChannel::FESlowControlsChannel(FEVInterface* interface,
const std::string& channelName,
const std::string& dataType,
const std::string& universalAddress,
const std::string& transformation,
unsigned int universalDataBitOffset,
bool readAccess,
bool writeAccess,
Expand Down Expand Up @@ -67,6 +68,7 @@ FESlowControlsChannel::FESlowControlsChannel(FEVInterface* interface,
, saveBinaryFormat_(saveBinaryFormat)
, alarmsEnabled_(alarmsEnabled)
, latchAlarms_(latchAlarms)
, transformation_(transformation)
, lastSampleTime_(0)
, loloAlarmed_(false)
, loAlarmed_(false)
Expand All @@ -78,6 +80,7 @@ FESlowControlsChannel::FESlowControlsChannel(FEVInterface* interface,
__GEN_COUTV__(dataType_);
__GEN_COUTV__(interface->getUniversalAddressSize());
__GEN_COUTV__(universalAddress);
__GEN_COUTV__(transformation);

if(interface->getUniversalAddressSize() == 0 ||
interface->getUniversalDataSize() == 0)
Expand Down Expand Up @@ -293,6 +296,8 @@ void FESlowControlsChannel::print(std::ostream& out) const
<< "sizeOfReadBytes_: " << sizeOfReadBytes_ << __E__;
out << "\t"
<< "universalAddress_: " << BinaryStringMacros::binaryNumberToHexString(universalAddress_, "0x", " ") << __E__;
out << "\t"
<< "transformation_: " << transformation_ << __E__;
out << "\t"
<< "readAccess_: " << readAccess_ << __E__;
out << "\t"
Expand Down
2 changes: 2 additions & 0 deletions otsdaq/FECore/FESlowControlsChannel.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class FESlowControlsChannel
const std::string& channelName,
const std::string& dataType,
const std::string& universalAddress,
const std::string& transformation,
unsigned int universalDataBitOffset,
bool readAccess,
bool writeAccess,
Expand Down Expand Up @@ -78,6 +79,7 @@ class FESlowControlsChannel
const bool alarmsEnabled_, latchAlarms_;
std::string universalReadValue_;
std::string universalAddress_; // get size from parent FE interface
std::string transformation_;

private:
std::string sample_, lastSample_;
Expand Down
46 changes: 41 additions & 5 deletions otsdaq/FECore/FEVInterface.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#include "otsdaq/NetworkUtilities/UDPDataStreamerBase.h"
#include "otsdaq/Macros/BinaryStringMacros.h"

#include <TFormula.h>

#define TRACE_NAME "FEVInterface"
#include <iostream>
#include <sstream>
Expand Down Expand Up @@ -133,12 +135,21 @@ void FEVInterface::addSlowControlsChannels(ConfigurationTree
getInterfaceUID() << "/" << groupLinkChild.first
<< "\t Type:" << groupLinkChild.second.getNode("ChannelDataType") << __E__;

// Unit transforms
std::string transformation = "";
try {
transformation = groupLinkChild.second.getNode("Transformation").getValue<std::string>();
} catch (...) {
__FE_COUT__ << "Slow controls 'Transformation' setting not found." << __E__;
}

mapOfSlowControlsChannels->insert(std::pair<std::string, FESlowControlsChannel>(
groupLinkChild.first,
FESlowControlsChannel(this,
groupLinkChild.first,
groupLinkChild.second.getNode("ChannelDataType").getValue<std::string>(),
groupLinkChild.second.getNode("UniversalInterfaceAddress").getValue<std::string>(),
groupLinkChild.second.getNode("Transformation").getValue<std::string>(),
groupLinkChild.second.getNode("UniversalDataBitOffset").getValue<unsigned int>(),
groupLinkChild.second.getNode("ReadAccess").getValue<bool>(),
groupLinkChild.second.getNode("WriteAccess").getValue<bool>(),
Expand Down Expand Up @@ -351,19 +362,44 @@ try


// Use artdaq Metric Manager if available,
if(channel->monitoringEnabled_ && metricMan && metricMan->Running() && universalAddressSize_ <= 8)
if(channel->monitoringEnabled_ && metricMan && metricMan->Running() && universalAddressSize_ <= 8)
{
uint64_t val = 0; // 64 bits!
for(size_t ii = 0; ii < universalAddressSize_; ++ii)
val += (uint8_t)readVal[ii] << (ii * 8);

__FE_COUT__ << "Sending sample to Metric Manager..." << __E__;
metricMan->sendMetric(channel->fullChannelName_, val, "", 3, artdaq::MetricMode::LastPoint);
}
else
// Unit transforms
if((channel->transformation_).size() > 1) // Execute transformation if a formula is present
{
__FE_COUT__ << "Transformation formula = " <<channel->transformation_ << __E__;

TFormula transformationFormula("transformationFormula", (channel->transformation_).c_str());
double transformedVal = transformationFormula.Eval(val);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably a good idea to check for NaN here, instead of just reporting the value

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added an isnan check for transformedVal, which throws a COUT_ERR if it fails.


if(!std::isnan(transformedVal))
{
__FE_COUT__ << "Transformed " << val << " into " << transformedVal << __E__;
__FE_COUT__ << "Sending transformed sample to Metric Manager..." << __E__;
metricMan->sendMetric(channel->fullChannelName_, transformedVal, "", 3, artdaq::MetricMode::LastPoint);
}
else
{
__FE_SS__ << "Transformed value is NaN!" << __E__;
__FE_SS_THROW__;
}
}
else
{
__FE_COUT__ << "Sending sample to Metric Manager..." << __E__;
metricMan->sendMetric(channel->fullChannelName_, val, "", 3, artdaq::MetricMode::LastPoint);
}
}
else
{
__FE_COUT__ << "Skipping sample to Metric Manager: "
<< " channel->monitoringEnabled_=" << channel->monitoringEnabled_ << " metricMan=" << metricMan
<< " metricMan->Running()=" << (metricMan && metricMan->Running()) << __E__;
}

// make sure buffer hasn't exploded somehow
if(txBuffer.size() > txBufferSz)
Expand Down