]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - RICH/AliRICHRecon.cxx
MAJOR UPGRADE: 1. all objects are counted from 0 2. new AliRICHRecon 3. calib off...
[u/mrichter/AliRoot.git] / RICH / AliRICHRecon.cxx
index da26ee6722551fc0da253cd2c203c4376c74f529..023de2be14a9470037740710ceade17643a479a1 100644 (file)
 // AliRICHRecon                                                         //
 //                                                                      //
 // RICH class to perfom pattern recognition based on Hough transfrom    //
-//                                                                      //
+// for single chamber                                                   //
 //////////////////////////////////////////////////////////////////////////
 
-#include <Riostream.h>
-#include <TMath.h>
-#include <TRotation.h>
-#include <TVector3.h>
-
-#include "AliRICH.h"
-#include "AliRICHParam.h"
-#include "AliRICHRecon.h"
-#include "AliRICHHelix.h"
-#include <AliLog.h>
-
-#define NPointsOfRing 201
-
-//__________________________________________________________________________________________________
-AliRICHRecon::AliRICHRecon(AliRICHHelix *pHelix,TClonesArray *pClusters,Int_t iMipId)
-             :TTask("RichRec","RichPat")
+#include "AliRICHRecon.h"  //class header
+#include "AliRICHCluster.h" //CkovAngle()
+#include <AliLog.h>        //AliInfo()
+#include <TMath.h>         //many 
+#include <TRotation.h>      //
+#include <TH1D.h>          //HoughResponse()
+#include <TClonesArray.h>  //CkovAngle()
+
+const Double_t AliRICHRecon::fkRadThick=1.5;
+const Double_t AliRICHRecon::fkWinThick=0.5;
+const Double_t AliRICHRecon::fkGapThick=8.0;
+const Double_t AliRICHRecon::fkRadIdx  =1.292;
+const Double_t AliRICHRecon::fkWinIdx  =1.5787;
+const Double_t AliRICHRecon::fkGapIdx  =1.0005;
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+AliRICHRecon::AliRICHRecon():TTask("RichRec","RichPat"),
+  fPhotCnt(-1),
+  fCkovSigma2(0),
+  fIsWEIGHT(kFALSE),
+  fDTheta(0.001),
+  fWindowWidth(0.045),
+  fTrkDir(TVector3(0,0,1)),fTrkPos(TVector2(30,40))  
 {
 // main ctor
-  SetFreonScaleFactor(1);
-  fIsWEIGHT = kFALSE;
-  fThetaBin=750; fThetaMin = 0.0; fThetaMax = 0.75; 
-  fDTheta       = 0.001;   fWindowWidth  = 0.060;
-  fRadiatorWidth = AliRICHParam::Zfreon();
-  fQuartzWidth   = AliRICHParam::Zwin();
-  fGapWidth      = AliRICHParam::Freon2Pc() - fRadiatorWidth - fQuartzWidth;
-  fXmin         = -AliRICHParam::PcSizeX()/2.;
-  fXmax         =  AliRICHParam::PcSizeX()/2.;
-  fYmin         = -AliRICHParam::PcSizeY()/2.;
-  fYmax         =  AliRICHParam::PcSizeY()/2.; 
-  SetTrackTheta(pHelix->Ploc().Theta());
-  SetTrackPhi(pHelix->Ploc().Phi());
-  SetMipIndex(iMipId);
-  SetShiftX(pHelix->PosRad().X());
-  SetShiftY(pHelix->PosRad().Y());
-  fpClusters = pClusters;
+  for (Int_t i=0; i<3000; i++) {
+    fPhotFlag[i] =  0;
+    fPhotCkov[i] = -1;
+    fPhotPhi [i] = -1;
+    fPhotWei [i] =  0;
+  }
 }
-//__________________________________________________________________________________________________
-Double_t AliRICHRecon::ThetaCerenkov()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+Double_t AliRICHRecon::CkovAngle(TClonesArray *pCluLst,Int_t &iNaccepted)
 {
 // Pattern recognition method based on Hough transform
-// Return theta Cerenkov for a given track and list of clusters which are set in ctor  
-
-  if(fpClusters->GetEntries()==0) return -1;//no clusters at all for a given track
-  Bool_t kPatRec = kFALSE;  
-    
-  AliDebug(1,Form("---Track Parameters--- Theta: %f , Phi: %f ",GetTrackTheta()*TMath::RadToDeg(),GetTrackPhi()*TMath::RadToDeg()));
-
-  Int_t candidatePhotons = 0;
-
-  SetThetaCerenkov(999.);
-  SetHoughPhotons(0);
-  SetHoughPhotonsNorm(0);
-
-  for (Int_t j=0; j < fpClusters->GetEntries(); j++){//clusters loop
-    SetPhotonIndex(j);
-    SetPhotonFlag(0);
-    SetPhotonEta(-999.);
-    SetPhotonWeight(0.);
-    if (j == GetMipIndex()) continue; // do not consider MIP cluster as a candidate photon
-    Float_t xtoentr = ((AliRICHCluster*)fpClusters->UncheckedAt(j))->X() - GetShiftX();
-    Float_t ytoentr = ((AliRICHCluster*)fpClusters->UncheckedAt(j))->Y() - GetShiftY();
-    SetEntranceX(xtoentr);
-    SetEntranceY(ytoentr);
-    FindPhiPoint();
-//      Int_t photonStatus = PhotonInBand();
-//      if(photonStatus == 0) continue;
-    SetPhotonFlag(1);
-    FindThetaPhotonCerenkov();
-    Float_t thetaPhotonCerenkov = GetThetaPhotonCerenkov();
-    AliDebug(1,Form("THETA CERENKOV ---> %f",thetaPhotonCerenkov));
-    SetPhotonEta(thetaPhotonCerenkov);
-    candidatePhotons++;
-  }//clusters loop
-
-  if(candidatePhotons >= 1) kPatRec = kTRUE;
-
-  if(!kPatRec) return -1;
-
-  SetPhotonsNumber(fpClusters->GetEntries());
-
-  HoughResponse();
+// Arguments: pCluLst  - list of clusters for this chamber   
+//   Returns:          - track ckov angle, [rad], 
   
-  fNrings++;
-
-  FlagPhotons();
-  Int_t nPhotonHough = GetHoughPhotons();
-  if(nPhotonHough < 1) 
-    {
-      SetThetaCerenkov(999.);
-      SetHoughPhotonsNorm(0.);
-      return -1;
-    }
+  if(pCluLst->GetEntries()>200) fIsWEIGHT = kTRUE; // offset to take into account bkg in reconstruction
+  else                          fIsWEIGHT = kFALSE;
 
-  FindThetaCerenkov();
+  // Photon Flag:  Flag = 0 initial set; Flag = 1 good candidate (charge compatible with photon); Flag = 2 photon used for the ring;
 
-  AliDebug(1,Form("Number of clusters accepted --->  %i",nPhotonHough));
-  
-//  Float_t thetaCerenkov = GetThetaCerenkov();  
-//  SetThetaOfRing(thetaCerenkov);
-//  FindAreaAndPortionOfRing();
-
-//  Float_t nPhotonHoughNorm = ((Float_t)nPhotonHough)/GetPortionOfRing();
-//  SetHoughPhotonsNorm(nPhotonHoughNorm);
-
-  // Calculate the area where the photon are accepted...
-/*
-  Float_t thetaInternal = thetaCerenkov - 0.5*fWindowWidth; 
-  SetThetaOfRing(thetaInternal);
-  FindAreaAndPortionOfRing();
-  Float_t internalArea = GetAreaOfRing();
-
-  Float_t thetaExternal = thetaCerenkov + 0.5*fWindowWidth; 
-  SetThetaOfRing(thetaExternal);
-  FindAreaAndPortionOfRing();
-  Float_t externalArea = GetAreaOfRing();
-
-  Float_t houghArea = externalArea - internalArea;
-
-  SetHoughArea(houghArea);
-*/
-  return GetThetaCerenkov();
+  fPhotCnt=0;                                                      
+  for (Int_t iClu=0; iClu<pCluLst->GetEntriesFast();iClu++){//clusters loop
+    AliRICHCluster *pClu=(AliRICHCluster*)pCluLst->UncheckedAt(iClu);                       //get pointer to current cluster    
+    if(pClu->Q()>100) continue;                                                             //avoid MIP clusters from bkg
+    
+    fPhotCkov[fPhotCnt]=FindPhotCkov(pClu->X(),pClu->Y());                                  //find ckov angle for this  photon candidate
+    fPhotCnt++;         //increment counter of photon candidates
+  }//clusters loop
 
+  iNaccepted=FlagPhot(HoughResponse()); //flag photons according to individual theta ckov with respect to most probable track theta ckov
+  if(iNaccepted<1) return -11; 
+  else             return FindRingCkov(pCluLst->GetEntries());  //find best Theta ckov for ring i.e. track
 }//ThetaCerenkov()
