[yt-svn] commit/yt: MatthewTurk: Merged in jzuhone/yt/yt-3.0 (pull request #1053)
commits-noreply at bitbucket.org
commits-noreply at bitbucket.org
Thu Jul 24 04:50:05 PDT 2014
1 new commit in yt:
https://bitbucket.org/yt_analysis/yt/commits/1ba67463a525/
Changeset: 1ba67463a525
Branch: yt-3.0
User: MatthewTurk
Date: 2014-07-24 13:49:55
Summary: Merged in jzuhone/yt/yt-3.0 (pull request #1053)
Derived field documentation
Affected #: 4 files
diff -r f8f6cf1c1415a65032655b9b85f7e52eff1afef4 -r 1ba67463a5253d18d1767f1f06e96180078aca62 doc/source/analyzing/analysis_modules/photon_simulator.rst
--- a/doc/source/analyzing/analysis_modules/photon_simulator.rst
+++ b/doc/source/analyzing/analysis_modules/photon_simulator.rst
@@ -35,6 +35,11 @@
We'll demonstrate the functionality on a realistic dataset of a galaxy
cluster to get you started.
+.. note::
+
+ Currently, the ``photon_simulator`` analysis module only works with grid-based
+ data.
+
Creating an X-ray observation of a dataset on disk
++++++++++++++++++++++++++++++++++++++++++++++++++
diff -r f8f6cf1c1415a65032655b9b85f7e52eff1afef4 -r 1ba67463a5253d18d1767f1f06e96180078aca62 doc/source/analyzing/analysis_modules/synthetic_observation.rst
--- a/doc/source/analyzing/analysis_modules/synthetic_observation.rst
+++ b/doc/source/analyzing/analysis_modules/synthetic_observation.rst
@@ -16,6 +16,5 @@
star_analysis
xray_emission_fields
sunyaev_zeldovich
- radial_column_density
photon_simulator
ppv_cubes
diff -r f8f6cf1c1415a65032655b9b85f7e52eff1afef4 -r 1ba67463a5253d18d1767f1f06e96180078aca62 doc/source/analyzing/creating_derived_fields.rst
--- a/doc/source/analyzing/creating_derived_fields.rst
+++ b/doc/source/analyzing/creating_derived_fields.rst
@@ -11,7 +11,7 @@
So once a new field has been conceived of, the best way to create it is to
construct a function that performs an array operation -- operating on a
-collection of data, neutral to its size, shape, and type. (All fields should
+collection of data, neutral to its size, shape, and type. (All fields should
be provided as 64-bit floats.)
A simple example of this is the pressure field, which demonstrates the ease of
@@ -19,11 +19,13 @@
.. code-block:: python
- def _Pressure(field, data):
+ import yt
+
+ def _pressure(field, data):
return (data.ds.gamma - 1.0) * \
data["density"] * data["thermal_energy"]
-Note that we do a couple different things here. We access the "Gamma"
+Note that we do a couple different things here. We access the "gamma"
parameter from the dataset, we access the "density" field and we access
the "thermal_energy" field. "thermal_energy" is, in fact, another derived field!
("thermal_energy" deals with the distinction in storage of energy between dual
@@ -37,247 +39,123 @@
.. code-block:: python
- add_field("pressure", function=_Pressure, units=r"\rm{dyne}/\rm{cm}^{2}")
+ yt.add_field("pressure", function=_pressure, units="dyne/cm**2")
We feed it the name of the field, the name of the function, and the
-units. Note that the units parameter is a "raw" string, with some
-LaTeX-style formatting -- Matplotlib actually has a MathText rendering
-engine, so if you include LaTeX it will be rendered appropriately.
+units. Note that the units parameter is a "raw" string, in the format that ``yt`` uses
+in its `symbolic units implementation <units>`_ (e.g., employing only unit names, numbers,
+and mathematical operators in the string, and using ``"**"`` for exponentiation). We suggest
+that you name the function that creates a derived field with the intended field name prefixed
+by a single underscore, as in the ``_pressure`` example above.
-.. One very important thing to note about the call to ``add_field`` is
-.. that it **does not** need to specify the function name **if** the
-.. function is the name of the field prefixed with an underscore. If it
-.. is not -- and it won't be for fields in different units (such as
-.. "cell_mass") -- then you need to specify it with the argument
-.. ``function``.
+:func:`add_field` can be invoked in two other ways. The first is by the function
+decorator :func:`derived_field`. The following code is equivalent to the previous
+example:
-We suggest that you name the function that creates a derived field
-with the intended field name prefixed by a single underscore, as in
-the ``_Pressure`` example above.
+.. code-block:: python
+
+ from yt import derived_field
+
+ @derived_field(name="pressure", units="dyne/cm**2")
+ def _pressure(field, data):
+ return (data.ds.gamma - 1.0) * \
+ data["density"] * data["thermal_energy"]
+
+The :func:`derived_field` decorator takes the same arguments as :func:`add_field`,
+and is often a more convenient shorthand in cases where you want to quickly set up
+a new field.
+
+Defining derived fields in the above fashion must be done before a dataset is loaded,
+in order for the dataset to recognize it. If you want to set up a derived field after you
+have loaded a dataset, or if you only want to set up a derived field for a particular
+dataset, there is an :meth:`add_field` method that hangs off dataset objects. The calling
+syntax is the same:
+
+.. code-block:: python
+
+ ds = yt.load("GasSloshing/sloshing_nomag2_hdf5_plt_cnt_0100")
+ ds.add_field("pressure", function=_pressure, units="dyne/cm**2")
If you find yourself using the same custom-defined fields over and over, you
should put them in your plugins file as described in :ref:`plugin-file`.
-.. _conversion-factors:
+A More Complicated Example
+--------------------------
-Conversion Factors
-~~~~~~~~~~~~~~~~~~
-
-When creating a derived field, ``yt`` does not by default do unit
-conversion. All of the fields fed into the field are pre-supposed to
-be in CGS. If the field does not need any constants applied after
-that, you are done. If it does, you should define a second function
-that applies the proper multiple in order to return the desired units
-and use the argument ``convert_function`` to ``add_field`` to point to
-it.
-
-The argument that you pass to ``convert_function`` will be dependent on
-what fields are input into your derived field, and in what form they
-are passed from their native format. For enzo fields, nearly all the
-native on-disk fields are in CGS units already (except for ``dx``, ``dy``,
-and ``dz`` fields), so you typically only need to convert for
-off-standard fields taking into account where those fields are
-used in the final output derived field. For other codes, it can vary.
-
-You can check to see the units associated with any field in a dataset
-from any code by using the ``_units`` attribute. Here is an example
-with one of our sample FLASH datasets available publicly at
-http://yt-project.org/data :
+But what if we want to do something a bit more fancy? Here's an example of getting
+parameters from the data object and using those to define the field;
+specifically, here we obtain the ``center`` and ``bulk_velocity`` parameters
+and use those to define a field for radial velocity (there is already a ``"radial_velocity"``
+field in ``yt``, but we create this one here just as a transparent and simple example).
.. code-block:: python
- >>> from yt.mods import *
- >>> ds = load("GasSloshing/sloshing_nomag2_hdf5_plt_cnt_0100")
- >>> ds.field_list
- ['dens', 'temp', 'pres', 'gpot', 'divb', 'velx', 'vely', 'velz', 'magx', 'magy', 'magz', 'magp']
- >>> ds.field_info['dens']._units
- '\\rm{g}/\\rm{cm}^{3}'
- >>> ds.field_info['temp']._units
- '\\rm{K}'
- >>> ds.field_info['velx']._units
- '\\rm{cm}/\\rm{s}'
+ from yt.fields.api import ValidateParameter
+ import numpy as np
-Thus if you were using any of these fields as input to your derived field, you
-wouldn't have to worry about unit conversion because they're already in CGS.
+ def _my_radial_velocity(field, data):
+ if data.has_field_parameter("bulk_velocity"):
+ bv = data.get_field_parameter("bulk_velocity").in_units("cm/s")
+ else:
+ bv = data.ds.arr(np.zeros(3), "cm/s")
+ xv = data["gas","velocity_x"] - bv[0]
+ yv = data["gas","velocity_y"] - bv[1]
+ zv = data["gas","velocity_z"] - bv[2]
+ center = data.get_field_parameter('center')
+ x_hat = data["x"] - center[0]
+ y_hat = data["y"] - center[1]
+ z_hat = data["z"] - center[2]
+ r = np.sqrt(x_hat*x_hat+y_hat*y_hat+z_hat*z_hat)
+ x_hat /= r
+ y_hat /= r
+ z_hat /= r
+ return xv*x_hat + yv*y_hat + zv*z_hat
+ yt.add_field("my_radial_velocity",
+ function=_my_radial_velocity,
+ units="cm/s",
+ take_log=False,
+ validators=[ValidateParameter('center'),
+ ValidateParameter('bulk_velocity')])
-Some More Complicated Examples
-------------------------------
-
-But what if we want to do some more fancy stuff? Here's an example of getting
-parameters from the data object and using those to define the field;
-specifically, here we obtain the ``center`` and ``height_vector`` parameters
-and use those to define an angle of declination of a point with respect to a
-disk.
+Note that we have added a few parameters below the main function; we specify
+that we do not wish to display this field as logged, that we require both
+``bulk_velocity`` and ``center`` to be present in a given data object we wish
+to calculate this for, and we say that it should not be displayed in a
+drop-down box of fields to display. This is done through the parameter
+*validators*, which accepts a list of :class:`FieldValidator` objects. These
+objects define the way in which the field is generated, and when it is able to
+be created. In this case, we mandate that parameters *center* and
+*bulk_velocity* are set before creating the field. These are set via
+:meth:`~yt.data_objects.data_containers.set_field_parameter`, which can
+be called on any object that has fields:
.. code-block:: python
- def _DiskAngle(field, data):
- # We make both r_vec and h_vec into unit vectors
- center = data.get_field_parameter("center")
- r_vec = np.array([data["x"] - center[0],
- data["y"] - center[1],
- data["z"] - center[2]])
- r_vec = r_vec/np.sqrt((r_vec**2.0).sum(axis=0))
- h_vec = np.array(data.get_field_parameter("height_vector"))
- dp = r_vec[0,:] * h_vec[0] \
- + r_vec[1,:] * h_vec[1] \
- + r_vec[2,:] * h_vec[2]
- return np.arccos(dp)
- add_field("DiskAngle", take_log=False,
- validators=[ValidateParameter("height_vector"),
- ValidateParameter("center")],
- display_field=False)
+ ds = yt.load("GasSloshing/sloshing_nomag2_hdf5_plt_cnt_0100")
+ sp = ds.sphere("max", (200.,"kpc"))
+ sp.set_field_parameter("bulk_velocity", yt.YTArray([-100.,200.,300.], "km/s"))
-Note that we have added a few parameters below the main function; we specify
-that we do not wish to display this field as logged, that we require both
-``height_vector`` and ``center`` to be present in a given data object we wish
-to calculate this for, and we say that it should not be displayed in a
-drop-down box of fields to display. This is done through the parameter
-*validators*, which accepts a list of :class:`FieldValidator` objects. These
-objects define the way in which the field is generated, and when it is able to
-be created. In this case, we mandate that parameters *center* and
-*height_vector* are set before creating the field. These are set via
-:meth:`~yt.data_objects.data_containers.set_field_parameter`, which can
-be called on any object that has fields.
+In this case, we already know what the *center* of the sphere is, so we do not set it. Also,
+note that *center* and *bulk_velocity* need to be :class:`YTArray` objects with units.
-We can also define vector fields.
-
-.. code-block:: python
-
- def _SpecificAngularMomentum(field, data):
- if data.has_field_parameter("bulk_velocity"):
- bv = data.get_field_parameter("bulk_velocity")
- else: bv = np.zeros(3, dtype='float64')
- xv = data["velocity_x"] - bv[0]
- yv = data["velocity_y"] - bv[1]
- zv = data["velocity_z"] - bv[2]
- center = data.get_field_parameter('center')
- coords = np.array([data['x'],data['y'],data['z']], dtype='float64')
- new_shape = tuple([3] + [1]*(len(coords.shape)-1))
- r_vec = coords - np.reshape(center,new_shape)
- v_vec = np.array([xv,yv,zv], dtype='float64')
- return np.cross(r_vec, v_vec, axis=0)
- def _convertSpecificAngularMomentum(data):
- return data.convert("cm")
- add_field("SpecificAngularMomentum",
- convert_function=_convertSpecificAngularMomentum, vector_field=True,
- units=r"\rm{cm}^2/\rm{s}", validators=[ValidateParameter('center')])
-
-Here we define the SpecificAngularMomentum field, optionally taking a
-``bulk_velocity``, and returning a vector field that needs conversion by the
-function ``_convertSpecificAngularMomentum``.
-
-It is also possible to define fields that depend on spatial derivatives of
-other fields. Calculating the derivative for a single grid cell requires
-information about neighboring grid cells. Therefore, properly calculating
-a derivative for a cell on the edge of the grid will require cell values from
-neighboring grids. Below is an example of a field that is the divergence of the
-velocity.
-
-.. code-block:: python
-
- def _DivV(field, data):
- # We need to set up stencils
- if data.ds["HydroMethod"] == 2:
- sl_left = slice(None,-2,None)
- sl_right = slice(1,-1,None)
- div_fac = 1.0
- else:
- sl_left = slice(None,-2,None)
- sl_right = slice(2,None,None)
- div_fac = 2.0
- ds = div_fac * data['dx'].flat[0]
- f = data["velocity_x"][sl_right,1:-1,1:-1]/ds
- f -= data["velocity_x"][sl_left ,1:-1,1:-1]/ds
- if data.ds.dimensionality > 1:
- ds = div_fac * data['dy'].flat[0]
- f += data["velocity_y"][1:-1,sl_right,1:-1]/ds
- f -= data["velocity_y"][1:-1,sl_left ,1:-1]/ds
- if data.ds.dimensionality > 2:
- ds = div_fac * data['dz'].flat[0]
- f += data["velocity_z"][1:-1,1:-1,sl_right]/ds
- f -= data["velocity_z"][1:-1,1:-1,sl_left ]/ds
- new_field = np.zeros(data["velocity_x"].shape, dtype='float64')
- new_field[1:-1,1:-1,1:-1] = f
- return new_field
- def _convertDivV(data):
- return data.convert("cm")**-1.0
- add_field("DivV", function=_DivV,
- validators=[ValidateSpatial(ghost_zones=1,
- fields=["velocity_x","velocity_y","velocity_z"])],
- units=r"\rm{s}^{-1}", take_log=False,
- convert_function=_convertDivV)
-
-Note that *slice* is simply a native Python object used for taking slices of
-arrays or lists. Another :class:`FieldValidator` object, ``ValidateSpatial``
-is given in the list of *validators* in the call to ``add_field`` with
-*ghost_zones* = 1, specifying that the original grid be padded with one additional
-cell from the neighboring grids on all sides. The *fields* keyword simply
-mandates that the listed fields be present. With one ghost zone added to all sides
-of the grid, the data fields (data["velocity_x"], data["velocity_y"], and
-data["velocity_z"]) will have a shape of (NX+2, NY+2, NZ+2) inside of this function,
-where the original grid has dimension (NX, NY, NZ). However, when the final field
-data is returned, the ghost zones will be removed and the shape will again be
-(NX, NY, NZ).
-
-.. _derived-field-options:
-
-Saving Derived Fields
----------------------
-
-Complex fields can be time-consuming to generate, especially on large datasets.
-To mitigate this, ``yt`` provides a mechanism for saving fields to a backup file
-using the Grid Data Format. The next time you start yt, it will check this file
-and your field will be treated as native if present.
-
-The code below creates a new derived field called "Entr" and saves it to disk:
-
-.. code-block:: python
-
- from yt.mods import *
- from yt.utilities.grid_data_format import writer
-
- def _Entropy(field, data) :
- return data["temperature"]*data["density"]**(-2./3.)
- add_field("Entr", function=_Entropy)
-
- ds = load('GasSloshing/sloshing_nomag2_hdf5_plt_cnt_0100')
- writer.save_field(ds, "Entr")
-
-This creates a "_backup.gdf" file next to your datadump. If you load up the dataset again:
-
-.. code-block:: python
-
- from yt.mods import *
-
- ds = load('GasSloshing/sloshing_nomag2_hdf5_plt_cnt_0100')
- data = ds.all_data()
- print data["Entr"]
-
-you can work with the field exactly as before, without having to recompute it.
+Other examples for creating derived fields can be found in the cookbook recipes
+:ref:`cookbook-simple-derived-fields` and :ref:`cookbook-complex-derived-fields`.
Field Options
-------------
-The arguments to :func:`add_field` are passed on to the constructor of
-:class:`DerivedField`. :func:`add_field` takes care of finding the arguments
-`function` and `convert_function` if it can, however. There are a number of
-options available, but the only mandatory ones are ``name`` and possibly
-``function``.
+The arguments to :func:`add_field` are passed on to the constructor of :class:`DerivedField`.
+There are a number of options available, but the only mandatory ones are ``name``,
+``units``, and ``function``.
``name``
This is the name of the field -- how you refer to it. For instance,
- ``Pressure`` or ``H2I_Fraction``.
+ ``pressure`` or ``magnetic_field_strength``.
``function``
This is a function handle that defines the field
- ``convert_function``
- This is the function that converts the field to CGS. All inputs to this
- function are mandated to already *be* in CGS.
``units``
- This is a mathtext (LaTeX-like) string that describes the units.
- ``projected_units``
- This is a mathtext (LaTeX-like) string that describes the units if the
- field has been projected without a weighting.
+ This is a string that describes the units. Powers must be in
+ Python syntax (``**`` instead of ``^``).
``display_name``
This is a name used in the plots, for instance ``"Divergence of
Velocity"``. If not supplied, the ``name`` value is used.
@@ -289,43 +167,14 @@
``validators``
(*Advanced*) This is a list of :class:`FieldValidator` objects, for instance to mandate
spatial data.
- ``vector_field``
- (*Advanced*) Is this field more than one value per cell?
``display_field``
(*Advanced*) Should this field appear in the dropdown box in Reason?
``not_in_all``
(*Advanced*) If this is *True*, the field may not be in all the grids.
-
-How Do Units Work?
-------------------
-
-The best way to understand yt's unit system is to keep in mind that ``yt`` is really
-handling *two* unit systems: the internal unit system of the dataset and the
-physical (usually CGS) unit system. For simulation codes like FLASH and ORION
-that do all computations in CGS units internally, these two unit systems are the
-same. Most other codes do their calculations in a non-dimensionalized unit
-system chosen so that most primitive variables are as close to unity as
-possible. ``yt`` allows data access both in code units and physical units by
-providing a set of standard yt fields defined by all frontends.
-
-When a dataset is loaded, ``yt`` reads the conversion factors necessary convert the
-data to CGS units from the datafile itself or from a dictionary passed to the
-``load`` command. Raw on-disk fields are presented to the user via the string
-names used in the dataset. For a full enumeration of the known field names for
-each of the different frontends, see the :ref:`field-list`. In general, no
-conversion factors are applied to on-disk fields.
-
-To access data in physical CGS units, yt recognizes a number of 'universal'
-field names. All primitive fields (density, pressure, magnetic field strength,
-etc.) are mapped to Enzo field names, listed in the :ref:`enzo-field-names`.
-The reason Enzo field names are used here is because ``yt`` was originally written
-to only read Enzo data. In the future we will switch to a new system of
-universal field names - this will also make it much easier to access raw on-disk
-Enzo data!
-
-In addition to primitive fields, yt provides an extensive list of "universal"
-derived fields that are accessible from any of the frontends. For a full
-listing of the universal derived fields, see :ref:`universal-field-list`.
+ ``output_units``
+ (*Advanced*) For fields that exist on disk, which we may want to convert to other
+ fields or that get aliased to themselves, we can specify a different
+ desired output unit than the unit found on disk.
Units for Cosmological Datasets
-------------------------------
@@ -333,14 +182,13 @@
``yt`` has additional capabilities to handle the comoving coordinate system used
internally in cosmological simulations. Simulations that use comoving
coordinates, all length units have three other counterparts correspoding to
-comoving units, scaled comoving units, and scaled proper units. In all cases
-'scaled' units refer to scaling by the reduced Hubble constant - i.e. the length
-unit is what it would be in a universe where Hubble's constant is 100 km/s/Mpc.
+comoving units, scaled comoving units, and scaled proper units. In all cases
+'scaled' units refer to scaling by the reduced Hubble parameter - i.e. the length
+unit is what it would be in a universe where Hubble's parameter is 100 km/s/Mpc.
-To access these different units, yt has a common naming system. Scaled units
-are denoted by appending ``h`` to the end of the unit name. Comoving units are
-denoted by appending ``cm`` to the end of the unit name. If both are used, the
-strings should be appended in that order: 'Mpchcm', *but not* 'Mpccmh'.
+To access these different units, yt has a common naming system. Scaled units are denoted by
+dividing by the scaled Hubble parameter ``h`` (which is in itself a unit). Comoving
+units are denoted by appending ``cm`` to the end of the unit name.
Using the parsec as an example,
@@ -350,28 +198,10 @@
``pccm``
Comoving parsecs, :math:`\rm{pc}/(1+z)`.
-``pchcm``
+``pccm/h``
Comoving parsecs normalized by the scaled hubble constant, :math:`\rm{pc}/h/(1+z)`.
-``pch``
+``pc/h``
Proper parsecs, normalized by the scaled hubble constant, :math:`\rm{pc}/h`.
-Which Enzo Field names Does ``yt`` Know About?
-----------------------------------------------
-
-These are the names of primitive fields in the Enzo AMR code. ``yt`` was originally
-written to analyze Enzo data so the default field names used by the various
-frontends are the same as Enzo fields.
-
-.. note::
-
- Enzo field names are *universal* yt fields. All frontends define conversions
- to Enzo fields. Enzo fields are always in CGS.
-
-* Density
-* Temperature
-* Gas Energy
-* Total Energy
-* [xyz]-velocity
-* Species fields: HI, HII, Electron, HeI, HeII, HeIII, HM, H2I, H2II, DI, DII, HDI
-* Particle mass, velocity,
+Further examples of this functionality are shown in :ref:`comoving_units_and_code_units`.
diff -r f8f6cf1c1415a65032655b9b85f7e52eff1afef4 -r 1ba67463a5253d18d1767f1f06e96180078aca62 doc/source/cookbook/calculating_information.rst
--- a/doc/source/cookbook/calculating_information.rst
+++ b/doc/source/cookbook/calculating_information.rst
@@ -58,6 +58,8 @@
.. yt_cookbook:: time_series.py
+.. _cookbook-simple-derived-fields:
+
Simple Derived Fields
~~~~~~~~~~~~~~~~~~~~~
@@ -66,6 +68,8 @@
.. yt_cookbook:: derived_field.py
+.. _cookbook-complex-derived-fields:
+
Complex Derived Fields
~~~~~~~~~~~~~~~~~~~~~~
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