Ejemplo n.º 1
0
    def __applyCommandLineArgs(self):
        """Called when this action is executed. Prompts the user to enter
        some command line arguments, and then passes them to the
        :func:`applyCommandLineArgs` function.
        """

        # prompt user for some arguments
        dlg = fsldlg.TextEditDialog(self.__panel,
                                    strings.titles[self, 'title'],
                                    strings.messages[self, 'apply'],
                                    style=fsldlg.TED_MULTILINE
                                    | fsldlg.TED_OK_CANCEL)

        dlg.CentreOnParent()

        if dlg.ShowModal() != wx.ID_OK:
            return

        # Pass GetText through str, because it
        # returns a unicode string, and python's
        # argparse does not seem to like unicode.
        argv = str(dlg.GetText()).split()
        errTitle = strings.titles[self, 'error']
        errMsg = strings.messages[self, 'error']

        # apply said arguments
        with status.reportIfError(errTitle, errMsg):
            applyCommandLineArgs(self.__overlayList, self.__displayCtx, argv,
                                 self.__panel)
Ejemplo n.º 2
0
    def __loadVertexData(self):
        """Called when this action is executed. Prompts the user to load
        some vertex data for the currently selected :class:`.TriangleMesh`
        overlay, then sets the :attr:`.MeshOpts.vertexData` property
        accordingly. If the file was successfully loaded, also adds the
        loaded file as an option on the :attr:`.MeshOpts.vertexData`
        property.
        """

        import wx

        app     = wx.GetApp()
        overlay = self.__displayCtx.getSelectedOverlay()
        fromDir = op.dirname(overlay.dataSource)

        msg = strings.messages[self, 'loadVertexData'].format(overlay.name)
        dlg = wx.FileDialog(app.GetTopWindow(),
                            message=msg,
                            defaultDir=fromDir,
                            wildcard='*.*',
                            style=wx.FD_OPEN)

        if dlg.ShowModal() != wx.ID_OK:
            return

        path     = dlg.GetPath()
        errtitle = strings.titles[  self, 'error']
        errmsg   = strings.messages[self, 'error'].format(overlay.name)

        with status.reportIfError(errtitle, errmsg):
            loadVertexData(overlay, self.__displayCtx, path)
Ejemplo n.º 3
0
    def __onSaveButton(self, ev):
        """Called when the user pushe the *Save labels* button. Asks the user
        where they'd like the label saved, then saves said labels.
        """

        overlay   = self.displayCtx.getSelectedOverlay()
        volLabels = self.overlayList.getData(overlay, 'VolumeLabels')

        if isinstance(overlay, fslmelimage.MelodicImage):
            defaultDir = overlay.getMelodicDir()
        elif overlay.dataSource is not None:
            defaultDir = op.dirname(overlay.dataSource)
        else:
            defaultDir = None

        dlg = wx.FileDialog(
            self,
            message=strings.titles[self, 'saveDialog'],
            defaultDir=defaultDir,
            style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT)

        if dlg.ShowModal() != wx.ID_OK:
            return

        filename = dlg.GetPath()
        emsg     = strings.messages[self, 'saveError'].format(filename)
        etitle   = strings.titles[  self, 'saveError']

        with status.reportIfError(msg=emsg, title=etitle, raiseError=False):
            volLabels.save(filename, dirname=defaultDir)
Ejemplo n.º 4
0
def loadAtlas(parent=None):
    """Prompts the user to select an atlas specification file, and then
    loads the atlas.
    """

    import wx
    app = wx.GetApp()

    if parent is None:
        parent = app.GetTopWindow()

    msg = strings.titles[LoadAtlasAction, 'fileDialog']
    dlg = wx.FileDialog(parent,
                        message=msg,
                        wildcard='XML atlas specification|*.xml',
                        style=wx.FD_OPEN)

    if dlg.ShowModal() != wx.ID_OK:
        return

    path     = dlg.GetPath()
    errtitle = strings.titles[  LoadAtlasAction, 'error']
    errmsg   = strings.messages[LoadAtlasAction, 'error'].format(path)

    with status.reportIfError(errtitle, errmsg):
        atlases.addAtlas(path)
