Beispiel #1
0
def get_skel_extremes(vox_size, energy_type, strict_vox_size, hitc):

    voxels = plf.voxelize_hits(hitc.hits, vox_size, strict_vox_size,
                               energy_type)
    tracks = plf.make_track_graphs(voxels)

    df = pd.DataFrame(columns=[
        'event', 'trackID', 'energy', 'skel_extr1_x', 'skel_extr1_y',
        'skel_extr1_z', 'skel_extr2_x', 'skel_extr2_y', 'skel_extr2_z'
    ])

    if (len(voxels) == 0):
        return df

    vox_size_x = voxels[0].size[0]
    vox_size_y = voxels[0].size[1]
    vox_size_z = voxels[0].size[2]

    def get_track_energy(track):
        return sum([vox.Ehits for vox in track.nodes()])

    #sort tracks in energy
    tracks = sorted(tracks, key=get_track_energy, reverse=True)

    track_hits = []

    for c, t in enumerate(tracks, 0):
        tID = c
        energy = get_track_energy(t)

        extr1, extr2 = plf.find_extrema(t)
        extr1_pos = extr1.XYZ
        extr2_pos = extr2.XYZ

        list_of_vars = [
            hitc.event, tID, energy, extr1_pos[0], extr1_pos[1], extr1_pos[2],
            extr2_pos[0], extr2_pos[1], extr2_pos[2]
        ]

        df.loc[c] = list_of_vars
        try:
            types_dict
        except NameError:
            types_dict = dict(zip(df.columns, [type(x) for x in list_of_vars]))

        #change dtype of columns to match type of variables
        df = df.apply(lambda x: x.astype(types_dict[x.name]))

    return df
Beispiel #2
0
voxels_dict['voxel_id'] = [1, 2, 3, 4, 5, 6, 7]
voxels_dict['X'] = [30., 30., 60., 60., 60., 60., 20.]
voxels_dict['Y'] = [30., 30., 60., 60., 60., 60., 20.]
voxels_dict['Z'] = [30., 40., 30., 60., 70., 80., 80.]
voxels_dict['E'] = [0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.001]
voxels_dict['negli'] = [False, False, False, False, False, False, True]
voxels_df2 = pd.DataFrame(voxels_dict)
voxels_df2.set_index(['event_id', 'voxel_id'], inplace=True)

voxel_dimensions = (10., 10., 10.)
ic_voxels = [Voxel(voxels_df2.iloc[i].X, voxels_df2.iloc[i].Y,
                   voxels_df2.iloc[i].Z,
                   voxels_df2.iloc[i].E, voxel_dimensions) \
             for i in range(len(voxels_df2))]

event_tracks = make_track_graphs(ic_voxels)


def test_get_voxel_track_relations():
    relations = [0, 0, 1, 2, 2, 2, np.nan]
    assert relations == get_voxel_track_relations(voxels_df2, event_tracks)


def test_process_tracks():
    track_Eth = 0.15
    tracks_E = [0.3, 0.2]
    tracks_length = [20.0, 10.0]

    sorted_tracks = process_tracks(event_tracks, track_Eth)

    assert tracks_E[0] == pytest.approx(sorted_tracks[0][0])
