Esempio n. 1
0
def get_PV1(mouse, arena, day, speed_thresh=1.5, pf_file='placefields_cm1_manlims_1000shuf.pkl'):
    """
    Gets PV for each session with no spatial bins
    :param mouse:
    :param arena:
    :param day:
    :param speed_thresh: exclude data points where mouse's smoothed speed is below this (1.5cm/s default)
    :param pf_file: default = 'placefields_cm1_manlims_1000shuf.pkl'_
    :return: PV1: nneurons long 1-d np array of event rates for each neuron across the whole session
    """
    try:
        PF = load_pf(mouse, arena, day, pf_file=pf_file)
        # Speed threshold PSAbool
        PFthresh = PF.PSAbool_align[:, PF.speed_sm > speed_thresh]
        sr_image = PF.sr_image
    except FileNotFoundError:
        print('No placefields file found - creating PV1 from neural data only - NO SPEED THRESHOLDING')
        dir_use = get_dir(mouse, arena, day)
        im_data_file = path.join(dir_use, 'FinalOutput.mat')
        im_data = sio.loadmat(im_data_file)
        PSAbool = im_data['PSAbool']
        PFthresh = PSAbool
        sr_image = im_data['SampleRate'][0]

    # Calculate PV
    nframes = PFthresh.shape[1]
    try:
        PV1d = PFthresh.sum(axis=1)/nframes * sr_image[0]
    except TypeError:  # Catch a few errors for mice where sr_image is not properly formatted
        PV1d = PFthresh.sum(axis=1) / nframes * sr_image
    return PV1d
Esempio n. 2
0
def get_running_bool(mouse, arena, day,  speed_thresh=1.5, lims_method='auto', list_dir=master_directory,
                align_from_end=False):
    """Generate a boolean of times the animal is running to use with placefields. Can modify and then feed into
    placefields function to generate place field maps from arbitrary times throughout the session
    :param all same as in placefields function above
    :return isrunning: boolean when the mouse is running. """
    make_session_list(list_dir)

    # Get position and time information for .csv file (later need to align to imaging)
    dir_use = get_dir(mouse, arena, day)
    speed, pos, t_track, sr = get_speed(dir_use)
    t_track = t_track[0:-1]  # chop last time data point to match t_track match speed/pos length

    # Display warning if "aligntoend" is in folder name but you are running with align_from_end=False
    if str(dir_use).upper().find('ALIGNTOEND') != -1 and align_from_end is False:
        print('Folder structure for ' + mouse + ' ' + arena + ': Day ' + str(
            day) + ' suggests you should align data from end of recording')
        print('RE-RUN WITH align_from_end=False!!!')

    # Import imaging data
    # im_data_file = path.join(dir_use + '\imaging', 'FinalOutput.mat')
    im_data_file = path.join(dir_use, 'FinalOutput.mat')
    im_data = sio.loadmat(im_data_file)
    PSAbool = im_data['PSAbool']
    nneurons, _ = np.shape(PSAbool)
    try:
        sr_image = im_data['SampleRate'].squeeze()
    except KeyError:
        sr_image = 20

    # Convert position to cm
    pix2cm = er.get_conv_factors(arena)  # get conversion to cm for the arena
    pos_cm = pos * pix2cm
    speed_cm = speed * pix2cm

    # Align imaging and position data
    pos_align, speed_align, PSAbool_align, time_interp = \
        align_imaging_to_tracking(pos_cm, speed_cm, t_track, PSAbool, sr_image, align_from_end=align_from_end)

    # Smooth speed data for legitimate thresholding, get limits of data
    speed_sm = np.convolve(speed_align, np.ones(2 * int(sr)) / (2 * sr), mode='same')  # smooth speed

    # Get data limits
    if lims_method == 'auto':  # automatic by default
        lims = [np.min(pos_cm, axis=1), np.max(pos_cm, axis=1)]
    elif lims_method == 'file':  # file not yet enabled
        print('lims_method=''file'' not enabled yet')
    else:  # grab array!
        lims = lims_method

    good = np.ones(len(speed_sm)) == 1
    isrunning = good
    isrunning[speed_sm < speed_thresh] = False

    return isrunning
