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 **************************************************************************/
18 /////////////////////////////////////////////////////////////////////////////////////////
20 // Implementation of the TPC pulser calibration //
22 // Origin: Jens Wiechula, Marian Ivanov J.Wiechula@gsi.de, Marian.Ivanov@cern.ch //
24 /////////////////////////////////////////////////////////////////////////////////////////
25 /***************************************************************************
27 ***************************************************************************
29 The AliTPCCalibPulser class is used to get calibration data concerning the FEE using
30 runs performed with the calibration pulser.
32 The information retrieved is
34 - Signal width differences
35 - Amplification variations
37 the seen differences arise from the manufacturing tolerances of the PASAs and are very small within
38 one chip and somewhat large between different chips.
41 For each ROC three TH2S histos 'Reference Histograms' (ROC channel vs. [Time0, signal width, Q sum]) is created when
42 it is filled for the first time (GetHisto[T0,RMS,Q](ROC,kTRUE)). The histos are stored in the
43 TObjArrays fHistoT0Array, fHistoRMSArray and fHistoQArray.
48 Raw calibration pulser data is processed by calling one of the ProcessEvent(...) functions
49 (see below). These in the end call the Update(...) function.
51 - the Update(...) function:
52 In this function the array fPadSignal is filled with the adc signals between the specified range
53 fFirstTimeBin and fLastTimeBin for the current pad.
54 before going to the next pad the ProcessPad() function is called, which analyses the data for one pad
57 - the ProcessPad() function:
58 Find Pedestal and Noise information
59 - use database information which has to be set by calling
60 SetPedestalDatabase(AliTPCCalPad *pedestalTPC, AliTPCCalPad *padNoiseTPC)
61 - if no information from the pedestal data base
62 is available the informaion is calculated on the fly ( see FindPedestal() function )
64 Find the Pulser signal information
65 - calculate mean = T0, RMS = signal width and Q sum in a range of -2+7 timebins around Q max
66 the Q sum is scaled by pad area
67 (see FindPulserSignal(...) function)
69 Fill a temprary array for the T0 information (GetPadTimesEvent(fCurrentSector,kTRUE)) (why see below)
70 Fill the Q sum and RMS values in the histograms (GetHisto[RMS,Q](ROC,kTRUE)),
72 At the end of each event the EndEvent() function is called
74 - the EndEvent() function:
75 calculate the mean T0 for each ROC and fill the Time0 histogram with Time0-<Time0 for ROC>
76 This is done to overcome syncronisation problems between the trigger and the fec clock.
78 After accumulating the desired statistics the Analyse() function has to be called.
79 - the Analyse() function
80 Whithin this function the mean values of T0, RMS, Q are calculated for each pad, using
81 the AliMathBase::GetCOG(...) function, and the calibration
82 storage classes (AliTPCCalROC) are filled for each ROC.
83 The calibration information is stored in the TObjArrays fCalRocArrayT0, fCalRocArrayRMS and
88 User interface for filling data:
89 --------------------------------
91 To Fill information one of the following functions can be used:
93 Bool_t ProcessEvent(eventHeaderStruct *event);
95 - use AliTPCRawReaderDate and call ProcessEvent(AliRawReader *rawReader)
97 Bool_t ProcessEvent(AliRawReader *rawReader);
98 - process AliRawReader event
99 - use AliTPCRawStream to loop over data and call ProcessEvent(AliTPCRawStream *rawStream)
101 Bool_t ProcessEvent(AliTPCRawStream *rawStream);
102 - process event from AliTPCRawStream
103 - call Update function for signal filling
105 Int_t Update(const Int_t isector, const Int_t iRow, const Int_t
106 iPad, const Int_t iTimeBin, const Float_t signal);
107 - directly fill signal information (sector, row, pad, time bin, pad)
108 to the reference histograms
110 It is also possible to merge two independently taken calibrations using the function
112 void Merge(AliTPCCalibPulser *sig)
113 - copy histograms in 'sig' if the do not exist in this instance
114 - Add histograms in 'sig' to the histograms in this instance if the allready exist
115 - After merging call Analyse again!
119 -- example: filling data using root raw data:
120 void fillSignal(Char_t *filename)
122 rawReader = new AliRawReaderRoot(fileName);
123 if ( !rawReader ) return;
124 AliTPCCalibPulser *calib = new AliTPCCalibPulser;
125 while (rawReader->NextEvent()){
126 calib->ProcessEvent(rawReader);
129 calib->DumpToFile("SignalData.root");
135 What kind of information is stored and how to retrieve them:
136 ------------------------------------------------------------
138 - Accessing the 'Reference Histograms' (Time0, signal width and Q sum information pad by pad):
140 TH2F *GetHistoT0(Int_t sector);
141 TH2F *GetHistoRMS(Int_t sector);
142 TH2F *GetHistoQ(Int_t sector);
144 - Accessing the calibration storage objects:
146 AliTPCCalROC *GetCalRocT0(Int_t sector); // for the Time0 values
147 AliTPCCalROC *GetCalRocRMS(Int_t sector); // for the signal width values
148 AliTPCCalROC *GetCalRocQ(Int_t sector); // for the Q sum values
150 example for visualisation:
151 if the file "SignalData.root" was created using the above example one could do the following:
153 TFile fileSignal("SignalData.root")
154 AliTPCCalibPulser *sig = (AliTPCCalibPulser*)fileSignal->Get("AliTPCCalibPulser");
155 sig->GetCalRocT0(0)->Draw("colz");
156 sig->GetCalRocRMS(0)->Draw("colz");
158 or use the AliTPCCalPad functionality:
159 AliTPCCalPad padT0(ped->GetCalPadT0());
160 AliTPCCalPad padSigWidth(ped->GetCalPadRMS());
161 padT0->MakeHisto2D()->Draw("colz"); //Draw A-Side Time0 Information
162 padSigWidth->MakeHisto2D()->Draw("colz"); //Draw A-Side signal width Information
167 #include <TObjArray.h>
171 #include <TVectorF.h>
174 #include <TDirectory.h>
180 #include "AliRawReader.h"
181 #include "AliRawReaderRoot.h"
182 #include "AliRawReaderDate.h"
183 #include "AliTPCRawStream.h"
184 #include "AliTPCCalROC.h"
185 #include "AliTPCCalPad.h"
186 #include "AliTPCROC.h"
187 #include "AliTPCParam.h"
188 #include "AliTPCCalibPulser.h"
189 #include "AliTPCcalibDB.h"
190 #include "AliMathBase.h"
191 #include "TTreeStream.h"
199 ClassImp(AliTPCCalibPulser)
201 AliTPCCalibPulser::AliTPCCalibPulser() :
215 fOldRCUformat(kTRUE),
216 fROC(AliTPCROC::Instance()),
217 fParam(new AliTPCParam),
225 fCalRocArrayOutliers(72),
229 fPadTimesArrayEvent(72),
231 fPadRMSArrayEvent(72),
232 fPadPedestalArrayEvent(72),
242 fVTime0OffsetCounter(72),
248 // AliTPCSignal default constructor
252 //_____________________________________________________________________
253 AliTPCCalibPulser::AliTPCCalibPulser(const AliTPCCalibPulser &sig) :
255 fFirstTimeBin(sig.fFirstTimeBin),
256 fLastTimeBin(sig.fLastTimeBin),
257 fNbinsT0(sig.fNbinsT0),
258 fXminT0(sig.fXminT0),
259 fXmaxT0(sig.fXmaxT0),
260 fNbinsQ(sig.fNbinsQ),
263 fNbinsRMS(sig.fNbinsRMS),
264 fXminRMS(sig.fXminRMS),
265 fXmaxRMS(sig.fXmaxRMS),
267 fOldRCUformat(kTRUE),
268 fROC(AliTPCROC::Instance()),
269 fParam(new AliTPCParam),
277 fCalRocArrayOutliers(72),
281 fPadTimesArrayEvent(72),
283 fPadRMSArrayEvent(72),
284 fPadPedestalArrayEvent(72),
294 fVTime0OffsetCounter(72),
297 fDebugLevel(sig.fDebugLevel)
300 // AliTPCSignal default constructor
303 for (Int_t iSec = 0; iSec < 72; ++iSec){
304 const AliTPCCalROC *calQ = (AliTPCCalROC*)sig.fCalRocArrayQ.UncheckedAt(iSec);
305 const AliTPCCalROC *calT0 = (AliTPCCalROC*)sig.fCalRocArrayT0.UncheckedAt(iSec);
306 const AliTPCCalROC *calRMS = (AliTPCCalROC*)sig.fCalRocArrayRMS.UncheckedAt(iSec);
307 const AliTPCCalROC *calOut = (AliTPCCalROC*)sig.fCalRocArrayOutliers.UncheckedAt(iSec);
309 const TH2S *hQ = (TH2S*)sig.fHistoQArray.UncheckedAt(iSec);
310 const TH2S *hT0 = (TH2S*)sig.fHistoT0Array.UncheckedAt(iSec);
311 const TH2S *hRMS = (TH2S*)sig.fHistoRMSArray.UncheckedAt(iSec);
313 if ( calQ != 0x0 ) fCalRocArrayQ.AddAt(new AliTPCCalROC(*calQ), iSec);
314 if ( calT0 != 0x0 ) fCalRocArrayT0.AddAt(new AliTPCCalROC(*calT0), iSec);
315 if ( calRMS != 0x0 ) fCalRocArrayRMS.AddAt(new AliTPCCalROC(*calRMS), iSec);
316 if ( calOut != 0x0 ) fCalRocArrayOutliers.AddAt(new AliTPCCalROC(*calOut), iSec);
319 TH2S *hNew = new TH2S(*hQ);
320 hNew->SetDirectory(0);
321 fHistoQArray.AddAt(hNew,iSec);
324 TH2S *hNew = new TH2S(*hT0);
325 hNew->SetDirectory(0);
326 fHistoQArray.AddAt(hNew,iSec);
329 TH2S *hNew = new TH2S(*hRMS);
330 hNew->SetDirectory(0);
331 fHistoQArray.AddAt(hNew,iSec);
336 //_____________________________________________________________________
337 AliTPCCalibPulser& AliTPCCalibPulser::operator = (const AliTPCCalibPulser &source)
340 // assignment operator
342 if (&source == this) return *this;
343 new (this) AliTPCCalibPulser(source);
347 //_____________________________________________________________________
348 AliTPCCalibPulser::~AliTPCCalibPulser()
354 fCalRocArrayT0.Delete();
355 fCalRocArrayQ.Delete();
356 fCalRocArrayRMS.Delete();
357 fCalRocArrayOutliers.Delete();
359 fHistoQArray.Delete();
360 fHistoT0Array.Delete();
361 fHistoRMSArray.Delete();
363 fPadTimesArrayEvent.Delete();
364 fPadQArrayEvent.Delete();
365 fPadRMSArrayEvent.Delete();
366 fPadPedestalArrayEvent.Delete();
368 if ( fDebugStreamer) delete fDebugStreamer;
372 //_____________________________________________________________________
373 Int_t AliTPCCalibPulser::Update(const Int_t icsector,
376 const Int_t icTimeBin,
377 const Float_t csignal)
380 // Signal filling methode on the fly pedestal and time offset correction if necessary.
381 // no extra analysis necessary. Assumes knowledge of the signal shape!
382 // assumes that it is looped over consecutive time bins of one pad
384 if ( (icTimeBin>fLastTimeBin) || (icTimeBin<fFirstTimeBin) ) return 0;
386 Int_t iChannel = fROC->GetRowIndexes(icsector)[icRow]+icPad; // global pad position in sector
388 //init first pad and sector in this event
389 if ( fCurrentChannel == -1 ) {
390 fCurrentChannel = iChannel;
391 fCurrentSector = icsector;
395 //process last pad if we change to a new one
396 if ( iChannel != fCurrentChannel ){
398 fCurrentChannel = iChannel;
399 fCurrentSector = icsector;
403 //fill signals for current pad
404 fPadSignal[icTimeBin]=csignal;
405 if ( csignal > fMaxPadSignal ){
406 fMaxPadSignal = csignal;
407 fMaxTimeBin = icTimeBin;
411 //_____________________________________________________________________
412 void AliTPCCalibPulser::FindPedestal(Float_t part)
415 // find pedestal and noise for the current pad. Use either database or
416 // truncated mean with part*100%
418 Bool_t noPedestal = kTRUE;;
419 if (fPedestalTPC&&fPadNoiseTPC){
420 //use pedestal database
421 //only load new pedestals if the sector has changed
422 if ( fCurrentSector!=fLastSector ){
423 fPedestalROC = fPedestalTPC->GetCalROC(fCurrentSector);
424 fPadNoiseROC = fPadNoiseTPC->GetCalROC(fCurrentSector);
425 fLastSector=fCurrentSector;
428 if ( fPedestalROC&&fPadNoiseROC ){
429 fPadPedestal = fPedestalROC->GetValue(fCurrentChannel);
430 fPadNoise = fPadNoiseROC->GetValue(fCurrentChannel);
436 //if we are not running with pedestal database, or for the current sector there is no information
437 //available, calculate the pedestal and noise on the fly
439 const Int_t kPedMax = 100; //maximum pedestal value
448 UShort_t histo[kPedMax];
449 memset(histo,0,kPedMax*sizeof(UShort_t));
451 for (Int_t i=fFirstTimeBin; i<=fLastTimeBin; ++i){
452 padSignal = fPadSignal.GetMatrixArray()[i];
453 if (padSignal<=0) continue;
454 if (padSignal>max && i>10) {
458 if (padSignal>kPedMax-1) continue;
459 histo[Int_t(padSignal+0.5)]++;
463 for (Int_t i=1; i<kPedMax; ++i){
464 if (count1<count0*0.5) median=i;
469 Float_t count=histo[median] ,mean=histo[median]*median, rms=histo[median]*median*median ;
471 for (Int_t idelta=1; idelta<10; ++idelta){
472 if (median-idelta<=0) continue;
473 if (median+idelta>kPedMax) continue;
474 if (count<part*count1){
475 count+=histo[median-idelta];
476 mean +=histo[median-idelta]*(median-idelta);
477 rms +=histo[median-idelta]*(median-idelta)*(median-idelta);
478 count+=histo[median+idelta];
479 mean +=histo[median+idelta]*(median+idelta);
480 rms +=histo[median+idelta]*(median+idelta)*(median+idelta);
487 rms = TMath::Sqrt(TMath::Abs(rms/count-mean*mean));
493 //_____________________________________________________________________
494 void AliTPCCalibPulser::FindPulserSignal(TVectorD ¶m, Float_t &qSum)
497 // Find position, signal width and height of the CE signal (last signal)
498 // param[0] = Qmax, param[1] = mean time, param[2] = rms;
499 // maxima: array of local maxima of the pad signal use the one closest to the mean CE position
502 Float_t ceQmax =0, ceQsum=0, ceTime=0, ceRMS=0;
503 Int_t cemaxpos = fMaxTimeBin;
504 Float_t ceSumThreshold = 8.*fPadNoise; // threshold for the signal sum
505 const Int_t kCemin = 2; // range for the analysis of the ce signal +- channels from the peak
506 const Int_t kCemax = 7;
509 ceQmax = fPadSignal.GetMatrixArray()[cemaxpos]-fPadPedestal;
510 for (Int_t i=cemaxpos-kCemin; i<cemaxpos+kCemax; ++i){
511 Float_t signal = fPadSignal.GetMatrixArray()[i]-fPadPedestal;
512 if ( (i>fFirstTimeBin) && (i<fLastTimeBin) && (signal>0) ){
513 ceTime+=signal*(i+0.5);
514 ceRMS +=signal*(i+0.5)*(i+0.5);
519 if (ceQmax&&ceQsum>ceSumThreshold) {
521 ceRMS = TMath::Sqrt(TMath::Abs(ceRMS/ceQsum-ceTime*ceTime));
522 fVTime0Offset.GetMatrixArray()[fCurrentSector]+=ceTime; // mean time for each sector
523 fVTime0OffsetCounter.GetMatrixArray()[fCurrentSector]++;
525 //Normalise Q to the pad area
526 Float_t norm = fParam->GetPadPitchWidth(fCurrentSector)*fParam->GetPadPitchLength(fCurrentSector,fCurrentRow);
540 //_____________________________________________________________________
541 void AliTPCCalibPulser::ProcessPad()
544 // Process data of current pad
550 FindPulserSignal(param, qSum);
552 Double_t meanT = param[1];
553 Double_t sigmaT = param[2];
555 //Fill Event T0 counter
556 (*GetPadTimesEvent(fCurrentSector,kTRUE)).GetMatrixArray()[fCurrentChannel] = meanT;
559 GetHistoQ(fCurrentSector,kTRUE)->Fill( TMath::Sqrt(qSum), fCurrentChannel );
562 GetHistoRMS(fCurrentSector,kTRUE)->Fill( sigmaT, fCurrentChannel );
565 //Fill debugging info
566 if ( fDebugLevel>0 ){
567 (*GetPadPedestalEvent(fCurrentSector,kTRUE))[fCurrentChannel]=fPadPedestal;
568 (*GetPadRMSEvent(fCurrentSector,kTRUE))[fCurrentChannel]=sigmaT;
569 (*GetPadQEvent(fCurrentSector,kTRUE))[fCurrentChannel]=qSum;
573 //_____________________________________________________________________
574 void AliTPCCalibPulser::EndEvent()
577 // Process data of current event
580 //check if last pad has allready been processed, if not do so
581 if ( fMaxTimeBin>-1 ) ProcessPad();
583 //loop over all ROCs, fill Time0 histogram corrected for the mean Time0 of each ROC
584 for ( Int_t iSec = 0; iSec<72; ++iSec ){
585 TVectorF *vTimes = GetPadTimesEvent(iSec);
586 if ( !vTimes ) continue;
588 for ( UInt_t iChannel=0; iChannel<fROC->GetNChannels(iSec); ++iChannel ){
589 Float_t time0 = fVTime0Offset[iSec]/fVTime0OffsetCounter[iSec];
590 Float_t time = (*vTimes).GetMatrixArray()[iChannel];
592 GetHistoT0(iSec,kTRUE)->Fill( time-time0,iChannel );
596 if ( fDebugLevel>0 ){
597 if ( !fDebugStreamer ) {
599 TDirectory *backup = gDirectory;
600 fDebugStreamer = new TTreeSRedirector("deb2.root");
601 if ( backup ) backup->cd(); //we don't want to be cd'd to the debug streamer
608 Float_t q = (*GetPadQEvent(iSec)).GetMatrixArray()[iChannel];
609 Float_t rms = (*GetPadRMSEvent(iSec)).GetMatrixArray()[iChannel];
611 UInt_t channel=iChannel;
614 while ( channel > (fROC->GetRowIndexes(sector)[row]+fROC->GetNPads(sector,row)-1) ) row++;
615 pad = channel-fROC->GetRowIndexes(sector)[row];
616 padc = pad-(fROC->GetNPads(sector,row)/2);
618 TH1F *h1 = new TH1F(Form("hSignalD%d.%d.%d",sector,row,pad),
619 Form("hSignalD%d.%d.%d",sector,row,pad),
620 fLastTimeBin-fFirstTimeBin,
621 fFirstTimeBin,fLastTimeBin);
624 for (Int_t i=fFirstTimeBin; i<fLastTimeBin+1; ++i)
625 h1->Fill(i,fPadSignal(i));
627 (*fDebugStreamer) << "DataPad" <<
628 // "Event=" << fEvent <<
629 "Sector="<< sector <<
633 "PadSec="<< channel <<
649 //_____________________________________________________________________
650 Bool_t AliTPCCalibPulser::ProcessEvent(AliTPCRawStream *rawStream)
653 // Event Processing loop - AliTPCRawStream
656 rawStream->SetOldRCUFormat(fOldRCUformat);
660 Bool_t withInput = kFALSE;
662 while (rawStream->Next()) {
664 Int_t isector = rawStream->GetSector(); // current sector
665 Int_t iRow = rawStream->GetRow(); // current row
666 Int_t iPad = rawStream->GetPad(); // current pad
667 Int_t iTimeBin = rawStream->GetTime(); // current time bin
668 Float_t signal = rawStream->GetSignal(); // current ADC signal
670 Update(isector,iRow,iPad,iTimeBin,signal);
680 //_____________________________________________________________________
681 Bool_t AliTPCCalibPulser::ProcessEvent(AliRawReader *rawReader)
684 // Event processing loop - AliRawReader
688 AliTPCRawStream rawStream(rawReader);
690 rawReader->Select("TPC");
692 return ProcessEvent(&rawStream);
694 //_____________________________________________________________________
695 Bool_t AliTPCCalibPulser::ProcessEvent(eventHeaderStruct *event)
698 // Event processing loop - date event
700 AliRawReader *rawReader = new AliRawReaderDate((void*)event);
701 Bool_t result=ProcessEvent(rawReader);
706 //_____________________________________________________________________
707 TH2S* AliTPCCalibPulser::GetHisto(Int_t sector, TObjArray *arr,
708 Int_t nbinsY, Float_t ymin, Float_t ymax,
709 Char_t *type, Bool_t force)
712 // return pointer to Q histogram
713 // if force is true create a new histogram if it doesn't exist allready
715 if ( !force || arr->UncheckedAt(sector) )
716 return (TH2S*)arr->UncheckedAt(sector);
718 // if we are forced and histogram doesn't yes exist create it
719 Char_t name[255], title[255];
721 sprintf(name,"hCalib%s%.2d",type,sector);
722 sprintf(title,"%s calibration histogram sector %.2d",type,sector);
724 // new histogram with Q calib information. One value for each pad!
725 TH2S* hist = new TH2S(name,title,
727 fROC->GetNChannels(sector),0,fROC->GetNChannels(sector));
728 hist->SetDirectory(0);
729 arr->AddAt(hist,sector);
732 //_____________________________________________________________________
733 TH2S* AliTPCCalibPulser::GetHistoT0(Int_t sector, Bool_t force)
736 // return pointer to T0 histogram
737 // if force is true create a new histogram if it doesn't exist allready
739 TObjArray *arr = &fHistoT0Array;
740 return GetHisto(sector, arr, fNbinsT0, fXminT0, fXmaxT0, "T0", force);
742 //_____________________________________________________________________
743 TH2S* AliTPCCalibPulser::GetHistoQ(Int_t sector, Bool_t force)
746 // return pointer to Q histogram
747 // if force is true create a new histogram if it doesn't exist allready
749 TObjArray *arr = &fHistoQArray;
750 return GetHisto(sector, arr, fNbinsQ, fXminQ, fXmaxQ, "Q", force);
752 //_____________________________________________________________________
753 TH2S* AliTPCCalibPulser::GetHistoRMS(Int_t sector, Bool_t force)
756 // return pointer to Q histogram
757 // if force is true create a new histogram if it doesn't exist allready
759 TObjArray *arr = &fHistoRMSArray;
760 return GetHisto(sector, arr, fNbinsRMS, fXminRMS, fXmaxRMS, "RMS", force);
762 //_____________________________________________________________________
763 TVectorF* AliTPCCalibPulser::GetPadInfoEvent(Int_t sector, TObjArray *arr, Bool_t force)
766 // return pointer to Pad Info from 'arr' for the current event and sector
767 // if force is true create it if it doesn't exist allready
769 if ( !force || arr->UncheckedAt(sector) )
770 return (TVectorF*)arr->UncheckedAt(sector);
772 TVectorF *vect = new TVectorF(fROC->GetNChannels(sector));
773 arr->AddAt(vect,sector);
776 //_____________________________________________________________________
777 TVectorF* AliTPCCalibPulser::GetPadTimesEvent(Int_t sector, Bool_t force)
780 // return pointer to Pad Times Array for the current event and sector
781 // if force is true create it if it doesn't exist allready
783 TObjArray *arr = &fPadTimesArrayEvent;
784 return GetPadInfoEvent(sector,arr,force);
786 //_____________________________________________________________________
787 TVectorF* AliTPCCalibPulser::GetPadQEvent(Int_t sector, Bool_t force)
790 // return pointer to Pad Q Array for the current event and sector
791 // if force is true create it if it doesn't exist allready
792 // for debugging purposes only
795 TObjArray *arr = &fPadQArrayEvent;
796 return GetPadInfoEvent(sector,arr,force);
798 //_____________________________________________________________________
799 TVectorF* AliTPCCalibPulser::GetPadRMSEvent(Int_t sector, Bool_t force)
802 // return pointer to Pad RMS Array for the current event and sector
803 // if force is true create it if it doesn't exist allready
804 // for debugging purposes only
806 TObjArray *arr = &fPadRMSArrayEvent;
807 return GetPadInfoEvent(sector,arr,force);
809 //_____________________________________________________________________
810 TVectorF* AliTPCCalibPulser::GetPadPedestalEvent(Int_t sector, Bool_t force)
813 // return pointer to Pad RMS Array for the current event and sector
814 // if force is true create it if it doesn't exist allready
815 // for debugging purposes only
817 TObjArray *arr = &fPadPedestalArrayEvent;
818 return GetPadInfoEvent(sector,arr,force);
820 //_____________________________________________________________________
821 AliTPCCalROC* AliTPCCalibPulser::GetCalRoc(Int_t sector, TObjArray* arr, Bool_t force) const
824 // return pointer to ROC Calibration
825 // if force is true create a new histogram if it doesn't exist allready
827 if ( !force || arr->UncheckedAt(sector) )
828 return (AliTPCCalROC*)arr->UncheckedAt(sector);
830 // if we are forced and histogram doesn't yes exist create it
832 // new AliTPCCalROC for T0 information. One value for each pad!
833 AliTPCCalROC *croc = new AliTPCCalROC(sector);
834 arr->AddAt(croc,sector);
837 //_____________________________________________________________________
838 AliTPCCalROC* AliTPCCalibPulser::GetCalRocT0(Int_t sector, Bool_t force)
841 // return pointer to Carge ROC Calibration
842 // if force is true create a new histogram if it doesn't exist allready
844 TObjArray *arr = &fCalRocArrayT0;
845 return GetCalRoc(sector, arr, force);
847 //_____________________________________________________________________
848 AliTPCCalROC* AliTPCCalibPulser::GetCalRocQ(Int_t sector, Bool_t force)
851 // return pointer to T0 ROC Calibration
852 // if force is true create a new histogram if it doesn't exist allready
854 TObjArray *arr = &fCalRocArrayQ;
855 return GetCalRoc(sector, arr, force);
857 //_____________________________________________________________________
858 AliTPCCalROC* AliTPCCalibPulser::GetCalRocRMS(Int_t sector, Bool_t force)
861 // return pointer to signal width ROC Calibration
862 // if force is true create a new histogram if it doesn't exist allready
864 TObjArray *arr = &fCalRocArrayRMS;
865 return GetCalRoc(sector, arr, force);
867 //_____________________________________________________________________
868 AliTPCCalROC* AliTPCCalibPulser::GetCalRocOutliers(Int_t sector, Bool_t force)
871 // return pointer to Outliers
872 // if force is true create a new histogram if it doesn't exist allready
874 TObjArray *arr = &fCalRocArrayOutliers;
875 return GetCalRoc(sector, arr, force);
877 //_____________________________________________________________________
878 void AliTPCCalibPulser::ResetEvent()
881 // Reset global counters -- Should be called before each event is processed
890 fPadTimesArrayEvent.Delete();
891 fPadQArrayEvent.Delete();
892 fPadRMSArrayEvent.Delete();
893 fPadPedestalArrayEvent.Delete();
895 for ( Int_t i=0; i<72; ++i ){
897 fVTime0OffsetCounter[i]=0;
900 //_____________________________________________________________________
901 void AliTPCCalibPulser::ResetPad()
904 // Reset pad infos -- Should be called after a pad has been processed
906 for (Int_t i=fFirstTimeBin; i<fLastTimeBin+1; ++i)
913 //_____________________________________________________________________
914 void AliTPCCalibPulser::Merge(AliTPCCalibPulser *sig)
917 // Merge reference histograms of sig to the current AliTPCCalibPulser
921 for (Int_t iSec=0; iSec<72; ++iSec){
922 TH2S *hRefQmerge = sig->GetHistoQ(iSec);
923 TH2S *hRefT0merge = sig->GetHistoT0(iSec);
924 TH2S *hRefRMSmerge = sig->GetHistoRMS(iSec);
928 TDirectory *dir = hRefQmerge->GetDirectory(); hRefQmerge->SetDirectory(0);
929 TH2S *hRefQ = GetHistoQ(iSec);
930 if ( hRefQ ) hRefQ->Add(hRefQmerge);
932 TH2S *hist = new TH2S(*hRefQmerge);
933 hist->SetDirectory(0);
934 fHistoQArray.AddAt(hist, iSec);
936 hRefQmerge->SetDirectory(dir);
939 TDirectory *dir = hRefT0merge->GetDirectory(); hRefT0merge->SetDirectory(0);
940 TH2S *hRefT0 = GetHistoT0(iSec);
941 if ( hRefT0 ) hRefT0->Add(hRefT0merge);
943 TH2S *hist = new TH2S(*hRefT0merge);
944 hist->SetDirectory(0);
945 fHistoT0Array.AddAt(hist, iSec);
947 hRefT0merge->SetDirectory(dir);
950 TDirectory *dir = hRefRMSmerge->GetDirectory(); hRefRMSmerge->SetDirectory(0);
951 TH2S *hRefRMS = GetHistoRMS(iSec);
952 if ( hRefRMS ) hRefRMS->Add(hRefRMSmerge);
954 TH2S *hist = new TH2S(*hRefRMSmerge);
955 hist->SetDirectory(0);
956 fHistoRMSArray.AddAt(hist, iSec);
958 hRefRMSmerge->SetDirectory(dir);
963 //_____________________________________________________________________
964 void AliTPCCalibPulser::Analyse()
967 // Calculate calibration constants
972 TVectorD paramRMS(3);
975 for (Int_t iSec=0; iSec<72; ++iSec){
976 TH2S *hT0 = GetHistoT0(iSec);
979 AliTPCCalROC *rocQ = GetCalRocQ (iSec,kTRUE);
980 AliTPCCalROC *rocT0 = GetCalRocT0 (iSec,kTRUE);
981 AliTPCCalROC *rocRMS = GetCalRocRMS(iSec,kTRUE);
982 AliTPCCalROC *rocOut = GetCalRocOutliers(iSec,kTRUE);
984 TH2S *hQ = GetHistoQ(iSec);
985 TH2S *hRMS = GetHistoRMS(iSec);
987 Short_t *arrayhQ = hQ->GetArray();
988 Short_t *arrayhT0 = hT0->GetArray();
989 Short_t *arrayhRMS = hRMS->GetArray();
991 UInt_t nChannels = fROC->GetNChannels(iSec);
999 for (UInt_t iChannel=0; iChannel<nChannels; ++iChannel){
1002 Float_t cogTime0 = -1000;
1003 Float_t cogQ = -1000;
1004 Float_t cogRMS = -1000;
1008 Int_t offsetQ = (fNbinsQ+2)*(iChannel+1)+1;
1009 Int_t offsetT0 = (fNbinsT0+2)*(iChannel+1)+1;
1010 Int_t offsetRMS = (fNbinsRMS+2)*(iChannel+1)+1;
1013 AliMathBase::FitGaus(arrayhQ+offsetQ,fNbinsQ,fXminQ,fXmaxQ,¶mQ,&dummy);
1014 AliMathBase::FitGaus(arrayhT0+offsetT0,fNbinsT0,fXminT0,fXmaxT0,¶mT0,&dummy);
1015 AliMathBase::FitGaus(arrayhRMS+offsetRMS,fNbinsRMS,fXminRMS,fXmaxRMS,¶mRMS,&dummy);
1017 cogTime0 = paramT0[1];
1018 cogRMS = paramRMS[1];
1020 cogQ = AliMathBase::GetCOG(arrayhQ+offsetQ,fNbinsQ,fXminQ,fXmaxQ);
1021 cogTime0 = AliMathBase::GetCOG(arrayhT0+offsetT0,fNbinsT0,fXminT0,fXmaxT0);
1022 cogRMS = AliMathBase::GetCOG(arrayhRMS+offsetRMS,fNbinsRMS,fXminRMS,fXmaxRMS);
1027 if ( (cogQ < ??) && (cogTime0 > ??) && (cogTime0<??) && ( cogRMS>??) ){
1034 rocQ->SetValue(iChannel, cogQ*cogQ);
1035 rocT0->SetValue(iChannel, cogTime0);
1036 rocRMS->SetValue(iChannel, cogRMS);
1037 rocOut->SetValue(iChannel, cogOut);
1041 if ( fDebugLevel > 0 ){
1042 if ( !fDebugStreamer ) {
1044 TDirectory *backup = gDirectory;
1045 fDebugStreamer = new TTreeSRedirector("deb2.root");
1046 if ( backup ) backup->cd(); //we don't want to be cd'd to the debug streamer
1049 while ( iChannel > (fROC->GetRowIndexes(iSec)[row]+fROC->GetNPads(iSec,row)-1) ) row++;
1050 pad = iChannel-fROC->GetRowIndexes(iSec)[row];
1051 padc = pad-(fROC->GetNPads(iSec,row)/2);
1053 (*fDebugStreamer) << "DataEnd" <<
1054 "Sector=" << iSec <<
1058 "PadSec=" << iChannel <<
1060 "T0=" << cogTime0 <<
1069 delete fDebugStreamer;
1070 fDebugStreamer = 0x0;
1072 //_____________________________________________________________________
1073 void AliTPCCalibPulser::DumpToFile(const Char_t *filename, const Char_t *dir, Bool_t append)
1076 // Write class to file
1085 option = "recreate";
1087 TDirectory *backup = gDirectory;
1088 TFile f(filename,option.Data());
1090 if ( !sDir.IsNull() ){
1091 f.mkdir(sDir.Data());
1097 if ( backup ) backup->cd();
1099 //_____________________________________________________________________
1100 //_________________________ Test Functions ___________________________
1101 //_____________________________________________________________________
1102 TObjArray* AliTPCCalibPulser::TestBinning()
1105 // Function to test the binning of the reference histograms
1106 // type: T0, Q or RMS
1107 // mode: 0 - number of filled bins per channel
1108 // 1 - number of empty bins between filled bins in one ROC
1109 // returns TObjArray with the test histograms type*2+mode:
1110 // position 0 = T0,0 ; 1 = T0,1 ; 2 = Q,0 ...
1113 TObjArray *histArray = new TObjArray(6);
1114 const Char_t *type[] = {"T0","Q","RMS"};
1115 Int_t fNbins[3] = {fNbinsT0,fNbinsQ,fNbinsRMS};
1117 for (Int_t itype = 0; itype<3; ++itype){
1118 for (Int_t imode=0; imode<2; ++imode){
1119 Int_t icount = itype*2+imode;
1120 histArray->AddAt(new TH1F(Form("hTestBinning%s%d",type[itype],imode),
1121 Form("Test Binning of '%s', mode - %d",type[itype],imode),
1130 for (Int_t itype = 0; itype<3; ++itype){
1131 for (Int_t iSec=0; iSec<72; ++iSec){
1132 if ( itype == 0 ) hRef = GetHistoT0(iSec);
1133 if ( itype == 1 ) hRef = GetHistoQ(iSec);
1134 if ( itype == 2 ) hRef = GetHistoRMS(iSec);
1135 if ( hRef == 0x0 ) continue;
1136 array = (hRef->GetArray());
1137 UInt_t nChannels = fROC->GetNChannels(iSec);
1140 for (UInt_t iChannel=0; iChannel<nChannels; ++iChannel){
1142 Int_t offset = (fNbins[itype]+2)*(iChannel+1)+1;
1145 for (Int_t iBin=0; iBin<fNbins[itype]; ++iBin){
1146 if ( array[offset+iBin]>0 ) {
1148 if ( c1 && c2 ) nempty++;
1151 else if ( c1 ) c2 = 1;
1154 ((TH1F*)histArray->At(itype*2))->Fill(nfilled);
1156 ((TH1F*)histArray->At(itype*2+1))->Fill(iSec,nempty);