Main Page | Modules | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members

ResSelector.cpp

Go to the documentation of this file.
00001 #include "caf_util/ResSelector.hpp"
00002 #include "kinem_util/AnglesUtil.hpp"
00003 #include "cafe/Function.hpp"
00004 #include "cafe/Config.hpp"
00005 #include "cafe/Stat.hpp"
00006 #include "TH1.h"
00007 #include <iostream>
00008 #include <string>
00009 #include <sstream>
00010 
00011 using namespace cafe; 
00012 using namespace std;
00013 
00014 namespace caf_util {
00015   ResSelector::ResSelector(const char *name) : Processor(name), 
00016                                                _vars1("fX", "fY", "fZ"), 
00017                                                _vars2("fX", "fY", "fZ"),
00018                                                _masshist(0) {
00019     
00020     Config config(name);
00021     branch1 = config.get("Branch1","Muon");
00022     branch2 =  config.get("Branch2",branch1);
00023     
00024     _target_mass = config.get("target_mass",-1.0);
00025     _low_window = config.get("lower_mass_bound", -1.0);
00026     _high_window = config.get("upper_mass_bound",-1.0);
00027     _hist_lower = config.get("hist_lower",0.);
00028     _hist_upper = config.get("hist_upper",120.);
00029     _hist_bins = config.get("hist_bins", 0);
00030     string type1 = config.get("Object1_type","TMBLorentzVector");
00031     string type2 = config.get("Object2_type","TMBLorentzVector");
00032     _pt1_method = config.get("Object1_method","best");
00033     _pt2_method = config.get("Object2_method","best");
00034     _useEOPetrack = config.get("UseEOPTrackMatchElectron", false) ;
00035 
00036     string charges = config.get("Charge","noselection");  // noselection or opposite or samesign
00037     
00038     if (charges.find("opposite") != string::npos) _charge_req = OPPOSITESIGN ;
00039     else if (charges.find("samesign") != string::npos) _charge_req = SAMESIGN ;
00040     else if (charges.find("noselection") != string::npos) _charge_req = NOSELECTION ;
00041     else {
00042       err() << "ResSelector WARNING: "
00043             << " option ChargeSign = \"" << charges << "\" is not reconized!"
00044             << endl ;
00045       exit(1) ;
00046     }
00047      
00048     //check the types and set up the appropriate case.  Muon-muon, mu-e, e-e, mu-jet, etc.
00049     
00050     if(type1.compare("TMBMuon")==0 || type1=="muon"|| type1=="Muon") {
00051       _obj1 = MUON ;
00052       //print an error message if someone tries to to the cal method with a muon
00053        if(_pt1_method=="cal" || _pt1_method == "calorimeter") 
00054          {
00055            err() << " ResSelector named \"" << name 
00056                  << "\" ERROR: "
00057                  <<"Calorimeter pT methods not available for muons."<<endl;
00058            exit(1) ;
00059          }       
00060     } else if(type1=="TMBEMCluster"||type1=="electron"|| type1=="Electron")
00061       _obj1 = ELECTRON ;
00062     else if(type1=="TMBJet"||type1=="jet"|| type1=="Jet") {
00063       _obj1 = JET;
00064        //error message if someone does the track method with a jet
00065       if(_pt1_method=="track" || _pt1_method == "Track") {
00066         err() << " ResSelector named \"" << name 
00067               << "\" ERROR: "
00068               << "Track pT determination methods not available for jets. " 
00069               << endl ;
00070          exit(1) ;
00071       }
00072     } else if (type1 != "TMBLorentzVector") {
00073       err() << " ResSelector named \"" << name 
00074             << "\" ERROR: Option \"Object1_type: " << type1 
00075             << "\" has wrong value \"" << type1 << "\""
00076             << endl ;
00077       exit(1) ;  
00078     } else _obj1 = LORENTZVECTOR;
00079     
00080     
00081     if(type2.compare("TMBMuon")==0 || type2=="muon"|| type2=="Muon") {
00082       _obj2 = MUON ;
00083       //print an error message if someone tries to to the cal method with a muon
00084       if(_pt1_method=="cal" || _pt1_method == "calorimeter") 
00085          {
00086            err() << " ResSelector named \"" << name 
00087                  << "\" ERROR: "
00088                  <<"Calorimeter pT methods not available for muons."<<endl;
00089            exit(1) ;
00090          }       
00091     } else if(type2=="TMBEMCluster"||type2=="electron"|| type2=="Electron")
00092       _obj2 = ELECTRON ;
00093      else if(type2=="TMBJet"||type2=="jet"|| type2=="Jet") {
00094        _obj2 = JET;
00095        //error message if someone does the track method with a jet
00096        if(_pt1_method=="track" || _pt1_method == "Track") {
00097          err() << " ResSelector named \"" << name 
00098              << "\" ERROR: "
00099                << "Track pT determination methods not available for jets. " 
00100                << endl ;
00101          exit(1) ;
00102        }
00103      } else if (type2 != "TMBLorentzVector") {
00104        err() << " ResSelector named \"" << name 
00105              << "\" ERROR: Option \"Object1_type: " << type2 
00106              << "\" has wrong value \"" << type2 << "\""
00107              << endl ;
00108        exit(1) ;         
00109      } else _obj2 = LORENTZVECTOR;
00110 
00111 
00112     if (_obj1==MUON) {
00113       _vars1.add("_chptr") ;
00114       _vars1.add("_hasCentral") ;
00115       if (charges != NOSELECTION) {
00116         _vars1.add("_best") ;
00117         _vars1.add("_localcorr._charge") ;
00118         _vars1.add("_centralcorr._charge") ;
00119         _vars1.add("_smearedMC._charge") ;
00120       }
00121     }
00122 
00123     if (_obj2==MUON) {
00124       _vars2.add("_chptr") ;
00125       _vars2.add("_hasCentral") ;
00126       if (charges != NOSELECTION) {
00127         _vars2.add("_best") ;
00128         _vars2.add("_localcorr._charge") ;
00129         _vars2.add("_centralcorr._charge") ;
00130         _vars2.add("_smearedMC._charge") ;
00131       }
00132     }
00133 
00134     if (_obj1==ELECTRON) {
00135       if (_useEOPetrack) {
00136         _vars1.add("_SpatialTrMatchChi2Prob") ;
00137         _vars1.add("_chptrBest") ;
00138       } else {
00139         _vars1.add("_SpatialTrMatchChi2ProbBest") ;
00140         _vars1.add("_chptr") ;
00141       }
00142       if (charges != NOSELECTION) _vars1.add("_q") ;
00143     }
00144 
00145     if (_obj2==ELECTRON) {
00146       if (_useEOPetrack) {
00147         _vars2.add("_SpatialTrMatchChi2Prob") ;
00148         _vars2.add("_chptrBest") ;
00149       } else {
00150         _vars2.add("_SpatialTrMatchChi2ProbBest") ;
00151         _vars2.add("_chptr") ;
00152       }
00153       if (charges != NOSELECTION) _vars2.add("_q") ;
00154     }
00155     
00156   }//end constructor
00157   
00158   bool ResSelector::processEvent(cafe::Event& event)    
00159   {
00160     StatPointer stat ;
00161     event.get("StatPointer", stat) ;
00162     
00163     
00164      /* switch for the different cases.   
00165         The calculation is done exactly the same way each time; 
00166         only the types of collections change, depending on the case.  
00167      */     
00168     
00169 
00170     const TMBLorentzVector *first = 0, *second = 0 ; // objects forming the mass
00171     
00172     const TClonesArray* col1 = event.getClonesArray(branch1,_vars1) ;
00173     const TClonesArray* col2 = event.getClonesArray(branch2,_vars2) ;
00174     
00175     if (!col1) {
00176       err() << "caf_util::ResSelector named \"" << name()
00177             << "\" ERROR: branch \"" << branch1 << "\" could not be found!"
00178             << endl ;
00179       return false ; 
00180     }
00181 
00182     if (!col2) {
00183       err() << "caf_util::ResSelector named \"" << name()
00184             << "\" ERROR: branch \"" << branch2 << "\" could not be found!"
00185             << endl ;
00186       return false ; 
00187     }
00188 
00189     double rec_mass = -1.0 ;
00190     
00191     for (int i=0; i <= col1->GetLast(); i++) {
00192       
00193       const TMBLorentzVector* v1 = (const TMBLorentzVector*) col1 -> At(i);
00194       
00195       double pt1  = -1.0, eta1 = -10.0, phi1 = -10.0 ;
00196       int charge1 = 0;
00197       
00198       if (_obj1 == MUON) {
00199         if (!GetMuon(* dynamic_cast<const TMBMuon*> (v1), 
00200                      _pt1_method, pt1, eta1, phi1, charge1)) continue ;
00201       } else if (_obj1 == ELECTRON) {
00202         if (!GetElectron(* dynamic_cast<const TMBEMCluster*> (v1),  
00203                          _pt1_method, pt1, eta1, phi1, charge1)) continue ;
00204       } else {
00205         pt1 = v1->Pt() ;
00206         eta1 = v1->Eta() ;
00207         phi1 = v1->Phi() ;
00208         charge1 = 0 ;
00209       }
00210       
00211      int j = 0 ;
00212      if (branch1 == branch2) {
00213        if (i < col2->GetLast()) j = i+1 ;
00214        else continue ;
00215      }
00216      for (; j <= col2->GetLast(); j++) {
00217       
00218         const TMBLorentzVector* v2 = (const TMBLorentzVector*) col2 -> At(j);
00219         
00220         double pt2  = -1.0, eta2 = -10.0, phi2 = -10.0 ;
00221         int charge2 = 0 ;
00222         
00223         if (_obj2 == MUON) {
00224           if (!GetMuon(* dynamic_cast<const TMBMuon*> (v2), 
00225                        _pt2_method, pt2, eta2, phi2, charge2)) continue ;
00226         } else if (_obj2 == ELECTRON) {
00227           if (!GetElectron(* dynamic_cast<const TMBEMCluster*> (v2),
00228                            _pt2_method, pt2, eta2, phi2, charge2)) continue ;
00229         } else {
00230           pt2 = v2->Pt() ;
00231           eta2 = v2->Eta() ;
00232           phi2 = v2->Phi() ;
00233           charge2 = 0 ;
00234         }
00235         
00236         if (!mass(pt1, eta1, phi1, charge1, pt2, eta2, phi2, charge2, rec_mass)) continue ;
00237         first = v1 ;
00238         second = v2 ;
00239       }
00240     }
00241     
00242     if(rec_mass < 0) return false;// false will end event processing   
00243 
00244     //stat pointer stuff
00245     stat.EventSelected(name()+": Invarian mass selection") ; 
00246 
00247     //save the objects that form the resonance
00248     const TMBEMCluster *pe  = 0 ;
00249     const TMBMuon *pm  = 0 ;
00250     const TMBJet *pj  = 0 ;
00251     if (first) {
00252       if (pe = dynamic_cast<const TMBEMCluster*>(first))
00253         event.put(name()+":EM1", new TMBEMCluster(*pe)) ; 
00254 
00255       else if (pm = dynamic_cast<const TMBMuon*>(first))
00256         event.put(name()+":Muon1", new TMBMuon(*pm)) ; 
00257 
00258       else if (pj = dynamic_cast<const TMBJet*>(first))
00259         event.put(name()+":Jet1", new TMBJet(*pj)) ; 
00260 
00261       else 
00262         event.put(name()+":LorentzVector1", first) ; 
00263     }
00264     
00265     pe = 0 ; pm = 0 ; pj = 0 ;
00266 
00267     if (second) {
00268       if (pe = dynamic_cast<const TMBEMCluster*>(second))
00269         event.put(name()+":EM2", new TMBEMCluster(*pe)) ; 
00270 
00271       else if (pm = dynamic_cast<const TMBMuon*>(second))
00272         event.put(name()+":Muon2", new TMBMuon(*pm)) ; 
00273 
00274       else if (pj = dynamic_cast<const TMBJet*>(second))
00275         event.put(name()+":Jet2", new TMBJet(*pj)) ; 
00276 
00277       else 
00278         event.put(name()+":LorentzVector2", second) ; 
00279     }
00280     
00281     //output the  mass as well
00282     event.put(name()+":ResMass", (double) rec_mass);
00283     if(_masshist) _masshist->Fill(rec_mass); 
00284 
00285 
00286     if (debug() > 1) 
00287       out() << "caf_util::ResSelector named \"" << name() 
00288             << "\" invariant mass " << rec_mass << " GeV" << endl ;
00289 
00290     return true; 
00291     
00292   }    //processEvent
00293   
00294   
00295   void ResSelector::begin() {
00296     getDirectory()->cd();
00297     if(_hist_bins>0)
00298       _masshist = new TH1D(("masshist_"+name()).c_str(), "Invariant mass",
00299                            _hist_bins, _hist_lower, _hist_upper); 
00300   } 
00301   
00302   
00303   bool ResSelector::mass(double pt1, double eta1, double phi1, int charge1,
00304                          double pt2, double eta2, double phi2, int charge2, 
00305                          double& mass) {
00306     if (pt1 < 0 || pt2 < 0 || 
00307         eta1 < -9.9 || eta2 < -9.9 ||
00308         phi1 < -9.9 || phi2 < -9.9 ) {
00309       err() << "caf_util::ResSelector named \"" << name()
00310             << "\" ERROR: pt or eta or phi out of range!" << endl 
00311             << " pt1 = " << pt1 << " eta1 = " << eta1 << " phi1 = " << phi1 << endl
00312             << " pt2 = " << pt2 << " eta2 = " << eta2 << " phi2 = " << phi2 << endl ;
00313       return -1.0 ;
00314     } 
00315     
00316     if (_charge_req != NOSELECTION && (charge1 ==0 || charge2 ==0) ) {
00317       warn() << "ResSelector WARNING: "
00318              << " The charge selection is set to " ;
00319       if (_charge_req == OPPOSITESIGN) warn() << " \"opposite\" " ;
00320       if (_charge_req == SAMESIGN) warn() << " \"samesign\" " ;
00321       warn() << " but charge is not defined for the selected objects!"
00322              << endl ;       
00323       return false ;
00324     }
00325     if(_charge_req == OPPOSITESIGN && 
00326        ((charge1 >= 0 && charge2 >= 0) || (charge1 <= 0 && charge2 <= 0)) ) return false ;
00327     if(_charge_req == SAMESIGN &&
00328        ((charge1 >= 0 && charge2 <= 0) || (charge1 <= 0 && charge2 >=0)) ) return false ;
00329        
00330     //do the invariant mass calculation, assuming mass of the doughter particles is negligible compare to the parent
00331     double calc_mass = 2.*pt1*pt2*(cosh(eta1 - eta2)- cos(kinem::signed_delta_phi(phi1,phi2))) ;
00332      if (calc_mass < 0) {
00333        err() << "ResSelector ERROR: "
00334              << " error in the invariant mass calculation."
00335              << endl ;
00336        return false ;
00337      }
00338      
00339      calc_mass = sqrt(calc_mass) ;
00340      
00341      //make sure the mass is within the user-defined window
00342      if(_low_window >= 0 && calc_mass < _low_window) return false ;
00343      if (_high_window >= 0 &&  calc_mass > _high_window) return false ;
00344      
00345      if (mass < 0 ) {
00346        mass = calc_mass ;
00347        return true ;
00348      }
00349      
00350      if (_target_mass >= 0) {
00351        // if this latest resonance was is closer than the previous minimum, 
00352        // choose this pair as the new candidate            
00353        if(fabs(calc_mass - _target_mass)< fabs(mass - _target_mass)) {
00354          mass = calc_mass ;
00355          return true ;
00356        }
00357      } else {
00358        if(calc_mass > mass) {
00359          mass = calc_mass ;
00360          return true ;
00361        }
00362      }
00363      return false ;   
00364   }
00365 
00366 //---------------------------------------------------------------------------------
00367 
00368   bool ResSelector::GetMuon(const TMBMuon& muon, const string& pt_method,
00369                              double& pt, double& eta, double& phi, int& charge) {
00370      
00371      
00372      //determine where to get the pt from 
00373      if(pt_method == "track" || pt_method == "Track")
00374        {
00375          if (!muon.hasCentral()) {
00376            warn() << "ResSelector WARNING! "
00377                   << "You should use only muon with central track macthed when"
00378                   << " invarinat mass is calculated with track pT."
00379                   << endl ;
00380            return false ;
00381          }
00382          
00383          const TMBTrack* trk = muon.GetChargedTrack() ;
00384          if(!trk) {
00385            err() << "ResSelector ERROR: "
00386                  << " Track pointer is 0 for the track macthed muon!"
00387                  << endl ;
00388            return false ;
00389          }
00390          
00391          pt = trk->Pt();
00392          phi = trk->Phi();
00393          eta = trk->Eta();
00394          charge = trk->charge() ;
00395          
00396        } else {       
00397        eta = muon.Eta();
00398        pt = muon.Pt(); 
00399        phi = muon.Phi();
00400        charge = muon.charge() ;              
00401      }
00402 
00403      return true ;
00404    }
00405 
00406 
00407   bool ResSelector::GetElectron(const TMBEMCluster& electron, const string& pt_method,
00408                                 double& pt, double& eta, double& phi, int& charge) {
00409     
00410     //determine where to get the pt from 
00411     if(pt_method == "track" || pt_method == "Track") {
00412         const TMBTrack* trk  = 0 ;
00413         if ( (_useEOPetrack && !electron.has_track_match(0.0) ) ||
00414              (!_useEOPetrack && !electron.has_spatial_track_match(0.0))) {
00415           warn() << "ResSelector WARNING! "
00416                  << "You should use only electron with track macthed when"
00417                  << " invarinat mass is calculated with track pT."
00418                  << endl ;
00419           return false ;
00420         }
00421 
00422         if (!_useEOPetrack) 
00423           trk = electron.GetChargedTrack() ;
00424         else 
00425           trk = electron.getPtrChp() ;
00426 
00427         if(!trk) {
00428           err() << "ResSelector ERROR: "
00429                 << " Track pointer is 0 for the track macthed electron!"
00430                 << endl ;
00431           return false ;
00432         }
00433         
00434         pt = trk->Pt();
00435         phi = trk->Phi();
00436         eta = trk->Eta();
00437         charge = trk->charge() ;
00438         
00439       } else {       
00440       
00441       eta = electron.Eta();
00442       pt = electron.Pt(); 
00443       phi = electron.Phi();
00444       if (!_useEOPetrack) charge = (int) electron.charge() ;
00445       else {
00446         const TMBTrack* trk  = 0 ;
00447         if ( !electron.has_track_match(0.0)) {
00448           warn() << "ResSelector WARNING! "
00449                   << "You should use only electron with track macthed when"
00450                  << " determine charge with EOP track matched electron."
00451                  << endl ;
00452          return false ;
00453         }
00454         
00455         trk = electron.getPtrChp() ;
00456         if(!trk) {
00457           err() << "ResSelector ERROR: "
00458                 << " Track pointer is 0 for the track macthed electron!"
00459                 << endl ;
00460           return false ;
00461         }
00462         charge = (int) trk->charge() ;
00463       }
00464     }
00465     return true ;
00466   }
00467 
00468 }//namespace caf_util
00469 
00470   
00471 ClassImp(caf_util::ResSelector);

Generated on Tue Mar 28 10:13:04 2006 for CAF by doxygen 1.3.4