From 4821ecb4d2c0bf3f548fec6da85d7db38e9f368b Mon Sep 17 00:00:00 2001
From: FASER Reco <faserrec@lxplus764.cern.ch>
Date: Sat, 25 Nov 2023 04:25:16 +0100
Subject: [PATCH] Updates for backward tracking

---
 .../Reconstruction/scripts/faser_reco.py           | 14 +++++++++++++-
 .../NtupleDumper/scripts/faser_ntuple_maker.py     |  5 ++++-
 .../scripts/submit_faser_ntuple_maker.sh           |  7 ++++++-
 .../NtupleDumper/src/NtupleDumperAlg.cxx           |  4 +++-
 PhysicsAnalysis/NtupleDumper/src/NtupleDumperAlg.h |  3 ++-
 Tracking/Acts/FaserActsKalmanFilter/src/CKF2.cxx   |  2 ++
 6 files changed, 30 insertions(+), 5 deletions(-)

diff --git a/Control/CalypsoExample/Reconstruction/scripts/faser_reco.py b/Control/CalypsoExample/Reconstruction/scripts/faser_reco.py
index 5f1af19df..2235e03d1 100755
--- a/Control/CalypsoExample/Reconstruction/scripts/faser_reco.py
+++ b/Control/CalypsoExample/Reconstruction/scripts/faser_reco.py
@@ -243,13 +243,25 @@ if useCKF:
 
     #
     # Kalman Filter for tracking
+
+    # Do both forward and backward tracking
     from FaserActsKalmanFilter.CKF2Config import CKF2Cfg
     if not args.isOverlay:
+        # 4-station tracks
         acc.merge(CKF2Cfg(ConfigFlags, noDiagnostics=True))
 
     # Add tracking collection with no IFT 
     acc.merge(CKF2Cfg(ConfigFlags, maskedLayers=[0, 1, 2], name="CKF_woIFT", 
-                      OutputCollection="CKFTrackCollectionWithoutIFT", noDiagnostics=True))
+                      OutputCollection="CKFTrackCollectionWithoutIFT", 
+                      BackwardPropagation=False,
+                      noDiagnostics=True))
+
+
+    # Backward tracking with no IFT
+    acc.merge(CKF2Cfg(ConfigFlags, maskedLayers=[0, 1, 2], name="CKF_Back_woIFT", 
+                      OutputCollection="CKFTrackCollectionBackwardWithoutIFT", 
+                      BackwardPropagation=True,
+                      noDiagnostics=True))
 
 #
 # Configure output
diff --git a/PhysicsAnalysis/NtupleDumper/scripts/faser_ntuple_maker.py b/PhysicsAnalysis/NtupleDumper/scripts/faser_ntuple_maker.py
index f98772332..8020e7ba1 100755
--- a/PhysicsAnalysis/NtupleDumper/scripts/faser_ntuple_maker.py
+++ b/PhysicsAnalysis/NtupleDumper/scripts/faser_ntuple_maker.py
@@ -53,6 +53,8 @@ parser.add_argument("--scintFilt", action='store_true',
                     help="apply scintillator event filter")
 parser.add_argument("--NoTrackFilt", action='store_true',
                     help="Don't apply track event filter (default: do)")
+parser.add_argument("--noStable", action='store_true',
+                    help="Don't apply stable beam requirement (default: do)")
 
 parser.add_argument("--unblind", action='store_true',
                     help="Don't apply signal blinding (default: do)")
@@ -218,6 +220,7 @@ print(f"Scintillator Filter  = {args.scintFilt}")
 print(f"Track Filter = {not args.NoTrackFilt}")
 print(f"Blind = {not args.unblind}")
 print(f"OnlyBlinded = {args.onlyblind}")
+print(f"Stable Beams = {not args.noStable}")
 print(f"GRL = {args.grl}")
 
 # OK, lets run the job here
@@ -276,7 +279,7 @@ if args.isMC:
     acc.merge(NtupleDumperAlgCfg(ConfigFlags, outfile, **mc_kwargs))
 
 else:
-    acc.merge(NtupleDumperAlgCfg(ConfigFlags, outfile, DoBlinding=(not args.unblind), OnlyBlinded=args.onlyblind, DoScintFilter = args.scintFilt, DoTrackFilter = (not args.NoTrackFilt), DoTrigFilter = args.trigFilt, **grl_kwargs))
+    acc.merge(NtupleDumperAlgCfg(ConfigFlags, outfile, DoBlinding=(not args.unblind), OnlyBlinded=args.onlyblind, DoScintFilter = args.scintFilt, DoTrackFilter = (not args.NoTrackFilt), DoTrigFilter = args.trigFilt, StableOnly = (not args.noStable), **grl_kwargs) )
 
 if not args.verbose:
     from AthenaConfiguration.ComponentFactory import CompFactory
diff --git a/PhysicsAnalysis/NtupleDumper/scripts/submit_faser_ntuple_maker.sh b/PhysicsAnalysis/NtupleDumper/scripts/submit_faser_ntuple_maker.sh
index 01fe05f49..d50950316 100755
--- a/PhysicsAnalysis/NtupleDumper/scripts/submit_faser_ntuple_maker.sh
+++ b/PhysicsAnalysis/NtupleDumper/scripts/submit_faser_ntuple_maker.sh
@@ -35,6 +35,7 @@ mergestr=""
 flukastr=""
 geniestr=""
 unblindstr=""
