//////////////////////////////////////////////////////////////////////////
//                                                                      //
// ATLFast ElectronMaker class.                                         //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include <TMCParticle.h>
#include <TRandom.h>

#include "ATLFast.h"
#include "ATLFMCMaker.h"
#include "ATLFClusterMaker.h"
#include "ATLFElectronMaker.h"
#include "ATLFCluster.h"
#include "ATLFElectron.h"

const Float_t kPI   = TMath::Pi();
const Float_t k2PI  = 2*kPI;
const Int_t kMAXELE = 100;

ClassImp(ATLFElectronMaker)

//_____________________________________________________________________________
 ATLFElectronMaker::ATLFElectronMaker()
{
   m_Nelectrons = 0;
}

//_____________________________________________________________________________
 ATLFElectronMaker::ATLFElectronMaker(const char *name, const char *title)
                 :ATLFMaker(name,title)
{
   SetMinPT();
   SetMaxEta();
   SetRconeMatch();
   SetRconeSep();
   SetRconeDep();
   SetMaxEdep();

   m_Fruits     = new TClonesArray("ATLFElectron",2,kFALSE);
   m_BranchName = "Electrons";
   m_Nelectrons = 0;
   Save();
}

//_____________________________________________________________________________
 ATLFElectronMaker::~ATLFElectronMaker()
{
   //dummy
}

//_____________________________________________________________________________
 void  ATLFElectronMaker::AddElectron(Int_t code, Int_t mcparticle, Int_t mother, Float_t eta, Float_t phi, Float_t pt)
{
//            Add a new electron  to the list of electrons

 //Note the use of the "new with placement" to create a new electron object.
 //This complex "new" works in the following way:
 //   electrons[i] is the value of the pointer for electron number i in the TClonesArray
 //   if it is zero, then a new electron must be generated. This typically
 //   will happen only at the first events
 //   If it is not zero, then the already existing object is overwritten
 //   by the new electron parameters.
 // This technique should save a huge amount of time otherwise spent
 // in the operators new and delete.

   TClonesArray &electrons = *(TClonesArray*)m_Fruits;
   new(electrons[m_Nelectrons++]) ATLFElectron(code,mcparticle,mother,eta,phi,pt);
}

//_____________________________________________________________________________
 void ATLFElectronMaker::Clear(Option_t *option)
{
//    Reset Electron Maker

   m_Nelectrons = 0;
   ATLFMaker::Clear(option);
}


//_____________________________________________________________________________
 void ATLFElectronMaker::Init()
{
//  Create histograms
   m_Mult          = new TH1F("EleMult","//electron multiplicity",10,0,10);
   m_MultHard      = new TH1F("EleMultHard","electron multiplicity hard",10,0,10);
   m_MultHardIsol  = new TH1F("EleMultHardIsol","electron multiplicity hard + isol",10,0,10);
   m_PT            = new TH1F("ElePT","(pT- pTcru) vers E electron ISOLATED",50,0,100);
   m_Eta           = new TH1F("EleEta","(eta-etacru) vers E electron ISOLATED",50,0,100);
   m_Phi           = new TH1F("ElePhi","(phi-phicru) vers E electron ISOLATED",50,0,100);
   m_Counter       = new TH1F("EleCounter","counter vers E electron ISOLATED",50,0,100);
   m_Mass2e        = new TH1F("EleMass2e","ee mass",50,80,100);
   m_Mass2esubst   = new TH1F("EleMass2esubst","ee mass subtract width",50,80,100);
   m_Mass4e        = new TH1F("EleMass4e","eeee mass",50,120,140);
}

//_____________________________________________________________________________
 void ATLFElectronMaker::Finish()
{
// Function called by ATLFast::Finish at the end of the job
//   Normalize histograms

   m_PT->Divide(m_Counter);
   m_Eta->Divide(m_Counter);
   m_Phi->Divide(m_Counter);

}

