Beispiel #1
0
def simulate_reco_event(evt_id: int,
                        hits: pd.DataFrame,
                        particles: pd.DataFrame,
                        errmat_p_r: errmat,
                        errmat_p_phi: errmat,
                        errmat_p_z: errmat,
                        errmat_p_t: errmat,
                        errmat_c_r: errmat,
                        errmat_c_phi: errmat,
                        errmat_c_z: errmat,
                        errmat_c_t: errmat,
                        true_e_threshold: float = 0.) -> pd.DataFrame:
    """
    Simulate the reconstructed coordinates for 1 coincidence from true GEANT4 dataframes.
    Notice that the time binning must be provided in ps.
    """

    evt_parts = particles[particles.event_id == evt_id]
    evt_hits = hits[hits.event_id == evt_id]
    energy = evt_hits.energy.sum()
    if energy < true_e_threshold:
        events = pd.DataFrame({
            'event_id': [float(evt_id)],
            'true_energy': [energy],
            'true_r1': [0.],
            'true_phi1': [0.],
            'true_z1': [0.],
            'true_t1': [0.],
            'true_r2': [0.],
            'true_phi2': [0.],
            'true_z2': [0.],
            'true_t2': [0.],
            'phot_like1': [0.],
            'phot_like2': [0.],
            'reco_r1': [0.],
            'reco_phi1': [0.],
            'reco_z1': [0.],
            'reco_t1': [0.],
            'reco_r2': [0.],
            'reco_phi2': [0.],
            'reco_z2': [0.],
            'reco_t2': [0.]
        })
        return events

    pos1, pos2, t1, t2, phot1, phot2 = rf.find_first_interactions_in_active(
        evt_parts, evt_hits)

    if len(pos1) == 0 or len(pos2) == 0:
        events = pd.DataFrame({
            'event_id': [float(evt_id)],
            'true_energy': [energy],
            'true_r1': [0.],
            'true_phi1': [0.],
            'true_z1': [0.],
            'true_t1': [0.],
            'true_r2': [0.],
            'true_phi2': [0.],
            'true_z2': [0.],
            'true_t2': [0.],
            'phot_like1': [0.],
            'phot_like2': [0.],
            'reco_r1': [0.],
            'reco_phi1': [0.],
            'reco_z1': [0.],
            'reco_t1': [0.],
            'reco_r2': [0.],
            'reco_phi2': [0.],
            'reco_z2': [0.],
            'reco_t2': [0.]
        })
        return events

    t1 = t1 / units.ps
    t2 = t2 / units.ps

    # Transform in cylindrical coordinates
    cyl_pos = rf.from_cartesian_to_cyl(np.array([pos1, pos2]))

    r1 = cyl_pos[0, 0]
    phi1 = cyl_pos[0, 1]
    z1 = cyl_pos[0, 2]
    r2 = cyl_pos[1, 0]
    phi2 = cyl_pos[1, 1]
    z2 = cyl_pos[1, 2]

    # Get all errors.
    if phot1:
        er1 = errmat_p_r.get_random_error(r1)
        ephi1 = errmat_p_phi.get_random_error(phi1)
        ez1 = errmat_p_z.get_random_error(z1)
        et1 = errmat_p_t.get_random_error(t1)
    else:
        er1 = errmat_c_r.get_random_error(r1)
        ephi1 = errmat_c_phi.get_random_error(phi1)
        ez1 = errmat_c_z.get_random_error(z1)
        et1 = errmat_c_t.get_random_error(t1)

    if phot2:
        er2 = errmat_p_r.get_random_error(r2)
        ephi2 = errmat_p_phi.get_random_error(phi2)
        ez2 = errmat_p_z.get_random_error(z2)
        et2 = errmat_p_t.get_random_error(t2)
    else:
        er2 = errmat_c_r.get_random_error(r2)
        ephi2 = errmat_c_phi.get_random_error(phi2)
        ez2 = errmat_c_z.get_random_error(z2)
        et2 = errmat_c_t.get_random_error(t2)

    # Compute reconstructed quantities.
    r1_reco = r1 - er1
    r2_reco = r2 - er2
    phi1_reco = phi1 - ephi1
    phi2_reco = phi2 - ephi2
    z1_reco = z1 - ez1
    z2_reco = z2 - ez2
    t1_reco = t1 - et1
    t2_reco = t2 - et2

    event_ids = [float(evt_id)]
    energies = [energy]

    true_r1 = [r1]
    true_phi1 = [phi1]
    true_z1 = [z1]
    true_t1 = [t1]
    true_r2 = [r2]
    true_phi2 = [phi2]
    true_z2 = [z2]
    true_t2 = [t2]

    phot_like1 = [float(phot1)]
    phot_like2 = [float(phot2)]

    reco_r1 = [r1_reco]
    reco_phi1 = [phi1_reco]
    reco_z1 = [z1_reco]
    reco_t1 = [t1_reco]
    reco_r2 = [r2_reco]
    reco_phi2 = [phi2_reco]
    reco_z2 = [z2_reco]
    reco_t2 = [t2_reco]

    events = pd.DataFrame({
        'event_id': event_ids,
        'true_energy': energies,
        'true_r1': true_r1,
        'true_phi1': true_phi1,
        'true_z1': true_z1,
        'true_t1': true_t1,
        'true_r2': true_r2,
        'true_phi2': true_phi2,
        'true_z2': true_z2,
        'true_t2': true_t2,
        'phot_like1': phot_like1,
        'phot_like2': phot_like2,
        'reco_r1': reco_r1,
        'reco_phi1': reco_phi1,
        'reco_z1': reco_z1,
        'reco_t1': reco_t1,
        'reco_r2': reco_r2,
        'reco_phi2': reco_phi2,
        'reco_z2': reco_z2,
        'reco_t2': reco_t2
    })
    return events