-//__________________________________________________________________________________________________
-void AliRICHRecon::FindEmissionPoint()
-{
-  //estimate the emission point in radiator
-
-// Find emission point
-
-  Float_t absorbtionLenght=7.83*fRadiatorWidth; //absorption length in the freon (cm)
-  // 7.83 = -1/ln(T0) where 
-  // T0->Trasmission freon at 180nm = 0.88 (Eph=6.85eV)
-  Float_t photonLenght, photonLenghtMin, photonLenghtMax;
-
-  photonLenght=exp(-fRadiatorWidth/(absorbtionLenght*cos(fCerenkovAnglePad)));
-  photonLenghtMin=fRadiatorWidth*photonLenght/(1.-photonLenght);
-  photonLenghtMax=absorbtionLenght*cos(fCerenkovAnglePad);
-  Float_t emissionPoint = fRadiatorWidth + photonLenghtMin - photonLenghtMax;
-
-  SetEmissionPoint(emissionPoint);
-  SetEmissionPoint(fRadiatorWidth/2); // tune the emission point
-}
-//__________________________________________________________________________________________________
-Int_t AliRICHRecon::PhotonInBand()
-{
-  //search band fro photon candidates
-
-  //  Float_t massOfParticle;
-  Float_t nfreon;
-
-  Float_t thetacer;
-
-  Float_t xtoentr = GetEntranceX();
-  Float_t ytoentr = GetEntranceY();
-
-  Float_t innerRadius;
-  Float_t outerRadius;
-
-  Float_t phpad = GetPhiPoint();
-
-
-  // inner radius //
-  SetPhotonEnergy(5.6);
-  SetEmissionPoint(fRadiatorWidth -0.0001);
-  SetFreonRefractiveIndex();
-
-  nfreon = GetFreonRefractiveIndex();
-  thetacer = 0.;
-
-  AliDebug(1,Form("thetacer in photoninband min %f",thetacer));
-
-  FindThetaAtQuartz(thetacer);
-
-  if(thetacer == 999. || GetThetaAtQuartz() == 999.)
-    {
-      innerRadius = -999.;
-      SetXInnerRing(-999.);
-      SetYInnerRing(-999.);
-      SetRadiusInnerRing(-999.);
-    }
-  else
-    {
-      SetThetaPhotonInDRS(GetThetaAtQuartz());
-      SetPhiPhotonInDRS(phpad);
-
-      innerRadius = FromEmissionToCathode();
-       if(innerRadius == 999.) innerRadius = -999.;
-      
-      SetXInnerRing(GetXPointOnCathode());
-      SetYInnerRing(GetYPointOnCathode());
-      SetRadiusInnerRing(innerRadius);
-    }
-  
-  // outer radius //
-  SetPhotonEnergy(7.7);
-  SetEmissionPoint(0.);
-//  SetMassHypotesis(0.139567);
-  SetFreonRefractiveIndex();
-
-  nfreon = GetFreonRefractiveIndex();
-
-  thetacer = Cerenkovangle(nfreon,1);
-
-  //  thetacer = 0.75;
-
-  AliDebug(1,Form("thetacer in photoninband max %f",thetacer));
-
-  FindThetaAtQuartz(thetacer);
-
-  if(thetacer == 999. || GetThetaAtQuartz() == 999.)
-    {
-      outerRadius = 999.;
-      SetXOuterRing(999.);
-      SetYOuterRing(999.);
-      SetRadiusOuterRing(999.);
-    }
-  else
-    {
-      SetThetaPhotonInDRS(GetThetaAtQuartz());
-      SetPhiPhotonInDRS(phpad);
-
-      outerRadius = FromEmissionToCathode();
-//      cout << " outerRadius " << outerRadius << endl;
-      SetXOuterRing(GetXPointOnCathode());
-      SetYOuterRing(GetYPointOnCathode());
-      SetRadiusOuterRing(outerRadius);
-    }
-
-  Float_t padradius = sqrt(TMath::Power(xtoentr,2)+TMath::Power(ytoentr,2));
-  
-  AliDebug(1,Form("rmin %f r %f rmax %f",innerRadius,padradius,outerRadius));
-
-  if(padradius>=innerRadius && padradius<=outerRadius) return 1;
-  return 0;
-}
-//__________________________________________________________________________________________________
-void AliRICHRecon::FindThetaAtQuartz(Float_t thetaCerenkov)
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+Double_t AliRICHRecon::FindPhotCkov(Double_t cluX,Double_t cluY)
 {
-  //find the theta at the quartz plate
-
-  if(thetaCerenkov == 999.) 
-    {
-      SetThetaAtQuartz(999.);
-      return;
-    }
-
-  Float_t thetaAtQuartz = 999.;
-
-  Float_t trackTheta = GetTrackTheta();
-
-  if(trackTheta == 0) {
-
-    thetaAtQuartz = thetaCerenkov;
-    SetThetaAtQuartz(thetaAtQuartz);
-    return;
+// Finds Cerenkov angle  for this photon candidate
+// Arguments: cluX,cluY - position of cadidate's cluster  
+//   Returns: Cerenkov angle 
+
+  TVector2 pos(cluX,cluY); Double_t cluR=(pos-fTrkPos).Mod();  Double_t phi=FindPhotPhi(cluX,cluY);      
+  Printf("new dist %f phi %f",cluR,phi);
+  Double_t ckov1=0,ckov2=0.75;
+  const Double_t kTol=0.05; 
+  Int_t iIterCnt = 0;
+  while(1){
+    if(iIterCnt>=50) return -1;
+    Double_t ckov=0.5*(ckov1+ckov2);
+    Double_t dist=cluR-TracePhoton(ckov,phi,pos); iIterCnt++; //get distance between trial point and cluster position
+    Printf("New: phi %f ckov %f dist %f",phi,ckov,dist);
+    if     (dist> kTol) ckov1=ckov;                           //cluster @ larger ckov 
+    else if(dist<-kTol) ckov2=ckov;                           //cluster @ smaller ckov
+    else                return ckov;                          //precision achived         
   }
-
-  Float_t trackPhi   = GetTrackPhi();
-  Float_t phiPoint = GetPhiPoint();
-
-  Double_t den = TMath::Sin((Double_t)trackTheta)
-    *TMath::Cos((Double_t)trackPhi)
-    *TMath::Cos((Double_t)phiPoint) +
-    TMath::Sin((Double_t)trackTheta)
-    *TMath::Sin((Double_t)trackPhi)
-    *TMath::Sin((Double_t)phiPoint); 
-  Double_t b = TMath::Cos((Double_t)trackTheta)/den;
-  Double_t c = -TMath::Cos((Double_t)thetaCerenkov)/den;
-
-  Double_t underSqrt = 1 + b*b - c*c;
-
-  if(underSqrt < 0) {
-    SetThetaAtQuartz(999.);
-    return;
-  }
-
-  Double_t sol1 = (1+TMath::Sqrt(underSqrt))/(b-c);
-  Double_t sol2 = (1-TMath::Sqrt(underSqrt))/(b-c);
-
-  Double_t thetaSol1 = 2*TMath::ATan(sol1);
-  Double_t thetaSol2 = 2*TMath::ATan(sol2);
-
-  if(thetaSol1>0 && thetaSol1 < TMath::Pi()) thetaAtQuartz = (Float_t)thetaSol1;
-  if(thetaSol2>0 && thetaSol2 < TMath::Pi()) thetaAtQuartz = (Float_t)thetaSol2;
-
-//  AliDebug(1,Form(" Theta @ quartz window %f ",thetaAtQuartz));
-
-  SetThetaAtQuartz(thetaAtQuartz);
-}
-//__________________________________________________________________________________________________
-void AliRICHRecon::FindThetaPhotonCerenkov()
+}//FindPhotTheta()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+Double_t AliRICHRecon::FindPhotPhi(Double_t cluX,Double_t cluY)
 {
-  //find theta cerenkov of ring
-
-  Float_t thetaCerMin = 0.;
-  Float_t thetaCerMax = 0.75;
-  Float_t thetaCerMean;
-
-  Float_t radiusMin, radiusMax, radiusMean;
-  Int_t nIteration = 0;
-
-  const Float_t kTollerance = 0.05;
-
-
-  Float_t phiPoint = GetPhiPoint();
-
-  SetPhotonEnergy(AliRICHParam::MeanCkovEnergy());
-  SetEmissionPoint(fRadiatorWidth/2);
-
-  Float_t xPoint = GetEntranceX();
-  Float_t yPoint = GetEntranceY();
-  Float_t distPoint = TMath::Sqrt(xPoint*xPoint + yPoint*yPoint);
-
-//  AliDebug(1,Form(" DistPoint %f ",distPoint));
-
-  // Star minimization...
-
-  // First value...
-
-  FindThetaAtQuartz(thetaCerMin);
+// Finds phi angle og photon candidate by considering the cluster's position  of this candudate w.r.t track position
   
-  if(GetThetaAtQuartz() == 999.)
-    {
-      radiusMin = -999.;
-    }
-  else
-    {
-      SetThetaPhotonInDRS(GetThetaAtQuartz());
-      SetPhiPhotonInDRS(phiPoint);
-      
-      radiusMin = FromEmissionToCathode();
-    }
-
-  // Second value...
-
-  FindThetaAtQuartz(thetaCerMax);
-  if(GetThetaAtQuartz() == 999.)
-    {
-      radiusMax = 999.;
-    }
-  else
-    {
-      SetThetaPhotonInDRS(GetThetaAtQuartz());
-      SetPhiPhotonInDRS(phiPoint);
-      
-      radiusMax = FromEmissionToCathode();
-    }
-  // Mean value...
-
-  thetaCerMean = (thetaCerMax + thetaCerMin)/2;
-
-  FindThetaAtQuartz(thetaCerMean);
-  if(GetThetaAtQuartz() == 999.)
-    {
-      radiusMean = 999.;
-    }
-  else
-    {
-      SetThetaPhotonInDRS(GetThetaAtQuartz());
-      SetPhiPhotonInDRS(phiPoint);
-      
-      radiusMean = FromEmissionToCathode();
-    }
-
-//  AliDebug(1,Form(" r1 %f rmean %f r2 %f",radiusMin,radiusMean,radiusMax));
-
-  while (TMath::Abs(radiusMean-distPoint) > kTollerance)
-    {
-
-      if((radiusMin-distPoint)*(radiusMean-distPoint) < 0) thetaCerMax = thetaCerMean;
-      if((radiusMin-distPoint)*(radiusMean-distPoint) > 0) {
-
-       thetaCerMin = thetaCerMean;
-
-       FindThetaAtQuartz(thetaCerMin);
-       SetThetaPhotonInDRS(GetThetaAtQuartz());
-       SetPhiPhotonInDRS(phiPoint);
-
-       radiusMin =FromEmissionToCathode();
-      }
-
-      thetaCerMean = (thetaCerMax + thetaCerMin)/2;
-
-      FindThetaAtQuartz(thetaCerMean);
-      SetThetaPhotonInDRS(GetThetaAtQuartz());
-      SetPhiPhotonInDRS(phiPoint);
-
-      radiusMean = FromEmissionToCathode();
-
-      nIteration++;
-      if(nIteration>=50) {
-//     AliDebug(1,Form(" max iterations in FindPhotonCerenkov ",nIteration));
-       SetThetaPhotonCerenkov(999.);
-       return;
-      }
-    }
-
-//  AliDebug(1,Form(" distpoint %f radius %f ",distPoint,radiusMean));
-  SetThetaPhotonCerenkov(thetaCerMean);
-
+  Double_t emiss=0; 
+  return fPhotPhi[fPhotCnt]=TMath::ATan2(cluY-fTrkPos.Y()-emiss*TMath::Tan(fTrkDir.Theta())*TMath::Sin(fTrkDir.Phi()),
+                                         cluX-fTrkPos.X()-emiss*TMath::Tan(fTrkDir.Theta())*TMath::Cos(fTrkDir.Phi()));
 }
