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 **************************************************************************/
25 #include <TDirectory.h>
30 #include "AliRawReader.h"
31 #include "AliRawReaderRoot.h"
32 #include "AliRawReaderDate.h"
33 #include "AliTPCRawStream.h"
34 #include "AliTPCCalROC.h"
35 #include "AliTPCCalPad.h"
36 #include "AliTPCROC.h"
37 #include "AliTPCParam.h"
38 #include "AliTPCCalibPulser.h"
39 #include "AliTPCcalibDB.h"
40 #include "AliMathBase.h"
41 #include "TTreeStream.h"
47 ///////////////////////////////////////////////////////////////////////////////////////
48 // Implementation of the TPC pulser calibration
50 // Origin: Jens Wiechula, Marian Ivanov J.Wiechula@gsi.de, Marian.Ivanov@cern.ch
53 /***************************************************************************
55 ***************************************************************************
57 The AliTPCCalibPulser class is used to get calibration data concerning the FEE using
58 runs performed with the calibration pulser.
60 The information retrieved is
62 - Signal width differences
63 - Amplification variations
65 the seen differences arise from the manufacturing tolerances of the PASAs and are very small within
66 one chip and somewhat large between different chips.
69 For each ROC three TH2S histos 'Reference Histograms' (ROC channel vs. [Time0, signal width, Q sum]) is created when
70 it is filled for the first time (GetHisto[T0,RMS,Q](ROC,kTRUE)). The histos are stored in the
71 TObjArrays fHistoT0Array, fHistoRMSArray and fHistoQArray.
76 Raw calibration pulser data is processed by calling one of the ProcessEvent(...) functions
77 (see below). These in the end call the Update(...) function.
79 - the Update(...) function:
80 In this function the array fPadSignal is filled with the adc signals between the specified range
81 fFirstTimeBin and fLastTimeBin for the current pad.
82 before going to the next pad the ProcessPad() function is called, which analyses the data for one pad
85 - the ProcessPad() function:
86 Find Pedestal and Noise information
87 - use database information which has to be set by calling
88 SetPedestalDatabase(AliTPCCalPad *pedestalTPC, AliTPCCalPad *padNoiseTPC)
89 - if no information from the pedestal data base
90 is available the informaion is calculated on the fly ( see FindPedestal() function )
92 Find the Pulser signal information
93 - calculate mean = T0, RMS = signal width and Q sum in a range of -2+7 timebins around Q max
94 the Q sum is scaled by pad area
95 (see FindPulserSignal(...) function)
97 Fill a temprary array for the T0 information (GetPadTimesEvent(fCurrentSector,kTRUE)) (why see below)
98 Fill the Q sum and RMS values in the histograms (GetHisto[RMS,Q](ROC,kTRUE)),
100 At the end of each event the EndEvent() function is called
102 - the EndEvent() function:
103 calculate the mean T0 for each ROC and fill the Time0 histogram with Time0-<Time0 for ROC>
104 This is done to overcome syncronisation problems between the trigger and the fec clock.
106 After accumulating the desired statistics the Analyse() function has to be called.
107 - the Analyse() function
108 Whithin this function the mean values of T0, RMS, Q are calculated for each pad, using
109 the AliMathBase::GetCOG(...) function, and the calibration
110 storage classes (AliTPCCalROC) are filled for each ROC.
111 The calibration information is stored in the TObjArrays fCalRocArrayT0, fCalRocArrayRMS and
116 User interface for filling data:
117 --------------------------------
119 To Fill information one of the following functions can be used:
121 Bool_t ProcessEvent(eventHeaderStruct *event);
123 - use AliTPCRawReaderDate and call ProcessEvent(AliRawReader *rawReader)
125 Bool_t ProcessEvent(AliRawReader *rawReader);
126 - process AliRawReader event
127 - use AliTPCRawStream to loop over data and call ProcessEvent(AliTPCRawStream *rawStream)
129 Bool_t ProcessEvent(AliTPCRawStream *rawStream);
130 - process event from AliTPCRawStream
131 - call Update function for signal filling
133 Int_t Update(const Int_t isector, const Int_t iRow, const Int_t
134 iPad, const Int_t iTimeBin, const Float_t signal);
135 - directly fill signal information (sector, row, pad, time bin, pad)
136 to the reference histograms
138 It is also possible to merge two independently taken calibrations using the function
140 void Merge(AliTPCCalibPulser *sig)
141 - copy histograms in 'sig' if the do not exist in this instance
142 - Add histograms in 'sig' to the histograms in this instance if the allready exist
143 - After merging call Analyse again!
147 -- example: filling data using root raw data:
148 void fillSignal(Char_t *filename)
150 rawReader = new AliRawReaderRoot(fileName);
151 if ( !rawReader ) return;
152 AliTPCCalibPulser *calib = new AliTPCCalibPulser;
153 while (rawReader->NextEvent()){
154 calib->ProcessEvent(rawReader);
157 calib->DumpToFile("SignalData.root");
163 What kind of information is stored and how to retrieve them:
164 ------------------------------------------------------------
166 - Accessing the 'Reference Histograms' (Time0, signal width and Q sum information pad by pad):
168 TH2F *GetHistoT0(Int_t sector);
169 TH2F *GetHistoRMS(Int_t sector);
170 TH2F *GetHistoQ(Int_t sector);
172 - Accessing the calibration storage objects:
174 AliTPCCalROC *GetCalRocT0(Int_t sector); // for the Time0 values
175 AliTPCCalROC *GetCalRocRMS(Int_t sector); // for the signal width values
176 AliTPCCalROC *GetCalRocQ(Int_t sector); // for the Q sum values
178 example for visualisation:
179 if the file "SignalData.root" was created using the above example one could do the following:
181 TFile fileSignal("SignalData.root")
182 AliTPCCalibPulser *sig = (AliTPCCalibPulser*)fileSignal->Get("AliTPCCalibPulser");
183 sig->GetCalRocT0(0)->Draw("colz");
184 sig->GetCalRocRMS(0)->Draw("colz");
186 or use the AliTPCCalPad functionality:
187 AliTPCCalPad padT0(ped->GetCalPadT0());
188 AliTPCCalPad padSigWidth(ped->GetCalPadRMS());
189 padT0->MakeHisto2D()->Draw("colz"); //Draw A-Side Time0 Information
190 padSigWidth->MakeHisto2D()->Draw("colz"); //Draw A-Side signal width Information
194 ClassImp(AliTPCCalibPulser) /*FOLD00*/
196 AliTPCCalibPulser::AliTPCCalibPulser() : /*FOLD00*/
210 fOldRCUformat(kTRUE),
211 fROC(AliTPCROC::Instance()),
212 fParam(new AliTPCParam),
220 fCalRocArrayOutliers(72),
224 fPadTimesArrayEvent(72),
226 fPadRMSArrayEvent(72),
227 fPadPedestalArrayEvent(72),
237 fVTime0OffsetCounter(72),
243 // AliTPCSignal default constructor
247 //_____________________________________________________________________
248 AliTPCCalibPulser::AliTPCCalibPulser(const AliTPCCalibPulser &sig) :
250 fFirstTimeBin(sig.fFirstTimeBin),
251 fLastTimeBin(sig.fLastTimeBin),
252 fNbinsT0(sig.fNbinsT0),
253 fXminT0(sig.fXminT0),
254 fXmaxT0(sig.fXmaxT0),
255 fNbinsQ(sig.fNbinsQ),
258 fNbinsRMS(sig.fNbinsRMS),
259 fXminRMS(sig.fXminRMS),
260 fXmaxRMS(sig.fXmaxRMS),
262 fOldRCUformat(kTRUE),
263 fROC(AliTPCROC::Instance()),
264 fParam(new AliTPCParam),
272 fCalRocArrayOutliers(72),
276 fPadTimesArrayEvent(72),
278 fPadRMSArrayEvent(72),
279 fPadPedestalArrayEvent(72),
289 fVTime0OffsetCounter(72),
292 fDebugLevel(sig.fDebugLevel)
295 // AliTPCSignal default constructor
298 for (Int_t iSec = 0; iSec < 72; ++iSec){
299 const AliTPCCalROC *calQ = (AliTPCCalROC*)sig.fCalRocArrayQ.UncheckedAt(iSec);
300 const AliTPCCalROC *calT0 = (AliTPCCalROC*)sig.fCalRocArrayT0.UncheckedAt(iSec);
301 const AliTPCCalROC *calRMS = (AliTPCCalROC*)sig.fCalRocArrayRMS.UncheckedAt(iSec);
302 const AliTPCCalROC *calOut = (AliTPCCalROC*)sig.fCalRocArrayOutliers.UncheckedAt(iSec);
304 const TH2S *hQ = (TH2S*)sig.fHistoQArray.UncheckedAt(iSec);
305 const TH2S *hT0 = (TH2S*)sig.fHistoT0Array.UncheckedAt(iSec);
306 const TH2S *hRMS = (TH2S*)sig.fHistoRMSArray.UncheckedAt(iSec);
308 if ( calQ != 0x0 ) fCalRocArrayQ.AddAt(new AliTPCCalROC(*calQ), iSec);
309 if ( calT0 != 0x0 ) fCalRocArrayT0.AddAt(new AliTPCCalROC(*calT0), iSec);
310 if ( calRMS != 0x0 ) fCalRocArrayRMS.AddAt(new AliTPCCalROC(*calRMS), iSec);
311 if ( calOut != 0x0 ) fCalRocArrayOutliers.AddAt(new AliTPCCalROC(*calOut), iSec);
314 TH2S *hNew = new TH2S(*hQ);
315 hNew->SetDirectory(0);
316 fHistoQArray.AddAt(hNew,iSec);
319 TH2S *hNew = new TH2S(*hT0);
320 hNew->SetDirectory(0);
321 fHistoQArray.AddAt(hNew,iSec);
324 TH2S *hNew = new TH2S(*hRMS);
325 hNew->SetDirectory(0);
326 fHistoQArray.AddAt(hNew,iSec);
331 //_____________________________________________________________________
332 AliTPCCalibPulser& AliTPCCalibPulser::operator = (const AliTPCCalibPulser &source)
335 // assignment operator
337 if (&source == this) return *this;
338 new (this) AliTPCCalibPulser(source);
342 //_____________________________________________________________________
343 AliTPCCalibPulser::~AliTPCCalibPulser()
349 fCalRocArrayT0.Delete();
350 fCalRocArrayQ.Delete();
351 fCalRocArrayRMS.Delete();
352 fCalRocArrayOutliers.Delete();
354 fHistoQArray.Delete();
355 fHistoT0Array.Delete();
356 fHistoRMSArray.Delete();
358 fPadTimesArrayEvent.Delete();
359 fPadQArrayEvent.Delete();
360 fPadRMSArrayEvent.Delete();
361 fPadPedestalArrayEvent.Delete();
363 if ( fDebugStreamer) delete fDebugStreamer;
366 //_____________________________________________________________________
367 Int_t AliTPCCalibPulser::Update(const Int_t icsector, /*FOLD00*/
370 const Int_t icTimeBin,
371 const Float_t csignal)
374 // Signal filling methode on the fly pedestal and Time offset correction if necessary.
375 // no extra analysis necessary. Assumes knowledge of the signal shape!
376 // assumes that it is looped over consecutive time bins of one pad
378 if ( (icTimeBin>fLastTimeBin) || (icTimeBin<fFirstTimeBin) ) return 0;
380 Int_t iChannel = fROC->GetRowIndexes(icsector)[icRow]+icPad; // global pad position in sector
382 //init first pad and sector in this event
383 if ( fCurrentChannel == -1 ) {
384 fCurrentChannel = iChannel;
385 fCurrentSector = icsector;
389 //process last pad if we change to a new one
390 if ( iChannel != fCurrentChannel ){
392 fCurrentChannel = iChannel;
393 fCurrentSector = icsector;
397 //fill signals for current pad
398 fPadSignal[icTimeBin]=csignal;
399 if ( csignal > fMaxPadSignal ){
400 fMaxPadSignal = csignal;
401 fMaxTimeBin = icTimeBin;
405 //_____________________________________________________________________
406 void AliTPCCalibPulser::FindPedestal(Float_t part)
409 // find pedestal and noise for the current pad. Use either database or
410 // truncated mean with part*100%
412 Bool_t noPedestal = kTRUE;;
413 if (fPedestalTPC&&fPadNoiseTPC){
414 //use pedestal database
415 //only load new pedestals if the sector has changed
416 if ( fCurrentSector!=fLastSector ){
417 fPedestalROC = fPedestalTPC->GetCalROC(fCurrentSector);
418 fPadNoiseROC = fPadNoiseTPC->GetCalROC(fCurrentSector);
419 fLastSector=fCurrentSector;
422 if ( fPedestalROC&&fPadNoiseROC ){
423 fPadPedestal = fPedestalROC->GetValue(fCurrentChannel);
424 fPadNoise = fPadNoiseROC->GetValue(fCurrentChannel);
430 //if we are not running with pedestal database, or for the current sector there is no information
431 //available, calculate the pedestal and noise on the fly
433 const Int_t kPedMax = 100; //maximum pedestal value
442 UShort_t histo[kPedMax];
443 memset(histo,0,kPedMax*sizeof(UShort_t));
445 for (Int_t i=fFirstTimeBin; i<=fLastTimeBin; ++i){
446 padSignal = fPadSignal.GetMatrixArray()[i];
447 if (padSignal<=0) continue;
448 if (padSignal>max && i>10) {
452 if (padSignal>kPedMax-1) continue;
453 histo[Int_t(padSignal+0.5)]++;
457 for (Int_t i=1; i<kPedMax; ++i){
458 if (count1<count0*0.5) median=i;
463 Float_t count=histo[median] ,mean=histo[median]*median, rms=histo[median]*median*median ;
465 for (Int_t idelta=1; idelta<10; ++idelta){
466 if (median-idelta<=0) continue;
467 if (median+idelta>kPedMax) continue;
468 if (count<part*count1){
469 count+=histo[median-idelta];
470 mean +=histo[median-idelta]*(median-idelta);
471 rms +=histo[median-idelta]*(median-idelta)*(median-idelta);
472 count+=histo[median+idelta];
473 mean +=histo[median+idelta]*(median+idelta);
474 rms +=histo[median+idelta]*(median+idelta)*(median+idelta);
481 rms = TMath::Sqrt(TMath::Abs(rms/count-mean*mean));
487 //_____________________________________________________________________
488 void AliTPCCalibPulser::FindPulserSignal(TVectorD ¶m, Float_t &qSum)
491 // Find position, signal width and height of the CE signal (last signal)
492 // param[0] = Qmax, param[1] = mean time, param[2] = rms;
493 // maxima: array of local maxima of the pad signal use the one closest to the mean CE position
496 Float_t ceQmax =0, ceQsum=0, ceTime=0, ceRMS=0;
497 Int_t cemaxpos = fMaxTimeBin;
498 Float_t ceSumThreshold = 8.*fPadNoise; // threshold for the signal sum
499 const Int_t kCemin = 2; // range for the analysis of the ce signal +- channels from the peak
500 const Int_t kCemax = 7;
503 ceQmax = fPadSignal.GetMatrixArray()[cemaxpos]-fPadPedestal;
504 for (Int_t i=cemaxpos-kCemin; i<cemaxpos+kCemax; ++i){
505 Float_t signal = fPadSignal.GetMatrixArray()[i]-fPadPedestal;
506 if ( (i>fFirstTimeBin) && (i<fLastTimeBin) && (signal>0) ){
507 ceTime+=signal*(i+0.5);
508 ceRMS +=signal*(i+0.5)*(i+0.5);
513 if (ceQmax&&ceQsum>ceSumThreshold) {
515 ceRMS = TMath::Sqrt(TMath::Abs(ceRMS/ceQsum-ceTime*ceTime));
516 fVTime0Offset.GetMatrixArray()[fCurrentSector]+=ceTime; // mean time for each sector
517 fVTime0OffsetCounter.GetMatrixArray()[fCurrentSector]++;
519 //Normalise Q to the pad area
520 Float_t norm = fParam->GetPadPitchWidth(fCurrentSector)*fParam->GetPadPitchLength(fCurrentSector,fCurrentRow);
534 //_____________________________________________________________________
535 void AliTPCCalibPulser::ProcessPad() /*FOLD00*/
538 // Process data of current pad
544 FindPulserSignal(param, Qsum);
546 Double_t meanT = param[1];
547 Double_t sigmaT = param[2];
549 //Fill Event T0 counter
550 (*GetPadTimesEvent(fCurrentSector,kTRUE)).GetMatrixArray()[fCurrentChannel] = meanT;
553 GetHistoQ(fCurrentSector,kTRUE)->Fill( TMath::Sqrt(Qsum), fCurrentChannel );
556 GetHistoRMS(fCurrentSector,kTRUE)->Fill( sigmaT, fCurrentChannel );
559 //Fill debugging info
560 if ( fDebugLevel>0 ){
561 (*GetPadPedestalEvent(fCurrentSector,kTRUE))[fCurrentChannel]=fPadPedestal;
562 (*GetPadRMSEvent(fCurrentSector,kTRUE))[fCurrentChannel]=sigmaT;
563 (*GetPadQEvent(fCurrentSector,kTRUE))[fCurrentChannel]=Qsum;
568 //_____________________________________________________________________
569 void AliTPCCalibPulser::EndEvent() /*FOLD00*/
572 // Process data of current event
575 //check if last pad has allready been processed, if not do so
576 if ( fMaxTimeBin>-1 ) ProcessPad();
578 //loop over all ROCs, fill Time0 histogram corrected for the mean Time0 of each ROC
579 for ( Int_t iSec = 0; iSec<72; ++iSec ){
580 TVectorF *vTimes = GetPadTimesEvent(iSec);
581 if ( !vTimes ) continue;
583 for ( UInt_t iChannel=0; iChannel<fROC->GetNChannels(iSec); ++iChannel ){
584 Float_t Time0 = fVTime0Offset[iSec]/fVTime0OffsetCounter[iSec];
585 Float_t Time = (*vTimes).GetMatrixArray()[iChannel];
587 GetHistoT0(iSec,kTRUE)->Fill( Time-Time0,iChannel );
591 if ( fDebugLevel>0 ){
592 if ( !fDebugStreamer ) {
594 TDirectory *backup = gDirectory;
595 fDebugStreamer = new TTreeSRedirector("deb2.root");
596 if ( backup ) backup->cd(); //we don't want to be cd'd to the debug streamer
603 Float_t Q = (*GetPadQEvent(iSec)).GetMatrixArray()[iChannel];
604 Float_t RMS = (*GetPadRMSEvent(iSec)).GetMatrixArray()[iChannel];
606 UInt_t channel=iChannel;
609 while ( channel > (fROC->GetRowIndexes(sector)[row]+fROC->GetNPads(sector,row)-1) ) row++;
610 pad = channel-fROC->GetRowIndexes(sector)[row];
611 padc = pad-(fROC->GetNPads(sector,row)/2);
613 TH1F *h1 = new TH1F(Form("hSignalD%d.%d.%d",sector,row,pad),
614 Form("hSignalD%d.%d.%d",sector,row,pad),
615 fLastTimeBin-fFirstTimeBin,
616 fFirstTimeBin,fLastTimeBin);
619 for (Int_t i=fFirstTimeBin; i<fLastTimeBin+1; ++i)
620 h1->Fill(i,fPadSignal(i));
622 (*fDebugStreamer) << "DataPad" <<
623 "Event=" << fEvent <<
624 "Sector="<< sector <<
628 "PadSec="<< channel <<
644 //_____________________________________________________________________
645 Bool_t AliTPCCalibPulser::ProcessEvent(AliTPCRawStream *rawStream) /*FOLD00*/
648 // Event Processing loop - AliTPCRawStream
651 rawStream->SetOldRCUFormat(fOldRCUformat);
655 Bool_t withInput = kFALSE;
657 while (rawStream->Next()) {
659 Int_t isector = rawStream->GetSector(); // current sector
660 Int_t iRow = rawStream->GetRow(); // current row
661 Int_t iPad = rawStream->GetPad(); // current pad
662 Int_t iTimeBin = rawStream->GetTime(); // current time bin
663 Float_t signal = rawStream->GetSignal(); // current ADC signal
665 Update(isector,iRow,iPad,iTimeBin,signal);
675 //_____________________________________________________________________
676 Bool_t AliTPCCalibPulser::ProcessEvent(AliRawReader *rawReader)
679 // Event processing loop - AliRawReader
683 AliTPCRawStream rawStream(rawReader);
685 rawReader->Select("TPC");
687 return ProcessEvent(&rawStream);
689 //_____________________________________________________________________
690 Bool_t AliTPCCalibPulser::ProcessEvent(eventHeaderStruct *event)
693 // Event processing loop - date event
695 AliRawReader *rawReader = new AliRawReaderDate((void*)event);
696 Bool_t result=ProcessEvent(rawReader);
701 //_____________________________________________________________________
702 TH2S* AliTPCCalibPulser::GetHisto(Int_t sector, TObjArray *arr, /*FOLD00*/
703 Int_t nbinsY, Float_t ymin, Float_t ymax,
704 Char_t *type, Bool_t force)
707 // return pointer to Q histogram
708 // if force is true create a new histogram if it doesn't exist allready
710 if ( !force || arr->UncheckedAt(sector) )
711 return (TH2S*)arr->UncheckedAt(sector);
713 // if we are forced and histogram doesn't yes exist create it
714 Char_t name[255], title[255];
716 sprintf(name,"hCalib%s%.2d",type,sector);
717 sprintf(title,"%s calibration histogram sector %.2d",type,sector);
719 // new histogram with Q calib information. One value for each pad!
720 TH2S* hist = new TH2S(name,title,
722 fROC->GetNChannels(sector),0,fROC->GetNChannels(sector));
723 hist->SetDirectory(0);
724 arr->AddAt(hist,sector);
727 //_____________________________________________________________________
728 TH2S* AliTPCCalibPulser::GetHistoT0(Int_t sector, Bool_t force) /*FOLD00*/
731 // return pointer to T0 histogram
732 // if force is true create a new histogram if it doesn't exist allready
734 TObjArray *arr = &fHistoT0Array;
735 return GetHisto(sector, arr, fNbinsT0, fXminT0, fXmaxT0, "T0", force);
737 //_____________________________________________________________________
738 TH2S* AliTPCCalibPulser::GetHistoQ(Int_t sector, Bool_t force) /*FOLD00*/
741 // return pointer to Q histogram
742 // if force is true create a new histogram if it doesn't exist allready
744 TObjArray *arr = &fHistoQArray;
745 return GetHisto(sector, arr, fNbinsQ, fXminQ, fXmaxQ, "Q", force);
747 //_____________________________________________________________________
748 TH2S* AliTPCCalibPulser::GetHistoRMS(Int_t sector, Bool_t force) /*FOLD00*/
751 // return pointer to Q histogram
752 // if force is true create a new histogram if it doesn't exist allready
754 TObjArray *arr = &fHistoRMSArray;
755 return GetHisto(sector, arr, fNbinsRMS, fXminRMS, fXmaxRMS, "RMS", force);
757 //_____________________________________________________________________
758 TVectorF* AliTPCCalibPulser::GetPadInfoEvent(Int_t sector, TObjArray *arr, Bool_t force) /*FOLD00*/
761 // return pointer to Pad Info from 'arr' for the current event and sector
762 // if force is true create it if it doesn't exist allready
764 if ( !force || arr->UncheckedAt(sector) )
765 return (TVectorF*)arr->UncheckedAt(sector);
767 TVectorF *vect = new TVectorF(fROC->GetNChannels(sector));
768 arr->AddAt(vect,sector);
771 //_____________________________________________________________________
772 TVectorF* AliTPCCalibPulser::GetPadTimesEvent(Int_t sector, Bool_t force) /*FOLD00*/
775 // return pointer to Pad Times Array for the current event and sector
776 // if force is true create it if it doesn't exist allready
778 TObjArray *arr = &fPadTimesArrayEvent;
779 return GetPadInfoEvent(sector,arr,force);
781 //_____________________________________________________________________
782 TVectorF* AliTPCCalibPulser::GetPadQEvent(Int_t sector, Bool_t force) /*FOLD00*/
785 // return pointer to Pad Q Array for the current event and sector
786 // if force is true create it if it doesn't exist allready
787 // for debugging purposes only
790 TObjArray *arr = &fPadQArrayEvent;
791 return GetPadInfoEvent(sector,arr,force);
793 //_____________________________________________________________________
794 TVectorF* AliTPCCalibPulser::GetPadRMSEvent(Int_t sector, Bool_t force) /*FOLD00*/
797 // return pointer to Pad RMS Array for the current event and sector
798 // if force is true create it if it doesn't exist allready
799 // for debugging purposes only
801 TObjArray *arr = &fPadRMSArrayEvent;
802 return GetPadInfoEvent(sector,arr,force);
804 //_____________________________________________________________________
805 TVectorF* AliTPCCalibPulser::GetPadPedestalEvent(Int_t sector, Bool_t force) /*FOLD00*/
808 // return pointer to Pad RMS Array for the current event and sector
809 // if force is true create it if it doesn't exist allready
810 // for debugging purposes only
812 TObjArray *arr = &fPadPedestalArrayEvent;
813 return GetPadInfoEvent(sector,arr,force);
815 //_____________________________________________________________________
816 AliTPCCalROC* AliTPCCalibPulser::GetCalRoc(Int_t sector, TObjArray* arr, Bool_t force) /*FOLD00*/
819 // return pointer to ROC Calibration
820 // if force is true create a new histogram if it doesn't exist allready
822 if ( !force || arr->UncheckedAt(sector) )
823 return (AliTPCCalROC*)arr->UncheckedAt(sector);
825 // if we are forced and histogram doesn't yes exist create it
827 // new AliTPCCalROC for T0 information. One value for each pad!
828 AliTPCCalROC *croc = new AliTPCCalROC(sector);
829 arr->AddAt(croc,sector);
832 //_____________________________________________________________________
833 AliTPCCalROC* AliTPCCalibPulser::GetCalRocT0(Int_t sector, Bool_t force) /*FOLD00*/
836 // return pointer to Carge ROC Calibration
837 // if force is true create a new histogram if it doesn't exist allready
839 TObjArray *arr = &fCalRocArrayT0;
840 return GetCalRoc(sector, arr, force);
842 //_____________________________________________________________________
843 AliTPCCalROC* AliTPCCalibPulser::GetCalRocQ(Int_t sector, Bool_t force) /*FOLD00*/
846 // return pointer to T0 ROC Calibration
847 // if force is true create a new histogram if it doesn't exist allready
849 TObjArray *arr = &fCalRocArrayQ;
850 return GetCalRoc(sector, arr, force);
852 //_____________________________________________________________________
853 AliTPCCalROC* AliTPCCalibPulser::GetCalRocRMS(Int_t sector, Bool_t force) /*FOLD00*/
856 // return pointer to signal width ROC Calibration
857 // if force is true create a new histogram if it doesn't exist allready
859 TObjArray *arr = &fCalRocArrayRMS;
860 return GetCalRoc(sector, arr, force);
862 //_____________________________________________________________________
863 AliTPCCalROC* AliTPCCalibPulser::GetCalRocOutliers(Int_t sector, Bool_t force)
866 // return pointer to Outliers
867 // if force is true create a new histogram if it doesn't exist allready
869 TObjArray *arr = &fCalRocArrayOutliers;
870 return GetCalRoc(sector, arr, force);
872 //_____________________________________________________________________
873 void AliTPCCalibPulser::ResetEvent() /*FOLD00*/
876 // Reset global counters -- Should be called before each event is processed
885 fPadTimesArrayEvent.Delete();
886 fPadQArrayEvent.Delete();
887 fPadRMSArrayEvent.Delete();
888 fPadPedestalArrayEvent.Delete();
890 for ( Int_t i=0; i<72; ++i ){
892 fVTime0OffsetCounter[i]=0;
895 //_____________________________________________________________________
896 void AliTPCCalibPulser::ResetPad() /*FOLD00*/
899 // Reset pad infos -- Should be called after a pad has been processed
901 for (Int_t i=fFirstTimeBin; i<fLastTimeBin+1; ++i)
908 //_____________________________________________________________________
909 void AliTPCCalibPulser::Merge(AliTPCCalibPulser *sig)
912 // Merge reference histograms of sig to the current AliTPCCalibPulser
916 for (Int_t iSec=0; iSec<72; ++iSec){
917 TH2S *hRefQmerge = sig->GetHistoQ(iSec);
918 TH2S *hRefT0merge = sig->GetHistoT0(iSec);
919 TH2S *hRefRMSmerge = sig->GetHistoRMS(iSec);
923 TDirectory *dir = hRefQmerge->GetDirectory(); hRefQmerge->SetDirectory(0);
924 TH2S *hRefQ = GetHistoQ(iSec);
925 if ( hRefQ ) hRefQ->Add(hRefQmerge);
927 TH2S *hist = new TH2S(*hRefQmerge);
928 hist->SetDirectory(0);
929 fHistoQArray.AddAt(hist, iSec);
931 hRefQmerge->SetDirectory(dir);
934 TDirectory *dir = hRefT0merge->GetDirectory(); hRefT0merge->SetDirectory(0);
935 TH2S *hRefT0 = GetHistoT0(iSec);
936 if ( hRefT0 ) hRefT0->Add(hRefT0merge);
938 TH2S *hist = new TH2S(*hRefT0merge);
939 hist->SetDirectory(0);
940 fHistoT0Array.AddAt(hist, iSec);
942 hRefT0merge->SetDirectory(dir);
945 TDirectory *dir = hRefRMSmerge->GetDirectory(); hRefRMSmerge->SetDirectory(0);
946 TH2S *hRefRMS = GetHistoRMS(iSec);
947 if ( hRefRMS ) hRefRMS->Add(hRefRMSmerge);
949 TH2S *hist = new TH2S(*hRefRMSmerge);
950 hist->SetDirectory(0);
951 fHistoRMSArray.AddAt(hist, iSec);
953 hRefRMSmerge->SetDirectory(dir);
958 //_____________________________________________________________________
959 void AliTPCCalibPulser::Analyse() /*FOLD00*/
962 // Calculate calibration constants
967 TVectorD paramRMS(3);
970 for (Int_t iSec=0; iSec<72; ++iSec){
971 TH2S *hT0 = GetHistoT0(iSec);
974 AliTPCCalROC *rocQ = GetCalRocQ (iSec,kTRUE);
975 AliTPCCalROC *rocT0 = GetCalRocT0 (iSec,kTRUE);
976 AliTPCCalROC *rocRMS = GetCalRocRMS(iSec,kTRUE);
977 AliTPCCalROC *rocOut = GetCalRocOutliers(iSec,kTRUE);
979 TH2S *hQ = GetHistoQ(iSec);
980 TH2S *hRMS = GetHistoRMS(iSec);
982 Short_t *array_hQ = hQ->GetArray();
983 Short_t *array_hT0 = hT0->GetArray();
984 Short_t *array_hRMS = hRMS->GetArray();
986 UInt_t nChannels = fROC->GetNChannels(iSec);
994 for (UInt_t iChannel=0; iChannel<nChannels; ++iChannel){
997 Float_t cogTime0 = -1000;
998 Float_t cogQ = -1000;
999 Float_t cogRMS = -1000;
1003 Int_t offsetQ = (fNbinsQ+2)*(iChannel+1)+1;
1004 Int_t offsetT0 = (fNbinsT0+2)*(iChannel+1)+1;
1005 Int_t offsetRMS = (fNbinsRMS+2)*(iChannel+1)+1;
1008 AliMathBase::FitGaus(array_hQ+offsetQ,fNbinsQ,fXminQ,fXmaxQ,¶mQ,&dummy);
1009 AliMathBase::FitGaus(array_hT0+offsetT0,fNbinsT0,fXminT0,fXmaxT0,¶mT0,&dummy);
1010 AliMathBase::FitGaus(array_hRMS+offsetRMS,fNbinsRMS,fXminRMS,fXmaxRMS,¶mRMS,&dummy);
1012 cogTime0 = paramT0[1];
1013 cogRMS = paramRMS[1];
1015 cogQ = AliMathBase::GetCOG(array_hQ+offsetQ,fNbinsQ,fXminQ,fXmaxQ);
1016 cogTime0 = AliMathBase::GetCOG(array_hT0+offsetT0,fNbinsT0,fXminT0,fXmaxT0);
1017 cogRMS = AliMathBase::GetCOG(array_hRMS+offsetRMS,fNbinsRMS,fXminRMS,fXmaxRMS);
1022 if ( (cogQ < ??) && (cogTime0 > ??) && (cogTime0<??) && ( cogRMS>??) ){
1029 rocQ->SetValue(iChannel, cogQ*cogQ);
1030 rocT0->SetValue(iChannel, cogTime0);
1031 rocRMS->SetValue(iChannel, cogRMS);
1032 rocOut->SetValue(iChannel, cogOut);
1036 if ( fDebugLevel > 0 ){
1037 if ( !fDebugStreamer ) {
1039 TDirectory *backup = gDirectory;
1040 fDebugStreamer = new TTreeSRedirector("deb2.root");
1041 if ( backup ) backup->cd(); //we don't want to be cd'd to the debug streamer
1044 while ( iChannel > (fROC->GetRowIndexes(iSec)[row]+fROC->GetNPads(iSec,row)-1) ) row++;
1045 pad = iChannel-fROC->GetRowIndexes(iSec)[row];
1046 padc = pad-(fROC->GetNPads(iSec,row)/2);
1048 (*fDebugStreamer) << "DataEnd" <<
1049 "Sector=" << iSec <<
1053 "PadSec=" << iChannel <<
1055 "T0=" << cogTime0 <<
1064 delete fDebugStreamer;
1065 fDebugStreamer = 0x0;
1067 //_____________________________________________________________________
1068 void AliTPCCalibPulser::DumpToFile(const Char_t *filename, const Char_t *dir, Bool_t append)
1071 // Write class to file
1080 option = "recreate";
1082 TDirectory *backup = gDirectory;
1083 TFile f(filename,option.Data());
1085 if ( !sDir.IsNull() ){
1086 f.mkdir(sDir.Data());
1092 if ( backup ) backup->cd();
1094 //_____________________________________________________________________
1095 //_________________________ Test Functions ___________________________
1096 //_____________________________________________________________________
1097 TObjArray* AliTPCCalibPulser::TestBinning()
1100 // Function to test the binning of the reference histograms
1101 // type: T0, Q or RMS
1102 // mode: 0 - number of filled bins per channel
1103 // 1 - number of empty bins between filled bins in one ROC
1104 // returns TObjArray with the test histograms type*2+mode:
1105 // position 0 = T0,0 ; 1 = T0,1 ; 2 = Q,0 ...
1108 TObjArray *histArray = new TObjArray(6);
1109 const Char_t *type[] = {"T0","Q","RMS"};
1110 Int_t fNbins[3] = {fNbinsT0,fNbinsQ,fNbinsRMS};
1112 for (Int_t itype = 0; itype<3; ++itype){
1113 for (Int_t imode=0; imode<2; ++imode){
1114 Int_t icount = itype*2+imode;
1115 histArray->AddAt(new TH1F(Form("hTestBinning%s%d",type[itype],imode),
1116 Form("Test Binning of '%s', mode - %d",type[itype],imode),
1125 for (Int_t itype = 0; itype<3; ++itype){
1126 for (Int_t iSec=0; iSec<72; ++iSec){
1127 if ( itype == 0 ) hRef = GetHistoT0(iSec);
1128 if ( itype == 1 ) hRef = GetHistoQ(iSec);
1129 if ( itype == 2 ) hRef = GetHistoRMS(iSec);
1130 if ( hRef == 0x0 ) continue;
1131 array = (hRef->GetArray());
1132 UInt_t nChannels = fROC->GetNChannels(iSec);
1135 for (UInt_t iChannel=0; iChannel<nChannels; ++iChannel){
1137 Int_t offset = (fNbins[itype]+2)*(iChannel+1)+1;
1140 for (Int_t iBin=0; iBin<fNbins[itype]; ++iBin){
1141 if ( array[offset+iBin]>0 ) {
1143 if ( c1 && c2 ) nempty++;
1146 else if ( c1 ) c2 = 1;
1149 ((TH1F*)histArray->At(itype*2))->Fill(nfilled);
1151 ((TH1F*)histArray->At(itype*2+1))->Fill(iSec,nempty);