예제 #1
0
def test_init():

    with mockCmaps() as (assetDir, sdir):
        fslcm.init()

        cmap1 = op.join(assetDir, 'colourmaps', 'cmap1.cmap')
        cmap2 = op.join(sdir,     'colourmaps', 'cmap2.cmap')
        lut1  = op.join(assetDir, 'luts',       'lut1.lut')
        lut2  = op.join(sdir,     'luts',       'lut2.lut')

        assert fslcm.getColourMaps() == ['cmap1', 'cmap2']
        assert fslcm.getColourMapLabel( 'cmap1') == 'cmap1'
        assert fslcm.getColourMapLabel( 'cmap2') == 'cmap2'
        assert fslcm.getColourMapFile(  'cmap1') == cmap1
        assert fslcm.getColourMapFile(  'cmap2') == cmap2
        assert fslcm.getLookupTableFile('lut1')  == lut1
        assert fslcm.getLookupTableFile('lut2')  == lut2

        assert fslcm.isColourMapInstalled(   'cmap1')
        assert fslcm.isColourMapInstalled(   'cmap2')
        assert fslcm.isColourMapRegistered(  'cmap1')
        assert fslcm.isColourMapRegistered(  'cmap2')
        assert fslcm.isLookupTableInstalled( 'lut1')
        assert fslcm.isLookupTableInstalled( 'lut2')
        assert fslcm.isLookupTableRegistered('lut1')
        assert fslcm.isLookupTableRegistered('lut2')

        luts = fslcm.getLookupTables()
        assert len(luts)              == 2
        assert luts[0].key            == 'lut1'
        assert luts[1].key            == 'lut2'
예제 #2
0
 def init():
     fsleyes.initialise()
     props.initGUI()
     colourmaps.init()
     initialised[0] = True
     fslgl.bootstrap(glver)
     wx.CallAfter(run)
예제 #3
0
def fsleyes_embed(parent=None, make_fsleyesframe=True, **kwargs):
    """Initialise FSLeyes and create a :class:`.FSLeyesFrame`, when
    running within another application.
    .. note:: If a ``wx.App`` does not exist, one is created.
    :arg parent: ``wx`` parent object
    :arg make_fsleyesframe: bool, default is True to make a new :class:`.FSLeyesFrame`
    :returns:    A tuple containing:
                    - The :class:`.OverlayList`
                    - The master :class:`.DisplayContext`
                    - The :class:`.FSLeyesFrame` or None if make_fsleyesframe=False
    All other arguments are passed to :meth:`.FSLeyesFrame.__init__`.
    """

    import fsleyes_props as props
    import fsleyes.gl as fslgl
    import fsleyes.frame as fslframe
    import fsleyes.overlay as fsloverlay
    import fsleyes.displaycontext as fsldc

    app = wx.GetApp()
    ownapp = app is None
    if ownapp:
        app = FSLeyesApp()

    fsleyes.initialise()
    colourmaps.init()
    props.initGUI()

    called = [False]
    ret = [None]

    def until():
        return called[0]

    def ready():
        frame = None
        fslgl.bootstrap()

        overlayList = fsloverlay.OverlayList()
        displayCtx = fsldc.DisplayContext(overlayList)
        if make_fsleyesframe:
            frame = fslframe.FSLeyesFrame(parent, overlayList, displayCtx,
                                          **kwargs)

        if ownapp:
            app.SetOverlayListAndDisplayContext(overlayList, displayCtx)
            # Keep a ref to prevent the app from being GC'd
            if make_fsleyesframe:
                frame._embed_app = app

        called[0] = True
        ret[0] = (overlayList, displayCtx, frame)

    fslgl.getGLContext(ready=ready, raiseErrors=True)
    idle.block(10, until=until)

    if ret[0] is None:
        raise RuntimeError('Failed to start FSLeyes')
    return ret[0]
