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