def makeDisplayContext(namespace, splash): """Creates the top-level *FSLeyes* :class:`.DisplayContext` and :class:`.OverlayList` . This function does the following: 1. Creates the :class:`.OverlayList` and the top level :class:`.DisplayContext`. 2. Loads and configures all of the overlays which were passed in on the command line. :arg namesace: Parsed command line arguments (see :func:`parseArgs`). :arg splash: The :class:`.FSLeyesSplash` frame, created in :func:`init`. :returns: a tuple containing: - the :class:`.OverlayList` - the master :class:`.DisplayContext` """ import fsleyes_widgets.utils.status as status import fsleyes.overlay as fsloverlay import fsleyes.parseargs as parseargs import fsleyes.displaycontext as displaycontext # Splash status update must be # performed on the main thread. def splashStatus(msg): wx.CallAfter(splash.SetStatus, msg) # Redirect status updates # to the splash frame status.setTarget(splashStatus) # Create the overlay list (only one of these # ever exists) and the master DisplayContext. # A new DisplayContext instance will be # created for every new view that is opened # in the FSLeyesFrame, but all child # DisplayContext instances will be linked to # this master one. overlayList = fsloverlay.OverlayList() displayCtx = displaycontext.DisplayContext(overlayList) log.debug('Created overlay list and master DisplayContext ({})'.format( id(displayCtx))) # Load the images - the splash screen status will # be updated with the currently loading overlay name. parseargs.applyMainArgs(namespace, overlayList, displayCtx) parseargs.applyOverlayArgs(namespace, overlayList, displayCtx) return overlayList, displayCtx
def test_clearStatus(): target = MockTarget() status.setTarget(target) status.update('Status1', None) assert target.msg == 'Status1' status.clearStatus() assert target.msg == '' status.update('Status1', 0.25) assert target.msg == 'Status1' status.clearStatus() assert target.msg == ''
def test_update(): # Test without a target status.setTarget(None) status.update('Status') target = MockTarget() status.setTarget(target) assert target.msg is None status.update('Status1', None) assert target.msg == 'Status1' status.update('Status2', None) assert target.msg == 'Status2'
def test_ClearThread_die(): target = MockTarget() status.setTarget(target) # make sure the clearthread is running status.update('Status1', 1.0) time.sleep(1.1) # and can be killed status._clearThread.die() status._clearThread.clear(0.1) status._clearThread.join() status._clearThread = None # and then gets restarted again status.update('Status1', 0.25) assert target.msg == 'Status1' time.sleep(0.5) assert target.msg == ''
def test_update_timeout(): status.setTarget(None) status.clearStatus() target = MockTarget() status.setTarget(target) # Test that the message gets cleared status.update('Status1', 0.25) assert target.msg == 'Status1' time.sleep(0.5) assert target.msg == '' # If a timed update is followed by an untimed # update, the untimed one should persist status.update('Status2', 0.25) status.update('Status3', None) time.sleep(0.5) assert target.msg == 'Status3'
def run_with_fsleyes(func, *args, **kwargs): """Create a ``FSLeyesFrame`` and run the given function. """ from fsl.utils.platform import platform as fslplatform import fsleyes_widgets.utils.status as status fsleyes.configLogging() gc.collect() idle.idleLoop.reset() idle.idleLoop.allowErrors = True propagateRaise = kwargs.pop('propagateRaise', True) startingDelay = kwargs.pop('startingDelay', 500) finishingDelay = kwargs.pop('finishingDelay', 5) callAfterApp = kwargs.pop('callAfterApp', None) class State(object): pass state = State() state.result = None state.raised = None state.frame = None state.app = None state.dummy = None state.panel = None glver = os.environ.get('FSLEYES_TEST_GL', '2.1') glver = [int(v) for v in glver.split('.')] def init(): fsleyes.initialise() props.initGUI() colourmaps.init() initialised[0] = True fslgl.bootstrap(glver) wx.CallAfter(run) def finish(): state.frame.Close(askUnsaved=False, askLayout=False) state.dummy.Close() waitUntilIdle() realYield(100) state.app.ExitMainLoop() def run(): overlayList = fsloverlay.OverlayList() displayCtx = dc.DisplayContext(overlayList) state.frame = fslframe.FSLeyesFrame(None, overlayList, displayCtx) state.app.SetOverlayListAndDisplayContext(overlayList, displayCtx) state.app.SetTopWindow(state.frame) state.frame.Show() try: if func is not None: state.result = func(state.frame, overlayList, displayCtx, *args, **kwargs) except Exception as e: traceback.print_exc() state.raised = e finally: wx.CallLater(finishingDelay, finish) state.app = fslmain.FSLeyesApp() state.dummy = wx.Frame(None) state.panel = wx.Panel(state.dummy) state.sizer = wx.BoxSizer(wx.HORIZONTAL) state.sizer.Add(state.panel, flag=wx.EXPAND, proportion=1) state.dummy.SetSizer(state.sizer) if callAfterApp is not None: callAfterApp() state.dummy.SetSize((100, 100)) state.dummy.Layout() state.dummy.Show() if not initialised[0]: # gl already initialised if fslplatform.glVersion is not None: wx.CallLater(startingDelay, init) else: wx.CallLater(startingDelay, fslgl.getGLContext, ready=init, raiseErrors=True) else: wx.CallLater(startingDelay, run) with exitMainLoopOnError(state.app) as err: state.app.MainLoop() status.setTarget(None) if status._clearThread is not None: status._clearThread.die() status._clearThread.clear(0.01) status._clearThread.join() status._clearThread = None raised = state.raised result = state.result if err[0] is not None: raise err[0] time.sleep(1) if raised and propagateRaise: raise raised return result
def makeDisplayContext(namespace, splash): """Creates the top-level *FSLeyes* :class:`.DisplayContext` and :class:`.OverlayList` . This function does the following: 1. Creates the :class:`.OverlayList` and the top level :class:`.DisplayContext`. 2. Loads and configures all of the overlays which were passed in on the command line. :arg namesace: Parsed command line arguments (see :func:`parseArgs`). :arg splash: The :class:`.FSLeyesSplash` frame, created in :func:`init`. :returns: a tuple containing: - the :class:`.OverlayList` - the master :class:`.DisplayContext` """ import fsleyes_widgets.utils.status as status import fsleyes.overlay as fsloverlay import fsleyes.parseargs as parseargs import fsleyes.displaycontext as displaycontext # Splash status update must be # performed on the main thread. def splashStatus(msg): wx.CallAfter(splash.SetStatus, msg) # Redirect status updates # to the splash frame status.setTarget(splashStatus) # Create the overlay list (only one of these # ever exists) and the master DisplayContext. # A new DisplayContext instance will be # created for every new view that is opened # in the FSLeyesFrame, but all child # DisplayContext instances will be linked to # this master one. overlayList = fsloverlay.OverlayList() displayCtx = displaycontext.DisplayContext(overlayList) # While the DisplayContext may refer to # multiple overlay groups, we are currently # using just one, allowing the user to specify # a set of overlays for which their display # properties are 'locked'. lockGroup = displaycontext.OverlayGroup(displayCtx, overlayList) displayCtx.overlayGroups.append(lockGroup) log.debug('Created overlay list and master DisplayContext ({})'.format( id(displayCtx))) # Load the images - the splash screen status will # be updated with the currently loading overlay name. # # The applyOverlayArgs function gets called before # the applySceneArgs function, so we'll manually # apply some important settings to the DC here so # they get used when any overlays are loaded. if namespace.bigmem is not None: displayCtx.loadInMemory = namespace.bigmem if namespace.autoDisplay is not None: displayCtx.autoDisplay = namespace.autoDisplay parseargs.applyOverlayArgs(namespace, overlayList, displayCtx) return overlayList, displayCtx