]> git.uio.no Git - u/mrichter/AliRoot.git/blame - TPC/AliTPCdataQA.cxx
Option to switch on the Altro emulator
[u/mrichter/AliRoot.git] / TPC / AliTPCdataQA.cxx
CommitLineData
0ffacf98 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
17/* $Id$ */
18
266f8637 19/*
1267cf3a 20 June 2010
21
22 This update should solve two problems mainly:
23 * The vs event histograms have been limited to a fixed size for the
24 DQM. The 500k seemed to be a big size but is no longer so, so we
25 need to dynamically expand the range. The non-trivial point is that
26 we also have to do it for the copy owned by AliTPCQADataMakerRec.
27 * The amoreGui now remembers the x-range of the first visualization so
28 the trick of setting the relevant event range as the histogram is
29 filled no longer works.
30
31 The fix is a bit crude but avoids creating a new histogram. Instead
32 the range is expanded (max events and events per bin is doubled) but
33 the number of bins is kept constant! In this way we can change just
34 double the max of the X-axis of the hist and rebin the data. The
35 same can easily be done for the copy owned by AliTPCQADataMakerRec.
36
37 CAUTION:
38 If we change the number of bins we could crash the whole system
39 because ROOT does not create space for extra bins! (but we do not do
40 this). In that way it is a crude solution.
41 The rebinning in the code only works for an even number of bins.
42
43 In addition to the above a bug in the reading of the config file was
44 also found and corrected. fAdcMax was set instead of fEventsPerBin.
45
46 Finally cout was changes to AliInfo.
47
266f8637 48 February 2008
49
50 The code has been heavily modified so that now the RAW data is
51 "expanded" for each sector and stored in a big signal array. Then a
52 simple version of the code in AliTPCclustererMI is used to identify
53 the local maxima and these are then used for QA. This gives a better
54 estimate of the charge (both max and total) and also limits the
55 effect of noise.
56
57 Implementation:
58
59 In Update the RAW signals >= 3 ADC channels are stored in the arrays.
60
61 There are 3 arrays:
62 Float_t** fAllBins 2d array [row][bin(pad, time)] ADC signal
63 Int_t** fAllSigBins 2d array [row][signal#] bin(with signal)
64 Int_t* fAllNSigBins; 1d array [row] Nsignals
65
66 This is done sector by sector.
67
68 When data from a new sector is encountered, the method
69 FindLocalMaxima is called on the data from the previous sector, and
70 the calibration/data objects are updated with the "cluster"
71 info. Finally the arrays are cleared.
72
73 The requirements for a local maxima is:
74 Charge in bin is >= 5 ADC channels.
75 Charge in bin is larger than all the 8 neighboring bins.
76 At least one of the two pad neighbors has a signal.
77 At least one of the two time neighbors has a signal.
78
79 Before accessing the data it is expected that the Analyse method is
80 called. This normalizes some of the data objects to per event or per
81 cluster.
82 If more data is passed to the class after Analyse has been called
83 the normalization is reversed and Analyse has to be called again.
84*/
85
0ffacf98 86
87//Root includes
88#include <TH1F.h>
89#include <TH2F.h>
90#include <TString.h>
91#include <TMath.h>
0ffacf98 92#include <TDirectory.h>
93#include <TFile.h>
266f8637 94#include <TError.h>
ac940b58 95#include <TMap.h>
6a50ff96 96#include <TProfile.h>
0ffacf98 97//AliRoot includes
98#include "AliRawReader.h"
99#include "AliRawReaderRoot.h"
100#include "AliRawReaderDate.h"
101#include "AliTPCRawStream.h"
0c25417d 102#include "AliTPCRawStreamV3.h"
0ffacf98 103#include "AliTPCCalROC.h"
104#include "AliTPCROC.h"
105#include "AliMathBase.h"
106#include "TTreeStream.h"
107#include "AliTPCRawStreamFast.h"
108
109//date
110#include "event.h"
111#include "AliTPCCalPad.h"
258cd111 112#include "AliTPCPreprocessorOnline.h"
0ffacf98 113
114//header file
115#include "AliTPCdataQA.h"
ce0175fa 116#include "AliLog.h"
0ffacf98 117
0ffacf98 118ClassImp(AliTPCdataQA)
119
336156cc 120AliTPCdataQA::AliTPCdataQA() : /*FOLD00*/
0ffacf98 121 fFirstTimeBin(60),
122 fLastTimeBin(1000),
123 fAdcMin(1),
124 fAdcMax(100),
0ffacf98 125 fMapping(NULL),
f11b3071 126 fPedestal(0),
127 fNoise(0),
266f8637 128 fNLocalMaxima(0),
0ffacf98 129 fMaxCharge(0),
f11b3071 130 fMeanCharge(0),
131 fNoThreshold(0),
266f8637 132 fNTimeBins(0),
133 fNPads(0),
134 fTimePosition(0),
c94a79e1 135 fOverThreshold10(0),
136 fOverThreshold20(0),
137 fOverThreshold30(0),
23c9ab21 138 fHistQVsTimeSideA(0),
139 fHistQVsTimeSideC(0),
140 fHistQMaxVsTimeSideA(0),
141 fHistQMaxVsTimeSideC(0),
ce0175fa 142 fHistOccupancyVsEvent(0),
143 fHistNclustersVsEvent(0),
266f8637 144 fEventCounter(0),
145 fIsAnalysed(kFALSE),
ce0175fa 146 fMaxEvents(500000), // Max events for event histograms
147 fEventsPerBin(1000), // Events per bin for event histograms
148 fSignalCounter(0), // Signal counter
149 fClusterCounter(0), // Cluster counter
266f8637 150 fAllBins(0),
151 fAllSigBins(0),
152 fAllNSigBins(0),
153 fRowsMax(0),
154 fPadsMax(0),
155 fTimeBinsMax(0)
0ffacf98 156{
157 //
158 // default constructor
159 //
160}
161
57acd2d2 162//_____________________________________________________________________
163AliTPCdataQA::AliTPCdataQA(AliRecoParam::EventSpecie_t es) :
164fFirstTimeBin(60),
165fLastTimeBin(1000),
166fAdcMin(1),
167fAdcMax(100),
168fMapping(NULL),
169fPedestal(0),
170fNoise(0),
171fNLocalMaxima(0),
172fMaxCharge(0),
173fMeanCharge(0),
174fNoThreshold(0),
175fNTimeBins(0),
176fNPads(0),
177fTimePosition(0),
178fOverThreshold10(0),
179fOverThreshold20(0),
180fOverThreshold30(0),
23c9ab21 181fHistQVsTimeSideA(0),
182fHistQVsTimeSideC(0),
183fHistQMaxVsTimeSideA(0),
184fHistQMaxVsTimeSideC(0),
ce0175fa 185fHistOccupancyVsEvent(0),
186fHistNclustersVsEvent(0),
57acd2d2 187fEventCounter(0),
188fIsAnalysed(kFALSE),
ce0175fa 189fMaxEvents(500000),
190fEventsPerBin(1000),
191fSignalCounter(0),
192fClusterCounter(0),
57acd2d2 193fAllBins(0),
194fAllSigBins(0),
195fAllNSigBins(0),
196fRowsMax(0),
197fPadsMax(0),
198fTimeBinsMax(0)
199{
200// ctor creating the histogram
201 char * name = Form("TPCRAW_%s", AliRecoParam::GetEventSpecieName(es)) ;
202 TH1F(name, name,100,0,100) ;
203}
0ffacf98 204
205//_____________________________________________________________________
206AliTPCdataQA::AliTPCdataQA(const AliTPCdataQA &ped) : /*FOLD00*/
336156cc 207 TH1F(ped),
0ffacf98 208 fFirstTimeBin(ped.GetFirstTimeBin()),
209 fLastTimeBin(ped.GetLastTimeBin()),
210 fAdcMin(ped.GetAdcMin()),
211 fAdcMax(ped.GetAdcMax()),
266f8637 212 fMapping(NULL),
213 fPedestal(0),
214 fNoise(0),
215 fNLocalMaxima(0),
216 fMaxCharge(0),
217 fMeanCharge(0),
218 fNoThreshold(0),
266f8637 219 fNTimeBins(0),
220 fNPads(0),
221 fTimePosition(0),
c94a79e1 222 fOverThreshold10(0),
223 fOverThreshold20(0),
224 fOverThreshold30(0),
23c9ab21 225 fHistQVsTimeSideA(0),
226 fHistQVsTimeSideC(0),
227 fHistQMaxVsTimeSideA(0),
228 fHistQMaxVsTimeSideC(0),
ce0175fa 229 fHistOccupancyVsEvent(0),
230 fHistNclustersVsEvent(0),
266f8637 231 fEventCounter(ped.GetEventCounter()),
232 fIsAnalysed(ped.GetIsAnalysed()),
ce0175fa 233 fMaxEvents(ped.GetMaxEvents()),
234 fEventsPerBin(ped.GetEventsPerBin()),
235 fSignalCounter(ped.GetSignalCounter()),
236 fClusterCounter(ped.GetClusterCounter()),
266f8637 237 fAllBins(0),
238 fAllSigBins(0),
239 fAllNSigBins(0),
240 fRowsMax(0),
241 fPadsMax(0),
242 fTimeBinsMax(0)
0ffacf98 243{
244 //
245 // copy constructor
246 //
266f8637 247 if(ped.GetNLocalMaxima())
248 fNLocalMaxima = new AliTPCCalPad(*ped.GetNLocalMaxima());
249 if(ped.GetMaxCharge())
250 fMaxCharge = new AliTPCCalPad(*ped.GetMaxCharge());
251 if(ped.GetMeanCharge())
252 fMeanCharge = new AliTPCCalPad(*ped.GetMeanCharge());
253 if(ped.GetNoThreshold())
254 fNoThreshold = new AliTPCCalPad(*ped.GetNoThreshold());
255 if(ped.GetNTimeBins())
256 fNTimeBins = new AliTPCCalPad(*ped.GetNTimeBins());
257 if(ped.GetNPads())
258 fNPads = new AliTPCCalPad(*ped.GetNPads());
259 if(ped.GetTimePosition())
260 fTimePosition = new AliTPCCalPad(*ped.GetTimePosition());
261 if(ped.GetOverThreshold10())
262 fOverThreshold10 = new AliTPCCalPad(*ped.GetOverThreshold10());
263 if(ped.GetOverThreshold20())
264 fOverThreshold20 = new AliTPCCalPad(*ped.GetOverThreshold20());
265 if(ped.GetOverThreshold30())
266 fOverThreshold30 = new AliTPCCalPad(*ped.GetOverThreshold30());
1cb9ffdb 267 if(ped.GetHistQVsTimeSideA()) {
23c9ab21 268 fHistQVsTimeSideA = new TProfile(*ped.GetHistQVsTimeSideA());
1cb9ffdb 269 fHistQVsTimeSideA->SetDirectory(0);
270 }
271 if(ped.GetHistQVsTimeSideC()) {
23c9ab21 272 fHistQVsTimeSideC = new TProfile(*ped.GetHistQVsTimeSideC());
1cb9ffdb 273 fHistQVsTimeSideC->SetDirectory(0);
274 }
275 if(ped.GetHistQMaxVsTimeSideA()) {
23c9ab21 276 fHistQMaxVsTimeSideA = new TProfile(*ped.GetHistQMaxVsTimeSideA());
1cb9ffdb 277 fHistQMaxVsTimeSideA->SetDirectory(0);
278 }
279 if(ped.GetHistQMaxVsTimeSideC()) {
23c9ab21 280 fHistQMaxVsTimeSideC = new TProfile(*ped.GetHistQMaxVsTimeSideC());
1cb9ffdb 281 fHistQMaxVsTimeSideC->SetDirectory(0);
282 }
ce0175fa 283 if(ped.GetHistOccupancyVsEventConst()) {
284 fHistOccupancyVsEvent = new TH1F(*ped.GetHistOccupancyVsEventConst());
285 fHistOccupancyVsEvent->SetDirectory(0);
286 }
287 if(ped.GetHistNclustersVsEventConst()) {
288 fHistNclustersVsEvent = new TH1F(*ped.GetHistNclustersVsEventConst());
289 fHistNclustersVsEvent->SetDirectory(0);
290 }
0ffacf98 291}
292
ac940b58 293//_____________________________________________________________________
8ba97cc8 294AliTPCdataQA::AliTPCdataQA(const TMap *config) : /*FOLD00*/
ac940b58 295 TH1F("TPCRAW","TPCRAW",100,0,100),
296 fFirstTimeBin(60),
297 fLastTimeBin(1000),
298 fAdcMin(1),
299 fAdcMax(100),
300 fMapping(NULL),
301 fPedestal(0),
302 fNoise(0),
303 fNLocalMaxima(0),
304 fMaxCharge(0),
305 fMeanCharge(0),
306 fNoThreshold(0),
307 fNTimeBins(0),
308 fNPads(0),
309 fTimePosition(0),
310 fOverThreshold10(0),
311 fOverThreshold20(0),
312 fOverThreshold30(0),
23c9ab21 313 fHistQVsTimeSideA(0),
314 fHistQVsTimeSideC(0),
315 fHistQMaxVsTimeSideA(0),
316 fHistQMaxVsTimeSideC(0),
ce0175fa 317 fHistOccupancyVsEvent(0),
318 fHistNclustersVsEvent(0),
ac940b58 319 fEventCounter(0),
320 fIsAnalysed(kFALSE),
ce0175fa 321 fMaxEvents(500000),
322 fEventsPerBin(1000),
323 fSignalCounter(0),
324 fClusterCounter(0),
ac940b58 325 fAllBins(0),
326 fAllSigBins(0),
327 fAllNSigBins(0),
328 fRowsMax(0),
329 fPadsMax(0),
330 fTimeBinsMax(0)
331{
332 //
333 // default constructor
334 //
335 if (config->GetValue("FirstTimeBin")) fFirstTimeBin = ((TObjString*)config->GetValue("FirstTimeBin"))->GetString().Atoi();
336 if (config->GetValue("LastTimeBin")) fLastTimeBin = ((TObjString*)config->GetValue("LastTimeBin"))->GetString().Atoi();
337 if (config->GetValue("AdcMin")) fAdcMin = ((TObjString*)config->GetValue("AdcMin"))->GetString().Atoi();
338 if (config->GetValue("AdcMax")) fAdcMax = ((TObjString*)config->GetValue("AdcMax"))->GetString().Atoi();
ce0175fa 339 if (config->GetValue("MaxEvents")) fMaxEvents = ((TObjString*)config->GetValue("MaxEvents"))->GetString().Atoi();
1267cf3a 340 if (config->GetValue("EventsPerBin")) fEventsPerBin = ((TObjString*)config->GetValue("EventsPerBin"))->GetString().Atoi();
ac940b58 341}
0ffacf98 342
343//_____________________________________________________________________
344AliTPCdataQA& AliTPCdataQA::operator = (const AliTPCdataQA &source)
345{
346 //
347 // assignment operator
348 //
349 if (&source == this) return *this;
350 new (this) AliTPCdataQA(source);
351
352 return *this;
353}
354
355
356//_____________________________________________________________________
357AliTPCdataQA::~AliTPCdataQA() /*FOLD00*/
358{
359 //
360 // destructor
361 //
362
363 // do not delete fMapping, because we do not own it.
266f8637 364 // do not delete fMapping, because we do not own it.
365 // do not delete fNoise and fPedestal, because we do not own them.
366
367 delete fNLocalMaxima;
368 delete fMaxCharge;
369 delete fMeanCharge;
370 delete fNoThreshold;
371 delete fNTimeBins;
372 delete fNPads;
373 delete fTimePosition;
374 delete fOverThreshold10;
375 delete fOverThreshold20;
376 delete fOverThreshold30;
23c9ab21 377 delete fHistQVsTimeSideA;
378 delete fHistQVsTimeSideC;
379 delete fHistQMaxVsTimeSideA;
380 delete fHistQMaxVsTimeSideC;
ce0175fa 381 delete fHistOccupancyVsEvent;
382 delete fHistNclustersVsEvent;
266f8637 383
384 for (Int_t iRow = 0; iRow < fRowsMax; iRow++) {
385 delete [] fAllBins[iRow];
386 delete [] fAllSigBins[iRow];
387 }
388 delete [] fAllBins;
389 delete [] fAllSigBins;
390 delete [] fAllNSigBins;
0ffacf98 391}
ce0175fa 392
393//_____________________________________________________________________
394TH1F* AliTPCdataQA::GetHistOccupancyVsEvent()
395{
396 //
397 // Create Occupancy vs event histogram
398 // (we create this histogram differently then the other histograms
399 // because this we want to be able to access and copy
400 // from AliTPCQAMakerRec before it normally would be created)
401 //
402 if(!fHistOccupancyVsEvent) {
403
404 Int_t nBins = fMaxEvents/fEventsPerBin;
405 fHistOccupancyVsEvent = new TH1F("hOccupancyVsEvent", "Occupancy vs event number (~time); Event number; Occupancy", nBins, 0, nBins*fEventsPerBin);
406 fHistOccupancyVsEvent->SetDirectory(0);
ce0175fa 407 }
408
409 return fHistOccupancyVsEvent;
410}
411
412//_____________________________________________________________________
413TH1F* AliTPCdataQA::GetHistNclustersVsEvent()
414{
415 //
416 // Create Nclusters vs event histogram
417 // (we create this histogram differently then the other histograms
418 // because this we want to be able to access and copy
419 // from AliTPCQAMakerRec before it normally would be created)
420 //
421 if(!fHistNclustersVsEvent) {
422
423 Int_t nBins = fMaxEvents/fEventsPerBin;
424 fHistNclustersVsEvent = new TH1F("hNclustersVsEvent", "Nclusters vs event number (~time); Event number; Nclusters per event", nBins, 0, nBins*fEventsPerBin);
425 fHistNclustersVsEvent->SetDirectory(0);
ce0175fa 426 }
427
428 return fHistNclustersVsEvent;
429}
430
431//_____________________________________________________________________
432void AliTPCdataQA::UpdateEventHistograms()
433{
434 // Update histograms that display occupancy and
435 // number of clusters as a function of number of
436 // events
437 if (!fHistOccupancyVsEvent)
438 GetHistOccupancyVsEvent();
439 if (!fHistNclustersVsEvent)
440 GetHistNclustersVsEvent();
441
1267cf3a 442 if(fEventCounter > fMaxEvents) {
443
444 // we have to expand the histogram to handle the larger number of
445 // events. The way it is done now is to double the range and the
446 // number of events per bin (so the number of histogram bins stays
447 // constant)
448 fEventsPerBin *= 2;
449 fMaxEvents *= 2;
450
451 // Change histogram limits
452 const Int_t nBins = fHistOccupancyVsEvent->GetXaxis()->GetNbins();
453 fHistOccupancyVsEvent->GetXaxis()->Set(nBins, fHistOccupancyVsEvent->GetXaxis()->GetNbins(), fMaxEvents);
454 fHistNclustersVsEvent->GetXaxis()->Set(nBins, fHistNclustersVsEvent->GetXaxis()->GetNbins(), fMaxEvents);
455
456 // Rebin the histogram
457 for(Int_t bin = 1; bin <= nBins; bin+=2) {
458
459 Int_t newBin = TMath::Nint(Float_t(bin+1)/2.0);
460 Float_t newContent = (fHistOccupancyVsEvent->GetBinContent(bin)+
461 fHistOccupancyVsEvent->GetBinContent(bin+1))/2.0;
462 fHistOccupancyVsEvent->SetBinContent(newBin, newContent);
463
464 newContent = (fHistNclustersVsEvent->GetBinContent(bin)+
465 fHistNclustersVsEvent->GetBinContent(bin+1))/2.0;
466 fHistNclustersVsEvent->SetBinContent(newBin, newContent);
467 }
468
469 // Set the remaining bins to 0
470 Int_t lastHalf = nBins/2 +1;
471 for(Int_t bin = lastHalf; bin <= nBins; bin++) {
472
473 fHistOccupancyVsEvent->SetBinContent(bin, 0);
474 fHistNclustersVsEvent->SetBinContent(bin, 0);
475 }
476
477 // In this case we should nut update but wait untill the new
478 // number of events per bin is reached!
479 return;
480 }
481
482 const Int_t bin = TMath::Nint(Float_t(fEventCounter)/fEventsPerBin);
483
ce0175fa 484 Float_t averageOccupancy =
485 Float_t(fSignalCounter)/fEventsPerBin/(fLastTimeBin - fFirstTimeBin +1.0)
1267cf3a 486 / 570132.0; // 570,132 is number of pads
487 fHistOccupancyVsEvent->SetBinContent(bin, averageOccupancy);
ce0175fa 488 fSignalCounter = 0;
489
490 Float_t averageNclusters =
491 Float_t(fClusterCounter)/fEventsPerBin;
1267cf3a 492 fHistNclustersVsEvent->SetBinContent(bin, averageNclusters);
ce0175fa 493 fClusterCounter = 0;
494}
495
0c25417d 496//_____________________________________________________________________
6a50ff96 497Bool_t AliTPCdataQA::ProcessEvent(AliTPCRawStreamV3 *const rawStreamV3)
0c25417d 498{
499 //
500 // Event Processing loop - AliTPCRawStreamV3
501 //
502 Bool_t withInput = kFALSE;
503 Int_t nSignals = 0;
504 Int_t lastSector = -1;
505
506 while ( rawStreamV3->NextDDL() ){
1267cf3a 507
0c25417d 508 while ( rawStreamV3->NextChannel() ){
1267cf3a 509
0c25417d 510 Int_t iSector = rawStreamV3->GetSector(); // current sector
511 Int_t iRow = rawStreamV3->GetRow(); // current row
512 Int_t iPad = rawStreamV3->GetPad(); // current pad
513 if (iRow<0 || iPad<0) continue;
514 // Call local maxima finder if the data is in a new sector
515 if(iSector != lastSector) {
516
517 if(nSignals>0)
518 FindLocalMaxima(lastSector);
519
520 CleanArrays();
521 lastSector = iSector;
522 nSignals = 0;
523 }
524
525 while ( rawStreamV3->NextBunch() ){
1267cf3a 526
0c25417d 527 Int_t startTbin = (Int_t)rawStreamV3->GetStartTimeBin();
528 Int_t bunchlength = (Int_t)rawStreamV3->GetBunchLength();
529 const UShort_t *sig = rawStreamV3->GetSignals();
530
531 for (Int_t iTimeBin = 0; iTimeBin<bunchlength; iTimeBin++){
532 Float_t signal=(Float_t)sig[iTimeBin];
533 nSignals += Update(iSector,iRow,iPad,startTbin--,signal);
534 withInput = kTRUE;
535 }
536 }
537 }
538 }
1267cf3a 539
540 if (lastSector>=0&&nSignals>0)
0c25417d 541 FindLocalMaxima(lastSector);
542
543 return withInput;
544}
545
546//_____________________________________________________________________
6a50ff96 547Bool_t AliTPCdataQA::ProcessEvent(AliRawReader *const rawReader)
0c25417d 548{
549 //
550 // Event processing loop - AliRawReader
551 //
c75ba816 552 AliTPCRawStreamV3 rawStreamV3(rawReader, (AliAltroMapping**)fMapping);
553 Bool_t res=ProcessEvent(&rawStreamV3);
ce0175fa 554 if(res) {
0c25417d 555 fEventCounter++; // only increment event counter if there is TPC data
ce0175fa 556
1267cf3a 557 if(fEventCounter%fEventsPerBin==0)
ce0175fa 558 UpdateEventHistograms();
559 }
0c25417d 560 return res;
561}
0ffacf98 562
0ffacf98 563//_____________________________________________________________________
6a50ff96 564Bool_t AliTPCdataQA::ProcessEventFast(AliTPCRawStreamFast *const rawStreamFast)
0ffacf98 565{
566 //
567 // Event Processing loop - AliTPCRawStream
568 //
569 Bool_t withInput = kFALSE;
266f8637 570 Int_t nSignals = 0;
571 Int_t lastSector = -1;
0ffacf98 572
573 while ( rawStreamFast->NextDDL() ){
0c25417d 574 while ( rawStreamFast->NextChannel() ){
575
576 Int_t iSector = rawStreamFast->GetSector(); // current sector
577 Int_t iRow = rawStreamFast->GetRow(); // current row
578 Int_t iPad = rawStreamFast->GetPad(); // current pad
579 // Call local maxima finder if the data is in a new sector
580 if(iSector != lastSector) {
581
582 if(nSignals>0)
583 FindLocalMaxima(lastSector);
584
585 CleanArrays();
586 lastSector = iSector;
587 nSignals = 0;
0ffacf98 588 }
0c25417d 589
590 while ( rawStreamFast->NextBunch() ){
591 Int_t startTbin = (Int_t)rawStreamFast->GetStartTimeBin();
592 Int_t endTbin = (Int_t)rawStreamFast->GetEndTimeBin();
593
594 for (Int_t iTimeBin = startTbin; iTimeBin < endTbin; iTimeBin++){
595 Float_t signal = rawStreamFast->GetSignals()[iTimeBin-startTbin];
596 nSignals += Update(iSector,iRow,iPad,iTimeBin+1,signal);
597 withInput = kTRUE;
598 }
599 }
600 }
0ffacf98 601 }
266f8637 602
0ffacf98 603 return withInput;
604}
605//_____________________________________________________________________
6a50ff96 606Bool_t AliTPCdataQA::ProcessEventFast(AliRawReader *const rawReader)
0ffacf98 607{
608 //
609 // Event processing loop - AliRawReader
610 //
c75ba816 611 AliTPCRawStreamFast rawStreamFast(rawReader, (AliAltroMapping**)fMapping);
612 Bool_t res=ProcessEventFast(&rawStreamFast);
c75bf2f1 613 if(res)
614 fEventCounter++; // only increment event counter if there is TPC data
615 // otherwise Analyse (called in QA) fails
616
0ffacf98 617 return res;
618}
619
620//_____________________________________________________________________
6a50ff96 621Bool_t AliTPCdataQA::ProcessEvent(AliTPCRawStream *const rawStream)
0ffacf98 622{
623 //
624 // Event Processing loop - AliTPCRawStream
625 //
626
0ffacf98 627 Bool_t withInput = kFALSE;
266f8637 628 Int_t nSignals = 0;
629 Int_t lastSector = -1;
0ffacf98 630
631 while (rawStream->Next()) {
632
633 Int_t iSector = rawStream->GetSector(); // current ROC
634 Int_t iRow = rawStream->GetRow(); // current row
635 Int_t iPad = rawStream->GetPad(); // current pad
636 Int_t iTimeBin = rawStream->GetTime(); // current time bin
637 Float_t signal = rawStream->GetSignal(); // current ADC signal
0c25417d 638
266f8637 639 // Call local maxima finder if the data is in a new sector
640 if(iSector != lastSector) {
641
642 if(nSignals>0)
0c25417d 643 FindLocalMaxima(lastSector);
266f8637 644
645 CleanArrays();
646 lastSector = iSector;
647 nSignals = 0;
648 }
0ffacf98 649
266f8637 650 // Sometimes iRow==-1 if there is problems to read the data
651 if(iRow>=0) {
652 nSignals += Update(iSector,iRow,iPad,iTimeBin,signal);
653 withInput = kTRUE;
654 }
0ffacf98 655 }
656
0c25417d 657 if (lastSector>=0&&nSignals>0)
658 FindLocalMaxima(lastSector);
659
0ffacf98 660 return withInput;
661}
662
663
664//_____________________________________________________________________
6a50ff96 665Bool_t AliTPCdataQA::ProcessEventOld(AliRawReader *const rawReader)
0ffacf98 666{
667 //
668 // Event processing loop - AliRawReader
669 //
670
671 // if fMapping is NULL the rawstream will crate its own mapping
672 AliTPCRawStream rawStream(rawReader, (AliAltroMapping**)fMapping);
673 rawReader->Select("TPC");
c75bf2f1 674 Bool_t res = ProcessEvent(&rawStream);
675
676 if(res)
677 fEventCounter++; // only increment event counter if there is TPC data
678 // otherwise Analyse (called in QA) fails
679 return res;
0ffacf98 680}
681
682
683//_____________________________________________________________________
6a50ff96 684Bool_t AliTPCdataQA::ProcessEvent(eventHeaderStruct *const event)
0ffacf98 685{
686 //
687 // process date event
688 //
689
c75ba816 690 AliRawReaderDate rawReader((void*)event);
691 Bool_t result=ProcessEvent(&rawReader);
0ffacf98 692 return result;
693}
694
695
696
697//_____________________________________________________________________
698void AliTPCdataQA::DumpToFile(const Char_t *filename, const Char_t *dir, Bool_t append) /*FOLD00*/
699{
700 //
701 // Write class to file
702 //
703
704 TString sDir(dir);
705 TString option;
706
707 if ( append )
708 option = "update";
709 else
710 option = "recreate";
711
712 TDirectory *backup = gDirectory;
713 TFile f(filename,option.Data());
714 f.cd();
715 if ( !sDir.IsNull() ){
716 f.mkdir(sDir.Data());
717 f.cd(sDir);
718 }
719 this->Write();
720 f.Close();
721
722 if ( backup ) backup->cd();
723}
724
725
726//_____________________________________________________________________
266f8637 727Int_t AliTPCdataQA::Update(const Int_t iSector, /*FOLD00*/
728 const Int_t iRow,
729 const Int_t iPad,
730 const Int_t iTimeBin,
731 Float_t signal)
0ffacf98 732{
733 //
734 // Signal filling method
735 //
266f8637 736
737 //
738 // Define the calibration objects the first time Update is called
739 // NB! This has to be done first even if the data is rejected by the time
740 // cut to make sure that the objects are available in Analyse
741 //
742 if (!fNLocalMaxima) fNLocalMaxima = new AliTPCCalPad("NLocalMaxima","NLocalMaxima");
0ffacf98 743 if (!fMaxCharge) fMaxCharge = new AliTPCCalPad("MaxCharge","MaxCharge");
f11b3071 744 if (!fMeanCharge) fMeanCharge = new AliTPCCalPad("MeanCharge","MeanCharge");
745 if (!fNoThreshold) fNoThreshold = new AliTPCCalPad("NoThreshold","NoThreshold");
266f8637 746 if (!fNTimeBins) fNTimeBins = new AliTPCCalPad("NTimeBins","NTimeBins");
747 if (!fNPads) fNPads = new AliTPCCalPad("NPads","NPads");
748 if (!fTimePosition) fTimePosition = new AliTPCCalPad("TimePosition","TimePosition");
0ffacf98 749 if (!fOverThreshold10) fOverThreshold10 = new AliTPCCalPad("OverThreshold10","OverThreshold10");
750 if (!fOverThreshold20) fOverThreshold20 = new AliTPCCalPad("OverThreshold20","OverThreshold20");
751 if (!fOverThreshold30) fOverThreshold30 = new AliTPCCalPad("OverThreshold30","OverThreshold30");
1cb9ffdb 752 if (!fHistQVsTimeSideA) {
23c9ab21 753 fHistQVsTimeSideA = new TProfile("hQVsTimeSideA", "Q vs time (side A); Time [Timebin]; Q [ADC ch]", 100, 0, 1000);
1cb9ffdb 754 fHistQVsTimeSideA->SetDirectory(0);
755 }
756 if (!fHistQVsTimeSideC) {
23c9ab21 757 fHistQVsTimeSideC = new TProfile("hQVsTimeSideC", "Q vs time (side C); Time [Timebin]; Q [ADC ch]", 100, 0, 1000);
1cb9ffdb 758 fHistQVsTimeSideC->SetDirectory(0);
759 }
760 if (!fHistQMaxVsTimeSideA) {
23c9ab21 761 fHistQMaxVsTimeSideA = new TProfile("hQMaxVsTimeSideA", "Q_{MAX} vs time (side A); Time [Timebin]; Q_{MAX} [ADC ch]", 100, 0, 1000);
1cb9ffdb 762 fHistQMaxVsTimeSideA->SetDirectory(0);
763 }
764 if (!fHistQMaxVsTimeSideC) {
23c9ab21 765 fHistQMaxVsTimeSideC = new TProfile("hQMaxVsTimeSideC", "Q_{MAX} vs time (side C); Time [Timebin]; Q_{MAX} [ADC ch]", 100, 0, 1000);
1cb9ffdb 766 fHistQMaxVsTimeSideC->SetDirectory(0);
767 }
768
266f8637 769 // Make the arrays for expanding the data
f11b3071 770
266f8637 771 if (!fAllBins)
772 MakeArrays();
773
774 //
775 // If Analyse has been previously called we need now to denormalize the data
776 // as more data is coming
777 //
778 if(fIsAnalysed == kTRUE) {
779
780 const Int_t nTimeBins = fLastTimeBin - fFirstTimeBin +1;
781 const Float_t denormalization = Float_t(fEventCounter * nTimeBins);
782 fNoThreshold->Multiply(denormalization);
783
784 fMeanCharge->Multiply(fNLocalMaxima);
785 fMaxCharge->Multiply(fNLocalMaxima);
786 fNTimeBins->Multiply(fNLocalMaxima);
787 fNPads->Multiply(fNLocalMaxima);
788 fTimePosition->Multiply(fNLocalMaxima);
789 fIsAnalysed = kFALSE;
790 }
f11b3071 791
266f8637 792 //
793 // TimeBin cut
794 //
795 if (iTimeBin<fFirstTimeBin) return 0;
796 if (iTimeBin>fLastTimeBin) return 0;
797
f11b3071 798 // if pedestal calibrations are loaded subtract pedestals
799 if(fPedestal) {
800
266f8637 801 Float_t ped = fPedestal->GetCalROC(iSector)->GetValue(iRow, iPad);
802 // Don't use data from pads where pedestals are abnormally small or large
803 if(ped<10 || ped>90)
f11b3071 804 return 0;
266f8637 805 signal -= ped;
f11b3071 806 }
266f8637 807
808 // In fNoThreshold we fill all data to estimate the ZS volume
809 Float_t count = fNoThreshold->GetCalROC(iSector)->GetValue(iRow, iPad);
810 fNoThreshold->GetCalROC(iSector)->SetValue(iRow, iPad,count+1);
811
f11b3071 812 // Require at least 3 ADC channels
266f8637 813 if (signal < 3.0)
f11b3071 814 return 0;
815
816 // if noise calibrations are loaded require at least 3*sigmaNoise
817 if(fNoise) {
266f8637 818
819 Float_t noise = fNoise->GetCalROC(iSector)->GetValue(iRow, iPad);
820
821 if(signal < noise*3.0)
f11b3071 822 return 0;
823 }
266f8637 824
f11b3071 825 //
266f8637 826 // This signal is ok and we store it in the cluster map
0ffacf98 827 //
f11b3071 828
266f8637 829 SetExpandDigit(iRow, iPad, iTimeBin, signal);
ce0175fa 830
831 fSignalCounter++;
266f8637 832
833 return 1; // signal was accepted
f11b3071 834}
266f8637 835
f11b3071 836//_____________________________________________________________________
266f8637 837void AliTPCdataQA::FindLocalMaxima(const Int_t iSector)
f11b3071 838{
839 //
266f8637 840 // This method is called after the data from each sector has been
841 // exapanded into an array
842 // Loop over the signals and identify local maxima and fill the
843 // calibration objects with the information
f11b3071 844 //
266f8637 845
846 Int_t nLocalMaxima = 0;
847 const Int_t maxTimeBin = fTimeBinsMax+4; // Used to step between neighboring pads
848 // Because we have tha pad-time data in a
849 // 1d array
850
851 for (Int_t iRow = 0; iRow < fRowsMax; iRow++) {
852
853 Float_t* allBins = fAllBins[iRow];
854 Int_t* sigBins = fAllSigBins[iRow];
855 const Int_t nSigBins = fAllNSigBins[iRow];
856
857 for (Int_t iSig = 0; iSig < nSigBins; iSig++) {
858
859 Int_t bin = sigBins[iSig];
860 Float_t *b = &allBins[bin];
861
862 //
863 // Now we check if this is a local maximum
864 //
865
866 Float_t qMax = b[0];
867
868 // First check that the charge is bigger than the threshold
869 if (qMax<5)
870 continue;
871
872 // Require at least one neighboring pad with signal
873 if (b[-maxTimeBin]+b[maxTimeBin]<=0) continue;
874
875 // Require at least one neighboring time bin with signal
876 if (b[-1]+b[1]<=0) continue;
877
878 //
879 // Check that this is a local maximum
880 // Note that the checking is done so that if 2 charges has the same
881 // qMax then only 1 cluster is generated
882 // (that is why there is BOTH > and >=)
883 //
884 if (b[-maxTimeBin] >= qMax) continue;
885 if (b[-1 ] >= qMax) continue;
886 if (b[+maxTimeBin] > qMax) continue;
887 if (b[+1 ] > qMax) continue;
888 if (b[-maxTimeBin-1] >= qMax) continue;
889 if (b[+maxTimeBin-1] >= qMax) continue;
890 if (b[+maxTimeBin+1] > qMax) continue;
891 if (b[-maxTimeBin+1] >= qMax) continue;
892
893 //
894 // Now we accept the local maximum and fill the calibration/data objects
895 //
896 nLocalMaxima++;
897
898 Int_t iPad, iTimeBin;
899 GetPadAndTimeBin(bin, iPad, iTimeBin);
900
901 Float_t count = fNLocalMaxima->GetCalROC(iSector)->GetValue(iRow, iPad);
902 fNLocalMaxima->GetCalROC(iSector)->SetValue(iRow, iPad, count+1);
903
904 count = fTimePosition->GetCalROC(iSector)->GetValue(iRow, iPad);
905 fTimePosition->GetCalROC(iSector)->SetValue(iRow, iPad, count+iTimeBin);
906
907 Float_t charge = fMaxCharge->GetCalROC(iSector)->GetValue(iRow, iPad);
908 fMaxCharge->GetCalROC(iSector)->SetValue(iRow, iPad, charge + qMax);
909
910 if(qMax>=10) {
911 count = fOverThreshold10->GetCalROC(iSector)->GetValue(iRow, iPad);
912 fOverThreshold10->GetCalROC(iSector)->SetValue(iRow, iPad, count+1);
913 }
914 if(qMax>=20) {
915 count = fOverThreshold20->GetCalROC(iSector)->GetValue(iRow, iPad);
916 fOverThreshold20->GetCalROC(iSector)->SetValue(iRow, iPad, count+1);
917 }
918 if(qMax>=30) {
919 count = fOverThreshold30->GetCalROC(iSector)->GetValue(iRow, iPad);
920 fOverThreshold30->GetCalROC(iSector)->SetValue(iRow, iPad, count+1);
921 }
922
923 //
924 // Calculate the total charge as the sum over the region:
925 //
926 // o o o o o
927 // o i i i o
928 // o i C i o
929 // o i i i o
930 // o o o o o
931 //
932 // with qmax at the center C.
933 //
934 // The inner charge (i) we always add, but we only add the outer
935 // charge (o) if the neighboring inner bin (i) has a signal.
936 //
937 Int_t minP = 0, maxP = 0, minT = 0, maxT = 0;
938 Float_t qTot = qMax;
939 for(Int_t i = -1; i<=1; i++) {
940 for(Int_t j = -1; j<=1; j++) {
941
942 if(i==0 && j==0)
943 continue;
944
77f88633 945 Float_t charge1 = GetQ(b, i, j, maxTimeBin, minT, maxT, minP, maxP);
946 qTot += charge1;
947 if(charge1>0) {
266f8637 948 // see if the next neighbor is also above threshold
949 if(i*j==0) {
950 qTot += GetQ(b, 2*i, 2*j, maxTimeBin, minT, maxT, minP, maxP);
951 } else {
952 // we are in a diagonal corner
953 qTot += GetQ(b, i, 2*j, maxTimeBin, minT, maxT, minP, maxP);
954 qTot += GetQ(b, 2*i, j, maxTimeBin, minT, maxT, minP, maxP);
955 qTot += GetQ(b, 2*i, 2*j, maxTimeBin, minT, maxT, minP, maxP);
956 }
957 }
958 }
959 }
960
961 charge = fMeanCharge->GetCalROC(iSector)->GetValue(iRow, iPad);
962 fMeanCharge->GetCalROC(iSector)->SetValue(iRow, iPad, charge + qTot);
963
964 count = fNTimeBins->GetCalROC(iSector)->GetValue(iRow, iPad);
965 fNTimeBins->GetCalROC(iSector)->SetValue(iRow, iPad, count + maxT-minT+1);
966
967 count = fNPads->GetCalROC(iSector)->GetValue(iRow, iPad);
968 fNPads->GetCalROC(iSector)->SetValue(iRow, iPad, count + maxP-minP+1);
969
23c9ab21 970 if((iSector%36)<18) { // A side
971 fHistQVsTimeSideA->Fill(iTimeBin, qTot);
972 fHistQMaxVsTimeSideA->Fill(iTimeBin, qMax);
973 } else {
974 fHistQVsTimeSideC->Fill(iTimeBin, qTot);
975 fHistQMaxVsTimeSideC->Fill(iTimeBin, qMax);
976 }
266f8637 977 } // end loop over signals
978 } // end loop over rows
f11b3071 979
ce0175fa 980 fClusterCounter += nLocalMaxima;
0ffacf98 981}
11ccf1c1 982
f11b3071 983//_____________________________________________________________________
984void AliTPCdataQA::Analyse()
985{
11ccf1c1 986 //
f11b3071 987 // Calculate calibration constants
11ccf1c1 988 //
f11b3071 989
1267cf3a 990 AliInfo("Analyse called");
f11b3071 991
266f8637 992 if(fIsAnalysed == kTRUE) {
993
1267cf3a 994 AliInfo("No new data since Analyse was called last time");
266f8637 995 return;
996 }
f11b3071 997
266f8637 998 if(fEventCounter==0) {
999
1267cf3a 1000 AliInfo("EventCounter == 0, Cannot analyse");
f11b3071 1001 return;
1002 }
266f8637 1003
f11b3071 1004 Int_t nTimeBins = fLastTimeBin - fFirstTimeBin +1;
1267cf3a 1005 AliInfo(Form("EventCounter: %d , TimeBins: %d", fEventCounter, nTimeBins));
f11b3071 1006
f11b3071 1007 Float_t normalization = 1.0 / Float_t(fEventCounter * nTimeBins);
266f8637 1008 fNoThreshold->Multiply(normalization);
1009
1010 fMeanCharge->Divide(fNLocalMaxima);
1011 fMaxCharge->Divide(fNLocalMaxima);
1012 fNTimeBins->Divide(fNLocalMaxima);
1013 fNPads->Divide(fNLocalMaxima);
1014 fTimePosition->Divide(fNLocalMaxima);
1015
1016 fIsAnalysed = kTRUE;
11ccf1c1 1017}
258cd111 1018
1019
266f8637 1020//_____________________________________________________________________
6a50ff96 1021void AliTPCdataQA::MakeTree(const char *fname) const {
258cd111 1022 //
1023 // Export result to the tree -located in the file
1024 // This file can be analyzed using AliTPCCalibViewer
1025 //
258cd111 1026 AliTPCPreprocessorOnline preprocesor;
266f8637 1027
1028 if (fNLocalMaxima) preprocesor.AddComponent(fNLocalMaxima);
1029 if (fMaxCharge) preprocesor.AddComponent(fMaxCharge);
1030 if (fMeanCharge) preprocesor.AddComponent(fMeanCharge);
1031 if (fNoThreshold) preprocesor.AddComponent(fNoThreshold);
1032 if (fNTimeBins) preprocesor.AddComponent(fNTimeBins);
1033 if (fNPads) preprocesor.AddComponent(fNPads);
1034 if (fTimePosition) preprocesor.AddComponent(fTimePosition);
1035 if (fOverThreshold10) preprocesor.AddComponent(fOverThreshold10);
1036 if (fOverThreshold20) preprocesor.AddComponent(fOverThreshold20);
1037 if (fOverThreshold30) preprocesor.AddComponent(fOverThreshold30);
1038
258cd111 1039 preprocesor.DumpToFile(fname);
1040}
c322f08a 1041
1042
266f8637 1043//_____________________________________________________________________
c322f08a 1044void AliTPCdataQA::MakeArrays(){
1045 //
266f8637 1046 // The arrays for expanding the raw data are defined and
1047 // som parameters are intialised
c322f08a 1048 //
1049 AliTPCROC * roc = AliTPCROC::Instance();
1050 //
266f8637 1051 // To make the array big enough for all sectors we take
1052 // the dimensions from the outer row of an OROC (the last sector)
1053 //
1054 fRowsMax = roc->GetNRows(roc->GetNSector()-1);
1055 fPadsMax = roc->GetNPads(roc->GetNSector()-1,fRowsMax-1);
1056 fTimeBinsMax = fLastTimeBin - fFirstTimeBin +1;
1057
1058 //
1059 // Since we have added 2 pads (TimeBins) before and after the real pads (TimeBins)
1060 // to make sure that we can always query the exanded table even when the
1061 // max is on the edge
1062 //
1063
c322f08a 1064
266f8637 1065 fAllBins = new Float_t*[fRowsMax];
1066 fAllSigBins = new Int_t*[fRowsMax];
1067 fAllNSigBins = new Int_t[fRowsMax];
1068
1069 for (Int_t iRow = 0; iRow < fRowsMax; iRow++) {
c322f08a 1070 //
266f8637 1071 Int_t maxBin = (fTimeBinsMax+4)*(fPadsMax+4);
c322f08a 1072 fAllBins[iRow] = new Float_t[maxBin];
266f8637 1073 memset(fAllBins[iRow],0,sizeof(Float_t)*maxBin); // set all values to 0
c322f08a 1074 fAllSigBins[iRow] = new Int_t[maxBin];
266f8637 1075 fAllNSigBins[iRow] = 0;
c322f08a 1076 }
1077}
1078
1079
266f8637 1080//_____________________________________________________________________
c322f08a 1081void AliTPCdataQA::CleanArrays(){
1082 //
1083 //
1084 //
266f8637 1085
1086 for (Int_t iRow = 0; iRow < fRowsMax; iRow++) {
42919b08 1087
1088 // To speed up the performance by a factor 2 on cosmic data (and
1089 // presumably pp data as well) where the ocupancy is low, the
1090 // memset is only called if there is more than 1000 signals for a
1091 // row (of the order 1% occupancy)
1092 if(fAllNSigBins[iRow]<1000) {
1093
1094 Float_t* allBins = fAllBins[iRow];
1095 Int_t* sigBins = fAllSigBins[iRow];
1096 const Int_t nSignals = fAllNSigBins[iRow];
1097 for(Int_t i = 0; i < nSignals; i++)
23c9ab21 1098 allBins[sigBins[i]]=0;
42919b08 1099 } else {
23c9ab21 1100
42919b08 1101 Int_t maxBin = (fTimeBinsMax+4)*(fPadsMax+4);
1102 memset(fAllBins[iRow],0,sizeof(Float_t)*maxBin);
1103 }
1104
c322f08a 1105 fAllNSigBins[iRow]=0;
1106 }
1107}
1108
266f8637 1109//_____________________________________________________________________
1110void AliTPCdataQA::GetPadAndTimeBin(Int_t bin, Int_t& iPad, Int_t& iTimeBin){
1111 //
1112 // Return pad and timebin for a given bin
c322f08a 1113 //
266f8637 1114
1115 // Int_t bin = iPad*(fTimeBinsMax+4)+iTimeBin;
1116 iTimeBin = bin%(fTimeBinsMax+4);
1117 iPad = (bin-iTimeBin)/(fTimeBinsMax+4);
1118
1119 iPad -= 2;
1120 iTimeBin -= 2;
1121 iTimeBin += fFirstTimeBin;
1122
1123 R__ASSERT(iPad>=0 && iPad<=fPadsMax);
1124 R__ASSERT(iTimeBin>=fFirstTimeBin && iTimeBin<=fLastTimeBin);
1125}
1126
1127//_____________________________________________________________________
1128void AliTPCdataQA::SetExpandDigit(const Int_t iRow, Int_t iPad,
1129 Int_t iTimeBin, const Float_t signal)
1130{
c322f08a 1131 //
266f8637 1132 //
c322f08a 1133 //
266f8637 1134 R__ASSERT(iRow>=0 && iRow<fRowsMax);
1135 R__ASSERT(iPad>=0 && iPad<=fPadsMax);
1136 R__ASSERT(iTimeBin>=fFirstTimeBin && iTimeBin<=fLastTimeBin);
1137
1138 iTimeBin -= fFirstTimeBin;
1139 iPad += 2;
1140 iTimeBin += 2;
c322f08a 1141
266f8637 1142 Int_t bin = iPad*(fTimeBinsMax+4)+iTimeBin;
1143 fAllBins[iRow][bin] = signal;
1144 fAllSigBins[iRow][fAllNSigBins[iRow]] = bin;
1145 fAllNSigBins[iRow]++;
1146}
1147
1148Float_t AliTPCdataQA::GetQ(const Float_t* adcArray, const Int_t time,
1149 const Int_t pad, const Int_t maxTimeBins,
1150 Int_t& timeMin, Int_t& timeMax,
6a50ff96 1151 Int_t& padMin, Int_t& padMax) const
266f8637 1152{
1153 //
1154 // This methods return the charge in the bin time+pad*maxTimeBins
1155 // If the charge is above 0 it also updates the padMin, padMax, timeMin
1156 // and timeMax if necessary
1157 //
1158 Float_t charge = adcArray[time + pad*maxTimeBins];
1159 if(charge > 0) {
1160 timeMin = TMath::Min(time, timeMin); timeMax = TMath::Max(time, timeMax);
1161 padMin = TMath::Min(pad, padMin); padMax = TMath::Max(pad, padMax);
1162 }
1163 return charge;
c322f08a 1164}
ce4b4255 1165
1166//______________________________________________________________________________
6a50ff96 1167void AliTPCdataQA::Streamer(TBuffer &xRuub)
ce4b4255 1168{
1169 // Automatic schema evolution was first used from revision 4
1170 // Code based on:
1171 // http://root.cern.ch/root/roottalk/roottalk02/3207.html
1172
6a50ff96 1173 UInt_t xRuus, xRuuc;
1174 if (xRuub.IsReading()) {
1175 Version_t xRuuv = xRuub.ReadVersion(&xRuus, &xRuuc);
ce4b4255 1176 //we use the automatic algorithm for class version > 3
6a50ff96 1177 if (xRuuv > 3) {
1178 AliTPCdataQA::Class()->ReadBuffer(xRuub, this, xRuuv, xRuus,
1179 xRuuc);
ce4b4255 1180 return;
1181 }
6a50ff96 1182 TH1F::Streamer(xRuub);
1183 xRuub >> fFirstTimeBin;
1184 xRuub >> fLastTimeBin;
1185 xRuub >> fAdcMin;
1186 xRuub >> fAdcMax;
1187 xRuub >> fNLocalMaxima;
1188 xRuub >> fMaxCharge;
1189 xRuub >> fMeanCharge;
1190 xRuub >> fNoThreshold;
1191 xRuub >> fNTimeBins;
1192 xRuub >> fNPads;
1193 xRuub >> fTimePosition;
1194 xRuub >> fEventCounter;
1195 xRuub >> fIsAnalysed;
1196 xRuub.CheckByteCount(xRuus, xRuuc, AliTPCdataQA::IsA());
ce4b4255 1197 } else {
6a50ff96 1198 AliTPCdataQA::Class()->WriteBuffer(xRuub,this);
ce4b4255 1199 }
1200}