Skip to content

Commit 8e5cf37

Browse files
committed
Added gaussian dynamic precision
1 parent 5d720d4 commit 8e5cf37

File tree

5 files changed

+372
-27
lines changed

5 files changed

+372
-27
lines changed

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

Lines changed: 47 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,11 @@
2828
namespace o2::tpc
2929
{
3030

31-
struct CMVPerTF; // forward declaration
32-
struct CMVPerTFSparse; // forward declaration
33-
struct CMVPerTFHuffman; // forward declaration
34-
struct CMVPerTFCombined; // forward declaration
31+
struct CMVPerTF; // forward declaration
32+
struct CMVPerTFSparse; // forward declaration
33+
struct CMVPerTFHuffman; // forward declaration
34+
struct CMVPerTFCombined; // forward declaration
35+
struct CMVPerTFQuantized; // forward declaration
3536

3637
/// Delta+zigzag+varint compressed CMV data for one TF across all CRUs
3738
/// Produced by CMVPerTF::compressVarint(), restored with decompress()
@@ -108,7 +109,7 @@ struct CMVPerTFHuffman {
108109

109110
/// Hybrid sparse+compressed-value encoding for one TF across all CRUs
110111
///
111-
/// Non-zero positions are stored as sparse varint deltas (same as CMVPerTFSparse).
112+
/// Non-zero positions are stored as sparse varint deltas (same as CMVPerTFSparse)
112113
/// The remaining non-zero values are encoded according to mValueMode:
113114
///
114115
/// Mode 0 raw uint16_t — identical value encoding to CMVPerTFSparse
@@ -135,6 +136,31 @@ struct CMVPerTFCombined {
135136
ClassDefNV(CMVPerTFCombined, 1)
136137
};
137138

139+
/// Sparse positions + quantized-value symbols for one TF across all CRUs
140+
///
141+
/// Non-zero positions are stored as sparse varint deltas.
142+
/// The corresponding values are encoded as quantized signed symbols:
143+
/// Mode 0 raw symbols — 4-byte LE uint32 per symbol
144+
/// Mode 1 varint symbols — varint(symbol)
145+
/// Mode 2 Huffman symbols — canonical Huffman over symbol stream
146+
/// Quantized symbols represent decimal-style values below the internally derived full-precision cutoff
147+
/// and exact raw signed I8F7 values above it.
148+
struct CMVPerTFQuantized {
149+
uint32_t firstOrbit{0}; ///< First orbit of this TF
150+
uint16_t firstBC{0}; ///< First bunch crossing of this TF
151+
uint8_t mValueMode{0}; ///< 0 = raw symbols, 1 = varint symbols, 2 = Huffman symbols
152+
153+
std::vector<uint8_t> mData; ///< Encoded payload
154+
155+
/// Restore nearest raw-I8F7 values into *cmv (must not be null)
156+
void decompress(CMVPerTF* cmv) const;
157+
158+
/// Restore exact quantized float values into `values`, sized to CRU::MaxCRU * cmv::NTimeBinsPerTF
159+
void decompressToFloatBuffer(std::vector<float>& values) const;
160+
161+
ClassDefNV(CMVPerTFQuantized, 1)
162+
};
163+
138164
/// CMV data for one TF across all CRUs
139165
/// Raw 16-bit CMV values are stored in a flat C array indexed as [cru * NTimeBinsPerTF + timeBin]
140166
/// CRU::MaxCRU and cmv::NTimeBinsPerTF are compile-time constants, so no dynamic allocation is needed
@@ -166,12 +192,24 @@ struct CMVPerTF {
166192
/// threshold=0 rounding is not applied
167193
void roundToIntegers(uint16_t threshold);
168194

195+
/// Quantise |v| with a Gaussian-CDF recovery profile:
196+
/// coarse decimal-style precision below and around mean, then a smooth return to the
197+
/// full native I8F7 precision as the magnitude increases with width sigma
198+
void trimGaussianPrecision(float mean, float sigma);
199+
169200
/// Compress this object into a CMVPerTFVarint using delta+zigzag+varint encoding
170201
CMVPerTFVarint compressVarint() const;
171202

172203
/// Compress this object into a CMVPerTFSparse storing only non-zero timebins
173204
CMVPerTFSparse compressSparse() const;
174205

206+
/// Dedicated sparse + quantized-value compression
207+
/// valueMode:
208+
/// 0 = raw symbol stream
209+
/// 1 = varint symbol stream
210+
/// 2 = Huffman symbol stream
211+
CMVPerTFQuantized compressQuantized(uint8_t valueMode = 0, float quantizationMean = 1.f, float quantizationSigma = 0.f) const;
212+
175213
/// Hybrid sparse+compressed-value compression
176214
/// Positions encoded as sparse varint deltas; values encoded according to valueMode:
177215
/// 0 = raw uint16_t (same as compressSparse, no additional gain)
@@ -189,9 +227,10 @@ struct CMVPerTF {
189227
static void writeToFile(const std::string& filename, const std::unique_ptr<TTree>& tree);
190228

191229
private:
192-
static int32_t cmvToSigned(uint16_t raw); ///< Sign-magnitude uint16_t → signed integer
193-
static uint32_t zigzagEncode(int32_t value); ///< Zigzag encode
194-
static void encodeVarintInto(uint32_t value, std::vector<uint8_t>& out); ///< Varint encode
230+
static int32_t cmvToSigned(uint16_t raw); ///< Sign-magnitude uint16_t → signed integer
231+
static uint16_t quantizeBelowThreshold(uint16_t raw, float quantizationMean, float quantizationSigma); ///< Quantise sub-threshold values with a Gaussian-shaped recovery to full precision
232+
static uint32_t zigzagEncode(int32_t value); ///< Zigzag encode
233+
static void encodeVarintInto(uint32_t value, std::vector<uint8_t>& out); ///< Varint encode
195234

196235
public:
197236
ClassDefNV(CMVPerTF, 1)

Detectors/TPC/calibration/macro/drawCMV.C

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,14 @@
1111

1212
#if !defined(__CLING__) || defined(__ROOTCLING__)
1313
#include <string>
14+
#include <vector>
1415
#include <string_view>
1516
#include <fmt/format.h>
1617

1718
#include "TFile.h"
1819
#include "TParameter.h"
1920
#include "TTree.h"
21+
#include "TH1F.h"
2022
#include "TH2F.h"
2123
#include "TCanvas.h"
2224

@@ -79,34 +81,44 @@ TObjArray* drawCMV(std::string_view filename, std::string_view outDir)
7981
100, 0, nTimeBins,
8082
110, -100.5, 9.5);
8183
h2d->SetStats(1);
84+
TH1F* h1d = new TH1F("hCMV", ";Common Mode Values (ADC);Counts",
85+
1100, -100.5, 9.5);
86+
h1d->SetStats(1);
8287

8388
// auto-detect branch format
89+
const bool isQuantized = (tree->GetBranch("CMVPerTFQuantized") != nullptr);
8490
const bool isCombined = (tree->GetBranch("CMVPerTFCombined") != nullptr);
8591
const bool isSparse = (tree->GetBranch("CMVPerTFSparse") != nullptr);
8692
const bool isHuffman = (tree->GetBranch("CMVPerTFHuffman") != nullptr);
8793
const bool isVarint = (tree->GetBranch("CMVPerTFVarint") != nullptr);
8894
const bool isRaw = (tree->GetBranch("CMVPerTF") != nullptr);
89-
if (!isCombined && !isSparse && !isHuffman && !isVarint && !isRaw) {
90-
fmt::print("ERROR: no recognised branch found (expected CMVPerTFCombined, CMVPerTFSparse, CMVPerTFHuffman, CMVPerTFVarint, or CMVPerTF)\n");
95+
if (!isQuantized && !isCombined && !isSparse && !isHuffman && !isVarint && !isRaw) {
96+
fmt::print("ERROR: no recognised branch found (expected CMVPerTFQuantized, CMVPerTFCombined, CMVPerTFSparse, CMVPerTFHuffman, CMVPerTFVarint, or CMVPerTF)\n");
9197
return arrCanvases;
9298
}
9399
const std::string branchFormat =
94-
isCombined ? "CMVPerTFCombined (sparse + compressed exact values)" : isSparse ? "CMVPerTFSparse (sparse)"
95-
: isHuffman ? "CMVPerTFHuffman (delta+zigzag+Huffman)"
96-
: isVarint ? "CMVPerTFVarint (delta+zigzag+varint)"
97-
: "CMVPerTF (raw)";
100+
isQuantized ? "CMVPerTFQuantized (sparse + quantized float symbols)"
101+
: isCombined ? "CMVPerTFCombined (sparse + compressed exact values)"
102+
: isSparse ? "CMVPerTFSparse (sparse)"
103+
: isHuffman ? "CMVPerTFHuffman (delta+zigzag+Huffman)"
104+
: isVarint ? "CMVPerTFVarint (delta+zigzag+varint)"
105+
: "CMVPerTF (raw)";
98106
fmt::print("Branch format: {}\n", branchFormat);
99107

100108
// branch setup — only one pointer is active depending on the detected format
109+
o2::tpc::CMVPerTFQuantized* tfQuantized = nullptr;
101110
o2::tpc::CMVPerTFCombined* tfCombined = nullptr;
102111
o2::tpc::CMVPerTFSparse* tfSparse = nullptr;
103112
o2::tpc::CMVPerTFHuffman* tfHuffman = nullptr;
104113
o2::tpc::CMVPerTFVarint* tfVarint = nullptr;
105114
o2::tpc::CMVPerTF* tfRaw = nullptr;
106115
// staging object for decompression
107-
CMVPerTF* tfDecoded = (isCombined || isSparse || isHuffman || isVarint) ? new CMVPerTF() : nullptr;
116+
CMVPerTF* tfDecoded = (isCombined || isSparse || isHuffman || isVarint || isQuantized) ? new CMVPerTF() : nullptr;
117+
std::vector<float> tfDecodedFloats;
108118

109-
if (isCombined) {
119+
if (isQuantized) {
120+
tree->SetBranchAddress("CMVPerTFQuantized", &tfQuantized);
121+
} else if (isCombined) {
110122
tree->SetBranchAddress("CMVPerTFCombined", &tfCombined);
111123
} else if (isSparse) {
112124
tree->SetBranchAddress("CMVPerTFSparse", &tfSparse);
@@ -125,7 +137,11 @@ TObjArray* drawCMV(std::string_view filename, std::string_view outDir)
125137

126138
// resolve to a unified pointer regardless of storage format
127139
const CMVPerTF* tf = nullptr;
128-
if (isCombined) {
140+
if (isQuantized) {
141+
tfQuantized->decompress(tfDecoded);
142+
tfQuantized->decompressToFloatBuffer(tfDecodedFloats);
143+
tf = tfDecoded;
144+
} else if (isCombined) {
129145
tfCombined->decompress(tfDecoded);
130146
tf = tfDecoded;
131147
} else if (isSparse) {
@@ -147,14 +163,17 @@ TObjArray* drawCMV(std::string_view filename, std::string_view outDir)
147163

148164
for (int cru = 0; cru < nCRUs; ++cru) {
149165
for (int tb = 0; tb < nTimeBins; ++tb) {
150-
h2d->Fill(tb, tf->getCMVFloat(cru, tb));
151-
// fmt::print("cru: {}, tb: {}, cmv: {}\n", cru, tb, tf->getCMVFloat(cru, tb));
166+
const float cmvValue = isQuantized ? tfDecodedFloats[cru * nTimeBins + tb] : tf->getCMVFloat(cru, tb);
167+
h2d->Fill(tb, cmvValue);
168+
h1d->Fill(cmvValue);
169+
fmt::print("cru: {}, tb: {}, cmv: {}\n", cru, tb, cmvValue);
152170
}
153171
}
154172
}
155173

156174
delete tfDecoded;
157175
tree->ResetBranchAddresses();
176+
delete tfQuantized;
158177
delete tfCombined;
159178
delete tfSparse;
160179
delete tfHuffman;
@@ -169,6 +188,12 @@ TObjArray* drawCMV(std::string_view filename, std::string_view outDir)
169188

170189
arrCanvases->Add(c);
171190

191+
auto* c1 = new TCanvas("cCMVDistribution", "");
192+
c1->SetLogy();
193+
h1d->Draw();
194+
195+
arrCanvases->Add(c1);
196+
172197
if (outDir.size()) {
173198
utils::saveCanvases(*arrCanvases, outDir, "png,pdf", "CMVCanvases.root");
174199
}

0 commit comments

Comments
 (0)