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.

Files changed (63) hide show
  1. {drizzle-2.0.0 → drizzle-2.0.1}/.github/workflows/ci.yml +2 -2
  2. {drizzle-2.0.0 → drizzle-2.0.1}/CHANGES.rst +11 -1
  3. {drizzle-2.0.0/drizzle.egg-info → drizzle-2.0.1}/PKG-INFO +4 -3
  4. {drizzle-2.0.0 → drizzle-2.0.1}/drizzle/resample.py +1 -1
  5. drizzle-2.0.1/drizzle/tests/helpers.py +190 -0
  6. {drizzle-2.0.0 → drizzle-2.0.1}/drizzle/tests/test_resample.py +157 -494
  7. {drizzle-2.0.0 → drizzle-2.0.1}/drizzle/tests/test_utils.py +92 -47
  8. {drizzle-2.0.0 → drizzle-2.0.1}/drizzle/utils.py +56 -10
  9. {drizzle-2.0.0 → drizzle-2.0.1/drizzle.egg-info}/PKG-INFO +4 -3
  10. {drizzle-2.0.0 → drizzle-2.0.1}/drizzle.egg-info/SOURCES.txt +1 -0
  11. {drizzle-2.0.0 → drizzle-2.0.1}/drizzle.egg-info/requires.txt +2 -1
  12. {drizzle-2.0.0 → drizzle-2.0.1}/pyproject.toml +4 -1
  13. {drizzle-2.0.0 → drizzle-2.0.1}/tox.ini +3 -0
  14. {drizzle-2.0.0 → drizzle-2.0.1}/.clang-format +0 -0
  15. {drizzle-2.0.0 → drizzle-2.0.1}/.coveragerc +0 -0
  16. {drizzle-2.0.0 → drizzle-2.0.1}/.flake8 +0 -0
  17. {drizzle-2.0.0 → drizzle-2.0.1}/.github/CODEOWNERS +0 -0
  18. {drizzle-2.0.0 → drizzle-2.0.1}/.github/dependabot.yml +0 -0
  19. {drizzle-2.0.0 → drizzle-2.0.1}/.github/workflows/build.yml +0 -0
  20. {drizzle-2.0.0 → drizzle-2.0.1}/.gitignore +0 -0
  21. {drizzle-2.0.0 → drizzle-2.0.1}/.readthedocs.yaml +0 -0
  22. {drizzle-2.0.0 → drizzle-2.0.1}/.ruff.toml +0 -0
  23. {drizzle-2.0.0 → drizzle-2.0.1}/CODE_OF_CONDUCT.md +0 -0
  24. {drizzle-2.0.0 → drizzle-2.0.1}/LICENSE.rst +0 -0
  25. {drizzle-2.0.0 → drizzle-2.0.1}/MANIFEST.in +0 -0
  26. {drizzle-2.0.0 → drizzle-2.0.1}/README.rst +0 -0
  27. {drizzle-2.0.0 → drizzle-2.0.1}/docs/Makefile +0 -0
  28. {drizzle-2.0.0 → drizzle-2.0.1}/docs/_templates/autosummary/base.rst +0 -0
  29. {drizzle-2.0.0 → drizzle-2.0.1}/docs/_templates/autosummary/class.rst +0 -0
  30. {drizzle-2.0.0 → drizzle-2.0.1}/docs/_templates/autosummary/module.rst +0 -0
  31. {drizzle-2.0.0 → drizzle-2.0.1}/docs/conf.py +0 -0
  32. {drizzle-2.0.0 → drizzle-2.0.1}/docs/drizzle/api.rst +0 -0
  33. {drizzle-2.0.0 → drizzle-2.0.1}/docs/drizzle/index.rst +0 -0
  34. {drizzle-2.0.0 → drizzle-2.0.1}/docs/drizzle/user.rst +0 -0
  35. {drizzle-2.0.0 → drizzle-2.0.1}/docs/exts/numfig.py +0 -0
  36. {drizzle-2.0.0 → drizzle-2.0.1}/docs/index.rst +0 -0
  37. {drizzle-2.0.0 → drizzle-2.0.1}/docs/make.bat +0 -0
  38. {drizzle-2.0.0 → drizzle-2.0.1}/docs/rtd_environment.yaml +0 -0
  39. {drizzle-2.0.0 → drizzle-2.0.1}/drizzle/__init__.py +0 -0
  40. {drizzle-2.0.0 → drizzle-2.0.1}/drizzle/tests/__init__.py +0 -0
  41. {drizzle-2.0.0 → drizzle-2.0.1}/drizzle/tests/test_cdrizzle.py +0 -0
  42. {drizzle-2.0.0 → drizzle-2.0.1}/drizzle/tests/test_overlap_calc.py +0 -0
  43. {drizzle-2.0.0 → drizzle-2.0.1}/drizzle/util.py +0 -0
  44. {drizzle-2.0.0 → drizzle-2.0.1}/drizzle.egg-info/dependency_links.txt +0 -0
  45. {drizzle-2.0.0 → drizzle-2.0.1}/drizzle.egg-info/not-zip-safe +0 -0
  46. {drizzle-2.0.0 → drizzle-2.0.1}/drizzle.egg-info/top_level.txt +0 -0
  47. {drizzle-2.0.0 → drizzle-2.0.1}/setup.cfg +0 -0
  48. {drizzle-2.0.0 → drizzle-2.0.1}/setup.py +0 -0
  49. {drizzle-2.0.0 → drizzle-2.0.1}/src/cdrizzleapi.c +0 -0
  50. {drizzle-2.0.0 → drizzle-2.0.1}/src/cdrizzleblot.c +0 -0
  51. {drizzle-2.0.0 → drizzle-2.0.1}/src/cdrizzleblot.h +0 -0
  52. {drizzle-2.0.0 → drizzle-2.0.1}/src/cdrizzlebox.c +0 -0
  53. {drizzle-2.0.0 → drizzle-2.0.1}/src/cdrizzlebox.h +0 -0
  54. {drizzle-2.0.0 → drizzle-2.0.1}/src/cdrizzlemap.c +0 -0
  55. {drizzle-2.0.0 → drizzle-2.0.1}/src/cdrizzlemap.h +0 -0
  56. {drizzle-2.0.0 → drizzle-2.0.1}/src/cdrizzleutil.c +0 -0
  57. {drizzle-2.0.0 → drizzle-2.0.1}/src/cdrizzleutil.h +0 -0
  58. {drizzle-2.0.0 → drizzle-2.0.1}/src/driz_portability.h +0 -0
  59. {drizzle-2.0.0 → drizzle-2.0.1}/src/tests/.clang-format +0 -0
  60. {drizzle-2.0.0 → drizzle-2.0.1}/src/tests/drizzletest.h +0 -0
  61. {drizzle-2.0.0 → drizzle-2.0.1}/src/tests/fct.h +0 -0
  62. {drizzle-2.0.0 → drizzle-2.0.1}/src/tests/pandokia_fct.h +0 -0
  63. {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. Backward compatibility was
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
1
+ Metadata-Version: 2.2
2
2
  Name: drizzle
3
- Version: 2.0.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"
@@ -6,7 +6,7 @@ import numpy as np
6
6
 
7
7
  from drizzle import cdrizzle
8
8
 
9
- __all__ = ["blot_image", "Drizzle"]
9
+ __all__ = ["Drizzle", "blot_image"]
10
10
 
11
11
  SUPPORTED_DRIZZLE_KERNELS = [
12
12
  "square",
@@ -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