fe4da5cc |
1 | /////////////////////////////////////////////////////////////////////////////// |
2 | // // |
3 | // Time Projection Chamber // |
4 | // This class contains the basic functions for the Time Projection Chamber // |
5 | // detector. Functions specific to one particular geometry are // |
6 | // contained in the derived classes // |
7 | // // |
8 | //Begin_Html |
9 | /* |
1439f98e |
10 | <img src="picts/AliTPCClass.gif"> |
fe4da5cc |
11 | */ |
12 | //End_Html |
13 | // // |
8c555625 |
14 | // // |
fe4da5cc |
15 | /////////////////////////////////////////////////////////////////////////////// |
16 | |
17 | #include <TMath.h> |
18 | #include <TRandom.h> |
19 | #include <TVector.h> |
8c555625 |
20 | #include <TMatrix.h> |
fe4da5cc |
21 | #include <TGeometry.h> |
22 | #include <TNode.h> |
23 | #include <TTUBS.h> |
24 | #include <TObjectTable.h> |
1578254f |
25 | #include "TParticle.h" |
fe4da5cc |
26 | #include "AliTPC.h" |
27 | #include "AliRun.h" |
28 | #include <iostream.h> |
29 | #include <fstream.h> |
30 | #include "AliMC.h" |
31 | |
8c555625 |
32 | //MI change |
33 | #include "AliTPCParam.h" |
34 | #include "AliTPCD.h" |
35 | #include "AliTPCPRF2D.h" |
36 | #include "AliTPCRF1D.h" |
37 | |
38 | |
1283eee5 |
39 | |
fe4da5cc |
40 | ClassImp(AliTPC) |
41 | |
42 | //_____________________________________________________________________________ |
43 | AliTPC::AliTPC() |
44 | { |
45 | // |
46 | // Default constructor |
47 | // |
48 | fIshunt = 0; |
49 | fClusters = 0; |
50 | fHits = 0; |
51 | fDigits = 0; |
52 | fTracks = 0; |
53 | fNsectors = 0; |
54 | fNtracks = 0; |
55 | fNclusters= 0; |
3c0f9266 |
56 | |
8c555625 |
57 | fDigParam= new AliTPCD(); |
58 | fDigits = fDigParam->GetArray(); |
fe4da5cc |
59 | } |
60 | |
61 | //_____________________________________________________________________________ |
62 | AliTPC::AliTPC(const char *name, const char *title) |
63 | : AliDetector(name,title) |
64 | { |
65 | // |
66 | // Standard constructor |
67 | // |
68 | |
69 | // |
70 | // Initialise arrays of hits and digits |
71 | fHits = new TClonesArray("AliTPChit", 176); |
8c555625 |
72 | // fDigits = new TClonesArray("AliTPCdigit",10000); |
73 | //MI change |
74 | fDigParam= new AliTPCD; |
75 | fDigits = fDigParam->GetArray(); |
3c0f9266 |
76 | |
77 | AliTPCParam *fTPCParam = &(fDigParam->GetParam()); |
78 | |
fe4da5cc |
79 | // |
80 | // Initialise counters |
3c0f9266 |
81 | // |
fe4da5cc |
82 | fClusters = 0; |
83 | fTracks = 0; |
3c0f9266 |
84 | fNsectors = fTPCParam->GetNSector(); |
fe4da5cc |
85 | fNtracks = 0; |
86 | fNclusters= 0; |
87 | fDigitsIndex = new Int_t[fNsectors+1]; |
88 | fClustersIndex = new Int_t[fNsectors+1]; |
89 | // |
90 | fIshunt = 0; |
91 | // |
92 | // Initialise color attributes |
93 | SetMarkerColor(kYellow); |
94 | } |
95 | |
96 | //_____________________________________________________________________________ |
97 | AliTPC::~AliTPC() |
98 | { |
99 | // |
100 | // TPC destructor |
101 | // |
102 | fIshunt = 0; |
103 | delete fHits; |
104 | delete fDigits; |
105 | delete fClusters; |
106 | delete fTracks; |
8c555625 |
107 | delete fDigParam; |
fe4da5cc |
108 | if (fDigitsIndex) delete [] fDigitsIndex; |
109 | if (fClustersIndex) delete [] fClustersIndex; |
110 | } |
111 | |
112 | //_____________________________________________________________________________ |
113 | void AliTPC::AddCluster(Float_t *hits, Int_t *tracks) |
114 | { |
115 | // |
116 | // Add a simulated cluster to the list |
117 | // |
118 | if(!fClusters) fClusters=new TClonesArray("AliTPCcluster",10000); |
119 | TClonesArray &lclusters = *fClusters; |
120 | new(lclusters[fNclusters++]) AliTPCcluster(hits,tracks); |
121 | } |
122 | |
123 | //_____________________________________________________________________________ |
124 | void AliTPC::AddCluster(const AliTPCcluster &c) |
125 | { |
126 | // |
127 | // Add a simulated cluster copy to the list |
128 | // |
129 | if(!fClusters) fClusters=new TClonesArray("AliTPCcluster",10000); |
130 | TClonesArray &lclusters = *fClusters; |
131 | new(lclusters[fNclusters++]) AliTPCcluster(c); |
132 | } |
133 | |
134 | //_____________________________________________________________________________ |
135 | void AliTPC::AddDigit(Int_t *tracks, Int_t *digits) |
136 | { |
137 | // |
138 | // Add a TPC digit to the list |
139 | // |
8c555625 |
140 | // TClonesArray &ldigits = *fDigits; |
141 | //MI change |
142 | TClonesArray &ldigits = *fDigParam->GetArray(); |
fe4da5cc |
143 | new(ldigits[fNdigits++]) AliTPCdigit(tracks,digits); |
144 | } |
145 | |
146 | //_____________________________________________________________________________ |
147 | void AliTPC::AddHit(Int_t track, Int_t *vol, Float_t *hits) |
148 | { |
149 | // |
150 | // Add a hit to the list |
151 | // |
152 | TClonesArray &lhits = *fHits; |
153 | new(lhits[fNhits++]) AliTPChit(fIshunt,track,vol,hits); |
154 | } |
155 | |
156 | //_____________________________________________________________________________ |
157 | void AliTPC::AddTrack(Float_t *hits) |
158 | { |
159 | // |
160 | // Add a track to the list of tracks |
161 | // |
162 | TClonesArray <racks = *fTracks; |
163 | new(ltracks[fNtracks++]) AliTPCtrack(hits); |
164 | } |
165 | |
166 | //_____________________________________________________________________________ |
167 | void AliTPC::AddTrack(const AliTPCtrack& t) |
168 | { |
169 | // |
170 | // Add a track copy to the list of tracks |
171 | // |
172 | if(!fTracks) fTracks=new TClonesArray("AliTPCtrack",10000); |
173 | TClonesArray <racks = *fTracks; |
174 | new(ltracks[fNtracks++]) AliTPCtrack(t); |
175 | } |
176 | |
177 | //_____________________________________________________________________________ |
178 | void AliTPC::BuildGeometry() |
179 | { |
180 | // |
181 | // Build TPC ROOT TNode geometry for the event display |
182 | // |
183 | TNode *Node, *Top; |
184 | TTUBS *tubs; |
185 | Int_t i; |
186 | const int kColorTPC=19; |
1283eee5 |
187 | char name[5], title[25]; |
fe4da5cc |
188 | const Double_t kDegrad=TMath::Pi()/180; |
1283eee5 |
189 | const Double_t kRaddeg=180./TMath::Pi(); |
190 | |
191 | AliTPCParam * fTPCParam = &(fDigParam->GetParam()); |
192 | |
193 | Float_t InnerOpenAngle = fTPCParam->GetInnerAngle(); |
194 | Float_t OuterOpenAngle = fTPCParam->GetOuterAngle(); |
195 | |
196 | Float_t InnerAngleShift = fTPCParam->GetInnerAngleShift(); |
197 | Float_t OuterAngleShift = fTPCParam->GetOuterAngleShift(); |
198 | |
199 | Int_t nLo = fTPCParam->GetNInnerSector()/2; |
200 | Int_t nHi = fTPCParam->GetNOuterSector()/2; |
201 | |
202 | const Double_t loAng = (Double_t)TMath::Nint(InnerOpenAngle*kRaddeg); |
203 | const Double_t hiAng = (Double_t)TMath::Nint(OuterOpenAngle*kRaddeg); |
204 | const Double_t loAngSh = (Double_t)TMath::Nint(InnerAngleShift*kRaddeg); |
205 | const Double_t hiAngSh = (Double_t)TMath::Nint(OuterAngleShift*kRaddeg); |
206 | |
207 | |
fe4da5cc |
208 | const Double_t loCorr = 1/TMath::Cos(0.5*loAng*kDegrad); |
209 | const Double_t hiCorr = 1/TMath::Cos(0.5*hiAng*kDegrad); |
1283eee5 |
210 | |
211 | Double_t rl,ru; |
212 | |
213 | |
fe4da5cc |
214 | // |
215 | // Get ALICE top node |
fe4da5cc |
216 | // |
1283eee5 |
217 | |
218 | Top=gAlice->GetGeometry()->GetNode("alice"); |
219 | |
220 | // inner sectors |
221 | |
222 | rl = fTPCParam->GetInSecLowEdge(); |
223 | ru = fTPCParam->GetInSecUpEdge(); |
224 | |
225 | |
fe4da5cc |
226 | for(i=0;i<nLo;i++) { |
227 | sprintf(name,"LS%2.2d",i); |
1283eee5 |
228 | name[4]='\0'; |
229 | sprintf(title,"TPC low sector %3d",i); |
230 | title[24]='\0'; |
231 | |
232 | tubs = new TTUBS(name,title,"void",rl*loCorr,ru*loCorr,250., |
233 | loAng*(i-0.5)+loAngSh,loAng*(i+0.5)+loAngSh); |
fe4da5cc |
234 | tubs->SetNumberOfDivisions(1); |
235 | Top->cd(); |
236 | Node = new TNode(name,title,name,0,0,0,""); |
237 | Node->SetLineColor(kColorTPC); |
238 | fNodes->Add(Node); |
239 | } |
1283eee5 |
240 | |
fe4da5cc |
241 | // Outer sectors |
1283eee5 |
242 | |
243 | rl = fTPCParam->GetOuSecLowEdge(); |
244 | ru = fTPCParam->GetOuSecUpEdge(); |
245 | |
fe4da5cc |
246 | for(i=0;i<nHi;i++) { |
247 | sprintf(name,"US%2.2d",i); |
1283eee5 |
248 | name[4]='\0'; |
fe4da5cc |
249 | sprintf(title,"TPC upper sector %d",i); |
1283eee5 |
250 | title[24]='\0'; |
251 | tubs = new TTUBS(name,title,"void",rl*hiCorr,ru*hiCorr,250, |
252 | hiAng*(i-0.5)+hiAngSh,hiAng*(i+0.5)+hiAngSh); |
fe4da5cc |
253 | tubs->SetNumberOfDivisions(1); |
254 | Top->cd(); |
255 | Node = new TNode(name,title,name,0,0,0,""); |
256 | Node->SetLineColor(kColorTPC); |
257 | fNodes->Add(Node); |
258 | } |
1283eee5 |
259 | } |
260 | |
261 | |
262 | |
fe4da5cc |
263 | //_____________________________________________________________________________ |
264 | Int_t AliTPC::DistancetoPrimitive(Int_t , Int_t ) |
265 | { |
266 | // |
267 | // Calculate distance from TPC to mouse on the display |
268 | // Dummy procedure |
269 | // |
270 | return 9999; |
271 | } |
272 | |
fe4da5cc |
273 | //_____________________________________________________________________________ |
274 | static Double_t SigmaY2(Double_t r, Double_t tgl, Double_t pt) |
275 | { |
276 | // |
3c0f9266 |
277 | // Parametrised error of the cluster reconstruction (pad direction) |
fe4da5cc |
278 | // |
279 | pt=TMath::Abs(pt)*1000.; |
280 | Double_t x=r/pt; |
281 | tgl=TMath::Abs(tgl); |
282 | Double_t s=a_rphi - b_rphi*r*tgl + c_rphi*x*x + d_rphi*x; |
283 | if (s<0.4e-3) s=0.4e-3; |
3c0f9266 |
284 | s*=1.3; //Iouri Belikov |
fe4da5cc |
285 | return s; |
286 | } |
287 | |
288 | //_____________________________________________________________________________ |
289 | static Double_t SigmaZ2(Double_t r, Double_t tgl) |
290 | { |
291 | // |
3c0f9266 |
292 | // Parametrised error of the cluster reconstruction (drift direction) |
fe4da5cc |
293 | // |
294 | tgl=TMath::Abs(tgl); |
295 | Double_t s=a_z - b_z*r*tgl + c_z*tgl*tgl; |
296 | if (s<0.4e-3) s=0.4e-3; |
3c0f9266 |
297 | s*=1.3; //Iouri Belikov |
fe4da5cc |
298 | return s; |
299 | } |
300 | |
301 | //_____________________________________________________________________________ |
3c0f9266 |
302 | inline Double_t f1(Double_t x1,Double_t y1, |
fe4da5cc |
303 | Double_t x2,Double_t y2, |
304 | Double_t x3,Double_t y3) |
305 | { |
3c0f9266 |
306 | //----------------------------------------------------------------- |
307 | // Initial approximation of the track curvature |
fe4da5cc |
308 | // |
3c0f9266 |
309 | // Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch |
310 | //----------------------------------------------------------------- |
fe4da5cc |
311 | Double_t d=(x2-x1)*(y3-y2)-(x3-x2)*(y2-y1); |
312 | Double_t a=0.5*((y3-y2)*(y2*y2-y1*y1+x2*x2-x1*x1)- |
313 | (y2-y1)*(y3*y3-y2*y2+x3*x3-x2*x2)); |
314 | Double_t b=0.5*((x2-x1)*(y3*y3-y2*y2+x3*x3-x2*x2)- |
315 | (x3-x2)*(y2*y2-y1*y1+x2*x2-x1*x1)); |
8c555625 |
316 | |
fe4da5cc |
317 | Double_t xr=TMath::Abs(d/(d*x1-a)), yr=d/(d*y1-b); |
8c555625 |
318 | |
fe4da5cc |
319 | return -xr*yr/sqrt(xr*xr+yr*yr); |
320 | } |
321 | |
322 | |
323 | //_____________________________________________________________________________ |
3c0f9266 |
324 | inline Double_t f2(Double_t x1,Double_t y1, |
fe4da5cc |
325 | Double_t x2,Double_t y2, |
326 | Double_t x3,Double_t y3) |
327 | { |
3c0f9266 |
328 | //----------------------------------------------------------------- |
329 | // Initial approximation of the track curvature times center of curvature |
fe4da5cc |
330 | // |
3c0f9266 |
331 | // Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch |
332 | //----------------------------------------------------------------- |
fe4da5cc |
333 | Double_t d=(x2-x1)*(y3-y2)-(x3-x2)*(y2-y1); |
334 | Double_t a=0.5*((y3-y2)*(y2*y2-y1*y1+x2*x2-x1*x1)- |
335 | (y2-y1)*(y3*y3-y2*y2+x3*x3-x2*x2)); |
336 | Double_t b=0.5*((x2-x1)*(y3*y3-y2*y2+x3*x3-x2*x2)- |
337 | (x3-x2)*(y2*y2-y1*y1+x2*x2-x1*x1)); |
8c555625 |
338 | |
fe4da5cc |
339 | Double_t xr=TMath::Abs(d/(d*x1-a)), yr=d/(d*y1-b); |
340 | |
341 | return -a/(d*y1-b)*xr/sqrt(xr*xr+yr*yr); |
342 | } |
343 | |
344 | //_____________________________________________________________________________ |
3c0f9266 |
345 | inline Double_t f3(Double_t x1,Double_t y1, |
fe4da5cc |
346 | Double_t x2,Double_t y2, |
347 | Double_t z1,Double_t z2) |
348 | { |
3c0f9266 |
349 | //----------------------------------------------------------------- |
350 | // Initial approximation of the tangent of the track dip angle |
fe4da5cc |
351 | // |
3c0f9266 |
352 | // Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch |
353 | //----------------------------------------------------------------- |
fe4da5cc |
354 | return (z1 - z2)/sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)); |
355 | } |
356 | |
357 | //_____________________________________________________________________________ |
3c0f9266 |
358 | static int FindProlongation(AliTPCtrack& t, const AliTPCSector *sec, |
359 | int s, int rf=0) |
fe4da5cc |
360 | { |
3c0f9266 |
361 | //----------------------------------------------------------------- |
362 | // This function tries to find a track prolongation. |
fe4da5cc |
363 | // |
3c0f9266 |
364 | // Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch |
365 | //----------------------------------------------------------------- |
366 | const int ROWS_TO_SKIP=int(0.5*sec->GetNRows()); |
367 | const Float_t MAX_CHI2=12.; |
fe4da5cc |
368 | int try_again=ROWS_TO_SKIP; |
369 | Double_t alpha=sec->GetAlpha(); |
3c0f9266 |
370 | int ns=int(2*TMath::Pi()/alpha+0.5); |
8c555625 |
371 | |
3c0f9266 |
372 | for (int nr=sec->GetRowNumber(t.GetX())-1; nr>=rf; nr--) { |
373 | Double_t x=sec->GetX(nr), ymax=sec->GetMaxY(nr); |
374 | if (!t.PropagateTo(x)) return 0; |
8c555625 |
375 | |
3c0f9266 |
376 | AliTPCcluster *cl=0; |
fe4da5cc |
377 | Double_t max_chi2=MAX_CHI2; |
378 | const AliTPCRow& row=sec[s][nr]; |
379 | Double_t sy2=SigmaY2(t.GetX(),t.GetTgl(),t.GetPt()); |
380 | Double_t sz2=SigmaZ2(t.GetX(),t.GetTgl()); |
3c0f9266 |
381 | Double_t road=5.*sqrt(t.GetSigmaY2() + sy2), y=t.GetY(), z=t.GetZ(); |
8c555625 |
382 | |
fe4da5cc |
383 | if (road>30) { |
3c0f9266 |
384 | if (t>4) cerr<<t<<" FindProlongation warning: Too broad road !\n"; |
385 | return 0; |
fe4da5cc |
386 | } |
8c555625 |
387 | |
388 | if (row) { |
fe4da5cc |
389 | for (int i=row.Find(y-road); i<row; i++) { |
390 | AliTPCcluster* c=(AliTPCcluster*)(row[i]); |
391 | if (c->fY > y+road) break; |
392 | if (c->IsUsed()) continue; |
3c0f9266 |
393 | if ((c->fZ - z)*(c->fZ - z) > 25.*(t.GetSigmaZ2() + sz2)) continue; |
fe4da5cc |
394 | Double_t chi2=t.GetPredictedChi2(c); |
395 | if (chi2 > max_chi2) continue; |
396 | max_chi2=chi2; |
397 | cl=c; |
398 | } |
8c555625 |
399 | } |
fe4da5cc |
400 | if (cl) { |
401 | t.Update(cl,max_chi2); |
3c0f9266 |
402 | Double_t ll=TMath::Sqrt((1+t.GetTgl()*t.GetTgl())/ |
403 | (1-(t.GetC()*x-t.GetEta())*(t.GetC()*x-t.GetEta()))); |
404 | cl->fdEdX = cl->fQ/ll; |
fe4da5cc |
405 | try_again=ROWS_TO_SKIP; |
406 | } else { |
8c555625 |
407 | if (try_again==0) break; |
408 | if (y > ymax) { |
409 | s = (s+1) % ns; |
3c0f9266 |
410 | if (!t.Rotate(alpha)) return 0; |
8c555625 |
411 | } else if (y <-ymax) { |
3c0f9266 |
412 | s = (s-1+ns) % ns; |
413 | if (!t.Rotate(-alpha)) return 0; |
fe4da5cc |
414 | } |
8c555625 |
415 | try_again--; |
fe4da5cc |
416 | } |
417 | } |
8c555625 |
418 | |
3c0f9266 |
419 | return 1; |
fe4da5cc |
420 | } |
421 | |
8c555625 |
422 | |
fe4da5cc |
423 | //_____________________________________________________________________________ |
3c0f9266 |
424 | static void MakeSeeds(TObjArray& seeds,const AliTPCSector *sec, int max_sec, |
425 | int i1, int i2) |
fe4da5cc |
426 | { |
3c0f9266 |
427 | //----------------------------------------------------------------- |
428 | // This function creates track seeds. |
fe4da5cc |
429 | // |
3c0f9266 |
430 | // Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch |
431 | //----------------------------------------------------------------- |
fe4da5cc |
432 | TMatrix C(5,5); TVector x(5); |
3c0f9266 |
433 | double alpha=sec->GetAlpha(), shift=sec->GetAlphaShift(); |
434 | double cs=cos(alpha), sn=sin(alpha); |
fe4da5cc |
435 | for (int ns=0; ns<max_sec; ns++) { |
436 | int nl=sec[(ns-1+max_sec)%max_sec][i2]; |
437 | int nm=sec[ns][i2]; |
438 | int nu=sec[(ns+1)%max_sec][i2]; |
fe4da5cc |
439 | const AliTPCRow& r1=sec[ns][i1]; |
440 | for (int is=0; is < r1; is++) { |
3c0f9266 |
441 | double x1=sec->GetX(i1), y1=r1[is]->fY, z1=r1[is]->fZ; |
fe4da5cc |
442 | for (int js=0; js < nl+nm+nu; js++) { |
443 | const AliTPCcluster *cl; |
8c555625 |
444 | int ks; |
3c0f9266 |
445 | double x2=sec->GetX(i2), y2, z2, tmp; |
446 | |
fe4da5cc |
447 | if (js<nl) { |
8c555625 |
448 | ks=(ns-1+max_sec)%max_sec; |
fe4da5cc |
449 | const AliTPCRow& r2=sec[(ns-1+max_sec)%max_sec][i2]; |
450 | cl=r2[js]; |
3c0f9266 |
451 | y2=cl->fY; z2=cl->fZ; |
452 | tmp= x2*cs+y2*sn; |
453 | y2 =-x2*sn+y2*cs; x2=tmp; |
fe4da5cc |
454 | } else |
455 | if (js<nl+nm) { |
8c555625 |
456 | ks=ns; |
fe4da5cc |
457 | const AliTPCRow& r2=sec[ns][i2]; |
458 | cl=r2[js-nl]; |
3c0f9266 |
459 | y2=cl->fY; z2=cl->fZ; |
fe4da5cc |
460 | } else { |
8c555625 |
461 | ks=(ns+1)%max_sec; |
fe4da5cc |
462 | const AliTPCRow& r2=sec[(ns+1)%max_sec][i2]; |
463 | cl=r2[js-nl-nm]; |
3c0f9266 |
464 | y2=cl->fY; z2=cl->fZ; |
465 | tmp=x2*cs-y2*sn; |
466 | y2 =x2*sn+y2*cs; x2=tmp; |
fe4da5cc |
467 | } |
3c0f9266 |
468 | |
469 | double d=(x2-x1)*(0.-y2)-(0.-x2)*(y2-y1); |
470 | if (d==0.) {cerr<<"MakeSeeds warning: Straight seed !\n"; continue;} |
471 | |
fe4da5cc |
472 | x(0)=y1; |
473 | x(1)=z1; |
474 | x(2)=f1(x1,y1,x2,y2,0.,0.); |
475 | x(3)=f2(x1,y1,x2,y2,0.,0.); |
476 | x(4)=f3(x1,y1,x2,y2,z1,z2); |
477 | |
478 | if (TMath::Abs(x(2)*x1-x(3)) >= 0.999) continue; |
479 | |
480 | if (TMath::Abs(x(4)) > 1.2) continue; |
8c555625 |
481 | |
fe4da5cc |
482 | Double_t a=asin(x(3)); |
fe4da5cc |
483 | Double_t zv=z1 - x(4)/x(2)*(a+asin(x(2)*x1-x(3))); |
484 | if (TMath::Abs(zv)>33.) continue; |
8c555625 |
485 | |
fe4da5cc |
486 | TMatrix X(6,6); X=0.; |
487 | X(0,0)=r1[is]->fSigmaY2; X(1,1)=r1[is]->fSigmaZ2; |
488 | X(2,2)=cl->fSigmaY2; X(3,3)=cl->fSigmaZ2; |
489 | X(4,4)=3./12.; X(5,5)=3./12.; |
490 | TMatrix F(5,6); F.UnitMatrix(); |
491 | Double_t sy=sqrt(X(0,0)), sz=sqrt(X(1,1)); |
492 | F(2,0)=(f1(x1,y1+sy,x2,y2,0.,0.)-x(2))/sy; |
493 | F(2,2)=(f1(x1,y1,x2,y2+sy,0.,0.)-x(2))/sy; |
494 | F(2,4)=(f1(x1,y1,x2,y2,0.,0.+sy)-x(2))/sy; |
495 | F(3,0)=(f2(x1,y1+sy,x2,y2,0.,0.)-x(3))/sy; |
496 | F(3,2)=(f2(x1,y1,x2,y2+sy,0.,0.)-x(3))/sy; |
497 | F(3,4)=(f2(x1,y1,x2,y2,0.,0.+sy)-x(3))/sy; |
498 | F(4,0)=(f3(x1,y1+sy,x2,y2,z1,z2)-x(4))/sy; |
499 | F(4,1)=(f3(x1,y1,x2,y2,z1+sz,z2)-x(4))/sz; |
500 | F(4,2)=(f3(x1,y1,x2,y2+sy,z1,z2)-x(4))/sy; |
501 | F(4,3)=(f3(x1,y1,x2,y2,z1,z2+sz)-x(4))/sz; |
502 | F(4,4)=0; |
503 | F(3,3)=0; |
504 | |
505 | TMatrix t(F,TMatrix::kMult,X); |
506 | C.Mult(t,TMatrix(TMatrix::kTransposed,F)); |
8c555625 |
507 | |
3c0f9266 |
508 | AliTPCtrack *track=new AliTPCtrack(r1[is], x, C, x1, ns*alpha+shift); |
509 | int rc=FindProlongation(*track,sec,ns,i2); |
8c555625 |
510 | if (rc<0 || *track<(i1-i2)/2) delete track; |
511 | else seeds.AddLast(track); |
fe4da5cc |
512 | } |
513 | } |
514 | } |
515 | } |
516 | |
517 | //_____________________________________________________________________________ |
3c0f9266 |
518 | AliTPCParam *AliTPCSector::param; |
fe4da5cc |
519 | void AliTPC::Clusters2Tracks() |
520 | { |
3c0f9266 |
521 | //----------------------------------------------------------------- |
522 | // This is a track finder. |
fe4da5cc |
523 | // |
3c0f9266 |
524 | // Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch |
525 | //----------------------------------------------------------------- |
fe4da5cc |
526 | if (!fClusters) return; |
8c555625 |
527 | |
528 | AliTPCParam *p=&fDigParam->GetParam(); |
3c0f9266 |
529 | AliTPCSector::SetParam(p); |
8c555625 |
530 | |
3c0f9266 |
531 | const int nis=p->GetNInnerSector()/2; |
532 | AliTPCSSector *ssec=new AliTPCSSector[nis]; |
533 | int nrow_low=ssec->GetNRows(); |
8c555625 |
534 | |
3c0f9266 |
535 | const int nos=p->GetNOuterSector()/2; |
536 | AliTPCLSector *lsec=new AliTPCLSector[nos]; |
537 | int nrow_up=lsec->GetNRows(); |
8c555625 |
538 | |
fe4da5cc |
539 | int ncl=fClusters->GetEntriesFast(); |
540 | while (ncl--) { |
541 | AliTPCcluster *c=(AliTPCcluster*)fClusters->UncheckedAt(ncl); |
3c0f9266 |
542 | Int_t sec=c->fSector, row=c->fPadRow; |
543 | if (sec<nis*2) { |
544 | ssec[sec%nis][row].InsertCluster(c); |
fe4da5cc |
545 | } else { |
3c0f9266 |
546 | sec -= nis*2; |
547 | lsec[sec%nos][row].InsertCluster(c); |
fe4da5cc |
548 | } |
549 | } |
550 | |
fe4da5cc |
551 | TObjArray seeds(20000); |
3c0f9266 |
552 | |
553 | int nrows=nrow_low+nrow_up; |
554 | int gap=int(0.125*nrows), shift=int(0.5*gap); |
555 | MakeSeeds(seeds, lsec, nos, nrow_up-1, nrow_up-1-gap); |
556 | MakeSeeds(seeds, lsec, nos, nrow_up-1-shift, nrow_up-1-shift-gap); |
8c555625 |
557 | |
fe4da5cc |
558 | seeds.Sort(); |
559 | |
560 | int found=0; |
561 | int nseed=seeds.GetEntriesFast(); |
562 | |
563 | for (int s=0; s<nseed; s++) { |
564 | AliTPCtrack& t=*((AliTPCtrack*)seeds.UncheckedAt(s)); |
3c0f9266 |
565 | double alpha=t.GetAlpha(); |
fe4da5cc |
566 | if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi(); |
567 | if (alpha < 0. ) alpha += 2.*TMath::Pi(); |
3c0f9266 |
568 | int ns=int(alpha/lsec->GetAlpha())%nos; |
569 | |
570 | if (!FindProlongation(t,lsec,ns)) continue; |
571 | |
572 | alpha=t.GetAlpha() + 0.5*ssec->GetAlpha() - ssec->GetAlphaShift(); |
573 | if (alpha > 2.*TMath::Pi()) alpha -= 2.*TMath::Pi(); |
574 | if (alpha < 0. ) alpha += 2.*TMath::Pi(); |
575 | ns=int(alpha/ssec->GetAlpha())%nis; //index of the inner sector needed |
576 | |
577 | alpha=ns*ssec->GetAlpha() - t.GetAlpha(); |
578 | if (!t.Rotate(alpha)) continue; |
579 | |
580 | if (!FindProlongation(t,ssec,ns)) continue; |
fe4da5cc |
581 | |
3c0f9266 |
582 | if (t < int(0.4*nrows)) continue; |
fe4da5cc |
583 | |
584 | AddTrack(t); |
585 | t.UseClusters(); |
586 | cerr<<found++<<'\r'; |
587 | } |
3c0f9266 |
588 | |
589 | delete[] ssec; |
590 | delete[] lsec; |
fe4da5cc |
591 | } |
592 | |
593 | //_____________________________________________________________________________ |
594 | void AliTPC::CreateMaterials() |
595 | { |
8c555625 |
596 | //----------------------------------------------- |
fe4da5cc |
597 | // Create Materials for for TPC |
8c555625 |
598 | //----------------------------------------------- |
599 | |
600 | //----------------------------------------------------------------- |
601 | // Origin: Marek Kowalski IFJ, Krakow, Marek.Kowalski@ifj.edu.pl |
602 | //----------------------------------------------------------------- |
1283eee5 |
603 | |
fe4da5cc |
604 | Int_t ISXFLD=gAlice->Field()->Integ(); |
605 | Float_t SXMGMX=gAlice->Field()->Max(); |
1283eee5 |
606 | |
607 | Float_t amat[5]; // atomic numbers |
608 | Float_t zmat[5]; // z |
609 | Float_t wmat[5]; // proportions |
610 | |
611 | Float_t density; |
612 | |
613 | // ********************* Gases ******************* |
614 | |
615 | //-------------------------------------------------------------- |
616 | // pure gases |
617 | //-------------------------------------------------------------- |
618 | |
619 | // Ne |
620 | |
621 | |
622 | Float_t a_ne = 20.18; |
623 | Float_t z_ne = 10.; |
fe4da5cc |
624 | |
1283eee5 |
625 | density = 0.0009; |
626 | |
627 | AliMaterial(20,"Ne",a_ne,z_ne,density,999.,999.); |
628 | |
629 | // Ar |
630 | |
631 | Float_t a_ar = 39.948; |
632 | Float_t z_ar = 18.; |
633 | |
634 | density = 0.001782; |
635 | |
636 | AliMaterial(21,"Ar",a_ar,z_ar,density,999.,999.); |
637 | |
638 | Float_t a_pure[2]; |
fe4da5cc |
639 | |
1283eee5 |
640 | a_pure[0] = a_ne; |
641 | a_pure[1] = a_ar; |
fe4da5cc |
642 | |
1283eee5 |
643 | |
644 | //-------------------------------------------------------------- |
645 | // gases - compounds |
646 | //-------------------------------------------------------------- |
647 | |
648 | Float_t amol[3]; |
649 | |
650 | // CO2 |
651 | |
652 | amat[0]=12.011; |
653 | amat[1]=15.9994; |
654 | |
655 | zmat[0]=6.; |
656 | zmat[1]=8.; |
657 | |
658 | wmat[0]=1.; |
659 | wmat[1]=2.; |
660 | |
661 | density=0.001977; |
662 | |
663 | amol[0] = amat[0]*wmat[0]+amat[1]*wmat[1]; |
664 | |
665 | AliMixture(10,"CO2",amat,zmat,density,-2,wmat); |
666 | |
667 | // CF4 |
668 | |
669 | amat[0]=12.011; |
670 | amat[1]=18.998; |
671 | |
672 | zmat[0]=6.; |
673 | zmat[1]=9.; |
674 | |
675 | wmat[0]=1.; |
676 | wmat[1]=4.; |
677 | |
678 | density=0.003034; |
679 | |
680 | amol[1] = amat[0]*wmat[0]+amat[1]*wmat[1]; |
681 | |
682 | AliMixture(11,"CF4",amat,zmat,density,-2,wmat); |
683 | |
684 | // CH4 |
685 | |
686 | amat[0]=12.011; |
687 | amat[1]=1.; |
688 | |
689 | zmat[0]=6.; |
690 | zmat[1]=1.; |
691 | |
692 | wmat[0]=1.; |
693 | wmat[1]=4.; |
694 | |
695 | density=0.000717; |
696 | |
697 | amol[2] = amat[0]*wmat[0]+amat[1]*wmat[1]; |
698 | |
699 | AliMixture(12,"CH4",amat,zmat,density,-2,wmat); |
700 | |
701 | //---------------------------------------------------------------- |
702 | // gases - mixtures, ID >= 20 pure gases, <= 10 ID < 20 -compounds |
703 | //---------------------------------------------------------------- |
704 | |
fe4da5cc |
705 | char namate[21]; |
1283eee5 |
706 | |
707 | density = 0.; |
708 | Float_t am=0; |
709 | Int_t nc; |
710 | |
711 | Float_t a,z,rho,absl,X0,buf[1]; |
712 | Int_t nbuf; |
713 | |
714 | for(nc = 0;nc<fNoComp;nc++) |
715 | { |
716 | |
717 | // retrive material constants |
718 | |
719 | gMC->Gfmate((*fIdmate)[fMixtComp[nc]],namate,a,z,rho,X0,absl,buf,nbuf); |
720 | |
721 | amat[nc] = a; |
722 | zmat[nc] = z; |
723 | |
724 | Int_t nnc = (fMixtComp[nc]>=20) ? fMixtComp[nc]%20 : fMixtComp[nc]%10; |
725 | |
726 | am += fMixtProp[nc]*((fMixtComp[nc]>=20) ? a_pure[nnc] : amol[nnc]); |
727 | density += fMixtProp[nc]*rho; // density of the mixture |
728 | |
729 | } |
730 | |
731 | // mixture proportions by weight! |
732 | |
733 | for(nc = 0;nc<fNoComp;nc++) |
734 | { |
735 | |
736 | Int_t nnc = (fMixtComp[nc]>=20) ? fMixtComp[nc]%20 : fMixtComp[nc]%10; |
737 | |
738 | wmat[nc] = fMixtProp[nc]*((fMixtComp[nc]>=20) ? a_pure[nnc] : amol[nnc])/am; |
739 | |
740 | } |
fe4da5cc |
741 | |
1283eee5 |
742 | AliMixture(31,"Drift gas 1",amat,zmat,density,fNoComp,wmat); |
743 | AliMixture(32,"Drift gas 2",amat,zmat,density,fNoComp,wmat); |
744 | AliMixture(33,"Drift gas 3",amat,zmat,density,fNoComp,wmat); |
745 | |
746 | AliMedium(2, "Drift gas 1", 31, 0, ISXFLD, SXMGMX, 10., 999.,.1, .001, .001); |
747 | AliMedium(3, "Drift gas 2", 32, 0, ISXFLD, SXMGMX, 10., 999.,.1, .001, .001); |
748 | AliMedium(4, "Drift gas 3", 33, 1, ISXFLD, SXMGMX, 10., 999.,.1, .001, .001); |
749 | |
750 | // Air |
751 | |
752 | AliMaterial(24, "Air", 14.61, 7.3, .001205, 30420., 67500.); |
753 | |
754 | AliMedium(24, "Air", 24, 0, ISXFLD, SXMGMX, 10., .1, .1, .1, .1); |
755 | |
756 | //---------------------------------------------------------------------- |
757 | // solid materials |
758 | //---------------------------------------------------------------------- |
759 | |
760 | // Al |
761 | |
762 | AliMaterial(30, "Al", 26.98, 13., 2.7, 8.9, 37.2); |
763 | |
764 | AliMedium(0, "Al",30, 0, ISXFLD, SXMGMX, 10., .1, .1, .1, .1); |
765 | |
766 | // Si |
767 | |
768 | AliMaterial(31, "Si", 28.086, 14.,2.33, 9.36, 999.); |
769 | |
770 | AliMedium(7, "Al",31, 0, ISXFLD, SXMGMX, 10., .1, .1, .1, .1); |
fe4da5cc |
771 | |
1283eee5 |
772 | |
773 | // Mylar C5H4O2 |
774 | |
775 | amat[0]=12.011; |
776 | amat[1]=1.; |
777 | amat[2]=15.9994; |
778 | |
779 | zmat[0]=6.; |
780 | zmat[1]=1.; |
781 | zmat[2]=8.; |
782 | |
783 | wmat[0]=5.; |
784 | wmat[1]=4.; |
785 | wmat[2]=2.; |
786 | |
787 | density = 1.39; |
fe4da5cc |
788 | |
1283eee5 |
789 | AliMixture(32, "Mylar",amat,zmat,density,-3,wmat); |
790 | |
791 | AliMedium(5, "Mylar",32, 0, ISXFLD, SXMGMX, 10., .1, .1, .001, .01); |
792 | |
793 | |
794 | |
795 | |
796 | // Carbon (normal) |
797 | |
798 | AliMaterial(33,"C normal",12.011,6.,2.265,18.8,999.); |
799 | |
800 | AliMedium(6,"C normal",33,0, ISXFLD, SXMGMX, 10., .1, .1, .001, .01); |
801 | |
802 | // G10 for inner and outr field cage |
803 | // G10 is 60% SiO2 + 40% epoxy, right now I use A and Z for SiO2 |
804 | |
805 | Float_t rhoFactor; |
806 | |
807 | amat[0]=28.086; |
808 | amat[1]=15.9994; |
809 | |
810 | zmat[0]=14.; |
811 | zmat[1]=8.; |
812 | |
813 | wmat[0]=1.; |
814 | wmat[1]=2.; |
815 | |
816 | density = 1.7; |
fe4da5cc |
817 | |
1283eee5 |
818 | |
819 | AliMixture(34,"G10 aux.",amat,zmat,density,-2,wmat); |
820 | |
821 | |
822 | gMC->Gfmate((*fIdmate)[34],namate,a,z,rho,X0,absl,buf,nbuf); |
823 | |
824 | Float_t thickX0 = 0.0052; // field cage in X0 units |
fe4da5cc |
825 | |
1283eee5 |
826 | Float_t thick = 2.; // in cm |
827 | |
828 | X0=19.4; // G10 |
829 | |
830 | rhoFactor = X0*thickX0/thick; |
831 | density = rho*rhoFactor; |
832 | |
833 | AliMaterial(35,"G10-fc",a,z,density,999.,999.); |
834 | |
835 | AliMedium(8,"G10-fc",35,0, ISXFLD, SXMGMX, 10., .1, .1, .001, .01); |
836 | |
837 | thickX0 = 0.0027; // inner vessel (eta <0.9) |
838 | thick=0.5; |
839 | rhoFactor = X0*thickX0/thick; |
840 | density = rho*rhoFactor; |
841 | |
842 | AliMaterial(36,"G10-iv",a,z,density,999.,999.); |
843 | |
844 | AliMedium(9,"G10-iv",36,0, ISXFLD, SXMGMX, 10., .1, .1, .001, .01); |
845 | |
846 | // Carbon fibre |
fe4da5cc |
847 | |
1283eee5 |
848 | gMC->Gfmate((*fIdmate)[33],namate,a,z,rho,X0,absl,buf,nbuf); |
849 | |
850 | thickX0 = 0.0133; // outer vessel |
851 | thick=3.0; |
852 | rhoFactor = X0*thickX0/thick; |
853 | density = rho*rhoFactor; |
854 | |
855 | |
856 | AliMaterial(37,"C-ov",a,z,density,999.,999.); |
857 | |
858 | AliMedium(10,"C-ov",37,0, ISXFLD, SXMGMX, 10., .1, .1, .001, .01); |
859 | |
860 | thickX0=0.015; // inner vessel (cone, eta > 0.9) |
861 | thick=1.5; |
862 | rhoFactor = X0*thickX0/thick; |
863 | density = rho*rhoFactor; |
864 | |
865 | AliMaterial(38,"C-ivc",a,z,density,999.,999.); |
866 | |
867 | AliMedium(11,"C-ivc",38,0, ISXFLD, SXMGMX, 10., .1, .1, .001, .01); |
868 | |
869 | // |
870 | |
871 | AliMedium(12,"CO2",10,0, ISXFLD, SXMGMX, 10., 999.,.1, .001, .001); |
872 | |
873 | |
874 | |
fe4da5cc |
875 | } |
876 | |
877 | //_____________________________________________________________________________ |
878 | struct Bin { |
879 | const AliTPCdigit *dig; |
880 | int idx; |
881 | Bin() {dig=0; idx=-1;} |
882 | }; |
883 | |
884 | struct PreCluster : public AliTPCcluster { |
3c0f9266 |
885 | const AliTPCdigit* summit; //pointer to the maximum digit of this precluster |
886 | int idx; //index in AliTPC::fClusters |
887 | int npeaks; //number of peaks in this precluster |
888 | int ndigits; //number of digits in this precluster |
889 | PreCluster(); |
fe4da5cc |
890 | }; |
3c0f9266 |
891 | PreCluster::PreCluster() : AliTPCcluster() {npeaks=ndigits=0;} |
fe4da5cc |
892 | |
893 | //_____________________________________________________________________________ |
3c0f9266 |
894 | static void FindPreCluster(int i,int j,int maxj,Bin *bins,PreCluster &c) |
fe4da5cc |
895 | { |
3c0f9266 |
896 | //----------------------------------------------------------------- |
897 | // This function looks for "preclusters". |
fe4da5cc |
898 | // |
3c0f9266 |
899 | // Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch |
900 | //----------------------------------------------------------------- |
901 | Bin& b=bins[i*maxj+j]; |
902 | double q=(double)TMath::Abs(b.dig->fSignal); |
8c555625 |
903 | |
fe4da5cc |
904 | if (b.idx >= 0 && b.idx != c.idx) { |
905 | c.idx=b.idx; |
906 | c.npeaks++; |
907 | } |
908 | |
909 | if (q > TMath::Abs(c.summit->fSignal)) c.summit=b.dig; |
910 | |
911 | c.fY += i*q; |
912 | c.fZ += j*q; |
913 | c.fSigmaY2 += i*i*q; |
914 | c.fSigmaZ2 += j*j*q; |
915 | c.fQ += q; |
3c0f9266 |
916 | c.ndigits++; |
8c555625 |
917 | |
fe4da5cc |
918 | b.dig = 0; b.idx = c.idx; |
919 | |
3c0f9266 |
920 | if (bins[(i-1)*maxj+j].dig) FindPreCluster(i-1,j,maxj,bins,c); |
921 | if (bins[i*maxj+(j-1)].dig) FindPreCluster(i,j-1,maxj,bins,c); |
922 | if (bins[(i+1)*maxj+j].dig) FindPreCluster(i+1,j,maxj,bins,c); |
923 | if (bins[i*maxj+(j+1)].dig) FindPreCluster(i,j+1,maxj,bins,c); |
fe4da5cc |
924 | |
925 | } |
926 | |
927 | //_____________________________________________________________________________ |
928 | void AliTPC::Digits2Clusters() |
929 | { |
3c0f9266 |
930 | //----------------------------------------------------------------- |
931 | // This is a simple cluster finder. |
fe4da5cc |
932 | // |
3c0f9266 |
933 | // Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch |
934 | //----------------------------------------------------------------- |
935 | AliTPCParam *par = &(fDigParam->GetParam()); |
8c555625 |
936 | |
3c0f9266 |
937 | int inp=par->GetNPads(0, par->GetNRowLow()-1); |
938 | int onp=par->GetNPads(par->GetNSector()-1,par->GetNRowUp() -1); |
939 | const int MAXY=(inp>onp) ? inp+2 : onp+2; |
940 | const int MAXTBKT=int((z_end+6*par->GetZSigma())/par->GetZWidth())+1; |
941 | const int MAXZ=MAXTBKT+2; |
942 | const int THRESHOLD=20; |
fe4da5cc |
943 | |
8c555625 |
944 | TTree *t=(TTree*)gDirectory->Get("TreeD0_Param1"); |
945 | t->GetBranch("Digits")->SetAddress(&fDigits); |
fe4da5cc |
946 | Int_t sectors_by_rows=(Int_t)t->GetEntries(); |
947 | |
948 | int ncls=0; |
949 | |
950 | for (Int_t n=0; n<sectors_by_rows; n++) { |
951 | if (!t->GetEvent(n)) continue; |
3c0f9266 |
952 | Bin *bins=new Bin[MAXY*MAXZ]; |
fe4da5cc |
953 | AliTPCdigit *dig=(AliTPCdigit*)fDigits->UncheckedAt(0); |
3c0f9266 |
954 | int sec=dig->fSector, row=dig->fPadRow; |
955 | int ndigits=fDigits->GetEntriesFast(); |
fe4da5cc |
956 | |
3c0f9266 |
957 | int npads, sign; |
958 | { |
959 | int nis=par->GetNInnerSector(), nos=par->GetNOuterSector(); |
960 | if (sec < nis) { |
961 | npads = par->GetNPadsLow(row); |
962 | sign = (sec < nis/2) ? 1 : -1; |
963 | } else { |
964 | npads = par->GetNPadsUp(row); |
965 | sign = ((sec-nis) < nos/2) ? 1 : -1; |
966 | } |
fe4da5cc |
967 | } |
3c0f9266 |
968 | |
fe4da5cc |
969 | int ndig; |
970 | for (ndig=0; ndig<ndigits; ndig++) { |
971 | dig=(AliTPCdigit*)fDigits->UncheckedAt(ndig); |
3c0f9266 |
972 | int i=dig->fPad+1, j=dig->fTime+1; |
973 | if (i > npads) { |
974 | cerr<<"AliTPC::Digits2Clusters error: pad number is out of range ! "; |
975 | cerr<<i<<' '<<npads<<endl; |
976 | continue; |
977 | } |
978 | if (j > MAXTBKT) { |
979 | cerr<<"AliTPC::Digits2Clusters error: time bucket is out of range ! "; |
980 | cerr<<j<<' '<<MAXTBKT<<endl; |
981 | continue; |
982 | } |
983 | if (dig->fSignal >= THRESHOLD) bins[i*MAXZ+j].dig=dig; |
984 | if (i==1 || i==npads || j==1 || j==MAXTBKT) dig->fSignal*=-1; |
fe4da5cc |
985 | } |
3c0f9266 |
986 | |
fe4da5cc |
987 | int ncl=0; |
988 | int i,j; |
8c555625 |
989 | |
3c0f9266 |
990 | for (i=1; i<MAXY-1; i++) { |
991 | for (j=1; j<MAXZ-1; j++) { |
992 | if (bins[i*MAXZ+j].dig == 0) continue; |
993 | PreCluster c; c.summit=bins[i*MAXZ+j].dig; c.idx=ncls; |
994 | FindPreCluster(i, j, MAXZ, bins, c); |
fe4da5cc |
995 | c.fY /= c.fQ; |
996 | c.fZ /= c.fQ; |
8c555625 |
997 | |
998 | double s2 = c.fSigmaY2/c.fQ - c.fY*c.fY; |
999 | c.fSigmaY2 = s2 + 1./12.; |
3c0f9266 |
1000 | c.fSigmaY2 *= par->GetPadPitchWidth()*par->GetPadPitchWidth(); |
1001 | if (s2 != 0.) c.fSigmaY2 *= 0.17; |
8c555625 |
1002 | |
1003 | s2 = c.fSigmaZ2/c.fQ - c.fZ*c.fZ; |
1004 | c.fSigmaZ2 = s2 + 1./12.; |
3c0f9266 |
1005 | c.fSigmaZ2 *= par->GetZWidth()*par->GetZWidth(); |
1006 | if (s2 != 0.) c.fSigmaZ2 *= 0.41; |
1007 | |
1008 | c.fY = (c.fY - 0.5 - 0.5*npads)*par->GetPadPitchWidth(); |
1009 | c.fZ = par->GetZWidth()*c.fZ; |
1010 | c.fZ -= 3.*par->GetZSigma(); // PASA delay |
1011 | c.fZ = sign*(z_end - c.fZ); |
1012 | |
1013 | c.fSector=sec; |
1014 | c.fPadRow=row; |
fe4da5cc |
1015 | c.fTracks[0]=c.summit->fTracks[0]; |
1016 | c.fTracks[1]=c.summit->fTracks[1]; |
1017 | c.fTracks[2]=c.summit->fTracks[2]; |
8c555625 |
1018 | |
3c0f9266 |
1019 | if (c.summit->fSignal<0) { |
fe4da5cc |
1020 | c.fSigmaY2 *= 25.; |
1021 | c.fSigmaZ2 *= 4.; |
1022 | } |
1023 | |
1024 | AddCluster(c); ncls++; ncl++; |
1025 | } |
1026 | } |
3c0f9266 |
1027 | |
fe4da5cc |
1028 | for (ndig=0; ndig<ndigits; ndig++) { |
1029 | dig=(AliTPCdigit*)fDigits->UncheckedAt(ndig); |
3c0f9266 |
1030 | int i=dig->fPad+1, j=dig->fTime+1; |
1031 | if (i > npads) { |
1032 | cerr<<"AliTPC::Digits2Clusters error: pad number is out of range ! "; |
1033 | cerr<<i<<' '<<npads<<endl; |
1034 | continue; |
1035 | } |
1036 | if (j > MAXTBKT) { |
1037 | cerr<<"AliTPC::Digits2Clusters error: time bucket is out of range ! "; |
1038 | cerr<<j<<' '<<MAXTBKT<<endl; |
1039 | continue; |
1040 | } |
1041 | if (TMath::Abs(dig->fSignal)>=par->GetZeroSup()) bins[i*MAXZ+j].dig=dig; |
fe4da5cc |
1042 | } |
1043 | |
3c0f9266 |
1044 | for (i=1; i<MAXY-1; i++) { |
1045 | for (j=1; j<MAXZ-1; j++) { |
1046 | if (bins[i*MAXZ+j].dig == 0) continue; |
1047 | PreCluster c; c.summit=bins[i*MAXZ+j].dig; c.idx=ncls; |
1048 | FindPreCluster(i, j, MAXZ, bins, c); |
1049 | if (c.ndigits < 2) continue; //noise cluster |
8c555625 |
1050 | if (c.npeaks>1) continue; //overlapped cluster |
fe4da5cc |
1051 | c.fY /= c.fQ; |
1052 | c.fZ /= c.fQ; |
8c555625 |
1053 | |
1054 | double s2 = c.fSigmaY2/c.fQ - c.fY*c.fY; |
1055 | c.fSigmaY2 = s2 + 1./12.; |
3c0f9266 |
1056 | c.fSigmaY2 *= par->GetPadPitchWidth()*par->GetPadPitchWidth(); |
1057 | if (s2 != 0.) c.fSigmaY2 *= 0.04; |
8c555625 |
1058 | |
1059 | s2 = c.fSigmaZ2/c.fQ - c.fZ*c.fZ; |
1060 | c.fSigmaZ2 = s2 + 1./12.; |
3c0f9266 |
1061 | c.fSigmaZ2 *= par->GetZWidth()*par->GetZWidth(); |
1062 | if (s2 != 0.) c.fSigmaZ2 *= 0.10; |
1063 | |
1064 | c.fY = (c.fY - 0.5 - 0.5*npads)*par->GetPadPitchWidth(); |
1065 | c.fZ = par->GetZWidth()*c.fZ; |
1066 | c.fZ -= 3.*par->GetZSigma(); // PASA delay |
1067 | c.fZ = sign*(z_end - c.fZ); |
1068 | |
1069 | c.fSector=sec; |
1070 | c.fPadRow=row; |
fe4da5cc |
1071 | c.fTracks[0]=c.summit->fTracks[0]; |
1072 | c.fTracks[1]=c.summit->fTracks[1]; |
1073 | c.fTracks[2]=c.summit->fTracks[2]; |
1074 | |
3c0f9266 |
1075 | if (c.summit->fSignal<0) { |
fe4da5cc |
1076 | c.fSigmaY2 *= 25.; |
1077 | c.fSigmaZ2 *= 4.; |
1078 | } |
3c0f9266 |
1079 | |
fe4da5cc |
1080 | if (c.npeaks==0) {AddCluster(c); ncls++; ncl++;} |
1081 | else { |
1082 | new ((*fClusters)[c.idx]) AliTPCcluster(c); |
1083 | } |
1084 | } |
1085 | } |
1086 | |
1087 | cerr<<"sector, row, digits, clusters: " |
3c0f9266 |
1088 | <<sec<<' '<<row<<' '<<ndigits<<' '<<ncl<<" \r"; |
fe4da5cc |
1089 | |
1090 | fDigits->Clear(); |
3c0f9266 |
1091 | |
1092 | delete[] bins; |
fe4da5cc |
1093 | } |
1094 | } |
1095 | |
1096 | //_____________________________________________________________________________ |
1097 | void AliTPC::ElDiff(Float_t *xyz) |
1098 | { |
8c555625 |
1099 | //-------------------------------------------------- |
fe4da5cc |
1100 | // calculates the diffusion of a single electron |
8c555625 |
1101 | //-------------------------------------------------- |
1102 | |
1103 | //----------------------------------------------------------------- |
1104 | // Origin: Marek Kowalski IFJ, Krakow, Marek.Kowalski@ifj.edu.pl |
1105 | //----------------------------------------------------------------- |
1106 | AliTPCParam * fTPCParam = &(fDigParam->GetParam()); |
fe4da5cc |
1107 | Float_t driftl; |
8c555625 |
1108 | |
fe4da5cc |
1109 | Float_t z0=xyz[2]; |
8c555625 |
1110 | |
fe4da5cc |
1111 | driftl=z_end-TMath::Abs(xyz[2]); |
8c555625 |
1112 | |
fe4da5cc |
1113 | if(driftl<0.01) driftl=0.01; |
8c555625 |
1114 | |
1115 | // check the attachment |
1116 | |
fe4da5cc |
1117 | driftl=TMath::Sqrt(driftl); |
8c555625 |
1118 | |
1119 | // Float_t sig_t = driftl*diff_t; |
1120 | //Float_t sig_l = driftl*diff_l; |
1121 | Float_t sig_t = driftl*fTPCParam->GetDiffT(); |
1122 | Float_t sig_l = driftl*fTPCParam->GetDiffL(); |
fe4da5cc |
1123 | xyz[0]=gRandom->Gaus(xyz[0],sig_t); |
1124 | xyz[1]=gRandom->Gaus(xyz[1],sig_t); |
1125 | xyz[2]=gRandom->Gaus(xyz[2],sig_l); |
8c555625 |
1126 | |
fe4da5cc |
1127 | if (TMath::Abs(xyz[2])>z_end){ |
8c555625 |
1128 | xyz[2]=TMath::Sign(z_end,z0); |
fe4da5cc |
1129 | } |
1130 | if(xyz[2]*z0 < 0.){ |
8c555625 |
1131 | Float_t eps = 0.0001; |
1132 | xyz[2]=TMath::Sign(eps,z0); |
fe4da5cc |
1133 | } |
1134 | } |
1135 | |
1136 | //_____________________________________________________________________________ |
1137 | void AliTPC::Hits2Clusters() |
1138 | { |
8c555625 |
1139 | //-------------------------------------------------------- |
fe4da5cc |
1140 | // TPC simple cluster generator from hits |
1141 | // obtained from the TPC Fast Simulator |
8c555625 |
1142 | // The point errors are taken from the parametrization |
1143 | //-------------------------------------------------------- |
1144 | |
1145 | //----------------------------------------------------------------- |
1146 | // Origin: Marek Kowalski IFJ, Krakow, Marek.Kowalski@ifj.edu.pl |
1147 | //----------------------------------------------------------------- |
3c0f9266 |
1148 | |
8c555625 |
1149 | AliTPCParam * fTPCParam = &(fDigParam->GetParam()); |
fe4da5cc |
1150 | Float_t sigma_rphi,sigma_z,cl_rphi,cl_z; |
1151 | // |
1578254f |
1152 | TParticle *particle; // pointer to a given particle |
fe4da5cc |
1153 | AliTPChit *tpcHit; // pointer to a sigle TPC hit |
1154 | TClonesArray *Particles; //pointer to the particle list |
1155 | Int_t sector,nhits; |
1156 | Int_t ipart; |
1157 | Float_t xyz[5]; |
1158 | Float_t pl,pt,tanth,rpad,ratio; |
fe4da5cc |
1159 | Float_t cph,sph; |
1160 | |
1161 | //--------------------------------------------------------------- |
1162 | // Get the access to the tracks |
1163 | //--------------------------------------------------------------- |
1164 | |
1165 | TTree *TH = gAlice->TreeH(); |
1166 | Stat_t ntracks = TH->GetEntries(); |
3c0f9266 |
1167 | Particles=gAlice->Particles(); |
fe4da5cc |
1168 | |
1169 | //------------------------------------------------------------ |
1170 | // Loop over all sectors (72 sectors) |
3c0f9266 |
1171 | // Sectors 0-35 are lower sectors, 0-17 z>0, 18-35 z<0 |
1172 | // Sectors 36-71 are upper sectors, 36-53 z>0, 54-71 z<0 |
fe4da5cc |
1173 | // |
3c0f9266 |
1174 | // First cluster for sector 0 starts at "0" |
fe4da5cc |
1175 | //------------------------------------------------------------ |
1176 | |
1177 | |
3c0f9266 |
1178 | //fClustersIndex[0] = 0; |
fe4da5cc |
1179 | |
1180 | // |
3c0f9266 |
1181 | int Nsectors=fDigParam->GetParam().GetNSector(); |
1182 | for(Int_t isec=0; isec<Nsectors; isec++){ |
8c555625 |
1183 | //MI change |
1184 | fTPCParam->AdjustAngles(isec,cph,sph); |
fe4da5cc |
1185 | |
1186 | //------------------------------------------------------------ |
1187 | // Loop over tracks |
1188 | //------------------------------------------------------------ |
1189 | |
1190 | for(Int_t track=0;track<ntracks;track++){ |
1191 | ResetHits(); |
1192 | TH->GetEvent(track); |
1193 | // |
1194 | // Get number of the TPC hits and a pointer |
1195 | // to the particles |
1196 | // |
1197 | nhits=fHits->GetEntriesFast(); |
fe4da5cc |
1198 | // |
1199 | // Loop over hits |
1200 | // |
1201 | for(Int_t hit=0;hit<nhits;hit++){ |
1202 | tpcHit=(AliTPChit*)fHits->UncheckedAt(hit); |
1203 | sector=tpcHit->fSector; // sector number |
1204 | if(sector != isec) continue; //terminate iteration |
1205 | ipart=tpcHit->fTrack; |
1578254f |
1206 | particle=(TParticle*)Particles->UncheckedAt(ipart); |
1207 | pl=particle->Pz(); |
1208 | pt=particle->Pt(); |
fe4da5cc |
1209 | if(pt < 1.e-9) pt=1.e-9; |
1210 | tanth=pl/pt; |
1211 | tanth = TMath::Abs(tanth); |
1212 | rpad=TMath::Sqrt(tpcHit->fX*tpcHit->fX + tpcHit->fY*tpcHit->fY); |
1213 | ratio=0.001*rpad/pt; // pt must be in MeV/c - historical reason |
1214 | |
1215 | // space-point resolutions |
1216 | |
1217 | sigma_rphi=SigmaY2(rpad,tanth,pt); |
1218 | sigma_z =SigmaZ2(rpad,tanth ); |
1219 | |
1220 | // cluster widths |
1221 | |
1222 | cl_rphi=ac_rphi-bc_rphi*rpad*tanth+cc_rphi*ratio*ratio; |
1223 | cl_z=ac_z-bc_z*rpad*tanth+cc_z*tanth*tanth; |
1224 | |
1225 | // temporary protection |
1226 | |
1227 | if(sigma_rphi < 0.) sigma_rphi=0.4e-3; |
1228 | if(sigma_z < 0.) sigma_z=0.4e-3; |
1229 | if(cl_rphi < 0.) cl_rphi=2.5e-3; |
1230 | if(cl_z < 0.) cl_z=2.5e-5; |
1231 | |
1232 | // |
3c0f9266 |
1233 | // smearing --> rotate sectors firstly, |
fe4da5cc |
1234 | // then the inaccuracy in a X-Y plane is only along Y (pad row)! |
1235 | // |
1236 | Float_t xprim= tpcHit->fX*cph + tpcHit->fY*sph; |
1237 | Float_t yprim=-tpcHit->fX*sph + tpcHit->fY*cph; |
1238 | xyz[0]=gRandom->Gaus(yprim,TMath::Sqrt(sigma_rphi)); // y |
3c0f9266 |
1239 | Double_t alpha=(sector < fTPCParam->GetNInnerSector()) ? |
1240 | fTPCParam->GetInnerAngle() : fTPCParam->GetOuterAngle(); |
8c555625 |
1241 | if (TMath::Abs(xyz[0]/xprim) > TMath::Tan(0.5*alpha)) xyz[0]=yprim; |
fe4da5cc |
1242 | xyz[1]=gRandom->Gaus(tpcHit->fZ,TMath::Sqrt(sigma_z)); // z |
8c555625 |
1243 | if (TMath::Abs(xyz[1]) > 250) xyz[1]=tpcHit->fZ; |
3c0f9266 |
1244 | xyz[2]=tpcHit->fQ+1;// q; let it be not equal to zero (Y.Belikov) |
fe4da5cc |
1245 | xyz[3]=sigma_rphi; // fSigmaY2 |
1246 | xyz[4]=sigma_z; // fSigmaZ2 |
1283eee5 |
1247 | |
fe4da5cc |
1248 | // and finally add the cluster |
1283eee5 |
1249 | Int_t tracks[5]={tpcHit->fTrack, -1, -1, sector, tpcHit->fPadRow}; |
fe4da5cc |
1250 | AddCluster(xyz,tracks); |
1251 | |
1252 | } // end of loop over hits |
1253 | } // end of loop over tracks |
1254 | |
3c0f9266 |
1255 | //fClustersIndex[isec] = fNclusters; // update clusters index |
fe4da5cc |
1256 | |
1257 | } // end of loop over sectors |
1258 | |
3c0f9266 |
1259 | //fClustersIndex[fNsectors]--; // set end of the clusters buffer |
fe4da5cc |
1260 | |
1261 | } |
1262 | |
8c555625 |
1263 | |
1264 | void AliTPC::Hits2Digits() |
1265 | { |
1266 | |
1267 | //---------------------------------------------------- |
1268 | // Loop over all sectors (72 sectors) |
3c0f9266 |
1269 | // Sectors 0-35 are lower sectors, 0-17 z>0, 18-35 z<0 |
1270 | // Sectors 36-71 are upper sectors, 36-53 z>0, 54-71 z<0 |
8c555625 |
1271 | //---- |
3c0f9266 |
1272 | int Nsectors=fDigParam->GetParam().GetNSector(); |
1273 | for(Int_t isec=0;isec<Nsectors;isec++) Hits2DigitsSector(isec); |
8c555625 |
1274 | } |
1275 | |
1276 | |
fe4da5cc |
1277 | //_____________________________________________________________________________ |
8c555625 |
1278 | void AliTPC::Hits2DigitsSector(Int_t isec) |
fe4da5cc |
1279 | { |
8c555625 |
1280 | //------------------------------------------------------------------- |
fe4da5cc |
1281 | // TPC conversion from hits to digits. |
8c555625 |
1282 | //------------------------------------------------------------------- |
1283 | |
1284 | //----------------------------------------------------------------- |
1285 | // Origin: Marek Kowalski IFJ, Krakow, Marek.Kowalski@ifj.edu.pl |
1286 | //----------------------------------------------------------------- |
1287 | |
fe4da5cc |
1288 | //------------------------------------------------------- |
8c555625 |
1289 | // Get the access to the track hits |
fe4da5cc |
1290 | //------------------------------------------------------- |
8c555625 |
1291 | |
1292 | AliTPCParam * fTPCParam = &(fDigParam->GetParam()); |
1293 | TTree *TH = gAlice->TreeH(); // pointer to the hits tree |
fe4da5cc |
1294 | Stat_t ntracks = TH->GetEntries(); |
8c555625 |
1295 | |
1296 | if( ntracks > 0){ |
1297 | |
1298 | //------------------------------------------- |
1299 | // Only if there are any tracks... |
1300 | //------------------------------------------- |
1301 | |
fe4da5cc |
1302 | |
8c555625 |
1303 | // TObjArrays for three neighouring pad-rows |
1304 | |
1305 | TObjArray **rowTriplet = new TObjArray* [3]; |
fe4da5cc |
1306 | |
8c555625 |
1307 | // TObjArray-s for each pad-row |
1308 | |
1309 | TObjArray **row; |
1310 | |
1311 | for (Int_t trip=0;trip<3;trip++){ |
1312 | rowTriplet[trip]=new TObjArray; |
fe4da5cc |
1313 | } |
8c555625 |
1314 | |
1315 | |
fe4da5cc |
1316 | |
8c555625 |
1317 | printf("*** Processing sector number %d ***\n",isec); |
1318 | |
1319 | Int_t nrows =fTPCParam->GetNRow(isec); |
1320 | |
1321 | row= new TObjArray* [nrows]; |
fe4da5cc |
1322 | |
8c555625 |
1323 | MakeSector(isec,nrows,TH,ntracks,row); |
1324 | |
1325 | //-------------------------------------------------------- |
1326 | // Digitize this sector, row by row |
1327 | // row[i] is the pointer to the TObjArray of TVectors, |
1328 | // each one containing electrons accepted on this |
1329 | // row, assigned into tracks |
1330 | //-------------------------------------------------------- |
1331 | |
1332 | Int_t i; |
1333 | |
1334 | for (i=0;i<nrows;i++){ |
1335 | |
1336 | // Triplets for i = 0 and i=1 are identical! |
1337 | // The same for i = nrows-1 and nrows! |
1338 | |
1339 | if(i != 1 && i != nrows-1){ |
1340 | MakeTriplet(i,rowTriplet,row); |
1341 | } |
1342 | |
1343 | DigitizeRow(i,isec,rowTriplet); |
1344 | |
1345 | fDigParam->Fill(); |
1346 | |
1347 | Int_t ndig=fDigParam->GetArray()->GetEntriesFast(); |
1348 | |
1349 | printf("*** Sector, row, digits %d %d %d ***\n",isec,i,ndig); |
1350 | |
1351 | ResetDigits(); // reset digits for this row after storing them |
1352 | |
1353 | } // end of the sector digitization |
1354 | |
1355 | // delete the last triplet |
1356 | |
1357 | for (i=0;i<3;i++) rowTriplet[i]->Delete(); |
1358 | |
1359 | delete [] row; // delete the array of pointers to TObjArray-s |
1360 | |
1361 | } // ntracks >0 |
1362 | } // end of Hits2Digits |
1363 | //_____________________________________________________________________________ |
1364 | void AliTPC::MakeTriplet(Int_t row, |
1365 | TObjArray **rowTriplet, TObjArray **prow) |
1366 | { |
1367 | //------------------------------------------------------------------ |
1368 | // Makes the "triplet" of the neighbouring pad-row for the |
1369 | // digitization including the cross-talk between the pad-rows |
1370 | //------------------------------------------------------------------ |
1371 | |
1372 | //----------------------------------------------------------------- |
1373 | // Origin: Marek Kowalski IFJ, Krakow, Marek.Kowalski@ifj.edu.pl |
1374 | //----------------------------------------------------------------- |
1375 | |
1376 | AliTPCParam * fTPCParam = &(fDigParam->GetParam()); |
1377 | Float_t gasgain = fTPCParam->GetGasGain(); |
1378 | Int_t nTracks[3]; |
1379 | |
1380 | Int_t nElements,nElectrons; |
1381 | |
1382 | TVector *pv; |
1383 | TVector *tv; |
1384 | |
1385 | //------------------------------------------------------------------- |
1386 | // pv is an "old" track, i.e. label + triplets of (x,y,z) |
1387 | // for each electron |
1388 | // |
1389 | //------------------------------------------------------------------- |
1390 | |
1391 | |
1392 | Int_t i1,i2; |
1393 | Int_t nel,nt; |
1394 | |
1395 | if(row == 0 || row == 1){ |
1396 | |
1397 | // create entire triplet for the first AND the second row |
1398 | |
1399 | nTracks[0] = prow[0]->GetEntries(); |
1400 | nTracks[1] = prow[1]->GetEntries(); |
1401 | nTracks[2] = prow[2]->GetEntries(); |
1402 | |
1403 | for(i1=0;i1<3;i1++){ |
1404 | nt = nTracks[i1]; // number of tracks for this row |
1405 | |
1406 | for(i2=0;i2<nt;i2++){ |
1407 | pv = (TVector*)prow[i1]->At(i2); |
1408 | TVector &v1 = *pv; |
1409 | nElements = pv->GetNrows(); |
1410 | nElectrons = (nElements-1)/3; |
1411 | |
1412 | tv = new TVector(4*nElectrons+1); // create TVector for a modified track |
1413 | TVector &v2 = *tv; |
1414 | v2(0)=v1(0); //track label |
1415 | |
1416 | for(nel=0;nel<nElectrons;nel++){ |
1417 | Int_t idx1 = nel*3; |
1418 | Int_t idx2 = nel*4; |
1419 | // Avalanche, including fluctuations |
1420 | Int_t aval = (Int_t) (-gasgain*TMath::Log(gRandom->Rndm())); |
1421 | v2(idx2+1)= v1(idx1+1); |
1422 | v2(idx2+2)= v1(idx1+2); |
1423 | v2(idx2+3)= v1(idx1+3); |
1424 | v2(idx2+4)= (Float_t)aval; // in number of electrons! |
1425 | } // end of loop over electrons |
1426 | // |
1427 | // Add this track to a row |
1428 | // |
1429 | |
1430 | rowTriplet[i1]->Add(tv); |
1431 | |
1432 | |
1433 | } // end of loop over tracks for this row |
1434 | |
1435 | prow[i1]->Delete(); // remove "old" tracks |
1436 | delete prow[i1]; // delete TObjArray for this row |
1437 | prow[i1]=0; // set pointer to NULL |
1438 | |
1439 | } // end of loop over row triplets |
1440 | |
1441 | |
1442 | } |
1443 | else{ |
1444 | |
1445 | rowTriplet[0]->Delete(); // remove old lower row |
1446 | |
1447 | nTracks[0]=rowTriplet[1]->GetEntries(); // previous middle row |
1448 | nTracks[1]=rowTriplet[2]->GetEntries(); // previous upper row |
1449 | nTracks[2]=prow[row+1]->GetEntries(); // next row |
1450 | |
1451 | |
1452 | //------------------------------------------- |
1453 | // shift new tracks downwards |
1454 | //------------------------------------------- |
1455 | |
1456 | for(i1=0;i1<nTracks[0];i1++){ |
1457 | pv=(TVector*)rowTriplet[1]->At(i1); |
1458 | rowTriplet[0]->Add(pv); |
1459 | } |
1460 | |
1461 | rowTriplet[1]->Clear(); // leave tracks on the heap!!! |
1462 | |
1463 | for(i1=0;i1<nTracks[1];i1++){ |
1464 | pv=(TVector*)rowTriplet[2]->At(i1); |
1465 | rowTriplet[1]->Add(pv); |
1466 | } |
1467 | |
1468 | rowTriplet[2]->Clear(); // leave tracks on the heap!!! |
1469 | |
1470 | //--------------------------------------------- |
1471 | // Create new upper row |
1472 | //--------------------------------------------- |
1473 | |
1474 | |
1475 | |
1476 | for(i1=0;i1<nTracks[2];i1++){ |
1477 | pv = (TVector*)prow[row+1]->At(i1); |
1478 | TVector &v1 = *pv; |
1479 | nElements = pv->GetNrows(); |
1480 | nElectrons = (nElements-1)/3; |
1481 | |
1482 | tv = new TVector(4*nElectrons+1); // create TVector for a modified track |
1483 | TVector &v2 = *tv; |
1484 | v2(0)=v1(0); //track label |
1485 | |
1486 | for(nel=0;nel<nElectrons;nel++){ |
1487 | |
1488 | Int_t idx1 = nel*3; |
1489 | Int_t idx2 = nel*4; |
1490 | // Avalanche, including fluctuations |
1491 | Int_t aval = (Int_t) |
1492 | (-gasgain*TMath::Log(gRandom->Rndm())); |
1493 | |
1494 | v2(idx2+1)= v1(idx1+1); |
1495 | v2(idx2+2)= v1(idx1+2); |
1496 | v2(idx2+3)= v1(idx1+3); |
1497 | v2(idx2+4)= (Float_t)aval; // in number of electrons! |
1498 | } // end of loop over electrons |
1499 | |
1500 | rowTriplet[2]->Add(tv); |
1501 | |
1502 | } // end of loop over tracks |
1503 | |
1504 | prow[row+1]->Delete(); // delete tracks for this row |
1505 | delete prow[row+1]; // delete TObjArray for this row |
1506 | prow[row+1]=0; // set a pointer to NULL |
1507 | |
1508 | } |
1509 | |
1510 | } // end of MakeTriplet |
1511 | //_____________________________________________________________________________ |
1512 | void AliTPC::ExB(Float_t *xyz) |
1513 | { |
1514 | //------------------------------------------------ |
1515 | // ExB at the wires and wire number calulation |
1516 | //------------------------------------------------ |
1517 | |
1518 | //----------------------------------------------------------------- |
1519 | // Origin: Marek Kowalski IFJ, Krakow, Marek.Kowalski@ifj.edu.pl |
1520 | //----------------------------------------------------------------- |
1521 | AliTPCParam * fTPCParam = &(fDigParam->GetParam()); |
1522 | |
1523 | Float_t x1=xyz[0]; |
1524 | fTPCParam->GetWire(x1); //calculate nearest wire position |
1525 | Float_t dx=xyz[0]-x1; |
1526 | xyz[1]+=dx*fTPCParam->GetOmegaTau(); |
1527 | |
1528 | } // end of ExB |
1529 | //_____________________________________________________________________________ |
1530 | void AliTPC::DigitizeRow(Int_t irow,Int_t isec,TObjArray **rowTriplet) |
1531 | { |
1532 | //----------------------------------------------------------- |
1533 | // Single row digitization, coupling from the neighbouring |
1534 | // rows taken into account |
1535 | //----------------------------------------------------------- |
1536 | |
1537 | //----------------------------------------------------------------- |
1538 | // Origin: Marek Kowalski IFJ, Krakow, Marek.Kowalski@ifj.edu.pl |
1539 | //----------------------------------------------------------------- |
1540 | |
1541 | |
1542 | AliTPCParam * fTPCParam = &(fDigParam->GetParam()); |
1543 | Float_t chipgain= fTPCParam->GetChipGain(); |
1544 | Float_t zerosup = fTPCParam->GetZeroSup(); |
1545 | Int_t nrows =fTPCParam->GetNRow(isec); |
3c0f9266 |
1546 | const int MAXTBKT= |
1547 | int((z_end+6*fTPCParam->GetZSigma())/fTPCParam->GetZWidth())+1; |
8c555625 |
1548 | |
1549 | Int_t nTracks[3]; |
1550 | Int_t n_of_pads[3]; |
1551 | Int_t IndexRange[4]; |
1552 | Int_t i1; |
1553 | Int_t iFlag; |
1554 | |
1555 | // |
1556 | // iFlag = 0 -> inner row, iFlag = 1 -> the middle one, iFlag = 2 -> the outer one |
1557 | // |
1558 | |
1559 | nTracks[0]=rowTriplet[0]->GetEntries(); // lower row |
1560 | nTracks[1]=rowTriplet[1]->GetEntries(); // middle row |
1561 | nTracks[2]=rowTriplet[2]->GetEntries(); // upper row |
1562 | |
1563 | |
1564 | if(irow == 0){ |
1565 | iFlag=0; |
1566 | n_of_pads[0]=fTPCParam->GetNPads(isec,0); |
1567 | n_of_pads[1]=fTPCParam->GetNPads(isec,1); |
1568 | } |
1569 | else if(irow == nrows-1){ |
1570 | iFlag=2; |
1571 | n_of_pads[1]=fTPCParam->GetNPads(isec,irow-1); |
1572 | n_of_pads[2]=fTPCParam->GetNPads(isec,irow); |
1573 | } |
1574 | else { |
1575 | iFlag=1; |
1576 | for(i1=0;i1<3;i1++){ |
1577 | n_of_pads[i1]=fTPCParam->GetNPads(isec,irow-1+i1); |
1578 | } |
1579 | } |
1580 | |
1581 | // |
1582 | // Integrated signal for this row |
1583 | // and a single track signal |
1584 | // |
1585 | |
3c0f9266 |
1586 | TMatrix *m1 = new TMatrix(0,n_of_pads[iFlag]-1,0,MAXTBKT-1); // integrated |
1587 | TMatrix *m2 = new TMatrix(0,n_of_pads[iFlag]-1,0,MAXTBKT-1); // single |
8c555625 |
1588 | |
1589 | // |
1590 | |
1591 | TMatrix &Total = *m1; |
1592 | |
1593 | // Array of pointers to the label-signal list |
1594 | |
3c0f9266 |
1595 | Int_t NofDigits = n_of_pads[iFlag]*MAXTBKT; // number of digits for this row |
8c555625 |
1596 | |
1597 | Float_t **pList = new Float_t* [NofDigits]; |
1598 | |
1599 | Int_t lp; |
1600 | |
1601 | for(lp=0;lp<NofDigits;lp++)pList[lp]=0; // set all pointers to NULL |
1602 | |
1603 | // |
1604 | // Straight signal and cross-talk, cross-talk is integrated over all |
1605 | // tracks and added to the signal at the very end |
1606 | // |
1607 | |
1608 | |
1609 | for (i1=0;i1<nTracks[iFlag];i1++){ |
1610 | |
1611 | m2->Zero(); // clear single track signal matrix |
1612 | |
1613 | Float_t TrackLabel = |
1614 | GetSignal(rowTriplet[iFlag],i1,n_of_pads[iFlag],m2,m1,IndexRange); |
1615 | |
1616 | GetList(TrackLabel,n_of_pads[iFlag],m2,IndexRange,pList); |
1617 | |
1618 | } |
1619 | |
1620 | // |
1621 | // Cross talk from the neighbouring pad-rows |
1622 | // |
1623 | |
3c0f9266 |
1624 | TMatrix *m3 = new TMatrix(0,n_of_pads[iFlag]-1,0,MAXTBKT-1); // cross-talk |
8c555625 |
1625 | |
1626 | TMatrix &Cross = *m3; |
1627 | |
1628 | if(iFlag == 0){ |
1629 | |
1630 | // cross-talk from the outer row only (first pad row) |
1631 | |
1632 | GetCrossTalk(0,rowTriplet[1],nTracks[1],n_of_pads,m3); |
1633 | |
1634 | } |
1635 | else if(iFlag == 2){ |
1636 | |
1637 | // cross-talk from the inner row only (last pad row) |
1638 | |
1639 | GetCrossTalk(2,rowTriplet[1],nTracks[1],n_of_pads,m3); |
1640 | |
1641 | } |
1642 | else{ |
1643 | |
1644 | // cross-talk from both inner and outer rows |
1645 | |
1646 | GetCrossTalk(3,rowTriplet[0],nTracks[0],n_of_pads,m3); // inner |
1647 | GetCrossTalk(4,rowTriplet[2],nTracks[2],n_of_pads,m3); //outer |
1648 | } |
1649 | |
1650 | Total += Cross; // add the cross-talk |
1651 | |
1652 | // |
1653 | // Convert analog signal to ADC counts |
1654 | // |
1655 | |
1656 | Int_t tracks[3]; |
1657 | Int_t digits[5]; |
1658 | |
1659 | |
1283eee5 |
1660 | for(Int_t ip=0;ip<n_of_pads[iFlag];ip++){ |
3c0f9266 |
1661 | for(Int_t it=0;it<MAXTBKT;it++){ |
8c555625 |
1662 | |
1663 | Float_t q = Total(ip,it); |
1664 | |
1283eee5 |
1665 | Int_t gi =it*n_of_pads[iFlag]+ip; // global index |
8c555625 |
1666 | |
1667 | q = gRandom->Gaus(q,fTPCParam->GetNoise()); // apply noise |
1668 | q *= (q_el*1.e15); // convert to fC |
1669 | q *= chipgain; // convert to mV |
1670 | q *= (adc_sat/dyn_range); // convert to ADC counts |
1671 | |
1672 | if(q <zerosup) continue; // do not fill zeros |
1673 | if(q > adc_sat) q = adc_sat; // saturation |
1674 | |
1675 | // |
1676 | // "real" signal or electronic noise (list = -1)? |
1677 | // |
1678 | |
1679 | for(Int_t j1=0;j1<3;j1++){ |
1680 | tracks[j1] = (pList[gi]) ?(Int_t)(*(pList[gi]+j1)) : -1; |
1681 | } |
1682 | |
1683 | digits[0]=isec; |
1283eee5 |
1684 | digits[1]=irow; |
8c555625 |
1685 | digits[2]=ip; |
1686 | digits[3]=it; |
1687 | digits[4]= (Int_t)q; |
1688 | |
1689 | // Add this digit |
1690 | |
1691 | AddDigit(tracks,digits); |
1692 | |
1693 | } // end of loop over time buckets |
1694 | } // end of lop over pads |
1695 | |
1696 | // |
1697 | // This row has been digitized, delete nonused stuff |
1698 | // |
1699 | |
1700 | for(lp=0;lp<NofDigits;lp++){ |
1701 | if(pList[lp]) delete [] pList[lp]; |
1702 | } |
1703 | |
1704 | delete [] pList; |
1705 | |
1706 | delete m1; |
1707 | delete m2; |
1708 | delete m3; |
1709 | |
1710 | } // end of DigitizeRow |
1711 | //_____________________________________________________________________________ |
1712 | Float_t AliTPC::GetSignal(TObjArray *p1, Int_t ntr, Int_t np, TMatrix *m1, TMatrix *m2, |
1713 | Int_t *IndexRange) |
1714 | { |
1715 | |
1716 | //--------------------------------------------------------------- |
1717 | // Calculates 2-D signal (pad,time) for a single track, |
1718 | // returns a pointer to the signal matrix and the track label |
1719 | // No digitization is performed at this level!!! |
1720 | //--------------------------------------------------------------- |
1721 | |
1722 | //----------------------------------------------------------------- |
1723 | // Origin: Marek Kowalski IFJ, Krakow, Marek.Kowalski@ifj.edu.pl |
1724 | //----------------------------------------------------------------- |
1725 | |
1726 | TVector *tv; |
1727 | AliTPCParam * fTPCParam = &(fDigParam->GetParam()); |
1728 | AliTPCPRF2D * fPRF2D = &(fDigParam->GetPRF2D()); |
1729 | AliTPCRF1D * fRF = &(fDigParam->GetRF()); |
3c0f9266 |
1730 | const int MAXTBKT= |
1731 | int((z_end+6*fTPCParam->GetZSigma())/fTPCParam->GetZWidth())+1; |
8c555625 |
1732 | |
1733 | //to make the code faster we put parameters to the stack |
1734 | |
1735 | Float_t zwidth = fTPCParam->GetZWidth(); |
7ee081c2 |
1736 | Float_t zwidthm1 =1./zwidth; |
8c555625 |
1737 | |
1738 | tv = (TVector*)p1->At(ntr); // pointer to a track |
1739 | TVector &v = *tv; |
1740 | |
1741 | Float_t label = v(0); |
1742 | |
1283eee5 |
1743 | Int_t CentralPad = (np-1)/2; |
8c555625 |
1744 | Int_t PadNumber; |
1745 | Int_t nElectrons = (tv->GetNrows()-1)/4; |
1746 | Float_t range=((np-1)/2 + 0.5)*fTPCParam->GetPadPitchWidth(); // pad range |
8c555625 |
1747 | |
1283eee5 |
1748 | range -= 0.5; // dead zone, 5mm from the edge, according to H.G. Fischer |
1749 | |
8c555625 |
1750 | Float_t IneffFactor = 0.5; // inefficiency in the gain close to the edge, as above |
1751 | |
1752 | |
1753 | Float_t PadSignal[7]; // signal from a single electron |
1754 | |
1755 | TMatrix &signal = *m1; |
1756 | TMatrix &total = *m2; |
1757 | |
1758 | |
1759 | IndexRange[0]=9999; // min pad |
1760 | IndexRange[1]=-1; // max pad |
1761 | IndexRange[2]=9999; //min time |
1762 | IndexRange[3]=-1; // max time |
1763 | |
1764 | // |
1765 | // Loop over all electrons |
1766 | // |
1767 | |
1768 | for(Int_t nel=0; nel<nElectrons; nel++){ |
1769 | Int_t idx=nel*4; |
1770 | Float_t xwire = v(idx+1); |
1771 | Float_t y = v(idx+2); |
1772 | Float_t z = v(idx+3); |
1773 | |
1774 | |
1775 | Float_t absy=TMath::Abs(y); |
1776 | |
1777 | if(absy < 0.5*fTPCParam->GetPadPitchWidth()){ |
1778 | PadNumber=CentralPad; |
1779 | } |
1780 | else if (absy < range){ |
8022212f |
1781 | PadNumber=(Int_t) ((absy-0.5*fTPCParam->GetPadPitchWidth())/fTPCParam->GetPadPitchWidth()+1.); |
8c555625 |
1782 | PadNumber=(Int_t) (TMath::Sign((Float_t)PadNumber, y)+CentralPad); |
1783 | } |
1784 | else continue; // electron out of pad-range , lost at the sector edge |
1785 | |
1786 | Float_t aval = (absy<range-0.5) ? v(idx+4):v(idx+4)*IneffFactor; |
1787 | |
1788 | |
1789 | Float_t dist = y - (Float_t)(PadNumber-CentralPad)*fTPCParam->GetPadPitchWidth(); |
a03540ae |
1790 | for (Int_t i=0;i<7;i++){ |
b6738b36 |
1791 | PadSignal[i]=fPRF2D->GetPRF(-dist+(i-3)*fTPCParam->GetPadPitchWidth(),xwire)*aval; |
a03540ae |
1792 | PadSignal[i] *= fTPCParam->GetPadCoupling(); |
1793 | } |
8c555625 |
1794 | |
1283eee5 |
1795 | Int_t LeftPad = TMath::Max(0,PadNumber-3); |
1796 | Int_t RightPad = TMath::Min(np-1,PadNumber+3); |
8c555625 |
1797 | |
1798 | Int_t pmin=LeftPad-PadNumber+3; // lower index of the pad_signal vector |
1799 | Int_t pmax=RightPad-PadNumber+3; // upper index |
1800 | |
1283eee5 |
1801 | Float_t z_drift = z*zwidthm1; |
8c555625 |
1802 | Float_t z_offset = z_drift-(Int_t)z_drift; |
3c0f9266 |
1803 | |
1804 | Int_t FirstBucket = (Int_t)z_drift; // numbering starts from "0" |
8c555625 |
1805 | |
1806 | |
1807 | // loop over time bins (4 bins is enough - 3 sigma truncated Gaussian) |
3c0f9266 |
1808 | |
8c555625 |
1809 | for (Int_t i2=0;i2<4;i2++){ |
1810 | Int_t TrueTime = FirstBucket+i2; // current time bucket |
3c0f9266 |
1811 | Float_t dz = (Float_t(i2)+1.-z_offset)*zwidth; |
8c555625 |
1812 | Float_t ampl = fRF->GetRF(dz); |
3c0f9266 |
1813 | if( (TrueTime>MAXTBKT-1) ) break; // beyond the time range |
8c555625 |
1814 | |
1815 | IndexRange[2]=TMath::Min(IndexRange[2],TrueTime); // min time |
1816 | IndexRange[3]=TMath::Max(IndexRange[3],TrueTime); // max time |
1817 | |
1818 | // loop over pads, from pmin to pmax |
1819 | for(Int_t i3=pmin;i3<=pmax;i3++){ |
1820 | Int_t TruePad = LeftPad+i3-pmin; |
1821 | IndexRange[0]=TMath::Min(IndexRange[0],TruePad); // min pad |
1822 | IndexRange[1]=TMath::Max(IndexRange[1],TruePad); // max pad |
1823 | signal(TruePad,TrueTime)+=(PadSignal[i3]*ampl); // not converted to charge!!! |
1824 | total(TruePad,TrueTime)+=(PadSignal[i3]*ampl); // not converted to charge!!! |
1825 | } // end of pads loop |
1826 | } // end of time loop |
1827 | } // end of loop over electrons |
1828 | |
1829 | return label; // returns track label when finished |
1830 | } |
1831 | |
1832 | //_____________________________________________________________________________ |
1833 | void AliTPC::GetList(Float_t label,Int_t np,TMatrix *m,Int_t *IndexRange, |
1834 | Float_t **pList) |
1835 | { |
1836 | //---------------------------------------------------------------------- |
1837 | // Updates the list of tracks contributing to digits for a given row |
1838 | //---------------------------------------------------------------------- |
1839 | |
1840 | //----------------------------------------------------------------- |
1841 | // Origin: Marek Kowalski IFJ, Krakow, Marek.Kowalski@ifj.edu.pl |
1842 | //----------------------------------------------------------------- |
1843 | |
1844 | TMatrix &signal = *m; |
1845 | |
1846 | // lop over nonzero digits |
1847 | |
1848 | for(Int_t it=IndexRange[2];it<IndexRange[3]+1;it++){ |
1849 | for(Int_t ip=IndexRange[0];ip<IndexRange[1]+1;ip++){ |
1850 | |
1851 | |
1283eee5 |
1852 | Int_t GlobalIndex = it*np+ip; // GlobalIndex starts from 0! |
8c555625 |
1853 | |
1854 | if(!pList[GlobalIndex]){ |
1855 | |
1856 | // |
1857 | // Create new list (6 elements - 3 signals and 3 labels), |
1858 | // but only if the signal is > 0. |
1859 | // |
1860 | |
1861 | if(signal(ip,it)>0.){ |
1862 | |
1863 | pList[GlobalIndex] = new Float_t [6]; |
1864 | |
1865 | // set list to -1 |
1866 | |
1867 | *pList[GlobalIndex] = -1.; |
1868 | *(pList[GlobalIndex]+1) = -1.; |
1869 | *(pList[GlobalIndex]+2) = -1.; |
1870 | *(pList[GlobalIndex]+3) = -1.; |
1871 | *(pList[GlobalIndex]+4) = -1.; |
1872 | *(pList[GlobalIndex]+5) = -1.; |
1873 | |
1874 | |
1875 | *pList[GlobalIndex] = label; |
1876 | *(pList[GlobalIndex]+3) = signal(ip,it);} |
1877 | } |
1878 | else{ |
1879 | |
1880 | // check the signal magnitude |
1881 | |
1882 | Float_t highest = *(pList[GlobalIndex]+3); |
1883 | Float_t middle = *(pList[GlobalIndex]+4); |
1884 | Float_t lowest = *(pList[GlobalIndex]+5); |
1885 | |
1886 | // |
1887 | // compare the new signal with already existing list |
1888 | // |
1889 | |
1890 | if(signal(ip,it)<lowest) continue; // neglect this track |
1891 | |
1892 | // |
1893 | |
1894 | if (signal(ip,it)>highest){ |
1895 | *(pList[GlobalIndex]+5) = middle; |
1896 | *(pList[GlobalIndex]+4) = highest; |
1897 | *(pList[GlobalIndex]+3) = signal(ip,it); |
1898 | |
1899 | *(pList[GlobalIndex]+2) = *(pList[GlobalIndex]+1); |
1900 | *(pList[GlobalIndex]+1) = *pList[GlobalIndex]; |
1901 | *pList[GlobalIndex] = label; |
1902 | } |
1903 | else if (signal(ip,it)>middle){ |
1904 | *(pList[GlobalIndex]+5) = middle; |
1905 | *(pList[GlobalIndex]+4) = signal(ip,it); |
1906 | |
1907 | *(pList[GlobalIndex]+2) = *(pList[GlobalIndex]+1); |
1908 | *(pList[GlobalIndex]+1) = label; |
1909 | } |
1910 | else{ |
1911 | *(pList[GlobalIndex]+5) = signal(ip,it); |
1912 | *(pList[GlobalIndex]+2) = label; |
1913 | } |
1914 | } |
1915 | |
1916 | } // end of loop over pads |
1917 | } // end of loop over time bins |
1918 | |
1919 | |
1920 | |
1921 | |
1922 | }//end of GetList |
1923 | //___________________________________________________________________ |
1924 | void AliTPC::MakeSector(Int_t isec,Int_t nrows,TTree *TH, |
1925 | Stat_t ntracks,TObjArray **row) |
1926 | { |
1927 | |
1928 | //----------------------------------------------------------------- |
1929 | // Prepares the sector digitization, creates the vectors of |
1930 | // tracks for each row of this sector. The track vector |
1931 | // contains the track label and the position of electrons. |
1932 | //----------------------------------------------------------------- |
1933 | |
1934 | //----------------------------------------------------------------- |
1935 | // Origin: Marek Kowalski IFJ, Krakow, Marek.Kowalski@ifj.edu.pl |
1936 | //----------------------------------------------------------------- |
1937 | |
1938 | AliTPCParam * fTPCParam = &(fDigParam->GetParam()); |
1939 | Int_t i; |
1940 | Float_t xyz[3]; |
1941 | |
1942 | AliTPChit *tpcHit; // pointer to a sigle TPC hit |
1943 | |
1944 | //---------------------------------------------- |
1945 | // Create TObjArray-s, one for each row, |
1946 | // each TObjArray will store the TVectors |
1947 | // of electrons, one TVector per each track. |
1948 | //---------------------------------------------- |
1949 | |
1950 | for(i=0; i<nrows; i++){ |
1951 | row[i] = new TObjArray; |
1952 | } |
1953 | Int_t *n_of_electrons = new Int_t [nrows]; // electron counter for each row |
1954 | TVector **tr = new TVector* [nrows]; //pointers to the track vectors |
1955 | |
1956 | //-------------------------------------------------------------------- |
1957 | // Loop over tracks, the "track" contains the full history |
1958 | //-------------------------------------------------------------------- |
1959 | |
1960 | Int_t previousTrack,currentTrack; |
1961 | previousTrack = -1; // nothing to store so far! |
1962 | |
1963 | for(Int_t track=0;track<ntracks;track++){ |
1964 | |
1965 | ResetHits(); |
1966 | |
1967 | TH->GetEvent(track); // get next track |
1968 | Int_t nhits = fHits->GetEntriesFast(); // get number of hits for this track |
1969 | |
1970 | if(nhits == 0) continue; // no hits in the TPC for this track |
1971 | |
1972 | //-------------------------------------------------------------- |
1973 | // Loop over hits |
1974 | //-------------------------------------------------------------- |
1975 | |
1976 | for(Int_t hit=0;hit<nhits;hit++){ |
1977 | |
1978 | tpcHit = (AliTPChit*)fHits->UncheckedAt(hit); // get a pointer to a hit |
1979 | |
1980 | Int_t sector=tpcHit->fSector; // sector number |
1981 | if(sector != isec) continue; //terminate iteration |
1982 | |
1983 | currentTrack = tpcHit->fTrack; // track number |
1984 | if(currentTrack != previousTrack){ |
1985 | |
1986 | // store already filled fTrack |
1987 | |
1988 | for(i=0;i<nrows;i++){ |
1989 | if(previousTrack != -1){ |
1990 | if(n_of_electrons[i]>0){ |
1991 | TVector &v = *tr[i]; |
1992 | v(0) = previousTrack; |
1993 | tr[i]->ResizeTo(3*n_of_electrons[i]+1); // shrink if necessary |
1994 | row[i]->Add(tr[i]); |
1995 | } |
1996 | else{ |
1997 | delete tr[i]; // delete empty TVector |
1998 | tr[i]=0; |
1999 | } |
2000 | } |
2001 | |
2002 | n_of_electrons[i]=0; |
2003 | tr[i] = new TVector(361); // TVectors for the next fTrack |
2004 | |
2005 | } // end of loop over rows |
2006 | |
2007 | previousTrack=currentTrack; // update track label |
2008 | } |
2009 | |
2010 | Int_t QI = (Int_t) (tpcHit->fQ); // energy loss (number of electrons) |
2011 | |
2012 | //--------------------------------------------------- |
2013 | // Calculate the electron attachment probability |
2014 | //--------------------------------------------------- |
2015 | |
2016 | Float_t time = 1.e6*(z_end-TMath::Abs(tpcHit->fZ))/fTPCParam->GetDriftV(); |
2017 | // in microseconds! |
2018 | Float_t AttProb = fTPCParam->GetAttCoef()* |
2019 | fTPCParam->GetOxyCont()*time; // fraction! |
2020 | |
2021 | //----------------------------------------------- |
2022 | // Loop over electrons |
2023 | //----------------------------------------------- |
2024 | |
2025 | for(Int_t nel=0;nel<QI;nel++){ |
2026 | // skip if electron lost due to the attachment |
2027 | if((gRandom->Rndm(0)) < AttProb) continue; // electron lost! |
2028 | xyz[0]=tpcHit->fX; |
2029 | xyz[1]=tpcHit->fY; |
2030 | xyz[2]=tpcHit->fZ; |
2031 | ElDiff(xyz); // Appply the diffusion |
2032 | Int_t row_number; |
2033 | fTPCParam->XYZtoCRXYZ(xyz,isec,row_number,3); |
2034 | |
2035 | //transform position to local coordinates |
2036 | //option 3 means that we calculate x position relative to |
2037 | //nearest pad row |
2038 | |
2039 | if ((row_number<0)||row_number>=fTPCParam->GetNRow(isec)) continue; |
2040 | ExB(xyz); // ExB effect at the sense wires |
2041 | n_of_electrons[row_number]++; |
2042 | //---------------------------------- |
2043 | // Expand vector if necessary |
2044 | //---------------------------------- |
fe4da5cc |
2045 | if(n_of_electrons[row_number]>120){ |
2046 | Int_t range = tr[row_number]->GetNrows(); |
8c555625 |
2047 | if(n_of_electrons[row_number] > (range-1)/3){ |
2048 | tr[row_number]->ResizeTo(range+150); // Add 50 electrons |
fe4da5cc |
2049 | } |
2050 | } |
2051 | |
fe4da5cc |
2052 | TVector &v = *tr[row_number]; |
8c555625 |
2053 | Int_t idx = 3*n_of_electrons[row_number]-2; |
2054 | |
2055 | v(idx)= xyz[0]; // X |
2056 | v(idx+1)=xyz[1]; // Y (along the pad-row) |
2057 | v(idx+2)=xyz[2]; // Z |
2058 | |
2059 | } // end of loop over electrons |
2060 | |
2061 | } // end of loop over hits |
2062 | } // end of loop over tracks |
2063 | |
2064 | // |
2065 | // store remaining track (the last one) if not empty |
2066 | // |
2067 | |
2068 | for(i=0;i<nrows;i++){ |
2069 | if(n_of_electrons[i]>0){ |
2070 | TVector &v = *tr[i]; |
2071 | v(0) = previousTrack; |
2072 | tr[i]->ResizeTo(3*n_of_electrons[i]+1); // shrink if necessary |
2073 | row[i]->Add(tr[i]); |
fe4da5cc |
2074 | } |
2075 | else{ |
8c555625 |
2076 | delete tr[i]; |
2077 | tr[i]=0; |
2078 | } |
2079 | } |
2080 | |
2081 | delete [] tr; |
2082 | delete [] n_of_electrons; |
2083 | |
2084 | } // end of MakeSector |
2085 | //_____________________________________________________________________________ |
2086 | void AliTPC::GetCrossTalk (Int_t iFlag,TObjArray *p,Int_t ntracks,Int_t *npads, |
2087 | TMatrix *m) |
2088 | { |
2089 | |
2090 | //------------------------------------------------------------- |
2091 | // Calculates the cross-talk from one row (inner or outer) |
2092 | //------------------------------------------------------------- |
2093 | |
2094 | //----------------------------------------------------------------- |
2095 | // Origin: Marek Kowalski IFJ, Krakow, Marek.Kowalski@ifj.edu.pl |
2096 | //----------------------------------------------------------------- |
2097 | |
2098 | // |
2099 | // iFlag=2 & 3 --> cross-talk from the inner row |
2100 | // iFlag=0 & 4 --> cross-talk from the outer row |
2101 | // |
2102 | AliTPCParam * fTPCParam = &(fDigParam->GetParam()); |
2103 | AliTPCPRF2D * fPRF2D = &(fDigParam->GetPRF2D()); |
2104 | AliTPCRF1D * fRF = &(fDigParam->GetRF()); |
3c0f9266 |
2105 | const int MAXTBKT= |
2106 | int((z_end+6*fTPCParam->GetZSigma())/fTPCParam->GetZWidth())+1; |
8c555625 |
2107 | |
2108 | //to make code faster |
2109 | |
2110 | Float_t zwidth = fTPCParam->GetZWidth(); |
2111 | Float_t zwidthm1 =1/fTPCParam->GetZWidth(); |
2112 | |
2113 | Int_t PadNumber; |
2114 | Float_t xwire; |
2115 | |
2116 | Int_t nPadsSignal; // for this pads the signal is calculated |
2117 | Float_t range; // sense wire range |
2118 | Int_t nPadsDiff; |
2119 | |
2120 | Float_t IneffFactor=0.5; // gain inefficiency close to the edges |
2121 | |
2122 | if(iFlag == 0){ |
2123 | // 1-->0 |
2124 | nPadsSignal = npads[1]; |
2125 | range = ((npads[1]-1)/2 + 0.5)*fTPCParam->GetPadPitchWidth(); |
2126 | nPadsDiff = (npads[1]-npads[0])/2; |
2127 | } |
2128 | else if (iFlag == 2){ |
2129 | // 1-->2 |
2130 | nPadsSignal = npads[2]; |
2131 | range = ((npads[1]-1)/2 + 0.5)*fTPCParam->GetPadPitchWidth(); |
2132 | nPadsDiff = 0; |
2133 | } |
2134 | else if (iFlag == 3){ |
2135 | // 0-->1 |
2136 | nPadsSignal = npads[1]; |
2137 | range = ((npads[0]-1)/2 + 0.5)*fTPCParam->GetPadPitchWidth(); |
2138 | nPadsDiff = 0; |
2139 | } |
2140 | else{ |
2141 | // 2-->1 |
2142 | nPadsSignal = npads[2]; |
2143 | range = ((npads[2]-1)/2 + 0.5)*fTPCParam->GetPadPitchWidth(); |
2144 | nPadsDiff = (npads[2]-npads[1])/2; |
2145 | } |
2146 | |
2147 | range-=0.5; // dead zone close to the edges |
2148 | |
2149 | TVector *tv; |
2150 | TMatrix &signal = *m; |
2151 | |
1283eee5 |
2152 | Int_t CentralPad = (nPadsSignal-1)/2; |
8c555625 |
2153 | Float_t PadSignal[7]; // signal from a single electron |
2154 | // Loop over tracks |
2155 | for(Int_t nt=0;nt<ntracks;nt++){ |
2156 | tv=(TVector*)p->At(nt); // pointer to a track |
2157 | TVector &v = *tv; |
2158 | Int_t nElectrons = (tv->GetNrows()-1)/4; |
2159 | // Loop over electrons |
2160 | for(Int_t nel=0; nel<nElectrons; nel++){ |
2161 | Int_t idx=nel*4; |
2162 | xwire=v(idx+1); |
2163 | |
2164 | if (iFlag==0) xwire+=fTPCParam->GetPadPitchLength(); |
2165 | if (iFlag==2) xwire-=fTPCParam->GetPadPitchLength(); |
2166 | if (iFlag==3) xwire-=fTPCParam->GetPadPitchLength(); |
2167 | if (iFlag==4) xwire+=fTPCParam->GetPadPitchLength(); |
2168 | |
2169 | // electron acceptance for the cross-talk (only the closest wire) |
2170 | |
2171 | Float_t dxMax = fTPCParam->GetPadPitchLength()*0.5+fTPCParam->GetWWPitch(); |
2172 | if(TMath::Abs(xwire)>dxMax) continue; |
2173 | |
2174 | Float_t y = v(idx+2); |
2175 | Float_t z = v(idx+3); |
2176 | Float_t absy=TMath::Abs(y); |
2177 | |
2178 | if(absy < 0.5*fTPCParam->GetPadPitchWidth()){ |
2179 | PadNumber=CentralPad; |
2180 | } |
2181 | else if (absy < range){ |
8022212f |
2182 | PadNumber=(Int_t) ((absy-0.5*fTPCParam->GetPadPitchWidth())/fTPCParam->GetPadPitchWidth() +1.); |
8c555625 |
2183 | PadNumber=(Int_t) (TMath::Sign((Float_t)PadNumber, y)+CentralPad); |
2184 | } |
2185 | else continue; // electron out of sense wire range, lost at the sector edge |
2186 | |
2187 | Float_t aval = (absy<range-0.5) ? v(idx+4):v(idx+4)*IneffFactor; |
2188 | |
2189 | Float_t dist = y - (Float_t)(PadNumber-CentralPad)*fTPCParam->GetPadPitchWidth(); |
2190 | |
a03540ae |
2191 | for (Int_t i=0;i<7;i++){ |
b6738b36 |
2192 | PadSignal[i]=fPRF2D->GetPRF(-dist+(i-3)*fTPCParam->GetPadPitchWidth(),xwire)*aval; |
8c555625 |
2193 | |
a03540ae |
2194 | PadSignal[i] *= fTPCParam->GetPadCoupling(); |
2195 | } |
8c555625 |
2196 | // real pad range |
2197 | |
1283eee5 |
2198 | Int_t LeftPad = TMath::Max(0,PadNumber-3); |
2199 | Int_t RightPad = TMath::Min(nPadsSignal-1,PadNumber+3); |
8c555625 |
2200 | |
2201 | Int_t pmin=LeftPad-PadNumber+3; // lower index of the pad_signal vector |
2202 | Int_t pmax=RightPad-PadNumber+3; // upper index |
2203 | |
2204 | |
1283eee5 |
2205 | Float_t z_drift = z*zwidthm1; |
8c555625 |
2206 | Float_t z_offset = z_drift-(Int_t)z_drift; |
3c0f9266 |
2207 | |
2208 | Int_t FirstBucket = (Int_t)z_drift; // numbering starts from "0" |
2209 | |
8c555625 |
2210 | for (Int_t i2=0;i2<4;i2++){ |
2211 | Int_t TrueTime = FirstBucket+i2; // current time bucket |
3c0f9266 |
2212 | Float_t dz = (Float_t(i2)+1.- z_offset)*zwidth; |
8c555625 |
2213 | Float_t ampl = fRF->GetRF(dz); |
3c0f9266 |
2214 | if((TrueTime>MAXTBKT-1)) break; // beyond the time range |
8c555625 |
2215 | |
2216 | |
2217 | // loop over pads, from pmin to pmax |
2218 | |
2219 | for(Int_t i3=pmin;i3<pmax+1;i3++){ |
2220 | Int_t TruePad = LeftPad+i3-pmin; |
2221 | |
1283eee5 |
2222 | if(TruePad<nPadsDiff || TruePad > nPadsSignal-nPadsDiff-1) continue; |
8c555625 |
2223 | |
2224 | TruePad -= nPadsDiff; |
2225 | signal(TruePad,TrueTime)+=(PadSignal[i3]*ampl); // not converted to charge! |
2226 | |
2227 | } // end of loop over pads |
2228 | } // end of loop over time bins |
2229 | |
2230 | } // end of loop over electrons |
2231 | |
2232 | } // end of loop over tracks |
2233 | |
2234 | } // end of GetCrossTalk |
2235 | |
2236 | |
fe4da5cc |
2237 | |
2238 | //_____________________________________________________________________________ |
2239 | void AliTPC::Init() |
2240 | { |
2241 | // |
2242 | // Initialise TPC detector after definition of geometry |
2243 | // |
2244 | Int_t i; |
2245 | // |
2246 | printf("\n"); |
2247 | for(i=0;i<35;i++) printf("*"); |
2248 | printf(" TPC_INIT "); |
2249 | for(i=0;i<35;i++) printf("*"); |
2250 | printf("\n"); |
2251 | // |
2252 | for(i=0;i<80;i++) printf("*"); |
2253 | printf("\n"); |
2254 | } |
2255 | |
2256 | //_____________________________________________________________________________ |
2257 | void AliTPC::MakeBranch(Option_t* option) |
2258 | { |
2259 | // |
2260 | // Create Tree branches for the TPC. |
2261 | // |
2262 | Int_t buffersize = 4000; |
2263 | char branchname[10]; |
2264 | sprintf(branchname,"%s",GetName()); |
2265 | |
2266 | AliDetector::MakeBranch(option); |
2267 | |
2268 | char *D = strstr(option,"D"); |
2269 | |
2270 | if (fDigits && gAlice->TreeD() && D) { |
2271 | gAlice->TreeD()->Branch(branchname,&fDigits, buffersize); |
2272 | printf("Making Branch %s for digits\n",branchname); |
2273 | } |
2274 | |
2275 | char *R = strstr(option,"R"); |
2276 | |
2277 | if (fClusters && gAlice->TreeR() && R) { |
2278 | gAlice->TreeR()->Branch(branchname,&fClusters, buffersize); |
2279 | printf("Making Branch %s for Clusters\n",branchname); |
2280 | } |
2281 | } |
2282 | |
2283 | //_____________________________________________________________________________ |
2284 | void AliTPC::ResetDigits() |
2285 | { |
2286 | // |
2287 | // Reset number of digits and the digits array for this detector |
2288 | // reset clusters |
2289 | // |
2290 | fNdigits = 0; |
8c555625 |
2291 | // if (fDigits) fDigits->Clear(); |
2292 | if (fDigParam->GetArray()!=0) fDigParam->GetArray()->Clear(); |
fe4da5cc |
2293 | fNclusters = 0; |
2294 | if (fClusters) fClusters->Clear(); |
2295 | } |
2296 | |
2297 | //_____________________________________________________________________________ |
2298 | void AliTPC::SetSecAL(Int_t sec) |
2299 | { |
8c555625 |
2300 | //--------------------------------------------------- |
fe4da5cc |
2301 | // Activate/deactivate selection for lower sectors |
8c555625 |
2302 | //--------------------------------------------------- |
2303 | |
2304 | //----------------------------------------------------------------- |
2305 | // Origin: Marek Kowalski IFJ, Krakow, Marek.Kowalski@ifj.edu.pl |
2306 | //----------------------------------------------------------------- |
2307 | |
fe4da5cc |
2308 | fSecAL = sec; |
2309 | } |
2310 | |
2311 | //_____________________________________________________________________________ |
2312 | void AliTPC::SetSecAU(Int_t sec) |
2313 | { |
8c555625 |
2314 | //---------------------------------------------------- |
fe4da5cc |
2315 | // Activate/deactivate selection for upper sectors |
8c555625 |
2316 | //--------------------------------------------------- |
2317 | |
2318 | //----------------------------------------------------------------- |
2319 | // Origin: Marek Kowalski IFJ, Krakow, Marek.Kowalski@ifj.edu.pl |
2320 | //----------------------------------------------------------------- |
2321 | |
fe4da5cc |
2322 | fSecAU = sec; |
2323 | } |
2324 | |
2325 | //_____________________________________________________________________________ |
2326 | void AliTPC::SetSecLows(Int_t s1,Int_t s2,Int_t s3,Int_t s4,Int_t s5, Int_t s6) |
2327 | { |
8c555625 |
2328 | //---------------------------------------- |
fe4da5cc |
2329 | // Select active lower sectors |
8c555625 |
2330 | //---------------------------------------- |
2331 | |
2332 | //----------------------------------------------------------------- |
2333 | // Origin: Marek Kowalski IFJ, Krakow, Marek.Kowalski@ifj.edu.pl |
2334 | //----------------------------------------------------------------- |
2335 | |
fe4da5cc |
2336 | fSecLows[0] = s1; |
2337 | fSecLows[1] = s2; |
2338 | fSecLows[2] = s3; |
2339 | fSecLows[3] = s4; |
2340 | fSecLows[4] = s5; |
2341 | fSecLows[5] = s6; |
2342 | } |
2343 | |
2344 | //_____________________________________________________________________________ |
2345 | void AliTPC::SetSecUps(Int_t s1,Int_t s2,Int_t s3,Int_t s4,Int_t s5, Int_t s6, |
2346 | Int_t s7, Int_t s8 ,Int_t s9 ,Int_t s10, |
2347 | Int_t s11 , Int_t s12) |
2348 | { |
8c555625 |
2349 | //-------------------------------- |
fe4da5cc |
2350 | // Select active upper sectors |
8c555625 |
2351 | //-------------------------------- |
2352 | |
2353 | //----------------------------------------------------------------- |
2354 | // Origin: Marek Kowalski IFJ, Krakow, Marek.Kowalski@ifj.edu.pl |
2355 | //----------------------------------------------------------------- |
2356 | |
fe4da5cc |
2357 | fSecUps[0] = s1; |
2358 | fSecUps[1] = s2; |
2359 | fSecUps[2] = s3; |
2360 | fSecUps[3] = s4; |
2361 | fSecUps[4] = s5; |
2362 | fSecUps[5] = s6; |
2363 | fSecUps[6] = s7; |
2364 | fSecUps[7] = s8; |
2365 | fSecUps[8] = s9; |
2366 | fSecUps[9] = s10; |
2367 | fSecUps[10] = s11; |
2368 | fSecUps[11] = s12; |
2369 | } |
2370 | |
2371 | //_____________________________________________________________________________ |
2372 | void AliTPC::SetSens(Int_t sens) |
2373 | { |
8c555625 |
2374 | |
2375 | //------------------------------------------------------------- |
2376 | // Activates/deactivates the sensitive strips at the center of |
2377 | // the pad row -- this is for the space-point resolution calculations |
2378 | //------------------------------------------------------------- |
2379 | |
2380 | //----------------------------------------------------------------- |
2381 | // Origin: Marek Kowalski IFJ, Krakow, Marek.Kowalski@ifj.edu.pl |
2382 | //----------------------------------------------------------------- |
2383 | |
fe4da5cc |
2384 | fSens = sens; |
2385 | } |
4b0fdcad |
2386 | |
2387 | void AliTPC::SetSide(Float_t side) |
2388 | { |
2389 | fSide = side; |
2390 | |
2391 | } |
1283eee5 |
2392 | //____________________________________________________________________________ |
2393 | void AliTPC::SetGasMixt(Int_t nc,Int_t c1,Int_t c2,Int_t c3,Float_t p1, |
2394 | Float_t p2,Float_t p3) |
2395 | { |
fe4da5cc |
2396 | |
1283eee5 |
2397 | fNoComp = nc; |
2398 | |
2399 | fMixtComp[0]=c1; |
2400 | fMixtComp[1]=c2; |
2401 | fMixtComp[2]=c3; |
2402 | |
2403 | fMixtProp[0]=p1; |
2404 | fMixtProp[1]=p2; |
2405 | fMixtProp[2]=p3; |
2406 | |
2407 | |
2408 | } |
fe4da5cc |
2409 | //_____________________________________________________________________________ |
2410 | void AliTPC::Streamer(TBuffer &R__b) |
2411 | { |
2412 | // |
2413 | // Stream an object of class AliTPC. |
2414 | // |
2415 | if (R__b.IsReading()) { |
2416 | Version_t R__v = R__b.ReadVersion(); if (R__v) { } |
2417 | AliDetector::Streamer(R__b); |
2418 | if (R__v < 2) return; |
2419 | R__b >> fNsectors; |
2420 | R__b >> fNclusters; |
2421 | R__b >> fNtracks; |
2422 | fClustersIndex = new Int_t[fNsectors+1]; |
2423 | fDigitsIndex = new Int_t[fNsectors+1]; |
2424 | } else { |
2425 | R__b.WriteVersion(AliTPC::IsA()); |
2426 | AliDetector::Streamer(R__b); |
2427 | R__b << fNsectors; |
2428 | R__b << fNclusters; |
2429 | R__b << fNtracks; |
2430 | } |
2431 | } |
2432 | |
2433 | ClassImp(AliTPCcluster) |
2434 | |
2435 | //_____________________________________________________________________________ |
2436 | AliTPCcluster::AliTPCcluster(Float_t *hits, Int_t *lab) |
2437 | { |
2438 | // |
2439 | // Creates a simulated cluster for the TPC |
2440 | // |
2441 | fTracks[0] = lab[0]; |
2442 | fTracks[1] = lab[1]; |
2443 | fTracks[2] = lab[2]; |
2444 | fSector = lab[3]; |
2445 | fPadRow = lab[4]; |
2446 | fY = hits[0]; |
2447 | fZ = hits[1]; |
2448 | fQ = hits[2]; |
2449 | fSigmaY2 = hits[3]; |
2450 | fSigmaZ2 = hits[4]; |
2451 | } |
2452 | |
2453 | //_____________________________________________________________________________ |
8c555625 |
2454 | void AliTPCcluster::GetXYZ(Float_t *x, const AliTPCParam *par) const |
fe4da5cc |
2455 | { |
2456 | // |
8c555625 |
2457 | // Transformation from local to global coordinate system |
fe4da5cc |
2458 | // |
3c0f9266 |
2459 | x[0]=par->GetPadRowRadii(fSector,fPadRow); |
8c555625 |
2460 | x[1]=fY; |
2461 | x[2]=fZ; |
3c0f9266 |
2462 | par->CRXYZtoXYZ(x,fSector,fPadRow,1); |
2463 | x[2]=fZ; |
fe4da5cc |
2464 | } |
2465 | |
8c555625 |
2466 | //_____________________________________________________________________________ |
2467 | Int_t AliTPCcluster::Compare(TObject * o) |
2468 | { |
2469 | // |
2470 | // compare two clusters according y coordinata |
3c0f9266 |
2471 | // |
8c555625 |
2472 | AliTPCcluster *cl= (AliTPCcluster *)o; |
2473 | if (fY<cl->fY) return -1; |
2474 | if (fY==cl->fY) return 0; |
2475 | return 1; |
2476 | } |
2477 | |
2478 | Bool_t AliTPCcluster::IsSortable() const |
2479 | { |
2480 | // |
2481 | //make AliTPCcluster sortabale |
3c0f9266 |
2482 | // |
8c555625 |
2483 | return kTRUE; |
2484 | } |
2485 | |
2486 | |
2487 | |
fe4da5cc |
2488 | ClassImp(AliTPCdigit) |
2489 | |
2490 | //_____________________________________________________________________________ |
2491 | AliTPCdigit::AliTPCdigit(Int_t *tracks, Int_t *digits): |
2492 | AliDigit(tracks) |
2493 | { |
2494 | // |
2495 | // Creates a TPC digit object |
2496 | // |
2497 | fSector = digits[0]; |
2498 | fPadRow = digits[1]; |
2499 | fPad = digits[2]; |
2500 | fTime = digits[3]; |
2501 | fSignal = digits[4]; |
2502 | } |
2503 | |
2504 | |
2505 | ClassImp(AliTPChit) |
2506 | |
2507 | //_____________________________________________________________________________ |
2508 | AliTPChit::AliTPChit(Int_t shunt, Int_t track, Int_t *vol, Float_t *hits): |
2509 | AliHit(shunt,track) |
2510 | { |
2511 | // |
2512 | // Creates a TPC hit object |
2513 | // |
2514 | fSector = vol[0]; |
2515 | fPadRow = vol[1]; |
2516 | fX = hits[0]; |
2517 | fY = hits[1]; |
2518 | fZ = hits[2]; |
2519 | fQ = hits[3]; |
2520 | } |
2521 | |
2522 | |
2523 | ClassImp(AliTPCtrack) |
2524 | |
2525 | //_____________________________________________________________________________ |
2526 | AliTPCtrack::AliTPCtrack(Float_t *hits) |
2527 | { |
2528 | // |
2529 | // Default creator for a TPC reconstructed track object |
2530 | // |
3c0f9266 |
2531 | fX=hits[0]; // This is dummy code ! |
fe4da5cc |
2532 | } |
2533 | |
3c0f9266 |
2534 | AliTPCtrack::AliTPCtrack(const AliTPCcluster *c,const TVector& xx, |
2535 | const TMatrix& CC, Double_t xref, Double_t alpha): |
2536 | x(xx),C(CC),fClusters(200) |
fe4da5cc |
2537 | { |
3c0f9266 |
2538 | //----------------------------------------------------------------- |
2539 | // This is the main track constructor. |
fe4da5cc |
2540 | // |
3c0f9266 |
2541 | // Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch |
2542 | //----------------------------------------------------------------- |
2543 | fX=xref; |
2544 | fAlpha=alpha; |
2545 | fChi2=0.; |
2546 | fClusters.AddLast((AliTPCcluster*)(c)); |
fe4da5cc |
2547 | } |
2548 | |
2549 | //_____________________________________________________________________________ |
2550 | AliTPCtrack::AliTPCtrack(const AliTPCtrack& t) : x(t.x), C(t.C), |
3c0f9266 |
2551 | fClusters(t.fClusters.GetEntriesFast()) |
fe4da5cc |
2552 | { |
3c0f9266 |
2553 | //----------------------------------------------------------------- |
2554 | // This is a track copy constructor. |
fe4da5cc |
2555 | // |
3c0f9266 |
2556 | // Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch |
2557 | //----------------------------------------------------------------- |
2558 | fX=t.fX; |
2559 | fChi2=t.fChi2; |
fe4da5cc |
2560 | fAlpha=t.fAlpha; |
3c0f9266 |
2561 | int n=t.fClusters.GetEntriesFast(); |
2562 | for (int i=0; i<n; i++) fClusters.AddLast(t.fClusters.UncheckedAt(i)); |
fe4da5cc |
2563 | } |
2564 | |
2565 | //_____________________________________________________________________________ |
3c0f9266 |
2566 | Int_t AliTPCtrack::Compare(TObject *o) { |
2567 | //----------------------------------------------------------------- |
2568 | // This function compares tracks according to their curvature. |
fe4da5cc |
2569 | // |
3c0f9266 |
2570 | // Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch |
2571 | //----------------------------------------------------------------- |
2572 | AliTPCtrack *t=(AliTPCtrack*)o; |
2573 | Double_t co=t->GetSigmaY2(); |
2574 | Double_t c =GetSigmaY2(); |
2575 | if (c>co) return 1; |
2576 | else if (c<co) return -1; |
2577 | return 0; |
fe4da5cc |
2578 | } |
2579 | |
2580 | //_____________________________________________________________________________ |
2581 | int AliTPCtrack::PropagateTo(Double_t xk,Double_t x0,Double_t rho,Double_t pm) |
2582 | { |
3c0f9266 |
2583 | //----------------------------------------------------------------- |
2584 | // This function propagates a track to a reference plane x=xk. |
fe4da5cc |
2585 | // |
3c0f9266 |
2586 | // Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch |
2587 | //----------------------------------------------------------------- |
fe4da5cc |
2588 | if (TMath::Abs(x(2)*xk - x(3)) >= 0.999) { |
3c0f9266 |
2589 | if (*this>4) cerr<<*this<<" AliTPCtrack warning: Propagation failed !\n"; |
fe4da5cc |
2590 | return 0; |
2591 | } |
8c555625 |
2592 | |
3c0f9266 |
2593 | Double_t x1=fX, x2=x1+0.5*(xk-x1), dx=x2-x1, y1=x(0), z1=x(1); |
fe4da5cc |
2594 | Double_t c1=x(2)*x1 - x(3), r1=sqrt(1.- c1*c1); |
2595 | Double_t c2=x(2)*x2 - x(3), r2=sqrt(1.- c2*c2); |
2596 | |
2597 | x(0) += dx*(c1+c2)/(r1+r2); |
2598 | x(1) += dx*(c1+c2)/(c1*r2 + c2*r1)*x(4); |
8c555625 |
2599 | |
fe4da5cc |
2600 | TMatrix F(5,5); F.UnitMatrix(); |
2601 | Double_t rr=r1+r2, cc=c1+c2, xx=x1+x2; |
2602 | F(0,2)= dx*(rr*xx + cc*(c1*x1/r1+c2*x2/r2))/(rr*rr); |
2603 | F(0,3)=-dx*(2*rr + cc*(c1/r1 + c2/r2))/(rr*rr); |
2604 | Double_t cr=c1*r2+c2*r1; |
2605 | F(1,2)= dx*x(4)*(cr*xx-cc*(r1*x2-c2*c1*x1/r1+r2*x1-c1*c2*x2/r2))/(cr*cr); |
2606 | F(1,3)=-dx*x(4)*(2*cr + cc*(c2*c1/r1-r1 + c1*c2/r2-r2))/(cr*cr); |
2607 | F(1,4)= dx*cc/cr; |
2608 | TMatrix tmp(F,TMatrix::kMult,C); |
2609 | C.Mult(tmp,TMatrix(TMatrix::kTransposed,F)); |
2610 | |
3c0f9266 |
2611 | fX=x2; |
fe4da5cc |
2612 | |
2613 | //Multiple scattering****************** |
3c0f9266 |
2614 | Double_t ey=x(2)*fX - x(3); |
fe4da5cc |
2615 | Double_t ex=sqrt(1-ey*ey); |
2616 | Double_t ez=x(4); |
2617 | TMatrix Q(5,5); Q=0.; |
2618 | Q(2,2)=ez*ez+ey*ey; Q(2,3)=-ex*ey; Q(2,4)=-ex*ez; |
2619 | Q(3,2)=Q(2,3); Q(3,3)= ez*ez+ex*ex; Q(3,4)=-ey*ez; |
2620 | Q(4,2)=Q(2,4); Q(4,3)= Q(3,4); Q(4,4)=1.; |
2621 | |
2622 | F=0; |
2623 | F(2,2)=-x(2)*ex; F(2,3)=-x(2)*ey; |
3c0f9266 |
2624 | F(3,2)=-ex*(x(2)*fX-ey); F(3,3)=-(1.+ x(2)*fX*ey - ey*ey); |
fe4da5cc |
2625 | F(4,2)=-ez*ex; F(4,3)=-ez*ey; F(4,4)=1.; |
2626 | |
2627 | tmp.Mult(F,Q); |
2628 | Q.Mult(tmp,TMatrix(TMatrix::kTransposed,F)); |
2629 | |
2630 | Double_t p2=GetPt()*GetPt()*(1.+x(4)*x(4)); |
2631 | Double_t beta2=p2/(p2 + pm*pm); |
3c0f9266 |
2632 | Double_t d=sqrt((x1-fX)*(x1-fX)+(y1-x(0))*(y1-x(0))+(z1-x(1))*(z1-x(1))); |
fe4da5cc |
2633 | d*=2.; |
2634 | Double_t theta2=14.1*14.1/(beta2*p2*1e6)*d/x0*rho; |
2635 | Q*=theta2; |
2636 | C+=Q; |
2637 | |
2638 | //Energy losses************************ |
2639 | Double_t dE=0.153e-3/beta2*(log(5940*beta2/(1-beta2)) - beta2)*d*rho; |
2640 | if (x1 < x2) dE=-dE; |
2641 | x(2)*=(1.- sqrt(p2+pm*pm)/p2*dE); |
8c555625 |
2642 | //x(3)*=(1.- sqrt(p2+pm*pm)/p2*dE); |
fe4da5cc |
2643 | |
3c0f9266 |
2644 | x1=fX; x2=xk; y1=x(0); z1=x(1); |
fe4da5cc |
2645 | c1=x(2)*x1 - x(3); r1=sqrt(1.- c1*c1); |
2646 | c2=x(2)*x2 - x(3); r2=sqrt(1.- c2*c2); |
2647 | |
2648 | x(0) += dx*(c1+c2)/(r1+r2); |
2649 | x(1) += dx*(c1+c2)/(c1*r2 + c2*r1)*x(4); |
2650 | |
2651 | F.UnitMatrix(); |
2652 | rr=r1+r2; cc=c1+c2; xx=x1+x2; |
2653 | F(0,2)= dx*(rr*xx + cc*(c1*x1/r1+c2*x2/r2))/(rr*rr); |
2654 | F(0,3)=-dx*(2*rr + cc*(c1/r1 + c2/r2))/(rr*rr); |
2655 | cr=c1*r2+c2*r1; |
2656 | F(1,2)= dx*x(4)*(cr*xx-cc*(r1*x2-c2*c1*x1/r1+r2*x1-c1*c2*x2/r2))/(cr*cr); |
2657 | F(1,3)=-dx*x(4)*(2*cr + cc*(c2*c1/r1-r1 + c1*c2/r2-r2))/(cr*cr); |
2658 | F(1,4)= dx*cc/cr; |
2659 | tmp.Mult(F,C); |
2660 | C.Mult(tmp,TMatrix(TMatrix::kTransposed,F)); |
2661 | |
3c0f9266 |
2662 | fX=x2; |
fe4da5cc |
2663 | |
2664 | return 1; |
2665 | } |
2666 | |
2667 | //_____________________________________________________________________________ |
2668 | void AliTPCtrack::PropagateToVertex(Double_t x0,Double_t rho,Double_t pm) |
2669 | { |
3c0f9266 |
2670 | //----------------------------------------------------------------- |
2671 | // This function propagates tracks to the "vertex". |
fe4da5cc |
2672 | // |
3c0f9266 |
2673 | // Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch |
2674 | //----------------------------------------------------------------- |
2675 | Double_t c=x(2)*fX - x(3); |
fe4da5cc |
2676 | Double_t tgf=-x(3)/(x(2)*x(0) + sqrt(1-c*c)); |
2677 | Double_t snf=tgf/sqrt(1.+ tgf*tgf); |
2678 | Double_t xv=(x(3)+snf)/x(2); |
2679 | PropagateTo(xv,x0,rho,pm); |
2680 | } |
2681 | |
2682 | //_____________________________________________________________________________ |
2683 | void AliTPCtrack::Update(const AliTPCcluster *c, Double_t chisq) |
2684 | { |
3c0f9266 |
2685 | //----------------------------------------------------------------- |
2686 | // This function associates a clusters with this track. |
fe4da5cc |
2687 | // |
3c0f9266 |
2688 | // Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch |
2689 | //----------------------------------------------------------------- |
fe4da5cc |
2690 | TMatrix H(2,5); H.UnitMatrix(); |
2691 | TMatrix Ht(TMatrix::kTransposed,H); |
2692 | TVector m(2); m(0)=c->fY; m(1)=c->fZ; |
2693 | TMatrix V(2,2); V(0,0)=c->fSigmaY2; V(0,1)=0.; V(1,0)=0.; V(1,1)=c->fSigmaZ2; |
2694 | |
2695 | TMatrix tmp(H,TMatrix::kMult,C); |
2696 | TMatrix R(tmp,TMatrix::kMult,Ht); R+=V; |
2697 | |
2698 | Double_t det=(Double_t)R(0,0)*R(1,1) - (Double_t)R(0,1)*R(1,0); |
2699 | R(0,1)=R(0,0); R(0,0)=R(1,1); R(1,1)=R(0,1); |
2700 | R(1,0)*=-1; R(0,1)=R(1,0); |
2701 | R*=1./det; |
2702 | |
2703 | //R.Invert(); |
2704 | |
2705 | TMatrix K(C,TMatrix::kMult,Ht); K*=R; |
2706 | |
2707 | TVector savex=x; |
2708 | x*=H; x-=m; x*=-1; x*=K; x+=savex; |
3c0f9266 |
2709 | if (TMath::Abs(x(2)*fX-x(3)) >= 0.999) { |
2710 | if (*this>4) cerr<<*this<<" AliTPCtrack warning: Filtering failed !\n"; |
fe4da5cc |
2711 | x=savex; |
2712 | return; |
2713 | } |
2714 | |
2715 | TMatrix saveC=C; |
2716 | C.Mult(K,tmp); C-=saveC; C*=-1; |
2717 | |
3c0f9266 |
2718 | fClusters.AddLast((AliTPCcluster*)c); |
2719 | fChi2 += chisq; |
fe4da5cc |
2720 | } |
2721 | |
2722 | //_____________________________________________________________________________ |
2723 | int AliTPCtrack::Rotate(Double_t alpha) |
2724 | { |
3c0f9266 |
2725 | //----------------------------------------------------------------- |
2726 | // This function rotates this track. |
fe4da5cc |
2727 | // |
3c0f9266 |
2728 | // Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch |
2729 | //----------------------------------------------------------------- |
fe4da5cc |
2730 | fAlpha += alpha; |
2731 | |
3c0f9266 |
2732 | Double_t x1=fX, y1=x(0); |
fe4da5cc |
2733 | Double_t ca=cos(alpha), sa=sin(alpha); |
3c0f9266 |
2734 | Double_t r1=x(2)*fX - x(3); |
fe4da5cc |
2735 | |
3c0f9266 |
2736 | fX = x1*ca + y1*sa; |
fe4da5cc |
2737 | x(0)=-x1*sa + y1*ca; |
2738 | x(3)=x(3)*ca + (x(2)*y1 + sqrt(1.- r1*r1))*sa; |
2739 | |
3c0f9266 |
2740 | Double_t r2=x(2)*fX - x(3); |
fe4da5cc |
2741 | if (TMath::Abs(r2) >= 0.999) { |
3c0f9266 |
2742 | if (*this>4) cerr<<*this<<" AliTPCtrack warning: Rotation failed !\n"; |
fe4da5cc |
2743 | return 0; |
2744 | } |
2745 | |
2746 | Double_t y0=x(0) + sqrt(1.- r2*r2)/x(2); |
2747 | if ((x(0)-y0)*x(2) >= 0.) { |
3c0f9266 |
2748 | if (*this>4) cerr<<*this<<" AliTPCtrack warning: Rotation failed !!!\n"; |
fe4da5cc |
2749 | return 0; |
2750 | } |
2751 | |
2752 | TMatrix F(5,5); F.UnitMatrix(); |
2753 | F(0,0)=ca; |
2754 | F(3,0)=x(2)*sa; |
2755 | F(3,2)=(y1 - r1*x1/sqrt(1.- r1*r1))*sa; |
2756 | F(3,3)= ca + sa*r1/sqrt(1.- r1*r1); |
2757 | TMatrix tmp(F,TMatrix::kMult,C); |
2758 | // Double_t dy2=C(0,0); |
2759 | C.Mult(tmp,TMatrix(TMatrix::kTransposed,F)); |
2760 | // C(0,0)+=dy2*sa*sa*r1*r1/(1.- r1*r1); |
2761 | // C(1,1)+=dy2*sa*sa*x(4)*x(4)/(1.- r1*r1); |
2762 | |
2763 | return 1; |
2764 | } |
2765 | |
2766 | //_____________________________________________________________________________ |
2767 | void AliTPCtrack::UseClusters() const |
2768 | { |
3c0f9266 |
2769 | //----------------------------------------------------------------- |
2770 | // This function marks clusters associated with this track. |
fe4da5cc |
2771 | // |
3c0f9266 |
2772 | // Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch |
2773 | //----------------------------------------------------------------- |
2774 | int num_of_clusters=fClusters.GetEntriesFast(); |
fe4da5cc |
2775 | for (int i=0; i<num_of_clusters; i++) { |
2776 | //if (i<=14) continue; |
3c0f9266 |
2777 | AliTPCcluster *c=(AliTPCcluster*)fClusters.UncheckedAt(i); |
fe4da5cc |
2778 | c->Use(); |
2779 | } |
2780 | } |
2781 | |
2782 | //_____________________________________________________________________________ |
2783 | Double_t AliTPCtrack::GetPredictedChi2(const AliTPCcluster *c) const |
2784 | { |
3c0f9266 |
2785 | //----------------------------------------------------------------- |
2786 | // This function calculates a predicted chi2 increment. |
fe4da5cc |
2787 | // |
3c0f9266 |
2788 | // Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch |
2789 | //----------------------------------------------------------------- |
fe4da5cc |
2790 | TMatrix H(2,5); H.UnitMatrix(); |
2791 | TVector m(2); m(0)=c->fY; m(1)=c->fZ; |
2792 | TMatrix V(2,2); V(0,0)=c->fSigmaY2; V(0,1)=0.; V(1,0)=0.; V(1,1)=c->fSigmaZ2; |
2793 | TVector res=x; res*=H; res-=m; //res*=-1; |
2794 | TMatrix tmp(H,TMatrix::kMult,C); |
2795 | TMatrix R(tmp,TMatrix::kMult,TMatrix(TMatrix::kTransposed,H)); R+=V; |
2796 | |
2797 | Double_t det=(Double_t)R(0,0)*R(1,1) - (Double_t)R(0,1)*R(1,0); |
2798 | if (TMath::Abs(det) < 1.e-10) { |
3c0f9266 |
2799 | if (*this>4) cerr<<*this<<" AliTPCtrack warning: Singular matrix !\n"; |
fe4da5cc |
2800 | return 1e10; |
2801 | } |
2802 | R(0,1)=R(0,0); R(0,0)=R(1,1); R(1,1)=R(0,1); |
2803 | R(1,0)*=-1; R(0,1)=R(1,0); |
2804 | R*=1./det; |
2805 | |
2806 | //R.Invert(); |
2807 | |
2808 | TVector r=res; |
2809 | res*=R; |
2810 | return r*res; |
2811 | } |
2812 | |
2813 | //_____________________________________________________________________________ |
3c0f9266 |
2814 | struct S { int lab; int max; }; |
2815 | int AliTPCtrack::GetLabel(int nrows) const |
fe4da5cc |
2816 | { |
3c0f9266 |
2817 | //----------------------------------------------------------------- |
2818 | // This function returns the track label. If label<0, this track is fake. |
fe4da5cc |
2819 | // |
3c0f9266 |
2820 | // Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch |
2821 | //----------------------------------------------------------------- |
2822 | int num_of_clusters=fClusters.GetEntriesFast(); |
2823 | S *s=new S[num_of_clusters]; |
fe4da5cc |
2824 | int i; |
3c0f9266 |
2825 | for (i=0; i<num_of_clusters; i++) s[i].lab=s[i].max=0; |
2826 | |
2827 | int lab=123456789; |
fe4da5cc |
2828 | for (i=0; i<num_of_clusters; i++) { |
3c0f9266 |
2829 | AliTPCcluster *c=(AliTPCcluster*)fClusters.UncheckedAt(i); |
8c555625 |
2830 | lab=TMath::Abs(c->fTracks[0]); |
fe4da5cc |
2831 | int j; |
3c0f9266 |
2832 | for (j=0; j<num_of_clusters; j++) |
fe4da5cc |
2833 | if (s[j].lab==lab || s[j].max==0) break; |
2834 | s[j].lab=lab; |
2835 | s[j].max++; |
2836 | } |
2837 | |
2838 | int max=0; |
2839 | for (i=0; i<num_of_clusters; i++) |
2840 | if (s[i].max>max) {max=s[i].max; lab=s[i].lab;} |
3c0f9266 |
2841 | |
2842 | delete[] s; |
2843 | |
8c555625 |
2844 | for (i=0; i<num_of_clusters; i++) { |
3c0f9266 |
2845 | AliTPCcluster *c=(AliTPCcluster*)fClusters.UncheckedAt(i); |
8c555625 |
2846 | if (TMath::Abs(c->fTracks[1]) == lab || |
2847 | TMath::Abs(c->fTracks[2]) == lab ) max++; |
2848 | } |
fe4da5cc |
2849 | |
2850 | if (1.-float(max)/num_of_clusters > 0.10) return -lab; |
2851 | |
3c0f9266 |
2852 | int tail=int(0.08*nrows); |
2853 | if (num_of_clusters < tail) return lab; |
fe4da5cc |
2854 | |
2855 | max=0; |
3c0f9266 |
2856 | for (i=1; i<=tail; i++) { |
2857 | AliTPCcluster *c=(AliTPCcluster*)fClusters.UncheckedAt(num_of_clusters-i); |
8c555625 |
2858 | if (lab == TMath::Abs(c->fTracks[0]) || |
2859 | lab == TMath::Abs(c->fTracks[1]) || |
2860 | lab == TMath::Abs(c->fTracks[2])) max++; |
fe4da5cc |
2861 | } |
3c0f9266 |
2862 | if (max < int(0.5*tail)) return -lab; |
fe4da5cc |
2863 | |
2864 | return lab; |
2865 | } |
2866 | |
2867 | //_____________________________________________________________________________ |
2868 | void AliTPCtrack::GetPxPyPz(Double_t& px, Double_t& py, Double_t& pz) const |
2869 | { |
3c0f9266 |
2870 | //----------------------------------------------------------------- |
2871 | // This function returns reconstructed track momentum in the global system. |
fe4da5cc |
2872 | // |
3c0f9266 |
2873 | // Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch |
2874 | //----------------------------------------------------------------- |
2875 | Double_t pt=TMath::Abs(GetPt()); // GeV/c |
2876 | Double_t r=x(2)*fX-x(3); |
fe4da5cc |
2877 | Double_t y0=x(0) + sqrt(1.- r*r)/x(2); |
2878 | px=-pt*(x(0)-y0)*x(2); //cos(phi); |
3c0f9266 |
2879 | py=-pt*(x(3)-fX*x(2)); //sin(phi); |
fe4da5cc |
2880 | pz=pt*x(4); |
2881 | Double_t tmp=px*TMath::Cos(fAlpha) - py*TMath::Sin(fAlpha); |
2882 | py=px*TMath::Sin(fAlpha) + py*TMath::Cos(fAlpha); |
2883 | px=tmp; |
2884 | } |
2885 | |
2886 | //_____________________________________________________________________________ |
3c0f9266 |
2887 | Double_t AliTPCtrack::GetdEdX(Double_t low, Double_t up) const { |
2888 | //----------------------------------------------------------------- |
2889 | // This funtion calculates dE/dX within the "low" and "up" cuts. |
fe4da5cc |
2890 | // |
3c0f9266 |
2891 | // Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch |
2892 | //----------------------------------------------------------------- |
2893 | int ncl=fClusters.GetEntriesFast(); |
2894 | int n=0; |
2895 | Double_t *q=new Double_t[ncl]; |
2896 | int i; |
2897 | for (i=0; i<ncl; i++) { |
2898 | AliTPCcluster *cl=(AliTPCcluster*)(fClusters.UncheckedAt(i)); |
2899 | // if (cl->fdEdX > 3000) continue; |
2900 | if (cl->fdEdX <= 0) continue; |
2901 | q[n++]=cl->fdEdX; |
2902 | } |
2903 | |
2904 | //stupid sorting |
2905 | int swap; |
2906 | do { |
2907 | swap=0; |
2908 | for (i=0; i<n-1; i++) { |
2909 | if (q[i]<=q[i+1]) continue; |
2910 | Double_t tmp=q[i]; q[i]=q[i+1]; q[i+1]=tmp; |
2911 | swap++; |
2912 | } |
2913 | } while (swap); |
2914 | |
2915 | int nl=int(low*n), nu=int(up *n); |
2916 | Double_t dedx=0.; |
2917 | for (i=nl; i<=nu; i++) dedx += q[i]; |
2918 | dedx /= (nu-nl+1); |
2919 | return dedx; |
2920 | } |
2921 | |
2922 | //_________________________________________________________________________ |
2923 | // |
2924 | // Classes for internal tracking use |
2925 | //_________________________________________________________________________ |
2926 | void AliTPCRow::InsertCluster(const AliTPCcluster* c) { |
2927 | //----------------------------------------------------------------------- |
2928 | // Insert a cluster into this pad row in accordence with its y-coordinate |
2929 | // |
2930 | // Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch |
2931 | //----------------------------------------------------------------------- |
fe4da5cc |
2932 | if (num_of_clusters==MAX_CLUSTER_PER_ROW) { |
2933 | cerr<<"AliTPCRow::InsertCluster(): Too many clusters !\n"; return; |
2934 | } |
2935 | if (num_of_clusters==0) {clusters[num_of_clusters++]=c; return;} |
2936 | int i=Find(c->fY); |
2937 | memmove(clusters+i+1 ,clusters+i,(num_of_clusters-i)*sizeof(AliTPCcluster*)); |
2938 | clusters[i]=c; num_of_clusters++; |
2939 | } |
2940 | |
3c0f9266 |
2941 | int AliTPCRow::Find(Double_t y) const { |
2942 | //----------------------------------------------------------------------- |
2943 | // Return the index of the nearest cluster |
fe4da5cc |
2944 | // |
3c0f9266 |
2945 | // Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch |
2946 | //----------------------------------------------------------------------- |
fe4da5cc |
2947 | if (y <= clusters[0]->fY) return 0; |
2948 | if (y > clusters[num_of_clusters-1]->fY) return num_of_clusters; |
2949 | int b=0, e=num_of_clusters-1, m=(b+e)/2; |
2950 | for (; b<e; m=(b+e)/2) { |
2951 | if (y > clusters[m]->fY) b=m+1; |
2952 | else e=m; |
2953 | } |
2954 | return m; |
2955 | } |
8c555625 |
2956 | |