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
28 changes: 17 additions & 11 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
#
# Cheap, fast (<5 min), CPU-only. Runs on every PR and on push to main.
# Does NOT produce real result artifacts — the smoke step short-circuits
# every profile script via AUTOLENS_PROFILING_SMOKE=1 (lands as part of
# Phase 5; see scripts under likelihood/, simulators/, searches/nautilus/).
# every profile script via AUTOLENS_PROFILING_SMOKE=1 (see scripts under
# likelihood_runtime/, likelihood_breakdown/, simulators/, searches/nautilus/).
#
# Profile re-runs that actually produce results live in `profile.yml`.

Expand Down Expand Up @@ -60,12 +60,15 @@ jobs:

- name: Install runtime dependencies
run: |
python -m pip install --upgrade pip
pip install numpy scipy matplotlib jax jaxlib
pip install nautilus-sampler==1.0.5
pip install numba
# autoconf / autofit / autoarray / autogalaxy / autolens are imported
# from the sibling checkouts via PYTHONPATH below — no install needed.
python -m pip install --upgrade pip setuptools wheel
# Install each sibling checkout in dependency order (the PyAutoHeart
# lib-tests.yml pattern): satisfies the full third-party dep chain
# (pyyaml, astropy, jax, numba, ...) without hand-maintaining a
# package list. PYTHONPATH below still resolves the PyAuto* imports
# from source, so the checkouts stay authoritative.
for r in PyAutoConf PyAutoFit PyAutoArray PyAutoGalaxy PyAutoLens; do
pip install "./$r[optional]"
done

- name: Install lint tools
run: |
Expand All @@ -92,9 +95,11 @@ jobs:
working-directory: autolens_profiling
run: |
# Conservative scope: only README.md files in this repo, exclude
# GitHub UI links that lychee tends to false-positive on.
# GitHub UI links that lychee tends to false-positive on, and the
# Slack invite (302 -> 403 to any non-browser client).
lychee \
--exclude '^https://github\.com/.*/(issues|pull|commit|releases)/' \
--exclude '^https://join\.slack\.com/' \
--no-progress \
--accept '200..=299,429' \
--max-redirects 5 \
Expand All @@ -111,6 +116,7 @@ jobs:
# Each script reads AUTOLENS_PROFILING_SMOKE at module top and
# exits 0 immediately after the import + setup section. Catches
# import-graph breakage without running the full profile.
python likelihood/imaging/mge.py
python likelihood_runtime/imaging/mge.py
python likelihood_breakdown/imaging/mge.py
python simulators/imaging.py
python searches/nautilus/simple.py
python searches/nautilus/imaging/mge.py
8 changes: 4 additions & 4 deletions .github/workflows/profile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ jobs:
pip install nautilus-sampler==1.0.5
pip install numba

- name: Run likelihood/ scripts
- name: Run likelihood_runtime/ scripts
if: ${{ inputs.sections == '' || contains(inputs.sections, 'likelihood') }}
working-directory: autolens_profiling
continue-on-error: true
Expand All @@ -102,8 +102,8 @@ jobs:
PYTHONPATH: ${{ github.workspace }}/PyAutoConf:${{ github.workspace }}/PyAutoFit:${{ github.workspace }}/PyAutoArray:${{ github.workspace }}/PyAutoGalaxy:${{ github.workspace }}/PyAutoLens
run: |
set +e # don't abort the whole step on one script's failure
for script in likelihood/imaging/*.py likelihood/interferometer/*.py \
likelihood/point_source/*.py likelihood/datacube/delaunay.py; do
for script in likelihood_runtime/imaging/*.py likelihood_runtime/interferometer/*.py \
likelihood_runtime/point_source/*.py likelihood_runtime/datacube/delaunay.py; do
echo "::group::$script"
python "$script" || echo "::warning::$script failed — see log; dashboard cell will show ERR"
echo "::endgroup::"
Expand Down Expand Up @@ -163,7 +163,7 @@ jobs:
# gitignored; future hardware-tier work may flip a subset to
# tracked, in which case this `add -f` becomes redundant but
# harmless.
git add -f results/ likelihood/README.md likelihood/*/README.md \
git add -f results/ likelihood_runtime/README.md likelihood_breakdown/README.md \
simulators/README.md searches/README.md \
searches/nautilus/README.md README.md
git commit -m "chore: refresh profile artifacts + dashboard tables [skip ci]
Expand Down
10 changes: 4 additions & 6 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,10 @@ dataset/datacube/sim_*/
# that's purely an auto-cache.
dataset/**/lensed_source.fits

