]> git.uio.no Git - u/mrichter/AliRoot.git/blame - TPC/Attic/AliTPCCalibTCF.cxx
updated
[u/mrichter/AliRoot.git] / TPC / Attic / AliTPCCalibTCF.cxx
CommitLineData
eb7e0771 1/**************************************************************************
2 * Copyright(c) 2007-08, 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///////////////////////////////////////////////////////////////////////////////
18// //
19// Class for Evaluation and Validation of the ALTRO Tail Cancelation Filter //
20// (TCF) parameters out of TPC Raw data //
21// //
d0bd4fcc 22// Author: Stefan Rossegger, Simon Feigl //
eb7e0771 23// //
24///////////////////////////////////////////////////////////////////////////////
25
26#include "AliTPCCalibTCF.h"
27
28#include <TObject.h>
29#include <TCanvas.h>
30#include <TFile.h>
31#include <TKey.h>
32#include <TStyle.h>
33#include <TMinuit.h>
34#include <TH1F.h>
d0bd4fcc 35#include <TH2F.h>
7409c8db 36#include <AliSysInfo.h>
eb7e0771 37
38#include <TMath.h>
39#include <TNtuple.h>
40#include <TEntryList.h>
eb7e0771 41#include "AliRawReaderRoot.h"
55f06b51 42#include "AliRawHLTManager.h"
752b0cc7 43#include "AliTPCRawStreamV3.h"
eb7e0771 44#include "AliTPCROC.h"
45
46#include "AliTPCAltroEmulator.h"
47
df4cfd77 48#include "AliTPCmapper.h"
49#include <fstream>
50
eb7e0771 51ClassImp(AliTPCCalibTCF)
52
53AliTPCCalibTCF::AliTPCCalibTCF() :
54 TNamed(),
752b0cc7 55 fGateWidth(50),
eb7e0771 56 fSample(900),
752b0cc7 57 fPulseLength(400),
eb7e0771 58 fLowPulseLim(30),
752b0cc7 59 fUpPulseLim(900),
60 fRMSLim(1.0),
61 fRatioIntLim(2)
d0bd4fcc 62
eb7e0771 63{
64 //
65 // AliTPCCalibTCF standard constructor
66 //
67}
68
69//_____________________________________________________________________________
d0bd4fcc 70AliTPCCalibTCF::AliTPCCalibTCF(Int_t gateWidth, Int_t sample, Int_t pulseLength, Int_t lowPulseLim, Int_t upPulseLim, Double_t rmsLim, Double_t ratioIntLim) :
eb7e0771 71 TNamed(),
72 fGateWidth(gateWidth),
73 fSample(sample),
74 fPulseLength(pulseLength),
75 fLowPulseLim(lowPulseLim),
76 fUpPulseLim(upPulseLim),
d0bd4fcc 77 fRMSLim(rmsLim),
78 fRatioIntLim(ratioIntLim)
eb7e0771 79{
80 //
81 // AliTPCCalibTCF constructor with specific (non-standard) thresholds
82 //
83}
84
85//_____________________________________________________________________________
86AliTPCCalibTCF::AliTPCCalibTCF(const AliTPCCalibTCF &tcf) :
87 TNamed(tcf),
88 fGateWidth(tcf.fGateWidth),
89 fSample(tcf.fSample),
90 fPulseLength(tcf.fPulseLength),
91 fLowPulseLim(tcf.fLowPulseLim),
92 fUpPulseLim(tcf.fUpPulseLim),
d0bd4fcc 93 fRMSLim(tcf.fRMSLim),
94 fRatioIntLim(tcf.fRatioIntLim)
eb7e0771 95{
96 //
97 // AliTPCCalibTCF copy constructor
98 //
99}
100
101
102//_____________________________________________________________________________
103AliTPCCalibTCF& AliTPCCalibTCF::operator = (const AliTPCCalibTCF &source)
104{
105 //
106 // AliTPCCalibTCF assignment operator
107 //
108
109 if (&source == this) return *this;
110 new (this) AliTPCCalibTCF(source);
111
112 return *this;
113
114}
115
116//_____________________________________________________________________________
117AliTPCCalibTCF::~AliTPCCalibTCF()
118{
119 //
120 // AliTPCCalibTCF destructor
121 //
122}
123
752b0cc7 124
125//_____________________________________________________________________________
126void AliTPCCalibTCF::ProcessRawFileV3(const char *nameRawFile, const char *nameFileOut) {
127 //
128 // New RCU data format!: Standard middle of 2009
129 //
130 // Loops over all events within one RawData file and collects proper pulses
131 // (according to given tresholds) per pad
132 // Histograms per pad are stored in 'nameFileOut'
133 //
134
135 AliRawReader *rawReader = AliRawReader::Create(nameRawFile);
136 if (!rawReader) {
137 printf("Could not create a raw reader for %s\n",nameRawFile);
138 return;
139 }
140
141 rawReader->RewindEvents(); // just to make sure
142
143 rawReader->Select("TPC");
144
145 if (!rawReader->NextEvent()) {
146 printf("no events found in %s\n",nameRawFile);
147 return;
148 }
149
150 // TPC stream reader
151 AliTPCRawStreamV3 rawStream(rawReader);
152
153 Int_t ievent=0;
154 do {
155 AliSysInfo::AddStamp(Form("start_event_%d",ievent), ievent,-1,-1);
156 printf("Reading next event ... Nr: %d\n",ievent);
157 // Start the basic data extraction
158 ProcessRawEventV3(rawReader, &rawStream, nameFileOut);
159 AliSysInfo::AddStamp(Form("end_event_%d",ievent), ievent,-1,-1);
160 ievent++;
161
162 } while (rawReader->NextEvent());
163
164 rawReader->~AliRawReader();
165
166}
167
752b0cc7 168//_____________________________________________________________________________
169void AliTPCCalibTCF::ProcessRawEventV3( AliRawReader *rawReader, AliTPCRawStreamV3 *rawStream, const char *nameFileOut) {
170 //
171 // New RCU data format!: Standard middle of 2009
172 //
173 // Extracts proper pulses (according the given tresholds) within one event
174 // and accumulates them into one histogram per pad. All histograms are
175 // saved in the file 'nameFileOut'.
176 // The first bins of the histograms contain the following information:
177 // bin 1: Number of accumulated pulses
178 // bin 2;3;4: Sector; Row; Pad;
179 //
180
181 TFile fileOut(nameFileOut,"UPDATE");
182 fileOut.cd();
183
184 TH1I *tempHis = new TH1I("tempHis","tempHis",fSample,fGateWidth,fSample+fGateWidth);
185 TH1I *tempRMSHis = new TH1I("tempRMSHis","tempRMSHis",2000,0,2000);
186
187 // loop over the data in this event
188
189 while (rawStream->NextDDL() ) {
190
191 Int_t ddl = rawReader->GetDDLID();
192
193 while (rawStream->NextChannel() ) {
194
195 while (rawStream->NextBunch() ) {
196
197 Int_t t0 = rawStream->GetStartTimeBin();
198 Int_t bl = rawStream->GetBunchLength();
199
200 if (bl<fSample+fGateWidth) continue;
201
202 Int_t sector = rawStream->GetSector();
203 Int_t row = rawStream->GetRow();
204 Int_t pad = rawStream->GetPad();
205
206 UShort_t *signals=(UShort_t*)rawStream->GetSignals();
207 if (!signals) continue;
208
209 // Write to temporary histogramm
210 for (Int_t i=0;i<bl;++i) {
211 UShort_t time=t0-i;
212 UShort_t signal=signals[i];
213 if ( (fGateWidth<time) && (time<=fSample+fGateWidth) ) {
214 tempHis->SetBinContent(time-fGateWidth,signal);
215 }
216 }
217
218 // calculation of the pulse properties and comparison to thresholds settings
219
220 Int_t max = (Int_t)tempHis->GetMaximum(FLT_MAX);
221 Int_t maxpos = tempHis->GetMaximumBin();
222
223 Int_t first = (Int_t)TMath::Max(maxpos-10, 0);
224 Int_t last = TMath::Min((Int_t)maxpos+fPulseLength-10, fSample+fGateWidth);
225
226 // simple baseline substraction ? better one needed ? (pedestalsubstr.?)
227 // and RMS calculation with timebins before the pulse and at the end of
228 // the signal
229 for (Int_t ipos = 0; ipos<6; ipos++) {
230 // before the pulse
231 tempRMSHis->Fill(tempHis->GetBinContent(first+ipos));
232 }
233 for (Int_t ipos = 0; ipos<20; ipos++) {
234 // at the end to get rid of pulses with serious baseline fluctuations
235 tempRMSHis->Fill(tempHis->GetBinContent(last-ipos));
236 }
237
238 Double_t baseline = tempRMSHis->GetMean();
239 Double_t rms = tempRMSHis->GetRMS();
240 tempRMSHis->Reset();
241
242 Double_t lowLim = fLowPulseLim+baseline;
243 Double_t upLim = fUpPulseLim+baseline;
244
245 // get rid of pulses which contain gate signal and/or too much noise
246 // with the help of ratio of integrals
247 Double_t intHist = 0;
248 Double_t intPulse = 0;
249 Double_t binValue;
250 for(Int_t ipos=first; ipos<=last; ipos++) {
251 binValue = TMath::Abs(tempHis->GetBinContent(ipos) - baseline);
252 intHist += binValue;
253 if(ipos>=first+5 && ipos<=first+15) {intPulse += binValue;}
254 }
255
256 // gets rid of high frequency noise:
257 // calculating ratio (value one to the right of maximum)/(maximum)
258 // has to be >= 0.1; if maximum==0 set ratio to 0.1
259 Double_t maxCorr = max - baseline;
260 Double_t binRatio = 0.1;
261 if(TMath::Abs(maxCorr)>1e-5) {
262 binRatio = (tempHis->GetBinContent(maxpos+1) - baseline) / maxCorr;
263 }
264
265 // Decision if found pulse is a proper one according to given tresholds
266 if (max>lowLim && max<upLim && !((last-first)<fPulseLength) && rms<fRMSLim && (intHist/intPulse)<fRatioIntLim &&intPulse>10&& (binRatio >= 0.1) ) {
267
268 // 1D histogramm for mean pulse per pad
269 char hname[100];
270 snprintf(hname,100,"sec%drow%dpad%d",sector,row,pad);
271
272 TH1F *his = (TH1F*)fileOut.Get(hname);
273
274 if (!his ) { // new entry (pulse in new pad found)
275
276 his = new TH1F(hname,hname, fPulseLength+5, 0, fPulseLength+5);
277 his->SetBinContent(1,1); // pulse counter (1st pulse)
278 his->SetBinContent(2,sector); // sector
279 his->SetBinContent(3,row); // row
280 his->SetBinContent(4,pad); // pad
281
282 for (Int_t ipos=0; ipos<last-first; ipos++){
283 Int_t signal = (Int_t)(tempHis->GetBinContent(ipos+first)-baseline);
284 his->SetBinContent(ipos+5,signal);
285 }
286 his->Write(hname);
287 printf("new %s: Signal %d at bin %d \n", hname, max-(Int_t)baseline, maxpos+fGateWidth);
288
289 } else { // adding pulse to existing histogram (pad already found)
290
291 his->AddBinContent(1,1); // pulse counter for each pad
292 for (Int_t ipos=0; ipos<last-first; ipos++){
293 Int_t signal= (Int_t)(tempHis->GetBinContent(ipos+first)-baseline);
294 his->AddBinContent(ipos+5,signal);
295 }
296 printf("adding ... %s: Signal %d at bin %d \n", hname, max-(Int_t)baseline, maxpos+fGateWidth);
297 his->Write(hname,kOverwrite);
298 }
299
300
301 // 2D histogramm for pulse spread within a DDL (normalized to one)
302 char hname2d[100];
303 snprintf(hname2d,100,"2Dhisto_ddl%d",ddl);
304 TH2F *his2d = (TH2F*)fileOut.Get(hname2d);
305 if (!his2d ) { // new entry (ddl was not seen before)
306
307 his2d = new TH2F(hname2d,hname2d, fPulseLength, 0., (Double_t)fPulseLength, 50,-0.02,0.02);
308 for (Int_t ipos=0; ipos<last-first; ipos++){
309 Double_t signal = tempHis->GetBinContent(ipos+first)-baseline;
338e0dd9 310 if (TMath::Abs(signal/maxCorr)>1e-10) // zero bins are biased
311 his2d->Fill(ipos,signal/maxCorr);
752b0cc7 312 }
313 his2d->Write(hname2d);
314 printf("new %s: \n", hname2d);
752b0cc7 315 } else { // adding pulse to existing histogram
316
317 for (Int_t ipos=0; ipos<last-first; ipos++){
318 Double_t signal= tempHis->GetBinContent(ipos+first)-baseline;
338e0dd9 319 if (TMath::Abs(signal/maxCorr)>1e-10) // zero bins are biased
320 his2d->Fill(ipos,signal/maxCorr);
752b0cc7 321 }
322 his2d->Write(hname2d,kOverwrite);
323 }
324
325 tempHis->Reset();
326
327 } // pulse stored
328
329 } // bunch loop
330 }// channel loop
331 } // ddl loop
332
333 tempHis->~TH1I();
334 tempRMSHis->~TH1I();
335 printf("Finished to read event ... \n");
336 fileOut.Close();
337
338}
339
eb7e0771 340//____________________________________________________________________________
341void AliTPCCalibTCF::MergeHistoPerSector(const char *nameFileIn) {
342 //
343 // Merges all histograms within one sector, calculates the TCF parameters
344 // of the 'histogram-per-sector' and stores (histo and parameters) into
345 // seperated files ...
346 //
347 // note: first 4 timebins of a histogram hold specific informations
348 // about number of collected pulses, sector, row and pad
349 //
350 // 'nameFileIn': root file produced with Process function which holds
351 // one histogram per pad (sum of signals of proper pulses)
352 // 'Sec+nameFileIn': root file with one histogram per sector
353 // (information of row and pad are set to -1)
354 //
355
356 TFile fileIn(nameFileIn,"READ");
357 TH1F *hisPad = 0;
358 TKey *key = 0;
359 TIter next( fileIn.GetListOfKeys() );
360
361 char nameFileOut[100];
56c85970 362 snprintf(nameFileOut,100,"Sec-%s",nameFileIn);
eb7e0771 363
364 TFile fileOut(nameFileOut,"RECREATE");
365 fileOut.cd();
366
367 Int_t nHist = fileIn.GetNkeys();
368 Int_t iHist = 0; // histogram counter for merge-status print
369
370 while ( (key=(TKey*)next()) ) {
371
372 iHist++;
752b0cc7 373 TString name(key->GetName());
374 if (name.Contains("ddl") ) continue; // ignore the 2d histogramms per ddl
375
376 hisPad = (TH1F*)fileIn.Get(name.Data()); // copy object to memory
eb7e0771 377
eb7e0771 378 Int_t pulseLength = hisPad->GetNbinsX() -4;
379 // -4 because first four timebins contain pad specific informations
380 Int_t npulse = (Int_t)hisPad->GetBinContent(1);
381 Int_t sector = (Int_t)hisPad->GetBinContent(2);
382
383 char hname[100];
56c85970 384 snprintf(hname,100,"sector%d",sector);
eb7e0771 385 TH1F *his = (TH1F*)fileOut.Get(hname);
386
387 if (!his ) { // new histogram (new sector)
388 his = new TH1F(hname,hname, pulseLength+4, 0, pulseLength+4);
389 his->SetBinContent(1,npulse); // pulse counter
390 his->SetBinContent(2,sector); // set sector info
391 his->SetBinContent(3,-1); // set to dummy value
392 his->SetBinContent(4,-1); // set to dummy value
393 for (Int_t ipos=0; ipos<pulseLength; ipos++){
394 his->SetBinContent(ipos+5,hisPad->GetBinContent(ipos+5));
395 }
396 his->Write(hname);
397 printf("found %s ...\n", hname);
398 } else { // add to existing histogram for sector
399 his->AddBinContent(1,npulse); // pulse counter
400 for (Int_t ipos=0; ipos<pulseLength; ipos++){
401 his->AddBinContent(ipos+5,hisPad->GetBinContent(ipos+5));
402 }
752b0cc7 403 his->Write(hname,kOverwrite);
eb7e0771 404 }
405
406 if (iHist%500==0) {
407 printf("merging status: \t %d pads out of %d \n",iHist, nHist);
408 }
409 }
df4cfd77 410
eb7e0771 411 printf("merging done ...\n");
412 fileIn.Close();
413 fileOut.Close();
414
eb7e0771 415
416}
417
418
419//____________________________________________________________________________
d0bd4fcc 420void AliTPCCalibTCF::AnalyzeRootFile(const char *nameFileIn, Int_t minNumPulse, Int_t histStart, Int_t histEnd) {
eb7e0771 421 //
422 // This function takes a prepeared root file (accumulated histograms: output
423 // of process function) and performs an analysis (fit and equalization) in
424 // order to get the TCF parameters. These are stored in an TNtuple along with
425 // the pad and creation infos. The tuple is written to the output file
426 // "TCFparam+nameFileIn"
427 // To reduce the analysis time, the minimum number of accumulated pulses within
428 // one histogram 'minNumPulse' (to perform the analysis on) can be set
429 //
430
431 TFile fileIn(nameFileIn,"READ");
432 TH1F *hisIn;
433 TKey *key;
434 TIter next( fileIn.GetListOfKeys() );
435
436 char nameFileOut[100];
56c85970 437 snprintf(nameFileOut,100,"TCF-%s",nameFileIn);
eb7e0771 438
439 TFile fileOut(nameFileOut,"RECREATE");
440 fileOut.cd();
441
442 TNtuple *paramTuple = new TNtuple("TCFparam","TCFparameter","sec:row:pad:npulse:Z0:Z1:Z2:P0:P1:P2");
443
444 Int_t nHist = fileIn.GetNkeys();
445 Int_t iHist = 0; // counter for print of analysis-status
446
9389f9a4 447 while ((key = (TKey *) next())) { // loop over histograms
d0bd4fcc 448 ++iHist;
449 if(iHist < histStart || iHist > histEnd) {continue;}
752b0cc7 450
451 TString name(key->GetName());
452 if (name.Contains("ddl") ) continue; // ignore the 2d histogramms per ddl
453
eb7e0771 454 hisIn = (TH1F*)fileIn.Get(key->GetName()); // copy object to memory
338e0dd9 455
eb7e0771 456 Int_t numPulse = (Int_t)hisIn->GetBinContent(1);
457 if ( numPulse >= minNumPulse ) {
df4cfd77 458 printf("Analyze histogram %d out of %d\n",iHist,nHist);
eb7e0771 459 Double_t* coefP = new Double_t[3];
460 Double_t* coefZ = new Double_t[3];
461 for(Int_t i = 0; i < 3; i++){
462 coefP[i] = 0;
463 coefZ[i] = 0;
464 }
465 // perform the analysis on the given histogram
466 Int_t fitOk = AnalyzePulse(hisIn, coefZ, coefP);
467 if (fitOk) { // Add found parameters to file
468 Int_t sector = (Int_t)hisIn->GetBinContent(2);
469 Int_t row = (Int_t)hisIn->GetBinContent(3);
470 Int_t pad = (Int_t)hisIn->GetBinContent(4);
471 paramTuple->Fill(sector,row,pad,numPulse,coefZ[0],coefZ[1],coefZ[2],coefP[0],coefP[1],coefP[2]);
472 }
473 coefP->~Double_t();
474 coefZ->~Double_t();
df4cfd77 475 } else {
476 printf("Skip histogram %d out of %d | not enough accumulated pulses\n",iHist,nHist);
eb7e0771 477 }
df4cfd77 478
eb7e0771 479 }
480
481 fileIn.Close();
482 paramTuple->Write();
483 fileOut.Close();
484
485}
486
487
488//____________________________________________________________________________
56c85970 489Int_t AliTPCCalibTCF::AnalyzePulse(TH1F * const hisIn, Double_t *coefZ, Double_t *coefP) {
eb7e0771 490 //
491 // Performs the analysis on one specific pulse (histogram) by means of fitting
492 // the pulse and equalization of the pulseheight. The found TCF parameters
493 // are stored in the arrays coefZ and coefP
494 //
495
496 Int_t pulseLength = hisIn->GetNbinsX() -4;
d0bd4fcc 497 // -4 because the first four timebins usually contain pad specific informations
eb7e0771 498 Int_t npulse = (Int_t)hisIn->GetBinContent(1);
499 Int_t sector = (Int_t)hisIn->GetBinContent(2);
500 Int_t row = (Int_t)hisIn->GetBinContent(3);
501 Int_t pad = (Int_t)hisIn->GetBinContent(4);
502
503 // write pulseinformation to TNtuple and normalize to 100 ADC (because of
504 // given upper and lower fit parameter limits) in order to pass the pulse
505 // to TMinuit
506
507 TNtuple *dataTuple = new TNtuple("ntupleFit","Pulse","timebin:sigNorm:error");
508 Double_t error = 0.05;
509 Double_t max = hisIn->GetMaximum(FLT_MAX);
510 for (Int_t ipos=0; ipos<pulseLength; ipos++) {
511 Double_t errorz=error;
512 if (ipos>100) { errorz = error*100; } // very simple weight: FIXME in case
513 Double_t signal = hisIn->GetBinContent(ipos+5);
514 Double_t signalNorm = signal/max*100; //pulseheight normaliz. to 100ADC
515 dataTuple->Fill(ipos, signalNorm, errorz);
516 }
517
518 // Call fit function (TMinuit) to get the first 2 PZ Values for the
519 // Tail Cancelation Filter
520 Int_t fitOk = FitPulse(dataTuple, coefZ, coefP);
521
522 if (fitOk) {
523 // calculates the 3rd set (remaining 2 PZ values) in order to restore the
524 // original height of the pulse
d0bd4fcc 525 Int_t equOk = Equalization(dataTuple, coefZ, coefP);
526 if (!equOk) {
527 Error("FindFit", "Pulse equalisation procedure failed - pulse abandoned ");
528 printf("in Sector %d | Row %d | Pad %d |", sector, row, pad);
529 printf(" Npulses: %d \n\n", npulse);
530 coefP[2] = 0; coefZ[2] = 0;
531 dataTuple->~TNtuple();
532 return 0;
533 }
eb7e0771 534 printf("Calculated TCF parameters for: \n");
535 printf("Sector %d | Row %d | Pad %d |", sector, row, pad);
536 printf(" Npulses: %d \n", npulse);
537 for(Int_t i = 0; i < 3; i++){
538 printf("P[%d] = %f Z[%d] = %f \n",i,coefP[i],i,coefZ[i]);
539 if (i==2) { printf("\n"); }
540 }
541 dataTuple->~TNtuple();
542 return 1;
543 } else { // fit did not converge
544 Error("FindFit", "TCF fit not converged - pulse abandoned ");
545 printf("in Sector %d | Row %d | Pad %d |", sector, row, pad);
546 printf(" Npulses: %d \n\n", npulse);
547 coefP[2] = 0; coefZ[2] = 0;
548 dataTuple->~TNtuple();
549 return 0;
550 }
551
552}
553
554
555
556//____________________________________________________________________________
df4cfd77 557void AliTPCCalibTCF::TestTCFonRootFile(const char *nameFileIn, const char *nameFileTCF, Int_t minNumPulse, Int_t plotFlag, Int_t lowKey, Int_t upKey)
eb7e0771 558{
559 //
560 // Performs quality parameters evaluation of the calculated TCF parameters in
561 // the file 'nameFileTCF' for every (accumulated) histogram within the
562 // prepeared root file 'nameFileIn'.
563 // The found quality parameters are stored in an TNtuple which will be saved
564 // in a Root file 'Quality-*'.
565 // If the parameter for the given pulse (given pad) was not found, the pulse
566 // is rejected.
567 //
568
569 TFile fileIn(nameFileIn,"READ");
570
571 Double_t* coefP = new Double_t[3];
572 Double_t* coefZ = new Double_t[3];
573 for(Int_t i = 0; i < 3; i++){
574 coefP[i] = 0;
575 coefZ[i] = 0;
576 }
577
578 char nameFileOut[100];
56c85970 579 snprintf(nameFileOut,100,"Quality_%s_AT_%s",nameFileTCF, nameFileIn);
eb7e0771 580 TFile fileOut(nameFileOut,"RECREATE");
581
582 TNtuple *qualityTuple = new TNtuple("TCFquality","TCF quality Values","sec:row:pad:npulse:heightDev:areaRed:widthRed:undershot:maxUndershot");
583
584 TH1F *hisIn;
585 TKey *key;
586 TIter next( fileIn.GetListOfKeys() );
587
588 Int_t nHist = fileIn.GetNkeys();
589 Int_t iHist = 0;
590
591 for(Int_t i=0;i<lowKey-1;i++){++iHist; key = (TKey *) next();}
2c632057 592 while ((key = (TKey *) next())) { // loop over saved histograms
eb7e0771 593
594 // loading pulse to memory;
752b0cc7 595 TString name(key->GetName());
596 if (name.Contains("ddl") ) continue; // ignore the 2d histogramms per ddl
597
eb7e0771 598 printf("validating pulse %d out of %d\n",++iHist,nHist);
599 hisIn = (TH1F*)fileIn.Get(key->GetName());
338e0dd9 600
eb7e0771 601
602 // find the correct TCF parameter according to the his infos (first 4 bins)
603 Int_t nPulse = FindCorTCFparam(hisIn, nameFileTCF, coefZ, coefP);
df4cfd77 604 if (nPulse>=minNumPulse) { // doing the TCF quality analysis
eb7e0771 605 Double_t *quVal = GetQualityOfTCF(hisIn,coefZ,coefP, plotFlag);
606 Int_t sector = (Int_t)hisIn->GetBinContent(2);
607 Int_t row = (Int_t)hisIn->GetBinContent(3);
608 Int_t pad = (Int_t)hisIn->GetBinContent(4);
609 qualityTuple->Fill(sector,row,pad,nPulse,quVal[0],quVal[1],quVal[2],quVal[3],quVal[4],quVal[5]);
610 quVal->~Double_t();
611 }
612
613 if (iHist>=upKey) {break;}
614
615 }
616
617 fileOut.cd();
618 qualityTuple->Write();
619
620 coefP->~Double_t();
621 coefZ->~Double_t();
622
623 fileOut.Close();
624 fileIn.Close();
625
626}
627
628
629
630//_____________________________________________________________________________
55f06b51 631void AliTPCCalibTCF::TestTCFonRawFile(const char *nameRawFile, const char *nameFileOut, const char *nameFileTCF, Int_t minNumPulse, Int_t plotFlag, bool bUseHLTOUT) {
eb7e0771 632 //
633 // Performs quality parameters evaluation of the calculated TCF parameters in
634 // the file 'nameFileTCF' for every proper pulse (according to given thresholds)
635 // within the RAW file 'nameRawFile'.
636 // The found quality parameters are stored in a TNtuple which will be saved
637 // in the Root file 'nameFileOut'. If the parameter for the given pulse
638 // (given pad) was not found, the pulse is rejected.
639 //
640
641 //
642 // Reads a RAW data file, extracts Pulses (according the given tresholds)
643 // and test the found TCF parameters on them ...
644 //
645
55f06b51 646
647 // create the data reader
eb7e0771 648 AliRawReader *rawReader = new AliRawReaderRoot(nameRawFile);
55f06b51 649 if (!rawReader) {
650 return;
651 }
652
653 // create HLT reader for redirection of TPC data from HLTOUT to TPC reconstruction
654 AliRawReader *hltReader=AliRawHLTManager::AliRawHLTManager::CreateRawReaderHLT(rawReader, "TPC");
655
656 // now choose the data source
657 if (bUseHLTOUT) rawReader=hltReader;
658
659 // rawReader->Reset();
660 rawReader->RewindEvents();
661
662 if (!rawReader->NextEvent()) {
663 printf("no events found in %s\n",nameRawFile);
664 return;
665 }
666
eb7e0771 667 Double_t* coefP = new Double_t[3];
668 Double_t* coefZ = new Double_t[3];
669 for(Int_t i = 0; i < 3; i++){
670 coefP[i] = 0;
671 coefZ[i] = 0;
672 }
673
d0bd4fcc 674 Int_t ievent = 0;
675
676 TH1I *tempHis = new TH1I("tempHis","tempHis",fSample+fGateWidth,fGateWidth,fSample+fGateWidth);
677 TH1I *tempRMSHis = new TH1I("tempRMSHis","tempRMSHis",2000,0,2000);
678
679 TFile fileOut(nameFileOut,"UPDATE"); // Quality Parameters storage
680 TNtuple *qualityTuple = (TNtuple*)fileOut.Get("TCFquality");
681 if (!qualityTuple) { // no entry in file
682 qualityTuple = new TNtuple("TCFquality","TCF quality Values","sec:row:pad:npulse:heightDev:areaRed:widthRed:undershot:maxUndershot:pulseRMS");
683 }
684
55f06b51 685 do {
eb7e0771 686
d0bd4fcc 687 printf("Reading next event ... Nr:%d\n",ievent);
829455ad 688 AliTPCRawStreamV3 *rawStream = new AliTPCRawStreamV3(rawReader);
eb7e0771 689 rawReader->Select("TPC");
d0bd4fcc 690 ievent++;
eb7e0771 691
829455ad 692 while ( rawStream->NextDDL() ){
693 while ( rawStream->NextChannel() ){
694
695 const Int_t sector = rawStream->GetSector();
696 const Int_t row = rawStream->GetRow();
697 const Int_t pad = rawStream->GetPad();
698
699 while ( rawStream->NextBunch() ){
700 UInt_t startTbin = rawStream->GetStartTimeBin();
701 Int_t bunchlength = rawStream->GetBunchLength();
702 const UShort_t *sig = rawStream->GetSignals();
703 for (Int_t iTimeBin = 0; iTimeBin<bunchlength; iTimeBin++){
704 const Int_t time = startTbin-iTimeBin;
705 Float_t signal=(Float_t)sig[iTimeBin];
706
707 // this pad always gave a useless signal, probably induced by the supply
708 // voltage of the gate signal (date:2008-Aug-07)
709 if(sector==51 && row==95 && pad==0) {
710 continue;
711 }
712
713 // only process pulses of pads with correct address
714 if(sector<0 || sector+1 > Int_t(AliTPCROC::Instance()->GetNSector())) {
715 continue;
716 }
717 if(row<0 || row+1 > Int_t(AliTPCROC::Instance()->GetNRows(sector))) {
718 continue;
719 }
720 if(pad<0 || pad+1 > Int_t(AliTPCROC::Instance()->GetNPads(sector,row))) {
721 continue;
722 }
723
724 // still the same pad, save signal to temporary histogram
725 if (time<=fSample+fGateWidth && time>fGateWidth) {
726 tempHis->SetBinContent(time,signal);
727 }
728 }
729 }
730
731 Int_t max = (Int_t)tempHis->GetMaximum(FLT_MAX);
732 Int_t maxpos = tempHis->GetMaximumBin();
d0bd4fcc 733
829455ad 734 Int_t first = (Int_t)TMath::Max(maxpos-10, 0);
735 Int_t last = TMath::Min((Int_t)maxpos+fPulseLength-10, fSample+fGateWidth);
d0bd4fcc 736
eb7e0771 737
829455ad 738 // simple baseline substraction ? better one needed ? (pedestalsubstr.?)
739 // and RMS calculation with timebins before the pulse and at the end of
740 // the signal
741 for (Int_t ipos = 0; ipos<6; ipos++) {
742 // before the pulse
743 tempRMSHis->Fill(tempHis->GetBinContent(first+ipos));
744 }
745 for (Int_t ipos = 0; ipos<20; ipos++) {
746 // at the end to get rid of pulses with serious baseline fluctuations
747 tempRMSHis->Fill(tempHis->GetBinContent(last-ipos));
748 }
749 Double_t baseline = tempRMSHis->GetMean();
750 Double_t rms = tempRMSHis->GetRMS();
751 tempRMSHis->Reset();
752
753 Double_t lowLim = fLowPulseLim+baseline;
754 Double_t upLim = fUpPulseLim+baseline;
755
756 // get rid of pulses which contain gate signal and/or too much noise
757 // with the help of ratio of integrals
758 Double_t intHist = 0;
759 Double_t intPulse = 0;
760 Double_t binValue;
761 for(Int_t ipos=first; ipos<=last; ipos++) {
762 binValue = TMath::Abs(tempHis->GetBinContent(ipos) - baseline);
763 intHist += binValue;
764 if(ipos>=first+5 && ipos<=first+15) {intPulse += binValue;}
765 }
eb7e0771 766
829455ad 767 // gets rid of high frequency noise:
768 // calculating ratio (value one to the right of maximum)/(maximum)
769 // has to be >= 0.1; if maximum==0 set ratio to 0.1
770 Double_t maxCorr = max - baseline;
771 Double_t binRatio = 0.1;
772 if(TMath::Abs(maxCorr) > 1e-5 ) {
773 binRatio = (tempHis->GetBinContent(maxpos+1) - baseline) / maxCorr;
774 }
eb7e0771 775
829455ad 776 // Decision if found pulse is a proper one according to given tresholds
777 if (max>lowLim && max<upLim && !((last-first)<fPulseLength) && rms<fRMSLim && intHist/intPulse<fRatioIntLim && (binRatio >= 0.1) ){
778 // note:
779 // assuming that lowLim is higher than the pedestal value!
780 char hname[100];
781 snprintf(hname,100,"sec%drow%dpad%d",sector,row,pad);
782 TH1F *his = new TH1F(hname,hname, fPulseLength+4, 0, fPulseLength+4);
783 his->SetBinContent(1,1); // pulse counter (1st pulse)
784 his->SetBinContent(2,sector); // sector
785 his->SetBinContent(3,row); // row
786 his->SetBinContent(4,pad); // pad
787
788 for (Int_t ipos=0; ipos<last-first; ipos++){
789 const Double_t signal = tempHis->GetBinContent(ipos+first)-baseline;
790 his->SetBinContent(ipos+5,signal);
791 }
792
793 printf("Pulse found in %s: ADC %d at bin %d \n", hname, max, maxpos+fGateWidth);
794
795 // find the correct TCF parameter according to the his infos
796 // (first 4 bins)
797 Int_t nPulse = FindCorTCFparam(his, nameFileTCF, coefZ, coefP);
798
799 if (nPulse>=minNumPulse) { // Parameters found - doing the TCF quality analysis
eb7e0771 800 Double_t *quVal = GetQualityOfTCF(his,coefZ,coefP, plotFlag);
829455ad 801 qualityTuple->Fill(sector,row,pad,nPulse,quVal[0],quVal[1],quVal[2],quVal[3],quVal[4],quVal[5]);
802 quVal->~Double_t();
803 }
804 his->~TH1F();
805 }
806 tempHis->Reset();
eb7e0771 807 }
829455ad 808 }
809
810
d0bd4fcc 811 printf("Finished to read event ... \n");
eb7e0771 812
7409c8db 813 delete rawStream;
814
815
816 } while (rawReader->NextEvent()); // event loop
eb7e0771 817
d0bd4fcc 818 printf("Finished to read file - close output file ... \n");
819
820 fileOut.cd();
821 qualityTuple->Write("TCFquality",kOverwrite);
822 fileOut.Close();
823
824 tempHis->~TH1I();
825 tempRMSHis->~TH1I();
eb7e0771 826
827 coefP->~Double_t();
828 coefZ->~Double_t();
829
830 rawReader->~AliRawReader();
831
832}
833
df4cfd77 834//____________________________________________________________________________
835TH2F *AliTPCCalibTCF::PlotOccupSummary2Dhist(const char *nameFileIn, Int_t side) {
836 //
837 // Plots the number of summed pulses per pad on a given TPC side
838 // 'nameFileIn': root-file created with the Process function
839 //
840
841 TFile fileIn(nameFileIn,"READ");
842 TH1F *his;
843 TKey *key;
844 TIter next(fileIn.GetListOfKeys());
845
846 TH2F * his2D = new TH2F("his2D","his2D", 250,-250,250,250,-250,250);
8ad79793 847
df4cfd77 848 AliTPCROC * roc = AliTPCROC::Instance();
849
850 Int_t nHist=fileIn.GetNkeys();
8ad79793 851 if (!nHist) { return 0; }
852
df4cfd77 853 Int_t iHist = 0;
854 Float_t xyz[3];
855
856 Int_t binx = 0;
857 Int_t biny = 0;
858
859 Int_t npulse = 0;
860 Int_t sec = 0;
861 Int_t row = 0;
862 Int_t pad = 0;
863
864 while ((key = (TKey *) next())) { // loop over histograms within the file
8ad79793 865 iHist++;
752b0cc7 866
867 TString name(key->GetName());
868 if (name.Contains("ddl") ) continue; // ignore the 2d histogramms per ddl
869
df4cfd77 870 his = (TH1F*)fileIn.Get(key->GetName()); // copy object to memory
871
872 npulse = (Int_t)his->GetBinContent(1);
873 sec = (Int_t)his->GetBinContent(2);
874 row = (Int_t)his->GetBinContent(3);
875 pad = (Int_t)his->GetBinContent(4);
876
8ad79793 877 if ( (side==0) && (sec%36>=18) ) continue;
878 if ( (side>0) && (sec%36<18) ) continue;
df4cfd77 879
56c85970 880 if ( (row<0) && (pad<0) ) { // row and pad are equal to -1, then -> summed pulses per sector
df4cfd77 881 // fill all pad with this values
7409c8db 882 for (UInt_t rowi=0; rowi<roc->GetNRows(sec); rowi++) {
8ad79793 883 for (UInt_t padi=0; padi<roc->GetNPads(sec,rowi); padi++) {
7409c8db 884 roc->GetPositionGlobal(sec,rowi,padi,xyz);
df4cfd77 885 binx = 1+TMath::Nint((xyz[0]+250.)*0.5);
886 biny = 1+TMath::Nint((xyz[1]+250.)*0.5);
887 his2D->SetBinContent(binx,biny,npulse);
888 }
889 }
890 } else {
891 roc->GetPositionGlobal(sec,row,pad,xyz);
892 binx = 1+TMath::Nint((xyz[0]+250.)*0.5);
893 biny = 1+TMath::Nint((xyz[1]+250.)*0.5);
894
895 his2D->SetBinContent(binx,biny,npulse);
896 }
897 if (iHist%100==0){ printf("hist %d out of %d\n",iHist,nHist);}
898 }
899 his2D->SetXTitle("x (cm)");
900 his2D->SetYTitle("y (cm)");
8ad79793 901 his2D->SetStats(0);
902
903 his2D->DrawCopy("colz");
df4cfd77 904
905 if (!side) {
906 gPad->SetTitle("A side");
907 } else {
908 gPad->SetTitle("C side");
909 }
910
df4cfd77 911 return his2D;
912}
913
eb7e0771 914
915//____________________________________________________________________________
df4cfd77 916void AliTPCCalibTCF::PlotOccupSummary(const char *nameFile, Int_t side, Int_t nPulseMin) {
eb7e0771 917 //
918 // Plots the number of summed pulses per pad above a given minimum at the
df4cfd77 919 // pad position at a given TPC side
eb7e0771 920 // 'nameFile': root-file created with the Process function
921 //
922
923 TFile *file = new TFile(nameFile,"READ");
eb7e0771 924 TH1F *his;
925 TKey *key;
926 TIter next( file->GetListOfKeys() );
927
df4cfd77 928
929 char nameFileOut[100];
56c85970 930 snprintf(nameFileOut,100,"Occup-%s",nameFile);
df4cfd77 931 TFile fileOut(nameFileOut,"RECREATE");
8ad79793 932 // fileOut.cd();
df4cfd77 933
eb7e0771 934 TNtuple *ntuple = new TNtuple("ntuple","ntuple","x:y:z:npulse");
8ad79793 935 // ntuple->SetDirectory(0); // force to be memory resistent
eb7e0771 936
df4cfd77 937 Int_t nHist=file->GetNkeys();
8ad79793 938 if (!nHist) { return; }
df4cfd77 939 Int_t iHist = 0;
7409c8db 940
941 Int_t secWise = 0;
942
eb7e0771 943 while ((key = (TKey *) next())) { // loop over histograms within the file
752b0cc7 944
945 TString name(key->GetName());
946 if (name.Contains("ddl") ) continue; // ignore the 2d histogramms per ddl
947
eb7e0771 948 his = (TH1F*)file->Get(key->GetName()); // copy object to memory
8ad79793 949 iHist++;
eb7e0771 950 Int_t npulse = (Int_t)his->GetBinContent(1);
951 Int_t sec = (Int_t)his->GetBinContent(2);
952 Int_t row = (Int_t)his->GetBinContent(3);
953 Int_t pad = (Int_t)his->GetBinContent(4);
954
56c85970 955 if ( (row<0) && (pad<0) ) { // row and pad are equal to -1, then -> summed pulses per sector
eb7e0771 956 row = 40; pad = 40; // set to approx middle row for better plot
7409c8db 957 secWise=1;
eb7e0771 958 }
959
960 Float_t *pos = new Float_t[3];
961 // find x,y,z position of the pad
962 AliTPCROC::Instance()->GetPositionGlobal(sec,row,pad,pos);
963 if (npulse>=nPulseMin) {
964 ntuple->Fill(pos[0],pos[1],pos[2],npulse);
df4cfd77 965 if (iHist%100==0){ printf("hist %d out of %d\n",iHist,nHist);}
eb7e0771 966 }
967 pos->~Float_t();
eb7e0771 968 }
eb7e0771 969
7409c8db 970 if (secWise) { // pulse per sector
eb7e0771 971 ntuple->SetMarkerStyle(8);
972 ntuple->SetMarkerSize(4);
df4cfd77 973 } else { // pulse per Pad
eb7e0771 974 ntuple->SetMarkerStyle(7);
975 }
976
df4cfd77 977 char cSel[100];
978 if (!side) {
56c85970 979 snprintf(cSel,100,"z>0&&npulse>=%d",nPulseMin);
df4cfd77 980 ntuple->Draw("y:x:npulse",cSel,"colz");
df4cfd77 981 } else {
56c85970 982 snprintf(cSel,100,"z<0&&npulse>=%d",nPulseMin);
df4cfd77 983 ntuple->Draw("y:x:npulse",cSel,"colz");
8ad79793 984 }
985
986 if (!side) {
987 gPad->SetTitle("A side");
988 } else {
df4cfd77 989 gPad->SetTitle("C side");
990 }
eb7e0771 991
8ad79793 992
df4cfd77 993 ntuple->Write();
994 fileOut.Close();
eb7e0771 995 file->Close();
eb7e0771 996}
997
998//____________________________________________________________________________
999void AliTPCCalibTCF::PlotQualitySummary(const char *nameFileQuality, const char *plotSpec, const char *cut, const char *pOpt)
1000{
1001 //
1002 // This function is an easy interface to load the QualityTuple (produced with
1003 // the function 'TestOn%File' and plots them according to the plot specifications
1004 // 'plotSpec' e.g. "widthRed:maxUndershot"
1005 // One may also set cut and plot options ("cut","pOpt")
1006 //
1007 // The stored quality parameters are ...
1008 // sec:row:pad:npulse: ... usual pad info
1009 // heightDev ... height deviation in percent
1010 // areaRed ... area reduction in percent
1011 // widthRed ... width reduction in percent
1012 // undershot ... mean undershot after the pulse in ADC
1013 // maxUndershot ... maximum of the undershot after the pulse in ADC
1014 // pulseRMS ... RMS of the pulse used to calculate the Quality parameters in ADC
1015 //
1016
1017 TFile file(nameFileQuality,"READ");
1018 TNtuple *qualityTuple = (TNtuple*)file.Get("TCFquality");
df4cfd77 1019 //gStyle->SetPalette(1);
d0bd4fcc 1020
1021 TH2F *his2D = new TH2F(plotSpec,nameFileQuality,11,-10,1,25,1,100);
1022 char plSpec[100];
56c85970 1023 snprintf(plSpec,100,"%s>>%s",plotSpec,plotSpec);
d0bd4fcc 1024 qualityTuple->Draw(plSpec,cut,pOpt);
1025
1026 gStyle->SetLabelSize(0.03,"X");
1027 gStyle->SetLabelSize(0.03,"Y");
1028 gStyle->SetLabelSize(0.03,"Z");
1029 gStyle->SetLabelOffset(-0.02,"X");
1030 gStyle->SetLabelOffset(-0.01,"Y");
1031 gStyle->SetLabelOffset(-0.03,"Z");
1032
d0bd4fcc 1033 his2D->GetXaxis()->SetTitle("max. undershot [ADC]");
1034 his2D->GetYaxis()->SetTitle("width Reduction [%]");
1035
1036 his2D->DrawCopy(pOpt);
8ad79793 1037
1038 gPad->SetPhi(0.1);gPad->SetTheta(90);
d0bd4fcc 1039
1040 his2D->~TH2F();
eb7e0771 1041
1042}
1043
eb7e0771 1044//_____________________________________________________________________________
1045Int_t AliTPCCalibTCF::FitPulse(TNtuple *dataTuple, Double_t *coefZ, Double_t *coefP) {
1046 //
1047 // function to fit one pulse and to calculate the according pole-zero parameters
1048 //
1049
1050 // initialize TMinuit with a maximum of 8 params
7409c8db 1051 TMinuit *minuitFit = new TMinuit(8);
1052 minuitFit->mncler(); // Reset Minuit's list of paramters
1053 minuitFit->SetPrintLevel(-1); // No Printout
1054 minuitFit->SetFCN(AliTPCCalibTCF::FitFcn); // To set the address of the
eb7e0771 1055 // minimization function
7409c8db 1056 minuitFit->SetObjectFit(dataTuple);
eb7e0771 1057
1058 Double_t arglist[10];
1059 Int_t ierflg = 0;
1060
1061 arglist[0] = 1;
7409c8db 1062 minuitFit->mnexcm("SET ERR", arglist ,1,ierflg);
eb7e0771 1063
1064 // Set standard starting values and step sizes for each parameter
1065 // upper and lower limit (in a reasonable range) are set to improve
1066 // the stability of TMinuit
1067 static Double_t vstart[8] = {125, 4.0, 0.3, 0.5, 5.5, 100, 1, 2.24};
1068 static Double_t step[8] = {0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1};
1069 static Double_t min[8] = {100, 3., 0.1, 0.2, 3., 60., 0., 2.0};
1070 static Double_t max[8] = {200, 20., 5., 3., 30., 300., 20., 2.5};
1071
7409c8db 1072 minuitFit->mnparm(0, "A1", vstart[0], step[0], min[0], max[0], ierflg);
1073 minuitFit->mnparm(1, "A2", vstart[1], step[1], min[1], max[1], ierflg);
1074 minuitFit->mnparm(2, "A3", vstart[2], step[2], min[2], max[2], ierflg);
1075 minuitFit->mnparm(3, "T1", vstart[3], step[3], min[3], max[3], ierflg);
1076 minuitFit->mnparm(4, "T2", vstart[4], step[4], min[4], max[4], ierflg);
1077 minuitFit->mnparm(5, "T3", vstart[5], step[5], min[5], max[5], ierflg);
1078 minuitFit->mnparm(6, "T0", vstart[6], step[6], min[6], max[6], ierflg);
1079 minuitFit->mnparm(7, "TTP", vstart[7], step[7], min[7], max[7],ierflg);
1080 minuitFit->FixParameter(7); // 2.24 ... out of pulserRun Fit (->IRF)
eb7e0771 1081
1082 // Now ready for minimization step
1083 arglist[0] = 2000; // max num of iterations
1084 arglist[1] = 0.1; // tolerance
1085
7409c8db 1086 minuitFit->mnexcm("MIGRAD", arglist ,2,ierflg);
eb7e0771 1087
1088 Double_t p1 = 0.0 ;
7409c8db 1089 minuitFit->mnexcm("SET NOW", &p1 , 0, ierflg) ; // No Warnings
eb7e0771 1090
1091 if (ierflg == 4) { // Fit failed
1092 for (Int_t i=0;i<3;i++) {
1093 coefP[i] = 0;
1094 coefZ[i] = 0;
1095 }
7409c8db 1096 minuitFit->~TMinuit();
eb7e0771 1097 return 0;
1098 } else { // Fit successfull
1099
1100 // Extract parameters from TMinuit
1101 Double_t *fitParam = new Double_t[6];
1102 for (Int_t i=0;i<6;i++) {
1103 Double_t err = 0;
1104 Double_t val = 0;
7409c8db 1105 minuitFit->GetParameter(i,val,err);
eb7e0771 1106 fitParam[i] = val;
1107 }
1108
1109 // calculates the first 2 sets (4 PZ values) out of the fitted parameters
1110 Double_t *valuePZ = ExtractPZValues(fitParam);
1111
1112 // TCF coefficients which are used for the equalisation step (stage)
1113 // ZERO/POLE Filter
9c2921ef 1114 coefZ[0] = TMath::Exp(-1/valuePZ[2]);
1115 coefZ[1] = TMath::Exp(-1/valuePZ[3]);
1116 coefP[0] = TMath::Exp(-1/valuePZ[0]);
1117 coefP[1] = TMath::Exp(-1/valuePZ[1]);
eb7e0771 1118
1119 fitParam->~Double_t();
1120 valuePZ->~Double_t();
7409c8db 1121 minuitFit->~TMinuit();
eb7e0771 1122
1123 return 1;
1124
1125 }
1126
1127}
1128
1129
1130//____________________________________________________________________________
56c85970 1131void AliTPCCalibTCF::FitFcn(Int_t &/*nPar*/, Double_t */*grad*/, Double_t &f, Double_t * const par, Int_t /*iflag*/)
eb7e0771 1132{
1133 //
1134 // Minimization function needed for TMinuit with FitFunction included
1135 // Fit function: Sum of three convolution terms (IRF conv. with Exp.)
1136 //
1137
1138 // Get Data ...
1139 TNtuple *dataTuple = (TNtuple *) gMinuit->GetObjectFit();
1140
1141 //calculate chisquare
1142 Double_t chisq = 0;
1143 Double_t delta = 0;
1144 for (Int_t i=0; i<dataTuple->GetEntries(); i++) { // loop over data points
1145 dataTuple->GetEntry(i);
1146 Float_t *p = dataTuple->GetArgs();
1147 Double_t t = p[0];
1148 Double_t signal = p[1]; // Normalized signal
1149 Double_t error = p[2];
1150
1151 // definition and evaluation if the IonTail specific fit function
1152 Double_t sigFit = 0;
1153
1154 Double_t ttp = par[7]; // signal shaper raising time
1155 t=t-par[6]; // time adjustment
1156
1157 if (t<0) {
1158 sigFit = 0;
1159 } else {
9c2921ef 1160 Double_t f1 = 1/TMath::Power((4-ttp/par[3]),5)*(24*ttp*TMath::Exp(4)*(TMath::Exp(-t/par[3]) - TMath::Exp(-4*t/ttp) * ( 1+t*(4-ttp/par[3])/ttp+TMath::Power(t*(4-ttp/par[3])/ttp,2)/2 + TMath::Power(t*(4-ttp/par[3])/ttp,3)/6 + TMath::Power(t*(4-ttp/par[3])/ttp,4)/24)));
eb7e0771 1161
9c2921ef 1162 Double_t f2 = 1/TMath::Power((4-ttp/par[4]),5)*(24*ttp*TMath::Exp(4)*(TMath::Exp(-t/par[4]) - TMath::Exp(-4*t/ttp) * ( 1+t*(4-ttp/par[4])/ttp+TMath::Power(t*(4-ttp/par[4])/ttp,2)/2 + TMath::Power(t*(4-ttp/par[4])/ttp,3)/6 + TMath::Power(t*(4-ttp/par[4])/ttp,4)/24)));
eb7e0771 1163
9c2921ef 1164 Double_t f3 = 1/TMath::Power((4-ttp/par[5]),5)*(24*ttp*TMath::Exp(4)*(TMath::Exp(-t/par[5]) - TMath::Exp(-4*t/ttp) * ( 1+t*(4-ttp/par[5])/ttp+TMath::Power(t*(4-ttp/par[5])/ttp,2)/2 + TMath::Power(t*(4-ttp/par[5])/ttp,3)/6 + TMath::Power(t*(4-ttp/par[5])/ttp,4)/24)));
eb7e0771 1165
1166 sigFit = par[0]*f1 + par[1]*f2 +par[2]*f3;
1167 }
1168
1169 // chisqu calculation
1170 delta = (signal-sigFit)/error;
1171 chisq += delta*delta;
1172 }
1173
1174 f = chisq;
1175
1176}
1177
1178
1179
1180//____________________________________________________________________________
1181Double_t* AliTPCCalibTCF::ExtractPZValues(Double_t *param) {
1182 //
1183 // Calculation of Pole and Zero values out of fit parameters
1184 //
1185
1186 Double_t vA1, vA2, vA3, vTT1, vTT2, vTT3, vTa, vTb;
1187 vA1 = 0; vA2 = 0; vA3 = 0;
1188 vTT1 = 0; vTT2 = 0; vTT3 = 0;
1189 vTa = 0; vTb = 0;
1190
1191 // nasty method of sorting the fit parameters to avoid wrong mapping
1192 // to the different stages of the TCF filter
1193 // (e.g. first 2 fit parameters represent the electron signal itself!)
1194
56c85970 1195 if ((param[3]-param[4]) <1e-5 ) {param[3]=param[3]+0.0001;} // if equal
1196 if ((param[5]-param[4]) <1e-5 ) {param[5]=param[5]+0.0001;} // if equal
eb7e0771 1197
8ad79793 1198 if ((param[5]>param[4])&&(param[5]>param[3])) {
eb7e0771 1199 if (param[4]>=param[3]) {
1200 vA1 = param[0]; vA2 = param[1]; vA3 = param[2];
1201 vTT1 = param[3]; vTT2 = param[4]; vTT3 = param[5];
1202 } else {
1203 vA1 = param[1]; vA2 = param[0]; vA3 = param[2];
1204 vTT1 = param[4]; vTT2 = param[3]; vTT3 = param[5];
1205 }
8ad79793 1206 } else if ((param[4]>param[5])&&(param[4]>param[3])) {
eb7e0771 1207 if (param[5]>=param[3]) {
1208 vA1 = param[0]; vA2 = param[2]; vA3 = param[1];
1209 vTT1 = param[3]; vTT2 = param[5]; vTT3 = param[4];
1210 } else {
1211 vA1 = param[2]; vA2 = param[0]; vA3 = param[1];
1212 vTT1 = param[5]; vTT2 = param[3]; vTT3 = param[4];
1213 }
8ad79793 1214 } else if ((param[3]>param[4])&&(param[3]>param[5])) {
eb7e0771 1215 if (param[5]>=param[4]) {
1216 vA1 = param[1]; vA2 = param[2]; vA3 = param[0];
1217 vTT1 = param[4]; vTT2 = param[5]; vTT3 = param[3];
1218 } else {
1219 vA1 = param[2]; vA2 = param[1]; vA3 = param[0];
1220 vTT1 = param[5]; vTT2 = param[4]; vTT3 = param[3];
1221 }
1222 }
1223
1224
1225 // Transformation of fit parameters into PZ values (needed by TCF)
1226 Double_t beq = (vA1/vTT2+vA1/vTT3+vA2/vTT1+vA2/vTT3+vA3/vTT1+vA3/vTT2)/(vA1+vA2+vA3);
1227 Double_t ceq = (vA1/(vTT2*vTT3)+vA2/(vTT1*vTT3)+vA3/(vTT1*vTT2))/(vA1+vA2+vA3);
1228
1229 Double_t s1 = -beq/2-sqrt((beq*beq-4*ceq)/4);
1230 Double_t s2 = -beq/2+sqrt((beq*beq-4*ceq)/4);
1231
1232 if (vTT2<vTT3) {// not necessary but avoids significant undershots in first PZ
1233 vTa = -1/s1;
1234 vTb = -1/s2;
1235 }else{
1236 vTa = -1/s2;
1237 vTb = -1/s1;
1238 }
1239
1240 Double_t *valuePZ = new Double_t[4];
1241 valuePZ[0]=vTa;
1242 valuePZ[1]=vTb;
1243 valuePZ[2]=vTT2;
1244 valuePZ[3]=vTT3;
1245
1246 return valuePZ;
1247
1248}
1249
1250
1251//____________________________________________________________________________
d0bd4fcc 1252Int_t AliTPCCalibTCF::Equalization(TNtuple *dataTuple, Double_t *coefZ, Double_t *coefP) {
eb7e0771 1253 //
1254 // calculates the 3rd set of TCF parameters (remaining 2 PZ values) in
1255 // order to restore the original pulse height and adds them to the passed arrays
1256 //
1257
eb7e0771 1258 const Int_t kPulseLength = dataTuple->GetEntries();
56c85970 1259
1260 if (kPulseLength<2) {
1261 // prinft("PulseLength does not make sense\n");
1262 return 0;
1263 }
1264
1265 Double_t *s0 = new Double_t[kPulseLength]; // original pulse
1266 Double_t *s1 = new Double_t[kPulseLength]; // pulse after 1st PZ filter
1267 Double_t *s2 = new Double_t[kPulseLength]; // pulse after 2nd PZ filter
1268
eb7e0771 1269 for (Int_t ipos=0; ipos<kPulseLength; ipos++) {
1270 dataTuple->GetEntry(ipos);
1271 Float_t *p = dataTuple->GetArgs();
1272 s0[ipos] = p[1];
1273 }
1274
1275 // non-discret implementation of the first two TCF stages (recursive formula)
1276 // discrete Altro emulator is not used because of accuracy!
1277 s1[0] = s0[0]; // 1st PZ filter
1278 for(Int_t ipos = 1; ipos < kPulseLength ; ipos++){
1279 s1[ipos] = s0[ipos] + coefP[0]*s1[ipos-1] - coefZ[0]*s0[ipos-1];
1280 }
1281 s2[0] = s1[0]; // 2nd PZ filter
1282 for(Int_t ipos = 1; ipos < kPulseLength ; ipos++){
1283 s2[ipos] = s1[ipos] + coefP[1]*s2[ipos-1] - coefZ[1]*s1[ipos-1];
1284 }
1285
1286 // find maximum amplitude and position of original pulse and pulse after
1287 // the first two stages of the TCF
829455ad 1288 Int_t s0pos = 0;
eb7e0771 1289 Double_t s0ampl = s0[0], s2ampl = s2[0]; // start values
1290 for(Int_t ipos = 1; ipos < kPulseLength; ipos++){
1291 if (s0[ipos] > s0ampl){
1292 s0ampl = s0[ipos];
1293 s0pos = ipos; // should be pos 11 ... check?
1294 }
1295 if (s2[ipos] > s2ampl){
1296 s2ampl = s2[ipos];
eb7e0771 1297 }
1298 }
1299 // calculation of 3rd set ...
1300 if(s0ampl > s2ampl){
1301 coefZ[2] = 0;
1302 coefP[2] = (s0ampl - s2ampl)/s0[s0pos-1];
1303 } else if (s0ampl < s2ampl) {
1304 coefP[2] = 0;
1305 coefZ[2] = (s2ampl - s0ampl)/s0[s0pos-1];
1306 } else { // same height ? will most likely not happen ?
d0bd4fcc 1307 printf("No equalization because of identical height\n");
eb7e0771 1308 coefP[2] = 0;
1309 coefZ[2] = 0;
1310 }
1311
56c85970 1312 delete [] s0;
1313 delete [] s1;
1314 delete [] s2;
df4cfd77 1315
d0bd4fcc 1316 // if equalization out of range (<0 or >=1) it failed!
df4cfd77 1317 // if ratio of amplitudes of fittet to original pulse < 0.9 it failed!
1318 if (coefP[2]<0 || coefZ[2]<0 || coefP[2]>=1 || coefZ[2]>=1 || TMath::Abs(s2ampl / s0ampl)<0.9) {
d0bd4fcc 1319 return 0;
1320 } else {
1321 return 1;
1322 }
df4cfd77 1323
eb7e0771 1324}
1325
1326
1327
1328//____________________________________________________________________________
56c85970 1329Int_t AliTPCCalibTCF::FindCorTCFparam(TH1F * const hisIn, const char *nameFileTCF, Double_t *coefZ, Double_t *coefP) {
eb7e0771 1330 //
1331 // This function searches for the correct TCF parameters to the given
1332 // histogram 'hisIn' within the file 'nameFileTCF'
1333 // If no parameters for this pad (padinfo within the histogram!) where found
1334 // the function returns 0
1335
1336 // Int_t numPulse = (Int_t)hisIn->GetBinContent(1); // number of pulses
1337 Int_t sector = (Int_t)hisIn->GetBinContent(2);
1338 Int_t row = (Int_t)hisIn->GetBinContent(3);
1339 Int_t pad = (Int_t)hisIn->GetBinContent(4);
1340 Int_t nPulse = 0;
1341
1342 //-- searching for calculated TCF parameters for this pad/sector
1343 TFile fileTCF(nameFileTCF,"READ");
1344 TNtuple *paramTuple = (TNtuple*)fileTCF.Get("TCFparam");
1345
1346 // create selection criteria to find the correct TCF params
1347 char sel[100];
1348 if ( paramTuple->GetEntries("row==-1&&pad==-1") ) {
1349 // parameters per SECTOR
56c85970 1350 snprintf(sel,100,"sec==%d&&row==-1&&pad==-1",sector);
eb7e0771 1351 } else {
1352 // parameters per PAD
56c85970 1353 snprintf(sel,100,"sec==%d&&row==%d&&pad==%d",sector,row,pad);
eb7e0771 1354 }
1355
1356 // list should contain just ONE entry! ... otherwise there is a mistake!
1357 Long64_t entry = paramTuple->Draw(">>list",sel,"entrylist");
1358 TEntryList *list = (TEntryList*)gDirectory->Get("list");
1359
1360 if (entry) { // TCF set was found for this pad
1361 Long64_t pos = list->GetEntry(0);
1362 paramTuple->GetEntry(pos); // get specific TCF parameters
1363 Float_t *p = paramTuple->GetArgs();
1364 // check ...
56c85970 1365 if((sector-p[0])<1e-5) {printf("sector ok ... "); }
1366 if((row-p[1])<1e-5) {printf("row ok ... "); }
1367 if((pad-p[2])<1e-5) {printf("pad ok ... \n"); }
eb7e0771 1368
1369 // number of averaged pulses used to produce TCF params
1370 nPulse = (Int_t)p[3];
1371 // TCF parameters
1372 coefZ[0] = p[4]; coefP[0] = p[7];
1373 coefZ[1] = p[5]; coefP[1] = p[8];
1374 coefZ[2] = p[6]; coefP[2] = p[9];
1375
1376 } else { // no specific TCF parameters found for this pad
1377
df4cfd77 1378 printf(" no specific TCF paramaters found for pad in ...\n");
1379 printf(" Sector %d | Row %d | Pad %d |\n", sector, row, pad);
eb7e0771 1380 nPulse = 0;
1381 coefZ[0] = 0; coefP[0] = 0;
1382 coefZ[1] = 0; coefP[1] = 0;
1383 coefZ[2] = 0; coefP[2] = 0;
1384
1385 }
1386
1387 fileTCF.Close();
1388
1389 return nPulse; // number of averaged pulses for producing the TCF params
1390
1391}
1392
1393
1394//____________________________________________________________________________
1395Double_t *AliTPCCalibTCF::GetQualityOfTCF(TH1F *hisIn, Double_t *coefZ, Double_t *coefP, Int_t plotFlag) {
1396 //
1397 // This function evaluates the quality parameters of the given TCF parameters
1398 // tested on the passed pulse (hisIn)
1399 // The quality parameters are stored in an array. They are ...
1400 // height deviation [ADC]
1401 // area reduction [percent]
1402 // width reduction [percent]
1403 // mean undershot [ADC]
1404 // maximum of undershot after pulse [ADC]
1405 // Pulse RMS [ADC]
1406
1407 // perform ALTRO emulator
1408 TNtuple *pulseTuple = ApplyTCFilter(hisIn, coefZ, coefP, plotFlag);
1409
1410 printf("calculate quality val. for pulse in ... ");
1411 printf(" Sector %d | Row %d | Pad %d |\n", (Int_t)hisIn->GetBinContent(2), (Int_t)hisIn->GetBinContent(3), (Int_t)hisIn->GetBinContent(4));
1412
1413 // Reasonable limit for the calculation of the quality values
1414 Int_t binLimit = 80;
1415
1416 // ============== Variable preparation
1417
1418 // -- height difference in percent of orginal pulse
1419 Double_t maxSig = pulseTuple->GetMaximum("sig");
1420 Double_t maxSigTCF = pulseTuple->GetMaximum("sigAfterTCF");
1421 // -- area reduction (above zero!)
1422 Double_t area = 0;
1423 Double_t areaTCF = 0;
1424 // -- width reduction at certain ADC treshold
1425 // TODO: set treshold at ZS treshold? (3 sigmas of noise?)
1426 Int_t threshold = 3; // treshold in percent
1427 Int_t threshADC = (Int_t)(maxSig/100*threshold);
1428 Int_t startOfPulse = 0; Int_t startOfPulseTCF = 0;
1429 Int_t posOfStart = 0; Int_t posOfStartTCF = 0;
1430 Int_t widthFound = 0; Int_t widthFoundTCF = 0;
1431 Int_t width = 0; Int_t widthTCF = 0;
1432 // -- Calcluation of Undershot (mean of negavive signal after the first
1433 // undershot)
1434 Double_t undershotTCF = 0;
1435 Double_t undershotStart = 0;
1436 // -- Calcluation of Undershot (Sum of negative signal after the pulse)
1437 Double_t maxUndershot = 0;
1438
1439
1440 // === loop over timebins to calculate quality parameters
1441 for (Int_t i=0; i<binLimit; i++) {
1442
1443 // Read signal values
1444 pulseTuple->GetEntry(i);
1445 Float_t *p = pulseTuple->GetArgs();
1446 Double_t sig = p[1];
1447 Double_t sigTCF = p[2];
1448
1449 // calculation of area (above zero)
1450 if (sig>0) {area += sig; }
1451 if (sigTCF>0) {areaTCF += sigTCF; }
1452
1453
1454 // Search for width at certain ADC treshold
1455 // -- original signal
1456 if (widthFound == 0) {
1457 if( (sig > threshADC) && (startOfPulse == 0) ){
1458 startOfPulse = 1;
1459 posOfStart = i;
1460 }
d0bd4fcc 1461 if( (sig <= threshADC) && (startOfPulse == 1) ){
eb7e0771 1462 widthFound = 1;
1463 width = i - posOfStart + 1;
1464 }
1465 }
1466 // -- signal after TCF
1467 if (widthFoundTCF == 0) {
1468 if( (sigTCF > threshADC) && (startOfPulseTCF == 0) ){
1469 startOfPulseTCF = 1;
1470 posOfStartTCF = i;
1471 }
d0bd4fcc 1472 if( (sigTCF <= threshADC) && (startOfPulseTCF == 1) ){
eb7e0771 1473 widthFoundTCF = 1;
1474 widthTCF = i -posOfStartTCF + 1;
1475 }
1476
1477 }
1478
1479 // finds undershot start
1480 if ( (widthFoundTCF==1) && (sigTCF<0) ) {
1481 undershotStart = 1;
1482 }
1483
1484 // Calculation of undershot sum (after pulse)
1485 if ( widthFoundTCF==1 ) {
1486 undershotTCF += sigTCF;
1487 }
1488
1489 // Search for maximal undershot (is equal to minimum after the pulse)
56c85970 1490 if ( ((undershotStart-1)<1e-7)&&(i<(posOfStartTCF+widthTCF+20)) ) {
eb7e0771 1491 if (maxUndershot>sigTCF) { maxUndershot = sigTCF; }
1492 }
1493
1494 }
1495
1496 // == Calculation of Quality parameters
1497
1498 // -- height difference in ADC
1499 Double_t heightDev = maxSigTCF-maxSig;
1500
1501 // Area reduction of the pulse in percent
1502 Double_t areaReduct = 100-areaTCF/area*100;
1503
1504 // Width reduction in percent
1505 Double_t widthReduct = 0;
1506 if ((widthFound==1)&&(widthFoundTCF==1)) { // in case of not too big IonTail
1507 widthReduct = 100-(Double_t)widthTCF/(Double_t)width*100;
1508 if (widthReduct<0) { widthReduct = 0;}
1509 }
1510
1511 // Undershot - mean of neg.signals after pulse
1512 Double_t length = 1;
1513 if (binLimit-widthTCF-posOfStartTCF) { length = (binLimit-widthTCF-posOfStartTCF);}
1514 Double_t undershot = undershotTCF/length;
1515
1516
1517 // calculation of pulse RMS with timebins before and at the end of the pulse
1518 TH1I *tempRMSHis = new TH1I("tempRMSHis","tempRMSHis",100,-50,50);
1519 for (Int_t ipos = 0; ipos<6; ipos++) {
1520 // before the pulse
1521 tempRMSHis->Fill(hisIn->GetBinContent(ipos+5));
55f06b51 1522 // at the end
eb7e0771 1523 tempRMSHis->Fill(hisIn->GetBinContent(hisIn->GetNbinsX()-ipos));
1524 }
1525 Double_t pulseRMS = tempRMSHis->GetRMS();
1526 tempRMSHis->~TH1I();
1527
1528 if (plotFlag) {
1529 // == Output
1530 printf("height deviation [ADC]:\t\t\t %3.1f\n", heightDev);
1531 printf("area reduction [percent]:\t\t %3.1f\n", areaReduct);
1532 printf("width reduction [percent]:\t\t %3.1f\n", widthReduct);
1533 printf("mean undershot [ADC]:\t\t\t %3.1f\n", undershot);
1534 printf("maximum of undershot after pulse [ADC]: %3.1f\n", maxUndershot);
55f06b51 1535 printf("RMS of the original (or summed) pulse [ADC]: \t %3.2f\n\n", pulseRMS);
eb7e0771 1536
1537 }
1538
1539 Double_t *qualityParam = new Double_t[6];
1540 qualityParam[0] = heightDev;
1541 qualityParam[1] = areaReduct;
1542 qualityParam[2] = widthReduct;
1543 qualityParam[3] = undershot;
1544 qualityParam[4] = maxUndershot;
1545 qualityParam[5] = pulseRMS;
1546
1547 pulseTuple->~TNtuple();
1548
1549 return qualityParam;
1550}
1551
1552
1553//____________________________________________________________________________
56c85970 1554TNtuple *AliTPCCalibTCF::ApplyTCFilter(TH1F * const hisIn, Double_t * const coefZ, Double_t * const coefP, Int_t plotFlag) {
eb7e0771 1555 //
1556 // Applies the given TCF parameters on the given pulse via the ALTRO emulator
1557 // class (discret values) and stores both pulses into a returned TNtuple
1558 //
1559
1560 Int_t nbins = hisIn->GetNbinsX() -4;
1561 // -1 because the first four timebins usually contain pad specific informations
1562 Int_t nPulse = (Int_t)hisIn->GetBinContent(1); // Number of summed pulses
1563 Int_t sector = (Int_t)hisIn->GetBinContent(2);
1564 Int_t row = (Int_t)hisIn->GetBinContent(3);
1565 Int_t pad = (Int_t)hisIn->GetBinContent(4);
1566
1567 // redirect histogram values to arrays (discrete for altro emulator)
1568 Double_t *signalIn = new Double_t[nbins];
1569 Double_t *signalOut = new Double_t[nbins];
1570 short *signalInD = new short[nbins];
1571 short *signalOutD = new short[nbins];
1572 for (Int_t ipos=0;ipos<nbins;ipos++) {
1573 Double_t signal = hisIn->GetBinContent(ipos+5); // summed signal
1574 signalIn[ipos]=signal/nPulse; // mean signal
1575 signalInD[ipos]=(short)(TMath::Nint(signalIn[ipos])); //discrete mean signal
1576 signalOutD[ipos]=signalInD[ipos]; // will be overwritten by AltroEmulator
1577 }
1578
1579 // transform TCF parameters into ALTRO readable format (Integer)
6fefa5ce 1580 Int_t valK[3];
1581 Int_t valL[3];
eb7e0771 1582 for (Int_t i=0; i<3; i++) {
df4cfd77 1583 valK[i] = (Int_t)(coefP[i]*(TMath::Power(2,16)-1));
1584 valL[i] = (Int_t)(coefZ[i]*(TMath::Power(2,16)-1));
eb7e0771 1585 }
1586
1587 // discret ALTRO EMULATOR ____________________________
1588 AliTPCAltroEmulator *altro = new AliTPCAltroEmulator(nbins, signalOutD);
1589 altro->ConfigAltro(0,1,0,0,0,0); // perform just the TailCancelation
df4cfd77 1590 altro->ConfigTailCancellationFilter(valK[0],valK[1],valK[2],valL[0],valL[1],valL[2]);
eb7e0771 1591 altro->RunEmulation();
1592 delete altro;
1593
1594 // non-discret implementation of the (recursive formula)
1595 // discrete Altro emulator is not used because of accuracy!
1596 Double_t *s1 = new Double_t[1000]; // pulse after 1st PZ filter
1597 Double_t *s2 = new Double_t[1000]; // pulse after 2nd PZ filter
1598 s1[0] = signalIn[0]; // 1st PZ filter
1599 for(Int_t ipos = 1; ipos<nbins; ipos++){
1600 s1[ipos] = signalIn[ipos] + coefP[0]*s1[ipos-1] - coefZ[0]*signalIn[ipos-1];
1601 }
1602 s2[0] = s1[0]; // 2nd PZ filter
1603 for(Int_t ipos = 1; ipos<nbins; ipos++){
1604 s2[ipos] = s1[ipos] + coefP[1]*s2[ipos-1] - coefZ[1]*s1[ipos-1];
1605 }
1606 signalOut[0] = s2[0]; // 3rd PZ filter
1607 for(Int_t ipos = 1; ipos<nbins; ipos++){
1608 signalOut[ipos] = s2[ipos] + coefP[2]*signalOut[ipos-1] - coefZ[2]*s2[ipos-1];
1609 }
1610 s1->~Double_t();
1611 s2->~Double_t();
1612
1613 // writing pulses to tuple
1614 TNtuple *pulseTuple = new TNtuple("ntupleTCF","PulseTCF","timebin:sig:sigAfterTCF:sigND:sigNDAfterTCF");
1615 for (Int_t ipos=0;ipos<nbins;ipos++) {
1616 pulseTuple->Fill(ipos,signalInD[ipos],signalOutD[ipos],signalIn[ipos],signalOut[ipos]);
1617 }
1618
1619 if (plotFlag) {
1620 char hname[100];
56c85970 1621 snprintf(hname,100,"sec%drow%dpad%d",sector,row,pad);
eb7e0771 1622 new TCanvas(hname,hname,600,400);
1623 //just plotting non-discret pulses | they look pretties in case of mean sig ;-)
1624 pulseTuple->Draw("sigND:timebin","","L");
1625 // pulseTuple->Draw("sig:timebin","","Lsame");
1626 pulseTuple->SetLineColor(3);
1627 pulseTuple->Draw("sigNDAfterTCF:timebin","","Lsame");
1628 // pulseTuple->Draw("sigAfterTCF:timebin","","Lsame");
1629 }
1630
4ce766eb 1631 delete [] signalIn;
1632 delete [] signalOut;
56c85970 1633 delete [] signalInD;
1634 delete [] signalOutD;
1635
eb7e0771 1636 return pulseTuple;
1637
1638}
1639
1640
eb7e0771 1641//____________________________________________________________________________
1642void AliTPCCalibTCF::PrintPulseThresholds() {
1643 //
1644 // Prints the pulse threshold settings
1645 //
1646
1647 printf(" %4.0d [ADC] ... expected Gate fluctuation length \n", fGateWidth);
1648 printf(" %4.0d [ADC] ... expected usefull signal length \n", fSample);
1649 printf(" %4.0d [ADC] ... needed pulselength for TC characterisation \n", fPulseLength);
1650 printf(" %4.0d [ADC] ... lower pulse height limit \n", fLowPulseLim);
1651 printf(" %4.0d [ADC] ... upper pulse height limit \n", fUpPulseLim);
1652 printf(" %4.1f [ADC] ... maximal pulse RMS \n", fRMSLim);
df4cfd77 1653 printf(" %4.1f [ADC] ... pulse/tail integral ratio \n", fRatioIntLim);
eb7e0771 1654
1655}
d0bd4fcc 1656
1657
1658//____________________________________________________________________________
df4cfd77 1659void AliTPCCalibTCF::MergeHistoPerFile(const char *fileNameIn, const char *fileNameSum, Int_t mode)
d0bd4fcc 1660{
df4cfd77 1661 // Gets histograms from fileNameIn and adds contents to fileSum
1662 //
1663 // If fileSum doesn't exist, fileSum is created
1664 // mode = 0, just ONE BIG FILE ('fileSum') will be used
1665 // mode = 1, one file per sector ('fileSum-Sec#.root') will be used
1666 // mode=1 is much faster, but the additional function 'MergeToOneFile' has to be used in order to
1667 // get one big and complete collection file again ...
d0bd4fcc 1668 //
df4cfd77 1669 // !Make sure not to add the same file more than once!
d0bd4fcc 1670
1671 TFile fileIn(fileNameIn,"READ");
1672 TH1F *hisIn;
1673 TKey *key;
1674 TIter next(fileIn.GetListOfKeys());
56c85970 1675 // opens a file, although, it might not be uses (see "mode")
1676 TFile *fileOut = new TFile(fileNameSum,"UPDATE");
d0bd4fcc 1677 //fileOut.cd();
1678
1679 Int_t nHist=fileIn.GetNkeys();
1680 Int_t iHist=0;
df4cfd77 1681
1682 Int_t secPrev = -1;
1683 char fileNameSumSec[100];
1684
56c85970 1685
d0bd4fcc 1686 while((key=(TKey*)next())) {
1687 const char *hisName = key->GetName();
1688
752b0cc7 1689 TString name(key->GetName());
1690 if (name.Contains("ddl") ) continue; // ignore the 2d histogramms per ddl
1691
d0bd4fcc 1692 hisIn=(TH1F*)fileIn.Get(hisName);
338e0dd9 1693
d0bd4fcc 1694 Int_t numPulse=(Int_t)hisIn->GetBinContent(1);
df4cfd77 1695 Int_t sec=(Int_t)hisIn->GetBinContent(2);
d0bd4fcc 1696 Int_t pulseLength= hisIn->GetNbinsX()-4;
1697
df4cfd77 1698 // in case of mode 1, store histos in files per sector
1699 if (sec!=secPrev && mode != 0) {
1700 if (secPrev>0) { // closing old file
1701 fileOut->Close();
1702 }
1703 // opening new file
56c85970 1704 snprintf(fileNameSumSec,100,"%s-Sec%d.root",fileNameSum,sec);
df4cfd77 1705 fileOut = new TFile(fileNameSumSec,"UPDATE");
1706 secPrev = sec;
1707 }
d0bd4fcc 1708
df4cfd77 1709 // search for existing histogram
1710 TH1F *his=(TH1F*)fileOut->Get(hisName);
1711 if (iHist%100==0) {
1712 printf("Histogram %d / %d, %s, Action: ",iHist,nHist,hisName);
1713 if (!his) {
1714 printf("NEW\n");
1715 } else {
1716 printf("ADD\n");
1717 }
1718 }
1719 iHist++;
1720
d0bd4fcc 1721 if (!his) {
d0bd4fcc 1722 his=hisIn;
1723 his->Write(hisName);
1724 } else {
d0bd4fcc 1725 his->AddBinContent(1,numPulse);
1726 for (Int_t ii=5; ii<pulseLength+5; ii++) {
1727 his->AddBinContent(ii,hisIn->GetBinContent(ii));
1728 }
1729 his->Write(hisName,TObject::kOverwrite);
1730 }
1731 }
df4cfd77 1732
d0bd4fcc 1733 printf("closing files (may take a while)...\n");
df4cfd77 1734 fileOut->Close();
1735
1736
d0bd4fcc 1737 fileIn.Close();
1738 printf("...DONE\n\n");
1739}
1740
df4cfd77 1741
1742//____________________________________________________________________________
1743void AliTPCCalibTCF::MergeToOneFile(const char *nameFileSum) {
1744
1745 // Merges all Sec-files together ...
1746 // this is an additional functionality for the function MergeHistsPerFile
1747 // if for example mode=1
1748
1749 TH1F *hisIn;
1750 TKey *key;
1751
1752 // just delete the file entries ...
7409c8db 1753 TFile fileSumD(nameFileSum,"RECREATE");
1754 fileSumD.Close();
df4cfd77 1755
1756 char nameFileSumSec[100];
1757
1758 for (Int_t sec=0; sec<72; sec++) { // loop over all possible filenames
1759
56c85970 1760 snprintf(nameFileSumSec,100,"%s-Sec%d.root",nameFileSum,sec);
df4cfd77 1761 TFile *fileSumSec = new TFile(nameFileSumSec,"READ");
1762
1763 Int_t nHist=fileSumSec->GetNkeys();
1764 Int_t iHist=0;
1765
1766 if (nHist) { // file found \ NKeys not empty
1767
1768 TFile fileSum(nameFileSum,"UPDATE");
1769 fileSum.cd();
1770
1771 printf("Sector file %s found\n",nameFileSumSec);
1772 TIter next(fileSumSec->GetListOfKeys());
71a41e6c 1773 while( (key=(TKey*)next()) ) {
df4cfd77 1774 const char *hisName = key->GetName();
338e0dd9 1775 TString name(hisName);
1776 if (name.Contains("ddl") ) continue; // ignore the 2d histogramms per ddl
df4cfd77 1777 hisIn=(TH1F*)fileSumSec->Get(hisName);
1778
338e0dd9 1779
df4cfd77 1780 if (iHist%100==0) {
1781 printf("found histogram %d / %d, %s\n",iHist,nHist,hisName);
1782 }
1783 iHist++;
1784
1785 // TH1F *his = (TH1F*)hisIn->Clone(hisName);
1786 hisIn->Write(hisName);
1787
1788 }
1789 printf("Saving histograms from sector %d (may take a while) ...",sec);
1790 fileSum.Close();
1791
1792 }
1793 fileSumSec->Close();
1794 }
1795 printf("...DONE\n\n");
1796}
1797
1798
1799//____________________________________________________________________________
1800Int_t AliTPCCalibTCF::DumpTCFparamToFilePerPad(const char *nameFileTCFPerPad,const char *nameFileTCFPerSec, const char *nameMappingFile) {
1801 //
1802 // Writes TCF parameters per PAD to .data file
1803 //
1804 // from now on: "roc" refers to the offline sector numbering
1805 // "sector" refers to the 18 sectors per side
1806 //
1807 // Gets TCF parameters of single pads from nameFileTCFPerPad and writes them to
1808 // the file 'tpcTCFparamPAD.data'
1809 //
1810 // If there are parameters for a pad missing, then the parameters of the roc,
1811 // in which the pad is located, are used as the pad parameters. The parameters for
1812 // the roc are retreived from nameFileTCFPerSec. If there are parameters for
1813 // a roc missing, then the parameters are set to -1.
1814
56c85970 1815 Float_t k0 = -1, k1 = -1, k2 = -1, l0 = -1, l1 = -1, l2 = -1;
df4cfd77 1816 Int_t roc, row, pad, side, sector, rcu, hwAddr;
1817 Int_t entryNum = 0;
1818 Int_t checksum = 0;
1819 Int_t tpcPadNum = 557568;
1820 Int_t validFlag = 1; // 1 if parameters for pad exist, 0 if they are only inherited from the roc
1821
df4cfd77 1822 // get file/tuple with parameters per pad
1823 TFile fileTCFparam(nameFileTCFPerPad);
1824 TNtuple *paramTuple = (TNtuple*)fileTCFparam.Get("TCFparam");
1825
1826 // get mapping file
1827 // usual location of mapping file: $ALICE_ROOT/TPC/Calib/tpcMapping.root
1828 TFile *fileMapping = new TFile(nameMappingFile, "read");
1829 AliTPCmapper *mapping = (AliTPCmapper*) fileMapping->Get("tpcMapping");
1830 delete fileMapping;
1831
1832 if (mapping == 0) {
1833 printf("Failed to get mapping object from %s. ...\n", nameMappingFile);
1834 return -1;
1835 } else {
1836 printf("Got mapping object from %s\n", nameMappingFile);
1837 }
1838
5af1bc5b 1839 Bool_t *entryID = new Bool_t[7200000]; // helping vector
1840 for (Int_t ii = 0; ii<7200000; ii++) {
1841 entryID[ii]=0;
1842 }
1843
df4cfd77 1844 // creating outputfile
1845 ofstream fileOut;
1846 char nameFileOut[255];
56c85970 1847 snprintf(nameFileOut,255,"tpcTCFparamPAD.data");
df4cfd77 1848 fileOut.open(nameFileOut);
1849 // following not used:
1850 // char headerLine[255];
56c85970 1851 // snprintf(headerLine,255,"15\tside\tsector\tRCU\tHWadr\tk0\tk1\tk2\tl0\tl1\tl2\tValidFlag");
df4cfd77 1852 // fileOut << headerLine << std::endl;
1853 fileOut << "15" << std::endl;
1854
1855 // loop over nameFileTCFPerPad, write parameters into outputfile
1856 // NOTE: NO SPECIFIC ORDER !!!
1857 printf("\nstart assigning parameters to pad...\n");
1858 for (Int_t iParam = 0; iParam < paramTuple->GetEntries(); iParam++) {
1859 paramTuple->GetEntry(iParam);
1860 Float_t *paramArgs = paramTuple->GetArgs();
1861 roc = Int_t(paramArgs[0]);
1862 row = Int_t(paramArgs[1]);
1863 pad = Int_t(paramArgs[2]);
1864 side = Int_t(mapping->GetSideFromRoc(roc));
1865 sector = Int_t(mapping->GetSectorFromRoc(roc));
1866 rcu = Int_t(mapping->GetRcu(roc,row,pad));
1867 hwAddr = Int_t(mapping->GetHWAddress(roc,row,pad));
56c85970 1868 k0 = TMath::Nint(paramArgs[7] * (TMath::Power(2,16) - 1));
1869 k1 = TMath::Nint(paramArgs[8] * (TMath::Power(2,16) - 1));
1870 k2 = TMath::Nint(paramArgs[9] * (TMath::Power(2,16) - 1));
1871 l0 = TMath::Nint(paramArgs[4] * (TMath::Power(2,16) - 1));
1872 l1 = TMath::Nint(paramArgs[5] * (TMath::Power(2,16) - 1));
1873 l2 = TMath::Nint(paramArgs[6] * (TMath::Power(2,16) - 1));
df4cfd77 1874 if (entryNum%10000==0) {
1875 printf("assigned pad %i / %i\n",entryNum,tpcPadNum);
1876 }
1877
1878 fileOut << entryNum++ << "\t" << side << "\t" << sector << "\t" << rcu << "\t" << hwAddr << "\t";
56c85970 1879 fileOut << k0 << "\t" << k1 << "\t" << k2 << "\t" << l0 << "\t" << l1 << "\t" << l2 << "\t" << validFlag << std::endl;
df4cfd77 1880 entryID[roc*100000 + row*1000 + pad] = 1;
1881 }
1882
1883 // Wrote all found TCF params per pad into data file
1884 // NOW FILLING UP THE REST WITH THE PARAMETERS FROM THE ROC MEAN
1885
1886 // get file/tuple with parameters per roc
1887 TFile fileSecTCFparam(nameFileTCFPerSec);
1888 TNtuple *paramTupleSec = (TNtuple*)fileSecTCFparam.Get("TCFparam");
1889
1890 // loop over all pads and get/write parameters for pads which don't have
1891 // parameters assigned yet
1892 validFlag = 0;
1893 for (roc = 0; roc<72; roc++) {
1894 side = Int_t(mapping->GetSideFromRoc(roc));
1895 sector = Int_t(mapping->GetSectorFromRoc(roc));
1896 for (Int_t iParamSec = 0; iParamSec < paramTupleSec->GetEntries(); iParamSec++) {
1897 paramTupleSec->GetEntry(iParamSec);
1898 Float_t *paramArgsSec = paramTupleSec->GetArgs();
56c85970 1899 if ((paramArgsSec[0]-roc)<1e-7) { // if roc is found
1900 k0 = TMath::Nint(paramArgsSec[7] * (TMath::Power(2,16) - 1));
1901 k1 = TMath::Nint(paramArgsSec[8] * (TMath::Power(2,16) - 1));
1902 k2 = TMath::Nint(paramArgsSec[9] * (TMath::Power(2,16) - 1));
1903 l0 = TMath::Nint(paramArgsSec[4] * (TMath::Power(2,16) - 1));
1904 l1 = TMath::Nint(paramArgsSec[5] * (TMath::Power(2,16) - 1));
1905 l2 = TMath::Nint(paramArgsSec[6] * (TMath::Power(2,16) - 1));
df4cfd77 1906 break;
1907 } else {
56c85970 1908 k0 = k1 = k2 = l0 = l1 = l2 = -1;
df4cfd77 1909 }
1910 }
1911 for (row = 0; row<mapping->GetNpadrows(roc); row++) {
1912 for (pad = 0; pad<mapping->GetNpads(roc,row); pad++) {
1913 if (entryID[roc*100000 + row*1000 + pad]==1) {
1914 continue;
1915 }
1916
1917 entryID[roc*100000 + row*1000 + pad] = 1;
1918 rcu = Int_t(mapping->GetRcu(roc,row,pad));
1919 hwAddr = Int_t(mapping->GetHWAddress(roc,row,pad));
1920 if (entryNum%10000==0) {
1921 printf("assigned pad %i / %i\n",entryNum,tpcPadNum);
1922 }
1923
1924 fileOut << entryNum++ << "\t" << side << "\t" << sector << "\t" << rcu << "\t" << hwAddr << "\t";
56c85970 1925 fileOut << k0 << "\t" << k1 << "\t" << k2 << "\t" << l0 << "\t" << l1 << "\t" << l2 << "\t" << validFlag << std::endl;
df4cfd77 1926 }
1927 }
1928 }
1929
1930 printf("assigned pad %i / %i\ndone assigning\n",entryNum,tpcPadNum);
1931
1932 // check if correct amount of sets of parameters were written
1933 for (Int_t ii = 0; ii<7200000; ii++) {
1934 checksum += entryID[ii];
1935 }
1936 if (checksum == tpcPadNum) {
1937 printf("checksum ok, sets of parameters written = %i\n",checksum);
1938 } else {
1939 printf("\nCHECKSUM WRONG, sets of parameters written = %i, should be %i\n\n",checksum,tpcPadNum);
1940 }
1941
1942 // closing & destroying
1943 fileOut.close();
1944 fileTCFparam.Close();
1945 fileSecTCFparam.Close();
56c85970 1946 delete [] entryID;
df4cfd77 1947 printf("output written to file: %s\n",nameFileOut);
1948 return 0;
1949}
1950
1951
1952
1953//____________________________________________________________________________
1954Int_t AliTPCCalibTCF::DumpTCFparamToFilePerSector(const char *nameFileTCFPerSec, const char *nameMappingFile) {
1955 //
1956 // Writes TCF parameters per SECTOR (=ROC) to .data file
1957 //
1958 // from now on: "roc" refers to the offline sector numbering
1959 // "sector" refers to the 18 sectors per side
1960 //
1961 // Gets TCF parameters of a roc from nameFileTCFPerSec and writes them to
1962 // the file 'tpcTCFparamSector.data'
1963 //
1964 // If there are parameters for a roc missing, then the parameters are set to -1
1965
56c85970 1966 Float_t k0 = -1, k1 = -1, k2 = -1, l0 = -1, l1 = -1, l2 = -1;
df4cfd77 1967 Int_t entryNum = 0;
1968 Int_t validFlag = 0; // 1 if parameters for roc exist
1969
1970 // get file/tuple with parameters per roc
1971 TFile fileTCFparam(nameFileTCFPerSec);
1972 TNtuple *paramTupleSec = (TNtuple*)fileTCFparam.Get("TCFparam");
1973
1974
1975 // get mapping file
1976 // usual location of mapping file: $ALICE_ROOT/TPC/Calib/tpcMapping.root
1977 TFile *fileMapping = new TFile(nameMappingFile, "read");
1978 AliTPCmapper *mapping = (AliTPCmapper*) fileMapping->Get("tpcMapping");
1979 delete fileMapping;
1980
1981 if (mapping == 0) {
1982 printf("Failed to get mapping object from %s. ...\n", nameMappingFile);
1983 return -1;
1984 } else {
1985 printf("Got mapping object from %s\n", nameMappingFile);
1986 }
1987
1988
1989 // creating outputfile
1990
1991 ofstream fileOut;
1992 char nameFileOut[255];
56c85970 1993 snprintf(nameFileOut,255,"tpcTCFparamSector.data");
df4cfd77 1994 fileOut.open(nameFileOut);
1995 // following not used:
1996 // char headerLine[255];
56c85970 1997 // snprintf(headerLine,255,"16\tside\tsector\tRCU\tHWadr\tk0\tk1\tk2\tl0\tl1\tl2\tValidFlag");
df4cfd77 1998 // fileOut << headerLine << std::endl;
1999 fileOut << "16" << std::endl;
2000
2001 // loop over all rcu's in the TPC (6 per sector)
2002 printf("\nstart assigning parameters to rcu's...\n");
2003 for (Int_t side = 0; side<2; side++) {
2004 for (Int_t sector = 0; sector<18; sector++) {
2005 for (Int_t rcu = 0; rcu<6; rcu++) {
2006
2007 validFlag = 0;
2008 Int_t roc = Int_t(mapping->GetRocFromPatch(side, sector, rcu));
2009
2010 // get parameters (through loop search) for rcu from corresponding roc
2011 for (Int_t iParam = 0; iParam < paramTupleSec->GetEntries(); iParam++) {
2012 paramTupleSec->GetEntry(iParam);
2013 Float_t *paramArgs = paramTupleSec->GetArgs();
56c85970 2014 if ((paramArgs[0]-roc)<1e-7) { // if roc is found
df4cfd77 2015 validFlag = 1;
56c85970 2016 k0 = TMath::Nint(paramArgs[7] * (TMath::Power(2,16) - 1));
2017 k1 = TMath::Nint(paramArgs[8] * (TMath::Power(2,16) - 1));
2018 k2 = TMath::Nint(paramArgs[9] * (TMath::Power(2,16) - 1));
2019 l0 = TMath::Nint(paramArgs[4] * (TMath::Power(2,16) - 1));
2020 l1 = TMath::Nint(paramArgs[5] * (TMath::Power(2,16) - 1));
2021 l2 = TMath::Nint(paramArgs[6] * (TMath::Power(2,16) - 1));
df4cfd77 2022 break;
2023 }
2024 }
2025 if (!validFlag) { // No TCF parameters found for this roc
56c85970 2026 k0 = k1 = k2 = l0 = l1 = l2 = -1;
df4cfd77 2027 }
2028
2029 fileOut << entryNum++ << "\t" << side << "\t" << sector << "\t" << rcu << "\t" << -1 << "\t";
56c85970 2030 fileOut << k0 << "\t" << k1 << "\t" << k2 << "\t" << l0 << "\t" << l1 << "\t" << l2 << "\t" << validFlag << std::endl;
df4cfd77 2031 }
2032 }
2033 }
2034
2035 printf("done assigning\n");
2036
2037 // closing files
2038 fileOut.close();
2039 fileTCFparam.Close();
2040 printf("output written to file: %s\n",nameFileOut);
2041 return 0;
2042
2043}