Esempio n. 1
0
def main_launcher():
    options = parse_arguments()
    # flip the default vs the individual launchers - wait for all of the backends
    options.wait = True

    # save the total state
    _opts = get_printable_options_dict(options,
                                       include_experiment_and_playlist=True)
    with open(options.record_file.replace('.h5', '.config.yml'), 'wt') as f:
        yaml.safe_dump(_opts, f)

    log = logging.getLogger('flyvr.main')

    flyvr_shared_state = SharedState(options=options,
                                     logger=None,
                                     where='main')

    # start the IPC bus first as it is needed by many subsystems
    ipc_bus = ConcurrentTask(task=run_main_relay, comms=None, taskinitargs=[])
    ipc_bus.start()

    # start the GUI
    gui = ConcurrentTask(task=run_main_state_gui,
                         comms=None,
                         taskinitargs=[None, True])
    gui.start()

    backend_wait = [BACKEND_FICTRAC]

    trac_drv = _get_fictrac_driver(options, log)
    if trac_drv is not None:
        fictrac_task = ConcurrentTask(task=trac_drv.run,
                                      comms=None,
                                      taskinitargs=[options])
        fictrac_task.start()

        # wait till fictrac is processing frames
        flyvr_shared_state.wait_for_backends(BACKEND_FICTRAC)
        log.info('fictrac is ready')

    # start the other mainloops

    # these always run
    hwio = ConcurrentTask(task=run_phidget_io,
                          comms=None,
                          taskinitargs=[options])
    backend_wait.append(BACKEND_HWIO)
    hwio.start()

    daq = ConcurrentTask(task=run_io, comms=None, taskinitargs=[options])
    backend_wait.append(BACKEND_DAQ)
    daq.start()

    # these are optional
    if options.keepalive_video or options.playlist.get('video'):
        video = ConcurrentTask(task=run_video_server,
                               comms=None,
                               taskinitargs=[options])
        backend_wait.append(BACKEND_VIDEO)
        video.start()
    else:
        video = None
        log.info(
            'not starting video backend (playlist empty or keepalive_video not specified)'
        )

    if options.keepalive_audio or options.playlist.get('audio'):
        audio = ConcurrentTask(task=run_sound_server,
                               comms=None,
                               taskinitargs=[options])
        backend_wait.append(BACKEND_AUDIO)
        audio.start()
    else:
        audio = None
        log.info(
            'not starting video backend (playlist empty or keepalive_video not specified)'
        )

    log.info('waiting %ss for %r to be ready' % (60, backend_wait))
    if flyvr_shared_state.wait_for_backends(*backend_wait, timeout=60):

        if options.delay < 0:
            log.info('waiting for manual start signal')
            flyvr_shared_state.wait_for_start()
        elif options.delay >= 0:
            if options.delay > 0:
                log.info('delaying startup %ss' % options.delay)
                time.sleep(options.delay)
            log.info('sending start signal')
            flyvr_shared_state.signal_start()

        for i in itertools.count():
            try:
                inputimeout(
                    '\n---------------\nPress any key to finish\n---------------\n\n'
                    if i == 0 else '', 1)
                flyvr_shared_state.signal_stop().join(timeout=5)
                break
            except TimeoutOccurred:
                if flyvr_shared_state.is_stopped():
                    # stopped from elsewhere (gui)
                    break

    else:
        log.error(
            'not all required backends became ready - please check logs for '
            'error messages')
        flyvr_shared_state.signal_stop()

    log.info('stopped')

    for task in (ipc_bus, gui, hwio, daq, video, audio):
        if task is not None:
            log.debug('closing subprocess: %r' % task)
            task.close()

    log.info('finished')
Esempio n. 2
0
class FlyVRStateGui(QWidget):

    STATE = [
        'FICTRAC_FRAME_NUM', 'SOUND_OUTPUT_NUM_SAMPLES_WRITTEN',
        'VIDEO_OUTPUT_NUM_FRAMES', 'DAQ_OUTPUT_NUM_SAMPLES_WRITTEN',
        'DAQ_INPUT_NUM_SAMPLES_READ'
    ]
    FPS = 30

    def __init__(self, app, quit_app_on_stop):
        # noinspection PyArgumentList
        super().__init__(parent=None)
        self._app = app
        self._quit_app_on_stop = quit_app_on_stop

        self._entries = {}

        self._tick = 0
        self._fn0 = self._t0 = 0

        self._lbl_backends = None
        self._lbl_started = None
        self._lbl_fps = None

        self._init_ui()

        self.flyvr_shared_state = SharedState(options=None,
                                              logger=None,
                                              where='gui')

        self._timer = QTimer()
        # noinspection PyUnresolvedReferences
        self._timer.timeout.connect(self._update_state)
        self._timer.start(1000 / FlyVRStateGui.FPS)

    def _update_state(self):
        for s in FlyVRStateGui.STATE:
            v = getattr(self.flyvr_shared_state, s)
            self._entries[s].setText(str(v or 0))

        self._lbl_backends.setText(', '.join(
            self.flyvr_shared_state.backends_ready))
        self._lbl_started.setText(str(self.flyvr_shared_state.is_started()))

        # every second-ish
        if (self._tick % self.FPS) == 0:
            fictrac_fps = (self.flyvr_shared_state.FICTRAC_FRAME_NUM -
                           self._fn0) / (time.time() - self._t0)
            self._lbl_fps.setText('%.1f' % fictrac_fps)

            self._fn0 = self.flyvr_shared_state.FICTRAC_FRAME_NUM
            self._t0 = time.time()

        self._tick += 1

        if self._quit_app_on_stop:
            if self.flyvr_shared_state.is_stopped():
                self._app.quit()

    def _clicked_clear(self):
        for s in FlyVRStateGui.STATE:
            self._entries[s].setText('')

    def _clicked_start(self):
        self.flyvr_shared_state.signal_start()

    def _clicked_stop(self):
        self.flyvr_shared_state.signal_stop().join(2)

    # noinspection PyUnresolvedReferences,PyArgumentList
    def _init_ui(self):
        self.setWindowTitle('FlyVR')

        layout = QGridLayout()

        # noinspection PyArgumentList
        def _build_label(_name, _row):
            _lbl = QLabel('&%s' % _name, self)
            _edt = QLineEdit(self)
            _edt.setReadOnly(True)
            _lbl.setBuddy(_edt)

            layout.addWidget(_lbl, _row, 0)
            layout.addWidget(_edt, _row, 1, 1, 2)

            return _edt

        row = 0
        for s in FlyVRStateGui.STATE:
            self._entries[s] = _build_label(s, row)
            row += 1

        self._lbl_fps = _build_label('FicTrac Framerate', row)
        row += 1

        self._lbl_backends = _build_label('Backends Ready', row)
        row += 1

        self._lbl_started = _build_label('Experiment Started', row)
        row += 1

        # clear = QPushButton('&Clear')
        # clear.clicked.connect(self._clicked_clear)
        # layout.addWidget(clear, row, 2)
        # row += 1

        start = QPushButton('&Start Experiment')
        start.clicked.connect(self._clicked_start)
        stop = QPushButton('&Stop FlyVR')
        stop.clicked.connect(self._clicked_stop)

        layout.addWidget(start, row, 1)
        layout.addWidget(stop, row, 2)

        row += 1

        self.setLayout(layout)