drizzle 2.0.0__tar.gz → 2.0.1__tar.gz
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-2.0.0 → drizzle-2.0.1}/.github/workflows/ci.yml +2 -2
- {drizzle-2.0.0 → drizzle-2.0.1}/CHANGES.rst +11 -1
- {drizzle-2.0.0/drizzle.egg-info → drizzle-2.0.1}/PKG-INFO +4 -3
- {drizzle-2.0.0 → drizzle-2.0.1}/drizzle/resample.py +1 -1
- drizzle-2.0.1/drizzle/tests/helpers.py +190 -0
- {drizzle-2.0.0 → drizzle-2.0.1}/drizzle/tests/test_resample.py +157 -494
- {drizzle-2.0.0 → drizzle-2.0.1}/drizzle/tests/test_utils.py +92 -47
- {drizzle-2.0.0 → drizzle-2.0.1}/drizzle/utils.py +56 -10
- {drizzle-2.0.0 → drizzle-2.0.1/drizzle.egg-info}/PKG-INFO +4 -3
- {drizzle-2.0.0 → drizzle-2.0.1}/drizzle.egg-info/SOURCES.txt +1 -0
- {drizzle-2.0.0 → drizzle-2.0.1}/drizzle.egg-info/requires.txt +2 -1
- {drizzle-2.0.0 → drizzle-2.0.1}/pyproject.toml +4 -1
- {drizzle-2.0.0 → drizzle-2.0.1}/tox.ini +3 -0
- {drizzle-2.0.0 → drizzle-2.0.1}/.clang-format +0 -0
- {drizzle-2.0.0 → drizzle-2.0.1}/.coveragerc +0 -0
- {drizzle-2.0.0 → drizzle-2.0.1}/.flake8 +0 -0
- {drizzle-2.0.0 → drizzle-2.0.1}/.github/CODEOWNERS +0 -0
- {drizzle-2.0.0 → drizzle-2.0.1}/.github/dependabot.yml +0 -0
- {drizzle-2.0.0 → drizzle-2.0.1}/.github/workflows/build.yml +0 -0
- {drizzle-2.0.0 → drizzle-2.0.1}/.gitignore +0 -0
- {drizzle-2.0.0 → drizzle-2.0.1}/.readthedocs.yaml +0 -0
- {drizzle-2.0.0 → drizzle-2.0.1}/.ruff.toml +0 -0
- {drizzle-2.0.0 → drizzle-2.0.1}/CODE_OF_CONDUCT.md +0 -0
- {drizzle-2.0.0 → drizzle-2.0.1}/LICENSE.rst +0 -0
- {drizzle-2.0.0 → drizzle-2.0.1}/MANIFEST.in +0 -0
- {drizzle-2.0.0 → drizzle-2.0.1}/README.rst +0 -0
- {drizzle-2.0.0 → drizzle-2.0.1}/docs/Makefile +0 -0
- {drizzle-2.0.0 → drizzle-2.0.1}/docs/_templates/autosummary/base.rst +0 -0
- {drizzle-2.0.0 → drizzle-2.0.1}/docs/_templates/autosummary/class.rst +0 -0
- {drizzle-2.0.0 → drizzle-2.0.1}/docs/_templates/autosummary/module.rst +0 -0
- {drizzle-2.0.0 → drizzle-2.0.1}/docs/conf.py +0 -0
- {drizzle-2.0.0 → drizzle-2.0.1}/docs/drizzle/api.rst +0 -0
- {drizzle-2.0.0 → drizzle-2.0.1}/docs/drizzle/index.rst +0 -0
- {drizzle-2.0.0 → drizzle-2.0.1}/docs/drizzle/user.rst +0 -0
- {drizzle-2.0.0 → drizzle-2.0.1}/docs/exts/numfig.py +0 -0
- {drizzle-2.0.0 → drizzle-2.0.1}/docs/index.rst +0 -0
- {drizzle-2.0.0 → drizzle-2.0.1}/docs/make.bat +0 -0
- {drizzle-2.0.0 → drizzle-2.0.1}/docs/rtd_environment.yaml +0 -0
- {drizzle-2.0.0 → drizzle-2.0.1}/drizzle/__init__.py +0 -0
- {drizzle-2.0.0 → drizzle-2.0.1}/drizzle/tests/__init__.py +0 -0
- {drizzle-2.0.0 → drizzle-2.0.1}/drizzle/tests/test_cdrizzle.py +0 -0
- {drizzle-2.0.0 → drizzle-2.0.1}/drizzle/tests/test_overlap_calc.py +0 -0
- {drizzle-2.0.0 → drizzle-2.0.1}/drizzle/util.py +0 -0
- {drizzle-2.0.0 → drizzle-2.0.1}/drizzle.egg-info/dependency_links.txt +0 -0
- {drizzle-2.0.0 → drizzle-2.0.1}/drizzle.egg-info/not-zip-safe +0 -0
- {drizzle-2.0.0 → drizzle-2.0.1}/drizzle.egg-info/top_level.txt +0 -0
- {drizzle-2.0.0 → drizzle-2.0.1}/setup.cfg +0 -0
- {drizzle-2.0.0 → drizzle-2.0.1}/setup.py +0 -0
- {drizzle-2.0.0 → drizzle-2.0.1}/src/cdrizzleapi.c +0 -0
- {drizzle-2.0.0 → drizzle-2.0.1}/src/cdrizzleblot.c +0 -0
- {drizzle-2.0.0 → drizzle-2.0.1}/src/cdrizzleblot.h +0 -0
- {drizzle-2.0.0 → drizzle-2.0.1}/src/cdrizzlebox.c +0 -0
- {drizzle-2.0.0 → drizzle-2.0.1}/src/cdrizzlebox.h +0 -0
- {drizzle-2.0.0 → drizzle-2.0.1}/src/cdrizzlemap.c +0 -0
- {drizzle-2.0.0 → drizzle-2.0.1}/src/cdrizzlemap.h +0 -0
- {drizzle-2.0.0 → drizzle-2.0.1}/src/cdrizzleutil.c +0 -0
- {drizzle-2.0.0 → drizzle-2.0.1}/src/cdrizzleutil.h +0 -0
- {drizzle-2.0.0 → drizzle-2.0.1}/src/driz_portability.h +0 -0
- {drizzle-2.0.0 → drizzle-2.0.1}/src/tests/.clang-format +0 -0
- {drizzle-2.0.0 → drizzle-2.0.1}/src/tests/drizzletest.h +0 -0
- {drizzle-2.0.0 → drizzle-2.0.1}/src/tests/fct.h +0 -0
- {drizzle-2.0.0 → drizzle-2.0.1}/src/tests/pandokia_fct.h +0 -0
- {drizzle-2.0.0 → drizzle-2.0.1}/src/tests/utest_cdrizzle.c +0 -0
|
@@ -22,7 +22,6 @@ jobs:
|
|
|
22
22
|
envs: |
|
|
23
23
|
- linux: check-style
|
|
24
24
|
- linux: check-security
|
|
25
|
-
|
|
26
25
|
- linux: py310-xdist
|
|
27
26
|
- linux: py311-xdist
|
|
28
27
|
- linux: py313-xdist
|
|
@@ -30,5 +29,6 @@ jobs:
|
|
|
30
29
|
- windows: py312-xdist
|
|
31
30
|
- linux: py312-xdist-cov
|
|
32
31
|
coverage: codecov
|
|
33
|
-
|
|
34
32
|
- linux: py312-xdist-devdeps
|
|
33
|
+
secrets:
|
|
34
|
+
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
|
@@ -4,10 +4,20 @@
|
|
|
4
4
|
Release Notes
|
|
5
5
|
=============
|
|
6
6
|
|
|
7
|
+
2.0.1 (2025-01-28)
|
|
8
|
+
==================
|
|
9
|
+
|
|
10
|
+
- Update ``utils.calc_pixmap`` code to be ready for upcoming changes in GWCS
|
|
11
|
+
due to which inverse WCS transformations will respect bounding box by
|
|
12
|
+
allowing the caller of ``utils.calc_pixmap`` to disable the bounding box(es)
|
|
13
|
+
on both or one of the input WCS when computing the pixel map. [#164]
|
|
14
|
+
|
|
15
|
+
|
|
7
16
|
2.0.0 (2024-10-23)
|
|
8
17
|
==================
|
|
9
18
|
|
|
10
|
-
- Backward incompatible major re-design of API
|
|
19
|
+
- Backward incompatible major re-design of API to make the code I/O agnostic.
|
|
20
|
+
Removed FITS-specific code. Backward compatibility was
|
|
11
21
|
maintained with JWST and Roman pipelines only. [#134]
|
|
12
22
|
|
|
13
23
|
- Deprecated module ``util``. New software should not import from this
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: drizzle
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.1
|
|
4
4
|
Summary: A package for combining dithered images into a single image
|
|
5
5
|
Author-email: STScI <help@stsci.edu>
|
|
6
6
|
License: Copyright (C) 2011,2014 Association of Universities for Research in
|
|
@@ -43,8 +43,9 @@ Requires-Python: >=3.10
|
|
|
43
43
|
Description-Content-Type: text/x-rst
|
|
44
44
|
License-File: LICENSE.rst
|
|
45
45
|
Requires-Dist: numpy
|
|
46
|
-
Requires-Dist: astropy
|
|
47
46
|
Provides-Extra: test
|
|
47
|
+
Requires-Dist: astropy; extra == "test"
|
|
48
|
+
Requires-Dist: gwcs; extra == "test"
|
|
48
49
|
Requires-Dist: pytest; extra == "test"
|
|
49
50
|
Requires-Dist: pytest-cov; extra == "test"
|
|
50
51
|
Requires-Dist: pytest-doctestplus; extra == "test"
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
import gwcs
|
|
4
|
+
import numpy as np
|
|
5
|
+
from gwcs.coordinate_frames import CelestialFrame, Frame2D
|
|
6
|
+
|
|
7
|
+
from astropy import coordinates as coord
|
|
8
|
+
from astropy import units
|
|
9
|
+
from astropy import wcs as fits_wcs
|
|
10
|
+
from astropy.io import fits
|
|
11
|
+
from astropy.modeling.models import (
|
|
12
|
+
Mapping,
|
|
13
|
+
Pix2Sky_TAN,
|
|
14
|
+
Polynomial2D,
|
|
15
|
+
RotateNative2Celestial,
|
|
16
|
+
Shift,
|
|
17
|
+
)
|
|
18
|
+
from astropy.modeling.projections import AffineTransformation2D
|
|
19
|
+
|
|
20
|
+
__all__ = ["wcs_from_file"]
|
|
21
|
+
|
|
22
|
+
TEST_DIR = os.path.abspath(os.path.dirname(__file__))
|
|
23
|
+
DATA_DIR = os.path.join(TEST_DIR, 'data')
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def wcs_from_file(filename, ext=None, return_data=False, crpix_shift=None,
|
|
27
|
+
wcs_type="fits"):
|
|
28
|
+
"""
|
|
29
|
+
Read the WCS from a ".fits" file.
|
|
30
|
+
|
|
31
|
+
Parameters
|
|
32
|
+
----------
|
|
33
|
+
filename : str
|
|
34
|
+
Name of the file to load WCS from.
|
|
35
|
+
|
|
36
|
+
ext : int, None, optional
|
|
37
|
+
Extension number to load the WCS from. When `None`, the WCS will be
|
|
38
|
+
loaded from the first extension containing a WCS.
|
|
39
|
+
|
|
40
|
+
return_data : bool, optional
|
|
41
|
+
When `True`, this function will return a tuple with first item
|
|
42
|
+
being the WCS and the second item being the image data array.
|
|
43
|
+
|
|
44
|
+
crpix_shift : tuple, None, optional
|
|
45
|
+
A tuple of two values to be added to header CRPIX values before
|
|
46
|
+
creating the WCS. This effectively introduces a constant shift
|
|
47
|
+
in the image coordinate system.
|
|
48
|
+
|
|
49
|
+
wcs_type : {"fits", "gwcs"}, optional
|
|
50
|
+
Return either a FITS WCS or a gwcs.
|
|
51
|
+
|
|
52
|
+
Returns
|
|
53
|
+
-------
|
|
54
|
+
WCS or tuple of WCS and image data
|
|
55
|
+
|
|
56
|
+
"""
|
|
57
|
+
full_file_name = os.path.join(DATA_DIR, filename)
|
|
58
|
+
path = os.path.join(DATA_DIR, full_file_name)
|
|
59
|
+
with fits.open(path) as hdu:
|
|
60
|
+
if ext is None:
|
|
61
|
+
for k, u in enumerate(hdu):
|
|
62
|
+
if "CTYPE1" in u.header:
|
|
63
|
+
ext = k
|
|
64
|
+
break
|
|
65
|
+
|
|
66
|
+
hdr = hdu[ext].header
|
|
67
|
+
naxis1 = hdr.get("WCSNAX1", hdr.get("NAXIS1"))
|
|
68
|
+
naxis2 = hdr.get("WCSNAX2", hdr.get("NAXIS2"))
|
|
69
|
+
if naxis1 is not None and naxis2 is not None:
|
|
70
|
+
shape = (naxis2, naxis1)
|
|
71
|
+
if hdu[ext].data is None:
|
|
72
|
+
hdu[ext].data = np.zeros(shape, dtype=np.float32)
|
|
73
|
+
else:
|
|
74
|
+
shape = None
|
|
75
|
+
|
|
76
|
+
if crpix_shift is not None and "CRPIX1" in hdr:
|
|
77
|
+
hdr["CRPIX1"] += crpix_shift[0]
|
|
78
|
+
hdr["CRPIX2"] += crpix_shift[1]
|
|
79
|
+
|
|
80
|
+
result = fits_wcs.WCS(hdr, hdu)
|
|
81
|
+
result.array_shape = shape
|
|
82
|
+
|
|
83
|
+
if wcs_type == "gwcs":
|
|
84
|
+
result = _gwcs_from_hst_fits_wcs(result)
|
|
85
|
+
|
|
86
|
+
if return_data:
|
|
87
|
+
result = (result, )
|
|
88
|
+
if not isinstance(return_data, (list, tuple)):
|
|
89
|
+
return_data = [ext]
|
|
90
|
+
for ext in return_data:
|
|
91
|
+
data = (hdu[ext].data, )
|
|
92
|
+
result = result + data
|
|
93
|
+
|
|
94
|
+
return result
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def _gwcs_from_hst_fits_wcs(w):
|
|
98
|
+
# NOTE: this function ignores table distortions
|
|
99
|
+
def coeffs_to_poly(mat, degree):
|
|
100
|
+
pol = Polynomial2D(degree=degree)
|
|
101
|
+
for i in range(mat.shape[0]):
|
|
102
|
+
for j in range(mat.shape[1]):
|
|
103
|
+
if 0 < i + j <= degree:
|
|
104
|
+
setattr(pol, f'c{i}_{j}', mat[i, j])
|
|
105
|
+
return pol
|
|
106
|
+
|
|
107
|
+
nx, ny = w.pixel_shape
|
|
108
|
+
x0, y0 = w.wcs.crpix - 1
|
|
109
|
+
|
|
110
|
+
cd = w.wcs.piximg_matrix
|
|
111
|
+
|
|
112
|
+
if w.sip is None:
|
|
113
|
+
# construct GWCS:
|
|
114
|
+
det2sky = (
|
|
115
|
+
(Shift(-x0) & Shift(-y0)) |
|
|
116
|
+
Pix2Sky_TAN() | RotateNative2Celestial(*w.wcs.crval, 180)
|
|
117
|
+
)
|
|
118
|
+
else:
|
|
119
|
+
cfx, cfy = np.dot(cd, [w.sip.a.ravel(), w.sip.b.ravel()])
|
|
120
|
+
a = np.reshape(cfx, w.sip.a.shape)
|
|
121
|
+
b = np.reshape(cfy, w.sip.b.shape)
|
|
122
|
+
a[1, 0] = cd[0, 0]
|
|
123
|
+
a[0, 1] = cd[0, 1]
|
|
124
|
+
b[1, 0] = cd[1, 0]
|
|
125
|
+
b[0, 1] = cd[1, 1]
|
|
126
|
+
|
|
127
|
+
polx = coeffs_to_poly(a, w.sip.a_order)
|
|
128
|
+
poly = coeffs_to_poly(b, w.sip.b_order)
|
|
129
|
+
|
|
130
|
+
sip = Mapping((0, 1, 0, 1)) | (polx & poly)
|
|
131
|
+
|
|
132
|
+
# construct GWCS:
|
|
133
|
+
det2sky = (
|
|
134
|
+
(Shift(-x0) & Shift(-y0)) | sip |
|
|
135
|
+
Pix2Sky_TAN() | RotateNative2Celestial(*w.wcs.crval, 180)
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
detector_frame = Frame2D(
|
|
139
|
+
name="detector",
|
|
140
|
+
axes_names=("x", "y"),
|
|
141
|
+
unit=(units.pix, units.pix)
|
|
142
|
+
)
|
|
143
|
+
sky_frame = CelestialFrame(
|
|
144
|
+
reference_frame=getattr(coord, w.wcs.radesys).__call__(),
|
|
145
|
+
name=w.wcs.radesys,
|
|
146
|
+
unit=(units.deg, units.deg)
|
|
147
|
+
)
|
|
148
|
+
pipeline = [(detector_frame, det2sky), (sky_frame, None)]
|
|
149
|
+
gw = gwcs.wcs.WCS(pipeline)
|
|
150
|
+
gw.array_shape = w.array_shape
|
|
151
|
+
gw.bounding_box = ((-0.5, nx - 0.5), (-0.5, ny - 0.5))
|
|
152
|
+
|
|
153
|
+
if w.sip is not None:
|
|
154
|
+
# compute inverse SIP and re-create output GWCS
|
|
155
|
+
|
|
156
|
+
# compute inverse SIP:
|
|
157
|
+
hdr = gw.to_fits_sip(
|
|
158
|
+
max_inv_pix_error=1e-5,
|
|
159
|
+
inv_degree=None,
|
|
160
|
+
npoints=64,
|
|
161
|
+
crpix=w.wcs.crpix,
|
|
162
|
+
projection='TAN',
|
|
163
|
+
verbose=False
|
|
164
|
+
)
|
|
165
|
+
winv = fits_wcs.WCS(hdr)
|
|
166
|
+
ap = winv.sip.ap.copy()
|
|
167
|
+
bp = winv.sip.bp.copy()
|
|
168
|
+
ap[1, 0] += 1
|
|
169
|
+
bp[0, 1] += 1
|
|
170
|
+
polx_inv = coeffs_to_poly(ap, winv.sip.ap_order)
|
|
171
|
+
poly_inv = coeffs_to_poly(bp, winv.sip.bp_order)
|
|
172
|
+
af = AffineTransformation2D(
|
|
173
|
+
matrix=np.linalg.inv(winv.wcs.piximg_matrix)
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
# set analytical inverses:
|
|
177
|
+
sip.inverse = af | Mapping((0, 1, 0, 1)) | (polx_inv & poly_inv)
|
|
178
|
+
|
|
179
|
+
# construct GWCS:
|
|
180
|
+
det2sky = (
|
|
181
|
+
(Shift(-x0) & Shift(-y0)) | sip |
|
|
182
|
+
Pix2Sky_TAN() | RotateNative2Celestial(*w.wcs.crval, 180)
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
pipeline = [(detector_frame, det2sky), (sky_frame, None)]
|
|
186
|
+
gw = gwcs.wcs.WCS(pipeline)
|
|
187
|
+
gw.array_shape = w.array_shape
|
|
188
|
+
gw.bounding_box = ((-0.5, nx - 0.5), (-0.5, ny - 0.5))
|
|
189
|
+
|
|
190
|
+
return gw
|