Skip to main content

Learned mass-conserving deprojection of galaxy images -> 3D stellar density, rotation curve, potential.

Project description

Disk Galaxy Deprojection

This repository builds a baseline-plus-residual probabilistic benchmark for deprojecting barred-galaxy stellar mass structure from S4G-like images.

For project background, current Milestone 2b status, and continuation guidance, start with docs/reports/2026-06-10-project-handoff.md.

Deprojecting a galaxy image — the dgdp package

dgdp turns a galaxy image into its deprojected 3-D stellar-mass distribution, rotation curve, and (optionally) gravitational potential, using a bundled pretrained model — no training data or GPU required.

Install

pip install git+https://github.com/lucyundead/disk-galaxy-deprojection

Core install is light (numpy, astropy, matplotlib) and ships the ~1 MB model. Retraining the model additionally needs the TNG table and the [train] extra (pip install '.[train]').

Quickstart

Python:

from dgdp import deproject
r = deproject("galaxy.fits", distance_mpc=15.2, inclination_deg=30, pa_onsky_deg=153,
              ml=1.0, stellar_mass=6e10, n_samples=48)
r.density_3d              # (nR, nphi, nz) cylindrical stellar-mass cube [Msun]
r.v_circ([1, 2, 5, 10])   # rotation curve at those radii [km/s]
r.scale_height([1, 5, 10])       # sech^2 scale height h_z(R) [kpc] (rho ∝ sech²(z/h_z))
r.scale_height_samples([1, 5])   # posterior draws (n_samples, nR) -> uncertainty bands
r.rms_z([1, 5, 10])       # RMS|z|(R) moment [kpc] (tail-weighted; h_z is the obs-comparable one)
r.v_circ_samples([1, 5])  # same for the rotation curve
r.reproj["history"]       # reprojection-consistency residual (see below)
r.edge_on, r.face_on      # 2-D renderings
r.regrid(n_r=256, n_phi=192, n_z=128)   # same model re-evaluated on a finer grid (hydro ICs:
                          # vertical + m<=4 terms are analytic; only Sigma(R,phi) interpolates)
r.save("out/")            # density.npz + rotation_curve.csv + deprojection.png

CLI:

dgdp-deproject galaxy.fits --distance-mpc 15.2 --inclination-deg 30 --pa-onsky-deg 153 \
    --ml 1.0 --stellar-mass 6e10 -o out/

Geometry & M/L

  • Geometry: give pix_arcsec + pa_pix_deg (+ center) to bypass WCS (e.g. an S4G cutout), or let a FITS WCS supply the pixel scale and convert an on-sky pa_onsky_deg.
  • The deprojected shape is M/L-independent; M/L only sets the v_c amplitude. Fix the absolute scale with either (a) stellar_mass (total M*, M/L already folded in), (b) luminosity × ml, or (c) zeropoint + band_solar_mag + distance to calibrate the image to a luminosity. With none of these the outputs use a relative scale.

Potential (optional)

