예제 #1
0
def selection(sample, cuts, rnd, constant_cuts=False):
    ptcut = cuts[0]
    pcut = cuts[1]
    d_ptcut = cuts[2]
    max_ptcut = cuts[3]
    sum_ptcut = cuts[4]

    dalitz_sample = dalitz_phase_space.from_square_dalitz_plot(
        sample[:, 0], sample[:, 1])

    # Random momenta for a given Dalitz plot sample
    mom = dalitz_phase_space.final_state_momenta(
        dalitz_phase_space.m2ac(
            dalitz_sample
        ),  # Note AB<->AC because FroSquareDalitzPlot works with AC
        dalitz_phase_space.m2bc(dalitz_sample)
    )  # Generate momenta in a frame of the decaying particle

    mom = generate_rotation_and_boost(
        mom, md, meanpt, d_ptcut,
        rnd[:, :])  # Rotate and boost to the lab frame

    # Apply cuts
    sel = atfi.greater(atfk.pt(mom[0]), ptcut)
    sel = atfi.logical_and(sel, atfi.greater(atfk.pt(mom[1]), ptcut))
    sel = atfi.logical_and(sel, atfi.greater(atfk.pt(mom[2]), ptcut))
    sel = atfi.logical_and(
        sel, atfi.greater(atfk.pt(mom[0] + mom[1] + mom[2]), d_ptcut))
    sel = atfi.logical_and(sel, atfi.greater(atfk.p(mom[0]), pcut))
    sel = atfi.logical_and(sel, atfi.greater(atfk.p(mom[1]), pcut))
    sel = atfi.logical_and(sel, atfi.greater(atfk.p(mom[2]), pcut))
    sel = atfi.logical_and(
        sel,
        atfi.greater(
            atfi.max(atfi.max(atfk.pt(mom[0]), atfk.pt(mom[1])),
                     atfk.pt(mom[2])), max_ptcut))
    sel = atfi.logical_and(
        sel,
        atfi.greater(
            atfk.pt(mom[0]) + atfk.pt(mom[1]) + atfk.pt(mom[2]), sum_ptcut))
    sel = atfi.logical_and(sel, atfi.greater(atfk.eta(mom[0]), etamin))
    sel = atfi.logical_and(sel, atfi.greater(atfk.eta(mom[1]), etamin))
    sel = atfi.logical_and(sel, atfi.greater(atfk.eta(mom[2]), etamin))
    sel = atfi.logical_and(sel, atfi.less(atfk.eta(mom[0]), etamax))
    sel = atfi.logical_and(sel, atfi.less(atfk.eta(mom[1]), etamax))
    sel = atfi.logical_and(sel, atfi.less(atfk.eta(mom[2]), etamax))

    m2ab = atfk.mass(mom[0] + mom[1])**2
    m2bc = atfk.mass(mom[1] + mom[2])**2

    mprime = sample[:, 0]
    thetaprime = sample[:, 1]

    arrays = []
    outlist = [mprime, thetaprime]
    if not constant_cuts:
        outlist += [ptcut, pcut, d_ptcut, max_ptcut, sum_ptcut]
    for i in outlist:
        arrays += [i[sel]]
    return arrays
예제 #2
0
def momentum_scale(dm, moms):
    """
    Function to calculate the momentum scale factor for kinematic fit
      dm   : invariant mass shift from the desired value
      moms : list of 4-momenta of the final state particles
  """
    psum = sum(moms)  # sum of 4-momenta
    pvecsum = atfk.spatial_components(psum)
    esum = atfk.time_component(psum)
    dedd = atfi.const(0.)
    pdpdd = atfi.const(0.)
    for mom in moms:
        pm = atfk.p(mom)  # Absolute momentum
        em = atfk.time_component(mom)  # Energy
        pvec = atfk.spatial_components(mom)  # 3-momentum
        s = momentum_resolution(pm)
        dedd += s * pm**2 / em
        pdpdd += atfk.scalar_product(pvecsum, pvec) * s
    return -dm / (2. * esum * dedd - 2. * pdpdd)
예제 #3
0
def kinematic_fit(mfit, moms):
    """
    Kinematic fit to a fixed invariant mass for a multibody decay. 
    Returns the fitted mass and the list of final state 4-momenta. 
  """
    mcorr = atfk.mass(sum(moms))
    for l in range(3):
        dm2 = mcorr**2 - mfit**2
        delta = momentum_scale(dm2, moms)
        moms2 = []
        for mom in moms:
            m2 = atfk.mass(mom)**2
            momvec = atfk.spatial_components(mom) * atfk.scalar(
                1 + delta * momentum_resolution(atfk.p(mom)))
            mom2 = atfk.lorentz_vector(momvec,
                                       atfi.sqrt(m2 + atfk.norm(momvec)**2))
            moms2 += [mom2]
        moms = moms2
        mcorr = atfk.mass(sum(moms))
    return mcorr, moms
