[yt-svn] commit/yt: 4 new changesets
Bitbucket
commits-noreply at bitbucket.org
Fri Dec 16 13:09:39 PST 2011
4 new commits in yt:
https://bitbucket.org/yt_analysis/yt/changeset/22ce5d86a60b/
changeset: 22ce5d86a60b
branch: yt
user: brittonsmith
date: 2011-12-15 16:48:56
summary: Moved functionality to get a sphere for halo profiling to a separate
function to make way for a generalized halo analysis function.
affected #: 2 files
diff -r 40ea2908895ff6b9dd0dbbddd6e8da0346273886 -r 22ce5d86a60b71f9afb9f492a43b60f3463b7bb7 yt/analysis_modules/halo_profiler/api.py
--- a/yt/analysis_modules/halo_profiler/api.py
+++ b/yt/analysis_modules/halo_profiler/api.py
@@ -34,5 +34,5 @@
from .multi_halo_profiler import \
HaloProfiler, \
FakeProfile, \
- shift_projections, \
+ get_halo_sphere, \
standard_fields
diff -r 40ea2908895ff6b9dd0dbbddd6e8da0346273886 -r 22ce5d86a60b71f9afb9f492a43b60f3463b7bb7 yt/analysis_modules/halo_profiler/multi_halo_profiler.py
--- a/yt/analysis_modules/halo_profiler/multi_halo_profiler.py
+++ b/yt/analysis_modules/halo_profiler/multi_halo_profiler.py
@@ -510,7 +510,7 @@
def _get_halo_profile(self, halo, filename, virial_filter=True,
force_write=False):
- """Profile a single halo and write profile data to a file.
+ r"""Profile a single halo and write profile data to a file.
If file already exists, read profile data from file.
Return a dictionary of id, center, and virial quantities if virial_filter is True.
"""
@@ -528,39 +528,8 @@
mylog.error("Skipping halo with r_max / r_min = %f." % (halo['r_max']/r_min))
return None
- sphere = self.pf.h.sphere(halo['center'], halo['r_max']/self.pf.units['mpc'])
- if len(sphere._grids) == 0: return None
- new_sphere = False
-
- if self.recenter:
- old = halo['center']
- if self.recenter in centering_registry:
- new_x, new_y, new_z = \
- centering_registry[self.recenter](sphere)
- else:
- # user supplied function
- new_x, new_y, new_z = self.recenter(sphere)
- if new_x < self.pf.domain_left_edge[0] or \
- new_y < self.pf.domain_left_edge[1] or \
- new_z < self.pf.domain_left_edge[2]:
- mylog.info("Recentering rejected, skipping halo %d" % \
- halo['id'])
- return None
- halo['center'] = [new_x, new_y, new_z]
- d = self.pf['kpc'] * periodic_dist(old, halo['center'],
- self.pf.domain_right_edge - self.pf.domain_left_edge)
- mylog.info("Recentered halo %d %1.3e kpc away." % (halo['id'], d))
- # Expand the halo to account for recentering.
- halo['r_max'] += d / 1000 # d is in kpc -> want mpc
- new_sphere = True
-
- if new_sphere:
- # Temporary solution to memory leak.
- for g in self.pf.h.grids:
- g.clear_data()
- sphere.clear_data()
- del sphere
- sphere = self.pf.h.sphere(halo['center'], halo['r_max']/self.pf.units['mpc'])
+ # get a sphere object to profile
+ sphere = get_halo_sphere(halo, self.pf, recenter=self.recenter)
if self._need_bulk_velocity:
# Set bulk velocity to zero out radial velocity profiles.
@@ -733,7 +702,7 @@
# Set x and y limits, shift image if it overlaps domain boundary.
if need_per:
pw = self.projection_width/self.pf.units[self.projection_width_units]
- shift_projections(self.pf, projections, halo['center'], center, w)
+ _shift_projections(self.pf, projections, halo['center'], center, w)
# Projection has now been shifted to center of box.
proj_left = [center[x_axis]-0.5*pw, center[y_axis]-0.5*pw]
proj_right = [center[x_axis]+0.5*pw, center[y_axis]+0.5*pw]
@@ -1002,7 +971,94 @@
else:
os.mkdir(my_output_dir)
-def shift_projections(pf, projections, oldCenter, newCenter, axis):
+def get_halo_sphere(halo, pf, recenter=None):
+ r"""Returns a sphere object for a given halo.
+
+ With a dictionary containing halo properties, such as center
+ and r_max, this creates a sphere object and optionally
+ recenters and recreates the sphere using a recentering function.
+ This is to be used primarily to make spheres for a set of halos
+ loaded by the HaloProfiler.
+
+ Parameters
+ ----------
+ halo : dict, required
+ The dictionary containing halo properties used to make the sphere.
+ Required entries:
+ center : list with center coordinates.
+ r_max : sphere radius in Mpc.
+ pf : parameter file object, required
+ The parameter file from which the sphere will be made.
+ recenter : {None, string or function}
+ The exact location of the sphere center can significantly affect
+ radial profiles. The halo center loaded by the HaloProfiler will
+ typically be the dark matter center of mass calculated by a halo
+ finder. However, this may not be the best location for centering
+ profiles of baryon quantities. For example, one may want to center
+ on the maximum density.
+ If recenter is given as a string, one of the existing recentering
+ functions will be used:
+ Min_Dark_Matter_Density : location of minimum dark matter density
+ Max_Dark_Matter_Density : location of maximum dark matter density
+ CoM_Dark_Matter_Density : dark matter center of mass
+ Min_Gas_Density : location of minimum gas density
+ Max_Gas_Density : location of maximum gas density
+ CoM_Gas_Density : gas center of mass
+ Min_Total_Density : location of minimum total density
+ Max_Total_Density : location of maximum total density
+ CoM_Total_Density : total center of mass
+ Min_Temperature : location of minimum temperature
+ Max_Temperature : location of maximum temperature
+ Alternately, a function can be supplied for custom recentering.
+ The function should take only one argument, a sphere object.
+ Example function:
+ def my_center_of_mass(data):
+ my_x, my_y, my_z = data.quantities['CenterOfMass']()
+ return (my_x, my_y, my_z)
+
+ Examples: this should primarily be used with the halo list of the HaloProfiler.
+ This is an example with an abstract halo asssuming a pre-defined pf.
+ >>> halo = {'center': [0.5, 0.5, 0.5], 'r_max': 1.0}
+ >>> my_sphere = get_halo_sphere(halo, pf, recenter='Max_Gas_Density')
+ >>> # Assuming the above example function has been defined.
+ >>> my_sphere = get_halo_sphere(halo, pf, recenter=my_center_of_mass)
+ """
+
+ sphere = pf.h.sphere(halo['center'], halo['r_max']/pf.units['mpc'])
+ if len(sphere._grids) == 0: return None
+ new_sphere = False
+
+ if recenter:
+ old = halo['center']
+ if recenter in centering_registry:
+ new_x, new_y, new_z = \
+ centering_registry[recenter](sphere)
+ else:
+ # user supplied function
+ new_x, new_y, new_z = recenter(sphere)
+ if new_x < pf.domain_left_edge[0] or \
+ new_y < pf.domain_left_edge[1] or \
+ new_z < pf.domain_left_edge[2]:
+ mylog.info("Recentering rejected, skipping halo %d" % \
+ halo['id'])
+ return None
+ halo['center'] = [new_x, new_y, new_z]
+ d = pf['kpc'] * periodic_dist(old, halo['center'],
+ pf.domain_right_edge - pf.domain_left_edge)
+ mylog.info("Recentered halo %d %1.3e kpc away." % (halo['id'], d))
+ # Expand the halo to account for recentering.
+ halo['r_max'] += d / 1000 # d is in kpc -> want mpc
+ new_sphere = True
+
+ if new_sphere:
+ # Temporary solution to memory leak.
+ for g in pf.h.grids:
+ g.clear_data()
+ sphere.clear_data()
+ del sphere
+ sphere = pf.h.sphere(halo['center'], halo['r_max']/pf.units['mpc'])
+
+def _shift_projections(pf, projections, oldCenter, newCenter, axis):
"""
Shift projection data around.
This is necessary when projecting a preiodic region.
https://bitbucket.org/yt_analysis/yt/changeset/97f7357fd0ce/
changeset: 97f7357fd0ce
branch: yt
user: brittonsmith
date: 2011-12-15 18:00:30
summary: Added analyze_halo_sphere method to HaloProfiler to perform custom
analysis on every halo on a halo list.
affected #: 1 file
diff -r 22ce5d86a60b71f9afb9f492a43b60f3463b7bb7 -r 97f7357fd0ce361c39414aa20b350a96487ac20d yt/analysis_modules/halo_profiler/multi_halo_profiler.py
--- a/yt/analysis_modules/halo_profiler/multi_halo_profiler.py
+++ b/yt/analysis_modules/halo_profiler/multi_halo_profiler.py
@@ -66,7 +66,7 @@
recenter = None,
profile_output_dir='radial_profiles', projection_output_dir='projections',
projection_width=8.0, projection_width_units='mpc', project_at_level='max',
- velocity_center=['bulk', 'halo'], filter_quantities=['id','center'],
+ velocity_center=['bulk', 'halo'], filter_quantities=['id', 'center', 'r_max'],
use_critical_density=False):
r"""Initialize a Halo Profiler object.
@@ -530,6 +530,7 @@
# get a sphere object to profile
sphere = get_halo_sphere(halo, self.pf, recenter=self.recenter)
+ if sphere is None: return None
if self._need_bulk_velocity:
# Set bulk velocity to zero out radial velocity profiles.
@@ -742,6 +743,76 @@
del region
+ @parallel_blocking_call
+ def analyze_halo_spheres(self, analysis_function, halo_list='filtered',
+ analysis_output_dir=None):
+ r"""Perform custom analysis on all halos.
+
+ This will loop through all halo on the HaloProfiler's list,
+ creating a sphere object for each halo and passing that sphere
+ to the provided analysis function.
+
+ Parameters
+ ---------
+ analysis_function : function
+ A function taking two arguments, the halo dictionary, and a
+ sphere object.
+ Example function to calculate total mass of halo:
+ def my_analysis(halo, sphere):
+ total_mass = sphere.quantities['TotalMass']()
+ print total_mass
+ halo_list : {'filtered', 'all'}
+ Which set of halos to make profiles of, either ones passed by the
+ halo filters (if enabled/added), or all halos.
+ Default='filtered'.
+ analysis_output_dir : string, optional
+ If specified, this directory will be created within the dataset to
+ contain any output from the analysis function. Default: None.
+
+ Examples
+ --------
+ >>> hp.analyze_halo_spheres(my_analysis, halo_list="filtered",
+ analysis_output_dir='special_analysis')
+
+ """
+
+ # Get list of halos for projecting.
+ if halo_list == 'filtered':
+ self._halo_analysis_list = self.filtered_halos
+ elif halo_list == 'all':
+ self._halo_analysis_list = self.all_halos
+ elif isinstance(halo_list, types.StringType):
+ self._halo_analysis_list = self._read_halo_list(halo_list)
+ elif isinstance(halo_list, types.ListType):
+ self._halo_analysis_list = halo_list
+ else:
+ mylog.error("Keyword, halo_list', must be 'filtered', 'all', a filename, or an actual list.")
+ return
+
+ if len(self._halo_analysis_list) == 0:
+ mylog.error("Halo list for analysis is empty.")
+ return
+
+ # Create output directory.
+ if analysis_output_dir is not None:
+ if self.output_dir is not None:
+ self.__check_directory("%s/%s" % (self.output_dir, self.pf.directory))
+ my_output_dir = "%s/%s/%s" % (self.output_dir, self.pf.directory,
+ analysis_output_dir)
+ else:
+ my_output_dir = "%s/%s" % (self.pf.fullpath, analysis_output_dir)
+ self.__check_directory(my_output_dir)
+
+ for halo in self._get_objs('_halo_analysis_list', round_robin=True):
+ if halo is None: continue
+
+ # Get a sphere object to analze.
+ sphere = get_halo_sphere(halo, self.pf, recenter=self.recenter)
+ if sphere is None: continue
+
+ # Call the given analysis function.
+ analysis_function(halo, sphere)
+
def _add_actual_overdensity(self, profile):
"Calculate overdensity from TotalMassMsun and CellVolume fields."
@@ -1057,6 +1128,7 @@
sphere.clear_data()
del sphere
sphere = pf.h.sphere(halo['center'], halo['r_max']/pf.units['mpc'])
+ return sphere
def _shift_projections(pf, projections, oldCenter, newCenter, axis):
"""
https://bitbucket.org/yt_analysis/yt/changeset/bd9ef841c0aa/
changeset: bd9ef841c0aa
branch: yt
user: brittonsmith
date: 2011-12-15 22:30:30
summary: Merged.
affected #: 43 files
diff -r 97f7357fd0ce361c39414aa20b350a96487ac20d -r bd9ef841c0aacf5feb6479ce3d19153c8d821876 setup.py
--- a/setup.py
+++ b/setup.py
@@ -76,7 +76,7 @@
import setuptools
-VERSION = "2.3dev"
+VERSION = "2.4dev"
if os.path.exists('MANIFEST'): os.remove('MANIFEST')
diff -r 97f7357fd0ce361c39414aa20b350a96487ac20d -r bd9ef841c0aacf5feb6479ce3d19153c8d821876 yt/analysis_modules/halo_merger_tree/merger_tree.py
--- a/yt/analysis_modules/halo_merger_tree/merger_tree.py
+++ b/yt/analysis_modules/halo_merger_tree/merger_tree.py
@@ -86,6 +86,9 @@
"ChildHaloID3", "ChildHaloFrac3",
"ChildHaloID4", "ChildHaloFrac4"]
+NumNeighbors = 15
+NumDB = 5
+
class DatabaseFunctions(object):
# Common database functions so it doesn't have to be repeated.
def _open_database(self):
@@ -366,9 +369,9 @@
child_points = na.array(child_points)
fKD.pos = na.asfortranarray(child_points.T)
fKD.qv = na.empty(3, dtype='float64')
- fKD.dist = na.empty(5, dtype='float64')
- fKD.tags = na.empty(5, dtype='int64')
- fKD.nn = 5
+ fKD.dist = na.empty(NumNeighbors, dtype='float64')
+ fKD.tags = na.empty(NumNeighbors, dtype='int64')
+ fKD.nn = NumNeighbors
fKD.sort = True
fKD.rearrange = True
create_tree(0)
@@ -395,7 +398,7 @@
nIDs.append(n)
# We need to fill in fake halos if there aren't enough halos,
# which can happen at high redshifts.
- while len(nIDs) < 5:
+ while len(nIDs) < NumNeighbors:
nIDs.append(-1)
candidates[row[0]] = nIDs
@@ -405,12 +408,12 @@
self.candidates = candidates
# This stores the masses contributed to each child candidate.
- self.child_mass_arr = na.zeros(len(candidates)*5, dtype='float64')
+ self.child_mass_arr = na.zeros(len(candidates)*NumNeighbors, dtype='float64')
# Records where to put the entries in the above array.
self.child_mass_loc = defaultdict(dict)
for i,halo in enumerate(sorted(candidates)):
for j, child in enumerate(candidates[halo]):
- self.child_mass_loc[halo][child] = i*5 + j
+ self.child_mass_loc[halo][child] = i*NumNeighbors + j
def _build_h5_refs(self, filename):
# For this snapshot, add lists of file names that contain the
@@ -618,8 +621,8 @@
result = self.cursor.fetchone()
while result:
mass = result[0]
- self.child_mass_arr[mark:mark+5] /= mass
- mark += 5
+ self.child_mass_arr[mark:mark+NumNeighbors] /= mass
+ mark += NumNeighbors
result = self.cursor.fetchone()
# Get the global ID for the SnapHaloID=0 from the child, this will
@@ -642,14 +645,15 @@
# We need to get the GlobalHaloID for this child.
child_globalID = baseChildID + child
child_indexes.append(child_globalID)
- child_per.append(self.child_mass_arr[i*5 + j])
+ child_per.append(self.child_mass_arr[i*NumNeighbors + j])
# Sort by percentages, desending.
child_per, child_indexes = zip(*sorted(zip(child_per, child_indexes), reverse=True))
values = []
- for pair in zip(child_indexes, child_per):
+ for pair_count, pair in enumerate(zip(child_indexes, child_per)):
+ if pair_count == NumDB: break
values.extend([int(pair[0]), float(pair[1])])
#values.extend([parent_currt, parent_halo])
- # This has the child ID, child percent listed five times, followed
+ # This has the child ID, child percent listed NumDB times, followed
# by the currt and this parent halo ID (SnapHaloID).
#values = tuple(values)
self.write_values.append(values)
@@ -841,7 +845,7 @@
[1609, 0.0]]
"""
parents = []
- for i in range(5):
+ for i in range(NumDB):
string = "SELECT GlobalHaloID, ChildHaloFrac%d FROM Halos\
WHERE ChildHaloID%d=%d;" % (i, i, GlobalHaloID)
self.cursor.execute(string)
diff -r 97f7357fd0ce361c39414aa20b350a96487ac20d -r bd9ef841c0aacf5feb6479ce3d19153c8d821876 yt/analysis_modules/star_analysis/sfr_spectrum.py
--- a/yt/analysis_modules/star_analysis/sfr_spectrum.py
+++ b/yt/analysis_modules/star_analysis/sfr_spectrum.py
@@ -96,6 +96,8 @@
self._pf.current_redshift) # seconds
# Build the distribution.
self.build_dist()
+ # Attach some convenience arrays.
+ self.attach_arrays()
def build_dist(self):
"""
@@ -127,6 +129,47 @@
# We will want the time taken between bins.
self.time_bins_dt = self.time_bins[1:] - self.time_bins[:-1]
+ def attach_arrays(self):
+ """
+ Attach convenience arrays to the class for easy access.
+ """
+ if self.mode == 'data_source':
+ try:
+ vol = self._data_source.volume('mpc')
+ except AttributeError:
+ # If we're here, this is probably a HOPHalo object, and we
+ # can get the volume this way.
+ ds = self._data_source.get_sphere()
+ vol = ds.volume('mpc')
+ elif self.mode == 'provided':
+ vol = self.volume
+ tc = self._pf["Time"]
+ self.time = []
+ self.lookback_time = []
+ self.redshift = []
+ self.Msol_yr = []
+ self.Msol_yr_vol = []
+ self.Msol = []
+ self.Msol_cumulative = []
+ # Use the center of the time_bin, not the left edge.
+ for i, time in enumerate((self.time_bins[1:] + self.time_bins[:-1])/2.):
+ self.time.append(time * tc / YEAR)
+ self.lookback_time.append((self.time_now - time * tc)/YEAR)
+ self.redshift.append(self.cosm.ComputeRedshiftFromTime(time * tc))
+ self.Msol_yr.append(self.mass_bins[i] / \
+ (self.time_bins_dt[i] * tc / YEAR))
+ self.Msol_yr_vol.append(self.mass_bins[i] / \
+ (self.time_bins_dt[i] * tc / YEAR) / vol)
+ self.Msol.append(self.mass_bins[i])
+ self.Msol_cumulative.append(self.cum_mass_bins[i])
+ self.time = na.array(self.time)
+ self.lookback_time = na.array(self.lookback_time)
+ self.redshift = na.array(self.redshift)
+ self.Msol_yr = na.array(self.Msol_yr)
+ self.Msol_yr_vol = na.array(self.Msol_yr_vol)
+ self.Msol = na.array(self.Msol)
+ self.Msol_cumulative = na.array(self.Msol_cumulative)
+
def write_out(self, name="StarFormationRate.out"):
r"""Write out the star analysis to a text file *name*. The columns are in
order.
@@ -150,31 +193,21 @@
>>> sfr.write_out("stars-SFR.out")
"""
fp = open(name, "w")
- if self.mode == 'data_source':
- try:
- vol = self._data_source.volume('mpc')
- except AttributeError:
- # If we're here, this is probably a HOPHalo object, and we
- # can get the volume this way.
- ds = self._data_source.get_sphere()
- vol = ds.volume('mpc')
- elif self.mode == 'provided':
- vol = self.volume
- tc = self._pf["Time"]
- # Use the center of the time_bin, not the left edge.
fp.write("#time\tlookback\tredshift\tMsol/yr\tMsol/yr/Mpc3\tMsol\tcumMsol\t\n")
- for i, time in enumerate((self.time_bins[1:] + self.time_bins[:-1])/2.):
+ for i, time in enumerate(self.time):
line = "%1.5e %1.5e %1.5e %1.5e %1.5e %1.5e %1.5e\n" % \
- (time * tc / YEAR, # Time
- (self.time_now - time * tc)/YEAR, # Lookback time
- self.cosm.ComputeRedshiftFromTime(time * tc), # Redshift
- self.mass_bins[i] / (self.time_bins_dt[i] * tc / YEAR), # Msol/yr
- self.mass_bins[i] / (self.time_bins_dt[i] * tc / YEAR) / vol, # Msol/yr/vol
- self.mass_bins[i], # Msol in bin
- self.cum_mass_bins[i]) # cumulative
+ (time, # Time
+ self.lookback_time[i], # Lookback time
+ self.redshift[i], # Redshift
+ self.Msol_yr[i], # Msol/yr
+ self.Msol_yr_vol[i], # Msol/yr/vol
+ self.Msol[i], # Msol in bin
+ self.Msol_cumulative[i]) # cumulative
fp.write(line)
fp.close()
+### Begin Synthetic Spectrum Stuff. ####
+
CHABRIER = {
"Z0001" : "bc2003_hr_m22_chab_ssp.ised.h5", #/* 0.5% */
"Z0004" : "bc2003_hr_m32_chab_ssp.ised.h5", #/* 2% */
diff -r 97f7357fd0ce361c39414aa20b350a96487ac20d -r bd9ef841c0aacf5feb6479ce3d19153c8d821876 yt/data_objects/data_containers.py
--- a/yt/data_objects/data_containers.py
+++ b/yt/data_objects/data_containers.py
@@ -88,6 +88,20 @@
return tr
return save_state
+def restore_field_information_state(func):
+ """
+ A decorator that takes a function with the API of (self, grid, field)
+ and ensures that after the function is called, the field_parameters will
+ be returned to normal.
+ """
+ def save_state(self, grid, field=None, *args, **kwargs):
+ old_params = grid.field_parameters
+ grid.field_parameters = self.field_parameters
+ tr = func(self, grid, field, *args, **kwargs)
+ grid.field_parameters = old_params
+ return tr
+ return save_state
+
def cache_mask(func):
"""
For computationally intensive indexing operations, we can cache
@@ -833,6 +847,38 @@
self[field] = temp_data[field]
def to_frb(self, width, resolution, center = None):
+ r"""This function returns a FixedResolutionBuffer generated from this
+ object.
+
+ A FixedResolutionBuffer is an object that accepts a variable-resolution
+ 2D object and transforms it into an NxM bitmap that can be plotted,
+ examined or processed. This is a convenience function to return an FRB
+ directly from an existing 2D data object.
+
+ Parameters
+ ----------
+ width : width specifier
+ This can either be a floating point value, in the native domain
+ units of the simulation, or a tuple of the (value, unit) style.
+ This will be the width of the FRB.
+ resolution : int or tuple of ints
+ The number of pixels on a side of the final FRB.
+ center : array-like of floats, optional
+ The center of the FRB. If not specified, defaults to the center of
+ the current object.
+
+ Returns
+ -------
+ frb : :class:`~yt.visualization.fixed_resolution.FixedResolutionBuffer`
+ A fixed resolution buffer, which can be queried for fields.
+
+ Examples
+ --------
+
+ >>> proj = pf.h.proj(0, "Density")
+ >>> frb = proj.to_frb( (100.0, 'kpc'), 1024)
+ >>> write_image(na.log10(frb["Density"]), 'density_100kpc.png')
+ """
if center is None:
center = self.get_field_parameter("center")
if center is None:
@@ -1258,6 +1304,52 @@
return "%s/c%s_L%s" % \
(self._top_node, cen_name, L_name)
+ def to_frb(self, width, resolution):
+ r"""This function returns an ObliqueFixedResolutionBuffer generated
+ from this object.
+
+ An ObliqueFixedResolutionBuffer is an object that accepts a
+ variable-resolution 2D object and transforms it into an NxM bitmap that
+ can be plotted, examined or processed. This is a convenience function
+ to return an FRB directly from an existing 2D data object. Unlike the
+ corresponding to_frb function for other AMR2DData objects, this does
+ not accept a 'center' parameter as it is assumed to be centered at the
+ center of the cutting plane.
+
+ Parameters
+ ----------
+ width : width specifier
+ This can either be a floating point value, in the native domain
+ units of the simulation, or a tuple of the (value, unit) style.
+ This will be the width of the FRB.
+ resolution : int or tuple of ints
+ The number of pixels on a side of the final FRB.
+
+ Returns
+ -------
+ frb : :class:`~yt.visualization.fixed_resolution.ObliqueFixedResolutionBuffer`
+ A fixed resolution buffer, which can be queried for fields.
+
+ Examples
+ --------
+
+ >>> v, c = pf.h.find_max("Density")
+ >>> sp = pf.h.sphere(c, (100.0, 'au'))
+ >>> L = sp.quantities["AngularMomentumVector"]()
+ >>> cutting = pf.h.cutting(L, c)
+ >>> frb = cutting.to_frb( (1.0, 'pc'), 1024)
+ >>> write_image(na.log10(frb["Density"]), 'density_1pc.png')
+ """
+ if iterable(width):
+ w, u = width
+ width = w/self.pf[u]
+ if not iterable(resolution):
+ resolution = (resolution, resolution)
+ from yt.visualization.fixed_resolution import ObliqueFixedResolutionBuffer
+ bounds = (-width/2.0, width/2.0, -width/2.0, width/2.0)
+ frb = ObliqueFixedResolutionBuffer(self, bounds, resolution)
+ return frb
+
class AMRFixedResCuttingPlaneBase(AMR2DData):
"""
AMRFixedResCuttingPlaneBase is an oblique plane through the data,
@@ -3467,7 +3559,7 @@
output_field, output_left)
self.field_data[field] = output_field
- @restore_grid_state
+ @restore_field_information_state
def _get_data_from_grid(self, grid, fields):
fields = ensure_list(fields)
g_fields = [grid[field].astype("float64") for field in fields]
diff -r 97f7357fd0ce361c39414aa20b350a96487ac20d -r bd9ef841c0aacf5feb6479ce3d19153c8d821876 yt/frontends/flash/data_structures.py
--- a/yt/frontends/flash/data_structures.py
+++ b/yt/frontends/flash/data_structures.py
@@ -316,6 +316,13 @@
self.current_time = \
float(self._find_parameter("real", "time", scalar=True))
+ if self._flash_version == 7:
+ self.parameters['timestep'] = float(
+ self._handle["simulation parameters"]["timestep"])
+ else:
+ self.parameters['timestep'] = \
+ float(self._find_parameter("real", "dt", scalar=True))
+
try:
use_cosmo = self._find_parameter("logical", "usecosmology")
except:
diff -r 97f7357fd0ce361c39414aa20b350a96487ac20d -r bd9ef841c0aacf5feb6479ce3d19153c8d821876 yt/gui/reason/html/images/3d.png
Binary file yt/gui/reason/html/images/3d.png has changed
diff -r 97f7357fd0ce361c39414aa20b350a96487ac20d -r bd9ef841c0aacf5feb6479ce3d19153c8d821876 yt/gui/reason/html/images/3d_tab.png
Binary file yt/gui/reason/html/images/3d_tab.png has changed
diff -r 97f7357fd0ce361c39414aa20b350a96487ac20d -r bd9ef841c0aacf5feb6479ce3d19153c8d821876 yt/gui/reason/html/images/binary.png
Binary file yt/gui/reason/html/images/binary.png has changed
diff -r 97f7357fd0ce361c39414aa20b350a96487ac20d -r bd9ef841c0aacf5feb6479ce3d19153c8d821876 yt/gui/reason/html/images/blockdevice.png
Binary file yt/gui/reason/html/images/blockdevice.png has changed
diff -r 97f7357fd0ce361c39414aa20b350a96487ac20d -r bd9ef841c0aacf5feb6479ce3d19153c8d821876 yt/gui/reason/html/images/blockdevice_tab.png
Binary file yt/gui/reason/html/images/blockdevice_tab.png has changed
diff -r 97f7357fd0ce361c39414aa20b350a96487ac20d -r bd9ef841c0aacf5feb6479ce3d19153c8d821876 yt/gui/reason/html/images/console.png
Binary file yt/gui/reason/html/images/console.png has changed
diff -r 97f7357fd0ce361c39414aa20b350a96487ac20d -r bd9ef841c0aacf5feb6479ce3d19153c8d821876 yt/gui/reason/html/images/double_down.png
Binary file yt/gui/reason/html/images/double_down.png has changed
diff -r 97f7357fd0ce361c39414aa20b350a96487ac20d -r bd9ef841c0aacf5feb6479ce3d19153c8d821876 yt/gui/reason/html/images/double_down_sm.png
Binary file yt/gui/reason/html/images/double_down_sm.png has changed
diff -r 97f7357fd0ce361c39414aa20b350a96487ac20d -r bd9ef841c0aacf5feb6479ce3d19153c8d821876 yt/gui/reason/html/images/double_left.png
Binary file yt/gui/reason/html/images/double_left.png has changed
diff -r 97f7357fd0ce361c39414aa20b350a96487ac20d -r bd9ef841c0aacf5feb6479ce3d19153c8d821876 yt/gui/reason/html/images/double_left_sm.png
Binary file yt/gui/reason/html/images/double_left_sm.png has changed
diff -r 97f7357fd0ce361c39414aa20b350a96487ac20d -r bd9ef841c0aacf5feb6479ce3d19153c8d821876 yt/gui/reason/html/images/double_right.png
Binary file yt/gui/reason/html/images/double_right.png has changed
diff -r 97f7357fd0ce361c39414aa20b350a96487ac20d -r bd9ef841c0aacf5feb6479ce3d19153c8d821876 yt/gui/reason/html/images/double_right_sm.png
Binary file yt/gui/reason/html/images/double_right_sm.png has changed
diff -r 97f7357fd0ce361c39414aa20b350a96487ac20d -r bd9ef841c0aacf5feb6479ce3d19153c8d821876 yt/gui/reason/html/images/double_up.png
Binary file yt/gui/reason/html/images/double_up.png has changed
diff -r 97f7357fd0ce361c39414aa20b350a96487ac20d -r bd9ef841c0aacf5feb6479ce3d19153c8d821876 yt/gui/reason/html/images/double_up_sm.png
Binary file yt/gui/reason/html/images/double_up_sm.png has changed
diff -r 97f7357fd0ce361c39414aa20b350a96487ac20d -r bd9ef841c0aacf5feb6479ce3d19153c8d821876 yt/gui/reason/html/images/graph.png
Binary file yt/gui/reason/html/images/graph.png has changed
diff -r 97f7357fd0ce361c39414aa20b350a96487ac20d -r bd9ef841c0aacf5feb6479ce3d19153c8d821876 yt/gui/reason/html/images/kivio_flw.png
Binary file yt/gui/reason/html/images/kivio_flw.png has changed
diff -r 97f7357fd0ce361c39414aa20b350a96487ac20d -r bd9ef841c0aacf5feb6479ce3d19153c8d821876 yt/gui/reason/html/images/single_down.png
Binary file yt/gui/reason/html/images/single_down.png has changed
diff -r 97f7357fd0ce361c39414aa20b350a96487ac20d -r bd9ef841c0aacf5feb6479ce3d19153c8d821876 yt/gui/reason/html/images/single_down_sm.png
Binary file yt/gui/reason/html/images/single_down_sm.png has changed
diff -r 97f7357fd0ce361c39414aa20b350a96487ac20d -r bd9ef841c0aacf5feb6479ce3d19153c8d821876 yt/gui/reason/html/images/single_left.png
Binary file yt/gui/reason/html/images/single_left.png has changed
diff -r 97f7357fd0ce361c39414aa20b350a96487ac20d -r bd9ef841c0aacf5feb6479ce3d19153c8d821876 yt/gui/reason/html/images/single_left_sm.png
Binary file yt/gui/reason/html/images/single_left_sm.png has changed
diff -r 97f7357fd0ce361c39414aa20b350a96487ac20d -r bd9ef841c0aacf5feb6479ce3d19153c8d821876 yt/gui/reason/html/images/single_right.png
Binary file yt/gui/reason/html/images/single_right.png has changed
diff -r 97f7357fd0ce361c39414aa20b350a96487ac20d -r bd9ef841c0aacf5feb6479ce3d19153c8d821876 yt/gui/reason/html/images/single_right_sm.png
Binary file yt/gui/reason/html/images/single_right_sm.png has changed
diff -r 97f7357fd0ce361c39414aa20b350a96487ac20d -r bd9ef841c0aacf5feb6479ce3d19153c8d821876 yt/gui/reason/html/images/single_up.png
Binary file yt/gui/reason/html/images/single_up.png has changed
diff -r 97f7357fd0ce361c39414aa20b350a96487ac20d -r bd9ef841c0aacf5feb6479ce3d19153c8d821876 yt/gui/reason/html/images/single_up_sm.png
Binary file yt/gui/reason/html/images/single_up_sm.png has changed
diff -r 97f7357fd0ce361c39414aa20b350a96487ac20d -r bd9ef841c0aacf5feb6479ce3d19153c8d821876 yt/gui/reason/html/images/upload.png
Binary file yt/gui/reason/html/images/upload.png has changed
diff -r 97f7357fd0ce361c39414aa20b350a96487ac20d -r bd9ef841c0aacf5feb6479ce3d19153c8d821876 yt/gui/reason/html/leaflet/images/marker-shadow.png
Binary file yt/gui/reason/html/leaflet/images/marker-shadow.png has changed
diff -r 97f7357fd0ce361c39414aa20b350a96487ac20d -r bd9ef841c0aacf5feb6479ce3d19153c8d821876 yt/gui/reason/html/leaflet/images/marker.png
Binary file yt/gui/reason/html/leaflet/images/marker.png has changed
diff -r 97f7357fd0ce361c39414aa20b350a96487ac20d -r bd9ef841c0aacf5feb6479ce3d19153c8d821876 yt/gui/reason/html/leaflet/images/popup-close.png
Binary file yt/gui/reason/html/leaflet/images/popup-close.png has changed
diff -r 97f7357fd0ce361c39414aa20b350a96487ac20d -r bd9ef841c0aacf5feb6479ce3d19153c8d821876 yt/gui/reason/html/leaflet/images/zoom-in.png
Binary file yt/gui/reason/html/leaflet/images/zoom-in.png has changed
diff -r 97f7357fd0ce361c39414aa20b350a96487ac20d -r bd9ef841c0aacf5feb6479ce3d19153c8d821876 yt/gui/reason/html/leaflet/images/zoom-out.png
Binary file yt/gui/reason/html/leaflet/images/zoom-out.png has changed
diff -r 97f7357fd0ce361c39414aa20b350a96487ac20d -r bd9ef841c0aacf5feb6479ce3d19153c8d821876 yt/mods.py
--- a/yt/mods.py
+++ b/yt/mods.py
@@ -108,7 +108,7 @@
PlotCollection, PlotCollectionInteractive, \
get_multi_plot, FixedResolutionBuffer, ObliqueFixedResolutionBuffer, \
callback_registry, write_bitmap, write_image, annotate_image, \
- apply_colormap, scale_image
+ apply_colormap, scale_image, write_projection
from yt.visualization.volume_rendering.api import \
ColorTransferFunction, PlanckTransferFunction, ProjectionTransferFunction, \
@@ -122,6 +122,10 @@
from yt.convenience import all_pfs, max_spheres, load, projload
+# Import some helpful math utilities
+from yt.utilities.math_utils import \
+ ortho_find, quartiles
+
# We load plugins. Keep in mind, this can be fairly dangerous -
# the primary purpose is to allow people to have a set of functions
diff -r 97f7357fd0ce361c39414aa20b350a96487ac20d -r bd9ef841c0aacf5feb6479ce3d19153c8d821876 yt/utilities/_amr_utils/VolumeIntegrator.pyx
--- a/yt/utilities/_amr_utils/VolumeIntegrator.pyx
+++ b/yt/utilities/_amr_utils/VolumeIntegrator.pyx
@@ -65,6 +65,9 @@
double log2(double x)
long int lrint(double x)
double fabs(double x)
+ double cos(double x)
+ double sin(double x)
+ double asin(double x)
cdef struct Triangle:
Triangle *next
@@ -238,6 +241,33 @@
tr[i] = ipnest
return tr
+def arr_fisheye_vectors(int resolution, np.float64_t fov):
+ # We now follow figures 4-7 of:
+ # http://paulbourke.net/miscellaneous/domefisheye/fisheye/
+ # ...but all in Cython.
+ cdef np.ndarray[np.float64_t, ndim=3] vp
+ cdef int i, j, k
+ cdef np.float64_t r, phi, theta, px, py
+ cdef np.float64_t pi = 3.1415926
+ cdef np.float64_t fov_rad = fov * pi / 180.0
+ vp = np.zeros((resolution, resolution, 3), dtype="float64")
+ for i in range(resolution):
+ px = 2.0 * i / (resolution) - 1.0
+ for j in range(resolution):
+ py = 2.0 * j / (resolution) - 1.0
+ r = (px*px + py*py)**0.5
+ if r == 0.0:
+ phi = 0.0
+ elif px < 0:
+ phi = pi - asin(py / r)
+ else:
+ phi = asin(py / r)
+ theta = r * fov_rad / 2.0
+ vp[i,j,0] = sin(theta) * cos(phi)
+ vp[i,j,1] = sin(theta) * sin(phi)
+ vp[i,j,2] = cos(theta)
+ return vp
+
cdef class star_kdtree_container:
cdef kdtree_utils.kdtree *tree
cdef public np.float64_t sigma
diff -r 97f7357fd0ce361c39414aa20b350a96487ac20d -r bd9ef841c0aacf5feb6479ce3d19153c8d821876 yt/utilities/math_utils.py
--- a/yt/utilities/math_utils.py
+++ b/yt/utilities/math_utils.py
@@ -515,3 +515,107 @@
vec2 /= norm2
vec3 = na.cross(vec1, vec2)
return vec1, vec2, vec3
+
+def quartiles(a, axis=None, out=None, overwrite_input=False):
+ """
+ Compute the quartile values (25% and 75%) along the specified axis
+ in the same way that the numpy.median calculates the median (50%) value
+ alone a specified axis. Check numpy.median for details, as it is
+ virtually the same algorithm.
+
+ Returns an array of the quartiles of the array elements [lower quartile,
+ upper quartile].
+
+ Parameters
+ ----------
+ a : array_like
+ Input array or object that can be converted to an array.
+ axis : {None, int}, optional
+ Axis along which the quartiles are computed. The default (axis=None)
+ is to compute the quartiles along a flattened version of the array.
+ out : ndarray, optional
+ Alternative output array in which to place the result. It must
+ have the same shape and buffer length as the expected output,
+ but the type (of the output) will be cast if necessary.
+ overwrite_input : {False, True}, optional
+ If True, then allow use of memory of input array (a) for
+ calculations. The input array will be modified by the call to
+ quartiles. This will save memory when you do not need to preserve
+ the contents of the input array. Treat the input as undefined,
+ but it will probably be fully or partially sorted. Default is
+ False. Note that, if `overwrite_input` is True and the input
+ is not already an ndarray, an error will be raised.
+
+ Returns
+ -------
+ quartiles : ndarray
+ A new 2D array holding the result (unless `out` is specified, in
+ which case that array is returned instead). If the input contains
+ integers, or floats of smaller precision than 64, then the output
+ data-type is float64. Otherwise, the output data-type is the same
+ as that of the input.
+
+ See Also
+ --------
+ numpy.median, numpy.mean, numpy.percentile
+
+ Notes
+ -----
+ Given a vector V of length N, the quartiles of V are the 25% and 75% values
+ of a sorted copy of V, ``V_sorted`` - i.e., ``V_sorted[(N-1)/4]`` and
+ ``3*V_sorted[(N-1)/4]``, when N is odd. When N is even, it is the average
+ of the two values bounding these values of ``V_sorted``.
+
+ Examples
+ --------
+ >>> a = na.arange(100).reshape(10,10)
+ >>> a
+ array([[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
+ [10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
+ [20, 21, 22, 23, 24, 25, 26, 27, 28, 29],
+ [30, 31, 32, 33, 34, 35, 36, 37, 38, 39],
+ [40, 41, 42, 43, 44, 45, 46, 47, 48, 49],
+ [50, 51, 52, 53, 54, 55, 56, 57, 58, 59],
+ [60, 61, 62, 63, 64, 65, 66, 67, 68, 69],
+ [70, 71, 72, 73, 74, 75, 76, 77, 78, 79],
+ [80, 81, 82, 83, 84, 85, 86, 87, 88, 89],
+ [90, 91, 92, 93, 94, 95, 96, 97, 98, 99]])
+ >>> mu.quartiles(a)
+ array([ 24.5, 74.5])
+ >>> mu.quartiles(a,axis=0)
+ array([[ 15., 16., 17., 18., 19., 20., 21., 22., 23., 24.],
+ [ 65., 66., 67., 68., 69., 70., 71., 72., 73., 74.]])
+ >>> mu.quartiles(a,axis=1)
+ array([[ 1.5, 11.5, 21.5, 31.5, 41.5, 51.5, 61.5, 71.5, 81.5,
+ 91.5],
+ [ 6.5, 16.5, 26.5, 36.5, 46.5, 56.5, 66.5, 76.5, 86.5,
+ 96.5]])
+ """
+ if overwrite_input:
+ if axis is None:
+ sorted = a.ravel()
+ sorted.sort()
+ else:
+ a.sort(axis=axis)
+ sorted = a
+ else:
+ sorted = na.sort(a, axis=axis)
+ if axis is None:
+ axis = 0
+ indexer = [slice(None)] * sorted.ndim
+ indices = [int(sorted.shape[axis]/4), int(sorted.shape[axis]*.75)]
+ result = []
+ for index in indices:
+ if sorted.shape[axis] % 2 == 1:
+ # index with slice to allow mean (below) to work
+ indexer[axis] = slice(index, index+1)
+ else:
+ indexer[axis] = slice(index-1, index+1)
+ # special cases for small arrays
+ if sorted.shape[axis] == 2:
+ # index with slice to allow mean (below) to work
+ indexer[axis] = slice(index, index+1)
+ # Use mean in odd and even case to coerce data type
+ # and check, use out array.
+ result.append(na.mean(sorted[indexer], axis=axis, out=out))
+ return na.array(result)
diff -r 97f7357fd0ce361c39414aa20b350a96487ac20d -r bd9ef841c0aacf5feb6479ce3d19153c8d821876 yt/visualization/api.py
--- a/yt/visualization/api.py
+++ b/yt/visualization/api.py
@@ -49,7 +49,8 @@
splat_points, \
annotate_image, \
apply_colormap, \
- scale_image
+ scale_image, \
+ write_projection
from plot_modifications import \
PlotCallback, \
diff -r 97f7357fd0ce361c39414aa20b350a96487ac20d -r bd9ef841c0aacf5feb6479ce3d19153c8d821876 yt/visualization/image_writer.py
--- a/yt/visualization/image_writer.py
+++ b/yt/visualization/image_writer.py
@@ -327,3 +327,90 @@
im = image.copy()
au.add_points_to_image(im, points_x, points_y, val)
return im
+
+def write_projection(data, filename, colorbar=True, colorbar_label=None,
+ title=None, limits=None, take_log=True, var_fig_size=False):
+ r"""Write a projection or volume rendering to disk with a variety of
+ pretty parameters such as limits, title, colorbar, etc. write_projection
+ uses the standard matplotlib interface to create the figure. N.B. This code
+ only works *after* you have created the projection using the standard
+ framework (i.e. the Camera interface or off_axis_projection).
+
+ Accepts an NxM sized array representing the projection itself as well
+ as the filename to which you will save this figure.
+
+ Parameters
+ ----------
+ data : array_like
+ image array as output by off_axis_projection or camera.snapshot()
+ filename : string
+ the filename where the data will be saved
+ colorbar : boolean
+ do you want a colorbar generated to the right of the image?
+ colorbar_label : string
+ the label associated with your colorbar
+ title : string
+ the label at the top of the figure
+ limits : 2-element array_like
+ the lower limit and the upper limit to be plotted in the figure
+ of the data array
+ take_log : boolean
+ plot the log of the data array (and take the log of the limits if set)?
+ var_fig_size : boolean
+ If we want the resolution (and size) of the output image to scale
+ with the resolution of the image array.
+
+ Examples
+ --------
+
+ >>> image = off_axis_projection(pf, c, L, W, N, "Density", no_ghost=False)
+ >>> write_projection(image, 'test.png',
+ colorbar_label="Column Density (cm$^{-2}$)",
+ title="Offaxis Projection", limits=(1e-3,1e-5),
+ take_log=True)
+ """
+ import pylab as pl
+
+ # If there are limits, then clip the data before plotting
+ if limits is not None:
+ data = na.clip(data, limits[0], limits[1])
+
+ # If this is rendered as log, then apply now.
+ if take_log:
+ data = na.log10(data)
+ if limits is not None:
+ limits = na.log10(limits)
+
+
+ # Create the figure and paint the data on
+ fig = pl.figure()
+ ax = fig.add_subplot(111)
+ cax = ax.imshow(data)
+
+ # If there are limits, apply them to the colormap
+ if limits is not None:
+ cax.set_clim=limits
+ if title:
+ ax.set_title(title)
+
+ # Suppress the x and y pixel counts
+ ax.set_xticks(())
+ ax.set_yticks(())
+
+ # Add a color bar and label if requested
+ if colorbar:
+ cbar = fig.colorbar(cax)
+ if colorbar_label:
+ cbar.ax.set_ylabel(colorbar_label)
+
+ # If we want the resolution of the image to scale with the resolution
+ # of the image array. we increase the dpi value accordingly
+ if var_fig_size:
+ N = data.shape[0]
+ mag_factor = N/480.
+ pl.savefig(filename, dpi=100*mag_factor)
+ else:
+ pl.savefig(filename)
+
+ pl.clf()
+ pl.close()
diff -r 97f7357fd0ce361c39414aa20b350a96487ac20d -r bd9ef841c0aacf5feb6479ce3d19153c8d821876 yt/visualization/plot_collection.py
--- a/yt/visualization/plot_collection.py
+++ b/yt/visualization/plot_collection.py
@@ -211,9 +211,9 @@
Only ONE of the following options can be specified. If all 3 are
specified, they will be used in the following precedence order:
- * `ticks` - a list of floating point numbers at which to put ticks
- * `minmaxtick` - display DEFAULT ticks with min & max also displayed
- * `nticks` - if ticks not specified, can automatically determine a
+ * ``ticks`` - a list of floating point numbers at which to put ticks
+ * ``minmaxtick`` - display DEFAULT ticks with min & max also displayed
+ * ``nticks`` - if ticks not specified, can automatically determine a
number of ticks to be evenly spaced in log space
"""
for plot in self.plots:
@@ -1713,9 +1713,9 @@
r"""Construct a multiple axes plot object, with or without a colorbar, into
which multiple plots may be inserted.
- This will create a set of `matplotlib.axes.Axes`, all lined up into a grid,
- which are then returned to the user and which can be used to plot multiple
- plots on a single figure.
+ This will create a set of :class:`matplotlib.axes.Axes`, all lined up into
+ a grid, which are then returned to the user and which can be used to plot
+ multiple plots on a single figure.
Parameters
----------
@@ -1733,12 +1733,12 @@
Returns
-------
- fig : `matplotlib.figure.Figure
+ fig : :class:`matplotlib.figure.Figure`
The figure created inside which the axes reside
- tr : list of list of `matplotlib.axes.Axes` objects
+ tr : list of list of :class:`matplotlib.axes.Axes` objects
This is a list, where the inner list is along the x-axis and the outer
is along the y-axis
- cbars : list of `matplotlib.axes.Axes` objects
+ cbars : list of :class:`matplotlib.axes.Axes` objects
Each of these is an axes onto which a colorbar can be placed.
Notes
diff -r 97f7357fd0ce361c39414aa20b350a96487ac20d -r bd9ef841c0aacf5feb6479ce3d19153c8d821876 yt/visualization/plot_types.py
--- a/yt/visualization/plot_types.py
+++ b/yt/visualization/plot_types.py
@@ -170,10 +170,11 @@
Only ONE of the following options can be specified. If all 3 are
specified, they will be used in the following precedence order:
- ticks - a list of floating point numbers at which to put ticks
- minmaxtick - display DEFAULT ticks with min & max also displayed
- nticks - if ticks not specified, can automatically determine a
- number of ticks to be evenly spaced in log space
+
+ * ``ticks`` - a list of floating point numbers at which to put ticks
+ * ``minmaxtick`` - display DEFAULT ticks with min & max also displayed
+ * ``nticks`` - if ticks not specified, can automatically determine a
+ number of ticks to be evenly spaced in log space
"""
# This next call fixes some things, but is slower...
self._redraw_image()
diff -r 97f7357fd0ce361c39414aa20b350a96487ac20d -r bd9ef841c0aacf5feb6479ce3d19153c8d821876 yt/visualization/volume_rendering/camera.py
--- a/yt/visualization/volume_rendering/camera.py
+++ b/yt/visualization/volume_rendering/camera.py
@@ -32,7 +32,7 @@
from yt.utilities.amr_utils import TransferFunctionProxy, VectorPlane, \
arr_vec2pix_nest, arr_pix2vec_nest, AdaptiveRaySource, \
- arr_ang2pix_nest
+ arr_ang2pix_nest, arr_fisheye_vectors
from yt.visualization.image_writer import write_bitmap
from yt.data_objects.data_containers import data_object_registry
from yt.utilities.parallel_tools.parallel_analysis_interface import \
@@ -703,7 +703,7 @@
ax = fig.add_subplot(1,1,1,projection='mollweide')
implot = ax.imshow(img, extent=(-pi,pi,-pi/2,pi/2), clip_on=False, aspect=0.5)
cb = fig.colorbar(implot, orientation='horizontal')
- cb.set_label(r"$\mathrm{Column}\/\mathrm{Density}\/[\mathrm{g}/\mathrm{cm}^2]$")
+ cb.set_label(r"$\mathrm{log}\/\mathrm{Column}\/\mathrm{Density}\/[\mathrm{g}/\mathrm{cm}^2]$")
ax.xaxis.set_ticks(())
ax.yaxis.set_ticks(())
canvas = matplotlib.backends.backend_agg.FigureCanvasAgg(fig)
@@ -793,6 +793,59 @@
oc.sub_samples, oc.pf)
return (left_camera, right_camera)
+class FisheyeCamera(Camera):
+ def __init__(self, center, radius, fov, resolution,
+ transfer_function = None, fields = None,
+ sub_samples = 5, log_fields = None, volume = None,
+ pf = None, no_ghost=False):
+ ParallelAnalysisInterface.__init__(self)
+ if pf is not None: self.pf = pf
+ self.center = na.array(center, dtype='float64')
+ self.radius = radius
+ self.fov = fov
+ if iterable(resolution):
+ raise RuntimeError("Resolution must be a single int")
+ self.resolution = resolution
+ if transfer_function is None:
+ transfer_function = ProjectionTransferFunction()
+ self.transfer_function = transfer_function
+ if fields is None: fields = ["Density"]
+ self.fields = fields
+ self.sub_samples = sub_samples
+ self.log_fields = log_fields
+ if volume is None:
+ volume = AMRKDTree(self.pf, fields=self.fields, no_ghost=no_ghost,
+ log_fields=log_fields)
+ self.volume = volume
+
+ def snapshot(self):
+ image = na.zeros((self.resolution**2,1,3), dtype='float64', order='C')
+ # We now follow figures 4-7 of:
+ # http://paulbourke.net/miscellaneous/domefisheye/fisheye/
+ # ...but all in Cython.
+ vp = arr_fisheye_vectors(self.resolution, self.fov)
+ vp.shape = (self.resolution**2,1,3)
+ uv = na.ones(3, dtype='float64')
+ positions = na.ones((self.resolution**2, 1, 3), dtype='float64') * self.center
+ vector_plane = VectorPlane(positions, vp, self.center,
+ (0.0, 1.0, 0.0, 1.0), image, uv, uv)
+ tfp = TransferFunctionProxy(self.transfer_function)
+ tfp.ns = self.sub_samples
+ self.volume.initialize_source()
+ mylog.info("Rendering fisheye of %s^2", self.resolution)
+ pbar = get_pbar("Ray casting",
+ (self.volume.brick_dimensions + 1).prod(axis=-1).sum())
+
+ total_cells = 0
+ for brick in self.volume.traverse(None, self.center, image):
+ brick.cast_plane(tfp, vector_plane)
+ total_cells += na.prod(brick.my_data[0].shape)
+ pbar.update(total_cells)
+ pbar.finish()
+ image.shape = (self.resolution, self.resolution, 3)
+ return image
+
+
def off_axis_projection(pf, center, normal_vector, width, resolution,
field, weight = None, volume = None, no_ghost = True):
r"""Project through a parameter file, off-axis, and return the image plane.
https://bitbucket.org/yt_analysis/yt/changeset/3d6032495f52/
changeset: 3d6032495f52
branch: yt
user: brittonsmith
date: 2011-12-16 21:59:46
summary: Switched the splitting of halos in the HaloProfiler from _get_objs
to parallel_objects. This fixes some issues with processors getting
stuck at barriers when analysing different halos. Thanks to Matt
for the tip.
affected #: 1 file
diff -r bd9ef841c0aacf5feb6479ce3d19153c8d821876 -r 3d6032495f52c73e7962fa112b60ce1fe6ad6185 yt/analysis_modules/halo_profiler/multi_halo_profiler.py
--- a/yt/analysis_modules/halo_profiler/multi_halo_profiler.py
+++ b/yt/analysis_modules/halo_profiler/multi_halo_profiler.py
@@ -46,7 +46,8 @@
from yt.utilities.parallel_tools.parallel_analysis_interface import \
ParallelAnalysisInterface, \
parallel_blocking_call, \
- parallel_root_only
+ parallel_root_only, \
+ parallel_objects
from yt.visualization.fixed_resolution import \
FixedResolutionBuffer
from yt.visualization.image_writer import write_image
@@ -184,7 +185,6 @@
self._halo_filters = []
self.all_halos = []
self.filtered_halos = []
- self._projection_halo_list = []
# Create output directory if specified
if self.output_dir is not None:
@@ -454,7 +454,7 @@
# Profile all halos.
updated_halos = []
- for halo in self._get_objs('all_halos', round_robin=True):
+ for halo in parallel_objects(self.all_halos, -1):
# Apply prefilters to avoid profiling unwanted halos.
filter_result = True
haloQuantities = {}
@@ -618,18 +618,18 @@
# Get list of halos for projecting.
if halo_list == 'filtered':
- self._halo_projection_list = self.filtered_halos
+ halo_projection_list = self.filtered_halos
elif halo_list == 'all':
- self._halo_projection_list = self.all_halos
+ halo_projection_list = self.all_halos
elif isinstance(halo_list, types.StringType):
- self._halo_projection_list = self._read_halo_list(halo_list)
+ halo_projection_list = self._read_halo_list(halo_list)
elif isinstance(halo_list, types.ListType):
- self._halo_projection_list = halo_list
+ halo_projection_list = halo_list
else:
mylog.error("Keyword, halo_list', must be 'filtered', 'all', a filename, or an actual list.")
return
- if len(self._halo_projection_list) == 0:
+ if len(halo_projection_list) == 0:
mylog.error("Halo list for projections is empty.")
return
@@ -656,7 +656,7 @@
self.pf.parameters['DomainRightEdge'][w])
for w in range(self.pf.parameters['TopGridRank'])]
- for halo in self._get_objs('_halo_projection_list', round_robin=True):
+ for halo in parallel_objects(halo_projection_list, -1):
if halo is None:
continue
# Check if region will overlap domain edge.
@@ -778,18 +778,18 @@
# Get list of halos for projecting.
if halo_list == 'filtered':
- self._halo_analysis_list = self.filtered_halos
+ halo_analysis_list = self.filtered_halos
elif halo_list == 'all':
- self._halo_analysis_list = self.all_halos
+ halo_analysis_list = self.all_halos
elif isinstance(halo_list, types.StringType):
- self._halo_analysis_list = self._read_halo_list(halo_list)
+ halo_analysis_list = self._read_halo_list(halo_list)
elif isinstance(halo_list, types.ListType):
- self._halo_analysis_list = halo_list
+ halo_analysis_list = halo_list
else:
mylog.error("Keyword, halo_list', must be 'filtered', 'all', a filename, or an actual list.")
return
- if len(self._halo_analysis_list) == 0:
+ if len(halo_analysis_list) == 0:
mylog.error("Halo list for analysis is empty.")
return
@@ -803,7 +803,7 @@
my_output_dir = "%s/%s" % (self.pf.fullpath, analysis_output_dir)
self.__check_directory(my_output_dir)
- for halo in self._get_objs('_halo_analysis_list', round_robin=True):
+ for halo in parallel_objects(halo_analysis_list, -1):
if halo is None: continue
# Get a sphere object to analze.
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