Project
Loading...
Searching...
No Matches
CTFCoder.h
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
15
16#ifndef O2_FT0_CTFCODER_H
17#define O2_FT0_CTFCODER_H
18
19#include <algorithm>
20#include <iterator>
21#include <string>
22#include "FT0Base/Geometry.h"
23#include "DataFormatsFT0/CTF.h"
27#include "FT0Base/FT0DigParam.h"
29
30class TTree;
31
32namespace o2
33{
34namespace ft0
35{
36
37class CTFCoder final : public o2::ctf::CTFCoderBase
38{
39 public:
40 CTFCoder(o2::ctf::CTFCoderBase::OpType op, const std::string& ctfdictOpt = "none") : o2::ctf::CTFCoderBase(op, CTF::getNBlocks(), o2::detectors::DetID::FT0, 1.f, ctfdictOpt) {}
41 ~CTFCoder() final = default;
42
44 template <typename VEC>
45 o2::ctf::CTFIOSize encode(VEC& buff, const gsl::span<const Digit>& digitVec, const gsl::span<const ChannelData>& channelVec);
46
48 template <typename VDIG, typename VCHAN>
49 o2::ctf::CTFIOSize decode(const CTF::base& ec, VDIG& digitVec, VCHAN& channelVec);
50
51 void createCoders(const std::vector<char>& bufVec, o2::ctf::CTFCoderBase::OpType op) final;
52
53 private:
55 template <int MAJOR_VERSION, int MINOR_VERSION>
56 void compress(CompressedDigits& cd, const gsl::span<const Digit>& digitVec, const gsl::span<const ChannelData>& channelVec);
57 size_t estimateCompressedSize(const CompressedDigits& cc);
58
60 template <int MAJOR_VERSION, int MINOR_VERSION, typename VDIG, typename VCHAN>
61 void decompress(const CompressedDigits& cd, VDIG& digitVec, VCHAN& channelVec);
62
63 void appendToTree(TTree& tree, CTF& ec);
64 void readFromTree(TTree& tree, int entry, std::vector<Digit>& digitVec, std::vector<ChannelData>& channelVec);
65 void assignDictVersion(o2::ctf::CTFDictHeader& h) const final;
66};
67
69template <typename VEC>
70o2::ctf::CTFIOSize CTFCoder::encode(VEC& buff, const gsl::span<const Digit>& digitVec, const gsl::span<const ChannelData>& channelVec)
71{
73 // what to do which each field: see o2::ctd::Metadata explanation
74 constexpr MD optField[CTF::getNBlocks()] = {
75 MD::EENCODE_OR_PACK, // BLC_trigger
76 MD::EENCODE_OR_PACK, // BLC_bcInc
77 MD::EENCODE_OR_PACK, // BLC_orbitInc
78 MD::EENCODE_OR_PACK, // BLC_nChan
79 MD::EENCODE_OR_PACK, // BLC_status
80 MD::EENCODE_OR_PACK, // BLC_idChan
81 MD::EENCODE_OR_PACK, // BLC_qtcChain
82 MD::EENCODE_OR_PACK, // BLC_cfdTime
83 MD::EENCODE_OR_PACK // BLC_qtcAmpl
84 };
88 compress<1, 0>(cd, digitVec, channelVec);
89 } else {
90 compress<1, 1>(cd, digitVec, channelVec);
91 }
92 } else {
93 compress<1, 1>(cd, digitVec, channelVec);
94 }
95 // book output size with some margin
96 auto szIni = estimateCompressedSize(cd);
97 buff.resize(szIni);
98
99 auto ec = CTF::create(buff);
100 using ECB = CTF::base;
101
102 ec->setHeader(cd.header);
103 assignDictVersion(static_cast<o2::ctf::CTFDictHeader&>(ec->getHeader()));
104 ec->setANSHeader(mANSVersion);
105 // at every encoding the buffer might be autoexpanded, so we don't work with fixed pointer ec
106 o2::ctf::CTFIOSize iosize;
107#define ENCODEFT0(part, slot, bits) CTF::get(buff.data())->encode(part, int(slot), bits, optField[int(slot)], &buff, mCoders[int(slot)], getMemMarginFactor());
108 // clang-format off
109 iosize += ENCODEFT0(cd.trigger, CTF::BLC_trigger, 0);
110 iosize += ENCODEFT0(cd.bcInc, CTF::BLC_bcInc, 0);
111 iosize += ENCODEFT0(cd.orbitInc, CTF::BLC_orbitInc, 0);
112 iosize += ENCODEFT0(cd.nChan, CTF::BLC_nChan, 0);
113 iosize += ENCODEFT0(cd.eventStatus, CTF::BLC_status, 0);
114 iosize += ENCODEFT0(cd.idChan , CTF::BLC_idChan, 0);
115 iosize += ENCODEFT0(cd.qtcChain, CTF::BLC_qtcChain, 0);
116 iosize += ENCODEFT0(cd.cfdTime, CTF::BLC_cfdTime, 0);
117 iosize += ENCODEFT0(cd.qtcAmpl, CTF::BLC_qtcAmpl, 0);
118 // clang-format on
119 CTF::get(buff.data())->print(getPrefix(), mVerbosity);
120 finaliseCTFOutput<CTF>(buff);
121 iosize.rawIn = sizeof(Digit) * digitVec.size() + sizeof(ChannelData) * channelVec.size();
122 return iosize;
123}
124
126template <typename VDIG, typename VCHAN>
127o2::ctf::CTFIOSize CTFCoder::decode(const CTF::base& ec, VDIG& digitVec, VCHAN& channelVec)
128{
130 cd.header = ec.getHeader();
131 const auto& hd = static_cast<const o2::ctf::CTFDictHeader&>(cd.header);
134 o2::ctf::CTFIOSize iosize;
135#define DECODEFT0(part, slot) ec.decode(part, int(slot), mCoders[int(slot)])
136 // clang-format off
137 iosize += DECODEFT0(cd.trigger, CTF::BLC_trigger);
138 iosize += DECODEFT0(cd.bcInc, CTF::BLC_bcInc);
139 iosize += DECODEFT0(cd.orbitInc, CTF::BLC_orbitInc);
140 iosize += DECODEFT0(cd.nChan, CTF::BLC_nChan);
142 iosize += DECODEFT0(cd.idChan, CTF::BLC_idChan);
143 iosize += DECODEFT0(cd.qtcChain, CTF::BLC_qtcChain);
144 iosize += DECODEFT0(cd.cfdTime, CTF::BLC_cfdTime);
145 iosize += DECODEFT0(cd.qtcAmpl, CTF::BLC_qtcAmpl);
146 // clang-format on
147 //
148 if (hd.minorVersion == 0 && hd.majorVersion == 1) {
149 decompress<1, 0>(cd, digitVec, channelVec);
150 } else {
151 decompress<1, 1>(cd, digitVec, channelVec);
152 }
153 iosize.rawIn = sizeof(Digit) * digitVec.size() + sizeof(ChannelData) * channelVec.size();
154 return iosize;
155}
156
158template <int MAJOR_VERSION, int MINOR_VERSION, typename VDIG, typename VCHAN>
159void CTFCoder::decompress(const CompressedDigits& cd, VDIG& digitVec, VCHAN& channelVec)
160{
161 digitVec.clear();
162 channelVec.clear();
163 digitVec.reserve(cd.header.nTriggers);
164 channelVec.reserve(cd.idChan.size());
165
166 uint32_t firstEntry = 0, clCount = 0, chipCount = 0;
168 if (mBCShift && ir.toLong() >= mBCShift) {
169 ir -= mBCShift;
170 }
171 for (uint32_t idig = 0; idig < cd.header.nTriggers; idig++) {
172 // restore ROFRecord
173 if (cd.orbitInc[idig]) { // non-0 increment => new orbit
174 ir.bc = cd.bcInc[idig]; // bcInc has absolute meaning
175 ir.orbit += cd.orbitInc[idig];
176 } else {
177 ir.bc += cd.bcInc[idig];
178 }
179 const auto& params = FT0DigParam::Instance();
180 int triggerGate = params.mTime_trg_gate;
181 firstEntry = channelVec.size();
182 uint8_t chID = 0;
183 int8_t nChanA = 0, nChanC = 0;
184 int32_t amplA = 0, amplC = 0;
185 int16_t timeA = 0, timeC = 0;
186 for (uint8_t ic = 0; ic < cd.nChan[idig]; ic++) {
187 auto icc = channelVec.size();
188 if constexpr (MINOR_VERSION == 0 && MAJOR_VERSION == 1) {
189 // Old decoding procedure, mostly for Pilot Beam in October 2021
190 chID += cd.idChan[icc];
191 } else {
192 // New decoding procedure, w/o sorted ChID requriment
193 chID = cd.idChan[icc];
194 }
195 const auto& chan = channelVec.emplace_back(chID, cd.cfdTime[icc], cd.qtcAmpl[icc], cd.qtcChain[icc]);
196 if (std::abs(chan.CFDTime) < triggerGate) {
197 if (chan.ChId < 4 * uint8_t(Geometry::NCellsA)) { // A side
198 amplA += chan.QTCAmpl;
199 timeA += chan.CFDTime;
200 nChanA++;
201 } else {
202 amplC += chan.QTCAmpl;
203 timeC += chan.CFDTime;
204 nChanC++;
205 }
206 }
207 }
208 if (nChanA) {
209 timeA /= nChanA;
210 amplA *= 0.125;
211 } else {
214 }
215 if (nChanC) {
216 timeC /= nChanC;
217 amplC *= 0.125;
218 } else {
221 }
222 Triggers trig;
223 trig.setTriggers(cd.trigger[idig], nChanA, nChanC, amplA, amplC, timeA, timeC);
224 auto& d = digitVec.emplace_back(firstEntry, cd.nChan[idig], ir, trig, idig);
225 d.setEventStatus(cd.eventStatus[idig]);
226 }
227}
228
230template <int MAJOR_VERSION, int MINOR_VERSION>
231void CTFCoder::compress(CompressedDigits& cd, const gsl::span<const Digit>& digitVec, const gsl::span<const ChannelData>& channelVec)
232{
233 // convert digits/channel to their compressed version
234 cd.clear();
235 cd.header.det = mDet;
236 if (!digitVec.size()) {
237 return;
238 }
239 uint32_t firstDig = digitVec.size(), nDigSel = digitVec.size(), nChanSel = channelVec.size();
240 std::vector<bool> reject(digitVec.size());
241 if (mIRFrameSelector.isSet()) {
242 for (size_t id = 0; id < digitVec.size(); id++) {
243 if (mIRFrameSelector.check(digitVec[id].mIntRecord) < 0) {
244 reject[id] = true;
245 nDigSel--;
246 nChanSel -= digitVec[id].ref.getEntries();
247 } else if (firstDig == digitVec.size()) {
248 firstDig = id;
249 }
250 }
251 } else {
252 firstDig = 0;
253 }
254 if (nDigSel == 0) { // nothing is selected
255 return;
256 }
257
258 const auto& dig0 = digitVec[firstDig];
259 cd.header.nTriggers = nDigSel;
260 cd.header.firstOrbit = dig0.getOrbit();
261 cd.header.firstBC = dig0.getBC();
262 cd.header.triggerGate = FT0DigParam::Instance().mTime_trg_gate;
263
264 cd.trigger.resize(cd.header.nTriggers);
265 cd.bcInc.resize(cd.header.nTriggers);
266 cd.orbitInc.resize(cd.header.nTriggers);
267 cd.eventStatus.resize(cd.header.nTriggers);
268 cd.nChan.resize(cd.header.nTriggers);
269
270 cd.idChan.resize(nChanSel);
271 cd.qtcChain.resize(nChanSel);
272 cd.cfdTime.resize(nChanSel);
273 cd.qtcAmpl.resize(nChanSel);
274
275 uint16_t prevBC = cd.header.firstBC;
276 uint32_t prevOrbit = cd.header.firstOrbit;
277 uint32_t ccount = 0, dcount = 0;
278 for (uint32_t idig = 0; idig < digitVec.size(); idig++) {
279 if (reject[idig]) {
280 continue;
281 }
282 const auto& digit = digitVec[idig];
283 const auto chanels = digit.getBunchChannelData(channelVec); // we assume the channels are sorted
284
285 // fill trigger info
286 cd.trigger[dcount] = digit.getTriggers().getTriggersignals();
287 cd.eventStatus[dcount] = digit.getEventStatusWord();
288 if (prevOrbit == digit.getOrbit()) {
289 cd.bcInc[dcount] = digit.getBC() - prevBC;
290 cd.orbitInc[dcount] = 0;
291 } else {
292 cd.bcInc[dcount] = digit.getBC();
293 cd.orbitInc[dcount] = digit.getOrbit() - prevOrbit;
294 }
295 prevBC = digit.getBC();
296 prevOrbit = digit.getOrbit();
297 // fill channels info
298 cd.nChan[dcount] = chanels.size();
299 if (!cd.nChan[dcount]) {
300 LOG(debug) << "Digits with no channels";
301 dcount++;
302 continue;
303 }
304 uint8_t prevChan = 0;
305 for (uint8_t ic = 0; ic < cd.nChan[dcount]; ic++) {
306 if constexpr (MINOR_VERSION == 0 && MAJOR_VERSION == 1) {
307 cd.idChan[ccount] = chanels[ic].ChId - prevChan; // Old method, lets keep it for a while
308 } else {
309 cd.idChan[ccount] = chanels[ic].ChId;
310 }
311 cd.qtcChain[ccount] = chanels[ic].ChainQTC;
312 cd.cfdTime[ccount] = chanels[ic].CFDTime;
313 cd.qtcAmpl[ccount] = chanels[ic].QTCAmpl;
314 prevChan = chanels[ic].ChId;
315 ccount++;
316 }
317 dcount++;
318 }
319}
320
321} // namespace ft0
322} // namespace o2
323
324#endif // O2_FT0_CTFCODER_H
Declarations for CTFCoderBase class (support of external dictionaries)
std::ostringstream debug
Definitions for FT0 CTF data.
Class to describe fired and stored channels for the BC and to refer to channel data.
#define ENCODEFT0(part, slot, bits)
#define DECODEFT0(part, slot)
uint64_t nChanC
int64_t timeC
uint64_t nChanA
int64_t amplA
int64_t timeA
int64_t amplC
Configurable digitization parameters.
unsigned short int uint16_t
unsigned int uint32_t
uint32_t op
Timeframe settings Average distance in cm of events merged into Randomize distance around average distance of merged events Simulate correct bunch interactions instead of placing only the average number of events A value[n] sets TFlen for[n] collisions in Number of bunches per trainsort Number of bunch trains Instantaneous interaction rate Do not simulate border Total number of collisions to be placed in the interior of all time Do not select random but walk over array of events in stride steps h Event generator settings h configStandalone Use CPU for GPU Force usage of the specified GPU device no CPU fallback Continue processing after an error First event to Number of events to Number of iterations to Number of iterations to Number of initial iterations excluded from const char Directory with events to Events directory is and not inside events d
configStandalone Reconstruction rec_tpc multiplier for the combined cluster track error during track following area in cm for the search of for z only used if decrease removal by when above this local occupancy rowx Shift of TPC revert cluster flag edge bit distance to edge exceeds this ZOffset for secondary multiple of radius max P of electron K BB bands crossing max P of electron p BB bands crossing max P of electron d BB bands crossing max P of electron t BB bands crossing min accepted dEdxMaxTPC of the track Additive extra cluster error for Y2 if edge flag set Additive extra cluster error for Y2 if single set Additive extra cluster error for Y2 if or single set Additive extra cluster error for Z2 if or single set Extra errors to add to track when crossing depending on addErrorsCECrossing Inner portion of y range in sector that is not used in searching for extrapolated track candidates factor2YS for track merging factor2K for track merging Margin in cm of Y position when rejecting edge clusters based on uncorrected track Y Max fraction of shared clusters for tracklet Except pad from cluster finding if total number of charges in a fragment is above this Except pad from cluster finding if number of consecutive charges in a fragment is above this Threshold where a timebin is considered disabling the noisy pad check for that pad Treat signal above this minimum as saturated Smoothing factor for the exponential Highly Ionising Particle tail filter Number of timebins to use for the averaging Add additional custom track errors when crossing relative as fraction of Do N fit passes in final fit of< 0:reject at max -n hits") AddOptionRTC(rejectIFCLowRadiusCluster, uint8_t, 1, "", 0, "Reject clusters that get the IFC mask error during refit") AddOptionRTC(dEdxTruncLow, uint8_t, 2, "", 0, "Low truncation threshold, fraction of 128") AddOptionRTC(dEdxTruncHigh, uint8_t, 77, "", 0, "High truncation threshold, fraction of 128") AddOptionRTC(extrapolationTracking, int8_t, 1, "", 0, "Enable Extrapolation Tracking(prolong tracks to adjacent sectors to find short segments)") AddOptionRTC(disableRefitAttachment, uint8_t, 0, "", 0, "Bitmask to disable certain attachment steps during refit(1:attachment, 2:propagation, 4:loop following, 8:mirroring)") AddOptionRTC(rejectionStrategy, uint8_t, o2::gpu::GPUSettings::RejectionStrategyA, "", 0, "Enable rejection of TPC clusters for compression(0=no, 1=strategy A, 2=strategy B)") AddOptionRTC(mergeLoopersAfterburner, uint8_t, 1, "", 0, "Run afterburner for additional looper merging") AddOptionRTC(compressionTypeMask, uint8_t, o2::gpu::GPUSettings::CompressionFull, "", 0, "TPC Compression mode bits(1=truncate charge/width LSB, 2=differences, 4=track-model)") AddOptionRTC(compressionSortOrder, uint8_t, o2::gpu::GPUSettings::SortTime, "", 0, "Sort order of TPC compression(0=time, 1=pad, 2=Z-time-pad, 3=Z-pad-time, 4=no sorting(use incoming order))") AddOptionRTC(sigBitsCharge, uint8_t, 4, "", 0, "Number of significant bits for TPC cluster charge in compression mode 1") AddOptionRTC(sigBitsWidth, uint8_t, 3, "", 0, "Number of significant bits for TPC cluster width in compression mode 1") AddOptionRTC(dropLoopers, uint8_t, 0, "", 0, "Drop looping tracks starting from second loop") AddOptionRTC(mergerInterpolateErrors, uint8_t, 1, "", 0, "Use interpolation instead of extrapolation for chi2 based cluster rejection") AddOptionRTC(mergerInterpolateRejectAlsoOnCurrentPosition, uint8_t, 1, "", 0, "When using mergerInterpolateErrors, reject based on chi2 twice computed with interpolated and current track position starting from NDF > mergerNonInterpolateRejectMinNDF Merge tracks accross the central electrode Enable PID response Add sub threshold clusters in TPC dEdx computation OR mask of TPC flags that will reject the cluster in alternative dEdx Reject edge clusters based on uncorrected track Y during track fit Increase decrease removal by when on this number of pads from the edge h configStandalone Reconstruction rec_trd Max chi2 for TRD tracklets to be matched to a track Chi2 cut for strict matching mode Number of sigmas for ITS TPC track time error estimate Addition to search road around track prolongation along Y in cm Optimal tracklet rphi resolution in maximum chi2 per attached tracklet for TRD tracks take into account the full likelihood of the slope including exponential tails Tracks with less attached tracklets are discarded after the tracking Post trigger Pile up integration time in BCs fits all iterations but the last one in projections Use material lookup table for TPC refit Apply workarounds to avoid cyclic merge should not be needed tpc dyn configStandalone Processing proc_rtc Replace constant variables static by constexpr expressions Compile RTC in deterministic with NO_FAST_MATH flags and GPUCA_DETERMINISTIC_MODE define Use RTC to optimize GPU code h configStandalone Processing proc_rtctech Use a file lock to serialize access to the cache folder int32_t
Class for time synchronization of RawReader instances.
void checkDictVersion(const CTFDictHeader &h) const
ctf::ANSHeader mANSVersion
CTFDictHeader mExtHeader
std::string getPrefix() const
o2::utils::IRFrameSelector mIRFrameSelector
<<======================== Auxiliary classes =======================<<
static auto get(void *head)
cast arbitrary buffer head to container class. Head is supposed to respect the alignment
const H & getHeader() const
void print(const std::string &prefix="", int verbosity=1) const
print itself
EncodedBlocks< CTFHeader, N, uint32_t > base
static auto create(void *head, size_t sz)
create container from arbitrary buffer of predefined size (in bytes!!!). Head is supposed to respect ...
Static class with identifiers, bitmasks and names for ALICE detectors.
Definition DetID.h:60
static const int16_t DEFAULT_AMP
Definition Triggers.h:51
static const int16_t DEFAULT_TIME
Definition Triggers.h:50
void setTriggers(uint8_t trgsig, uint8_t chanA, uint8_t chanC, int32_t aamplA, int32_t aamplC, int16_t atimeA, int16_t atimeC)
Definition Triggers.h:103
void createCoders(const std::vector< char > &bufVec, o2::ctf::CTFCoderBase::OpType op) final
Definition CTFCoder.cxx:52
o2::ctf::CTFIOSize encode(VEC &buff, const gsl::span< const Digit > &digitVec, const gsl::span< const ChannelData > &channelVec)
entropy-encode digits to buffer with CTF
Definition CTFCoder.h:70
o2::ctf::CTFIOSize decode(const CTF::base &ec, VDIG &digitVec, VCHAN &channelVec)
entropy decode clusters from buffer with CTF
Definition CTFCoder.h:127
CTFCoder(o2::ctf::CTFCoderBase::OpType op, const std::string &ctfdictOpt="none")
Definition CTFCoder.h:40
~CTFCoder() final=default
static constexpr int NCellsA
Definition Geometry.h:52
long check(o2::dataformats::IRFrame fr, size_t bwd=0, size_t fwd=0)
GLenum const GLfloat * params
Definition glcorearb.h:272
GLuint id
Definition glcorearb.h:650
o2::fit::Triggers Triggers
Definition Digit.h:35
struct o2::upgrades_utils::@481 ft0
structure to keep V0C information
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
uint32_t orbit
LHC orbit.
uint16_t bc
bunch crossing ID of interaction
Detector header base.
bool isValidDictTimeStamp() const
uint32_t firstOrbit
number of triggers in TF
Definition CTF.h:31
uint16_t firstBC
1st orbit of TF
Definition CTF.h:32
uint32_t nTriggers
Definition CTF.h:30
wrapper for the Entropy-encoded clusters of the TF
Definition CTF.h:63
@ BLC_status
Definition CTF.h:71
@ BLC_idChan
Definition CTF.h:72
@ BLC_qtcChain
Definition CTF.h:73
@ BLC_bcInc
Definition CTF.h:68
@ BLC_qtcAmpl
Definition CTF.h:75
@ BLC_trigger
Definition CTF.h:67
@ BLC_cfdTime
Definition CTF.h:74
@ BLC_nChan
Definition CTF.h:70
@ BLC_orbitInc
Definition CTF.h:69
Intermediate, compressed but not yet entropy-encoded digits.
Definition CTF.h:38
std::vector< uint8_t > trigger
Definition CTF.h:43
std::vector< uint8_t > idChan
Definition CTF.h:50
std::vector< uint8_t > eventStatus
Definition CTF.h:47
std::vector< int16_t > bcInc
Definition CTF.h:44
std::vector< uint8_t > nChan
Definition CTF.h:46
std::vector< int32_t > orbitInc
Definition CTF.h:45
std::vector< int32_t > qtcAmpl
Definition CTF.h:52
std::vector< int16_t > cfdTime
Definition CTF.h:51
std::vector< uint8_t > qtcChain
Definition CTF.h:53
std::vector< o2::mch::ChannelCode > cc
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
o2::InteractionRecord ir(0, 0)
std::unique_ptr< TTree > tree((TTree *) flIn.Get(std::string(o2::base::NameConf::CTFTREENAME).c_str()))