drizzle 1.15.3__cp312-cp312-win32.whl → 2.0.1__cp312-cp312-win32.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of drizzle might be problematic. Click here for more details.

@@ -0,0 +1,238 @@
1
+ import numpy as np
2
+ import pytest
3
+ from numpy.testing import assert_almost_equal, assert_equal
4
+
5
+ from drizzle.utils import (
6
+ _estimate_pixel_scale,
7
+ calc_pixmap,
8
+ decode_context,
9
+ estimate_pixel_scale_ratio,
10
+ )
11
+
12
+ from .helpers import wcs_from_file
13
+
14
+
15
+ def test_map_rectangular():
16
+ """
17
+ Make sure the initial index array has correct values
18
+ """
19
+ naxis1 = 1000
20
+ naxis2 = 10
21
+
22
+ pixmap = np.indices((naxis1, naxis2), dtype='float32')
23
+ pixmap = pixmap.transpose()
24
+
25
+ assert_equal(pixmap[5, 500], (500, 5))
26
+
27
+
28
+ @pytest.mark.parametrize(
29
+ "wcs_type", ["fits", "gwcs"]
30
+ )
31
+ def test_map_to_self(wcs_type):
32
+ """
33
+ Map a pixel array to itself. Should return the same array.
34
+ """
35
+ input_wcs = wcs_from_file("j8bt06nyq_sip_flt.fits", ext=1, wcs_type=wcs_type)
36
+ shape = input_wcs.array_shape
37
+
38
+ ok_pixmap = np.indices(shape, dtype='float64')
39
+ ok_pixmap = ok_pixmap.transpose()
40
+
41
+ pixmap = calc_pixmap(input_wcs, input_wcs)
42
+
43
+ # Got x-y transpose right
44
+ assert_equal(pixmap.shape, ok_pixmap.shape)
45
+
46
+ # Mapping an array to itself
47
+ assert_almost_equal(pixmap, ok_pixmap, decimal=5)
48
+
49
+ # user-provided shape
50
+ pixmap = calc_pixmap(input_wcs, input_wcs, (12, 34))
51
+ assert_equal(pixmap.shape, (12, 34, 2))
52
+
53
+ # Check that an exception is raised for WCS without pixel_shape and
54
+ # bounding_box:
55
+ input_wcs.pixel_shape = None
56
+ input_wcs.bounding_box = None
57
+ with pytest.raises(ValueError):
58
+ calc_pixmap(input_wcs, input_wcs)
59
+
60
+ # user-provided shape when array_shape is not set:
61
+ pixmap = calc_pixmap(input_wcs, input_wcs, (12, 34))
62
+ assert_equal(pixmap.shape, (12, 34, 2))
63
+
64
+ # from bounding box:
65
+ input_wcs.bounding_box = ((5.3, 33.5), (2.8, 11.5))
66
+ pixmap = calc_pixmap(input_wcs, input_wcs)
67
+ assert_equal(pixmap.shape, (12, 34, 2))
68
+
69
+ # from bounding box and pixel_shape (the later takes precedence):
70
+ input_wcs.array_shape = shape
71
+ pixmap = calc_pixmap(input_wcs, input_wcs)
72
+ assert_equal(pixmap.shape, ok_pixmap.shape)
73
+
74
+
75
+ @pytest.mark.parametrize(
76
+ "wcs_type", ["fits", "gwcs"]
77
+ )
78
+ def test_translated_map(wcs_type):
79
+ """
80
+ Map a pixel array to at translated array.
81
+ """
82
+ first_wcs = wcs_from_file(
83
+ "j8bt06nyq_sip_flt.fits",
84
+ ext=1,
85
+ wcs_type=wcs_type
86
+ )
87
+ second_wcs = wcs_from_file(
88
+ "j8bt06nyq_sip_flt.fits",
89
+ ext=1,
90
+ crpix_shift=(-2, -2), # shift loaded WCS by adding this to CRPIX
91
+ wcs_type=wcs_type
92
+ )
93
+
94
+ ok_pixmap = np.indices(first_wcs.array_shape, dtype='float32') - 2.0
95
+ ok_pixmap = ok_pixmap.transpose()
96
+
97
+ pixmap = calc_pixmap(first_wcs, second_wcs)
98
+
99
+ # Got x-y transpose right
100
+ assert_equal(pixmap.shape, ok_pixmap.shape)
101
+ # Mapping an array to a translated array
102
+ assert_almost_equal(pixmap[2:, 2:], ok_pixmap[2:, 2:], decimal=5)
103
+
104
+
105
+ def test_disable_gwcs_bbox():
106
+ """
107
+ Map a pixel array to a translated version ofitself.
108
+ """
109
+ first_wcs = wcs_from_file(
110
+ "j8bt06nyq_sip_flt.fits",
111
+ ext=1,
112
+ wcs_type="gwcs"
113
+ )
114
+ second_wcs = wcs_from_file(
115
+ "j8bt06nyq_sip_flt.fits",
116
+ ext=1,
117
+ crpix_shift=(-2, -2), # shift loaded WCS by adding this to CRPIX
118
+ wcs_type="gwcs"
119
+ )
120
+
121
+ ok_pixmap = np.indices(first_wcs.array_shape, dtype='float64') - 2.0
122
+ ok_pixmap = ok_pixmap.transpose()
123
+
124
+ # Mapping an array to a translated array
125
+
126
+ # disable both bounding boxes:
127
+ pixmap = calc_pixmap(first_wcs, second_wcs, disable_bbox="both")
128
+ assert_almost_equal(pixmap[2:, 2:], ok_pixmap[2:, 2:], decimal=5)
129
+ assert np.all(np.isfinite(pixmap[:2, :2]))
130
+ assert np.all(np.isfinite(pixmap[-2:, -2:]))
131
+ # check bbox was restored
132
+ assert first_wcs.bounding_box is not None
133
+ assert second_wcs.bounding_box is not None
134
+
135
+ # disable "from" bounding box:
136
+ pixmap = calc_pixmap(second_wcs, first_wcs, disable_bbox="from")
137
+ assert_almost_equal(pixmap[:-2, :-2], ok_pixmap[:-2, :-2] + 4.0, decimal=5)
138
+ assert np.all(np.logical_not(np.isfinite(pixmap[-2:, -2:])))
139
+ # check bbox was restored
140
+ assert first_wcs.bounding_box is not None
141
+ assert second_wcs.bounding_box is not None
142
+
143
+ # disable "to" bounding boxes:
144
+ pixmap = calc_pixmap(first_wcs, second_wcs, disable_bbox="to")
145
+ assert_almost_equal(pixmap[2:, 2:], ok_pixmap[2:, 2:], decimal=5)
146
+ assert np.all(np.isfinite(pixmap[:2, :2]))
147
+ assert np.all(pixmap[:2, :2] < 0.0)
148
+ assert np.all(np.isfinite(pixmap[-2:, -2:]))
149
+ # check bbox was restored
150
+ assert first_wcs.bounding_box is not None
151
+ assert second_wcs.bounding_box is not None
152
+
153
+ # enable all bounding boxes:
154
+ pixmap = calc_pixmap(first_wcs, second_wcs, disable_bbox="none")
155
+ assert_almost_equal(pixmap[2:, 2:], ok_pixmap[2:, 2:], decimal=5)
156
+ assert np.all(np.logical_not(np.isfinite(pixmap[:2, :2])))
157
+ # check bbox was restored
158
+ assert first_wcs.bounding_box is not None
159
+ assert second_wcs.bounding_box is not None
160
+
161
+
162
+ def test_estimate_pixel_scale_ratio():
163
+ w = wcs_from_file("j8bt06nyq_flt.fits", ext=1)
164
+ pscale = estimate_pixel_scale_ratio(w, w, w.wcs.crpix, (0, 0))
165
+ assert abs(pscale - 0.9999999916964737) < 1.0e-9
166
+
167
+
168
+ def test_estimate_pixel_scale_no_refpix():
169
+ # create a WCS without higher order (polynomial) distortions:
170
+ w = wcs_from_file("j8bt06nyq_sip_flt.fits", ext=1)
171
+ w.sip = None
172
+ w.det2im1 = None
173
+ w.det2im2 = None
174
+ w.cpdis1 = None
175
+ w.cpdis2 = None
176
+ pixel_shape = w.pixel_shape[:]
177
+
178
+ ref_pscale = _estimate_pixel_scale(w, w.wcs.crpix)
179
+
180
+ if hasattr(w, 'bounding_box'):
181
+ del w.bounding_box
182
+ pscale1 = _estimate_pixel_scale(w, None)
183
+ assert np.allclose(ref_pscale, pscale1, atol=0.0, rtol=1.0e-8)
184
+
185
+ w.bounding_box = None
186
+ w.pixel_shape = None
187
+ pscale2 = _estimate_pixel_scale(w, None)
188
+ assert np.allclose(pscale1, pscale2, atol=0.0, rtol=1.0e-8)
189
+
190
+ w.pixel_shape = pixel_shape
191
+ pscale3 = _estimate_pixel_scale(w, None)
192
+ assert np.allclose(pscale1, pscale3, atol=0.0, rtol=1.0e-14)
193
+
194
+ w.bounding_box = ((-0.5, pixel_shape[0] - 0.5), (-0.5, pixel_shape[1] - 0.5))
195
+ pscale4 = _estimate_pixel_scale(w, None)
196
+ assert np.allclose(pscale3, pscale4, atol=0.0, rtol=1.0e-8)
197
+
198
+
199
+ def test_decode_context():
200
+ ctx = np.array(
201
+ [[[0, 0, 0, 0, 0, 0],
202
+ [0, 0, 0, 36196864, 0, 0],
203
+ [0, 0, 0, 0, 0, 0],
204
+ [0, 0, 0, 0, 0, 0],
205
+ [0, 0, 537920000, 0, 0, 0]],
206
+ [[0, 0, 0, 0, 0, 0,],
207
+ [0, 0, 0, 67125536, 0, 0],
208
+ [0, 0, 0, 0, 0, 0],
209
+ [0, 0, 0, 0, 0, 0],
210
+ [0, 0, 163856, 0, 0, 0]],
211
+ [[0, 0, 0, 0, 0, 0],
212
+ [0, 0, 0, 8203, 0, 0],
213
+ [0, 0, 0, 0, 0, 0],
214
+ [0, 0, 0, 0, 0, 0],
215
+ [0, 0, 32865, 0, 0, 0]]],
216
+ dtype=np.int32
217
+ )
218
+
219
+ idx1, idx2 = decode_context(ctx, [3, 2], [1, 4])
220
+
221
+ assert sorted(idx1) == [9, 12, 14, 19, 21, 25, 37, 40, 46, 58, 64, 65, 67, 77]
222
+ assert sorted(idx2) == [9, 20, 29, 36, 47, 49, 64, 69, 70, 79]
223
+
224
+ # context array must be 3D:
225
+ with pytest.raises(ValueError):
226
+ decode_context(ctx[0], [3, 2], [1, 4])
227
+
228
+ # pixel coordinates must be integer:
229
+ with pytest.raises(ValueError):
230
+ decode_context(ctx, [3.0, 2], [1, 4])
231
+
232
+ # coordinate lists must be equal in length:
233
+ with pytest.raises(ValueError):
234
+ decode_context(ctx, [3, 2], [1, 4, 5])
235
+
236
+ # coordinate lists must be 1D:
237
+ with pytest.raises(ValueError):
238
+ decode_context(ctx, [[3, 2]], [[1, 4]])
drizzle/util.py CHANGED
@@ -1,138 +1,15 @@
1
- import numpy as np
1
+ """
2
+ Module ``util`` has been deprecated.
3
+ """
4
+ import warnings
2
5
 
