From 1d115258436760549698bfc204a81a2209f7082f Mon Sep 17 00:00:00 2001
From: Ben Rosser <bjr@sas.upenn.edu>
Date: Fri, 21 Mar 2025 04:50:33 -0500
Subject: [PATCH 1/4] FPGATrackSim: rewrite matrix gen algorithm to use
 road-finding for hit selection

Previously we would first filter the hits that matched a truth track according to some
internal rules. This commit changes things so that instead we do not do this; we just
pass the barcode-matched hits immediately to pattern recognition.

Then, we use a version of the "road to track" code to produce track combinations if
we are running the first stage; if we're running the second stage we run the full
track fit. The hits on the track combinations then get used to fill the accumulator.

This doesn't actually work at present, the road to track is not producing any roads.
That requires further investigation
---
 .../python/FPGATrackSimBankGenConfig.py       |  12 +-
 .../src/FPGATrackSimMatrixGenAlgo.cxx         | 288 +++++++++++-------
 .../src/FPGATrackSimMatrixGenAlgo.h           |   2 +-
 .../src/FPGATrackSimRegionMap.cxx             |  12 +-
 4 files changed, 199 insertions(+), 115 deletions(-)

diff --git a/Trigger/EFTracking/FPGATrackSim/FPGATrackSimBankGen/python/FPGATrackSimBankGenConfig.py b/Trigger/EFTracking/FPGATrackSim/FPGATrackSimBankGen/python/FPGATrackSimBankGenConfig.py
index cea3732b7de6..880a81829114 100755
--- a/Trigger/EFTracking/FPGATrackSim/FPGATrackSimBankGen/python/FPGATrackSimBankGenConfig.py
+++ b/Trigger/EFTracking/FPGATrackSim/FPGATrackSimBankGen/python/FPGATrackSimBankGenConfig.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
+# Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
 '''
 @file FPGATrackSimBankGenConfig.py
 @author Riley Xu - rixu@cern.ch
@@ -6,12 +6,10 @@
 @brief This file declares functions to configure components in FPGATrackSimBankGen
 '''
 
-# Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
-
 from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
 from AthenaConfiguration.ComponentFactory import CompFactory
 from FPGATrackSimConfTools.FPGATrackSimAnalysisConfig import FPGATrackSimRoadUnionToolCfg,FPGATrackSimRoadUnionTool1DCfg,FPGATrackSimRoadUnionToolGenScanCfg
-from FPGATrackSimConfTools.FPGATrackSimDataPrepConfig import FPGATrackSimRawLogicCfg, FPGATrackSimMappingCfg
+from FPGATrackSimConfTools.FPGATrackSimDataPrepConfig import FPGATrackSimRawLogicCfg, FPGATrackSimMappingCfg, FPGATrackSimEventSelectionCfg
 from AthenaCommon.SystemOfUnits import GeV
 
 
@@ -69,6 +67,7 @@ def FPGATrackSimBankGenCfg(flags, **kwargs):
     theFPGATrackSimMatrixGenAlg.SpacePointTool = acc.getPrimaryAndMerge(FPGATrackSimSpacePointsToolCfg(flags))
     theFPGATrackSimMatrixGenAlg.minSpacePlusPixel = flags.Trigger.FPGATrackSim.minSpacePlusPixel
 
+    theFPGATrackSimMatrixGenAlg.FPGATrackSimEventSelectionSvc = acc.getPrimaryAndMerge(FPGATrackSimEventSelectionCfg(flags))
     theFPGATrackSimMatrixGenAlg.FPGATrackSimMappingSvc = acc.getPrimaryAndMerge(FPGATrackSimMappingCfg(flags))
 
     if (flags.Trigger.FPGATrackSim.ActiveConfig.secondStage):
@@ -136,6 +135,11 @@ if __name__ == "__main__":
     from AthenaConfiguration.Utils import setupLoggingLevels
     setupLoggingLevels(flags, acc)
 
+    acc.foreach_component("FPGATrackSim*").OutputLevel=flags.Trigger.FPGATrackSim.loglevel
+    if flags.Trigger.FPGATrackSim.msgLimit!=-1:
+        acc.getService("MessageSvc").debugLimit = flags.Trigger.FPGATrackSim.msgLimit
+        acc.getService("MessageSvc").infoLimit = flags.Trigger.FPGATrackSim.msgLimit
+
     MatrixFileName="matrix.root"
     acc.addService(CompFactory.THistSvc(Output = ["TRIGFPGATrackSimMATRIXOUT DATAFILE='"+MatrixFileName+"', OPT='RECREATE'"]))
 
diff --git a/Trigger/EFTracking/FPGATrackSim/FPGATrackSimBankGen/src/FPGATrackSimMatrixGenAlgo.cxx b/Trigger/EFTracking/FPGATrackSim/FPGATrackSimBankGen/src/FPGATrackSimMatrixGenAlgo.cxx
index 57eda2dfc949..c438bcc000c0 100755
--- a/Trigger/EFTracking/FPGATrackSim/FPGATrackSimBankGen/src/FPGATrackSimMatrixGenAlgo.cxx
+++ b/Trigger/EFTracking/FPGATrackSim/FPGATrackSimBankGen/src/FPGATrackSimMatrixGenAlgo.cxx
@@ -226,133 +226,143 @@ StatusCode FPGATrackSimMatrixGenAlgo::execute()
     int nSlices = m_FPGATrackSimMapping->SubRegionMap()->getNRegions();
 
     // Get list of hits associated to the current truth track
