Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,11 @@ API Changes

- ``astropy.wcs``

- ``calcFootprint`` was deprecated. It is replaced by ``calc_footprint``.
An optional boolean keyword ``center`` was added to ``calc_footprint``.
It controls whether the centers or the corners of the pixels are used
in the computation. [#2384]

Bug Fixes
^^^^^^^^^

Expand Down
43 changes: 43 additions & 0 deletions astropy/wcs/tests/test_wcs.py
Original file line number Diff line number Diff line change
Expand Up @@ -610,3 +610,46 @@ def test_out_of_bounds():

assert not np.isnan(ra)
assert not np.isnan(dec)


def test_calc_footprint_1():
fits = get_pkg_data_filename('data/sip.fits')
w = wcs.WCS(fits)

axes = (1000, 1051)
ref = np.array([[ 202.39314493, 47.17753352],
[ 202.71885939, 46.94630488],
[ 202.94631893, 47.15855022],
[ 202.72053428, 47.37893142]])
footprint = w.calc_footprint(axes=axes)
assert_allclose(footprint, ref)


def test_calc_footprint_2():
""" Test calc_footprint without distortion. """
fits = get_pkg_data_filename('data/sip.fits')
w = wcs.WCS(fits)

axes = (1000, 1051)
ref = np.array([[ 202.39265216, 47.17756518],
[ 202.7469062 , 46.91483312],
[ 203.11487481, 47.14359319],
[ 202.76092671, 47.40745948]])
footprint = w.calc_footprint(axes=axes, undistort=False)
assert_allclose(footprint, ref)


def test_calc_footprint_3():
""" Test calc_footprint with corner of the pixel."""
w = wcs.WCS()
w.wcs.ctype = ["GLON-CAR", "GLAT-CAR"]
w.wcs.crpix = [1.5, 5.5]
w.wcs.cdelt = [-0.1, 0.1]
axes = (2, 10)
ref = np.array([[0.1, -0.5],
[0.1, 0.5],
[359.9, 0.5],
[359.9, -0.5]])

footprint = w.calc_footprint(axes=axes, undistort=False, center=False)
assert_allclose(footprint, ref)
33 changes: 22 additions & 11 deletions astropy/wcs/wcs.py
Original file line number Diff line number Diff line change
Expand Up @@ -548,7 +548,12 @@ def fix(self, translate_units='', naxis=None):
format(key, val),
FITSFixedWarning)

@deprecated("0.4", name="calcFootprint", alternative="calc_footprint")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This shows up like this in the HTML docs:

calcFootprint(*args, **kwargs)
Deprecated since version 0.4: Use calc_footprint instead.

Is this a bug or a feature of the @deprecated decorator that this doesn't show up like this?

def calcFootprint(self, header=None, undistort=True, axes=None)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Decorators don't easily preserve the call signature. If you want this to work we need to make use of the decorator.py package. Maybe you could open a new issue for this so we can discuss it? It might not be important since it's deprecated though - in fact, deprecated functions/methods should probably not show up in the API.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's not easy to do, I don't think it's worth the trouble.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a small bug in the @deprecated decorator (#2359), which unfortunately doesn't resolve this issue.

functools.wraps (which is the stdlib's simpler implementation of what decorator.py does) doesn't adapt the function signature of the wrapper. I don't know if this is worth adding yet another dependency.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I might open an issue for this actually. I don't think it's worth it for the @deprecated decorator itself, but I have been intended to write my own (similar to what decorator.py has) function to safely write new functions with a given call signature, for use with the modeling package. Once I have that it should be easy to make a wrapper around functools.wraps that includes this capability.

def calcFootprint(self, header=None, undistort=True, axes=None):
return self.calc_footprint(header=header, undistort=undistort, axes=axes,
center=True)

def calc_footprint(self, header=None, undistort=True, axes=None, center=True):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you change this:

header : astropy.io.fits header object, optional

to this:

header : `~astropy.io.fits.Header`, optional
    FITS Header

"""
Calculates the footprint of the image on the sky.

Expand All @@ -558,7 +563,7 @@ def calcFootprint(self, header=None, undistort=True, axes=None):

Parameters
----------
header : astropy.io.fits header object, optional
header : `~astropy.io.fits.Header` object, optional

undistort : bool, optional
If `True`, take SIP and distortion lookup table into
Expand All @@ -570,9 +575,13 @@ def calcFootprint(self, header=None, undistort=True, axes=None):
keywords from the header that was used to create this
`WCS` object.

center : bool, optional
If `True` use the center of the pixel, otherwise use the corner.

Returns
-------
coord : (4, 2) array of (*x*, *y*) coordinates.
The order is counter-clockwise starting with the bottom left corner.
"""
if axes is not None:
naxis1, naxis2 = axes
Expand All @@ -590,18 +599,20 @@ def calcFootprint(self, header=None, undistort=True, axes=None):
naxis1 = header.get('NAXIS1', None)
naxis2 = header.get('NAXIS2', None)

corners = np.zeros(shape=(4, 2), dtype=np.float64)
if naxis1 is None or naxis2 is None:
return None

corners[0, 0] = 1.
corners[0, 1] = 1.
corners[1, 0] = 1.
corners[1, 1] = naxis2
corners[2, 0] = naxis1
corners[2, 1] = naxis2
corners[3, 0] = naxis1
corners[3, 1] = 1.
if center == True:
corners = np.array([[1, 1],
[1, naxis2],
[naxis1, naxis2],
[naxis1, 1]], dtype = np.float64)
else:
corners = np.array([[0.5, 0.5],
[0.5, naxis2 + 0.5],
[naxis1 + 0.5, naxis2 + 0.5],
[naxis1 + 0.5, 0.5]], dtype = np.float64)

if undistort:
return self.all_pix2world(corners, 1)
else:
Expand Down Expand Up @@ -1721,7 +1732,7 @@ def footprint_to_file(self, filename=None, color='green', width=2):
f.write(comments)
f.write('linear\n')
f.write('polygon(')
self.calcFootprint().tofile(f, sep=',')
self.calc_footprint().tofile(f, sep=',')
f.write(') # color={0}, width={1:d} \n'.format(color, width))
f.close()

Expand Down