.. DO NOT EDIT.
.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY.
.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE:
.. "auto_examples/anaevensimplerviewer.py"
.. LINE NUMBERS ARE GIVEN BELOW.

.. only:: html

    .. note::
        :class: sphx-glr-download-link-note

        :ref:`Go to the end <sphx_glr_download_auto_examples_anaevensimplerviewer.py>`
        to download the full example code

.. rst-class:: sphx-glr-example-title

.. _sphx_glr_auto_examples_anaevensimplerviewer.py:


Build a custom simplified viewer based on Anatomist
===================================================

An even simplified version of the anasimpleviewer application, which may also
be used as a programming example. Its code is in the “bin/”” directory of the
binary packages.

.. .. figure:: ../images/anaevensimplerviewer.png

.. GENERATED FROM PYTHON SOURCE LINES 45-391



.. image-sg:: /auto_examples/images/sphx_glr_anaevensimplerviewer_001.png
   :alt: anaevensimplerviewer
   :srcset: /auto_examples/images/sphx_glr_anaevensimplerviewer_001.png
   :class: sphx-glr-single-img


.. rst-class:: sphx-glr-script-out

 .. code-block:: none

    config.setitem: setAutomaticReferential : 1
    config.setitem: windowSizeFactor : 1.0
    Exiting






|

