-
Notifications
You must be signed in to change notification settings - Fork 30
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Realistic BTOF digitization #1635
Open
ssedd1123
wants to merge
119
commits into
main
Choose a base branch
from
pr/BTOF-digitization-clusterization
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
119 commits
Select commit
Hold shift + click to select a range
8123783
First commit of BTOF digitization code!
ssedd1123 2332d18
Update BTOFHitDigi.cc
eicsouvik 4b907cb
Update BTOFHitDigi.h
eicsouvik 204d472
Update BTOFHitDigi.cc
eicsouvik 1b08022
Merge pull request #3 from eicsouvik/patch-1
ssedd1123 5e011e1
Merge pull request #2 from eicsouvik/patch-2
ssedd1123 5e17954
Merge pull request #1 from eicsouvik/patch-3
ssedd1123 9fbe640
Changed the algorithm of BarrelTOFNeighborFinder so it's more intuita…
171ffd4
Merge branch 'main' of https://github.com/ssedd1123/EICrecon
52a9b33
Changed spread calculation. Originally the spread were estimated with…
54024b6
Fixed bugs when sensor ID from barrelTOFNeighborFinder gives wrong ne…
ssedd1123 5e1cec4
Merge branch 'eic:main' into main
ssedd1123 40abca0
Updated BTOF neighbor finder. To be used with updated epic geometry w…
ssedd1123 72edf8b
Merge branch 'eic:main' into main
ssedd1123 df48d16
Merge branch 'eic:main' into main
ssedd1123 1d3c040
Merge branch 'eic:main' into main
ssedd1123 1adfd02
Sync fork.
ssedd1123 f373972
Added missing closing parenthesis.
ssedd1123 0725492
Use more realistic charge sharing parameters and bug fix on ADC heights.
ssedd1123 a451aed
Merge branch 'main' of https://github.com/ssedd1123/EICrecon
ssedd1123 ce9122d
Fixed incorrect threshold for ADC TDC.
ssedd1123 08c83e6
Merge branch 'eic:main' into main
ssedd1123 350ca3b
Move digitization code to the main branch.
ssedd1123 4f892ee
Formated files.
ssedd1123 8d8a12a
Included config content in parameter ref.
ssedd1123 d260635
Merge remote-tracking branch 'new-origin/main' into pr/BTOF-digitizat…
ssedd1123 875f0f4
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] b12ee38
Fixed BTOF reco uncertainty estimation bug.
ssedd1123 0d91db5
Merge branch 'main' into pr/BTOF-digitization-clusterization
ssedd1123 34f4daa
Removed reconstruction for later pull request. Breaks TOF digi into t…
ssedd1123 9ab01c9
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 4cf1216
Removed legacy modification to JEventProcessorPODIO.cc
ssedd1123 83c9b88
Merge branch 'pr/BTOF-digitization-clusterization' of https://github.…
ssedd1123 deaf63c
Merge branch 'main' into pr/BTOF-digitization-clusterization
ssedd1123 14889de
Fixed bugs on charge sharing calculation. It was assumed that all gea…
ssedd1123 7474a52
Merge branch 'main' into pr/BTOF-digitization-clusterization
ssedd1123 569090d
Moved algorithms away from src/detectors.
ssedd1123 33c6587
Fix spelling mistakes to make codespell happy.
ssedd1123 b28d49f
Removed unnecessary header files.
ssedd1123 8f01587
Trigger Build
ssedd1123 595952d
Merge branch 'main' into pr/BTOF-digitization-clusterization
ssedd1123 a4b5211
Update src/algorithms/digi/BTOFChargeSharing.cc
ssedd1123 f4f3204
Update src/algorithms/digi/TOFPulseDigitization.cc
ssedd1123 76fccd8
Update src/algorithms/digi/TOFPulseDigitization.cc
ssedd1123 310c510
Update src/algorithms/digi/BTOFChargeSharing.cc
ssedd1123 6e44318
Update src/algorithms/digi/TOFPulseDigitization.h
ssedd1123 7ecc458
Update src/algorithms/digi/TOFPulseGeneration.h
ssedd1123 41614b8
Update src/algorithms/digi/BTOFChargeSharing.cc
ssedd1123 7ca28d3
Update src/algorithms/digi/BTOFChargeSharing.h
ssedd1123 576055c
Update src/algorithms/digi/BTOFChargeSharing.cc
ssedd1123 232a3ef
Replaced magic number in BTOFChargeSharing with the correct unit.
ssedd1123 8043bff
Make clang-tidy-iwyu happy.
ssedd1123 837900a
Trigger Build
ssedd1123 e51c007
Update src/algorithms/digi/TOFPulseGeneration.cc
ssedd1123 1d3f592
Update src/algorithms/digi/TOFPulseGeneration.cc
ssedd1123 3e0afdc
Make clang-tidy-iwyu happy.
ssedd1123 89452f4
TOFPulseGeneration_factory.h: mixedCase for parameter names
veprbl d0040c6
TOFPulseDigitization_factory.h: ditto
veprbl bbc6ab0
TOFPulseDigitization_factory.h: missed
veprbl 5664496
BTOFChargeSharing_factory.h: ditto
veprbl 00d1890
TOFHitDigiConfig.h: rm unused suff
veprbl 3af27a9
BTOFChargeSharing_factory.h: need algorithmsInit
veprbl cb3209d
TOFPulseDigitization_factory.h: ditto
veprbl 6ba7bab
TOFPulseGeneration_factory.h: ditto
veprbl fa7ad55
BTOFChargeSharing.h: remove cache stuff for now
veprbl 5f092d4
Merge branch 'main' into pr/BTOF-digitization-clusterization
veprbl ef00944
JEventProcessorPODIO.cc: add TOFBarrelADCTDC
veprbl a745e2b
Update src/services/io/podio/JEventProcessorPODIO.cc
veprbl dd95d6b
Added tests for TOFPulseDigitization and TOFPulseGeneration.
ssedd1123 d073d6b
Removed unnecessary credits.
ssedd1123 6e34d8a
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 22c9fe4
Merge branch 'main' into pr/BTOF-digitization-clusterization
ssedd1123 ce7b6a0
Merge branch 'main' into pr/BTOF-digitization-clusterization
ssedd1123 d732550
Update src/algorithms/digi/TOFHitDigiConfig.h
ssedd1123 aef5225
Merge branch 'main' into pr/BTOF-digitization-clusterization
ssedd1123 40cf825
Amplitude of Landau pulse is now a configurable parameter.
ssedd1123 fbde72c
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] da1321b
Beginning time of TOFPulse is now aligned to the beginning of clock c…
ssedd1123 515eba4
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] fcb0e07
Make clang-tidy-iwyu happy.
ssedd1123 5f3d182
Merge branch 'main' into pr/BTOF-digitization-clusterization
ssedd1123 a1455a8
Merge branch 'main' into pr/BTOF-digitization-clusterization
ssedd1123 9551964
Fix typo in code.
ssedd1123 3d4638c
Trigger Build
ssedd1123 99d7bd8
Merge branch 'main' into pr/BTOF-digitization-clusterization
veprbl 29239b7
apply clang-format
veprbl 6a67c57
Trigger Build
ssedd1123 92263ed
Merge branch 'main' into pr/BTOF-digitization-clusterization
ssedd1123 071d7af
Merge branch 'main' into pr/BTOF-digitization-clusterization
ssedd1123 a1ab224
Merge branch 'main' into pr/BTOF-digitization-clusterization
ssedd1123 b1f7166
Added extra bits to show which EIRCOR cycle a timestampe belongs to.
ssedd1123 f31c553
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 2981788
Separate config class for PulseDigitization and PulseGeneration.
ssedd1123 3883f9b
Merge branch 'pr/BTOF-digitization-clusterization' of https://github.…
ssedd1123 9fe2773
Make clang-tidy happy.
ssedd1123 2401f0a
Modified slightly so it works with negative global time.
ssedd1123 01473d3
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 2aab59b
Make clang-tidy happy.
ssedd1123 d1218e0
Merge branch 'main' into pr/BTOF-digitization-clusterization
ssedd1123 0093690
Update src/algorithms/digi/LGADPulseGenerationConfig.h
ssedd1123 6f852c0
Update src/algorithms/digi/LGADPulseDigitizationConfig.h
ssedd1123 231cb0a
Update src/algorithms/digi/LGADChargeSharingConfig.h
ssedd1123 7f8a8e3
Update src/algorithms/digi/LGADPulseGeneration.cc
ssedd1123 8e652c9
Removed legacy file LGADChargeSharingConfig.h
ssedd1123 e695627
Update src/algorithms/digi/BTOFChargeSharing.cc
ssedd1123 a1aa137
use private rather than protected on BTOFChargeSharing
ssedd1123 350d280
Merge branch 'main' into pr/BTOF-digitization-clusterization
ssedd1123 e9989fe
Update src/algorithms/digi/LGADPulseDigitization.cc
ssedd1123 542277a
BTOFChargeSharing -> LGADChargeSharing. The CellID fields to scan thr…
ssedd1123 f959908
Merge branch 'pr/BTOF-digitization-clusterization' of https://github.…
ssedd1123 018001e
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] e761e0d
make clang-tidy-iwyu happy.
ssedd1123 57de8af
Merge branch 'pr/BTOF-digitization-clusterization' of https://github.…
ssedd1123 ab5b497
LGADPulseDigitization: add some missing std:: namespaces
veprbl 8dd1c87
algorithms/digi: link to algorithms for use of GeoSvc
veprbl e6f1517
eicrecon: load evaluator before acts (acts depends on algorithms_digi…
veprbl 09a2899
move PulseShape to become a private API
veprbl 4076dbd
IWYU
veprbl 46c5c9f
Merge branch 'main' into pr/BTOF-digitization-clusterization
veprbl File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,185 @@ | ||
// SPDX-License-Identifier: LGPL-3.0-or-later | ||
// Copyright (C) 2024 Chun Yuen Tsang, Prithwish Tribedy | ||
// | ||
// Spread energy deposition from one strip to neighboring strips within sensor boundaries | ||
|
||
#include <DD4hep/DetElement.h> | ||
#include <DD4hep/Handle.h> | ||
#include <DD4hep/Readout.h> | ||
#include <DD4hep/Segmentations.h> | ||
#include <DD4hep/Volumes.h> | ||
#include <Evaluator/DD4hepUnits.h> | ||
#include <Math/GenVector/Cartesian3D.h> | ||
#include <Math/GenVector/DisplacementVector3D.h> | ||
#include <TGeoManager.h> | ||
#include <TGeoMatrix.h> | ||
#include <TGeoVolume.h> | ||
#include <algorithms/geo.h> | ||
#include <algorithms/service.h> | ||
#include <edm4hep/Vector3d.h> | ||
#include <edm4hep/Vector3f.h> | ||
#include <fmt/core.h> | ||
#include <cmath> | ||
#include <gsl/pointers> | ||
#include <stdexcept> | ||
#include <unordered_map> | ||
#include <utility> | ||
#include <vector> | ||
|
||
#include "DD4hep/Detector.h" | ||
#include "LGADChargeSharing.h" | ||
#include "algorithms/digi/LGADChargeSharingConfig.h" | ||
#include "services/evaluator/EvaluatorSvc.h" | ||
|
||
namespace eicrecon { | ||
|
||
void LGADChargeSharing::init() { | ||
m_detector = algorithms::GeoSvc::instance().detector(); | ||
m_converter = algorithms::GeoSvc::instance().cellIDPositionConverter(); | ||
|
||
auto seg = m_detector->readout(m_cfg.readout).segmentation(); | ||
auto type = seg.type(); | ||
if (type != "CartesianGridXY") | ||
throw std::runtime_error("Unsupported segmentation type: " + type + | ||
". BarrelTOF must use CartesianGridXY."); | ||
// retrieve meaning of cellID bits | ||
m_decoder = seg.decoder(); | ||
m_idSpec = m_detector->readout(m_cfg.readout).idSpec(); | ||
|
||
// convert cellID to name value pairs for EvaluatorSvc to determine of different cells are neighbors | ||
std::function hit_pair_to_map = [this](const dd4hep::rec::CellID& id1, const dd4hep::rec::CellID& id2) { | ||
std::unordered_map<std::string, double> params; | ||
for(const auto &p : m_idSpec.fields()) { | ||
const std::string &name = p.first; | ||
const dd4hep::IDDescriptor::Field* field = p.second; | ||
params.emplace(name + "_1", field->value(id1)); | ||
params.emplace(name + "_2", field->value(id2)); | ||
trace("{}_1 = {}", name, field->value(id1)); | ||
trace("{}_2 = {}", name, field->value(id2)); | ||
} | ||
return params; | ||
}; | ||
|
||
auto& serviceSvc = algorithms::ServiceSvc::instance(); | ||
_is_same_sensor = serviceSvc.service<EvaluatorSvc>("EvaluatorSvc")->compile(m_cfg.same_sensor_condition, hit_pair_to_map); | ||
|
||
} | ||
|
||
void LGADChargeSharing::process(const LGADChargeSharing::Input& input, | ||
const LGADChargeSharing::Output& output) const { | ||
const auto [simhits] = input; | ||
auto [sharedHits] = output; | ||
|
||
for (const auto& hit : *simhits) { | ||
auto cellID = hit.getCellID(); | ||
|
||
std::unordered_set<dd4hep::rec::CellID> dp; | ||
std::vector<dd4hep::rec::CellID> neighbors; | ||
this->_findAllNeighborsInSensor(cellID, neighbors, dp); | ||
|
||
double edep = hit.getEDep(); | ||
double time = hit.getTime(); | ||
auto momentum = hit.getMomentum(); | ||
auto truePos = hit.getPosition(); | ||
auto localPos_hit = this->_global2Local( | ||
dd4hep::Position(truePos.x * dd4hep::mm, truePos.y * dd4hep::mm, truePos.z * dd4hep::mm)); | ||
|
||
for (const auto neighbor : neighbors) { | ||
// integrate over neighbor area to get total energy deposition | ||
auto localPos_neighbor = this->_cell2LocalPosition(neighbor); | ||
auto cellDimension = m_converter->cellDimensions(neighbor); | ||
|
||
double edep_cell = edep * | ||
_integralGaus(localPos_hit.x(), m_cfg.sigma_sharingx, | ||
localPos_neighbor.x() - 0.5 * cellDimension[0], | ||
localPos_neighbor.x() + 0.5 * cellDimension[0]) * | ||
_integralGaus(localPos_hit.y(), m_cfg.sigma_sharingy, | ||
localPos_neighbor.y() - 0.5 * cellDimension[1], | ||
localPos_neighbor.y() + 0.5 * cellDimension[1]); | ||
|
||
if (edep_cell > 0) { | ||
auto globalPos = m_converter->position(neighbor); | ||
auto hit = sharedHits->create(); | ||
hit.setCellID(neighbor); | ||
hit.setEDep(edep_cell); | ||
hit.setTime(time); | ||
hit.setPosition({globalPos.x(), globalPos.y(), globalPos.z()}); | ||
hit.setMomentum({momentum.x, momentum.y, momentum.z}); | ||
} | ||
} | ||
} | ||
} // LGADChargeSharing:process | ||
|
||
void LGADChargeSharing::_findAllNeighborsInSensor( | ||
dd4hep::rec::CellID hitCell, std::vector<dd4hep::rec::CellID>& answer, | ||
std::unordered_set<dd4hep::rec::CellID>& dp) const { | ||
// search all neighbors with DFS | ||
answer.push_back(hitCell); | ||
dp.insert(hitCell); | ||
|
||
for(const auto& field : m_cfg.neighbor_fields) { | ||
// searchDir should either be +1 or -1 | ||
for(int searchDir = -1; searchDir <= 1; searchDir += 2) { | ||
auto fieldID = m_decoder->get(hitCell, field); | ||
auto testCell = hitCell; | ||
try { | ||
m_decoder->set(testCell, field, fieldID + searchDir); | ||
} catch (const std::runtime_error& err) { | ||
// catch overflow error | ||
// ignore if invalid position ID | ||
continue; | ||
} | ||
|
||
// check if new cellID really exists | ||
try { | ||
auto pos = m_converter->position(testCell); | ||
if (testCell != m_converter->cellID(pos)) | ||
continue; | ||
} catch (const std::invalid_argument& err) { | ||
// Ignore CellID that is invalid | ||
continue; | ||
} | ||
|
||
// only look for cells that have not been searched | ||
if (dp.find(testCell) == dp.end()) { | ||
if (_is_same_sensor(hitCell, testCell)) { | ||
// inside the same sensor | ||
this->_findAllNeighborsInSensor(testCell, answer, dp); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
double LGADChargeSharing::_integralGaus(double mean, double sd, double low_lim, | ||
double up_lim) const { | ||
// return integral Gauss(mean, sd) dx from x = low_lim to x = up_lim | ||
// default value is set when sd = 0 | ||
double up = mean > up_lim ? -0.5 : 0.5; | ||
double low = mean > low_lim ? -0.5 : 0.5; | ||
if (sd > 0) { | ||
up = -0.5 * std::erf(std::sqrt(2) * (mean - up_lim) / sd); | ||
low = -0.5 * std::erf(std::sqrt(2) * (mean - low_lim) / sd); | ||
} | ||
return up - low; | ||
} | ||
|
||
dd4hep::Position LGADChargeSharing::_cell2LocalPosition(const dd4hep::rec::CellID& cell) const { | ||
auto position = m_converter->position(cell); // global position | ||
return this->_global2Local(position); | ||
} | ||
|
||
dd4hep::Position LGADChargeSharing::_global2Local(const dd4hep::Position& pos) const { | ||
auto geoManager = m_detector->world().volume()->GetGeoManager(); | ||
auto node = geoManager->FindNode(pos.x(), pos.y(), pos.z()); | ||
auto currMatrix = geoManager->GetCurrentMatrix(); | ||
|
||
double g[3], l[3]; | ||
pos.GetCoordinates(g); | ||
currMatrix->MasterToLocal(g, l); | ||
dd4hep::Position position; | ||
position.SetCoordinates(l); | ||
return position; | ||
} | ||
|
||
} // namespace eicrecon |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
// SPDX-License-Identifier: LGPL-3.0-or-later | ||
// Copyright (C) 2024 Chun Yuen Tsang, Prithwish Tribedy | ||
// | ||
// Spread energy deposition from one strip to neighboring strips within sensor boundaries | ||
|
||
#pragma once | ||
|
||
#include <DD4hep/IDDescriptor.h> | ||
#include <DD4hep/Objects.h> | ||
#include <DDRec/CellIDPositionConverter.h> | ||
#include <DDSegmentation/BitFieldCoder.h> | ||
#include <algorithms/algorithm.h> | ||
#include <edm4hep/SimTrackerHitCollection.h> | ||
#include <functional> | ||
#include <string> | ||
#include <string_view> | ||
#include <unordered_set> | ||
#include <vector> | ||
|
||
#include "DD4hep/Detector.h" | ||
#include "algorithms/digi/LGADChargeSharingConfig.h" | ||
#include "algorithms/interfaces/WithPodConfig.h" | ||
|
||
namespace eicrecon { | ||
|
||
using LGADChargeSharingAlgorithm = | ||
algorithms::Algorithm<algorithms::Input<edm4hep::SimTrackerHitCollection>, | ||
algorithms::Output<edm4hep::SimTrackerHitCollection>>; | ||
|
||
class LGADChargeSharing : public LGADChargeSharingAlgorithm, | ||
public WithPodConfig<LGADChargeSharingConfig> { | ||
|
||
public: | ||
LGADChargeSharing(std::string_view name) | ||
: LGADChargeSharingAlgorithm{name, {"TOFBarrelHits"}, {"TOFBarrelSharedHits"}, ""} {}; | ||
|
||
void init() final; | ||
void process(const Input&, const Output&) const final; | ||
|
||
private: | ||
void _findAllNeighborsInSensor(dd4hep::rec::CellID hitCell, | ||
std::vector<dd4hep::rec::CellID>& answer, | ||
std::unordered_set<dd4hep::rec::CellID>& dp) const; | ||
double _integralGaus(double mean, double sd, double low_lim, double up_lim) const; | ||
dd4hep::Position _cell2LocalPosition(const dd4hep::rec::CellID& cell) const; | ||
dd4hep::Position _global2Local(const dd4hep::Position& pos) const; | ||
|
||
const dd4hep::DDSegmentation::BitFieldCoder* m_decoder = nullptr; | ||
const dd4hep::Detector* m_detector = nullptr; | ||
const dd4hep::rec::CellIDPositionConverter* m_converter = nullptr; | ||
dd4hep::IDDescriptor m_idSpec; | ||
|
||
// helper function to find neighbors | ||
std::function<bool(const dd4hep::rec::CellID &id1, const dd4hep::rec::CellID &id2)> _is_same_sensor; | ||
|
||
}; | ||
|
||
} // namespace eicrecon |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// SPDX-License-Identifier: LGPL-3.0-or-later | ||
// Copyright (C) 2024 Souvik Paul | ||
|
||
#pragma once | ||
|
||
#include <DD4hep/DD4hepUnits.h> | ||
|
||
namespace eicrecon { | ||
|
||
struct LGADChargeSharingConfig { | ||
// Parameters of AC-LGAD signal generation | ||
double sigma_sharingx; | ||
double sigma_sharingy; | ||
|
||
std::string readout; | ||
std::string same_sensor_condition; | ||
std::vector<std::string> neighbor_fields; | ||
}; | ||
|
||
} // namespace eicrecon |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
// SPDX-License-Identifier: LGPL-3.0-or-later | ||
// Copyright (C) 2024 Souvik Paul, Chun Yuen Tsang, Prithwish Tribedy | ||
// Special Acknowledgement: Kolja Kauder | ||
// | ||
// Convert ADC pulses from LGADPulseGeneration into ADC and TDC values | ||
|
||
#include <podio/RelationRange.h> | ||
#include <stdlib.h> | ||
#include <algorithm> | ||
#include <cmath> | ||
#include <gsl/pointers> | ||
#include <limits> | ||
#include <vector> | ||
|
||
#include "LGADPulseDigitization.h" | ||
#include "algorithms/digi/LGADPulseDigitizationConfig.h" | ||
|
||
namespace eicrecon { | ||
|
||
void LGADPulseDigitization::process(const LGADPulseDigitization::Input& input, | ||
const LGADPulseDigitization::Output& output) const { | ||
const auto [simhits] = input; | ||
auto [rawhits] = output; | ||
|
||
double thres = m_cfg.t_thres; | ||
int adc_range = m_cfg.adc_range; | ||
|
||
for (const auto& pulse : *simhits) { | ||
double intersectionX = 0.0; | ||
int tdc = std::numeric_limits<int>::max(); | ||
int adc = 0; | ||
double V = 0.0; | ||
|
||
int time_bin = 0; | ||
double adc_prev = 0; | ||
double time_interval = pulse.getInterval(); | ||
auto adcs = pulse.getAdcCounts(); | ||
double n_EICROC_cycle = static_cast<int>(std::floor(pulse.getTime()/m_cfg.tMax + 1e-3)); | ||
for (const auto adc : adcs) { | ||
if (adc_prev >= thres && adc <= thres) { | ||
tdc = time_bin + n_EICROC_cycle * m_cfg.tdc_range; | ||
} | ||
if (std::abs(adc) > std::abs(V)) // To get peak of the Analog signal | ||
V = adc; | ||
adc_prev = adc; | ||
++time_bin; | ||
} | ||
|
||
// limit the range of adc values | ||
adc = std::min(static_cast<double>(adc_range), std::round(-V)); | ||
// only store valid hits | ||
if (tdc < std::numeric_limits<int>::max()) | ||
rawhits->create(pulse.getCellID(), adc, tdc); | ||
//----------------------------------------------------------- | ||
} | ||
} // LGADPulseDigitization:process | ||
} // namespace eicrecon |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
// SPDX-License-Identifier: LGPL-3.0-or-later | ||
// Copyright (C) 2024 Souvik Paul, Chun Yuen Tsang, Prithwish Tribedy | ||
// Special Acknowledgement: Kolja Kauder | ||
// | ||
// Convert ADC pulses from LGADPulseGeneration into ADC and TDC values | ||
|
||
#pragma once | ||
|
||
#include <algorithms/algorithm.h> | ||
#include <edm4eic/RawTrackerHitCollection.h> | ||
#include <edm4hep/RawTimeSeriesCollection.h> | ||
#include <string> | ||
#include <string_view> | ||
|
||
#include "algorithms/digi/LGADPulseDigitizationConfig.h" | ||
#include "algorithms/interfaces/WithPodConfig.h" | ||
|
||
namespace eicrecon { | ||
|
||
using LGADPulseDigitizationAlgorithm = | ||
algorithms::Algorithm<algorithms::Input<edm4hep::RawTimeSeriesCollection>, | ||
algorithms::Output<edm4eic::RawTrackerHitCollection>>; | ||
|
||
class LGADPulseDigitization : public LGADPulseDigitizationAlgorithm, | ||
public WithPodConfig<LGADPulseDigitizationConfig> { | ||
|
||
public: | ||
LGADPulseDigitization(std::string_view name) | ||
: LGADPulseDigitizationAlgorithm{name, {"LGADPulse"}, {"ADCTDCOutput"}, {}} {} | ||
void init(){}; | ||
void process(const Input&, const Output&) const final; | ||
}; | ||
|
||
} // namespace eicrecon |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
// SPDX-License-Identifier: LGPL-3.0-or-later | ||
// Copyright (C) 2024 Souvik Paul | ||
|
||
#pragma once | ||
|
||
#include <DD4hep/DD4hepUnits.h> | ||
|
||
namespace eicrecon { | ||
|
||
struct LGADPulseDigitizationConfig { | ||
int adc_bit = 8; | ||
int tdc_bit = 10; | ||
// total number of TDC/ADC values | ||
// Since digitizer starts at zero, max ADC value = adc_range - 1 | ||
// Similar for TDC | ||
int adc_range = std::pow(2, adc_bit); | ||
int tdc_range = std::pow(2, tdc_bit); | ||
|
||
|
||
double t_thres = -0.1 * adc_range; // TDC value = time when pulse exceed t_thres. Negative because LGAD voltage is negative when hit | ||
// period of the sensor clock. Time internal to sensor will all be digitized to integer multiple | ||
// of tInterval | ||
double tMax = 25 * dd4hep::ns; // 25 ns is the period of 40MHz EIC clock | ||
}; | ||
|
||
} // namespace eicrecon |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will currently produce multiple hits for the edge cases where the analogue signal is above threshold on both sides of a 25ns boundary. This is (almost certainly) not going to be how the electronics works but hopefully won't cause issues at the moment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are correct. In the current implementation, if a pulse crosses the threshold very close to the 25 ns boundary, it will result in two hits: one with the correct TDC but incorrect ADC, and the other with the incorrect TDC but correct ADC. As you've rightly pointed out, this occurs because the time when the pulse crosses the threshold and the location of the pulse peak fall into different 25 ns windows.
I anticipated this issue and briefly mentioned it in my reply on December 20. However, I didn't take any further action because, as frustrating as it sounds, all the experts I consulted are also unsure about what will happen in such edge cases. The electronics are still under development, and I don't think anyone knows how this will behave in real-world scenarios.
I believe the best course of action is to document this behavior so that it can be addressed more accurately once we have more information. For now, I believe this is good enough as a reasonable first step toward digital simulation.