|
16 | 16 | #ifndef ALICEO2_TPC_CMVCONTAINER_H_ |
17 | 17 | #define ALICEO2_TPC_CMVCONTAINER_H_ |
18 | 18 |
|
19 | | -#include <vector> |
20 | 19 | #include <string> |
21 | 20 | #include <memory> |
22 | 21 | #include <stdexcept> |
23 | 22 | #include <fmt/format.h> |
24 | 23 |
|
25 | 24 | #include "TTree.h" |
| 25 | +#include "TPCBase/CRU.h" |
26 | 26 | #include "DataFormatsTPC/CMV.h" |
27 | 27 |
|
28 | 28 | namespace o2::tpc |
29 | 29 | { |
30 | 30 |
|
31 | 31 | /// CMV data for one TF across all CRUs |
| 32 | +/// Raw 16-bit CMV values are stored in a flat C array indexed as [cru * NTimeBinsPerTF + timeBin] |
| 33 | +/// CRU::MaxCRU and cmv::NTimeBinsPerTF are compile-time constants, so no dynamic allocation is needed |
| 34 | +/// Each TTree entry corresponds to one CMVPerTF object (one TF) |
32 | 35 | struct CMVPerTF { |
33 | | - int64_t firstOrbit{0}; ///< First orbit of this TF, from heartbeatOrbit of the first CMV packet |
34 | | - int64_t firstBC{0}; ///< First bunch crossing of this TF, from heartbeatBC of the first CMV packet |
| 36 | + uint32_t firstOrbit{0}; ///< First orbit of this TF, from heartbeatOrbit of the first CMV packet |
| 37 | + uint16_t firstBC{0}; ///< First bunch crossing of this TF, from heartbeatBC of the first CMV packet |
35 | 38 |
|
36 | | - /// CMV float values indexed as [CRU ID][time bin] |
37 | | - std::vector<std::vector<float>> mDataPerTF; |
| 39 | + // Raw 16-bit CMV values, flat array indexed as [cru * NTimeBinsPerTF + timeBin] |
| 40 | + uint16_t mDataPerTF[CRU::MaxCRU * cmv::NTimeBinsPerTF]{}; |
38 | 41 |
|
39 | | - /// Return the CMV value for a given CRU and time bin within this TF |
40 | | - float getCMV(const int cru, const int timeBin) const |
| 42 | + /// Return the raw 16-bit CMV value for a given CRU and timebin within this TF |
| 43 | + uint16_t getCMV(const int cru, const int timeBin) const |
41 | 44 | { |
42 | | - if (cru < 0 || static_cast<std::size_t>(cru) >= mDataPerTF.size()) { |
43 | | - throw std::out_of_range(fmt::format("CMVPerTF::getCMV: cru {} out of range [0, {})", cru, mDataPerTF.size())); |
| 45 | + if (cru < 0 || cru >= static_cast<int>(CRU::MaxCRU)) { |
| 46 | + throw std::out_of_range(fmt::format("CMVPerTF::getCMV: cru {} out of range [0, {})", cru, static_cast<int>(CRU::MaxCRU))); |
44 | 47 | } |
45 | 48 | if (timeBin < 0 || static_cast<uint32_t>(timeBin) >= cmv::NTimeBinsPerTF) { |
46 | | - throw std::out_of_range(fmt::format("CMVPerTF::getCMV: timeBin {} out of range [0, {})", timeBin, cmv::NTimeBinsPerTF)); |
| 49 | + throw std::out_of_range(fmt::format("CMVPerTF::getCMV: timeBin {} out of range [0, {})", timeBin, static_cast<int>(cmv::NTimeBinsPerTF))); |
47 | 50 | } |
48 | | - return mDataPerTF[cru][timeBin]; |
| 51 | + return mDataPerTF[cru * cmv::NTimeBinsPerTF + timeBin]; |
49 | 52 | } |
50 | 53 |
|
51 | | - ClassDefNV(CMVPerTF, 1) |
52 | | -}; |
53 | | - |
54 | | -/// Container holding CMVs for one aggregation interval |
55 | | -struct CMVPerInterval { |
56 | | - int64_t firstTF{0}; ///< First TF counter seen in this interval |
57 | | - int64_t lastTF{0}; ///< Last TF counter seen in this interval |
58 | | - |
59 | | - /// CMV data, one CMVPerTF entry per TF, indexed by relative TF [0, nTimeFrames) |
60 | | - std::vector<CMVPerTF> mCMVPerTF; |
61 | | - |
62 | | - /// Pre-allocate nTFs TF slots; each slot gets mDataPerTF resized to nCRUs entries |
63 | | - void reserve(uint32_t nTFs, uint32_t nCRUs); |
64 | | - |
65 | | - std::size_t size() const { return mCMVPerTF.size(); } |
66 | | - bool empty() const { return mCMVPerTF.empty(); } |
67 | | - |
68 | | - /// Clear all data and reset counters |
69 | | - void clear(); |
70 | | - |
71 | | - std::string summary() const; |
| 54 | + /// Return the float CMV value for a given CRU and timebin within this TF |
| 55 | + float getCMVFloat(const int cru, const int timeBin) const |
| 56 | + { |
| 57 | + auto cmv = getCMV(cru, timeBin); |
| 58 | + const bool positive = (cmv >> 15) & 1; // bit 15: sign (1=positive, 0=negative) |
| 59 | + const float magnitude = (cmv & 0x7FFF) / 128.f; // lower 15 bits, shift right by 7 (divide by 2^7) |
| 60 | + return positive ? magnitude : -magnitude; |
| 61 | + } |
72 | 62 |
|
73 | | - /// Serialise into a TTree with a single branch holding the whole CMVPerInterval object |
| 63 | + /// Serialise into a TTree; each Fill() call appends one entry (one TF) |
74 | 64 | std::unique_ptr<TTree> toTTree() const; |
75 | 65 |
|
76 | 66 | /// Write the TTree to a ROOT file |
77 | 67 | void writeToFile(const std::string& filename, const std::unique_ptr<TTree>& tree) const; |
78 | 68 |
|
79 | | - /// Restore a CMVPerInterval from a TTree previously written by toTTree() |
80 | | - static CMVPerInterval fromTTree(TTree* tree, int entry = 0); |
81 | | - |
82 | | - ClassDefNV(CMVPerInterval, 1) |
| 69 | + ClassDefNV(CMVPerTF, 8) |
83 | 70 | }; |
84 | 71 |
|
85 | 72 | } // namespace o2::tpc |
|
0 commit comments