//_____________________________________________________________________________
 Int_t ATLFElectronMaker::Make()
{
//.............................................
//  This function searches for isolated electrons, by scanning through
//  the list of MC particles. If an electron is found, its energy is
//  smeared using function RESELE. Different energy-smearing for low luminosity
//  and high luminosity can be invoked.
//  Isolated electrons are stored in The TClonesArray of electrons
//  and the energy clusters associated with them are removed.
//  Non-isolated electrons are not considered further.
//.............................................

   Int_t elCode[kMAXELE],    elPart[kMAXELE],  elMother[kMAXELE];
   Float_t elEta[kMAXELE],   elPhi[kMAXELE],   elPT[kMAXELE];

   Int_t sortindex[kMAXELE];
   Int_t nele   = 0;
   Int_t i, k, ic, ij, KF;

//........................................................
//... Get pointers to MCparticles arrays and ClonesArray
//........................................................
   ATLFMCMaker *mcarlo = gATLFast->MCMaker();
   TClonesArray *particles = mcarlo->Fruits();
   TMCParticle *part, *parent;
   Float_t *pPT  = mcarlo->PT();
   Float_t *pEta = mcarlo->Eta();
   Float_t *pPhi = mcarlo->Phi();
   Int_t   *Index= mcarlo->Index();
   

//........................................................
//... Get pointers to clustermaker arrays and ClonesArray
//........................................................
   ATLFClusterMaker *clustermaker = gATLFast->ClusterMaker();
   TClonesArray *clusters = clustermaker->Fruits();
   ATLFCluster *cluster;
   Float_t *cellEta   = clustermaker->CellEta();
   Float_t *cellPhi   = clustermaker->CellPhi();
   Float_t *cellSumPT = clustermaker->CellSumPT();
   Int_t nclusters    = clustermaker->Nclusters();
   Int_t ncells       = clustermaker->Ncells();

//........................................................
//....look for isolated electrons, sort clusters common
//........................................................
   Bool_t isolated;
   Float_t ptcru, etacru, phicru;
   Float_t sigma, pxele, pyele, pzele, eeele;
   Float_t pt, eta, phi, atheta, abseta, deta, dphi;
   Float_t adphi, dr, ddr, edep;
   Float_t theta = 0;
   Float_t ene;
   Int_t lclu;
   Int_t nstop = mcarlo->Nstop();
   Float_t RconeSep2   = m_RconeSep*m_RconeSep;
   Float_t RconeDep2   = m_RconeDep*m_RconeDep;
   Float_t RconeMatch2 = m_RconeMatch*m_RconeMatch;

   for (Int_t ind=0;ind<mcarlo->Nstables();ind++) {
      i = Index[ind];
      if (i < mcarlo->Nstart()) continue;
      part = (TMCParticle*)particles->UncheckedAt(i);
      KF   = part->GetKF();
      if (TMath::Abs(KF) != 11) continue;
                 //-- analyse  electrons
      isolated = kTRUE;
      lclu   = -1;
      pt     = pPT[i];
      eta    = pEta[i];
      phi    = pPhi[i];
      ptcru  = pt;
      etacru = eta;
      phicru = phi;
                 //.... apply smearing
      if (gATLFast->Smearing() == 1) {
          ene    = part->GetEnergy();
          if (ene <= 0) continue;
          sigma = ElectronResolution(gATLFast->Luminosity(),ene, eta, pt); 
          pxele = part->GetPx()*(1+sigma);
          pyele = part->GetPy()*(1+sigma);
          pzele = part->GetPz()*(1+sigma);
          eeele = part->GetEnergy()*(1+sigma);
          if (TMath::Abs(pzele/eeele) < 1) {
             theta = TMath::ACos(pzele/eeele);
          } else {
             if (pzele > 0) theta = 0;
             if (pzele < 0) theta = kPI;
          }
          atheta = TMath::Abs(TMath::Tan(0.5*theta));
          if (atheta < 0.0001) atheta = 0.0001;
          eta = -TMath::Log(atheta);
          phi = mcarlo->Angle(pxele,pyele);
          pt  = TMath::Sqrt(pxele*pxele + pyele*pyele);
      }
      if (pt < m_MinPT) continue;
      abseta = TMath::Abs(eta);
      if (abseta > m_MaxEta) continue;

           //........................................................
           //....mark electron cluster
           //........................................................
      dr = 100;
      for (k=0;k<nclusters;k++) {
         cluster = (ATLFCluster*)clusters->UncheckedAt(k);
         deta    = eta - cluster->Eta();
         dphi    = phi - cluster->Phi();
         adphi   = TMath::Abs(dphi) - k2PI;
         if (TMath::Abs(dphi) > kPI) ddr = deta*deta +adphi*adphi;
         else                        ddr = deta*deta + dphi*dphi;
         if (ddr < dr) {lclu = k; dr = ddr;}
      }
      if (dr > RconeMatch2) lclu = -1;
           //........................................................
           //....check if electron isolated from clusters
           //........................................................
      for (k=0;k<nclusters;k++) {
         if (k == lclu) {
            ddr = 100;
         } else {
            cluster = (ATLFCluster*)clusters->UncheckedAt(k);
            deta    = eta - cluster->Eta();
            dphi    = phi - cluster->Phi();
            adphi   = TMath::Abs(dphi) - k2PI;
            if (TMath::Abs(dphi) > kPI) ddr = deta*deta +adphi*adphi;
            else                        ddr = deta*deta + dphi*dphi;
         }
         if (ddr < RconeSep2) isolated = kFALSE;
      }

           //........................................................
           //....check on energy deposition of cells EDEP in cone m_MaxEdep
           //........................................................
      edep = 0;
      for (ic=0;ic<ncells;ic++) {
         deta  = eta - cellEta[ic];
         dphi  = phi - cellPhi[ic];
         adphi = TMath::Abs(dphi) - k2PI;
         if (TMath::Abs(dphi) > kPI)  ddr = deta*deta + adphi*adphi;
         else                         ddr = deta*deta + dphi*dphi;
         if (ddr < RconeDep2) edep += cellSumPT[ic];
      }
      if (edep-pt > m_MaxEdep) isolated = kFALSE;

      parent = (TMCParticle*)particles->UncheckedAt(part->GetParent()-1);
      if (isolated) { // fill isolated electron structure

         if (lclu >= 0) {nclusters--; clustermaker->RemoveCluster(lclu);}

         elCode[nele]   = KF;
         elPart[nele]   = i; 
         elMother[nele] = parent->GetKF();
         elEta[nele]    = eta;
         elPhi[nele]    = phi;
         elPT[nele]     = pt;
         nele++;
           //........................................................
           //.....monitor energy smearing for isolated electrons
           //........................................................
         m_PT->Fill(part->GetEnergy(), TMath::Abs(pt-ptcru));
         m_Eta->Fill(part->GetEnergy(),TMath::Abs(eta-etacru));
         m_Phi->Fill(part->GetEnergy(),TMath::Abs(phi-phicru));
         m_Counter->Fill(part->GetEnergy());
     }
 }  // end of loop on primary particles


    m_Mult->Fill(nele+0.01);

//........................................................
//.....arrange isolated electrons in falling E_T sequence
//........................................................

   Int_t eleCode[kMAXELE],    elePart[kMAXELE],  eleMother[kMAXELE];
   Float_t eleEta[kMAXELE],   elePhi[kMAXELE],   elePT[kMAXELE];

   gATLFast->SortDown(nele, elPT, sortindex);

   for (i=0;i<nele;i++) {
      ij = sortindex[i];
      eleCode[i]   = elCode[ij];
      elePart[i]   = elPart[ij];
      eleMother[i] = elMother[ij];
      eleEta[i]    = elEta[ij] ;
      elePhi[i]    = elPhi[ij];
      elePT[i]     = elPT[ij];
   }

   Float_t pxele1, pyele1, pzele1, eeele1;
   Float_t pxele2, pyele2, pzele2, eeele2;
   Float_t px4el,  py4el,  pz4el,  ee4el;
   Float_t aelel, ammc, ammcc;

//........................................................
//......check mass resolution
//........................................................
   if (nele == 2) {
      pxele1 = elePT[0]*TMath::Cos(elePhi[0]);
      pyele1 = elePT[0]*TMath::Sin(elePhi[0]);
      pzele1 = elePT[0]*TMath::SinH(eleEta[0]);
      eeele1 = elePT[0]*TMath::CosH(eleEta[0]);
      pxele2 = elePT[1]*TMath::Cos(elePhi[1]);
      pyele2 = elePT[1]*TMath::Sin(elePhi[1]);
      pzele2 = elePT[1]*TMath::SinH(eleEta[1]);
      eeele2 = elePT[1]*TMath::CosH(eleEta[1]);
      aelel  = (eeele1+eeele2)*(eeele1+eeele2) - (pxele1+pxele2)*(pxele1+pxele2)
              -(pyele1+pyele2)*(pyele1+pyele2) - (pzele1+pzele2)*(pzele1+pzele2);
      if (aelel > 0) aelel = TMath::Sqrt(aelel);
      m_Mass2e->Fill(aelel);
           //.....substract natural width
      for (k=0;k<nstop;k++) {
         part   = (TMCParticle*)particles->UncheckedAt(k);
         parent = (TMCParticle*)particles->UncheckedAt(part->GetParent()-1);
         KF     = part->GetKF();
         if (KF == 11 && parent->GetKF() == 23) {
            ammc  = 91.173;
            ammcc = parent->GetMass();
            m_Mass2esubst->Fill(aelel-(ammcc-ammc));
         }
      }
   }
//........................................................
//........mass of 4electrons
//........................................................
   if (nele == 4) {
      px4el = py4el = pz4el = ee4el = 0;
      for (k=0;k<4;k++) {
          px4el += elePT[k]*TMath::Cos(elePhi[k]);
          py4el += elePT[k]*TMath::Sin(elePhi[k]);
          pz4el += elePT[k]*TMath::SinH(eleEta[k]);
          ee4el += elePT[k]*TMath::CosH(eleEta[k]);
      }
      aelel = ee4el*ee4el -px4el*px4el -py4el*py4el - pz4el*pz4el;
      if (aelel > 0) aelel = TMath::Sqrt(aelel);
      m_Mass4e->Fill(aelel);
   }

//........................................................
//....cross-check with partons
//........................................................
   Int_t iele    = 0;
   Int_t ieleiso = 0;
   Float_t ener;
   Int_t KF2;
   TMCParticle *part2;
   for (i=0;i<nstop;i++) {
      part = (TMCParticle*)particles->UncheckedAt(i);
      KF   = part->GetKF();
      if (TMath::Abs(KF) == 11) {
         abseta   = TMath::Abs(pEta[i]);
         ener     = 0;
         isolated = kTRUE;
         for (k=0;k<nstop;k++) {
            part2  = (TMCParticle*)particles->UncheckedAt(k);
            KF2    = TMath::Abs(part2->GetKF());
            if ((KF2 <= 21) && (i != k) && (KF2 != 12) && (KF2 != 14) && (KF2 !=16)) {
               deta  = pEta[i] - pEta[k];
               dphi  = pPhi[i] - pPhi[k];
               adphi = TMath::Abs(dphi) - k2PI;
               if (TMath::Abs(dphi) > kPI) ddr = deta*deta + adphi*adphi;
               else                        ddr = deta*deta + dphi*dphi;
               if (ddr < RconeSep2 && pPT[k] > clustermaker->MinETCalo()) isolated = kFALSE;
               if (ddr < RconeDep2 && pPT[k] < clustermaker->MinETCalo()) ener += pPT[k];
            }
         }
         if (ener > m_MaxEdep) isolated = kFALSE;
         if (abseta < m_MaxEta && pPT[i] > m_MinPT) {
            iele++;
            if (isolated)  ieleiso++;
         }
      }
   }
   m_MultHard->Fill(iele+0.01);
   m_MultHardIsol->Fill(ieleiso+0.01);

//........................................................
//....Store electrons in Root ClonesArray
//........................................................
   m_Nelectrons = 0;
   for (k=0;k<nele;k++) {
      AddElectron(eleCode[k],
                  elePart[k],
                  eleMother[k],
                  eleEta[k],
                  elePhi[k],
                  elePT[k]);
   }
   return 0;
}

