def deconvolve(mat, fs, tau = 1.5): #neucoeff = 0.7 # neuropil coefficient # for computing and subtracting baseline baseline = 'maximin' # take the running max of the running min after smoothing with gaussian sig_baseline = 10.0 # in bins, standard deviation of gaussian with which to smooth win_baseline = 60.0 # in seconds, window in which to compute max/min filters ops = {'tau': tau, 'fs': fs, #'neucoeff': neucoeff, 'baseline': baseline, 'sig_baseline': sig_baseline, 'win_baseline': win_baseline} # get spikes spks = dcnv.oasis(mat, ops) return spks
def run_dcnv(opts): #% Set up paths: acquisition_dir = os.path.join(opts.rootdir, opts.animalid, opts.session, opts.acquisition) s2p_source_dir = os.path.join(acquisition_dir, opts.run, 'processed', opts.analysis, 'suite2p', 'plane0') #s2p files s2p_raw_trace_fn = os.path.join(s2p_source_dir, 'F.npy') s2p_np_trace_fn = os.path.join(s2p_source_dir, 'Fneu.npy') s2p_stat_fn = os.path.join(s2p_source_dir, 'stat.npy') s2p_ops_fn = os.path.join(s2p_source_dir, 'ops.npy') #load them in s2p_stat = np.load(s2p_stat_fn) s2p_ops = np.load(s2p_ops_fn).item() s2p_raw_trace_data = np.load(s2p_raw_trace_fn) s2p_np_trace_data = np.load(s2p_np_trace_fn) #doing spike deconv with correct tau param #from Dana et al (2018 paper): #In agreement with the cultured neuron results, jGCaMP7f has faster kinetics #than the other jGCaMP7 sensors and is comparable to GCaMP6f. #jGCaMP7s has slower decay time than all the other sensors (Fig. 5b) #therefore using same value for tau (decay constant) as suggested by Suite2p #for GCaMP6f data: 0.7 s2p_ops['tau'] = 0.7 #remove neuropil Fc0 = s2p_raw_trace_data - s2p_ops['neucoeff'] * s2p_np_trace_data #baseline operation Fc1 = dcnv.preprocess(Fc0, s2p_ops) print('Deconvoling trace') # get spikes spks = dcnv.oasis(Fc1, s2p_ops) # print(spks.shape) s2p_spks_fn = os.path.join(s2p_source_dir, 'spks.npy') print('Saving to: %s' % (s2p_spks_fn)) np.save(s2p_spks_fn, spks)
def run_s2p(ops={}, db={}): t0 = tic() ops0 = default_ops() ops = {**ops0, **ops} ops = {**ops, **db} print(db) if 'save_path0' not in ops or len(ops['save_path0']) == 0: if ('h5py' in ops) and len(ops['h5py']) > 0: ops['save_path0'], tail = os.path.split(ops['h5py']) else: ops['save_path0'] = ops['data_path'][0] # check if there are files already registered! fpathops1 = os.path.join(ops['save_path0'], 'suite2p', 'ops1.npy') if os.path.isfile(fpathops1): files_found_flag = True flag_binreg = True ops1 = np.load(fpathops1, allow_pickle=True) print('FOUND OPS IN %s' % ops1[0]['save_path']) for i, op in enumerate(ops1): # default behavior is to look in the ops flag_reg = os.path.isfile(op['reg_file']) if not flag_reg: # otherwise look in the user defined save_path0 op['save_path'] = os.path.join(ops['save_path0'], 'suite2p', 'plane%d' % i) op['ops_path'] = os.path.join(op['save_path'], 'ops.npy') op['reg_file'] = os.path.join(op['save_path'], 'data.bin') flag_reg = os.path.isfile(op['reg_file']) files_found_flag &= flag_reg if 'refImg' not in op or op['do_registration'] > 1: flag_binreg = False if i == len(ops1) - 1: print( "NOTE: not registered / registration forced with ops['do_registration']>1" ) # use the new False ops1[i] = {**op, **ops}.copy() # for mesoscope tiffs, preserve original lines, etc if 'lines' in op: ops1[i]['nrois'] = op['nrois'] ops1[i]['nplanes'] = op['nplanes'] ops1[i]['lines'] = op['lines'] ops1[i]['dy'] = op['dy'] ops1[i]['dx'] = op['dx'] ops1[i]['iplane'] = op['iplane'] #ops1[i] = ops1[i].copy() # except for registration results ops1[i]['xrange'] = op['xrange'] ops1[i]['yrange'] = op['yrange'] else: files_found_flag = False flag_binreg = False # if not set up files and copy tiffs/h5py to binary if not files_found_flag: # get default options ops0 = default_ops() # combine with user options ops = {**ops0, **ops} # copy tiff to a binary if len(ops['h5py']): ops1 = utils.h5py_to_binary(ops) print('time %4.2f sec. Wrote h5py to binaries for %d planes' % (toc(t0), len(ops1))) else: if 'mesoscan' in ops and ops['mesoscan']: ops1 = utils.mesoscan_to_binary(ops) print('time %4.2f sec. Wrote tifs to binaries for %d planes' % (toc(t0), len(ops1))) elif HAS_HAUS: print('time %4.2f sec. Using HAUSIO') dataset = haussio.load_haussio(ops['data_path'][0]) ops1 = dataset.tosuite2p(ops) print('time %4.2f sec. Wrote data to binaries for %d planes' % (toc(t0), len(ops1))) else: ops1 = utils.tiff_to_binary(ops) print('time %4.2f sec. Wrote tifs to binaries for %d planes' % (toc(t0), len(ops1))) np.save(fpathops1, ops1) # save ops1 else: print('FOUND BINARIES: %s' % ops1[0]['reg_file']) ops1 = np.array(ops1) #ops1 = utils.split_multiops(ops1) if not ops['do_registration']: flag_binreg = True if flag_binreg: print('SKIPPING REGISTRATION...') if flag_binreg and not files_found_flag: print('NOTE: binary file created, but registration not performed') # set up number of CPU workers for registration and cell detection ipl = 0 while ipl < len(ops1): print('>>>>>>>>>>>>>>>>>>>>> PLANE %d <<<<<<<<<<<<<<<<<<<<<<' % ipl) t1 = tic() if not flag_binreg: ######### REGISTRATION ######### t11 = tic() print('----------- REGISTRATION') ops1[ipl] = register.register_binary(ops1[ipl]) # register binary np.save(fpathops1, ops1) # save ops1 print('Total %0.2f sec' % (toc(t11))) if 'roidetect' in ops1[ipl]: roidetect = ops['roidetect'] else: roidetect = True if roidetect: ######## CELL DETECTION AND ROI EXTRACTION ############## t11 = tic() print('----------- ROI DETECTION AND EXTRACTION') ops1[ipl] = roiextract.roi_detect_and_extract(ops1[ipl]) ops = ops1[ipl] fpath = ops['save_path'] print('Total %0.2f sec.' % (toc(t11))) ######### SPIKE DECONVOLUTION ############### t11 = tic() print('----------- SPIKE DECONVOLUTION') F = np.load(os.path.join(fpath, 'F.npy')) Fneu = np.load(os.path.join(fpath, 'Fneu.npy')) dF = F - ops['neucoeff'] * Fneu spks = dcnv.oasis(dF, ops) np.save(os.path.join(ops['save_path'], 'spks.npy'), spks) print('Total %0.2f sec.' % (toc(t11))) # save as matlab file if ('save_mat' in ops) and ops['save_mat']: stat = np.load(os.path.join(fpath, 'stat.npy'), allow_pickle=True) iscell = np.load(os.path.join(fpath, 'iscell.npy')) matpath = os.path.join(ops['save_path'], 'Fall.mat') io.savemat( matpath, { 'stat': stat, 'ops': ops, 'F': F, 'Fneu': Fneu, 'spks': spks, 'iscell': iscell }) else: print("WARNING: skipping cell detection (ops['roidetect']=False)") print( 'Plane %d out of %d planes processed in %0.2f sec (can open in GUI).' % (ipl, len(ops1), toc(t1))) print('total = %0.2f sec.' % (toc(t0))) ipl += 1 #len(ipl) # save final ops1 with all planes np.save(fpathops1, ops1) #### COMBINE PLANES or FIELDS OF VIEW #### if len(ops1) > 1 and ops1[0]['combined'] and roidetect: utils.combined(ops1) # running a clean up script if 'clean_script' in ops1[0]: print('running clean-up script') os.system('python ' + ops['clean_script'] + ' ' + fpathops1) for ops in ops1: if ('delete_bin' in ops) and ops['delete_bin']: os.remove(ops['reg_file']) if ops['nchannels'] > 1: os.remove(ops['reg_file_chan2']) print('TOTAL RUNTIME %0.2f sec' % toc(t0)) return ops1
def masks_and_traces(ops, stat, stat_orig): ''' main extraction function inputs: ops and stat creates cell and neuropil masks and extracts traces returns: F (ROIs x time), Fneu (ROIs x time), F_chan2, Fneu_chan2, ops, stat F_chan2 and Fneu_chan2 will be empty if no second channel ''' t0 = time.time() # Concatenate stat so a good neuropil function can be formed stat_all = stat.copy() for n in range(len(stat_orig)): stat_all.append(stat_orig[n]) stat_all, cell_pix, _ = roiextract.create_cell_masks(ops, stat_all) stat = stat_all[:len(stat)] neuropil_masks = roiextract.create_neuropil_masks(ops, stat, cell_pix) Ly = ops['Ly'] Lx = ops['Lx'] neuropil_masks = np.reshape(neuropil_masks, (-1, Ly * Lx)) stat0 = [] for n in range(len(stat)): stat0.append({ 'ipix': stat[n]['ipix'], 'lam': stat[n]['lam'] / stat[n]['lam'].sum() }) print('Masks made in %0.2f sec.' % (time.time() - t0)) F, Fneu, ops = roiextract.extractF(ops, stat0, neuropil_masks, ops['reg_file']) if 'reg_file_chan2' in ops: F_chan2, Fneu_chan2, ops2 = roiextract.extractF( ops.copy(), stat0, neuropil_masks, ops['reg_file_chan2']) ops['meanImg_chan2'] = ops2['meanImg_chan2'] else: F_chan2, Fneu_chan2 = [], [] # compute activity statistics for classifier npix = np.array([stat_orig[n]['npix'] for n in range(len(stat_orig))]).astype('float32') for n in range(len(stat)): stat[n]['npix_norm'] = stat[n]['npix'] / np.mean( npix[:100]) # What if there are less than 100 cells? stat[n]['compact'] = 1 stat[n]['footprint'] = 2 stat[n]['Manual'] = 1 # Add manual key # subtract neuropil and compute skew, std from F dF = F - ops['neucoeff'] * Fneu sk = stats.skew(dF, axis=1) sd = np.std(dF, axis=1) for n in range(F.shape[0]): stat[n]['skew'] = sk[n] stat[n]['std'] = sd[n] stat[n]['med'] = [np.mean(stat[n]['ypix']), np.mean(stat[n]['xpix'])] dF = F - ops['neucoeff'] * Fneu spks = dcnv.oasis(dF, ops) # print('Ftrace size', np.shape(Fneu), np.shape(F)) return F, Fneu, F_chan2, Fneu_chan2, spks, ops, stat
def run_s2p(ops={}, db={}): i0 = tic() ops0 = default_ops() ops = {**ops0, **ops} ops = {**ops, **db} if 'save_path0' not in ops or len(ops['save_path0']) == 0: if ('h5py' in ops) and len(ops['h5py']) > 0: ops['save_path0'], tail = os.path.split(ops['h5py']) else: ops['save_path0'] = ops['data_path'][0] # check if there are files already registered fpathops1 = os.path.join(ops['save_path0'], 'suite2p', 'ops1.npy') if os.path.isfile(fpathops1): files_found_flag = True flag_binreg = True ops1 = np.load(fpathops1) for i, op in enumerate(ops1): # default behavior is to look in the ops flag_reg = os.path.isfile(op['reg_file']) if not flag_reg: # otherwise look in the user defined save_path0 op['save_path'] = os.path.join(ops['save_path0'], 'suite2p', 'plane%d' % i) op['ops_path'] = os.path.join(op['save_path'], 'ops.npy') op['reg_file'] = os.path.join(op['save_path'], 'data.bin') flag_reg = os.path.isfile(op['reg_file']) files_found_flag &= flag_reg if 'refImg' not in op: flag_binreg = False # use the new options ops1[i] = {**op, **ops}.copy() #ops1[i] = ops1[i].copy() print(ops1[i]['save_path']) # except for registration results ops1[i]['xrange'] = op['xrange'] ops1[i]['yrange'] = op['yrange'] else: files_found_flag = False flag_binreg = False ######### REGISTRATION ######### if not files_found_flag: # get default options ops0 = default_ops() # combine with user options ops = {**ops0, **ops} # copy tiff to a binary if len(ops['h5py']): ops1 = utils.h5py_to_binary(ops) print('time %4.4f. Wrote h5py to binaries for %d planes' % (toc(i0), len(ops1))) else: if 'mesoscan' in ops and ops['mesoscan']: ops1 = utils.mesoscan_to_binary(ops) print('time %4.4f. Wrote tifs to binaries for %d planes' % (toc(i0), len(ops1))) elif HAS_HAUS: print('time %4.4f. Using HAUSIO') dataset = haussio.load_haussio(ops['data_path'][0]) ops1 = dataset.tosuite2p(ops) print('time %4.4f. Wrote data to binaries for %d planes' % (toc(i0), len(ops1))) else: ops1 = utils.tiff_to_binary(ops) print('time %4.4f. Wrote tifs to binaries for %d planes' % (toc(i0), len(ops1))) np.save(fpathops1, ops1) # save ops1 ops1 = np.array(ops1) ops1 = utils.split_multiops(ops1) if not ops['do_registration']: flag_binreg = True if files_found_flag: print('found ops1 and binaries') print(ops1[0]['reg_file']) if flag_binreg: print('foundpre-registered binaries') print('skipping registration...') if flag_binreg and not files_found_flag: print('binary file created, but registration not performed') if len(ops1) > 1 and ops['num_workers_roi'] >= 0: if ops['num_workers_roi'] == 0: ops['num_workers_roi'] = len(ops1) ni = ops['num_workers_roi'] else: ni = 1 ik = 0 while ik < len(ops1): ipl = ik + np.arange(0, min(ni, len(ops1) - ik)) if not flag_binreg: ops1[ipl] = register.register_binary(ops1[ipl]) # register binary np.save(fpathops1, ops1) # save ops1 print('time %4.4f. Registration complete for %d planes' % (toc(i0), ni)) if ni > 1: with Pool(len(ipl)) as p: ops1[ipl] = p.map(utils.get_cells, ops1[ipl]) else: ops1[ipl[0]] = utils.get_cells(ops1[ipl[0]]) for ops in ops1[ipl]: fpath = ops['save_path'] F = np.load(os.path.join(fpath, 'F.npy')) Fneu = np.load(os.path.join(fpath, 'Fneu.npy')) dF = F - ops['neucoeff'] * Fneu spks = dcnv.oasis(dF, ops) np.save(os.path.join(ops['save_path'], 'spks.npy'), spks) print('time %4.4f. Detected spikes in %d ROIs' % (toc(i0), F.shape[0])) stat = np.load(os.path.join(fpath, 'stat.npy')) # apply default classifier classfile = os.path.join( os.path.abspath(os.path.dirname(__file__)), 'classifiers/classifier_user.npy') print(classfile) iscell = classifier.run(classfile, stat) np.save(os.path.join(ops['save_path'], 'iscell.npy'), iscell) # save as matlab file if ('save_mat' in ops) and ops['save_mat']: matpath = os.path.join(ops['save_path'], 'Fall.mat') io.savemat( matpath, { 'stat': stat, 'ops': ops, 'F': F, 'Fneu': Fneu, 'spks': spks, 'iscell': iscell }) ik += len(ipl) # save final ops1 with all planes np.save(fpathops1, ops1) #### COMBINE PLANES or FIELDS OF VIEW #### if len(ops1) > 1 and ops1[0]['combined']: utils.combined(ops1) # running a clean up script if 'clean_script' in ops1[0]: print('running clean-up script') os.system('python ' + ops['clean_script'] + ' ' + fpathops1) for ops in ops1: if ('delete_bin' in ops) and ops['delete_bin']: os.remove(ops['reg_file']) if ops['nchannels'] > 1: os.remove(ops['reg_file_chan2']) print('finished all tasks in total time %4.4f sec' % toc(i0)) return ops1
def run_s2p(ops={}, db={}): i0 = tic() ops = {**ops, **db} if 'save_path0' not in ops or len(ops['save_path0']) == 0: ops['save_path0'] = ops['data_path'][0] # check if there are files already registered fpathops1 = os.path.join(ops['save_path0'], 'suite2p', 'ops1.npy') if os.path.isfile(fpathops1): files_found_flag = True flag_binreg = True ops1 = np.load(fpathops1) for i, op in enumerate(ops1): # default behavior is to look in the ops flag_reg = os.path.isfile(op['reg_file']) if not flag_reg: # otherwise look in the user defined save_path0 op['save_path'] = os.path.join(ops['save_path0'], 'suite2p', 'plane%d' % i) op['ops_path'] = os.path.join(op['save_path'], 'ops.npy') op['reg_file'] = os.path.join(op['save_path'], 'data.bin') flag_reg = os.path.isfile(op['reg_file']) files_found_flag &= flag_reg if 'refImg' not in op: flag_binreg = False # use the new options ops1[i] = {**op, **ops} ops1[i] = ops1[i].copy() print(ops1[i]['save_path']) # except for registration results ops1[i]['xrange'] = op['xrange'] ops1[i]['yrange'] = op['yrange'] else: files_found_flag = False flag_binreg = False ######### REGISTRATION ######### if not files_found_flag: # get default options ops0 = default_ops() # combine with user options ops = {**ops0, **ops} # copy tiff to a binary if len(ops['h5py']): ops1 = utils.h5py_to_binary(ops) print('time %4.4f. Wrote h5py to binaries for %d planes' % (toc(i0), len(ops1))) else: ops1 = utils.tiff_to_binary(ops) print('time %4.4f. Wrote tifs to binaries for %d planes' % (toc(i0), len(ops1))) # save ops1 np.save(fpathops1, ops1) if not flag_binreg: ops1 = register.register_binary(ops1) # register tiff np.save(fpathops1, ops1) # save ops1 print('time %4.4f. Registration complete' % toc(i0)) else: print('found ops1 and pre-registered binaries') print(ops1[0]['reg_file']) print('overwriting ops1 with new ops') print('skipping registration...') ######### CELL DETECTION ######### if len(ops1) > 1 and ops['num_workers_roi'] >= 0: if ops['num_workers_roi'] == 0: ops['num_workers_roi'] = len(ops1) with Pool(ops['num_workers_roi']) as p: ops1 = p.map(utils.get_cells, ops1) else: for k in range(len(ops1)): ops1[k] = utils.get_cells(ops1[k]) ######### SPIKE DECONVOLUTION AND CLASSIFIER ######### for ops in ops1: fpath = ops['save_path'] F = np.load(os.path.join(fpath, 'F.npy')) Fneu = np.load(os.path.join(fpath, 'Fneu.npy')) dF = F - ops['neucoeff'] * Fneu spks = dcnv.oasis(dF, ops) np.save(os.path.join(ops['save_path'], 'spks.npy'), spks) print('time %4.4f. Detected spikes in %d ROIs' % (toc(i0), F.shape[0])) stat = np.load(os.path.join(fpath, 'stat.npy')) # apply default classifier classfile = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'classifiers/classifier_user.npy') print(classfile) iscell = classifier.run(classfile, stat) np.save(os.path.join(ops['save_path'], 'iscell.npy'), iscell) # save as matlab file if ('save_mat' in ops) and ops['save_mat']: matpath = os.path.join(ops['save_path'], 'Fall.mat') scipy.io.savemat( matpath, { 'stat': stat, 'ops': ops, 'F': F, 'Fneu': Fneu, 'spks': spks, 'iscell': iscell }) # save final ops1 with all planes np.save(fpathops1, ops1) #### COMBINE PLANES or FIELDS OF VIEW #### if len(ops1) > 1 and ops1[0]['combined']: utils.combined(ops1) for ops in ops1: if ('delete_bin' in ops) and ops['delete_bin']: os.remove(ops['reg_file']) if ops['nchannels'] > 1: os.remove(ops['reg_file_chan2']) print('finished all tasks in total time %4.4f sec' % toc(i0)) return ops1
def activity_stats(parent): i0 = int(1 - parent.iscell[parent.ichosen]) ypix = np.array([]) xpix = np.array([]) lam = np.array([]) footprints = np.array([]) F = np.zeros((0, parent.Fcell.shape[1]), np.float32) Fneu = np.zeros((0, parent.Fcell.shape[1]), np.float32) for n in np.array(parent.imerge): ypix = np.append(ypix, parent.stat[n]["ypix"]) xpix = np.append(xpix, parent.stat[n]["xpix"]) lam = np.append(lam, parent.stat[n]["lam"]) footprints = np.append(footprints, parent.stat[n]["footprint"]) F = np.append(F, parent.Fcell[n, :][np.newaxis, :], axis=0) Fneu = np.append(Fneu, parent.Fneu[n, :][np.newaxis, :], axis=0) # remove overlaps ipix = np.concatenate((ypix[:, np.newaxis], xpix[:, np.newaxis]), axis=1) _, goodi = np.unique(ipix, return_index=True, axis=0) ypix = ypix[goodi] xpix = xpix[goodi] lam = lam[goodi] stat0 = {} stat0["ypix"] = ypix.astype(np.int32) stat0["xpix"] = xpix.astype(np.int32) stat0["lam"] = lam stat0['med'] = [np.median(stat0["ypix"]), np.median(stat0["xpix"])] stat0["npix"] = ypix.size d0 = parent.ops["diameter"] radius = utils.fitMVGaus(ypix / d0[0], xpix / d0[1], lam, 2)[2] stat0["radius"] = radius[0] * d0.mean() stat0["aspect_ratio"] = 2 * radius[0] / (.01 + radius[0] + radius[1]) npix = np.array([parent.stat[n]['npix'] for n in range(len(parent.stat))]).astype('float32') stat0["npix_norm"] = stat0["npix"] / npix.mean() # compactness rs, dy, dx = sparsedetect.circleMask(d0) rsort = np.sort(rs.flatten()) r2 = ((ypix - stat0["med"][0]) / d0[0])**2 + ( (xpix - stat0["med"][1]) / d0[1])**2 r2 = r2**.5 stat0["mrs"] = np.mean(r2) stat0["mrs0"] = np.mean(rsort[:r2.size]) stat0["compact"] = stat0["mrs"] / (1e-10 + stat0["mrs0"]) # footprint stat0["footprint"] = footprints.mean() F = F.mean(axis=0) Fneu = Fneu.mean(axis=0) dF = F - parent.ops["neucoeff"] * Fneu # activity stats stat0["skew"] = stats.skew(dF) stat0["std"] = dF.std() # compute outline and circle around cell iext = fig.boundary(ypix, xpix) stat0["yext"] = ypix[iext] stat0["xext"] = xpix[iext] ycirc, xcirc = fig.circle(stat0["med"], stat0["radius"]) goodi = ((ycirc >= 0) & (xcirc >= 0) & (ycirc < parent.ops["Ly"]) & (xcirc < parent.ops["Lx"])) stat0["ycirc"] = ycirc[goodi] stat0["xcirc"] = xcirc[goodi] # deconvolve activity spks = dcnv.oasis(dF[np.newaxis, :], parent.ops) # add cell to structs parent.stat = np.concatenate((parent.stat, np.array([stat0])), axis=0) print(parent.stat[-1]["ypix"].shape) parent.Fcell = np.concatenate((parent.Fcell, F[np.newaxis, :]), axis=0) parent.Fneu = np.concatenate((parent.Fneu, Fneu[np.newaxis, :]), axis=0) parent.Spks = np.concatenate((parent.Spks, spks), axis=0) iscell = np.array([parent.iscell[parent.ichosen]], dtype=bool) parent.iscell = np.concatenate((parent.iscell, iscell), axis=0)
def merge_activity_masks(parent): print('merging activity... this may take some time') i0 = int(1-parent.iscell[parent.ichosen]) ypix = np.array([]) xpix = np.array([]) lam = np.array([]) footprints = np.array([]) F = np.zeros((0,parent.Fcell.shape[1]), np.float32) Fneu = np.zeros((0,parent.Fcell.shape[1]), np.float32) probcell = [] probredcell = [] merged_cells = [] remove_merged = [] for n in np.array(parent.imerge): if len(parent.stat[n]['imerge']) > 0: remove_merged.append(n) for k in parent.stat[n]['imerge']: merged_cells.append(k) else: merged_cells.append(n) merged_cells = np.unique(np.array(merged_cells)) for n in merged_cells: ypix = np.append(ypix, parent.stat[n]["ypix"]) xpix = np.append(xpix, parent.stat[n]["xpix"]) lam = np.append(lam, parent.stat[n]["lam"]) footprints = np.append(footprints, parent.stat[n]["footprint"]) F = np.append(F, parent.Fcell[n,:][np.newaxis,:], axis=0) Fneu = np.append(Fneu, parent.Fneu[n,:][np.newaxis,:], axis=0) probcell.append(parent.probcell[n]) probredcell.append(parent.probredcell[n]) probcell = np.array(probcell) probredcell = np.array(probredcell) pmean = probcell.mean() prmean = probredcell.mean() # remove overlaps ipix = np.concatenate((ypix[:,np.newaxis], xpix[:,np.newaxis]), axis=1) _, goodi = np.unique(ipix, return_index=True, axis=0) ypix = ypix[goodi] xpix = xpix[goodi] lam = lam[goodi] stat0 = {} if 'aspect' in parent.ops: d0 = np.array([int(parent.ops['aspect']*10), 10]) else: d0 = parent.ops['diameter'] if isinstance(d0, int): d0 = [d0,d0] ### compute statistics of merges stat0["imerge"] = merged_cells stat0["ypix"] = ypix.astype(np.int32) stat0["xpix"] = xpix.astype(np.int32) stat0["lam"] = lam / lam.sum() * merged_cells.size stat0['med'] = [np.median(stat0["ypix"]), np.median(stat0["xpix"])] stat0["npix"] = ypix.size radius = utils.fitMVGaus(ypix/d0[0], xpix/d0[1], lam, 2)[2] stat0["radius"] = radius[0] * d0.mean() stat0["aspect_ratio"] = 2 * radius[0]/(.01 + radius[0] + radius[1]) npix = np.array([parent.stat[n]['npix'] for n in range(len(parent.stat))]).astype('float32') stat0["npix_norm"] = stat0["npix"] / npix.mean() # compactness rs,dy,dx = sparsedetect.circleMask(d0) rsort = np.sort(rs.flatten()) r2 = ((ypix - stat0["med"][0])/d0[0])**2 + ((xpix - stat0["med"][1])/d0[1])**2 r2 = r2**.5 stat0["mrs"] = np.mean(r2) stat0["mrs0"] = np.mean(rsort[:r2.size]) stat0["compact"] = stat0["mrs"] / (1e-10 + stat0["mrs0"]) # footprint stat0["footprint"] = footprints.mean() # inmerge stat0["inmerge"] = 0 ### compute activity of merged cells F = F.mean(axis=0) Fneu = Fneu.mean(axis=0) dF = F - parent.ops["neucoeff"]*Fneu # activity stats stat0["skew"] = stats.skew(dF) stat0["std"] = dF.std() ### for GUI drawing # compute outline and circle around cell iext = fig.boundary(ypix, xpix) stat0["yext"] = ypix[iext].astype(np.int32) stat0["xext"] = xpix[iext].astype(np.int32) ycirc, xcirc = fig.circle(stat0["med"], stat0["radius"]) goodi = ( (ycirc >= 0) & (xcirc >= 0) & (ycirc < parent.ops["Ly"]) & (xcirc < parent.ops["Lx"]) ) stat0["ycirc"] = ycirc[goodi] stat0["xcirc"] = xcirc[goodi] # deconvolve activity spks = dcnv.oasis(dF[np.newaxis, :], parent.ops) ### remove previously merged cell (do not replace) for k in remove_merged: remove_mask(parent, k) np.delete(parent.stat, k, 0) np.delete(parent.Fcell, k, 0) np.delete(parent.Fneu, k, 0) np.delete(parent.Spks, k, 0) np.delete(parent.iscell, k, 0) np.delete(parent.probcell, k, 0) np.delete(parent.probredcell, k, 0) np.delete(parent.redcell, k, 0) np.delete(parent.notmerged, k, 0) # add cell to structs parent.stat = np.concatenate((parent.stat, np.array([stat0])), axis=0) parent.stat = sparsedetect.get_overlaps(parent.stat, parent.ops) parent.stat = np.array(parent.stat) parent.Fcell = np.concatenate((parent.Fcell, F[np.newaxis,:]), axis=0) parent.Fneu = np.concatenate((parent.Fneu, Fneu[np.newaxis,:]), axis=0) parent.Spks = np.concatenate((parent.Spks, spks), axis=0) iscell = np.array([parent.iscell[parent.ichosen]], dtype=bool) parent.iscell = np.concatenate((parent.iscell, iscell), axis=0) parent.probcell = np.append(parent.probcell, pmean) parent.probredcell = np.append(parent.probredcell, prmean) parent.redcell = np.append(parent.redcell, prmean > parent.chan2prob) parent.notmerged = np.append(parent.notmerged, False) # recompute binned F parent.mode_change(parent.activityMode) for n in merged_cells: parent.stat[n]['inmerge'] = parent.stat.size-1 add_mask(parent, parent.iscell.size-1)