Skip to content

Commit 37e12af

Browse files
committed
Replace CMVPerInterval with per TF TTree accumulation and raw uint16_t storage, fix CCDB timestamp for partial intervals, fix TMemFile padding
1 parent 82663fb commit 37e12af

File tree

6 files changed

+109
-146
lines changed

6 files changed

+109
-146
lines changed

Detectors/TPC/calibration/include/TPCCalibration/CMVContainer.h

Lines changed: 24 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -16,70 +16,57 @@
1616
#ifndef ALICEO2_TPC_CMVCONTAINER_H_
1717
#define ALICEO2_TPC_CMVCONTAINER_H_
1818

19-
#include <vector>
2019
#include <string>
2120
#include <memory>
2221
#include <stdexcept>
2322
#include <fmt/format.h>
2423

2524
#include "TTree.h"
25+
#include "TPCBase/CRU.h"
2626
#include "DataFormatsTPC/CMV.h"
2727

2828
namespace o2::tpc
2929
{
3030

3131
/// 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)
3235
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
3538

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]{};
3841

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
4144
{
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)));
4447
}
4548
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)));
4750
}
48-
return mDataPerTF[cru][timeBin];
51+
return mDataPerTF[cru * cmv::NTimeBinsPerTF + timeBin];
4952
}
5053

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+
}
7262

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)
7464
std::unique_ptr<TTree> toTTree() const;
7565

7666
/// Write the TTree to a ROOT file
7767
void writeToFile(const std::string& filename, const std::unique_ptr<TTree>& tree) const;
7868

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)
8370
};
8471

8572
} // namespace o2::tpc

Detectors/TPC/calibration/src/CMVContainer.cxx

Lines changed: 5 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -22,74 +22,29 @@
2222
namespace o2::tpc
2323
{
2424

25-
void CMVPerInterval::reserve(uint32_t nTFs, uint32_t nCRUs)
25+
std::unique_ptr<TTree> CMVPerTF::toTTree() const
2626
{
27-
mCMVPerTF.resize(nTFs);
28-
for (auto& tfData : mCMVPerTF) {
29-
tfData.mDataPerTF.resize(nCRUs);
30-
}
31-
}
32-
33-
void CMVPerInterval::clear()
34-
{
35-
mCMVPerTF.clear();
36-
firstTF = 0;
37-
lastTF = 0;
38-
}
39-
40-
std::string CMVPerInterval::summary() const
41-
{
42-
const std::size_t nCRUs = empty() ? 0 : mCMVPerTF.front().mDataPerTF.size();
43-
return fmt::format("CMVPerInterval: {} TFs, {} CRU slots, firstTF={}, lastTF={}",
44-
size(), nCRUs, firstTF, lastTF);
45-
}
46-
47-
std::unique_ptr<TTree> CMVPerInterval::toTTree() const
48-
{
49-
if (empty()) {
50-
throw std::runtime_error("CMVPerInterval::toTTree() called on empty container");
51-
}
52-
5327
auto tree = std::make_unique<TTree>("ccdb_object", "ccdb_object");
5428
tree->SetAutoSave(0);
5529
tree->SetDirectory(nullptr);
5630

57-
const CMVPerInterval* ptr = this;
58-
tree->Branch("CMVPerInterval", &ptr);
31+
const CMVPerTF* ptr = this;
32+
tree->Branch("CMVPerTF", &ptr);
5933
tree->Fill();
6034

6135
tree->ResetBranchAddresses();
6236

6337
return tree;
6438
}
6539

66-
void CMVPerInterval::writeToFile(const std::string& filename, const std::unique_ptr<TTree>& tree) const
40+
void CMVPerTF::writeToFile(const std::string& filename, const std::unique_ptr<TTree>& tree) const
6741
{
6842
TFile f(filename.c_str(), "RECREATE");
6943
if (f.IsZombie()) {
70-
throw std::runtime_error(fmt::format("CMVPerInterval::writeToFile: cannot open '{}'", filename));
44+
throw std::runtime_error(fmt::format("CMVPerTF::writeToFile: cannot open '{}'", filename));
7145
}
7246
tree->Write();
7347
f.Close();
7448
}
7549

76-
CMVPerInterval CMVPerInterval::fromTTree(TTree* tree, int entry)
77-
{
78-
if (!tree) {
79-
throw std::runtime_error("CMVPerInterval::fromTTree: null TTree pointer");
80-
}
81-
82-
CMVPerInterval* ptr = nullptr;
83-
tree->SetBranchAddress("CMVPerInterval", &ptr);
84-
tree->GetEntry(entry);
85-
86-
if (!ptr) {
87-
throw std::runtime_error("CMVPerInterval::fromTTree: failed to read object from TTree");
88-
}
89-
90-
CMVPerInterval result = std::move(*ptr);
91-
delete ptr;
92-
return result;
93-
}
94-
9550
} // namespace o2::tpc

Detectors/TPC/calibration/src/TPCCalibrationLinkDef.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,5 @@
125125
#pragma link C++ class o2::tpc::PressureTemperatureHelper + ;
126126

127127
#pragma link C++ class o2::tpc::CMVPerTF + ;
128-
#pragma link C++ class o2::tpc::CMVPerInterval + ;
129-
#pragma link C++ class std::vector < o2::tpc::CMVPerTF> + ;
130-
#pragma link C++ class std::vector < std::vector < float>> + ;
131128

132129
#endif

0 commit comments

Comments
 (0)