asteria-roman 0.1.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.
Files changed (55) hide show
  1. asteria_roman-0.1.0/.github/workflows/ci.yml +44 -0
  2. asteria_roman-0.1.0/.github/workflows/publish.yml +67 -0
  3. asteria_roman-0.1.0/.gitignore +64 -0
  4. asteria_roman-0.1.0/LICENSE +21 -0
  5. asteria_roman-0.1.0/PKG-INFO +158 -0
  6. asteria_roman-0.1.0/README.md +117 -0
  7. asteria_roman-0.1.0/docs/Makefile +13 -0
  8. asteria_roman-0.1.0/docs/_static/images/example_blinking.gif +0 -0
  9. asteria_roman-0.1.0/docs/api.rst +68 -0
  10. asteria_roman-0.1.0/docs/architecture.rst +97 -0
  11. asteria_roman-0.1.0/docs/conf.py +54 -0
  12. asteria_roman-0.1.0/docs/dataset.rst +68 -0
  13. asteria_roman-0.1.0/docs/index.rst +89 -0
  14. asteria_roman-0.1.0/docs/weights_history.rst +107 -0
  15. asteria_roman-0.1.0/notebooks/01_asteria_segmentation_and_deblending.ipynb +646 -0
  16. asteria_roman-0.1.0/notebooks/02_starnet3_star_removal.ipynb +681 -0
  17. asteria_roman-0.1.0/notebooks/03_center_offset_instance_segmentation.ipynb +470 -0
  18. asteria_roman-0.1.0/notebooks/demo_two_panel.png +0 -0
  19. asteria_roman-0.1.0/pyproject.toml +83 -0
  20. asteria_roman-0.1.0/src/asteria/__init__.py +193 -0
  21. asteria_roman-0.1.0/src/asteria/cli.py +502 -0
  22. asteria_roman-0.1.0/src/asteria/inference/__init__.py +32 -0
  23. asteria_roman-0.1.0/src/asteria/inference/center_offset.py +826 -0
  24. asteria_roman-0.1.0/src/asteria/inference/device.py +256 -0
  25. asteria_roman-0.1.0/src/asteria/inference/results.py +41 -0
  26. asteria_roman-0.1.0/src/asteria/inference/segmentor.py +599 -0
  27. asteria_roman-0.1.0/src/asteria/inference/starnet3.py +640 -0
  28. asteria_roman-0.1.0/src/asteria/io/__init__.py +5 -0
  29. asteria_roman-0.1.0/src/asteria/io/reader.py +376 -0
  30. asteria_roman-0.1.0/src/asteria/models/__init__.py +40 -0
  31. asteria_roman-0.1.0/src/asteria/models/offset_losses.py +464 -0
  32. asteria_roman-0.1.0/src/asteria/models/starnet3.py +864 -0
  33. asteria_roman-0.1.0/src/asteria/models/unetpp.py +175 -0
  34. asteria_roman-0.1.0/src/asteria/models/unetpp_offset.py +295 -0
  35. asteria_roman-0.1.0/src/asteria/py.typed +0 -0
  36. asteria_roman-0.1.0/src/asteria/stretch/__init__.py +23 -0
  37. asteria_roman-0.1.0/src/asteria/stretch/leakysb.py +583 -0
  38. asteria_roman-0.1.0/src/asteria/utils/__init__.py +5 -0
  39. asteria_roman-0.1.0/src/asteria/utils/synthetic.py +152 -0
  40. asteria_roman-0.1.0/src/asteria/visualization/__init__.py +27 -0
  41. asteria_roman-0.1.0/src/asteria/visualization/clarity.py +540 -0
  42. asteria_roman-0.1.0/src/asteria/visualization/plot.py +429 -0
  43. asteria_roman-0.1.0/src/asteria/weights/__init__.py +41 -0
  44. asteria_roman-0.1.0/src/asteria/weights/manager.py +169 -0
  45. asteria_roman-0.1.0/src/asteria/weights/registry.py +64 -0
  46. asteria_roman-0.1.0/src/asteria/weights/starnet3_manager.py +151 -0
  47. asteria_roman-0.1.0/src/asteria/weights/starnet3_registry.py +52 -0
  48. asteria_roman-0.1.0/tests/test_clarity.py +175 -0
  49. asteria_roman-0.1.0/tests/test_cli.py +115 -0
  50. asteria_roman-0.1.0/tests/test_device.py +27 -0
  51. asteria_roman-0.1.0/tests/test_inference.py +185 -0
  52. asteria_roman-0.1.0/tests/test_io.py +117 -0
  53. asteria_roman-0.1.0/tests/test_leakysb.py +81 -0
  54. asteria_roman-0.1.0/tests/test_models.py +52 -0
  55. asteria_roman-0.1.0/tests/test_weights.py +66 -0