Beispiel #3
0
def fanal_ana(
    det_name,  # Detector name: 'new', 'next100', 'next500'
    event_type,  # Event type: 'bb0nu', 'Tl208', 'Bi214'
    fwhm,  # FWHM at Qbb
    voxel_size,  # Voxel size (x, y, z)
    track_Eth,  # Track energy threshold
    max_num_tracks,  # Maximum number of tracks
    blob_radius,  # Blob radius
    blob_Eth,  # Blob energy threshold
    roi_Emin,  # ROI minimum energy
    roi_Emax,  # ROI maximum energy
    files_in,  # Input files
    event_range,  # Range of events to analyze: all, ... ??
    file_out,  # Output file
    compression,  # Compression of output file: 'ZLIB1', 'ZLIB4',
    # 'ZLIB5', 'ZLIB9', 'BLOSC5', 'BLZ4HC5'
    verbosity_level):

    ### LOGGER
    logger = get_logger('FanalAna', verbosity_level)

    ### DETECTOR NAME
    det_name = getattr(DetName, det_name)

    ### PRINTING GENERAL INFO
    print(
        '\n***********************************************************************************'
    )
    print('***** Detector: {}'.format(det_name.name))
    print('***** Analizing {} events'.format(event_type))
    print('***** Energy Resolution: {:.2f}% FWFM at Qbb'.format(fwhm /
                                                                units.perCent))
    print('***** Voxel Size: ({}, {}, {}) mm'.format(voxel_size[0] / units.mm,
                                                     voxel_size[1] / units.mm,
                                                     voxel_size[2] / units.mm))
    print(
        '***********************************************************************************\n'
    )

    print('* Track Eth: {:4.1f} keV   Max Num Tracks: {}\n'.format(
        track_Eth / units.keV, max_num_tracks))
    print('* Blob radius: {:.1f} mm   Blob Eth: {:4.1f} keV\n'.format(
        blob_radius, blob_Eth / units.keV))
    print('* ROI limits: [{:4.1f}, {:4.1f}] keV\n'.format(
        roi_Emin / units.keV, roi_Emax / units.keV))

    ### INPUT RECONSTRUCTION FILE AND GROUP
    reco_group_name = get_reco_group_name(fwhm / units.perCent, voxel_size)
    print('* {} {} input reco file names:'.format(len(files_in), event_type))
    for iFileName in files_in:
        print(' ', iFileName)
    print('  Reco group name: {}\n'.format(reco_group_name))

    ### OUTPUT FILE, ITS GROUPS & ATTRIBUTES
    # Output analysis file
    oFile = tb.open_file(file_out, 'w', filters=tbl_filters(compression))

    # Analysis group Name
    ana_group_name = get_ana_group_name(fwhm / units.perCent, voxel_size)
    oFile.create_group('/', 'FANALIC')
    oFile.create_group('/FANALIC', ana_group_name[9:])

    print('* Output analysis file name:', file_out)
    print('  Ana group name: {}\n'.format(ana_group_name))

    # Attributes
    oFile.set_node_attr(ana_group_name, 'input_reco_files', files_in)
    oFile.set_node_attr(ana_group_name, 'input_reco_group', reco_group_name)
    oFile.set_node_attr(ana_group_name, 'event_type', event_type)
    oFile.set_node_attr(ana_group_name, 'energy_resolution',
                        fwhm / units.perCent)
    oFile.set_node_attr(ana_group_name, 'track_Eth', track_Eth)
    oFile.set_node_attr(ana_group_name, 'max_num_tracks', max_num_tracks)
    oFile.set_node_attr(ana_group_name, 'blob_radius', blob_radius)
    oFile.set_node_attr(ana_group_name, 'blob_Eth', blob_Eth)
    oFile.set_node_attr(ana_group_name, 'roi_Emin', roi_Emin)
    oFile.set_node_attr(ana_group_name, 'roi_Emax', roi_Emax)

    ### DATA TO STORE
    # Event counters
    simulated_events = 0
    stored_events = 0
    smE_filter_events = 0
    fid_filter_events = 0
    tracks_filter_events = 0
    blobs_filter_events = 0
    roi_filter_events = 0

    analyzed_events = 0
    toUpdate_events = 1

    # Dictionaries for events & voxels data
    events_dict = get_events_ana_dict()
    voxels_dict = get_voxels_ana_dict()

    events_reco_df = pd.DataFrame()
    voxels_reco_df = pd.DataFrame()

    ### ANALYSIS PROCEDURE
    print('* Analyzing events ...\n')

    # Looping through all the input files
    for iFileName in files_in:

        # Updating reconstruction counters
        with tb.open_file(iFileName, mode='r') as reco_file:
            simulated_events += reco_file.get_node_attr(
                reco_group_name, 'simulated_events')
            stored_events += reco_file.get_node_attr(reco_group_name,
                                                     'stored_events')
            smE_filter_events += reco_file.get_node_attr(
                reco_group_name, 'smE_filter_events')
            fid_filter_events += reco_file.get_node_attr(
                reco_group_name, 'fid_filter_events')

        # Getting the events & voxels data from the reconstruction phase
        file_events = pd.read_hdf(iFileName, reco_group_name + '/events')
        file_voxels = pd.read_hdf(iFileName, reco_group_name + '/voxels')

        # Updating reconstruction dataframes
        events_reco_df = pd.concat([events_reco_df, file_events], axis=0)
        voxels_reco_df = pd.concat([voxels_reco_df, file_voxels], axis=0)

        print('* Processing {} ...'.format(iFileName))

        ### Looping through all the events that passed the fiducial filter
        for event_number, event_df in file_events[
                file_events.fid_filter].iterrows():

            # Updating counter of analyzed events
            analyzed_events += 1
            logger.info('Analyzing event Id: {0} ...'.format(event_number))

            # Getting event data
            event_data = get_event_ana_data()
            event_data['event_id'] = event_number

            event_voxels = file_voxels.loc[event_number]
            num_event_voxels = len(event_voxels)
            num_event_voxels_negli = len(event_voxels[event_voxels.negli])
            voxel_dimensions = (event_df.voxel_sizeX, event_df.voxel_sizeY,
                                event_df.voxel_sizeZ)

            logger.info('  Total Voxels: {}   Negli. Voxels: {}   Voxels Size: ({:3.1f}, {:3.1f}, {:3.1f}) mm'\
                        .format(num_event_voxels, num_event_voxels_negli, voxel_dimensions[0],
                                voxel_dimensions[1], voxel_dimensions[2]))

            # If there is any negligible Voxel, distribute its energy between its neighbours,
            # if not, all voxels maintain their previous energies
            if num_event_voxels_negli:
                event_voxels_newE = get_new_energies(event_voxels)
            else:
                event_voxels_newE = event_voxels.E.tolist()

            # Translate fanalIC voxels info to IC voxels to make tracks
            #ic_voxels = [Voxel(event_voxels.iloc[i].X, event_voxels.iloc[i].Y, event_voxels.iloc[i].Z,
            #                   event_voxels_newE[i], voxel_dimensions) for i in range(num_event_voxels)]
            ic_voxels = []
            for i, voxel in event_voxels.iterrows():
                ic_voxel = Voxel(voxel.X, voxel.Y, voxel.Z,
                                 event_voxels_newE[i], voxel_dimensions)
                ic_voxels.append(ic_voxel)

            # Make tracks
            event_tracks = make_track_graphs(ic_voxels)
            num_ini_tracks = len(event_tracks)
            logger.info('  Num initial tracks: {:2}'.format(num_ini_tracks))

            # Appending to every voxel, the track it belongs to
            event_voxels_tracks = get_voxel_track_relations(
                event_voxels, event_tracks)

            # Appending ana-info to this event voxels
            extend_voxels_ana_dict(voxels_dict, event_number,
                                   event_voxels.index.tolist(),
                                   event_voxels_newE, event_voxels_tracks)

            # Processing tracks: Getting energies, sorting and filtering ...
            event_sorted_tracks = process_tracks(event_tracks, track_Eth)
            event_data['num_tracks'] = len(event_sorted_tracks)

            # Getting 3 hottest tracks info
            if event_data['num_tracks'] >= 1:
                event_data['track0_E'] = event_sorted_tracks[0][0]
                event_data['track0_length'] = event_sorted_tracks[0][1]
                event_data['track0_voxels'] = len(
                    event_sorted_tracks[0][2].nodes())
            if event_data['num_tracks'] >= 2:
                event_data['track1_E'] = event_sorted_tracks[1][0]
                event_data['track1_length'] = event_sorted_tracks[1][1]
                event_data['track1_voxels'] = len(
                    event_sorted_tracks[1][2].nodes())
            if event_data['num_tracks'] >= 3:
                event_data['track2_E'] = event_sorted_tracks[2][0]
                event_data['track2_length'] = event_sorted_tracks[2][1]
                event_data['track2_voxels'] = len(
                    event_sorted_tracks[2][2].nodes())

            # Applying the tracks filter consisting on:
            # 0 < num tracks < max_num_tracks
            # the track length must be longer than 2 times the blob_radius
            event_data['tracks_filter'] = (
                (event_data['num_tracks'] > 0) &
                (event_data['num_tracks'] <= max_num_tracks) &
                (event_data['track0_length'] >= 2. * blob_radius))

            # Verbosing
            logger.info('  Num final tracks: {:2}  -->  tracks_filter: {}' \
                        .format(event_data['num_tracks'], event_data['tracks_filter']))

            ### For those events passing the tracks filter:
            if event_data['tracks_filter']:

                # Getting the blob energies of the track with highest energy
                event_data['blob1_E'], event_data['blob2_E'] = \
                    blob_energies(event_sorted_tracks[0][2], blob_radius)

                # Applying the blobs filter
                event_data['blobs_filter'] = (event_data['blob2_E'] > blob_Eth)

                # Verbosing
                logger.info('  Blob 1 energy: {:4.1f} keV   Blob 2 energy: {:4.1f} keV  -->  Blobs filter: {}'\
                            .format(event_data['blob1_E']/units.keV, event_data['blob2_E']/units.keV,
                                    event_data['blobs_filter']))

                ### For those events passing the blobs filter:
                if event_data['blobs_filter']:

                    # Getting the total event smeared energy
                    event_smE = file_events.loc[event_number].smE

                    # Applying the ROI filter
                    event_data['roi_filter'] = ((event_smE >= roi_Emin) &
                                                (event_smE <= roi_Emax))

                    # Verbosing
                    logger.info('  Event energy: {:6.1f} keV  -->  ROI filter: {}'\
                                .format(event_smE / units.keV, event_data['roi_filter']))

            # Storing event_data
            extend_events_ana_dict(events_dict, event_data)

            # Verbosing
            if (not (analyzed_events % toUpdate_events)):
                print('* Num analyzed events: {}'.format(analyzed_events))
            if (analyzed_events == (10 * toUpdate_events)):
                toUpdate_events *= 10

    ### STORING ANALYSIS DATA
    print('* Total analyzed events: {}'.format(analyzed_events))

    # Storing events and voxels dataframes
    print('\n* Storing data in the output file ...\n  {}\n'.format(file_out))
    store_events_ana_dict(file_out, ana_group_name, events_reco_df,
                          events_dict)
    store_voxels_ana_dict(file_out, ana_group_name, voxels_reco_df,
                          voxels_dict)

    # Storing event counters as attributes
    tracks_filter_events = sum(events_dict['tracks_filter'])
    blobs_filter_events = sum(events_dict['blobs_filter'])
    roi_filter_events = sum(events_dict['roi_filter'])

    store_events_ana_counters(oFile, ana_group_name, simulated_events,
                              stored_events, smE_filter_events,
                              fid_filter_events, tracks_filter_events,
                              blobs_filter_events, roi_filter_events)

    ### Ending ...
    oFile.close()
    print('* Analysis done !!\n')

    print('''* Event counters:
  Simulated events:     {0:9}
  Stored events:        {1:9}
  smE_filter events:    {2:9}
  fid_filter events:    {3:9}
  tracks_filter events: {4:9}
  blobs_filter events:  {5:9}
  roi_filter events:    {6:9}'''.format(simulated_events, stored_events,
                                        smE_filter_events, fid_filter_events,
                                        tracks_filter_events,
                                        blobs_filter_events,
                                        roi_filter_events))
