ROOT logo
// #ifndef __CINT__
#include "TCanvas.h"
#include "TDatabasePDG.h"
#include "TF1.h"
#include "TGraph.h"
#include "TH1.h"
#include "TString.h"
#include "TTree.h"
#include "TTreeStream.h"
#include "TSystem.h"
#include "TROOT.h"

#include "AliTPCcalibDB.h"
#include "AliToyMCEvent.h"
#include "AliToyMCTrack.h"
#include "AliTPCclusterMI.h"
#include "AliTPCParam.h"
#include "AliTPCROC.h"
#include "AliTPCSpaceCharge3D.h"
#include "AliTrackerBase.h"
#include "AliTrackPointArray.h"
// #endif


Float_t GetTimeAtVertex(Float_t &tVtx, Float_t &x, const AliToyMCTrack *tr, Int_t clsType=0, Int_t seedRow=140, Int_t seedDist=10, Int_t correctionType=0);
void SetTrackPointFromCluster(const AliTPCclusterMI *cl, AliTrackPoint &p);
void ClusterToSpacePoint(const AliTPCclusterMI *cl, Float_t xyz[3]);
void InitSpaceCharge(TTree *t=0x0);
/*

root.exe -l $ALICE_ROOT/TPC/Upgrade/macros/{loadlibs.C,ConfigOCDB.C}
.x $ALICE_ROOT/TPC/Upgrade/macros/testRec.C

*/

AliTPCParam *fTPCParam=0x0;
AliTPCSpaceCharge3D *fSpaceCharge=0x0;
TTreeSRedirector *fStreamer=0x0;

Int_t fEvent=-1;
Int_t fTrack=-1;
Float_t fT0event=-1;
Float_t fZevent=-1;

void testRec(const char* filename="toyMC.root", Int_t nmaxEv=-1)
{
  //
  //
  //

  fTPCParam=AliTPCcalibDB::Instance()->GetParameters();
  TFile f(filename);
  if (!f.IsOpen() || f.IsZombie()) {
    printf("ERROR: couldn't open the file '%s'\n", filename);
    return;
  }
  
  TTree *t=(TTree*)f.Get("toyMCtree");
  if (!t) {
    printf("ERROR: couldn't read the 'toyMCtree' from file '%s'\n", filename);
    return;
  }
  
  AliToyMCEvent *ev=0x0;
  t->SetBranchAddress("event",&ev);

  // read spacecharge from the Userinfo ot the tree
  InitSpaceCharge(t);
  
  TString debugName=filename;
  debugName.ReplaceAll(".root","");
  debugName.Append(".debug.root");
  
  gSystem->Exec(Form("test -f %s && rm %s", debugName.Data(), debugName.Data()));
  if (!fStreamer) fStreamer=new TTreeSRedirector(debugName.Data());
  
  gROOT->cd();

//   const Double_t kDriftVel = fTPCParam->GetDriftV()/1000000;
//   const Double_t kDriftVel = fTPCParam->GetDriftV();
//   const Double_t kMaxZ0=fTPCParam->GetZLength();

  TH1F *h0=new TH1F("h0","h0",1000,0,0);
  TH1F *hX=new TH1F("hX","hX",1000,0,0);
  TH1F *h1=new TH1F("h1","h1",1000,0,0);
  TH1I *hcount0=new TH1I("count0","Failed extrapolation1",5,0,5);
  TH1I *hcount1=new TH1I("count1","Failed extrapolation2",5,0,5);
  
  Int_t maxev=t->GetEntries();
  if (nmaxEv>0&&nmaxEv<maxev) maxev=nmaxEv;
  
  for (Int_t iev=0; iev<maxev; ++iev){
    t->GetEvent(iev);
    fEvent=iev;
    for (Int_t itr=0; itr<ev->GetNumberOfTracks(); ++itr){
      printf("==============  Processing Track %6d\n",itr);
      fTrack=itr;
      fT0event = ev->GetT0();
      fZevent  = ev->GetZ();

      //Float_t &tVtx, Float_t &x, AliToyMCTrack *tr,
      //  Int_t clsType=0, Int_t seedRow=140, Int_t seedDist=10, Int_t correctionType=0
      // correctionType: 0 none, 1 center, 2 mean tan,
      //                 3 full from seed (iterative), 4 ideal (real z-Position)
      const AliToyMCTrack *tr=ev->GetTrack(itr);
      Float_t tVtx0=0;
      Float_t xmin=0;
      Int_t ret0=GetTimeAtVertex(tVtx0,xmin,tr);
      hX->Fill(xmin);
      //fully distorted
      Float_t tVtx1=0;
      Int_t ret1=GetTimeAtVertex(tVtx1,xmin,tr,1);// seeding at the outside
      GetTimeAtVertex(tVtx1,xmin,tr,1,70); // seeding in the center
      GetTimeAtVertex(tVtx1,xmin,tr,1,0); // seeding at the inside
      //correction at tpc center
      GetTimeAtVertex(tVtx1,xmin,tr,1,140, 10, 1);
      //correction with mean tan theta
      GetTimeAtVertex(tVtx1,xmin,tr,1,140, 10, 2);
      //correction with ideal z
      GetTimeAtVertex(tVtx1,xmin,tr,1,140, 10, 4);
      
      hcount0->Fill(ret0);
      hcount1->Fill(ret1);
      if (ret0==0) {
        h0->Fill(tVtx0);
      }

      if (ret1==0) {
        h1->Fill(tVtx1);
      }
//       printf("TVtx: %f, %f\n",tVtx0,0);
    }
  }

  TCanvas *c=(TCanvas*)gROOT->GetListOfCanvases()->FindObject("cOutput");
  if (!c) c=new TCanvas("cOutput","Results");
  c->Clear();
  c->Divide(2,2);
  c->cd(1);
  h0->Draw();
  h1->SetLineColor(kRed);
  h1->Draw("same");
  c->cd(2);
  hcount0->Draw();
  hcount1->SetLineColor(kRed);
  hcount1->Draw("same");
  c->cd(3);
  hX->Draw();

  delete fStreamer;
  fStreamer=0x0;
}

