From bc64470b0869a0f17006cd5f5be50e9763896145 Mon Sep 17 00:00:00 2001
From: Joseph Philip Surdutovich <jsurduto@login04.af.uchicago.edu>
Date: Sun, 30 Mar 2025 23:20:54 -0500
Subject: [PATCH 1/3] adding varying chi2 flag and using chi2 for new eta
 regions

---
 .../python/FPGATrackSimAnalysisConfig.py      | 1414 +++++++++--------
 .../python/FPGATrackSimConfigFlags.py         |    2 +-
 2 files changed, 722 insertions(+), 694 deletions(-)

diff --git a/Trigger/EFTracking/FPGATrackSim/FPGATrackSimConfTools/python/FPGATrackSimAnalysisConfig.py b/Trigger/EFTracking/FPGATrackSim/FPGATrackSimConfTools/python/FPGATrackSimAnalysisConfig.py
index 25d3fc9cea6c..e69d74f1ff28 100755
--- a/Trigger/EFTracking/FPGATrackSim/FPGATrackSimConfTools/python/FPGATrackSimAnalysisConfig.py
+++ b/Trigger/EFTracking/FPGATrackSim/FPGATrackSimConfTools/python/FPGATrackSimAnalysisConfig.py
@@ -1,693 +1,721 @@
-# Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
-from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
-from AthenaConfiguration.ComponentFactory import CompFactory
-from AthenaCommon.Logging import AthenaLogger
-from PathResolver import PathResolver
-import importlib
-
-log = AthenaLogger(__name__)
-
-#### Now inmport Data Prep config from other file
-from FPGATrackSimConfTools import FPGATrackSimDataPrepConfig
-from FPGATrackSimConfTools import FPGATrackSimSecondStageConfig
-
-def getNSubregions(filePath):
-    with open(PathResolver.FindCalibFile(filePath), 'r') as f:
-        fields = f.readline()
-        assert(fields.startswith('towers'))
-        n = fields.split()[1]
-        return int(n)
-    
-
-# Need to figure out if we have two output writers or somehow only one.
-def FPGATrackSimWriteOutputCfg(flags):
-    result=ComponentAccumulator()
-    FPGATrackSimWriteOutput = CompFactory.FPGATrackSimOutputHeaderTool("FPGATrackSimWriteOutput")
-    FPGATrackSimWriteOutput.InFileName = ["test.root"]
-    # RECREATE means that that this tool opens the file.
-    # HEADER would mean that something else (e.g. THistSvc) opens it and we just add the object.
-    FPGATrackSimWriteOutput.RWstatus = "HEADER"
-    FPGATrackSimWriteOutput.THistSvc = CompFactory.THistSvc()
-    result.addPublicTool(FPGATrackSimWriteOutput, primary=True)
-    return result
-
-
-
-def FPGATrackSimBankSvcCfg(flags):
-    result=ComponentAccumulator()
-    FPGATrackSimBankSvc = CompFactory.FPGATrackSimBankSvc()
-    pathBankSvc = flags.Trigger.FPGATrackSim.bankDir if flags.Trigger.FPGATrackSim.bankDir != '' else f'/eos/atlas/atlascerngroupdisk/det-htt/HTTsim/{flags.GeoModel.AtlasVersion}/21.9.16/'+FPGATrackSimDataPrepConfig.getBaseName(flags)+'/SectorBanks/'
-    pathBankSvc=PathResolver.FindCalibDirectory(pathBankSvc)
-    FPGATrackSimBankSvc.constantsNoGuess_1st = [
-        f'{pathBankSvc}corrgen_raw_8L_skipPlane0.gcon', 
-        f'{pathBankSvc}corrgen_raw_8L_skipPlane1.gcon', 
-        f'{pathBankSvc}corrgen_raw_8L_skipPlane2.gcon', 
-        f'{pathBankSvc}corrgen_raw_8L_skipPlane3.gcon', 
-        f'{pathBankSvc}corrgen_raw_8L_skipPlane4.gcon', 
-        f'{pathBankSvc}corrgen_raw_8L_skipPlane5.gcon', 
-        f'{pathBankSvc}corrgen_raw_8L_skipPlane6.gcon', 
-        f'{pathBankSvc}corrgen_raw_8L_skipPlane7.gcon']
-    FPGATrackSimBankSvc.constantsNoGuess_2nd = [
-        f'{pathBankSvc}corrgen_raw_13L_skipPlane0.gcon', 
-        f'{pathBankSvc}corrgen_raw_13L_skipPlane1.gcon', 
-        f'{pathBankSvc}corrgen_raw_13L_skipPlane2.gcon', 
-        f'{pathBankSvc}corrgen_raw_13L_skipPlane3.gcon', 
-        f'{pathBankSvc}corrgen_raw_13L_skipPlane4.gcon', 
-        f'{pathBankSvc}corrgen_raw_13L_skipPlane5.gcon', 
-        f'{pathBankSvc}corrgen_raw_13L_skipPlane6.gcon', 
-        f'{pathBankSvc}corrgen_raw_13L_skipPlane7.gcon']
-    layers="5L" if flags.Trigger.FPGATrackSim.ActiveConfig.genScan else "9L"
-    FPGATrackSimBankSvc.constants_1st = f'{pathBankSvc}corrgen_raw_{layers}_reg{flags.Trigger.FPGATrackSim.region}_checkGood1.gcon'
-    FPGATrackSimBankSvc.constants_2nd = f'{pathBankSvc}corrgen_raw_13L_reg{flags.Trigger.FPGATrackSim.region}_checkGood1.gcon'
-    FPGATrackSimBankSvc.sectorBank_1st = f'{pathBankSvc}sectorsHW_raw_{layers}_reg{flags.Trigger.FPGATrackSim.region}_checkGood1.patt'
-    FPGATrackSimBankSvc.sectorBank_2nd = f'{pathBankSvc}sectorsHW_raw_13L_reg{flags.Trigger.FPGATrackSim.region}_checkGood1.patt'
-    FPGATrackSimBankSvc.sectorSlices = f'{pathBankSvc}slices_{layers}_reg{flags.Trigger.FPGATrackSim.region}.root'
-    FPGATrackSimBankSvc.phiShift = flags.Trigger.FPGATrackSim.phiShift
-
-    # These should be configurable. The tag system needs updating though.
-    FPGATrackSimBankSvc.sectorQPtBins = [-0.001, -0.0005, 0, 0.0005, 0.001]
-    FPGATrackSimBankSvc.qptAbsBinning = False
-
-    result.addService(FPGATrackSimBankSvc, create=True, primary=True)
-    return result
-
-
-def FPGATrackSimRoadUnionToolCfg(flags):
-    result=ComponentAccumulator()
-    RF = CompFactory.FPGATrackSimRoadUnionTool()
-    
-    xBins = flags.Trigger.FPGATrackSim.ActiveConfig.xBins
-    xBufferBins = flags.Trigger.FPGATrackSim.ActiveConfig.xBufferBins
-    yBins = flags.Trigger.FPGATrackSim.ActiveConfig.yBins
-    yBufferBins = flags.Trigger.FPGATrackSim.ActiveConfig.yBufferBins
-    yMin = flags.Trigger.FPGATrackSim.ActiveConfig.qptMin
-    yMax = flags.Trigger.FPGATrackSim.ActiveConfig.qptMax
-    xMin = flags.Trigger.FPGATrackSim.ActiveConfig.phiMin
-    xMax = flags.Trigger.FPGATrackSim.ActiveConfig.phiMax
-    if (not flags.Trigger.FPGATrackSim.oldRegionDefs): ### auto-configure this
-        phiRange = FPGATrackSimDataPrepConfig.getPhiRange(flags)
-        xMin = phiRange[0]
-        xMax = phiRange[1]
-
-    xBuffer = (xMax - xMin) / xBins * xBufferBins
-    xMin = xMin - xBuffer
-    xMax = xMax +  xBuffer
-    yBuffer = (yMax - yMin) / yBins * yBufferBins
-    yMin -= yBuffer
-    yMax += yBuffer
-    tools = []
-    
-    FPGATrackSimMapping = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimMappingCfg(flags))
-    for number in range(getNSubregions(FPGATrackSimMapping.subrmap)): 
-        HoughTransform = CompFactory.FPGATrackSimHoughTransformTool("HoughTransform_0_" + str(number))
-        HoughTransform.FPGATrackSimEventSelectionSvc = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimEventSelectionCfg(flags))
-        HoughTransform.FPGATrackSimBankSvc = result.getPrimaryAndMerge(FPGATrackSimBankSvcCfg(flags))
-        HoughTransform.FPGATrackSimMappingSvc = FPGATrackSimMapping 
-        HoughTransform.combine_layers = flags.Trigger.FPGATrackSim.ActiveConfig.combineLayers 
-        HoughTransform.convSize_x = flags.Trigger.FPGATrackSim.ActiveConfig.convSizeX 
-        HoughTransform.convSize_y = flags.Trigger.FPGATrackSim.ActiveConfig.convSizeY 
-        HoughTransform.convolution = flags.Trigger.FPGATrackSim.ActiveConfig.convolution 
-        HoughTransform.d0_max = 0 
-        HoughTransform.d0_min = 0 
-        HoughTransform.fieldCorrection = flags.Trigger.FPGATrackSim.ActiveConfig.fieldCorrection
-        HoughTransform.hitExtend_x = flags.Trigger.FPGATrackSim.ActiveConfig.hitExtendX
-        HoughTransform.localMaxWindowSize = flags.Trigger.FPGATrackSim.ActiveConfig.localMaxWindowSize        
-        HoughTransform.nBins_x = xBins + 2 * xBufferBins
-        HoughTransform.nBins_y = yBins + 2 * yBufferBins
-        HoughTransform.phi_max = xMax
-        HoughTransform.phi_min = xMin
-        HoughTransform.qpT_max = yMax 
-        HoughTransform.qpT_min = yMin 
-        HoughTransform.scale = flags.Trigger.FPGATrackSim.ActiveConfig.scale
-        HoughTransform.subRegion = number
-        HoughTransform.threshold = flags.Trigger.FPGATrackSim.ActiveConfig.threshold
-        HoughTransform.traceHits = True
-        HoughTransform.IdealGeoRoads = (flags.Trigger.FPGATrackSim.ActiveConfig.IdealGeoRoads and flags.Trigger.FPGATrackSim.tracking)
-        HoughTransform.useSpacePoints = flags.Trigger.FPGATrackSim.spacePoints
-
-        tools.append(HoughTransform)
-
-    RF.tools = tools
-    result.addPublicTool(RF, primary=True)
-    return result
-
-def FPGATrackSimRoadUnionTool1DCfg(flags):
-    result=ComponentAccumulator()
-    tools = []
-    RF = CompFactory.FPGATrackSimRoadUnionTool()
-    splitpt=flags.Trigger.FPGATrackSim.Hough1D.splitpt
-    FPGATrackSimMapping = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimMappingCfg(flags))
-    for ptstep in range(splitpt):
-        qpt_min = flags.Trigger.FPGATrackSim.Hough1D.qptMin
-        qpt_max = flags.Trigger.FPGATrackSim.Hough1D.qptMax
-        lowpt = qpt_min + (qpt_max-qpt_min)/splitpt*ptstep
-        highpt = qpt_min + (qpt_max-qpt_min)/splitpt*(ptstep+1)
-        nSlice = getNSubregions(FPGATrackSimMapping.subrmap)
-        for iSlice in range(nSlice):
-            tool = CompFactory.FPGATrackSimHough1DShiftTool("Hough1DShift" + str(iSlice)+(("_pt{}".format(ptstep))  if splitpt>1 else ""))
-            tool.subRegion = iSlice if nSlice > 1 else -1
-            xMin = flags.Trigger.FPGATrackSim.Hough1D.phiMin
-            xMax = flags.Trigger.FPGATrackSim.Hough1D.phiMax
-            if (not flags.Trigger.FPGATrackSim.oldRegionDefs): ### auto-configure this
-                phiRange = FPGATrackSimDataPrepConfig.getPhiRange(flags)
-                xMin = phiRange[0]
-                xMax = phiRange[1]
-            tool.phiMin = xMin
-            tool.phiMax = xMax
-            tool.qptMin = lowpt
-            tool.qptMax = highpt
-            tool.nBins = flags.Trigger.FPGATrackSim.Hough1D.xBins
-            tool.useDiff = True
-            tool.variableExtend = True
-            tool.drawHitMasks = False
-            tool.phiRangeCut = flags.Trigger.FPGATrackSim.Hough1D.phiRangeCut
-            tool.d0spread=-1.0 # mm
-            tool.iterStep = 0 # auto, TODO put in tag
-            tool.iterLayer = 7 # TODO put in tag
-            tool.threshold = flags.Trigger.FPGATrackSim.Hough1D.threshold[0]
-            tool.hitExtend = flags.Trigger.FPGATrackSim.Hough1D.hitExtendX
-            tool.FPGATrackSimEventSelectionSvc = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimEventSelectionCfg(flags))
-            tool.FPGATrackSimBankSvc = result.getPrimaryAndMerge(FPGATrackSimBankSvcCfg(flags))
-            tool.FPGATrackSimMappingSvc = FPGATrackSimMapping
-            tool.IdealGeoRoads = (flags.Trigger.FPGATrackSim.ActiveConfig.IdealGeoRoads and flags.Trigger.FPGATrackSim.tracking)
-            tool.useSpacePoints = flags.Trigger.FPGATrackSim.spacePoints
-
-            tools.append(tool)
-
-    RF.tools = tools
-    result.addPublicTool(RF, primary=True)
-    return result
-
-
-
-def FPGATrackSimRoadUnionToolGenScanCfg(flags):
-    result=ComponentAccumulator()
-
-    # read the cuts from a seperate python file specified by FPGATrackSim.GenScan.genScanCuts
-    cutset=None
-    if flags.Trigger.FPGATrackSim.oldRegionDefs:
-        toload=flags.Trigger.FPGATrackSim.GenScan.genScanCuts
-        if toload == 'FPGATrackSimGenScanCuts': # its on the newRegion default so it hasn't been set
-            toload = 'FPGATrackSimHough.FPGATrackSimGenScanCuts_incr'
-        cutset = importlib.import_module(toload).cuts[flags.Trigger.FPGATrackSim.region]
-    else:
-        # this allows the cut file defined in python to be loaded from the map directory
-        print("Cut File = ", flags.Trigger.FPGATrackSim.GenScan.genScanCuts,
-                                                    flags.Trigger.FPGATrackSim.mapsDir+"/{}.py".format(flags.Trigger.FPGATrackSim.GenScan.genScanCuts))
-        spec=importlib.util.spec_from_file_location(flags.Trigger.FPGATrackSim.GenScan.genScanCuts,
-                                                    flags.Trigger.FPGATrackSim.mapsDir+"/{}.py".format(flags.Trigger.FPGATrackSim.GenScan.genScanCuts))
-        if spec is None:
-            print("Failed to find Cut File")
-        cutmodule = importlib.util.module_from_spec(spec)
-        spec.loader.exec_module(cutmodule)
-        cutset=cutmodule.cuts[flags.Trigger.FPGATrackSim.region]
-
-    # make the binning class
-    Binning = None
-    if (cutset["parSet"]=="PhiSlicedKeyLyrPars") :
-        Binning = CompFactory.FPGATrackSimGenScanPhiSlicedKeyLyrBinning("GenScanBinning")
-        Binning.approxMath = False
-    else:
-        log.error("Unknown Binning") 
-    Binning.rin=cutset["rin"]
-    Binning.rout=cutset["rout"]
-    Binning.OutputLevel=flags.Trigger.FPGATrackSim.loglevel
-
-    # make the monitoring class
-    Monitor = CompFactory.FPGATrackSimGenScanMonitoring("GenScanMonitoring")
-    Monitor.THistSvc = CompFactory.THistSvc()
-    Monitor.OutputLevel=flags.Trigger.FPGATrackSim.loglevel
-
-    # make the main tool
-    tool = CompFactory.FPGATrackSimGenScanTool("GenScanTool")
-    tool.FPGATrackSimEventSelectionSvc = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimEventSelectionCfg(flags))
-    tool.FPGATrackSimBankSvc = result.getPrimaryAndMerge(FPGATrackSimBankSvcCfg(flags))
-    tool.FPGATrackSimMappingSvc = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimMappingCfg(flags))
-    tool.Monitoring = Monitor
-    tool.Binning = Binning
-    tool.OutputLevel=flags.Trigger.FPGATrackSim.loglevel
-
-    # configure which filers and thresholds to apply
-    tool.binFilter=flags.Trigger.FPGATrackSim.GenScan.binFilter
-    tool.reversePairDir=flags.Trigger.FPGATrackSim.GenScan.reverse
-    tool.applyPairFilter= not flags.Trigger.FPGATrackSim.GenScan.noCuts
-    tool.applyPairSetFilter= not flags.Trigger.FPGATrackSim.GenScan.noCuts
-    tool.threshold = 4
-
-    # configure the padding around the nominal region
-    tool.d0FractionalPadding =0.05
-    tool.z0FractionalPadding =0.05
-    tool.etaFractionalPadding =0.05
-    tool.phiFractionalPadding =0.05
-    tool.qOverPtFractionalPadding =0.05                
-
-    # set cuts
-    for (cut,val) in cutset.items():
-        setattr(tool,cut,val)
-
-    # set layer map
-    if not flags.Trigger.FPGATrackSim.GenScan.layerStudy:
-        if flags.Trigger.FPGATrackSim.oldRegionDefs:
-            tool.layerMapFile = flags.Trigger.FPGATrackSim.GenScan.layerMapFile
-        else:
-            # now assumed to be in the map directory with name = basename for region + _lyrmap.json
-            tool.layerMapFile = flags.Trigger.FPGATrackSim.mapsDir+"/"+FPGATrackSimDataPrepConfig.getBaseName(flags)+"_lyrmap.json"
-
-    # even though we are not actually doing a Union, we need the 
-    # RoadUnionTool because mapping is now there
-    RoadUnion = CompFactory.FPGATrackSimRoadUnionTool()
-    RoadUnion.tools = [tool,]
-    result.addPublicTool(RoadUnion, primary=True)
-
-    # special configuration for studing layer definitions
-    # pass through all hits, but turn off pairing because
-    # it won't be able to run
-    if flags.Trigger.FPGATrackSim.GenScan.layerStudy:
-        RoadUnion.noHitFilter=True
-        tool.binningOnly=True
-    return result
-
-def FPGATrackSimRoadUnionToolGNNCfg(flags):
-    result = ComponentAccumulator()
-    RF = CompFactory.FPGATrackSimRoadUnionTool()
-
-    patternRecoTool = CompFactory.FPGATrackSimGNNPatternRecoTool()
-    patternRecoTool.GNNGraphHitSelector = CompFactory.FPGATrackSimGNNGraphHitSelectorTool()
-    patternRecoTool.GNNGraphConstruction = result.popToolsAndMerge(FPGATrackSimGNNGraphConstructionToolCfg(flags))
-    patternRecoTool.GNNEdgeClassifier = result.popToolsAndMerge(FPGATrackSimGNNEdgeClassifierToolCfg(flags))
-    patternRecoTool.GNNRoadMaker = result.popToolsAndMerge(FPGATrackSimGNNRoadMakerToolCfg(flags))
-    patternRecoTool.GNNRootOutput = result.popToolsAndMerge(FPGATrackSimGNNRootOutputToolCfg(flags))
-    patternRecoTool.doGNNRootOutput = flags.Trigger.FPGATrackSim.GNN.doGNNRootOutput
-    
-    RF.tools = [patternRecoTool]
-    result.addPublicTool(RF, primary=True)
-
-    return result
-
-def FPGATrackSimGNNGraphConstructionToolCfg(flags):
-    result = ComponentAccumulator()
-
-    GNNGraphConstructionTool = CompFactory.FPGATrackSimGNNGraphConstructionTool()
-    GNNGraphConstructionTool.graphTool = flags.Trigger.FPGATrackSim.GNN.graphTool.value
-    GNNGraphConstructionTool.moduleMapType=flags.Trigger.FPGATrackSim.GNN.moduleMapType.value
-    GNNGraphConstructionTool.moduleMapFunc=flags.Trigger.FPGATrackSim.GNN.moduleMapFunc.value
-    GNNGraphConstructionTool.moduleMapTol=flags.Trigger.FPGATrackSim.GNN.moduleMapTol
-    GNNGraphConstructionTool.moduleMapPath=PathResolver.FindCalibFile(flags.Trigger.FPGATrackSim.GNN.moduleMapPath)
-
-    result.setPrivateTools(GNNGraphConstructionTool)
-
-    return result
-
-def FPGATrackSimGNNEdgeClassifierToolCfg(flags):
-    result = ComponentAccumulator()
-
-    from AthOnnxComps.OnnxRuntimeInferenceConfig import OnnxRuntimeInferenceToolCfg
-    from AthOnnxComps.OnnxRuntimeFlags import OnnxRuntimeType
-
-    GNNEdgeClassifierTool = CompFactory.FPGATrackSimGNNEdgeClassifierTool()
-    GNNEdgeClassifierTool.GNNInferenceTool = result.popToolsAndMerge(OnnxRuntimeInferenceToolCfg(
-       flags, flags.Trigger.FPGATrackSim.GNN.GNNModelPath, OnnxRuntimeType.CPU))
-
-    result.setPrivateTools(GNNEdgeClassifierTool)
-
-    return result
-
-def FPGATrackSimGNNRoadMakerToolCfg(flags):
-    result = ComponentAccumulator()
-
-    GNNRoadMakerTool = CompFactory.FPGATrackSimGNNRoadMakerTool()
-    GNNRoadMakerTool.roadMakerTool = flags.Trigger.FPGATrackSim.GNN.roadMakerTool.value
-    GNNRoadMakerTool.edgeScoreCut = flags.Trigger.FPGATrackSim.GNN.edgeScoreCut
-    GNNRoadMakerTool.FPGATrackSimMappingSvc = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimMappingCfg(flags))
-
-    result.setPrivateTools(GNNRoadMakerTool)
-
-    return result
-    
-def FPGATrackSimGNNRootOutputToolCfg(flags):
-    result = ComponentAccumulator()
-
-    GNNRootOutputTool = CompFactory.FPGATrackSimGNNRootOutputTool()
-
-    result.addService(CompFactory.THistSvc(Output = ["TRIGFPGATrackSimGNNOUTPUT DATAFILE='GNNRootOutput.root', OPT='RECREATE'"]))
-    result.setPrivateTools(GNNRootOutputTool)
-
-    return result
-
-def FPGATrackSimDataFlowToolCfg(flags):
-    result=ComponentAccumulator()
-    DataFlowTool = CompFactory.FPGATrackSimDataFlowTool()
-    DataFlowTool.FPGATrackSimEventSelectionSvc = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimEventSelectionCfg(flags))
-    DataFlowTool.FPGATrackSimMappingSvc =  result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimMappingCfg(flags))
-    DataFlowTool.Chi2ndofCut = flags.Trigger.FPGATrackSim.ActiveConfig.chi2cut
-    DataFlowTool.THistSvc = CompFactory.THistSvc()
-    result.setPrivateTools(DataFlowTool)
-    return result
-
-def FPGATrackSimHoughRootOutputToolCfg(flags):
-    result=ComponentAccumulator()
-    HoughRootOutputTool = CompFactory.FPGATrackSimHoughRootOutputTool()
-    HoughRootOutputTool.FPGATrackSimEventSelectionSvc = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimEventSelectionCfg(flags))
-    HoughRootOutputTool.FPGATrackSimMappingSvc = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimMappingCfg(flags))
-    HoughRootOutputTool.THistSvc = CompFactory.THistSvc()
-    result.setPrivateTools(HoughRootOutputTool)
-    return result
-
-def LRTRoadFinderCfg(flags):
-    result=ComponentAccumulator()
-    LRTRoadFinder =CompFactory.FPGATrackSimHoughTransform_d0phi0_Tool()
-    LRTRoadFinder.FPGATrackSimBankSvc = result.getPrimaryAndMerge(FPGATrackSimBankSvcCfg(flags))
-    LRTRoadFinder.FPGATrackSimMappingSvc = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimMappingCfg(flags))
-    LRTRoadFinder.combine_layers = flags.Trigger.FPGATrackSim.ActiveConfig.lrtStraighttrackCombineLayers
-    LRTRoadFinder.convolution = flags.Trigger.FPGATrackSim.ActiveConfig.lrtStraighttrackConvolution
-    LRTRoadFinder.hitExtend_x = flags.Trigger.FPGATrackSim.ActiveConfig.lrtStraighttrackHitExtendX
-    LRTRoadFinder.scale = flags.Trigger.FPGATrackSim.ActiveConfig.scale
-    LRTRoadFinder.threshold = flags.Trigger.FPGATrackSim.ActiveConfig.lrtStraighttrackThreshold
-    result.setPrivateTools(LRTRoadFinder)
-    return result
-
-def NNTrackToolCfg(flags):
-    result=ComponentAccumulator()
-    NNTrackTool = CompFactory.FPGATrackSimNNTrackTool()
-    NNTrackTool.THistSvc = CompFactory.THistSvc()
-    NNTrackTool.FPGATrackSimMappingSvc = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimMappingCfg(flags))
-    NNTrackTool.FPGATrackSimBankSvc = result.getPrimaryAndMerge(FPGATrackSimBankSvcCfg(flags))
-    NNTrackTool.IdealGeoRoads = (flags.Trigger.FPGATrackSim.ActiveConfig.IdealGeoRoads and flags.Trigger.FPGATrackSim.tracking)
-    NNTrackTool.useSpacePoints = flags.Trigger.FPGATrackSim.spacePoints and not flags.Trigger.FPGATrackSim.ActiveConfig.genScan
-    NNTrackTool.SPRoadFilterTool = getSPRoadFilterTool(flags)
-    NNTrackTool.MinNumberOfRealHitsInATrack = 5 if flags.Trigger.FPGATrackSim.ActiveConfig.genScan else 9
-    
-    result.setPrivateTools(NNTrackTool)
-    return result
-
-def FPGATrackSimTrackFitterToolCfg(flags):
-    result=ComponentAccumulator()
-    TF_1st = CompFactory.FPGATrackSimTrackFitterTool("FPGATrackSimTrackFitterTool_1st")
-    TF_1st.GuessHits = flags.Trigger.FPGATrackSim.ActiveConfig.guessHits
-    TF_1st.IdealCoordFitType = flags.Trigger.FPGATrackSim.ActiveConfig.idealCoordFitType
-    TF_1st.FPGATrackSimBankSvc = result.getPrimaryAndMerge(FPGATrackSimBankSvcCfg(flags))
-    TF_1st.FPGATrackSimMappingSvc = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimMappingCfg(flags))
-    TF_1st.chi2DofRecoveryMax = flags.Trigger.FPGATrackSim.ActiveConfig.chi2DoFRecoveryMax
-    TF_1st.chi2DofRecoveryMin = flags.Trigger.FPGATrackSim.ActiveConfig.chi2DoFRecoveryMin
-    TF_1st.doMajority = flags.Trigger.FPGATrackSim.ActiveConfig.doMajority
-    TF_1st.nHits_noRecovery = flags.Trigger.FPGATrackSim.ActiveConfig.nHitsNoRecovery
-    TF_1st.DoDeltaGPhis = flags.Trigger.FPGATrackSim.ActiveConfig.doDeltaGPhis
-    TF_1st.DoMissingHitsChecks = flags.Trigger.FPGATrackSim.ActiveConfig.doMissingHitsChecks
-    TF_1st.IdealGeoRoads = (flags.Trigger.FPGATrackSim.ActiveConfig.IdealGeoRoads and flags.Trigger.FPGATrackSim.tracking)
-    TF_1st.useSpacePoints = flags.Trigger.FPGATrackSim.spacePoints and not flags.Trigger.FPGATrackSim.ActiveConfig.genScan
-    TF_1st.SPRoadFilterTool = getSPRoadFilterTool(flags)
-    result.addPublicTool(TF_1st, primary=True)
-    return result
-
-def FPGATrackSimOverlapRemovalToolCfg(flags):
-    result=ComponentAccumulator()
-    OR_1st = CompFactory.FPGATrackSimOverlapRemovalTool("FPGATrackSimOverlapRemovalTool_1st")
-    OR_1st.ORAlgo = "Normal"
-    OR_1st.doFastOR =flags.Trigger.FPGATrackSim.ActiveConfig.doFastOR
-    OR_1st.NumOfHitPerGrouping = 3
-    OR_1st.FPGATrackSimMappingSvc = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimMappingCfg(flags))
-    OR_1st.MinChi2 = flags.Trigger.FPGATrackSim.ActiveConfig.chi2cut    
-    if flags.Trigger.FPGATrackSim.ActiveConfig.hough or flags.Trigger.FPGATrackSim.ActiveConfig.hough1D:
-        OR_1st.nBins_x = flags.Trigger.FPGATrackSim.ActiveConfig.xBins + 2 * flags.Trigger.FPGATrackSim.ActiveConfig.xBufferBins
-        OR_1st.nBins_y = flags.Trigger.FPGATrackSim.ActiveConfig.yBins + 2 * flags.Trigger.FPGATrackSim.ActiveConfig.yBufferBins
-        OR_1st.localMaxWindowSize = flags.Trigger.FPGATrackSim.ActiveConfig.localMaxWindowSize
-        OR_1st.roadSliceOR = flags.Trigger.FPGATrackSim.ActiveConfig.roadSliceOR
-    
-    result.addPublicTool(OR_1st, primary=True)
-    return result
-
-def prepareFlagsForFPGATrackSimLogicalHitsProcessAlg(flags):
-    newFlags = flags.cloneAndReplace("Trigger.FPGATrackSim.ActiveConfig", "Trigger.FPGATrackSim." + flags.Trigger.FPGATrackSim.algoTag)
-    return newFlags
-
-def getSPRoadFilterTool(flags,secondStage=False):
-    name="FPGATrackSimSpacepointRoadFilterTool_1st"
-    if secondStage:
-        name="FPGATrackSimSpacepointRoadFilterTool_2st"
-    SPRoadFilter = CompFactory.FPGATrackSimSpacepointRoadFilterTool(name)
-    SPRoadFilter.filtering = flags.Trigger.FPGATrackSim.ActiveConfig.spacePointFiltering
-    SPRoadFilter.minSpacePlusPixel = flags.Trigger.FPGATrackSim.minSpacePlusPixel
-    SPRoadFilter.isSecondStage = secondStage
-    # TODO guard here against threshold being more than one value?
-    if (flags.Trigger.FPGATrackSim.ActiveConfig.hough1D):
-        SPRoadFilter.threshold = flags.Trigger.FPGATrackSim.Hough1D.threshold[0]
-    else:
-        SPRoadFilter.threshold = flags.Trigger.FPGATrackSim.ActiveConfig.threshold[0]
-    SPRoadFilter.setSectors = (flags.Trigger.FPGATrackSim.ActiveConfig.IdealGeoRoads and flags.Trigger.FPGATrackSim.tracking)
-    return SPRoadFilter
-
-def FPGATrackSimLogicalHitsProcessAlgCfg(inputFlags):
-
-    flags = prepareFlagsForFPGATrackSimLogicalHitsProcessAlg(inputFlags)
-   
-    result=ComponentAccumulator()
-    if not flags.Trigger.FPGATrackSim.wrapperFileName:
-        from InDetConfig.InDetPrepRawDataFormationConfig import AthenaTrkClusterizationCfg
-        result.merge(AthenaTrkClusterizationCfg(flags))
-
-    theFPGATrackSimLogicalHitsProcessAlg=CompFactory.FPGATrackSimLogicalHitsProcessAlg()
-    theFPGATrackSimLogicalHitsProcessAlg.writeOutputData = flags.Trigger.FPGATrackSim.writeAdditionalOutputData
-    theFPGATrackSimLogicalHitsProcessAlg.tracking = flags.Trigger.FPGATrackSim.tracking
-    theFPGATrackSimLogicalHitsProcessAlg.doOverlapRemoval = flags.Trigger.FPGATrackSim.doOverlapRemoval
-    theFPGATrackSimLogicalHitsProcessAlg.DoMissingHitsChecks = flags.Trigger.FPGATrackSim.ActiveConfig.doMissingHitsChecks
-    theFPGATrackSimLogicalHitsProcessAlg.DoHoughRootOutput1st = flags.Trigger.FPGATrackSim.ActiveConfig.houghRootoutput1st
-    theFPGATrackSimLogicalHitsProcessAlg.NumOfHitPerGrouping = flags.Trigger.FPGATrackSim.ActiveConfig.NumOfHitPerGrouping
-    theFPGATrackSimLogicalHitsProcessAlg.DoNNTrack = flags.Trigger.FPGATrackSim.ActiveConfig.trackNNAnalysis
-    theFPGATrackSimLogicalHitsProcessAlg.eventSelector = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimEventSelectionCfg(flags))
-    theFPGATrackSimLogicalHitsProcessAlg.TrackScoreCut = flags.Trigger.FPGATrackSim.ActiveConfig.chi2cut
-    theFPGATrackSimLogicalHitsProcessAlg.passLowestChi2TrackOnly = flags.Trigger.FPGATrackSim.ActiveConfig.passLowestChi2TrackOnly
-    FPGATrackSimMaping = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimMappingCfg(flags))
-    theFPGATrackSimLogicalHitsProcessAlg.FPGATrackSimMapping = FPGATrackSimMaping
-
-    # If tracking is set to False, don't configure the bank service
-    if flags.Trigger.FPGATrackSim.tracking:
-        result.getPrimaryAndMerge(FPGATrackSimBankSvcCfg(flags))
-
-    if (flags.Trigger.FPGATrackSim.ActiveConfig.hough1D):
-        theFPGATrackSimLogicalHitsProcessAlg.RoadFinder = result.getPrimaryAndMerge(FPGATrackSimRoadUnionTool1DCfg(flags))
-    elif (flags.Trigger.FPGATrackSim.ActiveConfig.genScan):
-        theFPGATrackSimLogicalHitsProcessAlg.RoadFinder = result.getPrimaryAndMerge(FPGATrackSimRoadUnionToolGenScanCfg(flags))
-    elif (flags.Trigger.FPGATrackSim.ActiveConfig.GNN):
-        theFPGATrackSimLogicalHitsProcessAlg.RoadFinder = result.getPrimaryAndMerge(FPGATrackSimRoadUnionToolGNNCfg(flags))
-    else:
-        theFPGATrackSimLogicalHitsProcessAlg.RoadFinder = result.getPrimaryAndMerge(FPGATrackSimRoadUnionToolCfg(flags))
-
-    if (flags.Trigger.FPGATrackSim.ActiveConfig.etaPatternFilter):
-        EtaPatternFilter = CompFactory.FPGATrackSimEtaPatternFilterTool()
-        EtaPatternFilter.FPGATrackSimMappingSvc = FPGATrackSimMaping
-        EtaPatternFilter.threshold = flags.Trigger.FPGATrackSim.Hough1D.threshold[0]
-        EtaPatternFilter.EtaPatterns = flags.Trigger.FPGATrackSim.mapsDir+"/"+FPGATrackSimDataPrepConfig.getBaseName(flags)+".patt"
-        theFPGATrackSimLogicalHitsProcessAlg.RoadFilter = EtaPatternFilter
-        theFPGATrackSimLogicalHitsProcessAlg.FilterRoads = True
-
-    if (flags.Trigger.FPGATrackSim.ActiveConfig.phiRoadFilter):
-        RoadFilter2 = CompFactory.FPGATrackSimPhiRoadFilterTool()
-        RoadFilter2.FPGATrackSimMappingSvc = FPGATrackSimMaping
-        RoadFilter2.threshold = flags.Trigger.FPGATrackSim.Hough1D.threshold[0]
-        RoadFilter2.fieldCorrection = flags.Trigger.FPGATrackSim.ActiveConfig.fieldCorrection
-        ### set the window to be a constant value (could be changed), array should be length of the threshold
-        windows = [flags.Trigger.FPGATrackSim.Hough1D.phifilterwindow for i in range(len(flags.Trigger.FPGATrackSim.ActiveConfig.hitExtendX))]
-        RoadFilter2.window = windows
-        
-        theFPGATrackSimLogicalHitsProcessAlg.RoadFilter2 = RoadFilter2
-        theFPGATrackSimLogicalHitsProcessAlg.FilterRoads2 = True
-
-
-    theFPGATrackSimLogicalHitsProcessAlg.HoughRootOutputTool = result.getPrimaryAndMerge(FPGATrackSimHoughRootOutputToolCfg(flags))
-
-    LRTRoadFilter = CompFactory.FPGATrackSimLLPRoadFilterTool()
-    result.addPublicTool(LRTRoadFilter)
-    theFPGATrackSimLogicalHitsProcessAlg.LRTRoadFilter = LRTRoadFilter
-
-    theFPGATrackSimLogicalHitsProcessAlg.LRTRoadFinder = result.getPrimaryAndMerge(LRTRoadFinderCfg(flags))
-    theFPGATrackSimLogicalHitsProcessAlg.NNTrackTool = result.getPrimaryAndMerge(NNTrackToolCfg(flags))
-
-    theFPGATrackSimLogicalHitsProcessAlg.OutputTool = result.getPrimaryAndMerge(FPGATrackSimWriteOutputCfg(flags))
-    theFPGATrackSimLogicalHitsProcessAlg.TrackFitter_1st = result.getPrimaryAndMerge(FPGATrackSimTrackFitterToolCfg(flags))
-    theFPGATrackSimLogicalHitsProcessAlg.OverlapRemoval_1st = result.getPrimaryAndMerge(FPGATrackSimOverlapRemovalToolCfg(flags))
-
-    # Create SPRoadFilterTool if spacepoints are turned on. TODO: make things configurable?
-    if flags.Trigger.FPGATrackSim.spacePoints and not flags.Trigger.FPGATrackSim.ActiveConfig.genScan:
-        theFPGATrackSimLogicalHitsProcessAlg.SPRoadFilterTool = getSPRoadFilterTool(flags)
-        theFPGATrackSimLogicalHitsProcessAlg.Spacepoints = True
-
-
-    if flags.Trigger.FPGATrackSim.ActiveConfig.lrt:
-        assert flags.Trigger.FPGATrackSim.ActiveConfig.lrtUseBasicHitFilter != flags.Trigger.FPGATrackSim.ActiveConfig.lrtUseMlHitFilter, 'Inconsistent LRT hit filtering setup, need either ML of Basic filtering enabled'
-        assert flags.Trigger.FPGATrackSim.ActiveConfig.lrtUseStraightTrackHT != flags.Trigger.FPGATrackSim.ActiveConfig.lrtUseDoubletHT, 'Inconsistent LRT HT setup, need either double or strightTrack enabled'
-        theFPGATrackSimLogicalHitsProcessAlg.doLRT = True
-        theFPGATrackSimLogicalHitsProcessAlg.LRTHitFiltering = (not flags.Trigger.FPGATrackSim.ActiveConfig.lrtSkipHitFiltering)
-
-    from FPGATrackSimAlgorithms.FPGATrackSimAlgorithmConfig import FPGATrackSimLogicalHitsProcessAlgMonitoringCfg
-    theFPGATrackSimLogicalHitsProcessAlg.MonTool = result.getPrimaryAndMerge(FPGATrackSimLogicalHitsProcessAlgMonitoringCfg(flags))
-
-    result.addEventAlgo(theFPGATrackSimLogicalHitsProcessAlg)
-
-    return result
-
-
-
-
-if __name__ == "__main__":
-    from AthenaConfiguration.AllConfigFlags import initConfigFlags
-    from AthenaConfiguration.MainServicesConfig import MainServicesCfg
-    
-
-    flags = initConfigFlags()
-    
-    ############################################
-    # Flags used in the prototrack chain
-    FinalProtoTrackChainxAODTracksKey="FPGA"
-    flags.Detector.EnableCalo = False
-
-    # ensure that the xAOD SP and cluster containers are available
-    flags.Tracking.ITkMainPass.doAthenaToActsSpacePoint=True
-    flags.Tracking.ITkMainPass.doAthenaToActsCluster=True
-    from TrkConfig.TrkConfigFlags import TrackingComponent
-    flags.Tracking.recoChain = [TrackingComponent.ActsChain] # another viable option is TrackingComponent.AthenaChain
-    flags.Acts.doRotCorrection = False
-
-    ############################################
-    flags.Concurrency.NumThreads=1
-    #flags.Concurrency.NumProcs=0
-    flags.Scheduler.ShowDataDeps=True
-    flags.Scheduler.CheckDependencies=True
-    flags.Debug.DumpEvtStore=False
-
-    # flags.Exec.DebugStage="exec" # useful option to debug the execution of the job - we want it commented out for production
-    flags.fillFromArgs()
-
-    assert not flags.Trigger.FPGATrackSim.pipeline.startswith('F-5'),"ERROR You are trying to run an F-5* pipeline! This is not yet supported!"
-
-    if (flags.Trigger.FPGATrackSim.pipeline.startswith('F-1')):
-        print("You are trying to run an F-100 pipeline! I am going to run the Data Prep chain for you and nothing else!")
-        FPGATrackSimDataPrepConfig.runDataPrepChain()
-    elif (flags.Trigger.FPGATrackSim.pipeline.startswith('F-2')):
-        print("You are trying to run an F-2* pipeline! I am auto-configuring the 1D bitshift for you, including eta pattern filters and phi road filters")
-        flags.Trigger.FPGATrackSim.Hough.etaPatternFilter = True
-        flags.Trigger.FPGATrackSim.Hough.phiRoadFilter = True
-        flags.Trigger.FPGATrackSim.Hough.hough1D = True
-        flags.Trigger.FPGATrackSim.Hough.hough = False
-    elif (flags.Trigger.FPGATrackSim.pipeline.startswith('F-3')):
-        print("You are trying to run an F-3* pipeline! I am auto-configuring the 2D HT for you, and disabling the eta pattern filter and phi road filter. Whether you wanted to or not")
-        flags.Trigger.FPGATrackSim.Hough.etaPatternFilter = False
-        flags.Trigger.FPGATrackSim.Hough.phiRoadFilter = False
-        flags.Trigger.FPGATrackSim.Hough.hough1D = False
-        flags.Trigger.FPGATrackSim.Hough.hough = True
-    elif (flags.Trigger.FPGATrackSim.pipeline.startswith('F-4')):
-        print("You are trying to run an F-4* pipeline! I am auto-configuring the GNN pattern recognition for you. Whether you wanted to or not")
-        flags.Trigger.FPGATrackSim.Hough.GNN = True
-        flags.Trigger.FPGATrackSim.Hough.chi2cut = 25 # All of the track candidates have chi2 values around 20 for some reason. Needs further investigation. For now move the default cut value to 25
-    elif (flags.Trigger.FPGATrackSim.pipeline.startswith('F-6')):
-        print("You are trying to run an F-6* pipeline! I am auto-configuring the Inside-Out for you. Whether you wanted to or not")
-        flags.Trigger.FPGATrackSim.Hough.genScan=True
-        flags.Trigger.FPGATrackSim.spacePoints = flags.Trigger.FPGATrackSim.Hough.secondStage
-    elif (flags.Trigger.FPGATrackSim.pipeline != ""):
-        raise AssertionError("ERROR You are trying to run the pipeline " + flags.Trigger.FPGATrackSim.pipeline + " which is not yet supported!")
-
-    if (not flags.Trigger.FPGATrackSim.pipeline.startswith('F-1')): ### if DP pipeline skip everything else!
-
-        splitPipeline=flags.Trigger.FPGATrackSim.pipeline.split('-')
-        trackingOption=9999999
-        if (len(splitPipeline) > 1): trackingOption=int(splitPipeline[1])
-        if (trackingOption < 9999999):
-            trackingOptionMod = (trackingOption % 100)
-            if (trackingOptionMod == 0):
-                print("You are trying to run the linearized chi2 fit as part of a pipeline! I am going to enable this for you whether you want to or not")
-                flags.Trigger.FPGATrackSim.tracking = True
-                flags.Trigger.FPGATrackSim.Hough.trackNNAnalysis = False
-            elif (trackingOptionMod == 10):
-                print("You are trying to run the NN fake rejection as part of a pipeline! I am going to enable this for you whether you want to or not")
-                flags.Trigger.FPGATrackSim.tracking = True
-                flags.Trigger.FPGATrackSim.Hough.trackNNAnalysis = True
-            else:
-                raise AssertionError("ERROR Your tracking option for the pipeline = " + str(trackingOption) + " is not yet supported!")
-
-        if isinstance(flags.Trigger.FPGATrackSim.wrapperFileName, str):
-            log.info("wrapperFile is string, converting to list")
-            flags.Trigger.FPGATrackSim.wrapperFileName = [flags.Trigger.FPGATrackSim.wrapperFileName]
-            flags.Input.Files = lambda f: [f.Trigger.FPGATrackSim.wrapperFileName]
-
-        flags.lock()
-        flags.dump()
-        flags = flags.cloneAndReplace("Tracking.ActiveConfig","Tracking.MainPass")
-        acc=MainServicesCfg(flags)
-
-        if flags.Trigger.FPGATrackSim.writeAdditionalOutputData:
-            acc.addService(CompFactory.THistSvc(Output = ["EXPERT DATAFILE='monitoring.root', OPT='RECREATE'"]))
-
-            if (flags.Trigger.FPGATrackSim.Hough.trackNNAnalysis):
-                acc.addService(CompFactory.THistSvc(Output = ["FPGATRACKSIMOUTPUTNNPATHFINDER DATAFILE='NNPathfinder.root', OPT='RECREATE'"]))
-
-            if (flags.Trigger.FPGATrackSim.Hough.houghRootoutput1st | flags.Trigger.FPGATrackSim.Hough.houghRootoutput2nd):
-                acc.addService(CompFactory.THistSvc(Output = ["TRIGFPGATrackSimHOUGHOUTPUT DATAFILE='HoughRootOutput.root', OPT='RECREATE'"]))
-
-            if flags.Trigger.FPGATrackSim.Hough.writeTestOutput:
-                acc.addService(CompFactory.THistSvc(Output = ["FPGATRACKSIMOUTPUT DATAFILE='test.root', OPT='RECREATE'"]))
-
-            if (flags.Trigger.FPGATrackSim.Hough.genScan):
-                acc.addService(CompFactory.THistSvc(Output = ["GENSCAN DATAFILE='genscan.root', OPT='RECREATE'"]))
-
-        if not flags.Trigger.FPGATrackSim.wrapperFileName:
-            from AthenaPoolCnvSvc.PoolReadConfig import PoolReadCfg
-            acc.merge(PoolReadCfg(flags))
-
-            if flags.Input.isMC:
-                from xAODTruthCnv.xAODTruthCnvConfig import GEN_AOD2xAODCfg
-                acc.merge(GEN_AOD2xAODCfg(flags))
-
-                from JetRecConfig.JetRecoSteering import addTruthPileupJetsToOutputCfg # TO DO: check if this is indeed necessary for pileup samples
-                acc.merge(addTruthPileupJetsToOutputCfg(flags))
-
-            if flags.Detector.EnableCalo:
-                from CaloRec.CaloRecoConfig import CaloRecoCfg
-                acc.merge(CaloRecoCfg(flags))
-
-            if flags.Tracking.recoChain:
-                from InDetConfig.TrackRecoConfig import InDetTrackRecoCfg
-                acc.merge(InDetTrackRecoCfg(flags))
-
-        # Configure both the dataprep and logical hits algorithms.
-        acc.merge(FPGATrackSimDataPrepConfig.FPGATrackSimDataPrepAlgCfg(flags))
-        acc.merge(FPGATrackSimLogicalHitsProcessAlgCfg(flags))
-
-        # If second stage is turned on, turn that algorithm on too.
-        if flags.Trigger.FPGATrackSim.Hough.secondStage:
-            acc.merge(FPGATrackSimSecondStageConfig.FPGATrackSimSecondStageAlgCfg(flags))
-
-        if flags.Trigger.FPGATrackSim.doEDMConversion:
-            stage = "_2nd" if flags.Trigger.FPGATrackSim.Hough.secondStage else "_1st"
-            convertTracks = flags.Trigger.FPGATrackSim.tracking
-            acc.merge(FPGATrackSimDataPrepConfig.FPGAConversionAlgCfg(flags, name = f"FPGAConversionAlg{stage}",
-                                                                        stage = f"{stage}",
-                                                                        doActsTrk=True,
-                                                                        doSP=flags.Trigger.FPGATrackSim.spacePoints,
-                                                                        useRoads=not flags.Trigger.FPGATrackSim.tracking))
-
-            from FPGATrackSimPrototrackFitter.FPGATrackSimPrototrackFitterConfig import FPGATruthDecorationCfg, FPGAProtoTrackFitCfg
-            acc.merge(FPGAProtoTrackFitCfg(flags,stage=f"{stage}",
-                                            useRoads=not flags.Trigger.FPGATrackSim.tracking)) # Run ACTS KF
-            acc.merge(FPGATruthDecorationCfg(flags,FinalProtoTrackChainxAODTracksKey=FinalProtoTrackChainxAODTracksKey,stage=f"{stage}")) # Run Truth Matching/Decoration chain
-            if not flags.Trigger.FPGATrackSim.wrapperFileName and flags.Trigger.FPGATrackSim.runCKF:
-                from FPGATrackSimConfTools.FPGATrackExtensionConfig import FPGATrackExtensionAlgCfg
-                acc.merge(FPGATrackExtensionAlgCfg(flags, enableTrackStatePrinter=False, name="FPGATrackExtension",
-                                                    ProtoTracksLocation=f"ActsProtoTracks{stage}FromFPGATrack")) # run CKF track extension on FPGA tracks
-
-            if flags.Trigger.FPGATrackSim.writeToAOD: acc.merge(FPGATrackSimDataPrepConfig.WriteToAOD(flags,
-                                                                                                        stage = f"{stage}",
-                                                                                                        finalTrackParticles=f"{FinalProtoTrackChainxAODTracksKey}TrackParticles"))
-
-            # Reporting algorithm (used for debugging - can be disabled)
-            from FPGATrackSimReporting.FPGATrackSimReportingConfig import FPGATrackSimReportingCfg
-            acc.merge(FPGATrackSimReportingCfg(flags, stage=f"{stage}",
-                                                perEventReports = ((flags.Trigger.FPGATrackSim.sampleType != 'skipTruth') and flags.Exec.MaxEvents<=10 ) )) # disable perEventReports for pileup samples or many events
-
-        acc.store(open('AnalysisConfig.pkl','wb'))
-
-        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
-
-        statusCode = acc.run(flags.Exec.MaxEvents)
-        assert statusCode.isSuccess() is True, "Application execution did not succeed"
+# Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
+from AthenaConfiguration.ComponentFactory import CompFactory
+from AthenaCommon.Logging import AthenaLogger
+from PathResolver import PathResolver
+import importlib
+
+log = AthenaLogger(__name__)
+
+#### Now inmport Data Prep config from other file
+from FPGATrackSimConfTools import FPGATrackSimDataPrepConfig
+from FPGATrackSimConfTools import FPGATrackSimSecondStageConfig
+
+def getNSubregions(filePath):
+    with open(PathResolver.FindCalibFile(filePath), 'r') as f:
+        fields = f.readline()
+        assert(fields.startswith('towers'))
+        n = fields.split()[1]
+        return int(n)
+
+
+# Need to figure out if we have two output writers or somehow only one.
+def FPGATrackSimWriteOutputCfg(flags):
+    result=ComponentAccumulator()
+    FPGATrackSimWriteOutput = CompFactory.FPGATrackSimOutputHeaderTool("FPGATrackSimWriteOutput")
+    FPGATrackSimWriteOutput.InFileName = ["test.root"]
+    # RECREATE means that that this tool opens the file.
+    # HEADER would mean that something else (e.g. THistSvc) opens it and we just add the object.
+    FPGATrackSimWriteOutput.RWstatus = "HEADER"
+    FPGATrackSimWriteOutput.THistSvc = CompFactory.THistSvc()
+    result.addPublicTool(FPGATrackSimWriteOutput, primary=True)
+    return result
+
+
+
+def FPGATrackSimBankSvcCfg(flags):
+    result=ComponentAccumulator()
+    FPGATrackSimBankSvc = CompFactory.FPGATrackSimBankSvc()
+    pathBankSvc = flags.Trigger.FPGATrackSim.bankDir if flags.Trigger.FPGATrackSim.bankDir != '' else f'/eos/atlas/atlascerngroupdisk/det-htt/HTTsim/{flags.GeoModel.AtlasVersion}/21.9.16/'+FPGATrackSimDataPrepConfig.getBaseName(flags)+'/SectorBanks/'
+    pathBankSvc=PathResolver.FindCalibDirectory(pathBankSvc)
+    FPGATrackSimBankSvc.constantsNoGuess_1st = [
+        f'{pathBankSvc}corrgen_raw_8L_skipPlane0.gcon',
+        f'{pathBankSvc}corrgen_raw_8L_skipPlane1.gcon',
+        f'{pathBankSvc}corrgen_raw_8L_skipPlane2.gcon',
+        f'{pathBankSvc}corrgen_raw_8L_skipPlane3.gcon',
+        f'{pathBankSvc}corrgen_raw_8L_skipPlane4.gcon',
+        f'{pathBankSvc}corrgen_raw_8L_skipPlane5.gcon',
+        f'{pathBankSvc}corrgen_raw_8L_skipPlane6.gcon',
+        f'{pathBankSvc}corrgen_raw_8L_skipPlane7.gcon']
+    FPGATrackSimBankSvc.constantsNoGuess_2nd = [
+        f'{pathBankSvc}corrgen_raw_13L_skipPlane0.gcon',
+        f'{pathBankSvc}corrgen_raw_13L_skipPlane1.gcon',
+        f'{pathBankSvc}corrgen_raw_13L_skipPlane2.gcon',
+        f'{pathBankSvc}corrgen_raw_13L_skipPlane3.gcon',
+        f'{pathBankSvc}corrgen_raw_13L_skipPlane4.gcon',
+        f'{pathBankSvc}corrgen_raw_13L_skipPlane5.gcon',
+        f'{pathBankSvc}corrgen_raw_13L_skipPlane6.gcon',
+        f'{pathBankSvc}corrgen_raw_13L_skipPlane7.gcon']
+    layers="5L" if flags.Trigger.FPGATrackSim.ActiveConfig.genScan else "9L"
+    FPGATrackSimBankSvc.constants_1st = f'{pathBankSvc}corrgen_raw_{layers}_reg{flags.Trigger.FPGATrackSim.region}_checkGood1.gcon'
+    FPGATrackSimBankSvc.constants_2nd = f'{pathBankSvc}corrgen_raw_13L_reg{flags.Trigger.FPGATrackSim.region}_checkGood1.gcon'
+    FPGATrackSimBankSvc.sectorBank_1st = f'{pathBankSvc}sectorsHW_raw_{layers}_reg{flags.Trigger.FPGATrackSim.region}_checkGood1.patt'
+    FPGATrackSimBankSvc.sectorBank_2nd = f'{pathBankSvc}sectorsHW_raw_13L_reg{flags.Trigger.FPGATrackSim.region}_checkGood1.patt'
+    FPGATrackSimBankSvc.sectorSlices = f'{pathBankSvc}slices_{layers}_reg{flags.Trigger.FPGATrackSim.region}.root'
+    FPGATrackSimBankSvc.phiShift = flags.Trigger.FPGATrackSim.phiShift
+
+    # These should be configurable. The tag system needs updating though.
+    FPGATrackSimBankSvc.sectorQPtBins = [-0.001, -0.0005, 0, 0.0005, 0.001]
+    FPGATrackSimBankSvc.qptAbsBinning = False
+
+    result.addService(FPGATrackSimBankSvc, create=True, primary=True)
+    return result
+
+
+def FPGATrackSimRoadUnionToolCfg(flags):
+    result=ComponentAccumulator()
+    RF = CompFactory.FPGATrackSimRoadUnionTool()
+
+    xBins = flags.Trigger.FPGATrackSim.ActiveConfig.xBins
+    xBufferBins = flags.Trigger.FPGATrackSim.ActiveConfig.xBufferBins
+    yBins = flags.Trigger.FPGATrackSim.ActiveConfig.yBins
+    yBufferBins = flags.Trigger.FPGATrackSim.ActiveConfig.yBufferBins
+    yMin = flags.Trigger.FPGATrackSim.ActiveConfig.qptMin
+    yMax = flags.Trigger.FPGATrackSim.ActiveConfig.qptMax
+    xMin = flags.Trigger.FPGATrackSim.ActiveConfig.phiMin
+    xMax = flags.Trigger.FPGATrackSim.ActiveConfig.phiMax
+    if (not flags.Trigger.FPGATrackSim.oldRegionDefs): ### auto-configure this
+        phiRange = FPGATrackSimDataPrepConfig.getPhiRange(flags)
+        xMin = phiRange[0]
+        xMax = phiRange[1]
+
+    xBuffer = (xMax - xMin) / xBins * xBufferBins
+    xMin = xMin - xBuffer
+    xMax = xMax +  xBuffer
+    yBuffer = (yMax - yMin) / yBins * yBufferBins
+    yMin -= yBuffer
+    yMax += yBuffer
+    tools = []
+
+    FPGATrackSimMapping = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimMappingCfg(flags))
+    for number in range(getNSubregions(FPGATrackSimMapping.subrmap)):
+        HoughTransform = CompFactory.FPGATrackSimHoughTransformTool("HoughTransform_0_" + str(number))
+        HoughTransform.FPGATrackSimEventSelectionSvc = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimEventSelectionCfg(flags))
+        HoughTransform.FPGATrackSimBankSvc = result.getPrimaryAndMerge(FPGATrackSimBankSvcCfg(flags))
+        HoughTransform.FPGATrackSimMappingSvc = FPGATrackSimMapping
+        HoughTransform.combine_layers = flags.Trigger.FPGATrackSim.ActiveConfig.combineLayers
+        HoughTransform.convSize_x = flags.Trigger.FPGATrackSim.ActiveConfig.convSizeX
+        HoughTransform.convSize_y = flags.Trigger.FPGATrackSim.ActiveConfig.convSizeY
+        HoughTransform.convolution = flags.Trigger.FPGATrackSim.ActiveConfig.convolution
+        HoughTransform.d0_max = 0
+        HoughTransform.d0_min = 0
+        HoughTransform.fieldCorrection = flags.Trigger.FPGATrackSim.ActiveConfig.fieldCorrection
+        HoughTransform.hitExtend_x = flags.Trigger.FPGATrackSim.ActiveConfig.hitExtendX
+        HoughTransform.localMaxWindowSize = flags.Trigger.FPGATrackSim.ActiveConfig.localMaxWindowSize
+        HoughTransform.nBins_x = xBins + 2 * xBufferBins
+        HoughTransform.nBins_y = yBins + 2 * yBufferBins
+        HoughTransform.phi_max = xMax
+        HoughTransform.phi_min = xMin
+        HoughTransform.qpT_max = yMax
+        HoughTransform.qpT_min = yMin
+        HoughTransform.scale = flags.Trigger.FPGATrackSim.ActiveConfig.scale
+        HoughTransform.subRegion = number
+        HoughTransform.threshold = flags.Trigger.FPGATrackSim.ActiveConfig.threshold
+        HoughTransform.traceHits = True
+        HoughTransform.IdealGeoRoads = (flags.Trigger.FPGATrackSim.ActiveConfig.IdealGeoRoads and flags.Trigger.FPGATrackSim.tracking)
+        HoughTransform.useSpacePoints = flags.Trigger.FPGATrackSim.spacePoints
+
+        tools.append(HoughTransform)
+
+    RF.tools = tools
+    result.addPublicTool(RF, primary=True)
+    return result
+
+def FPGATrackSimRoadUnionTool1DCfg(flags):
+    result=ComponentAccumulator()
+    tools = []
+    RF = CompFactory.FPGATrackSimRoadUnionTool()
+    splitpt=flags.Trigger.FPGATrackSim.Hough1D.splitpt
+    FPGATrackSimMapping = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimMappingCfg(flags))
+    for ptstep in range(splitpt):
+        qpt_min = flags.Trigger.FPGATrackSim.Hough1D.qptMin
+        qpt_max = flags.Trigger.FPGATrackSim.Hough1D.qptMax
+        lowpt = qpt_min + (qpt_max-qpt_min)/splitpt*ptstep
+        highpt = qpt_min + (qpt_max-qpt_min)/splitpt*(ptstep+1)
+        nSlice = getNSubregions(FPGATrackSimMapping.subrmap)
+        for iSlice in range(nSlice):
+            tool = CompFactory.FPGATrackSimHough1DShiftTool("Hough1DShift" + str(iSlice)+(("_pt{}".format(ptstep))  if splitpt>1 else ""))
+            tool.subRegion = iSlice if nSlice > 1 else -1
+            xMin = flags.Trigger.FPGATrackSim.Hough1D.phiMin
+            xMax = flags.Trigger.FPGATrackSim.Hough1D.phiMax
+            if (not flags.Trigger.FPGATrackSim.oldRegionDefs): ### auto-configure this
+                phiRange = FPGATrackSimDataPrepConfig.getPhiRange(flags)
+                xMin = phiRange[0]
+                xMax = phiRange[1]
+            tool.phiMin = xMin
+            tool.phiMax = xMax
+            tool.qptMin = lowpt
+            tool.qptMax = highpt
+            tool.nBins = flags.Trigger.FPGATrackSim.Hough1D.xBins
+            tool.useDiff = True
+            tool.variableExtend = True
+            tool.drawHitMasks = False
+            tool.phiRangeCut = flags.Trigger.FPGATrackSim.Hough1D.phiRangeCut
+            tool.d0spread=-1.0 # mm
+            tool.iterStep = 0 # auto, TODO put in tag
+            tool.iterLayer = 7 # TODO put in tag
+            tool.threshold = flags.Trigger.FPGATrackSim.Hough1D.threshold[0]
+            tool.hitExtend = flags.Trigger.FPGATrackSim.Hough1D.hitExtendX
+            tool.FPGATrackSimEventSelectionSvc = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimEventSelectionCfg(flags))
+            tool.FPGATrackSimBankSvc = result.getPrimaryAndMerge(FPGATrackSimBankSvcCfg(flags))
+            tool.FPGATrackSimMappingSvc = FPGATrackSimMapping
+            tool.IdealGeoRoads = (flags.Trigger.FPGATrackSim.ActiveConfig.IdealGeoRoads and flags.Trigger.FPGATrackSim.tracking)
+            tool.useSpacePoints = flags.Trigger.FPGATrackSim.spacePoints
+
+            tools.append(tool)
+
+    RF.tools = tools
+    result.addPublicTool(RF, primary=True)
+    return result
+
+
+
+def FPGATrackSimRoadUnionToolGenScanCfg(flags):
+    result=ComponentAccumulator()
+
+    # read the cuts from a seperate python file specified by FPGATrackSim.GenScan.genScanCuts
+    cutset=None
+    if flags.Trigger.FPGATrackSim.oldRegionDefs:
+        toload=flags.Trigger.FPGATrackSim.GenScan.genScanCuts
+        if toload == 'FPGATrackSimGenScanCuts': # its on the newRegion default so it hasn't been set
+            toload = 'FPGATrackSimHough.FPGATrackSimGenScanCuts_incr'
+        cutset = importlib.import_module(toload).cuts[flags.Trigger.FPGATrackSim.region]
+    else:
+        # this allows the cut file defined in python to be loaded from the map directory
+        print("Cut File = ", flags.Trigger.FPGATrackSim.GenScan.genScanCuts,
+                                                    flags.Trigger.FPGATrackSim.mapsDir+"/{}.py".format(flags.Trigger.FPGATrackSim.GenScan.genScanCuts))
+        spec=importlib.util.spec_from_file_location(flags.Trigger.FPGATrackSim.GenScan.genScanCuts,
+                                                    flags.Trigger.FPGATrackSim.mapsDir+"/{}.py".format(flags.Trigger.FPGATrackSim.GenScan.genScanCuts))
+        if spec is None:
+            print("Failed to find Cut File")
+        cutmodule = importlib.util.module_from_spec(spec)
+        spec.loader.exec_module(cutmodule)
+        cutset=cutmodule.cuts[flags.Trigger.FPGATrackSim.region]
+
+    # make the binning class
+    Binning = None
+    if (cutset["parSet"]=="PhiSlicedKeyLyrPars") :
+        Binning = CompFactory.FPGATrackSimGenScanPhiSlicedKeyLyrBinning("GenScanBinning")
+        Binning.approxMath = False
+    else:
+        log.error("Unknown Binning")
+    Binning.rin=cutset["rin"]
+    Binning.rout=cutset["rout"]
+    Binning.OutputLevel=flags.Trigger.FPGATrackSim.loglevel
+
+    # make the monitoring class
+    Monitor = CompFactory.FPGATrackSimGenScanMonitoring("GenScanMonitoring")
+    Monitor.THistSvc = CompFactory.THistSvc()
+    Monitor.OutputLevel=flags.Trigger.FPGATrackSim.loglevel
+
+    # make the main tool
+    tool = CompFactory.FPGATrackSimGenScanTool("GenScanTool")
+    tool.FPGATrackSimEventSelectionSvc = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimEventSelectionCfg(flags))
+    tool.FPGATrackSimBankSvc = result.getPrimaryAndMerge(FPGATrackSimBankSvcCfg(flags))
+    tool.FPGATrackSimMappingSvc = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimMappingCfg(flags))
+    tool.Monitoring = Monitor
+    tool.Binning = Binning
+    tool.OutputLevel=flags.Trigger.FPGATrackSim.loglevel
+
+    # configure which filers and thresholds to apply
+    tool.binFilter=flags.Trigger.FPGATrackSim.GenScan.binFilter
+    tool.reversePairDir=flags.Trigger.FPGATrackSim.GenScan.reverse
+    tool.applyPairFilter= not flags.Trigger.FPGATrackSim.GenScan.noCuts
+    tool.applyPairSetFilter= not flags.Trigger.FPGATrackSim.GenScan.noCuts
+    tool.threshold = 4
+
+    # configure the padding around the nominal region
+    tool.d0FractionalPadding =0.05
+    tool.z0FractionalPadding =0.05
+    tool.etaFractionalPadding =0.05
+    tool.phiFractionalPadding =0.05
+    tool.qOverPtFractionalPadding =0.05
+
+    # set cuts
+    for (cut,val) in cutset.items():
+        setattr(tool,cut,val)
+
+    # set layer map
+    if not flags.Trigger.FPGATrackSim.GenScan.layerStudy:
+        if flags.Trigger.FPGATrackSim.oldRegionDefs:
+            tool.layerMapFile = flags.Trigger.FPGATrackSim.GenScan.layerMapFile
+        else:
+            # now assumed to be in the map directory with name = basename for region + _lyrmap.json
+            tool.layerMapFile = flags.Trigger.FPGATrackSim.mapsDir+"/"+FPGATrackSimDataPrepConfig.getBaseName(flags)+"_lyrmap.json"
+
+    # even though we are not actually doing a Union, we need the
+    # RoadUnionTool because mapping is now there
+    RoadUnion = CompFactory.FPGATrackSimRoadUnionTool()
+    RoadUnion.tools = [tool,]
+    result.addPublicTool(RoadUnion, primary=True)
+
+    # special configuration for studing layer definitions
+    # pass through all hits, but turn off pairing because
+    # it won't be able to run
+    if flags.Trigger.FPGATrackSim.GenScan.layerStudy:
+        RoadUnion.noHitFilter=True
+        tool.binningOnly=True
+    return result
+
+def FPGATrackSimRoadUnionToolGNNCfg(flags):
+    result = ComponentAccumulator()
+    RF = CompFactory.FPGATrackSimRoadUnionTool()
+
+    patternRecoTool = CompFactory.FPGATrackSimGNNPatternRecoTool()
+    patternRecoTool.GNNGraphHitSelector = CompFactory.FPGATrackSimGNNGraphHitSelectorTool()
+    patternRecoTool.GNNGraphConstruction = result.popToolsAndMerge(FPGATrackSimGNNGraphConstructionToolCfg(flags))
+    patternRecoTool.GNNEdgeClassifier = result.popToolsAndMerge(FPGATrackSimGNNEdgeClassifierToolCfg(flags))
+    patternRecoTool.GNNRoadMaker = result.popToolsAndMerge(FPGATrackSimGNNRoadMakerToolCfg(flags))
+    patternRecoTool.GNNRootOutput = result.popToolsAndMerge(FPGATrackSimGNNRootOutputToolCfg(flags))
+    patternRecoTool.doGNNRootOutput = flags.Trigger.FPGATrackSim.GNN.doGNNRootOutput
+
+    RF.tools = [patternRecoTool]
+    result.addPublicTool(RF, primary=True)
+
+    return result
+
+def FPGATrackSimGNNGraphConstructionToolCfg(flags):
+    result = ComponentAccumulator()
+
+    GNNGraphConstructionTool = CompFactory.FPGATrackSimGNNGraphConstructionTool()
+    GNNGraphConstructionTool.graphTool = flags.Trigger.FPGATrackSim.GNN.graphTool.value
+    GNNGraphConstructionTool.moduleMapType=flags.Trigger.FPGATrackSim.GNN.moduleMapType.value
+    GNNGraphConstructionTool.moduleMapFunc=flags.Trigger.FPGATrackSim.GNN.moduleMapFunc.value
+    GNNGraphConstructionTool.moduleMapTol=flags.Trigger.FPGATrackSim.GNN.moduleMapTol
+    GNNGraphConstructionTool.moduleMapPath=PathResolver.FindCalibFile(flags.Trigger.FPGATrackSim.GNN.moduleMapPath)
+
+    result.setPrivateTools(GNNGraphConstructionTool)
+
+    return result
+
+def FPGATrackSimGNNEdgeClassifierToolCfg(flags):
+    result = ComponentAccumulator()
+
+    from AthOnnxComps.OnnxRuntimeInferenceConfig import OnnxRuntimeInferenceToolCfg
+    from AthOnnxComps.OnnxRuntimeFlags import OnnxRuntimeType
+
+    GNNEdgeClassifierTool = CompFactory.FPGATrackSimGNNEdgeClassifierTool()
+    GNNEdgeClassifierTool.GNNInferenceTool = result.popToolsAndMerge(OnnxRuntimeInferenceToolCfg(
+       flags, flags.Trigger.FPGATrackSim.GNN.GNNModelPath, OnnxRuntimeType.CPU))
+
+    result.setPrivateTools(GNNEdgeClassifierTool)
+
+    return result
+
+def FPGATrackSimGNNRoadMakerToolCfg(flags):
+    result = ComponentAccumulator()
+
+    GNNRoadMakerTool = CompFactory.FPGATrackSimGNNRoadMakerTool()
+    GNNRoadMakerTool.roadMakerTool = flags.Trigger.FPGATrackSim.GNN.roadMakerTool.value
+    GNNRoadMakerTool.edgeScoreCut = flags.Trigger.FPGATrackSim.GNN.edgeScoreCut
+    GNNRoadMakerTool.FPGATrackSimMappingSvc = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimMappingCfg(flags))
+
+    result.setPrivateTools(GNNRoadMakerTool)
+
+    return result
+
+def FPGATrackSimGNNRootOutputToolCfg(flags):
+    result = ComponentAccumulator()
+
+    GNNRootOutputTool = CompFactory.FPGATrackSimGNNRootOutputTool()
+
+    result.addService(CompFactory.THistSvc(Output = ["TRIGFPGATrackSimGNNOUTPUT DATAFILE='GNNRootOutput.root', OPT='RECREATE'"]))
+    result.setPrivateTools(GNNRootOutputTool)
+
+    return result
+
+def FPGATrackSimDataFlowToolCfg(flags):
+    result=ComponentAccumulator()
+    DataFlowTool = CompFactory.FPGATrackSimDataFlowTool()
+    DataFlowTool.FPGATrackSimEventSelectionSvc = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimEventSelectionCfg(flags))
+    DataFlowTool.FPGATrackSimMappingSvc =  result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimMappingCfg(flags))
+    DataFlowTool.Chi2ndofCut = flags.Trigger.FPGATrackSim.ActiveConfig.chi2cut
+    DataFlowTool.THistSvc = CompFactory.THistSvc()
+    result.setPrivateTools(DataFlowTool)
+    return result
+
+def FPGATrackSimHoughRootOutputToolCfg(flags):
+    result=ComponentAccumulator()
+    HoughRootOutputTool = CompFactory.FPGATrackSimHoughRootOutputTool()
+    HoughRootOutputTool.FPGATrackSimEventSelectionSvc = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimEventSelectionCfg(flags))
+    HoughRootOutputTool.FPGATrackSimMappingSvc = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimMappingCfg(flags))
+    HoughRootOutputTool.THistSvc = CompFactory.THistSvc()
+    result.setPrivateTools(HoughRootOutputTool)
+    return result
+
+def LRTRoadFinderCfg(flags):
+    result=ComponentAccumulator()
+    LRTRoadFinder =CompFactory.FPGATrackSimHoughTransform_d0phi0_Tool()
+    LRTRoadFinder.FPGATrackSimBankSvc = result.getPrimaryAndMerge(FPGATrackSimBankSvcCfg(flags))
+    LRTRoadFinder.FPGATrackSimMappingSvc = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimMappingCfg(flags))
+    LRTRoadFinder.combine_layers = flags.Trigger.FPGATrackSim.ActiveConfig.lrtStraighttrackCombineLayers
+    LRTRoadFinder.convolution = flags.Trigger.FPGATrackSim.ActiveConfig.lrtStraighttrackConvolution
+    LRTRoadFinder.hitExtend_x = flags.Trigger.FPGATrackSim.ActiveConfig.lrtStraighttrackHitExtendX
+    LRTRoadFinder.scale = flags.Trigger.FPGATrackSim.ActiveConfig.scale
+    LRTRoadFinder.threshold = flags.Trigger.FPGATrackSim.ActiveConfig.lrtStraighttrackThreshold
+    result.setPrivateTools(LRTRoadFinder)
+    return result
+
+def NNTrackToolCfg(flags):
+    result=ComponentAccumulator()
+    NNTrackTool = CompFactory.FPGATrackSimNNTrackTool()
+    NNTrackTool.THistSvc = CompFactory.THistSvc()
+    NNTrackTool.FPGATrackSimMappingSvc = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimMappingCfg(flags))
+    NNTrackTool.FPGATrackSimBankSvc = result.getPrimaryAndMerge(FPGATrackSimBankSvcCfg(flags))
+    NNTrackTool.IdealGeoRoads = (flags.Trigger.FPGATrackSim.ActiveConfig.IdealGeoRoads and flags.Trigger.FPGATrackSim.tracking)
+    NNTrackTool.useSpacePoints = flags.Trigger.FPGATrackSim.spacePoints and not flags.Trigger.FPGATrackSim.ActiveConfig.genScan
+    NNTrackTool.SPRoadFilterTool = getSPRoadFilterTool(flags)
+    NNTrackTool.MinNumberOfRealHitsInATrack = 5 if flags.Trigger.FPGATrackSim.ActiveConfig.genScan else 9
+
+    result.setPrivateTools(NNTrackTool)
+    return result
+
+def FPGATrackSimTrackFitterToolCfg(flags):
+    result=ComponentAccumulator()
+    TF_1st = CompFactory.FPGATrackSimTrackFitterTool("FPGATrackSimTrackFitterTool_1st")
+    TF_1st.GuessHits = flags.Trigger.FPGATrackSim.ActiveConfig.guessHits
+    TF_1st.IdealCoordFitType = flags.Trigger.FPGATrackSim.ActiveConfig.idealCoordFitType
+    TF_1st.FPGATrackSimBankSvc = result.getPrimaryAndMerge(FPGATrackSimBankSvcCfg(flags))
+    TF_1st.FPGATrackSimMappingSvc = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimMappingCfg(flags))
+    TF_1st.chi2DofRecoveryMax = flags.Trigger.FPGATrackSim.ActiveConfig.chi2DoFRecoveryMax
+    TF_1st.chi2DofRecoveryMin = flags.Trigger.FPGATrackSim.ActiveConfig.chi2DoFRecoveryMin
+    TF_1st.doMajority = flags.Trigger.FPGATrackSim.ActiveConfig.doMajority
+    TF_1st.nHits_noRecovery = flags.Trigger.FPGATrackSim.ActiveConfig.nHitsNoRecovery
+    TF_1st.DoDeltaGPhis = flags.Trigger.FPGATrackSim.ActiveConfig.doDeltaGPhis
+    TF_1st.DoMissingHitsChecks = flags.Trigger.FPGATrackSim.ActiveConfig.doMissingHitsChecks
+    TF_1st.IdealGeoRoads = (flags.Trigger.FPGATrackSim.ActiveConfig.IdealGeoRoads and flags.Trigger.FPGATrackSim.tracking)
+    TF_1st.useSpacePoints = flags.Trigger.FPGATrackSim.spacePoints and not flags.Trigger.FPGATrackSim.ActiveConfig.genScan
+    TF_1st.SPRoadFilterTool = getSPRoadFilterTool(flags)
+    result.addPublicTool(TF_1st, primary=True)
+    return result
+
+def FPGATrackSimOverlapRemovalToolCfg(flags):
+    result=ComponentAccumulator()
+    OR_1st = CompFactory.FPGATrackSimOverlapRemovalTool("FPGATrackSimOverlapRemovalTool_1st")
+    OR_1st.ORAlgo = "Normal"
+    OR_1st.doFastOR =flags.Trigger.FPGATrackSim.ActiveConfig.doFastOR
+    OR_1st.NumOfHitPerGrouping = 3
+    OR_1st.FPGATrackSimMappingSvc = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimMappingCfg(flags))
+    OR_1st.MinChi2 = flags.Trigger.FPGATrackSim.ActiveConfig.chi2cut
+    if flags.Trigger.FPGATrackSim.ActiveConfig.hough or flags.Trigger.FPGATrackSim.ActiveConfig.hough1D:
+        OR_1st.nBins_x = flags.Trigger.FPGATrackSim.ActiveConfig.xBins + 2 * flags.Trigger.FPGATrackSim.ActiveConfig.xBufferBins
+        OR_1st.nBins_y = flags.Trigger.FPGATrackSim.ActiveConfig.yBins + 2 * flags.Trigger.FPGATrackSim.ActiveConfig.yBufferBins
+        OR_1st.localMaxWindowSize = flags.Trigger.FPGATrackSim.ActiveConfig.localMaxWindowSize
+        OR_1st.roadSliceOR = flags.Trigger.FPGATrackSim.ActiveConfig.roadSliceOR
+
+    result.addPublicTool(OR_1st, primary=True)
+    return result
+
+def prepareFlagsForFPGATrackSimLogicalHitsProcessAlg(flags):
+    newFlags = flags.cloneAndReplace("Trigger.FPGATrackSim.ActiveConfig", "Trigger.FPGATrackSim." + flags.Trigger.FPGATrackSim.algoTag)
+    return newFlags
+
+def getSPRoadFilterTool(flags,secondStage=False):
+    name="FPGATrackSimSpacepointRoadFilterTool_1st"
+    if secondStage:
+        name="FPGATrackSimSpacepointRoadFilterTool_2st"
+    SPRoadFilter = CompFactory.FPGATrackSimSpacepointRoadFilterTool(name)
+    SPRoadFilter.filtering = flags.Trigger.FPGATrackSim.ActiveConfig.spacePointFiltering
+    SPRoadFilter.minSpacePlusPixel = flags.Trigger.FPGATrackSim.minSpacePlusPixel
+    SPRoadFilter.isSecondStage = secondStage
+    # TODO guard here against threshold being more than one value?
+    if (flags.Trigger.FPGATrackSim.ActiveConfig.hough1D):
+        SPRoadFilter.threshold = flags.Trigger.FPGATrackSim.Hough1D.threshold[0]
+    else:
+        SPRoadFilter.threshold = flags.Trigger.FPGATrackSim.ActiveConfig.threshold[0]
+    SPRoadFilter.setSectors = (flags.Trigger.FPGATrackSim.ActiveConfig.IdealGeoRoads and flags.Trigger.FPGATrackSim.tracking)
+    return SPRoadFilter
+
+def FPGATrackSimLogicalHitsProcessAlgCfg(inputFlags):
+
+    flags = prepareFlagsForFPGATrackSimLogicalHitsProcessAlg(inputFlags)
+
+    result=ComponentAccumulator()
+    if not flags.Trigger.FPGATrackSim.wrapperFileName:
+        from InDetConfig.InDetPrepRawDataFormationConfig import AthenaTrkClusterizationCfg
+        result.merge(AthenaTrkClusterizationCfg(flags))
+
+    theFPGATrackSimLogicalHitsProcessAlg=CompFactory.FPGATrackSimLogicalHitsProcessAlg()
+    theFPGATrackSimLogicalHitsProcessAlg.writeOutputData = flags.Trigger.FPGATrackSim.writeAdditionalOutputData
+    theFPGATrackSimLogicalHitsProcessAlg.tracking = flags.Trigger.FPGATrackSim.tracking
+    theFPGATrackSimLogicalHitsProcessAlg.doOverlapRemoval = flags.Trigger.FPGATrackSim.doOverlapRemoval
+    theFPGATrackSimLogicalHitsProcessAlg.DoMissingHitsChecks = flags.Trigger.FPGATrackSim.ActiveConfig.doMissingHitsChecks
+    theFPGATrackSimLogicalHitsProcessAlg.DoHoughRootOutput1st = flags.Trigger.FPGATrackSim.ActiveConfig.houghRootoutput1st
+    theFPGATrackSimLogicalHitsProcessAlg.NumOfHitPerGrouping = flags.Trigger.FPGATrackSim.ActiveConfig.NumOfHitPerGrouping
+    theFPGATrackSimLogicalHitsProcessAlg.DoNNTrack = flags.Trigger.FPGATrackSim.ActiveConfig.trackNNAnalysis
+    theFPGATrackSimLogicalHitsProcessAlg.eventSelector = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimEventSelectionCfg(flags))
+    theFPGATrackSimLogicalHitsProcessAlg.TrackScoreCut = flags.Trigger.FPGATrackSim.ActiveConfig.chi2cut
+    theFPGATrackSimLogicalHitsProcessAlg.passLowestChi2TrackOnly = flags.Trigger.FPGATrackSim.ActiveConfig.passLowestChi2TrackOnly
+    FPGATrackSimMaping = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimMappingCfg(flags))
+    theFPGATrackSimLogicalHitsProcessAlg.FPGATrackSimMapping = FPGATrackSimMaping
+
+    # If tracking is set to False, don't configure the bank service
+    if flags.Trigger.FPGATrackSim.tracking:
+        result.getPrimaryAndMerge(FPGATrackSimBankSvcCfg(flags))
+
+    if (flags.Trigger.FPGATrackSim.ActiveConfig.hough1D):
+        theFPGATrackSimLogicalHitsProcessAlg.RoadFinder = result.getPrimaryAndMerge(FPGATrackSimRoadUnionTool1DCfg(flags))
+    elif (flags.Trigger.FPGATrackSim.ActiveConfig.genScan):
+        theFPGATrackSimLogicalHitsProcessAlg.RoadFinder = result.getPrimaryAndMerge(FPGATrackSimRoadUnionToolGenScanCfg(flags))
+    elif (flags.Trigger.FPGATrackSim.ActiveConfig.GNN):
+        theFPGATrackSimLogicalHitsProcessAlg.RoadFinder = result.getPrimaryAndMerge(FPGATrackSimRoadUnionToolGNNCfg(flags))
+    else:
+        theFPGATrackSimLogicalHitsProcessAlg.RoadFinder = result.getPrimaryAndMerge(FPGATrackSimRoadUnionToolCfg(flags))
+
+    if (flags.Trigger.FPGATrackSim.ActiveConfig.etaPatternFilter):
+        EtaPatternFilter = CompFactory.FPGATrackSimEtaPatternFilterTool()
+        EtaPatternFilter.FPGATrackSimMappingSvc = FPGATrackSimMaping
+        EtaPatternFilter.threshold = flags.Trigger.FPGATrackSim.Hough1D.threshold[0]
+        EtaPatternFilter.EtaPatterns = flags.Trigger.FPGATrackSim.mapsDir+"/"+FPGATrackSimDataPrepConfig.getBaseName(flags)+".patt"
+        theFPGATrackSimLogicalHitsProcessAlg.RoadFilter = EtaPatternFilter
+        theFPGATrackSimLogicalHitsProcessAlg.FilterRoads = True
+
+    if (flags.Trigger.FPGATrackSim.ActiveConfig.phiRoadFilter):
+        RoadFilter2 = CompFactory.FPGATrackSimPhiRoadFilterTool()
+        RoadFilter2.FPGATrackSimMappingSvc = FPGATrackSimMaping
+        RoadFilter2.threshold = flags.Trigger.FPGATrackSim.Hough1D.threshold[0]
+        RoadFilter2.fieldCorrection = flags.Trigger.FPGATrackSim.ActiveConfig.fieldCorrection
+        ### set the window to be a constant value (could be changed), array should be length of the threshold
+        windows = [flags.Trigger.FPGATrackSim.Hough1D.phifilterwindow for i in range(len(flags.Trigger.FPGATrackSim.ActiveConfig.hitExtendX))]
+        RoadFilter2.window = windows
+
+        theFPGATrackSimLogicalHitsProcessAlg.RoadFilter2 = RoadFilter2
+        theFPGATrackSimLogicalHitsProcessAlg.FilterRoads2 = True
+
+
+    theFPGATrackSimLogicalHitsProcessAlg.HoughRootOutputTool = result.getPrimaryAndMerge(FPGATrackSimHoughRootOutputToolCfg(flags))
+
+    LRTRoadFilter = CompFactory.FPGATrackSimLLPRoadFilterTool()
+    result.addPublicTool(LRTRoadFilter)
+    theFPGATrackSimLogicalHitsProcessAlg.LRTRoadFilter = LRTRoadFilter
+
+    theFPGATrackSimLogicalHitsProcessAlg.LRTRoadFinder = result.getPrimaryAndMerge(LRTRoadFinderCfg(flags))
+    theFPGATrackSimLogicalHitsProcessAlg.NNTrackTool = result.getPrimaryAndMerge(NNTrackToolCfg(flags))
+
+    theFPGATrackSimLogicalHitsProcessAlg.OutputTool = result.getPrimaryAndMerge(FPGATrackSimWriteOutputCfg(flags))
+    theFPGATrackSimLogicalHitsProcessAlg.TrackFitter_1st = result.getPrimaryAndMerge(FPGATrackSimTrackFitterToolCfg(flags))
+    theFPGATrackSimLogicalHitsProcessAlg.OverlapRemoval_1st = result.getPrimaryAndMerge(FPGATrackSimOverlapRemovalToolCfg(flags))
+
+    # Create SPRoadFilterTool if spacepoints are turned on. TODO: make things configurable?
+    if flags.Trigger.FPGATrackSim.spacePoints and not flags.Trigger.FPGATrackSim.ActiveConfig.genScan:
+        theFPGATrackSimLogicalHitsProcessAlg.SPRoadFilterTool = getSPRoadFilterTool(flags)
+        theFPGATrackSimLogicalHitsProcessAlg.Spacepoints = True
+
+
+    if flags.Trigger.FPGATrackSim.ActiveConfig.lrt:
+        assert flags.Trigger.FPGATrackSim.ActiveConfig.lrtUseBasicHitFilter != flags.Trigger.FPGATrackSim.ActiveConfig.lrtUseMlHitFilter, 'Inconsistent LRT hit filtering setup, need either ML of Basic filtering enabled'
+        assert flags.Trigger.FPGATrackSim.ActiveConfig.lrtUseStraightTrackHT != flags.Trigger.FPGATrackSim.ActiveConfig.lrtUseDoubletHT, 'Inconsistent LRT HT setup, need either double or strightTrack enabled'
+        theFPGATrackSimLogicalHitsProcessAlg.doLRT = True
+        theFPGATrackSimLogicalHitsProcessAlg.LRTHitFiltering = (not flags.Trigger.FPGATrackSim.ActiveConfig.lrtSkipHitFiltering)
+
+    from FPGATrackSimAlgorithms.FPGATrackSimAlgorithmConfig import FPGATrackSimLogicalHitsProcessAlgMonitoringCfg
+    theFPGATrackSimLogicalHitsProcessAlg.MonTool = result.getPrimaryAndMerge(FPGATrackSimLogicalHitsProcessAlgMonitoringCfg(flags))
+
+    result.addEventAlgo(theFPGATrackSimLogicalHitsProcessAlg)
+
+    return result
+
+def getChi2Cut(region):
+    #list of chi2 cuts for time being. Last four are stand ins since those new regions don't work for now!
+    chi2cut_l = [12, 16, 60, 16, 60, 60, 14, 20, 16, 19, 19, 15, 18, 12, 15, 15, 20, 20, 20, 20]
+    binSize = 0.2
+    side = (region >> 5) & 0x1
+    etaBin = (region >> 6) & 0x1F
+    etaRange = [round(binSize * etaBin, 1), round(binSize * (etaBin + 1), 1)] if side else [round(-binSize * (etaBin + 1), 1), round(-binSize * etaBin, 1)]
+    abs_etaRange = tuple(abs(val) for val in etaRange)
+
+    eta_to_chi2 = {
+        (0.0, 0.2): chi2cut_l[0], (0.2, 0.4): chi2cut_l[1], (0.4, 0.6): chi2cut_l[2],
+        (0.6, 0.8): chi2cut_l[3], (0.8, 1.0): chi2cut_l[4], (1.0, 1.2): chi2cut_l[5],
+        (1.2, 1.4): chi2cut_l[6], (1.4, 1.6): chi2cut_l[7], (1.6, 1.8): chi2cut_l[8],
+        (1.8, 2.0): chi2cut_l[9], (2.0, 2.2): chi2cut_l[10], (2.2, 2.4): chi2cut_l[11],
+        (2.4, 2.6): chi2cut_l[12], (2.6, 2.8): chi2cut_l[13], (2.8, 3.0): chi2cut_l[14],
+        (3.0, 3.2): chi2cut_l[15], (3.2, 3.4): chi2cut_l[16], (3.4, 3.6): chi2cut_l[17], 
+        (3.6, 3.8): chi2cut_l[18], (3.8, 4.0): chi2cut_l[19]
+    }
+
+    return eta_to_chi2.get(abs_etaRange, 9) #i set it back to default chi2 if the region is not found
+
+
+if __name__ == "__main__":
+    from AthenaConfiguration.AllConfigFlags import initConfigFlags
+    from AthenaConfiguration.MainServicesConfig import MainServicesCfg
+
+
+
+    flags = initConfigFlags()
+
+    ############################################
+    # Flags used in the prototrack chain
+    FinalProtoTrackChainxAODTracksKey="FPGA"
+    flags.Detector.EnableCalo = False
+
+    # ensure that the xAOD SP and cluster containers are available
+    flags.Tracking.ITkMainPass.doAthenaToActsSpacePoint=True
+    flags.Tracking.ITkMainPass.doAthenaToActsCluster=True
+    from TrkConfig.TrkConfigFlags import TrackingComponent
+    flags.Tracking.recoChain = [TrackingComponent.ActsChain] # another viable option is TrackingComponent.AthenaChain
+    flags.Acts.doRotCorrection = False
+
+    ############################################
+    flags.Concurrency.NumThreads=1
+    #flags.Concurrency.NumProcs=0
+    flags.Scheduler.ShowDataDeps=True
+    flags.Scheduler.CheckDependencies=True
+    flags.Debug.DumpEvtStore=False
+
+    # flags.Exec.DebugStage="exec" # useful option to debug the execution of the job - we want it commented out for production
+    flags.fillFromArgs()
+
+    if flags.Trigger.FPGATrackSim.Hough.useVaryingChi2Cut: 
+        flags.Trigger.FPGATrackSim.Hough.chi2cut = getChi2Cut(flags.Trigger.FPGATrackSim.region) 
+
+    assert not flags.Trigger.FPGATrackSim.pipeline.startswith('F-5'),"ERROR You are trying to run an F-5* pipeline! This is not yet supported!"
+
+    if (flags.Trigger.FPGATrackSim.pipeline.startswith('F-1')):
+        print("You are trying to run an F-100 pipeline! I am going to run the Data Prep chain for you and nothing else!")
+        FPGATrackSimDataPrepConfig.runDataPrepChain()
+    elif (flags.Trigger.FPGATrackSim.pipeline.startswith('F-2')):
+        print("You are trying to run an F-2* pipeline! I am auto-configuring the 1D bitshift for you, including eta pattern filters and phi road filters")
+        flags.Trigger.FPGATrackSim.Hough.etaPatternFilter = True
+        flags.Trigger.FPGATrackSim.Hough.phiRoadFilter = True
+        flags.Trigger.FPGATrackSim.Hough.hough1D = True
+        flags.Trigger.FPGATrackSim.Hough.hough = False
+    elif (flags.Trigger.FPGATrackSim.pipeline.startswith('F-3')):
+        print("You are trying to run an F-3* pipeline! I am auto-configuring the 2D HT for you, and disabling the eta pattern filter and phi road filter. Whether you wanted to or not")
+        flags.Trigger.FPGATrackSim.Hough.etaPatternFilter = False
+        flags.Trigger.FPGATrackSim.Hough.phiRoadFilter = False
+        flags.Trigger.FPGATrackSim.Hough.hough1D = False
+        flags.Trigger.FPGATrackSim.Hough.hough = True
+    elif (flags.Trigger.FPGATrackSim.pipeline.startswith('F-4')):
+        print("You are trying to run an F-4* pipeline! I am auto-configuring the GNN pattern recognition for you. Whether you wanted to or not")
+        flags.Trigger.FPGATrackSim.Hough.GNN = True
+        flags.Trigger.FPGATrackSim.Hough.chi2cut = 25 # All of the track candidates have chi2 values around 20 for some reason. Needs further investigation. For now move the default cut value to 25
+    elif flags.Trigger.FPGATrackSim.pipeline.startswith('F-6'):
+        print("You are trying to run an F-6* pipeline! I am auto-configuring the Inside-Out for you. Whether you wanted to or not.")
+        flags.Trigger.FPGATrackSim.Hough.genScan = True
+        flags.Trigger.FPGATrackSim.spacePoints = flags.Trigger.FPGATrackSim.Hough.secondStage
+
+    elif (flags.Trigger.FPGATrackSim.pipeline != ""):
+        raise AssertionError("ERROR You are trying to run the pipeline " + flags.Trigger.FPGATrackSim.pipeline + " which is not yet supported!")
+
+    if (not flags.Trigger.FPGATrackSim.pipeline.startswith('F-1')): ### if DP pipeline skip everything else!
+
+        splitPipeline=flags.Trigger.FPGATrackSim.pipeline.split('-')
+        trackingOption=9999999
+        if (len(splitPipeline) > 1): trackingOption=int(splitPipeline[1])
+        if (trackingOption < 9999999):
+            trackingOptionMod = (trackingOption % 100)
+            if (trackingOptionMod == 0):
+                print("You are trying to run the linearized chi2 fit as part of a pipeline! I am going to enable this for you whether you want to or not")
+                flags.Trigger.FPGATrackSim.tracking = True
+                flags.Trigger.FPGATrackSim.Hough.trackNNAnalysis = False
+            elif (trackingOptionMod == 10):
+                print("You are trying to run the NN fake rejection as part of a pipeline! I am going to enable this for you whether you want to or not")
+                flags.Trigger.FPGATrackSim.tracking = True
+                flags.Trigger.FPGATrackSim.Hough.trackNNAnalysis = True
+            else:
+                raise AssertionError("ERROR Your tracking option for the pipeline = " + str(trackingOption) + " is not yet supported!")
+
+        if isinstance(flags.Trigger.FPGATrackSim.wrapperFileName, str):
+            log.info("wrapperFile is string, converting to list")
+            flags.Trigger.FPGATrackSim.wrapperFileName = [flags.Trigger.FPGATrackSim.wrapperFileName]
+            flags.Input.Files = lambda f: [f.Trigger.FPGATrackSim.wrapperFileName]
+
+        flags.lock()
+        flags.dump()
+        flags = flags.cloneAndReplace("Tracking.ActiveConfig","Tracking.MainPass")
+        acc=MainServicesCfg(flags)
+
+        if flags.Trigger.FPGATrackSim.writeAdditionalOutputData:
+            acc.addService(CompFactory.THistSvc(Output = ["EXPERT DATAFILE='monitoring.root', OPT='RECREATE'"]))
+
+            if (flags.Trigger.FPGATrackSim.Hough.trackNNAnalysis):
+                acc.addService(CompFactory.THistSvc(Output = ["FPGATRACKSIMOUTPUTNNPATHFINDER DATAFILE='NNPathfinder.root', OPT='RECREATE'"]))
+
+            if (flags.Trigger.FPGATrackSim.Hough.houghRootoutput1st | flags.Trigger.FPGATrackSim.Hough.houghRootoutput2nd):
+                acc.addService(CompFactory.THistSvc(Output = ["TRIGFPGATrackSimHOUGHOUTPUT DATAFILE='HoughRootOutput.root', OPT='RECREATE'"]))
+
+            if flags.Trigger.FPGATrackSim.Hough.writeTestOutput:
+                acc.addService(CompFactory.THistSvc(Output = ["FPGATRACKSIMOUTPUT DATAFILE='test.root', OPT='RECREATE'"]))
+
+            if (flags.Trigger.FPGATrackSim.Hough.genScan):
+                acc.addService(CompFactory.THistSvc(Output = ["GENSCAN DATAFILE='genscan.root', OPT='RECREATE'"]))
+
+        if not flags.Trigger.FPGATrackSim.wrapperFileName:
+            from AthenaPoolCnvSvc.PoolReadConfig import PoolReadCfg
+            acc.merge(PoolReadCfg(flags))
+
+            if flags.Input.isMC:
+                from xAODTruthCnv.xAODTruthCnvConfig import GEN_AOD2xAODCfg
+                acc.merge(GEN_AOD2xAODCfg(flags))
+
+                from JetRecConfig.JetRecoSteering import addTruthPileupJetsToOutputCfg # TO DO: check if this is indeed necessary for pileup samples
+                acc.merge(addTruthPileupJetsToOutputCfg(flags))
+
+            if flags.Detector.EnableCalo:
+                from CaloRec.CaloRecoConfig import CaloRecoCfg
+                acc.merge(CaloRecoCfg(flags))
+
+            if flags.Tracking.recoChain:
+                from InDetConfig.TrackRecoConfig import InDetTrackRecoCfg
+                acc.merge(InDetTrackRecoCfg(flags))
+
+        # Configure both the dataprep and logical hits algorithms.
+        acc.merge(FPGATrackSimDataPrepConfig.FPGATrackSimDataPrepAlgCfg(flags))
+        acc.merge(FPGATrackSimLogicalHitsProcessAlgCfg(flags))
+
+        # If second stage is turned on, turn that algorithm on too.
+        if flags.Trigger.FPGATrackSim.Hough.secondStage:
+            acc.merge(FPGATrackSimSecondStageConfig.FPGATrackSimSecondStageAlgCfg(flags))
+        
+        #if (not flags.Trigger.FPGATrackSim.oldRegionDefs):                                                                          
+         #   flags.Trigger.FPGATrackSim.Hough.chi2cut = getChi2Cut(flags.Trigger.FPGATrackSim.region)
+        #print(f"Chi2 cut set to: {flags.Trigger.FPGATrackSim.Hough.chi2cut}")
+
+        if flags.Trigger.FPGATrackSim.doEDMConversion:
+            stage = "_2nd" if flags.Trigger.FPGATrackSim.Hough.secondStage else "_1st"
+            convertTracks = flags.Trigger.FPGATrackSim.tracking
+            acc.merge(FPGATrackSimDataPrepConfig.FPGAConversionAlgCfg(flags, name = f"FPGAConversionAlg{stage}",
+                                                                        stage = f"{stage}",
+                                                                        doActsTrk=True,
+                                                                        doSP=flags.Trigger.FPGATrackSim.spacePoints,
+                                                                        useRoads=not flags.Trigger.FPGATrackSim.tracking))
+
+            from FPGATrackSimPrototrackFitter.FPGATrackSimPrototrackFitterConfig import FPGATruthDecorationCfg, FPGAProtoTrackFitCfg
+            acc.merge(FPGAProtoTrackFitCfg(flags,stage=f"{stage}",
+                                            useRoads=not flags.Trigger.FPGATrackSim.tracking)) # Run ACTS KF
+            acc.merge(FPGATruthDecorationCfg(flags,FinalProtoTrackChainxAODTracksKey=FinalProtoTrackChainxAODTracksKey,stage=f"{stage}")) # Run Truth Matching/Decoration chain
+            if not flags.Trigger.FPGATrackSim.wrapperFileName and flags.Trigger.FPGATrackSim.runCKF:
+                from FPGATrackSimConfTools.FPGATrackExtensionConfig import FPGATrackExtensionAlgCfg
+                acc.merge(FPGATrackExtensionAlgCfg(flags, enableTrackStatePrinter=False, name="FPGATrackExtension",
+                                                    ProtoTracksLocation=f"ActsProtoTracks{stage}FromFPGATrack")) # run CKF track extension on FPGA tracks
+
+            if flags.Trigger.FPGATrackSim.writeToAOD: acc.merge(FPGATrackSimDataPrepConfig.WriteToAOD(flags,
+                                                                                                        stage = f"{stage}",
+                                                                                                        finalTrackParticles=f"{FinalProtoTrackChainxAODTracksKey}TrackParticles"))
+
+            # Reporting algorithm (used for debugging - can be disabled)
+            from FPGATrackSimReporting.FPGATrackSimReportingConfig import FPGATrackSimReportingCfg
+            acc.merge(FPGATrackSimReportingCfg(flags, stage=f"{stage}",
+                                                perEventReports = ((flags.Trigger.FPGATrackSim.sampleType != 'skipTruth') and flags.Exec.MaxEvents<=10 ) )) # disable perEventReports for pileup samples or many events
+
+        acc.store(open('AnalysisConfig.pkl','wb'))
+
+        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
+
+        statusCode = acc.run(flags.Exec.MaxEvents)
+        assert statusCode.isSuccess() is True, "Application execution did not succeed"
diff --git a/Trigger/EFTracking/FPGATrackSim/FPGATrackSimConfTools/python/FPGATrackSimConfigFlags.py b/Trigger/EFTracking/FPGATrackSim/FPGATrackSimConfTools/python/FPGATrackSimConfigFlags.py
index 79d4ab21b275..cfdce84e0797 100755
--- a/Trigger/EFTracking/FPGATrackSim/FPGATrackSimConfTools/python/FPGATrackSimConfigFlags.py
+++ b/Trigger/EFTracking/FPGATrackSim/FPGATrackSimConfTools/python/FPGATrackSimConfigFlags.py
@@ -180,7 +180,7 @@ def createBasicFPGATrackSimConfigFlags():
     cf.addFlag('idealCoordFitType', 2)
     cf.addFlag('doDeltaGPhis', False)
     cf.addFlag('chi2cut', 9)
