示例#1
0
def compute_choice_grasp_dur(LogDf, SessionDf):
    " FIXME - LAST CHOICE GRASP DUR IS NEVER COMPUTED SINCE THERE IS NO TRIAL AVAILABLE"

    # Trials spanning from choice available to end of ITI
    TrialSpans = bhv.get_spans_from_names(LogDf, "CHOICE_STATE", "TRIAL_AVAILABLE_STATE")

    TrialDfs = []
    for i, row in TrialSpans.iterrows():
        TrialDfs.append(bhv.time_slice(LogDf, row['t_on'], row['t_off']))

    # Compute grasp_dur for every trial
    grasp_dur = pd.Series()
    for TrialDf in TrialDfs:
        if has_choice(TrialDf).values:

            left_reach_spansDf = bhv.get_spans_from_names(TrialDf, 'REACH_LEFT_ON', 'REACH_LEFT_OFF')
            right_reach_spansDf = bhv.get_spans_from_names(TrialDf, 'REACH_RIGHT_ON', 'REACH_RIGHT_OFF')

            merge_spansDf = pd.concat([left_reach_spansDf, right_reach_spansDf]).reset_index(drop = True)

            choice_time = bhv.get_events_from_name(TrialDf, 'CHOICE_EVENT')['t'].values[0]
            
            # Which reach triggered the choice? The one which corresponding spansDf contains choice_time
            for row in merge_spansDf.iterrows():
                if (row[1]['t_on'] < choice_time < row[1]['t_off']):
                    grasp_dur = grasp_dur.append(pd.Series(row[1]['dt']))

        else: grasp_dur = grasp_dur.append(pd.Series(np.NaN))

    # FIXME Adding last trial manually
    grasp_dur = grasp_dur.append(pd.Series(np.NaN))

    SessionDf['grasp_dur'] = grasp_dur.reset_index(drop = True)

    return SessionDf
示例#2
0
def plot_trajectories_with_marker(LogDf,
                                  SessionDf,
                                  labelsDf,
                                  align_event,
                                  pre,
                                  post,
                                  animal_id,
                                  axes=None):
    " Plots trajectories from align event until choice with marker"

    if axes is None:
        _, axes = plt.subplots()

    ts_align = LogDf.loc[LogDf['name'] == align_event, 't'].values[0]

    left_paw, right_paw = [], []

    for t_align in ts_align:
        lDf = bhv.time_slice(labelsDf, t_align - pre, t_align + post)

        #left_paw.append(lDf['x'].values)
        #right_paw.append(lDf['y'].values)

    #Fx = np.array(Fx).T
    #Fy = np.array(Fy).T

    return axes
示例#3
0
def get_SessionDf(LogDf, metrics, trial_entry_event="TRIAL_AVAILABLE_STATE", trial_exit_event="ITI_STATE"):

    TrialSpans = bhv.get_spans_from_names(LogDf, trial_entry_event, trial_exit_event)

    TrialDfs = []
    for i, row in tqdm(TrialSpans.iterrows(),position=0, leave=True):
        TrialDfs.append(bhv.time_slice(LogDf, row['t_on'], row['t_off']))
    
    SessionDf = bhv.parse_trials(TrialDfs, metrics)
    return SessionDf, TrialDfs
示例#4
0
def reaches_during_delay_across_sess(animal_fd_path, tasks_names,
                                     init_day_idx):

    SessionsDf = utils.get_sessions(animal_fd_path)
    animal_meta = pd.read_csv(animal_fd_path / 'animal_meta.csv')

    # Filter sessions to the ones of the task we want to see
    FilteredSessionsDf = pd.concat(
        [SessionsDf.groupby('task').get_group(name) for name in tasks_names])
    log_paths = [
        Path(path) / 'arduino_log.txt' for path in FilteredSessionsDf['path']
    ]

    fig, axes = plt.subplots(ncols=2, figsize=[6, 4], sharey=True, sharex=True)
    colors = sns.color_palette(palette='turbo', n_colors=len(log_paths))

    for j, log_path in enumerate(log_paths[init_day_idx:]):

        LogDf = bhv.get_LogDf_from_path(log_path)

        # ADD SINGLE GO_CUE_EVENT
        LogDf = bhv.add_go_cue_LogDf(LogDf)
        TrialSpans = bhv.get_spans_from_names(LogDf, "TRIAL_ENTRY_STATE",
                                              "ITI_STATE")

        TrialDfs = []
        for i, row in tqdm(TrialSpans.iterrows(), position=0, leave=True):
            TrialDfs.append(bhv.time_slice(LogDf, row['t_on'], row['t_off']))

        metrics = (met.get_start, met.get_stop, met.get_correct_side,
                   met.get_outcome, met.get_interval_category,
                   met.get_chosen_side, met.has_reach_left,
                   met.has_reach_right)
        SessionDf = bhv.parse_trials(TrialDfs, metrics)

        CDF_of_reaches_during_delay(SessionDf,
                                    TrialDfs,
                                    axes=axes,
                                    color=colors[j],
                                    alpha=0.75,
                                    label='day ' + str(j + 1))

    fig.suptitle('CDF of first reach split on trial type \n' +
                 animal_meta['value'][5] + '-' + animal_meta['value'][0])

    axes[0].set_ylabel('Fraction of trials')
    axes[0].legend(frameon=False, fontsize='x-small')
    fig.tight_layout()

    return axes