3
-
4
- def find_keyword_extn(fimg, keyword, value=None):
5
- """
6
- This function will return the index of the extension in a multi-extension
7
- FITS file which contains the desired keyword with the given value.
8
-
9
- Parameters
10
- ----------
11
-
12
- fimg : hdulist
13
- A list of header data units
14
-
15
- keyword : str
16
- The keyword to search for
17
-
18
- value : str or number, optional
19
- If set, the value the keyword must have to match
20
-
21
- Returns
22
- -------
23
-
24
- The index of the extension
25
- """
26
-
27
- i = 0
28
- extnum = -1
29
- # Search through all the extensions in the FITS object
30
- for chip in fimg:
31
- hdr = chip.header
32
- # Check to make sure the extension has the given keyword
33
- if keyword in hdr:
34
- if value is not None:
35
- # If it does, then does the value match the desired value
36
- # MUST use 'str.strip' to match against any input string!
37
- if hdr[keyword].strip() == value:
38
- extnum = i
39
- break
40
- else:
41
- extnum = i
42
- break
43
- i += 1
44
- # Return the index of the extension which contained the
45
- # desired EXTNAME value.
46
- return extnum
47
-
48
-
49
- def get_extn(fimg, extn=''):
50
- """
51
- Returns the FITS extension corresponding to extension specified in
52
- filename. Defaults to returning the first extension with data or the
53
- primary extension, if none have data.
54
-
55
- Parameters
56
- ----------
57
-
58
- fimg : hdulist
59
- A list of header data units
60
-
61
- extn : str
62
- The extension name and version to match
63
-
64
- Returns
65
- -------
66
-
67
- The matching header data unit
68
- """
69
-
70
- if extn:
71
- try:
72
- _extn = parse_extn(extn)
73
- if _extn[0]:
74
- _e = fimg.index_of(_extn)
75
- else:
76
- _e = _extn[1]
77
-
78
- except KeyError:
79
- _e = None
80
-
81
- if _e is None:
82
- _extn = None
83
- else:
84
- _extn = fimg[_e]
85
-
86
- else:
87
- # If no extension is provided, search for first extension
88
- # in FITS file with data associated with it.
89
-
90
- # Set up default to point to PRIMARY extension.
91
- _extn = fimg[0]
92
- # then look for first extension with data.
93
- for _e in fimg:
94
- if _e.data is not None:
95
- _extn = _e
96
- break
97
-
98
- return _extn
99
-
100
-
101
- def get_keyword(fimg, keyword, default=None):
102
- """
103
- Return a keyword value from the header of an image,
104
- or the default if the keyword is not found.
105
-
106
- Parameters
107
- ----------
108
-
109
- fimg : hdulist
110
- A list of header data units
111
-
112
- keyword : hdulist
113
- The keyword value to search for
114
-
115
- default : str or number, optional
116
- The default value if not found
117
-
118
- Returns
119
- -------
120
-
121
- The value if found or default if not
122
- """
123
-
124
- value = None
125
- if keyword:
126
- _nextn = find_keyword_extn(fimg, keyword)
127
- try:
128
- value = fimg[_nextn].header[keyword]
129
- except KeyError:
130
- value = None
131
-
132
- if value is None and default is not None:
133
- value = default
134
-
135
- return value
6
+ warnings.warn(
7
+ "Module 'drizzle.util' has been deprecated since version 2.0.0 "
8
+ "and it will be removed in a future release. "
9
+ "Please replace calls to 'util.is_blank()' with alternative "
10
+ "implementation.",
11
+ DeprecationWarning
12
+ )
136
13
 
