+//____________________________________________________________________
+Bool_t AliTRDresolution::FitTrack(const Int_t np, AliTrackPoint *points, Float_t param[10])
+{
+//
+// Fit track with a staight line using the "np" clusters stored in the array "points".
+// The following particularities are stored in the clusters from points:
+// 1. pad tilt as cluster charge
+// 2. pad row cross or vertex constrain as fake cluster with cluster type 1
+// The parameters of the straight line fit are stored in the array "param" in the following order :
+// param[0] - x0 reference radial position
+// param[1] - y0 reference r-phi position @ x0
+// param[2] - z0 reference z position @ x0
+// param[3] - slope dy/dx
+// param[4] - slope dz/dx
+//
+// Attention :
+// Function should be used to refit tracks for B=0T
+//
+
+ if(np<40){
+ if(AliLog::GetDebugLevel("PWG1", "AliTRDresolution")>1) printf("D-AliTRDresolution::FitTrack: Not enough clusters to fit a track [%d].\n", np);
+ return kFALSE;
+ }
+ TLinearFitter yfitter(2, "pol1"), zfitter(2, "pol1");
+
+ Double_t x0(0.);
+ for(Int_t ip(0); ip<np; ip++) x0+=points[ip].GetX();
+ x0/=Float_t(np);
+
+ Double_t x, y, z, dx, tilt(0.);
+ for(Int_t ip(0); ip<np; ip++){
+ x = points[ip].GetX(); z = points[ip].GetZ();
+ dx = x - x0;
+ zfitter.AddPoint(&dx, z, points[ip].GetClusterType()?1.e-3:1.);
+ }
+ if(zfitter.Eval() != 0) return kFALSE;
+
+ Double_t z0 = zfitter.GetParameter(0);
+ Double_t dzdx = zfitter.GetParameter(1);
+ for(Int_t ip(0); ip<np; ip++){
+ if(points[ip].GetClusterType()) continue;
+ x = points[ip].GetX();
+ dx = x - x0;
+ y = points[ip].GetY();
+ z = points[ip].GetZ();
+ tilt = points[ip].GetCharge();
+ y -= tilt*(-dzdx*dx + z - z0);
+ Float_t xyz[3] = {x, y, z}; points[ip].SetXYZ(xyz);
+ yfitter.AddPoint(&dx, y, 1.);
+ }
+ if(yfitter.Eval() != 0) return kFALSE;
+ Double_t y0 = yfitter.GetParameter(0);
+ Double_t dydx = yfitter.GetParameter(1);
+
+ param[0] = x0; param[1] = y0; param[2] = z0; param[3] = dydx; param[4] = dzdx;
+ if(AliLog::GetDebugLevel("PWG1", "AliTRDresolution")>3) printf("D-AliTRDresolution::FitTrack: x0[%f] y0[%f] z0[%f] dydx[%f] dzdx[%f].\n", x0, y0, z0, dydx, dzdx);
+ return kTRUE;
+}
+
+//____________________________________________________________________
+Bool_t AliTRDresolution::FitTracklet(const Int_t ly, const Int_t np, const AliTrackPoint *points, const Float_t param[10], Float_t par[3])
+{
+//
+// Fit tracklet with a staight line using the coresponding subset of clusters out of the total "np" clusters stored in the array "points".
+// See function FitTrack for the data stored in the "clusters" array
+
+// The parameters of the straight line fit are stored in the array "param" in the following order :
+// par[0] - x0 reference radial position
+// par[1] - y0 reference r-phi position @ x0
+// par[2] - slope dy/dx
+//
+// Attention :
+// Function should be used to refit tracks for B=0T
+//
+
+ TLinearFitter yfitter(2, "pol1");
+
+ // grep data for tracklet
+ Double_t x0(0.), x[60], y[60], dy[60];
+ Int_t nly(0);
+ for(Int_t ip(0); ip<np; ip++){
+ if(points[ip].GetClusterType()) continue;
+ if(points[ip].GetVolumeID() != ly) continue;
+ Float_t xt(points[ip].GetX())
+ ,yt(param[1] + param[3] * (xt - param[0]));
+ x[nly] = xt;
+ y[nly] = points[ip].GetY();
+ dy[nly]= y[nly]-yt;
+ x0 += xt;
+ nly++;
+ }
+ if(nly<10){
+ if(AliLog::GetDebugLevel("PWG1", "AliTRDresolution")>1) printf("D-AliTRDresolution::FitTracklet: Not enough clusters to fit a tracklet [%d].\n", nly);
+ return kFALSE;
+ }
+ // set radial reference for fit
+ x0 /= Float_t(nly);
+
+ // find tracklet core
+ Double_t mean(0.), sig(1.e3);
+ AliMathBase::EvaluateUni(nly, dy, mean, sig, 0);
+
+ // simple cluster error parameterization
+ Float_t kSigCut = TMath::Sqrt(5.e-4 + param[3]*param[3]*0.018);
+
+ // fit tracklet core
+ for(Int_t jly(0); jly<nly; jly++){
+ if(TMath::Abs(dy[jly]-mean)>kSigCut) continue;
+ Double_t dx(x[jly]-x0);
+ yfitter.AddPoint(&dx, y[jly], 1.);
+ }
+ if(yfitter.Eval() != 0) return kFALSE;
+ par[0] = x0;
+ par[1] = yfitter.GetParameter(0);
+ par[2] = yfitter.GetParameter(1);
+ return kTRUE;
+}
+
+//____________________________________________________________________
+Bool_t AliTRDresolution::UseTrack(const Int_t np, const AliTrackPoint *points, Float_t param[10])
+{
+//
+// Global selection mechanism of tracksbased on cluster to fit residuals
+// The parameters are the same as used ni function FitTrack().
+
+ const Float_t kS(0.6), kM(0.2);
+ TH1S h("h1", "", 100, -5.*kS, 5.*kS);
+ Float_t dy, dz, s, m;
+ for(Int_t ip(0); ip<np; ip++){
+ if(points[ip].GetClusterType()) continue;
+ Float_t x0(points[ip].GetX())
+ ,y0(param[1] + param[3] * (x0 - param[0]))
+ ,z0(param[2] + param[4] * (x0 - param[0]));
+ dy=points[ip].GetY() - y0; h.Fill(dy);
+ dz=points[ip].GetZ() - z0;
+ }
+ TF1 fg("fg", "gaus", -5.*kS, 5.*kS);
+ fg.SetParameter(1, 0.);
+ fg.SetParameter(2, 2.e-2);
+ h.Fit(&fg, "QN");
+ m=fg.GetParameter(1); s=fg.GetParameter(2);
+ if(s>kS || TMath::Abs(m)>kM) return kFALSE;
+ return kTRUE;
+}
+