예제 #4
0
def main(args=None):
    """Entry point for ``render``.

    Creates and renders an OpenGL scene, and saves it to a file, according
    to the specified command line arguments (which default to
    ``sys.argv[1:]``).
    """

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

    # Initialise FSLeyes and implement hacks.
    # This must come first as, amongst other
    # things, it sets the fsleyes.assetDir.
    fsleyes.initialise()

    # Initialise colour maps module
    fslcm.init()

    # Create a GL context
    fslgl.getGLContext(offscreen=True, createApp=True)

    # Now that GL inititalisation is over,
    # make sure that the idle loop executes
    # all tasks synchronously, instead of
    # trying to schedule them on the wx
    # event loop. And make sure image textures
    # don't use separate threads for data
    # processing.
    with idle.idleLoop.synchronous(), \
         imagetexture.ImageTexture.enableThreading(False):

        # Parse arguments, and
        # configure logging/debugging
        namespace = parseArgs(args)
        fsleyes.configLogging(namespace.verbose, namespace.noisy)

        # Initialise the fsleyes.gl modules
        fslgl.bootstrap(namespace.glversion)

        # Create a description of the scene
        overlayList, displayCtx, sceneOpts = makeDisplayContext(namespace)

        import matplotlib.image as mplimg

        # Render that scene, and save it to file
        bitmap, bg = render(namespace, overlayList, displayCtx, sceneOpts)

        if namespace.crop is not None:
            bitmap = autocrop(bitmap, bg, namespace.crop)
        mplimg.imsave(namespace.outfile, bitmap)
예제 #5
0
def main(args=None):
    """Entry point for ``render``.

    Creates and renders an OpenGL scene, and saves it to a file, according
    to the specified command line arguments (which default to
    ``sys.argv[1:]``).
    """

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

    # Initialise FSLeyes and implement hacks.
    # This must come first as, amongst other
    # things, it sets the fsleyes.assetDir.
    fsleyes.initialise()

    # Initialise colour maps module
    fslcm.init()

    # Create a GL context
    fslgl.getGLContext(offscreen=True, createApp=True)

    # Parse arguments, and
    # configure logging/debugging
    namespace = parseArgs(args)
    fsleyes.configLogging(namespace.verbose, namespace.noisy)

    # Initialise the fsleyes.gl modules
    fslgl.bootstrap(namespace.glversion)

    # Create a description of the scene
    overlayList, displayCtx, sceneOpts = makeDisplayContext(namespace)

    import matplotlib.image as mplimg

    # Render that scene, and save it to file
    bitmap, bg = render(namespace, overlayList, displayCtx, sceneOpts)

    if namespace.crop is not None:
        bitmap = autocrop(bitmap, bg, namespace.crop)
    mplimg.imsave(namespace.outfile, bitmap)
예제 #6
0
def test_register():

    cmap = tw.dedent("""
    0 0 0
    0 0 1
    0 1 1
    1 1 1
    """).strip()

    lut = tw.dedent("""
    1 0 0 0 label 1
    2 0 0 1 label 2
    3 0 1 1 label 3
    4 1 1 1 label 4
    """).strip()

    with mockCmaps() as (assetDir, sdir):
        fslcm.init()

        with open('cmap.txt', 'wt') as f: f.write(cmap)
        with open('lut.txt',  'wt') as f: f.write(lut)

        assert not fslcm.isColourMapRegistered('mycmap')
        fslcm.registerColourMap('cmap.txt', key='mycmap', name='My cmap')
        fslcm.getColourMap('mycmap')
        assert     fslcm.isColourMapRegistered('mycmap')
        assert not fslcm.isColourMapInstalled( 'mycmap')
        assert     fslcm.getColourMapLabel('mycmap') == 'My cmap'
        fslcm.installColourMap('mycmap')
        assert     fslcm.isColourMapInstalled( 'mycmap')

        assert not fslcm.isLookupTableRegistered('mylut')
        fslcm.registerLookupTable('lut.txt', key='mylut', name='My lut')
        assert     fslcm.isLookupTableRegistered('mylut')
        assert not fslcm.isLookupTableInstalled( 'mylut')
        assert     fslcm.getLookupTable('mylut').name == 'My lut'
        fslcm.installLookupTable('mylut')
        assert     fslcm.isLookupTableInstalled( 'mylut')
