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
38{
39 public:
40 CTFCoder(o2::ctf::CTFCoderBase::OpType op) : o2::ctf::CTFCoderBase(op, CTF::getNBlocks(), o2::detectors::DetID::FT0) {}
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
169 for (uint32_t idig = 0; idig < cd.header.nTriggers; idig++) {
170 // restore ROFRecord
171 if (cd.orbitInc[idig]) { // non-0 increment => new orbit
172 ir.bc = cd.bcInc[idig]; // bcInc has absolute meaning
173 ir.orbit += cd.orbitInc[idig];
174 } else {
175 ir.bc += cd.bcInc[idig];
176 }
177 const auto& params = FT0DigParam::Instance();
178 int triggerGate = params.mTime_trg_gate;
179 firstEntry = channelVec.size();
180 uint8_t chID = 0;
181 int8_t nChanA = 0, nChanC = 0;
182 int32_t amplA = 0, amplC = 0;
183 int16_t timeA = 0, timeC = 0;
184 for (uint8_t ic = 0; ic < cd.nChan[idig]; ic++) {
185 auto icc = channelVec.size();
186 if constexpr (MINOR_VERSION == 0 && MAJOR_VERSION == 1) {
187 // Old decoding procedure, mostly for Pilot Beam in October 2021
188 chID += cd.idChan[icc];
189 } else {
190 // New decoding procedure, w/o sorted ChID requriment
191 chID = cd.idChan[icc];
192 }
193 const auto& chan = channelVec.emplace_back(chID, cd.cfdTime[icc], cd.qtcAmpl[icc], cd.qtcChain[icc]);
194 if (std::abs(chan.CFDTime) < triggerGate) {
195 if (chan.ChId < 4 * uint8_t(Geometry::NCellsA)) { // A side
196 amplA += chan.QTCAmpl;
197 timeA += chan.CFDTime;
198 nChanA++;
199 } else {
200 amplC += chan.QTCAmpl;
201 timeC += chan.CFDTime;
202 nChanC++;
203 }
204 }
205 }
206 if (nChanA) {
207 timeA /= nChanA;
208 amplA *= 0.125;
209 } else {
212 }
213 if (nChanC) {
214 timeC /= nChanC;
215 amplC *= 0.125;
216 } else {
219 }
220 Triggers trig;
221 trig.setTriggers(cd.trigger[idig], nChanA, nChanC, amplA, amplC, timeA, timeC);
222 auto& d = digitVec.emplace_back(firstEntry, cd.nChan[idig], ir, trig, idig);
223 d.setEventStatus(cd.eventStatus[idig]);
224 }
225}
226
228template <int MAJOR_VERSION, int MINOR_VERSION>
229void CTFCoder::compress(CompressedDigits& cd, const gsl::span<const Digit>& digitVec, const gsl::span<const ChannelData>& channelVec)
230{
231 // convert digits/channel to their compressed version
232 cd.clear();
233 cd.header.det = mDet;
234 if (!digitVec.size()) {
235 return;
236 }
237 uint32_t firstDig = digitVec.size(), nDigSel = digitVec.size(), nChanSel = channelVec.size();
238 std::vector<bool> reject(digitVec.size());
239 if (mIRFrameSelector.isSet()) {
240 for (size_t id = 0; id < digitVec.size(); id++) {
241 if (mIRFrameSelector.check(digitVec[id].mIntRecord) < 0) {
242 reject[id] = true;
243 nDigSel--;
244 nChanSel -= digitVec[id].ref.getEntries();
245 } else if (firstDig == digitVec.size()) {
246 firstDig = id;
247 }
248 }
249 } else {
250 firstDig = 0;
251 }
252 if (nDigSel == 0) { // nothing is selected
253 return;
254 }
255
256 const auto& dig0 = digitVec[firstDig];
257 cd.header.nTriggers = nDigSel;
258 cd.header.firstOrbit = dig0.getOrbit();
259 cd.header.firstBC = dig0.getBC();
260 cd.header.triggerGate = FT0DigParam::Instance().mTime_trg_gate;
261
262 cd.trigger.resize(cd.header.nTriggers);
263 cd.bcInc.resize(cd.header.nTriggers);
264 cd.orbitInc.resize(cd.header.nTriggers);
265 cd.eventStatus.resize(cd.header.nTriggers);
266 cd.nChan.resize(cd.header.nTriggers);
267
268 cd.idChan.resize(nChanSel);
269 cd.qtcChain.resize(nChanSel);
270 cd.cfdTime.resize(nChanSel);
271 cd.qtcAmpl.resize(nChanSel);
272
273 uint16_t prevBC = cd.header.firstBC;
274 uint32_t prevOrbit = cd.header.firstOrbit;
275 uint32_t ccount = 0, dcount = 0;
276 for (uint32_t idig = 0; idig < digitVec.size(); idig++) {
277 if (reject[idig]) {
278 continue;
279 }
280 const auto& digit = digitVec[idig];
281 const auto chanels = digit.getBunchChannelData(channelVec); // we assume the channels are sorted
282
283 // fill trigger info
284 cd.trigger[dcount] = digit.getTriggers().getTriggersignals();
285 cd.eventStatus[dcount] = digit.getEventStatusWord();
286 if (prevOrbit == digit.getOrbit()) {
287 cd.bcInc[dcount] = digit.getBC() - prevBC;
288 cd.orbitInc[dcount] = 0;
289 } else {
290 cd.bcInc[dcount] = digit.getBC();
291 cd.orbitInc[dcount] = digit.getOrbit() - prevOrbit;
292 }
293 prevBC = digit.getBC();
294 prevOrbit = digit.getOrbit();
295 // fill channels info
296 cd.nChan[dcount] = chanels.size();
297 if (!cd.nChan[dcount]) {
298 LOG(debug) << "Digits with no channels";
299 dcount++;
300 continue;
301 }
302 uint8_t prevChan = 0;
303 for (uint8_t ic = 0; ic < cd.nChan[dcount]; ic++) {
304 if constexpr (MINOR_VERSION == 0 && MAJOR_VERSION == 1) {
305 cd.idChan[ccount] = chanels[ic].ChId - prevChan; // Old method, lets keep it for a while
306 } else {
307 cd.idChan[ccount] = chanels[ic].ChId;
308 }
309 cd.qtcChain[ccount] = chanels[ic].ChainQTC;
310 cd.cfdTime[ccount] = chanels[ic].CFDTime;
311 cd.qtcAmpl[ccount] = chanels[ic].QTCAmpl;
312 prevChan = chanels[ic].ChId;
313 ccount++;
314 }
315 dcount++;
316 }
317}
318
319} // namespace ft0
320} // namespace o2
321
322#endif // O2_FT0_CTFCODER_H
Declarations for CTFCoderBase class (support of external dictionaries)
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
std::ostringstream debug
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:97
CTFCoder(o2::ctf::CTFCoderBase::OpType op)
Definition CTFCoder.h:40
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() 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::@462 ft0
structure to keep V0C information
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
Defining DataPointCompositeObject explicitly as copiable.
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()))