df = pd.read_csv("data_1000keV_local.csv",
                 usecols=["event_number", "x", "y", "z"])

mask = df.event_number < 20
df = df[mask]

trk_lengths = []
for i in range(df.event_number.max() + 1):
    #df_i = df[df.event_number == i]
    hit_list = [
        BHit(row.x, row.y, row.z, 1.)
        for indx, row in df[df.event_number == i].iterrows()
    ]
    voxels = plf.voxelize_hits(hit_list, np.array((1., 1., 1.)))
    tracks = plf.make_track_graphs(voxels)

    all_lengths = []
    for j in np.arange(len(tracks)):
        all_lengths.append(plf.length(tracks[j]))

    trk_lengths.append(max(all_lengths))

plt.figure(0)
plt.hist(trk_lengths, range=(0, 200), bins=70)
plt.xlabel("Track length (mm)")
plt.savefig(
    "/data5/users/miryam/temp/voxel/img/voxel_track_length_1000keV_local_20events.pdf"
)
plt.close(0)
Beispiel #5
0
def create_tracks_with_skel_extremes(vox_size, energy_type, strict_vox_size,
                                     blob_radius, df_extr, hitc):
    voxels = plf.voxelize_hits(hitc.hits, vox_size, strict_vox_size,
                               energy_type)
    tracks = plf.make_track_graphs(voxels)

    df = pd.DataFrame(columns=[
        'event', 'trackID', 'energy', 'length', 'numb_of_voxels',
        'numb_of_hits', 'numb_of_tracks', 'x_min', 'y_min', 'z_min', 'x_max',
        'y_max', 'z_max', 'r_max', 'x_ave', 'y_ave', 'z_ave', 'extreme1_x',
        'extreme1_y', 'extreme1_z', 'extreme2_x', 'extreme2_y', 'extreme2_z',
        'blob1_x', 'blob1_y', 'blob1_z', 'blob2_x', 'blob2_y', 'blob2_z',
        'eblob1', 'eblob2', 'ovlp_blob_energy', 'vox_size_x', 'vox_size_y',
        'vox_size_z'
    ])

    if (len(voxels) == 0):
        return df

    vox_size_x = voxels[0].size[0]
    vox_size_y = voxels[0].size[1]
    vox_size_z = voxels[0].size[2]

    def get_track_energy(track):
        return sum([vox.Ehits for vox in track.nodes()])

    #sort tracks in energy
    tracks = sorted(tracks, key=get_track_energy, reverse=True)

    track_hits = []

    for c, t in enumerate(tracks, 0):
        tID = c
        energy = get_track_energy(t)
        length = plf.length(t)
        numb_of_hits = len([h for vox in t.nodes() for h in vox.hits])
        numb_of_voxels = len(t.nodes())
        numb_of_tracks = len(tracks)

        min_x = min([h.X for v in t.nodes() for h in v.hits])
        max_x = max([h.X for v in t.nodes() for h in v.hits])
        min_y = min([h.Y for v in t.nodes() for h in v.hits])
        max_y = max([h.Y for v in t.nodes() for h in v.hits])
        min_z = min([h.Z for v in t.nodes() for h in v.hits])
        max_z = max([h.Z for v in t.nodes() for h in v.hits])
        max_r = max([
            np.sqrt(h.X * h.X + h.Y * h.Y) for v in t.nodes() for h in v.hits
        ])

        pos = [h.pos for v in t.nodes() for h in v.hits]
        e = [getattr(h, energy_type.value) for v in t.nodes() for h in v.hits]
        ave_pos = np.average(pos, weights=e, axis=0)

        # classic paolina extremes
        extr1, extr2 = plf.find_extrema(t)
        extr1_pos = extr1.XYZ
        extr2_pos = extr2.XYZ

        t_extr = df_extr[df_extr.trackID == tID]
        if len(t_extr) == 0:
            blob_pos1 = np.array([1.e6, 1.e6, 1.e6])
            blob_pos2 = np.array([1.e6, 1.e6, 1.e6])
            eblob1 = -1
            eblob2 = -1
            overlap = -1
        else:
            blob_pos1 = np.array([
                t_extr.skel_extr1_x.values[0], t_extr.skel_extr1_y.values[0],
                t_extr.skel_extr1_z.values[0]
            ])
            blob_pos2 = np.array([
                t_extr.skel_extr2_x.values[0], t_extr.skel_extr2_y.values[0],
                t_extr.skel_extr2_z.values[0]
            ])
            e_blob1, e_blob2, hits_blob1, hits_blob2, blob_pos1, blob_pos2 = blob_energies_hits(
                t, blob_radius, blob_pos1, blob_pos2)
            overlap = sum(
                [h.E for h in set(hits_blob1).intersection(set(hits_blob2))])

        list_of_vars = [
            hitc.event, tID, energy, length, numb_of_voxels, numb_of_hits,
            numb_of_tracks, min_x, min_y, min_z, max_x, max_y, max_z, max_r,
            ave_pos[0], ave_pos[1], ave_pos[2], extr1_pos[0], extr1_pos[1],
            extr1_pos[2], extr2_pos[0], extr2_pos[1], extr2_pos[2],
            blob_pos1[0], blob_pos1[1], blob_pos1[2], blob_pos2[0],
            blob_pos2[1], blob_pos2[2], e_blob1, e_blob2, overlap, vox_size_x,
            vox_size_y, vox_size_z
        ]
        df.loc[c] = list_of_vars
        try:
            types_dict
        except NameError:
            types_dict = dict(zip(df.columns, [type(x) for x in list_of_vars]))

    #change dtype of columns to match type of variables
    df = df.apply(lambda x: x.astype(types_dict[x.name]))

    return df
