Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-10-19 08:41:27

0001 // SPDX-License-Identifier: LGPL-3.0-or-later
0002 // Copyright (C) 2021 - 2025, Chao Peng, Sylvester Joosten, Whitney Armstrong, David Lawrence, Friederike Bock, Wouter Deconinck, Kolja Kauder, Sebouh Paul, Akio Ogawa
0003 
0004 #include <DD4hep/Detector.h>
0005 #include <Evaluator/DD4hepUnits.h>
0006 #include <JANA/JApplication.h>
0007 #include <JANA/JApplicationFwd.h>
0008 #include <JANA/Utils/JTypeInfo.h>
0009 #include <format>
0010 #include <spdlog/logger.h>
0011 #include <cmath>
0012 #include <gsl/pointers>
0013 #include <memory>
0014 #include <string>
0015 #include <variant>
0016 #include <vector>
0017 
0018 #include "algorithms/calorimetry/CalorimeterHitDigiConfig.h"
0019 #include "extensions/jana/JOmniFactoryGeneratorT.h"
0020 #include "factories/calorimetry/CalorimeterClusterRecoCoG_factory.h"
0021 #include "factories/calorimetry/CalorimeterClusterShape_factory.h"
0022 #include "factories/calorimetry/CalorimeterHitDigi_factory.h"
0023 #include "factories/calorimetry/CalorimeterHitReco_factory.h"
0024 #include "factories/calorimetry/CalorimeterIslandCluster_factory.h"
0025 #include "factories/calorimetry/CalorimeterTruthClustering_factory.h"
0026 #include "factories/calorimetry/TrackClusterMergeSplitter_factory.h"
0027 #include "services/geometry/dd4hep/DD4hep_service.h"
0028 #include "services/log/Log_service.h"
0029 
0030 extern "C" {
0031 void InitPlugin(JApplication* app) {
0032 
0033   using namespace eicrecon;
0034 
0035   InitJANAPlugin(app);
0036 
0037   const double logWeightBase = 3.6;
0038 
0039   auto log_service = app->GetService<Log_service>();
0040   auto mLog        = log_service->logger("FEMC");
0041 
0042   // Make sure digi and reco use the same value
0043   decltype(CalorimeterHitDigiConfig::capADC) EcalEndcapP_capADC =
0044       16384; //16384, assuming 14 bits. For approximate HGCROC resolution use 65536
0045   decltype(CalorimeterHitDigiConfig::dyRangeADC) EcalEndcapP_dyRangeADC   = 100 * dd4hep::GeV;
0046   decltype(CalorimeterHitDigiConfig::pedMeanADC) EcalEndcapP_pedMeanADC   = 200;
0047   decltype(CalorimeterHitDigiConfig::pedSigmaADC) EcalEndcapP_pedSigmaADC = 2.4576;
0048   decltype(CalorimeterHitDigiConfig::resolutionTDC) EcalEndcapP_resolutionTDC =
0049       10 * dd4hep::picosecond;
0050   const double EcalEndcapP_sampFrac = 0.029043; // updated with ratio to ScFi model
0051   decltype(CalorimeterHitDigiConfig::corrMeanScale) EcalEndcapP_corrMeanScale =
0052       std::format("{}", 1.0 / EcalEndcapP_sampFrac); //only used for ScFi model
0053   const double EcalEndcapP_nPhotonPerGeV          = 1500;
0054   const double EcalEndcapP_PhotonCollectionEff    = 0.285;
0055   const unsigned long long EcalEndcapP_totalPixel = 4 * 159565ULL;
0056 
0057   int EcalEndcapP_homogeneousFlag = 0;
0058   try {
0059     auto detector               = app->GetService<DD4hep_service>()->detector();
0060     EcalEndcapP_homogeneousFlag = detector->constant<int>("EcalEndcapP_Homogeneous_ScFi");
0061     if (EcalEndcapP_homogeneousFlag <= 1) {
0062       mLog->info("Homogeneous geometry loaded");
0063     } else {
0064       mLog->info("ScFi geometry loaded");
0065     }
0066   } catch (...) {
0067     // Variable not present apply legacy homogeneous geometry implementation
0068     EcalEndcapP_homogeneousFlag = 0;
0069   };
0070 
0071   if (EcalEndcapP_homogeneousFlag <= 1) {
0072     app->Add(new JOmniFactoryGeneratorT<CalorimeterHitDigi_factory>(
0073         "EcalEndcapPRawHits", {"EventHeader", "EcalEndcapPHits"},
0074         {"EcalEndcapPRawHits", "EcalEndcapPRawHitLinks", "EcalEndcapPRawHitAssociations"},
0075         {
0076             .eRes = {0.11333 * sqrt(dd4hep::GeV), 0.03,
0077                      0.0 * dd4hep::GeV}, // (11.333% / sqrt(E)) \oplus 3%
0078             .tRes = 0.0,
0079             .threshold =
0080                 0.0, // 15MeV threshold for a single tower will be applied on ADC at Reco below
0081             .readoutType = "sipm",
0082             .lightYield  = EcalEndcapP_nPhotonPerGeV / EcalEndcapP_PhotonCollectionEff,
0083             .photonDetectionEfficiency = EcalEndcapP_PhotonCollectionEff,
0084             .numEffectiveSipmPixels    = EcalEndcapP_totalPixel,
0085             .capADC                    = EcalEndcapP_capADC,
0086             .capTime                   = 100, // given in ns, 4 samples in HGCROC
0087             .dyRangeADC                = EcalEndcapP_dyRangeADC,
0088             .pedMeanADC                = EcalEndcapP_pedMeanADC,
0089             .pedSigmaADC               = EcalEndcapP_pedSigmaADC,
0090             .resolutionTDC             = EcalEndcapP_resolutionTDC,
0091             .corrMeanScale             = "1.0",
0092             .readout                   = "EcalEndcapPHits",
0093         },
0094         app // TODO: Remove me once fixed
0095         ));
0096   } else if (EcalEndcapP_homogeneousFlag == 2) {
0097     app->Add(new JOmniFactoryGeneratorT<CalorimeterHitDigi_factory>(
0098         "EcalEndcapPRawHits", {"EventHeader", "EcalEndcapPHits"},
0099         {"EcalEndcapPRawHits", "EcalEndcapPRawHitLinks", "EcalEndcapPRawHitAssociations"},
0100         {
0101             .eRes = {0.0, 0.022, 0.0}, // just constant term 2.2% based on MC data comparison
0102             .tRes = 0.0,
0103             .threshold =
0104                 0.0, // 15MeV threshold for a single tower will be applied on ADC at Reco below
0105             .readoutType = "sipm",
0106             .lightYield =
0107                 EcalEndcapP_nPhotonPerGeV / EcalEndcapP_PhotonCollectionEff / EcalEndcapP_sampFrac,
0108             .photonDetectionEfficiency = EcalEndcapP_PhotonCollectionEff,
0109             .numEffectiveSipmPixels    = EcalEndcapP_totalPixel,
0110             .capADC                    = EcalEndcapP_capADC,
0111             .capTime                   = 100, // given in ns, 4 samples in HGCROC
0112             .dyRangeADC                = EcalEndcapP_dyRangeADC,
0113             .pedMeanADC                = EcalEndcapP_pedMeanADC,
0114             .pedSigmaADC               = EcalEndcapP_pedSigmaADC,
0115             .resolutionTDC             = EcalEndcapP_resolutionTDC,
0116             .corrMeanScale             = EcalEndcapP_corrMeanScale,
0117             .readout                   = "EcalEndcapPHits",
0118             .fields                    = {"fiber_x", "fiber_y"},
0119         },
0120         app // TODO: Remove me once fixed
0121         ));
0122   }
0123 
0124   app->Add(new JOmniFactoryGeneratorT<CalorimeterHitReco_factory>(
0125       "EcalEndcapPRecHits", {"EcalEndcapPRawHits"}, {"EcalEndcapPRecHits"},
0126       {
0127           .capADC          = EcalEndcapP_capADC,
0128           .dyRangeADC      = EcalEndcapP_dyRangeADC,
0129           .pedMeanADC      = EcalEndcapP_pedMeanADC,
0130           .pedSigmaADC     = EcalEndcapP_pedSigmaADC,
0131           .resolutionTDC   = EcalEndcapP_resolutionTDC,
0132           .thresholdFactor = 0.0,
0133           .thresholdValue =
0134               3, // The ADC of a 15 MeV particle is adc = 200 + 15 * 0.03 * ( 1.0 + 0) / 3000 * 16384 = 200 + 2.4576
0135           // 15 MeV = 2.4576, but adc=llround(dE) and cut off is "<". So 3 here = 15.25MeV
0136           .sampFrac = "1.00", // already taken care in DIGI code above
0137           .readout  = "EcalEndcapPHits",
0138       },
0139       app // TODO: Remove me once fixed
0140       ));
0141   app->Add(new JOmniFactoryGeneratorT<CalorimeterTruthClustering_factory>(
0142       "EcalEndcapPTruthProtoClusters", {"EcalEndcapPRecHits", "EcalEndcapPRawHitLinks"},
0143       {"EcalEndcapPTruthProtoClusters"},
0144       app // TODO: Remove me once fixed
0145       ));
0146   app->Add(new JOmniFactoryGeneratorT<CalorimeterIslandCluster_factory>(
0147       "EcalEndcapPIslandProtoClusters", {"EcalEndcapPRecHits"}, {"EcalEndcapPIslandProtoClusters"},
0148       {.adjacencyMatrix{},
0149        .peakNeighbourhoodMatrix{},
0150        .readout{},
0151        .sectorDist = 5.0 * dd4hep::cm,
0152        .localDistXY{},
0153        .localDistXZ{},
0154        .localDistYZ{},
0155        .globalDistRPhi{},
0156        .globalDistEtaPhi{},
0157        .dimScaledLocalDistXY          = {1.5, 1.5},
0158        .splitCluster                  = false,
0159        .minClusterHitEdep             = 0.0 * dd4hep::MeV,
0160        .minClusterCenterEdep          = 60.0 * dd4hep::MeV,
0161        .transverseEnergyProfileMetric = "dimScaledLocalDistXY",
0162        .transverseEnergyProfileScale  = 1.,
0163        .transverseEnergyProfileScaleUnits{}},
0164       app // TODO: Remove me once fixed
0165       ));
0166 
0167   app->Add(new JOmniFactoryGeneratorT<CalorimeterClusterRecoCoG_factory>(
0168       "EcalEndcapPTruthClustersWithoutShapes",
0169       {
0170           "EcalEndcapPTruthProtoClusters", // edm4eic::ProtoClusterCollection
0171           "EcalEndcapPRawHitLinks",        // edm4eic::MCRecoCalorimeterHitLink
0172           "EcalEndcapPRawHitAssociations"  // edm4eic::MCRecoCalorimeterHitAssociationCollection
0173       },
0174       {"EcalEndcapPTruthClustersWithoutShapes", "EcalEndcapPTruthClusterLinksWithoutShapes",
0175        "EcalEndcapPTruthClusterAssociationsWithoutShapes"}, // edm4eic::MCRecoClusterParticleAssociation
0176       {.energyWeight    = "log",
0177        .sampFrac        = 1.0,
0178        .logWeightBase   = logWeightBase,
0179        .enableEtaBounds = true},
0180       app // TODO: Remove me once fixed
0181       ));
0182 
0183   app->Add(new JOmniFactoryGeneratorT<CalorimeterClusterShape_factory>(
0184       "EcalEndcapPTruthClusters",
0185       {"EcalEndcapPTruthClustersWithoutShapes", "EcalEndcapPTruthClusterLinksWithoutShapes"},
0186       {"EcalEndcapPTruthClusters", "EcalEndcapPTruthClusterLinks",
0187        "EcalEndcapPTruthClusterAssociations"},
0188       {.energyWeight = "log", .logWeightBase = logWeightBase}, app));
0189 
0190   app->Add(new JOmniFactoryGeneratorT<CalorimeterClusterRecoCoG_factory>(
0191       "EcalEndcapPClustersWithoutShapes",
0192       {
0193           "EcalEndcapPIslandProtoClusters", // edm4eic::ProtoClusterCollection
0194           "EcalEndcapPRawHitLinks",         // edm4eic::MCRecoCalorimeterHitLink
0195           "EcalEndcapPRawHitAssociations"   // edm4eic::MCRecoCalorimeterHitAssociationCollection
0196       },
0197       {"EcalEndcapPClustersWithoutShapes", "EcalEndcapPClusterLinksWithoutShapes",
0198        "EcalEndcapPClusterAssociationsWithoutShapes"}, // edm4eic::MCRecoClusterParticleAssociation
0199       {
0200           .energyWeight    = "log",
0201           .sampFrac        = 1.0,
0202           .logWeightBase   = logWeightBase,
0203           .enableEtaBounds = false,
0204       },
0205       app // TODO: Remove me once fixed
0206       ));
0207 
0208   app->Add(new JOmniFactoryGeneratorT<CalorimeterClusterShape_factory>(
0209       "EcalEndcapPClusters",
0210       {"EcalEndcapPClustersWithoutShapes", "EcalEndcapPClusterLinksWithoutShapes"},
0211       {"EcalEndcapPClusters", "EcalEndcapPClusterLinks", "EcalEndcapPClusterAssociations"},
0212       {.energyWeight = "log", .logWeightBase = logWeightBase}, app));
0213 
0214   app->Add(new JOmniFactoryGeneratorT<TrackClusterMergeSplitter_factory>(
0215       "EcalEndcapPSplitMergeProtoClusters",
0216       {"EcalEndcapPTrackClusterMatches", "EcalEndcapPClusters", "CalorimeterTrackProjections"},
0217       {"EcalEndcapPSplitMergeProtoClusters", "EcalEndcapPTrackSplitMergeProtoClusterLinks"},
0218       {.minSigCut                    = -2.0,
0219        .avgEP                        = 1.0,
0220        .sigEP                        = 0.10,
0221        .drAdd                        = 0.30,
0222        .surfaceToUse                 = 1,
0223        .transverseEnergyProfileScale = 1.0},
0224       app // TODO: remove me once fixed
0225       ));
0226 
0227   app->Add(new JOmniFactoryGeneratorT<CalorimeterClusterRecoCoG_factory>(
0228       "EcalEndcapPSplitMergeClustersWithoutShapes",
0229       {
0230           "EcalEndcapPSplitMergeProtoClusters", // edm4eic::ProtoClusterCollection
0231           "EcalEndcapPRawHitLinks",             // edm4eic::MCRecoCalorimeterHitLink
0232           "EcalEndcapPRawHitAssociations" // edm4hep::MCRecoCalorimeterHitAssociationCollection
0233       },
0234       {"EcalEndcapPSplitMergeClustersWithoutShapes",
0235        "EcalEndcapPSplitMergeClusterLinksWithoutShapes",
0236        "EcalEndcapPSplitMergeClusterAssociationsWithoutShapes"}, // edm4eic::MCRecoClusterParticleAssociation
0237       {
0238           .energyWeight    = "log",
0239           .sampFrac        = 1.0,
0240           .logWeightBase   = logWeightBase,
0241           .enableEtaBounds = false,
0242       },
0243       app // TODO: Remove me once fixed
0244       ));
0245 
0246   app->Add(new JOmniFactoryGeneratorT<CalorimeterClusterShape_factory>(
0247       "EcalEndcapPSplitMergeClusters",
0248       {"EcalEndcapPSplitMergeClustersWithoutShapes",
0249        "EcalEndcapPSplitMergeClusterLinksWithoutShapes"},
0250       {"EcalEndcapPSplitMergeClusters", "EcalEndcapPSplitMergeClusterLinks",
0251        "EcalEndcapPSplitMergeClusterAssociations"},
0252       {.energyWeight = "log", .logWeightBase = logWeightBase}, app));
0253 }
0254 }