Skip to content
Open
Show file tree
Hide file tree
Changes from 98 commits
Commits
Show all changes
107 commits
Select commit Hold shift + click to select a range
cb25871
First commit
mhkim-anl Jul 5, 2026
2517076
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 5, 2026
f4f02a5
Merge branch 'main' into 2728-edep-to-npe-conversion
mhkim-anl Jul 5, 2026
1327386
Implementation of an algorithm for Edep-to-Npe conversion (fix: iwyu)…
epic-capybara Jul 5, 2026
6e6f4db
Remove personal debug output and modify some comments
mhkim-anl Jul 5, 2026
b1fdee6
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 5, 2026
2ed9396
Implementation of an algorithm for Edep-to-Npe conversion (fix: iwyu)…
epic-capybara Jul 5, 2026
7e21f85
Merge branch 'main' into 2728-edep-to-npe-conversion
sly2j Jul 23, 2026
cdb407d
First commit on CalorimeterCALOROCCalibration
Jul 23, 2026
fd34410
Fixed contribution list
Jul 23, 2026
97f3a8a
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 23, 2026
2f25027
Fixed spelling errors in comments.
Jul 23, 2026
b659bad
merged
Jul 23, 2026
0fd7a64
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 23, 2026
f57c9c8
Fixed errors in git merge.
Jul 23, 2026
3fc492f
fix merge
Jul 23, 2026
6b2236e
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 23, 2026
c8dc9d3
Fix author list
Jul 23, 2026
fe794eb
Removed unused variable
Jul 23, 2026
d60a6f6
Removed unused variables.
Jul 23, 2026
4f7ebc9
Added default statement to switch statement in CalorimeterCALOROCCali…
Jul 24, 2026
47beb34
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 24, 2026
0654177
Added breaks to switch statement in CalorimeterCALOROCCalibration.
Jul 24, 2026
50be966
Add CalorimeterCALOROCCalibration (fix: iwyu) (#2775)
epic-capybara Jul 24, 2026
05272c9
Potential fix for pull request finding
ssedd1123 Jul 24, 2026
9475c6c
Potential fix for pull request finding
ssedd1123 Jul 24, 2026
f83bb0f
Potential fix for pull request finding
ssedd1123 Jul 24, 2026
0bb2e32
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 24, 2026
587eebb
Potential fix for pull request finding
ssedd1123 Jul 24, 2026
c2f395b
Potential fix for pull request finding
ssedd1123 Jul 24, 2026
a0538b1
Fixed typo in CalorimeterCALOROCCalibration
Jul 24, 2026
6b5f2a6
Potential fix for pull request finding
ssedd1123 Jul 24, 2026
e865d64
Add CalorimeterCALOROCCalibration (fix: iwyu) (#2776)
epic-capybara Jul 24, 2026
47371c1
Update the path to the LUT file
mhkim-anl Jul 24, 2026
869f441
Merge branch 'main' into 2728-edep-to-npe-conversion
mhkim-anl Jul 24, 2026
04c2eaa
Potential fix for pull request finding
ssedd1123 Jul 24, 2026
b968388
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 24, 2026
e93ec42
Potential fix for pull request finding
ssedd1123 Jul 24, 2026
c7038a9
Merge remote-tracking branch 'origin/2728-edep-to-npe-conversion' int…
Jul 24, 2026
f19614c
Update src/algorithms/calorimetry/CalorimeterCALOROCCalibration.cc
ssedd1123 Jul 24, 2026
89d2261
Fixed bug on filename not recognized.
Jul 25, 2026
d3e0f09
Add CalorimeterCALOROCCalibration (fix: iwyu) (#2787)
epic-capybara Jul 25, 2026
710360c
The file path calibrations/ was already included in the file name in …
mhkim-anl Jul 25, 2026
ef526ce
Update src/algorithms/calorimetry/EdepToNpeConversion.h
mhkim-anl Jul 26, 2026
a50e967
Update src/algorithms/calorimetry/EdepToNpeConversion.h
mhkim-anl Jul 26, 2026
7f564db
Update src/algorithms/calorimetry/EdepToNpeConversion.h
mhkim-anl Jul 26, 2026
de9cfee
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 26, 2026
755ca24
Update src/algorithms/calorimetry/EdepToNpeConversion.cc
mhkim-anl Jul 26, 2026
786605e
Update src/algorithms/calorimetry/EdepToNpeConversion.cc
mhkim-anl Jul 26, 2026
87e20de
Update src/factories/calorimetry/EdepToNpeConversion_factory.h
mhkim-anl Jul 26, 2026
f15f23f
Update src/factories/calorimetry/EdepToNpeConversion_factory.h
mhkim-anl Jul 26, 2026
baac55b
Update src/factories/calorimetry/EdepToNpeConversion_factory.h
mhkim-anl Jul 26, 2026
79269f5
Update src/detectors/BEMC/BEMC.cc
mhkim-anl Jul 26, 2026
132e9e3
Update src/detectors/BEMC/BEMC.cc
mhkim-anl Jul 26, 2026
c2e2cf3
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 26, 2026
30f54e1
Merge remote-tracking branch 'origin/2728-edep-to-npe-conversion' int…
Jul 26, 2026
a459487
Implementation of an algorithm for Edep-to-Npe conversion (fix: iwyu)…
epic-capybara Jul 27, 2026
378349d
Merge branch 'main' into 2728-edep-to-npe-conversion
mhkim-anl Jul 28, 2026
ebd778d
Merge remote-tracking branch 'origin/2728-edep-to-npe-conversion' int…
Jul 28, 2026
79c689a
Switch from reading Pulse class to Npe class for MC-reco information.
Jul 28, 2026
47ddeef
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 28, 2026
0f3fcad
Changed inputs for CALOROCCalibration in BEMC.cc
Jul 28, 2026
ab897a8
Merge branch 'pr/ECAL_calibration' of https://github.com/eic/EICrecon…
Jul 28, 2026
4f2fbba
Changed names of arguments in BEMC.cc
Jul 28, 2026
dd3be4c
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 28, 2026
967e13b
Merge branch 'main' into 2728-edep-to-npe-conversion
ssedd1123 Jul 28, 2026
cf8ead2
Add CalorimeterCALOROCCalibration (fix: iwyu) (#2796)
epic-capybara Jul 28, 2026
1a8b08f
Added unit test for CalorimeterCALOROCCalibration
Aug 3, 2026
9237d87
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 3, 2026
4b00bc7
Added Npe contributions to remove dangling references.
Aug 3, 2026
b268b3f
Merge branch 'pr/ECAL_calibration' of https://github.com/eic/EICrecon…
Aug 3, 2026
9f8bd7b
Add CalorimeterCALOROCCalibration (fix: iwyu) (#2826)
epic-capybara Aug 3, 2026
fc25f86
Renamed Calibration to Reco class.
Aug 3, 2026
07f590e
Merge branch 'pr/ECAL_calibration' of https://github.com/eic/EICrecon…
Aug 3, 2026
4c1a204
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 3, 2026
4ae997d
Update src/algorithms/calorimetry/CalorimeterCALOROCReco.cc
ssedd1123 Aug 4, 2026
26e0904
Update src/algorithms/calorimetry/CalorimeterCALOROCReco.cc
ssedd1123 Aug 4, 2026
fe9d277
Update src/algorithms/calorimetry/CalorimeterCALOROCReco.cc
ssedd1123 Aug 4, 2026
3a87431
Update src/algorithms/calorimetry/CalorimeterCALOROCReco.cc
ssedd1123 Aug 4, 2026
c26c10f
Update src/algorithms/calorimetry/CalorimeterCALOROCReco.cc
ssedd1123 Aug 4, 2026
eb1f651
Update src/algorithms/calorimetry/CalorimeterCALOROCReco.cc
ssedd1123 Aug 4, 2026
d679da3
Update src/algorithms/calorimetry/CalorimeterCALOROCReco.cc
ssedd1123 Aug 4, 2026
81f849d
Update src/algorithms/calorimetry/CalorimeterCALOROCReco.cc
ssedd1123 Aug 4, 2026
0f6f7c3
Update src/algorithms/calorimetry/CalorimeterCALOROCReco.cc
ssedd1123 Aug 4, 2026
44fc410
Update src/algorithms/calorimetry/CalorimeterCALOROCReco.cc
ssedd1123 Aug 4, 2026
9a91498
Update src/algorithms/calorimetry/CalorimeterCALOROCReco.cc
ssedd1123 Aug 4, 2026
ab54a5d
Update src/algorithms/calorimetry/CalorimeterCALOROCReco.cc
ssedd1123 Aug 4, 2026
3440b8f
Reordered functions, replace some member variables with straight call…
Aug 4, 2026
2333b2c
Removed unused variables.
Aug 4, 2026
d0c71fb
Add CalorimeterCALOROCCalibration (fix: iwyu) (#2830)
epic-capybara Aug 4, 2026
16cb803
Merge branch 'main' into 2728-edep-to-npe-conversion
mhkim-anl Aug 6, 2026
52382ff
Use clone() to preserve hit contribution relations. NpeHitContributio…
mhkim-anl Aug 8, 2026
bd5f332
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 8, 2026
b2acc13
Merge branch 'main' into 2728-edep-to-npe-conversion
mhkim-anl Aug 8, 2026
38e2e6f
Implementation of an algorithm for Edep-to-Npe conversion (fix: iwyu)…
epic-capybara Aug 8, 2026
fe1c725
Restore changes from main
mhkim-anl Aug 8, 2026
acb5b46
Merge branch 'main' into 2728-edep-to-npe-conversion
mhkim-anl Aug 10, 2026
7662580
Fix merge conflicts.
Aug 11, 2026
ddb93a5
Merge branch 'main' into pr/ECAL_calibration
ssedd1123 Aug 13, 2026
50cdd4a
Update JEventProcessorPODIO.cc
ssedd1123 Aug 13, 2026
cdefcf9
Update CalorimeterCALOROCReco.cc
ssedd1123 Aug 13, 2026
237ae32
Update BEMC.cc to remove a redundant #endif.
ssedd1123 Aug 13, 2026
eb21c1b
Update src/tests/algorithms_test/calorimetry_CalorimeterCALOROCReco.cc
ssedd1123 Aug 13, 2026
d252250
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 13, 2026
0db7a82
Update calorimetry_CalorimeterCALOROCReco.cc to fix the inability to …
ssedd1123 Aug 13, 2026
09a6874
Merge branch 'main' into pr/ECAL_calibration
ssedd1123 Aug 14, 2026
ade7c3e
Merge branch 'main' into pr/ECAL_calibration
ssedd1123 Aug 14, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
506 changes: 506 additions & 0 deletions src/algorithms/calorimetry/CalorimeterCALOROCReco.cc

Large diffs are not rendered by default.

84 changes: 84 additions & 0 deletions src/algorithms/calorimetry/CalorimeterCALOROCReco.h
Comment thread
ssedd1123 marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
// Copyright (C) 2026 Chun Yuen Tsang, Minho Kim

#pragma once

#include <DD4hep/DetElement.h>
#include <DD4hep/Detector.h>
#include <DD4hep/IDDescriptor.h>
#include <DDRec/CellIDPositionConverter.h>
#include <Parsers/Primitives.h>
#include <algorithms/algorithm.h>
#include <algorithms/geo.h>
#include <edm4eic/CalorimeterHitCollection.h>
#include <edm4eic/MCRecoCalorimeterHitAssociationCollection.h>
#include <edm4eic/MCRecoCalorimeterHitLinkCollection.h>
#include <edm4eic/RawCALOROCHitCollection.h>
#include <edm4hep/RawCalorimeterHitCollection.h>
#include <edm4hep/SimCalorimeterHitCollection.h>
#include <cstddef>
#include <functional>
#include <gsl/pointers>
#include <map>
#include <string>
#include <string_view>
#include <vector>

#include "CalorimeterCALOROCRecoConfig.h"
#include "algorithms/interfaces/WithPodConfig.h"

namespace eicrecon {

using CalorimeterCALOROCRecoAlgorithm = algorithms::Algorithm<
algorithms::Input<edm4hep::SimCalorimeterHitCollection, edm4eic::RawCALOROCHitCollection,
edm4hep::SimCalorimeterHitCollection, edm4eic::RawCALOROCHitCollection>,
algorithms::Output<edm4eic::CalorimeterHitCollection, edm4hep::RawCalorimeterHitCollection,
edm4eic::MCRecoCalorimeterHitLinkCollection,
edm4eic::MCRecoCalorimeterHitAssociationCollection>>;

class CalorimeterCALOROCReco : public CalorimeterCALOROCRecoAlgorithm,
public WithPodConfig<CalorimeterCALOROCRecoConfig> {

public:
CalorimeterCALOROCReco(std::string_view name)
: CalorimeterCALOROCRecoAlgorithm{
name,
{"inputNpeHitPCollection", "inputADCPCollection", "inputNpeHitNCollection",
"inputADCNCollection"},
{"outputRecHitCollection", "outputRawHitCollection", "outputRawLink", "outputRawAssoc"},
"Reconstruct hit from CALOROC ADC data with MC truth from NpeHits."} {}
Comment thread
ssedd1123 marked this conversation as resolved.

void init() final;
void process(const Input&, const Output&) const final;

private:
std::function<double(const edm4hep::RawCalorimeterHit& h)> sampFrac;

dd4hep::IDDescriptor id_spec;
dd4hep::BitFieldCoder* id_dec = nullptr;

double m_reference_z_p, m_reference_z_n;
std::size_t sector_idx{0}, layer_idx{0};

mutable bool warned_unsupported_segmentation = false;

dd4hep::DetElement m_local;
std::size_t local_mask = ~static_cast<std::size_t>(0), gpos_mask = static_cast<std::size_t>(0);

std::map<std::vector<int>, double> m_edep_to_npe_lut{};
std::vector<std::size_t> m_field_idxs{};

double _energyCor(double referencePos, double energy, double z) const;
double _sumADC(const edm4eic::RawCALOROCHit& ADC) const;
double _toa(const edm4eic::RawCALOROCHit& ADC) const;
double _timeWalkCorrection(double toa, double ADC) const;

const algorithms::GeoSvc& m_geo = algorithms::GeoSvc::instance();

private:
const dd4hep::Detector* m_detector{algorithms::GeoSvc::instance().detector()};
const dd4hep::rec::CellIDPositionConverter* m_converter{
algorithms::GeoSvc::instance().cellIDPositionConverter()};
};

} // namespace eicrecon
86 changes: 86 additions & 0 deletions src/algorithms/calorimetry/CalorimeterCALOROCRecoConfig.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
// Copyright (C) 2026 Chun Yuen Tsang, Minho Kim

#pragma once

#include <cstdint>
#include <iostream>
#include <string>
#include <vector>
Comment thread
Copilot marked this conversation as resolved.

namespace eicrecon {

struct CalorimeterCALOROCRecoConfig {
// readout fields
std::string readout{""};
std::string layerField{""};
std::string sectorField{""};

// name of detelment or fields to find the local detector (for global->local transform)
// if nothing is provided, the lowest level DetElement (from cellID) will be used
std::string localDetElement{""};
std::vector<std::string> localDetFields{};
std::string maskPos{""};
std::vector<std::string> maskPosFields{};

std::string edep_to_npe_filename{""};
Comment thread
ssedd1123 marked this conversation as resolved.
std::vector<std::string> edep_to_npe_fields{};
enum class ProxyType { sum = 0, simpson = 1, templateFit = 2 } proxy_type = ProxyType::sum;

bool timeWalkCor{false};
bool useNpeHitPos{false};

uint16_t highGainDR{0}; // high gain dynamic range
double gainRatio{1}; // gain ratio of low gain to high gain, it should be < 1

std::string attenuationReferencePositionNamePos{""};
std::string attenuationReferencePositionNameNeg{""};

// parameters for attenuation function
// [0] * exp(-|z_ref - z| / [1]) + (1 - [0]) * exp(-|z_ref - z| / [2])
// specified in edm4eic::units where dimensionfull
std::vector<double> attenuationParameters{0};

std::vector<double> timeWalkCorrectionParameters{0};
std::vector<double> lightSpeedParameters{0};

// calibration parameters
double slope = 1 / 9.41e-2;
double intercept = 0;
};

std::istream& operator>>(std::istream& in, CalorimeterCALOROCRecoConfig::ProxyType& proxyType) {
std::string s;
in >> s;
// stringifying the enums causes them to be converted to integers before conversion to strings
if (s == "sum" or s == "0") {
proxyType = CalorimeterCALOROCRecoConfig::ProxyType::sum;
} else if (s == "simpson" or s == "1") {
proxyType = CalorimeterCALOROCRecoConfig::ProxyType::simpson;
} else if (s == "templateFit" or s == "2") {
proxyType = CalorimeterCALOROCRecoConfig::ProxyType::templateFit;
} else {
in.setstate(std::ios::failbit); // Set the fail bit if the input is not valid
}

return in;
}
Comment thread
ruse-traveler marked this conversation as resolved.
std::ostream& operator<<(std::ostream& out,
const CalorimeterCALOROCRecoConfig::ProxyType& proxyType) {
switch (proxyType) {
case CalorimeterCALOROCRecoConfig::ProxyType::sum:
out << "sum";
break;
case CalorimeterCALOROCRecoConfig::ProxyType::simpson:
out << "simpson";
break;
case CalorimeterCALOROCRecoConfig::ProxyType::templateFit:
out << "templateFit";
break;
default:
out.setstate(std::ios::failbit);
}
return out;
}

} // namespace eicrecon
142 changes: 142 additions & 0 deletions src/algorithms/calorimetry/EdepToNpeConversion.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
// Copyright (C) 2026 Minho Kim

#include <DD4hep/Detector.h>
#include <DD4hep/Readout.h>
#include <DDSegmentation/BitFieldCoder.h>
#include <fmt/format.h>
#include <fmt/ranges.h>
#include <cstddef>
#include <fstream>
#include <random>
#include <sstream>
#include <stdexcept>
#include <string>
#include <tuple>
#include <utility>
#include <vector>

#include "EdepToNpeConversion.h"

namespace eicrecon {

void EdepToNpeConversion::init() {

// A nonzero constant factor takes precedence if it is configured together with LUT
if (m_cfg.edep_to_npe > 0) {
if (!m_cfg.edep_to_npe_filename.empty()) {
info("Constant edep-to-npe factor {} is set; ignoring LUT file {}", m_cfg.edep_to_npe,
m_cfg.edep_to_npe_filename);
}
return;
}

// Otherwise a complete LUT configuration is required
if (m_cfg.readout.empty() || m_cfg.edep_to_npe_fields.empty() ||
m_cfg.edep_to_npe_filename.empty()) {
throw std::runtime_error(
"No edep-to-npe conversion configured: set either a constant edep_to_npe factor or all "
"of (readout, edep_to_npe_fields, edep_to_npe_filename)");
}

// Get the cellID decoder and the indices of the LUT key fields
try {
m_id_spec = m_detector->readout(m_cfg.readout).idSpec();
} catch (...) {
throw std::runtime_error(fmt::format("Failed to get idSpec for readout {}", m_cfg.readout));
}
m_id_dec = m_id_spec.decoder();
if (m_id_dec == nullptr) {
throw std::runtime_error(fmt::format("Failed to get ID decoder for readout {}", m_cfg.readout));
}
for (const auto& field : m_cfg.edep_to_npe_fields) {
try {
m_field_idxs.push_back(m_id_dec->index(field));
} catch (...) {
throw std::runtime_error(
fmt::format("Field {} not found in idSpec of readout {}", field, m_cfg.readout));
}
}

// Load the LUT and parses each line into a lookup key and a conversion factor
std::string filename = m_cfg.edep_to_npe_filename;
std::ifstream infile(filename);
if (!infile) {
throw std::runtime_error(fmt::format("Unable to open LUT file: {}", filename));
}
std::string line;
std::size_t lineno = 0;
while (std::getline(infile, line)) {
lineno++;
if (line.empty()) {
throw std::runtime_error(
fmt::format("Empty line in LUT file {} at line {}", filename, lineno));
}
std::istringstream iss(line);
std::vector<int> key(m_cfg.edep_to_npe_fields.size());
double factor;
for (auto& value : key) {
if (!(iss >> value)) {
throw std::runtime_error(fmt::format("Malformed LUT file {} at line {}", filename, lineno));
}
}
if (!(iss >> factor)) {
throw std::runtime_error(fmt::format("Malformed LUT file {} at line {}", filename, lineno));
}
if (!m_edep_to_npe_lut.emplace(std::move(key), factor).second) {
throw std::runtime_error(
fmt::format("Duplicate key in LUT file {} at line {}", filename, lineno));
}
}
if (m_edep_to_npe_lut.empty()) {
throw std::runtime_error(fmt::format("LUT file {} contains no entries", filename));
}
} // EdepToNpeConversion:init

void EdepToNpeConversion::process(const EdepToNpeConversion::Input& input,
const EdepToNpeConversion::Output& output) const {
const auto [headers, inhits] = input;
auto [outhits] = output;

auto seed = m_uid.getUniqueID(*headers, name());
std::mt19937 generator(seed);

for (const auto& hit : *inhits) {
// Edep-to-Npe conversion & Apply Poisson smearing
const double mean_npe = hit.getEnergy() * get_edep_to_npe_factor(hit);
long npe = 0;
if (mean_npe > 0) {
std::poisson_distribution<long> poisson(mean_npe);
npe = poisson(generator);
}

if (npe == 0) {
continue;
}

auto out_hit = hit.clone();
out_hit.setEnergy(static_cast<float>(npe));
outhits->push_back(out_hit);
}

} // EdepToNpeConversion:process

double EdepToNpeConversion::get_edep_to_npe_factor(const edm4hep::SimCalorimeterHit& hit) const {
if (m_cfg.edep_to_npe > 0) {
return m_cfg.edep_to_npe;
}
std::vector<int> key;
key.reserve(m_field_idxs.size());
for (const auto idx : m_field_idxs) {
key.push_back(static_cast<int>(m_id_dec->get(hit.getCellID(), idx)));
}
const auto it = m_edep_to_npe_lut.find(key);
if (it == m_edep_to_npe_lut.end()) {
throw std::runtime_error(
fmt::format("No edep-to-npe factor for cellID {:#x} (fields [{}] = [{}])", hit.getCellID(),
fmt::join(m_cfg.edep_to_npe_fields, ", "), fmt::join(key, ", ")));
}
return it->second;
}

} // namespace eicrecon
51 changes: 51 additions & 0 deletions src/algorithms/calorimetry/EdepToNpeConversion.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
// Copyright (C) 2026 Minho Kim

#pragma once

#include <DD4hep/Detector.h>
#include <DD4hep/IDDescriptor.h>
#include <Parsers/Primitives.h>
#include <algorithms/algorithm.h>
#include <algorithms/geo.h>
#include <edm4hep/EventHeaderCollection.h>
#include <edm4hep/SimCalorimeterHitCollection.h>
#include <cstddef>
#include <gsl/pointers>
#include <map>
#include <string>
#include <string_view>
#include <vector>

#include "algorithms/calorimetry/EdepToNpeConversionConfig.h"
#include "algorithms/interfaces/UniqueIDGenSvc.h"
#include "algorithms/interfaces/WithPodConfig.h"

namespace eicrecon {

using EdepToNpeConversionAlgorithm = algorithms::Algorithm<
algorithms::Input<edm4hep::EventHeaderCollection, edm4hep::SimCalorimeterHitCollection>,
algorithms::Output<edm4hep::SimCalorimeterHitCollection>>;

class EdepToNpeConversion : public EdepToNpeConversionAlgorithm,
public WithPodConfig<EdepToNpeConversionConfig> {

public:
EdepToNpeConversion(std::string_view name)
: EdepToNpeConversionAlgorithm{name, {"EventHeader", "inputHits"}, {"outputHits"}, {}} {}
void init() final;
void process(const Input&, const Output&) const final;

private:
double get_edep_to_npe_factor(const edm4hep::SimCalorimeterHit& hit) const;

const dd4hep::Detector* m_detector{algorithms::GeoSvc::instance().detector()};
const algorithms::UniqueIDGenSvc& m_uid = algorithms::UniqueIDGenSvc::instance();

dd4hep::IDDescriptor m_id_spec;
const dd4hep::BitFieldCoder* m_id_dec = nullptr;
std::vector<std::size_t> m_field_idxs{};
std::map<std::vector<int>, double> m_edep_to_npe_lut{};
};

} // namespace eicrecon
20 changes: 20 additions & 0 deletions src/algorithms/calorimetry/EdepToNpeConversionConfig.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
// Copyright (C) 2026 Minho Kim

#pragma once

#include <string>
#include <vector>

namespace eicrecon {

struct EdepToNpeConversionConfig {
std::string readout{};
std::vector<std::string>
edep_to_npe_fields{}; // Fields the edep-to-npe conversion factor depends on
std::string
edep_to_npe_filename{}; // Lookup table name to get the field-dependent edep-to-npe conversion factors
double edep_to_npe{}; // Constant edep-to-npe conversion factor
};

} // namespace eicrecon
Loading
Loading