Beispiel #6
0
def fanal_ana(det_name,       # Detector name: 'new', 'next100', 'next500'
              event_type,     # Event type: 'bb0nu', 'Tl208', 'Bi214'
              fwhm,           # FWHM at Qbb
              spatial_def,    # Spatial definition: 'low', 'high'
              voxel_Eth,      # Voxel energy threshold
              track_Eth,      # Track energy threshold
              max_num_tracks, # Maximum number of tracks
              blob_radius,    # Blob radius
              blob_Eth,       # Blob energy threshold
              roi_Emin,       # ROI minimum energy
              roi_Emax,       # ROI maximum energy
              files_in,       # Input files
              event_range,    # Range of events to analyze: all, ... ??
              file_out,       # Output file
              compression,    # Compression of output file: 'ZLIB1', 'ZLIB4',
                              # 'ZLIB5', 'ZLIB9', 'BLOSC5', 'BLZ4HC5'
              verbosity_level):

    ### LOGGER
    logger = get_logger('FanalAna', verbosity_level)

    ### DETECTOR NAME
    det_name = getattr(DetName, det_name)

    ### SPATIAL DEFINITION
    spatial_def = getattr(SpatialDef, spatial_def)


    ### PRINTING GENERAL INFO
    print('\n***********************************************************************************')
    print('***** Detector: {}'.format(det_name.name))
    print('***** Analizing {} events'.format(event_type))
    print('***** Energy Resolution: {:.2f}% FWFM at Qbb'.format(fwhm / units.perCent))
    print('***** Spatial definition: {}'.format(spatial_def.name))
    print('***********************************************************************************\n')

    print('* Voxel Eth: {:4.1f} keV   Track Eth: {:4.1f} keV   Max Num Tracks: {}\n'
          .format(voxel_Eth/units.keV, track_Eth/units.keV, max_num_tracks))
    print('* Blob radius: {:.1f} mm   Blob Eth: {:4.1f} keV\n'
          .format(blob_radius, blob_Eth / units.keV))
    print('* ROI limits: [{:4.1f}, {:4.1f}] keV\n'
          .format(roi_Emin/units.keV, roi_Emax/units.keV))


    ### INPUT RECONSTRUCTION FILE AND GROUP
    reco_group_name = get_reco_group_name(fwhm/units.perCent, spatial_def)
    print('* Input reco file name:', files_in)
    print('  Reco group name: {}\n'.format(reco_group_name))


    ### OUTPUT FILE, ITS GROUPS & ATTRIBUTES
    # Output analysis file
    oFile = tb.open_file(file_out, 'w', filters=tbl_filters(compression))

    # Analysis group Name
    ana_group_name = get_ana_group_name(fwhm/units.perCent, spatial_def)
    oFile.create_group('/', 'FANALIC')
    oFile.create_group('/FANALIC', ana_group_name[9:])

    print('* Output analysis file name:', file_out)
    print('  Ana group name: {}\n'.format(ana_group_name))

    # Attributes
    oFile.set_node_attr(ana_group_name, 'input_reco_file', files_in[0])
    oFile.set_node_attr(ana_group_name, 'input_reco_group', reco_group_name)
    oFile.set_node_attr(ana_group_name, 'event_type', event_type)
    oFile.set_node_attr(ana_group_name, 'energy_resolution', fwhm / units.perCent)
    oFile.set_node_attr(ana_group_name, 'voxel_Eth', voxel_Eth)
    oFile.set_node_attr(ana_group_name, 'track_Eth', track_Eth)
    oFile.set_node_attr(ana_group_name, 'max_num_tracks', max_num_tracks)
    oFile.set_node_attr(ana_group_name, 'blob_radius', blob_radius)
    oFile.set_node_attr(ana_group_name, 'blob_Eth', blob_Eth)
    oFile.set_node_attr(ana_group_name, 'roi_Emin', roi_Emin)
    oFile.set_node_attr(ana_group_name, 'roi_Emax', roi_Emax)


    ### DATA TO STORE
    # Dictionaries for events & voxels data
    events_dict = get_events_ana_dict()
    voxels_dict = get_voxels_ana_dict()


    ### ANALYSIS PROCEDURE

    # Getting the events & voxels data from the reconstruction phase
    # This is the option a little bit slower that requires less memory ... (TO BE CHECKED!!)
    # event_numbers_toAnalize = pd.read_hdf(files_in[0], reco_group_name + '/events',
    #                                      where=['fid_filter = True']).index
    # And this is the fastest option requiring more memory
    events_df = pd.read_hdf(files_in[0], reco_group_name + '/events')
    voxels_df = pd.read_hdf(files_in[0], reco_group_name + '/voxels')

    # Identifying as negligible all the voxels with energy lower than threshold
    voxels_df['negli'] = voxels_df.E < voxel_Eth
    print('* Total Voxels in File: {0}     Negligible Voxels (below {1:3.1f} keV): {2}\n'
          .format(len(voxels_df), voxel_Eth / units.keV,
                  len(voxels_df[voxels_df.negli == True])))

    # Analyzing only the fiducial events ...
    print('* Analyzing events ...\n')

    # Counter of analyzed events for verbosing pourpouses
    num_analyzed_events = 0

    # Looping through all the events that passed the fiducial filter
    for event_id in events_df[events_df.fid_filter].index:

        # Updating counter of analyzed events
        num_analyzed_events += 1
        if not int(str(num_analyzed_events)[-int(math.log10(num_analyzed_events)):]):
            print('* Num analyzed events: {}'.format(num_analyzed_events))

        # Verbosing
        logger.info('Analyzing event Id: {0} ...'.format(event_id))

        # Getting the voxels of current event and their sizes
        event_voxels = voxels_df[voxels_df.event_id == event_id]
        num_event_voxels = len(event_voxels)
        num_event_voxels_negli = len(event_voxels[event_voxels.negli == True])
        event_data = events_df.loc[event_id]
        voxel_dimensions = (event_data.voxel_sizeX, event_data.voxel_sizeY,
                            event_data.voxel_sizeZ)

        logger.info('  Total Voxels: {}   Negli. Voxels: {}   Voxels Size: ({:3.1f}, {:3.1f}, {:3.1f}) mm'
                    .format(num_event_voxels, num_event_voxels_negli,
                            voxel_dimensions[0], voxel_dimensions[1],
                            voxel_dimensions[2]))

        # If there is any negligible Voxel,
        # distribute its energy between its neighbours,
        # if not, all voxels maintain their previous energies
        if num_event_voxels_negli:
            event_voxels_newE = get_new_energies(event_voxels)
        else:
            event_voxels_newE = event_voxels.E.tolist()

        # Translate fanalIC voxels info to IC voxels to make tracks
        ic_voxels = [Voxel(event_voxels.iloc[i].X, event_voxels.iloc[i].Y,
                           event_voxels.iloc[i].Z, event_voxels_newE[i],
                           voxel_dimensions) for i in range(num_event_voxels)]

        # Make tracks
        event_tracks = make_track_graphs(ic_voxels)
        num_event_tracks = len(event_tracks)
        logger.info('  Num initial tracks: {:2}'.format(num_event_tracks))

        # Appending to every voxel, the track it belongs to
        event_voxels_tracks = get_voxel_track_relations(event_voxels, event_tracks)

        # Appending info of this event voxels
        extend_voxels_ana_data(voxels_dict, event_voxels.index,
                               event_voxels_newE, event_voxels_tracks)

        # Processing tracks: Getting energies, sorting and filtering ...
        event_sorted_tracks = process_tracks(event_tracks, track_Eth)
        num_event_tracks    = len(event_sorted_tracks)

        # Storing 3 hottest track info
        if num_event_tracks >= 1:
            track0_E      = event_sorted_tracks[0][0]
            track0_voxels = len(event_sorted_tracks[0][1].nodes())
            track0_length = track_length(event_sorted_tracks[0][1])
        else:
            track0_E = track0_voxels = track0_length = np.nan
        if num_event_tracks >= 2:
            track1_E      = event_sorted_tracks[1][0]
            track1_voxels = len(event_sorted_tracks[1][1].nodes())
            track1_length = track_length(event_sorted_tracks[1][1])
        else:
            track1_E = track1_voxels = track1_length = np.nan
        if num_event_tracks >= 3:
            track2_E      = event_sorted_tracks[2][0]
            track2_voxels = len(event_sorted_tracks[2][1].nodes())
            track2_length = track_length(event_sorted_tracks[2][1])
        else:
            track2_E = track2_voxels = track2_length = np.nan

        # Applying the tracks filter
        tracks_filter = ((num_event_tracks > 0) &
                         (num_event_tracks <= max_num_tracks))

        # Verbosing
        logger.info('  Num final tracks: {:2}  -->  tracks_filter: {}'
                    .format(num_event_tracks, tracks_filter))

        # For those events NOT passing the tracks filter:
        # Storing data of NON tracks_filter vents
        if not tracks_filter:
            extend_events_ana_data(events_dict, event_id, num_event_tracks,
                                   track0_E, track0_voxels, track0_length,
                                   track1_E, track1_voxels, track1_length,
                                   track2_E, track2_voxels, track2_length,
                                   tracks_filter)

        # Only for those events passing the tracks filter:
        else:
            # Getting the blob energies of the track with highest energy
            blobs_E = blob_energies(event_sorted_tracks[0][1], blob_radius)
            blob1_E = blobs_E[1]
            blob2_E = blobs_E[0]

            # Applying the blobs filter
            blobs_filter = (blob2_E > blob_Eth)

            # Verbosing
            logger.info('  Blob 1 energy: {:4.1f} keV   Blob 2 energy: {:4.1f} keV  -->  Blobs filter: {}'
                        .format(blob1_E/units.keV, blob2_E/units.keV, blobs_filter))

            # For those events NOT passing the blobs filter:
            # Storing data of NON blobs_filter vents
            if not blobs_filter:
                extend_events_ana_data(events_dict, event_id, num_event_tracks,
                                       track0_E, track0_voxels, track0_length,
                                       track1_E, track1_voxels, track1_length,
                                       track2_E, track2_voxels,  track2_length,
                                       tracks_filter, blob1_E = blob1_E,
                                       blob2_E = blob2_E, blobs_filter = blobs_filter)

            # Only for those events passing the blobs filter:
            else:
                # Getting the total event smeared energy
                event_smE = events_df.loc[event_id].smE

                # Applying the ROI filter
                roi_filter = ((event_smE >= roi_Emin) & (event_smE <= roi_Emax))

                # Verbosing
                logger.info('  Event energy: {:6.1f} keV  -->  ROI filter: {}'
                            .format(event_smE / units.keV, roi_filter))

                # Storing all the events (as this is the last filter)
                extend_events_ana_data(events_dict, event_id, num_event_tracks,
                                       track0_E, track0_voxels, track0_length,
                                       track1_E, track1_voxels, track1_length,
                                       track2_E, track2_voxels, track2_length,
                                       tracks_filter, blob1_E = blob1_E,
                                       blob2_E = blob2_E, blobs_filter = blobs_filter,
                                       roi_filter = roi_filter)


    ### STORING DATA
    # Storing events and voxels dataframes
    print('\n* Storing data in the output file ...\n  {}\n'.format(file_out))
    store_events_ana_data(file_out, ana_group_name, events_df, events_dict)
    store_voxels_ana_data(file_out, ana_group_name, voxels_df, voxels_dict)

    # Storing event counters as attributes
    tracks_filter_events, blobs_filter_events, roi_filter_events = \
        store_events_ana_counters(oFile, ana_group_name, events_df)


    ### Ending ...
    oFile.close()
    print('* Analysis done !!\n')

    # Printing analysis numbers
    with tb.open_file(files_in[0], mode='r') as iFile:
        simulated_events  = iFile.get_node_attr(reco_group_name, 'simulated_events')
        stored_events     = iFile.get_node_attr(reco_group_name, 'stored_events')
        smE_filter_events = iFile.get_node_attr(reco_group_name, 'smE_filter_events')
        fid_filter_events = iFile.get_node_attr(reco_group_name, 'fid_filter_events')

    print('''* Event counters:
  Simulated events:     {0:9}
  Stored events:        {1:9}
  smE_filter events:    {2:9}
  fid_filter events:    {3:9}
  tracks_filter events: {4:9}
  blobs_filter events:  {5:9}
  roi_filter events:    {6:9}\n'''
    .format(simulated_events, stored_events, smE_filter_events,
            fid_filter_events, tracks_filter_events, blobs_filter_events,
            roi_filter_events))
    def create_extract_track_blob_info(hitc):
        df = pd.DataFrame(columns=list(types_dict_tracks.keys()))
        if len(hitc.hits) > max_num_hits:
            return df, hitc, True
        #track_hits is a new Hitcollection object that contains hits belonging to tracks, and hits that couldnt be corrected
        track_hitc = evm.HitCollection(hitc.event, hitc.time)
        out_of_map = np.any(np.isnan([h.Ep for h in hitc.hits]))
        if out_of_map:
            #add nan hits to track_hits, the track_id will be -1
            track_hitc.hits.extend([h for h in hitc.hits if np.isnan(h.Ep)])
            hits_without_nan = [h for h in hitc.hits if np.isfinite(h.Ep)]
            #create new Hitcollection object but keep the name hitc
            hitc = evm.HitCollection(hitc.event, hitc.time)
            hitc.hits = hits_without_nan

        if len(hitc.hits) > 0:
            voxels = plf.voxelize_hits(hitc.hits, vox_size, strict_vox_size,
                                       evm.HitEnergy.Ep)
            (mod_voxels, dropped_voxels) = plf.drop_end_point_voxels(
                voxels, energy_threshold, min_voxels)
            tracks = plf.make_track_graphs(mod_voxels)

            for v in dropped_voxels:
                track_hitc.hits.extend(v.hits)

            vox_size_x = voxels[0].size[0]
            vox_size_y = voxels[0].size[1]
            vox_size_z = voxels[0].size[2]
            del (voxels)
            #sort tracks in energy
            tracks = sorted(tracks, key=plf.get_track_energy, reverse=True)

            track_hits = []
            for c, t in enumerate(tracks, 0):
                tID = c
                energy = plf.get_track_energy(t)
                length = plf.length(t)
                numb_of_hits = len([h for vox in t.nodes() for h in vox.hits])
                numb_of_voxels = len(t.nodes())
                numb_of_tracks = len(tracks)
                pos = [h.pos for v in t.nodes() for h in v.hits]
                x, y, z = map(np.array, zip(*pos))
                r = np.sqrt(x**2 + y**2)

                e = [h.Ep for v in t.nodes() for h in v.hits]
                ave_pos = np.average(pos, weights=e, axis=0)
                ave_r = np.average(r, weights=e, axis=0)
                extr1, extr2 = plf.find_extrema(t)
                extr1_pos = extr1.XYZ
                extr2_pos = extr2.XYZ

                blob_pos1, blob_pos2 = plf.blob_centres(t, blob_radius)

                e_blob1, e_blob2, hits_blob1, hits_blob2 = plf.blob_energies_and_hits(
                    t, blob_radius)
                overlap = float(
                    sum(h.Ep for h in set(hits_blob1).intersection(
                        set(hits_blob2))))
                list_of_vars = [
                    hitc.event, tID, energy, length, numb_of_voxels,
                    numb_of_hits, numb_of_tracks,
                    min(x),
                    min(y),
                    min(z),
                    min(r),
                    max(x),
                    max(y),
                    max(z),
                    max(r), *ave_pos, ave_r, *extr1_pos, *extr2_pos,
                    *blob_pos1, *blob_pos2, e_blob1, e_blob2, overlap,
                    vox_size_x, vox_size_y, vox_size_z
                ]

                df.loc[c] = list_of_vars

                for vox in t.nodes():
                    for hit in vox.hits:
                        hit.track_id = tID
                        track_hits.append(hit)

            #change dtype of columns to match type of variables
            df = df.apply(lambda x: x.astype(types_dict_tracks[x.name]))
            track_hitc.hits.extend(track_hits)
        return df, mod_voxels, track_hitc, out_of_map
    def create_extract_track_blob_info(hitc):
        voxels = plf.voxelize_hits(hitc.hits, vox_size, strict_vox_size,
                                   energy_type)
        tracks = plf.make_track_graphs(voxels)

        df = pd.DataFrame(columns=[
            'event', 'trackID', 'energy', 'length', 'numb_of_voxels',
            'numb_of_hits', 'numb_of_tracks', 'x_min', 'y_min', 'z_min',
            'x_max', 'y_max', 'z_max', 'r_max', 'x_ave', 'y_ave', 'z_ave',
            'extreme1_x', 'extreme1_y', 'extreme1_z', 'extreme2_x',
            'extreme2_y', 'extreme2_z', 'blob1_x', 'blob1_y', 'blob1_z',
            'blob2_x', 'blob2_y', 'blob2_z', 'eblob1', 'eblob2',
            'ovlp_blob_energy', 'vox_size_x', 'vox_size_y', 'vox_size_z'
        ])

        if (len(voxels) == 0):
            return df, None

        vox_size_x = voxels[0].size[0]
        vox_size_y = voxels[0].size[1]
        vox_size_z = voxels[0].size[2]

        def get_track_energy(track):
            return sum([vox.Ehits for vox in track.nodes()])

        #sort tracks in energy
        tracks = sorted(tracks, key=get_track_energy, reverse=True)

        track_hits = []

        for c, t in enumerate(tracks, 0):
            tID = c
            energy = get_track_energy(t)
            length = plf.length(t)
            numb_of_hits = len([h for vox in t.nodes() for h in vox.hits])
            numb_of_voxels = len(t.nodes())
            numb_of_tracks = len(tracks)

            min_x = min([h.X for v in t.nodes() for h in v.hits])
            max_x = max([h.X for v in t.nodes() for h in v.hits])
            min_y = min([h.Y for v in t.nodes() for h in v.hits])
            max_y = max([h.Y for v in t.nodes() for h in v.hits])
            min_z = min([h.Z for v in t.nodes() for h in v.hits])
            max_z = max([h.Z for v in t.nodes() for h in v.hits])
            max_r = max([
                np.sqrt(h.X * h.X + h.Y * h.Y) for v in t.nodes()
                for h in v.hits
            ])

            pos = [h.pos for v in t.nodes() for h in v.hits]
            e = [
                getattr(h, energy_type.value) for v in t.nodes()
                for h in v.hits
            ]
            ave_pos = np.average(pos, weights=e, axis=0)

            extr1, extr2 = plf.find_extrema(t)
            extr1_pos = extr1.XYZ
            extr2_pos = extr2.XYZ

            blob_pos1, blob_pos2 = plf.blob_centres(t, blob_radius)

            e_blob1, e_blob2, hits_blob1, hits_blob2 = plf.blob_energies_and_hits(
                t, blob_radius)
            overlap = False
            overlap = sum(
                [h.E for h in set(hits_blob1).intersection(hits_blob2)])
            list_of_vars = [
                hitc.event, tID, energy, length, numb_of_voxels, numb_of_hits,
                numb_of_tracks, min_x, min_y, min_z, max_x, max_y, max_z,
                max_r, ave_pos[0], ave_pos[1], ave_pos[2], extr1_pos[0],
                extr1_pos[1], extr1_pos[2], extr2_pos[0], extr2_pos[1],
                extr2_pos[2], blob_pos1[0], blob_pos1[1], blob_pos1[2],
                blob_pos2[0], blob_pos2[1], blob_pos2[2], e_blob1, e_blob2,
                overlap, vox_size_x, vox_size_y, vox_size_z
            ]

            df.loc[c] = list_of_vars
            try:
                types_dict
            except NameError:
                types_dict = dict(
                    zip(df.columns, [type(x) for x in list_of_vars]))

            for vox in t.nodes():
                for hit in vox.hits:
                    hit.track_id = tID
                    track_hits.append(hit)

        track_hitc = evm.HitCollection(hitc.event, hitc.time)
        track_hitc.hits = track_hits
        #change dtype of columns to match type of variables
        df = df.apply(lambda x: x.astype(types_dict[x.name]))

        return df, track_hitc
