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.
uint32_t op
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:58
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)
GLuint entry
Definition glcorearb.h:5735
GLenum const GLfloat * params
Definition glcorearb.h:272
GLuint id
Definition glcorearb.h:650
uint8_t itsSharedClusterMap uint8_t
o2::fit::Triggers Triggers
Definition Digit.h:35
struct o2::upgrades_utils::@477 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()))