//////////////////////////////////////////////////////////////////////////
//                                                                      //
// ATLFast PhotonMaker class.                                         //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

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

#include "ATLFast.h"
#include "ATLFMCMaker.h"
#include "ATLFClusterMaker.h"
#include "ATLFPhotonMaker.h"
#include "ATLFCluster.h"
#include "ATLFPhoton.h"

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

ClassImp(ATLFPhotonMaker)

//_____________________________________________________________________________
 ATLFPhotonMaker::ATLFPhotonMaker()
{
   m_Nphotons = 0;
}

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

   m_Fruits     = new TClonesArray("ATLFPhoton",2, kFALSE);
   m_BranchName = "Photons";
   m_Nphotons   = 0;
   Save();
}

//_____________________________________________________________________________
 ATLFPhotonMaker::~ATLFPhotonMaker()
{
   //dummy
//printf("ATLFPhotonMaker destructor calledn");
}

//_____________________________________________________________________________
 void  ATLFPhotonMaker::AddPhoton(Int_t code, Int_t mcparticle, Int_t mother, Float_t eta, Float_t phi, Float_t pt)
{
//            Add a new photon to the list of photons

 //Note the use of the "new with placement" to create a new photon object.
 //This complex "new" works in the following way:
 //   photons[i] is the value of the pointer for photon number i in the TClonesArray
 //   if it is zero, then a new photon 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 photon parameters.
 // This technique should save a huge amount of time otherwise spent
 // in the operators new and delete.

   TClonesArray &photons = *(TClonesArray*)m_Fruits;
   new(photons[m_Nphotons++]) ATLFPhoton(code,mcparticle,mother,eta,phi,pt);
}

//_____________________________________________________________________________
 void ATLFPhotonMaker::Clear(Option_t *option)
{
//    Reset Photon Maker

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


//_____________________________________________________________________________
 void ATLFPhotonMaker::Init()
{
//  Create histograms
   m_Mult          = new TH1F("PhoMult","photon multiplicity isolated",10,0,10);
   m_MultHard      = new TH1F("PhoMultHard","photon multiplicity hard",10,0,10);
   m_MultHardIsol  = new TH1F("PhoMultHardIsol","photon multiplicity hard + isol",10,0,10);
   m_E             = new TH1F("PhoE","(E-Ecru)/Ecru  vers E photon ISOLATED",50,0,100);
   m_Theta         = new TH1F("PhoTheta","(theta-thetacru) vers E photon ISOLATED",50,0,100);
   m_Counter       = new TH1F("PhoCounter","counter vers E photon ISOLATED",50,0,100);
   m_Mass2ph       = new TH1F("PhoMass2ph","pho-pho mass",50,90,110);
}

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

   m_E->Divide(m_Counter);
   m_Theta->Divide(m_Counter);
}

