예제 #1
0
def run_denoised_caiman_pipeline(movie,
                                 fr,
                                 loaddir,
                                 savedir,
                                 usematlabroi,
                                 onlyspikepursuit=False):
    #%%
    filenames = os.listdir(loaddir)

    for filename in filenames:  # findinf mmap file
        if filename[-4:] == 'mmap':
            break
    filename = os.path.join(loaddir, filename)
    cpu_num = 4
    cpu_num_spikepursuit = 2
    #%%

    gsig_filt_micron = (4, 4)
    max_shifts_micron = (6, 6)
    strides_micron = (50, 50)
    overlaps_micron = (25, 25)

    max_deviation_rigid_micron = 4

    pixel_size = movie['movie_pixel_size']

    ROIs = None  # Region of interests
    index = None  # index of neurons
    weights = None  # reuse spatial weights by
    # opts.change_params(params_dict={'weights':vpy.estimates['weights']})
    # motion correction parameters
    pw_rigid = False  # flag for pw-rigid motion correction
    gSig_filt = tuple(
        np.asarray(np.round(np.asarray(gsig_filt_micron) / float(pixel_size)),
                   int))  # size of filter, in general gSig (see below),
    # change this one if algorithm does not work
    max_shifts = tuple(
        np.asarray(np.round(np.asarray(max_shifts_micron) / float(pixel_size)),
                   int))
    strides = tuple(
        np.asarray(np.round(np.asarray(strides_micron) / float(pixel_size)),
                   int)
    )  # start a new patch for pw-rigid motion correction every x pixels
    overlaps = tuple(
        np.asarray(np.round(np.asarray(overlaps_micron) / float(pixel_size)),
                   int)
    )  # start a new patch for pw-rigid motion correction every x pixels
    # overlap between pathes (size of patch strides+overlaps)
    max_deviation_rigid = int(
        round(max_deviation_rigid_micron / pixel_size)
    )  # maximum deviation allowed for patch with respect to rigid shifts
    border_nan = 'copy'
    opts_dict = {
        'fnames': filename,
        'fr': fr,
        'index': index,
        'ROIs': ROIs,
        'weights': weights,
        'pw_rigid': pw_rigid,
        'max_shifts': max_shifts,
        'gSig_filt': gSig_filt,
        'strides': strides,
        'overlaps': overlaps,
        'max_deviation_rigid': max_deviation_rigid,
        'border_nan': border_nan
    }
    opts = volparams(params_dict=opts_dict)

    # %% start a cluster for parallel processing
    if onlyspikepursuit:
        finishedfilenames = os.listdir(savedir)
        for fnow in finishedfilenames:
            if fnow[:6] == 'memmap':
                opts.change_params(
                    params_dict={'fnames': os.path.join(savedir, fnow)})
                break

        #%%

    else:
        c, dview, n_processes = cm.cluster.setup_cluster(backend='local',
                                                         n_processes=cpu_num,
                                                         single_thread=False)

        # % MOTION CORRECTION
        # Create a motion correction object with the specified parameters
        mcrig = MotionCorrect(filename,
                              dview=dview,
                              **opts.get_group('motion'))
        # Run piecewise rigid motion correction
        #%
        mcrig.motion_correct(save_movie=True)
        dview.terminate()

        # % MOTION CORRECTION2
        opts.change_params({'pw_rigid': True})
        c, dview, n_processes = cm.cluster.setup_cluster(backend='local',
                                                         n_processes=cpu_num,
                                                         single_thread=False)
        # Create a motion correction object with the specified parameters
        mc = MotionCorrect(mcrig.mmap_file,
                           dview=dview,
                           **opts.get_group('motion'))
        # Run piecewise rigid motion correction
        mc.motion_correct(save_movie=True)
        dview.terminate()

        # %% motion correction compared with original movie
        display_images = False
        if display_images:
            m_orig = cm.load(filename)
            m_rig = cm.load(mcrig.mmap_file)
            m_pwrig = cm.load(mc.mmap_file)
            ds_ratio = 0.2
            moviehandle = cm.concatenate([
                m_orig.resize(1, 1, ds_ratio) - mc.min_mov * mc.nonneg_movie,
                m_rig.resize(1, 1, ds_ratio),
                m_pwrig.resize(1, 1, ds_ratio)
            ],
                                         axis=2)
            moviehandle.play(fr=60, q_max=99.5,
                             magnification=2)  # press q to exit
            # % movie subtracted from the mean
            m_orig2 = (m_orig - np.mean(m_orig, axis=0))
            m_rig2 = (m_rig - np.mean(m_rig, axis=0))
            m_pwrig2 = (m_pwrig - np.mean(m_pwrig, axis=0))
            moviehandle1 = cm.concatenate([
                m_orig2.resize(1, 1, ds_ratio),
                m_rig2.resize(1, 1, ds_ratio),
                m_pwrig2.resize(1, 1, ds_ratio)
            ],
                                          axis=2)
            moviehandle1.play(fr=60, q_max=99.5, magnification=2)

        # %% Memory Mapping
        c, dview, n_processes = cm.cluster.setup_cluster(backend='local',
                                                         n_processes=cpu_num,
                                                         single_thread=False)
        border_to_0 = 0 if mc.border_nan == 'copy' else mc.border_to_0
        fname_new = cm.save_memmap_join(mc.mmap_file,
                                        base_name='memmap_',
                                        add_to_mov=border_to_0,
                                        dview=dview,
                                        n_chunks=10)
        dview.terminate()

        # %% change fnames to the new motion corrected one
        opts.change_params(params_dict={'fnames': fname_new})

    # %% SEGMENTATION

    roidir = savedir[:savedir.find('denoised_volpy'
                                   )] + 'Spikepursuit' + savedir[
                                       savedir.find('denoised_volpy') +
                                       len('denoised_volpy'):]
    try:
        files = os.listdir(roidir)
    except:
        files = []
    if usematlabroi and 'ROIs.mat' in files:
        ROIs = loadmat(os.path.join(roidir, 'ROIs.mat'))['ROIs']
        if len(np.shape(ROIs)) == 3:
            ROIs = np.moveaxis(np.asarray(ROIs, bool), 2, 0)
        else:
            ROIs = np.asarray([ROIs])
        all_rois = ROIs
        opts.change_params(
            params_dict={
                'ROIs': ROIs,
                'index': list(range(ROIs.shape[0])),
                'method': 'SpikePursuit'
            })

    else:
        #%
        print('WTF')
        # Create mean and correlation image
        use_maskrcnn = True  # set to True to predict the ROIs using the mask R-CNN
        if not use_maskrcnn:  # use manual annotations
            with h5py.File(path_ROIs, 'r') as fl:
                ROIs = fl['mov'][()]  # load ROIs
            opts.change_params(
                params_dict={
                    'ROIs': ROIs,
                    'index': list(range(ROIs.shape[0])),
                    'method': 'SpikePursuit'
                })
        else:
            try:
                m = cm.load(mc.mmap_file[0], subindices=slice(0, 20000))
            except:
                m = cm.load(
                    '/home/rozmar/Data/Voltage_imaging/Voltage_rig_1P/rozsam/20200120/40x_1xtube_10A_7_000_rig__d1_128_d2_512_d3_1_order_F_frames_2273_._els__d1_128_d2_512_d3_1_order_F_frames_2273_.mmap',
                    subindices=slice(0, 20000))
            m.fr = fr
            img = m.mean(axis=0)
            img = (img - np.mean(img)) / np.std(img)
            m1 = m.computeDFF(secsWindow=1, in_place=True)[0]
            m = m - m1
            Cn = m.local_correlations(swap_dim=False, eight_neighbours=True)
            img_corr = (Cn - np.mean(Cn)) / np.std(Cn)
            summary_image = np.stack([img, img, img_corr],
                                     axis=2).astype(np.float32)
            del m
            del m1

            # %
            # Mask R-CNN
            config = neurons.NeuronsConfig()

            class InferenceConfig(config.__class__):
                # Run detection on one image at a time
                GPU_COUNT = 1
                IMAGES_PER_GPU = 1
                DETECTION_MIN_CONFIDENCE = 0.7
                IMAGE_RESIZE_MODE = "pad64"
                IMAGE_MAX_DIM = 512
                RPN_NMS_THRESHOLD = 0.7
                POST_NMS_ROIS_INFERENCE = 1000

            config = InferenceConfig()
            config.display()
            model_dir = os.path.join(caiman_datadir(), 'model')
            DEVICE = "/cpu:0"  # /cpu:0 or /gpu:0
            with tf.device(DEVICE):
                model = modellib.MaskRCNN(mode="inference",
                                          model_dir=model_dir,
                                          config=config)
            weights_path = download_model('mask_rcnn')
            model.load_weights(weights_path, by_name=True)
            results = model.detect([summary_image], verbose=1)
            r = results[0]
            ROIs_mrcnn = r['masks'].transpose([2, 0, 1])

            # %visualize the result
            display_result = False
            if display_result:
                _, ax = plt.subplots(1, 1, figsize=(16, 16))
                visualize.display_instances(summary_image,
                                            r['rois'],
                                            r['masks'],
                                            r['class_ids'], ['BG', 'neurons'],
                                            r['scores'],
                                            ax=ax,
                                            title="Predictions")
        # %set rois
            opts.change_params(
                params_dict={
                    'ROIs': ROIs_mrcnn,
                    'index': list(range(ROIs_mrcnn.shape[0])),
                    'method': 'SpikePursuit'
                })
            #all_rois = ROIs_mrcnn

    # %% Trace Denoising and Spike Extraction

    c, dview, n_processes = cm.cluster.setup_cluster(
        backend='local',
        n_processes=cpu_num_spikepursuit,
        single_thread=False,
        maxtasksperchild=1)
    #dview=None
    vpy = VOLPY(n_processes=n_processes, dview=dview, params=opts)
    vpy.fit(n_processes=n_processes, dview=dview)

    #%%
    if not onlyspikepursuit:
        print('saving parameters')
        parameters = dict()
        parameters['motion'] = opts.motion
        parameters['data'] = opts.data
        parameters['volspike'] = opts.volspike
        with open(os.path.join(savedir, 'parameters.pickle'), 'wb') as outfile:
            pickle.dump(parameters, outfile)

        for mcidx, mc_now in enumerate([mcrig, mc]):
            motioncorr = dict()
            motioncorr['fname'] = mc_now.fname
            motioncorr['fname_tot_rig'] = mc_now.fname_tot_rig
            motioncorr['mmap_file'] = mc_now.mmap_file
            motioncorr['min_mov'] = mc_now.min_mov
            motioncorr['shifts_rig'] = mc_now.shifts_rig
            motioncorr['shifts_opencv'] = mc_now.shifts_opencv
            motioncorr['niter_rig'] = mc_now.niter_rig
            motioncorr['min_mov'] = mc_now.min_mov
            motioncorr['templates_rig'] = mc_now.templates_rig
            motioncorr['total_template_rig'] = mc_now.total_template_rig
            try:
                motioncorr['x_shifts_els'] = mc_now.x_shifts_els
                motioncorr['y_shifts_els'] = mc_now.y_shifts_els
            except:
                pass
            with open(
                    os.path.join(savedir,
                                 'motion_corr_' + str(mcidx) + '.pickle'),
                    'wb') as outfile:
                pickle.dump(motioncorr, outfile)
            #%% saving stuff
        #os.remove(str(mcrig.fname))
        print('moving files')
        for mmap_file in mcrig.mmap_file:
            fname = pathlib.Path(mmap_file).name
            os.remove(mmap_file)
            #shutil.move(mmap_file, os.path.join(savedir,fname))
        for mmap_file in mc.mmap_file:
            fname = pathlib.Path(mmap_file).name
            os.remove(mmap_file)
            #shutil.move(mmap_file, os.path.join(savedir,fname))
    #%%
    volspikedata = dict()
    volspikedata['estimates'] = vpy.estimates
    volspikedata['params'] = vpy.params.data
    with open(os.path.join(savedir, 'spikepursuit.pickle'), 'wb') as outfile:
        pickle.dump(volspikedata, outfile)
    #%%

    #%%
    #fname = pathlib.Path(fname_new).name
    #shutil.move(fname_new, os.path.join(savedir,fname))
    #print('waiting')
    #time.sleep(1000)
    # %% some visualization
    plotstuff = False
    if plotstuff:
        print(np.where(vpy.estimates['passedLocalityTest'])
              [0])  # neurons that pass locality test
        n = 0

        # Processed signal and spikes of neurons
        plt.figure()
        plt.plot(vpy.estimates['trace'][n])
        plt.plot(vpy.estimates['spikeTimes'][n],
                 np.max(vpy.estimates['trace'][n]) *
                 np.ones(vpy.estimates['spikeTimes'][n].shape),
                 color='g',
                 marker='o',
                 fillstyle='none',
                 linestyle='none')
        plt.title('signal and spike times')
        plt.show()
        # Location of neurons by Mask R-CNN or manual annotation
        plt.figure()
        if use_maskrcnn:
            plt.imshow(ROIs_mrcnn[n])
        else:
            plt.imshow(ROIs[n])
        mv = cm.load(fname_new)
        plt.imshow(mv.mean(axis=0), alpha=0.5)

        # Spatial filter created by algorithm
        plt.figure()
        plt.imshow(vpy.estimates['spatialFilter'][n])
        plt.colorbar()
        plt.title('spatial filter')
        plt.show()

    # %% STOP CLUSTER and clean up log files

    cm.stop_server(dview=dview)
    log_files = glob.glob('*_LOG_*')
    for log_file in log_files:
        os.remove(log_file)