예제 #4
0
def generate_selection(cuts, rnd, constant_cuts=False):
    """
    Call generation of fully combinatorial or combinatorial with intermediate K* or rho resonances with specified fractions. 
    Apply cuts to the final state particles and fill in output arrays. 
  """
    meankpt = cuts[0]
    meanpipt = cuts[1]
    ptcut = cuts[2]
    pcut = cuts[3]
    meankstarpt = cuts[4]
    meanrhopt = cuts[5]
    kstarfrac = cuts[6]
    rhofrac = cuts[7]

    p4k_1, p4pi1_1, p4pi2_1 = generate_combinatorial(cuts, rnd)
    p4k_2, p4pi1_2, p4pi2_2 = generate_kstar(cuts, rnd)
    p4k_3, p4pi1_3, p4pi2_3 = generate_rho(cuts, rnd)

    thr1 = 1. - kstarfrac - rhofrac
    thr2 = 1. - rhofrac

    cond1 = atfi.stack(4 * [rnd[:, 11] < thr1], axis=1)
    cond2 = atfi.stack(4 * [rnd[:, 11] < thr2], axis=1)

    p4k = tf.where(cond1, p4k_1, tf.where(cond2, p4k_2, p4k_3))
    p4pi1 = tf.where(cond1, p4pi1_1, tf.where(cond2, p4pi1_2, p4pi1_3))
    p4pi2 = tf.where(cond1, p4pi2_1, tf.where(cond2, p4pi2_2, p4pi2_3))

    mb = atfk.mass(p4k + p4pi1 + p4pi2)
    mfit, moms = kinematic_fit(atfi.const(md), [p4k, p4pi1, p4pi2])

    sel = tf.greater(atfk.p(moms[0]), pcut)
    sel = tf.logical_and(sel, tf.greater(atfk.p(moms[1]), pcut))
    sel = tf.logical_and(sel, tf.greater(atfk.p(moms[2]), pcut))
    sel = tf.logical_and(sel, tf.greater(atfk.pt(moms[0]), ptcut))
    sel = tf.logical_and(sel, tf.greater(atfk.pt(moms[1]), ptcut))
    sel = tf.logical_and(sel, tf.greater(atfk.pt(moms[2]), ptcut))

    m2kpi = atfk.mass(moms[0] + moms[1])**2
    m2pipi = atfk.mass(moms[1] + moms[2])**2

    sample = dlz_phsp.from_vectors(m2kpi, m2pipi)
    mprime = dlz_phsp.m_prime_bc(sample)
    thetaprime = dlz_phsp.theta_prime_bc(sample)

    sel = tf.logical_and(
        sel,
        observables_phase_space.inside(
            tf.stack([mprime, thetaprime, mb], axis=1)))

    observables = []
    outlist = [mprime, thetaprime, mb, m2kpi, m2pipi]

    if not constant_cuts:
        outlist += [
            meankpt, meanpipt, ptcut, pcut, meankstarpt, meanrhopt, kstarfrac,
            rhofrac
        ]
    for i in outlist:
        observables += [tf.boolean_mask(i, sel)]

    return observables
예제 #5
0
moms = final_state_momenta(toy_data)

# Apply random rotation and boost to lab frame
rnd = tf.random.uniform((len(toy_data), 6), dtype=tf.float64)
boosted_moms = random_rotation_and_boost(moms, rnd)

print(f"Number of events generated: {len(boosted_moms[0])}")

# Filter data according to "trigger conditions"
#   (minimun p and pT for tracks, and minimum angles between pairs of tracks).
filtered_data = toy_data[
    (atfk.pt(boosted_moms[0]) > 1.0)
    & (atfk.pt(boosted_moms[1]) > 1.0)
    & (atfk.pt(boosted_moms[2]) > 0.5)
    & (atfk.pt(boosted_moms[3]) > 0.5)
    & (atfk.p(boosted_moms[0]) > 5.0)
    & (atfk.p(boosted_moms[1]) > 5.0)
    & (atfk.p(boosted_moms[2]) > 3.0)
    & (atfk.p(boosted_moms[3]) > 3.0)
    & (
        atfk.scalar_product(
            atfk.unit_vector(boosted_moms[0]), atfk.unit_vector(boosted_moms[1])
        )
        < 0.9999
    )
    & (
        atfk.scalar_product(
            atfk.unit_vector(boosted_moms[0]), atfk.unit_vector(boosted_moms[2])
        )
        < 0.9999
    )