FairRoot/PandaRoot
Fitter.cxx
Go to the documentation of this file.
1 // ******************************************************
2 // DecayTreeFitter Package
3 // We thank the original author Wouter Hulsbergen
4 // (BaBar, LHCb) for providing the sources.
5 // http://arxiv.org/abs/physics/0503191v1 (2005)
6 // Adaptation & Development for PANDA: Ralf Kliemt (2015)
7 // ******************************************************
8 // $Id: Fitter.cpp,v 1.16 2010/06/09 17:55:46 ibelyaev Exp $
9 // ============================================================================
10 #include <iomanip>
11 #include <stdio.h>
12 #include <sstream>
13 //#include <boost/foreach.hpp>
14 
15 //#include "GaudiKernel/PhysicalConstants.h"
16 //#include "Event/Particle.h"
17 
18 #include "Fitter.h"
19 
20 #include "FitParams.h"
21 #include "DecayChain.h"
22 #include "ParticleBase.h"
23 #include "Configuration.h"
24 
25 #include "RhoDoubleErr.h"
26 #include "RhoFactory.h"
27 
28 using namespace DecayTreeFitter;
29 
31 
32 extern int vtxverbose ;
33 // ==========================================================================
34 // constructor from the particle (decay head)
35 // ==========================================================================
37 ( RhoCandidate* bc ,
38  RecoTrackStateProvider* aExtrapolator ,
39  int verbosity)
40 : RhoFitterBase(bc)
41 , m_particle (bc)
42 , m_decaychain (0)
43 , m_fitparams (0)
44 , m_status (UnFitted)
45 //, m_chiSquare (-1)
46 , m_niter (-1)
47 , m_errCode (0)
48 , m_extrapolator( aExtrapolator)
49 {
50  vtxverbose = verbosity;
51  if(vtxverbose>5) std::cout<<"Fitter::Fitter() ("<<this<<") A - config"<<std::endl;
52  Configuration config(aExtrapolator) ;
53  // build the tree
54  if(vtxverbose>5) std::cout<<"Fitter::Fitter() ("<<this<<") A - tree"<<std::endl;
55  m_decaychain = new DecayChain(bc,config) ;
56  // allocate the fit parameters
57  if(vtxverbose>5) std::cout<<"Fitter::Fitter() ("<<this<<") A - Fitparams"<<std::endl;
58  m_fitparams = new FitParams(m_decaychain->dim()) ;
59  if(vtxverbose>5) std::cout<<"Fitter::Fitter() ("<<this<<") A - done"<<std::endl;
60 }
61 
62 // ==========================================================================
63 // constructor from the particle (decay head) and primary vertex
64 // ==========================================================================
66 ( RhoCandidate* bc ,
67  const RhoVector3Err& pv ,
68  RecoTrackStateProvider* aExtrapolator ,
69  int verbosity)
70 : RhoFitterBase(bc)
71 , m_particle ( bc )
72 , m_decaychain ( 0 )
73 , m_fitparams ( 0 )
74 , m_status ( UnFitted )
75 //, m_chiSquare ( -1 )
76 , m_niter ( -1 )
77 , m_errCode ( 0 )
78 //
79 , m_extrapolator ( aExtrapolator)
80 //
81 {
82  vtxverbose = verbosity;
83  if(vtxverbose>5) std::cout<<"Fitter::Fitter() ("<<this<<") D - config"<<std::endl;
84  Configuration config(aExtrapolator) ;
85  if(vtxverbose>5) std::cout<<"Fitter::Fitter() ("<<this<<") D - tree "<<std::flush;
86  m_decaychain = new DecayChain(bc,pv,config) ;
87  if(vtxverbose>5) std::cout<<"Fitter::Fitter() ("<<this<<") D - fitparams "<<std::flush;
88  m_fitparams = new FitParams(m_decaychain->dim()) ;
89  if(vtxverbose>5) std::cout<<"Fitter::Fitter() ("<<this<<") D - done"<<std::endl;
90 }
91 // ==========================================================================
92 // constructor from the particle (decay head) and beam
93 // ==========================================================================
95 ( RhoCandidate* bc ,
96  const RhoLorentzVectorErr& lv ,
97  RecoTrackStateProvider* aExtrapolator ,
98  int verbosity)
99 : RhoFitterBase(bc)
100 , m_particle ( bc )
101 , m_decaychain ( 0 )
102 , m_fitparams ( 0 )
103 , m_status ( UnFitted )
104 //, m_chiSquare ( -1 )
105 , m_niter ( -1 )
106 , m_errCode ( 0 )
107 //
108 , m_extrapolator ( aExtrapolator)
109 //
110 {
111  vtxverbose = verbosity;
112  if(vtxverbose>5) std::cout<<"Fitter::Fitter() ("<<this<<") D - config"<<std::endl;
113  Configuration config(aExtrapolator) ;
114  if(vtxverbose>5) std::cout<<"Fitter::Fitter() ("<<this<<") D - tree "<<std::flush;
115  m_decaychain = new DecayChain(bc,lv,config) ;
116  if(vtxverbose>5) std::cout<<"Fitter::Fitter() ("<<this<<") D - fitparams "<<std::flush;
117  m_fitparams = new FitParams(m_decaychain->dim()) ;
118  if(vtxverbose>5) std::cout<<"Fitter::Fitter() ("<<this<<") D - done"<<std::endl;
119 }
120 // ==========================================================================
121 // constructor from the particle (decay head), beam and primary vertex
122 // ==========================================================================
125  const RhoLorentzVectorErr& lv ,
126  const RhoVector3Err& pv ,
127  RecoTrackStateProvider* aExtrapolator ,
128  int verbosity)
129 : RhoFitterBase(bc)
130 , m_particle ( bc )
131 , m_decaychain ( 0 )
132 , m_fitparams ( 0 )
133 , m_status ( UnFitted )
134 //, m_chiSquare ( -1 )
135 , m_niter ( -1 )
136 , m_errCode ( 0 )
137 //
138 , m_extrapolator ( aExtrapolator)
139 //
140 {
141  vtxverbose = verbosity;
142  if(vtxverbose>5) std::cout<<"Fitter::Fitter() ("<<this<<") C - config"<<std::endl;
143  Configuration config(aExtrapolator) ;
144  if(vtxverbose>5) std::cout<<"Fitter::Fitter() ("<<this<<") C - tree "<<std::flush;
145  m_decaychain = new DecayChain(bc,lv,pv,config) ;
146  if(vtxverbose>5) std::cout<<"Fitter::Fitter() ("<<this<<") C - fitparams "<<std::flush;
147  m_fitparams = new FitParams(m_decaychain->dim()) ;
148  if(vtxverbose>5) std::cout<<"Fitter::Fitter() ("<<this<<") C - done"<<std::endl;
149 }
150 
151 // ==========================================================================
152 // set the track extrapolator
153 // ==========================================================================
155 { m_extrapolator = aExtrapolator; }
156 
157 
159 
161 {
162 //std::cout<<"Fitter::~Fitter() ("<<this<<") - dc "<<m_decaychain<<std::endl;
163  if(m_decaychain) delete m_decaychain ;
164 //std::cout<<"Fitter::~Fitter() ("<<this<<") - fp "<<m_fitparams<<std::endl;
165  if(m_fitparams) delete m_fitparams ;
166  if(m_extrapolator) delete m_extrapolator;
167 //std::cout<<"Fitter::~Fitter() ("<<this<<") - done"<<std::endl;
168 }
169 
170 void
171 DecayTreeFitter::Fitter::fit(int nitermax, double dChisqConv)
172 {
173 if(vtxverbose>5){std::cout<<"Fitter::fit(): - start"<<std::endl;}
174 //FIXME it's not used?
175  // m_map.clear() ;
176 
177  const int maxndiverging=3 ;
178  //const double dChisqQuit = nDof() ; // if chi2 increases by more than this --> fit failed
179 
180  // initialize
181  fChiSquare = -1 ;
182  // m_errCode.reset() ;
183  m_errCode = 0 ;
184 
185  if( m_status == UnFitted )
186  {
187  if(vtxverbose>5){std::cout<<"Fitter::fit(): - unfitted: init decaychain"<<std::endl;}
188  m_errCode = m_decaychain->init(m_fitparams).flag() ;
189  }
190  if(vtxverbose>3){std::cout<<"Fitter:fit(): decaychain init ended with errcode "<<m_errCode<<std::endl;}
191  // if(m_errCode.failure()) {
192  if ( 0 != m_errCode )
193  {
194  // the input tracks are too far apart
195  m_status = BadInput ;
196 
197  } else {
198  // reset the status flag
199  m_status = UnFitted ;
200 
201  int ndiverging=0 ;
202  bool finished = false ;
203 
204  for(m_niter=0; m_niter<nitermax && !finished; ++m_niter)
205  {
206  TVectorD prevpar = m_fitparams->par() ;
207  bool firstpass = m_niter==0 ;
208  if(vtxverbose>5){std::cout<<"Fitter::fit(): - filtering"<<std::endl;}
209  m_errCode = m_decaychain->filter(m_fitparams,firstpass).flag() ;
210  if(vtxverbose>5){std::cout<<"Fitter::fit(): - filtering done"<<std::endl;}
211  double chisq = m_fitparams->chiSquare() ;
212  double deltachisq = chisq - fChiSquare ;
213  // if chi2 increases by more than this --> fit failed
214  const double dChisqQuit = std::max(double(2*nDof()),2*fChiSquare) ;
215 
216  // if(m_errCode.failure()) {
217  if( 0 != m_errCode ) {
218  finished = true ;
219  m_status = Failed ;
220  if(vtxverbose>5){std::cout<<"Fitter::fit(): - ow, we got an error: "<<m_errCode<<std::endl;}
221  } else {
222  if( m_niter>0 ) {
223  if( fabs( deltachisq ) < dChisqConv ) {
224  fChiSquare = chisq ;
225  m_status = Success ;
226  finished = true ;
227  if(vtxverbose>5){std::cout<<"Fitter::fit(): - yay! we filtered successfully"<<std::endl;}
228  } else if( m_niter>1 && deltachisq > dChisqQuit ) {
229  m_fitparams->par() = prevpar ;
230  m_status = Failed ;
231  m_errCode = ErrCode::fastdivergingfit ;
232  finished = true ;
233  if(vtxverbose>5){std::cout<<"Fitter::fit(): - fast diverging"<<std::endl;}
234  } else if( deltachisq > 0 && ++ndiverging>=maxndiverging) {
235  m_fitparams->par() = prevpar ;
236  m_status = NonConverged ;
237  m_errCode = ErrCode::slowdivergingfit ;
238  finished = true ;
239  if(vtxverbose>5){std::cout<<"Fitter::fit(): - slow diverging"<<std::endl;}
240  } else if( deltachisq > 0 ) {
241  if(vtxverbose>5){std::cout<<"Fitter::fit(): - well, smaller steps now"<<std::endl;}
242  // make a half step and reduce stepsize
243  m_fitparams->par() += prevpar ;
244  m_fitparams->par() *= 0.5 ;
245  //if( m_niter>10) m_fitparams->scale() *= 0.5 ;
246  }
247  }
248  if ( deltachisq < 0 ) ndiverging=0 ; // start over with counting
249  if(!finished) fChiSquare = chisq ;
250  }
251  fNDegreesOfFreedom = m_fitparams->nDof();
252 
253  if(vtxverbose>=1) {
254  std::cout << "Fitter::fit(): step, stat, errcode, ndf (ncon, dim) , chiSquare, dchisq: "
255  << std::setw(3) << m_niter
256  << std::setw(3) << m_status<<"\t"
257  << std::setw(3) << m_errCode<<"\t"
258  << std::setw(3) << nDof() << " ("
259  << std::setw(3) << m_fitparams->nConstraints() << ", "
260  << std::setw(3) << m_fitparams->dim() << ") "
261  << std::setprecision(6)
262  << std::setw(12) << chisq
263  << std::setw(12) << deltachisq << std::endl ;
264  }
265 
266  if(vtxverbose>=4) {
267  std::cout << print() << std::endl;
268  std::cout << "press a key ...." << std::endl ;
269  getchar() ;
270  }
271  }
272 
273  if( m_niter == nitermax && m_status != Success )
274  { m_status = NonConverged ; }
275 
276  //m_decaychain->mother()->forceP4Sum(m_fitparams) ;
277 
278  if(m_status == Success ) {
279  if(vtxverbose>5){std::cout<<"Fitter::fit(): - test cov"<<std::endl;}
280  if( !(m_fitparams->testCov() ) ) {
281  //static int counter(10) ;
282  //if( --counter>=0)
283  std::cout << "DecayTreeFitterter::Fitter: Error matrix not positive definite. "
284  << "Changing status to failed." << std::endl ;
285  m_status = Failed ;
286  //print() ;
287  }
288  }
289  }
290  if(vtxverbose>5){std::cout<<"Fitter::fit(): - done"<<std::endl;}
291 }
292 
293 void
295 {
296  bool firstpass = m_status==UnFitted ;
297  if( firstpass ) m_decaychain->init(m_fitparams) ;
298  m_decaychain->filter(m_fitparams,firstpass) ;
299  fChiSquare = m_fitparams->chiSquare() ;
300  fNDegreesOfFreedom = m_fitparams->nDof();
301  if(vtxverbose>=1)
302  std::cout << "In Fitter::fitOneStep(): " << m_status << " " << firstpass << " " << fChiSquare << " " << fNDegreesOfFreedom << std::endl ;
303  m_status = Success ;
304 }
305 
306 std::string
308 {
309  std::ostringstream s ;
310  m_decaychain->mother()->print(m_fitparams) ;
311  s << "chisq,ndof,ncontr,niter,status,errcode: "
312  << chiSquare() << " "
313  << nDof() << " " << m_fitparams->nConstraints() << " "
314  << nIter() << " " << status() << " " << m_errCode << std::endl ;
315  return s.str() ;
316 }
317 
318 int
320  return fNDegreesOfFreedom;
321 }
322 
323 
325 {
326  // first obtain a map
327  //ParticleBase::indexmap indexmap ;
328  //m_decaychain->mother()->addToMap( indexmap ) ;
329  // add this track
330 std::cout<<"Fitter::add(RhoCandidate*) - start"<<std::endl;
331  ParticleBase* bp = m_decaychain->mother()->addDaughter(cand, Configuration()) ;
332  int offset = m_fitparams->dim() ;
333  double deltachisq(999) ;
334  if( bp ) {
335  bp->updateIndex(offset) ;
336  // reassign indices
337  //int offset(0) ;
338  //m_decaychain->mother()->updIndex(offset) ;
339  // resize the fitparams
340 std::cout<<"Fitter::add(RhoCandidate*) - resize"<<std::endl;
341  m_fitparams->resize(offset) ;
342  // initialize the added track, filter and return the delta chisq
343  bp->initPar1(m_fitparams) ;
344  bp->initPar2(m_fitparams) ;
345  bp->initCov(m_fitparams) ;
346 
347 std::cout<<"Fitter::add(RhoCandidate*) - constrains"<<std::endl;
348  ParticleBase::constraintlist constraints ;
349  bp->addToConstraintList(constraints,0) ;
350  double chisq = m_fitparams->chiSquare() ;
351  ErrCode estatus ;
352  for( ParticleBase::constraintlist::const_iterator it = constraints.begin() ;
353  it != constraints.end(); ++it)
354  estatus |= it->filter(m_fitparams) ;
355 
356  deltachisq = m_fitparams->chiSquare() - chisq ;
357  fChiSquare = m_fitparams->chiSquare() ;
358 
359 std::cout<<"Fitter::add(RhoCandidate*) - init dchain"<<std::endl;
360  // we want this somewhere else, but too much work now
361  decaychain()->initConstraintList() ;
362 
363  // print() ;
364  } else {
365  std::cout << "cannot add track to this vertex ..."
366  << m_decaychain->mother()->type() << std::endl ;
367  }
368  return deltachisq ;
369 }
370 
372 {
373  ParticleBase* pb = const_cast<ParticleBase*>(m_decaychain->locate(cand)) ;
374  ErrCode estatus ;
375  double dchisq(0) ;
376  if(pb) {
377  // filter with negative weight
378  ParticleBase::constraintlist constraints ;
379  pb->addToConstraintList(constraints,0) ;
380  double chisq = m_fitparams->chiSquare() ;
381  for( ParticleBase::constraintlist::iterator it = constraints.begin() ;
382  it != constraints.end(); ++it) {
383  it->setWeight(-1) ;
384  estatus |= it->filter(m_fitparams) ;
385  }
386  dchisq = chisq - m_fitparams->chiSquare() ;
387  // remove
388  ParticleBase* themother = const_cast<ParticleBase*>(pb->mother()) ;
389  if(themother) themother->removeDaughter(pb);
390  }
391  return dchisq ;
392 }
393 
395 {
396  m_decaychain->setMassConstraint(bc,badd) ;
397  m_status = UnFitted ;
398 }
399 
401 {
402  m_decaychain->setMassConstraint(bc,mass) ;
403  m_status = UnFitted ;
404 }
405 
406 //TODO
407 // void DecayTreeFitter::Fitter::setMassConstraint( RhoCandidateID& pid, bool add)
408 // {
409 // m_decaychain->setMassConstraint(pid,add) ;
410 // m_status = UnFitted ;
411 // }
412 // void DecayTreeFitter::Fitter::setMassConstraint( RhoCandidateID& pid, double mass)
413 // {
414 // m_decaychain->setMassConstraint(pid,mass) ;
415 // m_status = UnFitted ;
416 // }
417 
419 {
420  std::cout<<"Fitter::updateIndex() start"<<std::endl;
421  int offset=0 ;
422  m_decaychain->mother()->updateIndex(offset) ;
423  std::cout<<"Fitter::updateIndex() resize"<<std::endl;
424  m_fitparams->resize(offset) ;
425 }
426 
428 {
429  return m_decaychain->chiSquare(m_fitparams) ;
430 }
431 
432 // Gaudi::Math::ParticleParams
433 // DecayTreeFitter::Fitter::fitParams(const ParticleBase& pb) const
434 // {
435 // int posindex = pb.posIndex() ;
436 // // hack: for tracks and photons, use the production vertex
437 // if(posindex<0 && pb.mother()) posindex = pb.mother()->posIndex() ;
438 // int momindex = pb.momIndex() ;
439 // int lenindex = pb.lenIndex() ;
440 // TVector3 pos(m_fitparams->par()(posindex+0),
441 // m_fitparams->par()(posindex+1),
442 // m_fitparams->par()(posindex+2)) ;
443 // TLorentzVector p4 ;
444 // p4.SetPx( m_fitparams->par()(momindex+0) ) ;
445 // p4.SetPy( m_fitparams->par()(momindex+1) ) ;
446 // p4.SetPz( m_fitparams->par()(momindex+2) ) ;
447 // Gaudi::SymMatrix8x8 cov8 ;
448 // double decaylength = lenindex>=0 ? m_fitparams->par()(lenindex) : 0 ;
449 //
450 // if( pb.hasEnergy() ) {
451 // // if particle has energy, get full p4 from fitparams
452 // p4.SetE( m_fitparams->par()(momindex+3) ) ;
453 // int parmap[8] ;
454 // for(int i=0; i<3; ++i) parmap[i] = posindex + i ;
455 // for(int i=0; i<4; ++i) parmap[i+3] = momindex + i ;
456 // parmap[7] = lenindex ;
457 // int maxrow = lenindex >=0 ? 8 : 7 ;
458 // for(int row=0; row<maxrow; ++row)
459 // for(int col=0; col<=row; ++col)
460 // cov8(row,col) = m_fitparams->cov()(parmap[row],parmap[col]) ;
461 // } else {
462 // // if not, use the pdttable mass
463 // Gaudi::SymMatrix7x7 cov7 ;
464 // int parmap[8] ;
465 // for(int i=0; i<3; ++i) parmap[i] = posindex + i ;
466 // for(int i=0; i<3; ++i) parmap[i+3] = momindex + i ;
467 // parmap[6] = lenindex ;
468 // int maxrow = lenindex >=0 ? 7 : 6 ;
469 // for(int row=0; row<maxrow; ++row)
470 // for(int col=0; col<=row; ++col)
471 // cov7(row,col) = m_fitparams->cov()(parmap[row],parmap[col]) ;
472 //
473 // // now fill the jacobian
474 // double mass = pb.pdtMass() ;
475 // double energy2 = mass*mass ;
476 // for(int row=0; row<3; ++row) {
477 // double px = m_fitparams->par()(momindex+row) ;
478 // energy2 += px*px ;
479 // }
480 // double energy = std::sqrt(energy2) ;
481 //
482 // ROOT::Math::SMatrix<double,8,7> jacobian ;
483 // for(int col=0; col<7; ++col)
484 // jacobian(col,col) = 1;
485 // for(int col=3; col<6; ++col)
486 // jacobian(6,col) = m_fitparams->par()(parmap[col])/energy ;
487 //
488 // p4.SetE(energy) ;
489 // cov8 = ROOT::Math::Similarity(jacobian,cov7) ;
490 // }
491 // //
492 // // VtxFitParams vtxfitparams(pb.charge(),pos,p4,decaylength,cov8) ;
493 // // return vtxfitparams ;
494 // return Gaudi::Math::ParticleParams ( pos , p4 , decaylength , cov8 ) ;
495 // }
496 //
497 
498 
499 // const Gaudi::Math::ParticleParams*
500 // DecayTreeFitter::Fitter::fitParams ( RhoCandidate* cand ) const
501 // {
502 // Map::const_iterator ifind = m_map.find ( cand ) ;
503 // if ( m_map.end() != ifind ) { return &ifind->second ; } // RETURN
504 // //
505 // const ParticleBase* pb =
506 // 0 != cand ? m_decaychain->locate(*cand) : m_decaychain->cand() ;
507 // //
508 // if ( 0 == pb ) { return NULL ; } // RETURN
509 // //
510 // return &(m_map.insert( Map::value_type ( cand , fitParams ( *pb ) ) ).first->second) ;
511 // }
512 
515 {
516  // returns the decaylengthsum of two particles (use ful for e.g. B->DD)
517  RhoDoubleErr rc(0,0) ;
518  const ParticleBase* pbA = m_decaychain->locate(candA) ;
519  const ParticleBase* pbB = m_decaychain->locate(candB) ;
520  if(pbA && pbB && pbA->mother() && pbB->mother() ) {
521  int lenindexA = pbA->lenIndex() ;
522  int lenindexB = pbB->lenIndex() ;
523  if( lenindexA>=0 && lenindexB>=0) {
524  double lenA = m_fitparams->par()(lenindexA) ;
525  double lenB = m_fitparams->par()(lenindexB) ;
526  double cov =
527  m_fitparams->cov()(lenindexA, lenindexA) +
528  m_fitparams->cov()(lenindexB, lenindexB) +
529  2*m_fitparams->cov()(lenindexA, lenindexB) ;
530 
531  // rc = VtxDoubleErr(lenA+lenB,std::sqrt(cov)) ;
532  rc = RhoDoubleErr( lenA+lenB , cov) ;
533  }
534  }
535  return rc ;
536 }
537 
538 std::string
540 {
541  const ParticleBase* pb = m_decaychain->locate(cand) ;
542  return pb ? pb->name() : "Not found" ;
543 }
544 
545 // RhoCandidate
546 // DecayTreeFitter::Fitter::getFitted() const
547 // {
548 // RhoCandidate thecand = *particle() ;
549 // // const ParticleBase* pb = m_decaychain->locate(thecand) ;
550 // const ParticleBase* pb = m_decaychain->locate( *particle() ) ;
551 // if( pb ) updateCand(*pb, thecand) ;
552 // else std::cout << "Error: cannot find particle in tree" << std::endl ;
553 // return thecand ;
554 // }
555 //
556 // RhoCandidate
557 // DecayTreeFitter::Fitter::getFitted(RhoCandidate* cand) const
558 // {
559 // // clone the particle
560 // RhoCandidate thecand = cand ;
561 // // find the ParticleBase corresponding to the original particle.
562 // const ParticleBase* pb = m_decaychain->locate(cand) ;
563 // if( pb ) updateCand(*pb, thecand) ;
564 // else std::cout << "Error: cannot find particle in tree" << std::endl ;
565 // return thecand ;
566 // }
567 
568 // RhoCandidate
569 // DecayTreeFitter::Fitter::getFitted(RhoCandidate* cand) const
570 // {
571 // RhoCandidate thecand = cand ;
572 // updateCand(thecand) ;
573 // return thecand ;
574 // }
575 
576 // RhoCandidate*
577 // DecayTreeFitter::Fitter::fittedCand(RhoCandidate* /*cand*/,
578 // RhoCandidate* /*headOfTree*/) const
579 // {
580 // std::cout << "DecayTreeFitter::Fitter::fittedCand: not yet implemented" << std::endl ;
581 // return 0 ;
582 // // assigns fitted parameters to candidate in tree
583 // //RhoCandidate* acand = const_cast<RhoCandidate*>(headOfTree->cloneInTree(cand)) ;
584 // //updateCand(*acand) ;
585 // //return acand ;
586 // }
587 
588 // LHCb::DecayTree
589 // DecayTreeFitter::Fitter::getFittedTree() const
590 // {
591 // // clone the decay tree
592 // LHCb::DecayTree tree(*m_particle) ;
593 // // update the tree.
594 // // the easy version will only work once we have a proper 'isCloneOf'.
595 // // updateTree( *tree.head() ) ;
596 // for ( LHCb::DecayTree::CloneMap::const_iterator it = tree.cloneMap().begin();
597 // it != tree.cloneMap().end(); ++it ) {
598 // const ParticleBase* pb = m_decaychain->locate(*(it->first)) ;
599 // if(pb!=0) updateCand( *pb, *(it->second) ) ;
600 // }
601 // return tree ;
602 // }
603 
604 /*
605  std::string myvtxprint(RhoCandidate & cand,
606  const ComIOManip & format) {
607  std::ostringstream stream;
608  const PdtEntry * pdtEntry = cand.pdtEntry();
609  if (0 != pdtEntry){
610  stream << pdtEntry->name();
611  if(!cand.isComposite())
612  stream << "(" << cand.uid() << ")" ;
613  stream << std::ends;
614  }
615  HepString result(stream.str());
616  //delete [] stream.str(); // must take ownership here
617  return result;
618  }
619  */
620 
621 // void
622 // DecayTreeFitter::Fitter::updateCand(const ParticleBase& pb,
623 // RhoCandidate* particle) const
624 // {
625 // //FIXME HIER MACHEN
626 // // assigns fitted parameters to a candidate
627 // // VtxFitParams vtxpar = fitParams(pb) ;
628 // Gaudi::Math::ParticleParams vtxpar = fitParams(pb) ;
629 // int posindex = pb.posIndex() ;
630 // // hack: for tracks and photons, use the production vertex
631 // if(posindex<0 && pb.mother()) posindex = pb.mother()->posIndex() ;
632 // int momindex = pb.momIndex() ;
633 // int lenindex = pb.lenIndex() ;
634 // TVector3 pos(m_fitparams->par()(posindex+0),
635 // m_fitparams->par()(posindex+1),
636 // m_fitparams->par()(posindex+2)) ;
637 // TLorentzVector p4 ;
638 // p4.SetPx( m_fitparams->par()(momindex+0) ) ;
639 // p4.SetPy( m_fitparams->par()(momindex+1) ) ;
640 // p4.SetPz( m_fitparams->par()(momindex+2) ) ;
641 // Gaudi::SymMatrix8x8 cov8 ;
642 // double decaylength = lenindex>=0 ? m_fitparams->par()(lenindex) : 0 ;
643 //
644 // if( pb.hasEnergy() ) {
645 // // if particle has energy, get full p4 from fitparams
646 // p4.SetE( m_fitparams->par()(momindex+3) ) ;
647 // int parmap[8] ;
648 // for(int i=0; i<3; ++i) parmap[i] = posindex + i ;
649 // for(int i=0; i<4; ++i) parmap[i+3] = momindex + i ;
650 // parmap[7] = lenindex ;
651 // int maxrow = lenindex >=0 ? 8 : 7 ;
652 // for(int row=0; row<maxrow; ++row)
653 // for(int col=0; col<=row; ++col)
654 // cov8(row,col) = m_fitparams->cov()(parmap[row],parmap[col]) ;
655 // } else {
656 // // if not, use the pdttable mass
657 // Gaudi::SymMatrix7x7 cov7 ;
658 // int parmap[8] ;
659 // for(int i=0; i<3; ++i) parmap[i] = posindex + i ;
660 // for(int i=0; i<3; ++i) parmap[i+3] = momindex + i ;
661 // parmap[6] = lenindex ;
662 // int maxrow = lenindex >=0 ? 7 : 6 ;
663 // for(int row=0; row<maxrow; ++row)
664 // for(int col=0; col<=row; ++col)
665 // cov7(row,col) = m_fitparams->cov()(parmap[row],parmap[col]) ;
666 //
667 // // now fill the jacobian
668 // double mass = pb.pdtMass() ;
669 // double energy2 = mass*mass ;
670 // for(int row=0; row<3; ++row) {
671 // double px = m_fitparams->par()(momindex+row) ;
672 // energy2 += px*px ;
673 // }
674 // double energy = std::sqrt(energy2) ;
675 //
676 // ROOT::Math::SMatrix<double,8,7> jacobian ;
677 // for(int col=0; col<7; ++col)
678 // jacobian(col,col) = 1;
679 // for(int col=3; col<6; ++col)
680 // jacobian(6,col) = m_fitparams->par()(parmap[col])/energy ;
681 //
682 // p4.SetE(energy) ;
683 // cov8 = ROOT::Math::Similarity(jacobian,cov7) ;
684 // }
685 // //
686 // // VtxFitParams vtxfitparams(pb.charge(),pos,p4,decaylength,cov8) ;
687 // // return vtxfitparams ;
688 // return Gaudi::Math::ParticleParams ( pos , p4 , decaylength , cov8 ) ;
689 //
690 // // update everything inside the particle. don't update the vertex, for now.
691 // particle.setMomentum ( vtxpar.momentum() ) ;
692 // particle.setReferencePoint ( vtxpar.position() ) ;
693 // particle.setMomCovMatrix ( vtxpar.momCovMatrix () ) ;
694 // particle.setPosCovMatrix ( vtxpar.posCovMatrix () ) ;
695 // particle.setPosMomCovMatrix ( vtxpar.momPosCov () ) ;
696 // //
697 // // update the chi2 of global fit if this is the head of the tree
698 // if( &pb == m_decaychain->cand() )
699 // {
700 // particle.eraseInfo ( RhoCandidate::Chi2OfParticleReFitter ) ;
701 // particle.addInfo ( RhoCandidate::Chi2OfParticleReFitter ,
702 // chiSquare() ) ;
703 // }
704 // // update the vertex as well, if this is the head of the tree
705 // if( &pb == m_decaychain->cand() )
706 // {
707 // LHCb::Vertex* vertex = particle.endVertex() ;
708 // if( !vertex )
709 // {
710 // // create a new vertex
711 // vertex = new LHCb::Vertex() ;
712 // // don't add any daughters. I don't understand why we need them anyway.
713 // particle.setEndVertex( vertex ) ;
714 // }
715 // vertex -> setTechnique ( LHCb::Vertex::LastGlobal ) ;
716 // vertex -> setChi2AndDoF ( chiSquare(), nDof() ) ;
717 // vertex -> setPosition ( vtxpar.position() ) ;
718 // vertex -> setCovMatrix ( vtxpar.posCovMatrix() ) ;
719 // }
720 
721 // if( pb ==m_decaychain->cand() ) {
722 // vtx = new VtxVertex(chiSquare(),nDof(),vtxpar.pos(),vtxpar.posCov(),vtxpar.xp4Cov()) ;
723 // vtx->setStatus(FitStatus::VtxStatus(status())) ;
724 // vtx->setType(FitStatus::Geometric) ;
725 // } else {
726 // // all updated daughters are reset to unfitted, but leave the chisquare
727 // double chisq = cand.decayVtx() ? cand.decayVtx()->chiSquared() : 0 ;
728 // int ndof = cand.decayVtx() ? cand.decayVtx()->nDof() : 0 ;
729 // vtx = new VtxVertex(chisq,ndof,vtxpar.pos(),vtxpar.posCov(),vtxpar.xp4Cov()) ;
730 // vtx->setStatus(FitStatus::UnFitted) ;
731 // }
732 // }
733 // cand.setTrajectory(vtxpar,vtx) ;
734 //}
735 
737 {
738  // Update the FittedCand of the RhoCandidate
739  // This replaces the previous updateCand() as well as fitParams() functions
743  int posindex = ( pb.mother() ? pb.mother()->posIndex() : pb.posIndex() ) ;
744  if(posindex<0) posindex = pb.posIndex() ;
745  int momindex = pb.momIndex() ;
746  int lenindex = pb.lenIndex() ;
747  TVector3 pos(m_fitparams->par()(posindex+0),
748  m_fitparams->par()(posindex+1),
749  m_fitparams->par()(posindex+2)) ;
750  TLorentzVector p4 ;
751  p4.SetPx( m_fitparams->par()(momindex+0) ) ;
752  p4.SetPy( m_fitparams->par()(momindex+1) ) ;
753  p4.SetPz( m_fitparams->par()(momindex+2) ) ;
754  // double decaylength = lenindex>=0 ? m_fitparams->par()(lenindex) : 0 ; // Unused
755  TMatrixDSym cov8(8) ;
756  //
757  if( pb.hasEnergy() ) {
758  // if particle has energy, get full p4 from fitparams
759  p4.SetE( m_fitparams->par()(momindex+3) ) ;
760  int parmap[8] ;
761  for(int i=0; i<3; ++i) parmap[i] = posindex + i ;
762  for(int i=0; i<4; ++i) parmap[i+3] = momindex + i ;
763  parmap[7] = lenindex ;
764  int maxrow = lenindex >=0 ? 8 : 7 ;
765  for(int row=0; row<maxrow; ++row)
766  //for(int col=0; col<=row; ++col) //TMatrixDSym is not really symmetric :-(
767  for(int col=0; col<maxrow; ++col)
768  cov8(row,col) = m_fitparams->cov()(parmap[row],parmap[col]) ;
769  } else {
770  // if not, use the pdttable mass
771  TMatrixDSym cov7(7) ;
772  int parmap[8] ;
773  for(int i=0; i<3; ++i) parmap[i] = posindex + i ;
774  for(int i=0; i<3; ++i) parmap[i+3] = momindex + i ;
775  parmap[6] = lenindex ;
776  int maxrow = lenindex >=0 ? 7 : 6 ;
777  for(int row=0; row<maxrow; ++row)
778  //for(int col=0; col<=row; ++col)
779  for(int col=0; col<maxrow; ++col)
780  cov7(row,col) = m_fitparams->cov()(parmap[row],parmap[col]) ;
781 
782  // now fill the jacobian
783  double mass = pb.pdtMass() ;
784  double energy2 = mass*mass ;
785  for(int row=0; row<3; ++row) {
786  double px = m_fitparams->par()(momindex+row) ;
787  energy2 += px*px ;
788  }
789  double energy = std::sqrt(energy2) ;
790  TMatrixD jacobian(8,7);
791  for(int col=0; col<7; ++col)
792  jacobian(col,col) = 1;
793  for(int col=3; col<6; ++col)
794  jacobian(6,col) = m_fitparams->par()(parmap[col])/energy ;
795 
796  p4.SetE(energy) ;
797  cov8 = cov7.Similarity(jacobian);
798  }
799  // // VtxFitParams vtxfitparams(pb.charge(),pos,p4,decaylength,cov8) ;
800  RhoCandidate* fittedcand=aParticle->GetFit();
801  if(!fittedcand)
802  {
803  fittedcand = RhoFactory::Instance()->NewCandidate ( aParticle );
804  fittedcand->RemoveAssociations();
805  aParticle->SetFit(fittedcand);//ready to be modified
806  }
807  fittedcand->SetPos(pos);
808  fittedcand->SetP4(p4);
809  fittedcand->SetCov7(cov8.GetSub(0,6,0,6));
810 }
812 // int posindex = pb.posIndex() ;
813 // // hack: for tracks and photons, use the production vertex
814 // if(posindex<0 && pb.mother()) posindex = pb.mother()->posIndex() ;
815 // int momindex = pb.momIndex() ;
816 // int lenindex = pb.lenIndex() ;
817 // TVector3 pos(m_fitparams->par()(posindex+0),
818 // m_fitparams->par()(posindex+1),
819 // m_fitparams->par()(posindex+2)) ;
820 // TLorentzVector p4 ;
821 // p4.SetPx( m_fitparams->par()(momindex+0) ) ;
822 // p4.SetPy( m_fitparams->par()(momindex+1) ) ;
823 // p4.SetPz( m_fitparams->par()(momindex+2) ) ;
824 // Gaudi::SymMatrix8x8 cov8 ;
825 // double decaylength = lenindex>=0 ? m_fitparams->par()(lenindex) : 0 ;
826 //
827 // if( pb.hasEnergy() ) {
828 // // if particle has energy, get full p4 from fitparams
829 // p4.SetE( m_fitparams->par()(momindex+3) ) ;
830 // int parmap[8] ;
831 // for(int i=0; i<3; ++i) parmap[i] = posindex + i ;
832 // for(int i=0; i<4; ++i) parmap[i+3] = momindex + i ;
833 // parmap[7] = lenindex ;
834 // int maxrow = lenindex >=0 ? 8 : 7 ;
835 // for(int row=0; row<maxrow; ++row)
836 // for(int col=0; col<=row; ++col)
837 // cov8(row,col) = m_fitparams->cov()(parmap[row],parmap[col]) ;
838 // } else {
839 // // if not, use the pdttable mass
840 // Gaudi::SymMatrix7x7 cov7 ;
841 // int parmap[8] ;
842 // for(int i=0; i<3; ++i) parmap[i] = posindex + i ;
843 // for(int i=0; i<3; ++i) parmap[i+3] = momindex + i ;
844 // parmap[6] = lenindex ;
845 // int maxrow = lenindex >=0 ? 7 : 6 ;
846 // for(int row=0; row<maxrow; ++row)
847 // for(int col=0; col<=row; ++col)
848 // cov7(row,col) = m_fitparams->cov()(parmap[row],parmap[col]) ;
849 //
850 // // now fill the jacobian
851 // double mass = pb.pdtMass() ;
852 // double energy2 = mass*mass ;
853 // for(int row=0; row<3; ++row) {
854 // double px = m_fitparams->par()(momindex+row) ;
855 // energy2 += px*px ;
856 // }
857 // double energy = std::sqrt(energy2) ;
858 //
859 // ROOT::Math::SMatrix<double,8,7> jacobian ;
860 // for(int col=0; col<7; ++col)
861 // jacobian(col,col) = 1;
862 // for(int col=3; col<6; ++col)
863 // jacobian(6,col) = m_fitparams->par()(parmap[col])/energy ;
864 //
865 // p4.SetE(energy) ;
866 // cov8 = ROOT::Math::Similarity(jacobian,cov7) ;
867 // }
868 // //
869 // // VtxFitParams vtxfitparams(pb.charge(),pos,p4,decaylength,cov8) ;
870 // // return vtxfitparams ;
871 // return Gaudi::Math::ParticleParams ( pos , p4 , decaylength , cov8 ) ;
873 
874 bool
876 {
877  // assigns fitted parameters to a candidate
878  const ParticleBase* pb = m_decaychain->locate(aParticle) ;
879  if(pb) updateCand(*pb,aParticle) ;
880  //else {
881  // this error message does not make sense, because it is also
882  // triggered for daughters that were simply not refitted. we
883  // have to do something about that.
884  // VtxPrintTree printer(&myvtxprint) ;
885  // ErrMsg(error) << "cann't find candidate " << std::endl
886  // << printer.print(cand)
887  // << "in tree " << std::endl
888  // << printer.print(*_bc)
889  // << endmsg;
890  return pb != 0 ;
891 }
892 
893 bool
895 {
896  bool rc ;
897  if ( (rc = updateCand(p) ) ) {
898  // BOOST_FOREACH( RhoCandidate* daughter, p.daughters() ) {
899  // updateTree( const_cast<RhoCandidate*>(*daughter) ) ;
900  for(int iDau=0;iDau<p->NDaughters();iDau++){
901  updateTree( const_cast<RhoCandidate*>(p->Daughter(iDau)) ) ;
902  }
903  }
904  return rc ;
905 }
906 
907 // Print the result of the fit
909 { return s << print() ; }
910 
911 // Get the chisquare of a particular particle in the decay chain
913 {
914  return m_decaychain->chiSquare(aParticle, m_fitparams) ;
915 }
916 
917 // ============================================================================
918 // The END
919 // ============================================================================
int row
Definition: anaLmdDigi.C:67
TVector3 pos
bool updateTree(RhoCandidate *cand) const
update a particlular candidate in the tree
Definition: Fitter.cxx:894
std::vector< DecayTreeFitter::Constraint > constraintlist
Definition: ParticleBase.h:110
const ParticleBase * locate(RhoCandidate *bc) const
void SetPos(const TVector3 &pos)
Definition: RhoCandidate.h:235
Int_t i
Definition: run_full.C:25
friend F32vec4 sqrt(const F32vec4 &a)
Definition: P4_F32vec4.h:29
virtual void addToConstraintList(constraintlist &alist, int depth) const =0
TLorentzVector s
Definition: Pnd2DStar.C:50
int col
Definition: anaLmdDigi.C:67
virtual int momIndex() const
Definition: ParticleBase.h:71
void fit(int maxNumberOfIterations=10, double deltaChisquareConverged=0.01)
Fit the decay tree.
Definition: Fitter.cxx:171
RhoCandidate * Daughter(Int_t n)
virtual int lenIndex() const
Definition: ParticleBase.h:70
friend F32vec4 max(const F32vec4 &a, const F32vec4 &b)
Definition: P4_F32vec4.h:26
TVector3 offset(2, 0, 0)
std::string name(RhoCandidate *cand) const
Name of a particle in the decay tree.
Definition: Fitter.cxx:539
virtual ErrCode initCov(FitParams *) const
virtual bool hasEnergy() const
Definition: ParticleBase.h:74
Double_t p
Definition: anasim.C:58
virtual ErrCode initPar2(FitParams *)=0
void SetP4(Double_t mass, const TVector3 &p3)
geoFace print()
const std::string & name() const
Definition: ParticleBase.h:61
virtual int posIndex() const
Definition: ParticleBase.h:69
double add(RhoCandidate *cand)
Definition: Fitter.cxx:324
virtual void updateIndex(int &offset)
void RemoveAssociations()
void removeDaughter(const ParticleBase *pb)
double globalChiSquare() const
Definition: Fitter.cxx:427
friend F32vec4 fabs(const F32vec4 &a)
Definition: P4_F32vec4.h:47
static RhoFactory * Instance()
Definition: RhoFactory.cxx:34
void setMassConstraint(RhoCandidate *cand, bool add=true)
Add or remove a mass constraint.
Definition: Fitter.cxx:394
void setStateProvider(RecoTrackStateProvider *extrapolator)
set the track extrapolator
Definition: Fitter.cxx:154
bool updateCand(RhoCandidate *cand) const
update a particlular candidate in the tree
Definition: Fitter.cxx:875
void SetFit(RhoCandidate *b)
Definition: RhoCandidate.h:292
std::ostream & fillStream(std::ostream &s) const
Print the result of the fit.
Definition: Fitter.cxx:908
void setVerbose(int i)
set the verbosity level (for debugging only)
Definition: Fitter.cxx:158
void fitOneStep()
Fit just one step.
Definition: Fitter.cxx:294
int nDof() const
Total number of DOFs.
Definition: Fitter.cxx:319
static RhoCandidate * NewCandidate()
Definition: RhoFactory.cxx:52
Fitter()
default constructor is disabled
Int_t NDaughters() const
RhoCandidate * GetFit() const
Definition: RhoCandidate.h:293
RhoDoubleErr decayLengthSum(RhoCandidate *, RhoCandidate *) const
Definition: Fitter.cxx:514
virtual ErrCode initPar1(FitParams *)=0
double chiSquare() const
Total chisquare.
Definition: Fitter.h:124
TF1 * bp
Definition: hist-t7.C:69
int vtxverbose
double remove(RhoCandidate *cand)
Definition: Fitter.cxx:371
virtual ~Fitter()
destructor
Definition: Fitter.cxx:160
ClassImp(Fitter)
void SetCov7(const TMatrixD &cov7)
const ParticleBase * mother() const
Definition: ParticleBase.h:60
TMatrixT< double > TMatrixD
Definition: PndLmdDim.h:52
int status[10]
Definition: f_Init.h:28
Double_t energy
Definition: plot_dirc.C:15
std::string print() const
Print the result of the fit.
Definition: Fitter.cxx:307