Ejemplo n.º 5
0
    def __loadit(self, key, func):
        """Shared by the :meth:`__loadVertices` and :meth:`__loadVertexData`
        methods.
        """

        import wx

        app = wx.GetApp()
        overlay = self.__displayCtx.getSelectedOverlay()
        fromDir = op.dirname(overlay.dataSource)

        msg = strings.messages[self, key].format(overlay.name)
        dlg = wx.FileDialog(app.GetTopWindow(),
                            message=msg,
                            defaultDir=fromDir,
                            wildcard='*.*',
                            style=wx.FD_OPEN)

        if dlg.ShowModal() != wx.ID_OK:
            return

        path = dlg.GetPath()
        errtitle = strings.titles[self, 'error']
        errmsg = strings.messages[self, 'error'].format(overlay.name)

        with status.reportIfError(errtitle, errmsg, raiseError=False):
            func(overlay, self.__displayCtx, path)
Ejemplo n.º 6
0
    def __saveFlirtXfm(self):
        """Called when this action is executed. Prompts the user to save
        a FLIRT transform for the currently selected image.
        """

        displayCtx = self.displayCtx
        overlayList = self.overlayList
        overlay = displayCtx.getSelectedOverlay()

        affType, matFile, refFile = applyflirtxfm.promptForFlirtFiles(
            self.__frame, overlay, overlayList, displayCtx, save=True)

        if all((affType is None, matFile is None, refFile is None)):
            return

        if affType == 'flirt':
            xform = calculateTransform(overlay, overlayList, displayCtx,
                                       refFile)
        else:
            xform = overlay.voxToWorldMat

        errtitle = strings.titles[self, 'error']
        errmsg = strings.messages[self, 'error']

        with status.reportIfError(errtitle, errmsg):
            np.savetxt(matFile, xform, fmt='%0.10f')
Ejemplo n.º 7
0
    def __checkForUpdates(self,
                          showUpToDateMessage=True,
                          showErrorMessage=True,
                          ignorePoint=False):
        """Run this action. Downloads a text file from a URL which contains
        the latest available version of FSLeyes. Compares that version with
        the running version. Displays a message to the user.

        :arg showUpToDateMessage: Defaults to ``True``. If ``False``, and
                                  the current version of FSLeyes is up to
                                  date, the user is not informed.

        :arg showErrorMessage:    Defaults to ``True``. If ``False``, and
                                  some error occurs while checking for
                                  updates, the user is not informed.

        :arg ignorePoint:         Defaults to ``False``. If ``True``, the
                                  point release number is ignored in the
                                  comparison.
        """

        errMsg = strings.messages[self, 'newVersionError']
        errTitle = strings.titles[self, 'newVersionError']

        with status.reportIfError(errTitle, errMsg, report=showErrorMessage):

            log.debug('Checking for FSLeyes updates ({})'.format(
                _FSLEYES_VERSION_URL))

            f = request.urlopen(_FSLEYES_VERSION_URL)
            latest = f.read().decode('utf-8').strip()
            current = version.__version__
            upToDate = fslversion.compareVersions(latest, current,
                                                  ignorePoint) <= 0

            log.debug('This version of FSLeyes ({}) is '
                      '{} date (latest: {})'.format(
                          current, 'up to' if upToDate else 'out of', latest))

            if upToDate and not showUpToDateMessage:
                return

            urlMsg = strings.messages[self, 'updateUrl']

            if upToDate:
                title = strings.titles[self, 'upToDate']
                msg = strings.messages[self, 'upToDate']
                msg = msg.format(current)

            else:
                title = strings.titles[self, 'newVersionAvailable']
                msg = strings.messages[self, 'newVersionAvailable']
                msg = msg.format(current, latest, _FSLEYES_URL)

            parent = wx.GetTopLevelWindows()[0]
            dlg = UrlDialog(parent, title, msg, urlMsg, _FSLEYES_URL)

            dlg.CentreOnParent()
            dlg.ShowModal()
Ejemplo n.º 8
0
 def __onSaveLut(self, ev):
     """Called when the user presses the *Save LUT* button. Makes sure
     that the current :class:`LookupTable` is saved (see the
     :func:`.colourmaps.installLookupTable` function).
     """
     etitle = strings.titles[self, 'installerror']
     emsg = strings.messages[self, 'installerror']
     with status.reportIfError(title=etitle, msg=emsg, raiseError=False):
         fslcmaps.installLookupTable(self.__selectedLut.key)