//_____________________________________________________________________________
 Int_t ATLFPhotonMaker::Make()
{
//.............................................
//  This function searches for isolated photons, by scanning through
//  the list of MC particles. If a photon is found, its energy is
//  smeared using function RESPHO  and its polar angle using RESTHE.
//  Different energy-smearing for low and high luminosity can be invoked.
//  Isolated photons are stored in The TClonesArray of photons
//  and the energy clusters associated with them are removed.
//  Non-isolated photons are not considered further.
//.............................................
   Int_t phoCode[kMAXPHOT],    phoPart[kMAXPHOT],  phoMother[kMAXPHOT];
   Float_t phoEta[kMAXPHOT],   phoPhi[kMAXPHOT],   phoPT[kMAXPHOT];

   Int_t sortindex[kMAXPHOT];
   Int_t nphot  = 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 photons, sort clusters common
//........................................................
   Bool_t isolated;
   Float_t pxphot, pyphot, pzphot, eephot;
   Float_t pz, pt, eta, phi, atheta, abseta, deta, dphi;
   Float_t adphi, dr, ddr, edep;
   Float_t enecru, thetacru, sigma1;
   Float_t ene   = 0;
   Float_t theta = 0;
   Int_t lclu;
   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();
      pt     = pPT[i];
      if (pt <= 0) continue;
      if (TMath::Abs(KF) != 22) continue;
                 //-- analyse  photons
      isolated = kTRUE;
      lclu   = -1;
      pz     = part->GetPz();
      eta    = pEta[i];
      phi    = pPhi[i];
      enecru = part->GetEnergy();
      thetacru = TMath::ACos(pz/enecru);
      
                 //.... apply smearing
      Float_t sigma2, theta1, etaphot, atheta1;
      if (gATLFast->Smearing() == 1) {
          ene    = enecru;
          if (ene <= 0) continue;
          pzphot = pz;
          eephot = enecru;
          if (TMath::Abs(pzphot/eephot) < 1) {
             theta = TMath::ACos(pzphot/eephot);
          } else {
             if (pzphot > 0) theta = 0;
             if (pzphot < 0) theta = kPI;
          }
          atheta = TMath::Abs(TMath::Tan(0.5*theta));
          if (atheta < 0.0001) atheta = 0.0001;
          eta = -TMath::Log(atheta);
          sigma2 = SmearTheta(ene, eta,theta);
          theta1 = theta + sigma2;
          pzphot = ene*TMath::Cos(theta1);
          atheta1= TMath::Abs(TMath::Tan(0.5*theta1));
          if (atheta1 < 0.0001) atheta1 = 0.0001;
          etaphot= -TMath::Log(atheta1);
          sigma1 = PhotonResolution(gATLFast->Luminosity(),ene,pt,etaphot);
          pxphot = part->GetPx()*(1+sigma1);
          pyphot = part->GetPy()*(1+sigma1);
          pzphot = pzphot*(1+sigma1);
          eephot = enecru*(1+sigma1);
          if (TMath::Abs(pzphot/eephot) < 1) {
             theta = TMath::ACos(pzphot/eephot);
          } else {
             if (pzphot > 0) theta = 0;
             if (pzphot < 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(pxphot, pyphot);
          pt   = TMath::Sqrt(pxphot*pxphot + pyphot*pyphot);
          ene  = eephot;
      }
      if (pt < m_MinPT) continue;
      abseta = TMath::Abs(eta);
      if (abseta > m_MaxEta) continue;

           //........................................................
           //....mark photon 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 photon 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 photon structure
           //........................................................
           //....remove pho-cluster from array of clustesr
           //........................................................
         if (lclu >= 0) {nclusters--; clustermaker->RemoveCluster(lclu);}

         phoCode[nphot]    = KF;
         phoPart[nphot]    = i; 
         phoMother[nphot]  = parent->GetKF();
         phoEta[nphot]     = eta;
         phoPhi[nphot]     = phi;
         phoPT[nphot]      = pt;
         nphot++;
           //........................................................
           //.....monitor energy smearing for isolated photons
           //........................................................
         m_E->Fill(part->GetEnergy(), TMath::Abs((ene-enecru)/enecru));
         m_Theta->Fill(part->GetEnergy(),TMath::Abs(theta-thetacru));
         m_Counter->Fill(part->GetEnergy());
     }
 }  // end of loop on primary particles


    m_Mult->Fill(nphot+0.01);

//........................................................
//.....arrange isolated photons in falling E_T sequence
//........................................................
   Int_t photCode[kMAXPHOT],    photPart[kMAXPHOT],  photMother[kMAXPHOT];
   Float_t photEta[kMAXPHOT],   photPhi[kMAXPHOT],   photPT[kMAXPHOT];

   gATLFast->SortDown(nphot, phoPT, sortindex);

   for (i=0;i<nphot;i++) {
      ij = sortindex[i];
      photCode[i]   = phoCode[ij];
      photPart[i]   = phoPart[ij];
      photMother[i] = phoMother[ij];
      photEta[i]    = phoEta[ij] ;
      photPhi[i]    = phoPhi[ij];
      photPT[i]     = phoPT[ij];
   }

   Float_t pxphot1, pyphot1, pzphot1, eephot1;
   Float_t pxphot2, pyphot2, pzphot2, eephot2;
   Float_t aphotphot;

//........................................................
//......check mass distribution
//........................................................
   if (nphot == 2) {
      pxphot1 = photPT[0]*TMath::Cos(photPhi[0]);
      pyphot1 = photPT[0]*TMath::Sin(photPhi[0]);
      pzphot1 = photPT[0]*TMath::SinH(photEta[0]);
      eephot1 = photPT[0]*TMath::CosH(photEta[0]);
      pxphot2 = photPT[1]*TMath::Cos(photPhi[1]);
      pyphot2 = photPT[1]*TMath::Sin(photPhi[1]);
      pzphot2 = photPT[1]*TMath::SinH(photEta[1]);
      eephot2 = photPT[1]*TMath::CosH(photEta[1]);
      aphotphot  = (eephot1+eephot2)*(eephot1+eephot2) - (pxphot1+pxphot2)*(pxphot1+pxphot2)
                  -(pyphot1+pyphot2)*(pyphot1+pyphot2) - (pzphot1+pzphot2)*(pzphot1+pzphot2);
      if (aphotphot > 0) aphotphot = TMath::Sqrt(aphotphot);
      m_Mass2ph->Fill(aphotphot);
   }

//........................................................
//....cross-check with partons
//........................................................
   Int_t iphot    = 0;
   Int_t iphotiso = 0;
   Float_t ener;
   Int_t KF2;
   TMCParticle *part2;
   Int_t nstop = mcarlo->Nstop();
   for (i=0;i<nstop;i++) {
      part = (TMCParticle*)particles->UncheckedAt(i);
      KF   = part->GetKF();
      if (TMath::Abs(KF) == 22) {
         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) {
            iphot++;
            if (isolated)  iphotiso++;
         }
      }
   }
   m_MultHard->Fill(iphot+0.01);
   m_MultHardIsol->Fill(iphotiso+0.01);

