1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
18 Revision 1.2 2000/06/12 15:26:09 jbarbosa
21 Revision 1.1 2000/06/09 14:53:01 jbarbosa
22 Bari's pattern recognition algorithm
26 #include "AliRICHHit.h"
27 #include "AliRICHCerenkov.h"
28 #include "AliRICHPadHit.h"
29 #include "AliRICHDigit.h"
30 #include "AliRICHRawCluster.h"
31 #include "AliRICHRecHit.h"
33 #include "AliDetector.h"
35 #include "AliRICHPoints.h"
36 #include "AliRICHSegmentation.h"
37 #include "AliRICHPatRec.h"
39 #include "AliRICHConst.h"
40 #include "AliRICHPoints.h"
43 #include <TParticle.h>
50 ClassImp(AliRICHPatRec)
51 //___________________________________________
52 AliRICHPatRec::AliRICHPatRec() : TObject()
54 // Default constructor
58 //___________________________________________
59 AliRICHPatRec::AliRICHPatRec(const char *name, const char *title)
62 //Constructor for Bari's pattern recogniton method object
65 void AliRICHPatRec::PatRec()
68 // Pattern recognition algorithm
70 AliRICHChamber* iChamber;
71 AliRICHSegmentation* segmentation;
73 Int_t ntracks, ndigits[kNCH];
80 Float_t gamma,massCer,betaCer;
84 printf("PatRec started\n");
86 TCanvas *c1 = new TCanvas("c1","Alice RICH pad hits",50,10,700,700);
88 TH2F *ring = new TH2F("ring","map",90,-30.,30.,90,-30.,30.);
89 TH2F *ringband = new TH2F("ringband","map",90,-65.,65.,90,-65.,65.);
90 TH1F *cerangle = new TH1F("cerangle","phot",300,0.45,0.75);
91 TH1F *ceranglew= new TH1F("ceranglew","phot",300,0.45,0.75);
92 TH1F *hough = new TH1F("hough","hough",75,0.45,0.75);
93 TH1F *mass = new TH1F("mass","mass",100,50.,1050.);
95 AliRICH *pRICH = (AliRICH*)gAlice->GetDetector("RICH");
96 TTree *treeH = gAlice->TreeH();
98 ntracks =(Int_t) treeH->GetEntries();
100 for (itr=0; itr<ntracks; itr++) {
102 status = TrackParam(itr,ich);
103 if(status==1) continue;
104 printf(" theta %f phi %f track \n",fTrackTheta,fTrackPhi);
105 // ring->Fill(fTrackLoc[0],fTrackLoc[1],100.);
107 iChamber = &(pRICH->Chamber(ich));
108 segmentation=iChamber->GetSegmentationModel();
110 nent=(Int_t)gAlice->TreeD()->GetEntries();
111 gAlice->TreeD()->GetEvent(nent-1);
112 TClonesArray *pDigitss = pRICH->DigitsAddress(ich);
113 ndigits[ich] = pDigitss->GetEntriesFast();
114 printf("ndigits %d in chamber %d\n",ndigits[ich],ich);
115 AliRICHDigit *padI = 0;
119 for (Int_t dig=0;dig<ndigits[ich];dig++) {
120 padI=(AliRICHDigit*) pDigitss->UncheckedAt(dig);
124 segmentation->GetPadCxy(x,y,rx,ry);
130 ringband->Fill(x,y,1.);
131 fCerenkovAnglePad = PhotonCerenkovAngle();
132 if(fCerenkovAnglePad==-999) continue;
134 if(!PhotonInBand()) continue;
136 ring->Fill(fXpad,fYpad,1.);
137 cerangle->Fill(fCerenkovAnglePad,1.);
140 fEtaPhotons[goodPhotons] = fCerenkovAnglePad;
142 fNumEtaPhotons = goodPhotons;
144 BackgroundEstimation();
146 for(i=0;i<goodPhotons;i++) {
147 ceranglew->Fill(fEtaPhotons[i],fWeightPhotons[i]);
148 // printf(" Eta %f weight %f \n",fEtaPhotons[i],fWeightPhotons[i]);
155 rechit[2] = fThetaCerenkov;
160 hough->Fill(fThetaCerenkov,1.);
162 pRICH->AddRecHit(ich,rechit);
164 betaCer = BetaCerenkov(1.29,fThetaCerenkov);
165 gamma = 1./sqrt(1.-TMath::Power(betaCer,2));
166 massCer = fTrackMom/(betaCer*gamma);
167 // printf(" mass %f \n",massCer);
168 mass->Fill(massCer*1000,1.);
171 gAlice->TreeR()->Fill();
173 for (i=0;i<kNCH;i++) {
174 fRec=pRICH->RecHitsAddress(i);
175 int ndig=fRec->GetEntriesFast();
176 printf ("Chamber %d, rings %d\n",i,ndig);
178 pRICH->ResetRecHits();
185 ringband->Draw("box");
194 Int_t AliRICHPatRec::TrackParam(Int_t itr, Int_t &ich)
196 // Get Local coordinates of track impact
198 AliRICHChamber* iChamber;
199 AliRICHSegmentation* segmentation;
201 Float_t trackglob[3];
209 printf("Calling TrackParam\n");
212 TTree *treeH = gAlice->TreeH();
213 treeH->GetEvent(itr);
215 AliRICH *pRICH = (AliRICH*)gAlice->GetDetector("RICH");
216 AliRICHHit* mHit=(AliRICHHit*)pRICH->FirstHit(-1);
217 if(mHit==0) return 1;
218 ich = mHit->fChamber-1;
219 trackglob[0] = mHit->fX;
220 trackglob[1] = mHit->fY;
221 trackglob[2] = mHit->fZ;
225 fTrackMom = sqrt(TMath::Power(pX,2)+TMath::Power(pY,2)+TMath::Power(pZ,2));
226 thetatr = (180 - mHit->fTheta)*(Float_t)kDegrad;
227 phitr = mHit->fPhi*(Float_t)kDegrad;
229 part = mHit->fParticle;
231 iChamber = &(pRICH->Chamber(ich));
232 iChamber->GlobaltoLocal(trackglob,trackloc);
234 segmentation=iChamber->GetSegmentationModel();
236 // retrieve geometrical params
238 AliRICHGeometry* fGeometry=iChamber->GetGeometryModel();
240 fRw = fGeometry->GetFreonThickness();
241 fQw = fGeometry->GetQuartzThickness();
242 fTgap = fGeometry->GetGapThickness()
243 + fGeometry->GetProximityGapThickness();
245 Float_t apar = (fRw + fQw + fTgap)*tan(thetatr);
246 fTrackLoc[0] = apar*cos(phitr);
247 fTrackLoc[1] = apar*sin(phitr);
248 fTrackLoc[2] = fRw + fQw + fTgap;
249 fTrackTheta = thetatr;
252 fXshift = trackloc[0] - fTrackLoc[0];
253 fYshift = trackloc[2] - fTrackLoc[1];
258 Float_t AliRICHPatRec::EstimationAtLimits(Float_t lim, Float_t radius,
262 // Estimation of emission point
264 Float_t nquartz = 1.585;
266 Float_t nfreon = 1.295;
269 // printf("Calling EstimationLimits\n");
271 Float_t apar = (fRw -fEmissPoint + fQw + fTgap)*tan(fTrackTheta);
272 Float_t b1 = (fRw-fEmissPoint)*tan(lim);
273 Float_t b2 = fQw / sqrt(TMath::Power(nquartz,2)-TMath::Power(nfreon*sin(lim),2));
274 Float_t b3 = fTgap / sqrt(TMath::Power(ngas,2)-TMath::Power(nfreon*sin(lim),2));
275 Float_t bpar = b1 + nfreon*sin(lim)*(b2+b3);
276 value = TMath::Power(radius,2)
277 -TMath::Power((apar*cos(fTrackPhi)-bpar*cos(phiphot)),2)
278 -TMath::Power((apar*sin(fTrackPhi)-bpar*sin(phiphot)),2);
283 Float_t AliRICHPatRec::PhotonCerenkovAngle()
285 // Cherenkov pad angle reconstruction
289 Float_t cherMax = 0.8;
291 Float_t eps = 0.0001;
292 Int_t niterEmiss = 0;
293 Int_t niterEmissMax = 0;
294 Float_t x1,x2,x3=0,p1,p2,p3;
298 // printf("Calling PhotonCerenkovAngle\n");
300 radius = sqrt(TMath::Power(fTrackLoc[0]-fXpad,2)+TMath::Power(fTrackLoc[1]-fYpad,2));
301 fEmissPoint = fRw/2.; //Start value of EmissionPoint
303 while(niterEmiss<=niterEmissMax) {
306 argY = fYpad - fEmissPoint*tan(fTrackTheta)*sin(fTrackPhi);
307 argX = fXpad - fEmissPoint*tan(fTrackTheta)*cos(fTrackPhi);
308 phiphot = atan2(argY,argX);
309 p1 = EstimationAtLimits(cherMin,radius,phiphot);
310 p2 = EstimationAtLimits(cherMax,radius,phiphot);
313 // printf("PhotonCerenkovAngle failed\n");
317 //start to find the Cherenkov pad angle
321 p3 = EstimationAtLimits(x3,radius,phiphot);
322 while(TMath::Abs(p3)>eps){
326 p1 = EstimationAtLimits(x1,radius,phiphot);
329 p3 = EstimationAtLimits(x3,radius,phiphot);
333 // printf(" max iterations in PhotonCerenkovAngle\n");
337 // printf("niterFun %i \n",niterFun);
339 if (niterEmiss != niterEmissMax+1) EmissionPoint();
342 printf(" phiphot %f fXpad %f fYpad %f fEmiss %f \n",
343 phiphot,fXpad,fYpad,fEmissPoint);
351 void AliRICHPatRec::EmissionPoint()
354 // Find emission point
356 Float_t absorbtionLength=7.83*fRw; //absorption length in the freon (cm)
357 // 7.83 = -1/ln(T0) where
358 // T0->Trasmission freon at 180nm = 0.88 (Eph=6.85eV)
359 Float_t photonLength, photonLengthMin, photonLengthMax;
361 photonLength=exp(-fRw/(absorbtionLength*cos(fCerenkovAnglePad)));
362 photonLengthMin=fRw*photonLength/(1.-photonLength);
363 photonLengthMax=absorbtionLength*cos(fCerenkovAnglePad);
364 fEmissPoint = fRw + photonLengthMin - photonLengthMax;
368 void AliRICHPatRec::PhotonSelection(Int_t track, Int_t &nphot, Float_t &thetamean)
371 // not implemented yet
373 printf("Calling PhotonSelection\n");
376 void AliRICHPatRec::BackgroundEstimation()
379 // estimate background noise
381 Float_t stepEta = 0.001;
382 Float_t etaMinBkg = 0.72;
383 Float_t etaMaxBkg = 0.75;
385 Float_t etaMax = 0.75;
387 Float_t nfreon = 1.295;
389 Float_t etaStepMin,etaStepMax,etaStepAvg;
391 Int_t numPhotBkg, numPhotonStep;
392 Float_t funBkg,areaBkg,normBkg;
393 Float_t densityBkg,storeBkg,numStore;
399 nstep = (int)((etaMaxBkg-etaMinBkg)/stepEta);
401 for (i=0;i<fNumEtaPhotons;i++) {
403 if(fEtaPhotons[i]>etaMinBkg && fEtaPhotons[i]<etaMaxBkg) {
407 if (numPhotBkg == 0) {
408 for (i=0;i<fNumEtaPhotons;i++) {
409 fWeightPhotons[i] = 1.;
414 // printf(" numPhotBkg %i ",numPhotBkg);
416 for (i=0;i<nstep;i++) {
417 etaStepMin = etaMinBkg + (Float_t)(i)*stepEta;
418 etaStepMax = etaMinBkg + (Float_t)(i+1)*stepEta;
419 etaStepAvg = 0.5*(etaStepMax + etaStepMin);
421 funBkg = tan(etaStepAvg)*TMath::Power((1.+TMath::Power(tan(etaStepAvg),2)),
422 5.52)-7.803 + 22.02*tan(etaStepAvg);
424 thetaSig = asin(nfreon/ngas*sin(etaStepAvg));
425 funBkg = tan(thetaSig)*(1.+TMath::Power(tan(thetaSig),2))*nfreon
426 /ngas*cos(etaStepAvg)/cos(thetaSig);
427 areaBkg += stepEta*funBkg;
430 densityBkg = 0.95*(Float_t)(numPhotBkg)/areaBkg;
431 // printf(" densityBkg %f \n",densityBkg);
433 nstep = (int)((etaMax-etaMin)/stepEta);
436 for (i=0;i<nstep;i++) {
437 etaStepMin = etaMinBkg + (Float_t)(i)*stepEta;
438 etaStepMax = etaMinBkg + (Float_t)(i+1)*stepEta;
439 etaStepAvg = 0.5*(etaStepMax + etaStepMin);
441 funBkg = tan(etaStepAvg)*TMath::Power((1.+TMath::Power(tan(etaStepAvg),2)),
442 5.52)-7.803 + 22.02*tan(etaStepAvg);
445 thetaSig = asin(nfreon/ngas*sin(etaStepAvg));
446 funBkg = tan(thetaSig)*(1.+TMath::Power(tan(thetaSig),2))*nfreon
447 /ngas*cos(etaStepAvg)/cos(thetaSig);
449 areaBkg = stepEta*funBkg;
450 normBkg = densityBkg*areaBkg;
452 for (ip=0;ip<fNumEtaPhotons;ip++) {
453 if(fEtaPhotons[ip]>etaStepMin && fEtaPhotons[ip]<etaStepMax) {
457 if (numPhotonStep == 0) {
465 if (numPhotonStep == 0) continue;
466 for (ip=0;ip<fNumEtaPhotons;ip++) {
467 if(fEtaPhotons[ip]>etaStepMin && fEtaPhotons[ip]<etaStepMax) {
471 fWeightPhotons[ip] = 1. - normBkg/(Float_t)(numPhotonStep);
473 printf(" normBkg %f numPhotonStep %i fW %f \n",
474 normBkg, numPhotonStep, fWeightPhotons[ip]);
476 if(fWeightPhotons[ip]<0) fWeightPhotons[ip] = 0.;
483 void AliRICHPatRec::FlagPhotons(Int_t track, Float_t theta)
486 // not implemented yet
488 printf("Calling FlagPhotons\n");
492 //////////////////////////////////////////
498 Int_t AliRICHPatRec::PhotonInBand()
500 //0=label for parameters giving internal band ellipse
501 //1=label for parameters giving external band ellipse
503 Float_t imp[2], mass[2], energy[2], beta[2];
504 Float_t emissPointLength[2];
505 Float_t e1, e2, f1, f2;
506 Float_t nfreon[2], nquartz[2];
510 Float_t phpad, thetacer[2];
511 Float_t bandradius[2], padradius;
513 imp[0] = 5.0; //threshold momentum for the proton Cherenkov emission
516 mass[0] = 0.938; //proton mass
517 mass[1] = 0.139; //pion mass
519 emissPointLength[0] = fRw-0.0001; //at the beginning of the radiator
520 emissPointLength[1] = 0.;//at the end of radiator
522 //parameters to calculate freon window refractive index vs. energy
526 //parameters to calculate quartz window refractive index vs. energy
541 for (times=0; times<=1; times++) {
543 nfreon[times] = a+b*energy[times];
545 nquartz[times] = sqrt(1+(f1/(TMath::Power(e1,2)-TMath::Power(energy[times],2)))+
546 (f2/(TMath::Power(e2,2)-TMath::Power(energy[times],2))));
548 beta[times] = imp[times]/sqrt(TMath::Power(imp[times],2)+TMath::Power(mass[times],2));
550 thetacer[times] = CherenkovAngle( nfreon[times], beta[times]);
552 bandradius[times] = DistanceFromMip( nfreon[times], nquartz[times],
553 emissPointLength[times],
554 thetacer[times], phpad);
557 bandradius[0] -= 1.6;
558 bandradius[1] += 1.6;
559 padradius = sqrt(TMath::Power(fXpad,2)+TMath::Power(fYpad,2));
560 // printf(" rmin %f r %f rmax %f \n",bandradius[0],padradius,bandradius[1]);
562 if(padradius>=bandradius[0] && padradius<=bandradius[1]) return 1;
566 Float_t AliRICHPatRec::DistanceFromMip(Float_t nfreon, Float_t nquartz,
567 Float_t emissPointLength, Float_t thetacer,
571 // Find the distance to MIP impact
573 Float_t distanceValue;
575 TVector3 radExitPhot(1,1,1);//photon impact at the radiator exit with respect
576 //to local reference sistem with the origin in the MIP entrance
578 TVector3 vectEmissPointLength(1,1,1);
579 Float_t magEmissPointLenght;
581 TVector3 radExitPhot2(1,1,1);//photon impact at the radiator exit with respect
582 Float_t magRadExitPhot2;
583 //to a reference sistem with origin in the photon emission point and
584 //axes parallel to the MIP reference sistem
586 TVector3 quarExitPhot(1,1,1);//photon impact at the quartz exit with respect
587 Float_t magQuarExitPhot;
589 TVector3 gapExitPhot(1,1,1) ;
590 Float_t magGapExitPhot;
592 TVector3 fPhotocatExitPhot(1,1,1);
594 Double_t thetarad , phirad ;
595 Double_t thetaquar, phiquar;
596 Double_t thetagap , phigap ;
600 magEmissPointLenght = emissPointLength/cos(fTrackTheta);
602 vectEmissPointLength.SetMag(magEmissPointLenght);
603 vectEmissPointLength.SetTheta(fTrackTheta);
604 vectEmissPointLength.SetPhi(fTrackPhi);
607 radExitPhot2.SetTheta(thetacer);
608 radExitPhot2.SetPhi(phpad);
615 r1. RotateY(fTrackTheta);
616 r2. RotateZ(fTrackPhi);
620 r = r2 * r1;//rotation about the y axis by MIP theta incidence angle
621 //following by a rotation about the z axis by MIP phi incidence angle;
624 radExitPhot2 = r * radExitPhot2;
625 theta2 = radExitPhot2.Theta();
626 magRadExitPhot2 = (fRw - vectEmissPointLength(2))/cos(theta2);
627 radExitPhot2.SetMag(magRadExitPhot2);
630 radExitPhot = vectEmissPointLength + radExitPhot2;
631 thetarad = radExitPhot.Theta();
633 phirad = radExitPhot.Phi(); //check on the original file //
635 thetaquar = SnellAngle( nfreon, nquartz, theta2);
636 phiquar = radExitPhot2.Phi();
637 if(thetaquar == 999.) return thetaquar;
638 magQuarExitPhot = fQw/cos(thetaquar);
639 quarExitPhot.SetMag( magQuarExitPhot);
640 quarExitPhot.SetTheta(thetaquar);
641 quarExitPhot.SetPhi(phiquar);
643 thetagap = SnellAngle( nquartz, ngas, thetaquar);
645 if(thetagap == 999.) return thetagap;
646 magGapExitPhot = fTgap/cos(thetagap);
647 gapExitPhot.SetMag( magGapExitPhot);
648 gapExitPhot.SetTheta(thetagap);
649 gapExitPhot.SetPhi(phigap);
651 fPhotocatExitPhot = radExitPhot + quarExitPhot + gapExitPhot;
653 distanceValue = sqrt(TMath::Power(fPhotocatExitPhot(0),2)
654 +TMath::Power(fPhotocatExitPhot(1),2));
655 return distanceValue ;
658 Float_t AliRICHPatRec::PhiPad()
664 Float_t thetapad, phipad;
665 Float_t thetarot, phirot;
667 zpad = fRw + fQw + fTgap;
669 TVector3 photonPad(fXpad, fYpad, zpad);
670 thetapad = photonPad.Theta();
671 phipad = photonPad.Phi();
677 thetarot = - fTrackTheta;
678 phirot = - fTrackPhi;
680 r2. RotateY(thetarot);
682 r = r2 * r1;//rotation about the z axis by MIP -phi incidence angle
683 //following by a rotation about the y axis by MIP -theta incidence angle;
685 photonPad = r * photonPad;
687 phipad = photonPad.Phi();
692 Float_t AliRICHPatRec:: SnellAngle(Float_t n1, Float_t n2, Float_t theta1)
695 // Compute the Snell angle
697 Float_t sinrefractangle;
698 Float_t refractangle;
700 sinrefractangle = (n1/n2)*sin(theta1);
702 if(sinrefractangle>1.) {
707 refractangle = asin(sinrefractangle);
711 Float_t AliRICHPatRec::CherenkovAngle(Float_t n, Float_t beta)
714 // Compute the cerenkov angle
723 thetacer = acos (1./(n*beta));
727 Float_t AliRICHPatRec::BetaCerenkov(Float_t n, Float_t theta)
734 beta = 1./(n*cos(theta));
741 void AliRICHPatRec::HoughResponse()
745 // Implement Hough response pat. rec. method
750 int i, j, k, nCorrBand;
753 float angle, thetaCerMean;
758 float stepEta = 0.001;
759 float windowEta = 0.040;
763 float etaPeakPos = -1;
764 Int_t etaPeakCount = -1;
769 nBin = (int)(0.5+etaMax/(stepEta));
770 nCorrBand = (int)(0.5+ windowEta/(2 * stepEta));
771 memset ((void *)hcs, 0, etaBin*sizeof(int));
773 for (k=0; k< fNumEtaPhotons; k++) {
775 angle = fEtaPhotons[k];
777 if (angle>=etaMin && angle<= etaMax) {
778 bin = (int)(0.5+angle/(stepEta));
782 if (bin2>nBin) bin2=nBin;
784 for (j=bin1; j<bin2; j++) {
785 hcs[j] += fWeightPhotons[k];
788 thetaCerMean += angle;
792 thetaCerMean /= fNumEtaPhotons;
796 for (bin=0; bin <nBin; bin++) {
797 angle = (bin+0.5) * (stepEta);
798 if (hcs[bin] && hcs[bin] > etaPeakPos) {
800 etaPeakPos = hcs[bin];
804 if (hcs[bin] == etaPeakPos) {
805 etaPeak[++etaPeakCount] = angle;
810 for (i=0; i<etaPeakCount+1; i++) {
811 fThetaCerenkov += etaPeak[i];
813 if (etaPeakCount>=0) {
814 fThetaCerenkov /= etaPeakCount+1;
815 fThetaPeakPos = etaPeakPos;
820 void AliRICHPatRec::HoughFiltering(float hcs[])
826 float k[5] = {0.05, 0.25, 0.4, 0.25, 0.05};
833 float stepEta = 0.001;
835 nBin = (int)(1+etaMax/stepEta);
836 sizeHCS = etaBin*sizeof(float);
838 memset ((void *)hcsFilt, 0, sizeHCS);
840 for (nx = 0; nx < nBin; nx++) {
841 for (i = 0; i < 5; i++) {
843 if (nxDx> -1 && nxDx<nBin)
844 hcsFilt[nx] += hcs[nxDx] * k[i];
848 for (nx = 0; nx < nBin; nx++) {
849 hcs[nx] = hcsFilt[nx];
853 Float_t AliRICHPatRec::CherenkovRingDrawing(Float_t fixedthetacer)
856 //to draw Cherenkov ring by known Cherenkov angle
858 Int_t nmaxdegrees, nstepdegrees;
859 Float_t phpad, thetacer;
860 Float_t nfreonave, nquartzave;
863 Float_t e1, e2, f1, f2;
865 Float_t coordPadRing;
867 //parameters to calculate freon window refractive index vs. energy
871 //parameters to calculate quartz window refractive index vs. energy
888 for (phpad=0; phpad<nmaxdegrees;phpad++) {
890 aveEnerg = (energy[0]+energy[1])/2.;
892 nfreonave = a+b*aveEnerg;
893 nquartzave = sqrt(1+(f1/(TMath::Power(e1,2)-TMath::Power(aveEnerg,2)))+
894 (f2/(TMath::Power(e2,2)-TMath::Power(aveEnerg,2))));
896 thetacer = fixedthetacer;
898 bandradius = DistanceFromMip(nfreonave, nquartzave,
899 fEmissPoint,thetacer, phpad);
901 coordPadRing=fPhotocatExitPhot;
903 phpad = (nmaxdegrees/nstepdegrees)*phpad;