-
Notifications
You must be signed in to change notification settings - Fork 494
TPC: Processing of common mode values in O2 #15137
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
tubagundem
wants to merge
19
commits into
AliceO2Group:dev
Choose a base branch
from
tubagundem:TPC_CMV
base: dev
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
33e2fd0
TPC: Processing of common mode values in O2
tubagundem 940e41c
Added CMVContainer.cxx, fixed missing links and includes
tubagundem 2075879
Fix formatting
tubagundem 4471254
Removed unused includes, directly write the TTree object to CCDB with…
tubagundem bf10504
Changed the decoding and encoding of CMVs, removed grouping per side
tubagundem 5d1cc3b
Update the dataformat of CMV
tubagundem 0a4d8ac
Updated the CMVContainer, corrected the timestamp range for CCDB
tubagundem dc3ff00
Fix formatting
tubagundem a4a09b1
Removed factorize workflow, updated the distribute workflow accordingly
tubagundem 3ead34a
Fix formatting
tubagundem 82663fb
Extend error tracking in CMVToVectorSpec.cxx
tubagundem 37e12af
Replace CMVPerInterval with per TF TTree accumulation and raw uint16_…
tubagundem baf4d6d
Added delta+zigzag+varint compression, added drawCMV.C macro for visu…
tubagundem 3c207a6
Added small value zeroing, added `--use-compression` and `--cmv-zero-…
tubagundem 9fc3e05
Added sparse and HUffman encoding to the CMVContainer, updatet the dr…
tubagundem 5d720d4
Added CMVPerTFCombined to CMVContainer to combine sparse encoding wit…
tubagundem 8e5cf37
Added gaussian dynamic precision
tubagundem 27b73e3
Refactored CMVContainer, unified CMV compression in a flag based cont…
tubagundem d218dec
Added CMV workflow documentation to README and fixed CMV packet size …
tubagundem File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,122 @@ | ||
| // Copyright 2019-2020 CERN and copyright holders of ALICE O2. | ||
| // See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. | ||
| // All rights not expressly granted are reserved. | ||
| // | ||
| // This software is distributed under the terms of the GNU General Public | ||
| // License v3 (GPL Version 3), copied verbatim in the file "COPYING". | ||
| // | ||
| // In applying this license CERN does not waive the privileges and immunities | ||
| // granted to it by virtue of its status as an Intergovernmental Organization | ||
| // or submit itself to any jurisdiction. | ||
|
|
||
| /// @file CMV.h | ||
| /// @author Tuba Gündem, tuba.gundem@cern.ch | ||
| /// @brief Common mode values data format definition | ||
|
|
||
| /// The data is sent by the CRU as 256+16 bit words. The CMV data layout is as follows: | ||
| /// - 256-bit Header: [version:8][packetID:8][errorCode:8][magicWord:8][heartbeatOrbit:32][heartbeatBC:16][padding:176] | ||
| /// - 16-bit CMV value: [sign:1][I8F7:15] where bit 15 is the sign (1=positive, 0=negative) and the lower 15 bits are a fixed point I8F7 value (8 integer bits, 7 fractional bits) | ||
| /// Float conversion: sign ? (value & 0x7FFF) / 128.0 : -(value & 0x7FFF) / 128.0 | ||
|
|
||
| #ifndef ALICEO2_DATAFORMATSTPC_CMV_H | ||
| #define ALICEO2_DATAFORMATSTPC_CMV_H | ||
|
|
||
| #include <cstdint> | ||
| #include <cmath> | ||
|
|
||
| namespace o2::tpc::cmv | ||
| { | ||
|
|
||
| static constexpr uint32_t NTimeBinsPerPacket = 3564; ///< number of time bins (covering 8 heartbeats) | ||
| static constexpr uint32_t NPacketsPerTFPerCRU = 4; ///< 4 packets per timeframe | ||
| static constexpr uint32_t NTimeBinsPerTF = NTimeBinsPerPacket * NPacketsPerTFPerCRU; ///< maximum number of timebins per timeframe (14256) | ||
|
|
||
| /// Data padding: NTimeBinsPerPacket * sizeof(Data) = 3564 * 2 = 7128 bytes | ||
| static constexpr uint32_t DataSizeBytes = NTimeBinsPerPacket * sizeof(uint16_t); ///< 7128 bytes | ||
| static constexpr uint32_t DataPaddingBytes = (32 - (DataSizeBytes % 32)) % 32; ///< 8 bytes | ||
|
|
||
| /// Header definition of the CMVs | ||
| struct Header { | ||
| static constexpr uint8_t MagicWord = 0xDC; | ||
| union { | ||
| uint64_t word0 = 0; ///< bits 0 - 63 | ||
| struct { | ||
| uint8_t version : 8; ///< version | ||
| uint8_t packetID : 8; ///< packet id | ||
| uint8_t errorCode : 8; ///< errors | ||
| uint8_t magicWord : 8; ///< magic word | ||
| uint32_t heartbeatOrbit : 32; ///< first heart beat timing of the package | ||
| }; | ||
| }; | ||
| union { | ||
| uint64_t word1 = 0; ///< bits 64 - 127 | ||
| struct { | ||
| uint16_t heartbeatBC : 16; ///< first BC id of the package | ||
| uint16_t unused1 : 16; ///< reserved | ||
| uint32_t unused2 : 32; ///< reserved | ||
| }; | ||
| }; | ||
| union { | ||
| uint64_t word3 = 0; ///< bits 128 - 191 | ||
| struct { | ||
| uint64_t unused3 : 64; ///< reserved | ||
| }; | ||
| }; | ||
| union { | ||
| uint64_t word4 = 0; ///< bits 192 - 255 | ||
| struct { | ||
| uint64_t unused4 : 64; ///< reserved | ||
| }; | ||
| }; | ||
| }; | ||
|
|
||
| /// CMV single data container | ||
| struct Data { | ||
| uint16_t cmv{0}; ///< 16-bit signed fixed point value: bit 15 = sign (1=positive, 0=negative), bits 14-0 = I8F7 magnitude | ||
|
|
||
| uint16_t getCMV() const { return cmv; } ///< raw 16-bit integer representation | ||
| void setCMV(uint16_t value) { cmv = value; } ///< set raw 16-bit integer representation | ||
|
|
||
| // Decode to float: sign-magnitude with 7 fractional bits, range ±255.992 | ||
| float getCMVFloat() const | ||
| { | ||
| const bool positive = (cmv >> 15) & 1; // bit 15: sign (1=positive, 0=negative) | ||
| const float magnitude = (cmv & 0x7FFF) / 128.f; // lower 15 bits, shift right by 7 (divide by 2^7) | ||
| return positive ? magnitude : -magnitude; | ||
| } | ||
|
|
||
| // Encode from float: clamps magnitude to 15 bits, range ±255.992 | ||
| void setCMVFloat(float value) | ||
| { | ||
| const bool positive = (value >= 0.f); | ||
| const uint16_t magnitude = static_cast<uint16_t>(std::abs(value) * 128.f + 0.5f) & 0x7FFF; | ||
| cmv = (positive ? 0x8000 : 0x0000) | magnitude; | ||
| } | ||
| }; | ||
|
|
||
| /// CMV full data container: one packet carries NTimeBinsPerPacket CMV values followed by padding | ||
| /// Layout: Header (32 bytes) + Data[NTimeBinsPerPacket] (7128 bytes) + padding (8 bytes) = 7168 bytes total (224 * 32 = 7168) | ||
| /// The padding bytes at the end of the data array are rubbish/unused and must not be interpreted as CMV values | ||
| struct Container { | ||
| Header header; ///< CMV data header | ||
| Data data[NTimeBinsPerPacket]; ///< data values | ||
| uint8_t padding[DataPaddingBytes]{}; ///< trailing padding to align data to 32-byte boundary | ||
|
|
||
| // Header and data accessors | ||
| const Header& getHeader() const { return header; } | ||
| Header& getHeader() { return header; } | ||
|
|
||
| const Data* getData() const { return data; } | ||
| Data* getData() { return data; } | ||
|
|
||
| // Per timebin CMV accessors | ||
| uint16_t getCMV(uint32_t timeBin) const { return data[timeBin].getCMV(); } | ||
| void setCMV(uint32_t timeBin, uint16_t value) { data[timeBin].setCMV(value); } | ||
|
|
||
| float getCMVFloat(uint32_t timeBin) const { return data[timeBin].getCMVFloat(); } | ||
| void setCMVFloat(uint32_t timeBin, float value) { data[timeBin].setCMVFloat(value); } | ||
| }; | ||
|
|
||
| } // namespace o2::tpc::cmv | ||
|
|
||
| #endif | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
141 changes: 141 additions & 0 deletions
141
Detectors/TPC/calibration/include/TPCCalibration/CMVContainer.h
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,141 @@ | ||
| // Copyright 2019-2020 CERN and copyright holders of ALICE O2. | ||
| // See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. | ||
| // All rights not expressly granted are reserved. | ||
| // | ||
| // This software is distributed under the terms of the GNU General Public | ||
| // License v3 (GPL Version 3), copied verbatim in the file "COPYING". | ||
| // | ||
| // In applying this license CERN does not waive the privileges and immunities | ||
| // granted to it by virtue of its status as an Intergovernmental Organization | ||
| // or submit itself to any jurisdiction. | ||
|
|
||
| /// @file CMVContainer.h | ||
| /// @author Tuba Gündem, tuba.gundem@cern.ch | ||
| /// @brief Structs for storing CMVs to the CCDB | ||
|
|
||
| #ifndef ALICEO2_TPC_CMVCONTAINER_H_ | ||
| #define ALICEO2_TPC_CMVCONTAINER_H_ | ||
|
|
||
| #include <string> | ||
| #include <memory> | ||
| #include <vector> | ||
| #include <cstdint> | ||
|
|
||
| #include "TTree.h" | ||
| #include "TPCBase/CRU.h" | ||
| #include "DataFormatsTPC/CMV.h" | ||
|
|
||
| namespace o2::tpc | ||
| { | ||
|
|
||
| struct CMVPerTF; // forward declaration | ||
| struct CMVPerTFCompressed; // forward declaration | ||
|
|
||
| /// Bitmask flags describing which encoding stages are applied in CMVPerTFCompressed | ||
| struct CMVEncoding { | ||
| static constexpr uint8_t kNone = 0x00; ///< No compression — raw uint16 values stored flat | ||
| static constexpr uint8_t kSparse = 0x01; ///< Non-zero positions stored sparsely (varint-encoded deltas) | ||
| static constexpr uint8_t kDelta = 0x02; ///< Delta coding between consecutive values (dense only) | ||
| static constexpr uint8_t kZigzag = 0x04; ///< Zigzag encoding of deltas or signed values | ||
| static constexpr uint8_t kVarint = 0x08; ///< Varint compression of the value stream | ||
| static constexpr uint8_t kHuffman = 0x10; ///< Canonical Huffman compression of the value stream | ||
| }; | ||
|
|
||
| /// Single compressed representation for one TF across all CRUs, stored in a TTree | ||
| /// mFlags is a bitmask of CMVEncoding values that fully describes the encoding pipeline | ||
| /// mData holds the encoded payload whose binary layout depends on mFlags: | ||
| /// | ||
| /// Dense path (!kSparse): | ||
| /// kZigzag absent → N × uint16_t LE (raw values, CRU-major order) | ||
| /// kZigzag + kVarint → N × varint(zigzag(delta(signed(raw)))) | ||
| /// kZigzag + kHuffman → [Huffman table] + [bitstream] of zigzag(delta(signed(raw))) | ||
| /// | ||
| /// Sparse path (kSparse): | ||
| /// 4 bytes LE uint32_t : posStreamSize | ||
| /// posStream: for each CRU: varint(N), N × varint(tb_delta) | ||
| /// valStream (one entry per non-zero): | ||
| /// default → uint16_t LE raw value | ||
| /// kZigzag + kVarint → varint(zigzag(signed(raw))) | ||
| /// kZigzag + kHuffman → [Huffman table] + [bitstream] of zigzag(signed(raw)) | ||
| struct CMVPerTFCompressed { | ||
| uint32_t firstOrbit{0}; ///< First orbit of this TF | ||
| uint16_t firstBC{0}; ///< First bunch crossing of this TF | ||
| uint8_t mFlags{0}; ///< Bitmask of CMVEncoding values | ||
|
|
||
| std::vector<uint8_t> mData; ///< Encoded payload | ||
|
|
||
| /// Restore a CMVPerTF from this compressed object into *cmv (must not be null) | ||
| void decompress(CMVPerTF* cmv) const; | ||
|
|
||
| /// Serialise into a TTree; each Fill() call appends one entry (one TF) | ||
| std::unique_ptr<TTree> toTTree() const; | ||
|
|
||
| private: | ||
| /// Decode the sparse position stream; advances ptr past the position block | ||
| /// Returns (cru, timeBin) pairs for every non-zero entry, in CRU-major order | ||
| static std::vector<std::pair<int, uint32_t>> decodeSparsePositions(const uint8_t*& ptr, const uint8_t* end); | ||
|
|
||
| /// Decode the value stream into raw uint32_t symbols | ||
| /// Dispatches to Huffman, varint, or raw uint16 based on flags | ||
| static std::vector<uint32_t> decodeValueStream(const uint8_t*& ptr, const uint8_t* end, uint32_t N, uint8_t flags); | ||
|
|
||
| /// Apply inverse zigzag and scatter decoded values into the sparse positions of *cmv | ||
| static void decodeSparseValues(const std::vector<uint32_t>& symbols, | ||
| const std::vector<std::pair<int, uint32_t>>& positions, | ||
| uint8_t flags, CMVPerTF* cmv); | ||
|
|
||
| /// Apply inverse zigzag and inverse delta, then fill the full dense CMV array in *cmv | ||
| static void decodeDenseValues(const std::vector<uint32_t>& symbols, uint8_t flags, CMVPerTF* cmv); | ||
|
|
||
| public: | ||
| ClassDefNV(CMVPerTFCompressed, 1) | ||
| }; | ||
|
|
||
| /// CMV data for one TF across all CRUs | ||
| /// Raw 16-bit CMV values are stored in a flat C array indexed as [cru * NTimeBinsPerTF + timeBin] | ||
| struct CMVPerTF { | ||
| uint32_t firstOrbit{0}; ///< First orbit of this TF, from heartbeatOrbit of the first CMV packet | ||
| uint16_t firstBC{0}; ///< First bunch crossing of this TF, from heartbeatBC of the first CMV packet | ||
|
|
||
| // Raw 16-bit CMV values, flat array indexed as [cru * NTimeBinsPerTF + timeBin] | ||
| uint16_t mDataPerTF[CRU::MaxCRU * cmv::NTimeBinsPerTF]{}; | ||
|
|
||
| /// Return the raw 16-bit CMV value for a given CRU and timebin within this TF | ||
| uint16_t getCMV(const int cru, const int timeBin) const; | ||
|
|
||
| /// Return the float CMV value for a given CRU and timebin within this TF | ||
| float getCMVFloat(const int cru, const int timeBin) const; | ||
|
|
||
| /// Zero out raw CMV values whose float magnitude is below threshold | ||
| void zeroSmallValues(float threshold = 1.0f); | ||
|
|
||
| /// Round values to the nearest integer ADC for all values whose rounded magnitude is <= threshold | ||
| void roundToIntegers(uint16_t threshold); | ||
|
|
||
| /// Quantise |v| with a Gaussian-CDF recovery profile: | ||
| /// Coarse decimal-style precision below and around mean, then a smooth return to the full native I8F7 precision as the magnitude increases with width sigma | ||
| void trimGaussianPrecision(float mean, float sigma); | ||
|
|
||
| /// Compress this object into a CMVPerTFCompressed using the encoding pipeline described by flags | ||
| /// Quantisation (trimGaussianPrecision / roundToIntegers / zeroSmallValues) should be applied to this object before calling compress(); it is not part of the flags pipeline | ||
| CMVPerTFCompressed compress(uint8_t flags) const; | ||
|
|
||
| /// Serialise into a TTree; each Fill() call appends one entry (one TF) | ||
| std::unique_ptr<TTree> toTTree() const; | ||
|
|
||
| /// Write the TTree to a ROOT file | ||
| static void writeToFile(const std::string& filename, const std::unique_ptr<TTree>& tree); | ||
|
|
||
| private: | ||
| static int32_t cmvToSigned(uint16_t raw); ///< Sign-magnitude uint16_t → signed integer | ||
| static uint16_t quantizeBelowThreshold(uint16_t raw, float quantizationMean, float quantizationSigma); ///< Quantise sub-threshold values with a Gaussian-shaped recovery to full precision | ||
| static uint32_t zigzagEncode(int32_t value); ///< Zigzag encode | ||
| static void encodeVarintInto(uint32_t value, std::vector<uint8_t>& out); ///< Varint encode | ||
|
|
||
| public: | ||
| ClassDefNV(CMVPerTF, 1) | ||
| }; | ||
|
|
||
| } // namespace o2::tpc | ||
|
|
||
| #endif // ALICEO2_TPC_CMVCONTAINER_H_ |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.