-//__________________________________________________________________________________________________
-void AliRICHRecon::FindAreaAndPortionOfRing()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+Double_t AliRICHRecon::FindRingArea(Double_t ckovAng)const
 {
-  //find fraction of the ring accepted by the RICH
-
-  Float_t xPoint[NPointsOfRing], yPoint[NPointsOfRing];
-
-  //  Float_t xtoentr = GetEntranceX();
-  //  Float_t ytoentr = GetEntranceY();
-  Float_t shiftX = GetShiftX();
-  Float_t shiftY = GetShiftY();
-
-  Float_t xemiss = GetXCoordOfEmission(); 
-  Float_t yemiss = GetYCoordOfEmission(); 
-
-  Float_t x0 = xemiss + shiftX;
-  Float_t y0 = yemiss + shiftY;
-
-
-  SetPhotonEnergy(AliRICHParam::MeanCkovEnergy());
-  SetFreonRefractiveIndex();
-
-  SetEmissionPoint(fRadiatorWidth/2.);
-
-  Float_t theta = GetThetaOfRing();
+// Find area inside the cerenkov ring which lays inside PCs
+// Arguments: ckovThe - cernkov    
+//   Returns: area of the ring in cm^2 for given theta ckov
+   
   
-  Int_t nPoints = 0;
-  Int_t nPsiAccepted = 0;
-  Int_t nPsiTotal = 0;
-
-  for(Int_t i=0;i<NPointsOfRing-1;i++)
-    {
-
-      Float_t psi = 2*TMath::Pi()*i/NPointsOfRing;
-      
-      SetThetaPhotonInTRS(theta);
-      SetPhiPhotonInTRS(psi);
-      FindPhotonAnglesInDRS();
-      
-      Float_t radius = FromEmissionToCathode();
-      if (radius == 999.) continue;
-      
-      nPsiTotal++;
-
-      Float_t xPointRing = GetXPointOnCathode() + shiftX;
-      Float_t yPointRing = GetYPointOnCathode() + shiftY;
-      
-      SetDetectorWhereX(xPointRing);
-      SetDetectorWhereY(yPointRing);
+  TVector2 pos1,pos2;
+  
+  const Int_t kN=100;
+  Double_t area=0;
+  for(Int_t i=0;i<kN;i++){
+    TracePhoton(ckovAng,Double_t(TMath::TwoPi()*i    /kN),pos1);//trace this photon 
+    TracePhoton(ckovAng,Double_t(TMath::TwoPi()*(i+1)/kN),pos2);//trace this photon 
+    area+=(pos1-fTrkPos)*(pos2-fTrkPos);
       
-      Int_t zone = CheckDetectorAcceptance();
-
-
-      if (zone != 0) 
-       {
-         FindIntersectionWithDetector();
-         xPoint[nPoints] = GetIntersectionX();
-         yPoint[nPoints] = GetIntersectionY();
-       }
-      else
-       {
-         xPoint[nPoints] = xPointRing;
-         yPoint[nPoints] = yPointRing;
-         nPsiAccepted++;
-       }
-
-      nPoints++;
-
-    }
-
-  xPoint[nPoints] = xPoint[0];
-  yPoint[nPoints] = yPoint[0];
+  }
+  return area;
+}//RingArea()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+Double_t AliRICHRecon::TracePhoton(Double_t ckovThe,Double_t ckovPhi,TVector2 &pos)const
+{
+// Trace a single Ckov photon from emission point somewhere in radiator up to photocathode taking into account ref indexes of materials it travereses
+// Arguments: ckovThe,ckovPhi- photon ckov angles, [rad]  (warning: not photon theta and phi)     
+//   Returns: distance between photon point on PC and track projection  
+  TRotation mtheta;   mtheta.RotateY(fTrkDir.Theta());
+  TRotation mphi;       mphi.RotateZ(fTrkDir.Phi());  
+  TRotation mrot=mphi*mtheta;
   
-  // find area...
-
-  Float_t area = 0;
-
-  for (Int_t i = 0; i < nPoints; i++)
-    {
-      area += TMath::Abs((xPoint[i]-x0)*(yPoint[i+1]-y0) - (xPoint[i+1]-x0)*(yPoint[i]-y0));
-    }
+  TVector3  posCkov(fTrkPos.X(),fTrkPos.Y(),-0.5*fkRadThick-fkWinThick-fkGapThick);   //RAD: photon position is track position @ middle of RAD 
+  TVector3  dirCkov;   dirCkov.SetMagThetaPhi(1,ckovThe,ckovPhi);                     //initially photon is directed according to requested ckov angle
+                                               dirCkov=mrot*dirCkov;                  //now we know photon direction in LORS
+                       dirCkov.SetPhi(ckovPhi);   
+  if(dirCkov.Theta() > TMath::ASin(1./fkRadIdx)) return -999;//total refraction on WIN-GAP boundary
   
-  area *= 0.5;
+  Propagate(dirCkov,posCkov,-fkWinThick-fkGapThick); //go to RAD-WIN boundary  remeber that z=0 is PC plane
+  Refract  (dirCkov,         fkRadIdx,fkWinIdx    ); //RAD-WIN refraction
+  Propagate(dirCkov,posCkov,-fkGapThick           ); //go to WIN-GAP boundary
+  Refract  (dirCkov,         fkWinIdx,fkGapIdx    ); //WIN-GAP refraction
+  Propagate(dirCkov,posCkov,0                     ); //go to PC
   
-  Float_t portionOfRing = ((Float_t)nPsiAccepted)/((Float_t)(nPsiTotal));
-
-
-  SetAreaOfRing(area);
-  SetPortionOfRing(portionOfRing);
-}
-//__________________________________________________________________________________________________
-void AliRICHRecon::FindIntersectionWithDetector()
+  pos.Set(posCkov.X(),posCkov.Y());
+  return (pos-fTrkPos).Mod();
+}//TracePhoton()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliRICHRecon::Propagate(const TVector3 &dir,TVector3 &pos,Double_t z)const
 {
-  // find ring intersection with CsI edges
-
-  Float_t xIntersect, yIntersect;
-  Float_t x1, x2, y1, y2;
-
-  Float_t shiftX = GetShiftX();
-  Float_t shiftY = GetShiftY();
-
-  Float_t xPoint = GetXPointOnCathode() + shiftX;
-  Float_t yPoint = GetYPointOnCathode() + shiftY;
-
-  Float_t xemiss = GetXCoordOfEmission(); 
-  Float_t yemiss = GetYCoordOfEmission(); 
-
-  Float_t phi = GetPhiPhotonInDRS();
-  Float_t m = tan(phi);
-
-  Float_t x0 = xemiss + shiftX;
-  Float_t y0 = yemiss + shiftY;
-
-  if(xPoint > x0)
-    {
-      x1 = x0;
-      x2 = xPoint;
-    }
-  else
-    {
-      x2 = x0;
-      x1 = xPoint;
-    }
-  if(yPoint > y0)
-    {
-      y1 = y0;
-      y2 = yPoint;
-    }
-  else
-    {
-      y2 = y0;
-      y1 = yPoint;
-    }
-  //
-  xIntersect = fXmax;
-  yIntersect = m*(xIntersect - x0) + y0;
-  if (yIntersect >= fYmin && yIntersect <= fYmax && xIntersect >= x1 && xIntersect <= x2)
-    {
-      SetIntersectionX(xIntersect);
-      SetIntersectionY(yIntersect);
-      return;
-    }
-  //
-  xIntersect = fXmin;
-  yIntersect = m*(xIntersect - x0) + y0;
-  if (yIntersect >= fYmin && yIntersect <= fYmax && xIntersect >= x1 && xIntersect <= x2)
-    {
-      SetIntersectionX(xIntersect);
-      SetIntersectionY(yIntersect);
-      return;
-    }
-  //
-  yIntersect = fYmax;
-  xIntersect = (yIntersect - y0)/m + x0;
-  if (xIntersect >= fXmin && xIntersect <= fXmax && yIntersect >= y1 && yIntersect <= y2)
-    {
-      SetIntersectionX(xIntersect);
-      SetIntersectionY(yIntersect);
-      return;
-    }
-  //
-  yIntersect = fYmin;
-  xIntersect = (yIntersect - y0)/m + x0;
-  if (xIntersect >= fXmin && xIntersect <= fXmax && yIntersect >= y1 && yIntersect <= y2)
-    {
-      SetIntersectionX(xIntersect);
-      SetIntersectionY(yIntersect);
-      return;
-    }
+// Finds an intersection point between a line and XY plane shifted along Z.
+// Arguments:  dir,pos   - vector along the line and any point of the line
+//             z         - z coordinate of plain 
+//   Returns:  none
+//   On exit:  pos is the position if this intesection if any
+  static TVector3 nrm(0,0,1); 
+         TVector3 pnt(0,0,z);
   
-  cout << " sono fuori!!!!!!" << endl;
-  
-}
-//__________________________________________________________________________________________________
-Int_t AliRICHRecon::CheckDetectorAcceptance() const
+  TVector3 diff=pnt-pos;
+  Double_t sint=(nrm*diff)/(nrm*dir);
+  pos+=sint*dir;
+}//Propagate()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliRICHRecon::Refract(TVector3 &dir,Double_t n1,Double_t n2)const
 {
-  // check for the acceptance
-
-  // crosses X -2.6 2.6 cm
-  // crosses Y -1 1 cm
-
-  Float_t xcoord = GetDetectorWhereX();
-  Float_t ycoord = GetDetectorWhereY();
-
-  if(xcoord > fXmax)
-    {
-      if(ycoord > fYmax) return 2;
-      if(ycoord > fYmin && ycoord < fYmax) return 3;
-      if(ycoord < fYmin) return 4;
-    }
-  if(xcoord < fXmin)
-    {
-      if(ycoord > fYmax) return 8;
-      if(ycoord > fYmin && ycoord < fYmax) return 7;
-      if(ycoord < fYmin) return 6;
-    }
-  if(xcoord > fXmin && xcoord < fXmax)
-    {
-      if(ycoord > fYmax) return 1;
-      if(ycoord > fYmin && ycoord < fYmax) return 0;
-      if(ycoord < fYmin) return 5;
-    }
-  return 999;
-}
-//__________________________________________________________________________________________________
-void AliRICHRecon::FindPhotonAnglesInDRS()
+// Refract direction vector according to Snell law
+// Arguments: 
+//            n1 - ref idx of first substance
+//            n2 - ref idx of second substance
+//   Returns: none
+//   On exit: dir is new direction
+  Double_t sinref=(n1/n2)*TMath::Sin(dir.Theta());
+  if(sinref>1.)    dir.SetXYZ(-999,-999,-999);
+  else             dir.SetTheta(TMath::ASin(sinref));
+}//Refract()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+Double_t AliRICHRecon::HoughResponse()
 {
-  // Setup the rotation matrix of the track...
-
-  TRotation mtheta;
-  TRotation mphi;
-  TRotation minv;
-  TRotation mrot;
+//
+//
+//       
+  Double_t kThetaMax=0.75;
+  Int_t nChannels = (Int_t)(kThetaMax/fDTheta+0.5);
+  TH1D *phots   = new TH1D("Rphot"  ,"phots"         ,nChannels,0,kThetaMax);
+  TH1D *photsw  = new TH1D("RphotWeighted" ,"photsw" ,nChannels,0,kThetaMax);
+  TH1D *resultw = new TH1D("resultw","resultw"       ,nChannels,0,kThetaMax);
+  Int_t nBin = (Int_t)(kThetaMax/fDTheta);
+  Int_t nCorrBand = (Int_t)(fWindowWidth/(2*fDTheta));
   
-  Float_t trackTheta = GetTrackTheta();
-  Float_t trackPhi = GetTrackPhi();
-
-  mtheta.RotateY(trackTheta);
-  mphi.RotateZ(trackPhi);
+  for (Int_t i=0; i< fPhotCnt; i++){//photon cadidates loop
+    Double_t angle = fPhotCkov[i];  if(angle<0||angle>kThetaMax) continue;
+    phots->Fill(angle);
+    Int_t bin = (Int_t)(0.5+angle/(fDTheta));
+    Double_t weight=1.;
+    if(fIsWEIGHT){
+      Double_t lowerlimit = ((Double_t)bin)*fDTheta - 0.5*fDTheta;  Double_t upperlimit = ((Double_t)bin)*fDTheta + 0.5*fDTheta;   
+      Double_t diffArea = FindRingArea(upperlimit)-FindRingArea(lowerlimit);
+      if(diffArea>0) weight = 1./diffArea;
+    }
+    photsw->Fill(angle,weight);
+    fPhotWei[i]=weight;
+  }//photon candidates loop 
+   
+  for (Int_t i=1; i<=nBin;i++){
+    Int_t bin1= i-nCorrBand;
+    Int_t bin2= i+nCorrBand;
+    if(bin1<1) bin1=1;
+    if(bin2>nBin)bin2=nBin;
+    Double_t sumPhots=phots->Integral(bin1,bin2);
+    if(sumPhots<3) continue;                            // if less then 3 photons don't trust to this ring
+    Double_t sumPhotsw=photsw->Integral(bin1,bin2);
+    resultw->Fill((Double_t)((i+0.5)*fDTheta),sumPhotsw);
+  } 
+// evaluate the "BEST" theta ckov as the maximum value of histogramm
+  Double_t *pVec = resultw->GetArray();
+  Int_t locMax = TMath::LocMax(nBin,pVec);
+  phots->Delete();photsw->Delete();resultw->Delete(); // Reset and delete objects
   
-  mrot = mphi * mtheta;
-  //  minv = mrot.Inverse();
-
-  TVector3 photonInRadiator(1,1,1);
-
-  Float_t thetaCerenkov = GetThetaPhotonInTRS();
-  Float_t phiCerenkov   = GetPhiPhotonInTRS();
-
-  photonInRadiator.SetTheta(thetaCerenkov);
-  photonInRadiator.SetPhi(phiCerenkov);
-  photonInRadiator = mrot * photonInRadiator;
-  Float_t theta = photonInRadiator.Theta();
-  Float_t phi = photonInRadiator.Phi();
-  SetThetaPhotonInDRS(theta);
-  SetPhiPhotonInDRS(phi);
-
-}
-//__________________________________________________________________________________________________
-Float_t AliRICHRecon::FromEmissionToCathode()
+  return (Double_t)(locMax*fDTheta+0.5*fDTheta); //final most probable track theta ckov   
+}//HoughResponse()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+Double_t AliRICHRecon::FindRingCkov(Int_t)
 {
-  // trace from emission point to cathode
-
-  Float_t nfreon, nquartz, ngas; 
-
-  SetFreonRefractiveIndex();
-  SetQuartzRefractiveIndex();
-  SetGasRefractiveIndex();
-
-  nfreon  = GetFreonRefractiveIndex();
-  nquartz = GetQuartzRefractiveIndex();
-  ngas    = GetGasRefractiveIndex();
-
-  Float_t trackTheta = GetTrackTheta();
-  Float_t trackPhi = GetTrackPhi();
-  Float_t lengthOfEmissionPoint = GetEmissionPoint();
-
-  Float_t theta = GetThetaPhotonInDRS();
-  Float_t phi   = GetPhiPhotonInDRS();
-
-//   cout << " Theta " << Theta << " Phi " << Phi << endl;
+// Loops on all Ckov candidates and estimates the best Theta Ckov for a ring formed by those candidates. Also estimates an error for that Theat Ckov
+// collecting errors for all single Ckov candidates thetas. (Assuming they are independent)  
+// Arguments: iNclus- total number of clusters in chamber for background estimation
+//    Return: best estimation of track Theta ckov
 
-  Float_t xemiss = lengthOfEmissionPoint*tan(trackTheta)*cos(trackPhi);
-  Float_t yemiss = lengthOfEmissionPoint*tan(trackTheta)*sin(trackPhi);
+  Double_t wei = 0.;
+  Double_t weightThetaCerenkov = 0.;
 
-  SetXCoordOfEmission(xemiss);
-  SetYCoordOfEmission(yemiss);
+  Double_t ckovMin=9999.,ckovMax=0.;
+  Double_t sigma2 = 0;   //to collect error squared for this ring
   
-  Float_t thetaquar = SnellAngle(nfreon, nquartz, theta);
-
-  if(thetaquar == 999.) 
-    {
-      SetXPointOnCathode(999.);
-      SetYPointOnCathode(999.);
-      return thetaquar;
-    }
-
-  Float_t thetagap  = SnellAngle( nquartz, ngas, thetaquar);
-
-  if(thetagap == 999.) 
-    {
-      SetXPointOnCathode(999.);
-      SetYPointOnCathode(999.);
-      return thetagap;
+  for(Int_t i=0;i<fPhotCnt;i++){//candidates loop
+    if(fPhotFlag[i] == 2){
+      if(fPhotCkov[i]<ckovMin) ckovMin=fPhotCkov[i];  //find max and min Theta ckov from all candidates within probable window
+      if(fPhotCkov[i]>ckovMax) ckovMax=fPhotCkov[i]; 
+      weightThetaCerenkov += fPhotCkov[i]*fPhotWei[i];   wei += fPhotWei[i];                 //collect weight as sum of all candidate weghts   
+      
+     //Double_t phiref=(GetPhiPoint()-GetTrackPhi());
+       if(fPhotCkov[i]<=0) continue;//?????????????????Flag photos = 2 may imply CkovEta = 0?????????????? 
+                                     
+      sigma2 += 1./Sigma2(fPhotCkov[i],fPhotPhi[i],fTrkDir.Theta(),fTrkDir.Phi());
     }
-
-  Float_t xw = (fRadiatorWidth - lengthOfEmissionPoint)*cos(phi)*tan(theta);
-  Float_t xq = fQuartzWidth*cos(phi)*tan(thetaquar);
-  Float_t xg = fGapWidth*cos(phi)*tan(thetagap);
-  Float_t yw = (fRadiatorWidth - lengthOfEmissionPoint)*sin(phi)*tan(theta);
-  Float_t yq = fQuartzWidth*sin(phi)*tan(thetaquar);
-  Float_t yg = fGapWidth*sin(phi)*tan(thetagap);
-
-
-  Float_t xtot = xemiss + xw + xq + xg;
-  Float_t ytot = yemiss + yw + yq + yg;
-
-  SetXPointOnCathode(xtot);
-  SetYPointOnCathode(ytot);
-
-
-  Float_t distanceFromEntrance = sqrt(TMath::Power(fPhotonLimitX,2)
-                                   +TMath::Power(fPhotonLimitY,2)); 
-
-  return distanceFromEntrance;
-
-}
-//__________________________________________________________________________________________________
-void AliRICHRecon::FindPhiPoint()
-{
-  //find phi of generated point 
-
-  Float_t xtoentr = GetEntranceX();
-  Float_t ytoentr = GetEntranceY();
-
-  Float_t trackTheta = GetTrackTheta();
-  Float_t trackPhi = GetTrackPhi();
-
-  Float_t emissionPoint = GetEmissionPoint();
-
-  Float_t argY = ytoentr - emissionPoint*tan(trackTheta)*sin(trackPhi);
-  Float_t argX = xtoentr - emissionPoint*tan(trackTheta)*cos(trackPhi);
-  Float_t phi = atan2(argY,argX);
-
-  SetPhiPoint(phi);
-
-}
-//__________________________________________________________________________________________________
-Float_t AliRICHRecon::Cerenkovangle(Float_t n, Float_t beta)
-{
-  // cerenkov angle from n and beta
-
-// Compute the cerenkov angle
-
-  Float_t thetacer;
-
-  if((n*beta)<1.) {
-    thetacer = 999.;
-    //    cout << " warning in Cerenkoangle !!!!!! " << endl;
-    return thetacer;
-  }
-
-  thetacer = acos (1./(n*beta));
-  return thetacer;
-}
-//__________________________________________________________________________________________________
-Float_t AliRICHRecon::SnellAngle(Float_t n1, Float_t n2, Float_t theta1)
-{
-  // Snell law
-
-// Compute the Snell angle
-
-  Float_t sinrefractangle;
-  Float_t refractangle;
-
-  sinrefractangle = (n1/n2)*sin(theta1);
-
-  if(sinrefractangle>1.) {
-    //    cout << " PROBLEMS IN SNELL ANGLE !!!!! " << endl;
-    refractangle = 999.;
-    return refractangle;
-  }
+  }//candidates loop
   
-  refractangle = asin(sinrefractangle);  
-  return refractangle;
-}
-//__________________________________________________________________________________________________
-void AliRICHRecon::HoughResponse()
-{
-  //Hough response
-
-// Implement Hough response pat. rec. method
-
-  Float_t *hCSspace;
-
-  int          bin=0;
-  int           bin1=0;
-  int           bin2=0;
-  int           i, j, k, nCorrBand;
-  float         hcs[750],hcsw[750];
-  float         angle, weight;
-  float         lowerlimit,upperlimit;
-
-  float         etaPeak[100];
-
-  int           nBin;
-
-  float etaPeakPos  = -1;
-
-  Int_t   etaPeakCount = -1;
+  if(sigma2>0) fCkovSigma2=1./sigma2;
+  else         fCkovSigma2=1e10;  
   
-  Float_t thetaCerenkov = 0.;
-    
-  nBin = (int)(0.5+fThetaMax/(fDTheta));
-  nCorrBand = (int)(0.5+ fWindowWidth/(2 * fDTheta)); 
-
-  memset ((void *)hcs, 0, fThetaBin*sizeof(float));
-  memset ((void *)hcsw, 0, fThetaBin*sizeof(float));
-
-  Int_t nPhotons = GetPhotonsNumber();
-
-  Int_t weightFlag = 0;
-
-  for (k=0; k< nPhotons; k++) {
-
-    SetPhotonIndex(k);
-
-    angle = GetPhotonEta();
-
-    if(angle == -999.) continue;
-
-    if (angle>=fThetaMin && angle<= fThetaMax) 
-
-      {
-
-       bin = (int)(0.5+angle/(fDTheta));
-
-       bin1= bin-nCorrBand;
-       bin2= bin+nCorrBand;
-
-       // calculate weights
-
-       if(fIsWEIGHT)
-         {
-           lowerlimit = ((Float_t)bin1)*fDTheta + 0.5*fDTheta;
-           SetThetaOfRing(lowerlimit);
-           FindAreaAndPortionOfRing();
-           Float_t area1 = GetAreaOfRing();
-           
-           upperlimit = ((Float_t)bin2)*fDTheta + 0.5*fDTheta;
-           SetThetaOfRing(upperlimit);
-           FindAreaAndPortionOfRing();
-           Float_t area2 = GetAreaOfRing();
-           
-           //      cout << "lowerlimit" << lowerlimit << "upperlimit " << upperlimit << endl;
-            Float_t diffarea = area2 - area1;
-
-            if(diffarea>0)
-              {
-               weight = 1./(area2-area1);
-              }
-            else
-              {
-                weightFlag = 1;
-               weight = 1.;
-              }
-
-           //      cout <<" low "<< lowerlimit << " up " << upperlimit << 
-           //        " area1 " << area1 << " area2 " << area2 << " weight " << weight << endl;
-           
-         }
-       else
-         {
-           weight = 1.;
-         }
-
-       SetPhotonWeight(weight);
-       
-       //      cout << "weight..." << weight << endl;
 
+  if(wei != 0.) weightThetaCerenkov /= wei; else weightThetaCerenkov = 0.;  
+  return weightThetaCerenkov;
+}//FindCkovRing()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+Int_t AliRICHRecon::FlagPhot(Double_t ckov)
+{
+// Flag photon candidates if their individual ckov angle is inside the window around ckov angle returned by  HoughResponse()
+// Arguments: ckov- value of most probable ckov angle for track as returned by HoughResponse()
+//   Returns: number of photon candidates happened to be inside the window
 
-       if (bin1<0)    bin1=0;
-       if (bin2>nBin) bin2=nBin;
-      
-       for (j=bin1; j<bin2; j++) 
-         {
-           hcs[j] += 1; 
-           hcsw[j] += weight;
-         }
-      }
-  }
   
+  Int_t steps = (Int_t)((ckov )/ fDTheta); //how many times we need to have fDTheta to fill the distance between 0  and thetaCkovHough
 
-  if(weightFlag == 0) 
-    {
-      hCSspace = hcsw;
-    }
-  else
-    {
-      hCSspace = hcs;
-      //      cout << " probems with weight...normal procedure adopted " << endl;
-    }
+  Double_t tmin = (Double_t)(steps - 1)*fDTheta;
+  Double_t tmax = (Double_t)(steps)*fDTheta;
+  Double_t tavg = 0.5*(tmin+tmax);
 
-  HoughFiltering(hCSspace);
+  tmin = tavg - 0.5*fWindowWidth;  tmax = tavg + 0.5*fWindowWidth;
 
-  for (bin=0; bin <nBin; bin++) {
-    angle = (bin+0.5) * (fDTheta);
-    if (hCSspace[bin] && hCSspace[bin] > etaPeakPos) {
-      etaPeakCount = 0;
-      etaPeakPos = hCSspace[bin];
-      etaPeak[0]=angle;
+  Int_t iInsideCnt = 0; //count photons which Theta ckov inside the window
+  for(Int_t i=0;i<fPhotCnt;i++){//photon candidates loop
+    if(fPhotCkov[i] >= tmin && fPhotCkov[i] <= tmax)   { 
+      fPhotFlag[i]=2;    
+      iInsideCnt++;
     }
-    else { 
-      if (hCSspace[bin] == etaPeakPos) {
-       etaPeak[++etaPeakCount] = angle;
-      }
-    }
-  } 
-
-  for (i=0; i<etaPeakCount+1; i++) {
-    thetaCerenkov += etaPeak[i];
-  }
-  if (etaPeakCount>=0) {
-    thetaCerenkov /= etaPeakCount+1;
-    fThetaPeakPos = etaPeakPos;
   }
-
-  SetThetaCerenkov(thetaCerenkov);
-}
-//__________________________________________________________________________________________________
-void AliRICHRecon::HoughFiltering(float hcs[])
+  return iInsideCnt;
+}//FlagPhotons()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+Double_t AliRICHRecon::Sigma2(Double_t ckovTh, Double_t ckovPh, Double_t trkTh, Double_t trkPh)const
 {
-  // filter for Hough
-
-// hough filtering
-
-   float hcsFilt[750];
-   float k[5] = {0.05, 0.25, 0.4, 0.25, 0.05};
-   int nx, i, nxDx;
-   int sizeHCS;
-   int nBin;
-
-   nBin =  (int)(1+fThetaMax/fDTheta); 
-   sizeHCS = fThetaBin*sizeof(float);
+// Analithical calculation of total error (as a sum of localization, geometrical and chromatic errors) on Cerenkov angle for a given Cerenkov photon 
+// created by a given MIP. Fromulae according to CERN-EP-2000-058 
+// Arguments: Cerenkov and azimuthal angles for Cerenkov photon, [radians]
+//            dip and azimuthal angles for MIP taken at the entrance to radiator, [radians]        
+//            MIP beta
+//   Returns: absolute error on Cerenkov angle, [radians]    
+  
+  TVector3 v(-999,-999,-999);
+  Double_t trkBeta = 1./(TMath::Cos(ckovTh)*fkRadIdx);
 
-   memset ((void *)hcsFilt, 0, sizeHCS); 
+  v.SetX(SigLoc (ckovTh,ckovPh,trkTh,trkPh,trkBeta));
+  v.SetY(SigGeom(ckovTh,ckovPh,trkTh,trkPh,trkBeta));
+  v.SetZ(SigCrom(ckovTh,ckovPh,trkTh,trkPh,trkBeta));
 
-   for (nx = 0; nx < nBin; nx++) {
-      for (i = 0; i < 5; i++)  {
-        nxDx = nx + (i-2);
-       if (nxDx> -1 && nxDx<nBin)
-             hcsFilt[nx] +=  hcs[nxDx] * k[i];
-      }      
-   }
-     
-   for (nx = 0; nx < nBin; nx++) {
-     hcs[nx] = hcsFilt[nx];
-   }
+  return v.Mag2();
 }
-//__________________________________________________________________________________________________
-void AliRICHRecon::FindThetaCerenkov()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+Double_t AliRICHRecon::SigLoc(Double_t thetaC, Double_t phiC, Double_t thetaM, Double_t phiM, Double_t betaM)const
 {
-  // manage with weight for photons
-
-  Float_t wei = 0.;
-  Float_t weightThetaCerenkov = 0.;
-
-  Int_t nPhotons = GetPhotonsNumber();
-  for(Int_t i=0;i<nPhotons;i++)
-    {
-      SetPhotonIndex(i);
-
-      if(GetPhotonFlag() == 2)
-       {
-         Float_t photonEta = GetPhotonEta();
-         Float_t photonWeight = GetPhotonWeight();
-         weightThetaCerenkov += photonEta*photonWeight;
-         wei += photonWeight;
-       }
-    }
-
-  if(wei != 0.) 
-    {
-      weightThetaCerenkov /= wei;
-    }
-  else
-    {
-      weightThetaCerenkov = 0.;
-    }
-  
-  SetThetaCerenkov(weightThetaCerenkov);
-
-  AliDebug(1,Form(" thetac weighted -> %f",weightThetaCerenkov));
+// Analithical calculation of localization error (due to finite segmentation of PC) on Cerenkov angle for a given Cerenkov photon 
+// created by a given MIP. Fromulae according to CERN-EP-2000-058 
+// Arguments: Cerenkov and azimuthal angles for Cerenkov photon, [radians]
+//            dip and azimuthal angles for MIP taken at the entrance to radiator, [radians]        
+//            MIP beta
+//   Returns: absolute error on Cerenkov angle, [radians]    
+  Double_t phiDelta = phiC - phiM;
+
+  Double_t alpha =TMath::Cos(thetaM)-TMath::Tan(thetaC)*TMath::Cos(phiDelta)*TMath::Sin(thetaM);
+  Double_t k = 1.-fkRadIdx*fkRadIdx+alpha*alpha/(betaM*betaM);
+  if (k<0) return 1e10;
+
+  Double_t mu =TMath::Sin(thetaM)*TMath::Sin(phiM)+TMath::Tan(thetaC)*(TMath::Cos(thetaM)*TMath::Cos(phiDelta)*TMath::Sin(phiM)+TMath::Sin(phiDelta)*TMath::Cos(phiM));
+  Double_t e  =TMath::Sin(thetaM)*TMath::Cos(phiM)+TMath::Tan(thetaC)*(TMath::Cos(thetaM)*TMath::Cos(phiDelta)*TMath::Cos(phiM)-TMath::Sin(phiDelta)*TMath::Sin(phiM));
+
+  Double_t kk = betaM*TMath::Sqrt(k)/(8*alpha);
+  Double_t dtdxc = kk*(k*(TMath::Cos(phiDelta)*TMath::Cos(phiM)-TMath::Cos(thetaM)*TMath::Sin(phiDelta)*TMath::Sin(phiM))-(alpha*mu/(betaM*betaM))*TMath::Sin(thetaM)*TMath::Sin(phiDelta));
+  Double_t dtdyc = kk*(k*(TMath::Cos(phiDelta)*TMath::Sin(phiM)+TMath::Cos(thetaM)*TMath::Sin(phiDelta)*TMath::Cos(phiM))+(alpha* e/(betaM*betaM))*TMath::Sin(thetaM)*TMath::Sin(phiDelta));
+
+  return  TMath::Sqrt(0.2*0.2*dtdxc*dtdxc + 0.25*0.25*dtdyc*dtdyc);
 }
-//__________________________________________________________________________________________________
-void AliRICHRecon::FlagPhotons()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+Double_t AliRICHRecon::SigCrom(Double_t thetaC, Double_t phiC, Double_t thetaM, Double_t phiM, Double_t betaM)const
 {
-  // flag photons
-
-  Int_t nPhotonHough = 0;
-
-  Float_t thetaCerenkov = GetThetaCerenkov();
-  AliDebug(1,Form(" fThetaCerenkov %f ",thetaCerenkov));
-
-  Float_t thetaDist= thetaCerenkov - fThetaMin;
-  Int_t steps = (Int_t)(thetaDist / fDTheta);
-
-  Float_t tmin = fThetaMin + (Float_t)(steps - 1)*fDTheta;
-  Float_t tmax = fThetaMin + (Float_t)(steps)*fDTheta;
-  Float_t tavg = 0.5*(tmin+tmax);
-
-  tmin = tavg - 0.5*fWindowWidth;
-  tmax = tavg + 0.5*fWindowWidth;
-
-  //  Int_t candidatePhotonsNumber = GetCandidatePhotonsNumber();
-
-  Int_t nPhotons = GetPhotonsNumber();
+// Analithical calculation of chromatic error (due to lack of knowledge of Cerenkov photon energy) on Cerenkov angle for a given Cerenkov photon 
+// created by a given MIP. Fromulae according to CERN-EP-2000-058 
+// Arguments: Cerenkov and azimuthal angles for Cerenkov photon, [radians]
+//            dip and azimuthal angles for MIP taken at the entrance to radiator, [radians]        
+//            MIP beta
+//   Returns: absolute error on Cerenkov angle, [radians]    
+  Double_t phiDelta = phiC - phiM;
+  Double_t alpha =TMath::Cos(thetaM)-TMath::Tan(thetaC)*TMath::Cos(phiDelta)*TMath::Sin(thetaM);
+
+  Double_t dtdn = TMath::Cos(thetaM)*fkRadIdx*betaM*betaM/(alpha*TMath::Tan(thetaC));
+            
+  Double_t f = 0.00928*(7.75-5.635)/TMath::Sqrt(12.);
+
+  return f*dtdn;
+}//SigCrom()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+Double_t AliRICHRecon::SigGeom(Double_t thetaC, Double_t phiC, Double_t thetaM, Double_t phiM, Double_t betaM)const
+{
+// Analithical calculation of geometric error (due to lack of knowledge of creation point in radiator) on Cerenkov angle for a given Cerenkov photon 
+// created by a given MIP. Formulae according to CERN-EP-2000-058 
+// Arguments: Cerenkov and azimuthal angles for Cerenkov photon, [radians]
+//            dip and azimuthal angles for MIP taken at the entrance to radiator, [radians]        
+//            MIP beta
+//   Returns: absolute error on Cerenkov angle, [radians]    
 
-  //  for(Int_t i=0;i<candidatePhotonsNumber;i++)
+  Double_t phiDelta = phiC - phiM;
+  Double_t alpha =TMath::Cos(thetaM)-TMath::Tan(thetaC)*TMath::Cos(phiDelta)*TMath::Sin(thetaM);
 
-  for(Int_t i=0;i<nPhotons;i++)
-    {
-      SetPhotonIndex(i);
+  Double_t k = 1.-fkRadIdx*fkRadIdx+alpha*alpha/(betaM*betaM);
+  if (k<0) return 1e10;
 
-      Float_t photonEta = GetPhotonEta();
+  Double_t eTr = 0.5*1.5*betaM*TMath::Sqrt(k)/(8*alpha);
+  Double_t lambda = 1.-TMath::Sin(thetaM)*TMath::Sin(thetaM)*TMath::Sin(phiC)*TMath::Sin(phiC);
 
-      if(photonEta == -999.) continue;
+  Double_t c = 1./(1.+ eTr*k/(alpha*alpha*TMath::Cos(thetaC)*TMath::Cos(thetaC)));
+  Double_t i = betaM*TMath::Tan(thetaC)*lambda*TMath::Power(k,1.5);
+  Double_t ii = 1.+eTr*betaM*i;
 
-      if(photonEta >= tmin && photonEta <= tmax)
-       {
-         SetPhotonFlag(2);
-         nPhotonHough++;
-       }
-    }
-  SetHoughPhotons(nPhotonHough);
-}
+  Double_t err = c * (i/(alpha*alpha*8) +  ii*(1.-lambda) / ( alpha*alpha*8*betaM*(1.+eTr)) );
+  Double_t trErr = 1.5/(TMath::Sqrt(12.)*TMath::Cos(thetaM));
 
+  return trErr*err;
+}//SigGeom()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++