//_____________________________________________________________________________
 void ATLFElectronMaker::PrintInfo()
{
   ATLFMaker::PrintInfo();
}

//_____________________________________________________________________________
 Float_t ATLFElectronMaker::ElectronResolution(Int_t lumi, Float_t ene, Float_t eta, Float_t pt)
{
//     parametrizes electron  resolution for low and high luminosity
//     parametrization from L. Poggioli

  Float_t rpilup = 0;
  Float_t aa, bb, sigph1, sigph, sigpu;
  Float_t sqrtene = TMath::Sqrt(ene);
  Float_t abseta  = TMath::Abs(eta);

  while(1) {
     gRandom->Rannor(aa,bb);
     sigph1 = aa*0.12/sqrtene;
     if (1 + sigph1 <= 0) continue;
     sigph = sigph1;
     if (abseta < 1.4) {
        while(1) {
           gRandom->Rannor(aa,bb);
           sigph1 = aa*0.245/pt + bb*0.007;
           if (1 + sigph1 > 0) break;
        }
     } else {
        while(1) {
           gRandom->Rannor(aa,bb);
           sigph1 = aa* 0.306*((2.4-abseta)+0.228)/ene + bb*0.007;
           if (1 + sigph1 > 0) break;
        }
     }
     sigph += sigph1;
     if (lumi == 2) {
        if (abseta <  0.6)                rpilup = 0.32;
        if (abseta > 0.6 && abseta < 1.4) rpilup = 0.295;
        if (abseta > 1.4)                 rpilup = 0.27;
        while(1) {
           gRandom->Rannor(aa,bb);
           sigpu = aa*rpilup/pt;
           if (1 + sigpu > 0) break;
        }
        sigph += sigpu;
     }
     if (1 + sigph > 0) return sigph;
  }
}



ROOT page - Class index - Top of the page

This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.