10 #include <analysis/variables/HelicityVariables.h>
11 #include <analysis/variables/EventVariables.h>
13 #include <analysis/dataobjects/Particle.h>
15 #include <analysis/utility/ReferenceFrame.h>
17 #include <framework/utilities/Conversion.h>
18 #include <framework/gearbox/Const.h>
20 #include <TLorentzVector.h>
31 double cosHelicityAngleMomentum(
const Particle* part)
35 TVector3 motherBoost = - frame.getMomentum(part).BoostVector();
36 TVector3 motherMomentum = frame.getMomentum(part).Vect();
37 const auto& daughters = part -> getDaughters() ;
39 if (daughters.size() == 2) {
41 bool isOneConversion =
false;
43 for (
auto& idaughter : daughters) {
44 if (idaughter -> getNDaughters() == 2) {
45 if (std::abs(idaughter -> getDaughters()[0]-> getPDGCode()) ==
Const::electron.getPDGCode()
46 && std::abs(idaughter -> getDaughters()[1]-> getPDGCode()) ==
Const::electron.getPDGCode()) {
47 isOneConversion =
true;
52 if (isOneConversion) {
55 TLorentzVector pGamma;
57 for (
auto& idaughter : daughters) {
58 if (idaughter -> getNDaughters() == 2)
continue;
59 else pGamma = frame.getMomentum(idaughter);
62 pGamma.Boost(motherBoost);
64 return std::cos(motherMomentum.Angle(pGamma.Vect()));
67 TLorentzVector pDaughter1 = frame.getMomentum(daughters[0]);
68 TLorentzVector pDaughter2 = frame.getMomentum(daughters[1]);
70 pDaughter1.Boost(motherBoost);
71 pDaughter2.Boost(motherBoost);
73 TVector3 p12 = (pDaughter2 - pDaughter1).Vect();
75 return std::cos(motherMomentum.Angle(p12));
78 }
else if (daughters.size() == 3) {
80 TLorentzVector pDaughter1 = frame.getMomentum(daughters[0]);
81 TLorentzVector pDaughter2 = frame.getMomentum(daughters[1]);
82 TLorentzVector pDaughter3 = frame.getMomentum(daughters[2]);
84 pDaughter1.Boost(motherBoost);
85 pDaughter2.Boost(motherBoost);
86 pDaughter3.Boost(motherBoost);
88 TVector3 p12 = (pDaughter2 - pDaughter1).Vect();
89 TVector3 p13 = (pDaughter3 - pDaughter1).Vect();
91 TVector3 n = p12.Cross(p13);
93 return std::cos(motherMomentum.Angle(n));
95 }
else return std::numeric_limits<float>::quiet_NaN();
99 double cosHelicityAngleMomentumPi0Dalitz(
const Particle* part)
103 TVector3 motherBoost = - frame.getMomentum(part).BoostVector();
104 TVector3 motherMomentum = frame.getMomentum(part).Vect();
105 const auto& daughters = part -> getDaughters() ;
108 if (daughters.size() == 3) {
110 TLorentzVector pGamma;
112 for (
auto& idaughter : daughters) {
113 if (std::abs(idaughter -> getPDGCode()) ==
Const::photon.getPDGCode()) pGamma = frame.getMomentum(idaughter);
116 pGamma.Boost(motherBoost);
118 return std::cos(motherMomentum.Angle(pGamma.Vect()));
120 }
else return std::numeric_limits<float>::quiet_NaN();
128 if (arguments.size() == 1) {
130 idau = Belle2::convertString<int>(arguments[0]);
131 }
catch (std::invalid_argument&) {
132 B2FATAL(
"The argument of cosHelicityAngleWrtCMSFrame must be an integer!");
135 B2FATAL(
"Wrong number of arguments for cosHelicityAngleIfCMSIsTheMother");
137 auto func = [idau](
const Particle * mother) ->
double {
138 const Particle* part = mother->getDaughter(idau);
141 B2FATAL(
"Couldn't find the " << idau <<
"th daughter");
144 TLorentzVector beam4Vector(getBeamPx(
nullptr), getBeamPy(
nullptr), getBeamPz(
nullptr), getBeamE(
nullptr));
145 TLorentzVector part4Vector = part->get4Vector();
146 TLorentzVector mother4Vector = mother->get4Vector();
148 TVector3 motherBoost = -(mother4Vector.BoostVector());
150 beam4Vector.Boost(motherBoost);
151 part4Vector.Boost(motherBoost);
153 return - part4Vector.Vect().Dot(beam4Vector.Vect()) / part4Vector.Vect().Mag() / beam4Vector.Vect().Mag();
163 if (arguments.size() == 2) {
165 iDau = Belle2::convertString<int>(arguments[0]);
166 iGrandDau = Belle2::convertString<int>(arguments[1]);
167 }
catch (std::invalid_argument&) {
168 B2FATAL(
"The two arguments of cosHelicityAngleIfRefFrameIsTheDaughter must be integers!");
171 B2FATAL(
"Wrong number of arguments for cosHelicityAngleIfRefFrameIsTheDaughter: two are needed.");
173 auto func = [iDau, iGrandDau](
const Particle * mother) ->
double {
175 const Particle* daughter = mother->getDaughter(iDau);
177 B2FATAL(
"Couldn't find the " << iDau <<
"th daughter.");
179 const Particle* grandDaughter = daughter->getDaughter(iGrandDau);
181 B2FATAL(
"Couldn't find the " << iGrandDau <<
"th daughter of the " << iDau <<
"th daughter.");
184 TLorentzVector mother4Vector = mother->get4Vector();
185 TLorentzVector daughter4Vector = daughter->get4Vector();
186 TLorentzVector grandDaughter4Vector = grandDaughter->get4Vector();
188 TVector3 daughterBoost = -(daughter4Vector.BoostVector());
191 grandDaughter4Vector.Boost(daughterBoost);
192 mother4Vector.Boost(daughterBoost);
194 return - grandDaughter4Vector.Vect().Dot(mother4Vector.Vect()) / grandDaughter4Vector.Vect().Mag() / mother4Vector.Vect().Mag();
204 if (arguments.size() == 2) {
206 iGrandDau1 = Belle2::convertString<int>(arguments[0]);
207 iGrandDau2 = Belle2::convertString<int>(arguments[1]);
208 }
catch (std::invalid_argument&) {
209 B2FATAL(
"The two arguments of cosAcoplanarityAngleIfRefFrameIsTheMother must be integers!");
212 B2FATAL(
"Wrong number of arguments for cosAcoplanarityAngleIfRefFrameIsTheMother: two are needed.");
214 auto func = [iGrandDau1, iGrandDau2](
const Particle * mother) ->
double {
216 if (mother->getNDaughters() != 2)
217 B2FATAL(
"cosAcoplanarityAngleIfRefFrameIsTheMother: this variable works only for two-body decays.");
219 const Particle* daughter1 = mother-> getDaughter(0);
220 const Particle* daughter2 = mother-> getDaughter(1);
222 const Particle* grandDaughter1 = daughter1 -> getDaughter(iGrandDau1);
224 B2FATAL(
"Couldn't find the " << iGrandDau1 <<
"th daughter of the first daughter.");
226 const Particle* grandDaughter2 = daughter2 -> getDaughter(iGrandDau2);
228 B2FATAL(
"Couldn't find the " << iGrandDau2 <<
"th daughter of the second daughter.");
230 TLorentzVector mother4Vector = mother->get4Vector();
231 TLorentzVector daughter4Vector1 = daughter1->get4Vector();
232 TLorentzVector daughter4Vector2 = daughter2->get4Vector();
233 TLorentzVector grandDaughter4Vector1 = grandDaughter1->get4Vector();
234 TLorentzVector grandDaughter4Vector2 = grandDaughter2->get4Vector();
236 TVector3 motherBoost = -(mother4Vector.BoostVector());
237 TVector3 daughter1Boost = -(daughter4Vector1.BoostVector());
238 TVector3 daughter2Boost = -(daughter4Vector2.BoostVector());
241 daughter4Vector1.Boost(motherBoost);
242 daughter4Vector2.Boost(motherBoost);
245 grandDaughter4Vector1.Boost(daughter1Boost);
246 grandDaughter4Vector2.Boost(daughter2Boost);
249 TVector3 normalVector1 = daughter4Vector1.Vect().Cross(grandDaughter4Vector1.Vect());
250 TVector3 normalVector2 = daughter4Vector2.Vect().Cross(grandDaughter4Vector2.Vect());
252 return std::cos(normalVector1.Angle(normalVector2));
259 double cosHelicityAnglePrimary(
const Particle* part)
261 return part->getCosHelicity();
267 int iGrandDaughter = 0;
268 if ((arguments.size() == 0) || (arguments.size() > 2)) {
269 B2FATAL(
"Wrong number of arguments for cosHelicityAngleDaughter: one or two are needed.");
272 iDaughter = Belle2::convertString<int>(arguments[0]);
273 if (arguments.size() == 2) {
274 iGrandDaughter = Belle2::convertString<int>(arguments[1]);
276 }
catch (std::invalid_argument&) {
277 B2FATAL(
"The arguments of cosHelicityAngleDaughter must be integers!");
280 auto func = [iDaughter, iGrandDaughter](
const Particle * part) ->
double {
281 return part->getCosHelicityDaughter(iDaughter, iGrandDaughter);
286 double acoplanarityAngle(
const Particle* part)
288 return part->getAcoplanarity();
292 VARIABLE_GROUP(
"Helicity variables");
294 REGISTER_VARIABLE(
"cosHelicityAngleMomentum",
295 cosHelicityAngleMomentum,
297 If the given particle has two daughters: cosine of the angle between the line defined by the momentum difference of the two daughters
298 in the frame of the given particle (mother)
299 and the momentum of the given particle in the lab frame.
301 If the given particle has three daughters: cosine of the angle between the normal vector of the plane defined by
302 the momenta of the three daughters in the frame of the given particle (mother)
303 and the momentum of the given particle in the lab frame.
305 Otherwise, it returns 0.)DOC");
307 REGISTER_VARIABLE("cosHelicityAngleMomentumPi0Dalitz",
308 cosHelicityAngleMomentumPi0Dalitz,
310 To be used for the decay :math:`\pi^0 \to e^+ e^- \gamma`:
311 cosine of the angle between the momentum of the gamma in the frame of the given particle (mother)
312 and the momentum of the given particle in the lab frame.
314 Otherwise, it returns 0.)DOC");
316 REGISTER_VARIABLE("cosHelicityAngleBeamMomentum(i)", cosHelicityAngleBeamMomentum,
318 Cosine of the helicity angle of the :math:`i`-th daughter of the particle provided,
319 assuming that the mother of the provided particle corresponds to the centre-of-mass system, whose parameters are
320 automatically loaded by the function, given the accelerator's conditions.)DOC");
322 REGISTER_VARIABLE("cosHelicityAngle(i, j)", cosHelicityAngle,
324 Cosine of the helicity angle between the momentum of the provided particle and the momentum of the selected granddaughter
325 in the reference frame of the selected daughter (:math:`\theta_1` and :math:`\theta_2` in the
326 `PDG <https://journals.aps.org/prd/abstract/10.1103/PhysRevD.98.030001>`_ 2018, p. 722).
328 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.
330 For example, in the decay :math:`B^0 \to \left(J/\psi \to \mu^+ \mu^-\right) \left(K^{*0} \to K^+ \pi^-\right)`,
331 if the provided particle is :math:`B^0` and the selected indices are (0, 0),
332 the variable will return the angle between the momentum of the :math:`B^0` and the momentum of the :math:`\mu^+`,
333 both momenta in the rest frame of the :math:`J/\psi`.
335 This variable is needed for angular analyses of :math:`B`-meson decays into two vector particles.)DOC");
337 REGISTER_VARIABLE("cosAcoplanarityAngle(i, j)", cosAcoplanarityAngle,
339 Cosine of the acoplanarity angle (:math:`\Phi` in the `PDG Polarization Review <http://pdg.lbl.gov/2019/reviews/rpp2018-rev-b-decays-polarization.pdf>`_).
340 Given a two-body decay, the acoplanarity angle is defined as
341 the angle between the two decay planes in the reference frame of the mother.
343 We calculate the acoplanarity angle as the angle between the two
344 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
345 momentum of one of the granddaughters (in the reference frame of the daughter).
347 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
348 second granddaughter.
350 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),
351 the variable will return the acoplanarity using the :math:`\mu^+` and the :math:`K^+` granddaughters.)DOC");
353 REGISTER_VARIABLE("cosHelicityAnglePrimary", cosHelicityAnglePrimary,
355 Cosine of the helicity angle (see``Particle::getCosHelicity``) assuming the center of mass system as mother rest frame.
356 See `PDG Polarization Review <http://pdg.lbl.gov/2019/reviews/rpp2018-rev-b-decays-polarization.pdf>`_ for the definition of the helicity angle.)DOC");
358 REGISTER_VARIABLE("cosHelicityAngleDaughter(i [, j] )", cosHelicityAngleDaughter,
360 Cosine of the helicity angle of the i-th daughter (see ``Particle::getCosHelicityDaughter``).
361 The optional second argument is the index of the granddaughter that defines the angle, default is 0.
363 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,
364 the variable will return the helicity angle of the :math:`\mu^+`.
365 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}`).
366 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^-`).
368 See `PDG Polarization Review <http://pdg.lbl.gov/2019/reviews/rpp2018-rev-b-decays-polarization.pdf>`_ for the definition of the helicity angle.)DOC");
370 REGISTER_VARIABLE("acoplanarityAngle", acoplanarityAngle,
372 Acoplanarity angle (see ``Particle::getAcoplanarity``) assuming a two body decay of the particle and its daughters.
373 See `PDG Polarization Review <http://pdg.lbl.gov/2019/reviews/rpp2018-rev-b-decays-polarization.pdf>`_ for the definition of the acoplanarity angle.)DOC");
static const ParticleType photon
photon particle
static const ChargedStable electron
electron particle
static const ReferenceFrame & GetCurrent()
Get current rest frame.
std::function< double(const Particle *)> FunctionPtr
NOTE: the python interface is documented manually in analysis/doc/Variables.rst (because we use ROOT ...
Abstract base class for different kinds of events.