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 **************************************************************************/
15 // Class for bad channels & bad runs identification
17 // This class is designed for the following tasks:
18 // 1. find bad (dead/noisy/strange) cells on a per run basis;
19 // 2. find the status/quality of analysed data (e.g. missing RCUs, run quality);
20 // 3. find the extent of problems related to bad cells: required for
21 // systematics estimation for a physical quantity related to a cluster.
23 // See also AliAnalysisTaskCellsQA.
24 // Works for EMCAL and PHOS. Requires initialized geometry.
25 // Class defaults are optimized for EMCAL.
27 // Usage example for EMCAL:
31 // // to check the quality of analysed data and detect most of the problems:
32 // AliEMCALGeometry::GetInstance("EMCAL_COMPLETEV1");
33 // cellsQA = new AliCaloCellsQA(10, AliCaloCellsQA::kEMCAL); // 10 supermodules
35 // // add this line for a full analysis (fills additional histograms):
36 // cellsQA->ActivateFullAnalysis();
38 // b) In UserCreateOutputObjects():
40 // // not required, but suggested
41 // cellsQA->InitSummaryHistograms();
46 // AliVEvent *event = InputEvent();
47 // AliVCaloCells* cells = event->GetEMCALCells();
49 // AliVVertex *vertex = (AliVVertex*) event->GetPrimaryVertex();
50 // Double_t vertexXYZ[3];
51 // vertex->GetXYZ(vertexXYZ);
54 // TObjArray clusArray;
55 // for (Int_t i = 0; i < event->GetNumberOfCaloClusters(); i++) {
56 // AliVCluster *clus = event->GetCaloCluster(i);
58 // // filter clusters here, if necessary
59 // // if (clus->E() < 0.3) continue;
60 // // if (clus->GetNCells() < 2) continue;
62 // clusArray.Add(clus);
65 // // apply afterburners, etc.
68 // cellsQA->Fill(event->GetRunNumber(), &clusArray, cells, vertexXYZ);
70 // d) Do not forget to post data, where necessary:
71 // PostData(1,cellsQA->GetListOfHistos());
73 // TODO: add DCAL (up to 6 supermodules?)
76 // Author: Olga Driga (SUBATECH)
78 // --- ROOT system ---
79 #include <TLorentzVector.h>
81 // --- AliRoot header files ---
82 #include <AliEMCALGeometry.h>
83 #include <AliPHOSGeometry.h>
84 #include <AliCaloCellsQA.h>
86 ClassImp(AliCaloCellsQA)
88 //_________________________________________________________________________
89 AliCaloCellsQA::AliCaloCellsQA() :
98 fNBinsXNCellsInCluster(0),
99 fNBinsYNCellsInCluster(0),
102 fXMaxNCellsInCluster(0),
109 fhNEventsProcessedPerRun(0),
110 fhCellLocMaxNTimesInClusterElow(),
111 fhCellLocMaxNTimesInClusterEhigh(),
112 fhCellLocMaxETotalClusterElow(),
113 fhCellLocMaxETotalClusterEhigh(),
114 fhCellNonLocMaxNTimesInClusterElow(),
115 fhCellNonLocMaxNTimesInClusterEhigh(),
116 fhCellNonLocMaxETotalClusterElow(),
117 fhCellNonLocMaxETotalClusterEhigh(),
122 fhCellAmplitudeEhigh(0),
123 fhCellAmplitudeNonLocMax(0),
124 fhCellAmplitudeEhighNonLocMax(0),
127 // Default constructor (for root I/O). Do not use it.
129 // tells the class to reinitialize its transient members
133 //_________________________________________________________________________
134 AliCaloCellsQA::AliCaloCellsQA(Int_t nmods, Int_t det, Int_t startRunNumber, Int_t endRunNumber) :
143 fNBinsXNCellsInCluster(0),
144 fNBinsYNCellsInCluster(0),
147 fXMaxNCellsInCluster(0),
154 fhNEventsProcessedPerRun(0),
155 fhCellLocMaxNTimesInClusterElow(),
156 fhCellLocMaxNTimesInClusterEhigh(),
157 fhCellLocMaxETotalClusterElow(),
158 fhCellLocMaxETotalClusterEhigh(),
159 fhCellNonLocMaxNTimesInClusterElow(),
160 fhCellNonLocMaxNTimesInClusterEhigh(),
161 fhCellNonLocMaxETotalClusterElow(),
162 fhCellNonLocMaxETotalClusterEhigh(),
167 fhCellAmplitudeEhigh(0),
168 fhCellAmplitudeNonLocMax(0),
169 fhCellAmplitudeEhighNonLocMax(0),
172 // Allows to set main class parameters.
174 // nmods -- maximum supermodule number + 1:
175 // use 4 for EMCAL <= 2010;
176 // use 4 for PHOS (PHOS numbers start from 1, not from zero);
177 // use 10 for EMCAL >= 2011.
179 // det -- detector: AliCaloCellsQA::kEMCAL or AliCaloCellsQA::kPHOS.
180 // Note: DCAL not yet implemented.
182 // startRunNumber, endRunNumber -- run range the analysis will run on
183 // (to allow later merging); wide (but reasonable) range can be provided.
187 Init(nmods, det, startRunNumber, endRunNumber);
190 //_________________________________________________________________________
191 AliCaloCellsQA::~AliCaloCellsQA()
193 delete fListOfHistos;
196 //_________________________________________________________________________
197 void AliCaloCellsQA::ActivateFullAnalysis()
199 // Activate initialization and filling of all the designed histograms.
200 // Must be called before InitSummaryHistograms() and Fill() methods, if necessary.
202 fkFullAnalysis = kTRUE;
205 //_________________________________________________________________________
206 void AliCaloCellsQA::InitSummaryHistograms(Int_t nbins, Double_t emax,
207 Int_t nbinsh, Double_t emaxh,
208 Int_t nbinst, Double_t tmin, Double_t tmax)
210 // Initialize summary (not per run) histograms.
211 // Must be called after ActivateFullAnalysis(), before calling Fill() method, if necessary.
213 // nbins, emax -- number of bins and maximum amplitude for fhCellAmplitude and fhCellAmplitudeNonLocMax;
214 // nbinsh, emaxh -- number of bins and maximum amplitude for fhCellAmplitudeEhigh and fhCellAmplitudeEhighNonLocMax;
215 // nbinst, tmin, tmax -- number of bins and minimum/maximum time for fhCellTime.
217 // do not add histograms to the current directory
218 Bool_t ads = TH1::AddDirectoryStatus();
219 TH1::AddDirectory(kFALSE);
221 fhCellAmplitude = new TH2F("hCellAmplitude",
222 "Amplitude distribution per cell", fAbsIdMax-fAbsIdMin,fAbsIdMin,fAbsIdMax, nbins,0,emax);
223 fhCellAmplitude->SetXTitle("AbsId");
224 fhCellAmplitude->SetYTitle("Amplitude, GeV");
225 fhCellAmplitude->SetZTitle("Counts");
227 fhCellAmplitudeEhigh = new TH2F("hCellAmplitudeEhigh",
228 "Amplitude distribution per cell, high energies", fAbsIdMax-fAbsIdMin,fAbsIdMin,fAbsIdMax, nbinsh,0,emaxh);
229 fhCellAmplitudeEhigh->SetXTitle("AbsId");
230 fhCellAmplitudeEhigh->SetYTitle("Amplitude, GeV");
231 fhCellAmplitudeEhigh->SetZTitle("Counts");
233 fhCellTime = new TH2F("hCellTime", "Time distribution per cell",
234 fAbsIdMax-fAbsIdMin,fAbsIdMin,fAbsIdMax, nbinst,tmin,tmax);
235 fhCellTime->SetXTitle("AbsId");
236 fhCellTime->SetYTitle("Time, microseconds");
237 fhCellTime->SetZTitle("Counts");
239 fListOfHistos->Add(fhCellAmplitude);
240 fListOfHistos->Add(fhCellAmplitudeEhigh);
241 fListOfHistos->Add(fhCellTime);
243 if (fkFullAnalysis) {
244 fhCellAmplitudeNonLocMax = new TH2F("hCellAmplitudeNonLocMax",
245 "Amplitude distribution per cell which is not a local maximum",
246 fAbsIdMax-fAbsIdMin,fAbsIdMin,fAbsIdMax, nbins,0,emax);
247 fhCellAmplitudeNonLocMax->SetXTitle("AbsId");
248 fhCellAmplitudeNonLocMax->SetYTitle("Amplitude, GeV");
249 fhCellAmplitudeNonLocMax->SetZTitle("Counts");
251 fhCellAmplitudeEhighNonLocMax = new TH2F("hCellAmplitudeEhighNonLocMax",
252 "Amplitude distribution per cell which is not a local maximum, high energies",
253 fAbsIdMax-fAbsIdMin,fAbsIdMin,fAbsIdMax, nbinsh,0,emaxh);
254 fhCellAmplitudeEhighNonLocMax->SetXTitle("AbsId");
255 fhCellAmplitudeEhighNonLocMax->SetYTitle("Amplitude, GeV");
256 fhCellAmplitudeEhighNonLocMax->SetZTitle("Counts");
258 fListOfHistos->Add(fhCellAmplitudeNonLocMax);
259 fListOfHistos->Add(fhCellAmplitudeEhighNonLocMax);
262 // return to the previous add directory status
263 TH1::AddDirectory(ads);
266 //_________________________________________________________________________
267 void AliCaloCellsQA::Fill(Int_t runNumber, TObjArray *clusArray, AliVCaloCells *cells, Double_t vertexXYZ[3])
269 // Does the job: fills histograms for current event.
271 // runNumber -- current run number;
272 // clusArray -- array of clusters (TObjArray or TClonesArray);
273 // cells -- EMCAL or PHOS cells;
274 // vertexXYZ -- primary vertex position.
276 InitTransientFindCurrentRun(runNumber);
278 fhNEventsProcessedPerRun->Fill(runNumber);
280 FillCellsInCluster(clusArray, cells);
281 FillJustCells(cells);
282 FillPi0Mass(clusArray, vertexXYZ);
285 //_________________________________________________________________________
286 void AliCaloCellsQA::SetClusterEnergyCuts(Double_t pi0EClusMin, Double_t elowMin, Double_t ehighMin)
288 // Set cuts for minimum cluster energies.
289 // Must be called before calling Fill() method, if necessary.
291 fClusElowMin = elowMin;
292 fClusEhighMin = ehighMin;
293 fPi0EClusMin = pi0EClusMin;
296 //_________________________________________________________________________
297 void AliCaloCellsQA::SetBinningParameters(Int_t nbins1, Int_t nbins2, Int_t nbins3x, Int_t nbins3y,
298 Double_t xmax1, Double_t xmax2, Double_t xmax3)
300 // Set binning parameters for histograms hECells, hNCellsInCluster and hPi0Mass.
301 // Must be called before Fill() method, if necessary.
303 // nbins1, xmax1 -- number of bins and maximum X axis value for hECells;
304 // nbins2, xmax2 -- number of bins and maximum X axis value for hPi0Mass;
305 // nbins3x, nbins3y, xmax3 -- number of bins in X and Y axes and maximum X axis value for hNCellsInCluster.
307 fNBinsECells = nbins1;
308 fNBinsPi0Mass = nbins2;
309 fNBinsXNCellsInCluster = nbins3x;
310 fNBinsYNCellsInCluster = nbins3y;
312 fXMaxPi0Mass = xmax2;
313 fXMaxNCellsInCluster = xmax3;
316 //_________________________________________________________________________
317 void AliCaloCellsQA::Init(Int_t nmods, Int_t det, Int_t startRunNumber, Int_t endRunNumber)
319 // Class initialization.
320 // Defaults: fClusElowMin = 0.3GeV, fClusEhighMin = 1GeV, fPi0EClusMin = 0.5GeV, fkFullAnalysis = false.
322 // check input (for design limitations only)
323 if (det != kEMCAL && det != kPHOS) {
324 AliError("Wrong detector provided");
325 AliInfo("I will use EMCAL");
328 if (nmods < 1 || nmods > 10) {
329 AliError("Wrong last supermodule number + 1 provided");
330 AliInfo("I will use nmods = 10");
336 fkFullAnalysis = kFALSE;
337 SetClusterEnergyCuts();
338 SetBinningParameters();
340 // minimum/maximum cell absId;
341 // straightforward solution avoids complications
343 fAbsIdMax = fNMods * 1152;
344 if (fDetector == kPHOS) {
346 fAbsIdMax = 1 + (fNMods-1)*3584;
349 fListOfHistos = new TObjArray;
350 fListOfHistos->SetOwner(kTRUE);
352 fhNEventsProcessedPerRun = new TH1D("hNEventsProcessedPerRun",
353 "Number of processed events vs run number", endRunNumber - startRunNumber, startRunNumber, endRunNumber);
354 fhNEventsProcessedPerRun->SetDirectory(0);
355 fhNEventsProcessedPerRun->SetXTitle("Run number");
356 fhNEventsProcessedPerRun->SetYTitle("Events");
357 fListOfHistos->Add(fhNEventsProcessedPerRun);
360 //_________________________________________________________________________
361 void AliCaloCellsQA::InitTransientFindCurrentRun(Int_t runNumber)
363 // Initialize transient members, add a new run if necessary.
365 // try previous value ...
366 if (fRI >= 0 && fRunNumbers[fRI] == runNumber) return;
368 // ... or find current run index ...
369 for (fRI = 0; fRI < fNRuns; fRI++)
370 if (fRunNumbers[fRI] == runNumber) break;
372 // ... or add a new run
374 if (fNRuns >= 1000) AliFatal("Too many runs, how is this possible?");
376 fRunNumbers[fNRuns] = runNumber;
377 InitHistosForRun(runNumber);
381 // initialize transient class members;
382 // this happens once per run, i.e. not a big overhead
383 InitTransientMembers(runNumber);
386 //_________________________________________________________________________
387 void AliCaloCellsQA::InitTransientMembers(Int_t run)
389 // Initializes transient data members -- references to histograms
390 // (e.g. in case the class was restored from a file);
391 // run -- current run number.
393 fhNEventsProcessedPerRun = (TH1D*) fListOfHistos->FindObject("hNEventsProcessedPerRun");
395 fhCellAmplitude = (TH2F*) fListOfHistos->FindObject("hCellAmplitude");
396 fhCellAmplitudeEhigh = (TH2F*) fListOfHistos->FindObject("hCellAmplitudeEhigh");
397 fhCellAmplitudeNonLocMax = (TH2F*) fListOfHistos->FindObject("hCellAmplitudeNonLocMax");
398 fhCellAmplitudeEhighNonLocMax = (TH2F*) fListOfHistos->FindObject("hCellAmplitudeEhighNonLocMax");
399 fhCellTime = (TH2F*) fListOfHistos->FindObject("hCellTime");
401 fhCellLocMaxNTimesInClusterElow = (TH1F*) fListOfHistos->FindObject(Form("run%i_hCellLocMaxNTimesInClusterElow",run));
402 fhCellLocMaxNTimesInClusterEhigh = (TH1F*) fListOfHistos->FindObject(Form("run%i_hCellLocMaxNTimesInClusterEhigh",run));
403 fhCellLocMaxETotalClusterElow = (TH1F*) fListOfHistos->FindObject(Form("run%i_hCellLocMaxETotalClusterElow",run));
404 fhCellLocMaxETotalClusterEhigh = (TH1F*) fListOfHistos->FindObject(Form("run%i_hCellLocMaxETotalClusterEhigh",run));
405 fhCellNonLocMaxNTimesInClusterElow = (TH1F*) fListOfHistos->FindObject(Form("run%i_hCellNonLocMaxNTimesInClusterElow",run));
406 fhCellNonLocMaxNTimesInClusterEhigh = (TH1F*) fListOfHistos->FindObject(Form("run%i_hCellNonLocMaxNTimesInClusterEhigh",run));
407 fhCellNonLocMaxETotalClusterElow = (TH1F*) fListOfHistos->FindObject(Form("run%i_hCellNonLocMaxETotalClusterElow",run));
408 fhCellNonLocMaxETotalClusterEhigh = (TH1F*) fListOfHistos->FindObject(Form("run%i_hCellNonLocMaxETotalClusterEhigh",run));
411 if (fDetector == kPHOS) minsm = 1;
413 // per supermodule histograms
414 for (Int_t sm = minsm; sm < fNMods; sm++) {
415 fhECells[sm] = (TH1F*) fListOfHistos->FindObject(Form("run%i_hECellsSM%i",run,sm));
416 fhNCellsInCluster[sm] = (TH2F*) fListOfHistos->FindObject(Form("run%i_hNCellsInClusterSM%i",run,sm));
418 for (Int_t sm2 = sm; sm2 < fNMods; sm2++)
419 fhPi0Mass[sm][sm2] = (TH1F*) fListOfHistos->FindObject(Form("run%i_hPi0MassSM%iSM%i",run,sm,sm2));
423 //_________________________________________________________________________
424 void AliCaloCellsQA::InitHistosForRun(Int_t run)
426 // Initialize per run histograms for a new run number;
427 // run -- run number.
429 // do not add histograms to the current directory
430 Bool_t ads = TH1::AddDirectoryStatus();
431 TH1::AddDirectory(kFALSE);
433 fhCellLocMaxNTimesInClusterElow = new TH1F(Form("run%i_hCellLocMaxNTimesInClusterElow",run),
434 "Number of times cell was local maximum in a low energy cluster", fAbsIdMax-fAbsIdMin,fAbsIdMin,fAbsIdMax);
435 fhCellLocMaxNTimesInClusterElow->SetXTitle("AbsId");
436 fhCellLocMaxNTimesInClusterElow->SetYTitle("Counts");
438 fhCellLocMaxNTimesInClusterEhigh = new TH1F(Form("run%i_hCellLocMaxNTimesInClusterEhigh",run),
439 "Number of times cell was local maximum in a high energy cluster", fAbsIdMax-fAbsIdMin,fAbsIdMin,fAbsIdMax);
440 fhCellLocMaxNTimesInClusterEhigh->SetXTitle("AbsId");
441 fhCellLocMaxNTimesInClusterEhigh->SetYTitle("Counts");
443 fhCellLocMaxETotalClusterElow = new TH1F(Form("run%i_hCellLocMaxETotalClusterElow",run),
444 "Total cluster energy for local maximum cell, low energy", fAbsIdMax-fAbsIdMin,fAbsIdMin,fAbsIdMax);
445 fhCellLocMaxETotalClusterElow->SetXTitle("AbsId");
446 fhCellLocMaxETotalClusterElow->SetYTitle("Energy");
448 fhCellLocMaxETotalClusterEhigh = new TH1F(Form("run%i_hCellLocMaxETotalClusterEhigh",run),
449 "Total cluster energy for local maximum cell, high energy", fAbsIdMax-fAbsIdMin,fAbsIdMin,fAbsIdMax);
450 fhCellLocMaxETotalClusterEhigh->SetXTitle("AbsId");
451 fhCellLocMaxETotalClusterEhigh->SetYTitle("Energy");
453 fListOfHistos->Add(fhCellLocMaxNTimesInClusterElow);
454 fListOfHistos->Add(fhCellLocMaxNTimesInClusterEhigh);
455 fListOfHistos->Add(fhCellLocMaxETotalClusterElow);
456 fListOfHistos->Add(fhCellLocMaxETotalClusterEhigh);
459 if (fkFullAnalysis) {
460 fhCellNonLocMaxNTimesInClusterElow = new TH1F(Form("run%i_hCellNonLocMaxNTimesInClusterElow",run),
461 "Number of times cell wasn't local maximum in a low energy cluster", fAbsIdMax-fAbsIdMin,fAbsIdMin,fAbsIdMax);
462 fhCellNonLocMaxNTimesInClusterElow->SetXTitle("AbsId");
463 fhCellNonLocMaxNTimesInClusterElow->SetYTitle("Counts");
465 fhCellNonLocMaxNTimesInClusterEhigh = new TH1F(Form("run%i_hCellNonLocMaxNTimesInClusterEhigh",run),
466 "Number of times cell wasn't local maximum in a high energy cluster", fAbsIdMax-fAbsIdMin,fAbsIdMin,fAbsIdMax);
467 fhCellNonLocMaxNTimesInClusterEhigh->SetXTitle("AbsId");
468 fhCellNonLocMaxNTimesInClusterEhigh->SetYTitle("Counts");
470 fhCellNonLocMaxETotalClusterElow = new TH1F(Form("run%i_hCellNonLocMaxETotalClusterElow",run),
471 "Total cluster energy for not local maximum cell, low energy", fAbsIdMax-fAbsIdMin,fAbsIdMin,fAbsIdMax);
472 fhCellNonLocMaxETotalClusterElow->SetXTitle("AbsId");
473 fhCellNonLocMaxETotalClusterElow->SetYTitle("Energy");
475 fhCellNonLocMaxETotalClusterEhigh = new TH1F(Form("run%i_hCellNonLocMaxETotalClusterEhigh",run),
476 "Total cluster energy for not local maximum cell, high energy", fAbsIdMax-fAbsIdMin,fAbsIdMin,fAbsIdMax);
477 fhCellNonLocMaxETotalClusterEhigh->SetXTitle("AbsId");
478 fhCellNonLocMaxETotalClusterEhigh->SetYTitle("Energy");
480 fListOfHistos->Add(fhCellNonLocMaxNTimesInClusterElow);
481 fListOfHistos->Add(fhCellNonLocMaxNTimesInClusterEhigh);
482 fListOfHistos->Add(fhCellNonLocMaxETotalClusterElow);
483 fListOfHistos->Add(fhCellNonLocMaxETotalClusterEhigh);
488 if (fDetector == kPHOS) minsm = 1;
490 // per supermodule histograms
491 for (Int_t sm = minsm; sm < fNMods; sm++) {
492 fhECells[sm] = new TH1F(Form("run%i_hECellsSM%i",run,sm),
493 "Cell amplitude distribution", fNBinsECells,0,fXMaxECells);
494 fhECells[sm]->SetXTitle("Amplitude, GeV");
495 fhECells[sm]->SetYTitle("Number of cells");
497 fhNCellsInCluster[sm] = new TH2F(Form("run%i_hNCellsInClusterSM%i",run,sm),
498 "Distrubution of number of cells in cluster vs cluster energy",
499 fNBinsXNCellsInCluster,0,fXMaxNCellsInCluster, fNBinsYNCellsInCluster,0,fNBinsYNCellsInCluster);
500 fhNCellsInCluster[sm]->SetXTitle("Energy, GeV");
501 fhNCellsInCluster[sm]->SetYTitle("Number of cells");
502 fhNCellsInCluster[sm]->SetZTitle("Counts");
504 fListOfHistos->Add(fhECells[sm]);
505 fListOfHistos->Add(fhNCellsInCluster[sm]);
509 for (Int_t sm = minsm; sm < fNMods; sm++)
510 for (Int_t sm2 = sm; sm2 < fNMods; sm2++) {
511 fhPi0Mass[sm][sm2] = new TH1F(Form("run%i_hPi0MassSM%iSM%i",run,sm,sm2),
512 "#pi^{0} mass spectrum", fNBinsPi0Mass,0,fXMaxPi0Mass);
513 fhPi0Mass[sm][sm2]->SetXTitle("M_{#gamma#gamma}, GeV");
514 fhPi0Mass[sm][sm2]->SetYTitle("Counts");
516 fListOfHistos->Add(fhPi0Mass[sm][sm2]);
519 // return to the previous add directory status
520 TH1::AddDirectory(ads);
523 //_________________________________________________________________________
524 void AliCaloCellsQA::FillCellsInCluster(TObjArray *clusArray, AliVCaloCells *cells)
526 // Fill histograms related to a cluster
530 for (Int_t i = 0; i < clusArray->GetEntriesFast(); i++)
532 AliVCluster *clus = (AliVCluster*) clusArray->At(i);
533 if ((sm = CheckClusterGetSM(clus)) < 0) continue;
535 if (fhNCellsInCluster[sm])
536 fhNCellsInCluster[sm]->Fill(clus->E(), clus->GetNCells());
538 if (clus->E() >= fClusElowMin)
539 for (Int_t c = 0; c < clus->GetNCells(); c++) {
540 Int_t absId = clus->GetCellAbsId(c);
542 if (IsCellLocalMaximum(c, clus, cells)) {// local maximum
543 if (clus->E() < fClusEhighMin) {
544 fhCellLocMaxNTimesInClusterElow->Fill(absId);
545 fhCellLocMaxETotalClusterElow->Fill(absId, clus->E());
547 fhCellLocMaxNTimesInClusterEhigh->Fill(absId);
548 fhCellLocMaxETotalClusterEhigh->Fill(absId, clus->E());
551 else if (fkFullAnalysis) {// not a local maximum
552 if (clus->E() < fClusEhighMin) {
553 fhCellNonLocMaxNTimesInClusterElow->Fill(absId);
554 fhCellNonLocMaxETotalClusterElow->Fill(absId, clus->E());
556 fhCellNonLocMaxNTimesInClusterEhigh->Fill(absId);
557 fhCellNonLocMaxETotalClusterEhigh->Fill(absId, clus->E());
566 //_________________________________________________________________________
567 void AliCaloCellsQA::FillJustCells(AliVCaloCells *cells)
569 // Fill cell histograms not related with a cluster
575 for (Short_t c = 0; c < cells->GetNumberOfCells(); c++) {
576 cells->GetCell(c, absId, amp, time);
577 if ((sm = GetSM(absId)) < 0) continue;
579 if (fhECells[sm]) fhECells[sm]->Fill(amp);
581 if (fhCellAmplitude) { // in case InitSummaryHistograms() was not called
582 fhCellAmplitude->Fill(absId, amp);
583 fhCellAmplitudeEhigh->Fill(absId, amp);
584 fhCellTime->Fill(absId, time);
586 // fill not a local maximum distributions
587 if (fkFullAnalysis && !IsCellLocalMaximum(absId, cells)) {
588 fhCellAmplitudeNonLocMax->Fill(absId, amp);
589 fhCellAmplitudeEhighNonLocMax->Fill(absId, amp);
596 //_________________________________________________________________________
597 void AliCaloCellsQA::FillPi0Mass(TObjArray *clusArray, Double_t vertexXYZ[3])
599 // Fill gamma+gamma invariant mass histograms.
603 TLorentzVector p1, p2, psum;
606 for (Int_t i = 0; i < clusArray->GetEntriesFast(); i++)
608 AliVCluster *clus = (AliVCluster*) clusArray->At(i);
609 if (clus->E() < fPi0EClusMin) continue;
610 if ((sm1 = CheckClusterGetSM(clus)) < 0) continue;
612 clus->GetMomentum(p1, vertexXYZ);
614 // second cluster loop
615 for (Int_t j = i+1; j < clusArray->GetEntriesFast(); j++)
617 AliVCluster *clus2 = (AliVCluster*) clusArray->At(j);
618 if (clus2->E() < fPi0EClusMin) continue;
619 if ((sm2 = CheckClusterGetSM(clus2)) < 0) continue;
621 clus2->GetMomentum(p2, vertexXYZ);
624 if (psum.M2() < 0) continue;
627 Int_t s1 = (sm1 <= sm2) ? sm1 : sm2;
628 Int_t s2 = (sm1 <= sm2) ? sm2 : sm1;
630 if (fhPi0Mass[s1][s2])
631 fhPi0Mass[s1][s2]->Fill(psum.M());
632 } // second cluster loop
636 //_________________________________________________________________________
637 Int_t AliCaloCellsQA::CheckClusterGetSM(AliVCluster* clus)
639 // Apply common cluster cuts and return supermodule number on success.
640 // Return -1 if cuts not passed or an error occured.
642 // check detector and number of cells in cluster
643 if (fDetector == kEMCAL && !clus->IsEMCAL()) return -1;
644 if (fDetector == kPHOS && !clus->IsPHOS()) return -1;
645 if (clus->GetNCells() < 1) return -1;
647 return GetSM(clus->GetCellAbsId(0));
650 //_________________________________________________________________________
651 Int_t AliCaloCellsQA::GetSM(Int_t absId)
653 // Convert cell absId --> supermodule number. Return -1 in case of error.
654 // Note: we use simple and straightforward way to find supermodule number.
655 // This allows to avoid unnecessary external dependencies (on geometry).
659 if (fDetector == kEMCAL) sm = absId/1152;
660 if (fDetector == kPHOS) sm = 1 + (absId-1)/3584;
662 // check for data corruption to avoid segfaults
663 if (sm < 0 || sm > 9) {
664 AliError("Data corrupted");
671 //____________________________________________________________
672 Bool_t AliCaloCellsQA::IsCellLocalMaximum(Int_t c, AliVCluster* clus, AliVCaloCells* cells)
674 // Returns true if cell is a local maximum in cluster (clusterizer dependent).
675 // Cell fractions are taken into account.
677 // c -- cell number in the cluster.
679 Int_t sm, eta, phi, sm2, eta2, phi2;
681 Int_t absId = clus->GetCellAbsId(c);
682 Double_t amp = cells->GetCellAmplitude(absId);
683 if (clus->GetCellAmplitudeFraction(c) > 1e-5) amp *= clus->GetCellAmplitudeFraction(c);
685 AbsIdToSMEtaPhi(absId, sm, eta, phi);
687 // try to find a neighbour which has bigger amplitude
688 for (Int_t c2 = 0; c2 < clus->GetNCells(); c2++) {
689 if (c == c2) continue;
691 Int_t absId2 = clus->GetCellAbsId(c2);
692 Double_t amp2 = cells->GetCellAmplitude(absId2);
693 if (clus->GetCellAmplitudeFraction(c2) > 1e-5) amp2 *= clus->GetCellAmplitudeFraction(c2);
695 AbsIdToSMEtaPhi(absId2, sm2, eta2, phi2);
696 if (sm != sm2) continue;
698 Int_t deta = TMath::Abs(eta-eta2);
699 Int_t dphi = TMath::Abs(phi-phi2);
701 if ((deta == 0 && dphi == 1) || (deta == 1 && dphi == 0) || (deta == 1 && dphi == 1))
702 if (amp < amp2) return kFALSE;
708 //____________________________________________________________
709 Bool_t AliCaloCellsQA::IsCellLocalMaximum(Int_t absId, AliVCaloCells* cells)
711 // Returns true if cell is a local maximum among cells (clusterizer independent).
713 Int_t sm, eta, phi, sm2, eta2, phi2;
715 Double_t amp = cells->GetCellAmplitude(absId);
716 AbsIdToSMEtaPhi(absId, sm, eta, phi);
718 // try to find a neighbour which has bigger amplitude
719 for (Short_t c2 = 0; c2 < cells->GetNumberOfCells(); c2++) {
720 Short_t absId2 = cells->GetCellNumber(c2);
721 if (absId2 == absId) continue;
723 AbsIdToSMEtaPhi(absId2, sm2, eta2, phi2);
724 if (sm != sm2) continue;
726 Int_t deta = TMath::Abs(eta-eta2);
727 Int_t dphi = TMath::Abs(phi-phi2);
729 if ((deta == 0 && dphi == 1) || (deta == 1 && dphi == 0) || (deta == 1 && dphi == 1))
730 if (amp < cells->GetAmplitude(c2))
737 //____________________________________________________________
738 void AliCaloCellsQA::AbsIdToSMEtaPhi(Int_t absId, Int_t &sm, Int_t &eta, Int_t &phi)
740 // Converts absId --> (sm, eta, phi) for a cell.
741 // Works both for EMCAL and for PHOS.
742 // Geometry must be already initialized.
745 if (fDetector == kEMCAL) {
746 AliEMCALGeometry *geomEMCAL = AliEMCALGeometry::GetInstance();
748 AliFatal("EMCAL geometry is not initialized");
750 Int_t nModule, nIphi, nIeta;
751 geomEMCAL->GetCellIndex(absId, sm, nModule, nIphi, nIeta);
752 geomEMCAL->GetCellPhiEtaIndexInSModule(sm, nModule, nIphi, nIeta, phi, eta);
757 if (fDetector == kPHOS) {
758 AliPHOSGeometry *geomPHOS = AliPHOSGeometry::GetInstance();
760 AliFatal("PHOS geometry is not initialized");
763 geomPHOS->AbsToRelNumbering(absId, relid);