def correlation_pnr(Y, gSig=None, center_psf: bool = True, swap_dim: bool = True, background_filter: str = 'disk') -> Tuple[np.ndarray, np.ndarray]: """ compute the correlation image and the peak-to-noise ratio (PNR) image. If gSig is provided, then spatially filtered the video. Args: Y: np.ndarray (3D or 4D). Input movie data in 3D or 4D format gSig: scalar or vector. gaussian width. If gSig == None, no spatial filtering center_psf: Boolean True indicates subtracting the mean of the filtering kernel swap_dim: Boolean True indicates that time is listed in the last axis of Y (matlab format) and moves it in the front background_filter: str (undocumented) Returns: cn: np.ndarray (2D or 3D). local correlation image of the spatially filtered (or not) data pnr: np.ndarray (2D or 3D). peak-to-noise ratios of all pixels/voxels """ if swap_dim: Y = np.transpose(Y, tuple(np.hstack((Y.ndim - 1, list(range(Y.ndim))[:-1])))) # parameters _, d1, d2 = Y.shape data_raw = Y.reshape(-1, d1, d2).astype('float32') # filter data data_filtered = data_raw.copy() if gSig: if not isinstance(gSig, list): gSig = [gSig, gSig] ksize = tuple([int(2 * i) * 2 + 1 for i in gSig]) if center_psf: if background_filter == 'box': for idx, img in enumerate(data_filtered): data_filtered[idx, ] = cv2.GaussianBlur( img, ksize=ksize, sigmaX=gSig[0], sigmaY=gSig[1], borderType=1) \ - cv2.boxFilter(img, ddepth=-1, ksize=ksize, borderType=1) else: psf = cv2.getGaussianKernel(ksize[0], gSig[0], cv2.CV_32F).dot(cv2.getGaussianKernel(ksize[1], gSig[1], cv2.CV_32F).T) ind_nonzero = psf >= psf[0].max() psf -= psf[ind_nonzero].mean() psf[~ind_nonzero] = 0 for idx, img in enumerate(data_filtered): data_filtered[idx,] = cv2.filter2D(img, -1, psf, borderType=1) # data_filtered[idx, ] = cv2.filter2D(img, -1, psf, borderType=1) else: for idx, img in enumerate(data_filtered): data_filtered[idx,] = cv2.GaussianBlur(img, ksize=ksize, sigmaX=gSig[0], sigmaY=gSig[1], borderType=1) # compute peak-to-noise ratio data_filtered -= data_filtered.mean(axis=0) data_max = np.max(data_filtered, axis=0) data_std = get_noise_fft(data_filtered.T, noise_method='mean')[0].T pnr = np.divide(data_max, data_std) pnr[pnr < 0] = 0 # remove small values tmp_data = data_filtered.copy() / data_std tmp_data[tmp_data < 3] = 0 # compute correlation image cn = local_correlations_fft(tmp_data, swap_dim=False) return cn, pnr
def init_neurons_corr_pnr(data, max_number=None, gSiz=15, gSig=None, center_psf=True, min_corr=0.8, min_pnr=10, seed_method='auto', deconvolve_options=None, min_pixel=3, bd=1, thresh_init=2, swap_dim=True, save_video=False, video_name='initialization.mp4'): """ using greedy method to initialize neurons by selecting pixels with large local correlation and large peak-to-noise ratio Args: data: np.ndarray (3D) the data used for initializing neurons. its dimension can be d1*d2*T or T*d1*d2. If it's the latter, swap_dim should be False; otherwise, True. max_number: integer maximum number of neurons to be detected. If None, then the algorithm will stop when all pixels are below the thresholds. gSiz: float average diameter of a neuron gSig: float number or a vector with two elements. gaussian width of the gaussian kernel used for spatial filtering. center_psf: Boolean True indicates centering the filtering kernel for background removal. This is useful for data with large background fluctuations. min_corr: float minimum local correlation coefficients for selecting a seed pixel. min_pnr: float minimum peak-to-noise ratio for selecting a seed pixel. seed_method: str {'auto', 'manual'} methods for choosing seed pixels. deconvolve_options: dict all options for deconvolving temporal traces. min_pixel: integer minimum number of nonzero pixels for one neuron. bd: integer pixels that are bd pixels away from the boundary will be ignored for initializing neurons. thresh_init: float pixel values smaller than thresh_init*noise will be set as 0 when computing the local correlation image. swap_dim: Boolean True indicates that time is listed in the last axis of Y (matlab format) save_video: Boolean save the initialization procedure if it's True video_name: str name of the video to be saved. Returns: A: np.ndarray (d1*d2*T) spatial components of all neurons C: np.ndarray (K*T) nonnegative and denoised temporal components of all neurons C_raw: np.ndarray (K*T) raw calcium traces of all neurons S: np.ndarray (K*T) deconvolved calcium traces of all neurons center: np.ndarray center localtions of all neurons """ if deconvolve_options is None: deconvolve_options = {'bl': None, 'c1': None, 'g': None, 'sn': None, 'p': 1, 'approach': 'constrained foopsi', 'method': 'oasis', 'bas_nonneg': True, 'noise_range': [.25, .5], 'noise_method': 'logmexp', 'lags': 5, 'fudge_factor': 1.0, 'verbosity': None, 'solvers': None, 'optimize_g': 1, 'penalty': 1} # parameters if swap_dim: d1, d2, total_frames = data.shape data_raw = np.transpose(data.copy(), [2, 0, 1]).astype('float32') else: total_frames, d1, d2 = data.shape data_raw = data.copy().astype('float32') if gSig: # spatially filter data data_filtered = data_raw.copy() if not isinstance(gSig, list): gSig = [gSig, gSig] ksize = tuple([(3 * i) // 2 * 2 + 1 for i in gSig]) # create a spatial filter for removing background if center_psf: for idx, img in enumerate(data_filtered): data_filtered[idx, ] = cv2.GaussianBlur(img, ksize=ksize, sigmaX=gSig[0], sigmaY=gSig[1], borderType=1) \ - cv2.boxFilter(img, ddepth=-1, ksize=ksize, borderType=1) # data_filtered[idx, ] = cv2.filter2D(img, -1, psf, borderType=1) else: for idx, img in enumerate(data_filtered): data_filtered[idx, ] = cv2.GaussianBlur(img, ksize=ksize, sigmaX=gSig[ 0], sigmaY=gSig[1], borderType=1) else: data_filtered = data_raw # compute peak-to-noise ratio data_filtered -= data_filtered.mean(axis=0) data_max = np.max(data_filtered, axis=0) noise_pixel = get_noise_fft(data_filtered.transpose())[0].transpose() pnr = np.divide(data_max, noise_pixel) # remove small values and only keep pixels with large fluorescence signals tmp_data = np.copy(data_filtered) tmp_data[tmp_data < thresh_init * noise_pixel] = 0 # compute correlation image cn = caiman.summary_images.local_correlations_fft(tmp_data, swap_dim=False) del(tmp_data) # cn[np.isnan(cn)] = 0 # remove abnormal pixels # screen seed pixels as neuron centers v_search = cn * pnr v_search[(cn < min_corr) | (pnr < min_pnr)] = 0 ind_search = (v_search <= 0) # indicate whether the pixel has # been searched before. pixels with low correlations or low PNRs are # ignored directly. ind_search[i]=0 means the i-th pixel is still under # consideration of being a seed pixel # pixels near the boundaries are ignored because of artifacts ind_bd = np.zeros(shape=(d1, d2)).astype(np.bool) # indicate boundary pixels if bd > 0: ind_bd[:bd, :] = True ind_bd[-bd:, :] = True ind_bd[:, :bd] = True ind_bd[:, -bd:] = True ind_search[ind_bd] = 1 # creating variables for storing the results if not max_number: # maximum number of neurons max_number = np.int32((ind_search.size - ind_search.sum()) / 5) Ain = np.zeros(shape=(max_number, d1, d2),dtype = np.float32) # neuron shapes Cin = np.zeros(shape=(max_number, total_frames),dtype = np.float32) # de-noised traces Sin = np.zeros(shape=(max_number, total_frames),dtype = np.float32) # spiking # activity Cin_raw = np.zeros(shape=(max_number, total_frames),dtype = np.float32) # raw traces center = np.zeros(shape=(2, max_number)) # neuron centers num_neurons = 0 # number of initialized neurons continue_searching = True min_v_search = min_corr * min_pnr if save_video: FFMpegWriter = animation.writers['ffmpeg'] metadata = dict(title='Initialization procedure', artist='CaImAn', comment='CaImAn is cool!') writer = FFMpegWriter(fps=2, metadata=metadata) # visualize the initialization procedure. fig = plt.figure(figsize=(12, 8), facecolor=(0.9, 0.9, 0.9)) # with writer.saving(fig, "initialization.mp4", 150): writer.setup(fig, video_name, 150) ax_cn = plt.subplot2grid((2, 3), (0, 0)) ax_cn.imshow(cn) ax_cn.set_title('Correlation') ax_cn.set_axis_off() ax_pnr_cn = plt.subplot2grid((2, 3), (0, 1)) ax_pnr_cn.imshow(cn * pnr) ax_pnr_cn.set_title('Correlation*PNR') ax_pnr_cn.set_axis_off() ax_cn_box = plt.subplot2grid((2, 3), (0, 2)) ax_cn_box.imshow(cn) ax_cn_box.set_xlim([54, 63]) ax_cn_box.set_ylim([54, 63]) ax_cn_box.set_title('Correlation') ax_cn_box.set_axis_off() ax_traces = plt.subplot2grid((2, 3), (1, 0), colspan=3) ax_traces.set_title('Activity at the seed pixel') writer.grab_frame() while continue_searching: if seed_method.lower() == 'manual': pass # manually pick seed pixels else: # local maximum, for identifying seed pixels in following steps v_search[(cn < min_corr) | (pnr < min_pnr)] = 0 v_search[ind_search] = 0 tmp_kernel = np.ones(shape=tuple([gSiz // 3] * 2)) v_max = cv2.dilate(v_search, tmp_kernel) # automatically select seed pixels as the local maximums v_max[(v_search != v_max) | (v_search < min_v_search)] = 0 v_max[ind_search] = 0 [rsub_max, csub_max] = v_max.nonzero() # subscript of seed pixels local_max = v_max[rsub_max, csub_max] n_seeds = len(local_max) # number of candidates if n_seeds == 0: # no more candidates for seed pixels break else: # order seed pixels according to their corr * pnr values ind_local_max = local_max.argsort()[::-1] img_vmax = np.median(local_max) # try to initialization neurons given all seed pixels for ith_seed, idx in enumerate(ind_local_max): r = rsub_max[idx] c = csub_max[idx] ind_search[r, c] = True # this pixel won't be searched if v_search[r, c] < min_v_search: # skip this pixel if it's not sufficient for being a seed pixel continue # roughly check whether this is a good seed pixel y0 = data_filtered[:, r, c] if np.max(y0) < thresh_init * noise_pixel[r, c]: continue # crop a small box for estimation of ai and ci r_min = np.max([0, r - gSiz]) r_max = np.min([d1, r + gSiz + 1]) c_min = np.max([0, c - gSiz]) c_max = np.min([d2, c + gSiz + 1]) nr = r_max - r_min nc = c_max - c_min patch_dims = (nr, nc) # patch dimension data_raw_box = \ data_raw[:, r_min:r_max, c_min:c_max].reshape(-1, nr * nc) data_filtered_box = \ data_filtered[:, r_min:r_max, c_min:c_max].reshape(-1, nr * nc) # index of the seed pixel in the cropped box ind_ctr = np.ravel_multi_index((r - r_min, c - c_min), dims=(nr, nc)) # neighbouring pixels to update after initializing one neuron r2_min = np.max([0, r - 2 * gSiz]) r2_max = np.min([d1, r + 2 * gSiz + 1]) c2_min = np.max([0, c - 2 * gSiz]) c2_max = np.min([d2, c + 2 * gSiz + 1]) if save_video: ax_pnr_cn.cla() ax_pnr_cn.imshow(v_search, vmin=0, vmax=img_vmax) ax_pnr_cn.set_title('Neuron %d' % (num_neurons + 1)) ax_pnr_cn.set_axis_off() ax_pnr_cn.plot(csub_max[ind_local_max[ith_seed:]], rsub_max[ ind_local_max[ith_seed:]], '.r', ms=5) ax_pnr_cn.plot(c, r, 'or', markerfacecolor='red') ax_cn_box.imshow(cn[r_min:r_max, c_min:c_max], vmin=0, vmax=1) ax_cn_box.set_title('Correlation') ax_traces.cla() ax_traces.plot(y0) ax_traces.set_title('The fluo. trace at the seed pixel') writer.grab_frame() [ai, ci_raw, ind_success] = extract_ac(data_filtered_box, data_raw_box, ind_ctr, patch_dims) if (np.sum(ai > 0) < min_pixel) or (not ind_success): # bad initialization. discard and continue continue else: # cheers! good initialization. center[:, num_neurons] = [c, r] Ain[num_neurons, r_min:r_max, c_min:c_max] = ai Cin_raw[num_neurons] = ci_raw.squeeze() if deconvolve_options: # deconvolution ci, si, tmp_options, baseline, c1 = \ deconvolve_ca(ci_raw, deconvolve_options) Cin[num_neurons] = ci Sin[num_neurons] = si else: # no deconvolution baseline = np.median(ci_raw) ci_raw -= baseline ci = ci_raw.copy() ci[ci < 0] = 0 Cin[num_neurons] = ci.squeeze() if save_video: # mark the seed pixel on the correlation image ax_cn.plot(c, r, '.r') ax_cn_box.cla() ax_cn_box.imshow(ai) ax_cn_box.set_title('Spatial component') ax_traces.cla() ax_traces.plot(ci_raw) ax_traces.plot(ci, 'r') ax_traces.set_title('Temporal component') writer.grab_frame() # remove the spatial-temporal activity of the initialized # and update correlation image & PNR image # update the raw data data_raw[:, r_min:r_max, c_min:c_max] -= \ ai[np.newaxis, ...] * ci[..., np.newaxis, np.newaxis] if gSig: # spatially filtered the neuron shape tmp_img = Ain[num_neurons, r2_min:r2_max, c2_min:c2_max] if center_psf: ai_filtered = cv2.GaussianBlur(tmp_img, ksize=ksize, sigmaX=gSig[0], sigmaY=gSig[1], borderType=cv2.BORDER_REFLECT) \ - cv2.boxFilter(tmp_img, ddepth=-1, ksize=ksize, borderType=cv2.BORDER_REFLECT) else: ai_filtered = cv2.GaussianBlur(tmp_img, ksize=ksize, sigmaX=gSig[0], sigmaY=gSig[1], borderType=cv2.BORDER_REFLECT) # update the filtered data data_filtered[:, r2_min:r2_max, c2_min:c2_max] -= \ ai_filtered[np.newaxis, ...] * ci[..., np.newaxis, np.newaxis] data_filtered_box = data_filtered[:, r2_min:r2_max, c2_min:c2_max].copy() else: data_filtered_box = data_raw[:, r2_min:r2_max, c2_min:c2_max].copy() # update PNR image data_filtered_box -= data_filtered_box.mean(axis=0) max_box = np.max(data_filtered_box, axis=0) noise_box = noise_pixel[r2_min:r2_max, c2_min:c2_max] pnr_box = np.divide(max_box, noise_box) pnr[r2_min:r2_max, c2_min:c2_max] = pnr_box pnr_box[pnr_box < min_pnr] = 0 # update correlation image data_filtered_box[data_filtered_box < thresh_init * noise_box] = 0 cn_box = caiman.summary_images.local_correlations_fft( data_filtered_box, swap_dim=False) cn_box[np.isnan(cn_box) | (cn_box < 0)] = 0 cn[r_min:r_max, c_min:c_max] = cn_box[ (r_min - r2_min):(r_max - r2_min), (c_min - c2_min):(c_max - c2_min)] cn_box = cn[r2_min:r2_max, c2_min:c2_max] cn_box[cn_box < min_corr] = 0 # update v_search v_search[r2_min:r2_max, c2_min:c2_max] = cn_box * pnr_box # increase the number of detected neurons num_neurons += 1 # if num_neurons == max_number: continue_searching = False break else: if num_neurons % 10 == 1: print(num_neurons - 1, 'neurons have been initialized') print('In total, ', num_neurons, 'neurons were initialized.') # A = np.reshape(Ain[:num_neurons], (-1, d1 * d2)).transpose() A = np.reshape(Ain[:num_neurons], (-1, d1 * d2), order='F').transpose() C = Cin[:num_neurons] C_raw = Cin_raw[:num_neurons] S = Sin[:num_neurons] center = center[:, :num_neurons] if save_video: plt.close() writer.finish() return A, C, C_raw, S, center
def __initialize_online(self, model_LN, Y): _, original_d1, original_d2 = Y.shape opts = self.params.get_group('online') init_batch = opts['init_batch'] if model_LN is not None: Y = Y - caiman.movie( np.squeeze(model_LN.predict(np.expand_dims(Y, -1)))) Y = np.maximum(Y, 0) # Downsample if needed ds_factor = np.maximum(opts['ds_factor'], 1) if ds_factor > 1: Y = Y.resize(1. / ds_factor, 1. / ds_factor) self.estimates.shifts = [] # store motion shifts here self.estimates.time_new_comp = [] if self.params.get('online', 'motion_correct'): max_shifts_online = self.params.get('online', 'max_shifts_online') if self.params.get('motion', 'gSig_filt') is None: mc = Y.motion_correct(max_shifts_online, max_shifts_online) Y = mc[0].astype(np.float32) else: Y_filt = np.stack([ high_pass_filter_space(yf, self.params.motion['gSig_filt']) for yf in Y ], axis=0) Y_filt = caiman.movie(Y_filt) mc = Y_filt.motion_correct(max_shifts_online, max_shifts_online) Y = Y.apply_shifts(mc[1]) if self.params.get('motion', 'pw_rigid'): n_p = len([(it[0], it[1]) for it in sliding_window( Y[0], self.params.get('motion', 'overlaps'), self.params.get('motion', 'strides'))]) for sh in mc[1]: self.estimates.shifts.append( [tuple(sh) for i in range(n_p)]) else: self.estimates.shifts.extend(mc[1]) self.img_min = Y.min() self.current_frame_cor = Y[-1] if self.params.get('online', 'normalize'): Y -= self.img_min img_norm = np.std(Y, axis=0) img_norm += np.median(img_norm) # normalize data to equalize the FOV logging.info('Frame size:' + str(img_norm.shape)) if self.params.get('online', 'normalize'): Y = Y / img_norm[None, :, :] total_frame, d1, d2 = Y.shape Yr = Y.to_2D().T # convert data into 2D array self.img_norm = img_norm if self.params.get('online', 'init_method') == 'bare': logging.info('Using bare init') init = self.params.get_group('init').copy() is1p = (init['method_init'] == 'corr_pnr' and init['ring_size_factor'] is not None) if is1p: self.estimates.sn, psx = pre_processing.get_noise_fft( Yr, noise_range=self.params.get('preprocess', 'noise_range'), noise_method=self.params.get('preprocess', 'noise_method'), max_num_samples_fft=self.params.get( 'preprocess', 'max_num_samples_fft')) for key in ('K', 'nb', 'gSig', 'method_init'): init.pop(key, None) tmp = online_cnmf.bare_initialization( Y.transpose(1, 2, 0), init_batch=self.params.get('online', 'init_batch'), k=self.params.get('init', 'K'), gnb=self.params.get('init', 'nb'), method_init=self.params.get('init', 'method_init'), sn=self.estimates.sn, gSig=self.params.get('init', 'gSig'), return_object=False, options_total=self.params.to_dict(), **init) if is1p: (self.estimates.A, self.estimates.b, self.estimates.C, self.estimates.f, self.estimates.YrA, self.estimates.W, self.estimates.b0) = tmp else: (self.estimates.A, self.estimates.b, self.estimates.C, self.estimates.f, self.estimates.YrA) = tmp if self.fp_detector.method is not None: self.__reject_fp_comps(Y.shape[1:], max_bright=Y.max()) self.estimates.S = np.zeros_like(self.estimates.C) nr = self.estimates.C.shape[0] self.estimates.g = np.array([ -np.poly( [0.9] * max(self.params.get('preprocess', 'p'), 1))[1:] for gg in np.ones(nr) ]) self.estimates.bl = np.zeros(nr) self.estimates.c1 = np.zeros(nr) self.estimates.neurons_sn = np.std(self.estimates.YrA, axis=-1) self.estimates.lam = np.zeros(nr) elif self.params.get('online', 'init_method') == 'seeded': init = self.params.get_group('init').copy() is1p = (init['method_init'] == 'corr_pnr' and init['ring_size_factor'] is not None) if self.seed_file is None: raise ValueError( 'Please input analyzed mat file path as seed_file.') with h5py.File(self.seed_file, 'r') as f: Ain = f['A'][()] try: Ain = Ain.reshape((original_d1, original_d2, -1)) except: raise ValueError( 'The shape of A does not match the video source!') window_name = 'please check A_seed' Ain_gray = Ain.sum(axis=2) cv2.imshow(window_name, np.dstack([Ain_gray, Ain_gray, Ain_gray])) cv2.waitKey(0) cv2.destroyWindow(window_name) Ain = cv2.resize(Ain, (d2, d1)) Ain = Ain.reshape((-1, Ain.shape[-1]), order='F') Ain_norm = (Ain - Ain.min(0)[None, :]) / (Ain.max(0) - Ain.min(0)) A_seed = Ain_norm > 0.5 tmp = online_cnmf.seeded_initialization( Y.transpose(1, 2, 0), A_seed, k=self.params.get('init', 'K'), gSig=self.params.get('init', 'gSig'), return_object=False) self.estimates.A, self.estimates.b, self.estimates.C, self.estimates.f, self.estimates.YrA = tmp if is1p: ssub_B = self.params.get('init', 'ssub_B') * self.params.get( 'init', 'ssub') ring_size_factor = self.params.get('init', 'ring_size_factor') gSiz = 2 * np.array(self.params.get('init', 'gSiz')) // 2 + 1 W, b0 = initialization.compute_W(Y.transpose(1, 2, 0).reshape( (-1, total_frame), order='F'), self.estimates.A, self.estimates.C, (d1, d2), ring_size_factor * gSiz[0], ssub=ssub_B) self.estimates.W, self.estimates.b0 = W, b0 self.estimates.S = np.zeros_like(self.estimates.C) nr = self.estimates.C.shape[0] self.estimates.g = np.array([ -np.poly( [0.9] * max(self.params.get('preprocess', 'p'), 1))[1:] for gg in np.ones(nr) ]) self.estimates.bl = np.zeros(nr) self.estimates.c1 = np.zeros(nr) self.estimates.neurons_sn = np.std(self.estimates.YrA, axis=-1) self.estimates.lam = np.zeros(nr) else: raise Exception('Unknown initialization method!') T1 = init_batch * self.params.get('online', 'epochs') self.params.set('data', {'dims': Y.shape[1:]}) self._prepare_object(Yr, T1) return self
def correlation_pnr(Y, gSig=None, center_psf=True, swap_dim=True): """ compute the correlation image and the peak-to-noise ratio (PNR) image. If gSig is provided, then spatially filtered the video. Args: Y: np.ndarray (3D or 4D). Input movie data in 3D or 4D format gSig: scalar or vector. gaussian width. If gSig == None, no spatial filtering center_psf: Boolearn True indicates subtracting the mean of the filtering kernel swap_dim: Boolean True indicates that time is listed in the last axis of Y (matlab format) and moves it in the front Returns: cn: np.ndarray (2D or 3D). local correlation image of the spatially filtered (or not) data pnr: np.ndarray (2D or 3D). peak-to-noise ratios of all pixels/voxels """ if swap_dim: Y = np.transpose( Y, tuple(np.hstack((Y.ndim - 1, list(range(Y.ndim))[:-1])))) # parameters T, d1, d2 = Y.shape data_raw = Y.reshape(-1, d1, d2).astype('float32') # filter data data_filtered = data_raw.copy() if gSig: if not isinstance(gSig, list): gSig = [gSig, gSig] ksize = tuple([(3 * i) // 2 * 2 + 1 for i in gSig]) # create a spatial filter for removing background # psf = gen_filter_kernel(width=ksize, sigma=gSig, center=center_psf) if center_psf: for idx, img in enumerate(data_filtered): data_filtered[idx, ] = cv2.GaussianBlur(img, ksize=ksize, sigmaX=gSig[0], sigmaY=gSig[1], borderType=1) \ - cv2.boxFilter(img, ddepth=-1, ksize=ksize, borderType=1) # data_filtered[idx, ] = cv2.filter2D(img, -1, psf, borderType=1) else: for idx, img in enumerate(data_filtered): data_filtered[idx, ] = cv2.GaussianBlur(img, ksize=ksize, sigmaX=gSig[0], sigmaY=gSig[1], borderType=1) # compute peak-to-noise ratio data_filtered -= np.mean(data_filtered, axis=0) data_max = np.max(data_filtered, axis=0) data_std = get_noise_fft(data_filtered.transpose())[0].transpose() # data_std = get_noise(data_filtered, method='diff2_med') pnr = np.divide(data_max, data_std) pnr[pnr < 0] = 0 # remove small values tmp_data = data_filtered.copy() / data_std tmp_data[tmp_data < 3] = 0 # compute correlation image # cn = local_correlation(tmp_data, d1=d1, d2=d2) cn = local_correlations_fft(tmp_data, swap_dim=False) return cn, pnr
def correlation_pnr(Y, gSig=None, center_psf=True, swap_dim=True, background_filter='disk'): """ compute the correlation image and the peak-to-noise ratio (PNR) image. If gSig is provided, then spatially filtered the video. Args: Y: np.ndarray (3D or 4D). Input movie data in 3D or 4D format gSig: scalar or vector. gaussian width. If gSig == None, no spatial filtering center_psf: Boolearn True indicates subtracting the mean of the filtering kernel swap_dim: Boolean True indicates that time is listed in the last axis of Y (matlab format) and moves it in the front Returns: cn: np.ndarray (2D or 3D). local correlation image of the spatially filtered (or not) data pnr: np.ndarray (2D or 3D). peak-to-noise ratios of all pixels/voxels """ if swap_dim: Y = np.transpose( Y, tuple(np.hstack((Y.ndim - 1, list(range(Y.ndim))[:-1])))) # parameters _, d1, d2 = Y.shape data_raw = Y.reshape(-1, d1, d2).astype('float32') # filter data data_filtered = data_raw.copy() if gSig: if not isinstance(gSig, list): gSig = [gSig, gSig] ksize = tuple([int(2 * i) * 2 + 1 for i in gSig]) if center_psf: if background_filter == 'box': for idx, img in enumerate(data_filtered): data_filtered[idx, ] = cv2.GaussianBlur( img, ksize=ksize, sigmaX=gSig[0], sigmaY=gSig[1], borderType=1) \ - cv2.boxFilter(img, ddepth=-1, ksize=ksize, borderType=1) else: psf = cv2.getGaussianKernel(ksize[0], gSig[0], cv2.CV_32F).dot( cv2.getGaussianKernel(ksize[1], gSig[1], cv2.CV_32F).T) ind_nonzero = psf >= psf[0].max() psf -= psf[ind_nonzero].mean() psf[~ind_nonzero] = 0 for idx, img in enumerate(data_filtered): data_filtered[idx, ] = cv2.filter2D(img, -1, psf, borderType=1) # data_filtered[idx, ] = cv2.filter2D(img, -1, psf, borderType=1) else: for idx, img in enumerate(data_filtered): data_filtered[idx, ] = cv2.GaussianBlur( img, ksize=ksize, sigmaX=gSig[0], sigmaY=gSig[1], borderType=1) # compute peak-to-noise ratio data_filtered -= data_filtered.mean(axis=0) data_max = np.max(data_filtered, axis=0) data_std = get_noise_fft(data_filtered.T, noise_method='mean')[0].T pnr = np.divide(data_max, data_std) pnr[pnr < 0] = 0 # remove small values tmp_data = data_filtered.copy() / data_std tmp_data[tmp_data < 3] = 0 # compute correlation image cn = local_correlations_fft(tmp_data, swap_dim=False) return cn, pnr