Analysis plugin contribution checklist
Use this page to copy a review checklist into a GitHub issue or pull request body. The rendered documentation shows the instructions, while the checklist itself lives in a copy-pasteable template so contributors can check items in GitHub.
How to use this checklist
Replace PLUGIN_NAME with your plugin’s stable lowercase name, paste the
template into a GitHub issue or PR body, and check boxes in GitHub as you work.
Delete irrelevant items or mark them N/A when a lifecycle stage does not apply
to your plugin.
What this checklist covers
The template covers the expected contributor contract for analysis plugins: source placement, public imports, lifecycle hooks, MDAnalysis jobs, artifacts, aggregation, comparison, plotting, formatting, tests, user-facing documentation, and pre-PR commands.
Copy-paste checklist template
## Analysis plugin checklist
Plugin: `PLUGIN_NAME`
Use this checklist before opening or reviewing an analysis plugin pull request.
Delete items that do not apply, or mark them `N/A` with a short reason.
### Placement and shape
- [ ] The plugin lives under `src/polyzymd/analyses/` as either one readable
module or one package with a public `__init__.py`.
- [ ] The public plugin class subclasses `Analysis` and defines `name` and
`Settings`.
- [ ] Advanced helper files such as `_mda.py`, `_plotters.py`, `_models.py`, and
`_formatters.py` exist only when they have clear responsibilities.
- [ ] The plugin name is stable, lowercase, and matches CLI/config usage.
### Public imports
- [ ] Contributor-facing code imports lifecycle classes from
`polyzymd.analyses.base`.
- [ ] MDAnalysis job, artifact, sidecar, and artifact-store types come from
`polyzymd.analyses.mda`.
- [ ] Shared helpers come only from documented `polyzymd.analyses.shared`
utilities when they fit the task.
- [ ] The plugin does not import from `polyzymd.analyses._framework`; that
package is private behind the public facades.
- [ ] Heavy dependencies such as MDAnalysis and matplotlib are imported lazily
inside functions or methods that need them.
### Plugin contract
- [ ] `Settings` is a Pydantic model with defaults, field descriptions, and
validation for invalid values.
- [ ] Compute-stage plugins implement `build_mda_jobs()` and, when needed,
`build_mda_collector()`.
- [ ] Compare-only plugins explicitly set the appropriate lifecycle flags and do
not pretend to run trajectory work.
- [ ] Lifecycle methods use framework-provided context objects; they do not reload
YAML configuration on their own.
- [ ] MDAnalysis selections use project conventions such as `chainid A` for
protein, `chainid B` for substrate, and `chainid C` for polymer.
### MDAnalysis jobs
- [ ] Jobs are `MDAAnalysisJob` objects built from the public MDAnalysis layer.
- [ ] Function-adapter jobs respect `frames` and `start`/`stop`/`step` frame
selection kwargs.
- [ ] `AnalysisBase`-compatible jobs can be tested with small fake workers.
- [ ] Job metadata records enough provenance to explain selections, frame windows,
settings fingerprints, and relevant algorithm choices.
- [ ] Job results are converted to JSON-compatible values or sidecars before they
become artifacts.
### Artifacts and sidecars
- [ ] Collectors return `ReplicateArtifact` objects.
- [ ] Scalar values intended for default aggregation are finite numbers under
`payload["metrics"]`.
- [ ] Payloads remain compact and JSON-compatible.
- [ ] Large arrays, event tables, and frame-by-frame data are stored as registered
sidecars, not inline JSON.
- [ ] Sidecar paths are store-relative and are loaded through `ArtifactStore`
validation helpers.
- [ ] Raw MDAnalysis `Results` objects are never serialized.
### Aggregation and comparison
- [ ] Simple scalar artifact plugins rely on default aggregation to build a
`ConditionArtifact` when that contract is sufficient.
- [ ] Custom aggregation is used only when condition-level data needs a custom
schema or sidecar handling.
- [ ] `extract_metrics()` implementations read canonical `ConditionArtifact`
payloads and return `MetricValue` objects for default scalar comparison.
- [ ] Custom `compare()` methods return a saveable comparison result or artifact
and have tests for missing or incomplete conditions.
- [ ] Metric names, units, and higher/lower-is-better interpretation are explicit
where scientific comparison depends on them.
### Plotting and formatting
- [ ] `plot()` reads cached artifacts and registered sidecars only.
- [ ] Plotting does not load trajectories, run MDAnalysis jobs, or recompute
analysis results.
- [ ] Plot helpers write figures under the provided `PlotContext.output_dir`.
- [ ] `format()` renders existing comparison output; it does not compute new
scientific quantities.
- [ ] Plot and format behavior is covered by focused tests or intentionally left
absent for plugins that do not provide them.
### Tests
- [ ] Discovery test covers `list_analyses()` and `get_analysis()`.
- [ ] Settings tests cover defaults and invalid values.
- [ ] `build_mda_jobs()` tests use fakes or mocks and verify frame selection and
settings wiring.
- [ ] Collector tests assert that a `ReplicateArtifact` is returned with expected
payload, provenance, warnings, and sidecars.
- [ ] Aggregation or metric-extraction tests cover condition-level outputs.
- [ ] Comparison tests cover the default metric path or custom comparison path.
- [ ] Plot tests are artifact-only and do not require trajectory data.
- [ ] Sidecar tests validate registered sidecars through `ArtifactStore` when the
plugin writes arrays or tables.
- [ ] Tests that require real trajectory data are marked `@pytest.mark.slow`.
### Documentation and user-facing surfaces
- [ ] New plugins, settings, public APIs, CLI options, or user workflows update
the relevant docs, reference pages, CLI help, and configuration examples.
- [ ] New analysis settings are documented where users look up
`comparison.yaml` plugin options.
- [ ] Stable versus experimental behavior is labeled clearly when the feature is
not yet a settled default workflow.
### Commands before PR
Run the focused checks for your plugin and the project-level checks relevant to
analysis contributions:
```bash
PLUGIN_NAME=my_plugin
pixi run -e build pytest "tests/analyses/plugins/test_${PLUGIN_NAME}.py" -v
pixi run -e build pytest tests/analyses/ -v
pixi run -e build ruff check src/ "tests/analyses/plugins/test_${PLUGIN_NAME}.py"
pixi run -e build black src/ "tests/analyses/plugins/test_${PLUGIN_NAME}.py" --check
pixi run -e build make -C docs clean html
```
If you changed documentation, the clean Sphinx build must complete with zero
warnings before review.