diff --git a/algo/detectors/trd/ReadoutConfig.cxx b/algo/detectors/trd/ReadoutConfig.cxx index 828665b6ff2e3ddf0d609db33404904c56f24873..4ffa48492d816efc8c8c6135610ae59eb1d28604 100644 --- a/algo/detectors/trd/ReadoutConfig.cxx +++ b/algo/detectors/trd/ReadoutConfig.cxx @@ -131,6 +131,28 @@ namespace cbm::algo::trd } // ------------------------------------------------------------------------------------ + void ReadoutConfig::SetElinkTimeOffset(uint32_t criid, uint8_t elinkid, int32_t offsetNs) + { + // create vector for criid if not yet existing + if (fElinkTimeOffsetMap.find(criid) == fElinkTimeOffsetMap.end()) { + //vector has fixed size of 256 (max elinkid) and is initialized to 0 + fElinkTimeOffsetMap.insert(std::make_pair(criid, std::vector<int32_t>(256, 0))); + } + + fElinkTimeOffsetMap[criid][elinkid] = offsetNs; + } + + int32_t ReadoutConfig::GetElinkTimeOffset(uint32_t criid, uint8_t elinkid) + { + auto it = fElinkTimeOffsetMap.find(criid); + if (it == fElinkTimeOffsetMap.end()) { + return 0; + } + + const auto& elinks = it->second; + return elinks.at(elinkid); + } + // ----- Print readout map ------------------------------------------------ std::string ReadoutConfig::PrintReadoutMap() diff --git a/algo/detectors/trd/ReadoutConfig.h b/algo/detectors/trd/ReadoutConfig.h index 42cec6d95adb009480019fd4e10bb3cdf0d91900..a20bc9d1ab4ddb8e98a5f2165e3b46df5758660c 100644 --- a/algo/detectors/trd/ReadoutConfig.h +++ b/algo/detectors/trd/ReadoutConfig.h @@ -68,6 +68,16 @@ namespace cbm::algo::trd */ std::pair<int32_t, std::vector<uint32_t>> Map(uint16_t equipId, uint16_t crob, uint16_t elink); + /** + * @brief Register a time offeset to be substracted from the digis which come from a specific CRI + **/ + void SetElinkTimeOffset(uint32_t criid, uint8_t elinkid, int32_t offsetNs); + + + /** + * @brief Get the time offeset to be substracted from the digis which come from a specific CRI + **/ + int32_t GetElinkTimeOffset(uint32_t criid, uint8_t elinkid); /** @brief Debug output of readout map **/ std::string PrintReadoutMap(); @@ -86,8 +96,14 @@ namespace cbm::algo::trd // --- Map index: (equipment, crob, elink, chan), map value: (channel address) std::map<uint16_t, std::vector<std::vector<std::vector<uint32_t>>>> fChannelMap = {}; //! - CBM_YAML_PROPERTIES(yaml::Property(&ReadoutConfig::fReadoutMap, "readoutMap", "TRD readout map", {}, YAML::Hex), - yaml::Property(&ReadoutConfig::fChannelMap, "channelMap", "TRD channel map")); + /** @brief Map to store time offsets for each CRI&Elink combination */ + std::map<uint32_t, std::vector<int32_t>> fElinkTimeOffsetMap; + + CBM_YAML_PROPERTIES( + yaml::Property(&ReadoutConfig::fReadoutMap, "readoutMap", "TRD readout map", {}, YAML::Hex), + yaml::Property(&ReadoutConfig::fChannelMap, "channelMap", "TRD channel map"), + yaml::Property(&ReadoutConfig::fElinkTimeOffsetMap, "elinkTimeOffset", "TRD time offset per CRI&Elink combination") + ); }; } // namespace cbm::algo::trd diff --git a/algo/detectors/trd/Unpack.cxx b/algo/detectors/trd/Unpack.cxx index f6e3bb135117ab02e2be457145e656335f8d3828..9a5fcdc1e58a7ccb3dc4ec5190a07e3bc81fb1d0 100644 --- a/algo/detectors/trd/Unpack.cxx +++ b/algo/detectors/trd/Unpack.cxx @@ -29,7 +29,7 @@ Unpack::Unpack(const ReadoutConfig& readout) : fReadout(readout) auto addresses = fReadout.Map(equip, crob, elink); elinkPar.fAddress = addresses.first; // Asic address for this elink elinkPar.fChanAddress = addresses.second; // Channel addresses for this elink - elinkPar.fTimeOffset = SystemTimeOffset; + elinkPar.fTimeOffset = SystemTimeOffset + fReadout.GetElinkTimeOffset(crob, elink); crobPar.fElinkParams.push_back(elinkPar); } par.fCrobParams.push_back(crobPar); diff --git a/algo/global/ParFiles.cxx b/algo/global/ParFiles.cxx index dc4b359db9b5d5be7a50b79c87d18abf91cc73d2..959ee5180157513374124e9facdcbe3836910690 100644 --- a/algo/global/ParFiles.cxx +++ b/algo/global/ParFiles.cxx @@ -64,8 +64,8 @@ ParFiles::ParFiles(uint32_t runId) tof.calibrate = "mcbm2024_05/TofCalibratePar.yaml"; tof.hitfinder = "mcbm2024_05/TofHitfinderPar.yaml"; - trd.readout = "TrdReadoutSetup_mcbm2024.yaml"; - trd.readout2d = "TrdReadout2DSetup_mcbm2022.yaml"; // TODO: no new readout for TRD2D? + trd.readout = "mcbm2024_05/TrdReadoutSetup.yaml"; + trd.readout2d = "mcbm2024_05/Trd2dReadoutSetup.yaml"; trd.hitfinder = "mcbm2024_05/TrdHitfinderPar.yaml"; trd.hitfinder2d = "mcbm2024_05/TrdHitfinder2DPar.yaml"; diff --git a/external/InstallParameter.cmake b/external/InstallParameter.cmake index 4ca65d3f18d1d36fdcb42ebb09a1a324b3d373d4..3bc364026971e738d7bb23ba307d38fe9b996619 100644 --- a/external/InstallParameter.cmake +++ b/external/InstallParameter.cmake @@ -1,4 +1,4 @@ -set(PARAMETER_VERSION e444a11048669f08b28894150b61d853f8987f7a) # 2024-05-09 +set(PARAMETER_VERSION 051bea5a7434ed876da39649f85187852e679a85) # 2024-05-11 set(PARAMETER_SRC_URL "https://git.cbm.gsi.de/CbmSoft/cbmroot_parameter.git") diff --git a/reco/steer/CbmOnlineParWrite.cxx b/reco/steer/CbmOnlineParWrite.cxx index 29c33293334e37bce1fe8a35166a17b486b5df18..e41dcc9d0fef17cc031f60c4b8cb2b33a833c4c5 100644 --- a/reco/steer/CbmOnlineParWrite.cxx +++ b/reco/steer/CbmOnlineParWrite.cxx @@ -17,6 +17,9 @@ #include "CbmTaskStsHitFinderParWrite.h" #include "CbmTaskTofClusterizerParWrite.h" #include "CbmTaskTrdHitFinderParWrite.h" +#include "CbmTaskTrdUnpackParWrite.h" +#include "CbmTrdParSetAsic.h" +#include "CbmTrdParSetDigi.h" #include <FairParAsciiFileIo.h> #include <FairParRootFileIo.h> @@ -51,22 +54,52 @@ void CbmOnlineParWrite::AddTrd() // ----- TRD digitisation parameters ------------------------------------- TString geoTagTrd; - if (fSetup->IsActive(ECbmModuleId::kTrd)) { - if (fSetup->GetGeoTag(ECbmModuleId::kTrd, geoTagTrd)) { - TString paramFilesTrd(Form("%s/parameters/trd/trd_%s", fSrcDir.Data(), geoTagTrd.Data())); - std::vector<TString> paramFilesVecTrd = {"asic", "digi", "gas", "gain"}; - for (auto parIt : paramFilesVecTrd) { - fParList->Add(new TObjString(Form("%s.%s.par", paramFilesTrd.Data(), parIt.Data()))); - } - } - for (auto parFileVecIt : *fParList) { - std::cout << Form("TrdParams - %s - added to parameter file list", parFileVecIt->GetName()) << std::endl; - } + if (!fSetup->IsActive(ECbmModuleId::kTrd)) { + throw std::runtime_error{"TRD not enabled in current geometry!"}; + } + + if (!fSetup->GetGeoTag(ECbmModuleId::kTrd, geoTagTrd)) { + throw std::runtime_error{"Failed to get TRD geo tag from CbmSetup!"}; + } + + TString paramFilesTrd(Form("%s/parameters/trd/trd_%s", fSrcDir.Data(), geoTagTrd.Data())); + std::vector<TString> paramFilesVecTrd = {"asic", "digi", "gas", "gain"}; + for (auto parIt : paramFilesVecTrd) { + fParList->Add(new TObjString(Form("%s.%s.par", paramFilesTrd.Data(), parIt.Data()))); + } + + for (auto parFileVecIt : *fParList) { + std::cout << Form("TrdParams - %s - added to parameter file list", parFileVecIt->GetName()) << std::endl; } // ----- TRD task --------------------------------------------------------- - auto* trdHitfinderPar = new CbmTaskTrdHitFinderParWrite(); + auto* trdHitfinderPar = new CbmTaskTrdHitFinderParWrite{}; fRun->AddTask(trdHitfinderPar); + + + // Initialize input files + FairParAsciiFileIo asciiInput; + std::string digiparfile = Form("%s/parameters/trd/trd_%s.digi.par", fSrcDir.Data(), geoTagTrd.Data()); + std::string asicparfile = Form("%s/parameters/trd/trd_%s.asic.par", fSrcDir.Data(), geoTagTrd.Data()); + + // Read the .digi file and store result + auto* digiparset = new CbmTrdParSetDigi{}; + if (asciiInput.open(digiparfile.data())) { + digiparset->init(&asciiInput); + } + asciiInput.close(); + + // Read the .asic file and store result + auto* asicparset = new CbmTrdParSetAsic{}; + if (asciiInput.open(asicparfile.data())) { + asicparset->init(&asciiInput); + } + asciiInput.close(); + + // Unpack + CbmTaskTrdUnpackParWrite::Pars parFilesUnpack{.asic = asicparset, .digi = digiparset, .setup = fConfig.setupType}; + auto* trdUnpackPar = new CbmTaskTrdUnpackParWrite{parFilesUnpack}; + fRun->AddTask(trdUnpackPar); } // =========================================================================== @@ -99,15 +132,18 @@ void CbmOnlineParWrite::AddTof() switch (fConfig.setupType) { case Setup::mCBM2022: doCalibration = true; - cCalId = "2391.5.000"; - iCalSet = 22002500; + cCalId = "2391.5.000"; + iCalSet = 22002500; break; case Setup::mCBM2024_03: doCalibration = true; - cCalId = "2912.1"; - iCalSet = 012032500; + cCalId = "2912.1"; + iCalSet = 012032500; + break; + case Setup::mCBM2024_05: + doCalibration = true; + cFname = Form("%s/3036_1_TofCal.hst.root", TofFileFolder.Data()); break; - case Setup::mCBM2024_05: doCalibration = false; break; default: throw std::runtime_error("TOF: Unknown setup type"); } @@ -141,6 +177,10 @@ void CbmOnlineParWrite::AddSts() // recoSts->SetTimeCutDigisAbs(20.0); // cluster finder: time cut in ns // recoSts->SetTimeCutClustersAbs(20.0); // hit finder: time cut in ns + TString geoTag; + fSetup->GetGeoTag(ECbmModuleId::kTof, geoTag); + LOG(info) << "STS geo tag: " << geoTag; + // Sensor params CbmStsParSensor sensor6cm(CbmStsSensorClass::kDssdStereo); sensor6cm.SetPar(0, 6.2092); // Extension in x @@ -379,4 +419,7 @@ void CbmOnlineParWrite::Run(const Config& config) gGeoManager->GetListOfVolumes()->Delete(); gGeoManager->GetListOfShapes()->Delete(); delete gGeoManager; + + // Delete files created by FairRun that I don't know how disable otherwise + gSystem->Exec("rm all_*.par"); } diff --git a/reco/tasks/CMakeLists.txt b/reco/tasks/CMakeLists.txt index 394be81dfde62c6c028f16cd86cd4332a95c058a..e16f986287de76cc2da9a0681360e50c28b01171 100644 --- a/reco/tasks/CMakeLists.txt +++ b/reco/tasks/CMakeLists.txt @@ -21,6 +21,7 @@ set(SRCS CbmTaskTofClusterizerParWrite.cxx CbmTaskTrdHitFinder.cxx CbmTaskTrdHitFinderParWrite.cxx + CbmTaskTrdUnpackParWrite.cxx CbmTaskStsHitFinderParWrite.cxx CbmTaskUnpack.cxx ) diff --git a/reco/tasks/CbmTaskTrdUnpackParWrite.cxx b/reco/tasks/CbmTaskTrdUnpackParWrite.cxx new file mode 100644 index 0000000000000000000000000000000000000000..f4baf1a72bacc09fb95709c274abd5383923d7dc --- /dev/null +++ b/reco/tasks/CbmTaskTrdUnpackParWrite.cxx @@ -0,0 +1,166 @@ +/* Copyright (C) 2024 FIAS Frankfurt Institute for Advanced Studies, Frankfurt / Main + SPDX-License-Identifier: GPL-3.0-only + Authors: Felix Weiglhofer [committer] */ + +#include "CbmTaskTrdUnpackParWrite.h" + +#include "CbmTrdParFasp.h" +#include "CbmTrdParModAsic.h" +#include "CbmTrdParModDigi.h" +#include "CbmTrdParSetAsic.h" +#include "CbmTrdParSetDigi.h" +#include "CbmTrdParSpadic.h" +#include "trd/ReadoutConfig.h" +#include "trd2d/ReadoutConfig.h" +#include "yaml/Yaml.h" + +#include <FairParamList.h> +#include <fairlogger/Logger.h> + +#include <fstream> + +using namespace cbm::algo; + +InitStatus CbmTaskTrdUnpackParWrite::Init() +{ + + assert(fPars.digi != nullptr); + auto& digiparset = *fPars.digi; + + assert(fPars.asic != nullptr); + auto& asicparset = *fPars.asic; + + + // TRD2D =================================================================== + { + // Output object + cbm::algo::trd2d::ReadoutConfig trd2dConfig; + + // Map (moduleId) -> (array of crobId) + std::map<uint32_t, uint16_t[NCROBMOD]> crobMap; + // Map (equipId, asicId, chanId) -> (pad address, mask flag, daq offset [FASP clk]) + std::map<size_t, std::map<size_t, std::map<size_t, std::tuple<int32_t, bool, uint64_t>>>> channelMap; + + // Loop through a list of module IDs from the .digi file (can in principle contradict crob_map). + for (auto entry : digiparset.GetModuleMap()) { + + const auto moduleId = entry.first; + + // Get ASIC parameters for this module + CbmTrdParModAsic* setDet = static_cast<CbmTrdParModAsic*>(asicparset.GetModulePar(moduleId)); + if (!setDet) continue; + if (setDet->GetAsicType() != CbmTrdDigi::eCbmTrdAsicType::kFASP) continue; + auto digipar = entry.second; + + const int* crobs = setDet->GetCrobAddresses(); + for (int icrob(0); icrob < NCROBMOD; icrob++) + crobMap[moduleId][icrob] = crobs[icrob]; + + // Loop through ASICs for this module + std::vector<int32_t> addresses; + setDet->GetAsicAddresses(&addresses); + for (auto add : addresses) { + //Get local IDs for this component / equipment. + const int32_t fasp_in_mod = add - 1000 * moduleId; + const int32_t fasp_in_eq = fasp_in_mod % (NFASPCROB); + const int32_t crob_in_mod = fasp_in_mod / (NFASPCROB); + const uint16_t eq_id = crobMap[moduleId][crob_in_mod]; + + // ASIC parameter set + CbmTrdParFasp* fasppar = (CbmTrdParFasp*) setDet->GetAsicPar(add); + + // Loop through channels for this ASIC and fill map + for (int chan = 0; chan < fasppar->GetNchannels(); chan++) { + const CbmTrdParFaspChannel* faspch = fasppar->GetChannel(chan); + const int32_t pad = fasppar->GetPadAddress(chan) * (faspch->HasPairingR() ? 1 : -1); + const bool isMasked = faspch->IsMasked(); + uint64_t daq_offset = 0; + if (((CbmTrdParModDigi*) digipar)->GetPadRow(pad) % 2 == 0) daq_offset = 3; + channelMap[eq_id][fasp_in_eq][chan] = std::make_tuple(pad, isMasked, daq_offset); + } + } + } + + trd2dConfig.InitComponentMap(crobMap); + trd2dConfig.InitChannelMap(channelMap); + + std::ofstream("Trd2dReadoutSetup.yaml") << yaml::Dump{}(trd2dConfig); + } + + // TRD1D =================================================================== + { + // Output object + cbm::algo::trd::ReadoutConfig trdConfig; + + FairParamList parlist; + asicparset.putParams(&parlist); + + std::vector<int> moduleIds(asicparset.GetNrOfModules()); + parlist.fill("ModuleId", moduleIds.data(), moduleIds.size()); + + std::map<size_t, std::map<size_t, std::map<size_t, size_t>>> addressMap; //[criId][crobId][elinkId] -> asicAddress + std::map<size_t, std::map<size_t, std::map<size_t, std::map<size_t, size_t>>>> + channelMap; //[criId][crobId][elinkId][chanId] -> chanAddress + + for (auto module : moduleIds) { + CbmTrdParModAsic* moduleSet = (CbmTrdParModAsic*) asicparset.GetModulePar(module); + + // Skip entries for "Fasp" modules in .asic.par file + if (moduleSet->GetAsicType() != CbmTrdDigi::eCbmTrdAsicType::kSPADIC) continue; + + std::vector<int> asicAddresses; + moduleSet->GetAsicAddresses(&asicAddresses); + + for (auto address : asicAddresses) { + CbmTrdParSpadic* asicPar = (CbmTrdParSpadic*) moduleSet->GetAsicPar(address); + const uint16_t criId = asicPar->GetCriId(); + const uint8_t crobId = asicPar->GetCrobId(); + const uint8_t elinkId = asicPar->GetElinkId(0); + if (elinkId >= 98) { + continue; + } // Don't add not connected asics to the map + addressMap[criId][crobId][elinkId] = address; + addressMap[criId][crobId][elinkId + 1] = address; + + const uint8_t numChans = 16; + for (uint8_t chan = 0; chan < numChans; chan++) { + auto asicChannelId = (elinkId % 2) == 0 ? chan : chan + numChans; + auto chanAddr = asicPar->GetChannelAddresses().at(asicChannelId); + channelMap[criId][crobId][elinkId][chan] = chanAddr; + } + for (uint8_t chan = 0; chan < numChans; chan++) { + auto asicChannelId = (elinkId + 1 % 2) == 0 ? chan : chan + numChans; + auto chanAddr = asicPar->GetChannelAddresses().at(asicChannelId); + channelMap[criId][crobId][elinkId + 1][chan] = chanAddr; + } + LOG(debug) << "componentID " << asicPar->GetComponentId() << " " + << "address " << address << " key " << criId << " " << unsigned(crobId) << " " << unsigned(elinkId); + } + } + trdConfig.Init(addressMap, channelMap); + + // Apply time offset per elink + // See: https://git.cbm.gsi.de/computing/cbmroot/-/merge_requests/1751 + if (fPars.setup == Setup::mCBM2024_05) { + for (int elinkId = 0; elinkId < 36; ++elinkId) { + trdConfig.SetElinkTimeOffset(20736, elinkId, -36); + trdConfig.SetElinkTimeOffset(20737, elinkId, -37); + trdConfig.SetElinkTimeOffset(20738, elinkId, -65); + trdConfig.SetElinkTimeOffset(20739, elinkId, -52); + trdConfig.SetElinkTimeOffset(20740, elinkId, -50); + trdConfig.SetElinkTimeOffset(20741, elinkId, -49); + + //trdConfig.SetElinkTimeOffset(20992, elinkId, 0); //no correlation + trdConfig.SetElinkTimeOffset(20993, elinkId, -50); + trdConfig.SetElinkTimeOffset(20994, elinkId, -57); + trdConfig.SetElinkTimeOffset(20995, elinkId, -52); + trdConfig.SetElinkTimeOffset(20996, elinkId, -52); + trdConfig.SetElinkTimeOffset(20997, elinkId, -53); + } + } + + std::ofstream("TrdReadoutSetup.yaml") << yaml::Dump{}(trdConfig); + } + + return kSUCCESS; +} diff --git a/reco/tasks/CbmTaskTrdUnpackParWrite.h b/reco/tasks/CbmTaskTrdUnpackParWrite.h new file mode 100644 index 0000000000000000000000000000000000000000..09203a69ff02e4882afc6ed9f0572f110d2059be --- /dev/null +++ b/reco/tasks/CbmTaskTrdUnpackParWrite.h @@ -0,0 +1,45 @@ +/* Copyright (C) 2024 FIAS Frankfurt Institute for Advanced Studies, Frankfurt / Main + SPDX-License-Identifier: GPL-3.0-only + Authors: Felix Weiglhofer [committer] */ + +#pragma once + +#include "Definitions.h" + +#include <FairTask.h> + +class CbmTrdParSetAsic; +class CbmTrdParSetDigi; + +class CbmTaskTrdUnpackParWrite : public FairTask { + + public: + struct Pars { + CbmTrdParSetAsic* asic; ///< parameter list for ASIC characterization + CbmTrdParSetDigi* digi; ///< parameter list for read-out geometry + cbm::algo::Setup setup; ///< Setup type + }; + + /** + * \brief Default constructor. + */ + CbmTaskTrdUnpackParWrite(Pars pars) : fPars(pars) {} + + /** + * \brief Default destructor. + */ + virtual ~CbmTaskTrdUnpackParWrite(){}; + + /** Initialisation **/ + virtual InitStatus Init(); + virtual void SetParContainers(){}; + + /** \brief Executed task **/ + virtual void Exec(Option_t* /*option*/){}; + + /** Finish task **/ + virtual void Finish(){}; + + private: + Pars fPars; +};