-
+    cf.addFlag('useVaryingChi2Cut', False)
     # second stage fitting
     cf.addFlag('secondStage', False)
     cf.addFlag('secondChi2Cut', 36)
-- 
GitLab


From 4d0cca13a22fc66114b1a061d2f2c20d8ab20664 Mon Sep 17 00:00:00 2001
From: Joseph Philip Surdutovich <surdutovich.1@buckeyemail.osu.edu>
Date: Mon, 31 Mar 2025 04:53:28 +0000
Subject: [PATCH 2/3] Replace FPGATrackSimAnalysisConfig.py

---
 .../python/FPGATrackSimAnalysisConfig.py      | 1414 ++++++++---------
 1 file changed, 693 insertions(+), 721 deletions(-)

diff --git a/Trigger/EFTracking/FPGATrackSim/FPGATrackSimConfTools/python/FPGATrackSimAnalysisConfig.py b/Trigger/EFTracking/FPGATrackSim/FPGATrackSimConfTools/python/FPGATrackSimAnalysisConfig.py
index e69d74f1ff28..25d3fc9cea6c 100755
--- a/Trigger/EFTracking/FPGATrackSim/FPGATrackSimConfTools/python/FPGATrackSimAnalysisConfig.py
+++ b/Trigger/EFTracking/FPGATrackSim/FPGATrackSimConfTools/python/FPGATrackSimAnalysisConfig.py
@@ -1,721 +1,693 @@
-# Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
-from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
-from AthenaConfiguration.ComponentFactory import CompFactory
-from AthenaCommon.Logging import AthenaLogger
-from PathResolver import PathResolver
-import importlib
-
-log = AthenaLogger(__name__)
-
-#### Now inmport Data Prep config from other file
-from FPGATrackSimConfTools import FPGATrackSimDataPrepConfig
-from FPGATrackSimConfTools import FPGATrackSimSecondStageConfig
-
-def getNSubregions(filePath):
-    with open(PathResolver.FindCalibFile(filePath), 'r') as f:
-        fields = f.readline()
-        assert(fields.startswith('towers'))
-        n = fields.split()[1]
-        return int(n)
-
-
-# Need to figure out if we have two output writers or somehow only one.
-def FPGATrackSimWriteOutputCfg(flags):
-    result=ComponentAccumulator()
-    FPGATrackSimWriteOutput = CompFactory.FPGATrackSimOutputHeaderTool("FPGATrackSimWriteOutput")
-    FPGATrackSimWriteOutput.InFileName = ["test.root"]
-    # RECREATE means that that this tool opens the file.
-    # HEADER would mean that something else (e.g. THistSvc) opens it and we just add the object.
-    FPGATrackSimWriteOutput.RWstatus = "HEADER"
-    FPGATrackSimWriteOutput.THistSvc = CompFactory.THistSvc()
-    result.addPublicTool(FPGATrackSimWriteOutput, primary=True)
-    return result
-
-
-
-def FPGATrackSimBankSvcCfg(flags):
-    result=ComponentAccumulator()
-    FPGATrackSimBankSvc = CompFactory.FPGATrackSimBankSvc()
-    pathBankSvc = flags.Trigger.FPGATrackSim.bankDir if flags.Trigger.FPGATrackSim.bankDir != '' else f'/eos/atlas/atlascerngroupdisk/det-htt/HTTsim/{flags.GeoModel.AtlasVersion}/21.9.16/'+FPGATrackSimDataPrepConfig.getBaseName(flags)+'/SectorBanks/'
-    pathBankSvc=PathResolver.FindCalibDirectory(pathBankSvc)
-    FPGATrackSimBankSvc.constantsNoGuess_1st = [
-        f'{pathBankSvc}corrgen_raw_8L_skipPlane0.gcon',
-        f'{pathBankSvc}corrgen_raw_8L_skipPlane1.gcon',
-        f'{pathBankSvc}corrgen_raw_8L_skipPlane2.gcon',
-        f'{pathBankSvc}corrgen_raw_8L_skipPlane3.gcon',
-        f'{pathBankSvc}corrgen_raw_8L_skipPlane4.gcon',
-        f'{pathBankSvc}corrgen_raw_8L_skipPlane5.gcon',
-        f'{pathBankSvc}corrgen_raw_8L_skipPlane6.gcon',
-        f'{pathBankSvc}corrgen_raw_8L_skipPlane7.gcon']
-    FPGATrackSimBankSvc.constantsNoGuess_2nd = [
-        f'{pathBankSvc}corrgen_raw_13L_skipPlane0.gcon',
-        f'{pathBankSvc}corrgen_raw_13L_skipPlane1.gcon',
-        f'{pathBankSvc}corrgen_raw_13L_skipPlane2.gcon',
-        f'{pathBankSvc}corrgen_raw_13L_skipPlane3.gcon',
-        f'{pathBankSvc}corrgen_raw_13L_skipPlane4.gcon',
-        f'{pathBankSvc}corrgen_raw_13L_skipPlane5.gcon',
-        f'{pathBankSvc}corrgen_raw_13L_skipPlane6.gcon',
-        f'{pathBankSvc}corrgen_raw_13L_skipPlane7.gcon']
-    layers="5L" if flags.Trigger.FPGATrackSim.ActiveConfig.genScan else "9L"
-    FPGATrackSimBankSvc.constants_1st = f'{pathBankSvc}corrgen_raw_{layers}_reg{flags.Trigger.FPGATrackSim.region}_checkGood1.gcon'
-    FPGATrackSimBankSvc.constants_2nd = f'{pathBankSvc}corrgen_raw_13L_reg{flags.Trigger.FPGATrackSim.region}_checkGood1.gcon'
-    FPGATrackSimBankSvc.sectorBank_1st = f'{pathBankSvc}sectorsHW_raw_{layers}_reg{flags.Trigger.FPGATrackSim.region}_checkGood1.patt'
-    FPGATrackSimBankSvc.sectorBank_2nd = f'{pathBankSvc}sectorsHW_raw_13L_reg{flags.Trigger.FPGATrackSim.region}_checkGood1.patt'
-    FPGATrackSimBankSvc.sectorSlices = f'{pathBankSvc}slices_{layers}_reg{flags.Trigger.FPGATrackSim.region}.root'
-    FPGATrackSimBankSvc.phiShift = flags.Trigger.FPGATrackSim.phiShift
-
-    # These should be configurable. The tag system needs updating though.
-    FPGATrackSimBankSvc.sectorQPtBins = [-0.001, -0.0005, 0, 0.0005, 0.001]
-    FPGATrackSimBankSvc.qptAbsBinning = False
-
-    result.addService(FPGATrackSimBankSvc, create=True, primary=True)
-    return result
-
-
-def FPGATrackSimRoadUnionToolCfg(flags):
-    result=ComponentAccumulator()
-    RF = CompFactory.FPGATrackSimRoadUnionTool()
-
-    xBins = flags.Trigger.FPGATrackSim.ActiveConfig.xBins
-    xBufferBins = flags.Trigger.FPGATrackSim.ActiveConfig.xBufferBins
-    yBins = flags.Trigger.FPGATrackSim.ActiveConfig.yBins
-    yBufferBins = flags.Trigger.FPGATrackSim.ActiveConfig.yBufferBins
-    yMin = flags.Trigger.FPGATrackSim.ActiveConfig.qptMin
-    yMax = flags.Trigger.FPGATrackSim.ActiveConfig.qptMax
-    xMin = flags.Trigger.FPGATrackSim.ActiveConfig.phiMin
-    xMax = flags.Trigger.FPGATrackSim.ActiveConfig.phiMax
-    if (not flags.Trigger.FPGATrackSim.oldRegionDefs): ### auto-configure this
-        phiRange = FPGATrackSimDataPrepConfig.getPhiRange(flags)
-        xMin = phiRange[0]
-        xMax = phiRange[1]
-
-    xBuffer = (xMax - xMin) / xBins * xBufferBins
-    xMin = xMin - xBuffer
-    xMax = xMax +  xBuffer
-    yBuffer = (yMax - yMin) / yBins * yBufferBins
-    yMin -= yBuffer
-    yMax += yBuffer
-    tools = []
-
-    FPGATrackSimMapping = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimMappingCfg(flags))
-    for number in range(getNSubregions(FPGATrackSimMapping.subrmap)):
-        HoughTransform = CompFactory.FPGATrackSimHoughTransformTool("HoughTransform_0_" + str(number))
-        HoughTransform.FPGATrackSimEventSelectionSvc = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimEventSelectionCfg(flags))
-        HoughTransform.FPGATrackSimBankSvc = result.getPrimaryAndMerge(FPGATrackSimBankSvcCfg(flags))
-        HoughTransform.FPGATrackSimMappingSvc = FPGATrackSimMapping
-        HoughTransform.combine_layers = flags.Trigger.FPGATrackSim.ActiveConfig.combineLayers
-        HoughTransform.convSize_x = flags.Trigger.FPGATrackSim.ActiveConfig.convSizeX
-        HoughTransform.convSize_y = flags.Trigger.FPGATrackSim.ActiveConfig.convSizeY
-        HoughTransform.convolution = flags.Trigger.FPGATrackSim.ActiveConfig.convolution
-        HoughTransform.d0_max = 0
-        HoughTransform.d0_min = 0
-        HoughTransform.fieldCorrection = flags.Trigger.FPGATrackSim.ActiveConfig.fieldCorrection
-        HoughTransform.hitExtend_x = flags.Trigger.FPGATrackSim.ActiveConfig.hitExtendX
-        HoughTransform.localMaxWindowSize = flags.Trigger.FPGATrackSim.ActiveConfig.localMaxWindowSize
-        HoughTransform.nBins_x = xBins + 2 * xBufferBins
-        HoughTransform.nBins_y = yBins + 2 * yBufferBins
-        HoughTransform.phi_max = xMax
-        HoughTransform.phi_min = xMin
-        HoughTransform.qpT_max = yMax
-        HoughTransform.qpT_min = yMin
-        HoughTransform.scale = flags.Trigger.FPGATrackSim.ActiveConfig.scale
-        HoughTransform.subRegion = number
-        HoughTransform.threshold = flags.Trigger.FPGATrackSim.ActiveConfig.threshold
-        HoughTransform.traceHits = True
-        HoughTransform.IdealGeoRoads = (flags.Trigger.FPGATrackSim.ActiveConfig.IdealGeoRoads and flags.Trigger.FPGATrackSim.tracking)
-        HoughTransform.useSpacePoints = flags.Trigger.FPGATrackSim.spacePoints
-
-        tools.append(HoughTransform)
-
-    RF.tools = tools
-    result.addPublicTool(RF, primary=True)
-    return result
-
-def FPGATrackSimRoadUnionTool1DCfg(flags):
-    result=ComponentAccumulator()
-    tools = []
-    RF = CompFactory.FPGATrackSimRoadUnionTool()
-    splitpt=flags.Trigger.FPGATrackSim.Hough1D.splitpt
-    FPGATrackSimMapping = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimMappingCfg(flags))
-    for ptstep in range(splitpt):
-        qpt_min = flags.Trigger.FPGATrackSim.Hough1D.qptMin
-        qpt_max = flags.Trigger.FPGATrackSim.Hough1D.qptMax
-        lowpt = qpt_min + (qpt_max-qpt_min)/splitpt*ptstep
-        highpt = qpt_min + (qpt_max-qpt_min)/splitpt*(ptstep+1)
-        nSlice = getNSubregions(FPGATrackSimMapping.subrmap)
-        for iSlice in range(nSlice):
-            tool = CompFactory.FPGATrackSimHough1DShiftTool("Hough1DShift" + str(iSlice)+(("_pt{}".format(ptstep))  if splitpt>1 else ""))
-            tool.subRegion = iSlice if nSlice > 1 else -1
-            xMin = flags.Trigger.FPGATrackSim.Hough1D.phiMin
-            xMax = flags.Trigger.FPGATrackSim.Hough1D.phiMax
-            if (not flags.Trigger.FPGATrackSim.oldRegionDefs): ### auto-configure this
-                phiRange = FPGATrackSimDataPrepConfig.getPhiRange(flags)
-                xMin = phiRange[0]
-                xMax = phiRange[1]
-            tool.phiMin = xMin
-            tool.phiMax = xMax
-            tool.qptMin = lowpt
-            tool.qptMax = highpt
-            tool.nBins = flags.Trigger.FPGATrackSim.Hough1D.xBins
-            tool.useDiff = True
-            tool.variableExtend = True
-            tool.drawHitMasks = False
-            tool.phiRangeCut = flags.Trigger.FPGATrackSim.Hough1D.phiRangeCut
-            tool.d0spread=-1.0 # mm
-            tool.iterStep = 0 # auto, TODO put in tag
-            tool.iterLayer = 7 # TODO put in tag
-            tool.threshold = flags.Trigger.FPGATrackSim.Hough1D.threshold[0]
-            tool.hitExtend = flags.Trigger.FPGATrackSim.Hough1D.hitExtendX
-            tool.FPGATrackSimEventSelectionSvc = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimEventSelectionCfg(flags))
-            tool.FPGATrackSimBankSvc = result.getPrimaryAndMerge(FPGATrackSimBankSvcCfg(flags))
-            tool.FPGATrackSimMappingSvc = FPGATrackSimMapping
-            tool.IdealGeoRoads = (flags.Trigger.FPGATrackSim.ActiveConfig.IdealGeoRoads and flags.Trigger.FPGATrackSim.tracking)
-            tool.useSpacePoints = flags.Trigger.FPGATrackSim.spacePoints
-
-            tools.append(tool)
-
-    RF.tools = tools
-    result.addPublicTool(RF, primary=True)
-    return result
-
-
-
-def FPGATrackSimRoadUnionToolGenScanCfg(flags):
-    result=ComponentAccumulator()
-
-    # read the cuts from a seperate python file specified by FPGATrackSim.GenScan.genScanCuts
-    cutset=None
-    if flags.Trigger.FPGATrackSim.oldRegionDefs:
-        toload=flags.Trigger.FPGATrackSim.GenScan.genScanCuts
-        if toload == 'FPGATrackSimGenScanCuts': # its on the newRegion default so it hasn't been set
-            toload = 'FPGATrackSimHough.FPGATrackSimGenScanCuts_incr'
-        cutset = importlib.import_module(toload).cuts[flags.Trigger.FPGATrackSim.region]
-    else:
-        # this allows the cut file defined in python to be loaded from the map directory
-        print("Cut File = ", flags.Trigger.FPGATrackSim.GenScan.genScanCuts,
-                                                    flags.Trigger.FPGATrackSim.mapsDir+"/{}.py".format(flags.Trigger.FPGATrackSim.GenScan.genScanCuts))
-        spec=importlib.util.spec_from_file_location(flags.Trigger.FPGATrackSim.GenScan.genScanCuts,
-                                                    flags.Trigger.FPGATrackSim.mapsDir+"/{}.py".format(flags.Trigger.FPGATrackSim.GenScan.genScanCuts))
-        if spec is None:
-            print("Failed to find Cut File")
-        cutmodule = importlib.util.module_from_spec(spec)
-        spec.loader.exec_module(cutmodule)
-        cutset=cutmodule.cuts[flags.Trigger.FPGATrackSim.region]
-
-    # make the binning class
-    Binning = None
-    if (cutset["parSet"]=="PhiSlicedKeyLyrPars") :
-        Binning = CompFactory.FPGATrackSimGenScanPhiSlicedKeyLyrBinning("GenScanBinning")
-        Binning.approxMath = False
-    else:
-        log.error("Unknown Binning")
-    Binning.rin=cutset["rin"]
-    Binning.rout=cutset["rout"]
-    Binning.OutputLevel=flags.Trigger.FPGATrackSim.loglevel
-
-    # make the monitoring class
-    Monitor = CompFactory.FPGATrackSimGenScanMonitoring("GenScanMonitoring")
-    Monitor.THistSvc = CompFactory.THistSvc()
-    Monitor.OutputLevel=flags.Trigger.FPGATrackSim.loglevel
-
-    # make the main tool
-    tool = CompFactory.FPGATrackSimGenScanTool("GenScanTool")
-    tool.FPGATrackSimEventSelectionSvc = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimEventSelectionCfg(flags))
-    tool.FPGATrackSimBankSvc = result.getPrimaryAndMerge(FPGATrackSimBankSvcCfg(flags))
-    tool.FPGATrackSimMappingSvc = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimMappingCfg(flags))
-    tool.Monitoring = Monitor
-    tool.Binning = Binning
-    tool.OutputLevel=flags.Trigger.FPGATrackSim.loglevel
-
-    # configure which filers and thresholds to apply
-    tool.binFilter=flags.Trigger.FPGATrackSim.GenScan.binFilter
-    tool.reversePairDir=flags.Trigger.FPGATrackSim.GenScan.reverse
-    tool.applyPairFilter= not flags.Trigger.FPGATrackSim.GenScan.noCuts
-    tool.applyPairSetFilter= not flags.Trigger.FPGATrackSim.GenScan.noCuts
-    tool.threshold = 4
-
-    # configure the padding around the nominal region
-    tool.d0FractionalPadding =0.05
-    tool.z0FractionalPadding =0.05
-    tool.etaFractionalPadding =0.05
-    tool.phiFractionalPadding =0.05
-    tool.qOverPtFractionalPadding =0.05
-
-    # set cuts
-    for (cut,val) in cutset.items():
-        setattr(tool,cut,val)
-
-    # set layer map
-    if not flags.Trigger.FPGATrackSim.GenScan.layerStudy:
-        if flags.Trigger.FPGATrackSim.oldRegionDefs:
-            tool.layerMapFile = flags.Trigger.FPGATrackSim.GenScan.layerMapFile
-        else:
-            # now assumed to be in the map directory with name = basename for region + _lyrmap.json
-            tool.layerMapFile = flags.Trigger.FPGATrackSim.mapsDir+"/"+FPGATrackSimDataPrepConfig.getBaseName(flags)+"_lyrmap.json"
-
-    # even though we are not actually doing a Union, we need the
-    # RoadUnionTool because mapping is now there
-    RoadUnion = CompFactory.FPGATrackSimRoadUnionTool()
-    RoadUnion.tools = [tool,]
-    result.addPublicTool(RoadUnion, primary=True)
-
-    # special configuration for studing layer definitions
-    # pass through all hits, but turn off pairing because
-    # it won't be able to run
-    if flags.Trigger.FPGATrackSim.GenScan.layerStudy:
-        RoadUnion.noHitFilter=True
-        tool.binningOnly=True
-    return result
-
-def FPGATrackSimRoadUnionToolGNNCfg(flags):
-    result = ComponentAccumulator()
-    RF = CompFactory.FPGATrackSimRoadUnionTool()
-
-    patternRecoTool = CompFactory.FPGATrackSimGNNPatternRecoTool()
-    patternRecoTool.GNNGraphHitSelector = CompFactory.FPGATrackSimGNNGraphHitSelectorTool()
-    patternRecoTool.GNNGraphConstruction = result.popToolsAndMerge(FPGATrackSimGNNGraphConstructionToolCfg(flags))
-    patternRecoTool.GNNEdgeClassifier = result.popToolsAndMerge(FPGATrackSimGNNEdgeClassifierToolCfg(flags))
-    patternRecoTool.GNNRoadMaker = result.popToolsAndMerge(FPGATrackSimGNNRoadMakerToolCfg(flags))
-    patternRecoTool.GNNRootOutput = result.popToolsAndMerge(FPGATrackSimGNNRootOutputToolCfg(flags))
-    patternRecoTool.doGNNRootOutput = flags.Trigger.FPGATrackSim.GNN.doGNNRootOutput
-
-    RF.tools = [patternRecoTool]
-    result.addPublicTool(RF, primary=True)
-
-    return result
-
-def FPGATrackSimGNNGraphConstructionToolCfg(flags):
-    result = ComponentAccumulator()
-
-    GNNGraphConstructionTool = CompFactory.FPGATrackSimGNNGraphConstructionTool()
-    GNNGraphConstructionTool.graphTool = flags.Trigger.FPGATrackSim.GNN.graphTool.value
-    GNNGraphConstructionTool.moduleMapType=flags.Trigger.FPGATrackSim.GNN.moduleMapType.value
-    GNNGraphConstructionTool.moduleMapFunc=flags.Trigger.FPGATrackSim.GNN.moduleMapFunc.value
-    GNNGraphConstructionTool.moduleMapTol=flags.Trigger.FPGATrackSim.GNN.moduleMapTol
-    GNNGraphConstructionTool.moduleMapPath=PathResolver.FindCalibFile(flags.Trigger.FPGATrackSim.GNN.moduleMapPath)
-
-    result.setPrivateTools(GNNGraphConstructionTool)
-
-    return result
-
-def FPGATrackSimGNNEdgeClassifierToolCfg(flags):
-    result = ComponentAccumulator()
-
-    from AthOnnxComps.OnnxRuntimeInferenceConfig import OnnxRuntimeInferenceToolCfg
-    from AthOnnxComps.OnnxRuntimeFlags import OnnxRuntimeType
-
-    GNNEdgeClassifierTool = CompFactory.FPGATrackSimGNNEdgeClassifierTool()
-    GNNEdgeClassifierTool.GNNInferenceTool = result.popToolsAndMerge(OnnxRuntimeInferenceToolCfg(
-       flags, flags.Trigger.FPGATrackSim.GNN.GNNModelPath, OnnxRuntimeType.CPU))
-
-    result.setPrivateTools(GNNEdgeClassifierTool)
-
-    return result
-
-def FPGATrackSimGNNRoadMakerToolCfg(flags):
-    result = ComponentAccumulator()
-
-    GNNRoadMakerTool = CompFactory.FPGATrackSimGNNRoadMakerTool()
-    GNNRoadMakerTool.roadMakerTool = flags.Trigger.FPGATrackSim.GNN.roadMakerTool.value
-    GNNRoadMakerTool.edgeScoreCut = flags.Trigger.FPGATrackSim.GNN.edgeScoreCut
-    GNNRoadMakerTool.FPGATrackSimMappingSvc = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimMappingCfg(flags))
-
-    result.setPrivateTools(GNNRoadMakerTool)
-
-    return result
-
-def FPGATrackSimGNNRootOutputToolCfg(flags):
-    result = ComponentAccumulator()
-
-    GNNRootOutputTool = CompFactory.FPGATrackSimGNNRootOutputTool()
-
-    result.addService(CompFactory.THistSvc(Output = ["TRIGFPGATrackSimGNNOUTPUT DATAFILE='GNNRootOutput.root', OPT='RECREATE'"]))
-    result.setPrivateTools(GNNRootOutputTool)
-
-    return result
-
-def FPGATrackSimDataFlowToolCfg(flags):
-    result=ComponentAccumulator()
-    DataFlowTool = CompFactory.FPGATrackSimDataFlowTool()
-    DataFlowTool.FPGATrackSimEventSelectionSvc = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimEventSelectionCfg(flags))
-    DataFlowTool.FPGATrackSimMappingSvc =  result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimMappingCfg(flags))
-    DataFlowTool.Chi2ndofCut = flags.Trigger.FPGATrackSim.ActiveConfig.chi2cut
-    DataFlowTool.THistSvc = CompFactory.THistSvc()
-    result.setPrivateTools(DataFlowTool)
-    return result
-
-def FPGATrackSimHoughRootOutputToolCfg(flags):
-    result=ComponentAccumulator()
-    HoughRootOutputTool = CompFactory.FPGATrackSimHoughRootOutputTool()
-    HoughRootOutputTool.FPGATrackSimEventSelectionSvc = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimEventSelectionCfg(flags))
-    HoughRootOutputTool.FPGATrackSimMappingSvc = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimMappingCfg(flags))
-    HoughRootOutputTool.THistSvc = CompFactory.THistSvc()
-    result.setPrivateTools(HoughRootOutputTool)
-    return result
-
-def LRTRoadFinderCfg(flags):
-    result=ComponentAccumulator()
-    LRTRoadFinder =CompFactory.FPGATrackSimHoughTransform_d0phi0_Tool()
-    LRTRoadFinder.FPGATrackSimBankSvc = result.getPrimaryAndMerge(FPGATrackSimBankSvcCfg(flags))
-    LRTRoadFinder.FPGATrackSimMappingSvc = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimMappingCfg(flags))
-    LRTRoadFinder.combine_layers = flags.Trigger.FPGATrackSim.ActiveConfig.lrtStraighttrackCombineLayers
-    LRTRoadFinder.convolution = flags.Trigger.FPGATrackSim.ActiveConfig.lrtStraighttrackConvolution
-    LRTRoadFinder.hitExtend_x = flags.Trigger.FPGATrackSim.ActiveConfig.lrtStraighttrackHitExtendX
-    LRTRoadFinder.scale = flags.Trigger.FPGATrackSim.ActiveConfig.scale
-    LRTRoadFinder.threshold = flags.Trigger.FPGATrackSim.ActiveConfig.lrtStraighttrackThreshold
-    result.setPrivateTools(LRTRoadFinder)
-    return result
-
-def NNTrackToolCfg(flags):
-    result=ComponentAccumulator()
-    NNTrackTool = CompFactory.FPGATrackSimNNTrackTool()
-    NNTrackTool.THistSvc = CompFactory.THistSvc()
-    NNTrackTool.FPGATrackSimMappingSvc = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimMappingCfg(flags))
-    NNTrackTool.FPGATrackSimBankSvc = result.getPrimaryAndMerge(FPGATrackSimBankSvcCfg(flags))
-    NNTrackTool.IdealGeoRoads = (flags.Trigger.FPGATrackSim.ActiveConfig.IdealGeoRoads and flags.Trigger.FPGATrackSim.tracking)
-    NNTrackTool.useSpacePoints = flags.Trigger.FPGATrackSim.spacePoints and not flags.Trigger.FPGATrackSim.ActiveConfig.genScan
-    NNTrackTool.SPRoadFilterTool = getSPRoadFilterTool(flags)
-    NNTrackTool.MinNumberOfRealHitsInATrack = 5 if flags.Trigger.FPGATrackSim.ActiveConfig.genScan else 9
-
-    result.setPrivateTools(NNTrackTool)
-    return result
-
-def FPGATrackSimTrackFitterToolCfg(flags):
-    result=ComponentAccumulator()
-    TF_1st = CompFactory.FPGATrackSimTrackFitterTool("FPGATrackSimTrackFitterTool_1st")
-    TF_1st.GuessHits = flags.Trigger.FPGATrackSim.ActiveConfig.guessHits
-    TF_1st.IdealCoordFitType = flags.Trigger.FPGATrackSim.ActiveConfig.idealCoordFitType
-    TF_1st.FPGATrackSimBankSvc = result.getPrimaryAndMerge(FPGATrackSimBankSvcCfg(flags))
-    TF_1st.FPGATrackSimMappingSvc = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimMappingCfg(flags))
-    TF_1st.chi2DofRecoveryMax = flags.Trigger.FPGATrackSim.ActiveConfig.chi2DoFRecoveryMax
-    TF_1st.chi2DofRecoveryMin = flags.Trigger.FPGATrackSim.ActiveConfig.chi2DoFRecoveryMin
-    TF_1st.doMajority = flags.Trigger.FPGATrackSim.ActiveConfig.doMajority
-    TF_1st.nHits_noRecovery = flags.Trigger.FPGATrackSim.ActiveConfig.nHitsNoRecovery
-    TF_1st.DoDeltaGPhis = flags.Trigger.FPGATrackSim.ActiveConfig.doDeltaGPhis
-    TF_1st.DoMissingHitsChecks = flags.Trigger.FPGATrackSim.ActiveConfig.doMissingHitsChecks
-    TF_1st.IdealGeoRoads = (flags.Trigger.FPGATrackSim.ActiveConfig.IdealGeoRoads and flags.Trigger.FPGATrackSim.tracking)
-    TF_1st.useSpacePoints = flags.Trigger.FPGATrackSim.spacePoints and not flags.Trigger.FPGATrackSim.ActiveConfig.genScan
-    TF_1st.SPRoadFilterTool = getSPRoadFilterTool(flags)
-    result.addPublicTool(TF_1st, primary=True)
-    return result
-
-def FPGATrackSimOverlapRemovalToolCfg(flags):
-    result=ComponentAccumulator()
-    OR_1st = CompFactory.FPGATrackSimOverlapRemovalTool("FPGATrackSimOverlapRemovalTool_1st")
-    OR_1st.ORAlgo = "Normal"
-    OR_1st.doFastOR =flags.Trigger.FPGATrackSim.ActiveConfig.doFastOR
-    OR_1st.NumOfHitPerGrouping = 3
-    OR_1st.FPGATrackSimMappingSvc = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimMappingCfg(flags))
-    OR_1st.MinChi2 = flags.Trigger.FPGATrackSim.ActiveConfig.chi2cut
-    if flags.Trigger.FPGATrackSim.ActiveConfig.hough or flags.Trigger.FPGATrackSim.ActiveConfig.hough1D:
-        OR_1st.nBins_x = flags.Trigger.FPGATrackSim.ActiveConfig.xBins + 2 * flags.Trigger.FPGATrackSim.ActiveConfig.xBufferBins
-        OR_1st.nBins_y = flags.Trigger.FPGATrackSim.ActiveConfig.yBins + 2 * flags.Trigger.FPGATrackSim.ActiveConfig.yBufferBins
-        OR_1st.localMaxWindowSize = flags.Trigger.FPGATrackSim.ActiveConfig.localMaxWindowSize
-        OR_1st.roadSliceOR = flags.Trigger.FPGATrackSim.ActiveConfig.roadSliceOR
-
-    result.addPublicTool(OR_1st, primary=True)
-    return result
-
-def prepareFlagsForFPGATrackSimLogicalHitsProcessAlg(flags):
-    newFlags = flags.cloneAndReplace("Trigger.FPGATrackSim.ActiveConfig", "Trigger.FPGATrackSim." + flags.Trigger.FPGATrackSim.algoTag)
-    return newFlags
-
-def getSPRoadFilterTool(flags,secondStage=False):
-    name="FPGATrackSimSpacepointRoadFilterTool_1st"
-    if secondStage:
-        name="FPGATrackSimSpacepointRoadFilterTool_2st"
-    SPRoadFilter = CompFactory.FPGATrackSimSpacepointRoadFilterTool(name)
-    SPRoadFilter.filtering = flags.Trigger.FPGATrackSim.ActiveConfig.spacePointFiltering
-    SPRoadFilter.minSpacePlusPixel = flags.Trigger.FPGATrackSim.minSpacePlusPixel
-    SPRoadFilter.isSecondStage = secondStage
-    # TODO guard here against threshold being more than one value?
-    if (flags.Trigger.FPGATrackSim.ActiveConfig.hough1D):
-        SPRoadFilter.threshold = flags.Trigger.FPGATrackSim.Hough1D.threshold[0]
-    else:
-        SPRoadFilter.threshold = flags.Trigger.FPGATrackSim.ActiveConfig.threshold[0]
-    SPRoadFilter.setSectors = (flags.Trigger.FPGATrackSim.ActiveConfig.IdealGeoRoads and flags.Trigger.FPGATrackSim.tracking)
-    return SPRoadFilter
-
-def FPGATrackSimLogicalHitsProcessAlgCfg(inputFlags):
-
-    flags = prepareFlagsForFPGATrackSimLogicalHitsProcessAlg(inputFlags)
-
-    result=ComponentAccumulator()
-    if not flags.Trigger.FPGATrackSim.wrapperFileName:
-        from InDetConfig.InDetPrepRawDataFormationConfig import AthenaTrkClusterizationCfg
-        result.merge(AthenaTrkClusterizationCfg(flags))
-
-    theFPGATrackSimLogicalHitsProcessAlg=CompFactory.FPGATrackSimLogicalHitsProcessAlg()
-    theFPGATrackSimLogicalHitsProcessAlg.writeOutputData = flags.Trigger.FPGATrackSim.writeAdditionalOutputData
-    theFPGATrackSimLogicalHitsProcessAlg.tracking = flags.Trigger.FPGATrackSim.tracking
-    theFPGATrackSimLogicalHitsProcessAlg.doOverlapRemoval = flags.Trigger.FPGATrackSim.doOverlapRemoval
-    theFPGATrackSimLogicalHitsProcessAlg.DoMissingHitsChecks = flags.Trigger.FPGATrackSim.ActiveConfig.doMissingHitsChecks
-    theFPGATrackSimLogicalHitsProcessAlg.DoHoughRootOutput1st = flags.Trigger.FPGATrackSim.ActiveConfig.houghRootoutput1st
-    theFPGATrackSimLogicalHitsProcessAlg.NumOfHitPerGrouping = flags.Trigger.FPGATrackSim.ActiveConfig.NumOfHitPerGrouping
-    theFPGATrackSimLogicalHitsProcessAlg.DoNNTrack = flags.Trigger.FPGATrackSim.ActiveConfig.trackNNAnalysis
-    theFPGATrackSimLogicalHitsProcessAlg.eventSelector = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimEventSelectionCfg(flags))
-    theFPGATrackSimLogicalHitsProcessAlg.TrackScoreCut = flags.Trigger.FPGATrackSim.ActiveConfig.chi2cut
-    theFPGATrackSimLogicalHitsProcessAlg.passLowestChi2TrackOnly = flags.Trigger.FPGATrackSim.ActiveConfig.passLowestChi2TrackOnly
-    FPGATrackSimMaping = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimMappingCfg(flags))
-    theFPGATrackSimLogicalHitsProcessAlg.FPGATrackSimMapping = FPGATrackSimMaping
-
-    # If tracking is set to False, don't configure the bank service
-    if flags.Trigger.FPGATrackSim.tracking:
-        result.getPrimaryAndMerge(FPGATrackSimBankSvcCfg(flags))
-
-    if (flags.Trigger.FPGATrackSim.ActiveConfig.hough1D):
-        theFPGATrackSimLogicalHitsProcessAlg.RoadFinder = result.getPrimaryAndMerge(FPGATrackSimRoadUnionTool1DCfg(flags))
-    elif (flags.Trigger.FPGATrackSim.ActiveConfig.genScan):
-        theFPGATrackSimLogicalHitsProcessAlg.RoadFinder = result.getPrimaryAndMerge(FPGATrackSimRoadUnionToolGenScanCfg(flags))
-    elif (flags.Trigger.FPGATrackSim.ActiveConfig.GNN):
-        theFPGATrackSimLogicalHitsProcessAlg.RoadFinder = result.getPrimaryAndMerge(FPGATrackSimRoadUnionToolGNNCfg(flags))
-    else:
-        theFPGATrackSimLogicalHitsProcessAlg.RoadFinder = result.getPrimaryAndMerge(FPGATrackSimRoadUnionToolCfg(flags))
-
-    if (flags.Trigger.FPGATrackSim.ActiveConfig.etaPatternFilter):
-        EtaPatternFilter = CompFactory.FPGATrackSimEtaPatternFilterTool()
-        EtaPatternFilter.FPGATrackSimMappingSvc = FPGATrackSimMaping
-        EtaPatternFilter.threshold = flags.Trigger.FPGATrackSim.Hough1D.threshold[0]
-        EtaPatternFilter.EtaPatterns = flags.Trigger.FPGATrackSim.mapsDir+"/"+FPGATrackSimDataPrepConfig.getBaseName(flags)+".patt"
-        theFPGATrackSimLogicalHitsProcessAlg.RoadFilter = EtaPatternFilter
-        theFPGATrackSimLogicalHitsProcessAlg.FilterRoads = True
-
-    if (flags.Trigger.FPGATrackSim.ActiveConfig.phiRoadFilter):
-        RoadFilter2 = CompFactory.FPGATrackSimPhiRoadFilterTool()
-        RoadFilter2.FPGATrackSimMappingSvc = FPGATrackSimMaping
-        RoadFilter2.threshold = flags.Trigger.FPGATrackSim.Hough1D.threshold[0]
-        RoadFilter2.fieldCorrection = flags.Trigger.FPGATrackSim.ActiveConfig.fieldCorrection
-        ### set the window to be a constant value (could be changed), array should be length of the threshold
-        windows = [flags.Trigger.FPGATrackSim.Hough1D.phifilterwindow for i in range(len(flags.Trigger.FPGATrackSim.ActiveConfig.hitExtendX))]
-        RoadFilter2.window = windows
-
-        theFPGATrackSimLogicalHitsProcessAlg.RoadFilter2 = RoadFilter2
-        theFPGATrackSimLogicalHitsProcessAlg.FilterRoads2 = True
-
-
-    theFPGATrackSimLogicalHitsProcessAlg.HoughRootOutputTool = result.getPrimaryAndMerge(FPGATrackSimHoughRootOutputToolCfg(flags))
-
-    LRTRoadFilter = CompFactory.FPGATrackSimLLPRoadFilterTool()
-    result.addPublicTool(LRTRoadFilter)
-    theFPGATrackSimLogicalHitsProcessAlg.LRTRoadFilter = LRTRoadFilter
-
-    theFPGATrackSimLogicalHitsProcessAlg.LRTRoadFinder = result.getPrimaryAndMerge(LRTRoadFinderCfg(flags))
-    theFPGATrackSimLogicalHitsProcessAlg.NNTrackTool = result.getPrimaryAndMerge(NNTrackToolCfg(flags))
-
-    theFPGATrackSimLogicalHitsProcessAlg.OutputTool = result.getPrimaryAndMerge(FPGATrackSimWriteOutputCfg(flags))
-    theFPGATrackSimLogicalHitsProcessAlg.TrackFitter_1st = result.getPrimaryAndMerge(FPGATrackSimTrackFitterToolCfg(flags))
-    theFPGATrackSimLogicalHitsProcessAlg.OverlapRemoval_1st = result.getPrimaryAndMerge(FPGATrackSimOverlapRemovalToolCfg(flags))
-
-    # Create SPRoadFilterTool if spacepoints are turned on. TODO: make things configurable?
-    if flags.Trigger.FPGATrackSim.spacePoints and not flags.Trigger.FPGATrackSim.ActiveConfig.genScan:
-        theFPGATrackSimLogicalHitsProcessAlg.SPRoadFilterTool = getSPRoadFilterTool(flags)
-        theFPGATrackSimLogicalHitsProcessAlg.Spacepoints = True
-
-
-    if flags.Trigger.FPGATrackSim.ActiveConfig.lrt:
-        assert flags.Trigger.FPGATrackSim.ActiveConfig.lrtUseBasicHitFilter != flags.Trigger.FPGATrackSim.ActiveConfig.lrtUseMlHitFilter, 'Inconsistent LRT hit filtering setup, need either ML of Basic filtering enabled'
-        assert flags.Trigger.FPGATrackSim.ActiveConfig.lrtUseStraightTrackHT != flags.Trigger.FPGATrackSim.ActiveConfig.lrtUseDoubletHT, 'Inconsistent LRT HT setup, need either double or strightTrack enabled'
-        theFPGATrackSimLogicalHitsProcessAlg.doLRT = True
-        theFPGATrackSimLogicalHitsProcessAlg.LRTHitFiltering = (not flags.Trigger.FPGATrackSim.ActiveConfig.lrtSkipHitFiltering)
-
-    from FPGATrackSimAlgorithms.FPGATrackSimAlgorithmConfig import FPGATrackSimLogicalHitsProcessAlgMonitoringCfg
-    theFPGATrackSimLogicalHitsProcessAlg.MonTool = result.getPrimaryAndMerge(FPGATrackSimLogicalHitsProcessAlgMonitoringCfg(flags))
-
-    result.addEventAlgo(theFPGATrackSimLogicalHitsProcessAlg)
-
-    return result
-
-def getChi2Cut(region):
-    #list of chi2 cuts for time being. Last four are stand ins since those new regions don't work for now!
-    chi2cut_l = [12, 16, 60, 16, 60, 60, 14, 20, 16, 19, 19, 15, 18, 12, 15, 15, 20, 20, 20, 20]
-    binSize = 0.2
-    side = (region >> 5) & 0x1
-    etaBin = (region >> 6) & 0x1F
-    etaRange = [round(binSize * etaBin, 1), round(binSize * (etaBin + 1), 1)] if side else [round(-binSize * (etaBin + 1), 1), round(-binSize * etaBin, 1)]
-    abs_etaRange = tuple(abs(val) for val in etaRange)
-
-    eta_to_chi2 = {
-        (0.0, 0.2): chi2cut_l[0], (0.2, 0.4): chi2cut_l[1], (0.4, 0.6): chi2cut_l[2],
-        (0.6, 0.8): chi2cut_l[3], (0.8, 1.0): chi2cut_l[4], (1.0, 1.2): chi2cut_l[5],
-        (1.2, 1.4): chi2cut_l[6], (1.4, 1.6): chi2cut_l[7], (1.6, 1.8): chi2cut_l[8],
-        (1.8, 2.0): chi2cut_l[9], (2.0, 2.2): chi2cut_l[10], (2.2, 2.4): chi2cut_l[11],
-        (2.4, 2.6): chi2cut_l[12], (2.6, 2.8): chi2cut_l[13], (2.8, 3.0): chi2cut_l[14],
-        (3.0, 3.2): chi2cut_l[15], (3.2, 3.4): chi2cut_l[16], (3.4, 3.6): chi2cut_l[17], 
-        (3.6, 3.8): chi2cut_l[18], (3.8, 4.0): chi2cut_l[19]
-    }
-
-    return eta_to_chi2.get(abs_etaRange, 9) #i set it back to default chi2 if the region is not found
-
-
-if __name__ == "__main__":
-    from AthenaConfiguration.AllConfigFlags import initConfigFlags
-    from AthenaConfiguration.MainServicesConfig import MainServicesCfg
-
-
-
-    flags = initConfigFlags()
-
-    ############################################
-    # Flags used in the prototrack chain
-    FinalProtoTrackChainxAODTracksKey="FPGA"
-    flags.Detector.EnableCalo = False
-
-    # ensure that the xAOD SP and cluster containers are available
-    flags.Tracking.ITkMainPass.doAthenaToActsSpacePoint=True
-    flags.Tracking.ITkMainPass.doAthenaToActsCluster=True
-    from TrkConfig.TrkConfigFlags import TrackingComponent
-    flags.Tracking.recoChain = [TrackingComponent.ActsChain] # another viable option is TrackingComponent.AthenaChain
-    flags.Acts.doRotCorrection = False
-
-    ############################################
-    flags.Concurrency.NumThreads=1
-    #flags.Concurrency.NumProcs=0
-    flags.Scheduler.ShowDataDeps=True
-    flags.Scheduler.CheckDependencies=True
-    flags.Debug.DumpEvtStore=False
-
-    # flags.Exec.DebugStage="exec" # useful option to debug the execution of the job - we want it commented out for production
-    flags.fillFromArgs()
-
-    if flags.Trigger.FPGATrackSim.Hough.useVaryingChi2Cut: 
-        flags.Trigger.FPGATrackSim.Hough.chi2cut = getChi2Cut(flags.Trigger.FPGATrackSim.region) 
-
-    assert not flags.Trigger.FPGATrackSim.pipeline.startswith('F-5'),"ERROR You are trying to run an F-5* pipeline! This is not yet supported!"
-
-    if (flags.Trigger.FPGATrackSim.pipeline.startswith('F-1')):
-        print("You are trying to run an F-100 pipeline! I am going to run the Data Prep chain for you and nothing else!")
-        FPGATrackSimDataPrepConfig.runDataPrepChain()
-    elif (flags.Trigger.FPGATrackSim.pipeline.startswith('F-2')):
-        print("You are trying to run an F-2* pipeline! I am auto-configuring the 1D bitshift for you, including eta pattern filters and phi road filters")
-        flags.Trigger.FPGATrackSim.Hough.etaPatternFilter = True
-        flags.Trigger.FPGATrackSim.Hough.phiRoadFilter = True
-        flags.Trigger.FPGATrackSim.Hough.hough1D = True
-        flags.Trigger.FPGATrackSim.Hough.hough = False
-    elif (flags.Trigger.FPGATrackSim.pipeline.startswith('F-3')):
-        print("You are trying to run an F-3* pipeline! I am auto-configuring the 2D HT for you, and disabling the eta pattern filter and phi road filter. Whether you wanted to or not")
-        flags.Trigger.FPGATrackSim.Hough.etaPatternFilter = False
-        flags.Trigger.FPGATrackSim.Hough.phiRoadFilter = False
-        flags.Trigger.FPGATrackSim.Hough.hough1D = False
-        flags.Trigger.FPGATrackSim.Hough.hough = True
-    elif (flags.Trigger.FPGATrackSim.pipeline.startswith('F-4')):
-        print("You are trying to run an F-4* pipeline! I am auto-configuring the GNN pattern recognition for you. Whether you wanted to or not")
-        flags.Trigger.FPGATrackSim.Hough.GNN = True
-        flags.Trigger.FPGATrackSim.Hough.chi2cut = 25 # All of the track candidates have chi2 values around 20 for some reason. Needs further investigation. For now move the default cut value to 25
-    elif flags.Trigger.FPGATrackSim.pipeline.startswith('F-6'):
-        print("You are trying to run an F-6* pipeline! I am auto-configuring the Inside-Out for you. Whether you wanted to or not.")
-        flags.Trigger.FPGATrackSim.Hough.genScan = True
-        flags.Trigger.FPGATrackSim.spacePoints = flags.Trigger.FPGATrackSim.Hough.secondStage
-
-    elif (flags.Trigger.FPGATrackSim.pipeline != ""):
-        raise AssertionError("ERROR You are trying to run the pipeline " + flags.Trigger.FPGATrackSim.pipeline + " which is not yet supported!")
-
-    if (not flags.Trigger.FPGATrackSim.pipeline.startswith('F-1')): ### if DP pipeline skip everything else!
-
-        splitPipeline=flags.Trigger.FPGATrackSim.pipeline.split('-')
-        trackingOption=9999999
-        if (len(splitPipeline) > 1): trackingOption=int(splitPipeline[1])
-        if (trackingOption < 9999999):
-            trackingOptionMod = (trackingOption % 100)
-            if (trackingOptionMod == 0):
-                print("You are trying to run the linearized chi2 fit as part of a pipeline! I am going to enable this for you whether you want to or not")
-                flags.Trigger.FPGATrackSim.tracking = True
-                flags.Trigger.FPGATrackSim.Hough.trackNNAnalysis = False
-            elif (trackingOptionMod == 10):
-                print("You are trying to run the NN fake rejection as part of a pipeline! I am going to enable this for you whether you want to or not")
-                flags.Trigger.FPGATrackSim.tracking = True
-                flags.Trigger.FPGATrackSim.Hough.trackNNAnalysis = True
-            else:
-                raise AssertionError("ERROR Your tracking option for the pipeline = " + str(trackingOption) + " is not yet supported!")
-
-        if isinstance(flags.Trigger.FPGATrackSim.wrapperFileName, str):
-            log.info("wrapperFile is string, converting to list")
-            flags.Trigger.FPGATrackSim.wrapperFileName = [flags.Trigger.FPGATrackSim.wrapperFileName]
-            flags.Input.Files = lambda f: [f.Trigger.FPGATrackSim.wrapperFileName]
-
-        flags.lock()
-        flags.dump()
-        flags = flags.cloneAndReplace("Tracking.ActiveConfig","Tracking.MainPass")
-        acc=MainServicesCfg(flags)
-
-        if flags.Trigger.FPGATrackSim.writeAdditionalOutputData:
-            acc.addService(CompFactory.THistSvc(Output = ["EXPERT DATAFILE='monitoring.root', OPT='RECREATE'"]))
-
-            if (flags.Trigger.FPGATrackSim.Hough.trackNNAnalysis):
-                acc.addService(CompFactory.THistSvc(Output = ["FPGATRACKSIMOUTPUTNNPATHFINDER DATAFILE='NNPathfinder.root', OPT='RECREATE'"]))
-
-            if (flags.Trigger.FPGATrackSim.Hough.houghRootoutput1st | flags.Trigger.FPGATrackSim.Hough.houghRootoutput2nd):
-                acc.addService(CompFactory.THistSvc(Output = ["TRIGFPGATrackSimHOUGHOUTPUT DATAFILE='HoughRootOutput.root', OPT='RECREATE'"]))
-
-            if flags.Trigger.FPGATrackSim.Hough.writeTestOutput:
-                acc.addService(CompFactory.THistSvc(Output = ["FPGATRACKSIMOUTPUT DATAFILE='test.root', OPT='RECREATE'"]))
-
-            if (flags.Trigger.FPGATrackSim.Hough.genScan):
-                acc.addService(CompFactory.THistSvc(Output = ["GENSCAN DATAFILE='genscan.root', OPT='RECREATE'"]))
-
-        if not flags.Trigger.FPGATrackSim.wrapperFileName:
-            from AthenaPoolCnvSvc.PoolReadConfig import PoolReadCfg
-            acc.merge(PoolReadCfg(flags))
-
-            if flags.Input.isMC:
-                from xAODTruthCnv.xAODTruthCnvConfig import GEN_AOD2xAODCfg
-                acc.merge(GEN_AOD2xAODCfg(flags))
-
-                from JetRecConfig.JetRecoSteering import addTruthPileupJetsToOutputCfg # TO DO: check if this is indeed necessary for pileup samples
-                acc.merge(addTruthPileupJetsToOutputCfg(flags))
-
-            if flags.Detector.EnableCalo:
-                from CaloRec.CaloRecoConfig import CaloRecoCfg
-                acc.merge(CaloRecoCfg(flags))
-
-            if flags.Tracking.recoChain:
-                from InDetConfig.TrackRecoConfig import InDetTrackRecoCfg
-                acc.merge(InDetTrackRecoCfg(flags))
-
-        # Configure both the dataprep and logical hits algorithms.
-        acc.merge(FPGATrackSimDataPrepConfig.FPGATrackSimDataPrepAlgCfg(flags))
-        acc.merge(FPGATrackSimLogicalHitsProcessAlgCfg(flags))
-
-        # If second stage is turned on, turn that algorithm on too.
-        if flags.Trigger.FPGATrackSim.Hough.secondStage:
-            acc.merge(FPGATrackSimSecondStageConfig.FPGATrackSimSecondStageAlgCfg(flags))
-        
-        #if (not flags.Trigger.FPGATrackSim.oldRegionDefs):                                                                          
-         #   flags.Trigger.FPGATrackSim.Hough.chi2cut = getChi2Cut(flags.Trigger.FPGATrackSim.region)
-        #print(f"Chi2 cut set to: {flags.Trigger.FPGATrackSim.Hough.chi2cut}")
-
-        if flags.Trigger.FPGATrackSim.doEDMConversion:
-            stage = "_2nd" if flags.Trigger.FPGATrackSim.Hough.secondStage else "_1st"
-            convertTracks = flags.Trigger.FPGATrackSim.tracking
-            acc.merge(FPGATrackSimDataPrepConfig.FPGAConversionAlgCfg(flags, name = f"FPGAConversionAlg{stage}",
-                                                                        stage = f"{stage}",
-                                                                        doActsTrk=True,
-                                                                        doSP=flags.Trigger.FPGATrackSim.spacePoints,
-                                                                        useRoads=not flags.Trigger.FPGATrackSim.tracking))
-
-            from FPGATrackSimPrototrackFitter.FPGATrackSimPrototrackFitterConfig import FPGATruthDecorationCfg, FPGAProtoTrackFitCfg
-            acc.merge(FPGAProtoTrackFitCfg(flags,stage=f"{stage}",
-                                            useRoads=not flags.Trigger.FPGATrackSim.tracking)) # Run ACTS KF
-            acc.merge(FPGATruthDecorationCfg(flags,FinalProtoTrackChainxAODTracksKey=FinalProtoTrackChainxAODTracksKey,stage=f"{stage}")) # Run Truth Matching/Decoration chain
-            if not flags.Trigger.FPGATrackSim.wrapperFileName and flags.Trigger.FPGATrackSim.runCKF:
-                from FPGATrackSimConfTools.FPGATrackExtensionConfig import FPGATrackExtensionAlgCfg
-                acc.merge(FPGATrackExtensionAlgCfg(flags, enableTrackStatePrinter=False, name="FPGATrackExtension",
-                                                    ProtoTracksLocation=f"ActsProtoTracks{stage}FromFPGATrack")) # run CKF track extension on FPGA tracks
-
-            if flags.Trigger.FPGATrackSim.writeToAOD: acc.merge(FPGATrackSimDataPrepConfig.WriteToAOD(flags,
-                                                                                                        stage = f"{stage}",
-                                                                                                        finalTrackParticles=f"{FinalProtoTrackChainxAODTracksKey}TrackParticles"))
-
-            # Reporting algorithm (used for debugging - can be disabled)
-            from FPGATrackSimReporting.FPGATrackSimReportingConfig import FPGATrackSimReportingCfg
-            acc.merge(FPGATrackSimReportingCfg(flags, stage=f"{stage}",
-                                                perEventReports = ((flags.Trigger.FPGATrackSim.sampleType != 'skipTruth') and flags.Exec.MaxEvents<=10 ) )) # disable perEventReports for pileup samples or many events
-
-        acc.store(open('AnalysisConfig.pkl','wb'))
-
-        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
-
-        statusCode = acc.run(flags.Exec.MaxEvents)
-        assert statusCode.isSuccess() is True, "Application execution did not succeed"
+# Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
+from AthenaConfiguration.ComponentFactory import CompFactory
+from AthenaCommon.Logging import AthenaLogger
+from PathResolver import PathResolver
+import importlib
+
+log = AthenaLogger(__name__)
+
+#### Now inmport Data Prep config from other file
+from FPGATrackSimConfTools import FPGATrackSimDataPrepConfig
+from FPGATrackSimConfTools import FPGATrackSimSecondStageConfig
+
+def getNSubregions(filePath):
+    with open(PathResolver.FindCalibFile(filePath), 'r') as f:
+        fields = f.readline()
+        assert(fields.startswith('towers'))
+        n = fields.split()[1]
+        return int(n)
+    
+
+# Need to figure out if we have two output writers or somehow only one.
+def FPGATrackSimWriteOutputCfg(flags):
+    result=ComponentAccumulator()
+    FPGATrackSimWriteOutput = CompFactory.FPGATrackSimOutputHeaderTool("FPGATrackSimWriteOutput")
+    FPGATrackSimWriteOutput.InFileName = ["test.root"]
+    # RECREATE means that that this tool opens the file.
+    # HEADER would mean that something else (e.g. THistSvc) opens it and we just add the object.
+    FPGATrackSimWriteOutput.RWstatus = "HEADER"
+    FPGATrackSimWriteOutput.THistSvc = CompFactory.THistSvc()
+    result.addPublicTool(FPGATrackSimWriteOutput, primary=True)
+    return result
+
+
+
+def FPGATrackSimBankSvcCfg(flags):
+    result=ComponentAccumulator()
+    FPGATrackSimBankSvc = CompFactory.FPGATrackSimBankSvc()
+    pathBankSvc = flags.Trigger.FPGATrackSim.bankDir if flags.Trigger.FPGATrackSim.bankDir != '' else f'/eos/atlas/atlascerngroupdisk/det-htt/HTTsim/{flags.GeoModel.AtlasVersion}/21.9.16/'+FPGATrackSimDataPrepConfig.getBaseName(flags)+'/SectorBanks/'
+    pathBankSvc=PathResolver.FindCalibDirectory(pathBankSvc)
+    FPGATrackSimBankSvc.constantsNoGuess_1st = [
+        f'{pathBankSvc}corrgen_raw_8L_skipPlane0.gcon', 
+        f'{pathBankSvc}corrgen_raw_8L_skipPlane1.gcon', 
+        f'{pathBankSvc}corrgen_raw_8L_skipPlane2.gcon', 
+        f'{pathBankSvc}corrgen_raw_8L_skipPlane3.gcon', 
+        f'{pathBankSvc}corrgen_raw_8L_skipPlane4.gcon', 
+        f'{pathBankSvc}corrgen_raw_8L_skipPlane5.gcon', 
+        f'{pathBankSvc}corrgen_raw_8L_skipPlane6.gcon', 
+        f'{pathBankSvc}corrgen_raw_8L_skipPlane7.gcon']
+    FPGATrackSimBankSvc.constantsNoGuess_2nd = [
+        f'{pathBankSvc}corrgen_raw_13L_skipPlane0.gcon', 
+        f'{pathBankSvc}corrgen_raw_13L_skipPlane1.gcon', 
+        f'{pathBankSvc}corrgen_raw_13L_skipPlane2.gcon', 
+        f'{pathBankSvc}corrgen_raw_13L_skipPlane3.gcon', 
+        f'{pathBankSvc}corrgen_raw_13L_skipPlane4.gcon', 
+        f'{pathBankSvc}corrgen_raw_13L_skipPlane5.gcon', 
+        f'{pathBankSvc}corrgen_raw_13L_skipPlane6.gcon', 
+        f'{pathBankSvc}corrgen_raw_13L_skipPlane7.gcon']
+    layers="5L" if flags.Trigger.FPGATrackSim.ActiveConfig.genScan else "9L"
+    FPGATrackSimBankSvc.constants_1st = f'{pathBankSvc}corrgen_raw_{layers}_reg{flags.Trigger.FPGATrackSim.region}_checkGood1.gcon'
+    FPGATrackSimBankSvc.constants_2nd = f'{pathBankSvc}corrgen_raw_13L_reg{flags.Trigger.FPGATrackSim.region}_checkGood1.gcon'
+    FPGATrackSimBankSvc.sectorBank_1st = f'{pathBankSvc}sectorsHW_raw_{layers}_reg{flags.Trigger.FPGATrackSim.region}_checkGood1.patt'
+    FPGATrackSimBankSvc.sectorBank_2nd = f'{pathBankSvc}sectorsHW_raw_13L_reg{flags.Trigger.FPGATrackSim.region}_checkGood1.patt'
+    FPGATrackSimBankSvc.sectorSlices = f'{pathBankSvc}slices_{layers}_reg{flags.Trigger.FPGATrackSim.region}.root'
+    FPGATrackSimBankSvc.phiShift = flags.Trigger.FPGATrackSim.phiShift
+
+    # These should be configurable. The tag system needs updating though.
+    FPGATrackSimBankSvc.sectorQPtBins = [-0.001, -0.0005, 0, 0.0005, 0.001]
+    FPGATrackSimBankSvc.qptAbsBinning = False
+
+    result.addService(FPGATrackSimBankSvc, create=True, primary=True)
+    return result
+
+
+def FPGATrackSimRoadUnionToolCfg(flags):
+    result=ComponentAccumulator()
+    RF = CompFactory.FPGATrackSimRoadUnionTool()
+    
+    xBins = flags.Trigger.FPGATrackSim.ActiveConfig.xBins
+    xBufferBins = flags.Trigger.FPGATrackSim.ActiveConfig.xBufferBins
+    yBins = flags.Trigger.FPGATrackSim.ActiveConfig.yBins
+    yBufferBins = flags.Trigger.FPGATrackSim.ActiveConfig.yBufferBins
+    yMin = flags.Trigger.FPGATrackSim.ActiveConfig.qptMin
+    yMax = flags.Trigger.FPGATrackSim.ActiveConfig.qptMax
+    xMin = flags.Trigger.FPGATrackSim.ActiveConfig.phiMin
+    xMax = flags.Trigger.FPGATrackSim.ActiveConfig.phiMax
+    if (not flags.Trigger.FPGATrackSim.oldRegionDefs): ### auto-configure this
+        phiRange = FPGATrackSimDataPrepConfig.getPhiRange(flags)
+        xMin = phiRange[0]
+        xMax = phiRange[1]
+
+    xBuffer = (xMax - xMin) / xBins * xBufferBins
+    xMin = xMin - xBuffer
+    xMax = xMax +  xBuffer
+    yBuffer = (yMax - yMin) / yBins * yBufferBins
+    yMin -= yBuffer
+    yMax += yBuffer
+    tools = []
+    
+    FPGATrackSimMapping = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimMappingCfg(flags))
+    for number in range(getNSubregions(FPGATrackSimMapping.subrmap)): 
+        HoughTransform = CompFactory.FPGATrackSimHoughTransformTool("HoughTransform_0_" + str(number))
+        HoughTransform.FPGATrackSimEventSelectionSvc = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimEventSelectionCfg(flags))
+        HoughTransform.FPGATrackSimBankSvc = result.getPrimaryAndMerge(FPGATrackSimBankSvcCfg(flags))
+        HoughTransform.FPGATrackSimMappingSvc = FPGATrackSimMapping 
+        HoughTransform.combine_layers = flags.Trigger.FPGATrackSim.ActiveConfig.combineLayers 
+        HoughTransform.convSize_x = flags.Trigger.FPGATrackSim.ActiveConfig.convSizeX 
+        HoughTransform.convSize_y = flags.Trigger.FPGATrackSim.ActiveConfig.convSizeY 
+        HoughTransform.convolution = flags.Trigger.FPGATrackSim.ActiveConfig.convolution 
+        HoughTransform.d0_max = 0 
+        HoughTransform.d0_min = 0 
+        HoughTransform.fieldCorrection = flags.Trigger.FPGATrackSim.ActiveConfig.fieldCorrection
+        HoughTransform.hitExtend_x = flags.Trigger.FPGATrackSim.ActiveConfig.hitExtendX
+        HoughTransform.localMaxWindowSize = flags.Trigger.FPGATrackSim.ActiveConfig.localMaxWindowSize        
+        HoughTransform.nBins_x = xBins + 2 * xBufferBins
+        HoughTransform.nBins_y = yBins + 2 * yBufferBins
+        HoughTransform.phi_max = xMax
+        HoughTransform.phi_min = xMin
+        HoughTransform.qpT_max = yMax 
+        HoughTransform.qpT_min = yMin 
+        HoughTransform.scale = flags.Trigger.FPGATrackSim.ActiveConfig.scale
+        HoughTransform.subRegion = number
+        HoughTransform.threshold = flags.Trigger.FPGATrackSim.ActiveConfig.threshold
+        HoughTransform.traceHits = True
+        HoughTransform.IdealGeoRoads = (flags.Trigger.FPGATrackSim.ActiveConfig.IdealGeoRoads and flags.Trigger.FPGATrackSim.tracking)
+        HoughTransform.useSpacePoints = flags.Trigger.FPGATrackSim.spacePoints
+
+        tools.append(HoughTransform)
+
+    RF.tools = tools
+    result.addPublicTool(RF, primary=True)
+    return result
+
+def FPGATrackSimRoadUnionTool1DCfg(flags):
+    result=ComponentAccumulator()
+    tools = []
+    RF = CompFactory.FPGATrackSimRoadUnionTool()
+    splitpt=flags.Trigger.FPGATrackSim.Hough1D.splitpt
+    FPGATrackSimMapping = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimMappingCfg(flags))
+    for ptstep in range(splitpt):
+        qpt_min = flags.Trigger.FPGATrackSim.Hough1D.qptMin
+        qpt_max = flags.Trigger.FPGATrackSim.Hough1D.qptMax
+        lowpt = qpt_min + (qpt_max-qpt_min)/splitpt*ptstep
+        highpt = qpt_min + (qpt_max-qpt_min)/splitpt*(ptstep+1)
+        nSlice = getNSubregions(FPGATrackSimMapping.subrmap)
+        for iSlice in range(nSlice):
+            tool = CompFactory.FPGATrackSimHough1DShiftTool("Hough1DShift" + str(iSlice)+(("_pt{}".format(ptstep))  if splitpt>1 else ""))
+            tool.subRegion = iSlice if nSlice > 1 else -1
+            xMin = flags.Trigger.FPGATrackSim.Hough1D.phiMin
+            xMax = flags.Trigger.FPGATrackSim.Hough1D.phiMax
+            if (not flags.Trigger.FPGATrackSim.oldRegionDefs): ### auto-configure this
+                phiRange = FPGATrackSimDataPrepConfig.getPhiRange(flags)
+                xMin = phiRange[0]
+                xMax = phiRange[1]
+            tool.phiMin = xMin
+            tool.phiMax = xMax
+            tool.qptMin = lowpt
+            tool.qptMax = highpt
+            tool.nBins = flags.Trigger.FPGATrackSim.Hough1D.xBins
+            tool.useDiff = True
+            tool.variableExtend = True
+            tool.drawHitMasks = False
+            tool.phiRangeCut = flags.Trigger.FPGATrackSim.Hough1D.phiRangeCut
+            tool.d0spread=-1.0 # mm
+            tool.iterStep = 0 # auto, TODO put in tag
+            tool.iterLayer = 7 # TODO put in tag
+            tool.threshold = flags.Trigger.FPGATrackSim.Hough1D.threshold[0]
+            tool.hitExtend = flags.Trigger.FPGATrackSim.Hough1D.hitExtendX
+            tool.FPGATrackSimEventSelectionSvc = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimEventSelectionCfg(flags))
+            tool.FPGATrackSimBankSvc = result.getPrimaryAndMerge(FPGATrackSimBankSvcCfg(flags))
+            tool.FPGATrackSimMappingSvc = FPGATrackSimMapping
+            tool.IdealGeoRoads = (flags.Trigger.FPGATrackSim.ActiveConfig.IdealGeoRoads and flags.Trigger.FPGATrackSim.tracking)
+            tool.useSpacePoints = flags.Trigger.FPGATrackSim.spacePoints
+
+            tools.append(tool)
+
+    RF.tools = tools
+    result.addPublicTool(RF, primary=True)
+    return result
+
+
+
+def FPGATrackSimRoadUnionToolGenScanCfg(flags):
+    result=ComponentAccumulator()
+
+    # read the cuts from a seperate python file specified by FPGATrackSim.GenScan.genScanCuts
+    cutset=None
+    if flags.Trigger.FPGATrackSim.oldRegionDefs:
+        toload=flags.Trigger.FPGATrackSim.GenScan.genScanCuts
+        if toload == 'FPGATrackSimGenScanCuts': # its on the newRegion default so it hasn't been set
+            toload = 'FPGATrackSimHough.FPGATrackSimGenScanCuts_incr'
+        cutset = importlib.import_module(toload).cuts[flags.Trigger.FPGATrackSim.region]
+    else:
+        # this allows the cut file defined in python to be loaded from the map directory
+        print("Cut File = ", flags.Trigger.FPGATrackSim.GenScan.genScanCuts,
+                                                    flags.Trigger.FPGATrackSim.mapsDir+"/{}.py".format(flags.Trigger.FPGATrackSim.GenScan.genScanCuts))
+        spec=importlib.util.spec_from_file_location(flags.Trigger.FPGATrackSim.GenScan.genScanCuts,
+                                                    flags.Trigger.FPGATrackSim.mapsDir+"/{}.py".format(flags.Trigger.FPGATrackSim.GenScan.genScanCuts))
+        if spec is None:
+            print("Failed to find Cut File")
+        cutmodule = importlib.util.module_from_spec(spec)
+        spec.loader.exec_module(cutmodule)
+        cutset=cutmodule.cuts[flags.Trigger.FPGATrackSim.region]
+
+    # make the binning class
+    Binning = None
+    if (cutset["parSet"]=="PhiSlicedKeyLyrPars") :
+        Binning = CompFactory.FPGATrackSimGenScanPhiSlicedKeyLyrBinning("GenScanBinning")
+        Binning.approxMath = False
+    else:
+        log.error("Unknown Binning") 
+    Binning.rin=cutset["rin"]
+    Binning.rout=cutset["rout"]
+    Binning.OutputLevel=flags.Trigger.FPGATrackSim.loglevel
+
+    # make the monitoring class
+    Monitor = CompFactory.FPGATrackSimGenScanMonitoring("GenScanMonitoring")
+    Monitor.THistSvc = CompFactory.THistSvc()
+    Monitor.OutputLevel=flags.Trigger.FPGATrackSim.loglevel
+
+    # make the main tool
+    tool = CompFactory.FPGATrackSimGenScanTool("GenScanTool")
+    tool.FPGATrackSimEventSelectionSvc = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimEventSelectionCfg(flags))
+    tool.FPGATrackSimBankSvc = result.getPrimaryAndMerge(FPGATrackSimBankSvcCfg(flags))
+    tool.FPGATrackSimMappingSvc = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimMappingCfg(flags))
+    tool.Monitoring = Monitor
+    tool.Binning = Binning
+    tool.OutputLevel=flags.Trigger.FPGATrackSim.loglevel
+
+    # configure which filers and thresholds to apply
+    tool.binFilter=flags.Trigger.FPGATrackSim.GenScan.binFilter
+    tool.reversePairDir=flags.Trigger.FPGATrackSim.GenScan.reverse
+    tool.applyPairFilter= not flags.Trigger.FPGATrackSim.GenScan.noCuts
+    tool.applyPairSetFilter= not flags.Trigger.FPGATrackSim.GenScan.noCuts
+    tool.threshold = 4
+
+    # configure the padding around the nominal region
+    tool.d0FractionalPadding =0.05
+    tool.z0FractionalPadding =0.05
+    tool.etaFractionalPadding =0.05
+    tool.phiFractionalPadding =0.05
+    tool.qOverPtFractionalPadding =0.05                
+
+    # set cuts
+    for (cut,val) in cutset.items():
+        setattr(tool,cut,val)
+
+    # set layer map
+    if not flags.Trigger.FPGATrackSim.GenScan.layerStudy:
+        if flags.Trigger.FPGATrackSim.oldRegionDefs:
+            tool.layerMapFile = flags.Trigger.FPGATrackSim.GenScan.layerMapFile
+        else:
+            # now assumed to be in the map directory with name = basename for region + _lyrmap.json
+            tool.layerMapFile = flags.Trigger.FPGATrackSim.mapsDir+"/"+FPGATrackSimDataPrepConfig.getBaseName(flags)+"_lyrmap.json"
+
+    # even though we are not actually doing a Union, we need the 
+    # RoadUnionTool because mapping is now there
+    RoadUnion = CompFactory.FPGATrackSimRoadUnionTool()
+    RoadUnion.tools = [tool,]
+    result.addPublicTool(RoadUnion, primary=True)
+
+    # special configuration for studing layer definitions
+    # pass through all hits, but turn off pairing because
+    # it won't be able to run
+    if flags.Trigger.FPGATrackSim.GenScan.layerStudy:
+        RoadUnion.noHitFilter=True
+        tool.binningOnly=True
+    return result
+
+def FPGATrackSimRoadUnionToolGNNCfg(flags):
+    result = ComponentAccumulator()
+    RF = CompFactory.FPGATrackSimRoadUnionTool()
+
+    patternRecoTool = CompFactory.FPGATrackSimGNNPatternRecoTool()
+    patternRecoTool.GNNGraphHitSelector = CompFactory.FPGATrackSimGNNGraphHitSelectorTool()
+    patternRecoTool.GNNGraphConstruction = result.popToolsAndMerge(FPGATrackSimGNNGraphConstructionToolCfg(flags))
+    patternRecoTool.GNNEdgeClassifier = result.popToolsAndMerge(FPGATrackSimGNNEdgeClassifierToolCfg(flags))
+    patternRecoTool.GNNRoadMaker = result.popToolsAndMerge(FPGATrackSimGNNRoadMakerToolCfg(flags))
+    patternRecoTool.GNNRootOutput = result.popToolsAndMerge(FPGATrackSimGNNRootOutputToolCfg(flags))
+    patternRecoTool.doGNNRootOutput = flags.Trigger.FPGATrackSim.GNN.doGNNRootOutput
+    
+    RF.tools = [patternRecoTool]
+    result.addPublicTool(RF, primary=True)
+
+    return result
+
+def FPGATrackSimGNNGraphConstructionToolCfg(flags):
+    result = ComponentAccumulator()
+
+    GNNGraphConstructionTool = CompFactory.FPGATrackSimGNNGraphConstructionTool()
+    GNNGraphConstructionTool.graphTool = flags.Trigger.FPGATrackSim.GNN.graphTool.value
+    GNNGraphConstructionTool.moduleMapType=flags.Trigger.FPGATrackSim.GNN.moduleMapType.value
+    GNNGraphConstructionTool.moduleMapFunc=flags.Trigger.FPGATrackSim.GNN.moduleMapFunc.value
+    GNNGraphConstructionTool.moduleMapTol=flags.Trigger.FPGATrackSim.GNN.moduleMapTol
+    GNNGraphConstructionTool.moduleMapPath=PathResolver.FindCalibFile(flags.Trigger.FPGATrackSim.GNN.moduleMapPath)
+
+    result.setPrivateTools(GNNGraphConstructionTool)
+
+    return result
+
+def FPGATrackSimGNNEdgeClassifierToolCfg(flags):
+    result = ComponentAccumulator()
+
+    from AthOnnxComps.OnnxRuntimeInferenceConfig import OnnxRuntimeInferenceToolCfg
+    from AthOnnxComps.OnnxRuntimeFlags import OnnxRuntimeType
+
+    GNNEdgeClassifierTool = CompFactory.FPGATrackSimGNNEdgeClassifierTool()
+    GNNEdgeClassifierTool.GNNInferenceTool = result.popToolsAndMerge(OnnxRuntimeInferenceToolCfg(
+       flags, flags.Trigger.FPGATrackSim.GNN.GNNModelPath, OnnxRuntimeType.CPU))
+
+    result.setPrivateTools(GNNEdgeClassifierTool)
+
+    return result
+
+def FPGATrackSimGNNRoadMakerToolCfg(flags):
+    result = ComponentAccumulator()
+
+    GNNRoadMakerTool = CompFactory.FPGATrackSimGNNRoadMakerTool()
+    GNNRoadMakerTool.roadMakerTool = flags.Trigger.FPGATrackSim.GNN.roadMakerTool.value
+    GNNRoadMakerTool.edgeScoreCut = flags.Trigger.FPGATrackSim.GNN.edgeScoreCut
+    GNNRoadMakerTool.FPGATrackSimMappingSvc = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimMappingCfg(flags))
+
+    result.setPrivateTools(GNNRoadMakerTool)
+
+    return result
+    
+def FPGATrackSimGNNRootOutputToolCfg(flags):
+    result = ComponentAccumulator()
+
+    GNNRootOutputTool = CompFactory.FPGATrackSimGNNRootOutputTool()
+
+    result.addService(CompFactory.THistSvc(Output = ["TRIGFPGATrackSimGNNOUTPUT DATAFILE='GNNRootOutput.root', OPT='RECREATE'"]))
+    result.setPrivateTools(GNNRootOutputTool)
+
+    return result
+
+def FPGATrackSimDataFlowToolCfg(flags):
+    result=ComponentAccumulator()
+    DataFlowTool = CompFactory.FPGATrackSimDataFlowTool()
+    DataFlowTool.FPGATrackSimEventSelectionSvc = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimEventSelectionCfg(flags))
+    DataFlowTool.FPGATrackSimMappingSvc =  result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimMappingCfg(flags))
+    DataFlowTool.Chi2ndofCut = flags.Trigger.FPGATrackSim.ActiveConfig.chi2cut
+    DataFlowTool.THistSvc = CompFactory.THistSvc()
+    result.setPrivateTools(DataFlowTool)
+    return result
+
+def FPGATrackSimHoughRootOutputToolCfg(flags):
+    result=ComponentAccumulator()
+    HoughRootOutputTool = CompFactory.FPGATrackSimHoughRootOutputTool()
+    HoughRootOutputTool.FPGATrackSimEventSelectionSvc = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimEventSelectionCfg(flags))
+    HoughRootOutputTool.FPGATrackSimMappingSvc = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimMappingCfg(flags))
+    HoughRootOutputTool.THistSvc = CompFactory.THistSvc()
+    result.setPrivateTools(HoughRootOutputTool)
+    return result
+
+def LRTRoadFinderCfg(flags):
+    result=ComponentAccumulator()
+    LRTRoadFinder =CompFactory.FPGATrackSimHoughTransform_d0phi0_Tool()
+    LRTRoadFinder.FPGATrackSimBankSvc = result.getPrimaryAndMerge(FPGATrackSimBankSvcCfg(flags))
+    LRTRoadFinder.FPGATrackSimMappingSvc = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimMappingCfg(flags))
+    LRTRoadFinder.combine_layers = flags.Trigger.FPGATrackSim.ActiveConfig.lrtStraighttrackCombineLayers
+    LRTRoadFinder.convolution = flags.Trigger.FPGATrackSim.ActiveConfig.lrtStraighttrackConvolution
+    LRTRoadFinder.hitExtend_x = flags.Trigger.FPGATrackSim.ActiveConfig.lrtStraighttrackHitExtendX
+    LRTRoadFinder.scale = flags.Trigger.FPGATrackSim.ActiveConfig.scale
+    LRTRoadFinder.threshold = flags.Trigger.FPGATrackSim.ActiveConfig.lrtStraighttrackThreshold
+    result.setPrivateTools(LRTRoadFinder)
+    return result
+
+def NNTrackToolCfg(flags):
+    result=ComponentAccumulator()
+    NNTrackTool = CompFactory.FPGATrackSimNNTrackTool()
+    NNTrackTool.THistSvc = CompFactory.THistSvc()
+    NNTrackTool.FPGATrackSimMappingSvc = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimMappingCfg(flags))
+    NNTrackTool.FPGATrackSimBankSvc = result.getPrimaryAndMerge(FPGATrackSimBankSvcCfg(flags))
+    NNTrackTool.IdealGeoRoads = (flags.Trigger.FPGATrackSim.ActiveConfig.IdealGeoRoads and flags.Trigger.FPGATrackSim.tracking)
+    NNTrackTool.useSpacePoints = flags.Trigger.FPGATrackSim.spacePoints and not flags.Trigger.FPGATrackSim.ActiveConfig.genScan
+    NNTrackTool.SPRoadFilterTool = getSPRoadFilterTool(flags)
+    NNTrackTool.MinNumberOfRealHitsInATrack = 5 if flags.Trigger.FPGATrackSim.ActiveConfig.genScan else 9
+    
+    result.setPrivateTools(NNTrackTool)
+    return result
+
+def FPGATrackSimTrackFitterToolCfg(flags):
+    result=ComponentAccumulator()
+    TF_1st = CompFactory.FPGATrackSimTrackFitterTool("FPGATrackSimTrackFitterTool_1st")
+    TF_1st.GuessHits = flags.Trigger.FPGATrackSim.ActiveConfig.guessHits
+    TF_1st.IdealCoordFitType = flags.Trigger.FPGATrackSim.ActiveConfig.idealCoordFitType
+    TF_1st.FPGATrackSimBankSvc = result.getPrimaryAndMerge(FPGATrackSimBankSvcCfg(flags))
+    TF_1st.FPGATrackSimMappingSvc = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimMappingCfg(flags))
+    TF_1st.chi2DofRecoveryMax = flags.Trigger.FPGATrackSim.ActiveConfig.chi2DoFRecoveryMax
+    TF_1st.chi2DofRecoveryMin = flags.Trigger.FPGATrackSim.ActiveConfig.chi2DoFRecoveryMin
+    TF_1st.doMajority = flags.Trigger.FPGATrackSim.ActiveConfig.doMajority
+    TF_1st.nHits_noRecovery = flags.Trigger.FPGATrackSim.ActiveConfig.nHitsNoRecovery
+    TF_1st.DoDeltaGPhis = flags.Trigger.FPGATrackSim.ActiveConfig.doDeltaGPhis
+    TF_1st.DoMissingHitsChecks = flags.Trigger.FPGATrackSim.ActiveConfig.doMissingHitsChecks
+    TF_1st.IdealGeoRoads = (flags.Trigger.FPGATrackSim.ActiveConfig.IdealGeoRoads and flags.Trigger.FPGATrackSim.tracking)
+    TF_1st.useSpacePoints = flags.Trigger.FPGATrackSim.spacePoints and not flags.Trigger.FPGATrackSim.ActiveConfig.genScan
+    TF_1st.SPRoadFilterTool = getSPRoadFilterTool(flags)
+    result.addPublicTool(TF_1st, primary=True)
+    return result
+
+def FPGATrackSimOverlapRemovalToolCfg(flags):
+    result=ComponentAccumulator()
+    OR_1st = CompFactory.FPGATrackSimOverlapRemovalTool("FPGATrackSimOverlapRemovalTool_1st")
+    OR_1st.ORAlgo = "Normal"
+    OR_1st.doFastOR =flags.Trigger.FPGATrackSim.ActiveConfig.doFastOR
+    OR_1st.NumOfHitPerGrouping = 3
+    OR_1st.FPGATrackSimMappingSvc = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimMappingCfg(flags))
+    OR_1st.MinChi2 = flags.Trigger.FPGATrackSim.ActiveConfig.chi2cut    
+    if flags.Trigger.FPGATrackSim.ActiveConfig.hough or flags.Trigger.FPGATrackSim.ActiveConfig.hough1D:
+        OR_1st.nBins_x = flags.Trigger.FPGATrackSim.ActiveConfig.xBins + 2 * flags.Trigger.FPGATrackSim.ActiveConfig.xBufferBins
+        OR_1st.nBins_y = flags.Trigger.FPGATrackSim.ActiveConfig.yBins + 2 * flags.Trigger.FPGATrackSim.ActiveConfig.yBufferBins
+        OR_1st.localMaxWindowSize = flags.Trigger.FPGATrackSim.ActiveConfig.localMaxWindowSize
+        OR_1st.roadSliceOR = flags.Trigger.FPGATrackSim.ActiveConfig.roadSliceOR
+    
+    result.addPublicTool(OR_1st, primary=True)
+    return result
+
+def prepareFlagsForFPGATrackSimLogicalHitsProcessAlg(flags):
+    newFlags = flags.cloneAndReplace("Trigger.FPGATrackSim.ActiveConfig", "Trigger.FPGATrackSim." + flags.Trigger.FPGATrackSim.algoTag)
+    return newFlags
+
+def getSPRoadFilterTool(flags,secondStage=False):
+    name="FPGATrackSimSpacepointRoadFilterTool_1st"
+    if secondStage:
+        name="FPGATrackSimSpacepointRoadFilterTool_2st"
+    SPRoadFilter = CompFactory.FPGATrackSimSpacepointRoadFilterTool(name)
+    SPRoadFilter.filtering = flags.Trigger.FPGATrackSim.ActiveConfig.spacePointFiltering
+    SPRoadFilter.minSpacePlusPixel = flags.Trigger.FPGATrackSim.minSpacePlusPixel
+    SPRoadFilter.isSecondStage = secondStage
+    # TODO guard here against threshold being more than one value?
+    if (flags.Trigger.FPGATrackSim.ActiveConfig.hough1D):
+        SPRoadFilter.threshold = flags.Trigger.FPGATrackSim.Hough1D.threshold[0]
+    else:
+        SPRoadFilter.threshold = flags.Trigger.FPGATrackSim.ActiveConfig.threshold[0]
+    SPRoadFilter.setSectors = (flags.Trigger.FPGATrackSim.ActiveConfig.IdealGeoRoads and flags.Trigger.FPGATrackSim.tracking)
+    return SPRoadFilter
+
+def FPGATrackSimLogicalHitsProcessAlgCfg(inputFlags):
+
+    flags = prepareFlagsForFPGATrackSimLogicalHitsProcessAlg(inputFlags)
+   
+    result=ComponentAccumulator()
+    if not flags.Trigger.FPGATrackSim.wrapperFileName:
+        from InDetConfig.InDetPrepRawDataFormationConfig import AthenaTrkClusterizationCfg
+        result.merge(AthenaTrkClusterizationCfg(flags))
+
+    theFPGATrackSimLogicalHitsProcessAlg=CompFactory.FPGATrackSimLogicalHitsProcessAlg()
+    theFPGATrackSimLogicalHitsProcessAlg.writeOutputData = flags.Trigger.FPGATrackSim.writeAdditionalOutputData
+    theFPGATrackSimLogicalHitsProcessAlg.tracking = flags.Trigger.FPGATrackSim.tracking
+    theFPGATrackSimLogicalHitsProcessAlg.doOverlapRemoval = flags.Trigger.FPGATrackSim.doOverlapRemoval
+    theFPGATrackSimLogicalHitsProcessAlg.DoMissingHitsChecks = flags.Trigger.FPGATrackSim.ActiveConfig.doMissingHitsChecks
+    theFPGATrackSimLogicalHitsProcessAlg.DoHoughRootOutput1st = flags.Trigger.FPGATrackSim.ActiveConfig.houghRootoutput1st
+    theFPGATrackSimLogicalHitsProcessAlg.NumOfHitPerGrouping = flags.Trigger.FPGATrackSim.ActiveConfig.NumOfHitPerGrouping
+    theFPGATrackSimLogicalHitsProcessAlg.DoNNTrack = flags.Trigger.FPGATrackSim.ActiveConfig.trackNNAnalysis
+    theFPGATrackSimLogicalHitsProcessAlg.eventSelector = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimEventSelectionCfg(flags))
+    theFPGATrackSimLogicalHitsProcessAlg.TrackScoreCut = flags.Trigger.FPGATrackSim.ActiveConfig.chi2cut
+    theFPGATrackSimLogicalHitsProcessAlg.passLowestChi2TrackOnly = flags.Trigger.FPGATrackSim.ActiveConfig.passLowestChi2TrackOnly
+    FPGATrackSimMaping = result.getPrimaryAndMerge(FPGATrackSimDataPrepConfig.FPGATrackSimMappingCfg(flags))
+    theFPGATrackSimLogicalHitsProcessAlg.FPGATrackSimMapping = FPGATrackSimMaping
+
+    # If tracking is set to False, don't configure the bank service
+    if flags.Trigger.FPGATrackSim.tracking:
+        result.getPrimaryAndMerge(FPGATrackSimBankSvcCfg(flags))
+
+    if (flags.Trigger.FPGATrackSim.ActiveConfig.hough1D):
+        theFPGATrackSimLogicalHitsProcessAlg.RoadFinder = result.getPrimaryAndMerge(FPGATrackSimRoadUnionTool1DCfg(flags))
+    elif (flags.Trigger.FPGATrackSim.ActiveConfig.genScan):
+        theFPGATrackSimLogicalHitsProcessAlg.RoadFinder = result.getPrimaryAndMerge(FPGATrackSimRoadUnionToolGenScanCfg(flags))
+    elif (flags.Trigger.FPGATrackSim.ActiveConfig.GNN):
+        theFPGATrackSimLogicalHitsProcessAlg.RoadFinder = result.getPrimaryAndMerge(FPGATrackSimRoadUnionToolGNNCfg(flags))
+    else:
+        theFPGATrackSimLogicalHitsProcessAlg.RoadFinder = result.getPrimaryAndMerge(FPGATrackSimRoadUnionToolCfg(flags))
+
+    if (flags.Trigger.FPGATrackSim.ActiveConfig.etaPatternFilter):
+        EtaPatternFilter = CompFactory.FPGATrackSimEtaPatternFilterTool()
+        EtaPatternFilter.FPGATrackSimMappingSvc = FPGATrackSimMaping
+        EtaPatternFilter.threshold = flags.Trigger.FPGATrackSim.Hough1D.threshold[0]
+        EtaPatternFilter.EtaPatterns = flags.Trigger.FPGATrackSim.mapsDir+"/"+FPGATrackSimDataPrepConfig.getBaseName(flags)+".patt"
+        theFPGATrackSimLogicalHitsProcessAlg.RoadFilter = EtaPatternFilter
+        theFPGATrackSimLogicalHitsProcessAlg.FilterRoads = True
+
+    if (flags.Trigger.FPGATrackSim.ActiveConfig.phiRoadFilter):
+        RoadFilter2 = CompFactory.FPGATrackSimPhiRoadFilterTool()
+        RoadFilter2.FPGATrackSimMappingSvc = FPGATrackSimMaping
+        RoadFilter2.threshold = flags.Trigger.FPGATrackSim.Hough1D.threshold[0]
+        RoadFilter2.fieldCorrection = flags.Trigger.FPGATrackSim.ActiveConfig.fieldCorrection
+        ### set the window to be a constant value (could be changed), array should be length of the threshold
+        windows = [flags.Trigger.FPGATrackSim.Hough1D.phifilterwindow for i in range(len(flags.Trigger.FPGATrackSim.ActiveConfig.hitExtendX))]
+        RoadFilter2.window = windows
+        
+        theFPGATrackSimLogicalHitsProcessAlg.RoadFilter2 = RoadFilter2
+        theFPGATrackSimLogicalHitsProcessAlg.FilterRoads2 = True
+
+
+    theFPGATrackSimLogicalHitsProcessAlg.HoughRootOutputTool = result.getPrimaryAndMerge(FPGATrackSimHoughRootOutputToolCfg(flags))
+
+    LRTRoadFilter = CompFactory.FPGATrackSimLLPRoadFilterTool()
+    result.addPublicTool(LRTRoadFilter)
+    theFPGATrackSimLogicalHitsProcessAlg.LRTRoadFilter = LRTRoadFilter
+
+    theFPGATrackSimLogicalHitsProcessAlg.LRTRoadFinder = result.getPrimaryAndMerge(LRTRoadFinderCfg(flags))
+    theFPGATrackSimLogicalHitsProcessAlg.NNTrackTool = result.getPrimaryAndMerge(NNTrackToolCfg(flags))
+
+    theFPGATrackSimLogicalHitsProcessAlg.OutputTool = result.getPrimaryAndMerge(FPGATrackSimWriteOutputCfg(flags))
+    theFPGATrackSimLogicalHitsProcessAlg.TrackFitter_1st = result.getPrimaryAndMerge(FPGATrackSimTrackFitterToolCfg(flags))
+    theFPGATrackSimLogicalHitsProcessAlg.OverlapRemoval_1st = result.getPrimaryAndMerge(FPGATrackSimOverlapRemovalToolCfg(flags))
+
+    # Create SPRoadFilterTool if spacepoints are turned on. TODO: make things configurable?
+    if flags.Trigger.FPGATrackSim.spacePoints and not flags.Trigger.FPGATrackSim.ActiveConfig.genScan:
+        theFPGATrackSimLogicalHitsProcessAlg.SPRoadFilterTool = getSPRoadFilterTool(flags)
+        theFPGATrackSimLogicalHitsProcessAlg.Spacepoints = True
+
+
+    if flags.Trigger.FPGATrackSim.ActiveConfig.lrt:
+        assert flags.Trigger.FPGATrackSim.ActiveConfig.lrtUseBasicHitFilter != flags.Trigger.FPGATrackSim.ActiveConfig.lrtUseMlHitFilter, 'Inconsistent LRT hit filtering setup, need either ML of Basic filtering enabled'
+        assert flags.Trigger.FPGATrackSim.ActiveConfig.lrtUseStraightTrackHT != flags.Trigger.FPGATrackSim.ActiveConfig.lrtUseDoubletHT, 'Inconsistent LRT HT setup, need either double or strightTrack enabled'
+        theFPGATrackSimLogicalHitsProcessAlg.doLRT = True
+        theFPGATrackSimLogicalHitsProcessAlg.LRTHitFiltering = (not flags.Trigger.FPGATrackSim.ActiveConfig.lrtSkipHitFiltering)
+
+    from FPGATrackSimAlgorithms.FPGATrackSimAlgorithmConfig import FPGATrackSimLogicalHitsProcessAlgMonitoringCfg
+    theFPGATrackSimLogicalHitsProcessAlg.MonTool = result.getPrimaryAndMerge(FPGATrackSimLogicalHitsProcessAlgMonitoringCfg(flags))
+
+    result.addEventAlgo(theFPGATrackSimLogicalHitsProcessAlg)
+
+    return result
+
+
+
+
+if __name__ == "__main__":
+    from AthenaConfiguration.AllConfigFlags import initConfigFlags
+    from AthenaConfiguration.MainServicesConfig import MainServicesCfg
+    
+
+    flags = initConfigFlags()
+    
+    ############################################
+    # Flags used in the prototrack chain
+    FinalProtoTrackChainxAODTracksKey="FPGA"
+    flags.Detector.EnableCalo = False
+
+    # ensure that the xAOD SP and cluster containers are available
+    flags.Tracking.ITkMainPass.doAthenaToActsSpacePoint=True
+    flags.Tracking.ITkMainPass.doAthenaToActsCluster=True
+    from TrkConfig.TrkConfigFlags import TrackingComponent
+    flags.Tracking.recoChain = [TrackingComponent.ActsChain] # another viable option is TrackingComponent.AthenaChain
+    flags.Acts.doRotCorrection = False
+
+    ############################################
+    flags.Concurrency.NumThreads=1
+    #flags.Concurrency.NumProcs=0
+    flags.Scheduler.ShowDataDeps=True
+    flags.Scheduler.CheckDependencies=True
+    flags.Debug.DumpEvtStore=False
+
+    # flags.Exec.DebugStage="exec" # useful option to debug the execution of the job - we want it commented out for production
+    flags.fillFromArgs()
+
+    assert not flags.Trigger.FPGATrackSim.pipeline.startswith('F-5'),"ERROR You are trying to run an F-5* pipeline! This is not yet supported!"
+
+    if (flags.Trigger.FPGATrackSim.pipeline.startswith('F-1')):
+        print("You are trying to run an F-100 pipeline! I am going to run the Data Prep chain for you and nothing else!")
+        FPGATrackSimDataPrepConfig.runDataPrepChain()
+    elif (flags.Trigger.FPGATrackSim.pipeline.startswith('F-2')):
+        print("You are trying to run an F-2* pipeline! I am auto-configuring the 1D bitshift for you, including eta pattern filters and phi road filters")
+        flags.Trigger.FPGATrackSim.Hough.etaPatternFilter = True
+        flags.Trigger.FPGATrackSim.Hough.phiRoadFilter = True
+        flags.Trigger.FPGATrackSim.Hough.hough1D = True
+        flags.Trigger.FPGATrackSim.Hough.hough = False
+    elif (flags.Trigger.FPGATrackSim.pipeline.startswith('F-3')):
+        print("You are trying to run an F-3* pipeline! I am auto-configuring the 2D HT for you, and disabling the eta pattern filter and phi road filter. Whether you wanted to or not")
+        flags.Trigger.FPGATrackSim.Hough.etaPatternFilter = False
+        flags.Trigger.FPGATrackSim.Hough.phiRoadFilter = False
+        flags.Trigger.FPGATrackSim.Hough.hough1D = False
+        flags.Trigger.FPGATrackSim.Hough.hough = True
+    elif (flags.Trigger.FPGATrackSim.pipeline.startswith('F-4')):
+        print("You are trying to run an F-4* pipeline! I am auto-configuring the GNN pattern recognition for you. Whether you wanted to or not")
+        flags.Trigger.FPGATrackSim.Hough.GNN = True
+        flags.Trigger.FPGATrackSim.Hough.chi2cut = 25 # All of the track candidates have chi2 values around 20 for some reason. Needs further investigation. For now move the default cut value to 25
+    elif (flags.Trigger.FPGATrackSim.pipeline.startswith('F-6')):
+        print("You are trying to run an F-6* pipeline! I am auto-configuring the Inside-Out for you. Whether you wanted to or not")
+        flags.Trigger.FPGATrackSim.Hough.genScan=True
+        flags.Trigger.FPGATrackSim.spacePoints = flags.Trigger.FPGATrackSim.Hough.secondStage
+    elif (flags.Trigger.FPGATrackSim.pipeline != ""):
+        raise AssertionError("ERROR You are trying to run the pipeline " + flags.Trigger.FPGATrackSim.pipeline + " which is not yet supported!")
+
+    if (not flags.Trigger.FPGATrackSim.pipeline.startswith('F-1')): ### if DP pipeline skip everything else!
+
+        splitPipeline=flags.Trigger.FPGATrackSim.pipeline.split('-')
+        trackingOption=9999999
+        if (len(splitPipeline) > 1): trackingOption=int(splitPipeline[1])
+        if (trackingOption < 9999999):
+            trackingOptionMod = (trackingOption % 100)
+            if (trackingOptionMod == 0):
+                print("You are trying to run the linearized chi2 fit as part of a pipeline! I am going to enable this for you whether you want to or not")
+                flags.Trigger.FPGATrackSim.tracking = True
+                flags.Trigger.FPGATrackSim.Hough.trackNNAnalysis = False
+            elif (trackingOptionMod == 10):
+                print("You are trying to run the NN fake rejection as part of a pipeline! I am going to enable this for you whether you want to or not")
+                flags.Trigger.FPGATrackSim.tracking = True
+                flags.Trigger.FPGATrackSim.Hough.trackNNAnalysis = True
+            else:
+                raise AssertionError("ERROR Your tracking option for the pipeline = " + str(trackingOption) + " is not yet supported!")
+
+        if isinstance(flags.Trigger.FPGATrackSim.wrapperFileName, str):
+            log.info("wrapperFile is string, converting to list")
+            flags.Trigger.FPGATrackSim.wrapperFileName = [flags.Trigger.FPGATrackSim.wrapperFileName]
+            flags.Input.Files = lambda f: [f.Trigger.FPGATrackSim.wrapperFileName]
+
+        flags.lock()
+        flags.dump()
+        flags = flags.cloneAndReplace("Tracking.ActiveConfig","Tracking.MainPass")
+        acc=MainServicesCfg(flags)
+
+        if flags.Trigger.FPGATrackSim.writeAdditionalOutputData:
+            acc.addService(CompFactory.THistSvc(Output = ["EXPERT DATAFILE='monitoring.root', OPT='RECREATE'"]))
+
+            if (flags.Trigger.FPGATrackSim.Hough.trackNNAnalysis):
+                acc.addService(CompFactory.THistSvc(Output = ["FPGATRACKSIMOUTPUTNNPATHFINDER DATAFILE='NNPathfinder.root', OPT='RECREATE'"]))
+
+            if (flags.Trigger.FPGATrackSim.Hough.houghRootoutput1st | flags.Trigger.FPGATrackSim.Hough.houghRootoutput2nd):
+                acc.addService(CompFactory.THistSvc(Output = ["TRIGFPGATrackSimHOUGHOUTPUT DATAFILE='HoughRootOutput.root', OPT='RECREATE'"]))
+
+            if flags.Trigger.FPGATrackSim.Hough.writeTestOutput:
+                acc.addService(CompFactory.THistSvc(Output = ["FPGATRACKSIMOUTPUT DATAFILE='test.root', OPT='RECREATE'"]))
+
+            if (flags.Trigger.FPGATrackSim.Hough.genScan):
+                acc.addService(CompFactory.THistSvc(Output = ["GENSCAN DATAFILE='genscan.root', OPT='RECREATE'"]))
+
+        if not flags.Trigger.FPGATrackSim.wrapperFileName:
+            from AthenaPoolCnvSvc.PoolReadConfig import PoolReadCfg
+            acc.merge(PoolReadCfg(flags))
+
+            if flags.Input.isMC:
+                from xAODTruthCnv.xAODTruthCnvConfig import GEN_AOD2xAODCfg
+                acc.merge(GEN_AOD2xAODCfg(flags))
+
+                from JetRecConfig.JetRecoSteering import addTruthPileupJetsToOutputCfg # TO DO: check if this is indeed necessary for pileup samples
+                acc.merge(addTruthPileupJetsToOutputCfg(flags))
+
+            if flags.Detector.EnableCalo:
+                from CaloRec.CaloRecoConfig import CaloRecoCfg
+                acc.merge(CaloRecoCfg(flags))
+
+            if flags.Tracking.recoChain:
+                from InDetConfig.TrackRecoConfig import InDetTrackRecoCfg
+                acc.merge(InDetTrackRecoCfg(flags))
+
+        # Configure both the dataprep and logical hits algorithms.
+        acc.merge(FPGATrackSimDataPrepConfig.FPGATrackSimDataPrepAlgCfg(flags))
+        acc.merge(FPGATrackSimLogicalHitsProcessAlgCfg(flags))
+
+        # If second stage is turned on, turn that algorithm on too.
+        if flags.Trigger.FPGATrackSim.Hough.secondStage:
+            acc.merge(FPGATrackSimSecondStageConfig.FPGATrackSimSecondStageAlgCfg(flags))
+
+        if flags.Trigger.FPGATrackSim.doEDMConversion:
+            stage = "_2nd" if flags.Trigger.FPGATrackSim.Hough.secondStage else "_1st"
+            convertTracks = flags.Trigger.FPGATrackSim.tracking
+            acc.merge(FPGATrackSimDataPrepConfig.FPGAConversionAlgCfg(flags, name = f"FPGAConversionAlg{stage}",
+                                                                        stage = f"{stage}",
+                                                                        doActsTrk=True,
+                                                                        doSP=flags.Trigger.FPGATrackSim.spacePoints,
+                                                                        useRoads=not flags.Trigger.FPGATrackSim.tracking))
+
+            from FPGATrackSimPrototrackFitter.FPGATrackSimPrototrackFitterConfig import FPGATruthDecorationCfg, FPGAProtoTrackFitCfg
+            acc.merge(FPGAProtoTrackFitCfg(flags,stage=f"{stage}",
+                                            useRoads=not flags.Trigger.FPGATrackSim.tracking)) # Run ACTS KF
+            acc.merge(FPGATruthDecorationCfg(flags,FinalProtoTrackChainxAODTracksKey=FinalProtoTrackChainxAODTracksKey,stage=f"{stage}")) # Run Truth Matching/Decoration chain
+            if not flags.Trigger.FPGATrackSim.wrapperFileName and flags.Trigger.FPGATrackSim.runCKF:
+                from FPGATrackSimConfTools.FPGATrackExtensionConfig import FPGATrackExtensionAlgCfg
+                acc.merge(FPGATrackExtensionAlgCfg(flags, enableTrackStatePrinter=False, name="FPGATrackExtension",
+                                                    ProtoTracksLocation=f"ActsProtoTracks{stage}FromFPGATrack")) # run CKF track extension on FPGA tracks
+
+            if flags.Trigger.FPGATrackSim.writeToAOD: acc.merge(FPGATrackSimDataPrepConfig.WriteToAOD(flags,
+                                                                                                        stage = f"{stage}",
+                                                                                                        finalTrackParticles=f"{FinalProtoTrackChainxAODTracksKey}TrackParticles"))
+
+            # Reporting algorithm (used for debugging - can be disabled)
+            from FPGATrackSimReporting.FPGATrackSimReportingConfig import FPGATrackSimReportingCfg
+            acc.merge(FPGATrackSimReportingCfg(flags, stage=f"{stage}",
+                                                perEventReports = ((flags.Trigger.FPGATrackSim.sampleType != 'skipTruth') and flags.Exec.MaxEvents<=10 ) )) # disable perEventReports for pileup samples or many events
+
+        acc.store(open('AnalysisConfig.pkl','wb'))
+
+        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
+
+        statusCode = acc.run(flags.Exec.MaxEvents)
+        assert statusCode.isSuccess() is True, "Application execution did not succeed"
-- 
GitLab


From 53012bcb3c06e93b9f2fa90dd12f96aa207d81ba Mon Sep 17 00:00:00 2001
From: Joseph Philip Surdutovich <surdutovich.1@buckeyemail.osu.edu>
Date: Mon, 31 Mar 2025 04:56:59 +0000
Subject: [PATCH 3/3] Edit FPGATrackSimAnalysisConfig.py

---
 .../python/FPGATrackSimAnalysisConfig.py      | 24 ++++++++++++++++++-
 1 file changed, 23 insertions(+), 1 deletion(-)

diff --git a/Trigger/EFTracking/FPGATrackSim/FPGATrackSimConfTools/python/FPGATrackSimAnalysisConfig.py b/Trigger/EFTracking/FPGATrackSim/FPGATrackSimConfTools/python/FPGATrackSimAnalysisConfig.py
index 25d3fc9cea6c..046caae5df13 100755
--- a/Trigger/EFTracking/FPGATrackSim/FPGATrackSimConfTools/python/FPGATrackSimAnalysisConfig.py
+++ b/Trigger/EFTracking/FPGATrackSim/FPGATrackSimConfTools/python/FPGATrackSimAnalysisConfig.py
@@ -525,7 +525,26 @@ def FPGATrackSimLogicalHitsProcessAlgCfg(inputFlags):
 
     return result
 
