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 Central Electrode calibration //
22 // Origin: Jens Wiechula, Marian Ivanov J.Wiechula@gsi.de, Marian.Ivanov@cern.ch //
24 ////////////////////////////////////////////////////////////////////////////////////////
27 // *************************************************************************************
28 // * Class Description *
29 // *************************************************************************************
32 <h4>The AliTPCCalibCE class is used to get calibration data from the Central Electrode
33 using laser runs.</h4>
35 The information retrieved is
36 <ul style="list-style-type: square;">
37 <li>Time arrival from the CE</li>
43 <ol style="list-style-type: upper-roman;">
44 <li><a href="#working">Working principle</a></li>
45 <li><a href="#user">User interface for filling data</a></li>
46 <li><a href="#info">Stored information</a></li>
49 <h3><a name="working">I. Working principle</a></h3>
51 <h4>Raw laser data is processed by calling one of the ProcessEvent(...) functions
52 (see below). These in the end call the Update(...) function.</h4>
54 <ul style="list-style-type: square;">
55 <li>the Update(...) function:<br />
56 In this function the array fPadSignal is filled with the adc signals between the specified range
57 fFirstTimeBin and fLastTimeBin for the current pad.
58 before going to the next pad the ProcessPad() function is called, which analyses the data for one pad
61 <ul style="list-style-type: square;">
62 <li>the ProcessPad() function:</li>
63 <ol style="list-style-type: decimal;">
64 <li>Find Pedestal and Noise information</li>
65 <ul style="list-style-type: square;">
66 <li>use database information which has to be set by calling<br />
67 SetPedestalDatabase(AliTPCCalPad *pedestalTPC, AliTPCCalPad *padNoiseTPC)</li>
68 <li>if no information from the pedestal data base
69 is available the informaion is calculated on the fly
70 ( see FindPedestal() function )</li>
72 <li>Find local maxima of the pad signal</li>
73 <ul style="list-style-type: square;">
74 <li>maxima arise from the laser tracks, the CE and also periodic postpeaks after the CE signal have
75 have been observed ( see FindLocalMaxima(...) )</li>
77 <li>Find the CE signal information</li>
78 <ul style="list-style-type: square;">
79 <li>to find the position of the CE signal the Tmean information from the previos event is used
80 as the CE signal the local maximum closest to this Tmean is identified</li>
81 <li>calculate mean = T0, RMS = signal width and Q sum in a range of -4+7 timebins around Q max position
82 the Q sum is scaled by pad area (see FindPulserSignal(...) function)</li>
84 <li>Fill a temprary array for the T0 information (GetPadTimesEvent(fCurrentSector,kTRUE)) (why see below)</li>
85 <li>Fill the Q sum and RMS values in the histograms (GetHisto[RMS,Q](ROC,kTRUE))</li>
90 <h4>At the end of each event the EndEvent() function is called</h4>
92 <ul style="list-style-type: square;">
93 <li>the EndEvent() function:</li>
94 <ul style="list-style-type: square;">
95 <li>calculate the mean T0 for side A and side C. Fill T0 histogram with Time0-<Time0 for side[A,C]>
96 This is done to overcome syncronisation problems between the trigger and the fec clock.</li>
97 <li>calculate Mean T for each ROC using the COG aroud the median of the LocalMaxima distribution in one sector</li>
98 <li>calculate Mean Q</li>
99 <li>calculate Global fit parameters for Pol1 and Pol2 fits</li>
103 <h4>After accumulating the desired statistics the Analyse() function has to be called.</h4>
104 <ul style="list-style-type: square;">
105 <li>the Analyse() function:</li>
106 <ul style="list-style-type: square;">
107 <li>calculate the mean values of T0, RMS, Q for each pad, using
108 the AliMathBase::GetCOG(...) function</li>
109 <li>fill the calibration storage classes (AliTPCCalROC) for each ROC</li>
110 (The calibration information is stored in the TObjArrays fCalRocArrayT0, fCalRocArrayRMS and fCalRocArrayQ</li>
114 <h3><a name="user">II. User interface for filling data</a></h3>
116 <h4>To Fill information one of the following functions can be used:</h4>
118 <ul style="list-style-type: none;">
119 <li> Bool_t ProcessEvent(eventHeaderStruct *event);</li>
120 <ul style="list-style-type: square;">
121 <li>process Date event</li>
122 <li>use AliTPCRawReaderDate and call ProcessEvent(AliRawReader *rawReader)</li>
126 <li> Bool_t ProcessEvent(AliRawReader *rawReader);</li>
127 <ul style="list-style-type: square;">
128 <li>process AliRawReader event</li>
129 <li>use AliTPCRawStream to loop over data and call ProcessEvent(AliTPCRawStream *rawStream)</li>
133 <li> Bool_t ProcessEvent(AliTPCRawStream *rawStream);</li>
134 <ul style="list-style-type: square;">
135 <li>process event from AliTPCRawStream</li>
136 <li>call Update function for signal filling</li>
140 <li> Int_t Update(const Int_t isector, const Int_t iRow, const Int_t
141 iPad, const Int_t iTimeBin, const Float_t signal);</li>
142 <ul style="list-style-type: square;">
143 <li>directly fill signal information (sector, row, pad, time bin, pad)
144 to the reference histograms</li>
148 <h4>It is also possible to merge two independently taken calibrations using the function</h4>
150 <ul style="list-style-type: none;">
151 <li> void Merge(AliTPCCalibSignal *sig)</li>
152 <ul style="list-style-type: square;">
153 <li>copy histograms in 'sig' if they do not exist in this instance</li>
154 <li>Add histograms in 'sig' to the histograms in this instance if the allready exist</li>
155 <li>After merging call Analyse again!</li>
160 <h4>example: filling data using root raw data:</h4>
162 void fillCE(Char_t *filename)
164 rawReader = new AliRawReaderRoot(fileName);
165 if ( !rawReader ) return;
166 AliTPCCalibCE *calib = new AliTPCCalibCE;
167 while (rawReader->NextEvent()){
168 calib->ProcessEvent(rawReader);
171 calib->DumpToFile("CEData.root");
177 <h3><a name="info">III. What kind of information is stored and how to retrieve it</a></h4>
179 <h4><a name="info:stored">III.1 Stored information</a></h4>
180 <ul style="list-style-type: none;">
182 <ul style="list-style-type: none;">
183 <li>For each ROC three TH2S histos 'Reference Histograms' (ROC channel vs. [Time0, signal width, Q sum])
184 is created when it is filled for the first time (GetHisto[T0,RMS,Q](ROC,kTRUE)). The histos are
185 stored in the TObjArrays fHistoT0Array, fHistoRMSArray and fHistoQArray.</li>
189 <li>Calibration Data:</li>
190 <ul style="list-style-type: none;">
191 <li>For each ROC three types of calibration data (AliTPCCalROC) is stored: for the mean arrival Time,
192 the signal width and the signal Sum. The AliTPCCalROC objects are stored in the TObjArrays
193 fCalRocArrayT0, fCalRocArrayRMS , fCalRocArrayQ. The object for each roc is created the first time it
194 is accessed (GetCalRoc[T0,RMS,Q](ROC,kTRUE));</li>
198 <li>For each event the following information is stored:</li>
200 <ul style="list-style-type: square;">
201 <li>event time ( TVectorD fVEventTime )</li>
202 <li>event id ( TVectorD fVEventNumber )</li>
204 <li>mean arrival time for each ROC ( TObjArray fTMeanArrayEvent )</li>
205 <li>mean Q for each ROC ( TObjArray fQMeanArrayEvent )</li>
206 <li>parameters of a plane fit for each ROC ( TObjArray fParamArrayEventPol1 )</li>
207 <li>parameters of a 2D parabola fit for each ROC ( TObjArray fParamArrayEventPol2 )</li>
211 <h4><a name="info:retrieve">III.2 Retrieving information</a></h4>
212 <ul style="list-style-type: none;">
213 <li>Accessing the 'Reference Histograms' (Time0, signal width and Q sum information pad by pad):</li>
214 <ul style="list-style-type: square;">
215 <li>TH2F *GetHistoT0(Int_t sector);</li>
216 <li>TH2F *GetHistoRMS(Int_t sector);</li>
217 <li>TH2F *GetHistoQ(Int_t sector);</li>
221 <li>Accessing the calibration storage objects:</li>
222 <ul style="list-style-type: square;">
223 <li>AliTPCCalROC *GetCalRocT0(Int_t sector); // for the Time0 values</li>
224 <li>AliTPCCalROC *GetCalRocRMS(Int_t sector); // for the signal width values</li>
225 <li>AliTPCCalROC *GetCalRocQ(Int_t sector); // for the Q sum values</li>
229 <li>Accessin the event by event information:</li>
230 <ul style="list-style-type: square;">
231 <li>The event by event information can be displayed using the</li>
232 <li>MakeGraphTimeCE(Int_t sector, Int_t xVariable, Int_t fitType, Int_t fitParameter)</li>
233 <li>which creates a graph from the specified variables</li>
237 <h4>example for visualisation:</h4>
239 //if the file "CEData.root" was created using the above example one could do the following:
240 TFile fileCE("CEData.root")
241 AliTPCCalibCE *ce = (AliTPCCalibCE*)fileCE->Get("AliTPCCalibCE");
242 ce->GetCalRocT0(0)->Draw("colz");
243 ce->GetCalRocRMS(0)->Draw("colz");
245 //or use the AliTPCCalPad functionality:
246 AliTPCCalPad padT0(ped->GetCalPadT0());
247 AliTPCCalPad padSigWidth(ped->GetCalPadRMS());
248 padT0->MakeHisto2D()->Draw("colz"); //Draw A-Side Time0 Information
249 padSigWidth->MakeHisto2D()->Draw("colz"); //Draw A-Side signal width Information
251 //display event by event information:
252 //Draw mean arrival time as a function of the event time for oroc sector A00
253 ce->MakeGraphTimeCE(36, 0, 2)->Draw("alp");
254 //Draw first derivative in local x from a plane fit as a function of the event time for oroc sector A00
255 ce->MakeGraphTimeCE(36, 0, 0, 1)->Draw("alp");
258 //////////////////////////////////////////////////////////////////////////////////////
262 #include <TObjArray.h>
266 #include <TVectorF.h>
267 #include <TVectorD.h>
268 #include <TMatrixD.h>
273 #include <TDirectory.h>
278 #include "AliRawReader.h"
279 #include "AliRawReaderRoot.h"
280 #include "AliRawReaderDate.h"
281 #include "AliRawEventHeaderBase.h"
282 #include "AliTPCRawStream.h"
283 #include "AliTPCRawStreamFast.h"
284 #include "AliTPCcalibDB.h"
285 #include "AliTPCCalROC.h"
286 #include "AliTPCCalPad.h"
287 #include "AliTPCROC.h"
288 #include "AliTPCParam.h"
289 #include "AliTPCCalibCE.h"
290 #include "AliMathBase.h"
291 #include "TTreeStream.h"
295 ClassImp(AliTPCCalibCE)
298 AliTPCCalibCE::AliTPCCalibCE() :
312 fOldRCUformat(kTRUE),
313 fROC(AliTPCROC::Instance()),
315 fParam(new AliTPCParam),
323 fCalRocArrayOutliers(72),
328 fParamArrayEventPol1(72),
329 fParamArrayEventPol2(72),
330 fTMeanArrayEvent(72),
331 fQMeanArrayEvent(72),
339 fPadTimesArrayEvent(72),
341 fPadRMSArrayEvent(72),
342 fPadPedestalArrayEvent(72),
352 fVTime0OffsetCounter(72),
360 // AliTPCSignal default constructor
362 // fHTime0 = new TH1F("hTime0Event","hTime0Event",(fLastTimeBin-fFirstTimeBin)*10,fFirstTimeBin,fLastTimeBin);
364 //_____________________________________________________________________
365 AliTPCCalibCE::AliTPCCalibCE(const AliTPCCalibCE &sig) :
367 fFirstTimeBin(sig.fFirstTimeBin),
368 fLastTimeBin(sig.fLastTimeBin),
369 fNbinsT0(sig.fNbinsT0),
370 fXminT0(sig.fXminT0),
371 fXmaxT0(sig.fXmaxT0),
372 fNbinsQ(sig.fNbinsQ),
375 fNbinsRMS(sig.fNbinsRMS),
376 fXminRMS(sig.fXminRMS),
377 fXmaxRMS(sig.fXmaxRMS),
379 fOldRCUformat(kTRUE),
380 fROC(AliTPCROC::Instance()),
382 fParam(new AliTPCParam),
390 fCalRocArrayOutliers(72),
395 fParamArrayEventPol1(72),
396 fParamArrayEventPol2(72),
397 fTMeanArrayEvent(72),
398 fQMeanArrayEvent(72),
401 fNevents(sig.fNevents),
406 fPadTimesArrayEvent(72),
408 fPadRMSArrayEvent(72),
409 fPadPedestalArrayEvent(72),
419 fVTime0OffsetCounter(72),
424 fDebugLevel(sig.fDebugLevel)
427 // AliTPCSignal copy constructor
430 for (Int_t iSec = 0; iSec < 72; ++iSec){
431 const AliTPCCalROC *calQ = (AliTPCCalROC*)sig.fCalRocArrayQ.UncheckedAt(iSec);
432 const AliTPCCalROC *calT0 = (AliTPCCalROC*)sig.fCalRocArrayT0.UncheckedAt(iSec);
433 const AliTPCCalROC *calRMS = (AliTPCCalROC*)sig.fCalRocArrayRMS.UncheckedAt(iSec);
434 const AliTPCCalROC *calOut = (AliTPCCalROC*)sig.fCalRocArrayOutliers.UncheckedAt(iSec);
436 const TH2S *hQ = (TH2S*)sig.fHistoQArray.UncheckedAt(iSec);
437 const TH2S *hT0 = (TH2S*)sig.fHistoT0Array.UncheckedAt(iSec);
438 const TH2S *hRMS = (TH2S*)sig.fHistoRMSArray.UncheckedAt(iSec);
440 if ( calQ != 0x0 ) fCalRocArrayQ.AddAt(new AliTPCCalROC(*calQ), iSec);
441 if ( calT0 != 0x0 ) fCalRocArrayT0.AddAt(new AliTPCCalROC(*calT0), iSec);
442 if ( calRMS != 0x0 ) fCalRocArrayRMS.AddAt(new AliTPCCalROC(*calRMS), iSec);
443 if ( calOut != 0x0 ) fCalRocArrayOutliers.AddAt(new AliTPCCalROC(*calOut), iSec);
446 // TDirectory *dir = hQ->GetDirectory();
447 // hQ->SetDirectory(0);
448 TH2S *hNew = new TH2S(*hQ);
449 hNew->SetDirectory(0);
450 fHistoQArray.AddAt(hNew,iSec);
451 // hQ->SetDirectory(dir);
454 // TDirectory *dir = hT0->GetDirectory();
455 // hT0->SetDirectory(0);
456 TH2S *hNew = new TH2S(*hT0);
457 hNew->SetDirectory(0);
458 fHistoT0Array.AddAt(hNew,iSec);
459 // hT0->SetDirectory(dir);
462 // TDirectory *dir = hRMS->GetDirectory();
463 // hRMS->SetDirectory(0);
464 TH2S *hNew = new TH2S(*hRMS);
465 hNew->SetDirectory(0);
466 fHistoRMSArray.AddAt(hNew,iSec);
467 // hRMS->SetDirectory(dir);
471 //copy fit parameters event by event
473 for (Int_t iSec=0; iSec<72; ++iSec){
474 arr = (TObjArray*)sig.fParamArrayEventPol1.UncheckedAt(iSec);
476 TObjArray *arrEvents = new TObjArray(arr->GetSize());
477 fParamArrayEventPol1.AddAt(arrEvents, iSec);
478 for (Int_t iEvent=0; iEvent<arr->GetSize(); ++iEvent)
479 if ( TVectorD *vec=(TVectorD*)arr->UncheckedAt(iEvent) )
480 arrEvents->AddAt(new TVectorD(*vec),iEvent);
483 arr = (TObjArray*)sig.fParamArrayEventPol2.UncheckedAt(iSec);
485 TObjArray *arrEvents = new TObjArray(arr->GetSize());
486 fParamArrayEventPol2.AddAt(arrEvents, iSec);
487 for (Int_t iEvent=0; iEvent<arr->GetSize(); ++iEvent)
488 if ( TVectorD *vec=(TVectorD*)arr->UncheckedAt(iEvent) )
489 arrEvents->AddAt(new TVectorD(*vec),iEvent);
492 TVectorF *vMeanTime = (TVectorF*)sig.fTMeanArrayEvent.UncheckedAt(iSec);
493 TVectorF *vMeanQ = (TVectorF*)sig.fQMeanArrayEvent.UncheckedAt(iSec);
495 fTMeanArrayEvent.AddAt(new TVectorF(*vMeanTime), iSec);
497 fQMeanArrayEvent.AddAt(new TVectorF(*vMeanQ), iSec);
501 fVEventTime.ResizeTo(sig.fVEventTime);
502 fVEventNumber.ResizeTo(sig.fVEventNumber);
503 fVEventTime.SetElements(sig.fVEventTime.GetMatrixArray());
504 fVEventNumber.SetElements(sig.fVEventNumber.GetMatrixArray());
507 //_____________________________________________________________________
508 AliTPCCalibCE& AliTPCCalibCE::operator = (const AliTPCCalibCE &source)
511 // assignment operator
513 if (&source == this) return *this;
514 new (this) AliTPCCalibCE(source);
518 //_____________________________________________________________________
519 AliTPCCalibCE::~AliTPCCalibCE()
525 fCalRocArrayT0.Delete();
526 fCalRocArrayQ.Delete();
527 fCalRocArrayRMS.Delete();
528 fCalRocArrayOutliers.Delete();
530 fHistoQArray.Delete();
531 fHistoT0Array.Delete();
532 fHistoRMSArray.Delete();
534 fHistoTmean.Delete();
536 fParamArrayEventPol1.Delete();
537 fParamArrayEventPol2.Delete();
538 fTMeanArrayEvent.Delete();
539 fQMeanArrayEvent.Delete();
541 fPadTimesArrayEvent.Delete();
542 fPadQArrayEvent.Delete();
543 fPadRMSArrayEvent.Delete();
544 fPadPedestalArrayEvent.Delete();
546 if ( fDebugStreamer) delete fDebugStreamer;
547 // if ( fHTime0 ) delete fHTime0;
551 //_____________________________________________________________________
552 Int_t AliTPCCalibCE::Update(const Int_t icsector,
555 const Int_t icTimeBin,
556 const Float_t csignal)
559 // Signal filling methode on the fly pedestal and Time offset correction if necessary.
560 // no extra analysis necessary. Assumes knowledge of the signal shape!
561 // assumes that it is looped over consecutive time bins of one pad
564 if (icRow<0) return 0;
565 if (icPad<0) return 0;
566 if (icTimeBin<0) return 0;
567 if ( (icTimeBin>fLastTimeBin) || (icTimeBin<fFirstTimeBin) ) return 0;
569 Int_t iChannel = fROC->GetRowIndexes(icsector)[icRow]+icPad; // global pad position in sector
571 //init first pad and sector in this event
572 if ( fCurrentChannel == -1 ) {
573 fCurrentChannel = iChannel;
574 fCurrentSector = icsector;
578 //process last pad if we change to a new one
579 if ( iChannel != fCurrentChannel ){
581 fCurrentChannel = iChannel;
582 fCurrentSector = icsector;
586 //fill signals for current pad
587 fPadSignal.GetMatrixArray()[icTimeBin]=csignal;
588 if ( csignal > fMaxPadSignal ){
589 fMaxPadSignal = csignal;
590 fMaxTimeBin = icTimeBin;
594 //_____________________________________________________________________
595 void AliTPCCalibCE::FindPedestal(Float_t part)
598 // find pedestal and noise for the current pad. Use either database or
599 // truncated mean with part*100%
601 Bool_t noPedestal = kTRUE;
603 //use pedestal database if set
604 if (fPedestalTPC&&fPadNoiseTPC){
605 //only load new pedestals if the sector has changed
606 if ( fCurrentSector!=fLastSector ){
607 fPedestalROC = fPedestalTPC->GetCalROC(fCurrentSector);
608 fPadNoiseROC = fPadNoiseTPC->GetCalROC(fCurrentSector);
609 fLastSector=fCurrentSector;
612 if ( fPedestalROC&&fPadNoiseROC ){
613 fPadPedestal = fPedestalROC->GetValue(fCurrentChannel);
614 fPadNoise = fPadNoiseROC->GetValue(fCurrentChannel);
620 //if we are not running with pedestal database, or for the current sector there is no information
621 //available, calculate the pedestal and noise on the fly
623 const Int_t kPedMax = 100; //maximum pedestal value
632 UShort_t histo[kPedMax];
633 memset(histo,0,kPedMax*sizeof(UShort_t));
635 //fill pedestal histogram
636 for (Int_t i=fFirstTimeBin; i<=fLastTimeBin; ++i){
637 padSignal = fPadSignal.GetMatrixArray()[i];
638 if (padSignal<=0) continue;
639 if (padSignal>max && i>10) {
643 if (padSignal>kPedMax-1) continue;
644 histo[int(padSignal+0.5)]++;
648 for (Int_t i=1; i<kPedMax; ++i){
649 if (count1<count0*0.5) median=i;
654 Float_t count=histo[median] ,mean=histo[median]*median, rms=histo[median]*median*median ;
656 for (Int_t idelta=1; idelta<10; ++idelta){
657 if (median-idelta<=0) continue;
658 if (median+idelta>kPedMax) continue;
659 if (count<part*count1){
660 count+=histo[median-idelta];
661 mean +=histo[median-idelta]*(median-idelta);
662 rms +=histo[median-idelta]*(median-idelta)*(median-idelta);
663 count+=histo[median+idelta];
664 mean +=histo[median+idelta]*(median+idelta);
665 rms +=histo[median+idelta]*(median+idelta)*(median+idelta);
672 rms = TMath::Sqrt(TMath::Abs(rms/count-mean*mean));
678 //_____________________________________________________________________
679 void AliTPCCalibCE::FindCESignal(TVectorD ¶m, Float_t &qSum, const TVectorF maxima)
682 // Find position, signal width and height of the CE signal (last signal)
683 // param[0] = Qmax, param[1] = mean time, param[2] = rms;
684 // maxima: array of local maxima of the pad signal use the one closest to the mean CE position
687 Float_t ceQmax =0, ceQsum=0, ceTime=0, ceRMS=0;
689 Float_t ceSumThreshold = 8.*fPadNoise; // threshold for the signal sum
690 const Int_t kCemin = 4; // range for the analysis of the ce signal +- channels from the peak
691 const Int_t kCemax = 7;
693 Float_t minDist = 25; //initial minimum distance betweek roc mean ce signal and pad ce signal
695 // find maximum closest to the sector mean from the last event
696 for ( Int_t imax=0; imax<maxima.GetNrows(); ++imax){
697 // get sector mean of last event
698 Float_t tmean = (*GetTMeanEvents(fCurrentSector))[fNevents-1];
699 if ( TMath::Abs( tmean-maxima[imax] ) < minDist ) {
700 minDist = tmean-maxima[imax];
701 cemaxpos = (Int_t)maxima[imax];
706 ceQmax = fPadSignal.GetMatrixArray()[cemaxpos]-fPadPedestal;
707 for (Int_t i=cemaxpos-kCemin; i<cemaxpos+kCemax; ++i){
708 if ( (i>fFirstTimeBin) && (i<fLastTimeBin) ){
709 Float_t signal = fPadSignal.GetMatrixArray()[i]-fPadPedestal;
711 ceTime+=signal*(i+0.5);
712 ceRMS +=signal*(i+0.5)*(i+0.5);
718 if (ceQmax&&ceQsum>ceSumThreshold) {
720 ceRMS = TMath::Sqrt(TMath::Abs(ceRMS/ceQsum-ceTime*ceTime));
721 fVTime0Offset.GetMatrixArray()[fCurrentSector]+=ceTime; // mean time for each sector
722 fVTime0OffsetCounter.GetMatrixArray()[fCurrentSector]++;
724 //Normalise Q to pad area of irocs
725 Float_t norm = fParam->GetPadPitchWidth(fCurrentSector)*fParam->GetPadPitchLength(fCurrentSector,fCurrentRow);
728 fVMeanQ.GetMatrixArray()[fCurrentSector]+=ceQsum;
729 fVMeanQCounter.GetMatrixArray()[fCurrentSector]++;
741 //_____________________________________________________________________
742 Bool_t AliTPCCalibCE::IsPeak(Int_t pos, Int_t tminus, Int_t tplus) const
745 // Check if 'pos' is a Maximum. Consider 'tminus' timebins before
746 // and 'tplus' timebins after 'pos'
748 if ( (pos-tminus)<fFirstTimeBin || (pos+tplus)>fLastTimeBin ) return kFALSE;
749 for (Int_t iTime = pos; iTime>pos-tminus; --iTime)
750 if ( fPadSignal[iTime-1] >= fPadSignal[iTime] ) return kFALSE;
751 for (Int_t iTime = pos, iTime2=pos; iTime<pos+tplus; ++iTime, ++iTime2){
752 if ( (iTime==pos) && (fPadSignal[iTime+1]==fPadSignal[iTime]) ) // allow two timebins with same adc value
754 if ( fPadSignal[iTime2+1] >= fPadSignal[iTime2] ) return kFALSE;
758 //_____________________________________________________________________
759 void AliTPCCalibCE::FindLocalMaxima(TVectorF &maxima)
762 // Find local maxima on the pad signal and Histogram them
764 Float_t ceThreshold = 5.*TMath::Max(fPadNoise,Float_t(1.)); // threshold for the signal
768 for (Int_t i=fLastTimeBin-tplus-1; i>=fFirstTimeBin+tminus; --i){
769 if ( (fPadSignal[i]-fPadPedestal)>ceThreshold && IsPeak(i,tminus,tplus) ){
770 if (count<maxima.GetNrows()){
771 maxima.GetMatrixArray()[count++]=i;
772 GetHistoTmean(fCurrentSector,kTRUE)->Fill(i);
777 //_____________________________________________________________________
778 void AliTPCCalibCE::ProcessPad()
781 // Process data of current pad
785 TVectorF maxima(15); // the expected maximum number of maxima in the complete TPC should be 8 laser beam layers
786 // + central electrode and possibly post peaks from the CE signal
787 // however if we are on a high noise pad a lot more peaks due to the noise might occur
788 FindLocalMaxima(maxima);
789 if ( (fNevents == 0) || (fOldRunNumber!=fRunNumber) ) return; // return because we don't have Time0 info for the CE yet
793 FindCESignal(param, qSum, maxima);
795 Double_t meanT = param[1];
796 Double_t sigmaT = param[2];
798 //Fill Event T0 counter
799 (*GetPadTimesEvent(fCurrentSector,kTRUE)).GetMatrixArray()[fCurrentChannel] = meanT;
802 GetHistoQ(fCurrentSector,kTRUE)->Fill( TMath::Sqrt(qSum), fCurrentChannel );
805 GetHistoRMS(fCurrentSector,kTRUE)->Fill( sigmaT, fCurrentChannel );
808 //Fill debugging info
809 if ( fDebugLevel>0 ){
810 (*GetPadPedestalEvent(fCurrentSector,kTRUE)).GetMatrixArray()[fCurrentChannel]=fPadPedestal;
811 (*GetPadRMSEvent(fCurrentSector,kTRUE)).GetMatrixArray()[fCurrentChannel]=sigmaT;
812 (*GetPadQEvent(fCurrentSector,kTRUE)).GetMatrixArray()[fCurrentChannel]=qSum;
817 //_____________________________________________________________________
818 void AliTPCCalibCE::EndEvent()
821 // Process data of current pad
822 // The Functions 'SetTimeStamp' and 'SetRunNumber' should be called
823 // before the EndEvent function to set the event timestamp and number!!!
824 // This is automatically done if the ProcessEvent(AliRawReader *rawReader)
825 // function was called
828 //check if last pad has allready been processed, if not do so
829 if ( fMaxTimeBin>-1 ) ProcessPad();
833 // TVectorF vMeanTime(72);
834 // TVectorF vMeanQ(72);
835 AliTPCCalROC *calIroc=new AliTPCCalROC(0);
836 AliTPCCalROC *calOroc=new AliTPCCalROC(36);
838 //find mean time0 offset for side A and C
839 Double_t time0Side[2]; //time0 for side A:0 and C:1
840 Double_t time0SideCount[2]; //time0 counter for side A:0 and C:1
841 time0Side[0]=0;time0Side[1]=0;time0SideCount[0]=0;time0SideCount[1]=0;
842 for ( Int_t iSec = 0; iSec<72; ++iSec ){
843 time0Side[(iSec/18)%2] += fVTime0Offset.GetMatrixArray()[iSec];
844 time0SideCount[(iSec/18)%2] += fVTime0OffsetCounter.GetMatrixArray()[iSec];
846 if ( time0SideCount[0] >0 )
847 time0Side[0]/=time0SideCount[0];
848 if ( time0SideCount[1] >0 )
849 time0Side[1]/=time0SideCount[1];
850 // end find time0 offset
852 //loop over all ROCs, fill CE Time histogram corrected for the mean Time0 of each ROC
853 for ( Int_t iSec = 0; iSec<72; ++iSec ){
854 //find median and then calculate the mean around it
855 TH1S *hMeanT = GetHistoTmean(iSec); //histogram with local maxima position information
856 if ( !hMeanT ) continue;
858 Double_t entries = hMeanT->GetEntries();
860 Short_t *arr = hMeanT->GetArray()+1;
862 for ( ibin=0; ibin<hMeanT->GetNbinsX(); ++ibin){
864 if ( sum>=(entries/2) ) break;
867 Int_t firstBin = fFirstTimeBin+ibin-delta;
868 Int_t lastBin = fFirstTimeBin+ibin+delta;
869 if ( firstBin<fFirstTimeBin ) firstBin=fFirstTimeBin;
870 if ( lastBin>fLastTimeBin ) lastBin =fLastTimeBin;
871 Float_t median =AliMathBase::GetCOG(arr+ibin-delta,2*delta,firstBin,lastBin);
873 // check boundaries for ebye info of mean time
874 TVectorF *vMeanTime=GetTMeanEvents(iSec,kTRUE);
875 Int_t vSize=vMeanTime->GetNrows();
876 if ( vSize < fNevents+1 )
877 vMeanTime->ResizeTo(vSize+100);
879 vMeanTime->GetMatrixArray()[fNevents]=median;
882 TVectorF *vTimes = GetPadTimesEvent(iSec);
883 if ( !vTimes ) continue; //continue if no time information for this sector is available
886 AliTPCCalROC calIrocOutliers(0);
887 AliTPCCalROC calOrocOutliers(36);
889 // calculate mean Q of the sector
891 if ( fVMeanQCounter.GetMatrixArray()[iSec]>0 ) meanQ=fVMeanQ.GetMatrixArray()[iSec]/fVMeanQCounter.GetMatrixArray()[iSec];
892 TVectorF *vMeanQ=GetQMeanEvents(iSec,kTRUE);
893 if ( vSize < fNevents+1 ) // vSize is the same as for vMeanTime!
894 vMeanQ->ResizeTo(vSize+100);
896 vMeanQ->GetMatrixArray()[fNevents]=meanQ;
898 for ( UInt_t iChannel=0; iChannel<fROC->GetNChannels(iSec); ++iChannel ){
899 Float_t time = (*vTimes).GetMatrixArray()[iChannel];
901 //set values for temporary roc calibration class
903 calIroc->SetValue(iChannel, time);
904 if ( time == 0 ) calIrocOutliers.SetValue(iChannel,1);
907 calOroc->SetValue(iChannel, time);
908 if ( time == 0 ) calOrocOutliers.SetValue(iChannel,1);
911 if ( (fNevents>0) && (fOldRunNumber==fRunNumber) )
912 GetHistoT0(iSec,kTRUE)->Fill( time-time0Side[(iSec/18)%2],iChannel );
916 //------------------------------- Debug start ------------------------------
917 if ( fDebugLevel>0 ){
918 if ( !fDebugStreamer ) {
920 TDirectory *backup = gDirectory;
921 fDebugStreamer = new TTreeSRedirector("debugCalibCE.root");
922 if ( backup ) backup->cd(); //we don't want to be cd'd to the debug streamer
929 Float_t q = (*GetPadQEvent(iSec))[iChannel];
930 Float_t rms = (*GetPadRMSEvent(iSec))[iChannel];
932 UInt_t channel=iChannel;
935 while ( channel > (fROC->GetRowIndexes(sector)[row]+fROC->GetNPads(sector,row)-1) ) row++;
936 pad = channel-fROC->GetRowIndexes(sector)[row];
937 padc = pad-(fROC->GetNPads(sector,row)/2);
939 // TH1F *h1 = new TH1F(Form("hSignalD%d.%d.%d",sector,row,pad),
940 // Form("hSignalD%d.%d.%d",sector,row,pad),
941 // fLastTimeBin-fFirstTimeBin,
942 // fFirstTimeBin,fLastTimeBin);
943 // h1->SetDirectory(0);
945 // for (Int_t i=fFirstTimeBin; i<fLastTimeBin+1; ++i)
946 // h1->Fill(i,fPadSignal(i));
949 if (fVTime0OffsetCounter.GetMatrixArray()[iSec]>0)
950 t0Sec = fVTime0Offset.GetMatrixArray()[iSec]/fVTime0OffsetCounter.GetMatrixArray()[iSec];
951 Double_t t0Side = time0Side[(iSec/18)%2];
952 (*fDebugStreamer) << "DataPad" <<
953 "Event=" << fNevents <<
954 "RunNumber=" << fRunNumber <<
955 "TimeStamp=" << fTimeStamp <<
956 "Sector="<< sector <<
960 "PadSec="<< channel <<
961 "Time0Sec=" << t0Sec <<
962 "Time0Side=" << t0Side <<
973 //----------------------------- Debug end ------------------------------
977 TVectorD paramPol1(3);
978 TVectorD paramPol2(6);
979 TMatrixD matPol1(3,3);
980 TMatrixD matPol2(6,6);
984 if ( (fNevents>0) && (fOldRunNumber==fRunNumber) ){
986 calIroc->GlobalFit(&calIrocOutliers,0,paramPol1,matPol1,chi2Pol1,0);
987 calIroc->GlobalFit(&calIrocOutliers,0,paramPol2,matPol2,chi2Pol2,1);
989 calOroc->GlobalFit(&calOrocOutliers,0,paramPol1,matPol1,chi2Pol1,0);
990 calOroc->GlobalFit(&calOrocOutliers,0,paramPol2,matPol2,chi2Pol2,1);
993 GetParamArrayPol1(iSec,kTRUE)->AddAtAndExpand(new TVectorD(paramPol1), fNevents);
994 GetParamArrayPol2(iSec,kTRUE)->AddAtAndExpand(new TVectorD(paramPol2), fNevents);
996 // printf("events: %d -- size: %d\n",fNevents,GetParamArrayPol1(iSec)->GetSize());
998 //------------------------------- Debug start ------------------------------
999 if ( fDebugLevel>0 ){
1000 if ( !fDebugStreamer ) {
1002 TDirectory *backup = gDirectory;
1003 fDebugStreamer = new TTreeSRedirector("debugCalibCE.root");
1004 if ( backup ) backup->cd(); //we don't want to be cd'd to the debug streamer
1006 (*fDebugStreamer) << "DataRoc" <<
1007 // "Event=" << fEvent <<
1008 "RunNumber=" << fRunNumber <<
1009 "TimeStamp=" << fTimeStamp <<
1011 "hMeanT.=" << hMeanT <<
1012 "median=" << median <<
1013 "paramPol1.=" << ¶mPol1 <<
1014 "paramPol2.=" << ¶mPol2 <<
1015 "matPol1.=" << &matPol1 <<
1016 "matPol2.=" << &matPol2 <<
1017 "chi2Pol1=" << chi2Pol1 <<
1018 "chi2Pol2=" << chi2Pol2 <<
1021 //------------------------------- Debug end ------------------------------
1024 // fTMeanArrayEvent.AddAtAndExpand(new TVectorF(vMeanTime),fNevents);
1025 // fQMeanArrayEvent.AddAtAndExpand(new TVectorF(vMeanQ),fNevents);
1026 if ( fVEventTime.GetNrows() < fNevents+1 ) {
1027 fVEventTime.ResizeTo((Int_t)(fVEventTime.GetNrows()+100));
1028 fVEventNumber.ResizeTo((Int_t)(fVEventNumber.GetNrows()+100));
1030 fVEventTime.GetMatrixArray()[fNevents] = fTimeStamp;
1031 fVEventNumber.GetMatrixArray()[fNevents] = fEventId;
1034 fOldRunNumber = fRunNumber;
1039 //_____________________________________________________________________
1040 Bool_t AliTPCCalibCE::ProcessEventFast(AliTPCRawStreamFast *rawStreamFast)
1043 // Event Processing loop - AliTPCRawStreamFast
1046 Bool_t withInput = kFALSE;
1047 while ( rawStreamFast->NextDDL() ){
1048 while ( rawStreamFast->NextChannel() ){
1049 Int_t isector = rawStreamFast->GetSector(); // current sector
1050 Int_t iRow = rawStreamFast->GetRow(); // current row
1051 Int_t iPad = rawStreamFast->GetPad(); // current pad
1052 Int_t startTbin = (Int_t)rawStreamFast->GetStartTimeBin();
1053 Int_t endTbin = (Int_t)rawStreamFast->GetEndTimeBin();
1055 while ( rawStreamFast->NextBunch() ){
1056 for (Int_t iTimeBin = startTbin; iTimeBin < endTbin; iTimeBin++){
1057 Float_t signal=(Float_t)rawStreamFast->GetSignals()[iTimeBin-startTbin];
1058 Update(isector,iRow,iPad,iTimeBin+1,signal);
1069 //_____________________________________________________________________
1070 Bool_t AliTPCCalibCE::ProcessEventFast(AliRawReader *rawReader)
1073 // Event processing loop using the fast raw stream algorithm- AliRawReader
1076 //printf("ProcessEventFast - raw reader\n");
1078 AliRawEventHeaderBase* eventHeader = (AliRawEventHeaderBase*)rawReader->GetEventHeader();
1080 fTimeStamp = eventHeader->Get("Timestamp");
1081 fRunNumber = eventHeader->Get("RunNb");
1083 fEventId = *rawReader->GetEventId();
1085 AliTPCRawStreamFast *rawStreamFast = new AliTPCRawStreamFast(rawReader, (AliAltroMapping**)fMapping);
1086 Bool_t res=ProcessEventFast(rawStreamFast);
1087 delete rawStreamFast;
1091 //_____________________________________________________________________
1092 Bool_t AliTPCCalibCE::ProcessEvent(AliTPCRawStream *rawStream)
1095 // Event Processing loop - AliTPCRawStream
1096 // The Function 'SetTimeStamp' should be called for each event to set the event time stamp!!!
1099 rawStream->SetOldRCUFormat(fOldRCUformat);
1103 Bool_t withInput = kFALSE;
1105 while (rawStream->Next()) {
1107 Int_t isector = rawStream->GetSector(); // current sector
1108 Int_t iRow = rawStream->GetRow(); // current row
1109 Int_t iPad = rawStream->GetPad(); // current pad
1110 Int_t iTimeBin = rawStream->GetTime(); // current time bin
1111 Float_t signal = rawStream->GetSignal(); // current ADC signal
1113 Update(isector,iRow,iPad,iTimeBin,signal);
1123 //_____________________________________________________________________
1124 Bool_t AliTPCCalibCE::ProcessEvent(AliRawReader *rawReader)
1127 // Event processing loop - AliRawReader
1131 AliTPCRawStream rawStream(rawReader,(AliAltroMapping**)fMapping);
1132 AliRawEventHeaderBase* eventHeader = (AliRawEventHeaderBase*)rawReader->GetEventHeader();
1134 fTimeStamp = eventHeader->Get("Timestamp");
1135 fRunNumber = eventHeader->Get("RunNb");
1137 fEventId = *rawReader->GetEventId();
1140 rawReader->Select("TPC");
1142 return ProcessEvent(&rawStream);
1144 //_____________________________________________________________________
1145 Bool_t AliTPCCalibCE::ProcessEvent(eventHeaderStruct *event)
1148 // Event processing loop - date event
1150 AliRawReader *rawReader = new AliRawReaderDate((void*)event);
1151 Bool_t result=ProcessEvent(rawReader);
1156 //_____________________________________________________________________
1157 TH2S* AliTPCCalibCE::GetHisto(Int_t sector, TObjArray *arr,
1158 Int_t nbinsY, Float_t ymin, Float_t ymax,
1159 Char_t *type, Bool_t force)
1162 // return pointer to TH2S histogram of 'type'
1163 // if force is true create a new histogram if it doesn't exist allready
1165 if ( !force || arr->UncheckedAt(sector) )
1166 return (TH2S*)arr->UncheckedAt(sector);
1168 // if we are forced and histogram doesn't exist yet create it
1169 Char_t name[255], title[255];
1171 sprintf(name,"hCalib%s%.2d",type,sector);
1172 sprintf(title,"%s calibration histogram sector %.2d",type,sector);
1174 // new histogram with Q calib information. One value for each pad!
1175 TH2S* hist = new TH2S(name,title,
1177 fROC->GetNChannels(sector),0,fROC->GetNChannels(sector));
1178 hist->SetDirectory(0);
1179 arr->AddAt(hist,sector);
1182 //_____________________________________________________________________
1183 TH2S* AliTPCCalibCE::GetHistoT0(Int_t sector, Bool_t force)
1186 // return pointer to T0 histogram
1187 // if force is true create a new histogram if it doesn't exist allready
1189 TObjArray *arr = &fHistoT0Array;
1190 return GetHisto(sector, arr, fNbinsT0, fXminT0, fXmaxT0, "T0", force);
1192 //_____________________________________________________________________
1193 TH2S* AliTPCCalibCE::GetHistoQ(Int_t sector, Bool_t force)
1196 // return pointer to Q histogram
1197 // if force is true create a new histogram if it doesn't exist allready
1199 TObjArray *arr = &fHistoQArray;
1200 return GetHisto(sector, arr, fNbinsQ, fXminQ, fXmaxQ, "Q", force);
1202 //_____________________________________________________________________
1203 TH2S* AliTPCCalibCE::GetHistoRMS(Int_t sector, Bool_t force)
1206 // return pointer to Q histogram
1207 // if force is true create a new histogram if it doesn't exist allready
1209 TObjArray *arr = &fHistoRMSArray;
1210 return GetHisto(sector, arr, fNbinsRMS, fXminRMS, fXmaxRMS, "RMS", force);
1212 //_____________________________________________________________________
1213 TH1S* AliTPCCalibCE::GetHisto(Int_t sector, TObjArray *arr,
1214 Char_t *type, Bool_t force)
1217 // return pointer to TH1S histogram
1218 // if force is true create a new histogram if it doesn't exist allready
1220 if ( !force || arr->UncheckedAt(sector) )
1221 return (TH1S*)arr->UncheckedAt(sector);
1223 // if we are forced and histogram doesn't yes exist create it
1224 Char_t name[255], title[255];
1226 sprintf(name,"hCalib%s%.2d",type,sector);
1227 sprintf(title,"%s calibration histogram sector %.2d",type,sector);
1229 // new histogram with Q calib information. One value for each pad!
1230 TH1S* hist = new TH1S(name,title,
1231 fLastTimeBin-fFirstTimeBin,fFirstTimeBin,fLastTimeBin);
1232 hist->SetDirectory(0);
1233 arr->AddAt(hist,sector);
1236 //_____________________________________________________________________
1237 TH1S* AliTPCCalibCE::GetHistoTmean(Int_t sector, Bool_t force)
1240 // return pointer to Q histogram
1241 // if force is true create a new histogram if it doesn't exist allready
1243 TObjArray *arr = &fHistoTmean;
1244 return GetHisto(sector, arr, "LastTmean", force);
1246 //_____________________________________________________________________
1247 TVectorF* AliTPCCalibCE::GetVectSector(Int_t sector, TObjArray *arr, UInt_t size, Bool_t force) const
1250 // return pointer to Pad Info from 'arr' for the current event and sector
1251 // if force is true create it if it doesn't exist allready
1253 if ( !force || arr->UncheckedAt(sector) )
1254 return (TVectorF*)arr->UncheckedAt(sector);
1256 TVectorF *vect = new TVectorF(size);
1257 arr->AddAt(vect,sector);
1260 //_____________________________________________________________________
1261 TVectorF* AliTPCCalibCE::GetPadTimesEvent(Int_t sector, Bool_t force)
1264 // return pointer to Pad Times Array for the current event and sector
1265 // if force is true create it if it doesn't exist allready
1267 TObjArray *arr = &fPadTimesArrayEvent;
1268 return GetVectSector(sector,arr,fROC->GetNChannels(sector),force);
1270 //_____________________________________________________________________
1271 TVectorF* AliTPCCalibCE::GetPadQEvent(Int_t sector, Bool_t force)
1274 // return pointer to Pad Q Array for the current event and sector
1275 // if force is true create it if it doesn't exist allready
1276 // for debugging purposes only
1279 TObjArray *arr = &fPadQArrayEvent;
1280 return GetVectSector(sector,arr,fROC->GetNChannels(sector),force);
1282 //_____________________________________________________________________
1283 TVectorF* AliTPCCalibCE::GetPadRMSEvent(Int_t sector, Bool_t force)
1286 // return pointer to Pad RMS Array for the current event and sector
1287 // if force is true create it if it doesn't exist allready
1288 // for debugging purposes only
1290 TObjArray *arr = &fPadRMSArrayEvent;
1291 return GetVectSector(sector,arr,fROC->GetNChannels(sector),force);
1293 //_____________________________________________________________________
1294 TVectorF* AliTPCCalibCE::GetPadPedestalEvent(Int_t sector, Bool_t force)
1297 // return pointer to Pad RMS Array for the current event and sector
1298 // if force is true create it if it doesn't exist allready
1299 // for debugging purposes only
1301 TObjArray *arr = &fPadPedestalArrayEvent;
1302 return GetVectSector(sector,arr,fROC->GetNChannels(sector),force);
1304 //_____________________________________________________________________
1305 TVectorF* AliTPCCalibCE::GetTMeanEvents(Int_t sector, Bool_t force)
1308 // return pointer to the EbyE info of the mean arrival time for 'sector'
1309 // if force is true create it if it doesn't exist allready
1311 TObjArray *arr = &fTMeanArrayEvent;
1312 return GetVectSector(sector,arr,100,force);
1314 //_____________________________________________________________________
1315 TVectorF* AliTPCCalibCE::GetQMeanEvents(Int_t sector, Bool_t force)
1318 // return pointer to the EbyE info of the mean arrival time for 'sector'
1319 // if force is true create it if it doesn't exist allready
1321 TObjArray *arr = &fQMeanArrayEvent;
1322 return GetVectSector(sector,arr,100,force);
1324 //_____________________________________________________________________
1325 AliTPCCalROC* AliTPCCalibCE::GetCalRoc(Int_t sector, TObjArray* arr, Bool_t force) const
1328 // return pointer to ROC Calibration
1329 // if force is true create a new histogram if it doesn't exist allready
1331 if ( !force || arr->UncheckedAt(sector) )
1332 return (AliTPCCalROC*)arr->UncheckedAt(sector);
1334 // if we are forced and histogram doesn't yes exist create it
1336 // new AliTPCCalROC for T0 information. One value for each pad!
1337 AliTPCCalROC *croc = new AliTPCCalROC(sector);
1338 arr->AddAt(croc,sector);
1341 //_____________________________________________________________________
1342 AliTPCCalROC* AliTPCCalibCE::GetCalRocT0(Int_t sector, Bool_t force)
1345 // return pointer to Carge ROC Calibration
1346 // if force is true create a new histogram if it doesn't exist allready
1348 TObjArray *arr = &fCalRocArrayT0;
1349 return GetCalRoc(sector, arr, force);
1351 //_____________________________________________________________________
1352 AliTPCCalROC* AliTPCCalibCE::GetCalRocQ(Int_t sector, Bool_t force)
1355 // return pointer to T0 ROC Calibration
1356 // if force is true create a new histogram if it doesn't exist allready
1358 TObjArray *arr = &fCalRocArrayQ;
1359 return GetCalRoc(sector, arr, force);
1361 //_____________________________________________________________________
1362 AliTPCCalROC* AliTPCCalibCE::GetCalRocRMS(Int_t sector, Bool_t force)
1365 // return pointer to signal width ROC Calibration
1366 // if force is true create a new histogram if it doesn't exist allready
1368 TObjArray *arr = &fCalRocArrayRMS;
1369 return GetCalRoc(sector, arr, force);
1371 //_____________________________________________________________________
1372 AliTPCCalROC* AliTPCCalibCE::GetCalRocOutliers(Int_t sector, Bool_t force)
1375 // return pointer to Outliers
1376 // if force is true create a new histogram if it doesn't exist allready
1378 TObjArray *arr = &fCalRocArrayOutliers;
1379 return GetCalRoc(sector, arr, force);
1381 //_____________________________________________________________________
1382 TObjArray* AliTPCCalibCE::GetParamArray(Int_t sector, TObjArray* arr, Bool_t force) const
1385 // return pointer to TObjArray of fit parameters
1386 // if force is true create a new histogram if it doesn't exist allready
1388 if ( !force || arr->UncheckedAt(sector) )
1389 return (TObjArray*)arr->UncheckedAt(sector);
1391 // if we are forced and array doesn't yes exist create it
1393 // new TObjArray for parameters
1394 TObjArray *newArr = new TObjArray;
1395 arr->AddAt(newArr,sector);
1398 //_____________________________________________________________________
1399 TObjArray* AliTPCCalibCE::GetParamArrayPol1(Int_t sector, Bool_t force)
1402 // return pointer to TObjArray of fit parameters from plane fit
1403 // if force is true create a new histogram if it doesn't exist allready
1405 TObjArray *arr = &fParamArrayEventPol1;
1406 return GetParamArray(sector, arr, force);
1408 //_____________________________________________________________________
1409 TObjArray* AliTPCCalibCE::GetParamArrayPol2(Int_t sector, Bool_t force)
1412 // return pointer to TObjArray of fit parameters from parabola fit
1413 // if force is true create a new histogram if it doesn't exist allready
1415 TObjArray *arr = &fParamArrayEventPol2;
1416 return GetParamArray(sector, arr, force);
1418 //_____________________________________________________________________
1419 void AliTPCCalibCE::ResetEvent()
1422 // Reset global counters -- Should be called before each event is processed
1431 fPadTimesArrayEvent.Delete();
1432 fPadQArrayEvent.Delete();
1433 fPadRMSArrayEvent.Delete();
1434 fPadPedestalArrayEvent.Delete();
1436 for ( Int_t i=0; i<72; ++i ){
1437 fVTime0Offset.GetMatrixArray()[i]=0;
1438 fVTime0OffsetCounter.GetMatrixArray()[i]=0;
1439 fVMeanQ.GetMatrixArray()[i]=0;
1440 fVMeanQCounter.GetMatrixArray()[i]=0;
1443 //_____________________________________________________________________
1444 void AliTPCCalibCE::ResetPad()
1447 // Reset pad infos -- Should be called after a pad has been processed
1449 for (Int_t i=fFirstTimeBin; i<fLastTimeBin+1; ++i)
1450 fPadSignal.GetMatrixArray()[i] = 0;
1456 //_____________________________________________________________________
1457 void AliTPCCalibCE::Merge(AliTPCCalibCE *ce)
1460 // Merge ce to the current AliTPCCalibCE
1464 for (Int_t iSec=0; iSec<72; ++iSec){
1465 TH2S *hRefQmerge = ce->GetHistoQ(iSec);
1466 TH2S *hRefT0merge = ce->GetHistoT0(iSec);
1467 TH2S *hRefRMSmerge = ce->GetHistoRMS(iSec);
1471 TDirectory *dir = hRefQmerge->GetDirectory(); hRefQmerge->SetDirectory(0);
1472 TH2S *hRefQ = GetHistoQ(iSec);
1473 if ( hRefQ ) hRefQ->Add(hRefQmerge);
1475 TH2S *hist = new TH2S(*hRefQmerge);
1476 hist->SetDirectory(0);
1477 fHistoQArray.AddAt(hist, iSec);
1479 hRefQmerge->SetDirectory(dir);
1482 TDirectory *dir = hRefT0merge->GetDirectory(); hRefT0merge->SetDirectory(0);
1483 TH2S *hRefT0 = GetHistoT0(iSec);
1484 if ( hRefT0 ) hRefT0->Add(hRefT0merge);
1486 TH2S *hist = new TH2S(*hRefT0merge);
1487 hist->SetDirectory(0);
1488 fHistoT0Array.AddAt(hist, iSec);
1490 hRefT0merge->SetDirectory(dir);
1492 if ( hRefRMSmerge ){
1493 TDirectory *dir = hRefRMSmerge->GetDirectory(); hRefRMSmerge->SetDirectory(0);
1494 TH2S *hRefRMS = GetHistoRMS(iSec);
1495 if ( hRefRMS ) hRefRMS->Add(hRefRMSmerge);
1497 TH2S *hist = new TH2S(*hRefRMSmerge);
1498 hist->SetDirectory(0);
1499 fHistoRMSArray.AddAt(hist, iSec);
1501 hRefRMSmerge->SetDirectory(dir);
1506 // merge time information
1509 Int_t nCEevents = ce->GetNeventsProcessed();
1510 for (Int_t iSec=0; iSec<72; ++iSec){
1511 TObjArray *arrPol1CE = ce->GetParamArrayPol1(iSec);
1512 TObjArray *arrPol2CE = ce->GetParamArrayPol2(iSec);
1513 TVectorF *vMeanTimeCE = ce->GetTMeanEvents(iSec);
1514 TVectorF *vMeanQCE = ce->GetQMeanEvents(iSec);
1516 TObjArray *arrPol1 = 0x0;
1517 TObjArray *arrPol2 = 0x0;
1518 TVectorF *vMeanTime = 0x0;
1519 TVectorF *vMeanQ = 0x0;
1522 if ( arrPol1CE && arrPol2CE ){
1523 arrPol1 = GetParamArrayPol1(iSec,kTRUE);
1524 arrPol2 = GetParamArrayPol2(iSec,kTRUE);
1525 arrPol1->Expand(fNevents+nCEevents);
1526 arrPol2->Expand(fNevents+nCEevents);
1528 if ( vMeanTimeCE && vMeanQCE ){
1529 vMeanTime = GetTMeanEvents(iSec,kTRUE);
1530 vMeanQ = GetQMeanEvents(iSec,kTRUE);
1531 vMeanTime->ResizeTo(fNevents+nCEevents);
1532 vMeanQ->ResizeTo(fNevents+nCEevents);
1536 for (Int_t iEvent=0; iEvent<nCEevents; ++iEvent){
1537 if ( arrPol1CE && arrPol2CE ){
1538 TVectorD *paramPol1 = (TVectorD*)(arrPol1CE->UncheckedAt(iEvent));
1539 TVectorD *paramPol2 = (TVectorD*)(arrPol2CE->UncheckedAt(iEvent));
1540 if ( paramPol1 && paramPol2 ){
1541 GetParamArrayPol1(iSec,kTRUE)->AddAt(new TVectorD(*paramPol1), fNevents+iEvent);
1542 GetParamArrayPol2(iSec,kTRUE)->AddAt(new TVectorD(*paramPol2), fNevents+iEvent);
1545 if ( vMeanTimeCE && vMeanQCE ){
1546 vMeanTime->GetMatrixArray()[fNevents+iEvent]=vMeanTimeCE->GetMatrixArray()[iEvent];
1547 vMeanQ->GetMatrixArray()[fNevents+iEvent]=vMeanQCE->GetMatrixArray()[iEvent];
1554 TVectorD* eventTimes = ce->GetEventTimes();
1555 TVectorD* eventIds = ce->GetEventIds();
1556 fVEventTime.ResizeTo(fNevents+nCEevents);
1557 fVEventNumber.ResizeTo(fNevents+nCEevents);
1559 for (Int_t iEvent=0; iEvent<nCEevents; ++iEvent){
1560 Double_t evTime = eventTimes->GetMatrixArray()[iEvent];
1561 Double_t evId = eventIds->GetMatrixArray()[iEvent];
1562 fVEventTime.GetMatrixArray()[fNevents+iEvent] = evTime;
1563 fVEventNumber.GetMatrixArray()[fNevents+iEvent] = evId;
1565 fNevents+=nCEevents; //increase event counter
1568 //_____________________________________________________________________
1569 TGraph *AliTPCCalibCE::MakeGraphTimeCE(Int_t sector, Int_t xVariable, Int_t fitType, Int_t fitParameter)
1572 // Make graph from fit parameters of pol1 fit, pol2 fit, mean arrival time or mean Q for ROC 'sector'
1573 // xVariable: 0-event time, 1-event id, 2-internal event counter
1574 // fitType: 0-pol1 fit, 1-pol2 fit, 2-mean time, 3-mean Q
1575 // fitParameter: fit parameter ( 0-2 for pol1 ([0]+[1]*x+[2]*y),
1576 // 0-5 for pol2 ([0]+[1]*x+[2]*y+[3]*x*x+[4]*y*y+[5]*x*y),
1577 // not used for mean time and mean Q )
1578 // for an example see class description at the beginning
1581 Double_t *x = new Double_t[fNevents];
1582 Double_t *y = new Double_t[fNevents];
1584 TVectorD *xVar = 0x0;
1585 TObjArray *aType = 0x0;
1589 if ( (sector<0) || (sector>71) ) return 0x0;
1590 if ( (xVariable<0) || (xVariable>2) ) return 0x0;
1591 if ( (fitType<0) || (fitType>3) ) return 0x0;
1593 if ( (fitParameter<0) || (fitParameter>2) ) return 0x0;
1594 aType = &fParamArrayEventPol1;
1595 if ( aType->At(sector)==0x0 ) return 0x0;
1597 else if ( fitType==1 ){
1598 if ( (fitParameter<0) || (fitParameter>5) ) return 0x0;
1599 aType = &fParamArrayEventPol2;
1600 if ( aType->At(sector)==0x0 ) return 0x0;
1604 if ( xVariable == 0 ) xVar = &fVEventTime;
1605 if ( xVariable == 1 ) xVar = &fVEventNumber;
1606 if ( xVariable == 2 ) {
1607 xVar = new TVectorD(fNevents);
1608 for ( Int_t i=0;i<fNevents; ++i) (*xVar)[i]=i;
1611 for (Int_t ievent =0; ievent<fNevents; ++ievent){
1613 TObjArray *events = (TObjArray*)(aType->At(sector));
1614 if ( events->GetSize()<=ievent ) break;
1615 TVectorD *v = (TVectorD*)(events->At(ievent));
1616 if ( (v!=0x0) && ((*xVar)[ievent]>0) ) { x[npoints]=(*xVar)[ievent]; y[npoints]=(*v)[fitParameter]; npoints++;}
1617 } else if (fitType == 2) {
1618 Double_t xValue=(*xVar)[ievent];
1619 Double_t yValue=(*GetTMeanEvents(sector))[ievent];
1620 if ( yValue>0 && xValue>0 ) { x[npoints]=xValue; y[npoints]=yValue;npoints++;}
1621 }else if (fitType == 3) {
1622 Double_t xValue=(*xVar)[ievent];
1623 Double_t yValue=(*GetQMeanEvents(sector))[ievent];
1624 if ( yValue>0 && xValue>0 ) { x[npoints]=xValue; y[npoints]=yValue;npoints++;}
1628 TGraph *gr = new TGraph(npoints);
1629 //sort xVariable increasing
1630 Int_t *sortIndex = new Int_t[npoints];
1631 TMath::Sort(npoints,x,sortIndex);
1632 for (Int_t i=0;i<npoints;++i){
1633 gr->SetPoint(i,x[sortIndex[i]],y[sortIndex[i]]);
1637 if ( xVariable == 2 ) delete xVar;
1643 //_____________________________________________________________________
1644 void AliTPCCalibCE::Analyse()
1647 // Calculate calibration constants
1651 TVectorD paramT0(3);
1652 TVectorD paramRMS(3);
1653 TMatrixD dummy(3,3);
1655 for (Int_t iSec=0; iSec<72; ++iSec){
1656 TH2S *hT0 = GetHistoT0(iSec);
1657 if (!hT0 ) continue;
1659 AliTPCCalROC *rocQ = GetCalRocQ (iSec,kTRUE);
1660 AliTPCCalROC *rocT0 = GetCalRocT0 (iSec,kTRUE);
1661 AliTPCCalROC *rocRMS = GetCalRocRMS(iSec,kTRUE);
1662 AliTPCCalROC *rocOut = GetCalRocOutliers(iSec,kTRUE);
1664 TH2S *hQ = GetHistoQ(iSec);
1665 TH2S *hRMS = GetHistoRMS(iSec);
1667 Short_t *arrayhQ = hQ->GetArray();
1668 Short_t *arrayhT0 = hT0->GetArray();
1669 Short_t *arrayhRMS = hRMS->GetArray();
1671 UInt_t nChannels = fROC->GetNChannels(iSec);
1679 for (UInt_t iChannel=0; iChannel<nChannels; ++iChannel){
1682 Float_t cogTime0 = -1000;
1683 Float_t cogQ = -1000;
1684 Float_t cogRMS = -1000;
1688 Int_t offsetQ = (fNbinsQ+2)*(iChannel+1)+1;
1689 Int_t offsetT0 = (fNbinsT0+2)*(iChannel+1)+1;
1690 Int_t offsetRMS = (fNbinsRMS+2)*(iChannel+1)+1;
1692 cogQ = AliMathBase::GetCOG(arrayhQ+offsetQ,fNbinsQ,fXminQ,fXmaxQ);
1693 cogTime0 = AliMathBase::GetCOG(arrayhT0+offsetT0,fNbinsT0,fXminT0,fXmaxT0);
1694 cogRMS = AliMathBase::GetCOG(arrayhRMS+offsetRMS,fNbinsRMS,fXminRMS,fXmaxRMS);
1699 //outlier specifications
1700 if ( (cogQ < ??) && (cogTime0 > ??) && (cogTime0<??) && ( cogRMS>??) ){
1707 rocQ->SetValue(iChannel, cogQ*cogQ);
1708 rocT0->SetValue(iChannel, cogTime0);
1709 rocRMS->SetValue(iChannel, cogRMS);
1710 rocOut->SetValue(iChannel, cogOut);
1714 if ( fDebugLevel > 0 ){
1715 if ( !fDebugStreamer ) {
1717 TDirectory *backup = gDirectory;
1718 fDebugStreamer = new TTreeSRedirector("debugCalibCEAnalysis.root");
1719 if ( backup ) backup->cd(); //we don't want to be cd'd to the debug streamer
1722 while ( iChannel > (fROC->GetRowIndexes(iSec)[row]+fROC->GetNPads(iSec,row)-1) ) row++;
1723 pad = iChannel-fROC->GetRowIndexes(iSec)[row];
1724 padc = pad-(fROC->GetNPads(iSec,row)/2);
1726 (*fDebugStreamer) << "DataEnd" <<
1727 "Sector=" << iSec <<
1731 "PadSec=" << iChannel <<
1733 "T0=" << cogTime0 <<
1742 if ( fDebugStreamer ) fDebugStreamer->GetFile()->Write();
1743 // delete fDebugStreamer;
1744 // fDebugStreamer = 0x0;
1746 //_____________________________________________________________________
1747 void AliTPCCalibCE::DumpToFile(const Char_t *filename, const Char_t *dir, Bool_t append)
1750 // Write class to file
1759 option = "recreate";
1761 TDirectory *backup = gDirectory;
1762 TFile f(filename,option.Data());
1764 if ( !sDir.IsNull() ){
1765 f.mkdir(sDir.Data());
1771 if ( backup ) backup->cd();