diff --git a/algo/CMakeLists.txt b/algo/CMakeLists.txt index 5eff2e5606eb1168612012299dcf42894acace4f..a04c55b1fd5e5fcf46244cefa9ffab4661590c03 100644 --- a/algo/CMakeLists.txt +++ b/algo/CMakeLists.txt @@ -114,6 +114,9 @@ set(SRCS detectors/much/ReadoutConfig.cxx detectors/much/Unpack.cxx detectors/much/UnpackMS.cxx + detectors/mvd/ReadoutConfig.cxx + detectors/mvd/Unpack.cxx + detectors/mvd/UnpackMS.cxx detectors/tof/HitFinder.cxx detectors/tof/Calibrate.cxx detectors/tof/Clusterizer.cxx @@ -346,6 +349,7 @@ install(DIRECTORY base/gpu TYPE INCLUDE FILES_MATCHING PATTERN "*.h") install(DIRECTORY data/sts TYPE INCLUDE FILES_MATCHING PATTERN "*.h") install(DIRECTORY detectors/bmon TYPE INCLUDE FILES_MATCHING PATTERN "*.h") install(DIRECTORY detectors/much TYPE INCLUDE FILES_MATCHING PATTERN "*.h") +install(DIRECTORY detectors/mvd TYPE INCLUDE FILES_MATCHING PATTERN "*.h") install(DIRECTORY detectors/sts TYPE INCLUDE FILES_MATCHING PATTERN "*.h") install(DIRECTORY detectors/tof TYPE INCLUDE FILES_MATCHING PATTERN "*.h") install(DIRECTORY detectors/trd TYPE INCLUDE FILES_MATCHING PATTERN "*.h") diff --git a/algo/base/AuxDigiData.h b/algo/base/AuxDigiData.h index e464da7e281fbb57a33557ccf43ff98947fd2767..25b221e8a245d9bc899fadfd894c8dc00820e111 100644 --- a/algo/base/AuxDigiData.h +++ b/algo/base/AuxDigiData.h @@ -17,6 +17,7 @@ #include "tof/UnpackMS.h" #include "trd/UnpackMS.h" #include "trd2d/UnpackMS.h" +#include "mvd/UnpackMS.h" #include <vector> @@ -32,5 +33,6 @@ namespace cbm::algo UnpackAux<tof::UnpackAuxData> fTof; UnpackAux<trd::UnpackAuxData> fTrd; UnpackAux<trd2d::UnpackAuxData> fTrd2d; + UnpackAux<mvd::UnpackAuxData> fMvd; }; } // namespace cbm::algo diff --git a/algo/base/DigiData.cxx b/algo/base/DigiData.cxx index 79fd5a4836022d2caae819e0715f3fcf0a1ecfe7..fab5281a5d13fce0a2ae8fe98760aa7d705238a1 100644 --- a/algo/base/DigiData.cxx +++ b/algo/base/DigiData.cxx @@ -14,6 +14,7 @@ DigiData::~DigiData() {} DigiData::DigiData(const CbmDigiData& storable) : fSts(ToPODVector(storable.fSts.fDigis)) , fMuch(ToPODVector(storable.fMuch.fDigis)) + , fMvd(ToPODVector(storable.fMvd.fDigis)) , fTof(ToPODVector(storable.fTof.fDigis)) , fBmon(ToPODVector(storable.fBmon.fDigis)) , fTrd(ToPODVector(storable.fTrd.fDigis)) @@ -29,6 +30,7 @@ size_t DigiData::Size(ECbmModuleId system) const switch (system) { case ECbmModuleId::kSts: return fSts.size(); case ECbmModuleId::kMuch: return fMuch.size(); + case ECbmModuleId::kMvd: return fMvd.size(); case ECbmModuleId::kTof: return fTof.size(); case ECbmModuleId::kBmon: return fBmon.size(); case ECbmModuleId::kTrd: return fTrd.size(); @@ -42,13 +44,13 @@ size_t DigiData::Size(ECbmModuleId system) const size_t DigiData::TotalSize() const { - return fSts.size() + fMuch.size() + fTof.size() + fBmon.size() + fTrd.size() + fTrd2d.size() + fRich.size() + return fSts.size() + fMuch.size() + fMvd.size() + fTof.size() + fBmon.size() + fTrd.size() + fTrd2d.size() + fRich.size() + fPsd.size() + fFsd.size(); } size_t DigiData::TotalSizeBytes() const { - return sizeof(CbmStsDigi) * fSts.size() + sizeof(CbmMuchDigi) * fMuch.size() + sizeof(CbmTofDigi) * fTof.size() + return sizeof(CbmStsDigi) * fSts.size() + sizeof(CbmMuchDigi) * fMuch.size() + sizeof(CbmMvdDigi) * fMvd.size() + sizeof(CbmTofDigi) * fTof.size() + sizeof(CbmBmonDigi) * fBmon.size() + sizeof(CbmTrdDigi) * fTrd.size() + sizeof(CbmTrdDigi) * fTrd2d.size() + sizeof(CbmRichDigi) * fRich.size() + sizeof(CbmPsdDigi) * fPsd.size() + sizeof(CbmFsdDigi) * fFsd.size(); } @@ -64,10 +66,14 @@ CbmDigiData DigiData::ToStorable() const { .fDigis = ToStdVector(fSts), }, - .fMuch = + .fMuch = { .fDigis = ToStdVector(fMuch), }, + .fMvd = + { + .fDigis = ToStdVector(fMvd), + }, .fRich = { .fDigis = ToStdVector(fRich), diff --git a/algo/base/DigiData.h b/algo/base/DigiData.h index 09b82d933478c57b65087b93e1d0a799120d287b..1b4376a6a051dc4177dbf8ce7727d23c24d556ba 100644 --- a/algo/base/DigiData.h +++ b/algo/base/DigiData.h @@ -10,6 +10,7 @@ #include "CbmEventTriggers.h" #include "CbmFsdDigi.h" #include "CbmMuchDigi.h" +#include "CbmMvdDigi.h" #include "CbmPsdDigi.h" #include "CbmRichDigi.h" #include "CbmStsDigi.h" @@ -32,6 +33,7 @@ namespace cbm::algo struct DigiData { PODVector<CbmStsDigi> fSts; ///< Unpacked STS digis PODVector<CbmMuchDigi> fMuch; ///< Unpacked MUCH digis + PODVector<CbmMvdDigi> fMvd; ///< Unpacked MVD digis PODVector<CbmTofDigi> fTof; ///< Unpacked TOF digis PODVector<CbmBmonDigi> fBmon; ///< Unpacked Bmon digis PODVector<CbmTrdDigi> fTrd; ///< Unpacked TRD digis diff --git a/algo/data/CMakeLists.txt b/algo/data/CMakeLists.txt index 717ba53896c880649c4c07c1ff010fad8c14551b..c1e3e6339b41a3cc8fd77b5637a0beecf76a7352 100644 --- a/algo/data/CMakeLists.txt +++ b/algo/data/CMakeLists.txt @@ -18,6 +18,9 @@ set(SRCS ${OFFLINE_DATA_DIR}/much/CbmMuchDigi.cxx ${OFFLINE_DATA_DIR}/much/CbmMuchAddress.cxx + ${OFFLINE_DATA_DIR}/mvd/CbmMvdDigi.cxx + # ${OFFLINE_DATA_DIR}/mvd/CbmMvdAddress.cxx + ${OFFLINE_DATA_DIR}/trd/CbmTrdDigi.cxx ${OFFLINE_DATA_DIR}/trd/CbmTrdRawMessageSpadic.cxx @@ -35,6 +38,7 @@ set(SRCS ${OFFLINE_DATA_DIR}/raw/CriGet4Mess001.cxx ${OFFLINE_DATA_DIR}/raw/StsXyterMessage.cxx + # ${OFFLINE_DATA_DIR}/raw/MimosisMessage.cxx // implement this for mimosis ) add_library(OnlineData SHARED ${SRCS}) @@ -46,6 +50,7 @@ target_include_directories(OnlineData PUBLIC ${OFFLINE_DATA_DIR}/sts PUBLIC ${OFFLINE_DATA_DIR}/rich PUBLIC ${OFFLINE_DATA_DIR}/much + PUBLIC ${OFFLINE_DATA_DIR}/mvd PUBLIC ${OFFLINE_DATA_DIR}/trd PUBLIC ${OFFLINE_DATA_DIR}/tof PUBLIC ${OFFLINE_DATA_DIR}/psd diff --git a/algo/detectors/mvd/ReadoutConfig.cxx b/algo/detectors/mvd/ReadoutConfig.cxx new file mode 100644 index 0000000000000000000000000000000000000000..ca4555caefbedbcdf785936f1ff8551a3f52c2b1 --- /dev/null +++ b/algo/detectors/mvd/ReadoutConfig.cxx @@ -0,0 +1,222 @@ +/* Copyright (C) 2017-2021 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Pierre-Alain Loizeau, Ajit Kumar, Florian Uhlig [committer] */ + +#include "ReadoutConfig.h" + +#include "AlgoFairloggerCompat.h" +// #include "CbmMvdAddress.h" // not needed for the time being + +#include <bitset> +#include <unordered_set> + +using namespace std; + +namespace cbm::algo::mvd +{ + // --- Constructor ------------------------------------------------------------------ + ReadoutConfig::ReadoutConfig() { Init(); } + // ------------------------------------------------------------------------------------ + + // --- Destructor ----------------------------------------------------------------- + ReadoutConfig::~ReadoutConfig() {} + // ------------------------------------------------------------------------------------ + + // --- Equipment IDs -------------------------------------------------------------- + std::vector<uint16_t> ReadoutConfig::GetEquipmentIds() + { + std::vector<uint16_t> result; + for (auto& entry : fReadoutMap) + result.push_back(entry.first); + return result; + } + // ------------------------------------------------------------------------------------ + + // --- Number of elinks for a component / equipment ------------------------------- + size_t ReadoutConfig::GetNumElinks(uint16_t equipmentId) + { + size_t result = 0; + auto it = fReadoutMap.find(equipmentId); + if (it != fReadoutMap.end()) result = fReadoutMap[equipmentId].size(); + return result; + } + // ------------------------------------------------------------------------------------ + + // --- Mapping (equimentId, elink) -> address[channel] ------------------------------ + std::vector<uint32_t> ReadoutConfig::Map(uint16_t equipmentId, uint16_t elinkId) + { + std::vector<uint32_t> result; + auto equipIter = fReadoutMap.find(equipmentId); + if (equipIter != fReadoutMap.end()) { + if (elinkId < equipIter->second.size()) { + result = equipIter->second.at(elinkId); + } + } + return result; + } + // ------------------------------------------------------------------------------------ + + // --- Mapping (equimentId, elink) -> (vector of mask flags) ------------------------ + std::vector<bool> ReadoutConfig::MaskMap(uint16_t equipmentId, uint16_t elinkId) + { + std::vector<bool> result; + auto equipIter = fMaskMap.find(equipmentId); + if (equipIter != fMaskMap.end()) { + auto elinkMap = equipIter->second; + auto elinkIter = elinkMap.find(elinkId); + if (elinkIter != elinkMap.end()) { + result = elinkIter->second; + } + } + return result; + } + // ------------------------------------------------------------------------------------ + + + void ReadoutConfig::Init() + { + // This here refers to the mCBM 2022 setup. + // Taken from CbmMvdUnpackPar in combination with macro/beamtime/mcbm2022/mMuchParUpto26052022.par + + // Array to hold the unique IDs (equipment ID) for all MUCH DPBs + uint16_t eqId[numComp] = {0x2001, 0x2002}; + + // Mapping of eLink to FEB number within CROB. If -1, elink not used. + // This mapping is the same for each component. + const int16_t elink2Sensor[numElinksPerCrob] = {0}; + + // Constructing the map (equipmentId, eLink, channel) -> (MUCH address) + uint16_t numElinksPerComp = numCrobPerComp * numElinksPerCrob; + + for (uint16_t comp = 0; comp < numComp; comp++) { + uint16_t equipment = eqId[comp]; + fReadoutMap[equipment].resize(numElinksPerComp); + for (uint16_t crob = 0; crob < numCrobPerComp; crob++) { + for (uint16_t elink = 0; elink < numElinksPerCrob; elink++) { + + // fReadoutMap[equipment][elink].resize(numChanPerAsic); + // uint16_t elinkId = numElinksPerCrob * crob + elink; // elink within component + + // Skip unconnected FEB slots + } //# elink + } //# CROB + } //# component + } + + //To do address need to be checked carefully + // uint32_t ReadoutConfig::CreateMuchAddress(uint32_t dpbidx, int32_t iFebId, uint32_t usChan) + // { + // // For generating Station number (GEM1 station = 0, GEM2 station = 1 and RPC station = 2) + // /// Below FebID is according to FEB Position in Module GEM A or Module GEM B (Carefully write MUCH Par file) + // int32_t station = -1; + // int32_t layer = -1; + // if (iFebId == -7) //Pulser FEB + // { + // station = 6; // for Pulser + // layer = 0; // + // } + // else if (dpbidx == 0 || dpbidx == 1 || dpbidx == 2) //First 3 DPBs are for GEM-1 + // { + // station = 0; // for mCBM setup + // layer = 0; // Station 0 for GEM-A and station 1 for Module GEM-B + // } + // else if (dpbidx == 4 || dpbidx == 5 || dpbidx == 6) //Last 3 DPBs are for GEM-2 after 10/04/2022 + // { + // station = 1; // for mCBM setup station + // layer = 0; // 0 for Module GEM-A and 1 for Module GEM-B + // } + // else if (dpbidx == 3) { + // station = 2; // for mCBM setup only one station + // layer = 0; // + // } + // else { + // LOG(warning) << "Wrong DPB Id x " << dpbidx; + // return 0; + // } //No address generated. + + // //Common layer side module will be 0 only for mCBM 2022 + // int32_t layerside = 0; // 0 in mCBM + // int32_t sModule = 0; // 0 in mCBM + + // int32_t sSector = -9; //channel values are from 0-96 therefore as per CbmMuchAddress it is sector + // int32_t sChannel = -9; //sector values are from 0-22 therefore as per CbmMuchAddress it is channel + + // // Channel flip in stsXYTER v2.1 : 0<->1, 2<->3, 3<->4 and so on... + // auto fiFlag = 1; //! Switch to smx2.0/smx2.1 data-> fiFlag = 0 for 2.0 and fiFlag = 1 for 2.1 + // if (fiFlag == 1) { + // if (usChan % 2 == 0) + // usChan = usChan + 1; + // else + // usChan = usChan - 1; + // } + + // // PadX means CHANNEL for CbmMuchAddress + // // PadY means SECTOR for CbmMuchAddress + // // Due to two FLEX cable connected to single FEB; First Flex Connector number + // // 1 - 63 and second flex connector number 64 - 127 + // //in few FEB positioned these flex connectors are flipped so below correction applied. + // if (station == 0 && fiFlag == 1 && layer == 0) { // First layer (GEM1) has old readout PCB + // if (iFebId == 0 || iFebId == 1 || iFebId == 2 || iFebId == 3 || iFebId == 4 || iFebId == 8 || iFebId == 9 + // || iFebId == 10 || iFebId == 11 || iFebId == 17) { + // sChannel = GetPadXA(iFebId, 127 - usChan); + // sSector = GetPadYA(iFebId, 127 - usChan); + // } + // else { + // sChannel = GetPadXA(iFebId, usChan); + // sSector = GetPadYA(iFebId, usChan); + // } + // } + // else if (station == 1 && fiFlag == 1 && layer == 0) { // second layer (GEM2) has new readout PCB + // if (iFebId == 0 || iFebId == 1 || iFebId == 2 || iFebId == 3 || iFebId == 4 || iFebId == 8 || iFebId == 9 + // || iFebId == 10 || iFebId == 11 || iFebId == 17) { + // sChannel = GetPadXB(iFebId, 127 - usChan); + // sSector = GetPadYB(iFebId, 127 - usChan); + // } + // else { + // sChannel = GetPadXB(iFebId, usChan); + // sSector = GetPadYB(iFebId, usChan); + // } + // } + // else if (station == 0 || station == 1) { // Both layer with same type of PCB (Probably below is not necessary) + // if (iFebId == 0 || iFebId == 1 || iFebId == 2 || iFebId == 3 || iFebId == 4 || iFebId == 8 || iFebId == 9 + // || iFebId == 10 || iFebId == 11 || iFebId == 17) { + // sChannel = GetPadXA(iFebId, 127 - usChan); + // sSector = GetPadYA(iFebId, 127 - usChan); + // } + // else { + // sChannel = GetPadXA(iFebId, usChan); + // sSector = GetPadYA(iFebId, usChan); + // } + // } + // else if (station == 2) { //For RPC + // sChannel = GetPadXRpc(iFebId, usChan); + // sSector = GetPadYRpc(iFebId, usChan); + // } + // else // Checking for the not connected or misconnected pads + // { + // LOG(debug) << "Sector " << sSector << " channel " << sChannel << " is not connected or misconnected to pad. " + // << " corresponding Feb is " << iFebId << " and uschan " << usChan << " DPB id " << dpbidx + // << " Skipping this hit message."; + // return 0; + // } + + // //Creating Unique address of the particular channel of GEM + // uint32_t address = CbmMuchAddress::GetAddress(station, layer, layerside, sModule, sSector, sChannel); + // // LOG(debug) << "Raw address " << address; + // address = CbmMuchAddress::SetElementId(address, 1, station); + // // LOG(debug) << "After adding station " << address << " binary " << std::bitset<32>(address); + // address = CbmMuchAddress::SetElementId(address, 2, layer); + // // LOG(debug) << "After adding Layer " << address << " binary " << std::bitset<32>(address); + // address = CbmMuchAddress::SetElementId(address, 3, layerside); + // // LOG(debug) << "After adding Layer Side " << address << " binary " << std::bitset<32>(address); + // address = CbmMuchAddress::SetElementId(address, 4, sModule); + // // LOG(debug) << "After adding module " << address << " binary " << std::bitset<32>(address); + // address = CbmMuchAddress::SetElementId(address, 5, sSector); + // // LOG(debug) << "After adding sector " << address << " binary " << std::bitset<32>(address); + // address = CbmMuchAddress::SetElementId(address, 6, sChannel); + // // LOG(debug) << "After adding channel " << address << " binary " << std::bitset<32>(address); + + // return address; + // } + +} // namespace cbm::algo::mvd diff --git a/algo/detectors/mvd/ReadoutConfig.h b/algo/detectors/mvd/ReadoutConfig.h new file mode 100644 index 0000000000000000000000000000000000000000..7bb63dc166b6657d67d1904d555eb9cd07499725 --- /dev/null +++ b/algo/detectors/mvd/ReadoutConfig.h @@ -0,0 +1,76 @@ +/* Copyright (C) 2021 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Dominik Smith [committer] */ + +#ifndef ALGO_DETECTORS_MVD_READOUTCONFIG_H +#define ALGO_DETECTORS_MVD_READOUTCONFIG_H + +#include <cstddef> +#include <cstdint> +#include <map> +#include <vector> + +namespace cbm::algo::mvd +{ + class ReadoutConfig { + + public: + /** @brief Constructor **/ + ReadoutConfig(); + + /** @brief Destructor **/ + virtual ~ReadoutConfig(); + + /** @brief Equipment in the configuration + ** @return Vector of equipment IDs + **/ + std::vector<uint16_t> GetEquipmentIds(); + + /** @brief Number of elinks of a component + ** @param Equipment ID + ** @return Number of elinks + **/ + size_t GetNumElinks(uint16_t equipmentId); + + /** @brief API: Mapping from component and elink to addresses per channel + ** @param equipId Equipment identifier (component) + ** @param elink Elink number within component + ** @return Vector of MVD addresses, indexed via channel number + */ + std::vector<uint32_t> Map(uint16_t equipId, uint16_t elink); + + /** @brief API: Mapping from component and elink to channel mask flags + ** @param equipId Equipment identifier (component) + ** @param elink Elink number within component + ** @return (vector of mask flags for channels per asic) + */ + std::vector<bool> MaskMap(uint16_t equipId, uint16_t elink); + + private: + // --- MVD readout map + // --- Map index: (equipment, elink, channel), map value: (MVD address) + std::map<uint16_t, std::vector<std::vector<uint32_t>>> fReadoutMap = {}; + + // --- MVD channel mask map + // --- Map index: (equipment, elink), map value: (vector of mask flags for channels per asic) + std::map<uint16_t, std::map<size_t, std::vector<bool>>> fMaskMap = {}; //! + + /** @brief Initialisation of readout map **/ + void Init(); + + /** @brief Maps component index, Fed Id and channel number to MVD Address **/ + // uint32_t CreateMvdAddress(uint32_t dpbidx, int32_t iFebId, uint32_t usChan); // not needed for the time being + + /// Constants + static const uint16_t numCrobPerComp = 2; ///< Number of CROBs possible per DPB + static const uint16_t numElinksPerCrob = 1; ///< Number of elinks in each CROB ? + static const uint16_t numComp = 2; ///< Total number of Mvd DPBs in system + + /// Variables + + + }; + +} // namespace cbm::algo::Mvd + +#endif // ALGO_DETECTORS_MVD_READOUTCONFIG_H diff --git a/algo/detectors/mvd/Unpack.cxx b/algo/detectors/mvd/Unpack.cxx new file mode 100644 index 0000000000000000000000000000000000000000..a5cb5ded296447b7dba8eff31028411c164e1299 --- /dev/null +++ b/algo/detectors/mvd/Unpack.cxx @@ -0,0 +1,36 @@ +/* Copyright (C) 2024 FIAS Frankfurt Institute for Advanced Studies, Frankfurt / Main + SPDX-License-Identifier: GPL-3.0-only + Authors: Felix Weiglhofer [committer], Dominik Smith */ + +#include "Unpack.h" + +#include "AlgoFairloggerCompat.h" + +using namespace cbm::algo::mvd; +using fles::Subsystem; + +Unpack::Unpack(const ReadoutConfig& readout) : fReadout(readout) +{ + constexpr i64 SystemTimeOffset = -980; + constexpr u8 SystemVersion = 0x20; + + // Create one algorithm per component for MVD and configure it with parameters + auto equipIdsMvd = fReadout.GetEquipmentIds(); + for (auto& equip : equipIdsMvd) { + mvd::UnpackPar par{}; + const size_t numElinks = fReadout.GetNumElinks(equip); + for (size_t elink = 0; elink < numElinks; elink++) { + mvd::UnpackElinkPar elinkPar; + elinkPar.fAddress = fReadout.Map(equip, elink); // Vector of MVD addresses for this elink + elinkPar.fTimeOffset = SystemTimeOffset; + elinkPar.fChanMask = fReadout.MaskMap(equip, elink); + par.fElinkParams.push_back(elinkPar); + } + auto algo = std::make_unique<UnpackMS>(par); + fAlgos[{equip, SystemVersion}] = std::move(algo); + L_(debug) << "--- Configured equipment " << equip << " with " << numElinks << " elinks"; + } + L_(info) << "--- Configured " << fAlgos.size() << " unpacker algorithms for MVD."; +} + +Unpack::Result_t Unpack::operator()(const fles::Timeslice& ts) const { return DoUnpack(Subsystem::MVD, ts); } diff --git a/algo/detectors/mvd/Unpack.h b/algo/detectors/mvd/Unpack.h new file mode 100644 index 0000000000000000000000000000000000000000..6112ded202feb82b1ee77aae92add09716aa9a18 --- /dev/null +++ b/algo/detectors/mvd/Unpack.h @@ -0,0 +1,32 @@ +/* Copyright (C) 2024 FIAS Frankfurt Institute for Advanced Studies, Frankfurt / Main + SPDX-License-Identifier: GPL-3.0-only + Authors: Felix Weiglhofer [committer], Dominik Smith */ + +#pragma once + +#include "CommonUnpacker.h" +#include "ReadoutConfig.h" +#include "UnpackMS.h" + +namespace cbm::algo::mvd +{ + + namespace detail + { + using UnpackBase = CommonUnpacker<CbmMvdDigi, UnpackMonitorData, UnpackAuxData>; + } + + class Unpack : public detail::UnpackBase { + + public: + using Result_t = detail::UnpackBase::Result_t; + + Unpack(const ReadoutConfig& readout); + + Result_t operator()(const fles::Timeslice&) const; + + private: + ReadoutConfig fReadout; + }; + +} // namespace cbm::algo::mvd diff --git a/algo/detectors/mvd/UnpackMS.cxx b/algo/detectors/mvd/UnpackMS.cxx new file mode 100644 index 0000000000000000000000000000000000000000..e2daa3699b21499f846252f46ff9e14f4dee3ef6 --- /dev/null +++ b/algo/detectors/mvd/UnpackMS.cxx @@ -0,0 +1,168 @@ +/* Copyright (C) 2021 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Pierre-Alain Loizeau, Volker Friese [committer] */ + +#include "UnpackMS.h" + +// #include "MimosisMessage.h" // implement this + +#include <cassert> +#include <cmath> +#include <utility> +#include <vector> + +using std::unique_ptr; +using std::vector; + +namespace cbm::algo::mvd +{ + + UnpackMS::UnpackMS(const UnpackPar& pars) : fParams(pars) {} + UnpackMS::~UnpackMS() = default; + + // ---- Algorithm execution --------------------------------------------- + UnpackMS::Result_t UnpackMS::operator()(const uint8_t* msContent, const fles::MicrosliceDescriptor& msDescr, + const uint64_t tTimeslice) const + { + + // --- Output data + Result_t result = {}; + + TimeSpec time; + + // --- Current Timeslice start time in epoch units. Note that it is always a multiple of epochs + // --- and the epoch is a multiple of ns. + // const uint64_t epochLengthInNs = fkEpochLength * fkClockCycleNom / fkClockCycleDen; + const uint64_t epochLengthInNs = fTimeStamp; + time.currentTsTime = tTimeslice / epochLengthInNs; + + // --- Current TS_MSB epoch cycle + auto const msTime = msDescr.idx; // Unix time of MS in ns + // time.currentCycle = std::ldiv(msTime, fkCycleLength).quot; + time.currentEpoch = 0; // Needed to make each MS independent of the previous! Will be updated in message 1 if MS OK + time.currentEpochTime = + 0; // Needed to make each MS independent of the previous! Will be updated in message 1 if MS OK + + // ---Â Number of messages in microslice + // auto msSize = msDescr.size; + // if (msSize % sizeof(mimosis::Message) != 0) { + // std::get<1>(result).fNumErrInvalidMsSize++; + // return result; + // } + // const uint32_t numMessages = msSize / sizeof(mimosis::Message); + // if (numMessages < 2) { + // std::get<1>(result).fNumErrInvalidMsSize++; + // return result; + // } + + // const uint32_t maxDigis = numMessages - 2; // -2 for the TS_MSB and EPOCH messages + // std::get<0>(result).reserve(maxDigis); + + // --- Interpret MS content as sequence of SMX messages + // auto message = reinterpret_cast<const mimosis::Message*>(msContent); + + // --- The first message in the MS is expected to be of type EPOCH and can be ignored. + // if (message[0].GetMessType() != mimosis::MessType::Epoch) { + // std::get<1>(result).fNumErrInvalidFirstMessage++; + // return result; + // } + + // --- The second message must be of type ts_msb. + // if (message[1].GetMessType() != mimosis::MessType::TsMsb) { + // std::get<1>(result).fNumErrInvalidFirstMessage++; + // return result; + // } + // ProcessTsmsbMessage(message[1], time); + + // --- Message loop + // for (uint32_t messageNr = 2; messageNr < numMessages; messageNr++) { + + // // --- Action depending on message type + // switch (message[messageNr].GetMessType()) { + + // case mimosis::MessType::Hit: { + // ProcessHitMessage(message[messageNr], time, std::get<0>(result), std::get<1>(result)); + // break; + // } + // case mimosis::MessType::TsMsb: { + // ProcessTsmsbMessage(message[messageNr], time); + // break; + // } + // default: { + // std::get<1>(result).fNumNonHitOrTsbMessage++; + // break; + // } + + // } //? Message type + + // } //# Messages + + return result; + } + // -------------------------------------------------------------------------- + + + // ----- Process hit message -------------------------------------------- + // inline void UnpackMS::ProcessHitMessage(const mimosis::Message& message, const TimeSpec& time, + // vector<CbmMuchDigi>& digiVec, UnpackMonitorData& monitor) const + // { + // // --- Check eLink and get parameters + // uint16_t elink = message.GetLinkIndexHitBinning(); + // if (elink >= fParams.fElinkParams.size()) { + // monitor.fNumErrElinkOutOfRange++; + // return; + // } + // const UnpackElinkPar& elinkPar = fParams.fElinkParams.at(elink); + // uint16_t channel = message.GetHitChannel(); + + // // --- Check for masked channel + // if (!elinkPar.fChanMask.empty() && elinkPar.fChanMask[channel] == true) { + // return; + // } + + // uint32_t address = (elinkPar.fAddress)[channel]; + + // // --- Expand time stamp to time within timeslice (in clock cycle) + // uint64_t messageTime = message.GetHitTimeBinning() + time.currentEpochTime; + + // // --- Convert time stamp from clock cycles to ns. Round to nearest full ns. + // messageTime = (messageTime * fkClockCycleNom + fkClockCycleDen / 2) / fkClockCycleDen; + + // // --- Correct ASIC-wise offsets + // messageTime -= elinkPar.fTimeOffset; + + // // --- Charge + // double charge = message.GetHitAdc(); + + // // --- Create output digi + // digiVec.emplace_back(address, charge, messageTime); + // } + // -------------------------------------------------------------------------- + + + // ----- Process an epoch (TS_MSB) message ------------------------------ + // inline void UnpackMS::ProcessTsmsbMessage(const mimosis::Message& message, TimeSpec& time) const + // { + // // The compression of time is based on the hierarchy epoch cycle - epoch - message time. + // // Cycles are counted from the start of Unix time and are multiples of an epoch (ts_msb). + // // The epoch number is counted within each cycle. The time in the hit message is expressed + // // in units of the readout clock cycle relative to the current epoch. + // // The ts_msb message indicates the start of a new epoch. Its basic information is the epoch + // // number within the current cycle. A cycle wrap resets the epoch number to zero, so it is + // // indicated by the epoch number being smaller than the previous one (epoch messages are + // // seemingly not consecutively in the data stream, but only if there are hit messages in between). + // auto epoch = message.GetTsMsbValBinning(); + + // // --- Cycle wrap + // if (epoch < time.currentEpoch) time.currentCycle++; + + // // --- Update current epoch counter + // time.currentEpoch = epoch; + + // // --- Calculate epoch time in clocks cycles relative to timeslice start time + // time.currentEpochTime = (time.currentCycle * fkEpochsPerCycle + epoch - time.currentTsTime) * fkEpochLength; + // } + // -------------------------------------------------------------------------- + + +} // namespace cbm::algo::much diff --git a/algo/detectors/mvd/UnpackMS.h b/algo/detectors/mvd/UnpackMS.h new file mode 100644 index 0000000000000000000000000000000000000000..ea386bf4e83a22e11850c1ccf2510e9eb92ea2c2 --- /dev/null +++ b/algo/detectors/mvd/UnpackMS.h @@ -0,0 +1,149 @@ +/* Copyright (C) 2021 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Pierre-Alain Loizeau, Volker Friese [committer] */ +#pragma once + +#include "CbmMvdDigi.h" +#include "MicrosliceDescriptor.hpp" +// #include "MimosisMessage.h" // create this class +#include "Timeslice.hpp" +#include "UnpackMSBase.h" + +#include <cassert> +#include <cstddef> +#include <cstdint> +#include <memory> +#include <sstream> +#include <vector> + +namespace cbm::algo::mvd +{ + + + /** @struct UnpackElinkPar + ** @author Volker Friese <v.friese@gsi.de> + ** @since 25 November 2021 + ** @brief STS Unpacking parameters for one eLink / ASIC + **/ + struct UnpackElinkPar { + // std::vector<uint32_t> fAddress; ///< CbmMuchAddress for different channels + std::vector<bool> fPixX; ///< col masking flags + std::vector<bool> fPixY; ///< row masking flags + uint64_t fTimeOffset = 0.; ///< Time calibration parameter + }; + + + /** @struct UnpackPar + ** @author Volker Friese <v.friese@gsi.de> + ** @since 25 November 2021 + ** @brief Parameters required for the STS unpacking (specific to one component) + **/ + struct UnpackPar { + std::vector<UnpackElinkPar> fElinkParams = {}; ///< Parameters for each eLink + }; + + + /** @struct UnpackMoni + ** @author Volker Friese <v.friese@gsi.de> + ** @since 2 December 2021 + ** @brief Monitoring data for STS unpacking + **/ + struct UnpackMonitorData { + uint32_t fNumNonHitOrTsbMessage = 0; + uint32_t fNumErrElinkOutOfRange = 0; ///< Elink not contained in parameters + uint32_t fNumErrInvalidFirstMessage = 0; ///< First message is not TS_MSB or second is not EPOCH + uint32_t fNumErrInvalidMsSize = 0; ///< Microslice size is not multiple of message size + uint32_t fNumErrTimestampOverflow = 0; ///< Overflow in 64 bit time stamp + bool HasErrors() + { + uint32_t numErrors = fNumNonHitOrTsbMessage + fNumErrElinkOutOfRange + fNumErrInvalidFirstMessage + + fNumErrInvalidMsSize + fNumErrTimestampOverflow; + return (numErrors > 0 ? true : false); + } + std::string print() + { + std::stringstream ss; + ss << "errors " << fNumNonHitOrTsbMessage << " | " << fNumErrElinkOutOfRange << " | " + << fNumErrInvalidFirstMessage << " | " << fNumErrInvalidMsSize << " | " << fNumErrTimestampOverflow << " | "; + return ss.str(); + } + }; + + /** @struct UnpackAux + ** @author Dominik Smith <d.smith@gsi.de> + ** @since 24 May 2024 + ** @brief Auxiliary data for BMON unpacking + **/ + struct UnpackAuxData { + ///// TO BE FILLED + }; + + /** @class UnpackMS + ** @author Pierre-Alain Loizeau <p.-a.loizeau@gsi.de> + ** @author Volker Friese <v.friese@gsi.de> + ** @since 25 November 2021 + ** @brief Unpack algorithm for STS + **/ + class UnpackMS : public UnpackMSBase<CbmMvdDigi, UnpackMonitorData, UnpackAuxData> { + + public: + /** @brief Construct with parameters **/ + UnpackMS(const UnpackPar& pars); + + /** @brief Destructor **/ + ~UnpackMS() override; + + + /** @brief Algorithm execution + ** @param msContent Microslice payload + ** @param msDescr Microslice descriptor + ** @param tTimeslice Unix start time of timeslice [ns] + ** @return STS digi data + **/ + Result_t operator()(const uint8_t* msContent, const fles::MicrosliceDescriptor& msDescr, + const uint64_t tTimeslice) const override; + + private: // datatypes + struct TimeSpec { + uint64_t currentTsTime = 0; ///< Unix time of timeslice in units of epoch length + uint64_t currentCycle = 0; ///< Current epoch cycle + uint32_t currentEpoch = 0; ///< Current epoch number within epoch cycle + uint64_t currentEpochTime = 0; ///< Current epoch time relative to timeslice in clock cycles + }; + + + private: // methods + /** @brief Process a hit message + ** @param message SMX message (32-bit word) + ** @param digiVec Vector to append the created digi to + ** @param monitor Reference to monitor object + **/ + // void ProcessHitMessage(const mimosis::Message& message, const TimeSpec& time, std::vector<CbmMvdDigi>& digiVec, + // UnpackMonitorData& monitor) const; + + /** @brief Process an epoch message (TS_MSB) + ** @param message SMX message (32-bit word) + **/ + // void ProcessTsmsbMessage(const mimosis::Message& message, TimeSpec& time) const; // to do + + + private: // members + UnpackPar fParams = {}; ///< Parameter container + + /** Number of TS_MSB epochs per cycle **/ + // static constexpr uint64_t fkEpochsPerCycle = mimosis::kuTsMsbNbTsBinsBinning; + + /** Length of TS_MSB epoch in clock cycles **/ + // static constexpr uint64_t fTimeStamp = mimosis::Time; + static constexpr uint64_t fTimeStamp = 0; + + /** Clock cycle nominator [ns] and denominator. The clock cycle in ns is nominator / denominator. **/ + // static constexpr uint32_t fkClockCycleNom = mimosis::kulClockCycleNom; + // static constexpr uint32_t fkClockCycleDen = mimosis::kulClockCycleDen; + + /** Epoch cycle length in ns **/ + // static constexpr uint64_t fkCycleLength = (fkEpochsPerCycle * fkEpochLength * fkClockCycleNom) / fkClockCycleDen; + }; + + +} // namespace cbm::algo::much diff --git a/algo/global/ParFiles.cxx b/algo/global/ParFiles.cxx index 9d4e8ee2cde9139b0cc765ea92b5f97d62025d66..e936debe09846bd9fc7b9dc2b53d7e16341956ab 100644 --- a/algo/global/ParFiles.cxx +++ b/algo/global/ParFiles.cxx @@ -34,6 +34,10 @@ ParFiles::ParFiles(uint32_t runId) sts.walkMap = "StsWalkMap_mcbm2022.yaml"; sts.hitfinder = "StsHitfinder_mcbm2022.yaml"; + mvd.readout = "MvdReadout_mcbm2025.yaml"; + // mvd.pixMask = "MvdChannelMaskSet_mcbm2025.yaml"; + // mvd.walkMap = "MvdWalkMap_mcbm2022.yaml"; + tof.readout = "TofReadout_mcbm2022.yaml"; tof.calibrate = "TofCalibratePar_mcbm2022.yaml"; tof.hitfinder = "TofHitfinderPar_mcbm2022.yaml"; diff --git a/algo/global/ParFiles.h b/algo/global/ParFiles.h index 0fe7b3094b1e25eaa0d7f3ccb207a6977f5d2836..cdcf88a04d300b288b3f9866e995a78f1b66e255 100644 --- a/algo/global/ParFiles.h +++ b/algo/global/ParFiles.h @@ -37,6 +37,12 @@ namespace cbm::algo fs::path hitfinder; } sts; + struct { + fs::path readout; + fs::path pixMask; + fs::path walkMap; + } mvd; + struct { fs::path readout; fs::path calibrate; diff --git a/algo/global/Reco.cxx b/algo/global/Reco.cxx index 79784707ea990ca10e78cc88ec1b83c2512481e5..7da16cfc55d12258ec5de92cadd72cf4490ccf26 100644 --- a/algo/global/Reco.cxx +++ b/algo/global/Reco.cxx @@ -13,6 +13,7 @@ #include "ParFiles.h" #include "RecoGeneralQa.h" #include "StsDigiQa.h" +// #include "MvdDigiQa.h" ToDo #include "TrackingSetup.h" #include "bmon/Calibrate.h" #include "bmon/Hitfind.h" @@ -31,6 +32,9 @@ #include "sts/ChannelMaskSet.h" #include "sts/HitfinderChain.h" #include "sts/Unpack.h" +// #include "mvd/ChannelMaskSet.h" // todo +// #include "mvd/HitfinderChain.h" // todo +#include "mvd/Unpack.h" #include "tof/Calibrate.h" #include "tof/Hitfind.h" #include "tof/Unpack.h" @@ -161,6 +165,27 @@ void Reco::Init(const Options& opts) } } + if (Opts().Has(Subsystem::MVD) && Opts().Has(Step::Unpack)) { + mvd::ReadoutConfig cfg{}; + fMvdUnpack = std::make_unique<mvd::Unpack>(cfg); + } + + // if (Opts().Has(Subsystem::MVD) && Opts().Has(Step::Unpack)) { + // mvd::ReadoutSetup readoutSetup = yaml::ReadFromFile<mvd::ReadoutSetup>(Opts().ParamsDir() / parFiles.mvd.readout); + // auto pixMask = yaml::ReadFromFile<mvd::ChannelMaskSet>(Opts().ParamsDir() / parFiles.mvd.chanMask); + // auto walkMap = yaml::ReadFromFile<mvd::WalkMap>(Opts().ParamsDir() / parFiles.mvd.walkMap); + // bool bCollectAux = (fSender != nullptr && Opts().CollectAuxData()); + // mvd::ReadoutConfig readout{readoutSetup, pixMask}; + // mvd::Unpack::Config cfg{.readout = readout, .walkMap = walkMap, .bCollectAuxData = bCollectAux}; + // fMvdUnpack = std::make_unique<mvd::Unpack>(cfg); + // // if (fSender != nullptr && Opts().Has(QaStep::UnpackMvd)) { + // // fMvdDigiQa = std::make_unique<mvd::DigiQa>(fSender); + // // fMvdDigiQa->SetUseAuxData(bCollectAux); + // // fMvdDigiQa->RegisterReadoutSetup(readoutSetup); + // // fMvdDigiQa->Init(); + // // } + // } + if (Opts().Has(Subsystem::TOF) && Opts().Has(Step::Unpack)) { tof::ReadoutSetup readoutSetup = yaml::ReadFromFile<tof::ReadoutSetup>(Opts().ParamsDir() / parFiles.tof.readout); tof::ReadoutConfig cfg{readoutSetup}; @@ -332,6 +357,7 @@ RecoResults Reco::Run(const fles::Timeslice& ts) std::tie(digis.fBmon, auxDigis.fBmon) = RunUnpacker(fBmonUnpack, ts); std::tie(digis.fMuch, auxDigis.fMuch) = RunUnpacker(fMuchUnpack, ts); + std::tie(digis.fMvd, auxDigis.fMvd) = RunUnpacker(fMvdUnpack, ts); std::tie(digis.fRich, auxDigis.fRich) = RunUnpacker(fRichUnpack, ts); std::tie(digis.fSts, auxDigis.fSts) = RunUnpacker(fStsUnpack, ts); std::tie(digis.fTof, auxDigis.fTof) = RunUnpacker(fTofUnpack, ts); @@ -342,7 +368,7 @@ RecoResults Reco::Run(const fles::Timeslice& ts) // digis.fPsd = RunUnpacker(fPsdUnpack, ts); // digis.fFsd = RunUnpacker(fFsdUnpack, ts); - L_(info) << "TS contains Digis: STS=" << digis.fSts.size() << " MUCH=" << digis.fMuch.size() + L_(info) << "TS contains Digis: STS=" << digis.fSts.size() << " MUCH=" << digis.fMuch.size() << " MVD=" << digis.fMvd.size() << " TOF=" << digis.fTof.size() << " BMON=" << digis.fBmon.size() << " TRD=" << digis.fTrd.size() << " TRD2D=" << digis.fTrd2d.size() << " RICH=" << digis.fRich.size() << " PSD=" << digis.fPsd.size() << " FSD=" << digis.fFsd.size(); @@ -457,6 +483,7 @@ RecoResults Reco::Run(const fles::Timeslice& ts) results.bmonDigis = std::move(digis.fBmon); results.stsDigis = std::move(digis.fSts); results.muchDigis = std::move(digis.fMuch); + results.mvdDigis = std::move(digis.fMvd); results.trd2dDigis = std::move(digis.fTrd2d); results.trdDigis = std::move(digis.fTrd); results.tofDigis = std::move(digis.fTof); @@ -736,6 +763,7 @@ void Reco::QueueEvbuildMetrics(const evbuild::EventbuildChainMonitorData& mon) queueDetMetrics("sts", mon.evbuild.sts); queueDetMetrics("much", mon.evbuild.much); + queueDetMetrics("mvd", mon.evbuild.mvd); queueDetMetrics("tof", mon.evbuild.tof); queueDetMetrics("bmon", mon.evbuild.bmon); queueDetMetrics("trd", mon.evbuild.trd); diff --git a/algo/global/Reco.h b/algo/global/Reco.h index e5a8412151d8e05a4cd1b5ee68d71d8ee6f47ebc..1f21990ef373644ec662bbad0ac0ebb154ad1495 100644 --- a/algo/global/Reco.h +++ b/algo/global/Reco.h @@ -41,6 +41,11 @@ namespace cbm::algo class Unpack; } + namespace mvd + { + class Unpack; + } + namespace rich { class Unpack; @@ -164,6 +169,9 @@ namespace cbm::algo // MUCH std::unique_ptr<much::Unpack> fMuchUnpack; + // MVD + std::unique_ptr<mvd::Unpack> fMvdUnpack; + // RICH std::unique_ptr<rich::Unpack> fRichUnpack; diff --git a/algo/global/RecoResults.h b/algo/global/RecoResults.h index 3bcee8be6acd66388ab8e0043313888c0f35c615..2653d34884cae6657a34973784f0fac5edff81d4 100644 --- a/algo/global/RecoResults.h +++ b/algo/global/RecoResults.h @@ -32,6 +32,7 @@ namespace cbm::algo PODVector<CbmBmonDigi> bmonDigis; PODVector<CbmStsDigi> stsDigis; PODVector<CbmMuchDigi> muchDigis; + PODVector<CbmMvdDigi> mvdDigis; PODVector<CbmTrdDigi> trd2dDigis; PODVector<CbmTrdDigi> trdDigis; PODVector<CbmTofDigi> tofDigis; diff --git a/algo/global/StorableRecoResults.h b/algo/global/StorableRecoResults.h index 5560b7d1ad1998bfacc2b35e0f64335acc571820..27b23a9d7b7452354f463c0c815581aa3b2346b7 100644 --- a/algo/global/StorableRecoResults.h +++ b/algo/global/StorableRecoResults.h @@ -58,6 +58,9 @@ namespace cbm::algo std::vector<CbmMuchDigi>& MuchDigis() { return fMuchDigis; } const std::vector<CbmMuchDigi>& MuchDigis() const { return fMuchDigis; } + std::vector<CbmMvdDigi>& MvdDigis() { return fMvdDigis; } + const std::vector<CbmMvdDigi>& MvdDigis() const { return fMvdDigis; } + std::vector<CbmTrdDigi>& Trd2dDigis() { return fTrd2dDigis; } const std::vector<CbmTrdDigi>& Trd2dDigis() const { return fTrd2dDigis; } @@ -102,6 +105,7 @@ namespace cbm::algo std::vector<CbmBmonDigi> fBmonDigis; std::vector<CbmStsDigi> fStsDigis; std::vector<CbmMuchDigi> fMuchDigis; + std::vector<CbmMvdDigi> fMvdDigis; std::vector<CbmTrdDigi> fTrd2dDigis; std::vector<CbmTrdDigi> fTrdDigis; std::vector<CbmTofDigi> fTofDigis; @@ -138,6 +142,7 @@ namespace cbm::algo ar& fBmonDigis; ar& fStsDigis; ar& fMuchDigis; + ar& fMvdDigis; ar& fTrd2dDigis; ar& fTrdDigis; ar& fTofDigis; diff --git a/core/data/CMakeLists.txt b/core/data/CMakeLists.txt index b5b59dd07855d9e7f8fb17bbd151c570757e7563..c5c6e3d0d492ddfbd571c64ab944603c0e5b29f7 100644 --- a/core/data/CMakeLists.txt +++ b/core/data/CMakeLists.txt @@ -134,7 +134,7 @@ SET_SOURCE_FILES_PROPERTIES(tof/etof/star_rhicf.c PROPERTIES COMPILE_FLAGS -Wno- list(APPEND HEADERS base/CbmDigiData.h global/CbmDigiEvent.h global/CbmDigiTimeslice.h -bmon/CbmBmonDigiData.h sts/CbmStsDigiData.h much/CbmMuchDigiData.h rich/CbmRichDigiData.h trd/CbmTrdDigiData.h +bmon/CbmBmonDigiData.h sts/CbmStsDigiData.h much/CbmMuchDigiData.h mvd/CbmMvdDigiData.h rich/CbmRichDigiData.h trd/CbmTrdDigiData.h tof/CbmTofDigiData.h psd/CbmPsdDigiData.h fsd/CbmFsdDigiData.h trd/CbmTrdFexMessageSpadic.h) set(LIBRARY_NAME CbmData) @@ -163,6 +163,7 @@ Install(FILES base/CbmDigiData.h base/CbmDigiVector.h bmon/CbmBmonDigiData.h much/CbmMuchDigiData.h + mvd/CbmMvdDigiData.h psd/CbmPsdDigiData.h fsd/CbmFsdDigiData.h rich/CbmRichDigiData.h rich/CbmRichRingLight.h diff --git a/core/data/base/CbmDigiData.h b/core/data/base/CbmDigiData.h index c864e8ba6fcef44cbdfc3a1f5f4a5886e4d2428f..6c5183a27a051b2799ed54208f71c2ac66153a62 100644 --- a/core/data/base/CbmDigiData.h +++ b/core/data/base/CbmDigiData.h @@ -9,6 +9,7 @@ #include "CbmBmonDigiData.h" #include "CbmFsdDigiData.h" #include "CbmMuchDigiData.h" +#include "CbmMvdDigiData.h" #include "CbmPsdDigiData.h" #include "CbmRichDigiData.h" #include "CbmStsDigiData.h" @@ -35,6 +36,7 @@ class CbmDigiData { CbmBmonDigiData fBmon; ///< Beam monitor data CbmStsDigiData fSts; ///< STS data CbmMuchDigiData fMuch; ///< MUCH data + CbmMvdDigiData fMvd; ///< MVD data CbmRichDigiData fRich; ///< RICH data CbmTrdDigiData fTrd; ///< TRD data CbmTrdDigiData fTrd2d; ///< TRD2D data @@ -51,6 +53,7 @@ class CbmDigiData { ar& fBmon; ar& fSts; ar& fMuch; + ar& fMvd; ar& fTrd; ar& fTrd2d; ar& fTof; @@ -70,6 +73,7 @@ class CbmDigiData { fBmon.Clear(); fSts.Clear(); fMuch.Clear(); + fMvd.Clear(); fTrd.Clear(); fTrd2d.Clear(); fTof.Clear(); @@ -85,6 +89,7 @@ class CbmDigiData { case ECbmModuleId::kBmon: return fBmon.Size(); break; case ECbmModuleId::kSts: return fSts.Size(); break; case ECbmModuleId::kMuch: return fMuch.Size(); break; + case ECbmModuleId::kMvd: return fMvd.Size(); break; case ECbmModuleId::kTrd: return fTrd.Size(); break; case ECbmModuleId::kTrd2d: return fTrd2d.Size(); break; case ECbmModuleId::kTof: return fTof.Size(); break; @@ -102,6 +107,7 @@ class CbmDigiData { size += fBmon.Size() * sizeof(CbmBmonDigi); size += fSts.Size() * sizeof(CbmStsDigi); size += fMuch.Size() * sizeof(CbmMuchDigi); + size += fMvd.Size() * sizeof(CbmMvdDigi); size += fTrd.Size() * sizeof(CbmTrdDigi); size += fTrd2d.Size() * sizeof(CbmTrdDigi); size += fTof.Size() * sizeof(CbmTofDigi); diff --git a/core/data/mvd/CbmMvdDigiData.h b/core/data/mvd/CbmMvdDigiData.h new file mode 100644 index 0000000000000000000000000000000000000000..798bf760abda11f88a9afc5057a18896ad1be39d --- /dev/null +++ b/core/data/mvd/CbmMvdDigiData.h @@ -0,0 +1,55 @@ +/* Copyright (C) 2022 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Volker Friese [committer] */ + +#ifndef CBMMVDDIGIDATA_H +#define CBMMVDDIGIDATA_H 1 + + +#include "CbmMvdDigi.h" + +#ifndef NO_ROOT +#include <Rtypes.h> // for ClassDef +#endif + +#include <boost/serialization/access.hpp> +#include <boost/serialization/base_object.hpp> + +#include <vector> + +/** @class CbmMvdDigiData + ** @brief Container class for CbmMvdDigi objects + ** @author Volker Friese <v.friese@gsi.de> + ** @since 7.12.2022 + ** @version 1.0 + ** + ** Container class for transporting CbmMvdDigi objects. + ** The current implementation is the simplest one: a std::vector. + **/ +class CbmMvdDigiData { + +public: + std::vector<CbmMvdDigi> fDigis = {}; ///< Data vector + + friend class boost::serialization::access; + + /** @brief BOOST serializer**/ + template<class Archive> + void serialize(Archive& ar, const unsigned int /*version*/) + { + ar& fDigis; + } + + /** @brief Clear content **/ + void Clear() { fDigis.clear(); } + + /** @brief Size */ + size_t Size() const { return fDigis.size(); } + + // --- ROOT serializer +#ifndef NO_ROOT + ClassDefNV(CbmMvdDigiData, 1); +#endif +}; + +#endif diff --git a/reco/app/cbmreco/main.cxx b/reco/app/cbmreco/main.cxx index 6dd23efc4481d3854e2f76af8d715f66528521a4..884c4142ec95446a3987e97e60825a48da2c4bcf 100644 --- a/reco/app/cbmreco/main.cxx +++ b/reco/app/cbmreco/main.cxx @@ -39,6 +39,7 @@ std::shared_ptr<StorableRecoResults> makeStorableRecoResults(const fles::Timesli storable->BmonDigis() = ToStdVector(results.bmonDigis); storable->StsDigis() = ToStdVector(results.stsDigis); storable->MuchDigis() = ToStdVector(results.muchDigis); + storable->MvdDigis() = ToStdVector(results.mvdDigis); storable->Trd2dDigis() = ToStdVector(results.trd2dDigis); storable->TrdDigis() = ToStdVector(results.trdDigis); storable->TofDigis() = ToStdVector(results.tofDigis);