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 fHistQVsTimeSideA->SetDirectory(0);
230 if(ped.GetHistQVsTimeSideC()) {
231 fHistQVsTimeSideC = new TProfile(*ped.GetHistQVsTimeSideC());
232 fHistQVsTimeSideC->SetDirectory(0);
234 if(ped.GetHistQMaxVsTimeSideA()) {
235 fHistQMaxVsTimeSideA = new TProfile(*ped.GetHistQMaxVsTimeSideA());
236 fHistQMaxVsTimeSideA->SetDirectory(0);
238 if(ped.GetHistQMaxVsTimeSideC()) {
239 fHistQMaxVsTimeSideC = new TProfile(*ped.GetHistQMaxVsTimeSideC());
240 fHistQMaxVsTimeSideC->SetDirectory(0);
244 //_____________________________________________________________________
245 AliTPCdataQA::AliTPCdataQA(const TMap *config) : /*FOLD00*/
246 TH1F("TPCRAW","TPCRAW",100,0,100),
264 fHistQVsTimeSideA(0),
265 fHistQVsTimeSideC(0),
266 fHistQMaxVsTimeSideA(0),
267 fHistQMaxVsTimeSideC(0),
278 // default constructor
280 if (config->GetValue("FirstTimeBin")) fFirstTimeBin = ((TObjString*)config->GetValue("FirstTimeBin"))->GetString().Atoi();
281 if (config->GetValue("LastTimeBin")) fLastTimeBin = ((TObjString*)config->GetValue("LastTimeBin"))->GetString().Atoi();
282 if (config->GetValue("AdcMin")) fAdcMin = ((TObjString*)config->GetValue("AdcMin"))->GetString().Atoi();
283 if (config->GetValue("AdcMax")) fAdcMax = ((TObjString*)config->GetValue("AdcMax"))->GetString().Atoi();
286 //_____________________________________________________________________
287 AliTPCdataQA& AliTPCdataQA::operator = (const AliTPCdataQA &source)
290 // assignment operator
292 if (&source == this) return *this;
293 new (this) AliTPCdataQA(source);
299 //_____________________________________________________________________
300 AliTPCdataQA::~AliTPCdataQA() /*FOLD00*/
306 // do not delete fMapping, because we do not own it.
307 // do not delete fMapping, because we do not own it.
308 // do not delete fNoise and fPedestal, because we do not own them.
310 delete fNLocalMaxima;
316 delete fTimePosition;
317 delete fOverThreshold10;
318 delete fOverThreshold20;
319 delete fOverThreshold30;
320 delete fHistQVsTimeSideA;
321 delete fHistQVsTimeSideC;
322 delete fHistQMaxVsTimeSideA;
323 delete fHistQMaxVsTimeSideC;
325 for (Int_t iRow = 0; iRow < fRowsMax; iRow++) {
326 delete [] fAllBins[iRow];
327 delete [] fAllSigBins[iRow];
330 delete [] fAllSigBins;
331 delete [] fAllNSigBins;
333 //_____________________________________________________________________
334 Bool_t AliTPCdataQA::ProcessEvent(AliTPCRawStreamV3 *rawStreamV3)
337 // Event Processing loop - AliTPCRawStreamV3
339 Bool_t withInput = kFALSE;
341 Int_t lastSector = -1;
343 while ( rawStreamV3->NextDDL() ){
344 while ( rawStreamV3->NextChannel() ){
345 Int_t iSector = rawStreamV3->GetSector(); // current sector
346 Int_t iRow = rawStreamV3->GetRow(); // current row
347 Int_t iPad = rawStreamV3->GetPad(); // current pad
348 if (iRow<0 || iPad<0) continue;
349 // Call local maxima finder if the data is in a new sector
350 if(iSector != lastSector) {
353 FindLocalMaxima(lastSector);
356 lastSector = iSector;
360 while ( rawStreamV3->NextBunch() ){
361 Int_t startTbin = (Int_t)rawStreamV3->GetStartTimeBin();
362 Int_t bunchlength = (Int_t)rawStreamV3->GetBunchLength();
363 const UShort_t *sig = rawStreamV3->GetSignals();
365 for (Int_t iTimeBin = 0; iTimeBin<bunchlength; iTimeBin++){
366 Float_t signal=(Float_t)sig[iTimeBin];
367 nSignals += Update(iSector,iRow,iPad,startTbin--,signal);
374 if (lastSector>=0&&nSignals>0)
375 FindLocalMaxima(lastSector);
380 //_____________________________________________________________________
381 Bool_t AliTPCdataQA::ProcessEvent(AliRawReader *rawReader)
384 // Event processing loop - AliRawReader
386 AliTPCRawStreamV3 rawStreamV3(rawReader, (AliAltroMapping**)fMapping);
387 Bool_t res=ProcessEvent(&rawStreamV3);
389 fEventCounter++; // only increment event counter if there is TPC data
393 //_____________________________________________________________________
394 Bool_t AliTPCdataQA::ProcessEventFast(AliTPCRawStreamFast *rawStreamFast)
397 // Event Processing loop - AliTPCRawStream
399 Bool_t withInput = kFALSE;
401 Int_t lastSector = -1;
403 while ( rawStreamFast->NextDDL() ){
404 while ( rawStreamFast->NextChannel() ){
406 Int_t iSector = rawStreamFast->GetSector(); // current sector
407 Int_t iRow = rawStreamFast->GetRow(); // current row
408 Int_t iPad = rawStreamFast->GetPad(); // current pad
409 // Call local maxima finder if the data is in a new sector
410 if(iSector != lastSector) {
413 FindLocalMaxima(lastSector);
416 lastSector = iSector;
420 while ( rawStreamFast->NextBunch() ){
421 Int_t startTbin = (Int_t)rawStreamFast->GetStartTimeBin();
422 Int_t endTbin = (Int_t)rawStreamFast->GetEndTimeBin();
424 for (Int_t iTimeBin = startTbin; iTimeBin < endTbin; iTimeBin++){
425 Float_t signal = rawStreamFast->GetSignals()[iTimeBin-startTbin];
426 nSignals += Update(iSector,iRow,iPad,iTimeBin+1,signal);
435 //_____________________________________________________________________
436 Bool_t AliTPCdataQA::ProcessEventFast(AliRawReader *rawReader)
439 // Event processing loop - AliRawReader
441 AliTPCRawStreamFast rawStreamFast(rawReader, (AliAltroMapping**)fMapping);
442 Bool_t res=ProcessEventFast(&rawStreamFast);
444 fEventCounter++; // only increment event counter if there is TPC data
445 // otherwise Analyse (called in QA) fails
450 //_____________________________________________________________________
451 Bool_t AliTPCdataQA::ProcessEvent(AliTPCRawStream *rawStream)
454 // Event Processing loop - AliTPCRawStream
457 Bool_t withInput = kFALSE;
459 Int_t lastSector = -1;
461 while (rawStream->Next()) {
463 Int_t iSector = rawStream->GetSector(); // current ROC
464 Int_t iRow = rawStream->GetRow(); // current row
465 Int_t iPad = rawStream->GetPad(); // current pad
466 Int_t iTimeBin = rawStream->GetTime(); // current time bin
467 Float_t signal = rawStream->GetSignal(); // current ADC signal
469 // Call local maxima finder if the data is in a new sector
470 if(iSector != lastSector) {
473 FindLocalMaxima(lastSector);
476 lastSector = iSector;
480 // Sometimes iRow==-1 if there is problems to read the data
482 nSignals += Update(iSector,iRow,iPad,iTimeBin,signal);
487 if (lastSector>=0&&nSignals>0)
488 FindLocalMaxima(lastSector);
494 //_____________________________________________________________________
495 Bool_t AliTPCdataQA::ProcessEventOld(AliRawReader *rawReader)
498 // Event processing loop - AliRawReader
501 // if fMapping is NULL the rawstream will crate its own mapping
502 AliTPCRawStream rawStream(rawReader, (AliAltroMapping**)fMapping);
503 rawReader->Select("TPC");
504 Bool_t res = ProcessEvent(&rawStream);
507 fEventCounter++; // only increment event counter if there is TPC data
508 // otherwise Analyse (called in QA) fails
513 //_____________________________________________________________________
514 Bool_t AliTPCdataQA::ProcessEvent(eventHeaderStruct *event)
517 // process date event
520 AliRawReaderDate rawReader((void*)event);
521 Bool_t result=ProcessEvent(&rawReader);
527 //_____________________________________________________________________
528 void AliTPCdataQA::DumpToFile(const Char_t *filename, const Char_t *dir, Bool_t append) /*FOLD00*/
531 // Write class to file
542 TDirectory *backup = gDirectory;
543 TFile f(filename,option.Data());
545 if ( !sDir.IsNull() ){
546 f.mkdir(sDir.Data());
552 if ( backup ) backup->cd();
556 //_____________________________________________________________________
557 Int_t AliTPCdataQA::Update(const Int_t iSector, /*FOLD00*/
560 const Int_t iTimeBin,
564 // Signal filling method
568 // Define the calibration objects the first time Update is called
569 // NB! This has to be done first even if the data is rejected by the time
570 // cut to make sure that the objects are available in Analyse
572 if (!fNLocalMaxima) fNLocalMaxima = new AliTPCCalPad("NLocalMaxima","NLocalMaxima");
573 if (!fMaxCharge) fMaxCharge = new AliTPCCalPad("MaxCharge","MaxCharge");
574 if (!fMeanCharge) fMeanCharge = new AliTPCCalPad("MeanCharge","MeanCharge");
575 if (!fNoThreshold) fNoThreshold = new AliTPCCalPad("NoThreshold","NoThreshold");
576 if (!fNTimeBins) fNTimeBins = new AliTPCCalPad("NTimeBins","NTimeBins");
577 if (!fNPads) fNPads = new AliTPCCalPad("NPads","NPads");
578 if (!fTimePosition) fTimePosition = new AliTPCCalPad("TimePosition","TimePosition");
579 if (!fOverThreshold10) fOverThreshold10 = new AliTPCCalPad("OverThreshold10","OverThreshold10");
580 if (!fOverThreshold20) fOverThreshold20 = new AliTPCCalPad("OverThreshold20","OverThreshold20");
581 if (!fOverThreshold30) fOverThreshold30 = new AliTPCCalPad("OverThreshold30","OverThreshold30");
582 if (!fHistQVsTimeSideA) {
583 fHistQVsTimeSideA = new TProfile("hQVsTimeSideA", "Q vs time (side A); Time [Timebin]; Q [ADC ch]", 100, 0, 1000);
584 fHistQVsTimeSideA->SetDirectory(0);
586 if (!fHistQVsTimeSideC) {
587 fHistQVsTimeSideC = new TProfile("hQVsTimeSideC", "Q vs time (side C); Time [Timebin]; Q [ADC ch]", 100, 0, 1000);
588 fHistQVsTimeSideC->SetDirectory(0);
590 if (!fHistQMaxVsTimeSideA) {
591 fHistQMaxVsTimeSideA = new TProfile("hQMaxVsTimeSideA", "Q_{MAX} vs time (side A); Time [Timebin]; Q_{MAX} [ADC ch]", 100, 0, 1000);
592 fHistQMaxVsTimeSideA->SetDirectory(0);
594 if (!fHistQMaxVsTimeSideC) {
595 fHistQMaxVsTimeSideC = new TProfile("hQMaxVsTimeSideC", "Q_{MAX} vs time (side C); Time [Timebin]; Q_{MAX} [ADC ch]", 100, 0, 1000);
596 fHistQMaxVsTimeSideC->SetDirectory(0);
599 // Make the arrays for expanding the data
605 // If Analyse has been previously called we need now to denormalize the data
606 // as more data is coming
608 if(fIsAnalysed == kTRUE) {
610 const Int_t nTimeBins = fLastTimeBin - fFirstTimeBin +1;
611 const Float_t denormalization = Float_t(fEventCounter * nTimeBins);
612 fNoThreshold->Multiply(denormalization);
614 fMeanCharge->Multiply(fNLocalMaxima);
615 fMaxCharge->Multiply(fNLocalMaxima);
616 fNTimeBins->Multiply(fNLocalMaxima);
617 fNPads->Multiply(fNLocalMaxima);
618 fTimePosition->Multiply(fNLocalMaxima);
619 fIsAnalysed = kFALSE;
625 if (iTimeBin<fFirstTimeBin) return 0;
626 if (iTimeBin>fLastTimeBin) return 0;
628 // if pedestal calibrations are loaded subtract pedestals
631 Float_t ped = fPedestal->GetCalROC(iSector)->GetValue(iRow, iPad);
632 // Don't use data from pads where pedestals are abnormally small or large
638 // In fNoThreshold we fill all data to estimate the ZS volume
639 Float_t count = fNoThreshold->GetCalROC(iSector)->GetValue(iRow, iPad);
640 fNoThreshold->GetCalROC(iSector)->SetValue(iRow, iPad,count+1);
642 // Require at least 3 ADC channels
646 // if noise calibrations are loaded require at least 3*sigmaNoise
649 Float_t noise = fNoise->GetCalROC(iSector)->GetValue(iRow, iPad);
651 if(signal < noise*3.0)
656 // This signal is ok and we store it in the cluster map
659 SetExpandDigit(iRow, iPad, iTimeBin, signal);
661 return 1; // signal was accepted
664 //_____________________________________________________________________
665 void AliTPCdataQA::FindLocalMaxima(const Int_t iSector)
668 // This method is called after the data from each sector has been
669 // exapanded into an array
670 // Loop over the signals and identify local maxima and fill the
671 // calibration objects with the information
674 Int_t nLocalMaxima = 0;
675 const Int_t maxTimeBin = fTimeBinsMax+4; // Used to step between neighboring pads
676 // Because we have tha pad-time data in a
679 for (Int_t iRow = 0; iRow < fRowsMax; iRow++) {
681 Float_t* allBins = fAllBins[iRow];
682 Int_t* sigBins = fAllSigBins[iRow];
683 const Int_t nSigBins = fAllNSigBins[iRow];
685 for (Int_t iSig = 0; iSig < nSigBins; iSig++) {
687 Int_t bin = sigBins[iSig];
688 Float_t *b = &allBins[bin];
691 // Now we check if this is a local maximum
696 // First check that the charge is bigger than the threshold
700 // Require at least one neighboring pad with signal
701 if (b[-maxTimeBin]+b[maxTimeBin]<=0) continue;
703 // Require at least one neighboring time bin with signal
704 if (b[-1]+b[1]<=0) continue;
707 // Check that this is a local maximum
708 // Note that the checking is done so that if 2 charges has the same
709 // qMax then only 1 cluster is generated
710 // (that is why there is BOTH > and >=)
712 if (b[-maxTimeBin] >= qMax) continue;
713 if (b[-1 ] >= qMax) continue;
714 if (b[+maxTimeBin] > qMax) continue;
715 if (b[+1 ] > qMax) continue;
716 if (b[-maxTimeBin-1] >= qMax) continue;
717 if (b[+maxTimeBin-1] >= qMax) continue;
718 if (b[+maxTimeBin+1] > qMax) continue;
719 if (b[-maxTimeBin+1] >= qMax) continue;
722 // Now we accept the local maximum and fill the calibration/data objects
726 Int_t iPad, iTimeBin;
727 GetPadAndTimeBin(bin, iPad, iTimeBin);
729 Float_t count = fNLocalMaxima->GetCalROC(iSector)->GetValue(iRow, iPad);
730 fNLocalMaxima->GetCalROC(iSector)->SetValue(iRow, iPad, count+1);
732 count = fTimePosition->GetCalROC(iSector)->GetValue(iRow, iPad);
733 fTimePosition->GetCalROC(iSector)->SetValue(iRow, iPad, count+iTimeBin);
735 Float_t charge = fMaxCharge->GetCalROC(iSector)->GetValue(iRow, iPad);
736 fMaxCharge->GetCalROC(iSector)->SetValue(iRow, iPad, charge + qMax);
739 count = fOverThreshold10->GetCalROC(iSector)->GetValue(iRow, iPad);
740 fOverThreshold10->GetCalROC(iSector)->SetValue(iRow, iPad, count+1);
743 count = fOverThreshold20->GetCalROC(iSector)->GetValue(iRow, iPad);
744 fOverThreshold20->GetCalROC(iSector)->SetValue(iRow, iPad, count+1);
747 count = fOverThreshold30->GetCalROC(iSector)->GetValue(iRow, iPad);
748 fOverThreshold30->GetCalROC(iSector)->SetValue(iRow, iPad, count+1);
752 // Calculate the total charge as the sum over the region:
760 // with qmax at the center C.
762 // The inner charge (i) we always add, but we only add the outer
763 // charge (o) if the neighboring inner bin (i) has a signal.
765 Int_t minP = 0, maxP = 0, minT = 0, maxT = 0;
767 for(Int_t i = -1; i<=1; i++) {
768 for(Int_t j = -1; j<=1; j++) {
773 Float_t charge1 = GetQ(b, i, j, maxTimeBin, minT, maxT, minP, maxP);
776 // see if the next neighbor is also above threshold
778 qTot += GetQ(b, 2*i, 2*j, maxTimeBin, minT, maxT, minP, maxP);
780 // we are in a diagonal corner
781 qTot += GetQ(b, i, 2*j, maxTimeBin, minT, maxT, minP, maxP);
782 qTot += GetQ(b, 2*i, j, maxTimeBin, minT, maxT, minP, maxP);
783 qTot += GetQ(b, 2*i, 2*j, maxTimeBin, minT, maxT, minP, maxP);
789 charge = fMeanCharge->GetCalROC(iSector)->GetValue(iRow, iPad);
790 fMeanCharge->GetCalROC(iSector)->SetValue(iRow, iPad, charge + qTot);
792 count = fNTimeBins->GetCalROC(iSector)->GetValue(iRow, iPad);
793 fNTimeBins->GetCalROC(iSector)->SetValue(iRow, iPad, count + maxT-minT+1);
795 count = fNPads->GetCalROC(iSector)->GetValue(iRow, iPad);
796 fNPads->GetCalROC(iSector)->SetValue(iRow, iPad, count + maxP-minP+1);
798 if((iSector%36)<18) { // A side
799 fHistQVsTimeSideA->Fill(iTimeBin, qTot);
800 fHistQMaxVsTimeSideA->Fill(iTimeBin, qMax);
802 fHistQVsTimeSideC->Fill(iTimeBin, qTot);
803 fHistQMaxVsTimeSideC->Fill(iTimeBin, qMax);
805 } // end loop over signals
806 } // end loop over rows
808 // cout << "Number of local maximas found: " << nLocalMaxima << endl;
811 //_____________________________________________________________________
812 void AliTPCdataQA::Analyse()
815 // Calculate calibration constants
818 cout << "Analyse called" << endl;
820 if(fIsAnalysed == kTRUE) {
822 cout << "No new data since Analyse was called last time" << endl;
826 if(fEventCounter==0) {
828 cout << "EventCounter == 0, Cannot analyse" << endl;
832 Int_t nTimeBins = fLastTimeBin - fFirstTimeBin +1;
833 cout << "EventCounter: " << fEventCounter << endl
834 << "TimeBins: " << nTimeBins << endl;
836 Float_t normalization = 1.0 / Float_t(fEventCounter * nTimeBins);
837 fNoThreshold->Multiply(normalization);
839 fMeanCharge->Divide(fNLocalMaxima);
840 fMaxCharge->Divide(fNLocalMaxima);
841 fNTimeBins->Divide(fNLocalMaxima);
842 fNPads->Divide(fNLocalMaxima);
843 fTimePosition->Divide(fNLocalMaxima);
849 //_____________________________________________________________________
850 void AliTPCdataQA::MakeTree(const char *fname){
852 // Export result to the tree -located in the file
853 // This file can be analyzed using AliTPCCalibViewer
855 AliTPCPreprocessorOnline preprocesor;
857 if (fNLocalMaxima) preprocesor.AddComponent(fNLocalMaxima);
858 if (fMaxCharge) preprocesor.AddComponent(fMaxCharge);
859 if (fMeanCharge) preprocesor.AddComponent(fMeanCharge);
860 if (fNoThreshold) preprocesor.AddComponent(fNoThreshold);
861 if (fNTimeBins) preprocesor.AddComponent(fNTimeBins);
862 if (fNPads) preprocesor.AddComponent(fNPads);
863 if (fTimePosition) preprocesor.AddComponent(fTimePosition);
864 if (fOverThreshold10) preprocesor.AddComponent(fOverThreshold10);
865 if (fOverThreshold20) preprocesor.AddComponent(fOverThreshold20);
866 if (fOverThreshold30) preprocesor.AddComponent(fOverThreshold30);
868 preprocesor.DumpToFile(fname);
872 //_____________________________________________________________________
873 void AliTPCdataQA::MakeArrays(){
875 // The arrays for expanding the raw data are defined and
876 // som parameters are intialised
878 AliTPCROC * roc = AliTPCROC::Instance();
880 // To make the array big enough for all sectors we take
881 // the dimensions from the outer row of an OROC (the last sector)
883 fRowsMax = roc->GetNRows(roc->GetNSector()-1);
884 fPadsMax = roc->GetNPads(roc->GetNSector()-1,fRowsMax-1);
885 fTimeBinsMax = fLastTimeBin - fFirstTimeBin +1;
888 // Since we have added 2 pads (TimeBins) before and after the real pads (TimeBins)
889 // to make sure that we can always query the exanded table even when the
890 // max is on the edge
894 fAllBins = new Float_t*[fRowsMax];
895 fAllSigBins = new Int_t*[fRowsMax];
896 fAllNSigBins = new Int_t[fRowsMax];
898 for (Int_t iRow = 0; iRow < fRowsMax; iRow++) {
900 Int_t maxBin = (fTimeBinsMax+4)*(fPadsMax+4);
901 fAllBins[iRow] = new Float_t[maxBin];
902 memset(fAllBins[iRow],0,sizeof(Float_t)*maxBin); // set all values to 0
903 fAllSigBins[iRow] = new Int_t[maxBin];
904 fAllNSigBins[iRow] = 0;
909 //_____________________________________________________________________
910 void AliTPCdataQA::CleanArrays(){
915 for (Int_t iRow = 0; iRow < fRowsMax; iRow++) {
917 // To speed up the performance by a factor 2 on cosmic data (and
918 // presumably pp data as well) where the ocupancy is low, the
919 // memset is only called if there is more than 1000 signals for a
920 // row (of the order 1% occupancy)
921 if(fAllNSigBins[iRow]<1000) {
923 Float_t* allBins = fAllBins[iRow];
924 Int_t* sigBins = fAllSigBins[iRow];
925 const Int_t nSignals = fAllNSigBins[iRow];
926 for(Int_t i = 0; i < nSignals; i++)
927 allBins[sigBins[i]]=0;
930 Int_t maxBin = (fTimeBinsMax+4)*(fPadsMax+4);
931 memset(fAllBins[iRow],0,sizeof(Float_t)*maxBin);
934 fAllNSigBins[iRow]=0;
938 //_____________________________________________________________________
939 void AliTPCdataQA::GetPadAndTimeBin(Int_t bin, Int_t& iPad, Int_t& iTimeBin){
941 // Return pad and timebin for a given bin
944 // Int_t bin = iPad*(fTimeBinsMax+4)+iTimeBin;
945 iTimeBin = bin%(fTimeBinsMax+4);
946 iPad = (bin-iTimeBin)/(fTimeBinsMax+4);
950 iTimeBin += fFirstTimeBin;
952 R__ASSERT(iPad>=0 && iPad<=fPadsMax);
953 R__ASSERT(iTimeBin>=fFirstTimeBin && iTimeBin<=fLastTimeBin);
956 //_____________________________________________________________________
957 void AliTPCdataQA::SetExpandDigit(const Int_t iRow, Int_t iPad,
958 Int_t iTimeBin, const Float_t signal)
963 R__ASSERT(iRow>=0 && iRow<fRowsMax);
964 R__ASSERT(iPad>=0 && iPad<=fPadsMax);
965 R__ASSERT(iTimeBin>=fFirstTimeBin && iTimeBin<=fLastTimeBin);
967 iTimeBin -= fFirstTimeBin;
971 Int_t bin = iPad*(fTimeBinsMax+4)+iTimeBin;
972 fAllBins[iRow][bin] = signal;
973 fAllSigBins[iRow][fAllNSigBins[iRow]] = bin;
974 fAllNSigBins[iRow]++;
977 Float_t AliTPCdataQA::GetQ(const Float_t* adcArray, const Int_t time,
978 const Int_t pad, const Int_t maxTimeBins,
979 Int_t& timeMin, Int_t& timeMax,
980 Int_t& padMin, Int_t& padMax)
983 // This methods return the charge in the bin time+pad*maxTimeBins
984 // If the charge is above 0 it also updates the padMin, padMax, timeMin
985 // and timeMax if necessary
987 Float_t charge = adcArray[time + pad*maxTimeBins];
989 timeMin = TMath::Min(time, timeMin); timeMax = TMath::Max(time, timeMax);
990 padMin = TMath::Min(pad, padMin); padMax = TMath::Max(pad, padMax);
995 //______________________________________________________________________________
996 void AliTPCdataQA::Streamer(TBuffer &R__b)
998 // Automatic schema evolution was first used from revision 4
1000 // http://root.cern.ch/root/roottalk/roottalk02/3207.html
1003 if (R__b.IsReading()) {
1004 Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
1005 //we use the automatic algorithm for class version > 3
1007 AliTPCdataQA::Class()->ReadBuffer(R__b, this, R__v, R__s,
1011 TH1F::Streamer(R__b);
1012 R__b >> fFirstTimeBin;
1013 R__b >> fLastTimeBin;
1016 R__b >> fNLocalMaxima;
1018 R__b >> fMeanCharge;
1019 R__b >> fNoThreshold;
1022 R__b >> fTimePosition;
1023 R__b >> fEventCounter;
1024 R__b >> fIsAnalysed;
1025 R__b.CheckByteCount(R__s, R__c, AliTPCdataQA::IsA());
1027 AliTPCdataQA::Class()->WriteBuffer(R__b,this);