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_CPV_CTFCODER_H
17#define O2_CPV_CTFCODER_H
18
19#include <algorithm>
20#include <iterator>
21#include <string>
22#include <array>
23#include "DataFormatsCPV/CTF.h"
27
28class TTree;
29
30namespace o2
31{
32namespace cpv
33{
34
36{
37 public:
38 CTFCoder(o2::ctf::CTFCoderBase::OpType op) : o2::ctf::CTFCoderBase(op, CTF::getNBlocks(), o2::detectors::DetID::CPV) {}
39 ~CTFCoder() final = default;
40
42 template <typename VEC>
43 o2::ctf::CTFIOSize encode(VEC& buff, const gsl::span<const TriggerRecord>& trigData, const gsl::span<const Cluster>& cluData);
44
46 template <typename VTRG, typename VCLUSTER>
47 o2::ctf::CTFIOSize decode(const CTF::base& ec, VTRG& trigVec, VCLUSTER& cluVec);
48
49 void createCoders(const std::vector<char>& bufVec, ctf::CTFCoderBase::OpType op) final;
50
51 private:
52 template <typename VEC>
53 o2::ctf::CTFIOSize encode_impl(VEC& buff, const gsl::span<const TriggerRecord>& trigData, const gsl::span<const Cluster>& cluData);
54
55 void appendToTree(TTree& tree, CTF& ec);
56 void readFromTree(TTree& tree, int entry, std::vector<TriggerRecord>& trigVec, std::vector<Cluster>& cluVec);
57 std::vector<TriggerRecord> mTrgDataFilt;
58 std::vector<Cluster> mClusDataFilt;
59};
60
62template <typename VEC>
63o2::ctf::CTFIOSize CTFCoder::encode(VEC& buff, const gsl::span<const TriggerRecord>& trigData, const gsl::span<const Cluster>& cluData)
64{
65 if (mIRFrameSelector.isSet()) { // preselect data
66 mTrgDataFilt.clear();
67 mClusDataFilt.clear();
68 for (const auto& trig : trigData) {
69 if (mIRFrameSelector.check(trig.getBCData()) >= 0) {
70 mTrgDataFilt.push_back(trig);
71 auto clusIt = cluData.begin() + trig.getFirstEntry();
72 auto& trigC = mTrgDataFilt.back();
73 trigC.setDataRange((int)mClusDataFilt.size(), trig.getNumberOfObjects());
74 std::copy(clusIt, clusIt + trig.getNumberOfObjects(), std::back_inserter(mClusDataFilt));
75 }
76 }
77 return encode_impl(buff, mTrgDataFilt, mClusDataFilt);
78 }
79 return encode_impl(buff, trigData, cluData);
80}
81
82template <typename VEC>
83o2::ctf::CTFIOSize CTFCoder::encode_impl(VEC& buff, const gsl::span<const TriggerRecord>& trigData, const gsl::span<const Cluster>& cluData)
84{
86 // what to do which each field: see o2::ctd::Metadata explanation
87 constexpr MD optField[CTF::getNBlocks()] = {
88 MD::EENCODE_OR_PACK, // BLC_bcIncTrig
89 MD::EENCODE_OR_PACK, // BLC_orbitIncTrig
90 MD::EENCODE_OR_PACK, // BLC_entriesTrig
91 MD::EENCODE_OR_PACK, // BLC_posX
92 MD::EENCODE_OR_PACK, // BLC_posZ
93 MD::EENCODE_OR_PACK, // BLC_energy
94 MD::EENCODE_OR_PACK // BLC_status
95 };
96
97 CTFHelper helper(trigData, cluData);
98
99 // book output size with some margin
100 auto szIni = sizeof(CTFHeader) + helper.getSize() * 2. / 3; // will be autoexpanded if needed
101 buff.resize(szIni);
102
103 auto ec = CTF::create(buff);
104 using ECB = CTF::base;
105
106 ec->setHeader(helper.createHeader());
107 assignDictVersion(static_cast<o2::ctf::CTFDictHeader&>(ec->getHeader()));
108 ec->setANSHeader(mANSVersion);
109 // at every encoding the buffer might be autoexpanded, so we don't work with fixed pointer ec
110 o2::ctf::CTFIOSize iosize;
111#define ENCODECPV(beg, end, slot, bits) CTF::get(buff.data())->encode(beg, end, int(slot), bits, optField[int(slot)], &buff, mCoders[int(slot)], getMemMarginFactor());
112 // clang-format off
113 iosize += ENCODECPV(helper.begin_bcIncTrig(), helper.end_bcIncTrig(), CTF::BLC_bcIncTrig, 0);
114 iosize += ENCODECPV(helper.begin_orbitIncTrig(), helper.end_orbitIncTrig(), CTF::BLC_orbitIncTrig, 0);
115 iosize += ENCODECPV(helper.begin_entriesTrig(), helper.end_entriesTrig(), CTF::BLC_entriesTrig, 0);
116
117 iosize += ENCODECPV(helper.begin_posX(), helper.end_posX(), CTF::BLC_posX, 0);
118 iosize += ENCODECPV(helper.begin_posZ(), helper.end_posZ(), CTF::BLC_posZ, 0);
119 iosize += ENCODECPV(helper.begin_energy(), helper.end_energy(), CTF::BLC_energy, 0);
120 iosize += ENCODECPV(helper.begin_status(), helper.end_status(), CTF::BLC_status, 0);
121 // clang-format on
122 CTF::get(buff.data())->print(getPrefix(), mVerbosity);
123 finaliseCTFOutput<CTF>(buff);
124 iosize.rawIn = trigData.size() * sizeof(TriggerRecord) + cluData.size() * sizeof(Cluster);
125 return iosize;
126}
127
129template <typename VTRG, typename VCLUSTER>
130o2::ctf::CTFIOSize CTFCoder::decode(const CTF::base& ec, VTRG& trigVec, VCLUSTER& cluVec)
131{
132 auto header = ec.getHeader();
133 checkDictVersion(static_cast<const o2::ctf::CTFDictHeader&>(header));
135 std::vector<int16_t> bcInc;
136 std::vector<int32_t> orbitInc;
137 std::vector<uint16_t> entries, posX, posZ;
138 std::vector<uint8_t> energy, status;
139
140 o2::ctf::CTFIOSize iosize;
141#define DECODECPV(part, slot) ec.decode(part, int(slot), mCoders[int(slot)])
142 // clang-format off
143 iosize += DECODECPV(bcInc, CTF::BLC_bcIncTrig);
144 iosize += DECODECPV(orbitInc, CTF::BLC_orbitIncTrig);
145 iosize += DECODECPV(entries, CTF::BLC_entriesTrig);
146 iosize += DECODECPV(posX, CTF::BLC_posX);
147 iosize += DECODECPV(posZ, CTF::BLC_posZ);
148 iosize += DECODECPV(energy, CTF::BLC_energy);
149 iosize += DECODECPV(status, CTF::BLC_status);
150 // clang-format on
151 //
152 trigVec.clear();
153 cluVec.clear();
154 trigVec.reserve(header.nTriggers);
155 status.reserve(header.nClusters);
156
157 uint32_t firstEntry = 0, cluCount = 0;
158 o2::InteractionRecord ir(header.firstBC, header.firstOrbit);
159 bool checkIROK = (mBCShift == 0); // need to check if CTP offset correction does not make the local time negative ?
160 Cluster clu;
161 for (uint32_t itrig = 0; itrig < header.nTriggers; itrig++) {
162 // restore TrigRecord
163 if (orbitInc[itrig]) { // non-0 increment => new orbit
164 ir.bc = bcInc[itrig]; // bcInc has absolute meaning
165 ir.orbit += orbitInc[itrig];
166 } else {
167 ir.bc += bcInc[itrig];
168 }
169 if (checkIROK || canApplyBCShift(ir)) { // correction will be ok
170 checkIROK = true;
171 } else { // correction would make IR prior to mFirstTFOrbit, skip
172 cluCount += entries[itrig];
173 continue;
174 }
175 firstEntry = cluVec.size();
176 for (uint16_t ic = 0; ic < entries[itrig]; ic++) {
177 clu.setPacked(posX[cluCount], posZ[cluCount], energy[cluCount], status[cluCount]);
178 cluVec.emplace_back(clu);
179 cluCount++;
180 }
181 trigVec.emplace_back(ir - mBCShift, firstEntry, entries[itrig]);
182 }
183 assert(cluCount == header.nClusters);
184 iosize.rawIn = trigVec.size() * sizeof(TriggerRecord) + cluVec.size() * sizeof(Cluster);
185 return iosize;
186}
187
188} // namespace cpv
189} // namespace o2
190
191#endif // O2_CPV_CTFCODER_H
Definitions for CPV CTF data.
#define ENCODECPV(beg, end, slot, bits)
#define DECODECPV(part, slot)
Helper for CPV CTF creation.
Declarations for CTFCoderBase class (support of external dictionaries)
uint32_t op
o2::ctf::CTFIOSize decode(const CTF::base &ec, VTRG &trigVec, VCLUSTER &cluVec)
entropy decode data from buffer with CTF
Definition CTFCoder.h:130
o2::ctf::CTFIOSize encode(VEC &buff, const gsl::span< const TriggerRecord > &trigData, const gsl::span< const Cluster > &cluData)
entropy-encode data to buffer with CTF
Definition CTFCoder.h:63
~CTFCoder() final=default
CTFCoder(o2::ctf::CTFCoderBase::OpType op)
Definition CTFCoder.h:38
void createCoders(const std::vector< char > &bufVec, ctf::CTFCoderBase::OpType op) final
Definition CTFCoder.cxx:40
Contains CPV cluster parameters.
Definition Cluster.h:33
Header for data corresponding to the same hardware trigger adapted from DataFormatsEMCAL/TriggerRecor...
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
HMPID cluster implementation.
Definition Cluster.h:27
long check(o2::dataformats::IRFrame fr, size_t bwd=0, size_t fwd=0)
GLuint entry
Definition glcorearb.h:5735
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
wrapper for the Entropy-encoded triggers and cells of the TF
Definition CTF.h:41
@ BLC_entriesTrig
Definition CTF.h:46
@ BLC_bcIncTrig
Definition CTF.h:44
@ BLC_status
Definition CTF.h:50
@ BLC_posX
Definition CTF.h:47
@ BLC_orbitIncTrig
Definition CTF.h:45
@ BLC_energy
Definition CTF.h:49
@ BLC_posZ
Definition CTF.h:48
Detector header base.
Cluster clu
o2::InteractionRecord ir(0, 0)
std::unique_ptr< TTree > tree((TTree *) flIn.Get(std::string(o2::base::NameConf::CTFTREENAME).c_str()))