FairRoot/PandaRoot
InternalParticle.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 #include <iomanip>
9 #include <algorithm>
10 //#include <boost/foreach.hpp>
11 
12 //#include "Event/Particle.h"
13 #include "InternalParticle.h"
14 #include "MissingParticle.h"
15 #include "FitParams.h"
16 #include "RecoTrack.h"
17 
18 #include "LineTool.h"
19 //#include "StateVector.h"
20 #include "State.h"
21 #include <assert.h>
22 #include "RhoCalculationTools.h"
23 #include "SortTool.h"
24 
25 using namespace DecayTreeFitter;
26 
27 extern int vtxverbose ;
29 
31 : ParticleBase(bc,aMother),m_lifetimeconstraint(false)
32 {
33  // BOOST_FOREACH( RhoCandidate* daughter, bc.daughters() )
34  // addDaughter(*daughter,config) ;
35  for( int iDau=0;iDau<bc->NDaughters();iDau++ ){
36  addDaughter(const_cast<RhoCandidate*>(bc->Daughter(iDau)),config) ;
37  }
38  // copy constraints
39  m_lifetimeconstraint = false ; //bc && bc->constraint(BtaConstraint::Life) ;
40  m_isconversion = daughters().size()==2 && bc->PdgCode() == 22 ;
41 }
42 
43 ErrCode
45 {
46  // This is the most complicated part of the vertexer: an
47  // initialization that always works.
48 
49  // There are two ways out: If the RhoCandidate was vertexed
50  // before, we can rely on the existing vertex (case A). If not, we
51  // need to estimate the vertex position from the daughters; that
52  // is very complicated (case B). The momentum is always
53  // initialized from the sum of the daughter four-vectors. In the
54  // end, it doesn't really matter.
55 
56  // FIXME: Currently, this scheme does not work for B->K*D0, with
57  // D0->pi0Ks, because the D0 is initialized before there is a B
58  // vertex.
59 
60  if(vtxverbose>5){std::cout<<"InternalParticle::initPar1(): - "<<std::endl;}
61  if(vtxverbose>=3)
62  std::cout << "InternalParticle::initPar1(): "
63  << particle() << " "
64  << hasPosition() << " " << posIndex() << std::endl ;
65 
66  ErrCode status ;
67  int posindex = posIndex() ;
68 
69  // logic check: we do not want to call this routine for resonances.
70  assert( hasPosition() ) ;
71  if(vtxverbose>=3)
72  std::cout << "InternalParticle::initPar1(): assertion passed"<<std::endl;
73 
74  // Start with origin
75  for(int row=0; row<3; row++) fitparams->par()(row+posindex) = 0 ;
76 
77  // Step 1: pre-initialization of all daughters
78  for(daucontainer::const_iterator it = begin() ; it != end() ; ++it)
79  status |= (*it)->initPar1(fitparams) ;
80 
81  // Step 2: initialize the vertex. if we are lucky, we had a
82  // 'resonant' daughter, and we are already done.
83  if( fitparams->par()(posindex+0)==0 && fitparams->par()(posindex+1)==0 &&
84  fitparams->par()(posindex+2)==0 ) {
85 
86  //const RhoVector3Err* vtx(0) ;
87  RhoVector3Err vtx = particle()->DecayVtx();
88  if(vtx.Mag()>0){
89  if(vtxverbose>=3) std::cout << "InternalParticle::initPar1(): A"<<std::endl;
90  // we found an existing valid vertex. that's fine as well ...
91  //TVector3 point = vtx->position() ;
92  fitparams->par(posindex+0) = vtx.x() ;
93  fitparams->par(posindex+1) = vtx.y() ;
94  fitparams->par(posindex+2) = vtx.z() ;
95  if(vtxverbose>=2)
96  std::cout << "using existing vertex: " << vtx << std::endl ;
97 
98  } else {
99  if(vtxverbose>=3) std::cout << "InternalParticle::initPar1: B"<<std::endl;
100  // Case B: the hard way ... use the daughters to estimate the
101  // vertex. First we check if there are sufficient tracks
102  // attached to this vertex. If so, estimate the poca of the
103  // two tracks with the highest momentum. This will work for
104  // the majority of the cases. If there are not sufficient
105  // tracks, add the composites and take the two with the best
106  // doca.
107 
108  // create a vector with all daughters that constitute a
109  // 'trajectory' (ie tracks, composites and daughters of
110  // resonances.)
111  daucontainer alldaughters ;
112  collectVertexDaughters( alldaughters, posindex ) ;
113  if(vtxverbose>=3) std::cout << "InternalParticle::initPar1(): number of daughters for initializing vertex: "
114  << name() << " " << alldaughters.size() << std::endl ;
115 
116  if(vtxverbose>=3) std::cout << "InternalParticle::initPar1(): B - r?"<<std::endl;
117  // select daughters that are either charged, or have an initialized vertex
118  daucontainer vtxdaughters ;
119  std::vector<RecoTrack*> trkdaughters ;
120  for(daucontainer::const_iterator it = alldaughters.begin() ;
121  it != alldaughters.end() ; ++it) {
122  if( (*it)->type()==ParticleBase::kRecoTrack ) {
123  trkdaughters.push_back( static_cast<RecoTrack*>(*it) ) ;
124  } else if( (*it)->hasPosition() && fitparams->par((*it)->posIndex()+0)!=0 ) {
125  vtxdaughters.push_back( *it ) ;
126  }
127  }
128  if(vtxverbose>=3) std::cout << "InternalParticle::initPar1(): B -daughters?"<<std::endl;
129 
130  if( trkdaughters.size() >=2 ) {
131  if(vtxverbose>=3) std::cout << "InternalParticle::initPar1(): B -a?"<<std::endl;
132  // sort in pT. not very efficient, but it works.
133  if( trkdaughters.size()>2 )
134  std::sort(trkdaughters.begin(),trkdaughters.end(),compTrkTransverseMomentum) ;
135  // now, just take the first two ...
136  RecoTrack* dau1 = trkdaughters[0] ;
137  RecoTrack* dau2 = trkdaughters[1] ;
138 
139  //FIXME [R.K.03/2017] We at Panda don't have so many hard tracks.
140  // We
141  // get the poca of the two statevectors
142  const DecayTreeFitter::State& state1 = dau1->state() ;
143  const DecayTreeFitter::State& state2 = dau2->state() ;
144  DecayTreeFitter::Line line1(state1.position(),state1.slopes()) ;
145  DecayTreeFitter::Line line2(state2.position(),state2.slopes()) ;
146  double mu1(0),mu2(0) ;
147  DecayTreeFitter::closestPointParams(line1,line2,mu1,mu2) ;
148  TVector3 p1 = line1.position(mu1) ;
149  TVector3 p2 = line2.position(mu2) ;
150  fitparams->par()(posindex+0) = 0.5*(p1.x()+p2.x()) ;
151  fitparams->par()(posindex+1) = 0.5*(p1.y()+p2.y()) ;
152  fitparams->par()(posindex+2) = 0.5*(p1.z()+p2.z()) ;
153  dau1->setFlightLength( mu1 ) ;
154  dau2->setFlightLength( mu2 ) ;
155 
156  } else if(trkdaughters.size()+vtxdaughters.size()>=2) {
157  if(vtxverbose>=3) std::cout << "InternalParticle::initPar1(): B -b?"<<std::endl;
158  std::cout << "InternalParticle::initPar1(): InternalParticle: Trying new code!"<< std::endl ;
159  // ###################
160 
161  // that's unfortunate: no enough charged tracks from this
162  // vertex. need all daughters. create trajectories and use
163  // normal TrkPoca.
164 
165  //std::vector<LHCb::StateZTraj> trajectories ;
166  std::vector<DecayTreeFitter::Line> trajectories ;
167  for(std::vector<RecoTrack*>::const_iterator it = trkdaughters.begin() ; it != trkdaughters.end() ; ++it)
168  {
169  const DecayTreeFitter::State& state1 = (*it)->state() ;
170  trajectories.push_back( DecayTreeFitter::Line(state1.position(),state1.slopes()) );
171  //trajectories.push_back( (*it)->traj() ) ;
172  }
173 
174  //trajectories.push_back(&((*it)->particle().trkAbsFit()->traj())) ;
175 
176  //std::vector<DecayTreeFitter::Line> linetrajectories ; // store trajectories of composites
177  //linetrajectories.reserve( vtxdaughters.size() ) ;
178  for(daucontainer::const_iterator it = vtxdaughters.begin() ; it != vtxdaughters.end() ; ++it)
179  {
180  //std::cout << (*it)->particle().pdtEntry()->name() << std::endl ;
181  int dauposindex = (*it)->posIndex() ;
182  int daumomindex = (*it)->momIndex() ;
183  TVector3 point(fitparams->par()(dauposindex+0), fitparams->par()(dauposindex+1), fitparams->par()(dauposindex+2)) ;
184  TVector3 direction(fitparams->par()(daumomindex+0), fitparams->par()(daumomindex+1), fitparams->par()(daumomindex+2)) ;
185  trajectories.push_back(DecayTreeFitter::Line(point,direction) ) ;
186  //linetrajectories.push_back(DecayTreeFitter::Line(point,direction,1) ) ;
187  //trajectories.push_back(&(linetrajectories.back())) ;
188  //daupoint = point ;
189  }
190 
191  // we select the two trajectories with the best poca
192  double docabest(99999);
193  for( std::vector<DecayTreeFitter::Line>::iterator it1 = trajectories.begin() ; it1 != trajectories.end(); ++it1 )
194  {
195  for( std::vector<DecayTreeFitter::Line>::iterator it2 = trajectories.begin() ; it2 != it1; ++it2 )
196  {
197  double mu1(0),mu2(0) ;
199  TVector3 p1 = (*it1).position(mu1) ;
200  TVector3 p2 = (*it2).position(mu2) ;
201  double doca = (p1-p2).Mag();
202  if(fabs(doca)<fabs(docabest))
203  {
204  fitparams->par()(posindex+0) = 0.5*(p1.x()+p2.x()) ;
205  fitparams->par()(posindex+1) = 0.5*(p1.y()+p2.y()) ;
206  fitparams->par()(posindex+2) = 0.5*(p1.z()+p2.z()) ;
207  docabest = doca ;
208  }
209  }
210  }
211  // ###########################33
212  } else if( mother() && mother()->posIndex()>=0 ) {
213  if(vtxverbose>=3) std::cout << "InternalParticle::initPar1(): B -c?"<<std::endl;
214 
215  // let's hope the mother was initialized
216  int posindexmother = mother()->posIndex() ;
217  for(int ipos=0; ipos<3; ipos++) {
218  fitparams->par()(posindex+ipos) =
219  fitparams->par()(posindexmother+ipos) ;
220  }
221  } else {
222  if(vtxverbose>=3) std::cout << "InternalParticle::initPar1(): B -d?"<<std::endl;
223  // something is wrong!
224  std::cout << "InternalParticle::initPar1(): There are not sufficient geometric constraints to fit "
225  << "this decay tree. Perhaps you should add a beam constraint. "
226  << std::endl ;
227  //<< particle().constraint(BtaConstraint::Beam)
228  // << std::endl
229  // << treeprinter.print(*bc()) << endmsg ;
230  status |= ErrCode::badsetup ;
231  }
232  if(vtxverbose>=3) std::cout << "InternalParticle::initPar1(): C ?"<<std::endl;
233  }
234  }
235  if(vtxverbose>=3)
236  std::cout << "InternalParticle::initPar1(): big code chunk passed"<<std::endl;
237 
238  // step 3: do the post initialization step of all daughters
239  if(vtxverbose>5){std::cout<<"InternalParticle::initPar1(): - calling all initPar2()"<<std::endl;}
240  for(daucontainer::const_iterator it = daughters().begin() ;
241  it != daughters().end() ; ++it)
242  (*it)->initPar2(fitparams) ;
243 
244  // step 4: initialize the momentum by adding up the daughter 4-vectors
245  initMom(fitparams) ;
246 
247  if(vtxverbose>=3)
248  std::cout << "InternalParticle::initPar1(): End of initpar: "
249  << name() << " fitpar pos("
250  << fitparams->par()(posindex+0) << ","
251  << fitparams->par()(posindex+1) << ","
252  << fitparams->par()(posindex+2) << ")" << std::endl ;
253 
254  return status ;
255 }
256 
257 ErrCode
259 {
260  if(vtxverbose>5){std::cout<<"InternalParticle::initPar2: - "<<std::endl;}
261  // FIXME: in the unfortunate case (the B-->D0K*- above) that our
262  // vertex is still the origin, we copy the mother vertex.
263  int posindex = posIndex() ;
264  if( hasPosition() && mother() && fitparams->par(posindex+0)==0 &&
265  fitparams->par(posindex+1)==0 && fitparams->par(posindex+2)==0 ) {
266  int posindexmom = mother()->posIndex() ;
267  for(int irow=0; irow<3; irow++)
268  fitparams->par(posindex+irow) = fitparams->par(posindexmom+irow) ;
269  }
270  // step 5: initialize the lifetime
271  return initTau(fitparams) ;
272 }
273 
274 ErrCode
276 {
277  int momindex = momIndex() ;
278  // reset
279  for( int irow=0; irow<4; irow++)
280  fitparams->par(momindex+irow) = 0 ;
281 
282  // now add daughter momenta
283  for(daucontainer::const_iterator it = begin() ; it != end() ; ++it) {
284  int daumomindex = (*it)->momIndex() ;
285  double e2(0) ;
286  int maxrow = (*it)->hasEnergy() && !hasMassConstraint() ? 4 : 3 ;
287  for(int irow=0; irow<maxrow; irow++) {
288  double px = fitparams->par()(daumomindex+irow) ;
289  e2 += px*px ;
290  fitparams->par(momindex+irow) += px ;
291  }
292  if(maxrow==3) {
293  double mass = (*it)->pdtMass() ;
294  fitparams->par(momindex+3) += sqrt(e2+mass*mass) ;
295  if(vtxverbose>6){std::cout<<"InternalParticle::initMom: mass="<<mass<<", p^2="<<e2<<", E="<<sqrt(e2+mass*mass)<<" from daughter momindex "<<daumomindex<<" p=("<<fitparams->par()(daumomindex+0)<<","<<fitparams->par()(daumomindex+1)<<","<<fitparams->par()(daumomindex+2)<<")"<<std::endl;}
296  }
297  }
298  return ErrCode::success ;
299 }
300 
301 ErrCode
303  Projection& p) const
304 {
305  if(vtxverbose>6){std::cout<<"InternalParticle::projectKineConstraint():"<<std::endl;}
306  // these are in fact four independent constraints. i'll filter
307  // them as one, making the code simpler at the expense of a bit of
308  // CPU.
309 
310  // first add the mother
311  int momindex = momIndex() ;
312  for(int imom=0; imom<4; imom++) {
313  p.r(imom) = fitparams->par()(momindex+imom) ;
314  p.H(imom,momindex+imom) = 1 ;
315  }
316 
317  // now add the daughters
318  for(daucontainer::const_iterator it = daughters().begin() ;
319  it != daughters().end() ; ++it) {
320  int daulenindex = (*it)->lenIndex() ;
321  int daumomindex = (*it)->momIndex() ;
322  double mass = (*it)->pdtMass() ;
323  double e2=mass*mass ;
324  int maxrow = (*it)->hasEnergy() ? 4 : 3 ;
325  for(int imom=0; imom<maxrow; ++imom) {
326  double px = fitparams->par()(daumomindex+imom) ;
327  e2 += px*px ;
328  p.r(imom) += -px ;
329  p.H(imom,daumomindex+imom) = -1 ;
330  }
331 
332  if(maxrow==3) {
333  // treat the energy for particles that are parameterized with p3
334  double energy = sqrt(e2) ;
335  p.r(3) += -energy ;
336  for(int jmom=0; jmom<3; ++jmom) {
337  double px = fitparams->par()(daumomindex+jmom) ;
338  p.H(3,daumomindex+jmom) = -px/energy ;
339  }
340  } else if(false && daulenindex>=0 && (*it)->charge()!=0) {
341 //FIXME: test and reactivate decay length!
342  double tau = fitparams->par()(daulenindex) ;
343  double lambda = bFieldOverC() * (*it)->charge() ;
344  double px0 = fitparams->par()(daumomindex) ;
345  double py0 = fitparams->par()(daumomindex+1) ;
346  double pt0 = sqrt(px0*px0+py0*py0) ;
347  const double posprecision = 1e-4 ; // 1mu
348  if( fabs(pt0*lambda*tau*tau) > posprecision ) {
349  double sinlt = sin(lambda*tau) ;
350  double coslt = cos(lambda*tau) ;
351  double px = px0*coslt - py0*sinlt ;
352  double py = py0*coslt + px0*sinlt ;
353  p.r(0) += px0 - px ;
354  p.r(1) += py0 - py ;
355  p.H(0,daumomindex+0) += 1 - coslt ;
356  p.H(0,daumomindex+1) += sinlt ;
357  p.H(0,daulenindex+0) += lambda*py ;
358  p.H(1,daumomindex+0) += -sinlt ;
359  p.H(1,daumomindex+1) += 1 - coslt ;
360  p.H(1,daulenindex+0) += -lambda*px ;
361  }
362  }
363  }
364  return ErrCode::success ;
365 }
366 
367 ErrCode
369  Projection&) const
370 {
371  if(vtxverbose>6){std::cout<<"InternalParticle::projectLifeTimeConstraint():"<<std::endl;}
372  std::cout << "Not yet implemented lifetime constraint!" << std::endl ;
373  // int lenindex = lenIndex() ;
374  // assert(lenindex>=0) ;
375  // double tau = pdtTau() ;
376  // p.r(0) = fitparams->par()(lenindex) - tau ;
377  // p.Vfast(0,0) = tau*tau ;
378  // p.H(0,lenindex) = 1 ;
379  return ErrCode::success ;
380 }
381 
382 ErrCode
384  Projection& p) const
385 {
386  if(vtxverbose>6){std::cout<<"InternalParticle::projectConversionConstraint():"<<std::endl;}
387  // only works if there are two daughters. constraint those to be parallel:
388  // p1.in(p2) - |p1||p2|=0
389  assert(m_isconversion) ;
390  const ParticleBase* dauA = daughters()[0] ;
391  const ParticleBase* dauB = daughters()[1] ;
392  int daumomindexA = dauA->momIndex() ;
393  int daumomindexB = dauB->momIndex() ;
394 
395  // first calculate the total momenta
396  double momA2(0),momB2(0) ;
397  for(int irow=0; irow<3; irow++) {
398  double pxA = fitparams->par(daumomindexA+irow) ;
399  momA2 += pxA*pxA ;
400  double pxB = fitparams->par(daumomindexB+irow) ;
401  momB2 += pxB*pxB ;
402  }
403  double momA(sqrt(momA2)), momB(sqrt(momB2)) ;
404 
405  // now fill r and H
406  p.r(1) = -momA*momB ;
407  for(int irow=0; irow<3; irow++) {
408  double pxA = fitparams->par(daumomindexA+irow) ;
409  double pxB = fitparams->par(daumomindexB+irow) ;
410  p.r(1) += pxA*pxB ;
411  p.H(1,daumomindexA+irow) = pxB - pxA/momA * momB ;
412  p.H(1,daumomindexB+irow) = pxA - pxB/momB * momA ;
413  }
414 
415  return ErrCode::success ;
416 }
417 
418 ErrCode
420  const FitParams* fitparams,
421  Projection& p) const
422 {
423  ErrCode aStatus ;
424  switch(aType) {
425  case Constraint::mass:
427  // if( m_daughters.size()==2 &&
428  // !m_daughters.front()->hasEnergy() &&
429  // !m_daughters.back()->hasEnergy() )
430  // aStatus |= projectMassConstraintTwoBody(fitparams,p) ;
432  aStatus |= projectMassConstraint(fitparams,p) ;
433  //chisq = filterMassConstraintOnDaughters(fitpar) ;
434  break ;
436  aStatus |= projectGeoConstraint(fitparams,p) ;
437  break ;
439  aStatus |= projectKineConstraint(fitparams,p) ;
440  break ;
442  aStatus |= projectLifeTimeConstraint(fitparams,p) ;
443  break ;
445  aStatus |= projectConversionConstraint(fitparams,p) ;
446  break ;
447  default:
448  aStatus |= ParticleBase::projectConstraint(aType,fitparams,p) ;
449  }
450  if(vtxverbose>6){
451  std::cout<<"InternalParticle::projectConstraint(): projection is:"<<std::endl;
452  std::cout<<"r "; p.r().Print();
453  std::cout<<"V "; p.V().Print();
454  std::cout<<"H "; RhoCalculationTools::PrintMatrix(p.H());
455  }
456  return aStatus ;
457 }
458 
460  Projection& p) const
461 {
462  if(vtxverbose>6){std::cout<<"InternalParticle::projectMassConstraintTwoBody():"<<std::endl;}
463  // we can also apply the constraint to the daughters. that may
464  // work better if the opening angle is small.
465 
466  // m^2 = ma^1 + mb^2 + 2 * (Ea*Eb - pxa*pxb - pya*pyb - pza*pzb )
467 
468  ParticleBase* d1 = daughters()[0] ;
469  ParticleBase* d2 = daughters()[1] ;
470 
471  assert(d1->hasEnergy()==false && d2->hasEnergy()==false ) ;
472 
473  double mass = pdtMass() ;
474  double m1 = d1->pdtMass() ;
475  double m2 = d2->pdtMass() ;
476 
477  int momindex1 = d1->momIndex() ;
478  int momindex2 = d2->momIndex() ;
479 
480  // initialize the value
481  double px1 = fitparams->par()(momindex1+0) ;
482  double py1 = fitparams->par()(momindex1+1) ;
483  double pz1 = fitparams->par()(momindex1+2) ;
484 
485  double px2 = fitparams->par()(momindex2+0) ;
486  double py2 = fitparams->par()(momindex2+1) ;
487  double pz2 = fitparams->par()(momindex2+2) ;
488 
489  double E1 = std::sqrt( m1*m1 + px1*px1 + py1*py1 + pz1*pz1 ) ;
490  double E2 = std::sqrt( m2*m2 + px2*px2 + py2*py2 + pz2*pz2 ) ;
491 
492  p.r(0) = m1*m1 + m2*m2 + 2 * (E1*E2 - px1*px2 - py1*py2 - pz1*pz2 ) - mass* mass ;
493 
494  // calculate the projection matrix
495  p.H(0,momindex1+0) = 2 * (E2 * px1/E1 - px2 ) ;
496  p.H(0,momindex1+1) = 2 * (E2 * py1/E1 - py2 ) ;
497  p.H(0,momindex1+2) = 2 * (E2 * pz1/E1 - pz2 ) ;
498  p.H(0,momindex2+0) = 2 * (E1 * px2/E2 - px1 ) ;
499  p.H(0,momindex2+1) = 2 * (E1 * py2/E2 - py1 ) ;
500  p.H(0,momindex2+2) = 2 * (E1 * pz2/E2 - pz1 ) ;
501 
502  // set the variance in the residual
503  double width = pdtWidth() ;
504  p.Vfast(0,0) = 4*mass*mass*width*width ;
505 
506  return ErrCode::success ;
507 }
508 
510  int depth) const
511 {
512  // first the daughters
513  for(daucontainer::const_iterator it = daughters().begin() ;
514  it != daughters().end() ; ++it)
515  (*it)->addToConstraintList(alist,depth-1) ;
516 
517  //double geoprecision = 1e-5 ; // 1mu
518  //double massprecision = 4*pdtMass()*pdtMass()*1e-5 ; // 0.01 MeV
519 
520  // the lifetime constraint
521  if(lenIndex()>=0 && m_lifetimeconstraint)
522  alist.push_back(Constraint(this,Constraint::lifetime,depth,1)) ;
523  // the kinematic constraint
524  if(momIndex()>=0)
525  alist.push_back(Constraint(this,Constraint::kinematic,depth,4)) ;
526  // the geometric constraint
527  if(mother() && lenIndex()>=0)
528  alist.push_back(Constraint(this,Constraint::geometric,depth,3,3)) ;
529  // the mass constraint. FIXME: move to ParticleBase
530  if(hasMassConstraint()) {
531  if( !m_isconversion )
532  alist.push_back(Constraint(this,Constraint::mass,depth,1,10)) ;
533  else
534  alist.push_back(Constraint(this,Constraint::conversion,depth,1,3)) ;
535  }
536 }
537 
538 
539 std::string DecayTreeFitter::InternalParticle::parname(int thisindex) const
540 {
541  int id = thisindex ;
542  // skip the lifetime parameter if there is no mother
543  if(!mother() && id>=3) ++id ;
544  return ParticleBase::parname(id) ;
545 }
546 
547 // struct printfunctor : public unary_function<ParticleBase*,void>
548 // {
549 // printfunctor(const FitParams* fitpar) : _arg(fitpar) {}
550 // void operator() (const ParticleBase* x) { x->print(_arg) ; }
551 // const FitParams* _arg ;
552 // };
553 
554 
555 // bool InternalParticle::swapMotherDaughter(FitParams* fitparams,
556 // const ParticleBase* newmother)
557 // {
558 // // routine that switches momentum vectors in a vertex, used for
559 // // reconstructing the tagging vertex.
560 // assert((newmother->type()==kBtaComposite||newmother->type()==kBtaResonance)) ;
561 // daucontainer::iterator it = std::find(m_daughters.begin(),m_daughters.end(),newmother) ;
562 // assert( it != m_daughters.end() ) ;
563 
564 // // now start substituting
565 // // 1. assign the missing particle
566 // // 2.
567 // // 3. swap the momenta around
568 
569 // int dummy = newmother->index() ;
570 // ParticleBase* missingparticle = new MissingParticle(0,this) ;
571 // missingparticle->updateIndex(dummy) ;
572 
573 // // invert tau
574 // if( newmother->lenIndex()>=0 && tauIndex()>=0) {
575 // double tau = fitparams->par()(newmother->lenIndex()) ;
576 // fitparams->par()(lenIndex()) = -tau ;
577 // }
578 
579 // // set the btacandidate
580 // setCandidate( newmother->bc() ) ;
581 
582 // // do the momentum
583 // int momindex = momIndex() ;
584 // int momindexmother = newmother->momIndex() ;
585 // int momindexmissing = missingparticle->momIndex() ;
586 
587 // int maxrow = newmother->hasEnergy() && hasEnergy() ? 4 : 3 ;
588 // double energy2(0) ;
589 // for( int row=0; row<maxrow; row++) {
590 // double pxin = fitparams->par()(momindexmother+row) ;
591 // double pxout = fitparams->par()(momindex +row) ;
592 // // the new missing particle
593 // fitparams->par()(momindexmissing+row) = 2*pxin - pxout ;
594 // fitparams->par()(momindex+row) = pxin ;
595 // energy2 += pxin*pxin ;
596 // }
597 
598 // if( newmother->hasEnergy() && hasEnergy() ) {
599 // double mass = newmother->pdtMass() ;
600 // double Ein = sqrt(energy2+mass*mass) ;
601 // double Eout = fitparams->par()(momindex+3) ;
602 // fitparams->par()(momindexmissing+3) = 2*Ein - Eout ;
603 // fitparams->par()(momindex+3) = Ein ;
604 // }
605 
606 // ParticleBase* newmothercopy = *it ;
607 // *it = missingparticle ;
608 // delete newmothercopy ;
609 
610 // return true ;
611 // }
612 
613 
614 
615 
616 
617 
618 //Double_t InternalParticle::GetPocaTwoCharged(TVector3& vertex,RhoCandidate* a, RhoCandidate* b)
619 //{
622 
623  //vertex.SetXYZ(0.,0.,0.);
624  //Double_t bField = 0.1*RhoCalculationTools::GetBz(vertex); // T, assume field in z only
625  //Double_t bc = 0.0029979246*bField;
626  //TVector3 dB(0,0,1.0);
627  //TVector3 position1 = a->GetPosition();
629  //TVector3 ap3 = a->P3();
630  //Double_t pPerp1 = ap3.Perp();
631  //TVector3 d1 = ap3;
632  //d1.SetZ(0);
633  //d1*=1.0/pPerp1;
634 
636  //Double_t rho1 = pPerp1/bc; // Radius in cm
637  //TVector3 r1=d1.Cross(dB);
638  //r1 *= -a->Charge()*rho1;
639  //TVector3 center1 = position1 - r1;
640  //center1.SetZ(0);
641 
642  //TVector3 position2 = b->GetPosition();
643 
645  //TVector3 bp3 = b->P3();
646  //Double_t pPerp2 = bp3.Perp();
647  //TVector3 d2 = bp3;
648  //d2.SetZ(0);
649  //d2*=1.0/pPerp2;
650 
652  //Double_t rho2 = pPerp2/bc; // Radius in cm
653  //TVector3 r2=d2.Cross(dB);
654  //r2 *= -b->Charge()*rho2;
655  //TVector3 center2 = position2 - r2;
656  //center2.SetZ(0);
657 
659  //TVector3 ab = center2 - center1;
660  //Double_t dab = ab.Perp();
661  //Double_t cosTheAB = ab.X()/dab;
662  //Double_t sinTheAB = ab.Y()/dab;
663 
664  //Double_t darr = dab;
665  //darr -= rho1;
666  //darr -= rho2;
667 
669  //Int_t nSolMax=1;
670  //Double_t x=0;
671  //Double_t y=0;
672  //if (darr < 0) {
674  //nSolMax=2;
676  //x = 0.5*dab + ( rho1*rho1 - rho2*rho2 )/(2*dab);
678  //Double_t y2 = (rho1+x)*(rho1-x);
679  //if (y2 > 0) { y = sqrt(y2); }
680  //} else {
682  //x = 0.5*(dab + rho1 - rho2);
683  //}
685  //TVector3 newapos[2];
686  //TVector3 newbpos[2];
687  //Int_t best=0;
688  //Double_t actualDoca=1.E8;
689  //for (Int_t ns=0; ns<nSolMax; ns++) { // loop on the solutions
691  //Double_t sign = ns ? 1.0 : -1.0;
692  //TVector3 rs1( cosTheAB*x - sinTheAB*y * sign, sinTheAB*x + cosTheAB*y * sign, 0);
693  //TVector3 rs2( rs1-ab );
694 
696  //Double_t adir=(rs1-r1).Dot(ap3)>0 ? 1.0 : -1.0;
697  //Double_t aangle=adir * r1.Angle(rs1);
699  //Double_t newaz=position1.Z() + rho1*aangle/pPerp1 * ap3.Z();
700  //newapos[ns].SetX( center1.X() + rs1.X() );
701  //newapos[ns].SetY( center1.Y() + rs1.Y() );
702  //newapos[ns].SetZ( newaz );
703 
705  //Double_t bdir=(rs2-r2).Dot(bp3)>0 ? 1.0 : -1.0;
706  //Double_t bangle=bdir * r2.Angle(rs2);
707  //Double_t newbz=position2.Z() + rho2*bangle/pPerp2 * bp3.Z();
708  //newbpos[ns].SetX( center2.X() + rs2.X()); // ==newapos[ns].X()
709  //newbpos[ns].SetY( center2.Y() + rs2.Y()); // ==newapos[ns].Y()
710  //newbpos[ns].SetZ( newbz );
711 
712  //Double_t delta = (newapos[ns]-newbpos[ns]).Mag();
713 
715  //if ( delta < actualDoca ) {
716  //best=ns;
717  //actualDoca = delta;
718  //}
719  //}
720  //vertex=0.5*(newapos[best]+newbpos[best]);
721  //return actualDoca;
722 //}
723 
724 //Double_t InternalParticle::GetPocaChargedToNeutral(TVector3& vertex,RhoCandidate* a, RhoCandidate* b)
725 //{
729 
730  //RhoCandidate* charged;
731  //RhoCandidate* neutral;
732  //if (fabs(a->Charge())<1e-6 && fabs(b->Charge())>1e-6){
733  //charged=b;
734  //neutral=a;
735  //} else if (fabs(a->Charge())>1e-6 && fabs(b->Charge())<1e-6){
736  //charged=a;
737  //neutral=b;
738  //} else return -99999.;
739 
740  //vertex.SetXYZ(0.,0.,0.);
741  //Double_t bField = 0.1*RhoCalculationTools::GetBz(vertex); // T, assume field in z only
742  //Double_t bc = 0.0029979246*bField;
743  //TVector3 dB(0,0,1.0);
744  //TVector3 position1 = charged->GetPosition();
746  //TVector3 ap3 = charged->P3();
747  //Double_t pPerp1 = ap3.Perp();
748  //TVector3 d1 = ap3;
749  //d1.SetZ(0);
750  //d1*=1.0/pPerp1;
751 
753  //Double_t rho1 = pPerp1/bc; // Radius in cm
754  //TVector3 r1=d1.Cross(dB);
755  //r1 *= -charged->Charge()*rho1;
756  //TVector3 center1 = position1 - r1;
757  //center1.SetZ(0);
758 
759  //TVector3 position2 = neutral->GetPosition();
760 
762  //TVector3 bp3 = neutral->P3();
763  //Double_t pPerp2 = bp3.Perp();
764  //TVector3 d2 = bp3;
765  //d2.SetZ(0);
766  //d2*=1.0/pPerp2; //direction of neutral
767  //TVector3 g_p = position2;
768  //g_p.SetZ(0);
769  //TVector3 c_to_g = (center1.Dot(d2) - g_p.Dot(d2))*d2 + g_p - center1; //vector pointing from center1 to the neutral
770 
771  //Int_t nSolMax=1;
772  //TVector3 newapos[2];
773  //TVector3 newbpos[2];
774  //if(c_to_g.Mag()<rho1)
775  //{
776  //newapos[0].SetZ(0.);
777  //newapos[1].SetZ(0.);
778  //nSolMax=2;
779 
780  //newapos[0] = center1 + TMath::Sqrt(rho1*rho1 - (c_to_g.Dot(c_to_g)))*d2 + c_to_g;
781  //newapos[1] = center1 - TMath::Sqrt(rho1*rho1 - (c_to_g.Dot(c_to_g)))*d2 + c_to_g;
782  //newbpos[0] = center1 + TMath::Sqrt(rho1*rho1 - (c_to_g.Dot(c_to_g)))*d2 + c_to_g;
783  //newbpos[1] = center1 - TMath::Sqrt(rho1*rho1 - (c_to_g.Dot(c_to_g)))*d2 + c_to_g;
784 
785  //TVector3 rs1 = newapos[0] - center1;
787  //Double_t adir=(rs1-r1).Dot(ap3)>0 ? 1.0 : -1.0;
788  //Double_t aangle=adir * r1.Angle(rs1);
789  //newapos[0].SetZ(position1.Z() + rho1*aangle/pPerp1 * ap3.Z());
790 
791  //rs1 = newapos[1] - center1;
793  //adir=(rs1-r1).Dot(ap3)>0 ? 1.0 : -1.0;
794  //aangle=adir * r1.Angle(rs1);
795  //newapos[1].SetZ(position1.Z() + rho1*aangle/pPerp1 * ap3.Z());
796 
798  //adir = bp3.Dot(newbpos[0] - position2)>0 ? 1.0 : -1.0;
799  //TVector3 length = newbpos[0] - g_p;
800  //newbpos[0].SetZ(position2.Z() + length.Mag() * adir * bp3.Z()/pPerp2);
801  //adir = bp3.Dot(newbpos[1] - position2)>0 ? 1.0 : -1.0;
802  //length = newbpos[1] - g_p;
803  //newbpos[1].SetZ(position2.Z() + length.Mag() * adir * bp3.Z()/pPerp2);
804  //}
805  //else
806  //{
807  //nSolMax=1;
808  //newapos[0] = 0.5*(c_to_g*(rho1/c_to_g.Mag()) + center1 + g_p);
809  //newbpos[0] = 0.5*(c_to_g*(rho1/c_to_g.Mag()) + center1 + g_p);
810 
811  //TVector3 rs1 = newapos[0] - center1;
813  //Double_t adir=(rs1-r1).Dot(ap3)>0 ? 1.0 : -1.0;
814  //Double_t aangle=adir * r1.Angle(rs1);
815  //newapos[0].SetZ(position1.Z() + rho1*aangle/pPerp1 * ap3.Z());
816 
818  //adir = bp3.Dot(newbpos[0] - position2)>0 ? 1.0 : -1.0;
819  //TVector3 length = newbpos[0] - g_p;
820  //newbpos[0].SetZ(position2.Z() + length.Mag() * adir * bp3.Z()/pPerp2);
821  //}
822 
823 
824  //Int_t best=0;
825  //Double_t actualDoca=1.E8;
826  //for(int ns=0; ns<nSolMax; ns++){
827  //Double_t delta = (newapos[ns]-newbpos[ns]).Mag();
829  //if ( delta < actualDoca ) {
830  //best=ns;
831  //actualDoca = delta;
832  //}
833  //}
834 
835  //vertex=0.5*(newapos[best]+newbpos[best]);
836  //return actualDoca;
837 //}
838 
839 //Double_t InternalParticle::GetPocaTwoNeutral(TVector3& vertex,RhoCandidate* canda, RhoCandidate* candb)
840  //{
843 
844  //vertex.SetXYZ(0.,0.,0.);
845 
846  //TVector3 av = canda->GetPosition();
847  //TVector3 ap = canda->P3();
848 
849  //TVector3 bv = candb->GetPosition();
850  //TVector3 bp = candb->P3();
851 
852  //TVector3 u = ap.Unit();
853  //TVector3 v = bp.Unit();
854  //TVector3 w = av - bv;
855  //double a = u.Mag(); //dot(u,u); // always >= 0
856  //double b = u.Dot(v); //dot(u,v);
857  //double c = v.Mag(); //dot(v,v); // always >= 0
858  //double d = u.Dot(w); //dot(u,w);
859  //double e = v.Dot(w); //dot(v,w);
860  //double D = a*c - b*b; // always >= 0
861  //double sc, tc;
862 
864  //if (D < 1e-9) { // the lines are almost parallel
865  //sc = 0.0;
866  //tc = (b>c ? d/b : e/c); // use the largest denominator
867  //}
868  //else {
869  //sc = (b*e - c*d) / D; //determination of s in g: x1 = av + s*ap
870  //tc = (a*e - b*d) / D; //determination of t in h: x2 = bv + t*bp
872  //}
873 
876  //TVector3 pocaa = av + sc*u;
877  //TVector3 pocab = bv + tc*v;
878  //vertex = 0.5*(pocaa+pocab);
879  //TVector3 diff = pocaa-pocab;
880 
881  //return diff.Mag(); // return the closest distance
882 
883  //}
884 
885 
886 
887 
int row
Definition: anaLmdDigi.C:67
virtual ErrCode initPar1(FitParams *)
Double_t p
Definition: anasim.C:58
friend F32vec4 cos(const F32vec4 &a)
Definition: P4_F32vec4.h:112
std::vector< DecayTreeFitter::Constraint > constraintlist
Definition: ParticleBase.h:110
const TVectorD & r() const
Definition: Projection.h:37
Double_t lambda(Double_t x, Double_t y, Double_t z)
Definition: drawdal.C:48
friend F32vec4 sqrt(const F32vec4 &a)
Definition: P4_F32vec4.h:29
friend F32vec4 sin(const F32vec4 &a)
Definition: P4_F32vec4.h:111
ErrCode projectConversionConstraint(const FitParams *, Projection &p) const
virtual std::string parname(int index) const
TVector3 position() const
Definition: State.h:82
virtual ErrCode projectConstraint(Constraint::Type type, const FitParams *fitparams, Projection &p) const
virtual int momIndex() const
Definition: ParticleBase.h:71
RhoCandidate * Daughter(Int_t n)
ErrCode projectLifeTimeConstraint(const FitParams *, Projection &) const
double mu1
Definition: reco_analys2.C:56
virtual bool hasEnergy() const
Definition: ParticleBase.h:74
const TMatrixD & H() const
Definition: Projection.h:28
virtual ErrCode initPar2(FitParams *)
const int particle
const TMatrixDSym & V() const
Definition: Projection.h:47
int vtxverbose
TString m2(TString pts, TString exts="e px py pz")
Definition: invexp.C:117
ErrCode projectKineConstraint(const FitParams *, Projection &) const
void setFlightLength(double flt)
Definition: RecoTrack.h:53
static void PrintMatrix(TMatrixT< double > m)
ErrCode projectMassConstraintTwoBody(const FitParams *fitparams, Projection &p) const
friend F32vec4 fabs(const F32vec4 &a)
Definition: P4_F32vec4.h:47
virtual ErrCode projectConstraint(Constraint::Type, const FitParams *, Projection &) const
virtual std::string parname(int index) const
TString name
virtual void addToConstraintList(constraintlist &alist, int depth) const
TPad * p2
Definition: hist-t7.C:117
ErrCode initMom(FitParams *fitparams) const
std::vector< ParticleBase * > daucontainer
Definition: ParticleBase.h:96
InternalParticle(RhoCandidate *bc, const ParticleBase *mother, const Configuration &config)
ParticleBase * addDaughter(RhoCandidate *, const Configuration &config)
bool compTrkTransverseMomentum(const RecoTrack *lhs, const RecoTrack *rhs)
Definition: SortTool.h:37
Int_t NDaughters() const
ClassImp(PndAnaContFact)
const daucontainer & daughters() const
Definition: ParticleBase.h:99
TPad * p1
Definition: hist-t7.C:116
bool closestPointParams(const Line &line0, const Line &line1, double &mu0, double &mu1)
Definition: LineTool.h:67
const DecayTreeFitter::State & state() const
Definition: RecoTrack.h:56
int status[10]
Definition: f_Init.h:28
TVector3 slopes() const
Definition: State.h:88
Double_t energy
Definition: plot_dirc.C:15
PndSdsMCPoint * point
Definition: anaLmdCluster.C:72
double & Vfast(int row, int col)
Definition: Projection.h:50