Beispiel #9
0
        events_in += len(hits_evt)
        for nevt, hitc in hits_evt.items():

            if bad_event[nevt]:
                not_fid += 1
                continue

            tot_e = sum(h.E for h in hitc)

            voxels = plf.voxelize_hits(hitc, vox_size)
            mod_voxels = plf.drop_end_point_voxels(voxels,
                                                   voxel_cut,
                                                   min_vxls=3)

            ### Make tracks with the new voxels
            trks = plf.make_track_graphs(mod_voxels)

            ### Is it a e+e- events?
            positron = False
            for _, particle in p_dict[nevt].items():
                if (particle.name == 'e+') & (len(particle.hits) > 0):
                    positron = True

            for c, t in enumerate(trks, 0):
                etrk = sum(vox.E for vox in t.nodes())
                n_hits = sum(len(v.hits) for v in t.nodes())

                extr1, extr2 = plf.find_extrema(t)
                e_blob1, e_blob2, hits_blob1, hits_blob2, pos1, pos2 = plf.blob_energies_hits_and_centres(
                    t, blob_radius)
Beispiel #10
0
def analyze_bb_event_ic(
        detector: Detector, event_id: int, params: BBAnalysisParams,
        fiducial_checker: Callable, event_mcParts: pd.DataFrame,
        event_mcHits: pd.DataFrame) -> Tuple[Event, TrackList, VoxelList]:
    """
    It assess the global acceptance factor after fiducial, topology and ROI cuts
    based on the paolina functions implemented into IC.
    """
    # Data to be filled
    event_data = Event()
    tracks_data = TrackList()
    voxels_data = VoxelList()

    # Storing basic MC data
    event_data.event_id = event_id
    event_data.num_mcParts = len(event_mcParts)
    event_data.num_mcHits = len(event_mcHits)

    logger.info(f"Num mcParticles: {event_data.num_mcParts:3}   " + \
                f"Num mcHits: {event_data.num_mcHits:3}   ")

    # Processing MC data
    event_data.mc_energy, event_data.mc_filter = \
        check_mc_data(event_mcHits, params.buffer_Eth, params.e_min, params.e_max)
    if not event_data.mc_filter: return event_data, tracks_data, voxels_data

    ### Continue analysis of events passing the mc_filter ###
    # Reconstruct hits
    active_mcHits = event_mcHits[event_mcHits.label == 'ACTIVE']
    recons_hits = reconstruct_hits(detector, active_mcHits,
                                   event_data.mc_energy, params.fwhm,
                                   params.trans_diff, params.long_diff)

    # Event smeared energy
    event_data.sm_energy = recons_hits.energy.sum()
    event_data.energy_filter = (params.e_min <= event_data.sm_energy <=
                                params.e_max)
    logger.info(f"smE: {event_data.sm_energy/units.keV:.1f} keV   " + \
                f"ENERGY filter: {event_data.energy_filter}")
    if not event_data.energy_filter:
        return event_data, tracks_data, voxels_data

    ### Continue analysis of events passing the energy_filter ###
    # Creating the IChits from reconstructed hits
    ic_hits = recons_hits.apply(lambda hit: \
        MCHit((hit.x, hit.y, hit.z), hit.time, hit.energy, 'ACTIVE'), axis=1).tolist()

    # Voxelizing using the ic_hits ...
    ic_voxels = voxelize_hits(
        ic_hits,
        [params.voxel_size_x, params.voxel_size_y, params.voxel_size_z],
        params.strict_voxel_size)

    # Cleaning voxels with energy < voxel_Eth
    ic_voxels = clean_voxels(ic_voxels, params.voxel_Eth)

    event_data.num_voxels = len(ic_voxels)
    eff_voxel_size = ic_voxels[0].size
    event_data.voxel_size_x = eff_voxel_size[0]
    event_data.voxel_size_y = eff_voxel_size[1]
    event_data.voxel_size_z = eff_voxel_size[2]
    logger.info(
        f"Num Voxels: {event_data.num_voxels:3}  of size: {eff_voxel_size} mm")

    # Check fiduciality
    event_data.veto_energy, event_data.fiduc_filter = \
        check_event_fiduciality(fiducial_checker, ic_voxels, params.veto_Eth)
    logger.info(f"Veto_E: {event_data.veto_energy/units.keV:.1f} keV   " + \
                f"FIDUC filter: {event_data.fiduc_filter}")

    if not event_data.fiduc_filter:
        # Storing voxels without track-id info
        for voxel_id in range(len(ic_voxels)):
            voxels_data.add(
                Voxel.from_icVoxel(event_id, -1, voxel_id,
                                   ic_voxels[voxel_id]))
        logger.debug(voxels_data)
        return event_data, tracks_data, voxels_data

    ### Continue analysis of events passing the fiduc_filter ###
    # Make tracks
    ic_tracks = make_track_graphs(ic_voxels)

    # Storing tracks from ic_tracks
    for track_id in range(len(ic_tracks)):
        ic_track = ic_tracks[track_id]
        tracks_data.add(Track.from_icTrack(event_id, track_id, ic_track))

        # Storing voxels from ic_voxels
        ic_voxels = list(ic_track.nodes())
        for voxel_id in range(len(ic_voxels)):
            voxels_data.add(
                Voxel.from_icVoxel(event_id, track_id, voxel_id,
                                   ic_voxels[voxel_id]))

    logger.debug(voxels_data)

    event_data.num_tracks = tracks_data.len()

    event_data.track_filter = (
        (event_data.num_tracks > 0) &
        (event_data.num_tracks <= params.max_num_tracks))

    logger.info(f"Num tracks: {event_data.num_tracks:3}  ->" + \
                f"  TRACK filter: {event_data.track_filter}")

    if not event_data.track_filter: return event_data, tracks_data, voxels_data

    ### Continue analysis of events passing the track_filter ###
    the_track = tracks_data.tracks[0]

    # Getting & Storing Blobs info
    blob1_energy, blob2_energy, blob1_hits, blob2_hits, blob1_pos, blob2_pos = \
        blob_energies_hits_and_centres(ic_tracks[0], params.blob_radius)
    blob1_pos, blob2_pos = XYZ.from_array(blob1_pos), XYZ.from_array(blob2_pos)

    the_track.blob1_energy, the_track.blob1_num_hits = blob1_energy, len(
        blob1_hits)
    the_track.blob1_x, the_track.blob1_y, the_track.blob1_z = \
        blob1_pos.x, blob1_pos.y, blob1_pos.z
    the_track.blob2_energy, the_track.blob2_num_hits = blob2_energy, len(
        blob2_hits)
    the_track.blob2_x, the_track.blob2_y, the_track.blob2_z = \
        blob2_pos.x, blob2_pos.y, blob2_pos.z

    the_track.ovlp_energy = \
        float(sum(hit.E for hit in set(blob1_hits).intersection(set(blob2_hits))))

    # Getting & Storing True extrema info
    ext1, ext2 = get_true_extrema(event_mcParts, params.event_type)
    ext1, ext2 = order_true_extrema(ext1, ext2, blob1_pos, blob2_pos)

    the_track.t_ext1_x, the_track.t_ext1_y, the_track.t_ext1_z = ext1.x, ext1.y, ext1.z
    the_track.t_ext2_x, the_track.t_ext2_y, the_track.t_ext2_z = ext2.x, ext2.y, ext2.z

    # Storing Track info in event data
    event_data.track_length = the_track.length
    event_data.blob1_energy, event_data.blob2_energy = blob1_energy, blob2_energy

    logger.info(tracks_data)

    # Applying the blob filter
    event_data.blob_filter = ((event_data.blob2_energy > params.blob_Eth) &
                              (the_track.ovlp_energy == 0.))

    logger.info(f"Blob 1 energy: {event_data.blob1_energy/units.keV:4.1f} keV " + \
                f"  Blob 2 energy: {event_data.blob2_energy/units.keV:4.1f} keV"  + \
                f"  Overlap: {the_track.ovlp_energy/units.keV:4.1f} keV"  + \
                f"  ->  BLOB filter: {event_data.blob_filter}")

    if not event_data.blob_filter: return event_data, tracks_data, voxels_data

    ### Continue analysis of events passing the blob_filter ###
    # Applying the ROI filter
    event_data.roi_filter = ((event_data.sm_energy >= params.roi_Emin) &
                             (event_data.sm_energy <= params.roi_Emax))

    logger.info(f"Event energy: {event_data.sm_energy/units.keV:6.1f} keV" + \
                f"  ->  ROI filter: {event_data.roi_filter}")

    return event_data, tracks_data, voxels_data