def get_fig_gSig_filt_vals(cropped_file, gSig_filt_vals): """ Plot original cropped frame and several versions of spatial filtering for comparison :param cropped_file :param gSig_filt_vals: array containing size of spatial filters that will be applied :return: figure """ m = cm.load(cropped_file) temp = cm.motion_correction.bin_median(m) N = len(gSig_filt_vals) fig, axes = plt.subplots(int(math.ceil((N + 1) / 2)), 2) axes[0, 0].imshow(temp, cmap='gray') axes[0, 0].set_title('unfiltered') axes[0, 0].axis('off') for i in range(0, N): gSig_filt = gSig_filt_vals[i] m_filt = [ high_pass_filter_space(m_, (gSig_filt, gSig_filt)) for m_ in m ] temp_filt = cm.motion_correction.bin_median(m_filt) axes.flatten()[i + 1].imshow(temp_filt, cmap='gray') axes.flatten()[i + 1].set_title(f'gSig_filt = {gSig_filt}') axes.flatten()[i + 1].axis('off') if N + 1 != axes.size: for i in range(N + 1, axes.size): axes.flatten()[i].axis('off') # Get output file paths sql = "SELECT mouse,session,trial,is_rest,cropping_v,decoding_v,motion_correction_v FROM Analysis WHERE cropping_main=%s " val = [ cropped_file, ] mycursor.execute(sql, val) myresult = mycursor.fetchall() data = [] for x in myresult: data += x file_name = f"mouse_{data[0]}_session_{data[1]}_trial_{data[2]}.{data[3]}.v{data[5]}.{data[4]}.{data[6]}" data_dir = 'data/interim/motion_correction/' output_meta_gSig_filt = data_dir + f'meta/figures/frame_gSig_filt/{file_name}.png' fig.savefig(output_meta_gSig_filt) return fig
def get_fig_gSig_filt_vals(m, gSig_filt_vals): temp = cm.motion_correction.bin_median(m) N = len(gSig_filt_vals) fig, axes = plt.subplots(int(math.ceil((N + 1) / 4)), 4) axes[0, 0].imshow(temp, cmap='gray') axes[0, 0].set_title('unfiltered') axes[0, 0].axis('off') for i in range(0, N): gSig_filt = gSig_filt_vals[i] m_filt = [ high_pass_filter_space(m_, (gSig_filt, gSig_filt)) for m_ in m ] temp_filt = cm.motion_correction.bin_median(m_filt) axes.flatten()[i + 1].imshow(temp_filt, cmap='gray') axes.flatten()[i + 1].set_title(f'gSig_filt = {gSig_filt}') axes.flatten()[i + 1].axis('off') if N + 1 != axes.size: for i in range(N + 1, axes.size): axes.flatten()[i].axis('off') return fig
def get_fig_gSig_filt_vals(row, gSig_filt_vals): ''' Plot original cropped frame and several versions of spatial filtering for comparison :param row: analisis state row for which the filtering is computed :param gSig_filt_vals: array containing size of spatial filters that will be applyed :return: figure ''' output = row['cropping_output'] cropped_file = eval(output)['main'] m = cm.load(cropped_file) temp = cm.motion_correction.bin_median(m) N = len(gSig_filt_vals) fig, axes = plt.subplots(int(math.ceil((N + 1) / 2)), 2) axes[0, 0].imshow(temp, cmap='gray') axes[0, 0].set_title('unfiltered') axes[0, 0].axis('off') for i in range(0, N): gSig_filt = gSig_filt_vals[i] m_filt = [high_pass_filter_space(m_, (gSig_filt, gSig_filt)) for m_ in m] temp_filt = cm.motion_correction.bin_median(m_filt) axes.flatten()[i + 1].imshow(temp_filt, cmap='gray') axes.flatten()[i + 1].set_title(f'gSig_filt = {gSig_filt}') axes.flatten()[i + 1].axis('off') if N + 1 != axes.size: for i in range(N + 1, axes.size): axes.flatten()[i].axis('off') # Get output file paths index = row.name data_dir = 'data/interim/motion_correction/' step_index = db.get_step_index('motion_correction') file_name = db.create_file_name(step_index, index) output_meta_gSig_filt = data_dir + f'meta/figures/frame_gSig_filt/{file_name}.png' fig.savefig(output_meta_gSig_filt) return fig
def parameters_test_gSig(path, figname, gSig_filt_list=None): m_orig = cm.load(path) if gSig_filt_list == None: gSig_filt_list = [(2, 2), (4, 4), (6, 6), (8, 8), (10, 10), (20, 20), (30, 30)] m_filt_list = [] for i, gSig_filt in enumerate(gSig_filt_list): m_filt_list.append( cm.movie( np.array( [high_pass_filter_space(m_, gSig_filt) for m_ in m_orig]))) import matplotlib.pyplot as plt for i, mov in enumerate(m_filt_list): plt.figure() plt.imshow(mov[0], cmap='gray') gSig_size = gSig_filt_list[i] plt.title(f'{figname} \n gSig_size = {gSig_size}') plt.savefig( f'data/motion_correction/png/{figname}_gSig_experiment_{gSig_size}.png' ) return
def run_alignmnet(selected_rows, parameters, dview): ''' This is the main function for the alignment step. It applies methods from the CaImAn package used originally in motion correction to do alignment. Args: df: pd.DataFrame A dataframe containing the analysis states you want to have aligned. parameters: dict The alignment parameters. dview: object The dview object Returns: df: pd.DataFrame A dataframe containing the aligned analysis states. ''' # Sort the dataframe correctly df = selected_rows.copy() df = df.sort_values(by=paths.multi_index_structure) # Determine the mouse and session of the dataset index = df.iloc[0].name mouse, session, *r = index # alignment_v = index[len(paths.data_structure) + step_index] alignment_v = len(df) alignment_index = (mouse, session, alignment_v) # Determine the output .mmap file name file_name = f'mouse_{mouse}_session_{session}_v{alignment_v}' output_mmap_file_path = os.environ['DATA_DIR'] + f'data/interim/alignment/main/{file_name}.mmap' try: df.reset_index()[['session','trial', 'is_rest']].set_index(['session','trial', 'is_rest'], verify_integrity=True) except ValueError: logging.error('You passed multiple of the same trial in the dataframe df') return df output = { 'meta': { 'analysis': { 'analyst': os.environ['ANALYST'], 'date': datetime.datetime.today().strftime("%m-%d-%Y"), 'time': datetime.datetime.today().strftime("%H:%M:%S") }, 'duration': {} } } # Get necessary parameters motion_correction_parameters_list = [] motion_correction_output_list = [] input_mmap_file_list = [] trial_index_list = [] x_ = [] _x = [] y_ = [] _y = [] for idx, row in df.iterrows(): motion_correction_parameters_list.append(eval(row.loc['motion_correction_parameters'])) motion_correction_output = eval(row.loc['motion_correction_output']) motion_correction_output_list.append(motion_correction_output) input_mmap_file_list.append(motion_correction_output['main']) trial_index_list.append(db.get_trial_name(idx[2], idx[3])) [x1,x2,y1,y2] = motion_correction_output['meta']['cropping_points'] x_.append(x1) _x.append(x2) y_.append(y1) _y.append(y2) new_x1 = max(x_) new_x2 = max(_x) new_y1 = max(y_) new_y2 = max(_y) m_list = [] for i in range(len(input_mmap_file_list)): m = cm.load(input_mmap_file_list[i]) motion_correction_output = eval(df.iloc[i].loc['motion_correction_output']) [x1,x2,y1,y2] = motion_correction_output['meta']['cropping_points'] m = m.crop(new_x1 - x1, new_x2 - x2, new_y1 - y1, new_y2 - y2, 0, 0) m_list.append(m) # Concatenate them using the concat function m_concat = cm.concatenate(m_list, axis=0) data_dir = os.environ['DATA_DIR'] + 'data/interim/alignment/main/' file_name = db.create_file_name(step_index, index) fname= m_concat.save(data_dir + file_name + '.mmap', order='C') #meta_pkl_dict['pw_rigid']['cropping_points'] = [x_, _x, y_, _y] #output['meta']['cropping_points'] = [x_, _x, y_, _y] # Save the movie #fname_tot_els = m_els.save(data_dir + 'main/' + file_name + '_els' + '.mmap', order='C') #logging.info(f'{index} Cropped and saved rigid movie as {fname_tot_els}') # MOTION CORRECTING EACH INDIVIDUAL MOVIE WITH RESPECT TO A TEMPLATE MADE OF THE FIRST MOVIE logging.info(f'{alignment_index} Performing motion correction on all movies with respect to a template made of \ the first movie.') t0 = datetime.datetime.today() # Create a template of the first movie template_index = trial_index_list.index(parameters['make_template_from_trial']) m0 = cm.load(input_mmap_file_list[template_index ]) [x1, x2, y1, y2] = motion_correction_output_list[template_index]['meta']['cropping_points'] m0 = m0.crop(new_x1 - x1, new_x2 - x2, new_y1 - y1, new_y2 - y2, 0, 0) m0_filt = cm.movie( np.array([high_pass_filter_space(m_, parameters['gSig_filt']) for m_ in m0])) template0 = cm.motion_correction.bin_median( m0_filt.motion_correct(5, 5, template=None)[0]) # may be improved in the future # Setting the parameters opts = params.CNMFParams(params_dict=parameters) # Create a motion correction object mc = MotionCorrect(fname, dview=dview, **opts.get_group('motion')) # Perform non-rigid motion correction mc.motion_correct(template=template0, save_movie=True) # Cropping borders x_ = math.ceil(abs(np.array(mc.shifts_rig)[:, 1].max()) if np.array(mc.shifts_rig)[:, 1].max() > 0 else 0) _x = math.ceil(abs(np.array(mc.shifts_rig)[:, 1].min()) if np.array(mc.shifts_rig)[:, 1].min() < 0 else 0) y_ = math.ceil(abs(np.array(mc.shifts_rig)[:, 0].max()) if np.array(mc.shifts_rig)[:, 0].max() > 0 else 0) _y = math.ceil(abs(np.array(mc.shifts_rig)[:, 0].min()) if np.array(mc.shifts_rig)[:, 0].min() < 0 else 0) # Load the motion corrected movie into memory movie= cm.load(mc.fname_tot_rig[0]) # Crop all movies to those border pixels movie.crop(x_, _x, y_, _y, 0, 0) output['meta']['cropping_points'] = [x_, _x, y_, _y] #save motion corrected and cropped movie output_mmap_file_path_tot = movie.save(data_dir + file_name + '.mmap', order='C') logging.info(f'{index} Cropped and saved rigid movie as {output_mmap_file_path_tot}') # Save the path in teh output dictionary output['main'] = output_mmap_file_path_tot # Remove the remaining non-cropped movie os.remove(mc.fname_tot_rig[0]) # Create a timeline and store it timeline = [[trial_index_list[0], 0]] timepoints = [0] for i in range(1, len(m_list)): m = m_list[i] timeline.append([trial_index_list[i], timeline[i - 1][1] + m.shape[0]]) timepoints.append(timepoints[i-1]+ m.shape[0]) timeline_pkl_file_path = os.environ['DATA_DIR'] + f'data/interim/alignment/meta/timeline/{file_name}.pkl' with open(timeline_pkl_file_path,'wb') as f: pickle.dump(timeline,f) output['meta']['timeline'] = timeline_pkl_file_path timepoints.append(movie.shape[0]) dt = int((datetime.datetime.today() - t0).seconds / 60) # timedelta in minutes output['meta']['duration']['concatenation'] = dt logging.info(f'{alignment_index} Performed concatenation. dt = {dt} min.') for idx, row in df.iterrows(): df.loc[idx, 'alignment_output'] = str(output) df.loc[idx, 'alignment_parameters'] = str(parameters) ## modify all motion correction file to the aligned version data_dir = os.environ['DATA_DIR'] + 'data/interim/motion_correction/main/' for i in range(len(input_mmap_file_list)): row = df.iloc[i].copy() motion_correction_output_list.append(motion_correction_output) aligned_movie = movie[timepoints[i]:timepoints[i+1]] file_name = db.create_file_name(2, selected_rows.iloc[i].name) motion_correction_output_aligned = aligned_movie.save(data_dir + file_name + '_els' + '.mmap', order='C') new_output= {'main' : motion_correction_output_aligned } new_dict = eval(row['motion_correction_output']) new_dict.update(new_output) row['motion_correction_output'] = str(new_dict) df = db.append_to_or_merge_with_states_df(df, row) # # Delete the motion corrected movies # for fname in mc.fname_tot_rig: # os.remove(fname) return df
def __fit_next_frame(self, frame, t, model_LN=None, out=None): ssub_B = self.params.get('init', 'ssub_B') * self.params.get( 'init', 'ssub') d1, d2 = self.params.get('data', 'dims') max_shifts_online = self.params.get('online', 'max_shifts_online') if model_LN is not None: if self.params.get('ring_CNN', 'remove_activity'): activity = self.estimates.Ab[:, :self.N].dot( self.estimates.C_on[:self.N, t - 1]).reshape(self.params.get( 'data', 'dims'), order='F') if self.params.get('online', 'normalize'): activity *= self.img_norm else: activity = 0. # frame = frame.astype(np.float32) - activity frame = frame - np.squeeze( model_LN.predict( np.expand_dims( np.expand_dims(frame.astype(np.float32) - activity, 0), -1))) frame = np.maximum(frame, 0) t_frame_start = time.time() if np.isnan(np.sum(frame)): raise Exception('Current frame contains NaN') frame_ = frame.copy().astype(np.float32) if self.params.get('online', 'ds_factor') > 1: frame_ = cv2.resize(frame_, self.img_norm.shape[::-1]) if self.params.get('online', 'normalize'): frame_ -= self.img_min # make data non-negative if self.params.get('online', 'motion_correct'): templ = self.estimates.Ab.dot( np.median(self.estimates.C_on[:self.M, t - 51:t - 1], 1)).reshape(self.params.get('data', 'dims'), order='F') #*self.img_norm if self.is1p and self.estimates.W is not None: if ssub_B == 1: B = self.estimates.W.dot((frame_ - templ).flatten( order='F') - self.estimates.b0) + self.estimates.b0 B = B.reshape(self.params.get('data', 'dims'), order='F') else: b0 = self.estimates.b0.reshape((d1, d2), order='F') #*self.img_norm bc2 = initialization.downscale( frame_ - templ - b0, (ssub_B, ssub_B)).flatten(order='F') Wb = self.estimates.W.dot(bc2).reshape( ((d1 - 1) // ssub_B + 1, (d2 - 1) // ssub_B + 1), order='F') B = b0 + np.repeat(np.repeat(Wb, ssub_B, 0), ssub_B, 1)[:d1, :d2] templ += B if self.params.get('online', 'normalize'): templ *= self.img_norm if self.is1p: templ = high_pass_filter_space(templ, self.params.motion['gSig_filt']) if self.params.get('motion', 'pw_rigid'): frame_cor, shift, _, xy_grid = tile_and_correct( frame_, templ, self.params.motion['strides'], self.params.motion['overlaps'], self.params.motion['max_shifts'], newoverlaps=None, newstrides=None, upsample_factor_grid=4, upsample_factor_fft=10, show_movie=False, max_deviation_rigid=self.params. motion['max_deviation_rigid'], add_to_movie=0, shifts_opencv=True, gSig_filt=None, use_cuda=False, border_nan='copy') else: if self.is1p: frame_orig = frame_.copy() frame_ = high_pass_filter_space( frame_, self.params.motion['gSig_filt']) frame_cor, shift = motion_correct_iteration_fast( frame_, templ, max_shifts_online, max_shifts_online) if self.is1p: M = np.float32([[1, 0, shift[1]], [0, 1, shift[0]]]) frame_cor = cv2.warpAffine(frame_orig, M, frame_.shape[::-1], flags=cv2.INTER_CUBIC, borderMode=cv2.BORDER_REFLECT) self.estimates.shifts.append(shift) else: templ = None frame_cor = frame_ self.current_frame_cor = frame_cor if self.params.get('online', 'normalize'): frame_cor = frame_cor / self.img_norm self.fit_next(t, frame_cor.reshape(-1, order='F')) if self.fp_detector.method is not None: self.__reject_fp_comps((d1, d2), max_bright=frame_.max())
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 run_alignment(mouse, sessions, motion_correction_v, cropping_v, dview): """ This is the main function for the alignment step. It applies methods from the CaImAn package used originally in motion correction to do alignment. """ for session in sessions: # Update the database file_name = f"mouse_{mouse}_session_{session}_alignment" sql1 = "UPDATE Analysis SET alignment_main=? WHERE mouse = ? AND session=? AND motion_correction_v =? AND cropping_v=? " val1 = [file_name, mouse, session, motion_correction_v, cropping_v] cursor.execute(sql1, val1) # Determine the output .mmap file name output_mmap_file_path = os.environ[ 'DATA_DIR_LOCAL'] + f'data/interim/alignment/main/{file_name}.mmap' sql = "SELECT motion_correction_main FROM Analysis WHERE mouse = ? AND session=? AND motion_correction_v =? AND cropping_v=? " val = [mouse, session, motion_correction_v, cropping_v] cursor.execute(sql, val) result = cursor.fetchall() input_mmap_file_list = [] inter = [] for x in result: inter += x for y in inter: input_mmap_file_list.append(y) sql = "SELECT motion_correction_cropping_points_x1 FROM Analysis WHERE mouse = ? AND session=?AND motion_correction_v =? AND cropping_v=? " val = [mouse, session, motion_correction_v, cropping_v] cursor.execute(sql, val) result = cursor.fetchall() x_ = [] inter = [] for i in result: inter += i for j in range(0, len(inter)): x_.append(inter[j]) sql = "SELECT motion_correction_cropping_points_x2 FROM Analysis WHERE mouse = ? AND session=? AND motion_correction_v =? AND cropping_v=? " val = [mouse, session, motion_correction_v, cropping_v] cursor.execute(sql, val) result = cursor.fetchall() _x = [] inter = [] for i in result: inter += i for j in range(0, len(inter)): _x.append(inter[j]) sql = "SELECT motion_correction_cropping_points_y1 FROM Analysis WHERE mouse = ? AND session=? AND motion_correction_v =? AND cropping_v=?" val = [mouse, session, motion_correction_v, cropping_v] cursor.execute(sql, val) result = cursor.fetchall() _y = [] inter = [] for i in result: inter += i for j in range(0, len(inter)): _y.append(inter[j]) sql = "SELECT motion_correction_cropping_points_y2 FROM Analysis WHERE mouse = ? AND session=? AND motion_correction_v =? AND cropping_v=?" val = [mouse, session, motion_correction_v, cropping_v] cursor.execute(sql, val) result = cursor.fetchall() y_ = [] inter = [] for i in result: inter += i for j in range(0, len(inter)): y_.append(inter[j]) new_x1 = max(x_) new_x2 = max(_x) new_y1 = max(y_) new_y2 = max(_y) m_list = [] for i in range(len(input_mmap_file_list)): m = cm.load(input_mmap_file_list[i]) m = m.crop(new_x1 - x_[i], new_x2 - _x[i], new_y1 - y_[i], new_y2 - _y[i], 0, 0) m_list.append(m) # Concatenate them using the concat function m_concat = cm.concatenate(m_list, axis=0) fname = m_concat.save(output_mmap_file_path, order='C') # MOTION CORRECTING EACH INDIVIDUAL MOVIE WITH RESPECT TO A TEMPLATE MADE OF THE FIRST MOVIE logging.info( 'Performing motion correction on all movies with respect to a template made of the first movie.' ) t0 = datetime.datetime.today() # parameters alignment sql5 = "SELECT make_template_from_trial,gSig_filt,max_shifts,niter_rig,strides,overlaps,upsample_factor_grid,num_frames_split,max_deviation_rigid,shifts_opencv,use_conda,nonneg_movie, border_nan FROM Analysis WHERE alignment_main=? " val5 = [ file_name, ] cursor.execute(sql5, val5) myresult = cursor.fetchall() para = [] aux = [] for x in myresult: aux = x for y in aux: para.append(y) parameters = { 'make_template_from_trial': para[0], 'gSig_filt': (para[1], para[1]), 'max_shifts': (para[2], para[2]), 'niter_rig': para[3], 'strides': (para[4], para[4]), 'overlaps': (para[5], para[5]), 'upsample_factor_grid': para[6], 'num_frames_split': para[7], 'max_deviation_rigid': para[8], 'shifts_opencv': para[9], 'use_cuda': para[10], 'nonneg_movie': para[11], 'border_nan': para[12] } # Create a template of the first movie template_index = parameters['make_template_from_trial'] m0 = cm.load(input_mmap_file_list[1]) [x1, x2, y1, y2] = [x_, _x, y_, _y] for i in range(len(input_mmap_file_list)): m0 = m0.crop(new_x1 - x_[i], new_x2 - _x[i], new_y1 - y_[i], new_y2 - _y[i], 0, 0) m0_filt = cm.movie( np.array([ high_pass_filter_space(m_, parameters['gSig_filt']) for m_ in m0 ])) template0 = cm.motion_correction.bin_median( m0_filt.motion_correct( 5, 5, template=None)[0]) # may be improved in the future # Setting the parameters opts = params.CNMFParams(params_dict=parameters) # Create a motion correction object mc = MotionCorrect(fname, dview=dview, **opts.get_group('motion')) # Perform non-rigid motion correction mc.motion_correct(template=template0, save_movie=True) # Cropping borders x_ = math.ceil( abs(np.array(mc.shifts_rig)[:, 1].max() ) if np.array(mc.shifts_rig)[:, 1].max() > 0 else 0) _x = math.ceil( abs(np.array(mc.shifts_rig)[:, 1].min() ) if np.array(mc.shifts_rig)[:, 1].min() < 0 else 0) y_ = math.ceil( abs(np.array(mc.shifts_rig)[:, 0].max() ) if np.array(mc.shifts_rig)[:, 0].max() > 0 else 0) _y = math.ceil( abs(np.array(mc.shifts_rig)[:, 0].min() ) if np.array(mc.shifts_rig)[:, 0].min() < 0 else 0) # Load the motion corrected movie into memory movie = cm.load(mc.fname_tot_rig[0]) # Crop all movies to those border pixels movie.crop(x_, _x, y_, _y, 0, 0) sql1 = "UPDATE Analysis SET alignment_x1=?, alignment_x2 =?, alignment_y1=?, alignment_y2=? WHERE mouse = ? AND session=? AND motion_correction_v =? AND cropping_v=?" val1 = [ x_, _x, y_, _y, mouse, session, motion_correction_v, cropping_v ] cursor.execute(sql1, val1) # save motion corrected and cropped movie output_mmap_file_path_tot = movie.save( os.environ['DATA_DIR_LOCAL'] + f'data/interim/alignment/main/{file_name}.mmap', order='C') logging.info( f' Cropped and saved rigid movie as {output_mmap_file_path_tot}') # Remove the remaining non-cropped movie os.remove(mc.fname_tot_rig[0]) # Create a timeline and store it sql = "SELECT trial FROM Analysis WHERE mouse = ? AND session=? AND motion_correction_v =? AND cropping_v=?" val = [mouse, session, motion_correction_v, cropping_v] cursor.execute(sql, val) result = cursor.fetchall() trial_index_list = [] inter = [] for i in result: inter += i for j in range(0, len(inter)): trial_index_list.append(inter[j]) timeline = [[trial_index_list[0], 0]] timepoints = [0] for i in range(1, len(m_list)): m = m_list[i] timeline.append( [trial_index_list[i], timeline[i - 1][1] + m.shape[0]]) timepoints.append(timepoints[i - 1] + m.shape[0]) timeline_pkl_file_path = os.environ[ 'DATA_DIR'] + f'data/interim/alignment/meta/timeline/{file_name}.pkl' with open(timeline_pkl_file_path, 'wb') as f: pickle.dump(timeline, f) sql1 = "UPDATE Analysis SET alignment_timeline=? WHERE mouse = ? AND session=?AND motion_correction_v =? AND cropping_v=? " val1 = [ timeline_pkl_file_path, mouse, session, motion_correction_v, cropping_v ] cursor.execute(sql1, val1) timepoints.append(movie.shape[0]) dt = int((datetime.datetime.today() - t0).seconds / 60) # timedelta in minutes sql1 = "UPDATE Analysis SET alignment_duration_concatenation=? WHERE mouse = ? AND session=?AND motion_correction_v =? AND cropping_v=? " val1 = [dt, mouse, session, motion_correction_v, cropping_v] cursor.execute(sql1, val1) logging.info(f' Performed concatenation. dt = {dt} min.') ## modify all motion correction file to the aligned version data_dir = os.environ[ 'DATA_DIR'] + 'data/interim/motion_correction/main/' for i in range(len(input_mmap_file_list)): aligned_movie = movie[timepoints[i]:timepoints[i + 1]] motion_correction_output_aligned = aligned_movie.save( data_dir + file_name + '_els' + '.mmap', order='C') sql1 = "UPDATE Analysis SET motion_correct_align=? WHERE motion_correction_meta=? AND motion_correction_v" val1 = [ motion_correction_output_aligned, input_mmap_file_list[i], motion_correction_v ] cursor.execute(sql1, val1) database.commit() return
def run_alignmnet(states_df, parameters, dview): ''' This is the main function for the alignment step. It applies methods from the CaImAn package used originally in motion correction to do alignment. Args: df: pd.DataFrame A dataframe containing the analysis states you want to have aligned. parameters: dict The alignment parameters. dview: object The dview object Returns: df: pd.DataFrame A dataframe containing the aligned analysis states. ''' # Sort the dataframe correctly df = states_df.copy() df = df.sort_values(by=paths.multi_index_structure) # Determine the mouse and session of the dataset index = df.iloc[0].name mouse, session, *r = index #alignment_v = index[len(paths.data_structure) + step_index] alignment_v = len(df) alignment_index = (mouse, session, alignment_v) # Determine the output .mmap file name file_name = f'mouse_{mouse}_session_{session}_v{alignment_v}' output_mmap_file_path = f'data/interim/alignment/main/{file_name}.mmap' try: df.reset_index()[['trial', 'is_rest']].set_index(['trial', 'is_rest'], verify_integrity=True) except ValueError: logging.error( 'You passed multiple of the same trial in the dataframe df') return df output = { 'meta': { 'analysis': { 'analyst': os.environ['ANALYST'], 'date': datetime.datetime.today().strftime("%m-%d-%Y"), 'time': datetime.datetime.today().strftime("%H:%M:%S") }, 'duration': {} } } # Get necessary parameters motion_correction_parameters_list = [] motion_correction_output_list = [] input_mmap_file_list = [] trial_index_list = [] for idx, row in df.iterrows(): motion_correction_parameters_list.append( eval(row.loc['motion_correction_parameters'])) motion_correction_output = eval(row.loc['motion_correction_output']) motion_correction_output_list.append(motion_correction_output) input_mmap_file_list.append(motion_correction_output['main']) trial_index_list.append(db.get_trial_name(idx[2], idx[3])) # MOTION CORRECTING EACH INDIVIDUAL MOVIE WITH RESPECT TO A TEMPLATE MADE OF THE FIRST MOVIE logging.info( f'{alignment_index} Performing motion correction on all movies with respect to a template made of \ the first movie.') t0 = datetime.datetime.today() # Create a template of the first movie template_index = trial_index_list.index( parameters['make_template_from_trial']) m0 = cm.load(input_mmap_file_list[template_index]) m0_filt = cm.movie( np.array([ high_pass_filter_space(m_, parameters['gSig_filt']) for m_ in m0 ])) template0 = cm.motion_correction.bin_median( m0_filt.motion_correct( 5, 5, template=None)[0]) # may be improved in the future # Setting the parameters opts = params.CNMFParams(params_dict=parameters) # Create a motion correction object mc = MotionCorrect(input_mmap_file_list, dview=dview, **opts.get_group('motion')) # Perform non-rigid motion correction mc.motion_correct(template=template0, save_movie=True) # Cropping borders x_ = math.ceil( abs(np.array(mc.shifts_rig)[:, 1].max() ) if np.array(mc.shifts_rig)[:, 1].max() > 0 else 0) _x = math.ceil( abs(np.array(mc.shifts_rig)[:, 1].min() ) if np.array(mc.shifts_rig)[:, 1].min() < 0 else 0) y_ = math.ceil( abs(np.array(mc.shifts_rig)[:, 0].max() ) if np.array(mc.shifts_rig)[:, 0].max() > 0 else 0) _y = math.ceil( abs(np.array(mc.shifts_rig)[:, 0].min() ) if np.array(mc.shifts_rig)[:, 0].min() < 0 else 0) dt = int( (datetime.datetime.today() - t0).seconds / 60) # timedelta in minutes output['meta']['duration']['motion_correction'] = dt logging.info( f'{alignment_index} Performed motion correction. dt = {dt} min.') # CONCATENATING ALL MOTION CORRECTED MOVIES logging.info( f'{alignment_index} Concatenating all motion corrected movies.') # Load all movies into memory m_list = [cm.load(fname) for fname in mc.fname_tot_rig] # Crop all movies to those border pixels for idx, m in enumerate(m_list): m_list[idx] = m.crop(x_, _x, y_, _y, 0, 0) output['meta']['cropping_points'] = [x_, _x, y_, _y] # Concatenate them using the concat function m_concat = cm.concatenate(m_list, axis=0) # Create a timeline and store it timeline = [[trial_index_list[0], 0]] for i in range(1, len(m_list)): m = m_list[i] timeline.append([trial_index_list[i], timeline[i - 1][1] + m.shape[0]]) # timeline_pkl_file_path = f'data/interim/alignment/meta/timeline/{file_name}.pkl' # with open(timeline_pkl_file_path,'wb') as f: # pickle.dump(timeline,f) # output['meta']['timeline'] = timeline_pkl_file_path output['meta']['timeline'] = timeline # Save the concatenated movie output_mmap_file_path_tot = m_concat.save(output_mmap_file_path) output['main'] = output_mmap_file_path_tot # # Delete the motion corrected movies # for fname in mc.fname_tot_rig: # os.remove(fname) dt = int( (datetime.datetime.today() - t0).seconds / 60) # timedelta in minutes output['meta']['duration']['concatenation'] = dt logging.info(f'{alignment_index} Performed concatenation. dt = {dt} min.') for idx, row in df.iterrows(): df.loc[idx, 'alignment_output'] = str(output) df.loc[idx, 'alignment_parameters'] = str(parameters) return df
def get_correlations(df): ''' Get the correlation of both the origin movies and the aligned movie w.r.t a template created of the movie to which the movies were aligned Args: df: pd.DataFrame The dataframe containing the aligned analysis states. Returns: df: pd.DataFrame The dataframe containing the aligned analysis states with the metrics stored in the meta output. ''' # Load a dummy index index = df.iloc[0].name # Load the original movies and the aligned, concatenated movie original_m_list = [] trial_name_list = [] for index, row in df.iterrows(): motion_correction_output = eval(row.loc['motion_correction_output']) m = cm.load(motion_correction_output['main']) original_m_list.append(m) trial_name_list.append(db.get_trial_name(index[2], index[3])) alignment_output = eval(df.iloc[0].loc['alignment_output']) aligned_m = cm.load(alignment_output['main']) # Load the cropping points and timeline and to which trial the alignment was done cropping_points = alignment_output['meta']['cropping_points'] timeline = alignment_output['meta']['timeline'] alignment_parameters = eval(df.iloc[0].loc['alignment_parameters']) make_template_from_trial = alignment_parameters['make_template_from_trial'] template_index = trial_name_list.index(make_template_from_trial) # Crop the original movies cropped_original_m_list = [] for i, m in enumerate(original_m_list): [x_, _x, y_, _y] = cropping_points cropped_original_m_list.append(m.crop(x_, _x, y_, _y, 0, 0)) # Concatenate the original movie m_original_concat = cm.concatenate(cropped_original_m_list, axis=0) # ORIGINAL MOVIE CORRELATIONS # Create a template of the movie to which alignment has taken place m0 = cropped_original_m_list[template_index] m0_filt = cm.movie( np.array([ high_pass_filter_space(m_, alignment_parameters['gSig_filt']) for m_ in m0 ])) tmpl = caiman.motion_correction.bin_median( m0_filt.motion_correct( 5, 5, template=None)[0]) # may be improved in the future # Calculate the correlations of each movie with respect to that template logging.debug('Computing original movie correlations') t0 = datetime.datetime.today() correlations_orig = [] count = 0 m_compute = m_original_concat - np.min(m_original_concat) for fr in m_compute: if count % 100 == 0: logging.debug(f'Frame {count}') count += 1 correlations_orig.append( scipy.stats.pearsonr(fr.flatten(), tmpl.flatten())[0]) dt = int( (datetime.datetime.today() - t0).seconds / 60) # timedelta in minutes logging.debug(f'Computed original movie correlations. dt = {dt} min') # ALIGNED CORRELATIONS # Create a template of the movie to which alignment has taken place m0 = aligned_m[timeline[template_index][1]:timeline[ template_index + 1][1]] if template_index != len( timeline) - 1 else aligned_m[timeline[template_index][1]:] m0_filt = cm.movie( np.array([ high_pass_filter_space(m_, alignment_parameters['gSig_filt']) for m_ in m0 ])) tmpl = caiman.motion_correction.bin_median( m0_filt.motion_correct( 5, 5, template=None)[0]) # may be improved in the future # Calculate the correlations of each movie with respect to that template logging.debug('Computing aligned movie correlations') t0 = datetime.datetime.today() correlations_aligned = [] count = 0 m_compute = aligned_m - np.min(aligned_m) for fr in m_compute: if count % 100 == 0: logging.debug(f'Frame {count}') count += 1 correlations_aligned.append( scipy.stats.pearsonr(fr.flatten(), tmpl.flatten())[0]) dt = int( (datetime.datetime.today() - t0).seconds / 60) # timedelta in minutes logging.debug(f'Computed aligned movie correlations. dt = {dt} min') # STORE THE CORRELATIONS correlations = { 'original': correlations_orig, 'aligned': correlations_aligned } metrics_pkl_file_path = f'data/interim/alignment/meta/correlations/mouse_{index[0]}_session{index[1]}_v{index[7]}.pkl' with open(metrics_pkl_file_path, 'wb') as f: pickle.dump(correlations, f) alignment_output['meta']['correlations'] = metrics_pkl_file_path for idx, row in df.iterrows(): df.loc[idx, 'alignment_output'] = str(alignment_output) return df
def run_equalizer(states_df, parameters): ''' This function is meant to help with differences in different trials and session, to equalize general brightness or reduce photobleaching. It corrects the video and saves them in the corrected version. params df: pd.DataFrame -> A dataframe containing the analysis states you want to have aligned. params parameters: dict -> contains parameters concerning equalization returns df: pd.DataFrame -> A dataframe containing the aligned analysis states. ''' # Sort the dataframe correctly df = states_df.sort_values(by=paths.multi_index_structure) # Determine the output path output_mmap_file_path = f'data/interim/equalizer/main/' mouse, session, init_trial, *r = df.iloc[0].name histogram_name = f'mouse_{mouse}_session_{session}_init_trial_{init_trial}' output_steps_file_path = f'data/interim/equalizer/meta/figures/histograms/' + histogram_name try: df.reset_index()[['trial', 'is_rest']].set_index(['trial', 'is_rest'], verify_integrity=True) except ValueError: logging.error( 'You passed multiple of the same trial in the dataframe df') return df output = { 'meta': { 'analysis': { 'analyst': os.environ['ANALYST'], 'date': datetime.datetime.today().strftime("%m-%d-%Y"), 'time': datetime.datetime.today().strftime("%H:%M:%S") }, 'duration': {} } } # Get necessary parameters decoding_output_list = [] input_tif_file_list = [] trial_index_list = [] for idx, row in df.iterrows(): decoding_output = eval(row.loc['decoding_output']) decoding_output_list.append(decoding_output) input_tif_file_list.append(decoding_output['main']) trial_index_list.append(db.get_trial_name(idx[2], idx[3])) colors = [] for i in range(len(df)): colors.append('#%06X' % randint(0, 0xFFFFFF)) m_list = [] m_reshape_list = [] legend = [] min_list = [] max_list = [] h_step = parameters['histogram_step'] fig, ax = plt.subplots(1, 2) for i in range(len(input_tif_file_list)): im = io.imread(input_tif_file_list[i]) #m_list.append(im) reshape_m = np.reshape(im, (im.shape[0] * im.shape[1] * im.shape[2])) m_reshape_list.append(reshape_m) legend.append('trial = ' + f'{df.iloc[i].name[2]}') total_min = 200 total_max = 1500 cdf_list = [] for i in range(len(input_tif_file_list)): hist, bins = np.histogram( m_reshape_list[i], bins=np.linspace(total_min, total_max, (total_max - total_min) / h_step), density=True) cdf = np.cumsum(hist) * h_step cdf_list.append(cdf) ax[0].plot(bins[0:-1], hist, color=colors[i]) ax[1].plot(bins[0:-1], cdf, color=colors[i]) ax[0].set_xlabel('Pixel Intensity') ax[1].set_xlabel('Pixel Intensity') ax[0].set_ylabel('Density') ax[1].set_ylabel('CDF') ax[0].legend((legend)) fig.savefig(output_steps_file_path + '.png') # Concatenate them using the concat function m_concat = cm.concatenate(m_list, axis=0) data_dir = 'data/interim/alignment/main' file_name = db.create_file_name(step_index, index) fname = m_concat.save(data_dir + '/' + file_name + '_pw_rig' + '.mmap', order='C') cdf_m = np.ma.masked_equal(cdf, 0) cdf_m = (cdf_m - cdf_m.min()) * 255 / (cdf_m.max() - cdf_m.min()) cdf = np.ma.filled(cdf_m, 0).astype('uint8') #meta_pkl_dict['pw_rigid']['cropping_points'] = [x_, _x, y_, _y] #output['meta']['cropping_points'] = [x_, _x, y_, _y] # Save the movie #fname_tot_els = m_els.save(data_dir + 'main/' + file_name + '_els' + '.mmap', order='C') #logging.info(f'{index} Cropped and saved rigid movie as {fname_tot_els}') # MOTION CORRECTING EACH INDIVIDUAL MOVIE WITH RESPECT TO A TEMPLATE MADE OF THE FIRST MOVIE logging.info( f'{alignment_index} Performing motion correction on all movies with respect to a template made of \ the first movie.') t0 = datetime.datetime.today() # Create a template of the first movie template_index = trial_index_list.index( parameters['make_template_from_trial']) m0 = cm.load(input_mmap_file_list[template_index]) [x1, x2, y1, y2] = motion_correction_output_list[template_index]['meta'][ 'cropping_points'] m0 = m0.crop(new_x1 - x1, new_x2 - x2, new_y1 - y1, new_y2 - y2, 0, 0) m0_filt = cm.movie( np.array([ high_pass_filter_space(m_, parameters['gSig_filt']) for m_ in m0 ])) template0 = cm.motion_correction.bin_median( m0_filt.motion_correct( 5, 5, template=None)[0]) # may be improved in the future # Setting the parameters opts = params.CNMFParams(params_dict=parameters) # Create a motion correction object mc = MotionCorrect(fname, dview=dview, **opts.get_group('motion')) # Perform non-rigid motion correction mc.motion_correct(template=template0, save_movie=True) # Cropping borders x_ = math.ceil( abs(np.array(mc.shifts_rig)[:, 1].max() ) if np.array(mc.shifts_rig)[:, 1].max() > 0 else 0) _x = math.ceil( abs(np.array(mc.shifts_rig)[:, 1].min() ) if np.array(mc.shifts_rig)[:, 1].min() < 0 else 0) y_ = math.ceil( abs(np.array(mc.shifts_rig)[:, 0].max() ) if np.array(mc.shifts_rig)[:, 0].max() > 0 else 0) _y = math.ceil( abs(np.array(mc.shifts_rig)[:, 0].min() ) if np.array(mc.shifts_rig)[:, 0].min() < 0 else 0) dt = int( (datetime.datetime.today() - t0).seconds / 60) # timedelta in minutes output['meta']['duration']['motion_correction'] = dt logging.info( f'{alignment_index} Performed motion correction. dt = {dt} min.') # Create a timeline and store it timeline = [[trial_index_list[0], 0]] for i in range(1, len(m_list)): m = m_list[i] timeline.append([trial_index_list[i], timeline[i - 1][1] + m.shape[0]]) # timeline_pkl_file_path = f'data/interim/alignment/meta/timeline/{file_name}.pkl' # with open(timeline_pkl_file_path,'wb') as f: # pickle.dump(timeline,f) # output['meta']['timeline'] = timeline_pkl_file_path output['meta']['timeline'] = timeline # Save the concatenated movie output_mmap_file_path_tot = m_concat.save(output_mmap_file_path, order='C') output['main'] = output_mmap_file_path_tot # # Delete the motion corrected movies # for fname in mc.fname_tot_rig: # os.remove(fname) dt = int( (datetime.datetime.today() - t0).seconds / 60) # timedelta in minutes output['meta']['duration']['concatenation'] = dt logging.info(f'{alignment_index} Performed concatenation. dt = {dt} min.') for idx, row in df.iterrows(): df.loc[idx, 'alignment_output'] = str(output) df.loc[idx, 'alignment_parameters'] = str(parameters) return df