]> git.uio.no Git - u/mrichter/AliRoot.git/blob - RICH/AliRICHTracker.cxx
Number of pads along z is corrected
[u/mrichter/AliRoot.git] / RICH / AliRICHTracker.cxx
1 #include "AliRICHTracker.h"
2 #include <AliESD.h>
3 #include <TVector3.h>
4 #include <TTree.h>
5 #include "AliRICH.h"
6 #include "AliRICHHelix.h"
7 #include <AliMagF.h>
8 #include "AliRICHRecon.h"
9 #include <AliStack.h>
10 #include <TParticle.h>
11 #include <TMath.h>
12 #include <AliRun.h>
13 ClassImp(AliRICHTracker)
14 //__________________________________________________________________________________________________
15 Int_t AliRICHTracker::PropagateBack(AliESD *pESD)
16 {
17 // Interface callback methode invoked by AliRecontruction during tracking after TOF
18 // It steers to different way to provide the final reconstructed information sutable for analisys:
19 // 1. AliESD  - reconstructed tracks are used     
20 // 2. RICH private ntuple for debug- stack particles used instead of reconstructed tracks     
21   AliDebug(1,"Start pattern recognition");
22   if(pESD->GetNumberOfTracks()) {
23     Int_t iNtracks=pESD->GetNumberOfTracks();
24     AliDebug(1,Form("Start with %i tracks",iNtracks));
25     AliRICH *pRich=((AliRICH*)gAlice->GetDetector("RICH"));  
26     for(Int_t iTrackN=0;iTrackN<iNtracks;iTrackN++){//ESD tracks loop
27       RecWithESD(pESD,pRich,iTrackN);
28     }
29   }
30   else RecWithStack(0);
31   AliDebug(1,"Stop pattern recognition");
32   return 0; // error code: 0=no error;
33 }//PropagateBack()
34 //__________________________________________________________________________________________________
35 void AliRICHTracker::RecWithESD(AliESD *pESD,AliRICH *pRich,Int_t iTrackN)
36 {
37 //recontruction from ESD- primary way to reconstruct particle ID signal from tracks provided by core detectors
38     fnPhotBKG = 0;
39
40     Double_t fField=GetFieldMap()->SolenoidField()/10;// magnetic field in Tesla
41     AliESDtrack *pTrack = pESD->GetTrack(iTrackN);// get next reconstructed track
42 //  if((pTrack->GetStatus()&AliESDtrack::kTOFout)==0) continue; //ignore tracks not recontructed by TOF
43 //    pTrack->GetXYZ(xb); 
44 //    pTrack->GetPxPyPz(pb); 
45     Int_t status=pTrack->GetStatus()&AliESDtrack::kTOFout;//get running track parameters
46     Int_t charge = (Int_t)(-TMath::Sign(1.,pTrack->GetSign()*fField));
47     AliDebug(1,Form("Track %i pmod=%f charge=%i stat=%i",iTrackN,pTrack->GetP(),charge,status));
48     AliRICHHelix helix(pTrack->X3(),pTrack->P3(),charge,fField);   
49     Int_t iChamber=helix.RichIntersect(pRich->P());        
50     AliDebug(1,Form("intersection with %i chamber found",iChamber));
51     if(!iChamber) {
52       pTrack->SetRICHsignal(-999); //to be improved by flags...
53       return;//intersection with no chamber found
54     }
55 //find MIP cluster candidate (cluster which is closest to track intersection point)
56     Double_t distMip=9999,distX=0,distY=0; //min distance between clusters and track position on PC 
57     Int_t iMipId=0; //index of that min distance cluster
58     Double_t chargeMip=0; //charge of the MIP
59     Bool_t kFound = kFALSE;
60     for(Int_t iClusN=0;iClusN<pRich->Clusters(iChamber)->GetEntries();iClusN++){//clusters loop for intersected chamber
61       AliRICHCluster *pClus=(AliRICHCluster*)pRich->Clusters(iChamber)->UncheckedAt(iClusN);//get pointer to current cluster
62       if(pClus->Q()<AliRICHParam::QthMIP()) continue;
63       Double_t distCurrent=pClus->DistTo(helix.PosPc());//distance between current cluster and helix intersection with PC
64       if(distCurrent<distMip){
65         kFound = kTRUE;
66         distMip=distCurrent;
67         iMipId=iClusN;
68         distX=pClus->DistX(helix.PosPc());
69         distY=pClus->DistY(helix.PosPc());
70         chargeMip=pClus->Q();
71       }//find cluster nearest to the track       
72       AliDebug(1,Form("Ploc (%f,%f,%f) dist= %f",helix.Ploc().Mag(),helix.Ploc().Theta()*TMath::RadToDeg(),
73                                        helix.Ploc().Phi()*TMath::RadToDeg(),pClus->DistTo(helix.PosPc())));
74     }//clusters loop for intersected chamber
75
76     if(!kFound) {
77       pTrack->SetRICHsignal(-999);
78       return;
79     }
80     AliDebug(1,Form("Min distance cluster: %i dist is %f",iMipId,distMip));
81     pTrack->SetRICHcluster(((Int_t)chargeMip)+1000000*iChamber);
82     pTrack->SetRICHdxdy(distX,distY);
83     pTrack->SetRICHthetaPhi(helix.Ploc().Theta(),helix.Ploc().Phi());
84 //
85 // HERE CUTS ON GOLD RINGS....
86 //
87     if(distMip>AliRICHParam::DmatchMIP()) {
88       //track not accepted for pattern recognition
89       pTrack->SetRICHsignal(-990); //to be improved by flags...
90       return;
91     }
92 //
93     AliRICHRecon recon(&helix,pRich->Clusters(iChamber),iMipId); //actual job is done there
94
95     Double_t thetaCerenkov=recon.ThetaCerenkov(); //search for mean Cerenkov angle for this track
96     
97     pTrack->SetRICHsignal(thetaCerenkov);
98     pTrack->SetRICHnclusters(recon.GetHoughPhotons());
99
100     fnPhotBKG = recon.GetPhotBKG();
101         
102     AliDebug(1,Form("FINAL Theta Cerenkov=%f",pTrack->GetRICHsignal()));
103 //
104     if(pTrack->GetRICHsignal()>0) {
105       AliDebug(1,Form("Start to assign the probabilities"));
106       Double_t sigmaPID[AliPID::kSPECIES];
107       Double_t richPID[AliPID::kSPECIES];
108       for (Int_t iPart=0;iPart<AliPID::kSPECIES;iPart++) {
109         sigmaPID[iPart] = 0;
110         fErrPar[iPart] = 0;
111         for(Int_t iphot=0;iphot<pRich->Clusters(iChamber)->GetEntries();iphot++) {
112           recon.SetPhotonIndex(iphot);
113           if(recon.GetPhotonFlag() == 2) {
114             Double_t theta_g=recon.GetTrackTheta();
115             Double_t phi_g=(recon.GetPhiPoint()-recon.GetTrackPhi());
116             Double_t sigma2 = AliRICHParam::SigmaSinglePhoton(iPart,pTrack->GetP(),theta_g,phi_g).Mag2(); 
117             if(sigma2>0) sigmaPID[iPart] += 1/sigma2;
118           }
119         }
120         if (sigmaPID[iPart]>0)
121           sigmaPID[iPart] *= (Double_t)(recon.GetHoughPhotons()-fnPhotBKG)/(Double_t)(recon.GetHoughPhotons()); // n total phots, m are background...the sigma are scaled..
122           if(sigmaPID[iPart]>0) sigmaPID[iPart] = 1/TMath::Sqrt(sigmaPID[iPart])*0.001; // sigma from parametrization are in mrad...
123           else                  sigmaPID[iPart] = 0;
124           fErrPar[iPart]=sigmaPID[iPart];
125         AliDebug(1,Form("sigma for %s is %f rad",AliPID::ParticleName(iPart),sigmaPID[iPart]));
126       }
127       CalcProb(thetaCerenkov,pTrack->GetP(),sigmaPID,richPID);
128       pTrack->SetRICHpid(richPID);         
129       AliDebug(1,Form("PROBABILITIES ---> %f - %f - %f - %f - %f",richPID[0],richPID[1],richPID[2],richPID[3],richPID[4]));
130     }    
131   AliDebug(1,"Stop.");  
132 } //RecWithESD
133 //__________________________________________________________________________________________________
134 void AliRICHTracker::RecWithStack(TNtupleD *hn)
135 {
136 //Reconstruction for particles from STACK. This methode is to be used for RICH standalone when no other detectors are switched on,
137 //so normal tracking is not available   
138   AliDebug(1,"Start.");  
139   AliRICH *pRich=((AliRICH*)gAlice->GetDetector("RICH"));
140   
141 //  pRich->GetLoader()->GetRunLoader()->LoadHeader();
142   if(!pRich->GetLoader()->GetRunLoader()->TreeK()) pRich->GetLoader()->GetRunLoader()->LoadKinematics();
143   AliStack *pStack =   pRich->GetLoader()->GetRunLoader()->Stack();
144   if(!pStack) {AliDebug(1,Form("No STACK found in AliRoot"));return;}
145   Int_t iNtracks=pStack->GetNtrack();
146   AliDebug(1,Form(" Start reconstruction with %i track(s) from Stack",iNtracks));
147   
148   Double_t hnvec[20];
149   
150   Double_t b=GetFieldMap()->SolenoidField()/10;// magnetic field in Tesla
151   AliDebug(1,Form("Start with simulated %i tracks in %f Tesla field",iNtracks,b));
152   TVector3 x0(0,0,0); TVector3 p0(0,0,0);//tmp storage for AliRICHHelix
153   
154
155   if(pRich->GetLoader()->LoadRecPoints()) {AliDebug(1,Form("No clusters found in RICH"));return;}
156   pRich->GetLoader()->TreeR()->GetEntry(0);
157
158   for(Int_t iTrackN=0;iTrackN<iNtracks;iTrackN++){//stack particles loop
159     TParticle *pParticle = pStack->Particle(iTrackN);
160     if(!pParticle) {AliDebug(1,Form("Not a valid TParticle pointer. Track skipped"));continue;}
161     AliDebug(1,Form(" PDG code : %i",pParticle->GetPdgCode()));
162 //
163 // problem of PDG code of some extra particles to be solved!!!!!!!!!
164 //
165 // found problem! Look in TRD directory : codes from Fluka are :
166 //
167 //    if ((pdg_code == 10010020) ||
168 //        (pdg_code == 10010030) ||
169 //        (pdg_code == 50000050) ||
170 //        (pdg_code == 50000051) ||
171 //        (pdg_code == 10020040)) {
172 //
173     if(pParticle->GetPdgCode()>=50000050||pParticle->GetPdgCode()==0||pParticle->GetPdgCode()>10000) {AliDebug(1,Form("A photon as track... Track skipped"));continue;}
174 //
175 // to be updated for us!!
176 //
177     AliDebug(1,Form("Track %i is a %s with charge %i and momentum %f",
178             iTrackN,pParticle->GetPDG()->GetName(),Int_t(pParticle->GetPDG()->Charge()),pParticle->P()));
179 //    if(pParticle->GetMother(0)!=-1) continue; //consider only primaries
180     if(pParticle->GetPDG()->Charge()==0||TMath::Abs(Int_t(pParticle->GetPDG()->Charge()))!=3) continue; //to avoid photons from stack...
181     hnvec[0]=pParticle->P();
182     hnvec[1]=pParticle->GetPDG()->Charge();
183     p0.SetMagThetaPhi(pParticle->P(),pParticle->Theta(),pParticle->Phi());
184     x0.SetXYZ(pParticle->Vx(),pParticle->Vy(),pParticle->Vz());
185     AliRICHHelix helix(x0,p0,TMath::Sign(1,(Int_t)pParticle->GetPDG()->Charge()),b);   
186     Int_t iChamber=helix.RichIntersect(pRich->P());        
187     hnvec[2]=helix.Ploc().Theta();
188     hnvec[3]=helix.Ploc().Phi();
189     AliDebug(1,Form("intersection with %i chamber found",iChamber));
190     if(!iChamber) continue;// no intersection with RICH found
191     hnvec[4]=helix.PosPc().X();
192     hnvec[5]=helix.PosPc().Y();
193     Double_t distMip=9999;   //min distance between clusters and track position on PC 
194     Double_t mipX=-1;      //min distance between clusters and track position on PC 
195     Double_t mipY=-1;      //min distance between clusters and track position on PC 
196     Double_t chargeMip=-1; // charge MIP to find
197     Int_t iMipId=-1;       //index of that min distance cluster 
198     for(Int_t iClusN=0;iClusN<pRich->Clusters(iChamber)->GetEntries();iClusN++){//clusters loop for intersected chamber
199       AliRICHCluster *pClus=(AliRICHCluster*)pRich->Clusters(iChamber)->UncheckedAt(iClusN);//get pointer to current cluster
200       Double_t distCurrent=pClus->DistTo(helix.PosPc());//ditance between current cluster and helix intersection with PC
201       if(distCurrent<distMip){distMip=distCurrent;mipX=pClus->X();
202                                                   mipY=pClus->Y();
203                                                   chargeMip=pClus->Q();iMipId=1000000*iChamber+iClusN;}//find cluster nearest to the track 
204       
205       AliDebug(1,Form("Ploc (%f,%f,%f) dist= %f",helix.Ploc().Mag(),helix.Ploc().Theta()*TMath::RadToDeg(),
206                                                                     helix.Ploc().Phi()*TMath::RadToDeg(),pClus->DistTo(helix.PosPc())));
207     }//clusters loop for intersected chamber
208     
209     AliDebug(1,Form("Min distance cluster: %i dist is %f",iMipId,distMip));
210     hnvec[6]=mipX;hnvec[7]=mipY;
211     hnvec[8]=chargeMip;
212     AliRICHRecon recon(&helix,pRich->Clusters(iChamber),iMipId);
213     Double_t thetaCerenkov=recon.ThetaCerenkov(); //search for mean Cerenkov angle for this track
214     hnvec[9]=thetaCerenkov;
215     hnvec[10]=recon.GetHoughPhotons();
216     hnvec[11]=(Double_t)iMipId;
217     hnvec[12]=(Double_t)iChamber;
218     hnvec[13]=(Double_t)pParticle->GetPdgCode();
219     if(hn) hn->Fill(hnvec);
220     AliDebug(1,Form("FINAL Theta Cerenkov=%f",thetaCerenkov));
221   }//stack particles loop
222   
223   pRich->GetLoader()->UnloadRecPoints();
224   AliDebug(1,"Stop.");  
225 }//RecWithStack
226 //__________________________________________________________________________________________________
227 Int_t AliRICHTracker::LoadClusters(TTree *pTree)
228 {
229 // Load clusters for RICH
230   AliDebug(1,"Start.");  pTree->GetEntry(0);  AliDebug(1,"Stop."); return 0;
231 }
232 //__________________________________________________________________________________________________
233 void AliRICHTracker::CalcProb(Double_t thetaCer,Double_t pmod, Double_t *sigmaPID, Double_t *richPID)
234 {
235 // Calculates probability to be a electron-muon-pion-kaon-proton
236 // from the given Cerenkov angle and momentum assuming no initial particle composition
237 // (i.e. apriory probability to be the particle of the given sort is the same for all sorts)
238   Double_t height[AliPID::kSPECIES];Double_t totalHeight=0;
239   Double_t thetaTh[AliPID::kSPECIES];
240   for(Int_t iPart=0;iPart<AliPID::kSPECIES;iPart++){
241     height[iPart]=0;
242     Double_t mass = AliRICHParam::fgMass[iPart];
243     Double_t refIndex=AliRICHParam::RefIdxC6F14(AliRICHParam::MeanCkovEnergy());
244     Double_t cosThetaTh = TMath::Sqrt(mass*mass+pmod*pmod)/(refIndex*pmod);
245     thetaTh[iPart]=0;
246     if(cosThetaTh>=1) continue;
247     thetaTh[iPart] = TMath::ACos(cosThetaTh);
248 //    Double_t sinThetaThNorm = TMath::Sin(thetaTh)/TMath::Sqrt(1-1/(refIndex*refIndex));
249 //    Double_t sigmaThetaTh = (0.014*(1/sinThetaThNorm-1) + 0.0043)*1.25;
250 //    height[iPart] = TMath::Gaus(thetaCer,thetaTh,sigmaThetaTh);
251     if(sigmaPID[iPart]>0) height[iPart] = TMath::Gaus(thetaCer,thetaTh[iPart],sigmaPID[iPart],kTRUE);
252     else                  height[iPart] = 0;
253     totalHeight +=height[iPart];
254     AliDebug(1,Form(" Particle %s with mass %f with height %f and thetaTH %f",AliPID::ParticleName(iPart),mass,height[iPart],thetaTh[iPart]));
255     AliDebug(1,Form(" partial height %15.14f total height %15.14f",height[iPart],totalHeight));
256   }
257   if(totalHeight<1e-5) {for(Int_t iPart=0;iPart<AliPID::kSPECIES;iPart++)richPID[iPart]=1.0/AliPID::kSPECIES;return;}
258   for(Int_t iPart=0;iPart<AliPID::kSPECIES;iPart++) richPID[iPart] = height[iPart]/totalHeight;
259   Int_t iPartNear = TMath::LocMax(AliPID::kSPECIES,richPID);
260   if(TMath::Abs(thetaCer-thetaTh[iPartNear])>5.*sigmaPID[iPartNear]) for(Int_t iPart=0;iPart<AliPID::kSPECIES;iPart++)richPID[iPart]=1.0/AliPID::kSPECIES;
261   //last line is to check if the nearest thetacerenkov to the teorethical one is within 5 sigma, otherwise no response (equal prob to every particle
262
263 }//CalcProb
264 //__________________________________________________________________________________________________