CbmRoot
Loading...
Searching...
No Matches
CbmPsdUnpackAlgo.cxx
Go to the documentation of this file.
1/* Copyright (C) 2021 Goethe-University Frankfurt, Frankfurt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Pascal Raisig [committer] */
4
5#include "CbmPsdUnpackAlgo.h"
6
7#include "PronyFitter.h"
10
11#include <FairParGenericSet.h>
12#include <FairTask.h>
13#include <Logger.h>
14
15#include <Rtypes.h>
16#include <RtypesCore.h>
17
18#include <cstddef>
19#include <cstdint>
20#include <numeric>
21
22CbmPsdUnpackAlgo::CbmPsdUnpackAlgo() : CbmRecoUnpackAlgo("CbmPsdUnpackAlgo") {}
23
24// ----- Channel address
25Int_t CbmPsdUnpackAlgo::getAddress(size_t channel)
26{
27 assert(channel < fChannelAddress.size());
28 return fChannelAddress[channel];
29}
30
31
32// ----- Energy calibration
33Double_t CbmPsdUnpackAlgo::getMipCalibration(uint8_t channel)
34{
35 assert(channel < fMipCalibration.size());
36 return fMipCalibration[channel];
37}
38
39
40// ---- GetParContainerRequest ----
41std::vector<std::pair<std::string, std::shared_ptr<FairParGenericSet>>>*
42 CbmPsdUnpackAlgo::GetParContainerRequest(std::string /*geoTag*/, std::uint32_t /*runId*/)
43{
44 // Basepath for default Trd parameter sets (those connected to a geoTag)
45 std::string basepath = Form("%s", fParFilesBasePath.data());
46 std::string temppath = "";
47
48 // // Get parameter container
49 temppath = basepath + "mPsdPar.par";
50 fParContVec.emplace_back(std::make_pair(temppath, std::make_shared<CbmMcbm2018PsdPar>()));
51
52 return &fParContVec;
53}
54
55// ---- init
56Bool_t CbmPsdUnpackAlgo::init() { return kTRUE; }
57
58// ---- initParSet(FairParGenericSet* parset) ----
59Bool_t CbmPsdUnpackAlgo::initParSet(FairParGenericSet* parset)
60{
61 LOG(info) << fName << "::initParSet - for container " << parset->ClassName();
62 if (parset->IsA() == CbmMcbm2018PsdPar::Class()) return initParSet(static_cast<CbmMcbm2018PsdPar*>(parset));
63
64 // If we do not know the derived ParSet class we return false
65 LOG(error)
66 << fName << "::initParSet - for container " << parset->ClassName()
67 << " failed, since CbmTrdUnpackAlgoBaseR::initParSet() does not know the derived ParSet and what to do with it!";
68 return kFALSE;
69}
70
71// ---- initParSet(CbmMcbm2018PsdPar* parset) ----
73{
74 LOG(debug) << fName << "::initParSetAsic - ";
75
77 LOG(debug) << "Data Version: " << fuRawDataVersion;
78
79 UInt_t uNrOfGdpbs = parset->GetNrOfGdpbs();
80 LOG(debug) << "Nr. of Tof GDPBs: " << uNrOfGdpbs;
81
82 UInt_t uNrOfFeePerGdpb = parset->GetNrOfFeesPerGdpb();
83 LOG(debug) << "Nr. of FEEs per Psd GDPB: " << uNrOfFeePerGdpb;
84
85 UInt_t uNrOfChannelsPerFee = parset->GetNrOfChannelsPerFee();
86 LOG(debug) << "Nr. of channels per FEE: " << uNrOfChannelsPerFee;
87
88 auto uNrOfChannelsPerGdpb = uNrOfChannelsPerFee * uNrOfFeePerGdpb;
89 LOG(debug) << "Nr. of channels per GDPB: " << uNrOfChannelsPerGdpb;
90
91 fGdpbIdIndexMap.clear();
92 for (UInt_t i = 0; i < uNrOfGdpbs; ++i) {
93 fGdpbIdIndexMap[parset->GetGdpbId(i)] = i;
94 LOG(debug) << "GDPB Id of PSD " << i << " : " << std::hex << parset->GetGdpbId(i) << std::dec;
95 } // for( UInt_t i = 0; i < fuNrOfGdpbs; ++i )
96
97 fuNrOfGbtx = parset->GetNrOfGbtx();
98 LOG(debug) << "Nr. of GBTx: " << fuNrOfGbtx;
99
100 //Temporary until creation of full psd map
101 UInt_t uNrOfModules = parset->GetNrOfModules();
102 UInt_t uNrOfSections = parset->GetNrOfSections();
103 UInt_t uNrOfChannels = uNrOfModules * uNrOfSections;
104 LOG(debug) << "Nr. of possible Psd channels: " << uNrOfChannels;
105 fviPsdChUId.resize(uNrOfChannels);
106
107 UInt_t iCh = 0;
108 for (UInt_t iModule = 0; iModule < uNrOfModules; ++iModule) {
109 for (UInt_t iSection = 0; iSection < uNrOfSections; ++iSection) {
110 iCh = iModule * uNrOfSections + iSection;
111 fviPsdChUId[iCh] = CbmPsdAddress::GetAddress(iModule, iSection);
112 }
113 }
114
115 for (size_t ichannel = 0; ichannel < fviPsdChUId.size(); ++ichannel) {
116 fMipCalibration.emplace_back(parset->GetMipCalibration(ichannel));
117 }
118 return kTRUE;
119}
120
121
122// ---- makeDigi
124{
125 std::unique_ptr<CbmPsdDigi> digi(new CbmPsdDigi(dsp.GetAddress(), dsp.GetTime(), dsp.GetEdep()));
126
127 if (digi) fOutputVec.emplace_back(*std::move(digi));
128
129 if (fOptOutAVec) {
130 fOptOutAVec->emplace_back(dsp);
131 }
132}
133
134
135// ---- unpack
136bool CbmPsdUnpackAlgo::unpack(const fles::Timeslice* ts, std::uint16_t icomp, UInt_t imslice)
137{
138 auto msDescriptor = ts->descriptor(icomp, imslice);
139 auto eqid = msDescriptor.eq_id;
140
141 const uint8_t* msContent = reinterpret_cast<const uint8_t*>(ts->content(icomp, imslice));
142
143 uint32_t uSize = msDescriptor.size;
144 auto mstime = msDescriptor.idx;
145
146 LOG(debug4) << "Microslice: " << mstime << " from EqId " << std::hex << eqid << std::dec << " has size: " << uSize;
147
148 if (0 == fvbMaskedComponents.size()) fvbMaskedComponents.resize(ts->num_components(), kFALSE);
149
150 auto dpbid = static_cast<uint16_t>(eqid & 0xFFFF);
151
153 auto it = fGdpbIdIndexMap.find(dpbid);
154 if (it == fGdpbIdIndexMap.end()) {
155 if (kFALSE == fvbMaskedComponents[icomp]) {
156 LOG(info) << "---------------------------------------------------------------";
157 LOG(warning) << "Could not find the gDPB index for AFCK id 0x" << std::hex << dpbid << std::dec
158 << " in timeslice " << ts->index() << " in microslice " << imslice << " component " << icomp << "\n"
159 << "If valid this index has to be added in the PSD "
160 "parameter file in the DbpIdArray field";
161 fvbMaskedComponents[icomp] = kTRUE;
162 } // if( kFALSE == fvbMaskedComponents[ uMsComp ] )
163 else
164 return kTRUE;
165
168
169 return kFALSE;
170
171 } // if( it == fGdpbIdIndexMap.end() )
172
173
174 // assert(dpbid == 0); // mCBM201: only one GPDB
175
176 // If not integer number of message in input buffer, print warning/error
177 if (0 != (uSize % kuBytesPerMessage))
178 LOG(error) << "The input microslice buffer does NOT "
179 << "contain only complete nDPB messages!";
180
182
183 Double_t dMsRelativeTime = mstime - fTsStartTime;
184
185 // Compute the number of complete messages in the input microslice buffer
186 uint32_t uNbMessages = (uSize - (uSize % kuBytesPerMessage)) / kuBytesPerMessage;
187
188 // Prepare variables for the loop on contents
189 const uint64_t* pInBuff = reinterpret_cast<const uint64_t*>(msContent);
190
191 // every 80bit gbt word is decomposed into two 64bit words
192 if (!(uNbMessages > 1)) return kTRUE;
193
194 PsdDataV100::PsdGbtReader PsdReader(pInBuff);
195 if (fair::Logger::Logging(fair::Severity::debug)) PsdReader.SetPrintOutMode(true);
196
197 while (PsdReader.GetTotalGbtWordsRead() < uNbMessages) {
198 int ReadResult = PsdReader.ReadMs();
199 if (fair::Logger::Logging(fair::Severity::debug)) {
200 // Cast requires to silence a warning on macos, there a uint64_t is a long long unsigned
201 printf("\nMicroslice idx: %lu\n", static_cast<size_t>(mstime));
202 PsdReader.PrintOut(); /*PsdReader.PrintSaveBuff();*/
203 }
204 if (ReadResult == 0) {
205
206 double prev_hit_time =
207 dMsRelativeTime + (double) PsdReader.VectPackHdr.at(0).uAdcTime * 12.5 - fdTimeOffsetNs; //in ns
208
209 //hit loop
210 for (uint64_t hit_iter = 0; hit_iter < PsdReader.VectHitHdr.size(); hit_iter++) {
211 if (PsdReader.VectPackHdr.size() != PsdReader.VectHitHdr.size()) {
212 LOG(error) << "Different vector headers sizes!"
213 << " in VectPackHdr " << PsdReader.VectPackHdr.size() << " in VectHitHdr "
214 << PsdReader.VectHitHdr.size() << "\n";
215 break;
216 }
217
218 uint8_t uHitChannel = PsdReader.VectHitHdr.at(hit_iter).uHitChannel;
219 if (uHitChannel >= fviPsdChUId.size()) {
220 LOG(error) << "hit channel number out of range! channel index: " << uHitChannel
221 << " max: " << fviPsdChUId.size();
222 break;
223 }
224 UInt_t uChanUId = fviPsdChUId[uHitChannel]; //unique ID
225
226 auto dTime = dMsRelativeTime + (double) PsdReader.VectPackHdr.at(hit_iter).uAdcTime * 12.5 - fdTimeOffsetNs;
227
228
229 Double_t dEdep = (double) PsdReader.VectHitHdr.at(hit_iter).uSignalCharge / getMipCalibration(uHitChannel);
231
232 UInt_t uZL = PsdReader.VectHitHdr.at(hit_iter).uZeroLevel;
233 Double_t dAccum = (double) PsdReader.VectHitHdr.at(hit_iter).uFeeAccum;
234 Double_t dAdcTime = (double) PsdReader.VectPackHdr.at(hit_iter).uAdcTime;
235
236 Double_t dEdepWfm = 0.;
237 Double_t dAmpl = 0.;
238 UInt_t uMinimum = 0;
239 UInt_t uTimeMax = 0;
240 std::vector<uint16_t> uWfm = PsdReader.VectHitData.at(hit_iter).uWfm;
241
242 Double_t dFitAmpl = 0.;
243 Double_t dFitZL = 0.;
244 Double_t dFitEdep = 0.;
245 Double_t dFitR2 = 999.;
246 Double_t dFitTimeMax = -1.;
247 std::vector<uint16_t> uFitWfm;
248
249 if (!uWfm.empty()) {
250
251 int32_t iHitChargeWfm = std::accumulate(uWfm.begin(), uWfm.end(), -uZL * uWfm.size());
252 auto const max_iter = std::max_element(uWfm.begin(), uWfm.end());
253 assert(max_iter != uWfm.end());
254 if (max_iter == uWfm.end()) break;
255 uint8_t uHitTimeMax = std::distance(uWfm.begin(), max_iter);
256 int32_t iHitAmlpitude = *max_iter - uZL;
257 auto const min_iter = std::min_element(uWfm.begin(), uWfm.end());
258 uint32_t uHitMinimum = *min_iter;
259
260 dEdepWfm = (double) iHitChargeWfm / getMipCalibration(uHitChannel); // ->now in MeV
261 dAmpl = (double) iHitAmlpitude / 16.5; // -> now in mV
262 uTimeMax = uHitTimeMax;
263 uMinimum = uHitMinimum;
264
265 int gate_beg = 0;
266 int gate_end = (int) uWfm.size() - 1;
267 PsdSignalFitting::PronyFitter Pfitter(2, 2, gate_beg, gate_end);
268 Pfitter.SetDebugMode(0);
269 Pfitter.SetWaveform(uWfm, uZL);
270 int SignalBeg = 4;
271 //0.6, 0.2 // 0.72 0.38
272 std::complex<float> first_fit_harmonic = {0.72, 0.0};
273 std::complex<float> second_fit_harmonic = {0.38, -0.0};
274 Pfitter.SetExternalHarmonics(first_fit_harmonic, second_fit_harmonic);
275 Int_t best_signal_begin = Pfitter.ChooseBestSignalBegin(SignalBeg - 1, SignalBeg + 1);
276 Pfitter.SetSignalBegin(best_signal_begin);
277 Pfitter.CalculateFitAmplitudes();
278
279 dFitEdep = Pfitter.GetIntegral(gate_beg, gate_end) / getMipCalibration(uHitChannel); // ->now in MeV
280 dFitAmpl = (Pfitter.GetMaxAmplitude() - Pfitter.GetZeroLevel()) / 16.5; // ->now in mV
281 dFitR2 = Pfitter.GetRSquare(gate_beg, gate_end);
282 dFitZL = Pfitter.GetZeroLevel();
283 dFitTimeMax = Pfitter.GetSignalMaxTime();
284 uFitWfm = Pfitter.GetFitWfm();
285 }
286
287 CbmPsdDsp dsp = CbmPsdDsp(uChanUId, dTime, fTsStartTime, dEdep, uZL, dAccum, dAdcTime,
288
289 dEdepWfm, dAmpl, uMinimum, uTimeMax, uWfm,
290
291 dFitAmpl, dFitZL, dFitEdep, dFitR2, dFitTimeMax, uFitWfm);
292
293 // Create the actual digi and move it to the output vector
294 makeDigi(dsp);
295
296 if (dTime < prev_hit_time) printf("negative time btw hits! %f after %f \n", dTime, prev_hit_time);
297
298 prev_hit_time = dTime;
299
300 } // for (uint64_t hit_iter = 0; hit_iter < PsdReader.VectHitHdr.size(); hit_iter++) {
301 }
302 else if (ReadResult == 1) {
303 LOG(error) << "no pack headers in message!";
304 }
305 else if (ReadResult == 2) {
306 LOG(error) << "wrong channel! In header: " << PsdReader.HitHdr.uHitChannel;
307 }
308 else if (ReadResult == 3) {
309 LOG(error) << "check number of waveform points! In header: " << PsdReader.HitHdr.uWfmWords - 1;
310 }
311 else {
312 LOG(error) << "PsdGbtReader.ReadEventFles() didn't return expected values";
313 }
314
315
316 } // while(PsdReader.GetTotalGbtWordsRead()<uNbMessages)
317
318 if (uNbMessages != PsdReader.GetTotalGbtWordsRead())
319 LOG(error) << "Wrong amount of messages read!"
320 << " in microslice " << uNbMessages << " by PsdReader " << PsdReader.GetTotalGbtWordsRead() << "\n";
321
322 return kTRUE;
323}
324
326
327
ClassImp(CbmConverterManager)
Baseclass for the TrdR unpacker algorithms.
Int_t GetGdpbId(Int_t i)
Double_t GetMipCalibration(UInt_t i)
static uint32_t GetAddress(int32_t moduleId, int32_t sectionId)
Return address from system ID, module, Section.
Data class for PSD digital information.
Definition CbmPsdDigi.h:36
Data class for PSD digital signal processing (DSP)
Definition CbmPsdDsp.h:30
double GetTime() const
Time.
Definition CbmPsdDsp.h:81
uint32_t GetAddress() const
Address.
Definition CbmPsdDsp.h:75
double GetEdep() const
Energy deposit.
Definition CbmPsdDsp.h:93
virtual std::vector< std::pair< std::string, std::shared_ptr< FairParGenericSet > > > * GetParContainerRequest(std::string geoTag, std::uint32_t runId)
Get the requested parameter containers. To be defined in the derived classes! Return the required par...
Bool_t initParSet(FairParGenericSet *parset)
Handles the distribution of the hidden derived classes to their explicit functions.
std::map< UInt_t, UInt_t > fGdpbIdIndexMap
std::vector< double > fMipCalibration
bool unpack(const fles::Timeslice *ts, std::uint16_t icomp, UInt_t imslice)
Unpack a given microslice. To be implemented in the derived unpacker algos.
virtual Bool_t init()
Intialisation at begin of run. Special inits of the derived algos.
CbmPsdUnpackAlgo()
Create the Cbm Trd Unpack AlgoBase object.
double getMipCalibration(uint8_t channel)
Energy calibration constants.
virtual ~CbmPsdUnpackAlgo()
Destroy the Cbm Trd Unpack Task object.
void makeDigi(CbmPsdDsp dsp)
Create a digi object from the signal.
UInt_t fuNrOfGbtx
Detector Mapping.
std::vector< Bool_t > fvbMaskedComponents
gDPB ID to index map
std::vector< Int_t > fviPsdChUId
Int_t getAddress(size_t channel)
Get channel address.
std::vector< Int_t > fChannelAddress
Double_t fdTimeOffsetNs
User settings: Data correction parameters.
static const UInt_t kuBytesPerMessage
std::vector< struct PsdPackHeader > VectPackHdr
std::vector< struct PsdHitData > VectHitData
std::vector< struct PsdHitHeader > VectHitHdr
void SetSignalBegin(int SignalBeg)
void SetExternalHarmonics(std::complex< float > z1, std::complex< float > z2)
std::vector< uint16_t > GetFitWfm()
Definition PronyFitter.h:74
float GetRSquare(int gate_beg, int gate_end)
void SetDebugMode(bool IsDebug)
Definition PronyFitter.h:50
void SetWaveform(std::vector< uint16_t > &uWfm, uint16_t uZeroLevel)
int ChooseBestSignalBegin(int first_sample, int last_sample)
float GetIntegral(int gate_beg, int gate_end)