3#include "BmnADCDigit.h"
4#include "BmnSyncDigit.h"
5#include "BmnTDCDigit.h"
6#include "BmnTQDCADCDigit.h"
12#include "UniDetectorParameter.h"
14#include <boost/algorithm/string/classification.hpp>
15#include <boost/algorithm/string/split.hpp>
16#include <boost/lexical_cast.hpp>
17#include <boost/tokenizer.hpp>
39 const std::string& mappingFile,
40 const std::string& calibrationFile)
51 auto logIfError = [
this](
const char* what,
BmnStatus st) {
53 LOG(error) <<
GetName() <<
": " << what <<
" was not loaded, decoder may misbehave!";
56 LOG(info) <<
Form(
"%s : Config file: %s",
GetName().Data(), mappingFile.c_str());
60 if (!calibrationFile.empty()) {
61 LOG(info) <<
Form(
"%s : Hand-set Calibration file: %s",
GetName().Data(), calibrationFile.c_str());
66 logIfError(
"calibration", calibStatus);
71 std::string fullPath = std::string(getenv(
"VMCWORKDIR")) +
"/parameters/hodo/" + file;
72 std::ifstream config_file(fullPath);
73 if (!config_file.is_open()) {
74 LOG(error) <<
GetName() <<
"::ParseConfig: Cannot open config file: " << fullPath;
81 }
catch (
const std::exception& e) {
82 LOG(error) <<
GetName() <<
"::ParseConfig: Failed to parse JSON: " << e.what();
86 LOG(debug) <<
GetName() <<
"::ParseConfig. Version: " << j.value(
"version",
"unknown");
87 LOG(debug) <<
GetName() <<
"::ParseConfig. Comment: " << j.value(
"comment",
"none");
90 for (
const auto& entry : j[
"mapping"]) {
91 std::string serial = entry[
"serial"];
92 int channel = entry[
"channel"];
93 int strip = entry[
"strip"];
94 int side = entry[
"side"];
95 int gain = entry[
"gain"];
97 auto key = std::make_pair(std::stoul(serial,
nullptr, 16), channel);
107 bool gotFromDb =
false;
110 if (pParam !=
nullptr) {
112 if (pValue !=
nullptr) {
121 LOG(info) <<
GetName() <<
" : Loaded calibration from DB for period " << period <<
", run " << run;
125 const std::string fallbackFile =
Form(
"HODO_Q_calibration_period%d.json", period);
127 LOG(warn) <<
GetName() <<
" : No calibration in DB for period " << period <<
", run " << run
128 <<
". Falling back to file " << fallbackFile;
136 std::string fullPath = std::string(getenv(
"VMCWORKDIR")) +
"/parameters/hodo/" + file;
137 std::ifstream config_file(fullPath);
138 if (!config_file.is_open()) {
139 LOG(error) <<
GetName() <<
"::ParseCalibration: Cannot open config file: " << fullPath;
146 }
catch (
const std::exception& e) {
147 LOG(error) <<
GetName() <<
"::ParseCalibration: Failed to parse JSON: " << e.what();
156 LOG(debug) <<
GetName() <<
"::ParseCalibrationJson. Version: " << j.value(
"version",
"unknown");
157 LOG(debug) <<
GetName() <<
"::ParseCalibrationJson. Comment: " << j.value(
"comment",
"none");
161 const auto& par = j.at(
"parameters");
163 fdigiPars.isWriteWfm = par.value(
"isWriteWfm",
false);
164 fdigiPars.gateBegin = par.at(
"gateBegin");
166 fdigiPars.threshold = par.at(
"threshold");
168 fdigiPars.doInvert = par.value(
"doInvert",
false);
169 bool applyINL = par.value(
"applyINLcorr",
true);
174 for (
const auto& ch : j.at(
"calibration")) {
175 int strip = ch.at(
"strip");
176 int side = ch.at(
"side");
177 int gain = ch.at(
"gain");
178 float calib = ch.at(
"ampl");
179 float integ = ch.at(
"integral");
184 if (j.contains(
"deconvParameters")) {
185 const auto& decpar = j.at(
"deconvParameters");
190 fMaxIters = decpar.value(
"iterations", 0);
192 if (decpar.contains(
"ethalon") && decpar[
"ethalon"].is_array()) {
193 auto tmp = decpar[
"ethalon"].get<std::vector<float>>();
198 if (j.contains(
"fitParameters")) {
199 const auto& fitpar = j.at(
"fitParameters");
200 fdigiPars.isfit = fitpar.value(
"isfit",
false);
202 for (
const auto& pair : fitpar.at(
"harmonics")) {
203 float re = pair.at(0).get<
float>();
204 float im = pair.at(1).get<
float>();
205 fdigiPars.harmonics.emplace_back(re, im);
209 int model_order =
fdigiPars.harmonics.size() + 1;
211 auto maxElement = std::max_element(
fdigiPars.harmonics.begin(),
fdigiPars.harmonics.end(),
212 [](
const std::complex<float>& a,
const std::complex<float>& b) {
213 return std::abs(a) < std::abs(b);
215 if (maxElement !=
fdigiPars.harmonics.end()) {
217 int maxElementLength =
floor(5. / (-
log(real(*maxElement))));
222 fAZik =
new std::complex<float>*[model_order];
223 for (
int i = 0;
i < model_order;
i++) {
224 fAZik[
i] =
new std::complex<float>[model_order];
225 for (
int k = 0; k < model_order; k++)
235 }
catch (
const std::exception& e) {
236 LOG(error) <<
GetName() <<
"::ParseCalibrationJson: error while parsing: " << e.what();
245 std::string path = std::string(getenv(
"VMCWORKDIR")) +
"/parameters/hodo/INLcorrections/";
246 LOG(info) <<
Form(
"%s : Loading INL corrections from directory: %s",
GetName().Data(), path.c_str());
248 boost::property_tree::ptree pt;
249 std::string header =
"TQDC16VS";
250 std::string iniheader = header +
"_E";
251 std::string postfix =
"inl_corr";
255 auto boardSerial = (
unsigned int)it.first.first;
256 std::string corrFileName =
Form(
"%s%s-%04X-%04X.ini", path.c_str(), header.c_str(),
257 ((boardSerial & 0xffff0000) >> 16), (boardSerial & 0xffff));
258 boost::property_tree::ini_parser::read_ini(corrFileName.c_str(), pt);
259 std::string thisHeader =
Form(
"%s-%08x-%s", iniheader.c_str(), boardSerial, postfix.c_str());
261 auto correction_string = pt.get<std::string>(
Form(
"%s.%d", thisHeader.c_str(), chan_iter));
262 istringstream ss(correction_string);
265 std::vector<float> corrV;
266 while (std::getline(ss, token,
','))
267 corrV.push_back(stof(token));
268 assert(corrV.size() == 1024);
270 auto key = std::make_pair(boardSerial, chan_iter);
282 }
catch (
const std::out_of_range& e) {
283 LOG(debug) <<
GetName() <<
":: GetAddressFromBoard. Board serial " << std::hex << key.first << std::dec
284 <<
" channel " << key.second <<
" is not connected. Skipping it";
293 }
catch (
const std::out_of_range& e) {
294 LOG(warning) <<
GetName() <<
"::correctINL. Board serial " << std::hex << key.first << std::dec <<
" channel "
295 << key.second <<
" is not connected. Leave without INL correction";
304 }
catch (
const std::out_of_range& e) {
305 LOG(debug) <<
GetName() <<
":: GetCalibPairFromAddress " << std::bitset<32>(address)
306 <<
" is marked badly in calibration file.";
314 LOG(debug) <<
GetName() <<
"::fillEvent";
322 auto key = std::make_pair(adcDig->GetSerial(), adcDig->GetChannel());
324 if (!catch_address.has_value())
326 auto address = catch_address.value();
329 if (!catch_calib.has_value())
331 auto calib_pair = catch_calib.value();
338 if (tdcDig->
GetChannel() != adcDig->GetChannel())
344 std::vector<float> wfm(adcDig->GetValue().begin(), adcDig->GetValue().end());
345 std::vector<BmnHodoDigi> digi_vector;
353 ThisDigi.
fIntegral = (int)std::accumulate(wfm.begin(), wfm.end(), 0.0);
361 digi_vector.push_back(ThisDigi);
366 LOG(debug4) <<
GetName() <<
"::ProcessWfm RLDeconvolutor";
371 assert(decomposition.size() == positions.size());
372 auto fitR2 = deconvolution.
getR2().back();
375 std::vector<size_t> indices(positions.size());
376 std::iota(indices.begin(), indices.end(), 0);
379 std::sort(indices.begin(), indices.end(),
380 [&positions](
size_t a,
size_t b) { return positions[a].second > positions[b].second; });
381 std::vector<size_t> topIndices = (
fMaxPeaks <= indices.size())
382 ? std::vector<size_t>(indices.begin(), indices.begin() +
fMaxPeaks)
386 LOG(debug4) <<
GetName() <<
"::ProcessWfm Selection";
387 for (
auto it : topIndices) {
388 auto time_max = positions.at(it).first;
389 auto ampl = positions.at(it).second;
390 auto sub_wfm = decomposition.at(it);
405 *std::min_element(sub_wfm.begin() +
fdigiPars.gateBegin, sub_wfm.begin() +
fdigiPars.gateEnd + 1);
413 digi_vector.push_back(SubDigi);
418 for (
auto& digi : digi_vector) {
419 digi.fNpeaks = digi_vector.size();
friend F32vec4 max(const F32vec4 &a, const F32vec4 &b)
char * Form(const char *fmt,...)
BmnStatus
Define status code.
void SetAddress(uint32_t address)
void SetTime(double time)
void SetSignal(double signal)
std::vector< float > fFitWfm
std::vector< float > fWfm
Time of maximum in fit of waveform [adc samples].
float fFitTimeMax
Quality of waveform fit [] – good near 0.
float fFitR2
Energy deposition from fit of waveform [adc counts].
int fZL
Amplitude from waveform [adc counts].
float fFitAmpl
Time over threshold [adc samples].
int fTimeMax
Energy deposition from waveform [adc counts].
int fIntegral
ZeroLevel from waveform [adc counts].
static uint32_t GetAddress(uint32_t StripId, uint32_t StripSide, uint32_t Gain)
Return address from system ID, StripId, StripSide, Gain.
Data class for BmnHodo digital signal processing.
void reset() override final
std::vector< float > fR2history
void SetIsSaturated(bool satur)
void FillEvent(TClonesArray *tdc_data, TClonesArray *adc_data, TClonesArray *Hododigit)
BmnStatus ParseConfig(const std::string &file)
uint32_t correctINL(uint32_t time, std::pair< size_t, size_t > key)
std::optional< std::pair< float, float > > GetCalibPairFromAddress(uint32_t address)
std::unordered_map< std::pair< size_t, size_t >, std::vector< float >, boost::hash< std::pair< size_t, size_t > > > fINLcorrMap
BmnStatus ParseINLcorrections()
BmnStatus LoadCalibration(int period, int run)
std::vector< float > fEthalon
BmnStatus ParseCalibrationJson(const nlohmann::json &j)
std::unordered_map< uint32_t, std::pair< float, float > > fuoCalibMap
BmnStatus ParseCalibration(const std::string &file)
std::unordered_map< std::pair< size_t, size_t >, uint32_t, boost::hash< std::pair< size_t, size_t > > > fuoChannelMap
std::optional< uint32_t > GetAddressFromBoard(std::pair< size_t, size_t > key)
UChar_t GetChannel() const
void SetExternalHarmonics(std::vector< std::complex< float > > harmonics)
void Initialize(int model_order, int exponent_number, int gate_beg, int gate_end)
void MakeInvHarmoMatrix(int signal_length, std::complex< float > **output)
Class to apply Richardson-Lucy deconvolution.
const std::vector< float > & getR2() const
const std::vector< std::pair< size_t, float > > & getSignalInfo() const
const std::vector< std::vector< float > > & getSignalDecomposition() const
Int_t GetEntriesFast() const
TObject * At(Int_t idx) const override
void Start(Bool_t reset=kTRUE)
int GetValue(vector< UniValue * > ¶meter_value)
get value of detector parameter presented by an array
static UniDetectorParameter * GetDetectorParameter(int value_id)
get detector parameter from the database
std::complex< float > ** fAZik
struct WfmProcessor::digiPars fdigiPars
void ProcessWfm(std::vector< float > &wfm, BmnDigiContainerTemplate *digi)
#define TQDC16_CHANNEL_COUNT
#define ADC_CLOCK_TQDC16VS
RVec< PromoteType< T > > floor(const RVec< T > &v)
RVec< PromoteType< T > > log(const RVec< T > &v)
basic_json<> json
default specialization