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 AliTPCCalibPulser
17 : /// \brief Implementation of the TPC pulser calibration
18 : ///
19 : /// \author Jens Wiechula, Marian Ivanov J.Wiechula@gsi.de, Marian.Ivanov@cern.ch
20 : ///
21 : /// Class Description
22 : /// -----------------
23 : ///
24 : /// The AliTPCCalibPulser class is used to get calibration data concerning the FEE using
25 : /// runs performed with the calibration pulser.
26 : ///
27 : /// The information retrieved is
28 : /// - Time0 differences
29 : /// - Signal width differences
30 : /// - Amplification variations
31 : ///
32 : /// the seen differences arise from the manufacturing tolerances of the PASAs and are very small within
33 : /// one chip and somewhat large between different chips.
34 : ///
35 : /// Histograms:
36 : /// For each ROC three TH2S histos 'Reference Histograms' (ROC channel vs. [Time0, signal width, Q sum]) is created when
37 : /// it is filled for the first time (GetHisto[T0,RMS,Q](ROC,kTRUE)). The histos are stored in the
38 : /// TObjArrays fHistoT0Array, fHistoRMSArray and fHistoQArray.
39 : ///
40 : ///
41 : /// Working principle:
42 : /// ------------------
43 : /// Raw calibration pulser data is processed by calling one of the ProcessEvent(...) functions
44 : /// (see below). These in the end call the Update(...) function.
45 : ///
46 : /// - the Update(...) function:
47 : /// In this function the array fPadSignal is filled with the adc signals between the specified range
48 : /// fFirstTimeBin and fLastTimeBin for the current pad.
49 : /// before going to the next pad the ProcessPad() function is called, which analyses the data for one pad
50 : /// stored in fPadSignal.
51 : ///
52 : /// - the ProcessPad() function:
53 : /// Find Pedestal and Noise information
54 : /// - use database information which has to be set by calling
55 : /// SetPedestalDatabase(AliTPCCalPad *pedestalTPC, AliTPCCalPad *padNoiseTPC)
56 : /// - if no information from the pedestal data base
57 : /// is available the informaion is calculated on the fly ( see FindPedestal() function )
58 : ///
59 : /// Find the Pulser signal information
60 : /// - calculate mean = T0, RMS = signal width and Q sum in a range of -2+7 timebins around Q max
61 : /// the Q sum is scaled by pad area
62 : /// (see FindPulserSignal(...) function)
63 : ///
64 : /// Fill a temprary array for the T0 information (GetPadTimesEvent(fCurrentSector,kTRUE)) (why see below)
65 : /// Fill the Q sum and RMS values in the histograms (GetHisto[RMS,Q](ROC,kTRUE)),
66 : ///
67 : /// At the end of each event the EndEvent() function is called
68 : ///
69 : /// - the EndEvent() function:
70 : /// calculate the mean T0 for each ROC and fill the Time0 histogram with Time0-<Time0 for ROC>
71 : /// This is done to overcome syncronisation problems between the trigger and the fec clock.
72 : ///
73 : /// After accumulating the desired statistics the Analyse() function has to be called.
74 : /// - the Analyse() function
75 : /// Whithin this function the mean values of T0, RMS, Q are calculated for each pad, using
76 : /// the AliMathBase::GetCOG(...) function, and the calibration
77 : /// storage classes (AliTPCCalROC) are filled for each ROC.
78 : /// The calibration information is stored in the TObjArrays fCalRocArrayT0, fCalRocArrayRMS and
79 : /// fCalRocArrayQ;
80 : ///
81 : ///
82 : ///
83 : /// User interface for filling data:
84 : /// --------------------------------
85 : ///
86 : /// To Fill information one of the following functions can be used:
87 : ///
88 : /// Bool_t ProcessEvent(eventHeaderStruct *event);
89 : /// - process Date event
90 : /// - use AliTPCRawReaderDate and call ProcessEvent(AliRawReader *rawReader)
91 : ///
92 : /// Bool_t ProcessEvent(AliRawReader *rawReader);
93 : /// - process AliRawReader event
94 : /// - use AliTPCRawStreamV3 to loop over data and call ProcessEvent(AliTPCRawStreamV3 *rawStream)
95 : ///
96 : /// Bool_t ProcessEvent(AliTPCRawStreamV3 *rawStream);
97 : /// - process event from AliTPCRawStreamV3
98 : /// - call Update function for signal filling
99 : ///
100 : /// Int_t Update(const Int_t isector, const Int_t iRow, const Int_t
101 : /// iPad, const Int_t iTimeBin, const Float_t signal);
102 : /// - directly fill signal information (sector, row, pad, time bin, pad)
103 : /// to the reference histograms
104 : ///
105 : /// It is also possible to merge two independently taken calibrations using the function
106 : ///
107 : /// void Merge(AliTPCCalibPulser *sig)
108 : /// - copy histograms in 'sig' if the do not exist in this instance
109 : /// - Add histograms in 'sig' to the histograms in this instance if the allready exist
110 : /// - After merging call Analyse again!
111 : ///
112 : ///
113 : ///
114 : /// -- example: filling data using root raw data:
115 : /// ~~~{.cpp}
116 : /// void fillSignal(Char_t *filename)
117 : /// {
118 : /// rawReader = new AliRawReaderRoot(fileName);
119 : /// if ( !rawReader ) return;
120 : /// AliTPCCalibPulser *calib = new AliTPCCalibPulser;
121 : /// while (rawReader->NextEvent()){
122 : /// calib->ProcessEvent(rawReader);
123 : /// }
124 : /// calib->Analyse();
125 : /// calib->DumpToFile("SignalData.root");
126 : /// delete rawReader;
127 : /// delete calib;
128 : /// }
129 : /// ~~~
130 : ///
131 : /// What kind of information is stored and how to retrieve them:
132 : /// ------------------------------------------------------------
133 : ///
134 : /// - Accessing the 'Reference Histograms' (Time0, signal width and Q sum information pad by pad):
135 : ///
136 : /// TH2F *GetHistoT0(Int_t sector);
137 : /// TH2F *GetHistoRMS(Int_t sector);
138 : /// TH2F *GetHistoQ(Int_t sector);
139 : ///
140 : /// - Accessing the calibration storage objects:
141 : ///
142 : /// AliTPCCalROC *GetCalRocT0(Int_t sector); // for the Time0 values
143 : /// AliTPCCalROC *GetCalRocRMS(Int_t sector); // for the signal width values
144 : /// AliTPCCalROC *GetCalRocQ(Int_t sector); // for the Q sum values
145 : ///
146 : /// example for visualisation:
147 : /// if the file "SignalData.root" was created using the above example one could do the following:
148 : ///
149 : /// ~~~{.cpp}
150 : /// TFile fileSignal("SignalData.root")
151 : /// AliTPCCalibPulser *sig = (AliTPCCalibPulser*)fileSignal->Get("AliTPCCalibPulser");
152 : /// sig->GetCalRocT0(0)->Draw("colz");
153 : /// sig->GetCalRocRMS(0)->Draw("colz");
154 : /// ~~~
155 : ///
156 : /// or use the AliTPCCalPad functionality:
157 : ///
158 : /// ~~~{.cpp}
159 : /// AliTPCCalPad padT0(ped->GetCalPadT0());
160 : /// AliTPCCalPad padSigWidth(ped->GetCalPadRMS());
161 : /// padT0->MakeHisto2D()->Draw("colz"); //Draw A-Side Time0 Information
162 : /// padSigWidth->MakeHisto2D()->Draw("colz"); //Draw A-Side signal width Information
163 : /// ~~~
164 :
165 : //Root includes
166 : #include <TObjArray.h>
167 : #include <TH1F.h>
168 : #include <TH2F.h>
169 : #include <TH2S.h>
170 : #include <TString.h>
171 : #include <TVectorF.h>
172 : #include <TMath.h>
173 : #include <TMap.h>
174 : #include <TDirectory.h>
175 : #include <TSystem.h>
176 : #include <TROOT.h>
177 : #include <TFile.h>
178 :
179 : //AliRoot includes
180 : #include "AliRawReader.h"
181 : #include "AliRawReaderRoot.h"
182 : #include "AliRawReaderDate.h"
183 : #include "AliTPCCalROC.h"
184 : #include "AliTPCCalPad.h"
185 : #include "AliTPCROC.h"
186 : #include "AliTPCParam.h"
187 : #include "AliTPCCalibPulser.h"
188 : #include "AliTPCcalibDB.h"
189 : #include "AliMathBase.h"
190 : #include "AliLog.h"
191 : #include "TTreeStream.h"
192 :
193 : //date
194 : #include "event.h"
195 :
196 :
197 :
198 :
199 : /// \cond CLASSIMP
200 24 : ClassImp(AliTPCCalibPulser)
201 : /// \endcond
202 :
203 : AliTPCCalibPulser::AliTPCCalibPulser() :
204 0 : AliTPCCalibRawBase(),
205 0 : fNbinsT0(200),
206 0 : fXminT0(-2),
207 0 : fXmaxT0(2),
208 0 : fNbinsQ(200),
209 0 : fXminQ(10),
210 0 : fXmaxQ(40),
211 0 : fNbinsRMS(100),
212 0 : fXminRMS(0.1),
213 0 : fXmaxRMS(5.1),
214 0 : fPeakIntMinus(2),
215 0 : fPeakIntPlus(2),
216 0 : fIsZeroSuppressed(kFALSE),
217 0 : fLastSector(-1),
218 0 : fParam(new AliTPCParam),
219 0 : fPedestalTPC(0x0),
220 0 : fPadNoiseTPC(0x0),
221 0 : fOutliers(0x0),
222 0 : fPedestalROC(0x0),
223 0 : fPadNoiseROC(0x0),
224 0 : fCalRocArrayT0(72),
225 0 : fCalRocArrayQ(72),
226 0 : fCalRocArrayRMS(72),
227 0 : fCalRocArrayOutliers(72),
228 0 : fHistoQArray(72),
229 0 : fHistoT0Array(72),
230 0 : fHistoRMSArray(72),
231 0 : fHMeanTimeSector(0x0),
232 0 : fVMeanTimeSector(72),
233 0 : fPadTimesArrayEvent(72),
234 0 : fPadQArrayEvent(72),
235 0 : fPadRMSArrayEvent(72),
236 0 : fPadPedestalArrayEvent(72),
237 0 : fCurrentChannel(-1),
238 0 : fCurrentSector(-1),
239 0 : fCurrentRow(-1),
240 0 : fCurrentPad(-1),
241 0 : fMaxPadSignal(-1),
242 0 : fMaxTimeBin(-1),
243 0 : fPadSignal(1024),
244 0 : fPadPedestal(0),
245 0 : fPadNoise(0),
246 0 : fVTime0Offset(72),
247 0 : fVTime0OffsetCounter(72)
248 0 : {
249 : //
250 : // AliTPCSignal default constructor
251 : //
252 0 : SetNameTitle("AliTPCCalibPulser","AliTPCCalibPulser");
253 0 : fFirstTimeBin=60;
254 0 : fLastTimeBin=900;
255 0 : fParam->Update();
256 0 : }
257 : //_____________________________________________________________________
258 : AliTPCCalibPulser::AliTPCCalibPulser(const AliTPCCalibPulser &sig) :
259 0 : AliTPCCalibRawBase(sig),
260 0 : fNbinsT0(sig.fNbinsT0),
261 0 : fXminT0(sig.fXminT0),
262 0 : fXmaxT0(sig.fXmaxT0),
263 0 : fNbinsQ(sig.fNbinsQ),
264 0 : fXminQ(sig.fXminQ),
265 0 : fXmaxQ(sig.fXmaxQ),
266 0 : fNbinsRMS(sig.fNbinsRMS),
267 0 : fXminRMS(sig.fXminRMS),
268 0 : fXmaxRMS(sig.fXmaxRMS),
269 0 : fPeakIntMinus(sig.fPeakIntMinus),
270 0 : fPeakIntPlus(sig.fPeakIntPlus),
271 0 : fIsZeroSuppressed(sig.fIsZeroSuppressed),
272 0 : fLastSector(-1),
273 0 : fParam(new AliTPCParam),
274 0 : fPedestalTPC(0x0),
275 0 : fPadNoiseTPC(0x0),
276 0 : fOutliers(0x0),
277 0 : fPedestalROC(0x0),
278 0 : fPadNoiseROC(0x0),
279 0 : fCalRocArrayT0(72),
280 0 : fCalRocArrayQ(72),
281 0 : fCalRocArrayRMS(72),
282 0 : fCalRocArrayOutliers(72),
283 0 : fHistoQArray(72),
284 0 : fHistoT0Array(72),
285 0 : fHistoRMSArray(72),
286 0 : fHMeanTimeSector(0x0),
287 0 : fVMeanTimeSector(72),
288 0 : fPadTimesArrayEvent(72),
289 0 : fPadQArrayEvent(72),
290 0 : fPadRMSArrayEvent(72),
291 0 : fPadPedestalArrayEvent(72),
292 0 : fCurrentChannel(-1),
293 0 : fCurrentSector(-1),
294 0 : fCurrentRow(-1),
295 0 : fCurrentPad(-1),
296 0 : fMaxPadSignal(-1),
297 0 : fMaxTimeBin(-1),
298 0 : fPadSignal(1024),
299 0 : fPadPedestal(0),
300 0 : fPadNoise(0),
301 0 : fVTime0Offset(72),
302 0 : fVTime0OffsetCounter(72)
303 0 : {
304 : /// AliTPCSignal default constructor
305 :
306 0 : for (Int_t iSec = 0; iSec < 72; ++iSec){
307 0 : const AliTPCCalROC *calQ = (AliTPCCalROC*)sig.fCalRocArrayQ.UncheckedAt(iSec);
308 0 : const AliTPCCalROC *calT0 = (AliTPCCalROC*)sig.fCalRocArrayT0.UncheckedAt(iSec);
309 0 : const AliTPCCalROC *calRMS = (AliTPCCalROC*)sig.fCalRocArrayRMS.UncheckedAt(iSec);
310 0 : const AliTPCCalROC *calOut = (AliTPCCalROC*)sig.fCalRocArrayOutliers.UncheckedAt(iSec);
311 :
312 0 : const TH2S *hQ = (TH2S*)sig.fHistoQArray.UncheckedAt(iSec);
313 0 : const TH2S *hT0 = (TH2S*)sig.fHistoT0Array.UncheckedAt(iSec);
314 0 : const TH2S *hRMS = (TH2S*)sig.fHistoRMSArray.UncheckedAt(iSec);
315 :
316 0 : if ( calQ != 0x0 ) fCalRocArrayQ.AddAt(new AliTPCCalROC(*calQ), iSec);
317 0 : if ( calT0 != 0x0 ) fCalRocArrayT0.AddAt(new AliTPCCalROC(*calT0), iSec);
318 0 : if ( calRMS != 0x0 ) fCalRocArrayRMS.AddAt(new AliTPCCalROC(*calRMS), iSec);
319 0 : if ( calOut != 0x0 ) fCalRocArrayOutliers.AddAt(new AliTPCCalROC(*calOut), iSec);
320 :
321 0 : if ( hQ != 0x0 ){
322 0 : TH2S *hNew = new TH2S(*hQ);
323 0 : hNew->SetDirectory(0);
324 0 : fHistoQArray.AddAt(hNew,iSec);
325 0 : }
326 0 : if ( hT0 != 0x0 ){
327 0 : TH2S *hNew = new TH2S(*hT0);
328 0 : hNew->SetDirectory(0);
329 0 : fHistoQArray.AddAt(hNew,iSec);
330 0 : }
331 0 : if ( hRMS != 0x0 ){
332 0 : TH2S *hNew = new TH2S(*hRMS);
333 0 : hNew->SetDirectory(0);
334 0 : fHistoQArray.AddAt(hNew,iSec);
335 0 : }
336 0 : fVMeanTimeSector[iSec]=sig.fVMeanTimeSector[iSec];
337 : }
338 :
339 0 : if ( sig.fHMeanTimeSector ) fHMeanTimeSector=(TH2F*)sig.fHMeanTimeSector->Clone();
340 0 : fParam->Update();
341 0 : }
342 : AliTPCCalibPulser::AliTPCCalibPulser(const TMap *config) :
343 0 : AliTPCCalibRawBase(),
344 0 : fNbinsT0(200),
345 0 : fXminT0(-2),
346 0 : fXmaxT0(2),
347 0 : fNbinsQ(200),
348 0 : fXminQ(10),
349 0 : fXmaxQ(40),
350 0 : fNbinsRMS(100),
351 0 : fXminRMS(0.1),
352 0 : fXmaxRMS(5.1),
353 0 : fPeakIntMinus(2),
354 0 : fPeakIntPlus(2),
355 0 : fIsZeroSuppressed(kFALSE),
356 0 : fLastSector(-1),
357 0 : fParam(new AliTPCParam),
358 0 : fPedestalTPC(0x0),
359 0 : fPadNoiseTPC(0x0),
360 0 : fOutliers(0x0),
361 0 : fPedestalROC(0x0),
362 0 : fPadNoiseROC(0x0),
363 0 : fCalRocArrayT0(72),
364 0 : fCalRocArrayQ(72),
365 0 : fCalRocArrayRMS(72),
366 0 : fCalRocArrayOutliers(72),
367 0 : fHistoQArray(72),
368 0 : fHistoT0Array(72),
369 0 : fHistoRMSArray(72),
370 0 : fHMeanTimeSector(0x0),
371 0 : fVMeanTimeSector(72),
372 0 : fPadTimesArrayEvent(72),
373 0 : fPadQArrayEvent(72),
374 0 : fPadRMSArrayEvent(72),
375 0 : fPadPedestalArrayEvent(72),
376 0 : fCurrentChannel(-1),
377 0 : fCurrentSector(-1),
378 0 : fCurrentRow(-1),
379 0 : fCurrentPad(-1),
380 0 : fMaxPadSignal(-1),
381 0 : fMaxTimeBin(-1),
382 0 : fPadSignal(1024),
383 0 : fPadPedestal(0),
384 0 : fPadNoise(0),
385 0 : fVTime0Offset(72),
386 0 : fVTime0OffsetCounter(72)
387 0 : {
388 : /// This constructor uses a TMap for setting some parametes
389 :
390 0 : SetNameTitle("AliTPCCalibPulser","AliTPCCalibPulser");
391 0 : fFirstTimeBin=60;
392 0 : fLastTimeBin=900;
393 0 : if (config->GetValue("FirstTimeBin")) fFirstTimeBin = ((TObjString*)config->GetValue("FirstTimeBin"))->GetString().Atoi();
394 0 : if (config->GetValue("LastTimeBin")) fLastTimeBin = ((TObjString*)config->GetValue("LastTimeBin"))->GetString().Atoi();
395 0 : if (config->GetValue("NbinsT0")) fNbinsT0 = ((TObjString*)config->GetValue("NbinsT0"))->GetString().Atoi();
396 0 : if (config->GetValue("XminT0")) fXminT0 = ((TObjString*)config->GetValue("XminT0"))->GetString().Atof();
397 0 : if (config->GetValue("XmaxT0")) fXmaxT0 = ((TObjString*)config->GetValue("XmaxT0"))->GetString().Atof();
398 0 : if (config->GetValue("NbinsQ")) fNbinsQ = ((TObjString*)config->GetValue("NbinsQ"))->GetString().Atoi();
399 0 : if (config->GetValue("XminQ")) fXminQ = ((TObjString*)config->GetValue("XminQ"))->GetString().Atof();
400 0 : if (config->GetValue("XmaxQ")) fXmaxQ = ((TObjString*)config->GetValue("XmaxQ"))->GetString().Atof();
401 0 : if (config->GetValue("NbinsRMS")) fNbinsRMS = ((TObjString*)config->GetValue("NbinsRMS"))->GetString().Atoi();
402 0 : if (config->GetValue("XminRMS")) fXminRMS = ((TObjString*)config->GetValue("XminRMS"))->GetString().Atof();
403 0 : if (config->GetValue("XmaxRMS")) fXmaxRMS = ((TObjString*)config->GetValue("XmaxRMS"))->GetString().Atof();
404 0 : if (config->GetValue("PeakIntMinus")) fPeakIntMinus = (Int_t)((TObjString*)config->GetValue("PeakIntMinus"))->GetString().Atof();
405 0 : if (config->GetValue("PeakIntPlus")) fPeakIntPlus = (Int_t)((TObjString*)config->GetValue("PeakIntPlus"))->GetString().Atof();
406 0 : if (config->GetValue("IsZeroSuppressed")) fIsZeroSuppressed = (Bool_t)((TObjString*)config->GetValue("IsZeroSuppressed"))->GetString().Atoi();
407 :
408 0 : fParam->Update();
409 0 : }
410 : //_____________________________________________________________________
411 : AliTPCCalibPulser& AliTPCCalibPulser::operator = (const AliTPCCalibPulser &source)
412 : {
413 : /// assignment operator
414 :
415 0 : if (&source == this) return *this;
416 0 : new (this) AliTPCCalibPulser(source);
417 :
418 0 : return *this;
419 0 : }
420 : //_____________________________________________________________________
421 : AliTPCCalibPulser::~AliTPCCalibPulser()
422 0 : {
423 : /// destructor
424 :
425 0 : Reset();
426 0 : delete fParam;
427 0 : }
428 : void AliTPCCalibPulser::Reset()
429 : {
430 : /// Delete all information: Arrays, Histograms, CalRoc objects
431 :
432 0 : fCalRocArrayT0.Delete();
433 0 : fCalRocArrayQ.Delete();
434 0 : fCalRocArrayRMS.Delete();
435 0 : fCalRocArrayOutliers.Delete();
436 :
437 0 : fHistoQArray.Delete();
438 0 : fHistoT0Array.Delete();
439 0 : fHistoRMSArray.Delete();
440 :
441 0 : fPadTimesArrayEvent.Delete();
442 0 : fPadQArrayEvent.Delete();
443 0 : fPadRMSArrayEvent.Delete();
444 0 : fPadPedestalArrayEvent.Delete();
445 :
446 0 : if (fHMeanTimeSector) delete fHMeanTimeSector;
447 0 : }
448 : //_____________________________________________________________________
449 : Int_t AliTPCCalibPulser::Update(const Int_t icsector,
450 : const Int_t icRow,
451 : const Int_t icPad,
452 : const Int_t icTimeBin,
453 : const Float_t csignal)
454 : {
455 : /// Signal filling methode on the fly pedestal and time offset correction if necessary.
456 : /// no extra analysis necessary. Assumes knowledge of the signal shape!
457 : /// assumes that it is looped over consecutive time bins of one pad
458 :
459 0 : if (icRow<0) return 0;
460 0 : if (icPad<0) return 0;
461 0 : if (icTimeBin<0) return 0;
462 0 : if ( (icTimeBin>fLastTimeBin) || (icTimeBin<fFirstTimeBin) ) return 0;
463 :
464 0 : if ( icRow<0 || icPad<0 ){
465 0 : AliWarning("Wrong Pad or Row number, skipping!");
466 0 : return 0;
467 : }
468 :
469 0 : Int_t iChannel = fROC->GetRowIndexes(icsector)[icRow]+icPad; // global pad position in sector
470 :
471 : //init first pad and sector in this event
472 0 : if ( fCurrentChannel == -1 ) {
473 0 : fCurrentChannel = iChannel;
474 0 : fCurrentSector = icsector;
475 0 : fCurrentRow = icRow;
476 0 : fCurrentPad = icPad;
477 0 : }
478 :
479 : //process last pad if we change to a new one
480 0 : if ( iChannel != fCurrentChannel ){
481 0 : ProcessPad();
482 0 : fLastSector=fCurrentSector;
483 0 : fCurrentChannel = iChannel;
484 0 : fCurrentSector = icsector;
485 0 : fCurrentRow = icRow;
486 0 : fCurrentPad = icPad;
487 0 : }
488 :
489 : //fill signals for current pad
490 0 : fPadSignal[icTimeBin]=csignal;
491 0 : if ( csignal > fMaxPadSignal ){
492 0 : fMaxPadSignal = csignal;
493 0 : fMaxTimeBin = icTimeBin;
494 0 : }
495 : return 0;
496 0 : }
497 : //_____________________________________________________________________
498 : void AliTPCCalibPulser::FindPedestal(Float_t part)
499 : {
500 : /// find pedestal and noise for the current pad. Use either database or
501 : /// truncated mean with part*100%
502 :
503 : Bool_t noPedestal = kTRUE;;
504 0 : if (fPedestalTPC&&fPadNoiseTPC){
505 : //use pedestal database
506 : //only load new pedestals if the sector has changed
507 0 : if ( fCurrentSector!=fLastSector ){
508 0 : fPedestalROC = fPedestalTPC->GetCalROC(fCurrentSector);
509 0 : fPadNoiseROC = fPadNoiseTPC->GetCalROC(fCurrentSector);
510 0 : }
511 :
512 0 : if ( fPedestalROC&&fPadNoiseROC ){
513 0 : fPadPedestal = fPedestalROC->GetValue(fCurrentChannel);
514 0 : fPadNoise = fPadNoiseROC->GetValue(fCurrentChannel);
515 : noPedestal = kFALSE;
516 0 : }
517 :
518 : }
519 :
520 : //if we are not running with pedestal database, or for the current sector there is no information
521 : //available, calculate the pedestal and noise on the fly
522 0 : if ( noPedestal ) {
523 : const Int_t kPedMax = 100; //maximum pedestal value
524 : Float_t max = 0;
525 : Int_t median = -1;
526 : Int_t count0 = 0;
527 : Int_t count1 = 0;
528 : //
529 : Float_t padSignal=0;
530 : //
531 0 : UShort_t histo[kPedMax];
532 0 : memset(histo,0,kPedMax*sizeof(UShort_t));
533 :
534 0 : for (Int_t i=fFirstTimeBin; i<=fLastTimeBin; ++i){
535 0 : padSignal = fPadSignal.GetMatrixArray()[i];
536 0 : if (padSignal<=0) continue;
537 0 : if (padSignal>max && i>10) {
538 : max = padSignal;
539 0 : }
540 0 : if (padSignal>kPedMax-1) continue;
541 0 : histo[Int_t(padSignal+0.5)]++;
542 0 : count0++;
543 0 : }
544 : //
545 0 : for (Int_t i=1; i<kPedMax; ++i){
546 0 : if (count1<count0*0.5) median=i;
547 0 : count1+=histo[i];
548 : }
549 : // truncated mean
550 : //
551 : // what if by chance histo[median] == 0 ?!?
552 0 : Float_t count=histo[median] ,mean=histo[median]*median, rms=histo[median]*median*median ;
553 : //
554 0 : for (Int_t idelta=1; idelta<10; ++idelta){
555 0 : if (median-idelta<=0) continue;
556 0 : if (median+idelta>kPedMax) continue;
557 0 : if (count<part*count1){
558 0 : count+=histo[median-idelta];
559 0 : mean +=histo[median-idelta]*(median-idelta);
560 0 : rms +=histo[median-idelta]*(median-idelta)*(median-idelta);
561 0 : count+=histo[median+idelta];
562 0 : mean +=histo[median+idelta]*(median+idelta);
563 0 : rms +=histo[median+idelta]*(median+idelta)*(median+idelta);
564 0 : }
565 : }
566 0 : fPadPedestal = 0;
567 0 : fPadNoise = 0;
568 0 : if ( count > 0 ) {
569 0 : mean/=count;
570 0 : rms = TMath::Sqrt(TMath::Abs(rms/count-mean*mean));
571 0 : fPadPedestal = mean;
572 0 : fPadNoise = rms;
573 0 : }
574 0 : }
575 0 : fPadPedestal*=(Float_t)(!fIsZeroSuppressed);
576 0 : }
577 : //_____________________________________________________________________
578 : void AliTPCCalibPulser::FindPulserSignal(TVectorD ¶m, Float_t &qSum)
579 : {
580 : /// Find position, signal width and height of the CE signal (last signal)
581 : /// param[0] = Qmax, param[1] = mean time, param[2] = rms;
582 : /// maxima: array of local maxima of the pad signal use the one closest to the mean CE position
583 :
584 : Float_t ceQmax =0, ceQsum=0, ceTime=0, ceRMS=0;
585 0 : Int_t cemaxpos = fMaxTimeBin;
586 0 : Float_t ceSumThreshold = 10.*TMath::Max(fPadNoise,Float_t(1.)); // threshold for the signal sum
587 0 : Float_t ceMaxThreshold = 5.*TMath::Max(fPadNoise,Float_t(1.)); // threshold for the signal max
588 0 : const Int_t kCemin = fPeakIntMinus; // range for the analysis of the ce signal +- channels from the peak
589 0 : const Int_t kCemax = fPeakIntPlus;
590 0 : param[0] = ceQmax;
591 0 : param[1] = ceTime;
592 0 : param[2] = ceRMS;
593 0 : qSum = ceQsum;
594 :
595 0 : if (cemaxpos>0){
596 0 : ceQmax = fPadSignal.GetMatrixArray()[cemaxpos]-fPadPedestal;
597 0 : if ( ceQmax<ceMaxThreshold ) return;
598 0 : for (Int_t i=cemaxpos-kCemin; i<=cemaxpos+kCemax; ++i){
599 0 : Float_t signal = fPadSignal.GetMatrixArray()[i]-fPadPedestal;
600 0 : if ( (i>fFirstTimeBin) && (i<fLastTimeBin) && (signal>0) ){
601 0 : ceTime+=signal*(i+0.5);
602 0 : ceRMS +=signal*(i+0.5)*(i+0.5);
603 0 : ceQsum+=signal;
604 0 : }
605 : }
606 0 : }
607 0 : if (ceQsum>ceSumThreshold) {
608 0 : ceTime/=ceQsum;
609 0 : ceRMS = TMath::Sqrt(TMath::Abs(ceRMS/ceQsum-ceTime*ceTime));
610 0 : ceTime-=GetL1PhaseTB();
611 : //only fill the Time0Offset if pad was not marked as an outlier!
612 0 : if ( !fOutliers ){
613 : //skip edge pads for calculating the mean time
614 0 : if ( !IsEdgePad(fCurrentSector,fCurrentRow,fCurrentPad) ){
615 0 : fVTime0Offset.GetMatrixArray()[fCurrentSector]+=ceTime; // mean time for each sector
616 0 : fVTime0OffsetCounter.GetMatrixArray()[fCurrentSector]++;
617 0 : GetHistoTSec()->Fill(ceTime,fCurrentSector);
618 0 : }
619 : } else {
620 0 : if ( !(fOutliers->GetCalROC(fCurrentSector)->GetValue(fCurrentChannel)) ){
621 0 : fVTime0Offset.GetMatrixArray()[fCurrentSector]+=ceTime; // mean time for each sector
622 0 : fVTime0OffsetCounter.GetMatrixArray()[fCurrentSector]++;
623 0 : }
624 : }
625 :
626 : //Normalise Q to the 'cell-size': The wire density is the same in the IROC and OROC, therefore the
627 : // the pick-up signal should scale with the pad area. In addition
628 : // the signal should decrease with the wire distance (4mm in IROC, 6mm in OROC),
629 : // ratio 2/3. The pad area we express in mm2 (factor 100). We normalise the signal
630 : // to the OROC signal (factor 2/3 for the IROCs).
631 0 : Float_t norm = fParam->GetPadPitchWidth(fCurrentSector)*fParam->GetPadPitchLength(fCurrentSector,fCurrentRow)*100;
632 0 : if ( fCurrentSector<fParam->GetNInnerSector() ) norm*=3./2.;
633 :
634 0 : ceQsum/=norm;
635 0 : } else {
636 : ceQmax=0;
637 : ceTime=0;
638 : ceRMS =0;
639 : ceQsum=0;
640 : }
641 0 : param[0] = ceQmax;
642 0 : param[1] = ceTime;
643 0 : param[2] = ceRMS;
644 0 : qSum = ceQsum;
645 0 : }
646 : //_____________________________________________________________________
647 : void AliTPCCalibPulser::ProcessPad()
648 : {
649 : /// Process data of current pad
650 :
651 0 : FindPedestal();
652 0 : TVectorD param(3);
653 0 : Float_t qSum;
654 0 : FindPulserSignal(param, qSum);
655 :
656 0 : Double_t meanT = param[1];
657 0 : Double_t sigmaT = param[2];
658 :
659 :
660 : //Fill Event T0 counter
661 0 : (*GetPadTimesEvent(fCurrentSector,kTRUE)).GetMatrixArray()[fCurrentChannel] = meanT;
662 :
663 : //Fill Q histogram
664 : // GetHistoQ(fCurrentSector,kTRUE)->Fill( TMath::Sqrt(qSum), fCurrentChannel ); //use linear scale, needs also a change in the Analyse funciton.
665 0 : GetHistoQ(fCurrentSector,kTRUE)->Fill( qSum, fCurrentChannel );
666 :
667 : //Fill RMS histogram
668 0 : GetHistoRMS(fCurrentSector,kTRUE)->Fill( sigmaT, fCurrentChannel );
669 :
670 :
671 : //Fill debugging info
672 0 : if ( GetStreamLevel()>0 ){
673 0 : TTreeSRedirector *streamer=GetDebugStreamer();
674 0 : if ( GetStreamLevel() == 1 ){
675 0 : if ( streamer ) {
676 0 : Int_t padc = fCurrentPad-(fROC->GetNPads(fCurrentSector,fCurrentRow)/2);
677 0 : (*streamer) << "PadSignals" <<
678 0 : "Event=" <<fNevents <<
679 0 : "Sector=" <<fCurrentSector<<
680 0 : "Row=" <<fCurrentRow<<
681 0 : "Pad=" <<fCurrentPad<<
682 0 : "PadC=" <<padc<<
683 0 : "Channel="<<fCurrentChannel<<
684 0 : "Sum=" <<qSum<<
685 0 : "params.="<<¶m<<
686 0 : "signal.=" <<&fPadSignal<<
687 : "\n";
688 0 : }
689 : } else { //debug > 1
690 0 : (*GetPadPedestalEvent(fCurrentSector,kTRUE))[fCurrentChannel]=fPadPedestal;
691 0 : (*GetPadRMSEvent(fCurrentSector,kTRUE))[fCurrentChannel]=sigmaT;
692 0 : (*GetPadQEvent(fCurrentSector,kTRUE))[fCurrentChannel]=qSum;
693 : }
694 0 : }
695 0 : ResetPad();
696 0 : }
697 : //_____________________________________________________________________
698 : void AliTPCCalibPulser::EndEvent()
699 : {
700 : /// Process data of current event
701 :
702 : //check if last pad has allready been processed, if not do so
703 0 : if ( fMaxTimeBin>-1 ) ProcessPad();
704 :
705 : //loop over all ROCs, fill Time0 histogram corrected for the mean Time0 of each ROC
706 0 : for ( Int_t iSec = 0; iSec<72; ++iSec ){
707 0 : TVectorF *vTimes = GetPadTimesEvent(iSec);
708 0 : if ( !vTimes || fVTime0OffsetCounter[iSec]==0 ) continue;
709 0 : Float_t time0 = fVTime0Offset[iSec]/fVTime0OffsetCounter[iSec];
710 0 : for ( UInt_t iChannel=0; iChannel<fROC->GetNChannels(iSec); ++iChannel ){
711 0 : Float_t time = (*vTimes).GetMatrixArray()[iChannel];
712 :
713 0 : GetHistoT0(iSec,kTRUE)->Fill( time-time0,iChannel );
714 : //GetHistoT0(iSec,kTRUE)->Fill( time,iChannel );
715 :
716 :
717 : //Debug start
718 0 : if ( GetStreamLevel()>1 ){
719 0 : TTreeSRedirector *streamer=GetDebugStreamer();
720 0 : if ( streamer ) {
721 0 : Int_t row=0;
722 0 : Int_t pad=0;
723 0 : Int_t padc=0;
724 :
725 0 : Float_t q = (*GetPadQEvent(iSec)).GetMatrixArray()[iChannel];
726 0 : Float_t rms = (*GetPadRMSEvent(iSec)).GetMatrixArray()[iChannel];
727 :
728 0 : UInt_t channel=iChannel;
729 0 : Int_t sector=iSec;
730 :
731 0 : while ( channel > (fROC->GetRowIndexes(sector)[row]+fROC->GetNPads(sector,row)-1) ) row++;
732 0 : pad = channel-fROC->GetRowIndexes(sector)[row];
733 0 : padc = pad-(fROC->GetNPads(sector,row)/2);
734 :
735 0 : (*streamer) << "DataPad" <<
736 0 : "Event=" << fNevents <<
737 0 : "Sector="<< sector <<
738 0 : "Row=" << row<<
739 0 : "Pad=" << pad <<
740 0 : "PadC=" << padc <<
741 0 : "PadSec="<< channel <<
742 0 : "Time0=" << time0 <<
743 0 : "Time=" << time <<
744 0 : "RMS=" << rms <<
745 0 : "Sum=" << q <<
746 : "\n";
747 0 : }
748 0 : }
749 : //Debug end
750 0 : }
751 0 : }
752 0 : ++fNevents;
753 0 : }
754 : //_____________________________________________________________________
755 : TH2S* AliTPCCalibPulser::GetHisto(Int_t sector, TObjArray *arr,
756 : Int_t nbinsY, Float_t ymin, Float_t ymax,
757 : const Char_t *type, Bool_t force)
758 : {
759 : /// return pointer to Q histogram
760 : /// if force is true create a new histogram if it doesn't exist allready
761 :
762 0 : if ( !force || arr->UncheckedAt(sector) )
763 0 : return (TH2S*)arr->UncheckedAt(sector);
764 :
765 : // if we are forced and histogram doesn't yes exist create it
766 : // new histogram with Q calib information. One value for each pad!
767 0 : TH2S* hist = new TH2S(Form("hCalib%s%.2d",type,sector),Form("%s calibration histogram sector %.2d",type,sector),
768 0 : nbinsY, ymin, ymax,
769 0 : fROC->GetNChannels(sector),0,fROC->GetNChannels(sector));
770 0 : hist->SetDirectory(0);
771 0 : arr->AddAt(hist,sector);
772 : return hist;
773 0 : }
774 : //_____________________________________________________________________
775 : TH2S* AliTPCCalibPulser::GetHistoT0(Int_t sector, Bool_t force)
776 : {
777 : /// return pointer to T0 histogram
778 : /// if force is true create a new histogram if it doesn't exist allready
779 :
780 0 : TObjArray *arr = &fHistoT0Array;
781 0 : return GetHisto(sector, arr, fNbinsT0, fXminT0, fXmaxT0, "T0", force);
782 : }
783 : //_____________________________________________________________________
784 : TH2S* AliTPCCalibPulser::GetHistoQ(Int_t sector, Bool_t force)
785 : {
786 : /// return pointer to Q histogram
787 : /// if force is true create a new histogram if it doesn't exist allready
788 :
789 0 : TObjArray *arr = &fHistoQArray;
790 0 : return GetHisto(sector, arr, fNbinsQ, fXminQ, fXmaxQ, "Q", force);
791 : }
792 : //_____________________________________________________________________
793 : TH2S* AliTPCCalibPulser::GetHistoRMS(Int_t sector, Bool_t force)
794 : {
795 : /// return pointer to Q histogram
796 : /// if force is true create a new histogram if it doesn't exist allready
797 :
798 0 : TObjArray *arr = &fHistoRMSArray;
799 0 : return GetHisto(sector, arr, fNbinsRMS, fXminRMS, fXmaxRMS, "RMS", force);
800 : }
801 : //_____________________________________________________________________
802 : TH2F* AliTPCCalibPulser::GetHistoTSec()
803 : {
804 : /// return the pointer to the abs time distribution per sector
805 : /// create it if it does not exist
806 :
807 0 : if ( !fHMeanTimeSector ) //!!!if you change the binning here, you should also change it in the Analyse Function!!
808 0 : fHMeanTimeSector = new TH2F("fHMeanTimeSector","Abs mean time per sector",
809 0 : 20*(fLastTimeBin-fFirstTimeBin), fFirstTimeBin, fLastTimeBin,
810 : 72,0,72);
811 0 : return fHMeanTimeSector;
812 0 : }
813 : //_____________________________________________________________________
814 : TVectorF* AliTPCCalibPulser::GetPadInfoEvent(Int_t sector, TObjArray *arr, Bool_t force)
815 : {
816 : /// return pointer to Pad Info from 'arr' for the current event and sector
817 : /// if force is true create it if it doesn't exist allready
818 :
819 0 : if ( !force || arr->UncheckedAt(sector) )
820 0 : return (TVectorF*)arr->UncheckedAt(sector);
821 :
822 0 : TVectorF *vect = new TVectorF(fROC->GetNChannels(sector));
823 0 : arr->AddAt(vect,sector);
824 : return vect;
825 0 : }
826 : //_____________________________________________________________________
827 : TVectorF* AliTPCCalibPulser::GetPadTimesEvent(Int_t sector, Bool_t force)
828 : {
829 : /// return pointer to Pad Times Array for the current event and sector
830 : /// if force is true create it if it doesn't exist allready
831 :
832 0 : TObjArray *arr = &fPadTimesArrayEvent;
833 0 : return GetPadInfoEvent(sector,arr,force);
834 : }
835 : //_____________________________________________________________________
836 : TVectorF* AliTPCCalibPulser::GetPadQEvent(Int_t sector, Bool_t force)
837 : {
838 : /// return pointer to Pad Q Array for the current event and sector
839 : /// if force is true create it if it doesn't exist allready
840 : /// for debugging purposes only
841 :
842 0 : TObjArray *arr = &fPadQArrayEvent;
843 0 : return GetPadInfoEvent(sector,arr,force);
844 : }
845 : //_____________________________________________________________________
846 : TVectorF* AliTPCCalibPulser::GetPadRMSEvent(Int_t sector, Bool_t force)
847 : {
848 : /// return pointer to Pad RMS Array for the current event and sector
849 : /// if force is true create it if it doesn't exist allready
850 : /// for debugging purposes only
851 :
852 0 : TObjArray *arr = &fPadRMSArrayEvent;
853 0 : return GetPadInfoEvent(sector,arr,force);
854 : }
855 : //_____________________________________________________________________
856 : TVectorF* AliTPCCalibPulser::GetPadPedestalEvent(Int_t sector, Bool_t force)
857 : {
858 : /// return pointer to Pad RMS Array for the current event and sector
859 : /// if force is true create it if it doesn't exist allready
860 : /// for debugging purposes only
861 :
862 0 : TObjArray *arr = &fPadPedestalArrayEvent;
863 0 : return GetPadInfoEvent(sector,arr,force);
864 : }
865 : //_____________________________________________________________________
866 : AliTPCCalROC* AliTPCCalibPulser::GetCalRoc(Int_t sector, TObjArray* arr, Bool_t force) const
867 : {
868 : /// return pointer to ROC Calibration
869 : /// if force is true create a new histogram if it doesn't exist allready
870 :
871 0 : if ( !force || arr->UncheckedAt(sector) )
872 0 : return (AliTPCCalROC*)arr->UncheckedAt(sector);
873 :
874 : // if we are forced and histogram doesn't yes exist create it
875 :
876 : // new AliTPCCalROC for T0 information. One value for each pad!
877 0 : AliTPCCalROC *croc = new AliTPCCalROC(sector);
878 0 : arr->AddAt(croc,sector);
879 : return croc;
880 0 : }
881 : //_____________________________________________________________________
882 : AliTPCCalROC* AliTPCCalibPulser::GetCalRocT0(Int_t sector, Bool_t force)
883 : {
884 : /// return pointer to Carge ROC Calibration
885 : /// if force is true create a new histogram if it doesn't exist allready
886 :
887 0 : TObjArray *arr = &fCalRocArrayT0;
888 0 : return GetCalRoc(sector, arr, force);
889 : }
890 : //_____________________________________________________________________
891 : AliTPCCalROC* AliTPCCalibPulser::GetCalRocQ(Int_t sector, Bool_t force)
892 : {
893 : /// return pointer to T0 ROC Calibration
894 : /// if force is true create a new histogram if it doesn't exist allready
895 :
896 0 : TObjArray *arr = &fCalRocArrayQ;
897 0 : return GetCalRoc(sector, arr, force);
898 : }
899 : //_____________________________________________________________________
900 : AliTPCCalROC* AliTPCCalibPulser::GetCalRocRMS(Int_t sector, Bool_t force)
901 : {
902 : /// return pointer to signal width ROC Calibration
903 : /// if force is true create a new histogram if it doesn't exist allready
904 :
905 0 : TObjArray *arr = &fCalRocArrayRMS;
906 0 : return GetCalRoc(sector, arr, force);
907 : }
908 : //_____________________________________________________________________
909 : AliTPCCalROC* AliTPCCalibPulser::GetCalRocOutliers(Int_t sector, Bool_t force)
910 : {
911 : /// return pointer to Outliers
912 : /// if force is true create a new histogram if it doesn't exist allready
913 :
914 0 : TObjArray *arr = &fCalRocArrayOutliers;
915 0 : return GetCalRoc(sector, arr, force);
916 : }
917 : //_____________________________________________________________________
918 : void AliTPCCalibPulser::ResetEvent()
919 : {
920 : /// Reset global counters -- Should be called before each event is processed
921 :
922 0 : fLastSector=-1;
923 0 : fCurrentSector=-1;
924 0 : fCurrentRow=-1;
925 0 : fCurrentPad=-1;
926 0 : fCurrentChannel=-1;
927 :
928 0 : ResetPad();
929 :
930 0 : fPadTimesArrayEvent.Delete();
931 :
932 0 : fPadQArrayEvent.Delete();
933 0 : fPadRMSArrayEvent.Delete();
934 0 : fPadPedestalArrayEvent.Delete();
935 :
936 0 : for ( Int_t i=0; i<72; ++i ){
937 0 : fVTime0Offset[i]=0;
938 0 : fVTime0OffsetCounter[i]=0;
939 : }
940 0 : }
941 : //_____________________________________________________________________
942 : void AliTPCCalibPulser::ResetPad()
943 : {
944 : /// Reset pad infos -- Should be called after a pad has been processed
945 :
946 0 : for (Int_t i=fFirstTimeBin; i<fLastTimeBin+1; ++i)
947 0 : fPadSignal[i] = 0;
948 0 : fMaxTimeBin = -1;
949 0 : fMaxPadSignal = -1;
950 0 : fPadPedestal = -1;
951 0 : fPadNoise = -1;
952 0 : }
953 : //_____________________________________________________________________
954 : Bool_t AliTPCCalibPulser::IsEdgePad(Int_t sector, Int_t row, Int_t pad)
955 : {
956 : /// return true if pad is on the edge of a row
957 :
958 : Int_t edge1 = 0;
959 0 : Int_t edge2 = fROC->GetNPads(sector,row)-1;
960 0 : if ( pad == edge1 || pad == edge2 ) return kTRUE;
961 :
962 0 : return kFALSE;
963 0 : }
964 : //_____________________________________________________________________
965 : void AliTPCCalibPulser::Merge(AliTPCCalibPulser * const sig)
966 : {
967 : /// Merge reference histograms of sig to the current AliTPCCalibPulser
968 :
969 0 : MergeBase(sig);
970 : //merge histograms
971 0 : for (Int_t iSec=0; iSec<72; ++iSec){
972 0 : TH2S *hRefQmerge = sig->GetHistoQ(iSec);
973 0 : TH2S *hRefT0merge = sig->GetHistoT0(iSec);
974 0 : TH2S *hRefRMSmerge = sig->GetHistoRMS(iSec);
975 :
976 :
977 0 : if ( hRefQmerge ){
978 0 : TDirectory *dir = hRefQmerge->GetDirectory(); hRefQmerge->SetDirectory(0);
979 0 : TH2S *hRefQ = GetHistoQ(iSec);
980 0 : if ( hRefQ ) hRefQ->Add(hRefQmerge);
981 : else {
982 0 : TH2S *hist = new TH2S(*hRefQmerge);
983 0 : hist->SetDirectory(0);
984 0 : fHistoQArray.AddAt(hist, iSec);
985 : }
986 0 : hRefQmerge->SetDirectory(dir);
987 0 : }
988 0 : if ( hRefT0merge ){
989 0 : TDirectory *dir = hRefT0merge->GetDirectory(); hRefT0merge->SetDirectory(0);
990 0 : TH2S *hRefT0 = GetHistoT0(iSec);
991 0 : if ( hRefT0 ) hRefT0->Add(hRefT0merge);
992 : else {
993 0 : TH2S *hist = new TH2S(*hRefT0merge);
994 0 : hist->SetDirectory(0);
995 0 : fHistoT0Array.AddAt(hist, iSec);
996 : }
997 0 : hRefT0merge->SetDirectory(dir);
998 0 : }
999 0 : if ( hRefRMSmerge ){
1000 0 : TDirectory *dir = hRefRMSmerge->GetDirectory(); hRefRMSmerge->SetDirectory(0);
1001 0 : TH2S *hRefRMS = GetHistoRMS(iSec);
1002 0 : if ( hRefRMS ) hRefRMS->Add(hRefRMSmerge);
1003 : else {
1004 0 : TH2S *hist = new TH2S(*hRefRMSmerge);
1005 0 : hist->SetDirectory(0);
1006 0 : fHistoRMSArray.AddAt(hist, iSec);
1007 : }
1008 0 : hRefRMSmerge->SetDirectory(dir);
1009 0 : }
1010 :
1011 : }
1012 0 : if ( sig->fHMeanTimeSector ){
1013 0 : TDirectory *dir = sig->fHMeanTimeSector->GetDirectory(); sig->fHMeanTimeSector->SetDirectory(0);
1014 0 : if ( fHMeanTimeSector ) fHMeanTimeSector->Add(sig->fHMeanTimeSector);
1015 : else {
1016 0 : fHMeanTimeSector = new TH2F(*sig->fHMeanTimeSector);
1017 0 : fHMeanTimeSector->SetDirectory(0);
1018 : }
1019 0 : sig->fHMeanTimeSector->SetDirectory(dir);
1020 0 : }
1021 0 : }
1022 :
1023 :
1024 : //_____________________________________________________________________
1025 : Long64_t AliTPCCalibPulser::Merge(TCollection * const list)
1026 : {
1027 : /// Merge all objects of this type in list
1028 :
1029 : Long64_t nmerged=1;
1030 :
1031 0 : TIter next(list);
1032 : AliTPCCalibPulser *ce=0;
1033 : TObject *o=0;
1034 :
1035 0 : while ( (o=next()) ){
1036 0 : ce=dynamic_cast<AliTPCCalibPulser*>(o);
1037 0 : if (ce){
1038 0 : Merge(ce);
1039 0 : ++nmerged;
1040 0 : }
1041 : }
1042 :
1043 : return nmerged;
1044 0 : }
1045 :
1046 : //_____________________________________________________________________
1047 : void AliTPCCalibPulser::Analyse()
1048 : {
1049 : /// Calculate calibration constants
1050 :
1051 0 : TVectorD paramQ(3);
1052 0 : TVectorD paramT0(3);
1053 0 : TVectorD paramRMS(3);
1054 0 : TMatrixD dummy(3,3);
1055 : //calculate mean time for each sector and mean time for each side
1056 0 : TH1F hMeanTsec("hMeanTsec","hMeanTsec",20*(fLastTimeBin-fFirstTimeBin),fFirstTimeBin,fLastTimeBin);
1057 0 : fVMeanTimeSector.Zero();
1058 :
1059 0 : for (Int_t iSec=0; iSec<72; ++iSec){
1060 0 : TH2S *hT0 = GetHistoT0(iSec);
1061 0 : if (!hT0 ) continue;
1062 : //calculate sector mean T
1063 0 : if ( fHMeanTimeSector ){
1064 0 : Int_t nbinsT = fHMeanTimeSector->GetNbinsX();
1065 0 : Int_t offset = (nbinsT+2)*(iSec+1);
1066 0 : Float_t *arrP=fHMeanTimeSector->GetArray()+offset;
1067 : Int_t entries=0;
1068 0 : for ( Int_t i=0; i<nbinsT; i++ ) entries+=(Int_t)arrP[i+1];
1069 0 : hMeanTsec.Set(nbinsT+2,arrP);
1070 0 : hMeanTsec.SetEntries(entries);
1071 0 : paramT0.Zero();
1072 : // truncated mean: remove lower 5% and upper 5%
1073 0 : if ( entries>0 ) AliMathBase::TruncatedMean(&hMeanTsec,¶mT0,0.05,.95);
1074 0 : fVMeanTimeSector[iSec]=paramT0[1];
1075 0 : }
1076 :
1077 0 : AliTPCCalROC *rocQ = GetCalRocQ (iSec,kTRUE);
1078 0 : AliTPCCalROC *rocT0 = GetCalRocT0 (iSec,kTRUE);
1079 0 : AliTPCCalROC *rocRMS = GetCalRocRMS(iSec,kTRUE);
1080 0 : AliTPCCalROC *rocOut = GetCalRocOutliers(iSec,kTRUE);
1081 :
1082 0 : TH2S *hQ = GetHistoQ(iSec);
1083 0 : TH2S *hRMS = GetHistoRMS(iSec);
1084 :
1085 0 : Short_t *arrayhQ = hQ->GetArray();
1086 0 : Short_t *arrayhT0 = hT0->GetArray();
1087 0 : Short_t *arrayhRMS = hRMS->GetArray();
1088 :
1089 0 : UInt_t nChannels = fROC->GetNChannels(iSec);
1090 0 : Float_t meanTsec = fVMeanTimeSector[iSec];
1091 :
1092 : //debug
1093 0 : Int_t row=0;
1094 0 : Int_t pad=0;
1095 0 : Int_t padc=0;
1096 : //! debug
1097 :
1098 0 : for (UInt_t iChannel=0; iChannel<nChannels; ++iChannel){
1099 :
1100 0 : Float_t cogTime0 = -1000;
1101 0 : Float_t cogQ = -1000;
1102 0 : Float_t cogRMS = -1000;
1103 : Float_t cogOut = 0;
1104 :
1105 0 : Int_t offsetQ = (fNbinsQ+2)*(iChannel+1)+1;
1106 0 : Int_t offsetT0 = (fNbinsT0+2)*(iChannel+1)+1;
1107 0 : Int_t offsetRMS = (fNbinsRMS+2)*(iChannel+1)+1;
1108 : /*
1109 : AliMathBase::FitGaus(arrayhQ+offsetQ,fNbinsQ,fXminQ,fXmaxQ,¶mQ,&dummy);
1110 : AliMathBase::FitGaus(arrayhT0+offsetT0,fNbinsT0,fXminT0,fXmaxT0,¶mT0,&dummy);
1111 : AliMathBase::FitGaus(arrayhRMS+offsetRMS,fNbinsRMS,fXminRMS,fXmaxRMS,¶mRMS,&dummy);
1112 : cogQ = paramQ[1];
1113 : cogTime0 = paramT0[1];
1114 : cogRMS = paramRMS[1];
1115 : */
1116 0 : cogQ = AliMathBase::GetCOG(arrayhQ+offsetQ,fNbinsQ,fXminQ,fXmaxQ);
1117 0 : cogTime0 = AliMathBase::GetCOG(arrayhT0+offsetT0,fNbinsT0,fXminT0,fXmaxT0);
1118 0 : cogRMS = AliMathBase::GetCOG(arrayhRMS+offsetRMS,fNbinsRMS,fXminRMS,fXmaxRMS);
1119 :
1120 : /*
1121 : if ( (cogQ < ??) && (cogTime0 > ??) && (cogTime0<??) && ( cogRMS>??) ){
1122 : cogOut = 1;
1123 : cogTime0 = 0;
1124 : cogQ = 0;
1125 : cogRMS = 0;
1126 : }
1127 : */
1128 : // rocQ->SetValue(iChannel, cogQ*cogQ); // changed to linear scale again
1129 0 : rocQ->SetValue(iChannel, cogQ);
1130 0 : rocT0->SetValue(iChannel, cogTime0+meanTsec); //offset by mean time of the sector
1131 0 : rocRMS->SetValue(iChannel, cogRMS);
1132 0 : rocOut->SetValue(iChannel, cogOut);
1133 :
1134 : // in case a channel has no data set the value to 0
1135 0 : if (TMath::Abs(cogTime0-fXminT0)<1e-10){
1136 0 : rocQ->SetValue(iChannel, 0);
1137 0 : rocT0->SetValue(iChannel, 0); //offset by mean time of the sector
1138 0 : rocRMS->SetValue(iChannel, 0);
1139 0 : }
1140 :
1141 : //debug
1142 0 : if ( GetStreamLevel() > 2 ){
1143 0 : TTreeSRedirector *streamer=GetDebugStreamer();
1144 0 : if ( streamer ) {
1145 0 : while ( iChannel > (fROC->GetRowIndexes(iSec)[row]+fROC->GetNPads(iSec,row)-1) ) row++;
1146 0 : pad = iChannel-fROC->GetRowIndexes(iSec)[row];
1147 0 : padc = pad-(fROC->GetNPads(iSec,row)/2);
1148 :
1149 0 : (*streamer) << "DataEnd" <<
1150 0 : "Sector=" << iSec <<
1151 0 : "Pad=" << pad <<
1152 0 : "PadC=" << padc <<
1153 0 : "Row=" << row <<
1154 0 : "PadSec=" << iChannel <<
1155 0 : "Q=" << cogQ <<
1156 0 : "T0=" << cogTime0 <<
1157 0 : "RMS=" << cogRMS <<
1158 : "\n";
1159 : }
1160 0 : }
1161 : //! debug
1162 0 : }
1163 :
1164 :
1165 0 : }
1166 0 : }
1167 : //_____________________________________________________________________
1168 : //_________________________ Test Functions ___________________________
1169 : //_____________________________________________________________________
1170 : TObjArray* AliTPCCalibPulser::TestBinning()
1171 : {
1172 : /// Function to test the binning of the reference histograms
1173 : /// type: T0, Q or RMS
1174 : /// mode: 0 - number of filled bins per channel
1175 : /// 1 - number of empty bins between filled bins in one ROC
1176 : /// returns TObjArray with the test histograms type*2+mode:
1177 : /// position 0 = T0,0 ; 1 = T0,1 ; 2 = Q,0 ...
1178 :
1179 :
1180 0 : TObjArray *histArray = new TObjArray(6);
1181 0 : const Char_t *type[] = {"T0","Q","RMS"};
1182 0 : Int_t fNbins[3] = {fNbinsT0,fNbinsQ,fNbinsRMS};
1183 :
1184 0 : for (Int_t itype = 0; itype<3; ++itype){
1185 0 : for (Int_t imode=0; imode<2; ++imode){
1186 0 : Int_t icount = itype*2+imode;
1187 0 : histArray->AddAt(new TH1F(Form("hTestBinning%s%d",type[itype],imode),
1188 0 : Form("Test Binning of '%s', mode - %d",type[itype],imode),
1189 : 72,0,72),
1190 : icount);
1191 : }
1192 : }
1193 :
1194 :
1195 : TH2S *hRef=0x0;
1196 : Short_t *array=0x0;
1197 0 : for (Int_t itype = 0; itype<3; ++itype){
1198 0 : for (Int_t iSec=0; iSec<72; ++iSec){
1199 0 : if ( itype == 0 ) hRef = GetHistoT0(iSec);
1200 0 : if ( itype == 1 ) hRef = GetHistoQ(iSec);
1201 0 : if ( itype == 2 ) hRef = GetHistoRMS(iSec);
1202 0 : if ( hRef == 0x0 ) continue;
1203 0 : array = (hRef->GetArray());
1204 0 : UInt_t nChannels = fROC->GetNChannels(iSec);
1205 :
1206 : Int_t nempty=0;
1207 0 : for (UInt_t iChannel=0; iChannel<nChannels; ++iChannel){
1208 : Int_t nfilled=0;
1209 0 : Int_t offset = (fNbins[itype]+2)*(iChannel+1)+1;
1210 : Int_t c1 = 0;
1211 : Int_t c2 = 0;
1212 0 : for (Int_t iBin=0; iBin<fNbins[itype]; ++iBin){
1213 0 : if ( array[offset+iBin]>0 ) {
1214 0 : nfilled++;
1215 0 : if ( c1 && c2 ) nempty++;
1216 : else c1 = 1;
1217 : }
1218 0 : else if ( c1 ) c2 = 1;
1219 :
1220 : }
1221 0 : ((TH1F*)histArray->At(itype*2))->Fill(nfilled);
1222 : }
1223 0 : ((TH1F*)histArray->At(itype*2+1))->Fill(iSec,nempty);
1224 0 : }
1225 : }
1226 0 : return histArray;
1227 0 : }
|