Skip to content

Commit 0ec792d

Browse files
committed
Wrote tests for image parsing methods + codestyle
1 parent 68a5766 commit 0ec792d

File tree

6 files changed

+112
-10
lines changed

6 files changed

+112
-10
lines changed

specreduce/background.py

-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
import numpy as np
77
from astropy.nddata import NDData
88
from astropy.units import UnitTypeError
9-
from astropy import units as u
109
from specutils import Spectrum1D
1110

1211
from specreduce.core import _ImageParser

specreduce/extract.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from astropy.modeling import Model, models, fitting
1010
from astropy.nddata import NDData, VarianceUncertainty
1111

12-
from specreduce.core import _ImageParser, SpecreduceOperation
12+
from specreduce.core import SpecreduceOperation
1313
from specreduce.tracing import Trace, FlatTrace
1414
from specutils import Spectrum1D
1515

specreduce/tests/test_background.py

+6-4
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import numpy as np
33

44
import astropy.units as u
5-
from astropy.nddata import CCDData, VarianceUncertainty
5+
from astropy.nddata import VarianceUncertainty
66
from specutils import Spectrum1D
77

88
from specreduce.background import Background
@@ -43,11 +43,13 @@ def test_background():
4343
bg = Background(image, trace, width=bkg_width)
4444

4545
# test that image subtraction works
46-
sub1 = image - bg1
46+
# NOTE: uncomment sub1 test once Spectrum1D and Background subtraction works
47+
# (meaning specutils PR #988 is merged, released, and pinned here)
48+
# sub1 = image - bg1
4749
sub2 = bg1.sub_image(image)
4850
sub3 = bg1.sub_image()
49-
assert np.allclose(sub1.flux, sub2.flux)
50-
assert np.allclose(sub1.flux, sub3.flux)
51+
# assert np.allclose(sub1.flux, sub2.flux)
52+
assert np.allclose(sub2.flux, sub3.flux)
5153

5254
bkg_spec = bg1.bkg_spectrum()
5355
assert isinstance(bkg_spec, Spectrum1D)

specreduce/tests/test_extract.py