예제 #2
0
def run_volpy(fnames,
              options=None,
              do_motion_correction=True,
              do_memory_mapping=True,
              fr=400):
    #pass  # For compatibility between running under Spyder and the CLI

    # %%  Load demo movie and ROIs
    file_dir = os.path.split(fnames)[0]
    path_ROIs = [file for file in os.listdir(file_dir) if 'ROIs_gt' in file]
    if len(path_ROIs) > 0:
        path_ROIs = path_ROIs[0]
    #path_ROIs = '/home/nel/NEL-LAB Dropbox/NEL/Datasets/voltage_lin/peyman_golshani/ROIs.hdf5'

#%% dataset dependent parameters
# dataset dependent parameters
    fr = fr  # sample rate of the movie

    # motion correction parameters
    pw_rigid = False  # flag for pw-rigid motion correction
    gSig_filt = (3, 3)  # size of filter, in general gSig (see below),
    # change this one if algorithm does not work
    max_shifts = (5, 5)  # maximum allowed rigid shift
    strides = (
        48, 48
    )  # start a new patch for pw-rigid motion correction every x pixels
    overlaps = (24, 24
                )  # overlap between pathes (size of patch strides+overlaps)
    max_deviation_rigid = 3  # maximum deviation allowed for patch with respect to rigid shifts
    border_nan = 'copy'

    opts_dict = {
        'fnames': fnames,
        'fr': fr,
        'pw_rigid': pw_rigid,
        'max_shifts': max_shifts,
        'gSig_filt': gSig_filt,
        'strides': strides,
        'overlaps': overlaps,
        'max_deviation_rigid': max_deviation_rigid,
        'border_nan': border_nan
    }

    opts = volparams(params_dict=opts_dict)

    # %% start a cluster for parallel processing
    c, dview, n_processes = cm.cluster.setup_cluster(backend='local',
                                                     n_processes=None,
                                                     single_thread=False)

    # %%% MOTION CORRECTION
    # first we create a motion correction object with the specified parameters
    mc = MotionCorrect(fnames, dview=dview, **opts.get_group('motion'))
    # Run correction
    do_motion_correction = do_motion_correction
    if do_motion_correction:
        mc.motion_correct(save_movie=True)
    else:
        mc_list = [
            file for file in os.listdir(file_dir)
            if (os.path.splitext(os.path.split(fnames)[-1])[0] in file
                and '.mmap' in file)
        ]
        mc.mmap_file = [os.path.join(file_dir, mc_list[0])]
        print(f'reuse previously saved motion corrected file:{mc.mmap_file}')

