From 5db8ef02bdf9cdd572ecb8e42e7175070c15f31e Mon Sep 17 00:00:00 2001
From: Volker Friese <v.friese@gsi.de>
Date: Thu, 5 May 2022 10:13:44 +0000
Subject: [PATCH] Integrate reconstruction from timeslice data and from digi
 data (simulation).

---
 macro/reco/CMakeLists.txt                    |  21 +-
 macro/reco/reco_digi.C                       | 190 -------------------
 macro/reco/{reco_steer.C => reco_fairroot.C} |  30 +--
 macro/reco/reco_ts.C                         | 160 ----------------
 reco/tasks/CbmReco.cxx                       |  58 ++++--
 5 files changed, 61 insertions(+), 398 deletions(-)
 delete mode 100644 macro/reco/reco_digi.C
 rename macro/reco/{reco_steer.C => reco_fairroot.C} (76%)
 delete mode 100644 macro/reco/reco_ts.C

diff --git a/macro/reco/CMakeLists.txt b/macro/reco/CMakeLists.txt
index a64a507f80..b97fa05599 100644
--- a/macro/reco/CMakeLists.txt
+++ b/macro/reco/CMakeLists.txt
@@ -6,7 +6,7 @@
 GENERATE_ROOT_TEST_SCRIPT(${CBMROOT_SOURCE_DIR}/macro/run/run_tra_file.C)
 GENERATE_ROOT_TEST_SCRIPT(${CBMROOT_SOURCE_DIR}/macro/run/run_tra_beam.C)
 GENERATE_ROOT_TEST_SCRIPT(${CBMROOT_SOURCE_DIR}/macro/run/run_digi.C)
-GENERATE_ROOT_TEST_SCRIPT(${CBMROOT_SOURCE_DIR}/macro/reco/reco_digi.C)
+GENERATE_ROOT_TEST_SCRIPT(${CBMROOT_SOURCE_DIR}/macro/reco/reco_fairroot.C)
 # ============================================================================
 
 
@@ -85,7 +85,7 @@ foreach(setup IN LISTS cbm_setup)
   	RESOURCE_LOCK collParDb_${setup}
   )
 
-  # --- Test run_tra_sign
+  # --- Test reco_tra_sign
   # --- Transport run with signal events, using run_tra_file.C
   set(testname reco_tra_sign_${sname})
   set(input ${CBMROOT_SOURCE_DIR}/input/pluto.auau.8gev.omega.mpmm.0001.root)
@@ -100,7 +100,7 @@ foreach(setup IN LISTS cbm_setup)
   	RESOURCE_LOCK signParDb_${setup}
   )
 
-  # --- Test run_tra_beam
+  # --- Test reco_tra_beam
   # --- Transport run with beam events, using run_tra_beam.C
   set(testname reco_tra_beam_${sname})
   set(output ${datadir}/${sname}_beam)
@@ -114,7 +114,7 @@ foreach(setup IN LISTS cbm_setup)
   	RESOURCE_LOCK beamParDb_${setup}
   )
 
-  # --- Test run_digi_ts
+  # --- Test reco_digi
   # --- Detector response simulation, time-based, using run_digi.C
   set(testname reco_digi_${sname})
   set(eventrate 1.e7)
@@ -131,17 +131,16 @@ foreach(setup IN LISTS cbm_setup)
  	RESOURCE_LOCK collParDb_${setup}
   )
 
-  # --- Test reco_digi
+  # --- Test reco_reco_sim
   # --- Reconstruction from time-based simulation
