[yt-svn] commit/yt: 8 new changesets

commits-noreply at bitbucket.org commits-noreply at bitbucket.org
Fri Jul 11 10:01:25 PDT 2014


8 new commits in yt:

https://bitbucket.org/yt_analysis/yt/commits/94182bf98725/
Changeset:   94182bf98725
Branch:      yt-3.0
User:        ngoldbaum
Date:        2014-06-30 00:20:40
Summary:     Updating the plotting narrative docs.
Affected #:  9 files

diff -r 103131490fefcf01b2a7288ad246869fe853dd47 -r 94182bf987253d6d1cffc464e82a545bb1e64919 doc/source/cookbook/simple_plots.rst
--- a/doc/source/cookbook/simple_plots.rst
+++ b/doc/source/cookbook/simple_plots.rst
@@ -119,6 +119,8 @@
 
 .. yt_cookbook:: show_hide_axes_colorbar.py
 
+.. _matplotlib-primitives:
+
 Accessing and Modifying Plots Directly
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 

diff -r 103131490fefcf01b2a7288ad246869fe853dd47 -r 94182bf987253d6d1cffc464e82a545bb1e64919 doc/source/reference/api/api.rst
--- a/doc/source/reference/api/api.rst
+++ b/doc/source/reference/api/api.rst
@@ -15,6 +15,7 @@
    ~yt.visualization.plot_window.OffAxisSlicePlot
    ~yt.visualization.plot_window.ProjectionPlot
    ~yt.visualization.plot_window.OffAxisProjectionPlot
+   ~yt.visualization.plot_window.WindowPlotMPL
 
 ProfilePlot and PhasePlot
 ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -24,6 +25,7 @@
 
    ~yt.visualization.profile_plotter.ProfilePlot
    ~yt.visualization.profile_plotter.PhasePlot
+   ~yt.visualization.profile_plotter.PhasePlotMPL
 
 Fixed Resolution Pixelization
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

diff -r 103131490fefcf01b2a7288ad246869fe853dd47 -r 94182bf987253d6d1cffc464e82a545bb1e64919 doc/source/visualizing/_cb_docstrings.inc
--- a/doc/source/visualizing/_cb_docstrings.inc
+++ b/doc/source/visualizing/_cb_docstrings.inc
@@ -1,370 +1,416 @@
+Arrow callback
+~~~~~~~~~~~~~~
+
 .. function:: annotate_arrow(self, pos, code_size, plot_args=None):
 
-   (This is a proxy for :class:`~yt.visualization.plot_modifications.ArrowCallback`.)
+   (This is a proxy for
+   :class:`~yt.visualization.plot_modifications.ArrowCallback`.)
 
-   This adds an arrow pointing at *pos* with size
-   *code_size* in code units.  *plot_args* is a dict fed to
+   This adds an arrow pointing at ``pos`` with size
+   ``code_size`` in code units.  ``plot_args`` is a dict fed to
    matplotlib with arrow properties.
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   slc = SlicePlot(pf, 'z', 'density', width=(10,'kpc'), center='max')
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   slc = yt.SlicePlot(ds, 'z', 'density', width=(10,'kpc'), center='c')
    slc.annotate_arrow((0.5, 0.5, 0.5), (1, 'kpc'))
    slc.save()
 
--------------
+Clump Finder Callback
+~~~~~~~~~~~~~~~~~~~~~
 
 .. function:: annotate_clumps(self, clumps, plot_args=None):
 
-   (This is a proxy for :class:`~yt.visualization.plot_modifications.ClumpContourCallback`.)
+   (This is a proxy for
+   :class:`~yt.visualization.plot_modifications.ClumpContourCallback`.)
 
-   Take a list of *clumps* and plot them as a set of
+   Take a list of ``clumps`` and plot them as a set of
    contours.
 
 .. python-script::
 
-   from yt.mods import *
-   from yt.analysis_modules.level_sets.api import *
+   import yt
+   import numpy as np
+   from yt.analysis_modules.level_sets.api import \
+       Clump, find_clumps, get_lowest_clumps
 
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   data_source = pf.disk([0.5, 0.5, 0.5], [0., 0., 1.],
-                           (8., 'kpc'), (1., 'kpc'))
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   data_source = ds.disk([0.5, 0.5, 0.5], [0., 0., 1.],
+                         (8., 'kpc'), (1., 'kpc'))
 
    c_min = 10**np.floor(np.log10(data_source['density']).min()  )
    c_max = 10**np.floor(np.log10(data_source['density']).max()+1)
 
-   function = 'self.data[\'Density\'].size > 20'
+   function = 'self.data[\'density\'].size > 20'
    master_clump = Clump(data_source, None, 'density', function=function)
    find_clumps(master_clump, c_min, c_max, 2.0)
    leaf_clumps = get_lowest_clumps(master_clump)
 
-   prj = ProjectionPlot(pf, 2, 'density', center='c', width=(20,'kpc'))
+   prj = yt.ProjectionPlot(ds, 2, 'density', center='c', width=(20,'kpc'))
    prj.annotate_clumps(leaf_clumps)
    prj.save('clumps')
 
--------------
+Overplot Contours
+~~~~~~~~~~~~~~~~~
 
-.. function:: annotate_contour(self, field, ncont=5, factor=4, take_log=False, clim=None, plot_args=None):
+.. function:: annotate_contour(self, field, ncont=5, factor=4, take_log=False,
+                               clim=None, plot_args=None):
 
-   (This is a proxy for :class:`~yt.visualization.plot_modifications.ContourCallback`.)
+   (This is a proxy for
+   :class:`~yt.visualization.plot_modifications.ContourCallback`.)
 
-   Add contours in *field* to the plot.  *ncont* governs the
-   number of contours generated, *factor* governs the number
-   of points used in the interpolation, *take_log* governs
-   how it is contoured and *clim* gives the (upper, lower)
-   limits for contouring.
+   Add contours in ``field`` to the plot.  ``ncont`` governs the number of
+   contours generated, ``factor`` governs the number of points used in the
+   interpolation, ``take_log`` governs how it is contoured and ``clim`` gives
+   the (upper, lower) limits for contouring.
 
 .. python-script::
-   
-   from yt.mods import *
-   pf = load("Enzo_64/DD0043/data0043")
-   s = SlicePlot(pf, "x", ["density"], center="max")
+
+   import yt
+   ds = yt.load("Enzo_64/DD0043/data0043")
+   s = yt.SlicePlot(ds, "x", "density", center="max")
    s.annotate_contour("temperature")
    s.save()
 
--------------
+Overplot quivers
+~~~~~~~~~~~~~~~~
+
+Axis-Aligned data sources
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. function:: annotate_quiver(self, field_x, field_y, factor, scale=None,
+                              scale_units=None, normalize=False):
+
+   (This is a proxy for
+   :class:`~yt.visualization.plot_modifications.QuiverCallback`.)
+
+   Adds a 'quiver' plot to any plot, using the ``field_x`` and ``field_y`` from
+   the associated data, skipping every ``factor`` datapoints ``scale`` is the
+   data units per arrow length unit using ``scale_units`` (see
+   matplotlib.axes.Axes.quiver for more info)
+
+.. python-script::
+
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   p = yt.ProjectionPlot(ds, 'z', 'density', center=[0.5, 0.5, 0.5],
+                         weight_field='density', width=(20, 'kpc'))
+   p.annotate_quiver('velocity_x', 'velocity_y', 16)
+   p.save()
+
+Off-axis Data Sources
+^^^^^^^^^^^^^^^^^^^^^
 
 .. function:: annotate_cquiver(self, field_x, field_y, factor):
 
-   (This is a proxy for :class:`~yt.visualization.plot_modifications.CuttingQuiverCallback`.)
+   (This is a proxy for
+   :class:`~yt.visualization.plot_modifications.CuttingQuiverCallback`.)
 
-   Get a quiver plot on top of a cutting plane, using
-   *field_x* and *field_y*, skipping every *factor*
-   datapoint in the discretization.
+   Get a quiver plot on top of a cutting plane, using ``field_x`` and
+   ``field_y``, skipping every ``factor`` datapoint in the discretization.
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("Enzo_64/DD0043/data0043")
-   s = OffAxisSlicePlot(pf, [1,1,0], ["density"], center="c")
+   import yt
+   ds = yt.load("Enzo_64/DD0043/data0043")
+   s = yt.OffAxisSlicePlot(ds, [1,1,0], ["density"], center="c")
    s.annotate_cquiver('cutting_plane_velocity_x', 'cutting_plane_velocity_y', 10)
    s.zoom(1.5)
    s.save()
 
--------------
+Overplot grids
+~~~~~~~~~~~~~~
 
-.. function:: annotate_grids(self, alpha=1.0, min_pix=1, annotate=False, periodic=True):
+.. function:: annotate_grids(self, alpha=1.0, min_pix=1, annotate=False,
+                             periodic=True):
 
-   (This is a proxy for :class:`~yt.visualization.plot_modifications.GridBoundaryCallback`.)
+   (This is a proxy for
+   :class:`~yt.visualization.plot_modifications.GridBoundaryCallback`.)
 
-   Adds grid boundaries to a plot, optionally with
-   *alpha*-blending. Cuttoff for display is at *min_pix*
-   wide. *annotate* puts the grid id in the corner of the
-   grid.  (Not so great in projections...)
+   Adds grid boundaries to a plot, optionally with alpha-blending via the
+   ``alpha`` keyword. Cuttoff for display is at ``min_pix`` wide. ``annotate``
+   puts the grid id in the corner of the grid.  (Not so great in projections...)
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   slc = SlicePlot(pf, 'z', 'density', width=(10,'kpc'), center='max')
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   slc = yt.SlicePlot(ds, 'z', 'density', width=(10,'kpc'), center='max')
    slc.annotate_grids()
    slc.save()
 
--------------
+Overplot Halo Annotations
+~~~~~~~~~~~~~~~~~~~~~~~~~
 
-.. function:: annotate_halos(self, halo_catalog, col='white', alpha =1, width= None):
+.. function:: annotate_halos(self, halo_catalog, col='white', alpha =1,
+                             width=None):
 
-   (This is a proxy for :class:`~yt.visualization.plot_modifications.HaloCatalogCallback`.)
+   (This is a proxy for
+   :class:`~yt.visualization.plot_modifications.HaloCatalogCallback`.)
 
-   Accepts a :class:`yt.HaloCatalog` *HaloCatalog* and plots 
-   a circle at the location of each halo with the radius of
-   the circle corresponding to the virial radius of the halo.
-   If *width* is set to None (default) all halos are plotted.
-   Otherwise, only halos that fall within a slab with width
-   *width* centered on the center of the plot data. The 
-   color and transparency of the circles can be controlled with
-   *col* and *alpha* respectively.
+   Accepts a :class:`yt.HaloCatalog` and plots a circle at the location of each
+   halo with the radius of the circle corresponding to the virial radius of the
+   halo.  If ``width`` is set to None (default) all halos are plotted.
+   Otherwise, only halos that fall within a slab with width ``width`` centered
+   on the center of the plot data. The color and transparency of the circles can
+   be controlled with ``col`` and ``alpha`` respectively.
 
 .. python-script::
-   
-   from yt.mods import *
+
+   import yt
    from yt.analysis_modules.halo_analysis.halo_catalog import HaloCatalog
 
-   data_pf = load('Enzo_64/RD0006/RedshiftOutput0006')
-   halos_pf = load('rockstar_halos/halos_0.0.bin')
+   data_ds = yt.load('Enzo_64/RD0006/RedshiftOutput0006')
+   halos_ds = yt.load('rockstar_halos/halos_0.0.bin')
 
-   hc = HaloCatalog(halos_pf=halos_pf)
+   hc = HaloCatalog(halos_pf=halos_ds)
    hc.create()
 
-   prj = ProjectionPlot(data_pf, 'z', 'density')
+   prj = yt.ProjectionPlot(data_ds, 'z', 'density')
    prj.annotate_halos(hc)
    prj.save()
 
--------------
+Overplot a Straight Line
+~~~~~~~~~~~~~~~~~~~~~~~~
 
-.. function:: annotate_image_line(self, p1, p2, data_coords=False, plot_args=None):
+.. function:: annotate_image_line(self, p1, p2, data_coords=False,
+                                  plot_args=None):
 
-   (This is a proxy for :class:`~yt.visualization.plot_modifications.ImageLineCallback`.)
+   (This is a proxy for
+   :class:`~yt.visualization.plot_modifications.ImageLineCallback`.)
 
-   Plot from *p1* to *p2* (normalized image plane coordinates) with
-   *plot_args* fed into the plot.
+   Plot from ``p1`` to ``p2`` (normalized image plane coordinates) with
+  ``plot_args`` fed into the plot.
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   p = ProjectionPlot(pf, 'z', 'density', center='m', width=(10, 'kpc'))
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   p = yt.ProjectionPlot(ds, 'z', 'density', center='m', width=(10, 'kpc'))
    p.annotate_image_line((0.3, 0.4), (0.8, 0.9), plot_args={'linewidth':5})
    p.save()
 
--------------
+Overplot a line plot
+~~~~~~~~~~~~~~~~~~~~
 
 .. function:: annotate_line(self, x, y, plot_args=None):
 
-   (This is a proxy for :class:`~yt.visualization.plot_modifications.LinePlotCallback`.)
+   (This is a proxy for
+   :class:`~yt.visualization.plot_modifications.LinePlotCallback`.)
 
-   Over plot *x* and *y* (in code units) with *plot_args* fed into the plot.
+   Over plot numpy arrays or lists ``x`` and ``y`` (in code units) with
+   ``plot_args`` fed into the plot.
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   p = ProjectionPlot(pf, 'z', 'density', center='m', width=(10, 'kpc'))
-   p.annotate_line([-6, -4, -2, 0, 2, 4, 6], [3.6, 1.6, 0.4, 0, 0.4, 1.6, 3.6], plot_args={'linewidth':5})
+   import yt
+   import numpy as np
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   p = yt.ProjectionPlot(ds, 'z', 'density', center='m', width=(20, 'kpc'))
+   x = np.array([-6, -4, -2, 0, 2, 4, 6])
+   y = x**2/10
+   p.annotate_line(x, y, plot_args={'linewidth':5})
    p.save()
 
--------------
+Overplot Magnetic Field Quivers
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-.. function:: annotate_magnetic_field(self, factor=16, scale=None, scale_units=None, normalize=False):
+.. function:: annotate_magnetic_field(self, factor=16, scale=None,
+                                      scale_units=None, normalize=False):
 
-   (This is a proxy for :class:`~yt.visualization.plot_modifications.MagFieldCallback`.)
+   (This is a proxy for
+   :class:`~yt.visualization.plot_modifications.MagFieldCallback`.)
 
-   Adds a 'quiver' plot of magnetic field to the plot,
-   skipping all but every *factor* datapoint. *scale* is the
-   data units per arrow length unit using *scale_units* (see
-   matplotlib.axes.Axes.quiver for more info). if
-   *normalize* is True, the magnetic fields will be scaled
-   by their local (in-plane) length, allowing morphological
-   features to be more clearly seen for fields with
-   substantial variation in field strength.
+   Adds a 'quiver' plot of magnetic field to the plot, skipping all but every
+   ``factor`` datapoint. ``scale`` is the data units per arrow length unit using
+   ``scale_units`` (see matplotlib.axes.Axes.quiver for more info). if
+   ``normalize`` is ``True``, the magnetic fields will be scaled by their local
+   (in-plane) length, allowing morphological features to be more clearly seen
+   for fields with substantial variation in field strength.
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("MHDSloshing/virgo_low_res.0054.vtk",
-             parameters={"TimeUnits":3.1557e13, "LengthUnits":3.0856e24,
-                         "DensityUnits":6.770424595218825e-27})
-   p = ProjectionPlot(pf, 'z', 'density', center='c', width=(300, 'kpc'))
+   import yt
+   ds = yt.load("MHDSloshing/virgo_low_res.0054.vtk",
+                parameters={"time_unit":(1, 'Myr'), "length_unit":(1, 'Mpc'),
+                            "mass_unit":(1e17, 'Msun')})
+   p = yt.ProjectionPlot(ds, 'z', 'density', center='c', width=(300, 'kpc'))
    p.annotate_magnetic_field()
    p.save()
 
--------------
+Annotate a Point With a Marker
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 .. function:: annotate_marker(self, pos, marker='x', plot_args=None):
 
-   (This is a proxy for :class:`~yt.visualization.plot_modifications.MarkerAnnotateCallback`.)
+   (This is a proxy for
+   :class:`~yt.visualization.plot_modifications.MarkerAnnotateCallback`.)
 
-   Adds text *marker* at *pos* in code coordinates.
-   *plot_args* is a dict that will be forwarded to the plot
+   Adds ``marker`` at ``pos`` in code coordinates.
+   ``plot_args`` is a dict that will be forwarded to the plot
    command.
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   s = SlicePlot(pf, 'z', 'density', center='m', width=(10, 'kpc'))
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   s = yt.SlicePlot(ds, 'z', 'density', center='c', width=(10, 'kpc'))
    s.annotate_marker([0.5, 0.5, 0.5], plot_args={'s':10000})
-   s.save()   
+   s.save()
 
--------------
+Overplotting Particle Positions
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-.. function:: annotate_particles(self, width, p_size=1.0, col='k', marker='o', stride=1.0, ptype=None, stars_only=False, dm_only=False, minimum_mass=None):
+.. function:: annotate_particles(self, width, p_size=1.0, col='k', marker='o',
+                                 stride=1.0, ptype=None, stars_only=False,
+                                 dm_only=False, minimum_mass=None):
 
-   (This is a proxy for :class:`~yt.visualization.plot_modifications.ParticleCallback`.)
+   (This is a proxy for
+   :class:`~yt.visualization.plot_modifications.ParticleCallback`.)
 
-   Adds particle positions, based on a thick slab along
-   *axis* with a *width* along the line of sight.  *p_size*
-   controls the number of pixels per particle, and *col*
-   governs the color.  *ptype* will restrict plotted
-   particles to only those that are of a given type.
-   *minimum_mass* will require that the particles be of a
-   given mass, calculated via ParticleMassMsun, to be
-   plotted.
+   Adds particle positions, based on a thick slab along ``axis`` with a
+   ``width`` along the line of sight.  ``p_size`` controls the number of pixels
+   per particle, and ``col`` governs the color.  ``ptype`` will restrict plotted
+   particles to only those that are of a given type.  ``minimum_mass`` will
+   require that the particles be of a given mass minimum mass in solar units.
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("Enzo_64/DD0043/data0043")
-   p = ProjectionPlot(pf, "x", "density", center='m', width=(10, 'Mpc'))
+   import yt
+   ds = yt.load("Enzo_64/DD0043/data0043")
+   p = yt.ProjectionPlot(ds, "x", "density", center='m', width=(10, 'Mpc'))
    p.annotate_particles((10, 'Mpc'))
    p.save()
 
--------------
+Annotate a point with text
+~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 .. function:: annotate_point(self, pos, text, text_args=None):
 
-   (This is a proxy for :class:`~yt.visualization.plot_modifications.PointAnnotateCallback`.)
+   (This is a proxy for
+   :class:`~yt.visualization.plot_modifications.PointAnnotateCallback`.)
 
-   This adds *text* at position *pos*, where *pos* is in
-   code-space. *text_args* is a dict fed to the text
-   placement code.
+   This adds ``text`` at position ``pos``, where ``pos`` is in
+   code-space. ``text_args`` is a dict fed to the text placement code.
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   p = ProjectionPlot(pf, 'z', 'density', center='m', width=(10, 'kpc'))
-   p.annotate_point([0.5, 0.496, 0.5], "What's going on here?", text_args={'size':'xx-large', 'color':'w'})
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   p = yt.ProjectionPlot(ds, 'z', 'density', center='m', width=(10, 'kpc'))
+   p.annotate_point([0.5, 0.496, 0.5], "What's going on here?",
+                    text_args={'size':'xx-large', 'color':'w'})
    p.save()
 
--------------
+Overplot a circle on a plot
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-.. function:: annotate_quiver(self, field_x, field_y, factor, scale=None, scale_units=None, normalize=False):
+.. function:: annotate_sphere(self, center, radius, circle_args=None, text=None,
+                              text_args=None):
 
-   (This is a proxy for :class:`~yt.visualization.plot_modifications.QuiverCallback`.)
+   (This is a proxy for
+   :class:`~yt.visualization.plot_modifications.SphereCallback`.)
 
-   Adds a 'quiver' plot to any plot, using the *field_x* and
-   *field_y* from the associated data, skipping every
-   *factor* datapoints *scale* is the data units per arrow
-   length unit using *scale_units*  (see
-   matplotlib.axes.Axes.quiver for more info)
+   A sphere centered at ``center`` in code units with radius ``radius`` in code
+   units will be created, with optional ``circle_args``, ``text``, and
+   ``text_args``.
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   p = ProjectionPlot(pf, 'z', 'density', center=[0.5, 0.5, 0.5], 
-                      weight_field='density', width=(20, 'kpc'))
-   p.annotate_quiver('velocity_x', 'velocity_y', 16)
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   p = yt.ProjectionPlot(ds, 'z', 'density', center='c', width=(20, 'kpc'))
+   p.annotate_sphere([0.5, 0.5, 0.5], (2, 'kpc'), {'fill':True})
    p.save()
 
--------------
+Overplot streamlines
+~~~~~~~~~~~~~~~~~~~~
 
-.. function:: annotate_sphere(self, center, radius, circle_args=None, text=None, text_args=None):
+.. function:: annotate_streamlines(self, field_x, field_y, factor=6.0, nx=16,
+                                   ny=16, xstart=(0, 1), ystart=(0, 1),
+                                   nsample=256, start_at_xedge=False,
+                                   start_at_yedge=False, plot_args=None):
 
-   (This is a proxy for :class:`~yt.visualization.plot_modifications.SphereCallback`.)
+   (This is a proxy for
+   :class:`~yt.visualization.plot_modifications.StreamlineCallback`.)
 
-   A sphere centered at *center* in code units with radius
-   *radius* in code units will be created, with optional
-   *circle_args*, *text*, and *text_args*.
+   Add streamlines to any plot, using the ``field_x`` and ``field_y`` from the
+   associated data, using ``nx`` and ``ny`` starting points that are bounded by
+   ``xstart`` and ``ystart``.  To begin streamlines from the left edge of the
+   plot, set ``start_at_xedge`` to ``True``; for the bottom edge, use
+   ``start_at_yedge``.  A line with the qmean vector magnitude will cover
+   1.0/``factor`` of the image.
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   p = ProjectionPlot(pf, 'z', 'density', center='c', width=(20, 'kpc'))
-   p.annotate_sphere([0.5, 0.5, 0.5], (2, 'kpc'), {'fill':True})
-   p.save()
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   s = yt.SlicePlot(ds, 'z', 'density', center='c', width=(20, 'kpc'))
+   s.annotate_streamlines('velocity_x', 'velocity_y')
+   s.save()
 
--------------
+Add text
+~~~~~~~~
 
-.. function:: annotate_streamlines(self, field_x, field_y, factor=6.0, nx=16, ny=16, xstart=(0, 1), ystart=(0, 1), nsample=256, start_at_xedge=False, start_at_yedge=False, plot_args=None):
+.. function:: annotate_text(self, pos, text, data_coords=False, text_args=None):
 
-   (This is a proxy for :class:`~yt.visualization.plot_modifications.StreamlineCallback`.)
+   (This is a proxy for
+   :class:`~yt.visualization.plot_modifications.TextLabelCallback`.)
 
