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