r.potential(R, z) and dgdp-deproject --potential return the AGAMA CylSpline potential Φ(R,z). AGAMA is not pip-installable — build it from source (https://github.com/GalacticDynamics-Oxford/Agama) and put it on PYTHONPATH; everything else works without it.

Method

The in-plane surface density is anchored geometrically from the image; a learned fixed-dictionary sech² vertical profile q_m(z;R) — trained on 185 TNG50 barred galaxies × 198 projections — supplies the thickness, mass-conserving by construction. See docs/reports/2026-06-30-mixture-qm-fixed-dictionary.md.

The learned vertical profiles cover m ∈ {0, 2, 4}; the remaining azimuthal content of the surface density (spiral arms, odd m) is carried with the local m=0 vertical profile — being φ-mean-free it changes no ring mass and no RMS|z|(R), but keeps the arms in the maps and lets the reprojection loop drive the image residual to the discretization floor.

Two consistency layers on top:

  • Reprojection loop (reproject_iters, default 2): the thick reconstruction is projected back to the sky and the Σ anchors are corrected until the model actually reproduces the observed image (the plain geometric stretch assumes zero thickness). Early-stops with revert, so it never returns a worse-reprojecting model; r.reproj["history"] holds the obs-weighted mean |log(obs/model)| per pass and r.reproj["ratio"] the final residual map.
  • Posterior sampling (n_samples): the bundled model is a mixture density network; sampling its head propagates the vertical-profile posterior to RMS|z|(R) and v_c(R) bands (rms_z_samples / v_circ_samples). Band coverage is calibrated on the held-out TNG50 val split (src/dgdp/models/dgdp_fixed_dict.calibration.json).

Milestone 1 predicts posterior residuals for physical summaries:

  • radial stellar mass profile
  • radial surface-density profile
  • vertical scale-height summary
  • bar thickness summary
  • bar amplitude summary
  • central concentration summary

Start with:

python -m pytest -q
python scripts/build_synthetic_benchmark.py --config configs/milestone1.synthetic.toml
python scripts/train_summary_residual_mdn.py --data outputs/milestone1_synthetic/residual_table.npz
python scripts/evaluate_summary_residual.py --run-dir outputs/milestone1_synthetic

Synthetic Milestone 1 Benchmark

Run the synthetic benchmark:

python scripts/build_synthetic_benchmark.py --config configs/milestone1.synthetic.toml
python scripts/train_summary_residual_mdn.py --data outputs/milestone1_synthetic/residual_table.npz --output-dir outputs/milestone1_synthetic
python scripts/evaluate_summary_residual.py --run-dir outputs/milestone1_synthetic

The benchmark writes:

  • outputs/milestone1_synthetic/manifest.csv
  • outputs/milestone1_synthetic/residual_table.npz
  • outputs/milestone1_synthetic/summary_residual_mdn.pt
  • outputs/milestone1_synthetic/normalization.npz
  • outputs/milestone1_synthetic/metrics.json

Milestone 2 Cluster TNG50 Ingestion

Milestone 2 runs TNG-facing work on the remote cluster through the existing HPC wrapper at /home/lucyundead/codex/hpc-agent/hpc.

python scripts/cluster_dgdp.py sync
python scripts/cluster_dgdp.py check-env
python scripts/cluster_dgdp.py reproduce-milestone1
python scripts/cluster_dgdp.py run-tng50
python scripts/cluster_dgdp.py run-tng50-density
python scripts/cluster_dgdp.py fetch-tng50

The cluster workflow keeps full TNG50 snapshots remote and fetches only compact artifacts under outputs/tng50_milestone2/. If local rsync is unavailable, the project CLI falls back to archive transfer through the HPC wrapper and does not delete remote files.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

disk_galaxy_deprojection-0.4.1.tar.gz (629.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

disk_galaxy_deprojection-0.4.1-py3-none-any.whl (595.1 kB view details)

Uploaded Python 3

File details

Details for the file disk_galaxy_deprojection-0.4.1.tar.gz.

File metadata

  • Download URL: disk_galaxy_deprojection-0.4.1.tar.gz
  • Upload date:
  • Size: 629.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for disk_galaxy_deprojection-0.4.1.tar.gz
Algorithm Hash digest
SHA256 612bc653a15c3a50f8abd6428657b795e65b7eb16d2ba0db14dc58b066e07b6c
MD5 da2c94a2664ace77b2810ff2fd823257
BLAKE2b-256 164f7513db6c9a5c51cd5676c6cf633d3c4eb728741ef8432340fb28c1b62208

See more details on using hashes here.

Provenance

The following attestation bundles were made for disk_galaxy_deprojection-0.4.1.tar.gz:

Publisher: release.yml on lucyundead/disk-galaxy-deprojection

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file disk_galaxy_deprojection-0.4.1-py3-none-any.whl.

File metadata

File hashes

Hashes for disk_galaxy_deprojection-0.4.1-py3-none-any.whl
Algorithm Hash digest
SHA256 1bf54f3a1ce199afbc593deaebb88ca273c8c366a2ac527c92e1f01e7141f87c
MD5 7ba91d3ec33e90e368b67127f6dba5e1
BLAKE2b-256 2db353589a0f3c3cd17662443672ee40d649cc2066634803180e15fbcd533776

See more details on using hashes here.

Provenance

The following attestation bundles were made for disk_galaxy_deprojection-0.4.1-py3-none-any.whl:

Publisher: release.yml on lucyundead/disk-galaxy-deprojection

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page