Esempio n. 3
0
def plot_trajectory_overlay(mouse,
                            day_des=[-2, -1, 4, 1, 2, 7],
                            arenas=['Open', 'Shock'],
                            xmin=False,
                            ymin=False,
                            xlim=False,
                            ylim=False):
    """
    Plot mouse trajectory for each session
    :param
        mouse: name of mouse
        day_des: days to plot (day 0 = shock day, day -2 = 2 days before shock, 4 = 4 hr after shock (special case))
        arenas: 'Open' and/or 'Shock'
        xmin, ymin: #arenas by #days arrays or lists of minimum x/y values. False = don't adjust
        xlim, ylim: limits of x and y data you want to set as plotted. False = don't adjust.
    :return: h: figure handle
    """
    nsesh = len(day_des)
    narena = len(arenas)

    # Allocate xmin and ymin to zero if not designated
    if not xmin:
        xmin = np.zeros((narena, nsesh))
    if not ymin:
        ymin = np.zeros((narena, nsesh))

    # Cast xmin and ymin as 2d ndarrays for later
    xmin = np.reshape(xmin, (1, -1))
    ymin = np.reshape(ymin, (1, -1))

    fig, ax = plt.subplots(1,
                           narena,
                           figsize=(2.3, narena * 2.3),
                           squeeze=False)

    # Iterate through all sessions and plot stuff
    for ida, arena in enumerate(arenas):
        for idd, day in enumerate(day_des):
            dir_use = get_dir(mouse, arena, day)
            plot_frame_and_traj(ax[0, ida],
                                dir_use,
                                plot_frame=False,
                                xcorr=xmin[ida, idd],
                                ycorr=ymin[ida, idd])
        # set x and y limits
        if xlim is not False:
            ax[0, ida].set_xlim(xlim)
        if ylim is not False:
            ax[0, ida].set_ylim(ylim)

    # resize figure
    fig.set_size_inches(6.2, 5.7)

    return fig, ax
Esempio n. 4
0
def get_im_sample_rate(mouse, arena, day):
    """Gets sample rate for imaging data"""
    dir_use = get_dir(mouse, arena, day)
    im_data_file = path.join(dir_use, 'FinalOutput.mat')
    im_data = sio.loadmat(im_data_file, variable_names='SampleRate')
    try:
        sr_image = im_data['SampleRate'].squeeze()
    except KeyError:
        sr_image = 20

    return sr_image
Esempio n. 5
0
def get_all_freezing(mouse,
                     day_des=[-2, -1, 4, 1, 2, 7],
                     arenas=['Open', 'Shock'],
                     velocity_threshold=1.044,
                     min_freeze_duration=10):
    """
    Gets freezing ratio for all experimental sessions for a given mouse.
    :param
        mouse: Mouse name (string), e.g. 'DVHPC_5' or 'Marble7'
        arenas: 'Open' (denotes square) or 'Shock' or 'Circle' (denotes open field circle arena)
        day_des: array of session days -2,-1,0,1,2,7 and 4 = 4hr session on day 0
        list_dir: alternate location of SessionDirectories
    :return:
        fratios: narena x nsession array of fratios
    """
    nsesh = len(day_des)
    narena = len(arenas)

    # Iterate through all sessions and get fratio
    fratios = np.ones(
        (narena, nsesh)) * float('NaN')  # pre-allocate fratio as nan
    for idd, day in enumerate(day_des):
        for ida, arena in enumerate(arenas):
            # print(mouse + " " + str(day) + " " + arena)
            try:

                pix2cm = get_conv_factors(arena)
                dir_use = get_dir(mouse, arena, day)
                freezing, _ = detect_freezing(
                    dir_use,
                    velocity_threshold=velocity_threshold,
                    min_freeze_duration=min_freeze_duration,
                    arena=arena,
                    pix2cm=pix2cm)
                fratios[ida, idd] = freezing.sum() / freezing.__len__()
            except (IOError, IndexError, TypeError
                    ):  # FileNotFoundError is IOError in earlier versions
                # print(['Unknown error processing ' + mouse + ' ' + arena + ' ' + str(day)])
                print([
                    'Unknown file missing and/or IndexError for ' + mouse +
                    ' ' + arena + ' ' + str(day)
                ])
                print('Freezing left as NaN for this session')

    return fratios