.. code-block:: default


    import anatomist.direct.api as ana
    from soma import aims
    from soma.aims import colormaphints
    import sys
    import os
    from soma.qt_gui import qt_backend
    from soma.qt_gui.qt_backend import Qt, loadUi
    import six
    from six.moves import zip


    def findChild(x, y): return Qt.QObject.findChild(x, Qt.QObject, y)


    close_qt = False
    if 'sphinx_gallery' in sys.modules \
            or ('IPython' in sys.modules
                and Qt.QApplication.instance() is None):
        run_qt = False
        close_qt = True
    elif Qt.QApplication.instance() is None:
        run_qt = True
    else:
        run_qt = False


    # start the Anatomist engine, in batch mode (no main window)
    a = ana.Anatomist('-b')

    # load the anasimpleviewer GUI
    uifile = 'anasimpleviewer-qt4.ui'
    anasimpleviewerdir = os.path.join(six.text_type(a.anatomistSharedPath()),
                                      'anasimpleviewer')
    cwd = os.getcwd()
    # PyQt4 uic doesn' seem to allow specifying the directory when looking for
    # icon files: we have no other choice than globally changing the working
    # directory
    os.chdir(anasimpleviewerdir)
    awin = loadUi(os.path.join(anasimpleviewerdir, uifile))
    os.chdir(cwd)

    # global variables: lists of windows, objects, a fusion2d with a number of
    # volumes in it
    awindows = []
    aobjects = []
    fusion2d = []

    # vieww: parent block widget for anatomist windows
    vieww = findChild(awin, 'windows')
    viewgridlay = Qt.QGridLayout(vieww)
    nviews = 0


    # This class holds methods for menu/actions callbacks, and utility functions
    # like load/view objects, remove/delete, etc.
    class AnaSimpleViewer(Qt.QObject):

        def __init__(self):
            Qt.QObject.__init__(self)
            self.filedialogdir = '.'

        def createWindow(self, wintype='Axial'):
            '''Opens a new window in the windows grid layout.
            The new window will be set in MNI referential, and have no
            menu/toolbars.
            '''
            global vieww, nviews
            x = nviews % 2
            y = nviews // 2
            nviews += 1

            w = a.createWindow(wintype, no_decoration=True, options={'hidden': 1})
            w.setAcceptDrops(False)
            viewgridlay.addWidget(w.getInternalRep(), x, y)

            # keep it in anasimpleviewer list of windows
            awindows.append(w)
            a.assignReferential(a.mniTemplateRef, w)
            # force redrawing in MNI orientation
            # (there should be a better way to do so...)
            if wintype == 'Axial':
                w.muteAxial()
            elif wintype == 'Coronal':
                w.muteCoronal()
            elif wintype == 'Sagittal':
                w.muteSagittal()
            elif wintype == 'Oblique':
                w.muteOblique()
            # set a black background
            a.execute('WindowConfig', windows=[w],
                      light={'background': [0., 0., 0., 1.]})

        def loadObject(self, fname):
            '''Load an object and display it in all anasimpleviewer windows
            '''
            obj = a.loadObject(fname)
            self.registerObject(obj)

        def registerObject(self, obj):
            '''Register an object in anasimpleviewer objects list, and display it
            '''
            findChild(awin, 'objectslist').addItem(obj.name)
            # keep it in the global list
            aobjects.append(obj)
            if obj.objectType == 'VOLUME':
                # volume are checked for possible adequate colormaps
                hints = colormaphints.checkVolume(
                    ana.cpp.AObjectConverter.aims(obj))
                obj.attributed()['colormaphints'] = hints
            bb = obj.boundingbox()
            # create the 4 windows if they don't exist
            if len(awindows) == 0:
                self.createWindow('Coronal')
                self.createWindow('Axial')
                self.createWindow('Sagittal')
                self.createWindow('3D')
                # set a cool angle of view for 3D
                a.execute('Camera', windows=[awindows[-1]],
                          view_quaternion=[0.404603, 0.143829, 0.316813, 0.845718])
            # view obj in these views
            self.addObject(obj)
            # set the cursot at the center of the object (actually, overcome a bug
            # in anatomist...)
            position = (aims.Point3df(bb[1][:3]) - bb[0][:3]) / 2.
            t = a.getTransformation(obj.getReferential(),
                                    awindows[0].getReferential())
            if t:
                position = t.transform(position)
            a.execute('LinkedCursor', window=awindows[0], position=position)

        def addVolume(self, obj, opts={}):
            '''Display a volume in all windows.
            If several volumes are displayed, a Fusion2D will be built to wrap all
            of them.
            '''
            global fusion2d
            if obj in fusion2d:
                return
            if len(fusion2d) == 0:
                # only one object
                fusion2d = [None, obj]
            else:
                # several objects: fusion them
                fusobjs = fusion2d[1:] + [obj]
                f2d = a.fusionObjects(fusobjs, method='Fusion2DMethod')
                if fusion2d[0] is not None:
                    # destroy the previous fusion
                    a.deleteObjects(fusion2d[0])
                else:
                    a.removeObjects(fusion2d[1], awindows)
                fusion2d = [f2d] + fusobjs
                # repalette( fusobjs )
                obj = f2d
            if obj.objectType == 'VOLUME':
                # choose a good colormap for a single volume
                if 'volume_contents_likelihoods' in \
                        obj.attributed()['colormaphints']:
                    cmap = colormaphints.chooseColormaps(
                        (obj.attributed()['colormaphints'], ))
                    obj.setPalette(cmap[0])
            else:
                # choose good colormaps for the current set of volumes
                hints = [x.attributed()['colormaphints'] for x in obj.children]
                children = [x for x, y in zip(obj.children, hints)
                            if 'volume_contents_likelihoods' in y]
                hints = [x for x in hints
                         if 'volume_contents_likelihoods' in x]
                cmaps = colormaphints.chooseColormaps(hints)
                for x, y in zip(children, cmaps):
                    x.setPalette(y)
            a.addObjects(obj, awindows, **opts)

        def removeVolume(self, obj, opts={}):
            '''Hides a volume from views (low-level function: use removeObject)
            '''
            global fusion2d
            if obj in fusion2d:
                fusobjs = [o for o in fusion2d[1:] if o != obj]
                if len(fusobjs) >= 2:
                    f2d = a.fusionObjects(fusobjs, method='Fusion2DMethod')
                else:
                    f2d = None
                if fusion2d[0] is not None:
                    a.deleteObjects(fusion2d[0])
                else:
                    a.removeObjects(fusion2d[1], awindows)
                if len(fusobjs) == 0:
                    fusion2d = []
                else:
                    fusion2d = [f2d] + fusobjs
                # repalette( fusobjs )
                if f2d:
                    obj = f2d
                elif len(fusobjs) == 1:
                    obj = fusobjs[0]
                else:
                    return
                a.addObjects(obj, awindows, **opts)

        def addObject(self, obj):
            '''Display an object in all windows
            '''
            opts = {}
            if obj.objectType == 'VOLUME':
                # volumes have a specific function since several volumes have to be
                # fusionned, and a volume rendering may occur
                self.addVolume(obj, opts)
                return
            elif obj.objectType == 'GRAPH':
                opts['add_graph_nodes'] = 1
            a.addObjects(obj, awindows, **opts)

        def removeObject(self, obj):
            '''Hides an object from views
            '''
            if obj.objectType == 'VOLUME':
                self.removeVolume(obj)
            else:
                a.removeObjects(obj, awindows, remove_children=True)

        def fileOpen(self):
            '''File browser + load object(s)
            '''
            fdialog = Qt.QFileDialog()
            fdialog.setDirectory(self.filedialogdir)
            fdialog.setFileMode(fdialog.ExistingFiles)
            res = fdialog.exec_()
            if res:
                fnames = fdialog.selectedFiles()
                self.filedialogdir = fdialog.directory()
                for fname in fnames:
                    self.loadObject(six.text_type(fname))

        def selectedObjects(self):
            '''list of objects selected in the list box on the upper left panel
            '''
            olist = findChild(awin, 'objectslist')
            sobjs = []
            for o in olist.selectedItems():
                sobjs.append(six.text_type(o.text()).strip('\0'))
            return [o for o in aobjects if o.name in sobjs]

        def editAdd(self):
            '''Display selected objects'''
            objs = self.selectedObjects()
            for o in objs:
                self.addObject(o)

        def editRemove(self):
            '''Hide selected objects'''
            objs = self.selectedObjects()
            for o in objs:
                self.removeObject(o)

        def editDelete(self):
            '''Delete selected objects'''
            objs = self.selectedObjects()
            for o in objs:
                self.removeObject(o)
            olist = findChild(awin, 'objectslist')
            for o in objs:
                olist.takeItem(olist.row(olist.findItems(o.name,
                                                         Qt.Qt.MatchExactly)[0]))
            global aobjects
            aobjects = [o for o in aobjects if o not in objs]
            a.deleteObjects(objs)

        def closeAll(self):
            '''Exit'''
            print("Exiting")
            global vieww, awindows, fusion2d, aobjects, anasimple
            global awin, viewgridlay
            # remove windows from their parent to prevent them to be brutally
            # deleted by Qt.
            w = None  # ensure there is a w variable before the "del" later
            for w in awindows:
                w.hide()
                viewgridlay.removeWidget(w.internalRep._get())
                w.setParent(None)
            del w
            del viewgridlay, vieww
            del anasimple
            del awindows, fusion2d, aobjects
            awin.close()
            del awin
            a = ana.Anatomist()
            a.close()


    # instantiate the machine
    anasimple = AnaSimpleViewer()
    # connect GUI actions callbacks
    findChild(awin, 'fileOpenAction').triggered.connect(anasimple.fileOpen)
    findChild(awin, 'fileExitAction').triggered.connect(anasimple.closeAll)
    findChild(awin, 'editAddAction').triggered.connect(anasimple.editAdd)
    findChild(awin, 'editRemoveAction').triggered.connect(anasimple.editRemove)
    findChild(awin, 'editDeleteAction').triggered.connect(anasimple.editDelete)

    # display on the whole screen
    awin.showMaximized()

    # tweak: override some user config options
    a.config()['setAutomaticReferential'] = 1
    a.config()['windowSizeFactor'] = 1.

    # run Qt
    if __name__ == '__main__':
        if run_qt:
            Qt.QApplication.instance().exec_()
        elif 'sphinx_gallery' in sys.modules:
            # load a data
            awin.showNormal()
            awin.resize(1000, 700)  # control the size of the snapshot
            anasimple.loadObject('irm.ima')
            # these 2 events ensure things are actually drawn
            Qt.QApplication.instance().processEvents()
            Qt.QApplication.instance().processEvents()
            # snapshot the whole widget
            if Qt.QT_VERSION >= 0x050000:
                ws = awin.grab()  # Qt5 only
            else:
                ws = Qt.QPixmap.grabWidget(awin)  # Qt4 only
            # openGl areas are not rendered in the snapshot, we have to make them
            # by hand
            p = Qt.QPainter(ws)
            for w in awindows:
                s = w.snapshotImage()
                # draw the GL rendering into the image (pixmap)
                p.drawImage(w.mapTo(awin, Qt.QPoint(0, 0)), s)
            del w, s, p
            # snapshot to matplotlib
            import matplotlib
            # backend = matplotlib.get_backend()
            matplotlib.use('agg', force=True)  # force agg
            from matplotlib import pyplot
            im = qt_backend.qimage_to_np(ws)
            plot = pyplot.imshow(im)
            axes = pyplot.gcf().axes
            axes[0].get_xaxis().set_visible(False)
            axes[0].get_yaxis().set_visible(False)
            pyplot.show(block=False)
            # matplotlib.use(backend, force=True)  # restore backend

        if close_qt:
            anasimple.closeAll()


.. rst-class:: sphx-glr-timing

   **Total running time of the script:** (0 minutes 1.374 seconds)


.. _sphx_glr_download_auto_examples_anaevensimplerviewer.py:

.. only:: html

  .. container:: sphx-glr-footer sphx-glr-footer-example




    .. container:: sphx-glr-download sphx-glr-download-python

      :download:`Download Python source code: anaevensimplerviewer.py <anaevensimplerviewer.py>`

    .. container:: sphx-glr-download sphx-glr-download-jupyter

      :download:`Download Jupyter notebook: anaevensimplerviewer.ipynb <anaevensimplerviewer.ipynb>`


.. only:: html

 .. rst-class:: sphx-glr-signature

    `Gallery generated by Sphinx-Gallery <https://sphinx-gallery.github.io>`_