Scaffold your first analysis plugin

This tutorial gives you one safe first success with the PolyzyMD analysis scaffold. You will generate one default single-file plugin named solvent_shell, inspect the files the scaffold creates, and run the generated tests.

The scaffolded analysis is intentionally a placeholder. The goal here is not to design solvent-shell science yet. The goal is to learn where a new analysis lives, which public APIs it imports, and how to verify that the generated plugin starts from a working state.

Before you start

You need:

Use the throwaway plugin name solvent_shell exactly as written. If you keep working on a real contribution later, choose a name that describes your actual analysis.

Important

Do not commit the generated solvent_shell files unless you are intentionally turning this tutorial scaffold into a real plugin. For this tutorial, treat them as scratch files and remove them before committing unrelated documentation or code changes.

1. Check that the scaffold command is available

From the repository root, ask the CLI for the command help:

pixi run -e build polyzymd new-analysis --help

You should see help for polyzymd new-analysis, including the default files it creates and the generated-test command. If this command is not available, return to Set Up a Contributor Environment and make sure you are using the build pixi environment.

2. Generate the default scaffold

Before generating files, check whether the tutorial paths already exist:

git status --short src/polyzymd/analyses/solvent_shell.py tests/analyses/plugins/test_solvent_shell.py

If either path is already present, stop and inspect it before continuing. The scaffold may fail, or you may need to understand the scaffold’s --force option before replacing anything. Do not overwrite work you intend to keep.

Run the scaffold with the default options:

pixi run -e build polyzymd new-analysis solvent_shell

The command creates a default MDAnalysis-native, single-file plugin and matching tests.

3. Confirm the generated files

Confirm that the scaffold created exactly these two tutorial files:

src/polyzymd/analyses/solvent_shell.py
tests/analyses/plugins/test_solvent_shell.py

That is the expected outcome for this tutorial: one analysis module and one test module.

You can also check the same paths with Git:

git status --short src/polyzymd/analyses/solvent_shell.py tests/analyses/plugins/test_solvent_shell.py

Warning

These generated files are scratch content. Do not commit them unless you are intentionally continuing from this scaffold as a real solvent_shell plugin.

4. Inspect the generated plugin

Open src/polyzymd/analyses/solvent_shell.py and skim it from top to bottom. You do not need to edit anything yet.

Settings

Find the generated settings model. It should include placeholder options for the first working scaffold:

  • selection with default value "protein and name CA"

  • scale with default value 1.0

These settings are intentionally generic. In a real plugin, replace or extend them with options that describe your analysis.

Placeholder measurement

Find the small placeholder measurement function. It receives a loaded universe and frame-selection arguments, then computes a scaffold metric rather than a scientific solvent-shell measurement.

The generated metric is named solvent_shell_value.

Note

Treat the placeholder measurement as a wiring check. Replace it with domain-specific MDAnalysis logic before developing a scientific plugin.

MDAnalysis job and collector

Look for the MDAnalysis job wiring:

  • MDAAnalysisJob wraps the per-trajectory work.

  • Collector logic converts completed job output into a ReplicateArtifact.

  • The collector keeps raw trajectory handling out of later aggregation and comparison steps.

This is the scaffold’s main lesson: trajectory-native plugins should hand per-replicate results to PolyzyMD’s artifact lifecycle instead of inventing a separate cache format.

Analysis class

Find the SolventShellAnalysis class. It should define:

  • name = "solvent_shell"

  • a Settings class

  • build_mda_jobs()

  • build_mda_collector()

  • extract_metrics() when metric metadata needs customization

The generated extract_metrics() reads canonical condition-artifact payloads for the default artifact comparison contract.

Metrics and aggregation

The scaffold includes small private helpers that keep the generated example complete enough to test:

  • count selected frames for the placeholder calculation

  • validate JSON-compatible metrics

  • read default aggregate summaries

The generated plugin exposes the scalar metric through MetricValue, and the default aggregation path can combine replicate artifacts into condition-level results.

Public import boundaries

The most important breadcrumb is the import boundary. The generated plugin uses public contributor-facing imports such as:

  • polyzymd.analyses.base for the Analysis subclass and scalar MetricValue descriptors.

  • polyzymd.analyses.mda for MDAAnalysisJob, MDAnalysis job contexts, collectors, and artifact objects.

It should not import from polyzymd.analyses._framework. That package is an internal implementation detail behind the public facades described in How PolyzyMD analysis plugins work.

5. Inspect the generated tests

Open tests/analyses/plugins/test_solvent_shell.py next. The tests are part of the scaffold because a new plugin contribution should start with executable contract checks, not only a Python module.

Discovery and settings tests

Skim the first tests for discovery and settings behavior. They prove that:

  • the plugin can be discovered by the name solvent_shell

  • the discovered class subclasses Analysis

  • generated settings defaults and validation rules work

MDAnalysis job tests

Find the tests for build_mda_jobs(). They prove that the generated plugin can return an MDAAnalysisJob and that the placeholder measurement can run against small fake universe objects.

Collector and aggregation tests

Find the tests for collector and aggregation behavior. They prove that:

  • the generated collector returns a ReplicateArtifact

  • default aggregation can read replicate artifacts

  • aggregated output exposes scalar metrics for comparison

Why the tests use fakes

The tests use small fakes instead of real trajectories. That keeps the first success fast and reviewable.

The fakes are enough for this scaffold because the tutorial checks plugin wiring, artifact flow, and default aggregation behavior. Real analysis tests can add trajectory-backed cases later when the scientific implementation exists.

6. Run the generated tests

Run only the generated test file:

pixi run -e build pytest tests/analyses/plugins/test_solvent_shell.py -v

A successful run confirms that the scaffolded plugin is discoverable, can build its MDAnalysis job, can collect a replicate artifact, and can participate in the default aggregation path.

Your exact pytest timing may differ, but the important success state is that the generated test_solvent_shell.py tests pass.

7. Clean up the scratch scaffold

For this tutorial, solvent_shell is a throwaway name. Before you commit any real work, either continue developing it into an intentional plugin or remove the generated files.

If you are done with the tutorial, remove only these two files:

rm src/polyzymd/analyses/solvent_shell.py
rm tests/analyses/plugins/test_solvent_shell.py

Then confirm your checkout no longer contains the scratch scaffold:

git status --short src/polyzymd/analyses/solvent_shell.py tests/analyses/plugins/test_solvent_shell.py

These are the only files this tutorial asked you to create:

src/polyzymd/analyses/solvent_shell.py
tests/analyses/plugins/test_solvent_shell.py

The scaffold is valuable because it gives you a known-good starting point. A real contribution still needs domain-specific settings, trajectory logic, artifact payloads, metrics, plots if needed, and tests that match the scientific question.

Common mistakes

  • Running the command outside the pixi environment. Use pixi run -e build for every PolyzyMD scaffold and test command.

  • Starting from a real analysis name too early. Use solvent_shell as the throwaway learning name, then choose an intentional name for real work.

  • Importing from private framework modules. Contributor plugins should use polyzymd.analyses.base and polyzymd.analyses.mda, not polyzymd.analyses._framework.

  • Treating the placeholder metric as science. The generated atom-frame count is only a scaffold. Replace it before opening a scientific plugin PR.

  • Committing scratch scaffold files. If this was only a tutorial run, remove solvent_shell.py and test_solvent_shell.py before committing other work.