def __init__(self): # paths self.front_video_path = r"\front_video.avi" self.front_counter_path = r"\front_counter.csv" self.top_video_path = r"\top_video.avi" self.adc_path = r"\adc.bin" self.sync_path = r"\sync.bin" self.analysis_folder = "Analysis" self.analysis_file_name = r"\session.hdf5" # session.hdf5 structure self.fronttime_key = 'video/front/time' self.fronttrials_key = 'video/front/trials' self.toptime_key = 'video/top/time' self.paw_events_key = 'task/events/paws' self.good_trials_key = 'task/events/trials' self.trajectories_key = 'task/trajectories' # colums of trial_start_stop_info in session.hdf5 self.trials_info_start_frame = "start frame" self.trials_info_stop_frame = "stop frame" self.trials_info_start_frame_time = "start frame time" self.trials_info_end_frame_time = "end frame time" self.trials_info_trial_duration = "trial duration" # colums of paw_events in session.hdf5 self.blpaw = 'back left paw' self.brpaw = 'back right paw' self.flpaw = 'front left paw' self.frpaw = 'front right paw' self.trial_paw_event = 'trial of event' self.time_paw_event = 'time of event' # columns of trajectories in session.hdf5 self.name_traj_point = 'name of trajectory point' self.trial_traj_point = 'trial of trajectory point' self.frame_traj_point = 'frame of trajectory point' self.time_traj_point = 'time of trajectory point' self.x_traj_point = 'X of trajectory point' self.y_traj_point = 'Y of trajectory point' # instance variables app = QtWidgets.QApplication(sys.argv) window = QtWidgets.QMainWindow() self.ui = Ui_RatShuttlingPawEventsGenerator() self.ui.setupUi(window) self.rec_freq = 8000 self.ss_freq = 100 self.session = "" self.front_video = "" self.top_video = "" self.corrected_frame_numbers = [] self.cam_shutter_closing_samples = [] self.analysis_exists = False self.data_loaded = False self.t = RunVideoThread(self.ui) self.trajectory_lines = [] self.annotation = mpt.Annotation("", xy=(-1, -1)) self.connect_slots() window.show() app.exec_()
def __init__(self): # paths self.front_video_path = r"\front_video.avi" self.front_counter_path = r"\front_counter.csv" self.top_video_path = r"\top_video.avi" self.adc_path = r"\adc.bin" self.sync_path = r"\sync.bin" self.analysis_folder = "Analysis" self.analysis_file_name = r"\session.hdf5" # session.hdf5 structure self.fronttime_key = 'video/front/time' self.fronttrials_key = 'video/front/trials' self.toptime_key = 'video/top/time' self.paw_events_key = 'task/events/paws' self.good_trials_key = 'task/events/trials' self.trajectories_key = 'task/trajectories' # colums of trial_start_stop_info in session.hdf5 self.trials_info_start_frame = "start frame" self.trials_info_stop_frame = "stop frame" self.trials_info_start_frame_time = "start frame time" self.trials_info_end_frame_time = "end frame time" self.trials_info_trial_duration = "trial duration" # colums of paw_events in session.hdf5 self.blpaw = 'back left paw' self.brpaw = 'back right paw' self.flpaw = 'front left paw' self.frpaw = 'front right paw' self.trial_paw_event = 'trial of event' self.time_paw_event = 'time of event' # columns of trajectories in session.hdf5 self.name_traj_point = 'name of trajectory point' self.trial_traj_point = 'trial of trajectory point' self.frame_traj_point = 'frame of trajectory point' self.time_traj_point = 'time of trajectory point' self.x_traj_point = 'X of trajectory point' self.y_traj_point = 'Y of trajectory point' # instance variables app = QtWidgets.QApplication(sys.argv) window = QtWidgets.QMainWindow() self.ui = Ui_RatShuttlingPawEventsGenerator() self.ui.setupUi(window) self.rec_freq = 8000 self.ss_freq = 100 self.session = "" self.front_video = "" self.top_video = "" self.corrected_frame_numbers = [] self.cam_shutter_closing_samples = [] self.analysis_exists = False self.data_loaded = False self.t = RunVideoThread(self.ui) self.trajectory_lines = [] self.annotation = mpt.Annotation("", xy=(-1,-1)) self.connect_slots() window.show() app.exec_()
class RatShuttlingPawEventsGenerator: def __init__(self): # paths self.front_video_path = r"\front_video.avi" self.front_counter_path = r"\front_counter.csv" self.top_video_path = r"\top_video.avi" self.adc_path = r"\adc.bin" self.sync_path = r"\sync.bin" self.analysis_folder = "Analysis" self.analysis_file_name = r"\session.hdf5" # session.hdf5 structure self.fronttime_key = 'video/front/time' self.fronttrials_key = 'video/front/trials' self.toptime_key = 'video/top/time' self.paw_events_key = 'task/events/paws' self.good_trials_key = 'task/events/trials' self.trajectories_key = 'task/trajectories' # colums of trial_start_stop_info in session.hdf5 self.trials_info_start_frame = "start frame" self.trials_info_stop_frame = "stop frame" self.trials_info_start_frame_time = "start frame time" self.trials_info_end_frame_time = "end frame time" self.trials_info_trial_duration = "trial duration" # colums of paw_events in session.hdf5 self.blpaw = 'back left paw' self.brpaw = 'back right paw' self.flpaw = 'front left paw' self.frpaw = 'front right paw' self.trial_paw_event = 'trial of event' self.time_paw_event = 'time of event' # columns of trajectories in session.hdf5 self.name_traj_point = 'name of trajectory point' self.trial_traj_point = 'trial of trajectory point' self.frame_traj_point = 'frame of trajectory point' self.time_traj_point = 'time of trajectory point' self.x_traj_point = 'X of trajectory point' self.y_traj_point = 'Y of trajectory point' # instance variables app = QtWidgets.QApplication(sys.argv) window = QtWidgets.QMainWindow() self.ui = Ui_RatShuttlingPawEventsGenerator() self.ui.setupUi(window) self.rec_freq = 8000 self.ss_freq = 100 self.session = "" self.front_video = "" self.top_video = "" self.corrected_frame_numbers = [] self.cam_shutter_closing_samples = [] self.analysis_exists = False self.data_loaded = False self.t = RunVideoThread(self.ui) self.trajectory_lines = [] self.annotation = mpt.Annotation("", xy=(-1, -1)) self.connect_slots() window.show() app.exec_() # Slot that deals with the initialization of the GUI once data are loaded @QtCore.pyqtSlot('QString') def on_pB_select_data_clicked(self): self.ui.label_data_loaded.setText("Loading\nData") self.session = QtWidgets.QFileDialog.getExistingDirectory( parent=None, caption="Select Data Directory") self.ui.cB_trial_start_frames.clear() if os.path.isfile(self.session + self.front_video_path): self.front_video = cv2.VideoCapture(self.session + self.front_video_path) self.adc = tlf.load_raw_data(self.session + self.adc_path, numchannels=8, dtype=np.uint16).dataMatrix self.adc_ss = tlf.subsample_basis_data(self.adc, self.rec_freq, self.ss_freq, 'fir', 29) front_counter = tlf.load_colum_from_csv( self.session + self.front_counter_path, 0) self.corrected_frame_numbers = front_counter - front_counter[0] sync = np.squeeze( tlf.load_raw_data(self.session + self.sync_path, numchannels=1, dtype=np.uint8).dataMatrix) sync_diff = np.diff(sync.astype('int8')) self.cam_shutter_closing_samples = np.squeeze( (sync_diff < -0.9).nonzero()) self.ui.label_data_loaded.setText("Data\nLoaded") self.data_loaded = True analysis_path = os.path.join(self.session, self.analysis_folder) if os.path.exists(analysis_path ): # Add the list of good trials to the combobox self.analysis_exists = True session_hdf5 = pd.HDFStore(analysis_path + self.analysis_file_name) trials_start_stop_info = session_hdf5[self.fronttrials_key] start_frames_strlist = np.char.mod( '%d', trials_start_stop_info[ self.trials_info_start_frame].tolist()) self.ui.cB_trial_start_frames.addItems(start_frames_strlist) if self.paw_events_key in session_hdf5: # Add the lists of paw touch events to their comboboxes paw_events = session_hdf5[self.paw_events_key] """:type : pd.DataFrame""" self.ui.cB_br_paw_frames.addItems([ str(x) for x in paw_events[ paw_events[self.brpaw] != -1][self.brpaw] ]) self.ui.cB_bl_paw_frames.addItems([ str(x) for x in paw_events[ paw_events[self.blpaw] != -1][self.blpaw] ]) self.ui.cB_fr_paw_frames.addItems([ str(x) for x in paw_events[ paw_events[self.frpaw] != -1][self.frpaw] ]) self.ui.cB_fl_paw_frames.addItems([ str(x) for x in paw_events[ paw_events[self.flpaw] != -1][self.flpaw] ]) if self.good_trials_key in session_hdf5: # Add the list of good_tirls to its combobox good_trials = session_hdf5[self.good_trials_key] """:type : pd.Series""" self.ui.cB_selected_trials.addItems( [str(x) for x in good_trials]) if self.trajectories_key in session_hdf5: trajectories = session_hdf5[self.trajectories_key] """:type : pd.DataFrame""" self.ui.cB_trajectory_name.addItems( list(set(trajectories[self.name_traj_point].tolist()))) session_hdf5.close() else: self.ui.label_data_loaded.setText("No Data\nLoaded") self.data_loaded = False @QtCore.pyqtSlot(int) def on_sBox_FrameNum_valueChanged(self, i): if self.data_loaded: self.front_video.set(cv2.CAP_PROP_POS_FRAMES, i) r, f = self.front_video.read() if not r: self.ui.sBox_FrameNum.setValue(0) self.front_video.set(cv2.CAP_PROP_POS_FRAMES, i) r, f = self.front_video.read() resize_factor = self.ui.dSB_frame_resize.value() half_f = cv2.resize(f, dsize=(0, 0), fx=resize_factor, fy=resize_factor, interpolation=cv2.INTER_AREA) self.ui.mplg_frames._dataY = half_f self.ui.mplg_frames.all_sp_axes[0].clear() self.ui.mplg_frames.all_sp_axes[0].imshow( self.ui.mplg_frames._dataY, cmap=cm.gray) self.ui.mplg_frames.all_sp_axes[0].axis('image') self.trajectory_lines = [] self.ui.mplg_frames.canvas.draw() self.draw_piezos(i) self.ui.label_trial_number_int.setText(str(self.get_trial_num(i))) def get_trial_num(self, frame_num): if self.analysis_exists: trials_start_frames = self.get_all_combobox_values( self.ui.cB_trial_start_frames) trial_num_list = [ i for i, x in enumerate(trials_start_frames[:-1]) if int(x) <= frame_num and int(trials_start_frames[i + 1]) > frame_num ] if trial_num_list: trial_num = trial_num_list[0] else: trial_num = np.size(trials_start_frames) return trial_num else: return -1 def draw_piezos(self, frame_num): sync_pulse_index = self.corrected_frame_numbers[frame_num] sample_of_frame = self.cam_shutter_closing_samples[sync_pulse_index] ss_sample_of_frame = int(sample_of_frame * float(self.ss_freq / self.rec_freq)) piezo_samples_to_plot = self.ui.hSB_piezo_samples_to_plot.value() piezo_time = np.arange(-piezo_samples_to_plot / 2, piezo_samples_to_plot / 2) for k in np.arange(0, 8): data = self.adc_ss[k, ss_sample_of_frame - (piezo_samples_to_plot / 2):ss_sample_of_frame + (piezo_samples_to_plot / 2)] self.ui.mplg_piezos.all_sp_axes[k].clear() self.ui.mplg_piezos.all_sp_axes[k].plot(piezo_time, data) self.ui.mplg_piezos.canvas.draw() @QtCore.pyqtSlot(int) def on_hSB_piezo_samples_to_plot_valueChanged(self, i): if self.data_loaded: frame = self.ui.sBox_FrameNum.value() self.draw_piezos(frame) @QtCore.pyqtSlot(int) def on_sBox_frames_step_valueChanged(self, i): self.ui.sBox_FrameNum.setSingleStep(i) @QtCore.pyqtSlot(bool) def on_pB_Run_toggled(self, state): if self.data_loaded: if state: self.t.run_video = True if not self.t.isRunning(): self.t.start() else: self.t.run_video = False # Slot to resize the image of the video @QtCore.pyqtSlot(int) def on_dSB_frame_resize_valueChanged(self): if self.data_loaded: self.front_video.set(cv2.CAP_PROP_POS_FRAMES, 1) r, f = self.front_video.read() resize_factor = self.ui.dSB_frame_resize.value() half_f = cv2.resize(f, dsize=(0, 0), fx=resize_factor, fy=resize_factor, interpolation=cv2.INTER_AREA) image_size = np.max(np.shape(half_f)) if image_size >= 1000: self.ui.sB_updates_sec.setMaximum(1) elif image_size < 1000 and image_size >= 500: self.ui.sB_updates_sec.setMaximum(2) elif image_size < 500 and image_size >= 250: self.ui.sB_updates_sec.setMaximum(3) else: self.ui.sB_updates_sec.setMaximum(5) # Slot to move the video to the current frame shown on the trials start frames combobox @QtCore.pyqtSlot(bool) def on_pB_goto_trial_frame_clicked(self): if self.data_loaded: frame = int(self.ui.cB_trial_start_frames.currentText()) if not np.isnan(frame): self.ui.sBox_FrameNum.setValue(frame) # Slots to add and remove the good trials to session.hdf5 @QtCore.pyqtSlot(bool) def on_pB_add_trial_clicked(self): if self.data_loaded: trial = int(self.ui.label_trial_number_int.text()) all_trials = [ int(x) for x in self.get_all_combobox_values( self.ui.cB_selected_trials) ] if trial != -1 and trial not in all_trials: self.ui.cB_selected_trials.addItem(str(trial)) if self.analysis_exists: analysis_path = os.path.join(self.session, self.analysis_folder) session_hdf5 = pd.HDFStore(analysis_path + self.analysis_file_name) if self.good_trials_key in session_hdf5: good_trials = session_hdf5[self.good_trials_key] """:type : pd.Series""" good_trials.set_value( max(good_trials.keys()) + 1, trial) else: good_trials = pd.Series(trial) good_trials.to_hdf(analysis_path + self.analysis_file_name, self.good_trials_key) session_hdf5.close() @QtCore.pyqtSlot(bool) def on_pB_remove_trial_clicked(self): if self.data_loaded and self.ok_dialog(): index = self.ui.cB_selected_trials.currentIndex() trial = int(self.ui.cB_selected_trials.currentText()) self.ui.cB_selected_trials.removeItem(index) if self.analysis_exists: analysis_path = os.path.join(self.session, self.analysis_folder) session_hdf5 = pd.HDFStore(analysis_path + self.analysis_file_name) if self.good_trials_key in session_hdf5: good_trials = session_hdf5[self.good_trials_key] """:type : pd.Series""" good_trials = good_trials[good_trials != trial] good_trials.reset_index(drop=True) good_trials.to_hdf(analysis_path + self.analysis_file_name, self.good_trials_key) session_hdf5.close() # Slots for adding and removing paw touching events to session.hdf5 @QtCore.pyqtSlot(bool) def on_pB_fl_paw_add_frame_clicked(self): if self.data_loaded and self.analysis_exists: frame = self.ui.sBox_FrameNum.value() all_frames = self.get_all_combobox_values(self.ui.cB_fl_paw_frames) if frame not in all_frames: self.ui.cB_fl_paw_frames.addItem(str(frame)) self.ui.cB_fl_paw_frames.setCurrentIndex( self.ui.cB_fl_paw_frames.count() - 1) self.update_paw_events_dataframe(self.flpaw) @QtCore.pyqtSlot(bool) def on_pB_fl_paw_remove_frame_clicked(self): if self.data_loaded and self.analysis_exists and self.ok_dialog(): self.ui.cB_fl_paw_frames.removeItem( self.ui.cB_fl_paw_frames.currentIndex()) analysis_path = os.path.join(self.session, self.analysis_folder) session_hdf5 = pd.HDFStore(analysis_path + self.analysis_file_name) if self.paw_events_key in session_hdf5: paw_events = session_hdf5[self.paw_events_key] """:type : pd.DataFrame""" paw_events = paw_events[paw_events[self.flpaw] != int( self.ui.cB_fl_paw_frames.currentText())] paw_events.to_hdf(analysis_path + self.analysis_file_name, self.paw_events_key) session_hdf5.close() @QtCore.pyqtSlot(bool) def on_pB_fr_paw_add_frame_clicked(self): if self.data_loaded and self.analysis_exists: frame = self.ui.sBox_FrameNum.value() all_frames = self.get_all_combobox_values(self.ui.cB_fr_paw_frames) if frame not in all_frames: self.ui.cB_fr_paw_frames.addItem(str(frame)) self.ui.cB_fr_paw_frames.setCurrentIndex( self.ui.cB_fr_paw_frames.count() - 1) self.update_paw_events_dataframe(self.frpaw) @QtCore.pyqtSlot(bool) def on_pB_fr_paw_remove_frame_clicked(self): if self.data_loaded and self.analysis_exists and self.ok_dialog(): self.ui.cB_fr_paw_frames.removeItem( self.ui.cB_fr_paw_frames.currentIndex()) analysis_path = os.path.join(self.session, self.analysis_folder) session_hdf5 = pd.HDFStore(analysis_path + self.analysis_file_name) if self.paw_events_key in session_hdf5: paw_events = session_hdf5[self.paw_events_key] """:type : pd.DataFrame""" paw_events = paw_events[paw_events[self.frpaw] != int( self.ui.cB_fr_paw_frames.currentText())] paw_events.to_hdf(analysis_path + self.analysis_file_name, self.paw_events_key) session_hdf5.close() @QtCore.pyqtSlot(bool) def on_pB_bl_paw_add_frame_clicked(self): if self.data_loaded and self.analysis_exists: frame = self.ui.sBox_FrameNum.value() all_frames = self.get_all_combobox_values(self.ui.cB_bl_paw_frames) if frame not in all_frames: self.ui.cB_bl_paw_frames.addItem(str(frame)) self.ui.cB_bl_paw_frames.setCurrentIndex( self.ui.cB_bl_paw_frames.count() - 1) self.update_paw_events_dataframe(self.blpaw) @QtCore.pyqtSlot(bool) def on_pB_bl_paw_remove_frame_clicked(self): if self.data_loaded and self.analysis_exists and self.ok_dialog(): self.ui.cB_bl_paw_frames.removeItem( self.ui.cB_bl_paw_frames.currentIndex()) analysis_path = os.path.join(self.session, self.analysis_folder) session_hdf5 = pd.HDFStore(analysis_path + self.analysis_file_name) if self.paw_events_key in session_hdf5: paw_events = self.session_hdf5[self.paw_events_key] """:type : pd.DataFrame""" paw_events = paw_events[paw_events[self.blpaw] != int( self.ui.cB_bl_paw_frames.currentText())] paw_events.to_hdf(analysis_path + self.analysis_file_name, self.paw_events_key) session_hdf5.close() @QtCore.pyqtSlot(bool) def on_pB_br_paw_add_frame_clicked(self): if self.data_loaded and self.analysis_exists: frame = self.ui.sBox_FrameNum.value() all_frames = self.get_all_combobox_values(self.ui.cB_br_paw_frames) if frame not in all_frames: self.ui.cB_br_paw_frames.addItem(str(frame)) self.ui.cB_br_paw_frames.setCurrentIndex( self.ui.cB_br_paw_frames.count() - 1) self.update_paw_events_dataframe(self.brpaw) @QtCore.pyqtSlot(bool) def on_pB_br_paw_remove_frame_clicked(self): if self.data_loaded and self.analysis_exists and self.ok_dialog(): self.ui.cB_br_paw_frames.removeItem( self.ui.cB_br_paw_frames.currentIndex()) analysis_path = os.path.join(self.session, self.analysis_folder) session_hdf5 = pd.HDFStore(analysis_path + self.analysis_file_name) if self.paw_events_key in session_hdf5: paw_events = session_hdf5[self.paw_events_key] """:type : pd.DataFrame""" paw_events = paw_events[paw_events[self.brpaw] != int( self.ui.cB_br_paw_frames.currentText())] paw_events.to_hdf(analysis_path + self.analysis_file_name, self.paw_events_key) session_hdf5.close() def update_paw_events_dataframe(self, paw): frame_num = self.ui.sBox_FrameNum.value() analysis_path = os.path.join(self.session, self.analysis_folder) session_hdf5 = pd.HDFStore(analysis_path + self.analysis_file_name) time_of_frame = session_hdf5[self.fronttime_key].iloc[frame_num] trial_num = int(self.ui.label_trial_number_int.text()) self.ui.label_trial_number_int.setText(str(trial_num)) if self.paw_events_key in session_hdf5: paw_events = session_hdf5[self.paw_events_key] """:type : pd.DataFrame""" else: paw_events = pd.DataFrame(columns=[ self.trial_paw_event, self.time_paw_event, self.blpaw, self.brpaw, self.flpaw, self.frpaw ]) def bl_paw(): return np.array([[trial_num, time_of_frame, frame_num, -1, -1, -1]]) def br_paw(): return np.array([[trial_num, time_of_frame, -1, frame_num, -1, -1]]) def fl_paw(): return np.array([[trial_num, time_of_frame, -1, -1, frame_num, -1]]) def fr_paw(): return np.array([[trial_num, time_of_frame, -1, -1, -1, frame_num]]) paw_switch = { self.blpaw: bl_paw, self.brpaw: br_paw, self.flpaw: fl_paw, self.frpaw: fr_paw } df_to_append = pd.DataFrame(paw_switch[paw]().tolist(), columns=[ self.trial_paw_event, self.time_paw_event, self.blpaw, self.brpaw, self.flpaw, self.frpaw ]) df_to_append[[self.trial_paw_event, self.blpaw, self.brpaw, self.flpaw, self.frpaw]] = \ df_to_append[[self.trial_paw_event, self.blpaw, self.brpaw, self.flpaw, self.frpaw]].astype('int') paw_events = paw_events.append(df_to_append, ignore_index=True) paw_events.to_hdf(analysis_path + self.analysis_file_name, self.paw_events_key) session_hdf5.close() def get_all_combobox_values(self, combobox): return [combobox.itemText(i) for i in np.arange(combobox.count())] def ok_dialog(self): mb = QtWidgets.QMessageBox() mb.setText("Do you want to delete this event?") mb.setStandardButtons(QtWidgets.QMessageBox.Ok | QtWidgets.QMessageBox.Cancel) answer = mb.exec() if answer == QtWidgets.QMessageBox.Ok: return True else: return False # Slots for mouse events (right, middle, left clicks and movement @QtCore.pyqtSlot(object) def on_mplg_frames_buttonpressed(self, event): button = event.button xdata = event.xdata ydata = event.ydata if self.data_loaded and self.analysis_exists: traj_name = self.ui.cB_trajectory_name.currentText( ) # Get name of current trajectory if not traj_name: # Notify user if there is no current trajectory selected mb = QtWidgets.QMessageBox() mb.setText("You need to set a name for the trajectory.") mb.setStandardButtons(QtWidgets.QMessageBox.Ok) mb.exec() return analysis_path = os.path.join(self.session, self.analysis_folder) session_hdf5 = pd.HDFStore(analysis_path + self.analysis_file_name, mode='a', complevel=9, complib='zlib') trial_num = int(self.ui.label_trial_number_int.text()) frame_num = int(self.ui.sBox_FrameNum.text()) time_of_frame = session_hdf5[self.fronttime_key].iloc[frame_num] image_size_factor = self.ui.dSB_frame_resize.value() if button == 1: # On LMB add a point to the current trial's current trajectory df_to_append = pd.DataFrame( [[ traj_name, trial_num, frame_num, time_of_frame, int(xdata / image_size_factor), int(ydata / image_size_factor) ]], columns=[ self.name_traj_point, self.trial_traj_point, self.frame_traj_point, self.time_traj_point, self.x_traj_point, self.y_traj_point ]) if self.trajectories_key in session_hdf5: trajectories = session_hdf5[self.trajectories_key] """:type : pd.DataFrame""" trajectories = trajectories.append(df_to_append, ignore_index=True) else: trajectories = df_to_append trajectories[self.name_traj_point] = trajectories[ self.name_traj_point].astype('str') trajectories[[ self.trial_traj_point, self.frame_traj_point, self.x_traj_point, self.y_traj_point ]] = trajectories[[ self.trial_traj_point, self.frame_traj_point, self.x_traj_point, self.y_traj_point ]].astype('int') session_hdf5[self.trajectories_key] = trajectories self.plot_trajectory(trajectories, [traj_name], frame_num, trial_num) if button == 3 and self.trajectories_key in session_hdf5: # On RMB just draws the current trial's current trajectory trajectories = session_hdf5[self.trajectories_key] """:type : pd.DataFrame""" trials = trajectories[self.trial_traj_point] current_trial = int(self.ui.label_trial_number_int.text()) if trials[ trials == current_trial].size > 0: # Show only if there is a trajectory for this trial self.plot_trajectory(trajectories, [traj_name], frame_num, trial_num) if button == 2 and self.trajectories_key in session_hdf5: # On MMB deletes the clicked point of the current trial's current trajectory trajectories = session_hdf5[self.trajectories_key] """:type : pd.DataFrame""" x_data = trajectories[trajectories[ self.name_traj_point] == traj_name][trajectories[ self.trial_traj_point] == trial_num][self.x_traj_point] y_data = trajectories[trajectories[ self.name_traj_point] == traj_name][trajectories[ self.trial_traj_point] == trial_num][self.y_traj_point] xdiff = np.array(x_data - xdata / image_size_factor) ydiff = np.array(y_data - ydata / image_size_factor) max_diff = 20 * image_size_factor x_idx = np.where((xdiff > -max_diff) * (xdiff < max_diff)) y_idx = np.where((ydiff > -max_diff) * (ydiff < max_diff)) idx_to_remove = np.intersect1d(x_idx, y_idx) if x_data[idx_to_remove].size > 0 and y_data[ idx_to_remove].size > 0: for i in idx_to_remove: x_to_remove = x_data.iloc[i].tolist() y_to_remove = y_data.iloc[i].tolist() traj_indices_to_remove = trajectories[trajectories[ self.name_traj_point] == traj_name][trajectories[ self.trial_traj_point] == trial_num][ x_data == x_to_remove][y_data == y_to_remove].index trajectories = trajectories.drop( traj_indices_to_remove) trajectories = trajectories.reset_index(drop=True) trajectories[self.name_traj_point] = trajectories[ self.name_traj_point].astype('str') trajectories[[ self.trial_traj_point, self.frame_traj_point, self.x_traj_point, self.y_traj_point ]] = trajectories[[ self.trial_traj_point, self.frame_traj_point, self.x_traj_point, self.y_traj_point ]].astype('int') session_hdf5[self.trajectories_key] = trajectories self.plot_trajectory(trajectories, traj_name, frame_num, trial_num) session_hdf5.close() def plot_trajectory(self, trajectories, traj_names, frame_num, trial_num): self.on_sBox_FrameNum_valueChanged(frame_num) image_size_factor = self.ui.dSB_frame_resize.value() axes = self.ui.mplg_frames.all_sp_axes[0] """:type : matplotlib.axes.Axes""" trajectories = trajectories.sort(self.frame_traj_point, ascending=True) for traj_name in traj_names: x_data = trajectories[trajectories[ self.name_traj_point] == traj_name][trajectories[ self.trial_traj_point] == trial_num][ self.x_traj_point] * image_size_factor y_data = trajectories[trajectories[ self.name_traj_point] == traj_name][trajectories[ self.trial_traj_point] == trial_num][ self.y_traj_point] * image_size_factor index_of_trajectory = self.ui.cB_trajectory_name.currentIndex() index_to_color = {0: 'blue', 1: 'green', 2: 'yellow', 3: 'red'} color = index_to_color[index_of_trajectory % 4] line = axes.plot(x_data, y_data, color=color, marker='o', markersize=5) self.trajectory_lines.append(line[0]) self.ui.mplg_frames.canvas.draw() @QtCore.pyqtSlot(object) def on_mplg_frames_keypressed(self, event): key = event.key if key == 'q': self.ui.sBox_FrameNum.setValue(self.ui.sBox_FrameNum.value() - self.ui.sBox_frames_step.value()) if key == 'w': self.ui.sBox_FrameNum.setValue(self.ui.sBox_FrameNum.value() + self.ui.sBox_frames_step.value()) @QtCore.pyqtSlot(object) def on_mplg_frames_mousemove(self, event): if self.trajectory_lines: for line in self.trajectory_lines: line.set_pickradius(5) if line.contains(event)[0]: axes = self.ui.mplg_frames.all_sp_axes[0] """:type : matplotlib.axes.Axes""" xy = line.get_xydata() point_ind = line.contains(event)[1]['ind'][0] traj_name = self.ui.cB_trajectory_name.currentText() trial_num = int(self.ui.label_trial_number_int.text()) analysis_path = os.path.join(self.session, self.analysis_folder) session_hdf5 = pd.HDFStore(analysis_path + self.analysis_file_name, mode='r') trajectories = session_hdf5[self.trajectories_key] """:type : pd.DataFrame""" session_hdf5.close() trajectories = trajectories.sort(self.frame_traj_point, ascending=True) frame = trajectories[trajectories[ self.name_traj_point] == traj_name][trajectories[ self.trial_traj_point] == trial_num][ self.frame_traj_point].tolist()[point_ind] self.annotation = mpt.Annotation( str(frame), xy=tuple(xy[point_ind]), xytext=(xy[point_ind][0], xy[point_ind][1] - 40), xycoords='data', textcoords='data', horizontalalignment="left", arrowprops=dict(arrowstyle="simple", connectionstyle="arc3,rad=-0.2"), bbox=dict(boxstyle="round", facecolor="w", edgecolor="0.5", alpha=0.9)) axes.add_artist(self.annotation) self.ui.mplg_frames.canvas.draw() def connect_slots(self): self.ui.pB_selecet_data.clicked.connect(self.on_pB_select_data_clicked) self.ui.sBox_FrameNum.valueChanged.connect( self.on_sBox_FrameNum_valueChanged) self.ui.hSB_piezo_samples_to_plot.valueChanged.connect( self.on_hSB_piezo_samples_to_plot_valueChanged) self.ui.sBox_frames_step.valueChanged.connect( self.on_sBox_frames_step_valueChanged) self.ui.pB_Run.toggled.connect(self.on_pB_Run_toggled) self.ui.dSB_frame_resize.valueChanged.connect( self.on_dSB_frame_resize_valueChanged) self.ui.pB_goto_trial_frame.clicked.connect( self.on_pB_goto_trial_frame_clicked) self.ui.pB_add_trial.clicked.connect(self.on_pB_add_trial_clicked) self.ui.pB_remove_trial.clicked.connect( self.on_pB_remove_trial_clicked) self.ui.pB_fl_paw_add_frame.clicked.connect( self.on_pB_fl_paw_add_frame_clicked) self.ui.pB_fl_paw_remove_frame.clicked.connect( self.on_pB_fl_paw_remove_frame_clicked) self.ui.pB_fr_paw_add_frame.clicked.connect( self.on_pB_fr_paw_add_frame_clicked) self.ui.pB_fr_paw_remove_frame.clicked.connect( self.on_pB_fr_paw_remove_frame_clicked) self.ui.pB_bl_paw_add_frame.clicked.connect( self.on_pB_bl_paw_add_frame_clicked) self.ui.pB_bl_paw_remove_frame.clicked.connect( self.on_pB_bl_paw_remove_frame_clicked) self.ui.pB_br_paw_add_frame.clicked.connect( self.on_pB_br_paw_add_frame_clicked) self.ui.pB_br_paw_remove_frame.clicked.connect( self.on_pB_br_paw_remove_frame_clicked) self.ui.mplg_frames.button_pressed.connect( self.on_mplg_frames_buttonpressed) self.ui.mplg_frames.key_pressed.connect(self.on_mplg_frames_keypressed) self.ui.mplg_frames.mouse_move.connect(self.on_mplg_frames_mousemove)
class RatShuttlingPawEventsGenerator: def __init__(self): # paths self.front_video_path = r"\front_video.avi" self.front_counter_path = r"\front_counter.csv" self.top_video_path = r"\top_video.avi" self.adc_path = r"\adc.bin" self.sync_path = r"\sync.bin" self.analysis_folder = "Analysis" self.analysis_file_name = r"\session.hdf5" # session.hdf5 structure self.fronttime_key = 'video/front/time' self.fronttrials_key = 'video/front/trials' self.toptime_key = 'video/top/time' self.paw_events_key = 'task/events/paws' self.good_trials_key = 'task/events/trials' self.trajectories_key = 'task/trajectories' # colums of trial_start_stop_info in session.hdf5 self.trials_info_start_frame = "start frame" self.trials_info_stop_frame = "stop frame" self.trials_info_start_frame_time = "start frame time" self.trials_info_end_frame_time = "end frame time" self.trials_info_trial_duration = "trial duration" # colums of paw_events in session.hdf5 self.blpaw = 'back left paw' self.brpaw = 'back right paw' self.flpaw = 'front left paw' self.frpaw = 'front right paw' self.trial_paw_event = 'trial of event' self.time_paw_event = 'time of event' # columns of trajectories in session.hdf5 self.name_traj_point = 'name of trajectory point' self.trial_traj_point = 'trial of trajectory point' self.frame_traj_point = 'frame of trajectory point' self.time_traj_point = 'time of trajectory point' self.x_traj_point = 'X of trajectory point' self.y_traj_point = 'Y of trajectory point' # instance variables app = QtWidgets.QApplication(sys.argv) window = QtWidgets.QMainWindow() self.ui = Ui_RatShuttlingPawEventsGenerator() self.ui.setupUi(window) self.rec_freq = 8000 self.ss_freq = 100 self.session = "" self.front_video = "" self.top_video = "" self.corrected_frame_numbers = [] self.cam_shutter_closing_samples = [] self.analysis_exists = False self.data_loaded = False self.t = RunVideoThread(self.ui) self.trajectory_lines = [] self.annotation = mpt.Annotation("", xy=(-1,-1)) self.connect_slots() window.show() app.exec_() # Slot that deals with the initialization of the GUI once data are loaded @QtCore.pyqtSlot('QString') def on_pB_select_data_clicked(self): self.ui.label_data_loaded.setText("Loading\nData") self.session = QtWidgets.QFileDialog.getExistingDirectory(parent=None, caption="Select Data Directory") self.ui.cB_trial_start_frames.clear() if os.path.isfile(self.session+self.front_video_path): self.front_video = cv2.VideoCapture(self.session + self.front_video_path) self.adc = tlf.load_raw_data(self.session + self.adc_path, numchannels=8, dtype=np.uint16).dataMatrix self.adc_ss = tlf.subsample_basis_data(self.adc, self.rec_freq, self.ss_freq, 'fir', 29) front_counter = tlf.load_colum_from_csv(self.session + self.front_counter_path, 0) self.corrected_frame_numbers = front_counter - front_counter[0] sync = np.squeeze(tlf.load_raw_data(self.session + self.sync_path, numchannels=1, dtype=np.uint8).dataMatrix) sync_diff = np.diff(sync.astype('int8')) self.cam_shutter_closing_samples = np.squeeze((sync_diff < -0.9).nonzero()) self.ui.label_data_loaded.setText("Data\nLoaded") self.data_loaded = True analysis_path = os.path.join(self.session, self.analysis_folder) if os.path.exists(analysis_path): # Add the list of good trials to the combobox self.analysis_exists = True session_hdf5 = pd.HDFStore(analysis_path+self.analysis_file_name) trials_start_stop_info = session_hdf5[self.fronttrials_key] start_frames_strlist =np.char.mod('%d', trials_start_stop_info[self.trials_info_start_frame].tolist()) self.ui.cB_trial_start_frames.addItems(start_frames_strlist) if self.paw_events_key in session_hdf5: # Add the lists of paw touch events to their comboboxes paw_events = session_hdf5[self.paw_events_key]; """:type : pd.DataFrame""" self.ui.cB_br_paw_frames.addItems([str(x) for x in paw_events[paw_events[self.brpaw] != -1][self.brpaw]]) self.ui.cB_bl_paw_frames.addItems([str(x) for x in paw_events[paw_events[self.blpaw] != -1][self.blpaw]]) self.ui.cB_fr_paw_frames.addItems([str(x) for x in paw_events[paw_events[self.frpaw] != -1][self.frpaw]]) self.ui.cB_fl_paw_frames.addItems([str(x) for x in paw_events[paw_events[self.flpaw] != -1][self.flpaw]]) if self.good_trials_key in session_hdf5: # Add the list of good_tirls to its combobox good_trials = session_hdf5[self.good_trials_key]; """:type : pd.Series""" self.ui.cB_selected_trials.addItems([str(x) for x in good_trials]) if self.trajectories_key in session_hdf5: trajectories = session_hdf5[self.trajectories_key]; """:type : pd.DataFrame""" self.ui.cB_trajectory_name.addItems(list(set(trajectories[self.name_traj_point].tolist()))) session_hdf5.close() else: self.ui.label_data_loaded.setText("No Data\nLoaded") self.data_loaded = False @QtCore.pyqtSlot(int) def on_sBox_FrameNum_valueChanged(self,i): if self.data_loaded: self.front_video.set(cv2.CAP_PROP_POS_FRAMES, i) r, f = self.front_video.read() if not r: self.ui.sBox_FrameNum.setValue(0) self.front_video.set(cv2.CAP_PROP_POS_FRAMES, i) r, f = self.front_video.read() resize_factor = self.ui.dSB_frame_resize.value() half_f = cv2.resize(f, dsize=(0, 0), fx=resize_factor, fy=resize_factor, interpolation = cv2.INTER_AREA) self.ui.mplg_frames._dataY = half_f self.ui.mplg_frames.all_sp_axes[0].clear() self.ui.mplg_frames.all_sp_axes[0].imshow(self.ui.mplg_frames._dataY, cmap=cm.gray) self.ui.mplg_frames.all_sp_axes[0].axis('image') self.trajectory_lines = [] self.ui.mplg_frames.canvas.draw() self.draw_piezos(i) self.ui.label_trial_number_int.setText(str(self.get_trial_num(i))) def get_trial_num(self, frame_num): if self.analysis_exists: trials_start_frames = self.get_all_combobox_values(self.ui.cB_trial_start_frames) trial_num_list = [i for i, x in enumerate(trials_start_frames[:-1]) if int(x) <= frame_num and int(trials_start_frames[i+1]) > frame_num] if trial_num_list: trial_num = trial_num_list[0] else: trial_num = np.size(trials_start_frames) return trial_num else: return -1 def draw_piezos(self, frame_num): sync_pulse_index = self.corrected_frame_numbers[frame_num] sample_of_frame = self.cam_shutter_closing_samples[sync_pulse_index] ss_sample_of_frame = int(sample_of_frame*float(self.ss_freq/self.rec_freq)) piezo_samples_to_plot = self.ui.hSB_piezo_samples_to_plot.value() piezo_time = np.arange(-piezo_samples_to_plot/2,piezo_samples_to_plot/2) for k in np.arange(0, 8): data = self.adc_ss[k, ss_sample_of_frame-(piezo_samples_to_plot/2):ss_sample_of_frame+(piezo_samples_to_plot/2)] self.ui.mplg_piezos.all_sp_axes[k].clear() self.ui.mplg_piezos.all_sp_axes[k].plot(piezo_time, data) self.ui.mplg_piezos.canvas.draw() @QtCore.pyqtSlot(int) def on_hSB_piezo_samples_to_plot_valueChanged(self, i): if self.data_loaded: frame = self.ui.sBox_FrameNum.value() self.draw_piezos(frame) @QtCore.pyqtSlot(int) def on_sBox_frames_step_valueChanged(self, i): self.ui.sBox_FrameNum.setSingleStep(i) @QtCore.pyqtSlot(bool) def on_pB_Run_toggled(self, state): if self.data_loaded: if state: self.t.run_video = True if not self.t.isRunning(): self.t.start() else: self.t.run_video = False # Slot to resize the image of the video @QtCore.pyqtSlot(int) def on_dSB_frame_resize_valueChanged(self): if self.data_loaded: self.front_video.set(cv2.CAP_PROP_POS_FRAMES, 1) r, f = self.front_video.read() resize_factor = self.ui.dSB_frame_resize.value() half_f = cv2.resize(f, dsize=(0, 0), fx=resize_factor, fy=resize_factor, interpolation = cv2.INTER_AREA) image_size = np.max(np.shape(half_f)) if image_size >= 1000: self.ui.sB_updates_sec.setMaximum(1) elif image_size<1000 and image_size >= 500: self.ui.sB_updates_sec.setMaximum(2) elif image_size < 500 and image_size >=250: self.ui.sB_updates_sec.setMaximum(3) else: self.ui.sB_updates_sec.setMaximum(5) # Slot to move the video to the current frame shown on the trials start frames combobox @QtCore.pyqtSlot(bool) def on_pB_goto_trial_frame_clicked(self): if self.data_loaded: frame = int(self.ui.cB_trial_start_frames.currentText()) if not np.isnan(frame): self.ui.sBox_FrameNum.setValue(frame) # Slots to add and remove the good trials to session.hdf5 @QtCore.pyqtSlot(bool) def on_pB_add_trial_clicked(self): if self.data_loaded: trial = int(self.ui.label_trial_number_int.text()) all_trials = [int(x) for x in self.get_all_combobox_values(self.ui.cB_selected_trials)] if trial != -1 and trial not in all_trials: self.ui.cB_selected_trials.addItem(str(trial)) if self.analysis_exists: analysis_path = os.path.join(self.session, self.analysis_folder) session_hdf5 = pd.HDFStore(analysis_path+self.analysis_file_name) if self.good_trials_key in session_hdf5: good_trials = session_hdf5[self.good_trials_key]; """:type : pd.Series""" good_trials.set_value(max(good_trials.keys())+1, trial) else: good_trials = pd.Series(trial) good_trials.to_hdf(analysis_path+self.analysis_file_name, self.good_trials_key) session_hdf5.close() @QtCore.pyqtSlot(bool) def on_pB_remove_trial_clicked(self): if self.data_loaded and self.ok_dialog(): index =self.ui.cB_selected_trials.currentIndex() trial = int(self.ui.cB_selected_trials.currentText()) self.ui.cB_selected_trials.removeItem(index) if self.analysis_exists: analysis_path = os.path.join(self.session, self.analysis_folder) session_hdf5 = pd.HDFStore(analysis_path+self.analysis_file_name) if self.good_trials_key in session_hdf5: good_trials = session_hdf5[self.good_trials_key]; """:type : pd.Series""" good_trials = good_trials[good_trials != trial] good_trials.reset_index(drop=True) good_trials.to_hdf(analysis_path+self.analysis_file_name, self.good_trials_key) session_hdf5.close() # Slots for adding and removing paw touching events to session.hdf5 @QtCore.pyqtSlot(bool) def on_pB_fl_paw_add_frame_clicked(self): if self.data_loaded and self.analysis_exists: frame = self.ui.sBox_FrameNum.value() all_frames = self.get_all_combobox_values(self.ui.cB_fl_paw_frames) if frame not in all_frames: self.ui.cB_fl_paw_frames.addItem(str(frame)) self.ui.cB_fl_paw_frames.setCurrentIndex(self.ui.cB_fl_paw_frames.count()-1) self.update_paw_events_dataframe(self.flpaw) @QtCore.pyqtSlot(bool) def on_pB_fl_paw_remove_frame_clicked(self): if self.data_loaded and self.analysis_exists and self.ok_dialog(): self.ui.cB_fl_paw_frames.removeItem(self.ui.cB_fl_paw_frames.currentIndex()) analysis_path = os.path.join(self.session, self.analysis_folder) session_hdf5 = pd.HDFStore(analysis_path+self.analysis_file_name) if self.paw_events_key in session_hdf5: paw_events = session_hdf5[self.paw_events_key]; """:type : pd.DataFrame""" paw_events = paw_events[paw_events[self.flpaw] != int(self.ui.cB_fl_paw_frames.currentText())] paw_events.to_hdf(analysis_path+self.analysis_file_name, self.paw_events_key) session_hdf5.close() @QtCore.pyqtSlot(bool) def on_pB_fr_paw_add_frame_clicked(self): if self.data_loaded and self.analysis_exists: frame = self.ui.sBox_FrameNum.value() all_frames = self.get_all_combobox_values(self.ui.cB_fr_paw_frames) if frame not in all_frames: self.ui.cB_fr_paw_frames.addItem(str(frame)) self.ui.cB_fr_paw_frames.setCurrentIndex(self.ui.cB_fr_paw_frames.count()-1) self.update_paw_events_dataframe(self.frpaw) @QtCore.pyqtSlot(bool) def on_pB_fr_paw_remove_frame_clicked(self): if self.data_loaded and self.analysis_exists and self.ok_dialog(): self.ui.cB_fr_paw_frames.removeItem(self.ui.cB_fr_paw_frames.currentIndex()) analysis_path = os.path.join(self.session, self.analysis_folder) session_hdf5 = pd.HDFStore(analysis_path+self.analysis_file_name) if self.paw_events_key in session_hdf5: paw_events = session_hdf5[self.paw_events_key]; """:type : pd.DataFrame""" paw_events = paw_events[paw_events[self.frpaw] != int(self.ui.cB_fr_paw_frames.currentText())] paw_events.to_hdf(analysis_path+self.analysis_file_name, self.paw_events_key) session_hdf5.close() @QtCore.pyqtSlot(bool) def on_pB_bl_paw_add_frame_clicked(self): if self.data_loaded and self.analysis_exists: frame = self.ui.sBox_FrameNum.value() all_frames = self.get_all_combobox_values(self.ui.cB_bl_paw_frames) if frame not in all_frames: self.ui.cB_bl_paw_frames.addItem(str(frame)) self.ui.cB_bl_paw_frames.setCurrentIndex(self.ui.cB_bl_paw_frames.count()-1) self.update_paw_events_dataframe(self.blpaw) @QtCore.pyqtSlot(bool) def on_pB_bl_paw_remove_frame_clicked(self): if self.data_loaded and self.analysis_exists and self.ok_dialog(): self.ui.cB_bl_paw_frames.removeItem(self.ui.cB_bl_paw_frames.currentIndex()) analysis_path = os.path.join(self.session, self.analysis_folder) session_hdf5 = pd.HDFStore(analysis_path+self.analysis_file_name) if self.paw_events_key in session_hdf5: paw_events = self.session_hdf5[self.paw_events_key]; """:type : pd.DataFrame""" paw_events = paw_events[paw_events[self.blpaw] != int(self.ui.cB_bl_paw_frames.currentText())] paw_events.to_hdf(analysis_path+self.analysis_file_name, self.paw_events_key) session_hdf5.close() @QtCore.pyqtSlot(bool) def on_pB_br_paw_add_frame_clicked(self): if self.data_loaded and self.analysis_exists: frame = self.ui.sBox_FrameNum.value() all_frames = self.get_all_combobox_values(self.ui.cB_br_paw_frames) if frame not in all_frames: self.ui.cB_br_paw_frames.addItem(str(frame)) self.ui.cB_br_paw_frames.setCurrentIndex(self.ui.cB_br_paw_frames.count()-1) self.update_paw_events_dataframe(self.brpaw) @QtCore.pyqtSlot(bool) def on_pB_br_paw_remove_frame_clicked(self): if self.data_loaded and self.analysis_exists and self.ok_dialog(): self.ui.cB_br_paw_frames.removeItem(self.ui.cB_br_paw_frames.currentIndex()) analysis_path = os.path.join(self.session, self.analysis_folder) session_hdf5 = pd.HDFStore(analysis_path+self.analysis_file_name) if self.paw_events_key in session_hdf5: paw_events = session_hdf5[self.paw_events_key]; """:type : pd.DataFrame""" paw_events = paw_events[paw_events[self.brpaw] != int(self.ui.cB_br_paw_frames.currentText())] paw_events.to_hdf(analysis_path+self.analysis_file_name, self.paw_events_key) session_hdf5.close() def update_paw_events_dataframe(self, paw): frame_num = self.ui.sBox_FrameNum.value() analysis_path = os.path.join(self.session, self.analysis_folder) session_hdf5 = pd.HDFStore(analysis_path+self.analysis_file_name) time_of_frame = session_hdf5[self.fronttime_key].iloc[frame_num] trial_num = int(self.ui.label_trial_number_int.text()) self.ui.label_trial_number_int.setText(str(trial_num)) if self.paw_events_key in session_hdf5: paw_events = session_hdf5[self.paw_events_key]; """:type : pd.DataFrame""" else: paw_events = pd.DataFrame(columns=[self.trial_paw_event, self.time_paw_event, self.blpaw, self.brpaw, self.flpaw, self.frpaw]) def bl_paw(): return np.array([[trial_num, time_of_frame, frame_num, -1, -1, -1]]) def br_paw(): return np.array([[trial_num, time_of_frame, -1, frame_num, -1, -1]]) def fl_paw(): return np.array([[trial_num, time_of_frame, -1, -1, frame_num, -1]]) def fr_paw(): return np.array([[trial_num, time_of_frame, -1, -1, -1, frame_num]]) paw_switch = {self.blpaw: bl_paw, self.brpaw: br_paw, self.flpaw: fl_paw, self.frpaw: fr_paw} df_to_append = pd.DataFrame(paw_switch[paw]().tolist(), columns=[self.trial_paw_event, self.time_paw_event, self.blpaw, self.brpaw, self.flpaw, self.frpaw]) df_to_append[[self.trial_paw_event, self.blpaw, self.brpaw, self.flpaw, self.frpaw]] = \ df_to_append[[self.trial_paw_event, self.blpaw, self.brpaw, self.flpaw, self.frpaw]].astype('int') paw_events = paw_events.append(df_to_append, ignore_index=True) paw_events.to_hdf(analysis_path+self.analysis_file_name, self.paw_events_key) session_hdf5.close() def get_all_combobox_values(self, combobox): return [combobox.itemText(i) for i in np.arange(combobox.count())] def ok_dialog(self): mb = QtWidgets.QMessageBox() mb.setText("Do you want to delete this event?") mb.setStandardButtons(QtWidgets.QMessageBox.Ok | QtWidgets.QMessageBox.Cancel) answer = mb.exec() if answer == QtWidgets.QMessageBox.Ok: return True else: return False # Slots for mouse events (right, middle, left clicks and movement @QtCore.pyqtSlot(object) def on_mplg_frames_buttonpressed(self, event): button = event.button xdata = event.xdata ydata = event.ydata if self.data_loaded and self.analysis_exists: traj_name = self.ui.cB_trajectory_name.currentText() # Get name of current trajectory if not traj_name: # Notify user if there is no current trajectory selected mb = QtWidgets.QMessageBox() mb.setText("You need to set a name for the trajectory.") mb.setStandardButtons(QtWidgets.QMessageBox.Ok) mb.exec() return analysis_path = os.path.join(self.session, self.analysis_folder) session_hdf5 = pd.HDFStore(analysis_path+self.analysis_file_name, mode='a', complevel=9, complib='zlib') trial_num = int(self.ui.label_trial_number_int.text()) frame_num = int(self.ui.sBox_FrameNum.text()) time_of_frame = session_hdf5[self.fronttime_key].iloc[frame_num] image_size_factor = self.ui.dSB_frame_resize.value() if button == 1: # On LMB add a point to the current trial's current trajectory df_to_append = pd.DataFrame([[traj_name, trial_num, frame_num, time_of_frame, int(xdata/image_size_factor), int(ydata/image_size_factor)]], columns=[self.name_traj_point, self.trial_traj_point, self.frame_traj_point, self.time_traj_point, self.x_traj_point, self.y_traj_point]) if self.trajectories_key in session_hdf5: trajectories = session_hdf5[self.trajectories_key]; """:type : pd.DataFrame""" trajectories = trajectories.append(df_to_append, ignore_index=True) else: trajectories = df_to_append trajectories[self.name_traj_point] = trajectories[self.name_traj_point].astype('str') trajectories[[self.trial_traj_point, self.frame_traj_point, self.x_traj_point, self.y_traj_point]] = trajectories[[self.trial_traj_point, self.frame_traj_point, self.x_traj_point, self.y_traj_point]].astype('int') session_hdf5[self.trajectories_key] = trajectories self.plot_trajectory(trajectories, [traj_name], frame_num, trial_num) if button == 3 and self.trajectories_key in session_hdf5: # On RMB just draws the current trial's current trajectory trajectories = session_hdf5[self.trajectories_key]; """:type : pd.DataFrame""" trials = trajectories[self.trial_traj_point] current_trial = int(self.ui.label_trial_number_int.text()) if trials[trials==current_trial].size>0: # Show only if there is a trajectory for this trial self.plot_trajectory(trajectories, [traj_name], frame_num, trial_num) if button == 2 and self.trajectories_key in session_hdf5: # On MMB deletes the clicked point of the current trial's current trajectory trajectories = session_hdf5[self.trajectories_key]; """:type : pd.DataFrame""" x_data = trajectories[trajectories[self.name_traj_point] == traj_name][trajectories[self.trial_traj_point] == trial_num][self.x_traj_point] y_data = trajectories[trajectories[self.name_traj_point] == traj_name][trajectories[self.trial_traj_point] == trial_num][self.y_traj_point] xdiff = np.array(x_data - xdata/image_size_factor) ydiff = np.array(y_data - ydata/image_size_factor) max_diff = 20*image_size_factor x_idx = np.where((xdiff>-max_diff)*(xdiff<max_diff)) y_idx = np.where((ydiff>-max_diff)*(ydiff<max_diff)) idx_to_remove = np.intersect1d(x_idx, y_idx) if x_data[idx_to_remove].size > 0 and y_data[idx_to_remove].size > 0: for i in idx_to_remove: x_to_remove = x_data.iloc[i].tolist() y_to_remove = y_data.iloc[i].tolist() traj_indices_to_remove = trajectories[trajectories[self.name_traj_point] == traj_name][trajectories[self.trial_traj_point] == trial_num][x_data == x_to_remove][y_data == y_to_remove].index trajectories = trajectories.drop(traj_indices_to_remove) trajectories = trajectories.reset_index(drop=True) trajectories[self.name_traj_point] = trajectories[self.name_traj_point].astype('str') trajectories[[self.trial_traj_point, self.frame_traj_point, self.x_traj_point, self.y_traj_point]] = trajectories[[self.trial_traj_point, self.frame_traj_point, self.x_traj_point, self.y_traj_point]].astype('int') session_hdf5[self.trajectories_key] = trajectories self.plot_trajectory(trajectories, traj_name, frame_num, trial_num) session_hdf5.close() def plot_trajectory(self, trajectories, traj_names, frame_num, trial_num): self.on_sBox_FrameNum_valueChanged(frame_num) image_size_factor = self.ui.dSB_frame_resize.value() axes = self.ui.mplg_frames.all_sp_axes[0];""":type : matplotlib.axes.Axes""" trajectories = trajectories.sort(self.frame_traj_point, ascending=True) for traj_name in traj_names: x_data = trajectories[trajectories[self.name_traj_point] == traj_name][trajectories[self.trial_traj_point] == trial_num][self.x_traj_point]*image_size_factor y_data = trajectories[trajectories[self.name_traj_point] == traj_name][trajectories[self.trial_traj_point] == trial_num][self.y_traj_point]*image_size_factor index_of_trajectory = self.ui.cB_trajectory_name.currentIndex() index_to_color = {0: 'blue', 1: 'green', 2: 'yellow', 3: 'red'} color = index_to_color[index_of_trajectory % 4] line = axes.plot(x_data, y_data, color=color, marker='o', markersize=5) self.trajectory_lines.append(line[0]) self.ui.mplg_frames.canvas.draw() @QtCore.pyqtSlot(object) def on_mplg_frames_keypressed(self, event): key = event.key if key == 'q': self.ui.sBox_FrameNum.setValue(self.ui.sBox_FrameNum.value()-self.ui.sBox_frames_step.value()) if key == 'w': self.ui.sBox_FrameNum.setValue(self.ui.sBox_FrameNum.value()+self.ui.sBox_frames_step.value()) @QtCore.pyqtSlot(object) def on_mplg_frames_mousemove(self, event): if self.trajectory_lines: for line in self.trajectory_lines: line.set_pickradius(5) if line.contains(event)[0]: axes = self.ui.mplg_frames.all_sp_axes[0];""":type : matplotlib.axes.Axes""" xy = line.get_xydata() point_ind = line.contains(event)[1]['ind'][0] traj_name = self.ui.cB_trajectory_name.currentText() trial_num = int(self.ui.label_trial_number_int.text()) analysis_path = os.path.join(self.session, self.analysis_folder) session_hdf5 = pd.HDFStore(analysis_path+self.analysis_file_name, mode='r') trajectories = session_hdf5[self.trajectories_key]; """:type : pd.DataFrame""" session_hdf5.close() trajectories = trajectories.sort(self.frame_traj_point, ascending=True) frame = trajectories[trajectories[self.name_traj_point] == traj_name][trajectories[self.trial_traj_point] == trial_num][self.frame_traj_point].tolist()[point_ind] self.annotation = mpt.Annotation(str(frame), xy=tuple(xy[point_ind]), xytext=(xy[point_ind][0], xy[point_ind][1]-40), xycoords='data', textcoords='data', horizontalalignment="left", arrowprops=dict(arrowstyle="simple", connectionstyle="arc3,rad=-0.2"), bbox=dict(boxstyle="round", facecolor="w", edgecolor="0.5", alpha=0.9)) axes.add_artist(self.annotation) self.ui.mplg_frames.canvas.draw() def connect_slots(self): self.ui.pB_selecet_data.clicked.connect(self.on_pB_select_data_clicked) self.ui.sBox_FrameNum.valueChanged.connect(self.on_sBox_FrameNum_valueChanged) self.ui.hSB_piezo_samples_to_plot.valueChanged.connect(self.on_hSB_piezo_samples_to_plot_valueChanged) self.ui.sBox_frames_step.valueChanged.connect(self.on_sBox_frames_step_valueChanged) self.ui.pB_Run.toggled.connect(self.on_pB_Run_toggled) self.ui.dSB_frame_resize.valueChanged.connect(self.on_dSB_frame_resize_valueChanged) self.ui.pB_goto_trial_frame.clicked.connect(self.on_pB_goto_trial_frame_clicked) self.ui.pB_add_trial.clicked.connect(self.on_pB_add_trial_clicked) self.ui.pB_remove_trial.clicked.connect(self.on_pB_remove_trial_clicked) self.ui.pB_fl_paw_add_frame.clicked.connect(self.on_pB_fl_paw_add_frame_clicked) self.ui.pB_fl_paw_remove_frame.clicked.connect(self.on_pB_fl_paw_remove_frame_clicked) self.ui.pB_fr_paw_add_frame.clicked.connect(self.on_pB_fr_paw_add_frame_clicked) self.ui.pB_fr_paw_remove_frame.clicked.connect(self.on_pB_fr_paw_remove_frame_clicked) self.ui.pB_bl_paw_add_frame.clicked.connect(self.on_pB_bl_paw_add_frame_clicked) self.ui.pB_bl_paw_remove_frame.clicked.connect(self.on_pB_bl_paw_remove_frame_clicked) self.ui.pB_br_paw_add_frame.clicked.connect(self.on_pB_br_paw_add_frame_clicked) self.ui.pB_br_paw_remove_frame.clicked.connect(self.on_pB_br_paw_remove_frame_clicked) self.ui.mplg_frames.button_pressed.connect(self.on_mplg_frames_buttonpressed) self.ui.mplg_frames.key_pressed.connect(self.on_mplg_frames_keypressed) self.ui.mplg_frames.mouse_move.connect(self.on_mplg_frames_mousemove)