示例#5
0
def plot_reaches_window_aligned_on_event(LogDf,
                                         align_event,
                                         pre,
                                         post,
                                         bin_width,
                                         axes=None):
    " Plots the reaches around a [-pre,post] window aligned to an event "

    if axes is None:
        fig, axes = plt.subplots()

    no_bins = round((post + pre) / bin_width)

    t_aligns = LogDf[LogDf['name'] == align_event]['t']

    left_reaches, right_reaches = np.empty([1, 0]), np.empty([1, 0])
    for t_align in t_aligns:

        sliceDf = bhv.time_slice(LogDf, t_align - pre, t_align + post)

        left_reaches = np.append(
            left_reaches,
            bhv.get_events_from_name(sliceDf, 'REACH_LEFT_ON').values -
            np.array(t_align))
        right_reaches = np.append(
            right_reaches,
            bhv.get_events_from_name(sliceDf, 'REACH_RIGHT_ON').values -
            np.array(t_align))

    # Fancy plotting
    axes.hist(left_reaches,
              bins=no_bins,
              range=(-pre, post),
              alpha=0.5,
              label='Left reaches')
    axes.hist(right_reaches,
              bins=no_bins,
              range=(-pre, post),
              alpha=0.5,
              label='Right reaches')
    plt.setp(axes,
             xticks=np.arange(-pre, post + 1, 1000),
             xticklabels=np.arange(-pre / 1000, post / 1000 + 0.1, 1))
    axes.axvline(x=0, c='black')
    axes.set_xlabel('Time (s)')
    axes.set_ylabel('No. Reaches')
    axes.set_title(str(align_event))
    axes.legend()

    return axes
示例#6
0
def plot_all_trajectories(TrialDfs, ax=None):
    for i, TrialDf in enumerate(TrialDfs):
        if TrialDf.shape[0] > 0:
            t_on = TrialDf.iloc[0]['t']
            t_off = TrialDf.iloc[-1]['t']

            # trial by trial colors
            bp_cols = {}
            cmaps = dict(zip(bodyparts,['viridis','magma']))
            for bp in bodyparts:
                c = sns.color_palette(cmaps[bp],as_cmap=True)(sp.rand())
                bp_cols[bp] = c

            # marker for the start
            frame_ix = Sync.convert(t_on, 'arduino', 'dlc').round().astype('int')
            dlc.plot_bodyparts(bodyparts, DlcDf, frame_ix, colors=bp_cols, axes=ax, markersize=5)

            # the trajectory
            DlcDfSlice = bhv.time_slice(DlcDf, t_on, t_off)
            dlc.plot_trajectories(DlcDfSlice, bodyparts, colors=bp_cols, axes=ax, lw=0.75, alpha=0.5, p=0.8)
示例#7
0
def get_LC_slice_aligned_on_event(LoadCellDf, TrialDfs, align_event, pre,
                                  post):
    " Returns NUMPY ND.ARRAY of all trials aligned to an event in a window defined by [align-pre, align+post]"

    X, Y = [], []

    for TrialDf in TrialDfs:

        t_align = TrialDf.loc[TrialDf['name'] == align_event, 't'].values[0]
        LCDf = bhv.time_slice(LoadCellDf, t_align - pre,
                              t_align + post)  # slice around reference event

        # Store
        X.append(LCDf['x'].values)
        Y.append(LCDf['y'].values)

    # Turn into numpy arrays
    X = np.array(X, dtype=object).T
    Y = np.array(Y, dtype=object).T

    return X, Y
示例#8
0
def get_dist_aligned_on_event(DlcDf, TrialDfs, align_event, pre, post, func,
                              f_arg1, f_arg2):
    """
        Returns dist for func and args for all trials aligned to an event in a window defined by [align-pre, align+post]
        NOTE: we are returning NP nd.arrays so we use advanced slicing, meaning [row, col] instead of [row][col]
    """

    dist = []

    for TrialDf in TrialDfs:
        # Get time point of align_event
        t_align = TrialDf.loc[TrialDf['name'] == align_event, 't'].values[0]

        # Slice DlcDf and compute distance according to input func and args
        Dlc_TrialDf = bhv.time_slice(DlcDf, t_align - pre, t_align + post)
        dist.append(func(Dlc_TrialDf, f_arg1, f_arg2, filter=True))

    # Fix the fact that some arrays have different lengths (due to frame rate fluctuations)
    dist = truncate_pad_vector(dist)

    return dist
示例#9
0
def get_dist_between_events(DlcDf,
                            TrialDfs,
                            first_event,
                            second_event,
                            func,
                            f_arg1,
                            f_arg2,
                            pad_with=None):
    """
        Returns Fx/Fy/Fmag NUMPY ND.ARRAY with dimensions (trials, max_array_len) for all trials 
        NOTE: we are returning NP nd.arrays so we use advanced slicing, meaning [row, col] instead of [row][col]

        func anf f_arg1/2 are names for a more general implementation yet to test where one can get any function 
        between two events (does not have to be distance despite the function name)
    """

    dist = []
    for i, TrialDf in enumerate(TrialDfs):
        if not TrialDf.empty:

            if first_event == 'first':  # From start of trial
                time_1st = float(TrialDf['t'].iloc[0])
            else:
                time_1st = float(TrialDf[TrialDf.name == first_event]['t'])

            if second_event == 'last':  # Until end of trial
                time_2nd = float(TrialDf['t'].iloc[-1])
            else:
                time_2nd = float(TrialDf[TrialDf.name == second_event]['t'])

            # Slice DlcDf and compute distance according to input func and args
            Dlc_TrialDf = bhv.time_slice(DlcDf, time_1st, time_2nd)
            dist.append(func(Dlc_TrialDf, f_arg1, f_arg2, filter=True))

    # Make sure we have numpy arrays with same length, pad/truncate with given input pad_with
    dist = bhv.truncate_pad_vector(dist, pad_with)

    return dist
示例#10
0
def plot_reaches_between_events(SessionDf, LogDf, TrialDfs, event_1, event_2,
                                bin_width):
    " Plots the reaches during between two events split by trial side and outcome "

    hist_range = (0, 2500)

    trial_sides = ['left', 'right']
    outcomes = ['correct', 'incorrect']

    fig, axes = plt.subplots(nrows=len(outcomes),
                             ncols=len(trial_sides),
                             figsize=[6, 4],
                             sharex=True,
                             sharey=True)

    kwargs = dict(bins=(round(hist_range[1] / bin_width)),
                  range=hist_range,
                  alpha=0.5,
                  edgecolor='none')

    # For each side and outcome
    for i, trial_side in enumerate(trial_sides):
        for j, outcome in enumerate(outcomes):

            # Filter trials (continues if there are no trials to pool from)
            try:
                TrialDfs_filt = filter_trials_by(
                    SessionDf, TrialDfs,
                    dict(correct_side=trial_side, outcome=outcome))
            except:
                continue

            # For each trial get the left and right reaches during delay period
            left_reaches, right_reaches = [], []
            for TrialDf in TrialDfs_filt:

                t_event_1 = TrialDf[TrialDf['name'] == event_1].iloc[-1]['t']

                if 'GO_CUE_LEFT_EVENT' in TrialDf['name'].values:
                    t_event_2 = TrialDf.groupby('name').get_group(
                        "GO_CUE_LEFT_EVENT").iloc[-1]['t']
                elif 'GO_CUE_RIGHT_EVENT' in TrialDf['name'].values:
                    t_event_2 = TrialDf.groupby('name').get_group(
                        "GO_CUE_RIGHT_EVENT").iloc[-1]['t']

                # Slice trials between events
                sliceDf = bhv.time_slice(LogDf, t_event_1, t_event_2)

                left_reaches.append(
                    bhv.get_events_from_name(sliceDf, 'REACH_LEFT_ON').values -
                    t_event_1)
                right_reaches.append(
                    bhv.get_events_from_name(sliceDf, 'REACH_RIGHT_ON').values
                    - t_event_1)

            flat_left_reaches = [
                item for sublist in left_reaches for item in sublist
            ]
            flat_right_reaches = [
                item for sublist in right_reaches for item in sublist
            ]

            ax = axes[j, i]
            ax.hist(np.array(flat_left_reaches), **kwargs, label='reach left')
            ax.hist(np.array(flat_right_reaches),
                    **kwargs,
                    label='reach right')
            ax.legend(loc='upper right',
                      frameon=False,
                      fontsize=8,
                      handletextpad=0.3,
                      handlelength=0.5)

    # Formatting
    axes[0, 0].set_title('short trials')
    axes[0, 1].set_title('long trials')
    axes[0, 0].set_ylabel('correct')
    axes[1, 0].set_ylabel('incorrect')
    fig.suptitle('Hist of reaches between ' + str(event_1) + ' and ' +
                 str(event_2))
    fig.tight_layout()

    return axes
示例#11
0
LogDf['t'] = Sync.convert(LogDf['t'].values,'arduino','loadcell')

# %% median removal for loadcelldata
# %% median correction
samples = 10000 # 10s buffer: harp samples at 1khz, arduino at 100hz, LC controller has 1000 samples in buffer
LoadCellDf['x'] = LoadCellDf['x'] - LoadCellDf['x'].rolling(samples).median()
LoadCellDf['y'] = LoadCellDf['y'] - LoadCellDf['y'].rolling(samples).median()

# %%
Spans = bhv.get_spans_from_names(LogDf, "REWARD_RIGHT_VALVE_ON", "REWARD_RIGHT_VALVE_OFF")
N = 2000
Data = sp.zeros((N,27,2))
for  i, row in Spans.iterrows():
    t_on = row["t_on"]
    t_off = t_on + N
    data = bhv.time_slice(LoadCellDf, t_on, t_off)
    Data[:,i,:] = data.values[:,1:]

# %%
fs = sp.arange(60,310,10)
Data = Data[:,-fs.shape[0]:,:]

# %%
fig, axes = plt.subplots()
for i in range(fs.shape[0]):
    plt.plot(Data[:,i,0])

# %%
from scipy.signal import periodogram
import seaborn as sns
colors = sns.color_palette('viridis',n_colors=25)
示例#12
0
def plot_overview_simple(LogDf, align_event, pre, post, how='bars', axes=None):
    "Plots trials together with reach spans"

    if axes is None:
        fig, axes = plt.subplots()

    # Key Events and Spans
    key_list = [
        'REACH_LEFT_ON', 'REACH_RIGHT_ON', 'PRESENT_INTERVAL_STATE',
        'GO_CUE_SHORT_EVENT', 'GO_CUE_LONG_EVENT'
    ]

    colors = sns.color_palette('hls', n_colors=len(key_list))
    cdict = dict(zip(key_list, colors))

    t_ref = bhv.get_events_from_name(LogDf, align_event).values

    for i, t in enumerate(t_ref):

        Df = bhv.time_slice(LogDf, t - pre, t + post, 't')

        for name in cdict:
            # plot events
            if name.endswith("_EVENT") or name.endswith("_STATE"):
                event_name = name
                times = bhv.get_events_from_name(Df, name).values - t

                if how == 'dots':
                    axes.plot(times, [i] * len(times),
                              '.',
                              color=cdict[event_name],
                              alpha=0.75)  # a bar

                if how == 'bars':
                    for time in times:
                        axes.plot([time, time], [i - 0.5, i + 0.5],
                                  lw=2,
                                  color=cdict[event_name],
                                  alpha=0.75)  # a bar

            # plot spans
            if name.endswith("_ON"):
                span_name = name.split("_ON")[0]
                on_name = span_name + '_ON'
                off_name = span_name + '_OFF'

                SpansDf = bhv.get_spans_from_names(Df, on_name, off_name)

                if 'REACH' in span_name:
                    SpansDf = SpansDf[
                        SpansDf['dt'] >
                        10]  # remove reaches whose length is less than 10ms

                for j, row_s in SpansDf.iterrows():
                    time = row_s['t_on'] - t
                    dur = row_s['dt']
                    rect = plt.Rectangle((time, i - 0.5),
                                         dur,
                                         1,
                                         facecolor=cdict[on_name],
                                         linewidth=1)
                    axes.add_patch(rect)

    for key in cdict.keys():
        axes.plot([0], [0], color=cdict[key], label=key, lw=4)

    # Formatting
    axes.legend(loc="center",
                bbox_to_anchor=(0.5, -0.2),
                prop={'size': len(key_list)},
                ncol=len(key_list),
                frameon=False)
    axes.set_title('Trials aligned to ' + str(align_event))
    plt.setp(axes,
             xticks=np.arange(-pre, post + 1, 500),
             xticklabels=np.arange(-pre / 1000, post / 1000 + 0.1, 0.5))
    axes.set_ylim([0, len(t_ref)])
    axes.invert_yaxis()  # Needs to be after set_ylim
    axes.set_xlabel('Time (ms)')
    axes.set_ylabel('Trial No.')

    fig.tight_layout()

    return axes
示例#13
0
def make_annotated_video(Vid, t_on, t_off, LogDf, DlcDf, fps=20, save=None):
    LogDfSlice = bhv.time_slice(LogDf, t_on, t_off)
    DlcDfSlice = bhv.time_slice(DlcDf, t_on, t_off)

    # what events to display
    display_events = list(LogDfSlice.name.unique())
    # display_events = ['GO_CUE_SHORT_EVENT', 'GO_CUE_LONG_EVENT', 'CHOICE_CORRECT_EVENT', 'CHOICE_INCORRECT_EVENT', 'REWARD_LEFT_EVENT','REWARD_RIGHT_EVENT', 'REACH_LEFT_ON', 'REACH_LEFT_OFF', 'REACH_RIGHT_ON', 'REACH_RIGHT_OFF']
    if sp.nan in display_events:
        display_events.remove(np.nan)

    frame_on = DlcDfSlice.index[0]
    frame_off = DlcDfSlice.index[-1]
    ix = list(range(frame_on, frame_off))

    # plotting
    fig, ax = plt.subplots()
    ax.axis('off')

    if save is not None:
        import matplotlib as mpl
        # from matplotlib.animation import FFMpegWriter as AniWriter
        # Writer = AniWriter(fps=20, bitrate=7500, codec="h264", extra_args=['-pix_fmt','yuv420p'])
        # Writer = AniWriter(fps=20, bitrate=10000, codec="h264")
        from matplotlib.animation import FFMpegFileWriter as AniWriter
        Writer = AniWriter(fps=fps, codec="h264", bitrate=-1)
        mpl.rcParams['animation.ffmpeg_path'] = "/usr/bin/ffmpeg"

    # image
    ax.set_aspect('equal')
    frame = dlc.get_frame(Vid, ix[0])
    im = ax.imshow(frame, cmap='gray')

    # body parts
    bp_left = [bp for bp in bodyparts if bp.endswith('L')]
    bp_right = [bp for bp in bodyparts if bp.endswith('R')]
    c_l = sns.color_palette('viridis', n_colors=len(bp_left))
    c_r = sns.color_palette('magma', n_colors=len(bp_right))
    bp_cols = dict(zip(bp_left+bp_right,c_l+c_r))

    bp_markers = []
    for i, bp in enumerate(bodyparts):
        marker, = ax.plot([],[], 'o', color=bp_cols[bp], markersize=10)
        bp_markers.append(marker)

    # traces
    from matplotlib.collections import LineCollection
    n_segments = 10
    trace_len = 3
    lws = sp.linspace(0,5,n_segments)
    bp_traces = []
    for i, bp in enumerate(bodyparts):
        segments = []
        for j in range(n_segments):
            segment = sp.zeros((trace_len,2))
            segments.append(segment)
        
        lc = LineCollection(sp.array(segments),linewidths=lws,color=bp_cols[bp], alpha=0.75)
        bp_traces.append(lc)
        ax.add_artist(lc)
    p = 0.0

    # frame text
    inactive_color = 'white'
    frame_counter = ax.text(5, frame.shape[0]-25, '', color=inactive_color)
    time_counter = ax.text(5, frame.shape[0]-5, '', color=inactive_color)

    # event text annotations
    # color setup
    c = sns.color_palette('husl', n_colors=len(display_events))
    event_colors = dict(zip(display_events,c))
    event_display_dur = 50 # ms

    event_texts = []
    event_times = []
    for i, event in enumerate(display_events):
        # times 
        try:
            times = LogDfSlice.groupby('name').get_group(event)['t'].values
        except KeyError:
            times = [np.nan]
        event_times.append(times)

        # plot
        # bg_text = ax.text(10, i*20 + 20, event, color='black', fontweight='heavy', fontsize=6)
        text = ax.text(10, i*20 + 20, event, color=inactive_color, fontweight='heavy', fontsize=6)
        event_texts.append(text)

    fig.tight_layout()

    # the animation function
    def update(i):
        Frame = dlc.get_frame(Vid,i)
        im.set_data(Frame)

        # frame counter
        frame_counter.set_text("frame: %i - %i/%i" % (i, ix.index(i),len(ix)))
        t_abs = Sync.convert(i,'dlc','arduino') / 1000
        m = Sync.pairs[('dlc','arduino')][0]
        t_rel = (ix.index(i) * m) / 1000
        time_counter.set_text("time: %.2f - %.2f/%.2f" % (t_abs, t_rel,len(ix)*m/1000))

        # body parts
        for j, bp in enumerate(bodyparts):
            data = DlcDfSlice[bp].loc[i]
            if data['likelihood'] > p:
                bp_markers[j].set_data(data['x'], data['y'])
            else:
                bp_markers[j].set_data(sp.nan, sp.nan)
        
        # trace
        for j, bp in enumerate(bodyparts):
            i0 = i - n_segments*trace_len
            data = DlcDfSlice[bp].loc[i0:i]
            data.loc[data['likelihood'] < p] = sp.nan
            data = data[['x','y']].values[::-1,:]
            segments = bp_traces[j].get_segments()
            for k in range(n_segments):
                try:
                    segments[-k] = data[k*trace_len-5:(k+1)*trace_len+5,:]
                except:
                    pass
            bp_traces[j].set_segments(segments)

        for j, event in enumerate(display_events):
            t = Sync.convert(i, 'dlc', 'arduino')
            if sp.any(sp.logical_and(t > event_times[j], t < event_times[j] + event_display_dur)):
                event_texts[j].set_color(event_colors[event])
            else:
                event_texts[j].set_color(inactive_color)

        return (im, frame_counter, time_counter) + tuple(bp_markers) + tuple(bp_traces) + tuple(event_texts)

    ani = FuncAnimation(fig, update, frames=ix, blit=True, interval=1)
    if save is not None:
        utils.printer("saving video to %s" % save, 'msg')
        ani.save(save, writer=Writer)
        plt.close(fig)
示例#14
0
def plot_no_init_attempts(LoadCellDf,
                          TrialDfs,
                          log_path,
                          peaks_coincidence,
                          hist_crop,
                          axes=None):

    if axes is None:
        fig = plt.figure(figsize=(6, 4))

    # Load thresh from bonsai settings
    bonsai_settings_path = log_path.parent / "learn_to_choose_v2/Bonsai/interface_variables.ini"
    with open(bonsai_settings_path, 'r') as fH:
        lines = fH.readlines()
    init_tresh = int(''.join(x for x in lines[1] if x.isdigit()))

    sub_tresh = 0.66 * init_tresh  # About two thirds the original

    attempts = []
    for TrialDf in TrialDfs:

        # Slice when trial is available but not initiated
        Df = bhv.event_slice(TrialDf, "TRIAL_AVAILABLE_EVENT",
                             "TRIAL_ENTRY_EVENT")

        if not Df.empty:
            LCDf = bhv.time_slice(LoadCellDf, Df.iloc[0]['t'],
                                  Df.iloc[-1]['t'])

            X = LCDf['x'].values
            Y = LCDf['y'].values

            # sub thresh pulling peaks
            X_peaks, _ = sp.signal.find_peaks(X, height=sub_tresh,
                                              width=50)  # 50 ms
            Y_peaks, _ = sp.signal.find_peaks(Y, height=sub_tresh, width=50)

            # Computes distance between all X_peaks and all Y_peaks
            dist = np.abs(X_peaks[:, np.newaxis] - Y_peaks)

            # If its empty
            if len(dist) == 0:
                attempts.append(0)
            else:
                min_dist = np.min(dist, axis=0)

                # If time difference between peaks is lower than 50 ms, they coincide in time
                no_attempts = min_dist[np.where(
                    min_dist < peaks_coincidence)].shape[0]
                attempts.append(no_attempts)

        # Instant initiation
        else:
            attempts.append(0)

    # Plotting settings
    left, width = 0.1, 0.65
    bottom, height = 0.1, 0.65
    spacing = 0.005
    rect_scatter = [left, bottom, width, height]
    rect_histy = [left + width + spacing, bottom, 0.2, height]

    ax = fig.add_axes(rect_scatter)
    ax_histy = fig.add_axes(rect_histy, sharey=ax)

    # Formatting
    ax.scatter(np.arange(len(TrialDfs)), attempts, s=2)
    ax.set_ylim([-1, hist_crop])
    ax.set_ylabel('No of init attempts')
    ax.set_xlabel('Trial No.')

    ax_histy.hist(attempts,
                  bins=np.arange(hist_crop) - 0.5,
                  range=(0, hist_crop),
                  density=True,
                  orientation='horizontal')
    ax_histy.tick_params(axis="y", labelleft=False)
    ax_histy.set_xlabel('Perc. of trials (%)')
    ax_histy.set_xticks([0, 0.25, 0.5, 0.75, 1])
    ax_histy.set_xticklabels([0, 25, 50, 75, 100])
    ax_histy.set_xlim([0, 1])
    ax_histy.set_ylim([-1, hist_crop])

    ax.set_title('Number attempts before trial init')

    return ax
示例#15
0
Df = bhv.event_slice(TrialDf, 'TRIAL_ENTRY_EVENT', 'ITI_STATE')
t_on = Df.iloc[0]['t']
t_off = Df.iloc[-1]['t']

# %% static image with trajectory between t_on and t_off

bp_cols = make_bodypart_colors(bodyparts)

fig, axes = plt.subplots()
frame_ix = Sync.convert(t_on, 'arduino', 'dlc')
frame = dlc.get_frame(Vid, frame_ix)
dlc.plot_frame(frame, axes=axes)
dlc.plot_bodyparts(bodyparts, DlcDf, frame_ix, colors=bp_cols, axes=axes)

# trajectory
DlcDfSlice = bhv.time_slice(DlcDf, t_on, t_off)
dlc.plot_trajectories(DlcDfSlice, bodyparts, axes=axes, colors=bp_cols, lw=1, p=0.99)

# %% plot all of the selected trial type

# SDf = bhv.groupby_dict(SessionDf, dict(outcome='correct', correct_side='right', paw_resting=False))

# trial selection
SDf = bhv.groupby_dict(SessionDf, dict(has_choice=True, correct_side='left', outcome='correct'))

# plot some random frame
fig, axes = plt.subplots()

frame_ix = 1000
frame = dlc.get_frame(Vid, frame_ix)
dlc.plot_frame(frame, axes=axes)
示例#16
0
    
    # Filter sessions to the ones of the task we want to see
    task_name = ['learn_to_choose_v2']
    FilteredSessionsDf = pd.concat([SessionsDf.groupby('task').get_group(name) for name in task_name])
    log_paths = [Path(path)/'arduino_log.txt' for path in FilteredSessionsDf['path']]

    for k,log_path in enumerate(tqdm(log_paths[:no_sessions_to_analyze], position=0, leave=True, desc=animal)):
        
        LogDf = bhv.get_LogDf_from_path(log_path)

        # Getting metrics
        TrialSpans = bhv.get_spans_from_names(LogDf, "TRIAL_ENTRY_STATE", "ITI_STATE")

        TrialDfs = []
        for i, row in TrialSpans.iterrows():
            TrialDfs.append(bhv.time_slice(LogDf, row['t_on'], row['t_off']))

        metrics = ( met.get_start, met.get_stop, met.get_correct_side, met.get_outcome, met.get_chosen_side, met.has_choice,
                    met.rew_collected)
        SessionDf = bhv.parse_trials(TrialDfs, metrics)

        # Session metrics
        n_rews_collected[j,k] = SessionDf['rew_collect'].sum()
        n_anticipatory[j,k] = SessionDf['has_choice'].sum()

        no_trials[j,k] = len(SessionDf)
        session_length [j,k] = (LogDf['t'].iloc[-1]-LogDf['t'].iloc[0])/(1000*60) # convert msec. -> sec.-> min.

