def make_window(self): """Make experiment GUI, defined in children depending on experiments.""" if self.stim_plot: self.window_main = DynamicStimExperimentWindow(self) self.window_main.stream_plot.add_stream(self.protocol_runner.dynamic_log) self.gui_timer.start(1000 // 60) else: self.window_main = VisualExperimentWindow(self) self.window_main.construct_ui() self.window_main.show()
class VisualExperiment(Experiment): """General class that runs an experiment. Parameters ---------- calibrator : :class:`Calibrator <stytra.calibration.Calibrator>` object (optional) Calibrator object to calibrate the stimulus display. If not set, a CrossCalibrator will be used. display_config: dict (optional) Dictionary with specifications for the display. Possible key values are "full_screen" and "window_size". gl_display : bool (False) rec_stim_framerate : int (optional) Set to record a movie of the displayed visual stimulus. It specifies every how many frames one will be saved (set to 1 to record) all displayed frames. The final movie will be saved in the directory in an .h5 file. offline : bool if stytra is used in offline analysis, stimulus is not displayed """ sig_data_saved = pyqtSignal() def __init__( self, *args, calibrator=None, stim_plot=False, stim_movie_format="h5", record_stim_framerate=None, display=None, **kwargs ): """ """ if calibrator is None: self.calibrator = CrossCalibrator() else: self.calibrator = calibrator self.stim_movie_format = stim_movie_format self.stim_plot = stim_plot super().__init__(*args, **kwargs) self.dc.add(self.calibrator) if display is None: self.display_config = dict(full_screen=False, gl=True) else: self.display_config = display target_fps = self.display_config.get("framerate", 0) if target_fps > 0: self.protocol_runner.target_dt = 1000 // target_fps if not self.offline: self.window_display = StimulusDisplayWindow( self.protocol_runner, self.calibrator, gl=self.display_config.get("gl", True), record_stim_framerate=record_stim_framerate, ) self.display_framerate_acc = None self.protocol_runner.framerate_acc.goal_framerate = self.display_config.get( "min_framerate", None ) def start_experiment(self): """Start the experiment creating GUI and initialising metadata. Parameters ---------- Returns ------- """ super().start_experiment() if self.display_config.get("window_size", None) is not None: self.window_display.size = self.display_config["window_size"] self.window_display.set_dims() self.show_stimulus_screen(self.display_config.get("full_screen", False)) def restore_window_state(self): if self.gui_params.window_state: self.window_main.restoreState( QByteArray.fromHex(bytes(self.gui_params.window_state, "ascii")) ) self.window_main.restoreGeometry( QByteArray.fromHex(bytes(self.gui_params.geometry, "ascii")) ) def make_window(self): """Make experiment GUI, defined in children depending on experiments.""" if self.stim_plot: self.window_main = DynamicStimExperimentWindow(self) self.window_main.stream_plot.add_stream(self.protocol_runner.dynamic_log) self.gui_timer.start(1000 // 60) else: self.window_main = VisualExperimentWindow(self) self.window_main.construct_ui() self.window_main.show() def start_protocol(self): """Start the protocol from the ProtocolRunner. Before that, send a a notification and if required communicate with the microscope to synchronize and read configuration. Parameters ---------- Returns ------- """ self.window_display.widget_display.reset() super().start_protocol() def save_data(self): if self.base_dir is not None: if self.dc is not None: # save the stimulus movie if it is generated movie, movie_times = self.window_display.widget_display.get_movie() if movie is not None: if self.stim_movie_format == "h5": movie_dict = dict( movie=np.stack(movie, 0), movie_times=movie_times ) fl.save( self.filename_base() + "stim_movie.h5", movie_dict, compression="blosc", ) elif self.stim_movie_format == "mp4": imageio.mimwrite( self.filename_base() + "stim_movie.mp4", movie, fps=30, quality=None, ffmpeg_params=[ "-pix_fmt", "yuv420p", "-profile:v", "baseline", "-level", "3", ], ) else: raise Exception( "Tried to write the stimulus video into an unsupported format" ) super().save_data() def show_stimulus_screen(self, full_screen=False): """Open window to display the visual stimulus and make it full-screen if necessary. Parameters ---------- full_screen : (Default value = True) Returns ------- """ if self.offline: return None self.window_display.show() if full_screen: try: self.window_display.windowHandle().setScreen(self.app.screens()[1]) self.window_display.showFullScreen() except IndexError: print("Second screen not available")