10 #include <analysis/variables/HelicityVariables.h>
12 #include <analysis/variables/EventVariables.h>
14 #include <analysis/dataobjects/Particle.h>
16 #include <analysis/utility/ReferenceFrame.h>
17 #include <analysis/VariableManager/Manager.h>
19 #include <framework/utilities/Conversion.h>
20 #include <framework/gearbox/Const.h>
22 #include <Math/Boost.h>
23 #include <Math/Vector4D.h>
24 using namespace ROOT::Math;
34 double cosHelicityAngleMomentum(
const Particle* part)
37 const auto& frame = ReferenceFrame::GetCurrent();
38 B2Vector3D motherBoost = frame.getMomentum(part).BoostToCM();
39 B2Vector3D motherMomentum = frame.getMomentum(part).Vect();
40 const auto& daughters = part -> getDaughters() ;
42 if (daughters.size() == 2) {
44 bool isOneConversion =
false;
46 for (
auto& idaughter : daughters) {
47 if (idaughter -> getNDaughters() == 2) {
48 if (std::abs(idaughter -> getDaughters()[0]-> getPDGCode()) == Const::electron.getPDGCode()
49 && std::abs(idaughter -> getDaughters()[1]-> getPDGCode()) == Const::electron.getPDGCode()) {
50 isOneConversion =
true;
55 if (isOneConversion) {
60 for (
auto& idaughter : daughters) {
61 if (idaughter -> getNDaughters() == 2)
continue;
62 else pGamma = frame.getMomentum(idaughter);
65 pGamma = Boost(motherBoost) * pGamma;
67 return std::cos(motherMomentum.Angle(pGamma.Vect()));
70 PxPyPzEVector pDaughter1 = frame.getMomentum(daughters[0]);
71 PxPyPzEVector pDaughter2 = frame.getMomentum(daughters[1]);
73 pDaughter1 = Boost(motherBoost) * pDaughter1;
74 pDaughter2 = Boost(motherBoost) * pDaughter2;
76 B2Vector3D p12 = (pDaughter2 - pDaughter1).Vect();
78 return std::cos(motherMomentum.Angle(p12));
81 }
else if (daughters.size() == 3) {
83 PxPyPzEVector pDaughter1 = frame.getMomentum(daughters[0]);
84 PxPyPzEVector pDaughter2 = frame.getMomentum(daughters[1]);
85 PxPyPzEVector pDaughter3 = frame.getMomentum(daughters[2]);
87 pDaughter1 = Boost(motherBoost) * pDaughter1;
88 pDaughter2 = Boost(motherBoost) * pDaughter2;
89 pDaughter3 = Boost(motherBoost) * pDaughter3;
91 B2Vector3D p12 = (pDaughter2 - pDaughter1).Vect();
92 B2Vector3D p13 = (pDaughter3 - pDaughter1).Vect();
96 return std::cos(motherMomentum.Angle(n));
98 }
else return std::numeric_limits<float>::quiet_NaN();
102 double cosHelicityAngleMomentumPi0Dalitz(
const Particle* part)
105 const auto& frame = ReferenceFrame::GetCurrent();
106 B2Vector3D motherBoost = frame.getMomentum(part).BoostToCM();
107 B2Vector3D motherMomentum = frame.getMomentum(part).Vect();
108 const auto& daughters = part -> getDaughters() ;
111 if (daughters.size() == 3) {
113 PxPyPzEVector pGamma;
115 for (
auto& idaughter : daughters) {
116 if (std::abs(idaughter -> getPDGCode()) == Const::photon.getPDGCode()) pGamma = frame.getMomentum(idaughter);
119 pGamma = Boost(motherBoost) * pGamma;
121 return std::cos(motherMomentum.Angle(pGamma.Vect()));
123 }
else return std::numeric_limits<float>::quiet_NaN();
128 double cosHelicityAngleBeamMomentum(
const Particle* mother,
const std::vector<double>& index)
130 if (index.size() != 1) {
131 B2FATAL(
"Wrong number of arguments for cosHelicityAngleIfCMSIsTheMother");
134 int idau = std::lround(index[0]);
136 const Particle* part = mother->getDaughter(idau);
138 B2FATAL(
"Couldn't find the " << idau <<
"th daughter");
141 PxPyPzEVector beam4Vector(getBeamPx(
nullptr), getBeamPy(
nullptr), getBeamPz(
nullptr), getBeamE(
nullptr));
142 PxPyPzEVector part4Vector = part->get4Vector();
143 PxPyPzEVector mother4Vector = mother->get4Vector();
145 B2Vector3D motherBoost = mother4Vector.BoostToCM();
147 beam4Vector = Boost(motherBoost) * beam4Vector;
148 part4Vector = Boost(motherBoost) * part4Vector;
150 return - part4Vector.Vect().
Dot(beam4Vector.Vect()) / part4Vector.P() / beam4Vector.P();
154 double cosHelicityAngle(
const Particle* mother,
const std::vector<double>& indices)
156 if (indices.size() != 2) {
157 B2FATAL(
"Wrong number of arguments for cosHelicityAngleIfRefFrameIsTheDaughter: two are needed.");
160 int iDau = std::lround(indices[0]);
161 int iGrandDau = std::lround(indices[1]);
163 const Particle* daughter = mother->getDaughter(iDau);
165 B2FATAL(
"Couldn't find the " << iDau <<
"th daughter.");
167 const Particle* grandDaughter = daughter->getDaughter(iGrandDau);
169 B2FATAL(
"Couldn't find the " << iGrandDau <<
"th daughter of the " << iDau <<
"th daughter.");
171 PxPyPzEVector mother4Vector = mother->get4Vector();
172 PxPyPzEVector daughter4Vector = daughter->get4Vector();
173 PxPyPzEVector grandDaughter4Vector = grandDaughter->get4Vector();
175 B2Vector3D daughterBoost = daughter4Vector.BoostToCM();
178 grandDaughter4Vector = Boost(daughterBoost) * grandDaughter4Vector;
179 mother4Vector = Boost(daughterBoost) * mother4Vector;
181 return - grandDaughter4Vector.Vect().
Dot(mother4Vector.Vect()) / grandDaughter4Vector.P() / mother4Vector.P();
184 double cosAcoplanarityAngle(
const Particle* mother,
const std::vector<double>& granddaughters)
186 if (granddaughters.size() != 2) {
187 B2FATAL(
"Wrong number of arguments for cosAcoplanarityAngleIfRefFrameIsTheMother: two are needed.");
190 if (mother->getNDaughters() != 2)
191 B2FATAL(
"cosAcoplanarityAngleIfRefFrameIsTheMother: this variable works only for two-body decays.");
193 int iGrandDau1 = std::lround(granddaughters[0]);
194 int iGrandDau2 = std::lround(granddaughters[1]);
196 const Particle* daughter1 = mother->getDaughter(0);
197 const Particle* daughter2 = mother->getDaughter(1);
199 const Particle* grandDaughter1 = daughter1->getDaughter(iGrandDau1);
201 B2FATAL(
"Couldn't find the " << iGrandDau1 <<
"th daughter of the first daughter.");
203 const Particle* grandDaughter2 = daughter2->getDaughter(iGrandDau2);
205 B2FATAL(
"Couldn't find the " << iGrandDau2 <<
"th daughter of the second daughter.");
207 PxPyPzEVector mother4Vector = mother->get4Vector();
208 PxPyPzEVector daughter4Vector1 = daughter1->get4Vector();
209 PxPyPzEVector daughter4Vector2 = daughter2->get4Vector();
210 PxPyPzEVector grandDaughter4Vector1 = grandDaughter1->get4Vector();
211 PxPyPzEVector grandDaughter4Vector2 = grandDaughter2->get4Vector();
213 B2Vector3D motherBoost = mother4Vector.BoostToCM();
214 B2Vector3D daughter1Boost = daughter4Vector1.BoostToCM();
215 B2Vector3D daughter2Boost = daughter4Vector2.BoostToCM();
218 daughter4Vector1 = Boost(motherBoost) * daughter4Vector1;
219 daughter4Vector2 = Boost(motherBoost) * daughter4Vector2;
222 grandDaughter4Vector1 = Boost(daughter1Boost) * grandDaughter4Vector1;
223 grandDaughter4Vector2 = Boost(daughter2Boost) * grandDaughter4Vector2;
226 B2Vector3D normalVector1 = daughter4Vector1.Vect().
Cross(grandDaughter4Vector1.Vect());
227 B2Vector3D normalVector2 = daughter4Vector2.Vect().
Cross(grandDaughter4Vector2.Vect());
229 return std::cos(normalVector1.Angle(normalVector2));
232 double cosHelicityAnglePrimary(
const Particle* part)
234 return part->getCosHelicity();
237 double cosHelicityAngleDaughter(
const Particle* part,
const std::vector<double>& indices)
239 if ((indices.size() == 0) || (indices.size() > 2)) {
240 B2FATAL(
"Wrong number of arguments for cosHelicityAngleDaughter: one or two are needed.");
243 int iDaughter = std::lround(indices[0]);
244 int iGrandDaughter = 0;
245 if (indices.size() == 2) {
246 iGrandDaughter = std::lround(indices[1]);
249 return part->getCosHelicityDaughter(iDaughter, iGrandDaughter);
252 double acoplanarityAngle(
const Particle* part)
254 return part->getAcoplanarity();
258 VARIABLE_GROUP(
"Helicity variables");
260 REGISTER_VARIABLE(
"cosHelicityAngleMomentum", cosHelicityAngleMomentum, R
"DOC(
261 If the given particle has two daughters: cosine of the angle between the line defined by the momentum difference of the two daughters
262 in the frame of the given particle (mother)
263 and the momentum of the given particle in the lab frame.
265 If the given particle has three daughters: cosine of the angle between the normal vector of the plane defined by
266 the momenta of the three daughters in the frame of the given particle (mother)
267 and the momentum of the given particle in the lab frame.
269 Otherwise, it returns 0.)DOC");
271 REGISTER_VARIABLE("cosHelicityAngleMomentumPi0Dalitz", cosHelicityAngleMomentumPi0Dalitz, R
"DOC(
272 To be used for the decay :math:`\pi^0 \to e^+ e^- \gamma`:
273 cosine of the angle between the momentum of the gamma in the frame of the given particle (mother)
274 and the momentum of the given particle in the lab frame.
276 Otherwise, it returns 0.)DOC");
278 REGISTER_VARIABLE("cosHelicityAngleBeamMomentum(i)", cosHelicityAngleBeamMomentum, R
"DOC(
279 Cosine of the helicity angle of the :math:`i`-th daughter of the particle provided,
280 assuming that the mother of the provided particle corresponds to the centre-of-mass system, whose parameters are
281 automatically loaded by the function, given the accelerator's conditions.)DOC");
283 REGISTER_VARIABLE("cosHelicityAngle(i, j)", cosHelicityAngle, R
"DOC(
284 Cosine of the helicity angle between the momentum of the provided particle and the momentum of the selected granddaughter
285 in the reference frame of the selected daughter (:math:`\theta_1` and :math:`\theta_2` in the
286 `PDG <https://journals.aps.org/prd/abstract/10.1103/PhysRevD.98.030001>`_ 2018, p. 722).
288 This variable needs two integer arguments: the first one, ``i``, is the index of the daughter and the second one, ``j`` is the index of the granddaughter.
290 For example, in the decay :math:`B^0 \to \left(J/\psi \to \mu^+ \mu^-\right) \left(K^{*0} \to K^+ \pi^-\right)`,
291 if the provided particle is :math:`B^0` and the selected indices are (0, 0),
292 the variable will return the angle between the momentum of the :math:`B^0` and the momentum of the :math:`\mu^+`,
293 both momenta in the rest frame of the :math:`J/\psi`.
295 This variable is needed for angular analyses of :math:`B`-meson decays into two vector particles.)DOC");
297 REGISTER_VARIABLE("cosAcoplanarityAngle(i, j)", cosAcoplanarityAngle, R
"DOC(
298 Cosine of the acoplanarity angle (:math:`\Phi` in the `PDG Polarization Review <http://pdg.lbl.gov/2019/reviews/rpp2018-rev-b-decays-polarization.pdf>`_).
299 Given a two-body decay, the acoplanarity angle is defined as
300 the angle between the two decay planes in the reference frame of the mother.
302 We calculate the acoplanarity angle as the angle between the two
303 normal vectors of the decay planes. Each normal vector is the cross product of the momentum of one daughter (in the frame of the mother) and the
304 momentum of one of the granddaughters (in the reference frame of the daughter).
306 This variable needs two integer arguments: the first one, ``i`` is the index of the first granddaughter, and the second one, ``j`` the index of the
307 second granddaughter.
309 For example, in the decay :math:`B^0 \to \left(J/\psi \to \mu^+ \mu^-\right) \left(K^{*0} \to K^+ \pi^-\right)`, if the provided particle is :math:`B^0` and the selected indices are (0, 0),
310 the variable will return the acoplanarity using the :math:`\mu^+` and the :math:`K^+` granddaughters.)DOC");
312 REGISTER_VARIABLE("cosHelicityAnglePrimary", cosHelicityAnglePrimary, R
"DOC(
313 Cosine of the helicity angle (see``Particle::getCosHelicity``) assuming the center of mass system as mother rest frame.
314 See `PDG Polarization Review <http://pdg.lbl.gov/2019/reviews/rpp2018-rev-b-decays-polarization.pdf>`_ for the definition of the helicity angle.)DOC");
316 REGISTER_VARIABLE("cosHelicityAngleDaughter(i [, j] )", cosHelicityAngleDaughter, R
"DOC(
317 Cosine of the helicity angle of the i-th daughter (see ``Particle::getCosHelicityDaughter``).
318 The optional second argument is the index of the granddaughter that defines the angle, default is 0.
320 For example, in the decay: :math:`B^0 \to \left(J/\psi \to \mu^+ \mu^-\right) \left(K^{*0} \to K^+ \pi^-\right)`, if the provided particle is :math:`B^0` and the selected index is 0,
321 the variable will return the helicity angle of the :math:`\mu^+`.
322 If the selected index is 1 the variable will return the helicity angle of the :math:`K^+` (defined via the rest frame of the :math:`K^{*0}`).
323 In rare cases if one wanted the helicity angle of the second granddaughter, indices 1,1 would return the helicity angle of the :math:`\pi^-`).
325 See `PDG Polarization Review <http://pdg.lbl.gov/2019/reviews/rpp2018-rev-b-decays-polarization.pdf>`_ for the definition of the helicity angle.)DOC");
327 REGISTER_VARIABLE("acoplanarityAngle", acoplanarityAngle, R
"DOC(
328 Acoplanarity angle (see ``Particle::getAcoplanarity``) assuming a two body decay of the particle and its daughters.
329 See `PDG Polarization Review <http://pdg.lbl.gov/2019/reviews/rpp2018-rev-b-decays-polarization.pdf>`_ for the definition of the acoplanarity angle.)DOC",
B2Vector3< DataType > Cross(const B2Vector3< DataType > &p) const
Cross product.
DataType Dot(const B2Vector3< DataType > &p) const
Scalar product.
B2Vector3< double > B2Vector3D
typedef for common usage with double
Abstract base class for different kinds of events.