Skip to content

Commit

Permalink
improve mangle tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Benjamin Alan Weaver committed Mar 16, 2016
1 parent a2c3a29 commit 2184e80
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 38 deletions.
95 changes: 63 additions & 32 deletions pydl/pydlutils/mangle.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,50 @@
from astropy.extern import six


if six.PY3:
# This works, but wouldn't `int` intead of `long` be OK to use here?
# http://python3porting.com/differences.html#long
long = int
class FITS_polygon(fits.FITS_rec):
"""Handle polygons read in from a FITS file.
This class creates a copy of the ``XCAPS`` and ``CMCAPS`` columns.
This isn't especially efficient, but we can optimize later.
"""

#
# Right now, this class is only instantiated by calling .view() on
# a FITS_rec object, so only __array_finalize__ is needed.
#
# def __new__(*args):
# self = super(FITS_polygon, self).__new__(*args)
# self._caps = None
# return self

def __array_finalize__(self, obj):
super(FITS_polygon, self).__array_finalize__(obj)
self._caps = None

def __getitem__(self, key):
if isinstance(key, six.string_types):
if key.upper() == 'CAPS':
#
# 'CAPS' is a container with two columns: 'X', 'CM'.
#
if self._caps is None:
xdt = self['XCAPS'].dtype
cmdt = self['CMCAPS'].dtype
self._caps = np.empty((self.size,),
dtype=[('X', xdt, (9, 3)),
('CM', cmdt, (9,))]
).view(np.recarray)
self._caps['X'] = self['XCAPS']
self._caps['CM'] = self['CMCAPS']
return self._caps
return super(FITS_polygon, self).__getitem__(key)
else:
return super(FITS_polygon, self).__getitem__(key)

def __getattribute__(self, key):
if key.upper() == 'CAPS':
return self.__getitem__(key)
return super(FITS_polygon, self).__getattribute__(key)


def is_cap_used(use_caps, i):
Expand All @@ -33,9 +73,10 @@ def is_cap_used(use_caps, i):
def read_fits_polygons(filename):
"""Read a "polygon" format FITS file.
Unlike the IDL version of this routine, the ``XCAPS`` and ``CMPCAPS``
columns are *not* replaced with ``poly['CAPS']['X']`` and
``poly['CAPS']['CM']``.
This function returns a subclass of :class:`~astropy.io.fits.FITS_rec`
that simulates a "subcolumn" for compatibility with IDL code.
For example, if ``poly`` is the object returned by this function, then
the column ``XCAPS`` is accessible as ``poly.CAPS.X``.
Parameters
----------
Expand All @@ -44,33 +85,25 @@ def read_fits_polygons(filename):
Returns
-------
:class:`~astropy.io.fits.FITS_rec`
:class:`~pydl.pydlutils.mangle.FITS_polygon`
The data contained in HDU 1 of the FITS file.
"""
with fits.open(filename) as hdulist:
poly = hdulist[1].data
# poly['CAPS'] = {'CM': list(), 'X': list()}
# for k in range(len(poly['NCAPS'])):
# poly['CAPS']['CM'].append(poly['CMCAPS'][k,0:poly['NCAPS'][k]])
# poly['CAPS']['X'].append(
# poly['XCAPS'][k].reshape((8, 3))[0:poly['NCAPS'][k]])
# del poly['CMCAPS']
# del poly['XCAPS']
with fits.open(filename, uint=True) as hdulist:
poly = hdulist[1].data.view(FITS_polygon)
return poly