# %% MEMORY MAPPING
    do_memory_mapping = do_memory_mapping
    if do_memory_mapping:
        border_to_0 = 0 if mc.border_nan == 'copy' else mc.border_to_0
        # you can include the boundaries of the FOV if you used the 'copy' option
        # during motion correction, although be careful about the components near
        # the boundaries

        # memory map the file in order 'C'
        fname_new = cm.save_memmap_join(
            mc.mmap_file,
            base_name='memmap_' +
            os.path.splitext(os.path.split(fnames)[-1])[0],
            add_to_mov=border_to_0,
            dview=dview)  # exclude border
    else:
        mmap_list = [
            file for file in os.listdir(file_dir)
            if ('memmap_' +
                os.path.splitext(os.path.split(fnames)[-1])[0]) in file
        ]
        fname_new = os.path.join(file_dir, mmap_list[0])
        print(f'reuse previously saved memory mapping file:{fname_new}')

# %% SEGMENTATION
# create summary images
    img = mean_image(mc.mmap_file[0], window=1000, dview=dview)
    img = (img - np.mean(img)) / np.std(img)

    gaussian_blur = False  # Use gaussian blur when there is too much noise in the video
    Cn = local_correlations_movie_offline(mc.mmap_file[0],
                                          fr=fr,
                                          window=fr * 4,
                                          stride=fr * 4,
                                          winSize_baseline=fr,
                                          remove_baseline=True,
                                          gaussian_blur=gaussian_blur,
                                          dview=dview).max(axis=0)
    img_corr = (Cn - np.mean(Cn)) / np.std(Cn)
    summary_images = np.stack([img, img, img_corr], axis=0).astype(np.float32)
    # ! save summary image, it is used in GUI
    cm.movie(summary_images).save(fnames[:-5] + '_summary_images.tif')
    #plt.imshow(summary_images[0])
    #%% three methods for segmentation
    methods_list = [
        'manual_annotation',  # manual annotation needs user to prepare annotated datasets same format as demo ROIs 
        'gui_annotation',  # use gui to manually annotate neurons, but this is still under developing
        'maskrcnn'
    ]  # maskrcnn is a convolutional network trained for finding neurons using summary images
    method = methods_list[0]
    if method == 'manual_annotation':
        #with h5py.File(path_ROIs, 'r') as fl:
        #    ROIs = fl['mov'][()]
        ROIs = np.load(os.path.join(file_dir, path_ROIs))

    elif method == 'gui_annotation':
        # run volpy_gui file in the caiman/source_extraction/volpy folder
        # load the summary images you have just saved
        # save the ROIs to the video folder
        path_ROIs = caiman_datadir() + '/example_movies/volpy/gui_roi.hdf5'
        with h5py.File(path_ROIs, 'r') as fl:
            ROIs = fl['mov'][()]

    elif method == 'maskrcnn':  # Important!! make sure install keras before using mask rcnn
        weights_path = download_model('mask_rcnn')
        weights_path = '/home/nel/Code/NEL_LAB/Mask_RCNN/logs/neurons20200824T1032/mask_rcnn_neurons_0040.h5'
        ROIs = utils.mrcnn_inference(
            img=summary_images.transpose([1, 2, 0]),
            size_range=[5, 100],
            weights_path=weights_path,
            display_result=True
        )  # size parameter decides size range of masks to be selected
        #np.save(os.path.join(file_dir, 'ROIs'), ROIs)
# %% restart cluster to clean up memory
    cm.stop_server(dview=dview)
    c, dview, n_processes = cm.cluster.setup_cluster(backend='local',
                                                     n_processes=None,
                                                     single_thread=False,
                                                     maxtasksperchild=1)

    # %% parameters for trace denoising and spike extraction
    ROIs = ROIs  # region of interests
    index = list(range(len(ROIs)))  # index of neurons
    weights = None  # reuse spatial weights

    context_size = 35  # number of pixels surrounding the ROI to censor from the background PCA
    flip_signal = True  # Important!! Flip signal or not, True for Voltron indicator, False for others
    hp_freq_pb = 1 / 3  # parameter for high-pass filter to remove photobleaching
    threshold_method = 'adaptive_threshold'  # 'simple' or 'adaptive_threshold'
    min_spikes = 30  # minimal spikes to be found
    threshold = 4  # threshold for finding spikes, increase threshold to find less spikes
    do_plot = False  # plot detail of spikes, template for the last iteration
    ridge_bg = 0.01  # ridge regression regularizer strength for background removement, larger value specifies stronger regularization
    sub_freq = 20  # frequency for subthreshold extraction
    weight_update = 'ridge'  # 'ridge' or 'NMF' for weight update
    n_iter = 2

    opts_dict = {
        'fnames': fname_new,
        'ROIs': ROIs,
        'index': index,
        'weights': weights,
        'context_size': context_size,
        'flip_signal': flip_signal,
        'hp_freq_pb': hp_freq_pb,
        'threshold_method': threshold_method,
        'min_spikes': min_spikes,
        'threshold': threshold,
        'do_plot': do_plot,
        'ridge_bg': ridge_bg,
        'sub_freq': sub_freq,
        'weight_update': weight_update,
        'n_iter': n_iter
    }

    opts.change_params(params_dict=opts_dict)

    if options is not None:
        print('using external options')
        opts.change_params(params_dict=options)
    else:
        print('not using external options')

#%% TRACE DENOISING AND SPIKE DETECTION
    vpy = VOLPY(n_processes=n_processes, dview=dview, params=opts)
    vpy.fit(n_processes=n_processes, dview=dview)

    #%% visualization
    display_images = False
    if display_images:
        print(np.where(
            vpy.estimates['locality'])[0])  # neurons that pass locality test
        idx = np.where(vpy.estimates['locality'] > 0)[0]
        utils.view_components(vpy.estimates, img_corr, idx)

#%% reconstructed movie
# note the negative spatial weights is cutoff
    if display_images:
        mv_all = utils.reconstructed_movie(vpy.estimates,
                                           fnames=mc.mmap_file,
                                           idx=idx,
                                           scope=(0, 1000),
                                           flip_signal=flip_signal)
        mv_all.play(fr=40)

#%% save the result in .npy format
    save_result = True
    if save_result:
        vpy.estimates['ROIs'] = ROIs
        save_name = f'volpy_{os.path.split(fnames)[1][:-5]}_{opts.volspike["threshold_method"]}_{opts.volspike["threshold"]}_{opts.volspike["weight_update"]}_bg_{opts.volspike["ridge_bg"]}'
        np.save(os.path.join(file_dir, save_name), vpy.estimates)

