Project
Loading...
Searching...
No Matches
CTFCoder.cxx
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
18#include <TTree.h>
19
20using namespace o2::itsmft;
21
23// Register encoded data in the tree (Fill is not called, will be done by caller)
24void CTFCoder::appendToTree(TTree& tree, CTF& ec)
25{
27}
28
30// extract and decode data from the tree
31void CTFCoder::readFromTree(TTree& tree, int entry, std::vector<ROFRecord>& rofRecVec,
32 std::vector<CompClusterExt>& cclusVec, std::vector<unsigned char>& pattVec, const NoiseMap* noiseMap, const LookUp& clPattLookup)
33{
34 assert(entry >= 0 && entry < tree.GetEntries());
35 CTF ec;
37 decode(ec, rofRecVec, cclusVec, pattVec, noiseMap, clPattLookup);
38}
39
41void CTFCoder::compress(CompressedClusters& cc,
42 const gsl::span<const ROFRecord>& rofRecVec,
43 const gsl::span<const CompClusterExt>& cclusVec,
44 const gsl::span<const unsigned char>& pattVec,
45 const LookUp& clPattLookup, int strobeLength)
46{
47 // store in the header the orbit of 1st ROF
48 cc.clear();
49 cc.header.det = mDet;
50 if (!rofRecVec.size()) {
51 return;
52 }
53 uint32_t firstROF = rofRecVec.size(), nrofSel = rofRecVec.size(), nClusSel = cclusVec.size();
54 std::vector<bool> reject(rofRecVec.size());
55 if (mIRFrameSelector.isSet()) {
56 for (size_t ir = 0; ir < rofRecVec.size(); ir++) {
57 auto irStart = rofRecVec[ir].getBCData();
58 if (mIRFrameSelector.check({irStart, irStart + strobeLength - 1}) < 0) {
59 reject[ir] = true;
60 nrofSel--;
61 nClusSel -= rofRecVec[ir].getNEntries();
62 } else if (firstROF == rofRecVec.size()) {
63 firstROF = ir;
64 }
65 }
66 } else {
67 firstROF = 0;
68 }
69 if (nrofSel == 0) { // nothing is selected
70 return;
71 }
72 assert(nClusSel <= cclusVec.size());
73
74 const auto& rofRec0 = rofRecVec[firstROF];
75 cc.header.firstOrbit = rofRec0.getBCData().orbit;
76 cc.header.firstBC = rofRec0.getBCData().bc;
77 cc.header.nROFs = nrofSel;
78 cc.header.nClusters = nClusSel;
79
80 cc.firstChipROF.resize(nrofSel);
81 cc.bcIncROF.resize(nrofSel);
82 cc.orbitIncROF.resize(nrofSel);
83 cc.nclusROF.resize(nrofSel);
84 //
85 cc.row.resize(nClusSel);
86 cc.colInc.resize(nClusSel);
87 // cc.chipInc.resize(cc.header.nClusters); // this is the version with chipInc stored for every pixel
88 cc.chipInc.reserve(1000); // this is the version with chipInc stored once per new chip
89 cc.chipMul.reserve(1000); // this is the version with chipInc stored once per new chip
90 cc.pattID.resize(nClusSel);
91
92 bool selectPatterns = nrofSel < rofRecVec.size();
93 if (!selectPatterns) { // nothing is rejected, simply copy the patterns
94 cc.header.nPatternBytes = pattVec.size();
95 cc.pattMap.resize(pattVec.size()); // to be resized in case of selection
96 memcpy(cc.pattMap.data(), pattVec.data(), pattVec.size());
97 } else {
98 cc.pattMap.reserve(pattVec.size());
99 }
100
101 uint16_t prevBC = cc.header.firstBC;
102 uint32_t prevOrbit = cc.header.firstOrbit;
103 int irofOut = 0, iclOut = 0;
104 auto pattIt = pattVec.begin(), pattIt0 = pattVec.begin();
105 for (uint32_t irof = 0; irof < rofRecVec.size(); irof++) {
106 const auto& rofRec = rofRecVec[irof];
107 const auto& intRec = rofRec.getBCData();
108
109 if (reject[irof]) { // need to skip some patterns
110 if (selectPatterns && pattIt != pattIt0) { // copy what was already selected
111 cc.pattMap.insert(cc.pattMap.end(), pattIt0, pattIt);
112 pattIt0 = pattIt;
113 }
114 for (int icl = rofRec.getFirstEntry(); icl < rofRec.getFirstEntry() + rofRec.getNEntries(); icl++) {
115 const auto& clus = cclusVec[icl];
116 if (clus.getPatternID() == o2::itsmft::CompCluster::InvalidPatternID || clPattLookup.isGroup(clus.getPatternID())) {
118 }
119 }
120 pattIt = pattIt0;
121 continue;
122 }
123 if (intRec.orbit == prevOrbit) {
124 cc.orbitIncROF[irofOut] = 0;
125#ifdef _CHECK_INCREMENTES_
126 if (intRec.bc < prevBC) {
127 LOG(warning) << "Negative BC increment " << intRec.bc << " -> " << prevBC;
128 }
129#endif
130 cc.bcIncROF[irofOut] = int16_t(intRec.bc - prevBC); // store increment of BC if in the same orbit
131 } else {
132 cc.orbitIncROF[irofOut] = int32_t(intRec.orbit - prevOrbit);
133#ifdef _CHECK_INCREMENTES_
134 if (intRec.orbit < prevOrbit) {
135 LOG(warning) << "Negative Orbit increment " << intRec.orbit << " -> " << prevOrbit;
136 }
137#endif
138 cc.bcIncROF[irofOut] = intRec.bc; // otherwise, store absolute bc
139 prevOrbit = intRec.orbit;
140 }
141 prevBC = intRec.bc;
142 auto ncl = rofRec.getNEntries();
143 cc.nclusROF[irofOut] = ncl;
144 if (!ncl) { // no hits data for this ROF
145 cc.firstChipROF[irofOut] = 0;
146 irofOut++;
147 continue;
148 }
149 cc.firstChipROF[irofOut] = cclusVec[rofRec.getFirstEntry()].getChipID();
150 int icl = rofRec.getFirstEntry(), iclMax = icl + ncl;
151
152 uint16_t prevChip = cc.firstChipROF[irofOut], prevCol = 0;
153 if (icl != iclMax) { // there are still clusters to store
154 cc.chipMul.push_back(0);
155 cc.chipInc.push_back(0);
156 }
157 for (; icl < iclMax; icl++) { // clusters within a chip are stored in increasing column number
158 const auto& cl = cclusVec[icl];
159 cc.row[iclOut] = cl.getRow(); // row is practically random, store it as it is
160 cc.pattID[iclOut] = cl.getPatternID();
161 if (selectPatterns && (cc.pattID[iclOut] == o2::itsmft::CompCluster::InvalidPatternID || clPattLookup.isGroup(cl.getPatternID()))) {
163 }
164 if (cl.getChipID() == prevChip) { // for the same chip store column increment
165 // cc.chipInc[iclOut] = 0; // this is the version with chipInc stored for every pixel
166 cc.chipMul.back()++; // this is the version with chipInc stored once per new chip
167 cc.colInc[iclOut] = int16_t(cl.getCol()) - prevCol;
168 prevCol = cl.getCol();
169 } else { // for new chips store chipID increment and abs. column
170 // cc.chipInc[iclOut] = cl.getChipID() - prevChip; // this is the version with chipInc stored for every pixel
171 cc.chipInc.push_back(int16_t(cl.getChipID() - prevChip)); // this is the version with chipInc stored once per new chip
172#ifdef _CHECK_INCREMENTES_
173 if (cl.getChipID() < prevChip) {
174 LOG(warning) << "Negative Chip increment " << cl.getChipID() << " -> " << prevChip;
175 }
176#endif
177 cc.chipMul.push_back(1); // this is the version with chipInc stored once per new chip
178 prevCol = cc.colInc[iclOut] = cl.getCol();
179 prevChip = cl.getChipID();
180 }
181 iclOut++;
182 }
183 irofOut++;
184 }
185 if (selectPatterns && pattIt != pattIt0) { // copy leftover patterns
186 cc.pattMap.insert(cc.pattMap.end(), pattIt0, pattIt);
187 pattIt0 = pattIt;
188 }
189 cc.header.nPatternBytes = cc.pattMap.size();
190 cc.header.nChips = cc.chipMul.size();
191}
192
194void CTFCoder::createCoders(const std::vector<char>& bufVec, o2::ctf::CTFCoderBase::OpType op)
195{
196 const auto ctf = CTF::getImage(bufVec.data());
197 CompressedClusters cc; // just to get member types
198#define MAKECODER(part, slot) createCoder(op, std::get<rans::RenormedDenseHistogram<decltype(part)::value_type>>(ctf.getDictionary<decltype(part)::value_type>(slot, mANSVersion)), int(slot))
199 // clang-format off
200 MAKECODER(cc.firstChipROF, CTF::BLCfirstChipROF);
201 MAKECODER(cc.bcIncROF, CTF::BLCbcIncROF );
202 MAKECODER(cc.orbitIncROF, CTF::BLCorbitIncROF );
203 MAKECODER(cc.nclusROF, CTF::BLCnclusROF );
204 //
205 MAKECODER(cc.chipInc, CTF::BLCchipInc );
206 MAKECODER(cc.chipMul, CTF::BLCchipMul );
207 MAKECODER(cc.row, CTF::BLCrow );
208 MAKECODER(cc.colInc, CTF::BLCcolInc );
209 MAKECODER(cc.pattID, CTF::BLCpattID );
210 MAKECODER(cc.pattMap, CTF::BLCpattMap );
211 // clang-format on
212}
213
215size_t CTFCoder::estimateCompressedSize(const CompressedClusters& cc)
216{
217 size_t sz = 0;
218 // RS FIXME this is very crude estimate, instead, an empirical values should be used
219
220 sz += estimateBufferSize(static_cast<int>(CTF::BLCfirstChipROF), cc.firstChipROF);
221 sz += estimateBufferSize(static_cast<int>(CTF::BLCbcIncROF), cc.bcIncROF);
222 sz += estimateBufferSize(static_cast<int>(CTF::BLCorbitIncROF), cc.orbitIncROF);
223 sz += estimateBufferSize(static_cast<int>(CTF::BLCnclusROF), cc.nclusROF);
224 //
225 sz += estimateBufferSize(static_cast<int>(CTF::BLCchipInc), cc.chipInc);
226 sz += estimateBufferSize(static_cast<int>(CTF::BLCchipMul), cc.chipMul);
227 sz += estimateBufferSize(static_cast<int>(CTF::BLCrow), cc.row);
228 sz += estimateBufferSize(static_cast<int>(CTF::BLCcolInc), cc.colInc);
229 sz += estimateBufferSize(static_cast<int>(CTF::BLCpattID), cc.pattID);
230 sz += estimateBufferSize(static_cast<int>(CTF::BLCpattMap), cc.pattMap);
231 sz *= 2. / 3; // if needed, will be autoexpanded
232 LOG(debug) << "Estimated output size is " << sz << " bytes";
233 return sz;
234}
235
237CompressedClusters CTFCoder::decodeCompressedClusters(const CTF::base& ec, o2::ctf::CTFIOSize& iosize)
238{
240 cc.header = ec.getHeader();
241 checkDictVersion(static_cast<const o2::ctf::CTFDictHeader&>(cc.header));
243#define DECODEITSMFT(part, slot) ec.decode(part, int(slot), mCoders[int(slot)])
244 // clang-format off
245 iosize += DECODEITSMFT(cc.firstChipROF, CTF::BLCfirstChipROF);
246 iosize += DECODEITSMFT(cc.bcIncROF, CTF::BLCbcIncROF);
247 iosize += DECODEITSMFT(cc.orbitIncROF, CTF::BLCorbitIncROF);
248 iosize += DECODEITSMFT(cc.nclusROF, CTF::BLCnclusROF);
249 //
250 iosize += DECODEITSMFT(cc.chipInc, CTF::BLCchipInc);
251 iosize += DECODEITSMFT(cc.chipMul, CTF::BLCchipMul);
252 iosize += DECODEITSMFT(cc.row, CTF::BLCrow);
253 iosize += DECODEITSMFT(cc.colInc, CTF::BLCcolInc);
254 iosize += DECODEITSMFT(cc.pattID, CTF::BLCpattID);
255 iosize += DECODEITSMFT(cc.pattMap, CTF::BLCpattMap);
256 // clang-format on
257 return cc;
258}
#define MAKECODER(part, slot)
uint32_t op
class for entropy encoding/decoding of ITS/MFT compressed clusters data
#define DECODEITSMFT(part, slot)
std::ostringstream debug
void checkDictVersion(const CTFDictHeader &h) const
std::string getPrefix() const
size_t estimateBufferSize(size_t slot, source_IT samplesBegin, source_IT samplesEnd)
o2::utils::IRFrameSelector mIRFrameSelector
<<======================== Auxiliary classes =======================<<
void readFromTree(TTree &tree, const std::string &name, int ev=0)
read from tree to non-flat object
const H & getHeader() const
void print(const std::string &prefix="", int verbosity=1) const
print itself
static auto getImage(const void *newHead)
get const image of the container wrapper, with pointers in the image relocated to new head
size_t appendToTree(TTree &tree, const std::string &name) const
attach to tree
static constexpr const char * getName(ID id)
names of defined detectors
Definition DetID.h:145
void createCoders(const std::vector< char > &bufVec, o2::ctf::CTFCoderBase::OpType op) final
Definition CTFCoder.cxx:194
o2::ctf::CTFIOSize decode(const CTF::base &ec, VROF &rofRecVec, VCLUS &cclusVec, VPAT &pattVec, const NoiseMap *noiseMap, const LookUp &clPattLookup)
entropy decode clusters from buffer with CTF
Definition CTFCoder.h:140
static void skipPattern(iterator &pattIt)
static constexpr unsigned short InvalidPatternID
Definition CompCluster.h:46
bool isGroup(int id) const
Definition LookUp.h:43
NoiseMap class for the ITS and MFT.
Definition NoiseMap.h:39
long check(o2::dataformats::IRFrame fr, size_t bwd=0, size_t fwd=0)
GLuint entry
Definition glcorearb.h:5735
Detector header base.
wrapper for the Entropy-encoded clusters of the TF
Definition CTF.h:69
@ BLCnclusROF
Definition CTF.h:75
@ BLCfirstChipROF
Definition CTF.h:72
@ BLCbcIncROF
Definition CTF.h:73
@ BLCorbitIncROF
Definition CTF.h:74
Compressed but not yet entropy-encoded clusters.
Definition CTF.h:43
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()))
LookUp clPattLookup
std::vector< unsigned char > pattVec
std::vector< CompClusterExt > cclusVec