[yt-svn] commit/yt: 2 new changesets
Bitbucket
commits-noreply at bitbucket.org
Sat Jun 2 05:03:25 PDT 2012
2 new commits in yt:
https://bitbucket.org/yt_analysis/yt/changeset/be3f7a60ad4c/
changeset: be3f7a60ad4c
branch: yt
user: brittonsmith
date: 2012-06-01 21:47:35
summary: Adding new EnzoSimulation class to the enzo frontend. The old
EnzoSimulation still exists, but will now be phased out.
affected #: 3 files
diff -r a437280f3cefff3e7a41198438a5dfb7922f74e5 -r be3f7a60ad4c226f13181a9a3e99e42ec8d29008 yt/frontends/enzo/api.py
--- a/yt/frontends/enzo/api.py
+++ b/yt/frontends/enzo/api.py
@@ -38,6 +38,9 @@
EnzoStaticOutput, \
EnzoStaticOutputInMemory
+from .simulation_handling import \
+ EnzoSimulation
+
from .fields import \
EnzoFieldInfo, \
Enzo2DFieldInfo, \
diff -r a437280f3cefff3e7a41198438a5dfb7922f74e5 -r be3f7a60ad4c226f13181a9a3e99e42ec8d29008 yt/frontends/enzo/simulation_handling.py
--- /dev/null
+++ b/yt/frontends/enzo/simulation_handling.py
@@ -0,0 +1,692 @@
+"""
+EnzoSimulation class and member functions.
+
+Author: Britton Smith <brittonsmith at gmail.com>
+Affiliation: Michigan State University
+Homepage: http://yt-project.org/
+License:
+ Copyright (C) 2008-2012 Britton Smith. 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 *
+
+import numpy as na
+import glob
+import os
+
+from yt.data_objects.time_series import \
+ TimeSeriesData
+from yt.utilities.cosmology import \
+ Cosmology, \
+ EnzoCosmology
+from yt.utilities.exceptions import \
+ YTException
+from yt.utilities.parallel_tools.parallel_analysis_interface import \
+ parallel_root_only
+
+from yt.convenience import \
+ load
+
+class EnzoSimulation(TimeSeriesData):
+ r"""Super class for performing the same operation over all data outputs in
+ a simulation from one redshift to another.
+ """
+ def __init__(self, parameter_filename):
+ r"""Initialize an Enzo Simulation object.
+
+ Upon creation, the parameter file is parsed and the time and redshift
+ are calculated and stored in all_outputs. A time units dictionary is
+ instantiated to allow for time outputs to be requested with physical
+ time units. The get_time_series can be used to generate a
+ TimeSeriesData object.
+
+ parameter_filename : str
+ The simulation parameter file.
+
+ Examples
+ --------
+ >>> from yt.mods import *
+ >>> es = ES.EnzoSimulation("my_simulation.par")
+ >>> print es.all_outputs
+
+ """
+ self.parameter_filename = parameter_filename
+ self.parameters = {}
+
+ # Set some parameter defaults.
+ self._set_parameter_defaults()
+ # Read the simulation parameter file.
+ self._parse_parameter_file()
+ # Set up time units dictionary.
+ self._set_time_units()
+
+ # Figure out the starting and stopping times and redshift.
+ self._calculate_simulation_bounds()
+ self.print_key_parameters()
+
+ # Get all possible datasets.
+ self._get_all_outputs()
+
+ def get_time_series(self, time_data=True, redshift_data=True,
+ initial_time=None, final_time=None, time_units='1',
+ initial_redshift=None, final_redshift=None,
+ initial_cycle=None, final_cycle=None,
+ times=None, redshifts=None, tolerance=None,
+ find_outputs=False, parallel=True):
+
+ """
+ Instantiate a TimeSeriesData object for a set of outputs.
+
+ If no additional keywords given, a TimeSeriesData object will be
+ created with all potential datasets created by the simulation.
+
+ Outputs can be gather by specifying a time or redshift range
+ (or combination of time and redshift), with a specific list of
+ times or redshifts, a range of cycle numbers (for cycle based
+ output), or by simply searching all subdirectories within the
+ simulation directory.
+
+ time_data : bool
+ Whether or not to include time outputs when gathering
+ datasets for time series.
+ Default: True.
+ redshift_data : bool
+ Whether or not to include redshift outputs when gathering
+ datasets for time series.
+ Default: True.
+ initial_time : float
+ The earliest time for outputs to be included. If None,
+ the initial time of the simulation is used. This can be
+ used in combination with either final_time or
+ final_redshift.
+ Default: None.
+ final_time : float
+ The latest time for outputs to be included. If None,
+ the final time of the simulation is used. This can be
+ used in combination with either initial_time or
+ initial_redshift.
+ Default: None.
+ times : array_like
+ A list of times for which outputs will be found.
+ Default: None.
+ time_units : str
+ The time units used for requesting outputs by time.
+ Default: '1' (code units).
+ initial_redshift : float
+ The earliest redshift for outputs to be included. If None,
+ the initial redshift of the simulation is used. This can be
+ used in combination with either final_time or
+ final_redshift.
+ Default: None.
+ final_time : float
+ The latest redshift for outputs to be included. If None,
+ the final redshift of the simulation is used. This can be
+ used in combination with either initial_time or
+ initial_redshift.
+ Default: None.
+ redshifts : array_like
+ A list of redshifts for which outputs will be found.
+ Default: None.
+ initial_cycle : float
+ The earliest cycle for outputs to be included. If None,
+ the initial cycle of the simulation is used. This can
+ only be used with final_cycle.
+ Default: None.
+ final_cycle : float
+ The latest cycle for outputs to be included. If None,
+ the final cycle of the simulation is used. This can
+ only be used in combination with initial_cycle.
+ Default: None.
+ tolerance : float
+ Used in combination with "times" or "redshifts" keywords,
+ this is the tolerance within which outputs are accepted
+ given the requested times or redshifts. If None, the
+ nearest output is always taken.
+ Default: None.
+ find_outputs : bool
+ If True, subdirectories within the GlobalDir directory are
+ searched one by one for datasets. Time and redshift
+ information are gathered by temporarily instantiating each
+ dataset. This can be used when simulation data was created
+ in a non-standard way, making it difficult to guess the
+ corresponding time and redshift information.
+ Default: False.
+ parallel : bool/int
+ If True, the generated TimeSeriesData will divide the work
+ such that a single processor works on each dataset. If an
+ integer is supplied, the work will be divided into that
+ number of jobs.
+ Default: True.
+
+ Examples
+ --------
+ >>> es.get_time_series(initial_redshift=10, final_time=13.7,
+ time_units='Gyr', redshift_data=False)
+
+ >>> es.get_time_series(redshifts=[3, 2, 1, 0])
+
+ >>> es.get_time_series(final_cycle=100000)
+
+ >>> es.get_time_series(find_outputs=True)
+
+ >>> # after calling get_time_series
+ >>> for pf in es.piter():
+ >>> pc = PlotCollection(pf, 'c')
+ >>> pc.add_projection('Density', 0)
+ >>> pc.save()
+
+ """
+
+ if (initial_redshift is not None or \
+ final_redshift is not None) and \
+ not self.cosmological_simulation:
+ mylog.error('An initial or final redshift has been given for a noncosmological simulation.')
+ return
+
+ if find_outputs:
+ my_outputs = self._find_outputs()
+
+ else:
+ if time_data and redshift_data:
+ my_all_outputs = self.all_outputs
+ elif time_data:
+ my_all_outputs = self.all_time_outputs
+ elif redshift_data:
+ my_all_outputs = self.all_redshift_outputs
+ else:
+ mylog.error('Both time_data and redshift_data are False.')
+ return
+
+ if times is not None:
+ my_outputs = self._get_outputs_by_time(times, tolerance=tolerance,
+ outputs=my_all_outputs,
+ time_units=time_units)
+
+ elif redshifts is not None:
+ my_outputs = self._get_outputs_by_redshift(redshifts, tolerance=tolerance,
+ outputs=my_all_outputs)
+
+ elif initial_cycle is not None or final_cycle is not None:
+ if initial_cycle is None:
+ initial_cycle = 0
+ else:
+ initial_cycle = max(initial_cycle, 0)
+ if final_cycle is None:
+ final_cycle = self.parameters['StopCycle']
+ else:
+ final_cycle = min(final_cycle, self.parameters['StopCycle'])
+ my_outputs = my_all_outputs[int(ceil(float(initial_cycle) /
+ self.parameters['CycleSkipDataDump'])):
+ (final_cycle / self.parameters['CycleSkipDataDump'])+1]
+
+ else:
+ if initial_time is not None:
+ my_initial_time = initial_time / self.time_units[time_units]
+ elif initial_redshift is not None:
+ my_initial_time = self.enzo_cosmology.ComputeTimeFromRedshift(initial_redshift) / \
+ self.enzo_cosmology.TimeUnits
+ else:
+ my_initial_time = self.initial_time
+
+ if final_time is not None:
+ my_final_time = final_time / self.time_units[time_units]
+ elif final_redshift is not None:
+ my_final_time = self.enzo_cosmology.ComputeTimeFromRedshift(final_redshift) / \
+ self.enzo_cosmology.TimeUnits
+ else:
+ my_final_time = self.final_time
+
+ my_times = na.array(map(lambda a:a['time'], my_all_outputs))
+ my_indices = na.digitize([my_initial_time, my_final_time], my_times)
+ if my_initial_time == my_times[my_indices[0] - 1]: my_indices[0] -= 1
+ my_outputs = my_all_outputs[my_indices[0]:my_indices[1]]
+
+ TimeSeriesData.__init__(self, outputs=[output['filename'] for output in my_outputs],
+ parallel=parallel)
+ mylog.info("%d outputs loaded into time series." % len(my_outputs))
+
+ @parallel_root_only
+ def print_key_parameters(self):
+ """
+ Print out some key parameters for the simulation.
+ """
+ for a in ["domain_dimensions", "domain_left_edge",
+ "domain_right_edge", "initial_time", "final_time",
+ "stop_cycle", "cosmological_simulation"]:
+ if not hasattr(self, a):
+ mylog.error("Missing %s in parameter file definition!", a)
+ continue
+ v = getattr(self, a)
+ mylog.info("Parameters: %-25s = %s", a, v)
+ if hasattr(self, "cosmological_simulation") and \
+ getattr(self, "cosmological_simulation"):
+ for a in ["omega_lambda", "omega_matter",
+ "hubble_constant", "initial_redshift",
+ "final_redshift"]:
+ if not hasattr(self, a):
+ mylog.error("Missing %s in parameter file definition!", a)
+ continue
+ v = getattr(self, a)
+ mylog.info("Parameters: %-25s = %s", a, v)
+
+ def _parse_parameter_file(self):
+ """
+ Parses the parameter file and establishes the various
+ dictionaries.
+ """
+
+ self.conversion_factors = {}
+ redshift_outputs = []
+
+ # Let's read the file
+ lines = open(self.parameter_filename).readlines()
+ for line in (l.strip() for l in lines):
+ if '#' in line: line = line[0:line.find('#')]
+ if '//' in line: line = line[0:line.find('//')]
+ if len(line) < 2: continue
+ param, vals = (i.strip() for i in line.split("="))
+ # First we try to decipher what type of value it is.
+ vals = vals.split()
+ # Special case approaching.
+ if "(do" in vals: vals = vals[:1]
+ if len(vals) == 0:
+ pcast = str # Assume NULL output
+ else:
+ v = vals[0]
+ # Figure out if it's castable to floating point:
+ try:
+ float(v)
+ except ValueError:
+ pcast = str
+ else:
+ if any("." in v or "e+" in v or "e-" in v for v in vals):
+ pcast = float
+ elif v == "inf":
+ pcast = str
+ else:
+ pcast = int
+ # Now we figure out what to do with it.
+ if param.endswith("Units") and not param.startswith("Temperature"):
+ dataType = param[:-5]
+ # This one better be a float.
+ self.conversion_factors[dataType] = float(vals[0])
+ if param.startswith("CosmologyOutputRedshift["):
+ index = param[param.find("[")+1:param.find("]")]
+ redshift_outputs.append({'index':int(index), 'redshift':float(vals[0])})
+ elif len(vals) == 0:
+ vals = ""
+ elif len(vals) == 1:
+ vals = pcast(vals[0])
+ else:
+ vals = na.array([pcast(i) for i in vals if i != "-99999"])
+ self.parameters[param] = vals
+ self.refine_by = self.parameters["RefineBy"]
+ self.dimensionality = self.parameters["TopGridRank"]
+ if self.dimensionality > 1:
+ self.domain_dimensions = self.parameters["TopGridDimensions"]
+ if len(self.domain_dimensions) < 3:
+ tmp = self.domain_dimensions.tolist()
+ tmp.append(1)
+ self.domain_dimensions = na.array(tmp)
+ self.domain_left_edge = na.array(self.parameters["DomainLeftEdge"],
+ "float64").copy()
+ self.domain_right_edge = na.array(self.parameters["DomainRightEdge"],
+ "float64").copy()
+ else:
+ self.domain_left_edge = na.array(self.parameters["DomainLeftEdge"],
+ "float64")
+ self.domain_right_edge = na.array(self.parameters["DomainRightEdge"],
+ "float64")
+ self.domain_dimensions = na.array([self.parameters["TopGridDimensions"],1,1])
+
+ if self.parameters["ComovingCoordinates"]:
+ cosmo_attr = {'omega_lambda': 'CosmologyOmegaLambdaNow',
+ 'omega_matter': 'CosmologyOmegaMatterNow',
+ 'hubble_constant': 'CosmologyHubbleConstantNow',
+ 'initial_redshift': 'CosmologyInitialRedshift',
+ 'final_redshift': 'CosmologyFinalRedshift'}
+ self.cosmological_simulation = 1
+ for a, v in cosmo_attr.items():
+ if not v in self.parameters:
+ raise MissingParameter(self.parameter_filename, v)
+ setattr(self, a, self.parameters[v])
+ else:
+ self.omega_lambda = self.omega_matter = \
+ self.hubble_constant = self.cosmological_simulation = 0.0
+
+ # make list of redshift outputs
+ self.all_redshift_outputs = []
+ if not self.cosmological_simulation: return
+ for output in redshift_outputs:
+ output['filename'] = os.path.join(self.parameters['GlobalDir'],
+ "%s%04d" % (self.parameters['RedshiftDumpDir'],
+ output['index']),
+ "%s%04d" % (self.parameters['RedshiftDumpName'],
+ output['index']))
+ del output['index']
+ self.all_redshift_outputs = redshift_outputs
+
+ def _calculate_redshift_dump_times(self):
+ "Calculates time from redshift of redshift outputs."
+
+ if not self.cosmological_simulation: return
+ for output in self.all_redshift_outputs:
+ output['time'] = self.enzo_cosmology.ComputeTimeFromRedshift(output['redshift']) / \
+ self.enzo_cosmology.TimeUnits
+
+ def _calculate_time_outputs(self):
+ "Calculate time outputs and their redshifts if cosmological."
+
+ if self.final_time is None or \
+ not 'dtDataDump' in self.parameters or \
+ self.parameters['dtDataDump'] <= 0.0: return []
+
+ self.all_time_outputs = []
+ index = 0
+ current_time = self.initial_time
+ while current_time <= self.final_time + self.parameters['dtDataDump']:
+ filename = os.path.join(self.parameters['GlobalDir'],
+ "%s%04d" % (self.parameters['DataDumpDir'], index),
+ "%s%04d" % (self.parameters['DataDumpName'], index))
+
+ output = {'index': index, 'filename': filename, 'time': current_time}
+ output['time'] = min(output['time'], self.final_time)
+ if self.cosmological_simulation:
+ output['redshift'] = self.enzo_cosmology.ComputeRedshiftFromTime(
+ current_time * self.enzo_cosmology.TimeUnits)
+
+ self.all_time_outputs.append(output)
+ if na.abs(self.final_time - current_time) / self.final_time < 1e-4: break
+ current_time += self.parameters['dtDataDump']
+ index += 1
+
+ def _calculate_cycle_outputs(self):
+ "Calculate cycle outputs."
+
+ mylog.warn('Calculating cycle outputs. Dataset times will be unavailable.')
+
+ if self.stop_cycle is None or \
+ not 'CycleSkipDataDump' in self.parameters or \
+ self.parameters['CycleSkipDataDump'] <= 0.0: return []
+
+ self.all_time_outputs = []
+ index = 0
+ for cycle in range(0, self.stop_cycle+1, self.parameters['CycleSkipDataDump']):
+ filename = os.path.join(self.parameters['GlobalDir'],
+ "%s%04d" % (self.parameters['DataDumpDir'], index),
+ "%s%04d" % (self.parameters['DataDumpName'], index))
+
+ output = {'index': index, 'filename': filename, 'cycle': cycle}
+ self.all_time_outputs.append(output)
+ index += 1
+
+ def _get_all_outputs(self):
+ "Get all potential datasets and combine into a time-sorted list."
+
+ if self.parameters['dtDataDump'] > 0 and \
+ self.parameters['CycleSkipDataDump'] > 0:
+ raise AmbiguousOutputs(self.parameter_filename)
+
+ # Get all time or cycle outputs.
+ if self.parameters['CycleSkipDataDump'] > 0:
+ self._calculate_cycle_outputs()
+ else:
+ self._calculate_time_outputs()
+
+ # Calculate times for redshift outputs.
+ self._calculate_redshift_dump_times()
+
+ self.all_outputs = self.all_time_outputs + self.all_redshift_outputs
+ if self.parameters['CycleSkipDataDump'] <= 0:
+ self.all_outputs.sort(key=lambda obj:obj['time'])
+
+ mylog.info("Total datasets: %d." % len(self.all_outputs))
+
+ def _calculate_simulation_bounds(self):
+ """
+ Figure out the starting and stopping time and redshift for the simulation.
+ """
+
+ if 'StopCycle' in self.parameters:
+ self.stop_cycle = self.parameters['StopCycle']
+
+ # Convert initial/final redshifts to times.
+ if self.cosmological_simulation:
+ # Instantiate EnzoCosmology object for units and time conversions.
+ self.enzo_cosmology = EnzoCosmology(HubbleConstantNow=
+ (100.0 * self.parameters['CosmologyHubbleConstantNow']),
+ OmegaMatterNow=self.parameters['CosmologyOmegaMatterNow'],
+ OmegaLambdaNow=self.parameters['CosmologyOmegaLambdaNow'],
+ InitialRedshift=self.parameters['CosmologyInitialRedshift'])
+ self.initial_time = self.enzo_cosmology.ComputeTimeFromRedshift(self.initial_redshift) / \
+ self.enzo_cosmology.TimeUnits
+ self.final_time = self.enzo_cosmology.ComputeTimeFromRedshift(self.final_redshift) / \
+ self.enzo_cosmology.TimeUnits
+
+ # If not a cosmology simulation, figure out the stopping criteria.
+ else:
+ if 'InitialTime' in self.parameters:
+ self.initial_time = self.parameters['InitialTime']
+ else:
+ self.initial_time = 0.
+
+ if 'StopTime' in self.parameters:
+ self.final_time = self.parameters['StopTime']
+ else:
+ self.final_time = None
+ if not ('StopTime' in self.parameters or
+ 'StopCycle' in self.parameters):
+ raise NoStoppingCondition(self.parameter_filename)
+ if self.final_time is None:
+ mylog.warn('Simulation %s has no stop time set, stopping condition will be based only on cycles.' %
+ self.parameter_filename)
+
+ def _set_parameter_defaults(self):
+ "Set some default parameters to avoid problems if they are not in the parameter file."
+
+ self.parameters['GlobalDir'] = "."
+ self.parameters['DataDumpName'] = "data"
+ self.parameters['DataDumpDir'] = "DD"
+ self.parameters['RedshiftDumpName'] = "RedshiftOutput"
+ self.parameters['RedshiftDumpDir'] = "RD"
+ self.parameters['ComovingCoordinates'] = 0
+ self.parameters['TopGridRank'] = 3
+ self.parameters['DomainLeftEdge'] = na.zeros(self.parameters['TopGridRank'])
+ self.parameters['DomainRightEdge'] = na.ones(self.parameters['TopGridRank'])
+ self.parameters['Refineby'] = 2 # technically not the enzo default
+ self.parameters['StopCycle'] = 100000
+ self.parameters['dtDataDump'] = 0.
+ self.parameters['CycleSkipDataDump'] = 0.
+ self.parameters['TimeUnits'] = 1.
+
+ def _set_time_units(self):
+ """
+ Set up a dictionary of time units conversions.
+ """
+
+ self.time_units = {}
+ if self.cosmological_simulation:
+ self.parameters['TimeUnits'] = 2.52e17 / na.sqrt(self.omega_matter) \
+ / self.hubble_constant / (1 + self.initial_redshift)**1.5
+ self.time_units['1'] = 1.
+ self.time_units['seconds'] = self.parameters['TimeUnits']
+ self.time_units['years'] = self.time_units['seconds'] / (365*3600*24.0)
+ self.time_units['days'] = self.time_units['seconds'] / (3600*24.0)
+ self.time_units['Myr'] = self.time_units['years'] / 1.0e6
+ self.time_units['Gyr'] = self.time_units['years'] / 1.0e9
+
+ def _find_outputs(self):
+ """
+ Search for directories matching the data dump keywords.
+ If found, get dataset times py opening the pf.
+ """
+
+ # look for time outputs.
+ potential_outputs = glob.glob(os.path.join(self.parameters['GlobalDir'],
+ "%s*" % self.parameters['DataDumpDir'])) + \
+ glob.glob(os.path.join(self.parameters['GlobalDir'],
+ "%s*" % self.parameters['RedshiftDumpDir']))
+ time_outputs = []
+ mylog.info("Checking %d potential time outputs." %
+ len(potential_outputs))
+
+ for output in potential_outputs:
+ if self.parameters['DataDumpDir'] in output:
+ dir_key = self.parameters['DataDumpDir']
+ output_key = self.parameters['DataDumpName']
+ else:
+ dir_key = self.parameters['RedshiftDumpDir']
+ output_key = self.parameters['RedshiftDumpName']
+ index = output[output.find(dir_key) + len(dir_key):]
+ filename = os.path.join(self.parameters['GlobalDir'],
+ "%s%s" % (dir_key, index),
+ "%s%s" % (output_key, index))
+ if os.path.exists(filename):
+ pf = load(filename)
+ if pf is not None:
+ time_outputs.append({'filename': filename, 'time': pf.current_time})
+ if pf.cosmological_simulation:
+ time_outputs[-1]['redshift'] = pf.current_redshift
+ del pf
+ mylog.info("Located %d time outputs." % len(time_outputs))
+ time_outputs.sort(key=lambda obj: obj['time'])
+ return time_outputs
+
+ def _get_outputs_by_key(self, key, values, tolerance=None, outputs=None):
+ r"""Get datasets at or near to given values.
+
+ Parameters
+ ----------
+ key: str
+ The key by which to retrieve outputs, usually 'time' or
+ 'redshift'.
+ values: array_like
+ A list of values, given as floats.
+ tolerance : float
+ If not None, do not return a dataset unless the value is
+ within the tolerance value. If None, simply return the
+ nearest dataset.
+ Default: None.
+ outputs : list
+ The list of outputs from which to choose. If None,
+ self.all_outputs is used.
+ Default: None.
+
+ Examples
+ --------
+ >>> datasets = es.get_outputs_by_key('redshift', [0, 1, 2], tolerance=0.1)
+
+ """
+
+ values = ensure_list(values)
+ if outputs is None:
+ outputs = self.all_outputs
+ my_outputs = []
+ for value in values:
+ outputs.sort(key=lambda obj:na.fabs(value - obj[key]))
+ if (tolerance is None or na.abs(value - outputs[0][key]) <= tolerance) \
+ and outputs[0] not in my_outputs:
+ my_outputs.append(outputs[0])
+ else:
+ mylog.error("No dataset added for %s = %f." % (key, value))
+
+ outputs.sort(key=lambda obj: obj['time'])
+ return my_outputs
+
+ def _get_outputs_by_redshift(self, redshifts, tolerance=None, outputs=None):
+ r"""Get datasets at or near to given redshifts.
+
+ Parameters
+ ----------
+ redshifts: array_like
+ A list of redshifts, given as floats.
+ tolerance : float
+ If not None, do not return a dataset unless the value is
+ within the tolerance value. If None, simply return the
+ nearest dataset.
+ Default: None.
+ outputs : list
+ The list of outputs from which to choose. If None,
+ self.all_outputs is used.
+ Default: None.
+
+ Examples
+ --------
+ >>> datasets = es.get_outputs_by_redshift([0, 1, 2], tolerance=0.1)
+
+ """
+
+ return self._get_outputs_by_key('redshift', redshifts, tolerance=tolerance,
+ outputs=outputs)
+
+ def _get_outputs_by_time(self, times, tolerance=None, outputs=None,
+ time_units='1'):
+ r"""Get datasets at or near to given times.
+
+ Parameters
+ ----------
+ times: array_like
+ A list of times, given in code units as floats.
+ tolerance : float
+ If not None, do not return a dataset unless the time is
+ within the tolerance value. If None, simply return the
+ nearest dataset.
+ Default = None.
+ outputs : list
+ The list of outputs from which to choose. If None,
+ self.all_outputs is used.
+ Default: None.
+ time_units : str
+ The units of the list of times.
+ Default: '1' (code units).
+
+ Examples
+ --------
+ >>> datasets = es.get_outputs_by_time([600, 500, 400], tolerance=10.)
+
+ """
+
+ times = na.array(times) / self.time_units[time_units]
+ return self._get_outputs_by_key('time', times, tolerance=tolerance,
+ outputs=outputs)
+
+class MissingParameter(YTException):
+ def __init__(self, pf, parameter):
+ YTException.__init__(self, pf)
+ self.parameter = parameter
+
+ def __str__(self):
+ return "Parameter file %s is missing %s parameter." % \
+ (self.pf, self.parameter)
+
+class NoStoppingCondition(YTException):
+ def __init__(self, pf):
+ YTException.__init__(self, pf)
+
+ def __str__(self):
+ return "Simulation %s has no stopping condition. StopTime or StopCycle should be set." % \
+ self.pf
+
+class AmbiguousOutputs(YTException):
+ def __init__(self, pf):
+ YTException.__init__(self, pf)
+
+ def __str__(self):
+ return "Simulation %s has both dtDataDump and CycleSkipDataDump set. Unable to calculate datasets." % \
+ self.pf
+
diff -r a437280f3cefff3e7a41198438a5dfb7922f74e5 -r be3f7a60ad4c226f13181a9a3e99e42ec8d29008 yt/mods.py
--- a/yt/mods.py
+++ b/yt/mods.py
@@ -67,7 +67,8 @@
add_quantity, quantity_info
from yt.frontends.enzo.api import \
- EnzoStaticOutput, EnzoStaticOutputInMemory, EnzoFieldInfo, \
+ EnzoStaticOutput, EnzoStaticOutputInMemory, \
+ EnzoSimulation, EnzoFieldInfo, \
add_enzo_field, add_enzo_1d_field, add_enzo_2d_field
from yt.frontends.castro.api import \
https://bitbucket.org/yt_analysis/yt/changeset/c99cc332c221/
changeset: c99cc332c221
branch: yt
user: MatthewTurk
date: 2012-06-02 14:03:25
summary: Merged in brittonsmith/yt (pull request #166)
affected #: 3 files
diff -r 63ff8d95dc5053e2b4811fea925fff04a5e7eb34 -r c99cc332c22114d8f64cf98623f8099193fdd1e8 yt/frontends/enzo/api.py
--- a/yt/frontends/enzo/api.py
+++ b/yt/frontends/enzo/api.py
@@ -38,6 +38,9 @@
EnzoStaticOutput, \
EnzoStaticOutputInMemory
+from .simulation_handling import \
+ EnzoSimulation
+
from .fields import \
EnzoFieldInfo, \
Enzo2DFieldInfo, \
diff -r 63ff8d95dc5053e2b4811fea925fff04a5e7eb34 -r c99cc332c22114d8f64cf98623f8099193fdd1e8 yt/frontends/enzo/simulation_handling.py
--- /dev/null
+++ b/yt/frontends/enzo/simulation_handling.py
@@ -0,0 +1,692 @@
+"""
+EnzoSimulation class and member functions.
+
+Author: Britton Smith <brittonsmith at gmail.com>
+Affiliation: Michigan State University
+Homepage: http://yt-project.org/
+License:
+ Copyright (C) 2008-2012 Britton Smith. 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 *
+
+import numpy as na
+import glob
+import os
+
+from yt.data_objects.time_series import \
+ TimeSeriesData
+from yt.utilities.cosmology import \
+ Cosmology, \
+ EnzoCosmology
+from yt.utilities.exceptions import \
+ YTException
+from yt.utilities.parallel_tools.parallel_analysis_interface import \
+ parallel_root_only
+
+from yt.convenience import \
+ load
+
+class EnzoSimulation(TimeSeriesData):
+ r"""Super class for performing the same operation over all data outputs in
+ a simulation from one redshift to another.
+ """
+ def __init__(self, parameter_filename):
+ r"""Initialize an Enzo Simulation object.
+
+ Upon creation, the parameter file is parsed and the time and redshift
+ are calculated and stored in all_outputs. A time units dictionary is
+ instantiated to allow for time outputs to be requested with physical
+ time units. The get_time_series can be used to generate a
+ TimeSeriesData object.
+
+ parameter_filename : str
+ The simulation parameter file.
+
+ Examples
+ --------
+ >>> from yt.mods import *
+ >>> es = ES.EnzoSimulation("my_simulation.par")
+ >>> print es.all_outputs
+
+ """
+ self.parameter_filename = parameter_filename
+ self.parameters = {}
+
+ # Set some parameter defaults.
+ self._set_parameter_defaults()
+ # Read the simulation parameter file.
+ self._parse_parameter_file()
+ # Set up time units dictionary.
+ self._set_time_units()
+
+ # Figure out the starting and stopping times and redshift.
+ self._calculate_simulation_bounds()
+ self.print_key_parameters()
+
+ # Get all possible datasets.
+ self._get_all_outputs()
+
+ def get_time_series(self, time_data=True, redshift_data=True,
+ initial_time=None, final_time=None, time_units='1',
+ initial_redshift=None, final_redshift=None,
+ initial_cycle=None, final_cycle=None,
+ times=None, redshifts=None, tolerance=None,
+ find_outputs=False, parallel=True):
+
+ """
+ Instantiate a TimeSeriesData object for a set of outputs.
+
+ If no additional keywords given, a TimeSeriesData object will be
+ created with all potential datasets created by the simulation.
+
+ Outputs can be gather by specifying a time or redshift range
+ (or combination of time and redshift), with a specific list of
+ times or redshifts, a range of cycle numbers (for cycle based
+ output), or by simply searching all subdirectories within the
+ simulation directory.
+
+ time_data : bool
+ Whether or not to include time outputs when gathering
+ datasets for time series.
+ Default: True.
+ redshift_data : bool
+ Whether or not to include redshift outputs when gathering
+ datasets for time series.
+ Default: True.
+ initial_time : float
+ The earliest time for outputs to be included. If None,
+ the initial time of the simulation is used. This can be
+ used in combination with either final_time or
+ final_redshift.
+ Default: None.
+ final_time : float
+ The latest time for outputs to be included. If None,
+ the final time of the simulation is used. This can be
+ used in combination with either initial_time or
+ initial_redshift.
+ Default: None.
+ times : array_like
+ A list of times for which outputs will be found.
+ Default: None.
+ time_units : str
+ The time units used for requesting outputs by time.
+ Default: '1' (code units).
+ initial_redshift : float
+ The earliest redshift for outputs to be included. If None,
+ the initial redshift of the simulation is used. This can be
+ used in combination with either final_time or
+ final_redshift.
+ Default: None.
+ final_time : float
+ The latest redshift for outputs to be included. If None,
+ the final redshift of the simulation is used. This can be
+ used in combination with either initial_time or
+ initial_redshift.
+ Default: None.
+ redshifts : array_like
+ A list of redshifts for which outputs will be found.
+ Default: None.
+ initial_cycle : float
+ The earliest cycle for outputs to be included. If None,
+ the initial cycle of the simulation is used. This can
+ only be used with final_cycle.
+ Default: None.
+ final_cycle : float
+ The latest cycle for outputs to be included. If None,
+ the final cycle of the simulation is used. This can
+ only be used in combination with initial_cycle.
+ Default: None.
+ tolerance : float
+ Used in combination with "times" or "redshifts" keywords,
+ this is the tolerance within which outputs are accepted
+ given the requested times or redshifts. If None, the
+ nearest output is always taken.
+ Default: None.
+ find_outputs : bool
+ If True, subdirectories within the GlobalDir directory are
+ searched one by one for datasets. Time and redshift
+ information are gathered by temporarily instantiating each
+ dataset. This can be used when simulation data was created
+ in a non-standard way, making it difficult to guess the
+ corresponding time and redshift information.
+ Default: False.
+ parallel : bool/int
+ If True, the generated TimeSeriesData will divide the work
+ such that a single processor works on each dataset. If an
+ integer is supplied, the work will be divided into that
+ number of jobs.
+ Default: True.
+
+ Examples
+ --------
+ >>> es.get_time_series(initial_redshift=10, final_time=13.7,
+ time_units='Gyr', redshift_data=False)
+
+ >>> es.get_time_series(redshifts=[3, 2, 1, 0])
+
+ >>> es.get_time_series(final_cycle=100000)
+
+ >>> es.get_time_series(find_outputs=True)
+
+ >>> # after calling get_time_series
+ >>> for pf in es.piter():
+ >>> pc = PlotCollection(pf, 'c')
+ >>> pc.add_projection('Density', 0)
+ >>> pc.save()
+
+ """
+
+ if (initial_redshift is not None or \
+ final_redshift is not None) and \
+ not self.cosmological_simulation:
+ mylog.error('An initial or final redshift has been given for a noncosmological simulation.')
+ return
+
+ if find_outputs:
+ my_outputs = self._find_outputs()
+
+ else:
+ if time_data and redshift_data:
+ my_all_outputs = self.all_outputs
+ elif time_data:
+ my_all_outputs = self.all_time_outputs
+ elif redshift_data:
+ my_all_outputs = self.all_redshift_outputs
+ else:
+ mylog.error('Both time_data and redshift_data are False.')
+ return
+
+ if times is not None:
+ my_outputs = self._get_outputs_by_time(times, tolerance=tolerance,
+ outputs=my_all_outputs,
+ time_units=time_units)
+
+ elif redshifts is not None:
+ my_outputs = self._get_outputs_by_redshift(redshifts, tolerance=tolerance,
+ outputs=my_all_outputs)
+
+ elif initial_cycle is not None or final_cycle is not None:
+ if initial_cycle is None:
+ initial_cycle = 0
+ else:
+ initial_cycle = max(initial_cycle, 0)
+ if final_cycle is None:
+ final_cycle = self.parameters['StopCycle']
+ else:
+ final_cycle = min(final_cycle, self.parameters['StopCycle'])
+ my_outputs = my_all_outputs[int(ceil(float(initial_cycle) /
+ self.parameters['CycleSkipDataDump'])):
+ (final_cycle / self.parameters['CycleSkipDataDump'])+1]
+
+ else:
+ if initial_time is not None:
+ my_initial_time = initial_time / self.time_units[time_units]
+ elif initial_redshift is not None:
+ my_initial_time = self.enzo_cosmology.ComputeTimeFromRedshift(initial_redshift) / \
+ self.enzo_cosmology.TimeUnits
+ else:
+ my_initial_time = self.initial_time
+
+ if final_time is not None:
+ my_final_time = final_time / self.time_units[time_units]
+ elif final_redshift is not None:
+ my_final_time = self.enzo_cosmology.ComputeTimeFromRedshift(final_redshift) / \
+ self.enzo_cosmology.TimeUnits
+ else:
+ my_final_time = self.final_time
+
+ my_times = na.array(map(lambda a:a['time'], my_all_outputs))
+ my_indices = na.digitize([my_initial_time, my_final_time], my_times)
+ if my_initial_time == my_times[my_indices[0] - 1]: my_indices[0] -= 1
+ my_outputs = my_all_outputs[my_indices[0]:my_indices[1]]
+
+ TimeSeriesData.__init__(self, outputs=[output['filename'] for output in my_outputs],
+ parallel=parallel)
+ mylog.info("%d outputs loaded into time series." % len(my_outputs))
+
+ @parallel_root_only
+ def print_key_parameters(self):
+ """
+ Print out some key parameters for the simulation.
+ """
+ for a in ["domain_dimensions", "domain_left_edge",
+ "domain_right_edge", "initial_time", "final_time",
+ "stop_cycle", "cosmological_simulation"]:
+ if not hasattr(self, a):
+ mylog.error("Missing %s in parameter file definition!", a)
+ continue
+ v = getattr(self, a)
+ mylog.info("Parameters: %-25s = %s", a, v)
+ if hasattr(self, "cosmological_simulation") and \
+ getattr(self, "cosmological_simulation"):
+ for a in ["omega_lambda", "omega_matter",
+ "hubble_constant", "initial_redshift",
+ "final_redshift"]:
+ if not hasattr(self, a):
+ mylog.error("Missing %s in parameter file definition!", a)
+ continue
+ v = getattr(self, a)
+ mylog.info("Parameters: %-25s = %s", a, v)
+
+ def _parse_parameter_file(self):
+ """
+ Parses the parameter file and establishes the various
+ dictionaries.
+ """
+
+ self.conversion_factors = {}
+ redshift_outputs = []
+
+ # Let's read the file
+ lines = open(self.parameter_filename).readlines()
+ for line in (l.strip() for l in lines):
+ if '#' in line: line = line[0:line.find('#')]
+ if '//' in line: line = line[0:line.find('//')]
+ if len(line) < 2: continue
+ param, vals = (i.strip() for i in line.split("="))
+ # First we try to decipher what type of value it is.
+ vals = vals.split()
+ # Special case approaching.
+ if "(do" in vals: vals = vals[:1]
+ if len(vals) == 0:
+ pcast = str # Assume NULL output
+ else:
+ v = vals[0]
+ # Figure out if it's castable to floating point:
+ try:
+ float(v)
+ except ValueError:
+ pcast = str
+ else:
+ if any("." in v or "e+" in v or "e-" in v for v in vals):
+ pcast = float
+ elif v == "inf":
+ pcast = str
+ else:
+ pcast = int
+ # Now we figure out what to do with it.
+ if param.endswith("Units") and not param.startswith("Temperature"):
+ dataType = param[:-5]
+ # This one better be a float.
+ self.conversion_factors[dataType] = float(vals[0])
+ if param.startswith("CosmologyOutputRedshift["):
+ index = param[param.find("[")+1:param.find("]")]
+ redshift_outputs.append({'index':int(index), 'redshift':float(vals[0])})
+ elif len(vals) == 0:
+ vals = ""
+ elif len(vals) == 1:
+ vals = pcast(vals[0])
+ else:
+ vals = na.array([pcast(i) for i in vals if i != "-99999"])
+ self.parameters[param] = vals
+ self.refine_by = self.parameters["RefineBy"]
+ self.dimensionality = self.parameters["TopGridRank"]
+ if self.dimensionality > 1:
+ self.domain_dimensions = self.parameters["TopGridDimensions"]
+ if len(self.domain_dimensions) < 3:
+ tmp = self.domain_dimensions.tolist()
+ tmp.append(1)
+ self.domain_dimensions = na.array(tmp)
+ self.domain_left_edge = na.array(self.parameters["DomainLeftEdge"],
+ "float64").copy()
+ self.domain_right_edge = na.array(self.parameters["DomainRightEdge"],
+ "float64").copy()
+ else:
+ self.domain_left_edge = na.array(self.parameters["DomainLeftEdge"],
+ "float64")
+ self.domain_right_edge = na.array(self.parameters["DomainRightEdge"],
+ "float64")
+ self.domain_dimensions = na.array([self.parameters["TopGridDimensions"],1,1])
+
+ if self.parameters["ComovingCoordinates"]:
+ cosmo_attr = {'omega_lambda': 'CosmologyOmegaLambdaNow',
+ 'omega_matter': 'CosmologyOmegaMatterNow',
+ 'hubble_constant': 'CosmologyHubbleConstantNow',
+ 'initial_redshift': 'CosmologyInitialRedshift',
+ 'final_redshift': 'CosmologyFinalRedshift'}
+ self.cosmological_simulation = 1
+ for a, v in cosmo_attr.items():
+ if not v in self.parameters:
+ raise MissingParameter(self.parameter_filename, v)
+ setattr(self, a, self.parameters[v])
+ else:
+ self.omega_lambda = self.omega_matter = \
+ self.hubble_constant = self.cosmological_simulation = 0.0
+
+ # make list of redshift outputs
+ self.all_redshift_outputs = []
+ if not self.cosmological_simulation: return
+ for output in redshift_outputs:
+ output['filename'] = os.path.join(self.parameters['GlobalDir'],
+ "%s%04d" % (self.parameters['RedshiftDumpDir'],
+ output['index']),
+ "%s%04d" % (self.parameters['RedshiftDumpName'],
+ output['index']))
+ del output['index']
+ self.all_redshift_outputs = redshift_outputs
+
+ def _calculate_redshift_dump_times(self):
+ "Calculates time from redshift of redshift outputs."
+
+ if not self.cosmological_simulation: return
+ for output in self.all_redshift_outputs:
+ output['time'] = self.enzo_cosmology.ComputeTimeFromRedshift(output['redshift']) / \
+ self.enzo_cosmology.TimeUnits
+
+ def _calculate_time_outputs(self):
+ "Calculate time outputs and their redshifts if cosmological."
+
+ if self.final_time is None or \
+ not 'dtDataDump' in self.parameters or \
+ self.parameters['dtDataDump'] <= 0.0: return []
+
+ self.all_time_outputs = []
+ index = 0
+ current_time = self.initial_time
+ while current_time <= self.final_time + self.parameters['dtDataDump']:
+ filename = os.path.join(self.parameters['GlobalDir'],
+ "%s%04d" % (self.parameters['DataDumpDir'], index),
+ "%s%04d" % (self.parameters['DataDumpName'], index))
+
+ output = {'index': index, 'filename': filename, 'time': current_time}
+ output['time'] = min(output['time'], self.final_time)
+ if self.cosmological_simulation:
+ output['redshift'] = self.enzo_cosmology.ComputeRedshiftFromTime(
+ current_time * self.enzo_cosmology.TimeUnits)
+
+ self.all_time_outputs.append(output)
+ if na.abs(self.final_time - current_time) / self.final_time < 1e-4: break
+ current_time += self.parameters['dtDataDump']
+ index += 1
+
+ def _calculate_cycle_outputs(self):
+ "Calculate cycle outputs."
+
+ mylog.warn('Calculating cycle outputs. Dataset times will be unavailable.')
+
+ if self.stop_cycle is None or \
+ not 'CycleSkipDataDump' in self.parameters or \
+ self.parameters['CycleSkipDataDump'] <= 0.0: return []
+
+ self.all_time_outputs = []
+ index = 0
+ for cycle in range(0, self.stop_cycle+1, self.parameters['CycleSkipDataDump']):
+ filename = os.path.join(self.parameters['GlobalDir'],
+ "%s%04d" % (self.parameters['DataDumpDir'], index),
+ "%s%04d" % (self.parameters['DataDumpName'], index))
+
+ output = {'index': index, 'filename': filename, 'cycle': cycle}
+ self.all_time_outputs.append(output)
+ index += 1
+
+ def _get_all_outputs(self):
+ "Get all potential datasets and combine into a time-sorted list."
+
+ if self.parameters['dtDataDump'] > 0 and \
+ self.parameters['CycleSkipDataDump'] > 0:
+ raise AmbiguousOutputs(self.parameter_filename)
+
+ # Get all time or cycle outputs.
+ if self.parameters['CycleSkipDataDump'] > 0:
+ self._calculate_cycle_outputs()
+ else:
+ self._calculate_time_outputs()
+
+ # Calculate times for redshift outputs.
+ self._calculate_redshift_dump_times()
+
+ self.all_outputs = self.all_time_outputs + self.all_redshift_outputs
+ if self.parameters['CycleSkipDataDump'] <= 0:
+ self.all_outputs.sort(key=lambda obj:obj['time'])
+
+ mylog.info("Total datasets: %d." % len(self.all_outputs))
+
+ def _calculate_simulation_bounds(self):
+ """
+ Figure out the starting and stopping time and redshift for the simulation.
+ """
+
+ if 'StopCycle' in self.parameters:
+ self.stop_cycle = self.parameters['StopCycle']
+
+ # Convert initial/final redshifts to times.
+ if self.cosmological_simulation:
+ # Instantiate EnzoCosmology object for units and time conversions.
+ self.enzo_cosmology = EnzoCosmology(HubbleConstantNow=
+ (100.0 * self.parameters['CosmologyHubbleConstantNow']),
+ OmegaMatterNow=self.parameters['CosmologyOmegaMatterNow'],
+ OmegaLambdaNow=self.parameters['CosmologyOmegaLambdaNow'],
+ InitialRedshift=self.parameters['CosmologyInitialRedshift'])
+ self.initial_time = self.enzo_cosmology.ComputeTimeFromRedshift(self.initial_redshift) / \
+ self.enzo_cosmology.TimeUnits
+ self.final_time = self.enzo_cosmology.ComputeTimeFromRedshift(self.final_redshift) / \
+ self.enzo_cosmology.TimeUnits
+
+ # If not a cosmology simulation, figure out the stopping criteria.
+ else:
+ if 'InitialTime' in self.parameters:
+ self.initial_time = self.parameters['InitialTime']
+ else:
+ self.initial_time = 0.
+
+ if 'StopTime' in self.parameters:
+ self.final_time = self.parameters['StopTime']
+ else:
+ self.final_time = None
+ if not ('StopTime' in self.parameters or
+ 'StopCycle' in self.parameters):
+ raise NoStoppingCondition(self.parameter_filename)
+ if self.final_time is None:
+ mylog.warn('Simulation %s has no stop time set, stopping condition will be based only on cycles.' %
+ self.parameter_filename)
+
+ def _set_parameter_defaults(self):
+ "Set some default parameters to avoid problems if they are not in the parameter file."
+
+ self.parameters['GlobalDir'] = "."
+ self.parameters['DataDumpName'] = "data"
+ self.parameters['DataDumpDir'] = "DD"
+ self.parameters['RedshiftDumpName'] = "RedshiftOutput"
+ self.parameters['RedshiftDumpDir'] = "RD"
+ self.parameters['ComovingCoordinates'] = 0
+ self.parameters['TopGridRank'] = 3
+ self.parameters['DomainLeftEdge'] = na.zeros(self.parameters['TopGridRank'])
+ self.parameters['DomainRightEdge'] = na.ones(self.parameters['TopGridRank'])
+ self.parameters['Refineby'] = 2 # technically not the enzo default
+ self.parameters['StopCycle'] = 100000
+ self.parameters['dtDataDump'] = 0.
+ self.parameters['CycleSkipDataDump'] = 0.
+ self.parameters['TimeUnits'] = 1.
+
+ def _set_time_units(self):
+ """
+ Set up a dictionary of time units conversions.
+ """
+
+ self.time_units = {}
+ if self.cosmological_simulation:
+ self.parameters['TimeUnits'] = 2.52e17 / na.sqrt(self.omega_matter) \
+ / self.hubble_constant / (1 + self.initial_redshift)**1.5
+ self.time_units['1'] = 1.
+ self.time_units['seconds'] = self.parameters['TimeUnits']
+ self.time_units['years'] = self.time_units['seconds'] / (365*3600*24.0)
+ self.time_units['days'] = self.time_units['seconds'] / (3600*24.0)
+ self.time_units['Myr'] = self.time_units['years'] / 1.0e6
+ self.time_units['Gyr'] = self.time_units['years'] / 1.0e9
+
+ def _find_outputs(self):
+ """
+ Search for directories matching the data dump keywords.
+ If found, get dataset times py opening the pf.
+ """
+
+ # look for time outputs.
+ potential_outputs = glob.glob(os.path.join(self.parameters['GlobalDir'],
+ "%s*" % self.parameters['DataDumpDir'])) + \
+ glob.glob(os.path.join(self.parameters['GlobalDir'],
+ "%s*" % self.parameters['RedshiftDumpDir']))
+ time_outputs = []
+ mylog.info("Checking %d potential time outputs." %
+ len(potential_outputs))
+
+ for output in potential_outputs:
+ if self.parameters['DataDumpDir'] in output:
+ dir_key = self.parameters['DataDumpDir']
+ output_key = self.parameters['DataDumpName']
+ else:
+ dir_key = self.parameters['RedshiftDumpDir']
+ output_key = self.parameters['RedshiftDumpName']
+ index = output[output.find(dir_key) + len(dir_key):]
+ filename = os.path.join(self.parameters['GlobalDir'],
+ "%s%s" % (dir_key, index),
+ "%s%s" % (output_key, index))
+ if os.path.exists(filename):
+ pf = load(filename)
+ if pf is not None:
+ time_outputs.append({'filename': filename, 'time': pf.current_time})
+ if pf.cosmological_simulation:
+ time_outputs[-1]['redshift'] = pf.current_redshift
+ del pf
+ mylog.info("Located %d time outputs." % len(time_outputs))
+ time_outputs.sort(key=lambda obj: obj['time'])
+ return time_outputs
+
+ def _get_outputs_by_key(self, key, values, tolerance=None, outputs=None):
+ r"""Get datasets at or near to given values.
+
+ Parameters
+ ----------
+ key: str
+ The key by which to retrieve outputs, usually 'time' or
+ 'redshift'.
+ values: array_like
+ A list of values, given as floats.
+ tolerance : float
+ If not None, do not return a dataset unless the value is
+ within the tolerance value. If None, simply return the
+ nearest dataset.
+ Default: None.
+ outputs : list
+ The list of outputs from which to choose. If None,
+ self.all_outputs is used.
+ Default: None.
+
+ Examples
+ --------
+ >>> datasets = es.get_outputs_by_key('redshift', [0, 1, 2], tolerance=0.1)
+
+ """
+
+ values = ensure_list(values)
+ if outputs is None:
+ outputs = self.all_outputs
+ my_outputs = []
+ for value in values:
+ outputs.sort(key=lambda obj:na.fabs(value - obj[key]))
+ if (tolerance is None or na.abs(value - outputs[0][key]) <= tolerance) \
+ and outputs[0] not in my_outputs:
+ my_outputs.append(outputs[0])
+ else:
+ mylog.error("No dataset added for %s = %f." % (key, value))
+
+ outputs.sort(key=lambda obj: obj['time'])
+ return my_outputs
+
+ def _get_outputs_by_redshift(self, redshifts, tolerance=None, outputs=None):
+ r"""Get datasets at or near to given redshifts.
+
+ Parameters
+ ----------
+ redshifts: array_like
+ A list of redshifts, given as floats.
+ tolerance : float
+ If not None, do not return a dataset unless the value is
+ within the tolerance value. If None, simply return the
+ nearest dataset.
+ Default: None.
+ outputs : list
+ The list of outputs from which to choose. If None,
+ self.all_outputs is used.
+ Default: None.
+
+ Examples
+ --------
+ >>> datasets = es.get_outputs_by_redshift([0, 1, 2], tolerance=0.1)
+
+ """
+
+ return self._get_outputs_by_key('redshift', redshifts, tolerance=tolerance,
+ outputs=outputs)
+
+ def _get_outputs_by_time(self, times, tolerance=None, outputs=None,
+ time_units='1'):
+ r"""Get datasets at or near to given times.
+
+ Parameters
+ ----------
+ times: array_like
+ A list of times, given in code units as floats.
+ tolerance : float
+ If not None, do not return a dataset unless the time is
+ within the tolerance value. If None, simply return the
+ nearest dataset.
+ Default = None.
+ outputs : list
+ The list of outputs from which to choose. If None,
+ self.all_outputs is used.
+ Default: None.
+ time_units : str
+ The units of the list of times.
+ Default: '1' (code units).
+
+ Examples
+ --------
+ >>> datasets = es.get_outputs_by_time([600, 500, 400], tolerance=10.)
+
+ """
+
+ times = na.array(times) / self.time_units[time_units]
+ return self._get_outputs_by_key('time', times, tolerance=tolerance,
+ outputs=outputs)
+
+class MissingParameter(YTException):
+ def __init__(self, pf, parameter):
+ YTException.__init__(self, pf)
+ self.parameter = parameter
+
+ def __str__(self):
+ return "Parameter file %s is missing %s parameter." % \
+ (self.pf, self.parameter)
+
+class NoStoppingCondition(YTException):
+ def __init__(self, pf):
+ YTException.__init__(self, pf)
+
+ def __str__(self):
+ return "Simulation %s has no stopping condition. StopTime or StopCycle should be set." % \
+ self.pf
+
+class AmbiguousOutputs(YTException):
+ def __init__(self, pf):
+ YTException.__init__(self, pf)
+
+ def __str__(self):
+ return "Simulation %s has both dtDataDump and CycleSkipDataDump set. Unable to calculate datasets." % \
+ self.pf
+
diff -r 63ff8d95dc5053e2b4811fea925fff04a5e7eb34 -r c99cc332c22114d8f64cf98623f8099193fdd1e8 yt/mods.py
--- a/yt/mods.py
+++ b/yt/mods.py
@@ -67,7 +67,8 @@
add_quantity, quantity_info
from yt.frontends.enzo.api import \
- EnzoStaticOutput, EnzoStaticOutputInMemory, EnzoFieldInfo, \
+ EnzoStaticOutput, EnzoStaticOutputInMemory, \
+ EnzoSimulation, EnzoFieldInfo, \
add_enzo_field, add_enzo_1d_field, add_enzo_2d_field
from yt.frontends.castro.api import \
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