# %% STOP CLUSTER and clean up log files
    cm.stop_server(dview=dview)
    log_files = glob.glob('*_LOG_*')
    for log_file in log_files:
        os.remove(log_file)
예제 #3
0
def run_caiman_pipeline(movie, fr, fnames, savedir, caiman_parameters):
    #%%
    usematlabroi = caiman_parameters['usematlabroi']

    cpu_num = 16
    cpu_num_spikepursuit = 3
    #gsig_filt_micron = (4, 4)
    #max_shifts_micron = (6,6)
    #strides_micron = (60,60)
    #overlaps_micron = (30, 30)

    gsig_filt_micron = (4, 4)
    max_shifts_micron = (6, 6)
    strides_micron = (30, 30)
    overlaps_micron = (15, 15)

    max_deviation_rigid_micron = 4

    pixel_size = movie['movie_pixel_size']

    ROIs = None  # Region of interests
    index = None  # index of neurons
    weights = None  # reuse spatial weights by
    # opts.change_params(params_dict={'weights':vpy.estimates['weights']})
    # motion correction parameters
    pw_rigid = False  # flag for pw-rigid motion correction
    gSig_filt = tuple(
        np.asarray(np.round(np.asarray(gsig_filt_micron) / float(pixel_size)),
                   int))  # size of filter, in general gSig (see below),
    # change this one if algorithm does not work
    max_shifts = tuple(
        np.asarray(np.round(np.asarray(max_shifts_micron) / float(pixel_size)),
                   int))
    strides = tuple(
        np.asarray(np.round(np.asarray(strides_micron) / float(pixel_size)),
                   int)
    )  # start a new patch for pw-rigid motion correction every x pixels
    overlaps = tuple(
        np.asarray(np.round(np.asarray(overlaps_micron) / float(pixel_size)),
                   int)
    )  # start a new patch for pw-rigid motion correction every x pixels
    # overlap between pathes (size of patch strides+overlaps)
    max_deviation_rigid = int(
        round(max_deviation_rigid_micron / pixel_size)
    )  # maximum deviation allowed for patch with respect to rigid shifts
    border_nan = 'copy'
    opts_dict = {
        'fnames': fnames,
        'fr': fr,
        'index': index,
        'ROIs': ROIs,
        'weights': weights,
        'pw_rigid': pw_rigid,
        'max_shifts': max_shifts,
        'gSig_filt': gSig_filt,
        'strides': strides,
        'overlaps': overlaps,
        'max_deviation_rigid': max_deviation_rigid,
        'border_nan': border_nan
    }
    opts = volparams(params_dict=opts_dict)
    #%%
    if not caiman_parameters['motion_correction_already_done']:

        # %% play the movie (optional)
        # playing the movie using opencv. It requires loading the movie in memory.
        # To close the video press q
        display_images = False

        if display_images:
            m_orig = cm.load(fnames)
            ds_ratio = 0.2
            moviehandle = m_orig.resize(1, 1, ds_ratio)
            moviehandle.play(q_max=99.5, fr=60, magnification=2)

        # %% start a cluster for parallel processing

        c, dview, n_processes = cm.cluster.setup_cluster(backend='local',
                                                         n_processes=cpu_num,
                                                         single_thread=False)

        # % MOTION CORRECTION
        # Create a motion correction object with the specified parameters
        mcrig = MotionCorrect(fnames, dview=dview, **opts.get_group('motion'))
        # Run piecewise rigid motion correction
        #%
        mcrig.motion_correct(save_movie=True)
        dview.terminate()

        # % MOTION CORRECTION2
        opts.change_params({'pw_rigid': True})
        c, dview, n_processes = cm.cluster.setup_cluster(backend='local',
                                                         n_processes=cpu_num,
                                                         single_thread=False)
        # Create a motion correction object with the specified parameters
        mc = MotionCorrect(mcrig.mmap_file,
                           dview=dview,
                           **opts.get_group('motion'))
        # Run piecewise rigid motion correction
        mc.motion_correct(save_movie=True)
        dview.terminate()

        # %% motion correction compared with original movie
        display_images = False
        if display_images:
            m_orig = cm.load(fnames)
            m_rig = cm.load(mcrig.mmap_file)
            m_pwrig = cm.load(mc.mmap_file)
            ds_ratio = 0.2
            moviehandle = cm.concatenate([
                m_orig.resize(1, 1, ds_ratio) - mc.min_mov * mc.nonneg_movie,
                m_rig.resize(1, 1, ds_ratio),
                m_pwrig.resize(1, 1, ds_ratio)
            ],
                                         axis=2)
            moviehandle.play(fr=60, q_max=99.5,
                             magnification=2)  # press q to exit
            # % movie subtracted from the mean
            m_orig2 = (m_orig - np.mean(m_orig, axis=0))
            m_rig2 = (m_rig - np.mean(m_rig, axis=0))
            m_pwrig2 = (m_pwrig - np.mean(m_pwrig, axis=0))
            moviehandle1 = cm.concatenate([
                m_orig2.resize(1, 1, ds_ratio),
                m_rig2.resize(1, 1, ds_ratio),
                m_pwrig2.resize(1, 1, ds_ratio)
            ],
                                          axis=2)
            moviehandle1.play(fr=60, q_max=99.5, magnification=2)

        # %% Memory Mapping
        c, dview, n_processes = cm.cluster.setup_cluster(backend='local',
                                                         n_processes=cpu_num,
                                                         single_thread=False)
        border_to_0 = 0 if mc.border_nan == 'copy' else mc.border_to_0
        fname_new = cm.save_memmap_join(mc.mmap_file,
                                        base_name='memmap_',
                                        add_to_mov=border_to_0,
                                        dview=dview,
                                        n_chunks=10)
        dview.terminate()

        # %% change fnames to the new motion corrected one
        opts.change_params(params_dict={'fnames': fname_new})
    else:
        #%%
        files = os.listdir(savedir)
        for file in files:
            if '.mmap' in file:
                break
        fname_new = os.path.join(savedir, file)
        opts.change_params(params_dict={'fnames': fname_new})

    # %% SEGMENTATION
    if caiman_parameters['dospikepursuit']:
        roidir_matlab = savedir[:savedir.find(
            'VolPy')] + 'Spikepursuit' + savedir[savedir.find('VolPy') +
                                                 len('Volpy'):]
        try:
            files_matlab = os.listdir(roidir)
        except:
            files_matlab = []
        roidir_volpy = savedir[:savedir.find('VolPy')] + 'ROI' + savedir[
            savedir.find('VolPy') + len('Volpy'):]
        try:
            files_volpy = os.listdir(roidir_volpy)
        except:
            files_volpy = []
        if usematlabroi and 'ROIs.mat' in files_matlab:
            ROIs = loadmat(os.path.join(roidir_matlab, 'ROIs.mat'))['ROIs']
            if len(np.shape(ROIs)) == 3:
                ROIs = np.moveaxis(np.asarray(ROIs, bool), 2, 0)
            else:
                ROIs = np.asarray([ROIs])
            all_rois = ROIs
            opts.change_params(
                params_dict={
                    'ROIs': ROIs,
                    'index': list(range(ROIs.shape[0])),
                    'method': 'SpikePursuit'
                })
        elif caiman_parameters['usevolpyroi'] and 'VolPy.npy' in files_volpy:
            ROIs_original = np.load(os.path.join(roidir_volpy, 'VolPy.npy'))
            roinum = int(np.max(np.unique(ROIs_original)))
            ROIs = np.asarray(
                np.zeros([
                    int(roinum), ROIs_original.shape[0], ROIs_original.shape[1]
                ]), bool)
            for i in range(1, roinum + 1):
                ROIs[i - 1, ROIs_original == i] = True

            all_rois = ROIs
            opts.change_params(
                params_dict={
                    'ROIs': ROIs,
                    'index': list(range(ROIs.shape[0])),
                    'method': 'SpikePursuit'
                })
        else:
            #%
            print('WTF')

        # %% Trace Denoising and Spike Extraction

        c, dview, n_processes = cm.cluster.setup_cluster(
            backend='local',
            n_processes=cpu_num_spikepursuit,
            single_thread=False,
            maxtasksperchild=1)
        #dview=None
        vpy = VOLPY(n_processes=n_processes, dview=dview, params=opts)
        vpy.fit(n_processes=n_processes, dview=dview)

    #%%
    if caiman_parameters['dospikepursuit']:
        volspikedata = dict()
        volspikedata['estimates'] = vpy.estimates
        volspikedata['params'] = vpy.params.data
        with open(os.path.join(savedir, 'spikepursuit.pickle'),
                  'wb') as outfile:
            pickle.dump(volspikedata, outfile)

    if not caiman_parameters['motion_correction_already_done']:
        print('saving parameters')
        parameters = dict()
        parameters['motion'] = opts.motion
        parameters['data'] = opts.data
        if caiman_parameters['dospikepursuit']:
            parameters['volspike'] = opts.volspike
        with open(os.path.join(savedir, 'parameters.pickle'), 'wb') as outfile:
            pickle.dump(parameters, outfile)
        #%

        #%

        for mcidx, mc_now in enumerate([mcrig, mc]):
            motioncorr = dict()
            motioncorr['fname'] = mc_now.fname
            motioncorr['fname_tot_rig'] = mc_now.fname_tot_rig
            motioncorr['mmap_file'] = mc_now.mmap_file
            motioncorr['min_mov'] = mc_now.min_mov
            motioncorr['shifts_rig'] = mc_now.shifts_rig
            motioncorr['shifts_opencv'] = mc_now.shifts_opencv
            motioncorr['niter_rig'] = mc_now.niter_rig
            motioncorr['min_mov'] = mc_now.min_mov
            motioncorr['templates_rig'] = mc_now.templates_rig
            motioncorr['total_template_rig'] = mc_now.total_template_rig
            try:
                motioncorr['x_shifts_els'] = mc_now.x_shifts_els
                motioncorr['y_shifts_els'] = mc_now.y_shifts_els
            except:
                pass
            with open(
                    os.path.join(savedir,
                                 'motion_corr_' + str(mcidx) + '.pickle'),
                    'wb') as outfile:
                pickle.dump(motioncorr, outfile)
        #%saving stuff
        print('moving files')
        for mmap_file in mcrig.mmap_file:
            fname = pathlib.Path(mmap_file).name
            os.remove(mmap_file)
            #shutil.move(mmap_file, os.path.join(savedir,fname))
        for mmap_file in mc.mmap_file:
            fname = pathlib.Path(mmap_file).name
            os.remove(mmap_file)
            #shutil.move(mmap_file, os.path.join(savedir,fname))

        fname = pathlib.Path(fname_new).name

        #Thread(target=shutil.copy, args=[fname_new, os.path.join(savedir,fname)]).start()
        shutil.move(fname_new, os.path.join(savedir, fname))

    #print('waiting')
    #time.sleep(1000)
    # %% some visualization
    plotstuff = False
    if plotstuff:
        print(np.where(vpy.estimates['passedLocalityTest'])
              [0])  # neurons that pass locality test
        n = 0

        # Processed signal and spikes of neurons
        plt.figure()
        plt.plot(vpy.estimates['trace'][n])
        plt.plot(vpy.estimates['spikeTimes'][n],
                 np.max(vpy.estimates['trace'][n]) *
                 np.ones(vpy.estimates['spikeTimes'][n].shape),
                 color='g',
                 marker='o',
                 fillstyle='none',
                 linestyle='none')
        plt.title('signal and spike times')
        plt.show()
        # Location of neurons by Mask R-CNN or manual annotation
        plt.figure()
        if use_maskrcnn:
            plt.imshow(ROIs_mrcnn[n])
        else:
            plt.imshow(ROIs[n])
        mv = cm.load(fname_new)
        plt.imshow(mv.mean(axis=0), alpha=0.5)

        # Spatial filter created by algorithm
        plt.figure()
        plt.imshow(vpy.estimates['spatialFilter'][n])
        plt.colorbar()
        plt.title('spatial filter')
        plt.show()

    # %% STOP CLUSTER and clean up log files

    cm.stop_server(dview=dview)
    log_files = glob.glob('*_LOG_*')
    for log_file in log_files:
        os.remove(log_file)
