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 **************************************************************************/
22 Changes to accomodate updates of general DQM/QA changes to have per trigger
23 histograms (for a given event specie).
25 AliTPCdataQA has a new flag for only keeping DQM info event by
27 The expert/DA functionality has been kept exactly the same!
32 This update should solve two problems mainly:
33 * The vs event histograms have been limited to a fixed size for the
34 DQM. The 500k seemed to be a big size but is no longer so, so we
35 need to dynamically expand the range. The non-trivial point is that
36 we also have to do it for the copy owned by AliTPCQADataMakerRec.
37 * The amoreGui now remembers the x-range of the first visualization so
38 the trick of setting the relevant event range as the histogram is
39 filled no longer works.
41 The fix is a bit crude but avoids creating a new histogram. Instead
42 the range is expanded (max events and events per bin is doubled) but
43 the number of bins is kept constant! In this way we can change just
44 double the max of the X-axis of the hist and rebin the data. The
45 same can easily be done for the copy owned by AliTPCQADataMakerRec.
48 If we change the number of bins we could crash the whole system
49 because ROOT does not create space for extra bins! (but we do not do
50 this). In that way it is a crude solution.
51 The rebinning in the code only works for an even number of bins.
53 In addition to the above a bug in the reading of the config file was
54 also found and corrected. fAdcMax was set instead of fEventsPerBin.
56 Finally cout was changes to AliInfo.
60 The code has been heavily modified so that now the RAW data is
61 "expanded" for each sector and stored in a big signal array. Then a
62 simple version of the code in AliTPCclustererMI is used to identify
63 the local maxima and these are then used for QA. This gives a better
64 estimate of the charge (both max and total) and also limits the
69 In Update the RAW signals >= 3 ADC channels are stored in the arrays.
72 Float_t** fAllBins 2d array [row][bin(pad, time)] ADC signal
73 Int_t** fAllSigBins 2d array [row][signal#] bin(with signal)
74 Int_t* fAllNSigBins; 1d array [row] Nsignals
76 This is done sector by sector.
78 When data from a new sector is encountered, the method
79 FindLocalMaxima is called on the data from the previous sector, and
80 the calibration/data objects are updated with the "cluster"
81 info. Finally the arrays are cleared.
83 The requirements for a local maxima is:
84 Charge in bin is >= 5 ADC channels.
85 Charge in bin is larger than all the 8 neighboring bins.
86 At least one of the two pad neighbors has a signal.
87 At least one of the two time neighbors has a signal.
89 Before accessing the data it is expected that the Analyse method is
90 called. This normalizes some of the data objects to per event or per
92 If more data is passed to the class after Analyse has been called
93 the normalization is reversed and Analyse has to be called again.
101 #include <TDirectory.h>
105 #include <TProfile.h>
107 #include "AliRawReader.h"
108 #include "AliRawReaderRoot.h"
109 #include "AliRawReaderDate.h"
110 #include "AliTPCRawStream.h"
111 #include "AliTPCRawStreamV3.h"
112 #include "AliTPCCalROC.h"
113 #include "AliTPCROC.h"
114 #include "AliMathBase.h"
115 #include "TTreeStream.h"
119 #include "AliTPCCalPad.h"
120 #include "AliTPCPreprocessorOnline.h"
123 #include "AliTPCdataQA.h"
126 ClassImp(AliTPCdataQA)
128 AliTPCdataQA::AliTPCdataQA() : /*FOLD00*/
146 fHistQVsTimeSideA(0),
147 fHistQVsTimeSideC(0),
148 fHistQMaxVsTimeSideA(0),
149 fHistQMaxVsTimeSideC(0),
150 fHistOccupancyVsEvent(0),
151 fHistNclustersVsEvent(0),
154 fMaxEvents(500000), // Max events for event histograms
155 fEventsPerBin(1000), // Events per bin for event histograms
156 fSignalCounter(0), // Signal counter
157 fClusterCounter(0), // Cluster counter
165 fHistOccVsSector(0x0),
167 fHistQmaxVsSector(0x0),
172 // default constructor
176 //_____________________________________________________________________
177 AliTPCdataQA::AliTPCdataQA(const AliTPCdataQA &ped) : /*FOLD00*/
179 fFirstTimeBin(ped.GetFirstTimeBin()),
180 fLastTimeBin(ped.GetLastTimeBin()),
181 fAdcMin(ped.GetAdcMin()),
182 fAdcMax(ped.GetAdcMax()),
196 fHistQVsTimeSideA(0),
197 fHistQVsTimeSideC(0),
198 fHistQMaxVsTimeSideA(0),
199 fHistQMaxVsTimeSideC(0),
200 fHistOccupancyVsEvent(0),
201 fHistNclustersVsEvent(0),
202 fEventCounter(ped.GetEventCounter()),
203 fIsAnalysed(ped.GetIsAnalysed()),
204 fMaxEvents(ped.GetMaxEvents()),
205 fEventsPerBin(ped.GetEventsPerBin()),
206 fSignalCounter(ped.GetSignalCounter()),
207 fClusterCounter(ped.GetClusterCounter()),
214 fIsDQM(ped.GetIsDQM()),
215 fHistOccVsSector(0x0),
217 fHistQmaxVsSector(0x0),
224 if(ped.GetNLocalMaxima())
225 fNLocalMaxima = new AliTPCCalPad(*ped.GetNLocalMaxima());
226 if(ped.GetMaxCharge())
227 fMaxCharge = new AliTPCCalPad(*ped.GetMaxCharge());
228 if(ped.GetMeanCharge())
229 fMeanCharge = new AliTPCCalPad(*ped.GetMeanCharge());
230 if(ped.GetNoThreshold())
231 fNoThreshold = new AliTPCCalPad(*ped.GetNoThreshold());
232 if(ped.GetNTimeBins())
233 fNTimeBins = new AliTPCCalPad(*ped.GetNTimeBins());
235 fNPads = new AliTPCCalPad(*ped.GetNPads());
236 if(ped.GetTimePosition())
237 fTimePosition = new AliTPCCalPad(*ped.GetTimePosition());
238 if(ped.GetOverThreshold10())
239 fOverThreshold10 = new AliTPCCalPad(*ped.GetOverThreshold10());
240 if(ped.GetOverThreshold20())
241 fOverThreshold20 = new AliTPCCalPad(*ped.GetOverThreshold20());
242 if(ped.GetOverThreshold30())
243 fOverThreshold30 = new AliTPCCalPad(*ped.GetOverThreshold30());
244 if(ped.GetHistQVsTimeSideA()) {
245 fHistQVsTimeSideA = new TProfile(*ped.GetHistQVsTimeSideA());
246 fHistQVsTimeSideA->SetDirectory(0);
248 if(ped.GetHistQVsTimeSideC()) {
249 fHistQVsTimeSideC = new TProfile(*ped.GetHistQVsTimeSideC());
250 fHistQVsTimeSideC->SetDirectory(0);
252 if(ped.GetHistQMaxVsTimeSideA()) {
253 fHistQMaxVsTimeSideA = new TProfile(*ped.GetHistQMaxVsTimeSideA());
254 fHistQMaxVsTimeSideA->SetDirectory(0);
256 if(ped.GetHistQMaxVsTimeSideC()) {
257 fHistQMaxVsTimeSideC = new TProfile(*ped.GetHistQMaxVsTimeSideC());
258 fHistQMaxVsTimeSideC->SetDirectory(0);
260 if(ped.GetHistOccupancyVsEventConst()) {
261 fHistOccupancyVsEvent = new TH1F(*ped.GetHistOccupancyVsEventConst());
262 fHistOccupancyVsEvent->SetDirectory(0);
264 if(ped.GetHistNclustersVsEventConst()) {
265 fHistNclustersVsEvent = new TH1F(*ped.GetHistNclustersVsEventConst());
266 fHistNclustersVsEvent->SetDirectory(0);
270 //_____________________________________________________________________
271 AliTPCdataQA::AliTPCdataQA(const TMap *config) : /*FOLD00*/
272 TH1F("TPCRAW","TPCRAW",100,0,100),
290 fHistQVsTimeSideA(0),
291 fHistQVsTimeSideC(0),
292 fHistQMaxVsTimeSideA(0),
293 fHistQMaxVsTimeSideC(0),
294 fHistOccupancyVsEvent(0),
295 fHistNclustersVsEvent(0),
309 fHistOccVsSector(0x0),
311 fHistQmaxVsSector(0x0),
316 // default constructor
318 if (config->GetValue("FirstTimeBin")) fFirstTimeBin = ((TObjString*)config->GetValue("FirstTimeBin"))->GetString().Atoi();
319 if (config->GetValue("LastTimeBin")) fLastTimeBin = ((TObjString*)config->GetValue("LastTimeBin"))->GetString().Atoi();
320 if (config->GetValue("AdcMin")) fAdcMin = ((TObjString*)config->GetValue("AdcMin"))->GetString().Atoi();
321 if (config->GetValue("AdcMax")) fAdcMax = ((TObjString*)config->GetValue("AdcMax"))->GetString().Atoi();
322 if (config->GetValue("MaxEvents")) fMaxEvents = ((TObjString*)config->GetValue("MaxEvents"))->GetString().Atoi();
323 if (config->GetValue("EventsPerBin")) fEventsPerBin = ((TObjString*)config->GetValue("EventsPerBin"))->GetString().Atoi();
326 //_____________________________________________________________________
327 AliTPCdataQA& AliTPCdataQA::operator = (const AliTPCdataQA &source)
330 // assignment operator
332 if (&source == this) return *this;
333 new (this) AliTPCdataQA(source);
339 //_____________________________________________________________________
340 AliTPCdataQA::~AliTPCdataQA() /*FOLD00*/
346 // do not delete fMapping, because we do not own it.
347 // do not delete fMapping, because we do not own it.
348 // do not delete fNoise and fPedestal, because we do not own them.
350 delete fNLocalMaxima;
356 delete fTimePosition;
357 delete fOverThreshold10;
358 delete fOverThreshold20;
359 delete fOverThreshold30;
360 delete fHistQVsTimeSideA;
361 delete fHistQVsTimeSideC;
362 delete fHistQMaxVsTimeSideA;
363 delete fHistQMaxVsTimeSideC;
364 delete fHistOccupancyVsEvent;
365 delete fHistNclustersVsEvent;
368 delete fHistOccVsSector;
369 delete fHistQVsSector;
370 delete fHistQmaxVsSector;
374 for (Int_t iRow = 0; iRow < fRowsMax; iRow++) {
375 delete [] fAllBins[iRow];
376 delete [] fAllSigBins[iRow];
379 delete [] fAllSigBins;
380 delete [] fAllNSigBins;
383 //_____________________________________________________________________
384 TH1F* AliTPCdataQA::GetHistOccupancyVsEvent()
387 // Create Occupancy vs event histogram
388 // (we create this histogram differently then the other histograms
389 // because this we want to be able to access and copy
390 // from AliTPCQAMakerRec before it normally would be created)
392 if(!fHistOccupancyVsEvent) {
394 Int_t nBins = fMaxEvents/fEventsPerBin;
395 fHistOccupancyVsEvent = new TH1F("hOccupancyVsEvent", "Occupancy vs event number (~time); Event number; Occupancy", nBins, 0, nBins*fEventsPerBin);
396 fHistOccupancyVsEvent->SetDirectory(0);
399 return fHistOccupancyVsEvent;
402 //_____________________________________________________________________
403 TH1F* AliTPCdataQA::GetHistNclustersVsEvent()
406 // Create Nclusters vs event histogram
407 // (we create this histogram differently then the other histograms
408 // because this we want to be able to access and copy
409 // from AliTPCQAMakerRec before it normally would be created)
411 if(!fHistNclustersVsEvent) {
413 Int_t nBins = fMaxEvents/fEventsPerBin;
414 fHistNclustersVsEvent = new TH1F("hNclustersVsEvent", "Nclusters vs event number (~time); Event number; Nclusters per event", nBins, 0, nBins*fEventsPerBin);
415 fHistNclustersVsEvent->SetDirectory(0);
418 return fHistNclustersVsEvent;
421 //_____________________________________________________________________
422 void AliTPCdataQA::UpdateEventHistograms()
424 // Update histograms that display occupancy and
425 // number of clusters as a function of number of
427 if (!fHistOccupancyVsEvent)
428 GetHistOccupancyVsEvent();
429 if (!fHistNclustersVsEvent)
430 GetHistNclustersVsEvent();
432 if(fEventCounter > fMaxEvents) {
434 // we have to expand the histogram to handle the larger number of
435 // events. The way it is done now is to double the range and the
436 // number of events per bin (so the number of histogram bins stays
441 // Change histogram limits
442 const Int_t nBins = fHistOccupancyVsEvent->GetXaxis()->GetNbins();
443 fHistOccupancyVsEvent->GetXaxis()->Set(nBins, fHistOccupancyVsEvent->GetXaxis()->GetNbins(), fMaxEvents);
444 fHistNclustersVsEvent->GetXaxis()->Set(nBins, fHistNclustersVsEvent->GetXaxis()->GetNbins(), fMaxEvents);
446 // Rebin the histogram
447 for(Int_t bin = 1; bin <= nBins; bin+=2) {
449 Int_t newBin = TMath::Nint(Float_t(bin+1)/2.0);
450 Float_t newContent = (fHistOccupancyVsEvent->GetBinContent(bin)+
451 fHistOccupancyVsEvent->GetBinContent(bin+1))/2.0;
452 fHistOccupancyVsEvent->SetBinContent(newBin, newContent);
454 newContent = (fHistNclustersVsEvent->GetBinContent(bin)+
455 fHistNclustersVsEvent->GetBinContent(bin+1))/2.0;
456 fHistNclustersVsEvent->SetBinContent(newBin, newContent);
459 // Set the remaining bins to 0
460 Int_t lastHalf = nBins/2 +1;
461 for(Int_t bin = lastHalf; bin <= nBins; bin++) {
463 fHistOccupancyVsEvent->SetBinContent(bin, 0);
464 fHistNclustersVsEvent->SetBinContent(bin, 0);
467 // In this case we should nut update but wait untill the new
468 // number of events per bin is reached!
472 const Int_t bin = TMath::Nint(Float_t(fEventCounter)/fEventsPerBin);
474 Float_t averageOccupancy =
475 Float_t(fSignalCounter)/fEventsPerBin/(fLastTimeBin - fFirstTimeBin +1.0)
476 / 570132.0; // 570,132 is number of pads
477 fHistOccupancyVsEvent->SetBinContent(bin, averageOccupancy);
480 Float_t averageNclusters =
481 Float_t(fClusterCounter)/fEventsPerBin;
482 fHistNclustersVsEvent->SetBinContent(bin, averageNclusters);
486 //_____________________________________________________________________
487 Bool_t AliTPCdataQA::ProcessEvent(AliTPCRawStreamV3 *const rawStreamV3)
490 // Event Processing loop - AliTPCRawStreamV3
492 Bool_t withInput = kFALSE;
494 Int_t lastSector = -1;
496 while ( rawStreamV3->NextDDL() ){
498 while ( rawStreamV3->NextChannel() ){
500 Int_t iSector = rawStreamV3->GetSector(); // current sector
501 Int_t iRow = rawStreamV3->GetRow(); // current row
502 Int_t iPad = rawStreamV3->GetPad(); // current pad
503 if (iRow<0 || iPad<0) continue;
504 // Call local maxima finder if the data is in a new sector
505 if(iSector != lastSector) {
508 FindLocalMaxima(lastSector);
511 lastSector = iSector;
515 while ( rawStreamV3->NextBunch() ){
517 Int_t startTbin = (Int_t)rawStreamV3->GetStartTimeBin();
518 Int_t bunchlength = (Int_t)rawStreamV3->GetBunchLength();
519 const UShort_t *sig = rawStreamV3->GetSignals();
521 for (Int_t iTimeBin = 0; iTimeBin<bunchlength; iTimeBin++){
522 Float_t signal=(Float_t)sig[iTimeBin];
523 nSignals += Update(iSector,iRow,iPad,startTbin--,signal);
530 if (lastSector>=0&&nSignals>0)
531 FindLocalMaxima(lastSector);
536 //_____________________________________________________________________
537 Bool_t AliTPCdataQA::ProcessEvent(AliRawReader *const rawReader)
540 // Event processing loop - AliRawReader
542 AliTPCRawStreamV3 rawStreamV3(rawReader, (AliAltroMapping**)fMapping);
543 Bool_t res=ProcessEvent(&rawStreamV3);
545 fEventCounter++; // only increment event counter if there is TPC data
547 if(fEventCounter%fEventsPerBin==0)
548 UpdateEventHistograms();
553 //_____________________________________________________________________
554 Bool_t AliTPCdataQA::ProcessEvent(AliTPCRawStream *const rawStream)
557 // Event Processing loop - AliTPCRawStream
560 Bool_t withInput = kFALSE;
562 Int_t lastSector = -1;
564 while (rawStream->Next()) {
566 Int_t iSector = rawStream->GetSector(); // current ROC
567 Int_t iRow = rawStream->GetRow(); // current row
568 Int_t iPad = rawStream->GetPad(); // current pad
569 Int_t iTimeBin = rawStream->GetTime(); // current time bin
570 Float_t signal = rawStream->GetSignal(); // current ADC signal
572 // Call local maxima finder if the data is in a new sector
573 if(iSector != lastSector) {
576 FindLocalMaxima(lastSector);
579 lastSector = iSector;
583 // Sometimes iRow==-1 if there is problems to read the data
585 nSignals += Update(iSector,iRow,iPad,iTimeBin,signal);
590 if (lastSector>=0&&nSignals>0)
591 FindLocalMaxima(lastSector);
597 //_____________________________________________________________________
598 Bool_t AliTPCdataQA::ProcessEventOld(AliRawReader *const rawReader)
601 // Event processing loop - AliRawReader
604 // if fMapping is NULL the rawstream will crate its own mapping
605 AliTPCRawStream rawStream(rawReader, (AliAltroMapping**)fMapping);
606 rawReader->Select("TPC");
607 Bool_t res = ProcessEvent(&rawStream);
610 fEventCounter++; // only increment event counter if there is TPC data
611 // otherwise Analyse (called in QA) fails
616 //_____________________________________________________________________
617 Bool_t AliTPCdataQA::ProcessEvent(eventHeaderStruct *const event)
620 // process date event
623 AliRawReaderDate rawReader((void*)event);
624 Bool_t result=ProcessEvent(&rawReader);
630 //_____________________________________________________________________
631 void AliTPCdataQA::DumpToFile(const Char_t *filename, const Char_t *dir, Bool_t append) /*FOLD00*/
634 // Write class to file
645 TDirectory *backup = gDirectory;
646 TFile f(filename,option.Data());
648 if ( !sDir.IsNull() ){
649 f.mkdir(sDir.Data());
655 if ( backup ) backup->cd();
659 //_____________________________________________________________________
660 Int_t AliTPCdataQA::Update(const Int_t iSector, /*FOLD00*/
663 const Int_t iTimeBin,
667 // Signal filling method
671 // Define the calibration objects the first time Update is called
672 // NB! This has to be done first even if the data is rejected by the time
673 // cut to make sure that the objects are available in Analyse
677 if (!fNLocalMaxima) fNLocalMaxima = new AliTPCCalPad("NLocalMaxima","NLocalMaxima");
678 if (!fMaxCharge) fMaxCharge = new AliTPCCalPad("MaxCharge","MaxCharge");
679 if (!fMeanCharge) fMeanCharge = new AliTPCCalPad("MeanCharge","MeanCharge");
680 if (!fNoThreshold) fNoThreshold = new AliTPCCalPad("NoThreshold","NoThreshold");
681 if (!fNTimeBins) fNTimeBins = new AliTPCCalPad("NTimeBins","NTimeBins");
682 if (!fNPads) fNPads = new AliTPCCalPad("NPads","NPads");
683 if (!fTimePosition) fTimePosition = new AliTPCCalPad("TimePosition","TimePosition");
684 if (!fOverThreshold10) fOverThreshold10 = new AliTPCCalPad("OverThreshold10","OverThreshold10");
685 if (!fOverThreshold20) fOverThreshold20 = new AliTPCCalPad("OverThreshold20","OverThreshold20");
686 if (!fOverThreshold30) fOverThreshold30 = new AliTPCCalPad("OverThreshold30","OverThreshold30");
687 if (!fHistQVsTimeSideA) {
688 fHistQVsTimeSideA = new TProfile("hQVsTimeSideA", "Q vs time (side A); Time [Timebin]; Q [ADC ch]", 100, 0, 1000);
689 fHistQVsTimeSideA->SetDirectory(0);
691 if (!fHistQVsTimeSideC) {
692 fHistQVsTimeSideC = new TProfile("hQVsTimeSideC", "Q vs time (side C); Time [Timebin]; Q [ADC ch]", 100, 0, 1000);
693 fHistQVsTimeSideC->SetDirectory(0);
695 if (!fHistQMaxVsTimeSideA) {
696 fHistQMaxVsTimeSideA = new TProfile("hQMaxVsTimeSideA", "Q_{MAX} vs time (side A); Time [Timebin]; Q_{MAX} [ADC ch]", 100, 0, 1000);
697 fHistQMaxVsTimeSideA->SetDirectory(0);
699 if (!fHistQMaxVsTimeSideC) {
700 fHistQMaxVsTimeSideC = new TProfile("hQMaxVsTimeSideC", "Q_{MAX} vs time (side C); Time [Timebin]; Q_{MAX} [ADC ch]", 100, 0, 1000);
701 fHistQMaxVsTimeSideC->SetDirectory(0);
703 } else { // DQM histograms and array
705 if (!fHistOccVsSector) {
706 fHistOccVsSector = new TProfile("hOccVsSector", "Occupancy vs sector; Sector; Occupancy", 72, 0, 72);
707 fHistOccVsSector->SetDirectory(0);
709 fHistQVsSector = new TProfile("hQVsSector", "Q vs sector; Sector; Q [ADC ch]", 72, 0, 72);
710 fHistQVsSector->SetDirectory(0);
712 fHistQmaxVsSector = new TProfile("hQmaxVsSector", "Qmax vs sector; Sector; Qmax [ADC ch]", 72, 0, 72);
713 fHistQmaxVsSector->SetDirectory(0);
715 fOccVec = new TArrayD(72);
716 for(Int_t i = 0; i < 72; i++)
717 fOccVec->GetArray()[i] = 0;
719 fOccMaxVec = new TArrayD(72);
720 Double_t nTimeBins = fLastTimeBin - fFirstTimeBin +1;
721 for(Int_t i = 0; i < 72; i++)
723 if(i<36) // IROCs (5504 pads)
724 fOccMaxVec->GetArray()[i] = nTimeBins*5504;
725 else // OROCs (9984 pads)
726 fOccMaxVec->GetArray()[i] = nTimeBins*9984;
729 // Make the arrays for expanding the data
735 // If Analyse has been previously called we need now to denormalize the data
736 // as more data is coming
738 if(fIsAnalysed == kTRUE && !fIsDQM) {
740 const Int_t nTimeBins = fLastTimeBin - fFirstTimeBin +1;
741 const Float_t denormalization = Float_t(fEventCounter * nTimeBins);
742 fNoThreshold->Multiply(denormalization);
744 fMeanCharge->Multiply(fNLocalMaxima);
745 fMaxCharge->Multiply(fNLocalMaxima);
746 fNTimeBins->Multiply(fNLocalMaxima);
747 fNPads->Multiply(fNLocalMaxima);
748 fTimePosition->Multiply(fNLocalMaxima);
749 fIsAnalysed = kFALSE;
755 if (iTimeBin<fFirstTimeBin) return 0;
756 if (iTimeBin>fLastTimeBin) return 0;
758 // if pedestal calibrations are loaded subtract pedestals
761 Float_t ped = fPedestal->GetCalROC(iSector)->GetValue(iRow, iPad);
762 // Don't use data from pads where pedestals are abnormally small or large
770 fOccVec->GetArray()[iSector] += 1.0;
772 // In fNoThreshold we fill all data to estimate the ZS volume
773 Float_t count = fNoThreshold->GetCalROC(iSector)->GetValue(iRow, iPad);
774 fNoThreshold->GetCalROC(iSector)->SetValue(iRow, iPad,count+1);
777 // Require at least 3 ADC channels
781 // if noise calibrations are loaded require at least 3*sigmaNoise
784 Float_t noise = fNoise->GetCalROC(iSector)->GetValue(iRow, iPad);
786 if(signal < noise*3.0)
791 // This signal is ok and we store it in the cluster map
794 SetExpandDigit(iRow, iPad, iTimeBin, signal);
798 return 1; // signal was accepted
801 //_____________________________________________________________________
802 void AliTPCdataQA::FindLocalMaxima(const Int_t iSector)
805 // This method is called after the data from each sector has been
806 // exapanded into an array
807 // Loop over the signals and identify local maxima and fill the
808 // calibration objects with the information
811 Int_t nLocalMaxima = 0;
812 const Int_t maxTimeBin = fTimeBinsMax+4; // Used to step between neighboring pads
813 // Because we have tha pad-time data in a
816 for (Int_t iRow = 0; iRow < fRowsMax; iRow++) {
818 Float_t* allBins = fAllBins[iRow];
819 Int_t* sigBins = fAllSigBins[iRow];
820 const Int_t nSigBins = fAllNSigBins[iRow];
822 for (Int_t iSig = 0; iSig < nSigBins; iSig++) {
824 Int_t bin = sigBins[iSig];
825 Float_t *b = &allBins[bin];
828 // Now we check if this is a local maximum
833 // First check that the charge is bigger than the threshold
837 // Require at least one neighboring pad with signal
838 if (b[-maxTimeBin]+b[maxTimeBin]<=0) continue;
840 // Require at least one neighboring time bin with signal
841 if (b[-1]+b[1]<=0) continue;
844 // Check that this is a local maximum
845 // Note that the checking is done so that if 2 charges has the same
846 // qMax then only 1 cluster is generated
847 // (that is why there is BOTH > and >=)
849 if (b[-maxTimeBin] >= qMax) continue;
850 if (b[-1 ] >= qMax) continue;
851 if (b[+maxTimeBin] > qMax) continue;
852 if (b[+1 ] > qMax) continue;
853 if (b[-maxTimeBin-1] >= qMax) continue;
854 if (b[+maxTimeBin-1] >= qMax) continue;
855 if (b[+maxTimeBin+1] > qMax) continue;
856 if (b[-maxTimeBin+1] >= qMax) continue;
859 // Now we accept the local maximum and fill the calibration/data objects
863 Int_t iPad, iTimeBin;
864 GetPadAndTimeBin(bin, iPad, iTimeBin);
867 Float_t count = fNLocalMaxima->GetCalROC(iSector)->GetValue(iRow, iPad);
868 fNLocalMaxima->GetCalROC(iSector)->SetValue(iRow, iPad, count+1);
870 count = fTimePosition->GetCalROC(iSector)->GetValue(iRow, iPad);
871 fTimePosition->GetCalROC(iSector)->SetValue(iRow, iPad, count+iTimeBin);
873 Float_t charge = fMaxCharge->GetCalROC(iSector)->GetValue(iRow, iPad);
874 fMaxCharge->GetCalROC(iSector)->SetValue(iRow, iPad, charge + qMax);
877 count = fOverThreshold10->GetCalROC(iSector)->GetValue(iRow, iPad);
878 fOverThreshold10->GetCalROC(iSector)->SetValue(iRow, iPad, count+1);
881 count = fOverThreshold20->GetCalROC(iSector)->GetValue(iRow, iPad);
882 fOverThreshold20->GetCalROC(iSector)->SetValue(iRow, iPad, count+1);
885 count = fOverThreshold30->GetCalROC(iSector)->GetValue(iRow, iPad);
886 fOverThreshold30->GetCalROC(iSector)->SetValue(iRow, iPad, count+1);
891 // Calculate the total charge as the sum over the region:
899 // with qmax at the center C.
901 // The inner charge (i) we always add, but we only add the outer
902 // charge (o) if the neighboring inner bin (i) has a signal.
904 Int_t minP = 0, maxP = 0, minT = 0, maxT = 0;
906 for(Int_t i = -1; i<=1; i++) {
907 for(Int_t j = -1; j<=1; j++) {
912 Float_t charge1 = GetQ(b, i, j, maxTimeBin, minT, maxT, minP, maxP);
915 // see if the next neighbor is also above threshold
917 qTot += GetQ(b, 2*i, 2*j, maxTimeBin, minT, maxT, minP, maxP);
919 // we are in a diagonal corner
920 qTot += GetQ(b, i, 2*j, maxTimeBin, minT, maxT, minP, maxP);
921 qTot += GetQ(b, 2*i, j, maxTimeBin, minT, maxT, minP, maxP);
922 qTot += GetQ(b, 2*i, 2*j, maxTimeBin, minT, maxT, minP, maxP);
929 fHistQVsSector->Fill(iSector, qTot);
930 fHistQmaxVsSector->Fill(iSector, qMax);
932 Float_t charge = fMeanCharge->GetCalROC(iSector)->GetValue(iRow, iPad);
933 fMeanCharge->GetCalROC(iSector)->SetValue(iRow, iPad, charge + qTot);
935 Float_t count = fNTimeBins->GetCalROC(iSector)->GetValue(iRow, iPad);
936 fNTimeBins->GetCalROC(iSector)->SetValue(iRow, iPad, count + maxT-minT+1);
938 count = fNPads->GetCalROC(iSector)->GetValue(iRow, iPad);
939 fNPads->GetCalROC(iSector)->SetValue(iRow, iPad, count + maxP-minP+1);
941 if((iSector%36)<18) { // A side
942 fHistQVsTimeSideA->Fill(iTimeBin, qTot);
943 fHistQMaxVsTimeSideA->Fill(iTimeBin, qMax);
945 fHistQVsTimeSideC->Fill(iTimeBin, qTot);
946 fHistQMaxVsTimeSideC->Fill(iTimeBin, qMax);
949 } // end loop over signals
950 } // end loop over rows
952 fClusterCounter += nLocalMaxima;
955 //_____________________________________________________________________
956 void AliTPCdataQA::Analyse()
959 // Calculate calibration constants
962 AliInfo("Analyse called");
964 if(fIsDQM == kTRUE) {
966 AliInfo("DQM flas is set -> No 2d information to analyze");
970 if(fIsAnalysed == kTRUE) {
972 AliInfo("No new data since Analyse was called last time");
976 if(fEventCounter==0) {
978 AliInfo("EventCounter == 0, Cannot analyse");
982 Int_t nTimeBins = fLastTimeBin - fFirstTimeBin +1;
983 AliInfo(Form("EventCounter: %d , TimeBins: %d", fEventCounter, nTimeBins));
985 Float_t normalization = 1.0 / Float_t(fEventCounter * nTimeBins);
986 fNoThreshold->Multiply(normalization);
988 fMeanCharge->Divide(fNLocalMaxima);
989 fMaxCharge->Divide(fNLocalMaxima);
990 fNTimeBins->Divide(fNLocalMaxima);
991 fNPads->Divide(fNLocalMaxima);
992 fTimePosition->Divide(fNLocalMaxima);
998 //_____________________________________________________________________
999 void AliTPCdataQA::MakeTree(const char *fname) const {
1001 // Export result to the tree -located in the file
1002 // This file can be analyzed using AliTPCCalibViewer
1004 AliTPCPreprocessorOnline preprocesor;
1006 if (fNLocalMaxima) preprocesor.AddComponent(fNLocalMaxima);
1007 if (fMaxCharge) preprocesor.AddComponent(fMaxCharge);
1008 if (fMeanCharge) preprocesor.AddComponent(fMeanCharge);
1009 if (fNoThreshold) preprocesor.AddComponent(fNoThreshold);
1010 if (fNTimeBins) preprocesor.AddComponent(fNTimeBins);
1011 if (fNPads) preprocesor.AddComponent(fNPads);
1012 if (fTimePosition) preprocesor.AddComponent(fTimePosition);
1013 if (fOverThreshold10) preprocesor.AddComponent(fOverThreshold10);
1014 if (fOverThreshold20) preprocesor.AddComponent(fOverThreshold20);
1015 if (fOverThreshold30) preprocesor.AddComponent(fOverThreshold30);
1017 preprocesor.DumpToFile(fname);
1021 //_____________________________________________________________________
1022 void AliTPCdataQA::MakeArrays(){
1024 // The arrays for expanding the raw data are defined and
1025 // som parameters are intialised
1027 AliTPCROC * roc = AliTPCROC::Instance();
1029 // To make the array big enough for all sectors we take
1030 // the dimensions from the outer row of an OROC (the last sector)
1032 fRowsMax = roc->GetNRows(roc->GetNSector()-1);
1033 fPadsMax = roc->GetNPads(roc->GetNSector()-1,fRowsMax-1);
1034 fTimeBinsMax = fLastTimeBin - fFirstTimeBin +1;
1037 // Since we have added 2 pads (TimeBins) before and after the real pads (TimeBins)
1038 // to make sure that we can always query the exanded table even when the
1039 // max is on the edge
1043 fAllBins = new Float_t*[fRowsMax];
1044 fAllSigBins = new Int_t*[fRowsMax];
1045 fAllNSigBins = new Int_t[fRowsMax];
1047 for (Int_t iRow = 0; iRow < fRowsMax; iRow++) {
1049 Int_t maxBin = (fTimeBinsMax+4)*(fPadsMax+4);
1050 fAllBins[iRow] = new Float_t[maxBin];
1051 memset(fAllBins[iRow],0,sizeof(Float_t)*maxBin); // set all values to 0
1052 fAllSigBins[iRow] = new Int_t[maxBin];
1053 fAllNSigBins[iRow] = 0;
1058 //_____________________________________________________________________
1059 void AliTPCdataQA::CleanArrays(){
1064 for (Int_t iRow = 0; iRow < fRowsMax; iRow++) {
1066 // To speed up the performance by a factor 2 on cosmic data (and
1067 // presumably pp data as well) where the ocupancy is low, the
1068 // memset is only called if there is more than 1000 signals for a
1069 // row (of the order 1% occupancy)
1070 if(fAllNSigBins[iRow]<1000) {
1072 Float_t* allBins = fAllBins[iRow];
1073 Int_t* sigBins = fAllSigBins[iRow];
1074 const Int_t nSignals = fAllNSigBins[iRow];
1075 for(Int_t i = 0; i < nSignals; i++)
1076 allBins[sigBins[i]]=0;
1079 Int_t maxBin = (fTimeBinsMax+4)*(fPadsMax+4);
1080 memset(fAllBins[iRow],0,sizeof(Float_t)*maxBin);
1083 fAllNSigBins[iRow]=0;
1087 //_____________________________________________________________________
1088 void AliTPCdataQA::GetPadAndTimeBin(Int_t bin, Int_t& iPad, Int_t& iTimeBin){
1090 // Return pad and timebin for a given bin
1093 // Int_t bin = iPad*(fTimeBinsMax+4)+iTimeBin;
1094 iTimeBin = bin%(fTimeBinsMax+4);
1095 iPad = (bin-iTimeBin)/(fTimeBinsMax+4);
1099 iTimeBin += fFirstTimeBin;
1101 R__ASSERT(iPad>=0 && iPad<=fPadsMax);
1102 R__ASSERT(iTimeBin>=fFirstTimeBin && iTimeBin<=fLastTimeBin);
1105 //_____________________________________________________________________
1106 void AliTPCdataQA::SetExpandDigit(const Int_t iRow, Int_t iPad,
1107 Int_t iTimeBin, const Float_t signal)
1112 R__ASSERT(iRow>=0 && iRow<fRowsMax);
1113 R__ASSERT(iPad>=0 && iPad<=fPadsMax);
1114 R__ASSERT(iTimeBin>=fFirstTimeBin && iTimeBin<=fLastTimeBin);
1116 iTimeBin -= fFirstTimeBin;
1120 Int_t bin = iPad*(fTimeBinsMax+4)+iTimeBin;
1121 fAllBins[iRow][bin] = signal;
1122 fAllSigBins[iRow][fAllNSigBins[iRow]] = bin;
1123 fAllNSigBins[iRow]++;
1126 //______________________________________________________________________________
1127 Float_t AliTPCdataQA::GetQ(const Float_t* adcArray, const Int_t time,
1128 const Int_t pad, const Int_t maxTimeBins,
1129 Int_t& timeMin, Int_t& timeMax,
1130 Int_t& padMin, Int_t& padMax) const
1133 // This methods return the charge in the bin time+pad*maxTimeBins
1134 // If the charge is above 0 it also updates the padMin, padMax, timeMin
1135 // and timeMax if necessary
1137 Float_t charge = adcArray[time + pad*maxTimeBins];
1139 timeMin = TMath::Min(time, timeMin); timeMax = TMath::Max(time, timeMax);
1140 padMin = TMath::Min(pad, padMin); padMax = TMath::Max(pad, padMax);
1145 //______________________________________________________________________________
1146 void AliTPCdataQA::Streamer(TBuffer &xRuub)
1148 // Automatic schema evolution was first used from revision 4
1150 // http://root.cern.ch/root/roottalk/roottalk02/3207.html
1152 UInt_t xRuus, xRuuc;
1153 if (xRuub.IsReading()) {
1154 Version_t xRuuv = xRuub.ReadVersion(&xRuus, &xRuuc);
1155 //we use the automatic algorithm for class version > 3
1157 AliTPCdataQA::Class()->ReadBuffer(xRuub, this, xRuuv, xRuus,
1161 TH1F::Streamer(xRuub);
1162 xRuub >> fFirstTimeBin;
1163 xRuub >> fLastTimeBin;
1166 xRuub >> fNLocalMaxima;
1167 xRuub >> fMaxCharge;
1168 xRuub >> fMeanCharge;
1169 xRuub >> fNoThreshold;
1170 xRuub >> fNTimeBins;
1172 xRuub >> fTimePosition;
1173 xRuub >> fEventCounter;
1174 xRuub >> fIsAnalysed;
1175 xRuub.CheckByteCount(xRuus, xRuuc, AliTPCdataQA::IsA());
1177 AliTPCdataQA::Class()->WriteBuffer(xRuub,this);
1181 //____________________________________________________________________________________________
1182 void AliTPCdataQA::FillOccupancyProfile()
1184 // This has to be filled at the end of the loop over data
1186 AliInfo("Method only meaningful for DQM");
1188 for(Int_t i = 0; i < 72; i++) {
1190 fOccVec->GetArray()[i] /= fOccMaxVec->GetArray()[i];
1191 fHistOccVsSector->Fill(i, fOccVec->GetArray()[i]);
1195 //____________________________________________________________________________________________
1196 void AliTPCdataQA::ResetProfiles()
1199 AliInfo("Method only meaningful for DQM");
1202 fHistQVsSector->Reset();
1203 if(fHistQmaxVsSector)
1204 fHistQmaxVsSector->Reset();
1205 if(fHistOccVsSector)
1206 fHistOccVsSector->Reset();
1209 for(Int_t i = 0; i < 72; i++)
1210 fOccVec->GetArray()[i] = 0.0;