This commit was generated by cvs2svn to compensate for changes in r15977,
[u/mrichter/AliRoot.git] / HMPID / AliHMPIDCluster.cxx
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 #include "AliHMPIDCluster.h"  //class header
17 #include <TMinuit.h>         //Solve()
18 #include <TClonesArray.h>    //Solve()
19
20 ClassImp(AliHMPIDCluster)
21 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
22 void AliHMPIDCluster::CoG()
23 {
24 // Calculates naive cluster position as a center of gravity of its digits.
25 // Arguments: none 
26 //   Returns: shape of the cluster i.e. the box which fully contains the cluster      
27   if(fDigs==0) return;                                  //no digits in this cluster
28   fX=fY=0;                                              //set cluster position to (0,0) to start to collect contributions
29   for(Int_t iDig=0;iDig<fDigs->GetEntriesFast();iDig++){//digits loop
30     AliHMPIDDigit *pDig=(AliHMPIDDigit*)fDigs->At(iDig);  //get pointer to next digit
31     Float_t q=pDig->Q();                                //get QDC 
32     fX += pDig->LorsX()*q;fY +=pDig->LorsY()*q;         //add digit center weighted by QDC
33   }//digits loop
34   fX/=fQ;fY/=fQ;                                        //final center of gravity
35
36   CorrSin();
37   
38   fSt=kCoG;
39 }//CoG()
40 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
41 void AliHMPIDCluster::CorrSin() 
42 {
43 // Correction of cluster x position due to sinoid, see HMPID TDR  page 30
44 // Arguments: none
45 //   Returns: none
46   AliHMPIDDigit dig(Ch(),100,1,fX,fY);                                               //tmp digit to get it center
47   Float_t x=fX-dig.LorsX();  
48   fX+=3.31267e-2*TMath::Sin(2*TMath::Pi()/0.8*x)-2.66575e-3*TMath::Sin(4*TMath::Pi()/0.8*x)+2.80553e-3*TMath::Sin(6*TMath::Pi()/0.8*x)+0.0070;
49 }
50 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
51 void AliHMPIDCluster::FitFunc(Int_t &iNpars, Double_t *, Double_t &chi2, Double_t *par, Int_t )
52 {
53 // Cluster fit function 
54 // par[0]=x par[1]=y par[2]=q for the first Mathieson shape
55 // par[3]=x par[4]=y par[5]=q for the second Mathieson shape and so on up to iNpars/3 Mathieson shapes
56 // For each pad of the cluster calculates the difference between actual pad charge and the charge induced to this pad by all Mathieson distributions 
57 // Then the chi2 is calculated as the sum of this value squared for all pad in the cluster.  
58 // Arguments: iNpars - number of parameters which is number of local maxima of cluster * 3
59 //            chi2   - function result to be minimised 
60 //            par   - parameters array of size iNpars            
61 //   Returns: none  
62   AliHMPIDCluster *pClu=(AliHMPIDCluster*)gMinuit->GetObjectFit();
63   Int_t iNshape = iNpars/3;
64     
65   chi2 = 0;
66   for(Int_t i=0;i<pClu->Size();i++){                                       //loop on all pads of the cluster
67     Double_t dQpadMath = 0;                                                //pad charge collector  
68     for(Int_t j=0;j<iNshape;j++){                                          //Mathiesons loop as all of them may contribute to this pad
69       dQpadMath+=par[3*j+2]*pClu->Dig(i)->Mathieson(par[3*j],par[3*j+1]);  // par[3*j+2] is charge par[3*j] is x par[3*j+1] is y of current Mathieson
70     }
71     chi2 +=TMath::Power((pClu->Dig(i)->Q()-dQpadMath),2);                  //
72   }                                                                             //loop on all pads of the cluster     
73 }//FitFunction()
74 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
75 void AliHMPIDCluster::Print(Option_t* opt)const
76 {
77 //Print current cluster  
78   const char *status=0;
79   switch(fSt){
80     case      kFor: status="formed"     ;break;
81     case      kUnf: status="unfolded"   ;break;
82     case      kCoG: status="coged"      ;break;
83     case      kEmp: status="empty"      ;break;
84   }
85   Printf("%s cs=%2i, Size=%2i (x=%7.3f cm,y=%7.3f cm,Q=%4i qdc), %s",
86          opt,Ch(),Size(),X(),Y(),Q(),status);
87   for(Int_t i=0;i<Size();i++) Dig(i)->Print();    
88 }//Print()
89 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
90 Int_t AliHMPIDCluster::Solve(TClonesArray *pCluLst,Bool_t isTryUnfold)
91 {
92 //This methode is invoked when the cluster is formed to solve it. Solve the cluster means to try to unfold the cluster
93 //into the local maxima number of clusters. This methode is invoked by AliHMPIDRconstructor::Dig2Clu() on cluster by cluster basis.  
94 //At this point, cluster contains a list of digits, cluster charge and size is precalculated in AddDigit(), position is preset to (-1,-1) in ctor,
95 //status is preset to kFormed in AddDigit(), chamber-sector info is preseted to actual values in AddDigit()
96 //Method first finds number of local maxima and if it's more then one tries to unfold this cluster into local maxima number of clusters
97 //Arguments: pCluLst     - cluster list pointer where to add new cluster(s)
98 //           isTryUnfold - flag to switch on/off unfolding   
99 //  Returns: number of local maxima of original cluster
100
101 //Phase 0. Initialise TMinuit  
102   const Int_t kMaxLocMax=6;                                                            //max allowed number of loc max for fitting
103   TMinuit *pMinuit = new TMinuit(3*kMaxLocMax);                                        //init MINUIT with this number of parameters (3 params per mathieson)
104   pMinuit->SetObjectFit((TObject*)this);  pMinuit->SetFCN(AliHMPIDCluster::FitFunc);    //set fit function
105   Double_t aArg=-1,parStart,parStep,parLow,parHigh;     Int_t iErrFlg;                 //tmp vars for TMinuit
106   pMinuit->mnexcm("SET PRI",&aArg,1,iErrFlg);                                          //suspend all printout from TMinuit 
107   pMinuit->mnexcm("SET NOW",&aArg,0,iErrFlg);                                          //suspend all warning printout from TMinuit
108 //Phase 1. Find number of local maxima. Strategy is to check if the current pad has QDC more then all neigbours   
109   Int_t iLocMaxCnt=0;
110   for(Int_t iDig1=0;iDig1<Size();iDig1++) {                                             //first digits loop
111     AliHMPIDDigit *pDig1 = Dig(iDig1);                                                   //take next digit
112     Int_t iHowManyMoreCnt = 0;                                                          //counts how many neighbouring pads has QDC more then current one
113     for(Int_t iDig2=0;iDig2<Size();iDig2++) {                                           //loop on all digits again
114       if(iDig1==iDig2) continue;                                                        //the same digit, no need to compare 
115       AliHMPIDDigit *pDig2 = Dig(iDig2);                                                 //take second digit to compare with the first one
116       Int_t dist = TMath::Sign(Int_t(pDig1->PadX()-pDig2->PadX()),1)+TMath::Sign(Int_t(pDig1->PadY()-pDig2->PadY()),1);//distance between pads
117       if(dist==1)                                                                       //means dig2 is a neighbour of dig1
118          if(pDig2->Q()>=pDig1->Q()) iHowManyMoreCnt++;                                 //count number of pads with Q more then Q of current pad
119     }//second digits loop
120     if(iHowManyMoreCnt==0&&iLocMaxCnt<kMaxLocMax){                                     //this pad has Q more then any neighbour so it's local maximum
121         pMinuit->mnparm(3*iLocMaxCnt  ,Form("x%i",iLocMaxCnt),parStart=pDig1->LorsX(),parStep=0.01,parLow=0,parHigh=0,iErrFlg);
122         pMinuit->mnparm(3*iLocMaxCnt+1,Form("y%i",iLocMaxCnt),parStart=pDig1->LorsY(),parStep=0.01,parLow=0,parHigh=0,iErrFlg);
123         pMinuit->mnparm(3*iLocMaxCnt+2,Form("q%i",iLocMaxCnt),parStart=pDig1->Q()    ,parStep=0.01,parLow=0,parHigh=0,iErrFlg);
124         iLocMaxCnt++;
125     }//if this pad is local maximum
126   }//first digits loop
127 //Phase 2. Fit loc max number of Mathiesons or add this current cluster to the list
128   Int_t iCluCnt=pCluLst->GetEntriesFast();                                          //get current number of clusters already stored in the list by previous operations
129   if(isTryUnfold==kTRUE && iLocMaxCnt<kMaxLocMax){                                        //resonable number of local maxima to fit and user requested it
130     pMinuit->mnexcm("MIGRAD" ,&aArg,0,iErrFlg);                                     //start fitting
131     if (!iErrFlg) { // Only if MIGRAD converged normally
132       Double_t fitX,fitY,fitQ,d1,d2,d3; TString sName;                                //vars to get results from TMinuit
133       for(Int_t i=0;i<iLocMaxCnt;i++){//local maxima loop
134         pMinuit->mnpout(3*i   ,sName,  fitX, d1 , d2, d3, iErrFlg);
135         pMinuit->mnpout(3*i+1 ,sName,  fitY, d1 , d2, d3, iErrFlg);
136         pMinuit->mnpout(3*i+2 ,sName,  fitQ, d1 , d2, d3, iErrFlg);
137         if (TMath::Abs(fitQ)>2147483647.0) fitQ = TMath::Sign((Double_t)2147483647,fitQ);//???????????????
138         new ((*pCluLst)[iCluCnt++]) AliHMPIDCluster(Ch(),fitX,fitY,(Int_t)fitQ);            //add new unfolded clusters
139       }//local maxima loop
140     }
141   }else{//do not unfold since number of loc max is unresonably high or user's baned unfolding 
142     CoG();
143     new ((*pCluLst)[iCluCnt++]) AliHMPIDCluster(*this);  //add this raw cluster 
144   }
145   delete pMinuit;
146   return iLocMaxCnt;
147 }//Solve()
148 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++