예제 #7
0
def main(args=None):
    """Entry point for ``render``.

    Creates and renders an OpenGL scene, and saves it to a file, according
    to the specified command line arguments (which default to
    ``sys.argv[1:]``).
    """

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

    # Create a GL context
    fslgl.getGLContext(offscreen=True, createApp=True)

    # Initialise FSLeyes and implement hacks
    fsleyes.initialise()
    fsleyesmain.hacksAndWorkarounds()

    # Initialise colour maps module
    fslcm.init()

    # Parse arguments, and
    # configure logging/debugging
    namespace = parseArgs(args)
    fsleyes.configLogging(namespace)

    # Initialise the fsleyes.gl modules
    fslgl.bootstrap(namespace.glversion)

    # Create a description of the scene
    overlayList, displayCtx, sceneOpts = makeDisplayContext(namespace)

    import matplotlib.image as mplimg

    # Render that scene, and save it to file
    bitmap = render(namespace, overlayList, displayCtx, sceneOpts)
    mplimg.imsave(namespace.outfile, bitmap)
예제 #8
0
def embed(parent, callback=None, **kwargs):
    """Initialise FSLeyes and create a :class:`.FSLeyesFrame`, when
    running within another application.

    :arg parent:   ``wx`` parent object
    :arg callback: A function which will be called when FSLeyes
                   is ready. Must accept three positional arguments:
                     - The :class:`.OverlayList`
                     - The master :class:`.DisplayContext`
                     - The :class:`.FSLeyesFrame`

    All other arguments are passed to :meth:`.FSLeyesFrame.__init__`.
    """

    import fsleyes_props          as props
    import fsleyes.gl             as fslgl
    import fsleyes.frame          as fslframe
    import fsleyes.overlay        as fsloverlay
    import fsleyes.displaycontext as fsldc

    fsleyes.initialise()
    colourmaps.init()
    props.initGUI()

    def ready():
        fslgl.bootstrap()

        overlayList = fsloverlay.OverlayList()
        displayCtx  = fsldc.DisplayContext(overlayList)

        frame = fslframe.FSLeyesFrame(
            parent, overlayList, displayCtx, **kwargs)

        if callback is not None:
            callback(overlayList, displayCtx, frame)

    fslgl.getGLContext(parent=parent, ready=ready)
예제 #9
0
def embed(mkFrame=True, **kwargs):
    """Initialise FSLeyes and create a :class:`.FSLeyesFrame`, when
    running within another application.

    .. note:: In most cases, this function must be called from the
              ``wx.MainLoop``.

    :arg mkFrame: Defaults to ``True``. If ``False``, FSLeyes is
                  initialised, but a :class:`.FSLeyesFrame` is not created.
                  If you set this to ``False``, you must ensure that a
                  ``wx.App`` object exists before calling this function.

    :returns:     A tuple containing:

                   - The :class:`.OverlayList`
                   - The master :class:`.DisplayContext`
                   - The :class:`.FSLeyesFrame` (or ``None``, if
                     ``makeFrame is False``).

    All other arguments are passed to :meth:`.FSLeyesFrame.__init__`.
    """

    import fsleyes_props as props
    import fsleyes.gl as fslgl
    import fsleyes.frame as fslframe
    import fsleyes.overlay as fsloverlay
    import fsleyes.displaycontext as fsldc

    # initialise must be called before
    # a FSLeyesApp gets created, as it
    # tries to access app_icon.png
    fsleyes.initialise()

    app = wx.GetApp()
    ownapp = app is None

    if ownapp and (mkFrame is False):
        raise RuntimeError('If mkFrame is False, you '
                           'must create a wx.App before '
                           'calling fsleyes.main.embed')
    if ownapp:
        app = FSLeyesApp()

    colourmaps.init()
    props.initGUI()

    called = [False]
    ret = [None]

    def until():
        return called[0]

    def ready():
        fslgl.bootstrap()

        overlayList = fsloverlay.OverlayList()
        displayCtx = fsldc.DisplayContext(overlayList)

        if mkFrame:
            frame = fslframe.FSLeyesFrame(None, overlayList, displayCtx,
                                          **kwargs)
        else:
            frame = None

        if ownapp:
            app.SetOverlayListAndDisplayContext(overlayList, displayCtx)
            # Keep a ref to prevent the app from being GC'd
            frame._embed_app = app

        called[0] = True
        ret[0] = (overlayList, displayCtx, frame)

    fslgl.getGLContext(ready=ready, raiseErrors=True)
    idle.block(10, until=until)

    if ret[0] is None:
        raise RuntimeError('Failed to start FSLeyes')
    return ret[0]
