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

commits-noreply at bitbucket.org commits-noreply at bitbucket.org
Thu Jun 15 06:36:21 PDT 2017


16 new commits in yt:

https://bitbucket.org/yt_analysis/yt/commits/8f2382a543c2/
Changeset:   8f2382a543c2
Branch:      yt
User:        jzuhone
Date:        2017-01-26 15:21:56+00:00
Summary:     Some work on making FITSImageData simpler and less noisy. Return the data of a HDU with units by wrapping it in UnitfulHDU. If we open a file or combine images, bypass most of the logic in __init__, which means that misleading log messages won’t appear.
Affected #:  1 file

diff -r 5c3af8da1dd806d6f5d76466e04feade4b1d6e5f -r 8f2382a543c274a53f639c49fd48443b9cc61752 yt/visualization/fits_image.py
--- a/yt/visualization/fits_image.py
+++ b/yt/visualization/fits_image.py
@@ -22,6 +22,15 @@
 from yt.visualization.volume_rendering.off_axis_projection import off_axis_projection
 import re
 
+class UnitfulHDU(object):
+    def __init__(self, hdu):
+        self.hdu = hdu
+        self.header = self.hdu.header
+
+    @property
+    def data(self):
+        return YTArray(self.hdu.data, self.header["BUNIT"])
+
 class FITSImageData(object):
 
     def __init__(self, data, fields=None, units=None, width=None, wcs=None):
@@ -76,6 +85,9 @@
         >>> f_deg.writeto("temp.fits")
         """
 
+        self.fields = []
+        self.field_units = {}
+
         if units is None:
             units = "cm"
         if width is None:
@@ -84,6 +96,18 @@
         exclude_fields = ['x','y','z','px','py','pz',
                           'pdx','pdy','pdz','weight_field']
 
+        if isinstance(data, _astropy.pyfits.HDUList):
+            self.hdulist = data
+            for hdu in data:
+                self.fields.append(hdu.header["btype"])
+                self.field_units[hdu.header["btype"]] = hdu.header['bunit']
+
+            self.shape = self.hdulist[0].shape
+            self.dimensionality = len(self.shape)
+            self.wcs = _astropy.pywcs.WCS(header=self.hdulist[0].header,
+                                          naxis=self.dimensionality)
+            return
+
         self.hdulist = _astropy.pyfits.HDUList()
 
         if isinstance(fields, string_types):
@@ -102,7 +126,6 @@
                 fn = fields[0]
             img_data = {fn: data}
 
-        self.fields = []
         for fd in fields:
             if isinstance(fd, tuple):
                 self.fields.append(fd[1])
@@ -110,7 +133,6 @@
                 self.fields.append(fd)
 
         first = True
-        self.field_units = {}
         for key in fields:
             if key not in exclude_fields:
                 if hasattr(img_data[key], "units"):
@@ -138,22 +160,22 @@
                 # FRBs are a special case where we have coordinate
                 # information, so we take advantage of this and
                 # construct the WCS object
-                dx = (img_data.bounds[1]-img_data.bounds[0]).in_units(units).v/self.shape[0]
-                dy = (img_data.bounds[3]-img_data.bounds[2]).in_units(units).v/self.shape[1]
-                xctr = 0.5*(img_data.bounds[1]+img_data.bounds[0]).in_units(units).v
-                yctr = 0.5*(img_data.bounds[3]+img_data.bounds[2]).in_units(units).v
+                dx = (img_data.bounds[1]-img_data.bounds[0]).to(units).v/self.shape[0]
+                dy = (img_data.bounds[3]-img_data.bounds[2]).to(units).v/self.shape[1]
+                xctr = 0.5*(img_data.bounds[1]+img_data.bounds[0]).to(units).v
+                yctr = 0.5*(img_data.bounds[3]+img_data.bounds[2]).to(units).v
                 center = [xctr, yctr]
                 cdelt = [dx,dy]
             elif isinstance(img_data, YTCoveringGrid):
-                cdelt = img_data.dds.in_units(units).v
-                center = 0.5*(img_data.left_edge+img_data.right_edge).in_units(units).v
+                cdelt = img_data.dds.to(units).v
+                center = 0.5*(img_data.left_edge+img_data.right_edge).to(units).v
             else:
                 # If img_data is just an array, we assume the center is the origin
                 # and use the image width to determine the cell widths
                 if not iterable(width):
                     width = [width]*self.dimensionality
                 if isinstance(width[0], YTQuantity):
-                    cdelt = [wh.in_units(units).v/n for wh, n in zip(width, self.shape)]
+                    cdelt = [wh.to(units).v/n for wh, n in zip(width, self.shape)]
                 else:
                     cdelt = [float(wh)/n for wh, n in zip(width, self.shape)]
                 center = [0.0]*self.dimensionality
@@ -214,13 +236,13 @@
         return key in self.fields
 
     def values(self):
-        return [self.hdulist[k] for k in self.fields]
+        return [self[k] for k in self.fields]
 
     def items(self):
-        return [(k, self.hdulist[k]) for k in self.fields]
+        return [(k, self[k]) for k in self.fields]
 
     def __getitem__(self, item):
-        return self.hdulist[item]
+        return UnitfulHDU(self.hdulist[item])
 
     def info(self):
         return self.hdulist.info()
@@ -287,7 +309,7 @@
         Return the data array of the image corresponding to *field*
         with units attached.
         """
-        return YTArray(self.hdulist[field].data, self.field_units[field])
+        return self[field].data
 
     def set_unit(self, field, units):
         """
@@ -296,7 +318,8 @@
         if field not in self.keys():
             raise KeyError("%s not an image!" % field)
         idx = self.fields.index(field)
-        new_data = YTArray(self.hdulist[idx].data, self.field_units[field]).in_units(units)
+        new_data = YTArray(self.hdulist[idx].data, 
+                           self.field_units[field]).to(units)
         self.hdulist[idx].data = new_data.v
         self.hdulist[idx].header["bunit"] = units
         self.field_units[field] = units
@@ -311,10 +334,13 @@
             raise KeyError("%s not an image!" % key)
         idx = self.fields.index(key)
         im = self.hdulist.pop(idx)
-        data = YTArray(im.data, self.field_units[key])
         self.field_units.pop(key)
         self.fields.remove(key)
-        return FITSImageData(data, fields=key, wcs=self.wcs)
+        data = _astropy.pyfits.HDUList([im])
+        return FITSImageData(data)
+
+    def close(self):
+        self.hdulist.close()
 
     @classmethod
     def from_file(cls, filename):
@@ -327,12 +353,8 @@
         filename : string
             The name of the file to open.
         """
-        f = _astropy.pyfits.open(filename)
-        data = {}
-        for hdu in f:
-            data[hdu.header["btype"]] = YTArray(hdu.data, hdu.header["bunit"])
-        f.close()
-        return cls(data, wcs=_astropy.pywcs.WCS(header=hdu.header))
+        f = _astropy.pyfits.open(filename, lazy_load_hdus=False)
+        return cls(f)
 
     @classmethod
     def from_images(cls, image_list):