Ejemplo n.º 9
0
def test_reportIfError_error_noraise():

    title = 'title'
    msg = 'msg'
    exc = Exception()

    # report=True
    with mock.patch('fsleyes_widgets.utils.status.reportError') as reperr:
        with status.reportIfError(title, msg, raiseError=False):
            raise exc
        reperr.assert_called_once_with(title, msg, exc)

    # report=False
    with mock.patch('fsleyes_widgets.utils.status.reportError') as reperr, \
         mock.patch('fsleyes_widgets.utils.status.log.error') as log:
        with status.reportIfError(title, msg, raiseError=False, report=False):
            raise exc
        reperr.assert_not_called()
        log.assert_called_once()
Ejemplo n.º 10
0
    def __onLoadLut(self, ev):
        """Called when the user presses the *Load LUT* button.  Does the
        following:

          - Prompts the user to select a LUT file with a ``wx.FileDialog``

          - Prompts the user to enter a name for the LUT via the
            :func:`promptForLutName` function.

          - Creates and registers a new :class:`.LookupTable` instance,
            initialising it with the selected file.

          - Updates this ``LookupTablePanel`` via the
            :meth:`__updateLutChoices` and :meth:`__setLut` methods.
        """

        parent = wx.GetApp().GetTopWindow()
        loadDir = fslsettings.read('fsleyes.loadlutdir', os.getcwd())

        # Prompt the user to select a lut file
        fileDlg = wx.FileDialog(parent,
                                defaultDir=loadDir,
                                message=strings.titles[self, 'loadLut'],
                                style=wx.FD_OPEN)

        if fileDlg.ShowModal() != wx.ID_OK:
            return

        lutFile = fileDlg.GetPath()
        lutDir = op.dirname(lutFile)
        lutName = op.splitext(op.basename(lutFile))[0]

        # Prompt the user to enter a name
        lutKey, lutName = promptForLutName(lutName)
        if lutKey is None:
            return

        # Register the lut
        errTitle = strings.titles[self, 'loadError']
        errMsg = strings.messages[self, 'loadError'].format(lutFile)
        with status.reportIfError(errTitle, errMsg):
            lut = fslcmaps.registerLookupTable(lutFile,
                                               self.overlayList,
                                               self.displayCtx,
                                               key=lutKey,
                                               name=lutName)

        # Save the directory for next time
        fslsettings.write('fsleyes.loadlutdir', lutDir)

        # Select the lut in the panel
        self.__updateLutChoices()
        self.__setLut(lut)
Ejemplo n.º 11
0
def doSave(overlay, path=None):
    """Called by :func:`saveOverlay`.  Tries to save the given ``overlay`` to
    the given ``path``, and shows an error message if something goes wrong.
    Returns ``True`` if the save was successful, ``False`` otherwise.
    """

    emsg = strings.messages['SaveOverlayAction.saveError'].format(path)
    etitle = strings.titles['SaveOverlayAction.saveError']

    with status.reportIfError(msg=emsg, title=etitle, raiseError=False):
        overlay.save(path)
        return True

    return False
Ejemplo n.º 12
0
    def __loadPlugin(self, *args, **kwargs):
        """Prompts the user to select a plugin file, asks them whether they
        would like to install it permanently, and then passes it to either
        :func:`.loadPlugin` or :func:`.installPlugin`.
        """

        lastDir = fslsettings.read('loadPluginLastDir')

        if lastDir is None:
            lastDir = os.getcwd()

        msg = strings.messages[self, 'loadPlugin']
        dlg = wx.FileDialog(self.__frame,
                            message=msg,
                            defaultDir=lastDir,
                            wildcard='*.py',
                            style=wx.FD_OPEN)

        if dlg.ShowModal() != wx.ID_OK:
            return

        fname = dlg.GetPath()

        fslsettings.write('loadPluginLastDir', op.dirname(fname))

        dlg = wx.MessageDialog(self.__frame,
                               caption=strings.titles[self, 'installPlugin'],
                               message=strings.messages[self, 'installPlugin'],
                               style=wx.YES_NO | wx.CANCEL)

        result = dlg.ShowModal()

        if result == wx.ID_YES:
            etitle = strings.titles[self, 'installError']
            emsg = strings.messages[self, 'installError']
            func = plugins.installPlugin
        elif result == wx.ID_NO:
            etitle = strings.titles[self, 'loadError']
            emsg = strings.messages[self, 'loadError']
            func = plugins.loadPlugin
        else:
            return

        with status.reportIfError(title=etitle, msg=emsg, raiseError=False):
            func(fname)

        self.__frame.refreshViewMenu()
        self.__frame.refreshToolsMenu()
        self.__frame.refreshSettingsMenu()
