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");
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
00049
00050 if(type1.compare("TMBMuon")==0 || type1=="muon"|| type1=="Muon") {
00051 _obj1 = MUON ;
00052
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
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
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
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 }
00157
00158 bool ResSelector::processEvent(cafe::Event& event)
00159 {
00160 StatPointer stat ;
00161 event.get("StatPointer", stat) ;
00162
00163
00164
00165
00166
00167
00168
00169
00170 const TMBLorentzVector *first = 0, *second = 0 ;
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;
00243
00244
00245 stat.EventSelected(name()+": Invarian mass selection") ;
00246
00247
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
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 }
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
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
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
00352
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
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
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 }
00469
00470
00471 ClassImp(caf_util::ResSelector);