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;
}
Esempio n. 2
0
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];
}
Esempio n. 3
0
int main(int argc, char* argv[])
{
  TApplication theApp(srcName.Data(), &argc, argv);
//=============================================================================

  if (argc<5) return -1;
  TString sPath = argv[1]; if (sPath.IsNull()) return -1;
  TString sFile = argv[2]; if (sFile.IsNull()) return -1;
  TString sJetR = argv[3]; if (sJetR.IsNull()) return -1;
  TString sSjeR = argv[4]; if (sSjeR.IsNull()) return -1;
//=============================================================================

  sPath.ReplaceAll("#", "/");
//=============================================================================

  double dJetR = -1.;
  if (sJetR=="JetR02") dJetR = 0.2;
  if (sJetR=="JetR03") dJetR = 0.3;
  if (sJetR=="JetR04") dJetR = 0.4;
  if (sJetR=="JetR05") dJetR = 0.5;

  if (dJetR<0.) return -1;
  cout << "Jet R = " << dJetR << endl;
//=============================================================================

  double dSjeR = -1.;
  if (sSjeR=="SjeR01") dSjeR = 0.1;
  if (sSjeR=="SjeR02") dSjeR = 0.2;
  if (sSjeR=="SjeR03") dSjeR = 0.3;
  if (sSjeR=="SjeR04") dSjeR = 0.4;

  if (dSjeR<0.) return -1;
  cout << "Sub-jet R = " << dSjeR << endl;
//=============================================================================

  const double dJetsPtMin  = 0.001;
  const double dCutEtaMax  = 1.6;
  const double dJetEtaMax  = 1.;
  const double dJetAreaRef = TMath::Pi() * dJetR * dJetR;

  fastjet::GhostedAreaSpec areaSpc(dCutEtaMax);
  fastjet::JetDefinition   jetsDef(fastjet::antikt_algorithm, dJetR, fastjet::BIpt_scheme, fastjet::Best);

//fastjet::AreaDefinition  areaDef(fastjet::active_area,areaSpc);
  fastjet::AreaDefinition  areaDef(fastjet::active_area_explicit_ghosts,areaSpc);

//fastjet::JetDefinition   bkgsDef(fastjet::kt_algorithm, 0.2, fastjet::BIpt_scheme, fastjet::Best);
//fastjet::AreaDefinition  aBkgDef(fastjet::active_area_explicit_ghosts, areaSpc);

  fastjet::Selector selectJet = fastjet::SelectorAbsEtaMax(dJetEtaMax);
//fastjet::Selector selectRho = fastjet::SelectorAbsEtaMax(dCutEtaMax-0.2);
//fastjet::Selector selecHard = fastjet::SelectorNHardest(2);
//fastjet::Selector selectBkg = selectRho * (!(selecHard));
//fastjet::JetMedianBackgroundEstimator bkgsEstimator(selectBkg, bkgsDef, aBkgDef);
//fastjet::Subtractor                   bkgSubtractor(&bkgsEstimator);

  fastjet::JetDefinition subjDef(fastjet::antikt_algorithm, dSjeR, fastjet::BIpt_scheme, fastjet::Best);
//=============================================================================

  std::vector<fastjet::PseudoJet> fjInput;
//=============================================================================

  TList *list = new TList();
  TH1D *hWeightSum = new TH1D("hWeightSum", "", 1, 0., 1.); list->Add(hWeightSum);

  TH1D *hJet = new TH1D("hJet", "", 1000, 0., 1000.); hJet->Sumw2(); list->Add(hJet);
  TH2D *hJetNsj = new TH2D("hJetNsj", "", 1000, 0., 1000., 101, -0.5, 100.5); hJetNsj->Sumw2(); list->Add(hJetNsj);

  TH2D *hJetIsj = new TH2D("hJetIsj", "", 1000, 0., 1000., 1000, 0., 1000.); hJetIsj->Sumw2(); list->Add(hJetIsj);
  TH2D *hJet1sj = new TH2D("hJet1sj", "", 1000, 0., 1000., 1000, 0., 1000.); hJet1sj->Sumw2(); list->Add(hJet1sj);
  TH2D *hJet2sj = new TH2D("hJet2sj", "", 1000, 0., 1000., 1000, 0., 1000.); hJet2sj->Sumw2(); list->Add(hJet2sj);
  TH2D *hJetDsj = new TH2D("hJetDsj", "", 1000, 0., 1000., 1000, 0., 1000.); hJetDsj->Sumw2(); list->Add(hJetDsj);

  TH2D *hJetIsz = new TH2D("hJetIsz", "", 1000, 0., 1000., 120, 0., 1.2); hJetIsz->Sumw2(); list->Add(hJetIsz);
  TH2D *hJet1sz = new TH2D("hJet1sz", "", 1000, 0., 1000., 120, 0., 1.2); hJet1sz->Sumw2(); list->Add(hJet1sz);
  TH2D *hJet2sz = new TH2D("hJet2sz", "", 1000, 0., 1000., 120, 0., 1.2); hJet2sz->Sumw2(); list->Add(hJet2sz);
  TH2D *hJetDsz = new TH2D("hJetDsz", "", 1000, 0., 1000., 120, 0., 1.2); hJetDsz->Sumw2(); list->Add(hJetDsz);
//=============================================================================

  HepMC::IO_GenEvent ascii_in(Form("%s/%s.hepmc",sPath.Data(),sFile.Data()), std::ios::in);
  HepMC::GenEvent *evt = ascii_in.read_next_event();

  while (evt) {
    fjInput.resize(0);
    double dXsect  = evt->cross_section()->cross_section() / 1e9;
    double dWeight = evt->weights().back();
    double dNorm = dWeight * dXsect;
    hWeightSum->Fill(0.5, dWeight);

    TVector3 vPar;
    for (HepMC::GenEvent::particle_const_iterator p=evt->particles_begin(); p!=evt->particles_end(); ++p) if ((*p)->status()==1) {
      vPar.SetXYZ((*p)->momentum().px(), (*p)->momentum().py(), (*p)->momentum().pz());

      if ((TMath::Abs(vPar.Eta())<dCutEtaMax)) {
        fjInput.push_back(fastjet::PseudoJet(vPar.Px(), vPar.Py(), vPar.Pz(), vPar.Mag()));
      }
    }
//=============================================================================

    fastjet::ClusterSequenceArea clustSeq(fjInput, jetsDef, areaDef);
    std::vector<fastjet::PseudoJet> includJets = clustSeq.inclusive_jets(dJetsPtMin);
//  std::vector<fastjet::PseudoJet> subtedJets = bkgSubtractor(includJets);
    std::vector<fastjet::PseudoJet> selectJets = selectJet(includJets);
//  std::vector<fastjet::PseudoJet> sortedJets = fastjet::sorted_by_pt(selectJets);

    for (int j=0; j<selectJets.size(); j++) {
      double dJet = selectJets[j].pt();

      hJet->Fill(dJet, dNorm);
//=============================================================================

      fastjet::Filter trimmer(subjDef, fastjet::SelectorPtFractionMin(0.));
      fastjet::PseudoJet trimmdJet = trimmer(selectJets[j]);
      std::vector<fastjet::PseudoJet> trimmdSj = trimmdJet.pieces();

      double nIsj = 0.;
      double d1sj = -1.; int k1sj = -1;
      double d2sj = -1.; int k2sj = -1;
      for (int i=0; i<trimmdSj.size(); i++) {
        double dIsj = trimmdSj[i].pt(); if (dIsj<0.001) continue;

        hJetIsj->Fill(dJet, dIsj, dNorm);
        hJetIsz->Fill(dJet, dIsj/dJet, dNorm);

        if (dIsj>d1sj) {
          d2sj = d1sj; k2sj = k1sj;
          d1sj = dIsj; k1sj = i;
        } else if (dIsj>d2sj) {
          d2sj = dIsj; k2sj = i;
        } nIsj += 1.;
      }

      hJetNsj->Fill(dJet, nIsj, dNorm);
      if (d1sj>0.) { hJet1sj->Fill(dJet, d1sj, dNorm); hJet1sz->Fill(dJet, d1sj/dJet, dNorm); }
      if (d2sj>0.) { hJet2sj->Fill(dJet, d2sj, dNorm); hJet2sz->Fill(dJet, d2sj/dJet, dNorm); }

      if ((d1sj>0.) && (d2sj>0.)) {
        double dsj = d1sj - d2sj;
        double dsz = dsj / dJet;

        hJetDsj->Fill(dJet, dsj, dNorm);
        hJetDsz->Fill(dJet, dsz, dNorm);
      }
    }
//=============================================================================

    delete evt;
    ascii_in >> evt;
  }
//=============================================================================

  TFile *file = TFile::Open(Form("%s.root",sFile.Data()), "NEW");
  list->Write();
  file->Close();
//=============================================================================

  cout << "DONE" << endl;
  return 0;
}