mirror of
https://github.com/openmc-dev/openmc.git
synced 2026-07-26 21:25:36 -04:00
Allow color names, rename Plot attributes, add openmc.plot_inline()
This commit is contained in:
parent
24cd12cf3a
commit
3913d55e2c
28 changed files with 219 additions and 190 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -188,6 +188,7 @@ Running OpenMC
|
|||
openmc.run
|
||||
openmc.calculate_volumes
|
||||
openmc.plot_geometry
|
||||
openmc.plot_inline
|
||||
|
||||
Post-processing
|
||||
---------------
|
||||
|
|
|
|||
|
|
@ -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 ``<plot>`` 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
|
||||
|
||||
<col_spec id="23" rgb="0 0 255" />
|
||||
<color id="23" rgb="0 0 255" />
|
||||
|
||||
*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
|
||||
|
|
|
|||
|
|
@ -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])
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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])
|
||||
|
|
|
|||
|
|
@ -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])
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0"?>
|
||||
<plots>
|
||||
<plot id="1" type="slice">
|
||||
<color>cell</color>
|
||||
<color_by>cell</color_by>
|
||||
<origin>0. 0. 0.</origin>
|
||||
<width>20. 20.</width>
|
||||
<pixels>200 200</pixels>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0"?>
|
||||
<plots>
|
||||
|
||||
<plot id="1" color="mat">
|
||||
<plot id="1" color_by="material">
|
||||
<origin>0. 0. 0.</origin>
|
||||
<width>4.0 4.0</width>
|
||||
<pixels>400 400</pixels>
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
<?xml version="1.0"?>
|
||||
<plots>
|
||||
|
||||
<plot id="1" color="mat">
|
||||
<plot id="1" color_by="material">
|
||||
<origin>0. 0. 0.</origin>
|
||||
<width>4.0 4.0</width>
|
||||
<pixels>400 400</pixels>
|
||||
<!-- <meshlines mesh="1" linewidth="2" color="0 255 0"/> -->
|
||||
</plot>
|
||||
|
||||
</plots>
|
||||
|
|
|
|||
|
|
@ -4,21 +4,21 @@
|
|||
<plot>
|
||||
<id>1</id>
|
||||
<filename>mat</filename>
|
||||
<color>material</color>
|
||||
<color_by>material</color_by>
|
||||
<origin>0 0 0</origin>
|
||||
<width>1.26 1.26</width>
|
||||
<type>slice</type>
|
||||
<pixels>1000 1000 </pixels>
|
||||
<col_spec id="1" rgb="255 0 0" />
|
||||
<col_spec id="2" rgb="0 0 0" />
|
||||
<col_spec id="3" rgb="0 255 0" />
|
||||
<col_spec id="4" rgb="0 0 255" />
|
||||
<color id="1" rgb="255 0 0" />
|
||||
<color id="2" rgb="0 0 0" />
|
||||
<color id="3" rgb="0 255 0" />
|
||||
<color id="4" rgb="0 0 255" />
|
||||
</plot>
|
||||
|
||||
<plot>
|
||||
<id>2</id>
|
||||
<filename>cell</filename>
|
||||
<color>cell</color>
|
||||
<color_by>cell</color_by>
|
||||
<origin>0 0 0</origin>
|
||||
<width>1.26 1.26</width>
|
||||
<type>slice</type>
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
216
openmc/plots.py
216
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))
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 <col_spec> nodes and get a list of them
|
||||
call get_node_list(node_plot, "col_spec", node_col_list)
|
||||
! Get the number of <color> 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
|
||||
|
|
|
|||
|
|
@ -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+ } })
|
||||
|
|
|
|||
|
|
@ -45,17 +45,15 @@
|
|||
</optional>
|
||||
<optional>
|
||||
<choice>
|
||||
<element name="color">
|
||||
<element name="color_by">
|
||||
<choice>
|
||||
<value>cell</value>
|
||||
<value>mat</value>
|
||||
<value>material</value>
|
||||
</choice>
|
||||
</element>
|
||||
<attribute name="color">
|
||||
<attribute name="color_by">
|
||||
<choice>
|
||||
<value>cell</value>
|
||||
<value>mat</value>
|
||||
<value>material</value>
|
||||
</choice>
|
||||
</attribute>
|
||||
|
|
@ -162,7 +160,7 @@
|
|||
</choice>
|
||||
</optional>
|
||||
<zeroOrMore>
|
||||
<element name="col_spec">
|
||||
<element name="color">
|
||||
<interleave>
|
||||
<choice>
|
||||
<element name="id">
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -52,12 +52,12 @@
|
|||
</settings>
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<plots>
|
||||
<plot basis="xy" color="cell" filename="cellplot" id="1" type="slice">
|
||||
<plot basis="xy" color_by="cell" filename="cellplot" id="1" type="slice">
|
||||
<origin>0 0 0</origin>
|
||||
<width>7 7</width>
|
||||
<pixels>400 400</pixels>
|
||||
</plot>
|
||||
<plot basis="xy" color="mat" filename="matplot" id="2" type="slice">
|
||||
<plot basis="xy" color_by="material" filename="matplot" id="2" type="slice">
|
||||
<origin>0 0 0</origin>
|
||||
<width>7 7</width>
|
||||
<pixels>400 400</pixels>
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -1,28 +1,28 @@
|
|||
<?xml version="1.0"?>
|
||||
<plots>
|
||||
|
||||
<plot id="1" type="slice" basis="xy" color="cell">
|
||||
<plot id="1" type="slice" basis="xy" color_by="cell">
|
||||
<filename>xy_cell</filename>
|
||||
<origin>0 0 0</origin>
|
||||
<width>30 30</width>
|
||||
<pixels>500 500</pixels>
|
||||
</plot>
|
||||
|
||||
<plot id="2" type="slice" basis="xy" color="material">
|
||||
<plot id="2" type="slice" basis="xy" color_by="material">
|
||||
<filename>xy_material</filename>
|
||||
<origin>0 0 0</origin>
|
||||
<width>30 30</width>
|
||||
<pixels>500 500</pixels>
|
||||
</plot>
|
||||
|
||||
<plot id="3" type="slice" basis="yz" color="cell">
|
||||
<plot id="3" type="slice" basis="yz" color_by="cell">
|
||||
<filename>yz_cell</filename>
|
||||
<origin>0 0 0</origin>
|
||||
<width>50 400</width>
|
||||
<pixels>500 4000</pixels>
|
||||
</plot>
|
||||
|
||||
<plot id="4" type="slice" basis="yz" color="material">
|
||||
<plot id="4" type="slice" basis="yz" color_by="material">
|
||||
<filename>yz_material</filename>
|
||||
<origin>0 0 0</origin>
|
||||
<width>5 5</width>
|
||||
|
|
|
|||
|
|
@ -1,28 +1,28 @@
|
|||
<?xml version="1.0"?>
|
||||
<plots>
|
||||
|
||||
<plot id="1" type="slice" basis="xy" color="cell">
|
||||
<plot id="1" type="slice" basis="xy" color_by="cell">
|
||||
<filename>xy_cell</filename>
|
||||
<origin>0 0 0</origin>
|
||||
<width>30 30</width>
|
||||
<pixels>500 500</pixels>
|
||||
</plot>
|
||||
|
||||
<plot id="2" type="slice" basis="xy" color="material">
|
||||
<plot id="2" type="slice" basis="xy" color_by="material">
|
||||
<filename>xy_material</filename>
|
||||
<origin>0 0 0</origin>
|
||||
<width>30 30</width>
|
||||
<pixels>500 500</pixels>
|
||||
</plot>
|
||||
|
||||
<plot id="3" type="slice" basis="yz" color="cell">
|
||||
<plot id="3" type="slice" basis="yz" color_by="cell">
|
||||
<filename>yz_cell</filename>
|
||||
<origin>0 0 0</origin>
|
||||
<width>50 400</width>
|
||||
<pixels>500 4000</pixels>
|
||||
</plot>
|
||||
|
||||
<plot id="4" type="slice" basis="yz" color="material">
|
||||
<plot id="4" type="slice" basis="yz" color_by="material">
|
||||
<filename>yz_material</filename>
|
||||
<origin>0 0 0</origin>
|
||||
<width>5 5</width>
|
||||
|
|
|
|||
|
|
@ -51,12 +51,12 @@
|
|||
</settings>
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<plots>
|
||||
<plot basis="xy" color="cell" filename="cellplot" id="1" type="slice">
|
||||
<plot basis="xy" color_by="cell" filename="cellplot" id="1" type="slice">
|
||||
<origin>0 0 0</origin>
|
||||
<width>7 7</width>
|
||||
<pixels>400 400</pixels>
|
||||
</plot>
|
||||
<plot basis="xy" color="mat" filename="matplot" id="2" type="slice">
|
||||
<plot basis="xy" color_by="material" filename="matplot" id="2" type="slice">
|
||||
<origin>0 0 0</origin>
|
||||
<width>7 7</width>
|
||||
<pixels>400 400</pixels>
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
<origin>0. 0. 0.</origin>
|
||||
<width>25 25</width>
|
||||
<pixels>200 200</pixels>
|
||||
<col_spec id="1" rgb="255 0 0" /> <!-- Red -->
|
||||
<color id="1" rgb="255 0 0" /> <!-- Red -->
|
||||
<meshlines meshtype="entropy" linewidth="0" />
|
||||
</plot>
|
||||
|
||||
|
|
@ -16,7 +16,7 @@
|
|||
<mask components="1 3" background="255 255 255" />
|
||||
</plot>
|
||||
|
||||
<plot id="3" basis="yz" color="mat">
|
||||
<plot id="3" basis="yz" color_by="material">
|
||||
<origin>0. 0. 0.</origin>
|
||||
<width>25 25</width>
|
||||
<pixels>200 200</pixels>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0"?>
|
||||
<plots>
|
||||
<plot id="1" type="slice" basis="xy" color="material"
|
||||
<plot id="1" type="slice" basis="xy" color_by="material"
|
||||
origin="0.0 0.0 0.0" width="1.0 1.0" pixels="400 400">
|
||||
</plot>
|
||||
</plots>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue