From bffd070a30de02186de7b6afd8a61d1dce0317c2 Mon Sep 17 00:00:00 2001 From: P-A Loizeau <p.-a.loizeau@gsi.de> Date: Mon, 18 Oct 2021 19:01:23 +0200 Subject: [PATCH] [MQ] Add new algo based unpacker device + related changes - Split the InitUnpacker method of the UnpackConfig template into - InitOutput - RegisterOutput (Framework bound, to be replaced by method in Task class CbmRecoUnpack) - SetAlgo - initParContainer, moved to the Task Class CbmRecoUnpack - InitAlgo - Move to the template version of these methods all blocks common to all derived config classes - Whenever necessary, overload these methods in the derived config classes (including the common parts, no base method call) - Bump Config classes version number - Adapt the Sts Unpack algo classes to initialize the monitor classes - Adapt the CbmRecoUnpack - Adapt the CbmUnpackDevice to use the standard Unpack Config classes (compiles with full functionality but untested) --- MQ/mcbm/CMakeLists.txt | 41 + MQ/mcbm/CbmDeviceMcbmUnpack.cxx | 12 +- MQ/mcbm/CbmDeviceUnpack.cxx | 862 ++++++++++++++++++ MQ/mcbm/CbmDeviceUnpack.h | 276 ++++++ MQ/mcbm/runUnpack.cxx | 32 + core/data/CbmTsEventHeader.h | 4 + reco/base/CbmRecoUnpackConfig.tmpl | 204 +++-- .../psd/unpack/CbmPsdUnpackConfig.cxx | 26 +- .../detectors/psd/unpack/CbmPsdUnpackConfig.h | 28 +- .../rich/unpack/CbmRichUnpackConfig.cxx | 27 +- .../rich/unpack/CbmRichUnpackConfig.h | 30 +- .../detectors/sts/unpack/CbmStsUnpackAlgo.cxx | 2 + .../sts/unpack/CbmStsUnpackAlgoLegacy.cxx | 3 + .../sts/unpack/CbmStsUnpackConfig.cxx | 42 +- .../detectors/sts/unpack/CbmStsUnpackConfig.h | 14 +- .../tof/unpack/CbmTofUnpackConfig.cxx | 26 +- .../detectors/tof/unpack/CbmTofUnpackConfig.h | 12 - .../trd/unpack/CbmTrdUnpackConfig.cxx | 15 +- .../detectors/trd/unpack/CbmTrdUnpackConfig.h | 37 +- .../trd/unpack/CbmTrdUnpackConfigFasp2D.cxx | 26 +- .../trd/unpack/CbmTrdUnpackConfigFasp2D.h | 28 +- reco/steer/CMakeLists.txt | 1 + reco/steer/CbmRecoUnpack.cxx | 55 +- reco/steer/CbmRecoUnpack.h | 56 ++ 24 files changed, 1524 insertions(+), 335 deletions(-) create mode 100644 MQ/mcbm/CbmDeviceUnpack.cxx create mode 100644 MQ/mcbm/CbmDeviceUnpack.h create mode 100644 MQ/mcbm/runUnpack.cxx diff --git a/MQ/mcbm/CMakeLists.txt b/MQ/mcbm/CMakeLists.txt index 6671f55ab5..e11e1daafa 100644 --- a/MQ/mcbm/CMakeLists.txt +++ b/MQ/mcbm/CMakeLists.txt @@ -12,6 +12,13 @@ set(INCLUDE_DIRECTORIES ${CBMROOT_SOURCE_DIR}/fles/mcbm2018/commonMQ ${CBMROOT_SOURCE_DIR}/fles/flestools ${CBMROOT_SOURCE_DIR}/reco/eventbuilder/digis + ${CBMROOT_SOURCE_DIR}/reco/base/ + ${CBMROOT_SOURCE_DIR}/reco/detectors/psd/unpack + ${CBMROOT_SOURCE_DIR}/reco/detectors/sts/unpack + ${CBMROOT_SOURCE_DIR}/reco/detectors/tof/unpack + ${CBMROOT_SOURCE_DIR}/reco/detectors/trd/unpack + ${CBMROOT_SOURCE_DIR}/reco/detectors/trd/rawToDigiMethods + ${CBMROOT_SOURCE_DIR}/reco/detectors/rich/unpack ${CBMDATA_DIR} ${CBMDATA_DIR}/global ${CBMDATA_DIR}/raw @@ -23,8 +30,13 @@ set(INCLUDE_DIRECTORIES ${CBMDATA_DIR}/trd ${CBMDATA_DIR}/mvd # Feint to avoid crash of DigiManager due to missing source pointer ${CBMBASE_DIR} + ${CBMROOT_SOURCE_DIR}/sim/transport/steer # For CbmSetup.h! + ${CBMROOT_SOURCE_DIR}/sim/transport/geosetup # For CbmGeoSetupDbProvider.h, needed by CbmSetup + ${CBMDETECTORBASE_DIR}/sts # required for parameter handling of the sts ${CBMDETECTORBASE_DIR}/trd # required for parameter handling of the trd + ${CBMDETECTORBASE_DIR}/tof # required for parameter handling of the tof + ${CBMDETECTORBASE_DIR}/rich # required for parameter handling of the rich ${CBMDETECTORBASE_DIR}/psd # required for fitting tools of the psd ) @@ -191,3 +203,32 @@ set(DEPENDENCIES #GENERATE_LIBRARY() GENERATE_EXECUTABLE() + +set(EXE_NAME MqUnpack) +set(SRCS CbmDeviceUnpack.cxx runUnpack.cxx) + +set(DEPENDENCIES + ${DEPENDENCIES} + ${FAIR_LIBS} + ParBase + ${BOOST_LIBS} + fles_ipc + CbmFlibMcbm2018 + CbmFlibFlesTools + CbmBase + CbmRecoBase + CbmPsdReco + CbmRichReco + CbmRecoSts + CbmTofReco + CbmTrdReco + CbmData + CbmSimSteer # for CbmSetup! + Core + RIO + Net + Hist + RHTTP +) +GENERATE_EXECUTABLE() + diff --git a/MQ/mcbm/CbmDeviceMcbmUnpack.cxx b/MQ/mcbm/CbmDeviceMcbmUnpack.cxx index f73a825c82..d72d85b1ae 100644 --- a/MQ/mcbm/CbmDeviceMcbmUnpack.cxx +++ b/MQ/mcbm/CbmDeviceMcbmUnpack.cxx @@ -475,32 +475,32 @@ Bool_t CbmDeviceMcbmUnpack::DoUnpack(const fles::Timeslice& ts, size_t /*compone if (kFALSE == fUnpAlgoSts->ProcessTs(ts)) { LOG(error) << "Failed processing TS " << ts.index() << " in STS unpacker algorithm class"; - return kTRUE; + return kFALSE; } // if( kFALSE == fUnpAlgoSts->ProcessTs( ts ) ) if (kFALSE == fUnpAlgoMuch->ProcessTs(ts)) { LOG(error) << "Failed processing TS " << ts.index() << " in MUCH unpacker algorithm class"; - return kTRUE; + return kFALSE; } // if( kFALSE == fUnpAlgoMuch->ProcessTs( ts ) ) if (kFALSE == fUnpAlgoTrd->ProcessTs(ts)) { LOG(error) << "Failed processing TS " << ts.index() << " in TRD unpacker algorithm class"; - return kTRUE; + return kFALSE; } // if( kFALSE == fUnpAlgoTrd->ProcessTs( ts ) ) if (kFALSE == fUnpAlgoTof->ProcessTs(ts)) { LOG(error) << "Failed processing TS " << ts.index() << " in TOF unpacker algorithm class"; - return kTRUE; + return kFALSE; } // if( kFALSE == fUnpAlgoTof->ProcessTs( ts ) ) if (kFALSE == fUnpAlgoRich->ProcessTs(ts)) { LOG(error) << "Failed processing TS " << ts.index() << " in RICH unpacker algorithm class"; - return kTRUE; + return kFALSE; } // if( kFALSE == fUnpAlgoRich->ProcessTs( ts ) ) if (kFALSE == fUnpAlgoPsd->ProcessTs(ts)) { LOG(error) << "Failed processing TS " << ts.index() << " in PSD unpacker algorithm class"; - return kTRUE; + return kFALSE; } // if( kFALSE == fUnpAlgoPsd->ProcessTs( ts ) ) diff --git a/MQ/mcbm/CbmDeviceUnpack.cxx b/MQ/mcbm/CbmDeviceUnpack.cxx new file mode 100644 index 0000000000..cd895deaaf --- /dev/null +++ b/MQ/mcbm/CbmDeviceUnpack.cxx @@ -0,0 +1,862 @@ +/* Copyright (C) 2021 Facility for Antiproton and Ion Research in Europe, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Pierre-Alain Loizeau [committer] */ + +/** + * CbmDeviceUnpack.cxx + * + * @since 2020-05-04 + * @author P.-A. Loizeau + */ + +#include "CbmDeviceUnpack.h" + +#include "CbmFlesCanvasTools.h" +#include "CbmMQDefs.h" +#include "CbmMuchDigi.h" +#include "CbmPsdUnpackConfig.h" +#include "CbmRichUnpackConfig.h" +#include "CbmSetup.h" +#include "CbmStsUnpackConfig.h" +#include "CbmTofUnpackConfig.h" +#include "CbmTrdUnpackConfig.h" +#include "CbmTrdUnpackConfigFasp2D.h" + +#include "StorableTimeslice.hpp" +#include "TimesliceMetaData.h" + +#include "FairMQLogger.h" +#include "FairMQProgOptions.h" // device->fConfig +#include "FairParGenericSet.h" + +#include "TCanvas.h" +#include "TFile.h" +#include "TH1.h" +#include "TList.h" +#include "TNamed.h" + +#include "BoostSerializer.h" +#include <boost/archive/binary_iarchive.hpp> +#include <boost/serialization/utility.hpp> + +#include <array> +#include <iomanip> +#include <stdexcept> +#include <string> +#include <utility> + +#include "RootSerializer.h" +struct InitTaskError : std::runtime_error { + using std::runtime_error::runtime_error; +}; + +using namespace std; + +//Bool_t bMcbm2018MonitorTaskT0ResetHistos = kFALSE; + +CbmDeviceUnpack::CbmDeviceUnpack() {} + +void CbmDeviceUnpack::InitTask() +try { + /// Read options from executable + LOG(info) << "Init options for CbmDeviceUnpack."; + fsSetupName = fConfig->GetValue<std::string>("Setup"); + fuRunId = fConfig->GetValue<uint32_t>("RunId"); + fbIgnoreOverlapMs = fConfig->GetValue<bool>("IgnOverMs"); + fbOutputFullTimeSorting = fConfig->GetValue<bool>("FullTimeSort"); + fvsSetTimeOffs = fConfig->GetValue<std::vector<std::string>>("SetTimeOffs"); + fsChannelNameDataInput = fConfig->GetValue<std::string>("TsNameIn"); + fsChannelNameDataOutput = fConfig->GetValue<std::string>("TsNameOut"); + /// TODO: option to set fuDigiMaskedIdT0 !!!! + fsAllowedChannels[0] = fsChannelNameDataInput; + + // Get the information about created channels from the device + // Check if the defined channels from the topology (by name) + // are in the list of channels which are possible/allowed + // for the device + // The idea is to check at initilization if the devices are + // properly connected. For the time beeing this is done with a + // nameing convention. It is not avoided that someone sends other + // data on this channel. + //logger::SetLogLevel("INFO"); + + int noChannel = fChannels.size(); + LOG(info) << "Number of defined channels: " << noChannel; + for (auto const& entry : fChannels) { + LOG(info) << "Channel name: " << entry.first; + if (std::string::npos != entry.first.find(fsChannelNameDataInput)) { + if (!IsChannelNameAllowed(entry.first)) throw InitTaskError("Channel name does not match."); + OnData(entry.first, &CbmDeviceUnpack::HandleData); + } // if( entry.first.find( "ts" ) + } // for( auto const &entry : fChannels ) + InitContainers(); +} +catch (InitTaskError& e) { + LOG(error) << e.what(); + // Wrapper defined in CbmMQDefs.h to support different FairMQ versions + cbm::mq::ChangeState(this, cbm::mq::Transition::ErrorFound); +} + +bool CbmDeviceUnpack::IsChannelNameAllowed(std::string channelName) +{ + + for (auto const& entry : fsAllowedChannels) { + std::size_t pos1 = channelName.find(entry); + if (pos1 != std::string::npos) { + const vector<std::string>::const_iterator pos = + std::find(fsAllowedChannels.begin(), fsAllowedChannels.end(), entry); + const vector<std::string>::size_type idx = pos - fsAllowedChannels.begin(); + LOG(info) << "Found " << entry << " in " << channelName; + LOG(info) << "Channel name " << channelName << " found in list of allowed channel names at position " << idx; + return true; + } // if (pos1!=std::string::npos) + } // for(auto const &entry : fsAllowedChannels) + LOG(info) << "Channel name " << channelName << " not found in list of allowed channel names."; + LOG(error) << "Stop device."; + + return false; +} + +Bool_t CbmDeviceUnpack::InitContainers() +{ + LOG(info) << "Init parameter containers for CbmDeviceUnpack."; + + // ----- FIXME: Environment settings? or binary option? + TString srcDir = std::getenv("VMCWORKDIR"); // top source directory, standard C++ library + // TString srcDir = gSystem->Getenv("VMCWORKDIR"); // top source directory + + // ----- CbmSetup ----------------------------------------------------- + auto cbmsetup = CbmSetup::Instance(); + cbmsetup->LoadSetup(fsSetupName.data()); //nh - accesses file system! FIXME + // ------------------------------------------------------------------------ + + /// Initialize the UnpackerConfigs objects and their "user options" + // ---- STS ---- + std::shared_ptr<CbmStsUnpackConfig> stsconfig = nullptr; + TString stsSetupTag = ""; + cbmsetup->GetGeoTag(ECbmModuleId::kSts, stsSetupTag); + if ("" != stsSetupTag) { + stsconfig = std::make_shared<CbmStsUnpackConfig>(std::string(fsSetupName), fuRunId); + if (stsconfig) { + // stsconfig->SetDebugState(); + stsconfig->SetDoWriteOutput(); + stsconfig->SetDoWriteOptOutA("StsDigiPulser"); + std::string parfilesbasepathSts = Form("%s/macro/beamtime/mcbm2021/", srcDir.Data()); + stsconfig->SetParFilesBasePath(parfilesbasepathSts); + /// Enable duplicates rejection, Ignores the ADC for duplicates check + stsconfig->SetDuplicatesRejection(true, true); + /// Enable Monitor plots + // stsconfig->SetMonitor(GetStsMonitor(outfilename, true)); // FIXME: Unsupported for now + stsconfig->SetSystemTimeOffset(-2221); // [ns] value to be updated + + stsconfig->SetMinAdcCut(1, 1); + stsconfig->SetMinAdcCut(2, 1); + stsconfig->SetMinAdcCut(3, 1); + stsconfig->SetMinAdcCut(4, 1); + + stsconfig->MaskNoisyChannel(7, 715); + stsconfig->MaskNoisyChannel(7, 162); + stsconfig->MaskNoisyChannel(7, 159); + stsconfig->MaskNoisyChannel(7, 158); + stsconfig->MaskNoisyChannel(7, 125); + stsconfig->MaskNoisyChannel(7, 124); + stsconfig->MaskNoisyChannel(7, 123); + stsconfig->MaskNoisyChannel(12, 119); + stsconfig->MaskNoisyChannel(3, 85); + stsconfig->MaskNoisyChannel(3, 79); + stsconfig->MaskNoisyChannel(3, 75); + stsconfig->MaskNoisyChannel(3, 56); + stsconfig->MaskNoisyChannel(9, 709); + } + } // if ("" != stsSetupTag) + // ------------- + // ---- TRD ---- + std::shared_ptr<CbmTrdUnpackConfig> trd1Dconfig = nullptr; + TString trdsetuptag = ""; + cbmsetup->GetGeoTag(ECbmModuleId::kTrd, trdsetuptag); + if ("" != trdsetuptag) { + // trd1Dconfig = std::make_shared<CbmTrdUnpackConfig>(trdsetuptag.Data(), fuRunId); + trd1Dconfig = std::make_shared<CbmTrdUnpackConfig>(trdsetuptag.Data(), 3); + if (trd1Dconfig) { + trd1Dconfig->SetDoWriteOutput(); + // Activate the line below to write Trd1D digis to a separate "TrdSpadicDigi" branch. Can be used to separate between Fasp and Spadic digis + // trd1Dconfig->SetOutputBranchName("TrdSpadicDigi"); + // trd1Dconfig->SetDoWriteOptOutA(CbmTrdRawMessageSpadic::GetBranchName()); + // trd1Dconfig->SetDoWriteOptOutB("SpadicInfoMessages"); // SpadicInfoMessages + + std::string parfilesbasepathTrd = Form("%s/parameters/trd", srcDir.Data()); + trd1Dconfig->SetParFilesBasePath(parfilesbasepathTrd); + // trd1Dconfig->SetMonitor(GetTrdMonitor(outfilename)); // FIXME: Unsupported for now + // Get the spadic configuration true = avg baseline active / false plain sample 0 + trd1Dconfig->SetSpadicObject(GetTrdSpadic(true)); + trd1Dconfig->SetSystemTimeOffset(0); // [ns] value to be updated + } + } // if ("" != trdsetuptag) + // ------------- + // ---- TRDFASP2D ---- + std::shared_ptr<CbmTrdUnpackConfigFasp2D> trdfasp2dconfig = nullptr; + if ("" != trdsetuptag) { + trdfasp2dconfig = std::make_shared<CbmTrdUnpackConfigFasp2D>(trdsetuptag.Data(), 3); + if (trdfasp2dconfig) { + // trdfasp2dconfig->SetDebugState(); + trdfasp2dconfig->SetDoWriteOutput(); + // Activate the line below to write Trd1D digis to a separate "TrdFaspDigi" branch. Can be used to separate between Fasp and Spadic digis + trdfasp2dconfig->SetOutputBranchName("TrdFaspDigi"); + std::string parfilesbasepathTrdfasp2d = Form("%s/parameters/trd", srcDir.Data()); + trdfasp2dconfig->SetParFilesBasePath(parfilesbasepathTrdfasp2d); + trdfasp2dconfig->SetSystemTimeOffset(-1800); // [ns] value to be updated + } + } // if ("" != trdsetuptag) + // ------------- + // ---- TOF ---- + std::shared_ptr<CbmTofUnpackConfig> tofconfig = nullptr; + TString tofSetupTag = ""; + cbmsetup->GetGeoTag(ECbmModuleId::kTof, tofSetupTag); + if ("" != tofSetupTag) { + tofconfig = std::make_shared<CbmTofUnpackConfig>("", fuRunId); + if (tofconfig) { + // tofconfig->SetDebugState(); + tofconfig->SetDoWriteOutput(); + // tofconfig->SetDoWriteOptOutA("CbmTofErrors"); + std::string parfilesbasepathTof = Form("%s/macro/beamtime/mcbm2021/", srcDir.Data()); + tofconfig->SetParFilesBasePath(parfilesbasepathTof); + tofconfig->SetSystemTimeOffset(-1220); // [ns] value to be updated + } + } // if ("" != tofSetupTag) + // ------------- + // ---- RICH ---- + std::shared_ptr<CbmRichUnpackConfig> richconfig = nullptr; + TString richSetupTag = ""; + cbmsetup->GetGeoTag(ECbmModuleId::kRich, richSetupTag); + if ("" != richSetupTag) { + richconfig = std::make_shared<CbmRichUnpackConfig>("", fuRunId); + if (richconfig) { + richconfig->SetDebugState(); + richconfig->SetDoWriteOutput(); + std::string parfilesbasepathRich = Form("%s/macro/beamtime/mcbm2021/", srcDir.Data()); + richconfig->SetParFilesBasePath(parfilesbasepathRich); + richconfig->SetSystemTimeOffset(256000 - 1200); // [ns] 1 MS and additional correction + if (1588 == fuRunId) richconfig->MaskDiRICH(0x7150); + } + } // if ("" != richSetupTag) + // ------------- + // ---- PSD ---- + std::shared_ptr<CbmPsdUnpackConfig> psdconfig = nullptr; + TString psdSetupTag = ""; + cbmsetup->GetGeoTag(ECbmModuleId::kPsd, psdSetupTag); + if ("" != psdSetupTag) { + psdconfig = std::make_shared<CbmPsdUnpackConfig>("", fuRunId); + if (psdconfig) { + // psdconfig->SetDebugState(); + psdconfig->SetDoWriteOutput(); + // psdconfig->SetDoWriteOptOutA("CbmPsdDsp"); + std::string parfilesbasepathPsd = Form("%s/macro/beamtime/mcbm2021/", srcDir.Data()); + psdconfig->SetParFilesBasePath(parfilesbasepathPsd); + psdconfig->SetSystemTimeOffset(0); // [ns] value to be updated + } + } // if ("" != psdSetupTag) + // ------------- + + /// Enable full time sorting instead of time sorting per FLIM link + if (stsconfig) SetUnpackConfig(stsconfig); + if (trd1Dconfig) SetUnpackConfig(trd1Dconfig); + if (trdfasp2dconfig) SetUnpackConfig(trdfasp2dconfig); + if (tofconfig) SetUnpackConfig(tofconfig); + if (richconfig) SetUnpackConfig(richconfig); + if (psdconfig) SetUnpackConfig(psdconfig); + + /// Load time offsets + for (std::vector<std::string>::iterator itStrOffs = fvsSetTimeOffs.begin(); itStrOffs != fvsSetTimeOffs.end(); + ++itStrOffs) { + size_t charPosDel = (*itStrOffs).find(','); + if (std::string::npos == charPosDel) { + LOG(info) << "CbmDeviceUnpack::InitContainers => " + << "Trying to set trigger window with invalid option pattern, ignored! " + << " (Should be ECbmModuleId,dWinBeg,dWinEnd but instead found " << (*itStrOffs) << " )"; + } // if( std::string::npos == charPosDel ) + + /// Detector Enum Tag + std::string sSelDet = (*itStrOffs).substr(0, charPosDel); + /// Min number + charPosDel++; + int32_t iOffset = std::stoi((*itStrOffs).substr(charPosDel)); + + if ("kSTS" == sSelDet && fStsConfig) { // + fStsConfig->SetSystemTimeOffset(iOffset); + + fStsConfig->SetMinAdcCut(1, 1); + fStsConfig->SetMinAdcCut(2, 1); + fStsConfig->SetMinAdcCut(3, 1); + fStsConfig->SetMinAdcCut(4, 1); + + fStsConfig->MaskNoisyChannel(7, 715); + fStsConfig->MaskNoisyChannel(7, 162); + fStsConfig->MaskNoisyChannel(7, 159); + fStsConfig->MaskNoisyChannel(7, 158); + fStsConfig->MaskNoisyChannel(7, 125); + fStsConfig->MaskNoisyChannel(7, 124); + fStsConfig->MaskNoisyChannel(7, 123); + fStsConfig->MaskNoisyChannel(12, 119); + fStsConfig->MaskNoisyChannel(3, 85); + fStsConfig->MaskNoisyChannel(3, 79); + fStsConfig->MaskNoisyChannel(3, 75); + fStsConfig->MaskNoisyChannel(3, 56); + fStsConfig->MaskNoisyChannel(9, 709); + + // Time OffSet + // U2 MOD1 + fStsConfig->SetAsicTimeOffset(104, 0.235097); + fStsConfig->SetAsicTimeOffset(105, -0.919854); + fStsConfig->SetAsicTimeOffset(106, 0.470871); + fStsConfig->SetAsicTimeOffset(107, -0.302136); + fStsConfig->SetAsicTimeOffset(108, 0.0538701); + fStsConfig->SetAsicTimeOffset(109, -0.726945); + fStsConfig->SetAsicTimeOffset(110, -0.474958); + fStsConfig->SetAsicTimeOffset(111, -0.426105); + fStsConfig->SetAsicTimeOffset(112, -0.642128); + fStsConfig->SetAsicTimeOffset(113, 3.90217); + fStsConfig->SetAsicTimeOffset(114, 4.50206); + fStsConfig->SetAsicTimeOffset(115, 4.16447); + fStsConfig->SetAsicTimeOffset(116, 5.00525); + fStsConfig->SetAsicTimeOffset(117, 4.2554); + fStsConfig->SetAsicTimeOffset(118, 5.51313); + fStsConfig->SetAsicTimeOffset(119, 3.38058); + // U2 MOD0 + fStsConfig->SetAsicTimeOffset(88, 5.32785); + fStsConfig->SetAsicTimeOffset(89, 5.10337); + fStsConfig->SetAsicTimeOffset(90, 6.63223); + fStsConfig->SetAsicTimeOffset(91, 4.44318); + fStsConfig->SetAsicTimeOffset(92, 6.5406); + fStsConfig->SetAsicTimeOffset(93, 3.82063); + fStsConfig->SetAsicTimeOffset(94, 5.8673); + fStsConfig->SetAsicTimeOffset(95, 4.41679); + fStsConfig->SetAsicTimeOffset(96, 0.917994); + fStsConfig->SetAsicTimeOffset(97, 2.7819); + fStsConfig->SetAsicTimeOffset(98, 5.61836); + fStsConfig->SetAsicTimeOffset(99, 5.9533); + fStsConfig->SetAsicTimeOffset(100, 5.9789); + fStsConfig->SetAsicTimeOffset(101, 5.24167); + fStsConfig->SetAsicTimeOffset(102, 7.14848); + fStsConfig->SetAsicTimeOffset(103, 6.12267); + // U1 MOD1 + fStsConfig->SetAsicTimeOffset(64, 6.94614); + fStsConfig->SetAsicTimeOffset(65, 6.79433); + fStsConfig->SetAsicTimeOffset(66, 5.57188); + fStsConfig->SetAsicTimeOffset(67, 4.78256); + fStsConfig->SetAsicTimeOffset(68, 4.47773); + fStsConfig->SetAsicTimeOffset(69, 3.70702); + fStsConfig->SetAsicTimeOffset(70, 4.02281); + fStsConfig->SetAsicTimeOffset(71, 4.74402); + fStsConfig->SetAsicTimeOffset(72, 2.13448); + fStsConfig->SetAsicTimeOffset(73, 3.28798); + fStsConfig->SetAsicTimeOffset(74, 4.13604); + fStsConfig->SetAsicTimeOffset(76, 5.02552); + fStsConfig->SetAsicTimeOffset(77, 3.55128); + fStsConfig->SetAsicTimeOffset(78, 4.66596); + fStsConfig->SetAsicTimeOffset(79, 3.76298); + // U1 MOD0 + fStsConfig->SetAsicTimeOffset(48, 10.0742); + fStsConfig->SetAsicTimeOffset(49, 9.31221); + fStsConfig->SetAsicTimeOffset(50, 6.09788); + fStsConfig->SetAsicTimeOffset(51, 2.85866); + fStsConfig->SetAsicTimeOffset(52, 5.45111); + fStsConfig->SetAsicTimeOffset(53, 3.18376); + fStsConfig->SetAsicTimeOffset(54, 4.77448); + fStsConfig->SetAsicTimeOffset(55, 3.20388); + fStsConfig->SetAsicTimeOffset(56, 3.37812); + fStsConfig->SetAsicTimeOffset(57, 4.08165); + fStsConfig->SetAsicTimeOffset(58, 5.06481); + fStsConfig->SetAsicTimeOffset(59, 4.39388); + fStsConfig->SetAsicTimeOffset(60, 5.63931); + fStsConfig->SetAsicTimeOffset(61, 4.15354); + fStsConfig->SetAsicTimeOffset(62, 6.67062); + fStsConfig->SetAsicTimeOffset(63, 6.33579); + // U0 MOD1 + fStsConfig->SetAsicTimeOffset(24, 5.01505); + fStsConfig->SetAsicTimeOffset(25, 3.84039); + fStsConfig->SetAsicTimeOffset(26, 5.36344); + fStsConfig->SetAsicTimeOffset(27, 2.96807); + fStsConfig->SetAsicTimeOffset(28, 4.14668); + fStsConfig->SetAsicTimeOffset(29, 2.4282); + fStsConfig->SetAsicTimeOffset(30, 4.02055); + fStsConfig->SetAsicTimeOffset(31, 4.13309); + fStsConfig->SetAsicTimeOffset(32, 1.2073); + fStsConfig->SetAsicTimeOffset(33, 4.02747); + fStsConfig->SetAsicTimeOffset(34, 5.03306); + fStsConfig->SetAsicTimeOffset(35, 3.5234); + fStsConfig->SetAsicTimeOffset(36, 5.41946); + fStsConfig->SetAsicTimeOffset(37, 4.82807); + fStsConfig->SetAsicTimeOffset(38, 6.33436); + fStsConfig->SetAsicTimeOffset(39, 4.71413); + // U0 MOD0 + fStsConfig->SetAsicTimeOffset(8, 8.15031); + fStsConfig->SetAsicTimeOffset(9, 6.99897); + fStsConfig->SetAsicTimeOffset(10, 8.14826); + fStsConfig->SetAsicTimeOffset(11, 3.29095); + fStsConfig->SetAsicTimeOffset(12, 3.04337); + fStsConfig->SetAsicTimeOffset(14, 3.71628); + fStsConfig->SetAsicTimeOffset(15, 3.82512); + fStsConfig->SetAsicTimeOffset(16, 4.05862); + fStsConfig->SetAsicTimeOffset(17, 4.53291); + fStsConfig->SetAsicTimeOffset(18, 5.22825); + fStsConfig->SetAsicTimeOffset(19, 4.93144); + fStsConfig->SetAsicTimeOffset(20, 6.33821); + fStsConfig->SetAsicTimeOffset(21, 5.66979); + fStsConfig->SetAsicTimeOffset(22, 9.33802); + fStsConfig->SetAsicTimeOffset(23, 7.41302); + } // if( "kSTS" == sSelDet && fStsConfig) + /* + else if ("kMUCH" == sSelDet) { + fUnpAlgoMuch->SetSystemTimeOffset(iOffset); + } // else if( "kMUCH" == sSelDet ) +*/ + else if ("kTRD" == sSelDet && fTrd1DConfig) { + fTrd1DConfig->SetSystemTimeOffset(iOffset); + } // else if( "kTRD" == sSelDet && fTrd2DConfig ) + else if ("kTRD2D" == sSelDet && fTrd2DConfig) { + fTrd2DConfig->SetSystemTimeOffset(iOffset); + } // else if( "kTRD" == sSelDet && fTrd2DConfig ) + else if ("kTOF" == sSelDet && fTofConfig) { + fTofConfig->SetSystemTimeOffset(iOffset); + } // else if( "kTOF" == sSelDet && fTofConfig) + else if ("kRICH" == sSelDet && fRichConfig) { + fRichConfig->SetSystemTimeOffset(iOffset); + } // else if( "kRICH" == sSelDet && fRichConfig) + else if ("kPSD" == sSelDet && fPsdConfig) { + fPsdConfig->SetSystemTimeOffset(iOffset); + } // else if( "kPSD" == sSelDet ) + else { + LOG(info) << "CbmDeviceUnpack::InitContainers => Trying to set time " + "offset for unsupported detector, ignored! " + << (sSelDet); + continue; + } // else of detector enum detection + } // for( std::vector< std::string >::iterator itStrAdd = fvsAddDet.begin(); itStrAdd != fvsAddDet.end(); ++itStrAdd ) + + Bool_t initOK = kTRUE; + // --- Sts + if (fStsConfig) { + fStsConfig->InitOutput(); + // RegisterOutputs( ioman, fStsConfig ); /// Framework bound work = kept in this Task + fStsConfig->SetDoIgnoreOverlappMs(fbIgnoreOverlapMs); + fStsConfig->SetAlgo(); + initOK &= InitParameters(fStsConfig->GetParContainerRequest()); /// Framework bound work = kept in this Device + fStsConfig->InitAlgo(); + // initPerformanceMaps(fkFlesSts, "STS"); + } + // --- Tof + if (fTofConfig) { + fTofConfig->InitOutput(); + // RegisterOutputs( ioman, fTofConfig ); /// Framework bound work = kept in this Task + fTofConfig->SetDoIgnoreOverlappMs(fbIgnoreOverlapMs); + fTofConfig->SetAlgo(); + initOK &= InitParameters(fTofConfig->GetParContainerRequest()); /// Framework bound work = kept in this Device + LOG(info) << "TOF call InitAlgo()"; + fTofConfig->InitAlgo(); + // initPerformanceMaps(fkFlesTof, "TOF"); + } + // --- Trd + if (fTrd1DConfig) { + fTrd1DConfig->InitOutput(); + // RegisterOutputs( ioman, fTrd1DConfig ); /// Framework bound work = kept in this Task + fTrd1DConfig->SetDoIgnoreOverlappMs(fbIgnoreOverlapMs); + fTrd1DConfig->SetAlgo(); + initOK &= InitParameters(fTrd1DConfig->GetParContainerRequest()); /// Framework bound work = kept in this Device + fTrd1DConfig->InitAlgo(); + // initPerformanceMaps(fkFlesTrd, "TRD1D"); + } + // --- TRD2D + if (fTrd2DConfig) { + if (fTrd1DConfig && (fTrd2DConfig->GetOutputBranchName() == fTrd1DConfig->GetOutputBranchName())) { + LOG(info) << fTrd2DConfig->GetName() << "::Init() ---------------------------------"; + fTrd2DConfig->SetOutputVec(fTrd1DConfig->GetOutputVec()); + } + else { + fTrd2DConfig->InitOutput(); + // RegisterOutputs( ioman, fTrd2DConfig ); /// Framework bound work = kept in this Task + } + fTrd2DConfig->SetDoIgnoreOverlappMs(fbIgnoreOverlapMs); + fTrd2DConfig->SetAlgo(); + initOK &= InitParameters(fTrd2DConfig->GetParContainerRequest()); /// Framework bound work = kept in this Device + fTrd2DConfig->InitAlgo(); + // initPerformanceMaps(fkFlesTrd2D, "TRD2D"); + } + // This is an ugly work around, because the TRD and TRD2D want to access the same vector and there is no + // function to retrieve a writeable vector<obj> from the FairRootManager, especially before the branches + // are created, as far as I am aware. + // The second option workaround is in in Init() to look for the fasp config and create a separate branch + // for fasp created CbmTrdDigis PR 072021 + // --- Rich + if (fRichConfig) { + fRichConfig->InitOutput(); + // RegisterOutputs( ioman, fRichConfig ); /// Framework bound work = kept in this Task + fRichConfig->SetDoIgnoreOverlappMs(fbIgnoreOverlapMs); + fRichConfig->SetAlgo(); + initOK &= InitParameters(fRichConfig->GetParContainerRequest()); /// Framework bound work = kept in this Device + fRichConfig->InitAlgo(); + // initPerformanceMaps(fkFlesRich, "RICH"); + } + // --- Psd + if (fPsdConfig) { + fPsdConfig->InitOutput(); + // RegisterOutputs( ioman, fPsdConfig ); /// Framework bound work = kept in this Task + fPsdConfig->SetDoIgnoreOverlappMs(fbIgnoreOverlapMs); + fPsdConfig->SetAlgo(); + initOK &= InitParameters(fPsdConfig->GetParContainerRequest()); /// Framework bound work = kept in this Device + fPsdConfig->InitAlgo(); + // initPerformanceMaps(fkFlesPsd, "PSD"); + } + + /// Event header object + fCbmTsEventHeader = new CbmTsEventHeader(); + + return initOK; +} + +Bool_t +CbmDeviceUnpack::InitParameters(std::vector<std::pair<std::string, std::shared_ptr<FairParGenericSet>>>* reqparvec) +{ + LOG(info) << "CbmDeviceUnpack::InitParameters"; + if (!reqparvec) { + LOG(info) << "CbmDeviceUnpack::InitParameters - empty requirements vector no parameters initialized."; + return kTRUE; + } + + // Now get the actual ascii files and init the containers with the asciiIo + for (auto& pair : *reqparvec) { + /* + auto filepath = pair.first; + auto parset = pair.second; + FairParAsciiFileIo asciiInput; + if (!filepath.empty()) { + if (asciiInput.open(filepath.data())) { parset->init(&asciiInput); } + } + * */ + std::string paramName {pair.second->GetName()}; + // NewSimpleMessage creates a copy of the data and takes care of its destruction (after the transfer takes place). + // Should only be used for small data because of the cost of an additional copy + + // Here must come the proper Runid + std::string message = paramName + ",111"; + LOG(info) << "Requesting parameter container " << paramName << ", sending message: " << message; + + FairMQMessagePtr req(NewSimpleMessage(message)); + FairMQMessagePtr rep(NewMessage()); + + FairParGenericSet* newObj = nullptr; + + if (Send(req, "parameters") > 0) { + if (Receive(rep, "parameters") >= 0) { + if (0 != rep->GetSize()) { + CbmMqTMessage tmsg(rep->GetData(), rep->GetSize()); + newObj = static_cast<FairParGenericSet*>(tmsg.ReadObject(tmsg.GetClass())); + LOG(info) << "Received unpack parameter from the server: " << newObj->GetName(); + newObj->print(); + } // if( 0 != rep->GetSize() ) + else { + LOG(error) << "Received empty reply. Parameter not available"; + return kFALSE; + } // else of if( 0 != rep->GetSize() ) + } // if( Receive( rep, "parameters" ) >= 0) + } // if( Send(req, "parameters") > 0 ) + pair.second.reset(newObj); /// Potentially unsafe reasignment of raw pointer to the shared pointer? + //delete newObj; + } + return kTRUE; +} + +// handler is called whenever a message arrives on "data", with a reference to the message and a sub-channel index (here 0) +bool CbmDeviceUnpack::HandleData(FairMQMessagePtr& msg, int /*index*/) +{ + fulNumMessages++; + LOG(debug) << "Received message number " << fulNumMessages << " with size " << msg->GetSize(); + + if (0 == fulNumMessages % 10000) LOG(info) << "Received " << fulNumMessages << " messages"; + + std::string msgStr(static_cast<char*>(msg->GetData()), msg->GetSize()); + std::istringstream iss(msgStr); + boost::archive::binary_iarchive inputArchive(iss); + + /// Create an empty TS and fill it with the incoming message + fles::StorableTimeslice ts {0}; + inputArchive >> ts; + + /// On first TS, extract the TS parameters from header (by definition stable over time) + if (-1.0 == fdTsCoreSizeInNs) { + fuNbCoreMsPerTs = ts.num_core_microslices(); + fuNbOverMsPerTs = ts.num_microslices(0) - ts.num_core_microslices(); + fdMsSizeInNs = (ts.descriptor(0, fuNbCoreMsPerTs).idx - ts.descriptor(0, 0).idx) / fuNbCoreMsPerTs; + fdTsCoreSizeInNs = fdMsSizeInNs * (fuNbCoreMsPerTs); + fdTsOverSizeInNs = fdMsSizeInNs * (fuNbOverMsPerTs); + fdTsFullSizeInNs = fdTsCoreSizeInNs + fdTsOverSizeInNs; + LOG(info) << "Timeslice parameters: each TS has " << fuNbCoreMsPerTs << " Core MS and " << fuNbOverMsPerTs + << " Overlap MS, for a MS duration of " << fdMsSizeInNs << " ns, a core duration of " << fdTsCoreSizeInNs + << " ns and a full duration of " << fdTsFullSizeInNs << " ns"; + fTsMetaData = new TimesliceMetaData(ts.descriptor(0, 0).idx, fdTsCoreSizeInNs, fdTsOverSizeInNs, ts.index()); + } // if( -1.0 == fdTsCoreSizeInNs ) + else { + /// Update only the fields changing from TS to TS + fTsMetaData->SetStartTime(ts.descriptor(0, 0).idx); + fTsMetaData->SetIndex(ts.index()); + } + + /// Process the Timeslice + DoUnpack(ts, 0); + + /// Send digi vectors to ouput + if (!SendUnpData()) return false; + + // Reset the event header for a new timeslice + fCbmTsEventHeader->Reset(); + + // Reset the unpackers for a new timeslice, e.g. clear the output vectors + // ---- Sts ---- + if (fStsConfig) fStsConfig->Reset(); + // ---- Tof ---- + if (fTofConfig) fTofConfig->Reset(); + // ---- Trd ---- + if (fTrd1DConfig) fTrd1DConfig->Reset(); + // ---- Trd2D ---- + if (fTrd2DConfig) fTrd2DConfig->Reset(); + // ---- Rich ---- + if (fRichConfig) fRichConfig->Reset(); + // ---- Psd ---- + if (fPsdConfig) fPsdConfig->Reset(); + + return true; +} + +bool CbmDeviceUnpack::SendUnpData() +{ + FairMQParts parts; + + /// Prepare serialized versions of the TS Event header + FairMQMessagePtr messTsHeader(NewMessage()); + Serialize<RootSerializer>(*messTsHeader, fCbmTsEventHeader); + parts.AddPart(std::move(messTsHeader)); + + // ---- T0 ---- + std::stringstream ossT0; + boost::archive::binary_oarchive oaT0(ossT0); + // oaT0 << fUnpAlgoTof->GetOptOutAVec(); + oaT0 << (std::vector<CbmTofDigi>()); + std::string* strMsgT0 = new std::string(ossT0.str()); + + parts.AddPart(NewMessage( + const_cast<char*>(strMsgT0->c_str()), // data + strMsgT0->length(), // size + [](void*, void* object) { delete static_cast<std::string*>(object); }, + strMsgT0)); // object that manages the data + + // ---- Sts ---- + std::stringstream ossSts; + boost::archive::binary_oarchive oaSts(ossSts); + if (fStsConfig) { // + oaSts << *(fStsConfig->GetOutputVec()); + } + std::string* strMsgSts = new std::string(ossSts.str()); + + parts.AddPart(NewMessage( + const_cast<char*>(strMsgSts->c_str()), // data + strMsgSts->length(), // size + [](void*, void* object) { delete static_cast<std::string*>(object); }, + strMsgSts)); // object that manages the data + + // ---- Much ---- + std::stringstream ossMuch; + boost::archive::binary_oarchive oaMuch(ossMuch); + // oaMuch << fUnpAlgoMuch->GetVector(); + oaMuch << (std::vector<CbmMuchDigi>()); + std::string* strMsgMuch = new std::string(ossMuch.str()); + + parts.AddPart(NewMessage( + const_cast<char*>(strMsgMuch->c_str()), // data + strMsgMuch->length(), // size + [](void*, void* object) { delete static_cast<std::string*>(object); }, + strMsgMuch)); // object that manages the data + + + // ---- Trd ---- + std::stringstream ossTrd; + boost::archive::binary_oarchive oaTrd(ossTrd); + if (fTrd1DConfig || fTrd2DConfig) { // + oaTrd << *(fTrd1DConfig ? fTrd1DConfig->GetOutputVec() : fTrd2DConfig->GetOutputVec()); + } + std::string* strMsgTrd = new std::string(ossTrd.str()); + + parts.AddPart(NewMessage( + const_cast<char*>(strMsgTrd->c_str()), // data + strMsgTrd->length(), // size + [](void*, void* object) { delete static_cast<std::string*>(object); }, + strMsgTrd)); // object that manages the data + + // ---- Tof ---- + std::stringstream ossTof; + boost::archive::binary_oarchive oaTof(ossTof); + if (fTofConfig) { // + oaTof << *(fTofConfig->GetOutputVec()); + } + std::string* strMsgTof = new std::string(ossTof.str()); + + parts.AddPart(NewMessage( + const_cast<char*>(strMsgTof->c_str()), // data + strMsgTof->length(), // size + [](void*, void* object) { delete static_cast<std::string*>(object); }, + strMsgTof)); // object that manages the data + + // ---- Rich ---- + std::stringstream ossRich; + boost::archive::binary_oarchive oaRich(ossRich); + if (fRichConfig) { // + oaRich << *(fRichConfig->GetOutputVec()); + } + std::string* strMsgRich = new std::string(ossRich.str()); + + parts.AddPart(NewMessage( + const_cast<char*>(strMsgRich->c_str()), // data + strMsgRich->length(), // size + [](void*, void* object) { delete static_cast<std::string*>(object); }, + strMsgRich)); // object that manages the data + + // ---- Psd ---- + std::stringstream ossPsd; + boost::archive::binary_oarchive oaPsd(ossPsd); + if (fPsdConfig) { // + oaPsd << *(fPsdConfig->GetOutputVec()); + } + std::string* strMsgPsd = new std::string(ossPsd.str()); + + parts.AddPart(NewMessage( + const_cast<char*>(strMsgPsd->c_str()), // data + strMsgPsd->length(), // size + [](void*, void* object) { delete static_cast<std::string*>(object); }, + strMsgPsd)); // object that manages the data + + /// Prepare serialized versions of the TS Meta + /// FIXME: only for TS duration and overlap, should be sent to parameter service instead as stable values in run + /// Index and start time are already included in the TsHeader object! + FairMQMessagePtr messTsMeta(NewMessage()); + Serialize<RootSerializer>(*messTsMeta, fTsMetaData); + parts.AddPart(std::move(messTsMeta)); + + if (Send(parts, fsChannelNameDataOutput) < 0) { + LOG(error) << "Problem sending data to " << fsChannelNameDataOutput; + return false; + } + + return true; +} + + +CbmDeviceUnpack::~CbmDeviceUnpack() +{ + if (fStsConfig) fStsConfig->GetUnpacker()->Finish(); + if (fTofConfig) fTofConfig->GetUnpacker()->Finish(); + if (fTrd1DConfig) fTrd1DConfig->GetUnpacker()->Finish(); + if (fTrd2DConfig) fTrd2DConfig->GetUnpacker()->Finish(); + if (fRichConfig) fRichConfig->GetUnpacker()->Finish(); + if (fPsdConfig) fPsdConfig->GetUnpacker()->Finish(); +} + +Bool_t CbmDeviceUnpack::DoUnpack(const fles::Timeslice& ts, size_t /*component*/) +{ + fulTsCounter++; + // Prepare timeslice + // const fles::Timeslice& timeslice = *ts; + + fCbmTsEventHeader->SetTsIndex(ts.index()); + fCbmTsEventHeader->SetTsStartTime(ts.start_time()); + + uint64_t nComponents = ts.num_components(); + // if (fDoDebugPrints) LOG(info) << "Unpack: TS index " << ts.index() << " components " << nComponents; + LOG(info) << "Unpack: TS index " << ts.index() << " components " << nComponents; + + for (uint64_t component = 0; component < nComponents; component++) { + auto systemId = static_cast<std::uint16_t>(ts.descriptor(component, 0).sys_id); + + switch (systemId) { + case fkFlesSts: { + if (fStsConfig) { + fCbmTsEventHeader->AddNDigisSts( + unpack(systemId, &ts, component, fStsConfig, fStsConfig->GetOptOutAVec(), fStsConfig->GetOptOutBVec())); + } + break; + } + case fkFlesTof: { + if (fTofConfig) { + fCbmTsEventHeader->AddNDigisTof( + unpack(systemId, &ts, component, fTofConfig, fTofConfig->GetOptOutAVec(), fTofConfig->GetOptOutBVec())); + } + break; + } + case fkFlesTrd: { + if (fTrd1DConfig) { + fCbmTsEventHeader->AddNDigisTrd1D(unpack(systemId, &ts, component, fTrd1DConfig, + fTrd1DConfig->GetOptOutAVec(), fTrd1DConfig->GetOptOutBVec())); + } + break; + } + case fkFlesTrd2D: { + if (fTrd2DConfig) { + fCbmTsEventHeader->AddNDigisTrd2D(unpack(systemId, &ts, component, fTrd2DConfig, + fTrd2DConfig->GetOptOutAVec(), fTrd2DConfig->GetOptOutBVec())); + } + break; + } + case fkFlesRich: { + if (fRichConfig) { + fCbmTsEventHeader->AddNDigisRich( + unpack(systemId, &ts, component, fRichConfig, fRichConfig->GetOptOutAVec(), fRichConfig->GetOptOutBVec())); + } + break; + } + case fkFlesPsd: { + if (fPsdConfig) { + fCbmTsEventHeader->AddNDigisPsd( + unpack(systemId, &ts, component, fPsdConfig, fPsdConfig->GetOptOutAVec(), fPsdConfig->GetOptOutBVec())); + } + break; + } + default: { + if (fDoDebugPrints) LOG(error) << "Unpack: Unknown system ID " << systemId << " for component " << component; + break; + } + } + } + + if (fbOutputFullTimeSorting) { + /// Time sort the output vectors of all unpackers present + if (fStsConfig && fStsConfig->GetOutputVec()) { timesort(fStsConfig->GetOutputVec()); } + if (fTofConfig && fTofConfig->GetOutputVec()) { timesort(fTofConfig->GetOutputVec()); } + if (fTrd1DConfig && fTrd1DConfig->GetOutputVec()) { timesort(fTrd1DConfig->GetOutputVec()); } + if (fTrd2DConfig && fTrd2DConfig->GetOutputVec()) { timesort(fTrd2DConfig->GetOutputVec()); } + if (fRichConfig && fRichConfig->GetOutputVec()) { timesort(fRichConfig->GetOutputVec()); } + if (fPsdConfig && fPsdConfig->GetOutputVec()) { timesort(fPsdConfig->GetOutputVec()); } + + /// Time sort the output vectors of all unpackers present + if (fStsConfig && fStsConfig->GetOptOutAVec()) { timesort(fStsConfig->GetOptOutAVec()); } + if (fTofConfig && fTofConfig->GetOptOutAVec()) { timesort(fTofConfig->GetOptOutAVec()); } + if (fTrd1DConfig && fTrd1DConfig->GetOptOutAVec()) { timesort(fTrd1DConfig->GetOptOutAVec()); } + if (fTrd2DConfig && fTrd2DConfig->GetOptOutAVec()) { timesort(fTrd2DConfig->GetOptOutAVec()); } + if (fRichConfig && fRichConfig->GetOptOutAVec()) { timesort(fRichConfig->GetOptOutAVec()); } + if (fPsdConfig && fPsdConfig->GetOptOutAVec()) { timesort(fPsdConfig->GetOptOutAVec()); } + } + + if (0 == fulTsCounter % 10000) LOG(info) << "Processed " << fulTsCounter << " time slices"; + + return kTRUE; +} +/** + * @brief Get the Trd Spadic + * @return std::shared_ptr<CbmTrdSpadic> +*/ +std::shared_ptr<CbmTrdSpadic> CbmDeviceUnpack::GetTrdSpadic(bool useAvgBaseline) +{ + auto spadic = std::make_shared<CbmTrdSpadic>(); + spadic->SetUseBaselineAverage(useAvgBaseline); + spadic->SetMaxAdcToEnergyCal(1.0); + + return spadic; +} + +void CbmDeviceUnpack::Finish() {} diff --git a/MQ/mcbm/CbmDeviceUnpack.h b/MQ/mcbm/CbmDeviceUnpack.h new file mode 100644 index 0000000000..1eb6ad1a00 --- /dev/null +++ b/MQ/mcbm/CbmDeviceUnpack.h @@ -0,0 +1,276 @@ +/* Copyright (C) 2021 Facility for Antiproton and Ion Research in Europe, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Pierre-Alain Loizeau [committer] */ + +/** + * CbmDeviceUnpack.h + * + * @since 2020-05-04 + * @author P.-A. Loizeau + */ + +#ifndef CBMDEVICEUNPACK_H_ +#define CBMDEVICEUNPACK_H_ + +#include "CbmMqTMessage.h" +#include "CbmTsEventHeader.h" + +#include "Timeslice.hpp" + +#include "FairMQDevice.h" +#include "FairParGenericSet.h" + +#include "Rtypes.h" +#include "TObjArray.h" + +#include <map> +#include <vector> + +class TList; +class CbmPsdUnpackConfig; +class CbmRichUnpackConfig; +class CbmStsUnpackConfig; +class CbmTofUnpackConfig; +class CbmTrdUnpackConfigFasp2D; +class CbmTrdUnpackConfig; + +class TimesliceMetaData; + +class CbmTrdSpadic; + +class CbmDeviceUnpack : public FairMQDevice { +public: + CbmDeviceUnpack(); + virtual ~CbmDeviceUnpack(); + +protected: + virtual void InitTask(); + bool HandleData(FairMQMessagePtr&, int); + bool HandleCommand(FairMQMessagePtr&, int); + + /** @brief Set the Sts Unpack Config @param config */ + void SetUnpackConfig(std::shared_ptr<CbmStsUnpackConfig> config) { fStsConfig = config; } + + // /** @brief Set the Tof Unpack Config @param config */ + void SetUnpackConfig(std::shared_ptr<CbmTofUnpackConfig> config) { fTofConfig = config; } + + /** @brief Set the Trd Unpack Config @param config */ + void SetUnpackConfig(std::shared_ptr<CbmTrdUnpackConfig> config) { fTrd1DConfig = config; } + + /** @brief Set the Trd2D Unpack Config @param config */ + void SetUnpackConfig(std::shared_ptr<CbmTrdUnpackConfigFasp2D> config) { fTrd2DConfig = config; } + + /** @brief Set the Rich Unpack Config @param config */ + void SetUnpackConfig(std::shared_ptr<CbmRichUnpackConfig> config) { fRichConfig = config; } + + /** @brief Set the Psd Unpack Config @param config */ + void SetUnpackConfig(std::shared_ptr<CbmPsdUnpackConfig> config) { fPsdConfig = config; } + +private: + /// Constants + static const uint16_t kusSysIdSts = 0x10; + static const uint16_t kusSysIdMuch = 0x50; + static const uint16_t kusSysIdTrd = 0x40; + static const uint16_t kusSysIdTof = 0x60; + static const uint16_t kusSysIdT0 = 0x90; + static const uint16_t kusSysIdRich = 0x30; + static const uint16_t kusSysIdPsd = 0x80; + + static constexpr std::uint16_t fkFlesMvd = static_cast<std::uint16_t>(fles::SubsystemIdentifier::MVD); + static constexpr std::uint16_t fkFlesSts = static_cast<std::uint16_t>(fles::SubsystemIdentifier::STS); + static constexpr std::uint16_t fkFlesMuch = static_cast<std::uint16_t>(fles::SubsystemIdentifier::MUCH); + static constexpr std::uint16_t fkFlesTrd = static_cast<std::uint16_t>(fles::SubsystemIdentifier::TRD); + static constexpr std::uint16_t fkFlesTrd2D = static_cast<std::uint16_t>(fles::SubsystemIdentifier::TRD2D); + static constexpr std::uint16_t fkFlesTof = static_cast<std::uint16_t>(fles::SubsystemIdentifier::RPC); + static constexpr std::uint16_t fkFlesRich = static_cast<std::uint16_t>(fles::SubsystemIdentifier::RICH); + static constexpr std::uint16_t fkFlesPsd = static_cast<std::uint16_t>(fles::SubsystemIdentifier::PSD); + + + /// Control flags + Bool_t fbIgnoreOverlapMs = false; //! Ignore Overlap Ms: all fuOverlapMsNb MS at the end of timeslice + Bool_t fbComponentsAddedToList = kFALSE; + + /** @brief Flag if extended debug output is to be printed or not*/ + bool fDoDebugPrints = false; //! + /** @brief Flag if performance profiling should be activated or not.*/ + bool fDoPerfProf = false; //! + /** @brief Flag to Enable/disable a full time sorting. If off, time sorting happens per link/FLIM source */ + bool fbOutputFullTimeSorting = false; + + /// User settings parameters + std::string fsSetupName = "mcbm_beam_2021_07"; + uint32_t fuRunId = 1588; + std::string fsChannelNameDataInput = "fullts"; + std::string fsChannelNameDataOutput = "unpts_0"; + std::string fsChannelNameCommands = "commands"; + UInt_t fuDigiMaskedIdT0 = 0x00005006; + UInt_t fuDigiMaskId = 0x0001FFFF; + + /// List of MQ channels names + std::vector<std::string> fsAllowedChannels = {fsChannelNameDataInput}; + + /// Parameters management + // TList* fParCList = nullptr; + Bool_t InitParameters(std::vector<std::pair<std::string, std::shared_ptr<FairParGenericSet>>>* reqparvec); + + /// Statistics & first TS rejection + uint64_t fulNumMessages = 0; + uint64_t fulTsCounter = 0; + /** @brief Map to store a name for the unpackers and the processed amount of digis, key = fkFlesId*/ + std::map<std::uint16_t, std::pair<std::string, size_t>> fNameMap = {}; //! + /** @brief Map to store the cpu and wall time, key = fkFlesId*/ + std::map<std::uint16_t, std::pair<double, double>> fTimeMap = {}; //! + /** @brief Map to store the in and out data amount, key = fkFlesId*/ + std::map<std::uint16_t, std::pair<double, double>> fDataSizeMap = {}; //! + + /// Configuration of the unpackers. Provides the configured algorithm + std::shared_ptr<CbmStsUnpackConfig> fStsConfig = nullptr; + std::shared_ptr<CbmTrdUnpackConfigFasp2D> fTrd2DConfig = nullptr; + std::shared_ptr<CbmTrdUnpackConfig> fTrd1DConfig = nullptr; + std::shared_ptr<CbmTofUnpackConfig> fTofConfig = nullptr; + std::shared_ptr<CbmRichUnpackConfig> fRichConfig = nullptr; + std::shared_ptr<CbmPsdUnpackConfig> fPsdConfig = nullptr; + + /// Pointer to the Timeslice header conatining start time and index + CbmTsEventHeader* fCbmTsEventHeader = nullptr; + + /// Time offsets + std::vector<std::string> fvsSetTimeOffs = {}; + + /// TS MetaData storage: stable so should be moved somehow to parameters handling (not transmitted with each TS + size_t fuNbCoreMsPerTs = 0; //! + size_t fuNbOverMsPerTs = 0; //! + Double_t fdMsSizeInNs = 0; //! Size of a single MS, [nanoseconds] + Double_t fdTsCoreSizeInNs = -1.0; //! Total size of the core MS in a TS, [nanoseconds] + Double_t fdTsOverSizeInNs = -1.0; //! Total size of the overlap MS in a TS, [nanoseconds] + Double_t fdTsFullSizeInNs = -1.0; //! Total size of all MS in a TS, [nanoseconds] + TimesliceMetaData* fTsMetaData; + + bool IsChannelNameAllowed(std::string channelName); + Bool_t InitContainers(); + Bool_t DoUnpack(const fles::Timeslice& ts, size_t component); + void Finish(); + bool SendUnpData(); + + std::shared_ptr<CbmTrdSpadic> GetTrdSpadic(bool useAvgBaseline); + + /** @brief Sort a vector timewise vector type has to provide GetTime() */ + template<typename TVecobj> + typename std::enable_if<std::is_same<TVecobj, std::nullptr_t>::value == true, void>::type + timesort(std::vector<TVecobj>* /*vec = nullptr*/) + { + LOG(debug) << "CbmDeviceUnpack::timesort() got an object that has no member function GetTime(). Hence, we can and " + "will not timesort it!"; + } + + template<typename TVecobj> + typename std::enable_if<!std::is_member_function_pointer<decltype(&TVecobj::GetTime)>::value, void>::type + timesort(std::vector<TVecobj>* /*vec = nullptr*/) + { + LOG(debug) << "CbmDeviceUnpack::timesort() " << TVecobj::Class_Name() + << "is an object that has no member function GetTime(). Hence, we can and " + "will not timesort it!"; + } + + template<typename TVecobj> + typename std::enable_if<std::is_member_function_pointer<decltype(&TVecobj::GetTime)>::value, void>::type + timesort(std::vector<TVecobj>* vec = nullptr) + { + if (vec == nullptr) return; + std::sort(vec->begin(), vec->end(), + [](const TVecobj& a, const TVecobj& b) -> bool { return a.GetTime() < b.GetTime(); }); + } + + /** + * @brief Template for the unpacking call of a given algorithm. + * + * @tparam TAlgo Algorithm to be called + * @tparam TOutput Output element types + * @tparam TOptoutputs Optional output element types + * @param ts Timeslice + * @param icomp Component number + * @param algo Algorithm to be used for this component + * @param outtargetvec Target vector for the output elements + * @param optoutputvecs Target vectors for optional outputs + * @return std::pair<ndigis, std::pair<cputime, walltime>> + */ + template<class TConfig, class TOptOutA = std::nullptr_t, class TOptOutB = std::nullptr_t> + size_t unpack(const std::uint16_t subsysid, const fles::Timeslice* ts, std::uint16_t icomp, TConfig config, + std::vector<TOptOutA>* optouttargetvecA = nullptr, std::vector<TOptOutB>* optouttargetvecB = nullptr) + { + + auto wallstarttime = std::chrono::high_resolution_clock::now(); + std::clock_t cpustarttime = std::clock(); + + auto algo = config->GetUnpacker(); + std::vector<TOptOutA> optoutAvec = {}; + std::vector<TOptOutB> optoutBvec = {}; + if (optouttargetvecA) { algo->SetOptOutAVec(&optoutAvec); } + if (optouttargetvecB) { algo->SetOptOutBVec(&optoutBvec); } + + // Set the start time of the current TS for this algorithm + algo->SetTsStartTime(ts->start_time()); + + // Run the actual unpacking + auto digivec = algo->Unpack(ts, icomp); + + // Check if we want to write the output to somewhere (in pure online monitoring mode for example this can/would/should be skipped) + if (config->GetOutputVec()) { + // Lets do some time-sorting if we are not doing it later + if (!fbOutputFullTimeSorting) timesort(&digivec); + + // Transfer the data from the timeslice vector to the target branch vector + // Digis/default output retrieved as offered by the algorithm + for (auto digi : digivec) + config->GetOutputVec()->emplace_back(digi); + } + if (optouttargetvecA) { + // Lets do some timesorting + if (!fbOutputFullTimeSorting) timesort(&optoutAvec); + // Transfer the data from the timeslice vector to the target branch vector + for (auto optoutA : optoutAvec) + optouttargetvecA->emplace_back(optoutA); + } + if (optouttargetvecB) { + // Second opt output is not time sorted to allow non GetTime data container. + // Lets do some timesorting + timesort(&optoutAvec); + // Transfer the data from the timeslice vector to the target branch vector + for (auto optoutB : optoutBvec) + optouttargetvecB->emplace_back(optoutB); + } + + std::clock_t cpuendtime = std::clock(); + auto wallendtime = std::chrono::high_resolution_clock::now(); + + // Cpu time in [µs] + auto cputime = 1e6 * (cpuendtime - cpustarttime) / CLOCKS_PER_SEC; + algo->AddCpuTime(cputime); + // Real time in [µs] + auto walltime = std::chrono::duration<double, std::micro>(wallendtime - wallstarttime).count(); + algo->AddWallTime(walltime); + + + // Check some numbers from this timeslice + size_t nDigis = digivec.size(); + LOG(debug) << "Component " << icomp << " connected to config " << config->GetName() << " n-Digis " << nDigis + << " processed in walltime(cputime) = " << walltime << "(" << cputime << cputime << ") µs" + << "this timeslice."; + + if (fDoPerfProf) { + auto timeit = fTimeMap.find(subsysid); + timeit->second.first += cputime; + timeit->second.second += walltime; + + auto datait = fDataSizeMap.find(subsysid); + datait->second.first += ts->size_component(icomp) / 1.0e6; + datait->second.second += nDigis * algo->GetOutputObjSize() / 1.0e6; + + fNameMap.find(subsysid)->second.second += nDigis; + } + + return nDigis; + } +}; + +#endif /* CBMDEVICEMCBMUNPACK_H_ */ diff --git a/MQ/mcbm/runUnpack.cxx b/MQ/mcbm/runUnpack.cxx new file mode 100644 index 0000000000..2eba9e3a9a --- /dev/null +++ b/MQ/mcbm/runUnpack.cxx @@ -0,0 +1,32 @@ +/* Copyright (C) 2021 Facility for Antiproton and Ion Research in Europe, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Pierre-Alain Loizeau [committer] */ + +#include "CbmDeviceUnpack.h" + +#include <iomanip> +#include <string> + +#include "runFairMQDevice.h" + +namespace bpo = boost::program_options; +using namespace std; + +void addCustomOptions(bpo::options_description& options) +{ + options.add_options()("Setup", bpo::value<std::string>()->default_value("mcbm_beam_2021_07_surveyed"), + "Name/tag of the geomatry setup"); + options.add_options()("RunId", bpo::value<uint32_t>()->default_value(1588), "Run ID"); + options.add_options()("IgnOverMs", bpo::value<bool>()->default_value(true), "Ignore overlap MS if true"); + options.add_options()("FullTimeSort", bpo::value<bool>()->default_value(true), + "Full time sorting per detector before sending output array"); + options.add_options()("SetTimeOffs", bpo::value<std::vector<std::string>>()->multitoken()->composing(), + "Set time offset in ns for selected detector, use string matching " + "ECbmModuleId,dOffs e.g. kTof,-35.2"); + options.add_options()("TsNameIn", bpo::value<std::string>()->default_value("fullts"), + "MQ channel name for raw TS data"); + options.add_options()("TsNameOut", bpo::value<std::string>()->default_value("unpts_0"), + "MQ channel name for unpacked TS data"); +} + +FairMQDevicePtr getDevice(const FairMQProgOptions& /*config*/) { return new CbmDeviceUnpack(); } diff --git a/core/data/CbmTsEventHeader.h b/core/data/CbmTsEventHeader.h index 932e2c8d0e..32e1a72c62 100644 --- a/core/data/CbmTsEventHeader.h +++ b/core/data/CbmTsEventHeader.h @@ -71,6 +71,10 @@ public: /** @brief Set the Ts Start Time @param value Start time of the TS */ void SetTsStartTime(uint64_t value) { fTsStartTime = value; } + + CbmTsEventHeader(const CbmTsEventHeader&) = default; + CbmTsEventHeader& operator=(const CbmTsEventHeader&) = default; + protected: /** Timeslice index */ uint64_t fTsIndex = 0; diff --git a/reco/base/CbmRecoUnpackConfig.tmpl b/reco/base/CbmRecoUnpackConfig.tmpl index 421c709ec8..5ebb830407 100644 --- a/reco/base/CbmRecoUnpackConfig.tmpl +++ b/reco/base/CbmRecoUnpackConfig.tmpl @@ -8,15 +8,12 @@ * @brief Configuration class for an unpacker algorithm * @version 0.1 * @date 2021-04-21 - * + * * @copyright Copyright (c) 2021 - * - * This is the common steering task to run unpacking processes in a FairRun for the - * CbmTrd. - * - * - * - * + * + * This is the common steering task to run unpacking processes in a FairRun for the + * CBM detectors. + * */ #ifndef CbmRecoUnpackConfig_tmpl @@ -25,7 +22,7 @@ #include "CbmRecoUnpackAlgo.tmpl" #include <FairLogger.h> -#include <FairParAsciiFileIo.h> +//#include <FairParAsciiFileIo.h> #include <FairRootManager.h> #include <Logger.h> @@ -43,11 +40,14 @@ public: /** * @brief Create a Cbm Reco Unpack Config object */ - CbmRecoUnpackConfig(std::string name) : fName(name) {}; + CbmRecoUnpackConfig(std::string name, std::string detGeoSetupTag, UInt_t runid) : + fName(name) + , fGeoSetupTag(detGeoSetupTag) + , fRunId(runid) {}; /** * @brief Destroy the Cbm Trd Unpack Task object - * + * */ virtual ~CbmRecoUnpackConfig() {}; @@ -86,6 +86,12 @@ protected: /** @brief Name of the (derived) class for debugging statements */ std::string fName = ""; + /** @brief Geometry setup tag for the given detector as used by CbmSetup objects */ + std::string fGeoSetupTag = ""; + + /** @brief RunId of the current run, if not known 0 is a valid runtime case. Used runId based parameter loading. */ + UInt_t fRunId = 0; + /** @brief Do debug printouts. Call SetDebugState() to activate*/ bool fDoLog = false; @@ -107,6 +113,9 @@ protected: */ int32_t fSystemTimeOffset = 0; + /** @brief Flag to control whether the unpacker algo ignores the overlapp microslices (if true).*/ + bool fDoIgnoreOverlappMs = true; + /** @brief Use this function to implement additional actions to be called once per TS, e.g. needed if more than the default output vector is used. */ virtual void reset() { return; }; @@ -115,85 +124,158 @@ public: // Getters /** * @brief Get the Output Branch Name - * - * @return std::string + * + * @return std::string */ std::string GetOutputBranchName() { return fOutputBranchName.empty() ? TOutput::GetBranchName() : fOutputBranchName; } + /** + * @brief Get the Output Branch Name + * + * @return std::string + */ + std::string GetOutputBranchNameOptA() { return fOptoutABranchName; } + + /** + * @brief Get the Output Branch Name + * + * @return std::string + */ + std::string GetOutputBranchNameOptB() { return fOptoutBBranchName; } + /** @brief Get the name of the given derived config */ std::string GetName() { return fName; } /** * @brief Get a given output vector connected to the tree, if called after calling InitUnpacker(). - * - * @return std::vector<TOutput>* + * + * @return std::vector<TOutput>* */ std::vector<TOutput>* GetOutputVec() { return fOutputVec; } /** * @brief Get a given output vector connected to the tree, if called after calling InitUnpacker(). - * - * @return std::vector<TOptOutA>* + * + * @return std::vector<TOptOutA>* */ std::vector<TOptOutA>* GetOptOutAVec() { return fOptOutAVec; } /** * @brief Get a given output vector connected to the tree, if called after calling InitUnpacker(). - * - * @return std::vector<TOptOutA>* + * + * @return std::vector<TOptOutA>* */ std::vector<TOptOutB>* GetOptOutBVec() { return fOptOutBVec; } /** * @brief Get the ready to run Unpacker. To be defined in the derived classes. * In this function also all initialization steps of the unpacker algorithms have to happen. - * @return std::shared_ptr<CbmRecoUnpackAlgo> + * @return std::shared_ptr<CbmRecoUnpackAlgo> */ std::shared_ptr<CbmRecoUnpackAlgo<TOutput, TOptOutA, TOptOutB>> GetUnpacker() { return fAlgo; }; + /** + * @brief Get the requested parameter containers from the Algo. + * Return the required parameter containers together with the paths to the ascii + * files to. + * @return fParContVec + */ + virtual std::vector<std::pair<std::string, std::shared_ptr<FairParGenericSet>>>* + GetParContainerRequest() + { + if(fAlgo) return fAlgo->GetParContainerRequest(fGeoSetupTag, fRunId); + else return {}; + } + /** * @brief Init function of the configs to be called by CbmRecoUnpack() * Initializes the output branches and calls InitUnpacker() * @param ioman Pointer to the FairRootManager instance * @param branchname by default TOutput::GetBranchName() is used for the first output. If branchname is not empty that branchname is used. */ - void Init(FairRootManager* ioman) + void InitOutput() { LOG(info) << fName << "::Init() ---------------------------------"; if (fDoWriteOutput) { - fOutputVec = new std::vector<TOutput>(); - ioman->RegisterAny(GetOutputBranchName().data(), fOutputVec, kTRUE); - LOG(info) << fName << "::registerBranchToTree(" << GetOutputBranchName().data() << ")"; + LOG(info) << fName << "::InitOutput(" << GetOutputBranchName().data() << ")"; } /** @todo for the optional outputs it is more complicated to check if they exist. Needs exceptions for the std::nullptr_t. Should be added at some point in time. */ if (fDoWriteOptOutA) { if (!fOptOutAVec) { fOptOutAVec = new std::vector<TOptOutA>(); - ioman->RegisterAny(fOptoutABranchName.data(), fOptOutAVec, kTRUE); - LOG(info) << fName << "::registerBranchToTree(" << fOptoutABranchName.data() << ")"; + LOG(info) << fName << "::InitOutput(" << fOptoutABranchName.data() << ")"; } } if (fDoWriteOptOutB) { fOptOutBVec = new std::vector<TOptOutB>(); + LOG(info) << fName << "::InitOutput(" << fOptoutBBranchName.data() << ")"; + } + } + + /** + * @brief Register the output vectors (if needed) to the FairRoot Manager) + * FIXME: To be removed with the Manager include whenever the similar code in the CbmRecoUnpack task work as expected + * + */ + void RegisterOutput(FairRootManager* ioman) + { + if (fDoWriteOutput && fOutputVec) { + ioman->RegisterAny(GetOutputBranchName().data(), fOutputVec, kTRUE); + LOG(info) << fName << "::registerBranchToTree(" << GetOutputBranchName().data() << ")"; + } + + /** @todo for the optional outputs it is more complicated to check if they exist. Needs exceptions for the std::nullptr_t. Should be added at some point in time. */ + if (fDoWriteOptOutA && fOptOutAVec) { + ioman->RegisterAny(fOptoutABranchName.data(), fOptOutAVec, kTRUE); + LOG(info) << fName << "::registerBranchToTree(" << fOptoutABranchName.data() << ")"; + } + + if (fDoWriteOptOutB && fOptOutBVec) { ioman->RegisterAny(fOptoutBBranchName.data(), fOptOutBVec, kTRUE); LOG(info) << fName << "::registerBranchToTree(" << fOptoutBBranchName.data() << ")"; } + } - // Init the unpacker - InitUnpacker(); + /** + * @brief Setup the derived unpacker algorithm to be used for the DAQ output to Digi translation. + * Can be re-implemented in the derived classes if more than the Algo choice and path setting needs to be done before getting the Parameters + * + */ + virtual void SetAlgo() + { + LOG(info) << fName << "::SetAlgo -"; + + // First choose the derived unpacking algorithm to be used + // TODO: To avoid having to check if the pointer is assigned nultiples times, an exception + // should be thrown in case of failure + fAlgo = chooseAlgo(); + + if (fDoLog) LOG(info) << fName << "::SetAlgo - SetParFilesBasePath"; + fAlgo->SetParFilesBasePath(fParFilesBasePath); // Set the global system time offset - if (fAlgo) fAlgo->SetSystemTimeOffset(fSystemTimeOffset); + if (fDoLog) LOG(info) << fName << "::SetAlgo - SetSystemTimeOffset"; + fAlgo->SetSystemTimeOffset(fSystemTimeOffset); - LOG(info) << fName << " succesful initialized -----------------\n"; + // Set the flag controlling the overlap ignore + if (fDoLog) LOG(info) << fName << "::SetAlgo - SetDoIgnoreOverlappMs"; + fAlgo->SetDoIgnoreOverlappMs(fDoIgnoreOverlappMs); } - /** @brief Prepare the Unpacker algorithm for the run, to be implemented in the derived classes. */ - virtual void InitUnpacker() {}; + /** + * @brief Initialize the algorithm, should include all steps needing te parameter objects to be present. + * To be re-implemented in the derived classes if not all settings in parameter classes. + * + */ + virtual void InitAlgo() + { + // Now we have all information required to initialise the algorithm + fAlgo->Init(); + } /** @brief Reset called once per ReadEvent() */ void Reset() @@ -215,16 +297,16 @@ public: /** * @brief Set the Output Branch Name - * By default TOutput::GetBranchName() is used. Set this if you want to use a + * By default TOutput::GetBranchName() is used. Set this if you want to use a * different output name - * @param value + * @param value */ void SetOutputBranchName(std::string value) { fOutputBranchName = value; } /** * @brief Set the Do Write OptOutput A flag, without activation the opt out is not written to the sink - * @param branchname name of the branch in the output tree - * @param value bool + * @param branchname name of the branch in the output tree + * @param value bool */ void SetDoWriteOptOutA(std::string branchname, bool value = true) { @@ -234,8 +316,8 @@ public: /** * @brief Set the Do Write OptOutput B flag, without activation the opt out is not written to the sink - * @param branchname name of the branch in the output tree - * @param value bool + * @param branchname name of the branch in the output tree + * @param value bool */ void SetDoWriteOptOutB(std::string branchname, bool value = true) { @@ -245,61 +327,47 @@ public: /** * @brief Set the Debug State, influences the log messages. - * - * @param value + * + * @param value */ void SetDebugState(bool value = true) { fDoLog = value; } /** * @brief Set the is MC flag. Activates the Match branch. - * + * * @param value */ void SetIsMC(bool value = true) { fIsMC = value; } /** * @brief Set the Output Vec - * - * @tparam Output - * @param value + * + * @tparam Output + * @param value */ void SetOutputVec(std::vector<TOutput>* value) { fOutputVec = value; } /** * @brief Set the Par Files Base Path (absolute directory path were the files are stored) - * - * @param value + * + * @param value */ void SetParFilesBasePath(std::string value) { fParFilesBasePath = value; } /** @brief Set the global system time offset @remark in princible this should go to parameters */ void SetSystemTimeOffset(int32_t value) { fSystemTimeOffset = value; } + /** @brief Set the value of the flag to ignore the overlap microslices @remark in princible this should go to parameters */ + void SetDoIgnoreOverlappMs(bool value = false) { fDoIgnoreOverlappMs = value; } + protected: /** - * @brief Initialise the parameter containers requested by the algorithm - * - * @return Bool_t initOk + * @brief Choose the derived unpacker algorithm to be used for the DAQ output to Digi translation. If algo was already set manually by the user this algorithm is used. + * To be implemented in the derived classes + * + * @return std::shared_ptr<TAlgo> */ - virtual Bool_t initParContainers(std::vector<std::pair<std::string, std::shared_ptr<FairParGenericSet>>>* reqparvec) - { - if (fDoLog) LOG(info) << GetName() << "::Init - initParContainers"; - if (!reqparvec) { - LOG(info) << GetName() << "::Init - initParContainers - empty requirements vector no parameters initialized."; - return kTRUE; - } - - // Now get the actual ascii files and init the containers with the asciiIo - for (auto& pair : *reqparvec) { - auto filepath = pair.first; - auto parset = pair.second; - FairParAsciiFileIo asciiInput; - if (!filepath.empty()) { - if (asciiInput.open(filepath.data())) { parset->init(&asciiInput); } - } - } - return kTRUE; - } + virtual std::shared_ptr<TAlgo> chooseAlgo() = 0; }; diff --git a/reco/detectors/psd/unpack/CbmPsdUnpackConfig.cxx b/reco/detectors/psd/unpack/CbmPsdUnpackConfig.cxx index 8407d4fccc..4c6a90fd52 100644 --- a/reco/detectors/psd/unpack/CbmPsdUnpackConfig.cxx +++ b/reco/detectors/psd/unpack/CbmPsdUnpackConfig.cxx @@ -15,37 +15,13 @@ #include <vector> CbmPsdUnpackConfig::CbmPsdUnpackConfig(std::string detGeoSetupTag, UInt_t runid) - : CbmRecoUnpackConfig("CbmPsdUnpackConfig") - , fGeoSetupTag(detGeoSetupTag) - , fRunId(runid) + : CbmRecoUnpackConfig("CbmPsdUnpackConfig", detGeoSetupTag, runid) { } CbmPsdUnpackConfig::~CbmPsdUnpackConfig() {} // ---- Init ---- -void CbmPsdUnpackConfig::InitUnpacker() -{ - LOG(info) << fName << "::Init -"; - - auto initOk = kTRUE; - - // First choose the derived unpacking algorithm to be used and pass the raw to digi method - auto algo = chooseAlgo(); - - if (fDoLog) LOG(info) << fName << "::Init - SetParFilesBasePath"; - algo->SetParFilesBasePath(fParFilesBasePath); - - // Initialise the parameter containers required by the unpacker algo. Includes loading the corresponding ascii files - auto reqparvec = algo->GetParContainerRequest(fGeoSetupTag, fRunId); - initOk &= initParContainers(reqparvec); - - // Now we have all information required to initialise the algorithm - algo->Init(); - - // Pass the algo to its member in the base class - fAlgo = algo; -} // ---- chooseAlgo ---- std::shared_ptr<CbmPsdUnpackAlgo> CbmPsdUnpackConfig::chooseAlgo() diff --git a/reco/detectors/psd/unpack/CbmPsdUnpackConfig.h b/reco/detectors/psd/unpack/CbmPsdUnpackConfig.h index 34fcac3e26..19fcf86072 100644 --- a/reco/detectors/psd/unpack/CbmPsdUnpackConfig.h +++ b/reco/detectors/psd/unpack/CbmPsdUnpackConfig.h @@ -8,11 +8,11 @@ * @brief Configuration class for an unpacker algorithm * @version 0.1 * @date 2021-04-21 - * + * * @copyright Copyright (c) 2021 - * + * * This is the common configuration class for unpacking algorithms - * + * */ #ifndef CbmPsdUnpackConfig_H @@ -38,7 +38,7 @@ class CbmPsdUnpackConfig : public CbmRecoUnpackConfig<CbmPsdUnpackAlgo, CbmPsdDi public: /** * @brief Create the Cbm Trd Unpack Task object - * + * * @param geoSetupTag Geometry setup tag for the given detector as used by CbmSetup objects * @param runid set if unpacker is rerun on a special run with special parameters *@remark We use the string instead of CbmSetup here, to not having to link against sim/steer... @@ -47,7 +47,7 @@ public: /** * @brief Destroy the Cbm Trd Unpack Task object - * + * */ virtual ~CbmPsdUnpackConfig(); @@ -60,30 +60,18 @@ public: // Getters - /** - * @brief Prepare the unpacker to be ready to run. - * In this function all initialization steps of the unpacker algorithms happen. - */ - void InitUnpacker(); - // Setters protected: /** * @brief Choose the derived unpacker algorithm to be used for the DAQ output to Digi translation. If algo was already set manually by the user this algorithm is used. - * - * @return Bool_t initOk + * + * @return Bool_t initOk */ virtual std::shared_ptr<CbmPsdUnpackAlgo> chooseAlgo(); - /** @brief Geometry setup tag for the given detector as used by CbmSetup objects */ - std::string fGeoSetupTag = ""; - - /** @brief RunId of the current run, if not known 0 is a valid runtime case. Used runId based parameter loading. */ - UInt_t fRunId = 0; - private: - ClassDef(CbmPsdUnpackConfig, 2) + ClassDef(CbmPsdUnpackConfig, 3) }; #endif // CbmPsdUnpackConfig_H diff --git a/reco/detectors/rich/unpack/CbmRichUnpackConfig.cxx b/reco/detectors/rich/unpack/CbmRichUnpackConfig.cxx index 94e8df82a3..a2d2700dcf 100644 --- a/reco/detectors/rich/unpack/CbmRichUnpackConfig.cxx +++ b/reco/detectors/rich/unpack/CbmRichUnpackConfig.cxx @@ -15,39 +15,20 @@ #include <vector> CbmRichUnpackConfig::CbmRichUnpackConfig(std::string detGeoSetupTag, UInt_t runid) - : CbmRecoUnpackConfig("CbmRichUnpackConfig") - , fGeoSetupTag(detGeoSetupTag) - , fRunId(runid) + : CbmRecoUnpackConfig("CbmRichUnpackConfig", detGeoSetupTag, runid) { } CbmRichUnpackConfig::~CbmRichUnpackConfig() {} // ---- Init ---- -void CbmRichUnpackConfig::InitUnpacker() +void CbmRichUnpackConfig::InitAlgo() { - LOG(info) << fName << "::Init -"; - - auto initOk = kTRUE; - - // First choose the derived unpacking algorithm to be used and pass the raw to digi method - auto algo = chooseAlgo(); - - if (fDoLog) LOG(info) << fName << "::Init - SetParFilesBasePath"; - algo->SetParFilesBasePath(fParFilesBasePath); - if (fDoLog) LOG(info) << fName << "::Init - SetMaskedDiRICHes"; - algo->SetMaskedDiRICHes(&fMaskedDiRICHes); - - // Initialise the parameter containers required by the unpacker algo. Includes loading the corresponding ascii files - auto reqparvec = algo->GetParContainerRequest(fGeoSetupTag, fRunId); - initOk &= initParContainers(reqparvec); + fAlgo->SetMaskedDiRICHes(&fMaskedDiRICHes); // Now we have all information required to initialise the algorithm - algo->Init(); - - // Pass the algo to its member in the base class - fAlgo = algo; + fAlgo->Init(); } // ---- chooseAlgo ---- diff --git a/reco/detectors/rich/unpack/CbmRichUnpackConfig.h b/reco/detectors/rich/unpack/CbmRichUnpackConfig.h index 0f57445a5c..f73bd36f95 100644 --- a/reco/detectors/rich/unpack/CbmRichUnpackConfig.h +++ b/reco/detectors/rich/unpack/CbmRichUnpackConfig.h @@ -8,11 +8,11 @@ * @brief Configuration class for an unpacker algorithm * @version 0.1 * @date 2021-04-21 - * + * * @copyright Copyright (c) 2021 - * + * * This is the common configuration class for unpacking algorithms - * + * */ #ifndef CbmRichUnpackConfig_H @@ -38,7 +38,7 @@ class CbmRichUnpackConfig : public CbmRecoUnpackConfig<CbmRichUnpackAlgo, CbmRic public: /** * @brief Create the Cbm Trd Unpack Task object - * + * * @param geoSetupTag Geometry setup tag for the given detector as used by CbmSetup objects * @param runid set if unpacker is rerun on a special run with special parameters *@remark We use the string instead of CbmSetup here, to not having to link against sim/steer... @@ -47,7 +47,7 @@ public: /** * @brief Destroy the Cbm Trd Unpack Task object - * + * */ virtual ~CbmRichUnpackConfig(); @@ -61,10 +61,10 @@ public: /** - * @brief Prepare the unpacker to be ready to run. - * In this function all initialization steps of the unpacker algorithms happen. + * @brief Initialize the algorithm, should include all steps needing te parameter objects to be present. + * In this function most initialization steps of the unpacker algorithms happen. */ - void InitUnpacker(); + void InitAlgo(); // Setters @@ -73,21 +73,15 @@ public: protected: /** * @brief Choose the derived unpacker algorithm to be used for the DAQ output to Digi translation. If algo was already set manually by the user this algorithm is used. - * - * @return Bool_t initOk + * + * @return Bool_t initOk */ virtual std::shared_ptr<CbmRichUnpackAlgo> chooseAlgo(); - /** @brief Geometry setup tag for the given detector as used by CbmSetup objects */ - std::string fGeoSetupTag = ""; - - /** @brief RunId of the current run, if not known 0 is a valid runtime case. Used runId based parameter loading. */ - UInt_t fRunId = 0; - - std::vector<Int_t> fMaskedDiRICHes; + std::vector<Int_t> fMaskedDiRICHes = {}; private: - ClassDef(CbmRichUnpackConfig, 2) + ClassDef(CbmRichUnpackConfig, 3) }; #endif // CbmRichUnpackConfig_H diff --git a/reco/detectors/sts/unpack/CbmStsUnpackAlgo.cxx b/reco/detectors/sts/unpack/CbmStsUnpackAlgo.cxx index 27f212776a..4a0f00e707 100644 --- a/reco/detectors/sts/unpack/CbmStsUnpackAlgo.cxx +++ b/reco/detectors/sts/unpack/CbmStsUnpackAlgo.cxx @@ -231,6 +231,8 @@ Bool_t CbmStsUnpackAlgo::initParSet(CbmMcbm2018StsPar* parset) LOG(debug) << "Unpacking data in bin sorter FW mode"; initInternalStatus(parset); + if (fMonitor) fMonitor->Init(parset); + return kTRUE; } diff --git a/reco/detectors/sts/unpack/CbmStsUnpackAlgoLegacy.cxx b/reco/detectors/sts/unpack/CbmStsUnpackAlgoLegacy.cxx index 097ceecedd..20c411571a 100644 --- a/reco/detectors/sts/unpack/CbmStsUnpackAlgoLegacy.cxx +++ b/reco/detectors/sts/unpack/CbmStsUnpackAlgoLegacy.cxx @@ -93,6 +93,9 @@ Bool_t CbmStsUnpackAlgoLegacy::initParSet(CbmMcbm2018StsPar* parset) { fUnpackPar = parset; bool initOK = InitParameters(); + + if (fMonitor) initOK &= fMonitor->Init(parset); + return initOK; } diff --git a/reco/detectors/sts/unpack/CbmStsUnpackConfig.cxx b/reco/detectors/sts/unpack/CbmStsUnpackConfig.cxx index e2ce1e5526..b6c7be4c22 100644 --- a/reco/detectors/sts/unpack/CbmStsUnpackConfig.cxx +++ b/reco/detectors/sts/unpack/CbmStsUnpackConfig.cxx @@ -16,59 +16,37 @@ #include <vector> CbmStsUnpackConfig::CbmStsUnpackConfig(std::string detGeoSetupTag, UInt_t runid) - : CbmRecoUnpackConfig("CbmStsUnpackConfig") - , fGeoSetupTag(detGeoSetupTag) - , fRunId(runid) + : CbmRecoUnpackConfig("CbmStsUnpackConfig", detGeoSetupTag, runid) { } CbmStsUnpackConfig::~CbmStsUnpackConfig() {} // ---- Init ---- -void CbmStsUnpackConfig::InitUnpacker() +void CbmStsUnpackConfig::InitAlgo() { - LOG(info) << fName << "::Init -"; - - auto initOk = kTRUE; - - // First choose the derived unpacking algorithm to be used and pass the raw to digi method - auto algo = chooseAlgo(); - - if (fDoLog) LOG(info) << fName << "::Init - SetParFilesBasePath"; - algo->SetParFilesBasePath(fParFilesBasePath); - - // Initialise the parameter containers required by the unpacker algo. Includes loading the corresponding ascii files - auto reqparvec = algo->GetParContainerRequest(fGeoSetupTag, fRunId); - initOk &= initParContainers(reqparvec); - // Set the minimum adc cut - algo->SetMinAdcCut(fdAdcCut); + fAlgo->SetMinAdcCut(fdAdcCut); // Set the minimum adc cut Feb independent for (auto cut = fdAdcCut_perFeb.begin(); cut != fdAdcCut_perFeb.end(); cut++) { - algo->SetMinAdcCut(cut->first, cut->second); + fAlgo->SetMinAdcCut(cut->first, cut->second); } // Set the single asics time offsets - algo->SetAsicTimeOffsetVec(fvdTimeOffsetNsAsics); + fAlgo->SetAsicTimeOffsetVec(fvdTimeOffsetNsAsics); // Set the flags for duplicate digis rejections - algo->SetDuplicatesRejection(fbRejectDuplicateDigis, fbDupliWithoutAdc); + fAlgo->SetDuplicatesRejection(fbRejectDuplicateDigis, fbDupliWithoutAdc); + + if (fMonitor) { fAlgo->SetMonitor(fMonitor); } // Now we have all information required to initialise the algorithm - algo->Init(); + fAlgo->Init(); // Mask the noisy channels set by the user for (auto chmask : fvChanMasks) - algo->MaskNoisyChannel(chmask.uFeb, chmask.uChan, chmask.bMasked); - - if (fMonitor) { - fMonitor->Init(static_cast<CbmMcbm2018StsPar*>(reqparvec->at(0).second.get())); - algo->SetMonitor(fMonitor); - } - - // Pass the algo to its member in the base class - fAlgo = algo; + fAlgo->MaskNoisyChannel(chmask.uFeb, chmask.uChan, chmask.bMasked); } // ---- chooseAlgo ---- diff --git a/reco/detectors/sts/unpack/CbmStsUnpackConfig.h b/reco/detectors/sts/unpack/CbmStsUnpackConfig.h index d116e3f23d..d71c152a64 100644 --- a/reco/detectors/sts/unpack/CbmStsUnpackConfig.h +++ b/reco/detectors/sts/unpack/CbmStsUnpackConfig.h @@ -70,10 +70,10 @@ public: std::shared_ptr<CbmStsUnpackMonitor> GetMonitor() { return fMonitor; } /** - * @brief Prepare the unpacker to be ready to run. - * In this function all initialization steps of the unpacker algorithms happen. + * @brief Initialize the algorithm, should include all steps needing te parameter objects to be present. + * In this function most initialization steps of the unpacker algorithms happen. */ - void InitUnpacker(); + void InitAlgo(); void MaskNoisyChannel(UInt_t uFeb, UInt_t uChan, Bool_t bMasked = kTRUE) { @@ -138,14 +138,8 @@ protected: /// Temporary storage of user parameters std::vector<FebChanMaskReco> fvChanMasks = {}; - /** @brief Geometry setup tag for the given detector as used by CbmSetup objects */ - std::string fGeoSetupTag = ""; - - /** @brief RunId of the current run, if not known 0 is a valid runtime case. Used runId based parameter loading. */ - UInt_t fRunId = 0; - private: - ClassDef(CbmStsUnpackConfig, 2) + ClassDef(CbmStsUnpackConfig, 3) }; #endif // CbmStsUnpackConfig_H diff --git a/reco/detectors/tof/unpack/CbmTofUnpackConfig.cxx b/reco/detectors/tof/unpack/CbmTofUnpackConfig.cxx index 1bb23b5d92..a2a4d239c6 100644 --- a/reco/detectors/tof/unpack/CbmTofUnpackConfig.cxx +++ b/reco/detectors/tof/unpack/CbmTofUnpackConfig.cxx @@ -15,37 +15,13 @@ #include <vector> CbmTofUnpackConfig::CbmTofUnpackConfig(std::string detGeoSetupTag, UInt_t runid) - : CbmRecoUnpackConfig("CbmTofUnpackConfig") - , fGeoSetupTag(detGeoSetupTag) - , fRunId(runid) + : CbmRecoUnpackConfig("CbmTofUnpackConfig", detGeoSetupTag, runid) { } CbmTofUnpackConfig::~CbmTofUnpackConfig() {} // ---- Init ---- -void CbmTofUnpackConfig::InitUnpacker() -{ - LOG(info) << fName << "::Init -"; - - auto initOk = kTRUE; - - // First choose the derived unpacking algorithm to be used and pass the raw to digi method - auto algo = chooseAlgo(); - - if (fDoLog) LOG(info) << fName << "::Init - SetParFilesBasePath"; - algo->SetParFilesBasePath(fParFilesBasePath); - - // Initialise the parameter containers required by the unpacker algo. Includes loading the corresponding ascii files - auto reqparvec = algo->GetParContainerRequest(fGeoSetupTag, fRunId); - initOk &= initParContainers(reqparvec); - - // Now we have all information required to initialise the algorithm - algo->Init(); - - // Pass the algo to its member in the base class - fAlgo = algo; -} // ---- chooseAlgo ---- std::shared_ptr<CbmTofUnpackAlgo> CbmTofUnpackConfig::chooseAlgo() diff --git a/reco/detectors/tof/unpack/CbmTofUnpackConfig.h b/reco/detectors/tof/unpack/CbmTofUnpackConfig.h index fae84af847..4589a7bf8f 100644 --- a/reco/detectors/tof/unpack/CbmTofUnpackConfig.h +++ b/reco/detectors/tof/unpack/CbmTofUnpackConfig.h @@ -61,12 +61,6 @@ public: // Getters - /** - * @brief Prepare the unpacker to be ready to run. - * In this function all initialization steps of the unpacker algorithms happen. - */ - void InitUnpacker(); - // Setters protected: @@ -77,12 +71,6 @@ protected: */ virtual std::shared_ptr<CbmTofUnpackAlgo> chooseAlgo(); - /** @brief Geometry setup tag for the given detector as used by CbmSetup objects */ - std::string fGeoSetupTag = ""; - - /** @brief RunId of the current run, if not known 0 is a valid runtime case. Used runId based parameter loading. */ - UInt_t fRunId = 0; - private: ClassDef(CbmTofUnpackConfig, 1) }; diff --git a/reco/detectors/trd/unpack/CbmTrdUnpackConfig.cxx b/reco/detectors/trd/unpack/CbmTrdUnpackConfig.cxx index ef89941f4d..2048fff829 100644 --- a/reco/detectors/trd/unpack/CbmTrdUnpackConfig.cxx +++ b/reco/detectors/trd/unpack/CbmTrdUnpackConfig.cxx @@ -16,21 +16,17 @@ #include <vector> CbmTrdUnpackConfig::CbmTrdUnpackConfig(std::string detGeoSetupTag, UInt_t runid) - : CbmRecoUnpackConfig("CbmTrdUnpackConfig") - , fGeoSetupTag(detGeoSetupTag) - , fRunId(runid) + : CbmRecoUnpackConfig("CbmTrdUnpackConfig", detGeoSetupTag, runid) { } CbmTrdUnpackConfig::~CbmTrdUnpackConfig() {} // ---- Init ---- -void CbmTrdUnpackConfig::InitUnpacker() +void CbmTrdUnpackConfig::SetAlgo() { LOG(info) << fName << "::Init -"; - auto initOk = kTRUE; - // First choose the derived unpacking algorithm to be used and pass the raw to digi method auto algo = chooseAlgo(); @@ -49,13 +45,6 @@ void CbmTrdUnpackConfig::InitUnpacker() // If we have a monitor in the config add it to the algo if (fMonitor) algo->SetMonitor(fMonitor); - // Initialise the parameter containers required by the unpacker algo. Includes loading the corresponding ascii files - auto reqparvec = algo->GetParContainerRequest(fGeoSetupTag, fRunId); - initOk &= initParContainers(reqparvec); - - // Now we have all information required to initialise the algorithm - algo->Init(); - // Pass the algo to its member in the base class fAlgo = algo; } diff --git a/reco/detectors/trd/unpack/CbmTrdUnpackConfig.h b/reco/detectors/trd/unpack/CbmTrdUnpackConfig.h index a17e5c289d..0a8e96d553 100644 --- a/reco/detectors/trd/unpack/CbmTrdUnpackConfig.h +++ b/reco/detectors/trd/unpack/CbmTrdUnpackConfig.h @@ -8,11 +8,11 @@ * @brief Configuration class for an unpacker algorithm * @version 0.1 * @date 2021-04-21 - * + * * @copyright Copyright (c) 2021 - * + * * This is the common configuration class for unpacking algorithms - * + * */ #ifndef CbmTrdUnpackConfig_H @@ -42,7 +42,7 @@ class CbmTrdUnpackConfig : public: /** * @brief Create the Cbm Trd Unpack Task object - * + * * @param geoSetupTag Geometry setup tag for the given detector as used by CbmSetup objects * @param runid set if unpacker is rerun on a special run with special parameters *@remark We use the string instead of CbmSetup here, to not having to link against sim/steer... @@ -51,7 +51,7 @@ public: /** * @brief Destroy the Cbm Trd Unpack Task object - * + * */ virtual ~CbmTrdUnpackConfig(); @@ -69,10 +69,11 @@ public: std::shared_ptr<CbmTrdSpadic> GetSpadicObject() { return fSpadic; } /** - * @brief Prepare the unpacker to be ready to run. - * In this function all initialization steps of the unpacker algorithms happen. + * @brief Setup the derived unpacker algorithm to be used for the DAQ output to Digi translation. + * Re-implementing because the Monitor has to be set before requesting parameter objects + * */ - void InitUnpacker(); + void SetAlgo(); // Setters @@ -81,23 +82,23 @@ public: /** * @brief Set the raw to digi method - * - * @param value + * + * @param value */ void SetRawToDigiMethod(std::shared_ptr<CbmTrdRawToDigiBaseR> value) { fRTDMethod = value; } /** * @brief Set the Spadic Object - * - * @param value + * + * @param value */ void SetSpadicObject(std::shared_ptr<CbmTrdSpadic> value) { fSpadic = value; } protected: /** * @brief Choose the derived unpacker algorithm to be used for the DAQ output to Digi translation. If algo was already set manually by the user this algorithm is used. - * - * @return Bool_t initOk + * + * @return Bool_t initOk */ virtual std::shared_ptr<CbmTrdUnpackAlgoBaseR> chooseAlgo(); @@ -110,14 +111,8 @@ protected: /** @brief pointer to the monitor object */ std::shared_ptr<CbmTrdUnpackMonitor> fMonitor = nullptr; - /** @brief Geometry setup tag for the given detector as used by CbmSetup objects */ - std::string fGeoSetupTag = ""; - - /** @brief RunId of the current run, if not known 0 is a valid runtime case. Used runId based parameter loading. */ - UInt_t fRunId = 0; - private: - ClassDef(CbmTrdUnpackConfig, 2) + ClassDef(CbmTrdUnpackConfig, 3) }; #endif // CbmTrdUnpackConfig_H diff --git a/reco/detectors/trd/unpack/CbmTrdUnpackConfigFasp2D.cxx b/reco/detectors/trd/unpack/CbmTrdUnpackConfigFasp2D.cxx index d5a0333032..2fe94bfb04 100644 --- a/reco/detectors/trd/unpack/CbmTrdUnpackConfigFasp2D.cxx +++ b/reco/detectors/trd/unpack/CbmTrdUnpackConfigFasp2D.cxx @@ -15,37 +15,13 @@ #include <vector> CbmTrdUnpackConfigFasp2D::CbmTrdUnpackConfigFasp2D(std::string detGeoSetupTag, UInt_t runid) - : CbmRecoUnpackConfig("CbmTrdUnpackConfigFasp2D") - , fGeoSetupTag(detGeoSetupTag) - , fRunId(runid) + : CbmRecoUnpackConfig("CbmTrdUnpackConfigFasp2D", detGeoSetupTag, runid) { } CbmTrdUnpackConfigFasp2D::~CbmTrdUnpackConfigFasp2D() {} // ---- Init ---- -void CbmTrdUnpackConfigFasp2D::InitUnpacker() -{ - LOG(info) << fName << "::Init -"; - - auto initOk = kTRUE; - - // First choose the derived unpacking algorithm to be used and pass the raw to digi method - auto algo = chooseAlgo(); - - if (fDoLog) LOG(info) << fName << "::Init - SetParFilesBasePath"; - algo->SetParFilesBasePath(fParFilesBasePath); - - // Initialise the parameter containers required by the unpacker algo. Includes loading the corresponding ascii files - auto reqparvec = algo->GetParContainerRequest(fGeoSetupTag, fRunId); - initOk &= initParContainers(reqparvec); - - // Now we have all information required to initialise the algorithm - algo->Init(); - - // Pass the algo to its member in the base class - fAlgo = algo; -} // ---- chooseAlgo ---- std::shared_ptr<CbmTrdUnpackAlgoFasp2D> CbmTrdUnpackConfigFasp2D::chooseAlgo() diff --git a/reco/detectors/trd/unpack/CbmTrdUnpackConfigFasp2D.h b/reco/detectors/trd/unpack/CbmTrdUnpackConfigFasp2D.h index ac03873b64..79c15828e2 100644 --- a/reco/detectors/trd/unpack/CbmTrdUnpackConfigFasp2D.h +++ b/reco/detectors/trd/unpack/CbmTrdUnpackConfigFasp2D.h @@ -8,11 +8,11 @@ * @brief Configuration class for an unpacker algorithm * @version 0.1 * @date 2021-04-21 - * + * * @copyright Copyright (c) 2021 - * + * * This is the common configuration class for unpacking algorithms - * + * */ #ifndef CbmTrdUnpackConfigFasp2D_H @@ -39,7 +39,7 @@ class CbmTrdUnpackConfigFasp2D : public CbmRecoUnpackConfig<CbmTrdUnpackAlgoFasp public: /** * @brief Create the Cbm Trd Unpack Task object - * + * * @param geoSetupTag Geometry setup tag for the given detector as used by CbmSetup objects * @param runid set if unpacker is rerun on a special run with special parameters *@remark We use the string instead of CbmSetup here, to not having to link against sim/steer... @@ -48,7 +48,7 @@ public: /** * @brief Destroy the Cbm Trd Unpack Task object - * + * */ virtual ~CbmTrdUnpackConfigFasp2D(); @@ -58,28 +58,16 @@ public: /** @brief Assignment operator - not implemented **/ CbmTrdUnpackConfigFasp2D& operator=(const CbmTrdUnpackConfigFasp2D&) = delete; - /** - * @brief Prepare the unpacker to be ready to run. - * In this function all initialization steps of the unpacker algorithms happen. - */ - void InitUnpacker(); - protected: /** * @brief Choose the derived unpacker algorithm to be used for the DAQ output to Digi translation. If algo was already set manually by the user this algorithm is used. - * - * @return Bool_t initOk + * + * @return Bool_t initOk */ virtual std::shared_ptr<CbmTrdUnpackAlgoFasp2D> chooseAlgo(); - /** @brief Geometry setup tag for the given detector as used by CbmSetup objects */ - std::string fGeoSetupTag = ""; - - /** @brief RunId of the current run, if not known 0 is a valid runtime case. Used runId based parameter loading. */ - UInt_t fRunId = 0; - private: - ClassDef(CbmTrdUnpackConfigFasp2D, 2) + ClassDef(CbmTrdUnpackConfigFasp2D, 3) }; #endif // CbmTrdUnpackConfigFasp2D_H diff --git a/reco/steer/CMakeLists.txt b/reco/steer/CMakeLists.txt index e020938e05..ecfbb7e297 100644 --- a/reco/steer/CMakeLists.txt +++ b/reco/steer/CMakeLists.txt @@ -81,6 +81,7 @@ CbmPsdReco CbmRichReco CbmRecoSts CbmTofBase +CbmTofReco CbmTrdReco CbmData KF diff --git a/reco/steer/CbmRecoUnpack.cxx b/reco/steer/CbmRecoUnpack.cxx index 589aeede05..f63fbb4e81 100644 --- a/reco/steer/CbmRecoUnpack.cxx +++ b/reco/steer/CbmRecoUnpack.cxx @@ -70,49 +70,70 @@ Bool_t CbmRecoUnpack::Init() // --- Psd if (fPsdConfig) { - fPsdConfig->Init(ioman); + fPsdConfig->InitOutput(); + RegisterOutputs(ioman, fPsdConfig); /// Framework bound work = kept in this Task + fPsdConfig->SetAlgo(); + initParContainers(fPsdConfig->GetParContainerRequest()); /// Framework bound work = kept in this Task + fPsdConfig->InitAlgo(); initPerformanceMaps(fkFlesPsd, "PSD"); } // --- Rich if (fRichConfig) { - fRichConfig->Init(ioman); + fRichConfig->InitOutput(); + RegisterOutputs(ioman, fRichConfig); /// Framework bound work = kept in this Task + fRichConfig->SetAlgo(); + initParContainers(fRichConfig->GetParContainerRequest()); /// Framework bound work = kept in this Task + fRichConfig->InitAlgo(); initPerformanceMaps(fkFlesRich, "RICH"); } // --- Sts if (fStsConfig) { - fStsConfig->Init(ioman); + fStsConfig->InitOutput(); + RegisterOutputs(ioman, fStsConfig); /// Framework bound work = kept in this Task + fStsConfig->SetAlgo(); + initParContainers(fStsConfig->GetParContainerRequest()); /// Framework bound work = kept in this Task + fStsConfig->InitAlgo(); initPerformanceMaps(fkFlesSts, "STS"); } // --- Tof if (fTofConfig) { - fTofConfig->Init(ioman); + fTofConfig->InitOutput(); + RegisterOutputs(ioman, fTofConfig); /// Framework bound work = kept in this Task + fTofConfig->SetAlgo(); + initParContainers(fTofConfig->GetParContainerRequest()); /// Framework bound work = kept in this Task + fTofConfig->InitAlgo(); initPerformanceMaps(fkFlesTof, "TOF"); } // --- Trd if (fTrd1DConfig) { - fTrd1DConfig->Init(ioman); + fTrd1DConfig->InitOutput(); + RegisterOutputs(ioman, fTrd1DConfig); /// Framework bound work = kept in this Task + fTrd1DConfig->SetAlgo(); + initParContainers(fTrd1DConfig->GetParContainerRequest()); /// Framework bound work = kept in this Task + fTrd1DConfig->InitAlgo(); initPerformanceMaps(fkFlesTrd, "TRD1D"); } // --- TRD2D if (fTrd2DConfig) { - if (fTrd1DConfig) { - if (fTrd2DConfig->GetOutputBranchName() == fTrd1DConfig->GetOutputBranchName()) { - LOG(info) << fTrd2DConfig->GetName() << "::Init() ---------------------------------"; - fTrd2DConfig->SetOutputVec(fTrd1DConfig->GetOutputVec()); - fTrd2DConfig->InitUnpacker(); - LOG(info) << fTrd2DConfig->GetName() << " succesful initialized -----------------\n"; - } - else { - fTrd2DConfig->Init(ioman); - } + if (fTrd1DConfig && (fTrd2DConfig->GetOutputBranchName() == fTrd1DConfig->GetOutputBranchName())) { + LOG(info) << fTrd2DConfig->GetName() << "::Init() ---------------------------------"; + fTrd2DConfig->SetOutputVec(fTrd1DConfig->GetOutputVec()); } else { - fTrd2DConfig->Init(ioman); + fTrd2DConfig->InitOutput(); + RegisterOutputs(ioman, fTrd2DConfig); /// Framework bound work = kept in this Task } + fTrd2DConfig->SetAlgo(); + initParContainers(fTrd2DConfig->GetParContainerRequest()); /// Framework bound work = kept in this Task + fTrd2DConfig->InitAlgo(); initPerformanceMaps(fkFlesTrd2D, "TRD2D"); } - // This is an ugly work around, because the TRD and TRD2D want to access the same vector and there is no function to retrieve a writeable vector<obj> from the FairRootManager, especially before the branches are created, as far as I am aware. The second option workaround is in in Init() to look for the fasp config and create a separate branch for fasp created CbmTrdDigis PR 072021 + // This is an ugly work around, because the TRD and TRD2D want to access the same vector and there is no + // function to retrieve a writeable vector<obj> from the FairRootManager, especially before the branches + // are created, as far as I am aware. + // The second option workaround is in in Init() to look for the fasp config and create a separate branch + // for fasp created CbmTrdDigis PR 072021 return kTRUE; } diff --git a/reco/steer/CbmRecoUnpack.h b/reco/steer/CbmRecoUnpack.h index 5e131a4b2e..0ae07e4257 100644 --- a/reco/steer/CbmRecoUnpack.h +++ b/reco/steer/CbmRecoUnpack.h @@ -23,6 +23,9 @@ #include <MicrosliceDescriptor.hpp> #include <Timeslice.hpp> +#include <FairParAsciiFileIo.h> +#include <FairRootManager.h> + #include <RtypesCore.h> #include <THnSparse.h> #include <TObject.h> @@ -159,6 +162,59 @@ private: */ void initPerformanceMaps(std::uint16_t subsysid, std::string name); + + template<class TConfig> + void RegisterOutputs(FairRootManager* ioman, std::shared_ptr<TConfig> config) + { + /* + * FIXME: Compiling but leading to a segfault at runtime + auto pOutVect = config->GetOutputVec(); + if (pOutVect) { + ioman->RegisterAny(config->GetOutputBranchName().data(), pOutVect, kTRUE); + LOG(info) << "CbmRecoUnpack::RegisterOutputs() " << config->GetOutputBranchName() << " at " << pOutVect; + } + + auto pOutVectOptA = config->GetOptOutAVec(); + if (pOutVectOptA) { + ioman->RegisterAny(config->GetOutputBranchNameOptA().data(), pOutVectOptA, kTRUE); + LOG(info) << "CbmRecoUnpack::RegisterOutputs() " << config->GetOutputBranchNameOptA() << " at " << pOutVectOptA; + } + + auto pOutVectOptB = config->GetOptOutBVec(); + if (pOutVectOptB) { + ioman->RegisterAny(config->GetOutputBranchNameOptB().data(), pOutVectOptB, kTRUE); + LOG(info) << "CbmRecoUnpack::RegisterOutputs() " << config->GetOutputBranchNameOptB() << " at " << pOutVectOptB; + } +*/ + /// Alternative which compiles and run but forces to keep a Fairroot dependency in the Config template + config->RegisterOutput(ioman); + } + + /** + * @brief Initialise the parameter containers requested by the algorithm + * + * @return Bool_t initOk + */ + virtual Bool_t initParContainers(std::vector<std::pair<std::string, std::shared_ptr<FairParGenericSet>>>* reqparvec) + { + LOG(debug) << GetName() << "::Init - initParContainers"; + if (!reqparvec) { + LOG(info) << GetName() << "::Init - initParContainers - empty requirements vector no parameters initialized."; + return kTRUE; + } + + // Now get the actual ascii files and init the containers with the asciiIo + for (auto& pair : *reqparvec) { + auto filepath = pair.first; + auto parset = pair.second; + FairParAsciiFileIo asciiInput; + if (!filepath.empty()) { + if (asciiInput.open(filepath.data())) { parset->init(&asciiInput); } + } + } + return kTRUE; + } + /** @brief Sort a vector timewise vector type has to provide GetTime() */ template<typename TVecobj> typename std::enable_if<std::is_same<TVecobj, std::nullptr_t>::value == true, void>::type -- GitLab