-    std::vector<FPGATrackSimHit> & track_hits = barcode_hits[track.getBarcode()];
+    std::vector<FPGATrackSimHit> & sector_hits = barcode_hits[track.getBarcode()];
 
     const FPGATrackSimPlaneMap *t_pmap = nullptr;
 
     // Get the hits that will form the actual sector
 
     for (int iSlice = 0; iSlice<nSlices; iSlice++){
-      t_pmap = m_FPGATrackSimMapping->PlaneMap_1st(iSlice);
+      t_pmap = m_FPGATrackSimMapping->PlaneMap_2nd(iSlice);
       
-      for (auto & iHit : track_hits) {
+      for (auto & iHit : sector_hits) {
+        t_pmap->doRemap(iHit);
         t_pmap->map(iHit);
       }
       
-      
+      /* For now, don't do this. If we need regionalized/binned fit constants it needs to come from the road.
       std::vector<FPGATrackSimHit> sector_hits;
       bool success = filterSectorHits(track_hits, sector_hits, track, true, iSlice);
       if (!success) continue; // Skip this track if it has bad hits (not complete, etc.)
+      */
+
       m_h_trackQoP_okHits->Fill(track.getQOverPt());
+      bool success;
       
       // Get the region of this sector
-      int region = getRegion(sector_hits, true);
-      if (region < 0 || region >= m_nRegions) continue;
+      // TODO: do we need this the pattern recognition should deal with it.
+      int region = 0; //sgetRegion(sector_hits, false);
+      //if (region < 0 || region >= m_nRegions) continue;
       m_h_trackQoP_okRegion->Fill(track.getQOverPt());
+
       //For the Hough constants, find the Hough roads
       std::vector<std::shared_ptr<const FPGATrackSimRoad>> houghRoads;
       if (m_doHoughConstants){
-	
-	std::vector<std::shared_ptr<const FPGATrackSimHit>> phits;
-	
-	for (const FPGATrackSimHit& hit : sector_hits) if (hit.isMapped() && hit.isReal()) phits.emplace_back(std::make_shared<const FPGATrackSimHit>(hit));
-	StatusCode sc = m_roadFinderTool->getRoads(phits, houghRoads);
-	if (sc.isFailure()) ATH_MSG_WARNING("Hough Transform -> getRoads() failed");
-	if (m_doSecondStage) { // if doing 2nd stage, we want to get tracks from the road and then do tracking and overlap removal
-
-	  /// map hits as 2nd stage
-	  const FPGATrackSimPlaneMap *pmap_2nd = m_FPGATrackSimMapping->PlaneMap_2nd(iSlice);
-	  for (auto & iHit : track_hits) {
-	    pmap_2nd->map(iHit);
-	  }
-
-	  std::vector<FPGATrackSimTrack> tracks_1st;
-	  ATH_CHECK(m_trackFitterTool_1st->getTracks(houghRoads, tracks_1st));
-	  ATH_CHECK(m_overlapRemovalTool->runOverlapRemoval(tracks_1st));
-	  // Prepare the accumulator struct
-	  std::vector<module_t> modules(m_nLayers_2nd);
-	  FPGATrackSimMatrixAccumulator acc(m_nLayers_2nd, m_nDim_2nd);	
-	  std::vector<FPGATrackSimHit> hits_2nd;
-	  std::vector<std::shared_ptr<const FPGATrackSimHit>> phits_2nd;
-	  success = filterSectorHits(track_hits, hits_2nd, track, false, iSlice); // only look at 2nd stage hits!
-	  
-	  
-	  if (!success) continue; // Skip this track if it has bad hits (not complete, etc.)
-	  // awkward fixme
-	  for (const auto& hit : hits_2nd) {
-	    phits_2nd.push_back(std::make_shared<const FPGATrackSimHit>(hit));
-	  }
-	  
-	  // Use the track extension tool to actually produce a new set of roads.
-	  std::vector<std::shared_ptr<const FPGATrackSimRoad>> roads_2nd;
-	  std::vector<std::shared_ptr<const FPGATrackSimTrack>> ptracks_1st;
-	  ptracks_1st.reserve(tracks_1st.size());
-	  for (const auto& track : tracks_1st) {
-	    ptracks_1st.push_back(std::make_shared<const FPGATrackSimTrack>(track));
-	  }
-	  ATH_CHECK(m_trackExtensionTool->extendTracks(phits_2nd, ptracks_1st, roads_2nd));
-	  for (auto road_2nd : roads_2nd) {
-	    std::vector<module_t> modules(m_nLayers_2nd);
-	    FPGATrackSimMatrixAccumulator acc(m_nLayers_2nd, m_nDim_2nd);
-	    acc.pars.qOverPt = road_2nd->getY();
-	    acc.pars.phi = road_2nd->getX();
-	    
-	    std::pair<std::vector<module_t>, FPGATrackSimMatrixAccumulator> modules_acc = {modules, acc};
-	    std::vector<std::shared_ptr<const FPGATrackSimHit>> phits;
-	    ATH_CHECK(makeAccumulator(hits_2nd, track, modules_acc));
-	    
-	    // Add the track to the accumulate map
-	    accumulate(m_sector_cum[region], modules_acc.first, modules_acc.second);
-	    
-	    if (m_dropHitsAndFill)
-	      ATH_CHECK(fillAccumulatorByDropping(hits_2nd, false, acc.pars.phi, acc.pars.qOverPt, modules, m_sector_cum[region], track, iSlice));
-	    
-	    m_nTracksUsed++;
-	  }
-	}
-	else {	
-	  //For each Hough road, make the accumulator
-	  if (!houghRoads.empty()){
-	    double y = 0.0;
-	    double x = 0.0;
-	    
-	    //For each Hough road, make the accumulator
-	    for (auto const &hr : houghRoads){
-	      y = hr->getY();
-	      x = hr->getX();
-	      // Prepare the accumulator struct
-	      std::vector<module_t> modules(m_nLayers_1st);
-	      FPGATrackSimMatrixAccumulator acc(m_nLayers_1st, m_nDim_1st);
-	      acc.pars.qOverPt = y;
-	      acc.pars.phi = x;
-	      std::pair<std::vector<module_t>, FPGATrackSimMatrixAccumulator> modules_acc = {modules, acc};
-	      ATH_CHECK(makeAccumulator(sector_hits, track, modules_acc));
-	      
-	      // Add the track to the accumulate map
-	      accumulate(m_sector_cum[region], modules_acc.first, modules_acc.second);
-	      
-	      if (m_dropHitsAndFill)
-		ATH_CHECK(fillAccumulatorByDropping(sector_hits, true, acc.pars.phi, acc.pars.qOverPt, modules, m_sector_cum[region], track, iSlice));	      
-	      
-	      m_nTracksUsed++;
-	    }
-	  }
-	}
+
+        std::vector<std::shared_ptr<const FPGATrackSimHit>> phits;
+
+        ATH_MSG_INFO("Starting from some number of sector hits = " << sector_hits.size());
+        for (const FPGATrackSimHit& hit : sector_hits) if (hit.isMapped() && hit.isReal()) phits.emplace_back(std::make_shared<const FPGATrackSimHit>(hit));
+        ATH_MSG_INFO("Passing nhits = " << phits.size() << " to road finder");
+        StatusCode sc = m_roadFinderTool->getRoads(phits, houghRoads, truth_tracks);
+        if (sc.isFailure()) ATH_MSG_WARNING("Hough Transform -> getRoads() failed");
+
+        ATH_MSG_INFO("We found " << houghRoads.size() << " roads");
+
+        // We now want to just form the accumulator for any valid combination of hits
+        // In first stage mode we'll make the track fitter just generate combinations
+        std::vector<FPGATrackSimTrack> tracks_1st;
+        if (m_doSecondStage) {
+          ATH_CHECK(m_trackFitterTool_1st->getTracks(houghRoads, tracks_1st));
+          ATH_CHECK(m_overlapRemovalTool->runOverlapRemoval(tracks_1st));
+        } else {
+          roadsToTrack(houghRoads, tracks_1st);
+          ATH_MSG_INFO("We found " << tracks_1st.size() << " combinations");
+        }
+        for (const auto& track_comb : tracks_1st) {
+          std::vector<FPGATrackSimHit> track_hits = track_comb.getFPGATrackSimHits();
+
+          if (m_doSecondStage) { // if doing 2nd stage, we want to get tracks from the road and then do tracking and overlap removal
+
+            // Prepare the accumulator struct
+            std::vector<module_t> modules(m_nLayers_2nd);
+            FPGATrackSimMatrixAccumulator acc(m_nLayers_2nd, m_nDim_2nd);
+            std::vector<FPGATrackSimHit> hits_2nd;
+            std::vector<std::shared_ptr<const FPGATrackSimHit>> phits_2nd;
+
+            // This will need updating once we have the second stage working again.
+            success = filterSectorHits(track_hits, hits_2nd, track, false, iSlice); // only look at 2nd stage hits!
+
+
+            if (!success) continue; // Skip this track if it has bad hits (not complete, etc.)
+            // awkward fixme
+            for (const auto& hit : hits_2nd) {
+              phits_2nd.push_back(std::make_shared<const FPGATrackSimHit>(hit));
+            }
+
+            // Use the track extension tool to actually produce a new set of roads.
+            std::vector<std::shared_ptr<const FPGATrackSimRoad>> roads_2nd;
+            std::vector<std::shared_ptr<const FPGATrackSimTrack>> ptracks_1st;
+            ptracks_1st.reserve(tracks_1st.size());
+            for (const auto& track : tracks_1st) {
+              ptracks_1st.push_back(std::make_shared<const FPGATrackSimTrack>(track));
+            }
+            ATH_CHECK(m_trackExtensionTool->extendTracks(phits_2nd, ptracks_1st, roads_2nd));
+            for (auto road_2nd : roads_2nd) {
+              std::vector<module_t> modules(m_nLayers_2nd);
+              FPGATrackSimMatrixAccumulator acc(m_nLayers_2nd, m_nDim_2nd);
+              acc.pars.qOverPt = road_2nd->getY();
+              acc.pars.phi = road_2nd->getX();
+
+              std::pair<std::vector<module_t>, FPGATrackSimMatrixAccumulator> modules_acc = {modules, acc};
+              std::vector<std::shared_ptr<const FPGATrackSimHit>> phits;
+              ATH_CHECK(makeAccumulator(hits_2nd, track, modules_acc));
+
+              // Add the track to the accumulate map
+              accumulate(m_sector_cum[region], modules_acc.first, modules_acc.second);
+
+              if (m_dropHitsAndFill)
+                ATH_CHECK(fillAccumulatorByDropping(hits_2nd, false, acc.pars.phi, acc.pars.qOverPt, modules, m_sector_cum[region], track, iSlice));
+
+              m_nTracksUsed++;
+            }
+          }
+          else {
+            // For each track combination (from a Hough road)
+            double y = track_comb.getHoughY();
+            double x = track_comb.getHoughX();
+            // Prepare the accumulator struct
+            std::vector<module_t> modules(m_nLayers_1st);
+            FPGATrackSimMatrixAccumulator acc(m_nLayers_1st, m_nDim_1st);
+            acc.pars.qOverPt = y;
+            acc.pars.phi = x;
+            std::pair<std::vector<module_t>, FPGATrackSimMatrixAccumulator> modules_acc = {modules, acc};
+            ATH_CHECK(makeAccumulator(track_hits, track, modules_acc));
+
+            // Add the track to the accumulate map
+            accumulate(m_sector_cum[region], modules_acc.first, modules_acc.second);
+
+            if (m_dropHitsAndFill)
+              ATH_CHECK(fillAccumulatorByDropping(track_hits, true, acc.pars.phi, acc.pars.qOverPt, modules, m_sector_cum[region], track, iSlice));
+
+            m_nTracksUsed++;
+          }
+        }
       }
       else{
-	// Prepare the accumulator struct
-	std::vector<module_t> modules(m_nLayers_1st);
-	FPGATrackSimMatrixAccumulator acc(m_nLayers_1st, m_nDim_1st);
-	std::pair<std::vector<module_t>, FPGATrackSimMatrixAccumulator> modules_acc = {modules, acc};
-	ATH_CHECK(makeAccumulator(sector_hits, track, modules_acc));
-	
-	// Add the track to the accumulate map
-	accumulate(m_sector_cum[region], modules_acc.first, modules_acc.second);      
-	
-	if (m_dropHitsAndFill)
-	  ATH_CHECK(fillAccumulatorByDropping(sector_hits, true, acc.pars.phi, acc.pars.qOverPt, modules, m_sector_cum[region], track, iSlice));
-	
-	m_nTracksUsed++;
+        // Prepare the accumulator struct
+        std::vector<module_t> modules(m_nLayers_1st);
+        FPGATrackSimMatrixAccumulator acc(m_nLayers_1st, m_nDim_1st);
+        std::pair<std::vector<module_t>, FPGATrackSimMatrixAccumulator> modules_acc = {modules, acc};
+        ATH_CHECK(makeAccumulator(sector_hits, track, modules_acc));
+
+        // Add the track to the accumulate map
+        accumulate(m_sector_cum[region], modules_acc.first, modules_acc.second);
+
+        if (m_dropHitsAndFill)
+          ATH_CHECK(fillAccumulatorByDropping(sector_hits, true, acc.pars.phi, acc.pars.qOverPt, modules, m_sector_cum[region], track, iSlice));
+
+        m_nTracksUsed++;
       }
     }
   }