//____________________________________________________________________________
Float_t GetTimeAtVertex(Float_t &tVtx,  Float_t &x, const AliToyMCTrack *tr, Int_t clsType, Int_t seedRow, Int_t seedDist, Int_t correctionType)
{
  //
  // clsType:    0 undistorted; 1 distorted
  // seedRow:    seeding row
  // seedDist:   distance of seeding points
  // correctionType: 0 none, 1 center, 2 mean tan,
  //                 3 full from seed (iterative), 4 ideal (real z-Position)
  //

  // seed point informaion
  AliTrackPoint    seedPoint[3];
  const AliTPCclusterMI *seedCluster[3]={0x0,0x0,0x0};

  // number of clusters to loop over
  const Int_t ncls=(clsType==0)?tr->GetNumberOfSpacePoints():tr->GetNumberOfDistSpacePoints();

  UChar_t nextSeedRow=seedRow;
  Int_t   seed=0;

  //assumes sorted clusters
  for (Int_t icl=0;icl<ncls;++icl) {
    const AliTPCclusterMI *cl=tr->GetSpacePoint(icl);
    if (clsType==1) cl=tr->GetDistortedSpacePoint(icl);
    if (!cl) continue;
    // use row in sector
    const UChar_t row=cl->GetRow() + 63*(cl->GetDetector()>35);
    // skip clusters without proper pad row
    if (row>200) continue;

    //check seeding row
    // if we are in the last row and still miss a seed we use the last row
    //   even if the row spacing will not be equal
    if (row>=nextSeedRow || icl==ncls-1){
      seedCluster[seed]=cl;
      SetTrackPointFromCluster(cl, seedPoint[seed]);
//       printf("\nSeed point %d: %d, %d, %.2f, %.2f, %.2f, %.2f, %.2f\n",seed, cl->GetDetector(), row, seedPoint[seed].GetX(),seedPoint[seed].GetY(),seedPoint[seed].GetZ(), seedPoint[seed].GetAngle(), ((cl->GetDetector()%18)*20.+10.)/180.*TMath::Pi());
      ++seed;
      nextSeedRow+=seedDist;

      if (seed==3) break;
    }
  }

  // check we really have 3 seeds
  if (seed!=3  && x>-900.) {

    AliToyMCTrack *nctr = const_cast<AliToyMCTrack*>(tr);
    // debug output for failed seeding
    (*fStreamer) << "TracksFailSeed" <<
      "iev="      << fEvent <<
      "t0="       << fT0event <<
      "z0="       << fZevent <<
      "itrack="   << fTrack <<
      "clsType="  << clsType <<
      "seedRow="  << seedRow <<
      "seedDist=" << seedDist <<
      "corrType=" << correctionType <<
      "track.="   << nctr    <<
      "\n";
    
    printf("Seeding failed for parameters %d, %d\n",seedRow,seedDist);
    return 1;
  }

  Float_t tVtx_opt3=0;
  if (correctionType==3) {
    Float_t xDummy=-999.;
    GetTimeAtVertex(tVtx_opt3,xDummy, tr, clsType, seedRow, seedDist, 2);
  }
  // do cluster correction and 
  // assign the cluster abs time as z component to all seeds
  for (Int_t iseed=0; iseed<3; ++iseed) {
    Float_t xyz[3]={0,0,0};
    seedPoint[iseed].GetXYZ(xyz);
    Float_t r=TMath::Sqrt(xyz[0]*xyz[0]+xyz[1]*xyz[1]);
    
    Int_t sector=seedCluster[iseed]->GetDetector();
    Int_t sign=1-2*((sector/18)%2);
    
    if (clsType && correctionType) {
      if (correctionType==1) xyz[2]=125.;
      //!!! TODO: is this the correct association?
      if (correctionType==2) xyz[2]=TMath::Tan(45./2.*TMath::DegToRad())*r*sign;
//       if (correctionType==3) {
//         xyz[2]=(seedCluster[iseed]->GetTimeBin()-tVtx_opt3)*kDriftVel;
//         
//       }
      if (correctionType==4) xyz[2]=seedCluster[iseed]->GetZ();

      fSpaceCharge->CorrectPoint(xyz, seedCluster[iseed]->GetDetector());
    }

    // set different sign for c-Side (only for testing: makes half of the times negative)
    // xyz[2]=seedCluster[iseed]->GetTimeBin() * sign;
    
    // correct with track z (only for testing: not possible in exp?)
    // xyz[2]=seedCluster[iseed]->GetTimeBin() + sign * tr->GetZ()/(fTPCParam->GetDriftV());
    
    // no correction (default)
    xyz[2]=seedCluster[iseed]->GetTimeBin();
    
    seedPoint[iseed].SetXYZ(xyz);
  }

  // create seed and Propagate to r=0;

  const Double_t kMaxSnp = 0.85;
  const Double_t kMass = TDatabasePDG::Instance()->GetParticle("pi+")->Mass();
  
  AliExternalTrackParam *track = 0x0;
  track = AliTrackerBase::MakeSeed(seedPoint[0], seedPoint[1], seedPoint[2]);
  track->ResetCovariance(10);

//   printf("orig:  %.2f, %.2f, %.2f, %.2f, %.2f, %.2f\n",
//          tr->GetParameter()[0],tr->GetParameter()[1],tr->GetParameter()[2],
//          tr->GetParameter()[3],tr->GetParameter()[4],tr->GetAlpha());
  
//   printf("seed:  %.2f, %.2f, %.2f, %.2f, %.2f, %.2f\n",
//          track->GetParameter()[0],track->GetParameter()[1],track->GetParameter()[2],
//          track->GetParameter()[3],track->GetParameter()[4],track->GetAlpha());
  
  //   printf("Track: %.2f, %.2f, %.2f, %.2f, %.2f\n",track->GetX(),track->GetY(),track->GetZ(), track->GetAlpha(),track->Phi());
  AliExternalTrackParam pInit(*track);

  // NOTE:
  // when propagating with the time binwe need to switch off the material correction
  // otherwise we will be quite off ...
  // 
  AliTrackerBase::PropagateTrackTo(track,0,kMass,5,kTRUE,kMaxSnp,0,kFALSE,kFALSE);
  if (TMath::Abs(track->GetX())>3) {
    printf("Could not propagate track to 0, %.2f, %.2f, %.2f\n",track->GetX(),track->GetAlpha(),track->Pt());
//     return 2;
  }
//   printf("Track2: %.2f, %.2f, %.2f, %.2f\n",track->GetX(),track->GetY(),track->GetZ(), track->GetAlpha());

  // simple linear fit
  TGraph gr;
  for (Int_t i=0; i<3; ++i)
    gr.SetPoint(gr.GetN(),seedPoint[i].GetX(),seedPoint[i].GetZ());
//   gr.Print();
  TF1 fpol1("fpol1","pol1");
  gr.Fit(&fpol1,"QN");
  Float_t fitT0=fpol1.Eval(0);
//   fpol1.Print();
  AliExternalTrackParam pOrig(*tr);
  AliToyMCTrack *nctr = const_cast<AliToyMCTrack*>(tr);

  if (x>-900.){
    (*fStreamer) << "Tracks" <<
      "iev="      << fEvent <<
      "t0="       << fT0event <<
      "z0="       << fZevent <<
      "itrack="   << fTrack <<
      "clsType="  << clsType <<
      "seedRow="  << seedRow <<
      "seedDist=" << seedDist <<
      "corrType=" << correctionType <<
      "track.="   << nctr    <<
      "seed.="    << track <<
      "seedI.="   << &pInit <<
  //     "seedcl0.=" << seedCluster[0] <<
  //     "seedcl1.=" << seedCluster[1] <<
  //     "seedcl2.=" << seedCluster[2] <<
  //     "seedp0.="  << &seedPoint[0] <<
  //     "seedp1.="  << &seedPoint[1] <<
  //     "seedp2.="  << &seedPoint[2] <<
      "fitT0="    << fitT0 <<
      "\n";
  }
  
  tVtx=track->GetZ();
  x=track->GetX();
  delete track;
  return 0;
}