-  set(testname reco_reco_digi_${sname})
-  add_test(${testname} ${MACRODIR}/reco_digi.sh
-  	\"${datadir}/${sname}\" -1 0 \"${datadir}/${sname}\" \"${setup}\"
-  	\"${datadir}/${sname}_coll\")
+  set(testname reco_reco_sim_${sname})
+  add_test(${testname} ${MACRODIR}/reco_fairroot.sh
+  	\"${datadir}/${sname}.raw.root\" \"${datadir}/${sname}.reco.root\")
   set_tests_properties(${testname} PROPERTIES
   	TIMEOUT ${timeOutTime}
   	PASS_REGULAR_EXPRESSION "Macro finished successfully"
 	FIXTURES_REQUIRED fixt_digi_ts_${setup}
-	FIXTURES_SETUP fixt_reco_digi_${setup}
+	FIXTURES_SETUP fixt_reco_sim_${setup}
  	RESOURCE_LOCK collParDb_${setup}
   )
 
@@ -150,7 +149,7 @@ endforeach(setup IN LISTS cbm_setup)
 
 # ============================================================================
 
-Install(FILES reco_digi.C
+Install(FILES reco_fairroot.C reco_unpack.C
         DESTINATION share/cbmroot/macro/reco
        )
 Install(CODE "FILE(MAKE_DIRECTORY \${CMAKE_INSTALL_PREFIX}/share/cbmroot/macro/reco/data)")
diff --git a/macro/reco/reco_digi.C b/macro/reco/reco_digi.C
deleted file mode 100644
index 8b8c7b5515..0000000000
--- a/macro/reco/reco_digi.C
+++ /dev/null
@@ -1,190 +0,0 @@
-/* Copyright (C) 2020-2021 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
-   SPDX-License-Identifier: GPL-3.0-only
-   Authors: Volker Friese [committer], Dominik Smith */
-
-
-// --- Includes needed for IDE
-#include <RtypesCore.h>
-#if !defined(__CLING__)
-#include "CbmDefs.h"
-#include "CbmSetup.h"
-#include "CbmTaskBuildEvents.h"
-#include "CbmTaskTriggerDigi.h"
-
-#include <FairFileSource.h>
-#include <FairMonitor.h>
-#include <FairParAsciiFileIo.h>
-#include <FairParRootFileIo.h>
-#include <FairRunAna.h>
-#include <FairRuntimeDb.h>
-#include <FairSystemInfo.h>
-
-#include <TStopwatch.h>
-
-#include <memory>
-#endif
-
-#include <FairLogger.h>
-
-/** @brief Macro for CBM reconstruction from digi level
- ** @author Volker Friese <v.friese@gsi.de>
- ** @since  15 November 2021
- ** @param input          Name of input file (w/o extension .raw.root)
- ** @param nTimeSlices    Number of time-slices to process
- ** @param firstTimeSlice First time-slice (entry) to be processed
- ** @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)
- **
- ** Reconstruction from digi level. Currently included stages:
- ** - Event building (CbmTaskBuildEvents) (STS only)
- **
- ** TODO: To be expanded with the progress of the algo project.
- **
- ** 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.C)
- ** from the ROOT prompt without user intervention.
- **
- **/
-void reco_digi(TString input = "", Int_t nTimeSlices = -1, Int_t firstTimeSlice = 0, TString output = "",
-               TString setup = "sis100_electron", TString paramFile = "")
-{
-
-  // ========================================================================
-  //          Adjust this part according to your requirements
-
-  // --- Logger settings ----------------------------------------------------
-  TString logLevel     = "INFO";
-  TString logVerbosity = "LOW";
-  // ------------------------------------------------------------------------
-
-  // -----   Environment   --------------------------------------------------
-  TString myName = "reco_digi";                    // this macro's name for screen log
-  TString srcDir = gSystem->Getenv("VMCWORKDIR");  // top source directory
-  // ------------------------------------------------------------------------
-
-
-  // -----   In- and output file names   ------------------------------------
-  if (input.IsNull()) input = "test";
-  TString rawFile = input + ".raw.root";
-  TString traFile = input + ".tra.root";
-  if (output.IsNull()) output = input;
-  TString outFile = output + ".events.root";
-  TString monFile = output + ".moni_reco.root";
-  if (paramFile.IsNull()) paramFile = input;
-  TString parFile = paramFile + ".par.root";
-  LOG(info) << myName << ": Input file is     " << rawFile;
-  LOG(info) << myName << ": Output file is    " << outFile;
-  LOG(info) << myName << ": Parameter file is " << parFile;
-
-  // -----   Load the geometry setup   -------------------------------------
-  std::cout << std::endl;
-  std::cout << "-I- " << myName << ": Loading setup " << setup << std::endl;
-  CbmSetup* geo = CbmSetup::Instance();
-  geo->LoadSetup(setup);
-  // ------------------------------------------------------------------------
-
-
-  // -----   Timer   --------------------------------------------------------
-  TStopwatch timer;
-  timer.Start();
-  // ------------------------------------------------------------------------
-
-
-  // -----   FairRunAna   ---------------------------------------------------
-  FairRunAna* run             = new FairRunAna();
-  FairFileSource* inputSource = new FairFileSource(rawFile);
-  run->SetSource(inputSource);
-  run->SetOutputFile(outFile);
-  run->SetGenerateRunInfo(kTRUE);
-  FairMonitor::GetMonitor()->EnableMonitor(kTRUE, monFile);
-  // ------------------------------------------------------------------------
-
-
-  // -----   Logger settings   ----------------------------------------------
-  FairLogger::GetLogger()->SetLogScreenLevel(logLevel.Data());
-  FairLogger::GetLogger()->SetLogVerbosityLevel(logVerbosity.Data());
-  // ------------------------------------------------------------------------
-
-
-  // -----   Digi trigger   -------------------------------------------------
-  auto trigger         = std::make_unique<CbmTaskTriggerDigi>();
-  double triggerWindow = 10.;  // Trigger window size in ns
-  int32_t minNumDigis  = 100;  // Trigger threshold in number of digis
-  double deadTime      = 50.;  // Minimum time between two triggers
-  trigger->SetAlgoParams(triggerWindow, minNumDigis, deadTime);
-  trigger->AddSystem(ECbmModuleId::kSts);
-  LOG(info) << myName << ": Added task " << trigger->GetName();
-  run->AddTask(trigger.release());
-  // ------------------------------------------------------------------------
-
-
-  // -----   Event building   -----------------------------------------------
-  auto evtBuild = std::make_unique<CbmTaskBuildEvents>();
-  evtBuild->SetEventWindow(ECbmModuleId::kSts, -20., 30.);  // event building time window for STS
-  LOG(info) << myName << ": Added task " << evtBuild->GetName();
-  run->AddTask(evtBuild.release());
-  // ------------------------------------------------------------------------
-
-
-  // -----  Parameter database   --------------------------------------------
-  std::cout << std::endl << std::endl;
-  std::cout << "-I- " << myName << ": Set runtime DB" << std::endl;
-  FairRuntimeDb* rtdb      = run->GetRuntimeDb();
-  FairParRootFileIo* parIo = new FairParRootFileIo();
-  parIo->open(parFile.Data(), "UPDATE");
-  rtdb->setFirstInput(parIo);
-  // ------------------------------------------------------------------------
-
-
-  // -----   Run initialisation   -------------------------------------------
-  std::cout << std::endl;
-  std::cout << "-I- " << myName << ": Initialise run" << std::endl;
-  run->Init();
-  rtdb->setOutput(parIo);
-  rtdb->saveOutput();
-  rtdb->print();
-  // ------------------------------------------------------------------------
-
-
-  // -----   Start run   ----------------------------------------------------
-  std::cout << std::endl << std::endl;
-  std::cout << "-I- " << myName << ": Starting run" << std::endl;
-  run->Run(firstTimeSlice, nTimeSlices);
-  // ------------------------------------------------------------------------
-
-
-  // -----   Finish   -------------------------------------------------------
-  timer.Stop();
-  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/macro/reco/reco_steer.C b/macro/reco/reco_fairroot.C
similarity index 76%
rename from macro/reco/reco_steer.C
rename to macro/reco/reco_fairroot.C
index c3d4872b99..9e9508c3ac 100644
--- a/macro/reco/reco_steer.C
+++ b/macro/reco/reco_fairroot.C
@@ -18,27 +18,25 @@
 
 using std::string;
 
-/** @brief Macro for CBM reconstruction from FLES timeslices
+/** @brief Macro for CBM reconstruction from FLES timeslices or digi level
  ** @author Volker Friese <v.friese@gsi.de>
  ** @since  12 March 2022
- ** @param tsaFile    Name of input file (w/o extension .tsa)
- ** @param outFile    Name of output file (w/o extension .digi.root)
+ ** @param tsaFile    Name of input file (.tsa or .root)
+ ** @param outFile    Name of output file
  ** @param numTs      Number of timeslices to process. If not specified, all available will be used.
  ** @param port       Port of http server. If 0, server will not be activated.
  **
- ** Reconstruction from timeslice level, making use of the steering class CbmReco.
+ ** Reconstruction from timeslice level with FairRoot, making use of the steering class CbmReco.
  ** Currently included stages:
- ** - Unpacking (STS only)
+ ** - Unpacking (STS only) (if from timeslice level)
  ** - Event trigger based on STS digis (CbmTaskDigiTrigger)
  ** - Event building (CbmTaskBuildEvents) (STS only)
  **
- ** If the tsaFile name is not specified, a default file from the repository will be used.
- ** If the outFile name is not specified, the input file name will be used, replacing
- ** the extension .tsa by .digi.root
+ ** If the input file name is left empty, a default file from the repository will be used.
  **/
 
-void reco_steer(TString tsaFile = "", TString outFile = "", int32_t numTs = std::numeric_limits<int32_t>::max(),
-                uint32_t port = 8080)
+void reco_fairroot(TString tsaFile, TString outFile, int32_t numTs = std::numeric_limits<int32_t>::max(),
+                   uint16_t port = 0)
 {
 
   // ========================================================================
@@ -74,7 +72,7 @@ void reco_steer(TString tsaFile = "", TString outFile = "", int32_t numTs = std:
 
 
   // -----   Environment   --------------------------------------------------
-  TString myName = "reco_steer";                   // this macro's name for screen output
+  TString myName = "reco_fairoot";                 // this macro's name for screen output
   TString srcDir = gSystem->Getenv("VMCWORKDIR");  // top source directory
   // ------------------------------------------------------------------------
 
@@ -83,14 +81,6 @@ void reco_steer(TString tsaFile = "", TString outFile = "", int32_t numTs = std:
   // the code is outdated.
 
 
-  // ----- Default file names   ---------------------------------------------
-  if (tsaFile.IsNull()) tsaFile = srcDir + "/input/mcbm_run399_first20Ts";
-  TString inFile = tsaFile + ".tsa";
-  if (outFile.IsNull()) outFile = tsaFile;
-  outFile += ".digi.root";
-  // ------------------------------------------------------------------------
-
-
   // -----   Logger settings   ----------------------------------------------
   FairLogger::GetLogger()->SetLogScreenLevel(logLevel.Data());
   FairLogger::GetLogger()->SetLogVerbosityLevel(logVerbosity.Data());
@@ -100,7 +90,7 @@ void reco_steer(TString tsaFile = "", TString outFile = "", int32_t numTs = std:
   // -----   Run reconstruction   -------------------------------------------
   TStopwatch timer;
   timer.Start();
-  CbmReco run(inFile.Data(), outFile.Data(), numTs, config, port);
+  CbmReco run(tsaFile.Data(), outFile.Data(), numTs, config, port);
   run.Run();
   timer.Stop();
   // ------------------------------------------------------------------------
diff --git a/macro/reco/reco_ts.C b/macro/reco/reco_ts.C
deleted file mode 100644
index ea0cebc743..0000000000
--- a/macro/reco/reco_ts.C
+++ /dev/null
@@ -1,160 +0,0 @@
-/* Copyright (C) 2022 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
-   SPDX-License-Identifier: GPL-3.0-only
-   Authors: Volker Friese [committer] */
-
-
-// --- Includes needed for IDE code analyser
-#if !defined(__CLING__)
-#include "CbmSourceTs.h"
-#include "CbmTaskUnpack.h"
-#include "CbmTsEventHeader.h"
-
-#include <FairRootFileSink.h>
-#include <FairRunOnline.h>
-
-#include <TStopwatch.h>
-#include <TSystem.h>
-
-#include <iostream>
-#include <memory>
-#endif
-
-#include <FairLogger.h>
-
-
-using std::string;
-
-/** @brief Macro for CBM reconstruction from FLES timeslices
- ** @author Volker Friese <v.friese@gsi.de>
- ** @since  12 March 2022
- ** @param tsaFile    Name of input file (w/o extension .tsa)
- ** @param outFile    Name of output file (w/o extension .digi.root)
- **
- ** Reconstruction from timeslice level. Currently included stages:
- ** - Unpacking (STS only)
- ** - Event trigger based on STS digis (CbmTaskDigiTrigger)
- ** - Event building (CbmTaskBuildEvents) (STS only)
- **
- ** TODO: To be expanded with the progress of the algo project.
- **
- ** If the tsaFile name is not specified, a default file from the reporistory will be used.
- ** If the outFile name is not specified, the input file name will be used, replacing
- ** the extension .tsa by .digi.root
- **/
-
-void reco_ts(TString tsaFile = "", TString outFile = "")
-{
-
-  // ========================================================================
-  //          Adjust this part according to your requirements
-
-  // --- Logger settings ----------------------------------------------------
-  TString logLevel     = "INFO";
-  TString logVerbosity = "LOW";
-  // ------------------------------------------------------------------------
-
-  // -----   Environment   --------------------------------------------------
-  TString myName = "reco_ts";                      // this macro's name for screen output
-  TString srcDir = gSystem->Getenv("VMCWORKDIR");  // top source directory
-  // ------------------------------------------------------------------------
-
-  // In general, the following parts need not be touched
-  // ========================================================================
-
-  // Tested with file 1588_node8_1_0000.tsa
-  // TODO: Would need a small up-to-date default input file; the one distributed with
-  // the code is outdated.
-
-
-  // ----- Default file names   ---------------------------------------------
-  if (tsaFile.IsNull()) tsaFile = srcDir + "/input/mcbm_run399_first20Ts";
-  TString inFile = tsaFile + ".tsa";
-  if (outFile.IsNull()) outFile = tsaFile;
-  outFile += ".digi.root";
-  std::cout << std::endl << std::endl;
-  LOG(info) << myName << ": Using input file " << inFile;
-  LOG(info) << myName << ": Output file is   " << outFile;
-  // ------------------------------------------------------------------------
-
-
-  // -----   Timer   --------------------------------------------------------
-  TStopwatch timer;
-  timer.Start();
-  // ------------------------------------------------------------------------
-
-
-  // ----   Run configuration   ---------------------------------------------
-  auto source = new CbmSourceTs(inFile.Data());
-  auto run    = new FairRunOnline(source);
-  auto sink   = new FairRootFileSink(outFile.Data());
-  run->SetSink(sink);
-  auto eventheader = new CbmTsEventHeader();
-  run->SetEventHeader(new CbmTsEventHeader());
-  // ------------------------------------------------------------------------
-
-
-  // -----   Unpacking   ----------------------------------------------------
-  auto unpack = std::make_unique<CbmTaskUnpack>();
-  unpack->SetOutputBranchPersistent("DigiTimeslice.", kFALSE);
-  LOG(info) << myName << ": Added task " << unpack->GetName();
-  run->AddTask(unpack.release());
-  // ------------------------------------------------------------------------
-
-
-  // -----   Digi trigger   -------------------------------------------------
-  auto trigger         = std::make_unique<CbmTaskTriggerDigi>();
-  double triggerWindow = 10.;  // Trigger window size in ns
-  int32_t minNumDigis  = 100;  // Trigger threshold in number of digis
-  double deadTime      = 50.;  // Minimum time between two triggers
-  trigger->SetAlgoParams(triggerWindow, minNumDigis, deadTime);
-  trigger->AddSystem(ECbmModuleId::kSts);
-  trigger->SetOutputBranchPersistent("Trigger", kFALSE);
-  LOG(info) << myName << ": Added task " << trigger->GetName();
-  run->AddTask(trigger.release());
-  // ------------------------------------------------------------------------
-
-
-  // -----   Event building   -----------------------------------------------
-  auto evtBuild = std::make_unique<CbmTaskBuildEvents>();
-  evtBuild->SetEventWindow(ECbmModuleId::kSts, -20., 30.);  // event building time window for STS
-  LOG(info) << myName << ": Added task " << evtBuild->GetName();
-  run->AddTask(evtBuild.release());
-  // ------------------------------------------------------------------------
-
-
-  // -----   Event QA   -----------------------------------------------------
-  auto eventQa = std::make_unique<CbmTaskDigiEventQa>();
-  LOG(info) << myName << ": Added task " << eventQa->GetName();
-  run->AddTask(eventQa.release());
-  // ------------------------------------------------------------------------
-
-
-  // -----   Logger settings   ----------------------------------------------
-  FairLogger::GetLogger()->SetLogScreenLevel(logLevel.Data());
-  FairLogger::GetLogger()->SetLogVerbosityLevel(logVerbosity.Data());
-  // ------------------------------------------------------------------------
-
-
-  // -----   Run initialisation   -------------------------------------------
-  std::cout << std::endl;
-  LOG(info) << myName << ": Initialise run" << std::endl;
-  run->Init();
-  // ------------------------------------------------------------------------
-
-
-  // -----   Start run   ----------------------------------------------------
-  std::cout << std::endl << std::endl;
-  LOG(info) << myName << ": Starting run" << std::endl;
-  run->Run(-1, 0);
-  // ------------------------------------------------------------------------
-
-
-  // -----   Finish   -------------------------------------------------------
-  timer.Stop();
-  std::cout << std::endl << std::endl;
-  std::cout << "Macro finished successfully." << std::endl;
-  std::cout << "Output file: " << outFile << std::endl;
-  std::cout << "CPU time = " << timer.CpuTime() << " s, real time = " << timer.RealTime() << " s." << std::endl;
-  // ------------------------------------------------------------------------
-
-}  // End of main macro function
diff --git a/reco/tasks/CbmReco.cxx b/reco/tasks/CbmReco.cxx
index ec47da729f..b29a262edd 100644
--- a/reco/tasks/CbmReco.cxx
+++ b/reco/tasks/CbmReco.cxx
@@ -11,8 +11,10 @@
 #include "CbmTaskUnpack.h"
 #include "CbmTsEventHeader.h"
 
+#include <FairFileSource.h>
 #include <FairLogger.h>
 #include <FairRootFileSink.h>
+#include <FairRunAna.h>
 #include <FairRunOnline.h>
 
 #include <THttpServer.h>
@@ -130,12 +132,31 @@ int32_t CbmReco::Run()
   TStopwatch timer;
   timer.Start();
 
+  // --- Check if the input is a ROOT file. In that case, digis are already present and
+  // --- the unpacking stage must be skipped. The digis are in direct branches of the ROOT
+  // --- tree when coming from simulation, or in form of CbmDigiTimeslice if produced
+  // --- by a previous unpacking run. This variety is caught by the tasks and need not be
+  // --- considered here.
+  bool isRootInput =
+    fSourceNames.size() == 1 && fSourceNames.at(0).compare(fSourceNames.at(0).size() - 5, 5, ".root") == 0;
+
+  // --- Run instance
+  FairRunOnline run;
+
   // --- Input source
-  auto source = make_unique<CbmSourceTs>(fSourceNames);
-  if (source) LOG(info) << "Reco: Using sources " << ListSources();
+  if (isRootInput) {
+    auto source = make_unique<FairFileSource>(fSourceNames.at(0));
+    LOG(info) << "Reco: Using ROOT input " << fSourceNames.at(0);
+    run.SetSource(source.release());
+  }
   else {
-    LOG(error) << "Reco: Could not open sources " << ListSources() << "; aborting.";
-    return -1;
+    auto source = make_unique<CbmSourceTs>(fSourceNames);
+    if (source) LOG(info) << "Reco: Using sources " << ListSources();
+    else {
+      LOG(error) << "Reco: Could not open sources " << ListSources() << "; aborting.";
+      return -1;
+    }
+    run.SetSource(source.release());
   }
 
   // --- Output file
@@ -145,37 +166,36 @@ int32_t CbmReco::Run()
     LOG(error) << "Reco: Could not open output " << fOutputFileName.Data() << "; aborting.";
     return -1;
   }
+  run.SetSink(sink.release());
 
   // --- Event header
   auto header = make_unique<CbmTsEventHeader>();
+  run.SetEventHeader(header.release());
 
   // --- Unpacking
-  auto unpack = make_unique<CbmTaskUnpack>();
-  unpack->SetOutputBranchPersistent("DigiTimeslice.", fConfig.fStoreTimeslice);
+  if (!isRootInput) {
+    auto unpack = make_unique<CbmTaskUnpack>();
+    unpack->SetOutputBranchPersistent("DigiTimeslice.", fConfig.fStoreTimeslice);
+    run.AddTask(unpack.release());
+  }
 
   // --- Digi trigger
   auto trigger = make_unique<CbmTaskTriggerDigi>();
   trigger->AddSystem(fConfig.fTriggerDet);
   trigger->SetAlgoParams(fConfig.fTriggerWin, fConfig.fTriggerThreshold, fConfig.fTriggerDeadTime);
   trigger->SetOutputBranchPersistent("Trigger", fConfig.fStoreTrigger);
+  run.AddTask(trigger.release());
 
   // --- Event building
   auto evtBuild = make_unique<CbmTaskBuildEvents>();
   for (auto& entry : fConfig.fEvtbuildWindows)
     evtBuild->SetEventWindow(entry.first, entry.second.first, entry.second.second);
   evtBuild->SetOutputBranchPersistent("DigiEvent", fConfig.fStoreEvents);
+  run.AddTask(evtBuild.release());
 
   // --- Event QA
   auto evtQa = make_unique<CbmTaskDigiEventQa>();
   evtQa->Config(fConfig);
-
-  // --- Run configuration
-  FairRunOnline run(source.release());
-  run.SetSink(sink.release());
-  run.SetEventHeader(header.release());
-  run.AddTask(unpack.release());
-  run.AddTask(trigger.release());
-  run.AddTask(evtBuild.release());
   run.AddTask(evtQa.release());
 
   // ----- HttpServer for online monitoring
@@ -204,9 +224,13 @@ int32_t CbmReco::Run()
 
   // --- Run log
   std::cout << std::endl;
-  auto src = dynamic_cast<CbmSourceTs*>(run.GetSource());
-  assert(src);
-  size_t numTs     = src->GetNumTs();
+  size_t numTs = 1;
+  if (!isRootInput) {
+    auto src = dynamic_cast<CbmSourceTs*>(run.GetSource());
+    assert(src);
+    numTs = src->GetNumTs();
+  }
+  // TODO: Don't know how to get the number of processed timeslices for ROOT input.
   double timeTotal = timeSetup + timeInit + timeRun;
   LOG(info) << "=====================================";
   LOG(info) << "Reco: Run summary";
-- 
GitLab