From f7bdc2acff3c13a6d632c28c4569690ab106eed7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Picca=20Fr=C3=A9d=C3=A9ric-Emmanuel?= Date: Fri, 18 Aug 2017 14:48:52 +0200 Subject: Import Upstream version 0.5.0+dfsg --- examples/viewer3DVolume.py | 209 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 209 insertions(+) create mode 100644 examples/viewer3DVolume.py (limited to 'examples/viewer3DVolume.py') diff --git a/examples/viewer3DVolume.py b/examples/viewer3DVolume.py new file mode 100644 index 0000000..7a95d8a --- /dev/null +++ b/examples/viewer3DVolume.py @@ -0,0 +1,209 @@ +# coding: utf-8 +# /*########################################################################## +# +# Copyright (c) 2016-2017 European Synchrotron Radiation Facility +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# +# ###########################################################################*/ +"""This script illustrates the use of silx.gui.plot3d.ScalarFieldView. + +It loads a 3D scalar data set from a file and displays iso-surfaces and +an interactive cutting plane. +It can also be started without providing a file. +""" + +from __future__ import absolute_import, division, unicode_literals + +__authors__ = ["T. Vincent"] +__license__ = "MIT" +__date__ = "05/01/2017" + + +import argparse +import logging +import os.path + +import numpy + +from silx.gui import qt + +from silx.gui.plot3d.ScalarFieldView import ScalarFieldView +from silx.gui.plot3d import SFViewParamTree + +logging.basicConfig() + +_logger = logging.getLogger(__name__) + + +try: + import h5py +except ImportError: + _logger.warning('h5py is not installed: HDF5 not supported') + h5py = None + + +def load(filename): + """Load 3D scalar field from file. + + It supports 3D stack HDF5 files and numpy files. + + :param str filename: Name of the file to open + and path in file for hdf5 file + :return: numpy.ndarray with 3 dimensions. + """ + if not os.path.isfile(filename.split('::')[0]): + raise IOError('No input file: %s' % filename) + + if h5py is not None and h5py.is_hdf5(filename.split('::')[0]): + if '::' not in filename: + raise ValueError( + 'HDF5 path not provided: Use :: format') + + filename, path = filename.split('::') + path, indices = path.split('#')[0], path.split('#')[1:] + + with h5py.File(filename) as f: + data = f[path] + + # Loop through indices along first dimensions + for index in indices: + data = data[int(index)] + + data = numpy.array(data, order='C', dtype='float32') + + else: # Try with numpy + try: + data = numpy.load(filename) + except IOError: + raise IOError('Unsupported file format: %s' % filename) + + if data.ndim != 3: + raise RuntimeError( + 'Unsupported data set dimensions, only supports 3D datasets') + + return data + + +def main(argv=None): + # Parse input arguments + parser = argparse.ArgumentParser( + description=__doc__) + parser.add_argument( + '-l', '--level', nargs='?', type=float, default=float('nan'), + help="The value at which to generate the iso-surface") + parser.add_argument( + '-sx', '--xscale', nargs='?', type=float, default=1., + help="The scale of the data on the X axis") + parser.add_argument( + '-sy', '--yscale', nargs='?', type=float, default=1., + help="The scale of the data on the Y axis") + parser.add_argument( + '-sz', '--zscale', nargs='?', type=float, default=1., + help="The scale of the data on the Z axis") + parser.add_argument( + '-ox', '--xoffset', nargs='?', type=float, default=0., + help="The offset of the data on the X axis") + parser.add_argument( + '-oy', '--yoffset', nargs='?', type=float, default=0., + help="The offset of the data on the Y axis") + parser.add_argument( + '-oz', '--zoffset', nargs='?', type=float, default=0., + help="The offset of the data on the Z axis") + parser.add_argument( + 'filename', + nargs='?', + default=None, + help="""Filename to open. + + It supports 3D volume saved as .npy or in .h5 files. + + It also support nD data set (n>=3) stored in a HDF5 file. + For HDF5, provide the filename and path as: ::. + If the data set has more than 3 dimensions, it is possible to choose a + 3D data set as a subset by providing the indices along the first n-3 + dimensions with '#': + ::#<1st_dim_index>...# + + E.g.: data.h5::/data_5D#1#1 + """) + args = parser.parse_args(args=argv) + + # Start GUI + global app # QApplication must be global to avoid seg fault on quit + app = qt.QApplication([]) + + # Create the viewer main window + window = ScalarFieldView() + window.setAttribute(qt.Qt.WA_DeleteOnClose) + + # Create a parameter tree for the scalar field view + treeView = SFViewParamTree.TreeView(window) + treeView.setSfView(window) # Attach the parameter tree to the view + + # Add the parameter tree to the main window in a dock widget + dock = qt.QDockWidget() + dock.setWindowTitle('Parameters') + dock.setWidget(treeView) + window.addDockWidget(qt.Qt.RightDockWidgetArea, dock) + + # Load data from file + if args.filename is not None: + data = load(args.filename) + _logger.info('Data:\n\tShape: %s\n\tRange: [%f, %f]', + str(data.shape), data.min(), data.max()) + else: + # Create dummy data + _logger.warning('Not data file provided, creating dummy data') + size = 128 + z, y, x = numpy.mgrid[0:size, 0:size, 0:size] + data = numpy.asarray( + size**2 - ((x-size/2)**2 + (y-size/2)**2 + (z-size/2)**2), + dtype='float32') + + # Set ScalarFieldView data + window.setData(data) + + # Set scale of the data + window.setScale(args.xscale, args.yscale, args.zscale) + + # Set offset of the data + window.setTranslation(args.xoffset, args.yoffset, args.zoffset) + + # Set axes labels + window.setAxesLabels('X', 'Y', 'Z') + + # Add an iso-surface + if not numpy.isnan(args.level): + # Add an iso-surface at the given iso-level + window.addIsosurface(args.level, '#FF0000FF') + else: + # Add an iso-surface from a function + window.addIsosurface( + lambda data: numpy.mean(data) + numpy.std(data), + '#FF0000FF') + + window.show() + return app.exec_() + + +if __name__ == '__main__': + import sys + + sys.exit(main(argv=sys.argv[1:])) -- cgit v1.2.3