diff --git a/.travis.yml b/.travis.yml index e80ab4a9c..b601d1036 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,7 +29,7 @@ before_install: - conda config --set always_yes yes --set changeps1 no - conda update -q conda - conda info -a - - conda create -q -n test-environment python=$TRAVIS_PYTHON_VERSION six numpy scipy h5py=2.5 pandas + - conda create -q -n test-environment python=$TRAVIS_PYTHON_VERSION six numpy scipy h5py=2.5 pandas matplotlib - source activate test-environment # Install GCC, MPICH, HDF5, PHDF5 diff --git a/docs/source/conf.py b/docs/source/conf.py index 89dd585d7..fbbc7cf8b 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -25,7 +25,8 @@ except ImportError: MOCK_MODULES = ['numpy', 'numpy.polynomial', 'numpy.polynomial.polynomial', - 'h5py', 'pandas', 'uncertainties', 'openmoc'] + 'h5py', 'pandas', 'uncertainties', 'matplotlib.colors', + 'openmoc'] sys.modules.update((mod_name, MagicMock()) for mod_name in MOCK_MODULES) import numpy as np diff --git a/docs/source/pythonapi/index.rst b/docs/source/pythonapi/index.rst index d07cf60d3..a1ce6b2b1 100644 --- a/docs/source/pythonapi/index.rst +++ b/docs/source/pythonapi/index.rst @@ -188,6 +188,7 @@ Running OpenMC openmc.run openmc.calculate_volumes openmc.plot_geometry + openmc.plot_inline Post-processing --------------- diff --git a/docs/source/usersguide/input.rst b/docs/source/usersguide/input.rst index 284f4f41a..991c5912a 100644 --- a/docs/source/usersguide/input.rst +++ b/docs/source/usersguide/input.rst @@ -2050,13 +2050,13 @@ sub-elements: *Default*: "plot" - :color: - Keyword for plot coloring. This can only be either ``cell`` or ``mat``, + :color_by: + Keyword for plot coloring. This can only be either "cell" or "material", which colors regions by cells and materials, respectively. For voxel plots, this determines which id (cell or material) is associated with each position. - *Default*: ``cell`` + *Default*: "cell" :level: Universe depth to plot at (optional). This parameter controls how many @@ -2142,10 +2142,10 @@ attributes or sub-elements. These are not used in "voxel" plots: *Default*: 0 0 0 (black) - :col_spec: + :color: Any number of this optional tag may be included in each ```` element, which can override the default random colors for cells or materials. Each - ``col_spec`` element must contain ``id`` and ``rgb`` sub-elements. + ``color`` element must contain ``id`` and ``rgb`` sub-elements. :id: Specifies the cell or material unique id for the color specification. @@ -2155,11 +2155,11 @@ attributes or sub-elements. These are not used in "voxel" plots: separated by spaces. As an example, if your plot is colored by material and you want material 23 - to be blue, the corresponding ``col_spec`` element would look like: + to be blue, the corresponding ``color`` element would look like: .. code-block:: xml - + *Default*: None @@ -2175,7 +2175,7 @@ attributes or sub-elements. These are not used in "voxel" plots: :background: Color to apply to all cells or materials not in the ``components`` list of - cells or materials to plot. This overrides any ``col_spec`` color + cells or materials to plot. This overrides any ``color`` color specifications. *Default*: None diff --git a/examples/python/boxes/build-xml.py b/examples/python/boxes/build-xml.py index 03e81b073..d04f0f67a 100644 --- a/examples/python/boxes/build-xml.py +++ b/examples/python/boxes/build-xml.py @@ -118,7 +118,7 @@ plot = openmc.Plot(plot_id=1) plot.origin = [0, 0, 0] plot.width = [20, 20] plot.pixels = [200, 200] -plot.color = 'cell' +plot.color_by = 'cell' # Instantiate a Plots collection and export to XML plot_file = openmc.Plots([plot]) diff --git a/examples/python/lattice/hexagonal/build-xml.py b/examples/python/lattice/hexagonal/build-xml.py index 8d124930f..1065e6e06 100644 --- a/examples/python/lattice/hexagonal/build-xml.py +++ b/examples/python/lattice/hexagonal/build-xml.py @@ -132,7 +132,7 @@ plot_xy.filename = 'plot_xy' plot_xy.origin = [0, 0, 0] plot_xy.width = [6, 6] plot_xy.pixels = [400, 400] -plot_xy.color = 'mat' +plot_xy.color_by = 'material' plot_yz = openmc.Plot(plot_id=2) plot_yz.filename = 'plot_yz' @@ -140,7 +140,7 @@ plot_yz.basis = 'yz' plot_yz.origin = [0, 0, 0] plot_yz.width = [8, 8] plot_yz.pixels = [400, 400] -plot_yz.color = 'mat' +plot_yz.color_by = 'material' # Instantiate a Plots collection, add plots, and export to XML plot_file = openmc.Plots((plot_xy, plot_yz)) diff --git a/examples/python/lattice/nested/build-xml.py b/examples/python/lattice/nested/build-xml.py index 363d0db90..ef74173f5 100644 --- a/examples/python/lattice/nested/build-xml.py +++ b/examples/python/lattice/nested/build-xml.py @@ -138,7 +138,7 @@ plot = openmc.Plot(plot_id=1) plot.origin = [0, 0, 0] plot.width = [4, 4] plot.pixels = [400, 400] -plot.color = 'mat' +plot.color_by = 'material' # Instantiate a Plots object and export to XML plot_file = openmc.Plots([plot]) diff --git a/examples/python/lattice/simple/build-xml.py b/examples/python/lattice/simple/build-xml.py index 354ce9cc4..6222cd366 100644 --- a/examples/python/lattice/simple/build-xml.py +++ b/examples/python/lattice/simple/build-xml.py @@ -131,7 +131,7 @@ plot = openmc.Plot(plot_id=1) plot.origin = [0, 0, 0] plot.width = [4, 4] plot.pixels = [400, 400] -plot.color = 'mat' +plot.color_by = 'material' # Instantiate a Plots collection and export to XML plot_file = openmc.Plots([plot]) diff --git a/examples/xml/boxes/plots.xml b/examples/xml/boxes/plots.xml index b7a3093d2..0a75f574e 100644 --- a/examples/xml/boxes/plots.xml +++ b/examples/xml/boxes/plots.xml @@ -1,7 +1,7 @@ - cell + cell 0. 0. 0. 20. 20. 200 200 diff --git a/examples/xml/lattice/nested/plots.xml b/examples/xml/lattice/nested/plots.xml index a8c6fbb7c..0f92e0621 100644 --- a/examples/xml/lattice/nested/plots.xml +++ b/examples/xml/lattice/nested/plots.xml @@ -1,7 +1,7 @@ - + 0. 0. 0. 4.0 4.0 400 400 diff --git a/examples/xml/lattice/simple/plots.xml b/examples/xml/lattice/simple/plots.xml index a25a5a828..0f92e0621 100644 --- a/examples/xml/lattice/simple/plots.xml +++ b/examples/xml/lattice/simple/plots.xml @@ -1,11 +1,10 @@ - + 0. 0. 0. 4.0 4.0 400 400 - diff --git a/examples/xml/pincell_multigroup/plots.xml b/examples/xml/pincell_multigroup/plots.xml index cbb8e532c..92ab1c2ca 100644 --- a/examples/xml/pincell_multigroup/plots.xml +++ b/examples/xml/pincell_multigroup/plots.xml @@ -4,21 +4,21 @@ 1 mat - material + material 0 0 0 1.26 1.26 slice 1000 1000 - - - - + + + + 2 cell - cell + cell 0 0 0 1.26 1.26 slice diff --git a/openmc/cell.py b/openmc/cell.py index 0adc64083..e26af7f99 100644 --- a/openmc/cell.py +++ b/openmc/cell.py @@ -99,7 +99,6 @@ class Cell(object): self.fill = fill self.region = region self._rotation = None - self._rotation_matrix = None self._temperature = None self._translation = None self._paths = [] @@ -197,7 +196,14 @@ class Cell(object): @property def rotation_matrix(self): - return self._rotation_matrix + if self.rotation is not None: + phi, theta, psi = self.rotation*(-pi/180.) + c3, s3 = cos(phi), sin(phi) + c2, s2 = cos(theta), sin(theta) + c1, s1 = cos(psi), sin(psi) + return np.array([[c1*c2, c1*s2*s3 - c3*s1, s1*s3 + c1*c3*s2], + [c2*s1, c1*c3 + s1*s2*s3, c3*s1*s2 - c1*s3], + [-s2, c2*s3, c2*c3]]) @property def temperature(self): @@ -267,23 +273,13 @@ class Cell(object): @rotation.setter def rotation(self, rotation): if not isinstance(self.fill, openmc.Universe): - raise RuntimeError('Cell rotation can only be applied if the cell ' - 'is filled with a Universe') + raise TypeError('Cell rotation can only be applied if the cell ' + 'is filled with a Universe.') cv.check_type('cell rotation', rotation, Iterable, Real) cv.check_length('cell rotation', rotation, 3) self._rotation = np.asarray(rotation) - # Save rotation matrix - phi, theta, psi = self.rotation*(-pi/180.) - c3, s3 = cos(phi), sin(phi) - c2, s2 = cos(theta), sin(theta) - c1, s1 = cos(psi), sin(psi) - self._rotation_matrix = np.array([ - [c1*c2, c1*s2*s3 - c3*s1, s1*s3 + c1*c3*s2], - [c2*s1, c1*c3 + s1*s2*s3, c3*s1*s2 - c1*s3], - [-s2, c2*s3, c2*c3]]) - @translation.setter def translation(self, translation): cv.check_type('cell translation', translation, Iterable, Real) diff --git a/openmc/executor.py b/openmc/executor.py index 1fc00b998..518153512 100644 --- a/openmc/executor.py +++ b/openmc/executor.py @@ -1,9 +1,11 @@ from __future__ import print_function +from collections import Iterable import subprocess from numbers import Integral from six import string_types +import openmc from openmc import VolumeCalculation @@ -32,17 +34,56 @@ def plot_geometry(output=True, openmc_exec='openmc', cwd='.'): Parameters ---------- - output : bool + output : bool, optional Capture OpenMC output from standard out - openmc_exec : str + openmc_exec : str, optional Path to OpenMC executable cwd : str, optional - Path to working directory to run in. Defaults to the current working directory. + Path to working directory to run in """ return _run([openmc_exec, '-p'], output, cwd) +def plot_inline(plots, openmc_exec='openmc', cwd='.', convert_exec='convert'): + """Display plots inline in a Jupyter notebook. + + Parameters + ---------- + plots : Iterable of openmc.Plot + Plots to display + openmc_exec : str + Path to OpenMC executable + cwd : str, optional + Path to working directory to run in + convert_exec : str, optional + Command that can convert PPM files into PNG files + + """ + from IPython.display import Image, display + + if not isinstance(plots, Iterable): + plots = [plots] + + # Create plots.xml + openmc.Plots(plots).export_to_xml() + + # Run OpenMC in geometry plotting mode + plot_geometry(False, openmc_exec, cwd) + + images = [] + if plots is not None: + for p in plots: + if p.filename is not None: + ppm_file = '{}.ppm'.format(p.filename) + else: + ppm_file = 'plot_{}.ppm'.format(p.id) + png_file = ppm_file.replace('.ppm', '.png') + subprocess.check_call([convert_exec, ppm_file, png_file]) + images.append(Image(png_file)) + display(*images) + + def calculate_volumes(threads=None, output=True, cwd='.', openmc_exec='openmc', mpi_args=None): """Run stochastic volume calculations in OpenMC. diff --git a/openmc/plots.py b/openmc/plots.py index bbefb1076..3da996034 100644 --- a/openmc/plots.py +++ b/openmc/plots.py @@ -1,4 +1,4 @@ -from collections import Iterable +from collections import Iterable, Mapping from numbers import Real, Integral from xml.etree import ElementTree as ET import sys @@ -6,6 +6,7 @@ import warnings from six import string_types import numpy as np +from matplotlib.colors import is_color_like, to_rgb import openmc import openmc.checkvalue as cv @@ -50,20 +51,20 @@ class Plot(object): Origin (center) of the plot filename : Path to write the plot to - color : {'cell', 'mat'} + color_by : {'cell', 'material'} Indicate whether the plot should be colored by cell or by material type : {'slice', 'voxel'} The type of the plot basis : {'xy', 'xz', 'yz'} The basis directions for the plot - background : tuple or list of ndarray + background : Iterable of int or str Color of the background defined by RGB - mask_components : Iterable of int - Unique id numbers of the cells or materials to plot + mask_components : Iterable of openmc.Cell or openmc.Material + The cells or materials to plot mask_background : Iterable of int Color to apply to all cells/materials not listed in mask_components defined by RGB - col_spec : dict + colors : dict Dictionary indicating that certain cells/materials (keys) should be colored with a specific RGB (values) level : int @@ -81,14 +82,14 @@ class Plot(object): self._width = [4.0, 4.0] self._pixels = [1000, 1000] self._origin = [0., 0., 0.] - self._filename = 'plot' - self._color = 'cell' + self._filename = None + self._color_by = 'cell' self._type = 'slice' self._basis = 'xy' self._background = None self._mask_components = None self._mask_background = None - self._col_spec = None + self._colors = {} self._level = None self._meshlines = None @@ -117,8 +118,8 @@ class Plot(object): return self._filename @property - def color(self): - return self._color + def color_by(self): + return self._color_by @property def type(self): @@ -141,8 +142,8 @@ class Plot(object): return self._mask_background @property - def col_spec(self): - return self._col_spec + def colors(self): + return self._colors @property def level(self): @@ -193,55 +194,51 @@ class Plot(object): cv.check_type('filename', filename, string_types) self._filename = filename - @color.setter - def color(self, color): - cv.check_type('plot color', color, string_types) - cv.check_value('plot color', color, ['cell', 'mat']) - self._color = color + @color_by.setter + def color_by(self, color_by): + cv.check_value('plot color_by', color_by, ['cell', 'material']) + self._color_by = color_by @type.setter def type(self, plottype): - cv.check_type('plot type', plottype, string_types) cv.check_value('plot type', plottype, ['slice', 'voxel']) self._type = plottype @basis.setter def basis(self, basis): - cv.check_type('plot basis', basis, string_types) cv.check_value('plot basis', basis, ['xy', 'xz', 'yz']) self._basis = basis @background.setter def background(self, background): - cv.check_type('plot background', background, Iterable, Integral) - cv.check_length('plot background', background, 3) - for rgb in background: - cv.check_greater_than('plot background', rgb, 0, True) - cv.check_less_than('plot background', rgb, 256) + cv.check_type('plot background', background, Iterable) + if isinstance(background, string_types): + if not is_color_like(background): + raise ValueError("'{}' is not a valid color.".format(background)) + else: + cv.check_length('plot background', background, 3) + for rgb in background: + cv.check_greater_than('plot background', rgb, 0, True) + cv.check_less_than('plot background', rgb, 256) self._background = background - @col_spec.setter - def col_spec(self, col_spec): - cv.check_type('plot col_spec parameter', col_spec, dict, Integral) + @colors.setter + def colors(self, colors): + cv.check_type('plot colors', colors, Mapping) + for key, value in colors.items(): + cv.check_type('plot color key', key, (openmc.Cell, openmc.Material)) + cv.check_type('plot color value', value, Iterable) + if isinstance(value, string_types): + if not is_color_like(value): + raise ValueError("'{}' is not a valid color.".format(value)) + else: + cv.check_length('plot color (RGB)', value, 3) + for component in value: + cv.check_type('RGB component', component, Real) + cv.check_greater_than('RGB component', component, 0, True) + cv.check_less_than('RGB component', component, 255, True) - for key in col_spec: - if key < 0: - msg = 'Unable to create Plot ID="{0}" with col_spec ID "{1}" ' \ - 'which is less than 0'.format(self._id, key) - raise ValueError(msg) - - elif not isinstance(col_spec[key], Iterable): - msg = 'Unable to create Plot ID="{0}" with col_spec RGB values' \ - ' "{1}" which is not iterable'.format(self._id, col_spec[key]) - raise ValueError(msg) - - elif len(col_spec[key]) != 3: - msg = 'Unable to create Plot ID="{0}" with col_spec RGB ' \ - 'values of length "{1}" since 3 values must be ' \ - 'input'.format(self._id, len(col_spec[key])) - raise ValueError(msg) - - self._col_spec = col_spec + self._colors = colors @mask_components.setter def mask_components(self, mask_components): @@ -300,25 +297,23 @@ class Plot(object): def __repr__(self): string = 'Plot\n' - string += '{0: <16}{1}{2}\n'.format('\tID', '=\t', self._id) - string += '{0: <16}{1}{2}\n'.format('\tName', '=\t', self._name) - string += '{0: <16}{1}{2}\n'.format('\tFilename', '=\t', self._filename) - string += '{0: <16}{1}{2}\n'.format('\tType', '=\t', self._type) - string += '{0: <16}{1}{2}\n'.format('\tBasis', '=\t', self._basis) - string += '{0: <16}{1}{2}\n'.format('\tWidth', '=\t', self._width) - string += '{0: <16}{1}{2}\n'.format('\tOrigin', '=\t', self._origin) - string += '{0: <16}{1}{2}\n'.format('\tPixels', '=\t', self._origin) - string += '{0: <16}{1}{2}\n'.format('\tColor', '=\t', self._color) - string += '{0: <16}{1}{2}\n'.format('\tBackground', '=\t', - self._background) - string += '{0: <16}{1}{2}\n'.format('\tMask components', '=\t', + string += '{: <16}=\t{}\n'.format('\tID', self._id) + string += '{: <16}=\t{}\n'.format('\tName', self._name) + string += '{: <16}=\t{}\n'.format('\tFilename', self._filename) + string += '{: <16}=\t{}\n'.format('\tType', self._type) + string += '{: <16}=\t{}\n'.format('\tBasis', self._basis) + string += '{: <16}=\t{}\n'.format('\tWidth', self._width) + string += '{: <16}=\t{}\n'.format('\tOrigin', self._origin) + string += '{: <16}=\t{}\n'.format('\tPixels', self._origin) + string += '{: <16}=\t{}\n'.format('\tColor by', self._color) + string += '{: <16}=\t{}\n'.format('\tBackground', self._background) + string += '{: <16}=\t{}\n'.format('\tMask components', self._mask_components) - string += '{0: <16}{1}{2}\n'.format('\tMask background', '=\t', + string += '{: <16}=\t{}\n'.format('\tMask background', self._mask_background) - string += '{0: <16}{1}{2}\n'.format('\tCol Spec', '=\t', self._col_spec) - string += '{0: <16}{1}{2}\n'.format('\tLevel', '=\t', self._level) - string += '{0: <16}{1}{2}\n'.format('\tMeshlines', '=\t', - self._meshlines) + string += '{: <16}=\t{}\n'.format('\tColors', self._colors) + string += '{: <16}=\t{}\n'.format('\tLevel', self._level) + string += '{: <16}=\t{}\n'.format('\tMeshlines', self._meshlines) return string def colorize(self, geometry, seed=1): @@ -341,78 +336,71 @@ class Plot(object): cv.check_greater_than('seed', seed, 1, equality=True) # Get collections of the domains which will be plotted - if self.color is 'mat': - domains = geometry.get_all_materials() + if self.color_by == 'material': + domains = geometry.get_all_materials().values() else: - domains = geometry.get_all_cells() + domains = geometry.get_all_cells().values() # Set the seed for the random number generator np.random.seed(seed) # Generate random colors for each feature - self.col_spec = {} - for domain_id in domains: - r = np.random.randint(0, 256) - g = np.random.randint(0, 256) - b = np.random.randint(0, 256) - self.col_spec[domain_id] = (r, g, b) + for domain in domains: + self.colors[domain] = np.random.randint(0, 256, (3,)) def highlight_domains(self, geometry, domains, seed=1, alpha=0.5, background='gray'): """Use alpha compositing to highlight one or more domains in the plot. - This routine generates a color scheme and applies alpha compositing - to make all domains except the highlighted ones appear partially + This routine generates a color scheme and applies alpha compositing to + make all domains except the highlighted ones appear partially transparent. Parameters ---------- geometry : openmc.Geometry The geometry for which the plot is defined - domains : Iterable of Integral + domains : Iterable of openmc.Cell or openmc.Material A collection of the domain IDs to highlight in the plot - seed : Integral + seed : int The random number seed used to generate the color scheme - alpha : Real in [0,1] + alpha : float The value to apply in alpha compisiting - background : 3-tuple of Integral or 'white' or 'black' or 'gray' + background : 3-tuple of int or str The background color to apply in alpha compisiting """ - cv.check_iterable_type('domains', domains, Integral) + cv.check_type('domains', domains, Iterable, + (openmc.Cell, openmc.Material)) cv.check_type('alpha', alpha, Real) cv.check_greater_than('alpha', alpha, 0., equality=True) cv.check_less_than('alpha', alpha, 1., equality=True) + cv.check_type('background', background, Iterable) # Get a background (R,G,B) tuple to apply in alpha compositing if isinstance(background, string_types): - if background == 'white': - background = (255, 255, 255) - elif background == 'black': - background = (0, 0, 0) - elif background == 'gray': - background = (160, 160, 160) - else: - msg = 'The background "{}" is not defined'.format(background) - raise ValueError(msg) - - cv.check_iterable_type('background', background, Integral) + try: + background = to_rgb(background) + except ValueError: + raise ValueError("'{}' is not a valid color.".format(background)) # Generate a color scheme self.colorize(geometry, seed) # Apply alpha compositing to the colors for all domains # other than those the user wishes to highlight - for domain_id in self.col_spec: - if domain_id not in domains: - r, g, b = self.col_spec[domain_id] + for domain, color in self.colors.items(): + if domain not in domains: + if isinstance(color, string_types): + color = [int(255*x) for x in to_rgb(color)] + r, g, b = color r = int(((1-alpha) * background[0]) + (alpha * r)) g = int(((1-alpha) * background[1]) + (alpha * g)) b = int(((1-alpha) * background[2]) + (alpha * b)) - self._col_spec[domain_id] = (r, g, b) + self._colors[domain] = (r, g, b) - def get_plot_xml(self): + def to_xml_element(self): """Return XML representation of the plot Returns @@ -424,8 +412,9 @@ class Plot(object): element = ET.Element("plot") element.set("id", str(self._id)) - element.set("filename", self._filename) - element.set("color", self._color) + if self._filename is not None: + element.set("filename", self._filename) + element.set("color_by", self._color_by) element.set("type", self._type) if self._type is 'slice': @@ -442,14 +431,18 @@ class Plot(object): if self._background is not None: subelement = ET.SubElement(element, "background") - subelement.text = ' '.join(map(str, self._background)) + color = self._background + if isinstance(color, string_types): + color = [int(255*x) for x in to_rgb(color)] + subelement.text = ' '.join(str(x) for x in color) - if self._col_spec is not None: - for key in self._col_spec: - subelement = ET.SubElement(element, "col_spec") - subelement.set("id", str(key)) - subelement.set("rgb", ' '.join(map( - str, self._col_spec[key]))) + if self._colors: + for domain, color in self._colors.items(): + subelement = ET.SubElement(element, "color") + subelement.set("id", str(domain.id)) + if isinstance(color, string_types): + color = [int(255*x) for x in to_rgb(color)] + subelement.set("rgb", ' '.join(str(x) for x in color)) if self._mask_components is not None: subelement = ET.SubElement(element, "mask") @@ -585,20 +578,21 @@ class Plots(cv.CheckedList): alpha=0.5, background='gray'): """Use alpha compositing to highlight one or more domains in the plot. - This routine generates a color scheme and applies alpha compositing - to make all domains except the highlighted ones partially transparent. + This routine generates a color scheme and applies alpha compositing to + make all domains except the highlighted ones appear partially + transparent. Parameters ---------- geometry : openmc.Geometry The geometry for which the plot is defined - domains : Iterable of Integral + domains : Iterable of openmc.Cell or openmc.Material A collection of the domain IDs to highlight in the plot - seed : Integral + seed : int The random number seed used to generate the color scheme - alpha : Real in [0,1] + alpha : float The value to apply in alpha compisiting - background : 3-tuple of Integral or 'white' or 'black' or 'gray' + background : 3-tuple of int or str The background color to apply in alpha compisiting """ @@ -608,7 +602,7 @@ class Plots(cv.CheckedList): def _create_plot_subelements(self): for plot in self: - xml_element = plot.get_plot_xml() + xml_element = plot.to_xml_element() if len(plot.name) > 0: self._plots_file.append(ET.Comment(plot.name)) diff --git a/openmc/universe.py b/openmc/universe.py index 4cc3f482e..506bacef4 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -225,7 +225,6 @@ class Universe(object): color_by : {'cell', 'material'} Indicate whether the plot should be colored by cell or by material colors : dict - Assigns colors to specific materials or cells. Keys are instances of :class:`Cell` or :class:`Material` and values are RGB 3-tuples or RGBA 4-tuples. Red, green, blue, and alpha should all be floats in diff --git a/src/input_xml.F90 b/src/input_xml.F90 index e7365330c..3d8e32750 100644 --- a/src/input_xml.F90 +++ b/src/input_xml.F90 @@ -4364,8 +4364,8 @@ contains ! Copy plot color type and initialize all colors randomly temp_str = "cell" - if (check_for_node(node_plot, "color")) & - call get_node_value(node_plot, "color", temp_str) + if (check_for_node(node_plot, "color_by")) & + call get_node_value(node_plot, "color_by", temp_str) temp_str = to_lower(temp_str) select case (trim(temp_str)) case ("cell") @@ -4378,7 +4378,7 @@ contains pl % colors(j) % rgb(3) = int(prn()*255) end do - case ("mat", "material") + case ("material") pl % color_by = PLOT_COLOR_MATS allocate(pl % colors(n_materials)) @@ -4393,8 +4393,8 @@ contains // "' in plot " // trim(to_str(pl % id))) end select - ! Get the number of nodes and get a list of them - call get_node_list(node_plot, "col_spec", node_col_list) + ! Get the number of nodes and get a list of them + call get_node_list(node_plot, "color", node_col_list) n_cols = size(node_col_list) ! Copy user specified colors diff --git a/src/relaxng/plots.rnc b/src/relaxng/plots.rnc index 5ef14f229..e53cc15f7 100644 --- a/src/relaxng/plots.rnc +++ b/src/relaxng/plots.rnc @@ -5,8 +5,8 @@ element plots { attribute filename { xsd:string { maxLength = "50" } })? & (element type { "slice" | "voxel" } | attribute type { "slice" | "voxel" })? & - (element color { ( "cell" | "mat" | "material" ) } | - attribute color { ( "cell" | "mat" | "material" ) })? & + (element color_by { ( "cell" | "material" ) } | + attribute color_by { ( "cell" | "material" ) })? & (element level { xsd:int } | attribute level { xsd:int })? & (element origin { list { xsd:double+ } } | attribute origin { list { xsd:double+ } })? & @@ -18,7 +18,7 @@ element plots { attribute pixels { list { xsd:int+ } })? & (element background { list { xsd:int+ } } | attribute background { list { xsd:int+ } })? & - element col_spec { + element color { (element id { xsd:int } | attribute id { xsd:int }) & (element rgb { list { xsd:int+ } } | attribute rgb { list { xsd:int+ } }) diff --git a/src/relaxng/plots.rng b/src/relaxng/plots.rng index a21f4d141..55d69008e 100644 --- a/src/relaxng/plots.rng +++ b/src/relaxng/plots.rng @@ -45,17 +45,15 @@ - + cell - mat material - + cell - mat material @@ -162,7 +160,7 @@ - + diff --git a/tests/input_set.py b/tests/input_set.py index 7971a8a4c..ce5e3d5bc 100644 --- a/tests/input_set.py +++ b/tests/input_set.py @@ -471,7 +471,7 @@ class InputSet(object): plot.origin = (125, 125, 0) plot.width = (250, 250) plot.pixels = (3000, 3000) - plot.color = 'mat' + plot.color_by = 'material' self.plots.add_plot(plot) @@ -563,7 +563,7 @@ class PinCellInputSet(object): plot.origin = (0.0, 0.0, 0) plot.width = (1.26, 1.26) plot.pixels = (300, 300) - plot.color = 'mat' + plot.color_by = 'material' self.plots.add_plot(plot) @@ -714,7 +714,7 @@ class AssemblyInputSet(object): plot.origin = (0.0, 0.0, 0) plot.width = (21.42, 21.42) plot.pixels = (300, 300) - plot.color = 'mat' + plot.color_by = 'material' self.plots.add_plot(plot) @@ -793,6 +793,6 @@ class MGInputSet(InputSet): plot.width = (2.5, 2.5) plot.basis = 'xz' plot.pixels = (3000, 3000) - plot.color = 'mat' + plot.color_by = 'material' self.plots.add_plot(plot) diff --git a/tests/test_distribmat/inputs_true.dat b/tests/test_distribmat/inputs_true.dat index 746bb8bef..2d3e39a65 100644 --- a/tests/test_distribmat/inputs_true.dat +++ b/tests/test_distribmat/inputs_true.dat @@ -52,12 +52,12 @@ - + 0 0 0 7 7 400 400 - + 0 0 0 7 7 400 400 diff --git a/tests/test_distribmat/test_distribmat.py b/tests/test_distribmat/test_distribmat.py index 6c1c5f79c..2816bbfbc 100644 --- a/tests/test_distribmat/test_distribmat.py +++ b/tests/test_distribmat/test_distribmat.py @@ -95,7 +95,7 @@ class DistribmatTestHarness(PyAPITestHarness): plot = openmc.Plot(plot_id=1) plot.basis = 'xy' - plot.color = 'cell' + plot.color_by = 'cell' plot.filename = 'cellplot' plot.origin = (0, 0, 0) plot.width = (7, 7) @@ -104,7 +104,7 @@ class DistribmatTestHarness(PyAPITestHarness): plot = openmc.Plot(plot_id=2) plot.basis = 'xy' - plot.color = 'mat' + plot.color_by = 'material' plot.filename = 'matplot' plot.origin = (0, 0, 0) plot.width = (7, 7) diff --git a/tests/test_lattice_hex/plots.xml b/tests/test_lattice_hex/plots.xml index 651c81144..903d69aef 100644 --- a/tests/test_lattice_hex/plots.xml +++ b/tests/test_lattice_hex/plots.xml @@ -1,28 +1,28 @@ - + xy_cell 0 0 0 30 30 500 500 - + xy_material 0 0 0 30 30 500 500 - + yz_cell 0 0 0 50 400 500 4000 - + yz_material 0 0 0 5 5 diff --git a/tests/test_lattice_mixed/plots.xml b/tests/test_lattice_mixed/plots.xml index 651c81144..903d69aef 100644 --- a/tests/test_lattice_mixed/plots.xml +++ b/tests/test_lattice_mixed/plots.xml @@ -1,28 +1,28 @@ - + xy_cell 0 0 0 30 30 500 500 - + xy_material 0 0 0 30 30 500 500 - + yz_cell 0 0 0 50 400 500 4000 - + yz_material 0 0 0 5 5 diff --git a/tests/test_multipole/inputs_true.dat b/tests/test_multipole/inputs_true.dat index 2a1e865ad..ee1ba636e 100644 --- a/tests/test_multipole/inputs_true.dat +++ b/tests/test_multipole/inputs_true.dat @@ -51,12 +51,12 @@ - + 0 0 0 7 7 400 400 - + 0 0 0 7 7 400 400 diff --git a/tests/test_multipole/test_multipole.py b/tests/test_multipole/test_multipole.py index 85c360e73..33a9295db 100644 --- a/tests/test_multipole/test_multipole.py +++ b/tests/test_multipole/test_multipole.py @@ -79,7 +79,7 @@ class MultipoleTestHarness(PyAPITestHarness): plot = openmc.Plot(plot_id=1) plot.basis = 'xy' - plot.color = 'cell' + plot.color_by = 'cell' plot.filename = 'cellplot' plot.origin = (0, 0, 0) plot.width = (7, 7) @@ -88,7 +88,7 @@ class MultipoleTestHarness(PyAPITestHarness): plot = openmc.Plot(plot_id=2) plot.basis = 'xy' - plot.color = 'mat' + plot.color_by = 'material' plot.filename = 'matplot' plot.origin = (0, 0, 0) plot.width = (7, 7) diff --git a/tests/test_plot/plots.xml b/tests/test_plot/plots.xml index d5e03f598..ecfe69125 100644 --- a/tests/test_plot/plots.xml +++ b/tests/test_plot/plots.xml @@ -5,7 +5,7 @@ 0. 0. 0. 25 25 200 200 - + @@ -16,7 +16,7 @@ - + 0. 0. 0. 25 25 200 200 diff --git a/tests/test_triso/plots.xml b/tests/test_triso/plots.xml index 60ae7d9d8..eafe3206b 100644 --- a/tests/test_triso/plots.xml +++ b/tests/test_triso/plots.xml @@ -1,6 +1,6 @@ -