Rivet analyses
Decay kinematics of semileptonic BâââD* decays.
Experiment: BELLE (KEKB)
Inspire ID: 2624324
Status: VALIDATED NOHEPDATA
Authors: - Peter Richardson
References: - arXiv: 2301.07529
Beams: * *
Beam energies: ANY
Run details: - Any process producing B0, B+ mesons
Measurement of recoil w, helicity and decay plane angles of semileptonc BĖ to D* decays.
Source
code:BELLE_2023_I2624324.cc
// -*- C++ -*-
#include "Rivet/Analysis.hh"
#include "Rivet/Projections/FinalState.hh"
#include "Rivet/Projections/UnstableParticles.hh"
namespace Rivet {
/// @brief B -> D* semileptonic
class BELLE_2023_I2624324 : public Analysis {
public:
/// Constructor
RIVET_DEFAULT_ANALYSIS_CTOR(BELLE_2023_I2624324);
/// @name Analysis methods
/// @{
/// Book histograms and initialise projections before the run
void init() {
// Initialise and register projections
declare(UnstableParticles(Cuts::abspid == 511 || Cuts::abspid == 521), "UFS");
// histograms
for (unsigned int ix = 0; ix < 4; ++ix) {
book(_h_aver[ix], 2, 1 + ix, 1);
for (unsigned int iy = 0; iy < 4; ++iy) {
book(_h[ix][iy], 1, 1 + ix, 1 + iy);
}
}
}
/// Perform the per-event analysis
bool analyzeDecay(const Particle& mother, const vector<int>& ids) {
// There is no point in looking for decays with less particles than to be analysed
if (mother.children().size() == ids.size()) {
bool decayfound = true;
for (int id : ids) {
if (!contains(mother, id)) decayfound = false;
}
return decayfound;
}
return false;
}
bool contains(const Particle& mother, int id) {
return any(mother.children(), HasPID(id));
}
double recoilW(const Particle& mother) {
FourMomentum lepton, neutrino, meson, q;
for (const Particle& c : mother.children()) {
if (c.isNeutrino()) neutrino = c.mom();
if (c.isLepton() && !c.isNeutrino()) lepton = c.mom();
if (c.isHadron()) meson = c.mom();
}
q = lepton + neutrino; //no hadron before
double mb2 = mother.mom() * mother.mom();
double mD2 = meson * meson;
return (mb2 + mD2 - q * q) / (2. * sqrt(mb2) * sqrt(mD2));
}
/// Perform the per-event analysis
void analyze(const Event& event) {
FourMomentum pl, pnu, pB, pD, pDs, ppi;
// Iterate of B mesons
for (const Particle& p : apply<UnstableParticles>(event, "UFS").particles()) {
pB = p.mom();
// Find semileptonic decays
int sign = p.pid() / p.abspid();
int iDStar = sign * (p.abspid() == 511 ? -413 : -423);
int iloc = -1;
if (analyzeDecay(p, {iDStar, 12 * sign, -11 * sign}))
iloc = 0;
else if (analyzeDecay(p, {iDStar, 14 * sign, -13 * sign}))
iloc = 1;
else
continue;
if (p.abspid() == 521) iloc += 2;
double w = recoilW(p);
_h[0][iloc]->fill(w);
_h_aver[0]->fill(w);
// Get the necessary momenta for the angles
bool foundDdecay = false;
for (const Particle& c : p.children()) {
if (c.abspid() == 413 || c.abspid() == 423) {
if ((c.pid() == -413
&& (analyzeDecay(c, {PID::PIMINUS, PID::D0BAR}) || analyzeDecay(c, {PID::PI0, PID::DMINUS})))
|| (c.pid() == 413
&& (analyzeDecay(c, {PID::PIPLUS, PID::D0}) || analyzeDecay(c, {PID::PI0, PID::DPLUS})))
|| (c.pid() == -423 && analyzeDecay(c, {PID::PI0, PID::D0BAR}))
|| (c.pid() == 423 && analyzeDecay(c, {PID::PI0, PID::D0}))) {
foundDdecay = true;
pDs = c.mom();
for (const Particle& dc : c.children()) {
if (dc.hasCharm())
pD = dc.mom();
else
ppi = dc.mom();
}
}
}
else if (c.abspid() == 11 || c.abspid() == 13)
pl = c.mom();
else if (c.abspid() == 12 || c.abspid() == 14)
pnu = c.mom();
}
// This is the angle analysis
if (!foundDdecay) continue;
// First boost all relevant momenta into the B-rest frame
const LorentzTransform B_boost = LorentzTransform::mkFrameTransformFromBeta(pB.betaVec());
// Momenta in B rest frame:
FourMomentum lv_brest_Dstar = B_boost.transform(pDs);
FourMomentum lv_brest_w = B_boost.transform(pB - pDs);
FourMomentum lv_brest_D = B_boost.transform(pD);
FourMomentum lv_brest_lep = B_boost.transform(pl);
const LorentzTransform Ds_boost = LorentzTransform::mkFrameTransformFromBeta(
lv_brest_Dstar.betaVec());
FourMomentum lv_Dstarrest_D = Ds_boost.transform(lv_brest_D);
const LorentzTransform W_boost = LorentzTransform::mkFrameTransformFromBeta(lv_brest_w.betaVec());
FourMomentum lv_wrest_lep = W_boost.transform(lv_brest_lep);
double cos_thetaV = cos(lv_brest_Dstar.p3().angle(lv_Dstarrest_D.p3()));
_h[2][iloc]->fill(cos_thetaV);
_h_aver[2]->fill(cos_thetaV);
double cos_thetaL = cos(lv_brest_w.p3().angle(lv_wrest_lep.p3()));
_h[1][iloc]->fill(cos_thetaL);
_h_aver[1]->fill(cos_thetaL);
Vector3 LTrans = lv_wrest_lep.p3() - cos_thetaL * lv_wrest_lep.p3().perp() * lv_brest_w.p3().unit();
Vector3 VTrans = lv_Dstarrest_D.p3()
- cos_thetaV * lv_Dstarrest_D.p3().perp() * lv_brest_Dstar.p3().unit();
float chi = atan2(LTrans.cross(VTrans).dot(lv_brest_w.p3().unit()), LTrans.dot(VTrans));
if (chi < 0.) chi += 2. * M_PI;
_h[3][iloc]->fill(chi);
_h_aver[3]->fill(chi);
}
}
/// Normalise histograms etc., after the run
void finalize() {
normalize(_h, 1.0);
normalize(_h_aver, 1.0);
}
/// @}
/// @name Histograms
/// @{
Histo1DPtr _h[4][4];
Histo1DPtr _h_aver[4];
/// @}
};
RIVET_DECLARE_PLUGIN(BELLE_2023_I2624324);
}