예제 #4
0
def run_modified_caiman_pipeline(movie, fr, fnames, savedir,
                                 registered_movie_file, usematlabroi):
    #%%
    cpu_num = 12
    cpu_num_spikepursuit = 3
    #gsig_filt_micron = (4, 4)
    #max_shifts_micron = (6,6)
    #strides_micron = (60,60)
    #overlaps_micron = (30, 30)

    gsig_filt_micron = (4, 4)
    max_shifts_micron = (6, 6)
    strides_micron = (30, 30)
    overlaps_micron = (15, 15)

    max_deviation_rigid_micron = 4

    pixel_size = movie['movie_pixel_size']

    ROIs = None  # Region of interests
    index = None  # index of neurons
    weights = None  # reuse spatial weights by
    # opts.change_params(params_dict={'weights':vpy.estimates['weights']})
    # motion correction parameters
    pw_rigid = False  # flag for pw-rigid motion correction
    gSig_filt = tuple(
        np.asarray(np.round(np.asarray(gsig_filt_micron) / float(pixel_size)),
                   int))  # size of filter, in general gSig (see below),
    # change this one if algorithm does not work
    max_shifts = tuple(
        np.asarray(np.round(np.asarray(max_shifts_micron) / float(pixel_size)),
                   int))
    strides = tuple(
        np.asarray(np.round(np.asarray(strides_micron) / float(pixel_size)),
                   int)
    )  # start a new patch for pw-rigid motion correction every x pixels
    overlaps = tuple(
        np.asarray(np.round(np.asarray(overlaps_micron) / float(pixel_size)),
                   int)
    )  # start a new patch for pw-rigid motion correction every x pixels
    # overlap between pathes (size of patch strides+overlaps)
    max_deviation_rigid = int(
        round(max_deviation_rigid_micron / pixel_size)
    )  # maximum deviation allowed for patch with respect to rigid shifts
    border_nan = 'copy'
    opts_dict = {
        'fnames': registered_movie_file,
        'fr': fr,
        'index': index,
        'ROIs': ROIs,
        'weights': weights,
        'pw_rigid': pw_rigid,
        'max_shifts': max_shifts,
        'gSig_filt': gSig_filt,
        'strides': strides,
        'overlaps': overlaps,
        'max_deviation_rigid': max_deviation_rigid,
        'border_nan': border_nan
    }
    opts = volparams(params_dict=opts_dict)

    # %% SEGMENTATION

    roidir = savedir[:savedir.find('VolPy_modified'
                                   )] + 'Spikepursuit' + savedir[
                                       savedir.find('VolPy_modified') +
                                       len('VolPy_modified'):]
    try:
        files = os.listdir(roidir)
    except:
        files = []
    if usematlabroi and 'ROIs.mat' in files:
        ROIs = loadmat(os.path.join(roidir, 'ROIs.mat'))['ROIs']
        if len(np.shape(ROIs)) == 3:
            ROIs = np.moveaxis(np.asarray(ROIs, bool), 2, 0)
        else:
            ROIs = np.asarray([ROIs])
        all_rois = ROIs
        opts.change_params(
            params_dict={
                'ROIs': ROIs,
                'index': list(range(ROIs.shape[0])),
                'method': 'SpikePursuit'
            })

    else:
        #%
        print('WTF.. no ROIs defined.. sleeping')
        time.sleep(1000)
    # %% Trace Denoising and Spike Extraction

    c, dview, n_processes = cm.cluster.setup_cluster(
        backend='local',
        n_processes=cpu_num_spikepursuit,
        single_thread=False,
        maxtasksperchild=1)
    #dview=None
    vpy_modified = VOLPY(n_processes=n_processes, dview=dview, params=opts)
    vpy_modified.fit(n_processes=n_processes, dview=dview)

    #%%
    print('saving parameters')
    parameters = dict()
    parameters['motion'] = opts.motion
    parameters['data'] = opts.data
    parameters['volspike'] = opts.volspike
    #%%
    with open(os.path.join(savedir, 'parameters.pickle'), 'wb') as outfile:
        pickle.dump(parameters, outfile)
    #%%
    volspikedata = dict()
    volspikedata['estimates'] = vpy.estimates
    volspikedata['params'] = vpy.params.data
    with open(os.path.join(savedir, 'spikepursuit.pickle'), 'wb') as outfile:
        pickle.dump(volspikedata, outfile)
    #%%

    for mcidx, mc_now in enumerate([mcrig, mc]):
        motioncorr = dict()
        motioncorr['fname'] = mc_now.fname
        motioncorr['fname_tot_rig'] = mc_now.fname_tot_rig
        motioncorr['mmap_file'] = mc_now.mmap_file
        motioncorr['min_mov'] = mc_now.min_mov
        motioncorr['shifts_rig'] = mc_now.shifts_rig
        motioncorr['shifts_opencv'] = mc_now.shifts_opencv
        motioncorr['niter_rig'] = mc_now.niter_rig
        motioncorr['min_mov'] = mc_now.min_mov
        motioncorr['templates_rig'] = mc_now.templates_rig
        motioncorr['total_template_rig'] = mc_now.total_template_rig
        try:
            motioncorr['x_shifts_els'] = mc_now.x_shifts_els
            motioncorr['y_shifts_els'] = mc_now.y_shifts_els
        except:
            pass
        with open(
                os.path.join(savedir, 'motion_corr_' + str(mcidx) + '.pickle'),
                'wb') as outfile:
            pickle.dump(motioncorr, outfile)
    #%% saving stuff
    print('moving files')
    for mmap_file in mcrig.mmap_file:
        fname = pathlib.Path(mmap_file).name
        os.remove(mmap_file)
        #shutil.move(mmap_file, os.path.join(savedir,fname))
    for mmap_file in mc.mmap_file:
        fname = pathlib.Path(mmap_file).name
        os.remove(mmap_file)
        #shutil.move(mmap_file, os.path.join(savedir,fname))

    fname = pathlib.Path(fname_new).name

    #Thread(target=shutil.copy, args=[fname_new, os.path.join(savedir,fname)]).start()
    shutil.move(fname_new, os.path.join(savedir, fname))

    #print('waiting')
    #time.sleep(1000)
    # %% some visualization
    plotstuff = False
    if plotstuff:
        print(np.where(vpy.estimates['passedLocalityTest'])
              [0])  # neurons that pass locality test
        n = 0

        # Processed signal and spikes of neurons
        plt.figure()
        plt.plot(vpy.estimates['trace'][n])
        plt.plot(vpy.estimates['spikeTimes'][n],
                 np.max(vpy.estimates['trace'][n]) *
                 np.ones(vpy.estimates['spikeTimes'][n].shape),
                 color='g',
                 marker='o',
                 fillstyle='none',
                 linestyle='none')
        plt.title('signal and spike times')
        plt.show()
        # Location of neurons by Mask R-CNN or manual annotation
        plt.figure()
        if use_maskrcnn:
            plt.imshow(ROIs_mrcnn[n])
        else:
            plt.imshow(ROIs[n])
        mv = cm.load(fname_new)
        plt.imshow(mv.mean(axis=0), alpha=0.5)

        # Spatial filter created by algorithm
        plt.figure()
        plt.imshow(vpy.estimates['spatialFilter'][n])
        plt.colorbar()
        plt.title('spatial filter')
        plt.show()

    # %% STOP CLUSTER and clean up log files

    cm.stop_server(dview=dview)
    log_files = glob.glob('*_LOG_*')
    for log_file in log_files:
        os.remove(log_file)
