[yt-svn] commit/yt: MatthewTurk: Merging from development tip.
Bitbucket
commits-noreply at bitbucket.org
Wed Feb 20 08:02:51 PST 2013
1 new commit in yt:
https://bitbucket.org/yt_analysis/yt/commits/3161cb50ce62/
changeset: 3161cb50ce62
branch: stable
user: MatthewTurk
date: 2013-02-20 17:02:42
summary: Merging from development tip.
affected #: 15 files
diff -r 329d11eeff224ed16d054e989680ba6f193318e9 -r 3161cb50ce626380cbf2958e0abacf61677072e3 CREDITS
--- a/CREDITS
+++ b/CREDITS
@@ -1,29 +1,41 @@
YT is a group effort.
-Contributors: Matthew Turk (matthewturk at gmail.com)
- Britton Smith (brittonsmith at gmail.com)
- Jeff Oishi (jsoishi at gmail.com)
- Stephen Skory (s at skory.us)
- Sam Skillman (samskillman at gmail.com)
- Devin Silvia (devin.silvia at gmail.com)
- John Wise (jwise at astro.princeton.edu)
- David Collins (dcollins at physics.ucsd.edu)
- Christopher Moody (cemoody at ucsc.edu)
- Oliver Hahn (ohahn at stanford.edu)
- John ZuHone (jzuhone at cfa.harvard.edu)
- Chris Malone (cmalone at mail.astro.sunysb.edu)
- Cameron Hummels (chummels at astro.columbia.edu)
- Stefan Klemer (sklemer at phys.uni-goettingen.de)
- Tom Abel (tabel at stanford.edu)
- Andrew Myers (atmyers at astro.berkeley.edu)
- Michael Kuhlen (mqk at astro.berkeley.edu)
- Casey Stark (caseywstark at gmail.com)
- JC Passy (jcpassy at gmail.com)
- Eve Lee (elee at cita.utoronto.ca)
- Elizabeth Tasker (tasker at astro1.sci.hokudai.ac.jp)
- Kacper Kowalik (xarthisius.kk at gmail.com)
- Nathan Goldbaum (goldbaum at ucolick.org)
- Anna Rosen (rosen at ucolick.org)
+Contributors: Tom Abel (tabel at stanford.edu)
+ David Collins (dcollins at physics.ucsd.edu)
+ Brian Crosby (crosby.bd at gmail.com)
+ Andrew Cunningham (ajcunn at gmail.com)
+ Nathan Goldbaum (goldbaum at ucolick.org)
+ Markus Haider (markus.haider at uibk.ac.at)
+ Cameron Hummels (chummels at gmail.com)
+ Christian Karch (chiffre at posteo.de)
+ Ji-hoon Kim (me at jihoonkim.org)
+ Steffen Klemer (sklemer at phys.uni-goettingen.de)
+ Kacper Kowalik (xarthisius.kk at gmail.com)
+ Michael Kuhlen (mqk at astro.berkeley.edu)
+ Eve Lee (elee at cita.utoronto.ca)
+ Yuan Li (yuan at astro.columbia.edu)
+ Chris Malone (chris.m.malone at gmail.com)
+ Josh Maloney (joshua.moloney at colorado.edu)
+ Chris Moody (cemoody at ucsc.edu)
+ Andrew Myers (atmyers at astro.berkeley.edu)
+ Jeff Oishi (jsoishi at gmail.com)
+ Jean-Claude Passy (jcpassy at uvic.ca)
+ Mark Richardson (Mark.L.Richardson at asu.edu)
+ Thomas Robitaille (thomas.robitaille at gmail.com)
+ Anna Rosen (rosen at ucolick.org)
+ Anthony Scopatz (scopatz at gmail.com)
+ Devin Silvia (devin.silvia at colorado.edu)
+ Sam Skillman (samskillman at gmail.com)
+ Stephen Skory (s at skory.us)
+ Britton Smith (brittonsmith at gmail.com)
+ Geoffrey So (gsiisg at gmail.com)
+ Casey Stark (caseywstark at gmail.com)
+ Elizabeth Tasker (tasker at astro1.sci.hokudai.ac.jp)
+ Stephanie Tonnesen (stonnes at gmail.com)
+ Matthew Turk (matthewturk at gmail.com)
+ Rich Wagner (rwagner at physics.ucsd.edu)
+ John Wise (jwise at physics.gatech.edu)
+ John ZuHone (jzuhone at gmail.com)
We also include the Delaunay Triangulation module written by Robert Kern of
Enthought, the cmdln.py module by Trent Mick, and the progressbar module by
diff -r 329d11eeff224ed16d054e989680ba6f193318e9 -r 3161cb50ce626380cbf2958e0abacf61677072e3 yt/analysis_modules/halo_finding/rockstar/rockstar.py
--- a/yt/analysis_modules/halo_finding/rockstar/rockstar.py
+++ b/yt/analysis_modules/halo_finding/rockstar/rockstar.py
@@ -164,6 +164,13 @@
If set to ``True``, it will be assumed that there are only dark
matter particles present in the simulation. This can save analysis
time if this is indeed the case. Default: ``False``.
+ hires_dm_mass : float
+ If supplied, use only the highest resolution dark matter
+ particles, with a mass less than (1.1*hires_dm_mass), in units
+ of ParticleMassMsun. This is useful for multi-dm-mass
+ simulations. Note that this will only give sensible results for
+ halos that are not "polluted" by lower resolution
+ particles. Default: ``None``.
Returns
-------
@@ -187,7 +194,8 @@
"""
def __init__(self, ts, num_readers = 1, num_writers = None,
outbase="rockstar_halos", dm_type=1,
- force_res=None, total_particles=None, dm_only=False):
+ force_res=None, total_particles=None, dm_only=False,
+ hires_dm_mass=None):
mylog.warning("The citation for the Rockstar halo finder can be found at")
mylog.warning("http://adsabs.harvard.edu/abs/2013ApJ...762..109B")
ParallelAnalysisInterface.__init__(self)
@@ -217,6 +225,7 @@
self.force_res = force_res
self.total_particles = total_particles
self.dm_only = dm_only
+ self.hires_dm_mass = hires_dm_mass
# Setup pool and workgroups.
self.pool, self.workgroup = self.runner.setup_pool()
p = self._setup_parameters(ts)
@@ -227,28 +236,51 @@
def _setup_parameters(self, ts):
if self.workgroup.name != "readers": return None
tpf = ts[0]
+
def _particle_count(field, data):
- if self.dm_only:
- return np.prod(data["particle_position_x"].shape)
try:
- return (data["particle_type"]==self.dm_type).sum()
+ data["particle_type"]
+ has_particle_type=True
except KeyError:
- return np.prod(data["particle_position_x"].shape)
+ has_particle_type=False
+
+ if (self.dm_only or (not has_particle_type)):
+ if self.hires_dm_mass is None:
+ return np.prod(data["particle_position_x"].shape)
+ else:
+ return (data['ParticleMassMsun'] < self.hires_dm_mass*1.1).sum()
+ elif has_particle_type:
+ if self.hires_dm_mass is None:
+ return (data["particle_type"]==self.dm_type).sum()
+ else:
+ return ( (data["particle_type"]==self.dm_type) &
+ (data['ParticleMassMsun'] < self.hires_dm_mass*1.1) ).sum()
+ else:
+ raise RuntimeError() # should never get here
+
add_field("particle_count", function=_particle_count,
not_in_all=True, particle_type=True)
dd = tpf.h.all_data()
# Get DM particle mass.
all_fields = set(tpf.h.derived_field_list + tpf.h.field_list)
- for g in tpf.h._get_objs("grids"):
- if g.NumberOfParticles == 0: continue
- if self.dm_only:
- iddm = Ellipsis
- elif "particle_type" in all_fields:
- iddm = g["particle_type"] == self.dm_type
- else:
- iddm = Ellipsis
- particle_mass = g['ParticleMassMsun'][iddm][0] / tpf.hubble_constant
- break
+ has_particle_type = ("particle_type" in all_fields)
+
+ if self.hires_dm_mass is None:
+ for g in tpf.h._get_objs("grids"):
+ if g.NumberOfParticles == 0: continue
+
+ if (self.dm_only or (not has_particle_type)):
+ iddm = Ellipsis
+ elif has_particle_type:
+ iddm = g["particle_type"] == self.dm_type
+ else:
+ iddm = Ellipsis # should never get here
+
+ particle_mass = g['ParticleMassMsun'][iddm][0] / tpf.hubble_constant
+ break
+ else:
+ particle_mass = self.hires_dm_mass / tpf.hubble_constant
+
p = {}
if self.total_particles is None:
# Get total_particles in parallel.
@@ -302,6 +334,7 @@
force_res = self.force_res,
particle_mass = float(self.particle_mass),
dm_only = int(self.dm_only),
+ hires_only = (self.hires_dm_mass is not None),
**kwargs)
# Make the directory to store the halo lists in.
if self.comm.rank == 0:
diff -r 329d11eeff224ed16d054e989680ba6f193318e9 -r 3161cb50ce626380cbf2958e0abacf61677072e3 yt/analysis_modules/halo_finding/rockstar/rockstar_interface.pyx
--- a/yt/analysis_modules/halo_finding/rockstar/rockstar_interface.pyx
+++ b/yt/analysis_modules/halo_finding/rockstar/rockstar_interface.pyx
@@ -163,6 +163,7 @@
SCALE_NOW = 1.0/(pf.current_redshift+1.0)
# Now we want to grab data from only a subset of the grids for each reader.
all_fields = set(pf.h.derived_field_list + pf.h.field_list)
+ has_particle_type = ("particle_type" in all_fields)
# First we need to find out how many this reader is going to read in
# if the number of readers > 1.
@@ -170,12 +171,19 @@
local_parts = 0
for g in pf.h._get_objs("grids"):
if g.NumberOfParticles == 0: continue
- if rh.dm_only:
- iddm = Ellipsis
- elif "particle_type" in all_fields:
- iddm = g["particle_type"] == rh.dm_type
+ if (rh.dm_only or (not has_particle_type)):
+ if rh.hires_only:
+ iddm = (g['ParticleMassMsun'] < PARTICLE_MASS*1.1)
+ else:
+ iddm = Ellipsis
+ elif has_particle_type:
+ if rh.hires_only:
+ iddm = ( (g["particle_type"]==rh.dm_type) &
+ (g['ParticleMassMsun'] < PARTICLE_MASS*1.1) )
+ else:
+ iddm = g["particle_type"] == rh.dm_type
else:
- iddm = Ellipsis
+ iddm = Ellipsis # should never get here
arri = g["particle_index"].astype("int64")
arri = arri[iddm] #pick only DM
local_parts += arri.size
@@ -195,12 +203,19 @@
pi = 0
for g in pf.h._get_objs("grids"):
if g.NumberOfParticles == 0: continue
- if rh.dm_only:
- iddm = Ellipsis
- elif "particle_type" in all_fields:
- iddm = g["particle_type"] == rh.dm_type
- else:
- iddm = Ellipsis
+ if (rh.dm_only or (not has_particle_type)):
+ if rh.hires_only:
+ iddm = (g['ParticleMassMsun'] < PARTICLE_MASS*1.1)
+ else:
+ iddm = Ellipsis
+ elif has_particle_type:
+ if rh.hires_only:
+ iddm = ( (g["particle_type"]==rh.dm_type) &
+ (g['ParticleMassMsun'] < PARTICLE_MASS*1.1) )
+ else:
+ iddm = g["particle_type"] == rh.dm_type
+ else:
+ iddm = Ellipsis # should never get here
arri = g["particle_index"].astype("int64")
arri = arri[iddm] #pick only DM
npart = arri.size
@@ -230,6 +245,7 @@
cdef public int dm_type
cdef public int total_particles
cdef public int dm_only
+ cdef public int hires_only
def __cinit__(self, ts):
self.ts = ts
@@ -244,7 +260,7 @@
int writing_port = -1, int block_ratio = 1,
int periodic = 1, force_res=None,
int min_halo_size = 25, outbase = "None",
- int dm_only = 0):
+ int dm_only = 0, int hires_only = False):
global PARALLEL_IO, PARALLEL_IO_SERVER_ADDRESS, PARALLEL_IO_SERVER_PORT
global FILENAME, FILE_FORMAT, NUM_SNAPS, STARTING_SNAP, h0, Ol, Om
global BOX_SIZE, PERIODIC, PARTICLE_MASS, NUM_BLOCKS, NUM_READERS
@@ -276,6 +292,7 @@
TOTAL_PARTICLES = total_particles
self.block_ratio = block_ratio
self.dm_only = dm_only
+ self.hires_only = hires_only
tpf = self.ts[0]
h0 = tpf.hubble_constant
diff -r 329d11eeff224ed16d054e989680ba6f193318e9 -r 3161cb50ce626380cbf2958e0abacf61677072e3 yt/analysis_modules/halo_merger_tree/enzofof_merger_tree.py
--- a/yt/analysis_modules/halo_merger_tree/enzofof_merger_tree.py
+++ b/yt/analysis_modules/halo_merger_tree/enzofof_merger_tree.py
@@ -810,6 +810,6 @@
ax.set_xscale("log")
if y_log:
ax.set_yscale("log")
- ofn = "%s_%s_%s.png" % (basename, fields[0], fields[1])
+ ofn = "%s/%s_%s_%s.png" % (FOF_directory, basename, fields[0], fields[1])
plt.savefig(ofn)
plt.clf()
diff -r 329d11eeff224ed16d054e989680ba6f193318e9 -r 3161cb50ce626380cbf2958e0abacf61677072e3 yt/data_objects/image_array.py
--- a/yt/data_objects/image_array.py
+++ b/yt/data_objects/image_array.py
@@ -71,12 +71,12 @@
>>> im = np.zeros([64,128,3])
>>> for i in xrange(im.shape[0]):
- >>> for k in xrange(im.shape[2]):
- >>> im[i,:,k] = np.linspace(0.,0.3*k, im.shape[1])
+ ... for k in xrange(im.shape[2]):
+ ... im[i,:,k] = np.linspace(0.,0.3*k, im.shape[1])
>>> myinfo = {'field':'dinosaurs', 'east_vector':np.array([1.,0.,0.]),
- >>> 'north_vector':np.array([0.,0.,1.]), 'normal_vector':np.array([0.,1.,0.]),
- >>> 'width':0.245, 'units':'cm', 'type':'rendering'}
+ ... 'north_vector':np.array([0.,0.,1.]), 'normal_vector':np.array([0.,1.,0.]),
+ ... 'width':0.245, 'units':'cm', 'type':'rendering'}
>>> im_arr = ImageArray(im, info=myinfo)
>>> im_arr.save('test_ImageArray')
@@ -112,12 +112,12 @@
--------
>>> im = np.zeros([64,128,3])
>>> for i in xrange(im.shape[0]):
- >>> for k in xrange(im.shape[2]):
- >>> im[i,:,k] = np.linspace(0.,0.3*k, im.shape[1])
+ ... for k in xrange(im.shape[2]):
+ ... im[i,:,k] = np.linspace(0.,0.3*k, im.shape[1])
>>> myinfo = {'field':'dinosaurs', 'east_vector':np.array([1.,0.,0.]),
- >>> 'north_vector':np.array([0.,0.,1.]), 'normal_vector':np.array([0.,1.,0.]),
- >>> 'width':0.245, 'units':'cm', 'type':'rendering'}
+ ... 'north_vector':np.array([0.,0.,1.]), 'normal_vector':np.array([0.,1.,0.]),
+ ... 'width':0.245, 'units':'cm', 'type':'rendering'}
>>> im_arr = ImageArray(im, info=myinfo)
>>> im_arr.write_hdf5('test_ImageArray.h5')
@@ -133,38 +133,191 @@
d.attrs.create(k, v)
f.close()
- def write_png(self, filename, clip_ratio=None):
+ def add_background_color(self, background='black', inline=True):
+ r"""Adds a background color to a 4-channel ImageArray
+
+ This adds a background color to a 4-channel ImageArray, by default
+ doing so inline. The ImageArray must already be normalized to the
+ [0,1] range.
+
+ Parameters
+ ----------
+ background:
+ This can be used to set a background color for the image, and can
+ take several types of values:
+
+ * ``white``: white background, opaque
+ * ``black``: black background, opaque
+ * ``None``: transparent background
+ * 4-element array [r,g,b,a]: arbitrary rgba setting.
+
+ Default: 'black'
+ inline: boolean, optional
+ If True, original ImageArray is modified. If False, a copy is first
+ created, then modified. Default: True
+
+ Returns
+ -------
+ out: ImageArray
+ The modified ImageArray with a background color added.
+
+ Examples
+ --------
+ >>> im = np.zeros([64,128,4])
+ >>> for i in xrange(im.shape[0]):
+ ... for k in xrange(im.shape[2]):
+ ... im[i,:,k] = np.linspace(0.,10.*k, im.shape[1])
+
+ >>> im_arr = ImageArray(im)
+ >>> im_arr.rescale()
+ >>> new_im = im_arr.add_background_color([1.,0.,0.,1.], inline=False)
+ >>> new_im.write_png('red_bg.png')
+ >>> im_arr.add_background_color('black')
+ >>> im_arr.write_png('black_bg.png')
+ """
+ assert(self.shape[-1] == 4)
+
+ if background == None:
+ background = (0., 0., 0., 0.)
+ elif background == 'white':
+ background = (1., 1., 1., 1.)
+ elif background == 'black':
+ background = (0., 0., 0., 1.)
+
+ # Alpha blending to background
+ if inline:
+ out = self
+ else:
+ out = self.copy()
+
+ for i in range(3):
+ out[:,:,i] = self[:,:,i]*self[:,:,3] + \
+ background[i]*background[3]*(1.0-self[:,:,3])
+ out[:,:,3] = self[:,:,3] + background[3]*(1.0-self[:,:,3])
+ return out
+
+
+ def rescale(self, cmax=None, amax=None, inline=True):
+ r"""Rescales the image to be in [0,1] range.
+
+ Parameters
+ ----------
+ cmax: float, optional
+ Normalization value to use for rgb channels. Defaults to None,
+ corresponding to using the maximum value in the rgb channels.
+ amax: float, optional
+ Normalization value to use for alpha channel. Defaults to None,
+ corresponding to using the maximum value in the alpha channel.
+ inline: boolean, optional
+ Specifies whether or not the rescaling is done inline. If false,
+ a new copy of the ImageArray will be created, returned.
+ Default:True.
+
+ Returns
+ -------
+ out: ImageArray
+ The rescaled ImageArray, clipped to the [0,1] range.
+
+ Notes
+ -----
+ This requires that the shape of the ImageArray to have a length of 3,
+ and for the third dimension to be >= 3. If the third dimension has
+ a shape of 4, the alpha channel will also be rescaled.
+
+ Examples
+ --------
+ >>> im = np.zeros([64,128,4])
+ >>> for i in xrange(im.shape[0]):
+ ... for k in xrange(im.shape[2]):
+ ... im[i,:,k] = np.linspace(0.,0.3*k, im.shape[1])
+
+ >>> im_arr.write_png('original.png')
+ >>> im_arr.rescale()
+ >>> im_arr.write_png('normalized.png')
+
+ """
+ assert(len(self.shape) == 3)
+ assert(self.shape[2] >= 3)
+ if inline:
+ out = self
+ else:
+ out = self.copy()
+ if cmax is None:
+ cmax = self[:,:,:3].sum(axis=2).max()
+
+ np.multiply(self[:,:,:3], 1./cmax, out[:,:,:3])
+
+ if self.shape[2] == 4:
+ if amax is None:
+ amax = self[:,:,3].max()
+ if amax > 0.0:
+ np.multiply(self[:,:,3], 1./amax, out[:,:,3])
+
+ np.clip(out, 0.0, 1.0, out)
+ return out
+
+ def write_png(self, filename, clip_ratio=None, background='black',
+ rescale=True):
r"""Writes ImageArray to png file.
Parameters
----------
filename: string
Note filename not be modified.
+ clip_ratio: float, optional
+ Image will be clipped before saving to the standard deviation
+ of the image multiplied by this value. Useful for enhancing
+ images. Default: None
+ background:
+ This can be used to set a background color for the image, and can
+ take several types of values:
+
+ * ``white``: white background, opaque
+ * ``black``: black background, opaque
+ * ``None``: transparent background
+ * 4-element array [r,g,b,a]: arbitrary rgba setting.
+
+ Default: 'black'
+ rescale: boolean, optional
+ If True, will write out a rescaled image (without modifying the
+ original image). Default: True
Examples
--------
-
- >>> im = np.zeros([64,128,3])
+ >>> im = np.zeros([64,128,4])
>>> for i in xrange(im.shape[0]):
- >>> for k in xrange(im.shape[2]):
- >>> im[i,:,k] = np.linspace(0.,0.3*k, im.shape[1])
+ ... for k in xrange(im.shape[2]):
+ ... im[i,:,k] = np.linspace(0.,10.*k, im.shape[1])
- >>> myinfo = {'field':'dinosaurs', 'east_vector':np.array([1.,0.,0.]),
- >>> 'north_vector':np.array([0.,0.,1.]), 'normal_vector':np.array([0.,1.,0.]),
- >>> 'width':0.245, 'units':'cm', 'type':'rendering'}
-
- >>> im_arr = ImageArray(im, info=myinfo)
- >>> im_arr.write_png('test_ImageArray.png')
+ >>> im_arr = ImageArray(im)
+ >>> im_arr.write_png('standard.png')
+ >>> im_arr.write_png('non-scaled.png', rescale=False)
+ >>> im_arr.write_png('black_bg.png', background='black')
+ >>> im_arr.write_png('white_bg.png', background='white')
+ >>> im_arr.write_png('green_bg.png', background=[0,1,0,1])
+ >>> im_arr.write_png('transparent_bg.png', background=None)
"""
+ if rescale:
+ scaled = self.rescale(inline=False)
+ else:
+ scaled = self
+
+ if self.shape[-1] == 4:
+ out = scaled.add_background_color(background, inline=False)
+ else:
+ out = scaled
+
if filename[-4:] != '.png':
filename += '.png'
if clip_ratio is not None:
- return write_bitmap(self.swapaxes(0, 1), filename,
- clip_ratio * self.std())
+ nz = out[:,:,:3][out[:,:,:3].nonzero()]
+ return write_bitmap(out.swapaxes(0, 1), filename,
+ nz.mean() + \
+ clip_ratio * nz.std())
else:
- return write_bitmap(self.swapaxes(0, 1), filename)
+ return write_bitmap(out.swapaxes(0, 1), filename)
def write_image(self, filename, color_bounds=None, channel=None, cmap_name="algae", func=lambda x: x):
r"""Writes a single channel of the ImageArray to a png file.
@@ -197,11 +350,11 @@
>>> im = np.zeros([64,128])
>>> for i in xrange(im.shape[0]):
- >>> im[i,:] = np.linspace(0.,0.3*k, im.shape[1])
+ ... im[i,:] = np.linspace(0.,0.3*k, im.shape[1])
>>> myinfo = {'field':'dinosaurs', 'east_vector':np.array([1.,0.,0.]),
- >>> 'north_vector':np.array([0.,0.,1.]), 'normal_vector':np.array([0.,1.,0.]),
- >>> 'width':0.245, 'units':'cm', 'type':'rendering'}
+ ... 'north_vector':np.array([0.,0.,1.]), 'normal_vector':np.array([0.,1.,0.]),
+ ... 'width':0.245, 'units':'cm', 'type':'rendering'}
>>> im_arr = ImageArray(im, info=myinfo)
>>> im_arr.write_image('test_ImageArray.png')
@@ -245,27 +398,3 @@
__doc__ += np.ndarray.__doc__
-if __name__ == "__main__":
- im = np.zeros([64,128,3])
- for i in xrange(im.shape[0]):
- for k in xrange(im.shape[2]):
- im[i,:,k] = np.linspace(0.,0.3*k, im.shape[1])
-
- myinfo = {'field':'dinosaurs', 'east_vector':np.array([1.,0.,0.]),
- 'north_vector':np.array([0.,0.,1.]), 'normal_vector':np.array([0.,1.,0.]),
- 'width':0.245, 'units':'cm', 'type':'rendering'}
-
- im_arr = ImageArray(im, info=myinfo)
- im_arr.save('test_3d_ImageArray')
-
- im = np.zeros([64,128])
- for i in xrange(im.shape[0]):
- im[i,:] = np.linspace(0.,0.3*k, im.shape[1])
-
- myinfo = {'field':'dinosaurs', 'east_vector':np.array([1.,0.,0.]),
- 'north_vector':np.array([0.,0.,1.]), 'normal_vector':np.array([0.,1.,0.]),
- 'width':0.245, 'units':'cm', 'type':'rendering'}
-
- im_arr = ImageArray(im, info=myinfo)
- im_arr.save('test_2d_ImageArray')
-
diff -r 329d11eeff224ed16d054e989680ba6f193318e9 -r 3161cb50ce626380cbf2958e0abacf61677072e3 yt/data_objects/tests/test_image_array.py
--- /dev/null
+++ b/yt/data_objects/tests/test_image_array.py
@@ -0,0 +1,130 @@
+from yt.testing import *
+from yt.data_objects.image_array import ImageArray
+import numpy as np
+import os
+import tempfile
+import shutil
+
+def setup():
+ from yt.config import ytcfg
+ ytcfg["yt","__withintesting"] = "True"
+ np.seterr(all = 'ignore')
+
+def test_rgba_rescale():
+ im = np.zeros([64,128,4])
+ for i in xrange(im.shape[0]):
+ for k in xrange(im.shape[2]):
+ im[i,:,k] = np.linspace(0.,10.*k, im.shape[1])
+ im_arr = ImageArray(im)
+
+ new_im = im_arr.rescale(inline=False)
+ yield assert_equal, im_arr[:,:,:3].max(), 2*10.
+ yield assert_equal, im_arr[:,:,3].max(), 3*10.
+ yield assert_equal, new_im[:,:,:3].sum(axis=2).max(), 1.0
+ yield assert_equal, new_im[:,:,3].max(), 1.0
+
+ im_arr.rescale()
+ yield assert_equal, im_arr[:,:,:3].sum(axis=2).max(), 1.0
+ yield assert_equal, im_arr[:,:,3].max(), 1.0
+
+def test_image_array_hdf5():
+ # Perform I/O in safe place instead of yt main dir
+ tmpdir = tempfile.mkdtemp()
+ curdir = os.getcwd()
+ os.chdir(tmpdir)
+
+ im = np.zeros([64,128,3])
+ for i in xrange(im.shape[0]):
+ for k in xrange(im.shape[2]):
+ im[i,:,k] = np.linspace(0.,0.3*k, im.shape[1])
+
+ myinfo = {'field':'dinosaurs', 'east_vector':np.array([1.,0.,0.]),
+ 'north_vector':np.array([0.,0.,1.]), 'normal_vector':np.array([0.,1.,0.]),
+ 'width':0.245, 'units':'cm', 'type':'rendering'}
+
+ im_arr = ImageArray(im, info=myinfo)
+ im_arr.save('test_3d_ImageArray')
+
+ im = np.zeros([64,128])
+ for i in xrange(im.shape[0]):
+ im[i,:] = np.linspace(0.,0.3*k, im.shape[1])
+
+ myinfo = {'field':'dinosaurs', 'east_vector':np.array([1.,0.,0.]),
+ 'north_vector':np.array([0.,0.,1.]), 'normal_vector':np.array([0.,1.,0.]),
+ 'width':0.245, 'units':'cm', 'type':'rendering'}
+
+ im_arr = ImageArray(im, info=myinfo)
+ im_arr.save('test_2d_ImageArray')
+
+ os.chdir(curdir)
+ # clean up
+ shutil.rmtree(tmpdir)
+
+def test_image_array_rgb_png():
+ # Perform I/O in safe place instead of yt main dir
+ tmpdir = tempfile.mkdtemp()
+ curdir = os.getcwd()
+ os.chdir(tmpdir)
+
+ im = np.zeros([64,128,3])
+ for i in xrange(im.shape[0]):
+ for k in xrange(im.shape[2]):
+ im[i,:,k] = np.linspace(0.,10.*k, im.shape[1])
+
+ im_arr = ImageArray(im)
+ im_arr.write_png('standard.png')
+
+def test_image_array_rgba_png():
+ # Perform I/O in safe place instead of yt main dir
+ tmpdir = tempfile.mkdtemp()
+ curdir = os.getcwd()
+ os.chdir(tmpdir)
+
+ im = np.zeros([64,128,4])
+ for i in xrange(im.shape[0]):
+ for k in xrange(im.shape[2]):
+ im[i,:,k] = np.linspace(0.,10.*k, im.shape[1])
+
+ im_arr = ImageArray(im)
+ im_arr.write_png('standard.png')
+ im_arr.write_png('non-scaled.png', rescale=False)
+ im_arr.write_png('black_bg.png', background='black')
+ im_arr.write_png('white_bg.png', background='white')
+ im_arr.write_png('green_bg.png', background=[0.,1.,0.,1.])
+ im_arr.write_png('transparent_bg.png', background=None)
+
+
+def test_image_array_background():
+ # Perform I/O in safe place instead of yt main dir
+ tmpdir = tempfile.mkdtemp()
+ curdir = os.getcwd()
+ os.chdir(tmpdir)
+
+ im = np.zeros([64,128,4])
+ for i in xrange(im.shape[0]):
+ for k in xrange(im.shape[2]):
+ im[i,:,k] = np.linspace(0.,10.*k, im.shape[1])
+
+ im_arr = ImageArray(im)
+ im_arr.rescale()
+ new_im = im_arr.add_background_color([1.,0.,0.,1.], inline=False)
+ new_im.write_png('red_bg.png')
+ im_arr.add_background_color('black')
+ im_arr.write_png('black_bg2.png')
+
+ os.chdir(curdir)
+ # clean up
+ shutil.rmtree(tmpdir)
+
+
+
+
+
+
+
+
+
+
+
+
+
diff -r 329d11eeff224ed16d054e989680ba6f193318e9 -r 3161cb50ce626380cbf2958e0abacf61677072e3 yt/utilities/amr_kdtree/amr_kdtree.py
--- a/yt/utilities/amr_kdtree/amr_kdtree.py
+++ b/yt/utilities/amr_kdtree/amr_kdtree.py
@@ -35,12 +35,6 @@
from yt.utilities.lib.grid_traversal import PartitionedGrid
from yt.utilities.math_utils import periodic_position
-import pdb
-
-def my_break():
- my_debug = False
- if my_debug: pdb.set_trace()
-
steps = np.array([[-1, -1, -1], [-1, -1, 0], [-1, -1, 1],
[-1, 0, -1], [-1, 0, 0], [-1, 0, 1],
[-1, 1, -1], [-1, 1, 0], [-1, 1, 1],
@@ -81,7 +75,6 @@
self.build(grids)
def add_grids(self, grids):
- my_break()
lvl_range = range(self.min_level, self.max_level+1)
if grids is None:
level_iter = self.pf.hierarchy.get_levels()
@@ -95,7 +88,6 @@
gles = np.array([g.LeftEdge for g in grids])[gmask]
gres = np.array([g.RightEdge for g in grids])[gmask]
gids = np.array([g.id for g in grids])[gmask]
- my_break()
add_grids(self.trunk, gles, gres, gids, self.comm_rank, self.comm_size)
del gles, gres, gids, grids
else:
diff -r 329d11eeff224ed16d054e989680ba6f193318e9 -r 3161cb50ce626380cbf2958e0abacf61677072e3 yt/utilities/lib/misc_utilities.pyx
--- a/yt/utilities/lib/misc_utilities.pyx
+++ b/yt/utilities/lib/misc_utilities.pyx
@@ -126,19 +126,24 @@
cdef int nx = image.shape[0]
cdef int ny = image.shape[1]
cdef int nl = xs.shape[0]
- cdef np.float64_t alpha[3], nalpha
+ cdef np.float64_t alpha[4]
cdef int i, j
cdef int dx, dy, sx, sy, e2, err
cdef np.int64_t x0, x1, y0, y1
+ cdef int has_alpha = (image.shape[-1] == 4)
for j in range(0, nl, 2):
# From wikipedia http://en.wikipedia.org/wiki/Bresenham's_line_algorithm
x0 = xs[j]; y0 = ys[j]; x1 = xs[j+1]; y1 = ys[j+1]
dx = abs(x1-x0)
dy = abs(y1-y0)
err = dx - dy
- for i in range(3):
- alpha[i] = colors[j/points_per_color,3]*colors[j/points_per_color,i]
- nalpha = 1.0-colors[j/points_per_color,3]
+ if has_alpha:
+ for i in range(4):
+ alpha[i] = colors[j/points_per_color,i]
+ else:
+ for i in range(3):
+ alpha[i] = colors[j/points_per_color,3]*\
+ colors[j/points_per_color,i]
if x0 < x1:
sx = 1
else:
@@ -153,8 +158,13 @@
elif (y0 < 0 and sy == -1): break
elif (y0 >= nx and sy == 1): break
if (x0 >=0 and x0 < nx and y0 >= 0 and y0 < ny):
- for i in range(3):
- image[x0,y0,i] = (1.-alpha[i])*image[x0,y0,i] + alpha[i]
+ if has_alpha:
+ for i in range(4):
+ image[x0,y0,i] = (1.-alpha[i])*image[x0,y0,i] + alpha[i]
+ else:
+ for i in range(3):
+ image[x0,y0,i] = (1.-alpha[i])*image[x0,y0,i] + alpha[i]
+
if (x0 == x1 and y0 == y1):
break
e2 = 2*err
diff -r 329d11eeff224ed16d054e989680ba6f193318e9 -r 3161cb50ce626380cbf2958e0abacf61677072e3 yt/utilities/particle_generator.py
--- a/yt/utilities/particle_generator.py
+++ b/yt/utilities/particle_generator.py
@@ -7,9 +7,8 @@
default_fields = ["particle_position_x",
"particle_position_y",
- "particle_position_z",
- "particle_index"]
-
+ "particle_position_z"]
+
def __init__(self, pf, num_particles, field_list) :
"""
Base class for generating particle fields which may be applied to
@@ -21,20 +20,21 @@
self.pf = pf
self.num_particles = num_particles
self.field_list = field_list
-
+ self.field_list.append("particle_index")
+
try :
self.posx_index = self.field_list.index(self.default_fields[0])
self.posy_index = self.field_list.index(self.default_fields[1])
self.posz_index = self.field_list.index(self.default_fields[2])
- self.index_index = self.field_list.index(self.default_fields[3])
except :
raise KeyError("Field list must contain the following fields: " +
"\'particle_position_x\', \'particle_position_y\'" +
- ", \'particle_position_z\', \'particle_index\' ")
-
+ ", \'particle_position_z\' ")
+ self.index_index = self.field_list.index("particle_index")
+
self.num_grids = self.pf.h.num_grids
self.NumberOfParticles = np.zeros((self.num_grids), dtype='int64')
- self.ParticleIndices = np.zeros(self.num_grids + 1, dtype='int64')
+ self.ParticleGridIndices = np.zeros(self.num_grids + 1, dtype='int64')
self.num_fields = len(self.field_list)
@@ -78,8 +78,8 @@
Return a dict containing all of the particle fields in the specified grid.
"""
ind = grid.id-grid._id_offset
- start = self.ParticleIndices[ind]
- end = self.ParticleIndices[ind+1]
+ start = self.ParticleGridIndices[ind]
+ end = self.ParticleGridIndices[ind+1]
return dict([(field, self.particles[start:end,self.field_list.index(field)])
for field in self.field_list])
@@ -97,9 +97,9 @@
minlength=self.num_grids)
if self.num_grids > 1 :
np.add.accumulate(self.NumberOfParticles.squeeze(),
- out=self.ParticleIndices[1:])
+ out=self.ParticleGridIndices[1:])
else :
- self.ParticleIndices[1] = self.NumberOfParticles.squeeze()
+ self.ParticleGridIndices[1] = self.NumberOfParticles.squeeze()
if setup_fields is not None:
for key, value in setup_fields.items():
if key not in self.default_fields:
@@ -130,8 +130,8 @@
for i, grid in enumerate(self.pf.h.grids) :
pbar.update(i)
if self.NumberOfParticles[i] > 0:
- start = self.ParticleIndices[i]
- end = self.ParticleIndices[i+1]
+ start = self.ParticleGridIndices[i]
+ end = self.ParticleGridIndices[i+1]
# Note we add one ghost zone to the grid!
cube = grid.retrieve_ghost_zones(1, mapping_dict.keys())
le = np.array(grid.LeftEdge).astype(np.float64)
@@ -257,7 +257,7 @@
>>> le = np.array([0.25,0.25,0.25])
>>> re = np.array([0.75,0.75,0.75])
>>> fields = ["particle_position_x","particle_position_y",
- >>> "particle_position_z","particle_index",
+ >>> "particle_position_z",
>>> "particle_density","particle_temperature"]
>>> particles = LatticeParticleGenerator(pf, dims, le, re, fields)
"""
@@ -321,7 +321,7 @@
>>> sphere = pf.h.sphere(pf.domain_center, 0.5)
>>> num_p = 100000
>>> fields = ["particle_position_x","particle_position_y",
- >>> "particle_position_z","particle_index",
+ >>> "particle_position_z",
>>> "particle_density","particle_temperature"]
>>> particles = WithDensityParticleGenerator(pf, sphere, num_particles,
>>> fields, density_field='Dark_Matter_Density')
diff -r 329d11eeff224ed16d054e989680ba6f193318e9 -r 3161cb50ce626380cbf2958e0abacf61677072e3 yt/visualization/image_writer.py
--- a/yt/visualization/image_writer.py
+++ b/yt/visualization/image_writer.py
@@ -28,6 +28,7 @@
from yt.funcs import *
import _colormap_data as cmd
import yt.utilities.lib as au
+import __builtin__
def scale_image(image, mi=None, ma=None):
r"""Scale an image ([NxNxM] where M = 1-4) to be uint8 and values scaled
@@ -120,14 +121,16 @@
r"""Write out a bitmapped image directly to a PNG file.
This accepts a three- or four-channel `bitmap_array`. If the image is not
- already uint8, it will be scaled and converted. If it is not four channel, a
- fourth alpha channel will be added and set to fully opaque. The resultant
- image will be directly written to `filename` as a PNG with no colormap
- applied. `max_val` is a value used if the array is passed in as anything
- other than uint8; it will be the value used for scaling and clipping when the
- array is converted. Additionally, the minimum is assumed to be zero; this
- makes it primarily suited for the results of volume rendered images, rather
- than misaligned projections.
+ already uint8, it will be scaled and converted. If it is four channel,
+ only the first three channels will be scaled, while the fourth channel is
+ assumed to be in the range of [0,1]. If it is not four channel, a fourth
+ alpha channel will be added and set to fully opaque. The resultant image
+ will be directly written to `filename` as a PNG with no colormap applied.
+ `max_val` is a value used if the array is passed in as anything other than
+ uint8; it will be the value used for scaling and clipping in the first
+ three channels when the array is converted. Additionally, the minimum is
+ assumed to be zero; this makes it primarily suited for the results of
+ volume rendered images, rather than misaligned projections.
Parameters
----------
@@ -141,16 +144,19 @@
The upper limit to clip values to in the output, if converting to uint8.
If `bitmap_array` is already uint8, this will be ignore.
"""
- if bitmap_array.dtype != np.uint8:
- if max_val is None: max_val = bitmap_array.max()
- bitmap_array = np.clip(bitmap_array / max_val, 0.0, 1.0) * 255
- bitmap_array = bitmap_array.astype("uint8")
if len(bitmap_array.shape) != 3 or bitmap_array.shape[-1] not in (3,4):
raise RuntimeError
- if bitmap_array.shape[-1] == 3:
+ if bitmap_array.dtype != np.uint8:
s1, s2 = bitmap_array.shape[:2]
- alpha_channel = 255*np.ones((s1,s2,1), dtype='uint8')
- bitmap_array = np.concatenate([bitmap_array, alpha_channel], axis=-1)
+ if bitmap_array.shape[-1] == 3:
+ alpha_channel = 255*np.ones((s1,s2,1), dtype='uint8')
+ else:
+ alpha_channel = (255*bitmap_array[:,:,3]).astype('uint8')
+ alpha_channel.shape = s1, s2, 1
+ if max_val is None: max_val = bitmap_array[:,:,:3].max()
+ bitmap_array = np.clip(bitmap_array[:,:,:3] / max_val, 0.0, 1.0) * 255
+ bitmap_array = np.concatenate([bitmap_array.astype('uint8'),
+ alpha_channel], axis=-1)
if transpose:
bitmap_array = bitmap_array.swapaxes(0,1)
if filename is not None:
@@ -433,7 +439,6 @@
def write_fits(image, filename_prefix, clobber=True, coords=None, gzip_file=False) :
-
"""
This will export a FITS image of a floating point array. The output filename is
*filename_prefix*. If clobber is set to True, this will overwrite any existing
@@ -497,4 +502,32 @@
clob = ""
if (clobber) : clob="-f"
system("gzip "+clob+" %s.fits" % (filename_prefix))
+
+def display_in_notebook(image, max_val=None):
+ """
+ A helper function to display images in an IPython notebook
+ Must be run from within an IPython notebook, or else it will raise
+ a YTNotInsideNotebook exception.
+
+ Parameters
+ ----------
+ image : array_like
+ This is an (unscaled) array of floating point values, shape (N,N,3) or
+ (N,N,4) to display in the notebook. The first three channels will be
+ scaled automatically.
+ max_val : float, optional
+ The upper limit to clip values of the image. Only applies to the first
+ three channels.
+ """
+
+ if "__IPYTHON__" in dir(__builtin__):
+ from IPython.core.displaypub import publish_display_data
+ data = write_bitmap(image, None, max_val=max_val)
+ publish_display_data(
+ 'yt.visualization.image_writer.display_in_notebook',
+ {'image/png' : data}
+ )
+ else:
+ raise YTNotInsideNotebook
+
diff -r 329d11eeff224ed16d054e989680ba6f193318e9 -r 3161cb50ce626380cbf2958e0abacf61677072e3 yt/visualization/plot_collection.py
--- a/yt/visualization/plot_collection.py
+++ b/yt/visualization/plot_collection.py
@@ -74,9 +74,7 @@
self.images.append((os.path.basename(fn), np.fromfile(fn, dtype='c')))
class PlotCollection(object):
- r"""The primary interface for creating plots.
-
- The PlotCollection object was created to ease the creation of multiple
+ r"""The PlotCollection object was created to ease the creation of multiple
slices, projections and so forth made from a single parameter file.
The concept is that when the width on one image changes, it should
change on all the others. The PlotCollection can create all plot types
diff -r 329d11eeff224ed16d054e989680ba6f193318e9 -r 3161cb50ce626380cbf2958e0abacf61677072e3 yt/visualization/volume_rendering/blenders.py
--- a/yt/visualization/volume_rendering/blenders.py
+++ b/yt/visualization/volume_rendering/blenders.py
@@ -11,3 +11,18 @@
del nz
np.clip(im, 0.0, 1.0, im)
+def enhance_rgba(im, stdval=6.0):
+ nzc = im[:,:,:3][im[:,:,:3]>0.0]
+ cmax = nzc.mean()+stdval*nzc.std()
+
+
+ nza = im[:,:,3][im[:,:,3]>0.0]
+ if len(nza) == 0:
+ im[:,:,3]=1.0
+ amax = 1.0
+ else:
+ amax = nza.mean()+stdval*nza.std()
+
+ im.rescale(amax=amax, cmax=cmax, inline=True)
+ np.clip(im, 0.0, 1.0, im)
+
diff -r 329d11eeff224ed16d054e989680ba6f193318e9 -r 3161cb50ce626380cbf2958e0abacf61677072e3 yt/visualization/volume_rendering/camera.py
--- a/yt/visualization/volume_rendering/camera.py
+++ b/yt/visualization/volume_rendering/camera.py
@@ -49,7 +49,7 @@
from yt.utilities.parallel_tools.parallel_analysis_interface import \
ParallelAnalysisInterface, ProcessorPool, parallel_objects
from yt.utilities.amr_kdtree.api import AMRKDTree
-from .blenders import enhance
+from .blenders import enhance_rgba
from numpy import pi
def get_corners(le, re):
@@ -267,7 +267,8 @@
px = (res[1]*(dy/self.width[1])).astype('int')
return px, py, dz
- def draw_grids(self, im, alpha=0.3, cmap='algae'):
+ def draw_grids(self, im, alpha=0.3, cmap='algae', min_level=None,
+ max_level=None):
r"""Draws Grids on an existing volume rendering.
By mapping grid level to a color, drawes edges of grids on
@@ -284,6 +285,9 @@
Default : 0.3
cmap : string, optional
Colormap to be used mapping grid levels to colors.
+ min_level, max_level : int, optional
+ Optional parameters to specify the min and max level grid boxes
+ to overplot on the image.
Returns
-------
@@ -298,6 +302,16 @@
"""
corners = self.pf.h.grid_corners
levels = self.pf.h.grid_levels[:,0]
+
+ if max_level is not None:
+ subset = levels <= max_level
+ levels = levels[subset]
+ corners = corners[:,:,subset]
+ if min_level is not None:
+ subset = levels >= min_level
+ levels = levels[subset]
+ corners = corners[:,:,subset]
+
colors = apply_colormap(levels*1.0,
color_bounds=[0,self.pf.h.max_level],
cmap_name=cmap)[0,:,:]*1.0/255.
@@ -315,11 +329,12 @@
px, py, dz = self.project_to_plane(vertices, res=im.shape[:2])
# Must normalize the image
- ma = im.max()
- if ma > 0.0:
- enhance(im)
+ nim = im.rescale(inline=False)
+ enhance_rgba(nim)
+ nim.add_background_color('black', inline=True)
- lines(im, px, py, colors, 24)
+ lines(nim, px, py, colors, 24)
+ return nim
def draw_line(self, im, x0, x1, color=None):
r"""Draws a line on an existing volume rendering.
@@ -388,12 +403,14 @@
>>> write_bitmap(im, 'render_with_domain_boundary.png')
"""
-
- ma = im.max()
- if ma > 0.0:
- enhance(im)
- self.draw_box(im, self.pf.domain_left_edge, self.pf.domain_right_edge,
+ # Must normalize the image
+ nim = im.rescale(inline=False)
+ enhance_rgba(nim)
+ nim.add_background_color('black', inline=True)
+
+ self.draw_box(nim, self.pf.domain_left_edge, self.pf.domain_right_edge,
color=np.array([1.0,1.0,1.0,alpha]))
+ return nim
def draw_box(self, im, le, re, color=None):
r"""Draws a box on an existing volume rendering.
@@ -529,6 +546,8 @@
def finalize_image(self, image):
view_pos = self.front_center + self.orienter.unit_vectors[2] * 1.0e6 * self.width[2]
image = self.volume.reduce_tree_images(image, view_pos)
+ if self.transfer_function.grey_opacity is False:
+ image[:,:,3]=1.0
return image
def _render(self, double_check, num_threads, image, sampler):
@@ -598,12 +617,14 @@
self.annotate(ax.axes, enhance)
self._pylab.savefig(fn, bbox_inches='tight', facecolor='black', dpi=dpi)
- def save_image(self, fn, clip_ratio, image, transparent=False):
- if self.comm.rank is 0 and fn is not None:
+ def save_image(self, image, fn=None, clip_ratio=None, transparent=False):
+ if self.comm.rank == 0 and fn is not None:
if transparent:
- image.write_png(fn, clip_ratio=clip_ratio)
+ image.write_png(fn, clip_ratio=clip_ratio, rescale=True,
+ background=None)
else:
- image[:,:,:3].write_png(fn, clip_ratio=clip_ratio)
+ image.write_png(fn, clip_ratio=clip_ratio, rescale=True,
+ background='black')
def initialize_source(self):
return self.volume.initialize_source()
@@ -619,7 +640,7 @@
return info_dict
def snapshot(self, fn = None, clip_ratio = None, double_check = False,
- num_threads = 0):
+ num_threads = 0, transparent=False):
r"""Ray-cast the camera.
This method instructs the camera to take a snapshot -- i.e., call the ray
@@ -640,6 +661,9 @@
If supplied, will use 'num_threads' number of OpenMP threads during
the rendering. Defaults to 0, which uses the environment variable
OMP_NUM_THREADS.
+ transparent: bool, optional
+ Optionally saves out the 4-channel rgba image, which can appear
+ empty if the alpha channel is low everywhere. Default: False
Returns
-------
@@ -655,7 +679,8 @@
image = ImageArray(self._render(double_check, num_threads,
image, sampler),
info=self.get_information())
- self.save_image(fn, clip_ratio, image)
+ self.save_image(image, fn=fn, clip_ratio=clip_ratio,
+ transparent=transparent)
return image
def show(self, clip_ratio = None):
@@ -1191,11 +1216,11 @@
image = ImageArray(self._render(double_check, num_threads,
image, sampler),
info=self.get_information())
- self.save_image(fn, clim, image, label = label)
+ self.save_image(image, fn=fn, clim=clim, label = label)
return image
- def save_image(self, fn, clim, image, label = None):
- if self.comm.rank is 0 and fn is not None:
+ def save_image(self, image, fn=None, clim=None, label = None):
+ if self.comm.rank == 0 and fn is not None:
# This assumes Density; this is a relatively safe assumption.
import matplotlib.figure
import matplotlib.backends.backend_agg
@@ -1509,7 +1534,7 @@
sto.id = self.imj*self.nimx + self.imi
sto.result = image
image = self.reduce_images(my_storage)
- self.save_image(fn, clip_ratio, image)
+ self.save_image(image, fn=fn, clip_ratio=clip_ratio)
return image
def reduce_images(self,im_dict):
@@ -2165,12 +2190,12 @@
image = self.finalize_image(sampler.aimage)
return image
- def save_image(self, fn, clip_ratio, image):
+ def save_image(self, image, fn=None, clip_ratio=None):
if self.pf.field_info[self.field].take_log:
im = np.log10(image)
else:
im = image
- if self.comm.rank is 0 and fn is not None:
+ if self.comm.rank == 0 and fn is not None:
if clip_ratio is not None:
write_image(im, fn)
else:
@@ -2197,7 +2222,7 @@
image, sampler),
info=self.get_information())
- self.save_image(fn, clip_ratio, image)
+ self.save_image(image, fn=fn, clip_ratio=clip_ratio)
return image
snapshot.__doc__ = Camera.snapshot.__doc__
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