# %%
"""
.########..##........#######..########..######.
示例#17
0
# Detection rectangle
w = 30 # box size
rect = dlc_utils.box2rect(SL_coords, w)
R = dlc_utils.Rectangle(*dlc_utils.rect2cart(rect),lw=1,facecolor='none',edgecolor='r')
axes.add_patch(R)

# Obtain all reaches within rectangle, convert from frame to time
bp = 'PR'
SpansDf = dlc_utils.in_box_span(DlcDf, bp, rect, min_dur=1)
SpansDf = pd.DataFrame(Sync.convert(SpansDf.values,'dlc','arduino'), columns=SpansDf.columns)

# Plot all reaches to given side 
df = DlcDf[bp]
for i, row in tqdm(SpansDf.iterrows()):
    t_on = row['t_on']
    df = bhv.time_slice(DlcDf,t_on-avg_mvmt_time,t_on+500)[bp]

    ix = df.likelihood > p
    df = df.loc[ix]
    axes.plot(df.x,df.y,lw=1, alpha=0.85)

axes.set_title('Reach trajectories for right_spout with ' + str(bp))
plt.savefig(plot_dir / ('reaches_for_right_spout_with_' + str(bp) + '.png'), dpi=600)

# %% distance / speed over time
fig, axes = plt.subplots(nrows=2,sharex=True)

bps = ['PR','PL']

line_kwargs = dict(lw=1,alpha=0.8)
for i, bp in enumerate(bps):
示例#18
0
def plot_forces_on_init(session_folder, save=None):
    LogDf = bhv.get_LogDf_from_path(session_folder / "arduino_log.txt")

    ### LoadCell Data
    LoadCellDf = bhv.parse_bonsai_LoadCellData(session_folder / 'bonsai_LoadCellData.csv')

    # Syncer
    from Utils import sync
    lc_sync_event = sync.parse_harp_sync(session_folder / 'bonsai_harp_sync.csv', trig_len=100, ttol=5)
    arduino_sync_event = sync.get_arduino_sync(session_folder / 'arduino_log.txt')

    Sync = sync.Syncer()
    Sync.data['arduino'] = arduino_sync_event['t'].values
    Sync.data['loadcell'] = lc_sync_event['t'].values
    Sync.sync('arduino','loadcell')

    LogDf['t_orig'] = LogDf['t']
    LogDf['t'] = Sync.convert(LogDf['t'].values, 'arduino', 'loadcell')

    # preprocessing
    samples = 10000 # 10s buffer: harp samples at 1khz, arduino at 100hz, LC controller has 1000 samples in buffer
    LoadCellDf['x'] = LoadCellDf['x'] - LoadCellDf['x'].rolling(samples).mean()
    LoadCellDf['y'] = LoadCellDf['y'] - LoadCellDf['y'].rolling(samples).mean()

    # plot forces  
    times = LogDf.groupby('name').get_group('TRIAL_ENTRY_EVENT')['t'].values
    pre, post = -1000, 1000
    fig, axes = plt.subplots(nrows=2,sharex=True,sharey=False)

    x_avgs = []
    y_avgs = []
    for i,t in enumerate(tqdm(times)):
        Df = bhv.time_slice(LoadCellDf, t+pre, t+post, reset_index=False)
        # these colors need to be thorougly checked
        axes[0].plot(Df['t'].values - t, Df['x'])
        axes[1].plot(Df['t'].values - t, Df['y'])

        x_avgs.append(Df['x'].values)
        y_avgs.append(Df['y'].values)

    x_avgs = np.average(np.array(x_avgs),axis=0)
    y_avgs = np.average(np.array(y_avgs),axis=0)

    tvec = np.linspace(pre,post,x_avgs.shape[0])
    axes[0].plot(tvec, x_avgs, color='k',lw=2)
    axes[1].plot(tvec, y_avgs, color='k',lw=2)

    kws = dict(linestyle=':',lw=1, alpha=0.8, color='k')
    for ax in axes:
        ax.axhline(-500, **kws)
        ax.axvline(0, **kws)

    # deco
    Session = utils.Session(session_folder)
    Animal = utils.Animal(session_folder.parent)
    title = ' - '.join([Animal.display(), Session.date, 'day: %s'% Session.day])

    for ax in axes:
        ax.set_ylim(-2500,2500)
        ax.set_ylabel('Force [au]')
    axes[1].set_xlabel('time (ms)')

    sns.despine(fig)
    fig.suptitle(title)
    fig.tight_layout()
    fig.subplots_adjust(top=0.9)

    if save is not None:
        os.makedirs(session_folder / 'plots', exist_ok=True)
        plt.savefig(save, dpi=600)
        plt.close(fig)
示例#19
0
t_on = Df.iloc[0]['t']
t_off = Df.iloc[-1]['t']


# %% static image with trajectory between t_on and t_off

bp_cols = make_bodypart_colors(bodyparts)

fig, axes = plt.subplots()
frame_ix = Sync.convert(t_on, 'arduino', 'dlc')
frame = dlc.get_frame(Vid, frame_ix)
dlc.plot_frame(frame, axes=axes)
dlc.plot_bodyparts(bodyparts, DlcDf, frame_ix, colors=bp_cols, axes=axes)

# trajectory
DlcDfSlice = bhv.time_slice(DlcDf, t_on, t_off)
dlc.plot_trajectories(DlcDfSlice, bodyparts, axes=axes, colors=bp_cols, lw=1, p=0.99)

# %% plot all of the selected trial type
# trial selection
SDf = bhv.groupby_dict(SessionDf, dict(correct_side='left',outcome='incorrect'))
# SDf = SessionDf.groupby('correct_side').get_group('right')

# plot some random frame
fig, axes = plt.subplots()
frame_ix = 1000
frame = dlc.get_frame(Vid, frame_ix)
dlc.plot_frame(frame, axes=axes)

# plot all traj in selection
for i in tqdm(SDf.index):
示例#20
0
    meso_framesDf.drop(meso_framesDf.tail(n).index,inplace=True) 

# %% AVG across neurons across events
events = ['GO_CUE_EVENT','REWARD_STATE','REWARD_RIGHT_COLLECTED_EVENT']

fig, axes = plt.subplots(ncols=len(events), sharey=True, figsize=(8,4))

pre, post = 500,2000

for i,event in enumerate(events):
    t_refs = bhv.get_events_from_name(LogDf, event).values

    N_mean,frame_time = [],[]
    for t_ref in t_refs:

        sliceDf = bhv.time_slice(meso_framesDf, t_ref-pre, t_ref+post)
        frame_time.append(sliceDf['t'].values - t_ref) # relative to t_ref
        frame_idx = sliceDf.index.values # get frames

        N_mean.append(np.mean(neural_data[:,frame_idx], axis = 0)) # Avg across neurons

    N_mean_time = bhv.tolerant_mean(N_mean)
    time = np.arange(-pre,post+1,main_freq) # begin,stop,step
    axes[i].plot(time,N_mean_time,'o-', color = 'black')
    axes[i].vlines(0,0,1, color = 'black', alpha = 0.25)

    axes[i].set_ylim([0,0.03])
    axes[i].set_title(event)
    axes[i].set_xlabel('Time (ms)')
    axes[i].set_ylabel('\u0394F/F')
示例#21
0
        # check each reach
        ReachesLeftDf = bhv.get_spans_from_names(LogDf, "REACH_LEFT_ON", "REACH_LEFT_OFF")

        # drop invalid
        min_th = 5
        max_th = 2000

        binds = np.logical_and(ReachesLeftDf['dt'].values > min_th, ReachesLeftDf['dt'].values < max_th)

        ReachesLeftDf = ReachesLeftDf.loc[binds]

        ReachesLeftDf['is_grasp'] = False
        for i, row in ReachesLeftDf.iterrows():
            t_on = row['t_on']
            t_off = row['t_off']
            Df = bhv.time_slice(LogDf, t_on, t_off)
            if 'GRASP_LEFT_ON' in Df.name.values:
                ReachesLeftDf.loc[i,'is_grasp'] = True

        if np.any(ReachesLeftDf['is_grasp']):
            GraspsLeftDf = ReachesLeftDf.groupby('is_grasp').get_group(True)
        else:
            GraspsLeftDf = pd.DataFrame([],columns=ReachesLeftDf.columns)
        ReachesRightDf = bhv.get_spans_from_names(LogDf, "REACH_RIGHT_ON", "REACH_RIGHT_OFF")

        # drop invalid
        min_th = 5
        max_th = 2000

        binds = np.logical_and(ReachesRightDf['dt'].values > min_th, ReachesRightDf['dt'].values < max_th)
示例#22
0
def plot_hist_no_reaches_per_trial(LogDf, reach_crop):

    fig, axes = plt.subplots(figsize=[6, 4], ncols=2)
    kwargs = dict(bins=np.arange(reach_crop) - 0.5,
                  range=(0, reach_crop),
                  edgecolor='none',
                  alpha=0.5,
                  density=True)

    # Trials spanning from choice available to end of ITI
    TrialSpans = bhv.get_spans_from_names(LogDf, "GO_CUE_EVENT",
                                          "TRIAL_AVAILABLE_STATE")

    TrialDfs = []
    for i, row in TrialSpans.iterrows():
        TrialDfs.append(bhv.time_slice(LogDf, row['t_on'], row['t_off']))

    sides = ['left', 'right']
    no_reaches_dict = {'left': [], 'right': []}
    choice_reach_no_dict = {'left': [], 'right': []}
    key = []

    # Obtain no of reaches before choice and total for each trial
    for TrialDf in TrialDfs:
        if met.has_choice(TrialDf).values:

            # Can't use metric due to cutting between choice and end of ITI
            if "GO_CUE_LEFT_EVENT" in TrialDf['name'].values:
                key = 'left'
            if "GO_CUE_RIGHT_EVENT" in TrialDf['name'].values:
                key = 'right'

            left_reach_spansDf = bhv.get_spans_from_names(
                TrialDf, 'REACH_LEFT_ON', 'REACH_LEFT_OFF')
            right_reach_spansDf = bhv.get_spans_from_names(
                TrialDf, 'REACH_RIGHT_ON', 'REACH_RIGHT_OFF')

            merge_spansDf = pd.concat(
                [left_reach_spansDf,
                 right_reach_spansDf]).reset_index(drop=True)

            choice_time = bhv.get_events_from_name(
                TrialDf, 'CHOICE_EVENT')['t'].values[0]

            # Which reach triggered the choice? The one which corresponding spansDf contains choice_time
            for i, row in enumerate(merge_spansDf.iterrows()):
                if (row[1]['t_on'] < choice_time < row[1]['t_off']):
                    no_reaches_needed = i + 1
                    choice_reach_no_dict[key].append(no_reaches_needed)

            no_reaches_dict[key].append(
                len(merge_spansDf) - no_reaches_needed
            )  # subtract the no. of reaches leading to choice

    # Plotting
    for ax, side in zip(axes, sides):
        ax.hist(no_reaches_dict[side],
                color='r',
                label='No. in vain reaches',
                **kwargs)
        ax.axvline(np.percentile(no_reaches_dict[side], 75), color='r')
        ax.hist(choice_reach_no_dict[side],
                color='y',
                label='No. reaches needed \n to clock choice',
                **kwargs)
        ax.axvline(np.percentile(choice_reach_no_dict[side], 75), color='y')
        ax.legend(frameon=False, fontsize='small')
        ax.set_title(side + ' trials')
        ax.set_xlabel('No. Reaches')
        ax.set_ylim([0, 1])

    # Formatting
    axes[0].set_ylabel('Ratio of trials')
    fig.suptitle('Histogram of no. of reaches per trial ')
    fig.tight_layout()

    return axes
示例#23
0
def grasp_dur_across_sess(animal_fd_path, tasks_names):

    SessionsDf = utils.get_sessions(animal_fd_path)
    animal_meta = pd.read_csv(animal_fd_path / 'animal_meta.csv')

    # Filter sessions to the ones of the task we want to see
    FilteredSessionsDf = pd.concat(
        [SessionsDf.groupby('task').get_group(name) for name in tasks_names])
    log_paths = [
        Path(path) / 'arduino_log.txt' for path in FilteredSessionsDf['path']
    ]

    fig, axes = plt.subplots(ncols=2, figsize=[8, 4], sharey=True, sharex=True)
    sides = ['LEFT', 'RIGHT']

    Df = []
    # gather data
    for day, log_path in enumerate(log_paths):

        LogDf = bhv.get_LogDf_from_path(log_path)
        TrialSpans = bhv.get_spans_from_names(LogDf, "TRIAL_ENTRY_STATE",
                                              "ITI_STATE")

        TrialDfs = []
        for i, row in tqdm(TrialSpans.iterrows(), position=0, leave=True):
            TrialDfs.append(bhv.time_slice(LogDf, row['t_on'], row['t_off']))

        metrics = (met.get_start, met.get_stop, met.get_correct_side,
                   met.get_outcome, met.get_interval_category,
                   met.get_chosen_side, met.has_reach_left,
                   met.has_reach_right)
        SessionDf = bhv.parse_trials(TrialDfs, metrics)

        for side in sides:
            event_on, event_off = 'REACH_' + str(side) + '_ON', 'REACH_' + str(
                side) + '_OFF'  # event names

            # reaches
            grasp_spansDf = bhv.get_spans_from_names(LogDf, event_on,
                                                     event_off)
            reach_durs = np.array(grasp_spansDf['dt'].values, dtype=object)
            Df.append([reach_durs], columns=['durs'], ignore_index=True)

            # grasps
            choiceDf = bhv.groupby_dict(
                SessionDf, dict(has_choice=True, chosen_side=side.lower()))
            grasp_durs = choiceDf[~choiceDf['grasp_dur'].isna(
            )]['grasp_dur'].values  # filter out Nans
            Df.append([grasp_durs, 'g', side],
                      columns=['durs', 'type', 'side'],
                      ignore_index=True)

        sns.violinplot(data=Df[Df['type'] == 'r'],
                       x=day,
                       y='durs',
                       hue='side',
                       split=True,
                       cut=0,
                       legend='reaches')
        sns.violinplot(data=Df[Df['type'] == 'g'],
                       x=day,
                       y='durs',
                       hue='side',
                       split=True,
                       cut=0,
                       legend='grasps')

    fig.suptitle('CDF of first reach split on trial type \n' +
                 animal_meta['value'][5] + '-' + animal_meta['value'][0])
    axes.legend

    return axes
示例#24
0
# %% check each reach
ReachesDf = bhv.get_spans_from_names(LogDf, "REACH_ON", "REACH_OFF")

# drop invalid
min_th = 5
max_th = 2000

binds = np.logical_and(ReachesDf['dt'].values > min_th, ReachesDf['dt'].values < max_th)

ReachesDf = ReachesDf.loc[binds]

ReachesDf['is_grasp'] = False
for i, row in ReachesDf.iterrows():
    t_on = row['t_on']
    t_off = row['t_off']
    Df = bhv.time_slice(LogDf, t_on, t_off)
    if 'GRASP_ON' in Df.name.values:
        ReachesDf.loc[i,'is_grasp'] = True
GraspsDf = ReachesDf.groupby('is_grasp').get_group(True)

# %%
fig, axes = plt.subplots(ncols=2, gridspec_kw=dict(width_ratios=(1,0.2)))
axes[0].plot(ReachesDf['t_on']/6e4, ReachesDf['dt'],'.',label='reach')
axes[0].plot(GraspsDf['t_on']/6e4, GraspsDf['dt'],'.',label='grasp')
wm = 3
w = wm*60*1000
w2 = int(w/2)
avgs = []
t_max = LogDf.iloc[-1]['t']
for t in tqdm(range(w2*2,int(t_max - w2),w2)):
    Df_reach = bhv.time_slice(ReachesDf, t-w/2, t+w/2, col='t_on')
示例#25
0
fig.tight_layout()
# %%
LogDf.groupby('name').get_group('FRAME_EVENT').shape[0]
LogDf.groupby('name').get_group('FRAME_INF_EVENT').shape[0]
# -> works, assign idex
nFrames = LogDf.groupby('name').get_group('FRAME_INF_EVENT').shape[0]
offset = dFF.shape[1] - nFrames
LogDf.loc[LogDf['name'] == 'FRAME_INF_EVENT','var'] = np.arange(offset, nFrames+offset)

# %% test slicing
w = (-3000, 3000)
event = 'REACH_RIGHT_ON'
times = LogDf.groupby('name').get_group(event)['t']
ix_ts = []
for t in times.values:
    Df = bhv.time_slice(LogDf,t+w[0],t+w[1])
    try:
        frame_ix = Df.groupby('name').get_group('FRAME_INF_EVENT')['var'].values
        frame_times = Df.groupby('name').get_group('FRAME_INF_EVENT')['t'].values - t
        ix_ts.append((frame_ix.astype('int32'),frame_times))
    except:
        pass

# %% sorting by kmeans
from sklearn.cluster import KMeans
k = 4 # todo find a way to find k
clust = KMeans(n_clusters=k)
clust.fit(dFF)
labels = clust.labels_
order = np.argsort(labels)
dFF = dFF[order,:]