From 1d24bf713d2f7ea9c92b0fae8c1cdeeff0da6b45 Mon Sep 17 00:00:00 2001
From: Chris Jones <jonesc@hep.phy.cam.ac.uk>
Date: Tue, 31 Oct 2023 11:54:25 +0000
Subject: [PATCH] DecodedDataFromMCRichHits: Add 0-25 time window, option to
 reject scintillation

---
 .../component/DecodedDataFromMCRichHits.cpp   | 92 ++++++++++++-------
 1 file changed, 57 insertions(+), 35 deletions(-)

diff --git a/Rich/RichFutureMCUtils/src/component/DecodedDataFromMCRichHits.cpp b/Rich/RichFutureMCUtils/src/component/DecodedDataFromMCRichHits.cpp
index d8067b837c8..ac7ce7f6c4c 100644
--- a/Rich/RichFutureMCUtils/src/component/DecodedDataFromMCRichHits.cpp
+++ b/Rich/RichFutureMCUtils/src/component/DecodedDataFromMCRichHits.cpp
@@ -9,6 +9,10 @@
 * or submit itself to any jurisdiction.                                       *
 \*****************************************************************************/
 
+// Gaudi (must be first)
+#include "GaudiKernel/ParsersFactory.h"
+#include "GaudiKernel/StdArrayAsProperty.h"
+
 // Rich (Future) Kernel
 #include "RichFutureKernel/RichAlgBase.h"
 
