diff --git a/macro/run/run_unpack_tsa_algo.C b/macro/run/run_unpack_tsa_algo.C index 2fd9dcd58a51c013bb271882da7a530b35ae5780..e2ea853e0b9a04bf981925e8154ed1e96f115327 100644 --- a/macro/run/run_unpack_tsa_algo.C +++ b/macro/run/run_unpack_tsa_algo.C @@ -29,7 +29,7 @@ #endif void run_unpack_tsa_algo(std::string infile, std::string outpath, std::string paramsdir, UInt_t runid, - std::int32_t nevents = -1) + std::int32_t nevents = -1, bool bCbmrootLikeOutput = false) { // ======================================================================== @@ -75,7 +75,9 @@ void run_unpack_tsa_algo(std::string infile, std::string outpath, std::string pa // ----- Algo Unpacker ------------------------------------------------- //run->AddTask(new CbmTaskUnpack()); - run->AddTask(new CbmTaskUnpack(paramsdir, runid)); + auto unpackTask = new CbmTaskUnpack(paramsdir, runid); + unpackTask->SetOutputModeCbmrootLike(bCbmrootLikeOutput); + run->AddTask(unpackTask); run->SetSink(sink); auto eventheader = new CbmTsEventHeader(); diff --git a/reco/steer/CbmSourceDigiTimeslice.cxx b/reco/steer/CbmSourceDigiTimeslice.cxx index 780d1d25e12727cd3ff76252ae4315e8c802d5cc..707d9a824f4ecaf3cc6b4343d80ba9a9c519ee92 100644 --- a/reco/steer/CbmSourceDigiTimeslice.cxx +++ b/reco/steer/CbmSourceDigiTimeslice.cxx @@ -63,8 +63,6 @@ Bool_t CbmSourceDigiTimeslice::Init() FairRootManager* ioman = FairRootManager::Instance(); assert(ioman); - auto* pEvtHeader = FairRun::Instance()->GetEventHeader(); - if (!(fTsEventHeader = dynamic_cast<CbmTsEventHeader*>(FairRun::Instance()->GetEventHeader()))) { LOG(fatal) << "CbmSourceDigiTimeslice::Init() no CbmTsEventHeader was added to the run. Without it, we can not " "store the UTC of the " diff --git a/reco/tasks/CbmTaskUnpack.cxx b/reco/tasks/CbmTaskUnpack.cxx index 9fa2a88fdae8899afee3f4badb03fe37d339d3d5..db0d9042fe6123738a7225636377b34a6eb23c3f 100644 --- a/reco/tasks/CbmTaskUnpack.cxx +++ b/reco/tasks/CbmTaskUnpack.cxx @@ -11,12 +11,14 @@ #include "CbmDigiManager.h" #include "CbmDigiTimeslice.h" #include "CbmSourceTs.h" +#include "CbmTimeSlice.h" #include "CbmTrdParFasp.h" #include "CbmTrdParModAsic.h" #include "CbmTrdParModDigi.h" #include "CbmTrdParSetAsic.h" #include "CbmTrdParSetDigi.h" #include "CbmTrdParSpadic.h" +#include "CbmTsEventHeader.h" #include "MicrosliceDescriptor.hpp" #include "ParFiles.h" #include "System.hpp" @@ -89,7 +91,17 @@ CbmTaskUnpack::CbmTaskUnpack(fs::path paramsDir, uint32_t runId) : FairTask("Unp // ----- Destructor ------------------------------------------------------ CbmTaskUnpack::~CbmTaskUnpack() { - if (fTimeslice) delete fTimeslice; + if (fDigiTimeslice) delete fDigiTimeslice; + + if (fCbmrootFormatOutput) { + // Clear output vectors + fBmonDigis->clear(); + fStsDigis->clear(); + fMuchDigis->clear(); + fTrdDigis->clear(); + fTofDigis->clear(); + fRichDigis->clear(); + } } // --------------------------------------------------------------------------- @@ -97,10 +109,6 @@ CbmTaskUnpack::~CbmTaskUnpack() // ----- Execution ------------------------------------------------------- void CbmTaskUnpack::Exec(Option_t*) { - - // --- Reset output branch (CbmDigiTimeslice) - fTimeslice->Clear(); - // --- Get FLES timeslice assert(fSource); fles::Timeslice* timeslice = fSource->GetTimeslice(); @@ -122,12 +130,42 @@ void CbmTaskUnpack::Exec(Option_t*) digis.fTrd = RunUnpacker(fTrdUnpack, *timeslice, monitor); digis.fTrd2d = RunUnpacker(fTrd2dUnpack, *timeslice, monitor); - // Use lines below to combine TRD 1D and 2D - //auto& digis1d = digis.fTrd; - //auto& digis2d = digis.fTrd2d; - //std::copy(digis2d.begin(), digis2d.end(), std::back_inserter(digis1d)); + if (fCbmrootFormatOutput) { + // Clear output vectors + fBmonDigis->clear(); + fStsDigis->clear(); + fMuchDigis->clear(); + fTrdDigis->clear(); + fTofDigis->clear(); + fRichDigis->clear(); + + fTsEventHeader->SetTsIndex(timeslice->index()); + fTsEventHeader->SetTsStartTime(timeslice->start_time()); + + fTimeslice->SetStartTime(timeslice->start_time()); + + std::move(digis.fBmon.begin(), digis.fBmon.end(), std::back_inserter(*fBmonDigis)); + std::move(digis.fSts.begin(), digis.fSts.end(), std::back_inserter(*fStsDigis)); + std::move(digis.fMuch.begin(), digis.fMuch.end(), std::back_inserter(*fMuchDigis)); + std::move(digis.fTrd2d.begin(), digis.fTrd2d.end(), std::back_inserter(*fTrdDigis)); + std::move(digis.fTrd.begin(), digis.fTrd.end(), std::back_inserter(*fTrdDigis)); + std::move(digis.fTof.begin(), digis.fTof.end(), std::back_inserter(*fTofDigis)); + std::move(digis.fRich.begin(), digis.fRich.end(), std::back_inserter(*fRichDigis)); + + // Time-sort the TRD vector as we merged TRD1D and TRD2D (needed for compatibility with legacy unpackers) + Timesort(fTrdDigis); + } + else { + // --- Reset output branch (CbmDigiTimeslice) + fDigiTimeslice->Clear(); - fTimeslice->fData = digis.ToStorable(); + // Use lines below to combine TRD 1D and 2D + //auto& digis1d = digis.fTrd; + //auto& digis2d = digis.fTrd2d; + //std::copy(digis2d.begin(), digis2d.end(), std::back_inserter(digis1d)); + + fDigiTimeslice->fData = digis.ToStorable(); + } // --- Timeslice log timer.Stop(); @@ -180,6 +218,20 @@ void CbmTaskUnpack::Finish() // ----- Initialisation --------------------------------------------------- +template<typename TVecobj> +Bool_t CbmTaskUnpack::RegisterVector(FairRootManager* ioman, std::vector<TVecobj>*& vec) +{ + if (ioman->GetObject(TVecobj::GetBranchName())) { + LOG(fatal) << GetName() << ": Branch " << TVecobj::GetBranchName() << " already exists!"; + return kFALSE; + } + + ioman->RegisterAny(TVecobj::GetBranchName(), vec, kTRUE); + LOG(info) << GetName() << ": Registered branch " << TVecobj::GetBranchName() << " at " << vec; + + return kTRUE; +} + InitStatus CbmTaskUnpack::Init() { LOG(info) << "=================================================="; @@ -205,9 +257,67 @@ InitStatus CbmTaskUnpack::Init() LOG(fatal) << GetName() << ": Branch DigiTimeslice already exists!"; return kFATAL; } - fTimeslice = new CbmDigiTimeslice(); - ioman->RegisterAny("DigiTimeslice.", fTimeslice, IsOutputBranchPersistent("DigiTimeslice.")); - LOG(info) << "--- Registered branch DigiTimeslice."; + + if (fCbmrootFormatOutput) { + + if (!(fTsEventHeader = dynamic_cast<CbmTsEventHeader*>(FairRun::Instance()->GetEventHeader()))) { + LOG(fatal) << "CbmSourceDigiTimeslice::Init() no CbmTsEventHeader was added to the run. " + "Without it, we can not store the UTC of the Timeslices correctly. " + "Hence, this causes a fatal. Please add it to the Run in the steering macro."; + return kFATAL; + } + + // TimeSlice. branch initialization + if (ioman->GetObject("TimeSlice.")) { + LOG(fatal) << "Source: Branch TimeSlice. already exists!"; + return kFATAL; + } + else { + // NOTE: the max time of timeslice is 1.28e8, taken from CbmRecoUnpack.cxx + fTimeslice = new CbmTimeSlice(0., 1.28e8 + 1.28e6); + ioman->Register("TimeSlice.", "DAQ", fTimeslice, kTRUE); + } + + fBmonDigis = new std::vector<CbmBmonDigi>(); + if (kFALSE == RegisterVector<CbmBmonDigi>(ioman, fBmonDigis)) { + return kFATAL; + } + + + fStsDigis = new std::vector<CbmStsDigi>(); + if (kFALSE == RegisterVector<CbmStsDigi>(ioman, fStsDigis)) { + return kFATAL; + } + + + fMuchDigis = new std::vector<CbmMuchDigi>(); + if (kFALSE == RegisterVector<CbmMuchDigi>(ioman, fMuchDigis)) { + return kFATAL; + } + + + fTrdDigis = new std::vector<CbmTrdDigi>(); + if (kFALSE == RegisterVector<CbmTrdDigi>(ioman, fTrdDigis)) { + return kFATAL; + } + + + fTofDigis = new std::vector<CbmTofDigi>(); + if (kFALSE == RegisterVector<CbmTofDigi>(ioman, fTofDigis)) { + return kFATAL; + } + + + fRichDigis = new std::vector<CbmRichDigi>(); + if (kFALSE == RegisterVector<CbmRichDigi>(ioman, fRichDigis)) { + return kFATAL; + } + } + else { + fDigiTimeslice = new CbmDigiTimeslice(); + ioman->RegisterAny("DigiTimeslice.", fDigiTimeslice, IsOutputBranchPersistent("DigiTimeslice.")); + LOG(info) << "--- Registered branch DigiTimeslice."; + } return kSUCCESS; } diff --git a/reco/tasks/CbmTaskUnpack.h b/reco/tasks/CbmTaskUnpack.h index 69cec6e193a28324643c168000f593ecba5bb76a..c091dd2873c62b087bc130309801813065f25ba3 100644 --- a/reco/tasks/CbmTaskUnpack.h +++ b/reco/tasks/CbmTaskUnpack.h @@ -39,6 +39,9 @@ namespace cbm class CbmDigiManager; class CbmSourceTs; +class CbmTimeSlice; +class CbmTsEventHeader; +class FairRootManager; namespace fs = boost::filesystem; @@ -99,6 +102,10 @@ class CbmTaskUnpack : public FairTask { void SetMonitor(cbm::Monitor* monitor) { fMonitor = monitor; } + /** @brief Set the output file in "as if cbmroot digi file" mode (default is "as if rra") **/ + void SetOutputModeCbmrootLike(bool flag = true) { fCbmrootFormatOutput = flag; } + + private: // methods /** @brief Task initialisation **/ virtual InitStatus Init(); @@ -117,18 +124,45 @@ class CbmTaskUnpack : public FairTask { std::unique_ptr<cbm::algo::trd::Unpack> fTrdUnpack; std::unique_ptr<cbm::algo::trd2d::Unpack> fTrd2dUnpack; - size_t fNumTs = 0; - size_t fNumMs = 0; - size_t fNumBytes = 0; - size_t fNumDigis = 0; - double fTime = 0.; - CbmDigiTimeslice* fTimeslice = nullptr; ///< Output data + size_t fNumTs = 0; + size_t fNumMs = 0; + size_t fNumBytes = 0; + size_t fNumDigis = 0; + double fTime = 0.; + CbmDigiTimeslice* fDigiTimeslice = nullptr; ///< Output data if writing root files "as if rra" + + /// Output data if writing root file "as if cbmroot digi file" + /// Flag controlling the output mode + bool fCbmrootFormatOutput = false; + /// => Time-slice header (old version, class about to be deprecated? one should use only CbmTsEventHeader soon?) + CbmTimeSlice* fTimeslice = nullptr; + /// Time-slice event header + CbmTsEventHeader* fTsEventHeader = nullptr; + /// => Branch vectors of Digis + std::vector<CbmBmonDigi>* fBmonDigis = nullptr; + std::vector<CbmStsDigi>* fStsDigis = nullptr; + std::vector<CbmMuchDigi>* fMuchDigis = nullptr; + std::vector<CbmTrdDigi>* fTrdDigis = nullptr; + std::vector<CbmTofDigi>* fTofDigis = nullptr; + std::vector<CbmRichDigi>* fRichDigis = nullptr; template<class Unpacker> auto RunUnpacker(const std::unique_ptr<Unpacker>& unpacker, const fles::Timeslice& ts, Monitor& monitor) -> cbm::algo::algo_traits::Output_t<Unpacker>; - ClassDef(CbmTaskUnpack, 3); + template<typename TVecobj> + Bool_t RegisterVector(FairRootManager* ioman, std::vector<TVecobj>*& vec); + + 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(); }); + } + + ClassDef(CbmTaskUnpack, 4); }; #endif /* CBMTASKUNPACK_H */