Beispiel #2
0
    for evt in events[:]:

        ### Select photoelectric events only
        evt_parts = particles[particles.event_id == evt]
        evt_hits = hits[hits.event_id == evt]
        select, true_pos = mcf.select_photoelectric(evt_parts, evt_hits)
        if not select: continue

        sns_resp = sel_df[sel_df.event_id == evt]
        if len(sns_resp) == 0: continue

        _, _, pos1, pos2, q1, q2 = rf.assign_sipms_to_gammas(
            sns_resp, true_pos, DataSiPM_idx)

        if len(pos1) > 0:
            pos_phi = rf.from_cartesian_to_cyl(np.array(pos1))[:, 1]
            _, var_phi = rf.phi_mean_var(pos_phi, q1)

            pos_z = np.array(pos1)[:, 2]
            mean_z = np.average(pos_z, weights=q1)
            var_z = np.average((pos_z - mean_z)**2, weights=q1)

            reco_cart = np.average(pos1, weights=q1, axis=0)

            var_phi1.append(var_phi)
            var_z1.append(var_z)
            touched_sipms1.append(len(pos1))

            r = np.sqrt(true_pos[0][0]**2 + true_pos[0][1]**2)
            true_r1.append(r)
Beispiel #3
0
def simulate_reco_event(evt_id: int, hits: pd.DataFrame, particles: pd.DataFrame,
                        errmat_p_r: errmat, errmat_p_phi: errmat3d, errmat_p_z: errmat3d,
                        errmat_p_t: errmat, errmat_c_r: errmat, errmat_c_phi: errmat3d,
                        errmat_c_z: errmat3d, errmat_c_t: errmat,
                        true_e_threshold: float = 0., photo_range: float = 1.,
                        only_phot: bool = False) -> pd.DataFrame:
    """
    Simulate the reconstructed coordinates for 1 coincidence from true GEANT4 dataframes.
    """

    evt_parts = particles[particles.event_id == evt_id]
    evt_hits  = hits     [hits     .event_id == evt_id]
    energy    = evt_hits.energy.sum()
    if energy < true_e_threshold:
        return None

    pos1, pos2, t1, t2, phot1, phot2 = rf.find_first_interactions_in_active(evt_parts, evt_hits, photo_range)

    no_reco_positions = len(pos1) == 0 or len(pos2) == 0
    no_phot_interactions = not phot1 or not phot2
    if no_reco_positions or (only_phot and no_phot_interactions):
        return None

    t1 = t1 / units.ps
    t2 = t2 / units.ps

    # Transform in cylindrical coordinates
    (r1, phi1, z1), (r2, phi2, z2) = rf.from_cartesian_to_cyl(np.array([pos1, pos2]))

    # Get all errors.
    if phot1:
        er1, ephi1, ez1, et1 = get_reco_interaction(r1, phi1, z1, t1, errmat_p_r, errmat_p_phi, errmat_p_z, errmat_p_t)
    else:
        er1, ephi1, ez1, et1 = get_reco_interaction(r1, phi1, z1, t1, errmat_c_r, errmat_c_phi, errmat_c_z, errmat_c_t)

    if phot2:
        er2, ephi2, ez2, et2 = get_reco_interaction(r2, phi2, z2, t2, errmat_p_r, errmat_p_phi, errmat_p_z, errmat_p_t)
    else:
        er2, ephi2, ez2, et2 = get_reco_interaction(r2, phi2, z2, t2, errmat_c_r, errmat_c_phi, errmat_c_z, errmat_c_t)

    if er1 == None or ephi1 == None or ez1 == None or et1 == None or er2 == None or ephi2 == None or ez2 == None or et2 == None:
        return None


    # Compute reconstructed quantities.
    r1_reco = r1 - er1
    r2_reco = r2 - er2
    phi1_reco = phi1 - ephi1
    phi2_reco = phi2 - ephi2
    z1_reco = z1 - ez1
    z2_reco = z2 - ez2
    t1_reco = t1 - et1
    t2_reco = t2 - et2

    events = pd.DataFrame({'event_id':    float(evt_id),
                           'true_energy': energy,
                           'true_r1':     r1,
                           'true_phi1':   phi1,
                           'true_z1':     z1,
                           'true_t1':     t1,
                           'true_r2':     r2,
                           'true_phi2':   phi2,
                           'true_z2':     z2,
                           'true_t2':     t2,
                           'phot_like1':  float(phot1),
                           'phot_like2':  float(phot2),
                           'reco_r1':     r1_reco,
                           'reco_phi1':   phi1_reco,
                           'reco_z1':     z1_reco,
                           'reco_t1':     t1_reco,
                           'reco_r2':     r2_reco,
                           'reco_phi2':   phi2_reco,
                           'reco_z2':     z2_reco,
                           'reco_t2':     t2_reco}, index=[0])
    return events
