Esempio n. 1
0
def run_render_test(args,
                    outfile,
                    benchmark,
                    size=(640, 480),
                    scene='ortho',
                    threshold=50):

    glver = os.environ.get('FSLEYES_TEST_GL', '2.1')
    glver = [int(v) for v in glver.split('.')]

    args = '-gl {} {}'.format(*glver) .split() + \
           '-of {}'   .format(outfile).split() + \
           '-sz {} {}'.format(*size)  .split() + \
           '-s  {}'   .format(scene)  .split() + \
           list(args)

    fslrender.main(args)

    # gaaargh, why is macos case insensitive??
    if not op.exists(benchmark):
        benchmark = benchmark.lower()

    testimg = mplimg.imread(outfile)
    benchimg = mplimg.imread(benchmark)

    result, diff = compare_images(testimg, benchimg, threshold)

    assert result
Esempio n. 2
0
def main(args=None):
    """*FSLeyes* entry point. Shows a :class:`.FSLeyesSplash` screen, parses
    command line arguments, and shows a :class:`.FSLeyesFrame`. Returns
    an exit code.
    """

    if args is None:
        args = sys.argv[1:]

    # Hack to allow render to
    # be called via fsleyes.main
    if len(args) >= 1 and args[0] == 'render':
        import fsleyes.render as render
        render.main(args[1:])
        sys.exit(0)

    # the fsleyes.initialise function figures
    # out the path to asset files (e.g. cmaps)
    fsleyes.initialise()

    # Hook which allows us to run a jupyter
    # notebook server from a frozen version
    # of FSLeyes
    if len(args) >= 1 and args[0] == 'notebook':
        from fsleyes.actions.notebook import nbmain
        fsleyes.configLogging()
        sys.exit(nbmain(args))

    # initialise colour maps - this must be
    # done before parsing arguments, as if
    # the user asks for help, available
    # colourmaps/luts will be listed.
    colourmaps.init()

    # Function to bootstrap the GUI - keep
    # reading below.
    def initgui():

        # First thing's first. Create a wx.App,
        # and initialise the FSLeyes package.
        app = FSLeyesApp()

        # Create a splash screen frame
        splash = fslsplash.FSLeyesSplash(None)
        return app, splash

    # If it looks like the user is asking for
    # help, or using cliserver to pass arguments
    # to an existing FSLeyes instance, then we
    # parse command line arguments before
    # creating a wx.App and showing the splash
    # screen. This means that FSLeyes help/
    # version information can be retrieved
    # without a display, and hopefully fairly
    # quickly.
    #
    # Otherwise we create the app and splash
    # screen first, so the splash screen gets
    # shown as soon as possible. Arguments
    # will get parsed in the init function below.
    #
    # The argparse.Namespace object is kept in a
    # list so it can be shared between the sub-
    # functions below
    #
    # If argument parsing bombs out, we put the
    # exit code here and return it at the bottom.
    namespace = [None]
    exitCode = [0]

    # user asking for help - parse args first
    if (len(args) > 0) and (args[0]
                            in ('-V', '-h', '-fh', '-cs', '--version',
                                '--help', '--fullhelp', '--cliserver')):
        namespace = [parseArgs(args)]
        app, splash = initgui()

    # otherwise parse arguments on wx.MainLoop
    # below
    else:
        app, splash = initgui()

    # We are going do all processing on the
    # wx.MainLoop, so the GUI can be shown
    # as soon as possible, and because it is
    # difficult to force immediate GUI
    # refreshes when not running on the main
    # loop - this is important for FSLeyes,
    # which displays status updates to the
    # user while it is loading overlays and
    # setting up the interface.
    #
    # All of the work is defined in a series
    # of functions, which are chained together
    # via ugly callbacks, but which are
    # ultimately scheduled and executed on the
    # wx main loop.

    def init(splash):

        # See FSLeyesSplash.Show
        # for horribleness.
        splash.Show()

        # Parse command line arguments if necessary.
        # If arguments are invalid, the parseargs
        # module will raise SystemExit.
        try:
            if namespace[0] is None:

                errmsg = strings.messages['main.parseArgs.error']
                errtitle = strings.titles['main.parseArgs.error']
                with status.reportIfError(errtitle, errmsg, raiseError=True):
                    namespace[0] = parseArgs(args)

        # But the wx.App.MainLoop eats SystemExit
        # exceptions for unknown reasons, and
        # causes the application to exit
        # immediately. This makes testing FSLeyes
        # (e.g. code coverage) impossible. So I'm
        # catching SystemExit here, and then
        # telling the wx.App to exit gracefully.
        except (SystemExit, Exception) as e:
            app.ExitMainLoop()
            exitCode[0] = getattr(e, 'code', 1)
            return

        # Configure logging (this has to be done
        # after cli arguments have been parsed,
        # but before initialise is called).
        fsleyes.configLogging(namespace[0].verbose, namespace[0].noisy)

        # Initialise sub-modules/packages. The
        # buildGui function is passed through
        # as a callback, which gets called when
        # initialisation is complete.
        initialise(splash, namespace[0], buildGui)

    def buildGui():

        # Now the main stuff - create the overlay
        # list and the master display context,
        # and then create the FSLeyesFrame.
        overlayList, displayCtx = makeDisplayContext(namespace[0], splash)
        app.SetOverlayListAndDisplayContext(overlayList, displayCtx)
        frame = makeFrame(namespace[0], displayCtx, overlayList, splash)

        app.SetTopWindow(frame)
        frame.Show()

        # Check that $FSLDIR is set, complain
        # to the user if it isn't
        if not namespace[0].skipfslcheck:
            wx.CallAfter(fslDirWarning, frame)

        # Check for updates. Ignore point
        # releases, otherwise users might
        # get swamped with update notifications.
        if namespace[0].updatecheck:
            import fsleyes.actions.updatecheck as updatecheck
            wx.CallAfter(updatecheck.UpdateCheckAction(),
                         showUpToDateMessage=False,
                         showErrorMessage=False,
                         ignorePoint=False)

        # start notebook server
        if namespace[0].notebookFile is not None:
            namespace[0].notebook = True
            namespace[0].notebookFile = op.abspath(namespace[0].notebookFile)
        if namespace[0].notebook:
            from fsleyes.actions.notebook import NotebookAction
            frame.menuActions[NotebookAction](namespace[0].notebookFile)

        # start CLI server
        if namespace[0].cliserver:
            cliserver.runserver(overlayList, displayCtx)

    # Shut down cleanly on sigint/sigterm.
    # We do this so that any functions
    # registered with atexit will actually
    # get called.
    nsignals = [0]

    def sigHandler(signo, frame):
        log.debug('Signal received - FSLeyes is shutting down...')

        # first signal - try to exit cleanly
        if nsignals[0] == 0:
            nsignals[0] += 1
            exitCode[0] = signo

            # kill any modal windows
            # that are open
            for mdlg in app.modals:
                mdlg.EndModal(wx.ID_CANCEL)

            wx.CallAfter(app.ExitMainLoop)

        # subsequent signals - exit immediately
        else:
            sys.exit(signo)

    signal.signal(signal.SIGINT, sigHandler)
    signal.signal(signal.SIGTERM, sigHandler)

    # Note: If no wx.Frame is created, the
    # wx.MainLoop call will exit immediately,
    # even if we have scheduled something via
    # wx.CallAfter. In this case, we have
    # already created the splash screen, so
    # all is well.
    wx.CallAfter(init, splash)

    # under mac, use appnope to make sure
    # we don't get put to sleep. This is
    # primarily for the jupyter notebook
    # integration - if the user is working
    # with a notebook in the web browser,
    # macos might put FSLeyes to sleep,
    # causing the kernel to become
    # unresponsive.
    try:
        import appnope
        appnope.nope()
    except ImportError:
        pass
    app.MainLoop()
    shutdown()
    return exitCode[0]