Ejemplo n.º 13
0
    def __openNotebooks(self, nbfile=None):
        """Called when this ``NotebookAction`` is invoked. Starts the
        server and kernel if necessary.

        If the server/kernel have not yet been started and ``nbfile`` is
        provided, the server will be started with ``nbfile`` opened.
        """

        # If the kernel and server are both
        # ok, open the notebook homepage
        if self.__kernel is not None and \
           self.__server is not None and \
           self.__kernel.is_alive()  and \
           self.__server.is_alive():
            webbrowser.open(self.__server.url)
            return

        # have the kernel or server threads crashed?
        if self.__kernel is not None and not self.__kernel.is_alive():
            self.__kernel = None
        if self.__server is not None and not self.__server.is_alive():
            self.__server = None

        # show a progress dialog if we need
        # to initialise the kernel or server
        if self.__kernel is None or self.__server is None:
            title = strings.titles[self, 'init']
            progdlg = progress.Bounce(title)
        else:
            progdlg = None

        try:
            # start the kernel/server, and show
            # an error if something goes wrong
            errt = strings.titles[self, 'init.error']
            errm = strings.messages[self, 'init.error']
            with status.reportIfError(errt, errm):
                if self.__kernel is None:
                    self.__kernel = self.__startKernel(progdlg)
                if self.__server is None:
                    self.__server = self.__startServer(progdlg, nbfile)

        finally:
            if progdlg is not None:
                progdlg.Destroy()
                progdlg = None
Ejemplo n.º 14
0
    def __onSave(self, ev):
        """Called when the Save button is pushed. Saves the current crop
        parameters to a text file.
        """

        overlay  = self.__overlay
        cropBox  = self.__profile.cropBox
        fileName = '{}_crop.txt'.format(overlay.name)

        if overlay.dataSource is not None:
            dirName = op.dirname(overlay.dataSource)
        else:
            dirName = os.getcwd()

        dlg = wx.FileDialog(
            self,
            defaultDir=dirName,
            defaultFile=fileName,
            message=strings.messages[self, 'saveCrop'],
            style=wx.FD_SAVE)

        if dlg.ShowModal() != wx.ID_OK:
            return

        filePath = dlg.GetPath()

        # The crop parameters are saved
        # in a fslroi-compatible manner.
        params = [cropBox.xlo,
                  cropBox.xhi - cropBox.xlo,
                  cropBox.ylo,
                  cropBox.yhi - cropBox.ylo,
                  cropBox.zlo,
                  cropBox.zhi - cropBox.zlo]

        if overlay.ndim >= 4:
            tlo     = self.__volumeWidget.GetLow()
            thi     = self.__volumeWidget.GetHigh()
            params.extend((tlo, thi - tlo))

        errTitle = strings.titles[  self, 'saveError']
        errMsg   = strings.messages[self, 'saveError']

        with status.reportIfError(errTitle, errMsg, raiseError=False):
            np.savetxt(filePath, [params], fmt='%i')
Ejemplo n.º 15
0
    def MacOpenURL(self, url):
        """On OSX, support opening files via a ``fsleyes://`` url. """

        if self.__overlayList is None:
            return

        import fsleyes_widgets.utils.status as status
        import fsleyes.strings as strings
        import fsleyes.parseargs as parseargs
        import fsleyes.actions.applycommandline as applycommandline

        errTitle = strings.titles[self, 'openURLError']
        errMsg = strings.messages[self, 'openURLError']

        with status.reportIfError(errTitle, errMsg):
            applycommandline.applyCommandLineArgs(
                self.__overlayList, self.__displayCtx,
                parseargs.fsleyesUrlToArgs(url))
Ejemplo n.º 16
0
    def __onSave(self, ev):
        """Called when the *save* button is pushed. Prompts the user to select
        a file name, then saves the current history to that file.
        """
        history = self.getHistory()
        msg     = strings.messages[self, 'save']
        defDir  = fslsettings.read('loadSaveOverlayDir')
        dlg     = wx.FileDialog(self,
                                message=msg,
                                defaultDir=defDir,
                                wildcard='*.txt',
                                style=wx.FD_SAVE)

        if dlg.ShowModal() != wx.ID_OK:
            return

        errTitle = strings.titles[  self, 'saveError']
        errMsg   = strings.messages[self, 'saveError'].format(dlg.GetPath())
        with status.reportIfError(errTitle, errMsg, raiseError=False):
            saveLocationHistory(history, dlg.GetPath())