Beispiel #4
0
        pos2 = np.array(pos2)

        ## Calculate R
        r1 = r2 = None

        sel1_r = q1 > thr_r
        q1r = q1[sel1_r]
        pos1r = pos1[sel1_r]
        sel2_r = q2 > thr_r
        q2r = q2[sel2_r]
        pos2r = pos2[sel2_r]
        if len(pos1r) == 0 or len(pos2r) == 0:
            c1 += 1
            continue

        pos1_phi = rf.from_cartesian_to_cyl(np.array(pos1r))[:, 1]
        diff_sign = min(pos1_phi) < 0 < max(pos1_phi)
        if diff_sign & (np.abs(np.min(pos1_phi)) > np.pi / 2.):
            pos1_phi[pos1_phi < 0] = np.pi + np.pi + pos1_phi[pos1_phi < 0]
        mean_phi = np.average(pos1_phi, weights=q1r)
        var_phi1 = np.average((pos1_phi - mean_phi)**2, weights=q1r)
        r1 = Rpos(np.sqrt(var_phi1)).value

        pos2_phi = rf.from_cartesian_to_cyl(np.array(pos2r))[:, 1]
        diff_sign = min(pos2_phi) < 0 < max(pos2_phi)
        if diff_sign & (np.abs(np.min(pos2_phi)) > np.pi / 2.):
            pos2_phi[pos2_phi < 0] = np.pi + np.pi + pos2_phi[pos2_phi < 0]
        mean_phi = np.average(pos2_phi, weights=q2r)
        var_phi2 = np.average((pos2_phi - mean_phi)**2, weights=q2r)
        r2 = Rpos(np.sqrt(var_phi2)).value
