Imported from ivolabbe/mophongo (
AGENTS.md). Install upstream withnpx skills add ivolabbe/mophongo. Copyright stays with the author.
AGENTS.md - Coding Agent Instructions
This file is the single source of agent-facing instructions for Mophongo.
CLAUDE.md should be a symlink to this file.
Mophongo is a scientific Python package for PSF modeling, image registration, image simulation, and template-fitting photometry.
Development Commands
- Install dependencies:
poetry install - Alternative editable install:
pip install -e . - Run tests:
poetry run pytest - Run one test file:
poetry run pytest tests/test_<module>.py - Run one test:
poetry run pytest tests/test_<module>.py::test_function - Add dependencies only with Poetry, for example
poetry add <package> - Never edit
poetry.lockdirectly
Required Reading
Before writing or modifying code:
- Read GUIDE.md.
- Check STATUS.md for recent/current implementation context.
- Check TODO.md for open future work that may overlap the task.
Documentation Tracking
STATUS.md and TODO.md must be kept current. Every implementation turn
that changes behavior, layout, validation state, or future work should update
one or both files before finishing.
- Update
STATUS.mdwhen a feature, fix, validation run, or behavior/layout change is completed. - Update the
Current Worksection inSTATUS.mdwhile actively working on a multi-step change. - Update
TODO.mdwhen future desired features, checks, or investigations are added, completed, or clarified.
Project Layout
src/mophongo/- main package source codetests/- pytest-based test suiteexamples/- notebooks and runnable examplesdata/- test data and PSF filesdocs/- longer-form documentationlegacy/- legacy IDL/Pro reference codescratch/- exploratory scripts and one-off diagnostics
Implementation Workflow
- Add reusable code inside
src/mophongo/. - Keep scratch code in
scratch/only when it is exploratory or not reusable. - Avoid project-wide refactors unless specifically requested.
- Prefer existing package patterns and helper APIs over new ad hoc utilities.
- Use type hints and Google-style docstrings for new public functions/classes.
- Prefer pure functions where practical.
- Use
loggingfor runtime reporting. Do not add newprintcalls in package code unless preserving an existing interface. - Use pytest tests for added functionality.
- Put tests under
tests/. - Use temporary files/mocks for FITS I/O in tests when possible.
- Avoid network access or external resources in tests.
Architecture Overview
The main photometry flow is:
- Template extraction from a high-resolution detection image
(
templates.py). - PSF handling and spatial PSF lookup (
psf.py,psf_map.py). - PSF matching / convolution kernels (
utils.py,psf.py). - Sparse or scene-based fitting (
fit.py,scene.py,scene_fitter.py). - Pipeline orchestration and diagnostics (
pipeline.py).
Key components:
TemplateandTemplates: source cutout geometry, extraction, convolution, block projection, and template collections.SparseFitter,Scene, andSceneFitter: flux solving, scene grouping, optional astrometric shift blocks, and error estimates.FitConfig: fitting configuration.PSF,DrizzlePSF, andPSFRegionMap: analytic/array PSFs, drizzled JWST PSFs, and spatially varying PSF maps.Catalog: detection, segmentation maps, source catalogs, and catalog-owned segmentation helpers.Pipeline: main entry point for image/template fitting.MockMosaic: synthetic JWST-like mosaic generation.PSFFactory(psf_factory.py): telescope-backend registry and MJD-aware PSF generation.saturate.py: saturated-pixel repair (see Module Boundaries).repair.py: standalone saturation-repair entry point (mophongo-repairconsole script /python -m mophongo.repair).cli.py: command-line access to a finished run's products (mophongoconsole script:psf,stamps,diag,info,run,config).template_schemes.py: self-contained ports of the alternative template build schemes (wren fork, IDL classic) selected byFitConfig.extend_mode.astrometry.py,jwst_psf.py: astrometric corrections and JWST PSF utilities. Deblending usesphotutils.segmentation.deblend_sources, re-exported frommophongo/__init__.py.astrom_robust.py: robust weighting of a scene's astrometric anchors, selected byFitConfig.astrom_robust.
Module Boundaries
Mophongo is being prepared for public release. Keep modules reusable and separable. Each module should own its own data type and interact with other modules through numpy arrays, astropy objects, Tables, dicts, or small dataclasses.
Guiding rules:
saturate.pyis pure image-pixel repair. Inputs aresci,wht,wcs, and aDrizzlePSF. Outputs are a repaired image and flat fit table. It must not import segmentation maps, catalogs, or photometry concepts.psf.py/DrizzlePSFown drizzling, ePSFs, PSF profiles, and kernel diagnostics. Do not add wrappers that import fitting, saturation, or catalog domains.catalog.pyowns segmentation maps, source catalogs, and helpers that act on segmentation/catalog state. It can consume flat tables from preprocessing, but preprocessing must not import catalog.fit.py,templates.py,scene.py,scene_fitter.py, andpipeline.pyown the photometry pipeline and should not reach into preprocessing utilities.verification.pyowns reusable validation and diagnostic helpers. Keep survey/instrument-specific orchestration in examples or scripts.repair.pyis an entry-point orchestrator (likepipeline.py): it may import bothsaturateandcatalogto chain image repair and catalog flagging, but must hold no algorithmic logic of its own.cli.pyis an entry-point orchestrator as well: argument parsing, path resolution, and FITS/PNG writing over existingPipeline/PSFRegionMapmethods. Any computation a subcommand needs belongs in the module that owns it, not here.template_schemes.pyholds the alternative build schemes and must stay a leaf: pure numpy in,(composite, info)dict out, no imports fromtemplates.py,fit.py,catalog.pyorpipeline.py. Dispatch lives inTemplates.extract_templatesandPipeline._extend_scheme_kwargsso a scheme can be adapted or removed as a unit.astrom_robust.pyis a leaf for the same reason: it takes an anchor table (implied shifts, information, basis rows) as plain arrays and returns weights, with no imports fromscene.py,fit.pyortemplates.py. The measurement that produces the table lives inscene.py, which is where the template geometry is. Keeping the statistics separable is what lets the non-joint path inastrometry.pyreuse them.
Concrete rule: if module A needs information that module B owns, prefer passing the result through a flat structure B already exposes rather than importing A into B.
Implementation Details To Preserve
- Templates maintain original-image and cutout coordinate systems. Be careful with slices and origin conventions.
- Multi-resolution fitting uses WCS-derived bin factors. When upsampling a
lower-resolution image, science pixels are flux-conserving block-replicated
and inverse variance is copied then multiplied by
factor**2. - Pipeline-facing PSF matching uses unit-sum PSF shapes. Finite PSF stamp sums are filter-level throughput metadata for total-flux reporting; do not silently renormalize native PSF stamps and lose that information.
Pipeline.run()writes raw fitted template amplitudes asflux_<i>and throughput-corrected totals asflux_<i>_total.- Use standard PSF diagnostic helpers, especially
PSF.optimize_matching_kernel_regularization(..., diagnostic_path=...), instead of reinventing PSF diagnostic figures.
Testing And Verification
- Run focused tests for the modules you touched.
- For shared pipeline behavior, run at least the relevant
tests/test_pipeline.pytests. - For PR preparation or large changes, run
poetry run pytest. - When adding diagnostics, make outputs reproducible and write tests for the data products or helper behavior, not just the image file existence.
- Long-form reports (
.tex/.mdcompiled to PDF): plain academic prose, no AI narrative tics; run a humanizer pass before finalizing/compiling.
Branches And Commits
- Do not create a branch, commit, push, or open a PR unless the user asked for it in this session. Work in the tree the user left you in.
- Ask before switching branches or moving work onto a new one, even when the current branch looks wrong for the change.
- The working tree often carries unrelated work in progress. Commit only the files belonging to the task you were given, and say which files you left uncommitted.
Pull Request Preparation
Before preparing a PR:
- Ensure relevant tests pass; use full
poetry run pytestwhen feasible. - Update
STATUS.mdandTODO.mdas appropriate. - Verify changes are scoped to relevant modules.
- Do not refactor unrelated modules unless requested.
PR body should include:
- Summary of logic
- Modules modified or added
- Validation/tests run
- Links or references to relevant status/design notes