//*************************************************************************
//* ======================
//* ANLJetFinder Classes
//* ======================
//*
//* (Description)
//* Jet finder classes for JLC analyses
//* (Requires)
//* class TLorentzVector
//* class Lockable
//* class ANL4DVector
//* (Provides)
//* class ANLJet
//* class ANLJetFinder
//* class ANLJadeJetFinder
//* class ANLJadeEJetFinder
//* class ANLDurhamJetFinder
//* (Usage)
//* // Example
//* Double_t ycut = 0.01;
//* ANLJadeEJetFinder jclust(ycut);
//* jclust.Initialize(tracks); // tracks: TObjArray of LVector derivatives.
//* jclust.FindJets(); // finds jets with ycut = 0.01.
//* ycut = 0.015;
//* jclust.SetYcut(ycut); // One can make the ycut "bigger"
//* jclust.FindJets(); // and resume with the new ycut.
//* ycut = 0.05;
//* ANLJadeEJetFinder jclust2(jclust);
//* jclust2.SetYcut(ycut); // One can copy the previous jet finder
//* jclust2.FindJets(); // and resume with the new "bigger" ycut.
//* Int_t njets = 2; // One can also force the event to be
//* jclust2.ForceNJets(njets); // "njets" jets.
//* (Caution)
//* One CANNOT decrease the ycut without restoring track information
//* by reinvoking the "Initialize" member function.
//* On the other hand, one can increase the ycut and resume jet
//* finding starting from the last result, thereby saving CPU time.
//* (Update Recored)
//* 1999/07/30 K.Fujii Original version derived from Rob Shanks's
//* LCD version. This version heavily uses
//* ROOT facilities to simplify algorithm.
//* It allows one to "increase" the last ycut
//* and resume jet finding. It also allows one
//* to force an event to be "n" jets.
//* 1999/08/14 K.Fujii Modified GetYmass as suggested by M.Iwasaki.
//* 1999/09/05 K.Ikematsu Replaced LockableLVector with ANL4DVector.
//* 1999/09/14 K.Ikematsu Added GetYmax method.
//* 2000/03/28 K.Ikematsu Bug fixed about fYmassMax.
//* 2000/10/12 K.Ikematsu Added maximum trial in ycut search part
//* of ForceNJets method. If binary search
//* reaches maximum trial, ForceNJets method
//* aborts to find ycut making "n" jets.
//* So you have to confirm to be "n" jets in
//* your analysis program.
//* 2001/10/22 K.Ikematsu Added virtual NewJet method
//* instead of ANLJet *jet = new ANLJet();
//* and changed fEvis member to protected
//* to overload in ANLCheatedJetFinder class.
//* 2001/10/22 K.Ikematsu Changed Merge method to virtual
//* for overloading in ANLTaggedJet class.
//* 2001/10/24 K.Ikematsu Added virtual NewJetFinder method.
//*
//* $Id: ANLJetFinder.cxx,v 1.7 2001/12/17 19:07:26 ikematsu Exp $
//*************************************************************************
//
#include "ANLJetFinder.h"
//_____________________________________________________________________
// ------------
// ANLJet Class
// ------------
//
ClassImp(ANLJet)
//*--
//* Constructors
//*--
ANLJet::ANLJet() : ANL4DVector(0.), fParts(1) {}
ANLJet::ANLJet(const TObjArray &parts) : ANL4DVector(0.), fParts(parts) {
TIter next(&parts);
TObject *obj;
while ((obj = next())) *this += *(ANL4DVector *)obj;
}
//*--
//* Destructor
//*--
ANLJet::~ANLJet() { fParts.Clear(); }
//*--
//* Getters
//*--
Int_t ANLJet::GetNparticles() const { return fParts.GetEntries(); }
const TObjArray & ANLJet::GetParticlesInJet() const { return fParts; }
const ANL4DVector & ANLJet::operator()() const { return *this; }
//*--
//* Setters
//*--
void ANLJet::Add(TObject *part) {
fParts.Add(part);
*this += *(ANL4DVector *)part;
// ::operator+=(*(ANL4DVector *)this,*(ANL4DVector *)part);
}
void ANLJet::Merge(TObject *part) { Add(part); }
void ANLJet::Merge(ANLJet *jet) {
TIter next(&jet->fParts);
TObject *obj;
while ((obj = next())) fParts.Add(obj);
*this += *jet;
}
void ANLJet::Remove(TObject *part) {
*this -= *(ANL4DVector *)part;
fParts.Remove(part);
}
//*--
//* Misc. Services
//*--
void ANLJet::DebugPrint(const Char_t *opt) const {
cerr << "Number of particles in jets = " << GetNparticles() << endl;
ANL4DVector::DebugPrint(opt);
if (opt == "Detailed") {
TIter next(&fParts);
ANL4DVector *p;
Int_t np = 0;
while((p = (ANL4DVector *)next())) {
cerr << "Particle " << ++np << endl;
p->DebugPrint(opt);
}
}
}
//_____________________________________________________________________
// ------------------
// ANLJetFinder Class
// ------------------
//
ClassImp(ANLJetFinder)
//*--
//* Constructors
//*--
ANLJetFinder::ANLJetFinder(Double_t y)
: fDone(kFALSE), fYcut(y), fJets(1),
fYmass(0), fYmassMax(0.), fEvis(0.) {}
ANLJetFinder::ANLJetFinder(const ANLJetFinder &jf)
: fDone(jf.fDone), fYcut(jf.fYcut), fJets(1),
fYmass(0), fYmassMax(jf.fYmassMax), fEvis(jf.fEvis) {
CopyJets(jf.fJets);
}
//*--
//* Destructor
//*--
ANLJetFinder::~ANLJetFinder() {
DeleteJets(); // clean the array of Jet's
if (fYmass) delete fYmass; // clean the pair mass array
}
//*--
//* Private service methods
//*--
void ANLJetFinder::CopyJets(const TObjArray &jets) {
DeleteJets();
TIter next(&jets);
TObject *obj;
while ((obj = next())) {
ANLJet *jet = NewJet();
jet->Merge((ANLJet *)obj);
fJets.Add(jet);
}
}
void ANLJetFinder::DeleteJets() {
fJets.Delete();
}
//*--
//* Getters
//*--
Bool_t ANLJetFinder::IsInitialized() const {
if (fJets.GetEntries() > 0) return kTRUE;
else return kFALSE;
}
Double_t ANLJetFinder::GetYcut() const { return fYcut; }
Double_t ANLJetFinder::GetYmax() {
if (!fDone) FindJets();
return fYmassMax/(fEvis*fEvis);
}
Int_t ANLJetFinder::GetNjets() {
if (!fDone) FindJets();
return fJets.GetEntries();
}
TObjArray & ANLJetFinder::GetJets() {
if (!fDone) FindJets();
return fJets;
}
//*--
//* Setters
//*--
void ANLJetFinder::SetYcut(Double_t ycut) {
if (ycut != fYcut) {
fDone = kFALSE;
fYcut = ycut;
}
}
void ANLJetFinder::Initialize(const TObjArray &parts) {
fDone = kFALSE;
DeleteJets();
fEvis = 0.;
//
// Store each unlocked object as a single jet.
//
TIter next(&parts);
TObject *obj;
while ((obj = next())) {
if (!obj->IsA()->InheritsFrom("ANL4DVector")) {
cerr << "ANLJetFinder::Initialize input is not a ANL4DVector" << endl;
continue;
}
if (((ANL4DVector *)obj)->IsLocked()) continue;
ANLJet *jet = NewJet();
jet->Merge(obj); // obj can be a jet, instead of being a track.
fEvis += jet->E();
fJets.Add(jet);
}
}
ANLJetFinder & ANLJetFinder::operator=(const ANLJetFinder & jf) {
fDone = jf.fDone;
fYcut = jf.fYcut;
fEvis = jf.fEvis;
CopyJets(jf.fJets);
if (fYmass) { delete fYmass; fYmass = 0; }
return *this;
}
//*--
//* Basic Services
//*--
void ANLJetFinder::FindJets() {
if (fDone) return;
if (!IsInitialized()) {
cout << "ANLJetFinder::FindJets : No particles in the stack" << endl
<< " Set them and retry." << endl;
return;
}
fDone = kTRUE;
Int_t np = fJets.GetEntries(); // There is yet no gap in fJets here.
if (np < 2) return;
//
// Initialize pair mass matrix.
//
if (fYmass) delete fYmass;
fYmass = new TMatrix(np,np);
TMatrix &ymass = *fYmass;
Int_t i, j;
for (i = 0; i < np - 1; i++) {
for (j = i + 1; j < np; j++) {
ANLJet &jeti = *(ANLJet *)fJets.UncheckedAt(i);
ANLJet &jetj = *(ANLJet *)fJets.UncheckedAt(j);
ymass(i,j) = GetYmass(jeti(),jetj());
}
}
//
// Start jet clustering
//
Double_t masscut = fYcut*fEvis*fEvis;
while (kTRUE) {
Int_t i, im = -1;
Int_t j, jm = -1;
Double_t minmass = 1.e+10;
for (i = 0; i < np - 1; i++) {
if (!(fJets.UncheckedAt(i))) continue;
for (j = i + 1; j < np; j++) {
if (!(fJets.UncheckedAt(j))) continue;
if (ymass(i,j) > minmass) continue;
minmass = ymass(i,j);
im = i;
jm = j;
}
}
if (minmass > masscut) {
fYmassMax = minmass;
break;
}
//
// Pair (im,jm) accepted.
//
ANLJet *oim = (ANLJet *)fJets.UncheckedAt(im);
ANLJet *ojm = (ANLJet *)fJets.UncheckedAt(jm);
oim->Merge(ojm); // Merge Jet j to i.
fJets.Remove(ojm); // Remove jet j from fJets
delete ojm; // Delete jet j
//
// Update the pair mass array.
//
for (j = 0; j < np; j++) {
if (j == im) continue;
ANLJet *oj = (ANLJet *)fJets.UncheckedAt(j);
if (oj == 0) continue;
ymass(TMath::Min(j,im),TMath::Max(j,im)) = GetYmass(*oim,*oj);
}
}
//
// Eliminate empty slots.
//
fJets.Compress();
}
void ANLJetFinder::ForceNJets(Int_t njets) {
if (njets < 1) {
cout << "ANLJetFinder::ForceNJets : njets = " << njets
<< " invalied" << endl;
return;
}
if (!fDone) FindJets(); // Find jets if not yet.
if (GetNjets() <= njets) return; // No further clustering necessary.
//
// Binary search ycut to make njets Jet's.
//
Double_t ycutLo = fYcut;
Double_t ycutHi = 1.0;
Double_t ycut;
ANLJetFinder *jf = 0;
Int_t ntrial = 0;
while (kTRUE) {
ntrial++;
ycut = (ycutLo + ycutHi)/2;
jf = NewJetFinder(this);
SetYcut(ycut);
FindJets();
Int_t nj = GetNjets();
if (ntrial > 100) cerr << "ANLJetFinder::ForceNJets : Making "
<< njets << "Jets was aborted ! Njets = "
<< nj << endl;
if (nj == njets || ntrial > 100) { delete jf; break; } // Found a valid ycut, quit looping.
if (nj > njets) {
ycutLo = ycut;
} else {
ycutHi = ycut;
*this = *jf;
}
delete jf;
}
}
Double_t ANLJetFinder::GetYmass(const ANL4DVector &p1,
const ANL4DVector &p2) const { return 0; }
//_____________________________________________________________________
// ----------------------
// ANLJadeJetFinder Class
// ----------------------
//
ClassImp(ANLJadeJetFinder)
ANLJadeJetFinder::ANLJadeJetFinder(Double_t y) : ANLJetFinder(y) {}
Double_t ANLJadeJetFinder::GetYmass(const ANL4DVector &p1,
const ANL4DVector &p2) const {
return 2 * p1.E() * p2.E() * ( 1 - p1.CosTheta(p2) );
}
//_____________________________________________________________________
// -----------------------
// ANLJadeEJetFinder Class
// -----------------------
//
ClassImp(ANLJadeEJetFinder)
ANLJadeEJetFinder::ANLJadeEJetFinder(Double_t y) : ANLJetFinder(y) {}
Double_t ANLJadeEJetFinder::GetYmass(const ANL4DVector &p1,
const ANL4DVector &p2) const {
return (p1+p2).GetMass2();
}
//_____________________________________________________________________
// ------------------------
// ANLDurhamJetFinder Class
// ------------------------
//
ClassImp(ANLDurhamJetFinder)
ANLDurhamJetFinder::ANLDurhamJetFinder(Double_t y) : ANLJetFinder(y) {}
Double_t ANLDurhamJetFinder::GetYmass(const ANL4DVector &p1,
const ANL4DVector &p2) const {
Double_t minE = TMath::Min(p1.E(),p2.E());
return 2 * minE * minE * ( 1 - p1.CosTheta(p2) );
}
ROOT page - Home 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.