File indexing completed on 2025-04-04 08:02:16
0001
0002
0003 #include <Evaluator/DD4hepUnits.h>
0004 #include <edm4eic/ClusterCollection.h>
0005 #include <edm4eic/ReconstructedParticleCollection.h>
0006 #include <edm4hep/Vector3f.h>
0007 #include <edm4hep/utils/vector_utils.h>
0008 #include <fmt/core.h>
0009 #include <cmath>
0010 #include <gsl/pointers>
0011 #include <stdexcept>
0012 #include <vector>
0013
0014 #include "FarForwardNeutralsReconstruction.h"
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026 namespace eicrecon {
0027
0028 void FarForwardNeutralsReconstruction::init() {
0029 if (m_cfg.neutronScaleCorrCoeffHcal.size() < 3) {
0030 error("Invalid configuration. m_cfg.neutronScaleCorrCoeffHcal should have at least 3 parameters");
0031 throw std::runtime_error("Invalid configuration. m_cfg.neutronScaleCorrCoeffHcal should have at least 3 parameters");
0032 }
0033 if (m_cfg.gammaScaleCorrCoeffHcal.size() < 3) {
0034 error("Invalid configuration. m_cfg.gamma_scale_corr_coeff_ecal should have at least 3 parameters");
0035 throw std::runtime_error("Invalid configuration. m_cfg.gamma_scale_corr_coeff_ecal should have at least 3 parameters");
0036 }
0037 trace("gamma detection params: max length={}, max width={}, max z={}", m_cfg.gammaMaxLength, m_cfg.gammaMaxWidth,
0038 m_cfg.gammaZMax);
0039 }
0040
0041 double FarForwardNeutralsReconstruction::calc_corr(double Etot, const std::vector<double>& coeffs) const{
0042 return coeffs[0]+coeffs[1]/sqrt(Etot)+coeffs[2]/Etot;
0043 }
0044
0045
0046
0047
0048
0049
0050 bool FarForwardNeutralsReconstruction::isGamma(const edm4eic::Cluster& cluster) const{
0051 double l1=sqrt(cluster.getShapeParameters(4))*dd4hep::mm;
0052 double l2=sqrt(cluster.getShapeParameters(5))*dd4hep::mm;
0053 double l3=sqrt(cluster.getShapeParameters(6))*dd4hep::mm;
0054
0055
0056 double z= (cluster.getPosition().z*cos(m_cfg.globalToProtonRotation)+cluster.getPosition().x*sin(m_cfg.globalToProtonRotation))*dd4hep::mm;
0057 trace("z recon = {}", z);
0058 trace("l1 = {}, l2 = {}, l3 = {}", l1, l2, l3);
0059 bool isZMoreThanMax = (z > m_cfg.gammaZMax);
0060 bool isLengthMoreThanMax = (l1> m_cfg.gammaMaxLength || l2> m_cfg.gammaMaxLength || l3 > m_cfg.gammaMaxLength);
0061 bool areWidthsMoreThanMax = (l1> m_cfg.gammaMaxWidth)+(l2> m_cfg.gammaMaxWidth)+(l3 > m_cfg.gammaMaxWidth)>=2;
0062 return !(isZMoreThanMax || isLengthMoreThanMax || areWidthsMoreThanMax);
0063
0064 }
0065
0066
0067
0068 void FarForwardNeutralsReconstruction::process(const FarForwardNeutralsReconstruction::Input& input,
0069 const FarForwardNeutralsReconstruction::Output& output) const {
0070 const auto [clustersHcal] = input;
0071 auto [out_neutrals] = output;
0072
0073 double Etot_hcal=0;
0074 double Emax=0;
0075 edm4hep::Vector3f n_position;
0076 for (const auto& cluster : *clustersHcal) {
0077 double E = cluster.getEnergy();
0078
0079 if(isGamma(cluster)){
0080 auto rec_part = out_neutrals->create();
0081 rec_part.setPDG(22);
0082 edm4hep::Vector3f position = cluster.getPosition();
0083 double corr=calc_corr(E,m_cfg.gammaScaleCorrCoeffHcal);
0084 E=E/(1+corr);
0085 double p = E;
0086 double r = edm4hep::utils::magnitude(position);
0087 edm4hep::Vector3f momentum = position * (p / r);
0088 rec_part.setEnergy(E);
0089 rec_part.setMomentum(momentum);
0090 rec_part.setReferencePoint(position);
0091 rec_part.setCharge(0);
0092 rec_part.setMass(0);
0093 rec_part.addToClusters(cluster);
0094 continue;
0095 }
0096
0097 Etot_hcal += E;
0098 if (E > Emax){
0099 Emax = E;
0100 n_position = cluster.getPosition();
0101 }
0102 }
0103
0104 double Etot=Etot_hcal;
0105 static const double m_neutron = m_particleSvc.particle(2112).mass;
0106 int n_neutrons;
0107 if (Etot > 0 && Emax > 0){
0108 auto rec_part = out_neutrals->create();
0109 double corr=calc_corr(Etot,m_cfg.neutronScaleCorrCoeffHcal);
0110 Etot_hcal=Etot_hcal/(1+corr);
0111 Etot=Etot_hcal;
0112 rec_part.setEnergy(Etot);
0113 rec_part.setPDG(2112);
0114 double p = sqrt(Etot*Etot-m_neutron*m_neutron);
0115 double r = edm4hep::utils::magnitude(n_position);
0116 edm4hep::Vector3f momentum = n_position * (p / r);
0117 rec_part.setMomentum(momentum);
0118 rec_part.setReferencePoint(n_position);
0119 rec_part.setCharge(0);
0120 rec_part.setMass(m_neutron);
0121 for (const auto& cluster : *clustersHcal){
0122 rec_part.addToClusters(cluster);
0123 }
0124 n_neutrons=1;
0125 } else {
0126 n_neutrons=0;
0127 }
0128 debug("Found {} neutron candidates", n_neutrons);
0129
0130 }
0131 }