-   Add streamlines to any plot, using the *field_x* and
-   *field_y* from the associated data, using *nx* and *ny*
-   starting points that are bounded by *xstart* and
-   *ystart*.  To begin streamlines from the left edge of the
-   plot, set *start_at_xedge* to True; for the bottom edge,
-   use *start_at_yedge*.  A line with the qmean vector
-   magnitude will cover 1.0/*factor* of the image.
+   Accepts a position in (0..1, 0..1) of the image, some text and optionally
+   some text arguments. If data_coords is True, position will be in code units
+   instead of image coordinates.
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   s = SlicePlot(pf, 'z', 'density', center='c', width=(20, 'kpc'))
-   s.annotate_streamlines('velocity_x', 'velocity_y')
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   s = yt.SlicePlot(ds, 'z', 'density', center='m', width=(10, 'kpc'))
+   s.annotate_text((0.5, 0.5), 'Sample text',
+                   text_args={'size':'xx-large', 'color':'w'})
    s.save()
 
--------------
+Add a title to the plot
+~~~~~~~~~~~~~~~~~~~~~~~
 
-.. function:: annotate_text(self, pos, text, data_coords=False, text_args=None):
+.. function:: annotate_title(self, title='Plot'):
 
-   (This is a proxy for :class:`~yt.visualization.plot_modifications.TextLabelCallback`.)
+   (This is a proxy for
+   :class:`~yt.visualization.plot_modifications.TitleCallback`.)
 
-   Accepts a position in (0..1, 0..1) of the image, some
-   text and optionally some text arguments. If data_coords
-   is True, position will be in code units instead of image
-   coordinates.
+   Accepts a ``title`` and adds it to the plot.
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   s = SlicePlot(pf, 'z', 'density', center='m', width=(10, 'kpc'))
-   s.annotate_text((0.5, 0.5), 'Sample text', text_args={'size':'xx-large', 'color':'w'})
-   s.save()
-
--------------
-
-.. function:: annotate_title(self, title='Plot'):
-
-   (This is a proxy for :class:`~yt.visualization.plot_modifications.TitleCallback`.)
-
-   Accepts a *title* and adds it to the plot
-
-.. python-script::
-
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   p = ProjectionPlot(pf, 'z', 'density', center='c', width=(20, 'kpc'))
-   p.annotate_title('Density plot')
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   p = yt.ProjectionPlot(ds, 'z', 'density', center='c', width=(20, 'kpc'))
+   p.annotate_title('Density Plot')
    p.save()
 
--------------
+Overplot quivers for the velocity field
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-.. function:: annotate_velocity(self, factor=16, scale=None, scale_units=None, normalize=False):
+.. function:: annotate_velocity(self, factor=16, scale=None, scale_units=None,
+                                normalize=False):
 
-   (This is a proxy for :class:`~yt.visualization.plot_modifications.VelocityCallback`.)
+   (This is a proxy for
+   :class:`~yt.visualization.plot_modifications.VelocityCallback`.)
 
-   Adds a 'quiver' plot of velocity to the plot, skipping
-   all but every *factor* datapoint. *scale* is the data
-   units per arrow length unit using *scale_units* (see
-   matplotlib.axes.Axes.quiver for more info). if
-   *normalize* is True, the velocity fields will be scaled
-   by their local (in-plane) length, allowing morphological
-   features to be more clearly seen for fields with
-   substantial variation in field strength (normalize is not
+   Adds a 'quiver' plot of velocity to the plot, skipping all but every
+   ``factor`` datapoint. ``scale`` is the data units per arrow length unit using
+   ``scale_units`` (see matplotlib.axes.Axes.quiver for more info). if
+   ``normalize`` is ``True``, the velocity fields will be scaled by their local
+   (in-plane) length, allowing morphological features to be more clearly seen
+   for fields with substantial variation in field strength (normalize is not
    implemented and thus ignored for Cutting Planes).
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   p = SlicePlot(pf, 'z', 'density', center='m', width=(10, 'kpc'))
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   p = yt.SlicePlot(ds, 'z', 'density', center='m', width=(10, 'kpc'))
    p.annotate_velocity()
    p.save()

diff -r 103131490fefcf01b2a7288ad246869fe853dd47 -r 94182bf987253d6d1cffc464e82a545bb1e64919 doc/source/visualizing/manual_plotting.rst
--- a/doc/source/visualizing/manual_plotting.rst
+++ b/doc/source/visualizing/manual_plotting.rst
@@ -35,11 +35,12 @@
 .. python-script::
    
    import pylab as P
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   import numpy as np
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
 
-   c = pf.h.find_max('density')[1]
-   proj = pf.proj('density', 0)
+   c = ds.find_max('density')[1]
+   proj = ds.proj('density', 0)
 
    width = (10, 'kpc') # we want a 1.5 mpc view
    res = [1000, 1000] # create an image with 1000x1000 pixels
@@ -64,16 +65,23 @@
 Line Plots
 ----------
 
-This is perhaps the simplest thing to do. ``yt`` provides a number of one dimensional objects, and these return a 1-D numpy array of their contents with direct dictionary access. As a simple example, take a :class:`~yt.data_objects.data_containers.AMROrthoRayBase` object, which can be created from a index by calling ``pf.ortho_ray(axis, center)``. 
+This is perhaps the simplest thing to do. ``yt`` provides a number of one
+dimensional objects, and these return a 1-D numpy array of their contents with
+direct dictionary access. As a simple example, take a
+:class:`~yt.data_objects.data_containers.AMROrthoRayBase` object, which can be
+created from a index by calling ``pf.ortho_ray(axis, center)``.
 
 .. python-script::
 
-   from yt.mods import *
+   import yt
+   import numpy as np
    import pylab as P
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   c = pf.h.find_max("density")[1]
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   c = ds.find_max("density")[1]
    ax = 0 # take a line cut along the x axis
-   ray = pf.ortho_ray(ax, (c[1], c[2])) # cutting through the y0,z0 such that we hit the max density
+
+   # cutting through the y0,z0 such that we hit the max density
+   ray = ds.ortho_ray(ax, (c[1], c[2]))
 
    P.subplot(211)
    P.semilogy(np.array(ray['x']), np.array(ray['density']))

diff -r 103131490fefcf01b2a7288ad246869fe853dd47 -r 94182bf987253d6d1cffc464e82a545bb1e64919 doc/source/visualizing/plots.rst
--- a/doc/source/visualizing/plots.rst
+++ b/doc/source/visualizing/plots.rst
@@ -25,10 +25,10 @@
 If you need to take a quick look at a single simulation output, ``yt``
 provides the ``PlotWindow`` interface for generating annotated 2D
 visualizations of simulation data.  You can create a ``PlotWindow`` plot by
-supplying a parameter file, a list of fields to plot, and a plot center to
-create a :class:`~yt.visualization.plot_window.SlicePlot`,
+supplying a dataset, a list of fields to plot, and a plot center to
+create a :class:`~yt.visualization.plot_window.AxisAlignedSlicePlot`,
 :class:`~yt.visualization.plot_window.ProjectionPlot`, or
-:class:`~yt.visualization.plot_window.OffAxisSlicePlot`.
+:class:`~yt.visualization.plot_window.OffAxisProjectionPlot`.
 
 Plot objects use ``yt`` data objects to extract the maximum resolution
 data available to render a 2D image of a field. Whenever a
@@ -37,7 +37,8 @@
 is requested of it -- for instance, when the width or field is changed
 -- this high-resolution data is then pixelized and placed in a buffer
 of fixed size. This is accomplished behind the scenes using
-:class:`~yt.visualization.fixed_resolution.FixedResolutionBuffer`
+:class:`~yt.visualization.fixed_resolution.FixedResolutionBuffer`.
+
 ``PlotWindow`` expose the underlying matplotlib ``figure`` and
 ``axes`` objects, making it easy to customize your plots and 
 add new annotations.
@@ -45,28 +46,33 @@
 .. _slice-plots:
 
 Slice Plots
------------
+~~~~~~~~~~~
 
-The quickest way to plot a slice of a field through your data is to use
-:class:`~yt.visualization.plot_window.SlicePlot`.  Say we want to visualize a
-slice through the Density field along the z-axis centered on the center of the
-simulation box in a simulation dataset we've opened and stored in the parameter
-file object ``pf``.  This can be accomplished with the following command:
+The quickest way to plot a slice of a field through your data is via
+:class:`~yt.visualization.plot_window.SlicePlot`.  These plots are generally
+quicker than projections because they only need to read and process a slice
+through the dataset.
+
+The following script plots a slice through the density field along the z-axis
+centered on the center of the simulation box in a simulation dataset we've
+opened and stored in ``ds``:
 
 .. code-block:: python
 
-   >>> slc = SlicePlot(pf, 'z', 'density')
+   >>> slc = yt.SlicePlot(ds, 'z', 'density')
    >>> slc.save()
 
 These two commands will create a slice object and store it in a variable we've
-called ``slc``.  We then call the ``save()`` function that is associated with
-the slice object.  This automatically saves the plot in png image format with an
-automatically generated filename.  If you don't want the slice object to stick
-around, you can accomplish the same thing in one line:
+called ``slc``.  Since this plot is aligned with the simulation coordinate
+system, ``slc`` is an instance of
+:class:`~yt.visualization.plot_window.AxisAlignedSlicePlot`. We then call the
+``save()`` function, which automatically saves the plot in png image format with
+an automatically generated filename.  If you don't want the slice object to
+stick around, you can accomplish the same thing in one line:
 
 .. code-block:: python
    
-   >>> SlicePlot(pf, 'z', 'density').save()
+   >>> yt.SlicePlot(ds, 'z', 'density').save()
 
 It's nice to keep the slice object around if you want to modify the plot.  By
 default, the plot width will be set to the size of the simulation box.  To zoom
@@ -75,41 +81,58 @@
 
 .. code-block:: python
 
-   >>> slc = SlicePlot(pf, 'z', 'density')
+   >>> slc = yt.SlicePlot(ds, 'z', 'density')
    >>> slc.zoom(10)
    >>> slc.save('zoom')
 
 This will save a new plot to disk with a different filename - prepended with
-'zoom' instead of the name of the parameter file. If you want to set the width
+'zoom' instead of the name of the dataset. If you want to set the width
 manually, you can do that as well. For example, the following sequence of
 commands will create a slice, set the width of the plot to 10 kiloparsecs, and
 save it to disk.
 
 .. code-block:: python
 
-   >>> slc = SlicePlot(pf, 'z', 'density')
-   >>> slc.set_width((10,'kpc'))
+   >>> from yt.units import kpc
+   >>> slc = yt.SlicePlot(ds, 'z', 'density')
+   >>> slc.set_width(10*kpc)
    >>> slc.save('10kpc')
 
-The SlicePlot also optionally accepts the coordinate to center the plot on and
-the width of the plot:
+The plot width can be specified independently along the x and y direction by
+passing a tuple of widths.  An individual width can also be represented using a
+``(value, unit)`` tuple.  The following sequence of commands all equivalently
+set the width of the plot to 200 kiloparsecs in the ``x`` and ``y`` direction.
 
 .. code-block:: python
 
-   >>> SlicePlot(pf, 'z', 'density', center=[0.2, 0.3, 0.8], 
-   ...           width = (10,'kpc')).save()
+   >>> from yt.units import kpc
+   >>> slc.set_width(200*kpc)
+   >>> slc.set_width((200, 'kpc'))
+   >>> slc.set_width((200*kpc, 200*kpc))
 
-The center must be given in code units.  Optionally, you can supply 'c' or 'm'
-for the center.  These two choices will center the plot on the center of the
-simulation box and the coordinate of the maximum density cell, respectively.
+The ``SlicePlot`` also optionally accepts the coordinate to center the plot on
+and the width of the plot:
+
+.. code-block:: python
+
+   >>> yt.SlicePlot(ds, 'z', 'density', center=[0.2, 0.3, 0.8],
+   ...              width = (10,'kpc')).save()
+
+The plot center is relative to the simulation coordinate system.  If supplied
+without units, the center is assumed by in code units.  Optionally, you can
+supply 'c' or 'm' for the center.  These two choices will center the plot on the
+center of the simulation box and the coordinate of the maximum density cell,
+respectively.
 
 Here is an example that combines all of the options we just discussed.
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   slc = SlicePlot(pf, 'z', 'density', center=[0.5, 0.5, 0.5], width=(20,'kpc'))
+   import yt
+   from yt.units import kpc
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   slc = yt.SlicePlot(ds, 'z', 'density', center=[0.5, 0.5, 0.5],
+                      width=(20,'kpc'))
    slc.save()
 
 The above example will display an annotated plot of a slice of the
@@ -118,14 +141,14 @@
 letter 'z', corresponding to the z-axis.  Finally, the image is saved to
 a png file.
 
-Conceptually, you can think of the SlicePlot as an adjustable window
+Conceptually, you can think of the plot object as an adjustable window
 into the data. For example:
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   slc = SlicePlot(pf, 'z', 'pressure', center='c')
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   slc = yt.SlicePlot(ds, 'z', 'pressure', center='c')
    slc.save()
    slc.zoom(30)
    slc.save('zoom')
@@ -138,32 +161,43 @@
 interesting region in the simulation and adjust the boundaries of the
 region to visualize on the fly.
 
-A slice object can also add annotations like a title, an overlying
-quiver plot, the location of grid boundaries, halo-finder annotations,
-and many other annotations, including user-customizable annotations.
-For example:
+See :class:`~yt.visualization.plot_window.AxisAlignedSlicePlot` for the 
+full class description.
+
+.. _off-axis-slices:
+
+Off Axis Slices
+~~~~~~~~~~~~~~~
+
+Off axis slice plots can be generated in much the same way as
+grid-aligned slices.  Off axis slices use
+:class:`~yt.data_objects.data_containers.AMRCuttingPlaneBase` to slice
+through simulation domains at an arbitrary oblique angle.  A
+:class:`~yt.visualization.plot_window.OffAxisSlicePlot` can be
+instantiated by specifying a dataset, the normal to the cutting
+plane, and the name of the fields to plot.  Just like an
+:class:`~yt.visualization.plot_window.AxisAlignedSlicePlot`, an
+``OffAxisSlicePlot`` can be created via the
+:class:`~yt.visualization.plot_window.SlicePlot` function. For example:
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   slc = SlicePlot(pf, 'z', 'density', width=(10,'kpc'))
-   slc.annotate_grids()
-   slc.save()
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   L = [1,1,0] # vector normal to cutting plane
+   north_vector = [-1,1,0]
+   cut = yt.SlicePlot(ds, L, 'density', width=(25, 'kpc'),
+                      north_vector=north_vector)
+   cut.save()
 
-will plot the density field in a 10 kiloparsec slice through the
-z-axis centered on the highest density point in the simulation domain.
-Before saving the plot, the script annotates it with the grid
-boundaries, which are drawn as thick black lines by default.
-
-Annotations are described in :ref:`callbacks`.  See
-:class:`~yt.visualization.plot_window.SlicePlot` for the full class
-description.
+In this case, a normal vector for the cutting plane is supplied in the second
+argument. Optionally, a `north_vector` can be specified to fix the orientation
+of the image plane.
 
 .. _projection-plots:
 
 Projection Plots
-----------------
+~~~~~~~~~~~~~~~~
 
 Using a fast adaptive projection, ``yt`` is able to quickly project
 simulation data along the coordinate axes.
@@ -174,15 +208,15 @@
 
 .. python-script::
  
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   prj = ProjectionPlot(pf, 2, 'density', width=(25, 'kpc'), 
-                        weight_field=None)
+   import yt
+   from yt.units import kpc
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   prj = yt.ProjectionPlot(ds, 2, 'temperature', width=25*kpc,
+                           weight_field='density')
    prj.save()
 
-will create a projection of Density field along the x axis, plot it,
-and then save it to a png image file.  The projection is only carried
-out to level 2 of the AMR index and no weighting is applied.
+will create a density-weighted projection of the temperature field along the x
+axis, plot it, and then save the plot to a png image file.
 
 Like :ref:`slice-plots`, annotations and modifications can be applied
 after creating the ``ProjectionPlot`` object.  Annotations are
@@ -190,43 +224,8 @@
 :class:`~yt.visualization.plot_window.ProjectionPlot` for the full
 class description.
 
-.. _off-axis-slices:
-
-Off Axis Slice Plots
---------------------
-
-Off axis slice plots can be generated in much the same way as
-grid-aligned slices.  Off axis slices use
-:class:`~yt.data_objects.data_containers.AMRCuttingPlaneBase` to slice
-through simulation domains at an arbitrary oblique angle.  A
-:class:`~yt.visualization.plot_window.OffAxisSlicePlot` can be
-instantiated by specifying a parameter file, the normal to the cutting
-plane, and the name of the fields to plot.  For example:
-
-.. python-script::
-
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   L = [1,1,0] # vector normal to cutting plane
-   north_vector = [-1,1,0]
-   cut = OffAxisSlicePlot(pf, L, 'density', width=(25, 'kpc'), 
-                          north_vector=north_vector)
-   cut.save()
-
-creates an off-axis slice in the plane perpendicular to ``L``,
-oriented such that ``north_vector`` is the up direction.  If ``L`` and
-``north_vector`` are not perpendicular, the component of
-``north_vector`` perpendicular to ``L`` is used. Like
-:ref:`slice-plots`, annotations and modifications can be applied after
-creating the ``OffAxisSlicePlot`` object.  Annotations are described
-in :ref:`callbacks`.  See
-:class:`~yt.visualization.plot_window.OffAxisSlicePlot` for the full
-class description.
-
-.. _off-axis-projections:
-
 Off Axis Projection Plots
--------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~
 
 Off axis projection plots .  Internally, off axis projections are
 created using :ref:`the-camera-interface` by applying the
@@ -246,15 +245,16 @@
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   import yt
+   import numpy as np
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
    L = [1,1,0] # vector normal to cutting plane
    north_vector = [-1,1,0]
    W = [0.02, 0.02, 0.02]
    c = [0.5, 0.5, 0.5]
    N = 512
-   image = off_axis_projection(pf, c, L, W, N, "density")
-   write_image(np.log10(image), "%s_offaxis_projection.png" % pf)
+   image = yt.off_axis_projection(ds, c, L, W, N, "density")
+   yt.write_image(np.log10(image), "%s_offaxis_projection.png" % ds)
 
 Here, ``W`` is the width of the projection in the x, y, *and* z
 directions.
@@ -268,32 +268,30 @@
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
    L = [1,1,0] # vector normal to cutting plane
    north_vector = [-1,1,0]
-   prj = OffAxisProjectionPlot(pf,L,'density',width=(25, 'kpc'), 
-                               north_vector=north_vector)
+   prj = yt.OffAxisProjectionPlot(ds,L,'density',width=(25, 'kpc'),
+                                  north_vector=north_vector)
    prj.save()
 
 OffAxisProjectionPlots can also be created with a number of
-keyword arguments, as described in the `api reference`__ for the
-class initializer.
-
-__ :class:`~yt.visualization.plot_window.OffAxisProjectionPlot`
+keyword arguments, as described in
+:class:`~yt.visualization.plot_window.OffAxisProjectionPlot`
 
 Plot Customization
 ------------------
 
 You can customize each of the four plot types above in identical ways.  We'll go
-over each of the customizations methos below.  For each of the examples below we
+over each of the customizations methods below.  For each of the examples below we
 will modify the following plot.
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   slc = SlicePlot(pf, 'z', 'density', width=(10,'kpc'))
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   slc = yt.SlicePlot(ds, 'z', 'density', width=(10,'kpc'))
    slc.save()
 
 Panning and zooming
@@ -301,78 +299,84 @@
 
 There are three methods to dynamically pan around the data.  
 
-:class:`~yt.visualization.plot_window.SlicePlot.pan` accepts x and y deltas in code
-units.
+:class:`~yt.visualization.plot_window.AxisAlignedSlicePlot.pan` accepts x and y
+deltas.
 
 .. python-script::
 
-   from yt.mods import *
+   import yt
    from yt.units import kpc
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   slc = SlicePlot(pf, 'z', 'density', width=(10,'kpc'))
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   slc = yt.SlicePlot(ds, 'z', 'density', width=(10,'kpc'))
    slc.pan((2*kpc, 2*kpc))
    slc.save()
 
-:class:`~yt.visualization.plot_window.SlicePlot.pan_rel` accepts deltas in units relative
-to the field of view of the plot.  
+:class:`~yt.visualization.plot_window.AxisAlignedSlicePlot.pan_rel` accepts deltas 
+in units relative to the field of view of the plot.
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   slc = SlicePlot(pf, 'z', 'density', width=(10,'kpc'))
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   slc = yt.SlicePlot(ds, 'z', 'density', width=(10,'kpc'))
    slc.pan_rel((0.1, -0.1))
    slc.save()
 
-:class:`~yt.visualization.plot_window.SlicePlot.zoom` accepts a factor to zoom in by.
+:class:`~yt.visualization.plot_window.AxisAlignedSlicePlot.zoom` accepts a factor to zoom in by.
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   slc = SlicePlot(pf, 'z', 'density', width=(10,'kpc'))
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   slc = yt.SlicePlot(ds, 'z', 'density', width=(10,'kpc'))
    slc.zoom(2)
    slc.save()
 
 Set axes units
 ~~~~~~~~~~~~~~
 
-:class:`~yt.visualization.plot_window.SlicePlot.set_axes_unit` allows the customization of
+:class:`~yt.visualization.plot_window.AxisAlignedSlicePlot.set_axes_unit` allows the customization of
 the axes unit labels.
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   slc = SlicePlot(pf, 'z', 'density', width=(10,'kpc'))
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   slc = yt.SlicePlot(ds, 'z', 'density', width=(10,'kpc'))
    slc.set_axes_unit('Mpc')
    slc.save()
 
+The same result could have been accomplished by explicitly setting the ``width``
+to ``(.01, 'Mpc')``.
+
 Set the plot center
 ~~~~~~~~~~~~~~~~~~~
 
-The :class:`~yt.visualization.plot_window.SlicePlot.set_center` function accepts a new
-center for the plot, in code units.  New centers must be two element tuples.
+The :class:`~yt.visualization.plot_window.AxisAlignedSlicePlot.set_center`
+function accepts a new center for the plot, in code units.  New centers must be
+two element tuples.
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   slc = SlicePlot(pf, 'z', 'density', width=(10,'kpc'))
-   slc.set_center((0.5, 0.5))
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   slc = yt.SlicePlot(ds, 'z', 'density', width=(10,'kpc'))
+   slc.set_center((0.5, 0.503))
    slc.save()
 
 Fonts
 ~~~~~
 
-:class:`~yt.visualization.plot_window.SlicePlot.set_font` allows font costomization.
+:class:`~yt.visualization.plot_window.AxisAlignedSlicePlot.set_font` allows font
+costomization.
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   slc = SlicePlot(pf, 'z', 'density', width=(10,'kpc'))
-   slc.set_font({'family': 'sans-serif', 'style': 'italic','weight': 'bold', 'size': 24})
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   slc = yt.SlicePlot(ds, 'z', 'density', width=(10,'kpc'))
+   slc.set_font({'family': 'sans-serif', 'style': 'italic',
+                 'weight': 'bold', 'size': 24})
    slc.save()
 
 Colormaps
@@ -383,117 +387,173 @@
 different fields tracked by the plot object.
 
 To change the colormap for the plot, call the
-:class:`~yt.visualization.plot_window.SlicePlot.set_cmap` function.  Use any of the
-colormaps listed in the :ref:`colormaps` section.
+:class:`~yt.visualization.plot_window.AxisAlignedSlicePlot.set_cmap` function.
+Use any of the colormaps listed in the :ref:`colormaps` section.
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   slc = SlicePlot(pf, 'z', 'density', width=(10,'kpc'))
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   slc = yt.SlicePlot(ds, 'z', 'density', width=(10,'kpc'))
    slc.set_cmap('density', 'RdBu_r')
    slc.save()
 
-The :class:`~yt.visualization.plot_window.SlicePlot.set_log` function accepts a field name
-and a boolean.  If the boolean is :code:`True`, the colormap for the field will
-be log scaled.  If it is `False` the colormap will be linear.
+The :class:`~yt.visualization.plot_window.AxisAlignedSlicePlot.set_log` function
+accepts a field name and a boolean.  If the boolean is ``True``, the colormap
+for the field will be log scaled.  If it is ``False`` the colormap will be
+linear.
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   slc = SlicePlot(pf, 'z', 'density', width=(10,'kpc'))
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   slc = yt.SlicePlot(ds, 'z', 'density', width=(10,'kpc'))
    slc.set_log('density', False)
    slc.save()
 
-Lastly, the :class:`~yt.visualization.plot_window.SlicePlot.set_zlim` function makes it
-possible to set a custom colormap range.
+Lastly, the :class:`~yt.visualization.plot_window.AxisAlignedSlicePlot.set_zlim`
+function makes it possible to set a custom colormap range.
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   slc = SlicePlot(pf, 'z', 'density', width=(10,'kpc'))
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   slc = yt.SlicePlot(ds, 'z', 'density', width=(10,'kpc'))
    slc.set_zlim('density', 1e-30, 1e-25)
    slc.save()
 
+Annotations
+~~~~~~~~~~~
+
+A slice object can also add annotations like a title, an overlying
+quiver plot, the location of grid boundaries, halo-finder annotations,
+and many other annotations, including user-customizable annotations.
+For example:
+
+.. python-script::
+
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   slc = yt.SlicePlot(ds, 'z', 'density', width=(10,'kpc'))
+   slc.annotate_grids()
+   slc.save()
+
+will plot the density field in a 10 kiloparsec slice through the
+z-axis centered on the highest density point in the simulation domain.
+Before saving the plot, the script annotates it with the grid
+boundaries, which are drawn as thick black lines by default.
+
+Annotations are described in :ref:`callbacks`.
+
 Set the size of the plot
 ~~~~~~~~~~~~~~~~~~~~~~~~
 
 To set the size of the plot, use the
-:class:`~yt.visualization.plot_window.SlicePlot.set_window_size` function.  The argument
+:class:`~yt.visualization.plot_window.AxisAlignedSlicePlot.set_figure_size` function.  The argument
 is the size of the longest edge of the plot in inches.  View the full resolution
 image to see the difference more clearly.
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   slc = SlicePlot(pf, 'z', 'density', width=(10,'kpc'))
-   slc.set_window_size(10)
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   slc = yt.SlicePlot(ds, 'z', 'density', width=(10,'kpc'))
+   slc.set_figure_size(10)
    slc.save()
 
 To change the resolution of the image, call the
-:class:`~yt.visualization.plot_window.SlicePlot.set_buff_size` function.
+:class:`~yt.visualization.plot_window.AxisAlignedSlicePlot.set_buff_size` function.
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   slc = SlicePlot(pf, 'z', 'density', width=(10,'kpc'))
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   slc = yt.SlicePlot(ds, 'z', 'density', width=(10,'kpc'))
    slc.set_buff_size(1600)
    slc.save()
 
+Further customization via matplotlib
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Each ``PlotWindow`` object is really a container for plots - one plot for each
+field specified in the list of fields supplied when the plot object is
+created. The individual plots can be accessed via the ``plots`` dictionary
+attached to each ``PlotWindow`` object:
+
+.. code-block:: python
+
+   >>> slc = SlicePlot(ds, 2, ['density', 'temperature']
+   >>> dens_plot = slc.plots['density']
+
+In this example ``dens_plot`` is an instance of
+:class:`~yt.visualization.plot_window.WindowPlotMPL`, an object that wraps the
+matplotlib ``figure`` and ``axes`` objects.  We can access these matplotlib primitives via attributes of ``dens_plot``.
+
+.. code-block:: python
+
+   >>> figure = dens_plot.figure
+   >>> axes = dens_plot.axes
+   >>> colorbar_axes = dens_plot.cax
+
+These are the :matplotlib:class:`figure`, and :matplotlib:class:`axes` objects
+that control the actual drawing of the plot.  Arbitrary plot customizations
+are possible by manipulating these objects.  See :ref:`matplotlib-primitives` for
+an example.
+
 .. _how-to-make-1d-profiles:
 
 1D Profile Plots
 ----------------
 
-1D profiles are used to calculated the average or the sum of a given quantity
-with respect to a second quantity.  This means the "average density as a
-function of radius" or "the total mass within a given set of density bins."
+1D profiles are used to calculate the average or the sum of a given quantity
+with respect to a second quantity.  Two common examples are the "average density
+as a function of radius" or "the total mass within a given set of density bins."
 When created, they default to the average: in fact, they default to the average
 as weighted by the total cell mass.  However, this can be modified to take
 either the total value or the average with respect to a different quantity.
 
-Profiles operate on data objects; they will take the entire data contained in a
-sphere, a prism, an extracted region and so on, and they will calculate and use
-that as input to their calculation.  To make a 1D profile plot, create a
-(:class:`~yt.visualization.profile_plotter.ProfilePlot`) object, supplying the 
-data object, the field for binning, and a list of fields to be profiled.
+Profiles operate on :ref:`data objects <using-objects>`; they will take the
+entire data contained in a sphere, a prism, an extracted region and so on, and
+they will calculate and use that as input to their calculation.  To make a 1D
+profile plot, create a (:class:`~yt.visualization.profile_plotter.ProfilePlot`)
+object, supplying the data object, the field for binning, and a list of fields
+to be profiled.
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   my_galaxy = pf.disk([0.5, 0.5, 0.5], [0.0, 0.0, 1.0], 0.01, 0.003)
-   plot = ProfilePlot(my_galaxy, "density", ["temperature"])
+   import yt
+   from yt.units import kpc
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   my_galaxy = ds.disk(ds.domain_center, [0.0, 0.0, 1.0], 10*kpc, 3*kpc)
+   plot = yt.ProfilePlot(my_galaxy, "density", ["temperature"])
    plot.save()
 
 This will create a :class:`yt.data_objects.data_containers.AMRCylinderBase`
-centered at [0.3, 0.5, 0.8], with a normal vector of [0.4, 0.5, 0.1], radius of
-0.01 and height of 0.001 and will then make a plot of the average (as a 
-function of the cell mass) temperature as a function of density.
+centered at [0.5, 0.5, 0.5], with a normal vector of [0.0, 0.0, 1.0], radius of
+10 kiloparsecs and height of 3 kiloparsecs and will then make a plot of the
+mass-weighted average temperature as a function of density for all of the gas
+contained in the cylinder.
 
-As another example, we create a sphere of radius 100 pc and plot total mass 
-in every equally-spaced temperature bin/
-
-We could also have allowed the plot collection to create a sphere for us, as
-well.  For instance:
+We could also have made a profile considering only the gas in a sphere.
+For instance:
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   my_sphere = pf.sphere([0.5, 0.5, 0.5], (100, "kpc"))
-   plot = ProfilePlot(my_sphere, "temperature", ["cell_mass"],
-                      weight_field=None)
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   my_sphere = ds.sphere([0.5, 0.5, 0.5], (100, "kpc"))
+   plot = yt.ProfilePlot(my_sphere, "temperature", ["cell_mass"],
+                         weight_field=None)
    plot.save()
 
-Note that because we have specified the weighting field to be none, it operates 
-as a local-bin accumulator.  We can also accumulate along the x-axis by setting 
-the **accumulation** keyword argument to True, which is useful for plots of 
-enclosed mass.
+Note that because we have specified the weighting field to be none, it operates
+the profile plot will display the accumulated cell mass as a function of
+temperature rather than the average.  We can also accumulate along the x-axis by
+setting the **accumulation** keyword argument to True, which is useful for plots
+of enclosed mass.
+
+Also note the use of a ``(value, unit)`` tuple. These can be used interchangably
+with units explicitly imported from ``yt.units``.
 
 You can also access the data generated by profiles directly, which can be
 useful for overplotting average quantities on top of phase plots, or for
@@ -502,7 +562,7 @@
 made.  For each item in the list, the x field data can be accessed with ``x``.  
 The profiled fields can be accessed from the dictionary ``field_data``.
 
-.. code-block:: python
+.. notebook-cell::
 
    plot = ProfilePlot(my_sphere, "temperature", ["cell_mass"],
                       weight_field=None)
@@ -523,15 +583,15 @@
 
 It is often desirable to overplot multiple 1D profile to show evolution 
 with time.  This is supported with the ``from_profiles`` class method.  
-1D profiles are created with the :meth:`yt.data_objects.profiles.create_profile` 
+1D profiles are created with the :func:`yt.data_objects.profiles.create_profile` 
 method and then given to the ProfilePlot object.
 
 .. python-script::
 
-   from yt.mods import *
+   import yt
 
    # Create a time-series object.
-   es = simulation("enzo_tiny_cosmology/32Mpc_32.enzo", "Enzo")
+   es = yt.simulation("enzo_tiny_cosmology/32Mpc_32.enzo", "Enzo")
    es.get_time_series(redshifts=[5, 4, 3, 2, 1, 0])
 
 
@@ -540,23 +600,114 @@
    labels = []
 
    # Loop over each dataset in the time-series.
-   for pf in es:
+   for ds in es:
        # Create a data container to hold the whole dataset.
-       ad = pf.h.all_data()
+       ad = ds.h.all_data()
        # Create a 1d profile of density vs. temperature.
-       profiles.append(create_profile(ad, ["temperature"], 
-                                      fields=["cell_mass"],
-                                      weight_field=None,
-                                      accumulation=True))
+       profiles.append(yt.create_profile(ad, ["temperature"], 
+                                         fields=["cell_mass"],
+                                         weight_field=None,
+                                         accumulation=True))
        # Add labels
-       labels.append("z = %.2f" % pf.current_redshift)
+       labels.append("z = %.2f" % ds.current_redshift)
 
    # Create the profile plot from the list of profiles.
-   plot = ProfilePlot.from_profiles(profiles, labels=labels)
+   plot = yt.ProfilePlot.from_profiles(profiles, labels=labels)
 
    # Save the image.
    plot.save()
 
+Customizing axis limits
+~~~~~~~~~~~~~~~~~~~~~~~
+
+By default the x and y limits for ``ProfilePlot`` are determined using the
+:class:`~yt.data_objects.derived_quantities.Extrema` derived quantity.  If you
+want to create a plot with custom axis limits, you have two options.
+
+First, you can create a custom profile object using
+:func:`~yt.data_objects.profiles.create_profile`.  This function accepts a dictionary of ``(max, min)`` tuples keyed to field names.
+
+.. python-script::
+
+    import yt
+    import yt.units as u
+    ds = yt.load('IsolatedGalaxy/galaxy0030/galaxy0030')
+    sp = ds.sphere('m', 10*u.kpc)
+    profiles = yt.create_profile(sp, "temperature", "density",
+                                 weight_field=None, 
+                                 extrema={'temperature': (1e3, 1e7),
+                                          'density': (1e-26, 1e-22)})
+    plot = yt.ProfilePlot.from_profiles(profiles)
+    plot.save()
+
+You can also make use of the
+:meth:`yt.visualization.profile_plotter.ProfilePlot.set_xlim` and
+:meth:`yt.visualization.profile_plotter.ProfilePlot.set_ylim` functions to
+customize the axes limits of a plot that has already been created.  Note that
+calling ``set_xlim`` is much slower than calling ``set_ylim``.  This is because
+```set_xlim`` must recreate the profile object using the specified extrema.
+Creating a profile directly via ``create_profile`` might be significant faster.
+If you find that this operation is slow, consider creating your profile via
+``create_profile``.  Note that since there is only one bin field, ``set_xlim``
+does not accept a field name as the first argument.
+
+.. python-script::
+
+   import yt
+   import yt.units as u
+   ds = yt.load('IsolatedGalaxy/galaxy0030/galaxy0030')
+   sp = ds.sphere('m', 10*u.kpc)
+   plot = yt.ProfilePlot(sp, "temperature", "density", weight_field=None)
+   plot.set_xlim(1e3, 1e7)
+   plot.set_ylim("density", 1e-26, 1e-22)
+   plot.save()
+
+
+Customizing Units
+~~~~~~~~~~~~~~~~~
+
+Units for both the x and y axis can be controlled via the
+:meth:`~yt.visualization.profile_plotter.ProfilePlot.set_unit` method.
+Adjusting the plot units does not require recreating the histogram, so adjusting
+units will always be inexpensive, requiring only an in-place unit conversion.
+
+In the following example we create a a plot of the average density in solar
+masses per cubic parsec as a function of radius in kiloparsecs.
+
+.. python-script::
+
+    import yt
+    import yt.units as u
+    ds = yt.load('IsolatedGalaxy/galaxy0030/galaxy0030')
+    sp = ds.sphere('m', 10*u.kpc)
+    plot = yt.ProfilePlot(sp, "radius", "density", weight_field=None)
+    plot.set_unit("density", "msun/pc**3")
+    plot.set_unit("radius", "kpc")
+    plot.save()
+
+Linear and Logarithmic Scaling
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The axis scaling can be manipulated via the
+:meth:`~yt.visualization.profile_plotter.ProfilePlot.set_log` function.  This
+function accepts a field name and a boolean.  If the boolean is ``True``, the
+field is plotted in log scale.  If ``False``, the field is plotted in linear
+scale.
+
+In the following example we create a plot of the average x velocity as a
+function of radius.  Since the x component of the velocity vector can be
+negative, we set the scaling to be linear for this field.
+
+.. python-script::
+
+   import yt
+   import yt.units as u
+   ds = yt.load('IsolatedGalaxy/galaxy0030/galaxy0030')
+   sp = ds.sphere('m', 10*u.kpc)
+   plot = yt.ProfilePlot(sp, "radius", "x-velocity", weight_field=None)
+   plot.set_log("x-velocity", False)
+   plot.save()
+
 Altering Line Properties
 ~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -581,47 +732,72 @@
 2D Phase Plots
 --------------
 
-2D phase plots function in much the same was as 1D phase plots, but with a 
-:class:`~yt.visualization.profile_plotter.PhasePlot` object.  Much like 1D profiles, 
-2D profiles (phase plots) are best thought of as plotting a distribution of points, 
-either taking the average or the accumulation in a bin.  For example, to generate a 
-2D distribution of mass enclosed in density and temperature bins, you can do:
+2D phase plots function in much the same was as 1D phase plots, but with a
+:class:`~yt.visualization.profile_plotter.PhasePlot` object.  Much like 1D
+profiles, 2D profiles (phase plots) are best thought of as plotting a
+distribution of points, either taking the average or the accumulation in a bin.
+For example, to generate a 2D distribution of mass enclosed in density and
+temperature bins, you can do:
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   my_sphere = pf.sphere("c", (50, "kpc"))
-   plot = PhasePlot(my_sphere, "density", "temperature", ["cell_mass"],
-                    weight_field=None)
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   my_sphere = ds.sphere("c", (50, "kpc"))
+   plot = yt.PhasePlot(my_sphere, "density", "temperature", ["cell_mass"],
+                       weight_field=None)
    plot.save()
 
 If you would rather see the average value of a field as a function of two other
-fields, you can neglect supplying the *weight* parameter.  This would look
+fields, you can set the ``weight_field`` parameter to ``None``.  This would look
 something like:
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   my_sphere = pf.sphere("c", (50, "kpc"))
-   plot = PhasePlot(my_sphere, "density", "temperature", ["H_fraction"],
-                    weight_field="cell_mass")
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   my_sphere = ds.sphere("c", (50, "kpc"))
+   plot = yt.PhasePlot(my_sphere, "density", "temperature", ["H_fraction"],
+                       weight_field=None)
+   plot.save()
+
+Customizing Phase Plots
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Similarly to 1D profile plots, ``PhasePlot`` can be customized via ``set_unit``,
+``set_xlim``, ``set_ylim``, and ``set_zlim``.  The following example illustrates
+how to manipulate these functions.
+
+.. python-script::
+
+   import yt
+   ds = yt.load("sizmbhloz-clref04SNth-rs9_a0.9011/sizmbhloz-clref04SNth-rs9_a0.9011.art")
+   center = ds.arr([64.0, 64.0, 64.0], 'code_length')
+   rvir = ds.quan(1e-1, "Mpccm/h")
+
+   sph = ds.sphere(center, rvir)
+   plot = yt.PhasePlot(sph, "density", "temperature", "cell_mass",
+                       weight_field=None)
+   plot.set_unit('density', 'Msun/pc**3')
+   plot.set_unit('cell_mass', 'Msun')
+   plot.set_xlim(1e-5,1e1)
+   plot.set_ylim(1,1e7)
    plot.save()
 
 Probability Distribution Functions and Accumulation
 ---------------------------------------------------
 
-Both 1D and 2D profiles which show the total of amount of some field, such as mass, 
-in a bin (done by setting the **weight_field** keyword to None) can be turned into 
-probability distribution functions (PDFs) by setting the **fractional** keyword to 
-True.  When set to True, the value in each bin is divided by the sum total from all 
-bins.  These can be turned into cumulative distribution functions (CDFs) by setting 
-the **accumulation** keyword to True.  This will make is so that the value in any bin 
-N is the cumulative sum of all bins from 0 to N.  The direction of the summation can be 
-rversed by setting **accumulation** to -True.  For PhasePlots, the accumulation can be 
-set independently for each axis by setting **accumulation** to a list of True/-True/False 
-values.
+Both 1D and 2D profiles which show the total of amount of some field, such as
+mass, in a bin (done by setting the ``weight_field`` keyword to ``None``) can be
+turned into probability distribution functions (PDFs) by setting the
+``fractional`` keyword to ``True``.  When set to ``True``, the value in each bin
+is divided by the sum total from all bins.  These can be turned into cumulative
+distribution functions (CDFs) by setting the ``accumulation`` keyword to
+``True``.  This will make is so that the value in any bin N is the cumulative
+sum of all bins from 0 to N.  The direction of the summation can be reversed by
+setting ``accumulation`` to ``-True``.  For ``PhasePlot``, the accumulation can
+be set independently for each axis by setting ``accumulation`` to a list of
+``True``/ ``-True`` /``False`` values.
 
 .. _interactive-plotting:
 
@@ -646,9 +822,9 @@
 
 .. notebook-cell::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   p = ProjectionPlot(pf, "x", "density", center='m', width=(10,'kpc'),
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   p = ProjectionPlot(ds, "x", "density", center='m', width=(10,'kpc'),
                       weight_field='density')
    p.show()
 
@@ -682,7 +858,7 @@
 .. code-block:: python
 
    >>> import yt.visualization.eps_writer as eps
-   >>> slc = SlicePlot(pf, 'z', 'density')
+   >>> slc = yt.SlicePlot(ds, 'z', 'density')
    >>> slc.set_width(25, 'kpc')
    >>> eps_fig = eps.single_plot(slc)
    >>> eps_fig.save_fig('zoom', format='eps')
@@ -706,9 +882,11 @@
 
 .. code-block:: python
 
+   >>> import yt
    >>> import yt.visualization.eps_writer as eps
-   >>> slc = SlicePlot(pf, 'z', ['density', 'temperature', 'Pressure',
-                       'VelocityMagnitude'])
+   >>>
+   >>> slc = yt.SlicePlot(ds, 'z', ['density', 'temperature', 'Pressure',
+                          'VelocityMagnitude'])
    >>> slc.set_width(25, 'kpc')
    >>> eps_fig = eps.multiplot_yt(2, 2, slc, bare_axes=True)
    >>> eps_fig.scale_line(0.2, '5 kpc')

diff -r 103131490fefcf01b2a7288ad246869fe853dd47 -r 94182bf987253d6d1cffc464e82a545bb1e64919 yt/utilities/amr_kdtree/amr_kdtree.py
--- a/yt/utilities/amr_kdtree/amr_kdtree.py
+++ b/yt/utilities/amr_kdtree/amr_kdtree.py
@@ -185,7 +185,7 @@
             yield self.get_brick_data(node)
 
     def slice_traverse(self, viewpoint = None):
-        if not hasattr(self.pf.h, "grid"):
+        if not hasattr(self.pf.index, "grid"):
             raise NotImplementedError
         for node in kd_traverse(self.tree.trunk, viewpoint=viewpoint):
             grid = self.pf.index.grids[node.grid - self._id_offset]

diff -r 103131490fefcf01b2a7288ad246869fe853dd47 -r 94182bf987253d6d1cffc464e82a545bb1e64919 yt/visualization/plot_modifications.py
--- a/yt/visualization/plot_modifications.py
+++ b/yt/visualization/plot_modifications.py
@@ -548,8 +548,12 @@
         self.plot_args = plot_args
 
     def __call__(self, plot):
+        xx0, xx1 = plot._axes.get_xlim()
+        yy0, yy1 = plot._axes.get_ylim()
         plot._axes.hold(True)
         plot._axes.plot(self.x, self.y, **self.plot_args)
+        plot._axes.set_xlim(xx0,xx1)
+        plot._axes.set_ylim(yy0,yy1)
         plot._axes.hold(False)
 
 class ImageLineCallback(LinePlotCallback):
@@ -718,7 +722,8 @@
             pos = self.pos[xi], self.pos[yi]
         else: pos = self.pos
         if isinstance(self.code_size[1], basestring):
-            code_size = plot.data.pf.quan(*self.code_size).value
+            code_size = plot.data.pf.quan(*self.code_size)
+            code_size = code_size.in_units('code_length').value
             self.code_size = (code_size, code_size)
         from matplotlib.patches import Arrow
         # Now convert the pixels to code information
@@ -812,7 +817,7 @@
 
         if iterable(self.radius):
             self.radius = plot.data.pf.quan(self.radius[0], self.radius[1])
-            self.radius = np.float64(self.radius)
+            self.radius = np.float64(self.radius.in_units(plot.xlim[0].units))
 
         radius = self.radius * self.pixel_scale(plot)[0]
 

diff -r 103131490fefcf01b2a7288ad246869fe853dd47 -r 94182bf987253d6d1cffc464e82a545bb1e64919 yt/visualization/plot_window.py
--- a/yt/visualization/plot_window.py
+++ b/yt/visualization/plot_window.py
@@ -1680,6 +1680,7 @@
 
 
 class WindowPlotMPL(ImagePlotMPL):
+    """A container for a single PlotWindow matplotlib figure and axes"""
     def __init__(self, data, cbname, cmap, extent, zlim, figure_size, fontsize,
                  unit_aspect, figure, axes, cax):
         self._draw_colorbar = True
@@ -1855,7 +1856,7 @@
         if np.count_nonzero(normal) == 1:
             normal = ("x","y","z")[np.nonzero(normal)[0][0]]
         else:
-            normal = np.array(normal)
+            normal = np.array(normal, dtype='float64')
             np.divide(normal, np.dot(normal,normal), normal)
 
     # by now the normal should be properly set to get either a On/Off Axis plot

diff -r 103131490fefcf01b2a7288ad246869fe853dd47 -r 94182bf987253d6d1cffc464e82a545bb1e64919 yt/visualization/profile_plotter.py
--- a/yt/visualization/profile_plotter.py
+++ b/yt/visualization/profile_plotter.py
@@ -1071,6 +1071,7 @@
 
 
 class PhasePlotMPL(ImagePlotMPL):
+    """A container for a single matplotlib figure and axes for a PhasePlot"""
     def __init__(self, x_data, y_data, data,
                  x_scale, y_scale, z_scale, cmap,
                  zlim, figure_size, fontsize, figure, axes, cax):


https://bitbucket.org/yt_analysis/yt/commits/4059ceb57653/
Changeset:   4059ceb57653
Branch:      yt-3.0
User:        ngoldbaum
Date:        2014-06-30 08:37:32
Summary:     Fixing two minor errors not covered by the previous commit.
Affected #:  1 file

diff -r 94182bf987253d6d1cffc464e82a545bb1e64919 -r 4059ceb5765358f28fbed9839c36b7d089bbb98f doc/source/visualizing/plots.rst
--- a/doc/source/visualizing/plots.rst
+++ b/doc/source/visualizing/plots.rst
@@ -562,21 +562,19 @@
 made.  For each item in the list, the x field data can be accessed with ``x``.  
 The profiled fields can be accessed from the dictionary ``field_data``.
 
-.. notebook-cell::
+.. code-block:: python
 
    plot = ProfilePlot(my_sphere, "temperature", ["cell_mass"],
                       weight_field=None)
-   # print the x field
+   profile = plot.profiles[0]
+   # print the bin field, in this case temperature
    print plot.profiles[-1].x
-   # print the profiled temperature field
-   print plot.profiles[-1].field_data["temperature"]
+   # print the profiled cell_mass field
+   print plot.profiles[-1]["cell_mass"]
 
-Other options, such as the number of bins, are also configurable. See the 
-documentation for 
-The number of bins and other options and tweaks are 
-available for these methods.  See the documentation for 
-:class:`~yt.visualization.profile_plotter.ProfilePlot`
-for more information.
+Other options, such as the number of bins, are also configurable. See the
+documentation for :class:`~yt.visualization.profile_plotter.ProfilePlot` for
+more information.
 
 Overplotting Multiple 1D Profiles
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -602,7 +600,7 @@
    # Loop over each dataset in the time-series.
    for ds in es:
        # Create a data container to hold the whole dataset.
-       ad = ds.h.all_data()
+       ad = ds.all_data()
        # Create a 1d profile of density vs. temperature.
        profiles.append(yt.create_profile(ad, ["temperature"], 
                                          fields=["cell_mass"],


https://bitbucket.org/yt_analysis/yt/commits/1e3f253ad978/
Changeset:   1e3f253ad978
Branch:      yt-3.0
User:        ngoldbaum
Date:        2014-07-06 14:39:11
Summary:     Merging with mainline tip.
Affected #:  36 files

diff -r 4059ceb5765358f28fbed9839c36b7d089bbb98f -r 1e3f253ad97810f36d634c5e307a6710294e9505 doc/install_script.sh
--- a/doc/install_script.sh
+++ b/doc/install_script.sh
@@ -567,8 +567,10 @@
 
 mkdir -p ${DEST_DIR}/data
 cd ${DEST_DIR}/data
-echo 'de6d8c6ea849f0206d219303329a0276b3cce7c051eec34377d42aacbe0a4f47ac5145eb08966a338ecddd2b83c8f787ca9956508ad5c39ee2088ad875166410  xray_emissivity.h5' > xray_emissivity.h5.sha512
-[ ! -e xray_emissivity.h5 ] && get_ytdata xray_emissivity.h5
+echo 'de6d8c6ea849f0206d219303329a0276b3cce7c051eec34377d42aacbe0a4f47ac5145eb08966a338ecddd2b83c8f787ca9956508ad5c39ee2088ad875166410  cloudy_emissivity.h5' > cloudy_emissivity.h5.sha512
+[ ! -e cloudy_emissivity.h5 ] && get_ytdata cloudy_emissivity.h5
+echo '0f714ae2eace0141b1381abf1160dc8f8a521335e886f99919caf3beb31df1fe271d67c7b2a804b1467949eb16b0ef87a3d53abad0e8160fccac1e90d8d9e85f  apec_emissivity.h5' > apec_emissivity.h5.sha512
+[ ! -e apec_emissivity.h5 ] && get_ytdata apec_emissivity.h5
 
 # Set paths to what they should be when yt is activated.
 export PATH=${DEST_DIR}/bin:$PATH

diff -r 4059ceb5765358f28fbed9839c36b7d089bbb98f -r 1e3f253ad97810f36d634c5e307a6710294e9505 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
@@ -1,6 +1,11 @@
 Constructing Mock X-ray Observations
 ------------------------------------
 
+.. note::
+
+  If you just want to create derived fields for X-ray emission,
+  you should go `here <xray_emission_fields.html>`_ instead.
+
 The ``photon_simulator`` analysis module enables the creation of
 simulated X-ray photon lists of events from datasets that ``yt`` is able
 to read. The simulated events then can be exported to X-ray telescope

diff -r 4059ceb5765358f28fbed9839c36b7d089bbb98f -r 1e3f253ad97810f36d634c5e307a6710294e9505 doc/source/analyzing/analysis_modules/xray_emission_fields.rst
--- a/doc/source/analyzing/analysis_modules/xray_emission_fields.rst
+++ b/doc/source/analyzing/analysis_modules/xray_emission_fields.rst
@@ -2,41 +2,46 @@
 
 X-ray Emission Fields
 =====================
-.. sectionauthor:: Britton Smith <brittonsmith at gmail.com>
+.. sectionauthor:: Britton Smith <brittonsmith at gmail.com>, John ZuHone <jzuhone at gmail.com>
+
+.. note::
+
+  If you came here trying to figure out how to create simulated X-ray photons and observations,
+  you should go `here <photon_simulator.html>`_ instead.
 
 This functionality provides the ability to create metallicity-dependent 
-X-ray luminosity, emissivity, and photo emissivity fields for a given 
+X-ray luminosity, emissivity, and photon emissivity fields for a given
 photon energy range.  This works by interpolating from emission tables 
-created with the photoionization code, `Cloudy <http://nublado.org/>`_.  
-If you installed yt with the install script, the data should be located in 
-the *data* directory inside the installation directory.  Emission fields can 
-be made for any interval between 0.1 keV and 100 keV.
+created from the photoionization code `Cloudy <http://nublado.org/>`_ or
+the collisional ionization database `AtomDB <http://www.atomdb.org>`_. If
+you installed yt with the install script, these data files should be located in
+the *data* directory inside the installation directory, or can be downloaded
+from `<http://yt-project.org/data>`_. Emission fields can be made for any
+interval between 0.1 keV and 100 keV.
 
 Adding Emission Fields
 ----------------------
 
-Fields can be created for luminosity (erg/s), emissivity (erg/s/cm^3), 
-and photon emissivity (photons/s/cm^3).  The only required arguments are 
-the minimum and maximum energies.
+Fields will be created for luminosity :math:`{\rm (erg~s^{-1})}`, emissivity :math:`{\rm (erg~s^{-1}~cm^{-3})}`,
+and photon emissivity :math:`{\rm (photons~s^{-1}~cm^{-3})}`.  The only required arguments are the
+dataset object, and the minimum and maximum energies of the energy band.
 
 .. code-block:: python
 
-  from yt.mods import *
+  import yt
   from yt.analysis_modules.spectral_integrator.api import \
-       add_xray_luminosity_field, \
-       add_xray_emissivity_field, \
-       add_xray_photon_emissivity_field
+       add_xray_emissivity_field
 
-  add_xray_luminosity_field(0.5, 7)
-  add_xray_emissivity_field(0.5, 7)
-  add_xray_photon_emissivity_field(0.5, 7)
+  xray_fields = add_xray_emissivity_field(0.5, 7.0)
 
 Additional keyword arguments are:
 
- * **filename**  (*string*): Path to data file containing emissivity 
-   values.  If None, a file called xray_emissivity.h5 is used.  This file 
-   contains emissivity tables for primordial elements and for metals at 
-   solar metallicity for the energy range 0.1 to 100 keV.  Default: None.
+ * **filename** (*string*): Path to data file containing emissivity values. If None,
+   a file called "cloudy_emissivity.h5" is used, for photoionized plasmas. A second
+   option, for collisionally ionized plasmas, is in the file "apec_emissivity.h5",
+   available at http://yt-project.org/data. These files contain emissivity tables
+   for primordial elements and for metals at solar metallicity for the energy range
+   0.1 to 100 keV. Default: None.
 
  * **with_metals** (*bool*): If True, use the metallicity field to add the 
    contribution from metals.  If False, only the emission from H/He is 
@@ -46,24 +51,27 @@
    metallicity for the emission from metals.  The *with_metals* keyword 
    must be set to False to use this.  Default: None.
 
-The resulting fields can be used like all normal fields.
+The resulting fields can be used like all normal fields. The function will return the names of
+the created fields in a Python list.
 
-.. python-script::
+.. code-block:: python
 
-  from yt.mods import *
+  import yt
   from yt.analysis_modules.spectral_integrator.api import \
-       add_xray_luminosity_field, \
-       add_xray_emissivity_field, \
-       add_xray_photon_emissivity_field
+       add_xray_emissivity_field
 
-  add_xray_luminosity_field(0.5, 7)
-  add_xray_emissivity_field(0.5, 7)
-  add_xray_photon_emissivity_field(0.5, 7)
+  xray_fields = add_xray_emissivity_field(0.5, 7.0, filename="apec_emissivity.h5")
 
-  pf = load("enzo_tiny_cosmology/DD0046/DD0046")
-  plot = SlicePlot(pf, 'x', 'Xray_Luminosity_0.5_7keV')
+  ds = yt.load("enzo_tiny_cosmology/DD0046/DD0046")
+  plot = yt.SlicePlot(ds, 'x', 'xray_luminosity_0.5_7.0_keV')
   plot.save()
-  plot = ProjectionPlot(pf, 'x', 'Xray_Emissivity_0.5_7keV')
+  plot = yt.ProjectionPlot(ds, 'x', 'xray_emissivity_0.5_7.0_keV')
   plot.save()
-  plot = ProjectionPlot(pf, 'x', 'Xray_Photon_Emissivity_0.5_7keV')
+  plot = yt.ProjectionPlot(ds, 'x', 'xray_photon_emissivity_0.5_7.0_keV')
   plot.save()
+
+.. warning::
+
+  The X-ray fields depend on the number density of hydrogen atoms, in the yt field
+  ``H_number_density``. If this field is not defined (either in the dataset or by the user),
+  the primordial hydrogen mass fraction (X = 0.76) will be used to construct it.
\ No newline at end of file

diff -r 4059ceb5765358f28fbed9839c36b7d089bbb98f -r 1e3f253ad97810f36d634c5e307a6710294e9505 doc/source/cookbook/aligned_cutting_plane.py
--- a/doc/source/cookbook/aligned_cutting_plane.py
+++ /dev/null
@@ -1,20 +0,0 @@
-### THIS RECIPE IS CURRENTLY BROKEN IN YT-3.0
-### DO NOT TRUST THIS RECIPE UNTIL THIS LINE IS REMOVED
-
-import yt
-
-# Load the dataset.
-ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
-
-# Create a 15 kpc radius sphere, centered on the center of the sim volume
-sp = ds.sphere("center", (15.0, "kpc"))
-
-# Get the angular momentum vector for the sphere.
-L = sp.quantities.angular_momentum_vector()
-
-print "Angular momentum vector: {0}".format(L)
-
-# Create an OffAxisSlicePlot of density centered on the object with the L 
-# vector as its normal and a width of 25 kpc on a side
-p = yt.OffAxisSlicePlot(ds, L, "density", sp.center, (25, "kpc"))
-p.save()

diff -r 4059ceb5765358f28fbed9839c36b7d089bbb98f -r 1e3f253ad97810f36d634c5e307a6710294e9505 doc/source/cookbook/camera_movement.py
--- a/doc/source/cookbook/camera_movement.py
+++ b/doc/source/cookbook/camera_movement.py
@@ -1,6 +1,3 @@
-### THIS RECIPE IS CURRENTLY BROKEN IN YT-3.0
-### DO NOT TRUST THIS RECIPE UNTIL THIS LINE IS REMOVED
-
 import yt
 import numpy as np
 

diff -r 4059ceb5765358f28fbed9839c36b7d089bbb98f -r 1e3f253ad97810f36d634c5e307a6710294e9505 doc/source/cookbook/halo_plotting.py
--- a/doc/source/cookbook/halo_plotting.py
+++ b/doc/source/cookbook/halo_plotting.py
@@ -1,6 +1,3 @@
-### THIS RECIPE IS CURRENTLY BROKEN IN YT-3.0
-### DO NOT TRUST THIS RECIPE UNTIL THIS LINE IS REMOVED
-
 import yt
 from yt.analysis_modules.halo_analysis.halo_catalog import HaloCatalog
 

diff -r 4059ceb5765358f28fbed9839c36b7d089bbb98f -r 1e3f253ad97810f36d634c5e307a6710294e9505 doc/source/cookbook/rad_velocity.py
--- a/doc/source/cookbook/rad_velocity.py
+++ b/doc/source/cookbook/rad_velocity.py
@@ -1,6 +1,3 @@
-### THIS RECIPE IS CURRENTLY BROKEN IN YT-3.0
-### DO NOT TRUST THIS RECIPE UNTIL THIS LINE IS REMOVED
-
 import yt
 import matplotlib.pyplot as plt
 

diff -r 4059ceb5765358f28fbed9839c36b7d089bbb98f -r 1e3f253ad97810f36d634c5e307a6710294e9505 doc/source/cookbook/radial_profile_styles.py
--- a/doc/source/cookbook/radial_profile_styles.py
+++ b/doc/source/cookbook/radial_profile_styles.py
@@ -1,6 +1,3 @@
-### THIS RECIPE IS CURRENTLY BROKEN IN YT-3.0
-### DO NOT TRUST THIS RECIPE UNTIL THIS LINE IS REMOVED
-
 import yt
 import matplotlib.pyplot as plt
 

diff -r 4059ceb5765358f28fbed9839c36b7d089bbb98f -r 1e3f253ad97810f36d634c5e307a6710294e9505 doc/source/cookbook/simple_off_axis_projection.py
--- a/doc/source/cookbook/simple_off_axis_projection.py
+++ b/doc/source/cookbook/simple_off_axis_projection.py
@@ -3,9 +3,7 @@
 # Load the dataset.
 ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
 
-# Create a 1 kpc radius sphere, centered on the max density.  Note that this
-# sphere is very small compared to the size of our final plot, and it has a
-# non-axially aligned L vector.
+# Create a 15 kpc radius sphere, centered on the center of the sim volume
 sp = ds.sphere("center", (15.0, "kpc"))
 
 # Get the angular momentum vector for the sphere.
@@ -13,6 +11,7 @@
 
 print "Angular momentum vector: {0}".format(L)
 
-# Create an OffAxisSlicePlot on the object with the L vector as its normal
+# Create an OffAxisProjectionPlot of density centered on the object with the L 
+# vector as its normal and a width of 25 kpc on a side
 p = yt.OffAxisProjectionPlot(ds, L, "density", sp.center, (25, "kpc"))
 p.save()

diff -r 4059ceb5765358f28fbed9839c36b7d089bbb98f -r 1e3f253ad97810f36d634c5e307a6710294e9505 doc/source/cookbook/simple_off_axis_slice.py
--- /dev/null
+++ b/doc/source/cookbook/simple_off_axis_slice.py
@@ -0,0 +1,17 @@
+import yt
+
+# Load the dataset.
+ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+
+# Create a 15 kpc radius sphere, centered on the center of the sim volume
+sp = ds.sphere("center", (15.0, "kpc"))
+
+# Get the angular momentum vector for the sphere.
+L = sp.quantities.angular_momentum_vector()
+
+print "Angular momentum vector: {0}".format(L)
+
+# Create an OffAxisSlicePlot of density centered on the object with the L 
+# vector as its normal and a width of 25 kpc on a side
+p = yt.OffAxisSlicePlot(ds, L, "density", sp.center, (25, "kpc"))
+p.save()

diff -r 4059ceb5765358f28fbed9839c36b7d089bbb98f -r 1e3f253ad97810f36d634c5e307a6710294e9505 doc/source/cookbook/simple_plots.rst
--- a/doc/source/cookbook/simple_plots.rst
+++ b/doc/source/cookbook/simple_plots.rst
@@ -49,8 +49,7 @@
 Simple Radial Profiles
 ~~~~~~~~~~~~~~~~~~~~~~
 
-This shows how to make a profile of a quantity with respect to the radius, in
-this case the radius in Mpc.
+This shows how to make a profile of a quantity with respect to the radius.
 
 .. yt_cookbook:: simple_radial_profile.py
 
@@ -87,17 +86,17 @@
 Off-Axis Slicing
 ~~~~~~~~~~~~~~~~
 
-A cutting plane allows you to slice at some angle that isn't aligned with the
-axes.
+One can create slices from any arbitrary angle, not just those aligned with
+the x,y,z axes.
 
-.. yt_cookbook:: aligned_cutting_plane.py
+.. yt_cookbook:: simple_off_axis_slice.py
 
 .. _cookbook-simple-off-axis-projection:
 
 Off-Axis Projection
 ~~~~~~~~~~~~~~~~~~~
 
-Like cutting planes, off-axis projections can be created from any arbitrary 
+Like off-axis slices, off-axis projections can be created from any arbitrary 
 viewing angle.
 
 .. yt_cookbook:: simple_off_axis_projection.py

diff -r 4059ceb5765358f28fbed9839c36b7d089bbb98f -r 1e3f253ad97810f36d634c5e307a6710294e9505 doc/source/cookbook/simple_slice_with_multiple_fields.py
--- a/doc/source/cookbook/simple_slice_with_multiple_fields.py
+++ b/doc/source/cookbook/simple_slice_with_multiple_fields.py
@@ -1,6 +1,3 @@
-### THIS RECIPE IS CURRENTLY BROKEN IN YT-3.0
-### DO NOT TRUST THIS RECIPE UNTIL THIS LINE IS REMOVED
-
 import yt
 
 # Load the dataset

diff -r 4059ceb5765358f28fbed9839c36b7d089bbb98f -r 1e3f253ad97810f36d634c5e307a6710294e9505 doc/source/cookbook/time_series_profiles.py
--- a/doc/source/cookbook/time_series_profiles.py
+++ b/doc/source/cookbook/time_series_profiles.py
@@ -1,6 +1,3 @@
-### THIS RECIPE IS CURRENTLY BROKEN IN YT-3.0
-### DO NOT TRUST THIS RECIPE UNTIL THIS LINE IS REMOVED
-
 import yt
 
 # Create a time-series object.

diff -r 4059ceb5765358f28fbed9839c36b7d089bbb98f -r 1e3f253ad97810f36d634c5e307a6710294e9505 doc/source/reference/api/api.rst
--- a/doc/source/reference/api/api.rst
+++ b/doc/source/reference/api/api.rst
@@ -552,8 +552,6 @@
    ~yt.analysis_modules.absorption_spectrum.absorption_spectrum.AbsorptionSpectrum
    ~yt.analysis_modules.spectral_integrator.spectral_frequency_integrator.EmissivityIntegrator
    ~yt.analysis_modules.spectral_integrator.spectral_frequency_integrator.add_xray_emissivity_field
-   ~yt.analysis_modules.spectral_integrator.spectral_frequency_integrator.add_xray_luminosity_field
-   ~yt.analysis_modules.spectral_integrator.spectral_frequency_integrator.add_xray_photon_emissivity_field
 
 Absorption spectra fitting:
 

diff -r 4059ceb5765358f28fbed9839c36b7d089bbb98f -r 1e3f253ad97810f36d634c5e307a6710294e9505 yt/analysis_modules/api.py
--- a/yt/analysis_modules/api.py
+++ b/yt/analysis_modules/api.py
@@ -84,9 +84,7 @@
     RadialColumnDensity
 
 from .spectral_integrator.api import \
-     add_xray_emissivity_field, \
-     add_xray_luminosity_field, \
-     add_xray_photon_emissivity_field
+     add_xray_emissivity_field
 
 from .star_analysis.api import \
     StarFormationRate, \

diff -r 4059ceb5765358f28fbed9839c36b7d089bbb98f -r 1e3f253ad97810f36d634c5e307a6710294e9505 yt/analysis_modules/halo_analysis/halo_catalog.py
--- a/yt/analysis_modules/halo_analysis/halo_catalog.py
+++ b/yt/analysis_modules/halo_analysis/halo_catalog.py
@@ -59,6 +59,8 @@
     output_dir : str
         The top level directory into which analysis output will be written.
         Default: "."
+    finder_kwargs : dict
+        Arguments to pass to the halo finder if finder_method is given.
 
     Examples
     --------
@@ -98,6 +100,7 @@
     
     def __init__(self, halos_pf=None, data_pf=None, 
                  data_source=None, finder_method=None, 
+                 finder_kwargs=None,
                  output_dir="halo_catalogs/catalog"):
         ParallelAnalysisInterface.__init__(self)
         self.halos_pf = halos_pf
@@ -122,8 +125,11 @@
         self.data_source = data_source
 
         if finder_method is not None:
-            finder_method = finding_method_registry.find(finder_method)
+            finder_method = finding_method_registry.find(finder_method,
+                        **finder_kwargs)
         self.finder_method = finder_method            
+        if finder_kwargs is None:
+            finder_kwargs = {}
         
         # all of the analysis actions to be performed: callbacks, filters, and quantities
         self.actions = []
@@ -203,6 +209,7 @@
             field_type = kwargs.pop("field_type")
         else:
             field_type = None
+        prepend = kwargs.pop("prepend",False)
         if field_type is None:
             quantity = quantity_registry.find(key, *args, **kwargs)
         elif (field_type, key) in self.halos_pf.field_info:
@@ -210,7 +217,10 @@
         else:
             raise RuntimeError("HaloCatalog quantity must be a registered function or a field of a known type.")
         self.quantities.append(key)
-        self.actions.append(("quantity", (key, quantity)))
+        if prepend:
+            self.actions.insert(0, ("quantity", (key, quantity)))
+        else:
+            self.actions.append(("quantity", (key, quantity)))
 
     def add_filter(self, halo_filter, *args, **kwargs):
         r"""
@@ -430,10 +440,10 @@
         out_file.close()
 
     def add_default_quantities(self, field_type='halos'):
-        self.add_quantity("particle_identifier", field_type=field_type)
-        self.add_quantity("particle_mass", field_type=field_type)
-        self.add_quantity("particle_position_x", field_type=field_type)
-        self.add_quantity("particle_position_y", field_type=field_type)
-        self.add_quantity("particle_position_z", field_type=field_type)
-        self.add_quantity("virial_radius", field_type=field_type)
+        self.add_quantity("particle_identifier", field_type=field_type,prepend=True)
+        self.add_quantity("particle_mass", field_type=field_type,prepend=True)
+        self.add_quantity("particle_position_x", field_type=field_type,prepend=True)
+        self.add_quantity("particle_position_y", field_type=field_type,prepend=True)
+        self.add_quantity("particle_position_z", field_type=field_type,prepend=True)
+        self.add_quantity("virial_radius", field_type=field_type,prepend=True)
 

diff -r 4059ceb5765358f28fbed9839c36b7d089bbb98f -r 1e3f253ad97810f36d634c5e307a6710294e9505 yt/analysis_modules/halo_analysis/halo_finding_methods.py
--- a/yt/analysis_modules/halo_analysis/halo_finding_methods.py
+++ b/yt/analysis_modules/halo_analysis/halo_finding_methods.py
@@ -44,27 +44,27 @@
     def __call__(self, ds):
         return self.function(ds, *self.args, **self.kwargs)
 
-def _hop_method(pf):
+def _hop_method(pf, **finder_kwargs):
     r"""
     Run the Hop halo finding method.
     """
     
-    halo_list = HOPHaloFinder(pf)
+    halo_list = HOPHaloFinder(pf, **finder_kwargs)
     halos_pf = _parse_old_halo_list(pf, halo_list)
     return halos_pf
 add_finding_method("hop", _hop_method)
 
-def _fof_method(pf):
+def _fof_method(pf, **finder_kwargs):
     r"""
     Run the FoF halo finding method.
     """
 
-    halo_list = FOFHaloFinder(pf)
+    halo_list = FOFHaloFinder(pf, **finder_kwargs)
     halos_pf = _parse_old_halo_list(pf, halo_list)
     return halos_pf
 add_finding_method("fof", _fof_method)
 
-def _rockstar_method(pf):
+def _rockstar_method(pf, **finder_kwargs):
     r"""
     Run the Rockstar halo finding method.
     """
@@ -74,7 +74,7 @@
     from yt.analysis_modules.halo_finding.rockstar.api import \
      RockstarHaloFinder
     
-    rh = RockstarHaloFinder(pf)
+    rh = RockstarHaloFinder(pf, **finder_kwargs)
     rh.run()
 
 

diff -r 4059ceb5765358f28fbed9839c36b7d089bbb98f -r 1e3f253ad97810f36d634c5e307a6710294e9505 yt/analysis_modules/photon_simulator/photon_simulator.py
--- a/yt/analysis_modules/photon_simulator/photon_simulator.py
+++ b/yt/analysis_modules/photon_simulator/photon_simulator.py
@@ -956,7 +956,7 @@
 
         if isinstance(self.parameters["Area"], basestring):
              mylog.error("Writing SIMPUT files is only supported if you didn't convolve with an ARF.")
-             raise TypeError
+             raise TypeError("Writing SIMPUT files is only supported if you didn't convolve with an ARF.")
         
         if emin is None:
             emin = self.events["eobs"].min().value*0.95
@@ -1032,7 +1032,10 @@
         f = h5py.File(h5file, "w")
 
         f.create_dataset("/exp_time", data=float(self.parameters["ExposureTime"]))
-        f.create_dataset("/area", data=float(self.parameters["Area"]))
+        area = self.parameters["Area"]
+        if not isinstance(area, basestring):
+            area = float(area)
+        f.create_dataset("/area", data=area)
         f.create_dataset("/redshift", data=self.parameters["Redshift"])
         f.create_dataset("/d_a", data=float(self.parameters["AngularDiameterDistance"]))
         if "ARF" in self.parameters:

diff -r 4059ceb5765358f28fbed9839c36b7d089bbb98f -r 1e3f253ad97810f36d634c5e307a6710294e9505 yt/analysis_modules/photon_simulator/spectral_models.py
--- a/yt/analysis_modules/photon_simulator/spectral_models.py
+++ b/yt/analysis_modules/photon_simulator/spectral_models.py
@@ -181,7 +181,7 @@
     Examples
     --------
     >>> apec_model = TableApecModel("/Users/jzuhone/Data/atomdb_v2.0.2/", 0.05, 50.0,
-                                    1000, thermal_broad=True)
+    ...                             1000, thermal_broad=True)
     """
     def __init__(self, apec_root, emin, emax, nchan,
                  apec_vers="2.0.2", thermal_broad=False):
@@ -226,7 +226,7 @@
         
         tmpspec = np.zeros((self.nchan))
         
-        i = np.where((self.line_handle[tindex].data.field('element')==element) &
+        i = np.where((self.line_handle[tindex].data.field('element') == element) &
                      (self.line_handle[tindex].data.field('lambda') > self.minlam) &
                      (self.line_handle[tindex].data.field('lambda') < self.maxlam))[0]
 
@@ -242,24 +242,24 @@
                 vec += np.diff(cdf)*a
         else:
             ie = np.searchsorted(ebins, E0, side='right')-1
-            for i,a in zip(ie,amp): vec[i] += a
+            for i, a in zip(ie, amp): vec[i] += a
         tmpspec += vec
 
-        ind = np.where((self.coco_handle[tindex].data.field('Z')==element) &
-                       (self.coco_handle[tindex].data.field('rmJ')==0))[0]
-        if len(ind)==0:
+        ind = np.where((self.coco_handle[tindex].data.field('Z') == element) &
+                       (self.coco_handle[tindex].data.field('rmJ') == 0))[0]
+        if len(ind) == 0:
             return tmpspec
         else:
-            ind=ind[0]
+            ind = ind[0]
                                                     
-        n_cont=self.coco_handle[tindex].data.field('N_Cont')[ind]
-        e_cont=self.coco_handle[tindex].data.field('E_Cont')[ind][:n_cont]
+        n_cont = self.coco_handle[tindex].data.field('N_Cont')[ind]
+        e_cont = self.coco_handle[tindex].data.field('E_Cont')[ind][:n_cont]
         continuum = self.coco_handle[tindex].data.field('Continuum')[ind][:n_cont]
 
         tmpspec += np.interp(self.emid.ndarray_view(), e_cont, continuum)*self.de.ndarray_view()
         
-        n_pseudo=self.coco_handle[tindex].data.field('N_Pseudo')[ind]
-        e_pseudo=self.coco_handle[tindex].data.field('E_Pseudo')[ind][:n_pseudo]
+        n_pseudo = self.coco_handle[tindex].data.field('N_Pseudo')[ind]
+        e_pseudo = self.coco_handle[tindex].data.field('E_Pseudo')[ind][:n_pseudo]
         pseudo = self.coco_handle[tindex].data.field('Pseudo')[ind][:n_pseudo]
         
         tmpspec += np.interp(self.emid.ndarray_view(), e_pseudo, pseudo)*self.de.ndarray_view()

diff -r 4059ceb5765358f28fbed9839c36b7d089bbb98f -r 1e3f253ad97810f36d634c5e307a6710294e9505 yt/analysis_modules/spectral_integrator/api.py
--- a/yt/analysis_modules/spectral_integrator/api.py
+++ b/yt/analysis_modules/spectral_integrator/api.py
@@ -15,6 +15,4 @@
 
 from .spectral_frequency_integrator import \
     EmissivityIntegrator, \
-    add_xray_emissivity_field, \
-    add_xray_luminosity_field, \
-    add_xray_photon_emissivity_field
+    add_xray_emissivity_field
\ No newline at end of file

diff -r 4059ceb5765358f28fbed9839c36b7d089bbb98f -r 1e3f253ad97810f36d634c5e307a6710294e9505 yt/analysis_modules/spectral_integrator/spectral_frequency_integrator.py
--- a/yt/analysis_modules/spectral_integrator/spectral_frequency_integrator.py
+++ b/yt/analysis_modules/spectral_integrator/spectral_frequency_integrator.py
@@ -1,6 +1,6 @@
 """
 Integrator classes to deal with interpolation and integration of input spectral
-bins.  Currently only supports Cloudy-style data.
+bins.  Currently only supports Cloudy and APEC-style data.
 
 
 
@@ -23,19 +23,21 @@
      mylog, \
      only_on_root
 
-from yt.fields.local_fields import add_field
+from yt.utilities.exceptions import YTFieldNotFound
 from yt.utilities.exceptions import YTException
 from yt.utilities.linear_interpolators import \
-    BilinearFieldInterpolator
+    UnilinearFieldInterpolator, BilinearFieldInterpolator
 from yt.utilities.physical_constants import \
-    erg_per_eV, hcgs
-from yt.units import keV, Hz
-keV_per_Hz = keV/Hz/hcgs
+    hcgs, mp
+from yt.units.yt_array import YTArray, YTQuantity
+from yt.utilities.physical_ratios import \
+    primordial_H_mass_fraction, erg_per_keV
 
 xray_data_version = 1
 
-def _get_data_file():
-    data_file = "xray_emissivity.h5"
+def _get_data_file(data_file=None):
+    if data_file is None:
+        data_file = "cloudy_emissivity.h5"
     data_url = "http://yt-project.org/data"
     if "YT_DEST" in os.environ and \
       os.path.isdir(os.path.join(os.environ["YT_DEST"], "data")):
@@ -62,8 +64,9 @@
 
 class ObsoleteDataException(YTException):
     def __str__(self):
-        return "X-ray emissivity data is out of data.\nDownload the latest data from http://yt-project.org/data/xray_emissivity.h5 and move it to %s." % \
-          os.path.join(os.environ["YT_DEST"], "data", "xray_emissivity.h5")
+        return "X-ray emissivity data is out of date.\n" + \
+               "Download the latest data from http://yt-project.org/data/cloudy_emissivity.h5 and move it to %s." % \
+          os.path.join(os.environ["YT_DEST"], "data", "cloudy_emissivity.h5")
           
 class EmissivityIntegrator(object):
     r"""Class for making X-ray emissivity fields with hdf5 data tables 
@@ -75,9 +78,11 @@
     ----------
     filename: string, default None
         Path to data file containing emissivity values.  If None,
-        a file called xray_emissivity.h5 is used.  This file contains 
-        emissivity tables for primordial elements and for metals at 
-        solar metallicity for the energy range 0.1 to 100 keV.
+        a file called "cloudy_emissivity.h5" is used, for photoionized
+        plasmas. A second option, for collisionally ionized plasmas, is
+        in the file "apec_emissivity.h5", available at http://yt-project.org/data.
+        These files contain emissivity tables for primordial elements and
+        for metals at solar metallicity for the energy range 0.1 to 100 keV.
         Default: None.
         
     """
@@ -89,7 +94,8 @@
             default_filename = True
 
         if not os.path.exists(filename):
-            raise IOError("File does not exist: %s." % filename)
+            mylog.warning("File %s does not exist, will attempt to find it." % filename)
+            filename = _get_data_file(data_file=filename)
         only_on_root(mylog.info, "Loading emissivity data from %s." % filename)
         in_file = h5py.File(filename, "r")
         if "info" in in_file.attrs:
@@ -103,51 +109,51 @@
 
         for field in ["emissivity_primordial", "emissivity_metals",
                       "log_nH", "log_T", "log_E"]:
-            setattr(self, field, in_file[field][:])
+            if field in in_file:
+                setattr(self, field, in_file[field][:])
         in_file.close()
 
         E_diff = np.diff(self.log_E)
         self.E_bins = \
-                  np.power(10, np.concatenate([self.log_E[:-1] - 0.5 * E_diff,
-                                               [self.log_E[-1] - 0.5 * E_diff[-1],
-                                                self.log_E[-1] + 0.5 * E_diff[-1]]]))
-        self.dnu = keV_per_Hz * np.diff(self.E_bins)
+                  YTArray(np.power(10, np.concatenate([self.log_E[:-1] - 0.5 * E_diff,
+                                                      [self.log_E[-1] - 0.5 * E_diff[-1],
+                                                       self.log_E[-1] + 0.5 * E_diff[-1]]])),
+                          "keV")
+        self.dnu = (np.diff(self.E_bins)/hcgs).in_units("Hz")
 
-    def _get_interpolator(self, data, e_min, e_max):
-        r"""Create an interpolator for total emissivity in a 
-        given energy range.
-
-        Parameters
-        ----------
-        e_min: float
-            the minimum energy in keV for the energy band.
-        e_min: float
-            the maximum energy in keV for the energy band.
-
-        """
+    def get_interpolator(self, data, e_min, e_max):
+        e_min = YTQuantity(e_min, "keV")
+        e_max = YTQuantity(e_max, "keV")
         if (e_min - self.E_bins[0]) / e_min < -1e-3 or \
           (e_max - self.E_bins[-1]) / e_max > 1e-3:
-            raise EnergyBoundsException(np.power(10, self.E_bins[0]),
-                                        np.power(10, self.E_bins[-1]))
+            raise EnergyBoundsException(self.E_bins[0], self.E_bins[-1])
         e_is, e_ie = np.digitize([e_min, e_max], self.E_bins)
         e_is = np.clip(e_is - 1, 0, self.E_bins.size - 1)
         e_ie = np.clip(e_ie, 0, self.E_bins.size - 1)
 
-        my_dnu = np.copy(self.dnu[e_is: e_ie])
+        my_dnu = self.dnu[e_is: e_ie].copy()
         # clip edge bins if the requested range is smaller
-        my_dnu[0] -= e_min - self.E_bins[e_is]
-        my_dnu[-1] -= self.E_bins[e_ie] - e_max
+        my_dnu[0] -= ((e_min - self.E_bins[e_is])/hcgs).in_units("Hz")
+        my_dnu[-1] -= ((self.E_bins[e_ie] - e_max)/hcgs).in_units("Hz")
 
         interp_data = (data[..., e_is:e_ie] * my_dnu).sum(axis=-1)
-        return BilinearFieldInterpolator(np.log10(interp_data),
-                                         [self.log_nH[0], self.log_nH[-1],
-                                          self.log_T[0],  self.log_T[-1]],
-                                         ["log_nH", "log_T"], truncate=True)
+        if len(data.shape) == 2:
+            emiss = UnilinearFieldInterpolator(np.log10(interp_data),
+                                               [self.log_T[0],  self.log_T[-1]],
+                                               "log_T", truncate=True)
+        else:
+            emiss = BilinearFieldInterpolator(np.log10(interp_data),
+                                              [self.log_nH[0], self.log_nH[-1],
+                                               self.log_T[0],  self.log_T[-1]],
+                                              ["log_nH", "log_T"], truncate=True)
 
-def add_xray_emissivity_field(e_min, e_max, filename=None,
+        return emiss
+
+def add_xray_emissivity_field(ds, e_min, e_max,
+                              filename=None,
                               with_metals=True,
                               constant_metallicity=None):
-    r"""Create an X-ray emissivity field for a given energy range.
+    r"""Create X-ray emissivity fields for a given energy range.
 
     Parameters
     ----------
@@ -155,197 +161,117 @@
         the minimum energy in keV for the energy band.
     e_min: float
         the maximum energy in keV for the energy band.
-
-    Other Parameters
-    ----------------
-    filename: string
+    filename: string, optional
         Path to data file containing emissivity values.  If None,
-        a file called xray_emissivity.h5 is used.  This file contains 
-        emissivity tables for primordial elements and for metals at 
-        solar metallicity for the energy range 0.1 to 100 keV.
+        a file called "cloudy_emissivity.h5" is used, for photoionized
+        plasmas. A second option, for collisionally ionized plasmas, is
+        in the file "apec_emissivity.h5", available at http://yt-project.org/data.
+        These files contain emissivity tables for primordial elements and
+        for metals at solar metallicity for the energy range 0.1 to 100 keV.
         Default: None.
-    with_metals: bool
+    with_metals: bool, optional
         If True, use the metallicity field to add the contribution from 
         metals.  If False, only the emission from H/He is considered.
         Default: True.
-    constant_metallicity: float
+    constant_metallicity: float, optional
         If specified, assume a constant metallicity for the emission 
         from metals.  The *with_metals* keyword must be set to False 
         to use this.
         Default: None.
 
-    This will create a field named "Xray_Emissivity_{e_min}_{e_max}keV".
-    The units of the field are erg s^-1 cm^-3.
+    This will create three fields:
+
+    "xray_emissivity_{e_min}_{e_max}_keV" (erg s^-1 cm^-3)
+    "xray_luminosity_{e_min}_{e_max}_keV" (erg s^-1)
+    "xray_photon_emissivity_{e_min}_{e_max}_keV" (photons s^-1 cm^-3)
 
     Examples
     --------
 
     >>> from yt.mods import *
     >>> from yt.analysis_modules.spectral_integrator.api import *
-    >>> add_xray_emissivity_field(0.5, 2)
-    >>> pf = load(dataset)
-    >>> p = ProjectionPlot(pf, 'x', "Xray_Emissivity_0.5_2keV")
+    >>> ds = load(dataset)
+    >>> add_xray_emissivity_field(ds, 0.5, 2)
+    >>> p = ProjectionPlot(ds, 'x', "xray_emissivity_0.5_2_keV")
     >>> p.save()
 
     """
 
+    if with_metals:
+        try:
+            ds._get_field_info("metal_density")
+        except YTFieldNotFound:
+            raise RuntimeError("Your dataset does not have a \"metal_density\" field! " +
+                               "Perhaps you should specify a constant metallicity?")
+
     my_si = EmissivityIntegrator(filename=filename)
 
-    em_0 = my_si._get_interpolator(my_si.emissivity_primordial, e_min, e_max)
+    em_0 = my_si.get_interpolator(my_si.emissivity_primordial, e_min, e_max)
     em_Z = None
     if with_metals or constant_metallicity is not None:
-        em_Z = my_si._get_interpolator(my_si.emissivity_metals, e_min, e_max)
+        em_Z = my_si.get_interpolator(my_si.emissivity_metals, e_min, e_max)
+
+    energy_erg = np.power(10, my_si.log_E) * erg_per_keV
+    emp_0 = my_si.get_interpolator((my_si.emissivity_primordial[..., :] / energy_erg),
+                                   e_min, e_max)
+    emp_Z = None
+    if with_metals or constant_metallicity is not None:
+        emp_Z = my_si.get_interpolator((my_si.emissivity_metals[..., :] / energy_erg),
+                                       e_min, e_max)
+
+    try:
+        ds._get_field_info("H_number_density")
+    except YTFieldNotFound:
+        mylog.warning("Could not find a field for \"H_number_density\". Assuming primordial H " +
+                      "mass fraction.")
+        def _nh(field, data):
+            return primordial_H_mass_fraction*data["gas","density"]/mp
+        ds.add_field(("gas","H_number_density"), function=_nh, units="cm**-3")
 
     def _emissivity_field(field, data):
-        dd = {"log_nH" : np.log10(data["H_NumberDensity"]),
-              "log_T"   : np.log10(data["Temperature"])}
+        dd = {"log_nH" : np.log10(data["gas","H_number_density"]),
+              "log_T"   : np.log10(data["gas","temperature"])}
 
         my_emissivity = np.power(10, em_0(dd))
         if em_Z is not None:
             if with_metals:
-                my_Z = data["Metallicity"]
+                my_Z = data["gas","metallicity"]
             elif constant_metallicity is not None:
                 my_Z = constant_metallicity
             my_emissivity += my_Z * np.power(10, em_Z(dd))
 
-        return data["H_NumberDensity"]**2 * my_emissivity
+        return data["gas","H_number_density"]**2 * YTArray(my_emissivity, "erg*cm**3/s")
 
-    field_name = "Xray_Emissivity_%s_%skeV" % (e_min, e_max)
-    add_field(field_name, function=_emissivity_field,
-              projection_conversion="cm",
-              display_name=r"\epsilon_{X}\/(%s-%s\/keV)" % (e_min, e_max),
-              units=r"\rm{erg}\/\rm{cm}^{-3}\/\rm{s}^{-1}")
-    return field_name
-
-def add_xray_luminosity_field(e_min, e_max, filename=None,
-                              with_metals=True,
-                              constant_metallicity=None):
-    r"""Create an X-ray luminosity field for a given energy range.
-
-    Parameters
-    ----------
-    e_min: float
-        the minimum energy in keV for the energy band.
-    e_min: float
-        the maximum energy in keV for the energy band.
-
-    Other Parameters
-    ----------------
-    filename: string
-        Path to data file containing emissivity values.  If None,
-        a file called xray_emissivity.h5 is used.  This file contains 
-        emissivity tables for primordial elements and for metals at 
-        solar metallicity for the energy range 0.1 to 100 keV.
-        Default: None.
-    with_metals: bool
-        If True, use the metallicity field to add the contribution from 
-        metals.  If False, only the emission from H/He is considered.
-        Default: True.
-    constant_metallicity: float
-        If specified, assume a constant metallicity for the emission 
-        from metals.  The *with_metals* keyword must be set to False 
-        to use this.
-        Default: None.
-
-    This will create a field named "Xray_Luminosity_{e_min}_{e_max}keV".
-    The units of the field are erg s^-1.
-
-    Examples
-    --------
-
-    >>> from yt.mods import *
-    >>> from yt.analysis_modules.spectral_integrator.api import *
-    >>> add_xray_luminosity_field(0.5, 2)
-    >>> pf = load(dataset)
-    >>> sp = pf.sphere('max', (2., 'mpc'))
-    >>> print sp.quantities['TotalQuantity']('Xray_Luminosity_0.5_2keV')
-    
-    """
-
-    em_field = add_xray_emissivity_field(e_min, e_max, filename=filename,
-                                         with_metals=with_metals,
-                                         constant_metallicity=constant_metallicity)
+    emiss_name = "xray_emissivity_%s_%s_keV" % (e_min, e_max)
+    ds.add_field(emiss_name, function=_emissivity_field,
+                 display_name=r"\epsilon_{X}\/(%s-%s\/keV)" % (e_min, e_max),
+                 units="erg/cm**3/s")
 
     def _luminosity_field(field, data):
-        return data[em_field] * data["CellVolume"]
-    field_name = "Xray_Luminosity_%s_%skeV" % (e_min, e_max)
-    add_field(field_name, function=_luminosity_field,
-              display_name=r"\rm{L}_{X}\/(%s-%s\/keV)" % (e_min, e_max),
-              units=r"\rm{erg}\/\rm{s}^{-1}")
-    return field_name
+        return data[emiss_name] * data["cell_volume"]
 
-def add_xray_photon_emissivity_field(e_min, e_max, filename=None,
-                                     with_metals=True,
-                                     constant_metallicity=None):
-    r"""Create an X-ray photon emissivity field for a given energy range.
+    lum_name = "xray_luminosity_%s_%s_keV" % (e_min, e_max)
+    ds.add_field(lum_name, function=_luminosity_field,
+                 display_name=r"\rm{L}_{X}\/(%s-%s\/keV)" % (e_min, e_max),
+                 units="erg/s")
 
-    Parameters
-    ----------
-    e_min: float
-        the minimum energy in keV for the energy band.
-    e_min: float
-        the maximum energy in keV for the energy band.
+    def _photon_emissivity_field(field, data):
+        dd = {"log_nH" : np.log10(data["gas","H_number_density"]),
+              "log_T"   : np.log10(data["gas","temperature"])}
 
-    Other Parameters
-    ----------------
-    filename: string
-        Path to data file containing emissivity values.  If None,
-        a file called xray_emissivity.h5 is used.  This file contains 
-        emissivity tables for primordial elements and for metals at 
-        solar metallicity for the energy range 0.1 to 100 keV.
-        Default: None.
-    with_metals: bool
-        If True, use the metallicity field to add the contribution from 
-        metals.  If False, only the emission from H/He is considered.
-        Default: True.
-    constant_metallicity: float
-        If specified, assume a constant metallicity for the emission 
-        from metals.  The *with_metals* keyword must be set to False 
-        to use this.
-        Default: None.
-
-    This will create a field named "Xray_Photon_Emissivity_{e_min}_{e_max}keV".
-    The units of the field are photons s^-1 cm^-3.
-
-    Examples
-    --------
-
-    >>> from yt.mods import *
-    >>> from yt.analysis_modules.spectral_integrator.api import *
-    >>> add_xray_emissivity_field(0.5, 2)
-    >>> pf = load(dataset)
-    >>> p = ProjectionPlot(pf, 'x', "Xray_Emissivity_0.5_2keV")
-    >>> p.save()
-
-    """
-
-    my_si = EmissivityIntegrator(filename=filename)
-    energy_erg = np.power(10, my_si.log_E) * erg_per_eV
-
-    em_0 = my_si._get_interpolator((my_si.emissivity_primordial[..., :] / energy_erg),
-                                   e_min, e_max)
-    em_Z = None
-    if with_metals or constant_metallicity is not None:
-        em_Z = my_si._get_interpolator((my_si.emissivity_metals[..., :] / energy_erg),
-                                       e_min, e_max)
-
-    def _emissivity_field(field, data):
-        dd = {"log_nH" : np.log10(data["H_NumberDensity"]),
-              "log_T"   : np.log10(data["Temperature"])}
-
-        my_emissivity = np.power(10, em_0(dd))
-        if em_Z is not None:
+        my_emissivity = np.power(10, emp_0(dd))
+        if emp_Z is not None:
             if with_metals:
-                my_Z = data["Metallicity"]
+                my_Z = data["gas","metallicity"]
             elif constant_metallicity is not None:
                 my_Z = constant_metallicity
-            my_emissivity += my_Z * np.power(10, em_Z(dd))
+            my_emissivity += my_Z * np.power(10, emp_Z(dd))
 
-        return data["H_NumberDensity"]**2 * my_emissivity
+        return data["gas","H_number_density"]**2 * YTArray(my_emissivity, "photons*cm**3/s")
 
-    field_name = "Xray_Photon_Emissivity_%s_%skeV" % (e_min, e_max)
-    add_field(field_name, function=_emissivity_field,
-              projection_conversion="cm",
-              display_name=r"\epsilon_{X}\/(%s-%s\/keV)" % (e_min, e_max),
-              units=r"\rm{photons}\/\rm{cm}^{-3}\/\rm{s}^{-1}")
-    return field_name
+    phot_name = "xray_photon_emissivity_%s_%s_keV" % (e_min, e_max)
+    ds.add_field(phot_name, function=_photon_emissivity_field,
+                 display_name=r"\epsilon_{X}\/(%s-%s\/keV)" % (e_min, e_max),
+                 units="photons/cm**3/s")
+
+    return emiss_name, lum_name, phot_name
\ No newline at end of file

diff -r 4059ceb5765358f28fbed9839c36b7d089bbb98f -r 1e3f253ad97810f36d634c5e307a6710294e9505 yt/data_objects/construction_data_containers.py
--- a/yt/data_objects/construction_data_containers.py
+++ b/yt/data_objects/construction_data_containers.py
@@ -626,7 +626,7 @@
         self.ActiveDimensions = np.array(dims, dtype='int32')
         if self.ActiveDimensions.size == 1:
             self.ActiveDimensions = np.array([dims, dims, dims], dtype="int32")
-        self.dds = (self.right_edge - self.left_edge)/self.ActiveDimensions
+        self.dds = self.base_dds = (self.right_edge - self.left_edge)/self.ActiveDimensions
         self.level = 99
         self._setup_data_source()
 

diff -r 4059ceb5765358f28fbed9839c36b7d089bbb98f -r 1e3f253ad97810f36d634c5e307a6710294e9505 yt/data_objects/octree_subset.py
--- a/yt/data_objects/octree_subset.py
+++ b/yt/data_objects/octree_subset.py
@@ -199,7 +199,7 @@
         op.process_octree(self.oct_handler, mdom_ind, positions, 
             self.fcoords, fields,
             self.domain_id, self._domain_offset, self.pf.periodicity,
-            index_fields, particle_octree, pdom_ind)
+            index_fields, particle_octree, pdom_ind, self.pf.geometry)
         vals = op.finalize()
         if vals is None: return
         if isinstance(vals, list):

diff -r 4059ceb5765358f28fbed9839c36b7d089bbb98f -r 1e3f253ad97810f36d634c5e307a6710294e9505 yt/frontends/chombo/data_structures.py
--- a/yt/frontends/chombo/data_structures.py
+++ b/yt/frontends/chombo/data_structures.py
@@ -145,14 +145,14 @@
 
         # look for fluid fields
         output_fields = []
-        for key, val in self._handle['/'].attrs.items():
+        for key, val in self._handle.attrs.items():
             if key.startswith("component"):
                 output_fields.append(val)
         self.field_list = [("chombo", c) for c in output_fields]
 
         # look for particle fields
         particle_fields = []
-        for key, val in self._handle['/'].attrs.items():
+        for key, val in self._handle.attrs.items():
             if key.startswith("particle"):
                 particle_fields.append(val)
         self.field_list.extend([("io", c) for c in particle_fields])        

diff -r 4059ceb5765358f28fbed9839c36b7d089bbb98f -r 1e3f253ad97810f36d634c5e307a6710294e9505 yt/frontends/chombo/io.py
--- a/yt/frontends/chombo/io.py
+++ b/yt/frontends/chombo/io.py
@@ -37,7 +37,7 @@
         if self._field_dict is not None:
             return self._field_dict
         field_dict = {}
-        for key, val in self._handle['/'].attrs.items():
+        for key, val in self._handle.attrs.items():
             if key.startswith('component_'):
                 comp_number = int(re.match('component_(\d)', key).groups()[0])
                 field_dict[val] = comp_number
@@ -50,7 +50,7 @@
         if self._particle_field_index is not None:
             return self._particle_field_index
         field_dict = {}
-        for key, val in self._handle['/'].attrs.items():
+        for key, val in self._handle.attrs.items():
             if key.startswith('particle_'):
                 comp_number = int(re.match('particle_component_(\d)', key).groups()[0])
                 field_dict[val] = comp_number
@@ -58,8 +58,8 @@
         return self._particle_field_index        
         
     def _read_field_names(self,grid):
-        ncomp = int(self._handle['/'].attrs['num_components'])
-        fns = [c[1] for c in f['/'].attrs.items()[-ncomp-1:-1]]
+        ncomp = int(self._handle.attrs['num_components'])
+        fns = [c[1] for c in f.attrs.items()[-ncomp-1:-1]]
     
     def _read_data(self,grid,field):
 

diff -r 4059ceb5765358f28fbed9839c36b7d089bbb98f -r 1e3f253ad97810f36d634c5e307a6710294e9505 yt/frontends/stream/data_structures.py
--- a/yt/frontends/stream/data_structures.py
+++ b/yt/frontends/stream/data_structures.py
@@ -970,7 +970,7 @@
 def load_particles(data, length_unit = None, bbox=None,
                    sim_time=0.0, mass_unit = None, time_unit = None,
                    velocity_unit=None, periodicity=(True, True, True),
-                   n_ref = 64, over_refine_factor = 1):
+                   n_ref = 64, over_refine_factor = 1, geometry = "cartesian"):
     r"""Load a set of particles into yt as a
     :class:`~yt.frontends.stream.data_structures.StreamParticleHandler`.
 
@@ -1083,7 +1083,7 @@
     handler.simulation_time = sim_time
     handler.cosmology_simulation = 0
 
-    spf = StreamParticlesDataset(handler)
+    spf = StreamParticlesDataset(handler, geometry = geometry)
     spf.n_ref = n_ref
     spf.over_refine_factor = over_refine_factor
 

diff -r 4059ceb5765358f28fbed9839c36b7d089bbb98f -r 1e3f253ad97810f36d634c5e307a6710294e9505 yt/geometry/particle_deposit.pyx
--- a/yt/geometry/particle_deposit.pyx
+++ b/yt/geometry/particle_deposit.pyx
@@ -95,7 +95,7 @@
             if self.update_values == 1:
                 for j in range(nf):
                     field_pointers[j][i] = field_vals[j] 
-        
+
     @cython.boundscheck(False)
     @cython.wraparound(False)
     def process_grid(self, gobj,
@@ -424,3 +424,56 @@
         return
 
 deposit_mesh_id = MeshIdentifier
+
+cdef class NNParticleField(ParticleDepositOperation):
+    cdef np.float64_t *nnfield
+    cdef np.float64_t *distfield
+    cdef public object onnfield
+    cdef public object odistfield
+    def initialize(self):
+        self.onnfield = np.zeros(self.nvals, dtype="float64", order='F')
+        cdef np.ndarray arr = self.onnfield
+        self.nnfield = <np.float64_t*> arr.data
+
+        self.odistfield = np.zeros(self.nvals, dtype="float64", order='F')
+        self.odistfield[:] = np.inf
+        arr = self.odistfield
+        self.distfield = <np.float64_t*> arr.data
+
+    @cython.cdivision(True)
+    cdef void process(self, int dim[3],
+                      np.float64_t left_edge[3], 
+                      np.float64_t dds[3],
+                      np.int64_t offset, 
+                      np.float64_t ppos[3],
+                      np.float64_t *fields,
+                      np.int64_t domain_ind
+                      ):
+        # This one is a bit slow.  Every grid cell is going to be iterated
+        # over, and we're going to deposit particles in it.
+        cdef int ii[3], i, j, k
+        cdef np.int64_t ggind
+        cdef np.float64_t r2, gpos[3]
+        gpos[0] = left_edge[0] + 0.5 * dds[0]
+        for i in range(dim[0]):
+            gpos[1] = left_edge[1] + 0.5 * dds[1]
+            for j in range(dim[1]):
+                gpos[2] = left_edge[2] + 0.5 * dds[2]
+                for k in range(dim[2]):
+                    ggind = gind(i, j, k, dim) + offset
+                    r2 = ((ppos[0] - gpos[0])*(ppos[0] - gpos[0]) +
+                          (ppos[1] - gpos[1])*(ppos[1] - gpos[1]) +
+                          (ppos[2] - gpos[2])*(ppos[2] - gpos[2]))
+                    if r2 < self.distfield[ggind]:
+                        self.distfield[ggind] = r2
+                        self.nnfield[ggind] = fields[0]
+                    gpos[2] += dds[2]
+                gpos[1] += dds[1]
+            gpos[0] += dds[0]
+        return
+        
+    def finalize(self):
+        return self.onnfield
+
+deposit_nearest = NNParticleField
+

diff -r 4059ceb5765358f28fbed9839c36b7d089bbb98f -r 1e3f253ad97810f36d634c5e307a6710294e9505 yt/geometry/particle_smooth.pxd
--- a/yt/geometry/particle_smooth.pxd
+++ b/yt/geometry/particle_smooth.pxd
@@ -36,27 +36,6 @@
     np.int64_t pn       # Particle number
     np.float64_t r2     # radius**2
 
- at cython.cdivision(True)
- at cython.boundscheck(False)
- at cython.wraparound(False)
-cdef inline np.float64_t r2dist(np.float64_t ppos[3],
-                                np.float64_t cpos[3],
-                                np.float64_t DW[3],
-                                bint periodicity[3]):
-    cdef int i
-    cdef np.float64_t r2, DR
-    r2 = 0.0
-    for i in range(3):
-        DR = (ppos[i] - cpos[i])
-        if not periodicity[i]:
-            pass
-        elif (DR > DW[i]/2.0):
-            DR -= DW[i]
-        elif (DR < -DW[i]/2.0):
-            DR += DW[i]
-        r2 += DR * DR
-    return r2
-
 cdef class ParticleSmoothOperation:
     # We assume each will allocate and define their own temporary storage
     cdef public object nvals
@@ -71,6 +50,7 @@
     cdef np.float64_t *ppos
     # Note that we are preallocating here, so this is *not* threadsafe.
     cdef NeighborList *neighbors
+    cdef void (*pos_setup)(np.float64_t ipos[3], np.float64_t opos[3])
     cdef void neighbor_process(self, int dim[3], np.float64_t left_edge[3],
                                np.float64_t dds[3], np.float64_t *ppos,
                                np.float64_t **fields, np.int64_t nneighbors,

diff -r 4059ceb5765358f28fbed9839c36b7d089bbb98f -r 1e3f253ad97810f36d634c5e307a6710294e9505 yt/geometry/particle_smooth.pyx
--- a/yt/geometry/particle_smooth.pyx
+++ b/yt/geometry/particle_smooth.pyx
@@ -18,7 +18,7 @@
 import numpy as np
 from libc.stdlib cimport malloc, free, realloc
 cimport cython
-from libc.math cimport sqrt, fabs
+from libc.math cimport sqrt, fabs, sin, cos
 
 from fp_utils cimport *
 from oct_container cimport Oct, OctAllocationContainer, \
@@ -37,6 +37,40 @@
     else:
         return 1
 
+ at cython.cdivision(True)
+ at cython.boundscheck(False)
+ at cython.wraparound(False)
+cdef np.float64_t r2dist(np.float64_t ppos[3],
+                         np.float64_t cpos[3],
+                         np.float64_t DW[3],
+                         bint periodicity[3],
+                         np.float64_t max_dist2):
+    cdef int i
+    cdef np.float64_t r2, DR
+    r2 = 0.0
+    for i in range(3):
+        DR = (ppos[i] - cpos[i])
+        if not periodicity[i]:
+            pass
+        elif (DR > DW[i]/2.0):
+            DR -= DW[i]
+        elif (DR < -DW[i]/2.0):
+            DR += DW[i]
+        r2 += DR * DR
+        if max_dist2 >= 0.0 and r2 > max_dist2:
+            return -1.0
+    return r2
+
+cdef void spherical_coord_setup(np.float64_t ipos[3], np.float64_t opos[3]):
+    opos[0] = ipos[0] * sin(ipos[1]) * cos(ipos[2])
+    opos[1] = ipos[0] * sin(ipos[1]) * sin(ipos[2])
+    opos[2] = ipos[0] * cos(ipos[1])
+
+cdef void cart_coord_setup(np.float64_t ipos[3], np.float64_t opos[3]):
+    opos[0] = ipos[0]
+    opos[1] = ipos[1]
+    opos[2] = ipos[2]
+
 cdef class ParticleSmoothOperation:
     def __init__(self, nvals, nfields, max_neighbors):
         # This is the set of cells, in grids, blocks or octs, we are handling.
@@ -66,7 +100,8 @@
                      periodicity = (True, True, True),
                      index_fields = None,
                      OctreeContainer particle_octree = None,
-                     np.ndarray[np.int64_t, ndim=1] pdom_ind = None):
+                     np.ndarray[np.int64_t, ndim=1] pdom_ind = None,
+                     geometry = "cartesian"):
         # This will be a several-step operation.
         #
         # We first take all of our particles and assign them to Octs.  If they
@@ -108,6 +143,25 @@
         cdef np.ndarray[np.int64_t, ndim=2] doff_m
         cdef np.ndarray[np.float64_t, ndim=1] tarr
         cdef np.ndarray[np.float64_t, ndim=4] iarr
+        cdef np.ndarray[np.float64_t, ndim=2] cart_positions
+        if geometry == "cartesian":
+            self.pos_setup = cart_coord_setup
+            cart_positions = positions
+        elif geometry == "spherical":
+            self.pos_setup = spherical_coord_setup
+            cart_positions = np.empty((positions.shape[0], 3), dtype="float64")
+
+            cart_positions[:,0] = positions[:,0] * \
+                                  np.sin(positions[:,1]) * \
+                                  np.cos(positions[:,2])
+            cart_positions[:,1] = positions[:,0] * \
+                                  np.sin(positions[:,1]) * \
+                                  np.sin(positions[:,2])
+            cart_positions[:,2] = positions[:,0] * \
+                                  np.cos(positions[:,1])
+            periodicity = (False, False, False)
+        else:
+            raise NotImplementedError
         dims[0] = dims[1] = dims[2] = (1 << mesh_octree.oref)
         cdef int nz = dims[0] * dims[1] * dims[2]
         numpart = positions.shape[0]
@@ -174,6 +228,7 @@
         # Now doff is full of offsets to the first entry in the pind that
         # refers to that oct's particles.
         ppos = <np.float64_t *> positions.data
+        cart_pos = <np.float64_t *> cart_positions.data
         doffs = <np.int64_t*> doff.data
         pinds = <np.int64_t*> pind.data
         pcounts = <np.int64_t*> pcount.data
@@ -213,7 +268,7 @@
             free(neighbors)
             nproc += 1
             self.neighbor_process(dims, moi.left_edge, moi.dds,
-                         ppos, field_pointers, nneighbors, nind, doffs,
+                         cart_pos, field_pointers, nneighbors, nind, doffs,
                          pinds, pcounts, offset, index_field_pointers)
         #print "VISITED", visited.sum(), visited.size,
         #print 100.0*float(visited.sum())/visited.size
@@ -253,7 +308,7 @@
         if self.curn < self.maxn:
             cur = &self.neighbors[self.curn]
             cur.pn = pn
-            cur.r2 = r2dist(ppos, cpos, self.DW, self.periodicity)
+            cur.r2 = r2dist(ppos, cpos, self.DW, self.periodicity, -1)
             self.curn += 1
             if self.curn == self.maxn:
                 # This time we sort it, so that future insertions will be able
@@ -262,7 +317,10 @@
                       Neighbor_compare)
             return
         # This will go (curn - 1) through 0.
-        r2_c = r2dist(ppos, cpos, self.DW, self.periodicity)
+        r2_o = self.neighbors[self.curn - 1].r2
+        r2_c = r2dist(ppos, cpos, self.DW, self.periodicity, r2_o)
+        # Early terminate
+        if r2_c < 0: return
         pn_c = pn
         for i in range((self.curn - 1), -1, -1):
             # First we evaluate against i.  If our candidate radius is greater
@@ -320,15 +378,16 @@
         # units supplied.  We can now iterate over every cell in the block and
         # every particle to find the nearest.  We will use a priority heap.
         cdef int i, j, k, ntot, nntot, m
-        cdef np.float64_t cpos[3]
+        cdef np.float64_t cpos[3], opos[3]
         cpos[0] = left_edge[0] + 0.5*dds[0]
         for i in range(dim[0]):
             cpos[1] = left_edge[1] + 0.5*dds[1]
             for j in range(dim[1]):
                 cpos[2] = left_edge[2] + 0.5*dds[2]
                 for k in range(dim[2]):
+                    self.pos_setup(cpos, opos)
                     self.neighbor_find(nneighbors, nind, doffs, pcounts,
-                        pinds, ppos, cpos)
+                        pinds, ppos, opos)
                     # Now we have all our neighbors in our neighbor list.
                     if self.curn <-1*self.maxn:
                         ntot = nntot = 0
@@ -337,7 +396,7 @@
                             nntot += 1
                             ntot += pcounts[nind[m]]
                         print "SOMETHING WRONG", self.curn, nneighbors, ntot, nntot
-                    self.process(offset, i, j, k, dim, cpos, fields,
+                    self.process(offset, i, j, k, dim, opos, fields,
                                  index_fields)
                     cpos[2] += dds[2]
                 cpos[1] += dds[1]
@@ -407,3 +466,76 @@
         return
 
 volume_weighted_smooth = VolumeWeightedSmooth
+
+cdef class NearestNeighborSmooth(ParticleSmoothOperation):
+    cdef np.float64_t *fp
+    cdef public object vals
+    def initialize(self):
+        cdef np.ndarray tarr
+        assert(self.nfields == 1)
+        tarr = np.zeros(self.nvals, dtype="float64", order="F")
+        self.vals = tarr
+        self.fp = <np.float64_t *> tarr.data
+
+    def finalize(self):
+        return self.vals
+
+    @cython.cdivision(True)
+    @cython.boundscheck(False)
+    @cython.wraparound(False)
+    cdef void process(self, np.int64_t offset, int i, int j, int k,
+                      int dim[3], np.float64_t cpos[3], np.float64_t **fields,
+                      np.float64_t **index_fields):
+        # We have our i, j, k for our cell, as well as the cell position.
+        # We also have a list of neighboring particles with particle numbers.
+        cdef np.int64_t pn
+        # We get back our mass 
+        # rho_i = sum(j = 1 .. n) m_j * W_ij
+        pn = self.neighbors[0].pn
+        self.fp[gind(i,j,k,dim) + offset] = fields[0][pn]
+        #self.fp[gind(i,j,k,dim) + offset] = self.neighbors[0].r2
+        return
+
+nearest_smooth = NearestNeighborSmooth
+
+cdef class IDWInterpolationSmooth(ParticleSmoothOperation):
+    cdef np.float64_t *fp
+    cdef public int p2
+    cdef public object vals
+    def initialize(self):
+        cdef np.ndarray tarr
+        assert(self.nfields == 1)
+        tarr = np.zeros(self.nvals, dtype="float64", order="F")
+        self.vals = tarr
+        self.fp = <np.float64_t *> tarr.data
+        self.p2 = 2 # Power, for IDW, in units of 2.  So we only do even p's.
+
+    def finalize(self):
+        return self.vals
+
+    @cython.cdivision(True)
+    @cython.boundscheck(False)
+    @cython.wraparound(False)
+    cdef void process(self, np.int64_t offset, int i, int j, int k,
+                      int dim[3], np.float64_t cpos[3], np.float64_t **fields,
+                      np.float64_t **index_fields):
+        # We have our i, j, k for our cell, as well as the cell position.
+        # We also have a list of neighboring particles with particle numbers.
+        cdef np.int64_t pn, ni, di
+        cdef np.float64_t total_weight = 0.0, total_value = 0.0, r2, val, w
+        # We're going to do a very simple IDW average
+        if self.neighbors[0].r2 == 0.0:
+            pn = self.neighbors[0].pn
+            self.fp[gind(i,j,k,dim) + offset] = fields[0][pn]
+        for ni in range(self.curn):
+            r2 = self.neighbors[ni].r2
+            val = fields[0][self.neighbors[ni].pn]
+            w = r2
+            for di in range(self.p2 - 1):
+                w *= r2
+            total_value += w * val
+            total_weight += w
+        self.fp[gind(i,j,k,dim) + offset] = total_value / total_weight
+        return
+
+idw_smooth = IDWInterpolationSmooth

diff -r 4059ceb5765358f28fbed9839c36b7d089bbb98f -r 1e3f253ad97810f36d634c5e307a6710294e9505 yt/units/unit_lookup_table.py
--- a/yt/units/unit_lookup_table.py
+++ b/yt/units/unit_lookup_table.py
@@ -89,6 +89,7 @@
     "angstrom": (cm_per_ang, dimensions.length),
     "Jy": (jansky_cgs, dimensions.specific_flux),
     "counts": (1.0, dimensions.dimensionless),
+    "photons": (1.0, dimensions.dimensionless),
 
     # for AstroPy compatibility
     "solMass": (mass_sun_grams, dimensions.mass),

diff -r 4059ceb5765358f28fbed9839c36b7d089bbb98f -r 1e3f253ad97810f36d634c5e307a6710294e9505 yt/utilities/file_handler.py
--- a/yt/utilities/file_handler.py
+++ b/yt/utilities/file_handler.py
@@ -40,6 +40,10 @@
     def keys(self):
         return self.handle.keys
 
+    @property
+    def items(self):
+        return self.handle.items
+
 class FITSFileHandler(HDF5FileHandler):
     def __init__(self, filename):
         from yt.utilities.on_demand_imports import _astropy

diff -r 4059ceb5765358f28fbed9839c36b7d089bbb98f -r 1e3f253ad97810f36d634c5e307a6710294e9505 yt/utilities/lib/ContourFinding.pyx
--- a/yt/utilities/lib/ContourFinding.pyx
+++ b/yt/utilities/lib/ContourFinding.pyx
@@ -24,7 +24,6 @@
     OctreeContainer, OctInfo
 from yt.geometry.oct_visitors cimport \
     Oct
-from yt.geometry.particle_smooth cimport r2dist
 from .amr_kdtools cimport _find_node, Node
 from .grid_traversal cimport VolumeContainer, PartitionedGrid, \
     vc_index, vc_pos_index

diff -r 4059ceb5765358f28fbed9839c36b7d089bbb98f -r 1e3f253ad97810f36d634c5e307a6710294e9505 yt/visualization/plot_modifications.py
--- a/yt/visualization/plot_modifications.py
+++ b/yt/visualization/plot_modifications.py
@@ -16,6 +16,7 @@
 
 import numpy as np
 import h5py
+from matplotlib.patches import Circle
 
 from yt.funcs import *
 from yt.extern.six import add_metaclass
@@ -870,21 +871,49 @@
         plot._axes.text(x, y, self.text, **kwargs)
 
 class HaloCatalogCallback(PlotCallback):
+    """
+    annotate_halos(halo_catalog, circle_kwargs=None,
+        width = None, annotate_field=False,
+        font_kwargs = None, factor = 1.0)
+
+    Plots circles at the locations of all the halos
+    in a halo catalog with radii corresponding to the
+    virial radius of each halo. 
+
+    circle_kwargs: Contains the arguments controlling the
+        appearance of the circles, supplied to the 
+        Matplotlib patch Circle.
+    width: the width over which to select halos to plot,
+        useful when overplotting to a slice plot. Accepts
+        a tuple in the form (1.0, 'Mpc').
+    annotate_field: Accepts a field contained in the 
+        halo catalog to add text to the plot near the halo.
+        Example: annotate_field = 'particle_mass' will
+        write the halo mass next to each halo.
+    font_kwargs: Contains the arguments controlling the text
+        appearance of the annotated field.
+    factor: A number the virial radius is multiplied by for
+        plotting the circles. Ex: factor = 2.0 will plot
+        circles with twice the radius of each halo virial radius.
+    """
 
     _type_name = 'halos'
     region = None
     _descriptor = None
 
-    def __init__(self, halo_catalog, col='white', alpha =1, 
-            width = None, annotate_field = False, font_kwargs = None):
+    def __init__(self, halo_catalog, circle_kwargs = None, 
+            width = None, annotate_field = False,
+            font_kwargs = None, factor = 1.0):
 
         PlotCallback.__init__(self)
         self.halo_catalog = halo_catalog
-        self.color = col
-        self.alpha = alpha
         self.width = width
         self.annotate_field = annotate_field
         self.font_kwargs = font_kwargs
+        self.factor = factor
+        if circle_kwargs is None:
+            circle_kwargs = {'edgecolor':'white', 'facecolor':'None'}
+        self.circle_kwargs = circle_kwargs
 
     def __call__(self, plot):
         data = plot.data
@@ -903,20 +932,20 @@
         plot._axes.hold(True)
 
         # Set up scales for pixel size and original data
-        units = 'Mpccm'
         pixel_scale = self.pixel_scale(plot)[0]
         data_scale = data.pf.length_unit
+        units = data_scale.units
 
         # Convert halo positions to code units of the plotted data
         # and then to units of the plotted window
         px = halo_data[field_x][:].in_units(units) / data_scale
         py = halo_data[field_y][:].in_units(units) / data_scale
         px, py = self.convert_to_plot(plot,[px,py])
+
+        # Convert halo radii to a radius in pixels
+        radius = halo_data['virial_radius'][:].in_units(units)
+        radius = np.array(radius*pixel_scale*self.factor/data_scale)
         
-        # Convert halo radii to a radius in pixels
-        radius = halo_data['radius'][:].in_units(units)
-        radius = radius*pixel_scale/data_scale
-
         if self.width:
             pz = halo_data[field_z][:].in_units(units)/data_scale
             pz = data.pf.arr(pz, 'code_length')
@@ -932,8 +961,10 @@
             py = py[indices]
             radius = radius[indices]
 
-        plot._axes.scatter(px, py, edgecolors='None', marker='o',
-                           s=radius, c=self.color,alpha=self.alpha)
+        for x,y,r in zip(px, py, radius):
+            plot._axes.add_artist(Circle(xy=(x,y), 
+                radius = r, **self.circle_kwargs)) 
+
         plot._axes.set_xlim(xx0,xx1)
         plot._axes.set_ylim(yy0,yy1)
         plot._axes.hold(False)
@@ -963,8 +994,7 @@
     region = None
     _descriptor = None
     def __init__(self, width, p_size=1.0, col='k', marker='o', stride=1.0,
-                 ptype=None, stars_only=False, dm_only=False,
-                 minimum_mass=None, alpha=1.0):
+                 ptype='all', minimum_mass=None, alpha=1.0):
         PlotCallback.__init__(self)
         self.width = width
         self.p_size = p_size
@@ -972,8 +1002,6 @@
         self.marker = marker
         self.stride = stride
         self.ptype = ptype
-        self.stars_only = stars_only
-        self.dm_only = dm_only
         self.minimum_mass = minimum_mass
         self.alpha = alpha
 
@@ -993,24 +1021,16 @@
         axis_names = plot.data.pf.coordinates.axis_name
         field_x = "particle_position_%s" % axis_names[xax]
         field_y = "particle_position_%s" % axis_names[yax]
-        gg = ( ( reg[field_x] >= x0 ) & ( reg[field_x] <= x1 )
-           &   ( reg[field_y] >= y0 ) & ( reg[field_y] <= y1 ) )
-        if self.ptype is not None:
-            gg &= (reg["particle_type"] == self.ptype)
-            if gg.sum() == 0: return
-        if self.stars_only:
-            gg &= (reg["creation_time"] > 0.0)
-            if gg.sum() == 0: return
-        if self.dm_only:
-            gg &= (reg["creation_time"] <= 0.0)
-            if gg.sum() == 0: return
+        pt = self.ptype
+        gg = ( ( reg[pt, field_x] >= x0 ) & ( reg[pt, field_x] <= x1 )
+           &   ( reg[pt, field_y] >= y0 ) & ( reg[pt, field_y] <= y1 ) )
         if self.minimum_mass is not None:
-            gg &= (reg["particle_mass"] >= self.minimum_mass)
+            gg &= (reg[pt, "particle_mass"] >= self.minimum_mass)
             if gg.sum() == 0: return
         plot._axes.hold(True)
         px, py = self.convert_to_plot(plot,
-                    [np.array(reg[field_x][gg][::self.stride]),
-                     np.array(reg[field_y][gg][::self.stride])])
+                    [np.array(reg[pt, field_x][gg][::self.stride]),
+                     np.array(reg[pt, field_y][gg][::self.stride])])
         plot._axes.scatter(px, py, edgecolors='None', marker=self.marker,
                            s=self.p_size, c=self.color,alpha=self.alpha)
         plot._axes.set_xlim(xx0,xx1)

diff -r 4059ceb5765358f28fbed9839c36b7d089bbb98f -r 1e3f253ad97810f36d634c5e307a6710294e9505 yt/visualization/profile_plotter.py
--- a/yt/visualization/profile_plotter.py
+++ b/yt/visualization/profile_plotter.py
@@ -883,7 +883,7 @@
                 for k, v in self.plots.iteritems():
                     names.append(v.save(name, mpl_kwargs))
                 return names
-            fn = "%s_%s%s" % (prefix, middle, suffix)
+            fn = "%s_%s%s" % (prefix, middle, '.png')
             names.append(fn)
             self.plots[f].save(fn, mpl_kwargs)
         return names


https://bitbucket.org/yt_analysis/yt/commits/37696c30a18b/
Changeset:   37696c30a18b
Branch:      yt-3.0
User:        ngoldbaum
Date:        2014-07-06 14:45:41
Summary:     Fixing an issue with ray ordering in the manual plotting docs.
Affected #:  1 file

diff -r 1e3f253ad97810f36d634c5e307a6710294e9505 -r 37696c30a18b6a4c688b5f02661860ffbda0a781 doc/source/visualizing/manual_plotting.rst
--- a/doc/source/visualizing/manual_plotting.rst
+++ b/doc/source/visualizing/manual_plotting.rst
@@ -83,11 +83,15 @@
    # cutting through the y0,z0 such that we hit the max density
    ray = ds.ortho_ray(ax, (c[1], c[2]))
 
+   # Sort the ray values by 'x' so there are no discontinuities
+   # in the line plot
+   srt = np.argsort(ray['x'])
+
    P.subplot(211)
-   P.semilogy(np.array(ray['x']), np.array(ray['density']))
+   P.semilogy(np.array(ray['x'][srt]), np.array(ray['density'][srt]))
    P.ylabel('density')
    P.subplot(212)
-   P.semilogy(np.array(ray['x']), np.array(ray['temperature']))
+   P.semilogy(np.array(ray['x'][srt]), np.array(ray['temperature'][srt]))
    P.xlabel('x')
    P.ylabel('temperature')
 


https://bitbucket.org/yt_analysis/yt/commits/e6fd5b15ee05/
Changeset:   e6fd5b15ee05
Branch:      yt-3.0
User:        ngoldbaum
Date:        2014-07-11 16:44:23
Summary:     Updating the timestamp callback, removing two unused callbacks.
Affected #:  1 file

diff -r 37696c30a18b6a4c688b5f02661860ffbda0a781 -r e6fd5b15ee05c573c2ac33e0382d5efa58bad60b yt/visualization/plot_modifications.py
--- a/yt/visualization/plot_modifications.py
+++ b/yt/visualization/plot_modifications.py
@@ -1069,114 +1069,29 @@
     def __call__(self,plot):
         plot._axes.set_title(self.title)
 
-class FlashRayDataCallback(PlotCallback):
-    """ 
-    annotate_flash_ray_data(cmap_name='bone', sample=None)
-
-    Adds ray trace data to the plot.  *cmap_name* is the name of the color map 
-    ('bone', 'jet', 'hot', etc).  *sample* dictates the amount of down sampling 
-    to do to prevent all of the rays from being  plotted.  This may be None 
-    (plot all rays, default), an integer (step size), or a slice object.
+class TimestampCallback(PlotCallback):
     """
-    _type_name = "flash_ray_data"
-    def __init__(self, cmap_name='bone', sample=None):
-        self.cmap_name = cmap_name
-        self.sample = sample if isinstance(sample, slice) else slice(None, None, sample)
-
-    def __call__(self, plot):
-        ray_data = plot.data.pf._handle["RayData"][:]
-        idx = ray_data[:,0].argsort(kind="mergesort")
-        ray_data = ray_data[idx]
-
-        tags = ray_data[:,0]
-        coords = ray_data[:,1:3]
-        power = ray_data[:,4]
-        power /= power.max()
-        cx, cy = self.convert_to_plot(plot, coords.T)
-        coords[:,0], coords[:,1] = cx, cy
-        splitidx = np.argwhere(0 < (tags[1:] - tags[:-1])) + 1
-        coords = np.split(coords, splitidx.flat)[self.sample]
-        power = np.split(power, splitidx.flat)[self.sample]
-        cmap = matplotlib.cm.get_cmap(self.cmap_name)
-
-        plot._axes.hold(True)
-        colors = [cmap(p.max()) for p in power]
-        lc = matplotlib.collections.LineCollection(coords, colors=colors)
-        plot._axes.add_collection(lc)
-        plot._axes.hold(False)
-
-
-class TimestampCallback(PlotCallback):
-    """ 
     annotate_timestamp(x, y, units=None, format="{time:.3G} {units}", **kwargs,
                        normalized=False, bbox_dict=None)
 
-    Adds the current time to the plot at point given by *x* and *y*.  If *units* 
-    is given ('s', 'ms', 'ns', etc), it will covert the time to this basis.  If 
-    *units* is None, it will attempt to figure out the correct value by which to 
-    scale.  The *format* keyword is a template string that will be evaluated and 
-    displayed on the plot.  If *normalized* is true, *x* and *y* are interpreted 
-    as normalized plot coordinates (0,0 is lower-left and 1,1 is upper-right) 
-    otherwise *x* and *y* are assumed to be in plot coordinates. The *bbox_dict* 
-    is an optional dict of arguments for the bbox that frames the timestamp, see 
-    matplotlib's text annotation guide for more details. All other *kwargs* will 
-    be passed to the text() method on the plot axes.  See matplotlib's text() 
+    Adds the current time to the plot at point given by *x* and *y*.  If *units*
+    is given ('s', 'ms', 'ns', etc), it will covert the time to this basis.  If
+    *units* is None, it will attempt to figure out the correct value by which to
+    scale.  The *format* keyword is a template string that will be evaluated and
+    displayed on the plot.  If *normalized* is true, *x* and *y* are interpreted
+    as normalized plot coordinates (0,0 is lower-left and 1,1 is upper-right)
+    otherwise *x* and *y* are assumed to be in plot coordinates. The *bbox_dict*
+    is an optional dict of arguments for the bbox that frames the timestamp, see
+    matplotlib's text annotation guide for more details. All other *kwargs* will
+    be passed to the text() method on the plot axes.  See matplotlib's text()
     functions for more information.
     """
     _type_name = "timestamp"
-    _time_conv = {
-          'as': 1e-18,
-          'attosec': 1e-18,
-          'attosecond': 1e-18,
-          'attoseconds': 1e-18,
-          'fs': 1e-15,
-          'femtosec': 1e-15,
-          'femtosecond': 1e-15,
-          'femtoseconds': 1e-15,
-          'ps': 1e-12,
-          'picosec': 1e-12,
-          'picosecond': 1e-12,
-          'picoseconds': 1e-12,
-          'ns': 1e-9,
-          'nanosec': 1e-9,
-          'nanosecond':1e-9,
-          'nanoseconds' : 1e-9,
-          'us': 1e-6,
-          'microsec': 1e-6,
-          'microsecond': 1e-6,
-          'microseconds': 1e-6,
-          'ms': 1e-3,
-          'millisec': 1e-3,
-          'millisecond': 1e-3,
-          'milliseconds': 1e-3,
-          's': 1.0,
-          'sec': 1.0,
-          'second':1.0,
-          'seconds': 1.0,
-          'm': 60.0,
-          'min': 60.0,
-          'minute': 60.0,
-          'minutes': 60.0,
-          'h': sec_per_hr,
-          'hour': sec_per_hr,
-          'hours': sec_per_hr,
-          'd': sec_per_day,
-          'day': sec_per_day,
-          'days': sec_per_day,
-          'y': sec_per_year,
-          'year': sec_per_year,
-          'years': sec_per_year,
-          'kyr': sec_per_kyr,
-          'myr': sec_per_Myr,
-          'gyr': sec_per_Gyr,
-          'ev': 1e-9 * 7.6e-8 / 6.03,
-          'kev': 1e-12 * 7.6e-8 / 6.03,
-          'mev': 1e-15 * 7.6e-8 / 6.03,
-          }
-    _bbox_dict = {'boxstyle': 'square,pad=0.6', 'fc': 'white', 'ec': 'black', 'alpha': 1.0}
+    _bbox_dict = {'boxstyle': 'square,pad=0.6', 'fc': 'white', 'ec': 'black',
+                  'alpha': 1.0}
 
-    def __init__(self, x, y, units=None, format="{time:.3G} {units}", normalized=False, 
-                 bbox_dict=None, **kwargs):
+    def __init__(self, x, y, units=None, format="{time:.3G} {units}",
+                 normalized=False, bbox_dict=None, **kwargs):
         self.x = x
         self.y = y
         self.format = format
@@ -1191,55 +1106,30 @@
 
     def __call__(self, plot):
         if self.units is None:
-            t = plot.data.pf.current_time * plot.data.pf['Time']
-            scale_keys = ['as', 'fs', 'ps', 'ns', 'us', 'ms', 's', 
-                          'hour', 'day', 'year', 'kyr', 'myr', 'gyr']
-            self.units = 's'
-            for k in scale_keys:
-                if t < self._time_conv[k]:
+            t = plot.data.pf.current_time.in_units('s')
+            scale_keys = ['fs', 'ps', 'ns', 'us', 'ms', 's', 'hr', 'day',
+                          'yr', 'kyr', 'Myr', 'Gyr']
+            for i, k in enumerate(scale_keys):
+                if t < YTQuantity(1, k):
                     break
-                self.units = k
-        t = plot.data.pf.current_time * plot.data.pf['Time'] 
-        t /= self._time_conv[self.units.lower()]
+                t.convert_to_units(k)
+            self.units = scale_keys[i-1]
+        else:
+            t = plot.data.pf.current_time.in_units(self.units)
         if self.units == 'us':
             self.units = '$\\mu s$'
-        s = self.format.format(time=t, units=self.units)
+        s = self.format.format(time=float(t), units=self.units)
         plot._axes.hold(True)
         if self.normalized:
             plot._axes.text(self.x, self.y, s, horizontalalignment='center',
                             verticalalignment='center', 
-                            transform = plot._axes.transAxes, bbox=self.bbox_dict)
+                            transform = plot._axes.transAxes,
+                            bbox=self.bbox_dict)
         else:
-            plot._axes.text(self.x, self.y, s, bbox=self.bbox_dict, **self.kwargs)
+            plot._axes.text(self.x, self.y, s, bbox=self.bbox_dict,
+                            **self.kwargs)
         plot._axes.hold(False)
 
-
-class MaterialBoundaryCallback(ContourCallback):
-    """ 
-    annotate_material_boundary(self, field='targ', ncont=1, factor=4, 
-                               clim=(0.9, 1.0), **kwargs):
-
-    Add the limiting contours of *field* to the plot.  Nominally, *field* is 
-    the target material but may be any other field present in the index.
-    The number of contours generated is given by *ncount*, *factor* governs 
-    the number of points used in the interpolation, and *clim* gives the 
-    (upper, lower) limits for contouring.  For this to truly be the boundary
-    *clim* should be close to the edge.  For example the default is (0.9, 1.0)
-    for 'targ' which is defined on the range [0.0, 1.0].  All other *kwargs* 
-    will be passed to the contour() method on the plot axes.  See matplotlib
-    for more information.
-    """
-    _type_name = "material_boundary"
-    def __init__(self, field='targ', ncont=1, factor=4, clim=(0.9, 1.0), **kwargs):
-        plot_args = {'colors': 'w'}
-        plot_args.update(kwargs)
-        super(MaterialBoundaryCallback, self).__init__(field=field, ncont=ncont,
-                                                       factor=factor, clim=clim,
-                                                       plot_args=plot_args)
-
-    def __call__(self, plot):
-        super(MaterialBoundaryCallback, self).__call__(plot)
-
 class TriangleFacetsCallback(PlotCallback):
     """ 
     annotate_triangle_facets(triangle_vertices, plot_args=None )


https://bitbucket.org/yt_analysis/yt/commits/88685f526f93/
Changeset:   88685f526f93
Branch:      yt-3.0
User:        ngoldbaum
Date:        2014-07-11 16:56:18
Summary:     Adding docs for the timestamp callback.
Affected #:  1 file

diff -r e6fd5b15ee05c573c2ac33e0382d5efa58bad60b -r 88685f526f93dd1ad55aa7f841a53b822fdaf108 doc/source/visualizing/_cb_docstrings.inc
--- a/doc/source/visualizing/_cb_docstrings.inc
+++ b/doc/source/visualizing/_cb_docstrings.inc
@@ -414,3 +414,32 @@
    p = yt.SlicePlot(ds, 'z', 'density', center='m', width=(10, 'kpc'))
    p.annotate_velocity()
    p.save()
+
+Add a Timestamp Inset Box
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. function:: annotate_timestamp(x, y, units=None, format="{time:.3G} {units}", 
+                                 **kwargs, normalized=False, bbox_dict=None)
+
+   (This is a proxy for
+   :class:`~yt.visualization.plot_modifications.TimestampCallback`.)
+
+   Adds the current time to the plot at point given by *x* and *y*.  If *units*
+   is given ('s', 'ms', 'ns', etc), it will covert the time to this basis.  If
+   *units* is None, it will attempt to figure out the correct value by which to
+   scale.  The *format* keyword is a template string that will be evaluated and
+   displayed on the plot.  If *normalized* is true, *x* and *y* are interpreted
+   as normalized plot coordinates (0,0 is lower-left and 1,1 is upper-right)
+   otherwise *x* and *y* are assumed to be in plot coordinates. The *bbox_dict*
+   is an optional dict of arguments for the bbox that frames the timestamp, see
+   matplotlib's text annotation guide for more details. All other *kwargs* will
+   be passed to the text() method on the plot axes.  See matplotlib's text()
+   functions for more information.
+
+.. python-script::
+
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   p = yt.SlicePlot(ds, 'z', 'density', center='c', width=(20, 'kpc'))
+   p.annotate_timestamp()
+   p.save()


https://bitbucket.org/yt_analysis/yt/commits/1e7aeba4c9ad/
Changeset:   1e7aeba4c9ad
Branch:      yt-3.0
User:        ngoldbaum
Date:        2014-07-11 16:56:52
Summary:     Merging with mainline tip.
Affected #:  4 files

diff -r 88685f526f93dd1ad55aa7f841a53b822fdaf108 -r 1e7aeba4c9ad5885aa038c1c757bc72d39c6b338 doc/source/cookbook/fits_radio_cubes.ipynb
--- a/doc/source/cookbook/fits_radio_cubes.ipynb
+++ b/doc/source/cookbook/fits_radio_cubes.ipynb
@@ -81,8 +81,7 @@
      "collapsed": false,
      "input": [
       "from yt.frontends.fits.misc import PlotWindowWCS\n",
-      "wcs_slc = PlotWindowWCS(slc)\n",
-      "wcs_slc[\"intensity\"]"
+      "PlotWindowWCS(slc)\n"
      ],
      "language": "python",
      "metadata": {},
@@ -99,7 +98,7 @@
      "cell_type": "code",
      "collapsed": false,
      "input": [
-      "wcs_slc.save()"
+      "slc.save()"
      ],
      "language": "python",
      "metadata": {},
@@ -463,4 +462,4 @@
    "metadata": {}
   }
  ]
-}
\ No newline at end of file
+}

diff -r 88685f526f93dd1ad55aa7f841a53b822fdaf108 -r 1e7aeba4c9ad5885aa038c1c757bc72d39c6b338 yt/frontends/fits/misc.py
--- a/yt/frontends/fits/misc.py
+++ b/yt/frontends/fits/misc.py
@@ -11,6 +11,8 @@
 #-----------------------------------------------------------------------------
 
 import numpy as np
+import base64
+from yt.extern.six.moves import StringIO
 from yt.fields.derived_field import ValidateSpatial
 from yt.utilities.on_demand_imports import _astropy
 from yt.funcs import mylog, get_image_suffix
@@ -177,13 +179,21 @@
                 return self.plots[k]
 
     def show(self):
-        from IPython.core.display import display
-        for k, v in sorted(self.plots.iteritems()):
-            canvas = FigureCanvasAgg(v)
-            display(v)
+        return self
 
     def save(self, name=None, mpl_kwargs=None):
         if mpl_kwargs is None:
             mpl_kwargs = {}
         mpl_kwargs["bbox_inches"] = "tight"
         self.pw.save(name=name, mpl_kwargs=mpl_kwargs)
+
+    def _repr_html_(self):
+        ret = ''
+        for k, v in self.plots.iteritems():
+            canvas = FigureCanvasAgg(v)
+            f = StringIO()
+            canvas.print_figure(f)
+            f.seek(0)
+            img = base64.b64encode(f.read())
+            ret += '<img src="data:image/png;base64,%s"><br>' % img
+        return ret

diff -r 88685f526f93dd1ad55aa7f841a53b822fdaf108 -r 1e7aeba4c9ad5885aa038c1c757bc72d39c6b338 yt/frontends/flash/data_structures.py
--- a/yt/frontends/flash/data_structures.py
+++ b/yt/frontends/flash/data_structures.py
@@ -210,16 +210,19 @@
         self.parameters["Time"] = 1. # default unit is 1...
         
     def _set_code_unit_attributes(self):
-        if "cgs" in (self.parameters.get('pc_unitsbase', "").lower(),
-                     self.parameters.get('unitsystem', "").lower()):
-             b_factor = 1
-        elif self['unitsystem'].lower() == "si":
-             b_factor = np.sqrt(4*np.pi/1e7)
-        elif self['unitsystem'].lower() == "none":
-             b_factor = np.sqrt(4*np.pi)
+
+        if 'unitsystem' in self.parameters:
+            if self['unitsystem'].lower() == "cgs":
+                b_factor = 1.0
+            elif self['unitsystem'].lower() == "si":
+                b_factor = np.sqrt(4*np.pi/1e7)
+            elif self['unitsystem'].lower() == "none":
+                b_factor = np.sqrt(4*np.pi)
+            else:
+                raise RuntimeError("Runtime parameter unitsystem with "
+                                   "value %s is unrecognized" % self['unitsystem'])
         else:
-            raise RuntimeError("Runtime parameter unitsystem with "
-                               "value %s is unrecognized" % self['unitsystem'])
+            b_factor = 1.
         if self.cosmological_simulation == 1:
             length_factor = 1.0 / (1.0 + self.current_redshift)
             temperature_factor = 1.0 / (1.0 + self.current_redshift)**2
@@ -227,6 +230,7 @@
             length_factor = 1.0
             temperature_factor = 1.0
         self.magnetic_unit = self.quan(b_factor, "gauss")
+
         self.length_unit = self.quan(length_factor, "cm")
         self.mass_unit = self.quan(1.0, "g")
         self.time_unit = self.quan(1.0, "s")
@@ -234,7 +238,8 @@
         self.temperature_unit = self.quan(temperature_factor, "K")
         # Still need to deal with:
         #self.conversion_factors['temp'] = (1.0 + self.current_redshift)**-2.0
-
+        self.unit_registry.modify("code_magnetic", self.magnetic_unit)
+        
     def set_code_units(self):
         super(FLASHDataset, self).set_code_units()
         self.unit_registry.modify("code_temperature",
@@ -247,9 +252,9 @@
         for tpname, pval in zip(self._handle[nn][:,'name'],
                                 self._handle[nn][:,'value']):
             if tpname.strip() == pname:
-                if ptype == "string" :
+                if ptype == "string":
                     return pval.strip()
-                else :
+                else:
                     return pval
         raise KeyError(pname)
 

diff -r 88685f526f93dd1ad55aa7f841a53b822fdaf108 -r 1e7aeba4c9ad5885aa038c1c757bc72d39c6b338 yt/visualization/plot_window.py
--- a/yt/visualization/plot_window.py
+++ b/yt/visualization/plot_window.py
@@ -1698,7 +1698,7 @@
         else:
             fsize = figure_size
         self._cb_size = 0.0375*fsize
-        self._ax_text_size = [0.9*fontscale, 0.7*fontscale]
+        self._ax_text_size = [1.2*fontscale, 0.9*fontscale]
         self._top_buff_size = 0.30*fontscale
         self._aspect = ((extent[1] - extent[0])/(extent[3] - extent[2]))
 


https://bitbucket.org/yt_analysis/yt/commits/2d6e0253ad91/
Changeset:   2d6e0253ad91
Branch:      yt-3.0
User:        ngoldbaum
Date:        2014-07-11 19:01:13
Summary:     Merged in ngoldbaum/yt/yt-3.0 (pull request #985)

Updates for the narrative docs on plotting
Affected #:  9 files

diff -r 14dfbdf28b07dd18e112abafce364d04a4864829 -r 2d6e0253ad916f379fa19ec9521beb1932851e59 doc/source/cookbook/simple_plots.rst
--- a/doc/source/cookbook/simple_plots.rst
+++ b/doc/source/cookbook/simple_plots.rst
@@ -118,6 +118,8 @@
 
 .. yt_cookbook:: show_hide_axes_colorbar.py
 
+.. _matplotlib-primitives:
+
 Accessing and Modifying Plots Directly
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 

diff -r 14dfbdf28b07dd18e112abafce364d04a4864829 -r 2d6e0253ad916f379fa19ec9521beb1932851e59 doc/source/reference/api/api.rst
--- a/doc/source/reference/api/api.rst
+++ b/doc/source/reference/api/api.rst
@@ -15,6 +15,7 @@
    ~yt.visualization.plot_window.OffAxisSlicePlot
    ~yt.visualization.plot_window.ProjectionPlot
    ~yt.visualization.plot_window.OffAxisProjectionPlot
+   ~yt.visualization.plot_window.WindowPlotMPL
 
 ProfilePlot and PhasePlot
 ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -24,6 +25,7 @@
 
    ~yt.visualization.profile_plotter.ProfilePlot
    ~yt.visualization.profile_plotter.PhasePlot
+   ~yt.visualization.profile_plotter.PhasePlotMPL
 
 Fixed Resolution Pixelization
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

diff -r 14dfbdf28b07dd18e112abafce364d04a4864829 -r 2d6e0253ad916f379fa19ec9521beb1932851e59 doc/source/visualizing/_cb_docstrings.inc
--- a/doc/source/visualizing/_cb_docstrings.inc
+++ b/doc/source/visualizing/_cb_docstrings.inc
@@ -1,370 +1,445 @@
+Arrow callback
+~~~~~~~~~~~~~~
+
 .. function:: annotate_arrow(self, pos, code_size, plot_args=None):
 
-   (This is a proxy for :class:`~yt.visualization.plot_modifications.ArrowCallback`.)
+   (This is a proxy for
+   :class:`~yt.visualization.plot_modifications.ArrowCallback`.)
 
-   This adds an arrow pointing at *pos* with size
-   *code_size* in code units.  *plot_args* is a dict fed to
+   This adds an arrow pointing at ``pos`` with size
+   ``code_size`` in code units.  ``plot_args`` is a dict fed to
    matplotlib with arrow properties.
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   slc = SlicePlot(pf, 'z', 'density', width=(10,'kpc'), center='max')
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   slc = yt.SlicePlot(ds, 'z', 'density', width=(10,'kpc'), center='c')
    slc.annotate_arrow((0.5, 0.5, 0.5), (1, 'kpc'))
    slc.save()
 
--------------
+Clump Finder Callback
+~~~~~~~~~~~~~~~~~~~~~
 
 .. function:: annotate_clumps(self, clumps, plot_args=None):
 
-   (This is a proxy for :class:`~yt.visualization.plot_modifications.ClumpContourCallback`.)
+   (This is a proxy for
+   :class:`~yt.visualization.plot_modifications.ClumpContourCallback`.)
 
-   Take a list of *clumps* and plot them as a set of
+   Take a list of ``clumps`` and plot them as a set of
    contours.
 
 .. python-script::
 
-   from yt.mods import *
-   from yt.analysis_modules.level_sets.api import *
+   import yt
+   import numpy as np
+   from yt.analysis_modules.level_sets.api import \
+       Clump, find_clumps, get_lowest_clumps
 
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   data_source = pf.disk([0.5, 0.5, 0.5], [0., 0., 1.],
-                           (8., 'kpc'), (1., 'kpc'))
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   data_source = ds.disk([0.5, 0.5, 0.5], [0., 0., 1.],
+                         (8., 'kpc'), (1., 'kpc'))
 
    c_min = 10**np.floor(np.log10(data_source['density']).min()  )
    c_max = 10**np.floor(np.log10(data_source['density']).max()+1)
 
-   function = 'self.data[\'Density\'].size > 20'
+   function = 'self.data[\'density\'].size > 20'
    master_clump = Clump(data_source, None, 'density', function=function)
    find_clumps(master_clump, c_min, c_max, 2.0)
    leaf_clumps = get_lowest_clumps(master_clump)
 
-   prj = ProjectionPlot(pf, 2, 'density', center='c', width=(20,'kpc'))
+   prj = yt.ProjectionPlot(ds, 2, 'density', center='c', width=(20,'kpc'))
    prj.annotate_clumps(leaf_clumps)
    prj.save('clumps')
 
--------------
+Overplot Contours
+~~~~~~~~~~~~~~~~~
 
-.. function:: annotate_contour(self, field, ncont=5, factor=4, take_log=False, clim=None, plot_args=None):
+.. function:: annotate_contour(self, field, ncont=5, factor=4, take_log=False,
+                               clim=None, plot_args=None):
 
-   (This is a proxy for :class:`~yt.visualization.plot_modifications.ContourCallback`.)
+   (This is a proxy for
+   :class:`~yt.visualization.plot_modifications.ContourCallback`.)
 
-   Add contours in *field* to the plot.  *ncont* governs the
-   number of contours generated, *factor* governs the number
-   of points used in the interpolation, *take_log* governs
-   how it is contoured and *clim* gives the (upper, lower)
-   limits for contouring.
+   Add contours in ``field`` to the plot.  ``ncont`` governs the number of
+   contours generated, ``factor`` governs the number of points used in the
+   interpolation, ``take_log`` governs how it is contoured and ``clim`` gives
+   the (upper, lower) limits for contouring.
 
 .. python-script::
-   
-   from yt.mods import *
-   pf = load("Enzo_64/DD0043/data0043")
-   s = SlicePlot(pf, "x", ["density"], center="max")
+
+   import yt
+   ds = yt.load("Enzo_64/DD0043/data0043")
+   s = yt.SlicePlot(ds, "x", "density", center="max")
    s.annotate_contour("temperature")
    s.save()
 
--------------
+Overplot quivers
+~~~~~~~~~~~~~~~~
+
+Axis-Aligned data sources
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. function:: annotate_quiver(self, field_x, field_y, factor, scale=None,
+                              scale_units=None, normalize=False):
+
+   (This is a proxy for
+   :class:`~yt.visualization.plot_modifications.QuiverCallback`.)
+
+   Adds a 'quiver' plot to any plot, using the ``field_x`` and ``field_y`` from
+   the associated data, skipping every ``factor`` datapoints ``scale`` is the
+   data units per arrow length unit using ``scale_units`` (see
+   matplotlib.axes.Axes.quiver for more info)
+
+.. python-script::
+
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   p = yt.ProjectionPlot(ds, 'z', 'density', center=[0.5, 0.5, 0.5],
+                         weight_field='density', width=(20, 'kpc'))
+   p.annotate_quiver('velocity_x', 'velocity_y', 16)
+   p.save()
+
+Off-axis Data Sources
+^^^^^^^^^^^^^^^^^^^^^
 
 .. function:: annotate_cquiver(self, field_x, field_y, factor):
 
-   (This is a proxy for :class:`~yt.visualization.plot_modifications.CuttingQuiverCallback`.)
+   (This is a proxy for
+   :class:`~yt.visualization.plot_modifications.CuttingQuiverCallback`.)
 
-   Get a quiver plot on top of a cutting plane, using
-   *field_x* and *field_y*, skipping every *factor*
-   datapoint in the discretization.
+   Get a quiver plot on top of a cutting plane, using ``field_x`` and
+   ``field_y``, skipping every ``factor`` datapoint in the discretization.
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("Enzo_64/DD0043/data0043")
-   s = OffAxisSlicePlot(pf, [1,1,0], ["density"], center="c")
+   import yt
+   ds = yt.load("Enzo_64/DD0043/data0043")
+   s = yt.OffAxisSlicePlot(ds, [1,1,0], ["density"], center="c")
    s.annotate_cquiver('cutting_plane_velocity_x', 'cutting_plane_velocity_y', 10)
    s.zoom(1.5)
    s.save()
 
--------------
+Overplot grids
+~~~~~~~~~~~~~~
 
-.. function:: annotate_grids(self, alpha=1.0, min_pix=1, annotate=False, periodic=True):
+.. function:: annotate_grids(self, alpha=1.0, min_pix=1, annotate=False,
+                             periodic=True):
 
-   (This is a proxy for :class:`~yt.visualization.plot_modifications.GridBoundaryCallback`.)
+   (This is a proxy for
+   :class:`~yt.visualization.plot_modifications.GridBoundaryCallback`.)
 
-   Adds grid boundaries to a plot, optionally with
-   *alpha*-blending. Cuttoff for display is at *min_pix*
-   wide. *annotate* puts the grid id in the corner of the
-   grid.  (Not so great in projections...)
+   Adds grid boundaries to a plot, optionally with alpha-blending via the
+   ``alpha`` keyword. Cuttoff for display is at ``min_pix`` wide. ``annotate``
+   puts the grid id in the corner of the grid.  (Not so great in projections...)
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   slc = SlicePlot(pf, 'z', 'density', width=(10,'kpc'), center='max')
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   slc = yt.SlicePlot(ds, 'z', 'density', width=(10,'kpc'), center='max')
    slc.annotate_grids()
    slc.save()
 
--------------
+Overplot Halo Annotations
+~~~~~~~~~~~~~~~~~~~~~~~~~
 
-.. function:: annotate_halos(self, halo_catalog, col='white', alpha =1, width= None):
+.. function:: annotate_halos(self, halo_catalog, col='white', alpha =1,
+                             width=None):
 
-   (This is a proxy for :class:`~yt.visualization.plot_modifications.HaloCatalogCallback`.)
+   (This is a proxy for
+   :class:`~yt.visualization.plot_modifications.HaloCatalogCallback`.)
 
-   Accepts a :class:`yt.HaloCatalog` *HaloCatalog* and plots 
-   a circle at the location of each halo with the radius of
-   the circle corresponding to the virial radius of the halo.
-   If *width* is set to None (default) all halos are plotted.
-   Otherwise, only halos that fall within a slab with width
-   *width* centered on the center of the plot data. The 
-   color and transparency of the circles can be controlled with
-   *col* and *alpha* respectively.
+   Accepts a :class:`yt.HaloCatalog` and plots a circle at the location of each
+   halo with the radius of the circle corresponding to the virial radius of the
+   halo.  If ``width`` is set to None (default) all halos are plotted.
+   Otherwise, only halos that fall within a slab with width ``width`` centered
+   on the center of the plot data. The color and transparency of the circles can
+   be controlled with ``col`` and ``alpha`` respectively.
 
 .. python-script::
-   
-   from yt.mods import *
+
+   import yt
    from yt.analysis_modules.halo_analysis.halo_catalog import HaloCatalog
 
-   data_pf = load('Enzo_64/RD0006/RedshiftOutput0006')
-   halos_pf = load('rockstar_halos/halos_0.0.bin')
+   data_ds = yt.load('Enzo_64/RD0006/RedshiftOutput0006')
+   halos_ds = yt.load('rockstar_halos/halos_0.0.bin')
 
-   hc = HaloCatalog(halos_pf=halos_pf)
+   hc = HaloCatalog(halos_pf=halos_ds)
    hc.create()
 
-   prj = ProjectionPlot(data_pf, 'z', 'density')
+   prj = yt.ProjectionPlot(data_ds, 'z', 'density')
    prj.annotate_halos(hc)
    prj.save()
 
--------------
+Overplot a Straight Line
+~~~~~~~~~~~~~~~~~~~~~~~~
 
-.. function:: annotate_image_line(self, p1, p2, data_coords=False, plot_args=None):
+.. function:: annotate_image_line(self, p1, p2, data_coords=False,
+                                  plot_args=None):
 
-   (This is a proxy for :class:`~yt.visualization.plot_modifications.ImageLineCallback`.)
+   (This is a proxy for
+   :class:`~yt.visualization.plot_modifications.ImageLineCallback`.)
 
-   Plot from *p1* to *p2* (normalized image plane coordinates) with
-   *plot_args* fed into the plot.
+   Plot from ``p1`` to ``p2`` (normalized image plane coordinates) with
+  ``plot_args`` fed into the plot.
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   p = ProjectionPlot(pf, 'z', 'density', center='m', width=(10, 'kpc'))
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   p = yt.ProjectionPlot(ds, 'z', 'density', center='m', width=(10, 'kpc'))
    p.annotate_image_line((0.3, 0.4), (0.8, 0.9), plot_args={'linewidth':5})
    p.save()
 
--------------
+Overplot a line plot
+~~~~~~~~~~~~~~~~~~~~
 
 .. function:: annotate_line(self, x, y, plot_args=None):
 
-   (This is a proxy for :class:`~yt.visualization.plot_modifications.LinePlotCallback`.)
+   (This is a proxy for
+   :class:`~yt.visualization.plot_modifications.LinePlotCallback`.)
 
-   Over plot *x* and *y* (in code units) with *plot_args* fed into the plot.
+   Over plot numpy arrays or lists ``x`` and ``y`` (in code units) with
+   ``plot_args`` fed into the plot.
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   p = ProjectionPlot(pf, 'z', 'density', center='m', width=(10, 'kpc'))
-   p.annotate_line([-6, -4, -2, 0, 2, 4, 6], [3.6, 1.6, 0.4, 0, 0.4, 1.6, 3.6], plot_args={'linewidth':5})
+   import yt
+   import numpy as np
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   p = yt.ProjectionPlot(ds, 'z', 'density', center='m', width=(20, 'kpc'))
+   x = np.array([-6, -4, -2, 0, 2, 4, 6])
+   y = x**2/10
+   p.annotate_line(x, y, plot_args={'linewidth':5})
    p.save()
 
--------------
+Overplot Magnetic Field Quivers
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-.. function:: annotate_magnetic_field(self, factor=16, scale=None, scale_units=None, normalize=False):
+.. function:: annotate_magnetic_field(self, factor=16, scale=None,
+                                      scale_units=None, normalize=False):
 
-   (This is a proxy for :class:`~yt.visualization.plot_modifications.MagFieldCallback`.)
+   (This is a proxy for
+   :class:`~yt.visualization.plot_modifications.MagFieldCallback`.)
 
-   Adds a 'quiver' plot of magnetic field to the plot,
-   skipping all but every *factor* datapoint. *scale* is the
-   data units per arrow length unit using *scale_units* (see
-   matplotlib.axes.Axes.quiver for more info). if
-   *normalize* is True, the magnetic fields will be scaled
-   by their local (in-plane) length, allowing morphological
-   features to be more clearly seen for fields with
-   substantial variation in field strength.
+   Adds a 'quiver' plot of magnetic field to the plot, skipping all but every
+   ``factor`` datapoint. ``scale`` is the data units per arrow length unit using
+   ``scale_units`` (see matplotlib.axes.Axes.quiver for more info). if
+   ``normalize`` is ``True``, the magnetic fields will be scaled by their local
+   (in-plane) length, allowing morphological features to be more clearly seen
+   for fields with substantial variation in field strength.
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("MHDSloshing/virgo_low_res.0054.vtk",
-             parameters={"TimeUnits":3.1557e13, "LengthUnits":3.0856e24,
-                         "DensityUnits":6.770424595218825e-27})
-   p = ProjectionPlot(pf, 'z', 'density', center='c', width=(300, 'kpc'))
+   import yt
+   ds = yt.load("MHDSloshing/virgo_low_res.0054.vtk",
+                parameters={"time_unit":(1, 'Myr'), "length_unit":(1, 'Mpc'),
+                            "mass_unit":(1e17, 'Msun')})
+   p = yt.ProjectionPlot(ds, 'z', 'density', center='c', width=(300, 'kpc'))
    p.annotate_magnetic_field()
    p.save()
 
--------------
+Annotate a Point With a Marker
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 .. function:: annotate_marker(self, pos, marker='x', plot_args=None):
 
-   (This is a proxy for :class:`~yt.visualization.plot_modifications.MarkerAnnotateCallback`.)
+   (This is a proxy for
+   :class:`~yt.visualization.plot_modifications.MarkerAnnotateCallback`.)
 
-   Adds text *marker* at *pos* in code coordinates.
-   *plot_args* is a dict that will be forwarded to the plot
+   Adds ``marker`` at ``pos`` in code coordinates.
+   ``plot_args`` is a dict that will be forwarded to the plot
    command.
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   s = SlicePlot(pf, 'z', 'density', center='m', width=(10, 'kpc'))
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   s = yt.SlicePlot(ds, 'z', 'density', center='c', width=(10, 'kpc'))
    s.annotate_marker([0.5, 0.5, 0.5], plot_args={'s':10000})
-   s.save()   
+   s.save()
 
--------------
+Overplotting Particle Positions
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-.. function:: annotate_particles(self, width, p_size=1.0, col='k', marker='o', stride=1.0, ptype=None, stars_only=False, dm_only=False, minimum_mass=None):
+.. function:: annotate_particles(self, width, p_size=1.0, col='k', marker='o',
+                                 stride=1.0, ptype=None, stars_only=False,
+                                 dm_only=False, minimum_mass=None):
 
-   (This is a proxy for :class:`~yt.visualization.plot_modifications.ParticleCallback`.)
+   (This is a proxy for
+   :class:`~yt.visualization.plot_modifications.ParticleCallback`.)
 
-   Adds particle positions, based on a thick slab along
-   *axis* with a *width* along the line of sight.  *p_size*
-   controls the number of pixels per particle, and *col*
-   governs the color.  *ptype* will restrict plotted
-   particles to only those that are of a given type.
-   *minimum_mass* will require that the particles be of a
-   given mass, calculated via ParticleMassMsun, to be
-   plotted.
+   Adds particle positions, based on a thick slab along ``axis`` with a
+   ``width`` along the line of sight.  ``p_size`` controls the number of pixels
+   per particle, and ``col`` governs the color.  ``ptype`` will restrict plotted
+   particles to only those that are of a given type.  ``minimum_mass`` will
+   require that the particles be of a given mass minimum mass in solar units.
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("Enzo_64/DD0043/data0043")
-   p = ProjectionPlot(pf, "x", "density", center='m', width=(10, 'Mpc'))
+   import yt
+   ds = yt.load("Enzo_64/DD0043/data0043")
+   p = yt.ProjectionPlot(ds, "x", "density", center='m', width=(10, 'Mpc'))
    p.annotate_particles((10, 'Mpc'))
    p.save()
 
--------------
+Annotate a point with text
+~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 .. function:: annotate_point(self, pos, text, text_args=None):
 
-   (This is a proxy for :class:`~yt.visualization.plot_modifications.PointAnnotateCallback`.)
+   (This is a proxy for
+   :class:`~yt.visualization.plot_modifications.PointAnnotateCallback`.)
 
-   This adds *text* at position *pos*, where *pos* is in
-   code-space. *text_args* is a dict fed to the text
-   placement code.
+   This adds ``text`` at position ``pos``, where ``pos`` is in
+   code-space. ``text_args`` is a dict fed to the text placement code.
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   p = ProjectionPlot(pf, 'z', 'density', center='m', width=(10, 'kpc'))
-   p.annotate_point([0.5, 0.496, 0.5], "What's going on here?", text_args={'size':'xx-large', 'color':'w'})
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   p = yt.ProjectionPlot(ds, 'z', 'density', center='m', width=(10, 'kpc'))
+   p.annotate_point([0.5, 0.496, 0.5], "What's going on here?",
+                    text_args={'size':'xx-large', 'color':'w'})
    p.save()
 
--------------
+Overplot a circle on a plot
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-.. function:: annotate_quiver(self, field_x, field_y, factor, scale=None, scale_units=None, normalize=False):
+.. function:: annotate_sphere(self, center, radius, circle_args=None, text=None,
+                              text_args=None):
 
-   (This is a proxy for :class:`~yt.visualization.plot_modifications.QuiverCallback`.)
+   (This is a proxy for
+   :class:`~yt.visualization.plot_modifications.SphereCallback`.)
 
-   Adds a 'quiver' plot to any plot, using the *field_x* and
-   *field_y* from the associated data, skipping every
-   *factor* datapoints *scale* is the data units per arrow
-   length unit using *scale_units*  (see
-   matplotlib.axes.Axes.quiver for more info)
+   A sphere centered at ``center`` in code units with radius ``radius`` in code
+   units will be created, with optional ``circle_args``, ``text``, and
+   ``text_args``.
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   p = ProjectionPlot(pf, 'z', 'density', center=[0.5, 0.5, 0.5], 
-                      weight_field='density', width=(20, 'kpc'))
-   p.annotate_quiver('velocity_x', 'velocity_y', 16)
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   p = yt.ProjectionPlot(ds, 'z', 'density', center='c', width=(20, 'kpc'))
+   p.annotate_sphere([0.5, 0.5, 0.5], (2, 'kpc'), {'fill':True})
    p.save()
 
--------------
+Overplot streamlines
+~~~~~~~~~~~~~~~~~~~~
 
-.. function:: annotate_sphere(self, center, radius, circle_args=None, text=None, text_args=None):
+.. function:: annotate_streamlines(self, field_x, field_y, factor=6.0, nx=16,
+                                   ny=16, xstart=(0, 1), ystart=(0, 1),
+                                   nsample=256, start_at_xedge=False,
+                                   start_at_yedge=False, plot_args=None):
 
-   (This is a proxy for :class:`~yt.visualization.plot_modifications.SphereCallback`.)
+   (This is a proxy for
+   :class:`~yt.visualization.plot_modifications.StreamlineCallback`.)
 
-   A sphere centered at *center* in code units with radius
-   *radius* in code units will be created, with optional
-   *circle_args*, *text*, and *text_args*.
+   Add streamlines to any plot, using the ``field_x`` and ``field_y`` from the
+   associated data, using ``nx`` and ``ny`` starting points that are bounded by
+   ``xstart`` and ``ystart``.  To begin streamlines from the left edge of the
+   plot, set ``start_at_xedge`` to ``True``; for the bottom edge, use
+   ``start_at_yedge``.  A line with the qmean vector magnitude will cover
+   1.0/``factor`` of the image.
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   p = ProjectionPlot(pf, 'z', 'density', center='c', width=(20, 'kpc'))
-   p.annotate_sphere([0.5, 0.5, 0.5], (2, 'kpc'), {'fill':True})
-   p.save()
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   s = yt.SlicePlot(ds, 'z', 'density', center='c', width=(20, 'kpc'))
+   s.annotate_streamlines('velocity_x', 'velocity_y')
+   s.save()
 
--------------
+Add text
+~~~~~~~~
 
-.. function:: annotate_streamlines(self, field_x, field_y, factor=6.0, nx=16, ny=16, xstart=(0, 1), ystart=(0, 1), nsample=256, start_at_xedge=False, start_at_yedge=False, plot_args=None):
+.. function:: annotate_text(self, pos, text, data_coords=False, text_args=None):
 
-   (This is a proxy for :class:`~yt.visualization.plot_modifications.StreamlineCallback`.)
+   (This is a proxy for
+   :class:`~yt.visualization.plot_modifications.TextLabelCallback`.)
 
-   Add streamlines to any plot, using the *field_x* and
-   *field_y* from the associated data, using *nx* and *ny*
-   starting points that are bounded by *xstart* and
-   *ystart*.  To begin streamlines from the left edge of the
-   plot, set *start_at_xedge* to True; for the bottom edge,
-   use *start_at_yedge*.  A line with the qmean vector
-   magnitude will cover 1.0/*factor* of the image.
+   Accepts a position in (0..1, 0..1) of the image, some text and optionally
+   some text arguments. If data_coords is True, position will be in code units
+   instead of image coordinates.
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   s = SlicePlot(pf, 'z', 'density', center='c', width=(20, 'kpc'))
-   s.annotate_streamlines('velocity_x', 'velocity_y')
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   s = yt.SlicePlot(ds, 'z', 'density', center='m', width=(10, 'kpc'))
+   s.annotate_text((0.5, 0.5), 'Sample text',
+                   text_args={'size':'xx-large', 'color':'w'})
    s.save()
 
--------------
+Add a title to the plot
+~~~~~~~~~~~~~~~~~~~~~~~
 
-.. function:: annotate_text(self, pos, text, data_coords=False, text_args=None):
+.. function:: annotate_title(self, title='Plot'):
 
-   (This is a proxy for :class:`~yt.visualization.plot_modifications.TextLabelCallback`.)
+   (This is a proxy for
+   :class:`~yt.visualization.plot_modifications.TitleCallback`.)
 
-   Accepts a position in (0..1, 0..1) of the image, some
-   text and optionally some text arguments. If data_coords
-   is True, position will be in code units instead of image
-   coordinates.
+   Accepts a ``title`` and adds it to the plot.
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   s = SlicePlot(pf, 'z', 'density', center='m', width=(10, 'kpc'))
-   s.annotate_text((0.5, 0.5), 'Sample text', text_args={'size':'xx-large', 'color':'w'})
-   s.save()
-
--------------
-
-.. function:: annotate_title(self, title='Plot'):
-
-   (This is a proxy for :class:`~yt.visualization.plot_modifications.TitleCallback`.)
-
-   Accepts a *title* and adds it to the plot
-
-.. python-script::
-
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   p = ProjectionPlot(pf, 'z', 'density', center='c', width=(20, 'kpc'))
-   p.annotate_title('Density plot')
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   p = yt.ProjectionPlot(ds, 'z', 'density', center='c', width=(20, 'kpc'))
+   p.annotate_title('Density Plot')
    p.save()
 
--------------
+Overplot quivers for the velocity field
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-.. function:: annotate_velocity(self, factor=16, scale=None, scale_units=None, normalize=False):
+.. function:: annotate_velocity(self, factor=16, scale=None, scale_units=None,
+                                normalize=False):
 
-   (This is a proxy for :class:`~yt.visualization.plot_modifications.VelocityCallback`.)
+   (This is a proxy for
+   :class:`~yt.visualization.plot_modifications.VelocityCallback`.)
 
-   Adds a 'quiver' plot of velocity to the plot, skipping
-   all but every *factor* datapoint. *scale* is the data
-   units per arrow length unit using *scale_units* (see
-   matplotlib.axes.Axes.quiver for more info). if
-   *normalize* is True, the velocity fields will be scaled
-   by their local (in-plane) length, allowing morphological
-   features to be more clearly seen for fields with
-   substantial variation in field strength (normalize is not
+   Adds a 'quiver' plot of velocity to the plot, skipping all but every
+   ``factor`` datapoint. ``scale`` is the data units per arrow length unit using
+   ``scale_units`` (see matplotlib.axes.Axes.quiver for more info). if
+   ``normalize`` is ``True``, the velocity fields will be scaled by their local
+   (in-plane) length, allowing morphological features to be more clearly seen
+   for fields with substantial variation in field strength (normalize is not
    implemented and thus ignored for Cutting Planes).
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   p = SlicePlot(pf, 'z', 'density', center='m', width=(10, 'kpc'))
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   p = yt.SlicePlot(ds, 'z', 'density', center='m', width=(10, 'kpc'))
    p.annotate_velocity()
    p.save()
+
+Add a Timestamp Inset Box
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. function:: annotate_timestamp(x, y, units=None, format="{time:.3G} {units}", 
+                                 **kwargs, normalized=False, bbox_dict=None)
+
+   (This is a proxy for
+   :class:`~yt.visualization.plot_modifications.TimestampCallback`.)
+
+   Adds the current time to the plot at point given by *x* and *y*.  If *units*
+   is given ('s', 'ms', 'ns', etc), it will covert the time to this basis.  If
+   *units* is None, it will attempt to figure out the correct value by which to
+   scale.  The *format* keyword is a template string that will be evaluated and
+   displayed on the plot.  If *normalized* is true, *x* and *y* are interpreted
+   as normalized plot coordinates (0,0 is lower-left and 1,1 is upper-right)
+   otherwise *x* and *y* are assumed to be in plot coordinates. The *bbox_dict*
+   is an optional dict of arguments for the bbox that frames the timestamp, see
+   matplotlib's text annotation guide for more details. All other *kwargs* will
+   be passed to the text() method on the plot axes.  See matplotlib's text()
+   functions for more information.
+
+.. python-script::
+
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   p = yt.SlicePlot(ds, 'z', 'density', center='c', width=(20, 'kpc'))
+   p.annotate_timestamp()
+   p.save()

diff -r 14dfbdf28b07dd18e112abafce364d04a4864829 -r 2d6e0253ad916f379fa19ec9521beb1932851e59 doc/source/visualizing/manual_plotting.rst
--- a/doc/source/visualizing/manual_plotting.rst
+++ b/doc/source/visualizing/manual_plotting.rst
@@ -35,11 +35,12 @@
 .. python-script::
    
    import pylab as P
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   import numpy as np
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
 
-   c = pf.h.find_max('density')[1]
-   proj = pf.proj('density', 0)
+   c = ds.find_max('density')[1]
+   proj = ds.proj('density', 0)
 
    width = (10, 'kpc') # we want a 1.5 mpc view
    res = [1000, 1000] # create an image with 1000x1000 pixels
@@ -64,22 +65,33 @@
 Line Plots
 ----------
 
-This is perhaps the simplest thing to do. ``yt`` provides a number of one dimensional objects, and these return a 1-D numpy array of their contents with direct dictionary access. As a simple example, take a :class:`~yt.data_objects.data_containers.AMROrthoRayBase` object, which can be created from a index by calling ``pf.ortho_ray(axis, center)``. 
+This is perhaps the simplest thing to do. ``yt`` provides a number of one
+dimensional objects, and these return a 1-D numpy array of their contents with
+direct dictionary access. As a simple example, take a
+:class:`~yt.data_objects.data_containers.AMROrthoRayBase` object, which can be
+created from a index by calling ``pf.ortho_ray(axis, center)``.
 
 .. python-script::
 
-   from yt.mods import *
+   import yt
+   import numpy as np
    import pylab as P
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   c = pf.h.find_max("density")[1]
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   c = ds.find_max("density")[1]
    ax = 0 # take a line cut along the x axis
-   ray = pf.ortho_ray(ax, (c[1], c[2])) # cutting through the y0,z0 such that we hit the max density
+
+   # cutting through the y0,z0 such that we hit the max density
+   ray = ds.ortho_ray(ax, (c[1], c[2]))
+
+   # Sort the ray values by 'x' so there are no discontinuities
+   # in the line plot
+   srt = np.argsort(ray['x'])
 
    P.subplot(211)
-   P.semilogy(np.array(ray['x']), np.array(ray['density']))
+   P.semilogy(np.array(ray['x'][srt]), np.array(ray['density'][srt]))
    P.ylabel('density')
    P.subplot(212)
-   P.semilogy(np.array(ray['x']), np.array(ray['temperature']))
+   P.semilogy(np.array(ray['x'][srt]), np.array(ray['temperature'][srt]))
    P.xlabel('x')
    P.ylabel('temperature')
 

diff -r 14dfbdf28b07dd18e112abafce364d04a4864829 -r 2d6e0253ad916f379fa19ec9521beb1932851e59 doc/source/visualizing/plots.rst
--- a/doc/source/visualizing/plots.rst
+++ b/doc/source/visualizing/plots.rst
@@ -25,10 +25,10 @@
 If you need to take a quick look at a single simulation output, ``yt``
 provides the ``PlotWindow`` interface for generating annotated 2D
 visualizations of simulation data.  You can create a ``PlotWindow`` plot by
-supplying a parameter file, a list of fields to plot, and a plot center to
-create a :class:`~yt.visualization.plot_window.SlicePlot`,
+supplying a dataset, a list of fields to plot, and a plot center to
+create a :class:`~yt.visualization.plot_window.AxisAlignedSlicePlot`,
 :class:`~yt.visualization.plot_window.ProjectionPlot`, or
-:class:`~yt.visualization.plot_window.OffAxisSlicePlot`.
+:class:`~yt.visualization.plot_window.OffAxisProjectionPlot`.
 
 Plot objects use ``yt`` data objects to extract the maximum resolution
 data available to render a 2D image of a field. Whenever a
@@ -37,7 +37,8 @@
 is requested of it -- for instance, when the width or field is changed
 -- this high-resolution data is then pixelized and placed in a buffer
 of fixed size. This is accomplished behind the scenes using
-:class:`~yt.visualization.fixed_resolution.FixedResolutionBuffer`
+:class:`~yt.visualization.fixed_resolution.FixedResolutionBuffer`.
+
 ``PlotWindow`` expose the underlying matplotlib ``figure`` and
 ``axes`` objects, making it easy to customize your plots and 
 add new annotations.
@@ -45,28 +46,33 @@
 .. _slice-plots:
 
 Slice Plots
------------
+~~~~~~~~~~~
 
-The quickest way to plot a slice of a field through your data is to use
-:class:`~yt.visualization.plot_window.SlicePlot`.  Say we want to visualize a
-slice through the Density field along the z-axis centered on the center of the
-simulation box in a simulation dataset we've opened and stored in the parameter
-file object ``pf``.  This can be accomplished with the following command:
+The quickest way to plot a slice of a field through your data is via
+:class:`~yt.visualization.plot_window.SlicePlot`.  These plots are generally
+quicker than projections because they only need to read and process a slice
+through the dataset.
+
+The following script plots a slice through the density field along the z-axis
+centered on the center of the simulation box in a simulation dataset we've
+opened and stored in ``ds``:
 
 .. code-block:: python
 
-   >>> slc = SlicePlot(pf, 'z', 'density')
+   >>> slc = yt.SlicePlot(ds, 'z', 'density')
    >>> slc.save()
 
 These two commands will create a slice object and store it in a variable we've
-called ``slc``.  We then call the ``save()`` function that is associated with
-the slice object.  This automatically saves the plot in png image format with an
-automatically generated filename.  If you don't want the slice object to stick
-around, you can accomplish the same thing in one line:
+called ``slc``.  Since this plot is aligned with the simulation coordinate
+system, ``slc`` is an instance of
+:class:`~yt.visualization.plot_window.AxisAlignedSlicePlot`. We then call the
+``save()`` function, which automatically saves the plot in png image format with
+an automatically generated filename.  If you don't want the slice object to
+stick around, you can accomplish the same thing in one line:
 
 .. code-block:: python
    
-   >>> SlicePlot(pf, 'z', 'density').save()
+   >>> yt.SlicePlot(ds, 'z', 'density').save()
 
 It's nice to keep the slice object around if you want to modify the plot.  By
 default, the plot width will be set to the size of the simulation box.  To zoom
@@ -75,41 +81,58 @@
 
 .. code-block:: python
 
-   >>> slc = SlicePlot(pf, 'z', 'density')
+   >>> slc = yt.SlicePlot(ds, 'z', 'density')
    >>> slc.zoom(10)
    >>> slc.save('zoom')
 
 This will save a new plot to disk with a different filename - prepended with
-'zoom' instead of the name of the parameter file. If you want to set the width
+'zoom' instead of the name of the dataset. If you want to set the width
 manually, you can do that as well. For example, the following sequence of
 commands will create a slice, set the width of the plot to 10 kiloparsecs, and
 save it to disk.
 
 .. code-block:: python
 
-   >>> slc = SlicePlot(pf, 'z', 'density')
-   >>> slc.set_width((10,'kpc'))
+   >>> from yt.units import kpc
+   >>> slc = yt.SlicePlot(ds, 'z', 'density')
+   >>> slc.set_width(10*kpc)
    >>> slc.save('10kpc')
 
-The SlicePlot also optionally accepts the coordinate to center the plot on and
-the width of the plot:
+The plot width can be specified independently along the x and y direction by
+passing a tuple of widths.  An individual width can also be represented using a
+``(value, unit)`` tuple.  The following sequence of commands all equivalently
+set the width of the plot to 200 kiloparsecs in the ``x`` and ``y`` direction.
 
 .. code-block:: python
 
-   >>> SlicePlot(pf, 'z', 'density', center=[0.2, 0.3, 0.8], 
-   ...           width = (10,'kpc')).save()
+   >>> from yt.units import kpc
+   >>> slc.set_width(200*kpc)
+   >>> slc.set_width((200, 'kpc'))
+   >>> slc.set_width((200*kpc, 200*kpc))
 
-The center must be given in code units.  Optionally, you can supply 'c' or 'm'
-for the center.  These two choices will center the plot on the center of the
-simulation box and the coordinate of the maximum density cell, respectively.
+The ``SlicePlot`` also optionally accepts the coordinate to center the plot on
+and the width of the plot:
+
+.. code-block:: python
+
+   >>> yt.SlicePlot(ds, 'z', 'density', center=[0.2, 0.3, 0.8],
+   ...              width = (10,'kpc')).save()
+
+The plot center is relative to the simulation coordinate system.  If supplied
+without units, the center is assumed by in code units.  Optionally, you can
+supply 'c' or 'm' for the center.  These two choices will center the plot on the
+center of the simulation box and the coordinate of the maximum density cell,
+respectively.
 
 Here is an example that combines all of the options we just discussed.
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   slc = SlicePlot(pf, 'z', 'density', center=[0.5, 0.5, 0.5], width=(20,'kpc'))
+   import yt
+   from yt.units import kpc
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   slc = yt.SlicePlot(ds, 'z', 'density', center=[0.5, 0.5, 0.5],
+                      width=(20,'kpc'))
    slc.save()
 
 The above example will display an annotated plot of a slice of the
@@ -118,14 +141,14 @@
 letter 'z', corresponding to the z-axis.  Finally, the image is saved to
 a png file.
 
-Conceptually, you can think of the SlicePlot as an adjustable window
+Conceptually, you can think of the plot object as an adjustable window
 into the data. For example:
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   slc = SlicePlot(pf, 'z', 'pressure', center='c')
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   slc = yt.SlicePlot(ds, 'z', 'pressure', center='c')
    slc.save()
    slc.zoom(30)
    slc.save('zoom')
@@ -138,32 +161,43 @@
 interesting region in the simulation and adjust the boundaries of the
 region to visualize on the fly.
 
-A slice object can also add annotations like a title, an overlying
-quiver plot, the location of grid boundaries, halo-finder annotations,
-and many other annotations, including user-customizable annotations.
-For example:
+See :class:`~yt.visualization.plot_window.AxisAlignedSlicePlot` for the 
+full class description.
+
+.. _off-axis-slices:
+
+Off Axis Slices
+~~~~~~~~~~~~~~~
+
+Off axis slice plots can be generated in much the same way as
+grid-aligned slices.  Off axis slices use
+:class:`~yt.data_objects.data_containers.AMRCuttingPlaneBase` to slice
+through simulation domains at an arbitrary oblique angle.  A
+:class:`~yt.visualization.plot_window.OffAxisSlicePlot` can be
+instantiated by specifying a dataset, the normal to the cutting
+plane, and the name of the fields to plot.  Just like an
+:class:`~yt.visualization.plot_window.AxisAlignedSlicePlot`, an
+``OffAxisSlicePlot`` can be created via the
+:class:`~yt.visualization.plot_window.SlicePlot` function. For example:
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   slc = SlicePlot(pf, 'z', 'density', width=(10,'kpc'))
-   slc.annotate_grids()
-   slc.save()
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   L = [1,1,0] # vector normal to cutting plane
+   north_vector = [-1,1,0]
+   cut = yt.SlicePlot(ds, L, 'density', width=(25, 'kpc'),
+                      north_vector=north_vector)
+   cut.save()
 
-will plot the density field in a 10 kiloparsec slice through the
-z-axis centered on the highest density point in the simulation domain.
-Before saving the plot, the script annotates it with the grid
-boundaries, which are drawn as thick black lines by default.
-
-Annotations are described in :ref:`callbacks`.  See
-:class:`~yt.visualization.plot_window.SlicePlot` for the full class
-description.
+In this case, a normal vector for the cutting plane is supplied in the second
+argument. Optionally, a `north_vector` can be specified to fix the orientation
+of the image plane.
 
 .. _projection-plots:
 
 Projection Plots
-----------------
+~~~~~~~~~~~~~~~~
 
 Using a fast adaptive projection, ``yt`` is able to quickly project
 simulation data along the coordinate axes.
@@ -174,15 +208,15 @@
 
 .. python-script::
  
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   prj = ProjectionPlot(pf, 2, 'density', width=(25, 'kpc'), 
-                        weight_field=None)
+   import yt
+   from yt.units import kpc
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   prj = yt.ProjectionPlot(ds, 2, 'temperature', width=25*kpc,
+                           weight_field='density')
    prj.save()
 
-will create a projection of Density field along the x axis, plot it,
-and then save it to a png image file.  The projection is only carried
-out to level 2 of the AMR index and no weighting is applied.
+will create a density-weighted projection of the temperature field along the x
+axis, plot it, and then save the plot to a png image file.
 
 Like :ref:`slice-plots`, annotations and modifications can be applied
 after creating the ``ProjectionPlot`` object.  Annotations are
@@ -190,43 +224,8 @@
 :class:`~yt.visualization.plot_window.ProjectionPlot` for the full
 class description.
 
-.. _off-axis-slices:
-
-Off Axis Slice Plots
---------------------
-
-Off axis slice plots can be generated in much the same way as
-grid-aligned slices.  Off axis slices use
-:class:`~yt.data_objects.data_containers.AMRCuttingPlaneBase` to slice
-through simulation domains at an arbitrary oblique angle.  A
-:class:`~yt.visualization.plot_window.OffAxisSlicePlot` can be
-instantiated by specifying a parameter file, the normal to the cutting
-plane, and the name of the fields to plot.  For example:
-
-.. python-script::
-
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   L = [1,1,0] # vector normal to cutting plane
-   north_vector = [-1,1,0]
-   cut = OffAxisSlicePlot(pf, L, 'density', width=(25, 'kpc'), 
-                          north_vector=north_vector)
-   cut.save()
-
-creates an off-axis slice in the plane perpendicular to ``L``,
-oriented such that ``north_vector`` is the up direction.  If ``L`` and
-``north_vector`` are not perpendicular, the component of
-``north_vector`` perpendicular to ``L`` is used. Like
-:ref:`slice-plots`, annotations and modifications can be applied after
-creating the ``OffAxisSlicePlot`` object.  Annotations are described
-in :ref:`callbacks`.  See
-:class:`~yt.visualization.plot_window.OffAxisSlicePlot` for the full
-class description.
-
-.. _off-axis-projections:
-
 Off Axis Projection Plots
--------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~
 
 Off axis projection plots .  Internally, off axis projections are
 created using :ref:`the-camera-interface` by applying the
@@ -246,15 +245,16 @@
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   import yt
+   import numpy as np
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
    L = [1,1,0] # vector normal to cutting plane
    north_vector = [-1,1,0]
    W = [0.02, 0.02, 0.02]
    c = [0.5, 0.5, 0.5]
    N = 512
-   image = off_axis_projection(pf, c, L, W, N, "density")
-   write_image(np.log10(image), "%s_offaxis_projection.png" % pf)
+   image = yt.off_axis_projection(ds, c, L, W, N, "density")
+   yt.write_image(np.log10(image), "%s_offaxis_projection.png" % ds)
 
 Here, ``W`` is the width of the projection in the x, y, *and* z
 directions.
@@ -268,32 +268,30 @@
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
    L = [1,1,0] # vector normal to cutting plane
    north_vector = [-1,1,0]
-   prj = OffAxisProjectionPlot(pf,L,'density',width=(25, 'kpc'), 
-                               north_vector=north_vector)
+   prj = yt.OffAxisProjectionPlot(ds,L,'density',width=(25, 'kpc'),
+                                  north_vector=north_vector)
    prj.save()
 
 OffAxisProjectionPlots can also be created with a number of
-keyword arguments, as described in the `api reference`__ for the
-class initializer.
-
-__ :class:`~yt.visualization.plot_window.OffAxisProjectionPlot`
+keyword arguments, as described in
+:class:`~yt.visualization.plot_window.OffAxisProjectionPlot`
 
 Plot Customization
 ------------------
 
 You can customize each of the four plot types above in identical ways.  We'll go
-over each of the customizations methos below.  For each of the examples below we
+over each of the customizations methods below.  For each of the examples below we
 will modify the following plot.
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   slc = SlicePlot(pf, 'z', 'density', width=(10,'kpc'))
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   slc = yt.SlicePlot(ds, 'z', 'density', width=(10,'kpc'))
    slc.save()
 
 Panning and zooming
@@ -301,78 +299,84 @@
 
 There are three methods to dynamically pan around the data.  
 
-:class:`~yt.visualization.plot_window.SlicePlot.pan` accepts x and y deltas in code
-units.
+:class:`~yt.visualization.plot_window.AxisAlignedSlicePlot.pan` accepts x and y
+deltas.
 
 .. python-script::
 
-   from yt.mods import *
+   import yt
    from yt.units import kpc
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   slc = SlicePlot(pf, 'z', 'density', width=(10,'kpc'))
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   slc = yt.SlicePlot(ds, 'z', 'density', width=(10,'kpc'))
    slc.pan((2*kpc, 2*kpc))
    slc.save()
 
-:class:`~yt.visualization.plot_window.SlicePlot.pan_rel` accepts deltas in units relative
-to the field of view of the plot.  
+:class:`~yt.visualization.plot_window.AxisAlignedSlicePlot.pan_rel` accepts deltas 
+in units relative to the field of view of the plot.
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   slc = SlicePlot(pf, 'z', 'density', width=(10,'kpc'))
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   slc = yt.SlicePlot(ds, 'z', 'density', width=(10,'kpc'))
    slc.pan_rel((0.1, -0.1))
    slc.save()
 
-:class:`~yt.visualization.plot_window.SlicePlot.zoom` accepts a factor to zoom in by.
+:class:`~yt.visualization.plot_window.AxisAlignedSlicePlot.zoom` accepts a factor to zoom in by.
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   slc = SlicePlot(pf, 'z', 'density', width=(10,'kpc'))
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   slc = yt.SlicePlot(ds, 'z', 'density', width=(10,'kpc'))
    slc.zoom(2)
    slc.save()
 
 Set axes units
 ~~~~~~~~~~~~~~
 
-:class:`~yt.visualization.plot_window.SlicePlot.set_axes_unit` allows the customization of
+:class:`~yt.visualization.plot_window.AxisAlignedSlicePlot.set_axes_unit` allows the customization of
 the axes unit labels.
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   slc = SlicePlot(pf, 'z', 'density', width=(10,'kpc'))
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   slc = yt.SlicePlot(ds, 'z', 'density', width=(10,'kpc'))
    slc.set_axes_unit('Mpc')
    slc.save()
 
+The same result could have been accomplished by explicitly setting the ``width``
+to ``(.01, 'Mpc')``.
+
 Set the plot center
 ~~~~~~~~~~~~~~~~~~~
 
-The :class:`~yt.visualization.plot_window.SlicePlot.set_center` function accepts a new
-center for the plot, in code units.  New centers must be two element tuples.
+The :class:`~yt.visualization.plot_window.AxisAlignedSlicePlot.set_center`
+function accepts a new center for the plot, in code units.  New centers must be
+two element tuples.
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   slc = SlicePlot(pf, 'z', 'density', width=(10,'kpc'))
-   slc.set_center((0.5, 0.5))
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   slc = yt.SlicePlot(ds, 'z', 'density', width=(10,'kpc'))
+   slc.set_center((0.5, 0.503))
    slc.save()
 
 Fonts
 ~~~~~
 
-:class:`~yt.visualization.plot_window.SlicePlot.set_font` allows font costomization.
+:class:`~yt.visualization.plot_window.AxisAlignedSlicePlot.set_font` allows font
+costomization.
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   slc = SlicePlot(pf, 'z', 'density', width=(10,'kpc'))
-   slc.set_font({'family': 'sans-serif', 'style': 'italic','weight': 'bold', 'size': 24})
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   slc = yt.SlicePlot(ds, 'z', 'density', width=(10,'kpc'))
+   slc.set_font({'family': 'sans-serif', 'style': 'italic',
+                 'weight': 'bold', 'size': 24})
    slc.save()
 
 Colormaps
@@ -383,117 +387,173 @@
 different fields tracked by the plot object.
 
 To change the colormap for the plot, call the
-:class:`~yt.visualization.plot_window.SlicePlot.set_cmap` function.  Use any of the
-colormaps listed in the :ref:`colormaps` section.
+:class:`~yt.visualization.plot_window.AxisAlignedSlicePlot.set_cmap` function.
+Use any of the colormaps listed in the :ref:`colormaps` section.
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   slc = SlicePlot(pf, 'z', 'density', width=(10,'kpc'))
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   slc = yt.SlicePlot(ds, 'z', 'density', width=(10,'kpc'))
    slc.set_cmap('density', 'RdBu_r')
    slc.save()
 
-The :class:`~yt.visualization.plot_window.SlicePlot.set_log` function accepts a field name
-and a boolean.  If the boolean is :code:`True`, the colormap for the field will
-be log scaled.  If it is `False` the colormap will be linear.
+The :class:`~yt.visualization.plot_window.AxisAlignedSlicePlot.set_log` function
+accepts a field name and a boolean.  If the boolean is ``True``, the colormap
+for the field will be log scaled.  If it is ``False`` the colormap will be
+linear.
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   slc = SlicePlot(pf, 'z', 'density', width=(10,'kpc'))
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   slc = yt.SlicePlot(ds, 'z', 'density', width=(10,'kpc'))
    slc.set_log('density', False)
    slc.save()
 
-Lastly, the :class:`~yt.visualization.plot_window.SlicePlot.set_zlim` function makes it
-possible to set a custom colormap range.
+Lastly, the :class:`~yt.visualization.plot_window.AxisAlignedSlicePlot.set_zlim`
+function makes it possible to set a custom colormap range.
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   slc = SlicePlot(pf, 'z', 'density', width=(10,'kpc'))
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   slc = yt.SlicePlot(ds, 'z', 'density', width=(10,'kpc'))
    slc.set_zlim('density', 1e-30, 1e-25)
    slc.save()
 
+Annotations
+~~~~~~~~~~~
+
+A slice object can also add annotations like a title, an overlying
+quiver plot, the location of grid boundaries, halo-finder annotations,
+and many other annotations, including user-customizable annotations.
+For example:
+
+.. python-script::
+
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   slc = yt.SlicePlot(ds, 'z', 'density', width=(10,'kpc'))
+   slc.annotate_grids()
+   slc.save()
+
+will plot the density field in a 10 kiloparsec slice through the
+z-axis centered on the highest density point in the simulation domain.
+Before saving the plot, the script annotates it with the grid
+boundaries, which are drawn as thick black lines by default.
+
+Annotations are described in :ref:`callbacks`.
+
 Set the size of the plot
 ~~~~~~~~~~~~~~~~~~~~~~~~
 
 To set the size of the plot, use the
-:class:`~yt.visualization.plot_window.SlicePlot.set_window_size` function.  The argument
+:class:`~yt.visualization.plot_window.AxisAlignedSlicePlot.set_figure_size` function.  The argument
 is the size of the longest edge of the plot in inches.  View the full resolution
 image to see the difference more clearly.
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   slc = SlicePlot(pf, 'z', 'density', width=(10,'kpc'))
-   slc.set_window_size(10)
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   slc = yt.SlicePlot(ds, 'z', 'density', width=(10,'kpc'))
+   slc.set_figure_size(10)
    slc.save()
 
 To change the resolution of the image, call the
-:class:`~yt.visualization.plot_window.SlicePlot.set_buff_size` function.
+:class:`~yt.visualization.plot_window.AxisAlignedSlicePlot.set_buff_size` function.
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   slc = SlicePlot(pf, 'z', 'density', width=(10,'kpc'))
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   slc = yt.SlicePlot(ds, 'z', 'density', width=(10,'kpc'))
    slc.set_buff_size(1600)
    slc.save()
 
+Further customization via matplotlib
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Each ``PlotWindow`` object is really a container for plots - one plot for each
+field specified in the list of fields supplied when the plot object is
+created. The individual plots can be accessed via the ``plots`` dictionary
+attached to each ``PlotWindow`` object:
+
+.. code-block:: python
+
+   >>> slc = SlicePlot(ds, 2, ['density', 'temperature']
+   >>> dens_plot = slc.plots['density']
+
+In this example ``dens_plot`` is an instance of
+:class:`~yt.visualization.plot_window.WindowPlotMPL`, an object that wraps the
+matplotlib ``figure`` and ``axes`` objects.  We can access these matplotlib primitives via attributes of ``dens_plot``.
+
+.. code-block:: python
+
+   >>> figure = dens_plot.figure
+   >>> axes = dens_plot.axes
+   >>> colorbar_axes = dens_plot.cax
+
+These are the :matplotlib:class:`figure`, and :matplotlib:class:`axes` objects
+that control the actual drawing of the plot.  Arbitrary plot customizations
+are possible by manipulating these objects.  See :ref:`matplotlib-primitives` for
+an example.
+
 .. _how-to-make-1d-profiles:
 
 1D Profile Plots
 ----------------
 
-1D profiles are used to calculated the average or the sum of a given quantity
-with respect to a second quantity.  This means the "average density as a
-function of radius" or "the total mass within a given set of density bins."
+1D profiles are used to calculate the average or the sum of a given quantity
+with respect to a second quantity.  Two common examples are the "average density
+as a function of radius" or "the total mass within a given set of density bins."
 When created, they default to the average: in fact, they default to the average
 as weighted by the total cell mass.  However, this can be modified to take
 either the total value or the average with respect to a different quantity.
 
-Profiles operate on data objects; they will take the entire data contained in a
-sphere, a prism, an extracted region and so on, and they will calculate and use
-that as input to their calculation.  To make a 1D profile plot, create a
-(:class:`~yt.visualization.profile_plotter.ProfilePlot`) object, supplying the 
-data object, the field for binning, and a list of fields to be profiled.
+Profiles operate on :ref:`data objects <using-objects>`; they will take the
+entire data contained in a sphere, a prism, an extracted region and so on, and
+they will calculate and use that as input to their calculation.  To make a 1D
+profile plot, create a (:class:`~yt.visualization.profile_plotter.ProfilePlot`)
+object, supplying the data object, the field for binning, and a list of fields
+to be profiled.
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   my_galaxy = pf.disk([0.5, 0.5, 0.5], [0.0, 0.0, 1.0], 0.01, 0.003)
-   plot = ProfilePlot(my_galaxy, "density", ["temperature"])
+   import yt
+   from yt.units import kpc
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   my_galaxy = ds.disk(ds.domain_center, [0.0, 0.0, 1.0], 10*kpc, 3*kpc)
+   plot = yt.ProfilePlot(my_galaxy, "density", ["temperature"])
    plot.save()
 
 This will create a :class:`yt.data_objects.data_containers.AMRCylinderBase`
-centered at [0.3, 0.5, 0.8], with a normal vector of [0.4, 0.5, 0.1], radius of
-0.01 and height of 0.001 and will then make a plot of the average (as a 
-function of the cell mass) temperature as a function of density.
+centered at [0.5, 0.5, 0.5], with a normal vector of [0.0, 0.0, 1.0], radius of
+10 kiloparsecs and height of 3 kiloparsecs and will then make a plot of the
+mass-weighted average temperature as a function of density for all of the gas
+contained in the cylinder.
 
-As another example, we create a sphere of radius 100 pc and plot total mass 
-in every equally-spaced temperature bin/
-
-We could also have allowed the plot collection to create a sphere for us, as
-well.  For instance:
+We could also have made a profile considering only the gas in a sphere.
+For instance:
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   my_sphere = pf.sphere([0.5, 0.5, 0.5], (100, "kpc"))
-   plot = ProfilePlot(my_sphere, "temperature", ["cell_mass"],
-                      weight_field=None)
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   my_sphere = ds.sphere([0.5, 0.5, 0.5], (100, "kpc"))
+   plot = yt.ProfilePlot(my_sphere, "temperature", ["cell_mass"],
+                         weight_field=None)
    plot.save()
 
-Note that because we have specified the weighting field to be none, it operates 
-as a local-bin accumulator.  We can also accumulate along the x-axis by setting 
-the **accumulation** keyword argument to True, which is useful for plots of 
-enclosed mass.
+Note that because we have specified the weighting field to be none, it operates
+the profile plot will display the accumulated cell mass as a function of
+temperature rather than the average.  We can also accumulate along the x-axis by
+setting the **accumulation** keyword argument to True, which is useful for plots
+of enclosed mass.
+
+Also note the use of a ``(value, unit)`` tuple. These can be used interchangably
+with units explicitly imported from ``yt.units``.
 
 You can also access the data generated by profiles directly, which can be
 useful for overplotting average quantities on top of phase plots, or for
@@ -506,32 +566,30 @@
 
    plot = ProfilePlot(my_sphere, "temperature", ["cell_mass"],
                       weight_field=None)
-   # print the x field
+   profile = plot.profiles[0]
+   # print the bin field, in this case temperature
    print plot.profiles[-1].x
-   # print the profiled temperature field
-   print plot.profiles[-1].field_data["temperature"]
+   # print the profiled cell_mass field
+   print plot.profiles[-1]["cell_mass"]
 
-Other options, such as the number of bins, are also configurable. See the 
-documentation for 
-The number of bins and other options and tweaks are 
-available for these methods.  See the documentation for 
-:class:`~yt.visualization.profile_plotter.ProfilePlot`
-for more information.
+Other options, such as the number of bins, are also configurable. See the
+documentation for :class:`~yt.visualization.profile_plotter.ProfilePlot` for
+more information.
 
 Overplotting Multiple 1D Profiles
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 It is often desirable to overplot multiple 1D profile to show evolution 
 with time.  This is supported with the ``from_profiles`` class method.  
-1D profiles are created with the :meth:`yt.data_objects.profiles.create_profile` 
+1D profiles are created with the :func:`yt.data_objects.profiles.create_profile` 
 method and then given to the ProfilePlot object.
 
 .. python-script::
 
-   from yt.mods import *
+   import yt
 
    # Create a time-series object.
-   es = simulation("enzo_tiny_cosmology/32Mpc_32.enzo", "Enzo")
+   es = yt.simulation("enzo_tiny_cosmology/32Mpc_32.enzo", "Enzo")
    es.get_time_series(redshifts=[5, 4, 3, 2, 1, 0])
 
 
@@ -540,23 +598,114 @@
    labels = []
 
    # Loop over each dataset in the time-series.
-   for pf in es:
+   for ds in es:
        # Create a data container to hold the whole dataset.
-       ad = pf.h.all_data()
+       ad = ds.all_data()
        # Create a 1d profile of density vs. temperature.
-       profiles.append(create_profile(ad, ["temperature"], 
-                                      fields=["cell_mass"],
-                                      weight_field=None,
-                                      accumulation=True))
+       profiles.append(yt.create_profile(ad, ["temperature"], 
+                                         fields=["cell_mass"],
+                                         weight_field=None,
+                                         accumulation=True))
        # Add labels
-       labels.append("z = %.2f" % pf.current_redshift)
+       labels.append("z = %.2f" % ds.current_redshift)
 
    # Create the profile plot from the list of profiles.
-   plot = ProfilePlot.from_profiles(profiles, labels=labels)
+   plot = yt.ProfilePlot.from_profiles(profiles, labels=labels)
 
    # Save the image.
    plot.save()
 
+Customizing axis limits
+~~~~~~~~~~~~~~~~~~~~~~~
+
+By default the x and y limits for ``ProfilePlot`` are determined using the
+:class:`~yt.data_objects.derived_quantities.Extrema` derived quantity.  If you
+want to create a plot with custom axis limits, you have two options.
+
+First, you can create a custom profile object using
+:func:`~yt.data_objects.profiles.create_profile`.  This function accepts a dictionary of ``(max, min)`` tuples keyed to field names.
+
+.. python-script::
+
+    import yt
+    import yt.units as u
+    ds = yt.load('IsolatedGalaxy/galaxy0030/galaxy0030')
+    sp = ds.sphere('m', 10*u.kpc)
+    profiles = yt.create_profile(sp, "temperature", "density",
+                                 weight_field=None, 
+                                 extrema={'temperature': (1e3, 1e7),
+                                          'density': (1e-26, 1e-22)})
+    plot = yt.ProfilePlot.from_profiles(profiles)
+    plot.save()
+
+You can also make use of the
+:meth:`yt.visualization.profile_plotter.ProfilePlot.set_xlim` and
+:meth:`yt.visualization.profile_plotter.ProfilePlot.set_ylim` functions to
+customize the axes limits of a plot that has already been created.  Note that
+calling ``set_xlim`` is much slower than calling ``set_ylim``.  This is because
+```set_xlim`` must recreate the profile object using the specified extrema.
+Creating a profile directly via ``create_profile`` might be significant faster.
+If you find that this operation is slow, consider creating your profile via
+``create_profile``.  Note that since there is only one bin field, ``set_xlim``
+does not accept a field name as the first argument.
+
+.. python-script::
+
+   import yt
+   import yt.units as u
+   ds = yt.load('IsolatedGalaxy/galaxy0030/galaxy0030')
+   sp = ds.sphere('m', 10*u.kpc)
+   plot = yt.ProfilePlot(sp, "temperature", "density", weight_field=None)
+   plot.set_xlim(1e3, 1e7)
+   plot.set_ylim("density", 1e-26, 1e-22)
+   plot.save()
+
+
+Customizing Units
+~~~~~~~~~~~~~~~~~
+
+Units for both the x and y axis can be controlled via the
+:meth:`~yt.visualization.profile_plotter.ProfilePlot.set_unit` method.
+Adjusting the plot units does not require recreating the histogram, so adjusting
+units will always be inexpensive, requiring only an in-place unit conversion.
+
+In the following example we create a a plot of the average density in solar
+masses per cubic parsec as a function of radius in kiloparsecs.
+
+.. python-script::
+
+    import yt
+    import yt.units as u
+    ds = yt.load('IsolatedGalaxy/galaxy0030/galaxy0030')
+    sp = ds.sphere('m', 10*u.kpc)
+    plot = yt.ProfilePlot(sp, "radius", "density", weight_field=None)
+    plot.set_unit("density", "msun/pc**3")
+    plot.set_unit("radius", "kpc")
+    plot.save()
+
+Linear and Logarithmic Scaling
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The axis scaling can be manipulated via the
+:meth:`~yt.visualization.profile_plotter.ProfilePlot.set_log` function.  This
+function accepts a field name and a boolean.  If the boolean is ``True``, the
+field is plotted in log scale.  If ``False``, the field is plotted in linear
+scale.
+
+In the following example we create a plot of the average x velocity as a
+function of radius.  Since the x component of the velocity vector can be
+negative, we set the scaling to be linear for this field.
+
+.. python-script::
+
+   import yt
+   import yt.units as u
+   ds = yt.load('IsolatedGalaxy/galaxy0030/galaxy0030')
+   sp = ds.sphere('m', 10*u.kpc)
+   plot = yt.ProfilePlot(sp, "radius", "x-velocity", weight_field=None)
+   plot.set_log("x-velocity", False)
+   plot.save()
+
 Altering Line Properties
 ~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -581,47 +730,72 @@
 2D Phase Plots
 --------------
 
-2D phase plots function in much the same was as 1D phase plots, but with a 
-:class:`~yt.visualization.profile_plotter.PhasePlot` object.  Much like 1D profiles, 
-2D profiles (phase plots) are best thought of as plotting a distribution of points, 
-either taking the average or the accumulation in a bin.  For example, to generate a 
-2D distribution of mass enclosed in density and temperature bins, you can do:
+2D phase plots function in much the same was as 1D phase plots, but with a
+:class:`~yt.visualization.profile_plotter.PhasePlot` object.  Much like 1D
+profiles, 2D profiles (phase plots) are best thought of as plotting a
+distribution of points, either taking the average or the accumulation in a bin.
+For example, to generate a 2D distribution of mass enclosed in density and
+temperature bins, you can do:
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   my_sphere = pf.sphere("c", (50, "kpc"))
-   plot = PhasePlot(my_sphere, "density", "temperature", ["cell_mass"],
-                    weight_field=None)
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   my_sphere = ds.sphere("c", (50, "kpc"))
+   plot = yt.PhasePlot(my_sphere, "density", "temperature", ["cell_mass"],
+                       weight_field=None)
    plot.save()
 
 If you would rather see the average value of a field as a function of two other
-fields, you can neglect supplying the *weight* parameter.  This would look
+fields, you can set the ``weight_field`` parameter to ``None``.  This would look
 something like:
 
 .. python-script::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   my_sphere = pf.sphere("c", (50, "kpc"))
-   plot = PhasePlot(my_sphere, "density", "temperature", ["H_fraction"],
-                    weight_field="cell_mass")
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   my_sphere = ds.sphere("c", (50, "kpc"))
+   plot = yt.PhasePlot(my_sphere, "density", "temperature", ["H_fraction"],
+                       weight_field=None)
+   plot.save()
+
+Customizing Phase Plots
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Similarly to 1D profile plots, ``PhasePlot`` can be customized via ``set_unit``,
+``set_xlim``, ``set_ylim``, and ``set_zlim``.  The following example illustrates
+how to manipulate these functions.
+
+.. python-script::
+
+   import yt
+   ds = yt.load("sizmbhloz-clref04SNth-rs9_a0.9011/sizmbhloz-clref04SNth-rs9_a0.9011.art")
+   center = ds.arr([64.0, 64.0, 64.0], 'code_length')
+   rvir = ds.quan(1e-1, "Mpccm/h")
+
+   sph = ds.sphere(center, rvir)
+   plot = yt.PhasePlot(sph, "density", "temperature", "cell_mass",
+                       weight_field=None)
+   plot.set_unit('density', 'Msun/pc**3')
+   plot.set_unit('cell_mass', 'Msun')
+   plot.set_xlim(1e-5,1e1)
+   plot.set_ylim(1,1e7)
    plot.save()
 
 Probability Distribution Functions and Accumulation
 ---------------------------------------------------
 
-Both 1D and 2D profiles which show the total of amount of some field, such as mass, 
-in a bin (done by setting the **weight_field** keyword to None) can be turned into 
-probability distribution functions (PDFs) by setting the **fractional** keyword to 
-True.  When set to True, the value in each bin is divided by the sum total from all 
-bins.  These can be turned into cumulative distribution functions (CDFs) by setting 
-the **accumulation** keyword to True.  This will make is so that the value in any bin 
-N is the cumulative sum of all bins from 0 to N.  The direction of the summation can be 
-rversed by setting **accumulation** to -True.  For PhasePlots, the accumulation can be 
-set independently for each axis by setting **accumulation** to a list of True/-True/False 
-values.
+Both 1D and 2D profiles which show the total of amount of some field, such as
+mass, in a bin (done by setting the ``weight_field`` keyword to ``None``) can be
+turned into probability distribution functions (PDFs) by setting the
+``fractional`` keyword to ``True``.  When set to ``True``, the value in each bin
+is divided by the sum total from all bins.  These can be turned into cumulative
+distribution functions (CDFs) by setting the ``accumulation`` keyword to
+``True``.  This will make is so that the value in any bin N is the cumulative
+sum of all bins from 0 to N.  The direction of the summation can be reversed by
+setting ``accumulation`` to ``-True``.  For ``PhasePlot``, the accumulation can
+be set independently for each axis by setting ``accumulation`` to a list of
+``True``/ ``-True`` /``False`` values.
 
 .. _interactive-plotting:
 
@@ -646,9 +820,9 @@
 
 .. notebook-cell::
 
-   from yt.mods import *
-   pf = load("IsolatedGalaxy/galaxy0030/galaxy0030")
-   p = ProjectionPlot(pf, "x", "density", center='m', width=(10,'kpc'),
+   import yt
+   ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030")
+   p = ProjectionPlot(ds, "x", "density", center='m', width=(10,'kpc'),
                       weight_field='density')
    p.show()
 
@@ -682,7 +856,7 @@
 .. code-block:: python
 
    >>> import yt.visualization.eps_writer as eps
-   >>> slc = SlicePlot(pf, 'z', 'density')
+   >>> slc = yt.SlicePlot(ds, 'z', 'density')
    >>> slc.set_width(25, 'kpc')
    >>> eps_fig = eps.single_plot(slc)
    >>> eps_fig.save_fig('zoom', format='eps')
@@ -706,9 +880,11 @@
 
 .. code-block:: python
 
+   >>> import yt
    >>> import yt.visualization.eps_writer as eps
-   >>> slc = SlicePlot(pf, 'z', ['density', 'temperature', 'Pressure',
-                       'VelocityMagnitude'])
+   >>>
+   >>> slc = yt.SlicePlot(ds, 'z', ['density', 'temperature', 'Pressure',
+                          'VelocityMagnitude'])
    >>> slc.set_width(25, 'kpc')
    >>> eps_fig = eps.multiplot_yt(2, 2, slc, bare_axes=True)
    >>> eps_fig.scale_line(0.2, '5 kpc')

diff -r 14dfbdf28b07dd18e112abafce364d04a4864829 -r 2d6e0253ad916f379fa19ec9521beb1932851e59 yt/utilities/amr_kdtree/amr_kdtree.py
--- a/yt/utilities/amr_kdtree/amr_kdtree.py
+++ b/yt/utilities/amr_kdtree/amr_kdtree.py
@@ -185,7 +185,7 @@
             yield self.get_brick_data(node)
 
     def slice_traverse(self, viewpoint = None):
-        if not hasattr(self.pf.h, "grid"):
+        if not hasattr(self.pf.index, "grid"):
             raise NotImplementedError
         for node in kd_traverse(self.tree.trunk, viewpoint=viewpoint):
             grid = self.pf.index.grids[node.grid - self._id_offset]

diff -r 14dfbdf28b07dd18e112abafce364d04a4864829 -r 2d6e0253ad916f379fa19ec9521beb1932851e59 yt/visualization/plot_modifications.py
--- a/yt/visualization/plot_modifications.py
+++ b/yt/visualization/plot_modifications.py
@@ -549,8 +549,12 @@
         self.plot_args = plot_args
 
     def __call__(self, plot):
+        xx0, xx1 = plot._axes.get_xlim()
+        yy0, yy1 = plot._axes.get_ylim()
         plot._axes.hold(True)
         plot._axes.plot(self.x, self.y, **self.plot_args)
+        plot._axes.set_xlim(xx0,xx1)
+        plot._axes.set_ylim(yy0,yy1)
         plot._axes.hold(False)
 
 class ImageLineCallback(LinePlotCallback):
@@ -719,7 +723,8 @@
             pos = self.pos[xi], self.pos[yi]
         else: pos = self.pos
         if isinstance(self.code_size[1], basestring):
-            code_size = plot.data.pf.quan(*self.code_size).value
+            code_size = plot.data.pf.quan(*self.code_size)
+            code_size = code_size.in_units('code_length').value
             self.code_size = (code_size, code_size)
         from matplotlib.patches import Arrow
         # Now convert the pixels to code information
@@ -813,7 +818,7 @@
 
         if iterable(self.radius):
             self.radius = plot.data.pf.quan(self.radius[0], self.radius[1])
-            self.radius = np.float64(self.radius)
+            self.radius = np.float64(self.radius.in_units(plot.xlim[0].units))
 
         radius = self.radius * self.pixel_scale(plot)[0]
 
@@ -1064,114 +1069,29 @@
     def __call__(self,plot):
         plot._axes.set_title(self.title)
 
-class FlashRayDataCallback(PlotCallback):
-    """ 
-    annotate_flash_ray_data(cmap_name='bone', sample=None)
-
-    Adds ray trace data to the plot.  *cmap_name* is the name of the color map 
-    ('bone', 'jet', 'hot', etc).  *sample* dictates the amount of down sampling 
-    to do to prevent all of the rays from being  plotted.  This may be None 
-    (plot all rays, default), an integer (step size), or a slice object.
+class TimestampCallback(PlotCallback):
     """
-    _type_name = "flash_ray_data"
-    def __init__(self, cmap_name='bone', sample=None):
-        self.cmap_name = cmap_name
-        self.sample = sample if isinstance(sample, slice) else slice(None, None, sample)
-
-    def __call__(self, plot):
-        ray_data = plot.data.pf._handle["RayData"][:]
-        idx = ray_data[:,0].argsort(kind="mergesort")
-        ray_data = ray_data[idx]
-
-        tags = ray_data[:,0]
-        coords = ray_data[:,1:3]
-        power = ray_data[:,4]
-        power /= power.max()
-        cx, cy = self.convert_to_plot(plot, coords.T)
-        coords[:,0], coords[:,1] = cx, cy
-        splitidx = np.argwhere(0 < (tags[1:] - tags[:-1])) + 1
-        coords = np.split(coords, splitidx.flat)[self.sample]
-        power = np.split(power, splitidx.flat)[self.sample]
-        cmap = matplotlib.cm.get_cmap(self.cmap_name)
-
-        plot._axes.hold(True)
-        colors = [cmap(p.max()) for p in power]
-        lc = matplotlib.collections.LineCollection(coords, colors=colors)
-        plot._axes.add_collection(lc)
-        plot._axes.hold(False)
-
-
-class TimestampCallback(PlotCallback):
-    """ 
     annotate_timestamp(x, y, units=None, format="{time:.3G} {units}", **kwargs,
                        normalized=False, bbox_dict=None)
 
-    Adds the current time to the plot at point given by *x* and *y*.  If *units* 
-    is given ('s', 'ms', 'ns', etc), it will covert the time to this basis.  If 
-    *units* is None, it will attempt to figure out the correct value by which to 
-    scale.  The *format* keyword is a template string that will be evaluated and 
-    displayed on the plot.  If *normalized* is true, *x* and *y* are interpreted 
-    as normalized plot coordinates (0,0 is lower-left and 1,1 is upper-right) 
-    otherwise *x* and *y* are assumed to be in plot coordinates. The *bbox_dict* 
-    is an optional dict of arguments for the bbox that frames the timestamp, see 
-    matplotlib's text annotation guide for more details. All other *kwargs* will 
-    be passed to the text() method on the plot axes.  See matplotlib's text() 
+    Adds the current time to the plot at point given by *x* and *y*.  If *units*
+    is given ('s', 'ms', 'ns', etc), it will covert the time to this basis.  If
+    *units* is None, it will attempt to figure out the correct value by which to
+    scale.  The *format* keyword is a template string that will be evaluated and
+    displayed on the plot.  If *normalized* is true, *x* and *y* are interpreted
+    as normalized plot coordinates (0,0 is lower-left and 1,1 is upper-right)
+    otherwise *x* and *y* are assumed to be in plot coordinates. The *bbox_dict*
+    is an optional dict of arguments for the bbox that frames the timestamp, see
+    matplotlib's text annotation guide for more details. All other *kwargs* will
+    be passed to the text() method on the plot axes.  See matplotlib's text()
     functions for more information.
     """
     _type_name = "timestamp"
-    _time_conv = {
-          'as': 1e-18,
-          'attosec': 1e-18,
-          'attosecond': 1e-18,
-          'attoseconds': 1e-18,
-          'fs': 1e-15,
-          'femtosec': 1e-15,
-          'femtosecond': 1e-15,
-          'femtoseconds': 1e-15,
-          'ps': 1e-12,
-          'picosec': 1e-12,
-          'picosecond': 1e-12,
-          'picoseconds': 1e-12,
-          'ns': 1e-9,
-          'nanosec': 1e-9,
-          'nanosecond':1e-9,
-          'nanoseconds' : 1e-9,
-          'us': 1e-6,
-          'microsec': 1e-6,
-          'microsecond': 1e-6,
-          'microseconds': 1e-6,
-          'ms': 1e-3,
-          'millisec': 1e-3,
-          'millisecond': 1e-3,
-          'milliseconds': 1e-3,
-          's': 1.0,
-          'sec': 1.0,
-          'second':1.0,
-          'seconds': 1.0,
-          'm': 60.0,
-          'min': 60.0,
-          'minute': 60.0,
-          'minutes': 60.0,
-          'h': sec_per_hr,
-          'hour': sec_per_hr,
-          'hours': sec_per_hr,
-          'd': sec_per_day,
-          'day': sec_per_day,
-          'days': sec_per_day,
-          'y': sec_per_year,
-          'year': sec_per_year,
-          'years': sec_per_year,
-          'kyr': sec_per_kyr,
-          'myr': sec_per_Myr,
-          'gyr': sec_per_Gyr,
-          'ev': 1e-9 * 7.6e-8 / 6.03,
-          'kev': 1e-12 * 7.6e-8 / 6.03,
-          'mev': 1e-15 * 7.6e-8 / 6.03,
-          }
-    _bbox_dict = {'boxstyle': 'square,pad=0.6', 'fc': 'white', 'ec': 'black', 'alpha': 1.0}
+    _bbox_dict = {'boxstyle': 'square,pad=0.6', 'fc': 'white', 'ec': 'black',
+                  'alpha': 1.0}
 
-    def __init__(self, x, y, units=None, format="{time:.3G} {units}", normalized=False, 
-                 bbox_dict=None, **kwargs):
+    def __init__(self, x, y, units=None, format="{time:.3G} {units}",
+                 normalized=False, bbox_dict=None, **kwargs):
         self.x = x
         self.y = y
         self.format = format
@@ -1186,55 +1106,30 @@
 
     def __call__(self, plot):
         if self.units is None:
-            t = plot.data.pf.current_time * plot.data.pf['Time']
-            scale_keys = ['as', 'fs', 'ps', 'ns', 'us', 'ms', 's', 
-                          'hour', 'day', 'year', 'kyr', 'myr', 'gyr']
-            self.units = 's'
-            for k in scale_keys:
-                if t < self._time_conv[k]:
+            t = plot.data.pf.current_time.in_units('s')
+            scale_keys = ['fs', 'ps', 'ns', 'us', 'ms', 's', 'hr', 'day',
+                          'yr', 'kyr', 'Myr', 'Gyr']
+            for i, k in enumerate(scale_keys):
+                if t < YTQuantity(1, k):
                     break
-                self.units = k
-        t = plot.data.pf.current_time * plot.data.pf['Time'] 
-        t /= self._time_conv[self.units.lower()]
+                t.convert_to_units(k)
+            self.units = scale_keys[i-1]
+        else:
+            t = plot.data.pf.current_time.in_units(self.units)
         if self.units == 'us':
             self.units = '$\\mu s$'
-        s = self.format.format(time=t, units=self.units)
+        s = self.format.format(time=float(t), units=self.units)
         plot._axes.hold(True)
         if self.normalized:
             plot._axes.text(self.x, self.y, s, horizontalalignment='center',
                             verticalalignment='center', 
-                            transform = plot._axes.transAxes, bbox=self.bbox_dict)
+                            transform = plot._axes.transAxes,
+                            bbox=self.bbox_dict)
         else:
-            plot._axes.text(self.x, self.y, s, bbox=self.bbox_dict, **self.kwargs)
+            plot._axes.text(self.x, self.y, s, bbox=self.bbox_dict,
+                            **self.kwargs)
         plot._axes.hold(False)
 
-
-class MaterialBoundaryCallback(ContourCallback):
-    """ 
-    annotate_material_boundary(self, field='targ', ncont=1, factor=4, 
-                               clim=(0.9, 1.0), **kwargs):
-
-    Add the limiting contours of *field* to the plot.  Nominally, *field* is 
-    the target material but may be any other field present in the index.
-    The number of contours generated is given by *ncount*, *factor* governs 
-    the number of points used in the interpolation, and *clim* gives the 
-    (upper, lower) limits for contouring.  For this to truly be the boundary
-    *clim* should be close to the edge.  For example the default is (0.9, 1.0)
-    for 'targ' which is defined on the range [0.0, 1.0].  All other *kwargs* 
-    will be passed to the contour() method on the plot axes.  See matplotlib
-    for more information.
-    """
-    _type_name = "material_boundary"
-    def __init__(self, field='targ', ncont=1, factor=4, clim=(0.9, 1.0), **kwargs):
-        plot_args = {'colors': 'w'}
-        plot_args.update(kwargs)
-        super(MaterialBoundaryCallback, self).__init__(field=field, ncont=ncont,
-                                                       factor=factor, clim=clim,
-                                                       plot_args=plot_args)
-
-    def __call__(self, plot):
-        super(MaterialBoundaryCallback, self).__call__(plot)
-
 class TriangleFacetsCallback(PlotCallback):
     """ 
     annotate_triangle_facets(triangle_vertices, plot_args=None )

This diff is so big that we needed to truncate the remainder.

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