@@ -0,0 +1,44 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [ main ]
6
+ pull_request:
7
+ branches: [ main ]
8
+
9
+ jobs:
10
+ test:
11
+ name: Test (${{ matrix.os }} - Python ${{ matrix.python-version }})
12
+ runs-on: ${{ matrix.os }}
13
+ strategy:
14
+ fail-fast: false
15
+ matrix:
16
+ os: [ ubuntu-latest, macos-latest, windows-latest ]
17
+ python-version: [ "3.11", "3.12" ]
18
+
19
+ steps:
20
+ - name: Checkout Repository
21
+ uses: actions/checkout@v4
22
+
23
+ - name: Set up Python ${{ matrix.python-version }}
24
+ uses: actions/setup-python@v5
25
+ with:
26
+ python-version: ${{ matrix.python-version }}
27
+ cache: "pip"
28
+
29
+ - name: Install Package & Test Dependencies
30
+ run: |
31
+ python -m pip install --upgrade pip setuptools wheel
32
+ python -m pip install -e ".[dev]"
33
+
34
+ - name: Run Test Suite (pytest)
35
+ run: |
36
+ pytest -v --cov=asteria --cov-report=xml
37
+
38
+ - name: Build Source Distribution & Wheel
39
+ run: |
40
+ python -m build
41
+
42
+ - name: Verify Package Metadata with Twine
43
+ run: |
44
+ twine check dist/*
@@ -0,0 +1,67 @@
1
+ name: Deploy to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+ workflow_dispatch:
8
+
9
+ permissions:
10
+ id-token: write # Mandatory for PyPI Trusted Publishing (OIDC)
11
+ contents: read
12
+
13
+ jobs:
14
+ test:
15
+ name: Run Pre-Release Tests
16
+ runs-on: ubuntu-latest
17
+ steps:
18
+ - name: Checkout Repository
19
+ uses: actions/checkout@v4
20
+
21
+ - name: Set up Python
22
+ uses: actions/setup-python@v5
23
+ with:
24
+ python-version: "3.11"
25
+ cache: "pip"
26
+
27
+ - name: Install Dependencies
28
+ run: |
29
+ python -m pip install --upgrade pip
30
+ python -m pip install -e ".[dev]"
31
+
32
+ - name: Run Pytest
33
+ run: |
34
+ pytest -v
35
+
36
+ build-and-publish:
37
+ name: Build & Publish to PyPI
38
+ needs: test
39
+ runs-on: ubuntu-latest
40
+ environment:
41
+ name: pypi
42
+ url: https://pypi.org/p/asteria-roman
43
+ steps:
44
+ - name: Checkout Repository
45
+ uses: actions/checkout@v4
46
+
47
+ - name: Set up Python
48
+ uses: actions/setup-python@v5
49
+ with:
50
+ python-version: "3.11"
51
+
52
+ - name: Install Build Tools
53
+ run: |
54
+ python -m pip install --upgrade pip build twine
55
+
56
+ - name: Build Distribution Packages
57
+ run: |
58
+ python -m build
59
+
60
+ - name: Validate Wheel & Sdist with Twine
61
+ run: |
62
+ twine check dist/*
63
+
64
+ - name: Publish Package to PyPI
65
+ uses: pypa/gh-action-pypi-publish@release/v1
66
+ with:
67
+ skip-existing: true
@@ -0,0 +1,64 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # Distribution / packaging
7
+ dist/
8
+ build/
9
+ *.egg-info/
10
+ .eggs/
11
+
12
+ # Environments
13
+ .env
14
+ .venv
15
+ env/
16
+ venv/
17
+ ENV/
18
+
19
+ # Testing & Coverage
20
+ .pytest_cache/
21
+ .coverage
22
+ htmlcov/
23
+ coverage.xml
24
+ *.xml
25
+
26
+ # Weights & Large Data (Never commit real weights or data files)
27
+ *.pt
28
+ *.pth
29
+ *.onnx
30
+ *.fits
31
+ *.fits.gz
32
+ *.asdf
33
+ *.tar
34
+ *.tar.gz
35
+ data/
36
+ /weights/
37
+ !src/asteria/weights/
38
+ .cache/
39
+
40
+ # Sphinx docs build
41
+ docs/_build/
42
+ docs/build/
43
+
44
+ # IDE & OS
45
+ .DS_Store
46
+ .idea/
47
+ .vscode/
48
+ *.swp
49
+
50
+ # Untracked developer notes & guidelines
51
+ guidelines.md
52
+ *guidelines*.md
53
+
54
+ # Agent memory & guidelines (kept locally for next sessions, excluded from git)
55
+ MEMORY.md
56
+ *memory*.md
57
+ AGENTS.md
58
+ *agent*.md
59
+ .agents/
60
+ .agent/
61
+ _agents/
62
+ _agent/
63
+ GEMINI.md
64
+ *gemini*.md
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Pablo M. Sanchez-Alarcon
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,158 @@
1
+ Metadata-Version: 2.5
2
+ Name: asteria-roman
3
+ Version: 0.1.0
4
+ Summary: Lightweight astronomical deep learning inference engine and instance deblender powered by boundary-aware UNet++
5
+ Project-URL: Homepage, https://github.com/PabloMSanAla/asteria
6
+ Project-URL: Documentation, https://asteria.readthedocs.io
7
+ Project-URL: Repository, https://github.com/PabloMSanAla/asteria.git
8
+ Project-URL: Issues, https://github.com/PabloMSanAla/asteria/issues
9
+ Author-email: "Pablo M. Sanchez-Alarcon" <pablo.sanchezalarcon@nasa.gov>
10
+ License-Expression: MIT
11
+ License-File: LICENSE
12
+ Keywords: asdf,astronomy,astrophysics,deblending,deep-learning,fits,roman-space-telescope,segmentation,unetplusplus
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Science/Research
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
20
+ Classifier: Topic :: Scientific/Engineering :: Astronomy
21
+ Requires-Python: >=3.11
22
+ Requires-Dist: astropy>=5.0.0
23
+ Requires-Dist: matplotlib>=3.6.0
24
+ Requires-Dist: numpy>=1.22.0
25
+ Requires-Dist: pixel-clarity>=0.9.0
26
+ Requires-Dist: requests>=2.28.0
27
+ Requires-Dist: roman-datamodels>=1.0.0
28
+ Requires-Dist: scipy>=1.9.0
29
+ Requires-Dist: torch>=2.0.0
30
+ Requires-Dist: tqdm>=4.65.0
31
+ Provides-Extra: dev
32
+ Requires-Dist: build>=1.0.0; extra == 'dev'
33
+ Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
34
+ Requires-Dist: pytest>=7.0.0; extra == 'dev'
35
+ Requires-Dist: twine>=5.0.0; extra == 'dev'
36
+ Provides-Extra: docs
37
+ Requires-Dist: myst-parser>=2.0.0; extra == 'docs'
38
+ Requires-Dist: sphinx-rtd-theme>=2.0.0; extra == 'docs'
39
+ Requires-Dist: sphinx>=7.0.0; extra == 'docs'
40
+ Description-Content-Type: text/markdown
41
+
42
+ # Asteria 🌌
43
+
44
+ [![PyPI version](https://img.shields.io/pypi/v/asteria.svg?color=blue)](https://pypi.org/project/asteria/)
45
+ [![Python Versions](https://img.shields.io/pypi/pyversions/asteria.svg)](https://pypi.org/project/asteria/)
46
+ [![CI Status](https://github.com/PabloMSanAla/asteria/actions/workflows/ci.yml/badge.svg)](https://github.com/PabloMSanAla/asteria/actions)
47
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
48
+ [![Documentation Status](https://readthedocs.org/projects/asteria/badge/?version=latest)](https://asteria.readthedocs.io/en/latest/?badge=latest)
49
+
50
+
51
+
52
+ <p><strong>Asteria</strong> is a lightweight, high-performance deep learning inference engine and instance deblender for stars in astronomical imaging, powered by boundary-aware <strong>UNet++ (Nested U-Net)</strong>.</p>
53
+
54
+ <p>Designed for the <strong>Nancy Grace Roman Space Telescope</strong>, Asteria provides promptless, end-to-end star detection in a single neural forward pass.</p>
55
+
56
+ <p align="center">
57
+ <img width="40%" src="https://raw.githubusercontent.com/PabloMSanAla/asteria/prepare-production/docs/_static/images/example_blinking.gif" alt="Asteria segmentation example">
58
+ <sub><br> Example of <strong>Asteria</strong> star detection on a simulated Roman WFI exposure.</sub>
59
+ </p>
60
+
61
+
62
+ ---
63
+
64
+ ## Key Features
65
+
66
+ - **Lightweight & Self-Contained**: Pure PyTorch UNet++ architecture without bulky dependencies or heavyweight vision foundation models.
67
+ - **Hardware Acceleration with Automatic Fallback**: Auto-detects and optimizes execution across **NVIDIA CUDA** (with TF32 and AMP), **Apple Silicon MPS** (Metal Performance Shaders on macOS), and universal **CPU**.
68
+ - **Physical Boundary-Aware Deblending**: Trained with 3-class supervision:
69
+ - `0`: Sky Background
70
+ - `1`: Source Interior / Core
71
+ - `2`: Deblending Boundary / Contact Interface
72
+ - **Seamless Tiled Dense Inference (`predict_dense`)**: Sliding-window 2D Hann/cosine window blending to process arbitrary image sizes (from local cutouts up to full $4088 \times 4088$ Roman WFI exposures) with bounded memory ($< 350$ MB VRAM).
73
+ - **Photometric LeakySB Stretch**: Non-linear surface brightness transformation that preserves stellar point-spread functions (PSFs) while lifting faint, diffuse galactic wings.
74
+ - **Unified Astronomical I/O**: Direct support for 2D astronomical **FITS** (`.fits`, `.fits.gz`), Roman **ASDF** (`.asdf` Level 2 calibrated exposures and Level 3 mosaics via `roman_datamodels`), and raw **NumPy** arrays. Automatically converts Level 2 exposures to surface brightness units ($\text{MJy/sr}$) using calibrated photometry and enables $\text{ZP}=20.472$.
75
+ - **Instant Deblending**: Marker-controlled watershed expansion turning dense neural predictions into discrete celestial catalogs with centroids, bounding boxes, and photometry.
76
+
77
+ ---
78
+
79
+ ## Installation
80
+
81
+ ### From PyPI
82
+ ```bash
83
+ pip install asteria-roman
84
+ ```
85
+
86
+ ### From Source
87
+ ```bash
88
+ git clone https://github.com/PabloMSanAla/asteria.git
89
+ cd asteria
90
+ pip install -e .
91
+ ```
92
+
93
+ ---
94
+
95
+ ## Quickstart
96
+
97
+ ### 1. Python API
98
+
99
+ ```python
100
+ import asteria
101
+
102
+ # 1. Load pre-trained model (auto-downloads weights on first run, auto-selects device)
103
+ segmentor = asteria.load_model("latest")
104
+
105
+ # 2. Run dense 3-class segmentation inference on a FITS or ASDF exposure
106
+ pred_mask, probs, stretched = segmentor.predict_dense(
107
+ "scene_0001_F106.fits",
108
+ tile_size=512,
109
+ overlap=64,
110
+ )
111
+
112
+ # 3. Render publication-ready side-by-side 2-panel figure
113
+ fig = asteria.plot_two_panel(
114
+ stretched=stretched,
115
+ pred_mask=pred_mask,
116
+ save_path="prediction.png",
117
+ )
118
+
119
+ # 4. Extract discrete, deblended astronomical sources (marker-controlled watershed)
120
+ catalog = segmentor.segment("scene_0001_F106.fits")
121
+ print(f"Extracted {len(catalog.masks)} distinct celestial objects!")
122
+ for idx, (cx, cy) in enumerate(catalog.centroids[:5]):
123
+ print(f"Source #{idx + 1}: centroid=({cx:.1f}, {cy:.1f}), area={catalog.areas[idx]} px")
124
+ ```
125
+
126
+ ### 2. Command-Line Interface (CLI)
127
+
128
+ Asteria includes the `asteria-predict` CLI command:
129
+
130
+ ```bash
131
+ # Basic prediction and display
132
+ asteria-predict scene.fits
133
+
134
+ # Full-field tiled inference with saving and FITS export
135
+ asteria-predict scene.fits \
136
+ --tile_size 512 \
137
+ --overlap 64 \
138
+ --output results.png \
139
+ --export_fits segmap.fits \
140
+ --deblend \
141
+ --no_display
142
+ ```
143
+
144
+ ---
145
+
146
+ ## Model Architecture & Weights History
147
+
148
+ | Weight Version | Backbone | Resolution | Training Set | Epochs | Interior IoU | Edge IoU (tol=1px) | Macro IoU | Training cutouts | Hardware |
149
+ | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- |
150
+ | **`v0.1.0`** (latest) | UNet++ (32-512) | $512 \times 512$ | Roman WFI Synthetic | 80 | **0.754** | **0.513** | **0.6335** | 2800 | NASA NAS GH200 |
151
+
152
+ For comprehensive architectural details and benchmark comparisons, see the [Asteria Documentation](https://asteria.readthedocs.io).
153
+
154
+ ---
155
+
156
+ ## License
157
+
158
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
@@ -0,0 +1,117 @@
1
+ # Asteria 🌌
2
+
3
+ [![PyPI version](https://img.shields.io/pypi/v/asteria.svg?color=blue)](https://pypi.org/project/asteria/)
4
+ [![Python Versions](https://img.shields.io/pypi/pyversions/asteria.svg)](https://pypi.org/project/asteria/)
5
+ [![CI Status](https://github.com/PabloMSanAla/asteria/actions/workflows/ci.yml/badge.svg)](https://github.com/PabloMSanAla/asteria/actions)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+ [![Documentation Status](https://readthedocs.org/projects/asteria/badge/?version=latest)](https://asteria.readthedocs.io/en/latest/?badge=latest)
8
+
9
+
10
+
11
+ <p><strong>Asteria</strong> is a lightweight, high-performance deep learning inference engine and instance deblender for stars in astronomical imaging, powered by boundary-aware <strong>UNet++ (Nested U-Net)</strong>.</p>
12
+
13
+ <p>Designed for the <strong>Nancy Grace Roman Space Telescope</strong>, Asteria provides promptless, end-to-end star detection in a single neural forward pass.</p>
14
+
15
+ <p align="center">
16
+ <img width="40%" src="https://raw.githubusercontent.com/PabloMSanAla/asteria/prepare-production/docs/_static/images/example_blinking.gif" alt="Asteria segmentation example">
17
+ <sub><br> Example of <strong>Asteria</strong> star detection on a simulated Roman WFI exposure.</sub>
18
+ </p>
19
+
20
+
21
+ ---
22
+
23
+ ## Key Features
24
+
25
+ - **Lightweight & Self-Contained**: Pure PyTorch UNet++ architecture without bulky dependencies or heavyweight vision foundation models.
26
+ - **Hardware Acceleration with Automatic Fallback**: Auto-detects and optimizes execution across **NVIDIA CUDA** (with TF32 and AMP), **Apple Silicon MPS** (Metal Performance Shaders on macOS), and universal **CPU**.
27
+ - **Physical Boundary-Aware Deblending**: Trained with 3-class supervision:
28
+ - `0`: Sky Background
29
+ - `1`: Source Interior / Core
30
+ - `2`: Deblending Boundary / Contact Interface
31
+ - **Seamless Tiled Dense Inference (`predict_dense`)**: Sliding-window 2D Hann/cosine window blending to process arbitrary image sizes (from local cutouts up to full $4088 \times 4088$ Roman WFI exposures) with bounded memory ($< 350$ MB VRAM).
32
+ - **Photometric LeakySB Stretch**: Non-linear surface brightness transformation that preserves stellar point-spread functions (PSFs) while lifting faint, diffuse galactic wings.
33
+ - **Unified Astronomical I/O**: Direct support for 2D astronomical **FITS** (`.fits`, `.fits.gz`), Roman **ASDF** (`.asdf` Level 2 calibrated exposures and Level 3 mosaics via `roman_datamodels`), and raw **NumPy** arrays. Automatically converts Level 2 exposures to surface brightness units ($\text{MJy/sr}$) using calibrated photometry and enables $\text{ZP}=20.472$.
34
+ - **Instant Deblending**: Marker-controlled watershed expansion turning dense neural predictions into discrete celestial catalogs with centroids, bounding boxes, and photometry.
35
+
36
+ ---
37
+
38
+ ## Installation
39
+
40
+ ### From PyPI
41
+ ```bash
42
+ pip install asteria-roman
43
+ ```
44
+
45
+ ### From Source
46
+ ```bash
47
+ git clone https://github.com/PabloMSanAla/asteria.git
48
+ cd asteria
49
+ pip install -e .
50
+ ```
51
+
52
+ ---
53
+
54
+ ## Quickstart
55
+
56
+ ### 1. Python API
57
+
58
+ ```python
59
+ import asteria
60
+
61
+ # 1. Load pre-trained model (auto-downloads weights on first run, auto-selects device)
62
+ segmentor = asteria.load_model("latest")
63
+
64
+ # 2. Run dense 3-class segmentation inference on a FITS or ASDF exposure
65
+ pred_mask, probs, stretched = segmentor.predict_dense(
66
+ "scene_0001_F106.fits",
67
+ tile_size=512,
68
+ overlap=64,
69
+ )
70
+
71
+ # 3. Render publication-ready side-by-side 2-panel figure
72
+ fig = asteria.plot_two_panel(
73
+ stretched=stretched,
74
+ pred_mask=pred_mask,
75
+ save_path="prediction.png",
76
+ )
77
+
78
+ # 4. Extract discrete, deblended astronomical sources (marker-controlled watershed)
79
+ catalog = segmentor.segment("scene_0001_F106.fits")
80
+ print(f"Extracted {len(catalog.masks)} distinct celestial objects!")
81
+ for idx, (cx, cy) in enumerate(catalog.centroids[:5]):
82
+ print(f"Source #{idx + 1}: centroid=({cx:.1f}, {cy:.1f}), area={catalog.areas[idx]} px")
83
+ ```
84
+
85
+ ### 2. Command-Line Interface (CLI)
86
+
87
+ Asteria includes the `asteria-predict` CLI command:
88
+
89
+ ```bash
90
+ # Basic prediction and display
91
+ asteria-predict scene.fits
92
+
93
+ # Full-field tiled inference with saving and FITS export
94
+ asteria-predict scene.fits \
95
+ --tile_size 512 \
96
+ --overlap 64 \
97
+ --output results.png \
98
+ --export_fits segmap.fits \
99
+ --deblend \
100
+ --no_display
101
+ ```
102
+
103
+ ---
104
+
105
+ ## Model Architecture & Weights History
106
+
107
+ | Weight Version | Backbone | Resolution | Training Set | Epochs | Interior IoU | Edge IoU (tol=1px) | Macro IoU | Training cutouts | Hardware |
108
+ | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- |
109
+ | **`v0.1.0`** (latest) | UNet++ (32-512) | $512 \times 512$ | Roman WFI Synthetic | 80 | **0.754** | **0.513** | **0.6335** | 2800 | NASA NAS GH200 |
110
+
111
+ For comprehensive architectural details and benchmark comparisons, see the [Asteria Documentation](https://asteria.readthedocs.io).
112
+
113
+ ---
114
+
115
+ ## License
116
+
117
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
@@ -0,0 +1,13 @@
1
+ # Minimal makefile for Sphinx documentation
2
+ SPHINXOPTS ?=
3
+ SPHINXBUILD ?= sphinx-build
4
+ SOURCEDIR = .
5
+ BUILDDIR = _build
6
+
7
+ help:
8
+ @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
9
+
10
+ .PHONY: help Makefile
11
+
12
+ %: Makefile
13
+ @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
@@ -0,0 +1,68 @@
1
+ .. _api:
2
+
3
+ API Reference
4
+ =============
5
+
6
+ This section documents the public classes, functions, and modules in Asteria.
7
+
8
+ Top-Level Functions
9
+ -------------------
10
+
11
+ .. autofunction:: asteria.load_model
12
+
13
+ Inference & Deblending
14
+ ----------------------
15
+
16
+ .. autoclass:: asteria.AsteriaSegmentor
17
+ :members:
18
+ :undoc-members:
19
+ :show-inheritance:
20
+
21
+ .. autoclass:: asteria.SegmentationResult
22
+ :show-inheritance:
23
+
24
+ .. autofunction:: asteria.get_optimal_device
25
+
26
+ .. autofunction:: asteria.get_device_info
27
+
28
+ Neural Network Architecture
29
+ ---------------------------
30
+
31
+ .. autoclass:: asteria.UNetPlusPlus
32
+ :members:
33
+ :undoc-members:
34
+ :show-inheritance:
35
+
36
+ Photometric Stretches
37
+ ---------------------
38
+
39
+ .. autofunction:: asteria.leaky_surface_brightness
40
+
41
+ .. autofunction:: asteria.asinh_stretch
42
+
43
+ .. autofunction:: asteria.linear_stretch
44
+
45
+ .. autofunction:: asteria.stretch_image
46
+
47
+ Astronomical Image I/O
48
+ ----------------------
49
+
50
+ .. autofunction:: asteria.load_image
51
+
52
+ .. autoclass:: asteria.AstroImage
53
+ :show-inheritance:
54
+
55
+ Visualization
56
+ -------------
57
+
58
+ .. autofunction:: asteria.plot_two_panel
59
+
60
+ .. autofunction:: asteria.plot_instance_overlay
61
+
62
+ Model Weights Registry
63
+ ----------------------
64
+
65
+ .. autoclass:: asteria.weights.registry.WeightMetadata
66
+ :show-inheritance:
67
+
68
+ .. autofunction:: asteria.weights.registry.get_weight_metadata
@@ -0,0 +1,97 @@
1
+ .. _architecture:
2
+
3
+ Model Architecture
4
+ ==================
5
+
6
+ Asteria is powered by a **Nested U-Net (UNet++)** deep convolutional neural network, engineered specifically for high-contrast astronomical imaging and crowded-field source extraction.
7
+
8
+ .. contents:: Table of Contents
9
+ :depth: 2
10
+ :local:
11
+
12
+ Why UNet++ for Astronomical Source Detection?
13
+ ---------------------------------------------
14
+
15
+ Traditional astronomical source extraction pipelines (such as SExtractor or standard thresholding) struggle in crowded stellar regions and galaxy clusters where object halos overlap. While standard U-Nets use direct skip connections between encoder and decoder stages, they suffer from a **semantic gap**: low-level encoder features contain rich spatial coordinates but high noise, whereas high-level decoder features contain abstract semantic context at degraded spatial resolution.
16
+
17
+ UNet++ (Zhou et al., 2018; 2019) overcomes this limitation by bridging the semantic gap through **nested, dense skip pathways**.
18
+
19
+ Mathematical Formulation
20
+ -------------------------
21
+
22
+ Let $x^{i,j}$ denote the output of node $X^{i,j}$, where:
23
+
24
+ * $i \in \{0, 1, 2, 3, 4\}$ indexes the downsampling depth along the encoder backbone.
25
+ * $j \in \{0, 1, 2, 3, 4\}$ indexes the dense convolution layer along the horizontal skip pathway.
26
+
27
+ The forward accumulation at each intermediate node is computed as:
28
+
29
+ .. math::
30
+
31
+ x^{i,j} = \begin{cases}
32
+ \mathcal{H}_{\text{enc}}\left( \mathcal{D}(x^{i-1, 0}) \right), & j = 0 \\
33
+ \mathcal{H}\left( \left[ [x^{i,k}]_{k=0}^{j-1}, \mathcal{U}(x^{i+1, j-1}) \right] \right), & j > 0
34
+ \end{cases}
35
+
36
+ where:
37
+
38
+ * $\mathcal{H}(\cdot)$ denotes a double convolution block (Conv2D $\to$ BatchNorm $\to$ ReLU $\to$ Conv2D $\to$ BatchNorm $\to$ ReLU).
39
+ * $\mathcal{D}(\cdot)$ denotes $2 \times 2$ max pooling with stride 2.
40
+ * $\mathcal{U}(\cdot)$ denotes bilinear upsampling with scale factor 2.
41
+ * $[\cdot]$ denotes channel-wise feature concatenation.
42
+
43
+ Through these nested skip pathways, feature maps from earlier stages are progressively merged and refined before reaching the decoder nodes, ensuring that fine astronomical boundary structures are preserved with sub-pixel fidelity.
44
+
45
+ Three-Class Boundary-Aware Target Formulation
46
+ ---------------------------------------------
47
+
48
+ Standard binary segmentation (source vs. background) inevitably merges touching or overlapping astronomical sources into contiguous blobs, requiring heuristic post-processing deblenders.
49
+
50
+ Asteria formulates source detection as a **3-class boundary-aware semantic segmentation** task:
51
+
52
+ * **Class 0 (Sky Background)**: Deep space sky noise and intergalactic regions.
53
+ * **Class 1 (Source Interior / Core)**: High surface brightness galactic cores and stellar point spread functions (PSFs).
54
+ * **Class 2 (Deblending Boundary / Edge)**: The outer perimeter of celestial sources and, critically, the contact interface between overlapping or touching objects.
55
+
56
+ Deblending via Marker-Controlled Watershed
57
+ ------------------------------------------
58
+
59
+ During inference, Asteria leverages the explicit boundary prediction to split touching galaxies:
60
+
61
+ 1. **Topological Seed Markers**: Identified by thresholding the interior probability map ($P_{\text{core}} \ge 0.45$). Connected components generate distinct integer markers for each galaxy core.
62
+ 2. **Total Foreground Mask**: Computed from $P_{\text{core}} + P_{\text{edge}} \ge 0.50$ (or $P_{\text{bg}} < 0.50$).
63
+ 3. **Watershed Expansion**: Inverted Euclidean distance transforms expand the core markers outward until they collide along the predicted Class 2 boundary line, cleanly separating touching objects into discrete instances without morphological distortion.
64
+
65
+ Loss Function & Class Weighting
66
+ -------------------------------
67
+
68
+ Due to the extreme class imbalance in deep astronomical exposures (where the sky background occupies $\sim 85-90\%$ of pixels, source cores $\sim 2-5\%$, and 1-pixel boundaries $\sim 5-10\%$), models trained with standard unweighted Cross-Entropy collapse toward predicting the background.
69
+
70
+ Asteria was trained using a **Combined Weighted Cross-Entropy and Multi-Class Dice Loss**:
71
+
72
+ .. math::
73
+
74
+ \mathcal{L}_{\text{total}} = \mathcal{L}_{\text{WCE}} + \lambda \mathcal{L}_{\text{Dice}}
75
+
76
+ with empirically optimized class weights:
77
+
78
+ .. math::
79
+
80
+ \mathbf{w}_{\text{CE}} = [w_{\text{bg}} = 0.5, \; w_{\text{core}} = 2.5, \; w_{\text{edge}} = 8.0]
81
+
82
+ The high penalty ($8.0$) on boundary errors forces the network to prioritize thin edge continuity, which is the decisive factor for successful instance deblending.
83
+
84
+ Tiled Dense Sliding-Window Inference (`predict_dense`)
85
+ ------------------------------------------------------
86
+
87
+ To process large scientific exposures (such as the $4088 \times 4088$ detector arrays of the Nancy Grace Roman Space Telescope) without GPU out-of-memory (OOM) failures or artificial boundary seams:
88
+
89
+ 1. The exposure is decomposed into overlapping $512 \times 512$ tiles with a default 64-pixel margin.
90
+ 2. Each tile is evaluated in mini-batches through the neural network.
91
+ 3. Softmax probability maps are accumulated using a **2D separable Hann / cosine window**:
92
+
93
+ .. math::
94
+
95
+ W(x, y) = \sin\left(\frac{\pi x}{T}\right) \cdot \sin\left(\frac{\pi y}{T}\right)
96
+
97
+ 4. The accumulated probability tensor is normalized by the total weight matrix, completely eliminating edge discontinuity artifacts and bounding memory consumption to $< 350$ MB VRAM.