Skip to content

Commit c5e4a69

Browse files
committed
MID CTFcoder + encoder/decocer specs
1 parent 02b2924 commit c5e4a69

19 files changed

+846
-6
lines changed

Detectors/MUON/MID/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ add_subdirectory(Base)
1212
add_subdirectory(Clustering)
1313
add_subdirectory(QC)
1414
add_subdirectory(Raw)
15+
add_subdirectory(CTF)
1516
add_subdirectory(Simulation)
1617
add_subdirectory(TestingSimTools)
1718
add_subdirectory(Tracking)
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Copyright CERN and copyright holders of ALICE O2. This software is distributed
2+
# under the terms of the GNU General Public License v3 (GPL Version 3), copied
3+
# 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 or
9+
# submit itself to any jurisdiction.
10+
11+
o2_add_library(MIDCTF
12+
SOURCES src/CTFCoder.cxx src/CTFHelper.cxx
13+
PUBLIC_LINK_LIBRARIES O2::DataFormatsMID
14+
O2::DetectorsBase
15+
O2::CommonDataFormat
16+
O2::DetectorsCommonDataFormats
17+
O2::rANS
18+
ms_gsl::ms_gsl)
19+

Detectors/MUON/MID/CTF/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<!-- doxy
2+
\page refMUONMIDCTF MID CTF encoding library
3+
/doxy -->
4+
5+
# MID CTF
6+
This directory contains the classes to handle entropy encoding of MID
7+
ROFRecord and ColumnData data.
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
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
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
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 CTFHelper.h
12+
/// \author ruben.shahoyan@cern.ch
13+
/// \brief Helper for MID CTF creation
14+
15+
#ifndef O2_MID_CTF_HELPER_H
16+
#define O2_MID_CTF_HELPER_H
17+
18+
#include "DataFormatsMID/ROFRecord.h"
19+
#include "DataFormatsMID/ColumnData.h"
20+
#include "DataFormatsMID/CTF.h"
21+
#include <gsl/span>
22+
23+
namespace o2
24+
{
25+
namespace mid
26+
{
27+
28+
class CTFHelper
29+
{
30+
31+
public:
32+
CTFHelper(const gsl::span<const o2::mid::ROFRecord>& rofData, const gsl::span<const o2::mid::ColumnData>& colData)
33+
: mROFData(rofData), mColData(colData) {}
34+
35+
CTFHeader createHeader()
36+
{
37+
CTFHeader h{uint32_t(mROFData.size()), uint32_t(mColData.size()), 0, 0};
38+
if (mROFData.size()) {
39+
h.firstOrbit = mROFData[0].interactionRecord.orbit;
40+
h.firstBC = mROFData[0].interactionRecord.bc;
41+
}
42+
return h;
43+
}
44+
45+
size_t getSize() const { return mROFData.size() * sizeof(o2::mid::ROFRecord) + mColData.size() * sizeof(o2::mid::ColumnData); }
46+
47+
//>>> =========================== ITERATORS ========================================
48+
49+
template <typename I, typename D, typename T, int M = 1>
50+
class _Iter
51+
{
52+
public:
53+
using difference_type = int64_t;
54+
using value_type = T;
55+
using pointer = const T*;
56+
using reference = const T&;
57+
using iterator_category = std::random_access_iterator_tag;
58+
59+
_Iter(const gsl::span<const D>& data, bool end = false) : mData(data), mIndex(end ? M * data.size() : 0){};
60+
_Iter() = default;
61+
62+
const I& operator++()
63+
{
64+
++mIndex;
65+
return (I&)(*this);
66+
}
67+
68+
const I& operator--()
69+
{
70+
mIndex--;
71+
return (I&)(*this);
72+
}
73+
74+
difference_type operator-(const I& other) const { return mIndex - other.mIndex; }
75+
76+
difference_type operator-(size_t idx) const { return mIndex - idx; }
77+
78+
const I& operator-(size_t idx)
79+
{
80+
mIndex -= idx;
81+
return (I&)(*this);
82+
}
83+
84+
bool operator!=(const I& other) const { return mIndex != other.mIndex; }
85+
bool operator==(const I& other) const { return mIndex == other.mIndex; }
86+
bool operator>(const I& other) const { return mIndex > other.mIndex; }
87+
bool operator<(const I& other) const { return mIndex < other.mIndex; }
88+
89+
protected:
90+
gsl::span<const D> mData{};
91+
size_t mIndex = 0;
92+
};
93+
94+
//_______________________________________________
95+
// BC difference wrt previous if in the same orbit, otherwise the abs.value.
96+
// For the very 1st entry return 0 (diff wrt 1st BC in the CTF header)
97+
class Iter_bcIncROF : public _Iter<Iter_bcIncROF, ROFRecord, uint16_t>
98+
{
99+
public:
100+
using _Iter<Iter_bcIncROF, ROFRecord, uint16_t>::_Iter;
101+
value_type operator*() const
102+
{
103+
if (mIndex) {
104+
if (mData[mIndex].interactionRecord.orbit == mData[mIndex - 1].interactionRecord.orbit) {
105+
return mData[mIndex].interactionRecord.bc - mData[mIndex - 1].interactionRecord.bc;
106+
} else {
107+
return mData[mIndex].interactionRecord.bc;
108+
}
109+
}
110+
return 0;
111+
}
112+
};
113+
114+
//_______________________________________________
115+
// Orbit difference wrt previous. For the very 1st entry return 0 (diff wrt 1st BC in the CTF header)
116+
class Iter_orbitIncROF : public _Iter<Iter_orbitIncROF, ROFRecord, uint32_t>
117+
{
118+
public:
119+
using _Iter<Iter_orbitIncROF, ROFRecord, uint32_t>::_Iter;
120+
value_type operator*() const { return mIndex ? mData[mIndex].interactionRecord.orbit - mData[mIndex - 1].interactionRecord.orbit : 0; }
121+
};
122+
123+
//_______________________________________________
124+
// Number of entries in the ROF
125+
class Iter_entriesROF : public _Iter<Iter_entriesROF, ROFRecord, uint16_t>
126+
{
127+
public:
128+
using _Iter<Iter_entriesROF, ROFRecord, uint16_t>::_Iter;
129+
value_type operator*() const { return mData[mIndex].nEntries; }
130+
};
131+
132+
//_______________________________________________
133+
// Event type for the ROF
134+
class Iter_evtypeROF : public _Iter<Iter_evtypeROF, ROFRecord, uint8_t>
135+
{
136+
public:
137+
using _Iter<Iter_evtypeROF, ROFRecord, uint8_t>::_Iter;
138+
value_type operator*() const { return value_type(mData[mIndex].eventType); }
139+
};
140+
141+
//_______________________________________________
142+
class Iter_pattern : public _Iter<Iter_pattern, ColumnData, uint16_t, 5>
143+
{
144+
public:
145+
using _Iter<Iter_pattern, ColumnData, uint16_t, 5>::_Iter;
146+
value_type operator*() const { return mData[mIndex / 5].patterns[mIndex % 5]; }
147+
};
148+
149+
//_______________________________________________
150+
class Iter_deId : public _Iter<Iter_deId, ColumnData, uint8_t>
151+
{
152+
public:
153+
using _Iter<Iter_deId, ColumnData, uint8_t>::_Iter;
154+
value_type operator*() const { return mData[mIndex].deId; }
155+
};
156+
157+
//_______________________________________________
158+
class Iter_colId : public _Iter<Iter_colId, ColumnData, uint8_t>
159+
{
160+
public:
161+
using _Iter<Iter_colId, ColumnData, uint8_t>::_Iter;
162+
value_type operator*() const { return mData[mIndex].columnId; }
163+
};
164+
165+
//<<< =========================== ITERATORS ========================================
166+
167+
Iter_bcIncROF begin_bcIncROF() const { return Iter_bcIncROF(mROFData, false); }
168+
Iter_bcIncROF end_bcIncROF() const { return Iter_bcIncROF(mROFData, true); }
169+
170+
Iter_orbitIncROF begin_orbitIncROF() const { return Iter_orbitIncROF(mROFData, false); }
171+
Iter_orbitIncROF end_orbitIncROF() const { return Iter_orbitIncROF(mROFData, true); }
172+
173+
Iter_entriesROF begin_entriesROF() const { return Iter_entriesROF(mROFData, false); }
174+
Iter_entriesROF end_entriesROF() const { return Iter_entriesROF(mROFData, true); }
175+
176+
Iter_evtypeROF begin_evtypeROF() const { return Iter_evtypeROF(mROFData, false); }
177+
Iter_evtypeROF end_evtypeROF() const { return Iter_evtypeROF(mROFData, true); }
178+
179+
Iter_pattern begin_pattern() const { return Iter_pattern(mColData, false); }
180+
Iter_pattern end_pattern() const { return Iter_pattern(mColData, true); }
181+
182+
Iter_deId begin_deId() const { return Iter_deId(mColData, false); }
183+
Iter_deId end_deId() const { return Iter_deId(mColData, true); }
184+
185+
Iter_colId begin_colId() const { return Iter_colId(mColData, false); }
186+
Iter_colId end_colId() const { return Iter_colId(mColData, true); }
187+
188+
private:
189+
const gsl::span<const o2::mid::ROFRecord> mROFData;
190+
const gsl::span<const o2::mid::ColumnData> mColData;
191+
};
192+
193+
} // namespace mid
194+
} // namespace o2
195+
196+
#endif

0 commit comments

Comments
 (0)