The scripts that processed the NGC 5128 session of 2026-07-21 previously lived inside the data directory and addressed it with absolute paths. Code and data are now separated: the code lives here, and a session is located at runtime through the ASTRO_SESSION environment variable. layout.py is what makes that work. It maps a FILENAME to the subdirectory that file belongs in, using the same rules the session directories are organised with, so a script can go on asking for 'master-Red.fit' or '_stars.npz' without any call site knowing the directory structure. Anything unrecognised resolves to the session root, which is visible and correctable rather than silently wrong. restructure.py reorganises a flat session directory into that layout. It is idempotent and dry-run by default. The 50 session scripts are kept as they were run rather than tidied into a library. They were written in sequence as the work went along, several of them by parallel agents, and they show it - but they are the honest provenance of a published set of results, and the productionised pipeline should be able to reproduce those results exactly. Verified before committing: all 51 files compile without warnings, and verify_core.py, closeup.py and triptych.py were run end to end against the reorganised session, correctly finding inputs across calibrated/, stacks/masters/ and final/ and writing outputs back to the right places.
62 lines
2.4 KiB
Python
62 lines
2.4 KiB
Python
"""Side-by-side of the three renderings, full field and a matched core crop.
|
|
|
|
Same pixels in all three panels, so any difference is processing and nothing
|
|
else.
|
|
"""
|
|
import os
|
|
|
|
import matplotlib
|
|
matplotlib.use("Agg")
|
|
import matplotlib.pyplot as plt
|
|
import numpy as np
|
|
from PIL import Image
|
|
|
|
import layout
|
|
|
|
OUT = layout.SESSION
|
|
# The finished renderings live in their own directory: they are the
|
|
# deliverables, and keeping them apart from the masters, the
|
|
# intermediates and the analysis figures makes it obvious which
|
|
# files are meant to be looked at.
|
|
FINAL = layout.path("final")
|
|
PANELS = [
|
|
("NGC5128-final-1-stacked.png", "1. Stacked + standard stretch",
|
|
"align, average, stretch - nothing else"),
|
|
("NGC5128-final-2-processed.png", "2. Conventionally processed",
|
|
"gradient removal, colour balance, denoise"),
|
|
("NGC5128-final-3-best.png", "3. Science-informed",
|
|
"halo-preserving background, solar-analogue colour,\n"
|
|
"core recovered, star-protected deconvolution"),
|
|
]
|
|
CROP = (1950, 1200, 2850, 1875) # the dust lane, at full resolution
|
|
|
|
fig, axes = plt.subplots(2, 3, figsize=(21, 11.5),
|
|
gridspec_kw=dict(height_ratios=[1.35, 1]))
|
|
fig.patch.set_facecolor("#111111")
|
|
|
|
for col, (fname, title, sub) in enumerate(PANELS):
|
|
im = Image.open(layout.path(fname))
|
|
wide = im.copy()
|
|
wide.thumbnail((1500, 1500), Image.LANCZOS)
|
|
axes[0, col].imshow(np.asarray(wide))
|
|
axes[0, col].set_title(title, color="white", fontsize=15, pad=10)
|
|
axes[0, col].text(0.5, -0.055, sub, color="#9fb8d0", fontsize=10,
|
|
ha="center", va="top", linespacing=1.4, wrap=True,
|
|
transform=axes[0, col].transAxes)
|
|
axes[1, col].imshow(np.asarray(im.crop(CROP)))
|
|
axes[1, col].set_title("core, 1:1", color="#9fb8d0", fontsize=11, pad=6)
|
|
for row in (0, 1):
|
|
axes[row, col].set_xticks([])
|
|
axes[row, col].set_yticks([])
|
|
for s in axes[row, col].spines.values():
|
|
s.set_color("#333333")
|
|
|
|
fig.suptitle("NGC 5128 (Centaurus A) - iTelescope T32, 2026-07-21 - "
|
|
"L 12x300s, RGB 4x300s each - the same data, three treatments",
|
|
color="white", fontsize=17, y=0.975)
|
|
fig.tight_layout(rect=[0, 0.01, 1, 0.955])
|
|
fig.subplots_adjust(hspace=0.16)
|
|
path = layout.path("NGC5128-final-comparison.jpg")
|
|
fig.savefig(path, dpi=100, facecolor=fig.get_facecolor(),
|
|
pil_kwargs={"quality": 92})
|
|
print("wrote", path)
|