doxy: all TPC root converted
[u/mrichter/AliRoot.git] / TPC / AliTPCCombinedTrackfit.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 /// \class AliTPCCombinedTrackfit
17 ///
18 /// Combine cosmic track pairs (upper, lower) and do track fitting
19 ///
20 /// \author Xianguo Lu <lu@physi.uni-heidelberg.de>
21
22 #include <TAxis.h>
23 #include <TCanvas.h>
24 #include <TFile.h>
25 #include <TGraph.h>
26 #include <TTreeStream.h>
27 #include <TVector3.h>
28
29 #include "AliESDtrack.h"
30 #include "AliESDfriendTrack.h"
31 #include "AliTPCseed.h"
32 #include "AliTrackerBase.h"
33 #include "AliTrackPointArray.h"
34
35 #include "AliTPCCosmicUtils.h"
36 #include "AliTPCCombinedTrackfit.h"
37
38 AliTPCCombinedTrackfit::AliTPCCombinedTrackfit(const Int_t dlev, const TString tag):
39   fStreamer(0x0), fDebugLevel(dlev)
40   , fSeedUp(0x0), fSeedLow(0x0), fTrackparUp(0x0), fTrackparLow(0x0)
41   , fStatus(-999)
42   , fLeverArm(-999)
43   , fFitNcls(-999), fMissNcls(-999), fPreChi2(-999)
44 {
45   /// Constructor
46
47   fInnerClusterUp.SetXYZ(-999,-999,-999);
48   fInnerClusterLow.SetXYZ(-999,-999,-999);
49
50   if(fDebugLevel>0)
51     fStreamer = new TTreeSRedirector(Form("CombinedTrackfit_%s.root", tag.Data()));
52 }
53
54 AliTPCCombinedTrackfit::~AliTPCCombinedTrackfit()
55 {
56   /// Destructor
57
58   delete fStreamer;
59   
60   delete fTrackparUp;
61   delete fTrackparLow;
62 }
63
64 Bool_t AliTPCCombinedTrackfit::CombineESDtracks(AliESDtrack * &trk0, AliESDtrack *&trk1)
65 {
66   /// Get TPCseeds from the 2 ESDtracks, swap TPCseeds and ESDTracks (if necessary) according to y (0:upper 1:lower), perform trackfit using TPCseeds
67   /// if fStatus==0, i.e. combine is successful, swap of the ESDtracks is kept since pointer *& is used
68
69   IniCombineESDtracks();
70
71   if(!GetTPCseeds(trk0, trk1)){
72     return kFALSE; 
73   }
74
75   Bool_t kswap = kFALSE;
76   CombineTPCseeds(kswap);
77
78   if(fStatus == 0){
79     if(kswap){
80       AliESDtrack * tmptrk = trk0;
81       trk0 = trk1;
82       trk1 = tmptrk;
83     }
84     return kTRUE;
85   }
86   else
87     return kFALSE;
88 }
89
90 Bool_t AliTPCCombinedTrackfit::CombineTPCseeds(AliTPCseed * &seed0, AliTPCseed *&seed1)
91 {
92   /// same as AliTPCCombinedTrackfit::CombineESDtracks, except that the seeds are passed in from outside, which can be still unordered
93   /// if fStatus==0, i.e. combine is successful, swap of the TPCseeds is kept since pointer *& is used
94
95   IniCombineESDtracks();
96
97   fSeedUp  = seed0;
98   fSeedLow = seed1;
99   
100   Bool_t kswap = kFALSE;
101   CombineTPCseeds(kswap);
102
103   if(fStatus==0){
104     if(kswap){
105       AliTPCseed * tmpseed = seed0;
106       seed0 = seed1;
107       seed1 = tmpseed;
108     }
109     return kTRUE;
110   }
111   else 
112     return kFALSE;
113 }
114
115 void AliTPCCombinedTrackfit::Print() const
116 {
117   /// print out variable values
118
119   printf("Status %2d NclsU %3d NclsD %3d ZinnerU %7.2f ZinnerD %7.2f LeverArm %7.2f\n", fStatus, fSeedUp->GetNumberOfClusters(), fSeedLow->GetNumberOfClusters(), fInnerClusterUp.Z(), fInnerClusterLow.Z(), fLeverArm);
120 }
121
122 Double_t AliTPCCombinedTrackfit::ImpactParameter() const
123 {
124   /// calculate the impactparameter from (0,0,0)
125
126   const TVector3 p0(0,0,0);
127   const TVector3 va = p0 - fInnerClusterUp;
128   const TVector3 vb = fInnerClusterLow - fInnerClusterUp;
129
130   const TVector3 dd = va.Cross(vb);
131
132   return dd.Mag()/vb.Mag();
133 }
134
135 Double_t AliTPCCombinedTrackfit::MinPhi() const
136 {
137   /// the smaller phi of the two tracks w.r.t. horizon
138
139   Double_t fsp[] = {fabs(sin(fTrackparUp->Phi())), fabs(sin(fTrackparLow->Phi()))};;
140   return asin(TMath::Min(fsp[0], fsp[1])) * TMath::RadToDeg();
141 }
142 //===================================================================================================
143 //===================================================================================================
144
145 void AliTPCCombinedTrackfit::IniCombineESDtracks()
146 {
147   /// initialization, for reuse of the same AliTPCCombinedTrackfit instance
148
149   fSeedUp = 0x0;
150   fSeedLow = 0x0;
151   delete fTrackparUp;
152   delete fTrackparLow;
153   fTrackparUp = 0x0;
154   fTrackparLow = 0x0;
155
156   fStatus = 0;
157 }
158
159 void AliTPCCombinedTrackfit::CombineTPCseeds(Bool_t &kswap)
160 {
161   /// do combined trackfit using TPCseeds
162
163   if(
164      !CheckNcls()
165      || !AnaSeeds(kswap) 
166      || !CheckLeverArm()
167      )
168     return;
169
170   //AliExternalTrackParam object created
171   fTrackparUp  = AliTPCCosmicUtils::MakeSeed(fSeedUp);
172   fTrackparLow = AliTPCCosmicUtils::MakeSeed(fSeedLow);
173   if(!fTrackparUp || !fTrackparLow){
174     fStatus = kFailMakeSeed;
175     return;
176   }
177
178   AliExternalTrackParam * trackPars[]={fTrackparUp, fTrackparLow};
179   const AliTPCseed *seeds[]={fSeedUp, fSeedLow};
180   TTreeSRedirector * debugstreamer = 0x0;
181   if(fDebugLevel&2){
182     debugstreamer = fStreamer;
183   }
184
185   AliTPCCosmicUtils::CombinedFit(trackPars, seeds, fFitNcls, fMissNcls, fPreChi2, debugstreamer);
186
187   Update();
188
189   return;
190 }
191
192 void AliTPCCombinedTrackfit::Update()
193 {
194   /// Update variables depending on the fit result
195
196   if(fMissNcls || fFitNcls==0){
197     fStatus = kFailPropagation;
198     return;
199   }
200
201   fPreChi2 /= fFitNcls;
202   if(fPreChi2>fgkMaxChi2){
203     fStatus = kFailChi2;
204     return;
205   }
206
207   if( fStatus == 0 && (fDebugLevel&1) ){
208     Double_t momup  = fTrackparUp->P();
209     Double_t momlow = fTrackparLow->P();
210     Double_t ptup   = fTrackparUp->Pt();
211     Double_t ptlow  = fTrackparLow->Pt();
212
213     (*fStreamer)<<"TrackProp"<<
214       "Tup.="<<fTrackparUp<<
215       "Tlow.="<<fTrackparLow<<
216       "icup.="<<&fInnerClusterUp<<
217       "iclow.="<<&fInnerClusterLow<<
218       "leverarm="<<fLeverArm<<
219       "ncl="<<fFitNcls<<
220       "nmiss="<<fMissNcls<<
221       "chi2="<<fPreChi2<<
222       "momup="<<  momup <<
223       "momlow="<< momlow <<
224       "ptup="<<   ptup <<
225       "ptlow="<<  ptlow <<
226       "\n";
227   }
228 }
229
230 Bool_t AliTPCCombinedTrackfit::CheckLeverArm()
231 {
232   /// if lever arm is too short, no need to use combined track fit.
233   /// On the other hand, short lever arm from two tracks mostly means they are fake pairs.
234   /// lever arm extents over one quadrant, e.g. (0,250)-(250,0): 250*sqrt(2)~350
235
236   if(fLeverArm<fgkCutLeverArm){
237     fStatus = kFailLeverArm;
238     return kFALSE;
239   }
240   else 
241     return kTRUE;
242 }
243
244 Bool_t AliTPCCombinedTrackfit::AnaSeeds(Bool_t &kswap)
245 {
246   /// swap seeds (if necessary) so that (y of fSeedUp) > (y of fSeedLow)
247
248   //---------------------------------- navigate through all clusters ----------------------------------
249   AliTPCseed ** seeds[]={&fSeedUp, &fSeedLow};
250
251   //min, max according to y
252   TVector3 singlemin[2], singlemax[2];
253   for(Int_t ii=0; ii<2; ii++){
254     singlemin[ii].SetXYZ( 1e10,  1e10,  1e10);
255     singlemax[ii].SetXYZ(-1e10, -1e10, -1e10);
256   }
257   
258   for(Int_t itrk=0; itrk<2; itrk++){
259     for(Int_t irow=0; irow<AliTPCCosmicUtils::fgkNRow; irow++){
260       const AliTPCclusterMI * cls = (*seeds[itrk])->GetClusterPointer(irow);
261       if(!cls)
262         continue;
263       
264       Float_t xyz[3]={-999,-999,-999};
265       cls->GetGlobalXYZ(xyz);
266       if(xyz[1]<singlemin[itrk].Y()){
267         singlemin[itrk].SetXYZ(xyz[0], xyz[1], xyz[2]);
268       }
269       if(xyz[1]>singlemax[itrk].Y()){
270         singlemax[itrk].SetXYZ(xyz[0], xyz[1], xyz[2]);
271       }
272     }
273   }
274
275   //--------------------------------
276
277   //kpass true if y of the two seeds clearly separate: min of one > max of the other
278   Bool_t kpass = kFALSE;
279
280   fInnerClusterUp.SetXYZ(-999,-999,-999);
281   fInnerClusterLow.SetXYZ(-999,-999,-999);
282   TVector3 combinedmin, combinedmax;
283   if(singlemin[0].Y()> singlemax[1].Y()){
284     fInnerClusterUp  = singlemin[0];
285     fInnerClusterLow = singlemax[1];
286
287     //no need to swap
288     kswap = kFALSE;
289
290     kpass = kTRUE;
291
292     combinedmax = singlemax[0];
293     combinedmin = singlemin[1];
294   }
295   else if(singlemin[1].Y()> singlemax[0].Y()){
296     fInnerClusterUp  = singlemin[1];
297     fInnerClusterLow = singlemax[0];
298   
299     //have to be swapped
300     kswap = kTRUE;
301     AliTPCseed *tmp=*(seeds[0]);
302     *(seeds[0])=*(seeds[1]);
303     *(seeds[1])=tmp;
304     
305     kpass = kTRUE;
306
307     combinedmax = singlemax[1];
308     combinedmin = singlemin[0];
309   }           
310   else
311     kpass = kFALSE;
312
313   const TVector3 comdelta = combinedmax-combinedmin;
314   fLeverArm = comdelta.Pt();
315
316   if(!kpass){
317     fStatus = kFailSwapSeeds;
318     return kFALSE;
319   }
320   else
321     return kTRUE;
322 }
323
324 Bool_t AliTPCCombinedTrackfit::CheckNcls()
325 {
326   /// check number of clusters in TPCseed, for too small number MakeSeed will fail
327
328   if( fSeedUp->GetNumberOfClusters()<AliTPCCosmicUtils::fgkNclsMin || fSeedLow->GetNumberOfClusters()<AliTPCCosmicUtils::fgkNclsMin ){
329     fStatus = kFailNclsMin;
330     return kFALSE;
331   }
332   else
333     return kTRUE;
334 }
335
336 Bool_t AliTPCCombinedTrackfit::GetTPCseeds(const AliESDtrack *trk0,  const AliESDtrack *trk1)
337 {
338   /// Get TPC seeds from ESDfriendTrack
339
340   fSeedUp  = AliTPCCosmicUtils::GetTPCseed(trk0);
341   fSeedLow = AliTPCCosmicUtils::GetTPCseed(trk1);
342
343   if(!fSeedUp || !fSeedLow){
344     fStatus = kFailGetTPCseeds;
345     return kFALSE;
346   }
347
348   return kTRUE;
349 }
350