]>
Commit | Line | Data |
---|---|---|
1f30d65c | 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 | **************************************************************************/ | |
0fd1fc0b | 15 | |
16 | /// \class AliTPCCombinedTrackfit | |
3a4edebe | 17 | /// |
0fd1fc0b | 18 | /// Combine cosmic track pairs (upper, lower) and do track fitting |
3a4edebe | 19 | /// |
0fd1fc0b | 20 | /// \author Xianguo Lu <lu@physi.uni-heidelberg.de> |
1f30d65c | 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 | { | |
0fd1fc0b | 45 | /// Constructor |
46 | ||
1f30d65c | 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 | { | |
0fd1fc0b | 56 | /// Destructor |
1f30d65c | 57 | |
58 | delete fStreamer; | |
59 | ||
60 | delete fTrackparUp; | |
61 | delete fTrackparLow; | |
62 | } | |
63 | ||
64 | Bool_t AliTPCCombinedTrackfit::CombineESDtracks(AliESDtrack * &trk0, AliESDtrack *&trk1) | |
65 | { | |
0fd1fc0b | 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 | |
1f30d65c | 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 | { | |
0fd1fc0b | 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 | ||
1f30d65c | 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 | { | |
0fd1fc0b | 117 | /// print out variable values |
118 | ||
1f30d65c | 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 | { | |
0fd1fc0b | 124 | /// calculate the impactparameter from (0,0,0) |
125 | ||
1f30d65c | 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 | { | |
0fd1fc0b | 137 | /// the smaller phi of the two tracks w.r.t. horizon |
138 | ||
1f30d65c | 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 | { | |
0fd1fc0b | 147 | /// initialization, for reuse of the same AliTPCCombinedTrackfit instance |
1f30d65c | 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 | { | |
0fd1fc0b | 161 | /// do combined trackfit using TPCseeds |
1f30d65c | 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 | { | |
0fd1fc0b | 194 | /// Update variables depending on the fit result |
1f30d65c | 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 | { | |
0fd1fc0b | 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 | ||
1f30d65c | 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 | { | |
0fd1fc0b | 246 | /// swap seeds (if necessary) so that (y of fSeedUp) > (y of fSeedLow) |
1f30d65c | 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 | { | |
0fd1fc0b | 326 | /// check number of clusters in TPCseed, for too small number MakeSeed will fail |
327 | ||
1f30d65c | 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 | { | |
0fd1fc0b | 338 | /// Get TPC seeds from ESDfriendTrack |
339 | ||
1f30d65c | 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 |