Ejemplo n.º 17
0
    def __onLoad(self, ev):
        """Called when the Save button is pushed. Prompts the user to select
        a file to load crop parameters from.
        """

        overlay  = self.__overlay
        cropBox  = self.__profile.cropBox
        fileName = '{}_crop.txt'.format(overlay.name)

        if overlay.dataSource is not None:
            dirName = op.dirname(overlay.dataSource)
        else:
            dirName = os.getcwd()

        if not op.exists(op.join(dirName, fileName)):
            fileName = ''

        dlg = wx.FileDialog(
            self,
            defaultDir=dirName,
            defaultFile=fileName,
            message=strings.messages[self, 'saveCrop'],
            style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST)

        if dlg.ShowModal() != wx.ID_OK:
            return

        filePath = dlg.GetPath()
        errTitle = strings.titles[  self, 'loadError']
        errMsg   = strings.messages[self, 'loadError']

        with status.reportIfError(errTitle, errMsg, raiseError=False):

            params     = loadCropParameters(filePath, overlay)
            cropBox[:] = params[:6]

            if overlay.ndim >= 4:
                tlo, thi = params[6:]
                self.__volumeWidget.SetLow(tlo)
                self.__volumeWidget.SetHigh(thi)
Ejemplo n.º 18
0
    def __openNotebooks(self):
        """Called when this ``NotebookAction`` is invoked. Starts the
        server and kernel if necessary, then opens a new notebook in a
        web browser.
        """

        # have the kernel or server threads crashed?
        if self.__kernel is not None and not self.__kernel.is_alive():
            self.__kernel = None
        if self.__server is not None and not self.__server.is_alive():
            self.__server = None

        # show a progress dialog if we need
        # to initialise the kernel or server
        if self.__kernel is None or self.__server is None:
            title   = strings.titles[self, 'init']
            progdlg = progress.Bounce(title)
        else:
            progdlg = None

        try:
            # start the kernel/server, and show
            # an error if something goes wrong
            errt = strings.titles[  self, 'init.error']
            errm = strings.messages[self, 'init.error']
            with status.reportIfError(errt, errm):
                if self.__kernel is None:
                    self.__kernel = self.__startKernel(progdlg)
                if self.__server is None:
                    self.__server = self.__startServer(progdlg)

        finally:
            if progdlg is not None:
                progdlg.Destroy()
                progdlg = None

        # if all is well, open the
        # notebook server homepage
        webbrowser.open(self.__server.url)
Ejemplo n.º 19
0
    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)
Ejemplo n.º 20
0
    def __onLoad(self, ev):
        """Called when the *load* button is pushed. Prompts the user to select
        a file, then loads a history from that file.
        """

        msg     = strings.messages[self, 'load']
        fromDir = fslsettings.read('loadSaveOverlayDir')
        dlg     = wx.FileDialog(self,
                                message=msg,
                                defaultDir=fromDir,
                                wildcard='*.txt',
                                style=wx.FD_OPEN)

        if dlg.ShowModal() != wx.ID_OK:
            return

        errTitle = strings.titles[  self, 'loadError']
        errMsg   = strings.messages[self, 'loadError'].format(dlg.GetPath())
        with status.reportIfError(errTitle, errMsg, raiseError=False):
            history = loadLocationHistory(dlg.GetPath())

        self.__list.Clear()
        for loc, comment  in history:
            self.__addLocation(loc, comment)
