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_TRD_CTFCODER_H
17#define O2_TRD_CTFCODER_H
18
19#include <algorithm>
20#include <iterator>
21#include <string>
22#include <array>
23#include "DataFormatsTRD/CTF.h"
28
29class TTree;
30
31namespace o2
32{
33namespace trd
34{
35
37{
38 public:
39 CTFCoder(o2::ctf::CTFCoderBase::OpType op) : o2::ctf::CTFCoderBase(op, CTF::getNBlocks(), o2::detectors::DetID::TRD) {}
40 ~CTFCoder() final = default;
41
43 template <typename VEC>
44 o2::ctf::CTFIOSize encode(VEC& buff, const gsl::span<const TriggerRecord>& trigData, const gsl::span<const Tracklet64>& trkData, const gsl::span<const Digit>& digData);
45
47 template <typename VTRG, typename VTRK, typename VDIG>
48 o2::ctf::CTFIOSize decode(const CTF::base& ec, VTRG& trigVec, VTRK& trkVec, VDIG& digVec);
49
50 void createCoders(const std::vector<char>& bufVec, o2::ctf::CTFCoderBase::OpType op) final;
51
52 void setCheckBogusTrig(int v) { mCheckBogusTrig = v; }
53
54 private:
55 template <typename VEC>
56 o2::ctf::CTFIOSize encode_impl(VEC& buff, const gsl::span<const TriggerRecord>& trigData, const gsl::span<const Tracklet64>& trkData, const gsl::span<const Digit>& digData);
57
58 void appendToTree(TTree& tree, CTF& ec);
59 void readFromTree(TTree& tree, int entry, std::vector<TriggerRecord>& trigVec, std::vector<Tracklet64>& trkVec, std::vector<Digit>& digVec);
60 int mCheckBogusTrig = 1;
61 // containers for locally filtered data
62 std::vector<TriggerRecord> mTrgRecFilt;
63 std::vector<Tracklet64> mTrkDataFilt;
64 std::vector<Digit> mDigDataFilt;
65};
66
68template <typename VEC>
69o2::ctf::CTFIOSize CTFCoder::encode(VEC& buff, const gsl::span<const TriggerRecord>& trigData, const gsl::span<const Tracklet64>& trkData, const gsl::span<const Digit>& digData)
70{
71 static size_t bogusWarnMsg = 0;
72 if (mCheckBogusTrig && bogusWarnMsg < mCheckBogusTrig) {
73 uint32_t orbitPrev = mFirstTFOrbit;
74 uint16_t bcPrev = 0;
75 int cnt = 0;
76 for (const auto& trig : trigData) {
77 LOGP(debug, "Trig#{} Old: {}/{} New: {}/{}", cnt++, bcPrev, orbitPrev, trig.getBCData().bc, trig.getBCData().orbit);
78 auto orbitPrevT = orbitPrev;
79 auto bcPrevT = bcPrev;
80 bcPrev = trig.getBCData().bc;
81 orbitPrev = trig.getBCData().orbit;
82 if (trig.getBCData().orbit < orbitPrevT || trig.getBCData().bc >= o2::constants::lhc::LHCMaxBunches || (trig.getBCData().orbit == orbitPrevT && trig.getBCData().bc < bcPrevT)) {
83 LOGP(warning, "Bogus TRD trigger at bc:{}/orbit:{} (previous was {}/{}), with {} tracklets and {} digits",
84 trig.getBCData().bc, trig.getBCData().orbit, bcPrevT, orbitPrevT, trig.getNumberOfTracklets(), trig.getNumberOfDigits());
85 if (++bogusWarnMsg >= mCheckBogusTrig) {
86 LOGP(warning, "Max amount of warnings ({}) was issued, will not warn anymore", size_t(mCheckBogusTrig));
87 break;
88 }
89 }
90 }
91 }
92
93 if (mIRFrameSelector.isSet()) { // preselect data
94 mTrgRecFilt.clear();
95 mTrkDataFilt.clear();
96 mDigDataFilt.clear();
97 for (const auto& trig : trigData) {
98 if (mIRFrameSelector.check(trig.getBCData()) >= 0) {
99 mTrgRecFilt.push_back(trig);
100 auto trkIt = trkData.begin() + trig.getFirstTracklet();
101 auto digIt = digData.begin() + trig.getFirstDigit();
102 auto& trigC = mTrgRecFilt.back();
103 trigC.setFirstTracklet((int)mTrkDataFilt.size());
104 trigC.setFirstDigit((int)mDigDataFilt.size());
105 std::copy(trkIt, trkIt + trig.getNumberOfTracklets(), std::back_inserter(mTrkDataFilt));
106 std::copy(digIt, digIt + trig.getNumberOfDigits(), std::back_inserter(mDigDataFilt));
107 }
108 }
109 return encode_impl(buff, mTrgRecFilt, mTrkDataFilt, mDigDataFilt);
110 }
111 return encode_impl(buff, trigData, trkData, digData);
112}
113
114template <typename VEC>
115o2::ctf::CTFIOSize CTFCoder::encode_impl(VEC& buff, const gsl::span<const TriggerRecord>& trigData, const gsl::span<const Tracklet64>& trkData, const gsl::span<const Digit>& digData)
116{
118 // what to do which each field: see o2::ctd::Metadata explanation
119 constexpr MD optField[CTF::getNBlocks()] = {
120 MD::EENCODE_OR_PACK, // BLC_bcIncTrig
121 MD::EENCODE_OR_PACK, // BLC_orbitIncTrig
122 MD::EENCODE_OR_PACK, // BLC_entriesTrk
123 MD::EENCODE_OR_PACK, // BLC_entriesDig
124 MD::EENCODE_OR_PACK, // BLC_HCIDTrk
125 MD::EENCODE_OR_PACK, // BLC_padrowTrk
126 MD::EENCODE_OR_PACK, // BLC_colTrk
127 MD::EENCODE_OR_PACK, // BLC_posTrk
128 MD::EENCODE_OR_PACK, // BLC_slopeTrk
129 MD::EENCODE_OR_PACK, // BLC_pidTrk
130 MD::EENCODE_OR_PACK, // BLC_CIDDig
131 MD::EENCODE_OR_PACK, // BLC_ROBDig
132 MD::EENCODE_OR_PACK, // BLC_MCMDig
133 MD::EENCODE_OR_PACK, // BLC_chanDig
134 MD::EENCODE_OR_PACK, // BLC_ADCDig
135 };
136
137 CTFHelper helper(trigData, trkData, digData);
138 // book output size with some margin
139 auto szIni = sizeof(CTFHeader) + helper.getSize() * 2. / 3; // will be autoexpanded if needed
140 buff.resize(szIni);
141
142 auto ec = CTF::create(buff);
143 using ECB = CTF::base;
144
145 ec->setHeader(helper.createHeader());
146 assignDictVersion(static_cast<o2::ctf::CTFDictHeader&>(ec->getHeader()));
147 ec->setANSHeader(mANSVersion);
148 // at every encoding the buffer might be autoexpanded, so we don't work with fixed pointer ec
149 o2::ctf::CTFIOSize iosize;
150#define ENCODETRD(beg, end, slot, bits) CTF::get(buff.data())->encode(beg, end, int(slot), bits, optField[int(slot)], &buff, mCoders[int(slot)], getMemMarginFactor());
151 // clang-format off
152 iosize += ENCODETRD(helper.begin_bcIncTrig(), helper.end_bcIncTrig(), CTF::BLC_bcIncTrig, 0);
153 iosize += ENCODETRD(helper.begin_orbitIncTrig(), helper.end_orbitIncTrig(), CTF::BLC_orbitIncTrig, 0);
154 iosize += ENCODETRD(helper.begin_entriesTrk(), helper.end_entriesTrk(), CTF::BLC_entriesTrk, 0);
155 iosize += ENCODETRD(helper.begin_entriesDig(), helper.end_entriesDig(), CTF::BLC_entriesDig, 0);
156
157 iosize += ENCODETRD(helper.begin_HCIDTrk(), helper.end_HCIDTrk(), CTF::BLC_HCIDTrk, 0);
158 iosize += ENCODETRD(helper.begin_padrowTrk(), helper.end_padrowTrk(), CTF::BLC_padrowTrk, 0);
159 iosize += ENCODETRD(helper.begin_colTrk(), helper.end_colTrk(), CTF::BLC_colTrk, 0);
160 iosize += ENCODETRD(helper.begin_posTrk(), helper.end_posTrk(), CTF::BLC_posTrk, 0);
161 iosize += ENCODETRD(helper.begin_slopeTrk(), helper.end_slopeTrk(), CTF::BLC_slopeTrk, 0);
162 iosize += ENCODETRD(helper.begin_pidTrk(), helper.end_pidTrk(), CTF::BLC_pidTrk, 0);
163
164 iosize += ENCODETRD(helper.begin_CIDDig(), helper.end_CIDDig(), CTF::BLC_CIDDig, 0);
165 iosize += ENCODETRD(helper.begin_ROBDig(), helper.end_ROBDig(), CTF::BLC_ROBDig, 0);
166 iosize += ENCODETRD(helper.begin_MCMDig(), helper.end_MCMDig(), CTF::BLC_MCMDig, 0);
167 iosize += ENCODETRD(helper.begin_chanDig(), helper.end_chanDig(), CTF::BLC_chanDig, 0);
168 iosize += ENCODETRD(helper.begin_ADCDig(), helper.end_ADCDig(), CTF::BLC_ADCDig, 0);
169
170 // clang-format on
171 CTF::get(buff.data())->print(getPrefix(), mVerbosity);
172 finaliseCTFOutput<CTF>(buff);
173 iosize.rawIn = trigData.size() * sizeof(TriggerRecord) + sizeof(Tracklet64) * trkData.size() + sizeof(Digit) * digData.size();
174 return iosize;
175}
176
178template <typename VTRG, typename VTRK, typename VDIG>
179o2::ctf::CTFIOSize CTFCoder::decode(const CTF::base& ec, VTRG& trigVec, VTRK& trkVec, VDIG& digVec)
180{
181 auto header = ec.getHeader();
182 checkDictVersion(static_cast<const o2::ctf::CTFDictHeader&>(header));
184 std::vector<uint16_t> HCIDTrk, posTrk, CIDDig, ADCDig;
185 std::vector<int16_t> bcInc; // RS to not crash at negative increments
186 std::vector<uint32_t> entriesTrk, entriesDig, pidTrk;
187 std::vector<int32_t> orbitInc; // RS to not crash at negative increments
188 std::vector<uint8_t> padrowTrk, colTrk, slopeTrk, ROBDig, MCMDig, chanDig;
189
190 o2::ctf::CTFIOSize iosize;
191#define DECODETRD(part, slot) ec.decode(part, int(slot), mCoders[int(slot)])
192 // clang-format off
193 iosize += DECODETRD(bcInc, CTF::BLC_bcIncTrig);
194 iosize += DECODETRD(orbitInc, CTF::BLC_orbitIncTrig);
195 iosize += DECODETRD(entriesTrk, CTF::BLC_entriesTrk);
196 iosize += DECODETRD(entriesDig, CTF::BLC_entriesDig);
197
198 iosize += DECODETRD(HCIDTrk, CTF::BLC_HCIDTrk);
199 iosize += DECODETRD(padrowTrk, CTF::BLC_padrowTrk);
200 iosize += DECODETRD(colTrk, CTF::BLC_colTrk);
201 iosize += DECODETRD(posTrk, CTF::BLC_posTrk);
202 iosize += DECODETRD(slopeTrk, CTF::BLC_slopeTrk);
203 iosize += DECODETRD(pidTrk, CTF::BLC_pidTrk);
204
205 iosize += DECODETRD(CIDDig, CTF::BLC_CIDDig);
206 iosize += DECODETRD(ROBDig, CTF::BLC_ROBDig);
207 iosize += DECODETRD(MCMDig, CTF::BLC_MCMDig);
208 iosize += DECODETRD(chanDig, CTF::BLC_chanDig);
209 iosize += DECODETRD(ADCDig, CTF::BLC_ADCDig);
210 // clang-format on
211 //
212 trigVec.clear();
213 trkVec.clear();
214 digVec.clear();
215 trigVec.reserve(header.nTriggers);
216 trkVec.reserve(header.nTracklets);
217 digVec.reserve(header.nDigits);
218 uint32_t trkCount = 0, digCount = 0, adcCount = 0;
219 uint32_t orbit = header.firstOrbit, orbitPrev = 0, orbitPrevGood = mFirstTFOrbit;
220 uint16_t bc = header.firstBC;
221 bool checkIROK = (mBCShift == 0); // need to check if CTP offset correction does not make the local time negative ?
222 static size_t countDiscardMsg = 0;
223
224 for (uint32_t itrig = 0; itrig < header.nTriggers; itrig++) {
225 // restore TrigRecord
226 if (orbitInc[itrig]) { // non-0 increment => new orbit
227 bc = bcInc[itrig]; // bcInc has absolute meaning
228 orbit += orbitInc[itrig];
229 } else {
230 bc += bcInc[itrig];
231 }
232 bool triggerOK = true;
233 if (mCheckBogusTrig && (bc >= o2::constants::lhc::LHCMaxBunches || orbitInc[itrig] < 0 || bcInc[itrig] < 0 || orbit < orbitPrevGood || (entriesTrk[itrig] == 0 && entriesDig[itrig] == 0))) {
234 if (countDiscardMsg < size_t(mCheckBogusTrig) || mCheckBogusTrig < 0) {
235 LOGP(warning, "Bogus TRD trigger at bc:{}/orbit:{} (increments: {}/{}, 1st TF orbit: {}) with {} tracklets and {} digits{}: {}",
236 bc, orbit, bcInc[itrig], orbitInc[itrig], mFirstTFOrbit, entriesTrk[itrig], entriesDig[itrig],
237 orbitInc[itrig] < 0 ? " (decreasing orbit!) " : "",
238 mCheckBogusTrig > 0 ? "discarding" : "discarding disabled");
239 if (++countDiscardMsg == size_t(mCheckBogusTrig) && mCheckBogusTrig > 0) {
240 LOGP(warning, "Max amount of warnings ({}) was issued, will not warn anymore", size_t(mCheckBogusTrig));
241 }
242 }
243 if (mCheckBogusTrig > 0) {
244 triggerOK = false;
245 }
246 }
247 orbitPrev = orbit;
249 if (triggerOK && (checkIROK || canApplyBCShift(ir))) { // correction will be ok
250 checkIROK = true; // don't check anymore since the following checks will yield same
251 orbitPrevGood = orbit;
252 uint32_t firstEntryTrk = trkVec.size();
253 uint16_t hcid = 0;
254 for (uint32_t it = 0; it < entriesTrk[itrig]; it++) {
255 hcid += HCIDTrk[trkCount]; // 1st tracklet of trigger was encoded with abs HCID, then increments
256 trkVec.emplace_back(header.format, hcid, padrowTrk[trkCount], colTrk[trkCount], posTrk[trkCount], slopeTrk[trkCount], pidTrk[trkCount]);
257 trkCount++;
258 }
259 uint32_t firstEntryDig = digVec.size();
260 int16_t cid = 0;
261 for (uint32_t id = 0; id < entriesDig[itrig]; id++) {
262 cid += CIDDig[digCount]; // 1st digit of trigger was encoded with abs CID, then increments
263 auto& dig = digVec.emplace_back(cid, ROBDig[digCount], MCMDig[digCount], chanDig[digCount]);
264 dig.setADC({&ADCDig[adcCount], constants::TIMEBINS});
265 digCount++;
266 adcCount += constants::TIMEBINS;
267 }
268 if (mBCShift && bc < o2::constants::lhc::LHCMaxBunches) { // we don't want corrupted orbit to look as good one after correction
269 ir -= mBCShift;
270 }
271
272 LOGP(debug, "Storing TRD trigger at {} (increments: {}/{}) with {} tracklets and {} digits", ir.asString(), bcInc[itrig], orbitInc[itrig], entriesTrk[itrig], entriesDig[itrig]);
273 trigVec.emplace_back(ir, firstEntryDig, entriesDig[itrig], firstEntryTrk, entriesTrk[itrig]);
274 } else { // skip the trigger with negative local time
275 trkCount += entriesTrk[itrig];
276 digCount += entriesDig[itrig];
277 adcCount += constants::TIMEBINS * entriesDig[itrig];
278 continue;
279 }
280 }
281 assert(digCount == header.nDigits && trkCount == header.nTracklets && adcCount == (int)ADCDig.size());
282 iosize.rawIn = trigVec.size() * sizeof(TriggerRecord) + sizeof(Tracklet64) * trkVec.size() + sizeof(Digit) * digVec.size();
283 return iosize;
284}
285
286} // namespace trd
287} // namespace o2
288
289#endif // O2_TRD_CTFCODER_H
Declarations for CTFCoderBase class (support of external dictionaries)
uint64_t orbit
Definition RawEventData.h:6
uint64_t bc
Definition RawEventData.h:5
uint32_t op
Header to collect LHC related constants.
Definitions for TRD CTF data.
#define DECODETRD(part, slot)
#define ENCODETRD(beg, end, slot, bits)
Helper for TRD CTF creation.
std::ostringstream debug
void checkDictVersion(const CTFDictHeader &h) const
ctf::ANSHeader mANSVersion
std::string getPrefix() const
o2::utils::IRFrameSelector mIRFrameSelector
virtual void assignDictVersion(CTFDictHeader &h) const
bool canApplyBCShift(const o2::InteractionRecord &ir, long shift) const
<<======================== 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
void setCheckBogusTrig(int v)
Definition CTFCoder.h:52
o2::ctf::CTFIOSize encode(VEC &buff, const gsl::span< const TriggerRecord > &trigData, const gsl::span< const Tracklet64 > &trkData, const gsl::span< const Digit > &digData)
entropy-encode data to buffer with CTF
Definition CTFCoder.h:69
void createCoders(const std::vector< char > &bufVec, o2::ctf::CTFCoderBase::OpType op) final
Definition CTFCoder.cxx:40
CTFCoder(o2::ctf::CTFCoderBase::OpType op)
Definition CTFCoder.h:39
~CTFCoder() final=default
o2::ctf::CTFIOSize decode(const CTF::base &ec, VTRG &trigVec, VTRK &trkVec, VDIG &digVec)
entropy decode data from buffer with CTF
Definition CTFCoder.h:179
Header for data corresponding to the same hardware trigger adapted from DataFormatsITSMFT/ROFRecord.
long check(o2::dataformats::IRFrame fr, size_t bwd=0, size_t fwd=0)
GLuint entry
Definition glcorearb.h:5735
const GLdouble * v
Definition glcorearb.h:832
constexpr int LHCMaxBunches
constexpr int TIMEBINS
the number of time bins
Definition Constants.h:74
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
Defining DataPointCompositeObject explicitly as copiable.
std::string asString() const
Detector header base.
wrapper for the Entropy-encoded triggers and cells of the TF
Definition CTF.h:41
@ BLC_slopeTrk
Definition CTF.h:52
@ BLC_bcIncTrig
Definition CTF.h:44
@ BLC_entriesTrk
Definition CTF.h:46
@ BLC_chanDig
Definition CTF.h:57
@ BLC_orbitIncTrig
Definition CTF.h:45
@ BLC_entriesDig
Definition CTF.h:47
@ BLC_pidTrk
Definition CTF.h:53
@ BLC_MCMDig
Definition CTF.h:56
@ BLC_HCIDTrk
Definition CTF.h:48
@ BLC_CIDDig
Definition CTF.h:54
@ BLC_colTrk
Definition CTF.h:50
@ BLC_padrowTrk
Definition CTF.h:49
@ BLC_posTrk
Definition CTF.h:51
@ BLC_ADCDig
Definition CTF.h:58
@ BLC_ROBDig
Definition CTF.h:55
o2::InteractionRecord ir(0, 0)
std::unique_ptr< TTree > tree((TTree *) flIn.Get(std::string(o2::base::NameConf::CTFTREENAME).c_str()))