@@ -68,7 +72,8 @@ namespace Rich::Future::MC {
       auto&   summaries    = std::get<LHCb::MCRichDigitSummarys>( out_data );
 
       // map from Smart ID to associated MC hits
-      std::unordered_map<LHCb::RichSmartID, std::vector<LHCb::MCRichHit*>> hitsPerPix;
+      using HitData = std::pair<const LHCb::MCRichHit*, double>;
+      std::unordered_map<LHCb::RichSmartID, std::vector<HitData>> hitsPerPix;
 
       // Get the location of the container of an MC hit in the TES
       auto hitLocation = [&]( const auto* obj ) { return ( obj ? objectLocation( obj->parent() ) : "Not Contained" ); };
@@ -77,20 +82,16 @@ namespace Rich::Future::MC {
       auto getTime = [&]( const auto* mchit ) {
         if ( !mchit ) { return 0.0; }
         // Deduce if this is a spillover event and if it is apply offset
-        const auto loc         = hitLocation( mchit );
-        double     spillOffset = 0.0;
-        if ( loc.find( "PrevPrev" ) != std::string::npos ) {
-          spillOffset = -50.0;
-        } else if ( loc.find( "Prev" ) != std::string::npos ) {
-          spillOffset = -25.0;
-        } else if ( loc.find( "NextNext" ) != std::string::npos ) {
-          spillOffset = 50.0;
-        } else if ( loc.find( "Next" ) != std::string::npos ) {
-          spillOffset = 25.0;
-        }
-        _ri_verbo << "Loc " << loc << " " << spillOffset << endmsg;
-        // return offset + TOF
-        return spillOffset + mchit->timeOfFlight();
+        const auto   loc         = hitLocation( mchit );
+        const double spillOffset =                                             //
+            ( ( loc.find( "PrevPrev" ) != std::string::npos ) ? -50.0 :        //
+                  ( loc.find( "Prev" ) != std::string::npos ) ? -25.0 :        //
+                      ( loc.find( "NextNext" ) != std::string::npos ) ? 50.0 : //
+                          ( loc.find( "Next" ) != std::string::npos ) ? 25.0 : //
+                              0.0 );
+        const auto hitT = spillOffset + mchit->timeOfFlight();
+        _ri_verbo << "TES Location '" << loc << "' SpillOffset=" << spillOffset << " HitTime=" << hitT << endmsg;
+        return hitT;
       };
 
       // process a container of MC hits
@@ -98,14 +99,27 @@ namespace Rich::Future::MC {
         for ( const auto mchit : mchits ) {
           const auto id = mchit->sensDetID();
           if ( id.isValid() ) {
+            _ri_verbo << id << " " << mchit->mcRichDigitHistoryCode() << endmsg;
             // Apply all sorts MC based filtering here, e.g. signal only, timing windows etc.
             // To be extended as needed
-            if ( m_rejectBackground && mchit->isBackground() ) {
-              _ri_verbo << id << " Rejected as background" << endmsg;
+            if ( m_rejectAllBackgrounds && mchit->isBackground() ) {
+              _ri_verbo << " -> Rejected as background" << endmsg;
               continue;
             }
-            // finally save this id -> hit mapping
-            hitsPerPix[id].push_back( mchit );
+            if ( m_rejectScintillation && mchit->radScintillation() ) {
+              _ri_verbo << " -> Rejected as scintillation" << endmsg;
+              continue;
+            }
+            // Are we inside the 0-25 ns window ?
+            const auto hitT = getTime( mchit );
+            // time with shift for each RICH
+            const auto hitTShifted = hitT - m_timeShift[id.rich()];
+            _ri_verbo << "Shifted time = " << hitTShifted << endmsg;
+            if ( hitTShifted >= 0.0 && hitTShifted <= 25.0 ) {
+              _ri_verbo << " -> In Time" << endmsg;
+              // finally save this id -> hit mapping
+              hitsPerPix[id].emplace_back( mchit, hitT );
+            }
           } // hit is valid
         }   // mc hit loop
       };
@@ -131,6 +145,9 @@ namespace Rich::Future::MC {
       summaries.reserve( hitsPerPix.size() );
       for ( const auto& [id, hits] : hitsPerPix ) {
 
+        // Should never fail but just in case...
+        if ( hits.empty() ) { continue; }
+
         // temporary copy of SmartID
         auto newID = id;
 
@@ -151,38 +168,36 @@ namespace Rich::Future::MC {
         // Add best time for this ID
         if ( m_includeTimeInfo ) {
           // attempt to select the 'best' time for this ID ...
-          const LHCb::MCRichHit* mch = nullptr;
-          if ( !hits.empty() ) { // should never fail ...
-            mch = hits.front();
-            for ( const auto hit : hits ) {
-              if ( hit->isSignal() ) {
-                mch = hit;
-                break;
-              }
+          const auto* mch = &hits.front();
+          for ( const auto& hit : hits ) {
+            if ( hit.first->isSignal() ) {
+              mch = &hit;
+              break;
             }
           }
-          newID.setTime( getTime( mch ) );
+          newID.setTime( mch->second );
         }
 
         // Add (dd4hep corrected) ID to decoded list
         ids.emplace_back( newID );
 
         // Form MC summaries for each MCHit
-        for ( const auto hit : hits ) {
+        for ( const auto& hit : hits ) {
           auto summary = std::make_unique<LHCb::MCRichDigitSummary>();
           // do not want dd4hep corrected ID here as utility does its own correction.
           summary->setRichSmartID( id );
-          summary->setMCParticle( hit->mcParticle() );
-          auto history = hit->mcRichDigitHistoryCode();
+          summary->setMCParticle( hit.first->mcParticle() );
+          auto history = hit.first->mcRichDigitHistoryCode();
           history.setSignalEvent( true ); // normally done by Boole for signal event only
           summary->setHistory( history );
           summaries.add( summary.release() );
         }
-      }
+
+      } // loop over hits
 
       // Sort
       SmartIDSorter::sortByRegion( ids );
-      for ( const auto id : ids ) { ri_debug( id, endmsg ); }
+      // for ( const auto id : ids ) { ri_debug( id, endmsg ); }
 
       // fill decoded data structure
       decoded_data.addSmartIDs( ids );
@@ -213,11 +228,18 @@ namespace Rich::Future::MC {
     /// Include time information in the decoded data
     Gaudi::Property<bool> m_includeTimeInfo{this, "IncludeTimeInfo", true};
 
-    /// Reject background hits
-    Gaudi::Property<bool> m_rejectBackground{this, "RejectBackground", false};
+    /// Reject all background hits
+    Gaudi::Property<bool> m_rejectAllBackgrounds{this, "RejectAllBackgrounds", false};
+
+    /// Reject scintillation hits
+    Gaudi::Property<bool> m_rejectScintillation{this, "RejectScintillation", false};
 
     /// Include spillover events
     Gaudi::Property<bool> m_enableSpillover{this, "EnableSpillover", true};
+
+    /// Time window shift for each RICH
+    Gaudi::Property<DetectorArray<double>> m_timeShift{
+        this, "TimeCalib", {0., 40.}, "Global time shift for each RICH, to get both to same calibrated point"};
   };
 
   // Declaration of the Algorithm Factory
-- 
GitLab