[yt-svn] commit/yt: 4 new changesets
commits-noreply at bitbucket.org
commits-noreply at bitbucket.org
Wed Oct 2 12:32:17 PDT 2013
4 new commits in yt:
https://bitbucket.org/yt_analysis/yt/commits/da308f4c50c7/
Changeset: da308f4c50c7
Branch: yt
User: samskillman
Date: 2013-06-30 00:22:39
Summary: Add a new TransferFunctionHelper object to help build, plot, and manage a
transfer function. Adds the capability of overplotting a 1D profile (of say,
CellMass) on the transfer function to help guide choices.
Affected #: 2 files
diff -r 8e8bd5b353df99c1510058a7c982329e5212fcfe -r da308f4c50c7b632169cb3e37036a9651c262864 yt/visualization/volume_rendering/transfer_function_helper.py
--- /dev/null
+++ b/yt/visualization/volume_rendering/transfer_function_helper.py
@@ -0,0 +1,216 @@
+"""
+A helper class to build, display, and modify transfer functions for volume
+rendering.
+
+Author: Samuel Skillman <samskillman at gmail.com>
+Affiliation: DOE CSGF, U. of Colorado at Boulder
+Homepage: http://yt-project.org/
+License:
+ Copyright (C) 2013 Samuel Skillman. All Rights Reserved.
+
+ This file is part of yt.
+
+ yt is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+"""
+from yt.funcs import mylog
+from yt.data_objects.profiles import BinnedProfile1D
+from yt.visualization.volume_rendering.api import ColorTransferFunction
+from yt.visualization._mpl_imports import FigureCanvasAgg
+from matplotlib.figure import Figure
+from IPython.core.display import Image
+import cStringIO
+import numpy as np
+
+
+class TransferFunctionHelper(object):
+
+ profiles = {}
+
+ def __init__(self, pf):
+ r"""A transfer function helper.
+
+ This attempts to help set up a good transfer function by finding
+ bounds, handling linear/log options, and displaying the transfer
+ function combined with 1D profiles of rendering quantity.
+
+ Parameters
+ ----------
+ pf: A StaticOutput instance
+ A static output that is currently being rendered. This is used to
+ help set up data bounds.
+
+ Notes
+ -----
+ """
+ self.pf = pf
+ self.field = None
+ self.log = False
+ self.tf = None
+ self.bounds = None
+ self.grey_opacity = True
+
+ def set_bounds(self, bounds=None):
+ """
+ Set the bounds of the transfer function.
+
+ Parameters
+ ----------
+ bounds: array-like, length 2, optional
+ A length 2 list/array in the form [min, max]. These should be the
+ raw values and not the logarithm of the min and max. If bounds is
+ None, the bounds of the data are calculated from all of the data
+ in the dataset. This can be slow for very large datasets.
+ """
+ if bounds is None:
+ self.bounds = \
+ self.pf.h.all_data().quantities['Extrema'](self.field)[0]
+
+ # Do some error checking.
+ assert(len(self.bounds) == 2)
+ if self.log:
+ assert(self.bounds[0] > 0.0)
+ assert(self.bounds[1] > 0.0)
+ return
+
+ def set_field(self, field):
+ """
+ Set the field to be rendered
+
+ Parameters
+ ----------
+ field: string
+ The field to be rendered.
+ """
+ self.field = field
+
+ def set_log(self, log):
+ """
+ Set whether or not the transfer function should be in log or linear
+ space. Also modifies the pf.field_info[field].take_log attribute to
+ stay in sync with this setting.
+
+ Parameters
+ ----------
+ log: boolean
+ Sets whether the transfer function should use log or linear space.
+ """
+ self.log = log
+ self.pf.h
+ self.pf.field_info[self.field].take_log = log
+
+ def build_transfer_function(self):
+ """
+ Builds the transfer function according to the current state of the
+ TransferFunctionHelper.
+
+ Parameters
+ ----------
+ None
+
+ Returns
+ -------
+
+ A ColorTransferFunction object.
+
+ """
+ if self.bounds is None:
+ mylog.info('Calculating data bounds. This may take a while.' +
+ ' Set the .bounds to avoid this.')
+ self.set_bounds()
+
+ if self.log:
+ mi, ma = np.log10(self.bounds[0]), np.log10(self.bounds[1])
+ else:
+ mi, ma = self.bounds
+ self.tf = ColorTransferFunction((mi, ma),
+ grey_opacity=self.grey_opacity,
+ nbins=512)
+ return self.tf
+
+ def plot(self, fn=None, profile_field=None, profile_weight=None):
+ """
+ Save the current transfer function to a bitmap, or display
+ it inline.
+
+ Parameters
+ ----------
+ fn: string, optional
+ Filename to save the image to. If None, the returns an image
+ to an IPython session.
+
+ Returns
+ -------
+
+ If fn is None, will return an image to an IPython notebook.
+
+ """
+ if self.tf is None:
+ self.build_transfer_function()
+ tf = self.tf
+ if self.log:
+ xfunc = np.logspace
+ xmi, xma = np.log10(self.bounds[0]), np.log10(self.bounds[1])
+ else:
+ xfunc = np.linspace
+ xmi, xma = self.bounds
+
+ x = xfunc(xmi, xma, tf.nbins)
+ y = tf.funcs[3].y
+ w = np.append(x[1:]-x[:-1], x[-1]-x[-2])
+ colors = np.array([tf.funcs[0].y, tf.funcs[1].y, tf.funcs[2].y,
+ np.ones_like(x)]).T
+
+ fig = Figure(figsize=[6, 3])
+ canvas = FigureCanvasAgg(fig)
+ ax = fig.add_axes([0.2, 0.2, 0.75, 0.75])
+ ax.bar(x, tf.funcs[3].y, w, edgecolor=[0.0, 0.0, 0.0, 0.0],
+ log=True, color=colors)
+
+ if profile_field is not None:
+ try:
+ prof = self.profiles[self.field]
+ except KeyError:
+ self.setup_profile(profile_field, profile_weight)
+ prof = self.profiles[self.field]
+ ax.plot(prof[self.field], prof[profile_field]*tf.funcs[3].y.max() /
+ prof[profile_field].max(), color='w', linewidth=3)
+ ax.plot(prof[self.field], prof[profile_field]*tf.funcs[3].y.max() /
+ prof[profile_field].max(), color='k')
+
+ ax.set_xscale({True: 'log', False: 'linear'}[self.log])
+ ax.set_xlim(x.min(), x.max())
+ ax.set_xlabel(self.pf.field_info[self.field].get_label())
+ ax.set_ylabel(r'$\mathrm{alpha}$')
+ ax.set_ylim(y.max()*1.0e-3, y.max()*2)
+
+ if fn is None:
+ f = cStringIO.StringIO()
+ canvas.print_figure(f)
+ f.seek(0)
+ img = f.read()
+ return Image(img)
+ else:
+ fig.savefig(fn)
+
+ def setup_profile(self, profile_field=None, profile_weight=None):
+ if profile_field is None:
+ profile_field = 'CellVolume'
+ prof = BinnedProfile1D(self.pf.h.all_data(), 128, self.field,
+ self.bounds[0], self.bounds[1],
+ log_space=self.log,
+ lazy_reader=False, end_collect=False)
+ prof.add_fields([profile_field], fractional=False,
+ weight=profile_weight)
+ self.profiles[self.field] = prof
+ return
diff -r 8e8bd5b353df99c1510058a7c982329e5212fcfe -r da308f4c50c7b632169cb3e37036a9651c262864 yt/visualization/volume_rendering/transfer_functions.py
--- a/yt/visualization/volume_rendering/transfer_functions.py
+++ b/yt/visualization/volume_rendering/transfer_functions.py
@@ -641,6 +641,8 @@
self.x_bounds[0]))
rel1 = int(self.nbins*(ma - self.x_bounds[0])/(self.x_bounds[1] -
self.x_bounds[0]))
+ rel0 = max(rel0, 0)
+ rel1 = min(rel1, self.nbins-1)
tomap = np.linspace(0.,1.,num=rel1-rel0)
cmap = get_cmap(colormap)
cc = cmap(tomap)
https://bitbucket.org/yt_analysis/yt/commits/1fb87198e5e9/
Changeset: 1fb87198e5e9
Branch: yt
User: samskillman
Date: 2013-06-30 04:10:52
Summary: Fix in case a profile is then asked for a different field.
Affected #: 1 file
diff -r da308f4c50c7b632169cb3e37036a9651c262864 -r 1fb87198e5e9d7cdf793da6a8150d4b1d2a07092 yt/visualization/volume_rendering/transfer_function_helper.py
--- a/yt/visualization/volume_rendering/transfer_function_helper.py
+++ b/yt/visualization/volume_rendering/transfer_function_helper.py
@@ -183,6 +183,9 @@
except KeyError:
self.setup_profile(profile_field, profile_weight)
prof = self.profiles[self.field]
+ if profile_field not in prof.keys():
+ prof.add_fields([profile_field], fractional=False,
+ weight=profile_weight)
ax.plot(prof[self.field], prof[profile_field]*tf.funcs[3].y.max() /
prof[profile_field].max(), color='w', linewidth=3)
ax.plot(prof[self.field], prof[profile_field]*tf.funcs[3].y.max() /
https://bitbucket.org/yt_analysis/yt/commits/a588666af47f/
Changeset: a588666af47f
Branch: yt
User: samskillman
Date: 2013-07-08 22:59:58
Summary: Fixing up the bounds to be respected, working around a matplotlib bug for
logarithmic bar plots, and initializing the profiles more properly.
Affected #: 1 file
diff -r 1fb87198e5e9d7cdf793da6a8150d4b1d2a07092 -r a588666af47f6e39cd931225df084a8633195e14 yt/visualization/volume_rendering/transfer_function_helper.py
--- a/yt/visualization/volume_rendering/transfer_function_helper.py
+++ b/yt/visualization/volume_rendering/transfer_function_helper.py
@@ -35,7 +35,7 @@
class TransferFunctionHelper(object):
- profiles = {}
+ profiles = None
def __init__(self, pf):
r"""A transfer function helper.
@@ -59,6 +59,7 @@
self.tf = None
self.bounds = None
self.grey_opacity = True
+ self.profiles = {}
def set_bounds(self, bounds=None):
"""
@@ -73,8 +74,8 @@
in the dataset. This can be slow for very large datasets.
"""
if bounds is None:
- self.bounds = \
- self.pf.h.all_data().quantities['Extrema'](self.field)[0]
+ bounds = self.pf.h.all_data().quantities['Extrema'](self.field)[0]
+ self.bounds = bounds
# Do some error checking.
assert(len(self.bounds) == 2)
@@ -175,7 +176,7 @@
canvas = FigureCanvasAgg(fig)
ax = fig.add_axes([0.2, 0.2, 0.75, 0.75])
ax.bar(x, tf.funcs[3].y, w, edgecolor=[0.0, 0.0, 0.0, 0.0],
- log=True, color=colors)
+ log=True, color=colors, bottom=[0])
if profile_field is not None:
try:
https://bitbucket.org/yt_analysis/yt/commits/51157128e185/
Changeset: 51157128e185
Branch: yt
User: MatthewTurk
Date: 2013-10-02 21:32:13
Summary: Merged in samskillman/yt (pull request #538)
Transfer Function Helper
Affected #: 1 file
diff -r 824ba0b66e9229d070e9323032301e061e57a916 -r 51157128e18557c82dc00a9f5853b6bcd361e63a yt/visualization/volume_rendering/transfer_function_helper.py
--- /dev/null
+++ b/yt/visualization/volume_rendering/transfer_function_helper.py
@@ -0,0 +1,220 @@
+"""
+A helper class to build, display, and modify transfer functions for volume
+rendering.
+
+Author: Samuel Skillman <samskillman at gmail.com>
+Affiliation: DOE CSGF, U. of Colorado at Boulder
+Homepage: http://yt-project.org/
+License:
+ Copyright (C) 2013 Samuel Skillman. All Rights Reserved.
+
+ This file is part of yt.
+
+ yt is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+"""
+from yt.funcs import mylog
+from yt.data_objects.profiles import BinnedProfile1D
+from yt.visualization.volume_rendering.api import ColorTransferFunction
+from yt.visualization._mpl_imports import FigureCanvasAgg
+from matplotlib.figure import Figure
+from IPython.core.display import Image
+import cStringIO
+import numpy as np
+
+
+class TransferFunctionHelper(object):
+
+ profiles = None
+
+ def __init__(self, pf):
+ r"""A transfer function helper.
+
+ This attempts to help set up a good transfer function by finding
+ bounds, handling linear/log options, and displaying the transfer
+ function combined with 1D profiles of rendering quantity.
+
+ Parameters
+ ----------
+ pf: A StaticOutput instance
+ A static output that is currently being rendered. This is used to
+ help set up data bounds.
+
+ Notes
+ -----
+ """
+ self.pf = pf
+ self.field = None
+ self.log = False
+ self.tf = None
+ self.bounds = None
+ self.grey_opacity = True
+ self.profiles = {}
+
+ def set_bounds(self, bounds=None):
+ """
+ Set the bounds of the transfer function.
+
+ Parameters
+ ----------
+ bounds: array-like, length 2, optional
+ A length 2 list/array in the form [min, max]. These should be the
+ raw values and not the logarithm of the min and max. If bounds is
+ None, the bounds of the data are calculated from all of the data
+ in the dataset. This can be slow for very large datasets.
+ """
+ if bounds is None:
+ bounds = self.pf.h.all_data().quantities['Extrema'](self.field)[0]
+ self.bounds = bounds
+
+ # Do some error checking.
+ assert(len(self.bounds) == 2)
+ if self.log:
+ assert(self.bounds[0] > 0.0)
+ assert(self.bounds[1] > 0.0)
+ return
+
+ def set_field(self, field):
+ """
+ Set the field to be rendered
+
+ Parameters
+ ----------
+ field: string
+ The field to be rendered.
+ """
+ self.field = field
+
+ def set_log(self, log):
+ """
+ Set whether or not the transfer function should be in log or linear
+ space. Also modifies the pf.field_info[field].take_log attribute to
+ stay in sync with this setting.
+
+ Parameters
+ ----------
+ log: boolean
+ Sets whether the transfer function should use log or linear space.
+ """
+ self.log = log
+ self.pf.h
+ self.pf.field_info[self.field].take_log = log
+
+ def build_transfer_function(self):
+ """
+ Builds the transfer function according to the current state of the
+ TransferFunctionHelper.
+
+ Parameters
+ ----------
+ None
+
+ Returns
+ -------
+
+ A ColorTransferFunction object.
+
+ """
+ if self.bounds is None:
+ mylog.info('Calculating data bounds. This may take a while.' +
+ ' Set the .bounds to avoid this.')
+ self.set_bounds()
+
+ if self.log:
+ mi, ma = np.log10(self.bounds[0]), np.log10(self.bounds[1])
+ else:
+ mi, ma = self.bounds
+ self.tf = ColorTransferFunction((mi, ma),
+ grey_opacity=self.grey_opacity,
+ nbins=512)
+ return self.tf
+
+ def plot(self, fn=None, profile_field=None, profile_weight=None):
+ """
+ Save the current transfer function to a bitmap, or display
+ it inline.
+
+ Parameters
+ ----------
+ fn: string, optional
+ Filename to save the image to. If None, the returns an image
+ to an IPython session.
+
+ Returns
+ -------
+
+ If fn is None, will return an image to an IPython notebook.
+
+ """
+ if self.tf is None:
+ self.build_transfer_function()
+ tf = self.tf
+ if self.log:
+ xfunc = np.logspace
+ xmi, xma = np.log10(self.bounds[0]), np.log10(self.bounds[1])
+ else:
+ xfunc = np.linspace
+ xmi, xma = self.bounds
+
+ x = xfunc(xmi, xma, tf.nbins)
+ y = tf.funcs[3].y
+ w = np.append(x[1:]-x[:-1], x[-1]-x[-2])
+ colors = np.array([tf.funcs[0].y, tf.funcs[1].y, tf.funcs[2].y,
+ np.ones_like(x)]).T
+
+ fig = Figure(figsize=[6, 3])
+ canvas = FigureCanvasAgg(fig)
+ ax = fig.add_axes([0.2, 0.2, 0.75, 0.75])
+ ax.bar(x, tf.funcs[3].y, w, edgecolor=[0.0, 0.0, 0.0, 0.0],
+ log=True, color=colors, bottom=[0])
+
+ if profile_field is not None:
+ try:
+ prof = self.profiles[self.field]
+ except KeyError:
+ self.setup_profile(profile_field, profile_weight)
+ prof = self.profiles[self.field]
+ if profile_field not in prof.keys():
+ prof.add_fields([profile_field], fractional=False,
+ weight=profile_weight)
+ ax.plot(prof[self.field], prof[profile_field]*tf.funcs[3].y.max() /
+ prof[profile_field].max(), color='w', linewidth=3)
+ ax.plot(prof[self.field], prof[profile_field]*tf.funcs[3].y.max() /
+ prof[profile_field].max(), color='k')
+
+ ax.set_xscale({True: 'log', False: 'linear'}[self.log])
+ ax.set_xlim(x.min(), x.max())
+ ax.set_xlabel(self.pf.field_info[self.field].get_label())
+ ax.set_ylabel(r'$\mathrm{alpha}$')
+ ax.set_ylim(y.max()*1.0e-3, y.max()*2)
+
+ if fn is None:
+ f = cStringIO.StringIO()
+ canvas.print_figure(f)
+ f.seek(0)
+ img = f.read()
+ return Image(img)
+ else:
+ fig.savefig(fn)
+
+ def setup_profile(self, profile_field=None, profile_weight=None):
+ if profile_field is None:
+ profile_field = 'CellVolume'
+ prof = BinnedProfile1D(self.pf.h.all_data(), 128, self.field,
+ self.bounds[0], self.bounds[1],
+ log_space=self.log,
+ lazy_reader=False, end_collect=False)
+ prof.add_fields([profile_field], fractional=False,
+ weight=profile_weight)
+ self.profiles[self.field] = prof
+ return
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