Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 10:30:52

0001 from Gaudi.Configuration import *
0002 
0003 from Configurables import ApplicationMgr, AuditorSvc, EICDataSvc, PodioOutput, GeoSvc
0004 from Configurables import Gaudi__Monitoring__MessageSvcSink as MessageSvcSink
0005 from Configurables import Gaudi__Histograming__Sink__Root as RootHistoSink
0006 from GaudiKernel import SystemOfUnits as units
0007 from GaudiKernel.SystemOfUnits import eV, MeV, GeV, mm, cm, mrad
0008 
0009 import json
0010 
0011 detector_path = str(os.environ.get("DETECTOR_PATH", "."))
0012 detector_name = str(os.environ.get("DETECTOR_CONFIG", "epic"))
0013 detector_config = str(os.environ.get("DETECTOR_CONFIG", detector_name))
0014 detector_version = str(os.environ.get("DETECTOR_VERSION", "main"))
0015 
0016 # Detector features that affect reconstruction
0017 has_ecal_barrel_imaging = True
0018 has_pid_backward_pfrich = True
0019 if "epic" in detector_name and "sciglass" in detector_config:
0020     has_ecal_barrel_imaging = False
0021     has_pid_backward_pfrich = False
0022 if "epic" in detector_name and "arches" in detector_config:
0023     has_ecal_barrel_imaging = False
0024     has_pid_backward_pfrich = False
0025 
0026 if "PBEAM" in os.environ:
0027     ionBeamEnergy = str(os.environ["PBEAM"])
0028 else:
0029     ionBeamEnergy = 100
0030 
0031 # ZDC reconstruction calibrations
0032 try:
0033     ffi_zdc_calibrations = "calibrations/ffi_zdc.json"
0034     with open(os.path.join(detector_path, ffi_zdc_calibrations)) as f:
0035         ffi_zdc_config = json.load(f)
0036 
0037         def ffi_zdc_cal_parse(ffi_zdc_cal):
0038             ffi_zdc_cal_sf = float(ffi_zdc_cal["sampling_fraction"])
0039             ffi_zdc_cal_cl_kwargs = {
0040                 "minClusterCenterEdep": eval(ffi_zdc_cal["minClusterCenterEdep"]),
0041                 "minClusterHitEdep": eval(ffi_zdc_cal["minClusterHitEdep"]),
0042                 "localDistXY": [
0043                     eval(ffi_zdc_cal["localDistXY"][0]),
0044                     eval(ffi_zdc_cal["localDistXY"][1]),
0045                 ],
0046                 "splitCluster": bool(ffi_zdc_cal["splitCluster"]),
0047             }
0048             return ffi_zdc_cal_sf, ffi_zdc_cal_cl_kwargs
0049 
0050         ffi_zdc_ecal_sf, ffi_zdc_ecal_cl_kwargs = ffi_zdc_cal_parse(
0051             ffi_zdc_config["ffi_zdc_ecal"]
0052         )
0053         ffi_zdc_hcal_sf, ffi_zdc_hcal_cl_kwargs = ffi_zdc_cal_parse(
0054             ffi_zdc_config["ffi_zdc_hcal"]
0055         )
0056 except (IOError, OSError):
0057     print(f"Using default ffi_zdc calibrations; {ffi_zdc_calibrations} not found.")
0058     ffi_zdc_ecal_sf = float(os.environ.get("FFI_ZDC_ECAL_SAMP_FRAC", 1.0))
0059     ffi_zdc_hcal_sf = float(os.environ.get("FFI_ZDC_HCAL_SAMP_FRAC", 1.0))
0060 
0061 # RICH reconstruction
0062 qe_data = [
0063     (1.0, 0.25),
0064     (7.5, 0.25),
0065 ]
0066 
0067 # CAL reconstruction
0068 # get sampling fractions from system environment variable
0069 ci_ecal_sf = float(os.environ.get("CI_ECAL_SAMP_FRAC", 0.03))
0070 cb_hcal_sf = float(os.environ.get("CB_HCAL_SAMP_FRAC", 0.038))
0071 ci_hcal_sf = float(os.environ.get("CI_HCAL_SAMP_FRAC", 0.025))
0072 ce_hcal_sf = float(os.environ.get("CE_HCAL_SAMP_FRAC", 0.025))
0073 
0074 # input arguments from calibration file
0075 with open(f"{detector_path}/calibrations/emcal_barrel_calibration.json") as f:
0076     calib_data = json.load(f)["electron"]
0077 
0078 print(calib_data)
0079 
0080 # input calorimeter DAQ info
0081 calo_daq = {}
0082 with open(f"{detector_path}/calibrations/calo_digi_default.json") as f:
0083     calo_config = json.load(f)
0084     ## add proper ADC capacity based on bit depth
0085     for sys in calo_config:
0086         cfg = calo_config[sys]
0087         calo_daq[sys] = {
0088             "dynamicRangeADC": eval(cfg["dynamicRange"]),
0089             "capacityADC": 2 ** int(cfg["capacityBitsADC"]),
0090             "pedestalMean": int(cfg["pedestalMean"]),
0091             "pedestalSigma": float(cfg["pedestalSigma"]),
0092         }
0093 print(calo_daq)
0094 
0095 img_barrel_sf = float(calib_data["sampling_fraction_img"])
0096 scifi_barrel_sf = float(calib_data["sampling_fraction_scfi"])
0097 
0098 # input and output
0099 input_sims = [
0100     f.strip() for f in str.split(os.environ["JUGGLER_SIM_FILE"], ",") if f.strip()
0101 ]
0102 output_rec = str(os.environ["JUGGLER_REC_FILE"])
0103 n_events = int(os.environ["JUGGLER_N_EVENTS"])
0104 
0105 # services
0106 services = []
0107 # auditor service
0108 services.append(AuditorSvc("AuditorSvc", Auditors=["ChronoAuditor"]))
0109 # geometry service
0110 ## note: old version of material map is called material-maps.XXX, new version is materials-map.XXX
0111 ##       these names are somewhat inconsistent, and should probably all be renamed to 'material-map.XXX'
0112 ##       FIXME
0113 services.append(
0114     GeoSvc(
0115         "GeoSvc",
0116         detectors=["{}/{}.xml".format(detector_path, detector_config)],
0117         materials="calibrations/materials-map.cbor",
0118         OutputLevel=WARNING,
0119     )
0120 )
0121 # data service
0122 services.append(EICDataSvc("EventDataSvc", inputs=input_sims, OutputLevel=WARNING))
0123 
0124 # message service
0125 MessageSvc().OutputLevel = INFO
0126 services.append(MessageSvcSink())
0127 
0128 # ROOT histogram service
0129 RootHistSvc("RootHistSvc").OutputFile = "histo.root"
0130 services.append(RootHistoSink())
0131 
0132 # juggler components
0133 from Configurables import PodioInput
0134 
0135 from Configurables import Jug__Fast__MC2SmearedParticle as MC2DummyParticle
0136 from Configurables import Jug__Fast__ParticlesWithTruthPID as ParticlesWithTruthPID
0137 from Configurables import Jug__Fast__SmearedFarForwardParticles as FFSmearedParticles
0138 
0139 from Configurables import Jug__Fast__MatchClusters as MatchClusters
0140 from Configurables import Jug__Fast__ClusterMerger as ClusterMerger
0141 from Configurables import (
0142     Jug__Fast__TruthEnergyPositionClusterMerger as EnergyPositionClusterMerger,
0143 )
0144 from Configurables import (
0145     Jug__Fast__InclusiveKinematicsTruth as InclusiveKinematicsTruth,
0146 )
0147 from Configurables import Jug__Fast__TruthClustering as TruthClustering
0148 
0149 from Configurables import Jug__Digi__SimTrackerHitsCollector as SimTrackerHitsCollector
0150 from Configurables import Jug__Digi__PhotoMultiplierDigi as PhotoMultiplierDigi
0151 from Configurables import Jug__Digi__CalorimeterHitDigi as CalHitDigi
0152 from Configurables import Jug__Digi__SiliconTrackerDigi as TrackerDigi
0153 
0154 from Configurables import Jug__Reco__FarForwardParticles as FarForwardParticles
0155 
0156 from Configurables import (
0157     Jug__Reco__TrackerHitReconstruction as TrackerHitReconstruction,
0158 )
0159 from Configurables import Jug__Reco__TrackingHitsCollector2 as TrackingHitsCollector
0160 from Configurables import Jug__Reco__TrackerSourceLinker as TrackerSourceLinker
0161 
0162 from Configurables import Jug__Reco__TrackParamTruthInit as TrackParamTruthInit
0163 from Configurables import Jug__Reco__TrackParamClusterInit as TrackParamClusterInit
0164 from Configurables import (
0165     Jug__Reco__TrackParamVertexClusterInit as TrackParamVertexClusterInit,
0166 )
0167 from Configurables import Jug__Reco__CKFTracking as CKFTracking
0168 from Configurables import Jug__Reco__ParticlesFromTrackFit as ParticlesFromTrackFit
0169 
0170 # from Configurables import Jug__Reco__TrajectoryFromTrackFit as TrajectoryFromTrackFit
0171 from Configurables import (
0172     Jug__Reco__InclusiveKinematicsElectron as InclusiveKinematicsElectron,
0173 )
0174 from Configurables import Jug__Reco__InclusiveKinematicsDA as InclusiveKinematicsDA
0175 from Configurables import Jug__Reco__InclusiveKinematicsJB as InclusiveKinematicsJB
0176 from Configurables import (
0177     Jug__Reco__InclusiveKinematicsSigma as InclusiveKinematicsSigma,
0178 )
0179 from Configurables import (
0180     Jug__Reco__InclusiveKinematicseSigma as InclusiveKinematicseSigma,
0181 )
0182 
0183 from Configurables import Jug__Reco__FarForwardParticles as FFRecoRP
0184 from Configurables import Jug__Reco__FarForwardParticlesOMD as FFRecoOMD
0185 
0186 from Configurables import Jug__Reco__CalorimeterHitReco as CalHitReco
0187 from Configurables import Jug__Reco__CalorimeterHitsMerger as CalHitsMerger
0188 from Configurables import Jug__Reco__CalorimeterIslandCluster as IslandCluster
0189 
0190 from Configurables import Jug__Reco__ImagingPixelReco as ImCalPixelReco
0191 from Configurables import Jug__Reco__ImagingTopoCluster as ImagingCluster
0192 
0193 from Configurables import Jug__Reco__ClusterRecoCoG as RecoCoG
0194 from Configurables import Jug__Reco__ImagingClusterReco as ImagingClusterReco
0195 
0196 from Configurables import Jug__Reco__PhotoMultiplierReco as PhotoMultiplierReco
0197 from Configurables import Jug__Reco__PhotoRingClusters as PhotoRingClusters
0198 
0199 from Configurables import Jug__Reco__ParticleCollector as ParticleCollector
0200 
0201 # branches needed from simulation root file
0202 sim_coll = [
0203     "MCParticles",
0204     "B0TrackerHits",
0205     "EcalEndcapNHits",
0206     "EcalEndcapNHitsContributions",
0207     "EcalEndcapPHits",
0208     "EcalEndcapPHitsContributions",
0209     "HcalBarrelHits",
0210     "HcalBarrelHitsContributions",
0211     "HcalEndcapPHits",
0212     "HcalEndcapPHitsContributions",
0213     "HcalEndcapNHits",
0214     "HcalEndcapNHitsContributions",
0215     "DRICHHits",
0216     "ZDCEcalHits",
0217     "ZDCEcalHitsContributions",
0218     "ZDCHcalHits",
0219     "ZDCHcalHitsContributions",
0220 ]
0221 ecal_barrel_imaging_collections = [
0222     "EcalBarrelImagingHits",
0223     "EcalBarrelImagingHitsContributions",
0224     "EcalBarrelScFiHits",
0225     "EcalBarrelScFiHitsContributions",
0226 ]
0227 ecal_barrel_sciglass_collections = [
0228     "EcalBarrelSciGlassHits",
0229     "EcalBarrelSciGlassHitsContributions",
0230 ]
0231 if has_ecal_barrel_imaging:
0232     sim_coll += ecal_barrel_imaging_collections
0233 else:
0234     sim_coll += ecal_barrel_sciglass_collections
0235 
0236 forward_romanpot_collections = [
0237     "ForwardRomanPotHits",
0238 ]
0239 forward_offmtracker_collections = [
0240     "ForwardOffMTrackerHits",
0241 ]
0242 sim_coll += forward_romanpot_collections + forward_offmtracker_collections
0243 
0244 tracker_endcap_collections = [
0245     "TrackerEndcapHits",
0246 ]
0247 tracker_barrel_collections = [
0248     "SiBarrelHits",
0249 ]
0250 vertex_barrel_collections = [
0251     "VertexBarrelHits",
0252 ]
0253 mpgd_barrel_collections = [
0254     "MPGDBarrelHits",
0255 ]
0256 
0257 sim_coll += (
0258     tracker_endcap_collections
0259     + tracker_barrel_collections
0260     + vertex_barrel_collections
0261     + mpgd_barrel_collections
0262 )
0263 
0264 if has_pid_backward_pfrich:
0265     sim_coll.append("PFRICHHits")
0266 else:
0267     sim_coll.append("MRICHHits")
0268 
0269 # list of algorithms
0270 algorithms = []
0271 
0272 # input
0273 podin = PodioInput("PodioReader", collections=sim_coll)
0274 algorithms.append(podin)
0275 
0276 # Generated particles
0277 dummy = MC2DummyParticle(
0278     "dummy",
0279     inputParticles="MCParticles",
0280     outputParticles="GeneratedParticles",
0281     smearing=0,
0282 )
0283 algorithms.append(dummy)
0284 
0285 # Truth level kinematics
0286 truth_incl_kin = InclusiveKinematicsTruth(
0287     "truth_incl_kin",
0288     inputMCParticles="MCParticles",
0289     outputInclusiveKinematics="InclusiveKinematicsTruth",
0290 )
0291 algorithms.append(truth_incl_kin)
0292 
0293 ## Roman pots
0294 ffi_romanpot_coll = SimTrackerHitsCollector(
0295     "ffi_romanpot_coll",
0296     inputSimTrackerHits=forward_romanpot_collections,
0297     outputSimTrackerHits="ForwardRomanPotAllHits",
0298 )
0299 algorithms.append(ffi_romanpot_coll)
0300 ffi_romanpot_digi = TrackerDigi(
0301     "ffi_romanpot_digi",
0302     inputHitCollection=ffi_romanpot_coll.outputSimTrackerHits,
0303     outputHitCollection="ForwardRomanPotRawHits",
0304     timeResolution=8,
0305 )
0306 algorithms.append(ffi_romanpot_digi)
0307 
0308 ffi_romanpot_reco = TrackerHitReconstruction(
0309     "ffi_romanpot_reco",
0310     inputHitCollection=ffi_romanpot_digi.outputHitCollection,
0311     outputHitCollection="ForwardRomanPotRecHits",
0312 )
0313 algorithms.append(ffi_romanpot_reco)
0314 
0315 ffi_romanpot_parts = FarForwardParticles(
0316     "ffi_romanpot_parts",
0317     inputCollection=ffi_romanpot_reco.outputHitCollection,
0318     outputCollection="ForwardRomanPotParticles",
0319 )
0320 algorithms.append(ffi_romanpot_parts)
0321 
0322 ## Off momentum tracker
0323 ffi_offmtracker_coll = SimTrackerHitsCollector(
0324     "ffi_offmtracker_coll",
0325     inputSimTrackerHits=forward_offmtracker_collections,
0326     outputSimTrackerHits="ForwardOffMTrackerAllHits",
0327 )
0328 algorithms.append(ffi_offmtracker_coll)
0329 ffi_offmtracker_digi = TrackerDigi(
0330     "ffi_offmtracker_digi",
0331     inputHitCollection=ffi_offmtracker_coll.outputSimTrackerHits,
0332     outputHitCollection="ForwardOffMTrackerRawHits",
0333     timeResolution=8,
0334 )
0335 algorithms.append(ffi_offmtracker_digi)
0336 
0337 ffi_offmtracker_reco = TrackerHitReconstruction(
0338     "ffi_offmtracker_reco",
0339     inputHitCollection=ffi_offmtracker_digi.outputHitCollection,
0340     outputHitCollection="ForwardOffMTrackerRecHits",
0341 )
0342 algorithms.append(ffi_offmtracker_reco)
0343 
0344 ffi_offmtracker_parts = FarForwardParticles(
0345     "ffi_offmtracker_parts",
0346     inputCollection=ffi_offmtracker_reco.outputHitCollection,
0347     outputCollection="ForwardOffMTrackerParticles",
0348 )
0349 algorithms.append(ffi_offmtracker_parts)
0350 
0351 ## B0 tracker
0352 trk_b0_digi = TrackerDigi(
0353     "trk_b0_digi",
0354     inputHitCollection="B0TrackerHits",
0355     outputHitCollection="B0TrackerRawHits",
0356     timeResolution=8,
0357 )
0358 algorithms.append(trk_b0_digi)
0359 
0360 trk_b0_reco = TrackerHitReconstruction(
0361     "trk_b0_reco",
0362     inputHitCollection=trk_b0_digi.outputHitCollection,
0363     outputHitCollection="B0TrackerRecHits",
0364 )
0365 algorithms.append(trk_b0_reco)
0366 
0367 # ZDC ECAL WSciFi
0368 ffi_zdc_ecal_digi = CalHitDigi(
0369     "ffi_zdc_ecal_digi",
0370     inputHitCollection="ZDCEcalHits",
0371     outputHitCollection="ZDCEcalRawHits",
0372 )
0373 algorithms.append(ffi_zdc_ecal_digi)
0374 
0375 ffi_zdc_ecal_reco = CalHitReco(
0376     "ffi_zdc_ecal_reco",
0377     inputHitCollection=ffi_zdc_ecal_digi.outputHitCollection,
0378     outputHitCollection="ZDCEcalRecHits",
0379     readoutClass="ZDCEcalHits",
0380     localDetFields=["system"],
0381 )
0382 algorithms.append(ffi_zdc_ecal_reco)
0383 
0384 ffi_zdc_ecal_cl = IslandCluster(
0385     "ffi_zdc_ecal_cl",
0386     inputHitCollection=ffi_zdc_ecal_reco.outputHitCollection,
0387     outputProtoClusterCollection="ZDCEcalProtoClusters",
0388     **ffi_zdc_ecal_cl_kwargs,
0389 )
0390 algorithms.append(ffi_zdc_ecal_cl)
0391 
0392 ffi_zdc_ecal_clreco = RecoCoG(
0393     "ffi_zdc_ecal_clreco",
0394     mcHits=ffi_zdc_ecal_digi.inputHitCollection,
0395     inputProtoClusterCollection=ffi_zdc_ecal_cl.outputProtoClusterCollection,
0396     outputClusterCollection="ZDCEcalClusters",
0397     outputAssociations="ZDCEcalClusterAssociations",
0398     logWeightBase=3.6,
0399     samplingFraction=ffi_zdc_ecal_sf,
0400 )
0401 algorithms.append(ffi_zdc_ecal_clreco)
0402 
0403 # ZDC HCAL PbSciFi
0404 ffi_zdc_hcal_digi = CalHitDigi(
0405     "ffi_zdc_hcal_digi",
0406     inputHitCollection="ZDCHcalHits",
0407     outputHitCollection="ZDCHcalRawHits",
0408 )
0409 algorithms.append(ffi_zdc_hcal_digi)
0410 
0411 ffi_zdc_hcal_reco = CalHitReco(
0412     "ffi_zdc_hcal_reco",
0413     inputHitCollection=ffi_zdc_hcal_digi.outputHitCollection,
0414     outputHitCollection="ZDCHcalRecHits",
0415     readoutClass="ZDCHcalHits",
0416     localDetFields=["system"],
0417 )
0418 algorithms.append(ffi_zdc_hcal_reco)
0419 
0420 ffi_zdc_hcal_cl = IslandCluster(
0421     "ffi_zdc_hcal_cl",
0422     inputHitCollection=ffi_zdc_hcal_reco.outputHitCollection,
0423     outputProtoClusterCollection="ZDCHcalProtoClusters",
0424     **ffi_zdc_hcal_cl_kwargs,
0425 )
0426 algorithms.append(ffi_zdc_hcal_cl)
0427 
0428 ffi_zdc_hcal_clreco = RecoCoG(
0429     "ffi_zdc_hcal_clreco",
0430     mcHits=ffi_zdc_hcal_digi.inputHitCollection,
0431     inputProtoClusterCollection=ffi_zdc_hcal_cl.outputProtoClusterCollection,
0432     outputClusterCollection="ZDCHcalClusters",
0433     outputAssociations="ZDCHcalClusterAssociations",
0434     logWeightBase=3.6,
0435     samplingFraction=ffi_zdc_hcal_sf,
0436 )
0437 algorithms.append(ffi_zdc_hcal_clreco)
0438 
0439 # Crystal Endcap Ecal
0440 ce_ecal_daq = calo_daq["ecal_neg_endcap"]
0441 ce_ecal_digi = CalHitDigi(
0442     "ce_ecal_digi",
0443     inputHitCollection="EcalEndcapNHits",
0444     outputHitCollection="EcalEndcapNRawHits",
0445     energyResolutions=[0.0, 0.02, 0.0],
0446     **ce_ecal_daq,
0447 )
0448 algorithms.append(ce_ecal_digi)
0449 
0450 ce_ecal_reco = CalHitReco(
0451     "ce_ecal_reco",
0452     inputHitCollection=ce_ecal_digi.outputHitCollection,
0453     outputHitCollection="EcalEndcapNRecHits",
0454     thresholdFactor=4,  # 4 sigma cut on pedestal sigma
0455     samplingFraction=0.998,  # this accounts for a small fraction of leakage
0456     readoutClass="EcalEndcapNHits",
0457     sectorField="sector",
0458     **ce_ecal_daq,
0459 )
0460 algorithms.append(ce_ecal_reco)
0461 
0462 ce_ecal_cl = TruthClustering(
0463     "ce_ecal_cl",
0464     mcHits="EcalEndcapNHits",
0465     inputHits=ce_ecal_reco.outputHitCollection,
0466     outputProtoClusters="EcalEndcapNTruthProtoClusters",
0467 )
0468 algorithms.append(ce_ecal_cl)
0469 
0470 ce_ecal_cl_island = IslandCluster(
0471     "ce_ecal_cl_island",
0472     inputHitCollection=ce_ecal_reco.outputHitCollection,
0473     outputProtoClusterCollection="EcalEndcapNIslandProtoClusters",
0474     splitCluster=False,
0475     minClusterHitEdep=1.0 * MeV,  # discard low energy hits
0476     minClusterCenterEdep=30 * MeV,
0477     sectorDist=5.0 * cm,
0478     dimScaledLocalDistXY=[1.8, 1.8],
0479 )  # dimension scaled dist is good for hybrid sectors with different module size
0480 algorithms.append(ce_ecal_cl_island)
0481 
0482 ce_ecal_clreco = RecoCoG(
0483     "ce_ecal_clreco",
0484     mcHits="EcalEndcapNHits",  # to create truth associations
0485     inputProtoClusterCollection=ce_ecal_cl.outputProtoClusters,
0486     outputClusterCollection="EcalEndcapNClusters",
0487     outputAssociations="EcalEndcapNClusterAssociations",
0488     logWeightBase=4.6,
0489 )
0490 algorithms.append(ce_ecal_clreco)
0491 
0492 ce_ecal_clmerger = ClusterMerger(
0493     "ce_ecal_clmerger",
0494     inputClusters=ce_ecal_clreco.outputClusterCollection,
0495     inputAssociations=ce_ecal_clreco.outputAssociations,
0496     outputClusters="EcalEndcapNMergedClusters",
0497     outputAssociations="EcalEndcapNMergedClusterAssociations",
0498 )
0499 algorithms.append(ce_ecal_clmerger)
0500 
0501 # Endcap ScFi Ecal (homogeneous approximation)
0502 ci_ecal_daq = calo_daq["ecal_pos_endcap"]
0503 
0504 ci_ecal_digi = CalHitDigi(
0505     "ci_ecal_digi",
0506     inputHitCollection="EcalEndcapPHits",
0507     outputHitCollection="EcalEndcapPRawHits",
0508     scaleResponse=ci_ecal_sf,
0509     energyResolutions=[0.00316, 0.0015, 0.0],
0510     threshold=5.0 * MeV,
0511     **ci_ecal_daq,
0512 )
0513 algorithms.append(ci_ecal_digi)
0514 
0515 ci_ecal_reco = CalHitReco(
0516     "ci_ecal_reco",
0517     inputHitCollection=ci_ecal_digi.outputHitCollection,
0518     outputHitCollection="EcalEndcapPRecHits",
0519     thresholdFactor=5.0,
0520     samplingFraction=ci_ecal_sf,
0521     **ci_ecal_daq,
0522 )
0523 algorithms.append(ci_ecal_reco)
0524 
0525 # merge hits in different layer (projection to local x-y plane)
0526 ci_ecal_merger = CalHitsMerger(
0527     "ci_ecal_merger",
0528     inputHitCollection=ci_ecal_reco.outputHitCollection,
0529     outputHitCollection="EcalEndcapPRecMergedHits",
0530     fields=["fiber_x", "fiber_y"],
0531     fieldRefNumbers=[1, 1],
0532     # fields = ["layer", "slice"],
0533     # fieldRefNumbers = [1, 0],
0534     readoutClass="EcalEndcapPHits",
0535 )
0536 algorithms.append(ci_ecal_merger)
0537 
0538 ci_ecal_cl = TruthClustering(
0539     "ci_ecal_cl",
0540     mcHits="EcalEndcapPHits",
0541     inputHits=ci_ecal_reco.outputHitCollection,
0542     outputProtoClusters="EcalEndcapPTruthProtoClusters",
0543 )
0544 algorithms.append(ci_ecal_cl)
0545 
0546 ci_ecal_cl_island = IslandCluster(
0547     "ci_ecal_cl_island",
0548     inputHitCollection=ci_ecal_merger.outputHitCollection,
0549     outputProtoClusterCollection="EcalEndcapPIslandProtoClusters",
0550     splitCluster=False,
0551     minClusterCenterEdep=10.0 * MeV,
0552     localDistXY=[10 * mm, 10 * mm],
0553 )
0554 algorithms.append(ci_ecal_cl_island)
0555 
0556 ci_ecal_clreco = RecoCoG(
0557     "ci_ecal_clreco",
0558     mcHits=ci_ecal_cl.mcHits,
0559     inputProtoClusterCollection=ci_ecal_cl.outputProtoClusters,
0560     outputClusterCollection="EcalEndcapPClusters",
0561     outputAssociations="EcalEndcapPClusterAssociations",
0562     enableEtaBounds=True,
0563     logWeightBase=6.2,
0564 )
0565 algorithms.append(ci_ecal_clreco)
0566 
0567 ci_ecal_clmerger = ClusterMerger(
0568     "ci_ecal_clmerger",
0569     inputClusters=ci_ecal_clreco.outputClusterCollection,
0570     inputAssociations=ci_ecal_clreco.outputAssociations,
0571     outputClusters="EcalEndcapPMergedClusters",
0572     outputAssociations="EcalEndcapPMergedClusterAssociations",
0573 )
0574 algorithms.append(ci_ecal_clmerger)
0575 
0576 # Central Barrel Ecal
0577 if has_ecal_barrel_imaging:
0578     # Central ECAL Imaging Calorimeter
0579     img_barrel_daq = calo_daq["ecal_barrel_imaging"]
0580 
0581     img_barrel_digi = CalHitDigi(
0582         "img_barrel_digi",
0583         inputHitCollection="EcalBarrelImagingHits",
0584         outputHitCollection="EcalBarrelImagingRawHits",
0585         energyResolutions=[0.0, 0.02, 0.0],  # 2% flat resolution
0586         **img_barrel_daq,
0587     )
0588     algorithms.append(img_barrel_digi)
0589 
0590     img_barrel_reco = ImCalPixelReco(
0591         "img_barrel_reco",
0592         inputHitCollection=img_barrel_digi.outputHitCollection,
0593         outputHitCollection="EcalBarrelImagingRecHits",
0594         thresholdFactor=3,  # about 20 keV
0595         samplingFraction=img_barrel_sf,
0596         readoutClass="EcalBarrelImagingHits",  # readout class
0597         layerField="layer",  # field to get layer id
0598         sectorField="sector",  # field to get sector id
0599         **img_barrel_daq,
0600     )
0601     algorithms.append(img_barrel_reco)
0602 
0603     img_barrel_cl = ImagingCluster(
0604         "img_barrel_cl",
0605         inputHitCollection=img_barrel_reco.outputHitCollection,
0606         outputProtoClusterCollection="EcalBarrelImagingProtoClusters",
0607         localDistXY=[2.0 * mm, 2 * mm],  # same layer
0608         layerDistEtaPhi=[10 * mrad, 10 * mrad],  # adjacent layer
0609         neighbourLayersRange=2,  # id diff for adjacent layer
0610         sectorDist=3.0 * cm,
0611     )  # different sector
0612     algorithms.append(img_barrel_cl)
0613 
0614     img_barrel_clreco = ImagingClusterReco(
0615         "img_barrel_clreco",
0616         mcHits=img_barrel_digi.inputHitCollection,
0617         inputProtoClusters=img_barrel_cl.outputProtoClusterCollection,
0618         outputLayers="EcalBarrelImagingLayers",
0619         outputClusters="EcalBarrelImagingClusters",
0620         outputAssociations="EcalBarrelImagingClusterAssociations",
0621     )
0622     algorithms.append(img_barrel_clreco)
0623 
0624     # Central ECAL SciFi
0625     scfi_barrel_daq = calo_daq["ecal_barrel_scfi"]
0626 
0627     scfi_barrel_digi = CalHitDigi(
0628         "scfi_barrel_digi",
0629         inputHitCollection="EcalBarrelScFiHits",
0630         outputHitCollection="EcalBarrelScFiRawHits",
0631         **scfi_barrel_daq,
0632     )
0633     algorithms.append(scfi_barrel_digi)
0634 
0635     scfi_barrel_reco = CalHitReco(
0636         "scfi_barrel_reco",
0637         inputHitCollection=scfi_barrel_digi.outputHitCollection,
0638         outputHitCollection="EcalBarrelScFiRecHits",
0639         thresholdFactor=5.0,
0640         samplingFraction=scifi_barrel_sf,
0641         readoutClass="EcalBarrelScFiHits",
0642         layerField="layer",
0643         sectorField="sector",
0644         localDetFields=[
0645             "system",
0646             "sector",
0647         ],  # use local coordinates in each sector
0648         **scfi_barrel_daq,
0649     )
0650     algorithms.append(scfi_barrel_reco)
0651 
0652     # merge hits in different layer (projection to local x-y plane)
0653     scfi_barrel_merger = CalHitsMerger(
0654         "scfi_barrel_merger",
0655         inputHitCollection=scfi_barrel_reco.outputHitCollection,
0656         outputHitCollection="EcalBarrelScFiMergedHits",
0657         fields=["fiber"],
0658         fieldRefNumbers=[1],
0659         readoutClass="EcalBarrelScFiHits",
0660     )
0661     algorithms.append(scfi_barrel_merger)
0662 
0663     scfi_barrel_cl = IslandCluster(
0664         "scfi_barrel_cl",
0665         inputHitCollection=scfi_barrel_merger.outputHitCollection,
0666         outputProtoClusterCollection="EcalBarrelScFiProtoClusters",
0667         splitCluster=False,
0668         minClusterCenterEdep=10.0 * MeV,
0669         localDistXZ=[30 * mm, 30 * mm],
0670     )
0671     algorithms.append(scfi_barrel_cl)
0672 
0673     scfi_barrel_clreco = RecoCoG(
0674         "scfi_barrel_clreco",
0675         mcHits=scfi_barrel_digi.inputHitCollection,
0676         inputProtoClusterCollection=scfi_barrel_cl.outputProtoClusterCollection,
0677         outputClusterCollection="EcalBarrelScFiClusters",
0678         outputAssociations="EcalBarrelScFiClusterAssociations",
0679         logWeightBase=6.2,
0680     )
0681     algorithms.append(scfi_barrel_clreco)
0682 
0683     ## barrel cluster merger
0684     barrel_clus_merger = EnergyPositionClusterMerger(
0685         "barrel_clus_merger",
0686         inputMCParticles="MCParticles",
0687         inputEnergyClusters=scfi_barrel_clreco.outputClusterCollection,
0688         inputEnergyAssociations=scfi_barrel_clreco.outputAssociations,
0689         inputPositionClusters=img_barrel_clreco.outputClusters,
0690         inputPositionAssociations=img_barrel_clreco.outputAssociations,
0691         outputClusters="EcalBarrelMergedClusters",
0692         outputAssociations="EcalBarrelMergedClusterAssociations",
0693     )
0694     algorithms.append(barrel_clus_merger)
0695 
0696 else:
0697     # SciGlass calorimeter
0698     sciglass_ecal_daq = dict(
0699         dynamicRangeADC=5.0 * GeV, capacityADC=32768, pedestalMean=400, pedestalSigma=3
0700     )
0701 
0702     sciglass_ecal_digi = CalHitDigi(
0703         "sciglass_ecal_digi",
0704         inputHitCollection="EcalBarrelSciGlassHits",
0705         outputHitCollection="EcalBarrelSciGlassHitsDigi",
0706         energyResolutions=[0.0, 0.02, 0.0],  # 2% flat resolution
0707         **sciglass_ecal_daq,
0708     )
0709     algorithms.append(sciglass_ecal_digi)
0710 
0711     sciglass_ecal_reco = CalHitReco(
0712         "sciglass_ecal_reco",
0713         inputHitCollection=sciglass_ecal_digi.outputHitCollection,
0714         outputHitCollection="EcalBarrelSciGlassHitsReco",
0715         thresholdFactor=3,  # about 20 keV
0716         readoutClass="EcalBarrelSciGlassHits",  # readout class
0717         sectorField="sector",  # field to get sector id
0718         samplingFraction=0.998,  # this accounts for a small fraction of leakage
0719         **sciglass_ecal_daq,
0720     )
0721     algorithms.append(sciglass_ecal_reco)
0722 
0723     sciglass_ecal_cl = TruthClustering(
0724         "sciglass_ecal_cl",
0725         mcHits="EcalBarrelSciGlassHits",
0726         inputHits=sciglass_ecal_reco.outputHitCollection,
0727         outputProtoClusters="EcalBarrelTruthProtoClusters",
0728     )
0729     algorithms.append(sciglass_ecal_cl)
0730 
0731     sciglass_ecal_cl_island = IslandCluster(
0732         "sciglass_ecal_cl_island",
0733         inputHitCollection=sciglass_ecal_reco.outputHitCollection,
0734         outputProtoClusterCollection="EcalBarrelIslandProtoClusters",
0735         splitCluster=False,
0736         minClusterHitEdep=1.0 * MeV,  # discard low energy hits
0737         minClusterCenterEdep=30 * MeV,
0738         sectorDist=5.0 * cm,
0739     )
0740     algorithms.append(sciglass_ecal_cl_island)
0741 
0742     sciglass_ecal_clreco = RecoCoG(
0743         "sciglass_ecal_clreco",
0744         mcHits="EcalBarrelSciGlassHits",
0745         inputProtoClusterCollection=sciglass_ecal_cl.outputProtoClusters,
0746         outputClusterCollection="EcalBarrelClusters",
0747         outputAssociations="EcalBarrelClusterAssociations",
0748         enableEtaBounds=True,
0749         logWeightBase=6.2,
0750     )
0751     algorithms.append(sciglass_ecal_clreco)
0752 
0753     barrel_clus_merger = ClusterMerger(
0754         "barrel_clus_merger",
0755         inputClusters=sciglass_ecal_clreco.outputClusterCollection,
0756         inputAssociations=sciglass_ecal_clreco.outputAssociations,
0757         outputClusters="EcalBarrelMergedClusters",
0758         outputAssociations="EcalBarrelMergedClusterAssociations",
0759     )
0760     algorithms.append(barrel_clus_merger)
0761 
0762 # Central Barrel Hcal
0763 cb_hcal_daq = calo_daq["hcal_barrel"]
0764 
0765 cb_hcal_digi = CalHitDigi(
0766     "cb_hcal_digi",
0767     inputHitCollection="HcalBarrelHits",
0768     outputHitCollection="HcalBarrelRawHits",
0769     **cb_hcal_daq,
0770 )
0771 algorithms.append(cb_hcal_digi)
0772 
0773 cb_hcal_reco = CalHitReco(
0774     "cb_hcal_reco",
0775     inputHitCollection=cb_hcal_digi.outputHitCollection,
0776     outputHitCollection="HcalBarrelRecHits",
0777     thresholdFactor=5.0,
0778     samplingFraction=cb_hcal_sf,
0779     readoutClass="HcalBarrelHits",
0780     sectorField="sector",
0781     **cb_hcal_daq,
0782 )
0783 algorithms.append(cb_hcal_reco)
0784 
0785 cb_hcal_merger = CalHitsMerger(
0786     "cb_hcal_merger",
0787     inputHitCollection=cb_hcal_reco.outputHitCollection,
0788     outputHitCollection="HcalBarrelMergedHits",
0789     readoutClass="HcalBarrelHits",
0790     fields=["tile"],
0791     fieldRefNumbers=[0],
0792 )
0793 algorithms.append(cb_hcal_merger)
0794 
0795 cb_hcal_cl = IslandCluster(
0796     "cb_hcal_cl",
0797     inputHitCollection=cb_hcal_merger.outputHitCollection,
0798     outputProtoClusterCollection="HcalBarrelProtoClusters",
0799     splitCluster=False,
0800     minClusterCenterEdep=30.0 * MeV,
0801     localDistXY=[15.0 * cm, 15.0 * cm],
0802 )
0803 algorithms.append(cb_hcal_cl)
0804 
0805 cb_hcal_clreco = RecoCoG(
0806     "cb_hcal_clreco",
0807     mcHits=cb_hcal_digi.inputHitCollection,
0808     inputProtoClusterCollection=cb_hcal_cl.outputProtoClusterCollection,
0809     outputClusterCollection="HcalBarrelClusters",
0810     outputAssociations="HcalBarrelClusterAssociations",
0811     logWeightBase=6.2,
0812 )
0813 algorithms.append(cb_hcal_clreco)
0814 
0815 # Hcal Hadron Endcap
0816 ci_hcal_daq = calo_daq["hcal_pos_endcap"]
0817 
0818 ci_hcal_digi = CalHitDigi(
0819     "ci_hcal_digi",
0820     inputHitCollection="HcalEndcapPHits",
0821     outputHitCollection="HcalEndcapPRawHits",
0822     **ci_hcal_daq,
0823 )
0824 algorithms.append(ci_hcal_digi)
0825 
0826 ci_hcal_reco = CalHitReco(
0827     "ci_hcal_reco",
0828     inputHitCollection=ci_hcal_digi.outputHitCollection,
0829     outputHitCollection="HcalEndcapPRecHits",
0830     thresholdFactor=5.0,
0831     samplingFraction=ci_hcal_sf,
0832     **ci_hcal_daq,
0833 )
0834 algorithms.append(ci_hcal_reco)
0835 
0836 ci_hcal_merger = CalHitsMerger(
0837     "ci_hcal_merger",
0838     inputHitCollection=ci_hcal_reco.outputHitCollection,
0839     outputHitCollection="HcalEndcapPMergedHits",
0840     readoutClass="HcalEndcapPHits",
0841     fields=["layer", "slice"],
0842     fieldRefNumbers=[1, 0],
0843 )
0844 algorithms.append(ci_hcal_merger)
0845 
0846 ci_hcal_cl = IslandCluster(
0847     "ci_hcal_cl",
0848     inputHitCollection=ci_hcal_merger.outputHitCollection,
0849     outputProtoClusterCollection="HcalEndcapPProtoClusters",
0850     splitCluster=False,
0851     minClusterCenterEdep=30.0 * MeV,
0852     localDistXY=[15.0 * cm, 15.0 * cm],
0853 )
0854 algorithms.append(ci_hcal_cl)
0855 
0856 ci_hcal_clreco = RecoCoG(
0857     "ci_hcal_clreco",
0858     mcHits=ci_hcal_digi.inputHitCollection,
0859     inputProtoClusterCollection=ci_hcal_cl.outputProtoClusterCollection,
0860     outputClusterCollection="HcalEndcapPClusters",
0861     outputAssociations="HcalEndcapPClusterAssociations",
0862     logWeightBase=6.2,
0863 )
0864 algorithms.append(ci_hcal_clreco)
0865 
0866 # Hcal Electron Endcap
0867 ce_hcal_daq = calo_daq["hcal_neg_endcap"]
0868 
0869 ce_hcal_digi = CalHitDigi(
0870     "ce_hcal_digi",
0871     inputHitCollection="HcalEndcapNHits",
0872     outputHitCollection="HcalEndcapNRawHits",
0873     **ce_hcal_daq,
0874 )
0875 algorithms.append(ce_hcal_digi)
0876 
0877 ce_hcal_reco = CalHitReco(
0878     "ce_hcal_reco",
0879     inputHitCollection=ce_hcal_digi.outputHitCollection,
0880     outputHitCollection="HcalEndcapNRecHits",
0881     thresholdFactor=5.0,
0882     samplingFraction=ce_hcal_sf,
0883     **ce_hcal_daq,
0884 )
0885 algorithms.append(ce_hcal_reco)
0886 
0887 ce_hcal_merger = CalHitsMerger(
0888     "ce_hcal_merger",
0889     inputHitCollection=ce_hcal_reco.outputHitCollection,
0890     outputHitCollection="HcalEndcapNMergedHits",
0891     readoutClass="HcalEndcapNHits",
0892     fields=["layer", "slice"],
0893     fieldRefNumbers=[1, 0],
0894 )
0895 algorithms.append(ce_hcal_merger)
0896 
0897 ce_hcal_cl = IslandCluster(
0898     "ce_hcal_cl",
0899     inputHitCollection=ce_hcal_merger.outputHitCollection,
0900     outputProtoClusterCollection="HcalEndcapNProtoClusters",
0901     splitCluster=False,
0902     minClusterCenterEdep=30.0 * MeV,
0903     localDistXY=[15.0 * cm, 15.0 * cm],
0904 )
0905 algorithms.append(ce_hcal_cl)
0906 
0907 ce_hcal_clreco = RecoCoG(
0908     "ce_hcal_clreco",
0909     mcHits=ce_hcal_digi.inputHitCollection,
0910     inputProtoClusterCollection=ce_hcal_cl.outputProtoClusterCollection,
0911     outputClusterCollection="HcalEndcapNClusters",
0912     outputAssociations="HcalEndcapNClusterAssociations",
0913     logWeightBase=6.2,
0914 )
0915 algorithms.append(ce_hcal_clreco)
0916 
0917 # Tracking
0918 trk_b_coll = SimTrackerHitsCollector(
0919     "trk_b_coll",
0920     inputSimTrackerHits=tracker_barrel_collections,
0921     outputSimTrackerHits="TrackerBarrelAllHits",
0922 )
0923 algorithms.append(trk_b_coll)
0924 
0925 trk_b_digi = TrackerDigi(
0926     "trk_b_digi",
0927     inputHitCollection=trk_b_coll.outputSimTrackerHits,
0928     outputHitCollection="TrackerBarrelRawHits",
0929     timeResolution=8,
0930 )
0931 algorithms.append(trk_b_digi)
0932 
0933 trk_ec_coll = SimTrackerHitsCollector(
0934     "trk_ec_coll",
0935     inputSimTrackerHits=tracker_endcap_collections,
0936     outputSimTrackerHits="TrackerEndcapAllHits",
0937 )
0938 algorithms.append(trk_ec_coll)
0939 
0940 trk_ec_digi = TrackerDigi(
0941     "trk_ec_digi",
0942     inputHitCollection=trk_ec_coll.outputSimTrackerHits,
0943     outputHitCollection="TrackerEndcapRawHits",
0944     timeResolution=8,
0945 )
0946 algorithms.append(trk_ec_digi)
0947 
0948 vtx_b_coll = SimTrackerHitsCollector(
0949     "vtx_b_coll",
0950     inputSimTrackerHits=vertex_barrel_collections,
0951     outputSimTrackerHits="VertexBarrelAllHits",
0952 )
0953 algorithms.append(vtx_b_coll)
0954 
0955 vtx_b_digi = TrackerDigi(
0956     "vtx_b_digi",
0957     inputHitCollection=vtx_b_coll.outputSimTrackerHits,
0958     outputHitCollection="VertexBarrelRawHits",
0959     timeResolution=8,
0960 )
0961 algorithms.append(vtx_b_digi)
0962 
0963 mpgd_b_coll = SimTrackerHitsCollector(
0964     "mpgd_b_coll",
0965     inputSimTrackerHits=mpgd_barrel_collections,
0966     outputSimTrackerHits="MPGDTrackerBarrelAllHits",
0967 )
0968 algorithms.append(mpgd_b_coll)
0969 
0970 mpgd_b_digi = TrackerDigi(
0971     "mpgd_b_digi",
0972     inputHitCollection=mpgd_b_coll.outputSimTrackerHits,
0973     outputHitCollection="MPGDTrackerBarrelRawHits",
0974     timeResolution=8,
0975 )
0976 algorithms.append(mpgd_b_digi)
0977 
0978 # Tracker and vertex reconstruction
0979 trk_b_reco = TrackerHitReconstruction(
0980     "trk_b_reco",
0981     inputHitCollection=trk_b_digi.outputHitCollection,
0982     outputHitCollection="TrackerBarrelRecHits",
0983 )
0984 algorithms.append(trk_b_reco)
0985 
0986 trk_ec_reco = TrackerHitReconstruction(
0987     "trk_ec_reco",
0988     inputHitCollection=trk_ec_digi.outputHitCollection,
0989     outputHitCollection="TrackerEndcapRecHits",
0990 )
0991 algorithms.append(trk_ec_reco)
0992 
0993 vtx_b_reco = TrackerHitReconstruction(
0994     "vtx_b_reco",
0995     inputHitCollection=vtx_b_digi.outputHitCollection,
0996     outputHitCollection="VertexBarrelRecHits",
0997 )
0998 algorithms.append(vtx_b_reco)
0999 
1000 mpgd_b_reco = TrackerHitReconstruction(
1001     "mpgd_b_reco",
1002     inputHitCollection=mpgd_b_digi.outputHitCollection,
1003     outputHitCollection="MPGDTrackerBarrelRecHits",
1004 )
1005 algorithms.append(mpgd_b_reco)
1006 
1007 input_tracking_hits = [
1008     str(trk_b_reco.outputHitCollection),
1009     str(trk_ec_reco.outputHitCollection),
1010     str(vtx_b_reco.outputHitCollection),
1011     str(mpgd_b_reco.outputHitCollection),
1012 ]
1013 
1014 trk_hit_col = TrackingHitsCollector(
1015     "trk_hit_col",
1016     inputTrackingHits=input_tracking_hits,
1017     trackingHits="trackingHits",
1018 )
1019 algorithms.append(trk_hit_col)
1020 
1021 # Hit Source linker
1022 sourcelinker = TrackerSourceLinker(
1023     "trk_srcslnkr",
1024     inputHitCollection=trk_hit_col.trackingHits,
1025     outputSourceLinks="TrackSourceLinks",
1026     outputMeasurements="TrackMeasurements",
1027 )
1028 algorithms.append(sourcelinker)
1029 
1030 ## Track param init
1031 truth_trk_init = TrackParamTruthInit(
1032     "truth_trk_init",
1033     inputMCParticles="MCParticles",
1034     outputInitialTrackParameters="InitTrackParams",
1035 )
1036 algorithms.append(truth_trk_init)
1037 
1038 # Tracking algorithms
1039 trk_find_alg = CKFTracking(
1040     "trk_find_alg",
1041     inputSourceLinks=sourcelinker.outputSourceLinks,
1042     inputMeasurements=sourcelinker.outputMeasurements,
1043     inputInitialTrackParameters=truth_trk_init.outputInitialTrackParameters,
1044     outputTrajectories="trajectories",
1045     chi2CutOff=[50.0],
1046 )
1047 algorithms.append(trk_find_alg)
1048 
1049 parts_from_fit = ParticlesFromTrackFit(
1050     "parts_from_fit",
1051     inputTrajectories=trk_find_alg.outputTrajectories,
1052     outputParticles="outputParticles",
1053     outputTrackParameters="outputTrackParameters",
1054 )
1055 algorithms.append(parts_from_fit)
1056 
1057 # trajs_from_fit = TrajectoryFromTrackFit("trajs_from_fit",
1058 #         inputTrajectories = trk_find_alg.outputTrajectories,
1059 #         outputTrajectoryParameters = "outputTrajectoryParameters")
1060 # algorithms.append(trajs_from_fit)
1061 
1062 # Event building
1063 parts_with_truth_pid = ParticlesWithTruthPID(
1064     "parts_with_truth_pid",
1065     inputMCParticles="MCParticles",
1066     inputTrackParameters=parts_from_fit.outputTrackParameters,
1067     outputParticles="ReconstructedChargedParticles",
1068     outputAssociations="ReconstructedChargedParticlesAssociations",
1069 )
1070 algorithms.append(parts_with_truth_pid)
1071 
1072 match_clusters = MatchClusters(
1073     "match_clusters",
1074     inputMCParticles="MCParticles",
1075     inputParticles=parts_with_truth_pid.outputParticles,
1076     inputParticlesAssoc=parts_with_truth_pid.outputAssociations,
1077     inputClusters=[
1078         str(ce_ecal_clmerger.outputClusters),
1079         str(barrel_clus_merger.outputClusters),
1080         str(ci_ecal_clmerger.outputClusters),
1081         str(ce_hcal_clreco.outputClusterCollection),
1082         str(cb_hcal_clreco.outputClusterCollection),
1083         str(ci_hcal_clreco.outputClusterCollection),
1084     ],
1085     inputClustersAssoc=[
1086         str(ce_ecal_clmerger.outputAssociations),
1087         str(barrel_clus_merger.outputAssociations),
1088         str(ci_ecal_clmerger.outputAssociations),
1089         str(ce_hcal_clreco.outputAssociations),
1090         str(cb_hcal_clreco.outputAssociations),
1091         str(ci_hcal_clreco.outputAssociations),
1092     ],
1093     outputParticles="ReconstructedParticles",
1094     outputParticlesAssoc="ReconstructedParticleAssociations",
1095 )
1096 algorithms.append(match_clusters)
1097 
1098 ## Far Forward for now stored separately
1099 fast_ff = FFSmearedParticles(
1100     "fast_ff",
1101     inputMCParticles="MCParticles",
1102     outputParticles="ReconstructedFFParticles",
1103     outputAssociations="ReconstructedFFParticlesAssociations",
1104     enableZDC=True,
1105     enableB0=True,
1106     enableRP=True,
1107     enableOMD=True,
1108     ionBeamEnergy=ionBeamEnergy,
1109     crossingAngle=-0.025,
1110 )
1111 algorithms.append(fast_ff)
1112 
1113 # DRICH
1114 drich_digi = PhotoMultiplierDigi(
1115     "drich_digi",
1116     inputHitCollection="DRICHHits",
1117     outputHitCollection="DRICHRawHits",
1118     quantumEfficiency=[(a * eV, b) for a, b in qe_data],
1119 )
1120 algorithms.append(drich_digi)
1121 
1122 drich_reco = PhotoMultiplierReco(
1123     "drich_reco",
1124     inputHitCollection=drich_digi.outputHitCollection,
1125     outputHitCollection="DRICHRecHits",
1126 )
1127 algorithms.append(drich_reco)
1128 
1129 # FIXME
1130 # drich_cluster = PhotoRingClusters("drich_cluster",
1131 #        inputHitCollection=pmtreco.outputHitCollection,
1132 #        #inputTrackCollection=parts_with_truth_pid.outputParticles,
1133 #        outputClusterCollection="ForwardRICHClusters")
1134 
1135 # PFRICH/MRICH
1136 if has_pid_backward_pfrich:
1137     pfrich_digi = PhotoMultiplierDigi(
1138         "pfrich_digi",
1139         inputHitCollection="PFRICHHits",
1140         outputHitCollection="PFRICHRawHits",
1141         quantumEfficiency=[(a * eV, b) for a, b in qe_data],
1142     )
1143     algorithms.append(pfrich_digi)
1144     pfrich_reco = PhotoMultiplierReco(
1145         "pfrich_reco",
1146         inputHitCollection=pfrich_digi.outputHitCollection,
1147         outputHitCollection="PFRICHRecHits",
1148     )
1149     algorithms.append(pfrich_reco)
1150 else:
1151     mrich_digi = PhotoMultiplierDigi(
1152         "mrich_digi",
1153         inputHitCollection="MRICHHits",
1154         outputHitCollection="MRICHRawHits",
1155         quantumEfficiency=[(a * eV, b) for a, b in qe_data],
1156     )
1157     algorithms.append(mrich_digi)
1158     mrich_reco = PhotoMultiplierReco(
1159         "mrich_reco",
1160         inputHitCollection=mrich_digi.outputHitCollection,
1161         outputHitCollection="MRICHRecHits",
1162     )
1163     algorithms.append(mrich_reco)
1164 
1165 # Inclusive kinematics
1166 incl_kin_electron = InclusiveKinematicsElectron(
1167     "incl_kin_electron",
1168     inputMCParticles="MCParticles",
1169     inputReconstructedParticles=parts_with_truth_pid.outputParticles,
1170     inputParticleAssociations=parts_with_truth_pid.outputAssociations,
1171     outputInclusiveKinematics="InclusiveKinematicsElectron",
1172 )
1173 algorithms.append(incl_kin_electron)
1174 incl_kin_jb = InclusiveKinematicsJB(
1175     "incl_kin_jb",
1176     inputMCParticles="MCParticles",
1177     inputReconstructedParticles=parts_with_truth_pid.outputParticles,
1178     inputParticleAssociations=parts_with_truth_pid.outputAssociations,
1179     outputInclusiveKinematics="InclusiveKinematicsJB",
1180 )
1181 algorithms.append(incl_kin_jb)
1182 incl_kin_da = InclusiveKinematicsDA(
1183     "incl_kin_da",
1184     inputMCParticles="MCParticles",
1185     inputReconstructedParticles=parts_with_truth_pid.outputParticles,
1186     inputParticleAssociations=parts_with_truth_pid.outputAssociations,
1187     outputInclusiveKinematics="InclusiveKinematicsDA",
1188 )
1189 algorithms.append(incl_kin_da)
1190 incl_kin_sigma = InclusiveKinematicsSigma(
1191     "incl_kin_sigma",
1192     inputMCParticles="MCParticles",
1193     inputReconstructedParticles=parts_with_truth_pid.outputParticles,
1194     inputParticleAssociations=parts_with_truth_pid.outputAssociations,
1195     outputInclusiveKinematics="InclusiveKinematicsSigma",
1196 )
1197 algorithms.append(incl_kin_sigma)
1198 incl_kin_esigma = InclusiveKinematicseSigma(
1199     "incl_kin_esigma",
1200     inputMCParticles="MCParticles",
1201     inputReconstructedParticles=parts_with_truth_pid.outputParticles,
1202     inputParticleAssociations=parts_with_truth_pid.outputAssociations,
1203     outputInclusiveKinematics="InclusiveKinematicseSigma",
1204 )
1205 algorithms.append(incl_kin_esigma)
1206 
1207 # Output
1208 podout = PodioOutput("out", filename=output_rec)
1209 podout.outputCommands = (
1210     [
1211         "keep *",
1212         "drop *Hits",
1213         "keep *Layers",
1214         "keep *Clusters",
1215         "drop *ProtoClusters",
1216         "drop outputParticles",
1217         "drop InitTrackParams",
1218     ]
1219     + ["drop " + c for c in sim_coll]
1220     + ["keep MCParticles"]
1221 )
1222 algorithms.append(podout)
1223 
1224 ApplicationMgr(
1225     TopAlg=algorithms,
1226     EvtSel="NONE",
1227     EvtMax=n_events,
1228     ExtSvc=services,
1229     OutputLevel=WARNING,
1230     AuditAlgorithms=True,
1231     HistogramPersistency="ROOT",
1232 )