コード例 #1
0
ファイル: radiation.c プロジェクト: project8/adiP8
int get_circ_wg_efield_vert(TVector3 &pos, TVector3 &efield)
{
  //returns the TE_11 efield inside an infinite circ. waveguide 
  //efield normalized the jackson way with 1/cm units
  //waveguide extends in x-direction
  // wavelength of 27 GHz radiation is 1.1 cm
  double p11 = 1.841;            //1st zero of the derivate of bessel function
  //k11 is angular wavenumber for cutoff frequency for TE11
  double k11 = p11 / tl_data.rO;
  //convert position to cylindrical
  pos.SetZ(0);
  double radius = pos.Mag();
  double phi = pos.Phi();//azimuthal position
  //double phi = acos(pos.Y()/radius);//azimuthal position, see definition of phase
  double J1 = TMath::BesselJ1(k11 * radius);//this term cancels in dot product w/ vel
  double Jp = TMath::BesselJ0(k11 * radius) - TMath::BesselJ1(k11 * radius) / k11 / radius;
  double e_amp = 1.63303/tl_data.rO;//cm
  int status = 0;

  if (radius > tl_data.rO) {
    cout << "Problem!!! Electron hit a wall! At radius " << radius << endl;
    status = 1;
  }
  efield.SetX(e_amp * (J1 / k11 / radius * cos(phi) * sin(phi) - Jp * sin(phi) * cos(phi)));
  efield.SetY(e_amp * (J1 / k11 / radius * sin(phi) * sin(phi) + Jp * cos(phi) * cos(phi)));
  efield.SetZ(0);                //only true for TE mode
  if (radius == 0) {
    Jp = 1.0/2; 
    phi = 0;
    efield.SetX(e_amp * (1. / 2 * cos(phi) * sin(phi) - Jp * sin(phi) * cos(phi)));
    efield.SetY(e_amp * (1. / 2 * sin(phi) * sin(phi) + Jp * cos(phi) * cos(phi)));
  }
  return status;
}
コード例 #2
0
ファイル: PCalTools.hpp プロジェクト: hengne/d0wmass
  static Bool_t is_in_phi_fiducial(const TVector3 &v) {
    // converted from emid::is_in_phi_fiducial
    
    const double PHI_CRACK_WIDTH=0.02; 
    
    double phi = v.Phi()>=0 ? v.Phi() : (v.Phi()+TMath::TwoPi()); 
    
    // CC phi cracks
    Bool_t outside_phi_crack=true;
    if (TMath::Abs(v.Z()) < 150.) {
      double phimod=fmod(phi+0.1,TMath::Pi()/16.);
      outside_phi_crack=(phimod<0.1-PHI_CRACK_WIDTH) || 
	(phimod>0.1+PHI_CRACK_WIDTH);
    }
    return outside_phi_crack;
  }