137
14
 
138
15
  def is_blank(value):
@@ -141,116 +18,17 @@ def is_blank(value):
141
18
 
142
19
  Parameters
143
20
  ----------
144
-
145
21
  value : str
146
22
  The value to check
147
23
 
148
24
  Returns
149
25
  -------
150
-
151
26
  True or False
152
27
  """
28
+ warnings.warn(
29
+ "'is_blank()' has been deprecated since version 2.0.0 "
30
+ "and it will be removed in a future release. "
31
+ "Please replace calls to 'is_blank()' with alternative implementation.",
32
+ DeprecationWarning
33
+ )
153
34
  return value.strip() == ""
154
-
155
-
156
- def parse_extn(extn=''):
157
- """
158
- Parse a string representing a qualified fits extension name as in the
159
- output of parse_filename and return a tuple (str(extname), int(extver)),
160
- which can be passed to pyfits functions using the 'ext' kw.
161
- Default return is the first extension in a fits file.
162
-
163
- Examples
164
- --------
165
- >>> parse_extn('sci,2')
166
- ('sci', 2)
167
- >>> parse_extn('2')
168
- ('', 2)
169
- >>> parse_extn('sci')
170
- ('sci', 1)
171
-
172
- Parameters
173
- ----------
174
- extn : str
175
- The extension name
176
-
177
- Returns
178
- -------
179
- A tuple of the extension name and value
180
- """
181
- if not extn:
182
- return ('', 0)
183
-
184
- try:
185
- lext = extn.split(',')
186
- except Exception:
187
- return ('', 1)
188
-
189
- if len(lext) == 1 and lext[0].isdigit():
190
- return ("", int(lext[0]))
191
- elif len(lext) == 2:
192
- return (lext[0], int(lext[1]))
193
- else:
194
- return (lext[0], 1)
195
-
196
-
197
- def parse_filename(filename):
198
- """
199
- Parse out filename from any specified extensions.
200
- Returns rootname and string version of extension name.
201
-
202
- Parameters
203
- ----------
204
-
205
- filename : str
206
- The filename to be parsed
207
-
208
- Returns
209
- -------
210
-
211
- A tuple with the filename root and extension
212
- """
213
- # Parse out any extension specified in filename
214
- _indx = filename.find('[')
215
- if _indx > 0:
216
- # Read extension name provided
217
- _fname = filename[:_indx]
218
- _extn = filename[_indx + 1:-1]
219
- else:
220
- _fname = filename
221
- _extn = ''
222
-
223
- return _fname, _extn
224
-
225
-
226
- def set_pscale(the_wcs):
227
- """
228
- Calculates the plate scale from cdelt and the pc matrix and adds
229
- it to the WCS. Plate scale is not part of the WCS standard, but is
230
- required by the drizzle code
231
-
232
- Parameters
233
- ----------
234
-
235
- the_wcs : wcs
236
- A WCS object
237
- """
238
- try:
239
- cdelt = the_wcs.wcs.get_cdelt()
240
- pc = the_wcs.wcs.get_pc()
241
-
242
- except Exception:
243
- try:
244
- # for non-celestial axes, get_cdelt doesnt work
245
- cdelt = the_wcs.wcs.cd * the_wcs.wcs.cdelt
246
- except AttributeError:
247
- cdelt = the_wcs.wcs.cdelt
248
-
249
- try:
250
- pc = the_wcs.wcs.pc
251
- except AttributeError:
252
- pc = 1
253
-
254
- pccd = np.array(cdelt * pc)
255
- scales = np.sqrt((pccd ** 2).sum(axis=0, dtype=float))
256
- the_wcs.pscale = scales[0]