Line data Source code
1 : /**************************************************************************
2 : * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3 : * *
4 : * Author: The ALICE Off-line Project. *
5 : * Contributors are mentioned in the code where appropriate. *
6 : * *
7 : * Permission to use, copy, modify and distribute this software and its *
8 : * documentation strictly for non-commercial purposes is hereby granted *
9 : * without fee, provided that the above copyright notice appears in all *
10 : * copies and that both the copyright notice and this permission notice *
11 : * appear in the supporting documentation. The authors make no claims *
12 : * about the suitability of this software for any purpose. It is *
13 : * provided "as is" without express or implied warranty. *
14 : **************************************************************************/
15 :
16 :
17 : /// \class AliTPCPRF2D
18 : /// \brief Pad response function object in two dimesions
19 : ///
20 : /// This class contains the basic functions for the
21 : /// calculation of PRF according generic charge distribution
22 : /// In Update function object calculate table of response function
23 : /// in discrete x and y position
24 : /// This table is used for interpolation od response function in any position
25 : /// (function GetPRF)
26 : ///
27 : /// \author Marian Ivanov, Uni. of Bratislava, ivanov@fmph.uniba.sk
28 :
29 : #include <Riostream.h>
30 : #include <TCanvas.h>
31 : #include <TClass.h>
32 : #include <TF2.h>
33 : #include <TH1.h>
34 : #include <TMath.h>
35 : #include <TPad.h>
36 : #include <TPaveText.h>
37 : #include <TStyle.h>
38 : #include <TText.h>
39 : #include <string.h>
40 : #include "TBuffer.h"
41 :
42 : #include "AliH2F.h"
43 : #include "AliTPCPRF2D.h"
44 :
45 :
46 : extern TStyle * gStyle;
47 :
48 : const Double_t AliTPCPRF2D::fgkDegtoRad = 0.01745329251994;
49 : const Double_t AliTPCPRF2D::fgkSQRT12=3.464101;
50 : const Int_t AliTPCPRF2D::fgkNPRF = 100;
51 :
52 :
53 : static Double_t FunGauss2D(const Double_t *const x, const Double_t *const par)
54 : {
55 : /// Gauss function -needde by the generic function object
56 :
57 0 : return ( TMath::Exp(-(x[0]*x[0])/(2*par[0]*par[0]))*
58 0 : TMath::Exp(-(x[1]*x[1])/(2*par[1]*par[1])));
59 :
60 : }
61 :
62 : static Double_t FunCosh2D(const Double_t *const x, const Double_t *const par)
63 : {
64 : /// Cosh function -needde by the generic function object
65 :
66 0 : return ( 1/(TMath::CosH(3.14159*x[0]/(2*par[0]))*
67 0 : TMath::CosH(3.14159*x[1]/(2*par[1]))));
68 : }
69 :
70 : static Double_t FunGati2D(const Double_t *const x, const Double_t *const par)
71 : {
72 : /// Gati function -needde by the generic function object
73 :
74 0 : Float_t k3=par[1];
75 0 : Float_t k3R=TMath::Sqrt(k3);
76 0 : Float_t k2=(TMath::Pi()/2)*(1-k3R/2.);
77 0 : Float_t k1=k2*k3R/(4*TMath::ATan(k3R));
78 0 : Float_t l=x[0]/par[0];
79 0 : Float_t tan2=TMath::TanH(k2*l);
80 0 : tan2*=tan2;
81 0 : Float_t res = k1*(1-tan2)/(1+k3*tan2);
82 : //par[4] = is equal to k3Y
83 0 : k3=par[4];
84 0 : k3R=TMath::Sqrt(k3);
85 0 : k2=(TMath::Pi()/2)*(1-k3R/2.);
86 0 : k1=k2*k3R/(4*TMath::ATan(k3R));
87 0 : l=x[1]/par[0];
88 0 : tan2=TMath::TanH(k2*l);
89 0 : tan2*=tan2;
90 0 : res = res*k1*(1-tan2)/(1+k3*tan2);
91 0 : return res;
92 : }
93 :
94 : ///////////////////////////////////////////////////////////////////////////
95 : ///////////////////////////////////////////////////////////////////////////
96 :
97 : /// \cond CLASSIMP
98 24 : ClassImp(AliTPCPRF2D)
99 : /// \endcond
100 :
101 : AliTPCPRF2D::AliTPCPRF2D()
102 3 : :TObject(),
103 3 : fcharge(0),
104 3 : fY1(0.),
105 3 : fY2(0.),
106 3 : fNYdiv(0),
107 3 : fNChargeArray(0),
108 3 : fChargeArray(0),
109 3 : fHeightFull(0.),
110 3 : fHeightS(0.),
111 3 : fShiftY(0.),
112 3 : fWidth(0.),
113 3 : fK(0.),
114 3 : fNPRF(0),
115 3 : fNdiv(5),
116 3 : fDStep(0.),
117 3 : fKNorm(1.),
118 3 : fInteg(0.),
119 3 : fGRF(0),
120 3 : fK3X(0.),
121 3 : fK3Y(0.),
122 3 : fPadDistance(0.),
123 3 : fOrigSigmaX(0.),
124 3 : fOrigSigmaY(0.),
125 3 : fChargeAngle(0.),
126 3 : fPadAngle(0.),
127 3 : fSigmaX(0.),
128 3 : fSigmaY(0.),
129 3 : fMeanX(0.),
130 3 : fMeanY(0.),
131 3 : fInterX(0),
132 3 : fInterY(0),
133 3 : fCurrentY(0.),
134 3 : fDYtoWire(0.),
135 3 : fDStepM1(0.)
136 15 : {
137 : //default constructor for response function object
138 :
139 3 : fNPRF =fgkNPRF ;
140 36 : for(Int_t i=0;i<5;i++){
141 15 : funParam[i]=0.;
142 15 : fType[i]=0;
143 : }
144 :
145 :
146 : //chewron default values
147 3 : SetPad(0.8,0.8);
148 3 : SetChevron(0.2,0.0,1.0);
149 3 : SetY(-0.2,0.2,2);
150 3 : SetInterpolationType(2,0);
151 6 : }
152 :
153 : AliTPCPRF2D::~AliTPCPRF2D()
154 18 : {
155 9 : if (fChargeArray!=0) delete [] fChargeArray;
156 6 : if (fGRF !=0 ) fGRF->Delete();
157 9 : }
158 :
159 : void AliTPCPRF2D::SetY(Float_t y1, Float_t y2, Int_t nYdiv)
160 : {
161 : /// set virtual line position
162 : /// first and last line and number of lines
163 :
164 6 : fNYdiv = nYdiv;
165 3 : fY1=y1;
166 3 : fY2=y2;
167 3 : }
168 :
169 : void AliTPCPRF2D::SetPad(Float_t width, Float_t height)
170 : {
171 : /// set base chevron parameters
172 :
173 6 : fHeightFull=height;
174 3 : fWidth=width;
175 3 : }
176 : void AliTPCPRF2D::SetChevron(Float_t hstep,
177 : Float_t shifty,
178 : Float_t fac)
179 : {
180 : /// set shaping of chewron parameters
181 :
182 6 : fHeightS=hstep;
183 3 : fShiftY=shifty;
184 3 : fK=fac;
185 3 : }
186 :
187 : void AliTPCPRF2D::SetChParam(Float_t width, Float_t height,
188 : Float_t hstep, Float_t shifty, Float_t fac)
189 : {
190 0 : SetPad(width,height);
191 0 : SetChevron(hstep,shifty,fac);
192 0 : }
193 :
194 :
195 : Float_t AliTPCPRF2D::GetPRF(Float_t xin, Float_t yin)
196 : {
197 : /// function which return pad response
198 : /// for the charge in distance xin
199 : /// return cubic aproximation of PRF or PRF at nearest virtual wire
200 :
201 15000000 : if (fChargeArray==0) return 0;
202 : //transform position to "wire position"
203 7500000 : Float_t y=fDYtoWire*(yin-fY1);
204 7500000 : if (fNYdiv == 1) y=fY1;
205 : //normaly it find nearest line charge
206 7500000 : if (fInterY ==0){
207 7500000 : Int_t i=Int_t(0.5+y);
208 8387500 : if (y<0) i=Int_t(-0.5+y);
209 15415000 : if ((i<0) || (i>=fNYdiv) ) return 0;
210 6662500 : fcharge = &(fChargeArray[i*fNPRF]);
211 6662500 : return GetPRFActiv(xin);
212 : }
213 : //make interpolation from more fore lines
214 0 : Int_t i= Int_t(y);
215 : Float_t res;
216 0 : if ((i<0) || (i>=fNYdiv) ) return 0;
217 : Float_t z0=0;
218 : Float_t z1=0;
219 : Float_t z2=0;
220 : Float_t z3=0;
221 0 : if (i>0) {
222 0 : fcharge =&(fChargeArray[(i-1)*fNPRF]);
223 0 : z0 = GetPRFActiv(xin);
224 0 : }
225 0 : fcharge =&(fChargeArray[i*fNPRF]);
226 0 : z1=GetPRFActiv(xin);
227 0 : if ((i+1)<fNYdiv){
228 0 : fcharge =&(fChargeArray[(i+1)*fNPRF]);
229 0 : z2 = GetPRFActiv(xin);
230 0 : }
231 0 : if ((i+2)<fNYdiv){
232 0 : fcharge =&(fChargeArray[(i+2)*fNPRF]);
233 0 : z3 = GetPRFActiv(xin);
234 0 : }
235 : Float_t a,b,c,d,k,l;
236 : a=z1;
237 0 : b=(z2-z0)/2.;
238 0 : k=z2-a-b;
239 0 : l=(z3-z1)/2.-b;
240 0 : d=l-2*k;
241 0 : c=k-d;
242 0 : Float_t dy=y-Float_t(i);
243 :
244 0 : res = a+b*dy+c*dy*dy+d*dy*dy*dy;
245 : return res;
246 7500000 : }
247 :
248 :
249 : Float_t AliTPCPRF2D::GetPRFActiv(Float_t xin)
250 : {
251 : /// GEt response function on given charege line
252 : /// return spline aproximaton
253 :
254 13325000 : Float_t x = (xin*fDStepM1)+fNPRF/2;
255 6662500 : Int_t i = Int_t(x);
256 :
257 12891266 : if ( (i>1) && ((i+2)<fNPRF)) {
258 : Float_t a,b,c,d,k,l;
259 5821021 : a = fcharge[i];
260 5821021 : b = (fcharge[i+1]-fcharge[i-1])*0.5;
261 5821021 : k = fcharge[i+1]-a-b;
262 5821021 : l = (fcharge[i+2]-fcharge[i])*0.5-b;
263 5821021 : d=l-2.*k;
264 5821021 : c=k-d;
265 5821021 : Float_t dx=x-Float_t(i);
266 5821021 : Float_t res = a+b*dx+c*dx*dx+d*dx*dx*dx;
267 : return res;
268 : }
269 841479 : else return 0;
270 6662500 : }
271 :
272 :
273 : Float_t AliTPCPRF2D::GetGRF(Float_t xin, Float_t yin)
274 : {
275 : /// function which returnoriginal charge distribution
276 : /// this function is just normalised for fKnorm
277 :
278 0 : if (GetGRF() != 0 )
279 0 : return fKNorm*GetGRF()->Eval(xin,yin)/fInteg;
280 : else
281 0 : return 0.;
282 0 : }
283 :
284 :
285 : void AliTPCPRF2D::SetParam( TF2 *const GRF, Float_t kNorm,
286 : Float_t sigmaX, Float_t sigmaY)
287 : {
288 : /// adjust parameters of the original charge distribution
289 : /// and pad size parameters
290 :
291 0 : if (fGRF !=0 ) fGRF->Delete();
292 0 : fGRF = GRF;
293 0 : fKNorm = kNorm;
294 : //sprintf(fType,"User");
295 0 : snprintf(fType,5,"User");
296 0 : if (sigmaX ==0) sigmaX=(fWidth*(1+TMath::Abs(fK)))/fgkSQRT12;
297 0 : if (sigmaY ==0) sigmaY=(fWidth*(1+TMath::Abs(fK)))/fgkSQRT12;
298 0 : fOrigSigmaX=sigmaX;
299 0 : fOrigSigmaY=sigmaY;
300 : Double_t estimsigma =
301 0 : TMath::Sqrt(sigmaX*sigmaX+(fWidth*fWidth*(1+TMath::Abs(fK))/12)+
302 0 : TMath::Tan(fPadAngle*fgkDegtoRad)*TMath::Tan(fPadAngle*fgkDegtoRad)*fHeightFull*fHeightFull/12);
303 0 : if (estimsigma < 5*sigmaX) {
304 0 : fDStep = estimsigma/10.;
305 0 : fNPRF = Int_t(estimsigma*8./fDStep);
306 0 : }
307 : else{
308 0 : fDStep = sigmaX;
309 0 : Double_t width = fWidth*(1+TMath::Abs(fK))+TMath::Abs(TMath::Tan(fPadAngle*fgkDegtoRad))*fHeightFull;
310 0 : fNPRF = Int_t((width+8.*sigmaX)/fDStep);
311 : };
312 :
313 0 : }
314 :
315 :
316 : void AliTPCPRF2D::SetGauss(Float_t sigmaX, Float_t sigmaY,
317 : Float_t kNorm)
318 : {
319 : /// set parameters for Gauss generic charge distribution
320 :
321 0 : fKNorm = kNorm;
322 0 : fOrigSigmaX=sigmaX;
323 0 : fOrigSigmaY=sigmaY;
324 : //sprintf(fType,"Gauss");
325 0 : snprintf(fType,5,"Gauss");
326 0 : if (fGRF !=0 ) fGRF->Delete();
327 0 : fGRF = new TF2("FunGauss2D",FunGauss2D,-5.,5.,-5.,5.,4);
328 :
329 0 : funParam[0]=sigmaX;
330 0 : funParam[1]=sigmaY;
331 0 : funParam[2]=fK;
332 0 : funParam[3]=fHeightS;
333 :
334 0 : fGRF->SetParameters(funParam);
335 : Double_t estimsigma =
336 0 : TMath::Sqrt(sigmaX*sigmaX+(fWidth*fWidth*(1+TMath::Abs(fK))/12)+
337 0 : TMath::Tan(fPadAngle)*TMath::Tan(fPadAngle*fgkDegtoRad)*fHeightFull*fHeightFull/12);
338 0 : if (estimsigma < 5*sigmaX) {
339 0 : fDStep = estimsigma/10.;
340 0 : fNPRF = Int_t(estimsigma*8./fDStep);
341 0 : }
342 : else{
343 0 : fDStep = sigmaX;
344 0 : Double_t width = fWidth*(1+TMath::Abs(fK))+TMath::Abs(TMath::Tan(fPadAngle*fgkDegtoRad))*fHeightFull;
345 0 : fNPRF = Int_t((width+8.*sigmaX)/fDStep);
346 : };
347 :
348 :
349 0 : }
350 : void AliTPCPRF2D::SetCosh(Float_t sigmaX, Float_t sigmaY,
351 : Float_t kNorm)
352 : {
353 : /// set parameters for Cosh generic charge distribution
354 :
355 0 : fKNorm = kNorm;
356 0 : fOrigSigmaX=sigmaX;
357 0 : fOrigSigmaY=sigmaY;
358 : // sprintf(fType,"Cosh");
359 0 : snprintf(fType,5,"Cosh");
360 0 : if (fGRF !=0 ) fGRF->Delete();
361 0 : fGRF = new TF2("FunCosh2D", FunCosh2D,-5.,5.,-5.,5.,4);
362 0 : funParam[0]=sigmaX;
363 0 : funParam[1]=sigmaY;
364 0 : funParam[2]=fK;
365 0 : funParam[3]=fHeightS;
366 0 : fGRF->SetParameters(funParam);
367 :
368 0 : Double_t estimsigma = TMath::Sqrt(sigmaX*sigmaX+fWidth*fWidth*(1+TMath::Abs(fK))/12);
369 0 : if (estimsigma < 5*sigmaX) {
370 0 : fDStep = estimsigma/10.;
371 0 : fNPRF = Int_t(estimsigma*8./fDStep);
372 0 : }
373 : else{
374 0 : fDStep = sigmaX;
375 0 : fNPRF = Int_t((1.2*fWidth*(1+TMath::Abs(fK))+8.*sigmaX)/fDStep);
376 : };
377 :
378 0 : }
379 :
380 : void AliTPCPRF2D::SetGati(Float_t K3X, Float_t K3Y,
381 : Float_t padDistance,
382 : Float_t kNorm)
383 : {
384 : /// set parameters for Gati generic charge distribution
385 :
386 0 : fKNorm = kNorm;
387 0 : fK3X=K3X;
388 0 : fK3Y=K3Y;
389 0 : fPadDistance=padDistance;
390 : //sprintf(fType,"Gati");
391 0 : snprintf(fType,5,"Gati");
392 0 : if (fGRF !=0 ) fGRF->Delete();
393 0 : fGRF = new TF2("FunGati2D", FunGati2D,-5.,5.,-5.,5.,5);
394 :
395 0 : funParam[0]=padDistance;
396 0 : funParam[1]=K3X;
397 0 : funParam[2]=fK;
398 0 : funParam[3]=fHeightS;
399 0 : funParam[4]=K3Y;
400 0 : fGRF->SetParameters(funParam);
401 0 : fOrigSigmaX=padDistance;
402 0 : fOrigSigmaY=padDistance;
403 0 : Float_t sigmaX = fOrigSigmaX;
404 0 : Double_t estimsigma = TMath::Sqrt(sigmaX*sigmaX+fWidth*fWidth*(1+TMath::Abs(fK))/12);
405 0 : if (estimsigma < 5*sigmaX) {
406 0 : fDStep = estimsigma/10.;
407 0 : fNPRF = Int_t(estimsigma*8./fDStep);
408 0 : }
409 : else{
410 0 : fDStep = sigmaX;
411 0 : fNPRF = Int_t((1.2*fWidth*(1+TMath::Abs(fK))+8.*sigmaX)/fDStep);
412 : };
413 0 : }
414 :
415 :
416 :
417 : void AliTPCPRF2D::Update()
418 : {
419 : /// update fields with interpolated values for
420 : /// PRF calculation
421 :
422 0 : if ( fGRF == 0 ) return;
423 : //initialize interpolated values to 0
424 : Int_t i;
425 0 : if (fChargeArray!=0) delete [] fChargeArray;
426 0 : fChargeArray = new Float_t[fNPRF*fNYdiv];
427 0 : fNChargeArray = fNPRF*fNYdiv;
428 0 : for (i =0; i<fNPRF*fNYdiv;i++) fChargeArray[i] = 0;
429 : //firstly calculate total integral of charge
430 :
431 : ////////////////////////////////////////////////////////
432 : //I'm waiting for normal integral
433 : //in this moment only sum
434 0 : Float_t x2= 4*fOrigSigmaX;
435 0 : Float_t y2= 4*fOrigSigmaY;
436 0 : Float_t dx = fOrigSigmaX/Float_t(fNdiv*6);
437 0 : Float_t dy = fOrigSigmaY/Float_t(fNdiv*6);
438 0 : Int_t nx = Int_t(0.5+x2/dx);
439 0 : Int_t ny = Int_t(0.5+y2/dy);
440 : Int_t ix,iy;
441 0 : fInteg = 0;
442 : Double_t dInteg =0;
443 0 : for (ix=-nx;ix<=nx;ix++)
444 0 : for ( iy=-ny;iy<=ny;iy++)
445 0 : dInteg+=fGRF->Eval(Float_t(ix)*dx,Float_t(iy)*dy)*dx*dy;
446 : /////////////////////////////////////////////////////
447 0 : fInteg =dInteg;
448 0 : if ( fInteg == 0 ) fInteg = 1;
449 :
450 0 : for (i=0; i<fNYdiv; i++){
451 0 : if (fNYdiv == 1) fCurrentY = fY1;
452 : else
453 0 : fCurrentY = fY1+Double_t(i)*(fY2-fY1)/Double_t(fNYdiv-1);
454 0 : fcharge = &(fChargeArray[i*fNPRF]);
455 0 : Update1();
456 : }
457 : //calculate conversion coefitient to convert position to virtual wire
458 0 : fDYtoWire=Float_t(fNYdiv-1)/(fY2-fY1);
459 0 : fDStepM1=1/fDStep;
460 0 : UpdateSigma();
461 0 : }
462 :
463 : void AliTPCPRF2D::Update1()
464 : {
465 : /// update fields with interpolated values for
466 : /// PRF calculation for given charge line
467 :
468 : Int_t i;
469 0 : Double_t cos = TMath::Cos(fChargeAngle);
470 0 : Double_t sin = TMath::Sin(fChargeAngle);
471 : const Double_t kprec =0.00000001;
472 : //integrate charge over pad for different distance of pad
473 0 : for (i =0; i<fNPRF;i++){
474 : //x in cm fWidth in cm
475 : //calculate integral
476 0 : Double_t xch = fDStep * (Double_t)(i-fNPRF/2);
477 0 : fcharge[i]=0;
478 : Double_t k=1;
479 :
480 :
481 0 : for (Double_t ym=-fHeightFull/2.-fShiftY; ym<fHeightFull/2.-kprec;ym+=fHeightS){
482 0 : Double_t y2chev=TMath::Min((ym+fHeightS),Double_t(fHeightFull/2.)); // end of chevron step
483 : Double_t y1chev= ym; //beginning of chevron step
484 0 : Double_t y2 = TMath::Min(y2chev,fCurrentY+3.5*fOrigSigmaY);
485 0 : Double_t y1 = TMath::Max((y1chev),Double_t(-fHeightFull/2.));
486 0 : y1 = TMath::Max(y1chev,fCurrentY-3.5*fOrigSigmaY);
487 :
488 0 : Double_t x0 = fWidth*(-1.-(Double_t(k)*fK))*0.5+ym*TMath::Tan(fPadAngle*fgkDegtoRad);
489 0 : Double_t kx = Double_t(k)*(fK*fWidth)/fHeightS;
490 0 : kx = TMath::Tan(TMath::ATan(kx))+TMath::Tan(fPadAngle*fgkDegtoRad);
491 :
492 0 : Int_t ny = TMath::Max(Int_t(fNdiv*TMath::Exp(-(y1-fCurrentY)*(y1-fCurrentY)/(2*fOrigSigmaY*fOrigSigmaY))),4);
493 0 : Double_t dy = TMath::Min(fOrigSigmaY/Double_t(ny),y2-y1);
494 : Double_t ndy = dy;
495 :
496 : //loop over different y strips with variable step size dy
497 0 : if (y2>(y1+kprec)) for (Double_t y = y1; y<y2+kprec;){
498 : //new step SIZE
499 :
500 0 : ny = TMath::Max(Int_t(fNdiv*TMath::Exp(-(y-fCurrentY)*(y-fCurrentY)/(2*fOrigSigmaY*fOrigSigmaY))),5);
501 0 : ndy = fOrigSigmaY/Double_t(ny);
502 0 : if (ndy>(y2-y-dy)) {
503 : ndy =y2-y-dy;
504 0 : if (ndy<kprec) ndy=2*kprec; //calculate new delta y
505 : }
506 : //
507 : Double_t sumch=0;
508 : //calculation of x borders and initial step
509 0 : Double_t deltay = (y-y1chev);
510 :
511 0 : Double_t xp1 = x0+deltay*kx;
512 : //x begining of pad at position y
513 0 : Double_t xp2 =xp1+fWidth; //x end of pad at position y
514 0 : Double_t xp3 =xp1+kx*dy; //...at position y+dy
515 0 : Double_t xp4 =xp2+kx*dy; //..
516 :
517 0 : Double_t x1 = TMath::Min(xp1,xp3);
518 0 : x1 = TMath::Max(xp1,xch-3.5*fOrigSigmaX); //beging of integration
519 0 : Double_t x2 = TMath::Max(xp2,xp4);
520 0 : x2 = TMath::Min(xp2+dy*kx,xch+3.5*fOrigSigmaX); //end of integration
521 :
522 0 : Int_t nx = TMath::Max(Int_t(fNdiv*TMath::Exp(-(x1-xch)*(x1-xch)/(2*fOrigSigmaX*fOrigSigmaX))*
523 0 : TMath::Exp(-(y1-fCurrentY)*(y1-fCurrentY)/(2*fOrigSigmaY*fOrigSigmaY))),2);
524 0 : Double_t dx = TMath::Min(fOrigSigmaX/Double_t(nx),x2-x1)/5.; //on the border more iteration
525 : Double_t ndx=dx;
526 :
527 0 : if (x2>(x1+kprec)) {
528 0 : for (Double_t x = x1; x<x2+kprec ;){
529 : //new step SIZE
530 0 : nx = TMath::Max(Int_t(fNdiv*TMath::Exp(-(x-xch)*(x-xch)/(2*fOrigSigmaX*fOrigSigmaX))),3);
531 0 : ndx = fOrigSigmaX/Double_t(nx);
532 0 : if (ndx>(x2-x-dx)) {
533 : ndx =x2-x-dx;
534 0 : }
535 0 : if ( ( (x+dx+ndx)<TMath::Max(xp3,xp1)) || ( (x+dx+ndx)>TMath::Min(xp4,xp2))) {
536 0 : ndx/=5.;
537 0 : }
538 0 : if (ndx<kprec) ndx=2*kprec;
539 : //INTEGRAL APROXIMATION
540 : Double_t ddx,ddy,dddx,dddy;
541 0 : ddx = xch-(x+dx/2.);
542 0 : ddy = fCurrentY-(y+dy/2.);
543 0 : dddx = cos*ddx-sin*ddy;
544 0 : dddy = sin*ddx+cos*ddy;
545 0 : Double_t z0=fGRF->Eval(dddx,dddy); //middle point
546 :
547 : ddx = xch-(x+dx/2.);
548 0 : ddy = fCurrentY-(y);
549 0 : dddx = cos*ddx-sin*ddy;
550 0 : dddy = sin*ddx+cos*ddy;
551 0 : Double_t z1=fGRF->Eval(dddx,dddy); //point down
552 :
553 : ddx = xch-(x+dx/2.);
554 0 : ddy = fCurrentY-(y+dy);
555 0 : dddx = cos*ddx-sin*ddy;
556 0 : dddy = sin*ddx+cos*ddy;
557 0 : Double_t z3=fGRF->Eval(dddx,dddy); //point up
558 :
559 0 : ddx = xch-(x);
560 0 : ddy = fCurrentY-(y+dy/2.);
561 0 : dddx = cos*ddx-sin*ddy;
562 0 : dddy = sin*ddx+cos*ddy;
563 0 : Double_t z2=fGRF->Eval(dddx,dddy); //point left
564 :
565 0 : ddx = xch-(x+dx);
566 0 : ddy = fCurrentY-(y+dy/2.);
567 0 : dddx = cos*ddx-sin*ddy;
568 0 : dddy = sin*ddx+cos*ddy;
569 0 : Double_t z4=fGRF->Eval(dddx,dddy); //point right
570 :
571 :
572 0 : if (z0<0) {z0=0;z1=0;z2=0;z3=0;z4=0;}
573 :
574 0 : Double_t f2x= (z3+z1-2*z0)*4.;//second derivation in y
575 0 : Double_t f2y= (z2+z4-2*z0)*4.;//second derivation in x
576 0 : Double_t f1y= (z3-z1);
577 : Double_t z ;
578 0 : z = (z0+f2x/6.+f2y/6.);//second order aproxiation of integral
579 0 : if (kx>kprec){ //positive derivation
580 0 : if (x<(xp1+dy*kx)){ //calculate volume at left border
581 : Double_t xx1 = x;
582 0 : Double_t xx2 = TMath::Min(x+dx,xp1+dy*kx);
583 0 : Double_t yy1 = y+(xx1-xp1)/kx;
584 0 : Double_t yy2 = TMath::Min(y+(xx2-xp1)/kx,y+dy);
585 : z=z0;
586 0 : if (yy2<y+dy) {
587 0 : z-= z0*(y+dy-yy2)/dy; //constant part rectangle
588 0 : z-= f1y*(xx2-xx1)*(y+dy-yy2)*(y+dy-yy2)/(2.*dx*dy);
589 0 : }
590 0 : z-=z0*(xx2-xx1)*(yy2-yy1)/(2*dx*dy); //constant part rectangle
591 :
592 0 : }
593 0 : if (x>xp2){ //calculate volume at right border
594 : Double_t xx1 = x;
595 : Double_t xx2 = x+dx;
596 0 : Double_t yy1 = y+(xx1-xp2)/kx;
597 0 : Double_t yy2 = y+(xx2-xp2)/kx;
598 : z=z0;
599 : //rectangle part
600 0 : z-=z0*(yy1-y)/dy; //constant part
601 0 : z-=f1y*(xx2-xx1)*(yy1-y)*(yy1-y)/(2*dx*dy);
602 : //triangle part
603 0 : z-=z0*(xx2-xx1)*(yy2-yy1)/(2*dx*dy); //constant part
604 0 : }
605 : }
606 0 : if (kx<-kprec){ //negative derivation
607 0 : if (x<(xp1+dy*kx)){ //calculate volume at left border
608 : Double_t xx1 = x;
609 0 : Double_t xx2 = TMath::Min(x+dx,xp3-dy/kx);
610 0 : Double_t yy1 = y+(xx1-xp1)/kx;
611 0 : Double_t yy2 = TMath::Max(y,yy1+(xx2-xx1)/kx); //yy2<yy1
612 : z = z0;
613 0 : z-= z0*(yy2-y)/dy; // constant part rectangle
614 0 : z-= f1y*(xx2-xx1)*(yy2-y)*(yy2-y)/(2.*dx*dy);
615 0 : z-=z0*(xx2-xx1)*(yy1-yy2)/(2*dx*dy); //constant part triangle
616 0 : }
617 0 : if (x>xp2){ //calculate volume at right border
618 0 : Double_t xx1 = TMath::Max(x,xp2+dy*kx);
619 : Double_t xx2 = x+dx;
620 0 : Double_t yy1 = TMath::Min(y+dy,y-(xp2-xx1)/kx);
621 0 : Double_t yy2 = y-(xp2-xx2)/kx;
622 : z=z0;
623 0 : z-=z0*(yy2-y)/dy; //constant part rextangle
624 0 : z-= f1y*(xx2-xx1)*(yy2-y)*(yy2-y)/(2.*dx*dy);
625 0 : z-=z0*(xx2-xx1)*(yy1-yy2)/(2*dx*dy); //constant part triangle
626 0 : }
627 : }
628 :
629 0 : if (z>0.) sumch+=fKNorm*z*dx*dy/fInteg;
630 :
631 : x+=dx;
632 : dx = ndx;
633 : }; //loop over x
634 0 : fcharge[i]+=sumch;
635 0 : }//if x2>x1
636 0 : y+=dy;
637 : dy =ndy;
638 0 : }//step over different y
639 0 : k*=-1.;
640 : }//step over chevron
641 :
642 : }//step over different points on line NPRF
643 0 : }
644 :
645 : void AliTPCPRF2D::UpdateSigma()
646 : {
647 : /// calulate effective sigma X and sigma y of PRF
648 :
649 0 : fMeanX = 0;
650 0 : fMeanY = 0;
651 0 : fSigmaX = 0;
652 0 : fSigmaY = 0;
653 :
654 : Float_t sum =0;
655 : Int_t i;
656 : Float_t x,y;
657 :
658 0 : for (i=-1; i<=fNYdiv; i++){
659 0 : if (fNYdiv == 1) y = fY1;
660 : else
661 0 : y = fY1+Float_t(i)*(fY2-fY1)/Float_t(fNYdiv-1);
662 0 : for (x =-fNPRF*fDStep; x<fNPRF*fDStep;x+=fDStep)
663 : {
664 : //x in cm fWidth in cm
665 0 : Float_t weight = GetPRF(x,y);
666 0 : fSigmaX+=x*x*weight;
667 0 : fSigmaY+=y*y*weight;
668 0 : fMeanX+=x*weight;
669 0 : fMeanY+=y*weight;
670 0 : sum+=weight;
671 : };
672 : }
673 0 : if (sum>0){
674 0 : fMeanX/=sum;
675 0 : fMeanY/=sum;
676 0 : fSigmaX = TMath::Sqrt(fSigmaX/sum-fMeanX*fMeanX);
677 0 : fSigmaY = TMath::Sqrt(fSigmaY/sum-fMeanY*fMeanY);
678 0 : }
679 0 : else fSigmaX=0;
680 0 : }
681 :
682 :
683 : void AliTPCPRF2D::Streamer(TBuffer &xRuub)
684 : {
685 : /// Stream an object of class AliTPCPRF2D
686 :
687 6 : if (xRuub.IsReading()) {
688 3 : UInt_t xRuus, xRuuc;
689 3 : Version_t xRuuv = xRuub.ReadVersion(&xRuus, &xRuuc);
690 3 : AliTPCPRF2D::Class()->ReadBuffer(xRuub, this, xRuuv, xRuus, xRuuc);
691 : //read functions
692 3 : if (strncmp(fType,"User",3)!=0){
693 6 : delete fGRF;
694 3 : if (strncmp(fType,"Gauss",3)==0)
695 0 : fGRF = new TF2("FunGauss2D",FunGauss2D,-5.,5.,-5.,5.,4);
696 3 : if (strncmp(fType,"Cosh",3)==0)
697 0 : fGRF = new TF2("FunCosh2D",FunCosh2D,-5.,5.,-5.,5.,4);
698 3 : if (strncmp(fType,"Gati",3)==0)
699 6 : fGRF = new TF2("FunGati2D",FunGati2D,-5.,5.,-5.,5.,5);
700 6 : if (fGRF!=0) fGRF->SetParameters(funParam);
701 : }
702 : //calculate conversion coefitient to convert position to virtual wire
703 3 : fDYtoWire=Float_t(fNYdiv-1)/(fY2-fY1);
704 3 : fDStepM1=1/fDStep;
705 3 : } else {
706 0 : AliTPCPRF2D::Class()->WriteBuffer(xRuub,this);
707 : }
708 3 : }
709 :
710 :
711 : TH1F * AliTPCPRF2D::GenerDrawXHisto(Float_t x1, Float_t x2,Float_t y)
712 : {
713 : /// gener one dimensional hist of pad response function
714 : /// at position y
715 :
716 0 : char s[100];
717 : const Int_t kn=200;
718 : //sprintf(s,"Pad Response Function");
719 0 : snprintf(s,100,"Pad Response Function");
720 0 : TH1F * hPRFc = new TH1F("hPRFc",s,kn+1,x1,x2);
721 : Float_t x=x1;
722 : Float_t y1;
723 :
724 0 : for (Int_t i = 0;i<kn+1;i++)
725 : {
726 0 : x+=(x2-x1)/Float_t(kn);
727 0 : y1 = GetPRF(x,y);
728 0 : hPRFc->Fill(x,y1);
729 : };
730 0 : hPRFc->SetXTitle("pad (cm)");
731 0 : return hPRFc;
732 0 : }
733 :
734 : AliH2F * AliTPCPRF2D::GenerDrawHisto(Float_t x1, Float_t x2, Float_t y1, Float_t y2, Int_t Nx, Int_t Ny)
735 : {
736 : /// gener two dimensional histogram with PRF
737 :
738 0 : char s[100];
739 : //sprintf(s,"Pad Response Function");
740 0 : snprintf(s,100,"Pad Response Function");
741 0 : AliH2F * hPRFc = new AliH2F("hPRFc",s,Nx,x1,x2,Ny,y1,y2);
742 0 : Float_t dx=(x2-x1)/Float_t(Nx);
743 0 : Float_t dy=(y2-y1)/Float_t(Ny) ;
744 : Float_t x,y,z;
745 : x = x1;
746 : y = y1;
747 0 : for ( Int_t i = 0;i<=Nx;i++,x+=dx){
748 : y=y1;
749 0 : for (Int_t j = 0;j<=Ny;j++,y+=dy){
750 0 : z = GetPRF(x,y);
751 0 : hPRFc->SetBinContent(hPRFc->GetBin(i,j),z);
752 : };
753 : };
754 0 : hPRFc->SetXTitle("pad direction (cm)");
755 0 : hPRFc->SetYTitle("pad row direction (cm)");
756 0 : hPRFc->SetTitleOffset(1.5,"X");
757 0 : hPRFc->SetTitleOffset(1.5,"Y");
758 0 : return hPRFc;
759 0 : }
760 :
761 :
762 : AliH2F * AliTPCPRF2D::GenerDrawDistHisto(Float_t x1, Float_t x2, Float_t y1, Float_t y2, Int_t Nx, Int_t Ny, Float_t thr)
763 : {
764 : /// return histogram with distortion
765 :
766 : const Float_t kminth=0.00001;
767 0 : if (thr<kminth) thr=kminth;
768 0 : char s[100];
769 : //sprintf(s,"COG distortion of PRF (threshold=%2.2f)",thr);
770 0 : snprintf(s,100,"COG distortion of PRF (threshold=%2.2f)",thr);
771 0 : AliH2F * hPRFDist = new AliH2F("hDistortion",s,Nx,x1,x2,Ny,y1,y2);
772 0 : Float_t dx=(x2-x1)/Float_t(Nx);
773 0 : Float_t dy=(y2-y1)/Float_t(Ny) ;
774 : Float_t x,y,z,ddx;
775 : x=x1;
776 0 : for ( Int_t i = 0;i<=Nx;i++,x+=dx){
777 : y=y1;
778 0 : for(Int_t j = 0;j<=Ny;j++,y+=dy)
779 : {
780 : Float_t sumx=0;
781 : Float_t sum=0;
782 0 : for (Int_t k=-3;k<=3;k++)
783 : {
784 0 : Float_t padx=Float_t(k)*fWidth;
785 0 : z = GetPRF(x-padx,y);
786 0 : if (z>thr){
787 0 : sum+=z;
788 0 : sumx+=z*padx;
789 0 : }
790 : };
791 0 : if (sum>kminth)
792 : {
793 0 : ddx = (x-(sumx/sum));
794 0 : }
795 : else ddx=-1;
796 0 : if (TMath::Abs(ddx)<10) hPRFDist->SetBinContent(hPRFDist->GetBin(i,j),ddx);
797 : }
798 : }
799 :
800 0 : hPRFDist->SetXTitle("pad direction (cm)");
801 0 : hPRFDist->SetYTitle("pad row direction (cm)");
802 0 : hPRFDist->SetTitleOffset(1.5,"X");
803 0 : hPRFDist->SetTitleOffset(1.5,"Y");
804 0 : return hPRFDist;
805 0 : }
806 :
807 :
808 :
809 :
810 :
811 : void AliTPCPRF2D::DrawX(Float_t x1 ,Float_t x2,Float_t y1,Float_t y2, Int_t N)
812 : {
813 : /// draw pad response function at interval <x1,x2> at given y position
814 :
815 0 : if (N<0) return;
816 0 : TCanvas * c1 = new TCanvas("PRFX","Pad response function",700,900);
817 0 : c1->cd();
818 :
819 0 : TPaveText * comment = new TPaveText(0.05,0.02,0.95,0.20,"NDC");
820 0 : comment->SetTextAlign(12);
821 0 : comment->SetFillColor(42);
822 0 : DrawComment(comment);
823 0 : comment->Draw();
824 0 : c1->cd();
825 :
826 0 : TPad * pad2 = new TPad("pPRF","",0.05,0.22,0.95,0.95);
827 0 : pad2->Divide(2,(N+1)/2);
828 0 : pad2->Draw();
829 0 : gStyle->SetOptFit(1);
830 0 : gStyle->SetOptStat(1);
831 0 : for (Int_t i=0;i<N;i++){
832 0 : char ch[200];
833 : Float_t y;
834 0 : if (N==1) y=y1;
835 0 : else y = y1+i*(y2-y1)/Float_t(N-1);
836 0 : pad2->cd(i+1);
837 0 : TH1F * hPRFc =GenerDrawXHisto(x1, x2,y);
838 : //sprintf(ch,"PRF at wire position: %2.3f",y);
839 0 : snprintf(ch,40,"PRF at wire position: %2.3f",y);
840 0 : hPRFc->SetTitle(ch);
841 : //sprintf(ch,"PRF %d",i);
842 0 : snprintf(ch,15,"PRF %d",i);
843 0 : hPRFc->SetName(ch);
844 0 : hPRFc->Fit("gaus");
845 0 : }
846 :
847 0 : }
848 :
849 :
850 :
851 : void AliTPCPRF2D::DrawPRF(Float_t x1 ,Float_t x2,Float_t y1, Float_t y2, Int_t Nx, Int_t Ny)
852 : {
853 : ///
854 :
855 0 : TCanvas * c1 = new TCanvas("canPRF","Pad response function",700,900);
856 0 : c1->cd();
857 0 : TPad * pad2 = new TPad("pad2PRF","",0.05,0.22,0.95,0.95);
858 0 : pad2->Draw();
859 0 : gStyle->SetOptFit(1);
860 0 : gStyle->SetOptStat(1);
861 0 : TH2F * hPRFc = GenerDrawHisto(x1, x2, y1, y2, Nx,Ny);
862 0 : pad2->cd();
863 0 : hPRFc->Draw("surf");
864 0 : c1->cd();
865 0 : TPaveText * comment = new TPaveText(0.05,0.02,0.95,0.20,"NDC");
866 0 : comment->SetTextAlign(12);
867 0 : comment->SetFillColor(42);
868 0 : DrawComment(comment);
869 0 : comment->Draw();
870 0 : }
871 :
872 : void AliTPCPRF2D::DrawDist(Float_t x1 ,Float_t x2,Float_t y1, Float_t y2, Int_t Nx, Int_t Ny, Float_t thr)
873 : {
874 : /// draw distortion of the COG method - for different threshold parameter
875 :
876 0 : TCanvas * c1 = new TCanvas("padDistortion","COG distortion",700,900);
877 0 : c1->cd();
878 0 : TPad * pad1 = new TPad("dist","",0.05,0.55,0.95,0.95,21);
879 0 : pad1->Draw();
880 0 : TPad * pad2 = new TPad("dist","",0.05,0.22,0.95,0.53,21);
881 0 : pad2->Draw();
882 0 : gStyle->SetOptFit(1);
883 0 : gStyle->SetOptStat(0);
884 :
885 0 : AliH2F * hPRFDist = GenerDrawDistHisto(x1, x2, y1, y2, Nx,Ny,thr);
886 :
887 0 : pad1->cd();
888 0 : hPRFDist->Draw("surf");
889 0 : Float_t distmax =hPRFDist->GetMaximum();
890 0 : Float_t distmin =hPRFDist->GetMinimum();
891 0 : gStyle->SetOptStat(1);
892 :
893 0 : TH1F * dist = hPRFDist->GetAmplitudes(distmin,distmax,distmin-1);
894 0 : pad2->cd();
895 0 : dist->Draw();
896 0 : c1->cd();
897 0 : TPaveText * comment = new TPaveText(0.05,0.02,0.95,0.20,"NDC");
898 0 : comment->SetTextAlign(12);
899 0 : comment->SetFillColor(42);
900 0 : DrawComment(comment);
901 0 : comment->Draw();
902 0 : }
903 :
904 : void AliTPCPRF2D::DrawComment(TPaveText *comment)
905 : {
906 : /// function to write comment to picture
907 :
908 0 : char s[100];
909 : //draw comments to picture
910 0 : TText * title = comment->AddText("Pad Response Function parameters:");
911 0 : title->SetTextSize(0.03);
912 : //sprintf(s,"Height of pad: %2.2f cm",fHeightFull);
913 0 : snprintf(s,100,"Height of pad: %2.2f cm",fHeightFull);
914 0 : comment->AddText(s);
915 : //sprintf(s,"Width pad: %2.2f cm",fWidth);
916 0 : snprintf(s,100,"Width pad: %2.2f cm",fWidth);
917 0 : comment->AddText(s);
918 : //sprintf(s,"Pad Angle: %2.2f ",fPadAngle);
919 0 : snprintf(s,100,"Pad Angle: %2.2f ",fPadAngle);
920 0 : comment->AddText(s);
921 :
922 0 : if (TMath::Abs(fK)>0.0001){
923 : //sprintf(s,"Height of one chevron unit h: %2.2f cm",2*fHeightS);
924 0 : snprintf(s,100,"Height of one chevron unit h: %2.2f cm",2*fHeightS);
925 0 : comment->AddText(s);
926 : //sprintf(s,"Overlap factor: %2.2f",fK);
927 0 : snprintf(s,100,"Overlap factor: %2.2f",fK);
928 0 : comment->AddText(s);
929 0 : }
930 :
931 0 : if (strncmp(fType,"User",3)==0){
932 : //sprintf(s,"Charge distribution - user defined function %s ",fGRF->GetTitle());
933 0 : snprintf(s,100,"Charge distribution - user defined function %s ",fGRF->GetTitle());
934 0 : comment->AddText(s);
935 : //sprintf(s,"Sigma x of charge distribution: %2.2f ",fOrigSigmaX);
936 0 : snprintf(s,100,"Sigma x of charge distribution: %2.2f ",fOrigSigmaX);
937 0 : comment->AddText(s);
938 : //sprintf(s,"Sigma y of charge distribution: %2.2f ",fOrigSigmaY);
939 0 : snprintf(s,100,"Sigma y of charge distribution: %2.2f ",fOrigSigmaY);
940 0 : comment->AddText(s);
941 0 : }
942 0 : if (strncmp(fType,"Gauss",3)==0){
943 : //sprintf(s,"Gauss charge distribution");
944 0 : snprintf(s,100,"Gauss charge distribution");
945 0 : comment->AddText(s);
946 : //sprintf(s,"Sigma x of charge distribution: %2.2f ",fOrigSigmaX);
947 0 : snprintf(s,100,"Sigma x of charge distribution: %2.2f ",fOrigSigmaX);
948 0 : comment->AddText(s);
949 : //sprintf(s,"Sigma y of charge distribution: %2.2f ",fOrigSigmaY);
950 0 : snprintf(s,100,"Sigma y of charge distribution: %2.2f ",fOrigSigmaY);
951 0 : comment->AddText(s);
952 0 : }
953 0 : if (strncmp(fType,"Gati",3)==0){
954 : //sprintf(s,"Gati charge distribution");
955 0 : snprintf(s,100,"Gati charge distribution");
956 0 : comment->AddText(s);
957 : //sprintf(s,"K3X of Gati : %2.2f ",fK3X);
958 0 : snprintf(s,100,"K3X of Gati : %2.2f ",fK3X);
959 0 : comment->AddText(s);
960 : //sprintf(s,"K3Y of Gati: %2.2f ",fK3Y);
961 0 : snprintf(s,100,"K3Y of Gati: %2.2f ",fK3Y);
962 0 : comment->AddText(s);
963 : //sprintf(s,"Wire to Pad Distance: %2.2f ",fPadDistance);
964 0 : snprintf(s,100,"Wire to Pad Distance: %2.2f ",fPadDistance);
965 0 : comment->AddText(s);
966 0 : }
967 0 : if (strncmp(fType,"Cosh",3)==0){
968 : //sprintf(s,"Cosh charge distribution");
969 0 : snprintf(s,100,"Cosh charge distribution");
970 0 : comment->AddText(s);
971 : //sprintf(s,"Sigma x of charge distribution: %2.2f ",fOrigSigmaX);
972 0 : snprintf(s,100,"Sigma x of charge distribution: %2.2f ",fOrigSigmaX);
973 0 : comment->AddText(s);
974 : //sprintf(s,"Sigma y of charge distribution: %2.2f ",fOrigSigmaY);
975 0 : snprintf(s,100,"Sigma y of charge distribution: %2.2f ",fOrigSigmaY);
976 0 : comment->AddText(s);
977 0 : }
978 : //sprintf(s,"Normalisation: %2.2f ",fKNorm);
979 0 : snprintf(s,100,"Normalisation: %2.2f ",fKNorm);
980 0 : comment->AddText(s);
981 0 : }
982 :
|