@@ -347,14 +369,14 @@
         """
         w = image_list[0].wcs
         img_shape = image_list[0].shape
-        data = {}
-        for image in image_list:
-            assert_same_wcs(w, image.wcs)
-            if img_shape != image.shape:
+        data = []
+        for fid in image_list:
+            assert_same_wcs(w, fid.wcs)
+            if img_shape != fid.shape:
                 raise RuntimeError("Images do not have the same shape!")
-            for key in image.keys():
-                data[key] = image.get_data(key)
-        return cls(data, wcs=w)
+            data += fid.hdulist
+        data = _astropy.pyfits.HDUList(data)
+        return cls(data)
 
     def create_sky_wcs(self, sky_center, sky_scale,
                        ctype=["RA---TAN","DEC--TAN"],


https://bitbucket.org/yt_analysis/yt/commits/df7e1db1e3e5/
Changeset:   df7e1db1e3e5
Branch:      yt
User:        jzuhone
Date:        2017-01-26 16:06:04+00:00
Summary:     Making __repr__ and info fancier
Affected #:  1 file

diff -r 8f2382a543c274a53f639c49fd48443b9cc61752 -r df7e1db1e3e577e45e6c7161d852bdd6a5f54e36 yt/visualization/fits_image.py
--- a/yt/visualization/fits_image.py
+++ b/yt/visualization/fits_image.py
@@ -26,10 +26,16 @@
     def __init__(self, hdu):
         self.hdu = hdu
         self.header = self.hdu.header
+        self.name = self.header["BTYPE"]
+        self.units = self.header["BUNIT"]
+        self.shape = self.hdu.shape
 
     @property
     def data(self):
-        return YTArray(self.hdu.data, self.header["BUNIT"])
+        return YTArray(self.hdu.data, self.units)
+
+    def __repr__(self):
+        return "FITSImage: %s (%d x %d, %s)" % (self.name, *self.shape, self.units)
 
 class FITSImageData(object):
 
@@ -244,8 +250,17 @@
     def __getitem__(self, item):
         return UnitfulHDU(self.hdulist[item])
 
+    def __repr__(self):
+        return str([self[k] for k in self.keys()])
+
     def info(self):
-        return self.hdulist.info()
+        hinfo = self.hdulist.info(output=False)
+        format = '{:3d}  {:10}  {:11}  {:5d}   {}   {}   {}'
+        results = []
+        for line in hinfo:
+            units = self.field_units[self.hdulist[line[0]].header['btype']]
+            results.append(format.format(*line[:-1], units)) 
+        print('\n'.join(results)+'\n')
 
     @parallel_root_only
     def writeto(self, fileobj, fields=None, clobber=False, **kwargs):


https://bitbucket.org/yt_analysis/yt/commits/ee36b23acc56/
Changeset:   ee36b23acc56
Branch:      yt
User:        jzuhone
Date:        2017-01-26 16:19:32+00:00
Summary:     Make sure all of the WCS get copied over
Affected #:  1 file

diff -r df7e1db1e3e577e45e6c7161d852bdd6a5f54e36 -r ee36b23acc5698399f748c951cbad9cd41fd1e77 yt/visualization/fits_image.py
--- a/yt/visualization/fits_image.py
+++ b/yt/visualization/fits_image.py
@@ -110,8 +110,17 @@
 
             self.shape = self.hdulist[0].shape
             self.dimensionality = len(self.shape)
-            self.wcs = _astropy.pywcs.WCS(header=self.hdulist[0].header,
-                                          naxis=self.dimensionality)
+            wcs_names = [key for key in self.hdulist[0].header 
+                         if "WCSNAME" in key]
+            for name in wcs_names:
+                if name == "WCSNAME":
+                    key = ' '
+                else:
+                    key = name[-1]
+                w = _astropy.pywcs.WCS(header=self.hdulist[0].header,
+                                       key=key, naxis=self.dimensionality)
+                setattr(self, "wcs"+key.strip().lower(), w)
+
             return
 
         self.hdulist = _astropy.pyfits.HDUList()


https://bitbucket.org/yt_analysis/yt/commits/592c5830665c/
Changeset:   592c5830665c
Branch:      yt
User:        jzuhone
Date:        2017-01-26 16:36:02+00:00
Summary:     Tidying up this file
Affected #:  1 file

diff -r ee36b23acc5698399f748c951cbad9cd41fd1e77 -r 592c5830665c22323b0a248ed7e7c1abf2e3b8ed yt/visualization/fits_image.py
--- a/yt/visualization/fits_image.py
+++ b/yt/visualization/fits_image.py
@@ -134,7 +134,8 @@
                 fields = list(img_data.keys())
         elif isinstance(data, np.ndarray):
             if fields is None:
-                mylog.warning("No field name given for this array. Calling it 'image_data'.")
+                mylog.warning("No field name given for this array. "
+                              "Calling it 'image_data'.")
                 fn = 'image_data'
                 fields = [fn]
             else:
@@ -151,7 +152,7 @@
         for key in fields:
             if key not in exclude_fields:
                 if hasattr(img_data[key], "units"):
-                    self.field_units[key] = img_data[key].units
+                    self.field_units[key] = str(img_data[key].units)
                 else:
                     self.field_units[key] = "dimensionless"
                 mylog.info("Making a FITS image of field %s" % key)
@@ -162,31 +163,33 @@
                     hdu = _astropy.pyfits.ImageHDU(np.array(img_data[key]))
                 hdu.name = key
                 hdu.header["btype"] = key
-                if hasattr(img_data[key], "units"):
-                    hdu.header["bunit"] = re.sub('()', '', str(img_data[key].units))
+                hdu.header["bunit"] = re.sub('()', '', self.field_units[key])
                 self.hdulist.append(hdu)
 
         self.shape = self.hdulist[0].shape
         self.dimensionality = len(self.shape)
 
         if wcs is None:
-            w = _astropy.pywcs.WCS(header=self.hdulist[0].header, naxis=self.dimensionality)
+            w = _astropy.pywcs.WCS(header=self.hdulist[0].header,
+                                   naxis=self.dimensionality)
             if isinstance(img_data, FixedResolutionBuffer):
                 # FRBs are a special case where we have coordinate
                 # information, so we take advantage of this and
                 # construct the WCS object
-                dx = (img_data.bounds[1]-img_data.bounds[0]).to(units).v/self.shape[0]
-                dy = (img_data.bounds[3]-img_data.bounds[2]).to(units).v/self.shape[1]
+                dx = (img_data.bounds[1]-img_data.bounds[0]).to(units).v
+                dy = (img_data.bounds[3]-img_data.bounds[2]).to(units).v
+                dx /= self.shape[0]
+                dy /= self.shape[1]
                 xctr = 0.5*(img_data.bounds[1]+img_data.bounds[0]).to(units).v
                 yctr = 0.5*(img_data.bounds[3]+img_data.bounds[2]).to(units).v
                 center = [xctr, yctr]
-                cdelt = [dx,dy]
+                cdelt = [dx, dy]
             elif isinstance(img_data, YTCoveringGrid):
                 cdelt = img_data.dds.to(units).v
                 center = 0.5*(img_data.left_edge+img_data.right_edge).to(units).v
             else:
-                # If img_data is just an array, we assume the center is the origin
-                # and use the image width to determine the cell widths
+                # If img_data is just an array, we assume the center is the 
+                # origin and use the image width to determine the cell widths
                 if not iterable(width):
                     width = [width]*self.dimensionality
                 if isinstance(width[0], YTQuantity):
@@ -240,7 +243,7 @@
             self.hdulist[idx].header[key] = value
 
     def update_all_headers(self, key, value):
-        mylog.warning("update_all_headers is deprecated. "+
+        mylog.warning("update_all_headers is deprecated. "
                       "Use update_header('all', key, value) instead.")
         self.update_header("all", key, value)
 
@@ -322,8 +325,8 @@
     def to_aplpy(self, **kwargs):
         """
         Use APLpy (http://aplpy.github.io) for plotting. Returns an
-        `aplpy.FITSFigure` instance. All keyword arguments are passed to the
-        `aplpy.FITSFigure` constructor.
+        `aplpy.FITSFigure` instance. All keyword arguments are passed 
+        to the `aplpy.FITSFigure` constructor.
         """
         import aplpy
         return aplpy.FITSFigure(self.hdulist, **kwargs)
@@ -440,7 +443,8 @@
         else:
             scaleq = YTQuantity(sky_scale[0],sky_scale[1])
         if scaleq.units.dimensions != dimensions.angle/dimensions.length:
-            raise RuntimeError("sky_scale %s not in correct dimensions of angle/length!" % sky_scale)
+            raise RuntimeError("sky_scale %s not in correct " % sky_scale +
+                               "dimensions of angle/length!")
         deltas = old_wcs.wcs.cdelt
         units = [str(unit) for unit in old_wcs.wcs.cunit]
         new_dx = (YTQuantity(-deltas[0], units[0])*scaleq).in_units("deg")
@@ -530,7 +534,8 @@
         if iterable(axis):
             frb = data_source.to_frb(width[0], (nx, ny), height=width[1])
         else:
-            frb = data_source.to_frb(width[0], (nx, ny), center=center, height=width[1])
+            frb = data_source.to_frb(width[0], (nx, ny), center=center,
+                                     height=width[1])
     else:
         frb = None
     w = _astropy.pywcs.WCS(naxis=2)
@@ -583,14 +588,14 @@
         The fields to slice
     center : A sequence of floats, a string, or a tuple.
          The coordinate of the center of the image. If set to 'c', 'center' or
-         left blank, the plot is centered on the middle of the domain. If set to
-         'max' or 'm', the center will be located at the maximum of the
+         left blank, the plot is centered on the middle of the domain. If set 
+         to 'max' or 'm', the center will be located at the maximum of the
          ('gas', 'density') field. Centering on the max or min of a specific
-         field is supported by providing a tuple such as ("min","temperature") or
-         ("max","dark_matter_density"). Units can be specified by passing in *center*
-         as a tuple containing a coordinate and string unit name or by passing
-         in a YTArray. If a list or unitless array is supplied, code units are
-         assumed.
+         field is supported by providing a tuple such as ("min","temperature")
+         or ("max","dark_matter_density"). Units can be specified by passing in
+         *center* as a tuple containing a coordinate and string unit name or by
+         passing in a YTArray. If a list or unitless array is supplied, code 
+         units are assumed.
     width : tuple or a float.
          Width can have four different formats to support windows with variable
          x and y widths.  They are:
@@ -612,15 +617,17 @@
          x width of 0.2 and a y width of 0.3 in code units.  If units are
          provided the resulting plot axis labels will use the supplied units.
     image_res : an int or 2-tuple of ints
-        Specify the resolution of the resulting image. If not provided, it will be
-        determined based on the minimum cell size of the dataset.
+        Specify the resolution of the resulting image. If not provided, it will
+        be determined based on the minimum cell size of the dataset.
     """
-    def __init__(self, ds, axis, fields, center="c", width=None, image_res=None, **kwargs):
+    def __init__(self, ds, axis, fields, center="c", width=None, 
+                 image_res=None, **kwargs):
         fields = ensure_list(fields)
         axis = fix_axis(axis, ds)
         center, dcenter = ds.coordinates.sanitize_center(center, axis)
         slc = ds.slice(axis, center[axis], **kwargs)
-        w, frb = construct_image(ds, axis, slc, dcenter, width=width, image_res=image_res)
+        w, frb = construct_image(ds, axis, slc, dcenter, width=width, 
+                                 image_res=image_res)
         super(FITSSlice, self).__init__(frb, fields=fields, wcs=w)
 
 
@@ -640,14 +647,14 @@
         The field used to weight the projection.
     center : A sequence of floats, a string, or a tuple.
          The coordinate of the center of the image. If set to 'c', 'center' or
-         left blank, the plot is centered on the middle of the domain. If set to
-         'max' or 'm', the center will be located at the maximum of the
+         left blank, the plot is centered on the middle of the domain. If set 
+         to 'max' or 'm', the center will be located at the maximum of the
          ('gas', 'density') field. Centering on the max or min of a specific
-         field is supported by providing a tuple such as ("min","temperature") or
-         ("max","dark_matter_density"). Units can be specified by passing in *center*
-         as a tuple containing a coordinate and string unit name or by passing
-         in a YTArray. If a list or unitless array is supplied, code units are
-         assumed.
+         field is supported by providing a tuple such as ("min","temperature") 
+         or ("max","dark_matter_density"). Units can be specified by passing in
+         *center* as a tuple containing a coordinate and string unit name or by
+         passing in a YTArray. If a list or unitless array is supplied, code 
+         units are assumed.
     width : tuple or a float.
          Width can have four different formats to support windows with variable
          x and y widths.  They are:
@@ -669,8 +676,8 @@
          x width of 0.2 and a y width of 0.3 in code units.  If units are
          provided the resulting plot axis labels will use the supplied units.
     image_res : an int or 2-tuple of ints
-        Specify the resolution of the resulting image. If not provided, it will be
-        determined based on the minimum cell size of the dataset.
+        Specify the resolution of the resulting image. If not provided, it will
+        be determined based on the minimum cell size of the dataset.
     """
     def __init__(self, ds, axis, fields, center="c", width=None,
                  weight_field=None, image_res=None, **kwargs):
@@ -678,7 +685,8 @@
         axis = fix_axis(axis, ds)
         center, dcenter = ds.coordinates.sanitize_center(center, axis)
         prj = ds.proj(fields[0], axis, weight_field=weight_field, **kwargs)
-        w, frb = construct_image(ds, axis, prj, dcenter, width=width, image_res=image_res)
+        w, frb = construct_image(ds, axis, prj, dcenter, width=width, 
+                                 image_res=image_res)
         super(FITSProjection, self).__init__(frb, fields=fields, wcs=w)
 
 class FITSOffAxisSlice(FITSImageData):
@@ -698,11 +706,11 @@
         left blank, the plot is centered on the middle of the domain. If set to
         'max' or 'm', the center will be located at the maximum of the
         ('gas', 'density') field. Centering on the max or min of a specific
-        field is supported by providing a tuple such as ("min","temperature") or
-        ("max","dark_matter_density"). Units can be specified by passing in *center*
-        as a tuple containing a coordinate and string unit name or by passing
-        in a YTArray. If a list or unitless array is supplied, code units are
-        assumed.
+        field is supported by providing a tuple such as ("min","temperature") 
+        or ("max","dark_matter_density"). Units can be specified by passing in 
+        *center* as a tuple containing a coordinate and string unit name or by 
+        passing in a YTArray. If a list or unitless array is supplied, code 
+        units are assumed.
     width : tuple or a float.
         Width can have four different formats to support windows with variable
         x and y widths.  They are:
@@ -730,13 +738,14 @@
         option sets the orientation of the slicing plane.  If not
         set, an arbitrary grid-aligned north-vector is chosen.
     """
-    def __init__(self, ds, normal, fields, center='c', width=None, image_res=512,
-                 north_vector=None):
+    def __init__(self, ds, normal, fields, center='c', width=None,
+                 image_res=512, north_vector=None):
         fields = ensure_list(fields)
         center, dcenter = ds.coordinates.sanitize_center(center, 4)
         cut = ds.cutting(normal, center, north_vector=north_vector)
         center = ds.arr([0.0] * 2, 'code_length')
-        w, frb = construct_image(ds, normal, cut, center, width=width, image_res=image_res)
+        w, frb = construct_image(ds, normal, cut, center, width=width,
+                                 image_res=image_res)
         super(FITSOffAxisSlice, self).__init__(frb, fields=fields, wcs=w)
 
 
@@ -755,14 +764,14 @@
         The name of the field(s) to be plotted.
     center : A sequence of floats, a string, or a tuple.
          The coordinate of the center of the image. If set to 'c', 'center' or
-         left blank, the plot is centered on the middle of the domain. If set to
-         'max' or 'm', the center will be located at the maximum of the
+         left blank, the plot is centered on the middle of the domain. If set 
+         to 'max' or 'm', the center will be located at the maximum of the
          ('gas', 'density') field. Centering on the max or min of a specific
-         field is supported by providing a tuple such as ("min","temperature") or
-         ("max","dark_matter_density"). Units can be specified by passing in *center*
-         as a tuple containing a coordinate and string unit name or by passing
-         in a YTArray. If a list or unitless array is supplied, code units are
-         assumed.
+         field is supported by providing a tuple such as ("min","temperature") 
+         or ("max","dark_matter_density"). Units can be specified by passing in
+         *center* as a tuple containing a coordinate and string unit name or by
+         passing in a YTArray. If a list or unitless array is supplied, code 
+         units are assumed.
     width : tuple or a float.
          Width can have four different formats to support windows with variable
          x and y widths.  They are:
@@ -813,11 +822,13 @@
         This should only be used for uniform resolution grid datasets, as other
         datasets may result in unphysical images.
     data_source : yt.data_objects.data_containers.YTSelectionContainer, optional
-        If specified, this will be the data source used for selecting regions to project.
+        If specified, this will be the data source used for selecting regions 
+        to project.
     """
     def __init__(self, ds, normal, fields, center='c', width=(1.0, 'unitary'),
-                 weight_field=None, image_res=512, depth_res=256, data_source=None,
-                 north_vector=None, depth=(1.0,"unitary"), no_ghost=False, method='integrate'):
+                 weight_field=None, image_res=512, depth_res=256, 
+                 data_source=None, north_vector=None, depth=(1.0,"unitary"), 
+                 no_ghost=False, method='integrate'):
         fields = ensure_list(fields)
         center, dcenter = ds.coordinates.sanitize_center(center, 4)
         buf = {}
@@ -831,9 +842,11 @@
         else:
             source = data_source
         for field in fields:
-            buf[field] = off_axis_projection(source, center, normal, wd, res, field,
-                                             no_ghost=no_ghost, north_vector=north_vector,
-                                             method=method, weight=weight_field).swapaxes(0, 1)
+            buf[field] = off_axis_projection(source, center, normal, wd,
+                                             res, field, no_ghost=no_ghost, 
+                                             north_vector=north_vector, 
+                                             method=method, 
+                                             weight=weight_field).swapaxes(0,1)
         center = ds.arr([0.0] * 2, 'code_length')
         w, not_an_frb = construct_image(ds, normal, buf, center, width=width, image_res=image_res)
         super(FITSOffAxisProjection, self).__init__(buf, fields=fields, wcs=w)


https://bitbucket.org/yt_analysis/yt/commits/743fb233d5a8/
Changeset:   743fb233d5a8
Branch:      yt
User:        jzuhone
Date:        2017-02-09 14:51:09+00:00
Summary:     Merge
Affected #:  1 file

diff -r 441ff5e2dcd342526152309d260e912300fdcd3b -r 743fb233d5a830758d29aceb739cc87e34a7e5b1 yt/visualization/fits_image.py
--- a/yt/visualization/fits_image.py
+++ b/yt/visualization/fits_image.py
@@ -22,6 +22,21 @@
 from yt.visualization.volume_rendering.off_axis_projection import off_axis_projection
 import re
 
+class UnitfulHDU(object):
+    def __init__(self, hdu):
+        self.hdu = hdu
+        self.header = self.hdu.header
+        self.name = self.header["BTYPE"]
+        self.units = self.header["BUNIT"]
+        self.shape = self.hdu.shape
+
+    @property
+    def data(self):
+        return YTArray(self.hdu.data, self.units)
+
+    def __repr__(self):
+        return "FITSImage: %s (%d x %d, %s)" % (self.name, *self.shape, self.units)
+
 class FITSImageData(object):
 
     def __init__(self, data, fields=None, units=None, width=None, wcs=None):
@@ -76,6 +91,9 @@
         >>> f_deg.writeto("temp.fits")
         """
 
+        self.fields = []
+        self.field_units = {}
+
         if units is None:
             units = "cm"
         if width is None:
@@ -84,6 +102,27 @@
         exclude_fields = ['x','y','z','px','py','pz',
                           'pdx','pdy','pdz','weight_field']
 
+        if isinstance(data, _astropy.pyfits.HDUList):
+            self.hdulist = data
+            for hdu in data:
+                self.fields.append(hdu.header["btype"])
+                self.field_units[hdu.header["btype"]] = hdu.header['bunit']
+
+            self.shape = self.hdulist[0].shape
+            self.dimensionality = len(self.shape)
+            wcs_names = [key for key in self.hdulist[0].header 
+                         if "WCSNAME" in key]
+            for name in wcs_names:
+                if name == "WCSNAME":
+                    key = ' '
+                else:
+                    key = name[-1]
+                w = _astropy.pywcs.WCS(header=self.hdulist[0].header,
+                                       key=key, naxis=self.dimensionality)
+                setattr(self, "wcs"+key.strip().lower(), w)
+
+            return
+
         self.hdulist = _astropy.pyfits.HDUList()
 
         if isinstance(fields, string_types):
@@ -95,14 +134,14 @@
                 fields = list(img_data.keys())
         elif isinstance(data, np.ndarray):
             if fields is None:
-                mylog.warning("No field name given for this array. Calling it 'image_data'.")
+                mylog.warning("No field name given for this array. "
+                              "Calling it 'image_data'.")
                 fn = 'image_data'
                 fields = [fn]
             else:
                 fn = fields[0]
             img_data = {fn: data}
 
-        self.fields = []
         for fd in fields:
             if isinstance(fd, tuple):
                 self.fields.append(fd[1])
@@ -110,11 +149,10 @@
                 self.fields.append(fd)
 
         first = True
-        self.field_units = {}
         for key in fields:
             if key not in exclude_fields:
                 if hasattr(img_data[key], "units"):
-                    self.field_units[key] = img_data[key].units
+                    self.field_units[key] = str(img_data[key].units)
                 else:
                     self.field_units[key] = "dimensionless"
                 mylog.info("Making a FITS image of field %s" % key)
@@ -125,35 +163,37 @@
                     hdu = _astropy.pyfits.ImageHDU(np.array(img_data[key]))
                 hdu.name = key
                 hdu.header["btype"] = key
-                if hasattr(img_data[key], "units"):
-                    hdu.header["bunit"] = re.sub('()', '', str(img_data[key].units))
+                hdu.header["bunit"] = re.sub('()', '', self.field_units[key])
                 self.hdulist.append(hdu)
 
         self.shape = self.hdulist[0].shape
         self.dimensionality = len(self.shape)
 
         if wcs is None:
-            w = _astropy.pywcs.WCS(header=self.hdulist[0].header, naxis=self.dimensionality)
+            w = _astropy.pywcs.WCS(header=self.hdulist[0].header,
+                                   naxis=self.dimensionality)
             if isinstance(img_data, FixedResolutionBuffer):
                 # FRBs are a special case where we have coordinate
                 # information, so we take advantage of this and
                 # construct the WCS object
-                dx = (img_data.bounds[1]-img_data.bounds[0]).in_units(units).v/self.shape[0]
-                dy = (img_data.bounds[3]-img_data.bounds[2]).in_units(units).v/self.shape[1]
-                xctr = 0.5*(img_data.bounds[1]+img_data.bounds[0]).in_units(units).v
-                yctr = 0.5*(img_data.bounds[3]+img_data.bounds[2]).in_units(units).v
+                dx = (img_data.bounds[1]-img_data.bounds[0]).to(units).v
+                dy = (img_data.bounds[3]-img_data.bounds[2]).to(units).v
+                dx /= self.shape[0]
+                dy /= self.shape[1]
+                xctr = 0.5*(img_data.bounds[1]+img_data.bounds[0]).to(units).v
+                yctr = 0.5*(img_data.bounds[3]+img_data.bounds[2]).to(units).v
                 center = [xctr, yctr]
-                cdelt = [dx,dy]
+                cdelt = [dx, dy]
             elif isinstance(img_data, YTCoveringGrid):
-                cdelt = img_data.dds.in_units(units).v
-                center = 0.5*(img_data.left_edge+img_data.right_edge).in_units(units).v
+                cdelt = img_data.dds.to(units).v
+                center = 0.5*(img_data.left_edge+img_data.right_edge).to(units).v
             else:
-                # If img_data is just an array, we assume the center is the origin
-                # and use the image width to determine the cell widths
+                # If img_data is just an array, we assume the center is the 
+                # origin and use the image width to determine the cell widths
                 if not iterable(width):
                     width = [width]*self.dimensionality
                 if isinstance(width[0], YTQuantity):
-                    cdelt = [wh.in_units(units).v/n for wh, n in zip(width, self.shape)]
+                    cdelt = [wh.to(units).v/n for wh, n in zip(width, self.shape)]
                 else:
                     cdelt = [float(wh)/n for wh, n in zip(width, self.shape)]
                 center = [0.0]*self.dimensionality
@@ -203,7 +243,7 @@
             self.hdulist[idx].header[key] = value
 
     def update_all_headers(self, key, value):
-        mylog.warning("update_all_headers is deprecated. "+
+        mylog.warning("update_all_headers is deprecated. "
                       "Use update_header('all', key, value) instead.")
         self.update_header("all", key, value)
 
@@ -214,16 +254,25 @@
         return key in self.fields
 
     def values(self):
-        return [self.hdulist[k] for k in self.fields]
+        return [self[k] for k in self.fields]
 
     def items(self):
-        return [(k, self.hdulist[k]) for k in self.fields]
+        return [(k, self[k]) for k in self.fields]
 
     def __getitem__(self, item):
-        return self.hdulist[item]
+        return UnitfulHDU(self.hdulist[item])
+
+    def __repr__(self):
+        return str([self[k] for k in self.keys()])
 
     def info(self):
-        return self.hdulist.info()
+        hinfo = self.hdulist.info(output=False)
+        format = '{:3d}  {:10}  {:11}  {:5d}   {}   {}   {}'
+        results = []
+        for line in hinfo:
+            units = self.field_units[self.hdulist[line[0]].header['btype']]
+            results.append(format.format(*line[:-1], units)) 
+        print('\n'.join(results)+'\n')
 
     @parallel_root_only
     def writeto(self, fileobj, fields=None, clobber=False, **kwargs):
@@ -276,8 +325,8 @@
     def to_aplpy(self, **kwargs):
         """
         Use APLpy (http://aplpy.github.io) for plotting. Returns an
-        `aplpy.FITSFigure` instance. All keyword arguments are passed to the
-        `aplpy.FITSFigure` constructor.
+        `aplpy.FITSFigure` instance. All keyword arguments are passed 
+        to the `aplpy.FITSFigure` constructor.
         """
         import aplpy
         return aplpy.FITSFigure(self.hdulist, **kwargs)
@@ -287,7 +336,7 @@
         Return the data array of the image corresponding to *field*
         with units attached.
         """
-        return YTArray(self.hdulist[field].data, self.field_units[field])
+        return self[field].data
 
     def set_unit(self, field, units):
         """
@@ -296,7 +345,8 @@
         if field not in self.keys():
             raise KeyError("%s not an image!" % field)
         idx = self.fields.index(field)
-        new_data = YTArray(self.hdulist[idx].data, self.field_units[field]).in_units(units)
+        new_data = YTArray(self.hdulist[idx].data, 
+                           self.field_units[field]).to(units)
         self.hdulist[idx].data = new_data.v
         self.hdulist[idx].header["bunit"] = units
         self.field_units[field] = units
@@ -311,10 +361,13 @@
             raise KeyError("%s not an image!" % key)
         idx = self.fields.index(key)
         im = self.hdulist.pop(idx)
-        data = YTArray(im.data, self.field_units[key])
         self.field_units.pop(key)
         self.fields.remove(key)
-        return FITSImageData(data, fields=key, wcs=self.wcs)
+        data = _astropy.pyfits.HDUList([im])
+        return FITSImageData(data)
+
+    def close(self):
+        self.hdulist.close()
 
     @classmethod
     def from_file(cls, filename):
@@ -327,12 +380,8 @@
         filename : string
             The name of the file to open.
         """
-        f = _astropy.pyfits.open(filename)
-        data = {}
-        for hdu in f:
-            data[hdu.header["btype"]] = YTArray(hdu.data, hdu.header["bunit"])
-        f.close()
-        return cls(data, wcs=_astropy.pywcs.WCS(header=hdu.header))
+        f = _astropy.pyfits.open(filename, lazy_load_hdus=False)
+        return cls(f)
 
     @classmethod
     def from_images(cls, image_list):
@@ -347,14 +396,14 @@
         """
         w = image_list[0].wcs
         img_shape = image_list[0].shape
-        data = {}
-        for image in image_list:
-            assert_same_wcs(w, image.wcs)
-            if img_shape != image.shape:
+        data = []
+        for fid in image_list:
+            assert_same_wcs(w, fid.wcs)
+            if img_shape != fid.shape:
                 raise RuntimeError("Images do not have the same shape!")
-            for key in image.keys():
-                data[key] = image.get_data(key)
-        return cls(data, wcs=w)
+            data += fid.hdulist
+        data = _astropy.pyfits.HDUList(data)
+        return cls(data)
 
     def create_sky_wcs(self, sky_center, sky_scale,
                        ctype=["RA---TAN","DEC--TAN"],
@@ -394,7 +443,8 @@
         else:
             scaleq = YTQuantity(sky_scale[0],sky_scale[1])
         if scaleq.units.dimensions != dimensions.angle/dimensions.length:
-            raise RuntimeError("sky_scale %s not in correct dimensions of angle/length!" % sky_scale)
+            raise RuntimeError("sky_scale %s not in correct " % sky_scale +
+                               "dimensions of angle/length!")
         deltas = old_wcs.wcs.cdelt
         units = [str(unit) for unit in old_wcs.wcs.cunit]
         new_dx = (YTQuantity(-deltas[0], units[0])*scaleq).in_units("deg")
@@ -484,7 +534,8 @@
         if iterable(axis):
             frb = data_source.to_frb(width[0], (nx, ny), height=width[1])
         else:
-            frb = data_source.to_frb(width[0], (nx, ny), center=center, height=width[1])
+            frb = data_source.to_frb(width[0], (nx, ny), center=center,
+                                     height=width[1])
     else:
         frb = None
     w = _astropy.pywcs.WCS(naxis=2)
@@ -537,14 +588,14 @@
         The fields to slice
     center : A sequence of floats, a string, or a tuple.
          The coordinate of the center of the image. If set to 'c', 'center' or
-         left blank, the plot is centered on the middle of the domain. If set to
-         'max' or 'm', the center will be located at the maximum of the
+         left blank, the plot is centered on the middle of the domain. If set 
+         to 'max' or 'm', the center will be located at the maximum of the
          ('gas', 'density') field. Centering on the max or min of a specific
-         field is supported by providing a tuple such as ("min","temperature") or
-         ("max","dark_matter_density"). Units can be specified by passing in *center*
-         as a tuple containing a coordinate and string unit name or by passing
-         in a YTArray. If a list or unitless array is supplied, code units are
-         assumed.
+         field is supported by providing a tuple such as ("min","temperature")
+         or ("max","dark_matter_density"). Units can be specified by passing in
+         *center* as a tuple containing a coordinate and string unit name or by
+         passing in a YTArray. If a list or unitless array is supplied, code 
+         units are assumed.
     width : tuple or a float.
          Width can have four different formats to support windows with variable
          x and y widths.  They are:
@@ -566,15 +617,17 @@
          x width of 0.2 and a y width of 0.3 in code units.  If units are
          provided the resulting plot axis labels will use the supplied units.
     image_res : an int or 2-tuple of ints
-        Specify the resolution of the resulting image. If not provided, it will be
-        determined based on the minimum cell size of the dataset.
+        Specify the resolution of the resulting image. If not provided, it will
+        be determined based on the minimum cell size of the dataset.
     """
-    def __init__(self, ds, axis, fields, center="c", width=None, image_res=None, **kwargs):
+    def __init__(self, ds, axis, fields, center="c", width=None, 
+                 image_res=None, **kwargs):
         fields = ensure_list(fields)
         axis = fix_axis(axis, ds)
         center, dcenter = ds.coordinates.sanitize_center(center, axis)
         slc = ds.slice(axis, center[axis], **kwargs)
-        w, frb = construct_image(ds, axis, slc, dcenter, width=width, image_res=image_res)
+        w, frb = construct_image(ds, axis, slc, dcenter, width=width, 
+                                 image_res=image_res)
         super(FITSSlice, self).__init__(frb, fields=fields, wcs=w)
 
 
@@ -594,14 +647,14 @@
         The field used to weight the projection.
     center : A sequence of floats, a string, or a tuple.
          The coordinate of the center of the image. If set to 'c', 'center' or
-         left blank, the plot is centered on the middle of the domain. If set to
-         'max' or 'm', the center will be located at the maximum of the
+         left blank, the plot is centered on the middle of the domain. If set 
+         to 'max' or 'm', the center will be located at the maximum of the
          ('gas', 'density') field. Centering on the max or min of a specific
-         field is supported by providing a tuple such as ("min","temperature") or
-         ("max","dark_matter_density"). Units can be specified by passing in *center*
-         as a tuple containing a coordinate and string unit name or by passing
-         in a YTArray. If a list or unitless array is supplied, code units are
-         assumed.
+         field is supported by providing a tuple such as ("min","temperature") 
+         or ("max","dark_matter_density"). Units can be specified by passing in
+         *center* as a tuple containing a coordinate and string unit name or by
+         passing in a YTArray. If a list or unitless array is supplied, code 
+         units are assumed.
     width : tuple or a float.
          Width can have four different formats to support windows with variable
          x and y widths.  They are:
@@ -623,8 +676,8 @@
          x width of 0.2 and a y width of 0.3 in code units.  If units are
          provided the resulting plot axis labels will use the supplied units.
     image_res : an int or 2-tuple of ints
-        Specify the resolution of the resulting image. If not provided, it will be
-        determined based on the minimum cell size of the dataset.
+        Specify the resolution of the resulting image. If not provided, it will
+        be determined based on the minimum cell size of the dataset.
     """
     def __init__(self, ds, axis, fields, center="c", width=None,
                  weight_field=None, image_res=None, **kwargs):
@@ -632,7 +685,8 @@
         axis = fix_axis(axis, ds)
         center, dcenter = ds.coordinates.sanitize_center(center, axis)
         prj = ds.proj(fields[0], axis, weight_field=weight_field, **kwargs)
-        w, frb = construct_image(ds, axis, prj, dcenter, width=width, image_res=image_res)
+        w, frb = construct_image(ds, axis, prj, dcenter, width=width, 
+                                 image_res=image_res)
         super(FITSProjection, self).__init__(frb, fields=fields, wcs=w)
 
 class FITSOffAxisSlice(FITSImageData):
@@ -652,11 +706,11 @@
         left blank, the plot is centered on the middle of the domain. If set to
         'max' or 'm', the center will be located at the maximum of the
         ('gas', 'density') field. Centering on the max or min of a specific
-        field is supported by providing a tuple such as ("min","temperature") or
-        ("max","dark_matter_density"). Units can be specified by passing in *center*
-        as a tuple containing a coordinate and string unit name or by passing
-        in a YTArray. If a list or unitless array is supplied, code units are
-        assumed.
+        field is supported by providing a tuple such as ("min","temperature") 
+        or ("max","dark_matter_density"). Units can be specified by passing in 
+        *center* as a tuple containing a coordinate and string unit name or by 
+        passing in a YTArray. If a list or unitless array is supplied, code 
+        units are assumed.
     width : tuple or a float.
         Width can have four different formats to support windows with variable
         x and y widths.  They are:
@@ -684,13 +738,14 @@
         option sets the orientation of the slicing plane.  If not
         set, an arbitrary grid-aligned north-vector is chosen.
     """
-    def __init__(self, ds, normal, fields, center='c', width=None, image_res=512,
-                 north_vector=None):
+    def __init__(self, ds, normal, fields, center='c', width=None,
+                 image_res=512, north_vector=None):
         fields = ensure_list(fields)
         center, dcenter = ds.coordinates.sanitize_center(center, 4)
         cut = ds.cutting(normal, center, north_vector=north_vector)
         center = ds.arr([0.0] * 2, 'code_length')
-        w, frb = construct_image(ds, normal, cut, center, width=width, image_res=image_res)
+        w, frb = construct_image(ds, normal, cut, center, width=width,
+                                 image_res=image_res)
         super(FITSOffAxisSlice, self).__init__(frb, fields=fields, wcs=w)
 
 
@@ -709,14 +764,14 @@
         The name of the field(s) to be plotted.
     center : A sequence of floats, a string, or a tuple.
          The coordinate of the center of the image. If set to 'c', 'center' or
-         left blank, the plot is centered on the middle of the domain. If set to
-         'max' or 'm', the center will be located at the maximum of the
+         left blank, the plot is centered on the middle of the domain. If set 
+         to 'max' or 'm', the center will be located at the maximum of the
          ('gas', 'density') field. Centering on the max or min of a specific
-         field is supported by providing a tuple such as ("min","temperature") or
-         ("max","dark_matter_density"). Units can be specified by passing in *center*
-         as a tuple containing a coordinate and string unit name or by passing
-         in a YTArray. If a list or unitless array is supplied, code units are
-         assumed.
+         field is supported by providing a tuple such as ("min","temperature") 
+         or ("max","dark_matter_density"). Units can be specified by passing in
+         *center* as a tuple containing a coordinate and string unit name or by
+         passing in a YTArray. If a list or unitless array is supplied, code 
+         units are assumed.
     width : tuple or a float.
          Width can have four different formats to support windows with variable
          x and y widths.  They are:
@@ -767,11 +822,13 @@
         This should only be used for uniform resolution grid datasets, as other
         datasets may result in unphysical images.
     data_source : yt.data_objects.data_containers.YTSelectionContainer, optional
-        If specified, this will be the data source used for selecting regions to project.
+        If specified, this will be the data source used for selecting regions 
+        to project.
     """
     def __init__(self, ds, normal, fields, center='c', width=(1.0, 'unitary'),
-                 weight_field=None, image_res=512, depth_res=256, data_source=None,
-                 north_vector=None, depth=(1.0,"unitary"), no_ghost=False, method='integrate'):
+                 weight_field=None, image_res=512, depth_res=256, 
+                 data_source=None, north_vector=None, depth=(1.0,"unitary"), 
+                 no_ghost=False, method='integrate'):
         fields = ensure_list(fields)
         center, dcenter = ds.coordinates.sanitize_center(center, 4)
         buf = {}
@@ -785,9 +842,11 @@
         else:
             source = data_source
         for field in fields:
-            buf[field] = off_axis_projection(source, center, normal, wd, res, field,
-                                             no_ghost=no_ghost, north_vector=north_vector,
-                                             method=method, weight=weight_field).swapaxes(0, 1)
+            buf[field] = off_axis_projection(source, center, normal, wd,
+                                             res, field, no_ghost=no_ghost, 
+                                             north_vector=north_vector, 
+                                             method=method, 
+                                             weight=weight_field).swapaxes(0,1)
         center = ds.arr([0.0] * 2, 'code_length')
         w, not_an_frb = construct_image(ds, normal, buf, center, width=width, image_res=image_res)
         super(FITSOffAxisProjection, self).__init__(buf, fields=fields, wcs=w)


https://bitbucket.org/yt_analysis/yt/commits/f869c067e20c/
Changeset:   f869c067e20c
User:        jzuhone
Date:        2017-05-09 22:02:45+00:00
Summary:     Merge branch 'master' into fits_image

* master: (272 commits)
  tweak travis config to not capture logs and to print timing info
  fix bug in determining whether to throw YTBoundsDefinitionError
  covering and arbitrary grid do particle deposition in fortran order
  add travis builds for various python versions and OSX
  Add a test for code system uniqueness
  Docstring here for unit_system_id
  Rename this function and add a docstring
  Bump Athena++ answers
  This line is redundant because we set it above
  This should work like it does in the Athena frontend
  reorganize and clarify
  more comment fixes
  More comment fixes
  more comments from Marianne
  Incorporate Marianne's suggestions
  Harmonize placeholders.
  Fix docs for in_base("code")
  We should just set cgs units here and let units_override handle the rest
  This line can be less scary-sounding now
  Replace hg purge by git clean
  ...
Affected #:  282 files

diff -r 743fb233d5a830758d29aceb739cc87e34a7e5b1 -r f869c067e20c5186e3f8597ad0b1818fef0cfe68 .github/ISSUE_TEMPLATE.md
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE.md
@@ -0,0 +1,57 @@
+<!--To help us understand and resolve your issue, please fill out the form to
+the best of your ability.-->
+<!--You can feel free to delete the sections that do not apply.-->
+
+### Bug report
+
+**Bug summary**
+
+<!--A short 1-2 sentences that succinctly describes the bug-->
+
+**Code for reproduction**
+
+<!--A minimum code snippet required to reproduce the bug, also minimizing the
+number of dependencies required.-->
+
+<!-- If you need to use a data file to trigger the issue you're having, consider
+using one of the datasets from the yt data hub (http://yt-project.org/data). If
+your issue cannot be triggered using a public dataset, you can use the yt
+curldrop (https://docs.hub.yt/services.html#curldrop) to share data
+files. Please include a link to the dataset in the issue if you use the
+curldrop.-->
+
+```python
+# Paste your code here
+#
+#
+```
+
+**Actual outcome**
+
+<!--The output produced by the above code, which may be a screenshot, console
+output, etc.-->
+
+```
+# If applicable, paste the console output here
+#
+#
+```
+
+**Expected outcome**
+
+<!--A description of the expected outcome from the code snippet-->
+<!--If this used to work in an earlier version of yt, please note the
+version it used to work on-->
+
+**Version Information**
+<!--Please specify your platform and versions of the relevant libraries you are
+using:-->
+  * Operating System:
+  * Python Version:
+  * yt version:
+  * Other Libraries (if applicable): 
+
+<!--Please tell us how you installed yt and python e.g., from source,
+pip, conda. If you installed from conda, please specify which channel you used
+if not the default-->
+

diff -r 743fb233d5a830758d29aceb739cc87e34a7e5b1 -r f869c067e20c5186e3f8597ad0b1818fef0cfe68 .github/PULL_REQUEST_TEMPLATE.md
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,31 @@
+<!--Thank you so much for your PR! To help us review, fill out the form
+to the best of your ability.  Please make use of the development guide at
+http://yt-project.org/docs/dev/developing/index.html-->
+
+<!--Provide a general summary of your changes in the title above, for
+example "Raises ValueError on Non-Numeric Input to set_xlim".  Please avoid
+non-descriptive titles such as "Addresses issue #8576".-->
+
+<!--If you are able to do so, please do not create the PR out of master, but out
+of a separate branch. -->
+
+## PR Summary
+
+<!--Please provide at least 1-2 sentences describing the pull request in
+detail.  Why is this change required?  What problem does it solve?-->
+
+<!--If it fixes an open issue, please link to the issue here.-->
+
+## PR Checklist
+
+<!-- Note that some of these check boxes may not apply to all pull requests -->
+
+- [ ] Code passes flake8 checker
+- [ ] New features are documented, with docstrings and narrative docs
+- [ ] Adds a test for any bugs fixed. Adds tests for new features.
+
+<!--We understand that PRs can sometimes be overwhelming, especially as the
+reviews start coming in.  Please let us know if the reviews are unclear or the
+recommended next step seems overly demanding , or if you would like help in
+addressing a reviewer's comments.  And please ping us if you've been waiting
+too long to hear back on your PR.-->

diff -r 743fb233d5a830758d29aceb739cc87e34a7e5b1 -r f869c067e20c5186e3f8597ad0b1818fef0cfe68 .gitignore
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,88 @@
+build
+yt.egg-info
+__config__.py
+freetype.cfg
+hdf5.cfg
+png.cfg
+rockstar.cfg
+yt_updater.log
+yt/frontends/artio/_artio_caller.c
+yt/analysis_modules/halo_finding/rockstar/rockstar_groupies.c
+yt/analysis_modules/halo_finding/rockstar/rockstar_interface.c
+yt/analysis_modules/ppv_cube/ppv_utils.c
+yt/analysis_modules/photon_simulator/utils.c
+yt/frontends/ramses/_ramses_reader.cpp
+yt/frontends/sph/smoothing_kernel.c
+yt/geometry/fake_octree.c
+yt/geometry/grid_container.c
+yt/geometry/grid_visitors.c
+yt/geometry/oct_container.c
+yt/geometry/oct_visitors.c
+yt/geometry/particle_deposit.c
+yt/geometry/particle_oct_container.c
+yt/geometry/particle_smooth.c
+yt/geometry/selection_routines.c
+yt/utilities/amr_utils.c
+yt/utilities/lib/autogenerated_element_samplers.c
+yt/utilities/kdtree/forthonf2c.h
+yt/utilities/libconfig_wrapper.c
+yt/utilities/spatial/ckdtree.c
+yt/utilities/lib/allocation_container.c
+yt/utilities/lib/alt_ray_tracers.c
+yt/utilities/lib/amr_kdtools.c
+yt/utilities/lib/basic_octree.c
+yt/utilities/lib/bitarray.c
+yt/utilities/lib/bounding_volume_hierarchy.c
+yt/utilities/lib/contour_finding.c
+yt/utilities/lib/depth_first_octree.c
+yt/utilities/lib/distance_queue.c
+yt/utilities/lib/element_mappings.c
+yt/utilities/lib/fnv_hash.c
+yt/utilities/lib/fortran_reader.c
+yt/utilities/lib/freetype_writer.c
+yt/utilities/lib/geometry_utils.c
+yt/utilities/lib/image_samplers.c
+yt/utilities/lib/image_utilities.c
+yt/utilities/lib/interpolators.c
+yt/utilities/lib/kdtree.c
+yt/utilities/lib/lenses.c
+yt/utilities/lib/line_integral_convolution.c
+yt/utilities/lib/mesh_construction.cpp
+yt/utilities/lib/mesh_intersection.cpp
+yt/utilities/lib/mesh_samplers.cpp
+yt/utilities/lib/mesh_traversal.cpp
+yt/utilities/lib/mesh_triangulation.c
+yt/utilities/lib/mesh_utilities.c
+yt/utilities/lib/misc_utilities.c
+yt/utilities/lib/particle_mesh_operations.c
+yt/utilities/lib/partitioned_grid.c
+yt/utilities/lib/primitives.c
+yt/utilities/lib/origami.c
+yt/utilities/lib/particle_mesh_operations.c
+yt/utilities/lib/pixelization_routines.c
+yt/utilities/lib/png_writer.c
+yt/utilities/lib/points_in_volume.c
+yt/utilities/lib/quad_tree.c
+yt/utilities/lib/ray_integrators.c
+yt/utilities/lib/ragged_arrays.c
+yt/utilities/lib/cosmology_time.c
+yt/utilities/lib/grid_traversal.c
+yt/utilities/lib/marching_cubes.c
+yt/utilities/lib/png_writer.h
+yt/utilities/lib/write_array.c
+yt/utilities/lib/perftools_wrap.c
+yt/utilities/lib/partitioned_grid.c
+yt/utilities/lib/volume_container.c
+yt/utilities/lib/lenses.c
+yt/utilities/lib/image_samplers.c
+*.pyc
+*.pyd
+.*.swp
+*.so
+.idea/*
+tests/results/*
+doc/build/*
+doc/source/reference/api/generated/*
+doc/_temp/*
+doc/source/bootcamp/.ipynb_checkpoints/
+dist

diff -r 743fb233d5a830758d29aceb739cc87e34a7e5b1 -r f869c067e20c5186e3f8597ad0b1818fef0cfe68 .hgignore
--- a/.hgignore
+++ b/.hgignore
@@ -37,6 +37,7 @@
 yt/utilities/lib/depth_first_octree.c
 yt/utilities/lib/distance_queue.c
 yt/utilities/lib/element_mappings.c
+yt/utilities/lib/fnv_hash.c
 yt/utilities/lib/fortran_reader.c
 yt/utilities/lib/freetype_writer.c
 yt/utilities/lib/geometry_utils.c

diff -r 743fb233d5a830758d29aceb739cc87e34a7e5b1 -r f869c067e20c5186e3f8597ad0b1818fef0cfe68 .mailmap
--- /dev/null
+++ b/.mailmap
@@ -0,0 +1,89 @@
+Stephen Skory <s at skory.us> Stephen Skory <stephenskory at yahoo.com>
+Stephen Skory <s at skory.us> "Stephen Skory stephenskory at yahoo.com" <"Stephen Skory stephenskory at yahoo.com">
+Yuan Li <yuan at astro.columbia.edu> Yuan Li <bear0980 at gmail.com>
+Chris Moody <juxtaposicion at gmail.com> Chris Moody <cemoody at ucsc.edu>
+Chris Moody <juxtaposicion at gmail.com> Christopher Erick Moody <cemoody at ucsc.edu>
+Cameron Hummels <chummels at gmail.com> Cameron Hummels <chummels at astro.columbia.edu>
+Cameron Hummels <chummels at gmail.com> chummels <chummels at gmail.com>
+John Wise <jwise at physics.gatech.edu> John Wise <jwise at astro.princeton.edu>
+Sam Skillman <samskillman at gmail.com> Sam Skillman <sam.skillman at gmail.com>
+Sam Skillman <samskillman at gmail.com> samskillman <sam.skillman at gmail.com>
+Casey Stark <caseywstark at gmail.com> Casey Stark <casey at thestarkeffect.com>
+Christian Karch <chiffre at posteo.de> chiffre <none at none>
+Christian Karch <chiffre at posteo.de> Christian Karch <none at none>
+Andrew Myers <atmyers2 at gmail.com> Andrew Myers <atmyers at berkeley.edu>
+Andrew Myers <atmyers2 at gmail.com> atmyers <none at none>
+Douglas Rudd <drudd at uchicago.edu> drudd <none at none>
+Andrew Wetzel <andrew.wetzel at yale.edu> awetzel <none at none>
+David Collins <dcollins4096 at gmail.com> David Collins <dcollins at physics.ucsd.edu>
+David Collins <dcollins4096 at gmail.com> dcollins4096 <none at none>
+David Collins <dcollins4096 at gmail.com> David Collins (dcollins4096 at gmail.com) <David Collins (dcollins4096 at gmail.com)>
+Tom Abel <tabel at slac.stanford.edu> tabel <none at none>
+Kaylea Nelson <kaylea.nelson at yale.edu> sername=kayleanelson <none at none>
+Kaylea Nelson <kaylea.nelson at yale.edu> kayleanelson <none at none
+Kaylea Nelson <kaylea.nelson at yale.edu> kayleanelson <none at none>
+Stephanie Tonnesen <stonnes at gmail.com> stonnes <stonnes at gmail.com>
+John Forbes <jcforbes at ucsc.edu> John Forbes <jforbes at ucolick.org>
+Elliott Biondo <biondo at wisc.edu> Elliott Biondo <Biondo at wisc.edu>
+Sam Geen <samgeen at gmail.com> Sam Geen <samgeen at googlemail.com>
+Alex Bogert <fbogert at ucsc.edu> fbogert <none at none>
+Brian O'Shea <oshea at msu.edu> bwoshea <none at none>
+Ji-hoon Kim <me at jihoonkim.org> Ji-hoon Kim <mornkr at slac.stanford.edu>
+Kirk Barrow <kssbarrow at gatech.edu> Kirk Barrow <kssbarrow at gmail.com>
+Kirk Barrow <kssbarrow at gatech.edu> Kirk Barrow <kassbarrow at gmail.com>
+Kirk Barrow <kssbarrow at gatech.edu> kbarrow <none at none>
+Kirk Barrow <kssbarrow at gatech.edu> kbarrow <kassbarrow at gmail.com>
+Antoine Strugarek <antoine.strugarek at cea.fr> Antoine Strugarek <strugarek at astro.umontreal.ca>
+Antoine Strugarek <antoine.strugarek at cea.fr> astrugarek <strugarek at astro.umontreal.ca>
+Antoine Strugarek <antoine.strugarek at cea.fr> Antoine Strugarek <antoine.strugarek at cea.fr>
+Anna Rosen <rosen at ucolick.org> Anna Rosen <alrosen at ucsc.edu>
+John ZuHone <jzuhone at gmail.com> jzuhone <none at none>
+John ZuHone <jzuhone at gmail.com> jzuhone <jzuhone at gmail.com>
+Kenza Arraki <karraki at nmsu.edu> Kenza Arraki <karraki at gmail.com>
+Allyson Julian <astrohckr at gmail.com> Allyson Julian <hckr at eml.cc>
+Allyson Julian <astrohckr at gmail.com> Allyson Julian <julian3 at illinois.edu>
+Allyson Julian <astrohckr at gmail.com> Allyson Julian <aj at hckr.eml.cc>
+Allyson Julian <astrohckr at gmail.com> AJ <astrohckr at gmail.com>
+Allyson Julian <astrohckr at gmail.com> Al Jul <hckr at eml.cc>
+Allyson Julian <astrohckr at gmail.com> AJ <aj at hckr.eml.cc>
+Allyson Julian <astrohckr at gmail.com> AJ <hckr at eml.cc>
+Brian Crosby <bcrosby.bd at gmail.com> bcrosby <bcrosby.bd at gmail.com>
+Ben Thompson <bthompson2090 at gmail.com> Ben Thompson <none at none>
+Ben Thompson <bthompson2090 at gmail.com> cosmosquark <none at none>
+Chris Malone <chris.m.malone at gmail.com> Chris Malone <chris.m.malone at lanl.gov>
+Chris Malone <chris.m.malone at gmail.com> ChrisMalone <chris.m.malone at gmail.com>
+Chris Malone <chris.m.malone at gmail.com> ChrisMalone <chris.m.malone at lanl.gov>
+Jill Naiman <jnaiman at cfa.harvard.edu> Jill Naiman <jnaiman at ucolick.org>
+Jill Naiman <jnaiman at cfa.harvard.edu> jnaiman <none at none>
+Jill Naiman <jnaiman at cfa.harvard.edu> jnaiman <jnaiman at ucolick.org>
+Ricarda Beckmann <ricarda.beckmann at astro.ox.ac.uk> RicardaBeckmann <ricarda.beckmann at astro.ox.ac.uk>
+Miguel de Val-Borro <miguel.deval at gmail.com> Miguel de Val-Borro <miguel at archlinux.net>
+Stuary Levy <salevy at illinois.edu> Stuart Levy <slevy at ncsa.illinois.edu>
+Ben Keller <malzraa at gmail.com> Ben Keller <kellerbw at mcmaster.ca>
+Daniel Fenn <df11c at my.fsu.edu> dfenn <none at none>
+Meagan Lang <langmm.astro at gmail.com> langmm <none at none>
+Joseph Tomlinson <jmtomlinson95 at gmail.com> jmt354 <none at none>
+Desika Narayanan <dnarayan at haverford.edu> desika <none at none>
+Nathan Goldbaum <ngoldbau at illinois.edu> Nathan Goldbaum <goldbaum at ucolick.org>
+Nathan Goldbaum <ngoldbau at illinois.edu> Nathan Goldbaum <ngoldbau at ucsc.edu>
+Fabian Koller <anokfireball at poseto.de> NTAuthority at honeypot.fritz.box <NTAuthority at honeypot.fritz.box>
+Fabian Koller <anokfireball at posteo.de> NTAuthority at guest053.fz-rossendorf.de <NTAuthority at guest053.fz-rossendorf.de>
+Fabian Koller <anokfireball at posteo.de> NTAuthority at guest692.fz-rossendorf.de <NTAuthority at guest692.fz-rossendorf.de>
+Fabian Koller <anokfireball at posteo.de> NTAuthority at guest692.fz-rossendorf.de <NTAuthority at guest692.fz-rossendorf.de>
+Fabian Koller <anokfireball at posteo.de> Fabian Koller <none at none>
+Rafael Ruggiero <rafael.ruggiero at usp.br> Rafael Ruggiero <none at none>
+John Regan <john.regan at helsinki.fi> John Regan <john.a.regan at durham.ac.uk>
+Axel Huebl <a.huebl at hzdr.de> Axel Huebl <code at andre-bubel.de>
+Gabriel Altay <gabriel.altay at gmail.com> galtay <gabriel.altay at gmail.com>
+Mark Richardson <Mark.Richardson.Work at gmail.com> Mark Richardson <Mark.L.Richardson at asu.edu>
+Jared Coughlin <jcoughl2 at nd.edu> Jared <none at none>
+Corentin Cadiou <corentin.cadiou at iap.fr> cphyc <contact at cphyc.me>
+Corentin Cadiou <corentin.cadiou at iap.fr> ccc at pingouin.local <ccc at pingouin.local>
+Corentin Cadiou <corentin.cadiou at iap.fr> ccc at pingouin-2.local <ccc at pingouin-2.local>
+Corentin Cadiou <corentin.cadiou at iap.fr> Corentin Cadiou <contact at cphyc.me>
+convert-repo <none at none> None <none at none>
+Patrick Shriwise <shriwise at wisc.edu> pshriwise <shriwise at wisc.edu>
+Michael Zingale <michael.zingale at stonybrook.edu> Michael  Zingale <michael.zingale at stonybrook.edu>
+Sam Leitner <sam.leitner at gmail.com> Sam  Leitner <sam.leitner at gmail.com>
+Geoffrey So <gsiisg at gmail.com> gsiisg <gsiisg at gmail.com>
+Matthew Turk <matthewturk at gmail.com> Matt Turk <matthewturk at gmail.com>
\ No newline at end of file

diff -r 743fb233d5a830758d29aceb739cc87e34a7e5b1 -r f869c067e20c5186e3f8597ad0b1818fef0cfe68 .travis.yml
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,61 @@
+language: python
+sudo: false
+cache:
+  pip: true
+  directories:
+    - $HOME/.ccache  # https://github.com/travis-ci/travis-ci/issues/5853
+
+addons:
+  apt:
+    packages:
+      - libhdf5-serial-dev
+
+matrix:
+  include:
+    - python: 2.7
+    - python: 3.4
+    - python: 3.5
+    - python: 3.6
+    - os: osx
+      osx_image: xcode7.3
+      language: generic  # https://github.com/travis-ci/travis-ci/issues/2312
+      cache:
+        pip: false
+        directories:
+          - $HOME/Library/Caches/pip
+          # `cache` does not support `env`-like `global` so copy-paste from top
+          - $HOME/.ccache  # https://github.com/travis-ci/travis-ci/issues/5853
+
+before_install:
+  - |
+    if [[ $TRAVIS_OS_NAME != 'osx' ]]; then
+      pip install --upgrade virtualenv
+      python -m virtualenv venv
+      source venv/bin/activate
+      export PATH=/usr/lib/ccache:$PATH
+    else
+      brew update
+      brew install ccache hdf5
+      export PATH=/usr/local/opt/ccache/libexec:$PATH
+    fi
+    mkdir -p $HOME/.config/yt
+    echo "[yt]" > $HOME/.config/yt/ytrc
+    echo "suppressStreamLogging = True" >> $HOME/.config/yt/ytrc
+    cat $HOME/.config/yt/ytrc
+
+install:
+  - |
+    # setup environment
+    ccache -s
+    # Upgrade pip and setuptools and wheel to get clean install
+    pip install --upgrade pip
+    pip install --upgrade wheel
+    pip install --upgrade setuptools
+    # Install dependencies
+    pip install mock numpy scipy cython matplotlib sympy fastcache nose flake8 h5py ipython nose-timer
+    # install yt
+    pip install -e .
+
+script:
+  - |
+    nosetests --nologcapture --with-timer -sv yt

diff -r 743fb233d5a830758d29aceb739cc87e34a7e5b1 -r f869c067e20c5186e3f8597ad0b1818fef0cfe68 CONTRIBUTING.rst
--- a/CONTRIBUTING.rst
+++ b/CONTRIBUTING.rst
@@ -22,7 +22,7 @@
    You can connect through our web
    gateway without any special client, at http://yt-project.org/irc.html .
    *IRC is the first stop for conversation!*
- * Many yt developers participate in the yt Slack community. Slack is a free 
+ * Many yt developers participate in the yt Slack community. Slack is a free
    chat service that many teams use to organize their work. You can get an
    invite to yt's Slack organization by clicking the "Join us @ Slack" button
    on this page: http://yt-project.org/community.html
@@ -54,18 +54,18 @@
 help out.
 
 The easiest way to help out is to fork the main yt repository (where the
-documentation lives in the ``doc`` directory in the root of the yt mercurial
+documentation lives in the ``doc`` directory in the root of the yt git
 repository) and then make your changes in your own fork.  When you are done,
 issue a pull request through the website for your new fork, and we can comment
 back and forth and eventually accept your changes. See :ref:`sharing-changes` for
-more information about contributing your changes to yt on bitbucket.
+more information about contributing your changes to yt on GitHub.
 
 Gallery Images and Videos
 -------------------------
 
 If you have an image or video you'd like to display in the image or video
 galleries, getting it included it easy!  You can either fork the `yt homepage
-repository <http://bitbucket.org/yt_analysis/website>`_ and add it there, or
+repository <http://github.com/yt-project/website>`_ and add it there, or
 email it to us and we'll add it to the `Gallery
 <http://yt-project.org/gallery.html>`_.
 
@@ -80,20 +80,20 @@
 bug fixes, new features, analysis modules, or a new code frontend.  See
 :ref:`creating_frontend` for more details.
 
-The process is pretty simple: fork on BitBucket, make changes, issue a pull
+The process is pretty simple: fork on GitHub, make changes, issue a pull
 request.  We can then go back and forth with comments in the pull request, but
 usually we end up accepting.
 
 For more information, see :ref:`contributing-code`, where we spell out how to
 get up and running with a development environment, how to commit, and how to
-use BitBucket.
+use GitHub.
 
 Online Presence
 ---------------
 
 Some of these fall under the other items, but if you'd like to help out with
 the website or any of the other ways yt is presented online, please feel free!
-Almost everything is kept in hg repositories on BitBucket, and it is very easy
+Almost everything is kept in git repositories on GitHub, and it is very easy
 to fork and contribute back changes.
 
 Please feel free to dig in and contribute changes.
@@ -210,19 +210,19 @@
 yt is a community project!
 
 We are very happy to accept patches, features, and bugfixes from any member of
-the community!  yt is developed using mercurial, primarily because it enables
-very easy and straightforward submission of changesets.  We're eager to hear
+the community!  yt is developed using git, primarily because it enables
+very easy and straightforward submission of revisions.  We're eager to hear
 from you, and if you are developing yt, we encourage you to subscribe to the
 `developer mailing list
 <http://lists.spacepope.org/listinfo.cgi/yt-dev-spacepope.org>`_. Please feel
 free to hack around, commit changes, and send them upstream.
 
-.. note:: If you already know how to use the `mercurial version control system
-   <http://mercurial-scm.org>`_ and are comfortable with handling it yourself,
-   the quickest way to contribute to yt is to `fork us on BitBucket
-   <http://bitbucket.org/yt_analysis/yt/fork>`_, make your changes, push the
+.. note:: If you already know how to use the `git version control system
+   <https://git-scm.com/>`_ and are comfortable with handling it yourself,
+   the quickest way to contribute to yt is to `fork us on GitHub
+   <https://github.com/yt-project/yt/fork>`_, make your changes, push the
    changes to your fork and issue a `pull request
-   <http://bitbucket.org/yt_analysis/yt/pull-requests>`_.  The rest of this
+   <https://github.com/yt-project/yt/pulls>`_.  The rest of this
    document is just an explanation of how to do that.
 
 See :ref:`code-style-guide` for more information about coding style in yt and
@@ -238,8 +238,8 @@
 -----------
 
 If you're interested in participating in yt development, take a look at the
-`issue tracker on bitbucket
-<https://bitbucket.org/yt_analysis/yt/issues?milestone=easy?status=new>`_.
+`issue tracker on GitHub
+<https://github.com/yt-project/yt/issues>`_.
 Issues are marked with a milestone of "easy", "moderate", or "difficult"
 depending on the estimated level of difficulty for fixing the issue. While we
 try to triage the issue tracker regularly, it may be the case that issues marked
@@ -248,9 +248,8 @@
 
 Here are some predefined issue searches that might be useful:
 
-* Unresolved issues `marked "easy" <https://bitbucket.org/yt_analysis/yt/issues?milestone=easy&status=open&status=new>`_.
-* Unresolved issues `marked "easy" or "moderate" <https://bitbucket.org/yt_analysis/yt/issues?milestone=easy&milestone=moderate&status=open&status=new>`_
-* `All unresolved issues <https://bitbucket.org/yt_analysis/yt/issues?status=open&status=new>`_
+* Unresolved issues `marked "easy" <https://github.com/yt-project/yt/issues?utf8=%E2%9C%93&q=is%3Aissue%20is%3Aopen%20milestone%3Aeasy>`_.
+* `All unresolved issues <https://github.com/yt-project/yt/issues>`_
 
 Submitting Changes
 ------------------
@@ -258,7 +257,7 @@
 We provide a brief introduction to submitting changes here.  yt thrives on the
 strength of its communities (http://arxiv.org/abs/1301.7064 has further
 discussion) and we encourage contributions from any user.  While we do not
-discuss version control, mercurial or the advanced usage of BitBucket in detail
+discuss version control, git, or the advanced usage of GitHub in detail
 here, we do provide an outline of how to submit changes and we are happy to
 provide further assistance or guidance.
 
@@ -275,48 +274,49 @@
 How To Get The Source Code For Editing
 ++++++++++++++++++++++++++++++++++++++
 
-yt is hosted on BitBucket, and you can see all of the yt repositories at
-http://bitbucket.org/yt_analysis/.  With the yt installation script you should have a
-copy of Mercurial for checking out pieces of code.  Make sure you have followed
+yt is hosted on GitHub, and you can see all of the yt repositories at
+https://github.com/yt-project/.  With the yt installation script you should have a
+copy of git for checking out pieces of code.  Make sure you have followed
 the steps above for bootstrapping your development (to assure you have a
-bitbucket account, etc.)
+GitHub account, etc.)
 
 In order to modify the source code for yt, we ask that you make a "fork" of the
-main yt repository on bitbucket.  A fork is simply an exact copy of the main
+main yt repository on GitHub.  A fork is simply an exact copy of the main
 repository (along with its history) that you will now own and can make
 modifications as you please.  You can create a personal fork by visiting the yt
-bitbucket webpage at https://bitbucket.org/yt_analysis/yt/ .  After logging in,
-you should see an option near the top right labeled "fork".  Click this option,
-and then click the fork repository button on the subsequent page.  You now have
+GitHub webpage at https://github.com/yt-project/yt/ .  After logging in,
+you should see an option near the top right labeled "fork". You now have
 a forked copy of the yt repository for your own personal modification.
 
-This forked copy exists on the bitbucket repository, so in order to access
-it locally, follow the instructions at the top of that webpage for that
-forked repository, namely run at a local command line:
+This forked copy exists on the GitHub repository, so in order to access
+it locally you must clone it onto your machine from the command line:
 
 .. code-block:: bash
 
-   $ hg clone http://bitbucket.org/<USER>/<REPOSITORY_NAME>
+   $ git clone https://github.com/<USER>/yt ./yt-git
 
 This downloads that new forked repository to your local machine, so that you
 can access it, read it, make modifications, etc.  It will put the repository in
 a local directory of the same name as the repository in the current working
-directory. You should also run the following command, to make sure you are at
-the "yt" branch, and not other ones like "stable" (this will be important
-later when you want to submit your pull requests):
+directory.
 
 .. code-block:: bash
 
-   $ hg update yt
+   $ cd yt-git
+
+Verify that you are on the master branch of yt by running:
 
-You can see any past state of the code by using the hg log command.
-For example, the following command would show you the last 5 changesets
+.. code-block:: bash
+
+   $ git branch
+
+You can see any past state of the code by using the git log command.
+For example, the following command would show you the last 5 revisions
 (modifications to the code) that were submitted to that repository.
 
 .. code-block:: bash
 
-   $ cd <REPOSITORY_NAME>
-   $ hg log -l 5
+   $ git log -n 5
 
 Using the revision specifier (the number or hash identifier next to each
 changeset), you can update the local repository to any past state of the
@@ -324,7 +324,7 @@
 
 .. code-block:: bash
 
-   $ hg up revision_specifier
+   $ git checkout revision_specifier
 
 Lastly, if you want to use this new downloaded version of your yt repository as
 the *active* version of yt on your computer (i.e. the one which is executed when
@@ -334,8 +334,7 @@
 
 .. code-block:: bash
 
-   $ cd <REPOSITORY_NAME>
-   $ python2.7 setup.py develop
+   $ python setup.py develop
 
 This will rebuild all C modules as well.
 
@@ -346,13 +345,13 @@
 
 If you just want to *look* at the source code, you may already have it on your
 computer.  If you build yt using the install script, the source is available at
-``$YT_DEST/src/yt-hg``.  See :ref:`source-installation` for more details about
+``$YT_DEST/src/yt-git``.  See :ref:`source-installation` for more details about
 to obtain the yt source code if you did not build yt using the install
 script.
 
-The root directory of the yt mercurial repository contains a number of
+The root directory of the yt git repository contains a number of
 subdirectories with different components of the code.  Most of the yt source
-code is contained in the yt subdirectory.  This directory its self contains
+code is contained in the yt subdirectory.  This directory itself contains
 the following subdirectories:
 
 ``frontends``
@@ -431,49 +430,31 @@
 rebuild yt.  If your changes have exclusively been to Python modules, you will
 not need to re-build, but (see below) you may need to re-install.
 
+Note that you will need a functioning compilation environment to build yt. On
+linux this typically means installing the package that sets up a basic build
+environment (e.g. ``build-essential`` on Debian and Ubuntu). On MacOS this means
+installing the XCode command line tools. On Windows this means installing the
+version of the Microsoft Visual C++ compiler that is appropriate for your
+version of Python. See `the Python wiki
+<https://wiki.python.org/moin/WindowsCompilers>`_ for more details.
+
 If you are running from a clone that is executable in-place (i.e., has been
 installed via the installation script or you have run ``setup.py develop``) you
 can rebuild these modules by executing:
 
 .. code-block:: bash
 
-  $ python2.7 setup.py develop
+  $ python setup.py develop
 
 If you have previously "installed" via ``setup.py install`` you have to
 re-install:
 
 .. code-block:: bash
 
-  $ python2.7 setup.py install
+  $ python setup.py install
 
 Only one of these two options is needed.
 
-.. _windows-developing:
-
-Developing yt on Windows
-------------------------
-
-If you plan to develop yt on Windows, it is necessary to use the `MinGW
-<http://www.mingw.org/>`_ gcc compiler that can be installed using the `Anaconda
-Python Distribution <https://store.continuum.io/cshop/anaconda/>`_. The libpython package must be
-installed from Anaconda as well. These can both be installed with a single command:
-
-.. code-block:: bash
-
-  $ conda install libpython mingw
-
-Additionally, the syntax for the setup command is slightly different; you must type:
-
-.. code-block:: bash
-
-  $ python2.7 setup.py build --compiler=mingw32 develop
-
-or
-
-.. code-block:: bash
-
-  $ python2.7 setup.py build --compiler=mingw32 install
-
 .. _requirements-for-code-submission:
 
 Requirements for Code Submission
@@ -513,68 +494,61 @@
 out with them.  In :ref:`code-style-guide` there is a list of handy tips for
 how to structure and write your code.
 
-.. _mercurial-with-yt:
+.. _git-with-yt:
 
-How to Use Mercurial with yt
-----------------------------
+How to Use git with yt
+----------------------
 
-If you're new to Mercurial, these three resources are pretty great for learning
+If you're new to git, the following resource is pretty great for learning
 the ins and outs:
 
-* http://hginit.com/
-* http://hgbook.red-bean.com/read/
-* http://mercurial-scm.org/
-* http://mercurial-scm.org/wiki
+* https://git-scm.com/
 
-The commands that are essential for using mercurial include:
+The commands that are essential for using git include:
 
-* ``hg help`` which provides help for any mercurial command. For example, you
-  can learn more about the ``log`` command by doing ``hg help log``. Other useful
-  topics to use with ``hg help`` are ``hg help glossary``, ``hg help config``,
-  ``hg help extensions``, and ``hg help revsets``.
-* ``hg commit`` which commits changes in the working directory to the
-  repository, creating a new "changeset object."
-* ``hg add`` which adds a new file to be tracked by mercurial.  This does
-  not change the working directory.
-* ``hg pull`` which pulls (from an optional path specifier) changeset
-  objects from a remote source.  The working directory is not modified.
-* ``hg push`` which sends (to an optional path specifier) changeset objects
-  to a remote source.  The working directory is not modified.
-* ``hg log`` which shows a log of all changeset objects in the current
-  repository.  Use ``-G`` to show a graph of changeset objects and their
-  relationship.
-* ``hg update`` which (with an optional "revision" specifier) updates the
-  state of the working directory to match a changeset object in the
-  repository.
-* ``hg merge`` which combines two changesets to make a union of their lines
-  of development.  This updates the working directory.
+* ``git <command> --help`` which provides help for any git command. For example, you
+  can learn more about the ``log`` command by doing ``git log --help``.
+* ``git add <paths>`` which stages changes to the specified paths for subsequent
+  committing (see below).
+* ``git commit`` which commits staged changes (stage using ``git add`` as above)
+  in the working directory to the repository, creating a new "revision."
+* ``git merge <branch>`` which merges the revisions from the specified branch
+  into the current branch, creating a union of their lines of development. This
+  updates the working directory.
+* ``git pull <remote><branch>`` which pulls revisions from the specified branch of the
+  specified remote repository into the current local branch. Equivalent to ``git
+  fetch <remote>`` and then ``git merge <remote>/<branch>``. This updates the
+  working directory.
+* ``git push <remote>`` which sends revisions on local branches to matching
+  branches on the specified remote. ``git push <remote><branch>`` will only
+  push changes for the specified branch.
+* ``git log`` which shows a log of all revisions on the current branch. There
+  are many options you can pass to ``git log`` to get additional
+  information. One example is ``git log --oneline --decorate --graph --all``.
 
-We are happy to asnswers questions about mercurial use on our IRC, slack
+We are happy to answer questions about git use on our IRC, slack
 chat or on the mailing list to walk you through any troubles you might have.
-Here are some general suggestions for using mercurial with yt:
+Here are some general suggestions for using git with yt:
 
-* Named branches are to be avoided.  Try using bookmarks (``see hg help
-  bookmark``) to track work.  (`More info about bookmarks is available on the
-  mercurial wiki <http://mercurial-scm.org/wiki/Bookmarks>`_)
-* Make sure you set a username in your ``~/.hgrc`` before you commit any
-  changes!  All of the tutorials above will describe how to do this as one of
-  the very first steps.
+* Although not necessary, a common development work flow is to create a local
+  named branch other than ``master`` to address a feature request or bugfix. If
+  the dev work addresses a specific yt GitHub issue, you may include that issue
+  number in the branch name. For example, if you want to work on issue number X
+  regarding a cool new slice plot feature, you might name the branch:
+  ``cool_new_plot_feature_X``. When you're ready to share your work, push your
+  feature branch to your remote and create a pull request to the ``master``
+  branch of the yt-project's repository.
 * When contributing changes, you might be asked to make a handful of
   modifications to your source code.  We'll work through how to do this with
   you, and try to make it as painless as possible.
 * Your test may fail automated style checks. See :ref:`code-style-guide` for
   more information about automatically verifying your code style.
-* Please avoid deleting your yt forks, as that deletes the pull request
-  discussion from process from BitBucket's website, even if your pull request
-  is merged.
 * You should only need one fork.  To keep it in sync, you can sync from the
-  website. See Bitbucket's `Blog Post
-  <https://blog.bitbucket.org/2013/02/04/syncing-and-merging-come-to-bitbucket/>`_
-  about this. See :ref:`sharing-changes` for a description of the basic workflow
+  website. See :ref:`sharing-changes` for a description of the basic workflow
   and :ref:`multiple-PRs` for a discussion about what to do when you want to
   have multiple open pull requests at the same time.
-* If you run into any troubles, stop by IRC (see :ref:`irc`) or the mailing
-  list.
+* If you run into any troubles, stop by IRC (see :ref:`irc`), Slack, or the
+  mailing list.
 
 .. _sharing-changes:
 
@@ -583,30 +557,39 @@
 
 The simplest way to submit changes to yt is to do the following:
 
-* Build yt from the mercurial repository
+* Build yt from the git repository
 * Navigate to the root of the yt repository
 * Make some changes and commit them
-* Fork the `yt repository on BitBucket <https://bitbucket.org/yt_analysis/yt>`_
+* Fork the `yt repository on GitHub <https://github.com/yt-project/yt>`_
 * Push the changesets to your fork
 * Issue a pull request.
 
 Here's a more detailed flowchart of how to submit changes.
 
+#. Fork yt on GitHub.  (This step only has to be done once.)  You can do
+   this at: https://github.com/yt-project/yt/fork.
 #. If you have used the installation script, the source code for yt can be
-   found in ``$YT_DEST/src/yt-hg``.  Alternatively see
+   found in ``$YT_DEST/src/yt-git``.  Alternatively see
    :ref:`source-installation` for instructions on how to build yt from the
-   mercurial repository. (Below, in :ref:`reading-source`, we describe how to
-   find items of interest.)
+   git repository. (Below, in :ref:`reading-source`, we describe how to
+   find items of interest.) If you have already forked the repository then
+   you can clone your fork locally::
+
+     git clone https://github.com/<USER>/yt ./yt-git
+
+   This will create a local clone of your fork of yt in a folder named
+   ``yt-git``.
 #. Edit the source file you are interested in and
    test your changes.  (See :ref:`testing` for more information.)
-#. Fork yt on BitBucket.  (This step only has to be done once.)  You can do
-   this at: https://bitbucket.org/yt_analysis/yt/fork.  Call this repository
-   yt.
-#. Create a bookmark to track your work. For example: ``hg bookmark
-   my-first-pull-request``
-#. Commit these changes, using ``hg commit``.  This can take an argument
-   which is a series of filenames, if you have some changes you do not want
-   to commit.
+#. Create a uniquely named branch to track your work. For example: ``git
+   checkout -b my-first-pull-request``
+#. Stage your changes using ``git add <paths>``.  This command take an argument
+   which is a series of filenames whose changes you want to commit. After
+   staging, execute ``git commit -m "<Commit description>. Addresses Issue
+   #X"``. Note that supplying an actual GitHub issue # in place of ``X`` will
+   cause your commit to appear in the issue tracker after pushing to your
+   remote. This can be very helpful for others who are interested in what work
+   is being done in connection to that issue.
 #. Remember that this is a large development effort and to keep the code
    accessible to everyone, good documentation is a must.  Add in source code
    comments for what you are doing.  Add in docstrings
@@ -616,132 +599,96 @@
 #. If your changes include new functionality or cover an untested area of the
    code, add a test.  (See :ref:`testing` for more information.)  Commit
    these changes as well.
-#. Push your changes to your new fork using the command::
+#. Add your remote repository with a unique name identifier. It can be anything
+   but it is conventional to call it ``origin``.  You can see names and URLs of
+   all the remotes you currently have configured with::
+
+     git remote -v
 
-      hg push -B my-first-pull-request https://bitbucket.org/YourUsername/yt/
+   If you already have an ``origin`` remote, you can set it to your fork with::
+
+     git remote set-url origin https://github.com/<USER>/yt
+
+   If you do not have an ``origin`` remote you will need to add it::
+
+     git remote add origin https://github.com/<USER>/yt
 
-   Where you should substitute the name of the bookmark you are working on for
-   ``my-first-pull-request``. If you end up doing considerable development, you
-   can set an alias in the file ``.hg/hgrc`` to point to this path.
+   In addition, it is also useful to add a remote for the main yt repository.
+   By convention we name this remote ``upstream``::
+
+     git remote add upstream https://github.com/yt-project/yt
+
+   Note that if you forked the yt repository on GitHub and then cloned from
+   there you will not need to add the ``origin`` remote.
+
+#. Push your changes to your remote fork using the unique identifier you just
+   created and the command::
+
+      git push origin my-first-pull-request
+
+   Where you should substitute the name of the feature branch you are working on for
+   ``my-first-pull-request``.
 
    .. note::
      Note that the above approach uses HTTPS as the transfer protocol
-     between your machine and BitBucket.  If you prefer to use SSH - or
+     between your machine and GitHub.  If you prefer to use SSH - or
      perhaps you're behind a proxy that doesn't play well with SSL via
-     HTTPS - you may want to set up an `SSH key`_ on BitBucket.  Then, you use
-     the syntax ``ssh://hg@bitbucket.org/YourUsername/yt``, or equivalent, in
-     place of ``https://bitbucket.org/YourUsername/yt`` in Mercurial commands.
+     HTTPS - you may want to set up an `SSH key`_ on GitHub.  Then, you use
+     the syntax ``ssh://git@github.com/<USER>/yt``, or equivalent, in
+     place of ``https://github.com/<USER>/yt`` in git commands.
      For consistency, all commands we list in this document will use the HTTPS
      protocol.
 
-     .. _SSH key: https://confluence.atlassian.com/display/BITBUCKET/Set+up+SSH+for+Mercurial
-
-#. Issue a pull request at
-   https://bitbucket.org/YourUsername/yt/pull-request/new
-   A pull request is essentially just asking people to review and accept the
+     .. _SSH key: https://help.github.com/articles/connecting-to-github-with-ssh/
+#. Issue a pull request at https://github.com/yt-project/yt/pull/new/master A
+   pull request is essentially just asking people to review and accept the
    modifications you have made to your personal version of the code.
 
-
 During the course of your pull request you may be asked to make changes.  These
-changes may be related to style issues, correctness issues, or even requesting
+changes may be related to style issues, correctness issues, or requesting
 tests.  The process for responding to pull request code review is relatively
 straightforward.
 
 #. Make requested changes, or leave a comment indicating why you don't think
    they should be made.
 #. Commit those changes to your local repository.
-#. Push the changes to your fork:
+#. Push the changes to your fork::
+      git push origin my-first-pull-request
+#. Your pull request will be automatically updated.
+
+Once your pull request is merged, sync up with the main yt repository by pulling
+from the ``upstream`` remote::
+
+     git checkout master
+     git pull upstream master
+
+You might also want to sync your fork of yt on GitHub::
 
-      hg push https://bitbucket.org/YourUsername/yt/
+     # sync my fork of yt with upstream
+     git push origin master
+
+And delete the branch for the merged pull request::
 
-#. Your pull request will be automatically updated.
+     # delete branch for merged pull request
+     git branch -d my-first-pull-request
+     git push origin --delete my-first-pull-request
+
+These commands are optional but are nice for keeping your branch list
+manageable. You can also delete the branch on your fork of yt on GitHub by
+clicking the "delete branch" button on the page for the merged pull request on
+GitHub.
 
 .. _multiple-PRs:
 
-Working with Multiple BitBucket Pull Requests
----------------------------------------------
-
-Once you become active developing for yt, you may be working on
-various aspects of the code or bugfixes at the same time.  Currently,
-BitBucket's *modus operandi* for pull requests automatically updates
-your active pull request with every ``hg push`` of commits that are a
-descendant of the head of your pull request.  In a normal workflow,
-this means that if you have an active pull request, make some changes
-locally for, say, an unrelated bugfix, then push those changes back to
-your fork in the hopes of creating a *new* pull request, you'll
-actually end up updating your current pull request!
-
-There are a few ways around this feature of BitBucket that will allow
-for multiple pull requests to coexist; we outline one such method
-below.  We assume that you have a fork of yt at
-``http://bitbucket.org/YourUsername/Your_yt`` (see
-:ref:`sharing-changes` for instructions on creating a fork) and that
-you have an active pull request to the main repository.
-
-The main issue with starting another pull request is to make sure that
-your push to BitBucket doesn't go to the same head as your
-existing pull request and trigger BitBucket's auto-update feature.
-Here's how to get your local repository away from your current pull
-request head using `revsets <http://www.selenic.com/hg/help/revsets>`_
-and your ``hgrc`` file:
-
-#. Set up a Mercurial path for the main yt repository (note this is a convenience
-   step and only needs to be done once).  Add the following to your
-   ``Your_yt/.hg/hgrc``::
-
-     [paths]
-     upstream = https://bitbucket.org/yt_analysis/yt
-
-   This will create a path called ``upstream`` that is aliased to the URL of the
-   main yt repository.
-#. Now we'll use revsets_ to update your local repository to the tip of the
-   ``upstream`` path:
-
-   .. code-block:: bash
+Working with Multiple GitHub Pull Requests
+------------------------------------------
 
-      $ hg pull upstream
-      $ hg update -r "remote(yt, 'upstream')"
-
-After the above steps, your local repository should be at the current head of
-the ``yt`` branch in the main yt repository.  If you find yourself doing this a
-lot, it may be worth aliasing this task in your ``hgrc`` file by adding
-something like::
-
-  [alias]
-  ytupdate = update -r "remote(yt, 'upstream')"
-
-And then you can just issue ``hg ytupdate`` to get at the current head of the
-``yt`` branch on main yt repository.
-
-Make sure you are on the branch you want to be on, and then you can make changes
-and ``hg commit`` them.  If you prefer working with `bookmarks
-<http://mercurial-scm.org/wiki/Bookmarks>`_, you may want to make a bookmark
-before committing your changes, such as ``hg bookmark mybookmark``.
-
-To push your changes on a bookmark to bitbucket, you can issue the following
-command:
-
-.. code-block:: bash
-
-    $ hg push -B myfeature https://bitbucket.org/YourUsername/Your_yt
-
-The ``-B`` means "publish my bookmark, the changeset the bookmark is pointing
-at, and any ancestors of that changeset that aren't already on the remote
-server".
-
-To push to your fork on BitBucket if you didn't use a bookmark, you issue the
-following:
-
-.. code-block:: bash
-
-  $ hg push -r . -f https://bitbucket.org/YourUsername/Your_yt
-
-The ``-r .`` means "push only the commit I'm standing on and any ancestors."
-The ``-f`` is to force Mecurial to do the push since we are creating a new
-remote head without a bookmark.
-
-You can then go to the BitBucket interface and issue a new pull request based on
-your last changes, as usual.
+Dealing with multiple pull requests on GitHub is straightforward. Development on
+one feature should be isolated in one named branch, say ``feature_1`` while
+development of another feature should be in another named branch, say
+``feature_2``. A push to remote ``feature_1`` will automatically update any
+active PR for which ``feature_1`` is a pointer to the ``HEAD`` commit. A push to
+``feature_1`` *will not* update any pull requests involving ``feature_2``.
 
 .. _code-style-guide:
 
@@ -763,11 +710,11 @@
     $ pip install flake8
 
 And then navigate to the root of the yt repository and run ``flake8`` on the
-``yt`` folder:
+``yt`` subdirectory:
 
 .. code-block:: bash
 
-    $ cd $YT_HG
+    $ cd yt-git
     $ flake8 ./yt
 
 This will print out any ``flake8`` errors or warnings that your newly added code
@@ -795,7 +742,7 @@
    (something_else))`` should be rewritten as
    ``if something and something_else``. Python is more forgiving than C.
  * Avoid copying memory when possible. For example, don't do
-   ``a = a.reshape(3,4)`` when ``a.shape = (3,4)`` will do, and ``a = a * 3``
+   ``a = a.reshape(3, 4)`` when ``a.shape = (3, 4)`` will do, and ``a = a * 3``
    should be ``np.multiply(a, 3, a)``.
  * In general, avoid all double-underscore method names: ``__something`` is
    usually unnecessary.
@@ -941,13 +888,13 @@
     use the function.  Use the variables 'ds' for the dataset, 'pc' for
     a plot collection, 'c' for a center, and 'L' for a vector.
 
-    >>> a=[1,2,3]
-    >>> print [x + 3 for x in a]
+    >>> a = [1, 2, 3]
+    >>> print([x + 3 for x in a])
     [4, 5, 6]
-    >>> print "a\n\nb"
+    >>> print("a\n\nb")
     a
+
     b
-
     """
 
 Variable Names and Enzo-isms

diff -r 743fb233d5a830758d29aceb739cc87e34a7e5b1 -r f869c067e20c5186e3f8597ad0b1818fef0cfe68 clean.sh
--- a/clean.sh
+++ b/clean.sh
@@ -1,1 +1,1 @@
-hg --config extensions.purge= purge --all yt
+git clean -f -d -x yt

diff -r 743fb233d5a830758d29aceb739cc87e34a7e5b1 -r f869c067e20c5186e3f8597ad0b1818fef0cfe68 doc/Makefile
--- a/doc/Makefile
+++ b/doc/Makefile
@@ -33,20 +33,24 @@
 	@echo "  linkcheck   to check all external links for integrity"
 	@echo "  doctest     to run all doctests embedded in the documentation (if enabled)"
 	@echo "  clean 	     to remove the build directory"
-	@echo "  fullclean   to remove the build directory and autogenerated api docs"
 	@echo "  recipeclean to remove files produced by running the cookbook scripts"
 
 clean:
 	-rm -rf $(BUILDDIR)/*
+	-rm -rf source/reference/api/yt.*
+	-rm -rf source/reference/api/modules.rst
 
-fullclean:
-	-rm -rf $(BUILDDIR)/*
-	-rm -rf source/reference/api/generated
+fullclean: clean
 
 recipeclean:
 	-rm -rf _temp/*.done source/cookbook/_static/*
 
 html:
+ifneq ($(READTHEDOCS),True)
+	SPHINX_APIDOC_OPTIONS=members,undoc-members,inherited-members,show-inheritance sphinx-apidoc \
+        -o source/reference/api/ \
+        -e ../yt ../yt/extern/* $(shell find ../yt -name "*tests*" -type d) ../yt/utilities/voropp*
+endif
 	$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
 	@echo
 	@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."

diff -r 743fb233d5a830758d29aceb739cc87e34a7e5b1 -r f869c067e20c5186e3f8597ad0b1818fef0cfe68 doc/extensions/pythonscript_sphinxext.py
--- a/doc/extensions/pythonscript_sphinxext.py
+++ b/doc/extensions/pythonscript_sphinxext.py
@@ -1,4 +1,5 @@
 import tempfile
+import time
 import os
 import glob
 import shutil
@@ -37,12 +38,16 @@
             f.write(content)
 
         # Use sphinx logger?
+        uid = uuid.uuid4().hex[:8]
         print("")
+        print(">> Contents of the script: %s" % uid)
         print(content)
         print("")
 
+        start = time.time()
         subprocess.call(['python', 'temp.py'])
-
+        print(">> The execution of the script %s took %f s" %
+              (uid, time.time() - start))
         text = ''
         for im in sorted(glob.glob("*.png")):
             text += get_image_tag(im, image_dir, image_rel_dir)

diff -r 743fb233d5a830758d29aceb739cc87e34a7e5b1 -r f869c067e20c5186e3f8597ad0b1818fef0cfe68 doc/extensions/yt_cookbook.py
--- a/doc/extensions/yt_cookbook.py
+++ b/doc/extensions/yt_cookbook.py
@@ -23,7 +23,7 @@
 
     return retdict
 
-data_patterns = ["*.h5", "*.out", "*.dat"]
+data_patterns = ["*.h5", "*.out", "*.dat", "*.mp4"]
 
 class CookbookScript(Directive):
     required_arguments = 1

diff -r 743fb233d5a830758d29aceb739cc87e34a7e5b1 -r f869c067e20c5186e3f8597ad0b1818fef0cfe68 doc/extensions/yt_showfields.py
--- /dev/null
+++ b/doc/extensions/yt_showfields.py
@@ -0,0 +1,32 @@
+import subprocess
+import sys
+from sphinx.util.compat import Directive
+
+def setup(app):
+    app.add_directive('yt_showfields', ShowFields)
+    setup.app = app
+    setup.config = app.config
+    setup.confdir = app.confdir
+    
+    retdict = dict(
+        version='1.0',
+        parallel_read_safe=True,
+        parallel_write_safe=True
+    )
+
+    return retdict
+
+class ShowFields(Directive):
+    required_arguments = 0
+    optional_arguments = 0
+    parallel_read_safe = True
+    parallel_write_safe = True
+
+    def run(self):
+        rst_file = self.state_machine.document.attributes['source']
+        lines = subprocess.check_output(
+            [sys.executable, './helper_scripts/show_fields.py'])
+        lines = lines.decode('utf8')
+        lines = lines.split('\n')
+        self.state_machine.insert_input(lines, rst_file)
+        return []

diff -r 743fb233d5a830758d29aceb739cc87e34a7e5b1 -r f869c067e20c5186e3f8597ad0b1818fef0cfe68 doc/helper_scripts/run_recipes.py
--- a/doc/helper_scripts/run_recipes.py
+++ b/doc/helper_scripts/run_recipes.py
@@ -12,7 +12,7 @@
 from multiprocessing import Pool
 from yt.config import ytcfg
 
-FPATTERNS = ['*.png', '*.txt', '*.h5', '*.dat']
+FPATTERNS = ['*.png', '*.txt', '*.h5', '*.dat', '*.mp4']
 DPATTERNS = ['LC*', 'LR', 'DD0046']
 BADF = ['cloudy_emissivity.h5', 'apec_emissivity.h5',
         'xray_emissivity.h5', 'AMRGridData_Slice_x_density.png']

diff -r 743fb233d5a830758d29aceb739cc87e34a7e5b1 -r f869c067e20c5186e3f8597ad0b1818fef0cfe68 doc/helper_scripts/show_fields.py
--- a/doc/helper_scripts/show_fields.py
+++ b/doc/helper_scripts/show_fields.py
@@ -1,17 +1,14 @@
 import inspect
-from yt.mods import *
-from yt.testing import *
+from yt.testing import fake_random_ds
 import numpy as np
 from yt.utilities.cosmology import \
      Cosmology
-from yt.utilities.definitions import \
-    mpc_conversion, sec_conversion
 from yt.frontends.stream.fields import \
     StreamFieldInfo
 from yt.frontends.api import _frontends
 from yt.fields.derived_field import NullFunc
 import yt.frontends as frontends_module
-from yt.units.yt_array import YTArray, Unit
+from yt.units.yt_array import Unit
 from yt.units import dimensions
 
 fields, units = [], []
@@ -35,10 +32,11 @@
         return field
     return field[1]
 
+
 np.random.seed(int(0x4d3d3d3))
 units = [base_ds._get_field_info(*f).units for f in fields]
 fields = [_strip_ftype(f) for f in fields]
-ds = fake_random_ds(16, fields=fields, units=units, particles=True)
+ds = fake_random_ds(16, fields=fields, units=units, particles=1)
 ds.parameters["HydroMethod"] = "streaming"
 ds.parameters["EOSType"] = 1.0
 ds.parameters["EOSSoundSpeed"] = 1.0
@@ -160,6 +158,7 @@
                 print("  " + line)
             print()
 
+
 ds.index
 print_all_fields(ds.field_info)
 
@@ -183,6 +182,7 @@
         self.name = "(%s, '%s')" % (ftype, name)
         self.ptype = ptype
 
+
 current_frontends = [f for f in _frontends if f not in ["stream"]]
 
 for frontend in current_frontends:
@@ -194,7 +194,7 @@
         # Drop duplicate entry for GadgetHDF5, add special case for FieldInfo
         # entry
         dataset_names = ['GadgetDataset']
-        field_info_names = ['SPHFieldInfo']
+        field_info_names = ['GadgetFieldInfo']
     elif frontend == "boxlib":
         field_info_names = []
         for d in dataset_names:

diff -r 743fb233d5a830758d29aceb739cc87e34a7e5b1 -r f869c067e20c5186e3f8597ad0b1818fef0cfe68 doc/install_script.sh
--- a/doc/install_script.sh
+++ b/doc/install_script.sh
@@ -30,7 +30,7 @@
 # INST_CONDA=0
 # INST_YT_SOURCE=1
 
-BRANCH="yt" # This is the branch to which we will forcibly update.
+BRANCH="master" # This is the branch we will install from for source installs
 
 # What follows are some other options that you may or may not need to change.
 
@@ -44,11 +44,12 @@
 
 # These options can be set to customize the installation.
 
-INST_PY3=0          # Install Python 3 along with Python 2. If this is turned
+INST_PY3=1          # Install Python 3 instead of Python 2. If this is turned
                     # on, all Python packages (including yt) will be installed
-                    # in Python 3 (except Mercurial, which requires Python 2).
-INST_HG=1           # Install Mercurial or not?  If hg is not already
-                    # installed, yt cannot be installed from source.
+                    # in Python 3.
+INST_GIT=1          # Install git or not?  If git is not already installed, yt
+                    # cannot be installed from source. Ignored if INST_CONDA=0
+INST_HG=0           # Install Mercurial or not? Ignored if INST_CONDA=0.
 INST_EMBREE=0       # Install dependencies needed for Embree-accelerated 
                     # ray tracing
 
@@ -148,6 +149,10 @@
         echo "Please set INST_YT_SOURCE to 1 and re-run."
         exit 1
     fi
+    if [ $INST_GIT -eq 1 ]
+    then
+        INST_GIT=0
+    fi
     DEST_SUFFIX="yt-`uname -m`"
 fi
 
@@ -200,7 +205,7 @@
 {
     CONFIG_FILE=${DEST_DIR}/.yt_config
 
-    echo INST_HG=${INST_HG} > ${CONFIG_FILE}
+    echo INST_GIT=${INST_GIT} > ${CONFIG_FILE}
     echo INST_ZLIB=${INST_ZLIB} >> ${CONFIG_FILE}
     echo INST_BZLIB=${INST_BZLIB} >> ${CONFIG_FILE}
     echo INST_PNG=${INST_PNG} >> ${CONFIG_FILE}
@@ -397,9 +402,10 @@
         echo "  * gcc-{,c++,gfortran}"
         echo "  * make"
         echo "  * patch"
+        echo "  * git"
         echo
         echo "You can accomplish this by executing:"
-        echo "$ sudo yum install gcc gcc-c++ gcc-gfortran make patch zip"
+        echo "$ sudo yum install gcc gcc-c++ gcc-gfortran make patch zip git"
         echo "$ sudo yum install ncurses-devel uuid-devel openssl-devel readline-devel"
     fi
     if [ -f /etc/SuSE-release ] && [ `grep --count SUSE /etc/SuSE-release` -gt 0 ]
@@ -413,11 +419,12 @@
         echo "  * libuuid-devel"
         echo "  * zip"
         echo "  * gcc-c++"
+        echo "  * git"
         echo
         echo "You can accomplish this by executing:"
         echo
         echo "$ sudo zypper install -t pattern devel_C_C++"
-        echo "$ sudo zypper install gcc-c++ libopenssl-devel libuuid-devel zip"
+        echo "$ sudo zypper install git-core gcc-c++ libopenssl-devel libuuid-devel zip"
         echo
         echo "I am also setting special configure arguments to Python to"
         echo "specify control lib/lib64 issues."
@@ -437,10 +444,11 @@
         echo "  * uuid-dev"
         echo "  * libfreetype6-dev"
         echo "  * tk-dev"
+        echo "  * git"
         echo
         echo "You can accomplish this by executing:"
         echo
-        echo "$ sudo apt-get install libssl-dev build-essential libncurses5 libncurses5-dev zip uuid-dev libfreetype6-dev tk-dev"
+        echo "$ sudo apt-get install libssl-dev build-essential libncurses5 libncurses5-dev zip uuid-dev libfreetype6-dev tk-dev git"
         echo
         echo
         echo " Additionally, if you want to put yt's lib dir in your LD_LIBRARY_PATH"
@@ -566,9 +574,9 @@
 get_willwont ${INST_PY3}
 echo "be installing Python 3"
 
-printf "%-18s = %s so I " "INST_HG" "${INST_HG}"
-get_willwont ${INST_HG}
-echo "be installing Mercurial"
+printf "%-18s = %s so I " "INST_GIT" "${INST_GIT}"
+get_willwont ${INST_GIT}
+echo "be installing git"
 
 printf "%-18s = %s so I " "INST_EMBREE" "${INST_EMBREE}"
 get_willwont ${INST_EMBREE}
@@ -640,10 +648,12 @@
 echo "If you'd rather stop, maybe think things over, even grab a sandwich, "
 echo "hit Ctrl-C."
 echo
+
 if [ $INST_YT_SOURCE -ne 0 ]
 then
    host_specific
 fi
+
 if [ $INST_CONDA -eq 0 ]
 then
     if [ ${USED_CONFIG} ]
@@ -679,7 +689,7 @@
 
 if [ $INST_PY3 -eq 1 ]
 then
-     PYTHON_EXEC='python3.5'
+     PYTHON_EXEC='python3'
 else 
      PYTHON_EXEC='python2.7'
 fi
@@ -698,12 +708,7 @@
     [ ! -e $LIB/extracted ] && tar xfz $LIB.tar.gz
     touch $LIB/extracted
     BUILD_ARGS=""
-    if [[ $LIB =~ .*mercurial.* ]]
-    then
-        PYEXE="python2.7"
-    else
-        PYEXE=${PYTHON_EXEC}
-    fi
+    PYEXE=${PYTHON_EXEC}
     case $LIB in
         *h5py*)
             pushd $LIB &> /dev/null
@@ -836,10 +841,9 @@
     LAPACK='lapack-3.4.2'
     PNG='libpng-1.6.3'
     MATPLOTLIB='matplotlib-1.5.1'
-    MERCURIAL='mercurial-3.7.3'
     NOSE='nose-1.3.7'
     NUMPY='numpy-1.11.0'
-    PYTHON_HGLIB='python-hglib-2.0'
+    GITPYTHON='GitPython-2.1.3'
     ROCKSTAR='rockstar-0.99.6'
     SCIPY='scipy-0.17.0'
     SQLITE='sqlite-autoconf-3071700'
@@ -867,10 +871,9 @@
     echo '8770214491e31f0a7a3efaade90eee7b0eb20a8a6ab635c5f854d78263f59a1849133c14ef5123d01023f0110cbb9fc6f818da053c01277914ae81473430a952  lapack-3.4.2.tar.gz' > lapack-3.4.2.tar.gz.sha512
     echo '887582e5a22e4cde338aa8fec7a89f6dd31f2f02b8842735f00f970f64582333fa03401cea6d01704083403c7e8b7ebc26655468ce930165673b33efa4bcd586  libpng-1.6.3.tar.gz' > libpng-1.6.3.tar.gz.sha512
     echo 'a0e78b5027a3a49cf8e77dc0d26f5f380dcd80f7b309b6121199acd5e1d94f48482864a9eee3bd397f7ac6f07fe1d3c21bf517217df3c72e8e3d105b7c2ae58e  matplotlib-1.5.1.tar.gz' > matplotlib-1.5.1.tar.gz.sha512
-    echo '7f9f97229e40c7092c16ccf227b19a08a9839d8ce19a9d057341fff75876bff32241ee9aa10eab293f779ea3e8a1d97577597187bd96251fb499cbb1075a82cf  mercurial-3.7.3.tar.gz' > mercurial-3.7.3.tar.gz.sha512
     echo 'e65c914f621f8da06b9ab11a0ff2763d6e29b82ce2aaed56da0e3773dc899d9deb1f20015789d44c65a5dad7214520f5b659b3f8d7695fb207ad3f78e5cf1b62  nose-1.3.7.tar.gz' > nose-1.3.7.tar.gz.sha512
     echo '92c1889397ad013e25da3a0657fc01e787d528fc19c29cc2acd286c3f07d41b984252583457b1b9259fc303afbe9694565cdcf5752eb4ecb950cc7a99ec1ad8b  numpy-1.11.0.tar.gz' > numpy-1.11.0.tar.gz.sha512
-    echo '647cc82424783efc3d74540e34976af66acc35fc36d66afba169508946cc62027910c7e41dc9d11ec88c15d6b1e113ce22c2781711ea324de58db3b24d5079c4  python-hglib-2.0.tar.gz' > python-hglib-2.0.tar.gz.sha512
+    echo '918ff1765a85a818619165c2bcbb0d417f35c979c2f42f1bb7e41636696c0cb4d6837725f3655fbdfebea966476d1255ee18adabe9ed5536455b63336a1f399d  GitPython-2.1.3.tar.gz' > GitPython-2.1.3.tar.gz.sha512
     echo 'de6409d75a3ff3cf1e5391d3b09126f0bc7e1a40a15f9bee244195638fe2f8481fca032896d8534623e6122ff59aaf669664e27ff89cf1b094a5ce7312f220b7  scipy-0.17.0.tar.gz' > scipy-0.17.0.tar.gz.sha512
     echo '96f3e51b46741450bc6b63779c10ebb4a7066860fe544385d64d1eda52592e376a589ef282ace2e1df73df61c10eab1a0d793abbdaf770e60289494d4bf3bcb4  sqlite-autoconf-3071700.tar.gz' > sqlite-autoconf-3071700.tar.gz.sha512
     echo '977db6e9bc6a5918cceb255981a57e85e7060c0922aefd2968b004d25d704e25a5cb5bbe09eb387e8695581e23e2825d9c40310068fe25ece7e9c23037a21f39  sympy-1.0.tar.gz' > sympy-1.0.tar.gz.sha512
@@ -887,16 +890,19 @@
     [ $INST_SCIPY -eq 1 ] && get_ytproject $SCIPY.tar.gz
     [ $INST_SCIPY -eq 1 ] && get_ytproject blas.tar.gz
     [ $INST_SCIPY -eq 1 ] && get_ytproject $LAPACK.tar.gz
-    [ $INST_HG -eq 1 ] && get_ytproject $MERCURIAL.tar.gz
-    [ $INST_PY3 -eq 1 ] && get_ytproject $PYTHON3.tgz
+    if [ $INST_PY3 -eq 1 ]
+    then
+        get_ytproject $PYTHON3.tgz
+    else
+        get_ytproject $PYTHON2.tgz
+    fi
     [ $INST_H5PY -eq 1 ] && get_ytproject $H5PY.tar.gz
     [ $INST_NOSE -eq 1 ] && get_ytproject $NOSE.tar.gz
     [ $INST_ASTROPY -eq 1 ] && get_ytproject $ASTROPY.tar.gz
-    get_ytproject $PYTHON2.tgz
     get_ytproject $NUMPY.tar.gz
     get_ytproject $MATPLOTLIB.tar.gz
     get_ytproject $CYTHON.tar.gz
-    get_ytproject $PYTHON_HGLIB.tar.gz
+    get_ytproject $GITPYTHON.tar.gz
     get_ytproject $SYMPY.tar.gz
     get_ytproject $SETUPTOOLS.tar.gz
 
@@ -936,7 +942,7 @@
             cd $ZLIB
             ( ./configure --shared --prefix=${DEST_DIR}/ 2>&1 ) 1>> ${LOG_FILE} || do_exit
             ( make install 2>&1 ) 1>> ${LOG_FILE} || do_exit
-            ( make clean 2>&1) 1>> ${LOG_FILE} || do_exit
+            ( make clean 2>&1 ) 1>> ${LOG_FILE} || do_exit
             touch done
             cd ..
         fi
@@ -1016,37 +1022,11 @@
         fi
     fi
 
-    if [ ! -e $PYTHON2/done ]
-    then
-        echo "Installing Python 2. This may take a while, but don't worry. yt loves you."
-        [ ! -e $PYTHON2 ] && tar xfz $PYTHON2.tgz
-        cd $PYTHON2
-        ( ./configure --prefix=${DEST_DIR}/ ${PYCONF_ARGS} 2>&1 ) 1>> ${LOG_FILE} || do_exit
-        
-        ( make ${MAKE_PROCS} 2>&1 ) 1>> ${LOG_FILE} || do_exit
-        ( make install 2>&1 ) 1>> ${LOG_FILE} || do_exit
-        ( ln -sf ${DEST_DIR}/bin/python2.7 ${DEST_DIR}/bin/pyyt 2>&1 ) 1>> ${LOG_FILE}
-        ( make clean 2>&1) 1>> ${LOG_FILE} || do_exit
-        touch done
-        cd ..
-    fi
-
-    ( ${DEST_DIR}/bin/python -c "import _ssl" 2>&1 ) 1>> ${LOG_FILE}
-    RESULT=$?
-    if  [ $RESULT -ne 0 ]
-    then
-        echo "Unable to import the python SSL bindings."
-        echo "This means that OpenSSL is not installed or your system's OpenSSL"
-        echo "installation is out of date."
-        echo "Please install OpenSSL or set INST_CONDA=1"
-        do_exit
-    fi
-
     if [ $INST_PY3 -eq 1 ]
     then
         if [ ! -e $PYTHON3/done ]
         then
-            echo "Installing Python 3. Because two Pythons are better than one."
+            echo "Installing Python 3"
             [ ! -e $PYTHON3 ] && tar xfz $PYTHON3.tgz
             cd $PYTHON3
             ( ./configure --prefix=${DEST_DIR}/ ${PYCONF_ARGS} 2>&1 ) 1>> ${LOG_FILE} || do_exit
@@ -1060,6 +1040,31 @@
             touch done
             cd ..
         fi
+    else
+        if [ ! -e $PYTHON2/done ]
+        then
+            echo "Installing Python 2. This may take a while, but don't worry. yt loves you."
+            [ ! -e $PYTHON2 ] && tar xfz $PYTHON2.tgz
+            cd $PYTHON2
+            ( ./configure --prefix=${DEST_DIR}/ ${PYCONF_ARGS} 2>&1 ) 1>> ${LOG_FILE} || do_exit
+            ( make ${MAKE_PROCS} 2>&1 ) 1>> ${LOG_FILE} || do_exit
+            ( make install 2>&1 ) 1>> ${LOG_FILE} || do_exit
+            ( ln -sf ${DEST_DIR}/bin/python2.7 ${DEST_DIR}/bin/pyyt 2>&1 ) 1>> ${LOG_FILE}
+            ( make clean 2>&1) 1>> ${LOG_FILE} || do_exit
+            touch done
+            cd ..
+        fi
+    fi
+
+    ( ${DEST_DIR}/bin/python -c "import _ssl" 2>&1 ) 1>> ${LOG_FILE}
+    RESULT=$?
+    if  [ $RESULT -ne 0 ]
+    then
+        echo "Unable to import the python SSL bindings."
+        echo "This means that OpenSSL is not installed or your system's OpenSSL"
+        echo "installation is out of date."
+        echo "Please install OpenSSL or set INST_CONDA=1"
+        do_exit
     fi
 
     export PYTHONPATH=${DEST_DIR}/lib/${PYTHON_EXEC}/site-packages/
@@ -1067,19 +1072,12 @@
     # Install setuptools
     do_setup_py $SETUPTOOLS
 
-    if [ $INST_HG -eq 1 ]
+    if type -p git &>/dev/null
     then
-        do_setup_py $MERCURIAL
-        export HG_EXEC=${DEST_DIR}/bin/hg
+        GIT_EXE="git"
     else
-        # We assume that hg can be found in the path.
-        if type -P hg &>/dev/null
-        then
-            export HG_EXEC=hg
-        else
-            echo "Cannot find mercurial.  Please set INST_HG=1."
-            do_exit
-        fi
+        echo "Cannot find git. Please install git."
+        do_exit
     fi
 
     if [ -z "$YT_DIR" ]
@@ -1090,20 +1088,14 @@
         elif [ -e $ORIG_PWD/../yt/mods.py ]
         then
             YT_DIR=`dirname $ORIG_PWD`
-        elif [ ! -e yt-hg ]
+        elif [ ! -e yt-git ]
         then
             echo "Cloning yt"
-            YT_DIR="$PWD/yt-hg/"
-            ( ${HG_EXEC} --debug clone https://bitbucket.org/yt_analysis/yt-supplemental/ 2>&1 ) 1>> ${LOG_FILE}
-            # Recently the hg server has had some issues with timeouts.  In lieu of
-            # a new webserver, we are now moving to a three-stage process.
-            # First we clone the repo, but only up to r0.
-            ( ${HG_EXEC} --debug clone https://bitbucket.org/yt_analysis/yt/ ./yt-hg 2>&1 ) 1>> ${LOG_FILE}
-            # Now we update to the branch we're interested in.
-            ( ${HG_EXEC} -R ${YT_DIR} up -C ${BRANCH} 2>&1 ) 1>> ${LOG_FILE}
-        elif [ -e yt-hg ]
+            YT_DIR="$PWD/yt-git/"
+            ( ${GIT_EXE} clone https://github.com/yt-project/yt/ ${YT_DIR} 2>&1 ) 1>> ${LOG_FILE}
+        elif [ -e yt-git ]
         then
-            YT_DIR="$PWD/yt-hg/"
+            YT_DIR="$PWD/yt-git/"
         fi
         echo Setting YT_DIR=${YT_DIR}
     fi
@@ -1206,7 +1198,7 @@
     then
         do_setup_py $ASTROPY
     fi
-    do_setup_py $PYTHON_HGLIB
+    do_setup_py $GITPYTHON
     do_setup_py $SYMPY
     [ $INST_PYX -eq 1 ] && do_setup_py $PYX
 
@@ -1220,11 +1212,9 @@
             echo "Building Rockstar"
             if [ ! -e rockstar ]
             then
-                ( hg clone http://bitbucket.org/MatthewTurk/rockstar 2>&1 ) 1>> ${LOG_FILE}
+                ( ${GIT_EXE} clone https://github.com/yt-project/rockstar 2>&1 ) 1>> ${LOG_FILE}
             fi
             cd rockstar
-            ( hg pull 2>&1 ) 1>> ${LOG_FILE}
-            ( hg up -C tip 2>&1 ) 1>> ${LOG_FILE}
             ( make lib 2>&1 ) 1>> ${LOG_FILE} || do_exit
             cp librockstar.so ${DEST_DIR}/lib
             ROCKSTAR_DIR=${DEST_DIR}/src/rockstar
@@ -1234,10 +1224,9 @@
         fi
     fi
     
-    echo "Doing yt update, wiping local changes and updating to branch ${BRANCH}"
     MY_PWD=`pwd`
     cd $YT_DIR
-    ( ${HG_EXEC} pull 2>1 && ${HG_EXEC} up -C 2>1 ${BRANCH} 2>&1 ) 1>> ${LOG_FILE}
+    ( ${GIT_EXE} pull 2>1 && ${GIT_EXE} checkout ${BRANCH} 2>&1 ) 1>> ${LOG_FILE}
 
     echo "Installing yt"
     [ $INST_PNG -eq 1 ] && echo $PNG_DIR > png.cfg
@@ -1300,14 +1289,6 @@
         echo
         echo "The source for yt is located at:"
         echo "    $YT_DIR"
-        if [ $INST_HG -eq 1 ]
-        then
-            echo
-            echo "Mercurial has also been installed:"
-            echo
-            echo "$DEST_DIR/bin/hg"
-            echo
-        fi
         echo
         echo "For support, see the website and join the mailing list:"
         echo
@@ -1353,6 +1334,10 @@
             echo "Going with x86_64 architecture."
             MINICONDA_OS="Linux-x86_64"
         fi
+    else
+        echo "The yt install script is not supported on the ${MYOS}"
+        echo "operating system."
+        exit 1
     fi
 
     if [ $INST_PY3 -eq 1 ]
@@ -1399,6 +1384,11 @@
     YT_DEPS+=('jupyter')
     YT_DEPS+=('ipython')
     YT_DEPS+=('sphinx')
+    if [ ${INST_GIT} -eq 1 ]
+    then
+        YT_DEPS+=('git')
+        YT_DEPS+=('gitpython')
+    fi
     if [ $INST_H5PY -ne 0 ]
     then
         YT_DEPS+=('h5py')
@@ -1418,7 +1408,7 @@
         YT_DEPS+=('astropy')
     fi
     YT_DEPS+=('conda-build')
-    if [ $INST_PY3 -eq 0 ]
+    if [ $INST_PY3 -eq 0 ] && [ $INST_HG -eq 1 ]
     then
        YT_DEPS+=('mercurial')
     fi
@@ -1431,22 +1421,22 @@
     
     log_cmd ${DEST_DIR}/bin/conda update --yes conda
     
+    GIT_EXE=${DEST_DIR}/bin/git
+
     log_cmd echo "DEPENDENCIES" ${YT_DEPS[@]}
     for YT_DEP in "${YT_DEPS[@]}"; do
         echo "Installing $YT_DEP"
-        log_cmd ${DEST_DIR}/bin/conda install --yes ${YT_DEP}
+        log_cmd ${DEST_DIR}/bin/conda install -c conda-forge --yes ${YT_DEP}
     done
 
-    if [ $INST_PY3 -eq 1 ]
+    if [ $INST_PY3 -eq 1 ] && [ $INST_HG -eq 1 ]
     then
         echo "Installing mercurial"
         log_cmd ${DEST_DIR}/bin/conda create -y -n py27 python=2.7 mercurial
         log_cmd ln -s ${DEST_DIR}/envs/py27/bin/hg ${DEST_DIR}/bin
     fi
 
-    log_cmd ${DEST_DIR}/bin/pip install python-hglib
-
-    log_cmd ${DEST_DIR}/bin/hg clone https://bitbucket.org/yt_analysis/yt_conda ${DEST_DIR}/src/yt_conda
+    log_cmd ${GIT_EXE} clone https://github.com/yt-project/yt_conda ${DEST_DIR}/src/yt_conda
     
     if [ $INST_EMBREE -eq 1 ]
     then
@@ -1480,7 +1470,7 @@
     if [ $INST_ROCKSTAR -eq 1 ]
     then
         echo "Building Rockstar"
-        ( ${DEST_DIR}/bin/hg clone http://bitbucket.org/MatthewTurk/rockstar ${DEST_DIR}/src/rockstar/ 2>&1 ) 1>> ${LOG_FILE}
+        ( ${GIT_EXE} clone https://github.com/yt-project/rockstar ${DEST_DIR}/src/rockstar/ 2>&1 ) 1>> ${LOG_FILE}
         ROCKSTAR_PACKAGE=$(${DEST_DIR}/bin/conda build ${DEST_DIR}/src/yt_conda/rockstar --output)
         log_cmd ${DEST_DIR}/bin/conda build ${DEST_DIR}/src/yt_conda/rockstar
         log_cmd ${DEST_DIR}/bin/conda install $ROCKSTAR_PACKAGE
@@ -1504,9 +1494,9 @@
         log_cmd ${DEST_DIR}/bin/conda install -c conda-forge --yes yt
     else
         echo "Building yt from source"
-        YT_DIR="${DEST_DIR}/src/yt-hg"
-        log_cmd ${DEST_DIR}/bin/hg clone https://bitbucket.org/yt_analysis/yt ${YT_DIR}
-        log_cmd ${DEST_DIR}/bin/hg -R ${YT_DIR} up -C ${BRANCH}
+        YT_DIR="${DEST_DIR}/src/yt-git"
+        log_cmd ${GIT_EXE} clone https://github.com/yt-project/yt ${YT_DIR}
+        log_cmd ${GIT_EXE} -C ${YT_DIR} checkout ${BRANCH}
         if [ $INST_EMBREE -eq 1 ]
         then
             echo $DEST_DIR > ${YT_DIR}/embree.cfg

diff -r 743fb233d5a830758d29aceb739cc87e34a7e5b1 -r f869c067e20c5186e3f8597ad0b1818fef0cfe68 doc/source/about/index.rst
--- a/doc/source/about/index.rst
+++ b/doc/source/about/index.rst
@@ -16,7 +16,7 @@
 it has grown to handle any kind of data represented in a 2D or 3D volume.
 yt is an Python-based open source project and is open for anyone to use or
 contribute code.  The entire source code and history is available to all
-at https://bitbucket.org/yt_analysis/yt .
+at http://github.com/yt-project/yt .
 
 .. _who-is-yt:
 
@@ -31,7 +31,7 @@
 `our members website. <http://yt-project.org/members.html>`_
 
 For an up-to-date list of everyone who has contributed to the yt codebase,
-see the current `CREDITS <http://bitbucket.org/yt_analysis/yt/src/yt/CREDITS>`_ file.
+see the current `CREDITS <https://github.com/yt-project/yt/blob/master/CREDITS>`_ file.
 For a more detailed breakup of contributions made by individual users, see out
 `Open HUB page <https://www.openhub.net/p/yt_amr/contributors?query=&sort=commits>`_.
 

diff -r 743fb233d5a830758d29aceb739cc87e34a7e5b1 -r f869c067e20c5186e3f8597ad0b1818fef0cfe68 doc/source/analyzing/Particle_Trajectories.ipynb
--- a/doc/source/analyzing/Particle_Trajectories.ipynb
+++ b/doc/source/analyzing/Particle_Trajectories.ipynb
@@ -279,9 +279,9 @@
    "source": [
     "fig = plt.figure(figsize=(8.0, 8.0))\n",
     "ax = fig.add_subplot(111, projection='3d')\n",
-    "ax.plot(trajs[\"particle_position_x\"][100], trajs[\"particle_position_z\"][100], trajs[\"particle_position_z\"][100])\n",
-    "ax.plot(trajs[\"particle_position_x\"][8], trajs[\"particle_position_z\"][8], trajs[\"particle_position_z\"][8])\n",
-    "ax.plot(trajs[\"particle_position_x\"][25], trajs[\"particle_position_z\"][25], trajs[\"particle_position_z\"][25])"
+    "ax.plot(trajs[\"particle_position_x\"][100], trajs[\"particle_position_y\"][100], trajs[\"particle_position_z\"][100])\n",
+    "ax.plot(trajs[\"particle_position_x\"][8], trajs[\"particle_position_y\"][8], trajs[\"particle_position_z\"][8])\n",
+    "ax.plot(trajs[\"particle_position_x\"][25], trajs[\"particle_position_y\"][25], trajs[\"particle_position_z\"][25])"
    ]
   },
   {

diff -r 743fb233d5a830758d29aceb739cc87e34a7e5b1 -r f869c067e20c5186e3f8597ad0b1818fef0cfe68 doc/source/analyzing/analysis_modules/halo_catalogs.rst
--- a/doc/source/analyzing/analysis_modules/halo_catalogs.rst
+++ b/doc/source/analyzing/analysis_modules/halo_catalogs.rst
@@ -481,7 +481,9 @@
 
 A :class:`~yt.analysis_modules.halo_analysis.halo_catalog.HaloCatalog`
 saved to disk can be reloaded as a yt dataset with the
-standard call to ``yt.load``. Any side data, such as profiles, can be reloaded
+standard call to ``yt.load``.  See :ref:`halocatalog` for a demonstration
+of loading and working only with the catalog.
+Any side data, such as profiles, can be reloaded
 with a ``load_profiles`` callback and a call to
 :func:`~yt.analysis_modules.halo_analysis.halo_catalog.HaloCatalog.load`.
 

diff -r 743fb233d5a830758d29aceb739cc87e34a7e5b1 -r f869c067e20c5186e3f8597ad0b1818fef0cfe68 doc/source/analyzing/analysis_modules/halo_mass_function.rst
--- a/doc/source/analyzing/analysis_modules/halo_mass_function.rst
+++ b/doc/source/analyzing/analysis_modules/halo_mass_function.rst
@@ -1,5 +1,12 @@
 .. _halo_mass_function:
 
+.. note::
+
+   This module has been deprecated as it no longer functions correctly and is
+   unmaintained.  The code has been moved to the `yt attic
+   <https://github.com/yt-project/yt_attic>`__. If you'd like to take it
+   over, please do!
+
 Halo Mass Function
 ==================
 

diff -r 743fb233d5a830758d29aceb739cc87e34a7e5b1 -r f869c067e20c5186e3f8597ad0b1818fef0cfe68 doc/source/analyzing/analysis_modules/star_analysis.rst
--- a/doc/source/analyzing/analysis_modules/star_analysis.rst
+++ b/doc/source/analyzing/analysis_modules/star_analysis.rst
@@ -1,5 +1,11 @@
 .. _star_analysis:
 
+.. note::
+
+   This module has been deprecated as it is unmaintained.  The code has been
+   moved to the `yt attic <https://github.com/yt-project/yt_attic>`__.
+   If you'd like to take it over, please do!
+
 Star Particle Analysis
 ======================
 .. sectionauthor:: Stephen Skory <sskory at physics.ucsd.edu>
@@ -209,8 +215,8 @@
 There are two ways to write out the data once the spectrum has been calculated.
 The command ``write_out`` outputs two columns of data:
 
-  1. Wavelength :math:`(\text{\AA})`
-  2. Flux (Luminosity per unit wavelength :math:`(\mathrm{\rm{L}_\odot} / \text{\AA})` , where
+  1. Wavelength (:math:`\text{Angstroms}`)
+  2. Flux (Luminosity per unit wavelength :math:`(\mathrm{\rm{L}_\odot} / \text{Angstrom})` , where
        :math:`\mathrm{\rm{L}_\odot} = 3.826 \cdot 10^{33}\, \mathrm{ergs / s}` ).
 
 and can be called simply, specifying the output file:
@@ -225,7 +231,7 @@
 distribution to. The default is 5200 Angstroms. This command outputs the data
 in two columns:
 
-  1. Wavelength :math:`(\text{\AA})`
+  1. Wavelength :math:`(\text{Angstroms})`
   2. Relative flux normalized to the flux at *flux_norm*.
 
 .. code-block:: python

diff -r 743fb233d5a830758d29aceb739cc87e34a7e5b1 -r f869c067e20c5186e3f8597ad0b1818fef0cfe68 doc/source/analyzing/analysis_modules/sunrise_export.rst
--- a/doc/source/analyzing/analysis_modules/sunrise_export.rst
+++ b/doc/source/analyzing/analysis_modules/sunrise_export.rst
@@ -1,5 +1,11 @@
 .. _sunrise_export:
 
+.. note::
+
+   This module has been deprecated as it is unmaintained.  The code has been
+   moved to the `yt attic <https://github.com/yt-project/yt_attic>`__.
+   If you'd like to take it over, please do!
+
 Exporting to Sunrise
 ====================
 

diff -r 743fb233d5a830758d29aceb739cc87e34a7e5b1 -r f869c067e20c5186e3f8597ad0b1818fef0cfe68 doc/source/analyzing/analysis_modules/two_point_functions.rst
--- a/doc/source/analyzing/analysis_modules/two_point_functions.rst
+++ b/doc/source/analyzing/analysis_modules/two_point_functions.rst
@@ -1,5 +1,11 @@
 .. _two_point_functions:
 
+.. note::
+
+   This module has been deprecated as it is unmaintained.  The code has been
+   moved to the `yt attic <https://github.com/yt-project/yt_attic>`__.
+   If you'd like to take it over, please do!
+
 Two Point Functions
 ===================
 .. sectionauthor:: Stephen Skory <sskory at physics.ucsd.edu>

diff -r 743fb233d5a830758d29aceb739cc87e34a7e5b1 -r f869c067e20c5186e3f8597ad0b1818fef0cfe68 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
@@ -1,3 +1,6 @@
 .. _xray_emission_fields:
 
+X-ray Emission Fields
+=====================
+
 .. notebook:: XrayEmissionFields.ipynb

diff -r 743fb233d5a830758d29aceb739cc87e34a7e5b1 -r f869c067e20c5186e3f8597ad0b1818fef0cfe68 doc/source/analyzing/generating_processed_data.rst
--- a/doc/source/analyzing/generating_processed_data.rst
+++ b/doc/source/analyzing/generating_processed_data.rst
@@ -93,10 +93,10 @@
 
 Profile objects can be created from any data object (see :ref:`data-objects`,
 specifically the section :ref:`available-objects` for more information) and are
-best thought of as distribution calculations.  They can either sum up or
-average one quantity with respect to one or more other quantities, and they do
-this over all the data contained in their source object.  When calculating average
-values, the variance will also be calculated.
+best thought of as distribution calculations.  They can either sum up or average
+one quantity with respect to one or more other quantities, and they do this over
+all the data contained in their source object.  When calculating average values,
+the standard deviation will also be calculated.
 
 To generate a profile, one need only specify the binning fields and the field
 to be profiled.  The binning fields are given together in a list.  The
@@ -131,16 +131,17 @@
 
    print(profile.used)
 
-If a weight field was given, the profile data will represent the weighted mean of
-a field.  In this case, the weighted variance will be calculated automatically and
-can be access via the ``profile.variance`` attribute.
+If a weight field was given, the profile data will represent the weighted mean
+of a field.  In this case, the weighted standard deviation will be calculated
+automatically and can be access via the ``profile.standard_deviation``
+attribute.
 
 .. code-block:: python
 
-   print(profile.variance["gas", "temperature"])
+   print(profile.standard_deviation["gas", "temperature"])
 
-A two-dimensional profile of the total gas mass in bins of density and temperature
-can be created as follows:
+A two-dimensional profile of the total gas mass in bins of density and
+temperature can be created as follows:
 
 .. code-block:: python
 

diff -r 743fb233d5a830758d29aceb739cc87e34a7e5b1 -r f869c067e20c5186e3f8597ad0b1818fef0cfe68 doc/source/analyzing/units/2)_Fields_and_unit_conversion.ipynb
--- a/doc/source/analyzing/units/2)_Fields_and_unit_conversion.ipynb
+++ b/doc/source/analyzing/units/2)_Fields_and_unit_conversion.ipynb
@@ -161,7 +161,7 @@
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "`in_base` can even take a dataset as the argument to convert the `YTArray` into the base units of the dataset:"
+    "`in_base` also takes the `\"code\"` argument to convert the `YTArray` into the base units of the dataset:"
    ]
   },
   {
@@ -170,7 +170,7 @@
    "metadata": {},
    "outputs": [],
    "source": [
-    "print (dd['pressure'].in_base(ds)) # The IsolatedGalaxy dataset from above"
+    "print (dd['pressure'].in_base(\"code\")) # The IsolatedGalaxy dataset from above"
    ]
   },
   {

diff -r 743fb233d5a830758d29aceb739cc87e34a7e5b1 -r f869c067e20c5186e3f8597ad0b1818fef0cfe68 doc/source/analyzing/units/index.rst
--- a/doc/source/analyzing/units/index.rst
+++ b/doc/source/analyzing/units/index.rst
@@ -12,8 +12,8 @@
 and execute the documentation interactively, you need to download the repository
 and start the IPython notebook.
 
-You will then need to navigate to :code:`$YT_HG/doc/source/units` (where $YT_HG
-is the location of a clone of the yt mercurial repository), and then start an
+You will then need to navigate to :code:`$YT_GIT/doc/source/units` (where $YT_GIT
+is the location of a clone of the yt git repository), and then start an
 IPython notebook server:
 
 .. code:: bash

diff -r 743fb233d5a830758d29aceb739cc87e34a7e5b1 -r f869c067e20c5186e3f8597ad0b1818fef0cfe68 doc/source/conf.py
--- a/doc/source/conf.py
+++ b/doc/source/conf.py
@@ -11,9 +11,9 @@
 # All configuration values have a default; values that are commented out
 # serve to show the default.
 
-import sys, os, glob, re
-from sphinx.search import WordCollector
-from docutils.nodes import comment, title, Text, SkipNode
+import sys
+import os
+import glob
 
 on_rtd = os.environ.get("READTHEDOCS", None) == "True"
 
@@ -30,9 +30,9 @@
 # Add any Sphinx extension module names here, as strings. They can be extensions
 # coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
 extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx',
-              'sphinx.ext.pngmath', 'sphinx.ext.viewcode',
+              'sphinx.ext.mathjax', 'sphinx.ext.viewcode',
               'sphinx.ext.napoleon', 'yt_cookbook', 'yt_colormaps',
-              'config_help']
+              'config_help', 'yt_showfields']
 
 if not on_rtd:
     extensions.append('sphinx.ext.autosummary')
@@ -228,13 +228,6 @@
 # If true, show URL addresses after external links.
 #latex_show_urls = False
 
-# Additional stuff for the LaTeX preamble.
-latex_preamble = r"""
-\renewcommand{\AA}{\text{\r{A}}} % Allow \AA in math mode
-\usepackage[utf8]{inputenc}      % Allow unicode symbols in text
-\DeclareUnicodeCharacter {212B} {\AA}                  % Angstrom
-"""
-
 # Documents to append as an appendix to all manuals.
 #latex_appendices = []
 

diff -r 743fb233d5a830758d29aceb739cc87e34a7e5b1 -r f869c067e20c5186e3f8597ad0b1818fef0cfe68 doc/source/cookbook/complex_plots.rst
--- a/doc/source/cookbook/complex_plots.rst
+++ b/doc/source/cookbook/complex_plots.rst
@@ -71,6 +71,13 @@
 
 .. yt_cookbook:: multi_plot_3x2_FRB.py
 
+Time Series Movie
+~~~~~~~~~~~~~~~~~
+
+This shows how to use matplotlib's animation framework with yt plots.
+
+.. yt_cookbook:: matplotlib-animation.py
+
 .. _cookbook-offaxis_projection:
 
 Off-Axis Projection (an alternate method)
@@ -268,6 +275,14 @@
 
 .. yt_cookbook:: opaque_rendering.py
 
+Volume Rendering Multiple Fields
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+You can render multiple fields by adding new ``VolumeSource`` objects to the
+scene for each field you want to render.
+
+.. yt_cookbook:: render_two_fields.py
+
 .. _cookbook-amrkdtree_downsampling:
 
 Downsampling Data for Volume Rendering

diff -r 743fb233d5a830758d29aceb739cc87e34a7e5b1 -r f869c067e20c5186e3f8597ad0b1818fef0cfe68 doc/source/cookbook/matplotlib-animation.py
--- /dev/null
+++ b/doc/source/cookbook/matplotlib-animation.py
@@ -0,0 +1,22 @@
+import yt
+from matplotlib.animation import FuncAnimation
+from matplotlib import rc_context
+
+ts = yt.load('GasSloshingLowRes/sloshing_low_res_hdf5_plt_cnt_*')
+
+plot = yt.SlicePlot(ts[0], 'z', 'density')
+plot.set_zlim('density', 8e-29, 3e-26)
+
+fig = plot.plots['density'].figure
+
+# animate must accept an integer frame number. We use the frame number
+# to identify which dataset in the time series we want to load
+def animate(i):
+    ds = ts[i]
+    plot._switch_ds(ds)
+
+animation = FuncAnimation(fig, animate, frames=len(ts))
+
+# Override matplotlib's defaults to get a nicer looking font
+with rc_context({'mathtext.fontset': 'stix'}):
+    animation.save('animation.mp4')

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

https://bitbucket.org/yt_analysis/yt/commits/18db33731bcd/
Changeset:   18db33731bcd
User:        jzuhone
Date:        2017-05-23 13:18:03+00:00
Summary:     Remove code for datasets with a WCS already, as it is error-prone. Make sure cdelt can be different along the different axes
Affected #:  1 file

diff -r f869c067e20c5186e3f8597ad0b1818fef0cfe68 -r 18db33731bcda7c00e75c0d1936646409e3df38d yt/visualization/fits_image.py
--- a/yt/visualization/fits_image.py
+++ b/yt/visualization/fits_image.py
@@ -508,28 +508,20 @@
         else:
             nx, ny = image_res, image_res
     dx = width[0]/nx
+    dy = width[1]/ny
     crpix = [0.5*(nx+1), 0.5*(ny+1)]
-    if hasattr(ds, "wcs") and not iterable(axis):
-        # This is a FITS dataset, so we use it to construct the WCS
-        cunit = [str(ds.wcs.wcs.cunit[idx]) for idx in axis_wcs[axis]]
-        ctype = [ds.wcs.wcs.ctype[idx] for idx in axis_wcs[axis]]
-        cdelt = [ds.wcs.wcs.cdelt[idx] for idx in axis_wcs[axis]]
-        ctr_pix = center.in_units("code_length")[:ds.dimensionality].v
-        crval = ds.wcs.wcs_pix2world(ctr_pix.reshape(1, ds.dimensionality))[0]
-        crval = [crval[idx] for idx in axis_wcs[axis]]
+    if unit == "unitary":
+        unit = ds.get_smallest_appropriate_unit(ds.domain_width.max())
+    elif unit == "code_length":
+        unit = ds.get_smallest_appropriate_unit(ds.quan(1.0, "code_length"))
+    unit = sanitize_fits_unit(unit)
+    cunit = [unit]*2
+    ctype = ["LINEAR"]*2
+    cdelt = [dx.in_units(unit), dy.in_units(unit)]
+    if iterable(axis):
+        crval = center.in_units(unit)
     else:
-        if unit == "unitary":
-            unit = ds.get_smallest_appropriate_unit(ds.domain_width.max())
-        elif unit == "code_length":
-            unit = ds.get_smallest_appropriate_unit(ds.quan(1.0,"code_length"))
-        unit = sanitize_fits_unit(unit)
-        cunit = [unit]*2
-        ctype = ["LINEAR"]*2
-        cdelt = [dx.in_units(unit)]*2
-        if iterable(axis):
-            crval = center.in_units(unit)
-        else:
-            crval = [center[idx].in_units(unit) for idx in axis_wcs[axis]]
+        crval = [center[idx].in_units(unit) for idx in axis_wcs[axis]]
     if hasattr(data_source, 'to_frb'):
         if iterable(axis):
             frb = data_source.to_frb(width[0], (nx, ny), height=width[1])


https://bitbucket.org/yt_analysis/yt/commits/4d76d482a4f4/
Changeset:   4d76d482a4f4
User:        jzuhone
Date:        2017-05-23 13:18:56+00:00
Summary:     Remove deprecated arguments in FITSOffAxisProjection
Affected #:  1 file

diff -r 18db33731bcda7c00e75c0d1936646409e3df38d -r 4d76d482a4f457fc99e10de98212282125cb049d yt/visualization/fits_image.py
--- a/yt/visualization/fits_image.py
+++ b/yt/visualization/fits_image.py
@@ -792,9 +792,6 @@
          The name of the weighting field.  Set to None for no weight.
     image_res : an int or 2-tuple of ints
         Specify the resolution of the resulting image. 
-    depth_res : integer
-        Deprecated, this is still in the function signature for API
-        compatibility
     north_vector : a sequence of floats
         A vector defining the 'up' direction in the plot.  This
         option sets the orientation of the slicing plane.  If not
@@ -818,9 +815,8 @@
         to project.
     """
     def __init__(self, ds, normal, fields, center='c', width=(1.0, 'unitary'),
-                 weight_field=None, image_res=512, depth_res=256, 
-                 data_source=None, north_vector=None, depth=(1.0,"unitary"), 
-                 no_ghost=False, method='integrate'):
+                 weight_field=None, image_res=512, data_source=None,
+                 north_vector=None, depth=(1.0, "unitary"), method='integrate'):
         fields = ensure_list(fields)
         center, dcenter = ds.coordinates.sanitize_center(center, 4)
         buf = {}
@@ -835,10 +831,8 @@
             source = data_source
         for field in fields:
             buf[field] = off_axis_projection(source, center, normal, wd,
-                                             res, field, no_ghost=no_ghost, 
-                                             north_vector=north_vector, 
-                                             method=method, 
-                                             weight=weight_field).swapaxes(0,1)
+                                             res, field, north_vector=north_vector,
+                                             method=method, weight=weight_field).swapaxes(0,1)
         center = ds.arr([0.0] * 2, 'code_length')
         w, not_an_frb = construct_image(ds, normal, buf, center, width=width, image_res=image_res)
         super(FITSOffAxisProjection, self).__init__(buf, fields=fields, wcs=w)


https://bitbucket.org/yt_analysis/yt/commits/17347910e564/
Changeset:   17347910e564
User:        jzuhone
Date:        2017-05-23 13:20:00+00:00
Summary:     Fix test
Affected #:  1 file

diff -r 4d76d482a4f457fc99e10de98212282125cb049d -r 17347910e56417ad47921b2c3aec0bcf22a45cbf yt/visualization/tests/test_fits_image.py
--- a/yt/visualization/tests/test_fits_image.py
+++ b/yt/visualization/tests/test_fits_image.py
@@ -108,8 +108,8 @@
                               0.5, 128, "density").swapaxes(0, 1)
     fid4 = FITSImageData(buf, fields="density", width=100.0)
     fits_oap = FITSOffAxisProjection(ds, [0.1, 0.2, -0.9], "density",
-                                     width=(0.5,"unitary"), image_res=128,
-                                     depth_res=128, depth=(0.5,"unitary"))
+                                     width=(0.5, "unitary"), image_res=128,
+                                     depth=(0.5, "unitary"))
 
     assert_equal(fid4.get_data("density"), fits_oap.get_data("density"))
 
@@ -123,9 +123,9 @@
     assert fid4.wcsa.wcs.ctype[0] == "RA---TAN"
     assert fid4.wcsa.wcs.ctype[1] == "DEC--TAN"
 
-    cvg = ds.covering_grid(ds.index.max_level, [0.25,0.25,0.25],
-                           [32, 32, 32], fields=["density","temperature"])
-    fid5 = FITSImageData(cvg, fields=["density","temperature"])
+    cvg = ds.covering_grid(ds.index.max_level, [0.25, 0.25, 0.25],
+                           [32, 32, 32], fields=["density", "temperature"])
+    fid5 = FITSImageData(cvg, fields=["density", "temperature"])
     assert fid5.dimensionality == 3
 
     fid5.update_header("density", "time", 0.1)


https://bitbucket.org/yt_analysis/yt/commits/ae6b4661bcf7/
Changeset:   ae6b4661bcf7
User:        jzuhone
Date:        2017-05-23 14:23:11+00:00
Summary:     Mark get_data as deprecated
Affected #:  1 file

diff -r 17347910e56417ad47921b2c3aec0bcf22a45cbf -r ae6b4661bcf7bec15c41c3fa1ea98f4932f620c7 yt/visualization/fits_image.py
--- a/yt/visualization/fits_image.py
+++ b/yt/visualization/fits_image.py
@@ -334,7 +334,7 @@
     def get_data(self, field):
         """
         Return the data array of the image corresponding to *field*
-        with units attached.
+        with units attached. Deprecated.
         """
         return self[field].data
 


https://bitbucket.org/yt_analysis/yt/commits/411112c4f904/
Changeset:   411112c4f904
User:        jzuhone
Date:        2017-05-23 14:23:42+00:00
Summary:     Update the info() method to give the same information as HDUList does
Affected #:  1 file

diff -r ae6b4661bcf7bec15c41c3fa1ea98f4932f620c7 -r 411112c4f904c1fb6109e8948be4f275ebd4ed79 yt/visualization/fits_image.py
--- a/yt/visualization/fits_image.py
+++ b/yt/visualization/fits_image.py
@@ -21,6 +21,7 @@
     parallel_root_only
 from yt.visualization.volume_rendering.off_axis_projection import off_axis_projection
 import re
+import sys
 
 class UnitfulHDU(object):
     def __init__(self, hdu):
@@ -265,14 +266,40 @@
     def __repr__(self):
         return str([self[k] for k in self.keys()])
 
-    def info(self):
+    def info(self, output=None):
+        """
+        Summarize the info of the HDUs in this `FITSImageData`
+        instance.
+
+        Note that this function prints its results to the console---it
+        does not return a value.
+
+        Parameters
+        ----------
+        output : file, boolean, optional
+            A file-like object to write the output to.  If `False`, does not
+            output to a file and instead returns a list of tuples representing
+            the FITSImageData info.  Writes to ``sys.stdout`` by default.
+        """
         hinfo = self.hdulist.info(output=False)
         format = '{:3d}  {:10}  {:11}  {:5d}   {}   {}   {}'
-        results = []
+        if self.hdulist._file is None:
+            name = '(No file associated with this FITSImageData)'
+        else:
+            name = self.hdulist._file.name
+        results = ['Filename: {}'.format(name),
+                   'No.    Name         Type      Cards   Dimensions   Format     Units']
         for line in hinfo:
             units = self.field_units[self.hdulist[line[0]].header['btype']]
-            results.append(format.format(*line[:-1], units)) 
-        print('\n'.join(results)+'\n')
+            results.append(format.format(*line[:-1], units))
+        if output is None:
+            output = sys.stdout
+        if output:
+            output.write('\n'.join(results))
+            output.write('\n')
+            output.flush()
+        else:
+            return results[2:]
 
     @parallel_root_only
     def writeto(self, fileobj, fields=None, clobber=False, **kwargs):


https://bitbucket.org/yt_analysis/yt/commits/3e001d8a9fab/
Changeset:   3e001d8a9fab
User:        jzuhone
Date:        2017-05-23 14:26:46+00:00
Summary:     Update notebook
Affected #:  1 file

diff -r 411112c4f904c1fb6109e8948be4f275ebd4ed79 -r 3e001d8a9fabc8a3b0e69f28ca8e9d9a3373febb doc/source/visualizing/FITSImageData.ipynb
--- a/doc/source/visualizing/FITSImageData.ipynb
+++ b/doc/source/visualizing/FITSImageData.ipynb
@@ -53,7 +53,7 @@
    },
    "outputs": [],
    "source": [
-    "prj = yt.ProjectionPlot(ds, \"z\", [\"temperature\"], weight_field=\"density\", width=(500.,\"kpc\"))\n",
+    "prj = yt.ProjectionPlot(ds, \"z\", [\"temperature\"], weight_field=\"density\", width=(500., \"kpc\"))\n",
     "prj.show()"
    ]
   },
@@ -122,7 +122,7 @@
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "where we can see that the temperature units are in Kelvin and the cell widths are in kiloparsecs. If we want the raw image data with units, we can call `get_data`:"
+    "where we can see that the temperature units are in Kelvin and the cell widths are in kiloparsecs. If we want the raw image data with units, we can use the `data` attribute of this field:"
    ]
   },
   {
@@ -133,7 +133,7 @@
    },
    "outputs": [],
    "source": [
-    "prj_fits.get_data(\"temperature\")"
+    "prj_fits[\"temperature\"].data"
    ]
   },
   {
@@ -152,7 +152,7 @@
    "outputs": [],
    "source": [
     "prj_fits.set_unit(\"temperature\",\"R\")\n",
-    "prj_fits.get_data(\"temperature\")"
+    "prj_fits[\"temperature\"].data"
    ]
   },
   {
@@ -307,7 +307,7 @@
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "Alternatively, individual fields can be popped as well:"
+    "Alternatively, individual fields can be popped as well to produce new instances of `FITSImageData`:"
    ]
   },
   {
@@ -322,6 +322,13 @@
    ]
   },
   {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "So this new instance would only have the `\"density\"` field:"
+   ]
+  },
+  {
    "cell_type": "code",
    "execution_count": null,
    "metadata": {
@@ -333,6 +340,13 @@
    ]
   },
   {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "and the old one has the `\"density\"` field removed:"
+   ]
+  },
+  {
    "cell_type": "code",
    "execution_count": null,
    "metadata": {


https://bitbucket.org/yt_analysis/yt/commits/5b5e273ad3ad/
Changeset:   5b5e273ad3ad
User:        jzuhone
Date:        2017-05-23 14:31:33+00:00
Summary:     Use .data attribute instead of get_data
Affected #:  1 file

diff -r 3e001d8a9fabc8a3b0e69f28ca8e9d9a3373febb -r 5b5e273ad3adb09ea7b5407e57e15c1bd80e22c1 yt/visualization/tests/test_fits_image.py
--- a/yt/visualization/tests/test_fits_image.py
+++ b/yt/visualization/tests/test_fits_image.py
@@ -47,14 +47,14 @@
     fits_prj = FITSProjection(ds, "z", ["density","temperature"], image_res=128,
                               width=(0.5,"unitary"))
 
-    assert_equal(fid1.get_data("density"), fits_prj.get_data("density"))
-    assert_equal(fid1.get_data("temperature"), fits_prj.get_data("temperature"))
+    assert_equal(fid1["density"].data, fits_prj["density"].data)
+    assert_equal(fid1["temperature"].data, fits_prj["temperature"].data)
 
     fid1.writeto("fid1.fits", clobber=True)
     new_fid1 = FITSImageData.from_file("fid1.fits")
 
-    assert_equal(fid1.get_data("density"), new_fid1.get_data("density"))
-    assert_equal(fid1.get_data("temperature"), new_fid1.get_data("temperature"))
+    assert_equal(fid1["density"].data, new_fid1["density"].data)
+    assert_equal(fid1["temperature"].data, new_fid1["temperature"].data)
 
     ds2 = load("fid1.fits")
     ds2.index
@@ -74,8 +74,8 @@
     fits_slc = FITSSlice(ds, "z", ["density","temperature"], image_res=128,
                          width=(0.5,"unitary"))
 
-    assert_equal(fid2.get_data("density"), fits_slc.get_data("density"))
-    assert_equal(fid2.get_data("temperature"), fits_slc.get_data("temperature"))
+    assert_equal(fid2["density"].data, fits_slc["density"].data)
+    assert_equal(fid2["temperature"].data, fits_slc["temperature"].data)
 
     dens_img = fid2.pop("density")
     temp_img = fid2.pop("temperature")
@@ -92,8 +92,8 @@
                                 image_res=128, center=[0.5, 0.42, 0.6],
                                 width=(0.5,"unitary"))
 
-    assert_equal(fid3.get_data("density"), fits_cut.get_data("density"))
-    assert_equal(fid3.get_data("temperature"), fits_cut.get_data("temperature"))
+    assert_equal(fid3["density"].data, fits_cut["density"].data)
+    assert_equal(fid3["temperature"].data, fits_cut["temperature"].data)
 
     fid3.create_sky_wcs([30.,45.], (1.0,"arcsec/kpc"))
     fid3.writeto("fid3.fits", clobber=True)
@@ -111,7 +111,7 @@
                                      width=(0.5, "unitary"), image_res=128,
                                      depth=(0.5, "unitary"))
 
-    assert_equal(fid4.get_data("density"), fits_oap.get_data("density"))
+    assert_equal(fid4["density"].data, fits_oap["density"].data)
 
     fid4.create_sky_wcs([30., 45.], (1.0, "arcsec/kpc"), replace_old_wcs=False)
     assert fid4.wcs.wcs.cunit[0] == "cm"


https://bitbucket.org/yt_analysis/yt/commits/d2419cd6175c/
Changeset:   d2419cd6175c
User:        jzuhone
Date:        2017-05-23 15:35:15+00:00
Summary:     Bugfix
Affected #:  1 file

diff -r 5b5e273ad3adb09ea7b5407e57e15c1bd80e22c1 -r d2419cd6175c19a3e912085e34fda495d1f4f446 yt/visualization/fits_image.py
--- a/yt/visualization/fits_image.py
+++ b/yt/visualization/fits_image.py
@@ -36,7 +36,8 @@
         return YTArray(self.hdu.data, self.units)
 
     def __repr__(self):
-        return "FITSImage: %s (%d x %d, %s)" % (self.name, *self.shape, self.units)
+        im_shape = " x ".join([str(s) for s in self.shape])
+        return "FITSImage: %s (%s, %s)" % (self.name, im_shape, self.units)
 
 class FITSImageData(object):
 


https://bitbucket.org/yt_analysis/yt/commits/f714976e688d/
Changeset:   f714976e688d
User:        jzuhone
Date:        2017-05-23 17:06:11+00:00
Summary:     Bugfix
Affected #:  1 file

diff -r d2419cd6175c19a3e912085e34fda495d1f4f446 -r f714976e688d82cc45b44e28da2d546387dda0be yt/visualization/fits_image.py
--- a/yt/visualization/fits_image.py
+++ b/yt/visualization/fits_image.py
@@ -292,7 +292,11 @@
                    'No.    Name         Type      Cards   Dimensions   Format     Units']
         for line in hinfo:
             units = self.field_units[self.hdulist[line[0]].header['btype']]
-            results.append(format.format(*line[:-1], units))
+            summary = tuple(line[:-1] + [units])
+            if output:
+                results.append(format.format(*summary))
+            else:
+                results.append(summary)
         if output is None:
             output = sys.stdout
         if output:


https://bitbucket.org/yt_analysis/yt/commits/31b5c84d3d28/
Changeset:   31b5c84d3d28
User:        xarthisius
Date:        2017-06-15 13:35:57+00:00
Summary:     Merge pull request #1421 from jzuhone/fits_image

Improvements to FITSImageData
Affected #:  3 files

diff -r dd6dc6a11c26c2aa7bb30bbe22893518cbc65713 -r 31b5c84d3d288cadf419ba86429ba50f73877507 doc/source/visualizing/FITSImageData.ipynb
--- a/doc/source/visualizing/FITSImageData.ipynb
+++ b/doc/source/visualizing/FITSImageData.ipynb
@@ -53,7 +53,7 @@
    },
    "outputs": [],
    "source": [
-    "prj = yt.ProjectionPlot(ds, \"z\", [\"temperature\"], weight_field=\"density\", width=(500.,\"kpc\"))\n",
+    "prj = yt.ProjectionPlot(ds, \"z\", [\"temperature\"], weight_field=\"density\", width=(500., \"kpc\"))\n",
     "prj.show()"
    ]
   },
@@ -122,7 +122,7 @@
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "where we can see that the temperature units are in Kelvin and the cell widths are in kiloparsecs. If we want the raw image data with units, we can call `get_data`:"
+    "where we can see that the temperature units are in Kelvin and the cell widths are in kiloparsecs. If we want the raw image data with units, we can use the `data` attribute of this field:"
    ]
   },
   {
@@ -133,7 +133,7 @@
    },
    "outputs": [],
    "source": [
-    "prj_fits.get_data(\"temperature\")"
+    "prj_fits[\"temperature\"].data"
    ]
   },
   {
@@ -152,7 +152,7 @@
    "outputs": [],
    "source": [
     "prj_fits.set_unit(\"temperature\",\"R\")\n",
-    "prj_fits.get_data(\"temperature\")"
+    "prj_fits[\"temperature\"].data"
    ]
   },
   {
@@ -307,7 +307,7 @@
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "Alternatively, individual fields can be popped as well:"
+    "Alternatively, individual fields can be popped as well to produce new instances of `FITSImageData`:"
    ]
   },
   {
@@ -322,6 +322,13 @@
    ]
   },
   {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "So this new instance would only have the `\"density\"` field:"
+   ]
+  },
+  {
    "cell_type": "code",
    "execution_count": null,
    "metadata": {
@@ -333,6 +340,13 @@
    ]
   },
   {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "and the old one has the `\"density\"` field removed:"
+   ]
+  },
+  {
    "cell_type": "code",
    "execution_count": null,
    "metadata": {

diff -r dd6dc6a11c26c2aa7bb30bbe22893518cbc65713 -r 31b5c84d3d288cadf419ba86429ba50f73877507 yt/visualization/fits_image.py
--- a/yt/visualization/fits_image.py
+++ b/yt/visualization/fits_image.py
@@ -21,6 +21,23 @@
     parallel_root_only
 from yt.visualization.volume_rendering.off_axis_projection import off_axis_projection
 import re
+import sys
+
+class UnitfulHDU(object):
+    def __init__(self, hdu):
+        self.hdu = hdu
+        self.header = self.hdu.header
+        self.name = self.header["BTYPE"]
+        self.units = self.header["BUNIT"]
+        self.shape = self.hdu.shape
+
+    @property
+    def data(self):
+        return YTArray(self.hdu.data, self.units)
+
+    def __repr__(self):
+        im_shape = " x ".join([str(s) for s in self.shape])
+        return "FITSImage: %s (%s, %s)" % (self.name, im_shape, self.units)
 
 class FITSImageData(object):
 
@@ -76,6 +93,9 @@
         >>> f_deg.writeto("temp.fits")
         """
 
+        self.fields = []
+        self.field_units = {}
+
         if units is None:
             units = "cm"
         if width is None:
@@ -84,6 +104,27 @@
         exclude_fields = ['x','y','z','px','py','pz',
                           'pdx','pdy','pdz','weight_field']
 
+        if isinstance(data, _astropy.pyfits.HDUList):
+            self.hdulist = data
+            for hdu in data:
+                self.fields.append(hdu.header["btype"])
+                self.field_units[hdu.header["btype"]] = hdu.header['bunit']
+
+            self.shape = self.hdulist[0].shape
+            self.dimensionality = len(self.shape)
+            wcs_names = [key for key in self.hdulist[0].header 
+                         if "WCSNAME" in key]
+            for name in wcs_names:
+                if name == "WCSNAME":
+                    key = ' '
+                else:
+                    key = name[-1]
+                w = _astropy.pywcs.WCS(header=self.hdulist[0].header,
+                                       key=key, naxis=self.dimensionality)
+                setattr(self, "wcs"+key.strip().lower(), w)
+
+            return
+
         self.hdulist = _astropy.pyfits.HDUList()
 
         if isinstance(fields, string_types):
@@ -95,14 +136,14 @@
                 fields = list(img_data.keys())
         elif isinstance(data, np.ndarray):
             if fields is None:
-                mylog.warning("No field name given for this array. Calling it 'image_data'.")
+                mylog.warning("No field name given for this array. "
+                              "Calling it 'image_data'.")
                 fn = 'image_data'
                 fields = [fn]
             else:
                 fn = fields[0]
             img_data = {fn: data}
 
-        self.fields = []
         for fd in fields:
             if isinstance(fd, tuple):
                 self.fields.append(fd[1])
@@ -110,11 +151,10 @@
                 self.fields.append(fd)
 
         first = True
-        self.field_units = {}
         for key in fields:
             if key not in exclude_fields:
                 if hasattr(img_data[key], "units"):
-                    self.field_units[key] = img_data[key].units
+                    self.field_units[key] = str(img_data[key].units)
                 else:
                     self.field_units[key] = "dimensionless"
                 mylog.info("Making a FITS image of field %s" % key)
@@ -125,35 +165,37 @@
                     hdu = _astropy.pyfits.ImageHDU(np.array(img_data[key]))
                 hdu.name = key
                 hdu.header["btype"] = key
-                if hasattr(img_data[key], "units"):
-                    hdu.header["bunit"] = re.sub('()', '', str(img_data[key].units))
+                hdu.header["bunit"] = re.sub('()', '', self.field_units[key])
                 self.hdulist.append(hdu)
 
         self.shape = self.hdulist[0].shape
         self.dimensionality = len(self.shape)
 
         if wcs is None:
-            w = _astropy.pywcs.WCS(header=self.hdulist[0].header, naxis=self.dimensionality)
+            w = _astropy.pywcs.WCS(header=self.hdulist[0].header,
+                                   naxis=self.dimensionality)
             if isinstance(img_data, FixedResolutionBuffer):
                 # FRBs are a special case where we have coordinate
                 # information, so we take advantage of this and
                 # construct the WCS object
-                dx = (img_data.bounds[1]-img_data.bounds[0]).in_units(units).v/self.shape[0]
-                dy = (img_data.bounds[3]-img_data.bounds[2]).in_units(units).v/self.shape[1]
-                xctr = 0.5*(img_data.bounds[1]+img_data.bounds[0]).in_units(units).v
-                yctr = 0.5*(img_data.bounds[3]+img_data.bounds[2]).in_units(units).v
+                dx = (img_data.bounds[1]-img_data.bounds[0]).to(units).v
+                dy = (img_data.bounds[3]-img_data.bounds[2]).to(units).v
+                dx /= self.shape[0]
+                dy /= self.shape[1]
+                xctr = 0.5*(img_data.bounds[1]+img_data.bounds[0]).to(units).v
+                yctr = 0.5*(img_data.bounds[3]+img_data.bounds[2]).to(units).v
                 center = [xctr, yctr]
-                cdelt = [dx,dy]
+                cdelt = [dx, dy]
             elif isinstance(img_data, YTCoveringGrid):
-                cdelt = img_data.dds.in_units(units).v
-                center = 0.5*(img_data.left_edge+img_data.right_edge).in_units(units).v
+                cdelt = img_data.dds.to(units).v
+                center = 0.5*(img_data.left_edge+img_data.right_edge).to(units).v
             else:
-                # If img_data is just an array, we assume the center is the origin
-                # and use the image width to determine the cell widths
+                # If img_data is just an array, we assume the center is the 
+                # origin and use the image width to determine the cell widths
                 if not iterable(width):
                     width = [width]*self.dimensionality
                 if isinstance(width[0], YTQuantity):
-                    cdelt = [wh.in_units(units).v/n for wh, n in zip(width, self.shape)]
+                    cdelt = [wh.to(units).v/n for wh, n in zip(width, self.shape)]
                 else:
                     cdelt = [float(wh)/n for wh, n in zip(width, self.shape)]
                 center = [0.0]*self.dimensionality
@@ -203,7 +245,7 @@
             self.hdulist[idx].header[key] = value
 
     def update_all_headers(self, key, value):
-        mylog.warning("update_all_headers is deprecated. "+
+        mylog.warning("update_all_headers is deprecated. "
                       "Use update_header('all', key, value) instead.")
         self.update_header("all", key, value)
 
@@ -214,16 +256,55 @@
         return key in self.fields
 
     def values(self):
-        return [self.hdulist[k] for k in self.fields]
+        return [self[k] for k in self.fields]
 
     def items(self):
-        return [(k, self.hdulist[k]) for k in self.fields]
+        return [(k, self[k]) for k in self.fields]
 
     def __getitem__(self, item):
-        return self.hdulist[item]
+        return UnitfulHDU(self.hdulist[item])
+
+    def __repr__(self):
+        return str([self[k] for k in self.keys()])
+
+    def info(self, output=None):
+        """
+        Summarize the info of the HDUs in this `FITSImageData`
+        instance.
+
+        Note that this function prints its results to the console---it
+        does not return a value.
 
-    def info(self):
-        return self.hdulist.info()
+        Parameters
+        ----------
+        output : file, boolean, optional
+            A file-like object to write the output to.  If `False`, does not
+            output to a file and instead returns a list of tuples representing
+            the FITSImageData info.  Writes to ``sys.stdout`` by default.
+        """
+        hinfo = self.hdulist.info(output=False)
+        format = '{:3d}  {:10}  {:11}  {:5d}   {}   {}   {}'
+        if self.hdulist._file is None:
+            name = '(No file associated with this FITSImageData)'
+        else:
+            name = self.hdulist._file.name
+        results = ['Filename: {}'.format(name),
+                   'No.    Name         Type      Cards   Dimensions   Format     Units']
+        for line in hinfo:
+            units = self.field_units[self.hdulist[line[0]].header['btype']]
+            summary = tuple(line[:-1] + [units])
+            if output:
+                results.append(format.format(*summary))
+            else:
+                results.append(summary)
+        if output is None:
+            output = sys.stdout
+        if output:
+            output.write('\n'.join(results))
+            output.write('\n')
+            output.flush()
+        else:
+            return results[2:]
 
     @parallel_root_only
     def writeto(self, fileobj, fields=None, clobber=False, **kwargs):
@@ -276,8 +357,8 @@
     def to_aplpy(self, **kwargs):
         """
         Use APLpy (http://aplpy.github.io) for plotting. Returns an
-        `aplpy.FITSFigure` instance. All keyword arguments are passed to the
-        `aplpy.FITSFigure` constructor.
+        `aplpy.FITSFigure` instance. All keyword arguments are passed 
+        to the `aplpy.FITSFigure` constructor.
         """
         import aplpy
         return aplpy.FITSFigure(self.hdulist, **kwargs)
@@ -285,9 +366,9 @@
     def get_data(self, field):
         """
         Return the data array of the image corresponding to *field*
-        with units attached.
+        with units attached. Deprecated.
         """
-        return YTArray(self.hdulist[field].data, self.field_units[field])
+        return self[field].data
 
     def set_unit(self, field, units):
         """
@@ -296,7 +377,8 @@
         if field not in self.keys():
             raise KeyError("%s not an image!" % field)
         idx = self.fields.index(field)
-        new_data = YTArray(self.hdulist[idx].data, self.field_units[field]).in_units(units)
+        new_data = YTArray(self.hdulist[idx].data, 
+                           self.field_units[field]).to(units)
         self.hdulist[idx].data = new_data.v
         self.hdulist[idx].header["bunit"] = units
         self.field_units[field] = units
@@ -311,10 +393,13 @@
             raise KeyError("%s not an image!" % key)
         idx = self.fields.index(key)
         im = self.hdulist.pop(idx)
-        data = YTArray(im.data, self.field_units[key])
         self.field_units.pop(key)
         self.fields.remove(key)
-        return FITSImageData(data, fields=key, wcs=self.wcs)
+        data = _astropy.pyfits.HDUList([im])
+        return FITSImageData(data)
+
+    def close(self):
+        self.hdulist.close()
 
     @classmethod
     def from_file(cls, filename):
@@ -327,12 +412,8 @@
         filename : string
             The name of the file to open.
         """
-        f = _astropy.pyfits.open(filename)
-        data = {}
-        for hdu in f:
-            data[hdu.header["btype"]] = YTArray(hdu.data, hdu.header["bunit"])
-        f.close()
-        return cls(data, wcs=_astropy.pywcs.WCS(header=hdu.header))
+        f = _astropy.pyfits.open(filename, lazy_load_hdus=False)
+        return cls(f)
 
     @classmethod
     def from_images(cls, image_list):
@@ -347,14 +428,14 @@
         """
         w = image_list[0].wcs
         img_shape = image_list[0].shape
-        data = {}
-        for image in image_list:
-            assert_same_wcs(w, image.wcs)
-            if img_shape != image.shape:
+        data = []
+        for fid in image_list:
+            assert_same_wcs(w, fid.wcs)
+            if img_shape != fid.shape:
                 raise RuntimeError("Images do not have the same shape!")
-            for key in image.keys():
-                data[key] = image.get_data(key)
-        return cls(data, wcs=w)
+            data += fid.hdulist
+        data = _astropy.pyfits.HDUList(data)
+        return cls(data)
 
     def create_sky_wcs(self, sky_center, sky_scale,
                        ctype=["RA---TAN","DEC--TAN"],
@@ -394,7 +475,8 @@
         else:
             scaleq = YTQuantity(sky_scale[0],sky_scale[1])
         if scaleq.units.dimensions != dimensions.angle/dimensions.length:
-            raise RuntimeError("sky_scale %s not in correct dimensions of angle/length!" % sky_scale)
+            raise RuntimeError("sky_scale %s not in correct " % sky_scale +
+                               "dimensions of angle/length!")
         deltas = old_wcs.wcs.cdelt
         units = [str(unit) for unit in old_wcs.wcs.cunit]
         new_dx = (YTQuantity(-deltas[0], units[0])*scaleq).in_units("deg")
@@ -458,33 +540,26 @@
         else:
             nx, ny = image_res, image_res
     dx = width[0]/nx
+    dy = width[1]/ny
     crpix = [0.5*(nx+1), 0.5*(ny+1)]
-    if hasattr(ds, "wcs") and not iterable(axis):
-        # This is a FITS dataset, so we use it to construct the WCS
-        cunit = [str(ds.wcs.wcs.cunit[idx]) for idx in axis_wcs[axis]]
-        ctype = [ds.wcs.wcs.ctype[idx] for idx in axis_wcs[axis]]
-        cdelt = [ds.wcs.wcs.cdelt[idx] for idx in axis_wcs[axis]]
-        ctr_pix = center.in_units("code_length")[:ds.dimensionality].v
-        crval = ds.wcs.wcs_pix2world(ctr_pix.reshape(1, ds.dimensionality))[0]
-        crval = [crval[idx] for idx in axis_wcs[axis]]
+    if unit == "unitary":
+        unit = ds.get_smallest_appropriate_unit(ds.domain_width.max())
+    elif unit == "code_length":
+        unit = ds.get_smallest_appropriate_unit(ds.quan(1.0, "code_length"))
+    unit = sanitize_fits_unit(unit)
+    cunit = [unit]*2
+    ctype = ["LINEAR"]*2
+    cdelt = [dx.in_units(unit), dy.in_units(unit)]
+    if iterable(axis):
+        crval = center.in_units(unit)
     else:
-        if unit == "unitary":
-            unit = ds.get_smallest_appropriate_unit(ds.domain_width.max())
-        elif unit == "code_length":
-            unit = ds.get_smallest_appropriate_unit(ds.quan(1.0,"code_length"))
-        unit = sanitize_fits_unit(unit)
-        cunit = [unit]*2
-        ctype = ["LINEAR"]*2
-        cdelt = [dx.in_units(unit)]*2
-        if iterable(axis):
-            crval = center.in_units(unit)
-        else:
-            crval = [center[idx].in_units(unit) for idx in axis_wcs[axis]]
+        crval = [center[idx].in_units(unit) for idx in axis_wcs[axis]]
     if hasattr(data_source, 'to_frb'):
         if iterable(axis):
             frb = data_source.to_frb(width[0], (nx, ny), height=width[1])
         else:
-            frb = data_source.to_frb(width[0], (nx, ny), center=center, height=width[1])
+            frb = data_source.to_frb(width[0], (nx, ny), center=center,
+                                     height=width[1])
     else:
         frb = None
     w = _astropy.pywcs.WCS(naxis=2)
@@ -537,14 +612,14 @@
         The fields to slice
     center : A sequence of floats, a string, or a tuple.
          The coordinate of the center of the image. If set to 'c', 'center' or
-         left blank, the plot is centered on the middle of the domain. If set to
-         'max' or 'm', the center will be located at the maximum of the
+         left blank, the plot is centered on the middle of the domain. If set 
+         to 'max' or 'm', the center will be located at the maximum of the
          ('gas', 'density') field. Centering on the max or min of a specific
-         field is supported by providing a tuple such as ("min","temperature") or
-         ("max","dark_matter_density"). Units can be specified by passing in *center*
-         as a tuple containing a coordinate and string unit name or by passing
-         in a YTArray. If a list or unitless array is supplied, code units are
-         assumed.
+         field is supported by providing a tuple such as ("min","temperature")
+         or ("max","dark_matter_density"). Units can be specified by passing in
+         *center* as a tuple containing a coordinate and string unit name or by
+         passing in a YTArray. If a list or unitless array is supplied, code 
+         units are assumed.
     width : tuple or a float.
          Width can have four different formats to support windows with variable
          x and y widths.  They are:
@@ -566,15 +641,17 @@
          x width of 0.2 and a y width of 0.3 in code units.  If units are
          provided the resulting plot axis labels will use the supplied units.
     image_res : an int or 2-tuple of ints
-        Specify the resolution of the resulting image. If not provided, it will be
-        determined based on the minimum cell size of the dataset.
+        Specify the resolution of the resulting image. If not provided, it will
+        be determined based on the minimum cell size of the dataset.
     """
-    def __init__(self, ds, axis, fields, center="c", width=None, image_res=None, **kwargs):
+    def __init__(self, ds, axis, fields, center="c", width=None, 
+                 image_res=None, **kwargs):
         fields = ensure_list(fields)
         axis = fix_axis(axis, ds)
         center, dcenter = ds.coordinates.sanitize_center(center, axis)
         slc = ds.slice(axis, center[axis], **kwargs)
-        w, frb = construct_image(ds, axis, slc, dcenter, width=width, image_res=image_res)
+        w, frb = construct_image(ds, axis, slc, dcenter, width=width, 
+                                 image_res=image_res)
         super(FITSSlice, self).__init__(frb, fields=fields, wcs=w)
 
 
@@ -594,14 +671,14 @@
         The field used to weight the projection.
     center : A sequence of floats, a string, or a tuple.
          The coordinate of the center of the image. If set to 'c', 'center' or
-         left blank, the plot is centered on the middle of the domain. If set to
-         'max' or 'm', the center will be located at the maximum of the
+         left blank, the plot is centered on the middle of the domain. If set 
+         to 'max' or 'm', the center will be located at the maximum of the
          ('gas', 'density') field. Centering on the max or min of a specific
-         field is supported by providing a tuple such as ("min","temperature") or
-         ("max","dark_matter_density"). Units can be specified by passing in *center*
-         as a tuple containing a coordinate and string unit name or by passing
-         in a YTArray. If a list or unitless array is supplied, code units are
-         assumed.
+         field is supported by providing a tuple such as ("min","temperature") 
+         or ("max","dark_matter_density"). Units can be specified by passing in
+         *center* as a tuple containing a coordinate and string unit name or by
+         passing in a YTArray. If a list or unitless array is supplied, code 
+         units are assumed.
     width : tuple or a float.
          Width can have four different formats to support windows with variable
          x and y widths.  They are:
@@ -623,8 +700,8 @@
          x width of 0.2 and a y width of 0.3 in code units.  If units are
          provided the resulting plot axis labels will use the supplied units.
     image_res : an int or 2-tuple of ints
-        Specify the resolution of the resulting image. If not provided, it will be
-        determined based on the minimum cell size of the dataset.
+        Specify the resolution of the resulting image. If not provided, it will
+        be determined based on the minimum cell size of the dataset.
     """
     def __init__(self, ds, axis, fields, center="c", width=None,
                  weight_field=None, image_res=None, **kwargs):
@@ -632,7 +709,8 @@
         axis = fix_axis(axis, ds)
         center, dcenter = ds.coordinates.sanitize_center(center, axis)
         prj = ds.proj(fields[0], axis, weight_field=weight_field, **kwargs)
-        w, frb = construct_image(ds, axis, prj, dcenter, width=width, image_res=image_res)
+        w, frb = construct_image(ds, axis, prj, dcenter, width=width, 
+                                 image_res=image_res)
         super(FITSProjection, self).__init__(frb, fields=fields, wcs=w)
 
 class FITSOffAxisSlice(FITSImageData):
@@ -652,11 +730,11 @@
         left blank, the plot is centered on the middle of the domain. If set to
         'max' or 'm', the center will be located at the maximum of the
         ('gas', 'density') field. Centering on the max or min of a specific
-        field is supported by providing a tuple such as ("min","temperature") or
-        ("max","dark_matter_density"). Units can be specified by passing in *center*
-        as a tuple containing a coordinate and string unit name or by passing
-        in a YTArray. If a list or unitless array is supplied, code units are
-        assumed.
+        field is supported by providing a tuple such as ("min","temperature") 
+        or ("max","dark_matter_density"). Units can be specified by passing in 
+        *center* as a tuple containing a coordinate and string unit name or by 
+        passing in a YTArray. If a list or unitless array is supplied, code 
+        units are assumed.
     width : tuple or a float.
         Width can have four different formats to support windows with variable
         x and y widths.  They are:
@@ -684,13 +762,14 @@
         option sets the orientation of the slicing plane.  If not
         set, an arbitrary grid-aligned north-vector is chosen.
     """
-    def __init__(self, ds, normal, fields, center='c', width=None, image_res=512,
-                 north_vector=None):
+    def __init__(self, ds, normal, fields, center='c', width=None,
+                 image_res=512, north_vector=None):
         fields = ensure_list(fields)
         center, dcenter = ds.coordinates.sanitize_center(center, 4)
         cut = ds.cutting(normal, center, north_vector=north_vector)
         center = ds.arr([0.0] * 2, 'code_length')
-        w, frb = construct_image(ds, normal, cut, center, width=width, image_res=image_res)
+        w, frb = construct_image(ds, normal, cut, center, width=width,
+                                 image_res=image_res)
         super(FITSOffAxisSlice, self).__init__(frb, fields=fields, wcs=w)
 
 
@@ -709,14 +788,14 @@
         The name of the field(s) to be plotted.
     center : A sequence of floats, a string, or a tuple.
          The coordinate of the center of the image. If set to 'c', 'center' or
-         left blank, the plot is centered on the middle of the domain. If set to
-         'max' or 'm', the center will be located at the maximum of the
+         left blank, the plot is centered on the middle of the domain. If set 
+         to 'max' or 'm', the center will be located at the maximum of the
          ('gas', 'density') field. Centering on the max or min of a specific
-         field is supported by providing a tuple such as ("min","temperature") or
-         ("max","dark_matter_density"). Units can be specified by passing in *center*
-         as a tuple containing a coordinate and string unit name or by passing
-         in a YTArray. If a list or unitless array is supplied, code units are
-         assumed.
+         field is supported by providing a tuple such as ("min","temperature") 
+         or ("max","dark_matter_density"). Units can be specified by passing in
+         *center* as a tuple containing a coordinate and string unit name or by
+         passing in a YTArray. If a list or unitless array is supplied, code 
+         units are assumed.
     width : tuple or a float.
          Width can have four different formats to support windows with variable
          x and y widths.  They are:
@@ -745,9 +824,6 @@
          The name of the weighting field.  Set to None for no weight.
     image_res : an int or 2-tuple of ints
         Specify the resolution of the resulting image. 
-    depth_res : integer
-        Deprecated, this is still in the function signature for API
-        compatibility
     north_vector : a sequence of floats
         A vector defining the 'up' direction in the plot.  This
         option sets the orientation of the slicing plane.  If not
@@ -767,11 +843,12 @@
         This should only be used for uniform resolution grid datasets, as other
         datasets may result in unphysical images.
     data_source : yt.data_objects.data_containers.YTSelectionContainer, optional
-        If specified, this will be the data source used for selecting regions to project.
+        If specified, this will be the data source used for selecting regions 
+        to project.
     """
     def __init__(self, ds, normal, fields, center='c', width=(1.0, 'unitary'),
-                 weight_field=None, image_res=512, depth_res=256, data_source=None,
-                 north_vector=None, depth=(1.0,"unitary"), no_ghost=False, method='integrate'):
+                 weight_field=None, image_res=512, data_source=None,
+                 north_vector=None, depth=(1.0, "unitary"), method='integrate'):
         fields = ensure_list(fields)
         center, dcenter = ds.coordinates.sanitize_center(center, 4)
         buf = {}
@@ -785,9 +862,9 @@
         else:
             source = data_source
         for field in fields:
-            buf[field] = off_axis_projection(source, center, normal, wd, res, field,
-                                             no_ghost=no_ghost, north_vector=north_vector,
-                                             method=method, weight=weight_field).swapaxes(0, 1)
+            buf[field] = off_axis_projection(source, center, normal, wd,
+                                             res, field, north_vector=north_vector,
+                                             method=method, weight=weight_field).swapaxes(0,1)
         center = ds.arr([0.0] * 2, 'code_length')
         w, not_an_frb = construct_image(ds, normal, buf, center, width=width, image_res=image_res)
         super(FITSOffAxisProjection, self).__init__(buf, fields=fields, wcs=w)

diff -r dd6dc6a11c26c2aa7bb30bbe22893518cbc65713 -r 31b5c84d3d288cadf419ba86429ba50f73877507 yt/visualization/tests/test_fits_image.py
--- a/yt/visualization/tests/test_fits_image.py
+++ b/yt/visualization/tests/test_fits_image.py
@@ -47,14 +47,14 @@
     fits_prj = FITSProjection(ds, "z", ["density","temperature"], image_res=128,
                               width=(0.5,"unitary"))
 
-    assert_equal(fid1.get_data("density"), fits_prj.get_data("density"))
-    assert_equal(fid1.get_data("temperature"), fits_prj.get_data("temperature"))
+    assert_equal(fid1["density"].data, fits_prj["density"].data)
+    assert_equal(fid1["temperature"].data, fits_prj["temperature"].data)
 
     fid1.writeto("fid1.fits", clobber=True)
     new_fid1 = FITSImageData.from_file("fid1.fits")
 
-    assert_equal(fid1.get_data("density"), new_fid1.get_data("density"))
-    assert_equal(fid1.get_data("temperature"), new_fid1.get_data("temperature"))
+    assert_equal(fid1["density"].data, new_fid1["density"].data)
+    assert_equal(fid1["temperature"].data, new_fid1["temperature"].data)
 
     ds2 = load("fid1.fits")
     ds2.index
@@ -74,8 +74,8 @@
     fits_slc = FITSSlice(ds, "z", ["density","temperature"], image_res=128,
                          width=(0.5,"unitary"))
 
-    assert_equal(fid2.get_data("density"), fits_slc.get_data("density"))
-    assert_equal(fid2.get_data("temperature"), fits_slc.get_data("temperature"))
+    assert_equal(fid2["density"].data, fits_slc["density"].data)
+    assert_equal(fid2["temperature"].data, fits_slc["temperature"].data)
 
     dens_img = fid2.pop("density")
     temp_img = fid2.pop("temperature")
@@ -92,8 +92,8 @@
                                 image_res=128, center=[0.5, 0.42, 0.6],
                                 width=(0.5,"unitary"))
 
-    assert_equal(fid3.get_data("density"), fits_cut.get_data("density"))
-    assert_equal(fid3.get_data("temperature"), fits_cut.get_data("temperature"))
+    assert_equal(fid3["density"].data, fits_cut["density"].data)
+    assert_equal(fid3["temperature"].data, fits_cut["temperature"].data)
 
     fid3.create_sky_wcs([30.,45.], (1.0,"arcsec/kpc"))
     fid3.writeto("fid3.fits", clobber=True)
@@ -108,10 +108,10 @@
                               0.5, 128, "density").swapaxes(0, 1)
     fid4 = FITSImageData(buf, fields="density", width=100.0)
     fits_oap = FITSOffAxisProjection(ds, [0.1, 0.2, -0.9], "density",
-                                     width=(0.5,"unitary"), image_res=128,
-                                     depth_res=128, depth=(0.5,"unitary"))
+                                     width=(0.5, "unitary"), image_res=128,
+                                     depth=(0.5, "unitary"))
 
-    assert_equal(fid4.get_data("density"), fits_oap.get_data("density"))
+    assert_equal(fid4["density"].data, fits_oap["density"].data)
 
     fid4.create_sky_wcs([30., 45.], (1.0, "arcsec/kpc"), replace_old_wcs=False)
     assert fid4.wcs.wcs.cunit[0] == "cm"
@@ -123,9 +123,9 @@
     assert fid4.wcsa.wcs.ctype[0] == "RA---TAN"
     assert fid4.wcsa.wcs.ctype[1] == "DEC--TAN"
 
-    cvg = ds.covering_grid(ds.index.max_level, [0.25,0.25,0.25],
-                           [32, 32, 32], fields=["density","temperature"])
-    fid5 = FITSImageData(cvg, fields=["density","temperature"])
+    cvg = ds.covering_grid(ds.index.max_level, [0.25, 0.25, 0.25],
+                           [32, 32, 32], fields=["density", "temperature"])
+    fid5 = FITSImageData(cvg, fields=["density", "temperature"])
     assert fid5.dimensionality == 3
 
     fid5.update_header("density", "time", 0.1)

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