Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-08-01 09:04:34

0001 // Copyright 2024, Simon Gardner
0002 // Subject to the terms in the LICENSE file found in the top-level directory.
0003 //
0004 #pragma once
0005 
0006 #include <algorithms/geo.h>
0007 
0008 namespace eicrecon {
0009 
0010 // ----------------------------------------------------------------------------
0011 // Chain wrapper type for explicit member function call chaining
0012 // Usage: Chain<&A::getB, &B::getC> chains A->getB()->getC()
0013 // ----------------------------------------------------------------------------
0014 template <auto... MemberFunctionPtrs> struct Chain {};
0015 
0016 // ----------------------------------------------------------------------------
0017 // Helper to invoke a chain of member function calls
0018 // ----------------------------------------------------------------------------
0019 template <auto... MemberFunctionPtrs> struct ChainInvoker;
0020 
0021 // Base case: single member function
0022 template <auto MemberFunctionPtr> struct ChainInvoker<MemberFunctionPtr> {
0023   template <typename T> static auto invoke(T& instance) { return (instance.*MemberFunctionPtr)(); }
0024 };
0025 
0026 // Recursive case: chain multiple member functions
0027 template <auto FirstMemberFunctionPtr, auto... RestMemberFunctionPtrs>
0028 struct ChainInvoker<FirstMemberFunctionPtr, RestMemberFunctionPtrs...> {
0029   template <typename T> static auto invoke(T& instance) {
0030     auto nested = (instance.*FirstMemberFunctionPtr)();
0031     return ChainInvoker<RestMemberFunctionPtrs...>::invoke(nested);
0032   }
0033 };
0034 
0035 // ----------------------------------------------------------------------------
0036 // Functor to split collection based on a range of values
0037 // ----------------------------------------------------------------------------
0038 template <typename... Chains> class RangeSplit;
0039 
0040 // Specialization: single Chain
0041 template <auto... MemberFunctionPtrs> class RangeSplit<Chain<MemberFunctionPtrs...>> {
0042 public:
0043   RangeSplit(std::vector<std::pair<double, double>> ranges) : m_ranges(ranges) {};
0044 
0045   template <typename T> std::vector<int> operator()(T& instance) const {
0046     std::vector<int> ids;
0047     auto value = ChainInvoker<MemberFunctionPtrs...>::invoke(instance);
0048     // Check if requested value is within the ranges
0049     for (std::size_t i = 0; i < m_ranges.size(); i++) {
0050       if (value > m_ranges[i].first && value < m_ranges[i].second) {
0051         ids.push_back(i);
0052       }
0053     }
0054     return ids;
0055   }
0056 
0057 private:
0058   std::vector<std::pair<double, double>> m_ranges;
0059 };
0060 
0061 // ----------------------------------------------------------------------------
0062 // Functor to split collection based on geometry
0063 // ----------------------------------------------------------------------------
0064 class GeometrySplit {
0065 public:
0066   GeometrySplit(std::vector<std::vector<long int>> ids, std::string readout,
0067                 std::vector<std::string> divisions)
0068       : m_ids(ids)
0069       , m_divisions(divisions)
0070       , m_readout(readout)
0071       , is_init(std::make_shared<std::once_flag>())
0072       , m_id_dec(std::make_shared<dd4hep::DDSegmentation::BitFieldCoder*>())
0073       , m_div_ids(std::make_shared<std::vector<std::size_t>>()) {};
0074 
0075   template <typename T> std::vector<int> operator()(T& instance) const {
0076 
0077     // Initialize the decoder and division ids on the first function call
0078     std::call_once(*is_init, &GeometrySplit::init, this);
0079 
0080     //Check which detector division to put the hit into
0081     auto cellID = instance.getCellID();
0082     std::vector<long int> det_ids;
0083     for (auto d : *m_div_ids) {
0084       det_ids.push_back((*m_id_dec)->get(cellID, d));
0085     }
0086 
0087     auto index = std::find(m_ids.begin(), m_ids.end(), det_ids);
0088 
0089     std::vector<int> ids;
0090     if (index != m_ids.end()) {
0091       ids.push_back(std::distance(m_ids.begin(), index));
0092     }
0093     return ids;
0094   }
0095 
0096 private:
0097   void init() const {
0098     *m_id_dec = algorithms::GeoSvc::instance().detector()->readout(m_readout).idSpec().decoder();
0099     for (auto d : m_divisions) {
0100       m_div_ids->push_back((*m_id_dec)->index(d));
0101     }
0102   }
0103 
0104   std::vector<std::vector<long int>> m_ids;
0105   std::vector<std::string> m_divisions;
0106   std::string m_readout;
0107 
0108   std::shared_ptr<std::once_flag> is_init;
0109   std::shared_ptr<dd4hep::DDSegmentation::BitFieldCoder*> m_id_dec;
0110   std::shared_ptr<std::vector<std::size_t>> m_div_ids;
0111 };
0112 
0113 // ----------------------------------------------------------------------------
0114 // Functor to split collection based on any number of collection values
0115 // ----------------------------------------------------------------------------
0116 template <auto... MemberFunctionPtrs> class ValueSplit {
0117 public:
0118   ValueSplit(std::vector<std::vector<int>> ids) : m_ids(ids) {};
0119 
0120   template <typename T> std::vector<int> operator()(T& instance) const {
0121     std::vector<int> ids;
0122     // Check if requested value matches any configuration combinations
0123     std::vector<int> values;
0124     (values.push_back((instance.*MemberFunctionPtrs)()), ...);
0125     auto index = std::find(m_ids.begin(), m_ids.end(), values);
0126     if (index != m_ids.end()) {
0127       ids.push_back(std::distance(m_ids.begin(), index));
0128     }
0129     return ids;
0130   }
0131 
0132 private:
0133   std::vector<std::vector<int>> m_ids;
0134 };
0135 
0136 } // namespace eicrecon