Production & publication readiness: hardening, reproducibility, packaging, examples, docs, tests - #2
Merged
Conversation
Two release gates: - examples/template.yaml drifted from autosampler/templates.py:DEFAULT_TEMPLATE (the template comment was edited without regenerating the committed example), making tests/test_input_template.py fail. Regenerated from the single source. - env.yml pinned pydantic>=1.10 but the code requires Pydantic v2 (import would fail), and omitted shapely, a core dependency used by the Voronoi spawner/binner. Bumped pydantic>=2.0, added shapely>=2.0, and added the lightning/mlcolvar deep-CV backends so the documented `conda env create -f env.yml` can run the learned-CV tutorials. Suite: 96 passed. https://claude.ai/code/session_01MjnMX5xKm184y4sLXhq4pT
…backend) Checkpoint/resume (regressions from the delta-writing change): - paths.load_history() read only a single iter_*/history.pkl, which after delta writing holds just the entries since the previous checkpoint — so the autosampler-path lineage/path tool silently saw a truncated history. It now reconstructs the full history by merging all deltas up to the target checkpoint. - Checkpoint writes are now atomic (write .tmp, os.replace), mirroring run_task.py. A crash mid-write (e.g. an HPC walltime kill) can no longer truncate a delta and break the whole delta chain. The format_version marker is written last. - Resume tolerates a corrupt/truncated delta (skip + warn) instead of crashing all future resumes. Shared reconstruct_history() helper used by load() and paths. - Added tests/test_checkpoint_delta.py (round-trip, checkpoint-frequency gaps, corruption tolerance, atomicity, paths.load_history reconstruction). Execution (local backend): - A single walker raising (CUDA error, NaN blow-up, missing file) propagated through future.result() and crashed the entire iteration, discarding the other walkers and violating the list[bool] contract. The local backend now catches a walker's failure (in the worker and when collecting the result), logs it, and marks that walker unsuccessful — matching the scheduler path. Note: reviewed the MSM "least-counts = 1/count^2" report and confirmed it is NOT a bug — the per-frame value distributes the microstate-level 1/count weight across its frames, exactly like the MSM-guided path's base/size_per_frame. Left unchanged. Suite: 101 passed. https://claude.ai/code/session_01MjnMX5xKm184y4sLXhq4pT
…doc fixes
Packaging / release readiness:
- pyproject: add readme, license, [project.urls], keywords, real authors; bump
Development Status to Beta (was Alpha while versioned 2.0.0); single-source the
version from autosampler/__init__.py via [tool.setuptools.dynamic].
- Add CITATION.cff (GitHub "Cite this repository") with flagged TODOs for the
final author list, ORCIDs, affiliations, and DOI; add a "How to cite" section
to the README.
Examples / docs (zero-behavior, first-run experience):
- examples/AlaD/{config,config_voronoi}.yaml: replace the hardcoded developer path
/home/dm/Soft/GMX26/... with an instructional placeholder, and fix the silently
ignored `platform:` typo -> `platform_name:`. (OpenMM parses the GROMACS topology
and needs the force-field include dir to resolve amber99sb.ff.)
- docs/notebook_tutorial.md: fix stale blob/devel link -> blob/main.
- docs/configuration.md + template.yaml: note that adaptive_feature_type: phi_psi
is currently AIB9-specific and raises on other systems.
Suite: 101 passed.
https://claude.ai/code/session_01MjnMX5xKm184y4sLXhq4pT
…tor) tools/generate_review_pdf.py renders AutoSampler_Review.pdf — the consolidated code-review / publication-readiness assessment (verdict, strengths, items fixed during review, blockers, major correctness/reproducibility/packaging/docs gaps, minor nits, and a prioritised path to release). https://claude.ai/code/session_01MjnMX5xKm184y4sLXhq4pT
Learned-CV training was not reproducible from random_seed: - AdaptiveSpaceModel had no seed; SPIB hardcoded seed=42 and ignored the config seed entirely. Added a `seed` to AdaptiveSpaceModel (plumbed from config.random_seed via core._adaptive_model_kwargs), threaded it into train_spib, and reseed the torch RNG at the start of every fit() so a CV retrained at iteration N is reproducible regardless of intervening RNG draws (network init, DataLoader shuffling). - SeedManager now requests deterministic torch algorithm implementations (torch.use_deterministic_algorithms(warn_only=True)) and sets CUBLAS_WORKSPACE_CONFIG, in addition to the existing Python/NumPy/torch/cuDNN/ Lightning seeding. - Added tests/test_reproducibility.py (deterministic SeedManager; seed carried on the model; identical vampnet projection across two same-seed fits). Suite: 104 passed. https://claude.ai/code/session_01MjnMX5xKm184y4sLXhq4pT
The default OpenMM engine runs in-process, so a hung GPU/driver could stall the whole campaign forever (Batch 2 already handles walker *crashes*; this covers *hangs*). Added execution.walker_timeout (seconds, opt-in): the local backend now polls at the timeout cadence and, if any walker exceeds it, terminates the batch's worker processes and marks the remaining walkers unsuccessful instead of blocking indefinitely. Plumbed via make_backend; documented in the template. Added tests/test_execution.py::test_local_backend_walker_timeout (hanging-executor simulation; asserts the batch is reported failed and does not hang). Suite: 105 passed. https://claude.ai/code/session_01MjnMX5xKm184y4sLXhq4pT
- spawners/density.py: _weighted_choice used replace=False even when fewer than top_n entries had nonzero probability, raising "fewer non-zero entries in p than size" in target mode (target_closeness zeroes distant bins). Now switches to replace=True in that case, matching the MSM spawner. Added a regression test. - spaces/model.py: the deep-tica projection built its input tensor with no device while the model's params may be on CUDA, causing a device-mismatch RuntimeError. Now reads the device from the model parameters and moves the output to CPU, mirroring the spib branch. https://claude.ai/code/session_01MjnMX5xKm184y4sLXhq4pT
`import autosampler` previously required OpenMM because engines/__init__ eagerly
imported the OpenMM/GROMACS/Amber modules (openmm.py does `from openmm import *`
at top). Since OpenMM is most reliably installed from conda, a plain
`pip install autosampler` from PyPI would often fail to resolve.
- EngineFactory.register_lazy + lazy get(): engine backends are imported only
when first requested, with an actionable error if the optional dependency is
missing. engines/__init__ now registers lazily (no eager backend import); the
engine classes remain accessible via module __getattr__ for compatibility.
- pyproject: move openmm out of core dependencies into an `[openmm]` extra (added
to `all`); torch/MDAnalysis/deeptime remain pip-installable core deps.
- Verified: `import autosampler.core` no longer imports openmm; EngineFactory.get
("openmm") imports it on demand.
Suite: 107 passed.
https://claude.ai/code/session_01MjnMX5xKm184y4sLXhq4pT
- Cleaned the ~250 ruff findings across the previously-unlinted modules (core.py, config.py, engines/*, checkpoints/manager.py, paths.py, spaces/*, spawners/*): autofixed the cosmetic bulk (typing modernization, import order, whitespace), added `from e` to four bare re-raises in spaces/features.py, and added strict= to zip() calls. Per-file ruff ignores for the two intentional patterns (core.py's pre-import warnings.filterwarnings -> E402; the OpenMM engine's `from openmm import *` -> F403/F405). - CI now lints the WHOLE tree (`ruff check autosampler tests`) instead of a hand-picked subset, tests on Python 3.10/3.11/3.12 (was 3.10/3.11), installs shapely, and adds a docs-build job. - Added .github/workflows/release.yml: tag (v*) -> build sdist/wheel, twine check, publish to PyPI via Trusted Publishing (OIDC, no token). Added MANIFEST.in. Behaviour unchanged (cosmetic + lint only). Suite: 107 passed; whole-tree ruff clean. https://claude.ai/code/session_01MjnMX5xKm184y4sLXhq4pT
… index A new user's first run previously broke (the AlaD Quick Start needs an external GROMACS force field). This adds a genuinely self-contained, GPU-free hello-world under examples/alanine_dipeptide/: - structure.pdb: canonical 22-atom Ac-Ala-NMe (OpenMM test structure, MIT). - build_system.py: builds a vacuum Amber14 System from it (OpenMM only, no external force-field files) and serialises system.xml (regenerable). - system.py / project_phi_psi.py / config.yaml: fixed phi/psi CVs, density spawning, CPU platform, tiny walker/step counts. Verified end-to-end: `--check` passes and a 2-iteration run completes on CPU in ~2 s/iteration, producing trajectories, CVs, and checkpoints. Also adds examples/README.md indexing every example with what it demonstrates and what it requires (CPU vs GPU, external force fields), pointing new users to the alanine-dipeptide example first. https://claude.ai/code/session_01MjnMX5xKm184y4sLXhq4pT
… target, pbs) Adds worked AIB9 example configs (reusing the bundled aib9_system.xml — no new MD assets) for features that previously had no example: - config_spib.yaml — SPIB learned CV - config_deep_tica.yaml — deep-TICA learned CV - config_we.yaml — weighted-ensemble spawner - config_target.yaml — target-mode search toward a CV point - config_pbs.yaml — PBS/Torque HPC execution backend All eleven AIB9 configs validate against the schema; indexed in examples/README.md. https://claude.ai/code/session_01MjnMX5xKm184y4sLXhq4pT
…e helpers - Voronoi/LOF/FPS spawners: explore + target modes return top_n valid in-range indices (importorskip shapely/sklearn so they skip cleanly when absent). - autosampler.paths: frame_key, FrameRef round-trip, build_frame_records lineage links, map_global_frame bounds, history_records, nearest_record (incl. dim mismatch + empty-history errors). Adds 11 tests; full suite green. https://claude.ai/code/session_01MjnMX5xKm184y4sLXhq4pT
- mkdocs.yml: wire the mkdocstrings (python) plugin and add nav entries. - docs/api.md: mkdocstrings API reference for the public modules a user/referee calls (config, msm.estimator, msm.convergence, spaces.feature_selection, binning.adaptive, analysis.data/plots). Griffe analyses statically, so no heavy runtime deps are needed at build. - docs/references.md: primary literature for the methods (MSM/PCCA+, TICA, VAMP/ VAMPNets, SPIB, deep-TICA, TAE, weighted ensemble, MAB, deeptime/OpenMM/ MDAnalysis); cross-linked from cv_methods.md. - docs/cli.md: complete reference for all six console commands (incl. the previously-undocumented autosampler-init and autosampler-analyze), with real flags read from the *_cli modules. - configuration.md: document the previously-missing spawner-tuning keys (recent_density_window, lof_neighbors, voronoi_*, resolution_*, target) and the new execution.walker_timeout. - CI docs job installs the package (--no-deps) so mkdocstrings can resolve it. https://claude.ai/code/session_01MjnMX5xKm184y4sLXhq4pT
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A production- and publication-readiness pass over AutoSampler, acting on an independent code review. Fixes the release-gating blockers and works through the major correctness, reproducibility, packaging, CI, example, docs, and test gaps.
Suite: 95 → 118 tests passing · whole-tree ruff clean · all example configs validate · docs build verified.
Release-gating fixes
examples/template.yamlhad drifted from the module template.env.ymlpinnedpydantic1.x (code is Pydantic v2) and omittedshapely(a core dep).autosampler-path'sload_historyread a truncated (delta-only) history; now reconstructs the full history, writes atomically, and tolerates a corrupt delta. +tests.phi_psidocumented as AIB9-specific;CITATION.cffadded.Correctness & robustness
execution.walker_timeouthang guard.replace=Falsewith mostly-zero weights) and a deep-TICA device mismatch.Reproducibility
seed=42; torch RNG reseeded before everyfit);SeedManagerenables deterministic torch algorithms.Packaging (PyPI + conda)
import autosamplerno longer requires it, so the basepip installresolves; the engine imports on first use.MANIFEST.in.CI / quality
Examples, docs, tests
examples/README.mdindex.autosampler-init/-analyze), and the previously-missing config keys.pathslineage.Notes / follow-ups
coreorchestration tests; optionalextra="forbid"config strictness.CITATION.cff.🤖 Generated with Claude Code
https://claude.ai/code/session_01MjnMX5xKm184y4sLXhq4pT
Generated by Claude Code