Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2024-06-01 07:07:32

0001 
0002 #include <TDatabasePDG.h>
0003 
0004 #include "DelphesConfig.h"
0005 
0006 #define _ERROR_(message) { printf("\n\n  %s\n", message); exit(1); }
0007 
0008 // -------------------------------------------------------------------------------------
0009 
0010 DelphesConfig::DelphesConfig( void )://const char *dname): 
0011   //m_Name(dname),  
0012   m_DatabasePDG(0),
0013   m_EtaMin(0.0), m_EtaMax(0.0),
0014   m_MomentumMin(0.0), m_MomentumMax(0.0), m_EfficiencyContaminationMode(false),
0015   //m_PionThreshold(0.0), m_KaonThreshold(0.0), m_ProtonThreshold(0.0)
0016   m_PtMode(false)
0017 {
0018   //if (dname) {
0019   //m_Name = dname;
0020   //m_DatabasePDG = new TDatabasePDG();
0021   //} //if
0022 } // DelphesConfig::DelphesConfig()
0023 
0024 // -------------------------------------------------------------------------------------
0025 
0026 DelphesConfig::DelphesConfig(const char *dname): 
0027   m_Name(dname),  
0028   m_EtaMin(0.0), m_EtaMax(0.0),
0029   m_MomentumMin(0.0), m_MomentumMax(0.0), m_EfficiencyContaminationMode(false),
0030   //m_PionThreshold(0.0), m_KaonThreshold(0.0), m_ProtonThreshold(0.0)
0031   m_PtMode(false)
0032 {
0033   //if (dname) {
0034   m_Name = dname;
0035   m_DatabasePDG = new TDatabasePDG();
0036   //} //if
0037 } // DelphesConfig::DelphesConfig()
0038 
0039 // -------------------------------------------------------------------------------------
0040 
0041 MassHypothesis *DelphesConfig::AddMassHypothesisCore(TParticlePDG *pdg, 
0042                              double max_contamination_left, 
0043                              double max_contamination_right) 
0044 {
0045   // Apply certain sanity checks;
0046   if (!pdg) return 0;
0047   auto hypothesis = new MassHypothesis(pdg, max_contamination_left, max_contamination_right);
0048   if (!hypothesis) return 0;
0049 
0050   // Sanity check;
0051   MassHypothesis *prev = m_MassHypotheses.size() ? m_MassHypotheses.back() : 0;
0052   if (prev && pdg->Mass() <= prev->Mass()) {
0053     printf("Particle masses are not in ascending order (%7.4f is followed by %7.4f)\n", 
0054        prev->Mass(), pdg->Mass());
0055     exit(1);
0056   } //if
0057   m_MassHypotheses.push_back(hypothesis);
0058   //printf("-> %f\n", pdg->Mass());
0059 
0060   if (max_contamination_left != 1.0 || max_contamination_right != 1.0)
0061     m_EfficiencyContaminationMode = true;
0062 
0063   return hypothesis;
0064 } // DelphesConfig::AddMassHypothesisCore()
0065 
0066 // -------------------------------------------------------------------------------------
0067 
0068 MassHypothesis *DelphesConfig::AddMassHypothesis(int pdg, 
0069                          double max_contamination_left, 
0070                          double max_contamination_right) 
0071 {
0072   return AddMassHypothesisCore(m_DatabasePDG->GetParticle(pdg), 
0073                    max_contamination_left, max_contamination_right);
0074 } // DelphesConfig::AddMassHypothesis()
0075 
0076 // -------------------------------------------------------------------------------------
0077 
0078 MassHypothesis *DelphesConfig::AddMassHypothesis(const char *pname, 
0079                          double max_contamination_left, 
0080                          double max_contamination_right) 
0081 {
0082   return AddMassHypothesisCore(m_DatabasePDG->GetParticle(pname), 
0083                    max_contamination_left, max_contamination_right);
0084 } // DelphesConfig::AddMassHypothesis()
0085 
0086 // -------------------------------------------------------------------------------------
0087 
0088 MomentumRange *EtaRange::GetMomentumRange(double min, double max)
0089 {
0090   for(auto mrange: m_MomentumRanges) 
0091     if (mrange->GetMin() == min && mrange->GetMax() == max)
0092       return mrange;
0093 
0094   auto mrange = new MomentumRange(min, max);
0095   m_MomentumRanges.push_back(mrange);
0096   
0097   return mrange;
0098 } // EtaRange::GetMomentumRange()
0099 
0100 // -------------------------------------------------------------------------------------
0101 
0102 bool DelphesConfig::StoreSigmaEntry(MomentumRange *mrange, int pdg, double measurement, 
0103                     double sigma)
0104 {
0105   // Check that at least 'pdg' code is in order;
0106   unsigned mdim = mrange->GetSigmaCount();
0107 
0108   // This can not be for sure;
0109   if (mdim == m_MassHypotheses.size()) return false;
0110 
0111   if (pdg != m_MassHypotheses[mdim]->PdgCode()) return false;
0112 
0113   mrange->AddSigmaValue(measurement, sigma);
0114 
0115   return true;
0116 } // DelphesConfig::StoreSigmaEntry()
0117 
0118 // -------------------------------------------------------------------------------------
0119 
0120 bool DelphesConfig::StoreSigmaEntry(MomentumRange *mrange, int pdg, double sigma)
0121 {
0122   return StoreSigmaEntry(mrange, pdg, 0.0, sigma);
0123 } // DelphesConfig::StoreSigmaEntry()
0124 
0125 // -------------------------------------------------------------------------------------
0126 
0127 void DelphesConfig::AddZeroSigmaEntries( void )
0128 {
0129   for(auto erange: m_EtaRanges) 
0130     for(auto mrange: erange->m_MomentumRanges) {
0131       unsigned mdim = mrange->GetSigmaCount();
0132 
0133       for(unsigned iq=mdim; iq<m_MassHypotheses.size(); iq++)
0134     StoreSigmaEntry(mrange, m_MassHypotheses[iq]->PdgCode(), 0.0);
0135     } //for erange..mrange
0136 
0137   DetermineThresholds();
0138 } // DelphesConfig::AddZeroSigmaEntries()
0139 
0140 // -------------------------------------------------------------------------------------
0141 
0142 void DelphesConfig::DetermineThresholds( void )
0143 {
0144   for(unsigned ih=0; ih<m_MassHypotheses.size(); ih++) {
0145     auto hypo = m_MassHypotheses[ih];
0146 
0147     // Find the smallest non-zero entry;
0148     for(auto erange: m_EtaRanges) 
0149       for(auto mrange: erange->m_MomentumRanges) {
0150     double min = mrange->GetMin();
0151     // Called from DelphesConfig::AddZeroSigmaEntries() internally -> all 
0152     // sigma entries for all hypotheses must be present;
0153     if (mrange->GetSigma(ih) && (!hypo->GetThreshold() || hypo->GetThreshold() > min))
0154       hypo->SetThreshold(min);
0155       } //for erange..mrange
0156 
0157     printf("@T@ %d -> %7.2f\n", ih, hypo->GetThreshold());
0158   } //for iq
0159 } // DelphesConfig::DetermineThresholds()
0160 
0161 // -------------------------------------------------------------------------------------
0162 
0163 void DelphesConfig::Print( void )
0164 {
0165   for(auto erange: m_EtaRanges) {
0166     printf("@D@ eta %4.2f .. %4.2f\n", erange->GetMin(), erange->GetMax());
0167  
0168     for(auto mrange: erange->m_MomentumRanges) {
0169       printf("@D@       momentum %5.2f .. %5.2f -> sigma:", 
0170          mrange->GetMin(), mrange->GetMax());
0171       
0172       for(unsigned iq=0; iq<mrange->GetSigmaCount(); iq++)
0173     printf("      %5.2f (%4d)", mrange->GetSigma(iq), m_MassHypotheses[iq]->PdgCode());
0174       printf("\n");
0175     } //for mrange
0176   } //for erange
0177 } // DelphesConfig::AddZeroSigmaEntries()
0178 
0179 // -------------------------------------------------------------------------------------
0180 
0181 EtaRange *DelphesConfig::AddEtaRange(double min, double max) 
0182 {
0183   // First try to find already existing one;
0184   for(auto erange: m_EtaRanges) 
0185     if (erange->GetMin() == min && erange->GetMax() == max)
0186       return erange;
0187 
0188   auto erange = new EtaRange(min, max);
0189   auto prev = m_EtaRanges.size() ? m_EtaRanges.back() : 0;
0190   if (prev && min != prev->GetMax()){
0191     printf("Eta ranges sequence issue: %6.2f is followed by %6.2f\n", 
0192        prev->GetMax(), min);
0193     return 0;
0194   } //for if
0195   m_EtaRanges.push_back(erange);
0196   
0197   return erange;
0198 } // DelphesConfig::AddEtaRange()
0199 
0200 // -------------------------------------------------------------------------------------
0201 
0202 int DelphesConfig::Check(bool rigorous)
0203 {
0204   if (m_EtaRanges.empty()) _ERROR_("No eta ranges defined!");
0205 
0206   // Define eta(min) and eta(max);
0207   m_EtaMin = m_EtaRanges.front()->GetMin();
0208   m_EtaMax = m_EtaRanges.back ()->GetMax();
0209 
0210   // Define momentum ranges; for now there is no reason to assume they can be different 
0211   // for different eta; generalize later if really needed;
0212   for(auto erange: m_EtaRanges) {
0213     if (!erange->GetMomentumRangeCount()) _ERROR_("Empty eta range defined!");
0214 
0215     // First eta range: assign momentum range; 
0216     if (erange == m_EtaRanges.front()) {
0217       m_MomentumMin = erange->FirstMomentumRange()->GetMin();
0218       m_MomentumMax = erange->LastMomentumRange ()->GetMax();
0219       
0220       continue;
0221     } //if
0222     
0223     // Subsequent eta ranges: check that momentum range is the same;
0224     if (erange->FirstMomentumRange()->GetMin() != m_MomentumMin || 
0225     erange->LastMomentumRange() ->GetMax() != m_MomentumMax) 
0226       _ERROR_("Full momentum range should be the same in all eta ranges!");
0227 
0228     if (rigorous)
0229       for(auto mrange: erange->m_MomentumRanges) 
0230     if (mrange->GetSigmaCount() != m_MassHypotheses.size())
0231       _ERROR_("Momentum range entry has wrong number of sigma values!"); 
0232   } //for erange
0233   
0234   return 0;
0235 } // DelphesConfig::Check()
0236 
0237 // -------------------------------------------------------------------------------------
0238 
0239 void DelphesConfig::WriteMassHypothesis(FILE *fout, unsigned ih)
0240 {
0241   unsigned dim = m_MassHypotheses.size();
0242   const char *pstr = m_PtMode ? "pt" : "pt * cosh(eta)";
0243 
0244   auto prev = ih                              ?     m_MassHypotheses[ih-1] : 0;
0245   auto hypo =                                       m_MassHypotheses[ih  ];
0246   auto next = ih == m_MassHypotheses.size()-1 ? 0 : m_MassHypotheses[ih+1];
0247   MassHypothesis *arr[3] = {prev, hypo, next};
0248 
0249   for(unsigned ip=0; ip<3; ip++) {
0250     auto hto = arr[ip];
0251 
0252     if (hto) {
0253       fprintf(fout, "\n");
0254       fprintf(fout, "    add EfficiencyFormula {%d} {%d} {\n", hypo->PdgCode(), 
0255           hto->PdgCode());
0256       
0257       // Now the tricky part comes; calculate the actual entries; start with the out-of-area cut;
0258       fprintf(fout, "      (eta<%6.2f || eta>=%6.2f || %s < %7.2f || %s >= %7.2f) * ( 0.00 ) +\n", 
0259           m_EtaMin, m_EtaMax, pstr, m_MomentumMin, pstr, m_MomentumMax);
0260       
0261       // Then add eta and momentum range entries;
0262       for(auto erange: m_EtaRanges) {
0263     double emin = erange->GetMin(), emax = erange->GetMax();
0264     
0265     for(auto mrange: erange->m_MomentumRanges) {
0266       fprintf(fout, "      (%6.2f <= eta && eta < %6.2f) * (%7.2f <= %s && %s < %7.2f) * (%8.6f)%s\n",
0267           emin, emax, mrange->GetMin(), pstr, pstr, mrange->GetMax(), 
0268           mrange->m_Matrix[ih*dim + ih + ip - 1],
0269           erange == m_EtaRanges.back() && mrange == erange->m_MomentumRanges.back() ? "" : " +"); 
0270       
0271     } //for mrange
0272       } //for erange
0273       
0274       fprintf(fout, "    }\n");
0275     } //if
0276   } //for ip
0277 } // DelphesConfig::WriteMassHypothesis()
0278 
0279 // -------------------------------------------------------------------------------------
0280 
0281 void DelphesConfig::WriteTcl(bool check)
0282 {
0283   // First check that the configuration is self-consistent;
0284   if (check && Check()) return;
0285   if (Calculate()) return;
0286 
0287   auto fout = fopen((m_Name + ".tcl").c_str(), "w");
0288   if (!fout) {
0289     printf("Failed to open output file!\n");
0290     exit(1);
0291   } //if
0292 
0293   // Write header first; do not care much about cleanness;
0294   fprintf(fout, "module IdentificationMap %s {\n", m_Name.c_str());
0295   fprintf(fout, "  set InputArray TrackMerger/tracks\n");
0296   fprintf(fout, "  set OutputArray tracks\n");
0297   //fprintf(fout, "\n");
0298   
0299   // Essential part; loop through all mass hypotheses; the first and the 
0300   // last one will have two entries, the one(s) in the middle - three; 
0301   for(unsigned ih = 0; ih<m_MassHypotheses.size(); ih++) 
0302     WriteMassHypothesis(fout, ih);
0303 
0304   // Write trailer;
0305   fprintf(fout, "\n");
0306   fprintf(fout, "  add EfficiencyFormula {0} {0} { 0.00 }\n");
0307   fprintf(fout, "}\n");
0308   
0309   fclose(fout);
0310 } // DelphesConfig::WriteTcl()
0311 
0312 // -------------------------------------------------------------------------------------
0313 
0314 MassHypothesis *DelphesConfig::GetMassHypothesis(int pdg, bool ignore_sign)
0315 {
0316   for(auto hypo: m_MassHypotheses)
0317     if (pdg == hypo->PdgCode() || 
0318     (ignore_sign && pdg == abs(hypo->PdgCode())))
0319       return hypo;
0320     
0321   return 0;
0322 } // DelphesConfig::GetMassHypothesis()
0323 
0324 // -------------------------------------------------------------------------------------