//____________________________________________________________________________
void SetTrackPointFromCluster(const AliTPCclusterMI *cl, AliTrackPoint &p ) {
  //
  // make AliTrackPoint out of AliTPCclusterMI
  //

  if (!cl) return;
//   Float_t xyz[3]={0.,0.,0.};
//   ClusterToSpacePoint(cl,xyz);
//   cl->GetGlobalCov(cov);
  //TODO: what to do with the covariance matrix???
  //TODO: the problem is that it is used in GetAngle in AliTrackPoint
  //TODO: which is used by AliTrackerBase::MakeSeed to get alpha correct ...
  //TODO: for the moment simply assign 1 permill squared
  // in AliTrackPoint the cov is xx, xy, xz, yy, yz, zz
//   Float_t cov[6]={xyz[0]*xyz[0]*1e-6,xyz[0]*xyz[1]*1e-6,xyz[0]*xyz[2]*1e-6,
//                   xyz[1]*xyz[1]*1e-6,xyz[1]*xyz[2]*1e-6,xyz[2]*xyz[2]*1e-6};
//   cl->GetGlobalXYZ(xyz);
//   cl->GetGlobalCov(cov);
  // voluem ID to add later ....
//   p.SetXYZ(xyz);
//   p.SetCov(cov);
  AliTrackPoint *tp=const_cast<AliTPCclusterMI*>(cl)->MakePoint();
  p=*tp;
  delete tp;
//   cl->Print();
//   p.Print();
  p.SetVolumeID(cl->GetDetector());
//   p.Rotate(p.GetAngle()).Print();
}

//____________________________________________________________________________
void ClusterToSpacePoint(const AliTPCclusterMI *cl, Float_t xyz[3])
{
  //
  // convert the cluster to a space point in global coordinates
  //
  if (!cl) return;
  xyz[0]=cl->GetRow();
  xyz[1]=cl->GetPad();
  xyz[2]=cl->GetTimeBin(); // this will not be correct at all
  Int_t i[3]={0,cl->GetDetector(),cl->GetRow()};
//   printf("%.2f, %.2f, %.2f - %d, %d, %d\n",xyz[0],xyz[1],xyz[2],i[0],i[1],i[2]);
  fTPCParam->Transform8to4(xyz,i);
//   printf("%.2f, %.2f, %.2f - %d, %d, %d\n",xyz[0],xyz[1],xyz[2],i[0],i[1],i[2]);
  fTPCParam->Transform4to3(xyz,i);
//   printf("%.2f, %.2f, %.2f - %d, %d, %d\n",xyz[0],xyz[1],xyz[2],i[0],i[1],i[2]);
  fTPCParam->Transform2to1(xyz,i);
//   printf("%.2f, %.2f, %.2f - %d, %d, %d\n",xyz[0],xyz[1],xyz[2],i[0],i[1],i[2]);
}

