]> git.uio.no Git - u/mrichter/AliRoot.git/blob - TPC/TPCcalib/AliTPCcalibTracksGain.cxx
Adding new version of AliTPCCalibTracksGain
[u/mrichter/AliRoot.git] / TPC / TPCcalib / AliTPCcalibTracksGain.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 ////////////////////////////////////////////////////////////////////////////
17 //                                                                        
18 //       === Calibration class for gain calibration using tracks ===
19 //
20 //    1) Genereal idea
21 //    ================
22 //       A 6-parametric parabolic function
23 //
24 //          G(x, y) = p0 + p1*x + p2*y + p3*x^2 + p4*y^2 + p5 * x*y
25 //
26 //       is fitted to the maximum charge values or total charge values of
27 //       all the clusters contained in the tracks that are added to this
28 //       object. This fit is performed for each read out chamber, in fact even
29 //       for each type of pad sizes (thus for one segment, which consists of
30 //       an IROC and an OROC, there are three fitters used, corresponding to
31 //       the three pad sizes). The coordinate origin is at the center of the
32 //       particular pad size region on each ROC.
33 //
34 //       Because of the Landau nature of the charge deposition we use
35 //       different "types" of fitters instead of one to minimize the effect
36 //       of the long Landau tail. The difference between the fitters is only
37 //       the charge value, that is put into them, i.e. the charge is subject
38 //       to a transformation. At this point we use three different fit types:
39 //
40 //          a) simple: the charge is put in as it is
41 //          b) sqrt:   the square root of the charge is put into the fitter
42 //          c) log:    fgkM * Log(1+q/fgkM) is put into the fitter, with
43 //                     q being the untransformed charge and fgkM=25
44 //
45 //       The results of the fits may be visualized and further used by
46 //       creating an AliTPCCalROC or AliTPCCalPad. You may specify to undo
47 //       the transformation and/or to normalize to the pad size.
48 //
49 //       Not every track you add to this object is actually used for
50 //       calibration. There are some cuts and conditions to exclude bad
51 //       tracks, e.g. a pt cut to cut out tracks with too much charge
52 //       deposition or a cut on edge clusters which are not fully
53 //       registered and don't give a usable signal.
54 //
55 //    2) Interface / usage
56 //    ====================
57 //       For each track to be added you need to call Process().
58 //       This method expects an AliTPCseed, which contains the necessary
59 //       cluster information. At the moment of writing this information
60 //       is stored in an AliESDfriend corresponding to an AliESD.
61 //       You may also call AddTrack() if you don't want the cuts and
62 //       other quality conditions to kick in (thus forcing the object to
63 //       accept the track) or AddCluster() for adding single clusters.
64 //       Call one of the Evaluate functions to evaluate the fitter(s) and
65 //       to retrieve the fit parameters, erros and so on. You can also
66 //       do this later on by using the different Getters.
67 //
68 //       The visualization methods CreateFitCalPad() and CreateFitCalROC()
69 //       are straight forward to use.
70 //
71 //       Note: If you plan to write this object to a ROOT file, make sure
72 //             you evaluate all the fitters *before* writing, because due
73 //             to a bug in the fitter component writing fitters doesn't
74 //             work properly (yet). Be aware that you cannot re-evaluate
75 //             the fitters after loading this object from file.
76 //             (This will be gone for a new ROOT version > v5-17-05)
77 //                                                                        
78 ////////////////////////////////////////////////////////////////////////////
79
80 #include <TPDGCode.h>
81 #include <TStyle.h>
82 #include "TMatrixD.h"
83 #include "TTreeStream.h"
84 #include "TF1.h"
85 #include "AliTPCParamSR.h"
86 #include "AliTPCClusterParam.h"
87 #include "AliTrackPointArray.h"
88 #include "TCint.h"
89 #include "AliTPCcalibTracksGain.h"
90 #include <TH1.h>
91 #include <TH3F.h>
92 #include <TLinearFitter.h>
93 #include <TTreeStream.h>
94 #include <TFile.h>
95 #include <TCollection.h>
96 #include <TIterator.h>
97
98 //
99 // AliRoot includes
100 //
101 #include "AliMagF.h"
102 #include "AliMathBase.h"
103 //
104 #include "AliTPCROC.h"
105 #include "AliTPCParamSR.h"
106 #include "AliTPCCalROC.h"
107 #include "AliTPCCalPad.h"
108 //
109 #include "AliTracker.h"
110 #include "AliESD.h"
111 #include "AliESDtrack.h"
112 #include "AliESDfriend.h"
113 #include "AliESDfriendTrack.h" 
114 #include "AliTPCseed.h"
115 #include "AliTPCclusterMI.h"
116 #include "AliTPCcalibTracksCuts.h"
117 #include "AliTPCFitPad.h"
118
119 // REMOVE ALL OF THIS
120 #include <TTree.h>
121 #include "AliESDEvent.h"
122
123 /*
124   
125 TFile f("TPCCalibTracksGain.root")
126
127 gSystem->Load("libPWG1.so")
128 AliTreeDraw comp
129 comp.SetTree(dEdx)
130 Double_t chi2;
131 TVectorD vec(3)
132 TMatrixD mat(3,3)
133 TString * str = comp.FitPlane("Cl.fQ/dedxQ.fElements[0]","Cl.fY++Cl.fX","Cl.fDetector<36",chi2,vec,mat)
134
135 */
136
137 ClassImp(AliTPCcalibTracksGain)
138
139 const Bool_t   AliTPCcalibTracksGain::fgkUseTotalCharge = kTRUE;
140 const Double_t AliTPCcalibTracksGain::fgkM = 25.;
141 const char*    AliTPCcalibTracksGain::fgkDebugStreamFileName = "TPCCalibTracksGain.root";
142 AliTPCParamSR* AliTPCcalibTracksGain::fgTPCparam = new AliTPCParamSR();
143
144 AliTPCcalibTracksGain::AliTPCcalibTracksGain() :
145    TNamed(),
146    fDebugCalPadRaw(0),
147    fDebugCalPadCorr(0),
148    fDebugStream(0),
149    fSimpleFitter(0),
150    fSqrtFitter(0),
151    fLogFitter(0),
152    fZFitter(0),
153    fPrevIter(0),
154    fCuts(0)
155 {
156    //
157    // Default constructor.
158    //
159 }
160
161 AliTPCcalibTracksGain::AliTPCcalibTracksGain(const AliTPCcalibTracksGain& obj) :
162    TNamed(obj)
163 {
164    //
165    // Copy constructor.
166    //
167
168    fDebugCalPadRaw = new AliTPCCalPad(*(obj.fDebugCalPadRaw));
169    fDebugCalPadCorr = new AliTPCCalPad(*(obj.fDebugCalPadCorr));
170    fSimpleFitter = new AliTPCFitPad(*(obj.fSimpleFitter));
171    fSqrtFitter = new AliTPCFitPad(*(obj.fSqrtFitter));
172    fLogFitter = new AliTPCFitPad(*(obj.fLogFitter));
173    fZFitter = new TLinearFitter(*(obj.fZFitter));
174    fPrevIter = new AliTPCcalibTracksGain(*(obj.fPrevIter));
175    fCuts = new AliTPCcalibTracksCuts(*(obj.fCuts));
176 }
177
178 AliTPCcalibTracksGain& AliTPCcalibTracksGain::operator=(const AliTPCcalibTracksGain& rhs) {
179    //
180    // Assignment operator.
181    //
182
183    if (this != &rhs) {
184       TNamed::operator=(rhs);
185       fDebugCalPadRaw = new AliTPCCalPad(*(rhs.fDebugCalPadRaw));
186       fDebugCalPadCorr = new AliTPCCalPad(*(rhs.fDebugCalPadCorr));
187       fSimpleFitter = new AliTPCFitPad(*(rhs.fSimpleFitter));
188       fSqrtFitter = new AliTPCFitPad(*(rhs.fSqrtFitter));
189       fLogFitter = new AliTPCFitPad(*(rhs.fLogFitter));
190       fZFitter = new TLinearFitter(*(rhs.fZFitter));
191       fPrevIter = new AliTPCcalibTracksGain(*(rhs.fPrevIter));
192       fCuts = new AliTPCcalibTracksCuts(*(rhs.fCuts));
193    }
194    return *this;
195 }
196
197 AliTPCcalibTracksGain::AliTPCcalibTracksGain(const char* name, const char* title, AliTPCcalibTracksCuts* cuts, AliTPCcalibTracksGain* prevIter) :
198    TNamed(name, title),
199    fDebugCalPadRaw(0),
200    fDebugCalPadCorr(0),
201    fDebugStream(0),
202    fSimpleFitter(0),
203    fSqrtFitter(0),
204    fLogFitter(0),
205    fZFitter(0),
206    fPrevIter(0),
207    fCuts(0)
208 {
209    //
210    // Constructor.
211    //
212    
213    //TH1::AddDirectory(kFALSE);
214    G__SetCatchException(0);
215
216    fCuts = cuts;
217    fPrevIter = prevIter;
218
219    fSimpleFitter = new AliTPCFitPad(6, "hyp5", "");
220    fSqrtFitter   = new AliTPCFitPad(6, "hyp5", "");
221    fLogFitter    = new AliTPCFitPad(6, "hyp5", "");
222
223    fZFitter      = new TLinearFitter(2, "hyp1", "");
224    // workaround for TLinearFitter
225    Double_t workaround = 3.141592;
226    fZFitter->AddPoint(&workaround, 31.41592);
227    fZFitter->ClearPoints();
228
229    // just for debugging
230    fTotalTracks     = 0;
231    fAcceptedTracks  = 0;
232    fDebugCalPadRaw  = new AliTPCCalPad("DebugCalPadRaw", "All clusters simply added up before correction");
233    fDebugCalPadCorr = new AliTPCCalPad("DebugCalPadCorr", "All clusters simply added up after correction");
234    
235    // this will be gone for the a new ROOT version > v5-17-05
236    for (UInt_t i = 0; i < 36; i++) {
237       fNShortClusters[i]  = 0;
238       fNMediumClusters[i] = 0;
239       fNLongClusters[i]   = 0;
240    }
241  }
242
243 AliTPCcalibTracksGain::~AliTPCcalibTracksGain() {
244    //
245    // Destructor.
246    //
247    
248    if (fSimpleFitter) delete fSimpleFitter;
249    if (fSqrtFitter) delete fSqrtFitter;
250    if (fLogFitter) delete fLogFitter;
251
252    if (fZFitter) delete fZFitter;
253
254    if (fDebugStream) {
255       //fDebugStream->GetFile()->Close();
256       printf("Deleting debug stream object\n");
257       delete fDebugStream;
258    }
259
260    if (fDebugCalPadRaw) delete fDebugCalPadRaw;
261    if (fDebugCalPadCorr) delete fDebugCalPadCorr;
262 }
263
264 void AliTPCcalibTracksGain::AddInfo(TChain* chain, char* fileName) {
265    // 
266    // Add some parameters from a previous run (AliTPCcalibTracksGain object contained
267    // in root file fileName) to the chain.
268    // Note: The parameters are *not* added to this class, you need to do it later by retrieving
269    // the parameters from the chain and passing them to the constructor!
270    //
271    
272    TFile paramFile(fileName);
273    if (paramFile.IsZombie()) {
274       printf("File %s not found. Continuing without z dependence parametrisation.\n", fileName);
275       return;
276    }
277    
278    AliTPCcalibTracksGain *prevIter = (AliTPCcalibTracksGain*)paramFile.Get("calibTracksGain");
279    if (prevIter) {
280       //TVectorD* param = new TVectorD(2);
281       //prevIter->fZFitter->GetParameters(*param);
282       //chain->GetUserInfo()->AddLast((TObject*)param);
283       chain->GetUserInfo()->AddLast((TObject*)prevIter);
284    } else
285       printf("No calibTracksGain object found. Continuing without z dependence parametrisation.\n");
286 }
287
288 Int_t AliTPCcalibTracksGain::AcceptTrack(AliTPCseed* track) {
289    //
290    // Decides whether to accept a track or not.
291    // Tracks are discarded, if due to edge effects, the number of clusters
292    // is too low, the ratio of the number of clusters and the findable clusters is too low
293    // or the transverse momentum is too low.
294    // The corresponding cut values are specified in the fCuts member.
295    //
296    
297    if (track->GetNumberOfClusters() < fCuts->GetMinClusters()) return 1;
298    if ((TMath::Abs(track->GetY() / track->GetX()) > fCuts->GetEdgeYXCutNoise())
299       && (TMath::Abs(track->GetTgl()) < fCuts->GetEdgeThetaCutNoise())) return 2;
300    if (track->GetNumberOfClusters() / (track->GetNFoundable()+1.) < fCuts->GetMinRatio()) return 3;
301    if (TMath::Abs(track->GetSigned1Pt()) > fCuts->GetMax1pt()) return 4;
302    
303    //if (track->GetPt() < 50.) return kFALSE;
304    return 0;
305 }
306
307 /*Bool_t AliTPCcalibTracksGain::AcceptCluster(AliTPCclusterMI* cluster) {
308    //
309    // Decides whether to accept a cluster or not.
310    //
311
312    // cluster type < 0: edge cluster
313    // cluster type = 0: "golden" (i.e. good) cluster
314    // cluster type > 0: overlapping cluster
315    if (cluster->GetType() != 0) { Info("AcceptCluster", "Cluster not accepted (type %d)", cluster->GetType()); return kFALSE;}
316
317    // remove edge clusters
318    
319    
320    return kTRUE;
321 }*/
322
323 void AliTPCcalibTracksGain::Process(AliTPCseed* seed) {
324    //
325    // Main method to be called when a new seed is supposed to be processed
326    // and be used for gain calibration. Its quality is checked before it
327    // is added.
328    //
329    
330    fTotalTracks++;
331    //fTrackPt->Fill(seed->GetSignedPt());
332    Int_t status = AcceptTrack(seed);
333    if (status != 0) { /*cout << "Track not accepted (reason " << status << ")" << endl;*/ return; }
334    fAcceptedTracks++;
335    AddTrack(seed);
336 }
337
338 Long64_t AliTPCcalibTracksGain::Merge(TCollection *list) {
339    //
340    // Merge() merges the results of all AliTPCcalibTracksGain objects contained in
341    // list, thus allowing a distributed computation of several files, e.g. on PROOF.
342    // The merged results are stored in the data members of the AliTPCcalibTracksGain
343    // object used for calling the Merge method.
344    // The return value is 0 /*the total number of tracks used for calibration*/ if the merge
345    // is successful, otherwise it is -1.
346    //
347
348    if (!list || list->IsEmpty()) return -1;
349    
350    // reset the data members first
351    if (fSimpleFitter) delete fSimpleFitter;
352    if (fSqrtFitter)   delete fSqrtFitter;
353    if (fLogFitter)    delete fLogFitter;
354    if (fZFitter)      delete fZFitter;
355    fSimpleFitter = new AliTPCFitPad(6, "hyp5", "");
356    fSqrtFitter   = new AliTPCFitPad(6, "hyp5", "");
357    fLogFitter    = new AliTPCFitPad(6, "hyp5", "");
358    fZFitter      = new TLinearFitter(2, "hyp1", "");
359    // workaround for TLinearFitter
360    Double_t workaround = 3.141592;
361    fZFitter->AddPoint(&workaround, 31.41592);
362    fZFitter->ClearPoints();
363
364    // this will be gone for the a new ROOT version > v5-17-05
365    for (UInt_t i = 0; i < 36; i++) {
366       fNShortClusters[i]  = 0;
367       fNMediumClusters[i] = 0;
368       fNLongClusters[i]   = 0;
369    }
370
371    // just for debugging
372    if (fDebugCalPadRaw)  delete fDebugCalPadRaw;
373    if (fDebugCalPadCorr) delete fDebugCalPadCorr;
374    fDebugCalPadRaw  = new AliTPCCalPad("DebugCalPadRaw", "All clusters simply added up before correction");
375    fDebugCalPadCorr = new AliTPCCalPad("DebugCalPadCorr", "All clusters simply added up after correction");
376    fTotalTracks     = 0;
377    fAcceptedTracks  = 0;
378    
379    TIterator* iter = list->MakeIterator();
380    AliTPCcalibTracksGain* cal = 0;
381    
382    while ((cal = (AliTPCcalibTracksGain*)iter->Next())) {
383       if (!cal->InheritsFrom(AliTPCcalibTracksGain::Class())) {
384          Error("Merge","Attempt to add object of class %s to a %s", cal->ClassName(), this->ClassName());
385          return -1;
386       }
387       Add(cal);
388    }
389    return 0;
390 }
391
392 void AliTPCcalibTracksGain::Add(AliTPCcalibTracksGain* cal) {
393    //
394    // Adds another AliTPCcalibTracksGain object to this object.
395    //
396    
397    fSimpleFitter->Add(cal->fSimpleFitter);
398    fSqrtFitter->Add(cal->fSqrtFitter);
399    fLogFitter->Add(cal->fLogFitter);
400    fZFitter->Add(cal->fZFitter);
401
402    // this will be gone for the a new ROOT version > v5-17-05
403    for (UInt_t iSegment = 0; iSegment < 36; iSegment++) {
404       fNShortClusters[iSegment] += cal->fNShortClusters[iSegment];
405       fNMediumClusters[iSegment] += cal->fNMediumClusters[iSegment];
406       fNLongClusters[iSegment] += cal->fNLongClusters[iSegment];
407    }
408    
409    // just for debugging, remove me
410    fTotalTracks += cal->fTotalTracks;
411    fAcceptedTracks += cal->fAcceptedTracks;
412    fDebugCalPadRaw->Add(cal->fDebugCalPadRaw);
413    fDebugCalPadCorr->Add(cal->fDebugCalPadCorr);
414
415    // Let's see later what to do with fCuts and fDebugStream
416 }
417
418 void AliTPCcalibTracksGain::AddTrack(AliTPCseed* seed) {
419    //
420    // The clusters making up the track (seed) are added to various fit functions.
421    // See AddCluster(...) for more detail.
422    //
423    
424    if (!fDebugStream) fDebugStream = new TTreeSRedirector(fgkDebugStreamFileName);
425    DumpTrack(seed);
426
427    AliTPCcalibTracksGain::PreProcess preProc(seed);
428    for (Int_t iCluster = 0; iCluster < 159; iCluster++) {
429       AliTPCclusterMI* cluster = seed->GetClusterPointer(iCluster);
430       if (cluster && preProc.IsClusterAccepted(iCluster)) AddCluster(cluster, preProc);
431    }
432 }
433
434 void AliTPCcalibTracksGain::AddCluster(AliTPCclusterMI* cluster, AliTPCcalibTracksGain::PreProcess& preProc) {
435    //
436    // Adds cluster to the appropriate fitter for later analysis.
437    // The charge used for the fit is the maximum charge for this specific cluster or the
438    // accumulated charge per cluster, depending on the value of fgkUseTotalCharge.
439    // Depending on the pad size where the cluster is registered, the value will be put in
440    // the appropriate fitter. Furthermore, for each pad size three different types of fitters
441    // are used. The fit functions are the same for all fitters (parabolic functions), but the value
442    // added to each fitter is different. The simple fitter gets the charge plugged in as is, the sqrt fitter
443    // gets the square root of the charge, and the log fitter gets fgkM*(1+q/fgkM), where q is the original charge
444    // and fgkM==25.
445    // The preProc object is used for passing information which was gained by preprocessing the seed to which the
446    // cluster belongs. It is used for correcting the charge due to various effects, e.g. its dependence
447    // on the track length over each pad.
448    //
449
450    if (!cluster) {
451       Error("AddCluster", "Cluster not valid.");
452       return;
453    }
454    
455    Double_t xx[5];
456    
457    Int_t padType = GetPadType(cluster->GetX());
458    Double_t centerPad[2] = {0};
459    // this line is for using the center of the region with the same pad size as origin for the fit function,
460    // comment out the appropriate lines in AliTPCCalPadRegion::GetPadRegionCenterLocal() and here if you
461    // want the origin at lx=ly=0.
462    AliTPCFitPad::GetPadRegionCenterLocal(padType, centerPad);
463    
464    xx[0] = cluster->GetX() - centerPad[0];
465    xx[1] = cluster->GetY() - centerPad[1];
466    
467    //xx[0] = cluster->GetX();   // if you want the origin of the fit func at lx=ly=0
468    //xx[1] = cluster->GetY();   // if you want the origin of the fit func at lx=ly=0
469    xx[2] = xx[0] * xx[0];
470    xx[3] = xx[1] * xx[1];
471    xx[4] = xx[0] * xx[1];
472
473    Int_t segment = cluster->GetDetector() % 36;
474    Double_t q = fgkUseTotalCharge ? ((Double_t)(cluster->GetQ())) : ((Double_t)(cluster->GetMax()));  // note: no normalization to pad size!
475    //cerr << "AngleTrackPadrow(" << segment << ", " << padType << ") == " << preProc.GetAngleTrackPadrow(segment, padType) * TMath::RadToDeg() << endl;
476    //cerr << "AngleTrackBeam  (" << segment << ", " << padType << ") == " << preProc.GetAngleTrackBeam(segment, padType) * TMath:: RadToDeg() << endl;
477    //cerr << "Correction factor == " << TMath::Abs(TMath::Sin(preProc.GetAngleTrackPadrow(segment, padType))*TMath::Sin(preProc.GetAngleTrackBeam(segment, padType)))/GetPadLength(cluster->GetX()) << endl;
478
479    // just for debugging
480    Int_t row = 0;
481    Int_t pad = 0;
482    GetRowPad(cluster->GetX(), cluster->GetY(), row, pad);
483    fDebugCalPadRaw->GetCalROC(cluster->GetDetector())->SetValue(row, pad, q + fDebugCalPadRaw->GetCalROC(cluster->GetDetector())->GetValue(row, pad));
484    
485    // correct charge by normalising to mean charge per track
486    //q = TMath::Abs(TMath::Sin(preProc.GetAngleTrackPadrow(segment, padType))*TMath::Sin(preProc.GetAngleTrackBeam(segment, padType)))*q/(GetPadLength(cluster->GetX()) /* * preProc.GetMeanCharge(segment, padType) */);
487    //q *= TMath::Abs(TMath::Sin(preProc.GetAngleTrackPadrow(segment, padType))) / (/*GetPadLength(cluster->GetX()) * */preProc.GetMeanCharge(segment, padType));
488    q /= preProc.GetMeanCharge(segment, padType);
489    //q /= (1 + 0.36 * TMath::Abs(1/TMath::Tan(preProc.GetAngleTrackPadrow(segment, padType))));
490
491    // correct charge for dependency on z distance using previous iteration
492    if (fPrevIter) {
493       TVectorD param(2);
494       fPrevIter->fZFitter->GetParameters(param);
495       q /= param[0] + param[1] * (TMath::Abs(cluster->GetZ()) - TMath::Abs(preProc.GetMeanZ(segment, padType)));
496    }
497    
498    // just for debugging
499    fDebugCalPadCorr->GetCalROC(cluster->GetDetector())->SetValue(row, pad, q + fDebugCalPadCorr->GetCalROC(cluster->GetDetector())->GetValue(row, pad));
500
501    Double_t sqrtQ = TMath::Sqrt(q);
502    Double_t logQ = fgkM * TMath::Log(1 + q / fgkM);
503    fSimpleFitter->GetFitter(segment, padType)->AddPoint(xx, q);
504    fSqrtFitter->GetFitter(segment, padType)->AddPoint(xx, sqrtQ);
505    fLogFitter->GetFitter(segment, padType)->AddPoint(xx, logQ);
506
507    Double_t zz = TMath::Abs(cluster->GetZ()) - TMath::Abs(preProc.GetMeanZ(segment, padType));
508    fZFitter->AddPoint(&zz, q);
509    
510    // this will be gone for the a new ROOT version > v5-17-05
511    if (padType == kShortPads)
512       fNShortClusters[segment]++;
513    else if (padType == kMediumPads)
514       fNMediumClusters[segment]++;
515    else if (padType == kLongPads)
516       fNLongClusters[segment]++;
517 }
518
519 void AliTPCcalibTracksGain::Evaluate(Bool_t robust, Double_t frac) {
520    //
521    // Evaluates all fitters contained in this object.
522    // If the robust option is set to kTRUE a robust fit is performed with frac as
523    // the minimal fraction of good points (see TLinearFitter::EvalRobust for details).
524    // Beware: Robust fitting is much slower!
525    //
526    
527    fSimpleFitter->Evaluate(robust, frac);
528    fSqrtFitter->Evaluate(robust, frac);
529    fLogFitter->Evaluate(robust, frac);
530    if (robust) fZFitter->EvalRobust(frac);
531    else        fZFitter->Eval();
532 }
533
534 Int_t AliTPCcalibTracksGain::Evaluate(UInt_t segment, UInt_t padType, UInt_t fitType, TVectorD* fitParam, TVectorD* fitError, Double_t* redChi2, Bool_t robust, Double_t frac) {
535    //
536    // Evaluate the tracks for obtaining the calibration information.
537    // segment specifies the segment (IROC & OROC) for which the fitter shall be evaluated (it can take values from
538    // 0 to 35; segment == i means IROC# i and OROC# (i+36) are meant).
539    // padType is one of kShortPads, kMediumPads, kLongPads.
540    // fitType is one of kSimpleFitter, kSqrtFitter, kLogFitter.
541    // fitParam should be a TVectorD object with 6 elements where the fit parameters will be written to,
542    // the same is valid for fitError, which will contain the errors of course.
543    // redChi2 is a pointer to an Int_t value which will contain the reduced chi^2 of the fit.
544    // If fitParam, fitError or redChi2 is a null pointer, the corresponding value is not calculated.
545    // If the robust option is set to kTRUE a robust fit is performed with frac as
546    // the minimal fraction of good points (see TLinearFitter::EvalRobust for details).
547    // Beware: Robust fitting is much slower!
548    // Evaluate() returns the number of clusters in the specified padType.
549    //
550
551    TLinearFitter* fitter = GetFitter(segment, padType, fitType);
552    Int_t NClusters = 0;
553    // this will be gone for a new ROOT version > v5-17-05
554    // and replaced by
555    // UInt_t NClusters = fSimpleFitter->GetFitter(segment, padType)->GetNpoints();
556    switch (padType) {
557       case kShortPads:
558          NClusters = fNShortClusters[segment];
559          break;
560       case kMediumPads:
561          NClusters = fNMediumClusters[segment];
562          break;
563       case kLongPads:
564          NClusters = fNLongClusters[segment];
565          break;
566    }
567
568    if (robust) fitter->EvalRobust(frac);
569    else fitter->Eval();
570    
571    if (redChi2) *redChi2 = fitter->GetChisquare()/(NClusters - 6);
572    if (fitParam) fitter->GetParameters(*fitParam);
573    if (fitError) {
574       fitter->GetErrors(*fitError);
575       *fitError *= (redChi2) ? (TMath::Sqrt(*redChi2)) : (TMath::Sqrt(fitter->GetChisquare()/(NClusters - 6)));
576    }
577
578    return NClusters;
579 }
580
581 AliTPCCalPad* AliTPCcalibTracksGain::CreateFitCalPad(UInt_t fitType, Bool_t undoTransformation, Bool_t normalizeToPadSize) {
582    TObjArray tpc(72);
583    for (UInt_t iSector = 0; iSector < 72; iSector++)
584       tpc.Add(CreateFitCalROC(iSector, fitType, undoTransformation, normalizeToPadSize));
585    return new AliTPCCalPad(&tpc);
586 }
587
588 AliTPCCalROC* AliTPCcalibTracksGain::CreateFitCalROC(UInt_t sector, UInt_t fitType, Bool_t undoTransformation, Bool_t normalizeToPadSize) {
589    TVectorD par(6);
590    if (sector < 36) {
591       GetParameters(sector % 36, 0, fitType, par);
592       return CreateFitCalROC(sector, 0, par, fitType, undoTransformation, normalizeToPadSize);
593    }
594    else {
595       GetParameters(sector % 36, 1, fitType, par);
596       AliTPCCalROC* roc1 = CreateFitCalROC(sector, 1, par, fitType, undoTransformation, normalizeToPadSize);
597       GetParameters(sector % 36, 2, fitType, par);
598       AliTPCCalROC* roc2 = CreateFitCalROC(sector, 2, par, fitType, undoTransformation, normalizeToPadSize);
599       AliTPCCalROC* roc3 = CreateCombinedCalROC(roc1, roc2);
600       delete roc1;
601       delete roc2;
602       return roc3;
603    }
604 }
605
606 AliTPCCalROC* AliTPCcalibTracksGain::CreateFitCalROC(UInt_t sector, UInt_t padType, TVectorD &fitParam, UInt_t fitType, Bool_t undoTransformation, Bool_t normalizeToPadSize) {
607    //
608    // This function is essentially a copy of AliTPCCalROC::CreateGlobalFitCalROC(...), with the
609    // modifications, that the center of the region of same pad size is used as the origin
610    // of the fit function instead of the center of the ROC.
611    // The possibility of a linear fit is removed as well because it is not needed.
612    // Only values for pads with the given pad size are calculated, the rest is 0.
613    // Set undoTransformation for undoing the transformation that was applied to the
614    // charge values before they were put into the fitter (thus allowing comparison to the original
615    // charge values). For fitType use 0 for the simple fitter, 1 for the sqrt fitter, 2 for the log fitter.
616    // If normalizeToPadSize is true, the values are normalized to the pad size.
617    // Please be aware, that you even need to specify the fitType if you want to normalize to the pad size without
618    // undoing the transformation (because normalizing involves undoing the trafo first, then normalizing, then
619    // applying the trafo again).
620    // Please note: The normalization to the pad size is a simple linear scaling with the pad length, which
621    //              actually doesn't describe reality!
622    //
623    
624    Float_t dlx, dly;
625    Double_t centerPad[2] = {0};
626    Float_t localXY[3] = {0};
627    AliTPCROC* tpcROC = AliTPCROC::Instance();
628    if ((padType == 0 && sector >= tpcROC->GetNInnerSector()) || (padType > 0 && sector < tpcROC->GetNInnerSector()) || sector >= tpcROC->GetNSector())
629       return 0;
630    AliTPCCalROC* ROCfitted = new AliTPCCalROC(sector);
631    //tpcROC->GetPositionLocal(sector, ROCfitted->GetNrows()/2, ROCfitted->GetNPads(ROCfitted->GetNrows()/2)/2, centerPad);  // use this instead of the switch statement if you want to calculate the center of the ROC and not the center of the regions with the same pad size
632    UInt_t startRow = 0;
633    UInt_t endRow = 0;
634    switch (padType) {
635       case kShortPads:
636          startRow = 0;
637          endRow = ROCfitted->GetNrows();
638          break;
639       case kMediumPads:
640          startRow = 0;
641          endRow = 64;
642          break;
643       case kLongPads:
644          startRow = 64;
645          endRow = ROCfitted->GetNrows();
646          break;
647    }
648
649    AliTPCFitPad::GetPadRegionCenterLocal(padType, centerPad);   
650    Double_t value = 0;
651    for (UInt_t irow = startRow; irow < endRow; irow++) {
652       for (UInt_t ipad = 0; ipad < ROCfitted->GetNPads(irow); ipad++) {
653          tpcROC->GetPositionLocal(sector, irow, ipad, localXY);   // calculate position localXY by pad and row number
654          dlx = localXY[0] - centerPad[0];
655          dly = localXY[1] - centerPad[1];
656          value = fitParam[0] + fitParam[1]*dlx + fitParam[2]*dly + fitParam[3]*dlx*dlx + fitParam[4]*dly*dly + fitParam[5]*dlx*dly;
657
658          // Let q' = value be the transformed value without any pad size corrections,
659          // let T be the transformation and let l be the pad size
660          //    1) don't undo transformation, don't normalize: return q'
661          //    2) undo transformation,       don't normalize: return T^{-1} q'
662          //    3) undo transformation,       normalize:       return (T^{-1} q') / l
663          //    4) don't undo transformation, normalize:       return T((T^{-1} q') / l)
664          if (!undoTransformation && !normalizeToPadSize) {/* value remains unchanged */}  // (1)
665          else {                                                                           // (2), (3), (4)
666             //calculate T^{-1}
667             switch (fitType) {
668                case  0: /* value remains unchanged */ break;
669                case  1: value = value * value; break;
670                case  2: value = (TMath::Exp(value / fgkM) - 1) * fgkM; break;
671                default: Error("CreateFitCalROC", "Wrong fit type."); break;
672             }
673             if (normalizeToPadSize) value /= GetPadLength(localXY[0]);                    // (3)
674          }
675          if (!undoTransformation && normalizeToPadSize) {                                 // (4)
676             // calculate T
677             switch (fitType) {
678                case  0: /* value remains unchanged */ break;
679                case  1: value = TMath::Sqrt(value); break;
680                case  2: value = fgkM * TMath::Log(1 + value / fgkM); break;
681                default: Error("CreateFitCalROC", "Wrong fit type."); break;
682             }
683          }
684          ROCfitted->SetValue(irow, ipad, value);
685       }
686    }
687    return ROCfitted;
688 }
689
690 AliTPCCalROC* AliTPCcalibTracksGain::CreateCombinedCalROC(const AliTPCCalROC* roc1, const AliTPCCalROC* roc2) {
691    //
692    // Combines the medium pad size values of roc1 with the long pad size values of roc2 into a new
693    // AliTPCCalROC. Returns a null pointer if any one of the ROCs is an IROC; issues a warning message
694    // if the sectors of roc1 and roc2 don't match, but still continue and use the sector of roc1 as the
695    // sector of the new ROC.
696    //
697
698    if (!roc1 || !roc2) return 0;
699    if ((Int_t)(roc1->GetSector()) < fgTPCparam->GetNInnerSector()) return 0;
700    if ((Int_t)(roc2->GetSector()) < fgTPCparam->GetNInnerSector()) return 0;
701    if (roc1->GetSector() != roc2->GetSector()) Warning("CreateCombinedCalROC", "Sector number mismatch.");
702    AliTPCCalROC* roc = new AliTPCCalROC(roc1->GetSector());
703    
704    for (UInt_t iRow = 0; iRow < 64; iRow++) {
705       for (UInt_t iPad = 0; iPad < roc->GetNPads(iRow); iPad++)
706          roc->SetValue(iRow, iPad, roc1->GetValue(iRow, iPad));
707    }
708    for (UInt_t iRow = 64; iRow < roc->GetNrows(); iRow++) {
709       for (UInt_t iPad = 0; iPad < roc->GetNPads(iRow); iPad++)
710          roc->SetValue(iRow, iPad, roc2->GetValue(iRow, iPad));
711    }
712    return roc;
713 }
714
715 void AliTPCcalibTracksGain::GetParameters(UInt_t segment, UInt_t padType, UInt_t fitType, TVectorD &fitParam) {
716    //
717    // Puts the fit parameters for the specified segment (IROC & OROC), padType and fitType
718    // into the fitParam TVectorD (which should contain 6 elements).
719    // padType is one of kShortPads, kMediumPads, kLongPads. fitType is one of kSimpleFitter, kSqrtFitter, kLogFitter.
720    // Note: The fitter has to be evaluated first!
721    //
722
723    GetFitter(segment, padType, fitType)->GetParameters(fitParam);
724 }
725
726 void AliTPCcalibTracksGain::GetErrors(UInt_t segment, UInt_t padType, UInt_t fitType, TVectorD &fitError) {
727    //
728    // Puts the fit parameter errors for the specified segment (IROC & OROC), padType and fitType
729    // into the fitParam TVectorD (which should contain 6 elements).
730    // padType is one of kShortPads, kMediumPads, kLongPads. fitType is one of kSimpleFitter, kSqrtFitter, kLogFitter.
731    // Note: The fitter has to be evaluated first!
732    //
733
734    GetFitter(segment, padType, fitType)->GetErrors(fitError);
735    fitError *= TMath::Sqrt(GetRedChi2(segment, padType, fitType));
736 }
737
738 Double_t AliTPCcalibTracksGain::GetRedChi2(UInt_t segment, UInt_t padType, UInt_t fitType) {
739    //
740    // Returns the reduced chi^2 value for the specified segment, padType and fitType.
741    // padType is one of kShortPads, kMediumPads, kLongPads. fitType is one of kSimpleFitter, kSqrtFitter, kLogFitter.
742    // Note: The fitter has to be evaluated first!
743    //
744
745    Int_t NClusters = 0;
746    switch (padType) {
747       case kShortPads:
748          NClusters = fNShortClusters[segment];
749          break;
750       case kMediumPads:
751          NClusters = fNMediumClusters[segment];
752          break;
753       case kLongPads:
754          NClusters = fNLongClusters[segment];
755          break;
756    }
757    return GetFitter(segment, padType, fitType)->GetChisquare()/(NClusters - 6);
758 }
759
760 void AliTPCcalibTracksGain::GetCovarianceMatrix(UInt_t segment, UInt_t padType, UInt_t fitType, TMatrixD& covMatrix) {
761    //
762    // Returns the covariance matrix for the specified segment, padType, fitType.
763    // padType is one of kShortPads, kMediumPads, kLongPads. fitType is one of kSimpleFitter, kSqrtFitter, kLogFitter.
764    //
765
766    GetFitter(segment, padType, fitType)->GetCovarianceMatrix(covMatrix);
767 }
768
769 TLinearFitter* AliTPCcalibTracksGain::GetFitter(UInt_t segment, UInt_t padType, UInt_t fitType) {
770    //
771    // Returns the TLinearFitter object for the specified segment, padType, fitType.
772    // padType is one of kShortPads, kMediumPads, kLongPads. fitType is one of kSimpleFitter, kSqrtFitter, kLogFitter.
773    //
774    
775    switch (fitType) {
776       case kSimpleFitter:
777          return fSimpleFitter->GetFitter(segment, padType);
778       case kSqrtFitter:
779          return fSqrtFitter->GetFitter(segment, padType);
780       case kLogFitter:
781          return fLogFitter->GetFitter(segment, padType);
782    }
783    return 0;
784 }
785
786 Double_t AliTPCcalibTracksGain::GetPadLength(Double_t lx) {
787    //
788    // The function returns 0.75 for an IROC, 1. for an OROC at medium pad size position,
789    // 1.5 for an OROC at long pad size position, -1 if out of bounds.
790    //
791
792    Double_t irocLow = fgTPCparam->GetPadRowRadiiLow(0) - fgTPCparam->GetInnerPadPitchLength()/2;
793    Double_t irocUp = fgTPCparam->GetPadRowRadiiLow(fgTPCparam->GetNRowLow()-1) + fgTPCparam->GetInnerPadPitchLength()/2;
794    Double_t orocLow1 = fgTPCparam->GetPadRowRadiiUp(0) - fgTPCparam->GetOuter1PadPitchLength()/2;
795    Double_t orocUp1 = fgTPCparam->GetPadRowRadiiUp(fgTPCparam->GetNRowUp1()-1) + fgTPCparam->GetOuter1PadPitchLength()/2;
796    Double_t orocLow2 = fgTPCparam->GetPadRowRadiiUp(fgTPCparam->GetNRowUp1()) - fgTPCparam->GetOuter2PadPitchLength()/2;
797    Double_t orocUp2 = fgTPCparam->GetPadRowRadiiUp(fgTPCparam->GetNRowUp()-1) + fgTPCparam->GetOuter2PadPitchLength()/2;
798    
799    // if IROC
800    if (lx >= irocLow && lx <= irocUp) return 0.75;
801    // if OROC medium pads
802    if (lx >= orocLow1 && lx <= orocUp1) return 1.;
803    // if OROC long pads
804    if (lx >= orocLow2 && lx <= orocUp2) return 1.5;
805    // if out of bounds
806    return -1;
807 }
808
809 Int_t AliTPCcalibTracksGain::GetPadType(Double_t lx) {
810    //
811    // The function returns 0 for an IROC, 1 for an OROC at medium pad size position,
812    // 2 for an OROC at long pad size position, -1 if out of bounds.
813    //
814    
815    if (GetPadLength(lx) == 0.75) return 0;
816    else if (GetPadLength(lx) == 1.) return 1;
817    else if (GetPadLength(lx) == 1.5) return 2;
818    return -1;
819 }
820
821 // ONLY FOR DEBUGGING PURPOSES - REMOVE ME WHEN NOT NEEDED ANYMORE
822 Bool_t AliTPCcalibTracksGain::GetRowPad(Double_t lx, Double_t ly, Int_t& row, Int_t& pad) {
823    //
824    // Calculate the row and pad number when the local coordinates are given.
825    // Returns kFALSE if the position is out of range, otherwise return kTRUE.
826    // WARNING: This function is preliminary and probably isn't very accurate!!
827    //
828    
829    Double_t irocLow = fgTPCparam->GetPadRowRadiiLow(0) - fgTPCparam->GetInnerPadPitchLength()/2;
830    //Double_t irocUp = fgTPCparam->GetPadRowRadiiLow(fgTPCparam->GetNRowLow()-1) + fgTPCparam->GetInnerPadPitchLength()/2;
831    Double_t orocLow1 = fgTPCparam->GetPadRowRadiiUp(0) - fgTPCparam->GetOuter1PadPitchLength()/2;
832    //Double_t orocUp1 = fgTPCparam->GetPadRowRadiiUp(fgTPCparam->GetNRowUp1()-1) + fgTPCparam->GetOuter1PadPitchLength()/2;
833    Double_t orocLow2 = fgTPCparam->GetPadRowRadiiUp(fgTPCparam->GetNRowUp1()) - fgTPCparam->GetOuter2PadPitchLength()/2;
834    //Double_t orocUp2 = fgTPCparam->GetPadRowRadiiUp(fgTPCparam->GetNRowUp()-1) + fgTPCparam->GetOuter2PadPitchLength()/2;
835
836    if (GetPadType(lx) == 0) {
837       row = (Int_t)((lx - irocLow) / fgTPCparam->GetInnerPadPitchLength());
838       pad = (Int_t)((ly + fgTPCparam->GetYInner(row)) / fgTPCparam->GetInnerPadPitchWidth());
839    } else if (GetPadType(lx) == 1) {
840       row = (Int_t)((lx - orocLow1) / fgTPCparam->GetOuter1PadPitchLength());
841       pad = (Int_t)((ly + fgTPCparam->GetYOuter(row)) / fgTPCparam->GetOuterPadPitchWidth());
842    } else if (GetPadType(lx) == 2) {
843       row = fgTPCparam->GetNRowUp1() + (Int_t)((lx - orocLow2) / fgTPCparam->GetOuter2PadPitchLength());
844       pad = (Int_t)((ly + fgTPCparam->GetYOuter(row)) / fgTPCparam->GetOuterPadPitchWidth());
845    }
846    else return kFALSE;
847    return kTRUE;
848 }
849
850 void AliTPCcalibTracksGain::DumpTrack(AliTPCseed* track) {
851    //
852    //  Dump track information to the debug stream
853    //
854    
855    (*fDebugStream) << "Track" <<
856       "Track.=" << track <<        // track information
857       "\n";
858    Int_t rows[200];
859    for (Int_t ipad = 0; ipad < 3; ipad++) {
860       GetDedx(track, ipad, rows);
861    }
862 }
863
864 Bool_t AliTPCcalibTracksGain::GetDedx(AliTPCseed* track, Int_t padType, Int_t* rows) {
865    //
866    // GetDedx for given sector for given track
867    // padType - type of pads
868    //
869    
870    Int_t firstRow = 0, lastRow = 0;
871    Int_t minRow = 100;
872    Float_t xcenter = 0;
873    const Float_t ktany = TMath::Tan(TMath::DegToRad() * 10);
874    const Float_t kedgey = 4.;
875    if (padType == 0) {
876       firstRow = 0;
877       lastRow = fgTPCparam->GetNRowLow();
878       xcenter = 108.47;
879    }
880    if (padType == 1) {
881       firstRow = fgTPCparam->GetNRowLow();
882       lastRow = fgTPCparam->GetNRowLow() + fgTPCparam->GetNRowUp1();
883       xcenter = 166.60;
884    }
885    if (padType == 2) {
886       firstRow = fgTPCparam->GetNRowLow() + fgTPCparam->GetNRowUp1();
887       lastRow = fgTPCparam->GetNRowLow() + fgTPCparam->GetNRowUp();
888       xcenter = 222.6;
889    }
890    minRow = (lastRow - firstRow) / 2;
891    //
892    //
893    Int_t nclusters = 0;
894    Int_t nclustersNE = 0; // number of not edge clusters
895    Int_t lastSector = -1;
896    Float_t amplitudeQ[100];
897    Float_t amplitudeM[100];
898    Int_t rowIn[100];
899    Int_t index[100];
900    //
901    static TLinearFitter fitY(2, "pol1");
902    static TLinearFitter fitZ(2, "pol1");
903    static TVectorD parY(2);
904    static TVectorD parZ(2);
905    fitY.ClearPoints();
906    fitZ.ClearPoints();
907    TVectorD meanPos(6);
908    
909    for (Int_t iCluster = firstRow; iCluster < lastRow; iCluster++) {
910       AliTPCclusterMI* cluster = track->GetClusterPointer(iCluster);
911       if (cluster) {
912          Int_t detector = cluster->GetDetector() ;
913          if (lastSector == -1) lastSector = detector;
914          if (lastSector != detector) continue;
915          amplitudeQ[nclusters] = cluster->GetQ();
916          amplitudeM[nclusters] = cluster->GetMax();
917          rowIn[nclusters] = iCluster;
918          nclusters++;
919          Double_t dx = cluster->GetX() - xcenter;
920          Double_t y = cluster->GetY();
921          Double_t z = cluster->GetZ();
922          fitY.AddPoint(&dx, y);
923          fitZ.AddPoint(&dx, z);
924          meanPos[0] += dx;
925          meanPos[1] += dx;
926          meanPos[2] += y;
927          meanPos[3] += y*y;
928          meanPos[4] += z;
929          meanPos[5] += z*z;
930          if (TMath::Abs(cluster->GetY()) < cluster->GetX()*ktany - kedgey) nclustersNE++;
931       }
932    }
933    
934    if (nclusters < minRow / 2) return kFALSE;
935    if (nclustersNE < minRow / 2) return kFALSE;
936    for (Int_t i = 0; i < 6; i++) meanPos[i] /= Double_t(nclusters);
937    fitY.Eval();
938    fitZ.Eval();
939    fitY.GetParameters(parY);
940    fitZ.GetParameters(parZ);
941    //
942    // calculate truncated mean
943    //
944    TMath::Sort(nclusters, amplitudeQ, index, kFALSE);
945    
946    TVectorD dedxQ(5);
947    TVectorD dedxM(5);
948    Float_t ndedx[5];
949    for (Int_t i = 0; i < 5; i++) {
950       dedxQ[i] = 0;
951       dedxM[i] = 0;
952       ndedx[i] = 0;
953    }
954    //
955    // dedx calculation
956    //
957    Int_t inonEdge = 0;
958    for (Int_t i = 0; i < nclusters; i++) {
959       Int_t rowSorted = rowIn[index[i]];
960       AliTPCclusterMI* cluster = track->GetClusterPointer(rowSorted);
961       
962       if (TMath::Abs(cluster->GetY()) > cluster->GetX()*ktany - kedgey) continue;  //don't take edge clusters
963       inonEdge++;
964       if (inonEdge < nclustersNE * 0.5) {
965          ndedx[0]++;
966          dedxQ[0] += amplitudeQ[index[i]];
967          dedxM[0] += amplitudeM[index[i]];
968       }
969       if (inonEdge < nclustersNE * 0.6) {
970          ndedx[1]++;
971          dedxQ[1] += amplitudeQ[index[i]];
972          dedxM[1] += amplitudeM[index[i]];
973       }
974       if (inonEdge < nclustersNE * 0.7) {
975          ndedx[2]++;
976          dedxQ[2] += amplitudeQ[index[i]];
977          dedxM[2] += amplitudeM[index[i]];
978       }
979       if (inonEdge < nclustersNE * 0.8) {
980          ndedx[3]++;
981          dedxQ[3] += amplitudeQ[index[i]];
982          dedxM[3] += amplitudeM[index[i]];
983       }
984       if (inonEdge < nclustersNE * 0.9) {
985          ndedx[4]++;
986          dedxQ[4] += amplitudeQ[index[i]];
987          dedxM[4] += amplitudeM[index[i]];
988       }
989    }
990    for (Int_t i = 0; i < 5; i++) {
991       dedxQ[i] /= ndedx[i];
992       dedxM[i] /= ndedx[i];
993    }
994    
995    inonEdge = 0;
996    for (Int_t i = 0; i < nclusters; i++) {
997       Int_t rowSorted = rowIn[index[i]];
998       AliTPCclusterMI* cluster = track->GetClusterPointer(rowSorted);
999       if (!cluster) {
1000          printf("Problem\n");
1001          continue;
1002       }
1003       if (TMath::Abs(cluster->GetY()) < cluster->GetX()*ktany - kedgey) inonEdge++;
1004       Float_t dedge = cluster->GetX()*ktany - TMath::Abs(cluster->GetY());
1005       Float_t fraction = Float_t(i) / Float_t(nclusters);
1006       Float_t fraction2 = Float_t(inonEdge) / Float_t(nclustersNE);
1007       Float_t momenta = track->GetP();
1008       Float_t mdedx = track->GetdEdx();
1009
1010       (*fDebugStream) << "dEdx" <<
1011          "Cl.=" << cluster <<           // cluster of interest
1012          "P=" << momenta <<             // track momenta
1013          "dedx=" << mdedx <<            // mean dedx - corrected for angle
1014          "IPad=" << padType <<          // pad type 0..2
1015          "xc=" << xcenter <<            // x center of chamber
1016          "dedxQ.=" << &dedxQ <<         // dedxQ  - total charge
1017          "dedxM.=" << &dedxM <<         // dedxM  - maximal charge
1018          "fraction=" << fraction <<     // fraction - order in statistic (0,1)
1019          "fraction2=" << fraction2 <<   // fraction - order in statistic (0,1)
1020          "dedge=" << dedge <<           // distance to the edge
1021          "parY.=" << &parY <<           // line fit
1022          "parZ.=" << &parZ <<           // line fit
1023          "meanPos.=" << &meanPos <<     // mean position (dx, dx^2, y,y^2, z, z^2)
1024          "\n";
1025    }
1026    return kTRUE;
1027 }
1028
1029 AliTPCcalibTracksGain::PreProcess::PreProcess(AliTPCseed* seed) :
1030    fSeed(seed)
1031 {
1032    //
1033    // Constructor. Preprocesses the track contained in seed. After that
1034    // all relevant values gained from preprocessing can be accessed using
1035    // the getter methods.
1036    // For each pad region a line fit using the clusters of this region is made
1037    // for obtaining the angle between track and padrow.
1038    // The mean charge for the clusters of each pad region is calculated.
1039    // For all these calculations inappropriate clusters are not used
1040    // and are accordingly marked (which can be found out with IsClusterAccepted).
1041    //
1042
1043    // initialize data members and constants
1044    fAngleTrackPadrow = new Double_t[AliTPCFitPad::GetNSegments() * AliTPCFitPad::GetNPadTypes()];
1045    fAngleTrackBeam   = new Double_t[AliTPCFitPad::GetNSegments() * AliTPCFitPad::GetNPadTypes()];
1046    fMeanCharge       = new Double_t[AliTPCFitPad::GetNSegments() * AliTPCFitPad::GetNPadTypes()];
1047    fMeanZ            = new Double_t[AliTPCFitPad::GetNSegments() * AliTPCFitPad::GetNPadTypes()];
1048    for (UInt_t i = 0; i < AliTPCFitPad::GetNSegments() * AliTPCFitPad::GetNPadTypes(); i++) {
1049       fMeanCharge[i] = 0;
1050       fMeanZ[i] = 0;
1051    }
1052    for (UInt_t i = 0; i < 159; i++) fAcceptedClusters[i] = kFALSE;
1053    const Double_t kSmallNumber = 1E-20;
1054    const Double_t kTan10 = TMath::Tan(10*TMath::DegToRad());
1055    const Double_t kCos10 = TMath::Cos(10*TMath::DegToRad());
1056       
1057    Int_t nClusters[AliTPCFitPad::GetNSegments() * AliTPCFitPad::GetNPadTypes()];                              // this will be gone for a new ROOT version > v5-17-05
1058    for (UInt_t i = 0; i < AliTPCFitPad::GetNSegments() * AliTPCFitPad::GetNPadTypes(); i++) nClusters[i] = 0; // this will be gone for a new ROOT version > v5-17-05
1059    Int_t nAllClusters[AliTPCFitPad::GetNSegments() * AliTPCFitPad::GetNPadTypes()];
1060    for (UInt_t i = 0; i < AliTPCFitPad::GetNSegments() * AliTPCFitPad::GetNPadTypes(); i++) nAllClusters[i] = 0;
1061    
1062    Double_t clusterCharges[AliTPCFitPad::GetNSegments() * AliTPCFitPad::GetNPadTypes()][100];
1063    Int_t    clusterIndices[AliTPCFitPad::GetNSegments() * AliTPCFitPad::GetNPadTypes()][100];
1064    Int_t    clusterRows   [AliTPCFitPad::GetNSegments() * AliTPCFitPad::GetNPadTypes()][100];
1065    for (Int_t iCluster = 0; iCluster < 159; iCluster++) {
1066       AliTPCclusterMI* cluster = fSeed->GetClusterPointer(iCluster);
1067       // check if cluster is good cluster
1068       if (cluster) {
1069          Int_t segment = cluster->GetDetector() % 36;
1070          Int_t padType = (iCluster < AliTPCcalibTracksGain::fgTPCparam->GetNRowLow()) ? 0 : ((iCluster < fgTPCparam->GetNRowLow() + fgTPCparam->GetNRowUp1()) ? 1 : 2);
1071          Int_t index = segment + AliTPCFitPad::GetNSegments() * padType;
1072          nAllClusters[index]++;
1073
1074          // cluster type < 0: edge cluster
1075          // cluster type = 0: "golden" (i.e. good) cluster
1076          // cluster type > 0: overlapping cluster
1077          // if (cluster->GetType() != 0) continue;
1078          
1079          // add up z positions for later calculation of mean z position
1080          fMeanZ[index] += cluster->GetZ();
1081          
1082          // remove edge clusters (only keep those farther away than 3 cm from the edge)
1083          Double_t edgeDistance = (cluster->GetX() * kTan10 - TMath::Abs(cluster->GetY())); //* kCos10; // the cos is for the shortest distance
1084          if (edgeDistance < 3.) continue;
1085          
1086          // put cluster charges and their row position in arrays for each pad region and count them
1087          clusterCharges[index][nClusters[index]] = AliTPCcalibTracksGain::fgkUseTotalCharge ? cluster->GetQ() : cluster->GetMax();
1088          clusterRows[index][nClusters[index]] = iCluster;
1089          nClusters[index]++;
1090       }
1091    }
1092
1093    // order clusters according to their charge (in each pad region)
1094    //for (UInt_t index = 0; index < AliTPCFitPad::GetNSegments() * AliTPCFitPad::GetNPadTypes(); index++)
1095    //   TMath::Sort(nClusters[index], clusterCharges[index], clusterIndices[index], kFALSE);
1096
1097    AliTPCFitPad localXYfitters(2, "pol1", ""); // used for determining the angle between XY projection of track and Y axis (padrow) - local c.s.
1098    AliTPCFitPad localXZfitters(2, "pol1", ""); // used for determining the angle between XZ projection of track and Z axis (beam) - local c.s.
1099    
1100    Int_t minRows[3] = {0};
1101    minRows[0] = AliTPCcalibTracksGain::fgTPCparam->GetNRowLow();
1102    minRows[1] = AliTPCcalibTracksGain::fgTPCparam->GetNRowUp1();
1103    minRows[2] = AliTPCcalibTracksGain::fgTPCparam->GetNRowUp() - AliTPCcalibTracksGain::fgTPCparam->GetNRowUp1();
1104    // the minimum number of rows occupied by clusters in a pad region should be a quarter of the available rows
1105    for (Int_t i = 0; i < 3; minRows[i++] /= 4);
1106    
1107    for (UInt_t iSegment = 0; iSegment < AliTPCFitPad::GetNSegments(); iSegment++) {
1108       for (UInt_t iPadType = 0; iPadType < AliTPCFitPad::GetNPadTypes(); iPadType++) {
1109          Int_t index = iSegment + AliTPCFitPad::GetNSegments() * iPadType;
1110          
1111          // remove pad regions with too few rows occupied by clusters
1112          if (nAllClusters[index] < minRows[iPadType]) continue;
1113          // calculate mean z position
1114          fMeanZ[index] /= nAllClusters[index];
1115          // order clusters according to their charge (in each pad region)
1116          TMath::Sort(nClusters[index], clusterCharges[index], clusterIndices[index], kFALSE);
1117          
1118          for (Int_t i = 0; i < nClusters[index]; i++) {
1119             Int_t iCluster = clusterRows[index][clusterIndices[index][i]];
1120             AliTPCclusterMI* cluster = fSeed->GetClusterPointer(iCluster);
1121             // keep only the lower 70% of the clusters ordered according to their charge
1122             Double_t fraction = (Double_t)i / (Double_t)(nClusters[index]);
1123             if (fraction > 0.7) break;
1124                         
1125             fAcceptedClusters[iCluster] = kTRUE;
1126             // put cluster data into fitters (I should move this before the fraction cut, because the charge values don't matter - the problem is the number of points -> additional counter)
1127             Double_t x = cluster->GetX();             // maybe it's better for fitter stability to use difference from pad region center instead
1128             localXYfitters.GetFitter(iSegment, iPadType)->AddPoint(&x, cluster->GetY());
1129             localXZfitters.GetFitter(iSegment, iPadType)->AddPoint(&x, cluster->GetZ());
1130             // add up charges for later calculation of mean charges
1131             fMeanCharge[index] += AliTPCcalibTracksGain::fgkUseTotalCharge ? cluster->GetQ() : cluster->GetMax();
1132          }
1133          // calculate mean charges
1134          if (nClusters[index] != 0) fMeanCharge[index] /= (Double_t)(nClusters[index]);
1135       }
1136    }
1137       
1138    // evaluate fitters and set corresponding angles or default values, respectively
1139    for (UInt_t iSegment = 0; iSegment < AliTPCFitPad::GetNSegments(); iSegment++) {
1140       for (UInt_t iPadType = 0; iPadType < AliTPCFitPad::GetNPadTypes(); iPadType++) {
1141          UInt_t index = iSegment + AliTPCFitPad::GetNSegments() * iPadType;
1142          // evaluate XY fitters
1143          TLinearFitter* fitter = localXYfitters.GetFitterSimple(iSegment, iPadType);
1144          if (fitter && nClusters[index] >= 2 && fitter->Eval() == 0) {                                    // this will be gone for a new ROOT version > v5-17-05 and replaced by (fitter && fitter->GetNPoints() >= 2 && fitter->Eval() == 0)
1145             Double_t slope = fitter->GetParameter(1);
1146             if (TMath::Abs(slope) < kSmallNumber)
1147                fAngleTrackPadrow[index] = TMath::Sign(TMath::Pi()/2, slope); // default value for small slopes
1148             else
1149                fAngleTrackPadrow[index] = TMath::ATan(1/slope);
1150          }
1151          else  fAngleTrackPadrow[index] = TMath::Pi()/2; // default value if not enough data points in fitter
1152          // evaluate XZ fitters
1153          fitter = localXZfitters.GetFitterSimple(iSegment, iPadType);
1154          if (fitter && nClusters[index] >= 2 && fitter->Eval() == 0) {                                   // this will be gone for a new ROOT version > v5-17-05 and replaced by (fitter && fitter->GetNPoints() >= 2 && fitter->Eval() == 0)
1155             Double_t slope = fitter->GetParameter(1);
1156             if (TMath::Abs(slope) < kSmallNumber)
1157                fAngleTrackBeam[index] = TMath::Sign(TMath::Pi()/2, slope); // default value for small slopes
1158             else
1159                fAngleTrackBeam[index] = TMath::ATan(1/slope);
1160          }
1161          else  fAngleTrackBeam[index] = TMath::Pi()/2; // default value if not enough data points in fitter, should be pi/2 for cosmics, something like pi/4 for pp
1162       }
1163    }
1164 }
1165
1166 AliTPCcalibTracksGain::PreProcess::~PreProcess() {
1167    //
1168    // Destructor.
1169    //
1170    
1171    delete[] fAngleTrackPadrow;
1172    delete[] fAngleTrackBeam;
1173    delete[] fMeanCharge;
1174    delete[] fMeanZ;
1175 }
1176
1177 // REMOVE ME, just for debugging
1178 void AliTPCcalibTracksGain::testSeed(char* file, Int_t entry, Int_t tr) {
1179    // read a single AliTPCseed from AliESDs.root and AliESDfriends.root (with new AliRoot)
1180    TFile f(file);
1181    TTree* tree = (TTree*)(f.Get("esdTree"));
1182    tree->SetBranchStatus("*",1);
1183    AliESDEvent* fESDevent = new AliESDEvent();
1184    fESDevent->ReadFromTree(tree);
1185    tree->GetEntry(entry);
1186    AliESDfriend* fESDfriend = (AliESDfriend*)fESDevent->FindListObject("AliESDfriend");
1187    tree->SetBranchAddress("ESDfriend.",&fESDfriend);
1188    fESDevent->SetESDfriend(fESDfriend);
1189    AliESDtrack *esdTrack = (AliESDtrack*) fESDevent->GetTrack(tr);
1190    AliESDfriendTrack *friendtrack = (AliESDfriendTrack*) esdTrack->GetFriendTrack();
1191    AliTPCseed *seed = 0; TObject *cobject = 0;
1192    for (Int_t i = 0; ; i++){ cobject = friendtrack->GetCalibObject(i); if (!cobject) break; seed = dynamic_cast<AliTPCseed*>(cobject); if (seed) break;}
1193
1194    AliTPCcalibTracksGain::PreProcess preProc(seed);
1195    for (Int_t iCluster = 0; iCluster < 159; iCluster++) {
1196       AliTPCclusterMI* cluster = seed->GetClusterPointer(iCluster);
1197       if (cluster) {
1198          Int_t padType = AliTPCcalibTracksGain::GetPadType(cluster->GetX());
1199          Int_t segment = cluster->GetDetector() % 36;
1200          cout << "AngleTrackPadrow(" << segment << ", " << padType << ") == " << preProc.GetAngleTrackPadrow(segment, padType) * TMath::RadToDeg() << endl;
1201          cout << "AngleTrackBeam  (" << segment << ", " << padType << ") == " << preProc.GetAngleTrackBeam(segment, padType) * TMath:: RadToDeg() << endl;
1202          cout << "Correction factor == " << TMath::Abs(TMath::Sin(preProc.GetAngleTrackPadrow(segment, padType))*TMath::Sin(preProc.GetAngleTrackBeam(segment, padType)))/AliTPCcalibTracksGain::GetPadLength(cluster->GetX()) << endl;
1203       }
1204    }
1205 }