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 35 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
35 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
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
30 changes: 30 additions & 0 deletions src/algorithms/digi/BTOFHitDigiConfig.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
// Copyright (C) 2024 Souvik Paul

#pragma once

#include <DD4hep/DD4hepUnits.h>

namespace eicrecon {

struct BTOFHitDigiConfig {
// 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
// unsigned int pedMeanADC{0};
// double pedSigmaADC{0};
double resolutionTDC{1};
double resolutionADC{1};

// Parameters of AC-LGAD signal generation - Added by Souvik
double gain = 80;
double risetime = 0.45; // 0.02; //in ns
double sigma_analog = 0.293951;
double sigma_sharingx = 0.1;
double sigma_sharingy = 0.5;
double Vm = -1e-4 * gain;
double t_thres = 0.1 * Vm;
};

} // namespace eicrecon
180 changes: 180 additions & 0 deletions src/algorithms/tracking/BTOFHitReconstruction.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

#include "BTOFHitReconstruction.h"

#include <Evaluator/DD4hepUnits.h>
#include <Math/GenVector/Cartesian3D.h>
#include <Math/GenVector/DisplacementVector3D.h>
#include <edm4eic/Cov3f.h>
#include <edm4eic/CovDiag3f.h>
#include <edm4hep/Vector3f.h>
#include <fmt/core.h>
#include <iterator>
#include <spdlog/common.h>
#include <stddef.h>
#include <utility>
#include <vector>

#include "TMatrixT.h"

namespace eicrecon {

void BTOFHitReconstruction::init(const dd4hep::rec::CellIDPositionConverter* converter,
const dd4hep::Detector* detector,
std::shared_ptr<spdlog::logger>& logger) {

m_log = logger;

m_converter = converter;
m_detector = detector;
}

dd4hep::rec::CellID BTOFHitReconstruction::getDetInfos(const dd4hep::rec::CellID& id) {
// retrieve segmentation class if that hasn't been done
if (!m_decoder) {
const auto det = m_converter->findContext(id)->element;
auto readout = m_converter->findReadout(det);
auto seg = readout.segmentation();
m_decoder = seg.decoder();
}

// CellID for BarrelTOF is composed of 6 parts
// system, layer, module, sensor, x, y
// If we fix x and y to zero, what remains will be the detector information only
auto id_return = id;
m_decoder->set(id_return, "x", 0);
m_decoder->set(id_return, "y", 0);
return id_return;
}

std::unique_ptr<edm4eic::TrackerHitCollection>
BTOFHitReconstruction::process(const edm4eic::RawTrackerHitCollection& TDCADC_hits) {
using dd4hep::mm;

auto rec_hits{std::make_unique<edm4eic::TrackerHitCollection>()};

// collection of ADC values from all sensors
std::unordered_map<dd4hep::rec::CellID, std::vector<HitInfo>> hitsBySensors;

for (const auto& TDCADC_hit : TDCADC_hits) {

auto id = TDCADC_hit.getCellID();

// Get position and dimension
auto pos = m_converter->position(id);
// Get sensors info
auto detID = this->getDetInfos(id);
hitsBySensors[detID].emplace_back(pos.x(), pos.y(), pos.z(), int(TDCADC_hit.getCharge()),
int(TDCADC_hit.getTimeStamp()), id);
}

auto geoManager = m_detector->world().volume()->GetGeoManager();

for (const auto& sensor : hitsBySensors) {
// INSERT clustering algorithm for each sensors here
// Right now I just perform a simple average over all hits in a sensors
// Will be problematic near the edges, but it's just an illustration
double ave_x = 0, ave_y = 0, ave_z = 0;
double tot_charge = 0;
const auto& hits = sensor.second;
// find cellID for the cell with maximum ADC value within a sensor
// I don't know why you need cellID for reconstructed hits, but we'll do it anyway
auto id = hits[0].id;
auto curr_adc = hits[0].adc;
auto first_tdc = hits[0].tdc;
double maxADC_x = hits[0].x;
double maxADC_y = hits[0].y;
double maxADC_z = hits[0].z;

for (const auto& hit : hits) {
// weigh all hits by ADC value
ave_x += hit.adc * hit.x;
ave_y += hit.adc * hit.y;
ave_z += hit.adc * hit.z;

tot_charge += hit.adc;
if (hit.adc > curr_adc) {
maxADC_x = hit.x;
maxADC_y = hit.y;
maxADC_z = hit.z;
curr_adc = hit.adc;
id = hit.id;
}
first_tdc = std::min(first_tdc, hit.tdc);
}

ave_x /= tot_charge;
ave_y /= tot_charge;
ave_z /= tot_charge;

auto cellSize = m_converter->cellDimensions(id);

/** NVM. covariance is defined in sensor frame
* but the central position is defined in global frame
// get rotation matrix
auto node = geoManager -> FindNode(hits[0].x, hits[0].y, hits[0].z);
auto currMatrix = geoManager -> GetCurrentMatrix();
auto rotMatrixElements = currMatrix -> GetRotationMatrix();

// rotMatrix transforms local coordinates to global coordinates
// see line 342 of https://root.cern.ch/doc/master/TGeoMatrix_8cxx_source.html#l00342
TMatrixT<double> rot(3, 3, rotMatrixElements);
TMatrixT<double> rotT(3, 3);
rotT.Transpose(rot);

// loop through each sensors for Hit information
TMatrixT<double> varLocal(3, 3);
for(int i = 0; i < 3; ++i)
for(int j = 0; j < 3; ++j)
varLocal[i][j] = 0;


varLocal[0][0] = cellSize[0]*cellSize[0] / mm / mm / 12.; // final division by 12 because I
assumed uniform distribution varLocal[1][1] = cellSize[1]*cellSize[1] / mm / mm / 12.; // Std.
dev of uniformation = width/sqrt(12) varLocal[2][2] = 0;

// transform variance. see
https://robotics.stackexchange.com/questions/2556/how-to-rotate-covariance auto varGlobal =
rot*varLocal*rotT;
*/

// adc to charge
float charge = tot_charge * m_cfg.c_slope + m_cfg.c_intercept;
// TDC to time
float time = first_tdc * m_cfg.t_slope + m_cfg.t_intercept;
// >oO trace
double varX = cellSize[0] / mm;
varX *= varX;
double varY = cellSize[1] / mm;
varY *= varY;
double varZ = cellSize.size() > 2? cellSize[2] / mm : 0;
varZ *= varZ;

if (m_cfg.use_ave) {
rec_hits->create(id,
edm4hep::Vector3f{static_cast<float>(ave_x / mm),
static_cast<float>(ave_y / mm),
static_cast<float>(ave_z / mm)}, // mm
edm4eic::CovDiag3f{varX, varY, varZ}, // should be the covariance of position
time, // ns
0.0F, // covariance of time
charge, // total ADC sum
0.0F); // Error on the energy
} else {
rec_hits->create(id,
edm4hep::Vector3f{static_cast<float>(maxADC_x / mm),
static_cast<float>(maxADC_y / mm),
static_cast<float>(maxADC_z / mm)}, // mm
edm4eic::CovDiag3f{varX, varY, varZ}, // should be the covariance of position
time, // ns
0.0F, // covariance of time
charge, // total ADC sum
0.0F); // Error on the energy
}
}

return std::move(rec_hits);
}

} // namespace eicrecon
50 changes: 50 additions & 0 deletions src/algorithms/tracking/BTOFHitReconstruction.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
// Copyright (C) 2024 Chun Yuen Tsang

