@@ -1632,3 +1632,95 @@ def _mask_include(self):
16321632 chunks = self ._data .chunksize ),
16331633 wcs = self .wcs ,
16341634 shape = self .shape )
1635+
1636+ def reproject (self , header , order = 'bilinear' , use_memmap = False ,
1637+ filled = True , ** kwargs ):
1638+ """
1639+ Spatially reproject the cube into a new header. Fills the data with
1640+ the cube's ``fill_value`` to replace bad values before reprojection.
1641+
1642+ If you want to reproject a cube both spatially and spectrally, you need
1643+ to use `spectral_interpolate` as well.
1644+
1645+ .. warning::
1646+ The current implementation of ``reproject`` requires that the whole
1647+ cube be loaded into memory. Issue #506 notes that this is a
1648+ problem, and it is on our to-do list to fix.
1649+
1650+ Parameters
1651+ ----------
1652+ header : `astropy.io.fits.Header`
1653+ A header specifying a cube in valid WCS
1654+ order : int or str, optional
1655+ The order of the interpolation (if ``mode`` is set to
1656+ ``'interpolation'``). This can be either one of the following
1657+ strings:
1658+
1659+ * 'nearest-neighbor'
1660+ * 'bilinear'
1661+ * 'biquadratic'
1662+ * 'bicubic'
1663+
1664+ or an integer. A value of ``0`` indicates nearest neighbor
1665+ interpolation.
1666+ use_memmap : bool
1667+ If specified, a memory mapped temporary file on disk will be
1668+ written to rather than storing the intermediate spectra in memory.
1669+ filled : bool
1670+ Fill the masked values with the cube's fill value before
1671+ reprojection? Note that setting ``filled=False`` will use the raw
1672+ data array, which can be a workaround that prevents loading large
1673+ data into memory.
1674+ kwargs : dict
1675+ Passed to `reproject.reproject_interp`.
1676+ """
1677+
1678+ try :
1679+ from reproject .version import version
1680+ except ImportError :
1681+ raise ImportError ("Requires the reproject package to be"
1682+ " installed." )
1683+
1684+ reproj_kwargs = kwargs
1685+ # Need version > 0.2 to work with cubes, >= 0.5 for memmap
1686+ from distutils .version import LooseVersion
1687+ if LooseVersion (version ) < "0.5" :
1688+ raise Warning ("Requires version >=0.5 of reproject. The current "
1689+ "version is: {}" .format (version ))
1690+ elif LooseVersion (version ) >= "0.6" :
1691+ pass # no additional kwargs, no warning either
1692+ else :
1693+ reproj_kwargs ['independent_celestial_slices' ] = True
1694+
1695+ from reproject import reproject_interp
1696+
1697+ # TODO: Find the minimal subcube that contains the header and only reproject that
1698+ # (see FITS_tools.regrid_cube for a guide on how to do this)
1699+
1700+ newwcs = wcs .WCS (header )
1701+ shape_out = tuple ([header ['NAXIS{0}' .format (i + 1 )] for i in
1702+ range (header ['NAXIS' ])][::- 1 ])
1703+
1704+ def reproject_interp_wrapper (img_slice ):
1705+ # What exactly is the wrapper getting here?
1706+ # I think it is given a _cube_ that is a cutout?
1707+ if filled :
1708+ data = img_slice .filled_data [:]
1709+ else :
1710+ data = img_slice ._data
1711+ return reproject_interp ((data , img_slice .header ),
1712+ newwcs , shape_out = shape_out , ** kwargs )
1713+
1714+ newcube , newcube_valid = self .apply_function_parallel_spatial (
1715+ reproject_interp_wrapper ,
1716+ accepts_chunks = True ,
1717+ order = order ,
1718+ ** reproj_kwargs )
1719+
1720+ return self ._new_cube_with (data = newcube ,
1721+ wcs = newwcs ,
1722+ mask = BooleanArrayMask (newcube_valid .astype ('bool' ),
1723+ newwcs ),
1724+ meta = self .meta ,
1725+ )
1726+
0 commit comments