FairRoot/PandaRoot
RhoFindOmittedParticle.cxx
Go to the documentation of this file.
1 //--------------------------------------------------------------------------
2 // File and Version Information:
3 // $Id: RhoFindOmittedParticle.cxx,v 1.3 2002-02-01 23:00:13 marcel Exp $
4 //
5 // Description:
6 // Class RhoFindOmittedParticle.
7 // Given resonance (Y(4S)) momentum, B0 momentum, and
8 // K0L mass at creation, this object then finds the best
9 // candidate for the K0L 4-momentum given the 4-momentum
10 // of the J/psi and the direction of the neutral cluster.
11 //
12 // Because this is a general utility class, B0 is labeled Child,
13 // Y(4S) is labeled Reson (for Resonance), J/psi is labeled Obs
14 // (for Observed), and K0L is labeled Sought (for the calculated
15 // values) or Seen (for the actual IFR/EMC cluster).
16 //
17 // Constructor takes CM 4-momentum, Child mass, and Sought mass.
18 //
19 // fitToSeen() calls makeCone(), then closestFit().
20 //
21 // makeCone() finds the possible Sought 4-momenta given the Observed
22 // momentum.
23 //
24 // closestFit() finds the best fit between the cone of possibilities
25 // and the Seen neutral cluster.
26 //
27 // secondVector() returns the second momentum found by closestFit()
28 // but rejected as an inferior fit, for diagnostic purposes.
29 //
30 // If there is demand, a function may be added to extract the
31 // parameters of the cone describing possible Sought momenta;
32 // makeCone() and closestFit() would then be made public;
33 // or perhaps a subclass could implement this functionality.
34 //
35 // Note: this class by default currently only works in
36 // coordinate systems with the boost along the z-axis.
37 // Setting zBoostApprox to false overrides this.
38 //
39 // Note: this class currently assumes (as is the case for B0->J/psi KL)
40 // that in the resonance CM (Y(4S)) frame, the 3-momentum of the
41 // observed (J/psi) particle is much larger than the child (B0)
42 // 3-momentum, insuring that the CM angle between the observed and
43 // sought (KL) is greater than pi/2. (In the language of this class,
44 // openCos>0, since we use the opposite of the observed momentum).
45 //
46 // Environment:
47 // Software developed for the BaBar Detector at the SLAC B-Factory.
48 //
49 // Author List:
50 // Adam Breon Original Author
51 //
52 // Copyright Information:
53 // Copyright (C) 1997-1999 Lawrence Berkeley Laboratory
54 //
55 // ROOT Version by Marcel Kunze, RUB
56 // Ralf Kliemt, HIM/GSI Feb.2013 (Cleanup & Restructuring)
57 //------------------------------------------------------------------------
58 
60 #include <assert.h>
61 #include <math.h>
62 #include "TLorentzVector.h"
63 #include "TVector3.h"
64 #include "TBuffer.h"
65 
67 
68 TBuffer& operator>> ( TBuffer& buf, RhoFindOmittedParticle *&obj )
69 {
70  obj = ( RhoFindOmittedParticle* ) buf.ReadObject ( RhoFindOmittedParticle::Class() );
71  return buf;
72 }
73 
74 #include <iostream>
75 using namespace std;
76 
77 //----------------
78 // Constructors --
79 //----------------
80 
81 /*
82  * Constructor; sets mass of the child of the resonance and the
83  * particle to be found.
84  * For now, uses ErrMsg calls to ensure arguments
85  * make sense.
86  */
88  const TLorentzVector& ip4Reson, // set Y(4S) p4.
89  const double imChild, // B0 mass.
90  const double imSought, // K mass
91  const Bool_t izBoostApprox ) // boost in z approx?
92 //: p4Reson(ip4Reson)
93 //: mChild(fabs(imChild))
94  : mSought2 ( imSought* imSought )
95  , zBoostApprox ( izBoostApprox )
96  , p4ObsCache ( 0.0,0.0,0.0,-1.0 ) // Non-physical initial value
97 {
98  if ( imChild == 0.0 ) {
99  cerr << "RhoFindOmittedParticle constructed with mChild=0" << endl;
100  }
101 
102  if ( mSought2 == 0.0 ) {
103  cerr << "RhoFindOmittedParticle constructed with mSought=0" << endl;
104  }
105 
106  // Figure out the boost vectors to and from the center of mass
107 
108  //p4Reson = ip4Reson;
109  beta = -ip4Reson.BoostVector();
110 
111  // Figure out the decay energies, gamma factors, beta factors.
112  // Assume that resonance decays to two "child" particles (e.g. B + Bbar)
113 
114  cmEChild = ip4Reson.Mag() / 2;
115 
116  if ( cmEChild < fabs ( imChild ) ) {
117  cerr << "RhoFindOmittedParticle: mChild too large for decay" << endl;
118  }
119 
120  // The square of the three-momentum of the child (B0).
121  cmpChild2 = cmEChild*cmEChild - imChild*imChild;
122 
123 }
124 
125 //--------------
126 // Destructor --
127 //--------------
128 
129 // The destructor should be limited to undoing the work of the constructor
131 {
132 }
133 
134 
135 //--------------------
136 // Member Functions --
137 //--------------------
138 
139 /*
140  * Given the 4-momentum of the observed decay products, and assuming
141  * that p3Seen indicates a neutral cluster from the omitted particle,
142  * returns the most likely lab-frame 4-momentum with the sought mass
143  * specified in the constructor. Returns the zero vector if no such
144  * consistent vector can be found.
145  */
146 
147 TLorentzVector
148 RhoFindOmittedParticle::FitToSeen ( const TLorentzVector& p4Obs,
149  const TVector3& p3Seen )
150 {
151  if ( p4Obs != p4ObsCache ) {
152  this->MakeCone ( p4Obs );
153  p4ObsCache = p4Obs;
154  }
155  return this->ClosestFit ( p3Seen );
156 }
157 
158 
159 /*
160  * Given the already known resonance p4, figures out the cone
161  * of possible values for the sought particle in the center of
162  * mass.
163  */
164 
165 void
166 RhoFindOmittedParticle::MakeCone ( const TLorentzVector& p4Obs )
167 {
168  // Get the observed mass, figure out the decay momentum of the
169  // child -> sought + observed.
170 
171  // Square of mass of observed particle.
172  //const double mObs2 = p4Obs.Mag2();
173 
174  /* This was an old, labor-intensive way of calculating the
175  decay momentum. Using conservation of energy is much simpler to
176  understand and faster to compute.
177  // The following is a solution of sqrt(pDecay*pDecay + mSought*mSought)
178  // + sqrt(pDecay*pDecay + mObs*mObs) == mChild
179  double pDecay;
180  {
181  double temp;
182 
183  temp = (mObs2 - mSought*mSought) / mChild;
184  temp *= temp;
185  temp += mChild*mChild - 2 * (mObs2 + mSought*mSought);
186 
187  pDecay = 0.5 * sqrt(temp);
188  }
189 
190  //const double EObsDecay = sqrt(mObs2 + pDecay*pDecay);
191  //const double ESoughtDecay = sqrt(mSought*mSought + pDecay*pDecay);
192  */
193 
194 
195  // Boost vectors into the CM frame; extract vital statistics.
196 
197  TLorentzVector cmp4Obs ( p4Obs );
198  cmp4Obs.Boost ( beta );
199 
200  //const double cmEObs = cmp4Obs.t();
201  const double cmpObs2 = TVector3 ( cmp4Obs.X(),cmp4Obs.Y(),cmp4Obs.Z() ).Mag2();
202 
203  cmESought = cmEChild - cmp4Obs.T();
204  double cmESought2 = cmESought*cmESought;
205  if ( cmESought2 > mSought2 ) {
206  cmpSought2 = cmESought2 - mSought2;
207  } else {
208  cmpSought2 = 0.0;
209  }
210 
211 
212 
213  /*
214  * Because we know the lengths of the 3 momentum 3-vectors, we can
215  * get the angles using the law of cosines.
216  * abs(openCos) > 1 signifies an error, causing closestFit to return
217  * a zero vector, signifying an error.
218  */
219 
220  const double cmpSought = sqrt ( cmpSought2 );
221 
222  if ( cmpSought != 0 )
223  openCos =
224  ( cmpObs2 + cmpSought2 - cmpChild2 ) /
225  ( 2 * sqrt ( cmpObs2 ) * cmpSought );
226  else {
227  openCos = 2; // Error condition.
228  }
229 
230  cmAxis = -TVector3 ( cmp4Obs.X(),cmp4Obs.Y(),cmp4Obs.Z() ).Unit() * openCos * cmpSought;
231 
232 }
233 
234 
235 /*
236  * Given the cone of possible values for the sought momentum in the
237  * center of mass, takes that p3Seen points to a neutral cluster
238  * due to the sought particle in the lab frame. Assuming that the
239  * boost is solely along the z-axis, finds the intersection of the
240  * cone in the center of mass with the plane defined by the azimuthal
241  * angle of p3Seen. If there is no intersection, returns 0. Otherwise,
242  * boosts both intersections back to the lab frame. It returns the one
243  * at the smallest angular separation from p3Seen.
244  */
245 
246 TLorentzVector
247 RhoFindOmittedParticle::ClosestFit ( const TVector3& p3Seen )
248 {
249  // Take care of these now to save clock cycles.
250  if ( fabs ( openCos ) > 1.0 ) {
251  return TLorentzVector ( 0.0,0.0,0.0,0.0 ); // Error condition.
252  }
253 
254  TLorentzVector cmp4Sought[2]; // Two intersection points...
255 
256  // Set up local coordinate system:
257  // z = normal z.
258  // x-z plane contains p3Seen. Since we only keep phi information,
259  // we needn't bother boosting.
260  // I'm doing more stuff by hand than in previous versions in order
261  // to speed things up.
262  double cmCosPlaneAxis2; // Squared cosine between the plane and axis.
263  {
264  // Original, most abstract method:
265  //const TVector3 cmZ(0.0, 0.0, 1.0);
266  //const TVector3 cmX = (p3Seen - p3Seen.dot(cmZ) * cmZ).unit();
267  //const TVector3 cmY = cmZ.cross(cmX);
268 
269  // Slightly faster method:
270  //const TVector3 cmX = TVector3(p3Seen.x(), p3Seen.y(), 0.0).unit();
271  //const TVector3 cmY = TVector3(-cmX.y(), cmX.x(), 0.0);
272 
273  TVector3 cmY;
274  // Fastest method:
275  if ( zBoostApprox ) {
276  cmY = TVector3 ( -p3Seen.Y(), p3Seen.X(), 0.0 ).Unit();
277  } else {
278  cmY = beta.Cross ( p3Seen ).Unit();
279  }
280 
281  const TVector3 unitAxis = cmAxis.Unit();
282 
283  // Projection of unit vector of axis into x-z plane.
284 
285  // Project unitAxis into the xz plane.
286  const TVector3 unitProj = unitAxis - unitAxis.Dot ( cmY ) * cmY;
287  // While we know cmY.z() == 0, doing it by hand would make the
288  // code too baroque for not a great speed advantage.
289 
290  // Square of cosine of angle between plane and axis:
291  cmCosPlaneAxis2 = unitProj.Mag2();
292 
293 
294  if ( cmCosPlaneAxis2 < openCos*openCos ) {
295  return TLorentzVector ( 0.0,0.0,0.0,0.0 ); // Error condition.
296  }
297 
298  // Projection of full axis into x-z plane.
299  // Actually, it's longer; touches the base of the cone.
300  // cmAxis is projection of unitProj, hence 1/cosine.
301 
302  const TVector3 axisProj =
303  ( cmAxis.Mag() / ( cmCosPlaneAxis2 ) ) * unitProj;
304 
305  // vector difference between axisProj and the true
306  // vector, which could lie to either side.
307 
308  //const TVector3 difference = cmAxis.mag() *
309  //sqrt(1/(openCos*openCos) - 1/(cmCosPlaneAxis2)) *
310  //unitProj.cross(cmY).unit();
311 
312  const TVector3 difference =
313  sqrt ( cmpSought2 - axisProj.Mag2() ) *
314  unitProj.Cross ( cmY ).Unit();
315 
316  cmp4Sought[0] = TLorentzVector ( axisProj + difference, cmESought );
317  cmp4Sought[1] = TLorentzVector ( axisProj - difference, cmESought );
318  }
319 
320 
321  // Boost the results back into the lab frame.
322  // Return whichever one is closer in angle to the seen vector.
323 
324  cmp4Sought[0].Boost ( -beta );
325  cmp4Sought[1].Boost ( -beta );
326 
327  if ( TVector3 ( cmp4Sought[0].X(),cmp4Sought[0].Y(),cmp4Sought[0].Z() ).Unit().Dot ( p3Seen ) >
328  TVector3 ( cmp4Sought[1].X(),cmp4Sought[1].Y(),cmp4Sought[1].Z() ).Unit().Dot ( p3Seen ) ) {
329  secondChoice = cmp4Sought[1];
330  return cmp4Sought[0];
331  } else {
332  secondChoice = cmp4Sought[0];
333  return cmp4Sought[1];
334  }
335 }
336 
337 
338 /*
339  * Returns the worse-fit vector found in closestFit() and saved
340  * in secondChoice.
341  */
342 
343 TLorentzVector
345 {
346  return secondChoice;
347 }
TVector3 beta
The other vector, stored.
friend F32vec4 sqrt(const F32vec4 &a)
Definition: P4_F32vec4.h:29
double cmESought
cos of opening angle.
TLorentzVector p4ObsCache
energy, squared 3-momentum of Child.
TLorentzVector SecondVector() const
ClassImp(RhoFindOmittedParticle) TBuffer &operator>>(TBuffer &buf
TVector3 cmAxis
From lab to CM (-beta CM to lab)
TLorentzVector FitToSeen(const TLorentzVector &p4Obs, const TVector3 &p3Seen)
double Y
Definition: anaLmdDigi.C:68
double openCos
Axis of CM cone.
RhoFindOmittedParticle(const TLorentzVector &ip4Reson, const double imChild, const double imSought, const Bool_t izBoostApprox=kTRUE)
friend F32vec4 fabs(const F32vec4 &a)
Definition: P4_F32vec4.h:47
void MakeCone(const TLorentzVector &p4Obs)
double X
Definition: anaLmdDigi.C:68
float cmEChild
Flag: do we approximate boost in.
Bool_t zBoostApprox
squared mass of Sought
double Z
Definition: anaLmdDigi.C:68
double cmpSought2
CM energy of sought particle.
TLorentzVector ClosestFit(const TVector3 &p3Seen)
RhoFindOmittedParticle *& obj
return buf