Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2026-04-05 08:11:42

0001 #ifndef PT_CALCULATOR_H
0002 #define PT_CALCULATOR_H
0003 
0004 #include <functional>
0005 #include <string>
0006 #include <variant>
0007 #include <vector>
0008 #include <optional>
0009 #include <limits>
0010 #include <array>
0011 #include <memory>
0012 #include <iostream>
0013 
0014 namespace SiCaloPt {
0015 
0016 // consistent return struct
0017 struct PtResult 
0018 {
0019     float pt_reco = std::numeric_limits<float>::quiet_NaN(); // reconstructed pt
0020     bool ok = false; // whether successful
0021     std::string err; // error message if any
0022 };
0023 
0024 // Five approaches enum
0025 enum class Method 
0026 {
0027     MethodEMD,   // EM Deflection Method
0028     MethodEproj, // Energy Projection Method
0029     MethodMLEMD, // ML EM Deflection Method
0030     MethodMLEproj, // ML Energy Projection Method
0031     MethodMLCombined // ML Combined Method
0032 };
0033 
0034 // Formula method input struct
0035 struct InputEMD 
0036 {
0037     float EMD_Angle = 0.f; // delta_phi - EM Deflection angle in rad is between two vectors, one vector connect inner INTT and outer INTT,  another one connect outer INTT and Calo cluster
0038     float EMD_Eta = 0.f; // track eta
0039     float EMD_Radius = 0.f; // EMCal Cluster radius in cm
0040 };
0041 
0042 struct InputEproj 
0043 {
0044     float Energy_Calo = 0.f; // EMCal Cluster energy in GeV
0045     float Radius_Calo = 0.f; // EMCal Cluster radius in cm
0046     float Z_Calo = 0.f; // EMCal Cluster z in cm
0047     float Radius_vertex = 0.f; // Vertex radius in cm
0048     float Z_vertex = 0.f; // Vertex z in cm
0049 };
0050 
0051 // ML Model input struct, using vector is convenient for ONNX, length and order must be consistent with training
0052 // Defination of length and order is in the tutorial file PtCalcMLTutorial.C
0053 struct InputMLEMD 
0054 {
0055     std::vector<float> features; // 2-d features:{ 1/dphi_EMD, eta_track}
0056 };
0057 
0058 struct InputMLEproj 
0059 {
0060     std::vector<float> features; // 7-d input features:{ INTT 3/4 layer R, INTT 3/4 layer Z, INTT 5/4 layer R, INTT 5/4 layer Z, Calo cluster R, Calo cluster Z, Calo cluster Energy }
0061 };
0062 
0063 struct InputMLCombined 
0064 {
0065     std::vector<float> features; // 2-d features:{pT reconstuct with deflection information, pT reconstuct with Calo energy information}
0066 };
0067 
0068 // consistent input variant for all methods
0069 using AnyInput = std::variant<InputEMD, InputEproj, InputMLEMD, InputMLEproj, InputMLCombined>;
0070 
0071 // Config(optional) for ML: ML paths, standardizer params, etc.
0072 struct PtCalculatorConfig 
0073 {
0074     std::optional<std::string> mlEMD_model_path;
0075     std::optional<std::string> mlEproj_model_path;
0076     std::optional<std::string> mlCombined_model_path;
0077 
0078     std::optional<std::string> mlEMD_scaler_json;
0079     std::optional<std::string> mlEproj_scaler_json;
0080     std::optional<std::string> mlCombined_scaler_json;
0081 };
0082 
0083 // PtCalculator MAIN CLASS 
0084 class PtCalculator {
0085 public:
0086     // Main Function. general func. for Pt calculation, dispatching according to method
0087     PtResult ComputePt(Method method, const AnyInput& input) const;
0088 
0089     // independent interfaces for finer control
0090     PtResult ComputeEMD(const InputEMD& in) const; // using electromagnetic deflection to calculate pT by analytic formula pT = C_eta × |Δφ|^(Power)
0091     PtResult ComputeEproj(const InputEproj& in) const; // project the Calo cluster energy to XY-plane to get pT by analytic formula pT = Energy_Calo × (ΔR / Distance) 
0092     PtResult ComputeMLEMD(const InputMLEMD& in) const; // machine learning model trained for the EMD method, the features are 2-d features: { 1/dphi_EMD, eta_track} please setting the eta_track = 0, cause I just add the dimension but not trained with the eta data now
0093     PtResult ComputeMLEproj(const InputMLEproj& in) const; // machine learning model trained for the Eproj method, the features are 7-d input features:{ INTT 3/4 layer R, INTT 3/4 layer Z, INTT 5/4 layer R, INTT 5/4 layer Z, Calo R, Calo Z, Calo Energy }
0094     PtResult ComputeMLCombined(const InputMLCombined& in) const; // machine learning model trained to combine the pT estimates obtained from two different methods based on two independent sets of information {deflection, energy}; the final combined pT is given by pT = w1 * pT(deflection) + w2 * pT(energy), where the weights w1 and w2 are predicted by the model for deflection and energy
0095 
0096     // ===== setters for global-ish configuration =====
0097     // 0 = Projected(fixed radius 93.5cm), 1 = InnerFace center, 2 = geometric center
0098     void setClusterRecoMode(int mode)
0099     {
0100         if (mode < 0 || mode > 2) {
0101             std::cerr << "ERROR: ClusterRecoMode must be 0/1/2" << std::endl;
0102             return;
0103         }
0104         ClusterRecoMode = mode;
0105     }
0106     int  getClusterRecoMode() const { return ClusterRecoMode; }
0107 
0108     // EMD formula parameters setters
0109     void setParCeta(float v)  { m_par_Ceta = v; }
0110     void setParPower(float v) { m_par_Power = v; }
0111 
0112     // member functions
0113     PtCalculator() = default;
0114     explicit PtCalculator(const PtCalculatorConfig& cfg);
0115 
0116     // setting/configuration (does not auto-load external resources)
0117     void setConfig(const PtCalculatorConfig& cfg);
0118 
0119     // initialize (load models and scalers for ML methods)
0120     bool init(std::string* err = nullptr);
0121 
0122     // load ML infer, output is pt
0123     using InferFn = std::function<float(const std::vector<float>&)>;
0124     void setMLEMDInfer(InferFn fn);
0125     void setMLEprojInfer(InferFn fn);
0126     void setMLCombinedInfer(InferFn fn);
0127 
0128     //  optional: set standardizer for each ML model, or do standardization inside InferFn
0129     void setMLEMDStandardizer(std::vector<float> mean, std::vector<float> scale);
0130     void setMLEprojStandardizer(std::vector<float> mean, std::vector<float> scale);
0131     void setMLCombinedStandardizer(std::vector<float> mean, std::vector<float> scale);
0132 
0133 private:
0134     static void applyStandardize(std::vector<float>& x,
0135                                  const std::vector<float>& mean,
0136                                  const std::vector<float>& scale);
0137 
0138     static bool LoadScalerJson(const std::string& path,
0139                                 std::vector<float>& mean,
0140                                 std::vector<float>& scale,
0141                                 std::string* err = nullptr);
0142 
0143     static SiCaloPt::PtCalculator::InferFn MakeOnnxInfer(const std::string& onnx_path, std::string* err = nullptr);
0144 
0145 private:
0146     PtCalculatorConfig m_cfg;
0147 
0148     int getScenario(double bending_angle = 0.1) const
0149     {
0150         int TrkrCharge = -1; // default negative-1 charge, can be set to positive(=1) if needed.
0151         if (bending_angle > 0)
0152             TrkrCharge = +1;
0153         else if (bending_angle < 0)
0154             TrkrCharge = -1;
0155 
0156         // charge: -1 +1, ClusterRecoMode: 0/1/2 -> 6 scenarios
0157         int track_scenario = TrkrCharge*10 + TrkrCharge*ClusterRecoMode;
0158         if (!((track_scenario >= -12 && track_scenario <= -10) ||
0159               (track_scenario >= 10  && track_scenario <= 12)))
0160         {
0161             std::cerr << "[PtCalculator] Invalid scenario = "
0162                       << track_scenario
0163                       << " (charge=" << TrkrCharge
0164                       << ", mode=" << ClusterRecoMode << ")"
0165                       << std::endl;
0166         
0167             return -999;   // 明确的 invalid flag
0168         }
0169 
0170         return track_scenario;
0171     }
0172 
0173     // 0 = Projected(fixed radius 93.5cm), 1 = InnerFace center, 2 = geomtric center
0174     int ClusterRecoMode = 0; 
0175 
0176     // ML Model infer functions
0177     InferFn m_mlEMD_infer;
0178     InferFn m_mlEproj_infer;
0179     InferFn m_mlCombined_infer;
0180 
0181     // optional: ML Scaler params for standardization, not exist for EMD and Combined model now
0182     std::vector<float> m_mlEMD_mean, m_mlEMD_scale;
0183     std::vector<float> m_mlEproj_mean, m_mlEproj_scale; 
0184     std::vector<float> m_mlCombined_mean, m_mlCombined_scale;
0185 
0186     // EMD formula parameters
0187     mutable float m_par_Ceta = 0.2;
0188     mutable float m_par_Power = -1.0;
0189 
0190     bool consider_eta_dependence_on_EMDcompute = true;
0191 };
0192 
0193 } // namespace SiCaloPt
0194 
0195 #endif // PT_CALCULATOR_H