def main():
    pass  # For compatibility between running under Spyder and the CLI

    # %%  Load demo movie and ROIs
    fnames = download_demo(
        'demo_voltage_imaging.hdf5',
        'volpy')  # file path to movie file (will download if not present)
    path_ROIs = download_demo(
        'demo_voltage_imaging_ROIs.hdf5',
        'volpy')  # file path to ROIs file (will download if not present)
    file_dir = os.path.split(fnames)[0]

    #%% dataset dependent parameters
    # dataset dependent parameters
    fr = 400  # sample rate of the movie

    # motion correction parameters
    pw_rigid = False  # flag for pw-rigid motion correction
    gSig_filt = (3, 3)  # size of filter, in general gSig (see below),
    # change this one if algorithm does not work
    max_shifts = (5, 5)  # maximum allowed rigid shift
    strides = (
        48, 48
    )  # start a new patch for pw-rigid motion correction every x pixels
    overlaps = (24, 24
                )  # overlap between pathes (size of patch strides+overlaps)
    max_deviation_rigid = 3  # maximum deviation allowed for patch with respect to rigid shifts
    border_nan = 'copy'

    opts_dict = {
        'fnames': fnames,
        'fr': fr,
        'pw_rigid': pw_rigid,
        'max_shifts': max_shifts,
        'gSig_filt': gSig_filt,
        'strides': strides,
        'overlaps': overlaps,
        'max_deviation_rigid': max_deviation_rigid,
        'border_nan': border_nan
    }

    opts = volparams(params_dict=opts_dict)

    # %% play the movie (optional)
    # playing the movie using opencv. It requires loading the movie in memory.
    # To close the movie press q
    display_images = False

    if display_images:
        m_orig = cm.load(fnames)
        ds_ratio = 0.2
        moviehandle = m_orig.resize(1, 1, ds_ratio)
        moviehandle.play(q_max=99.5, fr=40, magnification=4)

# %% start a cluster for parallel processing
    c, dview, n_processes = cm.cluster.setup_cluster(backend='local',
                                                     n_processes=None,
                                                     single_thread=False)

    # %%% MOTION CORRECTION
    # first we create a motion correction object with the specified parameters
    mc = MotionCorrect(fnames, dview=dview, **opts.get_group('motion'))
    # Run correction
    do_motion_correction = True
    if do_motion_correction:
        mc.motion_correct(save_movie=True)
    else:
        mc_list = [
            file for file in os.listdir(file_dir)
            if (os.path.splitext(os.path.split(fnames)[-1])[0] in file
                and '.mmap' in file)
        ]
        mc.mmap_file = [os.path.join(file_dir, mc_list[0])]
        print(f'reuse previously saved motion corrected file:{mc.mmap_file}')