Ejemplo n.º 21
0
    def __onLoadButton(self, ev):
        """Called when the *Load labels* button is pushed.  Prompts the user
        to select a label file to load, then does the following:

        1. If the selected label file refers to the currently selected
           melodic_IC overlay, the labels are applied to the overlay.

        2. If the selected label file refers to a different melodic_IC
           overlay, the user is asked whether they want to load the
           different melodic_IC file (the default), or whether they
           want the labels applied to the existing overlay.

        3. If the selected label file does not refer to any overlay
           (it only contains the bad component list), the user is asked
           whether they want the labels applied to the current melodic_IC
           overlay.

        If the number of labels in the file is less than the number of
        melodic_IC components, the remaining components are labelled
        as unknown. If the number of labels in the file is greater than
        the number of melodic_IC components, an error is shown, and
        nothing is done.
        """

        # The aim of the code beneath the
        # applyLabels function is to load
        # a set of component labels, and
        # to figure out which overlay
        # they should be added to.

        # When it has done this, it calls
        # applyLabels, which applies the
        # loaded labels to the overlay.
        def applyLabels(labelFile, overlay, allLabels, newOverlay):
            # labelFile:  Path to the loaded label file
            # overlay:    Overlay to apply them to
            # allLabels:  Loaded labels (list of (component, [label]) tuples)
            # newOverlay: True if the selected overlay has changed, False
            #             otherwise

            lut       = self.__lut
            volLabels = self.overlayList.getData(overlay, 'VolumeLabels')

            ncomps  = volLabels.numComponents()
            nlabels = len(allLabels)

            # Error: number of labels in the
            # file is greater than the number
            # of components in the overlay.
            if ncomps < nlabels:
                msg   = strings.messages[self, 'wrongNComps'].format(
                    labelFile, overlay.dataSource)
                title = strings.titles[  self, 'loadError']
                wx.MessageBox(msg, title, wx.ICON_ERROR | wx.OK)
                return

            # Number of labels in the file is
            # less than number of components
            # in the overlay - we pad the
            # labels with 'Unknown'
            elif ncomps > nlabels:
                for i in range(nlabels, ncomps):
                    allLabels.append(['Unknown'])

            # Disable notification while applying
            # labels so the component/label grids
            # don't confuse themselves.
            with volLabels.skip(self.__componentGrid.name), \
                 volLabels.skip(self.__labelGrid    .name):

                volLabels.clear()

                for comp, lbls in enumerate(allLabels):
                    for lbl in lbls:
                        volLabels.addLabel(comp, lbl)

                # Make sure a colour in the melodic
                # lookup table exists for all labels
                for label in volLabels.getAllLabels():

                    label    = volLabels.getDisplayLabel(label)
                    lutLabel = lut.getByName(label)

                    if lutLabel is None:
                        log.debug('New melodic classification '
                                  'label: {}'.format(label))
                        lut.new(label, colour=fslcm.randomBrightColour())

            # New overlay was loaded
            if newOverlay:

                # Make sure the new image is selected.
                with props.skip(self.displayCtx,
                                'selectedOverlay',
                                self.name):
                    self.displayCtx.selectOverlay(overlay)

                self.__componentGrid.setOverlay(overlay)
                self.__labelGrid    .setOverlay(overlay)

            # Labels were applied to
            # already selected overlay.
            else:
                self.__componentGrid.refreshTags()
                self.__labelGrid    .refreshTags()

        # If the current overlay is a compatible
        # Image, the open file dialog starting
        # point will be its directory.
        overlay = self.__overlay

        if overlay is not None and overlay.dataSource is not None:
            loadDir = op.dirname(overlay.dataSource)

        # Otherwise it will be the most
        # recent overlay load directory.
        else:
            loadDir = fslsettings.read('loadSaveOverlayDir', os.getcwd())

        # Ask the user to select a label file
        dlg = wx.FileDialog(
            self,
            message=strings.titles[self, 'loadDialog'],
            defaultDir=loadDir,
            style=wx.FD_OPEN)

        # User cancelled the dialog
        if dlg.ShowModal() != wx.ID_OK:
            return

        # Load the specified label file
        filename = dlg.GetPath()
        emsg     = strings.messages[self, 'loadError'].format(filename)
        etitle   = strings.titles[  self, 'loadError']
        try:
            with status.reportIfError(msg=emsg, title=etitle):
                melDir, allLabels = fixlabels.loadLabelFile(filename)
        except Exception:
            return

        # Ok we've got the labels, now
        # we need to figure out which
        # overlay to add them to.

        # If the label file does not refer
        # to a Melodic directory, and the
        # current overlay is a compatible
        # image, apply the labels to the
        # image.
        if overlay is not None and melDir is None:
            applyLabels(filename, overlay, allLabels, False)
            return

        # If the label file refers to a
        # Melodic directory, and the
        # current overlay is a compatible
        # image.
        if overlay is not None and melDir is not None:

            if isinstance(overlay, fslmelimage.MelodicImage):
                overlayDir = overlay.getMelodicDir()
            elif overlay.dataSource is not None:
                overlayDir = op.dirname(overlay.dataSource)
            else:
                overlayDir = 'none'

            # And both the current overlay and
            # the label file refer to the same
            # directory, then we apply the
            # labels to the curent overlay.
            if op.abspath(melDir) == op.abspath(overlayDir):

                applyLabels(filename, overlay, allLabels, False)
                return

            # Otherwise, if the overlay and the
            # label file refer to different
            # directories...

            # Ask the user whether they want to load
            # the image specified in the label file,
            # or apply the labels to the currently
            # selected image.
            dlg = wx.MessageDialog(
                self,
                strings.messages[self, 'diffMelDir'].format(
                    melDir, overlayDir),
                style=wx.ICON_QUESTION | wx.YES_NO | wx.CANCEL)
            dlg.SetYesNoLabels(
                strings.messages[self, 'diffMelDir.labels'],
                strings.messages[self, 'diffMelDir.overlay'])

            response = dlg.ShowModal()

            # User cancelled the dialog
            if response == wx.ID_CANCEL:
                return

            # User chose to load the melodic
            # image specified in the label
            # file. We'll carry on with this
            # processing below.
            elif response == wx.ID_YES:
                pass

            # Apply the labels to the current
            # overlay, even though they are
            # from different analyses.
            else:
                applyLabels(filename, overlay, allLabels, False)
                return

        # If we've reached this far, we are
        # going to attempt to identify the
        # image associated with the label
        # file, load that image, and then
        # apply the labels.

        # The label file does not
        # specify a melodic directory
        if melDir is None:

            msg   = strings.messages[self, 'noMelDir'].format(filename)
            title = strings.titles[  self, 'loadError']
            wx.MessageBox(msg, title, wx.ICON_ERROR | wx.OK)
            return

        # Try loading the melodic_IC image
        # specified in the label file.
        try:
            overlay = fslmelimage.MelodicImage(melDir)

            log.debug('Adding {} to overlay list'.format(overlay))

            with props.skip(self.overlayList, 'overlays',        self.name),\
                 props.skip(self.displayCtx,  'selectedOverlay', self.name):

                self.overlayList.append(overlay)

            if self.displayCtx.autoDisplay:
                autodisplay.autoDisplay(overlay,
                                        self.overlayList,
                                        self.displayCtx)

            fslsettings.write('loadSaveOverlayDir', op.abspath(melDir))

        except Exception as e:

            e     = str(e)
            msg   = strings.messages[self, 'loadError'].format(filename, e)
            title = strings.titles[  self, 'loadError']
            log.debug('Error loading classification file '
                      '({}), ({})'.format(filename, e), exc_info=True)
            wx.MessageBox(msg, title, wx.ICON_ERROR | wx.OK)

        # Apply the loaded labels
        # to the loaded overlay.
        applyLabels(filename, overlay, allLabels, True)
