BmnRoot
Loading...
Searching...
No Matches
BmnNdetRaw2Digit.cxx
Go to the documentation of this file.
1#include "BmnNdetRaw2Digit.h"
2
3#include "BmnTrigRaw2Digit.h"
4#include "TMath.h"
5#include "TSystem.h"
6
8{
9 LOG(info) << Form("BmnNdetRaw2Digit");
10}
11
13 : WfmProcessor()
14{
15 fPeriodId = 0;
16 fRunId = 0;
17}
18
19BmnNdetRaw2Digit::BmnNdetRaw2Digit(int period, int run, TString mappingFile, TString CalibrationFile)
20 : WfmProcessor()
21{
22 LOG(info) << Form("BmnNdetRaw2Digit : Config file: %s", mappingFile.Data());
23 LOG(info) << Form("BmnNdetRaw2Digit : Calibration file: %s", CalibrationFile.Data());
24 fPeriodId = period;
25 fRunId = run;
26 fmappingFileName = mappingFile;
27 ParseConfig(fmappingFileName);
28 fcalibrationFileName = CalibrationFile;
29 ParseCalibration(fcalibrationFileName);
31}
32
33void BmnNdetRaw2Digit::ParseConfig(TString mappingFile)
34{
35
36 namespace po = boost::program_options;
37
38 TString dir = getenv("VMCWORKDIR");
39 TString path = dir + "/input/";
40
41 float version;
42 std::string comment;
43 std::vector<std::string> configuration;
44
45 // Setup options.
46 po::options_description desc("Options");
47 desc.add_options()("VERSION.id", po::value<float>(&version),
48 "version identificator")("COMMENT.str", po::value<std::string>(&comment), "comment")(
49 "CONFIGURATION.config", po::value<std::vector<std::string>>(&configuration)->multitoken(), "configuration");
50
51 // Load config file.
52 po::variables_map vm;
53 std::ifstream config_file((path + mappingFile).Data(), std::ifstream::in);
54 if (!config_file.is_open()) {
55 LOG(error) << Form("BmnNdetRaw2Digit : Loading Config from file: %s - file open error!", mappingFile.Data());
56 return;
57 }
58 LOG(debug) << Form("BmnNdetRaw2Digit : Loading Config from file: %s", mappingFile.Data());
59 po::store(po::parse_config_file(config_file, desc), vm);
60 config_file.close();
61 po::notify(vm);
62
63 std::string board_serial;
64 int board_channel;
65 int det_id, layer_id, row_id, column_id;
66
67 fuoChannelMap.clear();
68 for (auto it : configuration) {
69 istringstream ss(it);
70 ss >> board_serial >> board_channel >> det_id >> layer_id >> row_id >> column_id;
71 LOGF(debug, "config = %s %d %d %d %d %d", board_serial.c_str(), board_channel, 0, layer_id,
72 row_id, column_id);
73 assert(board_channel < 16);
74
75 auto key = std::make_pair(std::stoul(board_serial, nullptr, 16), board_channel);
76 fuoChannelMap[key] = BmnNdetAddress::GetAddress(det_id, row_id, column_id, layer_id);
77 }
78}
79
80void BmnNdetRaw2Digit::ParseCalibration(TString calibrationFile)
81{
82
83 namespace po = boost::program_options;
84
85 TString dir = getenv("VMCWORKDIR");
86 TString path = dir + "/parameters/ndet/";
87
88 float version;
89 std::string comment;
90 std::vector<std::string> harmonics;
91 std::vector<std::string> calibrations;
92
93 // Setup options.
94 po::options_description desc("Options");
95 desc.add_options()("VERSION.id", po::value<float>(&version),
96 "version identificator")("COMMENT.str", po::value<std::string>(&comment), "comment")(
97 "CHECKER.isWriteWfm", po::value<bool>(&fdigiPars.isWriteWfm),
98 "writing waveforms")("PARAMETERS.gateBegin", po::value<int>(&fdigiPars.gateBegin), "digi parameters")(
99 "PARAMETERS.gateEnd", po::value<int>(&fdigiPars.gateEnd),
100 "digi parameters")("PARAMETERS.threshold", po::value<float>(&fdigiPars.threshold), "digi parameters")(
101 "PARAMETERS.signalType", po::value<int>(&fdigiPars.signalType),
102 "digi parameters")("PARAMETERS.doInvert", po::value<bool>(&fdigiPars.doInvert), "digi parameters")(
103 "PARAMETERS.applyINLcorr", po::value<bool>(&fApplyINL),
104 "digi parameters")("PARAMETERS.applyAmplCalib", po::value<bool>(&fApplyAmplCalib), "digi parameters")(
105 "PARAMETERS.applyTimeCalib", po::value<bool>(&fApplyTimeCalib),
106 "digi parameters")("FITPARAMETERS.isfit", po::value<bool>(&fdigiPars.isfit), "digi parameters")(
107 "FITPARAMETERS.harmonic", po::value<std::vector<std::string>>(&harmonics)->multitoken(), "fit harmonics")(
108 "CALIBRATION.calib", po::value<std::vector<std::string>>(&calibrations)->multitoken(), "calibrations");
109
110 // Load config file.
111 po::variables_map vm;
112 std::ifstream calib_file((path + calibrationFile).Data(), std::ifstream::in);
113 if (!calib_file.is_open()) {
114 LOG(error) << Form("BmnNdetRaw2Digit : Loading Calibration from file: %s - file open error!",
115 calibrationFile.Data());
116 return;
117 }
118 LOG(debug) << Form("BmnNdetRaw2Digit : Loading Calibration from file: %s", calibrationFile.Data());
119 po::store(po::parse_config_file(calib_file, desc), vm);
120 calib_file.close();
121 po::notify(vm);
122
123 for (auto str : harmonics) {
124 if (str.find(',') != std::string::npos) {
125 // Split the string into real and imaginary parts
126 std::string real_part_str, imaginary_part_str;
127 std::istringstream iss(str);
128 std::getline(iss, real_part_str, ',');
129 std::getline(iss, imaginary_part_str);
130
131 // Convert the real and imaginary parts to floats
132 float real_part = std::stof(real_part_str);
133 float imaginary_part = std::stof(imaginary_part_str);
134
135 // Set the value to the complex number
136 fdigiPars.harmonics.push_back(std::complex<float>(real_part, imaginary_part));
137 } else
138 fdigiPars.harmonics.push_back(std::stof(str));
139 }
140
141 int det_id, layer_id, row_id, column_id;
142 float calibration;
143 float calibError;
144 float calibSlewP1;
145 float calibSlewP2;
146 float calibSlewP3;
147 float calibTimeShift;
148 fuoCalibMap.clear();
149 fuoCalibSlewShiftMap.clear();
150 for (auto it : calibrations) {
151 istringstream ss(it);
152 ss >> det_id >> layer_id >> row_id >> column_id >> calibration >> calibError >> calibSlewP1 >> calibSlewP2
153 >> calibSlewP3 >> calibTimeShift;
154
155 uint32_t address = BmnNdetAddress::GetAddress(det_id, row_id, column_id, layer_id);
156 fuoCalibMap[address] = std::make_pair(calibration, calibError);
157 std::vector<float> time_calib_vect{calibSlewP1, calibSlewP2, calibSlewP3, calibTimeShift};
158 fuoCalibSlewShiftMap[address] = time_calib_vect;
159 }
160
161 if (fdigiPars.isfit) {
162 int model_order = fdigiPars.harmonics.size() + 1;
164 auto maxElement = std::max_element(
165 fdigiPars.harmonics.begin(), fdigiPars.harmonics.end(),
166 [](const std::complex<float>& a, const std::complex<float>& b) { return std::abs(a) < std::abs(b); });
167 if (maxElement != fdigiPars.harmonics.end()) {
168 // set signal length as 5 * harmonic length
169 int maxElementLength = floor(5. / (-log(real(*maxElement))));
170 if (maxElementLength < fSignalLength)
171 fSignalLength = maxElementLength;
172 }
173
174 fAZik = new std::complex<float>*[model_order];
175 for (int i = 0; i < model_order; i++) {
176 fAZik[i] = new std::complex<float>[model_order];
177 for (int j = 0; j < model_order; j++)
178 fAZik[i][j] = {0., 0.};
179 }
185 }
186}
187
189{
190 if (!fApplyINL)
191 return;
192
193 TString dir = getenv("VMCWORKDIR");
194 TString path = dir + "/parameters/ndet/INLcorrections/";
195 LOG(info) << Form("BmnNdetRaw2Digit : Loading INL corrections from directory: %s", path.Data());
196
197 boost::property_tree::ptree pt;
198 TString header = "TQDC16VS_E";
199 TString postfix = "inl_corr";
200 fINLcorrMap.clear();
201
202 for (auto& it : fuoChannelMap) {
203 auto boardSerial = (unsigned int)it.first.first;
204 TString corrFileName = Form("%s%s-%04X-%04X.ini", path.Data(), header.Data(),
205 ((boardSerial & 0xffff0000) >> 16), (boardSerial & 0xffff));
206 boost::property_tree::ini_parser::read_ini(corrFileName.Data(), pt);
207 TString thisHeader = Form("%s-%08x-%s", header.Data(), boardSerial, postfix.Data());
208 for (UInt_t chan_iter = 0; chan_iter < TQDC16_CHANNEL_COUNT; chan_iter++) {
209 auto correction_string = pt.get<std::string>(Form("%s.%d", thisHeader.Data(), chan_iter));
210 istringstream ss(correction_string);
211
212 std::string token;
213 std::vector<float> corrV;
214 while (std::getline(ss, token, ','))
215 corrV.push_back(stof(token));
216 assert(corrV.size() == 1024);
217
218 auto key = std::make_pair(boardSerial, chan_iter);
219 fINLcorrMap[key] = corrV;
220 } // channels loop
221 } // serials loop
222}
223
224std::optional<uint32_t> BmnNdetRaw2Digit::GetAddressFromBoard(std::pair<size_t, size_t> key)
225{
226 try {
227 return fuoChannelMap.at(key);
228 } catch (const std::out_of_range& e) {
229 LOG(debug) << "BmnNdetRaw2Digit:: GetAddressFromBoard. Board serial " << std::hex << key.first << std::dec
230 << " channel " << key.second << " is not connected. Skipping it";
231 return std::nullopt;
232 }
233}
234
235std::optional<std::pair<float, float>> BmnNdetRaw2Digit::GetCalibPairFromAddress(uint32_t address)
236{
237 try {
238 return fuoCalibMap.at(address);
239 } catch (const std::out_of_range& e) {
240 LOG(debug) << "BmnNdetRaw2Digit:: GetCalibPairFromAddress " << std::bitset<32>(address)
241 << " is marked badly in calibration file.";
242 return std::nullopt;
243 }
244}
245
246uint32_t BmnNdetRaw2Digit::correctINL(uint32_t time, std::pair<size_t, size_t> key)
247{
248 try {
249 return time + fINLcorrMap.at(key).at(time & 1023);
250 } catch (const std::out_of_range& e) {
251 LOG(warning) << "BmnNdetRaw2Digit::correctINL. Board serial " << std::hex << key.first << std::dec
252 << " channel " << key.second << " is not connected. Leave without INL correction";
253 return time;
254 }
255}
256
257std::vector<float> BmnNdetRaw2Digit::GetCalibSlewShiftFromAddress(uint32_t address)
258{
259 if (fuoCalibSlewShiftMap.find(address) != fuoCalibSlewShiftMap.end())
260 return fuoCalibSlewShiftMap.at(address);
261
262 return {0.0, 0.0, 0.0, 0.0};
263}
264
265void BmnNdetRaw2Digit::fillEvent(TClonesArray* tdc,
266 TClonesArray* adc,
267 unordered_map<UInt_t, Long64_t>* mapTS,
268 TClonesArray* Ndetdigit)
269{
270
271 LOG(debug) << "BmnNdetRaw2Digit::fillEvent";
272 // double trigTime = findTriggerTime(tdc);
273 // time is more important, it goes first
274 for (Int_t iTdc = 0; iTdc < tdc->GetEntriesFast(); iTdc++) {
275 BmnTDCDigit* tdcDig = (BmnTDCDigit*)tdc->At(iTdc);
276 auto key = std::make_pair(tdcDig->GetSerial(), tdcDig->GetChannel());
277 auto catch_address = GetAddressFromBoard(key);
278 if (!catch_address.has_value())
279 continue; // Not connected lines
280 auto address = catch_address.value();
281 if (address == 0)
282 continue; // not connected lines
283
284 auto catch_calib = GetCalibPairFromAddress(address);
285 if (!catch_calib.has_value())
286 continue; // not involved in the analysis
287 auto calib_pair = catch_calib.value();
288
289 UInt_t ttvxs_ndet = 0x0CD9B727;
290 unordered_map<UInt_t, Long64_t>::iterator itTS = mapTS->find(ttvxs_ndet);
291 if (itTS == mapTS->end()) {
292 continue;
293 }
294 double TimeShift = itTS->second;
295 double time = (fApplyINL) ? correctINL(tdcDig->GetValue(), key) : tdcDig->GetValue();
296 time *= 0.024 / 1.024;
297 time += TimeShift;
298
299 BmnNdetDigi ThisDigi;
300 ThisDigi.reset();
301 ThisDigi.SetAddress(address);
302 ThisDigi.SetTime(time);
303 LOG(debug) << "BmnNdetRaw2Digit::Switch to adc digit" << endl;
304 for (int iAdc = 0; iAdc < adc->GetEntriesFast(); iAdc++) {
305 BmnTQDCADCDigit* adcDig = (BmnTQDCADCDigit*)adc->At(iAdc);
306 if (tdcDig->GetSerial() != adcDig->GetSerial() || tdcDig->GetSlot() != adcDig->GetSlot())
307 continue;
308 if (tdcDig->GetChannel() != adcDig->GetChannel())
309 continue;
310
311 std::vector<float> wfm(adcDig->GetShortValue(), adcDig->GetShortValue() + adcDig->GetNSamples());
312 ProcessWfm(wfm, &ThisDigi);
313
314 // Apply calibration
315 LOG(debug) << "BmnNdetRaw2Digit::ProcessWfm Calibration" << endl;
316 if (fApplyAmplCalib == true) {
317 if (fdigiPars.signalType == 0)
318 ThisDigi.SetSignal(ThisDigi.fAmpl * calib_pair.first);
319 if (fdigiPars.signalType == 1)
320 ThisDigi.SetSignal(ThisDigi.fIntegral * calib_pair.first);
321 } else {
322 if (fdigiPars.signalType == 0)
323 ThisDigi.SetSignal(ThisDigi.fAmpl);
324 if (fdigiPars.signalType == 1)
325 ThisDigi.SetSignal(ThisDigi.fIntegral);
326 }
327 if (fApplyTimeCalib == true) {
328 auto calib_slew_shift = GetCalibSlewShiftFromAddress(ThisDigi.GetAddress());
329 time = time
330 - ((calib_slew_shift.at(0)) / sqrt(ThisDigi.GetSignal() + calib_slew_shift.at(1))
331 + calib_slew_shift.at(2))
332 - calib_slew_shift.at(3);
333 ThisDigi.SetTime(time);
334 } else {
335 ThisDigi.SetTime(time);
336 }
337 }
338
339 if (ThisDigi.GetSignal() < fdigiPars.threshold)
340 continue;
341
342 TClonesArray& ar_Ndet = *Ndetdigit;
343 new (ar_Ndet[Ndetdigit->GetEntriesFast()]) BmnNdetDigi(ThisDigi);
344 }
345}
346
friend F32vec4 sqrt(const F32vec4 &a)
Definition P4_F32vec4.h:34
int i
Definition P4_F32vec4.h:22
friend F32vec4 log(const F32vec4 &a)
Definition P4_F32vec4.h:123
UInt_t GetNSamples() const
Definition BmnADCDigit.h:35
UShort_t GetChannel() const
Definition BmnADCDigit.h:33
UInt_t GetSerial() const
Definition BmnADCDigit.h:31
Short_t * GetShortValue() const
Definition BmnADCDigit.h:39
void SetAddress(uint32_t address)
void SetTime(double time)
double GetSignal() const
uint32_t GetAddress() const
void SetSignal(double signal)
int fIntegral
ZeroLevel from waveform [adc counts].
static uint32_t GetAddress(uint32_t ArmId, uint32_t RowId, uint32_t ColumnId, uint32_t LayerId)
Return address.
Data class for Bmn Ndet digital signal processing.
Definition BmnNdetDigi.h:24
void reset() override final
Definition BmnNdetDigi.h:37
std::optional< std::pair< float, float > > GetCalibPairFromAddress(uint32_t address)
void ParseCalibration(TString calibrationFile)
std::optional< uint32_t > GetAddressFromBoard(std::pair< size_t, size_t > key)
std::vector< float > GetCalibSlewShiftFromAddress(uint32_t address)
uint32_t correctINL(uint32_t time, std::pair< size_t, size_t > key)
void ParseConfig(TString mappingFile)
void fillEvent(TClonesArray *tdc_data, TClonesArray *adc_data, unordered_map< UInt_t, Long64_t > *mapTS, TClonesArray *Ndetdigit)
UInt_t GetValue() const
Definition BmnTDCDigit.h:32
UInt_t GetSerial() const
Definition BmnTDCDigit.h:22
UChar_t GetSlot() const
Definition BmnTDCDigit.h:26
UChar_t GetChannel() const
Definition BmnTDCDigit.h:30
UChar_t GetSlot() 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)
std::complex< float > ** fAZik
struct WfmProcessor::digiPars fdigiPars
void ProcessWfm(std::vector< float > &wfm, BmnDigiContainerTemplate *digi)
#define TQDC16_CHANNEL_COUNT
-clang-format
std::vector< std::complex< float > > harmonics