Line data Source code
1 : /**************************************************************************
2 : * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3 : * *
4 : * Author: The ALICE Off-line Project. *
5 : * Contributors are mentioned in the code where appropriate. *
6 : * *
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 : **************************************************************************/
15 :
16 : /// \class AliTPCCalibCE
17 : /// \brief Implementation of the TPC Central Electrode calibration
18 : ///
19 : /// \author Jens Wiechula, Marian Ivanov J.Wiechula@gsi.de, Marian.Ivanov@cern.ch
20 : ///
21 : /// Class Description
22 : /// The AliTPCCalibCE class is used to get calibration data from the Central Electrode
23 : /// using laser runs.
24 : ///
25 : /// The information retrieved is
26 : /// <ul style="list-style-type: square;">
27 : /// <li>Time arrival from the CE</li>
28 : /// <li>Signal width</li>
29 : /// <li>Signal sum</li>
30 : /// </ul>
31 : ///
32 : /// <h4>Overview:</h4>
33 : /// <ol style="list-style-type: upper-roman;">
34 : /// <li><a href="#working">Working principle</a></li>
35 : /// <li><a href="#user">User interface for filling data</a></li>
36 : /// <li><a href="#info">Stored information</a></li>
37 : /// </ol>
38 : ///
39 : /// <h3><a name="working">I. Working principle</a></h3>
40 : ///
41 : /// <h4>Raw laser data is processed by calling one of the ProcessEvent(...) functions
42 : /// (see below). These in the end call the Update(...) function.</h4>
43 : ///
44 : /// <ul style="list-style-type: square;">
45 : /// <li>the Update(...) function:<br />
46 : /// In this function the array fPadSignal is filled with the adc signals between the specified range
47 : /// fFirstTimeBin and fLastTimeBin for the current pad.
48 : /// before going to the next pad the ProcessPad() function is called, which analyses the data for one pad
49 : /// stored in fPadSignal.
50 : /// </li>
51 : /// <ul style="list-style-type: square;">
52 : /// <li>the ProcessPad() function:</li>
53 : /// <ol style="list-style-type: decimal;">
54 : /// <li>Find Pedestal and Noise information</li>
55 : /// <ul style="list-style-type: square;">
56 : /// <li>use database information which has to be set by calling<br />
57 : /// SetPedestalDatabase(AliTPCCalPad *pedestalTPC, AliTPCCalPad *padNoiseTPC)</li>
58 : /// <li>if no information from the pedestal data base
59 : /// is available the informaion is calculated on the fly
60 : /// ( see FindPedestal() function )</li>
61 : /// </ul>
62 : /// <li>Find local maxima of the pad signal</li>
63 : /// <ul style="list-style-type: square;">
64 : /// <li>maxima arise from the laser tracks, the CE and also periodic postpeaks after the CE signal have
65 : /// have been observed ( see FindLocalMaxima(...) )</li>
66 : /// </ul>
67 : /// <li>Find the CE signal information</li>
68 : /// <ul style="list-style-type: square;">
69 : /// <li>to find the position of the CE signal the Tmean information from the previos event is used
70 : /// as the CE signal the local maximum closest to this Tmean is identified</li>
71 : /// <li>calculate mean = T0, RMS = signal width and Q sum in a range of -4+7 timebins around Q max position
72 : /// the Q sum is scaled by pad area (see FindPulserSignal(...) function)</li>
73 : /// </ul>
74 : /// <li>Fill a temprary array for the T0 information (GetPadTimesEvent(fCurrentSector,kTRUE)) (why see below)</li>
75 : /// <li>Fill the Q sum and RMS values in the histograms (GetHisto[RMS,Q](ROC,kTRUE))</li>
76 : /// </ol>
77 : /// </ul>
78 : /// </ul>
79 : ///
80 : /// <h4>At the end of each event the EndEvent() function is called</h4>
81 : ///
82 : /// <ul style="list-style-type: square;">
83 : /// <li>the EndEvent() function:</li>
84 : /// <ul style="list-style-type: square;">
85 : /// <li>calculate the mean T0 for side A and side C. Fill T0 histogram with Time0-<Time0 for side[A,C]>
86 : /// This is done to overcome syncronisation problems between the trigger and the fec clock.</li>
87 : /// <li>calculate Mean T for each ROC using the COG aroud the median of the LocalMaxima distribution in one sector</li>
88 : /// <li>calculate Mean Q</li>
89 : /// <li>calculate Global fit parameters for Pol1 and Pol2 fits</li>
90 : /// </ul>
91 : /// </ul>
92 : ///
93 : /// <h4>After accumulating the desired statistics the Analyse() function has to be called.</h4>
94 : /// <ul style="list-style-type: square;">
95 : /// <li>the Analyse() function:</li>
96 : /// <ul style="list-style-type: square;">
97 : /// <li>calculate the mean values of T0, RMS, Q for each pad, using
98 : /// the AliMathBase::GetCOG(...) function</li>
99 : /// <li>fill the calibration storage classes (AliTPCCalROC) for each ROC</li>
100 : /// (The calibration information is stored in the TObjArrays fCalRocArrayT0, fCalRocArrayRMS and fCalRocArrayQ</li>
101 : /// </ul>
102 : /// </ul>
103 : ///
104 : /// <h3><a name="user">II. User interface for filling data</a></h3>
105 : ///
106 : /// <h4>To Fill information one of the following functions can be used:</h4>
107 : ///
108 : /// <ul style="list-style-type: none;">
109 : /// <li> Bool_t ProcessEvent(eventHeaderStruct *event);</li>
110 : /// <ul style="list-style-type: square;">
111 : /// <li>process Date event</li>
112 : /// <li>use AliTPCRawReaderDate and call ProcessEvent(AliRawReader *rawReader)</li>
113 : /// </ul>
114 : /// <br />
115 : ///
116 : /// <li> Bool_t ProcessEvent(AliRawReader *rawReader);</li>
117 : /// <ul style="list-style-type: square;">
118 : /// <li>process AliRawReader event</li>
119 : /// <li>use AliTPCRawStream to loop over data and call ProcessEvent(AliTPCRawStream *rawStream)</li>
120 : /// </ul>
121 : /// <br />
122 : ///
123 : /// <li> Bool_t ProcessEvent(AliTPCRawStream *rawStream);</li>
124 : /// <ul style="list-style-type: square;">
125 : /// <li>process event from AliTPCRawStream</li>
126 : /// <li>call Update function for signal filling</li>
127 : /// </ul>
128 : /// <br />
129 : ///
130 : /// <li> Int_t Update(const Int_t isector, const Int_t iRow, const Int_t
131 : /// iPad, const Int_t iTimeBin, const Float_t signal);</li>
132 : /// <ul style="list-style-type: square;">
133 : /// <li>directly fill signal information (sector, row, pad, time bin, pad)
134 : /// to the reference histograms</li>
135 : /// </ul>
136 : /// </ul>
137 : ///
138 : /// <h4>It is also possible to merge two independently taken calibrations using the function</h4>
139 : ///
140 : /// <ul style="list-style-type: none;">
141 : /// <li> void Merge(AliTPCCalibSignal *sig)</li>
142 : /// <ul style="list-style-type: square;">
143 : /// <li>copy histograms in 'sig' if they do not exist in this instance</li>
144 : /// <li>Add histograms in 'sig' to the histograms in this instance if the allready exist</li>
145 : /// <li>After merging call Analyse again!</li>
146 : /// </ul>
147 : /// </ul>
148 : ///
149 : ///
150 : /// <h4>example: filling data using root raw data:</h4>
151 : /// <pre>
152 : /// void fillCE(Char_t *filename)
153 : /// {
154 : /// rawReader = new AliRawReaderRoot(fileName);
155 : /// if ( !rawReader ) return;
156 : /// AliTPCCalibCE *calib = new AliTPCCalibCE;
157 : /// while (rawReader->NextEvent()){
158 : /// calib->ProcessEvent(rawReader);
159 : /// }
160 : /// calib->Analyse();
161 : /// calib->DumpToFile("CEData.root");
162 : /// delete rawReader;
163 : /// delete calib;
164 : /// }
165 : /// </pre>
166 : ///
167 : /// <h3><a name="info">III. What kind of information is stored and how to retrieve it</a></h4>
168 : ///
169 : /// <h4><a name="info:stored">III.1 Stored information</a></h4>
170 : /// <ul style="list-style-type: none;">
171 : /// <li>Histograms:</li>
172 : /// <ul style="list-style-type: none;">
173 : /// <li>For each ROC three TH2S histos 'Reference Histograms' (ROC channel vs. [Time0, signal width, Q sum])
174 : /// is created when it is filled for the first time (GetHisto[T0,RMS,Q](ROC,kTRUE)). The histos are
175 : /// stored in the TObjArrays fHistoT0Array, fHistoRMSArray and fHistoQArray.</li>
176 : /// </ul>
177 : /// <br />
178 : ///
179 : /// <li>Calibration Data:</li>
180 : /// <ul style="list-style-type: none;">
181 : /// <li>For each ROC three types of calibration data (AliTPCCalROC) is stored: for the mean arrival Time,
182 : /// the signal width and the signal Sum. The AliTPCCalROC objects are stored in the TObjArrays
183 : /// fCalRocArrayT0, fCalRocArrayRMS , fCalRocArrayQ. The object for each roc is created the first time it
184 : /// is accessed (GetCalRoc[T0,RMS,Q](ROC,kTRUE));</li>
185 : /// </ul>
186 : /// <br />
187 : ///
188 : /// <li>For each event the following information is stored:</li>
189 : ///
190 : /// <ul style="list-style-type: square;">
191 : /// <li>event time ( TVectorD fVEventTime )</li>
192 : /// <li>event id ( TVectorD fVEventNumber )</li>
193 : /// <br />
194 : /// <li>mean arrival time for each ROC ( TObjArray fTMeanArrayEvent )</li>
195 : /// <li>mean Q for each ROC ( TObjArray fQMeanArrayEvent )</li>
196 : /// <li>parameters of a plane fit for each ROC ( TObjArray fParamArrayEventPol1 )</li>
197 : /// <li>parameters of a 2D parabola fit for each ROC ( TObjArray fParamArrayEventPol2 )</li>
198 : /// </ul>
199 : /// </ul>
200 : ///
201 : /// <h4><a name="info:retrieve">III.2 Retrieving information</a></h4>
202 : /// <ul style="list-style-type: none;">
203 : /// <li>Accessing the 'Reference Histograms' (Time0, signal width and Q sum information pad by pad):</li>
204 : /// <ul style="list-style-type: square;">
205 : /// <li>TH2F *GetHistoT0(Int_t sector);</li>
206 : /// <li>TH2F *GetHistoRMS(Int_t sector);</li>
207 : /// <li>TH2F *GetHistoQ(Int_t sector);</li>
208 : /// </ul>
209 : /// <br />
210 : ///
211 : /// <li>Accessing the calibration storage objects:</li>
212 : /// <ul style="list-style-type: square;">
213 : /// <li>AliTPCCalROC *GetCalRocT0(Int_t sector); // for the Time0 values</li>
214 : /// <li>AliTPCCalROC *GetCalRocRMS(Int_t sector); // for the signal width values</li>
215 : /// <li>AliTPCCalROC *GetCalRocQ(Int_t sector); // for the Q sum values</li>
216 : /// </ul>
217 : /// <br />
218 : ///
219 : /// <li>Accessin the event by event information:</li>
220 : /// <ul style="list-style-type: square;">
221 : /// <li>The event by event information can be displayed using the</li>
222 : /// <li>MakeGraphTimeCE(Int_t sector, Int_t xVariable, Int_t fitType, Int_t fitParameter)</li>
223 : /// <li>which creates a graph from the specified variables</li>
224 : /// </ul>
225 : /// </ul>
226 : ///
227 : /// <h4>example for visualisation:</h4>
228 : /// <pre>
229 : /// //if the file "CEData.root" was created using the above example one could do the following:
230 : /// TFile fileCE("CEData.root")
231 : /// AliTPCCalibCE *ce = (AliTPCCalibCE*)fileCE->Get("AliTPCCalibCE");
232 : /// ce->GetCalRocT0(0)->Draw("colz");
233 : /// ce->GetCalRocRMS(0)->Draw("colz");
234 : ///
235 : /// //or use the AliTPCCalPad functionality:
236 : /// AliTPCCalPad padT0(ped->GetCalPadT0());
237 : /// AliTPCCalPad padSigWidth(ped->GetCalPadRMS());
238 : /// padT0->MakeHisto2D()->Draw("colz"); //Draw A-Side Time0 Information
239 : /// padSigWidth->MakeHisto2D()->Draw("colz"); //Draw A-Side signal width Information
240 : ///
241 : /// //display event by event information:
242 : /// //Draw mean arrival time as a function of the event time for oroc sector A00
243 : /// ce->MakeGraphTimeCE(36, 0, 2)->Draw("alp");
244 : /// //Draw first derivative in local x from a plane fit as a function of the event time for oroc sector A00
245 : /// ce->MakeGraphTimeCE(36, 0, 0, 1)->Draw("alp");
246 : /// </pre>
247 :
248 : //Root includes
249 : #include <TObjArray.h>
250 : #include <TH1.h>
251 : #include <TH1F.h>
252 : #include <TH2S.h>
253 : #include <TF1.h>
254 : #include <TString.h>
255 : #include <TVectorF.h>
256 : #include <TVectorD.h>
257 : #include <TVector3.h>
258 : #include <TMatrixD.h>
259 : #include <TMath.h>
260 : #include <TGraph.h>
261 : #include <TGraphErrors.h>
262 : #include <TString.h>
263 : #include <TMap.h>
264 : #include <TDirectory.h>
265 : #include <TSystem.h>
266 : #include <TFile.h>
267 : #include <TCollection.h>
268 : #include <TTimeStamp.h>
269 : #include <TList.h>
270 : #include <TKey.h>
271 : #include <TSpectrum.h>
272 :
273 : //AliRoot includes
274 : #include "AliLog.h"
275 : #include "AliRawReader.h"
276 : #include "AliRawReaderRoot.h"
277 : #include "AliRawReaderDate.h"
278 : #include "AliRawEventHeaderBase.h"
279 : #include "AliTPCCalROC.h"
280 : #include "AliTPCCalPad.h"
281 : #include "AliTPCROC.h"
282 : #include "AliTPCParam.h"
283 : #include "AliTPCCalibCE.h"
284 : #include "AliMathBase.h"
285 : #include "AliTPCTransform.h"
286 : #include "AliTPCLaserTrack.h"
287 : #include "TTreeStream.h"
288 :
289 : #include "AliCDBManager.h"
290 : #include "AliCDBEntry.h"
291 : //date
292 : #include "event.h"
293 : /// \cond CLASSIMP
294 24 : ClassImp(AliTPCCalibCE)
295 : /// \endcond
296 :
297 :
298 : AliTPCCalibCE::AliTPCCalibCE() :
299 0 : AliTPCCalibRawBase(),
300 0 : fNbinsT0(200),
301 0 : fXminT0(-5),
302 0 : fXmaxT0(5),
303 0 : fNbinsQ(200),
304 0 : fXminQ(1),
305 0 : fXmaxQ(40),
306 0 : fNbinsRMS(100),
307 0 : fXminRMS(0.1),
308 0 : fXmaxRMS(5.1),
309 0 : fPeakDetMinus(2),
310 0 : fPeakDetPlus(3),
311 0 : fPeakIntMinus(2),
312 0 : fPeakIntPlus(2),
313 0 : fNoiseThresholdMax(5.),
314 0 : fNoiseThresholdSum(8.),
315 0 : fROCblackDataDown(-1),
316 0 : fROCblackDataUp(-1),
317 0 : fIsZeroSuppressed(kFALSE),
318 0 : fLastSector(-1),
319 0 : fSecRejectRatio(.4),
320 0 : fParam(new AliTPCParam),
321 0 : fPedestalTPC(0x0),
322 0 : fPadNoiseTPC(0x0),
323 0 : fPedestalROC(0x0),
324 0 : fPadNoiseROC(0x0),
325 0 : fCalRocArrayT0(72),
326 0 : fCalRocArrayT0Err(72),
327 0 : fCalRocArrayQ(72),
328 0 : fCalRocArrayRMS(72),
329 0 : fCalRocArrayOutliers(72),
330 0 : fHistoQArray(72),
331 0 : fHistoT0Array(72),
332 0 : fHistoRMSArray(72),
333 0 : fMeanT0rms(0),
334 0 : fMeanQrms(0),
335 0 : fMeanRMSrms(0),
336 0 : fHistoTmean(72),
337 0 : fParamArrayEventPol1(72),
338 0 : fParamArrayEventPol2(72),
339 0 : fTMeanArrayEvent(72),
340 0 : fQMeanArrayEvent(72),
341 0 : fVEventTime(1000),
342 0 : fVEventNumber(1000),
343 0 : fVTime0SideA(1000),
344 0 : fVTime0SideC(1000),
345 0 : fEventId(-1),
346 0 : fOldRunNumber(0),
347 0 : fPadTimesArrayEvent(72),
348 0 : fPadQArrayEvent(72),
349 0 : fPadRMSArrayEvent(72),
350 0 : fPadPedestalArrayEvent(72),
351 0 : fCurrentChannel(-1),
352 0 : fCurrentSector(-1),
353 0 : fCurrentRow(-1),
354 0 : fMaxPadSignal(-1),
355 0 : fMaxTimeBin(-1),
356 : // fPadSignal(1024),
357 0 : fPadPedestal(0),
358 0 : fPadNoise(0),
359 0 : fVTime0Offset(72),
360 0 : fVTime0OffsetCounter(72),
361 0 : fVMeanQ(72),
362 0 : fVMeanQCounter(72),
363 0 : fCurrentCETimeRef(0),
364 0 : fProcessOld(kTRUE),
365 0 : fProcessNew(kFALSE),
366 0 : fAnalyseNew(kTRUE),
367 0 : fHnDrift(0x0),
368 0 : fArrHnDrift(100),
369 0 : fTimeBursts(100),
370 0 : fArrFitGraphs(0x0),
371 0 : fEventInBunch(0)
372 0 : {
373 : //
374 : // AliTPCSignal default constructor
375 : //
376 0 : SetNameTitle("AliTPCCalibCE","AliTPCCalibCE");
377 0 : fFirstTimeBin=650;
378 0 : fLastTimeBin=1030;
379 0 : fParam->Update();
380 0 : for (Int_t i=0;i<1024;++i) fPadSignal[i]=0;
381 0 : for (Int_t i=0;i<14;++i){
382 0 : fPeaks[i]=0;
383 0 : fPeakWidths[i]=0;
384 : }
385 0 : for (Int_t i=0; i<100; ++i) fBinsLastAna[i]=0;
386 0 : }
387 : //_____________________________________________________________________
388 : AliTPCCalibCE::AliTPCCalibCE(const AliTPCCalibCE &sig) :
389 0 : AliTPCCalibRawBase(sig),
390 0 : fNbinsT0(sig.fNbinsT0),
391 0 : fXminT0(sig.fXminT0),
392 0 : fXmaxT0(sig.fXmaxT0),
393 0 : fNbinsQ(sig.fNbinsQ),
394 0 : fXminQ(sig.fXminQ),
395 0 : fXmaxQ(sig.fXmaxQ),
396 0 : fNbinsRMS(sig.fNbinsRMS),
397 0 : fXminRMS(sig.fXminRMS),
398 0 : fXmaxRMS(sig.fXmaxRMS),
399 0 : fPeakDetMinus(sig.fPeakDetMinus),
400 0 : fPeakDetPlus(sig.fPeakDetPlus),
401 0 : fPeakIntMinus(sig.fPeakIntMinus),
402 0 : fPeakIntPlus(sig.fPeakIntPlus),
403 0 : fNoiseThresholdMax(sig.fNoiseThresholdMax),
404 0 : fNoiseThresholdSum(sig.fNoiseThresholdSum),
405 0 : fROCblackDataDown(-1),
406 0 : fROCblackDataUp(-1),
407 0 : fIsZeroSuppressed(sig.fIsZeroSuppressed),
408 0 : fLastSector(-1),
409 0 : fSecRejectRatio(.4),
410 0 : fParam(new AliTPCParam),
411 0 : fPedestalTPC(0x0),
412 0 : fPadNoiseTPC(0x0),
413 0 : fPedestalROC(0x0),
414 0 : fPadNoiseROC(0x0),
415 0 : fCalRocArrayT0(72),
416 0 : fCalRocArrayT0Err(72),
417 0 : fCalRocArrayQ(72),
418 0 : fCalRocArrayRMS(72),
419 0 : fCalRocArrayOutliers(72),
420 0 : fHistoQArray(72),
421 0 : fHistoT0Array(72),
422 0 : fHistoRMSArray(72),
423 0 : fMeanT0rms(sig.fMeanT0rms),
424 0 : fMeanQrms(sig.fMeanQrms),
425 0 : fMeanRMSrms(sig.fMeanRMSrms),
426 0 : fHistoTmean(72),
427 0 : fParamArrayEventPol1(72),
428 0 : fParamArrayEventPol2(72),
429 0 : fTMeanArrayEvent(72),
430 0 : fQMeanArrayEvent(72),
431 0 : fVEventTime(sig.fVEventTime),
432 0 : fVEventNumber(sig.fVEventNumber),
433 0 : fVTime0SideA(sig.fVTime0SideA),
434 0 : fVTime0SideC(sig.fVTime0SideC),
435 0 : fEventId(-1),
436 0 : fOldRunNumber(0),
437 0 : fPadTimesArrayEvent(72),
438 0 : fPadQArrayEvent(72),
439 0 : fPadRMSArrayEvent(72),
440 0 : fPadPedestalArrayEvent(72),
441 0 : fCurrentChannel(-1),
442 0 : fCurrentSector(-1),
443 0 : fCurrentRow(-1),
444 0 : fMaxPadSignal(-1),
445 0 : fMaxTimeBin(-1),
446 : // fPadSignal(1024),
447 0 : fPadPedestal(0),
448 0 : fPadNoise(0),
449 0 : fVTime0Offset(72),
450 0 : fVTime0OffsetCounter(72),
451 0 : fVMeanQ(72),
452 0 : fVMeanQCounter(72),
453 0 : fCurrentCETimeRef(0),
454 0 : fProcessOld(sig.fProcessOld),
455 0 : fProcessNew(sig.fProcessNew),
456 0 : fAnalyseNew(sig.fAnalyseNew),
457 0 : fHnDrift(0x0),
458 0 : fArrHnDrift(100),
459 0 : fTimeBursts(100),
460 0 : fArrFitGraphs(0x0),
461 0 : fEventInBunch(0)
462 0 : {
463 : /// AliTPCSignal copy constructor
464 :
465 0 : for (Int_t i=0;i<1024;++i) fPadSignal[i]=0;
466 :
467 0 : for (Int_t iSec = 0; iSec < 72; ++iSec){
468 0 : const AliTPCCalROC *calQ = (AliTPCCalROC*)sig.fCalRocArrayQ.UncheckedAt(iSec);
469 0 : const AliTPCCalROC *calT0 = (AliTPCCalROC*)sig.fCalRocArrayT0.UncheckedAt(iSec);
470 0 : const AliTPCCalROC *calRMS = (AliTPCCalROC*)sig.fCalRocArrayRMS.UncheckedAt(iSec);
471 0 : const AliTPCCalROC *calOut = (AliTPCCalROC*)sig.fCalRocArrayOutliers.UncheckedAt(iSec);
472 :
473 0 : const TH2S *hQ = (TH2S*)sig.fHistoQArray.UncheckedAt(iSec);
474 0 : const TH2S *hT0 = (TH2S*)sig.fHistoT0Array.UncheckedAt(iSec);
475 0 : const TH2S *hRMS = (TH2S*)sig.fHistoRMSArray.UncheckedAt(iSec);
476 :
477 0 : if ( calQ != 0x0 ) fCalRocArrayQ.AddAt(new AliTPCCalROC(*calQ), iSec);
478 0 : if ( calT0 != 0x0 ) fCalRocArrayT0.AddAt(new AliTPCCalROC(*calT0), iSec);
479 0 : if ( calRMS != 0x0 ) fCalRocArrayRMS.AddAt(new AliTPCCalROC(*calRMS), iSec);
480 0 : if ( calOut != 0x0 ) fCalRocArrayOutliers.AddAt(new AliTPCCalROC(*calOut), iSec);
481 :
482 0 : if ( hQ != 0x0 ){
483 0 : TH2S *hNew = new TH2S(*hQ);
484 0 : hNew->SetDirectory(0);
485 0 : fHistoQArray.AddAt(hNew,iSec);
486 0 : }
487 0 : if ( hT0 != 0x0 ){
488 0 : TH2S *hNew = new TH2S(*hT0);
489 0 : hNew->SetDirectory(0);
490 0 : fHistoT0Array.AddAt(hNew,iSec);
491 0 : }
492 0 : if ( hRMS != 0x0 ){
493 0 : TH2S *hNew = new TH2S(*hRMS);
494 0 : hNew->SetDirectory(0);
495 0 : fHistoRMSArray.AddAt(hNew,iSec);
496 0 : }
497 : }
498 :
499 : //copy fit parameters event by event
500 : TObjArray *arr=0x0;
501 0 : for (Int_t iSec=0; iSec<72; ++iSec){
502 0 : arr = (TObjArray*)sig.fParamArrayEventPol1.UncheckedAt(iSec);
503 0 : if ( arr ){
504 0 : TObjArray *arrEvents = new TObjArray(arr->GetSize());
505 0 : fParamArrayEventPol1.AddAt(arrEvents, iSec);
506 0 : for (Int_t iEvent=0; iEvent<arr->GetSize(); ++iEvent)
507 0 : if ( TVectorD *vec=(TVectorD*)arr->UncheckedAt(iEvent) )
508 0 : arrEvents->AddAt(new TVectorD(*vec),iEvent);
509 0 : }
510 :
511 0 : arr = (TObjArray*)sig.fParamArrayEventPol2.UncheckedAt(iSec);
512 0 : if ( arr ){
513 0 : TObjArray *arrEvents = new TObjArray(arr->GetSize());
514 0 : fParamArrayEventPol2.AddAt(arrEvents, iSec);
515 0 : for (Int_t iEvent=0; iEvent<arr->GetSize(); ++iEvent)
516 0 : if ( TVectorD *vec=(TVectorD*)arr->UncheckedAt(iEvent) )
517 0 : arrEvents->AddAt(new TVectorD(*vec),iEvent);
518 0 : }
519 :
520 0 : TVectorF *vMeanTime = (TVectorF*)sig.fTMeanArrayEvent.UncheckedAt(iSec);
521 0 : TVectorF *vMeanQ = (TVectorF*)sig.fQMeanArrayEvent.UncheckedAt(iSec);
522 0 : if ( vMeanTime )
523 0 : fTMeanArrayEvent.AddAt(new TVectorF(*vMeanTime), iSec);
524 0 : if ( vMeanQ )
525 0 : fQMeanArrayEvent.AddAt(new TVectorF(*vMeanQ), iSec);
526 : }
527 :
528 :
529 0 : fVEventTime.ResizeTo(sig.fVEventTime);
530 0 : fVEventNumber.ResizeTo(sig.fVEventNumber);
531 0 : fVEventTime.SetElements(sig.fVEventTime.GetMatrixArray());
532 0 : fVEventNumber.SetElements(sig.fVEventNumber.GetMatrixArray());
533 :
534 0 : fParam->Update();
535 :
536 0 : for (Int_t i=0; i<sig.fArrHnDrift.GetEntries();++i){
537 0 : TObject *o=sig.fArrHnDrift.UncheckedAt(i);
538 0 : if (o){
539 0 : TObject *newo=o->Clone("fHnDrift");
540 0 : fArrHnDrift.AddAt(newo,i);
541 0 : if (sig.fHnDrift && o==sig.fHnDrift) fHnDrift=(THnSparseI*)newo;
542 0 : }
543 : }
544 :
545 0 : for (Int_t i=0;i<sig.fTimeBursts.GetNrows();++i){
546 0 : fTimeBursts[i]=sig.fTimeBursts[i];
547 : }
548 :
549 0 : for (Int_t i=0;i<14;++i){
550 0 : fPeaks[i]=sig.fPeaks[i];
551 0 : fPeakWidths[i]=sig.fPeakWidths[i];
552 : }
553 0 : if (sig.fArrFitGraphs) {
554 0 : fArrFitGraphs=(TObjArray*)sig.fArrFitGraphs->Clone();
555 0 : fArrFitGraphs->SetOwner();
556 : }
557 :
558 0 : for (Int_t i=0; i<100; ++i) fBinsLastAna[i]=sig.fBinsLastAna[i];
559 :
560 0 : }
561 : //_____________________________________________________________________
562 : AliTPCCalibCE::AliTPCCalibCE(const TMap *config) :
563 0 : AliTPCCalibRawBase(),
564 0 : fNbinsT0(200),
565 0 : fXminT0(-5),
566 0 : fXmaxT0(5),
567 0 : fNbinsQ(200),
568 0 : fXminQ(1),
569 0 : fXmaxQ(40),
570 0 : fNbinsRMS(100),
571 0 : fXminRMS(0.1),
572 0 : fXmaxRMS(5.1),
573 0 : fPeakDetMinus(2),
574 0 : fPeakDetPlus(3),
575 0 : fPeakIntMinus(2),
576 0 : fPeakIntPlus(2),
577 0 : fNoiseThresholdMax(5.),
578 0 : fNoiseThresholdSum(8.),
579 0 : fROCblackDataDown(-1),
580 0 : fROCblackDataUp(-1),
581 0 : fIsZeroSuppressed(kFALSE),
582 0 : fLastSector(-1),
583 0 : fSecRejectRatio(.4),
584 0 : fParam(new AliTPCParam),
585 0 : fPedestalTPC(0x0),
586 0 : fPadNoiseTPC(0x0),
587 0 : fPedestalROC(0x0),
588 0 : fPadNoiseROC(0x0),
589 0 : fCalRocArrayT0(72),
590 0 : fCalRocArrayT0Err(72),
591 0 : fCalRocArrayQ(72),
592 0 : fCalRocArrayRMS(72),
593 0 : fCalRocArrayOutliers(72),
594 0 : fHistoQArray(72),
595 0 : fHistoT0Array(72),
596 0 : fHistoRMSArray(72),
597 0 : fMeanT0rms(0),
598 0 : fMeanQrms(0),
599 0 : fMeanRMSrms(0),
600 0 : fHistoTmean(72),
601 0 : fParamArrayEventPol1(72),
602 0 : fParamArrayEventPol2(72),
603 0 : fTMeanArrayEvent(72),
604 0 : fQMeanArrayEvent(72),
605 0 : fVEventTime(1000),
606 0 : fVEventNumber(1000),
607 0 : fVTime0SideA(1000),
608 0 : fVTime0SideC(1000),
609 0 : fEventId(-1),
610 0 : fOldRunNumber(0),
611 0 : fPadTimesArrayEvent(72),
612 0 : fPadQArrayEvent(72),
613 0 : fPadRMSArrayEvent(72),
614 0 : fPadPedestalArrayEvent(72),
615 0 : fCurrentChannel(-1),
616 0 : fCurrentSector(-1),
617 0 : fCurrentRow(-1),
618 0 : fMaxPadSignal(-1),
619 0 : fMaxTimeBin(-1),
620 : // fPadSignal(1024),
621 0 : fPadPedestal(0),
622 0 : fPadNoise(0),
623 0 : fVTime0Offset(72),
624 0 : fVTime0OffsetCounter(72),
625 0 : fVMeanQ(72),
626 0 : fVMeanQCounter(72),
627 0 : fCurrentCETimeRef(0),
628 0 : fProcessOld(kTRUE),
629 0 : fProcessNew(kFALSE),
630 0 : fAnalyseNew(kTRUE),
631 0 : fHnDrift(0x0),
632 0 : fArrHnDrift(100),
633 0 : fTimeBursts(100),
634 0 : fArrFitGraphs(0x0),
635 0 : fEventInBunch(0)
636 0 : {
637 : /// constructor which uses a tmap as input to set some specific parameters
638 :
639 0 : SetNameTitle("AliTPCCalibCE","AliTPCCalibCE");
640 0 : fFirstTimeBin=650;
641 0 : fLastTimeBin=1030;
642 0 : if (config->GetValue("FirstTimeBin")) fFirstTimeBin = ((TObjString*)config->GetValue("FirstTimeBin"))->GetString().Atoi();
643 0 : if (config->GetValue("LastTimeBin")) fLastTimeBin = ((TObjString*)config->GetValue("LastTimeBin"))->GetString().Atoi();
644 0 : if (config->GetValue("NbinsT0")) fNbinsT0 = ((TObjString*)config->GetValue("NbinsT0"))->GetString().Atoi();
645 0 : if (config->GetValue("XminT0")) fXminT0 = ((TObjString*)config->GetValue("XminT0"))->GetString().Atof();
646 0 : if (config->GetValue("XmaxT0")) fXmaxT0 = ((TObjString*)config->GetValue("XmaxT0"))->GetString().Atof();
647 0 : if (config->GetValue("NbinsQ")) fNbinsQ = ((TObjString*)config->GetValue("NbinsQ"))->GetString().Atoi();
648 0 : if (config->GetValue("XminQ")) fXminQ = ((TObjString*)config->GetValue("XminQ"))->GetString().Atof();
649 0 : if (config->GetValue("XmaxQ")) fXmaxQ = ((TObjString*)config->GetValue("XmaxQ"))->GetString().Atof();
650 0 : if (config->GetValue("NbinsRMS")) fNbinsRMS = ((TObjString*)config->GetValue("NbinsRMS"))->GetString().Atoi();
651 0 : if (config->GetValue("XminRMS")) fXminRMS = ((TObjString*)config->GetValue("XminRMS"))->GetString().Atof();
652 0 : if (config->GetValue("XmaxRMS")) fXmaxRMS = ((TObjString*)config->GetValue("XmaxRMS"))->GetString().Atof();
653 0 : if (config->GetValue("PeakDetMinus")) fPeakDetMinus = ((TObjString*)config->GetValue("PeakDetMinus"))->GetString().Atoi();
654 0 : if (config->GetValue("PeakDetPlus")) fPeakDetPlus = ((TObjString*)config->GetValue("PeakDetPlus"))->GetString().Atoi();
655 0 : if (config->GetValue("PeakIntMinus")) fPeakIntMinus = ((TObjString*)config->GetValue("PeakIntMinus"))->GetString().Atoi();
656 0 : if (config->GetValue("PeakIntPlus")) fPeakIntPlus = ((TObjString*)config->GetValue("PeakIntPlus"))->GetString().Atoi();
657 0 : if (config->GetValue("NoiseThresholdMax")) fNoiseThresholdMax = ((TObjString*)config->GetValue("NoiseThresholdMax"))->GetString().Atof();
658 0 : if (config->GetValue("NoiseThresholdSum")) fNoiseThresholdSum = ((TObjString*)config->GetValue("NoiseThresholdSum"))->GetString().Atof();
659 0 : if (config->GetValue("IsZeroSuppressed")) fIsZeroSuppressed = (Bool_t)((TObjString*)config->GetValue("IsZeroSuppressed"))->GetString().Atoi();
660 0 : if (config->GetValue("UseL1Phase")) fUseL1Phase = (Bool_t)((TObjString*)config->GetValue("UseL1Phase"))->GetString().Atoi();
661 0 : if (config->GetValue("SecRejectRatio")) fSecRejectRatio = ((TObjString*)config->GetValue("SecRejectRatio"))->GetString().Atof();
662 :
663 0 : if (config->GetValue("ProcessOld")) fProcessOld = (Bool_t)((TObjString*)config->GetValue("ProcessOld"))->GetString().Atoi();
664 0 : if (config->GetValue("ProcessNew")) fProcessNew = (Bool_t)((TObjString*)config->GetValue("ProcessNew"))->GetString().Atoi();
665 0 : if (config->GetValue("AnalyseNew")) fAnalyseNew = (Bool_t)((TObjString*)config->GetValue("AnalyseNew"))->GetString().Atoi();
666 :
667 0 : for (Int_t i=0;i<1024;++i) fPadSignal[i]=0;
668 0 : for (Int_t i=0;i<14;++i){
669 0 : fPeaks[i]=0;
670 0 : fPeakWidths[i]=0;
671 : }
672 :
673 0 : fParam->Update();
674 0 : for (Int_t i=0; i<100; ++i) fBinsLastAna[i]=0;
675 0 : }
676 :
677 : //_____________________________________________________________________
678 : AliTPCCalibCE& AliTPCCalibCE::operator = (const AliTPCCalibCE &source)
679 : {
680 : /// assignment operator
681 :
682 0 : if (&source == this) return *this;
683 0 : new (this) AliTPCCalibCE(source);
684 :
685 0 : return *this;
686 0 : }
687 : //_____________________________________________________________________
688 : AliTPCCalibCE::~AliTPCCalibCE()
689 0 : {
690 : /// destructor
691 :
692 0 : fCalRocArrayT0.Delete();
693 0 : fCalRocArrayT0Err.Delete();
694 0 : fCalRocArrayQ.Delete();
695 0 : fCalRocArrayRMS.Delete();
696 0 : fCalRocArrayOutliers.Delete();
697 :
698 0 : fHistoQArray.Delete();
699 0 : fHistoT0Array.Delete();
700 0 : fHistoRMSArray.Delete();
701 :
702 0 : fHistoTmean.Delete();
703 :
704 0 : fParamArrayEventPol1.Delete();
705 0 : fParamArrayEventPol2.Delete();
706 0 : fTMeanArrayEvent.Delete();
707 0 : fQMeanArrayEvent.Delete();
708 :
709 0 : fPadTimesArrayEvent.Delete();
710 0 : fPadQArrayEvent.Delete();
711 0 : fPadRMSArrayEvent.Delete();
712 0 : fPadPedestalArrayEvent.Delete();
713 :
714 0 : fArrHnDrift.SetOwner();
715 0 : fArrHnDrift.Delete();
716 :
717 0 : if (fArrFitGraphs){
718 0 : fArrFitGraphs->SetOwner();
719 0 : delete fArrFitGraphs;
720 : }
721 0 : }
722 : //_____________________________________________________________________
723 : Int_t AliTPCCalibCE::Update(const Int_t icsector,
724 : const Int_t icRow,
725 : const Int_t icPad,
726 : const Int_t icTimeBin,
727 : const Float_t csignal)
728 : {
729 : /// Signal filling methode on the fly pedestal and Time offset correction if necessary.
730 : /// no extra analysis necessary. Assumes knowledge of the signal shape!
731 : /// assumes that it is looped over consecutive time bins of one pad
732 :
733 0 : if (!fProcessOld) return 0;
734 : //temp
735 :
736 0 : if (icRow<0) return 0;
737 0 : if (icPad<0) return 0;
738 0 : if (icTimeBin<0) return 0;
739 0 : if ( (icTimeBin>fLastTimeBin) || (icTimeBin<fFirstTimeBin) ) return 0;
740 :
741 0 : Int_t iChannel = fROC->GetRowIndexes(icsector)[icRow]+icPad; // global pad position in sector
742 :
743 : //init first pad and sector in this event
744 0 : if ( fCurrentChannel == -1 ) {
745 0 : fLastSector=-1;
746 0 : fCurrentChannel = iChannel;
747 0 : fCurrentSector = icsector;
748 0 : fCurrentRow = icRow;
749 0 : }
750 :
751 : //process last pad if we change to a new one
752 0 : if ( iChannel != fCurrentChannel ){
753 0 : ProcessPad();
754 0 : fLastSector=fCurrentSector;
755 0 : fCurrentChannel = iChannel;
756 0 : fCurrentSector = icsector;
757 0 : fCurrentRow = icRow;
758 0 : }
759 :
760 : //fill signals for current pad
761 0 : fPadSignal[icTimeBin]=csignal;
762 0 : if ( csignal > fMaxPadSignal ){
763 0 : fMaxPadSignal = csignal;
764 0 : fMaxTimeBin = icTimeBin;
765 0 : }
766 : return 0;
767 0 : }
768 :
769 : //_____________________________________________________________________
770 : void AliTPCCalibCE::ProcessBunch(const Int_t sector, const Int_t row, const Int_t pad,
771 : const Int_t length, const UInt_t startTimeBin, const UShort_t* signal)
772 : {
773 : /// new filling method to fill the THnSparse histogram
774 :
775 0 : UShort_t timeBin = (UShort_t)startTimeBin;
776 : Int_t padFill = pad;
777 0 : Double_t timeBurst=SetBurstHnDrift();
778 :
779 0 : if (fROCblackDataDown==-1 || fROCblackDataUp==-1){
780 : //only in new processing mode
781 0 : if (!fProcessNew) return;
782 : //don't use the IROCs and inner part of OROCs
783 0 : if (sector<36) return;
784 0 : if (row<40) return;
785 : //only bunches with reasonable length
786 0 : if (length<3||length>10) return;
787 :
788 : //skip first laser layer
789 0 : if (timeBin<280) return;
790 :
791 0 : Int_t cePeak=((sector/18)%2)*7+6;
792 : //after 1 event setup peak ranges
793 0 : if (fEventInBunch==1 && fPeaks[cePeak]==0) {
794 : // set time range
795 0 : fHnDrift->GetAxis(4)->SetRangeUser(timeBurst-2*60,timeBurst+2*60);
796 0 : FindLaserLayers();
797 : // set time range
798 0 : fHnDrift->GetAxis(4)->SetRangeUser(fHnDrift->GetAxis(4)->GetXmin(),fHnDrift->GetAxis(4)->GetXmax());
799 0 : fHnDrift->Reset();
800 0 : }
801 :
802 : // After the first event only fill every 5th bin in a row with the CE information
803 0 : if (fEventInBunch==0||(fPeaks[cePeak]>100&&TMath::Abs((Short_t)fPeaks[cePeak]-(Short_t)timeBin)<(Short_t)fPeakWidths[cePeak])){
804 : Int_t mod=5;
805 0 : Int_t n=pad/mod;
806 0 : padFill=mod*n+mod/2;
807 0 : }
808 :
809 : //noise removal
810 0 : if (!IsPeakInRange(timeBin+length/2,sector)) return;
811 0 : } else if( !(sector>=fROCblackDataDown && sector<fROCblackDataUp) ) return;
812 :
813 :
814 :
815 :
816 0 : Double_t x[kHnBinsDV]={(Double_t)sector,(Double_t)row,
817 0 : (Double_t)padFill,(Double_t)timeBin,timeBurst};
818 :
819 0 : for (Int_t iTimeBin = 0; iTimeBin<length; iTimeBin++){
820 0 : Float_t sig=(Float_t)signal[iTimeBin];
821 : // if (fPeaks[6]>900&&timeBin>(fPeaks[6]-20)&&sig<20) continue;
822 : // if (fPeaks[6]>900&&timeBin<(fPeaks[6]-fPeakWidth[6])&&sig<5) continue;
823 0 : x[3]=timeBin;
824 0 : fHnDrift->Fill(x,sig);
825 0 : --timeBin;
826 : }
827 0 : }
828 : //_____________________________________________________________________
829 : void AliTPCCalibCE::FindLaserLayers()
830 : {
831 : /// Find the laser layer positoins
832 :
833 : //A-side + C-side
834 0 : for (Int_t iside=0;iside<2;++iside){
835 0 : Int_t add=7*iside;
836 : //find CE signal position and width
837 0 : fHnDrift->GetAxis(0)->SetRangeUser(36+iside*18,53+iside*18);
838 0 : TH1D *hproj=fHnDrift->Projection(3);
839 0 : hproj->GetXaxis()->SetRangeUser(700,1030);
840 0 : Int_t maxbin=hproj->GetMaximumBin();
841 0 : Double_t binc=hproj->GetBinCenter(maxbin);
842 0 : hproj->GetXaxis()->SetRangeUser(binc-5,binc+5);
843 :
844 0 : fPeaks[add+6]=(UShort_t)TMath::Nint(binc);
845 : // fPeakWidths[4]=(UShort_t)TMath::Nint(4*hproj->GetRMS()+.5);
846 0 : fPeakWidths[add+6]=7;
847 :
848 0 : hproj->GetXaxis()->SetRangeUser(0,maxbin-10);
849 0 : TSpectrum s(6);
850 0 : s.Search(hproj,2,"goff");
851 0 : Int_t index[6];
852 0 : TMath::Sort(6,s.GetPositionX(),index,kFALSE);
853 0 : for (Int_t i=0; i<6; ++i){
854 0 : fPeaks[i+add]=(UShort_t)TMath::Nint(s.GetPositionX()[index[i]]);
855 0 : fPeakWidths[i+add]=5;
856 : }
857 :
858 : //other peaks
859 :
860 : // Int_t timepos=fPeaks[4]-2*fPeakWidths[4];
861 : // Int_t width=100;
862 :
863 : // for (Int_t i=3; i>=0; --i){
864 : // hproj->GetXaxis()->SetRangeUser(timepos-width,timepos);
865 : // fPeaks[i]=hproj->GetMaximumBin();
866 : // fPeakWidths[i]=(UShort_t)TMath::Nint(10.);
867 : // width=250;
868 : // timepos=fPeaks[i]-width/2;
869 : // }
870 :
871 : // for (Int_t i=add; i<add+7; ++i){
872 : // printf("Peak: %u +- %u\n",fPeaks[i],fPeakWidths[i]);
873 : // }
874 : //check width and reset peak if >100
875 : // for (Int_t i=0; i<5; ++i){
876 : // if (fPeakWidths[i]>100) {
877 : // fPeaks[i]=0;
878 : // fPeakWidths[i]=0;
879 : // }
880 : // }
881 :
882 0 : delete hproj;
883 0 : }
884 0 : }
885 :
886 : //_____________________________________________________________________
887 : void AliTPCCalibCE::FindPedestal(Float_t part)
888 : {
889 : /// find pedestal and noise for the current pad. Use either database or
890 : /// truncated mean with part*100%
891 :
892 : Bool_t noPedestal = kTRUE;
893 :
894 : //use pedestal database if set
895 0 : if (fPedestalTPC&&fPadNoiseTPC){
896 : //only load new pedestals if the sector has changed
897 0 : if ( fCurrentSector!=fLastSector ){
898 0 : fPedestalROC = fPedestalTPC->GetCalROC(fCurrentSector);
899 0 : fPadNoiseROC = fPadNoiseTPC->GetCalROC(fCurrentSector);
900 0 : }
901 :
902 0 : if ( fPedestalROC&&fPadNoiseROC ){
903 0 : fPadPedestal = fPedestalROC->GetValue(fCurrentChannel)*(Float_t)(!fIsZeroSuppressed);
904 0 : fPadNoise = fPadNoiseROC->GetValue(fCurrentChannel);
905 : noPedestal = kFALSE;
906 0 : }
907 :
908 : }
909 :
910 : //if we are not running with pedestal database, or for the current sector there is no information
911 : //available, calculate the pedestal and noise on the fly
912 0 : if ( noPedestal ) {
913 0 : fPadPedestal = 0;
914 0 : fPadNoise = 0;
915 0 : if ( fIsZeroSuppressed ) return;
916 : const Int_t kPedMax = 100; //maximum pedestal value
917 : Float_t max = 0;
918 : Float_t maxPos = 0;
919 : Int_t median = -1;
920 : Int_t count0 = 0;
921 : Int_t count1 = 0;
922 : //
923 : Float_t padSignal=0;
924 : //
925 0 : UShort_t histo[kPedMax];
926 0 : memset(histo,0,kPedMax*sizeof(UShort_t));
927 :
928 : //fill pedestal histogram
929 0 : for (Int_t i=fFirstTimeBin; i<=fLastTimeBin; ++i){
930 0 : padSignal = fPadSignal[i];
931 0 : if (padSignal<=0) continue;
932 0 : if (padSignal>max && i>10) {
933 : max = padSignal;
934 : maxPos = i;
935 0 : }
936 0 : if (padSignal>kPedMax-1) continue;
937 0 : histo[int(padSignal+0.5)]++;
938 0 : count0++;
939 0 : }
940 : //find median
941 0 : for (Int_t i=1; i<kPedMax; ++i){
942 0 : if (count1<count0*0.5) median=i;
943 0 : count1+=histo[i];
944 : }
945 : // truncated mean
946 : //
947 0 : Float_t count=histo[median] ,mean=histo[median]*median, rms=histo[median]*median*median ;
948 : //
949 0 : for (Int_t idelta=1; idelta<10; ++idelta){
950 0 : if (median-idelta<=0) continue;
951 0 : if (median+idelta>kPedMax) continue;
952 0 : if (count<part*count1){
953 0 : count+=histo[median-idelta];
954 0 : mean +=histo[median-idelta]*(median-idelta);
955 0 : rms +=histo[median-idelta]*(median-idelta)*(median-idelta);
956 0 : count+=histo[median+idelta];
957 0 : mean +=histo[median+idelta]*(median+idelta);
958 0 : rms +=histo[median+idelta]*(median+idelta)*(median+idelta);
959 0 : }
960 : }
961 0 : if ( count > 0 ) {
962 0 : mean/=count;
963 0 : rms = TMath::Sqrt(TMath::Abs(rms/count-mean*mean));
964 0 : fPadPedestal = mean;
965 0 : fPadNoise = rms;
966 0 : }
967 0 : }
968 0 : }
969 : //_____________________________________________________________________
970 : void AliTPCCalibCE::UpdateCETimeRef()
971 : {
972 : /// Find the time reference of the last valid CE signal in sector
973 : /// for irocs of the A-Side the reference of the corresponging OROC is returned
974 : /// the reason are the non reflective bands on the A-Side, which make the reference very uncertain
975 :
976 0 : if ( fLastSector == fCurrentSector ) return;
977 : Int_t sector=fCurrentSector;
978 0 : if ( sector < 18 ) sector+=36;
979 0 : fCurrentCETimeRef=0;
980 0 : TVectorF *vtRef = GetTMeanEvents(sector);
981 0 : if ( !vtRef ) return;
982 0 : Int_t vtRefSize= vtRef->GetNrows();
983 0 : if ( vtRefSize < fNevents+1 ) vtRef->ResizeTo(vtRefSize+100);
984 : else vtRefSize=fNevents;
985 0 : while ( (*vtRef)[vtRefSize]==0 && vtRefSize>=0 ) --vtRefSize;
986 0 : fCurrentCETimeRef=(*vtRef)[vtRefSize];
987 0 : AliDebug(3,Form("Sector: %02d - T0 ref: %.2f",fCurrentSector,fCurrentCETimeRef));
988 0 : }
989 : //_____________________________________________________________________
990 : void AliTPCCalibCE::FindCESignal(TVectorD ¶m, Float_t &qSum, const TVectorF maxima)
991 : {
992 : /// Find position, signal width and height of the CE signal (last signal)
993 : /// param[0] = Qmax, param[1] = mean time, param[2] = rms;
994 : /// maxima: array of local maxima of the pad signal use the one closest to the mean CE position
995 :
996 : Float_t ceQmax =0, ceQsum=0, ceTime=0, ceRMS=0;
997 : Int_t cemaxpos = 0;
998 0 : Float_t ceSumThreshold = fNoiseThresholdSum*fPadNoise; // threshold for the signal sum
999 0 : const Int_t kCemin = fPeakIntMinus; // range for the analysis of the ce signal +- channels from the peak
1000 0 : const Int_t kCemax = fPeakIntPlus;
1001 :
1002 : Float_t minDist = 25; //initial minimum distance betweek roc mean ce signal and pad ce signal
1003 :
1004 : // find maximum closest to the sector mean from the last event
1005 0 : for ( Int_t imax=0; imax<maxima.GetNrows(); ++imax){
1006 : // get sector mean of last event
1007 0 : Float_t tmean = fCurrentCETimeRef;
1008 0 : if ( TMath::Abs( tmean-maxima[imax] ) < minDist ) {
1009 0 : minDist = tmean-maxima[imax];
1010 0 : cemaxpos = (Int_t)maxima[imax];
1011 0 : }
1012 : }
1013 : // printf("L1 phase TB: %f\n",GetL1PhaseTB());
1014 0 : if (cemaxpos!=0){
1015 0 : ceQmax = fPadSignal[cemaxpos]-fPadPedestal;
1016 0 : for (Int_t i=cemaxpos-kCemin; i<=cemaxpos+kCemax; ++i){
1017 0 : if ( (i>fFirstTimeBin) && (i<fLastTimeBin) ){
1018 0 : Float_t signal = fPadSignal[i]-fPadPedestal;
1019 0 : if (signal>0) {
1020 0 : ceTime+=signal*(i+0.5);
1021 0 : ceRMS +=signal*(i+0.5)*(i+0.5);
1022 0 : ceQsum+=signal;
1023 0 : }
1024 0 : }
1025 : }
1026 0 : }
1027 0 : if (ceQmax&&ceQsum>ceSumThreshold) {
1028 0 : ceTime/=ceQsum;
1029 0 : ceRMS = TMath::Sqrt(TMath::Abs(ceRMS/ceQsum-ceTime*ceTime));
1030 0 : ceTime-=GetL1PhaseTB();
1031 0 : fVTime0Offset.GetMatrixArray()[fCurrentSector]+=ceTime; // mean time for each sector
1032 0 : fVTime0OffsetCounter.GetMatrixArray()[fCurrentSector]++;
1033 :
1034 : //Normalise Q to the 'cell-size': The wire density is the same in the IROC and OROC, therefore the
1035 : // the pick-up signal should scale with the pad area. In addition
1036 : // the signal should decrease with the wire distance (4mm in IROC, 6mm in OROC),
1037 : // ratio 2/3. The pad area we express in cm2. We normalise the signal
1038 : // to the OROC signal (factor 2/3 for the IROCs).
1039 0 : Float_t norm = fParam->GetPadPitchWidth(fCurrentSector)*fParam->GetPadPitchLength(fCurrentSector,fCurrentRow);
1040 0 : if ( fCurrentSector<fParam->GetNInnerSector() ) norm*=3./2.;
1041 :
1042 0 : ceQsum/=norm;
1043 0 : fVMeanQ.GetMatrixArray()[fCurrentSector]+=ceQsum;
1044 0 : fVMeanQCounter.GetMatrixArray()[fCurrentSector]++;
1045 0 : } else {
1046 : ceQmax=0;
1047 : ceTime=0;
1048 : ceRMS =0;
1049 : ceQsum=0;
1050 : }
1051 0 : param[0] = ceQmax;
1052 0 : param[1] = ceTime;
1053 0 : param[2] = ceRMS;
1054 0 : qSum = ceQsum;
1055 0 : }
1056 : //_____________________________________________________________________
1057 : Bool_t AliTPCCalibCE::IsPeak(Int_t pos, Int_t tminus, Int_t tplus) const
1058 : {
1059 : /// Check if 'pos' is a Maximum. Consider 'tminus' timebins before
1060 : /// and 'tplus' timebins after 'pos'
1061 :
1062 0 : if ( (pos-tminus)<fFirstTimeBin || (pos+tplus)>fLastTimeBin ) return kFALSE;
1063 0 : for (Int_t iTime = pos; iTime>pos-tminus; --iTime)
1064 0 : if ( fPadSignal[iTime-1] >= fPadSignal[iTime] ) return kFALSE;
1065 0 : for (Int_t iTime = pos, iTime2=pos; iTime<pos+tplus; ++iTime, ++iTime2){
1066 0 : if ( (iTime==pos) && (fPadSignal[iTime+1]==fPadSignal[iTime]) ) // allow two timebins with same adc value
1067 0 : ++iTime2;
1068 0 : if ( fPadSignal[iTime2+1] >= fPadSignal[iTime2] ) return kFALSE;
1069 : }
1070 0 : return kTRUE;
1071 0 : }
1072 : //_____________________________________________________________________
1073 : void AliTPCCalibCE::FindLocalMaxima(TVectorF &maxima)
1074 : {
1075 : /// Find local maxima on the pad signal and Histogram them
1076 :
1077 0 : Float_t ceThreshold = fNoiseThresholdMax*TMath::Max(fPadNoise,Float_t(1.)); // threshold for the signal
1078 : Int_t count = 0;
1079 :
1080 0 : for (Int_t i=fLastTimeBin-fPeakDetPlus+1; i>=fFirstTimeBin+fPeakDetMinus; --i){
1081 0 : if ( (fPadSignal[i]-fPadPedestal)<ceThreshold ) continue;
1082 0 : if (IsPeak(i,fPeakDetMinus,fPeakDetPlus) ){
1083 0 : if (count<maxima.GetNrows()){
1084 0 : maxima.GetMatrixArray()[count++]=i;
1085 0 : GetHistoTmean(fCurrentSector,kTRUE)->Fill(i);
1086 0 : i-=(fPeakDetMinus+fPeakDetPlus-1); // next peak cannot be at bin fPeakDetMinus+fPeakDetPlus-1
1087 0 : }
1088 : }
1089 : }
1090 0 : }
1091 : //_____________________________________________________________________
1092 : void AliTPCCalibCE::ProcessPad()
1093 : {
1094 : /// Process data of current pad
1095 :
1096 0 : FindPedestal();
1097 :
1098 0 : TVectorF maxima(15); // the expected maximum number of maxima in the complete TPC should be 8 laser beam layers
1099 : // + central electrode and possibly post peaks from the CE signal
1100 : // however if we are on a high noise pad a lot more peaks due to the noise might occur
1101 0 : FindLocalMaxima(maxima);
1102 0 : if ( (fNevents == 0) || (fOldRunNumber!=fRunNumber) ) return; // return because we don't have Time0 info for the CE yet
1103 :
1104 0 : UpdateCETimeRef(); // update the time refenrence for the current sector
1105 0 : if ( fCurrentCETimeRef<1e-30 ) return; //return if we don't have time 0 info, eg if only one side has laser
1106 0 : TVectorD param(3);
1107 0 : Float_t qSum;
1108 0 : FindCESignal(param, qSum, maxima);
1109 :
1110 0 : Double_t meanT = param[1];
1111 0 : Double_t sigmaT = param[2];
1112 :
1113 : //Fill Event T0 counter
1114 0 : (*GetPadTimesEvent(fCurrentSector,kTRUE)).GetMatrixArray()[fCurrentChannel] = meanT;
1115 :
1116 : //Fill Q histogram
1117 0 : GetHistoQ(fCurrentSector,kTRUE)->Fill( TMath::Sqrt(qSum), fCurrentChannel );
1118 :
1119 : //Fill RMS histogram
1120 0 : GetHistoRMS(fCurrentSector,kTRUE)->Fill( sigmaT, fCurrentChannel );
1121 :
1122 :
1123 : //Fill debugging info
1124 0 : if ( GetStreamLevel()>0 ){
1125 0 : (*GetPadPedestalEvent(fCurrentSector,kTRUE)).GetMatrixArray()[fCurrentChannel]=fPadPedestal;
1126 0 : (*GetPadRMSEvent(fCurrentSector,kTRUE)).GetMatrixArray()[fCurrentChannel]=sigmaT;
1127 0 : (*GetPadQEvent(fCurrentSector,kTRUE)).GetMatrixArray()[fCurrentChannel]=qSum;
1128 0 : }
1129 :
1130 0 : ResetPad();
1131 0 : }
1132 : //_____________________________________________________________________
1133 : void AliTPCCalibCE::EndEvent()
1134 : {
1135 : /// Process data of current pad
1136 : /// The Functions 'SetTimeStamp' and 'SetRunNumber' should be called
1137 : /// before the EndEvent function to set the event timestamp and number!!!
1138 : /// This is automatically done if the ProcessEvent(AliRawReader *rawReader)
1139 : /// function was called
1140 :
1141 0 : if (!fProcessOld) {
1142 0 : if (fProcessNew){
1143 0 : ++fNevents;
1144 0 : ++fEventInBunch;
1145 0 : }
1146 : return;
1147 : }
1148 :
1149 : //check if last pad has allready been processed, if not do so
1150 0 : if ( fMaxTimeBin>-1 ) ProcessPad();
1151 :
1152 0 : AliDebug(3, Form("EndEvent() - Start; Event: %05d", fNevents));
1153 :
1154 0 : TVectorD param(3);
1155 0 : TMatrixD dummy(3,3);
1156 : // TVectorF vMeanTime(72);
1157 : // TVectorF vMeanQ(72);
1158 0 : AliTPCCalROC *calIroc=new AliTPCCalROC(0);
1159 0 : AliTPCCalROC *calOroc=new AliTPCCalROC(36);
1160 :
1161 : //find mean time0 offset for side A and C
1162 : //use only orocs due to the better statistics
1163 0 : Double_t time0Side[2]; //time0 for side A:0 and C:1
1164 0 : Double_t time0SideCount[2]; //time0 counter for side A:0 and C:1
1165 0 : time0Side[0]=0;time0Side[1]=0;time0SideCount[0]=0;time0SideCount[1]=0;
1166 0 : for ( Int_t iSec = 36; iSec<72; ++iSec ){
1167 0 : time0Side[(iSec/18)%2] += fVTime0Offset.GetMatrixArray()[iSec];
1168 0 : time0SideCount[(iSec/18)%2] += fVTime0OffsetCounter.GetMatrixArray()[iSec];
1169 : }
1170 0 : if ( time0SideCount[0] >0 )
1171 0 : time0Side[0]/=time0SideCount[0];
1172 0 : if ( time0SideCount[1] >0 )
1173 0 : time0Side[1]/=time0SideCount[1];
1174 : // end find time0 offset
1175 0 : AliDebug(3,Form("time0Side/time0SideCount: A=%.2f/%.2f, C=%.2f/%.2f",time0Side[0],time0SideCount[0],time0Side[1],time0SideCount[1]));
1176 : Int_t nSecMeanT=0;
1177 : //loop over all ROCs, fill CE Time histogram corrected for the mean Time0 of each ROC
1178 0 : for ( Int_t iSec = 0; iSec<72; ++iSec ){
1179 0 : AliDebug(4,Form("Processing sector '%02d'\n",iSec));
1180 : //find median and then calculate the mean around it
1181 0 : TH1S *hMeanT = GetHistoTmean(iSec); //histogram with local maxima position information
1182 0 : if ( !hMeanT ) continue;
1183 : //continue if not enough data is filled in the meanT histogram. This is the case if we do not have a laser event.
1184 0 : if ( hMeanT->GetEffectiveEntries() < fROC->GetNChannels(iSec)*fSecRejectRatio ){
1185 0 : hMeanT->Reset();
1186 0 : AliDebug(3,Form("Skipping sec. '%02d': Not enough statistics\n",iSec));
1187 0 : continue;
1188 : }
1189 :
1190 0 : Double_t entries = hMeanT->GetEffectiveEntries();
1191 : Double_t sum = 0;
1192 0 : Short_t *arr = hMeanT->GetArray()+1;
1193 : Int_t ibin=0;
1194 0 : for ( ibin=0; ibin<hMeanT->GetNbinsX(); ++ibin){
1195 0 : sum+=arr[ibin];
1196 0 : if ( sum>=(entries/2.) ) break;
1197 : }
1198 : Int_t delta = 4;
1199 0 : Int_t firstBin = fFirstTimeBin+ibin-delta;
1200 0 : Int_t lastBin = fFirstTimeBin+ibin+delta;
1201 0 : if ( firstBin<fFirstTimeBin ) firstBin=fFirstTimeBin;
1202 0 : if ( lastBin>fLastTimeBin ) lastBin =fLastTimeBin;
1203 0 : Float_t median =AliMathBase::GetCOG(arr+ibin-delta,2*delta,firstBin,lastBin);
1204 :
1205 : // check boundaries for ebye info of mean time
1206 0 : TVectorF *vMeanTime=GetTMeanEvents(iSec,kTRUE);
1207 0 : Int_t vSize=vMeanTime->GetNrows();
1208 0 : if ( vSize < fNevents+1 ){
1209 0 : vMeanTime->ResizeTo(vSize+100);
1210 : }
1211 :
1212 : // store mean time for the readout sides
1213 0 : vSize=fVTime0SideA.GetNrows();
1214 0 : if ( vSize < fNevents+1 ){
1215 0 : fVTime0SideA.ResizeTo(vSize+100);
1216 0 : fVTime0SideC.ResizeTo(vSize+100);
1217 : }
1218 0 : fVTime0SideA.GetMatrixArray()[fNevents]=time0Side[0];
1219 0 : fVTime0SideC.GetMatrixArray()[fNevents]=time0Side[1];
1220 :
1221 0 : vMeanTime->GetMatrixArray()[fNevents]=median;
1222 0 : nSecMeanT++;
1223 : // end find median
1224 :
1225 0 : TVectorF *vTimes = GetPadTimesEvent(iSec);
1226 0 : if ( !vTimes ) continue; //continue if no time information for this sector is available
1227 :
1228 0 : AliTPCCalROC calIrocOutliers(0);
1229 0 : AliTPCCalROC calOrocOutliers(36);
1230 :
1231 : // calculate mean Q of the sector
1232 0 : TVectorF *vMeanQ=GetQMeanEvents(iSec,kTRUE);
1233 0 : vSize=vMeanQ->GetNrows();
1234 0 : if ( vSize < fNevents+1 ){
1235 0 : vMeanQ->ResizeTo(vSize+100);
1236 : }
1237 0 : Float_t meanQ = 0;
1238 0 : if ( fVMeanQCounter.GetMatrixArray()[iSec]>0 ) meanQ=fVMeanQ.GetMatrixArray()[iSec]/fVMeanQCounter.GetMatrixArray()[iSec];
1239 0 : vMeanQ->GetMatrixArray()[fNevents]=meanQ;
1240 :
1241 0 : for ( UInt_t iChannel=0; iChannel<fROC->GetNChannels(iSec); ++iChannel ){
1242 0 : Float_t time = (*vTimes).GetMatrixArray()[iChannel];
1243 :
1244 : //set values for temporary roc calibration class
1245 0 : if ( iSec < 36 ) {
1246 0 : calIroc->SetValue(iChannel, time);
1247 0 : if ( TMath::Abs(time) < 1e-30 ) calIrocOutliers.SetValue(iChannel,1);
1248 :
1249 : } else {
1250 0 : calOroc->SetValue(iChannel, time);
1251 0 : if ( TMath::Abs(time) < 1e-30 ) calOrocOutliers.SetValue(iChannel,1);
1252 : }
1253 :
1254 0 : if ( (fNevents>0) && (fOldRunNumber==fRunNumber) )
1255 : // test that we really found the CE signal reliably
1256 0 : if ( TMath::Abs(fVTime0SideA.GetMatrixArray()[fNevents-1]-time0Side[0])<.05)
1257 0 : GetHistoT0(iSec,kTRUE)->Fill( time-time0Side[(iSec/18)%2],iChannel );
1258 :
1259 :
1260 :
1261 : //------------------------------- Debug start ------------------------------
1262 0 : if ( GetStreamLevel()>0 ){
1263 0 : TTreeSRedirector *streamer=GetDebugStreamer();
1264 0 : if (streamer){
1265 0 : Int_t row=0;
1266 0 : Int_t pad=0;
1267 0 : Int_t padc=0;
1268 :
1269 0 : Float_t q = (*GetPadQEvent(iSec))[iChannel];
1270 0 : Float_t rms = (*GetPadRMSEvent(iSec))[iChannel];
1271 :
1272 0 : UInt_t channel=iChannel;
1273 0 : Int_t sector=iSec;
1274 :
1275 0 : while ( channel > (fROC->GetRowIndexes(sector)[row]+fROC->GetNPads(sector,row)-1) ) row++;
1276 0 : pad = channel-fROC->GetRowIndexes(sector)[row];
1277 0 : padc = pad-(fROC->GetNPads(sector,row)/2);
1278 :
1279 : // TH1F *h1 = new TH1F(Form("hSignalD%d.%d.%d",sector,row,pad),
1280 : // Form("hSignalD%d.%d.%d",sector,row,pad),
1281 : // fLastTimeBin-fFirstTimeBin,
1282 : // fFirstTimeBin,fLastTimeBin);
1283 : // h1->SetDirectory(0);
1284 : //
1285 : // for (Int_t i=fFirstTimeBin; i<fLastTimeBin+1; ++i)
1286 : // h1->Fill(i,fPadSignal(i));
1287 :
1288 0 : Double_t t0Sec = 0;
1289 0 : if (fVTime0OffsetCounter.GetMatrixArray()[iSec]>0)
1290 0 : t0Sec = fVTime0Offset.GetMatrixArray()[iSec]/fVTime0OffsetCounter.GetMatrixArray()[iSec];
1291 0 : Double_t t0Side = time0Side[(iSec/18)%2];
1292 0 : (*streamer) << "DataPad" <<
1293 0 : "Event=" << fNevents <<
1294 0 : "RunNumber=" << fRunNumber <<
1295 0 : "TimeStamp=" << fTimeStamp <<
1296 0 : "Sector="<< sector <<
1297 0 : "Row=" << row<<
1298 0 : "Pad=" << pad <<
1299 0 : "PadC=" << padc <<
1300 0 : "PadSec="<< channel <<
1301 0 : "Time0Sec=" << t0Sec <<
1302 0 : "Time0Side=" << t0Side <<
1303 0 : "Time=" << time <<
1304 0 : "RMS=" << rms <<
1305 0 : "Sum=" << q <<
1306 0 : "MeanQ=" << meanQ <<
1307 : // "hist.=" << h1 <<
1308 : "\n";
1309 :
1310 : // delete h1;
1311 0 : }
1312 0 : }
1313 : //----------------------------- Debug end ------------------------------
1314 0 : }// end channel loop
1315 :
1316 :
1317 : //do fitting now only in debug mode
1318 0 : if (GetDebugLevel()>0){
1319 0 : TVectorD paramPol1(3);
1320 0 : TVectorD paramPol2(6);
1321 0 : TMatrixD matPol1(3,3);
1322 0 : TMatrixD matPol2(6,6);
1323 0 : Float_t chi2Pol1=0;
1324 0 : Float_t chi2Pol2=0;
1325 :
1326 0 : if ( (fNevents>0) && (fOldRunNumber==fRunNumber) ){
1327 0 : if ( iSec < 36 ){
1328 0 : calIroc->GlobalFit(&calIrocOutliers,0,paramPol1,matPol1,chi2Pol1,0);
1329 0 : calIroc->GlobalFit(&calIrocOutliers,0,paramPol2,matPol2,chi2Pol2,1);
1330 : } else {
1331 0 : calOroc->GlobalFit(&calOrocOutliers,0,paramPol1,matPol1,chi2Pol1,0);
1332 0 : calOroc->GlobalFit(&calOrocOutliers,0,paramPol2,matPol2,chi2Pol2,1);
1333 : }
1334 :
1335 0 : GetParamArrayPol1(iSec,kTRUE)->AddAtAndExpand(new TVectorD(paramPol1), fNevents);
1336 0 : GetParamArrayPol2(iSec,kTRUE)->AddAtAndExpand(new TVectorD(paramPol2), fNevents);
1337 : }
1338 :
1339 : //------------------------------- Debug start ------------------------------
1340 0 : if ( GetStreamLevel()>0 ){
1341 0 : TTreeSRedirector *streamer=GetDebugStreamer();
1342 0 : if ( streamer ) {
1343 0 : (*streamer) << "DataRoc" <<
1344 : // "Event=" << fEvent <<
1345 0 : "RunNumber=" << fRunNumber <<
1346 0 : "TimeStamp=" << fTimeStamp <<
1347 0 : "Sector="<< iSec <<
1348 0 : "hMeanT.=" << hMeanT <<
1349 0 : "median=" << median <<
1350 0 : "paramPol1.=" << ¶mPol1 <<
1351 0 : "paramPol2.=" << ¶mPol2 <<
1352 0 : "matPol1.=" << &matPol1 <<
1353 0 : "matPol2.=" << &matPol2 <<
1354 0 : "chi2Pol1=" << chi2Pol1 <<
1355 0 : "chi2Pol2=" << chi2Pol2 <<
1356 : "\n";
1357 : }
1358 0 : }
1359 0 : }
1360 : //------------------------------- Debug end ------------------------------
1361 0 : hMeanT->Reset();
1362 0 : }// end sector loop
1363 : //return if no sector has a valid mean time
1364 0 : if ( nSecMeanT == 0 ) return;
1365 :
1366 :
1367 : // fTMeanArrayEvent.AddAtAndExpand(new TVectorF(vMeanTime),fNevents);
1368 : // fQMeanArrayEvent.AddAtAndExpand(new TVectorF(vMeanQ),fNevents);
1369 0 : if ( fVEventTime.GetNrows() < fNevents+1 ) {
1370 0 : fVEventTime.ResizeTo((Int_t)(fVEventTime.GetNrows()+100));
1371 0 : fVEventNumber.ResizeTo((Int_t)(fVEventNumber.GetNrows()+100));
1372 : }
1373 0 : fVEventTime.GetMatrixArray()[fNevents] = fTimeStamp;
1374 0 : fVEventNumber.GetMatrixArray()[fNevents] = fEventId;
1375 :
1376 0 : ++fNevents;
1377 0 : if (fProcessNew) ++fEventInBunch;
1378 0 : fOldRunNumber = fRunNumber;
1379 :
1380 0 : delete calIroc;
1381 0 : delete calOroc;
1382 0 : AliDebug(3, Form("EndEvent() - End; Event: %05d", fNevents));
1383 0 : }
1384 : //_____________________________________________________________________
1385 : TH2S* AliTPCCalibCE::GetHisto(Int_t sector, TObjArray *arr,
1386 : Int_t nbinsY, Float_t ymin, Float_t ymax,
1387 : const Char_t *type, Bool_t force)
1388 : {
1389 : /// return pointer to TH2S histogram of 'type'
1390 : /// if force is true create a new histogram if it doesn't exist allready
1391 :
1392 0 : if ( !force || arr->UncheckedAt(sector) )
1393 0 : return (TH2S*)arr->UncheckedAt(sector);
1394 :
1395 : // if we are forced and histogram doesn't exist yet create it
1396 : // new histogram with Q calib information. One value for each pad!
1397 0 : TH2S* hist = new TH2S(Form("hCalib%s%.2d",type,sector),Form("%s calibration histogram sector %.2d",type,sector),
1398 0 : nbinsY, ymin, ymax,
1399 0 : fROC->GetNChannels(sector),0,fROC->GetNChannels(sector));
1400 0 : hist->SetDirectory(0);
1401 0 : arr->AddAt(hist,sector);
1402 : return hist;
1403 0 : }
1404 : //_____________________________________________________________________
1405 : TH2S* AliTPCCalibCE::GetHistoT0(Int_t sector, Bool_t force)
1406 : {
1407 : /// return pointer to T0 histogram
1408 : /// if force is true create a new histogram if it doesn't exist allready
1409 :
1410 0 : TObjArray *arr = &fHistoT0Array;
1411 0 : return GetHisto(sector, arr, fNbinsT0, fXminT0, fXmaxT0, "T0", force);
1412 : }
1413 : //_____________________________________________________________________
1414 : TH2S* AliTPCCalibCE::GetHistoQ(Int_t sector, Bool_t force)
1415 : {
1416 : /// return pointer to Q histogram
1417 : /// if force is true create a new histogram if it doesn't exist allready
1418 :
1419 0 : TObjArray *arr = &fHistoQArray;
1420 0 : return GetHisto(sector, arr, fNbinsQ, fXminQ, fXmaxQ, "Q", force);
1421 : }
1422 : //_____________________________________________________________________
1423 : TH2S* AliTPCCalibCE::GetHistoRMS(Int_t sector, Bool_t force)
1424 : {
1425 : /// return pointer to Q histogram
1426 : /// if force is true create a new histogram if it doesn't exist allready
1427 :
1428 0 : TObjArray *arr = &fHistoRMSArray;
1429 0 : return GetHisto(sector, arr, fNbinsRMS, fXminRMS, fXmaxRMS, "RMS", force);
1430 : }
1431 : //_____________________________________________________________________
1432 : TH1S* AliTPCCalibCE::GetHisto(Int_t sector, TObjArray *arr,
1433 : const Char_t *type, Bool_t force)
1434 : {
1435 : /// return pointer to TH1S histogram
1436 : /// if force is true create a new histogram if it doesn't exist allready
1437 :
1438 0 : if ( !force || arr->UncheckedAt(sector) )
1439 0 : return (TH1S*)arr->UncheckedAt(sector);
1440 :
1441 : // if we are forced and histogram doesn't yes exist create it
1442 : // new histogram with calib information. One value for each pad!
1443 0 : TH1S* hist = new TH1S(Form("hCalib%s%.2d",type,sector),Form("%s calibration histogram sector %.2d",type,sector),
1444 0 : fLastTimeBin-fFirstTimeBin,fFirstTimeBin,fLastTimeBin);
1445 0 : hist->SetDirectory(0);
1446 0 : arr->AddAt(hist,sector);
1447 : return hist;
1448 0 : }
1449 : //_____________________________________________________________________
1450 : TH1S* AliTPCCalibCE::GetHistoTmean(Int_t sector, Bool_t force)
1451 : {
1452 : /// return pointer to Q histogram
1453 : /// if force is true create a new histogram if it doesn't exist allready
1454 :
1455 0 : TObjArray *arr = &fHistoTmean;
1456 0 : return GetHisto(sector, arr, "LastTmean", force);
1457 : }
1458 : //_____________________________________________________________________
1459 : TVectorF* AliTPCCalibCE::GetVectSector(Int_t sector, TObjArray *arr, UInt_t size, Bool_t force) const
1460 : {
1461 : /// return pointer to Pad Info from 'arr' for the current event and sector
1462 : /// if force is true create it if it doesn't exist allready
1463 :
1464 0 : if ( !force || arr->UncheckedAt(sector) )
1465 0 : return (TVectorF*)arr->UncheckedAt(sector);
1466 :
1467 0 : TVectorF *vect = new TVectorF(size);
1468 0 : arr->AddAt(vect,sector);
1469 : return vect;
1470 0 : }
1471 : //_____________________________________________________________________
1472 : TVectorF* AliTPCCalibCE::GetPadTimesEvent(Int_t sector, Bool_t force)
1473 : {
1474 : /// return pointer to Pad Times Array for the current event and sector
1475 : /// if force is true create it if it doesn't exist allready
1476 :
1477 0 : TObjArray *arr = &fPadTimesArrayEvent;
1478 0 : return GetVectSector(sector,arr,fROC->GetNChannels(sector),force);
1479 : }
1480 : //_____________________________________________________________________
1481 : TVectorF* AliTPCCalibCE::GetPadQEvent(Int_t sector, Bool_t force)
1482 : {
1483 : /// return pointer to Pad Q Array for the current event and sector
1484 : /// if force is true create it if it doesn't exist allready
1485 : /// for debugging purposes only
1486 :
1487 0 : TObjArray *arr = &fPadQArrayEvent;
1488 0 : return GetVectSector(sector,arr,fROC->GetNChannels(sector),force);
1489 : }
1490 : //_____________________________________________________________________
1491 : TVectorF* AliTPCCalibCE::GetPadRMSEvent(Int_t sector, Bool_t force)
1492 : {
1493 : /// return pointer to Pad RMS Array for the current event and sector
1494 : /// if force is true create it if it doesn't exist allready
1495 : /// for debugging purposes only
1496 :
1497 0 : TObjArray *arr = &fPadRMSArrayEvent;
1498 0 : return GetVectSector(sector,arr,fROC->GetNChannels(sector),force);
1499 : }
1500 : //_____________________________________________________________________
1501 : TVectorF* AliTPCCalibCE::GetPadPedestalEvent(Int_t sector, Bool_t force)
1502 : {
1503 : /// return pointer to Pad RMS Array for the current event and sector
1504 : /// if force is true create it if it doesn't exist allready
1505 : /// for debugging purposes only
1506 :
1507 0 : TObjArray *arr = &fPadPedestalArrayEvent;
1508 0 : return GetVectSector(sector,arr,fROC->GetNChannels(sector),force);
1509 : }
1510 : //_____________________________________________________________________
1511 : TVectorF* AliTPCCalibCE::GetTMeanEvents(Int_t sector, Bool_t force)
1512 : {
1513 : /// return pointer to the EbyE info of the mean arrival time for 'sector'
1514 : /// if force is true create it if it doesn't exist allready
1515 :
1516 0 : TObjArray *arr = &fTMeanArrayEvent;
1517 0 : return GetVectSector(sector,arr,100,force);
1518 : }
1519 : //_____________________________________________________________________
1520 : TVectorF* AliTPCCalibCE::GetQMeanEvents(Int_t sector, Bool_t force)
1521 : {
1522 : /// return pointer to the EbyE info of the mean arrival time for 'sector'
1523 : /// if force is true create it if it doesn't exist allready
1524 :
1525 0 : TObjArray *arr = &fQMeanArrayEvent;
1526 0 : return GetVectSector(sector,arr,100,force);
1527 : }
1528 : //_____________________________________________________________________
1529 : AliTPCCalROC* AliTPCCalibCE::GetCalRoc(Int_t sector, TObjArray* arr, Bool_t force) const
1530 : {
1531 : /// return pointer to ROC Calibration
1532 : /// if force is true create a new histogram if it doesn't exist allready
1533 :
1534 0 : if ( !force || arr->UncheckedAt(sector) )
1535 0 : return (AliTPCCalROC*)arr->UncheckedAt(sector);
1536 :
1537 : // if we are forced and histogram doesn't yes exist create it
1538 :
1539 : // new AliTPCCalROC for T0 information. One value for each pad!
1540 0 : AliTPCCalROC *croc = new AliTPCCalROC(sector);
1541 0 : arr->AddAt(croc,sector);
1542 : return croc;
1543 0 : }
1544 : //_____________________________________________________________________
1545 : AliTPCCalROC* AliTPCCalibCE::GetCalRocT0(Int_t sector, Bool_t force)
1546 : {
1547 : /// return pointer to Time 0 ROC Calibration
1548 : /// if force is true create a new histogram if it doesn't exist allready
1549 :
1550 0 : TObjArray *arr = &fCalRocArrayT0;
1551 0 : return GetCalRoc(sector, arr, force);
1552 : }
1553 : //_____________________________________________________________________
1554 : AliTPCCalROC* AliTPCCalibCE::GetCalRocT0Err(Int_t sector, Bool_t force)
1555 : {
1556 : /// return pointer to the error of Time 0 ROC Calibration
1557 : /// if force is true create a new histogram if it doesn't exist allready
1558 :
1559 0 : TObjArray *arr = &fCalRocArrayT0Err;
1560 0 : return GetCalRoc(sector, arr, force);
1561 : }
1562 : //_____________________________________________________________________
1563 : AliTPCCalROC* AliTPCCalibCE::GetCalRocQ(Int_t sector, Bool_t force)
1564 : {
1565 : /// return pointer to T0 ROC Calibration
1566 : /// if force is true create a new histogram if it doesn't exist allready
1567 :
1568 0 : TObjArray *arr = &fCalRocArrayQ;
1569 0 : return GetCalRoc(sector, arr, force);
1570 : }
1571 : //_____________________________________________________________________
1572 : AliTPCCalROC* AliTPCCalibCE::GetCalRocRMS(Int_t sector, Bool_t force)
1573 : {
1574 : /// return pointer to signal width ROC Calibration
1575 : /// if force is true create a new histogram if it doesn't exist allready
1576 :
1577 0 : TObjArray *arr = &fCalRocArrayRMS;
1578 0 : return GetCalRoc(sector, arr, force);
1579 : }
1580 : //_____________________________________________________________________
1581 : AliTPCCalROC* AliTPCCalibCE::GetCalRocOutliers(Int_t sector, Bool_t force)
1582 : {
1583 : /// return pointer to Outliers
1584 : /// if force is true create a new histogram if it doesn't exist allready
1585 :
1586 0 : TObjArray *arr = &fCalRocArrayOutliers;
1587 0 : return GetCalRoc(sector, arr, force);
1588 : }
1589 : //_____________________________________________________________________
1590 : TObjArray* AliTPCCalibCE::GetParamArray(Int_t sector, TObjArray* arr, Bool_t force) const
1591 : {
1592 : /// return pointer to TObjArray of fit parameters
1593 : /// if force is true create a new histogram if it doesn't exist allready
1594 :
1595 0 : if ( !force || arr->UncheckedAt(sector) )
1596 0 : return (TObjArray*)arr->UncheckedAt(sector);
1597 :
1598 : // if we are forced and array doesn't yes exist create it
1599 :
1600 : // new TObjArray for parameters
1601 0 : TObjArray *newArr = new TObjArray;
1602 0 : arr->AddAt(newArr,sector);
1603 : return newArr;
1604 0 : }
1605 : //_____________________________________________________________________
1606 : TObjArray* AliTPCCalibCE::GetParamArrayPol1(Int_t sector, Bool_t force)
1607 : {
1608 : /// return pointer to TObjArray of fit parameters from plane fit
1609 : /// if force is true create a new histogram if it doesn't exist allready
1610 :
1611 0 : TObjArray *arr = &fParamArrayEventPol1;
1612 0 : return GetParamArray(sector, arr, force);
1613 : }
1614 : //_____________________________________________________________________
1615 : TObjArray* AliTPCCalibCE::GetParamArrayPol2(Int_t sector, Bool_t force)
1616 : {
1617 : /// return pointer to TObjArray of fit parameters from parabola fit
1618 : /// if force is true create a new histogram if it doesn't exist allready
1619 :
1620 0 : TObjArray *arr = &fParamArrayEventPol2;
1621 0 : return GetParamArray(sector, arr, force);
1622 : }
1623 :
1624 : //_____________________________________________________________________
1625 : void AliTPCCalibCE::CreateDVhist()
1626 : {
1627 : /// Setup the THnSparse for the drift velocity determination
1628 :
1629 : //HnSparse bins
1630 : //roc, row, pad, timebin, timestamp
1631 0 : TTimeStamp begin(2010,01,01,0,0,0);
1632 0 : TTimeStamp end(2035,01,01,0,0,0);
1633 0 : Int_t nbinsTime=(end.GetSec()-begin.GetSec())/60; //Minutes resolution
1634 :
1635 0 : Int_t bins[kHnBinsDV] = { 72, 96, 140, 1030, nbinsTime};
1636 0 : Double_t xmin[kHnBinsDV] = { 0., 0., 0., 0., (Double_t)begin.GetSec()};
1637 0 : Double_t xmax[kHnBinsDV] = {72., 96., 140., 1030., (Double_t)end.GetSec()};
1638 :
1639 0 : fHnDrift=new THnSparseI("fHnDrift","Laser digits",kHnBinsDV, bins, xmin, xmax);
1640 0 : fHnDrift->GetAxis(0)->SetNameTitle("ROC","Read-out chamber number");
1641 0 : fHnDrift->GetAxis(1)->SetNameTitle("Row","Row number");
1642 0 : fHnDrift->GetAxis(2)->SetNameTitle("Pad","Pad number");
1643 0 : fHnDrift->GetAxis(3)->SetNameTitle("Timebin","Time bin [x100ns]");
1644 0 : fHnDrift->GetAxis(4)->SetNameTitle("EventTime","Event time");
1645 0 : fHnDrift->Reset();
1646 0 : }
1647 :
1648 : //_____________________________________________________________________
1649 : void AliTPCCalibCE::ResetEvent()
1650 : {
1651 : /// Reset global counters -- Should be called before each event is processed
1652 :
1653 0 : fLastSector=-1;
1654 0 : fCurrentSector=-1;
1655 0 : fCurrentRow=-1;
1656 0 : fCurrentChannel=-1;
1657 :
1658 0 : ResetPad();
1659 :
1660 0 : fPadTimesArrayEvent.Delete();
1661 0 : fPadQArrayEvent.Delete();
1662 0 : fPadRMSArrayEvent.Delete();
1663 0 : fPadPedestalArrayEvent.Delete();
1664 :
1665 0 : for ( Int_t i=0; i<72; ++i ){
1666 0 : fVTime0Offset.GetMatrixArray()[i]=0;
1667 0 : fVTime0OffsetCounter.GetMatrixArray()[i]=0;
1668 0 : fVMeanQ.GetMatrixArray()[i]=0;
1669 0 : fVMeanQCounter.GetMatrixArray()[i]=0;
1670 : }
1671 0 : }
1672 : //_____________________________________________________________________
1673 : void AliTPCCalibCE::ResetPad()
1674 : {
1675 : /// Reset pad infos -- Should be called after a pad has been processed
1676 :
1677 0 : for (Int_t i=fFirstTimeBin; i<fLastTimeBin+1; ++i)
1678 0 : fPadSignal[i] = 0;
1679 0 : fMaxTimeBin = -1;
1680 0 : fMaxPadSignal = -1;
1681 0 : fPadPedestal = -1;
1682 0 : fPadNoise = -1;
1683 0 : }
1684 : //_____________________________________________________________________
1685 : void AliTPCCalibCE::Merge(AliTPCCalibCE * const ce)
1686 : {
1687 : /// Merge ce to the current AliTPCCalibCE
1688 :
1689 0 : MergeBase(ce);
1690 0 : Int_t nCEevents = ce->GetNeventsProcessed();
1691 :
1692 0 : if (fProcessOld&&ce->fProcessOld){
1693 : //merge histograms
1694 0 : for (Int_t iSec=0; iSec<72; ++iSec){
1695 0 : TH2S *hRefQmerge = ce->GetHistoQ(iSec);
1696 0 : TH2S *hRefT0merge = ce->GetHistoT0(iSec);
1697 0 : TH2S *hRefRMSmerge = ce->GetHistoRMS(iSec);
1698 :
1699 :
1700 0 : if ( hRefQmerge ){
1701 0 : TDirectory *dir = hRefQmerge->GetDirectory(); hRefQmerge->SetDirectory(0);
1702 0 : TH2S *hRefQ = GetHistoQ(iSec);
1703 0 : if ( hRefQ ) hRefQ->Add(hRefQmerge);
1704 : else {
1705 0 : TH2S *hist = new TH2S(*hRefQmerge);
1706 0 : hist->SetDirectory(0);
1707 0 : fHistoQArray.AddAt(hist, iSec);
1708 : }
1709 0 : hRefQmerge->SetDirectory(dir);
1710 0 : }
1711 0 : if ( hRefT0merge ){
1712 0 : TDirectory *dir = hRefT0merge->GetDirectory(); hRefT0merge->SetDirectory(0);
1713 0 : TH2S *hRefT0 = GetHistoT0(iSec);
1714 0 : if ( hRefT0 ) hRefT0->Add(hRefT0merge);
1715 : else {
1716 0 : TH2S *hist = new TH2S(*hRefT0merge);
1717 0 : hist->SetDirectory(0);
1718 0 : fHistoT0Array.AddAt(hist, iSec);
1719 : }
1720 0 : hRefT0merge->SetDirectory(dir);
1721 0 : }
1722 0 : if ( hRefRMSmerge ){
1723 0 : TDirectory *dir = hRefRMSmerge->GetDirectory(); hRefRMSmerge->SetDirectory(0);
1724 0 : TH2S *hRefRMS = GetHistoRMS(iSec);
1725 0 : if ( hRefRMS ) hRefRMS->Add(hRefRMSmerge);
1726 : else {
1727 0 : TH2S *hist = new TH2S(*hRefRMSmerge);
1728 0 : hist->SetDirectory(0);
1729 0 : fHistoRMSArray.AddAt(hist, iSec);
1730 : }
1731 0 : hRefRMSmerge->SetDirectory(dir);
1732 0 : }
1733 :
1734 : }
1735 :
1736 : // merge time information
1737 :
1738 :
1739 0 : for (Int_t iSec=0; iSec<72; ++iSec){
1740 0 : TObjArray *arrPol1CE = ce->GetParamArrayPol1(iSec);
1741 0 : TObjArray *arrPol2CE = ce->GetParamArrayPol2(iSec);
1742 0 : TVectorF *vMeanTimeCE = ce->GetTMeanEvents(iSec);
1743 0 : TVectorF *vMeanQCE = ce->GetQMeanEvents(iSec);
1744 :
1745 : TObjArray *arrPol1 = 0x0;
1746 : TObjArray *arrPol2 = 0x0;
1747 : TVectorF *vMeanTime = 0x0;
1748 : TVectorF *vMeanQ = 0x0;
1749 :
1750 : //resize arrays
1751 0 : if ( arrPol1CE && arrPol2CE ){
1752 0 : arrPol1 = GetParamArrayPol1(iSec,kTRUE);
1753 0 : arrPol2 = GetParamArrayPol2(iSec,kTRUE);
1754 0 : arrPol1->Expand(fNevents+nCEevents);
1755 0 : arrPol2->Expand(fNevents+nCEevents);
1756 0 : }
1757 0 : if ( vMeanTimeCE && vMeanQCE ){
1758 0 : vMeanTime = GetTMeanEvents(iSec,kTRUE);
1759 0 : vMeanQ = GetQMeanEvents(iSec,kTRUE);
1760 0 : vMeanTime->ResizeTo(fNevents+nCEevents);
1761 0 : vMeanQ->ResizeTo(fNevents+nCEevents);
1762 0 : }
1763 :
1764 0 : for (Int_t iEvent=0; iEvent<nCEevents; ++iEvent){
1765 0 : if ( arrPol1CE && arrPol2CE ){
1766 0 : TVectorD *paramPol1 = (TVectorD*)(arrPol1CE->UncheckedAt(iEvent));
1767 0 : TVectorD *paramPol2 = (TVectorD*)(arrPol2CE->UncheckedAt(iEvent));
1768 0 : if ( paramPol1 && paramPol2 ){
1769 0 : GetParamArrayPol1(iSec,kTRUE)->AddAt(new TVectorD(*paramPol1), fNevents+iEvent);
1770 0 : GetParamArrayPol2(iSec,kTRUE)->AddAt(new TVectorD(*paramPol2), fNevents+iEvent);
1771 0 : }
1772 0 : }
1773 0 : if ( vMeanTimeCE && vMeanQCE ){
1774 0 : vMeanTime->GetMatrixArray()[fNevents+iEvent]=vMeanTimeCE->GetMatrixArray()[iEvent];
1775 0 : vMeanQ->GetMatrixArray()[fNevents+iEvent]=vMeanQCE->GetMatrixArray()[iEvent];
1776 0 : }
1777 : }
1778 : }
1779 :
1780 :
1781 :
1782 0 : const TVectorD& eventTimes = ce->fVEventTime;
1783 0 : const TVectorD& eventIds = ce->fVEventNumber;
1784 0 : const TVectorF& time0SideA = ce->fVTime0SideA;
1785 0 : const TVectorF& time0SideC = ce->fVTime0SideC;
1786 0 : fVEventTime.ResizeTo(fNevents+nCEevents);
1787 0 : fVEventNumber.ResizeTo(fNevents+nCEevents);
1788 0 : fVTime0SideA.ResizeTo(fNevents+nCEevents);
1789 0 : fVTime0SideC.ResizeTo(fNevents+nCEevents);
1790 :
1791 0 : for (Int_t iEvent=0; iEvent<nCEevents; ++iEvent){
1792 0 : Double_t evTime = eventTimes.GetMatrixArray()[iEvent];
1793 0 : Double_t evId = eventIds.GetMatrixArray()[iEvent];
1794 0 : Float_t t0SideA = time0SideA.GetMatrixArray()[iEvent];
1795 0 : Float_t t0SideC = time0SideC.GetMatrixArray()[iEvent];
1796 :
1797 0 : fVEventTime.GetMatrixArray()[fNevents+iEvent] = evTime;
1798 0 : fVEventNumber.GetMatrixArray()[fNevents+iEvent] = evId;
1799 0 : fVTime0SideA.GetMatrixArray()[fNevents+iEvent] = t0SideA;
1800 0 : fVTime0SideC.GetMatrixArray()[fNevents+iEvent] = t0SideC;
1801 : }
1802 0 : }
1803 :
1804 0 : if (fProcessNew&&ce->fProcessNew) {
1805 0 : if (fArrHnDrift.GetEntries() != ce->fArrHnDrift.GetEntries() ){
1806 0 : AliError("Number of bursts in the instances to merge are different. No merging done!");
1807 0 : } else {
1808 0 : for (Int_t i=0;i<fArrHnDrift.GetEntries();++i){
1809 0 : THnSparseI *h=(THnSparseI*)fArrHnDrift.UncheckedAt(i);
1810 0 : THnSparseI *hce=(THnSparseI*)ce->fArrHnDrift.UncheckedAt(i);
1811 0 : if (h && hce) h->Add(hce);
1812 0 : else AliError(Form("AliTPCCalibCE::Merge - one THnSparse missing in burst %d",i));
1813 : }
1814 : //TODO: What to do with fTimeBursts???
1815 : }
1816 : }
1817 :
1818 0 : fNevents+=nCEevents; //increase event counter
1819 0 : }
1820 :
1821 : //_____________________________________________________________________
1822 : Long64_t AliTPCCalibCE::Merge(TCollection * const list)
1823 : {
1824 : /// Merge all objects of this type in list
1825 :
1826 : Long64_t nmerged=1;
1827 :
1828 0 : TIter next(list);
1829 : AliTPCCalibCE *ce=0;
1830 : TObject *o=0;
1831 :
1832 0 : while ( (o=next()) ){
1833 0 : ce=dynamic_cast<AliTPCCalibCE*>(o);
1834 0 : if (ce){
1835 0 : Merge(ce);
1836 0 : ++nmerged;
1837 0 : }
1838 : }
1839 :
1840 : return nmerged;
1841 0 : }
1842 :
1843 : //_____________________________________________________________________
1844 : TGraph *AliTPCCalibCE::MakeGraphTimeCE(Int_t sector, Int_t xVariable, Int_t fitType, Int_t fitParameter)
1845 : {
1846 : /// Make graph from fit parameters of pol1 fit, pol2 fit, mean arrival time or mean Q for ROC 'sector'
1847 : /// or side (-1: A-Side, -2: C-Side)
1848 : /// xVariable: 0-event time, 1-event id, 2-internal event counter
1849 : /// fitType: 0-pol1 fit, 1-pol2 fit, 2-mean time, 3-mean Q
1850 : /// fitParameter: fit parameter ( 0-2 for pol1 ([0]+[1]*x+[2]*y),
1851 : /// 0-5 for pol2 ([0]+[1]*x+[2]*y+[3]*x*x+[4]*y*y+[5]*x*y),
1852 : /// not used for mean time and mean Q )
1853 : /// for an example see class description at the beginning
1854 :
1855 : TVectorD *xVar = 0x0;
1856 : TObjArray *aType = 0x0;
1857 : Int_t npoints=0;
1858 :
1859 : // sanity checks
1860 0 : if ( (sector<-2) || (sector>71) ) return 0x0; //sector outside valid range
1861 0 : if ( (xVariable<0) || (xVariable>2) ) return 0x0; //invalid x-variable
1862 0 : if ( (fitType<0) || (fitType>3) ) return 0x0; //invalid fit type
1863 0 : if ( sector>=0 && fitType==2 && !GetTMeanEvents(sector) ) return 0x0; //no mean time information available
1864 0 : if ( sector>=0 && fitType==3 && !GetQMeanEvents(sector) ) return 0x0; //no mean charge information available
1865 0 : if ( sector<0 && fitType!=2) return 0x0; //for side wise information only mean time is available
1866 :
1867 0 : if (sector>=0){
1868 0 : if ( fitType==0 ){
1869 0 : if ( (fitParameter<0) || (fitParameter>2) ) return 0x0;
1870 0 : aType = &fParamArrayEventPol1;
1871 0 : if ( aType->At(sector)==0x0 ) return 0x0;
1872 : }
1873 0 : else if ( fitType==1 ){
1874 0 : if ( (fitParameter<0) || (fitParameter>5) ) return 0x0;
1875 0 : aType = &fParamArrayEventPol2;
1876 0 : if ( aType->At(sector)==0x0 ) return 0x0;
1877 : }
1878 :
1879 : }
1880 0 : if ( xVariable == 0 ) xVar = &fVEventTime;
1881 0 : if ( xVariable == 1 ) xVar = &fVEventNumber;
1882 0 : if ( xVariable == 2 ) {
1883 0 : xVar = new TVectorD(fNevents);
1884 0 : for ( Int_t i=0;i<fNevents; ++i) (*xVar)[i]=i;
1885 0 : }
1886 :
1887 0 : Double_t *x = new Double_t[fNevents];
1888 0 : Double_t *y = new Double_t[fNevents];
1889 :
1890 0 : for (Int_t ievent =0; ievent<fNevents; ++ievent){
1891 0 : if ( fitType<2 ){
1892 0 : TObjArray *events = (TObjArray*)(aType->At(sector));
1893 0 : if ( events->GetSize()<=ievent ) break;
1894 0 : TVectorD *v = (TVectorD*)(events->At(ievent));
1895 0 : if ( (v!=0x0) && ((*xVar)[ievent]>0) ) { x[npoints]=(*xVar)[ievent]; y[npoints]=(*v)[fitParameter]; npoints++;}
1896 0 : } else if (fitType == 2) {
1897 0 : Double_t xValue=(*xVar)[ievent];
1898 : Double_t yValue=0;
1899 0 : if (sector>=0) yValue = (*GetTMeanEvents(sector))[ievent];
1900 0 : else if (sector==-1) yValue=fVTime0SideA(ievent);
1901 0 : else if (sector==-2) yValue=fVTime0SideC(ievent);
1902 0 : if ( yValue>0 && xValue>0 ) { x[npoints]=xValue; y[npoints]=yValue;npoints++;}
1903 0 : }else if (fitType == 3) {
1904 0 : Double_t xValue=(*xVar)[ievent];
1905 0 : Double_t yValue=(*GetQMeanEvents(sector))[ievent];
1906 0 : if ( yValue>0 && xValue>0 ) { x[npoints]=xValue; y[npoints]=yValue;npoints++;}
1907 0 : }
1908 : }
1909 :
1910 0 : TGraph *gr = new TGraph(npoints);
1911 : //sort xVariable increasing
1912 0 : Int_t *sortIndex = new Int_t[npoints];
1913 0 : TMath::Sort(npoints,x,sortIndex, kFALSE);
1914 0 : for (Int_t i=0;i<npoints;++i){
1915 0 : gr->SetPoint(i,x[sortIndex[i]],y[sortIndex[i]]);
1916 : }
1917 :
1918 :
1919 0 : if ( xVariable == 2 ) delete xVar;
1920 0 : delete [] x;
1921 0 : delete [] y;
1922 0 : delete [] sortIndex;
1923 : return gr;
1924 0 : }
1925 : //_____________________________________________________________________
1926 : void AliTPCCalibCE::Analyse()
1927 : {
1928 : /// Calculate calibration constants
1929 :
1930 0 : if (fProcessOld){
1931 0 : TVectorD paramQ(3);
1932 0 : TVectorD paramT0(3);
1933 0 : TVectorD paramRMS(3);
1934 0 : TMatrixD dummy(3,3);
1935 :
1936 : Float_t channelCounter=0;
1937 0 : fMeanT0rms=0;
1938 0 : fMeanQrms=0;
1939 0 : fMeanRMSrms=0;
1940 :
1941 0 : for (Int_t iSec=0; iSec<72; ++iSec){
1942 0 : TH2S *hT0 = GetHistoT0(iSec);
1943 0 : if (!hT0 ) continue;
1944 :
1945 0 : AliTPCCalROC *rocQ = GetCalRocQ (iSec,kTRUE);
1946 0 : AliTPCCalROC *rocT0 = GetCalRocT0 (iSec,kTRUE);
1947 0 : AliTPCCalROC *rocT0Err = GetCalRocT0Err (iSec,kTRUE);
1948 0 : AliTPCCalROC *rocRMS = GetCalRocRMS(iSec,kTRUE);
1949 0 : AliTPCCalROC *rocOut = GetCalRocOutliers(iSec,kTRUE);
1950 :
1951 0 : TH2S *hQ = GetHistoQ(iSec);
1952 0 : TH2S *hRMS = GetHistoRMS(iSec);
1953 :
1954 0 : Short_t *arrayhQ = hQ->GetArray();
1955 0 : Short_t *arrayhT0 = hT0->GetArray();
1956 0 : Short_t *arrayhRMS = hRMS->GetArray();
1957 :
1958 0 : UInt_t nChannels = fROC->GetNChannels(iSec);
1959 :
1960 : //debug
1961 0 : Int_t row=0;
1962 0 : Int_t pad=0;
1963 0 : Int_t padc=0;
1964 : //! debug
1965 :
1966 0 : for (UInt_t iChannel=0; iChannel<nChannels; ++iChannel){
1967 :
1968 :
1969 0 : Float_t cogTime0 = -1000;
1970 0 : Float_t cogQ = -1000;
1971 0 : Float_t cogRMS = -1000;
1972 : Float_t cogOut = 0;
1973 0 : Float_t rms = 0;
1974 0 : Float_t rmsT0 = 0;
1975 :
1976 :
1977 0 : Int_t offsetQ = (fNbinsQ+2)*(iChannel+1)+1;
1978 0 : Int_t offsetT0 = (fNbinsT0+2)*(iChannel+1)+1;
1979 0 : Int_t offsetRMS = (fNbinsRMS+2)*(iChannel+1)+1;
1980 :
1981 0 : cogQ = AliMathBase::GetCOG(arrayhQ+offsetQ,fNbinsQ,fXminQ,fXmaxQ,&rms);
1982 0 : fMeanQrms+=rms;
1983 0 : cogTime0 = AliMathBase::GetCOG(arrayhT0+offsetT0,fNbinsT0,fXminT0,fXmaxT0,&rmsT0);
1984 0 : fMeanT0rms+=rmsT0;
1985 0 : cogRMS = AliMathBase::GetCOG(arrayhRMS+offsetRMS,fNbinsRMS,fXminRMS,fXmaxRMS,&rms);
1986 0 : fMeanRMSrms+=rms;
1987 0 : channelCounter++;
1988 :
1989 : /*
1990 : //outlier specifications
1991 : if ( (cogQ < ??) && (cogTime0 > ??) && (cogTime0<??) && ( cogRMS>??) ){
1992 : cogOut = 1;
1993 : cogTime0 = 0;
1994 : cogQ = 0;
1995 : cogRMS = 0;
1996 : }
1997 : */
1998 0 : rocQ->SetValue(iChannel, cogQ*cogQ);
1999 0 : rocT0->SetValue(iChannel, cogTime0);
2000 0 : rocT0Err->SetValue(iChannel, rmsT0);
2001 0 : rocRMS->SetValue(iChannel, cogRMS);
2002 0 : rocOut->SetValue(iChannel, cogOut);
2003 :
2004 :
2005 : //debug
2006 0 : if ( GetStreamLevel() > 0 ){
2007 0 : TTreeSRedirector *streamer=GetDebugStreamer();
2008 0 : if ( streamer ) {
2009 :
2010 0 : while ( iChannel > (fROC->GetRowIndexes(iSec)[row]+fROC->GetNPads(iSec,row)-1) ) row++;
2011 0 : pad = iChannel-fROC->GetRowIndexes(iSec)[row];
2012 0 : padc = pad-(fROC->GetNPads(iSec,row)/2);
2013 :
2014 0 : (*streamer) << "DataEnd" <<
2015 0 : "Sector=" << iSec <<
2016 0 : "Pad=" << pad <<
2017 0 : "PadC=" << padc <<
2018 0 : "Row=" << row <<
2019 0 : "PadSec=" << iChannel <<
2020 0 : "Q=" << cogQ <<
2021 0 : "T0=" << cogTime0 <<
2022 0 : "RMS=" << cogRMS <<
2023 : "\n";
2024 : }
2025 0 : }
2026 : //! debug
2027 :
2028 0 : }
2029 :
2030 0 : }
2031 0 : if ( channelCounter>0 ){
2032 0 : fMeanT0rms/=channelCounter;
2033 0 : fMeanQrms/=channelCounter;
2034 0 : fMeanRMSrms/=channelCounter;
2035 0 : }
2036 : // if ( fDebugStreamer ) fDebugStreamer->GetFile()->Write();
2037 : // delete fDebugStreamer;
2038 : // fDebugStreamer = 0x0;
2039 0 : fVEventTime.ResizeTo(fNevents);
2040 0 : fVEventNumber.ResizeTo(fNevents);
2041 0 : fVTime0SideA.ResizeTo(fNevents);
2042 0 : fVTime0SideC.ResizeTo(fNevents);
2043 0 : }
2044 :
2045 0 : if (fProcessNew&&fAnalyseNew){
2046 0 : AnalyseTrack();
2047 0 : for (Int_t iburst=0; iburst<fArrHnDrift.GetEntries(); ++iburst){
2048 0 : THnSparseI *h=(THnSparseI*)fArrHnDrift.UncheckedAt(iburst);
2049 0 : h->GetAxis(4)->SetRangeUser(fTimeBursts[iburst]-60*5,fTimeBursts[iburst]+60*5);
2050 : }
2051 0 : }
2052 0 : }
2053 :
2054 :
2055 :
2056 :
2057 : //
2058 : // New functions that also use the laser tracks
2059 : //
2060 :
2061 :
2062 :
2063 : //_____________________________________________________________________
2064 : void AliTPCCalibCE::FindLocalMaxima(TObjArray * const arrObj, Double_t timestamp, Int_t burst)
2065 : {
2066 : /// Find the local maximums for the projections to each axis
2067 :
2068 : //find laser layer positoins
2069 0 : fHnDrift->GetAxis(4)->SetRangeUser(timestamp-2*60,timestamp+2*60);
2070 0 : FindLaserLayers();
2071 0 : THnSparse *hProj=fHnDrift;
2072 0 : Double_t posCE[4]={0.,0.,0.,0.};
2073 0 : Double_t widthCE[4]={0.,0.,0.,0.};
2074 :
2075 : // if(fPeaks[4]!=0){
2076 : // find central electrode position once more, separately for IROC, OROC, A-, C-Side
2077 :
2078 0 : for (Int_t i=0; i<4; ++i){
2079 0 : Int_t ce=(i/2>0)*7+6;
2080 0 : hProj->GetAxis(0)->SetRangeUser(i*18,(i+1)*18-1);
2081 0 : TH1 *h=fHnDrift->Projection(3);
2082 0 : h->GetXaxis()->SetRangeUser(fPeaks[ce]-fPeakWidths[ce],fPeaks[ce]+fPeakWidths[ce]);
2083 0 : Int_t nbinMax=h->GetMaximumBin();
2084 0 : Double_t maximum=h->GetMaximum();
2085 : // Double_t maxExpected=fNevents/fArrHnDrift->GetEntries()*556568./5./10.;
2086 : // if (nbinMax<700||maximum<maxExpected) continue;
2087 0 : Double_t xbinMax=h->GetBinCenter(nbinMax);
2088 0 : TF1 fgaus("gaus","gaus",xbinMax-5,xbinMax+5);
2089 0 : fgaus.SetParameters(maximum,xbinMax,2);
2090 0 : fgaus.SetParLimits(1,xbinMax-5.,xbinMax+5.);
2091 0 : fgaus.SetParLimits(2,0.2,4.);
2092 0 : h->Fit(&fgaus,"RQN");
2093 : // Double_t deltaX=4*fgaus.GetParameter(2);
2094 : // xbinMax=fgaus.GetParameter(1);
2095 0 : delete h;
2096 0 : posCE[i]=fgaus.GetParameter(1);
2097 0 : widthCE[i]=4*fgaus.GetParameter(2);
2098 0 : hProj->GetAxis(0)->SetRangeUser(0,72);
2099 0 : }
2100 : // }
2101 : //Current drift velocity
2102 : Float_t vdrift=2.61301900000000000e+06;//fParam->GetDriftV();
2103 : // cout<<"vdrift="<<vdrift<<endl;
2104 :
2105 0 : AliDebug(5,Form("Timestamp %f - default drift velocity %f",timestamp,vdrift));
2106 : //loop over all entries in the histogram
2107 0 : Int_t coord[5];
2108 0 : for(Long64_t ichunk=0;ichunk<hProj->GetNbins();ichunk++){
2109 : //get entry position and content
2110 0 : Double_t adc=hProj->GetBinContent(ichunk,coord);
2111 :
2112 :
2113 0 : Int_t sector = coord[0]-1;
2114 0 : Int_t row = coord[1]-1;
2115 0 : Int_t pad = coord[2]-1;
2116 0 : Int_t timeBin= coord[3]-1;
2117 0 : Double_t time = fHnDrift->GetAxis(4)->GetBinCenter(coord[4]);
2118 0 : Int_t side = (sector/18)%2;
2119 : // return;
2120 : // fPeaks[4]=(UInt_t)posCE[sector/18];
2121 : // fPeakWidths[4]=(UInt_t)widthCE[sector/18];
2122 :
2123 : //cuts
2124 0 : if (time<timestamp-120||time>timestamp+120) continue; //window of +- 2min
2125 0 : if (adc < 5 ) continue;
2126 0 : if (IsEdgePad(sector,row,pad)) continue;
2127 : // if (!IsPeakInRange(timeBin)) continue;
2128 : // if (isCE&&((row%2)||(row%2)||(sector%2))) continue;
2129 : // if (isCE&&(sector!=0)) continue;
2130 :
2131 : Int_t padmin=-2, padmax=2;
2132 : Int_t timemin=-2, timemax=2;
2133 : Int_t minsumperpad=2;
2134 : //CE or laser tracks
2135 : Bool_t isCE=kFALSE;
2136 0 : if (TMath::Abs((Short_t)timeBin-(Short_t)posCE[sector/18])<(Short_t)widthCE[sector/18]) {
2137 : isCE=kTRUE;
2138 : padmin=0;
2139 : padmax=0;
2140 : timemin=-3;
2141 : timemax=7;
2142 0 : }
2143 :
2144 : //
2145 : // Find local maximum and cogs
2146 : //
2147 : Bool_t isMaximum=kTRUE;
2148 0 : Float_t totalmass=0, tbcm=0, padcm=0, rmstb=0, rmspad=0;
2149 0 : Double_t cogY=0, rmsY=0;
2150 0 : Int_t npart=0;
2151 :
2152 : // for position calculation use
2153 0 : for(Int_t ipad=padmin;ipad<=padmax;++ipad){
2154 0 : Float_t lxyz[3];
2155 0 : fROC->GetPositionLocal(sector,row,pad+ipad,lxyz);
2156 :
2157 0 : for(Int_t itime=timemin;itime<=timemax;++itime){
2158 :
2159 0 : Int_t a[5]={coord[0],coord[1],coord[2]+ipad,coord[3]+itime,coord[4]};
2160 0 : Double_t val=hProj->GetBinContent(a);
2161 0 : totalmass+=val;
2162 :
2163 0 : tbcm +=(timeBin+itime)*val;
2164 0 : padcm+=(pad+ipad)*val;
2165 0 : cogY +=lxyz[1]*val;
2166 :
2167 0 : rmstb +=(timeBin+itime)*(timeBin+itime)*val;
2168 0 : rmspad+=(pad+ipad)*(pad+ipad)*val;
2169 0 : rmsY +=lxyz[1]*lxyz[1]*val;
2170 :
2171 0 : if (val>0) ++npart;
2172 0 : if (val>adc) {
2173 : isMaximum=kFALSE;
2174 0 : break;
2175 : }
2176 0 : }
2177 0 : if (!isMaximum) break;
2178 0 : }
2179 :
2180 0 : if (!isMaximum||!npart) continue;
2181 0 : if (totalmass<npart*minsumperpad) continue;
2182 0 : if (!isCE&&rmspad<.1) continue; //most probably noise, since signal only in one pad,
2183 : //for CE we want only one pad by construction
2184 :
2185 0 : tbcm/=totalmass;
2186 0 : padcm/=totalmass;
2187 0 : cogY/=totalmass;
2188 :
2189 0 : rmstb/=totalmass;
2190 0 : rmspad/=totalmass;
2191 0 : rmsY/=totalmass;
2192 :
2193 0 : rmstb=TMath::Sqrt(TMath::Abs(tbcm*tbcm-rmstb));
2194 0 : rmspad=TMath::Sqrt(TMath::Abs(padcm*padcm-rmspad));
2195 0 : rmsY=TMath::Sqrt(TMath::Abs(cogY*cogY-rmsY));
2196 :
2197 0 : Int_t cog=TMath::Nint(padcm);
2198 :
2199 : // timebin --> z position
2200 0 : Float_t zlength=fParam->GetZLength(side);
2201 : // Float_t timePos=tbcm+(1000-fPeaks[4])
2202 : // drift velocity is in m/s we would like to have cm/100ns, so 100cm/(10^7*100ns)
2203 0 : Double_t gz=(zlength-(tbcm*vdrift*1.e-7))*TMath::Power(-1,side);
2204 :
2205 : // local to global transformation--> x and y positions
2206 0 : Float_t padlxyz[3];
2207 0 : fROC->GetPositionLocal(sector,row,pad,padlxyz);
2208 :
2209 0 : Double_t gxyz[3]={padlxyz[0],cogY,gz};
2210 0 : Double_t lxyz[3]={padlxyz[0],cogY,gz};
2211 0 : Double_t igxyz[3]={0,0,0};
2212 0 : AliTPCTransform t1;
2213 0 : t1.RotatedGlobal2Global(sector,gxyz);
2214 :
2215 0 : Double_t mindist=0;
2216 0 : Int_t trackID=-1;
2217 0 : Int_t trackID2=-1;
2218 :
2219 : //find track id and index of the position in the track (row)
2220 0 : Int_t index=0;
2221 0 : if (!isCE){
2222 0 : index=row+(sector>35)*fROC->GetNRows(0);
2223 0 : trackID=FindLaserTrackID(sector,index,gxyz,mindist,lxyz,trackID2);
2224 0 : } else {
2225 0 : trackID=336+((sector/18)%2);
2226 0 : index= fROC->GetRowIndexes(sector)[row]+pad; // global pad position in sector
2227 0 : if (sector<36) {
2228 0 : index+=(sector%18)*fROC->GetNChannels(sector);
2229 0 : } else {
2230 0 : index+=18*fROC->GetNChannels(0);
2231 0 : index+=(sector%18)*fROC->GetNChannels(sector);
2232 : }
2233 : //TODO: find out about the multiple peaks in the CE
2234 : // mindist=TMath::Abs(fPeaks[4]-tbcm);
2235 0 : mindist=1.;
2236 : }
2237 :
2238 : // fill track vectors
2239 0 : if (trackID>0){
2240 0 : AliTPCLaserTrack *ltr=(AliTPCLaserTrack*)arrObj->UncheckedAt(trackID);
2241 0 : Double_t oldMinDist=ltr->fVecPhi->GetMatrixArray()[index];
2242 :
2243 :
2244 : // travel time effect of light includes
2245 :
2246 0 : Double_t raylength=ltr->GetRayLength();
2247 0 : Double_t globmir[3]={ltr->Xv(),ltr->Yv(),ltr->Zv()};
2248 0 : ltr->GetXYZ(globmir);
2249 0 : if(trackID<336){
2250 : if(side==0){
2251 0 : gxyz[2]=gxyz[2]-(TMath::Sqrt((gxyz[0]-globmir[0])*(gxyz[0]-globmir[0])
2252 0 : +(gxyz[1]-globmir[1])*(gxyz[1]-globmir[1])
2253 0 : +(gxyz[2]-globmir[2])*(gxyz[2]-globmir[2])+raylength))*vdrift*TMath::Power(10.,-6.)/30000;
2254 0 : }
2255 : else {
2256 : gxyz[2]=gxyz[2]-(TMath::Sqrt((gxyz[0]-globmir[0])*(gxyz[0]-globmir[0])
2257 : +(gxyz[1]-globmir[1])*(gxyz[1]-globmir[1])
2258 : +(gxyz[2]-globmir[2])*(gxyz[2]-globmir[2])+raylength))*vdrift*TMath::Power(10.,-6.)/30000;
2259 : }
2260 : }
2261 :
2262 0 : if (TMath::Abs(oldMinDist)<1.e-20||oldMinDist>mindist){
2263 0 : ltr->fVecSec->GetMatrixArray()[index]=sector;
2264 0 : ltr->fVecP2->GetMatrixArray()[index]=0;
2265 0 : ltr->fVecPhi->GetMatrixArray()[index]=mindist;
2266 0 : ltr->fVecGX->GetMatrixArray()[index]=gxyz[0];
2267 0 : ltr->fVecGY->GetMatrixArray()[index]=gxyz[1];
2268 0 : ltr->fVecGZ->GetMatrixArray()[index]=gxyz[2];
2269 0 : ltr->fVecLX->GetMatrixArray()[index]=lxyz[0];
2270 0 : ltr->fVecLY->GetMatrixArray()[index]=lxyz[1];
2271 0 : ltr->fVecLZ->GetMatrixArray()[index]=lxyz[2];
2272 : // ltr->SetUniqueID((UInt_t)(mindist*10000)); //distance in um
2273 0 : }
2274 0 : TObjArray *arr=AliTPCLaserTrack::GetTracks();
2275 0 : ltr=(AliTPCLaserTrack*)arr->UncheckedAt(trackID);
2276 0 : igxyz[0]=ltr->fVecGX->GetMatrixArray()[row];
2277 0 : igxyz[1]=ltr->fVecGY->GetMatrixArray()[row];
2278 0 : igxyz[2]=ltr->fVecGZ->GetMatrixArray()[row];
2279 0 : }
2280 :
2281 :
2282 0 : if (fStreamLevel>4){
2283 0 : (*GetDebugStreamer()) << "clusters" <<
2284 0 : "run=" << fRunNumber <<
2285 0 : "timestamp=" << timestamp <<
2286 0 : "burst=" << burst <<
2287 0 : "side=" << side <<
2288 0 : "sec=" << sector <<
2289 0 : "row=" << row <<
2290 0 : "pad=" << pad <<
2291 0 : "padCog=" << cog <<
2292 0 : "timebin=" << timeBin <<
2293 0 : "cogCE=" << posCE[sector/18] <<
2294 0 : "withCE=" << widthCE[sector/18] <<
2295 0 : "index=" << index <<
2296 :
2297 0 : "padcm=" << padcm <<
2298 0 : "rmspad=" << rmspad <<
2299 :
2300 0 : "cogtb=" << tbcm <<
2301 0 : "rmstb=" << rmstb <<
2302 :
2303 0 : "npad=" << npart <<
2304 :
2305 0 : "lx=" << padlxyz[0]<<
2306 0 : "ly=" << cogY <<
2307 0 : "lypad=" << padlxyz[1]<<
2308 0 : "rmsY=" << rmsY <<
2309 :
2310 0 : "gx=" << gxyz[0] <<
2311 0 : "gy=" << gxyz[1] <<
2312 0 : "gz=" << gxyz[2] <<
2313 :
2314 0 : "igx=" << igxyz[0] <<
2315 0 : "igy=" << igxyz[1] <<
2316 0 : "igz=" << igxyz[2] <<
2317 :
2318 0 : "mind=" << mindist <<
2319 0 : "max=" << adc <<
2320 0 : "trackid=" << trackID <<
2321 0 : "trackid2=" << trackID2 <<
2322 0 : "npart=" << npart <<
2323 : "\n";
2324 : } // end stream levelmgz.fElements
2325 :
2326 0 : }
2327 :
2328 0 : }
2329 :
2330 : //_____________________________________________________________________
2331 : void AliTPCCalibCE::AnalyseTrack()
2332 : {
2333 : /// Analyse the tracks
2334 :
2335 :
2336 0 : AliTPCLaserTrack::LoadTracks();
2337 : // AliTPCParam *param=0x0;
2338 : // //cdb run number
2339 : // AliCDBManager *man=AliCDBManager::Instance();
2340 : // if (man->GetDefaultStorage()){
2341 : // AliCDBEntry *entry=man->Get("TPC/Calib/Parameters",fRunNumber);
2342 : // if (entry){
2343 : // entry->SetOwner(kTRUE);
2344 : // param = (AliTPCParam*)(entry->GetObject()->Clone());
2345 : // }
2346 : // }
2347 : // if (param){
2348 : // if (fParam) delete fParam;
2349 : // fParam=param;
2350 : // } else {
2351 : // AliError("Could not get updated AliTPCParam from OCDB!!!");
2352 : // }
2353 :
2354 : //Measured and ideal laser tracks
2355 0 : TObjArray* arrMeasured = SetupMeasured();
2356 0 : TObjArray* arrIdeal = AliTPCLaserTrack::GetTracks();
2357 0 : AddCEtoIdeal(arrIdeal);
2358 :
2359 : //find bursts and loop over them
2360 0 : for (Int_t iburst=0; iburst<fArrHnDrift.GetEntries();++iburst){
2361 0 : Double_t timestamp=fTimeBursts[iburst];
2362 0 : AliDebug(5,Form("Burst: %d (%f)",iburst,timestamp));
2363 0 : fHnDrift=(THnSparseI*)fArrHnDrift.UncheckedAt(iburst);
2364 0 : if (!fHnDrift) continue;
2365 0 : UInt_t entries=(UInt_t)fHnDrift->GetEntries();
2366 0 : if (fBinsLastAna[iburst]>=entries) continue; //already analysed!!!
2367 0 : fBinsLastAna[iburst]=entries;
2368 :
2369 0 : for (Int_t iDim=0; iDim<fHnDrift->GetNdimensions(); ++iDim) fHnDrift->GetAxis(iDim)->SetRange(0,0);
2370 : // if (iburst==0) FindLaserLayers();
2371 :
2372 : //reset laser tracks
2373 0 : ResetMeasured(arrMeasured);
2374 :
2375 : //find clusters and associate to the tracks
2376 0 : FindLocalMaxima(arrMeasured, timestamp, iburst);
2377 :
2378 : //calculate drift velocity
2379 0 : CalculateDV(arrIdeal,arrMeasured,iburst);
2380 :
2381 : //Dump information to file if requested
2382 0 : if (fStreamLevel>2){
2383 : //printf("make tree\n");
2384 : //laser track information
2385 :
2386 0 : for (Int_t itrack=0; itrack<338; ++itrack){
2387 0 : TObject *iltr=arrIdeal->UncheckedAt(itrack);
2388 0 : TObject *mltr=arrMeasured->UncheckedAt(itrack);
2389 0 : (*GetDebugStreamer()) << "tracks" <<
2390 0 : "run=" << fRunNumber <<
2391 0 : "time=" << timestamp <<
2392 0 : "burst="<< iburst <<
2393 0 : "iltr.=" << iltr <<
2394 0 : "mltr.=" << mltr <<
2395 : "\n";
2396 : }
2397 0 : }
2398 0 : }
2399 0 : if (fStreamLevel>0) GetDebugStreamer()->GetFile()->Write();
2400 0 : }
2401 :
2402 : //_____________________________________________________________________
2403 : Int_t AliTPCCalibCE::FindLaserTrackID(Int_t sector,Int_t row, const Double_t *peakpos,Double_t &mindist,
2404 : const Double_t *peakposloc, Int_t &itrackMin2)
2405 : {
2406 : /// Find the tracks, which are closest to the ideal tracks, from clusters closest to the ideal tracks
2407 :
2408 :
2409 0 : TObjArray *arr=AliTPCLaserTrack::GetTracks();
2410 0 : TVector3 vP(peakpos[0],peakpos[1],peakpos[2]);
2411 0 : TVector3 vDir;
2412 0 : TVector3 vSt;
2413 :
2414 : Int_t firstbeam=0;
2415 : Int_t lastbeam=336/2;
2416 0 : if ( (sector/18)%2 ) {
2417 : firstbeam=336/2;
2418 : lastbeam=336;
2419 0 : }
2420 :
2421 0 : mindist=1000000;
2422 : Int_t itrackMin=-1;
2423 0 : for (Int_t itrack=firstbeam; itrack<lastbeam; ++itrack){
2424 0 : AliTPCLaserTrack *ltr=(AliTPCLaserTrack*)arr->At(itrack); //get the track
2425 : // if (ltr->GetVecSec()->GetMatrixArray()[row]!=sector) continue;
2426 0 : vSt.SetXYZ(ltr->GetX(),ltr->GetY(),ltr->GetZ());
2427 0 : Double_t deltaZ=ltr->GetZ()-peakpos[2];
2428 0 : if (TMath::Abs(deltaZ)>40) continue;
2429 0 : vDir.SetMagThetaPhi(1,ltr->Theta(),TMath::ASin(ltr->GetSnp()));
2430 0 : vSt.RotateZ(ltr->GetAlpha());
2431 0 : vDir.RotateZ(ltr->GetAlpha());
2432 :
2433 0 : Double_t dist=(vDir.Cross(vSt-vP)).Mag()/vDir.Mag();
2434 :
2435 0 : if (dist<mindist){
2436 0 : mindist=dist;
2437 : itrackMin=itrack;
2438 0 : }
2439 :
2440 0 : }
2441 0 : itrackMin2=-1;
2442 : Float_t mindist2=10;
2443 0 : for (Int_t itrack=firstbeam; itrack<lastbeam; ++itrack){
2444 0 : AliTPCLaserTrack *ltr=(AliTPCLaserTrack*)arr->At(itrack); //get the track
2445 0 : if ((ltr->fVecSec->GetMatrixArray())[row]!=sector) continue;
2446 :
2447 0 : Double_t deltaZ=ltr->GetZ()-peakpos[2];
2448 0 : if (TMath::Abs(deltaZ)>40) continue;
2449 :
2450 0 : Double_t dist=TMath::Abs((ltr->fVecLY->GetMatrixArray())[row]-peakposloc[1]);
2451 0 : if (dist>1) continue;
2452 :
2453 0 : if (dist<mindist2){
2454 0 : mindist2=dist;
2455 0 : itrackMin2=itrack;
2456 0 : }
2457 0 : }
2458 0 : mindist=mindist2;
2459 0 : return itrackMin2;
2460 :
2461 0 : }
2462 :
2463 : //_____________________________________________________________________
2464 : Bool_t AliTPCCalibCE::IsEdgePad(Int_t sector, Int_t row, Int_t pad) const
2465 : {
2466 : /// return true if pad is on the edge of a row
2467 :
2468 : Int_t edge1 = 0;
2469 0 : if ( pad == edge1 ) return kTRUE;
2470 0 : Int_t edge2 = fROC->GetNPads(sector,row)-1;
2471 0 : if ( pad == edge2 ) return kTRUE;
2472 :
2473 0 : return kFALSE;
2474 0 : }
2475 :
2476 : //_____________________________________________________________________
2477 : TObjArray* AliTPCCalibCE::SetupMeasured()
2478 : {
2479 : /// setup array of measured laser tracks and CE
2480 :
2481 0 : TObjArray *arrIdeal = AliTPCLaserTrack::GetTracks();
2482 0 : TObjArray *arrMeasured = new TObjArray(338);
2483 0 : arrMeasured->SetOwner();
2484 0 : for(Int_t itrack=0;itrack<336;itrack++){
2485 0 : arrMeasured->AddAt(new AliTPCLaserTrack(*((AliTPCLaserTrack*)arrIdeal->At(itrack))),itrack);
2486 : }
2487 :
2488 : //"tracks" for CE
2489 0 : AliTPCLaserTrack *ltrce=new AliTPCLaserTrack;
2490 0 : ltrce->SetId(336);
2491 0 : ltrce->SetSide(0);
2492 0 : ltrce->fVecSec=new TVectorD(557568/2);
2493 0 : ltrce->fVecP2=new TVectorD(557568/2);
2494 0 : ltrce->fVecPhi=new TVectorD(557568/2);
2495 0 : ltrce->fVecGX=new TVectorD(557568/2);
2496 0 : ltrce->fVecGY=new TVectorD(557568/2);
2497 0 : ltrce->fVecGZ=new TVectorD(557568/2);
2498 0 : ltrce->fVecLX=new TVectorD(557568/2);
2499 0 : ltrce->fVecLY=new TVectorD(557568/2);
2500 0 : ltrce->fVecLZ=new TVectorD(557568/2);
2501 :
2502 0 : arrMeasured->AddAt(ltrce,336); //CE A-Side
2503 :
2504 0 : ltrce=new AliTPCLaserTrack;
2505 0 : ltrce->SetId(337);
2506 0 : ltrce->SetSide(1);
2507 0 : ltrce->fVecSec=new TVectorD(557568/2);
2508 0 : ltrce->fVecP2=new TVectorD(557568/2);
2509 0 : ltrce->fVecPhi=new TVectorD(557568/2);
2510 0 : ltrce->fVecGX=new TVectorD(557568/2);
2511 0 : ltrce->fVecGY=new TVectorD(557568/2);
2512 0 : ltrce->fVecGZ=new TVectorD(557568/2);
2513 0 : ltrce->fVecLX=new TVectorD(557568/2);
2514 0 : ltrce->fVecLY=new TVectorD(557568/2);
2515 0 : ltrce->fVecLZ=new TVectorD(557568/2);
2516 0 : arrMeasured->AddAt(ltrce,337); //CE C-Side
2517 :
2518 0 : return arrMeasured;
2519 0 : }
2520 :
2521 : //_____________________________________________________________________
2522 : void AliTPCCalibCE::ResetMeasured(TObjArray * const arr)
2523 : {
2524 : /// reset array of measured laser tracks and CE
2525 :
2526 0 : for(Int_t itrack=0;itrack<338;itrack++){
2527 0 : AliTPCLaserTrack *ltr=(AliTPCLaserTrack*)arr->UncheckedAt(itrack);
2528 0 : ltr->fVecSec->Zero();
2529 0 : ltr->fVecP2->Zero();
2530 0 : ltr->fVecPhi->Zero();
2531 0 : ltr->fVecGX->Zero();
2532 0 : ltr->fVecGY->Zero();
2533 0 : ltr->fVecGZ->Zero();
2534 0 : ltr->fVecLX->Zero();
2535 0 : ltr->fVecLY->Zero();
2536 0 : ltr->fVecLZ->Zero();
2537 : }
2538 0 : }
2539 :
2540 : //_____________________________________________________________________
2541 : void AliTPCCalibCE::AddCEtoIdeal(TObjArray *arr)
2542 : {
2543 : /// Add ideal CE positions to the ideal track data
2544 :
2545 0 : arr->Expand(338);
2546 : //"tracks" for CE
2547 0 : AliTPCLaserTrack *ltrceA=new AliTPCLaserTrack;
2548 0 : ltrceA->SetId(336);
2549 0 : ltrceA->SetSide(0);
2550 0 : ltrceA->fVecSec=new TVectorD(557568/2);
2551 0 : ltrceA->fVecP2=new TVectorD(557568/2);
2552 0 : ltrceA->fVecPhi=new TVectorD(557568/2);
2553 0 : ltrceA->fVecGX=new TVectorD(557568/2);
2554 0 : ltrceA->fVecGY=new TVectorD(557568/2);
2555 0 : ltrceA->fVecGZ=new TVectorD(557568/2);
2556 0 : ltrceA->fVecLX=new TVectorD(557568/2);
2557 0 : ltrceA->fVecLY=new TVectorD(557568/2);
2558 0 : ltrceA->fVecLZ=new TVectorD(557568/2);
2559 0 : arr->AddAt(ltrceA,336); //CE A-Side
2560 :
2561 0 : AliTPCLaserTrack *ltrceC=new AliTPCLaserTrack;
2562 0 : ltrceC->SetId(337);
2563 0 : ltrceC->SetSide(1);
2564 0 : ltrceC->fVecSec=new TVectorD(557568/2);
2565 0 : ltrceC->fVecP2=new TVectorD(557568/2);
2566 0 : ltrceC->fVecPhi=new TVectorD(557568/2);
2567 0 : ltrceC->fVecGX=new TVectorD(557568/2);
2568 0 : ltrceC->fVecGY=new TVectorD(557568/2);
2569 0 : ltrceC->fVecGZ=new TVectorD(557568/2);
2570 0 : ltrceC->fVecLX=new TVectorD(557568/2);
2571 0 : ltrceC->fVecLY=new TVectorD(557568/2);
2572 0 : ltrceC->fVecLZ=new TVectorD(557568/2);
2573 0 : arr->AddAt(ltrceC,337); //CE C-Side
2574 :
2575 : //Calculate ideal positoins
2576 0 : Float_t gxyz[3];
2577 0 : Float_t lxyz[3];
2578 : Int_t channelSideA=0;
2579 : Int_t channelSideC=0;
2580 : Int_t channelSide=0;
2581 : AliTPCLaserTrack *ltrce=0x0;
2582 :
2583 0 : for (Int_t isector=0; isector<72; ++isector){
2584 0 : Int_t side=((isector/18)%2);
2585 0 : for (UInt_t irow=0;irow<fROC->GetNRows(isector);++irow){
2586 0 : for (UInt_t ipad=0;ipad<fROC->GetNPads(isector,irow);++ipad){
2587 0 : fROC->GetPositionGlobal(isector,irow,ipad,gxyz);
2588 0 : fROC->GetPositionLocal(isector,irow,ipad,lxyz);
2589 0 : if (side==0) {
2590 : ltrce=ltrceA;
2591 : channelSide=channelSideA;
2592 0 : } else {
2593 : ltrce=ltrceC;
2594 : channelSide=channelSideC;
2595 : }
2596 :
2597 0 : ltrce->fVecSec->GetMatrixArray()[channelSide]=isector;
2598 0 : ltrce->fVecP2->GetMatrixArray()[channelSide]=0;
2599 0 : ltrce->fVecPhi->GetMatrixArray()[channelSide]=0;
2600 0 : ltrce->fVecGX->GetMatrixArray()[channelSide]=gxyz[0];
2601 0 : ltrce->fVecGY->GetMatrixArray()[channelSide]=gxyz[1];
2602 : // ltrce->fVecGZ->GetMatrixArray()[channelSide]=-1;
2603 0 : ltrce->fVecLX->GetMatrixArray()[channelSide]=lxyz[0];
2604 0 : ltrce->fVecLY->GetMatrixArray()[channelSide]=lxyz[1];
2605 : // ltrce->fVecLZ->GetMatrixArray()[channelSide]=-1;
2606 :
2607 0 : if (side==0){
2608 0 : ltrce->fVecGZ->GetMatrixArray()[channelSide]=-0.335;
2609 0 : ltrce->fVecLZ->GetMatrixArray()[channelSide]=-0.335;
2610 0 : ++channelSideA;
2611 0 : }
2612 : else {
2613 0 : ltrce->fVecGZ->GetMatrixArray()[channelSide]=0.15;
2614 0 : ltrce->fVecLZ->GetMatrixArray()[channelSide]=0.15;
2615 0 : ++channelSideC;
2616 : }
2617 : }
2618 : }
2619 : }
2620 :
2621 :
2622 0 : }
2623 :
2624 : //_____________________________________________________________________
2625 : void AliTPCCalibCE::CalculateDV(TObjArray * const arrIdeal, TObjArray * const arrMeasured, Int_t burst)
2626 : {
2627 : /// calculate the drift velocity from the reconstructed clusters associated
2628 : /// to the ideal laser tracks
2629 : /// use two different fit scenarios: Separate fit for A- and C-Side
2630 : /// Common fit for A- and C-Side
2631 :
2632 0 : if (!fArrFitGraphs){
2633 0 : fArrFitGraphs=new TObjArray;
2634 0 : }
2635 :
2636 : // static TLinearFitter fdriftA(5,"hyp4");
2637 : // static TLinearFitter fdriftC(5,"hyp4");
2638 : // static TLinearFitter fdriftAC(6,"hyp5");
2639 0 : Double_t timestamp=fTimeBursts[burst];
2640 :
2641 0 : static TLinearFitter fdriftA(4,"hyp3");
2642 0 : static TLinearFitter fdriftC(4,"hyp3");
2643 0 : static TLinearFitter fdriftAC(5,"hyp4");
2644 0 : TVectorD fitA(7),fitC(7),fitAC(8); //fit values+chi2+npoints
2645 :
2646 : Float_t chi2A = 10;
2647 : Float_t chi2C = 10;
2648 : Float_t chi2AC = 10;
2649 : Int_t npointsA=0;
2650 : Int_t npointsC=0;
2651 : Int_t npointsAC=0;
2652 :
2653 0 : Double_t minres[3]={20.,1,0.8};
2654 : //----
2655 0 : for(Int_t i=0;i<3;i++){
2656 :
2657 0 : fdriftA.ClearPoints();
2658 0 : fdriftC.ClearPoints();
2659 0 : fdriftAC.ClearPoints();
2660 :
2661 : chi2A = 10;
2662 : chi2C = 10;
2663 : chi2AC = 10;
2664 : npointsA=0;
2665 : npointsC=0;
2666 : npointsAC=0;
2667 :
2668 0 : for (Int_t itrack=0; itrack<338; ++itrack){
2669 0 : AliTPCLaserTrack *iltr=(AliTPCLaserTrack*)arrIdeal->UncheckedAt(itrack);
2670 0 : AliTPCLaserTrack *mltr=(AliTPCLaserTrack*)arrMeasured->UncheckedAt(itrack);
2671 :
2672 : //-- Exclude the tracks which has the biggest inclanation angle
2673 0 : if ((itrack%7==0||itrack%7==6)&&itrack<336) continue;
2674 : Int_t clustercounter=0;
2675 : Int_t indexMax=159;
2676 :
2677 : //-- exclude the low intensity tracks
2678 :
2679 0 : for (Int_t index=0; index<indexMax; ++index){
2680 :
2681 0 : Double_t mGx=mltr->fVecGX->GetMatrixArray()[index];
2682 0 : Double_t mGy=mltr->fVecGY->GetMatrixArray()[index];
2683 0 : Double_t mGz=mltr->fVecGZ->GetMatrixArray()[index];
2684 :
2685 0 : if (TMath::Abs(mGz)<1e-20 && TMath::Abs(mGy)<1e-20 && TMath::Abs(mGx)<1e-20) clustercounter++;
2686 : }
2687 0 : if (clustercounter>130&&itrack<336) continue; // don't accept tracks with <= 159-130=29 clusters
2688 : clustercounter=0;
2689 :
2690 :
2691 : //-- drift length
2692 0 : Double_t zlength = (iltr->GetSide()==0)? fParam->GetZLength(36): fParam->GetZLength(71);
2693 :
2694 0 : if (itrack>335) indexMax=557568/2;
2695 0 : for (Int_t index=0; index<indexMax; ++index){
2696 0 : Double_t iGx=iltr->fVecGX->GetMatrixArray()[index];
2697 0 : Double_t iGy=iltr->fVecGY->GetMatrixArray()[index];
2698 0 : Double_t iGz=iltr->fVecGZ->GetMatrixArray()[index];
2699 0 : Double_t iR=TMath::Sqrt(iGx*iGx+iGy*iGy);
2700 :
2701 0 : Double_t mGx=mltr->fVecGX->GetMatrixArray()[index];
2702 0 : Double_t mGy=mltr->fVecGY->GetMatrixArray()[index];
2703 0 : Double_t mGz=mltr->fVecGZ->GetMatrixArray()[index];
2704 0 : Double_t mR=TMath::Sqrt(mGx*mGx+mGy*mGy);
2705 :
2706 : //cut if no track info available
2707 0 : if (iltr->GetBundle()==0) continue;
2708 0 : if (iR<133||mR<133) continue;
2709 0 : if(TMath::Abs(mltr->fVecP2->GetMatrixArray()[index])>minres[i]) continue;
2710 :
2711 0 : Double_t ldrift = (iltr->GetSide()==0)?zlength-iGz:iGz+zlength;
2712 0 : Double_t mdrift = (iltr->GetSide()==0)?zlength-mGz:mGz+zlength;
2713 :
2714 : //Double_t xxx[4] = {ldrift,iGy*ldrift/(zlength*250.), 250.-mR, iltr->fVecSec->GetMatrixArray()[index]>35};
2715 0 : Double_t xxx[3] = {ldrift,iGy*ldrift/(zlength*250.), 250.-mR};
2716 :
2717 0 : if (iltr->GetSide()==0){
2718 0 : fdriftA.AddPoint(xxx,mdrift,1);
2719 : }else{
2720 0 : fdriftC.AddPoint(xxx,mdrift,1);
2721 : }
2722 : // Double_t xxx2[4] = { ldrift,iGy*ldrift/(zlength*250.), 250.-mR, iltr->fVecSec->GetMatrixArray()[index]>35, iltr->GetSide()};
2723 0 : Double_t xxx2[4] = { ldrift,iGy*ldrift/(zlength*250.), 250.-mR, static_cast<Double_t>(iltr->GetSide())};
2724 0 : fdriftAC.AddPoint(xxx2,mdrift,1);
2725 :
2726 0 : }//end index loop
2727 0 : }//end laser track loop
2728 :
2729 : //perform fit
2730 0 : fdriftA.Eval();
2731 0 : fdriftC.Eval();
2732 0 : fdriftAC.Eval();
2733 :
2734 :
2735 :
2736 : //get fit values
2737 0 : fdriftA.GetParameters(fitA);
2738 0 : fdriftC.GetParameters(fitC);
2739 0 : fdriftAC.GetParameters(fitAC);
2740 :
2741 : //Parameters: 0 linear offset
2742 : // 1 mean drift velocity correction factor
2743 : // 2 relative global y gradient
2744 : // 3 radial deformation
2745 : // 4 IROC/OROC offset
2746 :
2747 : // FindResiduals(arrMeasured,arrIdeal,fitA,fitC);
2748 :
2749 0 : for (Int_t itrack=0; itrack<338; ++itrack){
2750 0 : AliTPCLaserTrack *iltr=(AliTPCLaserTrack*)arrIdeal->UncheckedAt(itrack);
2751 0 : AliTPCLaserTrack *mltr=(AliTPCLaserTrack*)arrMeasured->UncheckedAt(itrack);
2752 :
2753 : //-- Exclude the tracks which has the biggest inclanation angle
2754 0 : if ((itrack%7==0||itrack%7==6)&&itrack<336) continue;
2755 : Int_t clustercounter=0;
2756 : Int_t indexMax=159;
2757 :
2758 : //-- exclude the low intensity tracks
2759 :
2760 0 : for (Int_t index=0; index<indexMax; ++index){
2761 0 : Double_t mGx=mltr->fVecGX->GetMatrixArray()[index];
2762 0 : Double_t mGy=mltr->fVecGY->GetMatrixArray()[index];
2763 0 : Double_t mGz=mltr->fVecGZ->GetMatrixArray()[index];
2764 0 : if (TMath::Abs(mGz)<1e-20 && TMath::Abs(mGy)<1e-20 && TMath::Abs(mGx)<1e-20) clustercounter++;
2765 : }
2766 0 : if (clustercounter>130&&itrack<336) continue; // don't accept tracks with <= 159-130=29 clusters
2767 : clustercounter=0;
2768 :
2769 : //-- drift length
2770 0 : Double_t zlength = (iltr->GetSide()==0)? fParam->GetZLength(36): fParam->GetZLength(71);
2771 :
2772 0 : if (itrack>335) indexMax=557568/2;
2773 0 : for (Int_t index=0; index<indexMax; ++index){
2774 0 : Double_t iGx=iltr->fVecGX->GetMatrixArray()[index];
2775 0 : Double_t iGy=iltr->fVecGY->GetMatrixArray()[index];
2776 0 : Double_t iGz=iltr->fVecGZ->GetMatrixArray()[index];
2777 0 : Double_t iR=TMath::Sqrt(iGx*iGx+iGy*iGy);
2778 :
2779 0 : Double_t mGx=mltr->fVecGX->GetMatrixArray()[index];
2780 0 : Double_t mGy=mltr->fVecGY->GetMatrixArray()[index];
2781 0 : Double_t mGz=mltr->fVecGZ->GetMatrixArray()[index];
2782 0 : Double_t mR=TMath::Sqrt(mGx*mGx+mGy*mGy);
2783 :
2784 : //cut if no track info available
2785 0 : if (iR<60||mR<60) continue;
2786 :
2787 0 : Double_t ldrift = (iltr->GetSide()==0)?zlength-iGz:iGz+zlength;
2788 0 : Double_t mdrift = (iltr->GetSide()==0)?zlength-mGz:mGz+zlength;
2789 :
2790 : TVectorD *v=&fitA;
2791 0 : if (iltr->GetSide()==1) v=&fitC;
2792 : // Double_t iCorr=(*v)[0]+(*v)[1]*ldrift+(*v)[2]*iGy*ldrift/(zlength*250.)+(*v)[3]*(250.-mR)+(*v)[4]*( iltr->fVecSec->GetMatrixArray()[index]>35);
2793 0 : Double_t iCorr=(*v)[0]+(*v)[1]*ldrift+(*v)[2]*iGy*ldrift/(zlength*250.)+(*v)[3]*(250.-mR);
2794 :
2795 0 : mltr->fVecP2->GetMatrixArray()[index]=mdrift-iCorr;
2796 :
2797 0 : }
2798 0 : }
2799 :
2800 0 : fitA.ResizeTo(7);
2801 0 : fitC.ResizeTo(7);
2802 0 : fitAC.ResizeTo(8);
2803 :
2804 : //set statistics values
2805 :
2806 0 : npointsA= fdriftA.GetNpoints();
2807 0 : if (npointsA>0) chi2A = fdriftA.GetChisquare()/fdriftA.GetNpoints();
2808 0 : fitA[5]=npointsA;
2809 0 : fitA[6]=chi2A;
2810 :
2811 0 : npointsC= fdriftC.GetNpoints();
2812 0 : if (npointsC>0) chi2C = fdriftC.GetChisquare()/fdriftC.GetNpoints();
2813 0 : fitC[5]=npointsC;
2814 0 : fitC[6]=chi2C;
2815 :
2816 0 : npointsAC= fdriftAC.GetNpoints();
2817 0 : if (npointsAC>0) chi2AC = fdriftAC.GetChisquare()/fdriftAC.GetNpoints();
2818 0 : fitAC[5]=npointsAC;
2819 0 : fitAC[6]=chi2AC;
2820 :
2821 0 : if (fStreamLevel>2){
2822 : //laser track information
2823 0 : (*GetDebugStreamer()) << "DriftV" <<
2824 0 : "iter=" << i <<
2825 0 : "run=" << fRunNumber <<
2826 0 : "time=" << timestamp <<
2827 0 : "fitA.=" << &fitA <<
2828 0 : "fitC.=" << &fitC <<
2829 0 : "fitAC.=" << &fitAC <<
2830 : "\n";
2831 :
2832 :
2833 : }
2834 :
2835 : }
2836 : //-----
2837 :
2838 :
2839 : //Parameters: 0 linear offset (global)
2840 : // 1 mean drift velocity correction factor
2841 : // 2 relative global y gradient
2842 : // 3 radial deformation
2843 : // 4 IROC/OROC offset
2844 : // 5 linear offset relative A-C
2845 :
2846 : //get graphs
2847 0 : TGraphErrors *grA[7];
2848 0 : TGraphErrors *grC[7];
2849 0 : TGraphErrors *grAC[8];
2850 0 : TString names("GRAPH_MEAN_DELAY_LASER_ALL_;GRAPH_MEAN_DRIFT_LASER_ALL_;GRAPH_MEAN_GLOBALYGRADIENT_LASER_ALL_;GRAPH_MEAN_RGRADIENT_LASER_ALL_;GRAPH_MEAN_IROCOROCOFFSET_LASER_ALL_;GRAPH_MEAN_NPOINTS_LASER_ALL_;GRAPH_MEAN_CHI2_LASER_ALL_");
2851 0 : TString namesAC("GRAPH_MEAN_DELAY_LASER_ALL_;GRAPH_MEAN_DRIFT_LASER_ALL_;GRAPH_MEAN_GLOBALYGRADIENT_LASER_ALL_;GRAPH_MEAN_RGRADIENT_LASER_ALL_;GRAPH_MEAN_IROCOROCOFFSET_LASER_ALL_;GRAPH_MEAN_NPOINTS_LASER_ALL_;GRAPH_MEAN_CHI2_LASER_ALL_;GRAPH_MEAN_DELAYC_LASER_ALL_");
2852 :
2853 0 : TObjArray *arrNames=names.Tokenize(";");
2854 0 : TObjArray *arrNamesAC=namesAC.Tokenize(";");
2855 :
2856 : //A-Side graphs
2857 0 : for (Int_t i=0; i<7; ++i){
2858 0 : TString grName=arrNames->UncheckedAt(i)->GetName();
2859 0 : grName+="A";
2860 0 : grA[i]=(TGraphErrors*)fArrFitGraphs->FindObject(grName.Data());
2861 0 : if (!grA[i]){
2862 0 : grA[i]=new TGraphErrors;
2863 0 : grA[i]->SetName(grName.Data());
2864 0 : grA[i]->SetTitle(grName.ReplaceAll("_"," ").Data());
2865 0 : fArrFitGraphs->Add(grA[i]);
2866 : }
2867 : // Int_t ipoint=grA[i]->GetN();
2868 : Int_t ipoint=burst;
2869 0 : grA[i]->SetPoint(ipoint,timestamp,fitA(i));
2870 0 : grA[i]->SetPointError(ipoint,60,.0001);
2871 0 : if (i<4) grA[i]->SetPointError(ipoint,60,fdriftA.GetCovarianceMatrixElement(i,i));
2872 0 : }
2873 :
2874 : //C-Side graphs
2875 0 : for (Int_t i=0; i<7; ++i){
2876 0 : TString grName=arrNames->UncheckedAt(i)->GetName();
2877 0 : grName+="C";
2878 0 : grC[i]=(TGraphErrors*)fArrFitGraphs->FindObject(grName.Data());
2879 0 : if (!grC[i]){
2880 0 : grC[i]=new TGraphErrors;
2881 0 : grC[i]->SetName(grName.Data());
2882 0 : grC[i]->SetTitle(grName.ReplaceAll("_"," ").Data());
2883 0 : fArrFitGraphs->Add(grC[i]);
2884 : }
2885 : // Int_t ipoint=grC[i]->GetN();
2886 : Int_t ipoint=burst;
2887 0 : grC[i]->SetPoint(ipoint,timestamp,fitC(i));
2888 0 : grC[i]->SetPointError(ipoint,60,.0001);
2889 0 : if (i<4) grC[i]->SetPointError(ipoint,60,fdriftC.GetCovarianceMatrixElement(i,i));
2890 0 : }
2891 :
2892 : //AC-Side graphs
2893 0 : for (Int_t i=0; i<8; ++i){
2894 0 : TString grName=arrNamesAC->UncheckedAt(i)->GetName();
2895 0 : grName+="AC";
2896 0 : grAC[i]=(TGraphErrors*)fArrFitGraphs->FindObject(grName.Data());
2897 0 : if (!grAC[i]){
2898 0 : grAC[i]=new TGraphErrors;
2899 0 : grAC[i]->SetName(grName.Data());
2900 0 : grAC[i]->SetTitle(grName.ReplaceAll("_"," ").Data());
2901 0 : fArrFitGraphs->Add(grAC[i]);
2902 : }
2903 : // Int_t ipoint=grAC[i]->GetN();
2904 : Int_t ipoint=burst;
2905 0 : grAC[i]->SetPoint(ipoint,timestamp,fitAC(i));
2906 0 : grAC[i]->SetPointError(ipoint,60,.0001);
2907 0 : if (i<5) grAC[i]->SetPointError(ipoint,60,fdriftAC.GetCovarianceMatrixElement(i,i));
2908 0 : }
2909 :
2910 0 : if (fDebugLevel>10){
2911 0 : printf("A side fit parameters:\n");
2912 0 : fitA.Print();
2913 0 : printf("\nC side fit parameters:\n");
2914 0 : fitC.Print();
2915 0 : printf("\nAC side fit parameters:\n");
2916 0 : fitAC.Print();
2917 : }
2918 0 : delete arrNames;
2919 0 : delete arrNamesAC;
2920 0 : }
2921 :
2922 : //_____________________________________________________________________
2923 : Double_t AliTPCCalibCE::SetBurstHnDrift()
2924 : {
2925 : /// Create a new THnSparse for the current burst
2926 : /// return the time of the current burst
2927 :
2928 : Int_t i=0;
2929 0 : for(i=0; i<fTimeBursts.GetNrows(); ++i){
2930 0 : if(fTimeBursts.GetMatrixArray()[i]<1.e-20) break;
2931 0 : if(TMath::Abs(fTimeBursts.GetMatrixArray()[i]-fTimeStamp)<300){
2932 0 : fHnDrift=(THnSparseI*)fArrHnDrift.UncheckedAt(i);
2933 0 : return fTimeBursts(i);
2934 : }
2935 : }
2936 :
2937 0 : CreateDVhist();
2938 0 : fArrHnDrift.AddAt(fHnDrift,i);
2939 0 : fTimeBursts.GetMatrixArray()[i]=fTimeStamp;
2940 0 : for (i=0;i<14;++i){
2941 0 : fPeaks[i]=0;
2942 0 : fPeakWidths[i]=0;
2943 : }
2944 0 : fEventInBunch=0;
2945 0 : return fTimeStamp;
2946 0 : }
2947 :
2948 : //_____________________________________________________________________
2949 : void AliTPCCalibCE::DumpToFile(const Char_t *filename, const Char_t *dir, Bool_t /*append*/)
2950 : {
2951 : /// Write class to file
2952 : /// option can be specified in the dir option:
2953 : /// options:
2954 : /// name=<objname>: the name of the calibration object in file will be <objname>
2955 : /// type=<type>: the saving type:
2956 : /// 0 - write the complte object
2957 : /// 1 - Store the histogram arrays separately to make the streamed object smaller, Analyse to be called
2958 : /// 2 - like 2, but in addition delete objects that will most probably not be used for calibration
2959 : /// 3 - store only calibration output, don't store the reference histograms
2960 : /// and THnSparse (requires Analyse called before)
2961 : ///
2962 : /// NOTE: to read the object back, the ReadFromFile function should be used
2963 :
2964 0 : TString sDir(dir);
2965 0 : TString objName=GetName();
2966 : Int_t type=0;
2967 :
2968 : //get options
2969 0 : TObjArray *arr=sDir.Tokenize(",");
2970 0 : TIter next(arr);
2971 : TObjString *s;
2972 0 : while ( (s=(TObjString*)next()) ){
2973 0 : TString optString=s->GetString();
2974 0 : optString.Remove(TString::kBoth,' ');
2975 0 : if (optString.BeginsWith("name=")){
2976 0 : objName=optString.ReplaceAll("name=","");
2977 : }
2978 0 : if (optString.BeginsWith("type=")){
2979 0 : optString.ReplaceAll("type=","");
2980 0 : type=optString.Atoi();
2981 0 : }
2982 0 : }
2983 0 : delete arr;
2984 :
2985 0 : if ( type==4 ){
2986 : // only for the new algorithm
2987 0 : AliTPCCalibCE ce;
2988 0 : ce.fArrFitGraphs=fArrFitGraphs;
2989 0 : ce.fNevents=fNevents;
2990 0 : ce.fTimeBursts.ResizeTo(fTimeBursts.GetNrows());
2991 0 : ce.fTimeBursts=fTimeBursts;
2992 0 : ce.fProcessNew=kTRUE;
2993 0 : TFile f(filename,"recreate");
2994 0 : ce.Write(objName.Data());
2995 0 : fArrHnDrift.Write("arrHnDrift",TObject::kSingleKey);
2996 0 : f.Close();
2997 0 : ce.fArrFitGraphs=0x0;
2998 : return;
2999 0 : }
3000 :
3001 :
3002 0 : if (type==1||type==2) {
3003 : //delete most probably not needed stuff
3004 : //This requires Analyse to be called after reading the object from file
3005 0 : fCalRocArrayT0.Delete();
3006 0 : fCalRocArrayT0Err.Delete();
3007 0 : fCalRocArrayQ.Delete();
3008 0 : fCalRocArrayRMS.Delete();
3009 0 : fCalRocArrayOutliers.Delete();
3010 : }
3011 0 : if (type==2||type==3){
3012 0 : fParamArrayEventPol1.Delete();
3013 0 : fParamArrayEventPol2.Delete();
3014 : }
3015 :
3016 0 : TObjArray histoQArray(72);
3017 0 : TObjArray histoT0Array(72);
3018 0 : TObjArray histoRMSArray(72);
3019 0 : TObjArray arrHnDrift(fArrHnDrift.GetEntries());
3020 :
3021 : //save all large 2D histograms in separte pointers
3022 : //to have a smaller memory print when saving the object
3023 0 : if (type==1||type==2||type==3){
3024 0 : for (Int_t i=0; i<72; ++i){
3025 0 : histoQArray.AddAt(fHistoQArray.UncheckedAt(i),i);
3026 0 : histoT0Array.AddAt(fHistoT0Array.UncheckedAt(i),i);
3027 0 : histoRMSArray.AddAt(fHistoRMSArray.UncheckedAt(i),i);
3028 : }
3029 0 : fHistoQArray.SetOwner(kFALSE);
3030 0 : fHistoT0Array.SetOwner(kFALSE);
3031 0 : fHistoRMSArray.SetOwner(kFALSE);
3032 0 : fHistoQArray.Clear();
3033 0 : fHistoT0Array.Clear();
3034 0 : fHistoRMSArray.Clear();
3035 :
3036 0 : for (Int_t i=0;i<fArrHnDrift.GetEntries();++i){
3037 0 : arrHnDrift.AddAt(fArrHnDrift.UncheckedAt(i),i);
3038 : }
3039 0 : fArrHnDrift.SetOwner(kFALSE);
3040 0 : fArrHnDrift.Clear();
3041 : }
3042 :
3043 :
3044 0 : TDirectory *backup = gDirectory;
3045 :
3046 0 : TFile f(filename,"recreate");
3047 0 : Write(objName.Data());
3048 0 : if (type==1||type==2) {
3049 0 : histoQArray.Write("histoQArray",TObject::kSingleKey);
3050 0 : histoT0Array.Write("histoT0Array",TObject::kSingleKey);
3051 0 : histoRMSArray.Write("histoRMSArray",TObject::kSingleKey);
3052 0 : arrHnDrift.Write("arrHnDrift",TObject::kSingleKey);
3053 : }
3054 :
3055 0 : f.Save();
3056 0 : f.Close();
3057 :
3058 : //move histograms back to the object
3059 0 : if (type==1||type==2){
3060 0 : for (Int_t i=0; i<72; ++i){
3061 0 : fHistoQArray.AddAt(histoQArray.UncheckedAt(i),i);
3062 0 : fHistoT0Array.AddAt(histoT0Array.UncheckedAt(i),i);
3063 0 : fHistoRMSArray.AddAt(histoRMSArray.UncheckedAt(i),i);
3064 : }
3065 0 : fHistoQArray.SetOwner(kTRUE);
3066 0 : fHistoT0Array.SetOwner(kTRUE);
3067 0 : fHistoRMSArray.SetOwner(kTRUE);
3068 :
3069 0 : for (Int_t i=0;i<arrHnDrift.GetEntries();++i){
3070 0 : fArrHnDrift.AddAt(arrHnDrift.UncheckedAt(i),i);
3071 : }
3072 0 : fArrHnDrift.SetOwner(kTRUE);
3073 : }
3074 :
3075 0 : if ( backup ) backup->cd();
3076 0 : }
3077 : //_____________________________________________________________________
3078 : AliTPCCalibCE* AliTPCCalibCE::ReadFromFile(const Char_t *filename)
3079 : {
3080 : /// Read object from file
3081 : /// Handle properly if the histogram arrays were stored separately
3082 : /// call Analyse to make sure to have the calibration relevant information in the object
3083 :
3084 0 : TFile f(filename);
3085 0 : if (!f.IsOpen() || f.IsZombie() ) return 0x0;
3086 0 : TList *l=f.GetListOfKeys();
3087 0 : TIter next(l);
3088 : TKey *key=0x0;
3089 : TObject *o=0x0;
3090 :
3091 : AliTPCCalibCE *ce=0x0;
3092 : TObjArray *histoQArray=0x0;
3093 : TObjArray *histoT0Array=0x0;
3094 : TObjArray *histoRMSArray=0x0;
3095 : TObjArray *arrHnDrift=0x0;
3096 :
3097 0 : while ( (key=(TKey*)next()) ){
3098 0 : o=key->ReadObj();
3099 0 : if ( o->IsA()==AliTPCCalibCE::Class() ){
3100 0 : ce=(AliTPCCalibCE*)o;
3101 0 : } else if ( o->IsA()==TObjArray::Class() ){
3102 0 : TString name=key->GetName();
3103 0 : if ( name=="histoQArray") histoQArray=(TObjArray*)o;
3104 0 : if ( name=="histoT0Array") histoT0Array=(TObjArray*)o;
3105 0 : if ( name=="histoRMSArray") histoRMSArray=(TObjArray*)o;
3106 0 : if ( name=="arrHnDrift") arrHnDrift=(TObjArray*)o;
3107 0 : }
3108 : }
3109 :
3110 0 : if (ce){
3111 : //move histograms back to the object
3112 : TH1* hist=0x0;
3113 0 : if (histoQArray){
3114 0 : for (Int_t i=0; i<72; ++i){
3115 0 : hist=(TH1*)histoQArray->UncheckedAt(i);
3116 0 : if (hist) hist->SetDirectory(0x0);
3117 0 : ce->fHistoQArray.AddAt(hist,i);
3118 : }
3119 0 : ce->fHistoQArray.SetOwner(kTRUE);
3120 : }
3121 :
3122 0 : if (histoT0Array) {
3123 0 : for (Int_t i=0; i<72; ++i){
3124 0 : hist=(TH1*)histoT0Array->UncheckedAt(i);
3125 0 : if (hist) hist->SetDirectory(0x0);
3126 0 : ce->fHistoT0Array.AddAt(hist,i);
3127 : }
3128 0 : ce->fHistoT0Array.SetOwner(kTRUE);
3129 : }
3130 :
3131 0 : if (histoRMSArray){
3132 0 : for (Int_t i=0; i<72; ++i){
3133 0 : hist=(TH1*)histoRMSArray->UncheckedAt(i);
3134 0 : if (hist) hist->SetDirectory(0x0);
3135 0 : ce->fHistoRMSArray.AddAt(hist,i);
3136 : }
3137 0 : ce->fHistoRMSArray.SetOwner(kTRUE);
3138 : }
3139 :
3140 0 : if (arrHnDrift){
3141 0 : for (Int_t i=0; i<arrHnDrift->GetEntries(); ++i){
3142 0 : THnSparseI *hSparse=(THnSparseI*)arrHnDrift->UncheckedAt(i);
3143 0 : ce->fArrHnDrift.AddAt(hSparse,i);
3144 : }
3145 0 : }
3146 :
3147 0 : ce->Analyse();
3148 0 : }
3149 0 : f.Close();
3150 :
3151 : return ce;
3152 0 : }
|