Beispiel #5
0
def build_r_map(input_file: str, output_file: str, threshold: float):
    """
    This function extracts the true radial position
    and the variance of the SiPM positions
    in phi and z for each gamma interaction.
    """

    DataSiPM = db.DataSiPMsim_only('petalo', 0)  # full body PET
    DataSiPM_idx = DataSiPM.set_index('SensorID')

    try:
        sns_response = pd.read_hdf(input_file, 'MC/sns_response')
    except ValueError:
        print(f'File {input_file} not found')
        exit()
    except OSError:
        print(f'File {input_file} not found')
        exit()
    except KeyError:
        print(f'No object named MC/sns_response in file {input_file}')
        exit()
    print(f'Analyzing file {input_file}')

    sel_df = rf.find_SiPMs_over_threshold(sns_response, threshold)

    particles = pd.read_hdf(input_file, 'MC/particles')
    hits = pd.read_hdf(input_file, 'MC/hits')
    events = particles.event_id.unique()

    true_r1, true_r2 = [], []
    var_phi1, var_phi2 = [], []
    var_z1, var_z2 = [], []

    touched_sipms1, touched_sipms2 = [], []

    for evt in events:

        ### Select photoelectric events only
        evt_parts = particles[particles.event_id == evt]
        evt_hits = hits[hits.event_id == evt]
        select, true_pos = mcf.select_photoelectric(evt_parts, evt_hits)
        if not select: continue

        sns_resp = sel_df[sel_df.event_id == evt]
        if len(sns_resp) == 0: continue

        _, _, pos1, pos2, q1, q2 = rf.assign_sipms_to_gammas(
            sns_resp, true_pos, DataSiPM_idx)

        if len(pos1) > 0:
            pos_phi = rf.from_cartesian_to_cyl(np.array(pos1))[:, 1]
            _, var_phi = rf.phi_mean_var(pos_phi, q1)

            pos_z = np.array(pos1)[:, 2]
            mean_z = np.average(pos_z, weights=q1)
            var_z = np.average((pos_z - mean_z)**2, weights=q1)
            r = np.sqrt(true_pos[0][0]**2 + true_pos[0][1]**2)

            var_phi1.append(var_phi)
            var_z1.append(var_z)
            touched_sipms1.append(len(pos1))
            true_r1.append(r)

        else:
            var_phi1.append(1.e9)
            var_z1.append(1.e9)
            touched_sipms1.append(1.e9)
            true_r1.append(1.e9)

        if len(pos2) > 0:
            pos_phi = rf.from_cartesian_to_cyl(np.array(pos2))[:, 1]
            _, var_phi = rf.phi_mean_var(pos_phi, q2)

            pos_z = np.array(pos2)[:, 2]
            mean_z = np.average(pos_z, weights=q2)
            var_z = np.average((pos_z - mean_z)**2, weights=q2)
            r = np.sqrt(true_pos[1][0]**2 + true_pos[1][1]**2)

            var_phi2.append(var_phi)
            var_z2.append(var_z)
            touched_sipms2.append(len(pos2))
            true_r2.append(r)

        else:
            var_phi2.append(1.e9)
            var_z2.append(1.e9)
            touched_sipms2.append(1.e9)
            true_r2.append(1.e9)

    a_true_r1 = np.array(true_r1)
    a_true_r2 = np.array(true_r2)
    a_var_phi1 = np.array(var_phi1)
    a_var_phi2 = np.array(var_phi2)
    a_var_z1 = np.array(var_z1)
    a_var_z2 = np.array(var_z2)

    a_touched_sipms1 = np.array(touched_sipms1)
    a_touched_sipms2 = np.array(touched_sipms2)

    np.savez(output_file,
             a_true_r1=a_true_r1,
             a_true_r2=a_true_r2,
             a_var_phi1=a_var_phi1,
             a_var_phi2=a_var_phi2,
             a_var_z1=a_var_z1,
             a_var_z2=a_var_z2,
             a_touched_sipms1=a_touched_sipms1,
             a_touched_sipms2=a_touched_sipms2)