예제 #10
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]
예제 #11
0
파일: main.py 프로젝트: neurodebian/fsleyes
def initialise(splash, namespace, callback):
    """Called by :func:`main`. Bootstraps/Initialises various parts of
    *FSLeyes*.

    The ``callback`` function is asynchronously called when the initialisation
    is complete.

    :arg splash:    The :class:`.FSLeyesSplash` screen.

    :arg namespace: The ``argparse.Namespace`` object containing parsed
                    command line arguments.

    :arg callback:  Function which is called when initialisation is done.
    """

    import fsl.utils.settings as fslsettings
    import fsleyes_props as props
    import fsleyes.gl as fslgl
    import fsleyes.colourmaps as colourmaps

    props.initGUI()

    colourmaps.init()

    # The save/load directory defaults
    # to the current working directory.
    curDir = op.normpath(os.getcwd())

    # But if we are running as a frozen application, check to
    # see if FSLeyes has been started by the system (e.g.
    # double-clicking instead of being called from the CLI).
    #
    # If so, we set the save/load directory
    # to the user's home directory instead.
    if fslplatform.frozen:

        fsleyesDir = op.dirname(__file__)

        # If we're a frozen OSX application,
        # we need to adjust the FSLeyes dir
        # (which will be:
        #   [install_dir]/FSLeyes.app/Contents/MacOS/fsleyes/),
        #
        # Because the cwd will default to:
        #   [install_dir/

        if fslplatform.os == 'Darwin':

            fsleyesDir = op.normpath(
                op.join(fsleyesDir, '..', '..', '..', '..'))

        # Similar adjustment for linux
        elif fslplatform.os == 'Linux':
            fsleyesDir = op.normpath(op.join(fsleyesDir, '..'))

        if curDir == fsleyesDir:
            curDir = op.expanduser('~')

    fslsettings.write('loadSaveOverlayDir', curDir)

    # Initialise silly things
    if namespace.bumMode:
        import fsleyes.controls.orthotoolbar as ot
        import fsleyes.controls.lightboxtoolbar as lbt
        ot.BUM_MODE = True
        lbt.BUM_MODE = True

    # This is called by fsleyes.gl.getGLContext
    # when the GL context is ready to be used.
    def realCallback():
        fslgl.bootstrap(namespace.glversion)
        callback()

    try:
        # Force the creation of a wx.glcanvas.GLContext object,
        # and initialise OpenGL version-specific module loads.
        # The splash screen is used as the parent of the dummy
        # canvas created by the gl.getWXGLContext function.
        fslgl.getGLContext(parent=splash, ready=realCallback)

    except:
        log.error('Unable to initialise OpenGL!', exc_info=True)
        splash.Destroy()
        sys.exit(1)