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
853 //loop over all ROCs, fill CE Time histogram corrected for the mean Time0 of each ROC
854 for ( Int_t iSec = 0; iSec<72; ++iSec ){
855 //find median and then calculate the mean around it
856 TH1S *hMeanT = GetHistoTmean(iSec); //histogram with local maxima position information
857 if ( !hMeanT ) continue;
858 //continue if not enough data is filled in the meanT histogram. This is the case if we do not have a laser event.
859 if ( hMeanT->GetEntries() < fROC->GetNChannels(iSec)*2/3 ){
864 Double_t entries = hMeanT->GetEntries();
866 Short_t *arr = hMeanT->GetArray()+1;
868 for ( ibin=0; ibin<hMeanT->GetNbinsX(); ++ibin){
870 if ( sum>=(entries/2.) ) break;
873 Int_t firstBin = fFirstTimeBin+ibin-delta;
874 Int_t lastBin = fFirstTimeBin+ibin+delta;
875 if ( firstBin<fFirstTimeBin ) firstBin=fFirstTimeBin;
876 if ( lastBin>fLastTimeBin ) lastBin =fLastTimeBin;
877 Float_t median =AliMathBase::GetCOG(arr+ibin-delta,2*delta,firstBin,lastBin);
879 // check boundaries for ebye info of mean time
880 TVectorF *vMeanTime=GetTMeanEvents(iSec,kTRUE);
881 Int_t vSize=vMeanTime->GetNrows();
882 if ( vSize < fNevents+1 )
883 vMeanTime->ResizeTo(vSize+100);
885 vMeanTime->GetMatrixArray()[fNevents]=median;
889 TVectorF *vTimes = GetPadTimesEvent(iSec);
890 if ( !vTimes ) continue; //continue if no time information for this sector is available
893 AliTPCCalROC calIrocOutliers(0);
894 AliTPCCalROC calOrocOutliers(36);
896 // calculate mean Q of the sector
898 if ( fVMeanQCounter.GetMatrixArray()[iSec]>0 ) meanQ=fVMeanQ.GetMatrixArray()[iSec]/fVMeanQCounter.GetMatrixArray()[iSec];
899 TVectorF *vMeanQ=GetQMeanEvents(iSec,kTRUE);
900 if ( vSize < fNevents+1 ) // vSize is the same as for vMeanTime!
901 vMeanQ->ResizeTo(vSize+100);
903 vMeanQ->GetMatrixArray()[fNevents]=meanQ;
905 for ( UInt_t iChannel=0; iChannel<fROC->GetNChannels(iSec); ++iChannel ){
906 Float_t time = (*vTimes).GetMatrixArray()[iChannel];
908 //set values for temporary roc calibration class
910 calIroc->SetValue(iChannel, time);
911 if ( time == 0 ) calIrocOutliers.SetValue(iChannel,1);
914 calOroc->SetValue(iChannel, time);
915 if ( time == 0 ) calOrocOutliers.SetValue(iChannel,1);
918 if ( (fNevents>0) && (fOldRunNumber==fRunNumber) )
919 GetHistoT0(iSec,kTRUE)->Fill( time-time0Side[(iSec/18)%2],iChannel );
923 //------------------------------- Debug start ------------------------------
924 if ( fDebugLevel>0 ){
925 if ( !fDebugStreamer ) {
927 TDirectory *backup = gDirectory;
928 fDebugStreamer = new TTreeSRedirector("debugCalibCE.root");
929 if ( backup ) backup->cd(); //we don't want to be cd'd to the debug streamer
936 Float_t q = (*GetPadQEvent(iSec))[iChannel];
937 Float_t rms = (*GetPadRMSEvent(iSec))[iChannel];
939 UInt_t channel=iChannel;
942 while ( channel > (fROC->GetRowIndexes(sector)[row]+fROC->GetNPads(sector,row)-1) ) row++;
943 pad = channel-fROC->GetRowIndexes(sector)[row];
944 padc = pad-(fROC->GetNPads(sector,row)/2);
946 // TH1F *h1 = new TH1F(Form("hSignalD%d.%d.%d",sector,row,pad),
947 // Form("hSignalD%d.%d.%d",sector,row,pad),
948 // fLastTimeBin-fFirstTimeBin,
949 // fFirstTimeBin,fLastTimeBin);
950 // h1->SetDirectory(0);
952 // for (Int_t i=fFirstTimeBin; i<fLastTimeBin+1; ++i)
953 // h1->Fill(i,fPadSignal(i));
956 if (fVTime0OffsetCounter.GetMatrixArray()[iSec]>0)
957 t0Sec = fVTime0Offset.GetMatrixArray()[iSec]/fVTime0OffsetCounter.GetMatrixArray()[iSec];
958 Double_t t0Side = time0Side[(iSec/18)%2];
959 (*fDebugStreamer) << "DataPad" <<
960 "Event=" << fNevents <<
961 "RunNumber=" << fRunNumber <<
962 "TimeStamp=" << fTimeStamp <<
963 "Sector="<< sector <<
967 "PadSec="<< channel <<
968 "Time0Sec=" << t0Sec <<
969 "Time0Side=" << t0Side <<
980 //----------------------------- Debug end ------------------------------
983 TVectorD paramPol1(3);
984 TVectorD paramPol2(6);
985 TMatrixD matPol1(3,3);
986 TMatrixD matPol2(6,6);
990 if ( (fNevents>0) && (fOldRunNumber==fRunNumber) ){
992 calIroc->GlobalFit(&calIrocOutliers,0,paramPol1,matPol1,chi2Pol1,0);
993 calIroc->GlobalFit(&calIrocOutliers,0,paramPol2,matPol2,chi2Pol2,1);
995 calOroc->GlobalFit(&calOrocOutliers,0,paramPol1,matPol1,chi2Pol1,0);
996 calOroc->GlobalFit(&calOrocOutliers,0,paramPol2,matPol2,chi2Pol2,1);
999 GetParamArrayPol1(iSec,kTRUE)->AddAtAndExpand(new TVectorD(paramPol1), fNevents);
1000 GetParamArrayPol2(iSec,kTRUE)->AddAtAndExpand(new TVectorD(paramPol2), fNevents);
1003 //------------------------------- Debug start ------------------------------
1004 if ( fDebugLevel>0 ){
1005 if ( !fDebugStreamer ) {
1007 TDirectory *backup = gDirectory;
1008 fDebugStreamer = new TTreeSRedirector("debugCalibCE.root");
1009 if ( backup ) backup->cd(); //we don't want to be cd'd to the debug streamer
1011 (*fDebugStreamer) << "DataRoc" <<
1012 // "Event=" << fEvent <<
1013 "RunNumber=" << fRunNumber <<
1014 "TimeStamp=" << fTimeStamp <<
1016 "hMeanT.=" << hMeanT <<
1017 "median=" << median <<
1018 "paramPol1.=" << ¶mPol1 <<
1019 "paramPol2.=" << ¶mPol2 <<
1020 "matPol1.=" << &matPol1 <<
1021 "matPol2.=" << &matPol2 <<
1022 "chi2Pol1=" << chi2Pol1 <<
1023 "chi2Pol2=" << chi2Pol2 <<
1026 //------------------------------- Debug end ------------------------------
1029 //return if no sector has a valid mean time
1030 if ( nSecMeanT == 0 ) return;
1033 // fTMeanArrayEvent.AddAtAndExpand(new TVectorF(vMeanTime),fNevents);
1034 // fQMeanArrayEvent.AddAtAndExpand(new TVectorF(vMeanQ),fNevents);
1035 if ( fVEventTime.GetNrows() < fNevents+1 ) {
1036 fVEventTime.ResizeTo((Int_t)(fVEventTime.GetNrows()+100));
1037 fVEventNumber.ResizeTo((Int_t)(fVEventNumber.GetNrows()+100));
1039 fVEventTime.GetMatrixArray()[fNevents] = fTimeStamp;
1040 fVEventNumber.GetMatrixArray()[fNevents] = fEventId;
1043 fOldRunNumber = fRunNumber;
1048 //_____________________________________________________________________
1049 Bool_t AliTPCCalibCE::ProcessEventFast(AliTPCRawStreamFast *rawStreamFast)
1052 // Event Processing loop - AliTPCRawStreamFast
1055 Bool_t withInput = kFALSE;
1056 while ( rawStreamFast->NextDDL() ){
1057 while ( rawStreamFast->NextChannel() ){
1058 Int_t isector = rawStreamFast->GetSector(); // current sector
1059 Int_t iRow = rawStreamFast->GetRow(); // current row
1060 Int_t iPad = rawStreamFast->GetPad(); // current pad
1062 while ( rawStreamFast->NextBunch() ){
1063 Int_t startTbin = (Int_t)rawStreamFast->GetStartTimeBin();
1064 Int_t endTbin = (Int_t)rawStreamFast->GetEndTimeBin();
1065 for (Int_t iTimeBin = startTbin; iTimeBin < endTbin; iTimeBin++){
1066 Float_t signal=(Float_t)rawStreamFast->GetSignals()[iTimeBin-startTbin];
1067 Update(isector,iRow,iPad,iTimeBin+1,signal);
1078 //_____________________________________________________________________
1079 Bool_t AliTPCCalibCE::ProcessEventFast(AliRawReader *rawReader)
1082 // Event processing loop using the fast raw stream algorithm- AliRawReader
1085 //printf("ProcessEventFast - raw reader\n");
1087 AliRawEventHeaderBase* eventHeader = (AliRawEventHeaderBase*)rawReader->GetEventHeader();
1089 fTimeStamp = eventHeader->Get("Timestamp");
1090 fRunNumber = eventHeader->Get("RunNb");
1092 fEventId = *rawReader->GetEventId();
1094 AliTPCRawStreamFast *rawStreamFast = new AliTPCRawStreamFast(rawReader, (AliAltroMapping**)fMapping);
1095 Bool_t res=ProcessEventFast(rawStreamFast);
1096 delete rawStreamFast;
1100 //_____________________________________________________________________
1101 Bool_t AliTPCCalibCE::ProcessEvent(AliTPCRawStream *rawStream)
1104 // Event Processing loop - AliTPCRawStream
1105 // The Function 'SetTimeStamp' should be called for each event to set the event time stamp!!!
1108 rawStream->SetOldRCUFormat(fOldRCUformat);
1112 Bool_t withInput = kFALSE;
1114 while (rawStream->Next()) {
1116 Int_t isector = rawStream->GetSector(); // current sector
1117 Int_t iRow = rawStream->GetRow(); // current row
1118 Int_t iPad = rawStream->GetPad(); // current pad
1119 Int_t iTimeBin = rawStream->GetTime(); // current time bin
1120 Float_t signal = rawStream->GetSignal(); // current ADC signal
1122 Update(isector,iRow,iPad,iTimeBin,signal);
1132 //_____________________________________________________________________
1133 Bool_t AliTPCCalibCE::ProcessEvent(AliRawReader *rawReader)
1136 // Event processing loop - AliRawReader
1140 AliTPCRawStream rawStream(rawReader,(AliAltroMapping**)fMapping);
1141 AliRawEventHeaderBase* eventHeader = (AliRawEventHeaderBase*)rawReader->GetEventHeader();
1143 fTimeStamp = eventHeader->Get("Timestamp");
1144 fRunNumber = eventHeader->Get("RunNb");
1146 fEventId = *rawReader->GetEventId();
1149 rawReader->Select("TPC");
1151 return ProcessEvent(&rawStream);
1153 //_____________________________________________________________________
1154 Bool_t AliTPCCalibCE::ProcessEvent(eventHeaderStruct *event)
1157 // Event processing loop - date event
1159 AliRawReader *rawReader = new AliRawReaderDate((void*)event);
1160 Bool_t result=ProcessEvent(rawReader);
1165 //_____________________________________________________________________
1166 TH2S* AliTPCCalibCE::GetHisto(Int_t sector, TObjArray *arr,
1167 Int_t nbinsY, Float_t ymin, Float_t ymax,
1168 Char_t *type, Bool_t force)
1171 // return pointer to TH2S histogram of 'type'
1172 // if force is true create a new histogram if it doesn't exist allready
1174 if ( !force || arr->UncheckedAt(sector) )
1175 return (TH2S*)arr->UncheckedAt(sector);
1177 // if we are forced and histogram doesn't exist yet create it
1178 Char_t name[255], title[255];
1180 sprintf(name,"hCalib%s%.2d",type,sector);
1181 sprintf(title,"%s calibration histogram sector %.2d",type,sector);
1183 // new histogram with Q calib information. One value for each pad!
1184 TH2S* hist = new TH2S(name,title,
1186 fROC->GetNChannels(sector),0,fROC->GetNChannels(sector));
1187 hist->SetDirectory(0);
1188 arr->AddAt(hist,sector);
1191 //_____________________________________________________________________
1192 TH2S* AliTPCCalibCE::GetHistoT0(Int_t sector, Bool_t force)
1195 // return pointer to T0 histogram
1196 // if force is true create a new histogram if it doesn't exist allready
1198 TObjArray *arr = &fHistoT0Array;
1199 return GetHisto(sector, arr, fNbinsT0, fXminT0, fXmaxT0, "T0", force);
1201 //_____________________________________________________________________
1202 TH2S* AliTPCCalibCE::GetHistoQ(Int_t sector, Bool_t force)
1205 // return pointer to Q histogram
1206 // if force is true create a new histogram if it doesn't exist allready
1208 TObjArray *arr = &fHistoQArray;
1209 return GetHisto(sector, arr, fNbinsQ, fXminQ, fXmaxQ, "Q", force);
1211 //_____________________________________________________________________
1212 TH2S* AliTPCCalibCE::GetHistoRMS(Int_t sector, Bool_t force)
1215 // return pointer to Q histogram
1216 // if force is true create a new histogram if it doesn't exist allready
1218 TObjArray *arr = &fHistoRMSArray;
1219 return GetHisto(sector, arr, fNbinsRMS, fXminRMS, fXmaxRMS, "RMS", force);
1221 //_____________________________________________________________________
1222 TH1S* AliTPCCalibCE::GetHisto(Int_t sector, TObjArray *arr,
1223 Char_t *type, Bool_t force)
1226 // return pointer to TH1S histogram
1227 // if force is true create a new histogram if it doesn't exist allready
1229 if ( !force || arr->UncheckedAt(sector) )
1230 return (TH1S*)arr->UncheckedAt(sector);
1232 // if we are forced and histogram doesn't yes exist create it
1233 Char_t name[255], title[255];
1235 sprintf(name,"hCalib%s%.2d",type,sector);
1236 sprintf(title,"%s calibration histogram sector %.2d",type,sector);
1238 // new histogram with calib information. One value for each pad!
1239 TH1S* hist = new TH1S(name,title,
1240 fLastTimeBin-fFirstTimeBin,fFirstTimeBin,fLastTimeBin);
1241 hist->SetDirectory(0);
1242 arr->AddAt(hist,sector);
1245 //_____________________________________________________________________
1246 TH1S* AliTPCCalibCE::GetHistoTmean(Int_t sector, Bool_t force)
1249 // return pointer to Q histogram
1250 // if force is true create a new histogram if it doesn't exist allready
1252 TObjArray *arr = &fHistoTmean;
1253 return GetHisto(sector, arr, "LastTmean", force);
1255 //_____________________________________________________________________
1256 TVectorF* AliTPCCalibCE::GetVectSector(Int_t sector, TObjArray *arr, UInt_t size, Bool_t force) const
1259 // return pointer to Pad Info from 'arr' for the current event and sector
1260 // if force is true create it if it doesn't exist allready
1262 if ( !force || arr->UncheckedAt(sector) )
1263 return (TVectorF*)arr->UncheckedAt(sector);
1265 TVectorF *vect = new TVectorF(size);
1266 arr->AddAt(vect,sector);
1269 //_____________________________________________________________________
1270 TVectorF* AliTPCCalibCE::GetPadTimesEvent(Int_t sector, Bool_t force)
1273 // return pointer to Pad Times Array for the current event and sector
1274 // if force is true create it if it doesn't exist allready
1276 TObjArray *arr = &fPadTimesArrayEvent;
1277 return GetVectSector(sector,arr,fROC->GetNChannels(sector),force);
1279 //_____________________________________________________________________
1280 TVectorF* AliTPCCalibCE::GetPadQEvent(Int_t sector, Bool_t force)
1283 // return pointer to Pad Q Array for the current event and sector
1284 // if force is true create it if it doesn't exist allready
1285 // for debugging purposes only
1288 TObjArray *arr = &fPadQArrayEvent;
1289 return GetVectSector(sector,arr,fROC->GetNChannels(sector),force);
1291 //_____________________________________________________________________
1292 TVectorF* AliTPCCalibCE::GetPadRMSEvent(Int_t sector, Bool_t force)
1295 // return pointer to Pad RMS Array for the current event and sector
1296 // if force is true create it if it doesn't exist allready
1297 // for debugging purposes only
1299 TObjArray *arr = &fPadRMSArrayEvent;
1300 return GetVectSector(sector,arr,fROC->GetNChannels(sector),force);
1302 //_____________________________________________________________________
1303 TVectorF* AliTPCCalibCE::GetPadPedestalEvent(Int_t sector, Bool_t force)
1306 // return pointer to Pad RMS Array for the current event and sector
1307 // if force is true create it if it doesn't exist allready
1308 // for debugging purposes only
1310 TObjArray *arr = &fPadPedestalArrayEvent;
1311 return GetVectSector(sector,arr,fROC->GetNChannels(sector),force);
1313 //_____________________________________________________________________
1314 TVectorF* AliTPCCalibCE::GetTMeanEvents(Int_t sector, Bool_t force)
1317 // return pointer to the EbyE info of the mean arrival time for 'sector'
1318 // if force is true create it if it doesn't exist allready
1320 TObjArray *arr = &fTMeanArrayEvent;
1321 return GetVectSector(sector,arr,100,force);
1323 //_____________________________________________________________________
1324 TVectorF* AliTPCCalibCE::GetQMeanEvents(Int_t sector, Bool_t force)
1327 // return pointer to the EbyE info of the mean arrival time for 'sector'
1328 // if force is true create it if it doesn't exist allready
1330 TObjArray *arr = &fQMeanArrayEvent;
1331 return GetVectSector(sector,arr,100,force);
1333 //_____________________________________________________________________
1334 AliTPCCalROC* AliTPCCalibCE::GetCalRoc(Int_t sector, TObjArray* arr, Bool_t force) const
1337 // return pointer to ROC Calibration
1338 // if force is true create a new histogram if it doesn't exist allready
1340 if ( !force || arr->UncheckedAt(sector) )
1341 return (AliTPCCalROC*)arr->UncheckedAt(sector);
1343 // if we are forced and histogram doesn't yes exist create it
1345 // new AliTPCCalROC for T0 information. One value for each pad!
1346 AliTPCCalROC *croc = new AliTPCCalROC(sector);
1347 arr->AddAt(croc,sector);
1350 //_____________________________________________________________________
1351 AliTPCCalROC* AliTPCCalibCE::GetCalRocT0(Int_t sector, Bool_t force)
1354 // return pointer to Carge ROC Calibration
1355 // if force is true create a new histogram if it doesn't exist allready
1357 TObjArray *arr = &fCalRocArrayT0;
1358 return GetCalRoc(sector, arr, force);
1360 //_____________________________________________________________________
1361 AliTPCCalROC* AliTPCCalibCE::GetCalRocQ(Int_t sector, Bool_t force)
1364 // return pointer to T0 ROC Calibration
1365 // if force is true create a new histogram if it doesn't exist allready
1367 TObjArray *arr = &fCalRocArrayQ;
1368 return GetCalRoc(sector, arr, force);
1370 //_____________________________________________________________________
1371 AliTPCCalROC* AliTPCCalibCE::GetCalRocRMS(Int_t sector, Bool_t force)
1374 // return pointer to signal width ROC Calibration
1375 // if force is true create a new histogram if it doesn't exist allready
1377 TObjArray *arr = &fCalRocArrayRMS;
1378 return GetCalRoc(sector, arr, force);
1380 //_____________________________________________________________________
1381 AliTPCCalROC* AliTPCCalibCE::GetCalRocOutliers(Int_t sector, Bool_t force)
1384 // return pointer to Outliers
1385 // if force is true create a new histogram if it doesn't exist allready
1387 TObjArray *arr = &fCalRocArrayOutliers;
1388 return GetCalRoc(sector, arr, force);
1390 //_____________________________________________________________________
1391 TObjArray* AliTPCCalibCE::GetParamArray(Int_t sector, TObjArray* arr, Bool_t force) const
1394 // return pointer to TObjArray of fit parameters
1395 // if force is true create a new histogram if it doesn't exist allready
1397 if ( !force || arr->UncheckedAt(sector) )
1398 return (TObjArray*)arr->UncheckedAt(sector);
1400 // if we are forced and array doesn't yes exist create it
1402 // new TObjArray for parameters
1403 TObjArray *newArr = new TObjArray;
1404 arr->AddAt(newArr,sector);
1407 //_____________________________________________________________________
1408 TObjArray* AliTPCCalibCE::GetParamArrayPol1(Int_t sector, Bool_t force)
1411 // return pointer to TObjArray of fit parameters from plane fit
1412 // if force is true create a new histogram if it doesn't exist allready
1414 TObjArray *arr = &fParamArrayEventPol1;
1415 return GetParamArray(sector, arr, force);
1417 //_____________________________________________________________________
1418 TObjArray* AliTPCCalibCE::GetParamArrayPol2(Int_t sector, Bool_t force)
1421 // return pointer to TObjArray of fit parameters from parabola fit
1422 // if force is true create a new histogram if it doesn't exist allready
1424 TObjArray *arr = &fParamArrayEventPol2;
1425 return GetParamArray(sector, arr, force);
1427 //_____________________________________________________________________
1428 void AliTPCCalibCE::ResetEvent()
1431 // Reset global counters -- Should be called before each event is processed
1440 fPadTimesArrayEvent.Delete();
1441 fPadQArrayEvent.Delete();
1442 fPadRMSArrayEvent.Delete();
1443 fPadPedestalArrayEvent.Delete();
1445 for ( Int_t i=0; i<72; ++i ){
1446 fVTime0Offset.GetMatrixArray()[i]=0;
1447 fVTime0OffsetCounter.GetMatrixArray()[i]=0;
1448 fVMeanQ.GetMatrixArray()[i]=0;
1449 fVMeanQCounter.GetMatrixArray()[i]=0;
1452 //_____________________________________________________________________
1453 void AliTPCCalibCE::ResetPad()
1456 // Reset pad infos -- Should be called after a pad has been processed
1458 for (Int_t i=fFirstTimeBin; i<fLastTimeBin+1; ++i)
1459 fPadSignal.GetMatrixArray()[i] = 0;
1465 //_____________________________________________________________________
1466 void AliTPCCalibCE::Merge(AliTPCCalibCE *ce)
1469 // Merge ce to the current AliTPCCalibCE
1473 for (Int_t iSec=0; iSec<72; ++iSec){
1474 TH2S *hRefQmerge = ce->GetHistoQ(iSec);
1475 TH2S *hRefT0merge = ce->GetHistoT0(iSec);
1476 TH2S *hRefRMSmerge = ce->GetHistoRMS(iSec);
1480 TDirectory *dir = hRefQmerge->GetDirectory(); hRefQmerge->SetDirectory(0);
1481 TH2S *hRefQ = GetHistoQ(iSec);
1482 if ( hRefQ ) hRefQ->Add(hRefQmerge);
1484 TH2S *hist = new TH2S(*hRefQmerge);
1485 hist->SetDirectory(0);
1486 fHistoQArray.AddAt(hist, iSec);
1488 hRefQmerge->SetDirectory(dir);
1491 TDirectory *dir = hRefT0merge->GetDirectory(); hRefT0merge->SetDirectory(0);
1492 TH2S *hRefT0 = GetHistoT0(iSec);
1493 if ( hRefT0 ) hRefT0->Add(hRefT0merge);
1495 TH2S *hist = new TH2S(*hRefT0merge);
1496 hist->SetDirectory(0);
1497 fHistoT0Array.AddAt(hist, iSec);
1499 hRefT0merge->SetDirectory(dir);
1501 if ( hRefRMSmerge ){
1502 TDirectory *dir = hRefRMSmerge->GetDirectory(); hRefRMSmerge->SetDirectory(0);
1503 TH2S *hRefRMS = GetHistoRMS(iSec);
1504 if ( hRefRMS ) hRefRMS->Add(hRefRMSmerge);
1506 TH2S *hist = new TH2S(*hRefRMSmerge);
1507 hist->SetDirectory(0);
1508 fHistoRMSArray.AddAt(hist, iSec);
1510 hRefRMSmerge->SetDirectory(dir);
1515 // merge time information
1518 Int_t nCEevents = ce->GetNeventsProcessed();
1519 for (Int_t iSec=0; iSec<72; ++iSec){
1520 TObjArray *arrPol1CE = ce->GetParamArrayPol1(iSec);
1521 TObjArray *arrPol2CE = ce->GetParamArrayPol2(iSec);
1522 TVectorF *vMeanTimeCE = ce->GetTMeanEvents(iSec);
1523 TVectorF *vMeanQCE = ce->GetQMeanEvents(iSec);
1525 TObjArray *arrPol1 = 0x0;
1526 TObjArray *arrPol2 = 0x0;
1527 TVectorF *vMeanTime = 0x0;
1528 TVectorF *vMeanQ = 0x0;
1531 if ( arrPol1CE && arrPol2CE ){
1532 arrPol1 = GetParamArrayPol1(iSec,kTRUE);
1533 arrPol2 = GetParamArrayPol2(iSec,kTRUE);
1534 arrPol1->Expand(fNevents+nCEevents);
1535 arrPol2->Expand(fNevents+nCEevents);
1537 if ( vMeanTimeCE && vMeanQCE ){
1538 vMeanTime = GetTMeanEvents(iSec,kTRUE);
1539 vMeanQ = GetQMeanEvents(iSec,kTRUE);
1540 vMeanTime->ResizeTo(fNevents+nCEevents);
1541 vMeanQ->ResizeTo(fNevents+nCEevents);
1545 for (Int_t iEvent=0; iEvent<nCEevents; ++iEvent){
1546 if ( arrPol1CE && arrPol2CE ){
1547 TVectorD *paramPol1 = (TVectorD*)(arrPol1CE->UncheckedAt(iEvent));
1548 TVectorD *paramPol2 = (TVectorD*)(arrPol2CE->UncheckedAt(iEvent));
1549 if ( paramPol1 && paramPol2 ){
1550 GetParamArrayPol1(iSec,kTRUE)->AddAt(new TVectorD(*paramPol1), fNevents+iEvent);
1551 GetParamArrayPol2(iSec,kTRUE)->AddAt(new TVectorD(*paramPol2), fNevents+iEvent);
1554 if ( vMeanTimeCE && vMeanQCE ){
1555 vMeanTime->GetMatrixArray()[fNevents+iEvent]=vMeanTimeCE->GetMatrixArray()[iEvent];
1556 vMeanQ->GetMatrixArray()[fNevents+iEvent]=vMeanQCE->GetMatrixArray()[iEvent];
1563 TVectorD* eventTimes = ce->GetEventTimes();
1564 TVectorD* eventIds = ce->GetEventIds();
1565 fVEventTime.ResizeTo(fNevents+nCEevents);
1566 fVEventNumber.ResizeTo(fNevents+nCEevents);
1568 for (Int_t iEvent=0; iEvent<nCEevents; ++iEvent){
1569 Double_t evTime = eventTimes->GetMatrixArray()[iEvent];
1570 Double_t evId = eventIds->GetMatrixArray()[iEvent];
1571 fVEventTime.GetMatrixArray()[fNevents+iEvent] = evTime;
1572 fVEventNumber.GetMatrixArray()[fNevents+iEvent] = evId;
1574 fNevents+=nCEevents; //increase event counter
1577 //_____________________________________________________________________
1578 TGraph *AliTPCCalibCE::MakeGraphTimeCE(Int_t sector, Int_t xVariable, Int_t fitType, Int_t fitParameter)
1581 // Make graph from fit parameters of pol1 fit, pol2 fit, mean arrival time or mean Q for ROC 'sector'
1582 // xVariable: 0-event time, 1-event id, 2-internal event counter
1583 // fitType: 0-pol1 fit, 1-pol2 fit, 2-mean time, 3-mean Q
1584 // fitParameter: fit parameter ( 0-2 for pol1 ([0]+[1]*x+[2]*y),
1585 // 0-5 for pol2 ([0]+[1]*x+[2]*y+[3]*x*x+[4]*y*y+[5]*x*y),
1586 // not used for mean time and mean Q )
1587 // for an example see class description at the beginning
1590 Double_t *x = new Double_t[fNevents];
1591 Double_t *y = new Double_t[fNevents];
1593 TVectorD *xVar = 0x0;
1594 TObjArray *aType = 0x0;
1598 if ( (sector<0) || (sector>71) ) return 0x0;
1599 if ( (xVariable<0) || (xVariable>2) ) return 0x0;
1600 if ( (fitType<0) || (fitType>3) ) return 0x0;
1602 if ( (fitParameter<0) || (fitParameter>2) ) return 0x0;
1603 aType = &fParamArrayEventPol1;
1604 if ( aType->At(sector)==0x0 ) return 0x0;
1606 else if ( fitType==1 ){
1607 if ( (fitParameter<0) || (fitParameter>5) ) return 0x0;
1608 aType = &fParamArrayEventPol2;
1609 if ( aType->At(sector)==0x0 ) return 0x0;
1613 if ( xVariable == 0 ) xVar = &fVEventTime;
1614 if ( xVariable == 1 ) xVar = &fVEventNumber;
1615 if ( xVariable == 2 ) {
1616 xVar = new TVectorD(fNevents);
1617 for ( Int_t i=0;i<fNevents; ++i) (*xVar)[i]=i;
1620 for (Int_t ievent =0; ievent<fNevents; ++ievent){
1622 TObjArray *events = (TObjArray*)(aType->At(sector));
1623 if ( events->GetSize()<=ievent ) break;
1624 TVectorD *v = (TVectorD*)(events->At(ievent));
1625 if ( (v!=0x0) && ((*xVar)[ievent]>0) ) { x[npoints]=(*xVar)[ievent]; y[npoints]=(*v)[fitParameter]; npoints++;}
1626 } else if (fitType == 2) {
1627 Double_t xValue=(*xVar)[ievent];
1628 Double_t yValue=(*GetTMeanEvents(sector))[ievent];
1629 if ( yValue>0 && xValue>0 ) { x[npoints]=xValue; y[npoints]=yValue;npoints++;}
1630 }else if (fitType == 3) {
1631 Double_t xValue=(*xVar)[ievent];
1632 Double_t yValue=(*GetQMeanEvents(sector))[ievent];
1633 if ( yValue>0 && xValue>0 ) { x[npoints]=xValue; y[npoints]=yValue;npoints++;}
1637 TGraph *gr = new TGraph(npoints);
1638 //sort xVariable increasing
1639 Int_t *sortIndex = new Int_t[npoints];
1640 TMath::Sort(npoints,x,sortIndex);
1641 for (Int_t i=0;i<npoints;++i){
1642 gr->SetPoint(i,x[sortIndex[i]],y[sortIndex[i]]);
1646 if ( xVariable == 2 ) delete xVar;
1652 //_____________________________________________________________________
1653 void AliTPCCalibCE::Analyse()
1656 // Calculate calibration constants
1660 TVectorD paramT0(3);
1661 TVectorD paramRMS(3);
1662 TMatrixD dummy(3,3);
1664 for (Int_t iSec=0; iSec<72; ++iSec){
1665 TH2S *hT0 = GetHistoT0(iSec);
1666 if (!hT0 ) continue;
1668 AliTPCCalROC *rocQ = GetCalRocQ (iSec,kTRUE);
1669 AliTPCCalROC *rocT0 = GetCalRocT0 (iSec,kTRUE);
1670 AliTPCCalROC *rocRMS = GetCalRocRMS(iSec,kTRUE);
1671 AliTPCCalROC *rocOut = GetCalRocOutliers(iSec,kTRUE);
1673 TH2S *hQ = GetHistoQ(iSec);
1674 TH2S *hRMS = GetHistoRMS(iSec);
1676 Short_t *arrayhQ = hQ->GetArray();
1677 Short_t *arrayhT0 = hT0->GetArray();
1678 Short_t *arrayhRMS = hRMS->GetArray();
1680 UInt_t nChannels = fROC->GetNChannels(iSec);
1688 for (UInt_t iChannel=0; iChannel<nChannels; ++iChannel){
1691 Float_t cogTime0 = -1000;
1692 Float_t cogQ = -1000;
1693 Float_t cogRMS = -1000;
1697 Int_t offsetQ = (fNbinsQ+2)*(iChannel+1)+1;
1698 Int_t offsetT0 = (fNbinsT0+2)*(iChannel+1)+1;
1699 Int_t offsetRMS = (fNbinsRMS+2)*(iChannel+1)+1;
1701 cogQ = AliMathBase::GetCOG(arrayhQ+offsetQ,fNbinsQ,fXminQ,fXmaxQ);
1702 cogTime0 = AliMathBase::GetCOG(arrayhT0+offsetT0,fNbinsT0,fXminT0,fXmaxT0);
1703 cogRMS = AliMathBase::GetCOG(arrayhRMS+offsetRMS,fNbinsRMS,fXminRMS,fXmaxRMS);
1708 //outlier specifications
1709 if ( (cogQ < ??) && (cogTime0 > ??) && (cogTime0<??) && ( cogRMS>??) ){
1716 rocQ->SetValue(iChannel, cogQ*cogQ);
1717 rocT0->SetValue(iChannel, cogTime0);
1718 rocRMS->SetValue(iChannel, cogRMS);
1719 rocOut->SetValue(iChannel, cogOut);
1723 if ( fDebugLevel > 0 ){
1724 if ( !fDebugStreamer ) {
1726 TDirectory *backup = gDirectory;
1727 fDebugStreamer = new TTreeSRedirector("debugCalibCEAnalysis.root");
1728 if ( backup ) backup->cd(); //we don't want to be cd'd to the debug streamer
1731 while ( iChannel > (fROC->GetRowIndexes(iSec)[row]+fROC->GetNPads(iSec,row)-1) ) row++;
1732 pad = iChannel-fROC->GetRowIndexes(iSec)[row];
1733 padc = pad-(fROC->GetNPads(iSec,row)/2);
1735 (*fDebugStreamer) << "DataEnd" <<
1736 "Sector=" << iSec <<
1740 "PadSec=" << iChannel <<
1742 "T0=" << cogTime0 <<
1751 if ( fDebugStreamer ) fDebugStreamer->GetFile()->Write();
1752 // delete fDebugStreamer;
1753 // fDebugStreamer = 0x0;
1755 //_____________________________________________________________________
1756 void AliTPCCalibCE::DumpToFile(const Char_t *filename, const Char_t *dir, Bool_t append)
1759 // Write class to file
1768 option = "recreate";
1770 TDirectory *backup = gDirectory;
1771 TFile f(filename,option.Data());
1773 if ( !sDir.IsNull() ){
1774 f.mkdir(sDir.Data());
1780 if ( backup ) backup->cd();