//____________________________________________________________________________
void InitSpaceCharge(TTree *t)
{
  //
  // Init the space charge map
  //

  TString filename="$ALICE_ROOT/TPC/Calib/maps/SC_NeCO2_eps5_50kHz_precal.root";
  if (t) {
    TList *l=t->GetUserInfo();
    for (Int_t i=0; i<l->GetEntries(); ++i) {
      TString s(l->At(i)->GetName());
      if (s.Contains("SC_")) {
        filename=s;
        break;
      }
    }
  }

  printf("Initialising the space charge map using the file: '%s'\n",filename.Data());
  TFile f(filename.Data());
  fSpaceCharge=(AliTPCSpaceCharge3D*)f.Get("map");
  
//   fSpaceCharge = new AliTPCSpaceCharge3D();
//   fSpaceCharge->SetSCDataFileName("$ALICE_ROOT/TPC/Calib/maps/SC_NeCO2_eps10_50kHz.root");
//   fSpaceCharge->SetOmegaTauT1T2(0.325,1,1); // Ne CO2
// //   fSpaceCharge->SetOmegaTauT1T2(0.41,1,1.05); // Ar CO2
//   fSpaceCharge->InitSpaceCharge3DDistortion();
  
}

//____________________________________________________________________________
AliExternalTrackParam* GetFullTrack(const AliToyMCTrack *tr, Int_t clsType=0, Int_t corrType=0, Bool_t useMaterial=kFALSE)
{
  //
  // clsType:  0=undistorted clusters; 1: distorted clusters
  // corrType: 0=none; 1: ideal
  //

  // no correction for undistorted clusters
  if (clsType==0) corrType=0;
  
  AliTPCROC * roc = AliTPCROC::Instance();
//   const Int_t    npoints0=roc->GetNRows(0)+roc->GetNRows(36);
  const Double_t kRTPC0  =roc->GetPadRowRadii(0,0);
  const Double_t kRTPC1  =roc->GetPadRowRadii(36,roc->GetNRows(36)-1);
  const Double_t kMaxSnp = 0.85;
//   const Double_t kSigmaY=0.1;
//   const Double_t kSigmaZ=0.1;
  const Double_t kMaxR=500;
  const Double_t kMaxZ=500;
  
//   const Double_t kMaxZ0=220;
  const Double_t kZcut=3;
  const Double_t kMass = TDatabasePDG::Instance()->GetParticle("pi+")->Mass();

  Int_t ncls=(clsType==0)?tr->GetNumberOfSpacePoints():tr->GetNumberOfDistSpacePoints();

  Int_t dir = -1;
  Double_t refX = tr->GetX();
  
  // get points for the seed
  Int_t seed=0;
  AliTrackPoint    seedPoint[3];
  for (Int_t ipoint=ncls-1; ipoint>=ncls-3; --ipoint){
    const AliTPCclusterMI *cl=tr->GetSpacePoint(ipoint);
    if (clsType==1) cl=tr->GetDistortedSpacePoint(ipoint);

    SetTrackPointFromCluster(cl, seedPoint[seed]);
    
    if (corrType==1){
      Float_t xyz[3]={0,0,0};
      seedPoint[seed].GetXYZ(xyz);
      fSpaceCharge->CorrectPoint(xyz, cl->GetDetector());
      seedPoint[seed].SetXYZ(xyz);
    }
//     seedPoint[seed].Print();
    ++seed;
  }
  
  AliExternalTrackParam *track = AliTrackerBase::MakeSeed(seedPoint[2], seedPoint[1], seedPoint[0]);
  track->ResetCovariance(10);

//   printf("============================================\n");
//   printf("orig:  %.2f, %.2f, %.2f, %.2f, %.2f, %.2f\n",
//          tr->GetParameter()[0],tr->GetParameter()[1],tr->GetParameter()[2],
//          tr->GetParameter()[3],tr->GetParameter()[4],tr->GetAlpha());
  
//   printf("seed:  %.2f, %.2f, %.2f, %.2f, %.2f, %.2f\n",
//          track->GetParameter()[0],track->GetParameter()[1],track->GetParameter()[2],
//          track->GetParameter()[3],track->GetParameter()[4],track->GetAlpha());

  // loop over all other points and add to the track
  for (Int_t ipoint=ncls-4; ipoint>=0; --ipoint){
    AliTrackPoint pIn;
    const AliTPCclusterMI *cl=tr->GetSpacePoint(ipoint);
    if (clsType==1) cl=tr->GetDistortedSpacePoint(ipoint);
    SetTrackPointFromCluster(cl, pIn);
    if (corrType==1){
      Float_t xyz[3]={0,0,0};
      pIn.GetXYZ(xyz);
      fSpaceCharge->CorrectPoint(xyz, cl->GetDetector());
      pIn.SetXYZ(xyz);
    }
    // rotate the cluster to the local detector frame
    track->Rotate(((cl->GetDetector()%18)*20+10)*TMath::DegToRad());
    AliTrackPoint prot = pIn.Rotate(track->GetAlpha());   // rotate to the local frame - non distoted  point
    if (TMath::Abs(prot.GetX())<kRTPC0) continue;
    if (TMath::Abs(prot.GetX())>kRTPC1) continue;
    //
    Int_t ret=0;
//     printf("before: %.2f, %.2f, %.2f, %.2f, %.2f, %.2f\n",
//            track->GetParameter()[0],track->GetParameter()[1],track->GetParameter()[2],
//            track->GetParameter()[3],track->GetParameter()[4],track->GetAlpha());
    if (useMaterial) ret=AliTrackerBase::PropagateTrackTo2(track,prot.GetX(),kMass,5,kFALSE,kMaxSnp);
    else ret=AliTrackerBase::PropagateTrackTo2(track,prot.GetX(),kMass,5,kFALSE,kMaxSnp,0,kFALSE,kFALSE);
//     printf("after: %.2f, %.2f, %.2f, %.2f, %.2f, %.2f\n",
//            track->GetParameter()[0],track->GetParameter()[1],track->GetParameter()[2],
//            track->GetParameter()[3],track->GetParameter()[4],track->GetAlpha());
    AliToyMCTrack *nctr = const_cast<AliToyMCTrack*>(tr);
    if (ret<0) {
      (*fStreamer) << "np" <<
      "iev="      << fEvent <<
      "itr="      << fTrack <<
      "track.="   << nctr     <<
      "seed.="    << track  <<
      "clsType="  << clsType <<
      "corrType=" << corrType <<
      "ret="      << ret <<
      "\n";
      printf("Could not propagate track: %d\n",ret);
      break;
    }
//     printf("\n=========\n%d:\n",ipoint);
//     printf("%.2f, %.2f, %.2f - %d, %d, %.2f, %.2g\n",cl->GetX(),cl->GetY(),cl->GetZ(),cl->GetDetector(),cl->GetRow(),cl->GetPad(),cl->GetTimeBin());
//     printf("%.2f, %.2f, %.2f - %.2f\n", prot.GetX(),prot.GetY(),prot.GetZ(), prot.GetAngle());
//     printf("%.2f, %.2f, %.2f - %.2f\n", track->GetX(),track->GetY(),track->GetZ(), track->GetAlpha());
    
    if (TMath::Abs(track->GetZ())>kMaxZ) break;
    if (TMath::Abs(track->GetX())>kMaxR) break;
    if (dir>0 && track->GetX()>refX) continue;
    if (dir<0 && track->GetX()<refX) continue;
    if (TMath::Abs(track->GetZ())<kZcut)continue;
    //
    Double_t pointPos[2]={0,0};
    Double_t pointCov[3]={0,0,0};
    pointPos[0]=prot.GetY();//local y
    pointPos[1]=prot.GetZ();//local z
    pointCov[0]=prot.GetCov()[3];//simay^2
    pointCov[1]=prot.GetCov()[4];//sigmayz
    pointCov[2]=prot.GetCov()[5];//sigmaz^2
    if (!track->Update(pointPos,pointCov)) {printf("no update\n"); break;}
  }
//   printf(">>> before2: %.2f, %.2f, %.2f, %.2f, %.2f, %.2f\n",
//          track->GetParameter()[0],track->GetParameter()[1],track->GetParameter()[2],
//          track->GetParameter()[3],track->GetParameter()[4],track->GetAlpha());
  if (useMaterial) AliTrackerBase::PropagateTrackTo2(track,refX,kMass,5.,kTRUE,kMaxSnp);
  else AliTrackerBase::PropagateTrackTo2(track,refX,kMass,5.,kTRUE,kMaxSnp,0,kFALSE,kFALSE);
//   printf(">>> after2: %.2f, %.2f, %.2f, %.2f, %.2f, %.2f\n",
//          track->GetParameter()[0],track->GetParameter()[1],track->GetParameter()[2],
//          track->GetParameter()[3],track->GetParameter()[4],track->GetAlpha());
  track->Rotate(tr->GetAlpha());
  Int_t ret=0;
  if (useMaterial) ret=AliTrackerBase::PropagateTrackTo2(track,refX,kMass,1.,kFALSE,kMaxSnp);
  else ret=AliTrackerBase::PropagateTrackTo2(track,refX,kMass,1.,kFALSE,kMaxSnp,0,kFALSE,kFALSE);
//   printf(">>> after2.2: %.2f, %.2f, %.2f, %.2f, %.2f, %.2f\n",
//          track->GetParameter()[0],track->GetParameter()[1],track->GetParameter()[2],
//          track->GetParameter()[3],track->GetParameter()[4],track->GetAlpha());
  printf("Propagation to 0 stopped at %.2f with %d\n",track->GetX(),ret);
  // once more propagate to refX
  // try without material budget correction
  return track;
}

