// ************************************************************************** // * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * // * * // * Author: The ALICE Off-line Project. * // * Contributors are mentioned in the code where appropriate. * // * * // * Permission to use, copy, modify and distribute this software and its * // * documentation strictly for non-commercial purposes is hereby granted * // * without fee, provided that the above copyright notice appears in all * // * copies and that both the copyright notice and this permission notice * // * appear in the supporting documentation. The authors make no claims * // * about the suitability of this software for any purpose. It is * // * provided "as is" without express or implied warranty. * // ************************************************************************** //----------------------------------------------------------------------------------- // Jet finder based on Deterministic Annealing // For further informations about the DA working features see: // Phys.Lett. B601 (2004) 56-63 (http://arxiv.org/abs/hep-ph/0407214) // Author: Davide Perrino (davide.perrino@ba.infn.it, davide.perrino@cern.ch) //----------------------------------------------------------------------------------- #include #include #include #include "AliJetReaderHeader.h" #include "AliJetReader.h" #include "AliDAJetHeader.h" #include "AliDAJetFinder.h" ClassImp(AliDAJetFinder) //----------------------------------------------------------------------------------- AliDAJetFinder::AliDAJetFinder(): AliJetFinder(), fAlpha(1.01), fDelta(1e-8), fAvDist(1e-6), fEps(1e-4), fEpsMax(1e-2), fNloopMax(100), fBeta(0.1), fNclustMax(0), fNin(0), fNeff(0) { // Constructor } //----------------------------------------------------------------------------------- AliDAJetFinder::~AliDAJetFinder() { // Destructor } //----------------------------------------------------------------------------------- void AliDAJetFinder::FindJets() { // Find the jets in current event // Float_t betaStop=100.; fDebug = fHeader->GetDebug(); Double_t dEtSum=0; Double_t *xData[2]; TVectorD *vPx = new TVectorD(); TVectorD *vPy = new TVectorD(); TMatrixD *mPyx= new TMatrixD(); TMatrixD *mY = new TMatrixD(); InitDetAnn(dEtSum,xData,vPx,vPy,mPyx,mY); if (fNin < fNclustMax){ delete [] xData[0], delete [] xData[1]; delete vPx; delete vPy; delete mPyx; delete mY; return; } Int_t nc=1, nk; DoubleClusters(nc,nk,vPy,mY); do{ //loop over beta fBeta*=fAlpha; Annealing(nk,xData,vPx,vPy,mPyx,mY); NumCl(nc,nk,vPy,mPyx,mY); }while((fBetaGetFixedCl() ? ((AliDAJetHeader*)fHeader)->GetNclustMax() : TMath::Max((Int_t)TMath::Sqrt(fNin),5); Float_t etaEff = ((AliDAJetHeader*)fHeader)->GetEtaEff(); TClonesArray *lvArray = fReader->GetMomentumArray(); Int_t nEntr = lvArray->GetEntries(); fNin=0; for (Int_t iEn=0; iEnGetCutFlag(iEn)==1) fNin++; fNeff = ((AliDAJetHeader*)fHeader)->GetNeff(); fNeff = TMath::Max(fNeff,fNin); Double_t *xEta = new Double_t[fNeff]; Double_t *xPhi = new Double_t[fNeff]; xData[0]=xEta; xData[1]=xPhi; vPx->ResizeTo(fNeff); Int_t iIn=0; for (Int_t iEn=0; iEnGetCutFlag(iEn)==0) continue; TLorentzVector *lv=(TLorentzVector*)lvArray->At(iEn); xEta[iIn] = lv->Eta(); xPhi[iIn] = lv->Phi()<0 ? lv->Phi() + 2*TMath::Pi() : lv->Phi(); (*vPx)(iIn)=lv->Pt(); dEtSum+=(*vPx)(iIn); iIn++; } TRandom2 r; r.SetSeed(0); for (iIn=fNin; iInResizeTo(fNeff,njdim); mY->ResizeTo(4,njdim); vPy->ResizeTo(njdim); mY->Zero();mPyx->Zero();vPy->Zero(); (*vPy)(0)=1; TMatrixDColumn(*mPyx,0)=1; Double_t ypos=0,xpos=0; for (iIn=0; iIn0) ? atan2(ypos,xpos) : atan2(ypos,xpos)+2*TMath::Pi(); } //----------------------------------------------------------------------------------- void AliDAJetFinder::DoubleClusters(Int_t nc,Int_t &nk, TVectorD *vPy, TMatrixD *mY) const { // Return double clusters for(Int_t iClust=0; iClustGetReaderHeader()->GetFiducialEtaMax(),pi}; TVectorD vPart(2); Double_t *m = new Double_t[nk]; Double_t chi,chi1; do{ Int_t nloop=0; for (Int_t iClust=0; iClustRndm(24); ry->Randomize(-0.5,0.5,seed); for (Int_t i=0; i<2; i++){ for (Int_t iClust=0; iClustZero(); y->Zero(); //recalculate codevectors for (Int_t iClust=0; iClust0) ? atan2(ypos,xpos) : atan2(ypos,xpos)+2*pi; } //verify codevectors' stability chi=0; for (Int_t iClust=0; iClustchi) chi=chi1; } chi=TMath::Sqrt(chi); for (Int_t iClust=0; iClustfNloopMax){ if (chi500) break; } }while (chi>fEps); }while (chi>fEpsMax); for (Int_t iClust=0; iClust= fNclustMax) growcl=false; //recalculate the nc distinct codevectors TMatrixD *pyx = new TMatrixD(fNeff,2*nc); TVectorD *py = new TVectorD(nk); TMatrixD *y1 = new TMatrixD(3,nk); for (Int_t iClust=0; iClust nk/2){ for (Int_t iClust=0; iClustZero(); mPyx->Zero(); vPy->Zero(); for (Int_t iIn=0; iIn0){ Double_t xpos=0,ypos=0,pxy; for (Int_t iIn=0; iIn0) ? atan2(ypos,xpos) : atan2(ypos,xpos)+2*TMath::Pi(); (*mY)(3,k)=(*mY)(3,iClust); k++; } } nk=k; } //----------------------------------------------------------------------------------- void AliDAJetFinder::StoreJets(Int_t nk, Double_t **xData, Int_t *xx, TMatrixD *mY) { //evaluate significant clusters properties const Double_t pi=TMath::Pi(); AliJetReaderHeader *rHeader=fReader->GetReaderHeader(); Float_t dFidEtaMax = rHeader->GetFiducialEtaMax(); Float_t dFidEtaMin = rHeader->GetFiducialEtaMin(); Float_t dFiducialEta= dFidEtaMax - dFidEtaMin; Double_t *xEta = xData[0]; Double_t *xPhi = xData[1]; Int_t nEff = 0; for (Int_t i=0; idFidEtaMin) nEff++; Double_t dMeanDist=0.; if (nEff > 0) dMeanDist=TMath::Sqrt(2*dFiducialEta*pi/nEff); Bool_t *isJet = new Bool_t[nk]; Double_t *etNoBg= new Double_t[nk]; Double_t *dDeltaEta=new Double_t[nk]; Double_t *dDeltaPhi=new Double_t[nk]; Double_t *surf = new Double_t[nk]; Double_t *etDens= new Double_t[nk]; for (Int_t iClust=0; iClustdFidEtaMax || xEta[iIn] dEtaMax) dEtaMax=xEta[iIn]; Double_t dPhi=xPhi[iIn]-(*mY)(1,iClust); if (dPhi > pi ) dPhi-=2*pi; else if (dPhi < (-1)*pi) dPhi+=2*pi; if (dPhi < dPhiMin) dPhiMin=dPhi; else if (dPhi > dPhiMax) dPhiMax=dPhi; } dDeltaEta[iClust]=dEtaMax-dEtaMin+dMeanDist; dDeltaPhi[iClust]=dPhiMax-dPhiMin+dMeanDist; surf[iClust]=0.25*pi*dDeltaEta[iClust]*dDeltaPhi[iClust]; etDens[iClust]=(*mY)(3,iClust)/surf[iClust]; } if (((AliDAJetHeader*)fHeader)->GetSelJets()){ for (Int_t iClust=0; iClustdFidEtaMin){ Double_t etDensMed=0.; Double_t etDensSqr=0.; Int_t norm=0; for (Int_t iClust1=0; iClust1dFidEtaMin){ etDensMed+=etDens[iClust1]; etDensSqr+=TMath::Power(etDens[iClust1],2); norm++; } } etDensMed/=TMath::Max(norm,1); etDensSqr/=TMath::Max(norm,1); Double_t deltaEtDens=TMath::Sqrt(etDensSqr-TMath::Power(etDensMed,2)); if ((*mY)(3,iClust) > (etDensMed+deltaEtDens)*surf[iClust]) isJet[iClust]=kTRUE; etNoBg[iClust]=(*mY)(3,iClust)-etDensMed*surf[iClust]; } } for (Int_t iClust=0; iClustGetEtMin()){ isJet[iClust]=kFALSE; iClust=-1; } } } } else { for (Int_t iClust=0; iClustClassName(),"AliJetAODReader"); if (fromAod) refs = fReader->GetReferences(); for (Int_t iClust=0; iClustGetMomentumArray()->GetEntries(); for (Int_t iEn=0; iEnGetCutFlag(iEn)==0) continue; if (xx[iIn]==iCl) jet.AddTrack(refs->At(iEn)); iIn++; } } AddJet(jet); if (fDebug > 0) printf("jet %d, Eta: %f, Phi: %f, Et: %f\n",iCl,jet.Eta(),jet.Phi(),jet.Pt()); } } delete [] dDeltaEta; delete [] dDeltaPhi; delete [] etNoBg; delete [] isJet; delete [] iSort; } //----------------------------------------------------------------------------------- Double_t Dist(TVectorD x,TVectorD y) { // Squared distance const Double_t pi=TMath::Pi(); Double_t dphi=TMath::Abs(x(1)-y(1)); if (dphi > pi) dphi=2*pi-dphi; Double_t dist=pow(x(0)-y(0),2)+pow(dphi,2); return dist; }