コード例 #3
0
void KVFAZIALNS2016::BuildFAZIA()
{
   //Build geometry of FAZIASYM
   //All telescopes are : Si(300µm)-Si(500µm)-CsI(10cm)
   //No attempt has been made to implement real thicknesses
   //
   Info("BuildFAZIA", "Compact geometry, %f cm from target",
        fFDist);

   TGeoVolume* top = gGeoManager->GetTopVolume();

   Double_t distance_block_cible = fFDist * KVUnits::cm;
   Double_t thick_si1 = 300 * KVUnits::um;
   TGeoTranslation trans;
   trans.SetDz(distance_block_cible + thick_si1 / 2.);

   KVFAZIABlock* block = new KVFAZIABlock;

   TGeoRotation rot1, rot2;
   TGeoHMatrix h;
   TGeoHMatrix* ph = 0;
   Double_t theta = 0;
   Double_t phi = 0;

   Double_t theta_min = fFThetaMin;//smallest lab polar angle in degrees
   Double_t centre_hole = 2.*tan(theta_min * TMath::DegToRad()) * distance_block_cible;
   Double_t dx = (block->GetTotalSideWithBlindage()) / 2.;

   TVector3 centre;
   for (Int_t bb = 0; bb < fNblocks; bb += 1) {

      if (bb == 1)        centre.SetXYZ(-1 * (dx - centre_hole / 2), -dx - centre_hole / 2, distance_block_cible);
      else if (bb == 2)   centre.SetXYZ(-1 * (dx + centre_hole / 2), dx - centre_hole / 2, distance_block_cible);
      else if (bb == 3)   centre.SetXYZ(-1 * (-dx + centre_hole / 2), dx + centre_hole / 2, distance_block_cible);
      else if (bb == 0)   centre.SetXYZ(-1 * (-dx - centre_hole / 2), -dx + centre_hole / 2, distance_block_cible);
      else if (bb == 4)   centre.SetXYZ(-1 * (-dx - centre_hole / 2), -3 * dx + centre_hole / 2, distance_block_cible); //centre.SetXYZ(-1 * (dx - centre_hole / 2), -3 * dx - centre_hole / 2, distance_block_cible);
      else {
         Warning("BuildFAZIA", "Block position definition is done only for %d blocks", fNblocks);
      }
      theta = centre.Theta() * TMath::RadToDeg();
      phi = centre.Phi() * TMath::RadToDeg();
      printf("BLK #%d => theta=%1.2lf - phi=%1.2lf\n", bb, theta, phi);

      rot2.SetAngles(phi + 90., theta, 0.);
      rot1.SetAngles(-1.*phi, 0., 0.);
      h = rot2 * trans * rot1;
      ph = new TGeoHMatrix(h);
      top->AddNode(block, bb, ph);
   }

   // add telescope for elastic scattering monitoring
//   RutherfordTelescope();
   // Change default geometry import angular range for rutherford telescope
   SetGeometryImportParameters(.25, 1., 1.84);
}
コード例 #4
0
ファイル: KVTenseur3.cpp プロジェクト: pwigg/kaliveda
//_________________________________________________________________
Double_t KVTenseur3::GetPhiPlan(void)
{
   // Obtention du Phi du plan de reaction (en degrès).
   // Cet angle suit les conventions de KaliVeda i.e. il est entre 0 et 360 degrees
   if (is_diago == 0)
      Diago();

   TVector3 vp = GetVep(3);

   if (vp.Z() < 0)
      vp = -vp;
   Double_t phi = vp.Phi() * TMath::RadToDeg();
   return (phi < 0 ? 360. + phi : phi);
}
コード例 #5
0
ファイル: xAna_allAna.C プロジェクト: hebda/ggAnalysis
int xAna::HggTreeWriteLoop(const char* filename, int ijob, 
					  bool correctVertex, bool correctEnergy, 
					  bool setRho0
					  ) {

  //bool invDRtoTrk = false;


  if( _config == 0 ) {
    cout << " config file was not set properly... bail out" << endl;
    return -1;
  }

  if (fChain == 0) return -1;
  
  Long64_t nentries = fChain->GetEntriesFast();
  //  nentries = 10000;
  cout << "nentries: " << nentries << endl;  
  Long64_t entry_start = ijob    *_config->nEvtsPerJob();
  Long64_t entry_stop  = (ijob+1)*_config->nEvtsPerJob();
  if( _config->nEvtsPerJob() < 0 ) {
    entry_stop = nentries;
  }
  if( entry_stop  > nentries ) entry_stop = nentries;
  cout << "   *** doing entries from: " << entry_start << " -> " << entry_stop << endl;
  if( entry_start > entry_stop ) return -1;

  
  EnergyScaleReader enScaleSkimEOS; /// skim EOS bugged so need to undo the energy scale in the skim
  EnergyScaleReader enScale;
  //  enScaleSkimEOS.setup( "ecalCalibFiles/EnergyScale2012_Lisbon_9fb.txt" );
  enScale.setup( _config->energyScaleFile() );


  Float_t HiggsMCMass =  _weight_manager->getCrossSection()->getHiggsMass();
  Float_t HiggsMCPt   = -1;
  bool isHiggsSignal = false;
  if( HiggsMCMass > 0 ) isHiggsSignal = true;

  mode_ = _weight_manager->getCrossSection()->mode();
  isData = false;
  if(mode_==-1) isData = true;        

//  mode_ = ijob; //  

  DoCorrectVertex_ = correctVertex;
  DoCorrectEnergy_ = correctEnergy;
  DoSetRho0_ = setRho0;

  doJetRegression = _config->getDoJetRegression();
  doControlSample = _config->getDoControlSample();
  
  phoID_2011[0] = new TMVA::Reader("!Color:Silent");
  phoID_2011[1] = new TMVA::Reader("!Color:Silent");
  phoID_2012[0] = new TMVA::Reader("!Color:Silent");
  phoID_2012[1] = new TMVA::Reader("!Color:Silent");
  DiscriDiPho_2011 = new TMVA::Reader("!Color:Silent");
  DiscriDiPho_2012 = new TMVA::Reader("!Color:Silent");
  if(doJetRegression!=0) jetRegres = new TMVA::Reader("!Color:Silent");
  Setup_MVA();
  
  if( _config->setup() == "ReReco2011" )  for( int i = 0 ; i < 2; i++ ) phoID_mva[i] = phoID_2011[i];
  else                                    for( int i = 0 ; i < 2; i++ ) phoID_mva[i] = phoID_2012[i];

  MassResolution massResoCalc;
  massResoCalc.addSmearingTerm();
  if( _config->setup() == "ReReco2011" )  Ddipho_mva = DiscriDiPho_2011;
  else                                    Ddipho_mva = DiscriDiPho_2012;

  float Ddipho_cat[5]; Ddipho_cat[4] = -1; 
  if( _config->setup() == "ReReco2011" ) { Ddipho_cat[0] = 0.89; Ddipho_cat[1] = 0.72; Ddipho_cat[2] = 0.55; Ddipho_cat[3] = +0.05; }
  else                                   { Ddipho_cat[0] = 0.91; Ddipho_cat[1] = 0.79; Ddipho_cat[2] = 0.49; Ddipho_cat[3] = -0.05; }
  //  else                                   { Ddipho_cat[0] = 0.88; Ddipho_cat[1] = 0.71; Ddipho_cat[2] = 0.50; Ddipho_cat[3] = -0.05; }

  DiscriVBF_UseDiPhoPt = true;
  DiscriVBF_UsePhoPt   = true;
  DiscriVBF_cat.resize(2); DiscriVBF_cat[0] = 0.985; DiscriVBF_cat[1] = 0.93;
  DiscriVBF_useMvaSel  = _config->doVBFmvaCat();


  


  /// depending on the selection veto or not on electrons (can do muele, elemu,eleele)
  bool vetoElec[2] = {true,true};
  if( _config->invertElectronVeto() ) { vetoElec[0] = false; vetoElec[1] = false; }
  if( _config->isEleGamma()         ) { vetoElec[0] = false; vetoElec[1] = true ; }
  if( _config->isGammaEle()         ) { vetoElec[0] = true ; vetoElec[1] = false; }
  cout << " --------- veto electron config -----------" << endl;
  cout << " Leading  Pho VetoElec: " << vetoElec[0] << endl;
  cout << " Trailing Pho VetoElec: " << vetoElec[1] << endl;
  

  DoDebugEvent = true;
  
  bool DoPreselection = true;
  //  bool DoPrint = true;
  
  
  TString VertexFileNamePrefix;
  
  TRandom3 *rnd = new TRandom3();
  rnd->SetSeed(0);
  
  /// output tree and cross check file
   _xcheckTextFile.open(TString(filename)+".xcheck.txt");
   // _xcheckTextFile = cout;

  _minitree = new MiniTree( filename );
  TTree * tSkim = 0;
  if( _config->doSkimming() ) tSkim = (TTree*) fChain->CloneTree(0);

  InitHists();
  _minitree->mc_wXsec = _weight_manager->xSecW();
  _minitree->mc_wNgen = 100000./_weight_manager->getNevts();
  if( isData ) {
    _minitree->mc_wXsec = 1;
    _minitree->mc_wNgen = 1;
  }
    
  Int_t isprompt0 = -1;
  Int_t isprompt1 = -1;
  
  set<Long64_t> syncEvt;

  cout <<" ================ mode  "  << mode_   <<" ===============================  "<<endl;
  /// setupType has to be passed via config file
  //  photonOverSmearing overSmearICHEP("Test52_ichep");
  photonOverSmearing overSmearHCP( "oversmear_hcp2012" );
  photonOverSmearing overSmear(    _config->setup()    );
  int overSmearSyst = _config->getEnergyOverSmearingSyst();

  Long64_t nbytes = 0, nb = 0;
  ////////////////////////////////////////////////////////////////////////////
  //////////////////////////// Start the loop ////////////////////////////////
  ////////////////////////////////////////////////////////////////////////////
  vector<int>    nEvts;
  vector<string> nCutName;
  nCutName.push_back("TOTAL          :"); nEvts.push_back(0);
  nCutName.push_back("2 gammas       :"); nEvts.push_back(0);
  nCutName.push_back("triggers       :"); nEvts.push_back(0);
  nCutName.push_back("nan weight     :"); nEvts.push_back(0);
  nCutName.push_back("presel kin cuts:"); nEvts.push_back(0);
  nCutName.push_back("pass 2 gam incl:"); nEvts.push_back(0);
  nCutName.push_back("pass all       :"); nEvts.push_back(0);
  nCutName.push_back("   --> pass 2 gam lep: "); nEvts.push_back(0);
  nCutName.push_back("   --> pass 2 gam vbf: "); nEvts.push_back(0);

  vector<int> selVtxSumPt2(3);  selVtxSumPt2[0] = 0; selVtxSumPt2[1] = -1;   selVtxSumPt2[2] = -1;

  for (Long64_t jentry=entry_start; jentry< entry_stop ; ++jentry) {
    Long64_t ientry = LoadTree(jentry);

    if (ientry < -9999) break;
    if( jentry % 10000 == 0) cout<<"processing event "<<jentry<<endl;
    nb = fChain->GetEntry(jentry);   nbytes += nb;

    /// reset minitree variables
    _minitree->initEvent();

    // study mc truth block
    if( !isData ) {
      fillMCtruthInfo_HiggsSignal();
      _minitree->fillMCtrueOnly();
    }

    /// reco analysis
    unsigned icutlevel = 0;
    nEvts[icutlevel++]++;
    if( nPho < 2 ) continue; 
    nEvts[icutlevel++]++;
    
    /// set synchronisation flag
    if( syncEvt.find(event) != syncEvt.end() ) DoDebugEvent = true;
    else                                       DoDebugEvent = false;
    if( DoDebugEvent ) _xcheckTextFile << "==========================================================" << endl;
    if( DoDebugEvent ) _xcheckTextFile << "================= debugging event: " << event << endl;
    
    /// PU & BSz reweightings
    if( !isData ) {
      int itpu = 1;  /// 0 without OOT PU - 1 with OOT PU
      _minitree->mc_wPU  = _weight_manager->puW( nPU[itpu] );
     // PUwei  = _weight_manager->puWTrue( puTrue[itpu] );      
    }
    hTotEvents->Fill(1,_minitree->mc_wPU);


    
    bool sigWH = false ;
    bool sigZH = false ;    
    int  mc_whzh_type = 0;
    _minitree->mc_wHQT = 1;
    if( isHiggsSignal ) {
      if ( _weight_manager->getCrossSection()->getMCType() == "vh" ) 
      for( Int_t i=0; i < nMC && i <= 1; ++i ) { 
	  if( abs(mcPID[i]) == 24 ) sigWH=true;
	  if( abs(mcPID[i]) == 23 ) sigZH=true;
	}
      if( sigWH ) mc_whzh_type = 1;
      if( sigZH ) mc_whzh_type = 2;
      
      for( Int_t i=0; i<nMC; ++i)
      if ( abs(mcPID[i]) == 25 ) HiggsMCPt   = mcPt[i];

      if( _weight_manager->getCrossSection()->getMCType() == "ggh" && 
	  _config->setup().find( "ReReco2011" ) != string::npos )
	_minitree->mc_wHQT = getHqTWeight(HiggsMCMass, HiggsMCPt);      
    }
    


    
    if ((mode_ == 2 || mode_ ==1 ||  mode_ == 18 || mode_ == 19) && processID==18) continue;      
    
    // Remove double counting in gamma+jets and QCDjets
    
    Int_t mcIFSR_pho = 0;
    Int_t mcPartonic_pho = 0;
    if (mode_ == 1 || mode_ == 2 || mode_ == 3  ||  mode_ == 18 ||  mode_ == 19 ) {
      for (Int_t i=0; i<nMC; ++i) {    
	if (mcPID[i] == 22 && (fabs(mcMomPID[i]) < 6 || mcMomPID[i] == 21)) mcIFSR_pho++;
	if (mcPID[i] == 22 && mcMomPID[i] == 22) mcPartonic_pho++;
      }
    }
    
    // if pythia is used for diphoton.. no IFSR removing from QCD and Gjets!!!!!!      
    if ((mode_==1 || mode_ == 2  ||   mode_ == 18 ) && mcIFSR_pho >= 1 && mcPartonic_pho >=1) continue;
    if ((mode_ == 3 ||  mode_ == 19 )&& mcIFSR_pho == 2) continue;   

 
    bool prompt2= false;
    bool prompt1= false;
    bool prompt0= false;
    vertProb = -1;
    
    if (mode_ == 2  || mode_ == 1    ||   mode_ == 18     ){
      if      ( mcPartonic_pho >= 1 &&  mcIFSR_pho >= 1 ) prompt2 = true;
      else if ( mcPartonic_pho >= 1 &&  mcIFSR_pho == 0 ) prompt1 = true;
      else if ( mcPartonic_pho == 0 &&  mcIFSR_pho == 0 ) prompt0 = true;
    } else if(mode_ == 3 ||  mode_ == 19   ){
      if      ( mcIFSR_pho >= 2 ) prompt2 = true;
      else if ( mcIFSR_pho == 1 ) prompt1 = true;
      else if ( mcIFSR_pho == 0 ) prompt0 = true;
      if( prompt1 ) _minitree->mc_wXsec = 1.3*_weight_manager->xSecW();
    }
    
    if(mode_==1 || mode_==2 || mode_==3 || mode_==18 || mode_==19){
      if(prompt0)isprompt0=1;
      else isprompt0=0;
      if(prompt1)isprompt1=1;
      else isprompt1=0;
    }
    
    if( mode_ == 20 && isZgamma() ) continue;

    /// wei weight is just temporary and may not contain all info.
    float wei = _minitree->mc_wXsec * _minitree->mc_wPU  
      * _minitree->mc_wNgen * _minitree->mc_wHQT;

    if( isData && !PassTriggerSelection() ) continue;      nEvts[icutlevel++]++;
    if( std::isinf( wei ) || std::isnan( wei ) )continue;  nEvts[icutlevel++]++;
    
    
    
    //// ********************* define S4 variable **********************////
    for( int i=0; i<nPho; ++i){
      if( _config->setup() == "ReReco2011" ) phoS4ratio[i] = 1;
      else                                   phoS4ratio[i] = phoE2x2[i] / phoE5x5[i];
    }
    //// ************************************************************* ////

    if( !isData ) {
      //// ************** MC corrections (mostly MC) ******************* //// 
      // 1. energy shifting / smearing
      for( int i=0; i<nPho; ++i)
	if( fabs(phoSCEta[i]) <= 2.5 ) {
	  float smearing = overSmear.randOverSmearing(phoSCEta[i],phoR9[i],isInGAP_EB(i),overSmearSyst);
	  phoRegrE[i] *= (1 + smearing); 
	  phoE[i]     *= (1 + smearing); 
	  /// from MassFactorized in gglobe:   energyCorrectedError[ipho] *=(l.pho_isEB[ipho]) ? 1.07 : 1.045 ;
	  float smearFactor = 1;
	  if( _config->setup() == "ReReco2011" ) smearFactor = fabs(phoSCEta[i]) < 1.45 ? 1.07: 1.045;
	  phoRegrErr[i] *= smearFactor;
	}  
      
      
      // 2. reweighting of photon id variables (R9...)
      for (int i=0; i<nPho; ++i) ReweightMC_phoIdVar(i);
      //// ************************************************************* ////
    }
    
    //// ********** Apply regression energy ************* ////
    float phoStdE[500];
    for( int i=0; i<nPho; ++i)
      if( fabs(phoSCEta[i]) <= 2.5 ) {
	if( isData ){
	  float enCorrSkim = 1;//enScaleSkimEOS.energyScale( phoR9[i], phoSCEta[i], run);
	  float phoEnScale = enScale.energyScale( phoR9[i], phoSCEta[i], run)/enCorrSkim;
	  phoRegrE[i]  *= phoEnScale;
	  phoE[i]      *= phoEnScale;
	}
	phoStdE[i] = phoE[i];
	phoE[i]   = phoRegrE[i];
	
	/// transform calo position abd etaVtx, phiVtx with SC position
	for( int x = 0 ; x < 3; x++ )  phoCaloPos[i][x] = phoSCPos[i][x];
	for( int ivtx = 0 ; ivtx < nVtxBS; ivtx++ ) {
	  TVector3 xxi = getCorPhotonTVector3(i,ivtx);
	  phoEtaVtx[i][ivtx] = xxi.Eta();
	  phoPhiVtx[i][ivtx] = xxi.Phi();
	}
	
	/// additionnal smearing to go to data energy resolution
	phoRegrSmear[i] = phoE[i]*overSmearHCP.meanOverSmearing(phoSCEta[i],phoR9[i],isInGAP_EB(i),0);
	phoEt[i] = phoE[i] / cosh(phoEta[i]);  
      }    
    //// ************************************************* ////
     

    /// lepton selection
    int iElecVtx(-1), iMuonVtx(-1);
    vector<int> elecIndex = selectElectronsHCP2012( wei, iElecVtx );
    vector<int> muonIndex = selectMuonsHCP2012(     wei, iMuonVtx );

    vector<int>             event_vtx; 
    vector<int>             event_ilead ;
    vector<int>             event_itrail;
    vector<TLorentzVector>  event_plead ;
    vector<TLorentzVector>  event_ptrail;
    TLorentzVector leptag;
    
    int lepCat = -1;
    bool exitLoop = false;
    for( int ii = 0     ; ii < nPho ; ++ii ) {
      for( int jj = (ii+1); jj < nPho ; ++jj ) {
	// Preselection 2nd leg
	if (DoPreselection && !preselectPhoton(ii,phoEt[ii])) continue;
	if (DoPreselection && !preselectPhoton(jj,phoEt[jj])) continue;
	
	/// define i, j locally, so when they are inverted this does not mess up the loop
	int i = ii; 
	int j = jj;
	if(phoEt[j] > phoEt[i]){ i = jj; j = ii; }	  
	
	// Select vertex
	int selVtx  = 0;
	TLorentzVector gi,gj;
	double mij(-1);
	
	vector<int> selVtxIncl;      
	if(_config->vtxSelType()==0)
	  selVtxIncl = getSelectedVertex(i,j,true,true );
	else //use sumpt2 ranking
	  selVtxIncl = selVtxSumPt2;
	selVtx = selVtxIncl[0];
	if( selVtx < 0 ) continue;

	/// check lepton tag
	if( muonIndex.size() > 0 ) {
	  //selVtx = iMuonVtx;	  
	  leptag.SetPtEtaPhiM( muPt[muonIndex[0]], muEta[muonIndex[0]], muPhi[muonIndex[0]],0);
	  if( selectTwoPhotons(i,j,selVtx,gi,gj,vetoElec) ) {
	    lepCat = 0;
	  }
	}
	
	/// check electron tag only if muon tag failed
	if( elecIndex.size() > 0 && lepCat == -1 ) {
	  //selVtx = iElecVtx;
	  leptag.SetPtEtaPhiM( elePt[elecIndex[0]], eleEta[elecIndex[0]], elePhi[elecIndex[0]],0);
	  if( selectTwoPhotons(i,j,selVtx,gi,gj,vetoElec) ) {
	    lepCat = 1;
	    if( fabs( (leptag+gi).M() - 91.19 ) < 10 || fabs( (leptag+gj).M() - 91.19 ) < 10 ) lepCat = -1;
	    /// this is not actually the cut, but it should be but ok (dR(pho,eleTrk) > 1 no dR(pho,anyTrk) > 1 )
	    if(phoCiCdRtoTrk[i] < 1 || phoCiCdRtoTrk[j] <1 ) lepCat = -1;
	  }
	}
	

	if( lepCat >= 0 ) {
	  mij = (gi+gj).M();
          if( _config->analysisType() == "MVA" )
	        if( gi.Pt() / mij < 45./120. || gj.Pt() / mij < 30./120. ) lepCat = -1;
          if( _config->analysisType() == "baselineCiC4PF" )
	        if( gi.Pt() / mij < 45./120. || gj.Pt() < 25. ) lepCat = -1;
	  if( leptag.DeltaR(gi) < 1.0  || leptag.DeltaR(gj) < 1.0  ) lepCat = -1;
	}
	if( lepCat >= 0 ) {
	  cout << " ****** keep leptag event pts[photons] i: " << i << " j: " << j << "   -> event: " << ientry <<  endl;
	  cout << "        leptonCat: " << lepCat << endl;
	  /// if one pair passes lepton tag then no need to go further
	  /// fill in variables
	  event_vtx.resize(   1); event_vtx[0]    = selVtx;
	  event_ilead.resize( 1); event_ilead[0]  = i;
	  event_itrail.resize(1); event_itrail[0] = j;
	  event_plead.resize( 1); event_plead[0]  = gi;
	  event_ptrail.resize(1); event_ptrail[0] = gj;
	  exitLoop = true;
	  break;	
	} else {
	  /// inclusive + VBF + MetTag preselection
	  
	  /// apply kinematic cuts
	  if( !selectTwoPhotons(i,j,selVtx,gi,gj,vetoElec) ) continue;
	  /// drop photon pt cuts from inclusive cuts (add them in categorisation only)
	  mij = (gi+gj).M();	
	  if( ! _config->doSkimming() && 
	      ( gi.Pt()     < _config->pt1Cut() || gi.Pt() < _config->pt2Cut() ||
		gi.Pt()/mij < _config->loosePt1MCut() ||
		gj.Pt()/mij < _config->loosePt2MCut() ) ) continue;
	}
	
	/// here i = lead; j = trail (selectTwoPhotons does that)
	/// fill in variables
	event_vtx.push_back( selVtx );
	event_ilead.push_back(   i  );
	event_itrail.push_back(  j  );
	event_plead.push_back(  gi  );
	event_ptrail.push_back( gj  );   	  
      }
      if( exitLoop ) break;
    }
      
    if(event_ilead.size()==0 || event_itrail.size()==0)continue;
    if(event_vtx.size() == 0 ) continue;  // no pairs selected
    nEvts[icutlevel++]++;

    // Now decide which photon-photon pair in the event to select
    // for lepton tag (size of arrays is 1, so dummy selection)
    unsigned int selectedPair = 0;
    float sumEt = -1;
    for (unsigned int p=0; p < event_vtx.size(); p++) {
      float tempSumEt = event_plead[p].Pt() + event_ptrail[p].Pt();
      if( tempSumEt > sumEt) {
	sumEt = tempSumEt;
      selectedPair = p;
      }
    } 
    

    int ilead  = event_ilead[  selectedPair ];
    int itrail = event_itrail[ selectedPair ];
    int selVtx = event_vtx[    selectedPair ];
    TLorentzVector glead  = event_plead[selectedPair];
    TLorentzVector gtrail = event_ptrail[selectedPair];
    TLorentzVector hcand  = glead + gtrail;

    int CAT4 = cat4(phoR9[ilead], phoR9[itrail], phoSCEta[ilead], phoSCEta[itrail]);
    
    if( glead.Pt()  < _config->pt1Cut() ) continue;
    if( gtrail.Pt() < _config->pt2Cut() ) continue;
    if( hcand.M()   < _config->mggCut() ) continue;
    nEvts[icutlevel++]++;

    _minitree->mtree_runNum = run;
    _minitree->mtree_evtNum = event;
    _minitree->mtree_lumiSec = lumis;

    //    TLorentzVector g1,g2;
    //    g1.SetPtEtaPhiM(phoE[ilead ]/cosh(phoEta[ilead]),phoEta[ilead ], phoPhi[ilead ], 0);
    //    g2.SetPtEtaPhiM(phoE[itrail]/cosh(phoEta[ilead]),phoEta[itrail], phoPhi[itrail], 0);
    //    TLorentzVector lgg = g1 + g2;
    //_minitree->mtree_massDefVtx = lgg.M();
    _minitree->mtree_massDefVtx = hcand.M()/sqrt(phoE[ilead]*phoE[itrail])*sqrt(phoStdE[ilead]*phoStdE[itrail]);

    // calc again vertex to get correct vertex probability (can be different from last one in loop)
    vector<int> sortedVertex;
    if(_config->vtxSelType()==0)
      sortedVertex = getSelectedVertex( ilead, itrail, true, true );
    else //use sumpt2 ranking
      sortedVertex = selVtxSumPt2;

    if( sortedVertex.size() < 2 ) sortedVertex.push_back(-1);
    if( sortedVertex.size() < 3 ) sortedVertex.push_back(-1);

    if( lepCat >= 0 ) {
      /// lepton tag
      sortedVertex[0] = selVtx;  
      sortedVertex[1] = -1; 
      sortedVertex[2] = -1; 
      //      vertProb = 1;
    } 

    _minitree->mtree_rho   = rho2012;
    _minitree->mtree_rho25 = rho25;    
    _minitree->mtree_zVtx  = vtxbs[selVtx][2];
    _minitree->mtree_nVtx  = nVtxBS;
    _minitree->mtree_ivtx1 = selVtx;
    _minitree->mtree_ivtx2 = sortedVertex[1];
    _minitree->mtree_ivtx3 = sortedVertex[2];
    _minitree->mtree_vtxProb = vertProb;
    _minitree->mtree_vtxMva  = vertMVA;

    _minitree->mtree_mass  = hcand.M();
    _minitree->mtree_pt    = hcand.Pt();
    _minitree->mtree_piT   = hcand.Pt()/hcand.M();
    _minitree->mtree_y     = hcand.Rapidity();

    /// spin variables
    TLorentzVector gtmp1 = glead;  gtmp1.Boost( -hcand.BoostVector() );
    TLorentzVector gtmp2 = gtrail; gtmp2.Boost( -hcand.BoostVector() );
    _minitree->mtree_cThetaLead_heli  = cos( gtmp1.Angle(hcand.BoostVector()) );
    _minitree->mtree_cThetaTrail_heli = cos( gtmp2.Angle(hcand.BoostVector()) );
    _minitree->mtree_cThetaStar_CS    = 2*(glead.E()*gtrail.Pz() - gtrail.E()*glead.Pz())/(hcand.M()*sqrt(hcand.M2()+hcand.Pt()*hcand.Pt()));
    
    /// fill photon id variables in main tree
    _minitree->mtree_minR9      = +999;
    _minitree->mtree_minPhoIdEB = +999;
    _minitree->mtree_minPhoIdEE = +999;
    _minitree->mtree_maxSCEta   =   -1;
    _minitree->mtree_minSCEta   = +999;
    for( int i = 0 ; i < 2; i++ ) {
      int ipho = -1;
      if( i == 0 ) ipho = ilead;
      if( i == 1 ) ipho = itrail;
      fillPhotonVariablesToMiniTree( ipho, selVtx, i );      
      if( _minitree->mtree_r9[i] < _minitree->mtree_minR9 ) _minitree->mtree_minR9 = _minitree->mtree_r9[i];
      if( fabs( _minitree->mtree_sceta[i] ) <  1.5 &&  _minitree->mtree_mvaid[i] <  _minitree->mtree_minPhoIdEB ) _minitree->mtree_minPhoIdEB = _minitree->mtree_mvaid[i];
      if( fabs( _minitree->mtree_sceta[i] ) >= 1.5 &&  _minitree->mtree_mvaid[i] <  _minitree->mtree_minPhoIdEE ) _minitree->mtree_minPhoIdEE = _minitree->mtree_mvaid[i];
      if( fabs( _minitree->mtree_sceta[i] ) > _minitree->mtree_maxSCEta ) _minitree->mtree_maxSCEta =  fabs(_minitree->mtree_sceta[i]);
      if( fabs( _minitree->mtree_sceta[i] ) < _minitree->mtree_minSCEta ) _minitree->mtree_minSCEta =  fabs(_minitree->mtree_sceta[i]);
    }
    
    //------------ compute diphoton mva (add var to minitree inside function) ----------------//
    massResoCalc.setP4CalPosVtxResoSmear( glead,gtrail, 
					  TVector3(phoCaloPos[ilead ][0], phoCaloPos[ilead ][1],phoCaloPos[ilead ][2]),
					  TVector3(phoCaloPos[itrail][0], phoCaloPos[itrail][1],phoCaloPos[itrail][2]),
					  TVector3(vtxbs[selVtx][0], vtxbs[selVtx][1], vtxbs[selVtx][2]),
					  _minitree->mtree_relResOverE, _minitree->mtree_relSmearing );

    
    _minitree->mtree_massResoTot = massResoCalc.relativeMassResolutionFab_total( vertProb );    
    _minitree->mtree_massResoEng = massResoCalc.relativeMassResolutionFab_energy( );    
    _minitree->mtree_massResoAng = massResoCalc.relativeMassResolutionFab_angular();    
   
    float diphotonmva = DiPhoID_MVA( glead, gtrail, hcand, massResoCalc, vertProb, 
				     _minitree->mtree_mvaid[0],_minitree->mtree_mvaid[1] );

    
    // ---- Start categorisation ---- //
    _minitree->mtree_lepTag  = 0;
    _minitree->mtree_metTag  = 0;
    _minitree->mtree_vbfTag  = 0;
    _minitree->mtree_hvjjTag = 0;

    // 1. lepton tag
    if( lepCat >= 0 ) {
      _minitree->mtree_lepTag = 1;
      _minitree->mtree_lepCat = lepCat;
      _minitree->mtree_fillLepTree  = true;
      // if( lepCat == 0 ) fillMuonTagVariables(lepTag,glead,gtrail,elecIndex[0],selVtx);
      // if( lepCat == 1 ) fillElecTagVariables(lepTag,glead,gtrail,muonIndex[0],selVtx);
    }

    // 3. met tag (For the jet energy regression, MET needs to be corrected first.)
    _minitree->mtree_rawMet    = recoPfMET;
    _minitree->mtree_rawMetPhi = recoPfMETPhi;
    //    if( !isData ) {
      /// bug in data skim, met correction already applied
      //3.1 Soft Jet correction (FC?)    
      applyJEC4SoftJets();
      //3.2 smearing
      if( !isData ) METSmearCorrection(ilead, itrail);
      //3.3 shifting (even in data? but different in data and MC)
      METPhiShiftCorrection();
      //3.4 scaling
      if( isData) METScaleCorrection(ilead, itrail);
      //    }
    _minitree->mtree_corMet    = recoPfMET;
    _minitree->mtree_corMetPhi = recoPfMETPhi;
    
    // 2. dijet tag
    Int_t nVtxJetID = -1;
    if( _config->doPUJetID() ) nVtxJetID = nVtxBS;
    //vector<int> goodJetsIndex = selectJets( ilead, itrail, nVtxJetID, wei, selVtx );
    vector<int> goodJetsIndex = selectJetsJEC(  ilead, itrail, nVtxJetID, wei, selVtx );
    int vbftag(-1),hstratag(-1),catjet(-1);
    dijetSelection( glead, gtrail, goodJetsIndex, wei, selVtx, vbftag, hstratag, catjet);
    _minitree->mtree_vbfTag  = vbftag;
    _minitree->mtree_hvjjTag = hstratag;
    _minitree->mtree_vbfCat  = catjet;      

    // 2x. radion analysis

    // take the very same photon candidates as in the H->GG analysis above
    _minitree->radion_evtNum = event;
    *(_minitree->radion_gamma1) = glead;
    *(_minitree->radion_gamma2) = gtrail;

    vector<int> goodJetsIndexRadion = selectJetsRadion(nVtxJetID, selVtx);
    _minitree->radion_bJetTags->Set(goodJetsIndexRadion.size());
    _minitree->radion_jet_genJetPt        ->Set(goodJetsIndexRadion.size());
    _minitree->radion_jet_eta             ->Set(goodJetsIndexRadion.size());
    _minitree->radion_jet_cef		  ->Set(goodJetsIndexRadion.size());
    _minitree->radion_jet_nef		  ->Set(goodJetsIndexRadion.size());
    _minitree->radion_jet_mef		  ->Set(goodJetsIndexRadion.size());
    _minitree->radion_jet_nconstituents	  ->Set(goodJetsIndexRadion.size());
    _minitree->radion_jet_chf		  ->Set(goodJetsIndexRadion.size());
    _minitree->radion_jet_JECUnc	  ->Set(goodJetsIndexRadion.size());
    _minitree->radion_jet_ptLeadTrack	  ->Set(goodJetsIndexRadion.size());
    _minitree->radion_jet_vtxPt		  ->Set(goodJetsIndexRadion.size());
    _minitree->radion_jet_vtx3dL	  ->Set(goodJetsIndexRadion.size());
    _minitree->radion_jet_SoftLeptPtCut	  ->Set(goodJetsIndexRadion.size());
    _minitree->radion_jet_dPhiMETJet	  ->Set(goodJetsIndexRadion.size());
    _minitree->radion_jet_nch		  ->Set(goodJetsIndexRadion.size());
    _minitree->radion_jet_vtx3deL	  ->Set(goodJetsIndexRadion.size());
    _minitree->radion_jet_vtxMass	  ->Set(goodJetsIndexRadion.size());
    _minitree->radion_jet_ptRaw		  ->Set(goodJetsIndexRadion.size());
    _minitree->radion_jet_EnRaw		  ->Set(goodJetsIndexRadion.size());
    _minitree->radion_jet_SoftLeptptRelCut->Set(goodJetsIndexRadion.size());
    _minitree->radion_jet_SoftLeptdRCut	  ->Set(goodJetsIndexRadion.size());
    _minitree->radion_jet_partonID	  ->Set(goodJetsIndexRadion.size());
    _minitree->radion_jet_dRJetGenJet         ->Set(goodJetsIndexRadion.size());
    _minitree->radion_MET = recoPfMET;
    _minitree->radion_rho25 = rho25;

    for (unsigned i = 0; i < goodJetsIndexRadion.size(); i++) {
      int iJet = goodJetsIndexRadion[i];

      //_minitree->radion_bJetTags->AddAt(jetCombinedSecondaryVtxMVABJetTags[iJet], i);
      _minitree->radion_bJetTags->AddAt(jetCombinedSecondaryVtxBJetTags[iJet], i);
      _minitree->radion_jet_genJetPt         ->AddAt(jetGenJetPt[iJet], i);
      _minitree->radion_jet_eta              ->AddAt(jetEta[iJet], i);
      _minitree->radion_jet_cef		     ->AddAt(jetCEF[iJet], i);
      _minitree->radion_jet_nef		     ->AddAt(jetNEF[iJet], i);
      _minitree->radion_jet_mef		     ->AddAt(jetMEF[iJet], i);
      _minitree->radion_jet_nconstituents    ->AddAt(jetNConstituents[iJet], i);
      _minitree->radion_jet_chf		     ->AddAt(jetCHF[iJet], i);
      _minitree->radion_jet_JECUnc	     ->AddAt(jetJECUnc[iJet], i);
      _minitree->radion_jet_ptLeadTrack	     ->AddAt(jetLeadTrackPt[iJet], i);
      _minitree->radion_jet_vtxPt	     ->AddAt(jetVtxPt[iJet], i);
      _minitree->radion_jet_vtx3dL	     ->AddAt(jetVtx3dL[iJet], i);
      _minitree->radion_jet_SoftLeptPtCut    ->AddAt(jetSoftLeptPt[iJet], i);
      _minitree->radion_jet_nch		     ->AddAt(jetNCH[iJet], i);
      _minitree->radion_jet_vtx3deL	     ->AddAt(jetVtx3deL[iJet], i);
      _minitree->radion_jet_vtxMass	     ->AddAt(jetVtxMass[iJet], i);
      _minitree->radion_jet_ptRaw	     ->AddAt(jetRawPt[iJet], i);
      _minitree->radion_jet_EnRaw	     ->AddAt(jetRawEn[iJet], i);
      _minitree->radion_jet_SoftLeptptRelCut ->AddAt(jetSoftLeptPtRel[iJet], i);
      _minitree->radion_jet_SoftLeptdRCut    ->AddAt(jetSoftLeptdR[iJet], i);
      _minitree->radion_jet_partonID	     ->AddAt(jetPartonID[iJet], i);
      _minitree->radion_jet_dRJetGenJet      ->AddAt(sqrt(pow(jetEta[iJet]-jetGenEta[iJet],2)+pow(jetPhi[iJet]-jetGenPhi[iJet],2)), i);
      float tmpPi = 3.1415927, tmpDPhi=fabs(jetPhi[iJet]-recoPfMETPhi);
      if(tmpDPhi>tmpPi) tmpDPhi=2*tmpPi-tmpDPhi;
      _minitree->radion_jet_dPhiMETJet	     ->AddAt(tmpDPhi, i);

      TLorentzVector* jet = new((*(_minitree->radion_jets))[_minitree->radion_jets->GetEntriesFast()]) TLorentzVector();
      jet->SetPtEtaPhiE(jetPt[iJet], jetEta[iJet], jetPhi[iJet], jetEn[iJet]);
    }

    // Continue step 3.
    if (  MetTagSelection(glead,gtrail,goodJetsIndex) && _minitree->mtree_vbfTag == 0 && _minitree->mtree_lepTag == 0   && 
	 _minitree->mtree_corMet > 70.  &&	 
	 fabs( phoSCEta[ilead] ) < 1.45 && fabs( phoSCEta[itrail]) < 1.45 ) _minitree->mtree_metTag = 1;

    //----------- categorisation (for now incl + vbf + lep + met) -----------//
    _minitree->mtree_catBase = CAT4;
    _minitree->mtree_catMva  = -1;
    for( int icat_mva = 0 ; icat_mva < 4; icat_mva++ )
      if( diphotonmva >= Ddipho_cat[icat_mva] ) { _minitree->mtree_catMva = icat_mva; break; }
    if       ( _minitree->mtree_lepTag == 1 ) {
      _minitree->mtree_catBase = _minitree->mtree_lepCat + 6;
      _minitree->mtree_catMva  = _minitree->mtree_lepCat + 6;
    } else if( _minitree->mtree_vbfTag == 1 ) {
      _minitree->mtree_catBase = _minitree->mtree_vbfCat + 4;
      _minitree->mtree_catMva  = _minitree->mtree_vbfCat + 4;
    } else if( _minitree->mtree_metTag == 1 ) {
      _minitree->mtree_catBase = 8;
      _minitree->mtree_catMva  = 8;
    }
    if( diphotonmva < Ddipho_cat[3] )  _minitree->mtree_catMva  = -1;
    
    /// photon pt cut was dropped from the inclusive cuts
    if(  _minitree->mtree_catMva  < 4 && (glead.Pt()/hcand.M() < 1./3. || gtrail.Pt()/hcand.M() < 1./4.) ) 
       _minitree->mtree_catMva  = -1;

    if(  _minitree->mtree_catBase < 4 && (glead.Pt()/hcand.M() < 1./3. || gtrail.Pt()/hcand.M() < 1./4.) ) 
       _minitree->mtree_catBase  = -1;
    
    //------------ MC weighting factors and corrections    
    if( !isData ) {
      /// needs to be recomputed for each event (because reinit var for each event)
      _minitree->mc_wNgen = 100000./_weight_manager->getNevts();
      _minitree->mc_wXsec  = _weight_manager->xSecW(mc_whzh_type);      
      if( ( mode_ == 3 ||  mode_ == 19 ) && isprompt1 == 1 ) _minitree->mc_wXsec  *= 1.3;
      _minitree->mc_wBSz   = _weight_manager->bszW(vtxbs[selVtx][2]-mcVtx[0][2]);
      _minitree->mc_wVtxId = _weight_manager->vtxPtCorrW( hcand.Pt() );
      
      /// photon identification
      float wPhoId[] = { 1., 1.};
      for( int i = 0 ; i < 2; i++ ) {
	wPhoId[i] = 1;
	int index = -1;
	if( i == 0 ) index = ilead;
	if( i == 1 ) index = itrail;
	wPhoId[i] *= _weight_manager->phoIdPresel(phoR9[index],phoSCEta[index]);
	if( _config->analysisType() == "baselineCiC4PF" ) wPhoId[i] *= _weight_manager->phoIdCiC(phoR9[index],phoSCEta[index]);
	if( _config->analysisType() == "MVA"            ) wPhoId[i] *= _weight_manager->phoIdMVA(phoR9[index],phoSCEta[index]);
	if( vetoElec[i] ) wPhoId[i] *= _weight_manager->phoIdEleVeto(phoR9[index],phoSCEta[index]);	      
      }
      _minitree->mc_wPhoEffi   = wPhoId[0]*wPhoId[1];
      
      /// trigger efficiency
      _minitree->mc_wTrigEffi = 0.9968; /// FIX ME

      /// cross section volontary not included in total weight
      _minitree->mc_wei = 
	_minitree->mc_wPU       *
	_minitree->mc_wBSz      *
	_minitree->mc_wHQT      *  /// = 1 but in 2011
	_minitree->mc_wVtxId    *
	_minitree->mc_wPhoEffi  *
	_minitree->mc_wTrigEffi *
	_minitree->mc_wNgen;

      wei =  _minitree->mc_wei;
    }
    nEvts[icutlevel++]++;
    if( _minitree->mtree_lepTag ) nEvts[icutlevel+0]++;
    if( _minitree->mtree_vbfTag ) nEvts[icutlevel+1]++;
    
    //// following crap can be removed when the synchornization will be successfull. 
    if( DoDebugEvent ) {
      _minitree->setSynchVariables();
      _xcheckTextFile << " pho1 pos: " << phoPos[ilead]  << endl;
      _xcheckTextFile << " ieta1 : " << phoSeedDetId1[ilead] << " iphi1: " << phoSeedDetId2[ilead] << endl;
      _xcheckTextFile << " pho2 pos: " << phoPos[itrail] << endl;
      _xcheckTextFile << " ieta1 : " << phoSeedDetId1[itrail] << " iphi1: " << phoSeedDetId2[itrail] << endl;

      _xcheckTextFile << " oversmear 1: " << overSmear.meanOverSmearing(phoSCEta[ilead],phoR9[ilead]  ,isInGAP_EB(ilead),0) << endl;
      _xcheckTextFile << " oversmear 2: " << overSmear.meanOverSmearing(phoSCEta[itrail],phoR9[itrail],isInGAP_EB(itrail),0) << endl;
      _xcheckTextFile << " mass reso (eng only): " << _minitree->mtree_massResoEng << endl;
      _xcheckTextFile << " mass reso (ang only): " << _minitree->mtree_massResoAng << endl;

      for( unsigned i = 0 ; i < _minitree->sync_iName.size(); i++ )
	cout  << _minitree->sync_iName[i] << ":" << *_minitree->sync_iVal[i]  << "  ";
      for( unsigned i = 0 ; i < _minitree->sync_lName.size(); i++ )
	cout << _minitree->sync_lName[i] << ":" << *_minitree->sync_lVal[i]  << "  ";
      for( unsigned i = 0 ; i < _minitree->sync_fName.size(); i++ )
	cout << _minitree->sync_fName[i] << ":" << *_minitree->sync_fVal[i]  << "  ";
      cout << endl;	
      

      cout << "  myVtx = " << selVtx << "; 1=" << sortedVertex[1] << " 2= " << sortedVertex[2] << endl;
      for( int ivtx = 0; ivtx < nVtxBS; ivtx++ ) {
	cout << " etas[ ivtx = " << ivtx << "] = " << phoEtaVtx[ilead][ivtx] << " - " << phoEtaVtx[itrail][ivtx] << "  - zVtx = " << vtxbs[ivtx][2] << endl;

      }
    }

    _minitree->fill();    
    if( _config->doSkimming() && tSkim ) {
      /// undo all modifs before filling the skim
      fChain->GetEntry(jentry);
      tSkim->Fill();
    }
    //---------------      
    
  //   }    
  }// end for entry
  if( _config->doSkimming() ) {
    _minitree->mtree_file->cd();
    TH1F *hEvents = new TH1F("hEvents","hEvents",2,0,2);
    hEvents->SetBinContent(1,_weight_manager->getNevts());
    hEvents->SetBinContent(2,nEvts[nEvts.size()-1]);
    hEvents->Write();
    tSkim->Write();
    _minitree->mtree_file->Close();
  } else  _minitree->end();

  for( unsigned icut = 0 ; icut < nEvts.size(); icut++ )
    cout << nCutName[icut] << nEvts[icut] << endl;
  
  delete rnd;  

  return nEvts[nEvts.size()-1];
}
コード例 #6
0
StatusCode CorrectECalBarrelSliWinCluster::execute() {
  // Get the input collection with clusters
  const fcc::CaloClusterCollection* inClusters = m_inClusters.get();
  fcc::CaloClusterCollection* correctedClusters = m_correctedClusters.createAndPut();

  // for single particle events compare with truth particles
  TVector3 momentum;
  double phiVertex = 0;
  double etaVertex = 0;
  double thetaVertex = 0;
  double zVertex = 0;
  const auto particle = m_particle.get();
  const auto vertex = m_vertex.get();
  if (particle->size() == 1 && vertex->size() == 1) {
    for(const auto& part : *particle) {
      momentum = TVector3(part.core().p4.px, part.core().p4.py, part.core().p4.pz);
      etaVertex = momentum.Eta();
      phiVertex = momentum.Phi();
      zVertex =  vertex->begin()->position().z;
      thetaVertex = 2 * atan( exp( - etaVertex ) );
    verbose() << " vertex eta " << etaVertex << "   phi = " << phiVertex << " theta = " << thetaVertex << " z = " << zVertex << endmsg;
   }
  }

  // TODO change that so all systems can be used
  uint systemId = m_systemId[0];
  const dd4hep::DDSegmentation::FCCSWGridPhiEta* segmentation = nullptr;
  if (m_segmentationPhiEta[systemId] != nullptr) {
    segmentation = m_segmentationPhiEta[systemId];
  }

  std::vector<TLorentzVector> clustersMassInv;
  std::vector<TLorentzVector> clustersMassInvScaled;
  for (const auto& cluster : *inClusters) {
    double oldEnergy = 0;
    TVector3 pos(cluster.core().position.x, cluster.core().position.y, cluster.core().position.z);
    double oldEta = pos.Eta();
    double oldPhi = pos.Phi();
    for (auto cell = cluster.hits_begin(); cell != cluster.hits_end(); cell++) {
      oldEnergy += cell->core().energy;
    }
    verbose() << " OLD ENERGY = " << oldEnergy << " from " << cluster.hits_size() << " cells" << endmsg;
    verbose() << " OLD CLUSTER ENERGY = " << cluster.core().energy << endmsg;

    // Do everything only using the first defined calorimeter (default: Ecal barrel)
    double oldEtaId = -1;
    double oldPhiId = -1;
    if (m_segmentationPhiEta[systemId] != nullptr) {
      oldEtaId = int(floor((oldEta + 0.5 * segmentation->gridSizeEta() - segmentation->offsetEta()) / segmentation->gridSizeEta()));
      oldPhiId = int(floor((oldPhi + 0.5 * segmentation->gridSizePhi() - segmentation->offsetPhi()) / segmentation->gridSizePhi()));
    }

    // 0. Create new cluster, copy information from input
    fcc::CaloCluster newCluster = correctedClusters->create();
    double energy = 0;
    newCluster.core().position.x = cluster.core().position.x;
    newCluster.core().position.y = cluster.core().position.y;
    newCluster.core().position.z = cluster.core().position.z;
    for (auto cell = cluster.hits_begin(); cell != cluster.hits_end(); cell++) {
      if (m_segmentationMulti[systemId] != nullptr) {
        segmentation = dynamic_cast<const dd4hep::DDSegmentation::FCCSWGridPhiEta*>(&m_segmentationMulti[systemId]->subsegmentation(cell->core().cellId));
        oldEtaId = int(floor((oldEta + 0.5 * segmentation->gridSizeEta() - segmentation->offsetEta()) / segmentation->gridSizeEta()));
        oldPhiId = int(floor((oldPhi + 0.5 * segmentation->gridSizePhi() - segmentation->offsetPhi()) / segmentation->gridSizePhi()));
      }
      if (m_decoder[systemId]->get(cell->core().cellId, "system") == systemId) {
        uint layerId = m_decoder[systemId]->get(cell->core().cellId, "layer");
        if(m_nPhiFinal[layerId] > 0 && m_nEtaFinal[layerId] > 0) {
          uint etaId = m_decoder[systemId]->get(cell->core().cellId, "eta");
          uint phiId = m_decoder[systemId]->get(cell->core().cellId, "phi");
          if ( etaId >= (oldEtaId - m_halfEtaFin[layerId]) &&  etaId <= (oldEtaId + m_halfEtaFin[layerId]) &&
               phiId >= phiNeighbour((oldPhiId - m_halfPhiFin[layerId]), segmentation->phiBins()) &&  phiId <= phiNeighbour((oldPhiId + m_halfPhiFin[layerId]), segmentation->phiBins()) ) {
            if (m_ellipseFinalCluster) {
              if ( pow( (etaId - oldEtaId) / (m_nEtaFinal[layerId] / 2.), 2) + pow( (phiId - oldPhiId) / (m_nPhiFinal[layerId] / 2.), 2) < 1) {
                newCluster.addhits(*cell);
                energy += cell->core().energy;
              }
            } else {
              newCluster.addhits(*cell);
              energy += cell->core().energy;
            }
          }
        }
      }
    }
    newCluster.core().energy = energy;

    // 1. Correct eta position with log-weighting
    double sumEnFirstLayer = 0;
    // get current pseudorapidity
    std::vector<double> sumEnLayer;
    std::vector<double> sumEnLayerSorted;
    std::vector<double> sumEtaLayer;
    std::vector<double> sumWeightLayer;
    sumEnLayer.assign(m_numLayers, 0);
    sumEnLayerSorted.assign(m_numLayers, 0);
    sumEtaLayer.assign(m_numLayers, 0);
    sumWeightLayer.assign(m_numLayers, 0);
    // first check the energy deposited in each layer
    for (auto cell = newCluster.hits_begin(); cell != newCluster.hits_end(); cell++) {
      dd4hep::DDSegmentation::CellID cID = cell->core().cellId;
      uint layer = m_decoder[systemId]->get(cID, m_layerFieldName) + m_firstLayerId;
      sumEnLayer[layer] += cell->core().energy;
    }
    // sort energy to check value of 2nd highest, 3rd highest etc
    for (uint iLayer = 0; iLayer < m_numLayers; iLayer++) {
      sumEnLayerSorted[iLayer] = sumEnLayer[iLayer];
    }
    std::sort(sumEnLayerSorted.begin(),sumEnLayerSorted.end(),std::greater<double>());
    sumEnFirstLayer = sumEnLayer[0];
    // repeat but calculating eta barycentre in each layer
    for (auto cell = newCluster.hits_begin(); cell != newCluster.hits_end(); cell++) {
      if (m_segmentationMulti[systemId] != nullptr) {
        segmentation = dynamic_cast<const dd4hep::DDSegmentation::FCCSWGridPhiEta*>(&m_segmentationMulti[systemId]->subsegmentation(cell->core().cellId));
      }
      dd4hep::DDSegmentation::CellID cID = cell->core().cellId;
      uint layer = m_decoder[systemId]->get(cID, m_layerFieldName) + m_firstLayerId;
      double weightLog = std::max(0., m_etaRecalcLayerWeights[layer] + log(cell->core().energy / sumEnLayer[layer]));
      double eta = segmentation->eta(cell->core().cellId);
      sumEtaLayer[layer] += (weightLog * eta);
      sumWeightLayer[layer] += weightLog;
    }
    // calculate eta position weighting with energy deposited in layer
    // this energy is a good estimator of 1/sigma^2 of (eta_barycentre-eta_MC) distribution
    double layerWeight = 0;
    double sumLayerWeight = 0;
    double sumLayerWeight2point = 0;
    double newEta = 0;
    double newEtaErrorRes = 0;
    double newEtaErrorRes2point = 0;
    for (uint iLayer = 0; iLayer < m_numLayers; iLayer++) {
      if (sumWeightLayer[iLayer] > 1e-10) {
        sumEtaLayer[iLayer] /= sumWeightLayer[iLayer];
        newEta += sumEtaLayer[iLayer] * sumEnLayer[iLayer];
        layerWeight = 1. / (pow(m_etaLayerResolutionSampling[iLayer], 2) / energy +  pow(m_etaLayerResolutionConst[iLayer], 2));
        sumLayerWeight += layerWeight;
        newEtaErrorRes += sumEtaLayer[iLayer] * layerWeight;
        if (iLayer == 1 || iLayer == 2) {
          newEtaErrorRes2point += sumEtaLayer[iLayer] * layerWeight;
          sumLayerWeight2point += layerWeight;
        }
      }
    }
    newEta /= energy;
    newEtaErrorRes /= sumLayerWeight;
    newEtaErrorRes2point /= sumLayerWeight2point;
    // alter Cartesian position of a cluster using new eta position
    double radius = pos.Perp();
    double phi = pos.Phi();
    newCluster.core().position.x = radius * cos(phi);
    newCluster.core().position.y = radius * sin(phi);
    newCluster.core().position.z = radius * sinh(newEta);

    // 2. Correct energy for pileup noise
    uint numCells = newCluster.hits_size();
    double noise = 0;
    if (m_constPileupNoise == 0) {
      noise = getNoiseConstantPerCluster(newEta, numCells) * m_gauss.shoot() * std::sqrt(static_cast<int>(m_mu));
      verbose() << " NUM CELLS = " << numCells << "   cluster noise const = " << getNoiseConstantPerCluster(newEta, numCells)
                << " scaled to PU " << m_mu<< "  = " << getNoiseConstantPerCluster(newEta, numCells)* std::sqrt(static_cast<int>(m_mu)) << endmsg;
    } else {
      noise = m_constPileupNoise * m_gauss.shoot() * std::sqrt(static_cast<int>(m_mu));
    }
    newCluster.core().energy += noise;
    m_hPileupEnergy->Fill(noise);

    // 3. Correct for energy upstream
    // correct for presampler based on energy in the first layer layer:
    // check eta of the cluster and get correction parameters:
    double P00 = 0, P01 = 0, P10 = 0, P11 = 0;
    for (uint iEta = 0; iEta < m_etaBorders.size(); iEta++) {
      if (fabs(newEta) < m_etaBorders[iEta]) {
        P00 = m_presamplerShiftP0[iEta];
        P01 = m_presamplerShiftP1[iEta];
        P10 = m_presamplerScaleP0[iEta];
        P11 = m_presamplerScaleP1[iEta];
        break;
      }
    }
    // if eta is larger than the last available eta values, take the last known parameters
    if (fabs(newEta) > m_etaBorders.back()) {
      warning() << "cluster eta = " << newEta << " is larger than last defined eta values." << endmsg;
      //return StatusCode::FAILURE;
    }
    double presamplerShift = P00 + P01 * cluster.core().energy;
    double presamplerScale = P10 + P11 * sqrt(cluster.core().energy);
    double energyFront = presamplerShift + presamplerScale * sumEnFirstLayer * m_samplingFraction[0];
    m_hUpstreamEnergy->Fill(energyFront);
    newCluster.core().energy += energyFront;

    // Fill histograms
    m_hEnergyPreAnyCorrections->Fill(oldEnergy);
    m_hEnergyPostAllCorrections->Fill(newCluster.core().energy);
    m_hEnergyPostAllCorrectionsAndScaling->Fill(newCluster.core().energy / m_response);

    // Position resolution
    m_hEta->Fill(newEta);
    m_hPhi->Fill(phi);
    verbose() << " energy " << energy << "   numCells = " << numCells << " old energy = " << oldEnergy <<
      " newEta " << newEta << "   phi = " << phi << " theta = " << 2 * atan( exp( - newEta ) ) << endmsg;
    m_hNumCells->Fill(numCells);
    // Fill histograms for single particle events
    if (particle->size() == 1) {
      m_hDiffEta->Fill(newEta - etaVertex);
      m_hDiffEtaResWeight->Fill(newEtaErrorRes - etaVertex);
      m_hDiffEtaResWeight2point->Fill(newEtaErrorRes2point - etaVertex);
      for(uint iLayer = 0; iLayer < m_numLayers; iLayer++) {
        m_hDiffEtaLayer[iLayer]->Fill(sumEtaLayer[iLayer] - etaVertex);
        if (energy > 0)
          m_hEnergyFractionInLayers->Fill(iLayer+1, sumEnLayer[iLayer] / energy);
      }
      m_hDiffPhi->Fill(phi - phiVertex);
    }
  }

  return StatusCode::SUCCESS;
}
コード例 #7
0
ファイル: KVFAZIABlock.cpp プロジェクト: pwigg/kaliveda
KVFAZIABlock::KVFAZIABlock() : TGeoVolumeAssembly("STRUCT_BLOCK")
{
   // Default constructor

   SetMedium(gGeoManager->GetMedium("Vacuum"));//to avoid warnings about STRUCT_BLOCK has dummy medium

   KVMaterial mat_si("Si");
   TGeoMedium *Silicon = mat_si.GetGeoMedium();

   KVMaterial mat_csi("CsI");
   TGeoMedium *CesiumIodide = mat_csi.GetGeoMedium();

   KVMaterial mat_plomb("Lead");
   TGeoMedium *Plomb = mat_plomb.GetGeoMedium();

   TGeoVolumeAssembly* quartet = gGeoManager->MakeVolumeAssembly("STRUCT_QUARTET");
   quartet->SetMedium(gGeoManager->GetMedium("Vacuum"));//to avoid warnings about STRUCT_QUARTET has dummy medium

   TGeoVolume* si = 0;
   TGeoVolume* csi = 0;

   Double_t distance_si2_si1 = 0.220;
   Double_t distance_csi_si2 = 0.434;

   Double_t side_si = 2;
   Double_t side_csi_front = 2.050;
   Double_t side_csi_back = 2.272;

   Double_t inter_si = 0.24;

   Double_t thick_si1 = 300 * KVUnits::um;
   Double_t thick_si2 = 500 * KVUnits::um;
   Double_t thick_csi = 10;

   Double_t adjust_csi = 0.0165;

   Int_t ndet = 1;;
   TGeoTranslation* tr = 0;

   Double_t shift = side_si / 2 + inter_si / 2;
   //printf("%lf\n", shift);

   Double_t coefx[4] = { -1., -1., 1., 1.};
   Double_t coefy[4] = {1., -1., -1., 1.};

   for (Int_t nt = 1; nt <= 4; nt += 1) {

      shift = side_si / 2 + inter_si / 2;

      si = gGeoManager->MakeBox(Form("DET_SI1-T%d", nt), Silicon, side_si / 2, side_si / 2, thick_si1 / 2.);
      tr = new TGeoTranslation(coefx[nt - 1]*shift, coefy[nt - 1]*shift, thick_si1 / 2.);

      quartet->AddNode(si, ndet++, tr);
      ((TGeoNodeMatrix*)quartet->GetNodes()->Last())->SetName(Form("DET_SI1-T%d", nt));

      si = gGeoManager->MakeBox(Form("DET_SI2-T%d", nt), Silicon, side_si / 2, side_si / 2, thick_si2 / 2.);
      tr = new TGeoTranslation(coefx[nt - 1]*shift, coefy[nt - 1]*shift, thick_si2 / 2. + distance_si2_si1);
      quartet->AddNode(si, ndet++, tr);
      ((TGeoNodeMatrix*)quartet->GetNodes()->Last())->SetName(Form("DET_SI2-T%d", nt));

      shift = side_si / 2 + inter_si / 2 + adjust_csi;

      csi = gGeoManager->MakeTrd2(Form("DET_CSI-T%d", nt), CesiumIodide, side_csi_front / 2, side_csi_back / 2, side_csi_front / 2, side_csi_back / 2, thick_csi / 2.);
      tr = new TGeoTranslation(coefx[nt - 1]*shift, coefy[nt - 1]*shift, thick_csi / 2. + distance_csi_si2);
      quartet->AddNode(csi, ndet++, tr);
      ((TGeoNodeMatrix*)quartet->GetNodes()->Last())->SetName(Form("DET_CSI-T%d", nt));

   }

   Int_t nbl = 1;
   TGeoVolume* blindage = 0;
//Double_t thick_bld = thick_si1+distance_si2_si1+thick_si2;
   /* l'epaisseur du si1 est compris dans la distance_si2_si1 */
   Double_t thick_bld = distance_si2_si1 + thick_si2;
   Double_t shift_bld = (side_si + inter_si) / 2.;
///Croix inter quartet
//
// Separation des 4 télescopes
//
//
   blindage = gGeoManager->MakeBox("DEADZONE_BLINDAGE_1", Plomb, inter_si / 2, (side_si + inter_si / 2), thick_bld / 2.);
   //printf("%s\n", blindage->GetMaterial()->GetTitle());
   tr = new TGeoTranslation(0, 0, thick_bld / 2.);
   quartet->AddNode(blindage, nbl++, tr);

   blindage = gGeoManager->MakeBox("DEADZONE_BLINDAGE_2", Plomb, (side_si / 2), inter_si / 2, thick_bld / 2.);
   tr = new TGeoTranslation(-1 * shift_bld, 0, thick_bld / 2.);
   quartet->AddNode(blindage, nbl++, tr);
   tr = new TGeoTranslation(+1 * shift_bld, 0, thick_bld / 2.);
   quartet->AddNode(blindage, nbl++, tr);

///Contour de l ensemble du quartet
//
//Délimiation des bords exterieurs
//
//
   shift_bld = (side_si + inter_si);

   blindage = gGeoManager->MakeBox("DEADZONE_BLINDAGE_3", Plomb, (side_si + inter_si / 2), inter_si / 2, thick_bld / 2.);
   tr = new TGeoTranslation(0, shift_bld, thick_bld / 2.);
   quartet->AddNode(blindage, nbl++, tr);
   tr = new TGeoTranslation(0, -1 * shift_bld, thick_bld / 2.);
   quartet->AddNode(blindage, nbl++, tr);
///
   blindage = gGeoManager->MakeBox("DEADZONE_BLINDAGE_4", Plomb, inter_si / 2, (side_si + inter_si * 1.5), thick_bld / 2.);
   tr = new TGeoTranslation(shift_bld, 0, thick_bld / 2.);
   quartet->AddNode(blindage, nbl++, tr);
   tr = new TGeoTranslation(-1 * shift_bld, 0, thick_bld / 2.);
   quartet->AddNode(blindage, nbl++, tr);

   fTotSidWBlind = 4 * side_si + 5 * inter_si;
//Coordonnées extraite des côtes données par Yvan M.
//vecteur pointant le milieu d un quartet
//X=-2.231625
//Y=-2.230525
//Z=99.950350
// Mag=100.000139
// Theta=1.808104
// Phi = -135.014124
   TVector3* placement = new TVector3(-2.231625, -2.230525, 99.950350);
   TVector3* Centre = new TVector3();

   TGeoRotation rot1, rot2;
   TGeoTranslation trans;
   TGeoTranslation invZtrans(0, 0, -100);

   TGeoHMatrix h;
   TGeoHMatrix* ph = 0;

//Boucle sur les 4 quartets d un block
   Double_t tx[4] = {1, -1, -1, 1};
   Double_t ty[4] = {1, 1, -1, -1};

   Double_t theta = 0;
   Double_t phi = 0;
   Double_t trans_z = 0;

   for (Int_t nq = 1; nq <= 4; nq += 1) {

      Centre->SetXYZ(placement->X()*tx[nq - 1], placement->Y()*ty[nq - 1], placement->Z());

      theta = Centre->Theta() * TMath::RadToDeg();
      phi = Centre->Phi() * TMath::RadToDeg();

      trans_z = Centre->Mag() + thick_si1 / 2.;

      rot2.SetAngles(phi + 90., theta, 0.);
      rot1.SetAngles(-1.*phi, 0., 0.);
      trans.SetDz(trans_z);

      h = invZtrans * rot2 * trans * rot1;
      ph = new TGeoHMatrix(h);

      AddNode(quartet, nq, ph);
   }
}
コード例 #8
0
ファイル: HwwDYBkgEstimate.C プロジェクト: sixie/EWKAna
void HwwDYBkgEstimate(const string inputFilename, Double_t mHiggs,
                 const string Label) 
{  
  gBenchmark->Start("WWTemplate");

  
  //--------------------------------------------------------------------------------------------------------------
  // Settings 
  //==============================================================================================================
  
  Double_t lumi = 35.5;              // luminosity (pb^-1)
  Int_t ChargeSelection = 0;
//   ChargeSelection = 1;
    
  Double_t fPtMaxLowerCut;
  Double_t fPtMinLowerCut;
  Double_t fDileptonMassUpperCut;
  Double_t fDeltaPhiCut;

  Double_t fHiggsMass = mHiggs;

  //Configure Higgs Mass Dependant Cuts
  if (fHiggsMass == 120) { fPtMaxLowerCut = 20.0;        fPtMinLowerCut = 20.0; 
                           fDileptonMassUpperCut = 40.0; fDeltaPhiCut = 60.0;
  }
  if (fHiggsMass == 130) { fPtMaxLowerCut = 25.0;        fPtMinLowerCut = 20.0;
                           fDileptonMassUpperCut = 45.0; fDeltaPhiCut = 60.0;
  }
  if (fHiggsMass == 140) { fPtMaxLowerCut = 25.0;        fPtMinLowerCut = 20.0;
                           fDileptonMassUpperCut = 45.0; fDeltaPhiCut = 60.0;
  }
  if (fHiggsMass == 150) { fPtMaxLowerCut = 27.0;        fPtMinLowerCut = 25.0;
                           fDileptonMassUpperCut = 50.0; fDeltaPhiCut = 60.0;
  }
  if (fHiggsMass == 160) { fPtMaxLowerCut = 30.0;        fPtMinLowerCut = 25.0;
                           fDileptonMassUpperCut = 50.0; fDeltaPhiCut = 60.0;
  }
  if (fHiggsMass == 170) { fPtMaxLowerCut = 34.0;        fPtMinLowerCut = 25.0;
                           fDileptonMassUpperCut = 50.0; fDeltaPhiCut = 60.0;
  }
  if (fHiggsMass == 180) { fPtMaxLowerCut = 36.0;        fPtMinLowerCut = 25.0;
                           fDileptonMassUpperCut = 60.0; fDeltaPhiCut = 70.0;
  }
  if (fHiggsMass == 190) { fPtMaxLowerCut = 38.0;        fPtMinLowerCut = 25.0;
                           fDileptonMassUpperCut = 80.0; fDeltaPhiCut = 90.0;
  }
  if (fHiggsMass == 200) { fPtMaxLowerCut = 40.0;        fPtMinLowerCut = 25.0;
                           fDileptonMassUpperCut = 90.0; fDeltaPhiCut = 100.0;
  }
  if (fHiggsMass == 210) { fPtMaxLowerCut = 44.0;         fPtMinLowerCut = 25.0;
                           fDileptonMassUpperCut = 110.0; fDeltaPhiCut = 110.0;
  }
  if (fHiggsMass == 220) { fPtMaxLowerCut = 48.0;         fPtMinLowerCut = 25.0;
                           fDileptonMassUpperCut = 120.0; fDeltaPhiCut = 120.0;
  }
  if (fHiggsMass == 230) { fPtMaxLowerCut = 52.0;         fPtMinLowerCut = 25.0;
                           fDileptonMassUpperCut = 130.0; fDeltaPhiCut = 130.0;
  }
  if (fHiggsMass == 250) { fPtMaxLowerCut = 55.0;         fPtMinLowerCut = 25.0;
                           fDileptonMassUpperCut = 150.0; fDeltaPhiCut = 140.0;
  }
  if (fHiggsMass == 300) { fPtMaxLowerCut = 70.0;         fPtMinLowerCut = 25.0;
                           fDileptonMassUpperCut = 200.0; fDeltaPhiCut = 175.0;
  }
  if (fHiggsMass == 350) { fPtMaxLowerCut = 80.0;         fPtMinLowerCut = 25.0;
                           fDileptonMassUpperCut = 250.0; fDeltaPhiCut = 175.0;
  }
  if (fHiggsMass == 400) { fPtMaxLowerCut = 90.0;         fPtMinLowerCut = 25.0;
                           fDileptonMassUpperCut = 300.0; fDeltaPhiCut = 175.0;
  }
  if (fHiggsMass == 450) { fPtMaxLowerCut = 110.0;        fPtMinLowerCut = 25.0;
                           fDileptonMassUpperCut = 350.0; fDeltaPhiCut = 175.0;
  }
  if (fHiggsMass == 500) { fPtMaxLowerCut = 120.0;        fPtMinLowerCut = 25.0;
                           fDileptonMassUpperCut = 400.0; fDeltaPhiCut = 175.0;
  }
  if (fHiggsMass == 550) { fPtMaxLowerCut = 130.0;        fPtMinLowerCut = 25.0;
                           fDileptonMassUpperCut = 450.0; fDeltaPhiCut = 175.0;
  }
  if (fHiggsMass == 600) { fPtMaxLowerCut = 140.0;        fPtMinLowerCut = 25.0;
                           fDileptonMassUpperCut = 500.0; fDeltaPhiCut = 175.0;
  }


  //--------------------------------------------------------------------------------------------------------------
  // Histograms
  //==============================================================================================================  
  TH1D *DileptonMass_allOtherCuts_ee = new TH1D("DileptonMass_allOtherCuts_ee", ";Mass_{ll};Number of Events",150,0.,300.);
  TH1D *DileptonMass_allOtherCuts_emu = new TH1D("DileptonMass_allOtherCuts_emu", ";Mass_{ll};Number of Events",150,0.,300.);
  TH1D *DileptonMass_allOtherCuts_mumu = new TH1D("DileptonMass_allOtherCuts_mumu", ";Mass_{ll};Number of Events",150,0.,300.);
  TH1D *DileptonMass_allOtherCutsExceptMetCut_ee = new TH1D("DileptonMass_allOtherCutsExceptMetCut_ee", ";Mass_{ll};Number of Events",150,0.,300.);
  TH1D *DileptonMass_allOtherCutsExceptMetCut_emu = new TH1D("DileptonMass_allOtherCutsExceptMetCut_emu", ";Mass_{ll};Number of Events",150,0.,300.);
  TH1D *DileptonMass_allOtherCutsExceptMetCut_mumu = new TH1D("DileptonMass_allOtherCutsExceptMetCut_mumu", ";Mass_{ll};Number of Events",150,0.,300.);

  Double_t NEventsIn_BeforeMetCut_ee = 0;
  Double_t NEventsIn_BeforeMetCut_em = 0;
  Double_t NEventsIn_BeforeMetCut_mm = 0;
  Double_t NEventsOut_BeforeMetCut_ee = 0;
  Double_t NEventsOut_BeforeMetCut_em = 0;
  Double_t NEventsOut_BeforeMetCut_mm = 0;
  Double_t NEventsIn_AfterMetCut_ee = 0;
  Double_t NEventsIn_AfterMetCut_em = 0;
  Double_t NEventsIn_AfterMetCut_mm = 0;
  Double_t NEventsOut_AfterMetCut_ee = 0;
  Double_t NEventsOut_AfterMetCut_em = 0;
  Double_t NEventsOut_AfterMetCut_mm = 0;


  //--------------------------------------------------------------------------------------------------------------
  // Main analysis code 
  //==============================================================================================================  
  
  //
  // Access samples and fill histograms
  TFile *inputFile=0;
  TTree *eventTree=0;  
   
  // Data structures to store info from TTrees
  mithep::TEventInfo *info    = new mithep::TEventInfo();
  TClonesArray *electronArr = new TClonesArray("mithep::TElectron");
  TClonesArray *muonArr = new TClonesArray("mithep::TMuon");
  TClonesArray *jetArr = new TClonesArray("mithep::TJet");
  
  //********************************************************
  // Good RunLumi Selection
  //********************************************************
  Bool_t hasJSON = kTRUE;
  mithep::RunLumiRangeMap rlrm;
//   rlrm.AddJSONFile("Cert_TopOct22_Merged_135821-148058_allPVT.txt"); 
   rlrm.AddJSONFile("Cert_136033-149442_7TeV_Dec22ReReco_Collisions10_JSON_v3.txt"); 
   hasJSON = kFALSE;

  //********************************************************
  // Get Tree
  //********************************************************
  eventTree = getTreeFromFile(inputFilename.c_str(),"Events"); 
  TBranch *infoBr;
  TBranch *electronBr;
  TBranch *muonBr;
  TBranch *jetBr;


  //*****************************************************************************************
  //Loop over muon Data Tree
  //*****************************************************************************************
  // Set branch address to structures that will store the info  
  eventTree->SetBranchAddress("Info",       &info);      infoBr       = eventTree->GetBranch("Info");
  eventTree->SetBranchAddress("Electron", &electronArr); electronBr = eventTree->GetBranch("Electron");
  eventTree->SetBranchAddress("Muon", &muonArr);         muonBr = eventTree->GetBranch("Muon");
  eventTree->SetBranchAddress("PFJet", &jetArr);         jetBr = eventTree->GetBranch("PFJet");
  
  for(UInt_t ientry=0; ientry<eventTree->GetEntries(); ientry++) {       	
    infoBr->GetEntry(ientry);
    if (ientry % 100000 == 0) cout << "Event " << ientry << endl;
		
    mithep::RunLumiRangeMap::RunLumiPairType rl(info->runNum, info->lumiSec);      
    if(hasJSON && !rlrm.HasRunLumi(rl)) continue;  // not certified run? Skip to next event...
     
    //for the skimmed input, I already required the HLT bits.
    //    if (!passHLT(info->triggerBits, info->runNum, kTRUE)) continue;

    //********************************************************
    // Load the branches
    //********************************************************
    electronArr->Clear(); 
    muonArr->Clear(); 
    jetArr->Clear(); 
    electronBr->GetEntry(ientry);
    muonBr->GetEntry(ientry);
    jetBr->GetEntry(ientry);

    //event weight
    Double_t eventweight = info->eventweight * lumi;

    //********************************************************
    // TcMet
    //********************************************************
    TVector3 met;        
    if(info->tcMEx!=0 || info->tcMEy!=0) {       
      met.SetXYZ(info->tcMEx, info->tcMEy, 0);
    }

    //********************************************************
    // TcMet
    //********************************************************

    Int_t NSoftMuons = 0;
    Int_t NLeptons = 0;
    vector<Int_t> leptonType;
    vector<Int_t> leptonIndex;
    vector<Double_t> leptonPt;
    vector<Double_t> leptonEta;
    vector<Double_t> leptonPhi;
    vector<Int_t> leptonCharge;

    Int_t NJets = 0;
    const mithep::TJet *leadingJet = 0;
    
    for(Int_t i=0; i<muonArr->GetEntries(); i++) {
      const mithep::TMuon *mu = (mithep::TMuon*)((*muonArr)[i]);      
      if ( (0==0)
           &&
           passMuonCuts(mu)
           &&
           fabs(mu->eta) < 2.4
           && 
           mu->pt > 10.0
        ) {
        leptonPt.push_back(mu->pt);
        leptonEta.push_back(mu->eta);
        leptonPhi.push_back(mu->phi);
        leptonType.push_back(13);
        leptonIndex.push_back(i);  
        leptonCharge.push_back(mu->q);
      }
    }
    //soft muons
    for(Int_t i=0; i<muonArr->GetEntries(); i++) {
      const mithep::TMuon *mu = (mithep::TMuon*)((*muonArr)[i]);
      Bool_t isCleanMuon = kFALSE;
      for (int k=0; k<leptonPt.size(); ++k) {
        if ( leptonType[k] == 13 
             && mithep::MathUtils::DeltaR(mu->phi, mu->eta, leptonPhi[k],leptonEta[k]) < 0.1
          ) {
          isCleanMuon = kTRUE; 
          break;
        }
      }
      if ( mu->pt > 3.0
           && (mu->qualityBits & kTMLastStationAngTight)
           && mu->nTkHits > 10
           && fabs(mu->d0) < 0.2
           && (mu->typeBits & kTracker)
           && !isCleanMuon
        ) {
        NSoftMuons++;
      }
    }
    for(Int_t i=0; i<electronArr->GetEntries(); i++) {
      const mithep::TElectron *ele = (mithep::TElectron*)((*electronArr)[i]);
      Bool_t isMuonOverlap = kFALSE;
      for (int k=0; k<leptonPt.size(); ++k) {
        if ( leptonType[k] == 13 
             && mithep::MathUtils::DeltaR(ele->phi, ele->eta, leptonPhi[k],leptonEta[k]) < 0.1
          ) {
          isMuonOverlap = kTRUE; 
          break;
        }        
      }

      if ( (0==0)
           && 
           passElectronCuts(ele)
           &&
           fabs(ele->eta) < 2.5
           && 
           ele->pt > 10.0
           &&
           !isMuonOverlap
        ) {
        leptonPt.push_back(ele->pt);
        leptonEta.push_back(ele->eta);
        leptonPhi.push_back(ele->phi);
        leptonType.push_back(11);
        leptonIndex.push_back(i);
        leptonCharge.push_back(ele->q);
      }
    }


    //sort leptons
    Int_t tempType;
    Int_t tempIndex;
    Double_t tempPt;
    Double_t tempEta;
    Double_t tempPhi;
    Int_t tempCharge;
    for (int l=0; l<leptonIndex.size(); l++) {
      for (int k=0; k < leptonIndex.size() - 1; k++) {
        if (leptonPt[k+1] > leptonPt[k]) {
          tempType = leptonType[k];
          tempIndex = leptonIndex[k];
          tempPt = leptonPt[k];
          tempEta = leptonEta[k];
          tempPhi = leptonPhi[k];
          tempCharge = leptonCharge[k];
          
          leptonType[k] = leptonType[k+1];
          leptonIndex[k] = leptonIndex[k+1];
          leptonPt[k] = leptonPt[k+1];
          leptonEta[k] = leptonEta[k+1];
          leptonPhi[k] = leptonPhi[k+1];
          leptonCharge[k] = leptonCharge[k+1];

          leptonType[k+1] = tempType;
          leptonIndex[k+1] = tempIndex;
          leptonPt[k+1] = tempPt;
          leptonEta[k+1] = tempEta;
          leptonPhi[k+1] = tempPhi;
          leptonCharge[k+1] = tempCharge;
          
        }
      }
    }

    double maxBtag = -99999;
    for(Int_t i=0; i<jetArr->GetEntries(); i++) {
      const mithep::TJet *jet = (mithep::TJet*)((*jetArr)[i]);

      Bool_t leptonOverlap = kFALSE;
      for (int k=0; k<leptonPt.size(); ++k) {
        if (mithep::MathUtils::DeltaR(jet->phi, jet->eta, leptonPhi[k],leptonEta[k]) < 0.3) {
          leptonOverlap = kTRUE;
        }
      }

      if (!leptonOverlap) {
        if (jet->pt > 25 && fabs(jet->eta) < 5.0 ) {
          if (!leadingJet || jet->pt > leadingJet->pt) {
            leadingJet = jet;
          }
          NJets++;
        } else {
          if (jet->TrackCountingHighEffBJetTagsDisc > maxBtag ) maxBtag = jet->TrackCountingHighEffBJetTagsDisc;
        }
      }
    }


    //******************************************************************************
    //dilepton preselection
    //******************************************************************************
    if (leptonPt.size() < 2) continue;
    if (!(leptonPt[0] > 20.0 && leptonPt[1] > 10.0)) continue;

    for(int i = 0; i < leptonPt.size(); ++i) {
      for(int j = i+1; j < leptonPt.size(); ++j) {

        //require opposite sign
        if ((ChargeSelection == 0 && leptonCharge[i] == leptonCharge[j]) || (ChargeSelection == 1 && leptonCharge[0] != leptonCharge[j])) continue;


        Int_t finalState = -1;
        if (leptonType[i] == 11 && leptonType[j] == 11) {
          finalState = 0;
        } else if (leptonType[i] == 13 && leptonType[j] == 13) {
          finalState = 1;
        } else if (leptonType[i] == 11 && leptonType[j] == 13) {
          finalState = 2;
        } else if (leptonType[i] == 13 && leptonType[j] == 11) {
          finalState = 3;
        }


        //***********************************************************************************************
        //|Z_vert-Z_l| maximum
        //***********************************************************************************************
        double zDiffMax = 0.0;
       
        double dz_i = 0;
        if (leptonType[0] == 11) {
          dz_i = ((mithep::TElectron*)((*electronArr)[leptonIndex[i]]))->dz;
        } else {
          dz_i = ((mithep::TMuon*)((*muonArr)[leptonIndex[i]]))->dz;
        }
        if (dz_i > zDiffMax) zDiffMax = dz_i;
    
        double dz_j;
        if (leptonType[j] == 11) {
          dz_j = ((mithep::TElectron*)((*electronArr)[leptonIndex[j]]))->dz;
        } else {
          dz_j = ((mithep::TMuon*)((*muonArr)[leptonIndex[j]]))->dz;
        }
        if (dz_j > zDiffMax) zDiffMax = dz_j;
        //szDiffMax = fabs(dz_i - dz_j);

        //******************************************************************************
        //construct event variables
        //******************************************************************************
        mithep::FourVectorM lepton1;
        mithep::FourVectorM lepton2;
        if (leptonType[i] == 11) {
          lepton1.SetCoordinates(leptonPt[i], leptonEta[i], leptonPhi[i], 0.51099892e-3 );
        } else {
          lepton1.SetCoordinates(leptonPt[i], leptonEta[i], leptonPhi[i], 105.658369e-3 );
        }
        if (leptonType[j] == 11) {
          lepton2.SetCoordinates(leptonPt[j], leptonEta[j], leptonPhi[j], 0.51099892e-3 );
        } else {
          lepton2.SetCoordinates(leptonPt[j], leptonEta[j], leptonPhi[j], 105.658369e-3 );
        }
        mithep::FourVectorM dilepton = lepton1+lepton2;

        double deltaPhiLeptons = mithep::MathUtils::DeltaPhi(lepton1.Phi(), 
                                                             lepton2.Phi())* 180.0 / TMath::Pi();    
        double deltaPhiDileptonMet = mithep::MathUtils::DeltaPhi(met.Phi(), 
                                                                 dilepton.Phi())*180.0 / TMath::Pi();    
        double mtHiggs = TMath::Sqrt(2.0*dilepton.Pt() * met.Phi()*
                                     (1.0 - cos(deltaPhiDileptonMet * TMath::Pi() / 180.0)));

        //angle between MET and closest lepton
        double deltaPhiMetLepton[2] = {mithep::MathUtils::DeltaPhi(met.Phi(), lepton1.Phi()),
                                       mithep::MathUtils::DeltaPhi(met.Phi(), lepton2.Phi())};
  
        double mTW[2] = {TMath::Sqrt(2.0*lepton1.Pt()*met.Pt()*
                                     (1.0 - cos(deltaPhiMetLepton[0]))),
                         TMath::Sqrt(2.0*lepton2.Pt()*met.Pt()*
                                     (1.0 - cos(deltaPhiMetLepton[1])))};

        double minDeltaPhiMetLepton = (deltaPhiMetLepton[0] < deltaPhiMetLepton[1])?
          deltaPhiMetLepton[0]:deltaPhiMetLepton[1];

        double METdeltaPhilEt = met.Pt();
        if(minDeltaPhiMetLepton < TMath::Pi()/2.)
          METdeltaPhilEt = METdeltaPhilEt * sin(minDeltaPhiMetLepton);

    
        //*********************************************************************************************
        //Define Cuts
        //*********************************************************************************************
        const int nCuts = 14;
        bool passCut[nCuts] = {false, false, false, false, false, false, false, false, false, false,
                               false, false, false, false};
  
        if(lepton1.Pt() >  20.0 &&
           lepton2.Pt() >= 10.0) passCut[0] = true;

        if(zDiffMax < 1.0)                    passCut[1] = true;
  
        if(met.Pt()    > 20.0)               passCut[2] = true;
  
        if(dilepton.M() > 12.0)            passCut[3] = true;
   
        if (finalState == 0 || finalState == 1){ // mumu/ee
          if(fabs(dilepton.M()-91.1876)   > 15.0)   passCut[4] = true;
          if(METdeltaPhilEt > 35) passCut[5] = true;
        }
        else if(finalState == 2 ||finalState == 3 ) { // emu
          passCut[4] = true;
          if(METdeltaPhilEt > 35) passCut[5] = true;
        }

        if(NJets     < 1)              passCut[6] = true;
        
        if (NSoftMuons == 0 )      passCut[7] = true;

        if (!(leptonPt.size() >= 3 && leptonPt[2] > 10.0)) passCut[8] = true;

        if(maxBtag < 2.1)                     passCut[9] = true;

        if (lepton1.Pt() > fPtMaxLowerCut) passCut[10] = true;
        if (lepton2.Pt() > fPtMinLowerCut) passCut[11] = true;
        if (dilepton.M() < fDileptonMassUpperCut)   passCut[12] = true;
        if (deltaPhiLeptons < fDeltaPhiCut) passCut[13] = true;

        //*********************************************************************************************
        //Make Selection Histograms. Number of events passing each level of cut
        //*********************************************************************************************  
        bool passAllCuts = true;
        for(int c=0; c<nCuts; c++) passAllCuts = passAllCuts & passCut[c];
    
  
        //*****************************************************************************************
        //Make Histograms Before Met Cut
        //*****************************************************************************************
        if (passCut[0] && passCut[1] && passCut[3] && passCut[6] &&passCut[7] && passCut[8] && passCut[9] 
//             && passCut[10] && passCut[11] && passCut[13] 
          ) {

          if (finalState == 0) {
            DileptonMass_allOtherCutsExceptMetCut_ee->Fill(dilepton.M());
            if(fabs(dilepton.M()-91.1876)   > 15.0) {
              NEventsOut_BeforeMetCut_ee++;
            } else {
              NEventsIn_BeforeMetCut_ee++;
            }

          } else if (finalState == 1) {
            DileptonMass_allOtherCutsExceptMetCut_mumu->Fill(dilepton.M());
            if(fabs(dilepton.M()-91.1876)   > 15.0) {
              NEventsOut_BeforeMetCut_mm++;
            } else {
              NEventsIn_BeforeMetCut_mm++;
            }

          } else {
            DileptonMass_allOtherCutsExceptMetCut_emu->Fill(dilepton.M());
            if(fabs(dilepton.M()-91.1876)   > 15.0) {
              NEventsOut_BeforeMetCut_em++;
            } else {
              NEventsIn_BeforeMetCut_em++;
            }
          }        
        }

        //*****************************************************************************************
        //Make Histograms  
        //*****************************************************************************************
        if (passCut[0] && passCut[1] && passCut[2] && passCut[3] && passCut[5] &&passCut[6] &&passCut[7] && passCut[8] && passCut[9] 
//             && passCut[10] && passCut[11] && passCut[13] 
          ) {

          if (finalState == 0) {
            DileptonMass_allOtherCuts_ee->Fill(dilepton.M());
            if(fabs(dilepton.M()-91.1876)   > 15.0) {
              NEventsOut_AfterMetCut_ee++;
            } else {
              NEventsIn_AfterMetCut_ee++;
              cout << info->runNum << " " << info->lumiSec << " " << info->evtNum << " : " << dilepton.M() << " " 
                   << finalState << " : " << lepton1.Pt() << " " << lepton1.Eta() << " " << lepton1.Phi() << " : " 
                   << " : " << lepton2.Pt() << " " << lepton2.Eta() << " " << lepton2.Phi() << " \n" ;
            }
          } else if (finalState == 1) {
            DileptonMass_allOtherCuts_mumu->Fill(dilepton.M());
            if(fabs(dilepton.M()-91.1876)   > 15.0) {
              NEventsOut_AfterMetCut_mm++;
            } else {
              NEventsIn_AfterMetCut_mm++;
              cout << info->runNum << " " << info->lumiSec << " " << info->evtNum << " : " << dilepton.M() << " " 
                   << finalState << " : " << lepton1.Pt() << " " << lepton1.Eta() << " " << lepton1.Phi() << " : " 
                   << " : " << lepton2.Pt() << " " << lepton2.Eta() << " " << lepton2.Phi() << " \n" ;
            }
          } else {
            DileptonMass_allOtherCuts_emu->Fill(dilepton.M());
            if(fabs(dilepton.M()-91.1876)   > 15.0) {
              NEventsOut_AfterMetCut_em++;
            } else {
              NEventsIn_AfterMetCut_em++;
              cout << info->runNum << " " << info->lumiSec << " " << info->evtNum << " : " << dilepton.M() << " " 
                   << finalState << " : " << lepton1.Pt() << " " << lepton1.Eta() << " " << lepton1.Phi() << " : " 
                   << " : " << lepton2.Pt() << " " << lepton2.Eta() << " " << lepton2.Phi() << " \n" ;
            }
          }        
        }



      }
    }
  

  } //end loop over data     



  delete info;
  delete electronArr;
  delete muonArr;
  delete jetArr;


  //--------------------------------------------------------------------------------------------------------------
  // Make plots
  //==============================================================================================================
  TCanvas *cv = new TCanvas("cv","cv", 800,600);

  //--------------------------------------------------------------------------------------------------------------
  // Summary print out
  //============================================================================================================== 



  cout << "Before Met Cut\n";
  cout << "Number of Events in Z window : (ee) " << NEventsIn_BeforeMetCut_ee << " (mm) " << NEventsIn_BeforeMetCut_mm << endl;
  cout << "Number of Events out of Z window : (ee) " << NEventsOut_BeforeMetCut_ee << " (mm) " << NEventsOut_BeforeMetCut_mm << endl;
  cout << "Ratio Out/In : (ee) " << NEventsOut_BeforeMetCut_ee / NEventsIn_BeforeMetCut_ee << " (mm) "
       << NEventsOut_BeforeMetCut_mm / NEventsIn_BeforeMetCut_mm << endl; 


  cout << "After Met Cut\n";
  cout << "Number of Events in Z window : (ee) " << NEventsIn_AfterMetCut_ee << " (mm) " 
       << NEventsIn_AfterMetCut_mm << " (em) " << NEventsIn_AfterMetCut_em << endl;
  cout << "Number of Events out of Z window : (ee) " << NEventsOut_AfterMetCut_ee << " (mm) " 
       << NEventsOut_AfterMetCut_mm << " (em) " << NEventsOut_AfterMetCut_em << endl;








  //--------------------------------------------------------------------------------------------------------------
  // Save Histograms;
  //============================================================================================================== 
  TFile *file = new TFile("HwwSelectionPlots.root", "RECREATE");
  
  
  file->WriteTObject(DileptonMass_allOtherCuts_ee ,DileptonMass_allOtherCuts_ee->GetName(), "WriteDelete");
  file->WriteTObject(DileptonMass_allOtherCuts_mumu ,DileptonMass_allOtherCuts_mumu->GetName(), "WriteDelete");
  file->WriteTObject(DileptonMass_allOtherCuts_emu ,DileptonMass_allOtherCuts_emu->GetName(), "WriteDelete");

  file->WriteTObject(DileptonMass_allOtherCutsExceptMetCut_ee ,DileptonMass_allOtherCutsExceptMetCut_ee->GetName(), "WriteDelete");
  file->WriteTObject(DileptonMass_allOtherCutsExceptMetCut_mumu ,DileptonMass_allOtherCutsExceptMetCut_mumu->GetName(), "WriteDelete");
  file->WriteTObject(DileptonMass_allOtherCutsExceptMetCut_emu ,DileptonMass_allOtherCutsExceptMetCut_emu->GetName(), "WriteDelete");
  file->Close();
  delete file;

        
  gBenchmark->Show("WWTemplate");       
} 
コード例 #9
0
ファイル: RecoInfoExport.C プロジェクト: kurthill/analysis
int
RecoInfoExport::process_event(PHCompositeNode *topNode)
{
  ++_event;

  stringstream fname;
  fname << _file_prefix << "_Event" << _event << ".dat";
  fstream fdata(fname.str(), ios_base::out);

  for (auto & calo_name : _calo_names)
    {
      string towernodename = "TOWER_CALIB_" + calo_name;
      // Grab the towers
      RawTowerContainer* towers = findNode::getClass<RawTowerContainer>(topNode,
          towernodename.c_str());
      if (!towers)
        {
          std::cout << PHWHERE << ": Could not find node "
              << towernodename.c_str() << std::endl;
          return Fun4AllReturnCodes::ABORTRUN;
        }
      string towergeomnodename = "TOWERGEOM_" + calo_name;
      RawTowerGeomContainer *towergeom = findNode::getClass<
          RawTowerGeomContainer>(topNode, towergeomnodename.c_str());
      if (!towergeom)
        {
          cout << PHWHERE << ": Could not find node "
              << towergeomnodename.c_str() << endl;
          return Fun4AllReturnCodes::ABORTRUN;
        }

      set<const RawTower *> good_towers;

      RawTowerContainer::ConstRange begin_end = towers->getTowers();
      RawTowerContainer::ConstIterator rtiter;
      for (rtiter = begin_end.first; rtiter != begin_end.second; ++rtiter)
        {
          const RawTower *tower = rtiter->second;
          assert(tower);
          if (tower->get_energy() > _tower_threshold)
            {
              good_towers.insert(tower);
            }
        }

      fdata
          << (boost::format("%1% (1..%2% hits)") % calo_name
              % good_towers.size()) << endl;

      bool first = true;
      for (const auto & tower : good_towers)
        {
          assert(tower);

          float eta = towergeom->get_etacenter(tower->get_bineta());
          float phi = towergeom->get_phicenter(tower->get_binphi());

          phi = atan2(cos(phi), sin(phi));

          if (first)
            {
              first = false;
            }
          else
            fdata << ",";

          fdata
              << (boost::format("[%1%,%2%,%3%]") % eta % phi
                  % tower->get_energy());

        }

      fdata << endl;
    }

    {
      fdata << "Track list" << endl;

      // need things off of the DST...
      PHG4TruthInfoContainer* truthinfo = findNode::getClass<
          PHG4TruthInfoContainer>(topNode, "G4TruthInfo");
      if (!truthinfo)
        {
          cerr << PHWHERE << " ERROR: Can't find G4TruthInfo" << endl;
          exit(-1);
        }

      // create SVTX eval stack
      SvtxEvalStack svtxevalstack(topNode);

//  SvtxVertexEval* vertexeval = svtxevalstack.get_vertex_eval();
//  SvtxTrackEval* trackeval = svtxevalstack.get_track_eval();
      SvtxTruthEval* trutheval = svtxevalstack.get_truth_eval();

      // loop over all truth particles
      PHG4TruthInfoContainer::Range range =
          truthinfo->GetPrimaryParticleRange();
      for (PHG4TruthInfoContainer::ConstIterator iter = range.first;
          iter != range.second; ++iter)
        {
          PHG4Particle* g4particle = iter->second;

          const TVector3 mom(g4particle->get_px(), g4particle->get_py(),
              g4particle->get_pz());

          std::set<PHG4Hit*> g4hits = trutheval->all_truth_hits(g4particle);

          map<float, PHG4Hit *> time_sort;
          map<float, PHG4Hit *> layer_sort;
          for (auto & hit : g4hits)
            {
              if (hit)
                {
                  time_sort[hit->get_avg_t()] = hit;
                }
            }

          for (auto & hit_pair : time_sort)
            {

              if (hit_pair.second->get_layer() != UINT_MAX
                  and layer_sort.find(hit_pair.second->get_layer())
                      == layer_sort.end())
                {
                  layer_sort[hit_pair.second->get_layer()] = hit_pair.second;
                }
            }

          if (layer_sort.size() > 5 and mom.Pt() > _pT_threshold) // minimal track length cut
            {

              stringstream spts;

              TVector3 last_pos(0, 0, 0);

              bool first = true;
              for (auto & hit_pair : layer_sort)
                {
                  TVector3 pos(hit_pair.second->get_avg_x(),
                      hit_pair.second->get_avg_y(),
                      hit_pair.second->get_avg_z());

                  // hit step cuts
                  if ((pos - last_pos).Mag() < _min_track_hit_dist
                      and hit_pair.first != (layer_sort.rbegin()->first)
                      and hit_pair.first != (layer_sort.begin()->first))
                    continue;

                  last_pos = pos;

                  if (first)
                    {
                      first = false;
                    }
                  else
                    spts << ",";

                  spts << "[";
                  spts << pos.x();
                  spts << ",";
                  spts << pos.y();
                  spts << ",";
                  spts << pos.z();
                  spts << "]";
                }

              const int abs_pid = abs(g4particle->get_pid());
              int t = 5;
              if (abs_pid
                  == TDatabasePDG::Instance()->GetParticle("pi+")->PdgCode())
                {
                  t = 1;
                }
              else if (abs_pid
                  == TDatabasePDG::Instance()->GetParticle("proton")->PdgCode())
                {
                  t = 2;
                }
              else if (abs_pid
                  == TDatabasePDG::Instance()->GetParticle("K+")->PdgCode())
                {
                  t = 3;
                }
              else if (abs_pid
                  == TDatabasePDG::Instance()->GetParticle("e-")->PdgCode())
                {
                  t = 3;
                }

              const TParticlePDG * pdg_part =
                  TDatabasePDG::Instance()->GetParticle(11);
              const int c =
                  (pdg_part != nullptr) ? (copysign(1, pdg_part->Charge())) : 0;

              fdata
                  << (boost::format(
                      "{ \"pt\": %1%, \"t\": %2%, \"e\": %3%, \"p\": %4%, \"c\": %5%, \"pts\":[ %6% ]}")
                      % mom.Pt() % t % mom.PseudoRapidity() % mom.Phi() % c
                      % spts.str()) << endl;

            }
        }
    }

  fdata.close();
  return 0;
}