diff --git a/.travis.yml b/.travis.yml index ca93cef..8882600 100644 --- a/.travis.yml +++ b/.travis.yml @@ -32,7 +32,7 @@ env: # For this package-template, we include examples of Cython modules, # so Cython is required for testing. If your package does not include # Cython code, you can set CONDA_DEPENDENCIES='' - - CONDA_DEPENDENCIES='' + - CONDA_DEPENDENCIES='numpy scipy astropy ginga' # If there are matplotlib or other GUI tests, uncomment the following # line to use the X virtual framebuffer. @@ -41,11 +41,22 @@ env: matrix: # Make sure that egg_info works without dependencies - SETUP_CMD='egg_info' + # Run actual tests + - SETUP_CMD='test' matrix: include: - # Test in Python 2. + # Check for sphinx doc build warnings - we do this first because it + # may run for a long time + - python: 3.6 + env: SETUP_CMD='build_docs -w' + PIP_DEPENDENCIES='ginga pandoc nbconvert tornado scipy' + + # Test in Python 2 + - python: 2.7 + env: ASTROPY_VERSION=lts SETUP_CMD='egg_info' + - python: 2.7 env: ASTROPY_VERSION=lts @@ -54,16 +65,9 @@ matrix: #- python: 3.6 # env: SETUP_CMD='test --coverage' - # Check for sphinx doc build warnings - we do this first because it - # may run for a long time - - python: 3.6 - env: SETUP_CMD='build_docs -w' - PIP_DEPENDENCIES='ginga pandoc nbconvert tornado scipy' - - # DISABLED FOR NOW # Try Astropy development version - #- python: 3.6 - # env: ASTROPY_VERSION=development + - python: 3.6 + env: ASTROPY_VERSION=development # Do a PEP8 test with flake8 - python: 3.6 diff --git a/README.rst b/README.rst index 3055e7e..d48a997 100644 --- a/README.rst +++ b/README.rst @@ -1,18 +1,21 @@ stginga ======= -.. image:: http://img.shields.io/badge/powered%20by-AstroPy-orange.svg?style=flat - :target: http://www.astropy.org - :alt: Powered by Astropy Badge +.. image:: https://readthedocs.org/projects/stginga/badge/?version=latest + :target: https://stginga.readthedocs.io/en/latest/?badge=latest + :alt: Documentation Status .. image:: https://travis-ci.org/spacetelescope/stginga.svg?branch=master :target: https://travis-ci.org/spacetelescope/stginga :alt: Travis CI results -.. image:: https://readthedocs.org/projects/stginga/badge/?version=latest - :target: https://stginga.readthedocs.io/en/latest/?badge=latest - :alt: Documentation Status +.. image:: https://ci.appveyor.com/api/projects/status/ulg6cmh15xpyyvp5?svg=true + :target: https://ci.appveyor.com/project/pllim/stginga + :alt: Appveyor CI results +.. image:: http://img.shields.io/badge/powered%20by-AstroPy-orange.svg?style=flat + :target: http://www.astropy.org + :alt: Powered by Astropy Badge `Ginga `_ products specific to STScI data analysis. diff --git a/appveyor.yml b/appveyor.yml index 7a4ab1c..88a2efa 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -21,7 +21,7 @@ environment: # We test Python 2.7 and 3.6 - PYTHON_VERSION: "2.7" - ASTROPY_VERSION: "stable" + ASTROPY_VERSION: "lts" NUMPY_VERSION: "stable" - PYTHON_VERSION: "3.6" diff --git a/stginga/tests/test_utils.py b/stginga/tests/test_utils.py new file mode 100644 index 0000000..fa72cd8 --- /dev/null +++ b/stginga/tests/test_utils.py @@ -0,0 +1,112 @@ +"""Tests for ``utils.py``.""" + +import numpy as np +import pytest +from astropy.io import fits +from astropy.utils.data import get_pkg_data_filename +from numpy.testing import assert_allclose, assert_array_equal + +from ..utils import (calc_stat, interpolate_badpix, find_ext, DQParser, + scale_image) + + +class TestCalcStat(object): + def setup_class(self): + rng = np.random.RandomState(1234) + self.array = rng.randn(10, 10) + + @pytest.mark.parametrize( + ('algo', 'ans'), + [('mean', 0.22538589848374507), + ('median', 0.21188338677770105), + ('mode', 0.22139729237840572), + ('stddev', 0.4925049855366562)]) + def test_algo(self, algo, ans): + result = calc_stat(self.array, algorithm=algo) + assert_allclose(result, ans) + + def test_no_support(self): + assert calc_stat([]) == 0 + + with pytest.raises(ValueError): + calc_stat(self.array, algorithm='foo') + + +class TestInterpBadPix(object): + def setup_class(self): + self.image = np.array([[1, 2, 3], + [4, 0, 6], + [7, 8, 9]], dtype=np.float) + self.basis_mask = np.array([[True, True, True], + [True, False, True], + [True, True, True]]) + self.badpix_mask = ~self.basis_mask + + @pytest.mark.parametrize( + ('algo', 'ans'), + [('nearest', 5), + ('linear', 2), + ('cubic', 5.00000013)]) + def test_algo(self, algo, ans): + im = self.image.copy() + interpolate_badpix( + im, self.badpix_mask, self.basis_mask, method=algo) + assert_array_equal(im[self.basis_mask], self.image[self.basis_mask]) + assert_allclose(im[self.badpix_mask], ans) + + def test_wrong_inputs(self): + with pytest.raises(ValueError): + interpolate_badpix( + self.image, self.badpix_mask, self.basis_mask, method='foo') + + with pytest.raises(ValueError): + interpolate_badpix(self.image, self.badpix_mask, []) + + +class TestStuffWithFITS(object): + def setup_class(self, tmpdir): + self.filename = str(tmpdir.join('test.fits')) + hdulist = fits.HDUList() + hduhdr = fits.PrimaryHDU() + hduhdr.header['INSTRUME'] = 'ACS' + hdulist.append(hduhdr) + hduimg = fits.ImageHDU(np.arange(100).reshape(10, 10), name='SCI') + hdulist.append(hduimg) + hdulist.writeto(self.filename) + + def test_find_ext(self): + for extname in ('PRIMARY', 'SCI'): + assert find_ext(self.filename, extname) + + assert not find_ext(self.filename, 'FOO') + assert not find_ext(None, 'SCI') + + def test_scale_image(self): + """WCS handling is not tested.""" + outfile = self.filename.replace('test.fits', 'out.fits') + scale_image(self.filename, outfile, 0.5, ext='SCI') + ans = [[0, 2, 4, 7, 9], + [22, 25, 27, 29, 31], + [45, 47, 49, 52, 54], + [68, 70, 72, 74, 77], + [90, 92, 95, 97, 99]] + with fits.open(outfile) as pf: + assert pf[0].header['INSTRUME'] == 'ACS' + assert_allclose(pf[0].data, ans) + + +# https://github.com/spacetelescope/reftools/blob/master/reftools/tests/test_interpretdq.py +def test_dq_parser(): + parsedq = DQParser(get_pkg_data_filename('../data/dqflags_acs.txt')) + + # One pixel + dqs = parsedq.interpret_dqval(16658) + assert sorted(dqs['DQFLAG']) == [2, 16, 256, 16384] + + # Array + dqs = parsedq.interpret_array([1, 1, 16658, 0]) + assert_array_equal(dqs[1][0], [0, 1]) + for i in [2, 16, 256, 16384]: + assert_array_equal(dqs[i][0], [2]) + for i in [4, 8, 32, 64, 128, 512, 1024, 2048, 4096, 8192, 32768]: + assert len(dqs[i][0]) == 0 diff --git a/stginga/utils.py b/stginga/utils.py index a1b84d4..d91ec84 100644 --- a/stginga/utils.py +++ b/stginga/utils.py @@ -311,7 +311,7 @@ def scale_image(infile, outfile, zoom_factor, ext=('SCI', 1), clobber=False, Unsupported number of dimension or invalid WCS. """ - if not clobber and os.path.exists(outfile): + if not clobber and os.path.exists(outfile): # pragma: no cover if debug: warnings.warn('{0} already exists'.format(outfile), AstropyUserWarning) @@ -329,7 +329,7 @@ def scale_image(infile, outfile, zoom_factor, ext=('SCI', 1), clobber=False, continue hdr[key] = prihdr[key] - if data.ndim != 2: + if data.ndim != 2: # pragma: no cover raise ValueError('Unsupported ndim={0}'.format(data.ndim)) # Scale the data. @@ -375,7 +375,7 @@ def scale_image(infile, outfile, zoom_factor, ext=('SCI', 1), clobber=False, # Update header if 'XTENSION' in hdr: del hdr['XTENSION'] - if 'SIMPLE' in hdr: + if 'SIMPLE' in hdr: # pragma: no cover hdr['SIMPLE'] = True else: hdr.insert(0, ('SIMPLE', True)) @@ -389,7 +389,7 @@ def scale_image(infile, outfile, zoom_factor, ext=('SCI', 1), clobber=False, # Write to output file hdu = fits.PrimaryHDU(data) hdu.header = hdr - if minversion(astropy, '1.3'): + if minversion(astropy, '1.3'): # pragma: no cover hdu.writeto(outfile, overwrite=clobber) else: hdu.writeto(outfile, clobber=clobber)