Esempio n. 6
0
def load_pf(mouse, arena, day, session_index=None, pf_file='placefields_cm1_manlims_1000shuf.pkl'):
    if session_index is None:
        dir_use = get_dir(mouse, arena, day)
    elif isinstance(session_index, int) and session_index >= 0:
        dir_use = session_list[session_index]["Location"]
    elif session_index == 'cwd':
        dir_use = os.getcwd()
    elif os.path.exists(session_index):
        dir_use = session_index

    position_path = path.join(dir_use, pf_file)
    with open(position_path, 'rb') as file:
        PF = load(file)

    if type(PF.sr_image) is not int:
        PF.sr_image = PF.sr_image.squeeze()  # Backwards compatibility fix

    return PF
Esempio n. 7
0
def get_ROIs(mouse: str, arena: str, day: int in [-2, -1, 0, 1, 4, 2, 7], **kwargs):
    """
    Get neuron ROI array.
    :param mouse: str of the format 'Marble##'
    :param arena: str in ['Open', Shock']
    :param day: int in [-2, -1, 0, 4, 1, 2, 7]
    :param **kwargs: input to session_directory.find_eraser_directory
    :return: rois an ncells x npixx x npixy ndarray of neuron ROIs
    """
    dir_use = Path(get_dir(mouse, arena, day, **kwargs))
    neural_data = loadmat(dir_use / 'FinalOutput.mat')
    neuron_image = neural_data['NeuronImage']

    # Convert from a series of xpix x ypix arrays to a 3d ndarray
    assert neuron_image.shape[0] == 1, 'Inappropriate format for NeuronImage in FinalOutput.mat - write code!'
    rois = np.asarray([roi for roi in neuron_image[0]])

    return rois
Esempio n. 8
0
def get_bad_epochs(mouse, arena, day):
    """
    Identifies bad epochs where mouse is at 0,0 for manual correction
    :param mouse:
    :param arena:
    :param day:
    :return:
    """

    # Commment here
    dir_use = get_dir(mouse, arena, day)

    # Comment here
    pos = get_pos(dir_use)

    # Comment here
    bad_bool = np.logical_and(pos[0, :] == 0, pos[1, :] == 0)

    # Comment here
    bad_epochs = get_freezing_epochs(bad_bool)

    # Insert code here to print bad epochs to screen if you wish. Might be easier in the long run
    #print(bad_epochs)
    return bad_epochs
Esempio n. 9
0
def plot_experiment_traj(mouse,
                         day_des=[-2, -1, 4, 1, 2, 7],
                         arenas=['Open', 'Shock'],
                         disp_fratio=False,
                         plot_frame=False):
    """
    Plot mouse trajectory for each session
    :param
        mouse: name of mouse
        day_des: days to plot (day 0 = shock day, day -2 = 2 days before shock, 4 = 4 hr after shock (special case))
        arenas: 'Open' and/or 'Shock'
        disp_fratio: true = display freezing ratio on plot
    :return: h: figure handle
    """
    nsesh = len(day_des)
    narena = len(arenas)
    fig, ax = plt.subplots(narena, nsesh, figsize=(12.7, 4.8), squeeze=False)

    # Iterate through all sessions and plot stuff
    for idd, day in enumerate(day_des):
        for ida, arena in enumerate(arenas):
            # try:
            dir_use = get_dir(mouse, arena, day)

            # Label stuff
            ax[ida, idd].set_xlabel(str(day))

            if idd == 0:
                ax[ida, idd].set_ylabel(arena)
            if ida == 0 and idd == 0:
                ax[ida, idd].set_title(mouse)

            axis_off(ax[ida, idd])
            plot_frame_and_traj(ax[ida, idd], dir_use, plot_frame=plot_frame)

            if disp_fratio:

                velocity_threshold, min_freeze_duration, pix2cm = get_conv_factors(
                    arena)
                # if arena == 'Open':
                #     # NK Note - velocity threshold is just a guess at this point
                #     # Also need to ignore positions at 0,0 somehow and/or interpolate
                #     velocity_threshold = 15
                #     min_freeze_duration = 75
                # elif arena == 'Shock':
                #     velocity_threshold = 15
                #     min_freeze_duration = 10

                freezing, velocity = detect_freezing(
                    dir_use,
                    velocity_threshold=velocity_threshold,
                    min_freeze_duration=min_freeze_duration,
                    arena=arena,
                    pix2cm=pix2cm)
                fratio = freezing.sum() / freezing.__len__()
                fratio_str = '%0.2f' % fratio  # make it a string

            # Label stuff - hack here to make sure things get labeled if try statement fails during plotting
            ax[ida, idd].set_xlabel(str(day))
            if idd == 0:
                ax[ida, idd].set_ylabel(arena)
            if ida == 0 and idd == 0:
                ax[ida, idd].set_title(mouse)

            if idd == 0 and ida == 0 and disp_fratio:
                ax[ida, idd].set_ylabel(fratio_str)
            elif disp_fratio:
                ax[ida, idd].set_title(fratio_str)

        # except:
        #     print(['Error processing ' + mouse + ' ' + arena + ' ' + str(day)])

    return fig, ax