+stablestr=""
 #
 # Parse command-line options
 while [ -n "$1" ]
@@ -76,6 +77,10 @@ do
 	  unblindstr="--unblind";
 	  shift;;
 
+      --no_stable)
+	  stablestr="--noStable";
+	  shift;;
+
       --) # End of options
 	  shift; # Eat this
 	  break;; # And stop parsing
@@ -258,7 +263,7 @@ export EOS_MGM_URL=root://eospublic.cern.ch
 #
 # Run job
 #
-faser_ntuple_maker.py $last_file_str $partialstr $tagstr $ismc --slice $slice --files $nfiles $mergestr $flukastr $geniestr $unblindstr $dir_path
+faser_ntuple_maker.py $last_file_str $partialstr $tagstr $ismc --slice $slice --files $nfiles $mergestr $flukastr $geniestr $unblindstr $stablestr $dir_path
 ntup_code=$?
 echo "Return code: $ntup_code"
 #
diff --git a/PhysicsAnalysis/NtupleDumper/src/NtupleDumperAlg.cxx b/PhysicsAnalysis/NtupleDumper/src/NtupleDumperAlg.cxx
index 0e88d1e46..a7b7d434a 100644
--- a/PhysicsAnalysis/NtupleDumper/src/NtupleDumperAlg.cxx
+++ b/PhysicsAnalysis/NtupleDumper/src/NtupleDumperAlg.cxx
@@ -621,8 +621,10 @@ StatusCode NtupleDumperAlg::execute(const EventContext &ctx) const
     // load in LHC data
     SG::ReadHandle<xAOD::FaserLHCData> lhcData { m_lhcData, ctx };
     ATH_CHECK(lhcData.isValid());
+
     // don't process events that were not taken during "Stable Beams"
-    if ( !(lhcData->stableBeams()) ) return StatusCode::SUCCESS;
+    if (!(lhcData->stableBeams()) && m_stableOnly) return StatusCode::SUCCESS;
+
     // store interesting data in ntuple variables
     m_fillNumber = lhcData->fillNumber();
     m_betaStar = lhcData->betaStar();
diff --git a/PhysicsAnalysis/NtupleDumper/src/NtupleDumperAlg.h b/PhysicsAnalysis/NtupleDumper/src/NtupleDumperAlg.h
index a741bcbe5..c30d24650 100644
--- a/PhysicsAnalysis/NtupleDumper/src/NtupleDumperAlg.h
+++ b/PhysicsAnalysis/NtupleDumper/src/NtupleDumperAlg.h
@@ -114,7 +114,8 @@ private:
   BooleanProperty m_onlyBlinded          { this, "OnlyBlinded", false, "Only events that would be blinded are saved" };
   BooleanProperty m_doTrigFilter         { this, "DoTrigFilter", false, "Only events that pass trigger cuts are passed" };
   BooleanProperty m_doScintFilter        { this, "DoScintFilter", false, "Only events that pass scintillator coincidence cuts are passed" };
-  BooleanProperty m_doTrackFilter        { this, "DoTrackFilter", true, "Only events that have >= 1 long track are passed, also non-colliding events with a track or calo signal are passed" };
+  BooleanProperty m_doTrackFilter        { this, "DoTrackFilter", true, "Only events that have >= 1 long track are passed, also non-colliding events with a track or calo signal are passed (default)" };
+  BooleanProperty m_stableOnly           { this, "StableOnly", true, "Only events recorded during stable beams are saved (default)" };
 
   BooleanProperty m_useFlukaWeights      { this, "UseFlukaWeights", false, "Flag to weight events according to value stored in HepMC::GenEvent" };
   BooleanProperty m_useGenieWeights      { this, "UseGenieWeights", false, "Flag to weight events according to Genie luminosity" };
diff --git a/Tracking/Acts/FaserActsKalmanFilter/src/CKF2.cxx b/Tracking/Acts/FaserActsKalmanFilter/src/CKF2.cxx
index 57d78d9d5..87380dd7e 100644
--- a/Tracking/Acts/FaserActsKalmanFilter/src/CKF2.cxx
+++ b/Tracking/Acts/FaserActsKalmanFilter/src/CKF2.cxx
@@ -73,6 +73,7 @@ StatusCode CKF2::initialize() {
   } else {
     m_logger = Acts::getDefaultLogger("KalmanFitter", Acts::Logging::INFO);
   }
+
   return StatusCode::SUCCESS;
 }
 
@@ -279,6 +280,7 @@ StatusCode CKF2::execute() {
 
 StatusCode CKF2::finalize() {
   ATH_MSG_INFO("CombinatorialKalmanFilterAlg::finalize()");
+  ATH_MSG_INFO("BackwardPropagation: " << m_backwardPropagation);
   ATH_MSG_INFO(m_numberOfEvents << " events processed.");
   ATH_MSG_INFO(m_numberOfTrackSeeds << " seeds.");
   ATH_MSG_INFO(m_numberOfFittedTracks << " fitted tracks.");
-- 
GitLab