diff --git a/cmake/modules/FairMacros.cmake b/cmake/modules/FairMacros.cmake index f95bd2f4330bb7448308cb7b80e88ddb827b96a4..4dc7871bbc3d780792e42aba1ad791d7c20d2264 100644 --- a/cmake/modules/FairMacros.cmake +++ b/cmake/modules/FairMacros.cmake @@ -285,14 +285,25 @@ ENDMACRO (GENERATE_TEST_SCRIPT) Macro(Generate_Exe_Script _Path _ExeName) - Message("PATH: ${_Path}") - Message("ExeName: ${_ExeName}") set(shell_script_name "${_ExeName}.sh") - Message("shell_script_name: ${shell_script_name}") - string(REPLACE ${PROJECT_SOURCE_DIR} - ${PROJECT_BINARY_DIR} new_path ${_Path} - ) + # Check if _Path is in the build directory + string(FIND ${_Path} ${PROJECT_BINARY_DIR} result) + + # replace path only if not in build directory + if(${result} EQUAL -1) + string(REPLACE ${PROJECT_SOURCE_DIR} + ${PROJECT_BINARY_DIR} new_path ${_Path} + ) + else() + set(new_path ${_Path}) + endif() + + +# Message("PATH: ${_Path}") +# Message("ExeName: ${_ExeName}") +# Message("shell_script_name: ${shell_script_name}") +# Message("new_path: ${new_path}") set(my_exe_name ${EXECUTABLE_OUTPUT_PATH}/${_ExeName}) Write_Geant4Data_Variables_sh() diff --git a/cmake/scripts/run_binary.sh.in b/cmake/scripts/run_binary.sh.in index f465cbfd837ec7a82abfce6dfedec5a5d3c4e2a2..da3f83522133fb03d517785eb5e151b6b0e86fe0 100644 --- a/cmake/scripts/run_binary.sh.in +++ b/cmake/scripts/run_binary.sh.in @@ -2,4 +2,4 @@ source @CMAKE_BINARY_DIR@/config.sh -@my_exe_name@ +@my_exe_name@ "$@" diff --git a/core/data/CbmDefs.h b/core/data/CbmDefs.h index d55c7d9c45e2b8bedc57cdfa61685058201b4b04..64ddc7fcbf744f1c2d92fbd6a0a193803b3a6629 100644 --- a/core/data/CbmDefs.h +++ b/core/data/CbmDefs.h @@ -148,6 +148,16 @@ enum class ECbmTreeAccess kRandom }; +/** @enum ECbmRecoMode + ** @brief Reconstruct the full time slice or event-by-event + **/ +enum class ECbmRecoMode +{ + Timeslice, + EventByEvent, + Undefined +}; + /** Global functions for particle masses **/ inline double CbmProtonMass() { return 0.938272046; } diff --git a/external/InstallKFParticle.cmake b/external/InstallKFParticle.cmake index c3b30403716fe60c3f2f709a8e7d5305307bbbf8..d95717419bcd33b48de86f427f872dcc2e53effb 100644 --- a/external/InstallKFParticle.cmake +++ b/external/InstallKFParticle.cmake @@ -50,6 +50,7 @@ ExternalProject_Add(KFPARTICLE -DFIXTARGET=TRUE -DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH} -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON + -DCMAKE_MACOSX_RPATH=TRUE INSTALL_COMMAND ${CMAKE_COMMAND} --build . --target install ) @@ -62,11 +63,6 @@ target_link_libraries(KFParticle INTERFACE Vc::Vc) add_dependencies(KFParticle KFPARTICLE) -set(KFParticle_LIB_DIR ${CMAKE_BINARY_DIR}/lib PARENT_SCOPE) -set(KFParticle_LIBRARIES KFParticle PARENT_SCOPE) -set(KFParticle_INCLUDE_DIR "${CMAKE_BINARY_DIR}/include" PARENT_SCOPE) -set(KFParticle_FOUND TRUE PARENT_SCOPE) - Install(FILES ${CMAKE_BINARY_DIR}/lib/${KFPARTICLE_LIBNAME} ${CMAKE_BINARY_DIR}/lib/${CMAKE_SHARED_LIBRARY_PREFIX}KFParticle.rootmap ${CMAKE_BINARY_DIR}/lib/${CMAKE_SHARED_LIBRARY_PREFIX}KFParticle_rdict.pcm diff --git a/macro/L1/run_reco_L1global.C b/macro/L1/run_reco_L1global.C index 0d15ce7b10e3a6c087d8d4e3f5a3cba578691505..2d2130013cc65dd68087f182c36826da0460e8d0 100644 --- a/macro/L1/run_reco_L1global.C +++ b/macro/L1/run_reco_L1global.C @@ -274,8 +274,8 @@ void run_reco_L1global(TString input = "", Int_t nTimeSlices = -1, Int_t firstTi // ----- Local reconstruction in STS ---------------------------------- if (useSts) { - CbmRecoSts* stsReco = new CbmRecoSts(ECbmRecoMode::kCbmRecoTimeslice); - if (eventBased) stsReco->SetMode(ECbmRecoMode::kCbmRecoEvent); + CbmRecoSts* stsReco = new CbmRecoSts(ECbmRecoMode::Timeslice); + if (eventBased) stsReco->SetMode(ECbmRecoMode::EventByEvent); run->AddTask(stsReco); std::cout << "-I- " << myName << ": Added task " << stsReco->GetName() << std::endl; } diff --git a/macro/L1/run_reco_LITglobal.C b/macro/L1/run_reco_LITglobal.C index 3bca70a90d7292bf10ce829747f58a25b1d25c39..7647cd2cd3091882cb800fd241b23a145ad6c098 100644 --- a/macro/L1/run_reco_LITglobal.C +++ b/macro/L1/run_reco_LITglobal.C @@ -284,9 +284,9 @@ void run_reco_LITglobal(TString input = "", Int_t nTimeSlices = -1, Int_t firstT // ----- Local reconstruction in STS ---------------------------------- if (useSts) { - CbmRecoSts* stsReco = new CbmRecoSts(ECbmRecoMode::kCbmRecoTimeslice); + CbmRecoSts* stsReco = new CbmRecoSts(ECbmRecoMode::Timeslice); stsReco->SetUseGpuReco(stsRecoUseGpu); - if (eventBased) stsReco->SetMode(ECbmRecoMode::kCbmRecoEvent); + if (eventBased) stsReco->SetMode(ECbmRecoMode::EventByEvent); run->AddTask(stsReco); std::cout << "-I- " << myName << ": Added task " << stsReco->GetName() << std::endl; } diff --git a/macro/PWG/common/production/run_reco_json_config.C b/macro/PWG/common/production/run_reco_json_config.C index fd18cbd4a7e2125541db156852188a3c99a2f797..9d62d2fdcfed96877903ce2d1e23a6aaf482f880 100644 --- a/macro/PWG/common/production/run_reco_json_config.C +++ b/macro/PWG/common/production/run_reco_json_config.C @@ -309,8 +309,8 @@ void run_reco_json_config(TString input = "", Int_t nTimeSlices = -1, Int_t firs // ----- Local reconstruction in STS ---------------------------------- if (useSts) { - CbmRecoSts* stsReco = new CbmRecoSts(ECbmRecoMode::kCbmRecoTimeslice); - if (eventBased) stsReco->SetMode(ECbmRecoMode::kCbmRecoEvent); + CbmRecoSts* stsReco = new CbmRecoSts(ECbmRecoMode::Timeslice); + if (eventBased) stsReco->SetMode(ECbmRecoMode::EventByEvent); run->AddTask(stsReco); std::cout << "-I- " << myName << ": Added task " << stsReco->GetName() << std::endl; } diff --git a/macro/analysis/dielectron/run_reco.C b/macro/analysis/dielectron/run_reco.C index a51ba8c3dd85ce04ba66d3e19445c7dc9f046a59..d10f528e731b822ef82b4ef593a71f34ecbec7c0 100644 --- a/macro/analysis/dielectron/run_reco.C +++ b/macro/analysis/dielectron/run_reco.C @@ -89,7 +89,7 @@ void run_reco(const string& traFile, const string& parFile, const string& digiFi if (useSts) { CbmRecoSts* stsReco = new CbmRecoSts(ECbmRecoMode::kCbmRecoTimeslice); - if (eventBased) stsReco->SetMode(ECbmRecoMode::kCbmRecoEvent); + if (eventBased) stsReco->SetMode(ECbmRecoMode::EventByEvent); run->AddTask(stsReco); } diff --git a/macro/beamtime/mcbm2020/mcbm_build_and_reco.C b/macro/beamtime/mcbm2020/mcbm_build_and_reco.C index 3ecbc4f3128a1a20917d9cc296c740b89ed63d4a..b190ae0fa13e7b7dcdc8d88cc8eeda9ce958c24f 100644 --- a/macro/beamtime/mcbm2020/mcbm_build_and_reco.C +++ b/macro/beamtime/mcbm2020/mcbm_build_and_reco.C @@ -1,6 +1,6 @@ /* Copyright (C) 2020-2021 PI-UHd, GSI SPDX-License-Identifier: GPL-3.0-only - Authors: Pierre-Alain Loizeau */ + Authors: Pierre-Alain Loizeau [committer] */ // -------------------------------------------------------------------------- // @@ -194,7 +194,7 @@ Bool_t mcbm_build_and_reco(UInt_t uRunId = 831, // ----- Local reconstruction in STS ---------------------------------- CbmRecoSts* recoSts = new CbmRecoSts(); - recoSts->SetMode(kCbmRecoEvent); + recoSts->SetMode(ECbmRecoMode::EventByEvent); //recoSts->SetTimeCutDigisAbs( 20 );// cluster finder: time cut in ns //recoSts->SetTimeCutClustersAbs(20.); // hit finder: time cut in ns diff --git a/macro/beamtime/mcbm2020/mcbm_event_ana.C b/macro/beamtime/mcbm2020/mcbm_event_ana.C index d66e84b0ee77690317539297d865186e28999b4c..442287da45f6b935f6d2d82228c487e335351a5b 100644 --- a/macro/beamtime/mcbm2020/mcbm_event_ana.C +++ b/macro/beamtime/mcbm2020/mcbm_event_ana.C @@ -128,7 +128,7 @@ void mcbm_event_ana(UInt_t uRunId = 831, // ----- Local reconstruction in STS ---------------------------------- CbmRecoSts* recoSts = new CbmRecoSts(); - recoSts->SetMode(kCbmRecoEvent); + recoSts->SetMode(ECbmRecoMode::EventByEvent); //recoSts->SetTimeCutDigisAbs( 20 );// cluster finder: time cut in ns //recoSts->SetTimeCutClustersAbs(20.); // hit finder: time cut in ns diff --git a/macro/beamtime/mcbm2020/mcbm_event_reco.C b/macro/beamtime/mcbm2020/mcbm_event_reco.C index 9b99527eb760bcf576c7b457fbf1630dc074b656..57331286060f44187cf6faefb7d1db835cd1225c 100644 --- a/macro/beamtime/mcbm2020/mcbm_event_reco.C +++ b/macro/beamtime/mcbm2020/mcbm_event_reco.C @@ -1,6 +1,6 @@ /* Copyright (C) 2020-2021 PI-UHd, GSI SPDX-License-Identifier: GPL-3.0-only - Authors: Pierre-Alain Loizeau, Pascal Raisig */ + Authors: Pierre-Alain Loizeau [committer], Pascal Raisig */ // -------------------------------------------------------------------------- // @@ -138,7 +138,7 @@ Bool_t mcbm_event_reco(UInt_t uRunId = 831, // ----- Local reconstruction in STS ---------------------------------- CbmRecoSts* recoSts = new CbmRecoSts(); - recoSts->SetMode(kCbmRecoEvent); + recoSts->SetMode(ECbmRecoMode::EventByEvent); //recoSts->SetTimeCutDigisAbs( 20 );// cluster finder: time cut in ns //recoSts->SetTimeCutClustersAbs(20.); // hit finder: time cut in ns diff --git a/macro/beamtime/mcbm2020/mcbm_event_reco_ana.C b/macro/beamtime/mcbm2020/mcbm_event_reco_ana.C index 7b1583c5a31b3d293b113b1365d2395a67dc108d..e242f794d6bf7a39ed7b1cd852d48e79bc3350a4 100644 --- a/macro/beamtime/mcbm2020/mcbm_event_reco_ana.C +++ b/macro/beamtime/mcbm2020/mcbm_event_reco_ana.C @@ -94,7 +94,7 @@ void mcbm_event_reco_ana(Int_t runId = 831, Int_t nTimeslices = 1000) // ----- Local reconstruction in STS ---------------------------------- CbmRecoSts* recoSts = new CbmRecoSts(); - recoSts->SetMode(kCbmRecoEvent); + recoSts->SetMode(ECbmRecoMode::EventByEvent); //recoSts->SetTimeCutDigisAbs( 20 );// cluster finder: time cut in ns //recoSts->SetTimeCutClustersAbs(20.); // hit finder: time cut in ns diff --git a/macro/beamtime/mcbm2021/dis_reco_mcbm_digievent.C b/macro/beamtime/mcbm2021/dis_reco_mcbm_digievent.C index 4e7e8b1bcdb310b1591d1207532039614bda6dc8..ea78004de38fe9539acfb70f1c050865005587f0 100644 --- a/macro/beamtime/mcbm2021/dis_reco_mcbm_digievent.C +++ b/macro/beamtime/mcbm2021/dis_reco_mcbm_digievent.C @@ -209,7 +209,7 @@ void dis_reco_mcbm_digievent(TString input = "", Int_t nTimeSlices = 1, Int_t fi //std::cout << "-I- " << myName << ": Adding task " << recoSts->GetName(); CbmRecoSts* recoSts = new CbmRecoSts(); - recoSts->SetMode(kCbmRecoEvent); + recoSts->SetMode(ECbmRecoMode::EventByEvent); recoSts->SetTimeCutDigisAbs(20.0); // cluster finder: time cut in ns recoSts->SetTimeCutClustersAbs(20.0); // hit finder: time cut in ns diff --git a/macro/beamtime/mcbm2021/mcbm_event_reco.C b/macro/beamtime/mcbm2021/mcbm_event_reco.C index 0a5b00426039dfb2a8bae33af028caccc02b1920..0950dacd3d84190225252f690fc2c37c110b6639 100644 --- a/macro/beamtime/mcbm2021/mcbm_event_reco.C +++ b/macro/beamtime/mcbm2021/mcbm_event_reco.C @@ -264,7 +264,7 @@ Bool_t mcbm_event_reco(UInt_t uRunId = 1588, if (geoSetup->IsActive(ECbmModuleId::kSts)) { CbmRecoSts* recoSts = new CbmRecoSts(); - recoSts->SetMode(kCbmRecoEvent); + recoSts->SetMode(ECbmRecoMode::EventByEvent); recoSts->SetTimeCutDigisAbs(20.0); // cluster finder: time cut in ns recoSts->SetTimeCutClustersAbs(20.0); // hit finder: time cut in ns diff --git a/macro/beamtime/mcbm2021/run_reco_mcbm_digievent.C b/macro/beamtime/mcbm2021/run_reco_mcbm_digievent.C index 663807f1db9997f46c2b2d54f2b11d38b4edfc9d..440089db77a21e7568112e314240c418a4c58a2a 100644 --- a/macro/beamtime/mcbm2021/run_reco_mcbm_digievent.C +++ b/macro/beamtime/mcbm2021/run_reco_mcbm_digievent.C @@ -225,7 +225,7 @@ void run_reco_mcbm_digievent(TString input = "", Int_t nTimeSlices = -1, Int_t f //std::cout << "-I- " << myName << ": Adding task " << recoSts->GetName(); CbmRecoSts* recoSts = new CbmRecoSts(); - recoSts->SetMode(kCbmRecoEvent); + recoSts->SetMode(ECbmRecoMode::EventByEvent); recoSts->SetTimeCutDigisAbs(20.0); // cluster finder: time cut in ns recoSts->SetTimeCutClustersAbs(20.0); // hit finder: time cut in ns diff --git a/macro/beamtime/mcbm2022/mcbm_digievent_reco.C b/macro/beamtime/mcbm2022/mcbm_digievent_reco.C index b404b52458e8922b79043567e08a756f06aebe22..5a2260af0c60caa00ecff8e0e038d0e9c54da16c 100644 --- a/macro/beamtime/mcbm2022/mcbm_digievent_reco.C +++ b/macro/beamtime/mcbm2022/mcbm_digievent_reco.C @@ -277,7 +277,7 @@ Bool_t mcbm_digievent_reco(UInt_t uRunId = 2365, if (bSTS && geoSetup->IsActive(ECbmModuleId::kSts)) { CbmRecoSts* recoSts = new CbmRecoSts(); - recoSts->SetMode(kCbmRecoEvent); + recoSts->SetMode(ECbmRecoMode::EventByEvent); recoSts->SetTimeCutDigisAbs(20.0); // cluster finder: time cut in ns recoSts->SetTimeCutClustersAbs(20.0); // hit finder: time cut in ns diff --git a/macro/beamtime/mcbm2022/mcbm_event_reco.C b/macro/beamtime/mcbm2022/mcbm_event_reco.C index bc684474d85e6000904614a0ccd5900d56a4b496..b14ad914d3bd9c6a0f5e59a4b14b414046f9faf3 100644 --- a/macro/beamtime/mcbm2022/mcbm_event_reco.C +++ b/macro/beamtime/mcbm2022/mcbm_event_reco.C @@ -301,7 +301,7 @@ Bool_t mcbm_event_reco(UInt_t uRunId = 2391, if (geoSetup->IsActive(ECbmModuleId::kSts)) { CbmRecoSts* recoSts = new CbmRecoSts(); - recoSts->SetMode(kCbmRecoEvent); + recoSts->SetMode(ECbmRecoMode::EventByEvent); recoSts->SetTimeCutDigisAbs(20.0); // cluster finder: time cut in ns recoSts->SetTimeCutClustersAbs(20.0); // hit finder: time cut in ns diff --git a/macro/beamtime/mcbm2022/mcbm_reco.C b/macro/beamtime/mcbm2022/mcbm_reco.C index 394bdcb7c3adcfb4060b968d66a7c3a451db505a..53a3578972a07d2224bb4f95f02bb8d87e2c12a8 100644 --- a/macro/beamtime/mcbm2022/mcbm_reco.C +++ b/macro/beamtime/mcbm2022/mcbm_reco.C @@ -287,7 +287,7 @@ Bool_t mcbm_reco(UInt_t uRunId = 2391, if (bSTS && geoSetup->IsActive(ECbmModuleId::kSts)) { CbmRecoSts* recoSts = new CbmRecoSts(); - recoSts->SetMode(kCbmRecoEvent); + recoSts->SetMode(ECbmRecoMode::EventByEvent); recoSts->SetTimeCutDigisAbs(20.0); // cluster finder: time cut in ns recoSts->SetTimeCutClustersAbs(20.0); // hit finder: time cut in ns diff --git a/macro/mcbm/mcbm_reco_event_tb_nh.C b/macro/mcbm/mcbm_reco_event_tb_nh.C index 62b7366625d9be2987a675100bf28ca3ecbc4761..b530685210505d90e2f15f2c3b0d528ee5a76aae 100644 --- a/macro/mcbm/mcbm_reco_event_tb_nh.C +++ b/macro/mcbm/mcbm_reco_event_tb_nh.C @@ -237,7 +237,7 @@ void mcbm_reco_event_tb_nh(Int_t nEvents = 10, TString RunId = "test", TString I if (setup->IsActive(ECbmModuleId::kSts)) { CbmRecoSts* stsReco = NULL; if (timebased) { - stsReco = new CbmRecoSts(kCbmRecoEvent, kFALSE, kFALSE); + stsReco = new CbmRecoSts(ECbmRecoMode::EventByEvent, kFALSE, kFALSE); // stsReco = new CbmRecoSts(); } else { diff --git a/macro/run/CMakeLists.txt b/macro/run/CMakeLists.txt index c8846808a37c387d89f6f59384823eee4c792f82..dd8fc5160f1b46c2ef1024cefb9b6f473b4bd451 100644 --- a/macro/run/CMakeLists.txt +++ b/macro/run/CMakeLists.txt @@ -5,6 +5,8 @@ GENERATE_ROOT_TEST_SCRIPT(${CBMROOT_SOURCE_DIR}/macro/run/run_digi.C) GENERATE_ROOT_TEST_SCRIPT(${CBMROOT_SOURCE_DIR}/macro/run/run_reco.C) GENERATE_ROOT_TEST_SCRIPT(${CBMROOT_SOURCE_DIR}/macro/run/run_qa.C) +GENERATE_EXE_SCRIPT(${CBMROOT_BINARY_DIR}/bin cbmreco_offline) + Set(MACRO_DIR ${CMAKE_CURRENT_BINARY_DIR}) # ============================================================================ @@ -165,13 +167,31 @@ foreach(setup IN LISTS cbm_setup) add_test(${testname} ${MACRODIR}/run_reco.sh \"data/${sname}_ev\" -1 0 \"data/${sname}_eb_eb_ideal\" \"Ideal\" \"${setup}\" \"data/${sname}_coll\") set_tests_properties(${testname} PROPERTIES - TIMEOUT ${timeOutTime} + TIMEOUT ${timeOutTime} FAIL_REGULAR_EXPRESSION "segmentation violation" PASS_REGULAR_EXPRESSION "Macro finished successfully" FIXTURES_REQUIRED fixt_digi_ev_${setup} FIXTURES_SETUP fixt_reco_ev_ideal_${setup} RESOURCE_LOCK collParDb_${setup} ) + + # --- Test run_reco_offline_ev_ideal + # --- Event-by-event reconstruction from event-based simulation, with binary cbmreco_offline + # --- Ideal raw event builder + set(testname run_${sname}_reco_offline_ev_ideal) + set(binary ${CBMROOT_BINARY_DIR}/bin/cbmreco_offline.sh) + set(inputname data/${sname}_ev.raw.root) + set(parfilename data/${sname}_coll.par.root) + set(outputname data/dummy.reco.root) + set(configname ${CBMROOT_SOURCE_DIR}/reco/offline/config/RecoConfig_event_ideal.yaml) + set(cl_options -i ${inputname} -o ${outputname} -p ${parfilename} -c ${configname} -s ${setup} -w) + add_test(NAME ${testname} COMMAND ${binary} ${cl_options}) + set_tests_properties(${testname} PROPERTIES + TIMEOUT ${timeOutTime} + FIXTURES_REQUIRED fixt_digi_ev_${setup} + FIXTURES_SETUP fixt_reco_offline_ev_ideal_${setup} + RESOURCE_LOCK collParDb_${setup} + ) # --- Test run_reco_ev_real # --- Event-by-event reconstruction from event-based simulation @@ -188,6 +208,24 @@ foreach(setup IN LISTS cbm_setup) FIXTURES_SETUP fixt_reco_ev_real_${setup} RESOURCE_LOCK collParDb_${setup} ) + + # --- Test run_reco_offline_ev_real + # --- Event-by-event reconstruction from event-based simulation, with binary cbmreco_offline + # --- Real raw event builder + set(testname run_${sname}_reco_offline_ev_real) + set(binary ${CBMROOT_BINARY_DIR}/bin/cbmreco_offline.sh) + set(inputname data/${sname}_ev.raw.root) + set(parfilename data/${sname}_coll.par.root) + set(outputname data/dummy.reco.root) + set(configname ${CBMROOT_SOURCE_DIR}/reco/offline/config/RecoConfig_event_real.yaml) + set(cl_options -i ${inputname} -o ${outputname} -p ${parfilename} -c ${configname} -s ${setup} -w) + add_test(NAME ${testname} COMMAND ${binary} ${cl_options}) + set_tests_properties(${testname} PROPERTIES + TIMEOUT ${timeOutTime} + FIXTURES_REQUIRED fixt_digi_ev_${setup} + FIXTURES_SETUP fixt_reco_offline_ev_ideal_${setup} + RESOURCE_LOCK collParDb_${setup} + ) # --- Test run_reco_ts_eb_ideal # --- Event-by-event reconstruction from time-based simulation @@ -204,7 +242,25 @@ foreach(setup IN LISTS cbm_setup) FIXTURES_SETUP fixt_reco_ts_eb_ideal_${setup} RESOURCE_LOCK collParDb_${setup} ) - + + # --- Test run_reco_offline_ts_eb_ideal + # --- Event-by-event reconstruction from time-based simulation, with binary cbmreco_offline + # --- Real raw event builder + set(testname run_${sname}_reco_offline_ts_eb_ideal) + set(binary ${CBMROOT_BINARY_DIR}/bin/cbmreco_offline.sh) + set(inputname data/${sname}_ts.raw.root) + set(parfilename data/${sname}_coll.par.root) + set(outputname data/dummy.reco.root) + set(configname ${CBMROOT_SOURCE_DIR}/reco/offline/config/RecoConfig_event_ideal.yaml) + set(cl_options -i ${inputname} -o ${outputname} -p ${parfilename} -c ${configname} -s ${setup} -w) + add_test(NAME ${testname} COMMAND ${binary} ${cl_options}) + set_tests_properties(${testname} PROPERTIES + TIMEOUT ${timeOutTime} + FIXTURES_REQUIRED fixt_digi_ev_${setup} + FIXTURES_SETUP fixt_reco_offline_ev_ideal_${setup} + RESOURCE_LOCK collParDb_${setup} + ) + # --- Test run_reco_ts_eb_real # --- Event-by-event reconstruction from time-based simulation # --- Real raw event builder @@ -220,7 +276,25 @@ foreach(setup IN LISTS cbm_setup) FIXTURES_SETUP fixt_reco_ts_eb_real_${setup} RESOURCE_LOCK collParDb_${setup} ) - + + # --- Test run_reco_offline_ts_eb_real + # --- Event-by-event reconstruction from event-based simulation, with binary cbmreco_offline + # --- Real raw event builder + set(testname run_${sname}_reco_offline_ts_eb_real) + set(binary ${CBMROOT_BINARY_DIR}/bin/cbmreco_offline.sh) + set(inputname data/${sname}_ts.raw.root) + set(parfilename data/${sname}_coll.par.root) + set(outputname data/dummy.reco.root) + set(configname ${CBMROOT_SOURCE_DIR}/reco/offline/config/RecoConfig_event_real.yaml) + set(cl_options -i ${inputname} -o ${outputname} -p ${parfilename} -c ${configname} -s ${setup} -w) + add_test(NAME ${testname} COMMAND ${binary} ${cl_options}) + set_tests_properties(${testname} PROPERTIES + TIMEOUT ${timeOutTime} + FIXTURES_REQUIRED fixt_digi_ev_${setup} + FIXTURES_SETUP fixt_reco_offline_ev_ideal_${setup} + RESOURCE_LOCK collParDb_${setup} + ) + # --- Test run_qa # --- Run QA tasks with Event-by-event reconstruction from time-based simulation # --- Real raw event builder @@ -252,6 +326,24 @@ foreach(setup IN LISTS cbm_setup) FIXTURES_SETUP fixt_reco_ts_tb_${setup} RESOURCE_LOCK collParDb_${setup} ) + + # --- Test run_reco_offline_ts_tb + # --- Time-based reconstruction from time-based simulation, with binary cbmreco_offline + set(testname run_${sname}_reco_offline_ts_tb) + set(binary ${CBMROOT_BINARY_DIR}/bin/cbmreco_offline.sh) + set(inputname data/${sname}_ts.raw.root) + set(parfilename data/${sname}_coll.par.root) + set(outputname data/dummy.reco.root) + set(configname ${CBMROOT_SOURCE_DIR}/reco/offline/config/RecoConfig_timeslice.yaml) + set(cl_options -i ${inputname} -o ${outputname} -p ${parfilename} -c ${configname} -s ${setup} -w) + add_test(NAME ${testname} COMMAND ${binary} ${cl_options}) + set_tests_properties(${testname} PROPERTIES + TIMEOUT ${timeOutTime} + FIXTURES_REQUIRED fixt_digi_ev_${setup} + FIXTURES_SETUP fixt_reco_offline_ev_ideal_${setup} + RESOURCE_LOCK collParDb_${setup} + ) + endforeach(setup IN LISTS cbm_setup) diff --git a/macro/run/run_reco.C b/macro/run/run_reco.C index ba81a3b3c95e51520c807bc7a168f426e043d841..06c5501f44c82f36ca0cffa4f3c451a647389e33 100644 --- a/macro/run/run_reco.C +++ b/macro/run/run_reco.C @@ -288,9 +288,9 @@ void run_reco(TString input = "", Int_t nTimeSlices = -1, Int_t firstTimeSlice = // ----- Local reconstruction in STS ---------------------------------- if (useSts) { - CbmRecoSts* stsReco = new CbmRecoSts(ECbmRecoMode::kCbmRecoTimeslice); + CbmRecoSts* stsReco = new CbmRecoSts(ECbmRecoMode::Timeslice); stsReco->SetUseGpuReco(stsRecoUseGpu); - if (eventBased) stsReco->SetMode(ECbmRecoMode::kCbmRecoEvent); + if (eventBased) stsReco->SetMode(ECbmRecoMode::EventByEvent); run->AddTask(stsReco); std::cout << "-I- " << myName << ": Added task " << stsReco->GetName() << std::endl; } diff --git a/macro/run/run_reco_digievent.C b/macro/run/run_reco_digievent.C index f1963615b28ce0f0df9aa0b90794a34b4be07228..087f8848ae3e91668b1103136834a57910088afb 100644 --- a/macro/run/run_reco_digievent.C +++ b/macro/run/run_reco_digievent.C @@ -189,7 +189,7 @@ void run_reco_digievent(TString input = "", Int_t nTimeSlices = -1, Int_t firstT // ----- Local reconstruction in STS ---------------------------------- if (useSts) { - auto recoSts = std::make_unique<CbmRecoSts>(kCbmRecoEvent); + auto recoSts = std::make_unique<CbmRecoSts>(ECbmRecoMode::EventByEvent); std::cout << "-I- " << myName << ": Adding task " << recoSts->GetName(); run->AddTask(recoSts.release()); } diff --git a/macro/run/run_reco_yaml.C b/macro/run/run_reco_yaml.C new file mode 100644 index 0000000000000000000000000000000000000000..e6d404df3deee7595a0a2da6b7cf60c28dc6abde --- /dev/null +++ b/macro/run/run_reco_yaml.C @@ -0,0 +1,133 @@ +/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Volker Friese [committer], Dominik Smith */ + +/** @file run_reco_yaml.C + ** @author Volker Friese <v.friese@gsi.de> + ** @since 3 June 2023 + **/ + + +// --- Includes needed for IDE +#include <RtypesCore.h> +#if !defined(__CLING__) +#include <FairMonitor.h> +#include <FairSystemInfo.h> + +#include <TStopwatch.h> + +#include "reco/offline/steer/Run.h" +#endif + + +/** @brief Macro for CBM offline reconstruction, configured from YAML + ** @author Volker Friese <v.friese@gsi.de> + ** @since 3 June 2023 + ** @param input Name of input file (w/o extension .raw.root) + ** @param numTs Number of time-slices to process + ** @param config YAML configuration file + ** @param output Name of output file (w/o extension .rec.root) + ** @param setup Name of predefined geometry setup + ** @param paramFile Parameter ROOT file (w/o extension .par.root) + ** + ** This macro performs reconstruction from digis. It can be used + ** for simulated data (result of run_digi.C) or real data after unpacking. + ** + ** The macro covers both time-based reconstruction and event-based + ** reconstruction using raw events build from digis. + ** + ** The file names must be specified without extensions. The convention is + ** that the raw (input) file is [input].raw.root. The output file + ** will be [input].rec.root if not specified by the user. The parameter file + ** has the extension .par.root. It is assumed to be [input].par.root if + ** not specified by the user. + ** + ** If no argument is specified, the input will be set to "test". This allows + ** to execute the macro chain (run_tra_file.C, run_digi.C and run_reco_yaml.C) + ** from the ROOT prompt without user intervention. + ** + **/ +void run_reco_yaml(TString input = "", Int_t numTs = 0, TString config = "", TString output = "", + TString setup = "sis100_electron", TString paramFile = "") +{ + + // ----- Environment -------------------------------------------------- + TString myName = "run_reco_yaml"; // this macro's name for screen output + TString srcDir = gSystem->Getenv("VMCWORKDIR"); // top source directory + // ------------------------------------------------------------------------ + + + // ----- In- and output file names ------------------------------------ + if (input.IsNull()) input = "test"; + TString inFile = input + ".raw.root"; + if (output.IsNull()) output = input; + TString outFile = output + ".reco.root"; + TString monFile = output + ".moni_reco.root"; + if (paramFile.IsNull()) paramFile = input; + TString parFile = paramFile + ".par.root"; + std::cout << myName << ": Input file " << inFile << std::endl; + std::cout << myName << ": Output file " << outFile << std::endl; + std::cout << myName << ": Parameter file " << parFile << std::endl; + std::cout << myName << ": Configuration " << (config.IsNull() ? "default" : config); + std::cout << std::endl; + std::cout << myName << ": Geometry setup " << setup << std::endl; + std::cout << myName << ": Number of Ts "; + if (numTs == 0) std::cout << "max"; + else + std::cout << numTs; + std::cout << std::endl; + // ------------------------------------------------------------------------ + + + // ----- Configure run ------------------------------------------------ + // TODO: The run should created on the stack, but then there is a segmentation fault + // when destructing it at the end of the main function. This is caused by + // the destructor of CbmStsReco (StsHitfinderBase). Until this is resolved, + // the run is created on the heap. + std::cout << myName << ": Configuring run" << std::endl; + cbm::reco::offline::Run* run = new cbm::reco::offline::Run(); + run->SetInput(inFile.Data()); + run->SetOutput(outFile.Data()); + run->SetParams(parFile.Data()); + run->SetGeoSetupTag(setup.Data()); + run->SetNumTs(numTs); + run->LoadConfig(config.Data()); + // ------------------------------------------------------------------------ + + + // ----- Start run ---------------------------------------------------- + TStopwatch timer; + timer.Start(); + std::cout << myName << ": Starting run" << std::endl; + run->Exec(); + timer.Stop(); + // ------------------------------------------------------------------------ + + + // ----- Finish ------------------------------------------------------- + FairMonitor::GetMonitor()->Print(); + Double_t rtime = timer.RealTime(); + Double_t ctime = timer.CpuTime(); + std::cout << std::endl << std::endl; + std::cout << "Macro finished successfully." << std::endl; + std::cout << "Output file is " << outFile << std::endl; + std::cout << "Parameter file is " << parFile << std::endl; + std::cout << "Real time " << rtime << " s, CPU time " << ctime << " s" << std::endl; + FairSystemInfo sysInfo; + Float_t maxMemory = sysInfo.GetMaxMemory(); + std::cout << "<DartMeasurement name=\"MaxMemory\" type=\"numeric/double\">"; + std::cout << maxMemory; + std::cout << "</DartMeasurement>" << std::endl; + Float_t cpuUsage = ctime / rtime; + std::cout << "<DartMeasurement name=\"CpuLoad\" type=\"numeric/double\">"; + std::cout << cpuUsage; + std::cout << "</DartMeasurement>" << std::endl; + // ------------------------------------------------------------------------ + + + // ----- This is to prevent a malloc error when exiting ROOT ---------- + // The source of the error is unknown. Related to TGeoManager. + RemoveGeoManager(); + // ------------------------------------------------------------------------ + +} // End of main macro function diff --git a/reco/CMakeLists.txt b/reco/CMakeLists.txt index df891db26df4340d6de9713049871c353feec60a..6bcd5fd587f3d91485f9b88597118d9279539004 100644 --- a/reco/CMakeLists.txt +++ b/reco/CMakeLists.txt @@ -4,6 +4,8 @@ # set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address") # set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=address") +add_subdirectory(alignment) +add_subdirectory(app) add_subdirectory(base) add_subdirectory(calibration) add_subdirectory(detectors) @@ -12,12 +14,11 @@ add_subdirectory(global) add_subdirectory(KF) add_subdirectory(L1) add_subdirectory(littrack) +add_subdirectory(mq) +add_subdirectory(offline) +add_subdirectory(qa) add_subdirectory(steer) +add_subdirectory(tasks) add_subdirectory(tracking) -add_subdirectory(qa) -add_subdirectory (tasks) -add_subdirectory (app) -add_subdirectory (mq) -add_subdirectory (alignment) diff --git a/reco/detectors/sts/CbmRecoSts.cxx b/reco/detectors/sts/CbmRecoSts.cxx index 6ecf42a6f8b6f94735c6da42318b4d461f9140e2..39d76808a29fcbaddf2fbc974aa1c4d9b26146b5 100644 --- a/reco/detectors/sts/CbmRecoSts.cxx +++ b/reco/detectors/sts/CbmRecoSts.cxx @@ -229,7 +229,7 @@ void CbmRecoSts::Exec(Option_t*) // Old reco in time based mode } - else if (fMode == kCbmRecoTimeslice) { + else if (fMode == ECbmRecoMode::Timeslice) { ProcessData(nullptr); @@ -295,7 +295,7 @@ void CbmRecoSts::Finish() else LOG(info) << "STS reconstruction ran multithreaded with OpenMP (nthreads = " << ompThreads << ")"; LOG(info) << "Time slices : " << fNofTs; - if (fMode == kCbmRecoEvent) LOG(info) << "Events : " << fNofEvents; + if (fMode == ECbmRecoMode::EventByEvent) LOG(info) << "Events : " << fNofEvents; LOG(info) << "Digis / TSlice : " << fixed << setprecision(2) << fNofDigisRun / Double_t(fNofTs); LOG(info) << "Digis used / TSlice : " << fixed << setprecision(2) << fNofDigisUsed / Double_t(fNofTs); LOG(info) << "Digis ignored / TSlice : " << fixed << setprecision(2) << fNofDigisIgnored / Double_t(fNofTs); @@ -398,7 +398,7 @@ InitStatus CbmRecoSts::Init() fDigiManager->Init(); // --- In event mode: get input array (CbmEvent) - if (fMode == kCbmRecoEvent) { + if (fMode == ECbmRecoMode::EventByEvent) { LOG(info) << GetName() << ": Using event-by-event mode"; fEvents = dynamic_cast<TClonesArray*>(ioman->GetObject("CbmEvent")); if (nullptr == fEvents) { @@ -726,7 +726,8 @@ void CbmRecoSts::ProcessData(CbmEvent* event) void CbmRecoSts::ProcessDataGpu() { - if (fMode == kCbmRecoEvent) throw std::runtime_error("STS GPU Reco does not yet support event-by-event mode."); + if (fMode == ECbmRecoMode::EventByEvent) + throw std::runtime_error("STS GPU Reco does not yet support event-by-event mode."); auto digis = fDigiManager->GetArray<CbmStsDigi>(); fGpuReco(digis); diff --git a/reco/detectors/sts/CbmRecoSts.h b/reco/detectors/sts/CbmRecoSts.h index 9cfa4e017840463ff2c0f7a91ce5c815bd97f588..5650d3b43e30fc66bbbdada2e8bf24817fc543da 100644 --- a/reco/detectors/sts/CbmRecoSts.h +++ b/reco/detectors/sts/CbmRecoSts.h @@ -34,16 +34,6 @@ class CbmStsSensor; class CbmStsSetup; -/** @enum ECbmMode - ** @brief Time-slice or event-by-event mode - **/ -enum ECbmRecoMode -{ - kCbmRecoTimeslice, - kCbmRecoEvent -}; - - /** @class CbmRecoSts ** @brief Task class for local reconstruction in the STS ** @author Volker Friese <v.friese@gsi.de> @@ -65,7 +55,7 @@ class CbmRecoSts : public FairTask { public: /** @brief Constructor **/ - CbmRecoSts(ECbmRecoMode mode = kCbmRecoTimeslice, Bool_t writeClusters = kFALSE); + CbmRecoSts(ECbmRecoMode mode = ECbmRecoMode::Timeslice, Bool_t writeClusters = kFALSE); /** @brief Copy constructor (disabled) **/ @@ -106,7 +96,7 @@ public: ** ** Alternative to using SetMode. **/ - void SetEventMode(Bool_t choice = kTRUE) { fMode = (choice ? kCbmRecoEvent : kCbmRecoTimeslice); } + void SetEventMode(Bool_t choice = kTRUE) { fMode = (choice ? ECbmRecoMode::EventByEvent : ECbmRecoMode::Timeslice); } /** @brief Set execution mode @@ -286,12 +276,12 @@ private: CbmStsParSetSensorCond* fUserParSetCond = nullptr; // --- Settings - ECbmRecoMode fMode = kCbmRecoEvent; ///< Time-slice or event - Double_t fTimeCutDigisSig = 3.; ///< Time cut for cluster finding - Double_t fTimeCutDigisAbs = -1.; ///< Time cut for cluster finding [ns] - Double_t fTimeCutClustersSig = 4.; ///< Time cut for hit finding - Double_t fTimeCutClustersAbs = -1.; ///< Time cut for hit finding [ns] - Bool_t fWriteClusters = kFALSE; ///< Write clusters to tree + ECbmRecoMode fMode = ECbmRecoMode::Timeslice; ///< Time-slice or event-by-event + Double_t fTimeCutDigisSig = 3.; ///< Time cut for cluster finding + Double_t fTimeCutDigisAbs = -1.; ///< Time cut for cluster finding [ns] + Double_t fTimeCutClustersSig = 4.; ///< Time cut for hit finding + Double_t fTimeCutClustersAbs = -1.; ///< Time cut for hit finding [ns] + Bool_t fWriteClusters = kFALSE; ///< Write clusters to tree // --- Timeslice counters Long64_t fNofDigis = 0; ///< Total number of digis processed diff --git a/reco/detectors/sts/CbmRecoStsPixel.cxx b/reco/detectors/sts/CbmRecoStsPixel.cxx index ed19abb7a78989836faf32ed7417e09f81e70405..20cda9824995c14c9817d4e098e7a4b5c595374c 100644 --- a/reco/detectors/sts/CbmRecoStsPixel.cxx +++ b/reco/detectors/sts/CbmRecoStsPixel.cxx @@ -82,7 +82,7 @@ InitStatus CbmRecoStsPixel::Init() assert(ioman); // --- In event mode: get input array (CbmEvent) - if (fMode == kCbmRecoEvent) { + if (fMode == ECbmRecoMode::EventByEvent) { LOG(info) << GetName() << ": Using event-by-event mode"; fEvents = dynamic_cast<TClonesArray*>(ioman->GetObject("CbmEvent")); if (nullptr == fEvents) { @@ -180,7 +180,7 @@ void CbmRecoStsPixel::Exec(Option_t*) // --- Reset cluster output array fClusters->Delete(); - if (fMode == kCbmRecoTimeslice) { + if (fMode == ECbmRecoMode::Timeslice) { // --- Time-slice mode: process entire array ProcessData(nullptr); } diff --git a/reco/detectors/sts/CbmRecoStsPixel.h b/reco/detectors/sts/CbmRecoStsPixel.h index d450bd2020b96862a7b1075a7f8150c3aba9d7fa..582b3be3951837371f0193c8a78e497e2d617360 100644 --- a/reco/detectors/sts/CbmRecoStsPixel.h +++ b/reco/detectors/sts/CbmRecoStsPixel.h @@ -50,7 +50,7 @@ class CbmRecoStsPixel : public FairTask { public: /** @brief Constructor **/ - CbmRecoStsPixel(ECbmRecoMode mode = kCbmRecoTimeslice); + CbmRecoStsPixel(ECbmRecoMode mode = ECbmRecoMode::Timeslice); /** @brief Copy constructor (disabled) **/ @@ -87,7 +87,7 @@ public: ** ** Alternative to using SetMode. **/ - void SetEventMode(Bool_t choice = kTRUE) { fMode = (choice ? kCbmRecoEvent : kCbmRecoTimeslice); } + void SetEventMode(Bool_t choice = kTRUE) { fMode = (choice ? ECbmRecoMode::EventByEvent : ECbmRecoMode::Timeslice); } /** @brief Set execution mode @@ -129,7 +129,7 @@ private: // --- Settings - ECbmRecoMode fMode = kCbmRecoEvent; ///< Time-slice or event + ECbmRecoMode fMode = ECbmRecoMode::Timeslice; ///< Time-slice or event ClassDef(CbmRecoStsPixel, 0); }; diff --git a/reco/eventbuilder/digis/CbmAlgoBuildRawEvents.cxx b/reco/eventbuilder/digis/CbmAlgoBuildRawEvents.cxx index 8c4c4385af80ba8cf5ca145f3027f829c84d93de..dee887ec98544a97fcb10b9bda6accbb15fa5f52 100644 --- a/reco/eventbuilder/digis/CbmAlgoBuildRawEvents.cxx +++ b/reco/eventbuilder/digis/CbmAlgoBuildRawEvents.cxx @@ -340,6 +340,7 @@ void CbmAlgoBuildRawEvents::CheckSeed(Double_t dSeedTime, UInt_t uSeedDigiIdx) return; break; } + default: break; } } // if( prev Event exists and mode forbiden overlap present ) else { @@ -617,9 +618,9 @@ void CbmAlgoBuildRawEvents::SetBmonEventTime(CbmEvent* event) const int32_t iNbDigis = event->GetNofData(ECbmDataType::kT0Digi); if (0 < iNbDigis) { - uint idx = event->GetIndex(ECbmDataType::kT0Digi, 0); + uint idx = event->GetIndex(ECbmDataType::kT0Digi, 0); const CbmBmonDigi* pDigi = GetDigi<CbmBmonDigi>(idx); - double eventTime = pDigi->GetTime(); + double eventTime = pDigi->GetTime(); for (int idigi = 1; idigi < iNbDigis; ++idigi) { idx = event->GetIndex(ECbmDataType::kT0Digi, idigi); diff --git a/reco/eventbuilder/digis/CbmAlgoBuildRawEvents.h b/reco/eventbuilder/digis/CbmAlgoBuildRawEvents.h index 8a17452d69e293c71e861b904b18323ac0fe9cc6..f17e0ee2711b6843a4fb576dcd13a5c843a2e518 100644 --- a/reco/eventbuilder/digis/CbmAlgoBuildRawEvents.h +++ b/reco/eventbuilder/digis/CbmAlgoBuildRawEvents.h @@ -45,7 +45,8 @@ enum class EOverlapModeRaw { NoOverlap, MergeOverlap, - AllowOverlap + AllowOverlap, + Undefined }; class RawEventBuilderDetector { diff --git a/reco/offline/CMakeLists.txt b/reco/offline/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..e8e0d8791b26cadc89262afed0b105510f4a3680 --- /dev/null +++ b/reco/offline/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(app) +add_subdirectory(steer) diff --git a/reco/offline/app/Application.cxx b/reco/offline/app/Application.cxx new file mode 100644 index 0000000000000000000000000000000000000000..cc31543a139ccc28b4412c69d62582852c389d72 --- /dev/null +++ b/reco/offline/app/Application.cxx @@ -0,0 +1,46 @@ +/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Volker Friese [committer] */ + +/** @file Application.cxx + ** @author Volker Friese <v.friese@gsi.de> + ** @date 09.06.2023 + **/ + +#include "Application.h" + +#include "Config.h" + +using std::string; + +namespace cbm::reco::offline +{ + + // ----- Constructor ---------------------------------------------------- + Application::Application(ProgramOptions const& opt) : fOpt(opt) {} + // -------------------------------------------------------------------------- + + + // ----- Run the reconstruction ----------------------------------------- + void Application::Exec() + { + + // --- Use program options + fRun.SetInput(fOpt.InputFile().c_str()); + fRun.SetOutput(fOpt.OutputFile().c_str()); + fRun.SetParams(fOpt.ParamFile().c_str()); + fRun.SetGeoSetupTag(fOpt.SetupTag().c_str()); + fRun.SetNumTs(fOpt.MaxNumTs()); + if (fOpt.Overwrite()) fRun.AllowOverwrite(); + + // --- Read configuration from YAML file + cbm::reco::offline::Config config; + config.LoadYaml(fOpt.ConfigFile()); + fRun.SetConfig(config); + + // --- Execute reconstruction run + fRun.Exec(); + } + // -------------------------------------------------------------------------- + +} // namespace cbm::reco::offline diff --git a/reco/offline/app/Application.h b/reco/offline/app/Application.h new file mode 100644 index 0000000000000000000000000000000000000000..650a74327df7a0b37fe206869d8ad89c005c2fd3 --- /dev/null +++ b/reco/offline/app/Application.h @@ -0,0 +1,54 @@ +/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Volker Friese [committer] */ + +/** @file Application.h + ** @author Volker Friese <v.friese@gsi.de> + ** @date 09.06.2023 + **/ + + +#ifndef CBM_RECO_OFFLINE_APP_APPLICATION_H +#define CBM_RECO_OFFLINE_APP_APPLICATION 1 + +#include "ProgramOptions.h" +#include "Run.h" + +namespace cbm::reco::offline +{ + + class Application { + + + public: + /** @brief Standard constructor, initialises the application + ** @param opt **/ + explicit Application(ProgramOptions const& opt); + + /** @brief Copy constructor forbidden **/ + Application(const Application&) = delete; + + /** @brief Assignment operator forbidden **/ + void operator=(const Application&) = delete; + + /** @brief Destructor **/ + ~Application() = default; + + /** @brief Run the application **/ + void Exec(); + + private: + const std::string& OutputFile() const; + const std::string& ParamFile() const; + const std::string& SetupTag() const; + const std::string& ConfigFile() const; + + + private: + ProgramOptions const& fOpt; ///< Program options object + Run fRun = {}; ///< Reconstruction run + }; + +} // namespace cbm::reco::offline + +#endif /* CBM_RECO_OFFLINE_APP_APPLICATION */ diff --git a/reco/offline/app/CMakeLists.txt b/reco/offline/app/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..feb7930a49e623365e9f5c262f67cbb64d72e100 --- /dev/null +++ b/reco/offline/app/CMakeLists.txt @@ -0,0 +1,25 @@ +# CMakeList file for binary cbmreco_offline +# V. Friese, 13 May 2023 + +set(SRCS + Application.cxx + ProgramOptions.cxx + main.cxx + ) + +set(HEADERS + Application.h + ProgramOptions.h + ) + + +add_executable(cbmreco_offline ${SRCS} ${HEADERS}) + +target_link_libraries(cbmreco_offline + PUBLIC + CbmRecoOfflineSteer + PRIVATE + Boost::program_options + ) + +install(TARGETS cbmreco_offline DESTINATION bin) diff --git a/reco/offline/app/ProgramOptions.cxx b/reco/offline/app/ProgramOptions.cxx new file mode 100644 index 0000000000000000000000000000000000000000..1b9740bd8ddc56220b5b52eba7dd4d69166bda7b --- /dev/null +++ b/reco/offline/app/ProgramOptions.cxx @@ -0,0 +1,79 @@ +/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Volker Friese [committer] */ + +/** @file ProgramOptions.cxx + ** @author Volker Friese <v.friese@gsi.de> + ** @date 09.06.2023 + ** + ** Code taken from reco/app/cbmreco_fairrun/ProgramOptions.cxx (J. de Cuveland) + **/ + +#include "ProgramOptions.h" + +#include <Logger.h> + +#include <boost/program_options.hpp> + +#include <iostream> + +namespace po = boost::program_options; + +using std::string; + +namespace cbm::reco::offline +{ + + // ----- Parse command line --------------------------------------------- + void ProgramOptions::ParseOptions(int argc, char* argv[]) + { + + // --- Define generic options + po::options_description generic("Generic options"); + auto generic_add = generic.add_options(); + generic_add("help,h", "display this help and exit"); + + // --- Define configuration options + string defconfig = std::getenv("VMCWORKDIR"); + defconfig.append("/"); + defconfig.append(DEFAULT_CONFIG); + po::options_description config("Configuration"); + auto config_add = config.add_options(); + config_add("input,i", po::value<string>(&fInput)->value_name("<file name>"), + "name of the input ROOT file containing digi data"); + config_add("output,o", po::value<string>(&fOutput)->value_name("<file name>"), + "name of the output ROOT file with reconstructed data"); + config_add("params,p", po::value<string>(&fParam)->value_name("<file name>"), + "name of a parameter ROOT file (FairRuntimeDb format)"); + config_add("config,c", po::value<string>(&fConfig)->value_name("<file name>")->default_value(defconfig), + "name of a YAML file describing the configuration of reconstruction"); + config_add("setup,s", po::value<string>(&fSetup)->value_name("<tag>")->default_value(DEFAULT_SETUP), + "geometry setup tag"); + config_add("max-timeslice-number,n", po::value<int32_t>(&fMaxNumTs)->value_name("<n>")->default_value(INT32_MAX), + "maximum number of timeslices to process (default: all in input file)"); + config_add("overwrite,w", po::bool_switch(&fOverwrite)->default_value(false), + "allow to overwite an existing output file"); + + // --- Allowed options + po::options_description cmdline_options("Allowed options"); + cmdline_options.add(generic).add(config); + + // --- Parse command line + po::variables_map vars; + po::store(po::parse_command_line(argc, argv, cmdline_options), vars); + po::notify(vars); + + // --- Help: print help information and exit program + if (vars.count("help") != 0u) { + std::cout << cmdline_options << std::endl; + exit(EXIT_SUCCESS); + } + + // --- Catch mandatory parameters not being specified + if (vars.count("input") == 0u) { throw std::runtime_error("no input file name specified"); } + if (vars.count("output") == 0u) { throw std::runtime_error("no output file name specified"); } + if (vars.count("params") == 0u) { throw std::runtime_error("no parameter file name specified"); } + } + // -------------------------------------------------------------------------- + +} // namespace cbm::reco::offline diff --git a/reco/offline/app/ProgramOptions.h b/reco/offline/app/ProgramOptions.h new file mode 100644 index 0000000000000000000000000000000000000000..cb5bdbda5d5d5146800a203b49959c6bc5889f64 --- /dev/null +++ b/reco/offline/app/ProgramOptions.h @@ -0,0 +1,83 @@ +/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Volker Friese [committer], Jan de Cuveland */ + +/** @file ProgramOptions.h + ** @author Volker Friese <v.friese@gsi.de> + ** @date 09.06.2023 + ** + ** Code taken from reco/app/cbmreco_fairrun/ProgramOptions.h (J. de Cuveland) + **/ + +#ifndef CBM_RECO_OFFLINE_APP_PROGRAMOPTIONS_H +#define CBM_RECO_OFFLINE_APP_PROGRAMOPTIONS_H 1 + +#define DEFAULT_CONFIG "reco/offline/config/RecoConfig_event_ideal.yaml" +#define DEFAULT_SETUP "sis100_electron" + + +#include <string> + +namespace cbm::reco::offline +{ + + /** @class ProgramOptions + ** @author Volker Friese <v.friese@gsi.de> + ** @since 9 June 2023 + ** + ** Program option class for the application cbmreco_offline + **/ + class ProgramOptions { + public: + /** @brief Standard constructor with command line arguments **/ + ProgramOptions(int argc, char* argv[]) { ParseOptions(argc, argv); } + + /** @brief Copy constructor forbidden **/ + ProgramOptions(const ProgramOptions&) = delete; + + /** @brief Assignment operator forbidden **/ + ProgramOptions& operator=(const ProgramOptions&) = delete; + + /** @brief Destructor **/ + ~ProgramOptions() = default; + + /** @brief Get input file name **/ + [[nodiscard]] const std::string& InputFile() const { return fInput; } + + /** @brief Get output file name (.root format) **/ + [[nodiscard]] const std::string& OutputFile() const { return fOutput; } + + /** @brief Get configuration file name (YAML format) **/ + [[nodiscard]] const std::string& ConfigFile() const { return fConfig; } + + /** @brief Get overwrite option **/ + [[nodiscard]] bool Overwrite() const { return fOverwrite; } + + /** @brief Get parameter file name **/ + [[nodiscard]] const std::string& ParamFile() const { return fParam; } + + /** @brief Get geometry setup tag **/ + [[nodiscard]] const std::string& SetupTag() const { return fSetup; } + + /** @brief Get maximum number of timeslices to process **/ + [[nodiscard]] int32_t MaxNumTs() const { return fMaxNumTs; } + + + private: + /** @brief Parse command line arguments using boost program_options **/ + void ParseOptions(int argc, char* argv[]); + + + private: // members + std::string fInput = ""; ///< Input file name (ROOT format) + std::string fOutput = ""; ///< Output file name (ROOT format) + std::string fParam = ""; ///< Parameter file name (ROOT format) + std::string fConfig = ""; ///< Configuration file name (YAML format) + std::string fSetup = ""; ///< Geometry setup tag + int32_t fMaxNumTs = INT32_MAX; ///< Maximum number of timeslices to process + bool fOverwrite = false; ///< Enable overwriting of existing output file + }; + +} // namespace cbm::reco::offline + +#endif /* CBM_RECO_OFFLINE_APP_PROGRAMOPTIONS_H */ diff --git a/reco/offline/app/main.cxx b/reco/offline/app/main.cxx new file mode 100644 index 0000000000000000000000000000000000000000..e80051dee517ff5cd1ae9e535e0153942244661e --- /dev/null +++ b/reco/offline/app/main.cxx @@ -0,0 +1,26 @@ +/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Volker Friese [committer], Jan de Cuveland */ +#include <Logger.h> + +#include "Application.h" +#include "ProgramOptions.h" + +using namespace cbm::reco::offline; + +int main(int argc, char* argv[]) +{ + LOG(info) << "***** CBM Offline Reconstruction *****"; + try { + ProgramOptions opt(argc, argv); + Application app(opt); + app.Exec(); + } + catch (std::exception const& e) { + LOG(error) << e.what() << "; terminating."; + return EXIT_FAILURE; + } + + LOG(info) << "CBM Offline Reconstruction: Program completed successfully; exiting."; + return EXIT_SUCCESS; +} diff --git a/reco/offline/config/RecoConfig_event_ideal.yaml b/reco/offline/config/RecoConfig_event_ideal.yaml new file mode 100644 index 0000000000000000000000000000000000000000..28c0cd9378c4dec38a9a9d7fbd80b61fae49404b --- /dev/null +++ b/reco/offline/config/RecoConfig_event_ideal.yaml @@ -0,0 +1,19 @@ +global: + log_level: INFO + log_verbose: LOW + mode: event +evbuild: + type: ideal + overlap: allow + triggerDetector: sts + minNumDigis: 1000 + maxNumDigis: -1 + trigWinMin: -500 + trigWinMax: 500 +sts: + usegpu: false +trd: + trigThresh: 0.5e-6 +littrack: + trackingType: branch + mergingType: nearest_hit diff --git a/reco/offline/config/RecoConfig_event_real.yaml b/reco/offline/config/RecoConfig_event_real.yaml new file mode 100644 index 0000000000000000000000000000000000000000..b98ef71727ded07ce2f7cf2b4d18ddc227cad30f --- /dev/null +++ b/reco/offline/config/RecoConfig_event_real.yaml @@ -0,0 +1,19 @@ +global: + log_level: INFO + log_verbose: LOW + mode: event +evbuild: + type: real + overlap: allow + triggerDetector: sts + minNumDigis: 1000 + maxNumDigis: -1 + trigWinMin: -500 + trigWinMax: 500 +sts: + usegpu: false +trd: + trigThresh: 0.5e-6 +littrack: + trackingType: branch + mergingType: nearest_hit diff --git a/reco/offline/config/RecoConfig_timeslice.yaml b/reco/offline/config/RecoConfig_timeslice.yaml new file mode 100644 index 0000000000000000000000000000000000000000..890a9751f5c18ad41d70ab8e666103f0a6602b3f --- /dev/null +++ b/reco/offline/config/RecoConfig_timeslice.yaml @@ -0,0 +1,19 @@ +global: + log_level: INFO + log_verbose: LOW + mode: timeslice +evbuild: + type: ideal + overlap: allow + triggerDetector: sts + minNumDigis: 1000 + maxNumDigis: -1 + trigWinMin: -500 + trigWinMax: 500 +sts: + usegpu: false +trd: + trigThresh: 0.5e-6 +littrack: + trackingType: branch + mergingType: nearest_hit diff --git a/reco/offline/steer/CMakeLists.txt b/reco/offline/steer/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..597907cb4e5f87e1d10b4cec9d165db90d72a9ad --- /dev/null +++ b/reco/offline/steer/CMakeLists.txt @@ -0,0 +1,69 @@ +# CMakeList file for library libCbmRecoOfflineSteer +# V. Friese, 13 May 2023 + + +set(SRCS + Config.cxx + Run.cxx + TaskFactory.cxx + ) + +set(INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}) + +if(OpenMP_CXX_FOUND) + list(APPEND DEPENDENCIES OpenMP::OpenMP_CXX) +endif() + + +set(LIBRARY_NAME CbmRecoOfflineSteer) +set(LINKDEF RootLinkDef.h) +set(PUBLIC_DEPENDENCIES + CbmData + FairRoot::Base + ROOT::Core + external::yaml-cpp + CbmEventBuilder + ) + +set(PRIVATE_DEPENDENCIES + CbmBase + CbmTrdBase + FairLogger::FairLogger + FairRoot::Online + ROOT::Hist + ROOT::RHTTP + CbmGlobal + CbmRichBase + CbmTofBase + CbmMuchReco + CbmMvdReco + CbmRichReco + CbmRecoSts + CbmTofReco + CbmTrdReco + CbmSimSteer + L1 + Algo + ) + +# Check if the compiler supports std::execution in the respective STL +# library +CHECK_CXX_SOURCE_COMPILES(" +#include <numeric> +#include <vector> +#include <execution> + +int main(int argc, char *argv[]) +{ + std::vector<double> v(10, 1); + + auto result = std::reduce(std::execution::par, v.begin(), v.end()); + return 0; +}" HAS_STD_EXECUTION) + +if (HAS_STD_EXECUTION) + message("Execution is available in STL") + add_definitions(-DWITH_EXECUTION) +endif() + +generate_cbm_library() diff --git a/reco/offline/steer/Config.cxx b/reco/offline/steer/Config.cxx new file mode 100644 index 0000000000000000000000000000000000000000..82aa9cc6b47eecc14ae319481c2be410fc680540 --- /dev/null +++ b/reco/offline/steer/Config.cxx @@ -0,0 +1,174 @@ +/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Volker Friese [committer] */ + +/** @file .cxx + ** @author Volker Friese <v.friese@gsi.de> + ** @date 31.05.2023 + **/ + + +#include "Config.h" + +#include <Logger.h> + +#include <fstream> + +#include <yaml-cpp/yaml.h> + +using std::string; + +namespace cbm::reco::offline +{ + + + // ----- Load settings from YAML file ------------------------------------- + void Config::LoadYaml(const string& fileName) + { + + LOG(info) << "Config: Reading configuration from " << fileName; + YAML::Node settings = YAML::LoadFile(fileName); + + // --- Global settings + f_glb_logLevel = settings["global"]["log_level"].as<string>(); + f_glb_logVerbose = settings["global"]["log_verbose"].as<string>(); + f_glb_mode = ToCbmRecoMode(settings["global"]["mode"].as<string>()); + + // --- Event builder + f_evbuild_type = ToCbmEvbuildType(settings["evbuild"]["type"].as<string>()); + f_evbuild_ovlapmode = ToOverlapModeRaw(settings["evbuild"]["overlap"].as<string>()); + f_evbuild_trigDet = ToCbmModuleIdCaseInsensitive(settings["evbuild"]["triggerDetector"].as<string>()); + f_evbuild_trigNumMin = settings["evbuild"]["minNumDigis"].as<int64_t>(); + f_evbuild_trigNumMax = settings["evbuild"]["maxNumDigis"].as<int64_t>(); + f_evbuild_trigWinMin = settings["evbuild"]["trigWinMin"].as<float>(); + f_evbuild_trigWinMax = settings["evbuild"]["trigWinMax"].as<float>(); + + // --- STS + f_sts_usegpu = settings["sts"]["usegpu"].as<bool>(); + + // --- TRD + f_trd_trigThresh = settings["trd"]["trigThresh"].as<double>(); + + // --- littrack + f_lit_trackType = settings["littrack"]["trackingType"].as<string>(); + f_lit_mergeType = settings["littrack"]["mergingType"].as<string>(); + } + // ---------------------------------------------------------------------------- + + + // ------ String to ECbmEvbuildType --------------------------------------- + ECbmEvbuildType Config::ToCbmEvbuildType(string choice) + { + string temp = choice; + std::transform(temp.begin(), temp.end(), temp.begin(), [](unsigned char c) { return std::tolower(c); }); + if (temp == "ideal") return ECbmEvbuildType::Ideal; + else if (temp == "real") + return ECbmEvbuildType::Real; + else + return ECbmEvbuildType::Undefined; + } + // ---------------------------------------------------------------------------- + + + // ------ String to ECbmRecoMode ------------------------------------------ + ECbmRecoMode Config::ToCbmRecoMode(string choice) + { + string temp = choice; + std::transform(temp.begin(), temp.end(), temp.begin(), [](unsigned char c) { return std::tolower(c); }); + if (temp == "timeslice") return ECbmRecoMode::Timeslice; + else if (temp == "event") + return ECbmRecoMode::EventByEvent; + else + return ECbmRecoMode::Undefined; + } + // ---------------------------------------------------------------------------- + + + // ------ String to EOverlapModeRaw --------------------------------------- + EOverlapModeRaw Config::ToOverlapModeRaw(string choice) + { + string temp = choice; + std::transform(temp.begin(), temp.end(), temp.begin(), [](unsigned char c) { return std::tolower(c); }); + if (temp == "no") return EOverlapModeRaw::NoOverlap; + else if (temp == "allow") + return EOverlapModeRaw::AllowOverlap; + else if (temp == "merge") + return EOverlapModeRaw::MergeOverlap; + else + return EOverlapModeRaw::Undefined; + } + // ---------------------------------------------------------------------------- + + + // ----- ECbmEvbuildType to string ---------------------------------------- + string Config::ToString(ECbmEvbuildType type) + { + if (type == ECbmEvbuildType::Ideal) return "ideal"; + else if (type == ECbmEvbuildType::Real) + return "real"; + else + return "undefined"; + } + // ---------------------------------------------------------------------------- + + + // ----- ECbmRecoMode to string ------------------------------------------- + string Config::ToString(ECbmRecoMode mode) + { + if (mode == ECbmRecoMode::Timeslice) return "timeslice"; + else if (mode == ECbmRecoMode::EventByEvent) + return "event"; + else + return "undefined"; + } + // ---------------------------------------------------------------------------- + + + // ----- EOverlapMode to string ------------------------------------------- + string Config::ToString(EOverlapModeRaw mode) + { + if (mode == EOverlapModeRaw::NoOverlap) return "no"; + else if (mode == EOverlapModeRaw::AllowOverlap) + return "allow"; + else if (mode == EOverlapModeRaw::MergeOverlap) + return "merge"; + else + return "undefined"; + } + // ---------------------------------------------------------------------------- + + + // ----- Save settings to YAML node --------------------------------------- + YAML::Node Config::ToYaml() + { + YAML::Node settings; + + // --- Global settings + settings["global"]["log_level"] = f_glb_logLevel; + settings["global"]["log_verbose"] = f_glb_logVerbose; + settings["global"]["mode"] = ToString(f_glb_mode); + + // --- Event builder + settings["evbuild"]["type"] = ToString(f_evbuild_type); + settings["evbuild"]["overlap"] = ToString(f_evbuild_ovlapmode); + settings["evbuild"]["triggerDetector"] = ::ToString(f_evbuild_trigDet); + settings["evbuild"]["minNumDigis"] = f_evbuild_trigNumMin; + settings["evbuild"]["maxNumDigis"] = f_evbuild_trigNumMax; + settings["evbuild"]["trigWinMin"] = f_evbuild_trigWinMin; + settings["evbuild"]["trigWinMax"] = f_evbuild_trigWinMax; + + // --- STS + settings["sts"]["usegpu"] = f_sts_usegpu; + + // --- TRD + settings["trd"]["trigThresh"] = f_trd_trigThresh; + + // --- littrack + settings["littrack"]["trackingType"] = f_lit_trackType; + settings["littrack"]["mergingType"] = f_lit_mergeType; + + return settings; + } + // ---------------------------------------------------------------------------- + +} // namespace cbm::reco::offline diff --git a/reco/offline/steer/Config.h b/reco/offline/steer/Config.h new file mode 100644 index 0000000000000000000000000000000000000000..a013033884705ad6b042d7e6886a9a8888a86026 --- /dev/null +++ b/reco/offline/steer/Config.h @@ -0,0 +1,117 @@ +/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Volker Friese [committer] */ + +/** @file Config.h + ** @author Volker Friese <v.friese@gsi.de> + ** @date 31.05.2023 + **/ + +#ifndef CBM_RECO_OFFLINE_STEER_CONFIG_H +#define CBM_RECO_OFFLINE_STEER_CONFIG_H 1 + +#include "CbmAlgoBuildRawEvents.h" +#include "CbmDefs.h" + +#include <array> +#include <fstream> +#include <sstream> +#include <string> + +#include <yaml-cpp/yaml.h> + +namespace cbm::reco::offline +{ + + enum class ECbmEvbuildType + { + Ideal, + Real, + Undefined + }; + + + /** @class Config + ** @author Volker Friese <v.friese@gsi.de> + ** @date 31.05.2023 + ** + ** Configuration for the offline reconstruction chain, replacing run_reco.C. + ** With interfaces to YAML. + **/ + class Config { + public: + /** @brief Constructor **/ + Config() = default; + + + /** @brief Destructor **/ + virtual ~Config() = default; + + + /** @brief Load from YAML file + ** @param filename Name of input YAML file + **/ + void LoadYaml(const std::string& filename); + + + /** @brief String output (YAML format) **/ + std::string ToString() + { + std::stringstream out; + out << ToYaml(); + return out.str(); + } + + + /** @brief Save to YAML file + ** @param filename Name of output YAML file + **/ + void SaveYaml(const std::string& filename) + { + std::ofstream fout(filename); + fout << ToYaml(); + } + + + private: + ECbmEvbuildType ToCbmEvbuildType(std::string tag); + ECbmRecoMode ToCbmRecoMode(std::string tag); + EOverlapModeRaw ToOverlapModeRaw(std::string tag); + std::string ToString(ECbmEvbuildType type); + std::string ToString(ECbmRecoMode mode); + std::string ToString(EOverlapModeRaw mode); + + /** @brief Save to YAML node **/ + YAML::Node ToYaml(); + + + public: + // --- Global settings + std::string f_glb_logLevel = "INFO"; + std::string f_glb_logVerbose = "LOW"; + ECbmRecoMode f_glb_mode = ECbmRecoMode::Undefined; + + // --- Event builder + ECbmEvbuildType f_evbuild_type = ECbmEvbuildType::Undefined; + EOverlapModeRaw f_evbuild_ovlapmode = EOverlapModeRaw::Undefined; + ECbmModuleId f_evbuild_trigDet = ECbmModuleId::kNotExist; + int64_t f_evbuild_trigNumMin = 0; + int64_t f_evbuild_trigNumMax = 0; + float f_evbuild_trigWinMin = std::nanf("undefined"); + float f_evbuild_trigWinMax = std::nanf("undefined"); + + // --- STS + bool f_sts_usegpu = false; + + // --- TRD + float f_trd_trigThresh = std::nanf("undefined"); + + // --- littrack + std::string f_lit_trackType = ""; + std::string f_lit_mergeType = ""; + }; + +} // namespace cbm::reco::offline + + +#endif /* CBM_RECO_OFFLINE_STEER_CONFIG_H */ diff --git a/reco/offline/steer/RootLinkDef.h b/reco/offline/steer/RootLinkDef.h new file mode 100644 index 0000000000000000000000000000000000000000..b0bb83217633e362d13c52a5731a35d8f60305d9 --- /dev/null +++ b/reco/offline/steer/RootLinkDef.h @@ -0,0 +1,17 @@ +/* Copyright (C) 2021 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Volker Friese [committer] */ + +// ===== LinkDef for reco/task ===== + +#ifdef __CINT__ + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; + +// --- Classes +#pragma link C++ class cbm::reco::offline::Run + ; + + +#endif /* __CINT__ */ diff --git a/reco/offline/steer/Run.cxx b/reco/offline/steer/Run.cxx new file mode 100644 index 0000000000000000000000000000000000000000..c11b30b037fa69bac728e3fcd5acdafec53ed1b6 --- /dev/null +++ b/reco/offline/steer/Run.cxx @@ -0,0 +1,234 @@ +/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Volker Friese [committer], Florian Uhlig */ + +/** @file Run.cxx + ** @author Volker Friese <v.friese@gsi.de> + ** @date 18.05.2018 + **/ + +#include "Run.h" + +#include "CbmSetup.h" + +#include <FairEventHeader.h> +#include <FairFileSource.h> +#include <FairMonitor.h> +#include <FairParRootFileIo.h> +#include <FairRootFileSink.h> +#include <FairRunAna.h> +#include <FairRuntimeDb.h> +#include <FairTask.h> +#include <Logger.h> + +#include "TaskFactory.h" +#include <TFile.h> +#include <TGeoManager.h> +#include <TStopwatch.h> +#include <TString.h> +#include <TTree.h> + +#include <cassert> +#include <iostream> + +#include <sys/stat.h> + +namespace cbm::reco::offline +{ + + + // ----- Constructor ---------------------------------------------------- + Run::Run() : TNamed("Run", "CBM Reconstruction Run") {} + // -------------------------------------------------------------------------- + + + // ----- Destructor ----------------------------------------------------- + Run::~Run() { LOG(debug) << "Destructing " << fName; } + // -------------------------------------------------------------------------- + + + // ----- Add a reconstruction task -------------------------------------- + void Run::AddTask(FairTask* task) + { + fRun.AddTask(task); + LOG(info) << GetName() << ": Added task " << task->GetName(); + } + // -------------------------------------------------------------------------- + + + // ----- Check a digi branch -------------------------------------------- + void Run::CheckDigiBranch(TTree* tree, ECbmModuleId detector) + { + TString branchName = ToString(detector); + branchName += "Digi"; + if (tree->GetBranchStatus(branchName.Data())) { + LOG(info) << GetName() << ": Found branch " << branchName; + fDataPresent.insert(detector); + } + } + // -------------------------------------------------------------------------- + + + // ----- Check existence of a file -------------------------------------- + bool Run::CheckFile(const char* fileName) + { + struct stat buffer; + return (stat(fileName, &buffer) == 0); + } + // -------------------------------------------------------------------------- + + + // ----- Check which input digi branches are present -------------------- + void Run::CheckInputBranches(FairFileSource* source) + { + + TFile* inFile = source->GetInFile(); + if (!inFile) throw std::runtime_error("No input file"); + TTree* inTree = dynamic_cast<TTree*>(inFile->Get("cbmsim")); + if (!inTree) throw std::runtime_error("No input tree"); + + for (ECbmModuleId detector = ECbmModuleId::kMvd; detector != ECbmModuleId::kNofSystems; ++detector) + CheckDigiBranch(inTree, detector); + } + // -------------------------------------------------------------------------- + + + // ----- Create the topology -------------------------------------------- + void Run::CreateTopology() + { + + TaskFactory fact(this); + + // --- Timeslice processing + if (fConfig.f_glb_mode == ECbmRecoMode::Timeslice) { + fact.RegisterStsReco(); // Local reconstruction in STS + fact.RegisterRichHitFinder(); // Hit finding in RICH + fact.RegisterMuchReco(); // Local reconstruction in MUCH + fact.RegisterTrdReco(); // Local reconstruction in TRD + fact.RegisterTofReco(); // Local reconstruction in TOF + fact.RegisterCaTracking(); // CA track finder in STS and MVD + fact.RegisterTrackEventBuilder(); // Event building from STS tracks + } + + // --- Event-by-event processing + else if (fConfig.f_glb_mode == ECbmRecoMode::EventByEvent) { + fact.RegisterDigiEventBuilder(); // Event building from digis + fact.RegisterMvdReco(); // Local reconstruction in MVD + fact.RegisterStsReco(); // Local reconstruction in STS + fact.RegisterRichHitFinder(); // Hit finding in RICH + fact.RegisterMuchReco(); // Local reconstruction in MUCH + fact.RegisterTrdReco(); // Local reconstruction in TRD + fact.RegisterTofReco(); // Local reconstruction in TOF + fact.RegisterCaTracking(); // CA track finder in STS and MVD + fact.RegisterPvFinder(); // Primary vertex finding + fact.RegisterGlobalTracking(); // Global tracking + fact.RegisterTrdPid(); // PID in TRD + fact.RegisterRichReco(); // Local RICH reconstruction + fact.RegisterTzeroReco(); // Reconstruction of T0 from BMON + } + + // --- Mode not defined + else + throw std::out_of_range("Reconstruction mode not defined"); + } + // -------------------------------------------------------------------------- + + + // ----- Execute reconstruction run ------------------------------------- + void Run::Exec() + { + + // --- Mirror options and configuration + LOG(info) << GetName() << ": Input file is " << fInput; + LOG(info) << GetName() << ": Parameter file is " << fParams; + LOG(info) << GetName() << ": Output file is " << fOutput; + LOG(info) << GetName() << ": Geometry setup is " << fSetupTag; + LOG(info) << "Configuration: \n" << fConfig.ToString(); + + // --- Timer + TStopwatch timer; + timer.Start(); + + // --- Run info + fRun.SetGenerateRunInfo(true); + + // --- Check input, output and parameter files + if (!CheckFile(fInput.Data())) throw std::runtime_error("Input file does not exist"); + if (!CheckFile(fParams.Data())) throw std::runtime_error("Parameter file does not exist"); + if (CheckFile(fOutput.Data()) && !fOverwrite) throw std::runtime_error("Output file already exists"); + + // --- Input and output + FairFileSource* source = new FairFileSource(fInput); + fRun.SetSource(source); + fRun.SetSink(new FairRootFileSink(fOutput)); + + // --- Check presence of input (digi) branches + LOG(info) << GetName() << ": Checking digi input..."; + CheckInputBranches(source); + + // --- Geometry setup + LOG(info) << GetName() << ": Loading setup " << fSetupTag; + fSetup = CbmSetup::Instance(); + fSetup->LoadSetup(fSetupTag); + // TODO: This CbmSetup business with singleton is not nice. Should be replaced eventually. + + // --- Topology + LOG(info) << GetName() << ": Creating topology..."; + CreateTopology(); + + // --- Parameter database + LOG(info) << GetName() << ": Set runtime DB..."; + FairRuntimeDb* rtdb = fRun.GetRuntimeDb(); + FairParRootFileIo* parIo1 = new FairParRootFileIo(); + parIo1->open(fParams.Data(), "UPDATE"); + rtdb->setFirstInput(parIo1); + + // --- Initialisation + LOG(info) << GetName() << ": Initialise FairRun..." << std::endl; + fRun.Init(); + rtdb->setOutput(parIo1); + rtdb->saveOutput(); + rtdb->print(); + timer.Stop(); + double timeInit = timer.RealTime(); + timer.Start(); + + // TODO: Register light ions (see run_reco.C). But what for? + + // --- Execute run + std::cout << std::endl << std::endl; + LOG(info) << GetName() << ": Starting run" << std::endl; + fRun.Run(fNumTs, 0); + + // --- Finish + timer.Stop(); + double timeExec = timer.RealTime(); + FairMonitor::GetMonitor()->Print(); + std::cout << std::endl << std::endl; + LOG(info) << GetName() << ": Execution successful"; + LOG(info) << GetName() << ": Input file was " << fInput; + LOG(info) << GetName() << ": Parameter file is " << fParams; + LOG(info) << GetName() << ": Output file is " << fOutput; + LOG(info) << GetName() << ": Execution time: Init " << timeInit << " s, Exec " << timeExec << "s"; + } + // -------------------------------------------------------------------------- + + + // ----- Read configuration from YAML file ------------------------------- + void Run::LoadConfig(const char* fileName) + { + + TString file(fileName); + if (file.IsNull()) { + file = std::getenv("VMCWORKDIR"); + file += "/reco/offline/config/RecoConfig_event_ideal.yaml"; + } + LOG(info) << GetName() << ": Loading configuration from " << file; + fConfig.LoadYaml(file.Data()); + } + // -------------------------------------------------------------------------- + + +} // namespace cbm::reco::offline + +ClassImp(cbm::reco::offline::Run) diff --git a/reco/offline/steer/Run.h b/reco/offline/steer/Run.h new file mode 100644 index 0000000000000000000000000000000000000000..6c819ad499ffc330ce2136a7196823c5d019b173 --- /dev/null +++ b/reco/offline/steer/Run.h @@ -0,0 +1,160 @@ +/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Volker Friese [committer] */ + +/** @file Run.h + ** @author Volker Friese <v.friese@gsi.de> + ** @date 12.05.2023 + **/ + +#ifndef CBM_RECO_OFFLINE_STEER_RUN_H +#define CBM_RECO_OFFLINE_STEER_RUN_H 1 + +#include "CbmDefs.h" + +#include <FairRunAna.h> + +#include <TNamed.h> +#include <TTree.h> + +#include <string> + +#include "Config.h" + +class TGeoManager; +class CbmSetup; +class FairTask; + +namespace cbm::reco::offline +{ + + class Run : public TNamed { + + public: + /** @brief Constructor **/ + Run(); + + + /** @brief Destructor **/ + virtual ~Run(); + + + /** @brief Add a task to the run **/ + void AddTask(FairTask* task); + + + /** @brief Allow overwriting if output file already exists **/ + void AllowOverwrite() { fOverwrite = true; } + + + /** @brief Run reconstruction **/ + void Exec(); + + + /** @brief Settings object **/ + const Config& GetConfig() const { return fConfig; } + + + /** @brief Presence of input digi data + ** @param detector Detector data to check + ** @return true if data present, else false + **/ + bool IsDataPresent(ECbmModuleId detector) const { return (fDataPresent.count(detector) == 0 ? false : true); } + + + /** @brief Set configuration file name + ** @param fileName Configuration file name + ** + ** Legacy interface for running from ROOT prompt. In the executable, the config is read in + ** by the application. + **/ + void LoadConfig(const char* fileName); + + + /** @brief Set configuration + ** @param fileName Configuration object + **/ + void SetConfig(const Config& config) { fConfig = config; } + + + /** @brief Set geometry setup tag + ** @param tag Geometry setup tag + **/ + void SetGeoSetupTag(const char* tag) { fSetupTag = tag; } + + + /** @brief Set input file name + ** @param fileName Input file name + **/ + void SetInput(const char* fileName) { fInput = fileName; } + + + /** @brief Set number of timeslices to process + ** @param numTs Number of timeslice to process + **/ + void SetNumTs(int32_t num) { fNumTs = num; } + + + /** @brief Set output file name + ** @param fileName Output file name + **/ + void SetOutput(const char* fileName) { fOutput = fileName; } + + + /** @brief Set parameter file name + ** @param fileName Parameter file name + **/ + void SetParams(const char* fileName) { fParams = fileName; } + + + private: + /** @brief Copy constructor forbidden **/ + Run(const Run&) = delete; + + + /** @brief Assignment operator forbidden **/ + Run operator=(const Run&) = delete; + + + /** @brief Check and mark presence of a digi branch + ** @param detector ECbmModuleId + ** @param tree Pointer to ROOT Tree + **/ + void CheckDigiBranch(TTree* tree, ECbmModuleId detector); + + + /** @brief Check existence of a file + ** @param fileName File name (absolute or relative to current directory) + ** @return true if file exists + **/ + bool CheckFile(const char* fileName); + + + /** @brief Check the presence of digi input branches **/ + void CheckInputBranches(FairFileSource* source); + + + /** @brief Create the reconstruction task topology (chain) **/ + void CreateTopology(); + + + private: + FairRunAna fRun {}; + TString fInput = ""; + TString fParams = ""; + TString fOutput = ""; + TString fSetupTag = ""; + CbmSetup* fSetup = nullptr; + size_t fNumTs = 0; + bool fOverwrite = false; + + Config fConfig = {}; + std::set<ECbmModuleId> fDataPresent = {}; + + + ClassDef(cbm::reco::offline::Run, 1); + }; + +} // namespace cbm::reco::offline + +#endif /* CBM_RECO_OFFLINE_STEER_RUN_H */ diff --git a/reco/offline/steer/TaskFactory.cxx b/reco/offline/steer/TaskFactory.cxx new file mode 100644 index 0000000000000000000000000000000000000000..565d4b4cf13d1fe482504163dad79bd3ac880126 --- /dev/null +++ b/reco/offline/steer/TaskFactory.cxx @@ -0,0 +1,338 @@ +/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Volker Friese [committer] */ + +/** @file TaskFactory.cxx + ** @author Volker Friese <v.friese@gsi.de> + ** @date 06.06.2023 + **/ + +#include "TaskFactory.h" + +#include "CbmBuildEventsFromTracksReal.h" +#include "CbmBuildEventsIdeal.h" +#include "CbmFindPrimaryVertex.h" +#include "CbmKF.h" +#include "CbmL1.h" +#include "CbmL1StsTrackFinder.h" +#include "CbmLitFindGlobalTracks.h" +#include "CbmMuchFindHitsGem.h" +#include "CbmMuchGeoScheme.h" +#include "CbmMvdClusterfinder.h" +#include "CbmMvdHitfinder.h" +#include "CbmPVFinderKF.h" +#include "CbmRecoSts.h" +#include "CbmRecoTzero.h" +#include "CbmRichHitProducer.h" +#include "CbmRichReconstruction.h" +#include "CbmSetup.h" +#include "CbmStsFindTracks.h" +#include "CbmStsFindTracksEvents.h" +#include "CbmTaskBuildRawEvents.h" +#include "CbmTofSimpClusterizer.h" +#include "CbmTrackingDetectorInterfaceInit.h" +#include "CbmTrdClusterFinder.h" +#include "CbmTrdHitProducer.h" +#include "CbmTrdSetTracksPidLike.h" + +#include <TSystem.h> + + +namespace cbm::reco::offline +{ + + + // ----- Constructor ---------------------------------------------------- + TaskFactory::TaskFactory(Run* run) : fRun(run) {} + // -------------------------------------------------------------------------- + + + // ----- CA tracking ---------------------------------------------------- + void TaskFactory::RegisterCaTracking() + { + assert(fRun); + + // --- Tracking geometry interface + auto interface = new CbmTrackingDetectorInterfaceInit(); + fRun->AddTask(interface); + + // --- Kalman Filter + auto kf = new CbmKF(); + fRun->AddTask(kf); + + // --- CA Track Finder + auto ca = new CbmL1("CA Track Finder", 0, 0, 4); + if (fRun->IsDataPresent(ECbmModuleId::kMvd)) { + TString mvdGeoTag; + if (CbmSetup::Instance()->GetGeoTag(ECbmModuleId::kMvd, mvdGeoTag)) { + TString parFileMvd = gSystem->Getenv("VMCWORKDIR"); + parFileMvd += "/parameters/mvd/mvd_matbudget_" + mvdGeoTag + ".root"; + ca->SetMvdMaterialBudgetFileName(parFileMvd.Data()); + } + else + throw std::runtime_error("CA: No geo tag for MVD"); + } + if (fRun->IsDataPresent(ECbmModuleId::kSts)) { + TString stsGeoTag; + if (CbmSetup::Instance()->GetGeoTag(ECbmModuleId::kSts, stsGeoTag)) { + TString parFileSts = gSystem->Getenv("VMCWORKDIR"); + parFileSts += "/parameters/sts/sts_matbudget_" + stsGeoTag + ".root"; + ca->SetStsMaterialBudgetFileName(parFileSts.Data()); + } + else + throw std::runtime_error("CA: No geo tag for STS"); + } + fRun->AddTask(ca); + + // --- Track finder steering class + auto trackFinder = new CbmL1StsTrackFinder(); + + // --- Track finder task + FairTask* findTracks = nullptr; + if (fRun->GetConfig().f_glb_mode == ECbmRecoMode::Timeslice) + findTracks = new CbmStsFindTracks(0, trackFinder, true); + else + findTracks = new CbmStsFindTracksEvents(trackFinder, true); + fRun->AddTask(findTracks); + } + // -------------------------------------------------------------------------- + + + // ----- Event building from digis -------------------------------------- + void TaskFactory::RegisterDigiEventBuilder() + { + assert(fRun); + if (fRun->GetConfig().f_evbuild_type == cbm::reco::offline::ECbmEvbuildType::Undefined) + throw std::out_of_range("Undefined event builder type"); + + // --- Ideal digi event builder (using MC truth information) + if (fRun->GetConfig().f_evbuild_type == cbm::reco::offline::ECbmEvbuildType::Ideal) { + FairTask* evBuildRaw = new CbmBuildEventsIdeal(); + fRun->AddTask(evBuildRaw); + } //? Ideal event builder + + // --- Real digi event builder + // TODO: This should be replaced by the newer algorithm algo/evbuild/EventBuilder + else { + + const cbm::reco::offline::Config& config = fRun->GetConfig(); + ECbmModuleId triggerDetector = config.f_evbuild_trigDet; + + if (!fRun->IsDataPresent(triggerDetector)) throw std::runtime_error("No input data for trigger detector"); + + // --- Task + CbmTaskBuildRawEvents* evBuildRaw = new CbmTaskBuildRawEvents(); + + // --- Mode + evBuildRaw->SetEventOverlapMode(config.f_evbuild_ovlapmode); + + // --- Reference detector + switch (triggerDetector) { + case ECbmModuleId::kSts: evBuildRaw->SetReferenceDetector(kRawEventBuilderDetSts); break; + case ECbmModuleId::kMuch: evBuildRaw->SetReferenceDetector(kRawEventBuilderDetMuch); break; + case ECbmModuleId::kTrd: evBuildRaw->SetReferenceDetector(kRawEventBuilderDetTrd); break; + case ECbmModuleId::kTrd2d: evBuildRaw->SetReferenceDetector(kRawEventBuilderDetTrd2D); break; + case ECbmModuleId::kTof: evBuildRaw->SetReferenceDetector(kRawEventBuilderDetTof); break; + case ECbmModuleId::kRich: evBuildRaw->SetReferenceDetector(kRawEventBuilderDetRich); break; + case ECbmModuleId::kPsd: evBuildRaw->SetReferenceDetector(kRawEventBuilderDetPsd); break; + case ECbmModuleId::kT0: evBuildRaw->SetReferenceDetector(kRawEventBuilderDetT0); break; + default: throw std::out_of_range("Event builder: Undefined trigger detector"); break; + } + + // --- Make BMON (default reference detector) a selected detector (with default parameters) + if (triggerDetector != ECbmModuleId::kT0) evBuildRaw->AddDetector(kRawEventBuilderDetT0); + + // --- Remove detectors of which there are no input data + if (!fRun->IsDataPresent(ECbmModuleId::kRich)) evBuildRaw->RemoveDetector(kRawEventBuilderDetRich); + if (!fRun->IsDataPresent(ECbmModuleId::kMuch)) evBuildRaw->RemoveDetector(kRawEventBuilderDetMuch); + if (!fRun->IsDataPresent(ECbmModuleId::kPsd)) evBuildRaw->RemoveDetector(kRawEventBuilderDetPsd); + if (!fRun->IsDataPresent(ECbmModuleId::kTof)) evBuildRaw->RemoveDetector(kRawEventBuilderDetTof); + if (!fRun->IsDataPresent(ECbmModuleId::kTrd)) evBuildRaw->RemoveDetector(kRawEventBuilderDetTrd); + + // --- Timeslice parameters + evBuildRaw->SetTsParameters(0.0, 1.e7, 0.0); + + // --- Use CbmMuchDigi instead of CbmMuchBeamtimeDigi + // TODO: Seems legacy. + evBuildRaw->ChangeMuchBeamtimeDigiFlag(kFALSE); + + // --- Set trigger parameters + evBuildRaw->SetTriggerMinNumber(triggerDetector, config.f_evbuild_trigNumMin); + evBuildRaw->SetTriggerMaxNumber(triggerDetector, config.f_evbuild_trigNumMax); + evBuildRaw->SetTriggerWindow(triggerDetector, config.f_evbuild_trigWinMin, config.f_evbuild_trigWinMax); + + fRun->AddTask(evBuildRaw); + + } //? Real event builder + } + // -------------------------------------------------------------------------- + + + // ----- LIT Global Tracking -------------------------------------------- + void TaskFactory::RegisterGlobalTracking() + { + assert(fRun); + CbmLitFindGlobalTracks* finder = new CbmLitFindGlobalTracks(); + finder->SetTrackingType(fRun->GetConfig().f_lit_trackType); + finder->SetMergerType(fRun->GetConfig().f_lit_mergeType); + fRun->AddTask(finder); + } + // -------------------------------------------------------------------------- + + + // ----- MUCH reconstruction -------------------------------------------- + void TaskFactory::RegisterMuchReco() + { + assert(fRun); + if (!fRun->IsDataPresent(ECbmModuleId::kMuch)) return; + + // --- Parameter file name + TString geoTag; + if (CbmSetup::Instance()->GetGeoTag(ECbmModuleId::kMuch, geoTag)) { + Int_t muchFlag = (geoTag.Contains("mcbm") ? 1 : 0); + TString parFile = gSystem->Getenv("VMCWORKDIR"); + parFile += "/parameters/much/much_" + geoTag(0, 4) + "_digi_sector.root"; + + auto muchGeoScheme = CbmMuchGeoScheme::Instance(); + if (!muchGeoScheme->IsInitialized()) { muchGeoScheme->Init(parFile, muchFlag); } + + FairTask* muchReco = new CbmMuchFindHitsGem(parFile.Data(), muchFlag); + fRun->AddTask(muchReco); + } + } + // -------------------------------------------------------------------------- + + + // ----- MVD reconstruction --------------------------------------------- + void TaskFactory::RegisterMvdReco() + { + assert(fRun); + if (!fRun->IsDataPresent(ECbmModuleId::kMvd)) return; + + CbmMvdClusterfinder* mvdCluster = new CbmMvdClusterfinder("MVD Cluster Finder", 0, 0); + fRun->AddTask(mvdCluster); + + CbmMvdHitfinder* mvdHit = new CbmMvdHitfinder("MVD Hit Finder", 0, 0); + mvdHit->UseClusterfinder(kTRUE); + fRun->AddTask(mvdHit); + } + // -------------------------------------------------------------------------- + + + // ----- Primary Vertex Finding ----------------------------------------- + void TaskFactory::RegisterPvFinder() + { + assert(fRun); + CbmPrimaryVertexFinder* pvFinder = new CbmPVFinderKF(); + CbmFindPrimaryVertex* findVertex = new CbmFindPrimaryVertex(pvFinder); + fRun->AddTask(findVertex); + } + // -------------------------------------------------------------------------- + + + // ----- RICH hit finding ----------------------------------------------- + void TaskFactory::RegisterRichHitFinder() + { + assert(fRun); + if (!fRun->IsDataPresent(ECbmModuleId::kRich)) return; + + CbmRichHitProducer* richHitProd = new CbmRichHitProducer(); + fRun->AddTask(richHitProd); + } + // -------------------------------------------------------------------------- + + + // ----- RICH reconstruction -------------------------------------------- + void TaskFactory::RegisterRichReco() + { + assert(fRun); + if (!fRun->IsDataPresent(ECbmModuleId::kRich)) return; + + CbmRichReconstruction* richReco = new CbmRichReconstruction(); + fRun->AddTask(richReco); + } + // -------------------------------------------------------------------------- + + + // ----- STS reconstruction --------------------------------------------- + void TaskFactory::RegisterStsReco() + { + assert(fRun); + if (!fRun->IsDataPresent(ECbmModuleId::kSts)) return; + + CbmRecoSts* stsReco = new CbmRecoSts(fRun->GetConfig().f_glb_mode); + stsReco->SetUseGpuReco(fRun->GetConfig().f_sts_usegpu); + fRun->AddTask(stsReco); + } + // -------------------------------------------------------------------------- + + + // ----- TOF reconstruction --------------------------------------------- + void TaskFactory::RegisterTofReco() + { + assert(fRun); + if (!fRun->IsDataPresent(ECbmModuleId::kTof)) return; + + CbmTofSimpClusterizer* tofCluster = new CbmTofSimpClusterizer("TOF Simple Clusterizer", 0); + tofCluster->SetOutputBranchPersistent("TofHit", kTRUE); + tofCluster->SetOutputBranchPersistent("TofDigiMatch", kTRUE); + fRun->AddTask(tofCluster); + } + // -------------------------------------------------------------------------- + + + // ----- Event building from tracks ------------------------------------- + void TaskFactory::RegisterTrackEventBuilder() + { + assert(fRun); + auto eventBuilder = new CbmBuildEventsFromTracksReal(); + fRun->AddTask(eventBuilder); + } + // -------------------------------------------------------------------------- + + + // ----- TRD PID -------------------------------------------------------- + void TaskFactory::RegisterTrdPid() + { + assert(fRun); + if (!fRun->IsDataPresent(ECbmModuleId::kTrd)) return; + + CbmTrdSetTracksPidLike* trdPid = new CbmTrdSetTracksPidLike("TRDLikelihood", "TRDLikelihood"); + trdPid->SetUseMCInfo(kTRUE); + trdPid->SetUseMomDependence(kTRUE); + fRun->AddTask(trdPid); + } + // -------------------------------------------------------------------------- + + + // ----- TRD reconstruction --------------------------------------------- + void TaskFactory::RegisterTrdReco() + { + assert(fRun); + if (!fRun->IsDataPresent(ECbmModuleId::kTrd)) return; + + CbmTrdClusterFinder* trdCluster = new CbmTrdClusterFinder(); + if (fRun->GetConfig().f_glb_mode == ECbmRecoMode::EventByEvent) trdCluster->SetTimeBased(kFALSE); + else + trdCluster->SetTimeBased(kTRUE); + trdCluster->SetNeighbourEnable(true, false); + trdCluster->SetMinimumChargeTH(fRun->GetConfig().f_trd_trigThresh); + trdCluster->SetRowMerger(true); + fRun->AddTask(trdCluster); + + CbmTrdHitProducer* trdHit = new CbmTrdHitProducer(); + fRun->AddTask(trdHit); + } + // -------------------------------------------------------------------------- + + + // ----- T0 reconstruction ---------------------------------------------- + void TaskFactory::RegisterTzeroReco() + { + assert(fRun); + CbmRecoTzero* recoT0 = new CbmRecoTzero(); + fRun->AddTask(recoT0); + } + // -------------------------------------------------------------------------- + +} // namespace cbm::reco::offline diff --git a/reco/offline/steer/TaskFactory.h b/reco/offline/steer/TaskFactory.h new file mode 100644 index 0000000000000000000000000000000000000000..5fd7bf11952008a61017131f66ad3581bda0cf01 --- /dev/null +++ b/reco/offline/steer/TaskFactory.h @@ -0,0 +1,52 @@ +/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Volker Friese [committer] */ + +/** @file TaskFactory.h + ** @author Volker Friese <v.friese@gsi.de> + ** @date 06.06.2023 + **/ + +#ifndef CBM_RECO_OFFLINE_STEER_TASKFACTORY_H +#define CBM_RECO_OFFLINE_STEER_TASKFACTORY_H 1 + +#include "Run.h" + +namespace cbm::reco::offline +{ + + /** @class TaskFactory + ** @brief Factory class for the instantiation of CBM reconstruction tasks + ** @author Volker Friese <v.friese@gsi.de> + ** @since 6 June 2023 + **/ + class TaskFactory { + public: + /** @brief Constructor **/ + TaskFactory(Run* steer = nullptr); + + /** @brief Destructor **/ + virtual ~TaskFactory() {}; + + void RegisterCaTracking(); /// CA track finding + void RegisterDigiEventBuilder(); /// Event building from digis + void RegisterGlobalTracking(); /// Global track finding + void RegisterMuchReco(); /// Local reconstruction for MUCH + void RegisterMvdReco(); /// Local reconstruction for MVD + void RegisterPvFinder(); /// Primary vertex finding + void RegisterRichHitFinder(); /// Hit finding in RICH + void RegisterRichReco(); /// Local reconstruction for RICH + void RegisterStsReco(); /// Local reconstruction for STS + void RegisterTofReco(); /// Local reconstruction for TOF + void RegisterTrackEventBuilder(); /// Event building from tracks + void RegisterTrdReco(); /// Local reconstruction for TRD + void RegisterTrdPid(); /// PID with TRD + void RegisterTzeroReco(); /// Reconstruction of T0 + + private: //members + Run* fRun = nullptr; + }; + +} // namespace cbm::reco::offline + +#endif /* CBM_RECO_OFFLINE_STEER_TASKFACTORY_H */