Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-12-17 09:19:52

0001 #include "RawClusterv1.h"
0002 
0003 #include "RawTowerDefs.h"
0004 
0005 #include <phool/phool.h>
0006 
0007 #include <cstdlib>
0008 #include <limits>
0009 #include <string>
0010 #include <vector>
0011 
0012 RawClusterv1::RawClusterv1(const RawCluster& cluster)
0013 {
0014   set_id(cluster.get_id());
0015   set_energy(cluster.get_energy());
0016   set_r(cluster.get_r());
0017   set_phi(cluster.get_phi());
0018   set_z(cluster.get_z());
0019 
0020   for (const auto& tower : cluster.get_towermap())
0021   {
0022     addTower(tower.first, tower.second);
0023   }
0024 
0025   static const PROPERTY kKnownProperties[] = {
0026       prop_ecore,
0027       prop_prob,
0028       prop_chi2,
0029       prop_merged_cluster_prob,
0030       prop_et_iso_calotower_sub_R01,
0031       prop_et_iso_calotower_R01,
0032       prop_et_iso_calotower_sub_R02,
0033       prop_et_iso_calotower_R02,
0034       prop_et_iso_calotower_sub_R03,
0035       prop_et_iso_calotower_R03,
0036       prop_et_iso_calotower_sub_R04,
0037       prop_et_iso_calotower_R04,
0038 
0039       // tower CoG and timing
0040       prop_tower_x_raw,
0041       prop_tower_y_raw,
0042       prop_tower_x_corr,
0043       prop_tower_y_corr,
0044       prop_tower_t_mean,
0045 
0046       // mechanical incidence angles
0047       prop_incidence_alpha_phi,
0048       prop_incidence_alpha_eta};
0049 
0050   for (const auto prop_id : kKnownProperties)
0051   {
0052     copy_property_from_cluster(cluster, prop_id);
0053   }
0054 }
0055 
0056 void RawClusterv1::copy_property_from_cluster(const RawCluster& source, const PROPERTY prop_id)
0057 {
0058   if (!source.has_property(prop_id))
0059   {
0060     return;
0061   }
0062 
0063   std::pair<const std::string, PROPERTY_TYPE> property_info = RawCluster::get_property_info(prop_id);
0064   switch (property_info.second)
0065   {
0066   case type_int:
0067     set_property(prop_id, source.get_property_int(prop_id));
0068     break;
0069   case type_uint:
0070     set_property(prop_id, source.get_property_uint(prop_id));
0071     break;
0072   case type_float:
0073     set_property(prop_id, source.get_property_float(prop_id));
0074     break;
0075   default:
0076     break;
0077   }
0078 }
0079 
0080 void RawClusterv1::Reset()
0081 {
0082   clusterid = 0;
0083   _z = std::numeric_limits<float>::quiet_NaN();
0084   _r = std::numeric_limits<float>::quiet_NaN();
0085   _phi = std::numeric_limits<float>::quiet_NaN();
0086   _energy = std::numeric_limits<float>::quiet_NaN();
0087   prop_map.clear();
0088   towermap.clear();
0089 }
0090 
0091 void RawClusterv1::addTower(const RawClusterDefs::keytype twrid, const float etower)
0092 {
0093   if (towermap.contains(twrid))
0094   {
0095     std::cout << "tower 0x" << std::hex << twrid << ", dec: " << std::dec
0096               << twrid << " already exists, that is bad" << std::endl;
0097     exit(1);
0098   }
0099   towermap[twrid] = etower;
0100 }
0101 
0102 void RawClusterv1::identify(std::ostream& os) const
0103 {
0104   os << "RawClusterv1 ID " << get_id() << " consist of " << getNTowers() << " towers with total energy of " << get_energy() << " GeV ";
0105   os << "@ (r,phi,z) = (" << get_r() << ", " << get_phi() << ", " << get_z() << "), (x,y,z) = (" << get_x() << ", " << get_y() << ", " << get_z() << ")";
0106 
0107   for (auto i : prop_map)
0108   {
0109     PROPERTY prop_id = static_cast<PROPERTY>(i.first);
0110     std::pair<const std::string, PROPERTY_TYPE> property_info = get_property_info(prop_id);
0111     os << "\t" << prop_id << ":\t" << property_info.first << " = \t";
0112     switch (property_info.second)
0113     {
0114     case type_int:
0115       os << get_property_int(prop_id);
0116       break;
0117     case type_uint:
0118       os << get_property_uint(prop_id);
0119       break;
0120     case type_float:
0121       os << get_property_float(prop_id);
0122       break;
0123     default:
0124       os << " unknown type ";
0125       break;
0126     }
0127     os << std::endl;
0128   }
0129 }
0130 
0131 ////! convert cluster location to psuedo-rapidity given a user chosen z-location
0132 // float RawClusterv1::get_eta(const float z) const
0133 //{
0134 //   if (get_r() <= 0) return numeric_limits<float>::quiet_NaN();
0135 //   return asinh((get_z() - z) / get_r());
0136 // }
0137 //
0138 ////! convert cluster E_T given a user chosen z-location
0139 // float RawClusterv1::get_et(const float z) const
0140 //{
0141 //   if (get_r() <= 0) return numeric_limits<float>::quiet_NaN();
0142 //   return get_energy() * sin(atan2(get_r(), (get_z() - z)));
0143 // }
0144 
0145 bool RawClusterv1::has_property(const PROPERTY prop_id) const
0146 {
0147   prop_map_t::const_iterator i = prop_map.find(prop_id);
0148   return i != prop_map.end();
0149 }
0150 
0151 float RawClusterv1::get_property_float(const PROPERTY prop_id) const
0152 {
0153   if (!check_property(prop_id, type_float))
0154   {
0155     std::pair<const std::string, PROPERTY_TYPE> property_info = get_property_info(prop_id);
0156     std::cout << PHWHERE << " Property " << property_info.first << " with id "
0157               << prop_id << " is of type " << get_property_type(property_info.second)
0158               << " not " << get_property_type(type_float) << std::endl;
0159     exit(1);
0160   }
0161   prop_map_t::const_iterator i = prop_map.find(prop_id);
0162 
0163   if (i != prop_map.end())
0164   {
0165     return u_property(i->second).fdata;
0166   }
0167 
0168   return std::numeric_limits<float>::quiet_NaN();
0169 }
0170 
0171 int RawClusterv1::get_property_int(const PROPERTY prop_id) const
0172 {
0173   if (!check_property(prop_id, type_int))
0174   {
0175     std::pair<const std::string, PROPERTY_TYPE> property_info = get_property_info(prop_id);
0176     std::cout << PHWHERE << " Property " << property_info.first << " with id "
0177               << prop_id << " is of type " << get_property_type(property_info.second)
0178               << " not " << get_property_type(type_int) << std::endl;
0179     exit(1);
0180   }
0181   prop_map_t::const_iterator i = prop_map.find(prop_id);
0182 
0183   if (i != prop_map.end())
0184   {
0185     return u_property(i->second).idata;
0186   }
0187 
0188   return std::numeric_limits<int>::min();
0189 }
0190 
0191 unsigned int
0192 RawClusterv1::get_property_uint(const PROPERTY prop_id) const
0193 {
0194   if (!check_property(prop_id, type_uint))
0195   {
0196     std::pair<const std::string, PROPERTY_TYPE> property_info = get_property_info(prop_id);
0197     std::cout << PHWHERE << " Property " << property_info.first << " with id "
0198               << prop_id << " is of type " << get_property_type(property_info.second)
0199               << " not " << get_property_type(type_uint) << std::endl;
0200     exit(1);
0201   }
0202   prop_map_t::const_iterator i = prop_map.find(prop_id);
0203 
0204   if (i != prop_map.end())
0205   {
0206     return u_property(i->second).uidata;
0207   }
0208 
0209   return std::numeric_limits<unsigned int>::max();
0210 }
0211 
0212 void RawClusterv1::set_property(const PROPERTY prop_id, const float value)
0213 {
0214   if (!check_property(prop_id, type_float))
0215   {
0216     std::pair<const std::string, PROPERTY_TYPE> property_info = get_property_info(prop_id);
0217     std::cout << PHWHERE << " Property " << property_info.first << " with id "
0218               << prop_id << " is of type " << get_property_type(property_info.second)
0219               << " not " << get_property_type(type_float) << std::endl;
0220     exit(1);
0221   }
0222   prop_map[prop_id] = u_property(value).get_storage();
0223 }
0224 
0225 void RawClusterv1::set_property(const PROPERTY prop_id, const int value)
0226 {
0227   if (!check_property(prop_id, type_int))
0228   {
0229     std::pair<const std::string, PROPERTY_TYPE> property_info = get_property_info(prop_id);
0230     std::cout << PHWHERE << " Property " << property_info.first << " with id "
0231               << prop_id << " is of type " << get_property_type(property_info.second)
0232               << " not " << get_property_type(type_int) << std::endl;
0233     exit(1);
0234   }
0235   prop_map[prop_id] = u_property(value).get_storage();
0236 }
0237 
0238 void RawClusterv1::set_property(const PROPERTY prop_id, const unsigned int value)
0239 {
0240   if (!check_property(prop_id, type_uint))
0241   {
0242     std::pair<const std::string, PROPERTY_TYPE> property_info = get_property_info(prop_id);
0243     std::cout << PHWHERE << " Property " << property_info.first << " with id "
0244               << prop_id << " is of type " << get_property_type(property_info.second)
0245               << " not " << get_property_type(type_uint) << std::endl;
0246     exit(1);
0247   }
0248   prop_map[prop_id] = u_property(value).get_storage();
0249 }
0250 void RawClusterv1::set_et_iso(const float et_iso, const int radiusx10, bool subtracted, bool clusterTower = true)
0251 {
0252   if (clusterTower)
0253   {
0254     if (subtracted)
0255     {
0256       switch (radiusx10)
0257       {
0258       case 1:
0259         set_property(prop_et_iso_calotower_sub_R01, et_iso);
0260         break;
0261       case 2:
0262         set_property(prop_et_iso_calotower_sub_R02, et_iso);
0263         break;
0264       case 3:
0265         set_property(prop_et_iso_calotower_sub_R03, et_iso);
0266         break;
0267       case 4:
0268         set_property(prop_et_iso_calotower_sub_R04, et_iso);
0269         break;
0270       default:
0271         std::string warning = "set_et_iso(const int radiusx10, bool subtracted, bool clusterTower) - radius:" + std::to_string(radiusx10) + " has not been defined";
0272         PHOOL_VIRTUAL_WARN(warning.c_str());
0273         break;
0274       }
0275     }
0276     else
0277     {
0278       switch (radiusx10)
0279       {
0280       case 1:
0281         set_property(prop_et_iso_calotower_R01, et_iso);
0282         break;
0283       case 2:
0284         set_property(prop_et_iso_calotower_R02, et_iso);
0285         break;
0286       case 3:
0287         set_property(prop_et_iso_calotower_R03, et_iso);
0288         break;
0289       case 4:
0290         set_property(prop_et_iso_calotower_R04, et_iso);
0291         break;
0292       default:
0293         std::string warning = "set_et_iso(const int radiusx10, bool subtracted, bool clusterTower) - radius:" + std::to_string(radiusx10) + " has not been defined";
0294         PHOOL_VIRTUAL_WARN(warning.c_str());
0295         break;
0296       }
0297     }
0298   }
0299   else
0300   {
0301     PHOOL_VIRTUAL_WARN("set_et_iso(const int radiusx10, bool subtracted, bool clusterTower) - nonclusterTower algorithms have not been defined");
0302   }
0303 }
0304 
0305 unsigned int
0306 RawClusterv1::get_property_nocheck(const PROPERTY prop_id) const
0307 {
0308   prop_map_t::const_iterator iter = prop_map.find(prop_id);
0309   if (iter != prop_map.end())
0310   {
0311     return iter->second;
0312   }
0313   return std::numeric_limits<unsigned int>::max();
0314 }
0315 
0316 float RawClusterv1::get_et_iso(const int radiusx10 = 3, bool subtracted = false, bool clusterTower = true) const
0317 {
0318   float r;
0319   if (clusterTower)
0320   {
0321     if (subtracted)
0322     {
0323       switch (radiusx10)
0324       {
0325       case 1:
0326         r = get_property_float(prop_et_iso_calotower_sub_R01);
0327         break;
0328       case 2:
0329         r = get_property_float(prop_et_iso_calotower_sub_R02);
0330         break;
0331       case 3:
0332         r = get_property_float(prop_et_iso_calotower_sub_R03);
0333         break;
0334       case 4:
0335         r = get_property_float(prop_et_iso_calotower_sub_R04);
0336         break;
0337       default:
0338         std::string warning = "get_et_iso(const int radiusx10, bool subtracted, bool clusterTower) - radius:" + std::to_string(radiusx10) + " has not been defined";
0339         PHOOL_VIRTUAL_WARN(warning.c_str());
0340         r = std::numeric_limits<float>::quiet_NaN();
0341         break;
0342       }
0343     }
0344     else
0345     {
0346       switch (radiusx10)
0347       {
0348       case 1:
0349         r = get_property_float(prop_et_iso_calotower_R01);
0350         break;
0351       case 2:
0352         r = get_property_float(prop_et_iso_calotower_R02);
0353         break;
0354       case 3:
0355         r = get_property_float(prop_et_iso_calotower_R03);
0356         break;
0357       case 4:
0358         r = get_property_float(prop_et_iso_calotower_R04);
0359         break;
0360       default:
0361         std::string warning = "get_et_iso(const int radiusx10, bool subtracted, bool clusterTower) - radius:" + std::to_string(radiusx10) + " has not been defined";
0362         PHOOL_VIRTUAL_WARN(warning.c_str());
0363         r = std::numeric_limits<float>::quiet_NaN();
0364         break;
0365       }
0366     }
0367   }
0368   else
0369   {
0370     PHOOL_VIRTUAL_WARN("get_et_iso(const int radiusx10, bool subtracted, bool clusterTower) - nonclusterTower algorithms have not been defined");
0371     r = std::numeric_limits<float>::quiet_NaN();
0372   }
0373   return r;
0374 }
0375 
0376 std::vector<float> RawClusterv1::get_shower_shapes(float tower_thresh) const
0377 {
0378   // loop over towermap
0379   RawTowerDefs::keytype maxtowerkey = 0;
0380   float maxtowerE = 0;
0381   for (const auto& iter : towermap)
0382   {
0383     if (iter.second > maxtowerE)
0384     {
0385       maxtowerE = iter.second;
0386       maxtowerkey = iter.first;
0387     }
0388   }
0389 
0390   // check if towermap is empty
0391   if (towermap.empty() || maxtowerE == 0)
0392   {
0393     std::vector<float> v;
0394     return v;
0395   }
0396   int maxtowerieta = RawTowerDefs::decode_index1(maxtowerkey);
0397   int maxtoweriphi = RawTowerDefs::decode_index2(maxtowerkey);
0398   // energy weighted avg eta and phi
0399   float deta1 = 0;
0400   float dphi1 = 0;
0401   // energy weighted second moment in eta and phi
0402   float deta2 = 0;
0403   float dphi2 = 0;
0404 
0405   float totalE = 0;
0406 
0407   // I will hard code the EMCal dim here for now hoping no one will read this :)
0408   int totalphibins = 256;
0409   auto dphiwrap = [totalphibins](float towerphi, float maxiphi)
0410   {
0411     float idphi = towerphi - maxiphi;
0412     float idphiwrap = totalphibins - std::abs(idphi);
0413     if (std::abs(idphiwrap) < std::abs(idphi))
0414     {
0415       return (idphi > 0) ? -idphiwrap : idphiwrap;
0416     }
0417     return idphi;
0418   };
0419   for (const auto& iter : towermap)
0420   {
0421     RawTowerDefs::keytype towerkey = iter.first;
0422     float E = iter.second;
0423     float eta = RawTowerDefs::decode_index1(towerkey);
0424     float phi = RawTowerDefs::decode_index2(towerkey);
0425     float deta = eta - maxtowerieta;
0426 
0427     float dphi = dphiwrap(phi, maxtoweriphi);
0428     if (E > tower_thresh)
0429     {
0430       totalE += E;
0431       deta1 += E * deta;
0432       dphi1 += E * dphi;
0433       deta2 += E * deta * deta;
0434       dphi2 += E * dphi * dphi;
0435     }
0436   }
0437   deta1 /= totalE;
0438   dphi1 /= totalE;
0439   deta2 = deta2 / totalE - (deta1 * deta1);
0440   dphi2 = dphi2 / totalE - (dphi1 * dphi1);
0441   // find the index of the center 4 towers
0442   int centertowerieta = std::floor(deta1 + 0.5);
0443   int centertoweriphi = std::floor(dphi1 + 0.5);
0444   int etashift = (deta1 - centertowerieta) < 0 ? -1 : 1;
0445   int phishift = (dphi1 - centertoweriphi) < 0 ? -1 : 1;
0446 
0447   auto wraptowerphi = [totalphibins](int phi) -> int
0448   {
0449     if (phi < 0)
0450     {
0451       return phi + totalphibins;
0452     }
0453     if (phi >= totalphibins)
0454     {
0455       return phi - totalphibins;
0456     }
0457     return phi;
0458   };
0459 
0460   int eta1 = centertowerieta + maxtowerieta;
0461   int eta2 = centertowerieta + etashift + maxtowerieta;
0462   int phi1 = wraptowerphi(centertoweriphi + maxtoweriphi);
0463   int phi2 = wraptowerphi(centertoweriphi + phishift + maxtoweriphi);
0464 
0465   auto gettowerenergy = [totalphibins, tower_thresh, this](int ieta, int phi) -> float
0466   {
0467     if (phi < 0)
0468     {
0469       return phi + totalphibins;
0470     }
0471     if (phi >= totalphibins)
0472     {
0473       return phi - totalphibins;
0474     }
0475     RawTowerDefs::keytype key = RawTowerDefs::encode_towerid(RawTowerDefs::CalorimeterId::CEMC, ieta, phi);
0476     if (towermap.contains(key))
0477     {
0478       if (towermap.at(key) > tower_thresh)
0479       {
0480         return towermap.at(key);
0481       }
0482     }
0483     return 0;
0484   };
0485 
0486   float e1 = gettowerenergy(eta1, phi1);
0487   float e2 = gettowerenergy(eta1, phi2);
0488   float e3 = gettowerenergy(eta2, phi2);
0489   float e4 = gettowerenergy(eta2, phi1);
0490 
0491   float e1t = (e1 + e2 + e3 + e4) / totalE;
0492   float e2t = (e1 + e2 - e3 - e4) / totalE;
0493   float e3t = (e1 - e2 - e3 + e4) / totalE;
0494   float e4t = (e3) / totalE;
0495 
0496   std::vector<float> v = {e1t, e2t, e3t, e4t, deta1 + maxtowerieta, dphi1 + maxtoweriphi, deta2, dphi2, e1, e2, e3, e4, totalE};
0497   return v;
0498 }
0499 
0500 std::pair<int, int> RawClusterv1::get_lead_tower() const
0501 {
0502   if (towermap.empty())
0503   {
0504     return {0, 0};  // or some indication of "no tower"
0505   }
0506 
0507   int phi_max = 0;
0508   int eta_max = 0;
0509   float e_max = std::numeric_limits<float>::lowest();
0510 
0511   for (const auto& iter : towermap)
0512   {
0513     RawTowerDefs::keytype towerkey = iter.first;
0514     float E = iter.second;
0515     float eta = RawTowerDefs::decode_index1(towerkey);
0516     float phi = RawTowerDefs::decode_index2(towerkey);
0517     if (E > e_max)
0518     {
0519       phi_max = phi;
0520       eta_max = eta;
0521       e_max = E;
0522     }
0523   }
0524   return {eta_max, phi_max};
0525 }