//____________________________________________________________________________
void testResolution(const char* filename, Int_t nmaxEv=-1, Bool_t useMaterial=kFALSE)
{
  fTPCParam=AliTPCcalibDB::Instance()->GetParameters();
  TFile f(filename);
  if (!f.IsOpen() || f.IsZombie()) {
    printf("ERROR: couldn't open the file '%s'\n", filename);
    return;
  }
  
  TTree *t=(TTree*)f.Get("toyMCtree");
  if (!t) {
    printf("ERROR: couldn't read the 'toyMCtree' from file '%s'\n", filename);
    return;
  }
  
  AliToyMCEvent *ev=0x0;
  t->SetBranchAddress("event",&ev);

  TString debugName=filename;
  debugName.ReplaceAll(".root","");
  if (useMaterial) debugName.Append(".Mat");
  else debugName.Append(".noMat");
  debugName.Append(".testRes.root");
  
  gSystem->Exec(Form("test -f %s && rm %s", debugName.Data(), debugName.Data()));
  if (!fStreamer) fStreamer=new TTreeSRedirector(debugName.Data());
  
  gROOT->cd();
  
  // read spacecharge from the Userinfo ot the tree
  InitSpaceCharge(t);

  Int_t maxev=t->GetEntries();
  if (nmaxEv>0&&nmaxEv<maxev) maxev=nmaxEv;
  
  for (Int_t iev=0; iev<maxev; ++iev){
    t->GetEvent(iev);
    fEvent=iev;
    printf("========== Processing event %3d =============\n",iev);
    for (Int_t itr=0; itr<ev->GetNumberOfTracks(); ++itr){
      fTrack=itr;
      printf("   ======= Processing track %3d ==========\n",itr);
      const AliToyMCTrack *tr=ev->GetTrack(itr);
      AliExternalTrackParam tOrig(*tr);
      AliExternalTrackParam *tIdeal    = GetFullTrack(tr,0,0,useMaterial);
      AliExternalTrackParam *tDist     = GetFullTrack(tr,1,0,useMaterial);
      AliExternalTrackParam *tDistCorr = GetFullTrack(tr,1,1,useMaterial);

      (*fStreamer) << "res" <<
      "iev="        << iev <<
      "itr="        << itr <<
      "tOrig.="     << &tOrig <<
      "tIdeal.="    << tIdeal <<
      "tDist.="     << tDist  <<
      "tDistCorr.=" << tDistCorr <<
      "\n";
    
      delete tIdeal;
      delete tDist;
      delete tDistCorr;
    }
  }

  delete fStreamer;
  fStreamer=0x0;
}