-1
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,6 @@ def test_horne_variance_errors():
144144
# single negative value raises error
145145
err = image.uncertainty.array
146146
err[0][0] = -1
147-
mask = np.zeros_like(image)
148147
with pytest.raises(ValueError, match='variance must be fully positive'):
149148
# remember variance, mask, and unit args are only checked if image
150149
# object doesn't have those attributes (e.g., numpy and Quantity arrays)
+104
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import numpy as np
2+
3+
from astropy import units as u
4+
from astropy.io import fits
5+
from astropy.nddata import CCDData, NDData, VarianceUncertainty
6+
from astropy.utils.data import download_file
7+
8+
from specreduce.extract import HorneExtract
9+
from specreduce.tracing import FlatTrace
10+
from specutils import Spectrum1D, SpectralAxis
11+
12+
# fetch test image
13+
fn = download_file('https://stsci.box.com/shared/static/exnkul627fcuhy5akf2gswytud5tazmw.fits',
14+
cache=True)
15+
16+
# duplicate image in all accepted formats
17+
# (one Spectrum1D variant has a physical spectral axis; the other is in pixels)
18+
img = fits.getdata(fn).T
19+
flux = img * u.MJy / u.sr
20+
sax = SpectralAxis(np.linspace(14.377, 3.677, flux.shape[-1]) * u.um)
21+
unc = VarianceUncertainty(np.random.rand(*flux.shape))
22+
23+
all_images = {}
24+
all_images['arr'] = img
25+
all_images['s1d'] = Spectrum1D(flux, spectral_axis=sax, uncertainty=unc)
26+
all_images['s1d_pix'] = Spectrum1D(flux, uncertainty=unc)
27+
all_images['ccd'] = CCDData(img, uncertainty=unc, unit=flux.unit)
28+
all_images['ndd'] = NDData(img, uncertainty=unc, unit=flux.unit)
29+
all_images['qnt'] = img * flux.unit
30+
31+
# save default values used for spectral axis and uncertainty when they are not
32+
# available from the image object or provided by the user
33+
sax_def = np.arange(img.shape[1]) * u.pix
34+
unc_def = np.ones_like(img)
35+
36+
37+
# (for use inside tests)
38+
def compare_images(key, collection, compare='s1d'):
39+
# was input converted to Spectrum1D?
40+
assert isinstance(collection[key], Spectrum1D), (f"image '{key}' not "
41+
"of type Spectrum1D")
42+
43+
# do key's fluxes match its comparison's fluxes?
44+
assert np.allclose(collection[key].data,
45+
collection[compare].data), (f"images '{key}' and "
46+
f"'{compare}' have unequal "
47+
"flux values")
48+
49+
# if the image came with a spectral axis, was it kept? if not, was the
50+
# default spectral axis in pixels applied?
51+
sax_provided = hasattr(all_images[key], 'spectral_axis')
52+
assert np.allclose(collection[key].spectral_axis,
53+
(all_images[key].spectral_axis if sax_provided
54+
else sax_def)), (f"spectral axis of image '{key}' does "
55+
f"not match {'input' if sax_provided else 'default'}")
56+
57+
# if the image came with an uncertainty, was it kept? if not, was the
58+
# default uncertainty created?
59+
unc_provided = hasattr(all_images[key], 'uncertainty')
60+
assert np.allclose(collection[key].uncertainty.array,
61+
(all_images[key].uncertainty.array if unc_provided
62+
else unc_def)), (f"uncertainty of image '{key}' does "
63+
f"not match {'input' if unc_provided else 'default'}")
64+
65+
# were masks created despite none being given? (all indices should be False)
66+
assert (getattr(collection[key], 'mask', None)
67+
is not None), f"no mask was created for image '{key}'"
68+
assert np.all(collection[key].mask == 0), ("mask not all False "
69+
f"for image '{key}'")
70+
71+
72+
# test consistency of general image parser results
73+
def test_parse_general():
74+
all_images_parsed = {k: FlatTrace._parse_image(object, im)
75+
for k, im in all_images.items()}
76+
77+
for key in all_images_parsed.keys():
78+
compare_images(key, all_images_parsed)
79+
80+
81+
# use verified general image parser results to check HorneExtract's image parser
82+
def test_parse_horne():
83+
# HorneExtract's parser is more stringent than the general one, hence the
84+
# separate test. Given proper inputs, both should produce the same results.
85+
images_collection = {k: {} for k in all_images.keys()}
86+
87+
for key, col in images_collection.items():
88+
img = all_images[key]
89+
col['general'] = FlatTrace._parse_image(object, img)
90+
91+
if hasattr(all_images[key], 'uncertainty'):
92+
defaults = {}
93+
else:
94+
# save default values of attributes used in general parser when
95+
# they are not available from the image object. HorneExtract always
96+
# requires a variance, so it's chosen here to be on equal footing
97+
# with the general case
98+
defaults = {'variance': unc_def,
99+
'mask': np.ma.masked_invalid(img).mask,
100+
'unit': getattr(img, 'unit', u.DN)}
101+
102+
col[key] = HorneExtract._parse_image(object, img, **defaults)
103+
104+
compare_images(key, col, compare='general')

specreduce/tracing.py

+1-3
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,9 @@
55
import warnings
66

77
from astropy.modeling import Model, fitting, models
8-
from astropy.nddata import NDData, VarianceUncertainty
8+
from astropy.nddata import NDData
99
from astropy.stats import gaussian_sigma_to_fwhm
1010
from astropy.utils.decorators import deprecated
11-
from astropy import units as u
12-
from specutils import Spectrum1D
1311
import numpy as np
1412

1513
from specreduce.core import _ImageParser

0 commit comments

Comments
 (0)