def set_use_caps(x, cm, polygon_use_caps, add=False, tol=1.0e-10,
def set_use_caps(polygon, index_list, add=False, tol=1.0e-10,
allow_doubles=False, allow_neg_doubles=False):
"""Set the bits in use_caps for a polygon.
"""Set the bits in USE_CAPS for a set of polygons.
Parameters
----------
x : array-like
Polygon `x` value.
cm : array-like
Polygon `cm` value.
polygon_use_caps : :class:`int`
Input value of use_caps.
polygon : :class:`~pydl.pydlutils.mangle.FITS_polygon`
A set of polygons.
index_list : array-like
A list of indices to set in each polygon. Should have the same
length as `polygon`.
add : :class:`bool`, optional
If ``True``, don't initialize the use_caps value to zero, use the
value of `polygon_use_caps` instead.
Expand All @@ -85,15 +118,13 @@ def set_use_caps(x, cm, polygon_use_caps, add=False, tol=1.0e-10,
Returns
-------
:class:`long`
:class:`int`
Value of use_caps.
"""
if add:
use_caps = long(polygon_use_caps)
else:
use_caps = long(0)
if not add:
polygon.USE_CAPS = 0
t2 = tol**2
use_caps |= long(2)**len(cm) - long(1)
polygon.USE_CAPS |= (1 << len(cm)) - 1
if not allow_doubles:
#
# Check for doubles
Expand All @@ -109,5 +140,5 @@ def set_use_caps(x, cm, polygon_use_caps, add=False, tol=1.0e-10,
#
# Don't use
#
use_caps -= long(2)**j
use_caps -= 1 << j
return use_caps
Binary file added pydl/pydlutils/tests/t/polygon.fits
Binary file not shown.
40 changes: 38 additions & 2 deletions pydl/pydlutils/tests/test_mangle.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,56 @@
# Licensed under a 3-clause BSD style license - see LICENSE.rst
# -*- coding: utf-8 -*-
import os
import numpy as np
from astropy.tests.helper import raises
from ..mangle import is_cap_used
from ..mangle import is_cap_used, read_fits_polygons


class TestMangle(object):
"""Test the functions in pydl.pydlutils.mangle.
"""

def setup(self):
pass
self.data_dir = os.path.join(os.path.dirname(__file__), 't')

def teardown(self):
pass

def test_is_cap_used(self):
assert is_cap_used(1 << 2, 2)
assert not is_cap_used(1 << 2, 1)

def test_read_fits_polygons(self):
poly = read_fits_polygons(os.path.join(self.data_dir, 'polygon.fits'))
use_caps = np.array([31, 15, 31, 7, 31, 15, 15, 7, 15, 15,
15, 31, 15, 15, 15, 15, 15, 15, 31, 15],
dtype=np.uint32)
assert (poly['USE_CAPS'] == use_caps).all()
cm0 = np.array([-1.0, -0.99369437, 1.0, -1.0, 0.00961538])
assert np.allclose(poly.CAPS.CM[0][0:poly.NCAPS[0]], cm0)
assert poly[0]['NCAPS'] == 5


def fits_polygon_file():
"""Create a small test version of a FITS polygon file.
"""
from datetime import date
from sys import argv
from astropy.io import fits
from pydl import __version__ as pydlversion
with fits.open(argv[1], uint=True) as hdulist:
header0 = hdulist[0].header
data = hdulist[1].data
if 'DATE' in header0:
header0['DATE'] = date.today().strftime('%Y-%m-%d')
if 'IDLUTILS' in header0:
header0['IDLUTILS'] = 'pydl-'+pydlversion
hdu0 = fits.PrimaryHDU(header=header0)
hdu1 = fits.BinTableHDU(data[0:20])
hdulist2 = fits.HDUList([hdu0, hdu1])
hdulist2.writeto('polygon.fits')
return 0

if __name__ == '__main__':
from sys import exit
exit(fits_polygon_file())
8 changes: 4 additions & 4 deletions pydl/tests/test_pydl.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,10 @@ def test_pcomp(self):
1.00127640e+00,
1.48380121e-01,
6.57156222e-04]))
# assert_allclose(foo.variance, np.array([7.12421581e-01,
# 2.50319100e-01,
# 3.70950302e-02,
# 1.64289056e-04]))
assert_allclose(foo.variance, np.array([7.12421581e-01,
2.50319100e-01,
3.70950302e-02,
1.64289056e-04]))

def test_rebin(self):
x = np.arange(40)
Expand Down

0 comments on commit 2184e80

Please sign in to comment.