Ejemplo n.º 22
0
    def DownloadFile(self, fobj, dest, showProgress=True):
        """Download the given ``xnat`` file object to the path specified by
        ``dest``.

        :arg fobj:         An XNAT file object, as returned by
                           :meth:`GetSelectedFiles`.

        :arg dest:         Directory to download the file to.

        :arg showProgress: If ``True``, a ``wx.ProgressDialog`` is shown,
                           displaying the download progress.

        :returns:          Path to the downloaded file, or ``None`` if the
                           download was cancelled.. Note that the path may
                           be different to ``dest``, as the user may be
                           prompted to select a different locaion.
        """

        fname = fobj.id
        fsize = fobj.size

        # if destination already exists, ask
        # the user if they want to skip,
        # overwrite, or choose a new name
        if op.exists(dest):

            # We potentially show two dialogs -
            # the first one asking the user what
            # they want to do, and the second
            # one prompting for a new file. If
            # the user cancels the second dialog,
            # he/she is re-shown the first.
            while True:
                dlg = wx.MessageDialog(
                    self,
                    message=LABELS['download.exists.message'].format(fname),
                    caption=LABELS['download.exists.title'],
                    style=(wx.YES_NO |
                           wx.CANCEL |
                           wx.CENTRE |
                           wx.ICON_QUESTION))

                dlg.SetYesNoCancelLabels(
                    LABELS['download.exists.overwrite'],
                    LABELS['download.exists.newdest'],
                    LABELS['download.exists.skip'])

                choice = dlg.ShowModal()

                # overwrite
                if choice == wx.ID_YES:
                    break

                # skip
                elif choice == wx.ID_CANCEL:
                    return None

                # choose a new destination
                elif choice == wx.ID_NO:
                    dlg = wx.FileDialog(
                        self,
                        message=LABELS['download.exists.choose'],
                        defaultDir=op.dirname(dest),
                        defaultFile=fname,
                        style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT)

                    # If user cancelled this dialog,
                    # show them the first dialog again.
                    if dlg.ShowModal() == wx.ID_OK:
                        dest  = dlg.GetPath()
                        fname = op.basename(dest)
                        break

        if showProgress:

            dlg = wx.ProgressDialog(
                LABELS['download.title'],
                LABELS['download.startMessage'].format(fname),
                maximum=int(fsize),
                parent=self)

            msg = LABELS['download.updateMessage']

            def update(nbytes, total, finished):

                nmb = nbytes / 1048576.
                tmb = total  / 1048576.

                dlg.Update(nbytes, msg.format(fname, nmb, tmb))
                dlg.Fit()

                if finished:
                    dlg.Close()

            dlg.Show()

        else:
            update = None

        errTitle = LABELS['download.error.title']
        errMsg   = LABELS['download.error.message'].format(fname)

        with status.reportIfError(errTitle, errMsg, raiseError=False):
            with open(dest, 'wb') as f:
                fobj.download_stream(f, update_func=update)

        if showProgress:
            dlg.Close()

        return dest
