Beispiel #1
0
    def run(self, options):

        flyvr_shared_state = SharedState(options=options,
                                         logger=None,
                                         where=BACKEND_HWIO,
                                         _start_rx_thread=False)

        # todo: only if all the things are connected? at least scanimage?
        _ = flyvr_shared_state.signal_ready(BACKEND_HWIO)

        with open(options.record_file.replace('.h5', '.toc.yml'), 'wt') as f:

            def _streaming_yaml_record(_msg):
                # stream yaml records (list of dicts) to the file
                f.write('- ')
                f.write(json.dumps(_msg))
                f.write('\n')
                f.flush()

            while True:
                msg = self._rx.get_next_element()
                if msg:
                    if CommonMessages.EXPERIMENT_PLAYLIST_ITEM in msg:

                        # a backend is playing a new playlist item
                        self._flash_led()

                        if self._tp_enable:
                            self.next_image()

                        _streaming_yaml_record(msg)

                    if CommonMessages.EXPERIMENT_START in msg:
                        # noinspection PyProtectedMember
                        msg = flyvr_shared_state._build_toc_message(
                            'experiment')
                        msg['identifier'] = '_start'
                        _streaming_yaml_record(msg)

                    if CommonMessages.EXPERIMENT_STOP in msg:
                        break

        self._log.info('stopped')

        self.stop_scanimage()
        self.close()
Beispiel #2
0
    def run(self, options=None):
        """
        Start the the FicTrac process and block till it closes. This function will poll a shared memory region for
        changes in tracking data and invoke a control function when they occur. FicTrac is assumed to exist on the
        system path.

        Args:
            options: options loaded from FlyVR config file. If None, driver runs without logging enabled, this is useful
                for testing.

        :return:
        """

        if options is not None:
            setup_logging(options)

            setup_experiment(options)
            if options.experiment:
                self._log.info('initialized experiment %r' %
                               options.experiment)
            self.experiment = options.experiment

            # fixme: this should be threaded and context manager to close
            log_server = DatasetLogServer()

            flyvr_shared_state = SharedState(
                options=options,
                logger=log_server.start_logging_server(options.record_file),
                where=BACKEND_FICTRAC)
            if self.experiment:
                # noinspection PyProtectedMember
                self.experiment._set_shared_state(flyvr_shared_state)

            # Setup dataset to log FicTrac data to.
            flyvr_shared_state.logger.create(
                "/fictrac/output",
                shape=[2048, NUM_FICTRAC_FIELDS],
                maxshape=[None, NUM_FICTRAC_FIELDS],
                dtype=np.float64,
                chunks=(2048, NUM_FICTRAC_FIELDS))
            flyvr_shared_state.logger.log("/fictrac/output",
                                          H5_DATA_VERSION,
                                          attribute_name='__version')
        else:
            flyvr_shared_state = None

        self.fictrac_signals = new_mmap_signals_buffer()

        # Start FicTrac
        with open(self.console_output_file, "wb") as out:

            self.fictrac_process = subprocess.Popen(
                [self.fictrac_bin_fullpath, self.config_file],
                stdout=out,
                stderr=subprocess.STDOUT)

            # Setup the shared memory conneciton and peek at the frame counter
            data = new_mmap_shmem_buffer()
            first_frame_count = data.frame_cnt
            old_frame_count = data.frame_cnt

            running = True
            self._log.info("waiting for fictrac updates in shared memory")

            semaphore = self._open_fictrac_semaphore()

            # Process FicTrac updates in shared memory
            while (self.fictrac_process.poll() is
                   None) and running and semaphore:

                # Acquire the semaphore copy the current fictrac state.
                try:
                    semaphore.acquire(timeout_ms=1000)
                    data_copy = SHMEMFicTracState()
                    ctypes.pointer(data_copy)[0] = data
                    semaphore.release()
                except FileNotFoundError:
                    # Semaphore is gone, lets shutdown things.
                    break
                except OSError:
                    break

                new_frame_count = data_copy.frame_cnt

                if old_frame_count != new_frame_count:
                    # If this is our first frame incremented, then send a signal to the
                    # that we have started processing frames
                    if old_frame_count == first_frame_count:
                        if flyvr_shared_state:
                            _ = flyvr_shared_state.signal_ready(
                                BACKEND_FICTRAC)

                    if new_frame_count - old_frame_count != 1:
                        # self.fictrac_process.terminate()
                        self._log.error(
                            "frame counter jumped by more than 1 (%s vs %s)" %
                            (old_frame_count, new_frame_count))

                    old_frame_count = new_frame_count

                    # Log the FicTrac data to our master log file.
                    if flyvr_shared_state:
                        flyvr_shared_state.logger.log(
                            '/fictrac/output', fictrac_state_to_vec(data_copy))

                    if self.experiment is not None:
                        self.experiment.process_state(data_copy)

                # If we detect it is time to shutdown, kill the FicTrac process
                if flyvr_shared_state and flyvr_shared_state.is_stopped():
                    running = False

            # Try to close up the semaphore
            try:
                if semaphore:
                    semaphore.close()
            except OSError:
                pass

        self.stop()  # blocks

        self._log.info('fictrac process finished')

        # Get the fictrac process return code
        if self.fictrac_process.returncode is not None and self.fictrac_process.returncode != 0:
            self._log.error(
                'fictrac failed because of an application error. Consult the fictrac console output file'
            )

            if flyvr_shared_state:
                flyvr_shared_state.runtime_error(2)