new functionality and new class added
[u/mrichter/AliRoot.git] / HMPID / AliHMPIDReconHTA.cxx
CommitLineData
5a3482a0 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// AliHMPIDReconHTA //
19// //
20// HMPID class to perfom pattern recognition based on Hough transfrom //
21// for single chamber //
22//////////////////////////////////////////////////////////////////////////
23
24#include "AliHMPIDReconHTA.h"//class header
25#include "AliHMPIDCluster.h" //CkovHiddenTrk()
26#include "AliHMPIDRecon.h" //FunMinPhot()
9785d5fb 27#include <TFile.h> //Database()
5a3482a0 28#include <TMinuit.h> //FitFree()
29#include <TClonesArray.h> //CkovHiddenTrk()
30#include <AliESDtrack.h> //CkovHiddenTrk()
9785d5fb 31#include <TH2F.h> //InitDatabase()
5a3482a0 32#include <TGraph.h> //ShapeModel()
5a3482a0 33#include <TSpline.h> //ShapeModel()
2e81abb0 34#include <TCanvas.h> //ShapeModel()
5a3482a0 35#include "TStopwatch.h" //
36
45118213 37Int_t AliHMPIDReconHTA::fgDB[500][150]={{75000*0}};
5a3482a0 38//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
c61a7285 39AliHMPIDReconHTA::AliHMPIDReconHTA():
40 TTask("RichRec","RichPat"),
41 fMipX(-999),
42 fMipY(-999),
43 fMipQ(-999),
44 fRadX(-999),
45 fRadY(-999),
46 fIdxMip(0),
47 fNClu(0),
48 fXClu(0),
49 fYClu(0),
2e81abb0 50 fPhiPhot(0),
51 fThetaPhot(0),
c61a7285 52 fClCk(0),
ee2f3539 53 fThTrkIn(-999),
54 fPhTrkIn(-999),
c61a7285 55 fThTrkFit(-999),
56 fPhTrkFit(-999),
57 fCkovFit(-999),
2e81abb0 58 fNCluFit(0),
c61a7285 59 fCkovSig2(0),
2e81abb0 60 fFitStatus(0),
c61a7285 61 fParam(AliHMPIDParam::Instance())
5a3482a0 62{
63//..
64//hidden algorithm
65//..
5a3482a0 66 fParam->SetRefIdx(fParam->MeanIdxRad()); // initialization of ref index to a default one
5565f017 67 InitDatabase();
5a3482a0 68}
69//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
70AliHMPIDReconHTA::~AliHMPIDReconHTA()
71{
72 DeleteVars();
73}
74//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
75void AliHMPIDReconHTA::InitVars(Int_t n)
76{
77//..
78//Init some variables
79//..
80 fXClu = new Double_t[n];
81 fYClu = new Double_t[n];
2e81abb0 82 fPhiPhot = new Double_t[n];
83 fThetaPhot = new Double_t[n];
5a3482a0 84 fClCk = new Bool_t[n];
85 for(Int_t i=0;i<n;i++) fClCk[i] = kTRUE;
86//
87}
88//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
aa00f952 89void AliHMPIDReconHTA::DeleteVars()const
5a3482a0 90{
91//..
92//Delete variables
93//..
94 if(fXClu) delete fXClu;
95 if(fYClu) delete fYClu;
2e81abb0 96 if(fPhiPhot) delete fPhiPhot;
97 if(fThetaPhot) delete fThetaPhot;
5a3482a0 98 if(fClCk) delete fClCk;
99}
100//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
9785d5fb 101Bool_t AliHMPIDReconHTA::CkovHiddenTrk(AliESDtrack *pTrk,TClonesArray *pCluLst,Int_t index, Double_t nmean)
5a3482a0 102{
103// Pattern recognition method without any infos from tracking:HTA (Hidden Track Algorithm)...
104// The method finds in the chmuber the cluster with the highest charge
105// compatibile with a MIP, then the strategy is applied
106// Arguments: pTrk - pointer to ESD track
107// pCluLs - list of clusters for a given chamber
9785d5fb 108// pNmean - pointer to ref. index
109// pQthre - pointer to qthre
5a3482a0 110// Returns: - 0=ok,1=not fitted
111
112 AliHMPIDParam *pParam = AliHMPIDParam::Instance();
5a3482a0 113
9785d5fb 114 if(!CluPreFilter(pCluLst)) return kFALSE;
115
5a3482a0 116 Int_t nCh=0;
43d3333b 117 Int_t sizeClu=0;
9785d5fb 118
119 fNClu = pCluLst->GetEntriesFast();
120
121 for (Int_t iClu=0;iClu<fNClu;iClu++){ //clusters loop
5a3482a0 122 AliHMPIDCluster *pClu=(AliHMPIDCluster*)pCluLst->UncheckedAt(iClu); //get pointer to current cluster
5a3482a0 123 fXClu[iClu] = pClu->X();fYClu[iClu] = pClu->Y(); //store x,y for fitting procedure
124 fClCk[iClu] = kTRUE; //all cluster are accepted at this stage to be reconstructed
9785d5fb 125
126 if(iClu == index) {
127
128 fMipX = pClu->X();
129 fMipY = pClu->Y();
130 fMipQ = pClu->Q();
131 sizeClu = pClu->Size();
132 nCh = pClu->Ch();
133 fClCk[index] = kFALSE;
134 fIdxMip = index;
2e81abb0 135 AliDebug(1,Form(" MIP n. %i x %f y %f Q %f",iClu,pClu->X(),pClu->Y(),pClu->Q()));
9785d5fb 136 }
5a3482a0 137 }//clusters loop
9785d5fb 138
139 pParam->SetRefIdx(nmean);
140
e56b695f 141 //
142 Float_t xra,yra,th,ph; pTrk->GetHMPIDtrk(xra,yra,th,ph);
2e81abb0 143 AliDebug(1,Form(" simulated phiTRK %6.2f thetaTRK %6.2f",ph*TMath::RadToDeg(),th*TMath::RadToDeg()));
e56b695f 144 //
145
9785d5fb 146 if(!DoRecHiddenTrk()) {
147 pTrk->SetHMPIDsignal(pParam->kNoPhotAccept);
148 return kFALSE;
149 } //Do track and ring reconstruction,if problems returns 1
2e81abb0 150 AliDebug(1,Form(" fitted phi %6.2f ",fPhTrkFit*TMath::RadToDeg()));
9785d5fb 151
152 pTrk->SetHMPIDtrk(fRadX,fRadY,fThTrkFit,fPhTrkFit); //store track intersection info
2e81abb0 153 pTrk->SetHMPIDmip(fMipX,fMipY,(Int_t)fMipQ,NCluFit()); //store mip info + n. phots of the ring
9785d5fb 154 pTrk->SetHMPIDcluIdx(nCh,fIdxMip+1000*sizeClu); //set cham number, index of cluster + cluster size
155 pTrk->SetHMPIDsignal(fCkovFit); //find best Theta ckov for ring i.e. track
156 pTrk->SetHMPIDchi2(fCkovSig2); //errors squared
2e81abb0 157 AliDebug(1,Form(" n clusters tot %i fitted to ring %i",fNClu,NCluFit()));
158 for(Int_t i=0;i<fNClu;i++) {
159 AliDebug(1,Form(" n.%3i ThetaCer %8.3f PhiCer %8.3f check %i",i,fThetaPhot[i],fPhiPhot[i],fClCk[i]));
160 }
161 AliDebug(1,Form("CkovHiddenTrk: thetaC %f th %f ph %f",fCkovFit,fThTrkFit*TMath::RadToDeg(),fPhTrkFit*TMath::RadToDeg()));
5a3482a0 162
9785d5fb 163 return kTRUE;
164
5a3482a0 165}//CkovHiddenTrk()
166//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
167Bool_t AliHMPIDReconHTA::DoRecHiddenTrk()
168{
169// Pattern recognition method without any infos from tracking...
170// First a preclustering filter to avoid part of the noise
171// Then only ellipsed-rings are fitted (no possibility,
172// for the moment, to reconstruct very inclined tracks)
173// Finally a fitting with (th,ph) free, starting by very close values
174// previously evaluated.
175// Arguments: none
176// Returns: none
177 Double_t thTrkRec,phiTrkRec,thetaCRec;
178
ee2f3539 179 if(!FindShape(thTrkRec,phiTrkRec,thetaCRec)) {
2e81abb0 180 AliDebug(1,Form(" FindShape failed...!"));
ee2f3539 181 return kFALSE;
182 }
2e81abb0 183 AliDebug(1,Form(" FindShape accepted...!"));
5a3482a0 184
2e81abb0 185 if(!FitRing(thTrkRec,phiTrkRec)) {
186 AliDebug(1,Form(" FitRing failed...!"));
ee2f3539 187 return kFALSE;
188 }
2e81abb0 189 AliDebug(1,Form(" FitRing accepted...!"));
190
191 if(!UniformDistrib()) {
192 AliDebug(1,Form(" UniformDistrib failed...!"));
193 return kFALSE;
194 }
195 AliDebug(1,Form(" UniformDistrib accepted...!"));
196
5a3482a0 197 return kTRUE;
198}//DoRecHiddenTrk()
5a3482a0 199//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
200Bool_t AliHMPIDReconHTA::CluPreFilter(TClonesArray *pCluLst)
201{
aa00f952 202// Pre-filter of bkg clusters
203// Arguments: pSluLst - List of the clusters for a given chamber
204// Returns: status - TRUE if filtering leaves enough photons, FALSE if not
5a3482a0 205//
206 Int_t nClusTot = pCluLst->GetEntriesFast();
207 if(nClusTot<4||nClusTot>100) {
208 return kFALSE;
209 } else {
210 InitVars(nClusTot);
211 return kTRUE;
212 }
213}
214//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
215Bool_t AliHMPIDReconHTA::FindShape(Double_t &thTrkRec,Double_t &phiTrkRec,Double_t &thetaCRec)
216{
aa00f952 217// Finds the estimates for phi and theta of the track and the ThetaCerenkov
218// by using a database of the shapes of the rings
219// Arguments: none
220// Returns: thTrkRec - estimate of theta track
221// phiTrkRec - estimate of phi track
222// thetaCRec - estimate of ThetaCerenkov
223// status - TRUE if a good solution is found, FALSE if not
224
5a3482a0 225 Double_t *phiphot = new Double_t[fNClu];
226 Double_t *dist = new Double_t[fNClu];
227 Int_t *indphi = new Int_t[fNClu];
228
229 Bool_t status;
230
9785d5fb 231// Sort in phi angle...
5a3482a0 232 for(Int_t i=0;i<fNClu;i++) {
9785d5fb 233 if(!fClCk[i]) {
2e81abb0 234 AliDebug(1,Form(" n.%3i xMIP %8.3f yMIP %8.3f check %i",i,fMipX,fMipY,fClCk[i]));
9785d5fb 235 phiphot[i] = 999.;
2e81abb0 236 dist[i] = 999.;
9785d5fb 237 continue;
238 }
5a3482a0 239 phiphot[i] = (TMath::ATan2(fMipY-fYClu[i],fMipX-fXClu[i])+TMath::Pi())*TMath::RadToDeg();
240 dist[i]=TMath::Sqrt((fMipX-fXClu[i])*(fMipX-fXClu[i])+(fMipY-fYClu[i])*(fMipY-fYClu[i]));
2e81abb0 241 AliDebug(1,Form(" n.%3i phiphot %8.3f dist %8.3f check %i",i,phiphot[i],dist[i],fClCk[i]));
5a3482a0 242 }
243
244 TMath::Sort(fNClu,phiphot,indphi,kFALSE);
245
246// Purify with a truncated mean;
247 Int_t np=0;
248 Double_t dMean = 0;
249 Double_t dMean2 = 0;
250 for(Int_t i=0;i<fNClu;i++) {
251 if(!fClCk[indphi[i]]) continue; // Check if a good photon candidate or not
252 dMean +=dist[indphi[i]];
253 dMean2+=dist[indphi[i]]*dist[indphi[i]];
254 np++;
255 }
256
257 dMean /=(Double_t)np;
258 dMean2 /=(Double_t)np;
259 Double_t rms = TMath::Sqrt(dMean2 - dMean*dMean);
260
261 for(Int_t i=0;i<fNClu;i++) {
262 if(!fClCk[indphi[i]]) continue; // Check if a good photon candidate or not
2e81abb0 263 if(TMath::Abs(dMean-dist[indphi[i]]) > 1.5*rms) {
5a3482a0 264 fClCk[indphi[i]] = kFALSE;
265 continue;
266 }
267 }
268
2e81abb0 269 AliDebug(1,"Purification of photons...");
5a3482a0 270//
271// purify vectors for good photon candidates
272//
273 Int_t npeff=0;
274 Double_t *phiphotP = new Double_t[fNClu+1];
275 Double_t *distP = new Double_t[fNClu+1];
276 for(Int_t i=0;i<fNClu;i++) {
2e81abb0 277 AliDebug(1,Form(" n. %3i phiphot %8.3f dist %8.3f check %i",i,phiphot[indphi[i]],dist[indphi[i]],fClCk[indphi[i]]));
5a3482a0 278 if(!fClCk[indphi[i]]) continue; // Check if a good photon candidate or not
279 phiphotP[npeff] = phiphot[indphi[i]];
280 distP[npeff] = dist[indphi[i]];
281 npeff++;
282 }
283
284 delete [] phiphot;
285 delete [] dist;
286 delete [] indphi;
287
288 if(npeff<3) {
2e81abb0 289 AliDebug(1,Form("FindShape failed: no enough photons = %i...",npeff));
5a3482a0 290 delete [] phiphotP;
291 delete [] distP;
292 return kFALSE;
293 }
294
5a3482a0 295 Double_t xA,xB;
9785d5fb 296 status = kFALSE;
ee2f3539 297
2e81abb0 298 if(!ShapeModel(npeff,phiphotP,distP,xA,xB,phiTrkRec)) {AliDebug(1,Form("ShapeModel failed ")); return kFALSE;}
299
300// if(xA > 50 || xB > 15) {AliDebug(1,Form("xA and xB failed out of range")); return kFALSE;}
5a3482a0 301
170a4fc5 302 Int_t binxDB,binyDB;
2e81abb0 303 Int_t compactDB=-1;
304
305 if(xA > xB) { //geometrically not possible, try to recover on a mean values...
306
307 FindBinDB(xA,xA,binxDB,binyDB);
308 if(binxDB<0 || binyDB<0) {AliDebug(1,Form("bin < 0 ! failed ")); return kFALSE;}
309 Int_t compactDB1 = CompactDB(binxDB,binyDB);
310 FindBinDB(xB,xB,binxDB,binyDB);
311 if(binxDB<0 || binyDB<0) {AliDebug(1,Form("bin < 0 ! failed ")); return kFALSE;}
312 Int_t compactDB2 = CompactDB(binxDB,binyDB);
313 Double_t thetaCRec1 = (Double_t)(compactDB1%1000);
314 Double_t thetaCRec2 = (Double_t)(compactDB2%1000);
315 Double_t thTrkRec1 = (Double_t)(compactDB1/1000);
316 Double_t thTrkRec2 = (Double_t)(compactDB2/1000);
317 thetaCRec = 0.5*(thetaCRec1+thetaCRec2);
318 thTrkRec = 0.5*( thTrkRec1+ thTrkRec2);
319
320 } else {
321
322 FindBinDB(xA,xB,binxDB,binyDB);
323 if(binxDB<0 || binyDB<0) {AliDebug(1,Form("bin < 0 ! failed ")); return kFALSE;}
5a3482a0 324
2e81abb0 325 compactDB = CompactDB(binxDB,binyDB);
326
327 if(compactDB<0) {AliDebug(1,Form("compact< 0! failed ")); return kFALSE;}
328 //
329 //
330 thetaCRec = (Double_t)(compactDB%1000);
331 thTrkRec = (Double_t)(compactDB/1000);
332
333 }
334
335 AliDebug(1,Form(" CompactDB %i thTrkRec %8.3f thetaCRec %8.3f ",compactDB,thTrkRec,thetaCRec));
336
337 phiTrkRec *= TMath::DegToRad();
ee2f3539 338 thTrkRec *= TMath::DegToRad();
339 thetaCRec *= TMath::DegToRad();
9785d5fb 340
ee2f3539 341 status = kTRUE;
5a3482a0 342
343 delete [] phiphotP;
344 delete [] distP;
345
346 return status;
347}
348//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
349Bool_t AliHMPIDReconHTA::ShapeModel(Int_t np,Double_t *phiphot,Double_t *dist,Double_t &xA,Double_t &xB,Double_t &phiStart)
350{
aa00f952 351// Find a Spline curve to define dist. vs. phi angle
352// in order to estimate the phi of the track
353// Arguments: np - # points corresponding to # photon candidates
354// dist - distance of each photon from MIP
355// phiphot - phi of the photon in the DRS
356// Returns: xA - min. distance from MIP
357// xB - dist. from mip perpedicular to the major axis
358// phiStart- estimate of the track phi
359
5a3482a0 360 TGraph *phigr = new TGraph(np,phiphot,dist);
2e81abb0 361 phiStart = FindSimmPhi();
362
363 Double_t phiStart1 = phiStart;
364 if(phiStart1 > 360) phiStart1 -= 360;
365 Double_t phiStart2 = phiStart+90;
366 if(phiStart2 > 360) phiStart2 -= 360;
367 xA = phigr->Eval(phiStart1);
368 xB = phigr->Eval(phiStart2);
369 //---
370 AliDebug(1,Form("phiStart %f phiStart1 %f phiStart2 %f ",phiStart,phiStart1,phiStart2));
371 AliDebug(1,Form("xA %f xB %f",xA,xB));
5a3482a0 372
2e81abb0 373 phiStart += 180;
374 if(phiStart>360) phiStart-=360;
5a3482a0 375
5a3482a0 376 return kTRUE;
377}
378//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
aa00f952 379Double_t AliHMPIDReconHTA::VertParab(Double_t x1,Double_t y1,Double_t x2, Double_t y2, Double_t x3, Double_t y3)const
5a3482a0 380{
aa00f952 381// It uses parabola from 3 points to evaluate the x-coord of the parab
382// Arguments: xi,yi - points
383// Returns: x-coord of the vertex
384
5a3482a0 385 Double_t a = ((x1-x3)*(y1-y2)-(x1-x2)*(y1-y3))/((x1*x1-x2*x2)*(x1-x3)-(x1*x1-x3*x3)*(x1-x2));
386 Double_t b = (y1-y2 - a*(x1*x1-x2*x2))/(x1-x2);
387// Double_t c = y1 - a*x1*x1-b*x1;
388 return -0.5*b/a;
389}
390//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2e81abb0 391Bool_t AliHMPIDReconHTA::FitRing(Double_t thTrkRec,Double_t phiTrkRec)
392{
393 Double_t th = thTrkRec;
394 Double_t ph = phiTrkRec;
395
396 FitFree(th,ph);
397 while(FitStatus()) {
398 th = fThTrkFit;
399 ph = fPhTrkFit;
400 FitFree(th,ph);
401 }
402 return kTRUE;
403}
404//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5a3482a0 405Bool_t AliHMPIDReconHTA::FitFree(Double_t thTrkRec,Double_t phiTrkRec)
406{
407// Fit performed by minimizing RMS/sqrt(n) of the
408// photons reconstructed. First phi is fixed and theta
409// is fouond, then (th,ph) of the track
410// as free parameters
411// Arguments: PhiRec phi of the track
412// Returns: none
413
5a3482a0 414 TMinuit *pMinuit = new TMinuit(2);
415 pMinuit->mncler();
416 gMinuit->SetObjectFit((TObject*)this); gMinuit->SetFCN(AliHMPIDReconHTA::FunMinPhot); //set fit function
417 Double_t aArg=-1,parStep,parLow,parHigh; Int_t iErrFlg; //tmp vars for TMinuit
418 Double_t d1,d2,d3;
419 TString sName;
420 Double_t th,ph;
421
422 pMinuit->mnexcm("SET PRI",&aArg,1,iErrFlg); //suspend all printout from TMinuit
423 pMinuit->mnexcm("SET NOW",&aArg,0,iErrFlg);
424
425 if(thTrkRec==0) thTrkRec = 3.*TMath::DegToRad(); // not to start from the edge...
426
2e81abb0 427 AliDebug(1,Form(" Minimization STARTED with phiTRK %6.2f thetaTRK %6.2f",phiTrkRec,thTrkRec));
428
5a3482a0 429 pMinuit->mnparm(0," thTrk ",thTrkRec ,parStep=0.01,parLow=0,parHigh=TMath::PiOver4(),iErrFlg);
430 pMinuit->mnparm(1," phiTrk ",phiTrkRec,parStep=0.01,parLow=0,parHigh=TMath::TwoPi(),iErrFlg);
431
432 pMinuit->FixParameter(1);
433 pMinuit->mnexcm("SIMPLEX" ,&aArg,0,iErrFlg);
434 pMinuit->mnexcm("MIGRAD" ,&aArg,0,iErrFlg);
435 pMinuit->Release(1);
436 pMinuit->mnexcm("MIGRAD" ,&aArg,0,iErrFlg);
437
438 pMinuit->mnpout(0,sName,th,d1,d2,d3,iErrFlg);
439 pMinuit->mnpout(1,sName,ph,d1,d2,d3,iErrFlg);
440
441 Double_t f,par[2];
442 Double_t *grad=0x0;
443 par[0] = th;par[1] = ph;
444 pMinuit->Eval(2,grad,f,par,3);
445
5a3482a0 446 SetTrkFit(th,ph);
447 return kTRUE;
448}
449//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
450void AliHMPIDReconHTA::FunMinPhot(Int_t &/* */,Double_t* /* */,Double_t &f,Double_t *par,Int_t iflag)
451{
452// Minimization function to find best track and thetaC parameters
453// Arguments: f = function value to minimize
454// par = list of parameter to find
455// iflag = flag status. See Minuit instructions
456// Returns: none
457//
458// Note: it is necessary to call an instance of AlihMPIDParam. Not possible to use fParam
459// because of the static instantiation of the function in Minuit
460
461 AliHMPIDParam *pParam=AliHMPIDParam::Instance();
462 AliHMPIDReconHTA *pRecHTA=(AliHMPIDReconHTA*)gMinuit->GetObjectFit();
463 AliHMPIDRecon pRec;
464 Double_t sizeCh = 0.5*pParam->RadThick()+pParam->WinThick()+pParam->GapThick();
465 Double_t thTrk = par[0];
466 Double_t phTrk = par[1];
467 Double_t xrad = pRecHTA->MipX() - sizeCh*TMath::Tan(thTrk)*TMath::Cos(phTrk);
468 Double_t yrad = pRecHTA->MipY() - sizeCh*TMath::Tan(thTrk)*TMath::Sin(phTrk);
469 pRecHTA->SetRadXY(xrad,yrad);
470 pRec.SetTrack(xrad,yrad,thTrk,phTrk);
471
472 Double_t meanCkov =0;
473 Double_t meanCkov2=0;
474 Double_t thetaCer,phiCer;
475 Int_t nClAcc = 0;
476 Int_t nClTot=pRecHTA->NClu();
2e81abb0 477
5a3482a0 478 for(Int_t i=0;i<nClTot;i++) {
2e81abb0 479
480 if(pRecHTA->IdxMip() == i) {
481 pRecHTA->SetPhotAngles(i,999.,999.);
482 continue;
483 }
484
5a3482a0 485 if(!(pRecHTA->ClCk(i))) continue;
2e81abb0 486
487 Bool_t status = pRec.FindPhotCkov(pRecHTA->XClu(i),pRecHTA->YClu(i),thetaCer,phiCer);
488 if(!status) {
489 pRecHTA->SetPhotAngles(i,999.,999.);
490 continue;
491 }
492 pRecHTA->SetPhotAngles(i,thetaCer,phiCer);
5a3482a0 493 meanCkov += thetaCer;
494 meanCkov2 += thetaCer*thetaCer;
495 nClAcc++;
496 }
2e81abb0 497
5a3482a0 498 if(nClAcc==0) {f=999;return;}
499 meanCkov /=(Double_t)nClAcc;
500 meanCkov2 /=(Double_t)nClAcc;
501 Double_t rms = TMath::Sqrt(TMath::Abs(meanCkov2 - meanCkov*meanCkov));
502 f = rms/TMath::Sqrt((Double_t)nClAcc);
503
504 if(iflag==3) {
2e81abb0 505 Int_t nClAccStep1 = nClAcc;
5a3482a0 506 nClAcc = 0;
507 Double_t meanCkov1=0;
876a9d77 508 Double_t meanCkov3=0;
5a3482a0 509 for(Int_t i=0;i<nClTot;i++) {
2e81abb0 510
511 if(!(pRecHTA->ClCk(i))) continue;
512 thetaCer = pRecHTA->PhotTheta(i);
5a3482a0 513 if(TMath::Abs(thetaCer-meanCkov)<2*rms) {
514 meanCkov1 += thetaCer;
876a9d77 515 meanCkov3 += thetaCer*thetaCer;
5a3482a0 516 nClAcc++;
2e81abb0 517 } else pRecHTA->SetClCk(i,kFALSE);
518 }
519
520 if(nClAcc<3) {
521 pRecHTA->SetFitStatus(kFALSE);
522 pRecHTA->SetCkovFit(meanCkov);
523 pRecHTA->SetCkovSig2(rms*rms);
524 pRecHTA->SetNCluFit(nClAccStep1);
525 return;
5a3482a0 526 }
2e81abb0 527
5a3482a0 528 meanCkov1/=nClAcc;
876a9d77 529 Double_t rms2 = (meanCkov3 - meanCkov*meanCkov*nClAcc)/nClAcc;
6d7793cf 530
531 // get a logger instance
532 // what for??
533 AliLog::GetRootLogger();
534
2e81abb0 535 if(nClAcc!=nClAccStep1) pRecHTA->SetFitStatus(kTRUE); else pRecHTA->SetFitStatus(kFALSE);
536
537 pRecHTA->SetCkovFit(meanCkov1);
538 pRecHTA->SetCkovSig2(rms2);
539 pRecHTA->SetNCluFit(nClAcc);
5a3482a0 540 }
541}//FunMinPhot()
542//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
543void AliHMPIDReconHTA::InitDatabase()
544{
aa00f952 545// Construction a database of ring shapes on fly
546// Arguments: none
547// Returns : none
170a4fc5 548// N.B. fgDB is the distance with x-min from MIP
549// y-dist from the ring of the MIP perpendicular to major axis
aa00f952 550// The content is the packed info of track theta and thetaC in degrees
551// thetaC+1000*thTrk
552//
9785d5fb 553// TFile *pout = new TFile("./database.root","recreate");
ee2f3539 554
170a4fc5 555 static Bool_t isDone = kFALSE;
556
5a3482a0 557 TStopwatch timer;
170a4fc5 558
559 if(isDone) {
5565f017 560 return;
561 }
170a4fc5 562
563 if(!isDone) {
564 timer.Start();
565 }
566
5a3482a0 567 AliInfo(Form("database HTA is being built.Please, wait..."));
568//
c61a7285 569 Double_t x[3]={0,0,0},y[3];
5a3482a0 570
571 AliHMPIDRecon rec;
572
573 if(!fParam) fParam=AliHMPIDParam::Instance();
574 Double_t thetaMax = TMath::ACos(1./fParam->MeanIdxRad());
575 Double_t thTrkMax = 1./TMath::ASin(fParam->MeanIdxRad());
576
577 Int_t nstepx = 1000;
578 Int_t nstepy = 1000;
579
5a3482a0 580 //
581 Double_t xrad = 0;
582 Double_t yrad = 0;
583 Double_t phTrk = 0;
584
585 for(Int_t i=0;i<nstepx;i++) { //loop on thetaC
586 for(Int_t j=0;j<nstepy;j++) { //loop on theta particle
587 Double_t thetaC = thetaMax/nstepx*((Double_t)i+0.5);
588 Double_t thTrk = thTrkMax/nstepy*((Double_t)j+0.5);
589 //
590 //mip position
591 //
fcaff63d 592 Double_t sizeCh = 0.5*fParam->RadThick()+fParam->WinThick()+fParam->GapThick();
5a3482a0 593 Double_t xmip = xrad + sizeCh*TMath::Tan(thTrk)*TMath::Cos(phTrk);
594 Double_t ymip = yrad + sizeCh*TMath::Tan(thTrk)*TMath::Sin(phTrk);
595
596 Double_t dist1,dist2;
597 //
598 //first point at phi=0
599 //
600 rec.SetTrack(xrad,yrad,thTrk,phTrk);
601 TVector2 pos;
602 pos=rec.TracePhot(thetaC,0);
603
604 if(pos.X()==-999) {
ee2f3539 605 dist1 = 0; //open ring...only the distance btw mip and point at 180 will be considered
5a3482a0 606 } else {
607 x[0] = pos.X(); y[0] = pos.Y();
608 dist1 = TMath::Sqrt((x[0]-xmip)*(x[0]-xmip)+(y[0]-ymip)*(y[0]-ymip));
609 }
610 //
611 //second point at phi=180
612 //
613 rec.SetTrack(xrad,yrad,thTrk,phTrk);
614 pos=rec.TracePhot(thetaC,TMath::Pi());
615
2e81abb0 616 if(pos.X()==-999) {AliDebug(1,Form("it should not happens!Bye"));return;}
5a3482a0 617 x[1] = pos.X(); y[1] = pos.Y();
618 if((x[1]-xmip)*(x[0]-xmip)>0) continue; // to avoid circles out mips (for very low ThetaC)
619 dist2 = TMath::Sqrt((x[1]-xmip)*(x[1]-xmip)+(y[1]-ymip)*(y[1]-ymip));
620
621// Double_t distA = dist1+dist2;
622 Double_t distA = dist2; // only the minimum: problem of acceptance
623 //
624 //second point at phi=90
625 //
626 rec.SetTrack(xrad,yrad,thTrk,phTrk);
627 pos=rec.TracePhot(thetaC,TMath::PiOver2());
628
629 if(pos.X()==-999) continue;
630 x[2] = pos.X(); y[2] = pos.Y();
631 Double_t distB = TMath::Sqrt((x[2]-xmip)*(x[2]-xmip)+(y[2]-ymip)*(y[2]-ymip));
632// compact the infos...
633 Int_t compact = (Int_t)(thetaC*TMath::RadToDeg())+1000*(Int_t)(thTrk*TMath::RadToDeg());
ee2f3539 634 Int_t binxDB,binyDB;
635 FindBinDB(distA,distB,binxDB,binyDB);
170a4fc5 636 if(fgDB[binxDB][binyDB]==0) fgDB[binxDB][binyDB] = compact;
5a3482a0 637 }
638 }
639
9785d5fb 640 FillZeroChan();
5a3482a0 641
170a4fc5 642 if(!isDone) {
643 timer.Stop();
644 Double_t nSecs = timer.CpuTime();
645 AliInfo(Form("database HTA successfully open in %3.1f sec.(CPU). Reconstruction is started.",nSecs));
646 isDone = kTRUE;
647 }
9785d5fb 648
649// pout->Write();
650// pout->Close();
651
9a573d52 652}//InitDatabase()
5a3482a0 653//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
9785d5fb 654void AliHMPIDReconHTA::FillZeroChan()const
5a3482a0 655{
606697a8 656 //If fills eventually channel without entries
657 //inthe histo "database" jyst interpolating the neighboring cells
658 // Arguments: histogram pointer of the database
659 // Returns: none
660 //
170a4fc5 661 const Int_t nxDB = 500;
662 const Int_t nyDB = 150;
663
664 for(Int_t i = 0;i<nxDB;i++) {
665 for(Int_t j = 0;j<nyDB;j++) {
666 if(fgDB[i][j] == 0) {
667 fgDB[i][j] = -1;
5a3482a0 668 Int_t nXmin = i-1; Int_t nXmax=i+1;
669 Int_t nYmin = j-1; Int_t nYmax=j+1;
670 Int_t nc = 0;
671 Double_t meanC =0;
672 Double_t meanTrk =0;
673 for(Int_t ix=nXmin;ix<=nXmax;ix++) {
170a4fc5 674 if(ix<0||ix>=nxDB) continue;
5a3482a0 675 for(Int_t iy=nYmin;iy<=nYmax;iy++) {
170a4fc5 676 if(iy<0||iy>=nyDB) continue;
677 meanC += (Int_t)(fgDB[ix][iy]%1000);
678 meanTrk+= (Int_t)(fgDB[ix][iy]/1000);
5a3482a0 679 nc++;
680 }
681 meanC/=nc; meanTrk/=nc;
682 Int_t compact = (Int_t)meanC+1000*(Int_t)meanTrk;
170a4fc5 683 if(compact>0)fgDB[i][j] = compact;
5a3482a0 684 }
685 }
686 }
687 }
9a573d52 688}//FillZeroChan()
5a3482a0 689//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ee2f3539 690Int_t AliHMPIDReconHTA::r2(Double_t *coef, Double_t &x1, Double_t &x2)
691{
692 //2nd deg. equation
693 //solution
694 // Arguments: coef 2 1 0: ax^2+bx+c=0
695 // Returns: n. of solutions
696 // x1= 1st sol
697 // x2= 2nd sol
698 Double_t a,b,c;
699 a = coef[2];
700 b = coef[1];
701 c = coef[0];
702 Double_t delta = b*b-4*a*c;
703 if(delta<0) {return 0;}
704 if(delta==0) {
705 x1=x2=-b/(2*a);
706 return 1;
707 }
708 // delta>0
709 x1 = (-b+TMath::Sqrt(delta))/(2*a);
710 x2 = (-b-TMath::Sqrt(delta))/(2*a);
711 return 2;
712}//r2()
713//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
9a573d52 714
715Double_t AliHMPIDReconHTA::FindSimmPhi()
ee2f3539 716{
717//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2e81abb0 718// Reconstruction of phiTRK angle with two methods (in switching)
719//
720// - least square method (for closed rings)
721// - by minimum distance mip-photon (for open rings)
ee2f3539 722
723 Float_t coeff1ord=0; Float_t coeff2ord=0; Float_t coeff0ord=0;
9a573d52 724 Float_t xrotsumm =0; Float_t yrotsumm =0; Float_t xx =0;
2e81abb0 725 Float_t yy =0; Float_t xy =0;
ee2f3539 726 Double_t xmin=0;
727 Double_t ymin=0;
9a573d52 728
729 Int_t np=0;
ee2f3539 730
731 Double_t distMin = 999.;
732
9a573d52 733 for(Int_t i=0;i<fNClu;i++) {
734 if(!fClCk[i]) continue;
735 np++;
736 xrotsumm+=fXClu[i]; // summ xi
737 yrotsumm+=fYClu[i]; // summ yi
738 xx+=fXClu[i]*fXClu[i]; // summ xixi
739 yy+=fYClu[i]*fYClu[i]; // summ yiyi
740 xy+=fXClu[i]*fYClu[i]; // summ yixi
ee2f3539 741 Double_t dist2= (fXClu[i]-fMipX)*(fXClu[i]-fMipX)+(fYClu[i]-fMipY)*(fYClu[i]-fMipY);
742 if(dist2<distMin) {
743 distMin = dist2;
744 xmin = fXClu[i];
745 ymin = fYClu[i];
746 }
9a573d52 747 }
ee2f3539 748
2e81abb0 749 Double_t AngM = TMath::ATan2(ymin-fMipY,(xmin-fMipX))*TMath::RadToDeg();
750 if (AngM<0) AngM+=360;
751
752 AliDebug(1,Form(" Simple angle prediction with MIN phi = %f",AngM));
9a573d52 753
ee2f3539 754 //_____calc. met min quadr using effective distance _________________________________________________
9a573d52 755
2e81abb0 756 coeff2ord = xy-xrotsumm*yrotsumm/np;
757 coeff1ord = yrotsumm*yrotsumm/np - xrotsumm*xrotsumm/np - yy + xx;
758 coeff0ord = -coeff2ord;
759
760 AliDebug(1,Form(" a = %f b = %f c = %f",coeff2ord,coeff1ord,coeff0ord));
761
ee2f3539 762 Double_t m1=0, m2=0; Double_t n1=0, n2=0;
763 // c // b // a
764 Double_t coeff[3]={coeff0ord,coeff1ord,coeff2ord};
9a573d52 765
766 r2(coeff,m1,m2);
767
768 n1=(yrotsumm-m1*xrotsumm)/np;
769 n2=(yrotsumm-m2*xrotsumm)/np;
ee2f3539 770 // 2 solutions.................
771
ee2f3539 772 // negative angles solved...
773
9a573d52 774 Double_t d1 =(1/(m1*m1+1))*(yy+m1*m1*xx+np*n1*n1-2*m1*xy-2*n1*yrotsumm+2*m1*n1*xrotsumm);
775 Double_t d2 =(1/(m2*m2+1))*(yy+m2*m2*xx+np*n2*n2-2*m2*xy-2*n2*yrotsumm+2*m2*n2*xrotsumm);
2e81abb0 776
777 AliDebug(1,Form(" predicted distance d1 %f for angle %6.2f d2 %f for angle %6.2f",d1,TMath::ATan(m1)*TMath::RadToDeg(),
778 d2,TMath::ATan(m2)*TMath::RadToDeg()));
9a573d52 779 Double_t mMin;
780 if(d1 > d2) mMin = m2; else mMin = m1;
781
2e81abb0 782 Double_t phiTrk=0;
ee2f3539 783 //
2e81abb0 784 if(ymin < fMipY && xmin > fMipX) {phiTrk = TMath::ATan(mMin)*TMath::RadToDeg()+180;}
785 if(ymin > fMipY && xmin < fMipX) {phiTrk = TMath::ATan(mMin)*TMath::RadToDeg()+360;}
786 if(ymin > fMipY && xmin > fMipX) {phiTrk = TMath::ATan(mMin)*TMath::RadToDeg()+180;}
787 if(ymin < fMipY && xmin < fMipX) {phiTrk = TMath::ATan(mMin)*TMath::RadToDeg();}
788 if(ymin == fMipY && xmin > fMipX) {phiTrk = TMath::ATan(mMin)*TMath::RadToDeg()+180;}
789 if(ymin == fMipY && xmin < fMipX) {phiTrk = TMath::ATan(mMin)*TMath::RadToDeg();}
790 if(ymin < fMipY && xmin == fMipX) {phiTrk = 90;}
791 if(ymin > fMipY && xmin == fMipX) {phiTrk = 270;}
9a573d52 792
ee2f3539 793 // ------------------------- choose the best-----------------------
9a573d52 794
ee2f3539 795
2e81abb0 796 if( AngM-40 <= phiTrk && AngM+40 >= phiTrk) return phiTrk; else return AngM;
9a573d52 797}
9a573d52 798//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ee2f3539 799void AliHMPIDReconHTA::FindBinDB(Double_t x,Double_t y,Int_t &binX,Int_t &binY)
9a573d52 800{
170a4fc5 801 const Int_t nxDB = 500;
802 const Int_t nyDB = 150;
ee2f3539 803 const Double_t xlowDB = 0;
804 const Double_t xhigDB = 50;
805 const Double_t ylowDB = 0;
2e81abb0 806 const Double_t yhigDB = 30;
ee2f3539 807
808 binX = -1;
809 binY = -1;
170a4fc5 810 if(x<xlowDB && x>xhigDB &&
811 y<ylowDB && y>yhigDB) return;
812 binX = Int_t((x-xlowDB)/(xhigDB-xlowDB)*nxDB);
813 binY = Int_t((y-ylowDB)/(yhigDB-ylowDB)*nyDB);
814 if(binX>=nxDB || binY>=nyDB) {
815 binX = -1;
816 binY = -1;
817 }
818
ee2f3539 819}
2e81abb0 820//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
821Bool_t AliHMPIDReconHTA::UniformDistrib()
822{
823 AliHMPIDParam *pParam=AliHMPIDParam::Instance();
824 AliHMPIDRecon pRec;
825
826 Double_t sizeCh = 0.5*pParam->RadThick()+pParam->WinThick()+pParam->GapThick();
827 Double_t xrad = MipX() - sizeCh*TMath::Tan(fThTrkFit)*TMath::Cos(fPhTrkFit);
828 Double_t yrad = MipY() - sizeCh*TMath::Tan(fThTrkFit)*TMath::Sin(fPhTrkFit);
829
830 pRec.SetTrack(xrad,yrad,fThTrkFit,fPhTrkFit);
831
832 Int_t npeff=0;
833 Int_t nPhotPerBin = 4;
834 for(Int_t i=0;i<fNClu;i++) {
835 if(!ClCk(i)) continue;
836 npeff++;
837 }
838
839 Int_t nPhiBins = npeff/nPhotPerBin+1;
840 if(nPhiBins<=1) nPhiBins = 2;
841
842 Double_t *iPhiBin;
843 iPhiBin = new Double_t[nPhiBins];
844
845 for(Int_t i=0;i<nPhiBins;i++) iPhiBin[i] =0;
846
847 for(Int_t i=0;i<fNClu;i++) {
848 if(!ClCk(i)) continue;
849 Double_t phiCer = PhotPhi(i);
850
851 Double_t PhiProva = phiCer*TMath::RadToDeg();
852 if(PhiProva<0) PhiProva+= 360;
853 Int_t index = (Int_t)((Float_t)nPhiBins*PhiProva/360.);
854 iPhiBin[index]++;
855 }
856
857 Double_t chi2 = 0;
858 for(Int_t i=0;i<nPhiBins;i++) {
859 Double_t theo = (Double_t)npeff/(Double_t)nPhiBins;
860 chi2+= (iPhiBin[i] - theo)*(iPhiBin[i] - theo)/theo;
861 }
862
863 delete iPhiBin;
864
865 Double_t prob = TMath::Prob(chi2, nPhiBins-1);
866 AliDebug(1,Form(" Probability for uniform distrib: %6f.3 %s",prob,(prob<0.05) ? "rejected" : "accepted"));
867 if(prob<0.05) return kFALSE;
868 return kTRUE;
869
870 }
871//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++