Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 20 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ SHINE/
├── shine/ # Main Python package
│ ├── __init__.py
│ ├── config.py # Base inference configuration
│ ├── prior_utils.py # Shared prior-parsing (config → NumPyro sample sites)
│ ├── inference.py # Inference engine (MAP, NUTS)
│ └── euclid/ # Euclid VIS instrument backend
│ ├── config.py # Euclid-specific configuration
Expand All @@ -55,7 +56,8 @@ SHINE/

| Module | Status | Purpose |
|--------|--------|---------|
| `shine.config` | Implemented | Inference configuration (MAP, NUTS, VI settings) |
| `shine.config` | Implemented | Configuration schema (galaxy model, inference, distributions with `center: catalog`) |
| `shine.prior_utils` | Implemented | Shared prior-parsing: converts `DistributionConfig` → NumPyro sample sites |
| `shine.inference` | Implemented | Inference engine (MAP optimization, NUTS via NumPyro) |
| `shine.euclid` | Implemented | Euclid VIS instrument backend: data loading, scene model, diagnostics |
| `shine.scene_modelling` | Planned | Generic NumPyro generative model definitions |
Expand All @@ -67,7 +69,7 @@ SHINE/

The first instrument backend, providing end-to-end shear inference on Euclid VIS quadrant-level data:

- **`config.py`** — Pydantic configuration: data paths, source selection (SNR, `det_quality_flag`, size filtering), prior distributions, multi-tier stamp sizes
- **`config.py`** — Pydantic configuration: data paths, source selection (SNR, `det_quality_flag`, size filtering), galaxy model specification via shared `GalaxyConfig` (supports `center: catalog` priors), multi-tier stamp sizes
- **`data_loader.py`** — Reads quadrant FITS files (SCI/RMS/FLG), PSF grids with bilinear interpolation, background maps, MER catalogs; computes per-source WCS positions, Jacobians, PSF stamps, and visibility
- **`scene.py`** — NumPyro generative model: renders Sersic galaxies convolved with spatially-varying PSFs via JAX-GalSim; multi-tier stamp sizes (64/128/256 px) with separate `vmap` per tier; standalone `render_model_images()` for post-inference visualization
- **`plots.py`** — 3-panel diagnostic figures (observed | model | chi residual) with configurable masking
Expand Down Expand Up @@ -120,6 +122,22 @@ Future testing should also include:

SHINE uses GalSim-compatible YAML configuration with a probabilistic extension: any parameter defined as a distribution (e.g., `type: Normal`) becomes a **latent variable** for inference rather than a fixed simulation value. See `DESIGN.md` Section 6.1 for config examples.

Both the generic `SceneBuilder` and the Euclid `MultiExposureScene` read their probabilistic model from the same `GalaxyConfig` schema in the YAML `gal:` section. The shared `parse_prior()` function in `shine.prior_utils` converts each config entry into a NumPyro sample site. For catalog-centered priors (where the location parameter comes from per-source catalog data), use `center: catalog`:

```yaml
gal:
type: Exponential
flux: {type: LogNormal, center: catalog, sigma: 0.5} # median from catalog
half_light_radius: {type: LogNormal, center: catalog, sigma: 0.3}
shear:
g1: {type: Normal, mean: 0.0, sigma: 0.05}
g2: {type: Normal, mean: 0.0, sigma: 0.05}
position:
type: Offset
dx: {type: Normal, mean: 0.0, sigma: 0.05}
dy: {type: Normal, mean: 0.0, sigma: 0.05}
```

## Development Roadmap

1. **Phase 1:** Prototype with simple parametric models (Sersic) and constant PSF
Expand Down
36 changes: 30 additions & 6 deletions configs/euclid_vis.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
#
# Points to the bundled test data in data/EUC_VIS_SWL/.
# Selects the 600 brightest sources and runs MAP inference for quick testing.
#
# The `gal:` section specifies the probabilistic model: galaxy profile type,
# which parameters are latent variables (distributions) vs fixed, and what
# priors are used. Parameters with `center: catalog` use per-source catalog
# values as the distribution location at runtime.

data:
exposure_paths:
Expand All @@ -26,12 +31,31 @@ sources:
det_quality_exclude_mask: 0x78C
max_sources: 600

priors:
shear_prior_sigma: 0.05
flux_prior_log_sigma: 0.5
hlr_prior_log_sigma: 0.3
ellipticity_prior_sigma: 0.3
position_prior_sigma: 0.05
# Galaxy model specification — the probabilistic model is explicit here.
# Each parameter is either a fixed value or a distribution (= latent variable).
gal:
type: Exponential

