Building the docs¶
The site is built with Zensical from zensical.toml
at the repository root and the Markdown under docs/.
uv sync --group docs
uv run --group docs zensical serve # live reload at http://127.0.0.1:8000
uv run --group docs zensical build --clean --strict
--strict turns warnings into errors. A link to a page that does not exist, or
a ::: block naming a module that cannot be imported, fails the build rather
than publishing a hole. CI builds this way on every pull request, so a page that
only works locally will not merge.
How the pages are put together¶
There are two kinds of page here and no third.
Wrappers. README.md, CHANGELOG.md, CONTRIBUTING.md, AUTHORS.md and
LICENSE.txt live at the repository root, where GitHub and PyPI read them. The
pages under docs/ include them from there with a snippet line:
# panoptes-pipeline
[](https://github.com/panoptes/panoptes-pipeline/actions/workflows/tests.yml)
[](https://panoptes.github.io/panoptes-pipeline/)
[](https://codecov.io/gh/panoptes/panoptes-pipeline)
[](https://github.com/panoptes/panoptes-pipeline/blob/main/LICENSE.txt)
Differential photometry for [Project PANOPTES](https://www.projectpanoptes.org):
recovering exoplanet transits from DSLR wide-field images with a Bayer color
filter array.
## The idea
A wide field gives any target many candidate reference stars whose light lands
on the color filter array the same way the target's does. Those references
build an idealized star that behaves as the target would absent a transit, so
the difference is zero unless the target's flux genuinely changed.
Dividing a stamp by its own summed flux marginalizes brightness out and leaves
the spatial profile, which is what separates shape from brightness: match on
shape, difference the brightness.
The algorithm and the network are the same principle at two scales, and low unit
cost enables both — many stars per unit to calibrate the systematic, many units
at different longitudes to cover a transit longer than one night.
## Status
Under active rebuild on `main`, which is the only long-lived branch. The
published description, [Gee et al., *On-sky Demonstration of Precision
Photometry with Bayer Color Filter Arrays*](https://www.projectpanoptes.org),
is earlier research and a building block rather than a specification.
What is planned, in progress and done lives in [GitHub
issues](https://github.com/panoptes/panoptes-pipeline/issues), grouped into
milestones. The plan documents below carry the reasoning behind that work.
Start with the design documents:
- **`plans/algorithm-design.md`** — what the algorithm is, independent of any
implementation, and the proposed architecture. Its section 5 says which
supporting measurements are solid and which are provisional.
- `plans/conformance-audit.md` — defects in the existing implementation.
Historical context for the rebuild, not a task list.
- `plans/improvement-plan.md` — metrics, benchmark selection, fleet
heterogeneity, and the open decisions in its section 6.
`AGENTS.md` carries the same orientation for agent sessions; `CLAUDE.md`
and `GEMINI.md` are symlinks to it.
The API reference is published at
<https://panoptes.github.io/panoptes-pipeline/>, built from the docstrings.
`plans/` is deliberately not part of it: those are working documents, read here
where their status is obvious.
## Install and test
Everything goes through [`uv`](https://docs.astral.sh/uv/), against the
committed `uv.lock`:
```shell
uv sync # project + dev tooling, pinned
uv run pytest
That is the whole install. The pipeline runs against a local directory of FITS
files — no cloud project, no credentials. Standalone scripts under scripts/
declare their dependencies inline per PEP 723 and need no sync.
src/panoptes/pipeline/lightcurve/ holds the algorithm as pure array code —
no I/O, no cloud, no notebook — and is where new work belongs.
Source matching needs a local copy of the PANOPTES Input Catalog, pointed at by
params.catalog.catalog_filename. Parquet, ECSV or CSV, chosen by suffix; it
must carry picid, catalog_ra, catalog_dec and catalog_vmag.
Contributing¶
Contributions are welcome — this is a citizen-science project and the pipeline is being rebuilt in the open.
- Start from an issue. If there is not one for what you want to do, open
one first. Anything needing a decision rather than an implementation gets the
decisionlabel. - Branch from
main, which is the only long-lived branch, and merge back into it. Name the branch for what it is for:type/issue-NNN, as incleanup/issue-171orfix/issue-93-background. - Run the checks before opening a pull request:
- Update
CHANGELOG.mdin the same branch, under## Unreleased, for any change someone using the package could observe. A branch is not finished until its entry is written. - Precision claims need evidence. A change that lowers scatter while
lowering signal transfer has suppressed signal rather than removed noise, so
report both.
AGENTS.mdhas the full rules under "Measuring a change".
Questions are welcome on the PANOPTES forum.
Credits¶
The PANOPTES Team, developers@projectpanoptes.org, and the contributors to this repository.
License¶
MIT. See LICENSE.txt.
`pymdownx.snippets.base_path` is the repository root and `check_paths` is on, so
a snippet pointing at a file that has moved fails the build. Without that check
the page renders as nothing at all and publishes with a hole in it.
This is also why there is no `edit_uri` in the configuration. Nearly every page
is a one-line wrapper, so an edit link would open the wrapper rather than the
file the reader is actually looking at.
**API reference.** A page under `docs/api/` is a `:::` block naming a module,
and nothing else:
```markdown
# `panoptes.pipeline.lightcurve.core`
::: panoptes.pipeline.lightcurve.core
mkdocstrings reads the docstrings; there is no generated intermediate to
commit and no second description of the API to keep in step with the first. A
new module means a new page here and a line in the nav. Improving a docstring
improves the reference, which is the point.
handlers.python.paths = ["src"] points griffe at the working tree, so the
reference describes this checkout rather than whichever copy of the package
happens to be installed.
What is not published¶
plans/ is not in the nav, deliberately. Those are living documents full of
provisional measurements -- several say so in their own text -- and publishing
them would present working notes as documentation. They are read in the
repository, where their status is obvious.
Publishing¶
docs.yml builds the site on every pull request and uploads it as an artifact,
so a reviewer can download it. On main a second job deploys that artifact
through the GitHub Pages API. Nothing is force-pushed to a gh-pages branch,
and the job that runs branch code has no write permission of any kind.