Fix directory resolution in layout, and generate the session READMEs

layout.path() treated every argument as a filename, so asking it for a
directory - layout.path('final'), which the rendering scripts do - built
a path to a file called 'final' INSIDE final/ and created an empty
final/final along the way. Directory names now resolve to the directory
itself.

Three scripts also held path literals split across two lines with
implicit string concatenation, where the rewrite had replaced only the
first fragment and left a dangling continuation. verify_core.py,
mo_gccheck.py and mo_mpc.py are corrected; all 52 files now compile
without warnings.

subdir_readmes.py writes a short README into each session subdirectory
saying what it holds, where it came from, and whether it is safe to
delete. Those three facts are what someone opening a folder cold needs,
and they belong with the data rather than in this repo.

Re-verified after the fix: closeup.py and triptych.py run end to end
against the reorganised session and leave no stray directories behind.
This commit is contained in:
laurence 2026-07-21 15:33:52 +01:00
parent 5286a2e81b
commit f2d173f047
2 changed files with 124 additions and 0 deletions

View file

@ -0,0 +1,117 @@
"""Drop a short README in each session subdirectory.
Each one says what the directory holds, where it came from, and whether it is
safe to delete - the three things someone opening a folder cold needs.
"""
import os
ROOT = r"C:\Users\lhorrocks-barlow\Downloads\NGC5128\20260721"
READMES = {
"raw": """# raw/
Exactly what iTelescope delivered, untouched.
- `calibrated-*.zip` - the calibrated frames, as archives (FITS and TIFF)
- `raw-*.zip` - the uncalibrated frames, kept for completeness
- `jpeg-*.jpg` - iTelescope's own preview of each sub
**Do not edit anything here.** This is the archive copy; everything else in the
session can be rebuilt from it. `calibrated/` holds these same frames
uncompressed.
""",
"calibrated": """# calibrated/
The 24 calibrated subs, uncompressed from `raw/`. 12 Luminance, 4 Red,
4 Green, 4 Blue, all 300 s, all BIN2.
`.fit` are the data the processing uses; `.tif` are the same frames in a form
other software can open.
Already bias, dark and flat corrected by iTelescope before delivery
(`CALSTAT = 'BDF'` in the headers) - that cannot be undone here.
Safe to delete: regenerable from `raw/` by re-running `unzip.py`.
""",
"stacks": """# stacks/
The combined frames, at two levels of processing.
- `masters/` - the real stacks: registered, transparency-normalised, combined
with outlier rejection, and plate-solved. Everything downstream uses these.
- `original/` - the baseline: aligned and averaged, and **nothing else**. No
rejection, no sky subtraction, no normalisation. Satellite trails and the
moon's gradient are still in it, deliberately. Useful when a processed result
looks odd and you need to know whether the data or the processing caused it.
Both sets are pixel-aligned to the same reference frame, so they can be
compared or subtracted directly.
""",
"final": """# final/
**The finished images.** Four renderings of the same data, differing only in
how much processing was applied, plus a side-by-side comparison.
| File | What it is |
|---|---|
| `NGC5128-final-1-stacked` | stacked and stretched, nothing else |
| `NGC5128-final-2-processed` | conventional processing |
| `NGC5128-final-3-best` | corrected by what the analyses established |
| `NGC5128-final-4-closeup` | image 3 cropped to the galaxy, 23.4' square |
| `NGC5128-final-comparison.jpg` | all three side by side, with a 1:1 crop |
Each comes as `.png` (viewing), `.tif` (16-bit, for editing or printing) and
`-preview.jpg` (small).
The reasoning behind each is in `../METHODS.md`.
""",
"renderings": """# renderings/
Finished images that are not the four deliverables in `final/`.
- `NGC5128-LRGB.*` - the first full composite
- `NGC5128-LRGB-hdr.*` - the same with the core recovered by a second tone curve
- `NGC5128-img-deconvolved.*` - sharpened luminance
- `NGC5128-img-annotated.jpg` - coordinate grid and catalogued objects, placed
by the plate solution. Includes SN 1986G and SN 2016adj, both real supernovae
in this galaxy.
- `NGC5128-img-starless.png` / `NGC5128-img-stars.png` - the field split into
nebulosity and stars
- `NGC5128-img-core-print.jpg` - a print crop
Kept because they show intermediate stages and because some are useful in their
own right. `final/` is what to look at first.
""",
"science": """# science/
The measurements, as opposed to the pictures.
- `notes/` - **start here.** Three write-ups covering the globular cluster
survey, the surface photometry, and the transient and moving-object search.
Each states its method, its numbers, and its limits.
- `figures/` - the plots those notes refer to
- `catalogues/` - the measured tables (CSV): cluster candidates, isophote
profiles, flagged objects
- `data/` - the galaxy model, star and dust masks, extinction map, and a plain
text summary of derived quantities
Headline results are summarised in `../METHODS.md`; the notes carry the detail,
the caveats and the things that did not work.
""",
"intermediates": """# intermediates/
Caches and scratch files: downloaded star catalogues, detection lists, partial
results, run logs.
**Safe to delete.** Everything here is regenerated by re-running the scripts,
at the cost of re-querying Gaia, SIMBAD and VizieR. Kept so a re-run is fast
and so the exact catalogue data used is preserved rather than silently changing
under a later query.
""",
}
for name, text in READMES.items():
path = os.path.join(ROOT, name, "README.md")
os.makedirs(os.path.dirname(path), exist_ok=True)
open(path, "w", encoding="utf-8").write(text)
print(f"wrote {name}/README.md")