@@ -360,6 +370,71 @@ StatusCode FPGATrackSimMatrixGenAlgo::execute()
   return StatusCode::SUCCESS;
 }
 
+// Adapted from TrackFitter, but TrackFitter *depends* on fit constants and this algorithm
+void FPGATrackSimMatrixGenAlgo::roadsToTrack(std::vector<std::shared_ptr<const FPGATrackSimRoad>>& houghRoads, std::vector<FPGATrackSimTrack>& track_cands)
+{
+    for (const std::shared_ptr<const FPGATrackSimRoad>& road : houghRoads) {
+
+      FPGATrackSimTrack temp;
+      temp.setNLayers(m_FPGATrackSimMapping->PlaneMap_1st(0)->getNLogiLayers());
+      temp.setBankID(-1);
+      temp.setPatternID(road->getPID());
+      temp.setHoughX(road->getX());
+      temp.setHoughY(road->getY());
+      temp.setQOverPt(road->getY());
+
+      temp.setSubRegion(road->getSubRegion());
+      temp.setHoughXBin(road->getXBin());
+      temp.setHoughYBin(road->getYBin());
+
+      // This comes from FPGATrackSimFunctions
+      std::vector<std::vector<int>> combs = getComboIndices(road->getNHits_layer());
+      unsigned existing_size = track_cands.size();
+      track_cands.resize(existing_size + combs.size(), temp);
+
+      //get the WC hits:
+      layer_bitmask_t wcbits= road->getWCLayers();
+      // Add the hits from each combination to the track, and set ID
+      for (size_t icomb = 0; icomb < combs.size(); icomb++)
+      {
+        track_cands[existing_size + icomb].setNLayers(m_FPGATrackSimMapping->PlaneMap_1st(0)->getNLogiLayers());
+        std::vector<int> const & hit_indices = combs[icomb]; // size nLayers
+        for (unsigned layer = 0; layer < m_FPGATrackSimMapping->PlaneMap_1st(0)->getNLogiLayers(); layer++)
+        {
+            if (hit_indices[layer] < 0) // Set a dummy hit if road has no hits in this layer
+            {
+                FPGATrackSimHit newhit=FPGATrackSimHit();
+                newhit.setLayer(layer);
+                newhit.setSection(0);
+                if (m_FPGATrackSimMapping->PlaneMap_1st(0)->getDim(layer) == 2) newhit.setDetType(SiliconTech::pixel);
+                    else newhit.setDetType(SiliconTech::strip);
+
+                if (wcbits & (1 << layer ) ) {
+                    newhit.setHitType(HitType::wildcard);
+                    newhit.setLayer(layer);
+                }
+
+                track_cands[existing_size + icomb].setFPGATrackSimHit(layer, newhit);
+            }
+            else
+            {
+                const std::shared_ptr<const FPGATrackSimHit> hit = road->getHits(layer)[hit_indices[layer]];
+                // If this is an outer spacepoint, and it is not the same as the inner spacepoint, reject it.
+                // Here we "reject" it by marking the candidate as "invalid", to be rejected later.
+                // That require another field on the track object, but it avoids having to change the sizes
+                // of arrays computed above.
+                if (hit->getHitType() == HitType::spacepoint && (hit->getPhysLayer() % 2) == 1) {
+                    const FPGATrackSimHit inner_hit = track_cands[existing_size + icomb].getFPGATrackSimHits().at(layer - 1);
+                    if ((hit->getX() != inner_hit.getX()) || (hit->getY() != inner_hit.getY()) || (hit->getZ() != inner_hit.getZ())) {
+                        track_cands[existing_size + icomb].setValidCand(false);
+                    }
+                }
+                track_cands[existing_size + icomb].setFPGATrackSimHit(layer, *hit);
+            }
+        }
+      }
+    }
+}
 
 // Converts raw hits from header into logical hits, and filters those in FPGATrackSim layers
 // Could replace this with the RawToLogical tool (but probably won't)