# Profiling result artifacts — written by scripts under likelihood/, simulators/, searches/.
# Each run produces fresh versioned JSON+PNG; Phase 4's dashboard will explicitly select
# which artifacts to commit. Until then, results stay local.
# Retired legacy results section (pre likelihood_runtime/breakdown split);
# nothing writes here since the phase-2 output retarget. Kept ignored so old
# local checkouts don't surface stale artifacts as untracked.
results/likelihood/
results/simulators/
results/searches/

# Latent profiling sweep outputs — regenerated by latent/sweep.py, not committed.
# Retired legacy latent output home (latent now writes results/latent/, in-repo).
latent/results/
47 changes: 47 additions & 0 deletions _profile_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,3 +257,50 @@ def auto_simulate_if_missing(
],
check=True,
)


def check_pinned(got, expected, *, label: str, rtol: float = 1e-4):
"""Compare a computed likelihood/evidence against its pinned baseline.

Profiling runs **record and flag** drift; they never adjudicate library
correctness (that is autolens_workspace_test's remit — see
``results/notes/design_lock_in.md``). Returns ``None`` when ``got`` is
within ``rtol`` of ``expected``; otherwise prints a loud warning and
returns a drift record for the result JSON, which PyAutoHeart's vitals
scan picks up. Never raises — a changed computation must not kill a
profiling job (the timing numbers are still data; the flag marks them
non-comparable to the pinned baseline).
"""
got_f = float(got)
rel = abs(got_f - expected) / max(abs(expected), 1e-300)
if rel <= rtol:
return None
print(
f" WARNING: PINNED-VALUE DRIFT [{label}] — got {got_f!r}, "
f"pinned {expected!r} (rel diff {rel:.3e} > rtol {rtol:g}). "
f"Timings from this run are NOT comparable to the pinned baseline; "
f"file a bug / check autolens_workspace_test before trusting trends."
)
return {
"label": label,
"expected": expected,
"got": got_f,
"rel_diff": rel,
"rtol": rtol,
}


def record_pinned_check(json_path, expected, drift_records) -> None:
"""Merge the pinned-value check outcome into an already-written result JSON.

Adds ``pinned_expected`` (the baseline value, or ``None`` when the
instrument has no pin) and ``pinned_drift`` (list of drift records —
empty means every compared value matched). The guard blocks run after
the summary JSON is written, so this rewrites the file in place.
"""
import json

