diff --git a/src/algorithms/digi/EICROCDigitization.cc b/src/algorithms/digi/EICROCDigitization.cc index 4bb9934f3f..e54b457dfb 100644 --- a/src/algorithms/digi/EICROCDigitization.cc +++ b/src/algorithms/digi/EICROCDigitization.cc @@ -26,9 +26,8 @@ void EICROCDigitization::process(const EICROCDigitization::Input& input, int adc_range = m_cfg.adc_range; for (const auto& pulse : *simhits) { - int tdc = std::numeric_limits::max(); - int adc = 0; - double V = 0.0; + int tdc = std::numeric_limits::max(); + int V = 0; int time_bin = 0; double adc_prev = 0; @@ -45,7 +44,7 @@ void EICROCDigitization::process(const EICROCDigitization::Input& input, } // limit the range of adc values - adc = std::min(static_cast(adc_range), std::round(-V)); + int adc = std::min(adc_range, -V); // only store valid hits if (tdc < std::numeric_limits::max()) rawhits->create(pulse.getCellID(), adc, tdc); diff --git a/src/algorithms/reco/LGADHitCalibration.cc b/src/algorithms/reco/LGADHitCalibration.cc new file mode 100644 index 0000000000..8247a7d41e --- /dev/null +++ b/src/algorithms/reco/LGADHitCalibration.cc @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright (C) 2024 Chun Yuen Tsang + +#include "LGADHitCalibration.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "algorithms/reco/LGADHitCalibrationConfig.h" + +namespace eicrecon { + +void LGADHitCalibration::init() { + m_converter = algorithms::GeoSvc::instance().cellIDPositionConverter(); +} + +void LGADHitCalibration::process(const LGADHitCalibration::Input& input, + const LGADHitCalibration::Output& output) const { + using dd4hep::mm; + + const auto [TDCADC_hits] = input; + auto [calibrated_hits] = output; + + for (const auto& TDCADC_hit : *TDCADC_hits) { + + auto id = TDCADC_hit.getCellID(); + + // Get position and dimension + auto pos = m_converter->position(id); + double ADC = TDCADC_hit.getCharge(); + double TDC = TDCADC_hit.getTimeStamp(); + + // adc to charge + double charge = ADC * m_cfg.c_slope + m_cfg.c_intercept; + // TDC to time + float time = TDC * m_cfg.t_slope + m_cfg.t_intercept; + + auto cellSize = m_converter->cellDimensions(id); + // sqrt(12) factor convertes ranges of uniform distribution to it's standard deviation + double varX = cellSize[0] / mm / std::sqrt(12.); + varX *= varX; // square of cell size + double varY = cellSize[1] / mm / std::sqrt(12.); + varY *= varY; + double varZ = cellSize.size() > 2 ? cellSize[2] / mm / std::sqrt(12.) : 0; + varZ *= varZ; + + calibrated_hits->create( + id, + edm4hep::Vector3f{static_cast(pos.x()), static_cast(pos.y()), + static_cast(pos.z())}, + edm4eic::CovDiag3f{varX, varY, varZ}, // should be the covariance of position + time, // ns + 0.0F, // covariance of time + std::max(0., charge), // total ADC sum + 0.0F); // Error on the energy + } +} + +} // namespace eicrecon diff --git a/src/algorithms/reco/LGADHitCalibration.h b/src/algorithms/reco/LGADHitCalibration.h new file mode 100644 index 0000000000..ebb15188f0 --- /dev/null +++ b/src/algorithms/reco/LGADHitCalibration.h @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright (C) 2024 Chun Yuen Tsang + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "LGADHitCalibrationConfig.h" +#include "algorithms/interfaces/WithPodConfig.h" + +namespace eicrecon { + +using LGADHitCalibrationAlgorithm = + algorithms::Algorithm, + algorithms::Output>; + +class LGADHitCalibration : public LGADHitCalibrationAlgorithm, + public WithPodConfig { + +public: + LGADHitCalibration(std::string_view name) + : LGADHitCalibrationAlgorithm{name, {"TOFBarrelADCTDC"}, {"TOFBarrelCalHit"}, ""} {}; + + void init() final; + void process(const Input&, const Output&) const final; + +private: + std::shared_ptr m_log; + + const dd4hep::rec::CellIDPositionConverter* m_converter = nullptr; +}; +} // namespace eicrecon diff --git a/src/algorithms/reco/LGADHitCalibrationConfig.h b/src/algorithms/reco/LGADHitCalibrationConfig.h new file mode 100644 index 0000000000..a667984335 --- /dev/null +++ b/src/algorithms/reco/LGADHitCalibrationConfig.h @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright (C) 2025 Chun Yuen Tsang + +#pragma once + +namespace eicrecon { +struct LGADHitCalibrationConfig { + // 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; +}; +} // namespace eicrecon diff --git a/src/algorithms/reco/LGADHitClusterAssociation.cc b/src/algorithms/reco/LGADHitClusterAssociation.cc new file mode 100644 index 0000000000..2406c1d4e1 --- /dev/null +++ b/src/algorithms/reco/LGADHitClusterAssociation.cc @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright (C) 2024 Chun Yuen Tsang + +#include "LGADHitClusterAssociation.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "algorithms/reco/LGADHitClusterAssociationConfig.h" + +namespace eicrecon { + +void LGADHitClusterAssociation::init() { + auto detector = algorithms::GeoSvc::instance().detector(); + auto seg = detector->readout(m_cfg.readout).segmentation(); + m_converter = algorithms::GeoSvc::instance().cellIDPositionConverter(); + m_decoder = seg.decoder(); +} + +dd4hep::rec::CellID LGADHitClusterAssociation::getSensorInfos(const dd4hep::rec::CellID& id) const { + // 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 sensor information only + auto id_return = id; + m_decoder->set(id_return, "x", 0); + m_decoder->set(id_return, "y", 0); + return id_return; +} + +edm4hep::Vector3f +LGADHitClusterAssociation::_local2Global(const dd4hep::VolumeManagerContext* context, + const edm4hep::Vector2f& locPos) const { + auto nodeMatrix = context->element.nominal().worldTransformation(); + + double g[3], l[3]; + l[0] = locPos.a * dd4hep::mm; + l[1] = locPos.b * dd4hep::mm; + l[2] = 0; + nodeMatrix.LocalToMaster(l, g); + return edm4hep::Vector3f{static_cast(g[0] / dd4hep::mm), + static_cast(g[1] / dd4hep::mm), + static_cast(g[2] / dd4hep::mm)}; +} + +void LGADHitClusterAssociation::process(const LGADHitClusterAssociation::Input& input, + const LGADHitClusterAssociation::Output& output) const { + using dd4hep::mm; + const auto [meas2D_hits, raw_hits] = input; + auto [asso_hits] = output; + + // group raw hit by cell ID + std::unordered_map> cellHitMap; + + for (const auto& meas2D_hit : *meas2D_hits) { + auto cellID = meas2D_hit.getSurface(); + auto time = meas2D_hit.getTime(); + + // sum ADC info + double tot_charge = 0; + // position info + auto locPos = meas2D_hit.getLoc(); + const auto* context = m_converter->findContext(cellID); + auto ave_pos = this->_local2Global(context, locPos); + auto asso_hit = asso_hits->create(cellID, ave_pos, edm4eic::CovDiag3f{0., 0., 0.}, time, 0., + tot_charge, 0.); + cellHitMap[getSensorInfos(asso_hit.getCellID())].push_back(asso_hit); + } + + // sort the tracker hits by time + for (auto& [cellID, hits] : cellHitMap) + std::sort(hits.begin(), hits.end(), + [](const edm4eic::MutableTrackerHit& a, const edm4eic::MutableTrackerHit& b) { + return a.getTime() < b.getTime(); + }); + + // get the associated raw_hits by the closest time + for (const auto& raw_hit : *raw_hits) { + auto time = raw_hit.getTimeStamp() / 1e3; // ps->ns + auto sensorID = getSensorInfos(raw_hit.getCellID()); + auto it = cellHitMap.find(sensorID); + if (it != cellHitMap.end()) { + auto& hits = it->second; + // if t_raw - assoDeltaT < t_hit < t_raw + assoDeltaT, we make the association + auto itVec = std::lower_bound( + hits.begin(), hits.end(), time - m_cfg.assoDeltaT, + [](const edm4eic::MutableTrackerHit& a, double t) { return a.getTime() < t; }); + for (; itVec != hits.end() && itVec->getTime() <= time + m_cfg.assoDeltaT; ++itVec) { + itVec->setRawHit(raw_hit); + } + } + } +} + +} // namespace eicrecon diff --git a/src/algorithms/reco/LGADHitClusterAssociation.h b/src/algorithms/reco/LGADHitClusterAssociation.h new file mode 100644 index 0000000000..85dd9b9e8e --- /dev/null +++ b/src/algorithms/reco/LGADHitClusterAssociation.h @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright (C) 2024 Chun Yuen Tsang + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "LGADHitClusterAssociationConfig.h" +#include "algorithms/interfaces/WithPodConfig.h" + +namespace eicrecon { + +using LGADHitClusterAssociationAlgorithm = algorithms::Algorithm< + algorithms::Input, + algorithms::Output>; + +class LGADHitClusterAssociation : public LGADHitClusterAssociationAlgorithm, + public WithPodConfig { + +public: + LGADHitClusterAssociation(std::string_view name) + : LGADHitClusterAssociationAlgorithm{ + name, {"TOFBarrelClusterHits", "TOFBarrelRawHits"}, {"TOFBarrelRecHits"}, ""} {}; + + void init() final; + void process(const Input&, const Output&) const final; + +private: + dd4hep::rec::CellID getSensorInfos(const dd4hep::rec::CellID& id) const; + edm4hep::Vector3f _local2Global(const dd4hep::VolumeManagerContext* context, + const edm4hep::Vector2f& locPos) const; + + std::shared_ptr m_log; + /// fetch sensor information from cellID + const dd4hep::DDSegmentation::BitFieldCoder* m_decoder = nullptr; + const dd4hep::rec::CellIDPositionConverter* m_converter = nullptr; +}; +} // namespace eicrecon diff --git a/src/algorithms/reco/LGADHitClusterAssociationConfig.h b/src/algorithms/reco/LGADHitClusterAssociationConfig.h new file mode 100644 index 0000000000..e05c8817fa --- /dev/null +++ b/src/algorithms/reco/LGADHitClusterAssociationConfig.h @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright (C) 2025 Chun Yuen Tsang + +#pragma once + +#include + +namespace eicrecon { +struct LGADHitClusterAssociationConfig { + std::string readout = "TOFBarrelHits"; + double assoDeltaT = 1 * edm4eic::unit::ns; +}; +} // namespace eicrecon diff --git a/src/algorithms/reco/LGADHitClustering.cc b/src/algorithms/reco/LGADHitClustering.cc new file mode 100644 index 0000000000..91d65f484f --- /dev/null +++ b/src/algorithms/reco/LGADHitClustering.cc @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright (C) 2024 Chun Yuen Tsang + +#include "LGADHitClustering.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "algorithms/reco/LGADHitClusteringConfig.h" + +namespace eicrecon { + +void LGADHitClustering::init() { + + m_converter = algorithms::GeoSvc::instance().cellIDPositionConverter(); + m_detector = algorithms::GeoSvc::instance().detector(); + m_seg = m_detector->readout(m_cfg.readout).segmentation(); + auto type = m_seg.type(); + m_decoder = m_seg.decoder(); +} + +dd4hep::rec::CellID LGADHitClustering::getSensorInfos(const dd4hep::rec::CellID& id) const { + // 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 sensor information only + auto id_return = id; + m_decoder->set(id_return, "x", 0); + m_decoder->set(id_return, "y", 0); + return id_return; +} + +dd4hep::Position LGADHitClustering::_local2Global(const dd4hep::VolumeManagerContext* context, + const edm4hep::Vector2f& locPos) const { + auto nodeMatrix = context->element.nominal().worldTransformation(); + + double g[3], l[3]; + l[0] = locPos.a * dd4hep::mm; + l[1] = locPos.b * dd4hep::mm; + l[2] = 0; + nodeMatrix.LocalToMaster(l, g); + dd4hep::Position position; + position.SetCoordinates(g); + return position; +} + +void LGADHitClustering::process(const LGADHitClustering::Input& input, + const LGADHitClustering::Output& output) const { + using dd4hep::mm; + + const auto [calibrated_hits] = input; + auto [clusters] = output; + + // collection of ADC values from all sensors and group them by sensor + std::unordered_map> hitsBySensors; + + for (const auto& calibrated_hit : *calibrated_hits) { + + auto id = calibrated_hit.getCellID(); + // Get sensors info + auto sensorID = this->getSensorInfos(id); + hitsBySensors[sensorID].emplace_back(calibrated_hit); + } + + for (const auto& sensor : hitsBySensors) { + auto cluster = clusters->create(); + // Right now the clustering algorithm a simple average over all hits in a sensors + // Will be problematic near the edges, but it's just an illustration + float ave_x = 0, ave_y = 0; + double tot_charge = 0; + const auto& hits = sensor.second; + if (hits.size() == 0) + continue; + // find cellID for the cell with maximum ADC value within a sensor + auto id = hits[0].getCellID(); + auto max_charge = hits[0].getEdep(); + auto earliest_time = hits[0].getTime(); + + ROOT::VecOps::RVec weights; + for (const auto& hit : hits) { + // weigh all hits by ADC value + auto pos = m_seg->position(hit.getCellID()); + if (hit.getEdep() < 0) + error("Edep for hit at cellID{} is negative. Abort!.", hit.getCellID()); + ave_x += hit.getEdep() * pos.x(); + ave_y += hit.getEdep() * pos.y(); + + tot_charge += hit.getEdep(); + if (hit.getEdep() > max_charge) { + max_charge = hit.getEdep(); + id = hit.getCellID(); + } + earliest_time = std::min(earliest_time, hit.getTime()); + cluster.addToHits(hit); + weights.push_back(hit.getEdep()); + } + + weights /= tot_charge; + ave_x /= tot_charge; + ave_y /= tot_charge; + + for (const auto& w : weights) + cluster.addToWeights(w); + + edm4eic::Cov3f covariance; + edm4hep::Vector2f locPos{static_cast(ave_x / mm), static_cast(ave_y / mm)}; + + // CAUTION: surface has to be the cell where the cluster center belongs to + // NOT the cell with MAX ADC value + const auto* context = m_converter->findContext(id); + auto gPos = this->_local2Global(context, locPos); + id = m_converter->cellID(gPos); + + if (!id) + error("Failed to find cellID for cluster center! Does your detector have hole in the middle " + "or somehow concave in shape? This class doesn't work with concave detector."); + + cluster.setSurface(id); + cluster.setLoc(locPos); + cluster.setTime(earliest_time); + cluster.setCovariance(covariance); + } +} + +} // namespace eicrecon diff --git a/src/algorithms/reco/LGADHitClustering.h b/src/algorithms/reco/LGADHitClustering.h new file mode 100644 index 0000000000..1899a81860 --- /dev/null +++ b/src/algorithms/reco/LGADHitClustering.h @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright (C) 2024 Chun Yuen Tsang + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "LGADHitClusteringConfig.h" +#include "algorithms/interfaces/WithPodConfig.h" + +namespace eicrecon { + +using LGADHitClusteringAlgorithm = + algorithms::Algorithm, + algorithms::Output>; + +class LGADHitClustering : public LGADHitClusteringAlgorithm, + public WithPodConfig { + +public: + LGADHitClustering(std::string_view name) + : LGADHitClusteringAlgorithm{name, {"TOFBarrelCalHit"}, {"TOFBarrelRecHit"}, ""} {}; + + void init() final; + void process(const Input&, const Output&) const final; + +private: + dd4hep::rec::CellID getSensorInfos(const dd4hep::rec::CellID& id) const; + dd4hep::Position _local2Global(const dd4hep::VolumeManagerContext* context, + const edm4hep::Vector2f& locPos) const; + + /** algorithm logger */ + std::shared_ptr 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; + + dd4hep::Segmentation m_seg; +}; +} // namespace eicrecon diff --git a/src/algorithms/reco/LGADHitClusteringConfig.h b/src/algorithms/reco/LGADHitClusteringConfig.h new file mode 100644 index 0000000000..8b24e96b8d --- /dev/null +++ b/src/algorithms/reco/LGADHitClusteringConfig.h @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright (C) 2024 Chun Yuen Tsang + +#pragma once + +namespace eicrecon { +struct LGADHitClusteringConfig { + std::string readout = "TOFBarrelHits"; +}; +} // namespace eicrecon diff --git a/src/detectors/BTOF/BTOF.cc b/src/detectors/BTOF/BTOF.cc index 4cc7f07b12..9bc610dba5 100644 --- a/src/detectors/BTOF/BTOF.cc +++ b/src/detectors/BTOF/BTOF.cc @@ -8,23 +8,25 @@ #include #include #include +#include #include #include #include #include #include -#include #include "algorithms/interfaces/WithPodConfig.h" #include "algorithms/pid_lut/PIDLookupConfig.h" #include "extensions/jana/JOmniFactoryGeneratorT.h" #include "factories/digi/EICROCDigitization_factory.h" #include "factories/digi/LGADChargeSharing_factory.h" +#include "factories/digi/PulseCombiner_factory.h" #include "factories/digi/SiliconPulseDiscretization_factory.h" #include "factories/digi/SiliconPulseGeneration_factory.h" #include "factories/digi/SiliconTrackerDigi_factory.h" -#include "factories/tracking/TrackerHitReconstruction_factory.h" -#include "factories/digi/PulseCombiner_factory.h" +#include "factories/reco/LGADHitCalibration_factory.h" +#include "factories/reco/LGADHitClustering_factory.h" +#include "factories/reco/LGADHitClusterAssociation_factory.h" #include "global/pid_lut/PIDLookup_factory.h" #include "services/geometry/dd4hep/DD4hep_service.h" @@ -43,13 +45,28 @@ void InitPlugin(JApplication* app) { }, app)); - // Convert raw digitized hits into hits with geometry info (ready for tracking) - app->Add(new JOmniFactoryGeneratorT( - "TOFBarrelRecHits", {"TOFBarrelRawHits"}, // Input data collection tags - {"TOFBarrelRecHits"}, // Output data tag - { - .timeResolution = 10, - }, + // Convert raw digitized hits into calibrated hits + // time walk correction is still TBD + app->Add(new JOmniFactoryGeneratorT( + "TOFBarrelCalHits", {"TOFBarrelADCTDC"}, // Input data collection tags + {"TOFBarrelCalHits"}, // Output data tag + {}, + app)); // Hit reco default config for factories + + // cluster all hits in a sensor into one hit location + // Currently it's just a simple weighted average + // More sophisticated algorithm TBD + app->Add(new JOmniFactoryGeneratorT( + "TOFBarrelClusterRecHits", {"TOFBarrelCalHits"}, // Input data collection tags + {"TOFBarrelClusterHits"}, // Output data tag + {}, + app)); // Hit reco default config for factories + + app->Add(new JOmniFactoryGeneratorT( + "TOFBarrelAssoRecHits", + {"TOFBarrelClusterHits", "TOFBarrelRawHits"}, // Input data collection tags + {"TOFBarrelRecHits"}, // Output data tag + {}, app)); // Hit reco default config for factories app->Add(new JOmniFactoryGeneratorT( @@ -74,10 +91,10 @@ void InitPlugin(JApplication* app) { const double gain = -adc_range / Vm / landau_min; const int offset = 3; app->Add(new JOmniFactoryGeneratorT( - "LGADPulseGeneration", {"TOFBarrelSharedHits"}, {"TOFBarrelSmoothPulses"}, + "TOFBarrelPulseGeneration", {"TOFBarrelSharedHits"}, {"TOFBarrelSmoothPulses"}, { .pulse_shape_function = "LandauPulse", - .pulse_shape_params = {gain, sigma_analog, offset * sigma_analog}, + .pulse_shape_params = {gain, sigma_analog, offset}, .ignore_thres = 0.05 * adc_range, .timestep = 0.01 * edm4eic::unit::ns, }, @@ -92,11 +109,11 @@ void InitPlugin(JApplication* app) { double risetime = 0.45 * edm4eic::unit::ns; app->Add(new JOmniFactoryGeneratorT( - "SiliconPulseDiscretization", {"TOFBarrelCombinedPulses"}, {"TOFBarrelPulses"}, + "TOFBarrelPulseDiscretization", {"TOFBarrelCombinedPulses"}, {"TOFBarrelPulses"}, { .EICROC_period = 25 * edm4eic::unit::ns, .local_period = 25 * edm4eic::unit::ns / 1024, - .global_offset = -offset * sigma_analog + risetime, + .global_offset = -(offset + x_when_landau_min) * sigma_analog + risetime, }, app)); diff --git a/src/factories/reco/LGADHitCalibration_factory.h b/src/factories/reco/LGADHitCalibration_factory.h new file mode 100644 index 0000000000..1303c578b5 --- /dev/null +++ b/src/factories/reco/LGADHitCalibration_factory.h @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright (C) 2025 Chun Yuen Tsang + +#pragma once + +#include "algorithms/reco/LGADHitCalibration.h" +#include "extensions/jana/JOmniFactory.h" +#include "services/geometry/dd4hep/DD4hep_service.h" + +namespace eicrecon { + +class LGADHitCalibration_factory + : public JOmniFactory { +private: + std::unique_ptr m_algo; + + PodioInput m_raw_hits_input{this}; + PodioOutput m_rec_hits_output{this}; + + ParameterRef m_c_slope{this, "c_slope", config().c_slope}; + ParameterRef m_c_intercept{this, "c_intercept", config().c_intercept}; + ParameterRef m_t_slope{this, "t_slope", config().t_slope}; + ParameterRef m_t_intercept{this, "t_intercept", config().t_intercept}; + +public: + void Configure() { + m_algo = std::make_unique(GetPrefix()); + m_algo->level(static_cast(logger()->level())); + m_algo->applyConfig(config()); + m_algo->init(); + } + + void ChangeRun(int32_t /* run_number */) {} + + void Process(int32_t /* run_number */, uint64_t /* event_number */) { + m_algo->process({m_raw_hits_input()}, {m_rec_hits_output().get()}); + } +}; + +} // namespace eicrecon diff --git a/src/factories/reco/LGADHitClusterAssociation_factory.h b/src/factories/reco/LGADHitClusterAssociation_factory.h new file mode 100644 index 0000000000..7b3ff0af57 --- /dev/null +++ b/src/factories/reco/LGADHitClusterAssociation_factory.h @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright (C) 2025 Chun Yuen Tsang + +#pragma once + +#include "algorithms/reco/LGADHitClusterAssociation.h" +#include "extensions/jana/JOmniFactory.h" +#include "services/geometry/dd4hep/DD4hep_service.h" + +namespace eicrecon { + +class LGADHitClusterAssociation_factory + : public JOmniFactory { +private: + std::unique_ptr m_algo; + + PodioInput m_meas_hits_input{this}; + PodioInput m_raw_hits_input{this}; + PodioOutput m_asso_hits_output{this}; + + ParameterRef m_readout{this, "readout", config().readout}; + ParameterRef m_assoDeltaT{this, "assoDeltaT", config().assoDeltaT}; + +public: + void Configure() { + m_algo = std::make_unique(GetPrefix()); + m_algo->level(static_cast(logger()->level())); + m_algo->applyConfig(config()); + m_algo->init(); + } + + void ChangeRun(int32_t /* run_number */) {} + + void Process(int32_t /* run_number */, uint64_t /* event_number */) { + m_algo->process({m_meas_hits_input(), m_raw_hits_input()}, {m_asso_hits_output().get()}); + } +}; + +} // namespace eicrecon diff --git a/src/factories/reco/LGADHitClustering_factory.h b/src/factories/reco/LGADHitClustering_factory.h new file mode 100644 index 0000000000..5b2dfbbc51 --- /dev/null +++ b/src/factories/reco/LGADHitClustering_factory.h @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright (C) 2025 Chun Yuen Tsang + +#pragma once + +#include "algorithms/reco/LGADHitClustering.h" +#include "extensions/jana/JOmniFactory.h" +#include "services/geometry/dd4hep/DD4hep_service.h" + +namespace eicrecon { + +class LGADHitClustering_factory + : public JOmniFactory { +private: + std::unique_ptr m_algo; + + PodioInput m_hits_input{this}; + PodioOutput m_clusters_output{this}; + + ParameterRef m_readout{this, "readout", config().readout}; + +public: + void Configure() { + m_algo = std::make_unique(GetPrefix()); + m_algo->level(static_cast(logger()->level())); + m_algo->applyConfig(config()); + m_algo->init(); + } + + void ChangeRun(int32_t /* run_number */) {} + + void Process(int32_t /* run_number */, uint64_t /* event_number */) { + m_algo->process({m_hits_input()}, {m_clusters_output().get()}); + } +}; + +} // namespace eicrecon diff --git a/src/global/tracking/tracking.cc b/src/global/tracking/tracking.cc index 3cab90019a..3d2b6df503 100644 --- a/src/global/tracking/tracking.cc +++ b/src/global/tracking/tracking.cc @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -39,7 +40,7 @@ void InitPlugin(JApplication* app) { app->Add(new JOmniFactoryGeneratorT>( "CentralTrackingRecHits", {"SiBarrelTrackerRecHits", "SiBarrelVertexRecHits", "SiEndcapTrackerRecHits", - "TOFBarrelRecHits", "TOFEndcapRecHits", "MPGDBarrelRecHits", "OuterMPGDBarrelRecHits", + "TOFEndcapRecHits", "MPGDBarrelRecHits", "OuterMPGDBarrelRecHits", "BackwardMPGDEndcapRecHits", "ForwardMPGDEndcapRecHits", "B0TrackerRecHits"}, {"CentralTrackingRecHits"}, // Output collection name app)); @@ -57,7 +58,13 @@ void InitPlugin(JApplication* app) { app)); app->Add(new JOmniFactoryGeneratorT( - "CentralTrackerMeasurements", {"CentralTrackingRecHits"}, {"CentralTrackerMeasurements"}, + "CentralTrackerMeasurements", {"CentralTrackingRecHits"}, {"CentralTrackerRecMeasurements"}, + app)); + + // include the collection from previous collector + app->Add(new JOmniFactoryGeneratorT>( + "CentralTrackingMeas2D", {"CentralTrackerRecMeasurements", "TOFBarrelClusterHits"}, + {"CentralTrackerMeasurements"}, // Output collection name app)); app->Add(new JOmniFactoryGeneratorT(