Esempio n. 3
0
def main(args=None):
    """*FSLeyes* entry point. Shows a :class:`.FSLeyesSplash` screen, parses
    command line arguments, and shows a :class:`.FSLeyesFrame`. Returns
    an exit code.
    """

    if args is None:
        args = sys.argv[1:]

    # Hack to allow render to
    # be called via fsleyes.main
    if len(args) >= 1 and args[0] == 'render':
        import fsleyes.render as render
        render.main(args[1:])
        sys.exit(0)

    # Implement various hacks and workarounds
    hacksAndWorkarounds()

    # Then, first thing's first. Create a wx.App,
    # and initialise the FSLeyes package.
    app = FSLeyesApp()
    fsleyes.initialise()

    # Show the splash screen as soon as
    # possible, unless it looks like the
    # user is asking for the software
    # version or command line help.
    splash = fslsplash.FSLeyesSplash(None)

    if (len(args) > 0) and (args[0] in ('-V', '-h', '-fh', '--version',
                                        '--help', '--fullhelp')):
        splash.Hide()

    # We are going do all processing on the
    # wx.MainLoop, so the GUI can be shown
    # as soon as possible, and because it is
    # difficult to force immediate GUI
    # refreshes when not running on the main
    # loop - this is important for FSLeyes,
    # which displays status updates to the
    # user while it is loading overlays and
    # setting up the interface.
    #
    # All of the work is defined in a series
    # of functions, which are chained together
    # via ugly callbacks, but which are
    # ultimately scheduled and executed on the
    # wx main loop.

    # This is a container, shared amongst
    # the callbacks, which contains the
    # parsed argparse.Namespace object.
    namespace = [None]

    # If argument parsing bombs out,
    # we put the exit code here and
    # return it at the bottom.
    exitCode = [0]

    def init(splash):

        # Parse command line arguments. If the
        # user has asked for help (see above),
        # the parseargs module will raise
        # SystemExit. Hence we make sure the
        # splash screen is shown only after
        # arguments have been parsed.
        try:
            namespace[0] = parseArgs(args)

        # But the wx.App.MainLoop eats SystemExit
        # exceptions for unknown reasons, and
        # and causes the application to exit
        # immediately. This makes testing FSLeyes
        # (e.g. code coverage) impossible. So I'm
        # catching SystemExit here, and then
        # telling the wx.App to exit gracefully.
        except SystemExit as e:
            app.ExitMainLoop()
            exitCode[0] = e.code
            return

        # See FSLeyesSplash.Show
        # for horribleness.
        splash.Show()

        # Configure logging (this has to be done
        # after cli arguments have been parsed,
        # but before initialise is called).
        fsleyes.configLogging(namespace[0])

        # Initialise sub-modules/packages. The
        # buildGui function is passed through
        # as a callback, which gets called when
        # initialisation is complete.
        initialise(splash, namespace[0], buildGui)

    def buildGui():

        # Now the main stuff - create the overlay
        # list and the master display context,
        # and then create the FSLeyesFrame.
        overlayList, displayCtx = makeDisplayContext(namespace[0], splash)
        app.SetOverlayListAndDisplayContext(overlayList, displayCtx)
        frame = makeFrame(namespace[0], displayCtx, overlayList, splash)

        app.SetTopWindow(frame)
        frame.Show()

        # Check that $FSLDIR is set, complain
        # to the user if it isn't
        if not namespace[0].skipfslcheck:
            wx.CallAfter(fslDirWarning, frame)

        # Check for updates. Ignore point
        # releases, otherwise users might
        # get swamped with update notifications.
        if namespace[0].updatecheck:
            import fsleyes.actions.updatecheck as updatecheck
            wx.CallAfter(updatecheck.UpdateCheckAction(),
                         showUpToDateMessage=False,
                         showErrorMessage=False,
                         ignorePoint=False)

    # Note: If no wx.Frame is created, the
    # wx.MainLoop call will exit immediately,
    # even if we have scheduled something via
    # wx.CallAfter. In this case, we have
    # already created the splash screen, so
    # all is well.
    wx.CallAfter(init, splash)
    app.MainLoop()
    shutdown()
    return exitCode[0]