data = json.loads(json_path.read_text())
data["pinned_expected"] = expected
data["pinned_drift"] = drift_records
json_path.write_text(json.dumps(data, indent=2))
Binary file added dataset/imaging/euclid/data.fits
Binary file not shown.
Binary file added dataset/imaging/euclid/noise_map.fits
Binary file not shown.
28 changes: 28 additions & 0 deletions dataset/imaging/euclid/positions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"type": "instance",
"class_path": "autoarray.structures.grids.irregular_2d.Grid2DIrregular",
"arguments": {
"values": {
"type": "ndarray",
"array": [
[
0.27109374999999997,
1.6729626159565016
],
[
-1.49921875,
0.1953067707493031
],
[
1.49921875,
-0.1953067707493031
],
[
-0.27109374999999997,
-1.6729626159565019
]
],
"dtype": "float64"
}
}
}
Binary file added dataset/imaging/euclid/psf.fits
Binary file not shown.
110 changes: 110 additions & 0 deletions dataset/imaging/euclid/tracer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
{
"type": "instance",
"class_path": "autolens.lens.tracer.Tracer",
"arguments": {
"galaxies": {
"type": "list",
"values": [
{
"type": "instance",
"class_path": "autogalaxy.galaxy.galaxy.Galaxy",
"arguments": {
"redshift": 0.5,
"label": null,
"bulge": {
"type": "instance",
"class_path": "autogalaxy.profiles.light.standard.sersic.Sersic",
"arguments": {
"centre": {
"type": "tuple",
"values": [
0.0,
0.0
]
},
"sersic_index": 3.0,
"intensity": 2.0,
"ell_comps": {
"type": "tuple",
"values": [
0.05263157894736841,
3.2227547345982974e-18
]
},
"effective_radius": 0.6
}
},
"mass": {
"type": "instance",
"class_path": "autogalaxy.profiles.mass.total.isothermal.Isothermal",
"arguments": {
"einstein_radius": 1.6,
"ell_comps": {
"type": "tuple",
"values": [
0.05263157894736841,
3.2227547345982974e-18
]
},
"centre": {
"type": "tuple",
"values": [
0.0,
0.0
]
}
}
},
"shear": {
"type": "instance",
"class_path": "autogalaxy.profiles.mass.sheets.external_shear.ExternalShear",
"arguments": {
"gamma_1": 0.05,
"gamma_2": 0.05
}
}
}
},
{
"type": "instance",
"class_path": "autogalaxy.galaxy.galaxy.Galaxy",
"arguments": {
"redshift": 1.0,
"label": null,
"bulge": {
"type": "instance",
"class_path": "autogalaxy.profiles.light.standard.sersic_core.SersicCore",
"arguments": {
"gamma": 0.25,
"centre": {
"type": "tuple",
"values": [
0.0,
0.0
]
},
"radius_break": 0.025,
"sersic_index": 1.0,
"intensity": 4.0,
"alpha": 3.0,
"ell_comps": {
"type": "tuple",
"values": [
0.0962250448649376,
-0.05555555555555551
]
},
"effective_radius": 0.1
}
}
}
}
]
},
"cosmology": {
"type": "instance",
"class_path": "autogalaxy.cosmology.model.Planck15",
"arguments": {}
}
}
}
55 changes: 55 additions & 0 deletions hpc/batch_gpu/submit_probe_delaunay_a100
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#!/bin/bash -l
#
# Probe-only sweep — DELAUNAY cells (10-30 min per XLA compile; scipy
# Delaunay via pure_callback bloats the graph, so probes are single-point
# per the vram/README.md methodology).
#
# Re-validates the vram/config.py batch-size table for the
# PreOptimizationTimes campaign (autolens_profiling#54). Each probe writes
# results/runtime/<class>/delaunay/vmap_probe_delaunay[_sparse].json
# and exits before any timing loop. See submit_probe_fast_a100 for the
# fast cells and vram/README.md "Probe-only submits" for the ingest step.

#SBATCH -J probe_delaunay_a100
#SBATCH --partition=gpu
#SBATCH --gres=gpu:1
#SBATCH --ntasks=1
#SBATCH --cpus-per-task=4
#SBATCH --mem=64gb
#SBATCH --time=8:00:00
#SBATCH -o output/output.%A.out
#SBATCH -e error/error.%A.err
#SBATCH --mail-type=END,FAIL
#SBATCH --mail-user=james.w.nightingale@durham.ac.uk

export AP_ROOT=/mnt/ral/jnightin/autolens_profiling
source $AP_ROOT/activate.sh

export JAX_PLATFORM_NAME=cuda
export JAX_PLATFORMS=cuda,cpu
export XLA_PYTHON_CLIENT_PREALLOCATE=false
export JAX_ENABLE_X64=True
export NUMBA_CACHE_DIR=/tmp/numba_cache
export MPLCONFIGDIR=/tmp/matplotlib

nvidia-smi
cd $AP_ROOT

run_probe () {
echo "=== probe: $1 --instrument $2 $3 ==="
date
python3 "$1" --instrument "$2" --vmap-probe $3 || echo "!!! probe FAILED: $1 $2 $3"
}

# Imaging delaunay — campaign instruments, dense + sparse.
for inst in ao jwst hst; do
run_probe likelihood_runtime/imaging/delaunay.py "$inst" ""
run_probe likelihood_runtime/imaging/delaunay.py "$inst" "--sparse"
done

# Interferometer delaunay — campaign anchor (alma_high) + the cheap sanity cell.
run_probe likelihood_runtime/interferometer/delaunay.py sma ""
run_probe likelihood_runtime/interferometer/delaunay.py alma_high ""

echo "Finished."
date
Loading
Loading