Made PPM meter range-aware. Improved PPM-code. Made RtAps sensitivity-aware. Improved code to get ranges for each channel from Daq object
This commit is contained in:
parent
4233e66d27
commit
b29f004f23
@ -75,14 +75,16 @@ const DataTypeDescriptor &Daq::dtypeDescr() const {
|
|||||||
return dtype_map.at(dataType());
|
return dtype_map.at(dataType());
|
||||||
}
|
}
|
||||||
|
|
||||||
double Daq::inputRangeForChannel(us ch) const {
|
dvec Daq::inputRangeForEnabledChannels(const bool include_monitor) const {
|
||||||
if (!(ch < ninchannels)) {
|
dvec res;
|
||||||
throw rte("Invalid channel number");
|
auto chs = enabledInChannels(include_monitor);
|
||||||
|
for(auto& ch : chs) {
|
||||||
|
res.push_back(availableInputRanges.at(ch.rangeIndex));
|
||||||
}
|
}
|
||||||
return availableInputRanges.at(inchannel_config[ch].rangeIndex);
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
us Daq::neninchannels(bool include_monitorchannel) const {
|
us Daq::neninchannels(const bool include_monitorchannel) const {
|
||||||
boolvec eninchannels = this->eninchannels(include_monitorchannel);
|
boolvec eninchannels = this->eninchannels(include_monitorchannel);
|
||||||
return std::count(eninchannels.cbegin(), eninchannels.cend(), true);
|
return std::count(eninchannels.cbegin(), eninchannels.cend(), true);
|
||||||
}
|
}
|
||||||
|
@ -136,7 +136,7 @@ public:
|
|||||||
*
|
*
|
||||||
* @return Boolean vector
|
* @return Boolean vector
|
||||||
*/
|
*/
|
||||||
boolvec eninchannels(bool include_monitor = true) const;
|
boolvec eninchannels(const bool include_monitor = true) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Create an array of booleans for each enabled output channel.
|
* @brief Create an array of booleans for each enabled output channel.
|
||||||
@ -153,15 +153,15 @@ public:
|
|||||||
double samplerate() const;
|
double samplerate() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the input range for each channel. Means the minimum from
|
* @brief Returns the input range for each channel. Maximum allowed absolute
|
||||||
* the absolute value of the minumum and maximum value that is allowed to
|
* value of the signal that can pass unclipped.
|
||||||
* pass unclipped.
|
|
||||||
*
|
|
||||||
* @param ch The channel index from the input channels.
|
|
||||||
*
|
*
|
||||||
|
* @param include_monitor If set to true and a monitor channel is available,
|
||||||
|
* the first index in the array will correspond to the monitor channel.
|
||||||
|
* *
|
||||||
* @return Maximum offset from 0 before clipping.
|
* @return Maximum offset from 0 before clipping.
|
||||||
*/
|
*/
|
||||||
double inputRangeForChannel(us ch) const;
|
dvec inputRangeForEnabledChannels(const bool include_monitor=true) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns datatype (enum) corresponding to the datatype of the
|
* @brief Returns datatype (enum) corresponding to the datatype of the
|
||||||
|
@ -86,9 +86,9 @@ int DaqConfiguration::getLowestEnabledOutChannel() const {
|
|||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
vector<DaqChannel> DaqConfiguration::enabledInChannels() const {
|
vector<DaqChannel> DaqConfiguration::enabledInChannels(const bool include_monitor) const {
|
||||||
vector<DaqChannel> res;
|
vector<DaqChannel> res;
|
||||||
if(monitorOutput) {
|
if(monitorOutput && include_monitor) {
|
||||||
DaqChannel ch;
|
DaqChannel ch;
|
||||||
ch.name = "Internal output monitor (loopback)";
|
ch.name = "Internal output monitor (loopback)";
|
||||||
ch.enabled = true;
|
ch.enabled = true;
|
||||||
|
@ -209,9 +209,9 @@ public:
|
|||||||
*
|
*
|
||||||
* @return true if equal
|
* @return true if equal
|
||||||
*/
|
*/
|
||||||
bool operator==(const DaqChannel& other) const {
|
bool operator==(const DaqChannel &other) const {
|
||||||
return other.name == name && other.sensitivity == sensitivity &&
|
return other.name == name && other.sensitivity == sensitivity &&
|
||||||
other.qty == qty;
|
other.qty == qty;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -250,9 +250,13 @@ public:
|
|||||||
/**
|
/**
|
||||||
* @brief Return list of enabled input channels
|
* @brief Return list of enabled input channels
|
||||||
*
|
*
|
||||||
|
* @param include_monitor If set to true and a monitor channel is available,
|
||||||
|
* the first indices in the array will correspond to the monitor channel(s).
|
||||||
|
*
|
||||||
* @return That.
|
* @return That.
|
||||||
*/
|
*/
|
||||||
std::vector<DaqChannel> enabledInChannels() const;
|
std::vector<DaqChannel>
|
||||||
|
enabledInChannels(const bool include_monitor = true) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Channel configuration for output channels
|
* @brief Channel configuration for output channels
|
||||||
@ -303,8 +307,8 @@ public:
|
|||||||
bool match(const DeviceInfo &devinfo) const;
|
bool match(const DeviceInfo &devinfo) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the enabled highest channel number from the list of enabled input
|
* @brief Get the enabled highest channel number from the list of enabled
|
||||||
* channels.
|
* input channels.
|
||||||
*
|
*
|
||||||
* @return Index to the highest input channel. -1 if no input channels are
|
* @return Index to the highest input channel. -1 if no input channels are
|
||||||
* enabled.
|
* enabled.
|
||||||
@ -342,7 +346,7 @@ public:
|
|||||||
* @param val true if enabled, false if disabled.
|
* @param val true if enabled, false if disabled.
|
||||||
*/
|
*/
|
||||||
void setAllInputEnabled(bool val) {
|
void setAllInputEnabled(bool val) {
|
||||||
for(auto& ch: inchannel_config) {
|
for (auto &ch : inchannel_config) {
|
||||||
ch.enabled = val;
|
ch.enabled = val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -353,7 +357,7 @@ public:
|
|||||||
* @param val true if enabled, false if disabled.
|
* @param val true if enabled, false if disabled.
|
||||||
*/
|
*/
|
||||||
void setAllOutputEnabled(bool val) {
|
void setAllOutputEnabled(bool val) {
|
||||||
for(auto& ch: outchannel_config) {
|
for (auto &ch : outchannel_config) {
|
||||||
ch.enabled = val;
|
ch.enabled = val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -182,13 +182,14 @@ public:
|
|||||||
boolvec eninchannels_without_mon = daq.eninchannels(false);
|
boolvec eninchannels_without_mon = daq.eninchannels(false);
|
||||||
|
|
||||||
// Initialize input, if any
|
// Initialize input, if any
|
||||||
|
dvec ranges = daq.inputRangeForEnabledChannels(false);
|
||||||
for (us chin = 0; chin < 4; chin++) {
|
for (us chin = 0; chin < 4; chin++) {
|
||||||
if (eninchannels_without_mon[chin] == true) {
|
if (eninchannels_without_mon[chin] == true) {
|
||||||
DaqInChanDescriptor indesc;
|
DaqInChanDescriptor indesc;
|
||||||
indesc.type = DAQI_ANALOG_SE;
|
indesc.type = DAQI_ANALOG_SE;
|
||||||
indesc.channel = chin;
|
indesc.channel = chin;
|
||||||
|
|
||||||
double rangeval = daq.inputRangeForChannel(chin);
|
double rangeval = ranges.at(chin);
|
||||||
Range rangenum;
|
Range rangenum;
|
||||||
if (fabs(rangeval - 1.0) < 1e-8) {
|
if (fabs(rangeval - 1.0) < 1e-8) {
|
||||||
rangenum = BIP1VOLTS;
|
rangenum = BIP1VOLTS;
|
||||||
|
@ -21,7 +21,7 @@ bool PPMHandler::inCallback_threaded(const DaqData &d) {
|
|||||||
Lck lck(_mtx);
|
Lck lck(_mtx);
|
||||||
|
|
||||||
dmat data = d.toFloat();
|
dmat data = d.toFloat();
|
||||||
/* data.print(); */
|
|
||||||
|
|
||||||
const us nchannels = d.nchannels;
|
const us nchannels = d.nchannels;
|
||||||
assert(data.n_cols == nchannels);
|
assert(data.n_cols == nchannels);
|
||||||
@ -31,26 +31,20 @@ bool PPMHandler::inCallback_threaded(const DaqData &d) {
|
|||||||
_cur_max = vd(nchannels, arma::fill::value(1e-80));
|
_cur_max = vd(nchannels, arma::fill::value(1e-80));
|
||||||
_clip_time = vd(nchannels, arma::fill::value(-1));
|
_clip_time = vd(nchannels, arma::fill::value(-1));
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(_clip_time.size() == _cur_max.size());
|
assert(_clip_time.size() == _cur_max.size());
|
||||||
|
|
||||||
/// Obtain max abs values
|
/// Obtain max abs values, and scale with range for each channel
|
||||||
vd maxabs = arma::max(arma::abs(data), 0).as_col();
|
vd maxabs = arma::max(arma::abs(data), 0).as_col() / _max_range;
|
||||||
/* maxabs.print(); */
|
|
||||||
|
|
||||||
arma::uvec clip_indices = arma::find(maxabs > clip_point);
|
/// Find indices for channels that have a clip
|
||||||
arma::uvec clip(nchannels, arma::fill::zeros);
|
arma::uvec clips = maxabs > clip_point;
|
||||||
clip.elem(clip_indices).fill(1);
|
|
||||||
|
|
||||||
arma::uvec update_max_idx = arma::find(maxabs > _cur_max);
|
/// Find channels where the new maximum is higher than the previous one
|
||||||
/* update_max_idx.print(); */
|
arma::uvec update_max = maxabs > _cur_max;
|
||||||
arma::uvec update_max(nchannels, arma::fill::zeros);
|
|
||||||
/* update_max.print(); */
|
|
||||||
update_max.elem(update_max_idx).fill(1);
|
|
||||||
|
|
||||||
assert(_cur_max.size() == _clip_time.size());
|
|
||||||
|
|
||||||
for (us i = 0; i < nchannels; i++) {
|
for (us i = 0; i < nchannels; i++) {
|
||||||
if (clip(i)) {
|
if (clips(i)) {
|
||||||
/// Reset clip counter
|
/// Reset clip counter
|
||||||
_clip_time(i) = 0;
|
_clip_time(i) = 0;
|
||||||
} else if (_clip_time(i) > clip_indication_time) {
|
} else if (_clip_time(i) > clip_indication_time) {
|
||||||
@ -90,6 +84,15 @@ void PPMHandler::reset(const Daq *daq) {
|
|||||||
|
|
||||||
_cur_max.fill(1e-80);
|
_cur_max.fill(1e-80);
|
||||||
|
|
||||||
|
const us nchannels = daq->neninchannels();
|
||||||
|
_max_range.resize(nchannels);
|
||||||
|
|
||||||
|
dvec ranges = daq->inputRangeForEnabledChannels();
|
||||||
|
assert(ranges.size() == nchannels);
|
||||||
|
for(us i=0;i<daq->neninchannels();i++) {
|
||||||
|
_max_range[i] = ranges[i];
|
||||||
|
}
|
||||||
|
|
||||||
_clip_time.fill(-1);
|
_clip_time.fill(-1);
|
||||||
|
|
||||||
const d fs = daq->samplerate();
|
const d fs = daq->samplerate();
|
||||||
|
@ -60,6 +60,11 @@ class PPMHandler: public ThreadedInDataHandler {
|
|||||||
*/
|
*/
|
||||||
vd _clip_time;
|
vd _clip_time;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Storage for maximum values
|
||||||
|
*/
|
||||||
|
vd _max_range;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Constructs Peak Programme Meter
|
* @brief Constructs Peak Programme Meter
|
||||||
|
@ -8,17 +8,17 @@ using std::endl;
|
|||||||
using Lck = std::scoped_lock<std::mutex>;
|
using Lck = std::scoped_lock<std::mutex>;
|
||||||
|
|
||||||
RtAps::RtAps(StreamMgr &mgr, const Filter *freqWeightingFilter,
|
RtAps::RtAps(StreamMgr &mgr, const Filter *freqWeightingFilter,
|
||||||
const us nfft,
|
const us nfft,
|
||||||
const Window::WindowType w,
|
const Window::WindowType w,
|
||||||
const d overlap_percentage, const d time_constant)
|
const d overlap_percentage, const d time_constant)
|
||||||
: ThreadedInDataHandler(mgr),
|
: ThreadedInDataHandler(mgr),
|
||||||
_ps(nfft, w, overlap_percentage, time_constant) {
|
_ps(nfft, w, overlap_percentage, time_constant) {
|
||||||
|
|
||||||
|
if (freqWeightingFilter != nullptr) {
|
||||||
|
_filterPrototype = freqWeightingFilter->clone();
|
||||||
|
}
|
||||||
|
|
||||||
if (freqWeightingFilter != nullptr) {
|
|
||||||
_filterPrototype = freqWeightingFilter->clone();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
RtAps::~RtAps() {
|
RtAps::~RtAps() {
|
||||||
Lck lck(_ps_mtx);
|
Lck lck(_ps_mtx);
|
||||||
stop();
|
stop();
|
||||||
@ -27,9 +27,15 @@ bool RtAps::inCallback_threaded(const DaqData &data) {
|
|||||||
|
|
||||||
DEBUGTRACE_ENTER;
|
DEBUGTRACE_ENTER;
|
||||||
|
|
||||||
|
Lck lck(_ps_mtx);
|
||||||
|
|
||||||
dmat fltdata = data.toFloat();
|
dmat fltdata = data.toFloat();
|
||||||
const us nchannels = fltdata.n_cols;
|
const us nchannels = fltdata.n_cols;
|
||||||
|
if(nchannels != _sens.size()) {
|
||||||
|
cerr << "**** Error: sensitivity size does not match! *****" << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
fltdata.each_row() %= _sens.as_row();
|
||||||
|
|
||||||
if (_filterPrototype) {
|
if (_filterPrototype) {
|
||||||
|
|
||||||
@ -45,7 +51,7 @@ bool RtAps::inCallback_threaded(const DaqData &data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Apply filtering
|
// Apply filtering
|
||||||
/* #pragma omp parallel for */
|
#pragma omp parallel for
|
||||||
for (us i = 0; i < nchannels; i++) {
|
for (us i = 0; i < nchannels; i++) {
|
||||||
vd col = fltdata.col(i);
|
vd col = fltdata.col(i);
|
||||||
_freqWeightingFilters.at(i)->filter(col);
|
_freqWeightingFilters.at(i)->filter(col);
|
||||||
@ -53,24 +59,32 @@ bool RtAps::inCallback_threaded(const DaqData &data) {
|
|||||||
}
|
}
|
||||||
} // End of if(_filterPrototype)
|
} // End of if(_filterPrototype)
|
||||||
|
|
||||||
Lck lck(_ps_mtx);
|
|
||||||
_ps.compute(fltdata);
|
_ps.compute(fltdata);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
void RtAps::reset(const Daq *daq) { // Explicitly say
|
void RtAps::reset(const Daq *daq) {
|
||||||
// to GCC that
|
|
||||||
// the argument is
|
|
||||||
// not used.
|
|
||||||
|
|
||||||
DEBUGTRACE_ENTER;
|
DEBUGTRACE_ENTER;
|
||||||
Lck lck(_ps_mtx);
|
Lck lck(_ps_mtx);
|
||||||
|
for (auto &filter : _freqWeightingFilters) {
|
||||||
|
filter->reset();
|
||||||
|
}
|
||||||
|
if(daq) {
|
||||||
|
_sens.resize(daq->neninchannels());
|
||||||
|
us i = 0;
|
||||||
|
for(const auto& ch: daq->enabledInChannels()) {
|
||||||
|
_sens[i] = ch.sensitivity;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_ps.reset();
|
_ps.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
ccube RtAps::getCurrentValue() const {
|
ccube RtAps::getCurrentValue() const {
|
||||||
|
|
||||||
/* DEBUGTRACE_ENTER; */
|
DEBUGTRACE_ENTER;
|
||||||
Lck lck(_ps_mtx);
|
Lck lck(_ps_mtx);
|
||||||
return _ps.get_est();
|
return _ps.get_est();
|
||||||
|
|
||||||
|
@ -24,6 +24,11 @@ class RtAps : public ThreadedInDataHandler {
|
|||||||
std::unique_ptr<Filter> _filterPrototype;
|
std::unique_ptr<Filter> _filterPrototype;
|
||||||
std::vector<std::unique_ptr<Filter>> _freqWeightingFilters;
|
std::vector<std::unique_ptr<Filter>> _freqWeightingFilters;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Storage for sensitivity values
|
||||||
|
*/
|
||||||
|
vd _sens;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Mutex only for _ps. Other members are only accessed in thread.
|
* @brief Mutex only for _ps. Other members are only accessed in thread.
|
||||||
*/
|
*/
|
||||||
|
@ -69,7 +69,9 @@ void init_daqconfiguration(py::module &m) {
|
|||||||
.value("UserDefined", DaqChannel::Qty::UserDefined);
|
.value("UserDefined", DaqChannel::Qty::UserDefined);
|
||||||
daqchannel.def_readwrite("qty", &DaqChannel::qty);
|
daqchannel.def_readwrite("qty", &DaqChannel::qty);
|
||||||
|
|
||||||
daqchannel.def("__eq__", [](const DaqChannel& a, const DaqChannel& b) { return a==b;});
|
daqchannel.def("__eq__", [](const DaqChannel &a, const DaqChannel &b) {
|
||||||
|
return a == b;
|
||||||
|
});
|
||||||
|
|
||||||
/// DaqConfiguration
|
/// DaqConfiguration
|
||||||
daqconfig.def(py::init<>());
|
daqconfig.def(py::init<>());
|
||||||
@ -95,5 +97,6 @@ void init_daqconfiguration(py::module &m) {
|
|||||||
&DaqConfiguration::outchannel_config);
|
&DaqConfiguration::outchannel_config);
|
||||||
daqconfig.def("setAllInputEnabled", &DaqConfiguration::setAllInputEnabled);
|
daqconfig.def("setAllInputEnabled", &DaqConfiguration::setAllInputEnabled);
|
||||||
daqconfig.def("setAllOutputEnabled", &DaqConfiguration::setAllOutputEnabled);
|
daqconfig.def("setAllOutputEnabled", &DaqConfiguration::setAllOutputEnabled);
|
||||||
daqconfig.def("enabledInChannels", &DaqConfiguration::enabledInChannels);
|
daqconfig.def("enabledInChannels", &DaqConfiguration::enabledInChannels,
|
||||||
|
py::arg("include_monitor") = true);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user