[yt-svn] commit/yt: 13 new changesets
commits-noreply at bitbucket.org
commits-noreply at bitbucket.org
Tue Jan 10 08:00:32 PST 2017
13 new commits in yt:
https://bitbucket.org/yt_analysis/yt/commits/7b9bbe1566a2/
Changeset: 7b9bbe1566a2
Branch: yt
User: atmyers
Date: 2016-09-28 21:53:18+00:00
Summary: Add sampler type for 1D linear elements.
Affected #: 4 files
diff -r 1d70bf4124996d584483c173e37f29670a73db99 -r 7b9bbe1566a22ebca39f1fc6a2971ddcb9d7acb6 yt/utilities/lib/element_mappings.pxd
--- a/yt/utilities/lib/element_mappings.pxd
+++ b/yt/utilities/lib/element_mappings.pxd
@@ -33,6 +33,21 @@
cdef int check_mesh_lines(self, double* mapped_coord) nogil
+cdef class P1Sampler1D(ElementSampler):
+
+ cdef void map_real_to_unit(self,
+ double* mapped_x,
+ double* vertices,
+ double* physical_x) nogil
+
+
+ cdef double sample_at_unit_point(self,
+ double* coord,
+ double* vals) nogil
+
+ cdef int check_inside(self, double* mapped_coord) nogil
+
+
cdef class P1Sampler2D(ElementSampler):
cdef void map_real_to_unit(self,
diff -r 1d70bf4124996d584483c173e37f29670a73db99 -r 7b9bbe1566a22ebca39f1fc6a2971ddcb9d7acb6 yt/utilities/lib/element_mappings.pyx
--- a/yt/utilities/lib/element_mappings.pyx
+++ b/yt/utilities/lib/element_mappings.pyx
@@ -115,6 +115,41 @@
return val
+cdef class P1Sampler1D(ElementSampler):
+ '''
+
+ This implements sampling inside a linear, 1D element.
+
+ '''
+
+ def __init__(self):
+ super(P1Sampler1D, self).__init__()
+ self.num_mapped_coords = 1
+
+ @cython.boundscheck(False)
+ @cython.wraparound(False)
+ @cython.cdivision(True)
+ cdef void map_real_to_unit(self, double* mapped_x,
+ double* vertices, double* physical_x) nogil:
+ mapped_x[0] = -1.0 + 2.0*(physical_x[0] - vertices[0]) / (vertices[1] - vertices[0])
+
+ @cython.boundscheck(False)
+ @cython.wraparound(False)
+ @cython.cdivision(True)
+ cdef double sample_at_unit_point(self,
+ double* coord,
+ double* vals) nogil:
+ return vals[0] * (1 - coord[0]) / 2.0 + vals[1] * (1.0 + coord[0]) / 2.0
+
+ @cython.boundscheck(False)
+ @cython.wraparound(False)
+ @cython.cdivision(True)
+ cdef int check_inside(self, double* mapped_coord) nogil:
+ if (fabs(mapped_coord[0]) - 1.0 > self.inclusion_tol):
+ return 0
+ return 1
+
+
cdef class P1Sampler2D(ElementSampler):
'''
@@ -972,6 +1007,24 @@
@cython.boundscheck(False)
@cython.wraparound(False)
@cython.cdivision(True)
+def test_linear1D_sampler(np.ndarray[np.float64_t, ndim=2] vertices,
+ np.ndarray[np.float64_t, ndim=1] field_values,
+ np.ndarray[np.float64_t, ndim=1] physical_x):
+
+ cdef double val
+
+ sampler = P1Sampler1D()
+
+ val = sampler.sample_at_real_point(<double*> vertices.data,
+ <double*> field_values.data,
+ <double*> physical_x.data)
+
+ return val
+
+
+ at cython.boundscheck(False)
+ at cython.wraparound(False)
+ at cython.cdivision(True)
def test_tri_sampler(np.ndarray[np.float64_t, ndim=2] vertices,
np.ndarray[np.float64_t, ndim=1] field_values,
np.ndarray[np.float64_t, ndim=1] physical_x):
diff -r 1d70bf4124996d584483c173e37f29670a73db99 -r 7b9bbe1566a22ebca39f1fc6a2971ddcb9d7acb6 yt/utilities/lib/tests/test_element_mappings.py
--- a/yt/utilities/lib/tests/test_element_mappings.py
+++ b/yt/utilities/lib/tests/test_element_mappings.py
@@ -24,7 +24,8 @@
test_hex20_sampler, \
test_wedge_sampler, \
test_tri2_sampler, \
- test_tet2_sampler
+ test_tet2_sampler, \
+ test_linear1D_sampler
def check_all_vertices(sampler, vertices, field_values):
@@ -37,6 +38,14 @@
assert_almost_equal(val, field_values[i])
+def test_P1Sampler1D():
+
+ vertices = np.array([[0.1], [0.3]])
+ field_values = np.array([ 1., 2.])
+
+ check_all_vertices(test_linear1D_sampler, vertices, field_values)
+
+
def test_P1Sampler2D():
vertices = np.array([[0.1, 0.2], [0.6, 0.3], [0.2, 0.7]])
diff -r 1d70bf4124996d584483c173e37f29670a73db99 -r 7b9bbe1566a22ebca39f1fc6a2971ddcb9d7acb6 yt/visualization/profile_plotter.py
--- a/yt/visualization/profile_plotter.py
+++ b/yt/visualization/profile_plotter.py
@@ -235,7 +235,7 @@
plot_spec = [plot_spec.copy() for p in profiles]
ProfilePlot._initialize_instance(self, profiles, label, plot_spec, y_log)
-
+
@validate_plot
def save(self, name=None, suffix=None, mpl_kwargs=None):
r"""
https://bitbucket.org/yt_analysis/yt/commits/faa010ec09a1/
Changeset: faa010ec09a1
Branch: yt
User: atmyers
Date: 2016-09-28 21:53:08+00:00
Summary: patch the element mesh pixelizer to also work with 1D data
Affected #: 1 file
diff -r 9b5937af58578d073179329863c7e220f8ec7df6 -r faa010ec09a1f5c4feb5a0027a02dd494b397804 yt/utilities/lib/pixelization_routines.pyx
--- a/yt/utilities/lib/pixelization_routines.pyx
+++ b/yt/utilities/lib/pixelization_routines.pyx
@@ -25,11 +25,12 @@
from vec3_ops cimport dot, cross, subtract
from yt.utilities.lib.element_mappings cimport \
ElementSampler, \
+ P1Sampler1D, \
+ P1Sampler2D, \
P1Sampler3D, \
Q1Sampler3D, \
+ Q1Sampler2D, \
S2Sampler3D, \
- P1Sampler2D, \
- Q1Sampler2D, \
W1Sampler3D, \
T2Sampler2D, \
Tet2Sampler3D
@@ -594,6 +595,8 @@
sampler = S2Sampler3D()
elif ndim == 2 and nvertices == 3:
sampler = P1Sampler2D()
+ elif ndim == 1 and nvertices == 2:
+ sampler = P1Sampler1D()
elif ndim == 2 and nvertices == 4:
sampler = Q1Sampler2D()
elif ndim == 2 and nvertices == 6:
@@ -648,10 +651,13 @@
pstart[i] = i64max(<np.int64_t> ((LE[i] - pLE[i])*idds[i]) - 1, 0)
pend[i] = i64min(<np.int64_t> ((RE[i] - pLE[i])*idds[i]) + 1, img.shape[i]-1)
- # override for the 2D case
- if ndim == 2:
+ # override for the low-dimensional case
+ if ndim < 3:
pstart[2] = 0
pend[2] = 0
+ if ndim < 2:
+ pstart[1] = 0
+ pend[1] = 0
if use == 0:
continue
https://bitbucket.org/yt_analysis/yt/commits/2e22ef06260d/
Changeset: 2e22ef06260d
Branch: yt
User: atmyers
Date: 2016-09-28 21:53:18+00:00
Summary: Add sampler type for 1D linear elements.
Affected #: 4 files
diff -r faa010ec09a1f5c4feb5a0027a02dd494b397804 -r 2e22ef06260ded3154b96f49cf0d856589c67132 yt/utilities/lib/element_mappings.pxd
--- a/yt/utilities/lib/element_mappings.pxd
+++ b/yt/utilities/lib/element_mappings.pxd
@@ -33,6 +33,21 @@
cdef int check_mesh_lines(self, double* mapped_coord) nogil
+cdef class P1Sampler1D(ElementSampler):
+
+ cdef void map_real_to_unit(self,
+ double* mapped_x,
+ double* vertices,
+ double* physical_x) nogil
+
+
+ cdef double sample_at_unit_point(self,
+ double* coord,
+ double* vals) nogil
+
+ cdef int check_inside(self, double* mapped_coord) nogil
+
+
cdef class P1Sampler2D(ElementSampler):
cdef void map_real_to_unit(self,
diff -r faa010ec09a1f5c4feb5a0027a02dd494b397804 -r 2e22ef06260ded3154b96f49cf0d856589c67132 yt/utilities/lib/element_mappings.pyx
--- a/yt/utilities/lib/element_mappings.pyx
+++ b/yt/utilities/lib/element_mappings.pyx
@@ -115,6 +115,41 @@
return val
+cdef class P1Sampler1D(ElementSampler):
+ '''
+
+ This implements sampling inside a linear, 1D element.
+
+ '''
+
+ def __init__(self):
+ super(P1Sampler1D, self).__init__()
+ self.num_mapped_coords = 1
+
+ @cython.boundscheck(False)
+ @cython.wraparound(False)
+ @cython.cdivision(True)
+ cdef void map_real_to_unit(self, double* mapped_x,
+ double* vertices, double* physical_x) nogil:
+ mapped_x[0] = -1.0 + 2.0*(physical_x[0] - vertices[0]) / (vertices[1] - vertices[0])
+
+ @cython.boundscheck(False)
+ @cython.wraparound(False)
+ @cython.cdivision(True)
+ cdef double sample_at_unit_point(self,
+ double* coord,
+ double* vals) nogil:
+ return vals[0] * (1 - coord[0]) / 2.0 + vals[1] * (1.0 + coord[0]) / 2.0
+
+ @cython.boundscheck(False)
+ @cython.wraparound(False)
+ @cython.cdivision(True)
+ cdef int check_inside(self, double* mapped_coord) nogil:
+ if (fabs(mapped_coord[0]) - 1.0 > self.inclusion_tol):
+ return 0
+ return 1
+
+
cdef class P1Sampler2D(ElementSampler):
'''
@@ -972,6 +1007,24 @@
@cython.boundscheck(False)
@cython.wraparound(False)
@cython.cdivision(True)
+def test_linear1D_sampler(np.ndarray[np.float64_t, ndim=2] vertices,
+ np.ndarray[np.float64_t, ndim=1] field_values,
+ np.ndarray[np.float64_t, ndim=1] physical_x):
+
+ cdef double val
+
+ sampler = P1Sampler1D()
+
+ val = sampler.sample_at_real_point(<double*> vertices.data,
+ <double*> field_values.data,
+ <double*> physical_x.data)
+
+ return val
+
+
+ at cython.boundscheck(False)
+ at cython.wraparound(False)
+ at cython.cdivision(True)
def test_tri_sampler(np.ndarray[np.float64_t, ndim=2] vertices,
np.ndarray[np.float64_t, ndim=1] field_values,
np.ndarray[np.float64_t, ndim=1] physical_x):
diff -r faa010ec09a1f5c4feb5a0027a02dd494b397804 -r 2e22ef06260ded3154b96f49cf0d856589c67132 yt/utilities/lib/tests/test_element_mappings.py
--- a/yt/utilities/lib/tests/test_element_mappings.py
+++ b/yt/utilities/lib/tests/test_element_mappings.py
@@ -24,7 +24,8 @@
test_hex20_sampler, \
test_wedge_sampler, \
test_tri2_sampler, \
- test_tet2_sampler
+ test_tet2_sampler, \
+ test_linear1D_sampler
def check_all_vertices(sampler, vertices, field_values):
@@ -37,6 +38,14 @@
assert_almost_equal(val, field_values[i])
+def test_P1Sampler1D():
+
+ vertices = np.array([[0.1], [0.3]])
+ field_values = np.array([ 1., 2.])
+
+ check_all_vertices(test_linear1D_sampler, vertices, field_values)
+
+
def test_P1Sampler2D():
vertices = np.array([[0.1, 0.2], [0.6, 0.3], [0.2, 0.7]])
diff -r faa010ec09a1f5c4feb5a0027a02dd494b397804 -r 2e22ef06260ded3154b96f49cf0d856589c67132 yt/visualization/profile_plotter.py
--- a/yt/visualization/profile_plotter.py
+++ b/yt/visualization/profile_plotter.py
@@ -235,7 +235,7 @@
plot_spec = [plot_spec.copy() for p in profiles]
ProfilePlot._initialize_instance(self, profiles, label, plot_spec, y_log)
-
+
@validate_plot
def save(self, name=None, suffix=None, mpl_kwargs=None):
r"""
https://bitbucket.org/yt_analysis/yt/commits/b1316c90c0f9/
Changeset: b1316c90c0f9
Branch: yt
User: atmyers
Date: 2016-09-28 22:57:31+00:00
Summary: merging
Affected #: 5 files
diff -r 098f53627175f611a2b5c45e69efbd5048bb70fb -r b1316c90c0f97d1189bd3920c16ed24969b9206c yt/utilities/lib/element_mappings.pxd
--- a/yt/utilities/lib/element_mappings.pxd
+++ b/yt/utilities/lib/element_mappings.pxd
@@ -33,6 +33,21 @@
cdef int check_mesh_lines(self, double* mapped_coord) nogil
+cdef class P1Sampler1D(ElementSampler):
+
+ cdef void map_real_to_unit(self,
+ double* mapped_x,
+ double* vertices,
+ double* physical_x) nogil
+
+
+ cdef double sample_at_unit_point(self,
+ double* coord,
+ double* vals) nogil
+
+ cdef int check_inside(self, double* mapped_coord) nogil
+
+
cdef class P1Sampler2D(ElementSampler):
cdef void map_real_to_unit(self,
diff -r 098f53627175f611a2b5c45e69efbd5048bb70fb -r b1316c90c0f97d1189bd3920c16ed24969b9206c yt/utilities/lib/element_mappings.pyx
--- a/yt/utilities/lib/element_mappings.pyx
+++ b/yt/utilities/lib/element_mappings.pyx
@@ -115,6 +115,41 @@
return val
+cdef class P1Sampler1D(ElementSampler):
+ '''
+
+ This implements sampling inside a linear, 1D element.
+
+ '''
+
+ def __init__(self):
+ super(P1Sampler1D, self).__init__()
+ self.num_mapped_coords = 1
+
+ @cython.boundscheck(False)
+ @cython.wraparound(False)
+ @cython.cdivision(True)
+ cdef void map_real_to_unit(self, double* mapped_x,
+ double* vertices, double* physical_x) nogil:
+ mapped_x[0] = -1.0 + 2.0*(physical_x[0] - vertices[0]) / (vertices[1] - vertices[0])
+
+ @cython.boundscheck(False)
+ @cython.wraparound(False)
+ @cython.cdivision(True)
+ cdef double sample_at_unit_point(self,
+ double* coord,
+ double* vals) nogil:
+ return vals[0] * (1 - coord[0]) / 2.0 + vals[1] * (1.0 + coord[0]) / 2.0
+
+ @cython.boundscheck(False)
+ @cython.wraparound(False)
+ @cython.cdivision(True)
+ cdef int check_inside(self, double* mapped_coord) nogil:
+ if (fabs(mapped_coord[0]) - 1.0 > self.inclusion_tol):
+ return 0
+ return 1
+
+
cdef class P1Sampler2D(ElementSampler):
'''
@@ -972,6 +1007,24 @@
@cython.boundscheck(False)
@cython.wraparound(False)
@cython.cdivision(True)
+def test_linear1D_sampler(np.ndarray[np.float64_t, ndim=2] vertices,
+ np.ndarray[np.float64_t, ndim=1] field_values,
+ np.ndarray[np.float64_t, ndim=1] physical_x):
+
+ cdef double val
+
+ sampler = P1Sampler1D()
+
+ val = sampler.sample_at_real_point(<double*> vertices.data,
+ <double*> field_values.data,
+ <double*> physical_x.data)
+
+ return val
+
+
+ at cython.boundscheck(False)
+ at cython.wraparound(False)
+ at cython.cdivision(True)
def test_tri_sampler(np.ndarray[np.float64_t, ndim=2] vertices,
np.ndarray[np.float64_t, ndim=1] field_values,
np.ndarray[np.float64_t, ndim=1] physical_x):
diff -r 098f53627175f611a2b5c45e69efbd5048bb70fb -r b1316c90c0f97d1189bd3920c16ed24969b9206c yt/utilities/lib/pixelization_routines.pyx
--- a/yt/utilities/lib/pixelization_routines.pyx
+++ b/yt/utilities/lib/pixelization_routines.pyx
@@ -25,11 +25,12 @@
from vec3_ops cimport dot, cross, subtract
from yt.utilities.lib.element_mappings cimport \
ElementSampler, \
+ P1Sampler1D, \
+ P1Sampler2D, \
P1Sampler3D, \
Q1Sampler3D, \
+ Q1Sampler2D, \
S2Sampler3D, \
- P1Sampler2D, \
- Q1Sampler2D, \
W1Sampler3D, \
T2Sampler2D, \
Tet2Sampler3D
@@ -594,6 +595,8 @@
sampler = S2Sampler3D()
elif ndim == 2 and nvertices == 3:
sampler = P1Sampler2D()
+ elif ndim == 1 and nvertices == 2:
+ sampler = P1Sampler1D()
elif ndim == 2 and nvertices == 4:
sampler = Q1Sampler2D()
elif ndim == 2 and nvertices == 6:
@@ -648,10 +651,13 @@
pstart[i] = i64max(<np.int64_t> ((LE[i] - pLE[i])*idds[i]) - 1, 0)
pend[i] = i64min(<np.int64_t> ((RE[i] - pLE[i])*idds[i]) + 1, img.shape[i]-1)
- # override for the 2D case
- if ndim == 2:
+ # override for the low-dimensional case
+ if ndim < 3:
pstart[2] = 0
pend[2] = 0
+ if ndim < 2:
+ pstart[1] = 0
+ pend[1] = 0
if use == 0:
continue
diff -r 098f53627175f611a2b5c45e69efbd5048bb70fb -r b1316c90c0f97d1189bd3920c16ed24969b9206c yt/utilities/lib/tests/test_element_mappings.py
--- a/yt/utilities/lib/tests/test_element_mappings.py
+++ b/yt/utilities/lib/tests/test_element_mappings.py
@@ -24,7 +24,8 @@
test_hex20_sampler, \
test_wedge_sampler, \
test_tri2_sampler, \
- test_tet2_sampler
+ test_tet2_sampler, \
+ test_linear1D_sampler
def check_all_vertices(sampler, vertices, field_values):
@@ -37,6 +38,14 @@
assert_almost_equal(val, field_values[i])
+def test_P1Sampler1D():
+
+ vertices = np.array([[0.1], [0.3]])
+ field_values = np.array([ 1., 2.])
+
+ check_all_vertices(test_linear1D_sampler, vertices, field_values)
+
+
def test_P1Sampler2D():
vertices = np.array([[0.1, 0.2], [0.6, 0.3], [0.2, 0.7]])
diff -r 098f53627175f611a2b5c45e69efbd5048bb70fb -r b1316c90c0f97d1189bd3920c16ed24969b9206c yt/visualization/profile_plotter.py
--- a/yt/visualization/profile_plotter.py
+++ b/yt/visualization/profile_plotter.py
@@ -235,7 +235,7 @@
plot_spec = [plot_spec.copy() for p in profiles]
ProfilePlot._initialize_instance(self, profiles, label, plot_spec, y_log)
-
+
@validate_plot
def save(self, name=None, suffix=None, mpl_kwargs=None):
r"""
https://bitbucket.org/yt_analysis/yt/commits/6c1dd626c63a/
Changeset: 6c1dd626c63a
Branch: yt
User: atmyers
Date: 2016-09-28 23:09:18+00:00
Summary: Add sampler type for 1D linear elements.
Affected #: 2 files
diff -r b1316c90c0f97d1189bd3920c16ed24969b9206c -r 6c1dd626c63a069aba3cc68d06a70afdd74e672b yt/frontends/exodus_ii/data_structures.py
--- a/yt/frontends/exodus_ii/data_structures.py
+++ b/yt/frontends/exodus_ii/data_structures.py
@@ -161,11 +161,17 @@
self.default_field = [f for f in self.field_list
if f[0] == 'connect1'][-1]
+ num_pseudo = None
for mesh in self.index.meshes:
- num_pseudo = get_num_pseudo_dims(mesh.connectivity_coords)
- if (num_pseudo > 1 or self.dimensionality < 2):
- raise RuntimeError("1D unstructured mesh data "
- "are currently not supported.")
+ num_pseudo_dims = get_num_pseudo_dims(mesh.connectivity_coords)
+ if num_pseudo:
+ assert(num_pseudo == num_pseudo_dims)
+ else:
+ num_pseudo = num_pseudo_dims
+
+ self.dimensionality -= num_pseudo
+ self.domain_right_edge = self.domain_right_edge[:self.dimensionality]
+ self.domain_left_edge = self.domain_left_edge[:self.dimensionality]
def _set_code_unit_attributes(self):
# This is where quantities are created that represent the various
@@ -195,7 +201,7 @@
self.parameters['nod_names'] = self._get_nod_names()
self.domain_left_edge, self.domain_right_edge = self._load_domain_edge()
- # set up psuedo-3D for lodim datasets here
+ # set up pseudo-3D for lodim datasets here
if self.dimensionality == 2:
self.domain_left_edge = np.append(self.domain_left_edge, 0.0)
self.domain_right_edge = np.append(self.domain_right_edge, 1.0)
diff -r b1316c90c0f97d1189bd3920c16ed24969b9206c -r 6c1dd626c63a069aba3cc68d06a70afdd74e672b yt/visualization/profile_plotter.py
--- a/yt/visualization/profile_plotter.py
+++ b/yt/visualization/profile_plotter.py
@@ -663,6 +663,492 @@
return (x_title, y_title)
+
+class LinePlot(object):
+ r"""
+ Create a 1d line plot.
+
+ Given a dataset and a list of fields, this will create a set of
+ one-dimensional plots showing the fields as functions of position.
+
+ Parameters
+ ----------
+
+ ds : :class:`yt.data_objects.api.Dataset`
+ This is the dataset object corresponding to the
+ simulation output to be plotted.
+ fields : str or list
+ The field or fields to be plotted.
+ label : str or list of strings
+ If a string, the label to be put on the line plotted. If a list,
+ this should be a list of labels, one for each field.
+ Default: None.
+ plot_spec : dict or list of dicts
+ A dictionary or list of dictionaries containing plot keyword
+ arguments. For example, dict(color="red", linestyle=":").
+ Default: None.
+ y_log : dict
+ A dictionary containing field:boolean pairs, setting the logarithmic
+ property for that field. May be overridden after instantiation using
+ set_log.
+ Default: None
+
+ Examples
+ --------
+
+ """
+ y_log = None
+ y_title = None
+ _plot_valid = False
+
+ def __init__(self, ds, fields, label=None, plot_spec=None, y_log=None):
+
+ if isinstance(data_source.ds, YTProfileDataset):
+ profiles = [data_source.ds.profile]
+ else:
+ profiles = [create_profile(data_source, [x_field],
+ n_bins=[n_bins],
+ fields=ensure_list(y_fields),
+ weight_field=weight_field,
+ accumulation=accumulation,
+ fractional=fractional,
+ logs=logs)]
+
+ if plot_spec is None:
+ plot_spec = [dict() for p in profiles]
+ if not isinstance(plot_spec, list):
+ plot_spec = [plot_spec.copy() for p in profiles]
+
+ ProfilePlot._initialize_instance(self, profiles, label, plot_spec, y_log)
+
+ @validate_plot
+ def save(self, name=None, suffix=None, mpl_kwargs=None):
+ r"""
+ Saves a 1d profile plot.
+
+ Parameters
+ ----------
+ name : str
+ The output file keyword.
+ suffix : string
+ Specify the image type by its suffix. If not specified, the output
+ type will be inferred from the filename. Defaults to PNG.
+ mpl_kwargs : dict
+ A dict of keyword arguments to be passed to matplotlib.
+ """
+ if not self._plot_valid:
+ self._setup_plots()
+ unique = set(self.plots.values())
+ if len(unique) < len(self.plots):
+ iters = izip(range(len(unique)), sorted(unique))
+ else:
+ iters = iteritems(self.plots)
+ if not suffix:
+ suffix = "png"
+ suffix = ".%s" % suffix
+ fullname = False
+ if name is None:
+ if len(self.profiles) == 1:
+ prefix = self.profiles[0].ds
+ else:
+ prefix = "Multi-data"
+ name = "%s%s" % (prefix, suffix)
+ else:
+ sfx = get_image_suffix(name)
+ if sfx != '':
+ suffix = sfx
+ prefix = name[:name.rfind(suffix)]
+ fullname = True
+ else:
+ prefix = name
+ xfn = self.profiles[0].x_field
+ if isinstance(xfn, tuple):
+ xfn = xfn[1]
+ fns = []
+ for uid, plot in iters:
+ if isinstance(uid, tuple):
+ uid = uid[1]
+ if fullname:
+ fns.append("%s%s" % (prefix, suffix))
+ else:
+ fns.append("%s_1d-Profile_%s_%s%s" % (prefix, xfn, uid, suffix))
+ mylog.info("Saving %s", fns[-1])
+ with matplotlib_style_context():
+ plot.save(fns[-1], mpl_kwargs=mpl_kwargs)
+ return fns
+
+ @validate_plot
+ def show(self):
+ r"""This will send any existing plots to the IPython notebook.
+
+ If yt is being run from within an IPython session, and it is able to
+ determine this, this function will send any existing plots to the
+ notebook for display.
+
+ If yt can't determine if it's inside an IPython session, it will raise
+ YTNotInsideNotebook.
+
+ Examples
+ --------
+
+ >>> import yt
+ >>> ds = yt.load('IsolatedGalaxy/galaxy0030/galaxy0030')
+ >>> pp = ProfilePlot(ds.all_data(), 'density', 'temperature')
+ >>> pp.show()
+
+ """
+ if "__IPYTHON__" in dir(builtins):
+ api_version = get_ipython_api_version()
+ if api_version in ('0.10', '0.11'):
+ self._send_zmq()
+ else:
+ from IPython.display import display
+ display(self)
+ else:
+ raise YTNotInsideNotebook
+
+ @validate_plot
+ def _repr_html_(self):
+ """Return an html representation of the plot object. Will display as a
+ png for each WindowPlotMPL instance in self.plots"""
+ from . import _mpl_imports as mpl
+ ret = ''
+ unique = set(self.figures.values())
+ if len(unique) < len(self.figures):
+ iters = izip(range(len(unique)), sorted(unique))
+ else:
+ iters = iteritems(self.figures)
+ for uid, fig in iters:
+ canvas = mpl.FigureCanvasAgg(fig)
+ f = BytesIO()
+ with matplotlib_style_context():
+ canvas.print_figure(f)
+ f.seek(0)
+ img = base64.b64encode(f.read()).decode()
+ ret += r'<img style="max-width:100%%;max-height:100%%;" ' \
+ r'src="data:image/png;base64,{0}"><br>'.format(img)
+ return ret
+
+ def _setup_plots(self):
+ if self._plot_valid is True:
+ return
+ for f in self.axes:
+ self.axes[f].cla()
+ for i, profile in enumerate(self.profiles):
+ for field, field_data in profile.items():
+ self.axes[field].plot(np.array(profile.x), np.array(field_data),
+ label=self.label[i], **self.plot_spec[i])
+
+ for (fname, axes), profile in zip(self.axes.items(), self.profiles):
+ xscale, yscale = self._get_field_log(fname, profile)
+ xtitle, ytitle = self._get_field_title(fname, profile)
+ axes.set_xscale(xscale)
+ axes.set_yscale(yscale)
+ axes.set_xlabel(xtitle)
+ axes.set_ylabel(ytitle)
+ axes.set_ylim(*self.axes.ylim[fname])
+ if any(self.label):
+ axes.legend(loc="best")
+ self._set_font_properties()
+ self._plot_valid = True
+
+ @classmethod
+ def _initialize_instance(cls, obj, profiles, labels, plot_specs, y_log):
+ from matplotlib.font_manager import FontProperties
+ obj._font_properties = FontProperties(family='stixgeneral', size=18)
+ obj._font_color = None
+ obj.profiles = ensure_list(profiles)
+ obj.x_log = None
+ obj.y_log = {}
+ if y_log is not None:
+ for field, log in y_log.items():
+ field, = obj.profiles[0].data_source._determine_fields([field])
+ obj.y_log[field] = log
+ obj.y_title = {}
+ obj.label = sanitize_label(labels, len(obj.profiles))
+ if plot_specs is None:
+ plot_specs = [dict() for p in obj.profiles]
+ obj.plot_spec = plot_specs
+ obj.plots = PlotContainer()
+ obj.figures = FigureContainer(obj.plots)
+ obj.axes = AxesContainer(obj.plots)
+ obj._setup_plots()
+ return obj
+
+ @classmethod
+ def from_profiles(cls, profiles, labels=None, plot_specs=None, y_log=None):
+ r"""
+ Instantiate a ProfilePlot object from a list of profiles
+ created with :func:`~yt.data_objects.profiles.create_profile`.
+
+ Parameters
+ ----------
+ profiles : a profile or list of profiles
+ A single profile or list of profile objects created with
+ :func:`~yt.data_objects.profiles.create_profile`.
+ labels : list of strings
+ A list of labels for each profile to be overplotted.
+ Default: None.
+ plot_specs : list of dicts
+ A list of dictionaries containing plot keyword
+ arguments. For example, [dict(color="red", linestyle=":")].
+ Default: None.
+
+ Examples
+ --------
+
+ >>> from yt import simulation
+ >>> es = simulation("AMRCosmology.enzo", "Enzo")
+ >>> es.get_time_series()
+
+ >>> profiles = []
+ >>> labels = []
+ >>> plot_specs = []
+ >>> for ds in es[-4:]:
+ ... ad = ds.all_data()
+ ... profiles.append(create_profile(ad, ["Density"],
+ ... fields=["Temperature",
+ ... "x-velocity"]))
+ ... labels.append(ds.current_redshift)
+ ... plot_specs.append(dict(linestyle="--", alpha=0.7))
+ >>>
+ >>> plot = ProfilePlot.from_profiles(profiles, labels=labels,
+ ... plot_specs=plot_specs)
+ >>> plot.save()
+
+ """
+ if labels is not None and len(profiles) != len(labels):
+ raise RuntimeError("Profiles list and labels list must be the same size.")
+ if plot_specs is not None and len(plot_specs) != len(profiles):
+ raise RuntimeError("Profiles list and plot_specs list must be the same size.")
+ obj = cls.__new__(cls)
+ return cls._initialize_instance(obj, profiles, labels, plot_specs, y_log)
+
+ @invalidate_plot
+ def set_line_property(self, property, value, index=None):
+ r"""
+ Set properties for one or all lines to be plotted.
+
+ Parameters
+ ----------
+ property : str
+ The line property to be set.
+ value : str, int, float
+ The value to set for the line property.
+ index : int
+ The index of the profile in the list of profiles to be
+ changed. If None, change all plotted lines.
+ Default : None.
+
+ Examples
+ --------
+
+ Change all the lines in a plot
+ plot.set_line_property("linestyle", "-")
+
+ Change a single line.
+ plot.set_line_property("linewidth", 4, index=0)
+
+ """
+ if index is None:
+ specs = self.plot_spec
+ else:
+ specs = [self.plot_spec[index]]
+ for spec in specs:
+ spec[property] = value
+ return self
+
+ @invalidate_plot
+ def set_log(self, field, log):
+ """set a field to log or linear.
+
+ Parameters
+ ----------
+ field : string
+ the field to set a transform
+ log : boolean
+ Log on/off.
+ """
+ if field == "all":
+ self.x_log = log
+ for field in list(self.profiles[0].field_data.keys()):
+ self.y_log[field] = log
+ else:
+ field, = self.profiles[0].data_source._determine_fields([field])
+ if field == self.profiles[0].x_field:
+ self.x_log = log
+ elif field in self.profiles[0].field_data:
+ self.y_log[field] = log
+ else:
+ raise KeyError("Field %s not in profile plot!" % (field))
+ return self
+
+ @invalidate_plot
+ def set_unit(self, field, unit):
+ """Sets a new unit for the requested field
+
+ Parameters
+ ----------
+ field : string
+ The name of the field that is to be changed.
+
+ new_unit : string or Unit object
+ The name of the new unit.
+ """
+ for profile in self.profiles:
+ if field == profile.x_field[1]:
+ profile.set_x_unit(unit)
+ elif field in self.profiles[0].field_map:
+ profile.set_field_unit(field, unit)
+ else:
+ raise KeyError("Field %s not in profile plot!" % (field))
+ return self
+
+ @invalidate_plot
+ def set_xlim(self, xmin=None, xmax=None):
+ """Sets the limits of the bin field
+
+ Parameters
+ ----------
+
+ xmin : float or None
+ The new x minimum. Defaults to None, which leaves the xmin
+ unchanged.
+
+ xmax : float or None
+ The new x maximum. Defaults to None, which leaves the xmax
+ unchanged.
+
+ Examples
+ --------
+
+ >>> import yt
+ >>> ds = yt.load('IsolatedGalaxy/galaxy0030/galaxy0030')
+ >>> pp = yt.ProfilePlot(ds.all_data(), 'density', 'temperature')
+ >>> pp.set_xlim(1e-29, 1e-24)
+ >>> pp.save()
+
+ """
+ for i, p in enumerate(self.profiles):
+ if xmin is None:
+ xmi = p.x_bins.min()
+ else:
+ xmi = xmin
+ if xmax is None:
+ xma = p.x_bins.max()
+ else:
+ xma = xmax
+ extrema = {p.x_field: ((xmi, str(p.x.units)), (xma, str(p.x.units)))}
+ units = {p.x_field: str(p.x.units)}
+ if self.x_log is None:
+ logs = None
+ else:
+ logs = {p.x_field: self.x_log}
+ for field in p.field_map.values():
+ units[field] = str(p.field_data[field].units)
+ self.profiles[i] = \
+ create_profile(p.data_source, p.x_field,
+ n_bins=len(p.x_bins)-1,
+ fields=list(p.field_map.values()),
+ weight_field=p.weight_field,
+ accumulation=p.accumulation,
+ fractional=p.fractional,
+ logs=logs,
+ extrema=extrema, units=units)
+ return self
+
+ @invalidate_plot
+ def set_ylim(self, field, ymin=None, ymax=None):
+ """Sets the plot limits for the specified field we are binning.
+
+ Parameters
+ ----------
+
+ field : string or field tuple
+
+ The field that we want to adjust the plot limits for.
+
+ ymin : float or None
+ The new y minimum. Defaults to None, which leaves the ymin
+ unchanged.
+
+ ymax : float or None
+ The new y maximum. Defaults to None, which leaves the ymax
+ unchanged.
+
+ Examples
+ --------
+
+ >>> import yt
+ >>> ds = yt.load('IsolatedGalaxy/galaxy0030/galaxy0030')
+ >>> pp = yt.ProfilePlot(ds.all_data(), 'density', ['temperature', 'x-velocity'])
+ >>> pp.set_ylim('temperature', 1e4, 1e6)
+ >>> pp.save()
+
+ """
+ if field is 'all':
+ fields = list(self.axes.keys())
+ else:
+ fields = ensure_list(field)
+ for profile in self.profiles:
+ for field in profile.data_source._determine_fields(fields):
+ if field in profile.field_map:
+ field = profile.field_map[field]
+ self.axes.ylim[field] = (ymin, ymax)
+ # Continue on to the next profile.
+ break
+ return self
+
+ def _set_font_properties(self):
+ for f in self.plots:
+ self.plots[f]._set_font_properties(
+ self._font_properties, self._font_color)
+
+ def _get_field_log(self, field_y, profile):
+ yfi = profile.field_info[field_y]
+ if self.x_log is None:
+ x_log = profile.x_log
+ else:
+ x_log = self.x_log
+ if field_y in self.y_log:
+ y_log = self.y_log[field_y]
+ else:
+ y_log = yfi.take_log
+ scales = {True: 'log', False: 'linear'}
+ return scales[x_log], scales[y_log]
+
+ def _get_field_label(self, field, field_info, field_unit, fractional=False):
+ field_unit = field_unit.latex_representation()
+ field_name = field_info.display_name
+ if isinstance(field, tuple): field = field[1]
+ if field_name is None:
+ field_name = r'$\rm{'+field+r'}$'
+ field_name = r'$\rm{'+field.replace('_','\ ').title()+r'}$'
+ elif field_name.find('$') == -1:
+ field_name = field_name.replace(' ','\ ')
+ field_name = r'$\rm{'+field_name+r'}$'
+ if fractional:
+ label = field_name + r'$\rm{\ Probability\ Density}$'
+ elif field_unit is None or field_unit == '':
+ label = field_name
+ else:
+ label = field_name+r'$\ \ ('+field_unit+r')$'
+ return label
+
+ def _get_field_title(self, field_y, profile):
+ field_x = profile.x_field
+ xfi = profile.field_info[field_x]
+ yfi = profile.field_info[field_y]
+ x_unit = profile.x.units
+ y_unit = profile.field_units[field_y]
+ fractional = profile.fractional
+ x_title = self.x_title or self._get_field_label(field_x, xfi, x_unit)
+ y_title = self.y_title.get(field_y, None) or \
+ self._get_field_label(field_y, yfi, y_unit, fractional)
+
+ return (x_title, y_title)
+
+
class PhasePlot(ImagePlotContainer):
r"""
Create a 2d profile (phase) plot from a data source or from
https://bitbucket.org/yt_analysis/yt/commits/474bbda62243/
Changeset: 474bbda62243
Branch: yt
User: atmyers
Date: 2016-09-28 23:21:39+00:00
Summary: trying to handle datasets with some dimensions set to zero.
Affected #: 1 file
diff -r 6c1dd626c63a069aba3cc68d06a70afdd74e672b -r 474bbda62243c09877986bc537c4f5959f830aec yt/frontends/exodus_ii/data_structures.py
--- a/yt/frontends/exodus_ii/data_structures.py
+++ b/yt/frontends/exodus_ii/data_structures.py
@@ -170,8 +170,9 @@
num_pseudo = num_pseudo_dims
self.dimensionality -= num_pseudo
- self.domain_right_edge = self.domain_right_edge[:self.dimensionality]
- self.domain_left_edge = self.domain_left_edge[:self.dimensionality]
+ for i in range(self.dimensionality, 3):
+ self.domain_left_edge[i] = 0.0
+ self.domain_right_edge[i] = 1.0
def _set_code_unit_attributes(self):
# This is where quantities are created that represent the various
https://bitbucket.org/yt_analysis/yt/commits/95454c7d941f/
Changeset: 95454c7d941f
Branch: yt
User: atmyers
Date: 2016-09-28 23:56:06+00:00
Summary: handling the pseudo-3D for datasets where one or more of the dimensions are zeroed out.
Affected #: 1 file
diff -r 474bbda62243c09877986bc537c4f5959f830aec -r 95454c7d941f75f8461e166c94af83932edd2b27 yt/frontends/exodus_ii/data_structures.py
--- a/yt/frontends/exodus_ii/data_structures.py
+++ b/yt/frontends/exodus_ii/data_structures.py
@@ -161,19 +161,6 @@
self.default_field = [f for f in self.field_list
if f[0] == 'connect1'][-1]
- num_pseudo = None
- for mesh in self.index.meshes:
- num_pseudo_dims = get_num_pseudo_dims(mesh.connectivity_coords)
- if num_pseudo:
- assert(num_pseudo == num_pseudo_dims)
- else:
- num_pseudo = num_pseudo_dims
-
- self.dimensionality -= num_pseudo
- for i in range(self.dimensionality, 3):
- self.domain_left_edge[i] = 0.0
- self.domain_right_edge[i] = 1.0
-
def _set_code_unit_attributes(self):
# This is where quantities are created that represent the various
# on-disk units. These are the currently available quantities which
@@ -201,12 +188,6 @@
self.parameters['elem_names'] = self._get_elem_names()
self.parameters['nod_names'] = self._get_nod_names()
self.domain_left_edge, self.domain_right_edge = self._load_domain_edge()
-
- # set up pseudo-3D for lodim datasets here
- if self.dimensionality == 2:
- self.domain_left_edge = np.append(self.domain_left_edge, 0.0)
- self.domain_right_edge = np.append(self.domain_right_edge, 1.0)
-
self.periodicity = (False, False, False)
# These attributes don't really make sense for unstructured
@@ -377,6 +358,18 @@
width = ma - mi
mi -= 0.1 * width
ma += 0.1 * width
+
+ # set up pseudo-3D for lodim datasets here
+ for _ in range(self.dimensionality, 3):
+ mi = np.append(mi, 0.0)
+ ma = np.append(ma, 1.0)
+
+ num_pseudo_dims = get_num_pseudo_dims(coords)
+ self.dimensionality -= num_pseudo_dims
+ for i in range(self.dimensionality, 3):
+ mi[i] = 0.0
+ ma[i] = 1.0
+
return mi, ma
@classmethod
https://bitbucket.org/yt_analysis/yt/commits/e928ec89f0bc/
Changeset: e928ec89f0bc
Branch: yt
User: atmyers
Date: 2016-09-30 20:26:02+00:00
Summary: some work towards implementing 1D plots for unstructured mesh datasets
Affected #: 1 file
diff -r 95454c7d941f75f8461e166c94af83932edd2b27 -r e928ec89f0bc1afe7e8827f5a8e1ce0707f55f78 yt/visualization/profile_plotter.py
--- a/yt/visualization/profile_plotter.py
+++ b/yt/visualization/profile_plotter.py
@@ -44,6 +44,8 @@
get_image_suffix, \
get_ipython_api_version, \
matplotlib_style_context
+from yt.utilities.lib.pixelization_routines import pixelize_element_mesh
+from yt.data_objects.unstructured_mesh import SemiStructuredMesh
def get_canvas(name):
from . import _mpl_imports as mpl
@@ -701,30 +703,64 @@
y_title = None
_plot_valid = False
- def __init__(self, ds, fields, label=None, plot_spec=None, y_log=None):
+ def __init__(self, ds, fields, label=None, plot_spec=None, y_log=None, resolution=800):
- if isinstance(data_source.ds, YTProfileDataset):
- profiles = [data_source.ds.profile]
- else:
- profiles = [create_profile(data_source, [x_field],
- n_bins=[n_bins],
- fields=ensure_list(y_fields),
- weight_field=weight_field,
- accumulation=accumulation,
- fractional=fractional,
- logs=logs)]
+ self.ds = ds
+ self.x_field = 'x'
+ index = ds.index
+ assert(ds.dimensionality == 1)
+ assert(hasattr(index, 'meshes') and not isinstance(index.meshes[0], SemiStructuredMesh))
+
+ buff_size = [resolution, 1, 1]
+
+ self.fields = ensure_list(fields)
+ self.y_data = []
+ for field in self.fields:
+ ftype, fname = field
+ mesh_id = int(ftype[-1]) - 1
+ mesh = index.meshes[mesh_id]
+ coords = mesh.connectivity_coords
+ indices = mesh.connectivity_indices
+ offset = mesh._index_offset
+ ad = ds.all_data()
+ field_data = ad[field]
+ extents = [[coords.min(), coords.max()]]
+
+ dds = (extents[0][1] - extents[0][0]) / buff_size[0]
+ x = np.linspace(extents[0][0] + 0.5*dds, extents[0][1] - 0.5*dds, buff_size[0])
+ self.x_data = x
+
+ img = pixelize_element_mesh(coords, indices, buff_size,
+ field_data, extents, index_offset=offset)
+ self.y_data.append(img[:, 0, 0])
if plot_spec is None:
- plot_spec = [dict() for p in profiles]
+ plot_spec = [dict() for f in self.fields]
if not isinstance(plot_spec, list):
- plot_spec = [plot_spec.copy() for p in profiles]
+ plot_spec = [plot_spec.copy() for f in self.fields]
- ProfilePlot._initialize_instance(self, profiles, label, plot_spec, y_log)
+ self.plot_spec = plot_spec
+ from matplotlib.font_manager import FontProperties
+ self._font_properties = FontProperties(family='stixgeneral', size=18)
+ self._font_color = None
+ self.x_log = None
+ self.y_log = {}
+ if y_log is not None:
+ for field, log in y_log.items():
+ field, = ad._determine_fields([field])
+ self.y_log[field] = log
+ self.y_title = {}
+ self.label = sanitize_label(label, len(self.y_data))
+ self.plots = PlotContainer()
+ self.figures = FigureContainer(self.plots)
+ self.axes = AxesContainer(self.plots)
+ self._setup_plots()
+
@validate_plot
def save(self, name=None, suffix=None, mpl_kwargs=None):
r"""
- Saves a 1d profile plot.
+ Saves a 1d line plot.
Parameters
----------
@@ -748,8 +784,8 @@
suffix = ".%s" % suffix
fullname = False
if name is None:
- if len(self.profiles) == 1:
- prefix = self.profiles[0].ds
+ if len(self.y_data) == 1:
+ prefix = self.ds
else:
prefix = "Multi-data"
name = "%s%s" % (prefix, suffix)
@@ -761,7 +797,7 @@
fullname = True
else:
prefix = name
- xfn = self.profiles[0].x_field
+ xfn = self.x_field
if isinstance(xfn, tuple):
xfn = xfn[1]
fns = []
@@ -834,10 +870,9 @@
return
for f in self.axes:
self.axes[f].cla()
- for i, profile in enumerate(self.profiles):
- for field, field_data in profile.items():
- self.axes[field].plot(np.array(profile.x), np.array(field_data),
- label=self.label[i], **self.plot_spec[i])
+ for i, field in enumerate(self.fields):
+ self.axes[field].plot(self.x_data, self.y_data[i],
+ label=self.label[i], **self.plot_spec[i])
for (fname, axes), profile in zip(self.axes.items(), self.profiles):
xscale, yscale = self._get_field_log(fname, profile)
@@ -852,78 +887,6 @@
self._set_font_properties()
self._plot_valid = True
- @classmethod
- def _initialize_instance(cls, obj, profiles, labels, plot_specs, y_log):
- from matplotlib.font_manager import FontProperties
- obj._font_properties = FontProperties(family='stixgeneral', size=18)
- obj._font_color = None
- obj.profiles = ensure_list(profiles)
- obj.x_log = None
- obj.y_log = {}
- if y_log is not None:
- for field, log in y_log.items():
- field, = obj.profiles[0].data_source._determine_fields([field])
- obj.y_log[field] = log
- obj.y_title = {}
- obj.label = sanitize_label(labels, len(obj.profiles))
- if plot_specs is None:
- plot_specs = [dict() for p in obj.profiles]
- obj.plot_spec = plot_specs
- obj.plots = PlotContainer()
- obj.figures = FigureContainer(obj.plots)
- obj.axes = AxesContainer(obj.plots)
- obj._setup_plots()
- return obj
-
- @classmethod
- def from_profiles(cls, profiles, labels=None, plot_specs=None, y_log=None):
- r"""
- Instantiate a ProfilePlot object from a list of profiles
- created with :func:`~yt.data_objects.profiles.create_profile`.
-
- Parameters
- ----------
- profiles : a profile or list of profiles
- A single profile or list of profile objects created with
- :func:`~yt.data_objects.profiles.create_profile`.
- labels : list of strings
- A list of labels for each profile to be overplotted.
- Default: None.
- plot_specs : list of dicts
- A list of dictionaries containing plot keyword
- arguments. For example, [dict(color="red", linestyle=":")].
- Default: None.
-
- Examples
- --------
-
- >>> from yt import simulation
- >>> es = simulation("AMRCosmology.enzo", "Enzo")
- >>> es.get_time_series()
-
- >>> profiles = []
- >>> labels = []
- >>> plot_specs = []
- >>> for ds in es[-4:]:
- ... ad = ds.all_data()
- ... profiles.append(create_profile(ad, ["Density"],
- ... fields=["Temperature",
- ... "x-velocity"]))
- ... labels.append(ds.current_redshift)
- ... plot_specs.append(dict(linestyle="--", alpha=0.7))
- >>>
- >>> plot = ProfilePlot.from_profiles(profiles, labels=labels,
- ... plot_specs=plot_specs)
- >>> plot.save()
-
- """
- if labels is not None and len(profiles) != len(labels):
- raise RuntimeError("Profiles list and labels list must be the same size.")
- if plot_specs is not None and len(plot_specs) != len(profiles):
- raise RuntimeError("Profiles list and plot_specs list must be the same size.")
- obj = cls.__new__(cls)
- return cls._initialize_instance(obj, profiles, labels, plot_specs, y_log)
-
@invalidate_plot
def set_line_property(self, property, value, index=None):
r"""
https://bitbucket.org/yt_analysis/yt/commits/11f718845127/
Changeset: 11f718845127
Branch: yt
User: atmyers
Date: 2016-09-30 21:20:34+00:00
Summary: merging
Affected #: 3 files
diff -r 7b9bbe1566a22ebca39f1fc6a2971ddcb9d7acb6 -r 11f718845127fd99e48f936424a5a5dd0b9d9b8d yt/frontends/exodus_ii/data_structures.py
--- a/yt/frontends/exodus_ii/data_structures.py
+++ b/yt/frontends/exodus_ii/data_structures.py
@@ -161,12 +161,6 @@
self.default_field = [f for f in self.field_list
if f[0] == 'connect1'][-1]
- for mesh in self.index.meshes:
- num_pseudo = get_num_pseudo_dims(mesh.connectivity_coords)
- if (num_pseudo > 1 or self.dimensionality < 2):
- raise RuntimeError("1D unstructured mesh data "
- "are currently not supported.")
-
def _set_code_unit_attributes(self):
# This is where quantities are created that represent the various
# on-disk units. These are the currently available quantities which
@@ -194,12 +188,6 @@
self.parameters['elem_names'] = self._get_elem_names()
self.parameters['nod_names'] = self._get_nod_names()
self.domain_left_edge, self.domain_right_edge = self._load_domain_edge()
-
- # set up psuedo-3D for lodim datasets here
- if self.dimensionality == 2:
- self.domain_left_edge = np.append(self.domain_left_edge, 0.0)
- self.domain_right_edge = np.append(self.domain_right_edge, 1.0)
-
self.periodicity = (False, False, False)
# These attributes don't really make sense for unstructured
@@ -370,6 +358,18 @@
width = ma - mi
mi -= 0.1 * width
ma += 0.1 * width
+
+ # set up pseudo-3D for lodim datasets here
+ for _ in range(self.dimensionality, 3):
+ mi = np.append(mi, 0.0)
+ ma = np.append(ma, 1.0)
+
+ num_pseudo_dims = get_num_pseudo_dims(coords)
+ self.dimensionality -= num_pseudo_dims
+ for i in range(self.dimensionality, 3):
+ mi[i] = 0.0
+ ma[i] = 1.0
+
return mi, ma
@classmethod
diff -r 7b9bbe1566a22ebca39f1fc6a2971ddcb9d7acb6 -r 11f718845127fd99e48f936424a5a5dd0b9d9b8d yt/utilities/lib/pixelization_routines.pyx
--- a/yt/utilities/lib/pixelization_routines.pyx
+++ b/yt/utilities/lib/pixelization_routines.pyx
@@ -25,11 +25,12 @@
from vec3_ops cimport dot, cross, subtract
from yt.utilities.lib.element_mappings cimport \
ElementSampler, \
+ P1Sampler1D, \
+ P1Sampler2D, \
P1Sampler3D, \
Q1Sampler3D, \
+ Q1Sampler2D, \
S2Sampler3D, \
- P1Sampler2D, \
- Q1Sampler2D, \
W1Sampler3D, \
T2Sampler2D, \
Tet2Sampler3D
@@ -604,6 +605,8 @@
sampler = S2Sampler3D()
elif ndim == 2 and nvertices == 3:
sampler = P1Sampler2D()
+ elif ndim == 1 and nvertices == 2:
+ sampler = P1Sampler1D()
elif ndim == 2 and nvertices == 4:
sampler = Q1Sampler2D()
elif ndim == 2 and nvertices == 6:
@@ -658,10 +661,13 @@
pstart[i] = i64max(<np.int64_t> ((LE[i] - pLE[i])*idds[i]) - 1, 0)
pend[i] = i64min(<np.int64_t> ((RE[i] - pLE[i])*idds[i]) + 1, img.shape[i]-1)
- # override for the 2D case
- if ndim == 2:
+ # override for the low-dimensional case
+ if ndim < 3:
pstart[2] = 0
pend[2] = 0
+ if ndim < 2:
+ pstart[1] = 0
+ pend[1] = 0
if use == 0:
continue
diff -r 7b9bbe1566a22ebca39f1fc6a2971ddcb9d7acb6 -r 11f718845127fd99e48f936424a5a5dd0b9d9b8d yt/visualization/profile_plotter.py
--- a/yt/visualization/profile_plotter.py
+++ b/yt/visualization/profile_plotter.py
@@ -44,6 +44,8 @@
get_image_suffix, \
get_ipython_api_version, \
matplotlib_style_context
+from yt.utilities.lib.pixelization_routines import pixelize_element_mesh
+from yt.data_objects.unstructured_mesh import SemiStructuredMesh
def get_canvas(name):
from . import _mpl_imports as mpl
@@ -663,6 +665,453 @@
return (x_title, y_title)
+
+class LinePlot(object):
+ r"""
+ Create a 1d line plot.
+
+ Given a dataset and a list of fields, this will create a set of
+ one-dimensional plots showing the fields as functions of position.
+
+ Parameters
+ ----------
+
+ ds : :class:`yt.data_objects.api.Dataset`
+ This is the dataset object corresponding to the
+ simulation output to be plotted.
+ fields : str or list
+ The field or fields to be plotted.
+ label : str or list of strings
+ If a string, the label to be put on the line plotted. If a list,
+ this should be a list of labels, one for each field.
+ Default: None.
+ plot_spec : dict or list of dicts
+ A dictionary or list of dictionaries containing plot keyword
+ arguments. For example, dict(color="red", linestyle=":").
+ Default: None.
+ y_log : dict
+ A dictionary containing field:boolean pairs, setting the logarithmic
+ property for that field. May be overridden after instantiation using
+ set_log.
+ Default: None
+
+ Examples
+ --------
+
+ """
+ y_log = None
+ y_title = None
+ _plot_valid = False
+
+ def __init__(self, ds, fields, label=None, plot_spec=None, y_log=None, resolution=800):
+
+ self.ds = ds
+ self.x_field = 'x'
+ index = ds.index
+ assert(ds.dimensionality == 1)
+ assert(hasattr(index, 'meshes') and not isinstance(index.meshes[0], SemiStructuredMesh))
+
+ buff_size = [resolution, 1, 1]
+
+ self.fields = ensure_list(fields)
+ self.y_data = []
+ for field in self.fields:
+ ftype, fname = field
+ mesh_id = int(ftype[-1]) - 1
+ mesh = index.meshes[mesh_id]
+ coords = mesh.connectivity_coords
+ indices = mesh.connectivity_indices
+ offset = mesh._index_offset
+ ad = ds.all_data()
+ field_data = ad[field]
+ extents = [[coords.min(), coords.max()]]
+
+ dds = (extents[0][1] - extents[0][0]) / buff_size[0]
+ x = np.linspace(extents[0][0] + 0.5*dds, extents[0][1] - 0.5*dds, buff_size[0])
+ self.x_data = x
+
+ img = pixelize_element_mesh(coords, indices, buff_size,
+ field_data, extents, index_offset=offset)
+ self.y_data.append(img[:, 0, 0])
+
+ if plot_spec is None:
+ plot_spec = [dict() for f in self.fields]
+ if not isinstance(plot_spec, list):
+ plot_spec = [plot_spec.copy() for f in self.fields]
+
+ self.plot_spec = plot_spec
+ from matplotlib.font_manager import FontProperties
+ self._font_properties = FontProperties(family='stixgeneral', size=18)
+ self._font_color = None
+ self.x_log = None
+ self.y_log = {}
+ if y_log is not None:
+ for field, log in y_log.items():
+ field, = ad._determine_fields([field])
+ self.y_log[field] = log
+ self.y_title = {}
+ self.label = sanitize_label(label, len(self.y_data))
+ self.plots = PlotContainer()
+ self.figures = FigureContainer(self.plots)
+ self.axes = AxesContainer(self.plots)
+ self._setup_plots()
+
+
+ @validate_plot
+ def save(self, name=None, suffix=None, mpl_kwargs=None):
+ r"""
+ Saves a 1d line plot.
+
+ Parameters
+ ----------
+ name : str
+ The output file keyword.
+ suffix : string
+ Specify the image type by its suffix. If not specified, the output
+ type will be inferred from the filename. Defaults to PNG.
+ mpl_kwargs : dict
+ A dict of keyword arguments to be passed to matplotlib.
+ """
+ if not self._plot_valid:
+ self._setup_plots()
+ unique = set(self.plots.values())
+ if len(unique) < len(self.plots):
+ iters = izip(range(len(unique)), sorted(unique))
+ else:
+ iters = iteritems(self.plots)
+ if not suffix:
+ suffix = "png"
+ suffix = ".%s" % suffix
+ fullname = False
+ if name is None:
+ if len(self.y_data) == 1:
+ prefix = self.ds
+ else:
+ prefix = "Multi-data"
+ name = "%s%s" % (prefix, suffix)
+ else:
+ sfx = get_image_suffix(name)
+ if sfx != '':
+ suffix = sfx
+ prefix = name[:name.rfind(suffix)]
+ fullname = True
+ else:
+ prefix = name
+ xfn = self.x_field
+ if isinstance(xfn, tuple):
+ xfn = xfn[1]
+ fns = []
+ for uid, plot in iters:
+ if isinstance(uid, tuple):
+ uid = uid[1]
+ if fullname:
+ fns.append("%s%s" % (prefix, suffix))
+ else:
+ fns.append("%s_1d-Profile_%s_%s%s" % (prefix, xfn, uid, suffix))
+ mylog.info("Saving %s", fns[-1])
+ with matplotlib_style_context():
+ plot.save(fns[-1], mpl_kwargs=mpl_kwargs)
+ return fns
+
+ @validate_plot
+ def show(self):
+ r"""This will send any existing plots to the IPython notebook.
+
+ If yt is being run from within an IPython session, and it is able to
+ determine this, this function will send any existing plots to the
+ notebook for display.
+
+ If yt can't determine if it's inside an IPython session, it will raise
+ YTNotInsideNotebook.
+
+ Examples
+ --------
+
+ >>> import yt
+ >>> ds = yt.load('IsolatedGalaxy/galaxy0030/galaxy0030')
+ >>> pp = ProfilePlot(ds.all_data(), 'density', 'temperature')
+ >>> pp.show()
+
+ """
+ if "__IPYTHON__" in dir(builtins):
+ api_version = get_ipython_api_version()
+ if api_version in ('0.10', '0.11'):
+ self._send_zmq()
+ else:
+ from IPython.display import display
+ display(self)
+ else:
+ raise YTNotInsideNotebook
+
+ @validate_plot
+ def _repr_html_(self):
+ """Return an html representation of the plot object. Will display as a
+ png for each WindowPlotMPL instance in self.plots"""
+ from . import _mpl_imports as mpl
+ ret = ''
+ unique = set(self.figures.values())
+ if len(unique) < len(self.figures):
+ iters = izip(range(len(unique)), sorted(unique))
+ else:
+ iters = iteritems(self.figures)
+ for uid, fig in iters:
+ canvas = mpl.FigureCanvasAgg(fig)
+ f = BytesIO()
+ with matplotlib_style_context():
+ canvas.print_figure(f)
+ f.seek(0)
+ img = base64.b64encode(f.read()).decode()
+ ret += r'<img style="max-width:100%%;max-height:100%%;" ' \
+ r'src="data:image/png;base64,{0}"><br>'.format(img)
+ return ret
+
+ def _setup_plots(self):
+ if self._plot_valid is True:
+ return
+ for f in self.axes:
+ self.axes[f].cla()
+ for i, field in enumerate(self.fields):
+ self.axes[field].plot(self.x_data, self.y_data[i],
+ label=self.label[i], **self.plot_spec[i])
+
+ for (fname, axes), profile in zip(self.axes.items(), self.profiles):
+ xscale, yscale = self._get_field_log(fname, profile)
+ xtitle, ytitle = self._get_field_title(fname, profile)
+ axes.set_xscale(xscale)
+ axes.set_yscale(yscale)
+ axes.set_xlabel(xtitle)
+ axes.set_ylabel(ytitle)
+ axes.set_ylim(*self.axes.ylim[fname])
+ if any(self.label):
+ axes.legend(loc="best")
+ self._set_font_properties()
+ self._plot_valid = True
+
+ @invalidate_plot
+ def set_line_property(self, property, value, index=None):
+ r"""
+ Set properties for one or all lines to be plotted.
+
+ Parameters
+ ----------
+ property : str
+ The line property to be set.
+ value : str, int, float
+ The value to set for the line property.
+ index : int
+ The index of the profile in the list of profiles to be
+ changed. If None, change all plotted lines.
+ Default : None.
+
+ Examples
+ --------
+
+ Change all the lines in a plot
+ plot.set_line_property("linestyle", "-")
+
+ Change a single line.
+ plot.set_line_property("linewidth", 4, index=0)
+
+ """
+ if index is None:
+ specs = self.plot_spec
+ else:
+ specs = [self.plot_spec[index]]
+ for spec in specs:
+ spec[property] = value
+ return self
+
+ @invalidate_plot
+ def set_log(self, field, log):
+ """set a field to log or linear.
+
+ Parameters
+ ----------
+ field : string
+ the field to set a transform
+ log : boolean
+ Log on/off.
+ """
+ if field == "all":
+ self.x_log = log
+ for field in list(self.profiles[0].field_data.keys()):
+ self.y_log[field] = log
+ else:
+ field, = self.profiles[0].data_source._determine_fields([field])
+ if field == self.profiles[0].x_field:
+ self.x_log = log
+ elif field in self.profiles[0].field_data:
+ self.y_log[field] = log
+ else:
+ raise KeyError("Field %s not in profile plot!" % (field))
+ return self
+
+ @invalidate_plot
+ def set_unit(self, field, unit):
+ """Sets a new unit for the requested field
+
+ Parameters
+ ----------
+ field : string
+ The name of the field that is to be changed.
+
+ new_unit : string or Unit object
+ The name of the new unit.
+ """
+ for profile in self.profiles:
+ if field == profile.x_field[1]:
+ profile.set_x_unit(unit)
+ elif field in self.profiles[0].field_map:
+ profile.set_field_unit(field, unit)
+ else:
+ raise KeyError("Field %s not in profile plot!" % (field))
+ return self
+
+ @invalidate_plot
+ def set_xlim(self, xmin=None, xmax=None):
+ """Sets the limits of the bin field
+
+ Parameters
+ ----------
+
+ xmin : float or None
+ The new x minimum. Defaults to None, which leaves the xmin
+ unchanged.
+
+ xmax : float or None
+ The new x maximum. Defaults to None, which leaves the xmax
+ unchanged.
+
+ Examples
+ --------
+
+ >>> import yt
+ >>> ds = yt.load('IsolatedGalaxy/galaxy0030/galaxy0030')
+ >>> pp = yt.ProfilePlot(ds.all_data(), 'density', 'temperature')
+ >>> pp.set_xlim(1e-29, 1e-24)
+ >>> pp.save()
+
+ """
+ for i, p in enumerate(self.profiles):
+ if xmin is None:
+ xmi = p.x_bins.min()
+ else:
+ xmi = xmin
+ if xmax is None:
+ xma = p.x_bins.max()
+ else:
+ xma = xmax
+ extrema = {p.x_field: ((xmi, str(p.x.units)), (xma, str(p.x.units)))}
+ units = {p.x_field: str(p.x.units)}
+ if self.x_log is None:
+ logs = None
+ else:
+ logs = {p.x_field: self.x_log}
+ for field in p.field_map.values():
+ units[field] = str(p.field_data[field].units)
+ self.profiles[i] = \
+ create_profile(p.data_source, p.x_field,
+ n_bins=len(p.x_bins)-1,
+ fields=list(p.field_map.values()),
+ weight_field=p.weight_field,
+ accumulation=p.accumulation,
+ fractional=p.fractional,
+ logs=logs,
+ extrema=extrema, units=units)
+ return self
+
+ @invalidate_plot
+ def set_ylim(self, field, ymin=None, ymax=None):
+ """Sets the plot limits for the specified field we are binning.
+
+ Parameters
+ ----------
+
+ field : string or field tuple
+
+ The field that we want to adjust the plot limits for.
+
+ ymin : float or None
+ The new y minimum. Defaults to None, which leaves the ymin
+ unchanged.
+
+ ymax : float or None
+ The new y maximum. Defaults to None, which leaves the ymax
+ unchanged.
+
+ Examples
+ --------
+
+ >>> import yt
+ >>> ds = yt.load('IsolatedGalaxy/galaxy0030/galaxy0030')
+ >>> pp = yt.ProfilePlot(ds.all_data(), 'density', ['temperature', 'x-velocity'])
+ >>> pp.set_ylim('temperature', 1e4, 1e6)
+ >>> pp.save()
+
+ """
+ if field is 'all':
+ fields = list(self.axes.keys())
+ else:
+ fields = ensure_list(field)
+ for profile in self.profiles:
+ for field in profile.data_source._determine_fields(fields):
+ if field in profile.field_map:
+ field = profile.field_map[field]
+ self.axes.ylim[field] = (ymin, ymax)
+ # Continue on to the next profile.
+ break
+ return self
+
+ def _set_font_properties(self):
+ for f in self.plots:
+ self.plots[f]._set_font_properties(
+ self._font_properties, self._font_color)
+
+ def _get_field_log(self, field_y, profile):
+ yfi = profile.field_info[field_y]
+ if self.x_log is None:
+ x_log = profile.x_log
+ else:
+ x_log = self.x_log
+ if field_y in self.y_log:
+ y_log = self.y_log[field_y]
+ else:
+ y_log = yfi.take_log
+ scales = {True: 'log', False: 'linear'}
+ return scales[x_log], scales[y_log]
+
+ def _get_field_label(self, field, field_info, field_unit, fractional=False):
+ field_unit = field_unit.latex_representation()
+ field_name = field_info.display_name
+ if isinstance(field, tuple): field = field[1]
+ if field_name is None:
+ field_name = r'$\rm{'+field+r'}$'
+ field_name = r'$\rm{'+field.replace('_','\ ').title()+r'}$'
+ elif field_name.find('$') == -1:
+ field_name = field_name.replace(' ','\ ')
+ field_name = r'$\rm{'+field_name+r'}$'
+ if fractional:
+ label = field_name + r'$\rm{\ Probability\ Density}$'
+ elif field_unit is None or field_unit == '':
+ label = field_name
+ else:
+ label = field_name+r'$\ \ ('+field_unit+r')$'
+ return label
+
+ def _get_field_title(self, field_y, profile):
+ field_x = profile.x_field
+ xfi = profile.field_info[field_x]
+ yfi = profile.field_info[field_y]
+ x_unit = profile.x.units
+ y_unit = profile.field_units[field_y]
+ fractional = profile.fractional
+ x_title = self.x_title or self._get_field_label(field_x, xfi, x_unit)
+ y_title = self.y_title.get(field_y, None) or \
+ self._get_field_label(field_y, yfi, y_unit, fractional)
+
+ return (x_title, y_title)
+
+
class PhasePlot(ImagePlotContainer):
r"""
Create a 2d profile (phase) plot from a data source or from
https://bitbucket.org/yt_analysis/yt/commits/1801e3dd0cf5/
Changeset: 1801e3dd0cf5
Branch: yt
User: atmyers
Date: 2016-09-30 21:21:50+00:00
Summary: Removing LinePlot for now.
Affected #: 1 file
diff -r 11f718845127fd99e48f936424a5a5dd0b9d9b8d -r 1801e3dd0cf5cb7996ebfe15f6ff3848538c2638 yt/visualization/profile_plotter.py
--- a/yt/visualization/profile_plotter.py
+++ b/yt/visualization/profile_plotter.py
@@ -666,452 +666,6 @@
return (x_title, y_title)
-class LinePlot(object):
- r"""
- Create a 1d line plot.
-
- Given a dataset and a list of fields, this will create a set of
- one-dimensional plots showing the fields as functions of position.
-
- Parameters
- ----------
-
- ds : :class:`yt.data_objects.api.Dataset`
- This is the dataset object corresponding to the
- simulation output to be plotted.
- fields : str or list
- The field or fields to be plotted.
- label : str or list of strings
- If a string, the label to be put on the line plotted. If a list,
- this should be a list of labels, one for each field.
- Default: None.
- plot_spec : dict or list of dicts
- A dictionary or list of dictionaries containing plot keyword
- arguments. For example, dict(color="red", linestyle=":").
- Default: None.
- y_log : dict
- A dictionary containing field:boolean pairs, setting the logarithmic
- property for that field. May be overridden after instantiation using
- set_log.
- Default: None
-
- Examples
- --------
-
- """
- y_log = None
- y_title = None
- _plot_valid = False
-
- def __init__(self, ds, fields, label=None, plot_spec=None, y_log=None, resolution=800):
-
- self.ds = ds
- self.x_field = 'x'
- index = ds.index
- assert(ds.dimensionality == 1)
- assert(hasattr(index, 'meshes') and not isinstance(index.meshes[0], SemiStructuredMesh))
-
- buff_size = [resolution, 1, 1]
-
- self.fields = ensure_list(fields)
- self.y_data = []
- for field in self.fields:
- ftype, fname = field
- mesh_id = int(ftype[-1]) - 1
- mesh = index.meshes[mesh_id]
- coords = mesh.connectivity_coords
- indices = mesh.connectivity_indices
- offset = mesh._index_offset
- ad = ds.all_data()
- field_data = ad[field]
- extents = [[coords.min(), coords.max()]]
-
- dds = (extents[0][1] - extents[0][0]) / buff_size[0]
- x = np.linspace(extents[0][0] + 0.5*dds, extents[0][1] - 0.5*dds, buff_size[0])
- self.x_data = x
-
- img = pixelize_element_mesh(coords, indices, buff_size,
- field_data, extents, index_offset=offset)
- self.y_data.append(img[:, 0, 0])
-
- if plot_spec is None:
- plot_spec = [dict() for f in self.fields]
- if not isinstance(plot_spec, list):
- plot_spec = [plot_spec.copy() for f in self.fields]
-
- self.plot_spec = plot_spec
- from matplotlib.font_manager import FontProperties
- self._font_properties = FontProperties(family='stixgeneral', size=18)
- self._font_color = None
- self.x_log = None
- self.y_log = {}
- if y_log is not None:
- for field, log in y_log.items():
- field, = ad._determine_fields([field])
- self.y_log[field] = log
- self.y_title = {}
- self.label = sanitize_label(label, len(self.y_data))
- self.plots = PlotContainer()
- self.figures = FigureContainer(self.plots)
- self.axes = AxesContainer(self.plots)
- self._setup_plots()
-
-
- @validate_plot
- def save(self, name=None, suffix=None, mpl_kwargs=None):
- r"""
- Saves a 1d line plot.
-
- Parameters
- ----------
- name : str
- The output file keyword.
- suffix : string
- Specify the image type by its suffix. If not specified, the output
- type will be inferred from the filename. Defaults to PNG.
- mpl_kwargs : dict
- A dict of keyword arguments to be passed to matplotlib.
- """
- if not self._plot_valid:
- self._setup_plots()
- unique = set(self.plots.values())
- if len(unique) < len(self.plots):
- iters = izip(range(len(unique)), sorted(unique))
- else:
- iters = iteritems(self.plots)
- if not suffix:
- suffix = "png"
- suffix = ".%s" % suffix
- fullname = False
- if name is None:
- if len(self.y_data) == 1:
- prefix = self.ds
- else:
- prefix = "Multi-data"
- name = "%s%s" % (prefix, suffix)
- else:
- sfx = get_image_suffix(name)
- if sfx != '':
- suffix = sfx
- prefix = name[:name.rfind(suffix)]
- fullname = True
- else:
- prefix = name
- xfn = self.x_field
- if isinstance(xfn, tuple):
- xfn = xfn[1]
- fns = []
- for uid, plot in iters:
- if isinstance(uid, tuple):
- uid = uid[1]
- if fullname:
- fns.append("%s%s" % (prefix, suffix))
- else:
- fns.append("%s_1d-Profile_%s_%s%s" % (prefix, xfn, uid, suffix))
- mylog.info("Saving %s", fns[-1])
- with matplotlib_style_context():
- plot.save(fns[-1], mpl_kwargs=mpl_kwargs)
- return fns
-
- @validate_plot
- def show(self):
- r"""This will send any existing plots to the IPython notebook.
-
- If yt is being run from within an IPython session, and it is able to
- determine this, this function will send any existing plots to the
- notebook for display.
-
- If yt can't determine if it's inside an IPython session, it will raise
- YTNotInsideNotebook.
-
- Examples
- --------
-
- >>> import yt
- >>> ds = yt.load('IsolatedGalaxy/galaxy0030/galaxy0030')
- >>> pp = ProfilePlot(ds.all_data(), 'density', 'temperature')
- >>> pp.show()
-
- """
- if "__IPYTHON__" in dir(builtins):
- api_version = get_ipython_api_version()
- if api_version in ('0.10', '0.11'):
- self._send_zmq()
- else:
- from IPython.display import display
- display(self)
- else:
- raise YTNotInsideNotebook
-
- @validate_plot
- def _repr_html_(self):
- """Return an html representation of the plot object. Will display as a
- png for each WindowPlotMPL instance in self.plots"""
- from . import _mpl_imports as mpl
- ret = ''
- unique = set(self.figures.values())
- if len(unique) < len(self.figures):
- iters = izip(range(len(unique)), sorted(unique))
- else:
- iters = iteritems(self.figures)
- for uid, fig in iters:
- canvas = mpl.FigureCanvasAgg(fig)
- f = BytesIO()
- with matplotlib_style_context():
- canvas.print_figure(f)
- f.seek(0)
- img = base64.b64encode(f.read()).decode()
- ret += r'<img style="max-width:100%%;max-height:100%%;" ' \
- r'src="data:image/png;base64,{0}"><br>'.format(img)
- return ret
-
- def _setup_plots(self):
- if self._plot_valid is True:
- return
- for f in self.axes:
- self.axes[f].cla()
- for i, field in enumerate(self.fields):
- self.axes[field].plot(self.x_data, self.y_data[i],
- label=self.label[i], **self.plot_spec[i])
-
- for (fname, axes), profile in zip(self.axes.items(), self.profiles):
- xscale, yscale = self._get_field_log(fname, profile)
- xtitle, ytitle = self._get_field_title(fname, profile)
- axes.set_xscale(xscale)
- axes.set_yscale(yscale)
- axes.set_xlabel(xtitle)
- axes.set_ylabel(ytitle)
- axes.set_ylim(*self.axes.ylim[fname])
- if any(self.label):
- axes.legend(loc="best")
- self._set_font_properties()
- self._plot_valid = True
-
- @invalidate_plot
- def set_line_property(self, property, value, index=None):
- r"""
- Set properties for one or all lines to be plotted.
-
- Parameters
- ----------
- property : str
- The line property to be set.
- value : str, int, float
- The value to set for the line property.
- index : int
- The index of the profile in the list of profiles to be
- changed. If None, change all plotted lines.
- Default : None.
-
- Examples
- --------
-
- Change all the lines in a plot
- plot.set_line_property("linestyle", "-")
-
- Change a single line.
- plot.set_line_property("linewidth", 4, index=0)
-
- """
- if index is None:
- specs = self.plot_spec
- else:
- specs = [self.plot_spec[index]]
- for spec in specs:
- spec[property] = value
- return self
-
- @invalidate_plot
- def set_log(self, field, log):
- """set a field to log or linear.
-
- Parameters
- ----------
- field : string
- the field to set a transform
- log : boolean
- Log on/off.
- """
- if field == "all":
- self.x_log = log
- for field in list(self.profiles[0].field_data.keys()):
- self.y_log[field] = log
- else:
- field, = self.profiles[0].data_source._determine_fields([field])
- if field == self.profiles[0].x_field:
- self.x_log = log
- elif field in self.profiles[0].field_data:
- self.y_log[field] = log
- else:
- raise KeyError("Field %s not in profile plot!" % (field))
- return self
-
- @invalidate_plot
- def set_unit(self, field, unit):
- """Sets a new unit for the requested field
-
- Parameters
- ----------
- field : string
- The name of the field that is to be changed.
-
- new_unit : string or Unit object
- The name of the new unit.
- """
- for profile in self.profiles:
- if field == profile.x_field[1]:
- profile.set_x_unit(unit)
- elif field in self.profiles[0].field_map:
- profile.set_field_unit(field, unit)
- else:
- raise KeyError("Field %s not in profile plot!" % (field))
- return self
-
- @invalidate_plot
- def set_xlim(self, xmin=None, xmax=None):
- """Sets the limits of the bin field
-
- Parameters
- ----------
-
- xmin : float or None
- The new x minimum. Defaults to None, which leaves the xmin
- unchanged.
-
- xmax : float or None
- The new x maximum. Defaults to None, which leaves the xmax
- unchanged.
-
- Examples
- --------
-
- >>> import yt
- >>> ds = yt.load('IsolatedGalaxy/galaxy0030/galaxy0030')
- >>> pp = yt.ProfilePlot(ds.all_data(), 'density', 'temperature')
- >>> pp.set_xlim(1e-29, 1e-24)
- >>> pp.save()
-
- """
- for i, p in enumerate(self.profiles):
- if xmin is None:
- xmi = p.x_bins.min()
- else:
- xmi = xmin
- if xmax is None:
- xma = p.x_bins.max()
- else:
- xma = xmax
- extrema = {p.x_field: ((xmi, str(p.x.units)), (xma, str(p.x.units)))}
- units = {p.x_field: str(p.x.units)}
- if self.x_log is None:
- logs = None
- else:
- logs = {p.x_field: self.x_log}
- for field in p.field_map.values():
- units[field] = str(p.field_data[field].units)
- self.profiles[i] = \
- create_profile(p.data_source, p.x_field,
- n_bins=len(p.x_bins)-1,
- fields=list(p.field_map.values()),
- weight_field=p.weight_field,
- accumulation=p.accumulation,
- fractional=p.fractional,
- logs=logs,
- extrema=extrema, units=units)
- return self
-
- @invalidate_plot
- def set_ylim(self, field, ymin=None, ymax=None):
- """Sets the plot limits for the specified field we are binning.
-
- Parameters
- ----------
-
- field : string or field tuple
-
- The field that we want to adjust the plot limits for.
-
- ymin : float or None
- The new y minimum. Defaults to None, which leaves the ymin
- unchanged.
-
- ymax : float or None
- The new y maximum. Defaults to None, which leaves the ymax
- unchanged.
-
- Examples
- --------
-
- >>> import yt
- >>> ds = yt.load('IsolatedGalaxy/galaxy0030/galaxy0030')
- >>> pp = yt.ProfilePlot(ds.all_data(), 'density', ['temperature', 'x-velocity'])
- >>> pp.set_ylim('temperature', 1e4, 1e6)
- >>> pp.save()
-
- """
- if field is 'all':
- fields = list(self.axes.keys())
- else:
- fields = ensure_list(field)
- for profile in self.profiles:
- for field in profile.data_source._determine_fields(fields):
- if field in profile.field_map:
- field = profile.field_map[field]
- self.axes.ylim[field] = (ymin, ymax)
- # Continue on to the next profile.
- break
- return self
-
- def _set_font_properties(self):
- for f in self.plots:
- self.plots[f]._set_font_properties(
- self._font_properties, self._font_color)
-
- def _get_field_log(self, field_y, profile):
- yfi = profile.field_info[field_y]
- if self.x_log is None:
- x_log = profile.x_log
- else:
- x_log = self.x_log
- if field_y in self.y_log:
- y_log = self.y_log[field_y]
- else:
- y_log = yfi.take_log
- scales = {True: 'log', False: 'linear'}
- return scales[x_log], scales[y_log]
-
- def _get_field_label(self, field, field_info, field_unit, fractional=False):
- field_unit = field_unit.latex_representation()
- field_name = field_info.display_name
- if isinstance(field, tuple): field = field[1]
- if field_name is None:
- field_name = r'$\rm{'+field+r'}$'
- field_name = r'$\rm{'+field.replace('_','\ ').title()+r'}$'
- elif field_name.find('$') == -1:
- field_name = field_name.replace(' ','\ ')
- field_name = r'$\rm{'+field_name+r'}$'
- if fractional:
- label = field_name + r'$\rm{\ Probability\ Density}$'
- elif field_unit is None or field_unit == '':
- label = field_name
- else:
- label = field_name+r'$\ \ ('+field_unit+r')$'
- return label
-
- def _get_field_title(self, field_y, profile):
- field_x = profile.x_field
- xfi = profile.field_info[field_x]
- yfi = profile.field_info[field_y]
- x_unit = profile.x.units
- y_unit = profile.field_units[field_y]
- fractional = profile.fractional
- x_title = self.x_title or self._get_field_label(field_x, xfi, x_unit)
- y_title = self.y_title.get(field_y, None) or \
- self._get_field_label(field_y, yfi, y_unit, fractional)
-
- return (x_title, y_title)
-
-
class PhasePlot(ImagePlotContainer):
r"""
Create a 2d profile (phase) plot from a data source or from
https://bitbucket.org/yt_analysis/yt/commits/1e9adb9b1369/
Changeset: 1e9adb9b1369
Branch: yt
User: atmyers
Date: 2016-09-30 21:23:58+00:00
Summary: removing some more changes from profile_plotter
Affected #: 1 file
diff -r 1801e3dd0cf5cb7996ebfe15f6ff3848538c2638 -r 1e9adb9b1369941687b74ca73843eed3fe509fe7 yt/visualization/profile_plotter.py
--- a/yt/visualization/profile_plotter.py
+++ b/yt/visualization/profile_plotter.py
@@ -44,8 +44,6 @@
get_image_suffix, \
get_ipython_api_version, \
matplotlib_style_context
-from yt.utilities.lib.pixelization_routines import pixelize_element_mesh
-from yt.data_objects.unstructured_mesh import SemiStructuredMesh
def get_canvas(name):
from . import _mpl_imports as mpl
@@ -237,7 +235,7 @@
plot_spec = [plot_spec.copy() for p in profiles]
ProfilePlot._initialize_instance(self, profiles, label, plot_spec, y_log)
-
+
@validate_plot
def save(self, name=None, suffix=None, mpl_kwargs=None):
r"""
@@ -665,7 +663,6 @@
return (x_title, y_title)
-
class PhasePlot(ImagePlotContainer):
r"""
Create a 2d profile (phase) plot from a data source or from
https://bitbucket.org/yt_analysis/yt/commits/f569db8df4c5/
Changeset: f569db8df4c5
Branch: yt
User: atmyers
Date: 2016-09-30 21:30:04+00:00
Summary: also handle 1D unstructured datasets in the streaming frontend.
Affected #: 2 files
diff -r 1e9adb9b1369941687b74ca73843eed3fe509fe7 -r f569db8df4c57b8672233a8230eeaec687cc968f yt/frontends/stream/data_structures.py
--- a/yt/frontends/stream/data_structures.py
+++ b/yt/frontends/stream/data_structures.py
@@ -1749,11 +1749,6 @@
"""
dimensionality = coordinates.shape[1]
- num_pseudo = get_num_pseudo_dims(coordinates)
- if (num_pseudo > 1 or dimensionality < 2):
- raise RuntimeError("1D unstructured mesh data "
- "are currently not supported.")
-
domain_dimensions = np.ones(3, "int32") * 2
nprocs = 1
@@ -1788,8 +1783,17 @@
coordinates[:,i].max() + 0.1 * abs(coordinates[:,i].max())]
for i in range(dimensionality)]
- if dimensionality == 2:
+ if dimensionality < 3:
bbox.append([0.0, 1.0])
+ if dimensionality < 2:
+ bbox.append([0.0, 1.0])
+
+ # handle pseudo-dims here
+ num_pseudo_dims = get_num_pseudo_dims(coordinates)
+ dimensionality -= num_pseudo_dims
+ for i in range(dimensionality, 3):
+ bbox[i][0] = 0.0
+ bbox[i][1] = 1.0
bbox = np.array(bbox, dtype=np.float64)
domain_left_edge = np.array(bbox[:, 0], 'float64')
diff -r 1e9adb9b1369941687b74ca73843eed3fe509fe7 -r f569db8df4c57b8672233a8230eeaec687cc968f yt/visualization/profile_plotter.py
--- a/yt/visualization/profile_plotter.py
+++ b/yt/visualization/profile_plotter.py
@@ -235,7 +235,7 @@
plot_spec = [plot_spec.copy() for p in profiles]
ProfilePlot._initialize_instance(self, profiles, label, plot_spec, y_log)
-
+
@validate_plot
def save(self, name=None, suffix=None, mpl_kwargs=None):
r"""
https://bitbucket.org/yt_analysis/yt/commits/98bb0abc0b14/
Changeset: 98bb0abc0b14
Branch: yt
User: ngoldbaum
Date: 2017-01-10 16:00:03+00:00
Summary: Merged in atmyers/yt (pull request #2402)
Some work towards 1D unstructured plotting support
Affected #: 7 files
diff -r 175a73a087238b633f6cc92f7f28d94878cd3217 -r 98bb0abc0b1421cba1c16df4ecca2ebd861d36d6 yt/frontends/exodus_ii/data_structures.py
--- a/yt/frontends/exodus_ii/data_structures.py
+++ b/yt/frontends/exodus_ii/data_structures.py
@@ -161,12 +161,6 @@
self.default_field = [f for f in self.field_list
if f[0] == 'connect1'][-1]
- for mesh in self.index.meshes:
- num_pseudo = get_num_pseudo_dims(mesh.connectivity_coords)
- if (num_pseudo > 1 or self.dimensionality < 2):
- raise RuntimeError("1D unstructured mesh data "
- "are currently not supported.")
-
def _set_code_unit_attributes(self):
# This is where quantities are created that represent the various
# on-disk units. These are the currently available quantities which
@@ -194,12 +188,6 @@
self.parameters['elem_names'] = self._get_elem_names()
self.parameters['nod_names'] = self._get_nod_names()
self.domain_left_edge, self.domain_right_edge = self._load_domain_edge()
-
- # set up psuedo-3D for lodim datasets here
- if self.dimensionality == 2:
- self.domain_left_edge = np.append(self.domain_left_edge, 0.0)
- self.domain_right_edge = np.append(self.domain_right_edge, 1.0)
-
self.periodicity = (False, False, False)
# These attributes don't really make sense for unstructured
@@ -370,6 +358,18 @@
width = ma - mi
mi -= 0.1 * width
ma += 0.1 * width
+
+ # set up pseudo-3D for lodim datasets here
+ for _ in range(self.dimensionality, 3):
+ mi = np.append(mi, 0.0)
+ ma = np.append(ma, 1.0)
+
+ num_pseudo_dims = get_num_pseudo_dims(coords)
+ self.dimensionality -= num_pseudo_dims
+ for i in range(self.dimensionality, 3):
+ mi[i] = 0.0
+ ma[i] = 1.0
+
return mi, ma
@classmethod
diff -r 175a73a087238b633f6cc92f7f28d94878cd3217 -r 98bb0abc0b1421cba1c16df4ecca2ebd861d36d6 yt/frontends/stream/data_structures.py
--- a/yt/frontends/stream/data_structures.py
+++ b/yt/frontends/stream/data_structures.py
@@ -1750,11 +1750,6 @@
"""
dimensionality = coordinates.shape[1]
- num_pseudo = get_num_pseudo_dims(coordinates)
- if (num_pseudo > 1 or dimensionality < 2):
- raise RuntimeError("1D unstructured mesh data "
- "are currently not supported.")
-
domain_dimensions = np.ones(3, "int32") * 2
nprocs = 1
@@ -1789,8 +1784,17 @@
coordinates[:,i].max() + 0.1 * abs(coordinates[:,i].max())]
for i in range(dimensionality)]
- if dimensionality == 2:
+ if dimensionality < 3:
bbox.append([0.0, 1.0])
+ if dimensionality < 2:
+ bbox.append([0.0, 1.0])
+
+ # handle pseudo-dims here
+ num_pseudo_dims = get_num_pseudo_dims(coordinates)
+ dimensionality -= num_pseudo_dims
+ for i in range(dimensionality, 3):
+ bbox[i][0] = 0.0
+ bbox[i][1] = 1.0
bbox = np.array(bbox, dtype=np.float64)
domain_left_edge = np.array(bbox[:, 0], 'float64')
diff -r 175a73a087238b633f6cc92f7f28d94878cd3217 -r 98bb0abc0b1421cba1c16df4ecca2ebd861d36d6 yt/utilities/lib/element_mappings.pxd
--- a/yt/utilities/lib/element_mappings.pxd
+++ b/yt/utilities/lib/element_mappings.pxd
@@ -33,6 +33,21 @@
cdef int check_mesh_lines(self, double* mapped_coord) nogil
+cdef class P1Sampler1D(ElementSampler):
+
+ cdef void map_real_to_unit(self,
+ double* mapped_x,
+ double* vertices,
+ double* physical_x) nogil
+
+
+ cdef double sample_at_unit_point(self,
+ double* coord,
+ double* vals) nogil
+
+ cdef int check_inside(self, double* mapped_coord) nogil
+
+
cdef class P1Sampler2D(ElementSampler):
cdef void map_real_to_unit(self,
diff -r 175a73a087238b633f6cc92f7f28d94878cd3217 -r 98bb0abc0b1421cba1c16df4ecca2ebd861d36d6 yt/utilities/lib/element_mappings.pyx
--- a/yt/utilities/lib/element_mappings.pyx
+++ b/yt/utilities/lib/element_mappings.pyx
@@ -115,6 +115,41 @@
return val
+cdef class P1Sampler1D(ElementSampler):
+ '''
+
+ This implements sampling inside a linear, 1D element.
+
+ '''
+
+ def __init__(self):
+ super(P1Sampler1D, self).__init__()
+ self.num_mapped_coords = 1
+
+ @cython.boundscheck(False)
+ @cython.wraparound(False)
+ @cython.cdivision(True)
+ cdef void map_real_to_unit(self, double* mapped_x,
+ double* vertices, double* physical_x) nogil:
+ mapped_x[0] = -1.0 + 2.0*(physical_x[0] - vertices[0]) / (vertices[1] - vertices[0])
+
+ @cython.boundscheck(False)
+ @cython.wraparound(False)
+ @cython.cdivision(True)
+ cdef double sample_at_unit_point(self,
+ double* coord,
+ double* vals) nogil:
+ return vals[0] * (1 - coord[0]) / 2.0 + vals[1] * (1.0 + coord[0]) / 2.0
+
+ @cython.boundscheck(False)
+ @cython.wraparound(False)
+ @cython.cdivision(True)
+ cdef int check_inside(self, double* mapped_coord) nogil:
+ if (fabs(mapped_coord[0]) - 1.0 > self.inclusion_tol):
+ return 0
+ return 1
+
+
cdef class P1Sampler2D(ElementSampler):
'''
@@ -1005,6 +1040,24 @@
@cython.boundscheck(False)
@cython.wraparound(False)
@cython.cdivision(True)
+def test_linear1D_sampler(np.ndarray[np.float64_t, ndim=2] vertices,
+ np.ndarray[np.float64_t, ndim=1] field_values,
+ np.ndarray[np.float64_t, ndim=1] physical_x):
+
+ cdef double val
+
+ sampler = P1Sampler1D()
+
+ val = sampler.sample_at_real_point(<double*> vertices.data,
+ <double*> field_values.data,
+ <double*> physical_x.data)
+
+ return val
+
+
+ at cython.boundscheck(False)
+ at cython.wraparound(False)
+ at cython.cdivision(True)
def test_tri_sampler(np.ndarray[np.float64_t, ndim=2] vertices,
np.ndarray[np.float64_t, ndim=1] field_values,
np.ndarray[np.float64_t, ndim=1] physical_x):
diff -r 175a73a087238b633f6cc92f7f28d94878cd3217 -r 98bb0abc0b1421cba1c16df4ecca2ebd861d36d6 yt/utilities/lib/pixelization_routines.pyx
--- a/yt/utilities/lib/pixelization_routines.pyx
+++ b/yt/utilities/lib/pixelization_routines.pyx
@@ -25,11 +25,12 @@
from vec3_ops cimport dot, cross, subtract
from yt.utilities.lib.element_mappings cimport \
ElementSampler, \
+ P1Sampler1D, \
+ P1Sampler2D, \
P1Sampler3D, \
Q1Sampler3D, \
+ Q1Sampler2D, \
S2Sampler3D, \
- P1Sampler2D, \
- Q1Sampler2D, \
W1Sampler3D, \
T2Sampler2D, \
Tet2Sampler3D
@@ -604,6 +605,8 @@
sampler = S2Sampler3D()
elif ndim == 2 and nvertices == 3:
sampler = P1Sampler2D()
+ elif ndim == 1 and nvertices == 2:
+ sampler = P1Sampler1D()
elif ndim == 2 and nvertices == 4:
sampler = Q1Sampler2D()
elif ndim == 2 and nvertices == 6:
@@ -658,10 +661,13 @@
pstart[i] = i64max(<np.int64_t> ((LE[i] - pLE[i])*idds[i]) - 1, 0)
pend[i] = i64min(<np.int64_t> ((RE[i] - pLE[i])*idds[i]) + 1, img.shape[i]-1)
- # override for the 2D case
- if ndim == 2:
+ # override for the low-dimensional case
+ if ndim < 3:
pstart[2] = 0
pend[2] = 0
+ if ndim < 2:
+ pstart[1] = 0
+ pend[1] = 0
if use == 0:
continue
diff -r 175a73a087238b633f6cc92f7f28d94878cd3217 -r 98bb0abc0b1421cba1c16df4ecca2ebd861d36d6 yt/utilities/lib/tests/test_element_mappings.py
--- a/yt/utilities/lib/tests/test_element_mappings.py
+++ b/yt/utilities/lib/tests/test_element_mappings.py
@@ -24,7 +24,8 @@
test_hex20_sampler, \
test_wedge_sampler, \
test_tri2_sampler, \
- test_tet2_sampler
+ test_tet2_sampler, \
+ test_linear1D_sampler
def check_all_vertices(sampler, vertices, field_values):
@@ -37,6 +38,14 @@
assert_almost_equal(val, field_values[i])
+def test_P1Sampler1D():
+
+ vertices = np.array([[0.1], [0.3]])
+ field_values = np.array([ 1., 2.])
+
+ check_all_vertices(test_linear1D_sampler, vertices, field_values)
+
+
def test_P1Sampler2D():
vertices = np.array([[0.1, 0.2], [0.6, 0.3], [0.2, 0.7]])
diff -r 175a73a087238b633f6cc92f7f28d94878cd3217 -r 98bb0abc0b1421cba1c16df4ecca2ebd861d36d6 yt/visualization/profile_plotter.py
--- a/yt/visualization/profile_plotter.py
+++ b/yt/visualization/profile_plotter.py
@@ -234,7 +234,7 @@
plot_spec = [plot_spec.copy() for p in profiles]
ProfilePlot._initialize_instance(self, profiles, label, plot_spec, y_log)
-
+
@validate_plot
def save(self, name=None, suffix=None, mpl_kwargs=None):
r"""
Repository URL: https://bitbucket.org/yt_analysis/yt/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
More information about the yt-svn
mailing list