# %% compare with original movie
    if display_images:
        m_orig = cm.load(fnames)
        m_rig = cm.load(mc.mmap_file)
        ds_ratio = 0.2
        moviehandle = cm.concatenate(
            [m_orig.resize(1, 1, ds_ratio),
             m_rig.resize(1, 1, ds_ratio)],
            axis=2)
        moviehandle.play(fr=40, q_max=99.5, magnification=4)  # press q to exit

# %% MEMORY MAPPING
    do_memory_mapping = True
    if do_memory_mapping:
        border_to_0 = 0 if mc.border_nan == 'copy' else mc.border_to_0
        # you can include the boundaries of the FOV if you used the 'copy' option
        # during motion correction, although be careful about the components near
        # the boundaries

        # memory map the file in order 'C'
        fname_new = cm.save_memmap_join(
            mc.mmap_file,
            base_name='memmap_' +
            os.path.splitext(os.path.split(fnames)[-1])[0],
            add_to_mov=border_to_0,
            dview=dview)  # exclude border
    else:
        mmap_list = [
            file for file in os.listdir(file_dir)
            if ('memmap_' +
                os.path.splitext(os.path.split(fnames)[-1])[0]) in file
        ]
        fname_new = os.path.join(file_dir, mmap_list[0])
        print(f'reuse previously saved memory mapping file:{fname_new}')

# %% SEGMENTATION
# create summary images
    img = mean_image(mc.mmap_file[0], window=1000, dview=dview)
    img = (img - np.mean(img)) / np.std(img)

    gaussian_blur = False  # Use gaussian blur when there is too much noise in the video
    Cn = local_correlations_movie_offline(mc.mmap_file[0],
                                          fr=fr,
                                          window=fr * 4,
                                          stride=fr * 4,
                                          winSize_baseline=fr,
                                          remove_baseline=True,
                                          gaussian_blur=gaussian_blur,
                                          dview=dview).max(axis=0)
    img_corr = (Cn - np.mean(Cn)) / np.std(Cn)
    summary_images = np.stack([img, img, img_corr], axis=0).astype(np.float32)
    # save summary images which are used in the VolPy GUI
    cm.movie(summary_images).save(fnames[:-5] + '_summary_images.tif')
    fig, axs = plt.subplots(1, 2)
    axs[0].imshow(summary_images[0])
    axs[1].imshow(summary_images[2])
    axs[0].set_title('mean image')
    axs[1].set_title('corr image')

    #%% methods for segmentation
    methods_list = [
        'manual_annotation',  # manual annotations need prepared annotated datasets in the same format as demo_voltage_imaging_ROIs.hdf5 
        'maskrcnn',  # Mask R-CNN is a convolutional neural network trained for detecting neurons in summary images
        'gui_annotation'
    ]  # use VolPy GUI to correct outputs of Mask R-CNN or annotate new datasets

    method = methods_list[0]
    if method == 'manual_annotation':
        with h5py.File(path_ROIs, 'r') as fl:
            ROIs = fl['mov'][()]

    elif method == 'maskrcnn':  # Important!! Make sure install keras before using mask rcnn.
        weights_path = download_model(
            'mask_rcnn'
        )  # also make sure you have downloaded the new weight. The weight was updated on Dec 1st 2020.
        ROIs = utils.mrcnn_inference(
            img=summary_images.transpose([1, 2, 0]),
            size_range=[5, 22],
            weights_path=weights_path,
            display_result=True
        )  # size parameter decides size range of masks to be selected
        cm.movie(ROIs).save(fnames[:-5] + 'mrcnn_ROIs.hdf5')

    elif method == 'gui_annotation':
        # run volpy_gui.py file in the caiman/source_extraction/volpy folder
        gui_ROIs = caiman_datadir() + '/example_movies/volpy/gui_roi.hdf5'
        with h5py.File(gui_ROIs, 'r') as fl:
            ROIs = fl['mov'][()]

    fig, axs = plt.subplots(1, 2)
    axs[0].imshow(summary_images[0])
    axs[1].imshow(ROIs.sum(0))
    axs[0].set_title('mean image')
    axs[1].set_title('masks')

    # %% restart cluster to clean up memory
    cm.stop_server(dview=dview)
    c, dview, n_processes = cm.cluster.setup_cluster(backend='local',
                                                     n_processes=None,
                                                     single_thread=False,
                                                     maxtasksperchild=1)

    # %% parameters for trace denoising and spike extraction
    ROIs = ROIs  # region of interests
    index = list(range(len(ROIs)))  # index of neurons
    weights = None  # reuse spatial weights

    context_size = 35  # number of pixels surrounding the ROI to censor from the background PCA
    visualize_ROI = False  # whether to visualize the region of interest inside the context region
    flip_signal = True  # Important!! Flip signal or not, True for Voltron indicator, False for others
    hp_freq_pb = 1 / 3  # parameter for high-pass filter to remove photobleaching
    clip = 100  # maximum number of spikes to form spike template
    threshold_method = 'adaptive_threshold'  # adaptive_threshold or simple
    min_spikes = 10  # minimal spikes to be found
    pnorm = 0.5  # a variable deciding the amount of spikes chosen for adaptive threshold method
    threshold = 3  # threshold for finding spikes only used in simple threshold method, Increase the threshold to find less spikes
    do_plot = False  # plot detail of spikes, template for the last iteration
    ridge_bg = 0.01  # ridge regression regularizer strength for background removement, larger value specifies stronger regularization
    sub_freq = 20  # frequency for subthreshold extraction
    weight_update = 'ridge'  # ridge or NMF for weight update
    n_iter = 2  # number of iterations alternating between estimating spike times and spatial filters

    opts_dict = {
        'fnames': fname_new,
        'ROIs': ROIs,
        'index': index,
        'weights': weights,
        'context_size': context_size,
        'visualize_ROI': visualize_ROI,
        'flip_signal': flip_signal,
        'hp_freq_pb': hp_freq_pb,
        'clip': clip,
        'threshold_method': threshold_method,
        'min_spikes': min_spikes,
        'pnorm': pnorm,
        'threshold': threshold,
        'do_plot': do_plot,
        'ridge_bg': ridge_bg,
        'sub_freq': sub_freq,
        'weight_update': weight_update,
        'n_iter': n_iter
    }

    opts.change_params(params_dict=opts_dict)

    #%% TRACE DENOISING AND SPIKE DETECTION
    vpy = VOLPY(n_processes=n_processes, dview=dview, params=opts)
    vpy.fit(n_processes=n_processes, dview=dview)

    #%% visualization
    display_images = True
    if display_images:
        print(np.where(
            vpy.estimates['locality'])[0])  # neurons that pass locality test
        idx = np.where(vpy.estimates['locality'] > 0)[0]
        utils.view_components(vpy.estimates, img_corr, idx)

#%% reconstructed movie
# note the negative spatial weights is cutoff
    if display_images:
        mv_all = utils.reconstructed_movie(vpy.estimates.copy(),
                                           fnames=mc.mmap_file,
                                           idx=idx,
                                           scope=(0, 1000),
                                           flip_signal=flip_signal)
        mv_all.play(fr=40)

#%% save the result in .npy format
    save_result = True
    if save_result:
        vpy.estimates['ROIs'] = ROIs
        vpy.estimates['params'] = opts
        save_name = f'volpy_{os.path.split(fnames)[1][:-5]}_{threshold_method}'
        np.save(os.path.join(file_dir, save_name), vpy.estimates)

# %% STOP CLUSTER and clean up log files
    cm.stop_server(dview=dview)
    log_files = glob.glob('*_LOG_*')
    for log_file in log_files:
        os.remove(log_file)
예제 #6
0
def main():
    pass  # For compatibility between running under Spyder and the CLI

    # %%  Load demo movie and ROIs
    fnames = download_demo(
        'demo_voltage_imaging.hdf5',
        'volpy')  # file path to movie file (will download if not present)
    path_ROIs = download_demo(
        'demo_voltage_imaging_ROIs.hdf5',
        'volpy')  # file path to ROIs file (will download if not present)

    #%% dataset dependent parameters
    # dataset dependent parameters
    fr = 400  # sample rate of the movie

    # motion correction parameters
    pw_rigid = False  # flag for pw-rigid motion correction
    gSig_filt = (3, 3)  # size of filter, in general gSig (see below),
    # change this one if algorithm does not work
    max_shifts = (5, 5)  # maximum allowed rigid shift
    strides = (
        48, 48
    )  # start a new patch for pw-rigid motion correction every x pixels
    overlaps = (24, 24
                )  # overlap between pathes (size of patch strides+overlaps)
    max_deviation_rigid = 3  # maximum deviation allowed for patch with respect to rigid shifts
    border_nan = 'copy'

    opts_dict = {
        'fnames': fnames,
        'fr': fr,
        'pw_rigid': pw_rigid,
        'max_shifts': max_shifts,
        'gSig_filt': gSig_filt,
        'strides': strides,
        'overlaps': overlaps,
        'max_deviation_rigid': max_deviation_rigid,
        'border_nan': border_nan
    }

    opts = volparams(params_dict=opts_dict)

    # %% play the movie (optional)
    # playing the movie using opencv. It requires loading the movie in memory.
    # To close the movie press q
    display_images = False

    if display_images:
        m_orig = cm.load(fnames)
        ds_ratio = 0.2
        moviehandle = m_orig.resize(1, 1, ds_ratio)
        moviehandle.play(q_max=99.5, fr=40, magnification=6)

# %% start a cluster for parallel processing
    c, dview, n_processes = cm.cluster.setup_cluster(backend='local',
                                                     n_processes=None,
                                                     single_thread=False)

    # %%% MOTION CORRECTION
    # first we create a motion correction object with the specified parameters
    mc = MotionCorrect(fnames, dview=dview, **opts.get_group('motion'))
    # Run correction
    mc.motion_correct(save_movie=True)

    # %% compare with original movie
    if display_images:
        m_orig = cm.load(fnames)
        m_rig = cm.load(mc.mmap_file)
        ds_ratio = 0.2
        moviehandle = cm.concatenate([
            m_orig.resize(1, 1, ds_ratio) - mc.min_mov * mc.nonneg_movie,
            m_rig.resize(1, 1, ds_ratio)
        ],
                                     axis=2)
        moviehandle.play(fr=60, q_max=99.5, magnification=4)  # press q to exit

# %% MEMORY MAPPING
    border_to_0 = 0 if mc.border_nan == 'copy' else mc.border_to_0
    # you can include the boundaries of the FOV if you used the 'copy' option
    # during motion correction, although be careful about the components near
    # the boundaries

    # memory map the file in order 'C'
    fname_new = cm.save_memmap_join(mc.mmap_file,
                                    base_name='memmap_',
                                    add_to_mov=border_to_0,
                                    dview=dview)  # exclude border

    # %% SEGMENTATION
    # create summary images
    img = mean_image(mc.mmap_file[0], window=1000, dview=dview)
    img = (img - np.mean(img)) / np.std(img)

    gaussian_blur = False  # Use gaussian blur when the quality of corr image(Cn) is bad
    Cn = local_correlations_movie_offline(mc.mmap_file[0],
                                          fr=fr,
                                          window=fr * 4,
                                          stride=fr * 4,
                                          winSize_baseline=fr,
                                          remove_baseline=True,
                                          gaussian_blur=gaussian_blur,
                                          dview=dview).max(axis=0)
    img_corr = (Cn - np.mean(Cn)) / np.std(Cn)
    summary_image = np.stack([img, img, img_corr], axis=2).astype(np.float32)

    #%% three methods for segmentation
    methods_list = [
        'manual_annotation',  # manual annotation needs user to prepare annotated datasets same format as demo ROIs 
        'quick_annotation',  # quick annotation annotates data with simple interface in python
        'maskrcnn'
    ]  # maskrcnn is a convolutional network trained for finding neurons using summary images
    method = methods_list[0]
    if method == 'manual_annotation':
        with h5py.File(path_ROIs, 'r') as fl:
            ROIs = fl['mov'][()]

    elif method == 'quick_annotation':
        ROIs = utils.quick_annotation(img, min_radius=4, max_radius=8)

    elif method == 'maskrcnn':  # Important!! make sure install keras before using mask rcnn
        weights_path = download_model('mask_rcnn')
        ROIs = utils.mrcnn_inference(img=summary_image,
                                     weights_path=weights_path,
                                     display_result=True)

# %% restart cluster to clean up memory
    cm.stop_server(dview=dview)
    c, dview, n_processes = cm.cluster.setup_cluster(backend='local',
                                                     n_processes=None,
                                                     single_thread=False,
                                                     maxtasksperchild=1)

    # %% parameters for trace denoising and spike extraction
    ROIs = ROIs  # region of interests
    index = list(range(len(ROIs)))  # index of neurons
    weights = None  # reuse spatial weights

    context_size = 35  # number of pixels surrounding the ROI to censor from the background PCA
    flip_signal = True  # Important!! Flip signal or not, True for Voltron indicator, False for others
    hp_freq_pb = 1 / 3  # parameter for high-pass filter to remove photobleaching
    threshold_method = 'simple'  # 'simple' or 'adaptive_threshold'
    min_spikes = 10  # minimal spikes to be found
    threshold = 3.5  # threshold for finding spikes, increase threshold to find less spikes
    do_plot = False  # plot detail of spikes, template for the last iteration
    ridge_bg = 0.001  # ridge regression regularizer strength for background removement
    sub_freq = 20  # frequency for subthreshold extraction
    weight_update = 'ridge'  # 'ridge' or 'NMF' for weight update

    opts_dict = {
        'fnames': fname_new,
        'ROIs': ROIs,
        'index': index,
        'weights': weights,
        'context_size': context_size,
        'flip_signal': flip_signal,
        'hp_freq_pb': hp_freq_pb,
        'threshold_method': threshold_method,
        'min_spikes': min_spikes,
        'threshold': threshold,
        'do_plot': do_plot,
        'ridge_bg': ridge_bg,
        'sub_freq': sub_freq,
        'weight_update': weight_update
    }

    opts.change_params(params_dict=opts_dict)

    #%% TRACE DENOISING AND SPIKE DETECTION
    vpy = VOLPY(n_processes=n_processes, dview=dview, params=opts)
    vpy.fit(n_processes=n_processes, dview=dview)

    #%% visualization
    if display_images:
        print(np.where(
            vpy.estimates['locality'])[0])  # neurons that pass locality test
        idx = np.where(vpy.estimates['locality'] > 0)[0]
        utils.view_components(vpy.estimates, img_corr, idx)

#%% reconstructed movie
# note the negative spatial weights is cutoff
    if display_images:
        mv_all = utils.reconstructed_movie(vpy.estimates,
                                           fnames=mc.mmap_file,
                                           idx=idx,
                                           scope=(0, 1000),
                                           flip_signal=flip_signal)
        mv_all.play(fr=40)

# %% STOP CLUSTER and clean up log files
    cm.stop_server(dview=dview)
    log_files = glob.glob('*_LOG_*')
    for log_file in log_files:
        os.remove(log_file)