Skip to content
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
wants to merge 72 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
72 commits
Select commit Hold shift + click to select a range
8123783
First commit of BTOF digitization code!
ssedd1123 Jul 18, 2024
2332d18
Update BTOFHitDigi.cc
eicsouvik Jul 19, 2024
4b907cb
Update BTOFHitDigi.h
eicsouvik Jul 19, 2024
204d472
Update BTOFHitDigi.cc
eicsouvik Jul 19, 2024
1b08022
Merge pull request #3 from eicsouvik/patch-1
ssedd1123 Jul 19, 2024
5e011e1
Merge pull request #2 from eicsouvik/patch-2
ssedd1123 Jul 19, 2024
5e17954
Merge pull request #1 from eicsouvik/patch-3
ssedd1123 Jul 19, 2024
9fbe640
Changed the algorithm of BarrelTOFNeighborFinder so it's more intuita…
Jul 19, 2024
171ffd4
Merge branch 'main' of https://github.com/ssedd1123/EICrecon
Jul 19, 2024
52a9b33
Changed spread calculation. Originally the spread were estimated with…
Jul 19, 2024
54024b6
Fixed bugs when sensor ID from barrelTOFNeighborFinder gives wrong ne…
ssedd1123 Jul 25, 2024
5e1cec4
Merge branch 'eic:main' into main
ssedd1123 Aug 3, 2024
40abca0
Updated BTOF neighbor finder. To be used with updated epic geometry w…
ssedd1123 Aug 3, 2024
72edf8b
Merge branch 'eic:main' into main
ssedd1123 Aug 26, 2024
df48d16
Merge branch 'eic:main' into main
ssedd1123 Aug 26, 2024
1d3c040
Merge branch 'eic:main' into main
ssedd1123 Aug 26, 2024
1adfd02
Sync fork.
ssedd1123 Sep 24, 2024
f373972
Added missing closing parenthesis.
ssedd1123 Sep 24, 2024
0725492
Use more realistic charge sharing parameters and bug fix on ADC heights.
ssedd1123 Sep 27, 2024
a451aed
Merge branch 'main' of https://github.com/ssedd1123/EICrecon
ssedd1123 Sep 27, 2024
ce9122d
Fixed incorrect threshold for ADC TDC.
ssedd1123 Oct 8, 2024
08c83e6
Merge branch 'eic:main' into main
ssedd1123 Oct 14, 2024
350ca3b
Move digitization code to the main branch.
ssedd1123 Oct 15, 2024
4f892ee
Formated files.
ssedd1123 Oct 15, 2024
8d8a12a
Included config content in parameter ref.
ssedd1123 Oct 15, 2024
d260635
Merge remote-tracking branch 'new-origin/main' into pr/BTOF-digitizat…
ssedd1123 Oct 15, 2024
875f0f4
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 15, 2024
b12ee38
Fixed BTOF reco uncertainty estimation bug.
ssedd1123 Oct 15, 2024
0d91db5
Merge branch 'main' into pr/BTOF-digitization-clusterization
ssedd1123 Oct 21, 2024
34f4daa
Removed reconstruction for later pull request. Breaks TOF digi into t…
ssedd1123 Oct 23, 2024
9ab01c9
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 23, 2024
4cf1216
Removed legacy modification to JEventProcessorPODIO.cc
ssedd1123 Oct 23, 2024
83c9b88
Merge branch 'pr/BTOF-digitization-clusterization' of https://github.…
ssedd1123 Oct 23, 2024
deaf63c
Merge branch 'main' into pr/BTOF-digitization-clusterization
ssedd1123 Oct 23, 2024
14889de
Fixed bugs on charge sharing calculation. It was assumed that all gea…
ssedd1123 Oct 23, 2024
7474a52
Merge branch 'main' into pr/BTOF-digitization-clusterization
ssedd1123 Oct 23, 2024
569090d
Moved algorithms away from src/detectors.
ssedd1123 Oct 23, 2024
33c6587
Fix spelling mistakes to make codespell happy.
ssedd1123 Oct 24, 2024
b28d49f
Removed unnecessary header files.
ssedd1123 Oct 25, 2024
8f01587
Trigger Build
ssedd1123 Oct 25, 2024
595952d
Merge branch 'main' into pr/BTOF-digitization-clusterization
ssedd1123 Nov 1, 2024
a4b5211
Update src/algorithms/digi/BTOFChargeSharing.cc
ssedd1123 Nov 1, 2024
f4f3204
Update src/algorithms/digi/TOFPulseDigitization.cc
ssedd1123 Nov 1, 2024
76fccd8
Update src/algorithms/digi/TOFPulseDigitization.cc
ssedd1123 Nov 1, 2024
310c510
Update src/algorithms/digi/BTOFChargeSharing.cc
ssedd1123 Nov 1, 2024
6e44318
Update src/algorithms/digi/TOFPulseDigitization.h
ssedd1123 Nov 1, 2024
7ecc458
Update src/algorithms/digi/TOFPulseGeneration.h
ssedd1123 Nov 1, 2024
41614b8
Update src/algorithms/digi/BTOFChargeSharing.cc
ssedd1123 Nov 1, 2024
7ca28d3
Update src/algorithms/digi/BTOFChargeSharing.h
ssedd1123 Nov 1, 2024
576055c
Update src/algorithms/digi/BTOFChargeSharing.cc
ssedd1123 Nov 1, 2024
232a3ef
Replaced magic number in BTOFChargeSharing with the correct unit.
ssedd1123 Nov 1, 2024
8043bff
Make clang-tidy-iwyu happy.
ssedd1123 Nov 1, 2024
837900a
Trigger Build
ssedd1123 Nov 2, 2024
e51c007
Update src/algorithms/digi/TOFPulseGeneration.cc
ssedd1123 Nov 2, 2024
1d3f592
Update src/algorithms/digi/TOFPulseGeneration.cc
ssedd1123 Nov 2, 2024
3e0afdc
Make clang-tidy-iwyu happy.
ssedd1123 Nov 2, 2024
89452f4
TOFPulseGeneration_factory.h: mixedCase for parameter names
veprbl Nov 4, 2024
d0040c6
TOFPulseDigitization_factory.h: ditto
veprbl Nov 4, 2024
bbc6ab0
TOFPulseDigitization_factory.h: missed
veprbl Nov 4, 2024
5664496
BTOFChargeSharing_factory.h: ditto
veprbl Nov 4, 2024
00d1890
TOFHitDigiConfig.h: rm unused suff
veprbl Nov 4, 2024
3af27a9
BTOFChargeSharing_factory.h: need algorithmsInit
veprbl Nov 4, 2024
cb3209d
TOFPulseDigitization_factory.h: ditto
veprbl Nov 4, 2024
6ba7bab
TOFPulseGeneration_factory.h: ditto
veprbl Nov 4, 2024
fa7ad55
BTOFChargeSharing.h: remove cache stuff for now
veprbl Nov 4, 2024
5f092d4
Merge branch 'main' into pr/BTOF-digitization-clusterization
veprbl Nov 5, 2024
ef00944
JEventProcessorPODIO.cc: add TOFBarrelADCTDC
veprbl Nov 5, 2024
a745e2b
Update src/services/io/podio/JEventProcessorPODIO.cc
veprbl Nov 5, 2024
dd95d6b
Added tests for TOFPulseDigitization and TOFPulseGeneration.
ssedd1123 Nov 7, 2024
d073d6b
Removed unnecessary credits.
ssedd1123 Nov 7, 2024
6e34d8a
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 7, 2024
22c9fe4
Merge branch 'main' into pr/BTOF-digitization-clusterization
ssedd1123 Nov 7, 2024
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
180 changes: 180 additions & 0 deletions src/algorithms/digi/BTOFChargeSharing.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
// 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 <Math/SpecFuncMathCore.h>
#include <TGeoManager.h>
#include <TGeoMatrix.h>
#include <TGeoVolume.h>
#include <algorithms/geo.h>
#include <edm4hep/Vector3d.h>
#include <edm4hep/Vector3f.h>
#include <gsl/pointers>
#include <stdexcept>
#include <utility>
#include <vector>