-
+def getChi2Cut(region):
+    #list of chi2 cuts for time being. Last four are stand ins since those new regions don't work for now!
+    chi2cut_l = [12, 16, 60, 16, 60, 60, 14, 20, 16, 19, 19, 15, 18, 12, 15, 15, 20, 20, 20, 20]
+    binSize = 0.2
+    side = (region >> 5) & 0x1
+    etaBin = (region >> 6) & 0x1F
+    etaRange = [round(binSize * etaBin, 1), round(binSize * (etaBin + 1), 1)] if side else [round(-binSize * (etaBin + 1), 1), round(-binSize * etaBin, 1)]
+    abs_etaRange = tuple(abs(val) for val in etaRange)
+
+    eta_to_chi2 = {
+        (0.0, 0.2): chi2cut_l[0], (0.2, 0.4): chi2cut_l[1], (0.4, 0.6): chi2cut_l[2],
+        (0.6, 0.8): chi2cut_l[3], (0.8, 1.0): chi2cut_l[4], (1.0, 1.2): chi2cut_l[5],
+        (1.2, 1.4): chi2cut_l[6], (1.4, 1.6): chi2cut_l[7], (1.6, 1.8): chi2cut_l[8],
+        (1.8, 2.0): chi2cut_l[9], (2.0, 2.2): chi2cut_l[10], (2.2, 2.4): chi2cut_l[11],
+        (2.4, 2.6): chi2cut_l[12], (2.6, 2.8): chi2cut_l[13], (2.8, 3.0): chi2cut_l[14],
+        (3.0, 3.2): chi2cut_l[15], (3.2, 3.4): chi2cut_l[16], (3.4, 3.6): chi2cut_l[17], 
+        (3.6, 3.8): chi2cut_l[18], (3.8, 4.0): chi2cut_l[19]
+    }
+
+    return eta_to_chi2.get(abs_etaRange, 9) #Set default chi2 if the region is not found
 
 
 if __name__ == "__main__":
@@ -556,6 +575,9 @@ if __name__ == "__main__":
 
     # flags.Exec.DebugStage="exec" # useful option to debug the execution of the job - we want it commented out for production
     flags.fillFromArgs()
+    
+    if flags.Trigger.FPGATrackSim.Hough.useVaryingChi2Cut: 
+        flags.Trigger.FPGATrackSim.Hough.chi2cut = getChi2Cut(flags.Trigger.FPGATrackSim.region)
 
     assert not flags.Trigger.FPGATrackSim.pipeline.startswith('F-5'),"ERROR You are trying to run an F-5* pipeline! This is not yet supported!"
 
-- 
GitLab