//____________________________________________________________________________
void ConnectTrees (const char* files, TObjArray &arrTrees) {
  TString s=gSystem->GetFromPipe(Form("ls %s",files));

  TObjArray *arrFiles=s.Tokenize("\n");
  for (Int_t ifile=0; ifile<arrFiles->GetEntriesFast(); ++ifile){
    TFile f(arrFiles->At(ifile)->GetName());
    if (!f.IsOpen() || f.IsZombie()) continue;
    TTree *t=f.Get("Tracks");
    if (!t) continue;
    arrTrees.Add
  }
}
 testRec.C:1
 testRec.C:2
 testRec.C:3
 testRec.C:4
 testRec.C:5
 testRec.C:6
 testRec.C:7
 testRec.C:8
 testRec.C:9
 testRec.C:10
 testRec.C:11
 testRec.C:12
 testRec.C:13
 testRec.C:14
 testRec.C:15
 testRec.C:16
 testRec.C:17
 testRec.C:18
 testRec.C:19
 testRec.C:20
 testRec.C:21
 testRec.C:22
 testRec.C:23
 testRec.C:24
 testRec.C:25
 testRec.C:26
 testRec.C:27
 testRec.C:28
 testRec.C:29
 testRec.C:30
 testRec.C:31
 testRec.C:32
 testRec.C:33
 testRec.C:34
 testRec.C:35
 testRec.C:36
 testRec.C:37
 testRec.C:38
 testRec.C:39
 testRec.C:40
 testRec.C:41
 testRec.C:42
 testRec.C:43
 testRec.C:44
 testRec.C:45
 testRec.C:46
 testRec.C:47
 testRec.C:48
 testRec.C:49
 testRec.C:50
 testRec.C:51
 testRec.C:52
 testRec.C:53
 testRec.C:54
 testRec.C:55
 testRec.C:56
 testRec.C:57
 testRec.C:58
 testRec.C:59
 testRec.C:60
 testRec.C:61
 testRec.C:62
 testRec.C:63
 testRec.C:64
 testRec.C:65
 testRec.C:66
 testRec.C:67
 testRec.C:68
 testRec.C:69
 testRec.C:70
 testRec.C:71
 testRec.C:72
 testRec.C:73
 testRec.C:74
 testRec.C:75
 testRec.C:76
 testRec.C:77
 testRec.C:78
 testRec.C:79
 testRec.C:80
 testRec.C:81
 testRec.C:82
 testRec.C:83
 testRec.C:84
 testRec.C:85
 testRec.C:86
 testRec.C:87
 testRec.C:88
 testRec.C:89
 testRec.C:90
 testRec.C:91
 testRec.C:92
 testRec.C:93
 testRec.C:94
 testRec.C:95
 testRec.C:96
 testRec.C:97
 testRec.C:98
 testRec.C:99
 testRec.C:100
 testRec.C:101
 testRec.C:102
 testRec.C:103
 testRec.C:104
 testRec.C:105
 testRec.C:106
 testRec.C:107
 testRec.C:108
 testRec.C:109
 testRec.C:110
 testRec.C:111
 testRec.C:112
 testRec.C:113
 testRec.C:114
 testRec.C:115
 testRec.C:116
 testRec.C:117
 testRec.C:118
 testRec.C:119
 testRec.C:120
 testRec.C:121
 testRec.C:122
 testRec.C:123
 testRec.C:124
 testRec.C:125
 testRec.C:126
 testRec.C:127
 testRec.C:128
 testRec.C:129
 testRec.C:130
 testRec.C:131
 testRec.C:132
 testRec.C:133
 testRec.C:134
 testRec.C:135
 testRec.C:136
 testRec.C:137
 testRec.C:138
 testRec.C:139
 testRec.C:140
 testRec.C:141
 testRec.C:142
 testRec.C:143
 testRec.C:144
 testRec.C:145
 testRec.C:146
 testRec.C:147
 testRec.C:148
 testRec.C:149
 testRec.C:150
 testRec.C:151
 testRec.C:152
 testRec.C:153
 testRec.C:154
 testRec.C:155
 testRec.C:156
 testRec.C:157
 testRec.C:158
 testRec.C:159
 testRec.C:160
 testRec.C:161
 testRec.C:162
 testRec.C:163
 testRec.C:164
 testRec.C:165
 testRec.C:166
 testRec.C:167
 testRec.C:168
 testRec.C:169
 testRec.C:170
 testRec.C:171
 testRec.C:172
 testRec.C:173
 testRec.C:174
 testRec.C:175
 testRec.C:176
 testRec.C:177
 testRec.C:178
 testRec.C:179
 testRec.C:180
 testRec.C:181
 testRec.C:182
 testRec.C:183
 testRec.C:184
 testRec.C:185
 testRec.C:186
 testRec.C:187
 testRec.C:188
 testRec.C:189
 testRec.C:190
 testRec.C:191
 testRec.C:192
 testRec.C:193
 testRec.C:194
 testRec.C:195
 testRec.C:196
 testRec.C:197
 testRec.C:198
 testRec.C:199
 testRec.C:200
 testRec.C:201
 testRec.C:202
 testRec.C:203
 testRec.C:204
 testRec.C:205
 testRec.C:206
 testRec.C:207
 testRec.C:208
 testRec.C:209
 testRec.C:210
 testRec.C:211
 testRec.C:212
 testRec.C:213
 testRec.C:214
 testRec.C:215
 testRec.C:216
 testRec.C:217
 testRec.C:218
 testRec.C:219
 testRec.C:220
 testRec.C:221
 testRec.C:222
 testRec.C:223
 testRec.C:224
 testRec.C:225
 testRec.C:226
 testRec.C:227
 testRec.C:228
 testRec.C:229
 testRec.C:230
 testRec.C:231
 testRec.C:232
 testRec.C:233
 testRec.C:234
 testRec.C:235
 testRec.C:236
 testRec.C:237
 testRec.C:238
 testRec.C:239
 testRec.C:240
 testRec.C:241
 testRec.C:242
 testRec.C:243
 testRec.C:244
 testRec.C:245
 testRec.C:246
 testRec.C:247
 testRec.C:248
 testRec.C:249
 testRec.C:250
 testRec.C:251
 testRec.C:252
 testRec.C:253
 testRec.C:254
 testRec.C:255
 testRec.C:256
 testRec.C:257
 testRec.C:258
 testRec.C:259
 testRec.C:260
 testRec.C:261
 testRec.C:262
 testRec.C:263
 testRec.C:264
 testRec.C:265
 testRec.C:266
 testRec.C:267
 testRec.C:268
 testRec.C:269
 testRec.C:270
 testRec.C:271
 testRec.C:272
 testRec.C:273
 testRec.C:274
 testRec.C:275
 testRec.C:276
 testRec.C:277
 testRec.C:278
 testRec.C:279
 testRec.C:280
 testRec.C:281
 testRec.C:282
 testRec.C:283
 testRec.C:284
 testRec.C:285
 testRec.C:286
 testRec.C:287
 testRec.C:288
 testRec.C:289
 testRec.C:290
 testRec.C:291
 testRec.C:292
 testRec.C:293
 testRec.C:294
 testRec.C:295
 testRec.C:296
 testRec.C:297
 testRec.C:298
 testRec.C:299
 testRec.C:300
 testRec.C:301
 testRec.C:302
 testRec.C:303
 testRec.C:304
 testRec.C:305
 testRec.C:306
 testRec.C:307
 testRec.C:308
 testRec.C:309
 testRec.C:310
 testRec.C:311
 testRec.C:312
 testRec.C:313
 testRec.C:314
 testRec.C:315
 testRec.C:316
 testRec.C:317
 testRec.C:318
 testRec.C:319
 testRec.C:320
 testRec.C:321
 testRec.C:322
 testRec.C:323
 testRec.C:324
 testRec.C:325
 testRec.C:326
 testRec.C:327
 testRec.C:328
 testRec.C:329
 testRec.C:330
 testRec.C:331
 testRec.C:332
 testRec.C:333
 testRec.C:334
 testRec.C:335
 testRec.C:336
 testRec.C:337
 testRec.C:338
 testRec.C:339
 testRec.C:340
 testRec.C:341
 testRec.C:342
 testRec.C:343
 testRec.C:344
 testRec.C:345
 testRec.C:346
 testRec.C:347
 testRec.C:348
 testRec.C:349
 testRec.C:350
 testRec.C:351
 testRec.C:352
 testRec.C:353
 testRec.C:354
 testRec.C:355
 testRec.C:356
 testRec.C:357
 testRec.C:358
 testRec.C:359
 testRec.C:360
 testRec.C:361
 testRec.C:362
 testRec.C:363
 testRec.C:364
 testRec.C:365
 testRec.C:366
 testRec.C:367
 testRec.C:368
 testRec.C:369
 testRec.C:370
 testRec.C:371
 testRec.C:372
 testRec.C:373
 testRec.C:374
 testRec.C:375
 testRec.C:376
 testRec.C:377
 testRec.C:378
 testRec.C:379
 testRec.C:380
 testRec.C:381
 testRec.C:382
 testRec.C:383
 testRec.C:384
 testRec.C:385
 testRec.C:386
 testRec.C:387
 testRec.C:388
 testRec.C:389
 testRec.C:390
 testRec.C:391
 testRec.C:392
 testRec.C:393
 testRec.C:394
 testRec.C:395
 testRec.C:396
 testRec.C:397
 testRec.C:398
 testRec.C:399
 testRec.C:400
 testRec.C:401
 testRec.C:402
 testRec.C:403
 testRec.C:404
 testRec.C:405
 testRec.C:406
 testRec.C:407
 testRec.C:408
 testRec.C:409
 testRec.C:410
 testRec.C:411
 testRec.C:412
 testRec.C:413
 testRec.C:414
 testRec.C:415
 testRec.C:416
 testRec.C:417
 testRec.C:418
 testRec.C:419
 testRec.C:420
 testRec.C:421
 testRec.C:422
 testRec.C:423
 testRec.C:424
 testRec.C:425
 testRec.C:426
 testRec.C:427
 testRec.C:428
 testRec.C:429
 testRec.C:430
 testRec.C:431
 testRec.C:432
 testRec.C:433
 testRec.C:434
 testRec.C:435
 testRec.C:436
 testRec.C:437
 testRec.C:438
 testRec.C:439
 testRec.C:440
 testRec.C:441
 testRec.C:442
 testRec.C:443
 testRec.C:444
 testRec.C:445
 testRec.C:446
 testRec.C:447
 testRec.C:448
 testRec.C:449
 testRec.C:450
 testRec.C:451
 testRec.C:452
 testRec.C:453
 testRec.C:454
 testRec.C:455
 testRec.C:456
 testRec.C:457
 testRec.C:458
 testRec.C:459
 testRec.C:460
 testRec.C:461
 testRec.C:462
 testRec.C:463
 testRec.C:464
 testRec.C:465
 testRec.C:466
 testRec.C:467
 testRec.C:468
 testRec.C:469
 testRec.C:470
 testRec.C:471
 testRec.C:472
 testRec.C:473
 testRec.C:474
 testRec.C:475
 testRec.C:476
 testRec.C:477
 testRec.C:478
 testRec.C:479
 testRec.C:480
 testRec.C:481
 testRec.C:482
 testRec.C:483
 testRec.C:484
 testRec.C:485
 testRec.C:486
 testRec.C:487
 testRec.C:488
 testRec.C:489
 testRec.C:490
 testRec.C:491
 testRec.C:492
 testRec.C:493
 testRec.C:494
 testRec.C:495
 testRec.C:496
 testRec.C:497
 testRec.C:498
 testRec.C:499
 testRec.C:500
 testRec.C:501
 testRec.C:502
 testRec.C:503
 testRec.C:504
 testRec.C:505
 testRec.C:506
 testRec.C:507
 testRec.C:508
 testRec.C:509
 testRec.C:510
 testRec.C:511
 testRec.C:512
 testRec.C:513
 testRec.C:514
 testRec.C:515
 testRec.C:516
 testRec.C:517
 testRec.C:518
 testRec.C:519
 testRec.C:520
 testRec.C:521
 testRec.C:522
 testRec.C:523
 testRec.C:524
 testRec.C:525
 testRec.C:526
 testRec.C:527
 testRec.C:528
 testRec.C:529
 testRec.C:530
 testRec.C:531
 testRec.C:532
 testRec.C:533
 testRec.C:534
 testRec.C:535
 testRec.C:536
 testRec.C:537
 testRec.C:538
 testRec.C:539
 testRec.C:540
 testRec.C:541
 testRec.C:542
 testRec.C:543
 testRec.C:544
 testRec.C:545
 testRec.C:546
 testRec.C:547
 testRec.C:548
 testRec.C:549
 testRec.C:550
 testRec.C:551
 testRec.C:552
 testRec.C:553
 testRec.C:554
 testRec.C:555
 testRec.C:556
 testRec.C:557
 testRec.C:558
 testRec.C:559
 testRec.C:560
 testRec.C:561
 testRec.C:562
 testRec.C:563
 testRec.C:564
 testRec.C:565
 testRec.C:566
 testRec.C:567
 testRec.C:568
 testRec.C:569
 testRec.C:570
 testRec.C:571
 testRec.C:572
 testRec.C:573
 testRec.C:574
 testRec.C:575
 testRec.C:576
 testRec.C:577
 testRec.C:578
 testRec.C:579
 testRec.C:580
 testRec.C:581
 testRec.C:582
 testRec.C:583
 testRec.C:584
 testRec.C:585
 testRec.C:586
 testRec.C:587
 testRec.C:588
 testRec.C:589
 testRec.C:590
 testRec.C:591
 testRec.C:592
 testRec.C:593
 testRec.C:594
 testRec.C:595
 testRec.C:596
 testRec.C:597
 testRec.C:598
 testRec.C:599
 testRec.C:600
 testRec.C:601
 testRec.C:602
 testRec.C:603
 testRec.C:604
 testRec.C:605
 testRec.C:606
 testRec.C:607
 testRec.C:608
 testRec.C:609
 testRec.C:610
 testRec.C:611
 testRec.C:612
 testRec.C:613
 testRec.C:614
 testRec.C:615
 testRec.C:616
 testRec.C:617
 testRec.C:618
 testRec.C:619
 testRec.C:620
 testRec.C:621
 testRec.C:622
 testRec.C:623
 testRec.C:624
 testRec.C:625
 testRec.C:626
 testRec.C:627
 testRec.C:628
 testRec.C:629
 testRec.C:630
 testRec.C:631
 testRec.C:632
 testRec.C:633
 testRec.C:634
 testRec.C:635
 testRec.C:636
 testRec.C:637
 testRec.C:638