//////////////////////////////////////////////////////////////////////////
// //
// ATLFast ClusterMaker class. //
// //
//////////////////////////////////////////////////////////////////////////
#include <TRandom.h>
#include <TMCParticle.h>
#include "ATLFClusterMaker.h"
#include "ATLFCluster.h"
#include "ATLFMCMaker.h"
#include "ATLFast.h"
const Float_t kPI = TMath::Pi();
const Float_t k2PI = 2*kPI;
const Int_t kMAXCELLS = 2000;
const Int_t kMAXCLU = 1000;
ClassImp(ATLFClusterMaker)
//_____________________________________________________________________________
ATLFClusterMaker::ATLFClusterMaker()
{
m_CellIndex = 0;
m_CellCount = 0;
m_CellFlag = 0;
m_CellEta = 0;
m_CellPhi = 0;
m_CellSumPT = 0;
}
//_____________________________________________________________________________
ATLFClusterMaker::ATLFClusterMaker(const char *name, const char *title)
:ATLFMaker(name,title)
{
SetMinETCalo();
SetDeltaRBarrel1();
SetDeltaRForward1();
SetDeltaRBarrel2();
SetDeltaRForward2();
SetEtaCoverage();
SetMinETInitiator();
SetMinPTBfield();
SetMinETCell();
SetBarrelForwardEta();
SetGranBarrelEta();
SetGranBarrelPhi();
SetCellsEsharing();
m_CellIndex = new Int_t[kMAXCELLS];
m_CellCount = new Int_t[kMAXCELLS];
m_CellFlag = new Int_t[kMAXCELLS];
m_CellEta = new Float_t[kMAXCELLS];
m_CellPhi = new Float_t[kMAXCELLS];
m_CellSumPT = new Float_t[kMAXCELLS];
m_Fruits = new TClonesArray("ATLFCluster",5,kFALSE);
m_BranchName = "Clusters";
m_Nclusters = 0;
m_Ncells = 0;
// Save(); //by default clustera are not saved
}
//_____________________________________________________________________________
ATLFClusterMaker::~ATLFClusterMaker()
{
delete [] m_CellIndex;
delete [] m_CellCount;
delete [] m_CellFlag;
delete [] m_CellEta;
delete [] m_CellPhi;
delete [] m_CellSumPT;
}
//_____________________________________________________________________________
void ATLFClusterMaker::AddCluster(Int_t code, Int_t ncells, Int_t nparticles, Int_t use, Float_t eta0, Float_t phi0,
Float_t eta, Float_t phi, Float_t et)
{
// Add a new cluster to the list of clusters
//Note the use of the "new with placement" to create a new cluster object.
//This complex "new" works in the following way:
// clusters[i] is the value of the pointer for cluster number i in the TClonesArray
// if it is zero, then a new cluster 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 cluster parameters.
// This technique should save a huge amount of time otherwise spent
// in the operators new and delete.
TClonesArray &clusters = *(TClonesArray*)m_Fruits;
new(clusters[m_Nclusters++]) ATLFCluster(code, ncells,nparticles, use, eta0,phi0,eta,phi,et);
}
//_____________________________________________________________________________
void ATLFClusterMaker::Clear(Option_t *option)
{
// Reset Cluster Maker
m_Nclusters = 0;
m_Ncells = 0;
ATLFMaker::Clear(option);
}
//_____________________________________________________________________________
void ATLFClusterMaker::Init()
{
// Create histograms
m_Multiplicity = new TH1F("CluMultiplicity","clusters multiplicity",10,0,10);
m_DeltaPhi = new TH1F("CluDeltaPhi","B-field delta_phi vers p_T",50,0,50);
m_Counters = new TH1F("CluCounters","B-field counters vers p_T",50,0,50);
m_PhiClu = new TH1F("CluPhiClu ","delta_phi clu-bari_centre_particle",50,-0.5,0.5);
m_EtaClu = new TH1F("CluEtaClu","delta_eta clu--bari_centre_particle",50,-0.5,0.5);
m_DeltaR = new TH1F("CluDeltaR","delta_r clu--bari_centre_particle",50,0,0.5);
}
//_____________________________________________________________________________
Float_t ATLFClusterMaker::FieldPhi(Float_t pt, Float_t eta, Float_t theta)
{
// parametrizes effects of the B-field
// shift in the phi position of the charged particle
// parametrization from L. Poggioli
Float_t def;
if (TMath::Abs(eta) < 1.4) {
def = -150. * 0.006/pt/2.0;
} else {
Float_t abstantheta = TMath::Abs(TMath::Tan(theta));
def = -350. * abstantheta* 0.006/pt/2.0;
}
return def;
}
//_____________________________________________________________________________
void ATLFClusterMaker::Finish()
{
// Function called by ATLFast::Finish at the end of the job
m_DeltaPhi->Divide(m_Counters);
}
//_____________________________________________________________________________
Float_t ATLFClusterMaker::HadronResolution(Int_t lumi, Float_t ene, Float_t eta, Float_t pt, Float_t rcone)
{
// parametrizes smearing for hadronic energy deposition
// parametrization from L. Poggioli
// pile-up added as in HADCALO
Float_t epileup = 0;
Float_t aa, bb, cc, dd, sigma;
Float_t sqrtene = TMath::Sqrt(ene);
Float_t abseta = TMath::Abs(eta);
if(rcone <= 0.4) epileup = 0.4;
if(rcone == 0.4) epileup = 7.5;
if(rcone > 0.4 && rcone <= 0.5) epileup = 12.0;
if(rcone > 0.5 && rcone <= 0.7) epileup = 18.0;
if(rcone > 0.7) epileup = 20.0;
if(lumi <= 1) {
while(1) {
gRandom->Rannor(aa,bb);
if(abseta < 3.) sigma = aa*0.5/sqrtene + bb*0.03;
else sigma = aa*1.0/sqrtene + bb*0.07;
if(1.+sigma > .0) return sigma;
}
} else if(lumi == 2) {
while(1) {
gRandom->Rannor(aa,bb);
gRandom->Rannor(cc,dd);
if(abseta < 3.) sigma = aa*0.5/sqrtene + bb*0.03 + cc*epileup/pt;
else sigma = aa*1.0/sqrtene + bb*0.07 + cc*epileup/pt;
if(1.+sigma > .0)return sigma;
}
}
return 0;
}
//_____________________________________________________________________________
Int_t ATLFClusterMaker::Make()
{
//.............................................
// This function deposits the transverse energies of undecayed particles
// (except neutrinos, muons and SUSY LSP) in ETA times PHI cells
// with default granularity: 0.1x0.1 for ETA<3 and 0.2x0.2 for ETA>3.
// This granularity can be modified, but with the limitation that the granularity
// of cells beyond the barrel/forward transition (ETA=3) is twice as large as
// inside. The algorithm then groups these cells into clusters
// if the sum of their transverse energy is above a threshold value.
// The energies deposited in the cells are stored also in a cell map
// Cells used for cluster reconstruction are flagged.
// The effect of the solenoidal magnetic field is only parametrized as
// a shift in the PHI position of charged particles, which is
// calculated by the function FieldPhi. Charged particles with PT
// below the default threshold of 0.5GeV are not stored if the magnetic field
// is on.
// There is the possibility to activate the energy sharing of cells belonging to
// overlaping jets (defaults: no sharing). In that case the corresponding
// cell energy is shared according to the relative energies of each overlaping jet.
// Clusters are arranged in order of decreasing ET.
// The reconstructed clusters are added to the list of clusters.
//.............................................
Float_t rconeb, rconef, ptlrat, abseta;
Float_t eta, phi, theta;
eta= phi= theta= 0;
Float_t detphi, pt, pz, pE, chrg;
Int_t i, nparticles, ncells, nclusters, kc, ic, icell, ij, k, KF, KS;
Int_t ieta, iphi, ietph;
Int_t nbeta = Int_t(2*m_EtaCoverage/m_GranBarrelEta);
Int_t nbphi = Int_t(2*kPI/m_GranBarrelPhi);
rconeb = m_DeltaRBarrel1;
rconef = m_DeltaRForward1;
if (gATLFast->Mode() == 2) {
rconeb= m_DeltaRBarrel2;
rconef= m_DeltaRForward2;
}
Float_t rconeb2 = rconeb*rconeb;
Float_t rconef2 = rconef*rconef;
//........................................................
//... Get pointers to MCparticles arrays and ClonesArray
//........................................................
ATLFMCMaker *mcarlo = gATLFast->MCMaker();
TClonesArray *particles = mcarlo->Fruits();
nparticles = particles->GetEntriesFast();
TMCParticle *part;
Float_t *pPT = mcarlo->PT();
Float_t *pPT2 = mcarlo->PT2();
Float_t *pEta = mcarlo->Eta();
Float_t *pPhi = mcarlo->Phi();
Int_t *Index= mcarlo->Index();
//........................................................
//...Loop over all particles. Find cell that was hit by given particle.
//........................................................
Float_t setacov = TMath::SinH(m_EtaCoverage);
ptlrat=1./(setacov*setacov);
Int_t kFLSP = gATLFast->SUSYcodeLSP();
ncells = 0;
for (Int_t ind=0;ind<mcarlo->Nstables();ind++) {
i = Index[ind];
part = (TMCParticle*)particles->UncheckedAt(i);
KS = part->GetKS();
KF = part->GetKF();
pz = part->GetPz();
if (pPT2[i] <= ptlrat*pz*pz) continue;
kc = mcarlo->Compress(KF);
if (kc == 0 || kc == 12 || kc == 14 || kc == 16) continue;
if (kc == 13 || kc == kFLSP) continue;
detphi = 0;
pt = pPT[i];
eta = pEta[i];
phi = pPhi[i];
pE = part->GetEnergy();
if (gATLFast->Bfield() == 1 && mcarlo->Charge(KF) != 0) {
if (pt < m_MinPTBfield) continue;
chrg = mcarlo->Charge(KF)/3.;
if (TMath::Abs(pz/pE) < 1.) {
theta = TMath::ACos(pz/pE);
} else {
if (pz > 0) theta = 0;
if (pz < 0) theta = kPI;
}
detphi= chrg*FieldPhi(pt,eta,theta);
m_DeltaPhi->Fill(pt,TMath::Abs(detphi));
m_Counters->Fill(pt);
}
phi += detphi;
abseta = TMath::Abs(eta);
if ( abseta < m_BarrelForwardEta) {
ieta = Int_t((eta+m_EtaCoverage)/2.0/m_EtaCoverage*nbeta)+1;
iphi = Int_t((phi+kPI)/2.0/kPI*nbphi)+1;
} else {
ieta = 2*Int_t((eta+m_EtaCoverage)/2.0/m_EtaCoverage*nbeta/2.0)+1;
iphi = 2*Int_t((phi+kPI)/2.0/kPI*nbphi/2.0)+1;
}
ietph = nbphi*ieta + iphi;
//........................................................
//...Add to cell already hit, or book new cell.
//........................................................
icell = ncells;
for (ic=0;ic<ncells;ic++) {
if (ietph == m_CellIndex[ic]) { icell = ic; break; }
}
if (icell == ncells) { // found new cell
ncells++;
m_CellIndex[icell] = ietph;
m_CellCount[icell] = 1;
m_CellFlag[icell] = 2;
if (abseta < m_BarrelForwardEta) {
m_CellEta[icell] = 2*m_EtaCoverage*(ieta -1 +0.5)/nbeta - m_EtaCoverage;
m_CellPhi[icell] = k2PI*(iphi -1 +0.5)/nbphi - kPI;
} else {
m_CellEta[icell] = 2*m_EtaCoverage*ieta/nbeta - m_EtaCoverage;
m_CellPhi[icell] = k2PI*iphi/nbphi - kPI;
}
m_CellSumPT[icell] = pt;
} else { // increment already found cell
m_CellCount[icell]++;
m_CellSumPT[icell] += pt;
}
} // end of loop on particles
//........................................................
//...Remove cells below threshold.
//........................................................
Int_t noldcells = ncells;
ncells = 0;
for (ic =0; ic<noldcells;ic++) {
if (m_CellSumPT[ic] < m_MinETCell) continue;
m_CellIndex[ncells] = m_CellIndex[ic];
m_CellCount[ncells] = m_CellCount[ic];
m_CellFlag[ncells] = m_CellFlag[ic];
m_CellEta[ncells] = m_CellEta[ic];
m_CellPhi[ncells] = m_CellPhi[ic];
ncells++;
}
//........................................................
//...Find initiator cell: the one with highest pT of not yet used ones.
//........................................................
Int_t sortindex[kMAXCLU];
Int_t clusterCells[kMAXCLU], clusterParts[kMAXCLU], clusterFlag[kMAXCLU];
Float_t clusterEta0[kMAXCLU], clusterPhi0[kMAXCLU];
Float_t clusterEta[kMAXCLU], clusterPhi[kMAXCLU], clusterET[kMAXCLU];
Int_t cluCode[kMAXCLU];
Int_t cluCells[kMAXCLU], cluParts[kMAXCLU], cluFlag[kMAXCLU];
Float_t cluEta0[kMAXCLU], cluPhi0[kMAXCLU];
Float_t cluEta[kMAXCLU], cluPhi[kMAXCLU], cluET[kMAXCLU];
Float_t ehad[kMAXCLU], iacc[kMAXCLU];
Float_t etmin = 0;
Float_t etmax, dr,dphia,phic,deta,dphi,adphi,acluphi,esum,detaphi;
Float_t etaBarrel;
Int_t icmax = 0;
nclusters = 0;
while(1) {
etmax = 0;
for (ic=0;ic<ncells;ic++) {
if (m_CellFlag[ic] != 2) continue;
if (m_CellSumPT[ic] <= etmax) continue;
icmax = ic;
eta = m_CellEta[ic];
phi = m_CellPhi[ic];
etmax = m_CellSumPT[ic];
}
if (etmax < m_MinETInitiator) break;
m_CellFlag[icmax] = 1;
cluCode[nclusters] = 98;
cluCells[nclusters] = 1;
cluParts[nclusters] = m_CellCount[icmax];
cluFlag[nclusters] = 1;
cluEta0[nclusters] = eta;
cluPhi0[nclusters] = phi;
cluEta[nclusters] = 0;
cluPhi[nclusters] = 0;
cluET[nclusters] = 0;
//........................................................
//...Sum up unused cells within required distance of initiator.
//........................................................
abseta = TMath::Abs(eta);
etaBarrel = abseta - m_BarrelForwardEta;
for (ic=0;ic<ncells;ic++) {
if (m_CellFlag[ic] == 0) continue;
phic = m_CellPhi[ic];
dphia = TMath::Abs(phic - phi);
if (dphia > kPI) phic += TMath::Sign(k2PI,phi);
deta = m_CellEta[ic] - eta;
dphi = phic - phi;
detaphi = deta*deta+dphi*dphi;
if (etaBarrel < 0 && detaphi > rconeb2) continue;
if (etaBarrel > 0 && detaphi > rconef2) continue;
m_CellFlag[ic] = -m_CellFlag[ic];
cluCells[nclusters]++;
cluParts[nclusters] += m_CellCount[ic];
cluEta[nclusters] += m_CellSumPT[ic]*m_CellEta[ic];
cluPhi[nclusters] += m_CellSumPT[ic]*phic;
cluET[nclusters] += m_CellSumPT[ic];
}
//........................................................
//...Reject cluster below minimum ET, else accept.
//........................................................
if (m_CellsEsharing == 0) etmin = m_MinETCalo;
if (m_CellsEsharing == 1) etmin = m_MinETInitiator;
if (cluET[nclusters] < etmin) {
for (ic=0;ic<ncells;ic++) {
if (m_CellFlag[ic] < 0) m_CellFlag[ic] = -m_CellFlag[ic];
}
} else {
cluEta[nclusters] /= cluET[nclusters];
cluPhi[nclusters] /= cluET[nclusters];
acluphi = TMath::Abs(cluPhi[nclusters]);
if (acluphi > kPI) cluPhi[nclusters] -= TMath::Sign(k2PI,cluPhi[nclusters]);
for (ic=0;ic<ncells;ic++) {if (m_CellFlag[ic] < 0) m_CellFlag[ic] = 0;}
nclusters++;
if (nclusters >= kMAXCLU) {
Error("Make","Too many clusters=%d",nclusters);
}
}
} //end of while
//........................................................
// ...Arrange clusters in falling ET sequence.
//........................................................
gATLFast->SortDown(nclusters, cluET, sortindex);
for (k=0;k<nclusters;k++) {
ij = sortindex[k];
clusterCells[k] = cluCells[ij];
clusterParts[k] = cluParts[ij];
clusterFlag[k] = cluFlag[ij];
clusterEta0[k] = cluEta0[ij];
clusterPhi0[k] = cluPhi0[ij];
clusterEta[k] = cluEta[ij];
clusterPhi[k] = cluPhi[ij];
clusterET[k] = cluET[ij];
}
//.....histogram NCLU
// printf("nparticles=%d, ncells=%d, nclusters=%dn",nparticles,ncells,nclusters);
m_Multiplicity->Fill(nclusters+0.01);
//........................................................
//...recalibrate for the energy sharing
//...loop on cells, share energy deposition in cells between clusters
//........................................................
if (m_CellsEsharing == 1) {
for (i=0;i<nclusters;i++) ehad[i] = 0;
for (i=0;i<ncells;i++) {
eta = m_CellEta[i];
phi = m_CellPhi[i];
esum = 0;
abseta = TMath::Abs(eta);
etaBarrel = abseta -m_BarrelForwardEta;
for (k=0;k<nclusters;k++) {
iacc[k] = 0;
deta = eta - clusterEta0[k];
dphi = phi - clusterPhi0[k];
adphi = TMath::Abs(dphi) -k2PI;
if (TMath::Abs(dphi) > kPI) dr = deta*deta + adphi*adphi;
else dr = deta*deta + dphi*dphi;
if (etaBarrel <= 0 && dr > rconeb2) continue;
if (etaBarrel > 0 && dr > rconef2) continue;
//...cluster K contains the running cell
//...esum is the total energy of jets containing the running cell
iacc[k] = 1;
esum += clusterET[k]*TMath::CosH(clusterEta0[k]);
}
//...redistribute the energy of the running cell among corresponding clusters
for (k=0;k<nclusters;k++) {
if (iacc[k] == 0) continue;
//...cluster K contains the running cell
//...the cell ene is shared among the overlaping clusters according to their energy
ehad[k] += m_CellSumPT[i]*TMath::CosH(m_CellEta[i])*clusterET[k]*TMath::CosH(clusterEta0[k])/esum;
}
}
//...update cluster energies
for (k=0;k<nclusters;k++) {
clusterET[k] = ehad[k]/TMath::CosH(clusterEta0[k]);
}
//........................................................
//.....rearrange clusters in falling E_T sequence
//........................................................
gATLFast->SortDown(nclusters, clusterET, sortindex);
for (k=0;k<nclusters;k++) {
ij = sortindex[k];
if (clusterET[ij] < m_MinETCalo) { nclusters = k; break; }
cluCells[k] = clusterCells[ij];
cluParts[k] = clusterParts[ij];
cluFlag[k] = clusterFlag[ij];
cluEta0[k] = clusterEta0[ij];
cluPhi0[k] = clusterPhi0[ij];
cluEta[k] = clusterEta[ij];
cluPhi[k] = clusterPhi[ij];
cluET[k] = clusterET[ij];
}
} // end of loop for energy sharing
//........................................................
//....Store clusters in Root ClonesArray
//........................................................
m_Ncells = ncells;
m_Nclusters = 0;
for (k=0;k<nclusters;k++) {
AddCluster(cluCode[k],
cluCells[k],
cluParts[k],
cluFlag[k],
cluEta0[k],
cluPhi0[k],
cluEta[k],
cluPhi[k],
cluET[k]);
}
//........................................................
//....reconstruct baricenter of particles
//........................................................
Float_t etarec, ptrec, phirec;
for (k=0;k<nclusters;k++) {
etarec = ptrec = phirec = 0;
for (i=0;i<nparticles;i++) {
part = (TMCParticle*)particles->UncheckedAt(i);
KS = part->GetKS();
if (KS <= 0 || KS > 10) continue;
KF = part->GetKF();
pz = part->GetPz();
if (pPT2[i] <= ptlrat*pz*pz) continue;
kc = mcarlo->Compress(KF);
if (kc == 0 || kc == 12 || kc == 14 || kc == 16) continue;
if (kc == 13 || kc == kFLSP) continue;
detphi = 0;
pt = pPT[i];
eta = pEta[i];
phi = pPhi[i];
pE = part->GetEnergy();
if (gATLFast->Bfield() == 1 && mcarlo->Charge(KF) != 0) {
if (pt < m_MinPTBfield) continue;
chrg = mcarlo->Charge(KF)/3.;
if (TMath::Abs(pz/pE) < 1.) {
theta = TMath::ACos(pz/pE);
} else {
if (pz > 0) theta = 0;
if (pz < 0) theta = kPI;
}
detphi= chrg*FieldPhi(pt,eta,theta);
}
phi += detphi;
dphia = TMath::Abs(cluPhi0[k] - phi);
if (dphia > kPI) dphia -= k2PI;
deta = cluEta0[k] - eta;
etaBarrel = TMath::Abs(cluEta0[k]) - m_BarrelForwardEta;
detaphi = deta*deta + dphia*dphia;
if (etaBarrel < 0 && detaphi > rconeb2) continue;
if (etaBarrel > 0 && detaphi > rconef2) continue;
ptrec += pt;
etarec += eta*pt;
phirec += phi*pt;
}
etarec /= ptrec;
phirec /= ptrec;
deta = etarec - cluEta[k];
dphi = phirec - cluPhi[k];
dr = TMath::Sqrt(deta*deta + dphi*dphi);
m_EtaClu->Fill(deta);
m_PhiClu->Fill(dphi);
m_DeltaR->Fill(dr);
}
return 0;
}
//_____________________________________________________________________________
void ATLFClusterMaker::PrintInfo()
{
ATLFMaker::PrintInfo();
}
//_____________________________________________________________________________
void ATLFClusterMaker::RemoveCluster(const Int_t cluster)
{
TClonesArray &clusters = *(TClonesArray*)m_Fruits;
clusters.RemoveAt(cluster);
clusters.Compress();
m_Nclusters--;
}
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.