Example #1
0
    def __init__(self, parent, overlayList, displayCtx, frame):
        """Create a ``LightBoxPanel``.

        :arg parent:      A :mod:`wx` parent object.
        :arg overlayList: A :class:`.OverlayList` instance.
        :arg displayCtx:  A :class:`.DisplayContext` instance.
        :arg frame:       The :class:`.FSLeyesFrame` instance.
        """

        sceneOpts = lightboxopts.LightBoxOpts(self)

        canvaspanel.CanvasPanel.__init__(self, parent, overlayList, displayCtx,
                                         frame, sceneOpts)

        self.__scrollbar = wx.ScrollBar(self.centrePanel, style=wx.SB_VERTICAL)
        self.__lbCanvas = lightboxcanvas.WXGLLightBoxCanvas(
            self.contentPanel, overlayList, displayCtx)

        lbopts = self.__lbCanvas.opts

        lbopts.bindProps('pos', displayCtx, 'location')
        lbopts.bindProps('zax', sceneOpts)
        lbopts.bindProps('bgColour', sceneOpts)
        lbopts.bindProps('cursorColour', sceneOpts)
        lbopts.bindProps('showCursor', sceneOpts)
        lbopts.bindProps('showGridLines', sceneOpts)
        lbopts.bindProps('highlightSlice', sceneOpts)
        lbopts.bindProps('renderMode', sceneOpts)
        lbopts.bindProps('highDpi', sceneOpts)

        # Bind these properties the other way around,
        # so that the sensible values calcualted by
        # the LBCanvas during its initialisation are
        # propagated to the LBOpts instance, rather
        # than the non-sensible default values in the
        # LBOpts instance.
        sceneOpts.bindProps('nrows', lbopts)
        sceneOpts.bindProps('ncols', lbopts)
        sceneOpts.bindProps('topRow', lbopts)
        sceneOpts.bindProps('sliceSpacing', lbopts)
        sceneOpts.bindProps('zrange', lbopts)

        self.__canvasSizer = wx.BoxSizer(wx.HORIZONTAL)
        self.contentPanel.SetSizer(self.__canvasSizer)

        self.__canvasSizer.Add(self.__lbCanvas, flag=wx.EXPAND, proportion=1)

        self.displayCtx.addListener('selectedOverlay', self.name,
                                    self.__selectedOverlayChanged)
        self.displayCtx.addListener('displaySpace', self.name,
                                    self.__radioOrientationChanged)
        self.displayCtx.addListener('radioOrientation', self.name,
                                    self.__radioOrientationChanged)
        self.overlayList.addListener('overlays', self.name,
                                     self.__selectedOverlayChanged)

        # When any lightbox properties change,
        # make sure the scrollbar is updated
        sceneOpts.addListener('ncols', self.name, self.__ncolsChanged)
        sceneOpts.addListener('nrows', self.name, self.__onLightBoxChange)
        sceneOpts.addListener('topRow', self.name, self.__onLightBoxChange)
        sceneOpts.addListener('sliceSpacing', self.name,
                              self.__onLightBoxChange)
        sceneOpts.addListener('zrange', self.name, self.__onLightBoxChange)
        sceneOpts.addListener('zax', self.name, self.__onLightBoxChange)
        sceneOpts.addListener('zoom', self.name, self.__onZoom)

        # When the scrollbar is moved,
        # update the canvas display
        self.__scrollbar.Bind(wx.EVT_SCROLL, self.__onScroll)

        self.Bind(wx.EVT_SIZE, self.__onResize)

        sceneOpts.zoom = 750

        self.__onLightBoxChange()
        self.__onZoom()

        self.__selectedOverlayChanged()
        self.centrePanelLayout()
        self.initProfile()
Example #2
0
def makeDisplayContext(namespace):
    """Creates :class:`.OverlayList`, :class:`.DisplayContext``, and
    :class:`.SceneOpts` instances which represent the scene to be rendered,
    as described by the arguments in the given ``namespace`` object.
    """

    # Create an overlay list and display context.
    # The DisplayContext, Display and DisplayOpts
    # classes are designed to be created in a
    # parent-child hierarchy. So we need to create
    # a 'dummy' master display context to make
    # things work properly.
    overlayList = fsloverlay.OverlayList()
    masterDisplayCtx = displaycontext.DisplayContext(overlayList)
    childDisplayCtx = displaycontext.DisplayContext(overlayList,
                                                    parent=masterDisplayCtx)

    # We have to artificially create a ref to the
    # master display context, otherwise it may get
    # gc'd arbitrarily. The parent reference in the
    # child creation above is ultimately stored as
    # a weakref, so we need to create a real one.
    childDisplayCtx.masterDisplayCtx = masterDisplayCtx

    # The handleOverlayArgs function uses the
    # fsleyes.overlay.loadOverlays function,
    # which will call these functions as it
    # goes through the list of overlay to be
    # loaded.
    def load(ovl):
        log.info('Loading overlay {} ...'.format(ovl))

    def error(ovl, error):
        log.info('Error loading overlay {}: '.format(ovl, error))

    # Load the overlays specified on the command
    # line, and configure their display properties
    parseargs.applyOverlayArgs(namespace,
                               overlayList,
                               masterDisplayCtx,
                               loadFunc=load,
                               errorFunc=error)

    # Create a SceneOpts instance describing
    # the scene to be rendered. The parseargs
    # module assumes that GL canvases have
    # already been created, so we use mock
    # objects to trick it. The options applied
    # to these mock objects are applied to the
    # real canvases later on, in the render
    # function below.
    if namespace.scene == 'ortho':
        sceneOpts = orthoopts.OrthoOpts(MockCanvasPanel(3))
    elif namespace.scene == 'lightbox':
        sceneOpts = lightboxopts.LightBoxOpts(MockCanvasPanel(1))
    elif namespace.scene == '3d':
        sceneOpts = scene3dopts.Scene3DOpts(MockCanvasPanel(1))

    # 3D views default to
    # world display space
    if namespace.scene == '3d':
        childDisplayCtx.displaySpace = 'world'

    parseargs.applySceneArgs(namespace, overlayList, childDisplayCtx,
                             sceneOpts)

    # Centre the location. The DisplayContext
    # will typically centre its location on
    # initialisation, but this may not work
    # if any overlay arguments change the bounds
    # of an overlay (e.g. mesh reference image)
    if namespace.worldLoc is None and namespace.voxelLoc is None:
        b = childDisplayCtx.bounds
        childDisplayCtx.location = [
            b.xlo + 0.5 * b.xlen, b.ylo + 0.5 * b.ylen, b.zlo + 0.5 * b.zlen
        ]

    # This has to be applied after applySceneArgs,
    # in case the user used the '-std'/'-std1mm'
    # options.
    if namespace.selectedOverlay is not None:
        masterDisplayCtx.selectedOverlay = namespace.selectedOverlay

    if len(overlayList) == 0:
        raise RuntimeError('At least one overlay must be specified')

    return overlayList, childDisplayCtx, sceneOpts