Skip to content

Commit be68024

Browse files
akioogawapre-commit-ci[bot]veprblwdconincgithub-actions[bot]
authored
Update FEMC for new geometry: (#1848)
### Briefly, what does this PR introduce? Following Forward EM calorimeter geometry update: eic/epic#855 this provides switch between Homogeneous and ScFi geometry implementations based on xml file loaded - For Homogenous, we keep energy smearing as is. SF=1.0 - For ScFi, hits from fibers are summed to a tower and no enrgy smearing applied. SF=0.03. - Remove active insert which won't be built Added an option to put SiPM saturation to CalorimeterHitDigi - Specify 2 new parameters : totalPixel and nPhotonPerGeV - default for totalPixel is 0, which case no attenuation is applied - For FEMC for both geometry models, SiPM saturation is ON by default - Use "-PFEMC:SiPMSaturation=OFF" to turn it off See following links for some more details: https://www.star.bnl.gov/~akio/epic/geometry/index.html https://www.star.bnl.gov/~akio/epic/reco/index.html https://www.star.bnl.gov/~akio/epic/hadron/index.html ### What kind of change does this PR introduce? - [ ] Bug fix (issue #__) - [x] New feature (issue #__) - [ ] Documentation update - [ ] Other: __ ### Please check if this PR fulfills the following: - [ ] Tests for the changes have been added - [ ] Documentation has been added / updated - [ ] Changes have been communicated to collaborators ### Does this PR introduce breaking changes? What changes might users need to make to their code? I don't think so, unless one provides wrong config xml file (until sum check in place) ### Does this PR change default behavior? It does apply SiPM attenuation by default for FEMC (but not other calorimeters). --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Dmitry Kalinkin <[email protected]> Co-authored-by: Wouter Deconinck <[email protected]> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
1 parent cb9b56d commit be68024

File tree

1 file changed

+90
-24
lines changed

1 file changed

+90
-24
lines changed

src/detectors/FEMC/FEMC.cc

Lines changed: 90 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
// SPDX-License-Identifier: LGPL-3.0-or-later
2-
// Copyright (C) 2021 - 2025, Chao Peng, Sylvester Joosten, Whitney Armstrong, David Lawrence, Friederike Bock, Wouter Deconinck, Kolja Kauder, Sebouh Paul
2+
// Copyright (C) 2021 - 2025, Chao Peng, Sylvester Joosten, Whitney Armstrong, David Lawrence, Friederike Bock, Wouter Deconinck, Kolja Kauder, Sebouh Paul, Akio Ogawa
33

4+
#include <DD4hep/Detector.h>
45
#include <Evaluator/DD4hepUnits.h>
6+
#include <JANA/JApplication.h>
57
#include <JANA/JApplicationFwd.h>
68
#include <JANA/Utils/JTypeInfo.h>
9+
#include <fmt/core.h>
10+
#include <spdlog/logger.h>
711
#include <cmath>
12+
#include <gsl/pointers>
13+
#include <memory>
814
#include <string>
915
#include <variant>
1016
#include <vector>
@@ -18,41 +24,100 @@
1824
#include "factories/calorimetry/CalorimeterIslandCluster_factory.h"
1925
#include "factories/calorimetry/CalorimeterTruthClustering_factory.h"
2026
#include "factories/calorimetry/TrackClusterMergeSplitter_factory.h"
27+
#include "services/geometry/dd4hep/DD4hep_service.h"
28+
#include "services/log/Log_service.h"
2129

2230
extern "C" {
2331
void InitPlugin(JApplication* app) {
2432

2533
using namespace eicrecon;
2634

2735
InitJANAPlugin(app);
36+
37+
auto log_service = app->GetService<Log_service>();
38+
auto mLog = log_service->logger("FEMC");
39+
2840
// Make sure digi and reco use the same value
2941
decltype(CalorimeterHitDigiConfig::capADC) EcalEndcapP_capADC =
3042
16384; //16384, assuming 14 bits. For approximate HGCROC resolution use 65536
31-
decltype(CalorimeterHitDigiConfig::dyRangeADC) EcalEndcapP_dyRangeADC = 3 * dd4hep::GeV;
43+
decltype(CalorimeterHitDigiConfig::dyRangeADC) EcalEndcapP_dyRangeADC = 100 * dd4hep::GeV;
3244
decltype(CalorimeterHitDigiConfig::pedMeanADC) EcalEndcapP_pedMeanADC = 200;
3345
decltype(CalorimeterHitDigiConfig::pedSigmaADC) EcalEndcapP_pedSigmaADC = 2.4576;
3446
decltype(CalorimeterHitDigiConfig::resolutionTDC) EcalEndcapP_resolutionTDC =
3547
10 * dd4hep::picosecond;
36-
app->Add(new JOmniFactoryGeneratorT<CalorimeterHitDigi_factory>(
37-
"EcalEndcapPRawHits", {"EventHeader", "EcalEndcapPHits"},
38-
{"EcalEndcapPRawHits", "EcalEndcapPRawHitAssociations"},
39-
{
40-
.eRes = {0.11333 * sqrt(dd4hep::GeV), 0.03,
41-
0.0 * dd4hep::GeV}, // (11.333% / sqrt(E)) \oplus 3%
42-
.tRes = 0.0,
43-
.threshold = 0.0,
44-
// .threshold = 15 * dd4hep::MeV for a single tower, applied on ADC level
45-
.capADC = EcalEndcapP_capADC,
46-
.capTime = 100, // given in ns, 4 samples in HGCROC
47-
.dyRangeADC = EcalEndcapP_dyRangeADC,
48-
.pedMeanADC = EcalEndcapP_pedMeanADC,
49-
.pedSigmaADC = EcalEndcapP_pedSigmaADC,
50-
.resolutionTDC = EcalEndcapP_resolutionTDC,
51-
.corrMeanScale = "0.03",
52-
.readout = "EcalEndcapPHits",
53-
},
54-
app // TODO: Remove me once fixed
55-
));
48+
const double EcalEndcapP_sampFrac = 0.029043; // updated with ratio to ScFi model
49+
decltype(CalorimeterHitDigiConfig::corrMeanScale) EcalEndcapP_corrMeanScale =
50+
fmt::format("{}", 1.0 / EcalEndcapP_sampFrac);
51+
const double EcalEndcapP_nPhotonPerGeV = 1500;
52+
const double EcalEndcapP_PhotonCollectionEff = 0.285;
53+
const unsigned long long EcalEndcapP_totalPixel = 4 * 159565ULL;
54+
55+
int EcalEndcapP_homogeneousFlag = 0;
56+
try {
57+
auto detector = app->GetService<DD4hep_service>()->detector();
58+
EcalEndcapP_homogeneousFlag = detector->constant<int>("EcalEndcapP_Homogeneous_ScFi");
59+
if (EcalEndcapP_homogeneousFlag <= 1) {
60+
mLog->info("Homogeneous geometry loaded");
61+
} else {
62+
mLog->info("ScFi geometry loaded");
63+
}
64+
} catch (...) {
65+
// Variable not present apply legacy homogeneous geometry implementation
66+
EcalEndcapP_homogeneousFlag = 0;
67+
};
68+
69+
if (EcalEndcapP_homogeneousFlag <= 1) {
70+
app->Add(new JOmniFactoryGeneratorT<CalorimeterHitDigi_factory>(
71+
"EcalEndcapPRawHits", {"EventHeader", "EcalEndcapPHits"},
72+
{"EcalEndcapPRawHits", "EcalEndcapPRawHitAssociations"},
73+
{
74+
.eRes = {0.11333 * sqrt(dd4hep::GeV), 0.03,
75+
0.0 * dd4hep::GeV}, // (11.333% / sqrt(E)) \oplus 3%
76+
.tRes = 0.0,
77+
.threshold =
78+
0.0, // 15MeV threshold for a single tower will be applied on ADC at Reco below
79+
.readoutType = "sipm",
80+
.lightYield = EcalEndcapP_nPhotonPerGeV / EcalEndcapP_PhotonCollectionEff,
81+
.photonDetectionEfficiency = EcalEndcapP_PhotonCollectionEff,
82+
.numEffectiveSipmPixels = EcalEndcapP_totalPixel,
83+
.capADC = EcalEndcapP_capADC,
84+
.capTime = 100, // given in ns, 4 samples in HGCROC
85+
.dyRangeADC = EcalEndcapP_dyRangeADC,
86+
.pedMeanADC = EcalEndcapP_pedMeanADC,
87+
.pedSigmaADC = EcalEndcapP_pedSigmaADC,
88+
.resolutionTDC = EcalEndcapP_resolutionTDC,
89+
.corrMeanScale = "1.0",
90+
.readout = "EcalEndcapPHits",
91+
},
92+
app // TODO: Remove me once fixed
93+
));
94+
} else if (EcalEndcapP_homogeneousFlag == 2) {
95+
app->Add(new JOmniFactoryGeneratorT<CalorimeterHitDigi_factory>(
96+
"EcalEndcapPRawHits", {"EventHeader", "EcalEndcapPHits"},
97+
{"EcalEndcapPRawHits", "EcalEndcapPRawHitAssociations"},
98+
{
99+
.eRes = {0.0, 0.022, 0.0}, // just constant term 2.2% based on MC data comparison
100+
.tRes = 0.0,
101+
.threshold =
102+
0.0, // 15MeV threshold for a single tower will be applied on ADC at Reco below
103+
.readoutType = "sipm",
104+
.lightYield = EcalEndcapP_nPhotonPerGeV / EcalEndcapP_PhotonCollectionEff,
105+
.photonDetectionEfficiency = EcalEndcapP_PhotonCollectionEff,
106+
.numEffectiveSipmPixels = EcalEndcapP_totalPixel,
107+
.capADC = EcalEndcapP_capADC,
108+
.capTime = 100, // given in ns, 4 samples in HGCROC
109+
.dyRangeADC = EcalEndcapP_dyRangeADC,
110+
.pedMeanADC = EcalEndcapP_pedMeanADC,
111+
.pedSigmaADC = EcalEndcapP_pedSigmaADC,
112+
.resolutionTDC = EcalEndcapP_resolutionTDC,
113+
.corrMeanScale = EcalEndcapP_corrMeanScale,
114+
.readout = "EcalEndcapPHits",
115+
.fields = {"fiber_x", "fiber_y"},
116+
},
117+
app // TODO: Remove me once fixed
118+
));
119+
}
120+
56121
app->Add(new JOmniFactoryGeneratorT<CalorimeterHitReco_factory>(
57122
"EcalEndcapPRecHits", {"EcalEndcapPRawHits"}, {"EcalEndcapPRecHits"},
58123
{
@@ -63,8 +128,9 @@ void InitPlugin(JApplication* app) {
63128
.resolutionTDC = EcalEndcapP_resolutionTDC,
64129
.thresholdFactor = 0.0,
65130
.thresholdValue =
66-
2, // The ADC of a 15 MeV particle is adc = 200 + 15 * 0.03 * ( 1.0 + 0) / 3000 * 16384 = 200 + 2.4576
67-
.sampFrac = "0.03",
131+
3, // The ADC of a 15 MeV particle is adc = 200 + 15 * 0.03 * ( 1.0 + 0) / 3000 * 16384 = 200 + 2.4576
132+
// 15 MeV = 2.4576, but adc=llround(dE) and cut off is "<". So 3 here = 15.25MeV
133+
.sampFrac = "1.00", // already taken care in DIGI code above
68134
.readout = "EcalEndcapPHits",
69135
},
70136
app // TODO: Remove me once fixed

0 commit comments

Comments
 (0)