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 AliTPCclusterer 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 "AliTPCRawStreamV3.h"
111 #include "AliTPCCalROC.h"
112 #include "AliTPCROC.h"
113 #include "AliMathBase.h"
114 #include "TTreeStream.h"
118 #include "AliTPCCalPad.h"
119 #include "AliTPCPreprocessorOnline.h"
122 #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),
166 fHistOcc2dVsSector(0x0),
168 fHistQmaxVsSector(0x0),
175 // default constructor
179 //_____________________________________________________________________
180 AliTPCdataQA::AliTPCdataQA(const AliTPCdataQA &ped) : /*FOLD00*/
182 fFirstTimeBin(ped.GetFirstTimeBin()),
183 fLastTimeBin(ped.GetLastTimeBin()),
184 fAdcMin(ped.GetAdcMin()),
185 fAdcMax(ped.GetAdcMax()),
199 fHistQVsTimeSideA(0),
200 fHistQVsTimeSideC(0),
201 fHistQMaxVsTimeSideA(0),
202 fHistQMaxVsTimeSideC(0),
203 fHistOccupancyVsEvent(0),
204 fHistNclustersVsEvent(0),
205 fEventCounter(ped.GetEventCounter()),
206 fIsAnalysed(ped.GetIsAnalysed()),
207 fMaxEvents(ped.GetMaxEvents()),
208 fEventsPerBin(ped.GetEventsPerBin()),
209 fSignalCounter(ped.GetSignalCounter()),
210 fClusterCounter(ped.GetClusterCounter()),
217 fIsDQM(ped.GetIsDQM()),
218 fHistOccVsSector(0x0),
219 fHistOcc2dVsSector(0x0),
221 fHistQmaxVsSector(0x0),
230 if(ped.GetNLocalMaxima())
231 fNLocalMaxima = new AliTPCCalPad(*ped.GetNLocalMaxima());
232 if(ped.GetMaxCharge())
233 fMaxCharge = new AliTPCCalPad(*ped.GetMaxCharge());
234 if(ped.GetMeanCharge())
235 fMeanCharge = new AliTPCCalPad(*ped.GetMeanCharge());
236 if(ped.GetNoThreshold())
237 fNoThreshold = new AliTPCCalPad(*ped.GetNoThreshold());
238 if(ped.GetNTimeBins())
239 fNTimeBins = new AliTPCCalPad(*ped.GetNTimeBins());
241 fNPads = new AliTPCCalPad(*ped.GetNPads());
242 if(ped.GetTimePosition())
243 fTimePosition = new AliTPCCalPad(*ped.GetTimePosition());
244 if(ped.GetOverThreshold10())
245 fOverThreshold10 = new AliTPCCalPad(*ped.GetOverThreshold10());
246 if(ped.GetOverThreshold20())
247 fOverThreshold20 = new AliTPCCalPad(*ped.GetOverThreshold20());
248 if(ped.GetOverThreshold30())
249 fOverThreshold30 = new AliTPCCalPad(*ped.GetOverThreshold30());
250 if(ped.GetHistQVsTimeSideA()) {
251 fHistQVsTimeSideA = new TProfile(*ped.GetHistQVsTimeSideA());
252 fHistQVsTimeSideA->SetDirectory(0);
254 if(ped.GetHistQVsTimeSideC()) {
255 fHistQVsTimeSideC = new TProfile(*ped.GetHistQVsTimeSideC());
256 fHistQVsTimeSideC->SetDirectory(0);
258 if(ped.GetHistQMaxVsTimeSideA()) {
259 fHistQMaxVsTimeSideA = new TProfile(*ped.GetHistQMaxVsTimeSideA());
260 fHistQMaxVsTimeSideA->SetDirectory(0);
262 if(ped.GetHistQMaxVsTimeSideC()) {
263 fHistQMaxVsTimeSideC = new TProfile(*ped.GetHistQMaxVsTimeSideC());
264 fHistQMaxVsTimeSideC->SetDirectory(0);
266 if(ped.GetHistOccupancyVsEventConst()) {
267 fHistOccupancyVsEvent = new TH1F(*ped.GetHistOccupancyVsEventConst());
268 fHistOccupancyVsEvent->SetDirectory(0);
270 if(ped.GetHistNclustersVsEventConst()) {
271 fHistNclustersVsEvent = new TH1F(*ped.GetHistNclustersVsEventConst());
272 fHistNclustersVsEvent->SetDirectory(0);
276 //_____________________________________________________________________
277 AliTPCdataQA::AliTPCdataQA(const TMap *config) : /*FOLD00*/
278 TH1F("TPCRAW","TPCRAW",100,0,100),
296 fHistQVsTimeSideA(0),
297 fHistQVsTimeSideC(0),
298 fHistQMaxVsTimeSideA(0),
299 fHistQMaxVsTimeSideC(0),
300 fHistOccupancyVsEvent(0),
301 fHistNclustersVsEvent(0),
315 fHistOccVsSector(0x0),
316 fHistOcc2dVsSector(0x0),
318 fHistQmaxVsSector(0x0),
325 // default constructor
327 if (config->GetValue("FirstTimeBin")) fFirstTimeBin = ((TObjString*)config->GetValue("FirstTimeBin"))->GetString().Atoi();
328 if (config->GetValue("LastTimeBin")) fLastTimeBin = ((TObjString*)config->GetValue("LastTimeBin"))->GetString().Atoi();
329 if (config->GetValue("AdcMin")) fAdcMin = ((TObjString*)config->GetValue("AdcMin"))->GetString().Atoi();
330 if (config->GetValue("AdcMax")) fAdcMax = ((TObjString*)config->GetValue("AdcMax"))->GetString().Atoi();
331 if (config->GetValue("MaxEvents")) fMaxEvents = ((TObjString*)config->GetValue("MaxEvents"))->GetString().Atoi();
332 if (config->GetValue("EventsPerBin")) fEventsPerBin = ((TObjString*)config->GetValue("EventsPerBin"))->GetString().Atoi();
335 //_____________________________________________________________________
336 AliTPCdataQA& AliTPCdataQA::operator = (const AliTPCdataQA &source)
339 // assignment operator
341 if (&source == this) return *this;
342 new (this) AliTPCdataQA(source);
348 //_____________________________________________________________________
349 AliTPCdataQA::~AliTPCdataQA() /*FOLD00*/
355 // do not delete fMapping, because we do not own it.
356 // do not delete fMapping, because we do not own it.
357 // do not delete fNoise and fPedestal, because we do not own them.
359 delete fNLocalMaxima;
365 delete fTimePosition;
366 delete fOverThreshold10;
367 delete fOverThreshold20;
368 delete fOverThreshold30;
369 delete fHistQVsTimeSideA;
370 delete fHistQVsTimeSideC;
371 delete fHistQMaxVsTimeSideA;
372 delete fHistQMaxVsTimeSideC;
373 delete fHistOccupancyVsEvent;
374 delete fHistNclustersVsEvent;
377 delete fHistOccVsSector;
378 delete fHistOcc2dVsSector;
379 delete fHistQVsSector;
380 delete fHistQmaxVsSector;
384 delete fOccMaxVecFine;
386 for (Int_t iRow = 0; iRow < fRowsMax; iRow++) {
387 delete [] fAllBins[iRow];
388 delete [] fAllSigBins[iRow];
391 delete [] fAllSigBins;
392 delete [] fAllNSigBins;
395 //_____________________________________________________________________
396 TH1F* AliTPCdataQA::GetHistOccupancyVsEvent()
399 // Create Occupancy vs event histogram
400 // (we create this histogram differently then the other histograms
401 // because this we want to be able to access and copy
402 // from AliTPCQAMakerRec before it normally would be created)
404 if(!fHistOccupancyVsEvent) {
406 Int_t nBins = fMaxEvents/fEventsPerBin;
407 fHistOccupancyVsEvent = new TH1F("hOccupancyVsEvent", "Occupancy vs event number (~time); Event number; Occupancy", nBins, 0, nBins*fEventsPerBin);
408 fHistOccupancyVsEvent->SetDirectory(0);
411 return fHistOccupancyVsEvent;
414 //_____________________________________________________________________
415 TH1F* AliTPCdataQA::GetHistNclustersVsEvent()
418 // Create Nclusters vs event histogram
419 // (we create this histogram differently then the other histograms
420 // because this we want to be able to access and copy
421 // from AliTPCQAMakerRec before it normally would be created)
423 if(!fHistNclustersVsEvent) {
425 Int_t nBins = fMaxEvents/fEventsPerBin;
426 fHistNclustersVsEvent = new TH1F("hNclustersVsEvent", "Nclusters vs event number (~time); Event number; Nclusters per event", nBins, 0, nBins*fEventsPerBin);
427 fHistNclustersVsEvent->SetDirectory(0);
430 return fHistNclustersVsEvent;
433 //_____________________________________________________________________
434 void AliTPCdataQA::UpdateEventHistograms()
436 // Update histograms that display occupancy and
437 // number of clusters as a function of number of
439 if (!fHistOccupancyVsEvent)
440 GetHistOccupancyVsEvent();
441 if (!fHistNclustersVsEvent)
442 GetHistNclustersVsEvent();
444 if(fEventCounter > fMaxEvents) {
446 // we have to expand the histogram to handle the larger number of
447 // events. The way it is done now is to double the range and the
448 // number of events per bin (so the number of histogram bins stays
453 // Change histogram limits
454 const Int_t nBins = fHistOccupancyVsEvent->GetXaxis()->GetNbins();
455 fHistOccupancyVsEvent->GetXaxis()->Set(nBins, fHistOccupancyVsEvent->GetXaxis()->GetNbins(), fMaxEvents);
456 fHistNclustersVsEvent->GetXaxis()->Set(nBins, fHistNclustersVsEvent->GetXaxis()->GetNbins(), fMaxEvents);
458 // Rebin the histogram
459 for(Int_t bin = 1; bin <= nBins; bin+=2) {
461 Int_t newBin = TMath::Nint(Float_t(bin+1)/2.0);
462 Float_t newContent = (fHistOccupancyVsEvent->GetBinContent(bin)+
463 fHistOccupancyVsEvent->GetBinContent(bin+1))/2.0;
464 fHistOccupancyVsEvent->SetBinContent(newBin, newContent);
466 newContent = (fHistNclustersVsEvent->GetBinContent(bin)+
467 fHistNclustersVsEvent->GetBinContent(bin+1))/2.0;
468 fHistNclustersVsEvent->SetBinContent(newBin, newContent);
471 // Set the remaining bins to 0
472 Int_t lastHalf = nBins/2 +1;
473 for(Int_t bin = lastHalf; bin <= nBins; bin++) {
475 fHistOccupancyVsEvent->SetBinContent(bin, 0);
476 fHistNclustersVsEvent->SetBinContent(bin, 0);
479 // In this case we should nut update but wait untill the new
480 // number of events per bin is reached!
484 const Int_t bin = TMath::Nint(Float_t(fEventCounter)/fEventsPerBin);
486 Float_t averageOccupancy =
487 Float_t(fSignalCounter)/fEventsPerBin/(fLastTimeBin - fFirstTimeBin +1.0)
488 / 570132.0; // 570,132 is number of pads
489 fHistOccupancyVsEvent->SetBinContent(bin, averageOccupancy);
492 Float_t averageNclusters =
493 Float_t(fClusterCounter)/fEventsPerBin;
494 fHistNclustersVsEvent->SetBinContent(bin, averageNclusters);
498 //_____________________________________________________________________
499 Bool_t AliTPCdataQA::ProcessEvent(AliTPCRawStreamV3 *const rawStreamV3)
502 // Event Processing loop - AliTPCRawStreamV3
504 Bool_t withInput = kFALSE;
506 Int_t lastSector = -1;
508 while ( rawStreamV3->NextDDL() ){
510 while ( rawStreamV3->NextChannel() ){
512 Int_t iSector = rawStreamV3->GetSector(); // current sector
513 Int_t iRow = rawStreamV3->GetRow(); // current row
514 Int_t iPad = rawStreamV3->GetPad(); // current pad
515 Int_t iPatch = rawStreamV3->GetPatchIndex(); // current patch
516 Int_t iBranch = rawStreamV3->GetBranch(); // current branch
517 if (iRow<0 || iPad<0) continue;
518 // Call local maxima finder if the data is in a new sector
519 if(iSector != lastSector) {
522 FindLocalMaxima(lastSector);
525 lastSector = iSector;
529 while ( rawStreamV3->NextBunch() ){
531 Int_t startTbin = (Int_t)rawStreamV3->GetStartTimeBin();
532 Int_t bunchlength = (Int_t)rawStreamV3->GetBunchLength();
533 const UShort_t *sig = rawStreamV3->GetSignals();
535 for (Int_t iTimeBin = 0; iTimeBin<bunchlength; iTimeBin++){
536 Float_t signal=(Float_t)sig[iTimeBin];
537 nSignals += Update(iSector,iRow,iPad,startTbin--,signal, iPatch, iBranch);
544 if (lastSector>=0&&nSignals>0)
545 FindLocalMaxima(lastSector);
550 //_____________________________________________________________________
551 Bool_t AliTPCdataQA::ProcessEvent(AliRawReader *const rawReader)
554 // Event processing loop - AliRawReader
556 AliTPCRawStreamV3 rawStreamV3(rawReader,(AliAltroMapping**)fMapping);
557 Bool_t res=ProcessEvent(&rawStreamV3);
559 fEventCounter++; // only increment event counter if there is TPC data
561 if(fEventCounter%fEventsPerBin==0)
562 UpdateEventHistograms();
567 //_____________________________________________________________________
568 Bool_t AliTPCdataQA::ProcessEvent(eventHeaderStruct *const event)
571 // process date event
574 AliRawReaderDate rawReader((void*)event);
575 Bool_t result=ProcessEvent(&rawReader);
581 //_____________________________________________________________________
582 void AliTPCdataQA::DumpToFile(const Char_t *filename, const Char_t *dir, Bool_t append) /*FOLD00*/
585 // Write class to file
596 TDirectory *backup = gDirectory;
597 TFile f(filename,option.Data());
599 if ( !sDir.IsNull() ){
600 f.mkdir(sDir.Data());
606 if ( backup ) backup->cd();
610 //_____________________________________________________________________
611 Int_t AliTPCdataQA::Update(const Int_t iSector, /*FOLD00*/
614 const Int_t iTimeBin,
620 // Signal filling method
624 // Define the calibration objects the first time Update is called
625 // NB! This has to be done first even if the data is rejected by the time
626 // cut to make sure that the objects are available in Analyse
630 if (!fNLocalMaxima) fNLocalMaxima = new AliTPCCalPad("NLocalMaxima","NLocalMaxima");
631 if (!fMaxCharge) fMaxCharge = new AliTPCCalPad("MaxCharge","MaxCharge");
632 if (!fMeanCharge) fMeanCharge = new AliTPCCalPad("MeanCharge","MeanCharge");
633 if (!fNoThreshold) fNoThreshold = new AliTPCCalPad("NoThreshold","NoThreshold");
634 if (!fNTimeBins) fNTimeBins = new AliTPCCalPad("NTimeBins","NTimeBins");
635 if (!fNPads) fNPads = new AliTPCCalPad("NPads","NPads");
636 if (!fTimePosition) fTimePosition = new AliTPCCalPad("TimePosition","TimePosition");
637 if (!fOverThreshold10) fOverThreshold10 = new AliTPCCalPad("OverThreshold10","OverThreshold10");
638 if (!fOverThreshold20) fOverThreshold20 = new AliTPCCalPad("OverThreshold20","OverThreshold20");
639 if (!fOverThreshold30) fOverThreshold30 = new AliTPCCalPad("OverThreshold30","OverThreshold30");
640 if (!fHistQVsTimeSideA) {
641 fHistQVsTimeSideA = new TProfile("hQVsTimeSideA", "Q vs time (side A); Time [Timebin]; Q [ADC ch]", 100, 0, 1000);
642 fHistQVsTimeSideA->SetDirectory(0);
644 if (!fHistQVsTimeSideC) {
645 fHistQVsTimeSideC = new TProfile("hQVsTimeSideC", "Q vs time (side C); Time [Timebin]; Q [ADC ch]", 100, 0, 1000);
646 fHistQVsTimeSideC->SetDirectory(0);
648 if (!fHistQMaxVsTimeSideA) {
649 fHistQMaxVsTimeSideA = new TProfile("hQMaxVsTimeSideA", "Q_{MAX} vs time (side A); Time [Timebin]; Q_{MAX} [ADC ch]", 100, 0, 1000);
650 fHistQMaxVsTimeSideA->SetDirectory(0);
652 if (!fHistQMaxVsTimeSideC) {
653 fHistQMaxVsTimeSideC = new TProfile("hQMaxVsTimeSideC", "Q_{MAX} vs time (side C); Time [Timebin]; Q_{MAX} [ADC ch]", 100, 0, 1000);
654 fHistQMaxVsTimeSideC->SetDirectory(0);
656 } else { // DQM histograms and array
658 if (!fHistOccVsSector) {
659 fHistOccVsSector = new TProfile("hOccVsSector", "Occupancy vs sector; Sector; Occupancy", 72, 0, 72);
660 fHistOccVsSector->SetDirectory(0);
662 fHistOcc2dVsSector = new TProfile2D("hOcc2dVsSector", "Occupancy vs sector and patch; Sector; Patch", 72, 0, 36, 6, 0, 6);
663 fHistOcc2dVsSector->SetDirectory(0);
665 fHistQVsSector = new TProfile("hQVsSector", "Q vs sector; Sector; Q [ADC ch]", 72, 0, 72);
666 fHistQVsSector->SetDirectory(0);
668 fHistQmaxVsSector = new TProfile("hQmaxVsSector", "Qmax vs sector; Sector; Qmax [ADC ch]", 72, 0, 72);
669 fHistQmaxVsSector->SetDirectory(0);
671 fOccVec = new TArrayD(72);
672 for(Int_t i = 0; i < 72; i++)
673 fOccVec->GetArray()[i] = 0;
675 fOccMaxVec = new TArrayD(72);
676 const Double_t nTimeBins = fLastTimeBin - fFirstTimeBin +1;
677 for(Int_t i = 0; i < 72; i++)
679 if(i<36) // IROCs (5504 pads)
680 fOccMaxVec->GetArray()[i] = nTimeBins*5504;
681 else // OROCs (9984 pads)
682 fOccMaxVec->GetArray()[i] = nTimeBins*9984;
684 // 12 branches for each full sector
685 const Int_t nBranches = 36*12;
686 fOccVecFine = new TArrayD(nBranches);
687 for(Int_t i = 0; i < nBranches; i++)
688 fOccVecFine->GetArray()[i] = 0;
690 // Pads per patch same for all sectors
691 Int_t nPads0[6] = {1152, 1536, 1152, 1280, 1280, 1280};
692 Int_t nPads1[6] = {1152, 1664, 1152, 1280, 1280, 1280};
694 fOccMaxVecFine = new TArrayD(nBranches);
695 for(Int_t i = 0; i < nBranches; i++) {
697 const Int_t fullSector = Int_t(i/12);
698 Int_t branch = i - fullSector*12;
699 R__ASSERT(branch>=0 && branch<12);
701 const Int_t patch = Int_t(branch/2);
704 R__ASSERT(branch>=0 && branch<2);
706 fOccMaxVecFine->GetArray()[i] = nTimeBins*nPads0[patch];
707 else // OROCs (9984 pads)
708 fOccMaxVecFine->GetArray()[i] = nTimeBins*nPads1[patch];
712 // Make the arrays for expanding the data
718 // If Analyse has been previously called we need now to denormalize the data
719 // as more data is coming
721 if(fIsAnalysed == kTRUE && !fIsDQM) {
723 const Int_t nTimeBins = fLastTimeBin - fFirstTimeBin +1;
724 const Float_t denormalization = Float_t(fEventCounter * nTimeBins);
725 fNoThreshold->Multiply(denormalization);
727 fMeanCharge->Multiply(fNLocalMaxima);
728 fMaxCharge->Multiply(fNLocalMaxima);
729 fNTimeBins->Multiply(fNLocalMaxima);
730 fNPads->Multiply(fNLocalMaxima);
731 fTimePosition->Multiply(fNLocalMaxima);
732 fIsAnalysed = kFALSE;
738 if (iTimeBin<fFirstTimeBin) return 0;
739 if (iTimeBin>fLastTimeBin) return 0;
741 // if pedestal calibrations are loaded subtract pedestals
744 Float_t ped = fPedestal->GetCalROC(iSector)->GetValue(iRow, iPad);
745 // Don't use data from pads where pedestals are abnormally small or large
753 fOccVec->GetArray()[iSector] += 1.0;
754 // To change before committing
755 if(iPatch>=0 && iBranch>=0 && iPatch<=5 && iBranch <= 1)
756 fOccVecFine->GetArray()[(iSector%36)*12+iPatch*2+iBranch] += 1.0;
758 // In fNoThreshold we fill all data to estimate the ZS volume
759 Float_t count = fNoThreshold->GetCalROC(iSector)->GetValue(iRow, iPad);
760 fNoThreshold->GetCalROC(iSector)->SetValue(iRow, iPad,count+1);
763 // Require at least 3 ADC channels
767 // if noise calibrations are loaded require at least 3*sigmaNoise
770 Float_t noise = fNoise->GetCalROC(iSector)->GetValue(iRow, iPad);
772 if(signal < noise*3.0)
777 // This signal is ok and we store it in the cluster map
780 SetExpandDigit(iRow, iPad, iTimeBin, signal);
784 return 1; // signal was accepted
787 //_____________________________________________________________________
788 void AliTPCdataQA::FindLocalMaxima(const Int_t iSector)
791 // This method is called after the data from each sector has been
792 // exapanded into an array
793 // Loop over the signals and identify local maxima and fill the
794 // calibration objects with the information
797 Int_t nLocalMaxima = 0;
798 const Int_t maxTimeBin = fTimeBinsMax+4; // Used to step between neighboring pads
799 // Because we have tha pad-time data in a
802 for (Int_t iRow = 0; iRow < fRowsMax; iRow++) {
804 Float_t* allBins = fAllBins[iRow];
805 Int_t* sigBins = fAllSigBins[iRow];
806 const Int_t nSigBins = fAllNSigBins[iRow];
808 for (Int_t iSig = 0; iSig < nSigBins; iSig++) {
810 Int_t bin = sigBins[iSig];
811 Float_t *b = &allBins[bin];
814 // Now we check if this is a local maximum
819 // First check that the charge is bigger than the threshold
823 // Require at least one neighboring pad with signal
824 if (b[-maxTimeBin]+b[maxTimeBin]<=0) continue;
826 // Require at least one neighboring time bin with signal
827 if (b[-1]+b[1]<=0) continue;
830 // Check that this is a local maximum
831 // Note that the checking is done so that if 2 charges has the same
832 // qMax then only 1 cluster is generated
833 // (that is why there is BOTH > and >=)
835 if (b[-maxTimeBin] >= qMax) continue;
836 if (b[-1 ] >= qMax) continue;
837 if (b[+maxTimeBin] > qMax) continue;
838 if (b[+1 ] > qMax) continue;
839 if (b[-maxTimeBin-1] >= qMax) continue;
840 if (b[+maxTimeBin-1] >= qMax) continue;
841 if (b[+maxTimeBin+1] > qMax) continue;
842 if (b[-maxTimeBin+1] >= qMax) continue;
845 // Now we accept the local maximum and fill the calibration/data objects
849 Int_t iPad, iTimeBin;
850 GetPadAndTimeBin(bin, iPad, iTimeBin);
853 Float_t count = fNLocalMaxima->GetCalROC(iSector)->GetValue(iRow, iPad);
854 fNLocalMaxima->GetCalROC(iSector)->SetValue(iRow, iPad, count+1);
856 count = fTimePosition->GetCalROC(iSector)->GetValue(iRow, iPad);
857 fTimePosition->GetCalROC(iSector)->SetValue(iRow, iPad, count+iTimeBin);
859 Float_t charge = fMaxCharge->GetCalROC(iSector)->GetValue(iRow, iPad);
860 fMaxCharge->GetCalROC(iSector)->SetValue(iRow, iPad, charge + qMax);
863 count = fOverThreshold10->GetCalROC(iSector)->GetValue(iRow, iPad);
864 fOverThreshold10->GetCalROC(iSector)->SetValue(iRow, iPad, count+1);
867 count = fOverThreshold20->GetCalROC(iSector)->GetValue(iRow, iPad);
868 fOverThreshold20->GetCalROC(iSector)->SetValue(iRow, iPad, count+1);
871 count = fOverThreshold30->GetCalROC(iSector)->GetValue(iRow, iPad);
872 fOverThreshold30->GetCalROC(iSector)->SetValue(iRow, iPad, count+1);
877 // Calculate the total charge as the sum over the region:
885 // with qmax at the center C.
887 // The inner charge (i) we always add, but we only add the outer
888 // charge (o) if the neighboring inner bin (i) has a signal.
890 Int_t minP = 0, maxP = 0, minT = 0, maxT = 0;
892 for(Int_t i = -1; i<=1; i++) {
893 for(Int_t j = -1; j<=1; j++) {
898 Float_t charge1 = GetQ(b, i, j, maxTimeBin, minT, maxT, minP, maxP);
901 // see if the next neighbor is also above threshold
903 qTot += GetQ(b, 2*i, 2*j, maxTimeBin, minT, maxT, minP, maxP);
905 // we are in a diagonal corner
906 qTot += GetQ(b, i, 2*j, maxTimeBin, minT, maxT, minP, maxP);
907 qTot += GetQ(b, 2*i, j, maxTimeBin, minT, maxT, minP, maxP);
908 qTot += GetQ(b, 2*i, 2*j, maxTimeBin, minT, maxT, minP, maxP);
915 fHistQVsSector->Fill(iSector, qTot);
916 fHistQmaxVsSector->Fill(iSector, qMax);
918 Float_t charge = fMeanCharge->GetCalROC(iSector)->GetValue(iRow, iPad);
919 fMeanCharge->GetCalROC(iSector)->SetValue(iRow, iPad, charge + qTot);
921 Float_t count = fNTimeBins->GetCalROC(iSector)->GetValue(iRow, iPad);
922 fNTimeBins->GetCalROC(iSector)->SetValue(iRow, iPad, count + maxT-minT+1);
924 count = fNPads->GetCalROC(iSector)->GetValue(iRow, iPad);
925 fNPads->GetCalROC(iSector)->SetValue(iRow, iPad, count + maxP-minP+1);
927 if((iSector%36)<18) { // A side
928 fHistQVsTimeSideA->Fill(iTimeBin, qTot);
929 fHistQMaxVsTimeSideA->Fill(iTimeBin, qMax);
931 fHistQVsTimeSideC->Fill(iTimeBin, qTot);
932 fHistQMaxVsTimeSideC->Fill(iTimeBin, qMax);
935 } // end loop over signals
936 } // end loop over rows
938 fClusterCounter += nLocalMaxima;
941 //_____________________________________________________________________
942 void AliTPCdataQA::Analyse()
945 // Calculate calibration constants
948 AliInfo("Analyse called");
950 if(fIsDQM == kTRUE) {
952 AliInfo("DQM flas is set -> No 2d information to analyze");
956 if(fIsAnalysed == kTRUE) {
958 AliInfo("No new data since Analyse was called last time");
962 if(fEventCounter==0) {
964 AliInfo("EventCounter == 0, Cannot analyse");
968 Int_t nTimeBins = fLastTimeBin - fFirstTimeBin +1;
969 AliInfo(Form("EventCounter: %d , TimeBins: %d", fEventCounter, nTimeBins));
971 Float_t normalization = 1.0 / Float_t(fEventCounter * nTimeBins);
972 fNoThreshold->Multiply(normalization);
974 fMeanCharge->Divide(fNLocalMaxima);
975 fMaxCharge->Divide(fNLocalMaxima);
976 fNTimeBins->Divide(fNLocalMaxima);
977 fNPads->Divide(fNLocalMaxima);
978 fTimePosition->Divide(fNLocalMaxima);
984 //_____________________________________________________________________
985 void AliTPCdataQA::MakeTree(const char *fname) const {
987 // Export result to the tree -located in the file
988 // This file can be analyzed using AliTPCCalibViewer
990 AliTPCPreprocessorOnline preprocesor;
992 if (fNLocalMaxima) preprocesor.AddComponent(fNLocalMaxima);
993 if (fMaxCharge) preprocesor.AddComponent(fMaxCharge);
994 if (fMeanCharge) preprocesor.AddComponent(fMeanCharge);
995 if (fNoThreshold) preprocesor.AddComponent(fNoThreshold);
996 if (fNTimeBins) preprocesor.AddComponent(fNTimeBins);
997 if (fNPads) preprocesor.AddComponent(fNPads);
998 if (fTimePosition) preprocesor.AddComponent(fTimePosition);
999 if (fOverThreshold10) preprocesor.AddComponent(fOverThreshold10);
1000 if (fOverThreshold20) preprocesor.AddComponent(fOverThreshold20);
1001 if (fOverThreshold30) preprocesor.AddComponent(fOverThreshold30);
1003 preprocesor.DumpToFile(fname);
1007 //_____________________________________________________________________
1008 void AliTPCdataQA::MakeArrays(){
1010 // The arrays for expanding the raw data are defined and
1011 // som parameters are intialised
1013 AliTPCROC * roc = AliTPCROC::Instance();
1015 // To make the array big enough for all sectors we take
1016 // the dimensions from the outer row of an OROC (the last sector)
1018 fRowsMax = roc->GetNRows(roc->GetNSector()-1);
1019 fPadsMax = roc->GetNPads(roc->GetNSector()-1,fRowsMax-1);
1020 fTimeBinsMax = fLastTimeBin - fFirstTimeBin +1;
1023 // Since we have added 2 pads (TimeBins) before and after the real pads (TimeBins)
1024 // to make sure that we can always query the exanded table even when the
1025 // max is on the edge
1029 fAllBins = new Float_t*[fRowsMax];
1030 fAllSigBins = new Int_t*[fRowsMax];
1031 fAllNSigBins = new Int_t[fRowsMax];
1033 for (Int_t iRow = 0; iRow < fRowsMax; iRow++) {
1035 Int_t maxBin = (fTimeBinsMax+4)*(fPadsMax+4);
1036 fAllBins[iRow] = new Float_t[maxBin];
1037 memset(fAllBins[iRow],0,sizeof(Float_t)*maxBin); // set all values to 0
1038 fAllSigBins[iRow] = new Int_t[maxBin];
1039 fAllNSigBins[iRow] = 0;
1044 //_____________________________________________________________________
1045 void AliTPCdataQA::CleanArrays(){
1050 for (Int_t iRow = 0; iRow < fRowsMax; iRow++) {
1052 // To speed up the performance by a factor 2 on cosmic data (and
1053 // presumably pp data as well) where the ocupancy is low, the
1054 // memset is only called if there is more than 1000 signals for a
1055 // row (of the order 1% occupancy)
1056 if(fAllNSigBins[iRow]<1000) {
1058 Float_t* allBins = fAllBins[iRow];
1059 Int_t* sigBins = fAllSigBins[iRow];
1060 const Int_t nSignals = fAllNSigBins[iRow];
1061 for(Int_t i = 0; i < nSignals; i++)
1062 allBins[sigBins[i]]=0;
1065 Int_t maxBin = (fTimeBinsMax+4)*(fPadsMax+4);
1066 memset(fAllBins[iRow],0,sizeof(Float_t)*maxBin);
1069 fAllNSigBins[iRow]=0;
1073 //_____________________________________________________________________
1074 void AliTPCdataQA::GetPadAndTimeBin(Int_t bin, Int_t& iPad, Int_t& iTimeBin){
1076 // Return pad and timebin for a given bin
1079 // Int_t bin = iPad*(fTimeBinsMax+4)+iTimeBin;
1080 iTimeBin = bin%(fTimeBinsMax+4);
1081 iPad = (bin-iTimeBin)/(fTimeBinsMax+4);
1085 iTimeBin += fFirstTimeBin;
1087 R__ASSERT(iPad>=0 && iPad<=fPadsMax);
1088 R__ASSERT(iTimeBin>=fFirstTimeBin && iTimeBin<=fLastTimeBin);
1091 //_____________________________________________________________________
1092 void AliTPCdataQA::SetExpandDigit(const Int_t iRow, Int_t iPad,
1093 Int_t iTimeBin, const Float_t signal)
1098 R__ASSERT(iRow>=0 && iRow<fRowsMax);
1099 R__ASSERT(iPad>=0 && iPad<=fPadsMax);
1100 R__ASSERT(iTimeBin>=fFirstTimeBin && iTimeBin<=fLastTimeBin);
1102 iTimeBin -= fFirstTimeBin;
1106 Int_t bin = iPad*(fTimeBinsMax+4)+iTimeBin;
1107 fAllBins[iRow][bin] = signal;
1108 fAllSigBins[iRow][fAllNSigBins[iRow]] = bin;
1109 fAllNSigBins[iRow]++;
1112 //______________________________________________________________________________
1113 Float_t AliTPCdataQA::GetQ(const Float_t* adcArray, const Int_t time,
1114 const Int_t pad, const Int_t maxTimeBins,
1115 Int_t& timeMin, Int_t& timeMax,
1116 Int_t& padMin, Int_t& padMax) const
1119 // This methods return the charge in the bin time+pad*maxTimeBins
1120 // If the charge is above 0 it also updates the padMin, padMax, timeMin
1121 // and timeMax if necessary
1123 Float_t charge = adcArray[time + pad*maxTimeBins];
1125 timeMin = TMath::Min(time, timeMin); timeMax = TMath::Max(time, timeMax);
1126 padMin = TMath::Min(pad, padMin); padMax = TMath::Max(pad, padMax);
1131 //______________________________________________________________________________
1132 void AliTPCdataQA::Streamer(TBuffer &xRuub)
1134 // Automatic schema evolution was first used from revision 4
1136 // http://root.cern.ch/root/roottalk/roottalk02/3207.html
1138 UInt_t xRuus, xRuuc;
1139 if (xRuub.IsReading()) {
1140 Version_t xRuuv = xRuub.ReadVersion(&xRuus, &xRuuc);
1141 //we use the automatic algorithm for class version > 3
1143 AliTPCdataQA::Class()->ReadBuffer(xRuub, this, xRuuv, xRuus,
1147 TH1F::Streamer(xRuub);
1148 xRuub >> fFirstTimeBin;
1149 xRuub >> fLastTimeBin;
1152 xRuub >> fNLocalMaxima;
1153 xRuub >> fMaxCharge;
1154 xRuub >> fMeanCharge;
1155 xRuub >> fNoThreshold;
1156 xRuub >> fNTimeBins;
1158 xRuub >> fTimePosition;
1159 xRuub >> fEventCounter;
1160 xRuub >> fIsAnalysed;
1161 xRuub.CheckByteCount(xRuus, xRuuc, AliTPCdataQA::IsA());
1163 AliTPCdataQA::Class()->WriteBuffer(xRuub,this);
1167 //____________________________________________________________________________________________
1168 void AliTPCdataQA::FillOccupancyProfile()
1170 // This has to be filled at the end of the loop over data
1172 AliInfo("Method only meaningful for DQM");
1174 for(Int_t i = 0; i < 72; i++) {
1176 fOccVec->GetArray()[i] /= fOccMaxVec->GetArray()[i];
1177 fHistOccVsSector->Fill(i, fOccVec->GetArray()[i]);
1180 const Int_t nBranches = 36*12;
1181 for(Int_t i = 0; i < nBranches; i++) {
1183 fOccVecFine->GetArray()[i] /= fOccMaxVecFine->GetArray()[i];
1185 const Int_t fullSector = Int_t(i/12);
1187 Int_t branch = i - fullSector*12;
1188 const Int_t patch = Int_t(branch/2);
1192 fHistOcc2dVsSector->Fill(fullSector+0.5*branch+0.1, patch+0.5, fOccVecFine->GetArray()[i]);
1196 //____________________________________________________________________________________________
1197 void AliTPCdataQA::ResetProfiles()
1200 AliInfo("Method only meaningful for DQM");
1203 fHistQVsSector->Reset();
1204 if(fHistQmaxVsSector)
1205 fHistQmaxVsSector->Reset();
1206 if(fHistOccVsSector)
1207 fHistOccVsSector->Reset();
1208 if(fHistOcc2dVsSector)
1209 fHistOcc2dVsSector->Reset();
1212 for(Int_t i = 0; i < 72; i++)
1213 fOccVec->GetArray()[i] = 0.0;
1215 for(Int_t i = 0; i < 36*12; i++)
1216 fOccVecFine->GetArray()[i] = 0.0;