drizzle 2.0.1__cp311-cp311-win_amd64.whl → 2.1.1__cp311-cp311-win_amd64.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.
- drizzle/cdrizzle.cp311-win_amd64.pyd +0 -0
- drizzle/resample.py +22 -17
- drizzle/tests/helpers.py +61 -30
- drizzle/tests/test_overlap_calc.py +24 -0
- drizzle/tests/test_resample.py +255 -5
- drizzle/tests/test_utils.py +1 -2
- drizzle/utils.py +1 -1
- {drizzle-2.0.1.dist-info → drizzle-2.1.1.dist-info}/METADATA +6 -37
- drizzle-2.1.1.dist-info/RECORD +16 -0
- {drizzle-2.0.1.dist-info → drizzle-2.1.1.dist-info}/WHEEL +1 -1
- drizzle-2.0.1.dist-info/RECORD +0 -16
- {drizzle-2.0.1.dist-info → drizzle-2.1.1.dist-info/licenses}/LICENSE.rst +0 -0
- {drizzle-2.0.1.dist-info → drizzle-2.1.1.dist-info}/top_level.txt +0 -0
|
Binary file
|
drizzle/resample.py
CHANGED
|
@@ -76,23 +76,24 @@ class Drizzle:
|
|
|
76
76
|
information about which input image has contributed to the corresponding
|
|
77
77
|
pixel in the resampled data array. Context image uses 32 bit integers to
|
|
78
78
|
encode this information and hence it can keep track of only 32 input images.
|
|
79
|
-
|
|
80
|
-
second input image, and so on.
|
|
81
|
-
|
|
79
|
+
The first bit corresponds to the first input image, the second bit
|
|
80
|
+
corresponds to the second input image, and so on.
|
|
81
|
+
We call this (0-indexed) order "context ID" which is represented by
|
|
82
|
+
the ``ctx_id`` parameter/property. If the number of
|
|
82
83
|
input images exceeds 32, then it is necessary to have multiple context
|
|
83
|
-
images ("planes") to hold information about all input images with the first
|
|
84
|
+
images ("planes") to hold information about all input images, with the first
|
|
84
85
|
plane encoding which of the first 32 images contributed to the output data
|
|
85
|
-
pixel, second plane representing next 32 input images (number 33-64),
|
|
86
|
-
For this reason, context array is either a 2D array (if the total
|
|
87
|
-
of resampled images is less than 33) of the type `numpy.int32` and
|
|
88
|
-
``(ny, nx)`` or a a 3D array of shape ``(np, ny, nx)`` where ``nx``
|
|
89
|
-
``ny`` are dimensions of image
|
|
90
|
-
|
|
91
|
-
``k`` in a pixel with coordinates ``(p, y, x)`` is 0 then input
|
|
92
|
-
``32 * p + k`` (0-indexed) did not contribute to the output
|
|
93
|
-
with array coordinates ``(y, x)`` and if that bit is 1 then
|
|
94
|
-
number ``32 * p + k`` did contribute to the pixel ``(y, x)``
|
|
95
|
-
resampled image.
|
|
86
|
+
pixel, the second plane representing next 32 input images (number 33-64),
|
|
87
|
+
etc. For this reason, context array is either a 2D array (if the total
|
|
88
|
+
number of resampled images is less than 33) of the type `numpy.int32` and
|
|
89
|
+
shape ``(ny, nx)`` or a a 3D array of shape ``(np, ny, nx)`` where ``nx``
|
|
90
|
+
and ``ny`` are dimensions of the image data. ``np`` is the number of
|
|
91
|
+
"planes" computed as ``(number of input images - 1) // 32 + 1``. If a bit at
|
|
92
|
+
position ``k`` in a pixel with coordinates ``(p, y, x)`` is 0, then input
|
|
93
|
+
image number ``32 * p + k`` (0-indexed) did not contribute to the output
|
|
94
|
+
data pixel with array coordinates ``(y, x)`` and if that bit is 1, then
|
|
95
|
+
input image number ``32 * p + k`` did contribute to the pixel ``(y, x)``
|
|
96
|
+
in the resampled image.
|
|
96
97
|
|
|
97
98
|
As an example, let's assume we have 8 input images. Then, when ``out_ctx``
|
|
98
99
|
pixel values are displayed using binary representation (and decimal in
|
|
@@ -413,7 +414,11 @@ class Drizzle:
|
|
|
413
414
|
)
|
|
414
415
|
|
|
415
416
|
if out_img is None:
|
|
416
|
-
self.
|
|
417
|
+
if self._fillval.upper() in ["INDEF", "NAN"]:
|
|
418
|
+
fillval = np.nan
|
|
419
|
+
else:
|
|
420
|
+
fillval = float(self._fillval)
|
|
421
|
+
self._out_img = np.full(out_shape, fillval, dtype=np.float32)
|
|
417
422
|
else:
|
|
418
423
|
self._out_img = out_img
|
|
419
424
|
|
|
@@ -548,7 +553,7 @@ class Drizzle:
|
|
|
548
553
|
|
|
549
554
|
self._alloc_output_arrays(
|
|
550
555
|
out_shape=self._out_shape,
|
|
551
|
-
max_ctx_id=
|
|
556
|
+
max_ctx_id=self._max_ctx_id,
|
|
552
557
|
out_img=None,
|
|
553
558
|
out_wht=None,
|
|
554
559
|
out_ctx=None,
|
drizzle/tests/helpers.py
CHANGED
|
@@ -56,40 +56,71 @@ def wcs_from_file(filename, ext=None, return_data=False, crpix_shift=None,
|
|
|
56
56
|
"""
|
|
57
57
|
full_file_name = os.path.join(DATA_DIR, filename)
|
|
58
58
|
path = os.path.join(DATA_DIR, full_file_name)
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
59
|
+
|
|
60
|
+
def get_shape(hdr):
|
|
61
|
+
naxis1 = hdr.get("WCSNAX1", hdr.get("NAXIS1"))
|
|
62
|
+
naxis2 = hdr.get("WCSNAX2", hdr.get("NAXIS2"))
|
|
63
|
+
if naxis1 is None or naxis2 is None:
|
|
64
|
+
return None
|
|
65
|
+
return (naxis2, naxis1)
|
|
66
|
+
|
|
67
|
+
def data_from_hdr(hdr, data=None, shape=None):
|
|
68
|
+
if data is not None:
|
|
69
|
+
return data
|
|
70
|
+
bitpix = hdr.get("BITPIX", -32)
|
|
71
|
+
dtype = fits.hdu.BITPIX2DTYPE[bitpix]
|
|
72
|
+
shape = get_shape(hdr) or shape
|
|
73
|
+
if shape is None:
|
|
74
|
+
return None
|
|
75
|
+
return np.zeros(shape, dtype=dtype)
|
|
76
|
+
|
|
77
|
+
if os.path.splitext(filename)[1] in [".hdr", ".txt"]:
|
|
78
|
+
hdul = None
|
|
79
|
+
hdr = fits.Header.fromfile(
|
|
80
|
+
path,
|
|
81
|
+
sep='\n',
|
|
82
|
+
endcard=False,
|
|
83
|
+
padding=False
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
else:
|
|
87
|
+
with fits.open(path) as fits_hdul:
|
|
88
|
+
hdul = fits.HDUList([hdu.copy() for hdu in fits_hdul])
|
|
89
|
+
|
|
90
|
+
if ext is None and hdul is not None:
|
|
91
|
+
for k, u in enumerate(hdul):
|
|
62
92
|
if "CTYPE1" in u.header:
|
|
63
93
|
ext = k
|
|
64
94
|
break
|
|
65
95
|
|
|
66
|
-
hdr =
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
96
|
+
hdr = hdul[ext].header
|
|
97
|
+
|
|
98
|
+
if crpix_shift is not None and "CRPIX1" in hdr:
|
|
99
|
+
hdr["CRPIX1"] += crpix_shift[0]
|
|
100
|
+
hdr["CRPIX2"] += crpix_shift[1]
|
|
101
|
+
|
|
102
|
+
result = fits_wcs.WCS(hdr, hdul)
|
|
103
|
+
shape = get_shape(hdr)
|
|
104
|
+
result.array_shape = shape
|
|
105
|
+
|
|
106
|
+
if wcs_type == "gwcs":
|
|
107
|
+
result = _gwcs_from_hst_fits_wcs(result)
|
|
108
|
+
|
|
109
|
+
if return_data:
|
|
110
|
+
if hdul is None:
|
|
111
|
+
data = data_from_hdr(hdr, data=None, shape=shape)
|
|
112
|
+
return (result, data)
|
|
113
|
+
|
|
114
|
+
result = (result, )
|
|
115
|
+
if not isinstance(return_data, (list, tuple)):
|
|
116
|
+
return_data = [ext]
|
|
117
|
+
for ext in return_data:
|
|
118
|
+
data = data_from_hdr(
|
|
119
|
+
hdul[ext].header,
|
|
120
|
+
data=hdul[ext].data,
|
|
121
|
+
shape=shape
|
|
122
|
+
)
|
|
123
|
+
result = result + (data, )
|
|
93
124
|
|
|
94
125
|
return result
|
|
95
126
|
|
|
@@ -260,3 +260,27 @@ def test_intersection_case01():
|
|
|
260
260
|
cp = clip_polygon(p, wnd)
|
|
261
261
|
|
|
262
262
|
assert _is_poly_eq(cp, cp_ref)
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
def test_intersection_case02():
|
|
266
|
+
# a real case of failure reported in #189
|
|
267
|
+
p = [
|
|
268
|
+
(-0.04000000000000009104, 1.5),
|
|
269
|
+
(2.73499999999999943157, 1.5),
|
|
270
|
+
(1.83500000000000018652, -0.5),
|
|
271
|
+
(-0.03999999999999998002, -0.5),
|
|
272
|
+
]
|
|
273
|
+
wnd = [
|
|
274
|
+
(-0.5, -0.5), (3.5, -0.5), (3.5, 3.5), (-0.5, 3.5)
|
|
275
|
+
]
|
|
276
|
+
|
|
277
|
+
cp_ref = [
|
|
278
|
+
(-0.04, 1.5),
|
|
279
|
+
(-0.04, -0.5),
|
|
280
|
+
(1.835, -0.5),
|
|
281
|
+
(2.735, 1.5),
|
|
282
|
+
]
|
|
283
|
+
|
|
284
|
+
cp = clip_polygon(p, wnd)
|
|
285
|
+
|
|
286
|
+
assert _is_poly_eq(cp, cp_ref)
|
drizzle/tests/test_resample.py
CHANGED
|
@@ -5,6 +5,7 @@ import numpy as np
|
|
|
5
5
|
import pytest
|
|
6
6
|
|
|
7
7
|
from astropy import wcs
|
|
8
|
+
from astropy.convolution import Gaussian2DKernel
|
|
8
9
|
from drizzle import cdrizzle, resample, utils
|
|
9
10
|
|
|
10
11
|
from .helpers import wcs_from_file
|
|
@@ -191,6 +192,57 @@ def make_grid_image(shape, spacing, value):
|
|
|
191
192
|
return output_image
|
|
192
193
|
|
|
193
194
|
|
|
195
|
+
@pytest.fixture(scope="module")
|
|
196
|
+
def nrcb5_stars():
|
|
197
|
+
full_file_name = os.path.join(DATA_DIR, "nrcb5_sip_wcs.hdr")
|
|
198
|
+
path = os.path.join(DATA_DIR, full_file_name)
|
|
199
|
+
|
|
200
|
+
wcs, data = wcs_from_file(path, return_data=True)
|
|
201
|
+
dq = np.zeros(data.shape, dtype=np.int32)
|
|
202
|
+
wht = np.zeros(data.shape, dtype=np.float32)
|
|
203
|
+
np.random.seed(0)
|
|
204
|
+
|
|
205
|
+
patch_size = 21
|
|
206
|
+
p2 = patch_size // 2
|
|
207
|
+
# add border so that resampled partial pixels can be isolated
|
|
208
|
+
# in the segmentation:
|
|
209
|
+
border = 4
|
|
210
|
+
pwb = patch_size + border
|
|
211
|
+
|
|
212
|
+
fwhm2sigma = 2.0 * math.sqrt(2.0 * math.log(2.0))
|
|
213
|
+
|
|
214
|
+
ny, nx = data.shape
|
|
215
|
+
|
|
216
|
+
stars = []
|
|
217
|
+
|
|
218
|
+
for yc in range(border + p2, ny - pwb, pwb):
|
|
219
|
+
for xc in range(border + p2, nx - pwb, pwb):
|
|
220
|
+
sl = np.s_[yc - p2:yc + p2 + 1, xc - p2:xc + p2 + 1]
|
|
221
|
+
flux = 1.0 + 99.0 * np.random.random()
|
|
222
|
+
if np.random.random() > 0.7:
|
|
223
|
+
# uniform image
|
|
224
|
+
psf = np.full((patch_size, patch_size), flux)
|
|
225
|
+
else:
|
|
226
|
+
# "star":
|
|
227
|
+
fwhm = 1.5 + 1.5 * np.random.random()
|
|
228
|
+
sigma = fwhm / fwhm2sigma
|
|
229
|
+
|
|
230
|
+
psf = flux * Gaussian2DKernel(
|
|
231
|
+
sigma,
|
|
232
|
+
x_size=patch_size,
|
|
233
|
+
y_size=patch_size
|
|
234
|
+
).array
|
|
235
|
+
weight = 0.6 + 0.4 * np.random.random((patch_size, patch_size))
|
|
236
|
+
wflux = (psf * weight).sum()
|
|
237
|
+
|
|
238
|
+
data[sl] = psf
|
|
239
|
+
wht[sl] = weight
|
|
240
|
+
dq[sl] = 0
|
|
241
|
+
stars.append((xc, yc, wflux, sl))
|
|
242
|
+
|
|
243
|
+
return data, wht, dq, stars, wcs
|
|
244
|
+
|
|
245
|
+
|
|
194
246
|
def test_drizzle_defaults():
|
|
195
247
|
n = 200
|
|
196
248
|
in_shape = (n, n)
|
|
@@ -234,6 +286,7 @@ def test_drizzle_defaults():
|
|
|
234
286
|
assert driz.out_img[1, 2] == 1
|
|
235
287
|
assert (driz.out_img[2, 1] - 2.0) < 1.0e-14
|
|
236
288
|
|
|
289
|
+
|
|
237
290
|
@pytest.mark.parametrize(
|
|
238
291
|
'kernel,test_image_type,max_diff_atol',
|
|
239
292
|
[
|
|
@@ -303,7 +356,10 @@ def test_resample_kernel(tmpdir, kernel, test_image_type, max_diff_atol):
|
|
|
303
356
|
scale=pscale_ratio,
|
|
304
357
|
)
|
|
305
358
|
else:
|
|
306
|
-
with pytest.warns(
|
|
359
|
+
with pytest.warns(
|
|
360
|
+
Warning,
|
|
361
|
+
match=f"Kernel '{kernel}' is not a flux-conserving kernel"
|
|
362
|
+
):
|
|
307
363
|
driz.add_image(
|
|
308
364
|
insci,
|
|
309
365
|
exptime=1.0,
|
|
@@ -434,7 +490,10 @@ def test_zero_input_weight(kernel, fc):
|
|
|
434
490
|
fillstr='INDEF',
|
|
435
491
|
)
|
|
436
492
|
else:
|
|
437
|
-
with pytest.warns(
|
|
493
|
+
with pytest.warns(
|
|
494
|
+
Warning,
|
|
495
|
+
match=f"Kernel '{kernel}' is not a flux-conserving kernel"
|
|
496
|
+
):
|
|
438
497
|
cdrizzle.tdriz(
|
|
439
498
|
insci,
|
|
440
499
|
inwht,
|
|
@@ -708,7 +767,10 @@ def test_flux_conservation_nondistorted(kernel, fc):
|
|
|
708
767
|
wtscale=1.0,
|
|
709
768
|
)
|
|
710
769
|
else:
|
|
711
|
-
with pytest.warns(
|
|
770
|
+
with pytest.warns(
|
|
771
|
+
Warning,
|
|
772
|
+
match=f"Kernel '{kernel}' is not a flux-conserving kernel"
|
|
773
|
+
):
|
|
712
774
|
cdrizzle.tdriz(
|
|
713
775
|
in_sci,
|
|
714
776
|
in_wht,
|
|
@@ -796,7 +858,10 @@ def test_flux_conservation_distorted(kernel, fc):
|
|
|
796
858
|
wtscale=1.0,
|
|
797
859
|
)
|
|
798
860
|
else:
|
|
799
|
-
with pytest.warns(
|
|
861
|
+
with pytest.warns(
|
|
862
|
+
Warning,
|
|
863
|
+
match=f"Kernel '{kernel}' is not a flux-conserving kernel"
|
|
864
|
+
):
|
|
800
865
|
cdrizzle.tdriz(
|
|
801
866
|
in_sci,
|
|
802
867
|
in_wht,
|
|
@@ -821,6 +886,50 @@ def test_flux_conservation_distorted(kernel, fc):
|
|
|
821
886
|
)
|
|
822
887
|
|
|
823
888
|
|
|
889
|
+
@pytest.mark.parametrize("kernel", ["square", "turbo", "point"])
|
|
890
|
+
@pytest.mark.parametrize("pscale_ratio", [0.55, 1.0, 1.2])
|
|
891
|
+
def test_flux_conservation_distorted_distributed_sources(nrcb5_stars, kernel, pscale_ratio):
|
|
892
|
+
""" test aperture photometry """
|
|
893
|
+
insci, inwht, dq, stars, wcs = nrcb5_stars
|
|
894
|
+
|
|
895
|
+
suffix = f"{pscale_ratio}".replace(".", "p")
|
|
896
|
+
output_wcs = wcs_from_file(f"nrcb5_output_wcs_psr_{suffix}.hdr")
|
|
897
|
+
|
|
898
|
+
pixmap = utils.calc_pixmap(
|
|
899
|
+
wcs,
|
|
900
|
+
output_wcs,
|
|
901
|
+
wcs.array_shape,
|
|
902
|
+
)
|
|
903
|
+
|
|
904
|
+
driz = resample.Drizzle(
|
|
905
|
+
kernel=kernel,
|
|
906
|
+
out_shape=output_wcs.array_shape,
|
|
907
|
+
fillval=0.0,
|
|
908
|
+
)
|
|
909
|
+
driz.add_image(
|
|
910
|
+
insci,
|
|
911
|
+
exptime=1.0,
|
|
912
|
+
pixmap=pixmap,
|
|
913
|
+
weight_map=inwht,
|
|
914
|
+
scale=1,
|
|
915
|
+
)
|
|
916
|
+
|
|
917
|
+
# for efficiency, instead of doing this patch-by-patch,
|
|
918
|
+
# multiply resampled data by resampled image weight
|
|
919
|
+
out_data = driz.out_img * driz.out_wht
|
|
920
|
+
|
|
921
|
+
dim3 = (slice(None, None, None), )
|
|
922
|
+
for _, _, fin, sl in stars:
|
|
923
|
+
xyout = pixmap[sl + dim3]
|
|
924
|
+
xmin = int(np.floor(xyout[:, :, 0].min() - 0.5))
|
|
925
|
+
xmax = int(np.ceil(xyout[:, :, 0].max() + 1.5))
|
|
926
|
+
ymin = int(np.floor(xyout[:, :, 1].min() - 0.5))
|
|
927
|
+
ymax = int(np.ceil(xyout[:, :, 1].max() + 1.5))
|
|
928
|
+
fout = np.nansum(out_data[ymin:ymax, xmin:xmax])
|
|
929
|
+
|
|
930
|
+
assert np.allclose(fin, fout, rtol=1.0e-6, atol=0.0)
|
|
931
|
+
|
|
932
|
+
|
|
824
933
|
def test_drizzle_exptime():
|
|
825
934
|
n = 200
|
|
826
935
|
in_shape = (n, n)
|
|
@@ -1042,7 +1151,7 @@ def test_resample_get_shape_from_pixmap():
|
|
|
1042
1151
|
exptime=0.0,
|
|
1043
1152
|
)
|
|
1044
1153
|
|
|
1045
|
-
driz.add_image(in_sci, weight_map=in_wht, exptime=1
|
|
1154
|
+
driz.add_image(in_sci, weight_map=in_wht, exptime=0.1, pixmap=pixmap)
|
|
1046
1155
|
assert driz.out_img.shape == in_shape
|
|
1047
1156
|
|
|
1048
1157
|
|
|
@@ -1098,3 +1207,144 @@ def test_resample_inconsistent_output():
|
|
|
1098
1207
|
out_wht=out_wht,
|
|
1099
1208
|
)
|
|
1100
1209
|
assert str(err_info.value).startswith("Inconsistent data shapes specified")
|
|
1210
|
+
|
|
1211
|
+
|
|
1212
|
+
def test_resample_disable_ctx():
|
|
1213
|
+
n = 20
|
|
1214
|
+
in_shape = (n, n)
|
|
1215
|
+
|
|
1216
|
+
pixmap = np.dstack(np.indices(in_shape, dtype=np.float64)[::-1])
|
|
1217
|
+
|
|
1218
|
+
# simulate constant data:
|
|
1219
|
+
in_sci = np.ones(in_shape, dtype=np.float32)
|
|
1220
|
+
|
|
1221
|
+
driz = resample.Drizzle(
|
|
1222
|
+
disable_ctx=True,
|
|
1223
|
+
)
|
|
1224
|
+
|
|
1225
|
+
driz.add_image(in_sci, exptime=1.0, pixmap=pixmap)
|
|
1226
|
+
|
|
1227
|
+
|
|
1228
|
+
@pytest.mark.parametrize(
|
|
1229
|
+
"fillval", ["NaN", "INDEF", "", None]
|
|
1230
|
+
)
|
|
1231
|
+
def test_nan_fillval(fillval):
|
|
1232
|
+
driz = resample.Drizzle(
|
|
1233
|
+
kernel='square',
|
|
1234
|
+
fillval=fillval,
|
|
1235
|
+
out_shape=(20, 20)
|
|
1236
|
+
)
|
|
1237
|
+
|
|
1238
|
+
assert np.all(np.isnan(driz.out_img))
|
|
1239
|
+
|
|
1240
|
+
|
|
1241
|
+
def test_resample_edge_sgarea_bug():
|
|
1242
|
+
"""
|
|
1243
|
+
Test from https://github.com/spacetelescope/drizzle/issues/187
|
|
1244
|
+
|
|
1245
|
+
"""
|
|
1246
|
+
pixmap = (np.array([
|
|
1247
|
+
[
|
|
1248
|
+
[0.31887051, 1.],
|
|
1249
|
+
[1.01898591, 1.],
|
|
1250
|
+
[1.71909665, 1.],
|
|
1251
|
+
],
|
|
1252
|
+
[
|
|
1253
|
+
[0.31591881, 0.],
|
|
1254
|
+
[1.0160342312345672, 0.],
|
|
1255
|
+
[1.716145, 0.],
|
|
1256
|
+
]
|
|
1257
|
+
], dtype="f8"))
|
|
1258
|
+
|
|
1259
|
+
in_shape = pixmap.shape[:2]
|
|
1260
|
+
img = np.full(in_shape, 42, dtype=np.float32)
|
|
1261
|
+
out_shape = (4, 4)
|
|
1262
|
+
|
|
1263
|
+
driz = resample.Drizzle(
|
|
1264
|
+
kernel='square',
|
|
1265
|
+
fillval='nan',
|
|
1266
|
+
out_shape=out_shape,
|
|
1267
|
+
disable_ctx=True,
|
|
1268
|
+
)
|
|
1269
|
+
|
|
1270
|
+
driz.add_image(
|
|
1271
|
+
img,
|
|
1272
|
+
exptime=11.776,
|
|
1273
|
+
in_units='cps',
|
|
1274
|
+
pixfrac=1.0,
|
|
1275
|
+
pixmap=pixmap,
|
|
1276
|
+
scale=1.0,
|
|
1277
|
+
wht_scale=1.0,
|
|
1278
|
+
)
|
|
1279
|
+
# expected pixels should be close to 42
|
|
1280
|
+
np.testing.assert_allclose(driz.out_img[:2, :3], img[0, 0], rtol=1e-6)
|
|
1281
|
+
|
|
1282
|
+
# other values should be nan
|
|
1283
|
+
np.testing.assert_equal(driz.out_img[:, 3:], np.nan)
|
|
1284
|
+
np.testing.assert_equal(driz.out_img[2:], np.nan)
|
|
1285
|
+
|
|
1286
|
+
|
|
1287
|
+
def test_resample_edge_collinear():
|
|
1288
|
+
"""
|
|
1289
|
+
Test that resample does not crash when the input image is smaller than the
|
|
1290
|
+
output image, and the edges of the two images are nearly collinear.
|
|
1291
|
+
|
|
1292
|
+
Test based on the example from
|
|
1293
|
+
https://github.com/spacetelescope/drizzle/issues/189#issue-3196294879
|
|
1294
|
+
|
|
1295
|
+
"""
|
|
1296
|
+
pixmap = (np.array([
|
|
1297
|
+
[
|
|
1298
|
+
[0.31, 1.0],
|
|
1299
|
+
[1.01, 1.0],
|
|
1300
|
+
[2.01, 1.0],
|
|
1301
|
+
],
|
|
1302
|
+
[
|
|
1303
|
+
[0.31, 0.],
|
|
1304
|
+
[1.01, 0.],
|
|
1305
|
+
[1.71, 0.],
|
|
1306
|
+
]
|
|
1307
|
+
], dtype="f8"))
|
|
1308
|
+
|
|
1309
|
+
in_shape = pixmap.shape[:2]
|
|
1310
|
+
img = np.full(in_shape, np.pi, dtype=np.float32)
|
|
1311
|
+
in_flux = np.sum(img)
|
|
1312
|
+
out_shape = (4, 4)
|
|
1313
|
+
|
|
1314
|
+
driz = resample.Drizzle(
|
|
1315
|
+
kernel='square',
|
|
1316
|
+
fillval='nan',
|
|
1317
|
+
out_shape=out_shape,
|
|
1318
|
+
disable_ctx=True,
|
|
1319
|
+
)
|
|
1320
|
+
|
|
1321
|
+
driz.add_image(
|
|
1322
|
+
img,
|
|
1323
|
+
exptime=11.776,
|
|
1324
|
+
in_units='cps',
|
|
1325
|
+
pixfrac=1.0,
|
|
1326
|
+
pixmap=pixmap,
|
|
1327
|
+
scale=1.0,
|
|
1328
|
+
wht_scale=1.0,
|
|
1329
|
+
)
|
|
1330
|
+
|
|
1331
|
+
out_flux = np.nansum(driz.out_img * driz.out_wht)
|
|
1332
|
+
|
|
1333
|
+
# Given this pixmap, the entire input image should fit within the output
|
|
1334
|
+
# image. There should be at least 7 pixels with finite values in the output
|
|
1335
|
+
# image. We can get more than 7 pixels with finite values due to rounding
|
|
1336
|
+
# errors when computing polygon intersections (those "extra" pixels should)
|
|
1337
|
+
# have very small weights.
|
|
1338
|
+
assert np.sum(driz.out_wht > 1e-30) == 7
|
|
1339
|
+
assert np.sum(np.isfinite(driz.out_img)) >= 7
|
|
1340
|
+
# output image intensity must be equal to the input image intensity:
|
|
1341
|
+
assert np.allclose(
|
|
1342
|
+
driz.out_img[np.isfinite(driz.out_img)],
|
|
1343
|
+
img[0, 0],
|
|
1344
|
+
rtol=0,
|
|
1345
|
+
atol=1e-6
|
|
1346
|
+
)
|
|
1347
|
+
# flux in the output image should be equal to the flux in the input image:
|
|
1348
|
+
assert np.allclose(out_flux, in_flux, rtol=1e-6, atol=0.0)
|
|
1349
|
+
# area of the signal in the input image:
|
|
1350
|
+
assert np.allclose(np.sum(driz.out_wht), 6.0, rtol=0, atol=1.0e-6)
|
drizzle/tests/test_utils.py
CHANGED
|
@@ -2,6 +2,7 @@ import numpy as np
|
|
|
2
2
|
import pytest
|
|
3
3
|
from numpy.testing import assert_almost_equal, assert_equal
|
|
4
4
|
|
|
5
|
+
from drizzle.tests.helpers import wcs_from_file
|
|
5
6
|
from drizzle.utils import (
|
|
6
7
|
_estimate_pixel_scale,
|
|
7
8
|
calc_pixmap,
|
|
@@ -9,8 +10,6 @@ from drizzle.utils import (
|
|
|
9
10
|
estimate_pixel_scale_ratio,
|
|
10
11
|
)
|
|
11
12
|
|
|
12
|
-
from .helpers import wcs_from_file
|
|
13
|
-
|
|
14
13
|
|
|
15
14
|
def test_map_rectangular():
|
|
16
15
|
"""
|
drizzle/utils.py
CHANGED
|
@@ -96,7 +96,7 @@ def calc_pixmap(wcs_from, wcs_to, shape=None, disable_bbox="to"):
|
|
|
96
96
|
bbox_from = (bbox_from, )
|
|
97
97
|
if nd > 1:
|
|
98
98
|
shape = tuple(
|
|
99
|
-
|
|
99
|
+
math.ceil(lim[1] + 0.5) for lim in bbox_from[::-1]
|
|
100
100
|
)
|
|
101
101
|
|
|
102
102
|
if shape is None:
|
|
@@ -1,40 +1,8 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: drizzle
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.1.1
|
|
4
4
|
Summary: A package for combining dithered images into a single image
|
|
5
5
|
Author-email: STScI <help@stsci.edu>
|
|
6
|
-
License: Copyright (C) 2011,2014 Association of Universities for Research in
|
|
7
|
-
Astronomy (AURA)
|
|
8
|
-
|
|
9
|
-
Redistribution and use in source and binary forms, with or without
|
|
10
|
-
modification, are permitted provided that the following conditions
|
|
11
|
-
are met:
|
|
12
|
-
|
|
13
|
-
1. Redistributions of source code must retain the above
|
|
14
|
-
copyright notice, this list of conditions and the following
|
|
15
|
-
disclaimer.
|
|
16
|
-
|
|
17
|
-
2. Redistributions in binary form must reproduce the above
|
|
18
|
-
copyright notice, this list of conditions and the following
|
|
19
|
-
disclaimer in the documentation and/or other materials
|
|
20
|
-
provided with the distribution.
|
|
21
|
-
|
|
22
|
-
3. The name of AURA and its representatives may not be used to
|
|
23
|
-
endorse or promote products derived from this software without
|
|
24
|
-
specific prior written permission.
|
|
25
|
-
|
|
26
|
-
THIS SOFTWARE IS PROVIDED BY AURA ``AS IS'' AND ANY EXPRESS OR
|
|
27
|
-
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
28
|
-
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
29
|
-
ARE DISCLAIMED. IN NO EVENT SHALL AURA BE LIABLE FOR ANY DIRECT,
|
|
30
|
-
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
31
|
-
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
32
|
-
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
33
|
-
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
34
|
-
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
35
|
-
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
|
36
|
-
OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
37
|
-
|
|
38
6
|
Project-URL: Homepage, https://github.com/spacetelescope/drizzle
|
|
39
7
|
Project-URL: Bug Tracker, https://github.com/spacetelescope/drizzle/issues
|
|
40
8
|
Project-URL: Documentation, http://spacetelescope.github.io/drizzle/
|
|
@@ -56,6 +24,7 @@ Requires-Dist: sphinx-automodapi; extra == "docs"
|
|
|
56
24
|
Requires-Dist: sphinx-rtd-theme; extra == "docs"
|
|
57
25
|
Requires-Dist: matplotlib; extra == "docs"
|
|
58
26
|
Requires-Dist: pytest-doctestplus; extra == "docs"
|
|
27
|
+
Dynamic: license-file
|
|
59
28
|
|
|
60
29
|
drizzle Documentation
|
|
61
30
|
=====================
|
|
@@ -108,8 +77,8 @@ Requirements
|
|
|
108
77
|
The Drizzle Algorithm
|
|
109
78
|
---------------------
|
|
110
79
|
|
|
111
|
-
This section has been extracted from Chapter
|
|
112
|
-
`The DrizzlePac Handbook <
|
|
80
|
+
This section has been extracted from Chapter 3 of
|
|
81
|
+
`The DrizzlePac Handbook <https://hst-docs.stsci.edu/drizzpac>`_ [Driz2025]_
|
|
113
82
|
|
|
114
83
|
There are a family of linear reconstruction techniques that, at two opposite
|
|
115
84
|
extremes, are represented by the interlacing and shift-and-add techniques, with
|
|
@@ -200,4 +169,4 @@ for identifying cosmic rays in the original image. Blot requires the user
|
|
|
200
169
|
to provide the world coordinate system (WCS)-based transformations in the
|
|
201
170
|
form of a pixel map array as input.
|
|
202
171
|
|
|
203
|
-
.. [
|
|
172
|
+
.. [Driz2025] Anand, G. S., Mack, J., et al., 2025, “The DrizzlePac Handbook”, Version 3.0, (Baltimore: STScI)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
drizzle/__init__.py,sha256=hMpqmjPhrUWTRU0eXNOcrpiqQFGp4lf9opY8FXqLLEQ,325
|
|
2
|
+
drizzle/cdrizzle.cp311-win_amd64.pyd,sha256=K4S53mhlTqiuRXdsirvSHn359sagxo6wqGUchNzISdw,102912
|
|
3
|
+
drizzle/resample.py,sha256=lps_nPPcEtOID3Y1oJALaFXQ8AyhFrmWu70O0z-tDak,29157
|
|
4
|
+
drizzle/util.py,sha256=os9wHm1JkKiG5jtnNCZAXG3vnnXxLHBpi8OTWsiPI7k,845
|
|
5
|
+
drizzle/utils.py,sha256=HvRPduBswRwi3OLN48tjv7y7XkP_sfcbNtxmcrfIDy0,10841
|
|
6
|
+
drizzle/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
|
+
drizzle/tests/helpers.py,sha256=vD2uBLKTlgNXeLdof7kCdrOJRTQ8HQEQDvUChqB1PSQ,6673
|
|
8
|
+
drizzle/tests/test_cdrizzle.py,sha256=utepqMiY8xtgQ8gBRBHwnlMhbBB1pq1xE4spf-wO7Kw,726
|
|
9
|
+
drizzle/tests/test_overlap_calc.py,sha256=umROaVBJQUVozJUyTB52oPaV3GVkcLiNhAr4z_9JZe0,7598
|
|
10
|
+
drizzle/tests/test_resample.py,sha256=SKhqAbEjKEIxUBKT3gcyfL8LiA9KsbTFt5rQHL-e40k,38856
|
|
11
|
+
drizzle/tests/test_utils.py,sha256=h24pE4cM-_FPPpZ9jBc9IdWKvKwFoTiA2ENeJx0oN6Q,7702
|
|
12
|
+
drizzle-2.1.1.dist-info/licenses/LICENSE.rst,sha256=sUXj5W73D9TcOw5ZXaDdcthYdY2b2dTJPsxBuZTOYWQ,1505
|
|
13
|
+
drizzle-2.1.1.dist-info/METADATA,sha256=MXMPJY-Vlw615zObvlnGrTx87ff2p7nVM0YXqfjuGGU,9104
|
|
14
|
+
drizzle-2.1.1.dist-info/WHEEL,sha256=JLOMsP7F5qtkAkINx5UnzbFguf8CqZeraV8o04b0I8I,101
|
|
15
|
+
drizzle-2.1.1.dist-info/top_level.txt,sha256=MA5uqwTj1sJBi-hCeQj9v3-sZ9nVUTe6bd_zGWTKy5A,8
|
|
16
|
+
drizzle-2.1.1.dist-info/RECORD,,
|
drizzle-2.0.1.dist-info/RECORD
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
drizzle/__init__.py,sha256=hMpqmjPhrUWTRU0eXNOcrpiqQFGp4lf9opY8FXqLLEQ,325
|
|
2
|
-
drizzle/cdrizzle.cp311-win_amd64.pyd,sha256=_PEpXUcvcJFL1kep8KmmAm8Zapc8tJ82lflmol1ALj0,100864
|
|
3
|
-
drizzle/resample.py,sha256=LXc3TxaXvOd05zrszMa94JZbMSu7T3kDn4zoL3N7yeI,28982
|
|
4
|
-
drizzle/util.py,sha256=os9wHm1JkKiG5jtnNCZAXG3vnnXxLHBpi8OTWsiPI7k,845
|
|
5
|
-
drizzle/utils.py,sha256=hz6TVSb5dWIVw3P28EeeSc6PjVJNy4JAG5tB1v1yIrE,10846
|
|
6
|
-
drizzle/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
|
-
drizzle/tests/helpers.py,sha256=BF_IbAwBZFgrTglw33Mgw56xfKYqNJXVTtjCwUB_U98,5887
|
|
8
|
-
drizzle/tests/test_cdrizzle.py,sha256=utepqMiY8xtgQ8gBRBHwnlMhbBB1pq1xE4spf-wO7Kw,726
|
|
9
|
-
drizzle/tests/test_overlap_calc.py,sha256=ucwDL9fd8NVAxTdz-sWum_uobhm-TGkCr2yl69BKiC4,7062
|
|
10
|
-
drizzle/tests/test_resample.py,sha256=13UfYaGtTT2utQfF7j_8pQXzC51RFZ8EpRLFYSdz1MM,31600
|
|
11
|
-
drizzle/tests/test_utils.py,sha256=s4-z4ZMTcoIUyxHW0pMRpQB2GiA1lbfuNLQzkOgflp8,7691
|
|
12
|
-
drizzle-2.0.1.dist-info/LICENSE.rst,sha256=sUXj5W73D9TcOw5ZXaDdcthYdY2b2dTJPsxBuZTOYWQ,1505
|
|
13
|
-
drizzle-2.0.1.dist-info/METADATA,sha256=2G_rWumBwJpBy9MC7qc_c7CHA3qj_4RLxIHehazIIdM,10894
|
|
14
|
-
drizzle-2.0.1.dist-info/WHEEL,sha256=yNnHoQL2GZYIUXm9YvoaBpFjGlUoK9qq9oqYeudrWlE,101
|
|
15
|
-
drizzle-2.0.1.dist-info/top_level.txt,sha256=MA5uqwTj1sJBi-hCeQj9v3-sZ9nVUTe6bd_zGWTKy5A,8
|
|
16
|
-
drizzle-2.0.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|