]> git.uio.no Git - u/mrichter/AliRoot.git/blame - RALICE/icepack/IcePandel.cxx
07-mar-2006 NvE Facility introduced in IceDwalk and IcePandel to modify the name...
[u/mrichter/AliRoot.git] / RALICE / icepack / IcePandel.cxx
CommitLineData
c29371c1 1/*******************************************************************************
2 * Copyright(c) 2003, IceCube Experiment at the South Pole. All rights reserved.
3 *
4 * Author: The IceCube RALICE-based Offline 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.
12 * The authors make no claims about the suitability of this software for
13 * any purpose. It is provided "as is" without express or implied warranty.
14 *******************************************************************************/
15
16// $Id$
17
18///////////////////////////////////////////////////////////////////////////
19// Class IcePandel
20// TTask derived class to perform Pandel fitting.
21//
22// The code in this processor is based on the algorithms as developed
23// by Oladipo Fadiran and George Japaridze (Clark Atlanta University, USA).
24//
25// Use the UseTracks memberfunction to specify the first guess tracks
26// to be processed by the minimiser.
27// By default only the first encountered IceDwalk track will be processed.
28//
29// Use the SelectHits memberfunction to specify the hits to be used.
30// By default only the hits associated to the first guess track are used.
31//
32// The fit processor (TFitter which is basically Minuit) printlevel
33// can be selected via the memberfunction SetPrintLevel.
34// By default all printout is suppressed (i.e. level=-2).
35//
36// An example of how to invoke this processor after Xtalk, hit cleaning
37// and a direct walk first guess estimate can be found in the ROOT example
38// macro icepandel.cc which resides in the /macros subdirectory.
39//
40// The minimisation results are stored in the IceEvent structure as
d6860cf1 41// tracks with as default the name "IcePandel" (just like the first guess
42// results of e.g. IceDwalk).
43// This track name identifier can be modified by the user via the
44// SetTrackName() memberfunction. This will allow unique identification
45// of tracks which are produced when re-processing existing data with
46// different criteria.
c29371c1 47// A pointer to the first guess track which was used as input is available
48// via the GetParentTrack facility of these "IcePandel" tracks.
49// Furthermore, all the hits that were used in the minisation are available
50// via the GetSignal facility of a certain track.
51// The statistics of the TFitter result are stored as an AliSignal object
52// in the track, which can be obtained via the GetFitDetails memberfunction.
53// Currently no overall probability has yet been defined to indicate the
54// quality of a certain fit result. So, for the time being the user has
55// to judge the fit quality his/herself by means of the various TFitter stats
56// as accessible via the GetFitDetails facility.
57//
58// An example of how the various data can be accessed is given below,
59// where "evt" indicates the pointer to the IceEvent structure.
60//
61// Example for accessing data :
62// ----------------------------
63// TObjArray* tracks=evt->GetTracks("IcePandel");
64// if (!tracks) return;
65// AliPosition* r0=0;
66// Float_t fcn=0;
67// for (Int_t jtk=0; jtk<tracks->GetEntries(); jtk++)
68// {
69// AliTrack* tx=(AliTrack*)tracks->At(jtk);
70// if (!tx) continue;
71// tx->Data("sph");
72// r0=tx->GetReferencePoint();
73// if (r0) r0->Data();
74// sx=(AliSignal*)tx->GetFitDetails();
75// if (sx) fcn=sx->GetSignal("FCN");
76// AliTrack* tx2=tx->GetParentTrack();
77// if (!tx2) continue;
78// tx2->Data("sph");
79// r0=tx2->GetReferencePoint();
80// if (r0) r0->Data();
81// }
82//
83// Notes :
84// -------
85// 1) This processor only works properly on data which are Time and ADC
86// calibrated and contain tracks from first guess algorithms like
87// e.g. IceDwalk.
88// 2) In view of the usage of TFitter/Minuit minimisation, a global pointer
89// to the instance of this class (gIcePandel) and a global static
90// wrapper function (IcePandelFCN) have been introduced, to allow the
91// actual minimisation to be performed via the memberfunction FitFCN.
92// This implies that in a certain processing job only 1 instance of
93// this IcePandel class may occur.
94//
95//--- Author: Nick van Eijndhoven 09-feb-2006 Utrecht University
96//- Modified: NvE $Date$ Utrecht University
97///////////////////////////////////////////////////////////////////////////
98
99#include "IcePandel.h"
100#include "Riostream.h"
101
102// Global pointer to the instance of this object
103 IcePandel* gIcePandel=0;
104
105// TFitter/Minuit interface to IcePandel::FitFCN
106 void IcePandelFCN(Int_t& npar,Double_t* gin,Double_t& f,Double_t* u,Int_t flag)
107 {
108 if (gIcePandel) gIcePandel->FitFCN(npar,gin,f,u,flag);
109 }
110
111ClassImp(IcePandel) // Class implementation to enable ROOT I/O
112
113IcePandel::IcePandel(const char* name,const char* title) : TTask(name,title)
114{
115// Default constructor.
116 fFirst=1;
117 fPrint=-2;
118 fSelhits=1;
119 fEvt=0;
120 fUseNames=0;
121 fUseNtk=0;
122 fTrack=0;
123 fHits=0;
124 fFitter=0;
d6860cf1 125 fTrackname="IcePandel";
c29371c1 126
127 // Set the global pointer to this instance
128 gIcePandel=this;
129}
130///////////////////////////////////////////////////////////////////////////
131IcePandel::~IcePandel()
132{
133// Default destructor.
134 if (fUseNames)
135 {
136 delete fUseNames;
137 fUseNames=0;
138 }
139 if (fUseNtk)
140 {
141 delete fUseNtk;
142 fUseNtk=0;
143 }
144 if (fHits)
145 {
146 delete fHits;
147 fHits=0;
148 }
149 if (fFitter)
150 {
151 delete fFitter;
152 fFitter=0;
153 }
154}
155///////////////////////////////////////////////////////////////////////////
156void IcePandel::Exec(Option_t* opt)
157{
158// Implementation of the hit fitting procedure.
159
160 TString name=opt;
161 AliJob* parent=(AliJob*)(gROOT->GetListOfTasks()->FindObject(name.Data()));
162
163 if (!parent) return;
164
165 fEvt=(IceEvent*)parent->GetObject("IceEvent");
166 if (!fEvt) return;
167
168 if (!fUseNames) UseTracks("IceDwalk",1);
169
170 Int_t nclasses=fUseNames->GetEntries(); // Number of first guess classes to be processed
171 Int_t ntkmax=0; // Max. number of tracks for a certain class
172 TObjString* strx=0;
173 TString str;
174
175 if (fFirst)
176 {
177 cout << " *IcePandel* First guess selections to be processed (-1=all)." << endl;
178 for (Int_t i=0; i<nclasses; i++)
179 {
180 strx=(TObjString*)fUseNames->At(i);
181 if (!strx) continue;
182 str=strx->GetString();
183 ntkmax=fUseNtk->At(i);
184 cout << " Maximally " << ntkmax << " track(s) per event for procedure : " << str.Data() << endl;
185 }
186 cout << " *IcePandel* Hit selection mode : " << fSelhits << endl;
187 cout << endl;
188 fFirst=0;
189 }
190
191 Double_t pi=acos(-1.);
192
193 // Initialisation of the minimisation processor
194 Double_t arglist[100];
195 if (!fFitter) fFitter=new TFitter();
196
197 // The number of reconstructed tracks already present in the event
198 Int_t ntkreco=fEvt->GetNtracks(1);
199
200 if (!fHits)
201 {
202 fHits=new TObjArray();
203 }
204 else
205 {
206 fHits->Clear();
207 }
208
209 // If selected, use all the good quality hits of the complete event
210 if (fSelhits==0)
211 {
212 TObjArray* hits=fEvt->GetHits("IceGOM");
213 for (Int_t ih=0; ih<hits->GetEntries(); ih++)
214 {
215 AliSignal* sx=(AliSignal*)hits->At(ih);
216 if (!sx) continue;
217 if (sx->GetDeadValue("ADC") || sx->GetDeadValue("LE") || sx->GetDeadValue("TOT")) continue;
218 fHits->Add(sx);
219 }
220 }
221
222 // Track by track processing of the selected first guess classes
223 Float_t vec[3];
224 Float_t err[3];
225 Float_t margin,minmarg=25; // (minimal) margin for the fitter r0 search area
226 Ali3Vector p;
227 AliPosition pos;
228 AliTrack tkfit;
d6860cf1 229 tkfit.SetNameTitle(fTrackname.Data(),"IcePandel fit result");
c29371c1 230 AliSignal fitstats;
231 fitstats.SetNameTitle("Fitstats","TFitter stats for Pandel fit");
232 fitstats.SetSlotName("IER",1);
233 fitstats.SetSlotName("FCN",2);
234 fitstats.SetSlotName("EDM",3);
235 fitstats.SetSlotName("NVARS",4);
d6860cf1 236 Float_t x,y,z,theta,phi;
237 Float_t xmin,xmax,ymin,ymax,zmin,zmax,thetamin,thetamax,phimin,phimax;
c29371c1 238 Double_t amin,edm,errdef; // Minimisation stats
239 Int_t ier,nvpar,nparx; // Minimisation stats
240 Int_t ntk=0;
241 Int_t nsig=0;
242 for (Int_t iclass=0; iclass<nclasses; iclass++) // Loop over first guess classes
243 {
244 strx=(TObjString*)fUseNames->At(iclass);
245 if (!strx) continue;
246 str=strx->GetString();
247 ntkmax=fUseNtk->At(iclass);
248 TObjArray* tracks=fEvt->GetTracks(str);
249 ntk=tracks->GetEntries();
250 if (ntkmax>0 && ntk>ntkmax) ntk=ntkmax;
251
252 for (Int_t jtk=0; jtk<ntk; jtk++) // Loop over tracks of a certain class
253 {
254 fTrack=(AliTrack*)tracks->At(jtk);
255 if (!fTrack) continue;
256
257 AliPosition* r0=fTrack->GetReferencePoint();
258 if (!r0) continue;
259
260 // If selected, use only the first guess track associated hits
261 if (fSelhits==1)
262 {
263 fHits->Clear();
264 nsig=fTrack->GetNsignals();
265 for (Int_t is=1; is<=nsig; is++)
266 {
267 AliSignal* sx=fTrack->GetSignal(is);
268 if (!sx) continue;
269 if (!sx->GetDevice()->InheritsFrom("IceGOM")) continue;
270 if (sx->GetDeadValue("ADC") || sx->GetDeadValue("LE") || sx->GetDeadValue("TOT")) continue;
271 fHits->Add(sx);
272 }
273 }
274
275 if (!fHits->GetEntries()) continue;
276
277 r0->GetVector(vec,"car");
278 r0->GetErrors(err,"car");
279
280 x=vec[0];
281 y=vec[1];
282 z=vec[2];
283 margin=5.*err[0];
284 if (margin<minmarg) margin=minmarg;
285 xmin=x-margin;
286 xmax=x+margin;
287 margin=5.*err[1];
288 if (margin<minmarg) margin=minmarg;
289 ymin=y-margin;
290 ymax=y+margin;
291 margin=5.*err[2];
292 if (margin<minmarg) margin=minmarg;
293 zmin=z-margin;
294 zmax=z+margin;
295
296 p=fTrack->Get3Momentum();
297 p.GetVector(vec,"sph");
298
299 theta=vec[1];
300 phi=vec[2];
301 thetamin=theta-(pi/3.);
302 if (thetamin<0) thetamin=0;
303 thetamax=theta+(pi/3.);
304 if (thetamax>pi) thetamax=pi;
305 phimin=phi-(pi/2.);
306 phimax=phi+(pi/2.);
307
308 // Process this first guess track with its associated hits
309 fFitter->Clear();
310
311 arglist[0]=fPrint;
312 if (fPrint==-2) arglist[0]=-1;
313 fFitter->ExecuteCommand("SET PRINT",arglist,1);
314 if (fPrint==-2) fFitter->ExecuteCommand("SET NOWARNINGS",arglist,0);
315
316 fFitter->SetFitMethod("loglikelihood");
317
318 fFitter->SetParameter(0,"r0x",x,0.001,xmin,xmax);
319 fFitter->SetParameter(1,"r0y",y,0.001,ymin,ymax);
320 fFitter->SetParameter(2,"r0z",z,0.001,zmin,zmax);
321 fFitter->SetParameter(3,"theta",theta,0.001,thetamin,thetamax);
322 fFitter->SetParameter(4,"phi",phi,0.001,phimin,phimax);
323
324 fFitter->SetFCN(IcePandelFCN);
325
326 arglist[0]=0;
327 ier=fFitter->ExecuteCommand("MINIMIZE",arglist,0);
328
329 fFitter->GetStats(amin,edm,errdef,nvpar,nparx);
330 fitstats.Reset();
331 fitstats.SetSignal(ier,1);
332 fitstats.SetSignal(amin,2);
333 fitstats.SetSignal(edm,3);
334 fitstats.SetSignal(nvpar,4);
335
336 // Resulting parameters after minimisation
337 vec[0]=fFitter->GetParameter(0);
338 vec[1]=fFitter->GetParameter(1);
339 vec[2]=fFitter->GetParameter(2);
340 err[0]=fFitter->GetParError(0);
341 err[1]=fFitter->GetParError(1);
342 err[2]=fFitter->GetParError(2);
343 pos.SetPosition(vec,"car");
344 pos.SetPositionErrors(err,"car");
345
346 vec[0]=1.;
347 vec[1]=fFitter->GetParameter(3);
348 vec[2]=fFitter->GetParameter(4);
349 err[0]=0.;
350 err[1]=fFitter->GetParError(3);
351 err[2]=fFitter->GetParError(4);
352 p.SetVector(vec,"sph");
353 p.SetErrors(err,"sph");
354
355 // Enter the fit result as a track in the event structure
356 tkfit.Reset();
357 ntkreco++;
358 tkfit.SetId(ntkreco);
359 tkfit.SetParentTrack(fTrack);
360 AliTimestamp* tt0=r0->GetTimestamp();
361 pos.SetTimestamp(*tt0);
362 tkfit.SetTimestamp(*tt0);
363 tkfit.SetReferencePoint(pos);
364 tkfit.Set3Momentum(p);
365 tkfit.SetFitDetails(fitstats);
366 for (Int_t ihit=0; ihit<fHits->GetEntries(); ihit++)
367 {
368 AliSignal* sx=(AliSignal*)fHits->At(ihit);
369 if (sx) tkfit.AddSignal(*sx);
370 }
371 fEvt->AddTrack(tkfit);
372 } // End loop over tracks
373 } // End loop over first guess classes
374
375}
376///////////////////////////////////////////////////////////////////////////
377void IcePandel::SetPrintLevel(Int_t level)
378{
379// Set the fitter (Minuit) print level.
380// See the TFitter and TMinuit docs for details.
381//
382// Note : level=-2 suppresses also all fit processor warnings.
383//
384// The default in the constructor is level=-2.
385
386 fPrint=level;
387}
388///////////////////////////////////////////////////////////////////////////
389void IcePandel::UseTracks(TString classname,Int_t n)
390{
391// Specification of the first guess tracks to be used.
392//
393// classname : Specifies the first guess algorithm (e.g. "IceDwalk");
394// n : Specifies the max. number of these tracks to be used
395//
396// Note : n<0 will use all the existing tracks of the specified classname
397//
398// The default is n=-1.
399//
400// Consecutive invokations of this memberfunction with different classnames
401// will result in an incremental effect.
402//
403// Example :
404// ---------
405// UseTracks("IceDwalk",5);
406// UseTracks("IceLfit",2);
407// UseTracks("IceJams");
408//
409// This will use the first 5 IceDwalk, the first 2 IceLfit and all the
410// IceJams tracks which are encountered in the event structure.
411
412 if (!fUseNames)
413 {
414 fUseNames=new TObjArray();
415 fUseNames->SetOwner();
416 }
417
418 if (!fUseNtk) fUseNtk=new TArrayI();
419
420 // Check if this classname has already been specified before
421 TString s;
422 Int_t nen=fUseNames->GetEntries();
423 for (Int_t i=0; i<nen; i++)
424 {
425 TObjString* sx=(TObjString*)fUseNames->At(i);
426 if (!sx) continue;
427 s=sx->GetString();
428 if (s==classname) return;
429 }
430
431 // New classname to be added into the storage
432 if (nen >= fUseNames->GetSize()) fUseNames->Expand(nen+1);
433 if (nen >= fUseNtk->GetSize()) fUseNtk->Set(nen+1);
434
435 TObjString* name=new TObjString();
436 name->SetString(classname);
437 fUseNames->Add(name);
438 fUseNtk->AddAt(n,nen);
439}
440///////////////////////////////////////////////////////////////////////////
441void IcePandel::SelectHits(Int_t mode)
442{
443// Specification of the hits to be used in the minimisation.
444//
445// mode = 0 : All hit cleaning survived hits of the complete event are used
446// 1 : Only the associated hits are used for each first guess track
447//
448// The default is mode=1.
449
450 if (mode==0 || mode==1) fSelhits=mode;
451}
452///////////////////////////////////////////////////////////////////////////
d6860cf1 453void IcePandel::SetTrackName(TString s)
454{
455// Set (alternative) name identifier for the produced tracks.
456// This allows unique identification of (newly) produced pandel tracks
457// in case of re-processing of existing data with different criteria.
458// By default the produced tracks have the name "IcePandel" which is
459// set in the constructor of this class.
460 fTrackname=s;
461}
462///////////////////////////////////////////////////////////////////////////
c29371c1 463void IcePandel::FitFCN(Int_t&,Double_t*,Double_t& f,Double_t* x,Int_t)
464{
465// The Pandel function used for the minimisation process.
466
467 const Float_t c=0.299792; // Light speed in vacuum in meters per ns
468 const Float_t nice=1.35634; // Refractive index of ice
469 const Float_t thetac=acos(1./nice); // Cherenkov angle (in radians)
470 const Float_t lambda=33.3; // Light scattering length in ice
471 const Float_t labs=98; // Light absorbtion length in ice
472 const Float_t cice=c/nice; // Light speed in ice in meters per ns
473 const Float_t tau=557;
474 const Double_t rho=((1./tau)+(cice/labs));
475
476 f=0;
477
478 // The first original guess track parameters
479 AliPosition* tr0=fTrack->GetReferencePoint();
480 AliTimestamp* tt0=tr0->GetTimestamp();
481 Float_t t0=fEvt->GetDifference(tt0,"ns");
482 Ali3Vector tp=fTrack->Get3Momentum();
483
484 // The new r0 and p vectors from the minimisation
485 Float_t vec[3];
486
487 AliPosition r0;
488 vec[0]=x[0];
489 vec[1]=x[1];
490 vec[2]=x[2];
491 r0.SetPosition(vec,"car");
492
493 Ali3Vector p;
494 vec[0]=1;
495 vec[1]=x[3];
496 vec[2]=x[4];
497 p.SetVector(vec,"sph");
498
499 Int_t nhits=fHits->GetEntries();
500 AliPosition rhit;
501 Ali3Vector r12;
502 Float_t d,dist,thit,tgeo;
503 Double_t tres,zeta,pandel;
504 for (Int_t i=0; i<nhits; i++)
505 {
506 AliSignal* sx=(AliSignal*)fHits->At(i);
507 if (!sx) continue;
508 IceGOM* omx=(IceGOM*)sx->GetDevice();
509 if (!omx) continue;
510 rhit=omx->GetPosition();
511 d=fTrack->GetDistance(rhit);
512 zeta=d/lambda;
513 d*=sin(thetac);
514 r12=rhit-r0;
515 dist=p.Dot(r12)+d*tan(thetac);
516 tgeo=t0+dist/c;
517 thit=sx->GetSignal("LE",7);
518 tres=thit-tgeo;
519
520 // The Pandel function evaluation
521 // Avoid minimiser problem for infinite derivative on Pandel surface
522 // This problem will be absent when using a smooth convoluted Pandel
523 if (tres>0 && zeta>=1)
524 {
525 pandel=pow(rho,zeta)*pow(tres,(zeta-1.))*exp(-rho*tres)/TMath::Gamma(zeta);
526 }
527 else
528 {
529 pandel=1.e-6;
530 }
531
532 // Use 10*log10 expression to obtain intuitive decibel scale
533 f-=10.*log10(pandel);
534 }
535}
536///////////////////////////////////////////////////////////////////////////