|
| 1 | +// Copyright CERN and copyright holders of ALICE O2. This software is |
| 2 | +// distributed under the terms of the GNU General Public License v3 (GPL |
| 3 | +// Version 3), copied verbatim in the file "COPYING". |
| 4 | +// |
| 5 | +// See http://alice-o2.web.cern.ch/license for full licensing information. |
| 6 | +// |
| 7 | +// In applying this license CERN does not waive the privileges and immunities |
| 8 | +// granted to it by virtue of its status as an Intergovernmental Organization |
| 9 | +// or submit itself to any jurisdiction. |
| 10 | + |
| 11 | +/// \file CTFCoder.h |
| 12 | +/// \author ruben.shahoyan@cern.ch |
| 13 | +/// \brief class for entropy encoding/decoding of MID column data |
| 14 | + |
| 15 | +#ifndef O2_MID_CTFCODER_H |
| 16 | +#define O2_MID_CTFCODER_H |
| 17 | + |
| 18 | +#include <algorithm> |
| 19 | +#include <iterator> |
| 20 | +#include <string> |
| 21 | +#include <array> |
| 22 | +#include "DataFormatsMID/CTF.h" |
| 23 | +#include "DataFormatsMID/ROFRecord.h" |
| 24 | +#include "DataFormatsMID/ColumnData.h" |
| 25 | +#include "DetectorsCommonDataFormats/DetID.h" |
| 26 | +#include "DetectorsBase/CTFCoderBase.h" |
| 27 | +#include "rANS/rans.h" |
| 28 | +#include "MIDCTF/CTFHelper.h" |
| 29 | + |
| 30 | +class TTree; |
| 31 | + |
| 32 | +namespace o2 |
| 33 | +{ |
| 34 | +namespace mid |
| 35 | +{ |
| 36 | + |
| 37 | +class CTFCoder : public o2::ctf::CTFCoderBase |
| 38 | +{ |
| 39 | + public: |
| 40 | + CTFCoder() : o2::ctf::CTFCoderBase(CTF::getNBlocks(), o2::detectors::DetID::MID) {} |
| 41 | + ~CTFCoder() = default; |
| 42 | + |
| 43 | + /// entropy-encode data to buffer with CTF |
| 44 | + template <typename VEC> |
| 45 | + void encode(VEC& buff, const gsl::span<const ROFRecord>& rofData, const gsl::span<const ColumnData>& colData); |
| 46 | + |
| 47 | + /// entropy decode data from buffer with CTF |
| 48 | + template <typename VROF, typename VCOL> |
| 49 | + void decode(const CTF::base& ec, VROF& rofVec, VCOL& colVec); |
| 50 | + |
| 51 | + void createCoders(const std::string& dictPath, o2::ctf::CTFCoderBase::OpType op); |
| 52 | + |
| 53 | + private: |
| 54 | + void appendToTree(TTree& tree, CTF& ec); |
| 55 | + void readFromTree(TTree& tree, int entry, std::vector<ROFRecord>& rofVec, std::vector<ColumnData>& colVec); |
| 56 | +}; |
| 57 | + |
| 58 | +/// entropy-encode clusters to buffer with CTF |
| 59 | +template <typename VEC> |
| 60 | +void CTFCoder::encode(VEC& buff, const gsl::span<const ROFRecord>& rofData, const gsl::span<const ColumnData>& colData) |
| 61 | +{ |
| 62 | + using MD = o2::ctf::Metadata::OptStore; |
| 63 | + // what to do which each field: see o2::ctd::Metadata explanation |
| 64 | + constexpr MD optField[CTF::getNBlocks()] = { |
| 65 | + MD::EENCODE, // BLC_bcIncROF |
| 66 | + MD::EENCODE, // BLC_orbitIncROF |
| 67 | + MD::EENCODE, // BLC_entriesROF |
| 68 | + MD::EENCODE, // BLC_evtypeROF |
| 69 | + MD::EENCODE, // BLC_pattern |
| 70 | + MD::EENCODE, // BLC_deId |
| 71 | + MD::EENCODE // BLC_colId |
| 72 | + }; |
| 73 | + CTFHelper helper(rofData, colData); |
| 74 | + |
| 75 | + // book output size with some margin |
| 76 | + auto szIni = sizeof(CTFHeader) + helper.getSize() / 4; // will be autoexpanded if needed |
| 77 | + buff.resize(szIni); |
| 78 | + |
| 79 | + auto ec = CTF::create(buff); |
| 80 | + using ECB = CTF::base; |
| 81 | + |
| 82 | + ec->setHeader(helper.createHeader()); |
| 83 | + ec->getANSHeader().majorVersion = 0; |
| 84 | + ec->getANSHeader().minorVersion = 1; |
| 85 | + // at every encoding the buffer might be autoexpanded, so we don't work with fixed pointer ec |
| 86 | +#define ENCODEMID(beg, end, slot, bits) CTF::get(buff.data())->encode(beg, end, int(slot), bits, optField[int(slot)], &buff, mCoders[int(slot)].get()); |
| 87 | + // clang-format off |
| 88 | + ENCODEMID(helper.begin_bcIncROF(), helper.end_bcIncROF(), CTF::BLC_bcIncROF, 0); |
| 89 | + ENCODEMID(helper.begin_orbitIncROF(), helper.end_orbitIncROF(), CTF::BLC_orbitIncROF, 0); |
| 90 | + ENCODEMID(helper.begin_entriesROF(), helper.end_entriesROF(), CTF::BLC_entriesROF, 0); |
| 91 | + ENCODEMID(helper.begin_evtypeROF(), helper.end_evtypeROF(), CTF::BLC_evtypeROF, 0); |
| 92 | + |
| 93 | + ENCODEMID(helper.begin_pattern(), helper.end_pattern(), CTF::BLC_pattern, 0); |
| 94 | + ENCODEMID(helper.begin_deId(), helper.end_deId(), CTF::BLC_deId, 0); |
| 95 | + ENCODEMID(helper.begin_colId(), helper.end_colId(), CTF::BLC_colId, 0); |
| 96 | + // clang-format on |
| 97 | + CTF::get(buff.data())->print(getPrefix()); |
| 98 | +} |
| 99 | + |
| 100 | +/// decode entropy-encoded clusters to standard compact clusters |
| 101 | +template <typename VROF, typename VCOL> |
| 102 | +void CTFCoder::decode(const CTF::base& ec, VROF& rofVec, VCOL& colVec) |
| 103 | +{ |
| 104 | + auto header = ec.getHeader(); |
| 105 | + ec.print(getPrefix()); |
| 106 | + std::vector<uint16_t> bcInc, entries, pattern; |
| 107 | + std::vector<uint32_t> orbitInc; |
| 108 | + std::vector<uint8_t> evType, deId, colId; |
| 109 | + |
| 110 | +#define DECODEFT0(part, slot) ec.decode(part, int(slot), mCoders[int(slot)].get()) |
| 111 | + // clang-format off |
| 112 | + DECODEFT0(bcInc, CTF::BLC_bcIncROF); |
| 113 | + DECODEFT0(orbitInc, CTF::BLC_orbitIncROF); |
| 114 | + DECODEFT0(entries, CTF::BLC_entriesROF); |
| 115 | + DECODEFT0(evType, CTF::BLC_evtypeROF); |
| 116 | + |
| 117 | + DECODEFT0(pattern, CTF::BLC_pattern); |
| 118 | + DECODEFT0(deId, CTF::BLC_deId); |
| 119 | + DECODEFT0(colId, CTF::BLC_colId); |
| 120 | + // clang-format on |
| 121 | + // |
| 122 | + rofVec.clear(); |
| 123 | + colVec.clear(); |
| 124 | + rofVec.reserve(header.nROFs); |
| 125 | + colVec.reserve(header.nColumns); |
| 126 | + |
| 127 | + uint32_t firstEntry = 0, rofCount = 0, colCount = 0, pCount = 0; |
| 128 | + o2::InteractionRecord ir(header.firstBC, header.firstOrbit); |
| 129 | + |
| 130 | + for (uint32_t irof = 0; irof < header.nROFs; irof++) { |
| 131 | + // restore ROFRecord |
| 132 | + if (orbitInc[irof]) { // non-0 increment => new orbit |
| 133 | + ir.bc = bcInc[irof]; // bcInc has absolute meaning |
| 134 | + ir.orbit += orbitInc[irof]; |
| 135 | + } else { |
| 136 | + ir.bc += bcInc[irof]; |
| 137 | + } |
| 138 | + |
| 139 | + firstEntry = colVec.size(); |
| 140 | + for (uint8_t ic = 0; ic < entries[irof]; ic++) { |
| 141 | + colVec.emplace_back(ColumnData{deId[colCount], colId[colCount], std::array{pattern[pCount], pattern[pCount + 1], pattern[pCount + 2], pattern[pCount + 3], pattern[pCount + 4]}}); |
| 142 | + pCount += 5; |
| 143 | + colCount++; |
| 144 | + } |
| 145 | + rofVec.emplace_back(ROFRecord{ir, EventType(evType[irof]), firstEntry, entries[irof]}); |
| 146 | + } |
| 147 | + assert(colCount == header.nColumns); |
| 148 | +} |
| 149 | + |
| 150 | +} // namespace mid |
| 151 | +} // namespace o2 |
| 152 | + |
| 153 | +#endif // O2_MID_CTFCODER_H |
0 commit comments