@@ -671,9 +746,10 @@ int FPGATrackSimMatrixGenAlgo::getRegion(std::vector<FPGATrackSimHit> const & hi
   }
 
   // For now just give preference to lowest region index for simplicity
-  for (int region = 0; region < m_nRegions; region++)
+  for (int region = 0; region < m_nRegions; region++) {
     if (region_mask[region])
       return region;
+  }
 
   return -1;
 }
diff --git a/Trigger/EFTracking/FPGATrackSim/FPGATrackSimBankGen/src/FPGATrackSimMatrixGenAlgo.h b/Trigger/EFTracking/FPGATrackSim/FPGATrackSimBankGen/src/FPGATrackSimMatrixGenAlgo.h
index fd28258437b6..d28d30acb372 100644
--- a/Trigger/EFTracking/FPGATrackSim/FPGATrackSimBankGen/src/FPGATrackSimMatrixGenAlgo.h
+++ b/Trigger/EFTracking/FPGATrackSim/FPGATrackSimBankGen/src/FPGATrackSimMatrixGenAlgo.h
@@ -159,7 +159,7 @@ class FPGATrackSimMatrixGenAlgo : public AthAlgorithm
         int getRegion(std::vector<FPGATrackSimHit> const & hits, bool is1ststage) const;
         StatusCode makeAccumulator(std::vector<FPGATrackSimHit> const & sector_hits, FPGATrackSimTruthTrack const & track, std::pair<std::vector<module_t>, FPGATrackSimMatrixAccumulator> & accumulator) const;
         StatusCode fillAccumulatorByDropping(std::vector<FPGATrackSimHit> & sector_hits, bool is1ststage, double x, double y, std::vector<module_t> &modules, AccumulateMap &map, FPGATrackSimTruthTrack const & track, int subregion) const;