#include "BTOFChargeSharing.h"
#include "DD4hep/Detector.h"
#include "TMath.h"
#include "algorithms/digi/TOFHitDigiConfig.h"


namespace eicrecon {

void BTOFChargeSharing::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();
}

void BTOFChargeSharing::process(const BTOFChargeSharing::Input& input,
const BTOFChargeSharing::Output& output) const {
const auto [simhits] = input;
auto [sharedHits] = output;
std::shared_ptr<std::vector<dd4hep::rec::CellID>> neighbors;

for(const auto & hit : *simhits) {
auto cellID = hit.getCellID();

if(!neighbors){
std::unordered_set<dd4hep::rec::CellID> dp;
neighbors = std::make_shared<std::vector<dd4hep::rec::CellID>>();
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});
}
}
}
} // BTOFChargeSharing:process


void BTOFChargeSharing::_findAllNeighborsInSensor(
dd4hep::rec::CellID hitCell, std::shared_ptr<std::vector<dd4hep::rec::CellID>>& answer,
std::unordered_set<dd4hep::rec::CellID>& dp) const {
// use MST to find all neighbor within a sensor
// I can probably write down the formula by hand, but why do things manually when computer do
// everything for you?
const std::vector<std::pair<int, int>> searchDirs{{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
answer->push_back(hitCell);
dp.insert(hitCell);

auto sensorID = this -> _getSensorID(hitCell);
auto xID = m_decoder->get(hitCell, "x");
auto yID = m_decoder->get(hitCell, "y");
for (const auto& dir : searchDirs) {
auto testCell = hitCell;
try {
m_decoder->set(testCell, "x", xID + dir.first);
m_decoder->set(testCell, "y", yID + dir.second);
} catch (const std::runtime_error& err) {
// catch overflow error
// ignore if invalid position ID
continue;
}

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()) {
auto testSensorID = _getSensorID(testCell);
if (testSensorID == sensorID) {
// inside the same sensor
this->_findAllNeighborsInSensor(testCell, answer, dp);
}
}
}
}

const dd4hep::rec::CellID
BTOFChargeSharing::_getSensorID(const dd4hep::rec::CellID& hitCell) const {
// fix x-y, what you left with are ids that corresponds to sensor info
// cellID may change when position changes.
auto sensorID = hitCell; //_converter -> cellID(_converter -> position(hitCell));
m_decoder->set(sensorID, "x", 0);
m_decoder->set(sensorID, "y", 0);

return sensorID;
}

double BTOFChargeSharing::_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 BTOFChargeSharing::_cell2LocalPosition(const dd4hep::rec::CellID& cell) const {
auto position = m_converter -> position(cell); // global position
return this -> _global2Local(position);
}

dd4hep::Position BTOFChargeSharing::_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
55 changes: 55 additions & 0 deletions src/algorithms/digi/BTOFChargeSharing.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// 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/Objects.h>
#include <DDRec/CellIDPositionConverter.h>
#include <DDSegmentation/BitFieldCoder.h>
#include <algorithms/algorithm.h>
#include <edm4hep/SimTrackerHitCollection.h>
#include <memory>
#include <string>
#include <string_view>
#include <unordered_set>
#include <vector>

#include "DD4hep/Detector.h"
#include "algorithms/digi/TOFHitDigiConfig.h"
#include "algorithms/interfaces/WithPodConfig.h"

namespace eicrecon {

using BTOFChargeSharingAlgorithm =
algorithms::Algorithm<algorithms::Input<edm4hep::SimTrackerHitCollection>,
algorithms::Output<edm4hep::SimTrackerHitCollection>>;

class BTOFChargeSharing : public BTOFChargeSharingAlgorithm,
public WithPodConfig<TOFHitDigiConfig> {

public:
BTOFChargeSharing(std::string_view name) : BTOFChargeSharingAlgorithm{name,
{"TOFBarrelHits"},
{"TOFBarrelSharedHits"},
""} {};

void init() final;
void process(const Input&, const Output&) const final;
protected:
void _findAllNeighborsInSensor(dd4hep::rec::CellID hitCell,
std::shared_ptr<std::vector<dd4hep::rec::CellID>>& answer,
std::unordered_set<dd4hep::rec::CellID>& dp) const;
const dd4hep::rec::CellID _getSensorID(const dd4hep::rec::CellID& hitCell) 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;
ssedd1123 marked this conversation as resolved.
Show resolved Hide resolved

const dd4hep::DDSegmentation::BitFieldCoder* m_decoder = nullptr;
const dd4hep::Detector* m_detector = nullptr;
const dd4hep::rec::CellIDPositionConverter* m_converter = nullptr;

};

} // namespace eicrecon
40 changes: 40 additions & 0 deletions src/algorithms/digi/TOFHitDigiConfig.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
// Copyright (C) 2024 Souvik Paul

#pragma once

#include <DD4hep/DD4hepUnits.h>

namespace eicrecon {

struct TOFHitDigiConfig {
// single hit energy deposition threshold
double threshold{1.0 * dd4hep::keV};
double tRes = 0.1; /// TODO 8 of what units??? Same TODO in juggler. Probably [ns]
// digitization settings
double resolutionTDC{1};
double resolutionADC{1};

// Parameters of AC-LGAD signal generation
double gain = 80;
double risetime = 0.45; // 0.02; //in ns
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remind me: what's the 0.02 here?

double sigma_analog = 0.293951;
double sigma_sharingx = 0.1;
double sigma_sharingy = 0.5;
double Vm = -1e-4 * dd4hep::GeV; // Vm = voltage maximum. When EDep = 1e-4 GeV, voltage corresponds to ADC = adc_max
double t_thres = 0.1 * Vm;
double ignore_thres = 0.01 * Vm; // If EDep below this value, digitization for the cell will be ignored. Speed up calculation
//
double tMin = 0.1;
double tMax = 25;// 25 ns is the period of 40MHz EIC clock
int total_time = ceil(tMax - tMin);
int adc_bit = 8;
int tdc_bit = 10;

int adc_range = pow(2, adc_bit);
int tdc_range = pow(2, tdc_bit);

std::string readout = "TOFBarrelHits";
};

} // namespace eicrecon
65 changes: 65 additions & 0 deletions src/algorithms/digi/TOFPulseDigitization.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// 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 TOFPulseGeneration into ADC and TDC values

#include <math.h>
#include <podio/RelationRange.h>
#include <stdlib.h>
#include <algorithm>
#include <gsl/pointers>
#include <limits>
#include <vector>

#include "TOFPulseDigitization.h"
#include "algorithms/digi/TOFHitDigiConfig.h"


namespace eicrecon {

void TOFPulseDigitization::process(const TOFPulseDigitization::Input& input,
const TOFPulseDigitization::Output& output) const {
const auto [simhits] = input;
auto [rawhits] = output;

double thres = m_cfg.t_thres;
// Vm in unit of GeV. When Edep = Vm, ADC = cfg.adc_range-1
double Vm = m_cfg.Vm;
int adc_range = m_cfg.adc_range;

// normalized time threshold
// convert threshold EDep to voltage
double norm_threshold = -thres * adc_range / Vm;

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();
for (const auto adc : adcs) {
if (adc_prev >= norm_threshold && adc <= norm_threshold) {
intersectionX = time_bin*time_interval + time_interval * (norm_threshold - adc_prev) / (adc - adc_prev);
tdc = static_cast<int>(intersectionX / time_interval);
}
if (abs(adc) > 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), round(-V));
// only store valid hits
if (tdc < std::numeric_limits<int>::max())
rawhits->create(pulse.getCellID(), adc, tdc);
//-----------------------------------------------------------

}
} // TOFPulseDigitization:process
} // namespace eicrecon
37 changes: 37 additions & 0 deletions src/algorithms/digi/TOFPulseDigitization.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// 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 TOFPulseGeneration 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/TOFHitDigiConfig.h"
#include "algorithms/interfaces/WithPodConfig.h"

namespace eicrecon {

using TOFPulseDigitizationAlgorithm =
algorithms::Algorithm<algorithms::Input<edm4hep::RawTimeSeriesCollection>,
algorithms::Output<edm4eic::RawTrackerHitCollection>>;

class TOFPulseDigitization : public TOFPulseDigitizationAlgorithm,
public WithPodConfig<TOFHitDigiConfig> {

public:
TOFPulseDigitization(std::string_view name) :
TOFPulseDigitizationAlgorithm{name,
{"TOFBarrelPulse"},
{"TOFBarrelADCTDC"},
{}} {}
void init() {};
void process(const Input&, const Output&) const final;
};

} // namespace eicrecon
Loading
Loading