shear:
type: G1G2
g1: {type: Normal, mean: 0.0, sigma: 0.05}
g2: {type: Normal, mean: 0.0, sigma: 0.05}

# Catalog-centered priors: center="catalog" means the LogNormal median
# is set to each source's catalog value at runtime.
flux: {type: LogNormal, center: catalog, sigma: 0.5}
half_light_radius: {type: LogNormal, center: catalog, sigma: 0.3}

ellipticity:
type: E1E2
e1: {type: Normal, mean: 0.0, sigma: 0.3}
e2: {type: Normal, mean: 0.0, sigma: 0.3}

# Position offsets from catalog positions (in arcsec)
position:
type: Offset
dx: {type: Normal, mean: 0.0, sigma: 0.05}
dy: {type: Normal, mean: 0.0, sigma: 0.05}

inference:
method: map
Expand Down
10 changes: 7 additions & 3 deletions docs/api/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@ Configuration handling with Pydantic models.

Parses YAML configuration files and validates all parameters. Distribution
parameters (Normal, LogNormal, Uniform) are automatically treated as latent
variables for Bayesian inference. The `InferenceConfig` supports three
inference methods (NUTS, MAP, VI) with method-specific config blocks
(`NUTSConfig`, `MAPConfig`, `VIConfig`).
variables for Bayesian inference. Distributions can use `center: "catalog"` to
resolve their location parameter from per-source catalog data at runtime.
Position priors support both `Uniform` (absolute pixel positions) and `Offset`
(small offsets from catalog positions) modes.

The `InferenceConfig` supports three inference methods (NUTS, MAP, VI) with
method-specific config blocks (`NUTSConfig`, `MAPConfig`, `VIConfig`).

::: shine.config
10 changes: 10 additions & 0 deletions docs/api/prior_utils.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# shine.prior_utils

Shared prior-parsing utilities for SHINE scene builders.

Converts `DistributionConfig` entries (or fixed numeric values) into NumPyro
sample sites. Supports catalog-centered priors via the `center="catalog"`
mechanism, where the distribution location parameter comes from per-source
catalog data at runtime.

::: shine.prior_utils
97 changes: 93 additions & 4 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,29 @@ Supported distributions:
| Type | Parameters | Description |
|------|-----------|-------------|
| `Normal` | `mean`, `sigma` | Gaussian prior |
| `LogNormal` | `mean`, `sigma` | Log-normal prior |
| `LogNormal` | `mean`, `sigma` | Log-normal prior (`mean` is the median) |
| `Uniform` | `min`, `max` | Uniform prior |

#### Catalog-centered priors

For instrument-specific backends (e.g. Euclid) where per-source catalog
measurements are available, any `Normal` or `LogNormal` distribution can be
centered on catalog values by using `center: catalog` instead of a fixed `mean`:

```yaml
flux:
type: LogNormal
center: catalog # median comes from each source's catalog flux at runtime
sigma: 0.5
```

When `center: catalog` is set, the `mean` field is ignored. The scene builder
resolves the location parameter from the data catalog at runtime:

- **LogNormal**: `LogNormal(log(catalog_value_i), sigma)` — the catalog value
is the median
- **Normal**: `Normal(catalog_value_i, sigma)` — the catalog value is the mean

### Shear

Gravitational shear is defined as two components:
Expand Down Expand Up @@ -140,8 +160,10 @@ gal:

### Position

Galaxy position priors. Values < 1 are treated as fractions of image size;
values >= 1 are absolute pixel coordinates.
Galaxy position priors support two modes:

**Uniform (absolute positions)** — values < 1 are treated as fractions of image
size; values >= 1 are absolute pixel coordinates.

```yaml
gal:
Expand All @@ -153,6 +175,24 @@ gal:
y_max: 0.7
```

**Offset (from catalog positions)** — small offsets from known catalog
positions, typically used with instrument backends where source positions
come from a detection catalog.

```yaml
gal:
position:
type: Offset
dx:
type: Normal
mean: 0.0
sigma: 0.05 # arcsec
dy:
type: Normal
mean: 0.0
sigma: 0.05
```

## Inference Section

Controls the inference method and its settings. SHINE supports three methods:
Expand Down Expand Up @@ -245,7 +285,9 @@ inference:
| `method` | `"nuts"` / `"map"` / `"vi"` | `"nuts"` | Inference method |
| `rng_seed` | int >= 0 | `0` | JAX PRNG seed |