-
+        void roadsToTrack(std::vector<std::shared_ptr<const FPGATrackSimRoad>>& houghRoads, std::vector<FPGATrackSimTrack>& track_cands);
   
         std::vector<TTree*> createMatrixTrees();
         void fillMatrixTrees(std::vector<TTree*> const & matrixTrees);
diff --git a/Trigger/EFTracking/FPGATrackSim/FPGATrackSimMaps/src/FPGATrackSimRegionMap.cxx b/Trigger/EFTracking/FPGATrackSim/FPGATrackSimMaps/src/FPGATrackSimRegionMap.cxx
index a1de7756d6c7..d39305d5ac55 100644
--- a/Trigger/EFTracking/FPGATrackSim/FPGATrackSimMaps/src/FPGATrackSimRegionMap.cxx
+++ b/Trigger/EFTracking/FPGATrackSim/FPGATrackSimMaps/src/FPGATrackSimRegionMap.cxx
@@ -224,14 +224,15 @@ void FPGATrackSimRegionMap::loadRadiiFile(std::string const & filepath)
 
 bool FPGATrackSimRegionMap::isInRegion(uint32_t region, const FPGATrackSimHit &hit) const
 {
-    // If the hit is unmapped, then instead of calling hit.getLayer(), use the (relevant) pmap
+    // Always assume that the hit's "layer" might not correspond to what's in the pmap
     // Also, to avoid confusion and double-counting, by convention, always use the coordinates of the inner hit
     // when testing if a spacepoint is in a (sub)region.
     uint32_t layer;
     uint32_t section;
-    if (hit.isMapped()) {
-        layer = (hit.getHitType() == HitType::spacepoint) ? hit.getPairedLayer() : hit.getLayer();
-        section = (hit.getHitType() == HitType::spacepoint) ? hit.getPairedSection() : hit.getSection();
+
+    LayerSection ls;
+    if (hit.getHitType() == HitType::spacepoint) {
+        ls = m_pmaps.at(region)->getLayerSection(hit.getPairedDetType(), hit.getPairedDetZone(), hit.getPairedPhysLayer());
     } else {
         LayerSection ls;
         if (hit.getHitType() == HitType::spacepoint) {
@@ -241,7 +242,10 @@ bool FPGATrackSimRegionMap::isInRegion(uint32_t region, const FPGATrackSimHit &h
         }
         layer = ls.layer;
         section = ls.section;
+        ls = m_pmaps.at(region)->getLayerSection(hit.getDetType(), hit.getDetectorZone(), hit.getPhysLayer());
     }
+    layer = ls.layer;
+    section = ls.section;
 
     int etamod = (hit.getHitType() == HitType::spacepoint) ? hit.getPairedEtaModule() : hit.getEtaModule();
     unsigned phimod = (hit.getHitType() == HitType::spacepoint) ? hit.getPairedPhiModule() : hit.getPhiModule();
-- 
GitLab


From 0a8296c19a65b7ba1e5f4d173714b774cc887f09 Mon Sep 17 00:00:00 2001
From: Ben Rosser <bjr@sas.upenn.edu>
Date: Fri, 21 Mar 2025 08:07:14 -0500
Subject: [PATCH 2/4] Bugfixes to make this version of matrix gen work

We also needed to set up the event selection service properly for constant generation;
otherwise it only used the old regions.
---
 .../python/FPGATrackSimBankConstGenConfig.py             | 9 +++------
 .../FPGATrackSimBankGen/src/FPGATrackSimConstGenAlgo.cxx | 1 +
 .../FPGATrackSimBankGen/src/FPGATrackSimConstGenAlgo.h   | 2 ++
 .../src/FPGATrackSimMatrixGenAlgo.cxx                    | 9 ++++-----
 .../FPGATrackSimMaps/src/FPGATrackSimRegionMap.cxx       | 1 -
 5 files changed, 10 insertions(+), 12 deletions(-)

diff --git a/Trigger/EFTracking/FPGATrackSim/FPGATrackSimBankGen/python/FPGATrackSimBankConstGenConfig.py b/Trigger/EFTracking/FPGATrackSim/FPGATrackSimBankGen/python/FPGATrackSimBankConstGenConfig.py
index cb7c80cdf44b..fab775ea96b9 100644
--- a/Trigger/EFTracking/FPGATrackSim/FPGATrackSimBankGen/python/FPGATrackSimBankConstGenConfig.py
+++ b/Trigger/EFTracking/FPGATrackSim/FPGATrackSimBankGen/python/FPGATrackSimBankConstGenConfig.py
@@ -10,6 +10,7 @@
 
 from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
 from AthenaConfiguration.ComponentFactory import CompFactory
+from FPGATrackSimConfTools.FPGATrackSimDataPrepConfig import FPGATrackSimEventSelectionCfg
 
 def FPGATrackSimConstsGenCfg(flags, **kwargs):
 
@@ -27,12 +28,8 @@ def FPGATrackSimConstsGenCfg(flags, **kwargs):
     theFPGATrackSimConstGenAlg = CompFactory.FPGATrackSimConstGenAlgo(**kwargs)
     theFPGATrackSimConstGenAlg.FPGATrackSimMappingSvc = FPGATrackSimMapping 
 
-    eventSelector = CompFactory.FPGATrackSimEventSelectionSvc()
-    eventSelector.regions = "HTT/TrigHTTMaps/V1/map_file/slices_v01_Jan21.txt"
-    eventSelector.regionID = 0
-    eventSelector.sampleType = flags.Trigger.FPGATrackSim.sampleType
-    eventSelector.withPU = False
-    acc.addService(eventSelector, create=True, primary=True)
+    # We need the "full" event selection service to be set up.
+    theFPGATrackSimConstGenAlg.FPGATrackSimEventSelectionSvc = acc.getPrimaryAndMerge(FPGATrackSimEventSelectionCfg(flags))
 
     acc.addEventAlgo(theFPGATrackSimConstGenAlg)
     return acc
diff --git a/Trigger/EFTracking/FPGATrackSim/FPGATrackSimBankGen/src/FPGATrackSimConstGenAlgo.cxx b/Trigger/EFTracking/FPGATrackSim/FPGATrackSimBankGen/src/FPGATrackSimConstGenAlgo.cxx
index 2ba8cfb844ff..daed76ac06e1 100644
--- a/Trigger/EFTracking/FPGATrackSim/FPGATrackSimBankGen/src/FPGATrackSimConstGenAlgo.cxx
+++ b/Trigger/EFTracking/FPGATrackSim/FPGATrackSimBankGen/src/FPGATrackSimConstGenAlgo.cxx
@@ -63,6 +63,7 @@ StatusCode FPGATrackSimConstGenAlgo::initialize()
     ATH_MSG_DEBUG("initialize()");
     ATH_MSG_DEBUG("Are we going to dump missing hist constants? " << m_dumpMissingHitsConstants);
     ATH_CHECK(m_FPGATrackSimMapping.retrieve());
+    ATH_CHECK(m_EvtSel.retrieve());
     m_pmap = (m_isSecondStage ? m_FPGATrackSimMapping->PlaneMap_2nd(0) : m_FPGATrackSimMapping->PlaneMap_1st(0) );
 
     ATH_CHECK(m_tHistSvc.retrieve());
diff --git a/Trigger/EFTracking/FPGATrackSim/FPGATrackSimBankGen/src/FPGATrackSimConstGenAlgo.h b/Trigger/EFTracking/FPGATrackSim/FPGATrackSimBankGen/src/FPGATrackSimConstGenAlgo.h
index 8d8c376ac760..afc195029972 100644
--- a/Trigger/EFTracking/FPGATrackSim/FPGATrackSimBankGen/src/FPGATrackSimConstGenAlgo.h
+++ b/Trigger/EFTracking/FPGATrackSim/FPGATrackSimBankGen/src/FPGATrackSimConstGenAlgo.h
@@ -30,6 +30,7 @@
 #include "FPGATrackSimObjects/FPGATrackSimTrackPars.h" //member
 #include "FPGATrackSimObjects/FPGATrackSimVectors.h" //vector2D
 #include "FPGATrackSimMaps/IFPGATrackSimMappingSvc.h"
+#include "FPGATrackSimConfTools/IFPGATrackSimEventSelectionSvc.h"
 
 #include "TMatrixDfwd.h"
 #include <string>
@@ -94,6 +95,7 @@ class FPGATrackSimConstGenAlgo : public AthAlgorithm
         // Handles
 
         ServiceHandle<IFPGATrackSimMappingSvc> m_FPGATrackSimMapping{this, "FPGATrackSimMappingSvc","FPGATrackSimMappingSvc"};
+        ServiceHandle<IFPGATrackSimEventSelectionSvc> m_EvtSel{this,"FPGATrackSimEventSelectionSvc","FPGATrackSimEventSelectionSvc"};
         ServiceHandle<ITHistSvc> m_tHistSvc{this, "THistSvc","THistSvc"};
 
         const FPGATrackSimPlaneMap* m_pmap = nullptr;
diff --git a/Trigger/EFTracking/FPGATrackSim/FPGATrackSimBankGen/src/FPGATrackSimMatrixGenAlgo.cxx b/Trigger/EFTracking/FPGATrackSim/FPGATrackSimBankGen/src/FPGATrackSimMatrixGenAlgo.cxx
index c438bcc000c0..20c614c3dca3 100755
--- a/Trigger/EFTracking/FPGATrackSim/FPGATrackSimBankGen/src/FPGATrackSimMatrixGenAlgo.cxx
+++ b/Trigger/EFTracking/FPGATrackSim/FPGATrackSimBankGen/src/FPGATrackSimMatrixGenAlgo.cxx
@@ -236,7 +236,6 @@ StatusCode FPGATrackSimMatrixGenAlgo::execute()
       t_pmap = m_FPGATrackSimMapping->PlaneMap_2nd(iSlice);
       
       for (auto & iHit : sector_hits) {
-        t_pmap->doRemap(iHit);
         t_pmap->map(iHit);
       }
       
@@ -261,13 +260,13 @@ StatusCode FPGATrackSimMatrixGenAlgo::execute()
 
         std::vector<std::shared_ptr<const FPGATrackSimHit>> phits;
 
-        ATH_MSG_INFO("Starting from some number of sector hits = " << sector_hits.size());
+        ATH_MSG_DEBUG("Starting from some number of sector hits = " << sector_hits.size());
         for (const FPGATrackSimHit& hit : sector_hits) if (hit.isMapped() && hit.isReal()) phits.emplace_back(std::make_shared<const FPGATrackSimHit>(hit));
-        ATH_MSG_INFO("Passing nhits = " << phits.size() << " to road finder");
+        ATH_MSG_DEBUG("Passing nhits = " << phits.size() << " to road finder");
         StatusCode sc = m_roadFinderTool->getRoads(phits, houghRoads, truth_tracks);
         if (sc.isFailure()) ATH_MSG_WARNING("Hough Transform -> getRoads() failed");
 
-        ATH_MSG_INFO("We found " << houghRoads.size() << " roads");
+        ATH_MSG_DEBUG("We found " << houghRoads.size() << " roads");
 
         // We now want to just form the accumulator for any valid combination of hits
         // In first stage mode we'll make the track fitter just generate combinations
@@ -277,7 +276,7 @@ StatusCode FPGATrackSimMatrixGenAlgo::execute()
           ATH_CHECK(m_overlapRemovalTool->runOverlapRemoval(tracks_1st));
         } else {
           roadsToTrack(houghRoads, tracks_1st);
-          ATH_MSG_INFO("We found " << tracks_1st.size() << " combinations");
+          ATH_MSG_DEBUG("We found " << tracks_1st.size() << " combinations");
         }
         for (const auto& track_comb : tracks_1st) {
           std::vector<FPGATrackSimHit> track_hits = track_comb.getFPGATrackSimHits();
diff --git a/Trigger/EFTracking/FPGATrackSim/FPGATrackSimMaps/src/FPGATrackSimRegionMap.cxx b/Trigger/EFTracking/FPGATrackSim/FPGATrackSimMaps/src/FPGATrackSimRegionMap.cxx
index d39305d5ac55..abb418ba82cd 100644
--- a/Trigger/EFTracking/FPGATrackSim/FPGATrackSimMaps/src/FPGATrackSimRegionMap.cxx
+++ b/Trigger/EFTracking/FPGATrackSim/FPGATrackSimMaps/src/FPGATrackSimRegionMap.cxx
@@ -234,7 +234,6 @@ bool FPGATrackSimRegionMap::isInRegion(uint32_t region, const FPGATrackSimHit &h
     if (hit.getHitType() == HitType::spacepoint) {
         ls = m_pmaps.at(region)->getLayerSection(hit.getPairedDetType(), hit.getPairedDetZone(), hit.getPairedPhysLayer());
     } else {
-        LayerSection ls;
         if (hit.getHitType() == HitType::spacepoint) {
             ls = m_pmaps.at(region)->getLayerSection(hit.getPairedDetType(), hit.getPairedDetZone(), hit.getPairedPhysLayer());
         } else {
-- 
GitLab


From e6f765f99eb113ec922e7cdd9aae33c95020ed3b Mon Sep 17 00:00:00 2001
From: Ben Rosser <bjr@sas.upenn.edu>
Date: Fri, 21 Mar 2025 08:50:31 -0500
Subject: [PATCH 3/4] Use the event selection service to veto tracks outside
 configured region

We weren't doing this before; this seems to be responsible for most of the noise
from the genscan algorithm.
---
 .../FPGATrackSimBankGen/src/FPGATrackSimMatrixGenAlgo.cxx    | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/Trigger/EFTracking/FPGATrackSim/FPGATrackSimBankGen/src/FPGATrackSimMatrixGenAlgo.cxx b/Trigger/EFTracking/FPGATrackSim/FPGATrackSimBankGen/src/FPGATrackSimMatrixGenAlgo.cxx
index 20c614c3dca3..84efd8f65c81 100755
--- a/Trigger/EFTracking/FPGATrackSim/FPGATrackSimBankGen/src/FPGATrackSimMatrixGenAlgo.cxx
+++ b/Trigger/EFTracking/FPGATrackSim/FPGATrackSimBankGen/src/FPGATrackSimMatrixGenAlgo.cxx
@@ -483,7 +483,10 @@ std::vector<FPGATrackSimTruthTrack> FPGATrackSimMatrixGenAlgo::filterTrainingTra
   for (FPGATrackSimTruthTrack const & track : truth_tracks) {
     if (HepMC::generations(&track) >= 1 || std::abs(track.getPDGCode()) != m_TRAIN_PDG) continue;
     if (std::abs(track.getD0()) > m_D0_THRESHOLD) continue;
-    
+
+    // Actually use the event selection service here to kill anything outside the region.
+    if (!(m_EvtSel->passMatching(track))) continue;
+
     double pt = TMath::Sqrt(track.getPX()*track.getPX() + track.getPY()*track.getPY());
     double pt_GeV = pt / 1000;
     
-- 
GitLab


From 5da196ce73b04991d3b75fbfdcc6d64cb0d82f59 Mon Sep 17 00:00:00 2001
From: Ben Rosser <bjr@sas.upenn.edu>
Date: Fri, 21 Mar 2025 09:26:49 -0500
Subject: [PATCH 4/4] Clean up FPGATrackSimRegionMap changes

Something went wrong when I tried to clean up this function, it was unnecessarily
redundant.
---
 .../FPGATrackSimMaps/src/FPGATrackSimRegionMap.cxx         | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/Trigger/EFTracking/FPGATrackSim/FPGATrackSimMaps/src/FPGATrackSimRegionMap.cxx b/Trigger/EFTracking/FPGATrackSim/FPGATrackSimMaps/src/FPGATrackSimRegionMap.cxx
index abb418ba82cd..c5b64de9ae47 100644
--- a/Trigger/EFTracking/FPGATrackSim/FPGATrackSimMaps/src/FPGATrackSimRegionMap.cxx
+++ b/Trigger/EFTracking/FPGATrackSim/FPGATrackSimMaps/src/FPGATrackSimRegionMap.cxx
@@ -234,13 +234,6 @@ bool FPGATrackSimRegionMap::isInRegion(uint32_t region, const FPGATrackSimHit &h
     if (hit.getHitType() == HitType::spacepoint) {
         ls = m_pmaps.at(region)->getLayerSection(hit.getPairedDetType(), hit.getPairedDetZone(), hit.getPairedPhysLayer());
     } else {
-        if (hit.getHitType() == HitType::spacepoint) {
-            ls = m_pmaps.at(region)->getLayerSection(hit.getPairedDetType(), hit.getPairedDetZone(), hit.getPairedPhysLayer());
-        } else {
-            ls = m_pmaps.at(region)->getLayerSection(hit.getDetType(), hit.getDetectorZone(), hit.getPhysLayer());
-        }
-        layer = ls.layer;
-        section = ls.section;
         ls = m_pmaps.at(region)->getLayerSection(hit.getDetType(), hit.getDetectorZone(), hit.getPhysLayer());
     }
     layer = ls.layer;
-- 
GitLab