示例#1
0
def main_sound_server():
    import yaml
    import os.path

    from flyvr.common.build_arg_parser import build_argparser, parse_options
    from flyvr.audio.util import plot_playlist
    from zmq.utils.win32 import allow_interrupt

    parser = build_argparser()
    parser.add_argument('--print-devices',
                        action='store_true',
                        help='print available audio devices')
    parser.add_argument('--convert-playlist',
                        help='convert a stimulus playlist to new format')
    parser.add_argument('--paused', action='store_true', help='start paused')
    parser.add_argument('--plot',
                        action='store_true',
                        help='plot the stimulus playlist')

    options = parse_options(parser.parse_args(), parser)

    if options.plot:
        setup_logging(options)

        if not options.playlist.get('audio'):
            return parser.error('Config file contains no audio playlist')

        plot_playlist(options, 'audio')

        return parser.exit(0)

    if options.convert_playlist:
        src = options.convert_playlist
        if os.path.isfile(src):
            pl = AudioStimPlaylist.from_legacy_filename(src)
            dest = options.convert_playlist + '.yml'
            with open(dest, 'wt') as f:
                yaml.dump({'playlist': {'audio': pl.describe()}}, f)

            return parser.exit(0, message='Wrote %s' % dest)

        else:
            return parser.error('Could not find %s' % src)

    if options.print_devices:
        SoundServer.list_supported_asio_output_devices()
        return parser.exit(0)

    quit_evt = threading.Event()

    # noinspection PyUnusedLocal
    def ctrlc(*args):
        quit_evt.set()

    with allow_interrupt(action=ctrlc):
        run_sound_server(options, quit_evt)
示例#2
0
def run_sound_server(options, quit_evt=None):
    from flyvr.common import SharedState, Randomizer
    from flyvr.common.logger import DatasetLogServerThreaded
    from flyvr.audio.util import get_paylist_object

    setup_logging(options)

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

    playlist_stim, basedirs = get_paylist_object(
        options,
        playlist_type='audio',
        # optional because we are also called
        # from flyvr main launcher
        paused_fallback=getattr(options, 'paused', False),
        # dudi requested to preserve the last default
        default_repeat=Randomizer.REPEAT_FOREVER,
        attenuator=None)  # fixme: attenuator from config
    if playlist_stim is not None:
        log.info('initialized audio playlist: %r' % playlist_stim)

    with DatasetLogServerThreaded() as log_server:
        logger = log_server.start_logging_server(
            options.record_file.replace('.h5', '.sound_server.h5'))
        state = SharedState(options=options,
                            logger=logger,
                            where=BACKEND_AUDIO)

        sound_server = SoundServer(flyvr_shared_state=state)
        if playlist_stim is not None:
            sound_server.queue.put(playlist_stim)

        ipc = threading.Thread(daemon=True,
                               name='AudioIpcThread',
                               target=_ipc_main,
                               args=(sound_server.queue, basedirs))
        ipc.start()

        # starts the thread
        sound_server.start_stream(
            frames_per_buffer=SoundServer.DEFAULT_CHUNK_SIZE)

        if quit_evt is not None:
            # the single process launcher
            try:
                quit_evt.wait()
            except KeyboardInterrupt:
                sound_server.queue.put(_QUIT)

        sound_server.join()

    log.info('finished')
示例#3
0
def main_replay():
    import argparse
    from flyvr.common.build_arg_parser import setup_logging

    parser = argparse.ArgumentParser()
    parser.add_argument('--fps', type=float, default=0, help='play back fictrac data at this fps '
                                                             '(0 = rate at which it was recorded)')
    parser.add_argument('-v', help='Verbose output', default=False, dest='verbose', action='store_true')
    parser.add_argument('h5file', nargs=1, metavar='PATH', help='path to h5 file of previous flyvr session')

    args = parser.parse_args()
    setup_logging(args)

    r = ReplayFictrac(args.h5file[0])
    r.replay('auto' if args.fps <= 0 else args.fps)
示例#4
0
def run_phidget_io(options):
    from flyvr.common.build_arg_parser import setup_logging

    setup_logging(options)

    io = PhidgetIO(
        tp_start=options.remote_start_2P_channel,
        tp_stop=options.remote_stop_2P_channel,
        tp_next=options.remote_next_2P_channel,
        tp_enable=not options.remote_2P_disable,
        signal_next_enable=not options.remote_2P_next_disable,
        start_after_next_delay=options.scanimage_next_start_delay,
        debug_led=getattr(options, 'debug_led', 2),
        remote_details=DEFAULT_REMOTE if options.phidget_network else None)
    io.run(options)
示例#5
0
文件: ipc.py 项目: murthylab/fly-vr
def main_ipc_send():
    import json
    import time
    import argparse

    from flyvr.common.build_arg_parser import setup_logging
    from flyvr.common import SharedState

    parser = argparse.ArgumentParser()
    parser.add_argument('-v', help='Verbose output', default=False, dest='verbose', action='store_true')
    parser.add_argument('--start', action='store_true', help='send start signal')
    parser.add_argument('--stop', action='store_true', help='send stop signal')
    parser.add_argument('json', nargs='?', help='raw json message contents (see README)')
    args = parser.parse_args()

    if args.start:
        setup_logging(args)
        SharedState(None, None, '').signal_start().join(timeout=5)
        return parser.exit(0)

    if args.stop:
        setup_logging(args)
        SharedState(None, None, '').signal_stop().join(timeout=5)
        return parser.exit(0)

    if not args.json:
        return parser.exit(0, 'nothing to do')

    # noinspection PyBroadException
    try:
        dat = json.loads(args.json)
    except json.JSONDecodeError as exc:
        print("PARSE ERROR:\t\n\t", (args.json, exc))
        return parser.exit(1)

    send = PlaylistSender()
    time.sleep(1.0)

    # warm up the pub/sub to give subscribers the chance to connect. this utility is transient and
    # only used for debugging, so this problem doesnt manifest in long running applications
    for i in range(10):
        send.process()

    send.process(**dat)
    send.close(block=True)
    print("SENT: %r" % dat)
