Metadata-Version: 2.4
Name: promage
Version: 0.2.0
Summary: ProMage observer-frame and absolute-magnitude emulator inference wrapper
Author-email: Luca Tortorelli <luca.tortorelli@physik.lmu.de>
License-Expression: MIT
Classifier: Intended Audience :: Science/Research
Classifier: Intended Audience :: Developers
Classifier: Natural Language :: English
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Operating System :: OS Independent
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: astropy
Requires-Dist: numpy
Requires-Dist: torch
Dynamic: license-file

# ProMage

ProMage is the inference wrapper for the magnitude emulator used by GalSBI.
End users provide galaxy physical properties and requested bands; ProMage loads
opaque TorchScript resources and returns emulated magnitudes.

The public API intentionally does not expose the neural-network architecture,
activation function, training loop, or scalers.

Each emulator instance is bound to one ProSpect star-formation-history (SFH)
model. The SFH model passed to ProMage must be the same SFH model used to create
the galaxy properties. Current resources provide `massfunc_snorm_trunc`; future
resources can also contain `massfunc_snorm_burst_trunc`.

## Installation

Install the released package from PyPI with:

```bash
pip install promage
```

For development, install a local checkout in editable mode:

```bash
pip install -e .
```

If the Python environment has no network access but already contains the build
dependencies, use:

```bash
pip install -e . --no-build-isolation
```

The magnitude-emulator resources are distributed separately through
cosmo-torrent. In GalSBI-SPS, load them with `data_path("ProMage_res")`.

## Basic Usage

```python
from promage import ProMage
from cosmo_torrent import data_path

emu = ProMage(
    data_path("ProMage_res"),
    sfh_model="massfunc_snorm_trunc",
)

mags = emu.predict(
    properties=properties,
    bands=["g_HSC", "r_HSC", "i_HSC"],
)
```

SFH-aware resources require `sfh_model`; omitting it or requesting an
unavailable family raises an error rather than silently loading the wrong
network. The selected family and all families in the resource can be inspected
with `emu.sfh_model` and `emu.available_sfh_models`.

By default, `predict` uses `frame="observed"` and returns final observer-frame
magnitudes. For artifacts trained as `m_obs - DM(z)`, ProMage adds the fixed
training distance modulus internally.

`mags` is a dictionary mapping each requested band to a NumPy array with the same
shape as the input property arrays.

## Absolute Magnitudes

Absolute/rest-frame magnitudes are requested with `frame="absolute"`:

```python
mags_abs = emu.predict(
    properties=properties,
    bands=["g_HSC", "r_HSC", "i_HSC"],
    frame="absolute",
)
```

Absolute-frame artifacts are trained directly on the ProSpect
`absolute_magnitudes` dataset. No distance-modulus correction is applied to
absolute-frame outputs.

Available frames and bands can be inspected with:

```python
print(emu.available_frames)
print(emu.available_roles)
print(emu.available_bands)
```

## Selection Magnitudes

Some resources include a threshold-selection role. This is separate from the
default precision magnitude emulators and is intended for broad sample
selection over the full redshift range. The current `massfunc_snorm_trunc`
resource was trained around an HSC `i_HSC = 32` threshold:

```python
i_selection = emu.predict(
    properties=properties,
    bands=["i_HSC"],
    role="selection",
)["i_HSC"]

threshold = emu.selection_threshold("i_HSC")
selected = i_selection < threshold
```

The default role is `role="magnitude"`, so existing calls to `predict(...)` are
unchanged. The selection role should not be treated as the final precision
magnitude estimate for all downstream photometry.

## Inputs

The resource manifest defines the required properties. Current ProSpect
Latin-hypercube resources use:

```python
[
    "z",
    "logmSFR",
    "mpeak",
    "logmperiod",
    "mskew",
    "logZfinal",
    "logtaubirth",
    "logtauscreen",
    "alphabirth",
    "alphascreen",
    "logU",
]
```

All arrays must have the same shape. Redshifts must lie inside the resource
domain, typically `0 < z <= 5`.

## Return Formats

The default return format is a dictionary:

```python
{
    "g_HSC": np.ndarray,
    "r_HSC": np.ndarray,
    "i_HSC": np.ndarray,
}
```

An array can be requested with:

```python
mag_array = emu.predict(
    properties=properties,
    bands=["g_HSC", "r_HSC", "i_HSC"],
    return_format="array",
)
```

The final axis follows the order of the requested bands.

## Resource Directory

`ProMage(...)` expects a directory containing a `manifest.json` and TorchScript
`.pt` artifacts.

An SFH-aware resource directory looks like:

```text
manifest.json
models/
  massfunc_snorm_trunc/
    observed/
      magnitude/
        g_HSC/
          z0p0_0p5.pt
          z0p5_1p0.pt
          ...
        r_HSC/
          ...
      selection/
        i_HSC/
          z0p0_5p0.pt
    absolute/
      magnitude/
        g_HSC/
          z0p0_0p5.pt
          z0p5_1p0.pt
          ...
        r_HSC/
          ...
  massfunc_snorm_burst_trunc/
    ...
```

SFH families, observer-frame artifacts, and absolute-frame artifacts can
coexist in the same `ProMage_res` directory because each has a distinct model
path.

Legacy manifests without explicit SFH families remain supported through
`ProMage(resource_dir)`. They cannot be safely assigned to a named SFH at load
time; regenerate those resources to obtain an SFH-aware manifest. Legacy
manifests without explicit roles are treated as `role="magnitude"`.

## Cosmology

The training data use a fixed flat LambdaCDM cosmology:

```text
H0 = 67.8
Omega_M = 0.308
Tcmb0 = 2.725
```

The package uses Astropy:

```python
from astropy.cosmology import FlatLambdaCDM

FlatLambdaCDM(H0=67.8, Om0=0.308, Tcmb0=2.725)
```

The distance-modulus correction is applied only for observer-frame artifacts
whose target convention is `obs_minus_dm`.

## Out-of-Range Redshifts

By default, ProMage raises an error if a redshift is outside the manifest domain:

```python
emu = ProMage(
    data_path("ProMage_res"),
    sfh_model="massfunc_snorm_trunc",
    on_out_of_range="raise",
)
```

To leave out-of-range predictions as `NaN`:

```python
emu = ProMage(
    data_path("ProMage_res"),
    sfh_model="massfunc_snorm_trunc",
    on_out_of_range="nan",
)
```

## License

ProMage is distributed under the MIT License. See `LICENSE`.
