1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
16 //---------------------------------------------------------------------
18 // interface to FastJet algorithm
19 // Author: Rafael.Diaz.Valdes@cern.ch
21 //---------------------------------------------------------------------
23 #include <Riostream.h>
24 #include <TLorentzVector.h>
30 #include <TClonesArray.h>
32 #include "AliFastJetFinder.h"
33 #include "AliFastJetHeader.h"
34 #include "AliJetReaderHeader.h"
35 #include "AliJetReader.h"
38 #include "FjPseudoJet.hh"
39 #include "FjClusterSequence.hh"
42 ClassImp(AliFastJetFinder);
45 ////////////////////////////////////////////////////////////////////////
47 AliFastJetFinder::AliFastJetFinder():
56 ////////////////////////////////////////////////////////////////////////
58 AliFastJetFinder::~AliFastJetFinder()
64 ////////////////////////////////////////////////////////////////////////
67 void AliFastJetFinder::FindJets()
70 //create cells and jets array
71 // 1) transform input to pt,eta,phi plus lego
72 TClonesArray *lvArray = fReader->GetMomentumArray();
73 Int_t nIn = lvArray->GetEntries();
76 // local arrays for particles input
77 Float_t* enT = new Float_t[nIn];
78 Float_t* ptT = new Float_t[nIn];
79 Float_t* etaT = new Float_t[nIn];
80 Float_t* phiT = new Float_t[nIn];
81 Int_t* injet = new Int_t[nIn];
84 //total energy in array
85 Float_t EtTotal = 0.0;
86 Float_t meanptCell = 0.0;
87 Float_t sqptCell = 0.0;
90 // load input vectors in fLego
91 for (Int_t i = 0; i < nIn; i++){
92 TLorentzVector *lv = (TLorentzVector*) lvArray->At(i);
93 enT[i] = lv->Energy();
96 phiT[i] = ((lv->Phi() < 0) ? (lv->Phi()) + 2 * TMath::Pi() : lv->Phi());
97 if (fReader->GetCutFlag(i) == 1){
98 fLego->Fill(etaT[i], phiT[i], ptT[i]);
99 if(fReader->GetSignalFlag(i) == 1)
100 fLegoSignal->Fill(etaT[i], phiT[i], ptT[i]);
101 EtTotal= EtTotal+ptT[i];
104 fJets->SetNinput(nIn);
106 // add soft background fixed
107 Int_t nsoft = (fHeader->GetLegoNbinEta())*(fHeader->GetLegoNbinPhi());
108 Float_t* ptRndm = new Float_t[nsoft];
109 if(fHeader->AddSoftBackg()){
110 gRandom->RndmArray(nsoft,ptRndm);
111 for(Int_t isoft = 0; isoft < nsoft; isoft++){
112 Float_t ptsoft = 0.005*ptRndm[isoft];
113 EtTotal= EtTotal+ptsoft;
126 Float_t* etCell = new Float_t[90000]; //! Cell Energy // check enough space! *to be done*
127 Float_t* etaCell = new Float_t[90000]; //! Cell eta
128 Float_t* phiCell = new Float_t[90000]; //! Cell phi
129 Int_t* jetflagCell = new Int_t[90000]; //! Cell flag for jets
130 Float_t* etsigCell = new Float_t[90000]; // signal in this cell
133 Float_t* etaJet = new Float_t[200];
134 Float_t* phiJet = new Float_t[200];
135 Float_t* etJet = new Float_t[200];
136 Float_t* etsigJet = new Float_t[200]; //signal energy
137 Float_t* etallJet = new Float_t[200]; //total energy in jet area
138 Int_t* ncellsJet = new Int_t[200];
139 memset(etaJet,0,sizeof(Float_t)*200);
140 memset(phiJet,0,sizeof(Float_t)*200);
141 memset(etJet,0,sizeof(Float_t)*200);
142 memset(etsigJet,0,sizeof(Float_t)*200);
143 memset(etallJet,0,sizeof(Float_t)*200);
144 memset(ncellsJet,0,sizeof(Int_t)*200);
150 TAxis* xaxis = fLego->GetXaxis();
151 TAxis* yaxis = fLego->GetYaxis();
152 Float_t e = 0.0; Float_t esig = 0.0;
154 for (Int_t ib = 1; ib <= fHeader->GetLegoNbinEta(); ib++) {
155 for (Int_t jb = 1; jb <= fHeader->GetLegoNbinPhi(); jb++) {
156 e = fLego->GetBinContent(ib,jb);
157 if (e < 0.0) continue; // don't include this cells
158 Float_t eta = xaxis->GetBinCenter(ib);
159 Float_t phi = yaxis->GetBinCenter(jb);
160 if(fHeader->AddSoftBackg())
161 etCell[nCell] = e + 0.005*ptRndm[nCell];
164 sqptCell = sqptCell + etCell[nCell]*etCell[nCell]; // xi^2 ////////
165 etaCell[nCell] = eta;
166 phiCell[nCell] = phi;
167 jetflagCell[nCell] = -1; //default
168 esig = fLegoSignal->GetBinContent(ib,jb);
170 etsigCell[nCell] = esig;
172 etsigCell[nCell] = 0.0;
177 meanptCell = EtTotal/(Float_t)nCell;
178 sqptCell = sqptCell/(Float_t)nCell;
181 //call to FastJet Algorithm
182 RunAlgorithm(nJets,etJet,etaJet,phiJet,etsigJet,etallJet,ncellsJet,
183 nCell,etCell,etaCell,phiCell,etsigCell,jetflagCell);
186 //subtract background
187 SubtractBackg(nCell,jetflagCell,etCell,
188 nJets,etJet,etallJet,ncellsJet,
189 meanptCell,sqptCell,EtTotal);
193 Int_t* index = new Int_t[nJets];
195 for(Int_t kj=0; kj<nJets; kj++){
196 if ((etaJet[kj] > (fHeader->GetJetEtaMax())) ||
197 (etaJet[kj] < (fHeader->GetJetEtaMin())) ||
198 (etJet[kj] < fHeader->GetMinJetEt())) continue; // acceptance eta range and etmin
199 Float_t px, py,pz,en; // convert to 4-vector
200 px = etJet[kj] * TMath::Cos(phiJet[kj]);
201 py = etJet[kj] * TMath::Sin(phiJet[kj]);
202 pz = etJet[kj] / TMath::Tan(2.0 * TMath::ATan(TMath::Exp(-etaJet[kj])));
203 en = TMath::Sqrt(px * px + py * py + pz * pz);
204 fJets->AddJet(px, py, pz, en);
209 //add signal percentage and total signal in AliJets for analysis tool
210 Float_t* percentage = new Float_t[nj];
211 Int_t* ncells = new Int_t[nj];
212 Int_t* mult = new Int_t[nj];
214 for(Int_t i = 0; i< nj; i++){
215 percentage[i] = etsigJet[index[i]]/etJet[index[i]];
216 ncells[i] = ncellsJet[index[i]];
219 //reorder injet flags
220 for(Int_t ipar = 0; ipar < nIn; ipar++){
221 Float_t injetflag =0;
222 Int_t iparCell = fLego->FindBin(etaT[ipar], phiT[ipar]);
223 injet[ipar] = jetflagCell[iparCell];
224 for(Int_t js = 0; js < nj; js++){
225 if(injet[ipar] == index[js]){
226 injet[ipar] = js; // set the new jet id value
227 mult[js]++; // add multiplicity in jet js
232 if(injetflag == 0) injet[ipar] = -1; // set default value
236 fJets->SetNCells(ncells);
237 fJets->SetPtFromSignal(percentage);
238 fJets->SetMultiplicities(mult);
239 fJets->SetInJet(injet);
240 fJets->SetEtaIn(etaT);
241 fJets->SetPhiIn(phiT);
243 fJets->SetEtAvg(meanptCell);
273 ////////////////////////////////////////////////////////////////////////
274 void AliFastJetFinder::RunAlgorithm(Int_t& nJets,Float_t* etJet,Float_t* etaJet,Float_t* phiJet,
275 Float_t* etsigJet, Float_t* etallJet, Int_t* ncellsJet,
276 Int_t& nCell,Float_t* etCell,Float_t* etaCell,Float_t* phiCell,
277 Float_t* etsigCell, Int_t* jetflagCell)
280 vector<FjPseudoJet> input_cells; // create a vector
281 for (Int_t i = 0; i < nCell; i++){
282 if(etCell[i] == 0.0) continue; // not include cell empty
283 Double_t px, py,pz,en; // convert to 4-vector
284 px = etCell[i]*TMath::Cos(phiCell[i]);
285 py = etCell[i]*TMath::Sin(phiCell[i]);
286 pz = etCell[i]/TMath::Tan(2.0 * TMath::ATan(TMath::Exp(-etaCell[i])));
287 en = TMath::Sqrt(px * px + py * py + pz * pz);
288 FjPseudoJet input_cell(px,py,pz,en); // create FjPseudoJet object
289 input_cell.set_user_index(i); //label the cell into Fastjet algortihm
290 //push FjPseudoJet of (px,py,pz,en) onto back of the input_cells
291 input_cells.push_back(input_cell);
294 //run the jet clustering with option R=1.0 and strategy= Best
295 Double_t Rparam = fHeader->GetRadius(); // default 1.0;
296 FjClusterSequence clust_seq(input_cells,Rparam);
299 //vector to get clusters
300 vector<FjPseudoJet> clusters;
302 ///////////////////////////////////////////////////////////////////////////
303 //extract the inclusive jets with pt> ptmin sorted by pt
304 //Float_t areaT = 4*(fHeader->GetLegoEtaMax())*TMath::Pi();
305 // Double_t ptbgRc = EtBackgT*(Rparam*Rparam*TMath::Pi()/areaT);
306 // Double_t ptbgRcfluct = dEtTotal*Rparam*TMath::Sqrt(TMath::Pi()/areaT);
307 // Double_t ptmin = ptbgRc + ptbgRcfluct;
308 clusters = clust_seq.inclusive_jets(0);
309 //////////////////////////////////////////////////////////////////////////
311 /////////////////////////////////////////////////////////////////////////
312 //extract the exclusive jets with dcut = 25 GeV**2 and sort them in order
314 //Float_t areaT = 4*(fHeader->GetLegoEtaMax())*TMath::Pi();
315 //Double_t ptbgRc = EtBackgT*(Rparam*Rparam*TMath::Pi()/areaT);
316 //Double_t ptbgRcfluct = dEtTotal*Rparam*TMath::Sqrt(TMath::Pi()/areaT);
317 //Double_t ptmin = ptbgRc + ptbgRcfluct;
318 //Double_t ktbackg = (fHeader->GetKfactor())*ptmin;
319 //Double_t dcut = ktbackg*ktbackg;
320 //clusters = sorted_by_pt(clust_seq.exclusive_jets(dcut));
321 //clusters = sorted_by_pt(clust_seq.exclusive_jets(5));
322 /////////////////////////////////////////////////////////////////////////
325 //cout << " ktClusters " << clusters.size() << endl;
326 nJets = (Int_t)clusters.size();
327 ////////////////////////////////////////////////////////////////////////
328 // add all clusters to jet arrays
329 for(UInt_t ij = 0; ij < clusters.size(); ij++){
331 vector<FjPseudoJet> constituents = clust_seq.constituents(clusters[ij]);
332 //fill jet array info
333 ncellsJet[ij] = (Int_t)constituents.size();
334 phiJet[ij] = clusters[ij].phi();
335 Float_t angle = TMath::ATan(clusters[ij].perp()/clusters[ij].pz());
336 angle = ((angle < 0) ? angle + TMath::Pi() : angle);
337 etaJet[ij] = - TMath::Log(TMath::Tan(angle/2.0));
338 etJet[ij] = clusters[ij].perp();
339 //get constituents cells
340 for(UInt_t jc = 0; jc < constituents.size(); jc++){ // loop for all cells in ij cluster
341 Int_t jcell = constituents[jc].user_index();
342 jetflagCell[jcell] = ij; //flag this cell for jet
343 etsigJet[ij] = etsigJet[ij] + etsigCell[jcell]; // add signal of this cell
344 etallJet[ij] = etallJet[ij] + etCell[jcell]; // add total of this cell
349 ////////////////////////////////////////////////////////////////////////
350 void AliFastJetFinder::SubtractBackg(Int_t& nCell, Int_t* jetflagCell, Float_t* etCell,
351 Int_t& nJets, Float_t* etJet, Float_t* etallJet, Int_t* ncellsJet,
352 Float_t& meanptCell, Float_t& sqptCell, Float_t& etBackg)
354 // simplest method: subtract background from external region to jets
356 //tmp array to flag jets
358 //tmp array to flag jet-cell status
359 Int_t tmpjetflagCell[90000];
361 Float_t etBackgOld = 0;
362 Float_t prec = fHeader->GetPrecBg();
365 while(bgprec > prec){
366 //clear tmpjetflagCell
367 memset(tmpjetflagCell,-1,sizeof(Int_t)*90000); // init with -1 (all cells are background)
369 memset(flagJet,0,sizeof(Int_t)*200); // init with 0 (no flag jets)
370 // select clusters > meantmpCell
371 for(Int_t i = 0; i < nJets; i++){
372 Float_t iptcell = etallJet[i]/(Float_t)ncellsJet[i];
373 if(iptcell < meanptCell) continue; // cluster not selected
374 // convert tmp cell background to jet cell
375 for(Int_t ic = 0; ic < nCell; ic++){ //loop for all cells
376 if(jetflagCell[ic] != i) continue; // other cells
377 tmpjetflagCell[ic] = i; // convert to a jet cell
379 //load total energy in cluster
380 etJet[i] = etallJet[i];
381 flagJet[i] = 1; // flag jet
383 //subtract background
384 for(Int_t j = 0; j < nCell; j++){ // loop for all cells
385 Int_t idxjet = tmpjetflagCell[j];
386 if(idxjet == -1) continue; // background cell
387 if(idxjet == -2) continue; // background protected cell
388 etJet[idxjet] = etJet[idxjet] - meanptCell;
390 // evaluate background fluctuations (rms value)
391 Float_t rmsptCell = TMath::Sqrt(sqptCell - meanptCell*meanptCell);
393 for(Int_t k = 0; k < nJets; k++){
394 if(flagJet[k] != 1) continue; // only flaged jets
395 //if(etJet[k] > fHeader->GetMinJetEt()) continue; // jet ok!!
396 if(etJet[k] > rmsptCell*ncellsJet[k]) continue; // jet ok!!
397 //clear tmpjetflag in cells
398 for(Int_t kc = 0; kc < nCell; kc++){ //loop for all cells
399 if(tmpjetflagCell[kc] != k) continue; // other cells
400 tmpjetflagCell[kc] = -1; // convert to background tmp cell
402 // clear all previous jet flags
406 // recalculate background
408 etBackgOld = etBackg;
410 Int_t nCellBackg = 0;
411 for(Int_t l = 0; l < nCell; l++){ // loop for all cells
412 if(tmpjetflagCell[l] != -1) continue; // cell included in some jet or protected
414 etBackg = etBackg + etCell[l]; //add cell to background
416 sqptCell = sqptCell + etCell[l]*etCell[l];
419 meanptCell = etBackg/(Float_t)nCellBackg; // new pt cell mean value
420 sqptCell = sqptCell/(Float_t)nCellBackg;
425 // evaluate presicion values
427 bgprec = (etBackgOld - etBackg)/etBackg;
432 // set etJet 0 for all clusters not flaged in order to
433 for(Int_t m = 0; m < nJets; m++){
434 if(flagJet[m] == 1) continue; // flaged jets
435 etJet[m] = 0; //others clusters
441 ////////////////////////////////////////////////////////////////////////
442 void AliFastJetFinder::SubtractBackgArea(Int_t& nCell, Int_t* jetflagCell,
443 Float_t* etCell,Int_t&nJets, Float_t* etJet, Float_t* etallJet)
445 // area method: subtract background from external region to jets
446 // using fixed area pi*Rc2
448 // n cells contained in a cone Rc
449 Double_t Rc = fHeader->GetRadius();
450 Float_t nCellRc = Rc*Rc*TMath::Pi()/(0.015*0.015); // change in future !!!!
451 //tmp array to flag fake jets
452 Int_t fakeflagJet[100];
453 memset(fakeflagJet,0,sizeof(Int_t)*100); // init with 0 (no fake jets)
454 Int_t njfake = nJets;
456 //calc background per cell
457 Int_t nCellBackg = 0;
458 Float_t EtBackg = 0.0;
459 for(Int_t i = 0; i < nCell; i++){ // loop for all cells
460 if(jetflagCell[i] != -1) continue; // cell included in some jet
462 EtBackg = EtBackg + etCell[i]; //add cell to background
464 //subtract background energy per jet
465 for(Int_t l = 0; l < nJets; l++){
466 if(fakeflagJet[l] == 1) continue; // fake jet
467 etJet[l] = etallJet[l] - nCellRc*EtBackg/(Float_t)nCellBackg;
471 for(Int_t k = 0; k < nJets; k++){
472 if(fakeflagJet[k] == 1) continue; // fake jet
473 if(etJet[k] < fHeader->GetMinJetEt()){ // a new fake jet
474 //clear jet flag in cells
475 for(Int_t kc = 0; kc < nCell; kc++){ //loop for all cells
476 Int_t kidx = jetflagCell[kc];
477 if(kidx != k) continue; // other cells
478 jetflagCell[kc] = -1; // convert to background cell
480 fakeflagJet[k] = 1; // mark as a fake jet
481 njfake++; //count fakes in this loop
487 ////////////////////////////////////////////////////////////////////////
491 void AliFastJetFinder::Reset()
494 fLegoSignal->Reset();
498 ////////////////////////////////////////////////////////////////////////
500 void AliFastJetFinder::WriteJHeaderToFile()
506 ////////////////////////////////////////////////////////////////////////
508 void AliFastJetFinder::Init()
510 // initializes some variables
513 TH2F("legoH","eta-phi",
514 fHeader->GetLegoNbinEta(), fHeader->GetLegoEtaMin(),
515 fHeader->GetLegoEtaMax(), fHeader->GetLegoNbinPhi(),
516 fHeader->GetLegoPhiMin(), fHeader->GetLegoPhiMax());
518 TH2F("legoSignalH","eta-phi signal",
519 fHeader->GetLegoNbinEta(), fHeader->GetLegoEtaMin(),
520 fHeader->GetLegoEtaMax(), fHeader->GetLegoNbinPhi(),
521 fHeader->GetLegoPhiMin(), fHeader->GetLegoPhiMax());