示例#6
0
def main_io():
    from flyvr.common.build_arg_parser import build_argparser, parse_options, setup_logging
    from flyvr.audio.util import plot_playlist

    parser = build_argparser()
    parser.add_argument('--plot',
                        action='store_true',
                        help='plot the stimulus playlist')
    options = parse_options(parser.parse_args(), parser)

    if options.plot:
        setup_logging(options)

        if not options.playlist.get('daq'):
            return parser.error('Config file contains no daq playlist')

        plot_playlist(options, 'daq')

        return parser.exit(0)

    run_io(options)
示例#7
0
    def run(self, options):
        setup_logging(options)

        log = logging.getLogger('flyvr.fictrac.FicTracDriverReplay')

        setup_experiment(options)
        if options.experiment:
            log.info('initialized experiment %r' % options.experiment)

        flyvr_shared_state = SharedState(options=options,
                                         logger=None,
                                         where=BACKEND_FICTRAC)
        if options.experiment:
            # noinspection PyProtectedMember
            options.experiment._set_shared_state(flyvr_shared_state)

        replay = FicTracDriverReplay.StateReplayFictrac(flyvr_shared_state,
                                                        options.experiment,
                                                        self._h5_path)
        replay.replay()  # blocks

        log.info('stopped')
示例#8
0
def run_io(options):
    from flyvr.common import SharedState
    from flyvr.common.logger import DatasetLogServerThreaded

    setup_logging(options)

    q = queue.Queue()
    basedirs = [os.getcwd()]
    if getattr(options, '_config_file_path'):
        # noinspection PyProtectedMember
        basedirs.insert(0, os.path.dirname(options._config_file_path))

    ipc = threading.Thread(daemon=True,
                           name='DAQIpcThread',
                           target=_ipc_main,
                           args=(q, basedirs))
    ipc.start()

    with DatasetLogServerThreaded() as log_server:
        logger = log_server.start_logging_server(
            options.record_file.replace('.h5', '.daq.h5'))
        state = SharedState(options=options, logger=logger, where=BACKEND_DAQ)
        io_task_loop(q, state, options)
示例#9
0
def main_experiment():
    from flyvr.common.build_arg_parser import build_argparser, parse_options, setup_experiment, setup_logging

    parser = build_argparser()
    parser.add_argument(
        '--force',
        action='store_true',
        help='force/fake iterate at 200fps even if no tracking data '
        'is present (for testing)')

    options = parse_options(parser.parse_args(), parser)
    setup_logging(options)

    setup_experiment(options)
    if not options.experiment:
        parser.error("No experiment specified")

    # noinspection PyProtectedMember
    options.experiment._set_shared_state(
        SharedState(options=options, logger=None))

    # noinspection PyProtectedMember
    options.experiment._log_describe()
    do_loop(options.experiment, 1 / 200., options.force)
示例#10
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)
示例#11
0
def run_video_server(options):
    from flyvr.common import SharedState, Randomizer
    from flyvr.common.logger import DatasetLogServerThreaded

    setup_logging(options)

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

    startup_stim = None
    playlist_stim = None
    stim_playlist = options.playlist.get('video')

    if stim_playlist:
        option_item_defn = {}

        stims = []
        for item_def in stim_playlist:
            id_, defn = item_def.popitem()

            if id_ == Randomizer.IN_PLAYLIST_IDENTIFIER:
                option_item_defn = {id_: defn}
                continue

            stims.append(stimulus_factory(defn.pop('name'), identifier=id_, **defn))

        random = Randomizer.new_from_playlist_option_item(option_item_defn,
                                                          *[s.identifier for s in stims])
        paused = option_item_defn.pop('paused', None)

        playlist_stim = VideoStimPlaylist(*stims, random=random,
                                          paused=paused if paused is not None else getattr(options, 'paused', False),
                                          play_item=getattr(options, 'play_item', None))
        log.info('initialized video playlist: %r' % playlist_stim)

    elif getattr(options, 'play_stimulus', None):
        startup_stim = stimulus_factory(options.play_stimulus)
        log.info('selecting single visual stimulus: %s' % options.play_stimulus)

    with DatasetLogServerThreaded() as log_server:
        logger = log_server.start_logging_server(options.record_file.replace('.h5', '.video_server.h5'))
        state = SharedState(options=options, logger=logger, where=BACKEND_VIDEO)

        video_server = VideoServer(calibration_file=options.screen_calibration,
                                   shared_state=state,
                                   use_lightcrafter=not getattr(options, 'projector_disable', False))

        if playlist_stim is not None:
            video_server.queue.put(playlist_stim)
        elif startup_stim is not None:
            video_server.queue.put(startup_stim)

        ipc = threading.Thread(daemon=True, name='VideoIpcThread',
                               target=_ipc_main, args=(video_server.queue,))
        ipc.start()

        try:
            video_server.run()  # blocks
        except KeyboardInterrupt:
            video_server.quit()

    log.info('finished')