diff --git a/src/algorithms/reco/PrimaryVertices.cc b/src/algorithms/reco/PrimaryVertices.cc new file mode 100644 index 000000000..290f991ec --- /dev/null +++ b/src/algorithms/reco/PrimaryVertices.cc @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright (C) 2024 Daniel Brandenburg, Xin Dong + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "algorithms/reco/PrimaryVertices.h" +#include "algorithms/reco/PrimaryVerticesConfig.h" + +namespace eicrecon { + + /** + * @brief Initialize the PrimaryVertices Algorithm + * + */ + void PrimaryVertices::init() { + } + + /** + * @brief Produce a list of primary vertex candidates + * + * @param rcvtx - input collection of all vertex candidates + * @return edm4eic::VertexCollection + */ + void PrimaryVertices::process(const PrimaryVertices::Input& input, + const PrimaryVertices::Output& output) const { + const auto [rcvtx] = input; + auto [out_primary_vertices] = output; + + // this multimap will store intermediate results + // so that we can sort them before filling output + // collection + std::multimap> primaryVertexMap; + + // our output collection of primary vertex + // ordered by N_trk = associatedParticle array size + out_primary_vertices->setSubsetCollection(); + + trace("We have {} candidate vertices", rcvtx->size()); + + for (const auto& vtx: *rcvtx) { + const auto &v = vtx.getPosition(); + + // some basic vertex selection + if (sqrt( v.x*v.x + v.y*v.y ) / edm4eic::unit::mm > m_cfg.maxVr || + fabs( v.z ) / edm4eic::unit::mm > m_cfg.maxVz ) + continue; + + if (vtx.getChi2() > m_cfg.maxChi2) continue; + + int N_trk = vtx.getAssociatedParticles().size(); + trace( "\t N_trk = {}", N_trk ); + primaryVertexMap.insert({N_trk, vtx}); + } // vertex loop + + bool first = true; + // map defined with std::greater<> will be iterated in descending order by the key + for (auto [N_trk, vertex] : primaryVertexMap) { + // Do not save primary candidates that + // are not within range + if ( N_trk > m_cfg.maxNtrk + || N_trk < m_cfg.minNtrk ){ + continue; + } + + // For logging and development + // report the highest N_trk candidate chosen + if (first) { + trace("Max N_trk Candidate:"); + trace("\t N_trk = {}", N_trk); + trace("\t Primary vertex has xyz=( {}, {}, {} )", vertex.getPosition().x, vertex.getPosition().y, vertex.getPosition().z); + first = false; + } + out_primary_vertices->push_back(vertex); + } // loop on primaryVertexMap + } +} // namespace eicrecon diff --git a/src/algorithms/reco/PrimaryVertices.h b/src/algorithms/reco/PrimaryVertices.h new file mode 100644 index 000000000..a6d6a2785 --- /dev/null +++ b/src/algorithms/reco/PrimaryVertices.h @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright (C) 2024 Daniel Brandenburg, Xin Dong + +#pragma once + +#include +#include +#include // for basic_string +#include // for string_view + +#include "algorithms/interfaces/WithPodConfig.h" +#include "algorithms/reco/PrimaryVerticesConfig.h" + + +namespace eicrecon { + +using PrimaryVerticesAlgorithm = algorithms::Algorithm< + algorithms::Input, + algorithms::Output>; + + class PrimaryVertices : + public PrimaryVerticesAlgorithm, + public WithPodConfig{ + + public: + PrimaryVertices(std::string_view name) + : PrimaryVerticesAlgorithm{name, + {"inputVertices"}, + {"outputPrimaryVertices"}, + "Sort reconstructed vertices in PrimaryVertices collection"} {} + + void init() final; + void process(const Input&, const Output&) const final; + + private: + + }; +} // namespace eicrecon diff --git a/src/algorithms/reco/PrimaryVerticesConfig.h b/src/algorithms/reco/PrimaryVerticesConfig.h new file mode 100644 index 000000000..c732a1e90 --- /dev/null +++ b/src/algorithms/reco/PrimaryVerticesConfig.h @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright (C) 2024 Xin Dong + +#pragma once + +#include +#include + +namespace eicrecon { + + struct PrimaryVerticesConfig { + + // For now these are wide open + // In the future the cut should depend + // on the generator settings + float maxVr = 50.0; // mm + float maxVz = 500.0; // mm + float maxChi2 = 10000.0; // + int minNtrk = 1; // >= + int maxNtrk = 1000000; // <= + }; + +} // end eicrecon namespace diff --git a/src/global/reco/PrimaryVertices_factory.h b/src/global/reco/PrimaryVertices_factory.h new file mode 100644 index 000000000..d325c6b9f --- /dev/null +++ b/src/global/reco/PrimaryVertices_factory.h @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright (C) 2024 Xin Dong + +#pragma once + +#include +#include +#include +#include +#include + +#include "algorithms/reco/PrimaryVertices.h" +#include "algorithms/reco/PrimaryVerticesConfig.h" +#include "services/algorithms_init/AlgorithmsInit_service.h" +#include "extensions/jana/JOmniFactory.h" + +namespace eicrecon { + +class PrimaryVertices_factory : + public JOmniFactory { + +public: + using AlgoT = eicrecon::PrimaryVertices; +private: + std::unique_ptr m_algo; + + PodioInput m_rc_vertices_input {this}; + + // Declare outputs + PodioOutput m_primary_vertices_output {this}; + + Service m_algorithmsInit {this}; + +public: + void Configure() { + m_algo = std::make_unique(GetPrefix()); + m_algo->level((algorithms::LogLevel)logger()->level()); + + m_algo->applyConfig(config()); + m_algo->init(); + } + + void ChangeRun(int64_t run_number) { + } + + void Process(int64_t run_number, uint64_t event_number) { + m_algo->process({m_rc_vertices_input()}, {m_primary_vertices_output().get()}); + } +}; + +} // eicrecon diff --git a/src/global/reco/reco.cc b/src/global/reco/reco.cc index 9813baac8..0c8e373bc 100644 --- a/src/global/reco/reco.cc +++ b/src/global/reco/reco.cc @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -44,6 +45,7 @@ #include "global/reco/ChargedReconstructedParticleSelector_factory.h" #include "global/reco/MC2SmearedParticle_factory.h" #include "global/reco/MatchClusters_factory.h" +#include "global/reco/PrimaryVertices_factory.h" #include "global/reco/ReconstructedElectrons_factory.h" #include "global/reco/ScatteredElectronsEMinusPz_factory.h" #include "global/reco/ScatteredElectronsTruth_factory.h" @@ -384,6 +386,19 @@ void InitPlugin(JApplication *app) { app )); + app->Add(new JOmniFactoryGeneratorT( + "PrimaryVertices", + { + "CentralTrackVertices" + }, + { + "PrimaryVertices" + }, + { + }, + app + )); + } } // extern "C" diff --git a/src/services/io/podio/JEventProcessorPODIO.cc b/src/services/io/podio/JEventProcessorPODIO.cc index 9b8afc0b1..f510c3df5 100644 --- a/src/services/io/podio/JEventProcessorPODIO.cc +++ b/src/services/io/podio/JEventProcessorPODIO.cc @@ -221,6 +221,7 @@ JEventProcessorPODIO::JEventProcessorPODIO() { "ReconstructedElectrons", "ScatteredElectronsTruth", "ScatteredElectronsEMinusPz", + "PrimaryVertices", #if EDM4EIC_VERSION_MAJOR >= 6 "HadronicFinalState", #endif