#pragma once

#include <DD4hep/Detector.h>
#include <DDRec/CellIDPositionConverter.h>
#include <edm4eic/RawTrackerHitCollection.h>
#include <edm4eic/TrackerHitCollection.h>
#include <memory>
#include <spdlog/logger.h>

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

namespace eicrecon {

/**
* Produces edm4eic::TrackerHit with geometric info from edm4eic::RawTrackerHit
*/
class BTOFHitReconstruction : public WithPodConfig<BTOFHitReconstructionConfig> {

public:
/// Once in a lifetime initialization
void init(const dd4hep::rec::CellIDPositionConverter* converter, const dd4hep::Detector* detector,
std::shared_ptr<spdlog::logger>& logger);

/// Processes RawTrackerHit and produces a TrackerHit
std::unique_ptr<edm4eic::TrackerHitCollection>
process(const edm4eic::RawTrackerHitCollection& TDCADC_hits);

private:
struct HitInfo {
double x, y, z;
int adc, tdc;
dd4hep::rec::CellID id;
};
dd4hep::rec::CellID getDetInfos(const dd4hep::rec::CellID& id);
/** algorithm logger */
std::shared_ptr<spdlog::logger> m_log;

/// Cell ID position converter
const dd4hep::rec::CellIDPositionConverter* m_converter = nullptr;

/// fetch sensor information from cellID
const dd4hep::DDSegmentation::BitFieldCoder* m_decoder = nullptr;

const dd4hep::Detector* m_detector = nullptr;
};
} // namespace eicrecon
16 changes: 16 additions & 0 deletions src/algorithms/tracking/BTOFHitReconstructionConfig.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
// Copyright (C) 2024 Chun Yuen Tsang

#pragma once

namespace eicrecon {
struct BTOFHitReconstructionConfig {
// parameters that convert ADC to EDep
double c_slope = 3.86976e-7, c_intercept=2.42716e-5;
// parameters that convert TDC to hit time (ns)
double t_slope = 0.0197305, t_intercept = 0.208047;
// if false, we use weighted ADC averages for position.
// By default, the position is just the center of cell with max ADC value in a sensor
bool use_ave = true;
};
}
Loading
Loading