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 The code has been heavily modified so that now the RAW data is
23 "expanded" for each sector and stored in a big signal array. Then a
24 simple version of the code in AliTPCclustererMI is used to identify
25 the local maxima and these are then used for QA. This gives a better
26 estimate of the charge (both max and total) and also limits the
31 In Update the RAW signals >= 3 ADC channels are stored in the arrays.
34 Float_t** fAllBins 2d array [row][bin(pad, time)] ADC signal
35 Int_t** fAllSigBins 2d array [row][signal#] bin(with signal)
36 Int_t* fAllNSigBins; 1d array [row] Nsignals
38 This is done sector by sector.
40 When data from a new sector is encountered, the method
41 FindLocalMaxima is called on the data from the previous sector, and
42 the calibration/data objects are updated with the "cluster"
43 info. Finally the arrays are cleared.
45 The requirements for a local maxima is:
46 Charge in bin is >= 5 ADC channels.
47 Charge in bin is larger than all the 8 neighboring bins.
48 At least one of the two pad neighbors has a signal.
49 At least one of the two time neighbors has a signal.
51 Before accessing the data it is expected that the Analyse method is
52 called. This normalizes some of the data objects to per event or per
54 If more data is passed to the class after Analyse has been called
55 the normalization is reversed and Analyse has to be called again.
71 #include <TDirectory.h>
76 #include "AliRawReader.h"
77 #include "AliRawReaderRoot.h"
78 #include "AliRawReaderDate.h"
79 #include "AliTPCRawStream.h"
80 #include "AliTPCRawStreamV3.h"
81 #include "AliTPCCalROC.h"
82 #include "AliTPCROC.h"
83 #include "AliMathBase.h"
84 #include "TTreeStream.h"
85 #include "AliTPCRawStreamFast.h"
89 #include "AliTPCCalPad.h"
90 #include "AliTPCPreprocessorOnline.h"
93 #include "AliTPCdataQA.h"
95 ClassImp(AliTPCdataQA)
97 AliTPCdataQA::AliTPCdataQA() : /*FOLD00*/
115 fHistQVsTimeSideA(0),
116 fHistQVsTimeSideC(0),
117 fHistQMaxVsTimeSideA(0),
118 fHistQMaxVsTimeSideC(0),
129 // default constructor
133 //_____________________________________________________________________
134 AliTPCdataQA::AliTPCdataQA(AliRecoParam::EventSpecie_t es) :
152 fHistQVsTimeSideA(0),
153 fHistQVsTimeSideC(0),
154 fHistQMaxVsTimeSideA(0),
155 fHistQMaxVsTimeSideC(0),
165 // ctor creating the histogram
166 char * name = Form("TPCRAW_%s", AliRecoParam::GetEventSpecieName(es)) ;
167 TH1F(name, name,100,0,100) ;
170 //_____________________________________________________________________
171 AliTPCdataQA::AliTPCdataQA(const AliTPCdataQA &ped) : /*FOLD00*/
173 fFirstTimeBin(ped.GetFirstTimeBin()),
174 fLastTimeBin(ped.GetLastTimeBin()),
175 fAdcMin(ped.GetAdcMin()),
176 fAdcMax(ped.GetAdcMax()),
190 fHistQVsTimeSideA(0),
191 fHistQVsTimeSideC(0),
192 fHistQMaxVsTimeSideA(0),
193 fHistQMaxVsTimeSideC(0),
194 fEventCounter(ped.GetEventCounter()),
195 fIsAnalysed(ped.GetIsAnalysed()),
206 if(ped.GetNLocalMaxima())
207 fNLocalMaxima = new AliTPCCalPad(*ped.GetNLocalMaxima());
208 if(ped.GetMaxCharge())
209 fMaxCharge = new AliTPCCalPad(*ped.GetMaxCharge());
210 if(ped.GetMeanCharge())
211 fMeanCharge = new AliTPCCalPad(*ped.GetMeanCharge());
212 if(ped.GetNoThreshold())
213 fNoThreshold = new AliTPCCalPad(*ped.GetNoThreshold());
214 if(ped.GetNTimeBins())
215 fNTimeBins = new AliTPCCalPad(*ped.GetNTimeBins());
217 fNPads = new AliTPCCalPad(*ped.GetNPads());
218 if(ped.GetTimePosition())
219 fTimePosition = new AliTPCCalPad(*ped.GetTimePosition());
220 if(ped.GetOverThreshold10())
221 fOverThreshold10 = new AliTPCCalPad(*ped.GetOverThreshold10());
222 if(ped.GetOverThreshold20())
223 fOverThreshold20 = new AliTPCCalPad(*ped.GetOverThreshold20());
224 if(ped.GetOverThreshold30())
225 fOverThreshold30 = new AliTPCCalPad(*ped.GetOverThreshold30());
226 if(ped.GetHistQVsTimeSideA())
227 fHistQVsTimeSideA = new TProfile(*ped.GetHistQVsTimeSideA());
228 if(ped.GetHistQVsTimeSideC())
229 fHistQVsTimeSideC = new TProfile(*ped.GetHistQVsTimeSideC());
230 if(ped.GetHistQMaxVsTimeSideA())
231 fHistQMaxVsTimeSideA = new TProfile(*ped.GetHistQMaxVsTimeSideA());
232 if(ped.GetHistQMaxVsTimeSideC())
233 fHistQMaxVsTimeSideC = new TProfile(*ped.GetHistQMaxVsTimeSideC());
236 //_____________________________________________________________________
237 AliTPCdataQA::AliTPCdataQA(const TMap *config) : /*FOLD00*/
238 TH1F("TPCRAW","TPCRAW",100,0,100),
256 fHistQVsTimeSideA(0),
257 fHistQVsTimeSideC(0),
258 fHistQMaxVsTimeSideA(0),
259 fHistQMaxVsTimeSideC(0),
270 // default constructor
272 if (config->GetValue("FirstTimeBin")) fFirstTimeBin = ((TObjString*)config->GetValue("FirstTimeBin"))->GetString().Atoi();
273 if (config->GetValue("LastTimeBin")) fLastTimeBin = ((TObjString*)config->GetValue("LastTimeBin"))->GetString().Atoi();
274 if (config->GetValue("AdcMin")) fAdcMin = ((TObjString*)config->GetValue("AdcMin"))->GetString().Atoi();
275 if (config->GetValue("AdcMax")) fAdcMax = ((TObjString*)config->GetValue("AdcMax"))->GetString().Atoi();
278 //_____________________________________________________________________
279 AliTPCdataQA& AliTPCdataQA::operator = (const AliTPCdataQA &source)
282 // assignment operator
284 if (&source == this) return *this;
285 new (this) AliTPCdataQA(source);
291 //_____________________________________________________________________
292 AliTPCdataQA::~AliTPCdataQA() /*FOLD00*/
298 // do not delete fMapping, because we do not own it.
299 // do not delete fMapping, because we do not own it.
300 // do not delete fNoise and fPedestal, because we do not own them.
302 delete fNLocalMaxima;
308 delete fTimePosition;
309 delete fOverThreshold10;
310 delete fOverThreshold20;
311 delete fOverThreshold30;
312 delete fHistQVsTimeSideA;
313 delete fHistQVsTimeSideC;
314 delete fHistQMaxVsTimeSideA;
315 delete fHistQMaxVsTimeSideC;
317 for (Int_t iRow = 0; iRow < fRowsMax; iRow++) {
318 delete [] fAllBins[iRow];
319 delete [] fAllSigBins[iRow];
322 delete [] fAllSigBins;
323 delete [] fAllNSigBins;
325 //_____________________________________________________________________
326 Bool_t AliTPCdataQA::ProcessEvent(AliTPCRawStreamV3 *rawStreamV3)
329 // Event Processing loop - AliTPCRawStreamV3
331 Bool_t withInput = kFALSE;
333 Int_t lastSector = -1;
335 while ( rawStreamV3->NextDDL() ){
336 while ( rawStreamV3->NextChannel() ){
337 Int_t iSector = rawStreamV3->GetSector(); // current sector
338 Int_t iRow = rawStreamV3->GetRow(); // current row
339 Int_t iPad = rawStreamV3->GetPad(); // current pad
340 if (iRow<0 || iPad<0) continue;
341 // Call local maxima finder if the data is in a new sector
342 if(iSector != lastSector) {
345 FindLocalMaxima(lastSector);
348 lastSector = iSector;
352 while ( rawStreamV3->NextBunch() ){
353 Int_t startTbin = (Int_t)rawStreamV3->GetStartTimeBin();
354 Int_t bunchlength = (Int_t)rawStreamV3->GetBunchLength();
355 const UShort_t *sig = rawStreamV3->GetSignals();
357 for (Int_t iTimeBin = 0; iTimeBin<bunchlength; iTimeBin++){
358 Float_t signal=(Float_t)sig[iTimeBin];
359 nSignals += Update(iSector,iRow,iPad,startTbin--,signal);
366 if (lastSector>=0&&nSignals>0)
367 FindLocalMaxima(lastSector);
372 //_____________________________________________________________________
373 Bool_t AliTPCdataQA::ProcessEvent(AliRawReader *rawReader)
376 // Event processing loop - AliRawReader
378 AliTPCRawStreamV3 *rawStreamV3 = new AliTPCRawStreamV3(rawReader, (AliAltroMapping**)fMapping);
379 Bool_t res=ProcessEvent(rawStreamV3);
382 fEventCounter++; // only increment event counter if there is TPC data
386 //_____________________________________________________________________
387 Bool_t AliTPCdataQA::ProcessEventFast(AliTPCRawStreamFast *rawStreamFast)
390 // Event Processing loop - AliTPCRawStream
392 Bool_t withInput = kFALSE;
394 Int_t lastSector = -1;
396 while ( rawStreamFast->NextDDL() ){
397 while ( rawStreamFast->NextChannel() ){
399 Int_t iSector = rawStreamFast->GetSector(); // current sector
400 Int_t iRow = rawStreamFast->GetRow(); // current row
401 Int_t iPad = rawStreamFast->GetPad(); // current pad
402 // Call local maxima finder if the data is in a new sector
403 if(iSector != lastSector) {
406 FindLocalMaxima(lastSector);
409 lastSector = iSector;
413 while ( rawStreamFast->NextBunch() ){
414 Int_t startTbin = (Int_t)rawStreamFast->GetStartTimeBin();
415 Int_t endTbin = (Int_t)rawStreamFast->GetEndTimeBin();
417 for (Int_t iTimeBin = startTbin; iTimeBin < endTbin; iTimeBin++){
418 Float_t signal = rawStreamFast->GetSignals()[iTimeBin-startTbin];
419 nSignals += Update(iSector,iRow,iPad,iTimeBin+1,signal);
428 //_____________________________________________________________________
429 Bool_t AliTPCdataQA::ProcessEventFast(AliRawReader *rawReader)
432 // Event processing loop - AliRawReader
434 AliTPCRawStreamFast *rawStreamFast = new AliTPCRawStreamFast(rawReader, (AliAltroMapping**)fMapping);
435 Bool_t res=ProcessEventFast(rawStreamFast);
437 fEventCounter++; // only increment event counter if there is TPC data
438 // otherwise Analyse (called in QA) fails
440 delete rawStreamFast;
444 //_____________________________________________________________________
445 Bool_t AliTPCdataQA::ProcessEvent(AliTPCRawStream *rawStream)
448 // Event Processing loop - AliTPCRawStream
451 Bool_t withInput = kFALSE;
453 Int_t lastSector = -1;
455 while (rawStream->Next()) {
457 Int_t iSector = rawStream->GetSector(); // current ROC
458 Int_t iRow = rawStream->GetRow(); // current row
459 Int_t iPad = rawStream->GetPad(); // current pad
460 Int_t iTimeBin = rawStream->GetTime(); // current time bin
461 Float_t signal = rawStream->GetSignal(); // current ADC signal
463 // Call local maxima finder if the data is in a new sector
464 if(iSector != lastSector) {
467 FindLocalMaxima(lastSector);
470 lastSector = iSector;
474 // Sometimes iRow==-1 if there is problems to read the data
476 nSignals += Update(iSector,iRow,iPad,iTimeBin,signal);
481 if (lastSector>=0&&nSignals>0)
482 FindLocalMaxima(lastSector);
488 //_____________________________________________________________________
489 Bool_t AliTPCdataQA::ProcessEventOld(AliRawReader *rawReader)
492 // Event processing loop - AliRawReader
495 // if fMapping is NULL the rawstream will crate its own mapping
496 AliTPCRawStream rawStream(rawReader, (AliAltroMapping**)fMapping);
497 rawReader->Select("TPC");
498 Bool_t res = ProcessEvent(&rawStream);
501 fEventCounter++; // only increment event counter if there is TPC data
502 // otherwise Analyse (called in QA) fails
507 //_____________________________________________________________________
508 Bool_t AliTPCdataQA::ProcessEvent(eventHeaderStruct *event)
511 // process date event
514 AliRawReader *rawReader = new AliRawReaderDate((void*)event);
515 Bool_t result=ProcessEvent(rawReader);
522 //_____________________________________________________________________
523 void AliTPCdataQA::DumpToFile(const Char_t *filename, const Char_t *dir, Bool_t append) /*FOLD00*/
526 // Write class to file
537 TDirectory *backup = gDirectory;
538 TFile f(filename,option.Data());
540 if ( !sDir.IsNull() ){
541 f.mkdir(sDir.Data());
547 if ( backup ) backup->cd();
551 //_____________________________________________________________________
552 Int_t AliTPCdataQA::Update(const Int_t iSector, /*FOLD00*/
555 const Int_t iTimeBin,
559 // Signal filling method
563 // Define the calibration objects the first time Update is called
564 // NB! This has to be done first even if the data is rejected by the time
565 // cut to make sure that the objects are available in Analyse
567 if (!fNLocalMaxima) fNLocalMaxima = new AliTPCCalPad("NLocalMaxima","NLocalMaxima");
568 if (!fMaxCharge) fMaxCharge = new AliTPCCalPad("MaxCharge","MaxCharge");
569 if (!fMeanCharge) fMeanCharge = new AliTPCCalPad("MeanCharge","MeanCharge");
570 if (!fNoThreshold) fNoThreshold = new AliTPCCalPad("NoThreshold","NoThreshold");
571 if (!fNTimeBins) fNTimeBins = new AliTPCCalPad("NTimeBins","NTimeBins");
572 if (!fNPads) fNPads = new AliTPCCalPad("NPads","NPads");
573 if (!fTimePosition) fTimePosition = new AliTPCCalPad("TimePosition","TimePosition");
574 if (!fOverThreshold10) fOverThreshold10 = new AliTPCCalPad("OverThreshold10","OverThreshold10");
575 if (!fOverThreshold20) fOverThreshold20 = new AliTPCCalPad("OverThreshold20","OverThreshold20");
576 if (!fOverThreshold30) fOverThreshold30 = new AliTPCCalPad("OverThreshold30","OverThreshold30");
577 if (!fHistQVsTimeSideA)
578 fHistQVsTimeSideA = new TProfile("hQVsTimeSideA", "Q vs time (side A); Time [Timebin]; Q [ADC ch]", 100, 0, 1000);
579 if (!fHistQVsTimeSideC)
580 fHistQVsTimeSideC = new TProfile("hQVsTimeSideC", "Q vs time (side C); Time [Timebin]; Q [ADC ch]", 100, 0, 1000);
581 if (!fHistQMaxVsTimeSideA)
582 fHistQMaxVsTimeSideA = new TProfile("hQMaxVsTimeSideA", "Q_{MAX} vs time (side A); Time [Timebin]; Q_{MAX} [ADC ch]", 100, 0, 1000);
583 if (!fHistQMaxVsTimeSideC)
584 fHistQMaxVsTimeSideC = new TProfile("hQMaxVsTimeSideC", "Q_{MAX} vs time (side C); Time [Timebin]; Q_{MAX} [ADC ch]", 100, 0, 1000);
586 // Make the arrays for expanding the data
592 // If Analyse has been previously called we need now to denormalize the data
593 // as more data is coming
595 if(fIsAnalysed == kTRUE) {
597 const Int_t nTimeBins = fLastTimeBin - fFirstTimeBin +1;
598 const Float_t denormalization = Float_t(fEventCounter * nTimeBins);
599 fNoThreshold->Multiply(denormalization);
601 fMeanCharge->Multiply(fNLocalMaxima);
602 fMaxCharge->Multiply(fNLocalMaxima);
603 fNTimeBins->Multiply(fNLocalMaxima);
604 fNPads->Multiply(fNLocalMaxima);
605 fTimePosition->Multiply(fNLocalMaxima);
606 fIsAnalysed = kFALSE;
612 if (iTimeBin<fFirstTimeBin) return 0;
613 if (iTimeBin>fLastTimeBin) return 0;
615 // if pedestal calibrations are loaded subtract pedestals
618 Float_t ped = fPedestal->GetCalROC(iSector)->GetValue(iRow, iPad);
619 // Don't use data from pads where pedestals are abnormally small or large
625 // In fNoThreshold we fill all data to estimate the ZS volume
626 Float_t count = fNoThreshold->GetCalROC(iSector)->GetValue(iRow, iPad);
627 fNoThreshold->GetCalROC(iSector)->SetValue(iRow, iPad,count+1);
629 // Require at least 3 ADC channels
633 // if noise calibrations are loaded require at least 3*sigmaNoise
636 Float_t noise = fNoise->GetCalROC(iSector)->GetValue(iRow, iPad);
638 if(signal < noise*3.0)
643 // This signal is ok and we store it in the cluster map
646 SetExpandDigit(iRow, iPad, iTimeBin, signal);
648 return 1; // signal was accepted
651 //_____________________________________________________________________
652 void AliTPCdataQA::FindLocalMaxima(const Int_t iSector)
655 // This method is called after the data from each sector has been
656 // exapanded into an array
657 // Loop over the signals and identify local maxima and fill the
658 // calibration objects with the information
661 Int_t nLocalMaxima = 0;
662 const Int_t maxTimeBin = fTimeBinsMax+4; // Used to step between neighboring pads
663 // Because we have tha pad-time data in a
666 for (Int_t iRow = 0; iRow < fRowsMax; iRow++) {
668 Float_t* allBins = fAllBins[iRow];
669 Int_t* sigBins = fAllSigBins[iRow];
670 const Int_t nSigBins = fAllNSigBins[iRow];
672 for (Int_t iSig = 0; iSig < nSigBins; iSig++) {
674 Int_t bin = sigBins[iSig];
675 Float_t *b = &allBins[bin];
678 // Now we check if this is a local maximum
683 // First check that the charge is bigger than the threshold
687 // Require at least one neighboring pad with signal
688 if (b[-maxTimeBin]+b[maxTimeBin]<=0) continue;
690 // Require at least one neighboring time bin with signal
691 if (b[-1]+b[1]<=0) continue;
694 // Check that this is a local maximum
695 // Note that the checking is done so that if 2 charges has the same
696 // qMax then only 1 cluster is generated
697 // (that is why there is BOTH > and >=)
699 if (b[-maxTimeBin] >= qMax) continue;
700 if (b[-1 ] >= qMax) continue;
701 if (b[+maxTimeBin] > qMax) continue;
702 if (b[+1 ] > qMax) continue;
703 if (b[-maxTimeBin-1] >= qMax) continue;
704 if (b[+maxTimeBin-1] >= qMax) continue;
705 if (b[+maxTimeBin+1] > qMax) continue;
706 if (b[-maxTimeBin+1] >= qMax) continue;
709 // Now we accept the local maximum and fill the calibration/data objects
713 Int_t iPad, iTimeBin;
714 GetPadAndTimeBin(bin, iPad, iTimeBin);
716 Float_t count = fNLocalMaxima->GetCalROC(iSector)->GetValue(iRow, iPad);
717 fNLocalMaxima->GetCalROC(iSector)->SetValue(iRow, iPad, count+1);
719 count = fTimePosition->GetCalROC(iSector)->GetValue(iRow, iPad);
720 fTimePosition->GetCalROC(iSector)->SetValue(iRow, iPad, count+iTimeBin);
722 Float_t charge = fMaxCharge->GetCalROC(iSector)->GetValue(iRow, iPad);
723 fMaxCharge->GetCalROC(iSector)->SetValue(iRow, iPad, charge + qMax);
726 count = fOverThreshold10->GetCalROC(iSector)->GetValue(iRow, iPad);
727 fOverThreshold10->GetCalROC(iSector)->SetValue(iRow, iPad, count+1);
730 count = fOverThreshold20->GetCalROC(iSector)->GetValue(iRow, iPad);
731 fOverThreshold20->GetCalROC(iSector)->SetValue(iRow, iPad, count+1);
734 count = fOverThreshold30->GetCalROC(iSector)->GetValue(iRow, iPad);
735 fOverThreshold30->GetCalROC(iSector)->SetValue(iRow, iPad, count+1);
739 // Calculate the total charge as the sum over the region:
747 // with qmax at the center C.
749 // The inner charge (i) we always add, but we only add the outer
750 // charge (o) if the neighboring inner bin (i) has a signal.
752 Int_t minP = 0, maxP = 0, minT = 0, maxT = 0;
754 for(Int_t i = -1; i<=1; i++) {
755 for(Int_t j = -1; j<=1; j++) {
760 Float_t charge1 = GetQ(b, i, j, maxTimeBin, minT, maxT, minP, maxP);
763 // see if the next neighbor is also above threshold
765 qTot += GetQ(b, 2*i, 2*j, maxTimeBin, minT, maxT, minP, maxP);
767 // we are in a diagonal corner
768 qTot += GetQ(b, i, 2*j, maxTimeBin, minT, maxT, minP, maxP);
769 qTot += GetQ(b, 2*i, j, maxTimeBin, minT, maxT, minP, maxP);
770 qTot += GetQ(b, 2*i, 2*j, maxTimeBin, minT, maxT, minP, maxP);
776 charge = fMeanCharge->GetCalROC(iSector)->GetValue(iRow, iPad);
777 fMeanCharge->GetCalROC(iSector)->SetValue(iRow, iPad, charge + qTot);
779 count = fNTimeBins->GetCalROC(iSector)->GetValue(iRow, iPad);
780 fNTimeBins->GetCalROC(iSector)->SetValue(iRow, iPad, count + maxT-minT+1);
782 count = fNPads->GetCalROC(iSector)->GetValue(iRow, iPad);
783 fNPads->GetCalROC(iSector)->SetValue(iRow, iPad, count + maxP-minP+1);
785 if((iSector%36)<18) { // A side
786 fHistQVsTimeSideA->Fill(iTimeBin, qTot);
787 fHistQMaxVsTimeSideA->Fill(iTimeBin, qMax);
789 fHistQVsTimeSideC->Fill(iTimeBin, qTot);
790 fHistQMaxVsTimeSideC->Fill(iTimeBin, qMax);
792 } // end loop over signals
793 } // end loop over rows
795 // cout << "Number of local maximas found: " << nLocalMaxima << endl;
798 //_____________________________________________________________________
799 void AliTPCdataQA::Analyse()
802 // Calculate calibration constants
805 cout << "Analyse called" << endl;
807 if(fIsAnalysed == kTRUE) {
809 cout << "No new data since Analyse was called last time" << endl;
813 if(fEventCounter==0) {
815 cout << "EventCounter == 0, Cannot analyse" << endl;
819 Int_t nTimeBins = fLastTimeBin - fFirstTimeBin +1;
820 cout << "EventCounter: " << fEventCounter << endl
821 << "TimeBins: " << nTimeBins << endl;
823 Float_t normalization = 1.0 / Float_t(fEventCounter * nTimeBins);
824 fNoThreshold->Multiply(normalization);
826 fMeanCharge->Divide(fNLocalMaxima);
827 fMaxCharge->Divide(fNLocalMaxima);
828 fNTimeBins->Divide(fNLocalMaxima);
829 fNPads->Divide(fNLocalMaxima);
830 fTimePosition->Divide(fNLocalMaxima);
836 //_____________________________________________________________________
837 void AliTPCdataQA::MakeTree(const char *fname){
839 // Export result to the tree -located in the file
840 // This file can be analyzed using AliTPCCalibViewer
842 AliTPCPreprocessorOnline preprocesor;
844 if (fNLocalMaxima) preprocesor.AddComponent(fNLocalMaxima);
845 if (fMaxCharge) preprocesor.AddComponent(fMaxCharge);
846 if (fMeanCharge) preprocesor.AddComponent(fMeanCharge);
847 if (fNoThreshold) preprocesor.AddComponent(fNoThreshold);
848 if (fNTimeBins) preprocesor.AddComponent(fNTimeBins);
849 if (fNPads) preprocesor.AddComponent(fNPads);
850 if (fTimePosition) preprocesor.AddComponent(fTimePosition);
851 if (fOverThreshold10) preprocesor.AddComponent(fOverThreshold10);
852 if (fOverThreshold20) preprocesor.AddComponent(fOverThreshold20);
853 if (fOverThreshold30) preprocesor.AddComponent(fOverThreshold30);
855 preprocesor.DumpToFile(fname);
859 //_____________________________________________________________________
860 void AliTPCdataQA::MakeArrays(){
862 // The arrays for expanding the raw data are defined and
863 // som parameters are intialised
865 AliTPCROC * roc = AliTPCROC::Instance();
867 // To make the array big enough for all sectors we take
868 // the dimensions from the outer row of an OROC (the last sector)
870 fRowsMax = roc->GetNRows(roc->GetNSector()-1);
871 fPadsMax = roc->GetNPads(roc->GetNSector()-1,fRowsMax-1);
872 fTimeBinsMax = fLastTimeBin - fFirstTimeBin +1;
875 // Since we have added 2 pads (TimeBins) before and after the real pads (TimeBins)
876 // to make sure that we can always query the exanded table even when the
877 // max is on the edge
881 fAllBins = new Float_t*[fRowsMax];
882 fAllSigBins = new Int_t*[fRowsMax];
883 fAllNSigBins = new Int_t[fRowsMax];
885 for (Int_t iRow = 0; iRow < fRowsMax; iRow++) {
887 Int_t maxBin = (fTimeBinsMax+4)*(fPadsMax+4);
888 fAllBins[iRow] = new Float_t[maxBin];
889 memset(fAllBins[iRow],0,sizeof(Float_t)*maxBin); // set all values to 0
890 fAllSigBins[iRow] = new Int_t[maxBin];
891 fAllNSigBins[iRow] = 0;
896 //_____________________________________________________________________
897 void AliTPCdataQA::CleanArrays(){
902 for (Int_t iRow = 0; iRow < fRowsMax; iRow++) {
904 // To speed up the performance by a factor 2 on cosmic data (and
905 // presumably pp data as well) where the ocupancy is low, the
906 // memset is only called if there is more than 1000 signals for a
907 // row (of the order 1% occupancy)
908 if(fAllNSigBins[iRow]<1000) {
910 Float_t* allBins = fAllBins[iRow];
911 Int_t* sigBins = fAllSigBins[iRow];
912 const Int_t nSignals = fAllNSigBins[iRow];
913 for(Int_t i = 0; i < nSignals; i++)
914 allBins[sigBins[i]]=0;
917 Int_t maxBin = (fTimeBinsMax+4)*(fPadsMax+4);
918 memset(fAllBins[iRow],0,sizeof(Float_t)*maxBin);
921 fAllNSigBins[iRow]=0;
925 //_____________________________________________________________________
926 void AliTPCdataQA::GetPadAndTimeBin(Int_t bin, Int_t& iPad, Int_t& iTimeBin){
928 // Return pad and timebin for a given bin
931 // Int_t bin = iPad*(fTimeBinsMax+4)+iTimeBin;
932 iTimeBin = bin%(fTimeBinsMax+4);
933 iPad = (bin-iTimeBin)/(fTimeBinsMax+4);
937 iTimeBin += fFirstTimeBin;
939 R__ASSERT(iPad>=0 && iPad<=fPadsMax);
940 R__ASSERT(iTimeBin>=fFirstTimeBin && iTimeBin<=fLastTimeBin);
943 //_____________________________________________________________________
944 void AliTPCdataQA::SetExpandDigit(const Int_t iRow, Int_t iPad,
945 Int_t iTimeBin, const Float_t signal)
950 R__ASSERT(iRow>=0 && iRow<fRowsMax);
951 R__ASSERT(iPad>=0 && iPad<=fPadsMax);
952 R__ASSERT(iTimeBin>=fFirstTimeBin && iTimeBin<=fLastTimeBin);
954 iTimeBin -= fFirstTimeBin;
958 Int_t bin = iPad*(fTimeBinsMax+4)+iTimeBin;
959 fAllBins[iRow][bin] = signal;
960 fAllSigBins[iRow][fAllNSigBins[iRow]] = bin;
961 fAllNSigBins[iRow]++;
964 Float_t AliTPCdataQA::GetQ(const Float_t* adcArray, const Int_t time,
965 const Int_t pad, const Int_t maxTimeBins,
966 Int_t& timeMin, Int_t& timeMax,
967 Int_t& padMin, Int_t& padMax)
970 // This methods return the charge in the bin time+pad*maxTimeBins
971 // If the charge is above 0 it also updates the padMin, padMax, timeMin
972 // and timeMax if necessary
974 Float_t charge = adcArray[time + pad*maxTimeBins];
976 timeMin = TMath::Min(time, timeMin); timeMax = TMath::Max(time, timeMax);
977 padMin = TMath::Min(pad, padMin); padMax = TMath::Max(pad, padMax);
982 //______________________________________________________________________________
983 void AliTPCdataQA::Streamer(TBuffer &R__b)
985 // Automatic schema evolution was first used from revision 4
987 // http://root.cern.ch/root/roottalk/roottalk02/3207.html
990 if (R__b.IsReading()) {
991 Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
992 //we use the automatic algorithm for class version > 3
994 AliTPCdataQA::Class()->ReadBuffer(R__b, this, R__v, R__s,
998 TH1F::Streamer(R__b);
999 R__b >> fFirstTimeBin;
1000 R__b >> fLastTimeBin;
1003 R__b >> fNLocalMaxima;
1005 R__b >> fMeanCharge;
1006 R__b >> fNoThreshold;
1009 R__b >> fTimePosition;
1010 R__b >> fEventCounter;
1011 R__b >> fIsAnalysed;
1012 R__b.CheckByteCount(R__s, R__c, AliTPCdataQA::IsA());
1014 AliTPCdataQA::Class()->WriteBuffer(R__b,this);