LCOV - code coverage report
Current view: top level - HMPID/HMPIDrec - AliHMPIDRecon.cxx (source / functions) Hit Total Coverage
Test: coverage.info Lines: 201 281 71.5 %
Date: 2016-06-14 17:26:59 Functions: 16 19 84.2 %

          Line data    Source code
       1             : /**************************************************************************
       2             :  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
       3             :  *                                                                        *
       4             :  * Author: The ALICE Off-line Project.                                    *
       5             :  * Contributors are mentioned in the code where appropriate.              *
       6             :  *                                                                        *
       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             :  **************************************************************************/
      15             : 
      16             : //////////////////////////////////////////////////////////////////////////
      17             : //                                                                      //
      18             : // AliHMPIDRecon                                                         //
      19             : //                                                                      //
      20             : // HMPID class to perfom pattern recognition based on Hough transfrom    //
      21             : // for single chamber                                                   //
      22             : //////////////////////////////////////////////////////////////////////////
      23             : 
      24             : #include "AliHMPIDRecon.h"   //class header
      25             : #include "AliHMPIDCluster.h" //CkovAngle()
      26             : #include <TRotation.h>       //TracePhot()
      27             : #include <TH1D.h>            //HoughResponse()
      28             : #include <TClonesArray.h>    //CkovAngle()
      29             : #include <AliESDtrack.h>     //CkovAngle()
      30             : #include <AliESDfriendTrack.h>     //CkovAngle()
      31             : 
      32             : //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
      33             : AliHMPIDRecon::AliHMPIDRecon():
      34          44 :   TNamed("RichRec","RichPat"),
      35          44 :   fPhotCnt(-1),
      36          44 :   fPhotFlag(0x0),
      37          44 :   fPhotClusIndex(0x0),    
      38          44 :   fPhotCkov(0x0),
      39          44 :   fPhotPhi(0x0),
      40          44 :   fPhotWei(0x0),
      41          44 :   fCkovSigma2(0),
      42          44 :   fIsWEIGHT(kFALSE),
      43          44 :   fDTheta(0.001),
      44          44 :   fWindowWidth(0.045),
      45          44 :   fRingArea(0),
      46          44 :   fRingAcc(0),
      47          44 :   fTrkDir(0,0,1),  // Just for test
      48          44 :   fTrkPos(30,40),  // Just for test
      49          44 :   fMipPos(0,0),
      50          44 :   fPc(0,0),
      51          88 :   fParam(AliHMPIDParam::Instance())
      52         220 : {
      53             : //..
      54             : //init of data members
      55             : //..
      56             :   
      57          88 :   fParam->SetRefIdx(fParam->MeanIdxRad()); // initialization of ref index to a default one
      58          88 : }
      59             : //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
      60             : void AliHMPIDRecon::InitVars(Int_t n)
      61             : {
      62             : //..
      63             : //Init some variables
      64             : //..
      65          16 :   if(n<=0) return;
      66           8 :   fPhotFlag = new Int_t[n];
      67           8 :   fPhotClusIndex  = new Int_t[n];
      68           8 :   fPhotCkov = new Double_t[n];
      69           8 :   fPhotPhi  = new Double_t[n];
      70           8 :   fPhotWei  = new Double_t[n];
      71             : //
      72          16 : }
      73             : //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
      74             : void AliHMPIDRecon::DeleteVars()const
      75             : {
      76             : //..
      77             : //Delete variables
      78             : //..
      79          24 :   delete [] fPhotFlag;
      80          16 :   delete [] fPhotClusIndex;
      81          16 :   delete [] fPhotCkov;
      82          16 :   delete [] fPhotPhi;
      83          16 :   delete [] fPhotWei;
      84           8 : }
      85             : //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
      86             : void AliHMPIDRecon::CkovAngle(AliESDtrack *pTrk,TClonesArray *pCluLst,Int_t index,Double_t nmean,Float_t xRa,Float_t yRa)
      87             : {
      88             : // Pattern recognition method based on Hough transform
      89             : // Arguments:   pTrk     - track for which Ckov angle is to be found
      90             : //              pCluLst  - list of clusters for this chamber   
      91             : //   Returns:            - track ckov angle, [rad], 
      92             :        
      93             :   const Int_t nMinPhotAcc = 3;                      // Minimum number of photons required to perform the pattern recognition
      94             :   
      95          16 :   Int_t nClusTot = pCluLst->GetEntries();
      96             : 
      97           8 :   InitVars(nClusTot);
      98             :   
      99           8 :   Float_t xPc,yPc,th,ph;
     100           8 :   pTrk->GetHMPIDtrk(xPc,yPc,th,ph);        //initialize this track: th and ph angles at middle of RAD 
     101           8 :   SetTrack(xRa,yRa,th,ph);
     102             : 
     103           8 :   fParam->SetRefIdx(nmean);
     104             : 
     105             :   Float_t mipX=-1,mipY=-1;
     106             :   Int_t chId=-1,mipQ=-1,sizeClu = -1;
     107             :   
     108           8 :   fPhotCnt=0;
     109             :   
     110             :   Int_t nPads = 0;
     111             :   
     112         336 :   for (Int_t iClu=0; iClu<pCluLst->GetEntriesFast();iClu++){//clusters loop
     113         160 :     AliHMPIDCluster *pClu=(AliHMPIDCluster*)pCluLst->UncheckedAt(iClu);                       //get pointer to current cluster
     114         160 :     nPads+=pClu->Size();    
     115         160 :     if(iClu == index) {                                                                       // this is the MIP! not a photon candidate: just store mip info
     116           8 :       mipX = pClu->X();
     117           8 :       mipY = pClu->Y();
     118           8 :       mipQ=(Int_t)pClu->Q();
     119           8 :       sizeClu=pClu->Size();
     120           8 :       continue;                                                             
     121             :     }
     122         152 :     chId=pClu->Ch();
     123         161 :     if(pClu->Q()>2*fParam->QCut()) continue;
     124         143 :     Double_t thetaCer,phiCer;
     125         143 :     if(FindPhotCkov(pClu->X(),pClu->Y(),thetaCer,phiCer)){                                    //find ckov angle for this  photon candidate
     126         138 :       fPhotCkov[fPhotCnt]=thetaCer;                                                           //actual theta Cerenkov (in TRS)
     127         138 :       fPhotPhi [fPhotCnt]=phiCer;
     128         138 :       fPhotClusIndex[fPhotCnt]=iClu;                                                             //actual phi   Cerenkov (in TRS): -pi to come back to "unusual" ref system (X,Y,-Z)
     129         138 :       fPhotCnt++;                                                                             //increment counter of photon candidates
     130         138 :     }
     131         143 :   }//clusters loop
     132             : 
     133           8 :   pTrk->SetHMPIDmip(mipX,mipY,mipQ,fPhotCnt);                                                 //store mip info in any case 
     134           8 :   pTrk->SetHMPIDcluIdx(chId,index+1000*sizeClu);                                              //set index of cluster
     135             :   
     136           8 :   if(fPhotCnt<nMinPhotAcc) {                                                                 //no reconstruction with <=3 photon candidates
     137           0 :     pTrk->SetHMPIDsignal(kNoPhotAccept);                                                      //set the appropriate flag
     138           0 :     return;
     139             :   }
     140             :     
     141           8 :   fMipPos.Set(mipX,mipY);
     142             :     
     143             : //PATTERN RECOGNITION STARTED: 
     144           8 :   if(fPhotCnt>fParam->MultCut()) fIsWEIGHT = kTRUE; // offset to take into account bkg in reconstruction
     145           8 :   else                           fIsWEIGHT = kFALSE;
     146             :     
     147           8 :   Int_t iNrec=FlagPhot(HoughResponse(),pCluLst,pTrk);                                                      //flag photons according to individual theta ckov with respect to most probable
     148             :   
     149           8 :   pTrk->SetHMPIDmip(mipX,mipY,mipQ,iNrec);                                                  //store mip info 
     150             : 
     151           8 :   if(iNrec<nMinPhotAcc){
     152           0 :     pTrk->SetHMPIDsignal(kNoPhotAccept);                                                    //no photon candidates are accepted
     153           0 :     return;
     154             :   }
     155             :   
     156           8 :   Int_t occupancy = (Int_t)(1000*(nPads/(6.*80.*48.))); 
     157             :   
     158           8 :   Double_t thetaC = FindRingCkov(pCluLst->GetEntries());                                    //find the best reconstructed theta Cherenkov
     159             : //    FindRingGeom(thetaC,2);
     160           8 :   pTrk->SetHMPIDsignal(thetaC+occupancy);                                                   //store theta Cherenkov and chmaber occupancy
     161           8 :   pTrk->SetHMPIDchi2(fCkovSigma2);                                                          //store experimental ring angular resolution squared
     162             :   
     163           8 :   DeleteVars();
     164          16 : }//CkovAngle()
     165             : //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     166             : Bool_t AliHMPIDRecon::FindPhotCkov(Double_t cluX,Double_t cluY,Double_t &thetaCer,Double_t &phiCer)
     167             : {
     168             : // Finds Cerenkov angle  for this photon candidate
     169             : // Arguments: cluX,cluY - position of cadidate's cluster  
     170             : // Returns: Cerenkov angle 
     171             : 
     172         286 :   TVector3 dirCkov;
     173             :   
     174         143 :   Double_t zRad= -0.5*fParam->RadThick()-0.5*fParam->WinThick();     //z position of middle of RAD
     175         143 :   TVector3 rad(fTrkPos.X(),fTrkPos.Y(),zRad);                        //impact point at middle of RAD
     176         143 :   TVector3  pc(cluX,cluY,0.5*fParam->WinThick()+fParam->GapIdx());   //mip at PC
     177         286 :   Double_t cluR = TMath::Sqrt((cluX-fTrkPos.X())*(cluX-fTrkPos.X())+
     178         143 :                               (cluY-fTrkPos.Y())*(cluY-fTrkPos.Y()));//ref. distance impact RAD-CLUSTER   
     179         429 :   Double_t phi=(pc-rad).Phi();                                       //phi of photon
     180             :     
     181             :   Double_t ckov1=0;
     182         286 :   Double_t ckov2=0.75+fTrkDir.Theta();                        //start to find theta cerenkov in DRS
     183             :   const Double_t kTol=0.01;
     184             :   Int_t iIterCnt = 0;
     185         143 :   while(1){
     186        1730 :     if(iIterCnt>=50) return kFALSE;
     187        1720 :     Double_t ckov=0.5*(ckov1+ckov2);
     188        1720 :     dirCkov.SetMagThetaPhi(1,ckov,phi);
     189        5160 :     TVector2 posC=TraceForward(dirCkov);                      //trace photon with actual angles
     190        5160 :     Double_t dist=cluR-(posC-fTrkPos).Mod();                  //get distance between trial point and cluster position
     191        1734 :     if(posC.X()==-999) dist = - 999;                          //total reflection problem
     192        1720 :     iIterCnt++;                                               //counter step
     193        2675 :     if     (dist> kTol) ckov1=ckov;                           //cluster @ larger ckov
     194         765 :     else if(dist<-kTol) ckov2=ckov;                           //cluster @ smaller ckov
     195             :     else{                                                     //precision achived: ckov in DRS found
     196         138 :       dirCkov.SetMagThetaPhi(1,ckov,phi);                     //
     197         414 :       Lors2Trs(dirCkov,thetaCer,phiCer);                       //find ckov (in TRS:the effective Cherenkov angle!)
     198         138 :       return kTRUE;
     199             :     }
     200        3302 :   }
     201         143 : }//FindPhotTheta()
     202             : //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     203             : TVector2 AliHMPIDRecon::TraceForward(TVector3 dirCkov)const
     204             : {
     205             :   //Trace forward a photon from (x,y) up to PC
     206             :   // Arguments: dirCkov photon vector in LORS
     207             :   //   Returns: pos of traced photon at PC
     208             :   
     209       16748 :   TVector2 pos(-999,-999);
     210        8374 :   Double_t thetaCer = dirCkov.Theta();
     211       17788 :   if(thetaCer > TMath::ASin(1./fParam->GetRefIdx())) return pos;          //total refraction on WIN-GAP boundary
     212        7334 :   Double_t zRad= -0.5*fParam->RadThick()-0.5*fParam->WinThick();          //z position of middle of RAD
     213        7334 :   TVector3  posCkov(fTrkPos.X(),fTrkPos.Y(),zRad);                        //RAD: photon position is track position @ middle of RAD 
     214       22002 :   Propagate(dirCkov,posCkov,           -0.5*fParam->WinThick());          //go to RAD-WIN boundary  
     215        7334 :   Refract  (dirCkov,         fParam->GetRefIdx(),fParam->WinIdx());       //RAD-WIN refraction
     216       22002 :   Propagate(dirCkov,posCkov,            0.5*fParam->WinThick());          //go to WIN-GAP boundary
     217        7334 :   Refract  (dirCkov,         fParam->WinIdx(),fParam->GapIdx());          //WIN-GAP refraction
     218       22002 :   Propagate(dirCkov,posCkov,0.5*fParam->WinThick()+fParam->GapThick());   //go to PC
     219        7334 :   pos.Set(posCkov.X(),posCkov.Y());
     220             :   return pos;
     221       24082 : }//TraceForward()
     222             : //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     223             : void AliHMPIDRecon::Lors2Trs(TVector3 dirCkov,Double_t &thetaCer,Double_t &phiCer)const
     224             : {
     225             :   //Theta Cerenkov reconstruction 
     226             :   // Arguments: dirCkov photon vector in LORS
     227             :   //   Returns: thetaCer of photon in TRS
     228             :   //              phiCer of photon in TRS
     229             : //  TVector3 dirTrk;
     230             : //  dirTrk.SetMagThetaPhi(1,fTrkDir.Theta(),fTrkDir.Phi());
     231             : //  Double_t thetaCer = TMath::ACos(dirCkov*dirTrk);
     232         414 :   TRotation mtheta;   mtheta.RotateY(-fTrkDir.Theta());
     233         414 :   TRotation mphi;       mphi.RotateZ(-fTrkDir.Phi());
     234         138 :   TRotation mrot=mtheta*mphi;
     235         138 :   TVector3 dirCkovTRS;
     236         276 :   dirCkovTRS=mrot*dirCkov;
     237         276 :   phiCer  = dirCkovTRS.Phi();                                          //actual value of the phi of the photon
     238         276 :   thetaCer= dirCkovTRS.Theta();                                        //actual value of thetaCerenkov of the photon
     239         138 : }
     240             : //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     241             : void AliHMPIDRecon::Trs2Lors(TVector3 dirCkov,Double_t &thetaCer,Double_t &phiCer)const
     242             : {
     243             :   //Theta Cerenkov reconstruction 
     244             :   // Arguments: dirCkov photon vector in TRS
     245             :   //   Returns: thetaCer of photon in LORS
     246             :   //              phiCer of photon in LORS
     247       19962 :   TRotation mtheta;   mtheta.RotateY(fTrkDir.Theta());
     248       19962 :   TRotation mphi;       mphi.RotateZ(fTrkDir.Phi());
     249        6654 :   TRotation mrot=mphi*mtheta;
     250        6654 :   TVector3 dirCkovLORS;
     251       13308 :   dirCkovLORS=mrot*dirCkov;
     252       13308 :   phiCer  = dirCkovLORS.Phi();                                          //actual value of the phi of the photon
     253       13308 :   thetaCer= dirCkovLORS.Theta();                                        //actual value of thetaCerenkov of the photon
     254        6654 : }
     255             : //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     256             : void AliHMPIDRecon::FindRingGeom(Double_t ckovAng,Int_t level)
     257             : {
     258             : // Find area covered in the PC acceptance
     259             : // Arguments: ckovAng - cerenkov angle
     260             : //            level   - precision in finding area and portion of ring accepted (multiple of 50)
     261             : //   Returns: area of the ring in cm^2 for given theta ckov
     262             :    
     263           0 :   Int_t kN=50*level;
     264             :   Int_t nPoints = 0;
     265             :   Double_t area=0;
     266             :   
     267             :   Bool_t first=kFALSE;
     268           0 :   TVector2 pos1;
     269             :   
     270           0 :   for(Int_t i=0;i<kN;i++){
     271           0 :    if(!first) {
     272           0 :       pos1=TracePhot(ckovAng,Double_t(TMath::TwoPi()*(i+1)/kN));                                    //find a good trace for the first photon
     273           0 :      if(pos1.X()==-999) continue;                                                                   //no area: open ring                  
     274           0 :      if(!fParam->IsInside(pos1.X(),pos1.Y(),0)) {
     275           0 :        pos1 = IntWithEdge(fMipPos,pos1);                                                            // find the very first intersection...
     276           0 :      } else {
     277           0 :        if(!AliHMPIDParam::IsInDead(pos1.X(),pos1.Y())) nPoints++;                                   //photon is accepted if not in dead zone
     278             :      }
     279             :      first=kTRUE;
     280           0 :      continue;
     281             :    }
     282           0 :    TVector2 pos2=TracePhot(ckovAng,Double_t(TMath::TwoPi()*(i+1)/kN));                              //trace the next photon
     283           0 :    if(pos2.X()==-999) continue;                                                                     //no area: open ring             
     284           0 :    if(!fParam->IsInside(pos2.X(),pos2.Y(),0)) {
     285           0 :      pos2 = IntWithEdge(fMipPos,pos2);
     286           0 :    } else {
     287           0 :      if(!AliHMPIDParam::IsInDead(pos2.X(),pos2.Y())) nPoints++;                                     //photon is accepted if not in dead zone
     288             :    }
     289           0 :    area+=TMath::Abs((pos1-fMipPos).X()*(pos2-fMipPos).Y()-(pos1-fMipPos).Y()*(pos2-fMipPos).X());   //add area of the triangle...            
     290           0 :    pos1 = pos2;
     291           0 :   }
     292             : //---  find area and length of the ring;
     293           0 :   fRingAcc = (Double_t)nPoints/(Double_t)kN;
     294           0 :   area*=0.5;
     295           0 :   fRingArea = area;
     296           0 : }//FindRingGeom()
     297             : //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     298             : TVector2 AliHMPIDRecon::IntWithEdge(TVector2 p1,TVector2 p2)const
     299             : {
     300             : // It finds the intersection of the line for 2 points traced as photons
     301             : // and the edge of a given PC
     302             : // Arguments: 2 points obtained tracing the photons
     303             : //   Returns: intersection point with detector (PC) edges
     304             : 
     305           0 :   Double_t xmin = (p1.X()<p2.X())? p1.X():p2.X(); 
     306           0 :   Double_t xmax = (p1.X()<p2.X())? p2.X():p1.X(); 
     307           0 :   Double_t ymin = (p1.Y()<p2.Y())? p1.Y():p2.Y(); 
     308           0 :   Double_t ymax = (p1.Y()<p2.Y())? p2.Y():p1.Y(); 
     309             :   
     310           0 :   Double_t m = TMath::Tan((p2-p1).Phi());
     311           0 :   TVector2 pint;
     312             :   //intersection with low  X
     313           0 :   pint.Set((Double_t)(p1.X() + (0-p1.Y())/m),0.);
     314           0 :   if(pint.X()>=0 && pint.X()<=fParam->SizeAllX() &&
     315           0 :      pint.X()>=xmin && pint.X()<=xmax            &&
     316           0 :      pint.Y()>=ymin && pint.Y()<=ymax) return pint;
     317             :   //intersection with high X  
     318           0 :   pint.Set((Double_t)(p1.X() + (fParam->SizeAllY()-p1.Y())/m),(Double_t)(fParam->SizeAllY()));
     319           0 :   if(pint.X()>=0 && pint.X()<=fParam->SizeAllX() &&
     320           0 :      pint.X()>=xmin && pint.X()<=xmax            &&
     321           0 :      pint.Y()>=ymin && pint.Y()<=ymax) return pint;
     322             :   //intersection with left Y  
     323           0 :   pint.Set(0.,(Double_t)(p1.Y() + m*(0-p1.X())));
     324           0 :   if(pint.Y()>=0 && pint.Y()<=fParam->SizeAllY() &&
     325           0 :      pint.Y()>=ymin && pint.Y()<=ymax            &&
     326           0 :      pint.X()>=xmin && pint.X()<=xmax) return pint;
     327             :   //intersection with righ Y  
     328           0 :   pint.Set((Double_t)(fParam->SizeAllX()),(Double_t)(p1.Y() + m*(fParam->SizeAllX()-p1.X())));
     329           0 :   if(pint.Y()>=0 && pint.Y()<=fParam->SizeAllY() &&
     330           0 :      pint.Y()>=ymin && pint.Y()<=ymax            &&
     331           0 :      pint.X()>=xmin && pint.X()<=xmax) return pint;
     332           0 :   return p1;
     333           0 : }//IntWithEdge()
     334             : //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     335             : Double_t AliHMPIDRecon::FindRingCkov(Int_t)
     336             : {
     337             : // 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
     338             : // collecting errors for all single Ckov candidates thetas. (Assuming they are independent)  
     339             : // Arguments: iNclus- total number of clusters in chamber for background estimation
     340             : //    Return: best estimation of track Theta ckov
     341             : 
     342             :   Double_t wei = 0.;
     343             :   Double_t weightThetaCerenkov = 0.;
     344             : 
     345             :   Double_t ckovMin=9999.,ckovMax=0.;
     346             :   Double_t sigma2 = 0;   //to collect error squared for this ring
     347             :   
     348         300 :   for(Int_t i=0;i<fPhotCnt;i++){//candidates loop
     349         138 :     if(fPhotFlag[i] == 2){
     350          97 :       if(fPhotCkov[i]<ckovMin) ckovMin=fPhotCkov[i];                         //find max and min Theta ckov from all candidates within probable window
     351         101 :       if(fPhotCkov[i]>ckovMax) ckovMax=fPhotCkov[i]; 
     352          76 :       weightThetaCerenkov += fPhotCkov[i]*fPhotWei[i];
     353          76 :       wei += fPhotWei[i];                                                    //collect weight as sum of all candidate weghts   
     354             :       
     355          76 :       sigma2 += 1./fParam->Sigma2(fTrkDir.Theta(),fTrkDir.Phi(),fPhotCkov[i],fPhotPhi[i]);
     356          76 :     }
     357             :   }//candidates loop
     358             :   
     359          16 :   if(sigma2>0) fCkovSigma2=1./sigma2;
     360           0 :   else         fCkovSigma2=1e10;  
     361             :   
     362          16 :   if(wei != 0.) weightThetaCerenkov /= wei; else weightThetaCerenkov = 0.;
     363           8 :   return weightThetaCerenkov;
     364             : }//FindCkovRing()
     365             : //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     366             : Int_t AliHMPIDRecon::FlagPhot(Double_t ckov,TClonesArray *pCluLst, AliESDtrack *pTrk)
     367             : {
     368             : // Flag photon candidates if their individual ckov angle is inside the window around ckov angle returned by  HoughResponse()
     369             : // Arguments: ckov- value of most probable ckov angle for track as returned by HoughResponse()
     370             : //   Returns: number of photon candidates happened to be inside the window
     371             : 
     372             : // Photon Flag:  Flag = 0 initial set; 
     373             : //               Flag = 1 good candidate (charge compatible with photon); 
     374             : //               Flag = 2 photon used for the ring;
     375             :   
     376          16 :   Int_t steps = (Int_t)((ckov )/ fDTheta); //how many times we need to have fDTheta to fill the distance between 0  and thetaCkovHough
     377             : 
     378           8 :   Double_t tmin = (Double_t)(steps - 1)*fDTheta;
     379           8 :   Double_t tmax = (Double_t)(steps)*fDTheta;
     380           8 :   Double_t tavg = 0.5*(tmin+tmax);
     381             : 
     382           8 :   tmin = tavg - 0.5*fWindowWidth;  tmax = tavg + 0.5*fWindowWidth;
     383             : 
     384             :   Int_t iInsideCnt = 0; //count photons which Theta ckov inside the window
     385         292 :   for(Int_t i=0;i<fPhotCnt;i++){//photon candidates loop
     386         138 :     fPhotFlag[i] = 0;
     387         260 :     if(fPhotCkov[i] >= tmin && fPhotCkov[i] <= tmax) { 
     388          76 :       fPhotFlag[i]=2;
     389          76 :       AddObjectToFriends(pCluLst,i,pTrk);
     390          76 :       iInsideCnt++;
     391          76 :     }
     392             :   }
     393             :       
     394           8 :   return iInsideCnt;
     395             :   
     396             : }//FlagPhot()
     397             : //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     398             : void  AliHMPIDRecon::AddObjectToFriends(TClonesArray *pCluLst, Int_t photonIndex, AliESDtrack *pTrk)
     399             : {
     400             : // Add AliHMPIDcluster object to ESD friends
     401             :     
     402         152 :   AliHMPIDCluster *pClu=(AliHMPIDCluster*)pCluLst->UncheckedAt(fPhotClusIndex[photonIndex]);   
     403          76 :   AliHMPIDCluster *pClus = new AliHMPIDCluster(*pClu);
     404          76 :   pClus->SetChi2(fPhotCkov[photonIndex]);  
     405          76 :   pTrk->AddCalibObject(pClus);   
     406          76 : }    
     407             : //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     408             : TVector2 AliHMPIDRecon::TracePhot(Double_t ckovThe,Double_t ckovPhi)const
     409             : {
     410             : // Trace a single Ckov photon from emission point somewhere in radiator up to photocathode taking into account ref indexes of materials it travereses
     411             : // Arguments: ckovThe,ckovPhi- photon ckov angles in TRS, [rad]
     412             : //   Returns: distance between photon point on PC and track projection  
     413             :   
     414       13308 :   Double_t theta,phi;
     415        6654 :   TVector3  dirTRS,dirLORS;   
     416        6654 :   dirTRS.SetMagThetaPhi(1,ckovThe,ckovPhi);                     //photon in TRS
     417       19962 :   Trs2Lors(dirTRS,theta,phi);
     418        6654 :   dirLORS.SetMagThetaPhi(1,theta,phi);                          //photon in LORS
     419       19962 :   return TraceForward(dirLORS);                                 //now foward tracing
     420        6654 : }//TracePhot()
     421             : //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     422             : void AliHMPIDRecon::Propagate(const TVector3 dir,TVector3 &pos,Double_t z)const
     423             : {
     424             : // Finds an intersection point between a line and XY plane shifted along Z.
     425             : // Arguments:  dir,pos   - vector along the line and any point of the line
     426             : //             z         - z coordinate of plain 
     427             : //   Returns:  none
     428             : //   On exit:  pos is the position if this intesection if any
     429       44010 :   static TVector3 nrm(0,0,1); 
     430       22002 :          TVector3 pnt(0,0,z);
     431             :   
     432       22002 :   TVector3 diff=pnt-pos;
     433       66006 :   Double_t sint=(nrm*diff)/(nrm*dir);
     434       44004 :   pos+=sint*dir;
     435       22002 : }//Propagate()
     436             : //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     437             : void AliHMPIDRecon::Refract(TVector3 &dir,Double_t n1,Double_t n2)const
     438             : {
     439             : // Refract direction vector according to Snell law
     440             : // Arguments: 
     441             : //            n1 - ref idx of first substance
     442             : //            n2 - ref idx of second substance
     443             : //   Returns: none
     444             : //   On exit: dir is new direction
     445       29336 :   Double_t sinref=(n1/n2)*TMath::Sin(dir.Theta());
     446       14668 :   if(TMath::Abs(sinref)>1.) dir.SetXYZ(-999,-999,-999);
     447       14668 :   else             dir.SetTheta(TMath::ASin(sinref));
     448       14668 : }//Refract()
     449             : //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     450             : Double_t AliHMPIDRecon::HoughResponse()
     451             : {
     452             : //
     453             : //    fIdxMip = mipId;
     454             : 
     455             : //       
     456             :   Double_t kThetaMax=0.75;
     457          16 :   Int_t nChannels = (Int_t)(kThetaMax/fDTheta+0.5);
     458           8 :   TH1D *phots   = new TH1D("Rphot"  ,"phots"         ,nChannels,0,kThetaMax);
     459           8 :   TH1D *photsw  = new TH1D("RphotWeighted" ,"photsw" ,nChannels,0,kThetaMax);
     460           8 :   TH1D *resultw = new TH1D("resultw","resultw"       ,nChannels,0,kThetaMax);
     461           8 :   Int_t nBin = (Int_t)(kThetaMax/fDTheta);
     462           8 :   Int_t nCorrBand = (Int_t)(fWindowWidth/(2*fDTheta));
     463             :   
     464         292 :   for (Int_t i=0; i< fPhotCnt; i++){//photon cadidates loop
     465         304 :     Double_t angle = fPhotCkov[i];  if(angle<0||angle>kThetaMax) continue;
     466         110 :     phots->Fill(angle);
     467         110 :     Int_t bin = (Int_t)(0.5+angle/(fDTheta));
     468             :     Double_t weight=1.;
     469         110 :     if(fIsWEIGHT){
     470           0 :       Double_t lowerlimit = ((Double_t)bin)*fDTheta - 0.5*fDTheta;  Double_t upperlimit = ((Double_t)bin)*fDTheta + 0.5*fDTheta;
     471           0 :       FindRingGeom(lowerlimit);
     472           0 :       Double_t areaLow  = GetRingArea();
     473           0 :       FindRingGeom(upperlimit);
     474           0 :       Double_t areaHigh = GetRingArea();
     475           0 :       Double_t diffArea = areaHigh - areaLow;
     476           0 :       if(diffArea>0) weight = 1./diffArea;
     477           0 :     }
     478         110 :     photsw->Fill(angle,weight);
     479         110 :     fPhotWei[i]=weight;
     480         110 :   }//photon candidates loop 
     481             :    
     482       12000 :   for (Int_t i=1; i<=nBin;i++){
     483        5992 :     Int_t bin1= i-nCorrBand;
     484        5992 :     Int_t bin2= i+nCorrBand;
     485        6168 :     if(bin1<1) bin1=1;
     486        6168 :     if(bin2>nBin)bin2=nBin;
     487        5992 :     Double_t sumPhots=phots->Integral(bin1,bin2);
     488       11314 :     if(sumPhots<3) continue;                            // if less then 3 photons don't trust to this ring
     489         670 :     Double_t sumPhotsw=photsw->Integral(bin1,bin2);
     490         797 :     if((Double_t)((i+0.5)*fDTheta)>0.7) continue;
     491         543 :     resultw->Fill((Double_t)((i+0.5)*fDTheta),sumPhotsw);
     492         543 :   } 
     493             : // evaluate the "BEST" theta ckov as the maximum value of histogramm
     494           8 :   Double_t *pVec = resultw->GetArray();
     495           8 :   Int_t locMax = TMath::LocMax(nBin,pVec);
     496          48 :   delete phots;delete photsw;delete resultw; // Reset and delete objects
     497             :   
     498           8 :   return (Double_t)(locMax*fDTheta+0.5*fDTheta); //final most probable track theta ckov   
     499           0 : }//HoughResponse()
     500             : //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     501             :   Double_t AliHMPIDRecon::FindRingExt(Double_t ckov,Int_t ch,Double_t xPc,Double_t yPc,Double_t thRa,Double_t phRa)
     502             : {
     503             : // To find the acceptance of the ring even from external inputs. 
     504             : //    
     505             : //       
     506           0 :   Double_t xRa = xPc - (fParam->RadThick()+fParam->WinThick()+fParam->GapThick())*TMath::Cos(phRa)*TMath::Tan(thRa); //just linear extrapolation back to RAD
     507           0 :   Double_t yRa = yPc - (fParam->RadThick()+fParam->WinThick()+fParam->GapThick())*TMath::Sin(phRa)*TMath::Tan(thRa);
     508             :   
     509             :   Int_t nStep = 500;
     510             :   Int_t nPhi = 0;  
     511             : 
     512           0 :   Int_t ipc,ipadx,ipady;
     513             :     
     514           0 :   if(ckov>0){
     515           0 :     SetTrack(xRa,yRa,thRa,phRa);
     516           0 :     for(Int_t j=0;j<nStep;j++){
     517           0 :       TVector2 pos; pos=TracePhot(ckov,j*TMath::TwoPi()/(Double_t)(nStep-1));
     518           0 :       if(fParam->IsInDead(pos.X(),pos.Y())) continue;
     519           0 :       fParam->Lors2Pad(pos.X(),pos.Y(),ipc,ipadx,ipady);
     520           0 :       ipadx+=(ipc%2)*fParam->kPadPcX;
     521           0 :       ipady+=(ipc/2)*fParam->kPadPcY;
     522           0 :       if(ipadx<0 || ipady>160 || ipady<0 || ipady>144 || ch<0 || ch>6) continue;
     523           0 :       if(fParam->IsDeadPad(ipadx,ipady,ch)) continue;
     524           0 :       nPhi++;
     525           0 :     }//point loop
     526           0 :   return ((Double_t)nPhi/(Double_t)nStep); 
     527             :   }//if
     528           0 :   return -1;
     529           0 : }  

Generated by: LCOV version 1.11