Esempio n. 10
0
                                                  shock1,
                                                  nan_policy='omit')

    # Plot stats in second subplot if it is there (only for 1st two groups though).
    label1 = xticklabels[0]
    label2 = xticklabels[1]
    if len(ax) == 2:
        # Plot across group stats in each arena
        ax[1].text(
            0.1, 0.9, label1 + ': ' + group_names[0] + ' v ' + group_names[1] +
            ' pval=' + "{0:.3g}".format(pval[0, 1, 0]) + ' tstat=' +
            "{0:.3g}".format(tstat[0, 1, 0]))
        ax[1].text(
            0.1, 0.75, label2 + ': ' + group_names[0] + ' v ' +
            group_names[1] + ' pval=' + "{0:.3g}".format(pval[0, 1, 1]) +
            ' tstat=' + "{0:.3g}".format(tstat[0, 1, 1]))
        # Plot within group stats between arenas...
        for idg, group_name in enumerate(group_names):
            ax[1].text(
                0.1, 0.50 - 0.15 * idg, group_name + ': ' + label1 + 'v ' +
                label2 + ' pval=' + "{0:.3g}".format(pval[idg, idg, 2]) +
                ' tstat=' + "{0:.3g}".format(tstat[idg, idg, 2]))

    return fig, ax, pval, tstat


if __name__ == '__main__':
    dir_use = get_dir('Marble07', 'Open', -2)
    detect_freezing(dir_use, arena='Open')

    pass
Esempio n. 11
0
    plt.close(fig)
## Workhorse code below - run before doing much of the above

## For mice with fixed registrations move all files to "archive" folders
arenas = ['Shock', 'Open']
days = [-2, -1, 0, 4, 1, 2, 7]
name_append = '_bad4'  # super ocd tracking of # times you've had to redo stuff _2 = 2nd, _87 = 87th, etc.

# IMPORTANT - comment out files you don't want to move in code below!
for mouse in err.all_mice_good:
    for arena1 in arenas:
        for arena2 in arenas:
            for id1, day1 in enumerate(days):
                for id2, day2 in enumerate(days):
                    if id1 <= id2 and arena1 != arena2 or id1 < id2 and arena1 == arena2:
                        dir_use = get_dir(mouse, arena1, day1)
                        archive_dir = os.path.join(dir_use, 'rot_archive')
                        if not os.path.isdir(archive_dir):
                            try:
                                os.mkdir(archive_dir)
                            except FileNotFoundError:
                                print('Error for ' + mouse + ' ' + arena1 +
                                      ' day ' + str(day1) + ' to ' + arena2 +
                                      ' day ' + str(day2))
                        files_move = glob(
                            os.path.join(dir_use,
                                         'shuffle_map_mean*nshuf1000.pkl'))
                        # files_move = glob(os.path.join(dir_use, 'best_rot*.pkl'))
                        # files_move.extend(glob(os.path.join(dir_use, 'PV1shuf*nshuf_1000.pkl')))
                        # files_move.extend(glob(os.path.join(dir_use, 'shuffle_map_mean*nshuf100.pkl')))
                        for file in files_move:
Esempio n. 12
0
    def save_data(self, filename='placefields_cm1.pkl'):
        dir_use = get_dir(self.mouse, self.arena, self.day, self.list_dir)
        save_file = path.join(dir_use, filename)

        with open(save_file, 'wb') as output:
            dump(self, output)
Esempio n. 13
0
def placefields(mouse, arena, day, cmperbin=1, nshuf=1000, speed_thresh=1.5, half=None,
                lims_method='auto', save_file='placefields_cm1.pkl', list_dir=master_directory,
                align_from_end=False, keep_shuffled=False, isrunning_custom=None):
    """
    Make placefields of each neuron. Ported over from Will Mau's/Dave Sullivan's MATLAB
    function
    :param mouse: mouse name to analyze
    :param arena: arena to analyze
    :param day: day to analyze
    :param cmperbin: 4 default
    :param lims_method: 'auto' (default) takes limits of data, 'file' looks for arena_lims.csv
            file in the session directory which supplies [[xmin, ymin],[xmax, ymax]], or you
            you can enter in [[xmin, ymin], [xmax, ymax]] manually
    :param nshuf: number of shuffles to perform for determining significance
    :param speed_thresh: speed threshold in cm/s
    :param save_file: default = 'placefields_cm1.pkl'. None = do not save
    :param align_from_end: False (default) align data assuming start of neural/behavioral data acquisition was
    synchronized, True = use end time-points to align (in case of bad triggering at beginning but good at end).
    :param half: None (default) = run whole session, 1 = run 1st half only, 2 = run 2nd half only, (odd/even not yet
    implemented as of 2021_02_01).
    :param keep_shuffled: True = keep shuffled smoothed tmaps (saved as .tmap_sm_shuf). False = default.
    :param isrunning_custom: use your own frames, specified in a boolean created by get_running_bool and modified by you
    as you please, to calculate the place field map for an arbitrary period of the session.
    :return:
    """

    make_session_list(list_dir)

    # Get position and time information for .csv file (later need to align to imaging)
    dir_use = get_dir(mouse, arena, day)
    speed, pos, t_track, sr = get_speed(dir_use)
    t_track = t_track[0:-1]  # chop last time data point to match t_track match speed/pos length

    # Display warning if "aligntoend" is in folder name but you are running with align_from_end=False
    if str(dir_use).upper().find('ALIGNTOEND') != -1 and align_from_end is False:
        print('Folder structure for ' + mouse + ' ' + arena + ': Day ' + str(day) + ' suggests you should align data from end of recording')
        print('RE-RUN WITH align_from_end=False!!!')

    # Import imaging data
    # im_data_file = path.join(dir_use + '\imaging', 'FinalOutput.mat')
    im_data_file = path.join(dir_use, 'FinalOutput.mat')
    im_data = sio.loadmat(im_data_file)
    PSAbool = im_data['PSAbool']
    nneurons, _ = np.shape(PSAbool)
    try:
        sr_image = im_data['SampleRate'].squeeze()
    except KeyError:
        sr_image = 20

    # Convert position to cm
    pix2cm = er.get_conv_factors(arena)  # get conversion to cm for the arena
    pos_cm = pos*pix2cm
    speed_cm = speed*pix2cm

    # Align imaging and position data
    pos_align, speed_align, PSAbool_align, time_interp = \
        align_imaging_to_tracking(pos_cm, speed_cm, t_track, PSAbool, sr_image, align_from_end=align_from_end)

    # Smooth speed data for legitimate thresholding, get limits of data
    speed_sm = np.convolve(speed_align, np.ones(2*int(sr))/(2*sr), mode='same')  # smooth speed

    # Get data limits
    if lims_method == 'auto':  # automatic by default
        lims = [np.min(pos_cm, axis=1), np.max(pos_cm, axis=1)]
    elif lims_method == 'file':  # file not yet enabled
        print('lims_method=''file'' not enabled yet')
    else:  # grab array!
        lims=lims_method

    good = np.ones(len(speed_sm)) == 1
    isrunning = good.copy()
    isrunning[speed_sm < speed_thresh] = False

    # Break up session into halves if necessary.
    if half is not None:
        # Identify # minutes and when half occurs
        half_id = np.floor(len(isrunning) / 2).astype('int')
        nminutes = np.ceil(len(isrunning) / sr_image / 60).astype(int)

        # Now chop things up!
        if half == 1:
            isrunning[half_id:] = False
        elif half == 2:
            isrunning[:half_id] = False
        elif half in ('odd', 'even'):
            odd_even_bool = np.zeros_like(isrunning, dtype=bool)
            start_minute = np.where([half == epoch for epoch in ['odd', 'even']])[0][0]
            for a in range(start_minute, nminutes, 2):
                odd_even_bool[a * 60 * sr_image:(a + 1) * 60 * sr_image] = 1
            isrunning[~odd_even_bool] = False

    # Use custom period for calculating placefields if specified
    if isrunning_custom is not None:
        isrunning = isrunning_custom

    # Get the mouse's occupancy in each spatial bin
    occmap, runoccmap, xEdges, yEdges, xBin, yBin = \
        makeoccmap(pos_align, lims, good, isrunning, cmperbin)

    # Get rid of non-running epochs
    xrun = pos_align[0, isrunning]
    yrun = pos_align[1, isrunning]
    PSAboolrun = PSAbool_align[:, isrunning]

    nGood = len(xrun)

    # Construct place field and compute mutual information
    neurons = list(range(0, nneurons))
    tmap_us, tcounts, tmap_gauss = [], [], []
    for idn, neuron in enumerate(neurons):
        tmap_us_temp, tcounts_temp, tmap_gauss_temp = \
            makeplacefield(PSAboolrun[neuron, :], xrun, yrun, xEdges, yEdges, runoccmap,
                       cmperbin=cmperbin)
        tmap_us.append(tmap_us_temp)
        tcounts.append(tcounts_temp)
        tmap_gauss.append(tmap_gauss_temp)

    # calculate mutual information
    mi, _, _, _, _ = spatinfo(tmap_us, runoccmap, PSAboolrun)

    # Shuffle to get p-value!
    pval, tmap_sm_shuf = [], []
    print('Shuffling to get placefield p-values')
    for neuron in tqdm(np.arange(nneurons)):
        rtmap, rtmap_sm = [], []
        shifts = np.random.randint(0, nGood, nshuf)
        for ns in np.arange(nshuf):
            # circularly shift PSAbool to disassociate transients from mouse location
            shuffled = np.roll(PSAboolrun[neuron, :], shifts[ns])
            map_temp, _, sm_map_temp = makeplacefield(shuffled, xrun, yrun, xEdges, yEdges, runoccmap,
                                      cmperbin=cmperbin)
            rtmap.append(map_temp)
            rtmap_sm.append(sm_map_temp)

        # Calculate mutual information of randomized vectors
        rmi, _, _, _, _ = spatinfo(rtmap, runoccmap, repmat(PSAboolrun[neuron, :], nshuf, 1))

        # Calculate p-value
        pval.append(1 - np.sum(mi[neuron] > rmi) / nshuf)

        # Aggregate shuffled maps if specified (worried this might kill memory)
        if keep_shuffled:
            tmap_sm_shuf.append(rtmap_sm)

    # save variables to working dirs as .pkl files in PFobject
    PFobj = PlaceFieldObject(tmap_us, tmap_gauss, xrun, yrun, PSAboolrun, occmap, runoccmap,
                 xEdges, yEdges, xBin, yBin, tcounts, pval, mi, pos_align, PSAbool_align,
                 speed_sm, isrunning, cmperbin, speed_thresh, mouse, arena, day, list_dir,
                             nshuf, sr_image, tmap_sm_shuf)

    if save_file is not None:
        PFobj.save_data(filename=save_file)

    return PFobj