void getCeF3Position( std::vector<float> cef3, float& xPos, float& yPos ) {

  xPos=0.;
  yPos=0.;

  float r02 = cef3[0]/cef3[2];
  float r13 = cef3[1]/cef3[3];

  TF1* f1_d02 = getCef3Function("diag02");
  TF1* f1_d13 = getCef3Function("diag13");

  float diag02 = f1_d02->GetX(r02, -50., 50.);
  float diag13 = f1_d13->GetX(r13, -50., 50.);

  TVector2 v( diag13, diag02 );
  float pi = 3.14159;
  float theta = pi/4.; // 45 degrees 
  TVector2 d = v.Rotate(+theta);

  xPos = d.X();
  yPos = d.Y();
  //xPos = diag02;
  //yPos = diag13;


  delete f1_d02;
  delete f1_d13;

}
Example #2
0
TVector2 HashTable::Discretize(TVector2 position) {
  position /= _NG_H_;
  position.Set(
    floor(position.X()),
    floor(position.Y())
  );
  return position;
}
Example #3
0
int Load3ds::CompileObjects()
{
#ifdef GRAPHICS_DEBUG
	FILE* file = NULL;
	file = fopen("normals.out", "w+");
	assert( file );
#endif

	int j = 0;
	TVector3<float> position, normal;
	TVector2<float> texCoord;

	// the number of faces * 3: 3 indices per face
	for (int i = 0; i < mModelData->mFaceCount * 3; i+=3)
	{
		mMesh->addTriangleIndices(mModelData->mFaces[ i ], 
			mModelData->mFaces[i + 1], mModelData->mFaces[i + 2]);
	}

	// set up all the information: position, normal and eventually
	// the texture coordinates, and compile them into our TVertex class
	for (int i = 0; i < mModelData->mVertexCount; i++)
	{
		j = i * 3;

		position.setX( mModelData->mVertices[ j ] );
		position.setY( mModelData->mVertices[j + 1] );
		position.setZ( mModelData->mVertices[j + 2] );

		normal.setX( mModelData->mNormals[ j ] );
		normal.setY( mModelData->mNormals[j + 1] );
		normal.setZ( mModelData->mNormals[j + 2] );

#ifdef GRAPHICS_DEBUG
		fprintf(file, "%i: X: %f, Y: %f, Z: %f\n", i, normal.x(), normal.y(), 
			normal.z());
#endif

		if ( mModelData->mContainsTexCoords )
		{
			// stride: one face -> 2 texture coordinates
			j = i * 2;

			texCoord.setX( mModelData->mTexCoords[ j ] );
			texCoord.setY( mModelData->mTexCoords[j + 1] );
		}

		mMesh->addVertex( TVertex(normal, position, texCoord) );
	}

#ifdef GRAPHICS_DEBUG
	fclose( file );
#endif

	return 1;
}
Example #4
0
void test::runtest3()
{
  TLorentzVector v1,v2,vds;
  double ecm = 14000.0;
  double mxlo = 0.0;
  TVector2 ptm;
  TMctLib t;

  // CGL/AB ExampleEvent.h: numerical = 412.629
  v1.SetPxPyPzE(410.0,20.0,-20.0,422.9657197);
  v2.SetPxPyPzE(-210.0,-300.0,44.0,398.1657946);
  vds.SetPxPyPzE(0,0,0,0);
  ptm.Set(-200.0,280.0);
  mxlo = 100.0;

//   // QCD J7
//   double in[10] = {1.258670e+05,1.571520e+06,1.572370e+05,9.757710e+04
//  ,-1.183100e+06,1.479710e+04,-5.753920e+04,-2.356870e+02,1.258670e+05,4.443730e+05};
//   double in[10] = {6.256940e+04,1.288650e+05,1.180090e+06,7.800940e+04
//  ,-1.329990e+05,-1.089660e+06,7.652250e+02,-8.213820e+04,8.228860e+04,4.454130e+05};
//   double in[10] = {1.341360e+05,3.326890e+05,-1.283550e+06,9.644650e+04
//  ,-6.514870e+04,1.149020e+06,1.437980e+03,9.277770e+04,1.341360e+05,5.101580e+05};
//   double in[10] = {9.235300e+04,-3.740560e+05,-1.064090e+06,1.830350e+05
//  ,3.642610e+05,1.065280e+06,-1.448250e+03,-3.466820e+04,1.830350e+05,3.324730e+05};
//   double in[10] = {9.046870e+04,1.840110e+06,6.785220e+05,9.780580e+04
//  ,-1.630920e+06,-6.143020e+05,-5.887950e+04,4.870900e+02,1.062900e+05,4.814570e+05};
//   double in[10] = {1.182120e+05,1.367560e+06,5.090250e+05,6.409280e+04
//  ,-1.290560e+06,-4.467530e+05,-2.323400e+04,-5.225580e+02,1.182120e+05,2.829080e+05};
//   double in[10] = {7.755540e+04,-9.667320e+05,7.152930e+05,1.010010e+05
//  ,8.471940e+05,-5.228630e+05,-8.270070e+02,3.081700e+04,1.043150e+05,2.405480e+05};
//   double in[10] = {9.918510e+04,-6.460480e+04,-1.343380e+06,1.204820e+05
//  ,9.848800e+04,1.335590e+06,3.381800e+02,-5.554830e+04,1.204820e+05,4.041840e+05};
//   // QCD J4
//   double in[10] = {1.990270e+04,8.762820e+03,1.808790e+05,1.786660e+04
//  ,-1.777620e+04,-1.537630e+05,-1.771590e+02,-4.196540e+04,2.149110e+04,1.250350e+05};
//   // SUSY SU3
//   double in[10] = {5.393630e+04,2.803780e+05,-5.825570e+05,4.760900e+04
//  ,-3.659650e+05,2.836080e+05,1.240290e+04,2.463720e+05,2.151650e+05,5.504520e+05};
//
//   v1.SetPxPyPzE(in[1]*0.001,in[2]*0.001,0.0
// 		,sqrt(pow(in[1],2)+pow(in[2],2)+pow(in[0],2))*0.001);
//   v2.SetPxPyPzE(in[4]*0.001,in[5]*0.001,0.0
// 		,sqrt(pow(in[4],2)+pow(in[5],2)+pow(in[3],2))*0.001);
//   vds.SetPxPyPzE(0,0,0,0);
//   ptm.Set(in[6]*0.001,in[7]*0.001); 
//   cout<<in[8]*0.001<<" "<<t.mt2(v1,v2,vds,ptm,ecm,mxlo)<<endl;

  cout<<"MCT = "<<t.mct(v1,v2)
      <<", MCTcorr = "<<t.mctcorr(v1,v2,vds,ptm,ecm,mxlo)
      <<", MT2 = "<<t.mt2(v1,v2,vds,ptm,ecm,mxlo)
      <<", MCy = "<<t.mcy(v1,v2,vds,ptm)
      <<", MCx = "<<t.mcx(v1,v2,vds,ptm)
      <<endl;
}
Example #5
0
void testPadDimensions(AliMq::Station12Type station, AliMp::PlaneType plane)
{
  AliMpDataProcessor mp;
  AliMpDataMap* dataMap = mp.CreateDataMap("data");
  AliMpDataStreams dataStreams(dataMap);

  AliMpSectorReader r(dataStreams, station, plane);
  AliMpSector* sector = r.BuildSector();
  AliMpSectorSegmentation segmentation(sector);  
  segmentation.PrintZones(); 
  
  TVector2 previousDimensions;
  for (Int_t i=1; i<segmentation.MaxPadIndexX()+1;i++) 
    for (Int_t j=1;j<segmentation.MaxPadIndexY()+1;++j) {

       if ( segmentation.HasPadByIndices(i,j) ) {

        // Check pad dimensions
	AliMpPad pad = segmentation.PadByIndices(i,j);
	TVector2 dimensions = segmentation.PadDimensions(segmentation.Zone(pad));
	
	if ( dimensions.X() != previousDimensions.X() || 
	     dimensions.Y() != previousDimensions.Y() ) {

          // Print dimensions
	  cout << "Pad: " << "(" << i << "," << j << ")";
	  cout << "  dimensions: (" << dimensions.X() << ", " << dimensions.Y() << ")" 
	       << endl;
          
	  previousDimensions = dimensions;
        }	     
     }
   }
}
Example #6
0
std::vector<unsigned int> HashTable::FindNN(TVector2 position) {
  std::vector<unsigned int> results;
  std::vector<unsigned int> cell;
  TVector2 min = Discretize(position) - TVector2(_NG_H_,_NG_H_);
  TVector2 max = Discretize(position) + TVector2(_NG_H_,_NG_H_);

  for(TVector2 it(min); it.X() <= max.X() ; it.Set(it.X()+1,it.Y())) {
    for(it.Set(it.X(),min.Y());it.Y() <= max.Y(); it.Set(it.X(),it.Y()+1)) {
      cell.clear();
      cell = hashTable[GetHash(it)];
      results.insert(results.end(), cell.begin(), cell.end());
    }
  }

  return results;
}
Example #7
0
bool TPinholeCamera::getPlaneProjection (const TVector& rktPOINT, TVector2& rtPROJ) const
{

  TScalar   u, v;
  TScalar   pt, pu, pv;
  TVector   tPoint = (rktPOINT - tLocation);
  
  pt = dotProduct (tDirection, tPoint);
  pu = dotProduct (I, tPoint) / tPixelSize;
  pv = dotProduct (J, tPoint) / tPixelSize;

  u = tHalfResX + ((pu / pt) / tPixelSize);
  if ( ( u < 0 ) || ( u > (tHalfResX * 2) ) )
  {
    return false;
  }
  v = tHalfResY - ((pv / pt) / tPixelSize);
  if ( ( v < 0 ) || ( v > (tHalfResY * 2) ) )
  {
    return false;
  }

  rtPROJ.set (u, v);
  
  return true;
  
}  /* getPlaneProjection() */
Example #8
0
void test::runtest2()
{
  TLorentzVector v1,v2,vds;
  v1.SetPxPyPzE(-16.6153436,-58.7089565,5.63960336,61.2749243);
  v2.SetPxPyPzE(-14.7269478,-76.4887243,-85.5243885,115.679856);
  vds.SetPxPyPzE(0,0,0,0);
  double ecm = 14000.0;
  double mxlo = 0.0;
  TVector2 ptm;
  ptm.Set(4.61125178,32.6525674);
  TMctLib t;
  cout<<"MCT = "<<t.mct(v1,v2)
      <<", MCTcorr = "<<t.mctcorr(v1,v2,vds,ptm,ecm,mxlo)
      <<", MT2 = "<<t.mt2(v1,v2,vds,ptm,ecm,mxlo)
      <<", MCy = "<<t.mcy(v1,v2,vds,ptm)
      <<", MCx = "<<t.mcx(v1,v2,vds,ptm)
      <<endl;
}
Example #9
0
void selectZee(const TString conf="zee.conf", // input file
               const TString outputDir=".",   // output directory
	       const Bool_t  doScaleCorr=0    // apply energy scale corrections?
) {
  gBenchmark->Start("selectZee");

  //--------------------------------------------------------------------------------------------------------------
  // Settings 
  //============================================================================================================== 

  const Double_t MASS_LOW  = 40;
  const Double_t MASS_HIGH = 200;
  const Double_t PT_CUT    = 22;
  const Double_t ETA_CUT   = 2.5;
  const Double_t ELE_MASS  = 0.000511;
  
  const Double_t ECAL_GAP_LOW  = 1.4442;
  const Double_t ECAL_GAP_HIGH = 1.566;

  const Double_t escaleNbins  = 2;
  const Double_t escaleEta[]  = { 1.4442, 2.5   };
  const Double_t escaleCorr[] = { 0.992,  1.009 };

  const Int_t BOSON_ID  = 23;
  const Int_t LEPTON_ID = 11;

  // load trigger menu
  const baconhep::TTrigger triggerMenu("../../BaconAna/DataFormats/data/HLT_50nsGRun");

  // load pileup reweighting file
  TFile *f_rw = TFile::Open("../Tools/pileup_rw_76X.root", "read");

  // for systematics we need 3
  TH1D *h_rw = (TH1D*) f_rw->Get("h_rw_golden");
  TH1D *h_rw_up = (TH1D*) f_rw->Get("h_rw_up_golden");
  TH1D *h_rw_down = (TH1D*) f_rw->Get("h_rw_down_golden");

  if (h_rw==NULL) cout<<"WARNIG h_rw == NULL"<<endl;
  if (h_rw_up==NULL) cout<<"WARNIG h_rw == NULL"<<endl;
  if (h_rw_down==NULL) cout<<"WARNIG h_rw == NULL"<<endl;

  //--------------------------------------------------------------------------------------------------------------
  // Main analysis code 
  //==============================================================================================================  

  enum { eEleEle2HLT=1, eEleEle1HLT1L1, eEleEle1HLT, eEleEleNoSel, eEleSC };  // event category enum
  
  vector<TString>  snamev;      // sample name (for output files)  
  vector<CSample*> samplev;     // data/MC samples

  //
  // parse .conf file
  //
  confParse(conf, snamev, samplev);
  const Bool_t hasData = (samplev[0]->fnamev.size()>0);

  // Create output directory
  gSystem->mkdir(outputDir,kTRUE);
  const TString ntupDir = outputDir + TString("/ntuples");
  gSystem->mkdir(ntupDir,kTRUE);
  
  //
  // Declare output ntuple variables
  //
  UInt_t  runNum, lumiSec, evtNum;
  UInt_t  matchGen;
  UInt_t  category;
  UInt_t  npv, npu;
  UInt_t  id_1, id_2;
  Double_t x_1, x_2, xPDF_1, xPDF_2;
  Double_t scalePDF, weightPDF;
  TLorentzVector *genV=0;
  Float_t genVPt, genVPhi, genVy, genVMass;
  Float_t genWeight, PUWeight;
  Float_t scale1fb,scale1fbUp,scale1fbDown;
  Float_t met, metPhi, sumEt, u1, u2;
  Float_t tkMet, tkMetPhi, tkSumEt, tkU1, tkU2;
  Float_t mvaMet, mvaMetPhi, mvaSumEt, mvaU1, mvaU2;
  Float_t puppiMet, puppiMetPhi, puppiSumEt, puppiU1, puppiU2;
  Int_t   q1, q2;
  TLorentzVector *dilep=0, *lep1=0, *lep2=0;
  ///// electron specific /////
  Float_t trkIso1, emIso1, hadIso1, trkIso2, emIso2, hadIso2;
  Float_t pfChIso1, pfGamIso1, pfNeuIso1, pfCombIso1, pfChIso2, pfGamIso2, pfNeuIso2, pfCombIso2;
  Float_t sigieie1, hovere1, eoverp1, fbrem1, ecalE1, sigieie2, hovere2, eoverp2, fbrem2, ecalE2;
  Float_t dphi1, deta1, dphi2, deta2;
  Float_t d01, dz1, d02, dz2;
  UInt_t  isConv1, nexphits1, typeBits1, isConv2, nexphits2, typeBits2; 
  TLorentzVector *sc1=0, *sc2=0;
  
  // Data structures to store info from TTrees
  baconhep::TEventInfo *info   = new baconhep::TEventInfo();
  baconhep::TGenEventInfo *gen = new baconhep::TGenEventInfo();
  TClonesArray *genPartArr     = new TClonesArray("baconhep::TGenParticle");
  TClonesArray *electronArr    = new TClonesArray("baconhep::TElectron");
  TClonesArray *scArr          = new TClonesArray("baconhep::TPhoton");
  TClonesArray *vertexArr      = new TClonesArray("baconhep::TVertex");

  TFile *infile=0;
  TTree *eventTree=0;
  
  //
  // loop over samples
  //  
  for(UInt_t isam=0; isam<samplev.size(); isam++) {
    
    // Assume data sample is first sample in .conf file
    // If sample is empty (i.e. contains no ntuple files), skip to next sample
    Bool_t isData=kFALSE;
    if(isam==0 && !hasData) continue;
    else if (isam==0) isData=kTRUE;
    
    // Assume signal sample is given name "zee" - flag to store GEN Z kinematics
    Bool_t isSignal = (snamev[isam].CompareTo("zee",TString::kIgnoreCase)==0);  
    // flag to reject Z->ee events when selecting at wrong-flavor background events
    Bool_t isWrongFlavor = (snamev[isam].CompareTo("zxx",TString::kIgnoreCase)==0);  
    
    CSample* samp = samplev[isam];
  
    //
    // Set up output ntuple
    //
    TString outfilename = ntupDir + TString("/") + snamev[isam] + TString("_select.root");
    if(isam!=0 && !doScaleCorr) outfilename = ntupDir + TString("/") + snamev[isam] + TString("_select.raw.root");
    TFile *outFile = new TFile(outfilename,"RECREATE"); 
    TTree *outTree = new TTree("Events","Events");
    outTree->Branch("runNum",     &runNum,     "runNum/i");      // event run number
    outTree->Branch("lumiSec",    &lumiSec,    "lumiSec/i");     // event lumi section
    outTree->Branch("evtNum",     &evtNum,     "evtNum/i");      // event number
    outTree->Branch("matchGen",   &matchGen,   "matchGen/i");    // event has both leptons matched to MC Z->ll
    outTree->Branch("category",   &category,   "category/i");    // dilepton category
    outTree->Branch("id_1",       &id_1,       "id_1/i");        // PDF info -- parton ID for parton 1
    outTree->Branch("id_2",       &id_2,       "id_2/i");        // PDF info -- parton ID for parton 2
    outTree->Branch("x_1",        &x_1,        "x_1/d");         // PDF info -- x for parton 1
    outTree->Branch("x_2",        &x_2,        "x_2/d");         // PDF info -- x for parton 2
    outTree->Branch("xPDF_1",     &xPDF_1,     "xPDF_1/d");      // PDF info -- x*F for parton 1
    outTree->Branch("xPDF_2",     &xPDF_2,     "xPDF_2/d");      // PDF info -- x*F for parton 2
    outTree->Branch("scalePDF",   &scalePDF,   "scalePDF/d");    // PDF info -- energy scale of parton interaction
    outTree->Branch("weightPDF",  &weightPDF,  "weightPDF/d");   // PDF info -- PDF weight
    outTree->Branch("npv",        &npv,        "npv/i");         // number of primary vertices
    outTree->Branch("npu",        &npu,        "npu/i");         // number of in-time PU events (MC)
    outTree->Branch("genV",      "TLorentzVector",  &genV);      // GEN boson 4-vector
    outTree->Branch("genVPt",     &genVPt,     "genVPt/F");      // GEN boson pT (signal MC)
    outTree->Branch("genVPhi",    &genVPhi,    "genVPhi/F");     // GEN boson phi (signal MC)
    outTree->Branch("genVy",      &genVy,      "genVy/F");       // GEN boson rapidity (signal MC)
    outTree->Branch("genVMass",   &genVMass,   "genVMass/F");    // GEN boson mass (signal MC)
    outTree->Branch("genWeight",   &genWeight,  "genWeight/F");
    outTree->Branch("PUWeight",    &PUWeight,   "PUWeight/F");
    outTree->Branch("scale1fb",   &scale1fb,   "scale1fb/F");    // event weight per 1/fb (MC)
    outTree->Branch("scale1fbUp",    &scale1fbUp,   "scale1fbUp/F");    // event weight per 1/fb (MC)
    outTree->Branch("scale1fbDown",    &scale1fbDown,   "scale1fbDown/F");    // event weight per 1/fb (MC)
    outTree->Branch("met",        &met,        "met/F");         // MET
    outTree->Branch("metPhi",     &metPhi,     "metPhi/F");      // phi(MET)
    outTree->Branch("sumEt",      &sumEt,      "sumEt/F");       // Sum ET
    outTree->Branch("u1",         &u1,         "u1/F");          // parallel component of recoil
    outTree->Branch("u2",         &u2,         "u2/F");          // perpendicular component of recoil
    outTree->Branch("tkMet",      &tkMet,      "tkMet/F");       // MET (track MET)
    outTree->Branch("tkMetPhi",   &tkMetPhi,   "tkMetPhi/F");    // phi(MET) (track MET)
    outTree->Branch("tkSumEt",    &tkSumEt,    "tkSumEt/F");     // Sum ET (track MET)
    outTree->Branch("tkU1",       &tkU1,       "tkU1/F");        // parallel component of recoil (track MET)
    outTree->Branch("tkU2",       &tkU2,       "tkU2/F");        // perpendicular component of recoil (track MET)
    outTree->Branch("mvaMet",     &mvaMet,     "mvaMet/F");      // MVA MET
    outTree->Branch("mvaMetPhi",  &mvaMetPhi,  "mvaMetPhi/F");   // phi(MVA MET)
    outTree->Branch("mvaSumEt",   &mvaSumEt,   "mvaSumEt/F");    // Sum ET (mva MET)
    outTree->Branch("mvaU1",      &mvaU1,      "mvaU1/F");       // parallel component of recoil (mva MET)
    outTree->Branch("mvaU2",      &mvaU2,      "mvaU2/F");       // perpendicular component of recoil (mva MET)
    outTree->Branch("puppiMet",    &puppiMet,   "puppiMet/F");      // Puppi MET
    outTree->Branch("puppiMetPhi", &puppiMetPhi,"puppiMetPhi/F");   // phi(Puppi MET)
    outTree->Branch("puppiSumEt",  &puppiSumEt, "puppiSumEt/F");    // Sum ET (Puppi MET)
    outTree->Branch("puppiU1",     &puppiU1,    "puppiU1/F");       // parallel component of recoil (Puppi MET)
    outTree->Branch("puppiU2",     &puppiU2,    "puppiU2/F");       // perpendicular component of recoil (Puppi MET)
    outTree->Branch("q1",         &q1,         "q1/I");          // charge of tag lepton
    outTree->Branch("q2",         &q2,         "q2/I");          // charge of probe lepton
    outTree->Branch("dilep",      "TLorentzVector",  &dilep);    // di-lepton 4-vector
    outTree->Branch("lep1",       "TLorentzVector",  &lep1);     // tag lepton 4-vector
    outTree->Branch("lep2",       "TLorentzVector",  &lep2);     // probe lepton 4-vector
    ///// electron specific /////
    outTree->Branch("trkIso1",    &trkIso1,    "trkIso1/F");     // track isolation of tag lepton
    outTree->Branch("trkIso2",    &trkIso2,    "trkIso2/F");     // track isolation of probe lepton
    outTree->Branch("emIso1",     &emIso1,     "emIso1/F");      // ECAL isolation of tag lepton
    outTree->Branch("emIso2",     &emIso2,     "emIso2/F");      // ECAL isolation of probe lepton
    outTree->Branch("hadIso1",    &hadIso1,    "hadIso1/F");     // HCAL isolation of tag lepton
    outTree->Branch("hadIso2",    &hadIso2,    "hadIso2/F");     // HCAL isolation of probe lepton
    outTree->Branch("pfChIso1",   &pfChIso1,   "pfChIso1/F");    // PF charged hadron isolation of tag lepton
    outTree->Branch("pfChIso2",   &pfChIso2,   "pfChIso2/F");    // PF charged hadron isolation of probe lepton
    outTree->Branch("pfGamIso1",  &pfGamIso1,  "pfGamIso1/F");   // PF photon isolation of tag lepton
    outTree->Branch("pfGamIso2",  &pfGamIso2,  "pfGamIso2/F");   // PF photon isolation of probe lepton
    outTree->Branch("pfNeuIso1",  &pfNeuIso1,  "pfNeuIso1/F");   // PF neutral hadron isolation of tag lepton
    outTree->Branch("pfNeuIso2",  &pfNeuIso2,  "pfNeuIso2/F");   // PF neutral hadron isolation of probe lepton
    outTree->Branch("pfCombIso1", &pfCombIso1, "pfCombIso1/F");  // PF combine isolation of tag lepton
    outTree->Branch("pfCombIso2", &pfCombIso2, "pfCombIso2/F");  // PF combined isolation of probe lepton    
    outTree->Branch("sigieie1",   &sigieie1,   "sigieie1/F");    // sigma-ieta-ieta of tag
    outTree->Branch("sigieie2",   &sigieie2,   "sigieie2/F");    // sigma-ieta-ieta of probe
    outTree->Branch("hovere1",    &hovere1,    "hovere1/F");     // H/E of tag
    outTree->Branch("hovere2",    &hovere2,    "hovere2/F");     // H/E of probe
    outTree->Branch("eoverp1",    &eoverp1,    "eoverp1/F");     // E/p of tag
    outTree->Branch("eoverp2",    &eoverp2,    "eoverp2/F");     // E/p of probe	 
    outTree->Branch("fbrem1",     &fbrem1,     "fbrem1/F");      // brem fraction of tag
    outTree->Branch("fbrem2",     &fbrem2,     "fbrem2/F");      // brem fraction of probe
    outTree->Branch("dphi1",      &dphi1,      "dphi1/F");       // GSF track - ECAL dphi of tag
    outTree->Branch("dphi2",      &dphi2,      "dphi2/F");       // GSF track - ECAL dphi of probe 	
    outTree->Branch("deta1",      &deta1,      "deta1/F");       // GSF track - ECAL deta of tag
    outTree->Branch("deta2",      &deta2,      "deta2/F");       // GSF track - ECAL deta of probe
    outTree->Branch("ecalE1",     &ecalE1,     "ecalE1/F");      // ECAL energy of tag
    outTree->Branch("ecalE2",     &ecalE2,     "ecalE2/F");      // ECAL energy of probe
    outTree->Branch("d01",        &d01,        "d01/F");	 // transverse impact parameter of tag
    outTree->Branch("d02",        &d02,        "d02/F");	 // transverse impact parameter of probe	  
    outTree->Branch("dz1",        &dz1,        "dz1/F");	 // longitudinal impact parameter of tag
    outTree->Branch("dz2",        &dz2,        "dz2/F");	 // longitudinal impact parameter of probe
    outTree->Branch("isConv1",    &isConv1,    "isConv1/i");     // conversion filter flag of tag lepton
    outTree->Branch("isConv2",    &isConv2,    "isConv2/i");     // conversion filter flag of probe lepton
    outTree->Branch("nexphits1",  &nexphits1,  "nexphits1/i");   // number of missing expected inner hits of tag lepton
    outTree->Branch("nexphits2",  &nexphits2,  "nexphits2/i");   // number of missing expected inner hits of probe lepton
    outTree->Branch("typeBits1",  &typeBits1,  "typeBits1/i");   // electron type of tag lepton
    outTree->Branch("typeBits2",  &typeBits2,  "typeBits2/i");   // electron type of probe lepton
    outTree->Branch("sc1",       "TLorentzVector",  &sc1);       // tag supercluster 4-vector
    outTree->Branch("sc2",       "TLorentzVector",  &sc2);       // probe supercluster 4-vector

    //
    // loop through files
    //
    const UInt_t nfiles = samp->fnamev.size();
    for(UInt_t ifile=0; ifile<nfiles; ifile++) {  

      // Read input file and get the TTrees
      cout << "Processing " << samp->fnamev[ifile] << " [xsec = " << samp->xsecv[ifile] << " pb] ... " << endl; cout.flush();
      infile = TFile::Open(samp->fnamev[ifile]); 
      assert(infile);

      Bool_t hasJSON = kFALSE;
      baconhep::RunLumiRangeMap rlrm;
      if(samp->jsonv[ifile].CompareTo("NONE")!=0) { 
	hasJSON = kTRUE;
	rlrm.addJSONFile(samp->jsonv[ifile].Data()); 
      }
  
      eventTree = (TTree*)infile->Get("Events");
      assert(eventTree);  
      eventTree->SetBranchAddress("Info",     &info);        TBranch *infoBr     = eventTree->GetBranch("Info");
      eventTree->SetBranchAddress("Electron", &electronArr); TBranch *electronBr = eventTree->GetBranch("Electron");
      eventTree->SetBranchAddress("Photon",   &scArr);       TBranch *scBr       = eventTree->GetBranch("Photon");
      eventTree->SetBranchAddress("PV",   &vertexArr);       TBranch *vertexBr = eventTree->GetBranch("PV");
      Bool_t hasGen = eventTree->GetBranchStatus("GenEvtInfo");
      TBranch *genBr=0, *genPartBr=0;
      if(hasGen) {
        eventTree->SetBranchAddress("GenEvtInfo", &gen); genBr = eventTree->GetBranch("GenEvtInfo");
	eventTree->SetBranchAddress("GenParticle",&genPartArr); genPartBr = eventTree->GetBranch("GenParticle");
      }

      // Compute MC event weight per 1/fb
      const Double_t xsec = samp->xsecv[ifile];
      Double_t totalWeight=0;
      Double_t totalWeightUp=0;
      Double_t totalWeightDown=0;
      Double_t puWeight=0;
      Double_t puWeightUp=0;
      Double_t puWeightDown=0;

      if (hasGen) {
	for(UInt_t ientry=0; ientry<eventTree->GetEntries(); ientry++) {
	  infoBr->GetEntry(ientry);
	  genBr->GetEntry(ientry);
	  puWeight = h_rw->GetBinContent(h_rw->FindBin(info->nPUmean));
	  puWeightUp = h_rw_up->GetBinContent(h_rw_up->FindBin(info->nPUmean));
	  puWeightDown = h_rw_down->GetBinContent(h_rw_down->FindBin(info->nPUmean));
	  totalWeight+=gen->weight*puWeight;
	  totalWeightUp+=gen->weight*puWeightUp;
	  totalWeightDown+=gen->weight*puWeightDown;
	}
      }
      else if (not isData){
	for(UInt_t ientry=0; ientry<eventTree->GetEntries(); ientry++) {
	  puWeight = h_rw->GetBinContent(h_rw->FindBin(info->nPUmean));
	  puWeightUp = h_rw_up->GetBinContent(h_rw_up->FindBin(info->nPUmean));
	  puWeightDown = h_rw_down->GetBinContent(h_rw_down->FindBin(info->nPUmean));
	  totalWeight+= 1.0*puWeight;
	  totalWeightUp+= 1.0*puWeightUp;
	  totalWeightDown+= 1.0*puWeightDown;
	}

      }
      
      //
      // loop over events
      //
      Double_t nsel=0, nselvar=0;
      for(UInt_t ientry=0; ientry<eventTree->GetEntries(); ientry++) {
        infoBr->GetEntry(ientry);

        if(ientry%1000000==0) cout << "Processing event " << ientry << ". " << (double)ientry/(double)eventTree->GetEntries()*100 << " percent done with this file." << endl;

        Double_t weight=1;
	Double_t weightUp=1;
	Double_t weightDown=1;
        if(xsec>0 && totalWeight>0) weight = xsec/totalWeight;
	if(xsec>0 && totalWeightUp>0) weightUp = xsec/totalWeightUp;
	if(xsec>0 && totalWeightDown>0) weightDown = xsec/totalWeightDown;
	if(hasGen) {
	  genPartArr->Clear();
	  genBr->GetEntry(ientry);
          genPartBr->GetEntry(ientry);
	  puWeight = h_rw->GetBinContent(h_rw->FindBin(info->nPUmean));
	  puWeightUp = h_rw_up->GetBinContent(h_rw_up->FindBin(info->nPUmean));
	  puWeightDown = h_rw_down->GetBinContent(h_rw_down->FindBin(info->nPUmean));
	  weight*=gen->weight*puWeight;
	  weightUp*=gen->weight*puWeightUp;
	  weightDown*=gen->weight*puWeightDown;
	}
	
	// veto z -> xx decays for signal and z -> ee for bacground samples (needed for inclusive DYToLL sample)
	if (isWrongFlavor && hasGen && fabs(toolbox::flavor(genPartArr, BOSON_ID))==LEPTON_ID) continue;
	else if (isSignal && hasGen && fabs(toolbox::flavor(genPartArr, BOSON_ID))!=LEPTON_ID) continue;

        // check for certified lumi (if applicable)
        baconhep::RunLumiRangeMap::RunLumiPairType rl(info->runNum, info->lumiSec);      
        if(hasJSON && !rlrm.hasRunLumi(rl)) continue;  

        // trigger requirement
	if (!isEleTrigger(triggerMenu, info->triggerBits, isData)) continue;

        // good vertex requirement
        if(!(info->hasGoodPV)) continue;

	electronArr->Clear();
        electronBr->GetEntry(ientry);
	scArr->Clear();
	scBr->GetEntry(ientry);

	TLorentzVector vTag(0,0,0,0);
	TLorentzVector vTagSC(0,0,0,0);
	Double_t tagPt=0;
	Double_t Pt1=0;
	Double_t Pt2=0;
	Int_t itag=-1;
	Int_t tagscID=-1;
		
	for(Int_t i1=0; i1<electronArr->GetEntriesFast(); i1++) {
          const baconhep::TElectron *tag = (baconhep::TElectron*)((*electronArr)[i1]);
	  
	  // check ECAL gap
	  if(fabs(tag->scEta)>=ECAL_GAP_LOW && fabs(tag->scEta)<=ECAL_GAP_HIGH) continue;
	  
          // apply scale and resolution corrections to MC
          Double_t tagscEt_corr = tag->scEt;
          if(doScaleCorr && snamev[isam].CompareTo("data",TString::kIgnoreCase)!=0)
            tagscEt_corr = gRandom->Gaus(tag->scEt*getEleScaleCorr(tag->scEta,0),getEleResCorr(tag->scEta,0));
	  
	  if(tagscEt_corr        < PT_CUT)     continue;  // lepton pT cut
	  if(fabs(tag->scEta)    > ETA_CUT)    continue;  // lepton |eta| cut
	  if(!passEleID(tag,info->rhoIso))     continue;  // lepton selection
	
	  double El_Pt=0;
	  if(doScaleCorr) {
	    El_Pt=gRandom->Gaus(tag->pt*getEleScaleCorr(tag->scEta,0),getEleResCorr(tag->scEta,0));
	  }
	  else
	    {
	      El_Pt=tag->pt;
	    }

	  if(El_Pt>Pt1)
	    {
	      Pt2=Pt1;
	      Pt1=El_Pt;
	    }
	  else if(El_Pt>Pt2&&El_Pt<Pt1)
	    {
	      Pt2=El_Pt;
	    }

	  if(!isEleTriggerObj(triggerMenu, tag->hltMatchBits, kFALSE, isData)) continue;
	  
	  if(El_Pt<tagPt) continue;
	  
	  tagPt=El_Pt;
	  itag=i1;
	  tagscID=tag->scID;

	  // apply scale and resolution corrections to MC
          if(doScaleCorr && snamev[isam].CompareTo("data",TString::kIgnoreCase)!=0) {
            vTag.SetPtEtaPhiM(El_Pt, tag->eta, tag->phi, ELE_MASS);
            vTagSC.SetPtEtaPhiM(tagscEt_corr, tag->scEta, tag->scPhi, ELE_MASS);
          } else {
  	    vTag.SetPtEtaPhiM(tag->pt, tag->eta, tag->phi, ELE_MASS);
	    vTagSC.SetPtEtaPhiM(tag->scEt, tag->scEta, tag->scPhi, ELE_MASS);
          }

	  trkIso1    = tag->trkIso;
	  emIso1     = tag->ecalIso;
	  hadIso1    = tag->hcalIso;
	  pfChIso1   = tag->chHadIso;
	  pfGamIso1  = tag->gammaIso;	    
	  pfNeuIso1  = tag->neuHadIso;
	  pfCombIso1 = tag->chHadIso + TMath::Max(tag->neuHadIso + tag->gammaIso - (info->rhoIso)*getEffAreaEl(tag->scEta), 0.);
	  sigieie1   = tag->sieie;
	  hovere1    = tag->hovere;
	  eoverp1    = tag->eoverp;
	  fbrem1     = tag->fbrem;
	  dphi1      = tag->dPhiIn;
	  deta1      = tag->dEtaIn;
	  ecalE1     = tag->ecalEnergy;
	  d01        = tag->d0;
	  dz1        = tag->dz;
	  isConv1    = tag->isConv;
	  nexphits1  = tag->nMissingHits;
	  typeBits1  = tag->typeBits;
	  q1         = tag->q;

	}

	if(tagPt<Pt2) continue;

	TLorentzVector vProbe(0,0,0,0); TLorentzVector vProbeSC(0,0,0,0);
	Double_t probePt=0;
	Int_t iprobe=-1;
	Int_t passID=false;
	UInt_t icat=0;
	
	const baconhep::TElectron *eleProbe=0;

	for(Int_t j=0; j<scArr->GetEntriesFast(); j++) {
	  const baconhep::TPhoton *scProbe = (baconhep::TPhoton*)((*scArr)[j]);
	  
	  if(scProbe->scID == tagscID) continue;

	  // check ECAL gap
	  if(fabs(scProbe->eta)>=ECAL_GAP_LOW && fabs(scProbe->eta)<=ECAL_GAP_HIGH) continue;
	  
	  // apply scale and resolution corrections to MC
	  Double_t scProbept_corr = scProbe->pt;
	  if(doScaleCorr && snamev[isam].CompareTo("data",TString::kIgnoreCase)!=0)
	    scProbept_corr = gRandom->Gaus(scProbe->pt*getEleScaleCorr(scProbe->eta,0),getEleResCorr(scProbe->eta,0));
	  
	  if(scProbept_corr        < PT_CUT)  continue;  // Supercluster ET cut ("pt" = corrected by PV position)
	  if(fabs(scProbe->eta)  > ETA_CUT) continue;  // Supercluster |eta| cuts

	  for(Int_t i2=0; i2<electronArr->GetEntriesFast(); i2++) {
	    if(itag==i2) continue;
	    const baconhep::TElectron *ele = (baconhep::TElectron*)((*electronArr)[i2]);
	    if(!(ele->typeBits & baconhep::EEleType::kEcalDriven)) continue;
	    if(scProbe->scID==ele->scID) { 
	      eleProbe = ele; 
	      iprobe   = i2;
	      break; 
	    }
	  }

	  double El_Pt=0;
	  if(doScaleCorr&&eleProbe) {
	    El_Pt=gRandom->Gaus(eleProbe->pt*getEleScaleCorr(scProbe->eta,0),getEleResCorr(scProbe->eta,0));
	  }
	  else if(!doScaleCorr&&eleProbe)
	    {
	      El_Pt=eleProbe->pt;
	    }
	  else
	    {
	      El_Pt=scProbept_corr;
	    }

	  if(passID&&eleProbe&&passEleID(eleProbe,info->rhoIso)&&El_Pt<probePt) continue;
	  if(passID&&eleProbe&&!passEleID(eleProbe,info->rhoIso)) continue;
	  if(passID&&!eleProbe) continue;
	  if(!passID&&eleProbe&&!passEleID(eleProbe,info->rhoIso)&&El_Pt<probePt) continue;
	  if(!passID&&!eleProbe&&El_Pt<probePt) continue;
	  if(!passID&&eleProbe&&passEleID(eleProbe,info->rhoIso)) passID=true;

	  probePt=El_Pt;

	  // apply scale and resolution corrections to MC
	  if(doScaleCorr && snamev[isam].CompareTo("data",TString::kIgnoreCase)!=0) {
	    vProbe.SetPtEtaPhiM((eleProbe) ? gRandom->Gaus(eleProbe->pt*getEleScaleCorr(scProbe->eta,0),getEleResCorr(scProbe->eta,0)) : scProbept_corr,
				(eleProbe) ? eleProbe->eta : scProbe->eta,
				(eleProbe) ? eleProbe->phi : scProbe->phi,
				ELE_MASS);
	    vProbeSC.SetPtEtaPhiM((eleProbe) ? gRandom->Gaus(eleProbe->scEt*getEleScaleCorr(scProbe->eta,0),getEleResCorr(scProbe->eta,0)) : gRandom->Gaus(scProbe->pt*getEleScaleCorr(scProbe->eta,0),getEleResCorr(scProbe->eta,0)),
				  scProbe->eta, scProbe->phi, ELE_MASS);
	  } else {
	    vProbe.SetPtEtaPhiM((eleProbe) ? eleProbe->pt : scProbe->pt,
				(eleProbe) ? eleProbe->eta : scProbe->eta,
				(eleProbe) ? eleProbe->phi : scProbe->phi,
				ELE_MASS);
	    vProbeSC.SetPtEtaPhiM((eleProbe) ? eleProbe->scEt : scProbe->pt,
				  scProbe->eta, scProbe->phi, ELE_MASS);
	  }

	  trkIso2    = (eleProbe) ? eleProbe->trkIso        : -1;
	  emIso2     = (eleProbe) ? eleProbe->ecalIso       : -1;
	  hadIso2    = (eleProbe) ? eleProbe->hcalIso       : -1;
	  pfChIso2   = (eleProbe) ? eleProbe->chHadIso      : -1;
	  pfGamIso2  = (eleProbe) ? eleProbe->gammaIso      : -1;
	  pfNeuIso2  = (eleProbe) ? eleProbe->neuHadIso     : -1;	    
	  pfCombIso2 = (eleProbe) ? 
	    eleProbe->chHadIso + TMath::Max(eleProbe->neuHadIso + eleProbe->gammaIso - 
					    (info->rhoIso)*getEffAreaEl(eleProbe->scEta), 0.) :  -1;
	  sigieie2   = (eleProbe) ? eleProbe->sieie         : scProbe->sieie;
	  hovere2    = (eleProbe) ? eleProbe->hovere        : scProbe->hovere;
	  eoverp2    = (eleProbe) ? eleProbe->eoverp        : -1;
	  fbrem2     = (eleProbe) ? eleProbe->fbrem         : -1;
	  dphi2      = (eleProbe) ? eleProbe->dPhiIn        : -999;
	  deta2      = (eleProbe) ? eleProbe->dEtaIn        : -999;
	  ecalE2     = (eleProbe) ? eleProbe->ecalEnergy    : -999;
	  d02        = (eleProbe) ? eleProbe->d0            : -999;
	  dz2        = (eleProbe) ? eleProbe->dz            : -999;
	  isConv2    = (eleProbe) ? eleProbe->isConv        : 0;
	  nexphits2  = (eleProbe) ? eleProbe->nMissingHits  : 0;
	  typeBits2  = (eleProbe) ? eleProbe->typeBits      : 0;
	  q2         = (eleProbe) ? eleProbe->q : -q1;

	  // determine event category
	  if(eleProbe) {
	    if(passEleID(eleProbe,info->rhoIso)) {
	      
	      if(isEleTriggerObj(triggerMenu, eleProbe->hltMatchBits, kFALSE, isData)) {
		icat=eEleEle2HLT;  
	      } 
	      else if(isEleTriggerObj(triggerMenu, eleProbe->hltMatchBits, kTRUE, isData)) {
		icat=eEleEle1HLT1L1; 
	      }
	      else { icat=eEleEle1HLT; }
	    }
	    else { icat=eEleEleNoSel; } 
	  } 
	  else { icat=eEleSC; }
	  
	}

	if(q1 == q2)         continue;  // opposite charge requirement

	// mass window
	TLorentzVector vDilep = vTag + vProbe;
	if((vDilep.M()<MASS_LOW) || (vDilep.M()>MASS_HIGH)) continue;

	if(icat==0) continue;

	//******** We have a Z candidate! HURRAY! ********
	nsel+=weight;
	nselvar+=weight*weight;

	// Perform matching of dileptons to GEN leptons from Z decay

	Int_t glepq1=-99;
	Int_t glepq2=-99;
	TLorentzVector *gvec=new TLorentzVector(0,0,0,0);
	TLorentzVector *glep1=new TLorentzVector(0,0,0,0);
	TLorentzVector *glep2=new TLorentzVector(0,0,0,0);
	TLorentzVector *gph=new TLorentzVector(0,0,0,0);
	Bool_t hasGenMatch = kFALSE;
	if(isSignal && hasGen) {
	  toolbox::fillGen(genPartArr, BOSON_ID, gvec, glep1, glep2,&glepq1,&glepq2,1);
	  
	  Bool_t match1 = ( ((glep1) && toolbox::deltaR(vTag.Eta(), vTag.Phi(), glep1->Eta(), glep1->Phi())<0.3) || 
			    ((glep2) && toolbox::deltaR(vTag.Eta(), vTag.Phi(), glep2->Eta(), glep2->Phi())<0.3) );
	  
	  Bool_t match2 = ( ((glep1) && toolbox::deltaR(vProbe.Eta(), vProbe.Phi(), glep1->Eta(), glep1->Phi())<0.3) || 
			    ((glep2) && toolbox::deltaR(vProbe.Eta(), vProbe.Phi(), glep2->Eta(), glep2->Phi())<0.3) );
	  
	  if(match1 && match2) {
	    hasGenMatch = kTRUE;
	    if (gvec!=0) {
	      genV=new TLorentzVector(0,0,0,0);
	      genV->SetPtEtaPhiM(gvec->Pt(), gvec->Eta(), gvec->Phi(), gvec->M());
	      genVPt   = gvec->Pt();
	      genVPhi  = gvec->Phi();
	      genVy    = gvec->Rapidity();
	      genVMass = gvec->M();
	    }
	    else {
	      TLorentzVector tvec=*glep1+*glep2;
	      genV=new TLorentzVector(0,0,0,0);
	      genV->SetPtEtaPhiM(tvec.Pt(), tvec.Eta(), tvec.Phi(), tvec.M());
	      genVPt   = tvec.Pt();
	      genVPhi  = tvec.Phi();
	      genVy    = tvec.Rapidity();
	      genVMass = tvec.M();
	    }
	    delete gvec;
	    delete glep1;
	    delete glep2;
	    glep1=0; glep2=0; gvec=0;
	  }
	  else {
	    genV     = new TLorentzVector(0,0,0,0);
	    genVPt   = -999;
	    genVPhi  = -999;
	    genVy    = -999;
	    genVMass = -999;
	  }
	}
	
	if (hasGen) {
	  id_1      = gen->id_1;
	  id_2      = gen->id_2;
	  x_1       = gen->x_1;
	  x_2       = gen->x_2;
	  xPDF_1    = gen->xPDF_1;
	  xPDF_2    = gen->xPDF_2;
	  scalePDF  = gen->scalePDF;
	  weightPDF = gen->weight;
	}
	else {
	  id_1      = -999;
	  id_2      = -999;
	  x_1       = -999;
	  x_2       = -999;
	  xPDF_1    = -999;
	  xPDF_2    = -999;
	  scalePDF  = -999;
	  weightPDF = -999;
	  }

	//
	// Fill tree
	//
	runNum   = info->runNum;
	lumiSec  = info->lumiSec;
	evtNum   = info->evtNum;

	if (hasGenMatch) matchGen=1;
	else matchGen=0;

	category = icat;

	vertexArr->Clear();
	vertexBr->GetEntry(ientry);

	npv      = vertexArr->GetEntries();
	npu      = info->nPUmean;
        genWeight= hasGen ? gen->weight: 1.;
        PUWeight = puWeight;
	scale1fb = weight;
	scale1fbUp = weightUp;
	scale1fbDown = weightDown;
	met      = info->pfMETC;
	metPhi   = info->pfMETCphi;
	sumEt    = 0;
	tkMet    = info->trkMET;
	tkMetPhi = info->trkMETphi;
	tkSumEt  = 0;
	mvaMet   = info->mvaMET;
	mvaMetPhi = info->mvaMETphi; 
	mvaSumEt = 0;
	TVector2 vZPt((vDilep.Pt())*cos(vDilep.Phi()),(vDilep.Pt())*sin(vDilep.Phi()));

	puppiMet = info->puppET;
        puppiMetPhi = info->puppETphi;
	puppiSumEt = 0;
	lep1     = &vTag;
	lep2     = &vProbe;
	dilep    = &vDilep;
	sc1        = &vTagSC;
	sc2        = &vProbeSC;

	TVector2 vMet((info->pfMETC)*cos(info->pfMETCphi), (info->pfMETC)*sin(info->pfMETCphi));
	TVector2 vU = -1.0*(vMet+vZPt);
	u1 = ((vDilep.Px())*(vU.Px()) + (vDilep.Py())*(vU.Py()))/(vDilep.Pt());  // u1 = (pT . u)/|pT|
	u2 = ((vDilep.Px())*(vU.Py()) - (vDilep.Py())*(vU.Px()))/(vDilep.Pt());  // u2 = (pT x u)/|pT|
	
	TVector2 vTkMet((info->trkMET)*cos(info->trkMETphi), (info->trkMET)*sin(info->trkMETphi));        
	TVector2 vTkU = -1.0*(vTkMet+vZPt);
	tkU1 = ((vDilep.Px())*(vTkU.Px()) + (vDilep.Py())*(vTkU.Py()))/(vDilep.Pt());  // u1 = (pT . u)/|pT|
	tkU2 = ((vDilep.Px())*(vTkU.Py()) - (vDilep.Py())*(vTkU.Px()))/(vDilep.Pt());  // u2 = (pT x u)/|pT|
	
	TVector2 vMvaMet((info->mvaMET)*cos(info->mvaMETphi), (info->mvaMET)*sin(info->mvaMETphi));
	TVector2 vMvaU = -1.0*(vMvaMet+vZPt);
	mvaU1 = ((vDilep.Px())*(vMvaU.Px()) + (vDilep.Py())*(vMvaU.Py()))/(vDilep.Pt());  // u1 = (pT . u)/|pT|
	mvaU2 = ((vDilep.Px())*(vMvaU.Py()) - (vDilep.Py())*(vMvaU.Px()))/(vDilep.Pt());  // u2 = (pT x u)/|pT|
        
	TVector2 vPuppiMet((info->puppET)*cos(info->puppETphi), (info->puppET)*sin(info->puppETphi));
	TVector2 vPuppiU = -1.0*(vPuppiMet+vZPt);
	puppiU1 = ((vDilep.Px())*(vPuppiU.Px()) + (vDilep.Py())*(vPuppiU.Py()))/(vDilep.Pt());  // u1 = (pT . u)/|pT|
	puppiU2 = ((vDilep.Px())*(vPuppiU.Py()) - (vDilep.Py())*(vPuppiU.Px()))/(vDilep.Pt());  // u2 = (pT x u)/|pT|

	outTree->Fill();
	delete genV;
	genV=0, dilep=0, lep1=0, lep2=0, sc1=0, sc2=0;
      }
      delete infile;
      infile=0, eventTree=0;    
      
      cout << nsel  << " +/- " << sqrt(nselvar);
      if(!isData) cout << " per 1/fb";
      cout << endl;
    }
    outFile->Write();
    outFile->Close(); 
  }
  delete h_rw;
  delete f_rw;
  delete info;
  delete gen;
  delete genPartArr;
  delete electronArr;
  delete scArr;
  delete vertexArr;
    
  //--------------------------------------------------------------------------------------------------------------
  // Output
  //==============================================================================================================
   
  cout << "*" << endl;
  cout << "* SUMMARY" << endl;
  cout << "*--------------------------------------------------" << endl;
  cout << " Z -> e e" << endl;
  cout << "  Mass window: [" << MASS_LOW << ", " << MASS_HIGH << "]" << endl;
  cout << "  pT > " << PT_CUT << endl;
  cout << "  |eta| < " << ETA_CUT << endl;
  cout << endl;
  
  cout << endl;
  cout << "  <> Output saved in " << outputDir << "/" << endl;    
  cout << endl;  
      
  gBenchmark->Show("selectZee"); 
}
Example #10
0
inline TVector3 Pi_versor_reco_from_2hits(double deltaz, TVector2 hit1, TVector2 hit2)
{
    double px = (hit2.X() - hit1.X())/deltaz;
    double py = (hit2.Y() - hit1.Y())/deltaz;
    return TVector3(px, py, 1);
}
Example #11
0
// D0 RedMET with CMG trees
double getD0RedMet(double lpx1, double lpy1, double lpterr1, 
		   double lpx2, double lpy2, double lpterr2, 
		   double sumjpx, double sumjpy, 
		   double pfmet, double pfmetphi, 
		   int flav, int pickAFlav = 1) {
			   


  if( flav==3 ) { 
    if( pickAFlav!=1 && pickAFlav!=2 ) {
      cout << " *** ERROR *** " << endl;
      cout << "  You need to pick a flavor in getD0RedMet(...)! " << endl;
      throw std::exception();
      return -1.;
    }
    else {
      flav = pickAFlav;
    }
  }

  // double wPerpMu = 1.0;
  // double wRecMu  = 2.0;
  // double wUncMu  = 2.5;
  double wPerpMu = 1.0;
  double wRecMu  = 1.5;
  double wUncMu  = 2.75;

  // double wPerpEl = 1.5;
  // double wRecEl  = 2.25;
  // double wUncEl  = 0.0;
  double wPerpEl = 0.75;
  double wRecEl  = 1.0;
  double wUncEl  = 0.25;
  
  int seplep = 1;
  
  if (seplep == 0){
		wPerpMu = 1.0;
		wRecMu  = 1.25;
		wUncMu  = 0.0;
		wPerpEl = wPerpMu;
		wRecEl  = wRecMu;
		wUncEl  = wUncMu;
  }

  double kPerp = 1.;
  double kRecoil_l = 1.;
  double kRecoil_t = 1.;
  double kSigmaPt_l = 1.;
  double kSigmaPt_t = 1.;

  if( flav==1 ) {        // mm
    kPerp = wPerpMu;
    kRecoil_l = kRecoil_t = wRecMu;
    kSigmaPt_l = kSigmaPt_t = wUncMu;
  }
  else if( flav==2 ) {  // ee
    kPerp = wPerpEl;
    kRecoil_l = kRecoil_t = wRecEl;
    kSigmaPt_l = kSigmaPt_t = wUncEl;
  }
  else {}

  double pt1 = sqrt(lpx1*lpx1 + lpy1*lpy1);
  double pt2 = sqrt(lpx2*lpx2 + lpy2*lpy2);

  TVector2 lead, subl;
  double leadpt, sublpt, leadpterr, sublpterr;
  if(pt1>pt2) {
    lead = TVector2(lpx1, lpy1);
    subl = TVector2(lpx2, lpy2);
    leadpt = pt1;
    leadpterr = lpterr1;
    sublpt = pt2;
    sublpterr = lpterr2;
  }
  else {
    lead = TVector2(lpx2, lpy2);
    subl = TVector2(lpx1, lpy1);
    leadpt = pt2;
    leadpterr = lpterr2;
    sublpt = pt1;
    sublpterr = lpterr1;
  }

  // Define the thrust and dilepton
  TVector2 dil = lead+subl;
  TVector2 thr = lead-subl;
  TVector2 longi;
  TVector2 perpe;
  double deltaPhi = fabs(lead.DeltaPhi(subl));

  if( deltaPhi>(3.141592654/2.) ) {
    longi = thr.Unit();
    perpe = longi.Rotate(3.141592654/2.);
    if(perpe*lead<0) perpe *= -1;
  }
  else {
    perpe = dil.Unit();
    longi = perpe.Rotate(3.141592654/2.);
    if(longi*lead<0) longi *= -1;
  }

  // Dilepton
  double dileptProj_l = dil*longi;
  double dileptProj_t = dil*perpe;

  // Unclustered
  TVector2 uncl( pfmet*cos(pfmetphi), pfmet*sin(pfmetphi) );
  uncl += dil;
  double unclProj_l = uncl*longi;
  double unclProj_t = uncl*perpe;

  // Sum of jets
  TVector2 sumjVec(sumjpx, sumjpy);
  double sumjetProj_l = sumjVec*longi;
  double sumjetProj_t = sumjVec*perpe;

  // Recoil
  double recoilProj_l = min( sumjetProj_l, -1.0*unclProj_l ); recoilProj_l = min( 0., recoilProj_l );
  double recoilProj_t = min( sumjetProj_t, -1.0*unclProj_t ); recoilProj_t = min( 0., recoilProj_t );
  // Case with 0 jets
  // double recoilProj_l = -1.0*unclProj_l; recoilProj_l = min( 0., recoilProj_l );
  // double recoilProj_t = -1.0*unclProj_t; recoilProj_t = min( 0., recoilProj_t );

  // Lepton uncertainty
  double relErrLead = min( leadpterr/leadpt, 1. );
  double relErrSubl = min( sublpterr/sublpt, 1. );
  TVector2 lowLead = lead*(1.0-relErrLead);
  TVector2 lowSubl = subl*(1.0-relErrSubl);
  TVector2 lowDil = lowLead + lowSubl;
  TVector2 lowThr = lowLead - lowSubl;

  double deltaDileptProj_t = lowDil*perpe - dileptProj_t;
  double deltaDileptProj_l = ( -relErrLead*lead + relErrSubl*subl )*longi;

  double redMET_l = max( (dileptProj_l + kRecoil_l*recoilProj_l + kSigmaPt_l*deltaDileptProj_l), 0.);
  double redMET_t = max( (dileptProj_t + kRecoil_t*recoilProj_t + kSigmaPt_t*deltaDileptProj_t), 0.);
  double redMET = sqrt( pow(redMET_l,2) + kPerp*pow(redMET_t,2) );

  return redMET;
}
void StdTopVarProcessor::Process(const InputCollections& input,VariableContainer& vars){
  if(!initialized) cerr << "tree processor not initialized" << endl;

  std::vector<pat::Jet> selectedTaggedJets;
  std::vector<pat::Jet> selectedUntaggedJets;
  for(std::vector<pat::Jet>::const_iterator itJet = input.selectedJets.begin(); itJet != input.selectedJets.end(); ++itJet){
    if(BoostedUtils::PassesCSV(*itJet, 'M')) selectedTaggedJets.push_back(*itJet);
    else selectedUntaggedJets.push_back(*itJet);
  }

  math::XYZTLorentzVector HadW;
  math::XYZTLorentzVector HadW1;
  math::XYZTLorentzVector HadW2;

  for(std::vector<pat::Jet>::const_iterator it1Jet = selectedUntaggedJets.begin(); it1Jet != selectedUntaggedJets.end(); ++it1Jet){
    for(std::vector<pat::Jet>::const_iterator it2Jet = selectedUntaggedJets.begin(); it2Jet != selectedUntaggedJets.end(); ++it2Jet){
      if(abs(80.4-(it1Jet->p4()+it2Jet->p4()).M())<abs(80.4-(HadW1+HadW2).M())){
        HadW1 = it1Jet->p4();
        HadW2 = it2Jet->p4();
        HadW = HadW1+HadW2;
      }
    }
  }

  vars.FillVar( "HadTop_W_Pt",HadW.Pt() );
  vars.FillVar( "HadTop_W_E",HadW.E() );
  vars.FillVar( "HadTop_W_Eta",HadW.Eta() );
  vars.FillVar( "HadTop_W_Phi",HadW.Phi() );
  vars.FillVar( "HadTop_W_M",HadW.M() );

  vars.FillVar( "HadTop_W1_Pt",HadW1.Pt() );
  vars.FillVar( "HadTop_W1_E",HadW1.E() );
  vars.FillVar( "HadTop_W1_Eta",HadW1.Eta() );
  vars.FillVar( "HadTop_W1_Phi",HadW1.Phi() );
  vars.FillVar( "HadTop_W1_M",HadW1.M() );

  vars.FillVar( "HadTop_W2_Pt",HadW2.Pt() );
  vars.FillVar( "HadTop_W2_E",HadW2.E() );
  vars.FillVar( "HadTop_W2_Eta",HadW2.Eta() );
  vars.FillVar( "HadTop_W2_Phi",HadW2.Phi() );
  vars.FillVar( "HadTop_W2_M",HadW2.M() );

  math::XYZTLorentzVector HadB;
  math::XYZTLorentzVector HadTop;

  for(std::vector<pat::Jet>::const_iterator itJet = selectedTaggedJets.begin(); itJet != selectedTaggedJets.end(); ++itJet){
    if(HadTop.M()==0 || abs(172.4-(HadW+itJet->p4()).M())<abs(172.4-HadTop.M())){
      HadB = itJet->p4();
      HadTop = HadB+HadW;
    }
    else{
      cout << "HadTop_W_Pt: " << HadW.Pt() << ", HadTop_B_Pt: " << itJet->pt() << ", Top mass: " << (HadW+itJet->p4()).M() << endl;
    }
  }

  vars.FillVar( "HadTop_B_Pt",HadB.Pt() );
  vars.FillVar( "HadTop_B_E",HadB.E() );
  vars.FillVar( "HadTop_B_Eta",HadB.Eta() );
  vars.FillVar( "HadTop_B_Phi",HadB.Phi() );
  vars.FillVar( "HadTop_B_M",HadB.M() );
//   vars.FillVar( "HadTop_B_CSV",MiniAODHelper::GetJetCSV(HadB,btagger) );
//   vars.FillVar( "HadTop_B_Flav",HadB.flavour() );

  vars.FillVar( "HadTop_Pt",HadTop.Pt() );
  vars.FillVar( "HadTop_E",HadTop.E() );
  vars.FillVar( "HadTop_Eta",HadTop.Eta() );
  vars.FillVar( "HadTop_Phi",HadTop.Phi() );
  vars.FillVar( "HadTop_M",HadTop.M() );

  math::XYZTLorentzVector nu1;
  math::XYZTLorentzVector nu2;
  TVector2 MET;
  MET.Set(input.pfMET.px(),input.pfMET.py());
  math::XYZTLorentzVector PrimLep = BoostedUtils::GetPrimLepVec(input.selectedElectrons, input.selectedMuons);
  BoostedUtils::GetNuVecs(PrimLep, MET, nu1, nu2);

  math::XYZTLorentzVector LepW;

  if(abs(80.4-(nu1+PrimLep).M())<abs(80.4-(nu2+PrimLep).M())) LepW = nu1+PrimLep;
  else LepW = nu2+PrimLep;

  vars.FillVar( "LepTop_W_Pt",LepW.Pt() );
  vars.FillVar( "LepTop_W_E",LepW.E() );
  vars.FillVar( "LepTop_W_Eta",LepW.Eta() );
  vars.FillVar( "LepTop_W_Phi",LepW.Phi() );
  vars.FillVar( "LepTop_W_M",LepW.M() );

  math::XYZTLorentzVector LepB;
  math::XYZTLorentzVector LepTop;

  for(std::vector<pat::Jet>::const_iterator itJet = selectedTaggedJets.begin(); itJet != selectedTaggedJets.end(); ++itJet){
    if(LepTop.M()==0 || abs(172.4-(LepW+itJet->p4()).M())<abs(172.4-LepTop.M())){
      LepB = itJet->p4();
      LepTop = LepW+LepB;
    }
  }

  vars.FillVar( "LepTop_B_Pt",LepB.Pt() );
  vars.FillVar( "LepTop_B_E",LepB.E() );
  vars.FillVar( "LepTop_B_Eta",LepB.Eta() );
  vars.FillVar( "LepTop_B_Phi",LepB.Phi() );
  vars.FillVar( "LepTop_B_M",LepB.M() );
//   vars.FillVar( "LepTop_B_CSV",MiniAODHelper::GetJetCSV(LepB,btagger) );
//   vars.FillVar( "LepTop_B_Flav",LepB.flavour() );

  vars.FillVar( "LepTop_Pt",LepTop.Pt() );
  vars.FillVar( "LepTop_E",LepTop.E() );
  vars.FillVar( "LepTop_Eta",LepTop.Eta() );
  vars.FillVar( "LepTop_Phi",LepTop.Phi() );
  vars.FillVar( "LepTop_M",LepTop.M() );

}
Example #13
0
void ttreco2( TString process ) {

	cout << "\n\n" << process << "\n" <<  endl; 

	TFile* fshape  = new TFile( "/afs/cern.ch/user/j/jgarciaf/mimick/mlb.root" ); 

	TH1F* shapemlb = (TH1F*) fshape->Get( "mlb" );

	MassReconstructor theMass( 100, shapemlb );  


	//TFile myfile( "../minitrees/" + inputdir + "/TTDM/" + process + ".root", "update" ); 
	TFile myfile( "../../../../public/minitrees_week-1_with-ttReco/" + process + ".root", "update" ); 
	//TFile myfile( "../minitrees/week-1-checks/" + process + ".root", "update" ); 

   	TTreeReader myreader( "latino", &myfile );

	TTree* mytree = (TTree*) myfile.Get( "latino" );


	//----- read -------------------------------------------------------

   	TTreeReaderValue<float> metPfType1   ( myreader, "metPfType1"    );
   	TTreeReaderValue<float> metPfType1Phi( myreader, "metPfType1Phi" );

   	TTreeReaderValue<float> lep1pt  ( myreader, "lep1pt"   );
   	TTreeReaderValue<float> lep1eta ( myreader, "lep1eta"  );
   	TTreeReaderValue<float> lep1phi ( myreader, "lep1phi"  );
   	TTreeReaderValue<float> lep1mass( myreader, "lep1mass" );

	TTreeReaderValue<float> lep2pt  ( myreader, "lep2pt"   );
   	TTreeReaderValue<float> lep2eta ( myreader, "lep2eta"  );
   	TTreeReaderValue<float> lep2phi ( myreader, "lep2phi"  );
   	TTreeReaderValue<float> lep2mass( myreader, "lep2mass" );

   	TTreeReaderValue<std::vector<float>> jet_pt ( myreader, "jet_pt"  );
   	TTreeReaderValue<std::vector<float>> jet_eta( myreader, "jet_eta" );
   	TTreeReaderValue<std::vector<float>> jet_phi( myreader, "jet_phi" );

   	TTreeReaderValue<std::vector<float>> bjet30csvv2m_pt ( myreader, "bjet30csvv2m_pt"  );
   	TTreeReaderValue<std::vector<float>> bjet30csvv2m_eta( myreader, "bjet30csvv2m_eta" );
   	TTreeReaderValue<std::vector<float>> bjet30csvv2m_phi( myreader, "bjet30csvv2m_phi" );

	//TTreeReaderValue<float> top1pt  ( myreader, "top1pt_gen"   );
   	//TTreeReaderValue<float> top1eta ( myreader, "top1eta_gen"  );
   	//TTreeReaderValue<float> top1phi ( myreader, "top1phi_gen"  );

	//TTreeReaderValue<float> top2pt  ( myreader, "top2pt_gen"   );
   	//TTreeReaderValue<float> top2eta ( myreader, "top2eta_gen"  );
   	//TTreeReaderValue<float> top2phi ( myreader, "top2phi_gen"  );


	//----- write ------------------------------------------------------

	float topRecoW;
	float darkpt  ; 

	TBranch* b_topRecoW = mytree -> Branch( "topRecoW", &topRecoW, "topRecoW/F" );
	TBranch* b_darkpt   = mytree -> Branch( "newdarkpt"  , &darkpt  , "darkpt/F"   );

	TBranch* b_mimick = mytree -> Branch( "mimick"  , &mimick  , "mimick/F"   );

	

	//----- loop -------------------------------------------------------


	int nentries = myreader.GetEntries(1); 

	//if ( nentries > 10 ) nentries = 10; 

	for ( Long64_t ievt = 0; ievt < nentries; ievt++ ) {

		if( ievt%10000 == 0 ) cout << "\n\n ievt: " << ievt << endl;

		myreader.SetEntry(ievt);

		//--- MET

		TVector2 MET;

		MET.SetMagPhi( *metPfType1, *metPfType1Phi );

		myreader.SetEntry(ievt);

		//--- leptons

		TLorentzVector l1, l2;   // top1gen, top2gen; 

		l1.SetPtEtaPhiM( *lep1pt, *lep1eta, *lep1phi, *lep1mass ); 
  		l2.SetPtEtaPhiM( *lep2pt, *lep2eta, *lep2phi, *lep2mass );

		//top1gen.SetPtEtaPhiM( *top1pt, *top1eta, *top1phi, 173.34 );
		//top2gen.SetPtEtaPhiM( *top2pt, *top2eta, *top2phi, 173.34 );


		//--- jets

		std::vector<TLorentzVector> jets;
 		std::vector<TLorentzVector> bjets;
		std::vector<Float_t>        unc;   // unimportant, but keep it, please

		for( int i = 0; i < jet_pt->size(); i++ ){

			TLorentzVector jet_tlv;

			jet_tlv.SetPtEtaPhiM( jet_pt->at(i), jet_eta->at(i), jet_phi->at(i), 0. ); 

			jets.push_back(jet_tlv);

			unc.push_back(5.);   // GeV 

		}


		for( int i = 0; i < bjet30csvv2m_pt->size(); i++ ){

			TLorentzVector bjet30csvv2m_tlv;

			bjet30csvv2m_tlv.SetPtEtaPhiM( bjet30csvv2m_pt->at(i), bjet30csvv2m_eta->at(i), bjet30csvv2m_phi->at(i), 0. ); 

			bjets.push_back(bjet30csvv2m_tlv);

		}

		//--- arguments by reference: neutrinos & tops

		std::vector<TLorentzVector> nu1, nu2;

	        TVector2 top1, top2;


		theMass.startVariations( l1, l2, bjets, jets, MET, top1, top2, topRecoW );
		

		//--- 'rosquillas' reco

		if(  top1.X() == 0  &&  top1.Y() == 0  &&  top2.X() == 0  &&  top2.Y() == 0 ){

			int theJet1 = -1; 
			int theJet2 = -1; 

			darkpt = theMass.performAllVariations( 1, 1, 1, l1, l2, jets, unc, MET, nu1, nu2, theJet1, theJet2 ); 

		}
	
		else{

			darkpt = 0.; 
			//darkpt = (top1+top2).Mod(); 

		}


		//--- writing... 

		if (WriteBranch){

			b_topRecoW -> Fill(); 
			b_darkpt   -> Fill(); 
 
		}

	}   // ievt

	fshape->Close();

	if (WriteBranch) mytree -> Write( "", TObject::kOverwrite );

  	myfile.Close();


}
Example #14
0
DGLE_RESULT DGLE_API CMesh::RecalculateTangentSpace()
{
	if (!_pBuffer)
		return S_FALSE;
	
	TDrawDataDesc desc;
		
	_pBuffer->GetBufferDrawDataDesc(desc);

	if (desc.uiTextureVertexOffset == -1 ||
		(desc.uiTangentOffset == -1 && desc.uiBinormalOffset != -1) || (desc.uiTangentOffset != -1 && desc.uiBinormalOffset == -1)) // confusing situation should never happen
		return E_ABORT;

	if (desc.uiNormalOffset == -1)
		RecalculateNormals(false);

	uint stride, verts_data_size, verts_count, idxs_data_size, idxs_count;
	_CopyMeshData(desc, stride, verts_data_size, verts_count, idxs_data_size, idxs_count);

	TDrawDataDesc desc_new(desc);
	bool do_delete_new = false;

	if (desc.uiTangentOffset == -1 && desc.uiBinormalOffset == -1)
	{
		do_delete_new = true;

		const uint new_verts_data_size = verts_data_size + verts_count * 6 * sizeof(float);
		desc_new.pData = new uint8[new_verts_data_size + idxs_data_size];
		memcpy(desc_new.pData, desc.pData, verts_data_size);

		desc_new.uiTangentOffset = verts_data_size;
		desc_new.uiTangentStride = 0;

		desc_new.uiBinormalOffset = verts_data_size + verts_count * 3 * sizeof(float);
		desc_new.uiBinormalStride = 0;

		if (idxs_count != 0)
		{
			desc_new.pIndexBuffer = &desc_new.pData[new_verts_data_size];
			memcpy(&desc_new.pData[new_verts_data_size], &desc.pData[verts_data_size], idxs_data_size);
		}

		memset(&desc_new.pData[verts_data_size], 0, new_verts_data_size - verts_data_size);
	}
	else
	{
		const uint t_stride = desc_new.uiTangentStride == 0 ? 3 * sizeof(float) : desc_new.uiTangentStride,
			b_stride = desc_new.uiBinormalStride == 0 ? 3 * sizeof(float) : desc_new.uiBinormalStride;

		for (uint i = 0; i < verts_count; ++i)
		{
			*(reinterpret_cast<TVector3 *>(&desc_new.pData[desc_new.uiTangentOffset + i * t_stride])) = TVector3();
			*(reinterpret_cast<TVector3 *>(&desc_new.pData[desc_new.uiBinormalOffset + i * b_stride])) = TVector3();
		}
	}

	const uint t_stride = desc_new.uiTangentStride == 0 ? 3 * sizeof(float) : desc_new.uiTangentStride,
		b_stride = desc_new.uiBinormalStride == 0 ? 3 * sizeof(float) : desc_new.uiBinormalStride,
		tex_stride = desc_new.uiTextureVertexStride == 0 ? 2 * sizeof(float) : desc_new.uiTextureVertexStride,
		v_stride = desc_new.uiVertexStride == 0 ? 3 * sizeof(float) : desc_new.uiVertexStride,
		n_stride = desc_new.uiNormalStride == 0 ? 3 * sizeof(float) : desc_new.uiNormalStride,
		count = idxs_count == 0 ? verts_count / 3 : idxs_count / 3;

	for(uint i = 0; i < count; ++i)
	{
		uint face[3];

		if (idxs_count == 0)
		{
			face[0] = i * 3;
			face[1] = i * 3 + 1;
			face[2] = i * 3 + 2;
		}
		else
			if (desc_new.bIndexBuffer32)
			{
				face[0] = reinterpret_cast<uint *>(&desc_new.pIndexBuffer[i * 3 * sizeof(uint)])[0];
				face[1] = reinterpret_cast<uint *>(&desc_new.pIndexBuffer[i * 3 * sizeof(uint)])[1];
				face[2] = reinterpret_cast<uint *>(&desc_new.pIndexBuffer[i * 3 * sizeof(uint)])[2];
			}
			else
			{
				face[0] = reinterpret_cast<uint16 *>(&desc_new.pIndexBuffer[i * 3 * sizeof(uint16)])[0];
				face[1] = reinterpret_cast<uint16 *>(&desc_new.pIndexBuffer[i * 3 * sizeof(uint16)])[1];
				face[2] = reinterpret_cast<uint16 *>(&desc_new.pIndexBuffer[i * 3 * sizeof(uint16)])[2];
			}
			
		const TPoint3 * const v[3] = {
			reinterpret_cast<TPoint3 *>(&desc_new.pData[face[0] * v_stride]),
			reinterpret_cast<TPoint3 *>(&desc_new.pData[face[1] * v_stride]),
			reinterpret_cast<TPoint3 *>(&desc_new.pData[face[2] * v_stride])};

		const TPoint2 * const t[3] = {
			reinterpret_cast<TPoint2 *>(&desc_new.pData[desc_new.uiTextureVertexOffset + face[0] * tex_stride]),
			reinterpret_cast<TPoint2 *>(&desc_new.pData[desc_new.uiTextureVertexOffset + face[1] * tex_stride]),
			reinterpret_cast<TPoint2 *>(&desc_new.pData[desc_new.uiTextureVertexOffset + face[2] * tex_stride])};

		const TVector3 v1 = *v[1] - *v[0], v2 = *v[2] - *v[0];
		const TVector2 v3 = *t[1] - *t[0], v4 = *t[2] - *t[0];

		const float d = v3.Cross(v4);

		if (d == 0.f) continue;

		const float r = 1.f / d;

		const TVector3 sdir = TVector3(v4.y * v1.x - v4.x * v2.x, v4.y * v1.y - v4.x * v2.y, v4.y * v1.z - v4.x * v2.z) * r,
			tdir = TVector3(v3.x * v2.x - v3.y * v1.x, v3.x * v2.y - v3.y * v1.y, v3.x * v2.z - v3.y * v1.z) * r;

		*(reinterpret_cast<TVector3 *>(&desc_new.pData[desc_new.uiTangentOffset + face[0] * t_stride])) += sdir;
		*(reinterpret_cast<TVector3 *>(&desc_new.pData[desc_new.uiTangentOffset + face[1] * t_stride])) += sdir;
		*(reinterpret_cast<TVector3 *>(&desc_new.pData[desc_new.uiTangentOffset + face[2] * t_stride])) += sdir;

		*(reinterpret_cast<TVector3 *>(&desc_new.pData[desc_new.uiBinormalOffset + face[0] * b_stride])) += tdir;
		*(reinterpret_cast<TVector3 *>(&desc_new.pData[desc_new.uiBinormalOffset + face[1] * b_stride])) += tdir;
		*(reinterpret_cast<TVector3 *>(&desc_new.pData[desc_new.uiBinormalOffset + face[2] * b_stride])) += tdir;
	}

	for (uint i = 0; i < verts_count; ++i)
	{
		const TVector3 * const normal = reinterpret_cast<TVector3 *>(&desc_new.pData[desc_new.uiNormalOffset + i * n_stride]);
		TVector3 *tangent = reinterpret_cast<TVector3 *>(&desc_new.pData[desc_new.uiTangentOffset + i * t_stride]),
			*binormal = reinterpret_cast<TVector3 *>(&desc_new.pData[desc_new.uiBinormalOffset + i * b_stride]);
		
		float dot_1 = normal->Dot(*tangent), dot_2;
		*tangent = (*tangent - *normal * dot_1).Normalize();
		dot_1 = normal->Dot(*tangent);
		dot_2 = tangent->Dot(*binormal);
		*binormal = (*binormal - *normal * dot_1 + *tangent * dot_2).Normalize();
	}

	PARANOIC_CHECK_RES(_pBuffer->Reallocate(desc_new, verts_count, idxs_count, CRDM_TRIANGLES));

	if (do_delete_new)
		delete[] desc_new.pData;

	delete[] desc.pData;

	return S_OK;
}
Example #15
0
Bool_t test::Process(Long64_t entry)
{
  // The Process() function is called for each entry in the tree (or possibly
  // keyed object in the case of PROOF) to be processed. The entry argument
  // specifies which entry in the currently loaded tree is to be processed.
  // It can be passed to either test::GetEntry() or TBranch::GetEntry()
  // to read either all or the required parts of the data. When processing
  // keyed objects with PROOF, the object is already loaded and is available
  // via the fObject pointer.
  //
  // This function should contain the "body" of the analysis. It can contain
  // simple or elaborate selection criteria, run algorithms on the data
  // of the event and typically fill histograms.
  //
  // The processing can be stopped by calling Abort().
  //
  // Use fStatus to set the return value of TTree::Process().
  //
  // The return value is currently not used.
  if (entry % 1000 == 0){
    std::cout<<"Entry: "<<entry<<std::endl;
  }

  GetEntry(entry);

  w=WT00;

  TLorentzVector * nVec = new TLorentzVector() ;
  TLorentzVector * eVec = new TLorentzVector() ;
  TLorentzVector * wVec = new TLorentzVector() ;


  nVec->SetPxPyPzE(Px_d2, Py_d2, Pz_d2, E_d2);
  eVec->SetPxPyPzE(Px_d1, Py_d1, Pz_d1, E_d1);
  wVec->SetPxPyPzE(Px_V, Py_V, Pz_V, E_V);

  if (eVec->Pt()>lep_ET){
    if (fabs(eVec->Eta())<lep_eta){
      if (fabs(eVec->Eta())<lep_crack_1 || fabs(eVec->Eta())>lep_crack_2){
        //std::cout<<"met: "<<met<<std::endl;
        if (bZ){
          if (fabs(nVec->Eta())<lep_crack_1 || fabs(nVec->Eta())>lep_crack_2){
            TVector2 * MET = new TVector2(0.,0.);

            TVector2 sumLepton(Px_d1+Px_d2, Py_d1+Py_d2);

            SetTreeVariables(wVec, wVec, &sumLepton, MET, MET, w, 0, iTree);

            delete MET;
          }
        }
        else{
          double met = nVec->Pt();
          double met_phi = nVec->Phi();
          TVector2 * MET = new TVector2(0.,0.);

          TVector2 sumLepton(Px_d1, Py_d1);

          MET->SetMagPhi(met,met_phi);
          SetTreeVariables(wVec, wVec, &sumLepton, MET, MET, w, 0, iTree);

          delete MET;
        }
      }
    }
  }
  delete nVec;
  delete eVec;
  delete wVec;
  return kTRUE;

}
void fillCategory(EventTree* tree, TH1F* hist, double weight){
	int EleP = 0;
	int EleM = 0;
	int MuP = 0;
	int MuM = 0;
	int TauP = 0;
	int TauM = 0;
	int ElePfid = 0;
	int EleMfid = 0;
	int MuPfid = 0;
	int MuMfid = 0;
	int nNufid = 0;

	int nPhofid = 0;
	int nJetfid = 0;
	int nBJetfid = 0;

	TVector2 MET = TVector2(0,0);
	TVector2 tempNu = TVector2(0,0);

	for( int mcI = 0; mcI < tree->nMC_; ++mcI){
	  if(abs(tree->mcMomPID->at(mcI))==24 && tree->mcParentage->at(mcI)==10){
	    if( tree->mcPID->at(mcI) == 11 ) EleP = 1;
	    if( tree->mcPID->at(mcI) == -11 ) EleM = 1;
	    if( tree->mcPID->at(mcI) == 13 ) MuP = 1;
	    if( tree->mcPID->at(mcI) == -13 ) MuM = 1;
	    if( tree->mcPID->at(mcI) == 15) TauP = 1;
	    if( tree->mcPID->at(mcI) == -15) TauM = 1;
	  }
	  if((abs(tree->mcMomPID->at(mcI))==24 && tree->mcParentage->at(mcI)==10) || (abs(tree->mcMomPID->at(mcI))==15 && tree->mcParentage->at(mcI)==26)){		  
	    if( tree->mcPID->at(mcI) == 11 ) {
	      if (tree->mcPt->at(mcI) > 35 && (fabs(tree->mcEta->at(mcI)) < 2.5 && !(fabs(tree->mcEta->at(mcI)) > 1.4442 && fabs(tree->mcEta->at(mcI))<1.566))) ElePfid += 1;
	    }
	    if( tree->mcPID->at(mcI) == -11 ) {
	      if (tree->mcPt->at(mcI) > 35 && (fabs(tree->mcEta->at(mcI)) < 2.5 && !(fabs(tree->mcEta->at(mcI)) > 1.4442 && fabs(tree->mcEta->at(mcI))<1.566))) EleMfid += 1;
	    }
	    if( tree->mcPID->at(mcI) == 13 ) {
	      if (tree->mcPt->at(mcI) > 26 && fabs(tree->mcEta->at(mcI)) < 2.1) MuPfid += 1;
	    }
	    if( tree->mcPID->at(mcI) == -13 ) {
	      if (tree->mcPt->at(mcI) > 26 && fabs(tree->mcEta->at(mcI)) < 2.1) MuMfid += 1;
	    }
	  }
	  if( fabs(tree->mcPID->at(mcI)) == 12 || fabs(tree->mcPID->at(mcI)) == 14 || fabs(tree->mcPID->at(mcI)) == 16 ) {
	    if (tree->mcPt->at(mcI) > 20){
	      nNufid += 1;
	      //cout << nNufid << "\t" << tree->run_ << tree->lumis_ << tree->event_ << "\t" << mcI << "\t" <<  tree->mcPt->at(mcI) << "\t" << tree->mcEta->at(mcI) << "\t" << tree->mcPhi->at(mcI) << endl;
	    }
	    tempNu.SetMagPhi(tree->mcPt->at(mcI),tree->mcPhi->at(mcI));
	    MET += tempNu;
	    //	    cout << nNufid << "\t" << tree->run_ << tree->lumis_ << tree->event_ << "\t" << mcI << "\t" << tree->mcPID->at(mcI) << "\t" <<  tree->mcPt->at(mcI) << "\t" << tree->mcEta->at(mcI) << "\t" << tree->mcPhi->at(mcI) << "\t" << MET.Mod() << endl;
	  }

	  if(tree->mcPID->at(mcI) == 22 && 
	     (tree->mcParentage->at(mcI)==2 || tree->mcParentage->at(mcI)==10 || tree->mcParentage->at(mcI)==26) && 
	     tree->mcPt->at(mcI) > 25 && 
	     fabs(tree->mcEta->at(mcI)) < 1.4442){
	    nPhofid += 1;
	  }

	  if( abs(tree->mcPID->at(mcI)) < 6 && (abs(tree->mcMomPID->at(mcI))==24 || abs(tree->mcMomPID->at(mcI))==6 ) && tree->mcPt->at(mcI) > 30 && abs(tree->mcEta->at(mcI))<2.4 ) {
	    nJetfid += 1;
	    if (abs(tree->mcMomPID->at(mcI))==6 && abs(tree->mcPID->at(mcI))==5){
	      nBJetfid += 1;
	    }
	  }
	}
	
	hist->Fill(1.0, weight); // Total
	int nEle = EleP + EleM;
	int nMu = MuP + MuM;
	int nTau = TauP + TauM;
	if( nEle + nMu + nTau == 0) hist->Fill(2.0, weight); // All Had
	if( nEle + nMu + nTau == 1) hist->Fill(3.0, weight); // Single Lepton
	if( nEle + nMu + nTau == 2) hist->Fill(4.0, weight); // Di Lepton

	int nElefid = ElePfid + EleMfid;
	int nMufid = MuPfid + MuMfid;

	if ( nEle==1 && nMu==0 && nTau==0 ) hist->Fill(6.0, weight);
	if ( nEle==0 && nMu==1 && nTau==0 ) hist->Fill(7.0, weight);
	if ( nEle==0 && nMu==0 && nTau==1 ) hist->Fill(8.0, weight);
	if ( nElefid==1 && nMufid==0) hist->Fill(9.0, weight); //Ejets final state (generated)
	if ( nElefid==0 && nMufid==1) hist->Fill(10.0, weight); //Mujets final state (generated)

	// if ( nElefid==1 && nMufid==0) hist->Fill(6.0, weight); //Ejets final state (generated)
	// if ( nElefid==2 && nMufid==0) hist->Fill(7.0, weight); //Ejets final state (generated)
	// if ( nElefid==0 && nMufid==1) hist->Fill(8.0, weight); //Mujets final state (generated)
	// if ( nElefid==0 && nMufid==2) hist->Fill(9.0, weight); //Ejets final state (generated)
	// if ( nElefid==1 && nMufid==1) hist->Fill(10.0, weight); //Ejets final state (generated)

	int nJetsfid = 0;
	int nBJetsfid = 0;
	
	if ((nElefid + nMufid)==1){
	  // for ( int jetI = 0; jetI < tree->genJetPt_->size(); jetI++){
	  //   if (tree->genJetPt_->at(jetI) >= 30 && fabs(tree->genJetEta_->at(jetI)) < 2.4) nJetsfid += 1;	    
	  // }
	  for ( int jetI = 0; jetI < tree->nJet_; jetI++){
	    //	    if (tree->jetGenPt_->at(jetI) >= 30 && fabs(tree->jetGenEta_->at(jetI)) < 2.4) nJetsfid += 1;
	    if (tree->jetGenJetPt_->at(jetI) >= 30 && fabs(tree->jetGenEta_->at(jetI)) < 2.4){
	      nJetsfid += 1;
	      if (abs(tree->jetGenPartonID_->at(jetI))==5) nBJetsfid += 1;
	    }
	  }
	}


	if(nElefid==1 && nMufid==0 && nJetsfid >=3){
	  hist->Fill(11.0, weight);
	  if (nBJetsfid >= 1){
	    hist->Fill(12.0, weight);
	    if (MET.Mod() > 20){
	      //	    if (tree->genMET_ > 20){
	      hist->Fill(13.0, weight);
	      if (nPhofid > 0) hist->Fill(14.0, weight);
	    }
	  }
	}


	// //TESTING
	// if(nElefid==0 && nMufid==1 && nJetsfid >=3){
	//   hist->Fill(11.0, weight);
	//   if (nNufid==1){
	//     hist->Fill(12.0,weight);
	//   }
	//   if (nNufid > 0){
	//     hist->Fill(13.0, weight);
	//   }
	//   if (MET.Mod() > 20) hist->Fill(14.0,weight);
	//   if (nBJetsfid >= 1){
	//     //	    hist->Fill(12.0, weight);
	//     if (tree->genMET_ > 20){
	//       //	      hist->Fill(13.0, weight);
	//       // if (nPhofid > 0) hist->Fill(14.0, weight);
	//     }
	//   }
	// }

	if(nElefid==0 && nMufid==1 && nJetsfid >=3){
	  hist->Fill(16.0, weight);
	  if (nBJetsfid >= 1){
	    hist->Fill(17.0, weight);
	    //	    if (tree->genMET_ > 20){
	    if (MET.Mod() > 20){
	      hist->Fill(18.0, weight);
	      if (nPhofid > 0) hist->Fill(19.0, weight);
	    }
	  }
	}
	// if(nElefid==0 && nMufid==1 && nJetfid >=3 && nBJetfid >= 1 && nNufid == 1) {
	//   hist->Fill(12.0, weight);
	//   if (nPhofid > 0) hist->Fill(15.0, weight);
	// }

	// if(nElefid==1 && nMufid==0 && nJetsfid >=3 && nNufid == 1){
	//   hist->Fill(11.0, weight);
	//   if (nPhofid > 0) hist->Fill(14.0, weight);
	// }
	// if(nElefid==0 && nMufid==1 && nJetsfid >=3 && nNufid == 1) {
	//   hist->Fill(12.0, weight);
	//   if (nPhofid > 0) hist->Fill(15.0, weight);
	// }

	return;
}
Example #17
0
template <typename T> ork::TVector2<T>::TVector2( const TVector2<T>& vec)
	: x( vec.GetX() )
	, y( vec.GetY() )
{
}
Example #18
0
void selectZmm(const TString conf="zmm.conf", // input file
               const TString outputDir=".",   // output directory
	       const Bool_t  doScaleCorr=0,    // apply energy scale corrections
	       const Bool_t  doPU=0
) {
  gBenchmark->Start("selectZmm");

  //--------------------------------------------------------------------------------------------------------------
  // Settings 
  //============================================================================================================== 

  const Double_t MASS_LOW  = 40;
  const Double_t MASS_HIGH = 200;
  const Double_t PT_CUT    = 22;
  const Double_t ETA_CUT   = 2.4;
  const Double_t MUON_MASS = 0.105658369;

  const Int_t BOSON_ID  = 23;
  const Int_t LEPTON_ID = 13;

  // load trigger menu                                                                                                  
  const baconhep::TTrigger triggerMenu("../../BaconAna/DataFormats/data/HLT_50nsGRun");

  // load pileup reweighting file                                                                                       
  TFile *f_rw = TFile::Open("../Tools/puWeights_76x.root", "read");

  TH1D *h_rw = (TH1D*) f_rw->Get("puWeights");
  TH1D *h_rw_up = (TH1D*) f_rw->Get("puWeightsUp");
  TH1D *h_rw_down = (TH1D*) f_rw->Get("puWeightsDown");


  if (h_rw==NULL) cout<<"WARNING h_rw == NULL"<<endl;
  if (h_rw_up==NULL) cout<<"WARNING h_rw == NULL"<<endl;
  if (h_rw_down==NULL) cout<<"WARNING h_rw == NULL"<<endl;

  //--------------------------------------------------------------------------------------------------------------
  // Main analysis code 
  //==============================================================================================================  

  enum { eMuMu2HLT=1, eMuMu1HLT1L1, eMuMu1HLT, eMuMuNoSel, eMuSta, eMuTrk };  // event category enum
  
  vector<TString>  snamev;      // sample name (for output files)  
  vector<CSample*> samplev;     // data/MC samples

  //
  // parse .conf file
  //
  confParse(conf, snamev, samplev);
  const Bool_t hasData = (samplev[0]->fnamev.size()>0);

  // Create output directory
  gSystem->mkdir(outputDir,kTRUE);
  const TString ntupDir = outputDir + TString("/ntuples");
  gSystem->mkdir(ntupDir,kTRUE);
  
  //
  // Declare output ntuple variables
  //
  UInt_t  runNum, lumiSec, evtNum;
  UInt_t  matchGen;
  UInt_t  category;
  UInt_t  npv, npu;
  UInt_t  id_1, id_2;
  Double_t x_1, x_2, xPDF_1, xPDF_2;
  Double_t scalePDF, weightPDF;
  TLorentzVector *genV=0;
  Float_t genVPt, genVPhi, genVy, genVMass;
  Float_t genWeight, PUWeight;
  Float_t scale1fb,scale1fbUp,scale1fbDown;
  Float_t met, metPhi, sumEt, u1, u2;
  Float_t tkMet, tkMetPhi, tkSumEt, tkU1, tkU2;
  Float_t mvaMet, mvaMetPhi, mvaSumEt, mvaU1, mvaU2;
  Float_t puppiMet, puppiMetPhi, puppiSumEt, puppiU1, puppiU2;
  Int_t   q1, q2;
  TLorentzVector *dilep=0, *lep1=0, *lep2=0;
  ///// muon specific /////
  Float_t trkIso1, emIso1, hadIso1, trkIso2, emIso2, hadIso2;
  Float_t pfChIso1, pfGamIso1, pfNeuIso1, pfCombIso1, pfChIso2, pfGamIso2, pfNeuIso2, pfCombIso2;
  Float_t d01, dz1, d02, dz2;
  Float_t muNchi21,  muNchi22;
  UInt_t nPixHits1, nTkLayers1, nPixHits2, nTkLayers2;
  UInt_t nValidHits1, nMatch1, nValidHits2, nMatch2;
  UInt_t typeBits1, typeBits2;
  TLorentzVector *sta1=0, *sta2=0;
  
  // Data structures to store info from TTrees
  baconhep::TEventInfo *info   = new baconhep::TEventInfo();
  baconhep::TGenEventInfo *gen = new baconhep::TGenEventInfo();
  TClonesArray *genPartArr = new TClonesArray("baconhep::TGenParticle");
  TClonesArray *muonArr    = new TClonesArray("baconhep::TMuon");
  TClonesArray *vertexArr  = new TClonesArray("baconhep::TVertex");
  
  TFile *infile=0;
  TTree *eventTree=0;

    
  //
  // loop over samples
  //  
  for(UInt_t isam=0; isam<samplev.size(); isam++) {
    // Assume data sample is first sample in .conf file
    // If sample is empty (i.e. contains no ntuple files), skip to next sample
    Bool_t isData=kFALSE;
    if(isam==0 && !hasData) continue;
    else if (isam==0) isData=kTRUE;
    
    // Assume signal sample is given name "zmm" - flag to store GEN Z kinematics
    Bool_t isSignal = (snamev[isam].CompareTo("zmm",TString::kIgnoreCase)==0);
    // flag to reject Z->mm events when selecting at wrong-flavor background events
    Bool_t isWrongFlavor = (snamev[isam].CompareTo("zxx",TString::kIgnoreCase)==0);
    
    CSample* samp = samplev[isam];
    
    //
    // Set up output ntuple
    //
    TString outfilename = ntupDir + TString("/") + snamev[isam] + TString("_select.root");
    if(isam!=0 && !doScaleCorr) outfilename = ntupDir + TString("/") + snamev[isam] + TString("_select.raw.root");
    
    TFile *outFile = new TFile(outfilename,"RECREATE"); 
    TTree *outTree = new TTree("Events","Events");
    outTree->Branch("runNum",      &runNum,     "runNum/i");      // event run number
    outTree->Branch("lumiSec",     &lumiSec,    "lumiSec/i");     // event lumi section
    outTree->Branch("evtNum",      &evtNum,     "evtNum/i");      // event number
    outTree->Branch("matchGen",    &matchGen,   "matchGen/i");    // event has both leptons matched to MC Z->ll
    outTree->Branch("category",    &category,   "category/i");    // dilepton category
    outTree->Branch("id_1",        &id_1,       "id_1/i");        // PDF info -- parton ID for parton 1
    outTree->Branch("id_2",        &id_2,       "id_2/i");        // PDF info -- parton ID for parton 2
    outTree->Branch("x_1",         &x_1,        "x_1/d");         // PDF info -- x for parton 1
    outTree->Branch("x_2",         &x_2,        "x_2/d");         // PDF info -- x for parton 2
    outTree->Branch("xPDF_1",      &xPDF_1,     "xPDF_1/d");      // PDF info -- x*F for parton 1
    outTree->Branch("xPDF_2",      &xPDF_2,     "xPDF_2/d");      // PDF info -- x*F for parton 2
    outTree->Branch("scalePDF",    &scalePDF,   "scalePDF/d");    // PDF info -- energy scale of parton interaction
    outTree->Branch("weightPDF",   &weightPDF,  "weightPDF/d");   // PDF info -- PDF weight
    outTree->Branch("npv",         &npv,        "npv/i");         // number of primary vertices
    outTree->Branch("npu",         &npu,        "npu/i");         // number of in-time PU events (MC)
    outTree->Branch("genV",        "TLorentzVector",  &genV);     // GEN boson 4-vector (signal MC)
    outTree->Branch("genVPt",      &genVPt,     "genVPt/F");      // GEN boson pT (signal MC)
    outTree->Branch("genVPhi",     &genVPhi,    "genVPhi/F");     // GEN boson phi (signal MC)
    outTree->Branch("genVy",       &genVy,      "genVy/F");       // GEN boson rapidity (signal MC)
    outTree->Branch("genVMass",    &genVMass,   "genVMass/F");    // GEN boson mass (signal MC)
    outTree->Branch("genWeight",   &genWeight,  "genWeight/F");
    outTree->Branch("PUWeight",    &PUWeight,   "PUWeight/F");
    outTree->Branch("scale1fb",    &scale1fb,   "scale1fb/F");    // event weight per 1/fb (MC)
    outTree->Branch("scale1fbUp",    &scale1fbUp,   "scale1fbUp/F");    // event weight per 1/fb (MC)
    outTree->Branch("scale1fbDown",    &scale1fbDown,   "scale1fbDown/F");    // event weight per 1/fb (MC)
    outTree->Branch("met",         &met,        "met/F");         // MET
    outTree->Branch("metPhi",      &metPhi,     "metPhi/F");      // phi(MET)
    outTree->Branch("sumEt",       &sumEt,      "sumEt/F");       // Sum ET
    outTree->Branch("u1",          &u1,         "u1/F");          // parallel component of recoil
    outTree->Branch("u2",          &u2,         "u2/F");          // perpendicular component of recoil
    outTree->Branch("tkMet",       &tkMet,      "tkMet/F");       // MET (track MET)
    outTree->Branch("tkMetPhi",    &tkMetPhi,   "tkMetPhi/F");    // phi(MET) (track MET)
    outTree->Branch("tkSumEt",     &tkSumEt,    "tkSumEt/F");     // Sum ET (track MET)
    outTree->Branch("tkU1",        &tkU1,       "tkU1/F");        // parallel component of recoil (track MET)
    outTree->Branch("tkU2",        &tkU2,       "tkU2/F");        // perpendicular component of recoil (track MET)
    outTree->Branch("mvaMet",      &mvaMet,     "mvaMet/F");      // MVA MET
    outTree->Branch("mvaMetPhi",   &mvaMetPhi,  "mvaMetPhi/F");   // phi(MVA MET)
    outTree->Branch("mvaSumEt",    &mvaSumEt,   "mvaSumEt/F");    // Sum ET (mva MET)
    outTree->Branch("mvaU1",       &mvaU1,      "mvaU1/F");       // parallel component of recoil (mva MET)
    outTree->Branch("mvaU2",       &mvaU2,      "mvaU2/F");       // perpendicular component of recoil (mva MET) 
    outTree->Branch("puppiMet",    &puppiMet,   "puppiMet/F");      // Puppi MET
    outTree->Branch("puppiMetPhi", &puppiMetPhi,"puppiMetPhi/F");   // phi(Puppi MET)
    outTree->Branch("puppiSumEt",  &puppiSumEt, "puppiSumEt/F");    // Sum ET (Puppi MET)
    outTree->Branch("puppiU1",     &puppiU1,    "puppiU1/F");       // parallel component of recoil (Puppi MET)
    outTree->Branch("puppiU2",     &puppiU2,    "puppiU2/F");       // perpendicular component of recoil (Puppi MET)
    outTree->Branch("q1",          &q1,         "q1/I");          // charge of tag lepton
    outTree->Branch("q2",          &q2,         "q2/I");          // charge of probe lepton
    outTree->Branch("dilep",       "TLorentzVector", &dilep);     // di-lepton 4-vector
    outTree->Branch("lep1",        "TLorentzVector", &lep1);      // tag lepton 4-vector
    outTree->Branch("lep2",        "TLorentzVector", &lep2);      // probe lepton 4-vector
    ///// muon specific /////
    outTree->Branch("trkIso1",     &trkIso1,     "trkIso1/F");       // track isolation of tag lepton
    outTree->Branch("trkIso2",     &trkIso2,     "trkIso2/F");       // track isolation of probe lepton
    outTree->Branch("emIso1",      &emIso1,      "emIso1/F");        // ECAL isolation of tag lepton
    outTree->Branch("emIso2",      &emIso2,      "emIso2/F");        // ECAL isolation of probe lepton
    outTree->Branch("hadIso1",     &hadIso1,     "hadIso1/F");       // HCAL isolation of tag lepton
    outTree->Branch("hadIso2",     &hadIso2,     "hadIso2/F");       // HCAL isolation of probe lepton
    outTree->Branch("pfChIso1",    &pfChIso1,    "pfChIso1/F");      // PF charged hadron isolation of tag lepton
    outTree->Branch("pfChIso2",    &pfChIso2,    "pfChIso2/F");      // PF charged hadron isolation of probe lepton
    outTree->Branch("pfGamIso1",   &pfGamIso1,   "pfGamIso1/F");     // PF photon isolation of tag lepton
    outTree->Branch("pfGamIso2",   &pfGamIso2,   "pfGamIso2/F");     // PF photon isolation of probe lepton
    outTree->Branch("pfNeuIso1",   &pfNeuIso1,   "pfNeuIso1/F");     // PF neutral hadron isolation of tag lepton
    outTree->Branch("pfNeuIso2",   &pfNeuIso2,   "pfNeuIso2/F");     // PF neutral hadron isolation of probe lepton
    outTree->Branch("pfCombIso1",  &pfCombIso1,  "pfCombIso1/F");    // PF combined isolation of tag lepton
    outTree->Branch("pfCombIso2",  &pfCombIso2,  "pfCombIso2/F");    // PF combined isolation of probe lepton    
    outTree->Branch("d01",         &d01,         "d01/F");           // transverse impact parameter of tag lepton
    outTree->Branch("d02",         &d02,         "d02/F");           // transverse impact parameter of probe lepton	 
    outTree->Branch("dz1",         &dz1,         "dz1/F");           // longitudinal impact parameter of tag lepton
    outTree->Branch("dz2",         &dz2,         "dz2/F");           // longitudinal impact parameter of probe lepton	 
    outTree->Branch("muNchi21",    &muNchi21,    "muNchi21/F");      // muon fit normalized chi^2 of tag lepton
    outTree->Branch("muNchi22",    &muNchi22,    "muNchi22/F");      // muon fit normalized chi^2 of probe lepton
    outTree->Branch("nPixHits1",   &nPixHits1,	 "nPixHits1/i");     // number of pixel hits of tag muon
    outTree->Branch("nPixHits2",   &nPixHits2,	 "nPixHits2/i");     // number of pixel hits of probe muon
    outTree->Branch("nTkLayers1",  &nTkLayers1,  "nTkLayers1/i");    // number of tracker layers of tag muon
    outTree->Branch("nTkLayers2",  &nTkLayers2,  "nTkLayers2/i");    // number of tracker layers of probe muon
    outTree->Branch("nMatch1",     &nMatch1,	 "nMatch1/i");       // number of matched segments of tag muon
    outTree->Branch("nMatch2",     &nMatch2,	 "nMatch2/i");       // number of matched segments of probe muon 
    outTree->Branch("nValidHits1", &nValidHits1, "nValidHits1/i");   // number of valid muon hits of tag muon
    outTree->Branch("nValidHits2", &nValidHits2, "nValidHits2/i");   // number of valid muon hits of probe muon
    outTree->Branch("typeBits1",   &typeBits1,   "typeBits1/i");     // muon type of tag muon
    outTree->Branch("typeBits2",   &typeBits2,   "typeBits2/i");     // muon type of probe muon
    outTree->Branch("sta1",        "TLorentzVector", &sta1);         // tag standalone muon 4-vector
    outTree->Branch("sta2",        "TLorentzVector", &sta2);         // probe standalone muon 4-vector
    
    //
    // loop through files
    //
    const UInt_t nfiles = samp->fnamev.size();
    for(UInt_t ifile=0; ifile<nfiles; ifile++) {  
      
      // Read input file and get the TTrees
      cout << "Processing " << samp->fnamev[ifile] << " [xsec = " << samp->xsecv[ifile] << " pb] ... "; cout.flush();
      infile = TFile::Open(samp->fnamev[ifile]); 
      assert(infile);
      if (samp->fnamev[ifile] == "/dev/null") 
	      {
	     	cout <<"-> Ignoring null input "<<endl; 
		continue;
	      }


      Bool_t hasJSON = kFALSE;
      baconhep::RunLumiRangeMap rlrm;
      if(samp->jsonv[ifile].CompareTo("NONE")!=0) { 
        hasJSON = kTRUE;
	rlrm.addJSONFile(samp->jsonv[ifile].Data()); 
      }
  
      eventTree = (TTree*)infile->Get("Events"); assert(eventTree);  
      eventTree->SetBranchAddress("Info", &info);      TBranch *infoBr = eventTree->GetBranch("Info");
      eventTree->SetBranchAddress("Muon", &muonArr);   TBranch *muonBr = eventTree->GetBranch("Muon");
      eventTree->SetBranchAddress("PV",   &vertexArr); TBranch *vertexBr = eventTree->GetBranch("PV");
      Bool_t hasGen = eventTree->GetBranchStatus("GenEvtInfo");
      TBranch *genBr=0, *genPartBr=0;
      if(hasGen) {
        eventTree->SetBranchAddress("GenEvtInfo", &gen); genBr = eventTree->GetBranch("GenEvtInfo");
	eventTree->SetBranchAddress("GenParticle",&genPartArr); genPartBr = eventTree->GetBranch("GenParticle");
      }

      // Compute MC event weight per 1/fb
      const Double_t xsec = samp->xsecv[ifile];
      Double_t totalWeight=0;
      Double_t totalWeightUp=0;
      Double_t totalWeightDown=0;
      Double_t puWeight=0;
      Double_t puWeightUp=0;
      Double_t puWeightDown=0;

      if (hasGen) {
	for(UInt_t ientry=0; ientry<eventTree->GetEntries(); ientry++) {
	  infoBr->GetEntry(ientry);
	  genBr->GetEntry(ientry);
	  puWeight = doPU ? h_rw->GetBinContent(h_rw->FindBin(info->nPUmean)) : 1.;
	  puWeightUp = doPU ? h_rw_up->GetBinContent(h_rw_up->FindBin(info->nPUmean)) : 1.;
	  puWeightDown = doPU ? h_rw_down->GetBinContent(h_rw_down->FindBin(info->nPUmean)) : 1.;
	  totalWeight+=gen->weight*puWeight;
	  totalWeightUp+=gen->weight*puWeightUp;
	  totalWeightDown+=gen->weight*puWeightDown;
	}
      }
      else if (not isData){
	for(UInt_t ientry=0; ientry<eventTree->GetEntries(); ientry++) {
	  puWeight = doPU ? h_rw->GetBinContent(h_rw->FindBin(info->nPUmean)) : 1.;
	  puWeightUp = doPU ? h_rw_up->GetBinContent(h_rw_up->FindBin(info->nPUmean)) : 1.;
	  puWeightDown = doPU ? h_rw_down->GetBinContent(h_rw_down->FindBin(info->nPUmean)) : 1.;
	  totalWeight+= 1.0*puWeight;
	  totalWeightUp+= 1.0*puWeightUp;
	  totalWeightDown+= 1.0*puWeightDown;
	}

      }
   
      //
      // loop over events
      //
      Double_t nsel=0, nselvar=0;
      for(UInt_t ientry=0; ientry<eventTree->GetEntries(); ientry++) {
        infoBr->GetEntry(ientry);

	if(ientry%1000000==0) cout << "Processing event " << ientry << ". " << (double)ientry/(double)eventTree->GetEntries()*100 << " percent done with this file." << endl;

	Double_t weight=1;
	Double_t weightUp=1;
	Double_t weightDown=1;
    if(xsec>0 && totalWeight>0) weight = xsec/totalWeight;
	if(xsec>0 && totalWeightUp>0) weightUp = xsec/totalWeightUp;
	if(xsec>0 && totalWeightDown>0) weightDown = xsec/totalWeightDown;
	if(hasGen) {
	  genPartArr->Clear();
	  genBr->GetEntry(ientry);
          genPartBr->GetEntry(ientry);
	  puWeight = doPU ? h_rw->GetBinContent(h_rw->FindBin(info->nPUmean)) : 1.;
	  puWeightUp = doPU ? h_rw_up->GetBinContent(h_rw_up->FindBin(info->nPUmean)) : 1.;
	  puWeightDown = doPU ? h_rw_down->GetBinContent(h_rw_down->FindBin(info->nPUmean)) : 1.;
	  weight*=gen->weight*puWeight;
	  weightUp*=gen->weight*puWeightUp;
	  weightDown*=gen->weight*puWeightDown;
	}

	// veto z -> xx decays for signal and z -> mm for bacground samples (needed for inclusive DYToLL sample)
        if (isWrongFlavor && hasGen && fabs(toolbox::flavor(genPartArr, BOSON_ID))==LEPTON_ID) continue;
        else if (isSignal && hasGen && fabs(toolbox::flavor(genPartArr, BOSON_ID))!=LEPTON_ID) continue;
     
        // check for certified lumi (if applicable)
        baconhep::RunLumiRangeMap::RunLumiPairType rl(info->runNum, info->lumiSec);      
        if(hasJSON && !rlrm.hasRunLumi(rl)) continue;

        // trigger requirement               
        if (!isMuonTrigger(triggerMenu, info->triggerBits)) continue;

        // good vertex requirement
        if(!(info->hasGoodPV)) continue;

	muonArr->Clear();
        muonBr->GetEntry(ientry);

	TLorentzVector vTag(0,0,0,0);
	TLorentzVector vTagSta(0,0,0,0);
	Double_t tagPt=0;
	Double_t Pt1=0;
	Double_t Pt2=0;
	Int_t itag=-1;
	
        for(Int_t i1=0; i1<muonArr->GetEntriesFast(); i1++) {
          const baconhep::TMuon *tag = (baconhep::TMuon*)((*muonArr)[i1]);

          // apply scale and resolution corrections to MC
          Double_t tagpt_corr = tag->pt;
          if(doScaleCorr && snamev[isam].CompareTo("data",TString::kIgnoreCase)!=0)
            tagpt_corr = gRandom->Gaus(tag->pt*getMuScaleCorr(tag->eta,0),getMuResCorr(tag->eta,0));
	
	  if(tagpt_corr     < PT_CUT)        continue;  // lepton pT cut
	  if(fabs(tag->eta) > ETA_CUT)       continue;  // lepton |eta| cut
	  if(!passMuonID(tag))               continue;  // lepton selection

	  double Mu_Pt=0;
	  if(doScaleCorr) {
	    Mu_Pt=gRandom->Gaus(tag->pt*getMuScaleCorr(tag->eta,0),getMuResCorr(tag->eta,0));
	  }
	  else
	    {
	      Mu_Pt=tag->pt;
	    }

	  if(Mu_Pt>Pt1)
	    {
	      Pt2=Pt1;
	      Pt1=Mu_Pt;
	    }
	  else if(Mu_Pt>Pt2&&Mu_Pt<Pt1)
	    {
	      Pt2=Mu_Pt;
	    }

          if(!isMuonTriggerObj(triggerMenu, tag->hltMatchBits, kFALSE)) continue;

	  if(Mu_Pt<tagPt) continue;

	  tagPt=Mu_Pt;
	  itag=i1;
        
          // apply scale and resolution corrections to MC
          if(doScaleCorr && snamev[isam].CompareTo("data",TString::kIgnoreCase)!=0) {
            vTag.SetPtEtaPhiM(tagpt_corr,tag->eta,tag->phi,MUON_MASS);
            vTagSta.SetPtEtaPhiM(gRandom->Gaus(tag->staPt*getMuScaleCorr(tag->eta,0),getMuResCorr(tag->eta,0)),tag->staEta,tag->staPhi,MUON_MASS);
          } else {
            vTag.SetPtEtaPhiM(tag->pt,tag->eta,tag->phi,MUON_MASS);
            vTagSta.SetPtEtaPhiM(tag->staPt,tag->staEta,tag->staPhi,MUON_MASS);
          }

	  trkIso1     = tag->trkIso;
	  emIso1      = tag->ecalIso;	    
	  hadIso1     = tag->hcalIso;
	  pfChIso1    = tag->chHadIso;
	  pfGamIso1   = tag->gammaIso;
	  pfNeuIso1   = tag->neuHadIso;
	  pfCombIso1  = tag->chHadIso + TMath::Max(tag->neuHadIso + tag->gammaIso - 
						   0.5*(tag->puIso),Double_t(0));
	  d01         = tag->d0;
	  dz1         = tag->dz;
	  muNchi21    = tag->muNchi2;
	  nPixHits1   = tag->nPixHits;
	  nTkLayers1  = tag->nTkLayers;
	  nMatch1     = tag->nMatchStn;
	  nValidHits1 = tag->nValidHits;
	  typeBits1   = tag->typeBits;
	  q1 = tag->q;
	}

	if(tagPt<Pt2) continue;

	TLorentzVector vProbe(0,0,0,0); TLorentzVector vProbeSta(0,0,0,0);
	Double_t probePt=0;
	Int_t passID=false;
	UInt_t icat=0;

	for(Int_t i2=0; i2<muonArr->GetEntriesFast(); i2++) {
	  if(itag==i2) continue;
	  const baconhep::TMuon *probe = (baconhep::TMuon*)((*muonArr)[i2]);
	  

	  // apply scale and resolution corrections to MC
	  Double_t probept_corr = probe->pt;
	  if(doScaleCorr && snamev[isam].CompareTo("data",TString::kIgnoreCase)!=0)
	    probept_corr = gRandom->Gaus(probe->pt*getMuScaleCorr(probe->eta,0),getMuResCorr(probe->eta,0));

	  if(probept_corr     < PT_CUT)  continue;  // lepton pT cut
	  if(fabs(probe->eta) > ETA_CUT) continue;  // lepton |eta| cut

	  double Mu_Pt=probept_corr;
  
	  if(passID&&passMuonID(probe)&&Mu_Pt<probePt) continue;
	  if(passID&&!passMuonID(probe)) continue;
	  if(!passID&&!passMuonID(probe)&&Mu_Pt<probePt) continue;

	  if(!passID&&passMuonID(probe)) passID=true;

	  probePt=Mu_Pt;

	  // apply scale and resolution corrections to MC
	  if(doScaleCorr && snamev[isam].CompareTo("data",TString::kIgnoreCase)!=0) {
	    vProbe.SetPtEtaPhiM(probept_corr,probe->eta,probe->phi,MUON_MASS);
	    if(probe->typeBits & baconhep::EMuType::kStandalone)
	      vProbeSta.SetPtEtaPhiM(gRandom->Gaus(probe->staPt*getMuScaleCorr(probe->eta,0),getMuResCorr(probe->eta,0)),probe->staEta,probe->staPhi,MUON_MASS);
	  } else {
	    vProbe.SetPtEtaPhiM(probe->pt,probe->eta,probe->phi,MUON_MASS);
	    if(probe->typeBits & baconhep::EMuType::kStandalone)
	      vProbeSta.SetPtEtaPhiM(probe->staPt,probe->staEta,probe->staPhi,MUON_MASS);
	  }

	  trkIso2     = probe->trkIso;
	  emIso2      = probe->ecalIso;
	  hadIso2     = probe->hcalIso;
	  pfChIso2    = probe->chHadIso;
	  pfGamIso2   = probe->gammaIso;
	  pfNeuIso2   = probe->neuHadIso;
	  pfCombIso2  = probe->chHadIso + TMath::Max(probe->neuHadIso + probe->gammaIso - 
						     0.5*(probe->puIso),Double_t(0));
	  d02         = probe->d0;
	  dz2         = probe->dz;
	  muNchi22    = probe->muNchi2;
	  nPixHits2   = probe->nPixHits;
	  nTkLayers2  = probe->nTkLayers;
	  nMatch2     = probe->nMatchStn;
	  nValidHits2 = probe->nValidHits;
	  typeBits2   = probe->typeBits;
	  q2 = probe->q;

	  // determine event category
	  if(passMuonID(probe)) {
	    if(isMuonTriggerObj(triggerMenu, probe->hltMatchBits, kFALSE)) {
	      icat=eMuMu2HLT;
	    }
	    else if(isMuonTriggerObj(triggerMenu, probe->hltMatchBits, kTRUE)) {
	      icat=eMuMu1HLT1L1;
	  }
	    else {
	      icat=eMuMu1HLT;
	    }
	  }
	  else if(probe->typeBits & baconhep::EMuType::kGlobal) { icat=eMuMuNoSel; }
	  else if(probe->typeBits & baconhep::EMuType::kStandalone) { icat=eMuSta; }
	  else if(probe->nTkLayers>=6 && probe->nPixHits>=1)        { icat=eMuTrk; }
	}
	
	if(q1 == q2)         continue;  // opposite charge requirement
	    
	// mass window
	TLorentzVector vDilep = vTag + vProbe;
	if((vDilep.M()<MASS_LOW) || (vDilep.M()>MASS_HIGH)) continue;
	
	if(icat==0) continue;
	
	/******** We have a Z candidate! HURRAY! ********/
	nsel+=weight;
	nselvar+=weight*weight;
	
	// Perform matching of dileptons to GEN leptons from Z decay

	Int_t glepq1=-99;
	Int_t glepq2=-99;
	TLorentzVector *gvec=new TLorentzVector(0,0,0,0);
	TLorentzVector *glep1=new TLorentzVector(0,0,0,0);
	TLorentzVector *glep2=new TLorentzVector(0,0,0,0);
	TLorentzVector *gph=new TLorentzVector(0,0,0,0);
	Bool_t hasGenMatch = kFALSE;
	if(isSignal && hasGen) {
	  toolbox::fillGen(genPartArr, BOSON_ID, gvec, glep1, glep2,&glepq1,&glepq2,1);
	  
	  Bool_t match1 = ( ((glep1) && toolbox::deltaR(vTag.Eta(), vTag.Phi(), glep1->Eta(), glep1->Phi())<0.5) ||
			    ((glep2) && toolbox::deltaR(vTag.Eta(), vTag.Phi(), glep2->Eta(), glep2->Phi())<0.5) );
	  
	  Bool_t match2 = ( ((glep1) && toolbox::deltaR(vProbe.Eta(), vProbe.Phi(), glep1->Eta(), glep1->Phi())<0.5) ||
			    ((glep2) && toolbox::deltaR(vProbe.Eta(), vProbe.Phi(), glep2->Eta(), glep2->Phi())<0.5) );

	  if(match1 && match2) {
	    hasGenMatch = kTRUE;
	    if (gvec!=0) {
	      genV=new TLorentzVector(0,0,0,0);
	      genV->SetPtEtaPhiM(gvec->Pt(), gvec->Eta(), gvec->Phi(), gvec->M());
	      genVPt   = gvec->Pt();
	      genVPhi  = gvec->Phi();
	      genVy    = gvec->Rapidity();
	      genVMass = gvec->M();
	    }
	    else {
	      TLorentzVector tvec=*glep1+*glep2;
	      genV=new TLorentzVector(0,0,0,0);
	      genV->SetPtEtaPhiM(tvec.Pt(), tvec.Eta(), tvec.Phi(), tvec.M());
	      genVPt   = tvec.Pt();
	      genVPhi  = tvec.Phi();
	      genVy    = tvec.Rapidity();
	      genVMass = tvec.M();
	    }
	    delete gvec;
	    delete glep1;
	    delete glep2;
	    glep1=0; glep2=0; gvec=0;
	  }
	  else {
	    genV     = new TLorentzVector(0,0,0,0); 
	    genVPt   = -999;
	    genVPhi  = -999;
	    genVy    = -999;
	    genVMass = -999;
	  }
	}
	
	if (hasGen) {
	  id_1      = gen->id_1;
	  id_2      = gen->id_2;
	  x_1       = gen->x_1;
	  x_2       = gen->x_2;
	  xPDF_1    = gen->xPDF_1;
	  xPDF_2    = gen->xPDF_2;
	  scalePDF  = gen->scalePDF;
	  weightPDF = gen->weight;
	}
	else {
	  id_1      = -999;
	  id_2      = -999;
	  x_1       = -999;
	  x_2       = -999;
	  xPDF_1    = -999;
	  xPDF_2    = -999;
	  scalePDF  = -999;
	  weightPDF = -999;
	}
	
	//
	// Fill tree
	//
	runNum   = info->runNum;
	lumiSec  = info->lumiSec;
	evtNum   = info->evtNum;
	
	if (hasGenMatch) matchGen=1;
	else matchGen=0;
	
	category = icat;
	
	vertexArr->Clear();
	vertexBr->GetEntry(ientry);
	
	npv      = vertexArr->GetEntries();
	npu      = info->nPUmean;
	genWeight= hasGen ? gen->weight: 1.;
	PUWeight = puWeight;
	scale1fb = weight;
	scale1fbUp = weightUp;
	scale1fbDown = weightDown;
	met      = info->pfMETC;
	metPhi   = info->pfMETCphi;
	sumEt    = 0;
	tkMet    = info->trkMET;
	tkMetPhi = info->trkMETphi;
	tkSumEt  = 0;
	mvaMet   = info->mvaMET;
	mvaMetPhi = info->mvaMETphi;
	mvaSumEt = 0;
	TVector2 vZPt((vDilep.Pt())*cos(vDilep.Phi()),(vDilep.Pt())*sin(vDilep.Phi()));

        puppiMet = info->puppET;
        puppiMetPhi = info->puppETphi;
	puppiSumEt = 0;
	lep1     = &vTag;
	lep2     = &vProbe;
	dilep    = &vDilep;
	sta1        = &vTagSta;
	sta2        = &vProbeSta;
	
	TVector2 vMet((info->pfMETC)*cos(info->pfMETCphi), (info->pfMETC)*sin(info->pfMETCphi));
	TVector2 vU = -1.0*(vMet+vZPt);
	u1 = ((vDilep.Px())*(vU.Px()) + (vDilep.Py())*(vU.Py()))/(vDilep.Pt());  // u1 = (pT . u)/|pT|
	u2 = ((vDilep.Px())*(vU.Py()) - (vDilep.Py())*(vU.Px()))/(vDilep.Pt());  // u2 = (pT x u)/|pT|
	
	TVector2 vTkMet((info->trkMET)*cos(info->trkMETphi), (info->trkMET)*sin(info->trkMETphi));
	TVector2 vTkU = -1.0*(vTkMet+vZPt);
	tkU1 = ((vDilep.Px())*(vTkU.Px()) + (vDilep.Py())*(vTkU.Py()))/(vDilep.Pt());  // u1 = (pT . u)/|pT|
	tkU2 = ((vDilep.Px())*(vTkU.Py()) - (vDilep.Py())*(vTkU.Px()))/(vDilep.Pt());  // u2 = (pT x u)/|pT|
	
	TVector2 vMvaMet((info->mvaMET)*cos(info->mvaMETphi), (info->mvaMET)*sin(info->mvaMETphi));
	TVector2 vMvaU = -1.0*(vMvaMet+vZPt);
	mvaU1 = ((vDilep.Px())*(vMvaU.Px()) + (vDilep.Py())*(vMvaU.Py()))/(vDilep.Pt());  // u1 = (pT . u)/|pT|
	mvaU2 = ((vDilep.Px())*(vMvaU.Py()) - (vDilep.Py())*(vMvaU.Px()))/(vDilep.Pt());  // u2 = (pT x u)/|pT|
        
        TVector2 vPuppiMet((info->puppET)*cos(info->puppETphi), (info->puppET)*sin(info->puppETphi));
	TVector2 vPuppiU = -1.0*(vPuppiMet+vZPt);
	puppiU1 = ((vDilep.Px())*(vPuppiU.Px()) + (vDilep.Py())*(vPuppiU.Py()))/(vDilep.Pt());  // u1 = (pT . u)/|pT|
	puppiU2 = ((vDilep.Px())*(vPuppiU.Py()) - (vDilep.Py())*(vPuppiU.Px()))/(vDilep.Pt());  // u2 = (pT x u)/|pT|
	
        outTree->Fill();
	delete genV;
	genV=0, dilep=0, lep1=0, lep2=0, sta1=0, sta2=0;
      }
      delete infile;
      infile=0, eventTree=0;    
      
      cout << nsel  << " +/- " << sqrt(nselvar);
      if(!isData) cout << " per 1/fb";
      cout << endl;
    }
    outFile->Write();
    outFile->Close(); 
  }
  delete h_rw;
  delete h_rw_up;
  delete h_rw_down;
  delete f_rw;
  delete info;
  delete gen;
  delete genPartArr;
  delete muonArr;
  delete vertexArr;
    
  //--------------------------------------------------------------------------------------------------------------
  // Output
  //==============================================================================================================
   
  cout << "*" << endl;
  cout << "* SUMMARY" << endl;
  cout << "*--------------------------------------------------" << endl;
  cout << " Z -> mu mu" << endl;
  cout << "  Mass window: [" << MASS_LOW << ", " << MASS_HIGH << "]" << endl;
  cout << "  pT > " << PT_CUT << endl;
  cout << "  |eta| < " << ETA_CUT << endl;
  cout << endl;
  
  cout << endl;
  cout << "  <> Output saved in " << outputDir << "/" << endl;    
  cout << endl;  
      
  gBenchmark->Show("selectZmm"); 
}
Example #19
0
unsigned int HashTable::GetHash(TVector2 position) {
  unsigned long int x = (unsigned long int) position.X();
  unsigned long int y = (unsigned long int) position.Y();
  return ((x*_HT_P1_)^(y*_HT_P2_))%_HT_NH_;
}
HHKinFit2::HHFitObjectMET::HHFitObjectMET(TVector2 const& v,TVector2 const& vfit)
  :HHFitObject(HHLorentzVector(v.X(),v.Y(),0,sqrt(v.X()*v.X()+v.Y()*v.Y()))){
  this->setFit4Vector(HHLorentzVector(vfit.X(),vfit.Y(),0,sqrt(vfit.X()*vfit.X()+vfit.Y()*vfit.Y())));
}
Example #21
0
void selectZee(const TString conf,        // input file
               const TString outputDir,   // output directory
	       const Bool_t  doScaleCorr  // apply energy scale corrections?
) {
  gBenchmark->Start("selectZee");

  //--------------------------------------------------------------------------------------------------------------
  // Settings 
  //============================================================================================================== 

  const Double_t MASS_LOW  = 40;
  const Double_t MASS_HIGH = 200;
  const Double_t PT_CUT    = 20;
  const Double_t ETA_CUT   = 2.5;
  const Double_t ELE_MASS  = 0.000511;
  
  const Double_t ECAL_GAP_LOW  = 1.4442;
  const Double_t ECAL_GAP_HIGH = 1.566;
  
  const Double_t escaleNbins  = 6;
  const Double_t escaleEta[]  = { 0.4,     0.8,     1.2,     1.4442,  2,        2.5 };
  const Double_t escaleCorr[] = { 1.00284, 1.00479, 1.00734, 1.00851, 1.00001,  0.982898 };


  //--------------------------------------------------------------------------------------------------------------
  // Main analysis code 
  //==============================================================================================================  

  enum { eEleEle2HLT=1, eEleEle1HLT, eEleEleNoSel, eEleSC };  // event category enum
  
  vector<TString>  snamev;      // sample name (for output files)  
  vector<CSample*> samplev;     // data/MC samples

  //
  // parse .conf file
  //
  confParse(conf, snamev, samplev);
  const Bool_t hasData = (samplev[0]->fnamev.size()>0);

  // Create output directory
  gSystem->mkdir(outputDir,kTRUE);
  const TString ntupDir = outputDir + TString("/ntuples");
  gSystem->mkdir(ntupDir,kTRUE);
  
  //
  // Declare output ntuple variables
  //
  UInt_t  runNum, lumiSec, evtNum;
  UInt_t  matchGen;
  UInt_t  category;
  UInt_t  npv, npu;
  Float_t genVPt, genVPhi, genVy, genVMass;
  Float_t scale1fb;
  Float_t met, metPhi, sumEt, u1, u2;
  Int_t   q1, q2;
  LorentzVector *dilep=0, *lep1=0, *lep2=0;
  ///// electron specific /////
  Float_t trkIso1, emIso1, hadIso1, trkIso2, emIso2, hadIso2;
  Float_t pfChIso1, pfGamIso1, pfNeuIso1, pfCombIso1, pfChIso2, pfGamIso2, pfNeuIso2, pfCombIso2;
  Float_t sigieie1, hovere1, eoverp1, fbrem1, ecalE1, sigieie2, hovere2, eoverp2, fbrem2, ecalE2;
  Float_t dphi1, deta1, dphi2, deta2;
  Float_t d01, dz1, d02, dz2;
  UInt_t  isConv1, nexphits1, typeBits1, isConv2, nexphits2, typeBits2; 
  LorentzVector *sc1=0, *sc2=0;
  
  // Data structures to store info from TTrees
  mithep::TEventInfo *info  = new mithep::TEventInfo();
  mithep::TGenInfo   *gen   = new mithep::TGenInfo();
  TClonesArray *electronArr = new TClonesArray("mithep::TElectron");
  TClonesArray *scArr       = new TClonesArray("mithep::TPhoton");
  TClonesArray *pvArr       = new TClonesArray("mithep::TVertex");
  
  TFile *infile=0;
  TTree *eventTree=0;
  
  //
  // loop over samples
  //  
  for(UInt_t isam=0; isam<samplev.size(); isam++) {
    
    // Assume data sample is first sample in .conf file
    // If sample is empty (i.e. contains no ntuple files), skip to next sample
    if(isam==0 && !hasData) continue;
    
    // Assume signal sample is given name "zee"
    // If it's the signal sample, toggle flag to store GEN W kinematics
    Bool_t isSignal = (snamev[isam].CompareTo("zee",TString::kIgnoreCase)==0);  
    
    CSample* samp = samplev[isam];
  
    //
    // Set up output ntuple
    //
    TString outfilename = ntupDir + TString("/") + snamev[isam] + TString("_select.root");
    if(isam==0 && !doScaleCorr) outfilename = ntupDir + TString("/") + snamev[isam] + TString("_select.raw.root");
    TFile *outFile = new TFile(outfilename,"RECREATE"); 
    TTree *outTree = new TTree("Events","Events");

    outTree->Branch("runNum",   &runNum,   "runNum/i");     // event run number
    outTree->Branch("lumiSec",  &lumiSec,  "lumiSec/i");    // event lumi section
    outTree->Branch("evtNum",   &evtNum,   "evtNum/i");     // event number
    outTree->Branch("matchGen", &matchGen, "matchGen/i");   // event has both leptons matched to MC Z->ll
    outTree->Branch("category", &category, "category/i");   // dilepton category
    outTree->Branch("npv",      &npv,      "npv/i");        // number of primary vertices
    outTree->Branch("npu",      &npu,      "npu/i");        // number of in-time PU events (MC)
    outTree->Branch("genVPt",   &genVPt,   "genVPt/F");     // GEN boson pT (signal MC)
    outTree->Branch("genVPhi",  &genVPhi,  "genVPhi/F");    // GEN boson phi (signal MC)
    outTree->Branch("genVy",    &genVy,    "genVy/F");      // GEN boson rapidity (signal MC)
    outTree->Branch("genVMass", &genVMass, "genVMass/F");   // GEN boson mass (signal MC)
    outTree->Branch("scale1fb", &scale1fb, "scale1fb/F");   // event weight per 1/fb (MC)
    outTree->Branch("met",      &met,      "met/F");        // MET
    outTree->Branch("metPhi",   &metPhi,   "metPhi/F");     // phi(MET)
    outTree->Branch("sumEt",    &sumEt,    "sumEt/F");      // Sum ET
    outTree->Branch("u1",       &u1,       "u1/F");         // parallel component of recoil
    outTree->Branch("u2",       &u2,       "u2/F");         // perpendicular component of recoil
    outTree->Branch("q1",       &q1,       "q1/I");         // charge of tag lepton
    outTree->Branch("q2",       &q2,       "q2/I");         // charge of probe lepton
    outTree->Branch("dilep", "ROOT::Math::LorentzVector<ROOT::Math::PtEtaPhiM4D<double> >", &dilep);  // dilepton 4-vector
    outTree->Branch("lep1",  "ROOT::Math::LorentzVector<ROOT::Math::PtEtaPhiM4D<double> >", &lep1);   // tag lepton 4-vector
    outTree->Branch("lep2",  "ROOT::Math::LorentzVector<ROOT::Math::PtEtaPhiM4D<double> >", &lep2);   // probe lepton 4-vector
    ///// electron specific /////
    outTree->Branch("trkIso1",    &trkIso1,    "trkIso1/F");     // track isolation of tag lepton
    outTree->Branch("trkIso2",    &trkIso2,    "trkIso2/F");     // track isolation of probe lepton
    outTree->Branch("emIso1",     &emIso1,     "emIso1/F");      // ECAL isolation of tag lepton
    outTree->Branch("emIso2",     &emIso2,     "emIso2/F");      // ECAL isolation of probe lepton
    outTree->Branch("hadIso1",    &hadIso1,    "hadIso1/F");     // HCAL isolation of tag lepton
    outTree->Branch("hadIso2",    &hadIso2,    "hadIso2/F");     // HCAL isolation of probe lepton
    outTree->Branch("pfChIso1",   &pfChIso1,   "pfChIso1/F");    // PF charged hadron isolation of tag lepton
    outTree->Branch("pfChIso2",   &pfChIso2,   "pfChIso2/F");    // PF charged hadron isolation of probe lepton
    outTree->Branch("pfGamIso1",  &pfGamIso1,  "pfGamIso1/F");   // PF photon isolation of tag lepton
    outTree->Branch("pfGamIso2",  &pfGamIso2,  "pfGamIso2/F");   // PF photon isolation of probe lepton
    outTree->Branch("pfNeuIso1",  &pfNeuIso1,  "pfNeuIso1/F");   // PF neutral hadron isolation of tag lepton
    outTree->Branch("pfNeuIso2",  &pfNeuIso2,  "pfNeuIso2/F");   // PF neutral hadron isolation of probe lepton
    outTree->Branch("pfCombIso1", &pfCombIso1, "pfCombIso1/F");  // PF combine isolation of tag lepton
    outTree->Branch("pfCombIso2", &pfCombIso2, "pfCombIso2/F");  // PF combined isolation of probe lepton    
    outTree->Branch("sigieie1",   &sigieie1,   "sigieie1/F");    // sigma-ieta-ieta of tag
    outTree->Branch("sigieie2",   &sigieie2,   "sigieie2/F");    // sigma-ieta-ieta of probe
    outTree->Branch("hovere1",    &hovere1,    "hovere1/F");     // H/E of tag
    outTree->Branch("hovere2",    &hovere2,    "hovere2/F");     // H/E of probe
    outTree->Branch("eoverp1",    &eoverp1,    "eoverp1/F");     // E/p of tag
    outTree->Branch("eoverp2",    &eoverp2,    "eoverp2/F");     // E/p of probe	 
    outTree->Branch("fbrem1",     &fbrem1,     "fbrem1/F");      // brem fraction of tag
    outTree->Branch("fbrem2",     &fbrem2,     "fbrem2/F");      // brem fraction of probe
    outTree->Branch("dphi1",      &dphi1,      "dphi1/F");       // GSF track - ECAL dphi of tag
    outTree->Branch("dphi2",      &dphi2,      "dphi2/F");       // GSF track - ECAL dphi of probe 	
    outTree->Branch("deta1",      &deta1,      "deta1/F");       // GSF track - ECAL deta of tag
    outTree->Branch("deta2",      &deta2,      "deta2/F");       // GSF track - ECAL deta of probe
    outTree->Branch("ecalE1",     &ecalE1,     "ecalE1/F");      // ECAL energy of tag
    outTree->Branch("ecalE2",     &ecalE2,     "ecalE2/F");      // ECAL energy of probe
    outTree->Branch("d01",        &d01,        "d01/F");	 // transverse impact parameter of tag
    outTree->Branch("d02",        &d02,        "d02/F");	 // transverse impact parameter of probe	  
    outTree->Branch("dz1",        &dz1,        "dz1/F");	 // longitudinal impact parameter of tag
    outTree->Branch("dz2",        &dz2,        "dz2/F");	 // longitudinal impact parameter of probe
    outTree->Branch("isConv1",    &isConv1,    "isConv1/i");     // conversion filter flag of tag lepton
    outTree->Branch("isConv2",    &isConv2,    "isConv2/i");     // conversion filter flag of probe lepton
    outTree->Branch("nexphits1",  &nexphits1,  "nexphits1/i");   // number of missing expected inner hits of tag lepton
    outTree->Branch("nexphits2",  &nexphits2,  "nexphits2/i");   // number of missing expected inner hits of probe lepton
    outTree->Branch("typeBits1",  &typeBits1,  "typeBits1/i");   // electron type of tag lepton
    outTree->Branch("typeBits2",  &typeBits2,  "typeBits2/i");   // electron type of probe lepton
    outTree->Branch("sc1",  "ROOT::Math::LorentzVector<ROOT::Math::PtEtaPhiM4D<double> >", &sc1);   // tag Supercluster 4-vector
    outTree->Branch("sc2",  "ROOT::Math::LorentzVector<ROOT::Math::PtEtaPhiM4D<double> >", &sc2);   // probe Supercluster 4-vector 
    
    //
    // loop through files
    //
    const UInt_t nfiles = samp->fnamev.size();
    for(UInt_t ifile=0; ifile<nfiles; ifile++) {  

      // Read input file and get the TTrees
      cout << "Processing " << samp->fnamev[ifile] << " [xsec = " << samp->xsecv[ifile] << " pb] ... "; cout.flush();
      infile = new TFile(samp->fnamev[ifile]); 
      assert(infile);

      Bool_t hasJSON = kFALSE;
      mithep::RunLumiRangeMap rlrm;
      if(samp->jsonv[ifile].CompareTo("NONE")!=0) { 
        hasJSON = kTRUE;
        rlrm.AddJSONFile(samp->jsonv[ifile].Data()); 
      }
  
      eventTree = (TTree*)infile->Get("Events");
      assert(eventTree);  
      eventTree->SetBranchAddress("Info",     &info);        TBranch *infoBr     = eventTree->GetBranch("Info");
      eventTree->SetBranchAddress("Electron", &electronArr); TBranch *electronBr = eventTree->GetBranch("Electron");
      eventTree->SetBranchAddress("Photon",   &scArr);       TBranch *scBr       = eventTree->GetBranch("Photon");
      eventTree->SetBranchAddress("PV",       &pvArr);       TBranch *pvBr       = eventTree->GetBranch("PV");
      Bool_t hasGen = eventTree->GetBranchStatus("Gen");
      TBranch *genBr=0;
      if(hasGen) {
        eventTree->SetBranchAddress("Gen", &gen);
	genBr = eventTree->GetBranch("Gen");
      }
      
      // Compute MC event weight per 1/fb
      Double_t weight = 1;
      const Double_t xsec = samp->xsecv[ifile];
      if(xsec>0) weight = 1000.*xsec/(Double_t)eventTree->GetEntries();     

      //
      // loop over events
      //
      Double_t nsel=0, nselvar=0;
      for(UInt_t ientry=0; ientry<eventTree->GetEntries(); ientry++) {
        infoBr->GetEntry(ientry);
	
	if(genBr) genBr->GetEntry(ientry);
     
        // check for certified lumi (if applicable)
        mithep::RunLumiRangeMap::RunLumiPairType rl(info->runNum, info->lumiSec);      
        if(hasJSON && !rlrm.HasRunLumi(rl)) continue;  

        // trigger requirement               
        ULong64_t trigger = kHLT_Ele22_CaloIdL_CaloIsoVL;
	ULong64_t trigObj = kHLT_Ele22_CaloIdL_CaloIsoVL_EleObj;  
        if(!(info->triggerBits & trigger)) continue;      
      
        // good vertex requirement
        if(!(info->hasGoodPV)) continue;
        pvArr->Clear();
        pvBr->GetEntry(ientry);
      
        //
	// SELECTION PROCEDURE:
	//  (1) Find a good electron matched to trigger -> this will be the "tag"
	//  (2) Pair the tag with Supercluster probes which form a tag+probe mass inside 
	//      the Z window and divide candidates into exclusive categories as follows:
	//      (a) if probe SC is part of a good electron matched to trigger     -> EleEle2HLT category
	//      (b) if probe SC is part of a good electron not matched to trigger -> EleEle1HLT category
	//      (c) if probe SC is part of an electron failing selection cuts     -> EleEleNoSel category
	//      (d) if probe SC is not part of an ECAL driven electron            -> EleSC category
	//	
	electronArr->Clear();
        electronBr->GetEntry(ientry);
	scArr->Clear();
	scBr->GetEntry(ientry);
        for(Int_t i1=0; i1<electronArr->GetEntriesFast(); i1++) {
          const mithep::TElectron *tag = (mithep::TElectron*)((*electronArr)[i1]);
	  
	  // check ECAL gap
	  if(fabs(tag->scEta)>=ECAL_GAP_LOW && fabs(tag->scEta)<=ECAL_GAP_HIGH) continue;
	  
	  Double_t escale1=1;
	  if(doScaleCorr && isam==0) {
	    for(UInt_t ieta=0; ieta<escaleNbins; ieta++) {
	      if(fabs(tag->scEta)<escaleEta[ieta]) {
	        escale1 = escaleCorr[ieta];
		break;
	      }
	    }
	  }
	  
	  if(escale1*(tag->scEt) < PT_CUT)    continue;  // lepton pT cut
	  if(fabs(tag->scEta)    > ETA_CUT)   continue;  // lepton |eta| cut
	  if(!passEleID(tag,info->rhoLowEta)) continue;  // lepton selection
	  if(!(tag->hltMatchBits & trigObj))  continue;  // check trigger matching
	  
	  LorentzVector vTag(escale1*(tag->pt), tag->eta, tag->phi, ELE_MASS);
	  LorentzVector vTagSC(escale1*(tag->scEt), tag->scEta, tag->scPhi, ELE_MASS);
	
	  for(Int_t j=0; j<scArr->GetEntriesFast(); j++) {
	    const mithep::TPhoton *scProbe = (mithep::TPhoton*)((*scArr)[j]);
	    if(scProbe->scID == tag->scID) continue;
	    
	    // check ECAL gap
	    if(fabs(scProbe->scEta)>=ECAL_GAP_LOW && fabs(scProbe->scEta)<=ECAL_GAP_HIGH) continue;
	    
	   Double_t escale2=1;
	    if(doScaleCorr && isam==0) {
	      for(UInt_t ieta=0; ieta<escaleNbins; ieta++) {
	        if(fabs(scProbe->scEta)<escaleEta[ieta]) {
	          escale2 = escaleCorr[ieta];
		  break;
	        }
	      }
	    }
	    
	    if(escale2*(scProbe->pt) < PT_CUT)  continue;  // Supercluster ET cut ("pt" = corrected by PV position)
	    if(fabs(scProbe->scEta)  > ETA_CUT) continue;  // Supercluster |eta| cuts
	    
	    const mithep::TElectron *eleProbe=0;
	    Int_t iprobe=-1;
	    for(Int_t i2=0; i2<electronArr->GetEntriesFast(); i2++) {
	      if(i1==i2) continue;
	      const mithep::TElectron *ele = (mithep::TElectron*)((*electronArr)[i2]);
	      if(!(ele->typeBits & kEcalDriven)) continue;
	      if(scProbe->scID==ele->scID) { 
	        eleProbe = ele; 
		iprobe   = i2;
		break; 
	      }
            }
	    
	    LorentzVector vProbe((eleProbe) ? escale2*(eleProbe->pt) : escale2*(scProbe->pt), 
	                         (eleProbe) ? eleProbe->eta : scProbe->eta, 
				 (eleProbe) ? eleProbe->phi : scProbe->phi, 
				 ELE_MASS);
	    LorentzVector vProbeSC((eleProbe) ? escale2*(eleProbe->scEt) : escale2*(scProbe->pt), 
	                           scProbe->scEta, scProbe->scPhi, ELE_MASS);
	    
	    // mass window
	    LorentzVector vDilep = vTag + vProbe;
	    if((vDilep.M()<MASS_LOW) || (vDilep.M()>MASS_HIGH)) continue;
	    
	    // determine event category
	    UInt_t icat=0;
	    if(eleProbe) {
	      if(passEleID(eleProbe,info->rhoLowEta)) {
	        if(eleProbe->hltMatchBits & trigObj) {
		  if(i1>iprobe) continue;  // make sure we don't double count EleEle2HLT category
		  icat=eEleEle2HLT;
		
		} else {
		  icat=eEleEle1HLT;
		}	      
	      } else { 
	        icat=eEleEleNoSel;
	      } 
	    } else { 
	      icat=eEleSC;
	    }
	    if(icat==0) continue;
	    
	    
	    /******** We have a Z candidate! HURRAY! ********/
	    
	    nsel+=weight;
            nselvar+=weight*weight;
	    
	    // Perform matching of dileptons to GEN leptons from Z decay
	    Bool_t hasGenMatch = kFALSE;
	    if(isSignal) {
	      Bool_t match1 = ( (abs(gen->id_1)==EGenType::kElectron) && ((toolbox::deltaR(tag->eta, tag->phi, gen->eta_1, gen->phi_1) < 0.5)) )
	                      || ( (abs(gen->id_2)==EGenType::kElectron) && ((toolbox::deltaR(tag->eta, tag->phi, gen->eta_2, gen->phi_2) < 0.5)) );
	      Bool_t match2 = ( (abs(gen->id_1)==EGenType::kElectron) && ((toolbox::deltaR(vProbe.Eta(), vProbe.Phi(), gen->eta_1, gen->phi_1) < 0.5)) )
	                      || ( (abs(gen->id_2)==EGenType::kElectron) && ((toolbox::deltaR(vProbe.Eta(), vProbe.Phi(), gen->eta_2, gen->phi_2) < 0.5)) );
	      if(match1 && match2) hasGenMatch = kTRUE;
	    };
	    
	    //
	    // Fill tree
	    //
	    runNum   = info->runNum;
	    lumiSec  = info->lumiSec;
	    evtNum   = info->evtNum;
	    matchGen = hasGenMatch ? 1 : 0;
	    category = icat;
	    npv      = pvArr->GetEntriesFast();
	    npu      = info->nPU;
	    genVPt   = (hasGen) ? gen->vpt   : 0;
	    genVPhi  = (hasGen) ? gen->vphi  : 0;
	    genVy    = (hasGen) ? gen->vy    : 0;
	    genVMass = (hasGen) ? gen->vmass : 0;
	    scale1fb = weight;
	    met      = info->pfMET;
	    metPhi   = info->pfMETphi;
	    sumEt    = info->pfSumET;
	    
	    lep1 = &vTag;
	    q1   = tag->q;
	    
	    lep2 = &vProbe;
	    q2   = (eleProbe) ? eleProbe->q : -(tag->q);
	    
	    dilep = &vDilep;
	    
	    TVector2 vZPt((vDilep.Pt())*cos(vDilep.Phi()),(vDilep.Pt())*sin(vDilep.Phi()));        
            TVector2 vMet((info->pfMET)*cos(info->pfMETphi), (info->pfMET)*sin(info->pfMETphi));        
            TVector2 vU = -1.0*(vMet+vZPt);
            u1 = ((vDilep.Px())*(vU.Px()) + (vDilep.Py())*(vU.Py()))/(vDilep.Pt());  // u1 = (pT . u)/|pT|
            u2 = ((vDilep.Px())*(vU.Py()) - (vDilep.Py())*(vU.Px()))/(vDilep.Pt());  // u2 = (pT x u)/|pT|
	  
	    ///// electron specific /////
	    sc1        = &vTagSC;
	    trkIso1    = tag->trkIso03;
	    emIso1     = tag->emIso03;
	    hadIso1    = tag->hadIso03;
	    pfChIso1   = tag->pfChIso03;
	    pfGamIso1  = tag->pfGamIso03;	    
	    pfNeuIso1  = tag->pfNeuIso03;
	    pfCombIso1 = tag->pfChIso03 + TMath::Max(tag->pfNeuIso03 + tag->pfGamIso03 - (info->rhoLowEta)*getEffArea(tag->scEta), 0.);
	    sigieie1   = tag->sigiEtaiEta;
	    hovere1    = tag->HoverE;
	    eoverp1    = tag->EoverP;
	    fbrem1     = tag->fBrem;
	    dphi1      = tag->deltaPhiIn;
	    deta1      = tag->deltaEtaIn;
	    ecalE1     = tag->ecalE;
	    d01        = tag->d0;
	    dz1        = tag->dz;
	    isConv1    = tag->isConv;
	    nexphits1  = tag->nExpHitsInner;
	    typeBits1  = tag->typeBits;
	    
	    sc2        = &vProbeSC;
	    trkIso2    = (eleProbe) ? eleProbe->trkIso03      : -1;
	    emIso2     = (eleProbe) ? eleProbe->emIso03       : -1;
	    hadIso2    = (eleProbe) ? eleProbe->hadIso03      : -1;
	    pfChIso2   = (eleProbe) ? eleProbe->pfChIso03     : -1;
	    pfGamIso2  = (eleProbe) ? eleProbe->pfGamIso03    : -1;
	    pfNeuIso2  = (eleProbe) ? eleProbe->pfNeuIso03    : -1;
	    
	    pfCombIso2 = (eleProbe) ? 
	                 eleProbe->pfChIso03 + TMath::Max(eleProbe->pfNeuIso03 + eleProbe->pfGamIso03 - (info->rhoLowEta)*getEffArea(eleProbe->scEta), 0.) : 
			 -1;
	    
	    sigieie2   = (eleProbe) ? eleProbe->sigiEtaiEta   : scProbe->sigiEtaiEta;
	    hovere2    = (eleProbe) ? eleProbe->HoverE        : scProbe->HoverE;
	    eoverp2    = (eleProbe) ? eleProbe->EoverP        : -1;
	    fbrem2     = (eleProbe) ? eleProbe->fBrem         : -1;
	    dphi2      = (eleProbe) ? eleProbe->deltaPhiIn    : -999;
	    deta2      = (eleProbe) ? eleProbe->deltaEtaIn    : -999;
	    ecalE2     = (eleProbe) ? eleProbe->ecalE         : -999;
	    d02        = (eleProbe) ? eleProbe->d0            : -999;
	    dz2        = (eleProbe) ? eleProbe->dz            : -999;
	    isConv2    = (eleProbe) ? eleProbe->isConv        : 0;
	    nexphits2  = (eleProbe) ? eleProbe->nExpHitsInner : 0;
	    typeBits2  = (eleProbe) ? eleProbe->typeBits      : 0; 
	    
	    outTree->Fill();
	  }
        }
      }
      delete infile;
      infile=0, eventTree=0;    

      cout << nsel  << " +/- " << sqrt(nselvar);
      if(isam!=0) cout << " per 1/fb";
      cout << endl;
    }
    outFile->Write();
    outFile->Close(); 
  }
  delete info;
  delete gen;
  delete electronArr;
  delete scArr;
  delete pvArr;
  
    
  //--------------------------------------------------------------------------------------------------------------
  // Output
  //==============================================================================================================
   
  cout << "*" << endl;
  cout << "* SUMMARY" << endl;
  cout << "*--------------------------------------------------" << endl;
  cout << " Z -> e e" << endl;
  cout << "  Mass window: [" << MASS_LOW << ", " << MASS_HIGH << "]" << endl;
  cout << "  pT > " << PT_CUT << endl;
  cout << "  |eta| < " << ETA_CUT << endl;
  if(doScaleCorr)
    cout << "  *** Scale corrections applied ***" << endl;
  cout << endl;
  
  cout << endl;
  cout << "  <> Output saved in " << outputDir << "/" << endl;    
  cout << endl;  
      
  gBenchmark->Show("selectZee"); 
}
int main( int argc, char* argv[] ) {


  std::string runName = "precalib_BGO_pedestal_noSource";
  if( argc>1 ) {
    std::string runName_str(argv[1]);
    runName = runName_str;
  }

  std::string tag = "V00";
  if( argc>2 ) {
    std::string tag_str(argv[2]);
    tag = tag_str;
  }

  TString runName_tstr(runName);
  bool isOnlyRunNumber = !(runName_tstr.BeginsWith("BTF_"));


  TChain* tree = new TChain("recoTree");
  if( isOnlyRunNumber ) {
    std::cout << "-> We believe you are passing the program only the run number!" << std::endl;
    std::cout << "-> So for instance you are passing '246' for run 'BTF_246_20140501-212512_beam'" << std::endl;
    std::cout << "(if this is not the case this means TROUBLE)" << std::endl;
    std::cout << "-> Will look for runs matching run number: " << runName << std::endl;
    tree->Add(Form("analysisTrees_%s/Reco_BTF_%s_*beam.root/recoTree", tag.c_str(), runName.c_str()) );
    if( tree->GetEntries()==0 ) {
      std::cout << "WARNING! Didn't find any events matching run: " << runName << std::endl;
      std::cout << "Exiting" << std::endl;
      exit(1913);
    }
  } else {
    std::string fileName = "analysisTrees_"+tag+"/Reco_" + runName + ".root";
    TFile* file = TFile::Open(fileName.c_str());
    if( file==0 ) {
      std::cout << "ERROR! Din't find file " << fileName << std::endl;
      std::cout << "Exiting." << std::endl;
      exit(11);
    }
    tree = (TChain*)file->Get("recoTree");
  }





  UInt_t evtNumber;
  tree->SetBranchAddress( "evtNumber", &evtNumber );
  UInt_t adcData[40];
  tree->SetBranchAddress( "adcData", adcData );
  UInt_t adcBoard[40];
  tree->SetBranchAddress( "adcBoard", adcBoard );
  UInt_t adcChannel[40];
  tree->SetBranchAddress( "adcChannel", adcChannel );


  unsigned int runNumber;
  int nHodoFibersX;
  int nHodoFibersY;
  int nHodoClustersX;
  int nHodoClustersY;
  float cef3_corr[CEF3_CHANNELS];
  float bgo_corr[BGO_CHANNELS];
  float scintFront;
  float pos_hodoClustX[HODOX_CHANNELS];
  float pos_hodoClustY[HODOY_CHANNELS];
  int nFibres_hodoClustX[HODOX_CHANNELS];
  int nFibres_hodoClustY[HODOY_CHANNELS];
  float xBeam, yBeam;
  bool isSingleEle_scintFront;
  bool cef3_ok;
  bool cef3_corr_ok;
  bool bgo_ok;
  bool bgo_corr_ok;

  tree->SetBranchAddress( "runNumber", &runNumber );

  tree->SetBranchAddress( "scintFront", &scintFront );
  tree->SetBranchAddress( "cef3_corr", cef3_corr );
  tree->SetBranchAddress( "bgo_corr", bgo_corr );

  tree->SetBranchAddress( "nHodoFibersX", &nHodoFibersX );
  tree->SetBranchAddress( "nHodoFibersY", &nHodoFibersY );
  tree->SetBranchAddress( "nHodoClustersX", &nHodoClustersX );
  tree->SetBranchAddress( "pos_hodoClustX", pos_hodoClustX );
  tree->SetBranchAddress( "nFibres_hodoClustX", nFibres_hodoClustX );
  tree->SetBranchAddress( "nHodoClustersY", &nHodoClustersY );
  tree->SetBranchAddress( "pos_hodoClustY", pos_hodoClustY );
  tree->SetBranchAddress( "nFibres_hodoClustY", nFibres_hodoClustY );
  tree->SetBranchAddress( "scintFront", &scintFront );
  tree->SetBranchAddress( "isSingleEle_scintFront", &isSingleEle_scintFront );
  tree->SetBranchAddress( "xBeam", &xBeam );
  tree->SetBranchAddress( "yBeam", &yBeam );

  tree->SetBranchAddress( "cef3_ok", &cef3_ok );
  tree->SetBranchAddress( "cef3_corr_ok", &cef3_corr_ok );
  tree->SetBranchAddress( "bgo_ok", &bgo_ok );
  tree->SetBranchAddress( "bgo_corr_ok", &bgo_corr_ok );




  int nBins = 500;
  float xMax = 25.*3./2.;


  TH1D* h1_xPos = new TH1D("xPos", "", nBins, -xMax, xMax);
  TH1D* h1_yPos = new TH1D("yPos", "", nBins, -xMax, xMax);
  TH2D* h2_xyPos = new TH2D("xyPos", "", nBins, -xMax, xMax, nBins, -xMax, xMax);

  TH1D* h1_xPos_singleEle = new TH1D("xPos_singleEle", "", nBins, -xMax, xMax);
  TH1D* h1_yPos_singleEle = new TH1D("yPos_singleEle", "", nBins, -xMax, xMax);
  TH2D* h2_xyPos_singleEle = new TH2D("xyPos_singleEle", "", nBins, -xMax, xMax, nBins, -xMax, xMax);

  TH1D* h1_xPos_new = new TH1D("xPos_new", "", nBins, -xMax, xMax);
  TH1D* h1_yPos_new = new TH1D("yPos_new", "", nBins, -xMax, xMax);
  TH2D* h2_xyPos_new = new TH2D("xyPos_new", "", nBins, -xMax, xMax, nBins, -xMax, xMax);

  TH1D* h1_xPos_new_singleEle = new TH1D("xPos_new_singleEle", "", nBins, -xMax, xMax);
  TH1D* h1_yPos_new_singleEle = new TH1D("yPos_new_singleEle", "", nBins, -xMax, xMax);
  TH2D* h2_xyPos_new_singleEle = new TH2D("xyPos_new_singleEle", "", nBins, -xMax, xMax, nBins, -xMax, xMax);


  TH1D* h1_xPos_bgo = new TH1D("xPos_bgo", "", nBins, -xMax, xMax);
  TH1D* h1_yPos_bgo = new TH1D("yPos_bgo", "", nBins, -xMax, xMax);
  TH2D* h2_xyPos_bgo = new TH2D("xyPos_bgo", "", nBins, -xMax, xMax, nBins, -xMax, xMax);

  TH1D* h1_xPos_singleEle_bgo = new TH1D("xPos_singleEle_bgo", "", nBins, -xMax, xMax);
  TH1D* h1_yPos_singleEle_bgo = new TH1D("yPos_singleEle_bgo", "", nBins, -xMax, xMax);
  TH2D* h2_xyPos_singleEle_bgo = new TH2D("xyPos_singleEle_bgo", "", nBins, -xMax, xMax, nBins, -xMax, xMax);

  TH1D* h1_xPos_hodo = new TH1D("xPos_hodo", "", nBins, -xMax, xMax);
  TH1D* h1_yPos_hodo = new TH1D("yPos_hodo", "", nBins, -xMax, xMax);
  TH2D* h2_xyPos_hodo = new TH2D("xyPos_hodo", "", nBins, -xMax, xMax, nBins, -xMax, xMax);

  TH1D* h1_xPos_singleEle_hodo = new TH1D("xPos_singleEle_hodo", "", nBins, -xMax, xMax);
  TH1D* h1_yPos_singleEle_hodo = new TH1D("yPos_singleEle_hodo", "", nBins, -xMax, xMax);
  TH2D* h2_xyPos_singleEle_hodo = new TH2D("xyPos_singleEle_hodo", "", nBins, -xMax, xMax, nBins, -xMax, xMax);

  TH1D* h1_xPos_singleEle_hodoClust = new TH1D("xPos_singleEle_hodoClust", "", nBins, -xMax, xMax);
  TH1D* h1_yPos_singleEle_hodoClust = new TH1D("yPos_singleEle_hodoClust", "", nBins, -xMax, xMax);
  TH2D* h2_xyPos_singleEle_hodoClust = new TH2D("xyPos_singleEle_hodoClust", "", nBins, -xMax, xMax, nBins, -xMax, xMax);

  TH1D* h1_xPos_calo = new TH1D("xPos_calo", "", nBins, -xMax, xMax);
  TH1D* h1_yPos_calo = new TH1D("yPos_calo", "", nBins, -xMax, xMax);
  TH2D* h2_xyPos_calo = new TH2D("xyPos_calo", "", nBins, -xMax, xMax, nBins, -xMax, xMax);

  TH1D* h1_xPos_singleEle_calo = new TH1D("xPos_singleEle_calo", "", nBins, -xMax, xMax);
  TH1D* h1_yPos_singleEle_calo = new TH1D("yPos_singleEle_calo", "", nBins, -xMax, xMax);
  TH2D* h2_xyPos_singleEle_calo = new TH2D("xyPos_singleEle_calo", "", nBins, -xMax, xMax, nBins, -xMax, xMax);

  TH1D* h1_xPos_calo_vs_hodo = new TH1D("xPos_calo_vs_hodo", "", nBins, -xMax, xMax);
  TH1D* h1_yPos_calo_vs_hodo = new TH1D("yPos_calo_vs_hodo", "", nBins, -xMax, xMax);

  TH1D* h1_xPos_calo_vs_beam = new TH1D("xPos_calo_vs_beam", "", nBins, -xMax, xMax);
  TH1D* h1_yPos_calo_vs_beam = new TH1D("yPos_calo_vs_beam", "", nBins, -xMax, xMax);

  TH1D* h1_xPos_calo_vs_hodo_singleElectron = new TH1D("xPos_calo_vs_hodo_singleElectron", "", nBins, -xMax, xMax);
  TH1D* h1_yPos_calo_vs_hodo_singleElectron = new TH1D("yPos_calo_vs_hodo_singleElectron", "", nBins, -xMax, xMax);

  TH1D* h1_xPos_calo_vs_beam_singleElectron = new TH1D("xPos_calo_vs_beam_singleElectron", "", nBins, -xMax, xMax);
  TH1D* h1_yPos_calo_vs_beam_singleElectron = new TH1D("yPos_calo_vs_beam_singleElectron", "", nBins, -xMax, xMax);

  TH1D* h1_xPos_calo_vs_hodo_singleElectron_HR = new TH1D("xPos_calo_vs_hodo_singleElectron_HR", "", nBins, -xMax, xMax);
  TH1D* h1_yPos_calo_vs_hodo_singleElectron_HR = new TH1D("yPos_calo_vs_hodo_singleElectron_HR", "", nBins, -xMax, xMax);

  TH1D* h1_xPos_calo_vs_beam_singleElectron_HR = new TH1D("xPos_calo_vs_beam_singleElectron_HR", "", nBins, -xMax, xMax);
  TH1D* h1_yPos_calo_vs_beam_singleElectron_HR = new TH1D("yPos_calo_vs_beam_singleElectron_HR", "", nBins, -xMax, xMax);


  TH2D* h2_correlation_cef3_hodo_xPos = new TH2D("correlation_cef3_hodo_xPos", "", 100, -12.5, 12.5,  100, -12.5, 12.5);
  TH2D* h2_correlation_cef3_hodo_yPos = new TH2D("correlation_cef3_hodo_yPos", "", 100, -12.5, 12.5,  100, -12.5, 12.5);

  TH2D* h2_correlation_cef3_bgo_xPos = new TH2D("correlation_cef3_bgo_xPos", "", 100, -12.5, 12.5,  100, -12.5, 12.5);
  TH2D* h2_correlation_cef3_bgo_yPos = new TH2D("correlation_cef3_bgo_yPos", "", 100, -12.5, 12.5,  100, -12.5, 12.5);

  TH2D* h2_correlation_hodo_bgo_xPos = new TH2D("correlation_hodo_bgo_xPos", "", 100, -12.5, 12.5,  100, -12.5, 12.5);
  TH2D* h2_correlation_hodo_bgo_yPos = new TH2D("correlation_hodo_bgo_yPos", "", 100, -12.5, 12.5,  100, -12.5, 12.5);


  TH2D* h2_correlation_cef3_hodo_xPos_singleEle = new TH2D("correlation_cef3_hodo_xPos_singleEle", "", 100, -12.5, 12.5,  100, -12.5, 12.5);
  TH2D* h2_correlation_cef3_hodo_yPos_singleEle = new TH2D("correlation_cef3_hodo_yPos_singleEle", "", 100, -12.5, 12.5,  100, -12.5, 12.5);

  TH2D* h2_correlation_cef3_bgo_xPos_singleEle = new TH2D("correlation_cef3_bgo_xPos_singleEle", "", 100, -12.5, 12.5,  100, -12.5, 12.5);
  TH2D* h2_correlation_cef3_bgo_yPos_singleEle = new TH2D("correlation_cef3_bgo_yPos_singleEle", "", 100, -12.5, 12.5,  100, -12.5, 12.5);

  TH2D* h2_correlation_hodo_bgo_xPos_singleEle = new TH2D("correlation_hodo_bgo_xPos_singleEle", "", 100, -12.5, 12.5,  100, -12.5, 12.5);
  TH2D* h2_correlation_hodo_bgo_yPos_singleEle = new TH2D("correlation_hodo_bgo_yPos_singleEle", "", 100, -12.5, 12.5,  100, -12.5, 12.5);



  int nentries = tree->GetEntries();


  if( isOnlyRunNumber ) {
    // modify runname in such a way that it's useful for getBeamPosition and outfile:
    runName = "BTF_" + runName + "_beam";
  }



  std::string outputdir = "PosAnTrees_"+tag;
  system( Form("mkdir -p %s", outputdir.c_str()) );
  std::string outfileName = outputdir + "/PosAn_" + runName + ".root";
  TFile* outfile = TFile::Open( outfileName.c_str(), "RECREATE" );

  TTree* outTree = new TTree("posTree","posTree");
  float xPos_calo_, yPos_calo_;
  float xPos_bgo_, yPos_bgo_;
  float xPos_new_, yPos_new_;
  float xPos_regr2D_, yPos_regr2D_;
  float r02_, r13_;

  outTree->Branch( "isSingleEle_scintFront", &isSingleEle_scintFront, "isSingleEle_scintFront/O" );
  outTree->Branch( "nHodoClustersX", &nHodoClustersX, "nHodoClustersX/I" );
  outTree->Branch( "nHodoClustersY", &nHodoClustersY, "nHodoClustersY/I" );
  outTree->Branch( "cef3_corr", cef3_corr, "cef3_corr[4]/F" );
  outTree->Branch( "r02", &r02_, "r02_/F" );
  outTree->Branch( "r13", &r13_, "r13_/F" );
  outTree->Branch( "xBeam", &xBeam, "xBeam/F" );
  outTree->Branch( "yBeam", &yBeam, "yBeam/F" );
  outTree->Branch( "xPos_bgo", &xPos_bgo_, "xPos_bgo_/F" );
  outTree->Branch( "yPos_bgo", &yPos_bgo_, "yPos_bgo_/F" );
  outTree->Branch( "xPos_calo", &xPos_calo_, "xPos_calo_/F" );
  outTree->Branch( "yPos_calo", &yPos_calo_, "yPos_calo_/F" );
  outTree->Branch( "xPos_new", &xPos_new_, "xPos_new_/F" );
  outTree->Branch( "yPos_new", &yPos_new_, "yPos_new_/F" );
  outTree->Branch( "xPos_regr2D", &xPos_regr2D_, "xPos_regr2D_/F" );
  outTree->Branch( "yPos_regr2D", &yPos_regr2D_, "yPos_regr2D_/F" );

  float diag02_calo_;
  float diag13_calo_;
  outTree->Branch( "diag02_calo", &diag02_calo_, "diag02_calo_/F" );
  outTree->Branch( "diag13_calo", &diag13_calo_, "diag13_calo_/F" );
  float diag02_new_;
  float diag13_new_;
  outTree->Branch( "diag02_new", &diag02_new_, "diag02_new_/F" );
  outTree->Branch( "diag13_new", &diag13_new_, "diag13_new_/F" );
  float diag02_beam_;
  float diag13_beam_;
  outTree->Branch( "diag02_beam", &diag02_beam_, "diag02_beam_/F" );
  outTree->Branch( "diag13_beam", &diag13_beam_, "diag13_beam_/F" );

  
  std::vector<float> xbgo, ybgo;
  for( unsigned i=0; i<BGO_CHANNELS; ++i ) {
    float x,y;
    RunHelper::getBGOCoordinates( i, x, y );
    xbgo.push_back( x );
    ybgo.push_back( y );
  }


  
  



  float cef3_regr[CEF3_CHANNELS];
  //TMVA::Reader* readerRegrX = new TMVA::Reader( "!Color:!Silent" );
  //readerRegrX->AddVariable("cef3_corr[0]/(cef3_corr[0]+cef3_corr[1]+cef3_corr[2]+cef3_corr[3])", &cef3_regr[0] );
  //readerRegrX->AddVariable("cef3_corr[1]/(cef3_corr[0]+cef3_corr[1]+cef3_corr[2]+cef3_corr[3])", &cef3_regr[1] );
  //readerRegrX->AddVariable("cef3_corr[2]/(cef3_corr[0]+cef3_corr[1]+cef3_corr[2]+cef3_corr[3])", &cef3_regr[2] );
  //readerRegrX->AddVariable("cef3_corr[3]/(cef3_corr[0]+cef3_corr[1]+cef3_corr[2]+cef3_corr[3])", &cef3_regr[3] );

  //TMVA::Reader* readerRegrY = new TMVA::Reader( "!Color:!Silent" );
  //readerRegrY->AddVariable("cef3_corr[0]/(cef3_corr[0]+cef3_corr[1]+cef3_corr[2]+cef3_corr[3])", &cef3_regr[0] );
  //readerRegrY->AddVariable("cef3_corr[1]/(cef3_corr[0]+cef3_corr[1]+cef3_corr[2]+cef3_corr[3])", &cef3_regr[1] );
  //readerRegrY->AddVariable("cef3_corr[2]/(cef3_corr[0]+cef3_corr[1]+cef3_corr[2]+cef3_corr[3])", &cef3_regr[2] );
  //readerRegrY->AddVariable("cef3_corr[3]/(cef3_corr[0]+cef3_corr[1]+cef3_corr[2]+cef3_corr[3])", &cef3_regr[3] ); // let try this trick

  //TMVA::Reader* readerRegr2D = new TMVA::Reader( "!Color:!Silent" );
  //readerRegr2D->AddVariable("cef3_corr[0]", &cef3_corr_[0] );
  //readerRegr2D->AddVariable("cef3_corr[1]", &cef3_corr_[1] );
  //readerRegr2D->AddVariable("cef3_corr[2]", &cef3_corr_[2] );
  //readerRegr2D->AddVariable("cef3_corr[3]", &cef3_corr_[3] );
  //readerRegr2D->BookMVA( "MLP", "TMVA/weights/TMVARegression_MLP.weights.xml" );


  std::vector<std::string> methodNames;
  //methodNames.push_back("BDTG");
  ////methodNames.push_back("FDA_MT");
  //methodNames.push_back("LD");
  //methodNames.push_back("MLP");
  ////methodNames.push_back("PDERS");

 
  //
  //std::cout << "-> Booking TMVA Reader" << std::endl;
  //for( unsigned i=0; i<methodNames.size(); ++i ) {
  //  readerRegrX->BookMVA( methodNames[i], Form("TMVA/weights/TMVARegression_%s.weights.xml", methodNames[i].c_str()) ); 
  //  readerRegrY->BookMVA( methodNames[i], Form("TMVA/weights/TMVARegression_%s.weights.xml", methodNames[i].c_str()) ); 
  //}


  std::vector< TH1D* > h1_xPos_regr_vs_calo;
  std::vector< TH1D* > h1_yPos_regr_vs_calo;
  std::vector< TH2D* > h2_xyPos_regr;
  std::vector< TH1D* > h1_xPos_regr_vs_calo_singleEle;
  std::vector< TH1D* > h1_yPos_regr_vs_calo_singleEle;
  std::vector< TH2D* > h2_xyPos_singleEle_regr;
  for( unsigned i=0; i<methodNames.size(); ++i ) {
    TH1D* newHistx = new TH1D( Form("xPos_regr%s_vs_calo", methodNames[i].c_str()), "", nBins, -xMax, xMax);
    h1_xPos_regr_vs_calo.push_back( newHistx );
    TH1D* newHisty = new TH1D( Form("yPos_regr%s_vs_calo", methodNames[i].c_str()), "", nBins, -xMax, xMax);
    h1_yPos_regr_vs_calo.push_back( newHisty );
    TH2D* newHistxy = new TH2D( Form("xyPos_regr%s", methodNames[i].c_str()), "", nBins, -xMax, xMax, nBins, -xMax, xMax);
    h2_xyPos_regr.push_back( newHistxy );
    TH1D* newHistx_singleEle = new TH1D( Form("xPos_regr%s_vs_calo_singleEle", methodNames[i].c_str()), "", nBins, -xMax, xMax);
    h1_xPos_regr_vs_calo_singleEle.push_back( newHistx_singleEle );
    TH1D* newHisty_singleEle = new TH1D( Form("yPos_regr%s_vs_calo_singleEle", methodNames[i].c_str()), "", nBins, -xMax, xMax);
    h1_yPos_regr_vs_calo_singleEle.push_back( newHisty_singleEle );
    TH2D* newHistxy_singleEle = new TH2D( Form("xyPos_singleEle_regr%s", methodNames[i].c_str()), "", nBins, -xMax, xMax, nBins, -xMax, xMax);
    h2_xyPos_singleEle_regr.push_back( newHistxy_singleEle );
  }


  TH2D* h2_xyPos_regr2D = new TH2D("xyPos_regr2D", "", nBins, -xMax, xMax, nBins, -xMax, xMax);
  TH2D* h2_xyPos_singleEle_regr2D = new TH2D("xyPos_singleEle_regr2D", "", nBins, -xMax, xMax, nBins, -xMax, xMax);





  for( unsigned iEntry=0; iEntry<nentries; ++iEntry ) {

    xPos_bgo_ = -999.;
    yPos_bgo_ = -999.;

    xPos_calo_ = -999.;
    yPos_calo_ = -999.;


    tree->GetEntry(iEntry);

    if( iEntry % 5000 == 0 ) std::cout << "Entry: " << iEntry << " / " << nentries << std::endl;

    if( !bgo_corr_ok ) continue;

    r02_ = cef3_corr[0]/cef3_corr[2];
    r13_ = cef3_corr[1]/cef3_corr[3];

    // FIRST GET POSITION FROM HODOSCOPE:


    float xPos_hodo = getMeanposHodo(nHodoClustersX, pos_hodoClustX);
    float yPos_hodo = getMeanposHodo(nHodoClustersY, pos_hodoClustY);



    if( xPos_hodo>-100. )
      h1_xPos_hodo->Fill(xPos_hodo);
    if( yPos_hodo>-100. )
      h1_yPos_hodo->Fill(yPos_hodo);

    if( xPos_hodo>-100. && yPos_hodo>-100. ) 
      h2_xyPos_hodo->Fill(xPos_hodo, yPos_hodo);


    if( isSingleEle_scintFront ) {

      if( xPos_hodo>-100. )
        h1_xPos_singleEle_hodo->Fill(xPos_hodo);
      if( yPos_hodo>-100. )
        h1_yPos_singleEle_hodo->Fill(yPos_hodo);

      if( xPos_hodo>-100. && yPos_hodo>-100. ) 
        h2_xyPos_singleEle_hodo->Fill(xPos_hodo, yPos_hodo);

    }



    std::vector<float> xPosW_bgo;
    std::vector<float> yPosW_bgo;

    std::vector<float> v_bgo_corr;
    for( unsigned i=0; i<BGO_CHANNELS; ++i ) v_bgo_corr.push_back(bgo_corr[i]);

    float eTot_bgo_corr = sumVector(v_bgo_corr);

    if( bgo_ok && bgo_corr_ok ) {

      //   0  1  2
      //   3     4
      //   5  6  7

      xPosW_bgo.push_back(bgo_corr[0]*xbgo[0]);
      xPosW_bgo.push_back(bgo_corr[1]*xbgo[1]);
      xPosW_bgo.push_back(bgo_corr[2]*xbgo[2]);
      xPosW_bgo.push_back(bgo_corr[3]*xbgo[3]);
      xPosW_bgo.push_back(bgo_corr[4]*xbgo[4]);
      xPosW_bgo.push_back(bgo_corr[5]*xbgo[5]);
      xPosW_bgo.push_back(bgo_corr[6]*xbgo[6]);
      xPosW_bgo.push_back(bgo_corr[7]*xbgo[7]);
      
      yPosW_bgo.push_back(bgo_corr[0]*ybgo[0]);
      yPosW_bgo.push_back(bgo_corr[1]*ybgo[1]);
      yPosW_bgo.push_back(bgo_corr[2]*ybgo[2]);
      yPosW_bgo.push_back(bgo_corr[3]*ybgo[3]);
      yPosW_bgo.push_back(bgo_corr[4]*ybgo[4]);
      yPosW_bgo.push_back(bgo_corr[5]*ybgo[5]);
      yPosW_bgo.push_back(bgo_corr[6]*ybgo[6]);
      yPosW_bgo.push_back(bgo_corr[7]*ybgo[7]);
      

      xPos_bgo_ = sumVector( xPosW_bgo )/eTot_bgo_corr;
      yPos_bgo_ = sumVector( yPosW_bgo )/eTot_bgo_corr;
      
      h1_xPos_bgo->Fill( xPos_bgo_ );
      h1_yPos_bgo->Fill( yPos_bgo_ );
      h2_xyPos_bgo->Fill( xPos_bgo_, yPos_bgo_ );

      h2_correlation_hodo_bgo_xPos->Fill( xPos_hodo, xPos_bgo_ );
      h2_correlation_hodo_bgo_yPos->Fill( yPos_hodo, yPos_bgo_ );
      
      if( isSingleEle_scintFront ) {

        h1_xPos_singleEle_bgo->Fill( xPos_bgo_ );
        h1_yPos_singleEle_bgo->Fill( yPos_bgo_ );
        h2_xyPos_singleEle_bgo->Fill( xPos_bgo_, yPos_bgo_ );

        h2_correlation_hodo_bgo_xPos_singleEle->Fill( xPos_hodo, xPos_bgo_ );
        h2_correlation_hodo_bgo_yPos_singleEle->Fill( yPos_hodo, yPos_bgo_ );

      }
      
    }  // if bgo ok



    // THEN USE CeF3 DATA:

    if( cef3_ok ) {


      std::vector<float> v_cef3_corr;
      for(unsigned i=0; i<CEF3_CHANNELS; ++i) v_cef3_corr.push_back(cef3_corr[i]);

      float eTot_corr = sumVector(v_cef3_corr);

      

      if( cef3_corr_ok ) {


        //   0      1
        //          
        //          
        //   3      2


        float position = 12. - 0.696; // using FN's infallible trigonometry

        //std::vector

        std::vector<float> xPosW;
        xPosW.push_back(cef3_corr[0]*(-position));
        xPosW.push_back(cef3_corr[1]*(+position));
        xPosW.push_back(cef3_corr[2]*(+position));
        xPosW.push_back(cef3_corr[3]*(-position));

        std::vector<float> yPosW;
        yPosW.push_back(cef3_corr[0]*(+position));
        yPosW.push_back(cef3_corr[1]*(+position));
        yPosW.push_back(cef3_corr[2]*(-position));
        yPosW.push_back(cef3_corr[3]*(-position));


        getCeF3Position( v_cef3_corr, xPos_new_, yPos_new_ );
        //diag02_new_ = xPos_new_;
        //diag13_new_ = yPos_new_;

        float pi = 3.14159;
        float theta = pi/4.; // 45 degrees 
        TVector2 vnew( xPos_new_, yPos_new_ );
        TVector2 dnew = vnew.Rotate(-theta);
        diag02_new_ = dnew.Y();
        diag13_new_ = dnew.X();


        TVector2 vBeam( xBeam, yBeam );
        TVector2 dBeam = vBeam.Rotate(-theta);
        diag02_beam_ = dBeam.Y();
        diag13_beam_ = dBeam.X();

        float xPos = sumVector(xPosW)/eTot_corr;
        float yPos = sumVector(yPosW)/eTot_corr;

        h1_xPos->Fill( xPos );
        h1_yPos->Fill( yPos );

        h2_xyPos->Fill( xPos, yPos );

        h1_xPos_new->Fill( xPos_new_ );
        h1_yPos_new->Fill( yPos_new_ );

        h2_xyPos_new->Fill( xPos_new_, yPos_new_ );


        // positioning with all 9 calorimeter channels:
        //float xPos_calo = sumVector( xPosW_bgo )/(eTot_bgo_corr + eTot_corr*0.07); // cef3 is in 0,0
        //float yPos_calo = sumVector( yPosW_bgo )/(eTot_bgo_corr + eTot_corr*0.08); // so counts only in denominator
        xPos_calo_ = sumVector( xPosW_bgo )/(eTot_bgo_corr + eTot_corr*0.06); // cef3 is in 0,0
        yPos_calo_ = sumVector( yPosW_bgo )/(eTot_bgo_corr + eTot_corr*0.10); // so counts only in denominator
        //float xPos_calo = sumVector( xPosW_bgo )/(eTot_bgo_corr + eTot_corr*0.791577); // cef3 is in 0,0
        //float yPos_calo = sumVector( yPosW_bgo )/(eTot_bgo_corr + eTot_corr*0.791577); // so counts only in denominator

        TVector2 vcalo( xPos_calo_, yPos_calo_ );
        TVector2 dcalo = vcalo.Rotate(-theta);
        diag02_calo_ = dcalo.Y();
        diag13_calo_ = dcalo.X();

        //xPos_regr2D_ = readerRegr2D->EvaluateRegression( "MLP" )[0];
        //yPos_regr2D_ = readerRegr2D->EvaluateRegression( "MLP" )[1];

        cef3_regr[0] = cef3_corr[0]/(cef3_corr[0]+cef3_corr[1]+cef3_corr[2]+cef3_corr[3]);
        cef3_regr[1] = cef3_corr[1]/(cef3_corr[0]+cef3_corr[1]+cef3_corr[2]+cef3_corr[3]);
        cef3_regr[2] = cef3_corr[2]/(cef3_corr[0]+cef3_corr[1]+cef3_corr[2]+cef3_corr[3]);
        cef3_regr[3] = cef3_corr[3]/(cef3_corr[0]+cef3_corr[1]+cef3_corr[2]+cef3_corr[3]);
  
        if( bgo_ok && bgo_corr_ok ) {

          h1_xPos_calo->Fill( xPos_calo_ );
          h1_yPos_calo->Fill( yPos_calo_ );
          h2_xyPos_calo->Fill( xPos_calo_, yPos_calo_ );

          //for( unsigned i=0; i<methodNames.size(); ++i ) {
          //  Float_t xPos_regr = (readerRegrX->EvaluateRegression( methodNames[i] ))[0];
          //  Float_t yPos_regr = (readerRegrY->EvaluateRegression( methodNames[i] ))[0];
          //  h1_xPos_regr_vs_calo[i]->Fill( xPos_regr-xPos_calo_ );
          //  h1_yPos_regr_vs_calo[i]->Fill( yPos_regr-yPos_calo_ );
          //  h2_xyPos_regr[i]->Fill( xPos_regr, yPos_regr );
          //}
          //h2_xyPos_regr2D->Fill( xPos_regr2D_, yPos_regr2D_ );

          h1_xPos_calo_vs_hodo->Fill( xPos_calo_-xPos_hodo );
          h1_yPos_calo_vs_hodo->Fill( yPos_calo_-yPos_hodo );

          h1_xPos_calo_vs_beam->Fill( xPos_calo_-xBeam );
          h1_yPos_calo_vs_beam->Fill( yPos_calo_-yBeam );

          // CORRELATIONS BETWEEN CALO AND HODO:

          h2_correlation_cef3_bgo_xPos->Fill( xPos, xPos_bgo_ );
          h2_correlation_cef3_bgo_yPos->Fill( yPos, yPos_bgo_ );

        }

        if( isSingleEle_scintFront ) {

          h1_xPos_singleEle->Fill( xPos );
          h1_yPos_singleEle->Fill( yPos );
          h2_xyPos_singleEle->Fill( xPos, yPos );

          h1_xPos_new_singleEle->Fill( xPos_new_ );
          h1_yPos_new_singleEle->Fill( yPos_new_ );
          h2_xyPos_new_singleEle->Fill( xPos_new_, yPos_new_ );

          h1_xPos_calo_vs_hodo_singleElectron->Fill( xPos_calo_-xPos_hodo );
          h1_yPos_calo_vs_hodo_singleElectron->Fill( yPos_calo_-yPos_hodo );

          h1_xPos_calo_vs_beam_singleElectron->Fill( xPos_calo_-xBeam );
          h1_yPos_calo_vs_beam_singleElectron->Fill( yPos_calo_-yBeam );

          if( nHodoClustersX==1 && nHodoClustersY==1 && nFibres_hodoClustX[0]<=2 && nFibres_hodoClustY[0]<=2 ) {

            h1_xPos_calo_vs_hodo_singleElectron_HR->Fill( xPos_calo_-xPos_hodo );
            h1_yPos_calo_vs_hodo_singleElectron_HR->Fill( yPos_calo_-yPos_hodo );
  
            h1_xPos_calo_vs_beam_singleElectron_HR->Fill( xPos_calo_-xBeam );
            h1_yPos_calo_vs_beam_singleElectron_HR->Fill( yPos_calo_-yBeam );

          }


          h2_correlation_cef3_hodo_xPos_singleEle->Fill( xPos, xPos_hodo );
          h2_correlation_cef3_hodo_yPos_singleEle->Fill( yPos, yPos_hodo );

  
          if( bgo_ok && bgo_corr_ok ) {

            h1_xPos_singleEle_calo->Fill( xPos_calo_ );
            h1_yPos_singleEle_calo->Fill( yPos_calo_ );
            h2_xyPos_singleEle_calo->Fill( xPos_calo_, yPos_calo_ );

            //for( unsigned i=0; i<methodNames.size(); ++i ) {
            //  Float_t xPos_regr = (readerRegrX->EvaluateRegression( methodNames[i] ))[0];
            //  Float_t yPos_regr = (readerRegrY->EvaluateRegression( methodNames[i] ))[0];
            //  h1_xPos_regr_vs_calo_singleEle[i]->Fill( xPos_regr-xPos_calo_ );
            //  h1_yPos_regr_vs_calo_singleEle[i]->Fill( yPos_regr-yPos_calo_ );
            //  h2_xyPos_singleEle_regr[i]->Fill( xPos_regr, yPos_regr );
            //}

            //h2_xyPos_singleEle_regr2D->Fill( xPos_regr2D_, yPos_regr2D_ );

            h2_correlation_cef3_bgo_xPos_singleEle->Fill( xPos, xPos_bgo_ );
            h2_correlation_cef3_bgo_yPos_singleEle->Fill( yPos, yPos_bgo_ );

          }

        }

        
        outTree->Fill();


      } // if cef3_ok

    }

  }


  outfile->cd();

  outTree->Write();


  for( unsigned i=0; i<h1_xPos_regr_vs_calo.size(); ++i ) {
    h1_xPos_regr_vs_calo[i]->Write();
    h1_yPos_regr_vs_calo[i]->Write();
    h1_xPos_regr_vs_calo_singleEle[i]->Write();
    h1_yPos_regr_vs_calo_singleEle[i]->Write();
    h2_xyPos_regr[i]->Write();
    h2_xyPos_singleEle_regr[i]->Write();
  }




  h1_xPos->Write();
  h1_yPos->Write();
  h2_xyPos->Write();

  h1_xPos_singleEle->Write();
  h1_yPos_singleEle->Write();
  h2_xyPos_singleEle->Write();

  h1_xPos_new->Write();
  h1_yPos_new->Write();
  h2_xyPos_new->Write();

  h1_xPos_new_singleEle->Write();
  h1_yPos_new_singleEle->Write();
  h2_xyPos_new_singleEle->Write();

  
  
  h1_xPos_bgo->Write();
  h1_yPos_bgo->Write();
  h2_xyPos_bgo->Write();
  

  h1_xPos_hodo->Write();
  h1_yPos_hodo->Write();
  h2_xyPos_hodo->Write();

  
  h1_xPos_calo_vs_hodo->Write();
  h1_yPos_calo_vs_hodo->Write();

  h1_xPos_calo_vs_beam->Write();
  h1_yPos_calo_vs_beam->Write();
  
  h1_xPos_calo_vs_hodo_singleElectron->Write();
  h1_yPos_calo_vs_hodo_singleElectron->Write();

  h1_xPos_calo_vs_beam_singleElectron->Write();
  h1_yPos_calo_vs_beam_singleElectron->Write();
  
  h1_xPos_calo_vs_hodo_singleElectron_HR->Write();
  h1_yPos_calo_vs_hodo_singleElectron_HR->Write();

  h1_xPos_calo_vs_beam_singleElectron_HR->Write();
  h1_yPos_calo_vs_beam_singleElectron_HR->Write();
  

  std::cout << std::endl;

  

  h2_correlation_cef3_hodo_xPos->Write();
  h2_correlation_cef3_hodo_yPos->Write();

  h2_correlation_cef3_bgo_xPos->Write();
  h2_correlation_cef3_bgo_yPos->Write();

  h2_correlation_hodo_bgo_xPos->Write();
  h2_correlation_hodo_bgo_yPos->Write();

  h1_xPos_singleEle_bgo->Write();
  h1_yPos_singleEle_bgo->Write();
  h2_xyPos_singleEle_bgo->Write();
  
  h1_xPos_singleEle_hodo->Write();
  h1_yPos_singleEle_hodo->Write();
  h2_xyPos_singleEle_hodo->Write();

  h1_xPos_singleEle_hodoClust->Write();
  h1_yPos_singleEle_hodoClust->Write();
  h2_xyPos_singleEle_hodoClust->Write();

  h1_xPos_calo->Write();
  h1_yPos_calo->Write();
  h2_xyPos_calo->Write();
  
  h1_xPos_singleEle_calo->Write();
  h1_yPos_singleEle_calo->Write();
  h2_xyPos_singleEle_calo->Write();
  

  h2_correlation_cef3_hodo_xPos_singleEle->Write();
  h2_correlation_cef3_hodo_yPos_singleEle->Write();

  h2_correlation_cef3_bgo_xPos_singleEle->Write();
  h2_correlation_cef3_bgo_yPos_singleEle->Write();

  h2_correlation_hodo_bgo_xPos_singleEle->Write();
  h2_correlation_hodo_bgo_yPos_singleEle->Write();


  outfile->Close();
  std::cout << "-> Histograms saved in: " << outfile->GetName() << std::endl;


  return 0;

}
Example #23
0
void PMCSZCand::SetA(PMCSEMObj &elec1, PMCSEMObj &elec2) {

  // First we need to calculate the thrust axis
  //
  TVector2 e1(elec1.ppx(),elec1.ppy());
  TVector2 e2(elec2.ppx(),elec2.ppy());

  // Calculate the two phi angles
  double phi1=e1.Phi();
  double phi2=e2.Phi();

  // Order in phi
  if (phi1<phi2) {
    TVector2 dummy=e1;
    e1=e2;
    e2=dummy;
    double dummy2=phi1;
    phi1=phi2;
    phi2=dummy2;
  }

  // Calculate lengths as well
  double len1=e1.Mod();
  double len2=e2.Mod();

  // Good old Newton
  //
  // initial guess
  TVector2 bisector=(e1.Unit()+e2.Unit()).Unit();
  double alpha=bisector.Phi()-TMath::Pi()/2.;
  double alphaBackup=alpha;
  int nIt=0;
  // iterate
  double oldAlpha=9999.;
  while (fabs(alpha-oldAlpha)>0.000001) {
    oldAlpha=alpha;
    double f=len2*sin(phi2-oldAlpha)+len1*sin(oldAlpha-phi1);
    double fp=-len2*cos(phi2-oldAlpha)+len1*cos(oldAlpha-phi1);
    alpha=oldAlpha-f/fp;
    nIt++;
    if (nIt>1000) {
      cout<<"Newton did not converge in search for thrust axis"<<endl;
      alpha=alphaBackup;
      break;
    }
  }

  // Build unit vector
  TVector2 r;
  r.SetMagPhi(1.,alpha);
  TVector2 rPerp=r.Rotate(TMath::Pi()/2.);

  // Checks
  if (fabs(e1*rPerp-e2*rPerp)>0.001) {
    cout<<"Looks like Newton was imprecise in calculation of thrust axis: "<<e1*rPerp<<" "<<e2*rPerp<<endl;
  }

  // now we can do the projections
  TVector2 Z=e1+e2;
  _pat=Z*rPerp;
  _pal=Z*r;
}
Example #24
0
void selectWe(const TString conf,        // input file
              const TString outputDir,   // output directory
	      const Bool_t  doScaleCorr  // apply energy scale corrections?
) {
  gBenchmark->Start("selectWe");

  //--------------------------------------------------------------------------------------------------------------
  // Settings 
  //============================================================================================================== 

  const Double_t PT_CUT   = 20;
  const Double_t ETA_CUT  = 2.5;
  const Double_t ELE_MASS = 0.000511;
  
  const Double_t ECAL_GAP_LOW  = 1.4442;
  const Double_t ECAL_GAP_HIGH = 1.566;
  
  const Double_t escaleNbins  = 6;
  const Double_t escaleEta[]  = { 0.4,     0.8,     1.2,     1.4442,  2,        2.5 };
  const Double_t escaleCorr[] = { 1.00284, 1.00479, 1.00734, 1.00851, 1.00001,  0.982898 };
  //--------------------------------------------------------------------------------------------------------------
  // Main analysis code 
  //==============================================================================================================  

  vector<TString>  snamev;      // sample name (for output files)  
  vector<CSample*> samplev;     // data/MC samples

  //
  // parse .conf file
  //
  confParse(conf, snamev, samplev);
  const Bool_t hasData = (samplev[0]->fnamev.size()>0);

  // Create output directory
  gSystem->mkdir(outputDir,kTRUE);
  const TString ntupDir = outputDir + TString("/ntuples");
  gSystem->mkdir(ntupDir,kTRUE);
  
  //
  // Declare output ntuple variables
  //
  UInt_t  runNum, lumiSec, evtNum;
  UInt_t  npv, npu;
  Float_t genVPt, genVPhi, genVy, genVMass;
  Float_t genLepPt, genLepPhi;
  Float_t scale1fb;
  Float_t met, metPhi, sumEt, mt, u1, u2;
  Int_t   q;
  LorentzVector *lep=0;
  ///// electron specific /////
  Float_t trkIso, emIso, hadIso;
  Float_t pfChIso, pfGamIso, pfNeuIso, pfCombIso;
  Float_t sigieie, hovere, eoverp, fbrem, ecalE;
  Float_t dphi, deta;
  Float_t d0, dz;
  UInt_t  isConv, nexphits, typeBits;
  LorentzVector *sc=0;
  
  // Data structures to store info from TTrees
  mithep::TEventInfo *info  = new mithep::TEventInfo();
  mithep::TGenInfo   *gen   = new mithep::TGenInfo();
  TClonesArray *electronArr = new TClonesArray("mithep::TElectron");
  TClonesArray *pvArr       = new TClonesArray("mithep::TVertex");
  
  TFile *infile=0;
  TTree *eventTree=0;
  
  //
  // loop over samples
  //  
  for(UInt_t isam=0; isam<samplev.size(); isam++) {
    
    // Assume data sample is first sample in .conf file
    // If sample is empty (i.e. contains no ntuple files), skip to next sample
    if(isam==0 && !hasData) continue;
  
    CSample* samp = samplev[isam];
  
    //
    // Set up output ntuple
    //
    TString outfilename = ntupDir + TString("/") + snamev[isam] + TString("_select.root");
    if(isam==0 && !doScaleCorr) outfilename = ntupDir + TString("/") + snamev[isam] + TString("_select.raw.root");
    TFile *outFile = new TFile(outfilename,"RECREATE"); 
    TTree *outTree = new TTree("Events","Events");

    outTree->Branch("runNum",   &runNum,   "runNum/i");     // event run number
    outTree->Branch("lumiSec",  &lumiSec,  "lumiSec/i");    // event lumi section
    outTree->Branch("evtNum",   &evtNum,   "evtNum/i");     // event number
    outTree->Branch("npv",      &npv,      "npv/i");        // number of primary vertices
    outTree->Branch("npu",      &npu,      "npu/i");        // number of in-time PU events (MC)
    outTree->Branch("genVPt",   &genVPt,   "genVPt/F");     // GEN boson pT (signal MC)
    outTree->Branch("genVPhi",  &genVPhi,  "genVPhi/F");    // GEN boson phi (signal MC)
    outTree->Branch("genVy",    &genVy,    "genVy/F");      // GEN boson rapidity (signal MC)
    outTree->Branch("genVMass", &genVMass, "genVMass/F");   // GEN boson mass (signal MC)
    outTree->Branch("genLepPt", &genLepPt, "genLepPt/F");   // GEN lepton pT (signal MC)
    outTree->Branch("genLepPhi",&genLepPhi,"genLepPhi/F");  // GEN lepton phi (signal MC)
    outTree->Branch("scale1fb", &scale1fb, "scale1fb/F");   // event weight per 1/fb (MC)
    outTree->Branch("met",      &met,      "met/F");        // MET
    outTree->Branch("metPhi",   &metPhi,   "metPhi/F");     // phi(MET)
    outTree->Branch("sumEt",    &sumEt,    "sumEt/F");      // Sum ET
    outTree->Branch("mt",       &mt,       "mt/F");         // transverse mass
    outTree->Branch("u1",       &u1,       "u1/F");         // parallel component of recoil
    outTree->Branch("u2",       &u2,       "u2/F");         // perpendicular component of recoil
    outTree->Branch("q",        &q,        "q/I");          // lepton charge
    outTree->Branch("lep", "ROOT::Math::LorentzVector<ROOT::Math::PtEtaPhiM4D<double> >", &lep);  // lepton 4-vector
    ///// electron specific /////
    outTree->Branch("trkIso",    &trkIso,    "trkIso/F");     // track isolation of tag lepton
    outTree->Branch("emIso",     &emIso,     "emIso/F");      // ECAL isolation of tag lepton
    outTree->Branch("hadIso",    &hadIso,    "hadIso/F");     // HCAL isolation of tag lepton
    outTree->Branch("pfChIso",   &pfChIso,   "pfChIso/F");    // PF charged hadron isolation of lepton
    outTree->Branch("pfGamIso",  &pfGamIso,  "pfGamIso/F");   // PF photon isolation of lepton
    outTree->Branch("pfNeuIso",  &pfNeuIso,  "pfNeuIso/F");   // PF neutral hadron isolation of lepton
    outTree->Branch("pfCombIso", &pfCombIso, "pfCombIso/F");  // PF combined isolation of electron
    outTree->Branch("sigieie",   &sigieie,   "sigieie/F");    // sigma-ieta-ieta of electron
    outTree->Branch("hovere",    &hovere,    "hovere/F");     // H/E of electron
    outTree->Branch("eoverp",    &eoverp,    "eoverp/F");     // E/p of electron
    outTree->Branch("fbrem",     &fbrem,     "fbrem/F");      // brem fraction of electron
    outTree->Branch("dphi",      &dphi,	     "dphi/F");       // GSF track - ECAL dphi of electron
    outTree->Branch("deta",      &deta,      "deta/F");       // GSF track - ECAL deta of electron
    outTree->Branch("ecalE",     &ecalE,     "ecalE/F");      // ECAL energy of electron
    outTree->Branch("d0",        &d0,        "d0/F");         // transverse impact parameter of electron
    outTree->Branch("dz",        &dz,        "dz/F");         // longitudinal impact parameter of electron
    outTree->Branch("isConv",    &isConv,    "isConv/i");     // conversion filter flag of electron
    outTree->Branch("nexphits",  &nexphits,  "nexphits/i");   // number of missing expected inner hits of electron
    outTree->Branch("typeBits",  &typeBits,  "typeBits/i");   // electron type of electron
    outTree->Branch("sc",  "ROOT::Math::LorentzVector<ROOT::Math::PtEtaPhiM4D<double> >", &sc);   // electron Supercluster 4-vector
    
    //
    // loop through files
    //
    const UInt_t nfiles = samp->fnamev.size();
    for(UInt_t ifile=0; ifile<nfiles; ifile++) {  

      // Read input file and get the TTrees
      cout << "Processing " << samp->fnamev[ifile] << " [xsec = " << samp->xsecv[ifile] << " pb] ... "; cout.flush();      
      infile = new TFile(samp->fnamev[ifile]); 
      assert(infile);

      Bool_t hasJSON = kFALSE;
      mithep::RunLumiRangeMap rlrm;
      if(samp->jsonv[ifile].CompareTo("NONE")!=0) { 
        hasJSON = kTRUE;
        rlrm.AddJSONFile(samp->jsonv[ifile].Data()); 
      }
  
      eventTree = (TTree*)infile->Get("Events");
      assert(eventTree);  
      eventTree->SetBranchAddress("Info",     &info);        TBranch *infoBr     = eventTree->GetBranch("Info");
      eventTree->SetBranchAddress("Electron", &electronArr); TBranch *electronBr = eventTree->GetBranch("Electron");
      eventTree->SetBranchAddress("PV",       &pvArr);       TBranch *pvBr       = eventTree->GetBranch("PV");
      Bool_t hasGen = eventTree->GetBranchStatus("Gen");
      TBranch *genBr=0;
      if(hasGen) {
        eventTree->SetBranchAddress("Gen", &gen);
	genBr = eventTree->GetBranch("Gen");
      }
    
      // Compute MC event weight per 1/fb
      Double_t weight = 1;
      const Double_t xsec = samp->xsecv[ifile];
      if(xsec>0) weight = 1000.*xsec/(Double_t)eventTree->GetEntries();     

      //
      // loop over events
      //
      Double_t nsel=0, nselvar=0;
      for(UInt_t ientry=0; ientry<eventTree->GetEntries(); ientry++) {
        infoBr->GetEntry(ientry);
	
	if(genBr) genBr->GetEntry(ientry);
     
        // check for certified lumi (if applicable)
        mithep::RunLumiRangeMap::RunLumiPairType rl(info->runNum, info->lumiSec);      
        if(hasJSON && !rlrm.HasRunLumi(rl)) continue;  

        // trigger requirement               
        ULong64_t trigger = kHLT_Ele22_CaloIdL_CaloIsoVL;
	ULong64_t trigObj = kHLT_Ele22_CaloIdL_CaloIsoVL_EleObj;   
        if(!(info->triggerBits & trigger)) continue;      
      
        // good vertex requirement
        if(!(info->hasGoodPV)) continue;
        pvArr->Clear();
        pvBr->GetEntry(ientry);
      
        //
	// SELECTION PROCEDURE:
	//  (1) Look for 1 good electron matched to trigger
	//  (2) Reject event if another electron is present passing looser cuts
	//
	electronArr->Clear();
        electronBr->GetEntry(ientry);
	Int_t nLooseLep=0;
	const mithep::TElectron *goodEle=0;
	Bool_t passSel=kFALSE;	
        for(Int_t i=0; i<electronArr->GetEntriesFast(); i++) {
          const mithep::TElectron *ele = (mithep::TElectron*)((*electronArr)[i]);
	  
	  // check ECAL gap
	  if(fabs(ele->scEta)>=ECAL_GAP_LOW && fabs(ele->scEta)<=ECAL_GAP_HIGH) continue;
	  
	  Double_t escale=1;
	  if(doScaleCorr && isam==0) {
	    for(UInt_t ieta=0; ieta<escaleNbins; ieta++) {
	      if(fabs(ele->scEta)<escaleEta[ieta]) {
	        escale = escaleCorr[ieta];
		break;
	      }
	    }
	  }
	  
	  if(fabs(ele->scEta)   > 2.5) continue;                // loose lepton |eta| cut
          if(escale*(ele->scEt) < 20)  continue;                // loose lepton pT cut
          if(passEleLooseID(ele,info->rhoLowEta)) nLooseLep++;  // loose lepton selection
          if(nLooseLep>1) {  // extra lepton veto
            passSel=kFALSE;
            break;
          }
          
          if(fabs(ele->scEta)   > ETA_CUT)    continue;  // lepton |eta| cut
          if(escale*(ele->scEt) < PT_CUT)     continue;  // lepton pT cut
          if(!passEleID(ele,info->rhoLowEta)) continue;  // lepton selection
          if(!(ele->hltMatchBits & trigObj))  continue;  // check trigger matching
	  
	  passSel=kTRUE;
	  goodEle = ele;  
	}
	
	if(passSel) {
	  
	  /******** We have a W candidate! HURRAY! ********/
	    
	  nsel+=weight;
          nselvar+=weight*weight;
	  
	  Double_t escale=1;
	  if(doScaleCorr && isam==0) {
	    for(UInt_t ieta=0; ieta<escaleNbins; ieta++) {
	      if(fabs(goodEle->scEta)<escaleEta[ieta]) {
	        escale = escaleCorr[ieta];
		break;
	      }
	    }
	  }
	  
	  LorentzVector vLep(escale*(goodEle->pt), goodEle->eta, goodEle->phi, ELE_MASS);  
	  LorentzVector vSC(escale*(goodEle->scEt), goodEle->scEta, goodEle->scPhi, ELE_MASS); 	  
	  
	  //
	  // Fill tree
	  //
	  runNum   = info->runNum;
	  lumiSec  = info->lumiSec;
	  evtNum   = info->evtNum;
	  npv	   = pvArr->GetEntriesFast();
	  npu	   = info->nPU;
	  genVPt   = 0;
	  genVPhi  = 0;
	  genVy    = 0;
	  genVMass = 0;
	  genLepPt = 0;
	  genLepPhi= 0;
	  u1       = 0;
	  u2       = 0;
	  if(hasGen) {
	    genVPt   = gen->vpt;
            genVPhi  = gen->vphi;
	    genVy    = gen->vy;
	    genVMass = gen->vmass;
	    TVector2 vWPt((gen->vpt)*cos(gen->vphi),(gen->vpt)*sin(gen->vphi));
	    TVector2 vLepPt(vLep.Px(),vLep.Py());      
            TVector2 vMet((info->pfMET)*cos(info->pfMETphi), (info->pfMET)*sin(info->pfMETphi));        
            TVector2 vU = -1.0*(vMet+vLepPt);
            u1 = ((vWPt.Px())*(vU.Px()) + (vWPt.Py())*(vU.Py()))/(gen->vpt);  // u1 = (pT . u)/|pT|
            u2 = ((vWPt.Px())*(vU.Py()) - (vWPt.Py())*(vU.Px()))/(gen->vpt);  // u2 = (pT x u)/|pT|
	    
	    if(abs(gen->id_1)==EGenType::kElectron) { genLepPt = gen->vpt_1; genLepPhi = gen->vphi_1; }
	    if(abs(gen->id_2)==EGenType::kElectron) { genLepPt = gen->vpt_2; genLepPhi = gen->vphi_2; }
	  }
	  scale1fb = weight;
	  met	   = info->pfMET;
	  metPhi   = info->pfMETphi;
	  sumEt    = info->pfSumET;
	  mt       = sqrt( 2.0 * (vLep.Pt()) * (info->pfMET) * (1.0-cos(toolbox::deltaPhi(vLep.Phi(),info->pfMETphi))) );
	  q        = goodEle->q;	  
	  lep      = &vLep;	  
	  
	  ///// electron specific /////
	  sc	    = &vSC;
	  trkIso    = goodEle->trkIso03;
	  emIso     = goodEle->emIso03;
	  hadIso    = goodEle->hadIso03;
	  pfChIso   = goodEle->pfChIso03;
	  pfGamIso  = goodEle->pfGamIso03;
	  pfNeuIso  = goodEle->pfNeuIso03;	
	  pfCombIso = goodEle->pfChIso03 + TMath::Max(goodEle->pfNeuIso03 + goodEle->pfGamIso03 - (info->rhoLowEta)*getEffArea(goodEle->scEta), 0.);
	  sigieie   = goodEle->sigiEtaiEta;
	  hovere    = goodEle->HoverE;
	  eoverp    = goodEle->EoverP;
	  fbrem     = goodEle->fBrem;
	  dphi      = goodEle->deltaPhiIn;
	  deta      = goodEle->deltaEtaIn;
	  d0        = goodEle->d0;
	  dz        = goodEle->dz;
	  isConv    = goodEle->isConv;
	  nexphits  = goodEle->nExpHitsInner;
	  typeBits  = goodEle->typeBits;
	   
	  outTree->Fill();
        }
      }
      delete infile;
      infile=0, eventTree=0;    

      cout << nsel  << " +/- " << sqrt(nselvar);
      if(isam!=0) cout << " per 1/fb";
      cout << endl;
    }
    outFile->Write();
    outFile->Close();
  }
  delete info;
  delete gen;
  delete electronArr;
  delete pvArr;
  
    
  //--------------------------------------------------------------------------------------------------------------
  // Output
  //==============================================================================================================
   
  cout << "*" << endl;
  cout << "* SUMMARY" << endl;
  cout << "*--------------------------------------------------" << endl;
  cout << " W -> e nu" << endl;
  cout << "  pT > " << PT_CUT << endl;
  cout << "  |eta| < " << ETA_CUT << endl;
  if(doScaleCorr)
    cout << "  *** Scale corrections applied ***" << endl;
  cout << endl;

  cout << endl;
  cout << "  <> Output saved in " << outputDir << "/" << endl;    
  cout << endl;  
      
  gBenchmark->Show("selectWe"); 
}
Example #25
0
void selectZee(const TString conf="zee.conf", // input file
               const TString outputDir=".",   // output directory
	       const Bool_t  doScaleCorr=0    // apply energy scale corrections?
) {
  gBenchmark->Start("selectZee");

  //--------------------------------------------------------------------------------------------------------------
  // Settings 
  //============================================================================================================== 

  const Double_t MASS_LOW  = 40;
  const Double_t MASS_HIGH = 200;
  const Double_t PT_CUT    = 10;
  const Double_t ETA_CUT   = 2.5;
  const Double_t ELE_MASS  = 0.000511;
  
  const Double_t ECAL_GAP_LOW  = 1.4442;
  const Double_t ECAL_GAP_HIGH = 1.566;
  
  const Double_t escaleNbins  = 6;
  const Double_t escaleEta[]  = { 0.4,     0.8,     1.2,     1.4442,  2,        2.5 };
  const Double_t escaleCorr[] = { 1.00284, 1.00479, 1.00734, 1.00851, 1.00001,  0.982898 };

  const Int_t BOSON_ID  = 23;
  const Int_t LEPTON_ID = 11;

  //--------------------------------------------------------------------------------------------------------------
  // Main analysis code 
  //==============================================================================================================  

  enum { eEleEle2HLT=1, eEleEle1HLT1L1, eEleEle1HLT, eEleEleNoSel, eEleSC };  // event category enum
  
  vector<TString>  snamev;      // sample name (for output files)  
  vector<CSample*> samplev;     // data/MC samples

  //
  // parse .conf file
  //
  confParse(conf, snamev, samplev);
  const Bool_t hasData = (samplev[0]->fnamev.size()>0);

  // Create output directory
  gSystem->mkdir(outputDir,kTRUE);
  const TString ntupDir = outputDir + TString("/ntuples");
  gSystem->mkdir(ntupDir,kTRUE);
  
  //
  // Declare output ntuple variables
  //
  UInt_t  runNum, lumiSec, evtNum;
  UInt_t  matchGen;
  UInt_t  category;
  UInt_t  npv, npu;
  UInt_t  id_1, id_2;
  Double_t x_1, x_2, xPDF_1, xPDF_2;
  Double_t scalePDF, weightPDF;
  TLorentzVector *genV=0;
  Float_t genVPt, genVPhi, genVy, genVMass;
  Float_t scale1fb;
  Float_t met, metPhi, sumEt, u1, u2;
  Float_t tkMet, tkMetPhi, tkSumEt, tkU1, tkU2;
  Int_t   q1, q2;
  TLorentzVector *dilep=0, *lep1=0, *lep2=0;
  ///// electron specific /////
  Float_t trkIso1, emIso1, hadIso1, trkIso2, emIso2, hadIso2;
  Float_t pfChIso1, pfGamIso1, pfNeuIso1, pfCombIso1, pfChIso2, pfGamIso2, pfNeuIso2, pfCombIso2;
  Float_t sigieie1, hovere1, eoverp1, fbrem1, ecalE1, sigieie2, hovere2, eoverp2, fbrem2, ecalE2;
  Float_t dphi1, deta1, dphi2, deta2;
  Float_t d01, dz1, d02, dz2;
  UInt_t  isConv1, nexphits1, typeBits1, isConv2, nexphits2, typeBits2; 
  TLorentzVector *sc1=0, *sc2=0;
  
  // Data structures to store info from TTrees
  baconhep::TEventInfo *info   = new baconhep::TEventInfo();
  baconhep::TGenEventInfo *gen = new baconhep::TGenEventInfo();
  TClonesArray *genPartArr     = new TClonesArray("baconhep::TGenParticle");
  TClonesArray *electronArr    = new TClonesArray("baconhep::TElectron");
  TClonesArray *scArr          = new TClonesArray("baconhep::TPhoton");
  TClonesArray *pvArr          = new TClonesArray("baconhep::TVertex");
  
  TFile *infile=0;
  TTree *eventTree=0;
  
  //
  // loop over samples
  //  
  for(UInt_t isam=0; isam<samplev.size(); isam++) {
    
    // Assume data sample is first sample in .conf file
    // If sample is empty (i.e. contains no ntuple files), skip to next sample
    if(isam==0 && !hasData) continue;
    
    // Assume signal sample is given name "zee" - flag to store GEN Z kinematics
    Bool_t isSignal = (snamev[isam].CompareTo("zee",TString::kIgnoreCase)==0);  
    // flag to reject Z->ee events for wrong flavor backgrounds
    Bool_t isWrongFlavor = (snamev[isam].CompareTo("zxx",TString::kIgnoreCase)==0);  
    
    CSample* samp = samplev[isam];
  
    //
    // Set up output ntuple
    //
    TString outfilename = ntupDir + TString("/") + snamev[isam] + TString("_select.root");
    if(isam==0 && !doScaleCorr) outfilename = ntupDir + TString("/") + snamev[isam] + TString("_select.raw.root");
    TFile *outFile = new TFile(outfilename,"RECREATE"); 
    TTree *outTree = new TTree("Events","Events");
    outTree->Branch("runNum",     &runNum,     "runNum/i");      // event run number
    outTree->Branch("lumiSec",    &lumiSec,    "lumiSec/i");     // event lumi section
    outTree->Branch("evtNum",     &evtNum,     "evtNum/i");      // event number
    outTree->Branch("matchGen",   &matchGen,   "matchGen/i");    // event has both leptons matched to MC Z->ll
    outTree->Branch("category",   &category,   "category/i");    // dilepton category
    outTree->Branch("id_1",       &id_1,       "id_1/i");        // PDF info -- parton ID for parton 1
    outTree->Branch("id_2",       &id_2,       "id_2/i");        // PDF info -- parton ID for parton 2
    outTree->Branch("x_1",        &x_1,        "x_1/d");         // PDF info -- x for parton 1
    outTree->Branch("x_2",        &x_2,        "x_2/d");         // PDF info -- x for parton 2
    outTree->Branch("xPDF_1",     &xPDF_1,     "xPDF_1/d");      // PDF info -- x*F for parton 1
    outTree->Branch("xPDF_2",     &xPDF_2,     "xPDF_2/d");      // PDF info -- x*F for parton 2
    outTree->Branch("scalePDF",   &scalePDF,   "scalePDF/d");    // PDF info -- energy scale of parton interaction
    outTree->Branch("weightPDF",  &weightPDF,  "weightPDF/d");   // PDF info -- PDF weight
    outTree->Branch("npv",        &npv,        "npv/i");         // number of primary vertices
    outTree->Branch("npu",        &npu,        "npu/i");         // number of in-time PU events (MC)
    outTree->Branch("genV",      "TLorentzVector",  &genV);      // GEN boson 4-vector
    outTree->Branch("genVPt",     &genVPt,     "genVPt/F");      // GEN boson pT (signal MC)
    outTree->Branch("genVPhi",    &genVPhi,    "genVPhi/F");     // GEN boson phi (signal MC)
    outTree->Branch("genVy",      &genVy,      "genVy/F");       // GEN boson rapidity (signal MC)
    outTree->Branch("genVMass",   &genVMass,   "genVMass/F");    // GEN boson mass (signal MC)
    outTree->Branch("scale1fb",   &scale1fb,   "scale1fb/F");    // event weight per 1/fb (MC)
    outTree->Branch("met",        &met,        "met/F");         // MET
    outTree->Branch("metPhi",     &metPhi,     "metPhi/F");      // phi(MET)
    outTree->Branch("sumEt",      &sumEt,      "sumEt/F");       // Sum ET
    outTree->Branch("u1",         &u1,         "u1/F");          // parallel component of recoil
    outTree->Branch("u2",         &u2,         "u2/F");          // perpendicular component of recoil
    outTree->Branch("tkMet",      &tkMet,      "tkMet/F");       // MET (track MET)
    outTree->Branch("tkMetPhi",   &tkMetPhi,   "tkMetPhi/F");    // phi(MET) (track MET)
    outTree->Branch("tkSumEt",    &tkSumEt,    "tkSumEt/F");     // Sum ET (track MET)
    outTree->Branch("tkU1",       &tkU1,       "tkU1/F");        // parallel component of recoil (track MET)
    outTree->Branch("tkU2",       &tkU2,       "tkU2/F");        // perpendicular component of recoil (track MET)
    outTree->Branch("q1",         &q1,         "q1/I");          // charge of tag lepton
    outTree->Branch("q2",         &q2,         "q2/I");          // charge of probe lepton
    outTree->Branch("dilep",      "TLorentzVector",  &dilep);    // di-lepton 4-vector
    outTree->Branch("lep1",       "TLorentzVector",  &lep1);     // tag lepton 4-vector
    outTree->Branch("lep2",       "TLorentzVector",  &lep2);     // probe lepton 4-vector
    ///// electron specific /////
    outTree->Branch("trkIso1",    &trkIso1,    "trkIso1/F");     // track isolation of tag lepton
    outTree->Branch("trkIso2",    &trkIso2,    "trkIso2/F");     // track isolation of probe lepton
    outTree->Branch("emIso1",     &emIso1,     "emIso1/F");      // ECAL isolation of tag lepton
    outTree->Branch("emIso2",     &emIso2,     "emIso2/F");      // ECAL isolation of probe lepton
    outTree->Branch("hadIso1",    &hadIso1,    "hadIso1/F");     // HCAL isolation of tag lepton
    outTree->Branch("hadIso2",    &hadIso2,    "hadIso2/F");     // HCAL isolation of probe lepton
    outTree->Branch("pfChIso1",   &pfChIso1,   "pfChIso1/F");    // PF charged hadron isolation of tag lepton
    outTree->Branch("pfChIso2",   &pfChIso2,   "pfChIso2/F");    // PF charged hadron isolation of probe lepton
    outTree->Branch("pfGamIso1",  &pfGamIso1,  "pfGamIso1/F");   // PF photon isolation of tag lepton
    outTree->Branch("pfGamIso2",  &pfGamIso2,  "pfGamIso2/F");   // PF photon isolation of probe lepton
    outTree->Branch("pfNeuIso1",  &pfNeuIso1,  "pfNeuIso1/F");   // PF neutral hadron isolation of tag lepton
    outTree->Branch("pfNeuIso2",  &pfNeuIso2,  "pfNeuIso2/F");   // PF neutral hadron isolation of probe lepton
    outTree->Branch("pfCombIso1", &pfCombIso1, "pfCombIso1/F");  // PF combine isolation of tag lepton
    outTree->Branch("pfCombIso2", &pfCombIso2, "pfCombIso2/F");  // PF combined isolation of probe lepton    
    outTree->Branch("sigieie1",   &sigieie1,   "sigieie1/F");    // sigma-ieta-ieta of tag
    outTree->Branch("sigieie2",   &sigieie2,   "sigieie2/F");    // sigma-ieta-ieta of probe
    outTree->Branch("hovere1",    &hovere1,    "hovere1/F");     // H/E of tag
    outTree->Branch("hovere2",    &hovere2,    "hovere2/F");     // H/E of probe
    outTree->Branch("eoverp1",    &eoverp1,    "eoverp1/F");     // E/p of tag
    outTree->Branch("eoverp2",    &eoverp2,    "eoverp2/F");     // E/p of probe	 
    outTree->Branch("fbrem1",     &fbrem1,     "fbrem1/F");      // brem fraction of tag
    outTree->Branch("fbrem2",     &fbrem2,     "fbrem2/F");      // brem fraction of probe
    outTree->Branch("dphi1",      &dphi1,      "dphi1/F");       // GSF track - ECAL dphi of tag
    outTree->Branch("dphi2",      &dphi2,      "dphi2/F");       // GSF track - ECAL dphi of probe 	
    outTree->Branch("deta1",      &deta1,      "deta1/F");       // GSF track - ECAL deta of tag
    outTree->Branch("deta2",      &deta2,      "deta2/F");       // GSF track - ECAL deta of probe
    outTree->Branch("ecalE1",     &ecalE1,     "ecalE1/F");      // ECAL energy of tag
    outTree->Branch("ecalE2",     &ecalE2,     "ecalE2/F");      // ECAL energy of probe
    outTree->Branch("d01",        &d01,        "d01/F");	 // transverse impact parameter of tag
    outTree->Branch("d02",        &d02,        "d02/F");	 // transverse impact parameter of probe	  
    outTree->Branch("dz1",        &dz1,        "dz1/F");	 // longitudinal impact parameter of tag
    outTree->Branch("dz2",        &dz2,        "dz2/F");	 // longitudinal impact parameter of probe
    outTree->Branch("isConv1",    &isConv1,    "isConv1/i");     // conversion filter flag of tag lepton
    outTree->Branch("isConv2",    &isConv2,    "isConv2/i");     // conversion filter flag of probe lepton
    outTree->Branch("nexphits1",  &nexphits1,  "nexphits1/i");   // number of missing expected inner hits of tag lepton
    outTree->Branch("nexphits2",  &nexphits2,  "nexphits2/i");   // number of missing expected inner hits of probe lepton
    outTree->Branch("typeBits1",  &typeBits1,  "typeBits1/i");   // electron type of tag lepton
    outTree->Branch("typeBits2",  &typeBits2,  "typeBits2/i");   // electron type of probe lepton
    outTree->Branch("sc1",       "TLorentzVector",  &sc1);       // tag supercluster 4-vector
    outTree->Branch("sc2",       "TLorentzVector",  &sc2);       // probe supercluster 4-vector

    //
    // loop through files
    //
    const UInt_t nfiles = samp->fnamev.size();
    for(UInt_t ifile=0; ifile<nfiles; ifile++) {  

      // Read input file and get the TTrees
      cout << "Processing " << samp->fnamev[ifile] << " [xsec = " << samp->xsecv[ifile] << " pb] ... " << endl; cout.flush();
      infile = TFile::Open(samp->fnamev[ifile]); 
      assert(infile);

      const baconhep::TTrigger triggerMenu("../../BaconAna/DataFormats/data/HLT_50nsGRun");
      UInt_t trigger    = triggerMenu.getTriggerBit("HLT_Ele23_WP75_Gsf_v*");
      //need to clean this up
      UInt_t trigObjL1  = 4;//triggerMenu.getTriggerObjectBit("HLT_Ele22_WP75_Gsf_v*", "hltL1sL1SingleEG20");
      UInt_t trigObjHLT = 5;//triggerMenu.getTriggerObjectBit("HLT_Ele23_WP75_Gsf_v*", "hltEle23WP75GsfTrackIsoFilter");

      /*      cout << endl << "Checking trigger bits: " << endl;
      cout << "HLT_Ele22_WP75_Gsf_v*         " << triggerMenu.getTriggerBit("HLT_Ele22_WP75_Gsf_v*") << endl;
      cout << "HLT_Ele23_WP75_Gsf_v*         " << triggerMenu.getTriggerBit("HLT_Ele23_WP75_Gsf_v*") << endl;
      cout << "HLT_IsoMu20_v*                " << triggerMenu.getTriggerBit("HLT_IsoMu20_v*")        << endl;

      cout << "trigObjL1     " << trigObjL1 << endl;
      cout << "trigObjHLT    " << trigObjHLT << endl;*/

      //Bool_t hasJSON = kFALSE;
      //baconhep::RunLumiRangeMap rlrm;
      //if(samp->jsonv[ifile].CompareTo("NONE")!=0) { 
      //hasJSON = kTRUE;
      //rlrm.AddJSONFile(samp->jsonv[ifile].Data()); 
      //}
  
      eventTree = (TTree*)infile->Get("Events");
      assert(eventTree);  
      eventTree->SetBranchAddress("Info",     &info);        TBranch *infoBr     = eventTree->GetBranch("Info");
      eventTree->SetBranchAddress("Electron", &electronArr); TBranch *electronBr = eventTree->GetBranch("Electron");
      eventTree->SetBranchAddress("Photon",   &scArr);       TBranch *scBr       = eventTree->GetBranch("Photon");
      Bool_t hasGen = eventTree->GetBranchStatus("GenEvtInfo");
      TBranch *genBr=0, *genPartBr=0;
      if(hasGen) {
        eventTree->SetBranchAddress("GenEvtInfo", &gen); genBr = eventTree->GetBranch("GenEvtInfo");
	eventTree->SetBranchAddress("GenParticle",&genPartArr); genPartBr = eventTree->GetBranch("GenParticle");
      }

      Bool_t hasVer = eventTree->GetBranchStatus("Vertex");
      TBranch *pvBr=0;
      if (hasVer) {
	eventTree->SetBranchAddress("Vertex", &pvArr); pvBr = eventTree->GetBranch("Vertex");
      }

      // Compute MC event weight per 1/fb
      Double_t weight = 1;
      const Double_t xsec = samp->xsecv[ifile];
      if(xsec>0) weight = 1000.*xsec/(Double_t)eventTree->GetEntries();     

      //
      // loop over events
      //
      Double_t nsel=0, nselvar=0;
      //for(UInt_t ientry=0; ientry<eventTree->GetEntries(); ientry++) {
      for(UInt_t ientry=0; ientry<1000; ientry++) {
        infoBr->GetEntry(ientry);
	
	if(hasGen) {
	  genBr->GetEntry(ientry);
	  genPartArr->Clear();
	  genPartBr->GetEntry(ientry);
	}
     
        // check for certified lumi (if applicable)
        //baconhep::RunLumiRangeMap::RunLumiPairType rl(info->runNum, info->lumiSec);      
        //if(hasJSON && !rlrm.HasRunLumi(rl)) continue;  

        // trigger requirement               
        if(!(info->triggerBits[trigger])) continue;
      
        // good vertex requirement
        if(!(info->hasGoodPV)) continue;
	if (hasVer) {
	  pvArr->Clear();
	  pvBr->GetEntry(ientry);
	}

        //
	// SELECTION PROCEDURE:
	//  (1) Find a good electron matched to trigger -> this will be the "tag"
	//  (2) Pair the tag with Supercluster probes which form a tag+probe mass inside 
	//      the Z window and divide candidates into exclusive categories as follows:
	//      (a) if probe SC is part of a good electron matched to trigger     -> EleEle2HLT category
	//      (b) if probe SC is part of a good electron not matched to trigger -> EleEle1HLT category
	//      (c) if probe SC is part of an electron failing selection cuts     -> EleEleNoSel category
	//      (d) if probe SC is not part of an ECAL driven electron            -> EleSC category
	//	
	electronArr->Clear();
        electronBr->GetEntry(ientry);
	scArr->Clear();
	scBr->GetEntry(ientry);
        for(Int_t i1=0; i1<electronArr->GetEntriesFast(); i1++) {
          const baconhep::TElectron *tag = (baconhep::TElectron*)((*electronArr)[i1]);
	  
	  // check ECAL gap
	  if(fabs(tag->scEta)>=ECAL_GAP_LOW && fabs(tag->scEta)<=ECAL_GAP_HIGH) continue;
	  
	  Double_t escale1=1;
	  if(doScaleCorr && isam==0) {
	    for(UInt_t ieta=0; ieta<escaleNbins; ieta++) {
	      if(fabs(tag->scEta)<escaleEta[ieta]) {
	        escale1 = escaleCorr[ieta];
		break;
	      }
	    }
	  }
	  if(escale1*(tag->scEt) < PT_CUT)     continue;  // lepton pT cut
	  if(fabs(tag->scEta)    > ETA_CUT)    continue;  // lepton |eta| cut
	  if(!passEleID(tag,info->rhoIso))     continue;  // lepton selection
	  if(!(tag->hltMatchBits[trigObjHLT])) continue;  // check trigger matching

	  TLorentzVector vTag;     vTag.SetPtEtaPhiM(escale1*(tag->pt),   tag->eta,   tag->phi,   ELE_MASS);
	  TLorentzVector vTagSC; vTagSC.SetPtEtaPhiM(escale1*(tag->scEt), tag->scEta, tag->scPhi, ELE_MASS);
	
	  for(Int_t j=0; j<scArr->GetEntriesFast(); j++) {
	    const baconhep::TPhoton *scProbe = (baconhep::TPhoton*)((*scArr)[j]);
	    if(scProbe->scID == tag->scID) continue;

	    // check ECAL gap
	    if(fabs(scProbe->scEta)>=ECAL_GAP_LOW && fabs(scProbe->scEta)<=ECAL_GAP_HIGH) continue;
	    
	    Double_t escale2=1;
	    if(doScaleCorr && isam==0) {
	      for(UInt_t ieta=0; ieta<escaleNbins; ieta++) {
	        if(fabs(scProbe->scEta)<escaleEta[ieta]) {
	          escale2 = escaleCorr[ieta];
		  break;
	        }
	      }
	    }
	    
	    if(escale2*(scProbe->pt) < PT_CUT)  continue;  // Supercluster ET cut ("pt" = corrected by PV position)
	    if(fabs(scProbe->scEta)  > ETA_CUT) continue;  // Supercluster |eta| cuts
	    
	    const baconhep::TElectron *eleProbe=0;
	    Int_t iprobe=-1;
	    for(Int_t i2=0; i2<electronArr->GetEntriesFast(); i2++) {
	      if(i1==i2) continue;
	      const baconhep::TElectron *ele = (baconhep::TElectron*)((*electronArr)[i2]);
	      if(!(ele->typeBits & baconhep::EEleType::kEcalDriven)) continue;
	      if(scProbe->scID==ele->scID) { 
	        eleProbe = ele; 
		iprobe   = i2;
		break; 
	      }
            }

	    TLorentzVector vProbe(0,0,0,0);
	    vProbe.SetPtEtaPhiM((eleProbe) ? escale2*(eleProbe->pt)  : escale2*(scProbe->pt),
				(eleProbe) ? eleProbe->eta : scProbe->eta,
				(eleProbe) ? eleProbe->phi : scProbe->phi,
				ELE_MASS);
	    TLorentzVector vProbeSC(0,0,0,0);
	    vProbeSC.SetPtEtaPhiM((eleProbe) ? escale2*(eleProbe->scEt)  : escale2*(scProbe->scEt),
				  scProbe->scEta, scProbe->scPhi, ELE_MASS);

	    // mass window
	    TLorentzVector vDilep = vTag + vProbe;
	    if((vDilep.M()<MASS_LOW) || (vDilep.M()>MASS_HIGH)) continue;

	    //only for looking at low pT trigger efficiencies
	    //if (toolbox::deltaR(vTag.Eta(), vProbe.Eta(), vTag.Phi(), vProbe.Phi())<0.3) continue;

	    // determine event category
	    UInt_t icat=0;
	    if(eleProbe) {
	      if(passEleID(eleProbe,info->rhoIso)) {

	        if(eleProbe->hltMatchBits[trigObjHLT]) {
		  if(i1>iprobe) continue;  // make sure we don't double count EleEle2HLT category
		  icat=eEleEle2HLT;  
		} 
		else if (eleProbe->hltMatchBits[trigObjL1]) { icat=eEleEle1HLT1L1; }
		else { icat=eEleEle1HLT; }
	      }
	      else { icat=eEleEleNoSel; } 
	    } 
	    else { icat=eEleSC; }

	    if(icat==0) continue;

	    // veto z -> ee decay for wrong flavor background samples (needed for inclusive DYToLL sample)
	    if (isWrongFlavor) {
	      TLorentzVector *vec=0, *lep1=0, *lep2=0;
	      if (fabs(toolbox::flavor(genPartArr, BOSON_ID, vec, lep1, lep2))==LEPTON_ID) continue;
	    }

	    /******** We have a Z candidate! HURRAY! ********/
	    nsel+=weight;
            nselvar+=weight*weight;

	    // Perform matching of dileptons to GEN leptons from Z decay
	    Bool_t hasGenMatch = kFALSE;
	    if(isSignal && hasGen) {
	      TLorentzVector *vec=0, *lep1=0, *lep2=0;
	      // veto wrong flavor events for signal sample
	      if (fabs(toolbox::flavor(genPartArr, BOSON_ID, vec, lep1, lep2))!=LEPTON_ID) continue;
	      Bool_t match1 = ( ((lep1) && toolbox::deltaR(tag->eta, tag->phi, lep1->Eta(), lep1->Phi())<0.3) || 
				((lep2) && toolbox::deltaR(tag->eta, tag->phi, lep2->Eta(), lep2->Phi())<0.3) );

	      Bool_t match2 = ( ((lep1) && toolbox::deltaR(vProbe.Eta(), vProbe.Phi(), lep1->Eta(), lep1->Phi())<0.3) || 
				((lep2) && toolbox::deltaR(vProbe.Eta(), vProbe.Phi(), lep2->Eta(), lep2->Phi())<0.3) );
	      if(match1 && match2) {
		hasGenMatch = kTRUE;
		if (vec!=0) {
		  genV=new TLorentzVector(0,0,0,0);
		  genV->SetPtEtaPhiM(vec->Pt(), vec->Eta(), vec->Phi(), vec->M());
		  genVPt   = vec->Pt();
		  genVPhi  = vec->Phi();
		  genVy    = vec->Rapidity();
		  genVMass = vec->M();
		}
		else {
		  TLorentzVector tvec=*lep1+*lep2;
		  genV=new TLorentzVector(0,0,0,0);
		  genV->SetPtEtaPhiM(tvec.Pt(), tvec.Eta(), tvec.Phi(), tvec.M());
		  genVPt   = tvec.Pt();
		  genVPhi  = tvec.Phi();
		  genVy    = tvec.Rapidity();
		  genVMass = tvec.M();
		}
	      }
	      else {
		genV     = new TLorentzVector(0,0,0,0);
		genVPt   = -999;
		genVPhi  = -999;
		genVy    = -999;
		genVMass = -999;
	      }
	    }
	    
	    if (hasGen) {
	      id_1      = gen->id_1;
	      id_2      = gen->id_2;
	      x_1       = gen->x_1;
	      x_2       = gen->x_2;
	      xPDF_1    = gen->xPDF_1;
	      xPDF_2    = gen->xPDF_2;
	      scalePDF  = gen->scalePDF;
	      weightPDF = gen->weight;
	    }
	    else {
	      id_1      = -999;
	      id_2      = -999;
	      x_1       = -999;
	      x_2       = -999;
	      xPDF_1    = -999;
	      xPDF_2    = -999;
	      scalePDF  = -999;
	      weightPDF = -999;
	    }

	    //
	    // Fill tree
	    //
	    runNum   = info->runNum;
	    lumiSec  = info->lumiSec;
	    evtNum   = info->evtNum;

	    if (hasGenMatch) matchGen=1;
            else matchGen=0;

	    category = icat;
	    npv      = hasVer ? pvArr->GetEntriesFast() : 0;
	    npu      = info->nPU;
	    scale1fb = weight;
	    met      = info->pfMET;
	    metPhi   = info->pfMETphi;
	    sumEt    = 0;
	    tkMet    = info->trkMET;
	    tkMetPhi = info->trkMETphi;
	    tkSumEt  = 0;
	    lep1     = &vTag;
	    lep2     = &vProbe;
	    dilep    = &vDilep;
	    q1       = tag->q;
	    q2       = (eleProbe) ? eleProbe->q : -(tag->q);

	    TVector2 vZPt((vDilep.Pt())*cos(vDilep.Phi()),(vDilep.Pt())*sin(vDilep.Phi()));        
            TVector2 vMet((info->pfMET)*cos(info->pfMETphi), (info->pfMET)*sin(info->pfMETphi));        
            TVector2 vU = -1.0*(vMet+vZPt);
            u1 = ((vDilep.Px())*(vU.Px()) + (vDilep.Py())*(vU.Py()))/(vDilep.Pt());  // u1 = (pT . u)/|pT|
            u2 = ((vDilep.Px())*(vU.Py()) - (vDilep.Py())*(vU.Px()))/(vDilep.Pt());  // u2 = (pT x u)/|pT|

            TVector2 vTkMet((info->trkMET)*cos(info->trkMETphi), (info->trkMET)*sin(info->trkMETphi));        
            TVector2 vTkU = -1.0*(vTkMet+vZPt);
            tkU1 = ((vDilep.Px())*(vTkU.Px()) + (vDilep.Py())*(vTkU.Py()))/(vDilep.Pt());  // u1 = (pT . u)/|pT|
            tkU2 = ((vDilep.Px())*(vTkU.Py()) - (vDilep.Py())*(vTkU.Px()))/(vDilep.Pt());  // u2 = (pT x u)/|pT|
	  
	    ///// electron specific ///// 
	    sc1        = &vTagSC;
	    trkIso1    = tag->trkIso;
	    emIso1     = tag->ecalIso;
	    hadIso1    = tag->hcalIso;
	    pfChIso1   = tag->chHadIso;
	    pfGamIso1  = tag->gammaIso;	    
	    pfNeuIso1  = tag->neuHadIso;
	    pfCombIso1 = tag->chHadIso + TMath::Max(tag->neuHadIso + tag->gammaIso - 
						    (info->rhoIso)*getEffArea(tag->scEta), 0.);
	    sigieie1   = tag->sieie;
	    hovere1    = tag->hovere;
	    eoverp1    = tag->eoverp;
	    fbrem1     = tag->fbrem;
	    dphi1      = tag->dPhiIn;
	    deta1      = tag->dEtaIn;
	    ecalE1     = tag->ecalEnergy;
	    d01        = tag->d0;
	    dz1        = tag->dz;
	    isConv1    = tag->isConv;
	    nexphits1  = tag->nMissingHits;
	    typeBits1  = tag->typeBits;

	    sc2        = &vProbeSC;
	    trkIso2    = (eleProbe) ? eleProbe->trkIso        : -1;
	    emIso2     = (eleProbe) ? eleProbe->ecalIso       : -1;
	    hadIso2    = (eleProbe) ? eleProbe->hcalIso       : -1;
	    pfChIso2   = (eleProbe) ? eleProbe->chHadIso      : -1;
	    pfGamIso2  = (eleProbe) ? eleProbe->gammaIso      : -1;
	    pfNeuIso2  = (eleProbe) ? eleProbe->neuHadIso     : -1;	    
	    pfCombIso2 = (eleProbe) ? 
	      eleProbe->chHadIso + TMath::Max(eleProbe->neuHadIso + eleProbe->gammaIso - 
					      (info->rhoIso)*getEffArea(eleProbe->scEta), 0.) :  -1;
	    sigieie2   = (eleProbe) ? eleProbe->sieie         : scProbe->sieie;
	    hovere2    = (eleProbe) ? eleProbe->hovere        : scProbe->hovere;
	    eoverp2    = (eleProbe) ? eleProbe->eoverp        : -1;
	    fbrem2     = (eleProbe) ? eleProbe->fbrem         : -1;
	    dphi2      = (eleProbe) ? eleProbe->dPhiIn        : -999;
	    deta2      = (eleProbe) ? eleProbe->dEtaIn        : -999;
	    ecalE2     = (eleProbe) ? eleProbe->ecalEnergy    : -999;
	    d02        = (eleProbe) ? eleProbe->d0            : -999;
	    dz2        = (eleProbe) ? eleProbe->dz            : -999;
	    isConv2    = (eleProbe) ? eleProbe->isConv        : 0;
	    nexphits2  = (eleProbe) ? eleProbe->nMissingHits  : 0;
	    typeBits2  = (eleProbe) ? eleProbe->typeBits      : 0; 

	    outTree->Fill();
	    genV=0, dilep=0, lep1=0, lep2=0, sc1=0, sc2=0;
	  }
        }
      }
      delete infile;
      infile=0, eventTree=0;    

      cout << nsel  << " +/- " << sqrt(nselvar);
      if(isam!=0) cout << " per 1/fb";
      cout << endl;
    }
    outFile->Write();
    outFile->Close(); 
  }
  delete info;
  delete gen;
  delete electronArr;
  delete scArr;
  delete pvArr;
  
    
  //--------------------------------------------------------------------------------------------------------------
  // Output
  //==============================================================================================================
   
  cout << "*" << endl;
  cout << "* SUMMARY" << endl;
  cout << "*--------------------------------------------------" << endl;
  cout << " Z -> e e" << endl;
  cout << "  Mass window: [" << MASS_LOW << ", " << MASS_HIGH << "]" << endl;
  cout << "  pT > " << PT_CUT << endl;
  cout << "  |eta| < " << ETA_CUT << endl;
  if(doScaleCorr)
    cout << "  *** Scale corrections applied ***" << endl;
  cout << endl;
  
  cout << endl;
  cout << "  <> Output saved in " << outputDir << "/" << endl;    
  cout << endl;  
      
  gBenchmark->Show("selectZee"); 
}
matrixstack::Vector::Vector(const TVector2 &v): TVectorT<double>(2)
{
    X() = v.X();
    Y() = v.Y();
}
SimulationOutput* LightSimulator::Run(){
    
  TRandom3 randgen = TRandom3(0);

  if (debug) cout << ntoys*nrays << " light propagations to simulate" << endl;

  long counter_ray=0;

  if (output) delete output;
  output = new SimulationOutput(deposit);
    
  if (!isinsideboundaries()) return output;

  for (int nrun = 0; nrun<ntoys; nrun++){
            
    vector<Int_t> myphotons(4,0);

    for (int nray = 0; nray<nrays; nray++){

      counter_ray++;
      //	if (counter_ray%(ntoys*nrays/10)==0) cout << "Done " << counter_ray << " rays" << endl;

      Double_t phi = randgen.Uniform(-Pi(),Pi());
      Double_t costheta = randgen.Uniform(-1,1);
      TVector3 dir; dir.SetMagThetaPhi(1,ACos(costheta),phi);
      LightRay lr(deposit.position,dir);

      bool matched = false;
      Int_t matchx = 999;
      Int_t matchy = 999;
      Int_t firstmatchx = 999;
      Int_t firstmatchy = 999;

      Int_t index=0;
      MatchObject m;
      vector<MatchObject> matches;
      while (index>=0 && index<pars.max_distance_unit_propagation && index<Max(firstmatchx,firstmatchy)){
	if (propray(lr,kNS,index,matchx,m)){
	  if (!matched) firstmatchx=matchx;
	  matched=true;
	  matches.push_back(m);
	}
	if (propray(lr,kEW,index,matchy,m)){
	  if (!matched) firstmatchy=matchy;
	  matched=true;
	  matches.push_back(m);
	}
	index++;
      }

      vector<GoodMatchObject> goodmatches=convert_matches(matches);
	
      Double_t pathxy = pars.max_distance_unit_propagation*10*pars.xtalsize;
      GoodMatchObject finalmatch;
      for (size_t i=0; i<goodmatches.size(); i++){
	Double_t path = sqrt(pow(goodmatches[i].positionx-lr.origin.x(),2)+pow(goodmatches[i].positiony-lr.origin.y(),2));
	if (path<pathxy) {pathxy=path; finalmatch=goodmatches[i];}
      }
      if (pathxy>1e4){
	if (debug) cout << "LOOPER" << endl;
	continue;
      }

      Int_t channel = findchannel(finalmatch.x,finalmatch.y)-1;
     
      if (debug) cout << finalmatch.x << " " << finalmatch.y << " " << pathxy << " " << channel+1 << endl;

      Double_t path3d = pathxy/Sin(lr.dirvect.Theta());
     
      TVector3 rotated_origin_xy = lr.origin; rotated_origin_xy.SetZ(0);
      TVector3 rotated_impact = TVector3(finalmatch.positionx,finalmatch.positiony,0);
      TRotation r;
      r.RotateZ(-Pi()/4);
      rotated_origin_xy = r*rotated_origin_xy;
      rotated_impact = r*rotated_impact;

      Int_t nx = 0;
      Int_t ny = 0;
      Int_t nz = 0;
      {
	Int_t sx = finalmatch.x+finalmatch.y;
	if (sx==0) nx=0;
	else if (sx>0) nx = sx/2-1;
	else nx = TMath::Abs(sx)/2;
	Int_t dy = finalmatch.y-finalmatch.x;
	if (dy==0) ny=0;
	else if (dy>0) ny = dy/2-1;
	else ny = TMath::Abs(dy)/2;
	Float_t finalz = path3d*Cos(lr.dirvect.Theta())+deposit.position.z()-pars.xtalheight/2;
	nz = Int_t((fabs(finalz)+pars.xtalheight/2)/pars.xtalheight);
      }
      Int_t all_crossings = nx+ny+nz;

      Int_t my_paper_refl = 0;

      TVector2 difference = TVector2(fabs(rotated_origin_xy.x()-rotated_impact.x()),fabs(rotated_origin_xy.y()-rotated_impact.y()));
      if (difference.Phi()<limit_angle) my_paper_refl+=nx;
      if (Pi()/2-difference.Phi()<limit_angle) my_paper_refl+=ny;
      if (lr.dirvect.Theta()<limit_angle) my_paper_refl+=nz;

      Double_t att_absorption_point = randgen.Exp(pars.light_att_length);
      if (path3d>att_absorption_point) continue;

      Double_t prob_loss_in_reflections = pow(pars.eff_reflection_paper,my_paper_refl)*pow(pars.eff_reflection_total,all_crossings-my_paper_refl);
      if (randgen.Uniform()>prob_loss_in_reflections*pars.eff_lightcoll) continue;
	
      Double_t scintillation_delay = randgen.Exp(pars.scintillation_typ_timescale);

      Double_t arrival_time = deposit.time+path3d/pars.speed_of_light+scintillation_delay;
      if (arrival_time>pars.limit_arrival_time) continue;

      myphotons.at(channel)++;
      output->chamfer_pulseshape[channel]->Fill(arrival_time);
      output->reflections_paper->Fill(my_paper_refl);
      output->reflections_total->Fill(all_crossings-my_paper_refl);
      output->reflections_all->Fill(all_crossings);
      output->optical_path->Fill(path3d);
	
    }

    for (int i=0; i<4; i++) output->chamfer_photons[i]->Fill(myphotons[i]);

  }

  for (int i=0; i<4; i++) Normalize(output->chamfer_pulseshape[i]);
  Normalize(output->reflections_paper);
  Normalize(output->reflections_total);
  Normalize(output->reflections_all);
  Normalize(output->optical_path);

  return output;

};
Example #28
0
void selectAntiWm(const TString conf="wm.conf", // input file
              const TString outputDir="."       // output directory
) {
  gBenchmark->Start("selectAntiWm");

  //--------------------------------------------------------------------------------------------------------------
  // Settings 
  //============================================================================================================== 

  const Double_t PT_CUT    = 25;
  const Double_t ETA_CUT   = 2.4;
  const Double_t MUON_MASS = 0.105658369;

  const Double_t VETO_PT   = 10;
  const Double_t VETO_ETA  = 2.4;

  const Int_t BOSON_ID  = 24;
  const Int_t LEPTON_ID = 13;

  // load trigger menu
  const baconhep::TTrigger triggerMenu("../../BaconAna/DataFormats/data/HLT_50nsGRun");

  // load pileup reweighting file
  TFile *f_rw = TFile::Open("../Tools/pileup_weights_2015B.root", "read");
  TH1D *h_rw = (TH1D*) f_rw->Get("npv_rw");

  //--------------------------------------------------------------------------------------------------------------
  // Main analysis code 
  //==============================================================================================================  

  vector<TString>  snamev;      // sample name (for output files)  
  vector<CSample*> samplev;     // data/MC samples

  //
  // parse .conf file
  //
  confParse(conf, snamev, samplev);
  const Bool_t hasData = (samplev[0]->fnamev.size()>0);

  // Create output directory
  gSystem->mkdir(outputDir,kTRUE);
  const TString ntupDir = outputDir + TString("/ntuples");
  gSystem->mkdir(ntupDir,kTRUE);
  
  //
  // Declare output ntuple variables
  //
  UInt_t  runNum, lumiSec, evtNum;
  UInt_t  npv, npu;
  UInt_t  id_1, id_2;
  Double_t x_1, x_2, xPDF_1, xPDF_2;
  Double_t scalePDF, weightPDF;
  TLorentzVector *genV=0, *genLep=0;
  Float_t genVPt, genVPhi, genVy, genVMass;
  Float_t genLepPt, genLepPhi;
  Float_t scale1fb, puWeight;
  Float_t met, metPhi, sumEt, mt, u1, u2;
  Float_t tkMet, tkMetPhi, tkSumEt, tkMt, tkU1, tkU2;
  Float_t mvaMet, mvaMetPhi, mvaSumEt, mvaMt, mvaU1, mvaU2;
  Int_t   q;
  TLorentzVector *lep=0;
  ///// muon specific /////
  Float_t trkIso, emIso, hadIso;
  Float_t pfChIso, pfGamIso, pfNeuIso, pfCombIso;
  Float_t d0, dz;
  Float_t muNchi2;
  UInt_t nPixHits, nTkLayers, nValidHits, nMatch, typeBits;
  
  // Data structures to store info from TTrees
  baconhep::TEventInfo *info  = new baconhep::TEventInfo();
  baconhep::TGenEventInfo *gen  = new baconhep::TGenEventInfo();
  TClonesArray *genPartArr = new TClonesArray("baconhep::TGenParticle");
  TClonesArray *muonArr    = new TClonesArray("baconhep::TMuon");
  TClonesArray *vertexArr  = new TClonesArray("baconhep::TVertex");
  
  TFile *infile=0;
  TTree *eventTree=0;
  
  //
  // loop over samples
  //  
  for(UInt_t isam=0; isam<samplev.size(); isam++) {
    
    // Assume data sample is first sample in .conf file
    // If sample is empty (i.e. contains no ntuple files), skip to next sample
    Bool_t isData=kFALSE;
    if(isam==0 && !hasData) continue;
    else if (isam==0) isData=kTRUE;
    
    // Assume signal sample is given name "wm"
    Bool_t isSignal = (snamev[isam].CompareTo("wm",TString::kIgnoreCase)==0);
    // flag to reject W->mnu events when selecting wrong-flavor background events
    Bool_t isWrongFlavor = (snamev[isam].CompareTo("wx",TString::kIgnoreCase)==0);  
    
    CSample* samp = samplev[isam];
  
    //
    // Set up output ntuple
    //
    TString outfilename = ntupDir + TString("/") + snamev[isam] + TString("_select.root");
    TFile *outFile = new TFile(outfilename,"RECREATE"); 
    TTree *outTree = new TTree("Events","Events");

    outTree->Branch("runNum",     &runNum,     "runNum/i");     // event run number
    outTree->Branch("lumiSec",    &lumiSec,    "lumiSec/i");    // event lumi section
    outTree->Branch("evtNum",     &evtNum,     "evtNum/i");     // event number
    outTree->Branch("npv",        &npv,        "npv/i");        // number of primary vertices
    outTree->Branch("npu",        &npu,        "npu/i");        // number of in-time PU events (MC)
    outTree->Branch("id_1",       &id_1,       "id_1/i");       // PDF info -- parton ID for parton 1
    outTree->Branch("id_2",       &id_2,       "id_2/i");       // PDF info -- parton ID for parton 2
    outTree->Branch("x_1",        &x_1,        "x_1/d");        // PDF info -- x for parton 1
    outTree->Branch("x_2",        &x_2,        "x_2/d");        // PDF info -- x for parton 2
    outTree->Branch("xPDF_1",     &xPDF_1,     "xPDF_1/d");     // PDF info -- x*F for parton 1
    outTree->Branch("xPDF_2",     &xPDF_2,     "xPDF_2/d");     // PDF info -- x*F for parton 2
    outTree->Branch("scalePDF",   &scalePDF,   "scalePDF/d");   // PDF info -- energy scale of parton interaction
    outTree->Branch("weightPDF",  &weightPDF,  "weightPDF/d");  // PDF info -- PDF weight
    outTree->Branch("genV",       "TLorentzVector", &genV);     // GEN boson 4-vector (signal MC)
    outTree->Branch("genLep",     "TLorentzVector", &genLep);   // GEN lepton 4-vector (signal MC)
    outTree->Branch("genVPt",     &genVPt,     "genVPt/F");     // GEN boson pT (signal MC)
    outTree->Branch("genVPhi",    &genVPhi,    "genVPhi/F");    // GEN boson phi (signal MC)
    outTree->Branch("genVy",      &genVy,      "genVy/F");      // GEN boson rapidity (signal MC)
    outTree->Branch("genVMass",   &genVMass,   "genVMass/F");   // GEN boson mass (signal MC)
    outTree->Branch("genLepPt",   &genLepPt,   "genLepPt/F");   // GEN lepton pT (signal MC)
    outTree->Branch("genLepPhi",  &genLepPhi,  "genLepPhi/F");  // GEN lepton phi (signal MC)
    outTree->Branch("scale1fb",   &scale1fb,   "scale1fb/F");   // event weight per 1/fb (MC)
    outTree->Branch("puWeight",   &puWeight,   "puWeight/F");    // scale factor for pileup reweighting (MC)
    outTree->Branch("met",        &met,        "met/F");        // MET
    outTree->Branch("metPhi",     &metPhi,     "metPhi/F");     // phi(MET)
    outTree->Branch("sumEt",      &sumEt,      "sumEt/F");      // Sum ET
    outTree->Branch("mt",         &mt,         "mt/F");         // transverse mass
    outTree->Branch("u1",         &u1,         "u1/F");         // parallel component of recoil
    outTree->Branch("u2",         &u2,         "u2/F");         // perpendicular component of recoil
    outTree->Branch("tkMet",      &tkMet,      "tkMet/F");      // MET (track MET)
    outTree->Branch("tkMetPhi",   &tkMetPhi,   "tkMetPhi/F");   // phi(MET) (track MET)
    outTree->Branch("tkSumEt",    &tkSumEt,    "tkSumEt/F");    // Sum ET (track MET)
    outTree->Branch("tkMt",       &tkMt,       "tkMt/F");       // transverse mass (track MET)
    outTree->Branch("tkU1",       &tkU1,       "tkU1/F");       // parallel component of recoil (track MET)
    outTree->Branch("tkU2",       &tkU2,       "tkU2/F");       // perpendicular component of recoil (track MET)
    outTree->Branch("mvaMet",     &mvaMet,     "mvaMet/F");     // MVA MET
    outTree->Branch("mvaMetPhi",  &mvaMetPhi,  "mvaMetPhi/F");  // phi(MVA MET)
    outTree->Branch("mvaSumEt",   &mvaSumEt,   "mvaSumEt/F");   // Sum ET (MVA MET)
    outTree->Branch("mvaMt",      &mvaMt,      "mvaMt/F");      // transverse mass (MVA MET)
    outTree->Branch("mvaU1",      &mvaU1,      "mvaU1/F");      // parallel component of recoil (mva MET)
    outTree->Branch("mvaU2",      &mvaU2,      "mvaU2/F");      // perpendicular component of recoil (mva MET)
    outTree->Branch("q",          &q,          "q/I");          // lepton charge
    outTree->Branch("lep",        "TLorentzVector", &lep);      // lepton 4-vector
    ///// muon specific /////
    outTree->Branch("trkIso",     &trkIso,     "trkIso/F");     // track isolation of lepton
    outTree->Branch("emIso",      &emIso,      "emIso/F");      // ECAL isolation of lepton
    outTree->Branch("hadIso",     &hadIso,     "hadIso/F");     // HCAL isolation of lepton
    outTree->Branch("pfChIso",    &pfChIso,    "pfChIso/F");    // PF charged hadron isolation of lepton
    outTree->Branch("pfGamIso",   &pfGamIso,   "pfGamIso/F");   // PF photon isolation of lepton
    outTree->Branch("pfNeuIso",   &pfNeuIso,   "pfNeuIso/F");   // PF neutral hadron isolation of lepton
    outTree->Branch("pfCombIso",  &pfCombIso,  "pfCombIso/F");  // PF combined isolation of lepton
    outTree->Branch("d0",         &d0,         "d0/F");         // transverse impact parameter of lepton
    outTree->Branch("dz",         &dz,         "dz/F");         // longitudinal impact parameter of lepton
    outTree->Branch("muNchi2",    &muNchi2,    "muNchi2/F");    // muon fit normalized chi^2 of lepton
    outTree->Branch("nPixHits",   &nPixHits,   "nPixHits/i");   // number of pixel hits of muon
    outTree->Branch("nTkLayers",  &nTkLayers,  "nTkLayers/i");  // number of tracker layers of muon
    outTree->Branch("nMatch",     &nMatch,     "nMatch/i");     // number of matched segments of muon	 
    outTree->Branch("nValidHits", &nValidHits, "nValidHits/i"); // number of valid muon hits of muon 
    outTree->Branch("typeBits",   &typeBits,   "typeBits/i");   // number of valid muon hits of muon 
    
    //
    // loop through files
    //
    const UInt_t nfiles = samp->fnamev.size();
    for(UInt_t ifile=0; ifile<nfiles; ifile++) {  

      // Read input file and get the TTrees
      cout << "Processing " << samp->fnamev[ifile] << " [xsec = " << samp->xsecv[ifile] << " pb] ... "; cout.flush();
      infile = TFile::Open(samp->fnamev[ifile]); 
      assert(infile);
      
      Bool_t hasJSON = kFALSE;
      baconhep::RunLumiRangeMap rlrm;
      if(samp->jsonv[ifile].CompareTo("NONE")!=0) { 
	hasJSON = kTRUE;
	rlrm.addJSONFile(samp->jsonv[ifile].Data()); 
      }

      eventTree = (TTree*)infile->Get("Events");
      assert(eventTree);
      eventTree->SetBranchAddress("Info", &info);    TBranch *infoBr = eventTree->GetBranch("Info");
      eventTree->SetBranchAddress("Muon", &muonArr); TBranch *muonBr = eventTree->GetBranch("Muon");
      eventTree->SetBranchAddress("PV",   &vertexArr); TBranch *vertexBr = eventTree->GetBranch("PV");
      Bool_t hasGen = eventTree->GetBranchStatus("GenEvtInfo");
      TBranch *genBr=0, *genPartBr=0;
      if(hasGen) {
        eventTree->SetBranchAddress("GenEvtInfo", &gen); genBr = eventTree->GetBranch("GenEvtInfo");
        eventTree->SetBranchAddress("GenParticle",&genPartArr); genPartBr = eventTree->GetBranch("GenParticle");
      }
    
      // Compute MC event weight per 1/fb
      const Double_t xsec = samp->xsecv[ifile];
      Double_t totalWeight=0;

      if (hasGen) {
	TH1D *hall = new TH1D("hall", "", 1,0,1);
	eventTree->Draw("0.5>>hall", "GenEvtInfo->weight");
	totalWeight=hall->Integral();
	delete hall;
	hall=0;
      }

      //
      // loop over events
      //
      Double_t nsel=0, nselvar=0;
      for(UInt_t ientry=0; ientry<eventTree->GetEntries(); ientry++) {
        infoBr->GetEntry(ientry);

	if(ientry%1000000==0) cout << "Processing event " << ientry << ". " << (double)ientry/(double)eventTree->GetEntries()*100 << " percent done with this file." << endl;

        Double_t weight=1;
        if(xsec>0 && totalWeight>0) weight = xsec/totalWeight;
	if(hasGen) {
          genPartArr->Clear();
          genBr->GetEntry(ientry);
          genPartBr->GetEntry(ientry);
	  weight*=gen->weight;
        }

        // veto w -> xv decays for signal and w -> mv for bacground samples (needed for inclusive WToLNu sample)
        if (isWrongFlavor && hasGen && fabs(toolbox::flavor(genPartArr, BOSON_ID))==LEPTON_ID) continue;
	else if (isSignal && hasGen && fabs(toolbox::flavor(genPartArr, BOSON_ID))!=LEPTON_ID) continue;
        
	// check for certified lumi (if applicable)
        baconhep::RunLumiRangeMap::RunLumiPairType rl(info->runNum, info->lumiSec);      
        if(hasJSON && !rlrm.hasRunLumi(rl)) continue;  

        // trigger requirement               
	if (!isMuonTrigger(triggerMenu, info->triggerBits)) continue;
      
        // good vertex requirement
        if(!(info->hasGoodPV)) continue;

        //
	// SELECTION PROCEDURE:
	//  (1) Look for 1 good muon matched to trigger
	//  (2) Reject event if another muon is present passing looser cuts
	//
	muonArr->Clear();
        muonBr->GetEntry(ientry);

	Int_t nLooseLep=0;
	const baconhep::TMuon *goodMuon=0;
	Bool_t passSel=kFALSE;

        for(Int_t i=0; i<muonArr->GetEntriesFast(); i++) {
          const baconhep::TMuon *mu = (baconhep::TMuon*)((*muonArr)[i]);

          if(fabs(mu->eta) > VETO_PT)  continue; // loose lepton |eta| cut
          if(mu->pt        < VETO_ETA) continue; // loose lepton pT cut
//          if(passMuonLooseID(mu)) nLooseLep++; // loose lepton selection
          if(nLooseLep>1) {  // extra lepton veto
            passSel=kFALSE;
            break;
          }
          
          if(fabs(mu->eta) > ETA_CUT)         continue; // lepton |eta| cut
          if(mu->pt < PT_CUT)                 continue; // lepton pT cut   
          if(!passAntiMuonID(mu))             continue; // lepton anti-selection
          if(!isMuonTriggerObj(triggerMenu, mu->hltMatchBits, kFALSE)) continue;
	  
	  passSel=kTRUE;
	  goodMuon = mu;
	}

	if(passSel) {	  
	  /******** We have a W candidate! HURRAY! ********/
	  nsel+=weight;
          nselvar+=weight*weight;
	  
	  TLorentzVector vLep; 
	  vLep.SetPtEtaPhiM(goodMuon->pt, goodMuon->eta, goodMuon->phi, MUON_MASS);

	  //
	  // Fill tree
	  //
	  runNum   = info->runNum;
	  lumiSec  = info->lumiSec;
	  evtNum   = info->evtNum;
	  
	  vertexArr->Clear();
	  vertexBr->GetEntry(ientry);

	  npv      = vertexArr->GetEntries();
	  npu	   = info->nPUmean;
	  genV      = new TLorentzVector(0,0,0,0);
          genLep    = new TLorentzVector(0,0,0,0);
	  genVPt    = -999;
          genVPhi   = -999;
          genVy     = -999;
          genVMass  = -999;
          u1        = -999;
          u2        = -999;
          tkU1      = -999;
          tkU2      = -999;
	  mvaU1     = -999;
          mvaU2     = -999;
          id_1      = -999;
          id_2      = -999;
          x_1       = -999;
          x_2       = -999;
          xPDF_1    = -999;
          xPDF_2    = -999;
          scalePDF  = -999;
          weightPDF = -999;

	  if(isSignal && hasGen) {
	    TLorentzVector *gvec=new TLorentzVector(0,0,0,0);
            TLorentzVector *glep1=new TLorentzVector(0,0,0,0);
            TLorentzVector *glep2=new TLorentzVector(0,0,0,0);
	    toolbox::fillGen(genPartArr, BOSON_ID, gvec, glep1, glep2,1);

            if (gvec && glep1) {
	      genV      = new TLorentzVector(0,0,0,0);
              genV->SetPtEtaPhiM(gvec->Pt(),gvec->Eta(),gvec->Phi(),gvec->M());
              genLep    = new TLorentzVector(0,0,0,0);
              genLep->SetPtEtaPhiM(glep1->Pt(),glep1->Eta(),glep1->Phi(),glep1->M());
              genVPt    = gvec->Pt();
              genVPhi   = gvec->Phi();
              genVy     = gvec->Rapidity();
              genVMass  = gvec->M();
              genLepPt  = glep1->Pt();
              genLepPhi = glep1->Phi();

	      TVector2 vWPt((genVPt)*cos(genVPhi),(genVPt)*sin(genVPhi));
	      TVector2 vLepPt(vLep.Px(),vLep.Py());
	      
	      TVector2 vMet((info->pfMETC)*cos(info->pfMETCphi), (info->pfMETC)*sin(info->pfMETCphi));
	      TVector2 vU = -1.0*(vMet+vLepPt);
	      u1 = ((vWPt.Px())*(vU.Px()) + (vWPt.Py())*(vU.Py()))/(genVPt);  // u1 = (pT . u)/|pT|
	      u2 = ((vWPt.Px())*(vU.Py()) - (vWPt.Py())*(vU.Px()))/(genVPt);  // u2 = (pT x u)/|pT|

	      TVector2 vTkMet((info->trkMET)*cos(info->trkMETphi), (info->trkMET)*sin(info->trkMETphi));
	      TVector2 vTkU = -1.0*(vTkMet+vLepPt);
	      tkU1 = ((vWPt.Px())*(vTkU.Px()) + (vWPt.Py())*(vTkU.Py()))/(genVPt);  // u1 = (pT . u)/|pT|
	      tkU2 = ((vWPt.Px())*(vTkU.Py()) - (vWPt.Py())*(vTkU.Px()))/(genVPt);  // u2 = (pT x u)/|pT|
	      
	      TVector2 vMvaMet((info->mvaMET)*cos(info->mvaMETphi), (info->mvaMET)*sin(info->mvaMETphi));
	      TVector2 vMvaU = -1.0*(vMvaMet+vLepPt);
	      mvaU1 = ((vWPt.Px())*(vMvaU.Px()) + (vWPt.Py())*(vMvaU.Py()))/(genVPt);  // u1 = (pT . u)/|pT|
	      mvaU2 = ((vWPt.Px())*(vMvaU.Py()) - (vWPt.Py())*(vMvaU.Px()))/(genVPt);  // u2 = (pT x u)/|pT|
          
            }
	    id_1      = gen->id_1;
            id_2      = gen->id_2;
            x_1       = gen->x_1;
            x_2       = gen->x_2;
            xPDF_1    = gen->xPDF_1;
            xPDF_2    = gen->xPDF_2;
            scalePDF  = gen->scalePDF;
            weightPDF = gen->weight;

	    delete gvec;
            delete glep1;
            delete glep2;
            gvec=0; glep1=0; glep2=0;
	  }
	  scale1fb = weight;
	  puWeight = h_rw->GetBinContent(info->nPUmean+1);
	  met	   = info->pfMETC;
	  metPhi   = info->pfMETCphi;
	  sumEt    = 0;
	  mt       = sqrt( 2.0 * (vLep.Pt()) * (info->pfMETC) * (1.0-cos(toolbox::deltaPhi(vLep.Phi(),info->pfMETCphi))) );
	  tkMet    = info->trkMET;
          tkMetPhi = info->trkMETphi;
          tkSumEt  = 0;
          tkMt     = sqrt( 2.0 * (vLep.Pt()) * (info->trkMET) * (1.0-cos(toolbox::deltaPhi(vLep.Phi(),info->trkMETphi))) );
	  mvaMet   = info->mvaMET;
          mvaMetPhi = info->mvaMETphi;
          mvaSumEt  = 0;
          mvaMt     = sqrt( 2.0 * (vLep.Pt()) * (info->mvaMET) * (1.0-cos(toolbox::deltaPhi(vLep.Phi(),info->mvaMETphi))) );
	  q        = goodMuon->q;
	  lep      = &vLep;
	  
	  ///// muon specific /////
	  trkIso     = goodMuon->trkIso;
          emIso      = goodMuon->ecalIso;
          hadIso     = goodMuon->hcalIso;
          pfChIso    = goodMuon->chHadIso;
          pfGamIso   = goodMuon->gammaIso;
          pfNeuIso   = goodMuon->neuHadIso;
          pfCombIso  = goodMuon->chHadIso + TMath::Max(goodMuon->neuHadIso + goodMuon->gammaIso -
						       0.5*(goodMuon->puIso),Double_t(0));
	  d0         = goodMuon->d0;
	  dz         = goodMuon->dz;
	  muNchi2    = goodMuon->muNchi2;
	  nPixHits   = goodMuon->nPixHits;
	  nTkLayers  = goodMuon->nTkLayers;
	  nMatch     = goodMuon->nMatchStn;
	  nValidHits = goodMuon->nValidHits;
	  typeBits   = goodMuon->typeBits;

	  outTree->Fill();
	  delete genV;
	  delete genLep;
	  genV=0, genLep=0, lep=0;
        }
      }
      delete infile;
      infile=0, eventTree=0;    

      cout << nsel  << " +/- " << sqrt(nselvar);
      if(isam!=0) cout << " per 1/fb";
      cout << endl;
    }
    outFile->Write();
    outFile->Close();
  }
  delete h_rw;
  delete f_rw;
  delete info;
  delete gen;
  delete genPartArr;
  delete muonArr;
  delete vertexArr;
      
  //--------------------------------------------------------------------------------------------------------------
  // Output
  //==============================================================================================================
   
  cout << "*" << endl;
  cout << "* SUMMARY" << endl;
  cout << "*--------------------------------------------------" << endl;
  cout << " W -> mu nu" << endl;
  cout << "  pT > " << PT_CUT << endl;
  cout << "  |eta| < " << ETA_CUT << endl;
  cout << endl;
  
  cout << endl;
  cout << "  <> Output saved in " << outputDir << "/" << endl;    
  cout << endl;  
      
  gBenchmark->Show("selectAntiWm"); 
}
Example #29
0
void selectWe(const TString conf="we.conf", // input file
              const TString outputDir=".",  // output directory
              const Bool_t  doScaleCorr=0   // apply energy scale corrections?
             ) {
    gBenchmark->Start("selectWe");

    //--------------------------------------------------------------------------------------------------------------
    // Settings
    //==============================================================================================================

    const Double_t PT_CUT   = 25;
    const Double_t ETA_CUT  = 2.5;
    const Double_t ELE_MASS = 0.000511;

    const Double_t VETO_PT   = 10;
    const Double_t VETO_ETA  = 2.5;

    const Double_t ECAL_GAP_LOW  = 1.4442;
    const Double_t ECAL_GAP_HIGH = 1.566;

    const Double_t escaleNbins  = 2;
    const Double_t escaleEta[]  = { 1.4442, 2.5   };
    const Double_t escaleCorr[] = { 0.992,  1.009 };

    const Int_t BOSON_ID  = 24;
    const Int_t LEPTON_ID = 11;

    // load trigger menu
    const baconhep::TTrigger triggerMenu("../../BaconAna/DataFormats/data/HLT_50nsGRun");

    // load pileup reweighting file
    TFile *f_rw = TFile::Open("../Tools/pileup_rw_Golden.root", "read");
    TH1D *h_rw = (TH1D*) f_rw->Get("h_rw_golden");
    TH1D *h_rw_up = (TH1D*) f_rw->Get("h_rw_up_golden");
    TH1D *h_rw_down = (TH1D*) f_rw->Get("h_rw_down_golden");

    //--------------------------------------------------------------------------------------------------------------
    // Main analysis code
    //==============================================================================================================

    vector<TString>  snamev;      // sample name (for output files)
    vector<CSample*> samplev;     // data/MC samples

    //
    // parse .conf file
    //
    confParse(conf, snamev, samplev);
    const Bool_t hasData = (samplev[0]->fnamev.size()>0);

    // Create output directory
    gSystem->mkdir(outputDir,kTRUE);
    const TString ntupDir = outputDir + TString("/ntuples");
    gSystem->mkdir(ntupDir,kTRUE);

    //
    // Declare output ntuple variables
    //
    UInt_t  runNum, lumiSec, evtNum;
    UInt_t  npv, npu;
    UInt_t  id_1, id_2;
    Double_t x_1, x_2, xPDF_1, xPDF_2;
    Double_t scalePDF, weightPDF;
    TLorentzVector *genV=0, *genLep=0;
    Float_t genVPt, genVPhi, genVy, genVMass;
    Float_t genLepPt, genLepPhi;
    Float_t scale1fb, puWeight, puWeightUp, puWeightDown;
    Float_t met, metPhi, sumEt, mt, u1, u2;
    Float_t tkMet, tkMetPhi, tkSumEt, tkMt, tkU1, tkU2;
    Float_t mvaMet, mvaMetPhi, mvaSumEt, mvaMt, mvaU1, mvaU2;
    Float_t puppiMet, puppiMetPhi, puppiSumEt, puppiMt, puppiU1, puppiU2;
    Int_t   q;
    TLorentzVector *lep=0;
    Int_t lepID;
    ///// electron specific /////
    Float_t trkIso, emIso, hadIso;
    Float_t pfChIso, pfGamIso, pfNeuIso, pfCombIso;
    Float_t sigieie, hovere, eoverp, fbrem, ecalE;
    Float_t dphi, deta;
    Float_t d0, dz;
    UInt_t  isConv, nexphits, typeBits;
    TLorentzVector *sc=0;

    // Data structures to store info from TTrees
    baconhep::TEventInfo *info   = new baconhep::TEventInfo();
    baconhep::TGenEventInfo *gen = new baconhep::TGenEventInfo();
    TClonesArray *genPartArr     = new TClonesArray("baconhep::TGenParticle");
    TClonesArray *electronArr    = new TClonesArray("baconhep::TElectron");
    TClonesArray *scArr          = new TClonesArray("baconhep::TPhoton");
    TClonesArray *vertexArr      = new TClonesArray("baconhep::TVertex");

    TFile *infile=0;
    TTree *eventTree=0;

    //
    // loop over samples
    //
    for(UInt_t isam=0; isam<samplev.size(); isam++) {

        // Assume data sample is first sample in .conf file
        // If sample is empty (i.e. contains no ntuple files), skip to next sample
        Bool_t isData=kFALSE;
        if(isam==0 && !hasData) continue;
        else if (isam==0) isData=kTRUE;

        // Assume signal sample is given name "we" -- flag to store GEN W kinematics
        Bool_t isSignal = (snamev[isam].CompareTo("we",TString::kIgnoreCase)==0);
        // flag to reject W->enu events when selecting at wrong-flavor background events
        Bool_t isWrongFlavor = (snamev[isam].CompareTo("wx",TString::kIgnoreCase)==0);

        CSample* samp = samplev[isam];

        //
        // Set up output ntuple
        //
        TString outfilename = ntupDir + TString("/") + snamev[isam] + TString("_select.root");
        if(isam!=0 && !doScaleCorr) outfilename = ntupDir + TString("/") + snamev[isam] + TString("_select.raw.root");
        TFile *outFile = new TFile(outfilename,"RECREATE");
        TTree *outTree = new TTree("Events","Events");

        outTree->Branch("runNum",     &runNum,     "runNum/i");      // event run number
        outTree->Branch("lumiSec",    &lumiSec,    "lumiSec/i");     // event lumi section
        outTree->Branch("evtNum",     &evtNum,     "evtNum/i");      // event number
        outTree->Branch("npv",        &npv,        "npv/i");         // number of primary vertices
        outTree->Branch("npu",        &npu,        "npu/i");         // number of in-time PU events (MC)
        outTree->Branch("id_1",       &id_1,       "id_1/i");        // PDF info -- parton ID for parton 1
        outTree->Branch("id_2",       &id_2,       "id_2/i");        // PDF info -- parton ID for parton 2
        outTree->Branch("x_1",        &x_1,        "x_1/d");         // PDF info -- x for parton 1
        outTree->Branch("x_2",        &x_2,        "x_2/d");         // PDF info -- x for parton 2
        outTree->Branch("xPDF_1",     &xPDF_1,     "xPDF_1/d");      // PDF info -- x*F for parton 1
        outTree->Branch("xPDF_2",     &xPDF_2,     "xPDF_2/d");      // PDF info -- x*F for parton 2
        outTree->Branch("scalePDF",   &scalePDF,   "scalePDF/d");    // PDF info -- energy scale of parton interaction
        outTree->Branch("weightPDF",  &weightPDF,  "weightPDF/d");   // PDF info -- PDF weight
        outTree->Branch("genV",      "TLorentzVector", &genV);       // GEN boson 4-vector (signal MC)
        outTree->Branch("genLep",    "TLorentzVector", &genLep);     // GEN lepton 4-vector (signal MC)
        outTree->Branch("genVPt",     &genVPt,     "genVPt/F");      // GEN boson pT (signal MC)
        outTree->Branch("genVPhi",    &genVPhi,    "genVPhi/F");     // GEN boson phi (signal MC)
        outTree->Branch("genVy",      &genVy,      "genVy/F");       // GEN boson rapidity (signal MC)
        outTree->Branch("genVMass",   &genVMass,   "genVMass/F");    // GEN boson mass (signal MC)
        outTree->Branch("genLepPt",   &genLepPt,   "genLepPt/F");    // GEN lepton pT (signal MC)
        outTree->Branch("genLepPhi",  &genLepPhi,  "genLepPhi/F");   // GEN lepton phi (signal MC)
        outTree->Branch("scale1fb",   &scale1fb,   "scale1fb/F");    // event weight per 1/fb (MC)
        outTree->Branch("puWeight",   &puWeight,   "puWeight/F");    // scale factor for pileup reweighting (MC)
        outTree->Branch("puWeightUp",    &puWeightUp,   "puWeightUp/F");    // scale factor for pileup reweighting (MC)
        outTree->Branch("puWeightDown",    &puWeightDown,   "puWeightDown/F");    // scale factor for pileup reweighting (MC)
        outTree->Branch("met",        &met,        "met/F");         // MET
        outTree->Branch("metPhi",     &metPhi,     "metPhi/F");      // phi(MET)
        outTree->Branch("sumEt",      &sumEt,      "sumEt/F");       // Sum ET
        outTree->Branch("mt",         &mt,         "mt/F");          // transverse mass
        outTree->Branch("u1",         &u1,         "u1/F");          // parallel component of recoil
        outTree->Branch("u2",         &u2,         "u2/F");          // perpendicular component of recoil
        outTree->Branch("tkMet",      &tkMet,      "tkMet/F");       // MET (track MET)
        outTree->Branch("tkMetPhi",   &tkMetPhi,   "tkMetPhi/F");    // phi(MET) (track MET)
        outTree->Branch("tkSumEt",    &tkSumEt,    "tkSumEt/F");     // Sum ET (track MET)
        outTree->Branch("tkMt",       &tkMt,       "tkMt/F");        // transverse mass (track MET)
        outTree->Branch("tkU1",       &tkU1,       "tkU1/F");        // parallel component of recoil (track MET)
        outTree->Branch("tkU2",       &tkU2,       "tkU2/F");        // perpendicular component of recoil (track MET)
        outTree->Branch("mvaMet",     &mvaMet,     "mvaMet/F");      // MVA MET
        outTree->Branch("mvaMetPhi",  &mvaMetPhi,  "mvaMetPhi/F");   // phi(MVA MET)
        outTree->Branch("mvaSumEt",   &mvaSumEt,   "mvaSumEt/F");    // Sum ET (mva MET)
        outTree->Branch("mvaMt",      &mvaMt,      "mvaMt/F");       // transverse mass (mva MET)
        outTree->Branch("mvaU1",      &mvaU1,      "mvaU1/F");       // parallel component of recoil (mva MET)
        outTree->Branch("mvaU2",      &mvaU2,      "mvaU2/F");       // perpendicular component of recoil (mva MET)
        outTree->Branch("puppiMet",    &puppiMet,   "puppiMet/F");      // Puppi MET
        outTree->Branch("puppiMetPhi", &puppiMetPhi,"puppiMetPhi/F");   // phi(Puppi MET)
        outTree->Branch("puppiSumEt",  &puppiSumEt, "puppiSumEt/F");    // Sum ET (Puppi MET)
        outTree->Branch("puppiU1",     &puppiU1,    "puppiU1/F");       // parallel component of recoil (Puppi MET)
        outTree->Branch("puppiU2",     &puppiU2,    "puppiU2/F");       // perpendicular component of recoil (Puppi MET)
        outTree->Branch("q",          &q,          "q/I");           // lepton charge
        outTree->Branch("lep",       "TLorentzVector", &lep);        // lepton 4-vector
        outTree->Branch("lepID",      &lepID,      "lepID/I");       // lepton PDG ID
        ///// electron specific /////
        outTree->Branch("trkIso",     &trkIso,     "trkIso/F");      // track isolation of tag lepton
        outTree->Branch("emIso",      &emIso,      "emIso/F");       // ECAL isolation of tag lepton
        outTree->Branch("hadIso",     &hadIso,     "hadIso/F");      // HCAL isolation of tag lepton
        outTree->Branch("pfChIso",    &pfChIso,    "pfChIso/F");     // PF charged hadron isolation of lepton
        outTree->Branch("pfGamIso",   &pfGamIso,   "pfGamIso/F");    // PF photon isolation of lepton
        outTree->Branch("pfNeuIso",   &pfNeuIso,   "pfNeuIso/F");    // PF neutral hadron isolation of lepton
        outTree->Branch("pfCombIso",  &pfCombIso,  "pfCombIso/F");   // PF combined isolation of electron
        outTree->Branch("sigieie",    &sigieie,    "sigieie/F");     // sigma-ieta-ieta of electron
        outTree->Branch("hovere",     &hovere,     "hovere/F");      // H/E of electron
        outTree->Branch("eoverp",     &eoverp,     "eoverp/F");      // E/p of electron
        outTree->Branch("fbrem",      &fbrem,      "fbrem/F");       // brem fraction of electron
        outTree->Branch("dphi",       &dphi,       "dphi/F");        // GSF track - ECAL dphi of electron
        outTree->Branch("deta",       &deta,       "deta/F");        // GSF track - ECAL deta of electron
        outTree->Branch("ecalE",      &ecalE,      "ecalE/F");       // ECAL energy of electron
        outTree->Branch("d0",         &d0,         "d0/F");          // transverse impact parameter of electron
        outTree->Branch("dz",         &dz,         "dz/F");          // longitudinal impact parameter of electron
        outTree->Branch("isConv",     &isConv,     "isConv/i");      // conversion filter flag of electron
        outTree->Branch("nexphits",   &nexphits,   "nexphits/i");    // number of missing expected inner hits of electron
        outTree->Branch("typeBits",   &typeBits,   "typeBits/i");    // electron type of electron
        outTree->Branch("sc",        "TLorentzVector", &sc);         // supercluster 4-vector

        //
        // loop through files
        //
        const UInt_t nfiles = samp->fnamev.size();
        for(UInt_t ifile=0; ifile<nfiles; ifile++) {

            // Read input file and get the TTrees
            cout << "Processing " << samp->fnamev[ifile] << " [xsec = " << samp->xsecv[ifile] << " pb] ... ";
            cout.flush();
            infile = TFile::Open(samp->fnamev[ifile]);
            assert(infile);

            Bool_t hasJSON = kFALSE;
            baconhep::RunLumiRangeMap rlrm;
            if(samp->jsonv[ifile].CompareTo("NONE")!=0) {
                hasJSON = kTRUE;
                rlrm.addJSONFile(samp->jsonv[ifile].Data());
            }

            eventTree = (TTree*)infile->Get("Events");
            assert(eventTree);
            eventTree->SetBranchAddress("Info",     &info);
            TBranch *infoBr     = eventTree->GetBranch("Info");
            eventTree->SetBranchAddress("Electron", &electronArr);
            TBranch *electronBr = eventTree->GetBranch("Electron");
            eventTree->SetBranchAddress("PV",   &vertexArr);
            TBranch *vertexBr = eventTree->GetBranch("PV");

            Bool_t hasGen = eventTree->GetBranchStatus("GenEvtInfo");
            TBranch *genBr=0, *genPartBr=0;
            if(hasGen) {
                eventTree->SetBranchAddress("GenEvtInfo", &gen);
                genBr = eventTree->GetBranch("GenEvtInfo");
                eventTree->SetBranchAddress("GenParticle",&genPartArr);
                genPartBr = eventTree->GetBranch("GenParticle");
            }

            // Compute MC event weight per 1/fb
            const Double_t xsec = samp->xsecv[ifile];
            Double_t totalWeight=0;

            if (hasGen) {
                TH1D *hall = new TH1D("hall", "", 1,0,1);
                eventTree->Draw("0.5>>hall", "GenEvtInfo->weight");
                totalWeight=hall->Integral();
                delete hall;
                hall=0;
            }

            //
            // loop over events
            //
            Double_t nsel=0, nselvar=0;
            for(UInt_t ientry=0; ientry<eventTree->GetEntries(); ientry++) {
                infoBr->GetEntry(ientry);

                if(ientry%1000000==0) cout << "Processing event " << ientry << ". " << (double)ientry/(double)eventTree->GetEntries()*100 << " percent done with this file." << endl;

                Double_t weight=1;
                if(xsec>0 && totalWeight>0) weight = xsec/totalWeight;
                if(hasGen) {
                    genPartArr->Clear();
                    genBr->GetEntry(ientry);
                    genPartBr->GetEntry(ientry);
                    weight*=gen->weight;
                }

                // veto w -> xv decays for signal and w -> ev for bacground samples (needed for inclusive WToLNu sample)
                if (isWrongFlavor && hasGen && fabs(toolbox::flavor(genPartArr, BOSON_ID))==LEPTON_ID) continue;
                else if (isSignal && hasGen && fabs(toolbox::flavor(genPartArr, BOSON_ID))!=LEPTON_ID) continue;

                // check for certified lumi (if applicable)
                baconhep::RunLumiRangeMap::RunLumiPairType rl(info->runNum, info->lumiSec);
                if(hasJSON && !rlrm.hasRunLumi(rl)) continue;

                // trigger requirement
                if (!isEleTrigger(triggerMenu, info->triggerBits, isData)) continue;

                // good vertex requirement
                if(!(info->hasGoodPV)) continue;

                //
                // SELECTION PROCEDURE:
                //  (1) Look for 1 good electron matched to trigger
                //  (2) Reject event if another electron is present passing looser cuts
                //
                electronArr->Clear();
                electronBr->GetEntry(ientry);

                Int_t nLooseLep=0;
                const baconhep::TElectron *goodEle=0;
                Bool_t passSel=kFALSE;

                for(Int_t i=0; i<electronArr->GetEntriesFast(); i++) {
                    const baconhep::TElectron *ele = (baconhep::TElectron*)((*electronArr)[i]);

                    // check ECAL gap
                    if(fabs(ele->scEta)>=ECAL_GAP_LOW && fabs(ele->scEta)<=ECAL_GAP_HIGH) continue;

                    // apply scale and resolution corrections to MC
                    Double_t elescEt_corr = ele->scEt;
                    if(doScaleCorr && snamev[isam].CompareTo("data",TString::kIgnoreCase)!=0)
                        elescEt_corr = gRandom->Gaus(ele->scEt*getEleScaleCorr(ele->scEta,0),getEleResCorr(ele->scEta,0));

                    if(fabs(ele->scEta)   > VETO_ETA) continue;        // loose lepton |eta| cut
                    if(elescEt_corr       < VETO_PT)  continue;        // loose lepton pT cut
                    if(passEleLooseID(ele,info->rhoIso)) nLooseLep++;  // loose lepton selection
                    if(nLooseLep>1) {  // extra lepton veto
                        passSel=kFALSE;
                        break;
                    }

                    if(fabs(ele->scEta)   > ETA_CUT)     continue;  // lepton |eta| cut
                    if(elescEt_corr       < PT_CUT)      continue;  // lepton pT cut
                    if(!passEleID(ele,info->rhoIso))     continue;  // lepton selection
                    if(!isEleTriggerObj(triggerMenu, ele->hltMatchBits, kFALSE, isData)) continue;

                    passSel=kTRUE;
                    goodEle = ele;
                }

                if(passSel) {

                    //******* We have a W candidate! HURRAY! ********
                    nsel+=weight;
                    nselvar+=weight*weight;

                    // apply scale and resolution corrections to MC
                    Double_t goodElept_corr = goodEle->pt;
                    if(doScaleCorr && snamev[isam].CompareTo("data",TString::kIgnoreCase)!=0)
                        goodElept_corr = gRandom->Gaus(goodEle->pt*getEleScaleCorr(goodEle->scEta,0),getEleResCorr(goodEle->scEta,0));

                    TLorentzVector vLep(0,0,0,0);
                    TLorentzVector vSC(0,0,0,0);
                    // apply scale and resolution corrections to MC
                    if(doScaleCorr && snamev[isam].CompareTo("data",TString::kIgnoreCase)!=0) {
                        vLep.SetPtEtaPhiM(goodElept_corr, goodEle->eta, goodEle->phi, ELE_MASS);
                        vSC.SetPtEtaPhiM(gRandom->Gaus(goodEle->scEt*getEleScaleCorr(goodEle->scEta,0),getEleResCorr(goodEle->scEta,0)), goodEle->scEta, goodEle->scPhi, ELE_MASS);
                    } else {
                        vLep.SetPtEtaPhiM(goodEle->pt,goodEle->eta,goodEle->phi,ELE_MASS);
                        vSC.SetPtEtaPhiM(goodEle->scEt,goodEle->scEta,goodEle->scPhi,ELE_MASS);
                    }

                    //
                    // Fill tree
                    //
                    runNum    = info->runNum;
                    lumiSec   = info->lumiSec;
                    evtNum    = info->evtNum;

                    vertexArr->Clear();
                    vertexBr->GetEntry(ientry);

                    npv      = vertexArr->GetEntries();
                    npu	    = info->nPUmean;
                    genV      = new TLorentzVector(0,0,0,0);
                    genLep    = new TLorentzVector(0,0,0,0);
                    genVPt    = -999;
                    genVPhi   = -999;
                    genVy     = -999;
                    genVMass  = -999;
                    genLepPt  = -999;
                    genLepPhi = -999;
                    u1        = -999;
                    u2        = -999;
                    tkU1      = -999;
                    tkU2      = -999;
                    mvaU1     = -999;
                    mvaU2     = -999;
                    puppiU1     = -999;
                    puppiU2     = -999;
                    id_1      = -999;
                    id_2      = -999;
                    x_1       = -999;
                    x_2       = -999;
                    xPDF_1    = -999;
                    xPDF_2    = -999;
                    scalePDF  = -999;
                    weightPDF = -999;

                    if(isSignal && hasGen) {
                        TLorentzVector *gvec=new TLorentzVector(0,0,0,0);
                        TLorentzVector *glep1=new TLorentzVector(0,0,0,0);
                        TLorentzVector *glep2=new TLorentzVector(0,0,0,0);
                        toolbox::fillGen(genPartArr, BOSON_ID, gvec, glep1, glep2,1);

                        if (gvec && glep1) {
                            genV      = new TLorentzVector(0,0,0,0);
                            genV->SetPtEtaPhiM(gvec->Pt(),gvec->Eta(),gvec->Phi(),gvec->M());
                            genLep    = new TLorentzVector(0,0,0,0);
                            genLep->SetPtEtaPhiM(glep1->Pt(),glep1->Eta(),glep1->Phi(),glep1->M());
                            genVPt    = gvec->Pt();
                            genVPhi   = gvec->Phi();
                            genVy     = gvec->Rapidity();
                            genVMass  = gvec->M();
                            genLepPt  = glep1->Pt();
                            genLepPhi = glep1->Phi();

                            TVector2 vWPt((genVPt)*cos(genVPhi),(genVPt)*sin(genVPhi));
                            TVector2 vLepPt(vLep.Px(),vLep.Py());

                            TVector2 vMet((info->pfMETC)*cos(info->pfMETCphi), (info->pfMETC)*sin(info->pfMETCphi));
                            TVector2 vU = -1.0*(vMet+vLepPt);
                            u1 = ((vWPt.Px())*(vU.Px()) + (vWPt.Py())*(vU.Py()))/(genVPt);  // u1 = (pT . u)/|pT|
                            u2 = ((vWPt.Px())*(vU.Py()) - (vWPt.Py())*(vU.Px()))/(genVPt);  // u2 = (pT x u)/|pT|

                            TVector2 vTkMet((info->trkMET)*cos(info->trkMETphi), (info->trkMET)*sin(info->trkMETphi));
                            TVector2 vTkU = -1.0*(vTkMet+vLepPt);
                            tkU1 = ((vWPt.Px())*(vTkU.Px()) + (vWPt.Py())*(vTkU.Py()))/(genVPt);  // u1 = (pT . u)/|pT|
                            tkU2 = ((vWPt.Px())*(vTkU.Py()) - (vWPt.Py())*(vTkU.Px()))/(genVPt);  // u2 = (pT x u)/|pT|

                            TVector2 vMvaMet((info->mvaMET)*cos(info->mvaMETphi), (info->mvaMET)*sin(info->mvaMETphi));
                            TVector2 vMvaU = -1.0*(vMvaMet+vLepPt);
                            mvaU1 = ((vWPt.Px())*(vMvaU.Px()) + (vWPt.Py())*(vMvaU.Py()))/(genVPt);  // u1 = (pT . u)/|pT|
                            mvaU2 = ((vWPt.Px())*(vMvaU.Py()) - (vWPt.Py())*(vMvaU.Px()))/(genVPt);  // u2 = (pT x u)/|pT|

                            TVector2 vPuppiMet((info->puppET)*cos(info->puppETphi), (info->puppET)*sin(info->puppETphi));
                            TVector2 vPuppiU = -1.0*(vPuppiMet+vLepPt);
                            puppiU1 = ((vWPt.Px())*(vPuppiU.Px()) + (vWPt.Py())*(vPuppiU.Py()))/(genVPt);  // u1 = (pT . u)/|pT|
                            puppiU2 = ((vWPt.Px())*(vPuppiU.Py()) - (vWPt.Py())*(vPuppiU.Px()))/(genVPt);  // u2 = (pT x u)/|pT|

                        }
                        id_1      = gen->id_1;
                        id_2      = gen->id_2;
                        x_1       = gen->x_1;
                        x_2       = gen->x_2;
                        xPDF_1    = gen->xPDF_1;
                        xPDF_2    = gen->xPDF_2;
                        scalePDF  = gen->scalePDF;
                        weightPDF = gen->weight;

                        delete gvec;
                        delete glep1;
                        delete glep2;
                        gvec=0;
                        glep1=0;
                        glep2=0;
                    }
                    scale1fb = weight;
                    puWeight = h_rw->GetBinContent(h_rw->FindBin(npu));
                    puWeightUp = h_rw_up->GetBinContent(h_rw_up->FindBin(npu));
                    puWeightDown = h_rw_down->GetBinContent(h_rw_down->FindBin(npu));
                    met	   = info->pfMETC;
                    metPhi   = info->pfMETCphi;
                    sumEt    = 0;
                    mt       = sqrt( 2.0 * (vLep.Pt()) * (info->pfMETC) * (1.0-cos(toolbox::deltaPhi(vLep.Phi(),info->pfMETCphi))) );
                    tkMet	   = info->trkMET;
                    tkMetPhi = info->trkMETphi;
                    tkSumEt  = 0;
                    tkMt     = sqrt( 2.0 * (vLep.Pt()) * (info->trkMET) * (1.0-cos(toolbox::deltaPhi(vLep.Phi(),info->trkMETphi))) );
                    mvaMet   = info->mvaMET;
                    mvaMetPhi = info->mvaMETphi;
                    mvaSumEt  = 0;
                    mvaMt     = sqrt( 2.0 * (vLep.Pt()) * (info->mvaMET) * (1.0-cos(toolbox::deltaPhi(vLep.Phi(),info->mvaMETphi))) );
// 	  TVector2 vLepPt(vLep.Px(),vLep.Py());
// 	  TVector2 vPuppi((info->puppET)*cos(info->puppETphi), (info->puppET)*sin(info->puppETphi));
// 	  TVector2 vpp; vpp=vPuppi-vLepPt;
                    puppiMet   = info->puppET;
                    puppiMetPhi = info->puppETphi;
                    puppiSumEt  = 0;
                    puppiMt     = sqrt( 2.0 * (vLep.Pt()) * (info->puppET) * (1.0-cos(toolbox::deltaPhi(vLep.Phi(),info->puppETphi))) );
                    q        = goodEle->q;
                    lep      = &vLep;

                    ///// electron specific /////
                    sc       = &vSC;
                    trkIso    = goodEle->trkIso;
                    emIso     = goodEle->ecalIso;
                    hadIso    = goodEle->hcalIso;
                    pfChIso   = goodEle->chHadIso;
                    pfGamIso  = goodEle->gammaIso;
                    pfNeuIso  = goodEle->neuHadIso;
                    pfCombIso = goodEle->chHadIso + TMath::Max(goodEle->neuHadIso + goodEle->gammaIso -
                                (info->rhoIso)*getEffAreaEl(goodEle->scEta), 0.);
                    sigieie   = goodEle->sieie;
                    hovere    = goodEle->hovere;
                    eoverp    = goodEle->eoverp;
                    fbrem     = goodEle->fbrem;
                    dphi      = goodEle->dPhiIn;
                    deta      = goodEle->dEtaIn;
                    ecalE     = goodEle->ecalEnergy;
                    d0        = goodEle->d0;
                    dz        = goodEle->dz;
                    isConv    = goodEle->isConv;
                    nexphits  = goodEle->nMissingHits;
                    typeBits  = goodEle->typeBits;

                    outTree->Fill();
                    delete genV;
                    delete genLep;
                    genV=0, genLep=0, lep=0, sc=0;
                }
            }
            delete infile;
            infile=0, eventTree=0;

            cout << nsel  << " +/- " << sqrt(nselvar);
            if(isam!=0) cout << " per 1/pb";
            cout << endl;
        }
        outFile->Write();
        outFile->Close();
    }
    delete h_rw;
    delete h_rw_up;
    delete h_rw_down;
    delete f_rw;
    delete info;
    delete gen;
    delete genPartArr;
    delete electronArr;
    delete vertexArr;

    //--------------------------------------------------------------------------------------------------------------
    // Output
    //==============================================================================================================

    cout << "*" << endl;
    cout << "* SUMMARY" << endl;
    cout << "*--------------------------------------------------" << endl;
    cout << " W -> e nu" << endl;
    cout << "  pT > " << PT_CUT << endl;
    cout << "  |eta| < " << ETA_CUT << endl;
    if(doScaleCorr)
        cout << "  *** Scale corrections applied ***" << endl;
    cout << endl;

    cout << endl;
    cout << "  <> Output saved in " << outputDir << "/" << endl;
    cout << endl;

    gBenchmark->Show("selectWe");
}
Example #30
-1
void smear_JetMET(vector <TLorentzVector> & orig_jets, const TVector2 & orig_met, vector <TLorentzVector> & smear_jets, TVector2 & smear_met, TRandom3* rand3, vector <TF1*> vPtRes, vector <TF1*> vEtaRes, vector <TF1*> vPhiRes, TLorentzVector lep_sum){

  smear_jets.clear();
  
  double sum_jpx = 0;
  double sum_jpy = 0;
  
  double sum_jpx_sm = 0;
  double sum_jpy_sm = 0;

  double Pt_sm, Eta_sm, Phi_sm;

  TLorentzVector v_temp;

//   double a, b, c;
//   double Et;

  for (unsigned int sui = 0; sui < orig_jets.size(); sui++){

//     a = 1.84; b = 1.14; c = 0.027;
    
//     if (orig_jets.at(sui).Eta() < 1.4){
//       a = 1.78; b = 1.3; c = 0.053;
//     }

//     Et = orig_jets.at(sui).Pt();
    
//     Pt_sm = Et + sqrt(a*a + b*b*Et + c*c*Et*Et) * rand3->Gaus();

//     Eta_sm = orig_jets.at(sui).Eta();
//     Phi_sm = orig_jets.at(sui).Phi();

    Long64_t iseed = (Long64_t) 10E10;
    
    gRandom->SetSeed(rand3->Integer(iseed));
//     Pt_sm  = orig_jets.at(sui).Pt()  * (1 + (vPtRes.at(sui)->GetRandom() - 1) * 1.1);
    Pt_sm  = orig_jets.at(sui).Pt()  * vPtRes.at(sui)->GetRandom();

    gRandom->SetSeed(rand3->Integer(iseed));
    Eta_sm = orig_jets.at(sui).Eta() + vEtaRes.at(sui)->GetRandom();
    
    gRandom->SetSeed(rand3->Integer(iseed));
    Phi_sm = orig_jets.at(sui).Phi() + vPhiRes.at(sui)->GetRandom();
    
    v_temp.SetPtEtaPhiM(Pt_sm, Eta_sm, Phi_sm, orig_jets.at(sui).M());
   
    sum_jpx += orig_jets.at(sui).Px();
    sum_jpy += orig_jets.at(sui).Py();

    sum_jpx_sm += v_temp.Px();
    sum_jpy_sm += v_temp.Py();

    smear_jets.push_back(v_temp);
  }

  double unclust_metx = orig_met.Px() + sum_jpx + lep_sum.Px();
  double unclust_mety = orig_met.Py() + sum_jpy + lep_sum.Py();

  //10% resolution
  double unclust_metx_sm = unclust_metx * (1 + 0.1*rand3->Gaus());
  double unclust_mety_sm = unclust_mety * (1 + 0.1*rand3->Gaus());

  smear_met.Set(orig_met.Px() + sum_jpx - unclust_metx - sum_jpx_sm + unclust_metx_sm, orig_met.Py() + sum_jpy - unclust_mety - sum_jpy_sm + unclust_mety_sm);
}