//........................................................
//....Store photons in Root ClonesArray
//........................................................
// AddPhoton(Int_t code, Int_t mcparticle, Int_t mother, Int_t use, Float_t eta, Float_t phi, Float_t pt)
   m_Nphotons = 0;
   for (k=0;k<nphot;k++) {
      AddPhoton(photCode[k],
              photPart[k],
              photMother[k],
              photEta[k],
              photPhi[k],
              photPT[k]);
   }
   return 0;
}

//_____________________________________________________________________________
 Float_t ATLFPhotonMaker::PhotonResolution(Int_t keylum, Float_t ene, Float_t pt, Float_t eta)
{
//     parametrizes photon  resolution for low and high luminosity
//     parametrization from L. Poggioli and F. Gianotti
//         keylum=1   -- low  luminosity
//         keylum=2   -- high luminosity

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

   while(1) {
      while(1) {
         gRandom->Rannor(aa,bb);
         sigph1 = aa*0.10/sqrt(ene); 
         if(1.+sigph1 > 0) break;
      }
      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 = sigph + sigph1;
      if (keylum == 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 + sigph;
      }
      if(1.+sigph > 0) break;
   } 
   return sigph;
}

//_____________________________________________________________________________
 Float_t ATLFPhotonMaker::SmearTheta(Float_t ene, Float_t eta, Float_t theta)
{
//     parametrizes smearing in photon position  theta
//     parametrization from F. Gianotti

   const Float_t kPI = 3.141592653;
   Float_t aa, bb;
   Float_t sigph2 = 0;
   Float_t abseta = TMath::Abs(eta);
   Float_t sqrene = TMath::Sqrt(ene);

   while(1) {
      gRandom->Rannor(aa,bb);
      if(abseta < 0.8)                  sigph2 = aa*0.065/sqrene;
      if(abseta >= 0.8 && abseta < 1.4) sigph2 = aa*0.050/sqrene;
      if(abseta >= 1.4 && abseta < 2.5) sigph2 = aa*0.040/sqrene;
      if(abseta >= 2.5)                 sigph2 = 0;
      if(TMath::Abs(theta+sigph2) <= kPI) break;
   }
   return sigph2;
}

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


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.