-
Notifications
You must be signed in to change notification settings - Fork 490
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
Draft
tubagundem
wants to merge
1
commit 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.
+2,006
−2
Draft
Changes from all commits
Commits
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,123 @@ | ||
| // 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: [CMV:16] | ||
|
|
||
| #ifndef ALICEO2_DATAFORMATSTPC_CMV_H | ||
| #define ALICEO2_DATAFORMATSTPC_CMV_H | ||
|
|
||
| #include <bitset> | ||
|
|
||
| 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) | ||
| static constexpr uint32_t SignificantBits = 2; ///< number of bits used for floating point precision | ||
| static constexpr float FloatConversion = 1.f / float(1 << SignificantBits); ///< conversion factor from integer representation to float | ||
|
|
||
| /// Header definition of the CMVs | ||
| struct Header { | ||
| static constexpr uint8_t MagicWord = 0xDC; | ||
| union { | ||
| uint32_t word0 = 0; ///< bits 0 - 31 | ||
| struct { | ||
| uint8_t version : 8; ///< version | ||
| uint8_t packetID : 8; ///< packet id | ||
| uint8_t errorCode : 8; ///< errors | ||
| uint8_t magicWord : 8; ///< magic word | ||
| }; | ||
| }; | ||
| union { | ||
| uint32_t word1 = 0; ///< bits 32 - 63 | ||
| struct { | ||
| uint32_t heartbeatOrbit : 32; ///< first heart beat timing of the package | ||
| }; | ||
| }; | ||
| union { | ||
| uint16_t word2 = 0; ///< bits 64 - 79 | ||
| struct { | ||
| uint16_t heartbeatBC : 16; ///< first BC id of the package | ||
| }; | ||
| }; | ||
| union { | ||
| uint16_t word3 = 0; ///< bits 80 - 95 | ||
| struct { | ||
| uint16_t unused1 : 16; ///< reserved | ||
| }; | ||
| }; | ||
| union { | ||
| uint32_t word4 = 0; ///< bits 96 - 127 | ||
| struct { | ||
| uint32_t unused2 : 32; ///< reserved | ||
| }; | ||
| }; | ||
| union { | ||
| uint64_t word5 = 0; ///< bits 128 - 191 | ||
| struct { | ||
| uint64_t unused3 : 64; ///< reserved | ||
| }; | ||
| }; | ||
| union { | ||
| uint64_t word6 = 0; ///< bits 192 - 255 | ||
| struct { | ||
| uint64_t unused4 : 64; ///< reserved | ||
| }; | ||
| }; | ||
| }; | ||
|
|
||
| /// CMV single data container | ||
| struct Data { | ||
| uint16_t CMV{0}; ///< 16bit ADC value | ||
|
|
||
| // Raw integer accessors | ||
| uint16_t getCMV() const { return CMV; } | ||
| void setCMV(uint16_t value) { CMV = value; } | ||
|
|
||
| // Float helpers using SignificantBits for fixed-point conversion | ||
| float getCMVFloat() const { return static_cast<float>(CMV) * FloatConversion; } | ||
| void setCMVFloat(float value) | ||
| { | ||
| // round to nearest representable fixed-point value | ||
| setCMV(uint32_t((value + 0.5f * FloatConversion) / FloatConversion)); | ||
| } | ||
| }; | ||
|
|
||
| /// CMV full data container: one packet carries NTimeBinsPerPacket | ||
| struct Container { | ||
| Header header; ///< CMV data header | ||
| Data data[NTimeBinsPerPacket]; ///< data values | ||
|
|
||
| // 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-time-bin 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
174 changes: 174 additions & 0 deletions
174
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,174 @@ | ||
| // 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 Struct for storing CMVs to the CCDB | ||
|
|
||
| #ifndef ALICEO2_TPC_CMVCONTAINER_H_ | ||
| #define ALICEO2_TPC_CMVCONTAINER_H_ | ||
|
|
||
| #include <vector> | ||
| #include <string> | ||
| #include <memory> | ||
| #include <stdexcept> | ||
|
|
||
| #include <fmt/format.h> | ||
|
|
||
| #include "TTree.h" | ||
| #include "TFile.h" | ||
|
|
||
| #include "DataFormatsTPC/CMV.h" | ||
|
|
||
| namespace o2::tpc | ||
| { | ||
|
|
||
| /// CMVContainer: accumulator for one aggregation interval | ||
| struct CMVContainer { | ||
|
|
||
| uint32_t nTFs{0}; ///< number of TFs accumulated | ||
| uint32_t nCRUs{0}; ///< number of contributing CRUs | ||
| long firstTF{0}; ///< first TF counter in this aggregation interval | ||
|
|
||
| std::vector<float> cmvValues{}; ///< CMV float values | ||
| std::vector<uint32_t> cru{}; ///< CRU indices | ||
| std::vector<uint32_t> timebin{}; ///< absolute timebins within the TF | ||
| std::vector<uint32_t> tf{}; ///< TF counters | ||
|
|
||
| /// Pre-allocate storage for the expected number of entries: expectedTFs × expectedCRUs × NTimeBinsPerTF | ||
| void reserve(uint32_t expectedTFs, uint32_t expectedCRUs) | ||
| { | ||
| const std::size_t n = static_cast<std::size_t>(expectedTFs) * expectedCRUs * o2::tpc::cmv::NTimeBinsPerTF; | ||
| cmvValues.reserve(n); | ||
| cru.reserve(n); | ||
| timebin.reserve(n); | ||
| tf.reserve(n); | ||
| } | ||
|
|
||
| /// Append one (cmv, cru, timebin, tf) tuple | ||
| void addEntry(float cmvVal, uint32_t cruID, uint32_t tb, uint32_t tfCounter) | ||
| { | ||
| cmvValues.push_back(cmvVal); | ||
| cru.push_back(cruID); | ||
| timebin.push_back(tb); | ||
| tf.push_back(tfCounter); | ||
| } | ||
|
|
||
| /// Append one full CRU packet (NTimeBinsPerPacket consecutive timebins) | ||
| /// \param packet pointer to NTimeBinsPerPacket floats | ||
| /// \param cruID CRU index | ||
| /// \param tbOffset absolute timebin of the first sample in this packet | ||
| /// \param tfCounter TF counter | ||
| void addPacket(const float* packet, uint32_t cruID, uint32_t tbOffset, uint32_t tfCounter) | ||
| { | ||
| for (uint32_t tb = 0; tb < o2::tpc::cmv::NTimeBinsPerPacket; ++tb) { | ||
| addEntry(packet[tb], cruID, tbOffset + tb, tfCounter); | ||
| } | ||
| } | ||
|
|
||
| std::size_t size() const { return cmvValues.size(); } | ||
| bool empty() const { return cmvValues.empty(); } | ||
|
|
||
| /// Clear all data and reset counters | ||
| void clear() | ||
| { | ||
| cmvValues.clear(); | ||
| cru.clear(); | ||
| timebin.clear(); | ||
| tf.clear(); | ||
| nTFs = 0; | ||
| nCRUs = 0; | ||
| firstTF = 0; | ||
| } | ||
|
|
||
| std::string summary() const | ||
| { | ||
| return fmt::format("CMVContainer: {} entries, {} TFs, {} CRUs, firstTF={}", | ||
| size(), nTFs, nCRUs, firstTF); | ||
| } | ||
|
|
||
| /// Build an in-memory TTree with one branch per field and one entry per tuple | ||
| std::unique_ptr<TTree> toTTree() const | ||
| { | ||
| const std::size_t n = size(); | ||
| if (n == 0) { | ||
| throw std::runtime_error("CMVContainer::toTTree() called on empty container"); | ||
| } | ||
|
|
||
| auto tree = std::make_unique<TTree>("CMVTree", "TPC common mode values"); | ||
| tree->SetAutoSave(0); | ||
|
|
||
| // Point branches directly at the vector data — single Fill() call writes all rows | ||
| float* pCmv = const_cast<float*>(cmvValues.data()); | ||
| uint32_t* pCru = const_cast<uint32_t*>(cru.data()); | ||
| uint32_t* pTimebin = const_cast<uint32_t*>(timebin.data()); | ||
| uint32_t* pTf = const_cast<uint32_t*>(tf.data()); | ||
|
|
||
| tree->Branch("cmv", pCmv, fmt::format("cmv[{}]/F", n).c_str()); | ||
| tree->Branch("cru", pCru, fmt::format("cru[{}]/i", n).c_str()); | ||
| tree->Branch("timebin", pTimebin, fmt::format("timebin[{}]/i", n).c_str()); | ||
| tree->Branch("tf", pTf, fmt::format("tf[{}]/i", n).c_str()); | ||
|
|
||
| tree->Fill(); | ||
| return tree; | ||
| } | ||
|
|
||
| /// Write the container as a TTree inside a TFile on disk | ||
| /// \param filename path to the output ROOT file | ||
| void writeToFile(const std::string& filename) const | ||
| { | ||
| TFile f(filename.c_str(), "RECREATE"); | ||
| if (f.IsZombie()) { | ||
| throw std::runtime_error(fmt::format("CMVContainer::writeToFile: cannot open '{}'", filename)); | ||
| } | ||
| auto tree = toTTree(); | ||
| tree->Write(); | ||
| f.Close(); | ||
| } | ||
|
|
||
| /// Restore a CMVContainer from a TTree previously written by toTTree() | ||
| static CMVContainer fromTTree(TTree* tree) | ||
| { | ||
| if (!tree) { | ||
| throw std::runtime_error("CMVContainer::fromTTree: null TTree pointer"); | ||
| } | ||
|
|
||
| CMVContainer c; | ||
| const Long64_t nEntries = tree->GetEntries(); | ||
| if (nEntries <= 0) { | ||
| return c; | ||
| } | ||
|
|
||
| // Read the array branches back into vectors in one GetEntry() call | ||
| std::vector<float> bCmv(nEntries); | ||
| std::vector<uint32_t> bCru(nEntries), bTimebin(nEntries), bTf(nEntries); | ||
|
|
||
| tree->SetBranchAddress("cmv", bCmv.data()); | ||
| tree->SetBranchAddress("cru", bCru.data()); | ||
| tree->SetBranchAddress("timebin", bTimebin.data()); | ||
| tree->SetBranchAddress("tf", bTf.data()); | ||
|
|
||
| tree->GetEntry(0); | ||
|
|
||
| c.cmvValues = std::move(bCmv); | ||
| c.cru = std::move(bCru); | ||
| c.timebin = std::move(bTimebin); | ||
| c.tf = std::move(bTf); | ||
|
|
||
| return c; | ||
| } | ||
|
|
||
| ClassDefNV(CMVContainer, 1) | ||
| }; | ||
|
|
||
| } // namespace o2::tpc | ||
|
|
||
| #endif // ALICEO2_TPC_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
31 changes: 31 additions & 0 deletions
31
Detectors/TPC/workflow/include/TPCWorkflow/CMVToVectorSpec.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,31 @@ | ||
| // 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 CMVToVectorSpec.h | ||
| /// @author Tuba Gündem, tuba.gundem@cern.ch | ||
| /// @brief Processor to convert CMVs to a vector in a CRU | ||
|
|
||
| #ifndef TPC_CMVToVectorSpec_H_ | ||
| #define TPC_CMVToVectorSpec_H_ | ||
|
|
||
| #include "Framework/DataProcessorSpec.h" | ||
| #include <string_view> | ||
|
|
||
| namespace o2::tpc | ||
| { | ||
|
|
||
| /// create a processor spec | ||
| /// convert CMV raw values to a vector in a CRU | ||
| o2::framework::DataProcessorSpec getCMVToVectorSpec(const std::string inputSpec, std::vector<uint32_t> const& crus); | ||
|
|
||
| } // end namespace o2::tpc | ||
|
|
||
| #endif // TPC_CMVToVectorSpec_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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be also declared in the Detectors/TPC/calibration/src/TPCCalibrationLinkDef.h