## Complete Example
## Complete Examples

### Level 0 — simple validation config

```yaml
image:
Expand Down Expand Up @@ -296,3 +338,50 @@ inference:
learning_rate: 0.01
rng_seed: 42
```

### Euclid VIS — instrument backend config

The Euclid config uses the same `gal:` schema but with `center: catalog`
priors and `Offset` positions. The `data:` and `sources:` sections are
specific to the Euclid backend (`EuclidInferenceConfig`).

```yaml
data:
exposure_paths:
- data/EUC_VIS_SWL/EUC_VIS_SWL-DET-..._3-4-F.fits.gz
psf_path: data/EUC_VIS_SWL/PSF_3-4-F.fits.gz
catalog_path: data/EUC_VIS_SWL/catalogue_3-4-F.fits.gz
pixel_scale: 0.1

sources:
min_snr: 10.0
max_sources: 600

gal:
type: Exponential
shear:
type: G1G2
g1: {type: Normal, mean: 0.0, sigma: 0.05}
g2: {type: Normal, mean: 0.0, sigma: 0.05}
flux: {type: LogNormal, center: catalog, sigma: 0.5}
half_light_radius: {type: LogNormal, center: catalog, sigma: 0.3}
ellipticity:
type: E1E2
e1: {type: Normal, mean: 0.0, sigma: 0.3}
e2: {type: Normal, mean: 0.0, sigma: 0.3}
position:
type: Offset
dx: {type: Normal, mean: 0.0, sigma: 0.05}
dy: {type: Normal, mean: 0.0, sigma: 0.05}

inference:
method: map
map_config:
enabled: true
num_steps: 200
learning_rate: 0.002
rng_seed: 42

galaxy_stamp_sizes: [64, 128, 256]
background: fixed
```
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ nav:
- GPU-Batched Inference: validation/batched.md
- API Reference:
- shine.config: api/config.md
- shine.prior_utils: api/prior_utils.md
- shine.scene: api/scene.md
- shine.inference: api/inference.md
- shine.data: api/data.md
Expand Down
36 changes: 3 additions & 33 deletions notebooks/euclid_vis_map.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -13,40 +13,10 @@
},
{
"cell_type": "code",
"execution_count": 1,
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import warnings\n",
"warnings.filterwarnings(\"ignore\", message=\".*complex128.*\", module=\"jax_galsim\")\n",
"\n",
"from pathlib import Path\n",
"\n",
"import jax\n",
"import jax.numpy as jnp\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"\n",
"from shine.config import InferenceConfig, MAPConfig\n",
"from shine.euclid.config import (\n",
" EuclidDataConfig,\n",
" EuclidInferenceConfig,\n",
" SourceSelectionConfig,\n",
")\n",
"from shine.euclid.data_loader import EuclidDataLoader\n",
"from shine.euclid.scene import MultiExposureScene, render_model_images\n",
"from shine.euclid.plots import plot_exposure_comparison\n",
"from shine.inference import Inference\n",
"\n",
"%matplotlib inline\n",
"\n",
"# --- Configuration ---\n",
"DATA_DIR = Path(\"../data/EUC_VIS_SWL\")\n",
"MAX_SOURCES = 1000\n",
"MIN_SNR = 10.0\n",
"MAP_STEPS = 220\n",
"RNG_SEED = 42"
]
"source": "import warnings\nwarnings.filterwarnings(\"ignore\", message=\".*complex128.*\", module=\"jax_galsim\")\n\nfrom pathlib import Path\n\nimport jax\nimport jax.numpy as jnp\nimport numpy as np\nimport matplotlib.pyplot as plt\n\nfrom shine.config import InferenceConfig, MAPConfig\nfrom shine.euclid.config import (\n EuclidDataConfig,\n EuclidInferenceConfig,\n SourceSelectionConfig,\n)\nfrom shine.euclid.data_loader import EuclidDataLoader\nfrom shine.euclid.scene import MultiExposureScene, render_model_images\nfrom shine.euclid.plots import plot_exposure_comparison\nfrom shine.inference import Inference\n\n%matplotlib inline\n\n# --- Configuration ---\nDATA_DIR = Path(\"../data/EUC_VIS_SWL\")\nMAX_SOURCES = 1000\nMIN_SNR = 10.0\nMAP_STEPS = 220\nRNG_SEED = 42"
},
{
"cell_type": "markdown",
Expand Down Expand Up @@ -512,4 +482,4 @@
},
"nbformat": 4,
"nbformat_minor": 4
}
}
Loading