1
1
# Licensed under a 3-clause BSD style license - see LICENSE.rst
2
2
3
-
4
3
import os
5
4
5
+ import numpy as np
6
6
from numpy .testing import assert_allclose
7
7
8
8
# performs similar tests as test_module.py, but performs
13
13
14
14
from astropy .table import Table
15
15
from astropy .io import fits
16
+ from astropy .wcs import WCS
16
17
17
18
from .. import conf , AstrometryNet
18
19
from ..core import _HAVE_SOURCE_DETECTION
@@ -35,6 +36,33 @@ def data_path(filename):
35
36
api_key = conf .api_key or os .environ .get ('ASTROMETRY_NET_API_KEY' )
36
37
37
38
39
+ def _calculate_wcs_separation_at_points (wcses , center , extent ):
40
+ """
41
+ Calculate the maximum separation between the given WCS solutions at a grid of points.
42
+
43
+ Parameters
44
+ ----------
45
+ wcses : list of `~astropy.wcs.WCS`
46
+ The WCS solutions to compare.
47
+ center : tuple of float
48
+ The center of the grid of points to use for the comparison.
49
+ extent : int
50
+ The extent of the grid of points to use for the comparison.
51
+
52
+ Returns
53
+ -------
54
+ max_separation : float
55
+ The maximum separation between the WCS solutions at the grid of points.
56
+ """
57
+ grid_points = np .mgrid [center [0 ] - extent // 2 :center [0 ] + extent // 2 ,
58
+ center [1 ] - extent // 2 :center [1 ] + extent // 2 ]
59
+
60
+ result_location = wcses [0 ].pixel_to_world (grid_points [0 ], grid_points [1 ])
61
+ expected_location = wcses [1 ].pixel_to_world (grid_points [0 ], grid_points [1 ])
62
+
63
+ return result_location .separation (expected_location )
64
+
65
+
38
66
@pytest .mark .skipif (not api_key , reason = 'API key not set.' )
39
67
@pytest .mark .remote_data
40
68
def test_solve_by_source_list ():
@@ -43,19 +71,25 @@ def test_solve_by_source_list():
43
71
sources = Table .read (os .path .join (DATA_DIR , 'test-source-list.fit' ))
44
72
# The image_width, image_height and crpix_center below are set to match the
45
73
# original solve on astrometry.net.
74
+ image_width = 4109
75
+ image_height = 4096
46
76
result = a .solve_from_source_list (sources ['X' ], sources ['Y' ],
47
- 4109 , 4096 ,
77
+ image_width , image_height ,
48
78
crpix_center = True )
49
79
50
80
expected_result = fits .getheader (os .path .join (DATA_DIR ,
51
- 'test- wcs-sol.fit' ))
81
+ 'wcs-sol-from-source-list-index-5200 .fit' ))
52
82
53
- for key in result :
54
- try :
55
- difference = expected_result [key ] - result [key ]
56
- except TypeError :
57
- pass
58
- assert difference == 0
83
+ wcs_r = WCS (result )
84
+ wcs_e = WCS (header = expected_result )
85
+ # Check that, at a a grid of points roughly in the center of the image, the WCS
86
+ # solutions are the same to within 0.1 arcsec.
87
+ # The grid created below covers about 1/4 of the pixels in the image.
88
+ center = np .array ([image_width // 2 , image_height // 2 ])
89
+ extent = image_width // 2
90
+
91
+ separations = _calculate_wcs_separation_at_points ([wcs_r , wcs_e ], center , extent )
92
+ assert (separations .arcsec ).max () < 0.1
59
93
60
94
61
95
@pytest .mark .skipif (not api_key , reason = 'API key not set.' )
@@ -65,20 +99,28 @@ def test_solve_image_upload():
65
99
a = AstrometryNet ()
66
100
a .api_key = api_key
67
101
image = os .path .join (DATA_DIR , 'thumbnail-image.fit.gz' )
102
+
103
+ image_width = 256
104
+ image_height = 256
68
105
# The test image only solves if it is not downsampled
106
+
69
107
result = a .solve_from_image (image ,
70
108
force_image_upload = True ,
71
- downsample_factor = 1 )
72
109
downsample_factor = 1 ,
73
110
crpix_center = True )
74
111
expected_result = fits .getheader (os .path .join (DATA_DIR ,
75
- 'thumbnail-wcs-sol.fit' ))
76
- for key in result :
77
- try :
78
- difference = expected_result [key ] - result [key ]
79
- except TypeError :
80
- pass
81
- assert difference == 0
112
+ 'wcs-sol-from-thumbnail-image-index-5200.fit' ))
113
+
114
+ wcs_r = WCS (result )
115
+ wcs_e = WCS (header = expected_result )
116
+ # Check that, at a a grid of points roughly in the center of the image, the WCS
117
+ # solutions are the same to within 0.1 arcsec.
118
+ # The grid created below covers all of this small image.
119
+ center = np .array ([image_width // 2 , image_height // 2 ])
120
+ extent = image_width
121
+
122
+ separations = _calculate_wcs_separation_at_points ([wcs_r , wcs_e ], center , extent )
123
+ assert (separations .arcsec ).max () < 0.1
82
124
83
125
84
126
@pytest .mark .skipif (not api_key , reason = 'API key not set.' )
@@ -107,6 +149,9 @@ def test_solve_image_detect_source_local():
107
149
a = AstrometryNet ()
108
150
a .api_key = api_key
109
151
image = os .path .join (DATA_DIR , 'thumbnail-image.fit.gz' )
152
+
153
+ image_width = 256
154
+ image_height = 256
110
155
# The source detection parameters below (fwhm, detect_threshold)
111
156
# are specific to this test image. They should not be construed
112
157
# as a general recommendation.
@@ -116,8 +161,33 @@ def test_solve_image_detect_source_local():
116
161
fwhm = 1.5 , detect_threshold = 5 ,
117
162
center_ra = 135.618 , center_dec = 49.786 ,
118
163
radius = 0.5 , crpix_center = True )
164
+
165
+ # Use the result from the image solve for this test. The two WCS solutions really should be
166
+ # nearly identical in thesee two cases. Note that the closeness of the match is affected by the
167
+ # very low resolution of these images (256 x 256 pixels). That low resolution was
168
+ # chosen to keep the test data small.
119
169
expected_result = fits .getheader (os .path .join (DATA_DIR ,
120
- 'thumbnail-wcs-sol-from-photutils.fit' ))
170
+ 'wcs-sol-from-thumbnail-image-index-5200.fit' ))
171
+
172
+ wcs_r = WCS (result )
173
+ wcs_e = WCS (header = expected_result )
174
+
175
+ # Check that, at a a grid of points roughly in the center of the image, the WCS
176
+ # solutions are the same to within 0.1 arcsec.
177
+ # The grid created below covers all of this small image.
178
+ center = np .array ([image_width // 2 , image_height // 2 ])
179
+ extent = image_width
180
+
181
+ separations = _calculate_wcs_separation_at_points ([wcs_r , wcs_e ], center , extent )
182
+
183
+ # The tolerance is higher here than in the other tests because of the
184
+ # low resolution of the test image. It leads to a difference in calculated
185
+ # coordinates of up to 2 arcsec across the whole image. The likely reason
186
+ # is that the source detection method is different locally than on
187
+ # astrometry.net.
188
+ assert (separations .arcsec ).max () < 2.2
189
+
190
+ # The headers should also be about the same in this case.
121
191
for key in result :
122
192
if key == 'COMMENT' or key == 'HISTORY' :
123
193
continue
@@ -151,7 +221,7 @@ def test_solve_timeout_behavior():
151
221
result = a .monitor_submission (submission_id , solve_timeout = 120 )
152
222
153
223
expected_result = fits .getheader (os .path .join (DATA_DIR ,
154
- 'test- wcs-sol.fit' ))
224
+ 'wcs-sol-from-source-list-index-5200 .fit' ))
155
225
156
226
for key in result :
157
227
if key == 'COMMENT' or key == 'HISTORY' :
0 commit comments