Source code for taurus.qt.qtgui.extra_nexus.taurusnexuswidget

#!/usr/bin/env python

# ###########################################################################
#
# This file is part of Taurus
#
# http://taurus-scada.org
#
# Copyright 2011 CELLS / ALBA Synchrotron, Bellaterra, Spain
#
# Taurus is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Taurus is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Taurus.  If not, see <http://www.gnu.org/licenses/>.
#
# ###########################################################################

"""
nexusWidget.py:
"""

import numpy
import posixpath
from functools import partial

from taurus.external.qt import Qt, compat
from PyMca5.PyMcaGui.io.hdf5 import HDF5Widget, HDF5Info, HDF5DatasetTable

from taurus.qt.qtgui.container import TaurusWidget
from taurus.core.util.log import deprecation_decorator


@deprecation_decorator(rel="5.0.0")
class NeXusInfoWidget(Qt.QTabWidget):
    """deprecated"""

    def setInfoDict(self, info):
        pass


[docs]class TaurusNeXusBrowser(TaurusWidget): """A Browser for nexus files with optional preview. Based on PyMCA's HDF5Widget""" def __init__(self, *args, **kwargs): TaurusWidget.__init__(self, *args) fileModel = kwargs.get("fileModel", None) if fileModel is None: fileModel = HDF5Widget.FileModel() self.__fileModel = fileModel self.treeWidget = HDF5Widget.HDF5Widget(self.__fileModel) self.treeWidget.setSizePolicy( Qt.QSizePolicy(Qt.QSizePolicy.Expanding, Qt.QSizePolicy.Expanding) ) # self.infoWidget = HDF5Info.HDF5InfoWidget() self.__previewStack = Qt.QStackedWidget() self.__currentPreview = None # layout self.__splitter = Qt.QSplitter() self.__splitter.setOrientation(Qt.Qt.Vertical) self.__splitter.addWidget(self.treeWidget) # self.__splitter.addWidget(self.infoWidget) self.__splitter.addWidget(self.__previewStack) self.setLayout(Qt.QVBoxLayout()) self.layout().addWidget(self.__splitter) # Actions self.setContextMenuPolicy(Qt.Qt.ActionsContextMenu) self.openFileAction = Qt.QAction( Qt.QIcon.fromTheme("document-open"), "Open Data File...", self ) self.togglePreviewAction = Qt.QAction( Qt.QIcon("actions:view.svg"), "Show/Hide preview", self ) self.togglePreviewAction.setCheckable(True) self.togglePreviewAction.setChecked(True) self.addActions([self.openFileAction, self.togglePreviewAction]) # Toolbar self._toolbar = Qt.QToolBar("NeXus browser toolbar") self._toolbar.setIconSize(Qt.QSize(16, 16)) self._toolbar.setFloatable(False) self._toolbar.addActions( [self.openFileAction, self.togglePreviewAction] ) self.layout().setMenuBar(self._toolbar) # connections self.__fileModel.sigFileAppended.connect(self.treeWidget.fileAppended) self.treeWidget.sigHDF5WidgetSignal.connect(self.onHDF5WidgetSignal) self.openFileAction.triggered.connect( partial(self.openFile, fname=None) ) self.togglePreviewAction.toggled.connect( self.__previewStack.setVisible ) # configuration self.registerConfigProperty( self.togglePreviewAction.isChecked, self.togglePreviewAction.setChecked, "showPreview", )
[docs] @Qt.pyqtSlot() @Qt.pyqtSlot("QString") def openFile(self, fname=None): if fname is None: fname, _ = compat.getOpenFileName(self, "Choose NeXus File", "") if fname: self.__nexusFile = self.__fileModel.openFile(fname)
[docs] def onHDF5WidgetSignal(self, ddict): self.__previewStack.removeWidget(self.__currentPreview) self.__currentPreview = self.neXusPreviewWidgetFactory(ddict) self.__previewStack.addWidget(self.__currentPreview) self.__previewStack.setCurrentWidget(self.__currentPreview)
[docs] def neXusPreviewWidgetFactory(self, ddict): """returns a widget showing a preview of a node in a NeXus file""" # @todo: check if this is the root group and it has a valid nexus # data directory, in which case the default plot should be # returned if ddict["type"] == "Dataset": node = ddict["name"] data = self.__nexusFile[node] if len(data.shape) == 1 and isinstance( data[0], (numpy.floating, numpy.integer, int, float) ): try: import pyqtgraph as pg w = pg.PlotWidget() w.plot(data) except ImportError: w = HDF5DatasetTable.HDF5DatasetTable() w.setDataset(data) else: w = HDF5DatasetTable.HDF5DatasetTable() w.setDataset(data) else: info = HDF5Info.getInfo(self.__nexusFile, ddict["name"]) w = HDF5Info.HDF5InfoWidget() w.setInfoDict(info) return w
[docs] def neXusWidget(self): return self.treeWidget
[docs] def findNodeIndex(self, filename, nodename): nexus_widget = self.neXusWidget() file_model = nexus_widget.model() for node in file_model.rootItem.children: if node.file.filename == filename: file_node = node break else: raise Exception("Could not find file %s" % filename) index = file_model.index(file_node.row, 0, Qt.QModelIndex()) node_parts = nodename.split(posixpath.sep) while node_parts: name = posixpath.basename(node_parts.pop(0)) for child in node.children: child_name = posixpath.basename(child.name) if child_name == name: node = child index = file_model.index(node.row, 0, index) break else: raise Exception( "Could not find node %s in %s" % (name, filename) ) return index
[docs] def setCurrentNode(self, filename, nodename): index = self.findNodeIndex(filename, nodename) self.setCurrentIndex(index)
[docs] @classmethod def getQtDesignerPluginInfo(cls): ret = TaurusWidget.getQtDesignerPluginInfo() ret["module"] = "taurus.qt.qtgui.extra_nexus" ret["icon"] = "designer:listview.png" ret["container"] = False ret["group"] = "Taurus Views" return ret
[docs] def closeEvent(self, event): """Close HDF5 files""" try: self.neXusWidget().model().close() except Exception: self.warning("Exception received while trying to close HDF5 files") self.traceback() TaurusWidget.closeEvent(self, event)
if __name__ == "__main__": import sys from taurus.qt.qtgui.application import TaurusApplication if len(sys.argv) > 1: fname = sys.argv[1] else: fname = None if len(sys.argv) > 2: path = sys.argv[2] else: path = None app = TaurusApplication(sys.argv, cmd_line_parser=None) w = TaurusNeXusBrowser() w.openFile(fname) w.show() if path is not None: index = w.findNodeIndex(fname, path) nexus_widget = w.neXusWidget() nexus_widget.setCurrentIndex(index) while index.row() != -1 and index.column() != -1: nexus_widget.expand(index) index = index.parent() sys.exit(app.exec_())