Ejemplo n.º 23
0
def test_reportIfError_noError():

    with mock.patch('fsleyes_widgets.utils.status.reportError') as func:
        with status.reportIfError('title', 'message'):
            pass
        func.assert_not_called()
Ejemplo n.º 24
0
    def __loadColourMap(self):
        """This method does the following:

        1. Prompts the user to select a colour map file

        2. Prompts the user to name the new colour map.

        3. Registers the colour map with the :mod:`.colourmaps` module.

        4. Asks the user if they want the colour map installed, and installs
           it if they do.
        """

        import wx

        app = wx.GetApp()

        # Get the most recent colour map
        # directory if there is one
        loadDir = fslsettings.read('fsleyes.loadcolourmapdir', os.getcwd())

        # prompt the user to choose a colour map file
        dlg = wx.FileDialog(app.GetTopWindow(),
                            defaultDir=loadDir,
                            message=strings.messages[self, 'loadcmap'],
                            style=wx.FD_OPEN)

        if dlg.ShowModal() != wx.ID_OK:
            return

        # prompt the user to choose  a name for the colour
        # map (using the filename prefix as the default)
        cmapFile = dlg.GetPath()
        cmapDir = op.dirname(cmapFile)
        cmapName = op.splitext(op.basename(cmapFile))[0]

        cmapNameMsg = strings.messages[self, 'namecmap']
        cmapNameTitle = strings.titles[self, 'namecmap']

        while True:

            dlg = wx.TextEntryDialog(app.GetTopWindow(), cmapNameMsg,
                                     cmapNameTitle, cmapName)

            if dlg.ShowModal() != wx.ID_OK:
                return

            cmapName = dlg.GetValue()
            cmapKey = fslcmap.makeValidMapKey(cmapName)

            # a colour map with the specified name already exists
            if fslcmap.isColourMapRegistered(cmapKey):
                cmapNameMsg = strings.messages[self, 'alreadyinstalled']
                continue

            break

        # register the selected colour map file
        fslcmap.registerColourMap(cmapFile,
                                  self.overlayList,
                                  self.displayCtx,
                                  key=cmapKey,
                                  name=cmapName)

        # Save the directory for next time
        fslsettings.write('fsleyes.loadcolourmapdir', cmapDir)

        # ask the user if they want to install
        # the colour map for future use
        dlg = wx.MessageDialog(app.GetTopWindow(),
                               caption=strings.titles[self, 'installcmap'],
                               message=strings.messages[self, 'installcmap'],
                               style=wx.YES_NO)

        if dlg.ShowModal() != wx.ID_YES:
            return

        # install the colour map
        etitle = strings.titles[self, 'installerror']
        emsg = strings.messages[self, 'installerror']

        with status.reportIfError(title=etitle, msg=emsg, raiseError=False):
            fslcmap.installColourMap(cmapKey)