astroimred 0.4.0__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.
- astroimred-0.4.0/.github/tests/test_release.py +122 -0
- astroimred-0.4.0/CHANGELOG.md +39 -0
- astroimred-0.4.0/LICENSE +28 -0
- astroimred-0.4.0/PKG-INFO +63 -0
- astroimred-0.4.0/README.md +14 -0
- astroimred-0.4.0/RELEASING.md +152 -0
- astroimred-0.4.0/pyproject.toml +117 -0
- astroimred-0.4.0/pyproject.toml.orig +105 -0
- astroimred-0.4.0/scripts/check_release.py +161 -0
- astroimred-0.4.0/scripts/smoke_install.py +56 -0
- astroimred-0.4.0/src/astroimred/__init__.py +18 -0
- astroimred-0.4.0/src/astroimred/_core/__init__.py +9 -0
- astroimred-0.4.0/src/astroimred/_core/astropy_helpers.py +299 -0
- astroimred-0.4.0/src/astroimred/_core/geometry.py +268 -0
- astroimred-0.4.0/src/astroimred/_core/numeric.py +531 -0
- astroimred-0.4.0/src/astroimred/_core/scales.py +61 -0
- astroimred-0.4.0/src/astroimred/_core/system.py +36 -0
- astroimred-0.4.0/src/astroimred/_core/types.py +30 -0
- astroimred-0.4.0/src/astroimred/_core/wcs.py +122 -0
- astroimred-0.4.0/src/astroimred/cli.py +44 -0
- astroimred-0.4.0/src/astroimred/external/__init__.py +7 -0
- astroimred-0.4.0/src/astroimred/external/sep.py +838 -0
- astroimred-0.4.0/src/astroimred/fitsmgmt/__init__.py +9 -0
- astroimred-0.4.0/src/astroimred/fitsmgmt/airmass.py +464 -0
- astroimred-0.4.0/src/astroimred/fitsmgmt/header.py +778 -0
- astroimred-0.4.0/src/astroimred/fitsmgmt/io.py +1029 -0
- astroimred-0.4.0/src/astroimred/fitsmgmt/naming.py +276 -0
- astroimred-0.4.0/src/astroimred/fitsmgmt/table.py +904 -0
- astroimred-0.4.0/src/astroimred/fitsmgmt/wcs.py +683 -0
- astroimred-0.4.0/src/astroimred/imutil/__init__.py +6 -0
- astroimred-0.4.0/src/astroimred/imutil/_docstrings.py +360 -0
- astroimred-0.4.0/src/astroimred/imutil/_util_fits.py +1372 -0
- astroimred-0.4.0/src/astroimred/imutil/ccdops.py +865 -0
- astroimred-0.4.0/src/astroimred/imutil/imarith.py +420 -0
- astroimred-0.4.0/src/astroimred/imutil/imcombine.py +1057 -0
- astroimred-0.4.0/src/astroimred/imutil/imcopy.py +160 -0
- astroimred-0.4.0/src/astroimred/imutil/imsmooth.py +45 -0
- astroimred-0.4.0/src/astroimred/imutil/imstat.py +322 -0
- astroimred-0.4.0/src/astroimred/imutil/pixels.py +456 -0
- astroimred-0.4.0/src/astroimred/logging.py +35 -0
- astroimred-0.4.0/src/astroimred/phot/__init__.py +14 -0
- astroimred-0.4.0/src/astroimred/phot/aperture.py +159 -0
- astroimred-0.4.0/src/astroimred/phot/apphot.py +549 -0
- astroimred-0.4.0/src/astroimred/phot/background.py +565 -0
- astroimred-0.4.0/src/astroimred/phot/center.py +1277 -0
- astroimred-0.4.0/src/astroimred/phot/daopsf.py +479 -0
- astroimred-0.4.0/src/astroimred/phot/growth.py +164 -0
- astroimred-0.4.0/src/astroimred/phot/polarimetry.py +1006 -0
- astroimred-0.4.0/src/astroimred/phot/radprof.py +480 -0
- astroimred-0.4.0/src/astroimred/reduction/__init__.py +3 -0
- astroimred-0.4.0/src/astroimred/reduction/_presets.py +74 -0
- astroimred-0.4.0/src/astroimred/reduction/cli.py +744 -0
- astroimred-0.4.0/src/astroimred/reduction/crrej.py +898 -0
- astroimred-0.4.0/src/astroimred/reduction/preproc.py +1011 -0
- astroimred-0.4.0/src/astroimred/viz/__init__.py +4 -0
- astroimred-0.4.0/src/astroimred/viz/imshow.py +251 -0
- astroimred-0.4.0/src/astroimred/viz/ticks.py +77 -0
- astroimred-0.4.0/tests/conftest.py +85 -0
- astroimred-0.4.0/tests/fitsmgmt/__init__.py +1 -0
- astroimred-0.4.0/tests/fitsmgmt/test_airmass.py +131 -0
- astroimred-0.4.0/tests/fitsmgmt/test_headers.py +104 -0
- astroimred-0.4.0/tests/fitsmgmt/test_io.py +253 -0
- astroimred-0.4.0/tests/fitsmgmt/test_summary.py +139 -0
- astroimred-0.4.0/tests/fitsmgmt/test_summary_export.py +109 -0
- astroimred-0.4.0/tests/fitsmgmt/test_wcstools.py +91 -0
- astroimred-0.4.0/tests/imutil/__init__.py +1 -0
- astroimred-0.4.0/tests/imutil/test_ccdops.py +172 -0
- astroimred-0.4.0/tests/imutil/test_chunked_fits_io.py +431 -0
- astroimred-0.4.0/tests/imutil/test_imstat.py +234 -0
- astroimred-0.4.0/tests/imutil/test_pixels.py +105 -0
- astroimred-0.4.0/tests/imutil/test_rejection_diagnostics.py +368 -0
- astroimred-0.4.0/tests/imutil/test_stack_memory.py +190 -0
- astroimred-0.4.0/tests/imutil/test_weighted_combine.py +183 -0
- astroimred-0.4.0/tests/phot/__init__.py +30 -0
- astroimred-0.4.0/tests/phot/conftest.py +325 -0
- astroimred-0.4.0/tests/phot/test_aperture.py +178 -0
- astroimred-0.4.0/tests/phot/test_apphot.py +463 -0
- astroimred-0.4.0/tests/phot/test_astroapers_parity.py +322 -0
- astroimred-0.4.0/tests/phot/test_background.py +673 -0
- astroimred-0.4.0/tests/phot/test_center.py +538 -0
- astroimred-0.4.0/tests/phot/test_polarimetry.py +634 -0
- astroimred-0.4.0/tests/phot/test_radprof.py +475 -0
- astroimred-0.4.0/tests/phot/test_seputil.py +577 -0
- astroimred-0.4.0/tests/phot/test_util.py +416 -0
- astroimred-0.4.0/tests/reduction/__init__.py +1 -0
- astroimred-0.4.0/tests/reduction/conftest.py +4 -0
- astroimred-0.4.0/tests/reduction/test_cli.py +214 -0
- astroimred-0.4.0/tests/reduction/test_crrej.py +111 -0
- astroimred-0.4.0/tests/reduction/test_imarith.py +61 -0
- astroimred-0.4.0/tests/reduction/test_imcombine.py +697 -0
- astroimred-0.4.0/tests/reduction/test_preproc.py +228 -0
- astroimred-0.4.0/tests/test_astroimred.py +224 -0
- astroimred-0.4.0/tests/test_core_helpers.py +85 -0
- astroimred-0.4.0/tests/test_core_numeric.py +614 -0
- astroimred-0.4.0/tests/verify_astroimred.py +191 -0
- astroimred-0.4.0/tests/viz/test_imshow.py +73 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"""Test release rejection paths without importing astroimred or its dependencies."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import importlib.util
|
|
6
|
+
import subprocess
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
import pytest
|
|
10
|
+
|
|
11
|
+
_ROOT = Path(__file__).resolve().parents[2]
|
|
12
|
+
_SPEC = importlib.util.spec_from_file_location(
|
|
13
|
+
"check_release", _ROOT / "scripts/check_release.py"
|
|
14
|
+
)
|
|
15
|
+
assert _SPEC is not None and _SPEC.loader is not None
|
|
16
|
+
release = importlib.util.module_from_spec(_SPEC)
|
|
17
|
+
_SPEC.loader.exec_module(release)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@pytest.fixture
|
|
21
|
+
def project(tmp_path: Path) -> Path:
|
|
22
|
+
"""Create a minimal, valid release tree."""
|
|
23
|
+
(tmp_path / "pyproject.toml").write_text(
|
|
24
|
+
'[project]\nname = "astroimred"\nversion = "1.2.3"\n'
|
|
25
|
+
'dependencies = ["numpy>=1.24"]\n'
|
|
26
|
+
'[build-system]\nrequires = ["uv_build>=0.9.18,<0.10.0"]\n',
|
|
27
|
+
encoding="utf-8",
|
|
28
|
+
)
|
|
29
|
+
(tmp_path / "CHANGELOG.md").write_text(
|
|
30
|
+
"# Changelog\n\n## 1.2.3 - 2026-09-07\n\n- Release change.\n"
|
|
31
|
+
"\n## 1.2.2 - 2026-09-01\n\n- Older change.\n",
|
|
32
|
+
encoding="utf-8",
|
|
33
|
+
)
|
|
34
|
+
return tmp_path
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def test_release_extracts_only_matching_notes(project: Path) -> None:
|
|
38
|
+
assert release.check_release(project, tag="v1.2.3") == (
|
|
39
|
+
"1.2.3",
|
|
40
|
+
"- Release change.\n",
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def test_rehearsal_accepts_pending_changes(project: Path) -> None:
|
|
45
|
+
(project / "CHANGELOG.md").write_text(
|
|
46
|
+
"## Unreleased\n\n- Pending.\n", encoding="utf-8"
|
|
47
|
+
)
|
|
48
|
+
assert release.check_release(project) == ("1.2.3", "- Pending.\n")
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@pytest.mark.parametrize("tag", ["v1.2.4", "1.2.3", "v1.2.3rc1", "v01.2.3", ""])
|
|
52
|
+
def test_rejects_wrong_tags(project: Path, tag: str) -> None:
|
|
53
|
+
with pytest.raises(ValueError, match="tag"):
|
|
54
|
+
release.check_release(project, tag=tag)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
@pytest.mark.parametrize("version", ["1.2.3rc1", "01.2.3", "1.2", "1.2.3+local"])
|
|
58
|
+
def test_rejects_nonstable_versions(project: Path, version: str) -> None:
|
|
59
|
+
manifest = project / "pyproject.toml"
|
|
60
|
+
manifest.write_text(
|
|
61
|
+
manifest.read_text().replace('"1.2.3"', f'"{version}"'), encoding="utf-8"
|
|
62
|
+
)
|
|
63
|
+
with pytest.raises(ValueError, match="stable"):
|
|
64
|
+
release.check_release(project)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
@pytest.mark.parametrize(
|
|
68
|
+
"notes",
|
|
69
|
+
[
|
|
70
|
+
"## Unreleased\n\n- Pending.\n\n## 1.2.3 - 2026-09-07\n\n- Change.\n",
|
|
71
|
+
"## 1.2.3 - 2026-09-07\n",
|
|
72
|
+
"## 1.2.3 - 2026-09-07\n\n### Added\n",
|
|
73
|
+
"## 1.2.3 - 2026-02-30\n\n- Change.\n",
|
|
74
|
+
"## 1.2.3 - soon\n\n- Change.\n",
|
|
75
|
+
"## 1.2.2 - 2026-09-07\n\n- Change.\n",
|
|
76
|
+
"## 1.2.3 - 2026-09-07\n\n- A.\n\n## 1.2.3 - 2026-09-08\n\n- B.\n",
|
|
77
|
+
"## Unreleased\n\n## Unreleased\n",
|
|
78
|
+
],
|
|
79
|
+
)
|
|
80
|
+
def test_rejects_unready_release_notes(project: Path, notes: str) -> None:
|
|
81
|
+
(project / "CHANGELOG.md").write_text(notes, encoding="utf-8")
|
|
82
|
+
with pytest.raises(ValueError):
|
|
83
|
+
release.check_release(project, tag="v1.2.3")
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def test_rejects_direct_dependencies(project: Path) -> None:
|
|
87
|
+
manifest = project / "pyproject.toml"
|
|
88
|
+
manifest.write_text(
|
|
89
|
+
manifest.read_text().replace("numpy>=1.24", "numpy @ file:///sibling/numpy"),
|
|
90
|
+
encoding="utf-8",
|
|
91
|
+
)
|
|
92
|
+
with pytest.raises(ValueError, match="registry"):
|
|
93
|
+
release.check_release(project)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def test_clean_check_detects_untracked_files(project: Path) -> None:
|
|
97
|
+
subprocess.run(["git", "init", "--quiet", str(project)], check=True)
|
|
98
|
+
with pytest.raises(ValueError, match="pending changes"):
|
|
99
|
+
release.check_release(project, require_clean=True)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def test_cli_outputs_and_failure(project: Path, tmp_path: Path) -> None:
|
|
103
|
+
output = tmp_path / "output"
|
|
104
|
+
notes = tmp_path / "notes"
|
|
105
|
+
assert (
|
|
106
|
+
release.main(
|
|
107
|
+
[
|
|
108
|
+
"--root",
|
|
109
|
+
str(project),
|
|
110
|
+
"--tag",
|
|
111
|
+
"v1.2.3",
|
|
112
|
+
"--github-output",
|
|
113
|
+
str(output),
|
|
114
|
+
"--notes-output",
|
|
115
|
+
str(notes),
|
|
116
|
+
]
|
|
117
|
+
)
|
|
118
|
+
== 0
|
|
119
|
+
)
|
|
120
|
+
assert output.read_text() == "version=1.2.3\n"
|
|
121
|
+
assert notes.read_text() == "- Release change.\n"
|
|
122
|
+
assert release.main(["--root", str(project), "--tag", "v9.0.0"]) == 1
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.4.0 - 2026-11-12
|
|
4
|
+
|
|
5
|
+
### Breaking changes
|
|
6
|
+
|
|
7
|
+
- Aperture-sum errors used `sqrt(sum(w * error**2))` and overestimated small
|
|
8
|
+
apertures; `apsum_err` and `radcum_profile` errors now use
|
|
9
|
+
`sqrt(sum(w**2 * error**2))` (`w`: pixel-overlap weight), as photutils 3.1 does.
|
|
10
|
+
- `srcsum_err` counted sky noise twice and omitted the sky-estimate error; it
|
|
11
|
+
now uses `sqrt(apsum_err**2 + (apsum_npix * dsky)**2)`.
|
|
12
|
+
- `sky_fit` and `apphot_annulus` add `dsky`, the standard error of `msky`
|
|
13
|
+
(`radial_profile`: `dpix`).
|
|
14
|
+
|
|
15
|
+
## 0.3.0 - 2026-06-18
|
|
16
|
+
|
|
17
|
+
- Migrated aperture photometry and image combination to the `astroapers` and `imcombiners` backends; deprecated `combutil`.
|
|
18
|
+
- Added linear WCS helper functions (`local_cd_matrix`, `make_linear_wcs`, `make_zoomed_wcs`).
|
|
19
|
+
- Performance improvements: cached regex, `fitsio`-preferred I/O, and perf for `bin_ccd` and `sep`-based extraction.
|
|
20
|
+
- Unified logging across the package.
|
|
21
|
+
- Large-scale internal reorganization and type-hint cleanup.
|
|
22
|
+
- [breaking] Removed FWHM-based aperture initialization.
|
|
23
|
+
|
|
24
|
+
## 0.2.0 - 2026-05-07
|
|
25
|
+
|
|
26
|
+
- Bumped to v0.2.0.
|
|
27
|
+
- Python >=3.11 and Astropy >=7.0. Some type hints and Astropy-affiliated dependency floors were updated accordingly.
|
|
28
|
+
- Renamed `make_summary` to `fits_summary` and added `.parq`/`.parquet` summary output.
|
|
29
|
+
|
|
30
|
+
## 0.1.1 - 2026-05-07
|
|
31
|
+
|
|
32
|
+
- Bumped to v0.1.1.
|
|
33
|
+
- Fixed minor typos in comments and docstrings.
|
|
34
|
+
- Replaced diagnostic `print` calls and non-deprecation warnings with package logger calls.
|
|
35
|
+
- Added small neutral type hints and formatting/import cleanup.
|
|
36
|
+
|
|
37
|
+
## 0.1.0 - 2026-05-07
|
|
38
|
+
|
|
39
|
+
- Initial port of FITS management utilities from `ysfitsutilpy` and lightweight visualization helpers from `ysvisutilpy`.
|
astroimred-0.4.0/LICENSE
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026, Yoonsoo P. Bach
|
|
4
|
+
|
|
5
|
+
Redistribution and use in source and binary forms, with or without
|
|
6
|
+
modification, are permitted provided that the following conditions are met:
|
|
7
|
+
|
|
8
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
9
|
+
list of conditions and the following disclaimer.
|
|
10
|
+
|
|
11
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
12
|
+
this list of conditions and the following disclaimer in the documentation
|
|
13
|
+
and/or other materials provided with the distribution.
|
|
14
|
+
|
|
15
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
16
|
+
contributors may be used to endorse or promote products derived from
|
|
17
|
+
this software without specific prior written permission.
|
|
18
|
+
|
|
19
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
20
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
21
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
22
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
23
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
24
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
25
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
26
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
27
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
28
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: astroimred
|
|
3
|
+
Version: 0.4.0
|
|
4
|
+
Summary: FITS file management and lightweight inspection utilities.
|
|
5
|
+
Author: ysBach
|
|
6
|
+
Author-email: ysBach <ysbach93@gmail.com>
|
|
7
|
+
License-Expression: BSD-3-Clause
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Requires-Dist: astropy>=7.0
|
|
10
|
+
Requires-Dist: astro-ndslice>=0.2
|
|
11
|
+
Requires-Dist: numpy>=1.24
|
|
12
|
+
Requires-Dist: pandas>=2.0
|
|
13
|
+
Requires-Dist: pyarrow>=14
|
|
14
|
+
Requires-Dist: astroapers>=0.1.2
|
|
15
|
+
Requires-Dist: imcombiners>=0.1.1
|
|
16
|
+
Requires-Dist: reducers>=0.3.0
|
|
17
|
+
Requires-Dist: astroapers ; extra == 'full'
|
|
18
|
+
Requires-Dist: fitsio>=1.2 ; extra == 'full'
|
|
19
|
+
Requires-Dist: astroscrappy>=1.1 ; extra == 'full'
|
|
20
|
+
Requires-Dist: ccdproc>=2.0 ; extra == 'full'
|
|
21
|
+
Requires-Dist: click>=8.0 ; extra == 'full'
|
|
22
|
+
Requires-Dist: fitsio>=1.2 ; extra == 'full'
|
|
23
|
+
Requires-Dist: matplotlib>=3.9.1 ; extra == 'full'
|
|
24
|
+
Requires-Dist: numba>=0.59 ; extra == 'full'
|
|
25
|
+
Requires-Dist: numexpr>=2.8 ; extra == 'full'
|
|
26
|
+
Requires-Dist: photutils>=2.0,<4.0 ; extra == 'full'
|
|
27
|
+
Requires-Dist: pyarrow>=14 ; extra == 'full'
|
|
28
|
+
Requires-Dist: scipy>=1.9.2 ; extra == 'full'
|
|
29
|
+
Requires-Dist: sep>=1.4 ; extra == 'full'
|
|
30
|
+
Requires-Dist: astroapers ; extra == 'phot'
|
|
31
|
+
Requires-Dist: matplotlib>=3.9.1 ; extra == 'phot'
|
|
32
|
+
Requires-Dist: photutils>=2.0,<4.0 ; extra == 'phot'
|
|
33
|
+
Requires-Dist: scipy>=1.9.2 ; extra == 'phot'
|
|
34
|
+
Requires-Dist: sep>=1.4 ; extra == 'phot'
|
|
35
|
+
Requires-Dist: astroscrappy>=1.1 ; extra == 'reduction'
|
|
36
|
+
Requires-Dist: ccdproc>=2.0 ; extra == 'reduction'
|
|
37
|
+
Requires-Dist: click>=8.0 ; extra == 'reduction'
|
|
38
|
+
Requires-Dist: numba>=0.59 ; extra == 'reduction'
|
|
39
|
+
Requires-Dist: scipy>=1.9.2 ; extra == 'reduction'
|
|
40
|
+
Requires-Python: >=3.11
|
|
41
|
+
Project-URL: Documentation, https://ysbach.github.io/astroimred/
|
|
42
|
+
Project-URL: Repository, https://github.com/ysBach/astroimred
|
|
43
|
+
Project-URL: Issues, https://github.com/ysBach/astroimred/issues
|
|
44
|
+
Project-URL: Changelog, https://github.com/ysBach/astroimred/blob/main/CHANGELOG.md
|
|
45
|
+
Provides-Extra: full
|
|
46
|
+
Provides-Extra: phot
|
|
47
|
+
Provides-Extra: reduction
|
|
48
|
+
Description-Content-Type: text/markdown
|
|
49
|
+
|
|
50
|
+
# astroimred
|
|
51
|
+
|
|
52
|
+
[FITS](https://en.wikipedia.org/wiki/FITS) file management and manipulation tool.
|
|
53
|
+
|
|
54
|
+
Recommended import:
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
import astroimred as air
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Many of initial skeleton are directly borrowed from legacy FITS utilities.
|
|
61
|
+
|
|
62
|
+
Reduction utilities from the former `fitsimred` package are being ported into
|
|
63
|
+
the `astroimred.reduction` namespace.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# astroimred
|
|
2
|
+
|
|
3
|
+
[FITS](https://en.wikipedia.org/wiki/FITS) file management and manipulation tool.
|
|
4
|
+
|
|
5
|
+
Recommended import:
|
|
6
|
+
|
|
7
|
+
```python
|
|
8
|
+
import astroimred as air
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Many of initial skeleton are directly borrowed from legacy FITS utilities.
|
|
12
|
+
|
|
13
|
+
Reduction utilities from the former `fitsimred` package are being ported into
|
|
14
|
+
the `astroimred.reduction` namespace.
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# Release astroimred
|
|
2
|
+
|
|
3
|
+
**Run a manual rehearsal, then push the matching `vX.Y.Z` tag to publish.**
|
|
4
|
+
Use the exact commit that passed the rehearsal.
|
|
5
|
+
|
|
6
|
+
| Event | Checks | Publication |
|
|
7
|
+
| --- | --- | --- |
|
|
8
|
+
| Branch push or pull request | CI and installed distributions | None |
|
|
9
|
+
| Manual `release.yml` | Same checks; dated notes required when run on a tag | None |
|
|
10
|
+
| Matching `vX.Y.Z` tag push | Same checks, plus dated release notes | PyPI, then GitHub release |
|
|
11
|
+
|
|
12
|
+
## Shared convention
|
|
13
|
+
|
|
14
|
+
Keep publication in one `release.yml`. The convention combines ImCombiners'
|
|
15
|
+
tag trigger, reducers' reusable CI and early release-note checks, and pqfilt's
|
|
16
|
+
installed-artifact checks. A GitHub release records successful publication;
|
|
17
|
+
creating one does not trigger publishing.
|
|
18
|
+
|
|
19
|
+
| Package type | Artifacts | Registries |
|
|
20
|
+
| --- | --- | --- |
|
|
21
|
+
| `astroimred`: pure Python, `uv_build` | One universal wheel and sdist | PyPI |
|
|
22
|
+
| `astroapers`: Maturin, public Rust API | Per-Python/platform wheels and sdist | PyPI and crates.io |
|
|
23
|
+
|
|
24
|
+
Publish the exact Python files that passed installation tests. Rust publication
|
|
25
|
+
packages the checked commit again with Cargo. Use registry dependencies and
|
|
26
|
+
temporary OIDC credentials. Never synchronize `~/.venvs/ysbpy`.
|
|
27
|
+
|
|
28
|
+
## One-time setup
|
|
29
|
+
|
|
30
|
+
1. Confirm the GitHub repository is `ysBach/astroimred`. Older clones can retain
|
|
31
|
+
the former `fitsmgmt` remote; inspect `git remote -v` and update it if needed:
|
|
32
|
+
|
|
33
|
+
```sh
|
|
34
|
+
git remote set-url origin https://github.com/ysBach/astroimred.git
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
The publisher job permits only `ysBach/astroimred`. A repository rename also
|
|
38
|
+
requires changing that guard and the PyPI trusted-publisher settings.
|
|
39
|
+
|
|
40
|
+
2. Create a GitHub environment named `pypi`. Restrict deployment to **tags**
|
|
41
|
+
matching `v*`. For fully automatic releases after tagging, do not configure
|
|
42
|
+
required environment reviewers. Protect tag creation with a repository ruleset.
|
|
43
|
+
|
|
44
|
+
3. Add a trusted publisher in
|
|
45
|
+
[PyPI Publishing settings](https://pypi.org/manage/project/astroimred/settings/publishing/):
|
|
46
|
+
|
|
47
|
+
| Setting | Value |
|
|
48
|
+
| --- | --- |
|
|
49
|
+
| Project | `astroimred` |
|
|
50
|
+
| Owner / repository | `ysBach` / `astroimred` |
|
|
51
|
+
| Workflow filename | `release.yml` |
|
|
52
|
+
| Environment | `pypi` |
|
|
53
|
+
|
|
54
|
+
For a project that does not exist yet, use a
|
|
55
|
+
[pending publisher](https://docs.pypi.org/trusted-publishers/creating-a-project-through-oidc/).
|
|
56
|
+
No permanent PyPI token belongs in GitHub secrets.
|
|
57
|
+
|
|
58
|
+
4. Enable Actions and require the CI build and installed-distribution checks
|
|
59
|
+
on `main`. Select their actual check names after the first hosted run.
|
|
60
|
+
Repository and registry settings are external setup; committing these files
|
|
61
|
+
does not configure them.
|
|
62
|
+
|
|
63
|
+
## Prepare and rehearse
|
|
64
|
+
|
|
65
|
+
1. Select the next unused version in `pyproject.toml`. Move `Unreleased` notes
|
|
66
|
+
into one nonempty `## X.Y.Z - YYYY-MM-DD` section with the real release date.
|
|
67
|
+
Leave `Unreleased` empty or remove it. The checker rejects prerelease tags,
|
|
68
|
+
mismatches, duplicate sections, and pending notes on tagged releases.
|
|
69
|
+
|
|
70
|
+
2. Activate the shared environment for local release-tool checks:
|
|
71
|
+
|
|
72
|
+
```sh
|
|
73
|
+
source ~/.venvs/ysbpy/bin/activate
|
|
74
|
+
uv run --active --no-sync python scripts/check_release.py
|
|
75
|
+
uv run --active --no-sync pytest .github/tests -q
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Release tooling requires Python 3.11+. With a project `.venv`, omit `--active`.
|
|
79
|
+
Do not run `uv sync` or `uv pip sync` against the shared environment.
|
|
80
|
+
`uv.lock` is intentionally untracked here: the version comes from
|
|
81
|
+
`pyproject.toml`, and CI resolves published dependencies for fresh installs.
|
|
82
|
+
|
|
83
|
+
3. Review and commit the intended files, including new files. Push the commit
|
|
84
|
+
and start a rehearsal:
|
|
85
|
+
|
|
86
|
+
```sh
|
|
87
|
+
uv run --active --no-sync python scripts/check_release.py --require-clean
|
|
88
|
+
git push origin main
|
|
89
|
+
gh workflow run release.yml --ref main
|
|
90
|
+
gh run list --workflow release.yml
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
4. Inspect the run with `gh run view RUN_ID`. All checks must pass; PyPI and
|
|
94
|
+
GitHub release jobs must be skipped. Record the successful run's full commit
|
|
95
|
+
SHA with `gh run view RUN_ID --json headSha --jq .headSha`.
|
|
96
|
+
|
|
97
|
+
## Publish
|
|
98
|
+
|
|
99
|
+
1. Check out that exact commit. Replace `REHEARSED_COMMIT_SHA` and `X.Y.Z`:
|
|
100
|
+
|
|
101
|
+
```sh
|
|
102
|
+
git switch --detach REHEARSED_COMMIT_SHA
|
|
103
|
+
uv run --active --no-sync python scripts/check_release.py --tag vX.Y.Z --require-clean
|
|
104
|
+
git tag -a vX.Y.Z -m "Release X.Y.Z"
|
|
105
|
+
git push origin vX.Y.Z
|
|
106
|
+
git switch main
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
**Pushing the tag publishes automatically.** A version bump or ordinary push
|
|
110
|
+
does not publish. Versions are selected by the maintainer, not by CI.
|
|
111
|
+
|
|
112
|
+
2. Check the tag-triggered Actions run, the PyPI version page, and the GitHub
|
|
113
|
+
release. Its wheel, sdist, and notes come from the same successful run.
|
|
114
|
+
|
|
115
|
+
## Coverage and recovery
|
|
116
|
+
|
|
117
|
+
### Check the tested artifacts
|
|
118
|
+
|
|
119
|
+
CI builds a `py3-none-any` wheel and sdist.
|
|
120
|
+
|
|
121
|
+
| Platform | Python coverage |
|
|
122
|
+
| --- | --- |
|
|
123
|
+
| Linux | 3.11–3.14; also installs the sdist on 3.14 |
|
|
124
|
+
| macOS ARM64 | 3.13 |
|
|
125
|
+
| Windows x86-64 | 3.13 |
|
|
126
|
+
|
|
127
|
+
Each install uses the `full` extra in a fresh environment. Checks cover isolated
|
|
128
|
+
imports, license/FITS handling, CLI help, and the Python suite. Release-tool
|
|
129
|
+
tests and Ruff checks cover `scripts/` and `.github/tests/`; existing application
|
|
130
|
+
formatting is outside this publishing change. These are configured targets,
|
|
131
|
+
not evidence of compatibility until hosted runs pass.
|
|
132
|
+
|
|
133
|
+
`UV_NO_SOURCES=true` disables developer overrides. Dependencies must be available
|
|
134
|
+
from registries; a test that needs unpublished sibling changes must fail until
|
|
135
|
+
those dependencies are released. CI intentionally does not substitute sibling
|
|
136
|
+
checkouts. The same retained wheel and sdist are uploaded without rebuilding.
|
|
137
|
+
|
|
138
|
+
### Recover without changing published files
|
|
139
|
+
|
|
140
|
+
- **Before uploading:** fix the problem, commit, and rehearse again. Source or
|
|
141
|
+
artifact changes after a tag push require a new version/tag; never move a
|
|
142
|
+
published tag.
|
|
143
|
+
- **Upload/network/setup failure:** fix the external issue and rerun only failed
|
|
144
|
+
jobs in the original tag-push run. Keep its original artifacts. `uv publish`
|
|
145
|
+
skips identical existing files and rejects conflicting bytes; see
|
|
146
|
+
[uv retry behavior](https://docs.astral.sh/uv/guides/package/).
|
|
147
|
+
- **GitHub release failure after PyPI succeeded:** rerun the failed job if no
|
|
148
|
+
GitHub release exists. If one exists, inspect it and restore missing assets
|
|
149
|
+
from the original run. Do not rebuild files or republish changed bytes.
|
|
150
|
+
|
|
151
|
+
PyPI publication and GitHub release creation are separate operations; a partial
|
|
152
|
+
release is possible. Retain the original successful artifacts during recovery.
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "astroimred"
|
|
3
|
+
version = "0.4.0"
|
|
4
|
+
description = "FITS file management and lightweight inspection utilities."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
license = "BSD-3-Clause"
|
|
7
|
+
license-files = ["LICENSE"]
|
|
8
|
+
requires-python = ">=3.11"
|
|
9
|
+
dependencies = [
|
|
10
|
+
"astropy>=7.0",
|
|
11
|
+
"astro-ndslice>=0.2",
|
|
12
|
+
"numpy>=1.24",
|
|
13
|
+
"pandas>=2.0",
|
|
14
|
+
"pyarrow>=14",
|
|
15
|
+
"astroapers>=0.1.2",
|
|
16
|
+
"imcombiners>=0.1.1",
|
|
17
|
+
"reducers>=0.3.0",
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
[[project.authors]]
|
|
21
|
+
name = "ysBach"
|
|
22
|
+
email = "ysbach93@gmail.com"
|
|
23
|
+
|
|
24
|
+
[project.scripts]
|
|
25
|
+
imred = "astroimred.reduction.cli:main"
|
|
26
|
+
|
|
27
|
+
[project.urls]
|
|
28
|
+
Documentation = "https://ysbach.github.io/astroimred/"
|
|
29
|
+
Repository = "https://github.com/ysBach/astroimred"
|
|
30
|
+
Issues = "https://github.com/ysBach/astroimred/issues"
|
|
31
|
+
Changelog = "https://github.com/ysBach/astroimred/blob/main/CHANGELOG.md"
|
|
32
|
+
|
|
33
|
+
[project.optional-dependencies]
|
|
34
|
+
phot = [
|
|
35
|
+
"astroapers",
|
|
36
|
+
"matplotlib>=3.9.1",
|
|
37
|
+
"photutils>=2.0,<4.0",
|
|
38
|
+
"scipy>=1.9.2",
|
|
39
|
+
"sep>=1.4",
|
|
40
|
+
]
|
|
41
|
+
reduction = [
|
|
42
|
+
"astroscrappy>=1.1",
|
|
43
|
+
"ccdproc>=2.0",
|
|
44
|
+
"click>=8.0",
|
|
45
|
+
"numba>=0.59",
|
|
46
|
+
"scipy>=1.9.2",
|
|
47
|
+
]
|
|
48
|
+
full = [
|
|
49
|
+
"astroapers",
|
|
50
|
+
"fitsio>=1.2",
|
|
51
|
+
"astroscrappy>=1.1",
|
|
52
|
+
"ccdproc>=2.0",
|
|
53
|
+
"click>=8.0",
|
|
54
|
+
"fitsio>=1.2",
|
|
55
|
+
"matplotlib>=3.9.1",
|
|
56
|
+
"numba>=0.59",
|
|
57
|
+
"numexpr>=2.8",
|
|
58
|
+
"photutils>=2.0,<4.0",
|
|
59
|
+
"pyarrow>=14",
|
|
60
|
+
"scipy>=1.9.2",
|
|
61
|
+
"sep>=1.4",
|
|
62
|
+
]
|
|
63
|
+
|
|
64
|
+
[dependency-groups]
|
|
65
|
+
dev = [
|
|
66
|
+
"pytest>=8.0",
|
|
67
|
+
"ruff>=0.8",
|
|
68
|
+
"sphinx>=7.2",
|
|
69
|
+
"sphinx-rtd-theme>=2.0",
|
|
70
|
+
]
|
|
71
|
+
|
|
72
|
+
[tool.ruff]
|
|
73
|
+
line-length = 88
|
|
74
|
+
target-version = "py311"
|
|
75
|
+
src = [
|
|
76
|
+
"src",
|
|
77
|
+
"tests",
|
|
78
|
+
]
|
|
79
|
+
|
|
80
|
+
[tool.ruff.lint]
|
|
81
|
+
select = [
|
|
82
|
+
"E",
|
|
83
|
+
"F",
|
|
84
|
+
"W",
|
|
85
|
+
"I",
|
|
86
|
+
"UP",
|
|
87
|
+
"B",
|
|
88
|
+
"C4",
|
|
89
|
+
"SIM",
|
|
90
|
+
]
|
|
91
|
+
ignore = [
|
|
92
|
+
"E501",
|
|
93
|
+
"W605",
|
|
94
|
+
]
|
|
95
|
+
fixable = ["ALL"]
|
|
96
|
+
|
|
97
|
+
[tool.ruff.lint.per-file-ignores]
|
|
98
|
+
"src/astroimred/**/__init__.py" = [
|
|
99
|
+
"F401",
|
|
100
|
+
"F403",
|
|
101
|
+
]
|
|
102
|
+
|
|
103
|
+
[tool.ruff.format]
|
|
104
|
+
line-ending = "auto"
|
|
105
|
+
|
|
106
|
+
[tool.uv.build-backend]
|
|
107
|
+
source-include = [
|
|
108
|
+
"CHANGELOG.md",
|
|
109
|
+
"RELEASING.md",
|
|
110
|
+
"scripts/**",
|
|
111
|
+
".github/tests/**",
|
|
112
|
+
"tests/**",
|
|
113
|
+
]
|
|
114
|
+
|
|
115
|
+
[build-system]
|
|
116
|
+
requires = ["uv_build>=0.9.18,<0.10.0"]
|
|
117
|
+
build-backend = "uv_build"
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "astroimred"
|
|
3
|
+
version = "0.4.0"
|
|
4
|
+
description = "FITS file management and lightweight inspection utilities."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
license = "BSD-3-Clause"
|
|
7
|
+
license-files = ["LICENSE"]
|
|
8
|
+
authors = [
|
|
9
|
+
{ name = "ysBach", email = "ysbach93@gmail.com" }
|
|
10
|
+
]
|
|
11
|
+
requires-python = ">=3.11"
|
|
12
|
+
# Core dependencies for basic manipulation of FITS
|
|
13
|
+
dependencies = [
|
|
14
|
+
"astropy>=7.0",
|
|
15
|
+
"astro-ndslice>=0.2",
|
|
16
|
+
"numpy>=1.24",
|
|
17
|
+
"pandas>=2.0",
|
|
18
|
+
"pyarrow>=14",
|
|
19
|
+
"astroapers>=0.1.2",
|
|
20
|
+
"imcombiners>=0.1.1",
|
|
21
|
+
"reducers>=0.3.0",
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
[project.scripts]
|
|
25
|
+
imred = "astroimred.reduction.cli:main"
|
|
26
|
+
|
|
27
|
+
[project.urls]
|
|
28
|
+
Documentation = "https://ysbach.github.io/astroimred/"
|
|
29
|
+
Repository = "https://github.com/ysBach/astroimred"
|
|
30
|
+
Issues = "https://github.com/ysBach/astroimred/issues"
|
|
31
|
+
Changelog = "https://github.com/ysBach/astroimred/blob/main/CHANGELOG.md"
|
|
32
|
+
|
|
33
|
+
[project.optional-dependencies]
|
|
34
|
+
phot = [
|
|
35
|
+
"astroapers",
|
|
36
|
+
"matplotlib>=3.9.1",
|
|
37
|
+
"photutils>=2.0,<4.0",
|
|
38
|
+
"scipy>=1.9.2",
|
|
39
|
+
"sep>=1.4",
|
|
40
|
+
]
|
|
41
|
+
reduction = [
|
|
42
|
+
"astroscrappy>=1.1",
|
|
43
|
+
"ccdproc>=2.0",
|
|
44
|
+
"click>=8.0",
|
|
45
|
+
"numba>=0.59",
|
|
46
|
+
"scipy>=1.9.2",
|
|
47
|
+
]
|
|
48
|
+
full = [
|
|
49
|
+
"astroapers",
|
|
50
|
+
"fitsio>=1.2",
|
|
51
|
+
"astroscrappy>=1.1",
|
|
52
|
+
"ccdproc>=2.0",
|
|
53
|
+
"click>=8.0",
|
|
54
|
+
"fitsio>=1.2",
|
|
55
|
+
"matplotlib>=3.9.1",
|
|
56
|
+
"numba>=0.59",
|
|
57
|
+
"numexpr>=2.8",
|
|
58
|
+
"photutils>=2.0,<4.0",
|
|
59
|
+
"pyarrow>=14",
|
|
60
|
+
"scipy>=1.9.2",
|
|
61
|
+
"sep>=1.4",
|
|
62
|
+
]
|
|
63
|
+
|
|
64
|
+
[dependency-groups]
|
|
65
|
+
dev = [
|
|
66
|
+
"pytest>=8.0",
|
|
67
|
+
"ruff>=0.8",
|
|
68
|
+
"sphinx>=7.2",
|
|
69
|
+
"sphinx-rtd-theme>=2.0",
|
|
70
|
+
]
|
|
71
|
+
|
|
72
|
+
[tool.ruff]
|
|
73
|
+
line-length = 88
|
|
74
|
+
target-version = "py311"
|
|
75
|
+
src = ["src", "tests"]
|
|
76
|
+
|
|
77
|
+
[tool.ruff.lint]
|
|
78
|
+
select = [
|
|
79
|
+
"E", # pycodestyle errors
|
|
80
|
+
"F", # Pyflakes
|
|
81
|
+
"W", # pycodestyle warnings
|
|
82
|
+
"I", # import sorting
|
|
83
|
+
"UP", # pyupgrade
|
|
84
|
+
"B", # flake8-bugbear
|
|
85
|
+
"C4", # comprehensions
|
|
86
|
+
"SIM", # simplifications
|
|
87
|
+
]
|
|
88
|
+
ignore = [
|
|
89
|
+
"E501", # Let the formatter wrap what it can; tolerate intentional long lines.
|
|
90
|
+
"W605", # Legacy astronomy strings often contain backslash-style notation.
|
|
91
|
+
]
|
|
92
|
+
fixable = ["ALL"]
|
|
93
|
+
|
|
94
|
+
[tool.ruff.lint.per-file-ignores]
|
|
95
|
+
"src/astroimred/**/__init__.py" = ["F401", "F403"]
|
|
96
|
+
|
|
97
|
+
[tool.ruff.format]
|
|
98
|
+
line-ending = "auto"
|
|
99
|
+
|
|
100
|
+
[build-system]
|
|
101
|
+
requires = ["uv_build>=0.9.18,<0.10.0"]
|
|
102
|
+
build-backend = "uv_build"
|
|
103
|
+
|
|
104
|
+
[tool.uv.build-backend]
|
|
105
|
+
source-include = ["CHANGELOG.md", "RELEASING.md", "scripts/**", ".github/tests/**", "tests/**"]
|