CbmDeviceUnpack.cxx 48.19 KiB
/* 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 "CbmBmonUnpackConfig.h"
#include "CbmFlesCanvasTools.h"
#include "CbmMQDefs.h"
#include "CbmMuchUnpackConfig.h"
#include "CbmPsdUnpackConfig.h"
#include "CbmRichUnpackConfig.h"
#include "CbmSetup.h"
#include "CbmStsUnpackConfig.h"
#include "CbmTofUnpackConfig.h"
#include "CbmTrdUnpackConfig.h"
#include "CbmTrdUnpackFaspConfig.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 bMcbm2018MonitorTaskBmonResetHistos = 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");
fbUnpBmon = fConfig->GetValue<bool>("UnpBmon");
fbUnpSts = fConfig->GetValue<bool>("UnpSts");
fbUnpMuch = fConfig->GetValue<bool>("UnpMuch");
fbUnpTrd1D = fConfig->GetValue<bool>("UnpTrd1d");
fbUnpTrd2D = fConfig->GetValue<bool>("UnpTrd2d");
fbUnpTof = fConfig->GetValue<bool>("UnpTof");
fbUnpRich = fConfig->GetValue<bool>("UnpRich");
fbUnpPsd = fConfig->GetValue<bool>("UnpPsd");
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");
fuPublishFreqTs = fConfig->GetValue<uint32_t>("PubFreqTs");
fdMinPublishTime = fConfig->GetValue<double_t>("PubTimeMin");
fdMaxPublishTime = fConfig->GetValue<double_t>("PubTimeMax");
fsChannelNameHistosInput = fConfig->GetValue<std::string>("ChNameIn");
}
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_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 -----------------------------------------------------
// TODO: support for multiple setups on Par Server? with request containing setup name?
CbmSetup* cbmsetup = CbmSetup::Instance();
FairMQMessagePtr req(NewSimpleMessage("setup"));
FairMQMessagePtr rep(NewMessage());
if (Send(req, "parameters") > 0) {
if (Receive(rep, "parameters") >= 0) {
if (0 != rep->GetSize()) {
CbmSetupStorable* exchangableSetup;
CbmMqTMessage tmsg(rep->GetData(), rep->GetSize());
exchangableSetup = dynamic_cast<CbmSetupStorable*>(tmsg.ReadObject(tmsg.GetClass()));
if (nullptr != exchangableSetup) {
/// Prevent clang format single line if
cbmsetup->LoadStoredSetup(exchangableSetup);
}
else {
LOG(error) << "Received corrupt reply. Setup not available";
throw InitTaskError("Setup not received from par-server.");
}
} // if( 0 != rep->GetSize() )
else {
LOG(error) << "Received empty reply. Setup not available";
throw InitTaskError("Setup not received from par-server.");
} // else of if( 0 != rep->GetSize() )
} // if( Receive( rep, "parameters" ) >= 0)
} // if( Send(req, "parameters") > 0 )
// ------------------------------------------------------------------------
/// Initialize the UnpackerConfigs objects and their "user options"
// ---- BMON ----
std::shared_ptr<CbmBmonUnpackConfig> bmonconfig = nullptr;
if (fbUnpBmon) {
bmonconfig = std::make_shared<CbmBmonUnpackConfig>("", fuRunId);
if (bmonconfig) {
// bmonconfig->SetDebugState();
bmonconfig->SetDoWriteOutput();
// bmonconfig->SetDoWriteOptOutA("CbmBmonErrors");
std::string parfilesbasepathBmon = Form("%s/macro/beamtime/mcbm2022/", srcDir.Data());
bmonconfig->SetParFilesBasePath(parfilesbasepathBmon);
bmonconfig->SetParFileName("mBmonCriPar.par");
bmonconfig->SetSystemTimeOffset(-1220); // [ns] value to be updated
if (2160 <= fuRunId) {
bmonconfig->SetSystemTimeOffset(-80); // [ns] value to be updated
}
if (2350 <= fuRunId) {
bmonconfig->SetSystemTimeOffset(0); // [ns] value to be updated
}
/// Enable Monitor plots
// bmonconfig->SetMonitor(GetTofMonitor(outfilename, true)); // FIXME: Unsupported for now
}
}
// -------------
// ---- STS ----
std::shared_ptr<CbmStsUnpackConfig> stsconfig = nullptr;
TString stsSetupTag = "";
cbmsetup->GetGeoTag(ECbmModuleId::kSts, stsSetupTag);
if ("" != stsSetupTag && fbUnpSts) {
LOG(info) << "From received setup, using STS tag: " << 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());
if (2060 <= fuRunId) {
/// Starting to readout the U3 since 10/03/2022 Carbon run
parfilesbasepathSts = Form("%s/macro/beamtime/mcbm2022/", 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
if (2160 <= fuRunId) {
stsconfig->SetSystemTimeOffset(-1075); // [ns] value to be updated
}
if (2350 <= fuRunId) {
stsconfig->SetSystemTimeOffset(-970); // [ns] value to be updated
}
stsconfig->SetMinAdcCut(1, 1);
stsconfig->SetMinAdcCut(2, 1);
stsconfig->SetMinAdcCut(3, 1);
stsconfig->SetMinAdcCut(4, 1);
stsconfig->MaskNoisyChannel(3, 56);
stsconfig->MaskNoisyChannel(3, 75);
stsconfig->MaskNoisyChannel(3, 79);
stsconfig->MaskNoisyChannel(3, 85);
stsconfig->MaskNoisyChannel(7, 123);
stsconfig->MaskNoisyChannel(7, 124);
stsconfig->MaskNoisyChannel(7, 125);
stsconfig->MaskNoisyChannel(7, 158);
stsconfig->MaskNoisyChannel(7, 159);
stsconfig->MaskNoisyChannel(7, 162);
stsconfig->MaskNoisyChannel(7, 715);
stsconfig->MaskNoisyChannel(9, 709);
stsconfig->MaskNoisyChannel(12, 119);
// Time Walk correction
std::map<uint32_t, CbmStsParModule> walkMap;
auto parAsic = new CbmStsParAsic(128, 31, 31., 1., 5., 800., 1000., 3.9789e-3);
// Module params: number of channels, number of channels per ASIC
auto parMod = new CbmStsParModule(2048, 128);
// default
double p0 = 0, p1 = 0, p2 = 0, p3 = 0;
parAsic->SetWalkCoef({p0, p1, p2, p3});
parMod->SetAllAsics(*parAsic);
walkMap[0x10107C02] = CbmStsParModule(*parMod); // Make a copy for storage
walkMap[0x101FFC02] = CbmStsParModule(*parMod); // Make a copy for storage
/// To be replaced by a storage in a new parameter class later
int sensor, asic;
std::ifstream asicTimeWalk_par(Form("%s/mStsAsicTimeWalk.par", parfilesbasepathSts.data()));
while (asicTimeWalk_par >> std::hex >> sensor >> std::dec >> asic >> p0 >> p1 >> p2 >> p3) {
std::cout << Form("Setting time-walk parametersfor: module %x, ASIC %u\n", sensor, asic);
parAsic->SetWalkCoef({p0, p1, p2, p3});
if (walkMap.find(sensor) == walkMap.end()) { walkMap[sensor] = CbmStsParModule(*parMod); }
walkMap[sensor].SetAsic(asic, *parAsic);
}
stsconfig->SetWalkMap(walkMap);
}
} // if ("" != stsSetupTag)
// -------------
// ---- MUCH ----
std::shared_ptr<CbmMuchUnpackConfig> muchconfig = nullptr;
TString muchSetupTag = "";
cbmsetup->GetGeoTag(ECbmModuleId::kMuch, muchSetupTag);
if ("" != muchSetupTag && fbUnpMuch) {
LOG(info) << "From received setup, using MUCH tag: " << muchSetupTag;
muchconfig = std::make_shared<CbmMuchUnpackConfig>(std::string(fsSetupName), fuRunId);
if (muchconfig) {
// muchconfig->SetDebugState();
muchconfig->SetDoWriteOutput();
muchconfig->SetDoWriteOptOutA("MuchDigiPulser");
std::string parfilesbasepathMuch = Form("%s/macro/beamtime/mcbm2022/", srcDir.Data());
muchconfig->SetParFilesBasePath(parfilesbasepathMuch);
if (2060 <= fuRunId && fuRunId <= 2162) {
/// Starting to use CRI Based MUCH setup with 2GEM and 1 RPC since 09/03/2022 Carbon run
muchconfig->SetParFileName("mMuchParUpto26032022.par");
}
else if (2163 <= fuRunId && fuRunId <= 2291) {
/// First nickel runs
muchconfig->SetParFileName("mMuchParUpto03042022.par");
}
else if (2311 <= fuRunId && fuRunId <= 2315) {
///
muchconfig->SetParFileName("mMuchParUpto10042022.par");
}
else if (2316 <= fuRunId && fuRunId <= 2366) {
///
muchconfig->SetParFileName("mMuchParUpto23052022.par");
}
else if (2367 <= fuRunId && fuRunId <= 2397) {
/// Starting to use GEM 2 moved to CRI 0 on 24/05/2022
muchconfig->SetParFileName("mMuchParUpto26052022.par");
}
/// Enable duplicates rejection, Ignores the ADC for duplicates check
muchconfig->SetDuplicatesRejection(true, true);
/// Enable Monitor plots
//muchconfig->SetMonitor(GetMuchMonitor(outfilename, true));
muchconfig->SetSystemTimeOffset(-2221); // [ns] value to be updated
if (2160 <= fuRunId) {
muchconfig->SetSystemTimeOffset(-1020); // [ns] value to be updated
}
if (2350 <= fuRunId) {
muchconfig->SetSystemTimeOffset(-980); // [ns] value to be updated
}
// muchconfig->SetMinAdcCut(1, 1);
// muchconfig->MaskNoisyChannel(3, 56);
}
}
// -------------
// ---- TRD ----
std::shared_ptr<CbmTrdUnpackConfig> trd1Dconfig = nullptr;
TString trdsetuptag = "";
cbmsetup->GetGeoTag(ECbmModuleId::kTrd, trdsetuptag);
if ("" != trdsetuptag && fbUnpTrd1D) {
LOG(info) << "From received setup, using TRD tag: " << 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 (2160 <= fuRunId) {
trd1Dconfig->SetSystemTimeOffset(1140); // [ns] value to be updated
}
if (2350 <= fuRunId) {
trd1Dconfig->SetSystemTimeOffset(1300); // [ns] value to be updated
}
}
} // if ("" != trdsetuptag)
// -------------
// ---- TRDFASP2D ----
std::shared_ptr<CbmTrdUnpackFaspConfig> trdfasp2dconfig = nullptr;
if ("" != trdsetuptag && fbUnpTrd2D) {
trdfasp2dconfig = std::make_shared<CbmTrdUnpackFaspConfig>(trdsetuptag.Data());
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");
// uint16_t crob_map[NCROBMOD];
// if (fuRunId <= 1588) {
// uint16_t crob_map21[] = {0x00f0, 0, 0, 0, 0};
// for (uint32_t i(0); i < NCROBMOD; i++)
// crob_map[i] = crob_map21[i];
// }
// else if (fuRunId >= 2335) {
// uint16_t crob_map22[] = {0xffc2, 0xffc5, 0xffc1, 0, 0};
// for (uint32_t i(0); i < NCROBMOD; i++)
// crob_map[i] = crob_map22[i];
// }
// trdfasp2dconfig->SetCrobMapping(5, crob_map);
std::string parfilesbasepathTrdfasp2d = Form("%s/parameters/trd", srcDir.Data());
trdfasp2dconfig->SetParFilesBasePath(parfilesbasepathTrdfasp2d);
trdfasp2dconfig->SetSystemTimeOffset(-1800); // [ns] value to be updated
if (2160 <= fuRunId) {
trdfasp2dconfig->SetSystemTimeOffset(-570); // [ns] value to be updated
}
if (2350 <= fuRunId) {
trdfasp2dconfig->SetSystemTimeOffset(-510); // [ns] value to be updated
}
}
} // if ("" != trdsetuptag)
// -------------
// ---- TOF ----
std::shared_ptr<CbmTofUnpackConfig> tofconfig = nullptr;
TString tofSetupTag = "";
cbmsetup->GetGeoTag(ECbmModuleId::kTof, tofSetupTag);
if ("" != tofSetupTag && fbUnpTof) {
LOG(info) << "From received setup, using TOF tag: " << 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());
std::string parFileNameTof = "mTofCriPar.par";
if (2060 <= fuRunId) {
/// Additional modules added just before the 10/03/2022 Carbon run
parfilesbasepathTof = Form("%s/macro/beamtime/mcbm2022/", srcDir.Data());
/// Setup changed multiple times between the 2022 carbon and uranium runs
if (fuRunId <= 2065) {
/// Carbon runs: 2060 - 2065
parFileNameTof = "mTofCriParCarbon.par";
}
else if (2150 <= fuRunId && fuRunId <= 2160) {
/// Iron runs: 2150 - 2160
parFileNameTof = "mTofCriParIron.par";
}
else if (2176 <= fuRunId && fuRunId <= 2310) {
/// Uranium runs: 2176 - 2310
parFileNameTof = "mTofCriParUranium.par";
}
else if (2335 <= fuRunId && fuRunId <= 2497) {
/// Nickel runs: 2335 - 2397
/// Gold runs: 2400 - 2497
parFileNameTof = "mTofCriParNickel.par";
}
else {
parFileNameTof = "mTofCriPar.par";
}
}
tofconfig->SetParFilesBasePath(parfilesbasepathTof);
tofconfig->SetParFileName(parFileNameTof);
tofconfig->SetSystemTimeOffset(-1220); // [ns] value to be updated
if (2160 <= fuRunId) {
tofconfig->SetSystemTimeOffset(0); // [ns] value to be updated
}
if (2350 <= fuRunId) {
tofconfig->SetSystemTimeOffset(45); // [ns] value to be updated
}
if (fuRunId <= 1659) {
/// Switch ON the -4 offset in epoch count (hack for Spring-Summer 2021)
tofconfig->SetFlagEpochCountHack2021();
}
}
} // if ("" != tofSetupTag)
// -------------
// ---- RICH ----
std::shared_ptr<CbmRichUnpackConfig> richconfig = nullptr;
TString richSetupTag = "";
cbmsetup->GetGeoTag(ECbmModuleId::kRich, richSetupTag);
if ("" != richSetupTag && fbUnpRich) {
LOG(info) << "From received setup, using RICH tag: " << richSetupTag;
richconfig = std::make_shared<CbmRichUnpackConfig>("", fuRunId);
if (richconfig) {
if (1904 < fuRunId) {
/// Switch to new unpacking algo starting from first combined cosmics run in 2022
richconfig->SetUnpackerVersion(CbmRichUnpackerVersion::v03);
}
richconfig->DoTotOffsetCorrection(); // correct ToT offset
richconfig->SetDebugState();
richconfig->SetDoWriteOutput();
std::string parfilesbasepathRich = Form("%s/macro/beamtime/mcbm2024/", srcDir.Data());
richconfig->SetParFilesBasePath(parfilesbasepathRich);
richconfig->SetSystemTimeOffset(256000 - 1200); // [ns] 1 MS and additional correction
if (1904 < fuRunId) richconfig->SetSystemTimeOffset(-1200);
if (2160 <= fuRunId) {
richconfig->SetSystemTimeOffset(50); // [ns] value to be updated
}
if (2350 <= fuRunId) {
richconfig->SetSystemTimeOffset(100); // [ns] value to be updated
}
if (1588 == fuRunId) richconfig->MaskDiRICH(0x7150);
}
} // if ("" != richSetupTag)
// -------------
// ---- PSD ----
std::shared_ptr<CbmPsdUnpackConfig> psdconfig = nullptr;
TString psdSetupTag = "";
cbmsetup->GetGeoTag(ECbmModuleId::kPsd, psdSetupTag);
if ("" != psdSetupTag && fbUnpPsd) {
LOG(info) << "From received setup, using PSD tag: " << 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 (muchconfig) SetUnpackConfig(muchconfig);
if (trd1Dconfig) SetUnpackConfig(trd1Dconfig);
if (trdfasp2dconfig) SetUnpackConfig(trdfasp2dconfig);
if (tofconfig) SetUnpackConfig(tofconfig);
if (bmonconfig) SetUnpackConfig(bmonconfig);
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 ("kBmon" == sSelDet && fBmonConfig) { //
fBmonConfig->SetSystemTimeOffset(iOffset);
} // else if( "kBmon" == sSelDet )
else if ("kSTS" == sSelDet && fStsConfig) { //
fStsConfig->SetSystemTimeOffset(iOffset);
} // if( "kSTS" == sSelDet && fStsConfig)
else if ("kMUCH" == sSelDet && fMuchConfig) {
fMuchConfig->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");
}
// --- Much
if (fMuchConfig) {
fMuchConfig->InitOutput();
// RegisterOutputs(ioman, fMuchConfig); /// Framework bound work = kept in this Task
fMuchConfig->SetAlgo();
initOK &= InitParameters(fMuchConfig->GetParContainerRequest()); /// Framework bound work = kept in this Device
fMuchConfig->InitAlgo();
// initPerformanceMaps(fkFlesMuch, "MUCH");
}
// --- 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
// --- 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");
}
// --- Bmon
if (fBmonConfig) {
fBmonConfig->InitOutput();
// RegisterOutputs(ioman, fBmonConfig); /// Framework bound work = kept in this Task
fBmonConfig->SetAlgo();
fBmonConfig->LoadParFileName(); /// Needed to change the Parameter file name before it is used!!!
initOK &= InitParameters(fBmonConfig->GetParContainerRequest()); /// Framework bound work = kept in this Device
fBmonConfig->InitAlgo();
// initPerformanceMaps(fkFlesBmon, "Bmon");
}
// --- 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;
}
bool CbmDeviceUnpack::InitHistograms()
{
/// Histos creation and obtain pointer on them
/// Trigger histo creation on all associated algos
// ALGO: bool initOK = fMonitorAlgo->CreateHistograms();
bool initOK = true;
/// Obtain vector of pointers on each histo from the algo (+ optionally desired folder)
// ALGO: std::vector<std::pair<TNamed*, std::string>> vHistos = fMonitorAlgo->GetHistoVector();
std::vector<std::pair<TNamed*, std::string>> vHistos = {};
/// Obtain vector of pointers on each canvas from the algo (+ optionally desired folder)
// ALGO: std::vector<std::pair<TCanvas*, std::string>> vCanvases = fMonitorAlgo->GetCanvasVector();
std::vector<std::pair<TCanvas*, std::string>> vCanvases = {};
/// Add pointers to each histo in the histo array
/// Create histo config vector
/// ===> Use an std::vector< std::pair< std::string, std::string > > with < Histo name, Folder >
/// and send it through a separate channel using the BoostSerializer
for (UInt_t uHisto = 0; uHisto < vHistos.size(); ++uHisto) {
// LOG(info) << "Registering " << vHistos[ uHisto ].first->GetName()
// << " in " << vHistos[ uHisto ].second.data()
// ;
fArrayHisto.Add(vHistos[uHisto].first);
std::pair<std::string, std::string> psHistoConfig(vHistos[uHisto].first->GetName(), vHistos[uHisto].second);
fvpsHistosFolder.push_back(psHistoConfig);
LOG(info) << "Config of hist " << psHistoConfig.first.data() << " in folder " << psHistoConfig.second.data();
} // for( UInt_t uHisto = 0; uHisto < vHistos.size(); ++uHisto )
/// Create canvas config vector
/// ===> Use an std::vector< std::pair< std::string, std::string > > with < Canvas name, config >
/// and send it through a separate channel using the BoostSerializer
for (UInt_t uCanv = 0; uCanv < vCanvases.size(); ++uCanv) {
// LOG(info) << "Registering " << vCanvases[ uCanv ].first->GetName()
// << " in " << vCanvases[ uCanv ].second.data();
std::string sCanvName = (vCanvases[uCanv].first)->GetName();
std::string sCanvConf = GenerateCanvasConfigString(vCanvases[uCanv].first);
std::pair<std::string, std::string> psCanvConfig(sCanvName, sCanvConf);
fvpsCanvasConfig.push_back(psCanvConfig);
LOG(info) << "Config string of Canvas " << psCanvConfig.first.data() << " is " << psCanvConfig.second.data();
} // for( UInt_t uCanv = 0; uCanv < vCanvases.size(); ++uCanv )
return initOK;
}
// Method called by run loop and requesting new data from the TS source whenever
bool CbmDeviceUnpack::ConditionalRun()
{
/// First do Algo related Initialization steps if needed
if (0 == fulNumMessages) {
try {
InitContainers();
}
catch (InitTaskError& e) {
LOG(error) << e.what();
ChangeState(fair::mq::Transition::ErrorFound);
}
} // if( 0 == fulNumMessages)
if (0 == fulNumMessages) InitHistograms();
/// First request a new TS (full one)
std::string message = "full";
LOG(debug) << "Requesting new TS by sending message: full" << message;
FairMQMessagePtr req(NewSimpleMessage(message));
FairMQMessagePtr rep(NewMessage());
if (Send(req, fsChannelNameDataInput) <= 0) {
LOG(error) << "Failed to send the request! message was " << message;
return false;
} // if (Send(req, fsChannelNameDataInput) <= 0)
else if (Receive(rep, fsChannelNameDataInput) < 0) {
LOG(error) << "Failed to receive a reply to the request! message was " << message;
return false;
} // else if (Receive(rep, fsChannelNameDataInput) < 0)
else if (rep->GetSize() == 0) {
LOG(error) << "Received empty reply. Something went wrong with the timeslice generation! message was " << message;
return false;
} // else if (rep->GetSize() == 0)
fulNumMessages++;
LOG(debug) << "Received message number " << fulNumMessages << " with size " << rep->GetSize();
if (0 == fulNumMessages % 10000) LOG(info) << "Received " << fulNumMessages << " messages";
std::string msgStr(static_cast<char*>(rep->GetData()), rep->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);
LOG(debug) << "Unpack: Sending TS index " << ts.index();
/// Send digi vectors to ouput
if (!SendUnpData()) return false;
LOG(debug) << "Unpack: Sent TS index " << ts.index();
// Reset the event header for a new timeslice
fCbmTsEventHeader->Reset();
// Reset the unpackers for a new timeslice, e.g. clear the output vectors
// ---- Bmon ----
if (fBmonConfig) fBmonConfig->Reset();
// ---- Sts ----
if (fStsConfig) fStsConfig->Reset();
// ----Much ----
if (fMuchConfig) fMuchConfig->Reset();
// ---- Trd ----
if (fTrd1DConfig) fTrd1DConfig->Reset();
// ---- Trd2D ----
if (fTrd2DConfig) fTrd2DConfig->Reset();
// ---- Tof ----
if (fTofConfig) fTofConfig->Reset();
// ---- Rich ----
if (fRichConfig) fRichConfig->Reset();
// ---- Psd ----
if (fPsdConfig) fPsdConfig->Reset();
/// Send histograms each 100 time slices. Should be each ~1s
/// Use also runtime checker to trigger sending after M s if
/// processing too slow or delay sending if processing too fast
std::chrono::system_clock::time_point currentTime = std::chrono::system_clock::now();
std::chrono::duration<double_t> elapsedSeconds = currentTime - fLastPublishTime;
if ((fdMaxPublishTime < elapsedSeconds.count())
|| (0 == fulNumMessages % fuPublishFreqTs && fdMinPublishTime < elapsedSeconds.count())) {
if (!fbConfigSent) {
// Send the configuration only once per run!
fbConfigSent = SendHistoConfAndData();
} // if( !fbConfigSent )
else
SendHistograms();
fLastPublishTime = std::chrono::system_clock::now();
} // if( ( fdMaxPublishTime < elapsedSeconds.count() ) || ( 0 == fulNumMessages % fuPublishFreqTs && fdMinPublishTime < elapsedSeconds.count() ) )
return true;
}
bool CbmDeviceUnpack::SendUnpData()
{
FairMQParts parts;
/// Prepare serialized versions of the TS Event header
FairMQMessagePtr messTsHeader(NewMessage());
// Serialize<RootSerializer>(*messTsHeader, fCbmTsEventHeader);
RootSerializer().Serialize(*messTsHeader, fCbmTsEventHeader);
parts.AddPart(std::move(messTsHeader));
// ---- Bmon ----
std::stringstream ossBmon;
boost::archive::binary_oarchive oaBmon(ossBmon);
if (fBmonConfig) { //
oaBmon << *(fBmonConfig->GetOutputVec());
}
else {
oaBmon << (std::vector<CbmBmonDigi>());
}
std::string* strMsgBmon = new std::string(ossBmon.str());
parts.AddPart(NewMessage(
const_cast<char*>(strMsgBmon->c_str()), // data
strMsgBmon->length(), // size
[](void*, void* object) { delete static_cast<std::string*>(object); },
strMsgBmon)); // object that manages the data
// ---- Sts ----
std::stringstream ossSts;
boost::archive::binary_oarchive oaSts(ossSts);
if (fStsConfig) { //
oaSts << *(fStsConfig->GetOutputVec());
}
else {
oaSts << (std::vector<CbmStsDigi>());
}
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);
if (fMuchConfig) { //
oaMuch << *(fMuchConfig->GetOutputVec());
}
else {
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());
}
else {
oaTrd << (std::vector<CbmTrdDigi>());
}
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());
}
else {
oaTof << (std::vector<CbmTofDigi>());
}
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());
}
else {
oaRich << (std::vector<CbmRichDigi>());
}
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());
}
else {
oaPsd << (std::vector<CbmPsdDigi>());
}
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);
RootSerializer().Serialize(*messTsMeta, fTsMetaData);
parts.AddPart(std::move(messTsMeta));
if (Send(parts, fsChannelNameDataOutput) < 0) {
LOG(error) << "Problem sending data to " << fsChannelNameDataOutput;
return false;
}
return true;
}
bool CbmDeviceUnpack::SendHistoConfAndData()
{
/// Prepare multiparts message and header
std::pair<uint32_t, uint32_t> pairHeader(fvpsHistosFolder.size(), fvpsCanvasConfig.size());
FairMQMessagePtr messageHeader(NewMessage());
// Serialize<BoostSerializer<std::pair<uint32_t, uint32_t>>>(*messageHeader, pairHeader);
BoostSerializer<std::pair<uint32_t, uint32_t>>().Serialize(*messageHeader, pairHeader);
FairMQParts partsOut;
partsOut.AddPart(std::move(messageHeader));
for (UInt_t uHisto = 0; uHisto < fvpsHistosFolder.size(); ++uHisto) {
/// Serialize the vector of histo config into a single MQ message
FairMQMessagePtr messageHist(NewMessage());
// Serialize<BoostSerializer<std::pair<std::string, std::string>>>(*messageHist, fvpsHistosFolder[uHisto]);
BoostSerializer<std::pair<std::string, std::string>>().Serialize(*messageHist, fvpsHistosFolder[uHisto]);
partsOut.AddPart(std::move(messageHist));
} // for (UInt_t uHisto = 0; uHisto < fvpsHistosFolder.size(); ++uHisto)
/// Catch case where no histos are registered!
/// => Add empty message
if (0 == fvpsHistosFolder.size()) {
FairMQMessagePtr messageHist(NewMessage());
partsOut.AddPart(std::move(messageHist));
}
for (UInt_t uCanv = 0; uCanv < fvpsCanvasConfig.size(); ++uCanv) {
/// Serialize the vector of canvas config into a single MQ message
FairMQMessagePtr messageCan(NewMessage());
// Serialize<BoostSerializer<std::pair<std::string, std::string>>>(*messageCan, fvpsCanvasConfig[uCanv]);
BoostSerializer<std::pair<std::string, std::string>>().Serialize(*messageCan, fvpsCanvasConfig[uCanv]);
partsOut.AddPart(std::move(messageCan));
} // for (UInt_t uCanv = 0; uCanv < fvpsCanvasConfig.size(); ++uCanv)
/// Catch case where no Canvases are registered!
/// => Add empty message
if (0 == fvpsCanvasConfig.size()) {
FairMQMessagePtr messageHist(NewMessage());
partsOut.AddPart(std::move(messageHist));
}
/// Serialize the array of histos into a single MQ message
FairMQMessagePtr msgHistos(NewMessage());
// Serialize<RootSerializer>(*msgHistos, &fArrayHisto);
RootSerializer().Serialize(*msgHistos, &fArrayHisto);
partsOut.AddPart(std::move(msgHistos));
/// Send the multi-parts message to the common histogram messages queue
if (Send(partsOut, fsChannelNameHistosInput) < 0) {
LOG(error) << "CbmTsConsumerReqDevExample::SendHistoConfAndData => Problem sending data";
return false;
} // if( Send( partsOut, fsChannelNameHistosInput ) < 0 )
/// Reset the histograms after sending them (but do not reset the time)
// ALGO: fMonitorAlgo->ResetHistograms(kFALSE);
return true;
}
bool CbmDeviceUnpack::SendHistograms()
{
/// Serialize the array of histos into a single MQ message
FairMQMessagePtr message(NewMessage());
// Serialize<RootSerializer>(*message, &fArrayHisto);
RootSerializer().Serialize(*message, &fArrayHisto);
/// Send message to the common histogram messages queue
if (Send(message, fsChannelNameHistosInput) < 0) {
LOG(error) << "Problem sending data";
return false;
} // if( Send( message, fsChannelNameHistosInput ) < 0 )
/// Reset the histograms after sending them (but do not reset the time)
// ALGO: fMonitorAlgo->ResetHistograms(kFALSE);
return true;
}
CbmDeviceUnpack::~CbmDeviceUnpack()
{
if (fBmonConfig) fBmonConfig->GetUnpacker()->Finish();
if (fStsConfig) fStsConfig->GetUnpacker()->Finish();
if (fMuchConfig) fMuchConfig->GetUnpacker()->Finish();
if (fTrd1DConfig) fTrd1DConfig->GetUnpacker()->Finish();
if (fTrd2DConfig) fTrd2DConfig->GetUnpacker()->Finish();
if (fTofConfig) fTofConfig->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(debug) << "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 fkFlesBmon: {
if (fBmonConfig) {
fCbmTsEventHeader->AddNDigisBmon(
unpack(systemId, &ts, component, fBmonConfig, fBmonConfig->GetOptOutAVec(), fBmonConfig->GetOptOutBVec()));
}
break;
}
case fkFlesSts: {
if (fStsConfig) {
fCbmTsEventHeader->AddNDigisSts(
unpack(systemId, &ts, component, fStsConfig, fStsConfig->GetOptOutAVec(), fStsConfig->GetOptOutBVec()));
}
break;
}
case fkFlesMuch: {
if (fMuchConfig) {
fCbmTsEventHeader->AddNDigisMuch(
unpack(systemId, &ts, component, fMuchConfig, fMuchConfig->GetOptOutAVec(), fMuchConfig->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 fkFlesTof: {
if (fTofConfig) {
fCbmTsEventHeader->AddNDigisTof(
unpack(systemId, &ts, component, fTofConfig, fTofConfig->GetOptOutAVec(), fTofConfig->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 (fBmonConfig && fBmonConfig->GetOutputVec()) { timesort(fBmonConfig->GetOutputVec()); }
if (fStsConfig && fStsConfig->GetOutputVec()) { timesort(fStsConfig->GetOutputVec()); }
if (fMuchConfig && fMuchConfig->GetOutputVec()) { timesort(fMuchConfig->GetOutputVec()); }
if (fTrd1DConfig && fTrd1DConfig->GetOutputVec()) { timesort(fTrd1DConfig->GetOutputVec()); }
if (fTrd2DConfig && fTrd2DConfig->GetOutputVec()) { timesort(fTrd2DConfig->GetOutputVec()); }
if (fTofConfig && fTofConfig->GetOutputVec()) { timesort(fTofConfig->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 (fBmonConfig && fBmonConfig->GetOptOutAVec()) { timesort(fBmonConfig->GetOptOutAVec()); }
if (fStsConfig && fStsConfig->GetOptOutAVec()) { timesort(fStsConfig->GetOptOutAVec()); }
if (fMuchConfig && fMuchConfig->GetOptOutAVec()) { timesort(fMuchConfig->GetOptOutAVec()); }
if (fTrd1DConfig && fTrd1DConfig->GetOptOutAVec()) { timesort(fTrd1DConfig->GetOptOutAVec()); }
if (fTrd2DConfig && fTrd2DConfig->GetOptOutAVec()) { timesort(fTrd2DConfig->GetOptOutAVec()); }
if (fTofConfig && fTofConfig->GetOptOutAVec()) { timesort(fTofConfig->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() {}