BmnRoot 26.10.0-18-g4e3414f9
Software framework of the BM@N experiment
Loading...
Searching...
No Matches
BmnScWallRaw2Digit.cxx
Go to the documentation of this file.
2
3#include "BmnADCDigit.h"
4#include "BmnScWallDigi.h"
5#include "BmnSyncDigit.h"
6#include "TMath.h"
7#include "TSystem.h"
8#include "UniDetectorParameter.h"
9
10#include <TStopwatch.h>
11#include <bitset>
12
14{
15 LOG(info) << Form("%s", GetName().Data());
16}
17
24
26 int run,
27 const std::string& mappingFile,
28 const std::string& calibrationFile)
29 : WfmProcessor()
30
31 , fworkTime_real(0.0)
32 , fworkTime_cpu(0.0)
33{
34 auto logIfError = [this](const char* what, BmnStatus st) {
35 if (st == kBMNERROR)
36 LOG(error) << GetName() << ": " << what << " was not loaded, decoder may misbehave!";
37 };
38
39 LOG(info) << Form("%s : Config file: %s", GetName().Data(), mappingFile.c_str());
40 logIfError("mapping", ParseConfig(mappingFile));
41
42 BmnStatus calibStatus;
43 if (!calibrationFile.empty()) {
44 LOG(info) << Form("%s : Hand-set Calibration file: %s", GetName().Data(), calibrationFile.c_str());
45 calibStatus = ParseCalibration(calibrationFile);
46 } else {
47 calibStatus = LoadCalibration(period, run);
48 }
49 logIfError("calibration", calibStatus);
50}
51
53{
54 std::string fullPath = std::string(getenv("VMCWORKDIR")) + "/parameters/scwall/" + file;
55 std::ifstream config_file(fullPath);
56 if (!config_file.is_open()) {
57 LOG(error) << GetName() << "::ParseConfig: Cannot open config file: " << fullPath;
58 return kBMNERROR;
59 }
60
62 try {
63 config_file >> j;
64 } catch (const std::exception& e) {
65 LOG(error) << GetName() << "::ParseConfig: Failed to parse JSON: " << e.what();
66 return kBMNERROR;
67 }
68
69 LOG(debug) << GetName() << "::ParseConfig. Version: " << j.value("version", "unknown");
70 LOG(debug) << GetName() << "::ParseConfig. Comment: " << j.value("comment", "none");
71
72 fuoChannelMap.clear();
73 for (const auto& entry : j["mapping"]) {
74 std::string serial = entry["serial"];
75 int channel = entry["channel"];
76 int cell = entry["cell"];
77
78 auto key = std::make_pair(std::stoul(serial, nullptr, 16), channel);
80 }
81
82 return kBMNSUCCESS;
83}
84
86{
88 bool gotFromDb = false;
89
90 UniDetectorParameter* pParam =
91 UniDetectorParameter::GetDetectorParameter("SCWALL", "scwall_calibration", period, run);
92 if (pParam != nullptr) {
93 JsonValue* pValue = (JsonValue*)pParam->GetValue();
94 if (pValue != nullptr) {
95 j = pValue->value;
96 gotFromDb = true;
97 delete pValue;
98 }
99 delete pParam;
100 }
101
102 if (gotFromDb) {
103 LOG(info) << GetName() << " : Loaded calibration from DB for period " << period << ", run " << run;
104
105 return ParseCalibrationJson(j);
106 } else {
107 const std::string fallbackFile = Form("SCWALL_calibration_period%d.json", period);
108
109 LOG(warn) << GetName() << " : No calibration in DB for period " << period << ", run " << run
110 << ". Falling back to file " << fallbackFile;
111
112 return ParseCalibration(fallbackFile);
113 }
114}
115
117{
118 std::string fullPath = std::string(getenv("VMCWORKDIR")) + "/parameters/scwall/" + file;
119 std::ifstream config_file(fullPath);
120 if (!config_file.is_open()) {
121 LOG(error) << GetName() << "::ParseCalibration: Cannot open config file: " << fullPath;
122 return kBMNERROR;
123 }
124
126 try {
127 config_file >> j;
128 } catch (const std::exception& e) {
129 LOG(error) << GetName() << "::ParseCalibration: Failed to parse JSON: " << e.what();
130 return kBMNERROR;
131 }
132
133 return ParseCalibrationJson(j);
134}
135
137{
138 LOG(debug) << GetName() << "::ParseCalibrationJson. Version: " << j.value("version", "unknown");
139 LOG(debug) << GetName() << "::ParseCalibrationJson. Comment: " << j.value("comment", "none");
140
141 try {
142
143 const auto& par = j.at("parameters");
144
145 fdigiPars.isWriteWfm = par.value("isWriteWfm", false);
146 fdigiPars.gateBegin = par.at("gateBegin");
147 fdigiPars.gateEnd = par.at("gateEnd");
148 fdigiPars.threshold = par.at("threshold");
149 fdigiPars.doInvert = par.value("doInvert", false);
150
151 fuoCalibMap.clear();
152 for (const auto& ch : j.at("calibration")) {
153 int cell = ch.at("cell");
154 float calib = ch.at("ampl");
155
156 fuoCalibMap[BmnScWallAddress::GetAddress(cell)] = std::make_pair(calib, 0.0);
157 }
158
159 if (j.contains("fitParameters")) {
160 const auto& fitpar = j.at("fitParameters");
161 fdigiPars.isfit = fitpar.value("isfit", false);
162 fdigiPars.harmonics.clear();
163 for (const auto& pair : fitpar.at("harmonics")) {
164 float re = pair.at(0).get<float>();
165 float im = pair.at(1).get<float>();
166 fdigiPars.harmonics.emplace_back(re, im);
167 }
168
169 if (fdigiPars.isfit) {
170 int model_order = fdigiPars.harmonics.size() + 1;
171 fSignalLength = fdigiPars.gateEnd - fdigiPars.gateBegin + 1;
172 auto maxElement = std::max_element(fdigiPars.harmonics.begin(), fdigiPars.harmonics.end(),
173 [](const std::complex<float>& a, const std::complex<float>& b) {
174 return std::abs(a) < std::abs(b);
175 });
176 if (maxElement != fdigiPars.harmonics.end()) {
177 // set signal length as 5 * harmonic length
178 int maxElementLength = floor(5. / (-log(real(*maxElement))));
179 if (maxElementLength < fSignalLength)
180 fSignalLength = maxElementLength;
181 }
182
183 fAZik = new std::complex<float>*[model_order];
184 for (int i = 0; i < model_order; i++) {
185 fAZik[i] = new std::complex<float>[model_order];
186 for (int k = 0; k < model_order; k++)
187 fAZik[i][k] = {0., 0.};
188 }
190 Pfitter.Initialize(fdigiPars.harmonics.size(), fdigiPars.harmonics.size(), fdigiPars.gateBegin,
191 fdigiPars.gateEnd);
192 Pfitter.SetExternalHarmonics(fdigiPars.harmonics);
194 }
195 }
196 } catch (const std::exception& e) {
197 LOG(error) << GetName() << "::ParseCalibrationJson: error while parsing: " << e.what();
198 return kBMNERROR;
199 }
200
201 return kBMNSUCCESS;
202}
203
204std::optional<uint32_t> BmnScWallRaw2Digit::GetAddressFromBoard(std::pair<size_t, size_t> key)
205{
206 try {
207 return fuoChannelMap.at(key);
208 } catch (const std::out_of_range& e) {
209 LOG(debug) << "BmnScWallRaw2Digit:: GetAddressFromBoard. Board serial " << std::hex << key.first << std::dec
210 << " channel " << key.second << " is not connected. Skipping it";
211 return std::nullopt;
212 }
213}
214
215std::optional<std::pair<float, float>> BmnScWallRaw2Digit::GetCalibPairFromAddress(uint32_t address)
216{
217 try {
218 return fuoCalibMap.at(address);
219 } catch (const std::out_of_range& e) {
220 LOG(debug) << "BmnScWallRaw2Digit:: GetCalibPairFromAddress " << std::bitset<32>(address)
221 << " is marked badly in calibration file.";
222 return std::nullopt;
223 }
224}
226{
227
228 LOG(debug) << "BmnScWallRaw2Digit::fillEvent";
229 TStopwatch timer;
230 timer.Start();
231
232 for (int i = 0; i < data->GetEntriesFast(); i++) {
234 auto key = std::make_pair(digit->GetSerial(), digit->GetChannel());
235 auto catch_address = GetAddressFromBoard(key);
236 if (!catch_address.has_value())
237 continue; // Not connected lines
238 auto address = catch_address.value();
239 if (address == 0)
240 continue; // Not connected lines
241
242 auto catch_calib = GetCalibPairFromAddress(address);
243 if (!catch_calib.has_value())
244 continue; // not involved in the analysis
245 auto calib_pair = catch_calib.value();
246
247 std::vector<float> wfm(digit->GetValue().begin(), digit->GetValue().end());
248 BmnScWallDigi ThisDigi;
249 ThisDigi.reset();
250 ThisDigi.SetAddress(address);
251 ProcessWfm(wfm, &ThisDigi);
252
253 // Apply calibration
254 LOG(debug4) << "BmnScWallRaw2Digit::ProcessWfm Calibration";
255 if (fdigiPars.signalType == 0)
256 ThisDigi.SetSignal((float)ThisDigi.fAmpl * calib_pair.first);
257 if (fdigiPars.signalType == 1)
258 ThisDigi.SetSignal((float)ThisDigi.fIntegral * calib_pair.first);
259 if (ThisDigi.GetSignal() < fdigiPars.threshold)
260 continue;
261
262 TClonesArray& ar_ScWall = *ScWalldigit;
263 new (ar_ScWall[ScWalldigit->GetEntriesFast()]) BmnScWallDigi(ThisDigi);
264 }
265
266 timer.Stop();
267 fworkTime_cpu += timer.RealTime();
268 fworkTime_real += timer.CpuTime();
269}
270
272{
273 LOG(info) << Form("%10s: Real time %4.3f s, CPU time %4.3f s", GetName().Data(), fworkTime_real, fworkTime_cpu);
274}
int i
Definition P4_F32vec4.h:22
char * Form(const char *fmt,...)
BmnStatus
Define status code.
Definition BmnEnums.h:93
@ kBMNERROR
Error.
Definition BmnEnums.h:95
@ kBMNSUCCESS
Success.
Definition BmnEnums.h:94
uint32_t GetSerial() const
Definition BmnADCDigit.h:49
vector< IntType > & GetValue()
Definition BmnADCDigit.h:55
uint16_t GetChannel() const
Definition BmnADCDigit.h:51
void SetAddress(uint32_t address)
double GetSignal() const
void SetSignal(double signal)
int fIntegral
ZeroLevel from waveform [adc counts].
static uint32_t GetAddress(uint32_t CellId)
Return address from system ID, Cell ID.
Class for experimental data at digi level.
void reset() override final
BmnStatus ParseCalibration(const std::string &file)
std::optional< uint32_t > GetAddressFromBoard(std::pair< size_t, size_t > key)
std::optional< std::pair< float, float > > GetCalibPairFromAddress(uint32_t address)
BmnStatus ParseCalibrationJson(const nlohmann::json &j)
std::unordered_map< std::pair< size_t, size_t >, uint32_t, boost::hash< std::pair< size_t, size_t > > > fuoChannelMap
BmnStatus ParseConfig(const std::string &file)
BmnStatus LoadCalibration(int period, int run)
std::unordered_map< uint32_t, std::pair< float, float > > fuoCalibMap
void FillEvent(TClonesArray *data, TClonesArray *ScWalldigit)
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)
Int_t GetEntriesFast() const
TObject * At(Int_t idx) const override
Double_t RealTime()
void Start(Bool_t reset=kTRUE)
Double_t CpuTime()
void Stop()
int GetValue(vector< UniValue * > &parameter_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)
RVec< PromoteType< T > > floor(const RVec< T > &v)
RVec< PromoteType< T > > log(const RVec< T > &v)
basic_json<> json
default specialization
Definition json.hpp:3365