fastmdxplora 2.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. fastmdxplora-2.0.0/.github/workflows/publish.yml +83 -0
  2. fastmdxplora-2.0.0/.github/workflows/tests.yml +49 -0
  3. fastmdxplora-2.0.0/.gitignore +50 -0
  4. fastmdxplora-2.0.0/.readthedocs.yaml +19 -0
  5. fastmdxplora-2.0.0/CHANGELOG.md +100 -0
  6. fastmdxplora-2.0.0/CITATION.cff +35 -0
  7. fastmdxplora-2.0.0/CODE_OF_CONDUCT.md +43 -0
  8. fastmdxplora-2.0.0/CONTRIBUTING.md +67 -0
  9. fastmdxplora-2.0.0/LICENSE +21 -0
  10. fastmdxplora-2.0.0/PKG-INFO +438 -0
  11. fastmdxplora-2.0.0/README.md +380 -0
  12. fastmdxplora-2.0.0/STRUCTURE.md +110 -0
  13. fastmdxplora-2.0.0/assets/README.md +6 -0
  14. fastmdxplora-2.0.0/docs/conf.py +37 -0
  15. fastmdxplora-2.0.0/docs/index.md +23 -0
  16. fastmdxplora-2.0.0/docs/usage_examples.md +509 -0
  17. fastmdxplora-2.0.0/environment.yml +34 -0
  18. fastmdxplora-2.0.0/examples/README.md +14 -0
  19. fastmdxplora-2.0.0/pyproject.toml +120 -0
  20. fastmdxplora-2.0.0/pytest.ini +6 -0
  21. fastmdxplora-2.0.0/recipes/fastmdx-alias/meta.yaml +52 -0
  22. fastmdxplora-2.0.0/recipes/fastmdxplora/meta.yaml +87 -0
  23. fastmdxplora-2.0.0/requirements.txt +2 -0
  24. fastmdxplora-2.0.0/scripts/README.md +3 -0
  25. fastmdxplora-2.0.0/scripts/make_benzene.py +91 -0
  26. fastmdxplora-2.0.0/setup.cfg +4 -0
  27. fastmdxplora-2.0.0/shim-package/README.md +36 -0
  28. fastmdxplora-2.0.0/shim-package/pyproject.toml +35 -0
  29. fastmdxplora-2.0.0/shim-package/src/fastmdx/__init__.py +34 -0
  30. fastmdxplora-2.0.0/src/fastmdxplora/__init__.py +78 -0
  31. fastmdxplora-2.0.0/src/fastmdxplora/_version.py +24 -0
  32. fastmdxplora-2.0.0/src/fastmdxplora/analysis/__init__.py +104 -0
  33. fastmdxplora-2.0.0/src/fastmdxplora/analysis/analyze.py +181 -0
  34. fastmdxplora-2.0.0/src/fastmdxplora/analysis/base.py +394 -0
  35. fastmdxplora-2.0.0/src/fastmdxplora/analysis/cluster.py +339 -0
  36. fastmdxplora-2.0.0/src/fastmdxplora/analysis/contacts.py +178 -0
  37. fastmdxplora-2.0.0/src/fastmdxplora/analysis/dihedrals.py +183 -0
  38. fastmdxplora-2.0.0/src/fastmdxplora/analysis/dimred.py +276 -0
  39. fastmdxplora-2.0.0/src/fastmdxplora/analysis/hbonds.py +191 -0
  40. fastmdxplora-2.0.0/src/fastmdxplora/analysis/ligand_rmsd.py +165 -0
  41. fastmdxplora-2.0.0/src/fastmdxplora/analysis/ligand_rmsf.py +124 -0
  42. fastmdxplora-2.0.0/src/fastmdxplora/analysis/loading.py +226 -0
  43. fastmdxplora-2.0.0/src/fastmdxplora/analysis/orchestrator.py +417 -0
  44. fastmdxplora-2.0.0/src/fastmdxplora/analysis/pl_hbonds.py +147 -0
  45. fastmdxplora-2.0.0/src/fastmdxplora/analysis/plotting.py +147 -0
  46. fastmdxplora-2.0.0/src/fastmdxplora/analysis/qvalue.py +176 -0
  47. fastmdxplora-2.0.0/src/fastmdxplora/analysis/rg.py +145 -0
  48. fastmdxplora-2.0.0/src/fastmdxplora/analysis/rmsd.py +171 -0
  49. fastmdxplora-2.0.0/src/fastmdxplora/analysis/rmsf.py +149 -0
  50. fastmdxplora-2.0.0/src/fastmdxplora/analysis/sasa.py +186 -0
  51. fastmdxplora-2.0.0/src/fastmdxplora/analysis/ss.py +172 -0
  52. fastmdxplora-2.0.0/src/fastmdxplora/batch/__init__.py +38 -0
  53. fastmdxplora-2.0.0/src/fastmdxplora/batch/compare.py +452 -0
  54. fastmdxplora-2.0.0/src/fastmdxplora/batch/explorer.py +442 -0
  55. fastmdxplora-2.0.0/src/fastmdxplora/batch/sweep.py +336 -0
  56. fastmdxplora-2.0.0/src/fastmdxplora/cli/__init__.py +5 -0
  57. fastmdxplora-2.0.0/src/fastmdxplora/cli/main.py +716 -0
  58. fastmdxplora-2.0.0/src/fastmdxplora/config/__init__.py +40 -0
  59. fastmdxplora-2.0.0/src/fastmdxplora/config/generate.py +293 -0
  60. fastmdxplora-2.0.0/src/fastmdxplora/config/loader.py +286 -0
  61. fastmdxplora-2.0.0/src/fastmdxplora/config/schema.py +412 -0
  62. fastmdxplora-2.0.0/src/fastmdxplora/datasets/__init__.py +9 -0
  63. fastmdxplora-2.0.0/src/fastmdxplora/datasets/trp_cage.py +33 -0
  64. fastmdxplora-2.0.0/src/fastmdxplora/orchestrator.py +634 -0
  65. fastmdxplora-2.0.0/src/fastmdxplora/report/__init__.py +18 -0
  66. fastmdxplora-2.0.0/src/fastmdxplora/report/bundle.py +68 -0
  67. fastmdxplora-2.0.0/src/fastmdxplora/report/document.py +262 -0
  68. fastmdxplora-2.0.0/src/fastmdxplora/report/run.py +96 -0
  69. fastmdxplora-2.0.0/src/fastmdxplora/report/slides.py +258 -0
  70. fastmdxplora-2.0.0/src/fastmdxplora/setup/__init__.py +25 -0
  71. fastmdxplora-2.0.0/src/fastmdxplora/setup/forcefields.py +147 -0
  72. fastmdxplora-2.0.0/src/fastmdxplora/setup/ligand.py +169 -0
  73. fastmdxplora-2.0.0/src/fastmdxplora/setup/pdbfix.py +110 -0
  74. fastmdxplora-2.0.0/src/fastmdxplora/setup/pipeline.py +428 -0
  75. fastmdxplora-2.0.0/src/fastmdxplora/setup/prepare.py +589 -0
  76. fastmdxplora-2.0.0/src/fastmdxplora/simulation/__init__.py +23 -0
  77. fastmdxplora-2.0.0/src/fastmdxplora/simulation/pipeline.py +290 -0
  78. fastmdxplora-2.0.0/src/fastmdxplora/simulation/plumed.py +146 -0
  79. fastmdxplora-2.0.0/src/fastmdxplora/simulation/runner.py +769 -0
  80. fastmdxplora-2.0.0/src/fastmdxplora/utils/__init__.py +31 -0
  81. fastmdxplora-2.0.0/src/fastmdxplora/utils/logging.py +278 -0
  82. fastmdxplora-2.0.0/src/fastmdxplora/utils/native_output.py +116 -0
  83. fastmdxplora-2.0.0/src/fastmdxplora/utils/presenter.py +387 -0
  84. fastmdxplora-2.0.0/src/fastmdxplora.egg-info/PKG-INFO +438 -0
  85. fastmdxplora-2.0.0/src/fastmdxplora.egg-info/SOURCES.txt +110 -0
  86. fastmdxplora-2.0.0/src/fastmdxplora.egg-info/dependency_links.txt +1 -0
  87. fastmdxplora-2.0.0/src/fastmdxplora.egg-info/entry_points.txt +2 -0
  88. fastmdxplora-2.0.0/src/fastmdxplora.egg-info/requires.txt +33 -0
  89. fastmdxplora-2.0.0/src/fastmdxplora.egg-info/top_level.txt +1 -0
  90. fastmdxplora-2.0.0/tests/__init__.py +0 -0
  91. fastmdxplora-2.0.0/tests/test_analysis_layer.py +513 -0
  92. fastmdxplora-2.0.0/tests/test_analysis_scope.py +254 -0
  93. fastmdxplora-2.0.0/tests/test_batch.py +627 -0
  94. fastmdxplora-2.0.0/tests/test_cli.py +175 -0
  95. fastmdxplora-2.0.0/tests/test_cli_flags.py +302 -0
  96. fastmdxplora-2.0.0/tests/test_compare.py +287 -0
  97. fastmdxplora-2.0.0/tests/test_concrete_analyses.py +420 -0
  98. fastmdxplora-2.0.0/tests/test_config.py +469 -0
  99. fastmdxplora-2.0.0/tests/test_forcefield_selector.py +178 -0
  100. fastmdxplora-2.0.0/tests/test_imports.py +58 -0
  101. fastmdxplora-2.0.0/tests/test_ligand.py +307 -0
  102. fastmdxplora-2.0.0/tests/test_ligand_rmsd.py +267 -0
  103. fastmdxplora-2.0.0/tests/test_logging.py +253 -0
  104. fastmdxplora-2.0.0/tests/test_md_engine_controls.py +507 -0
  105. fastmdxplora-2.0.0/tests/test_native_output.py +93 -0
  106. fastmdxplora-2.0.0/tests/test_orchestrator.py +250 -0
  107. fastmdxplora-2.0.0/tests/test_plumed.py +149 -0
  108. fastmdxplora-2.0.0/tests/test_presenter.py +307 -0
  109. fastmdxplora-2.0.0/tests/test_report_wiring.py +271 -0
  110. fastmdxplora-2.0.0/tests/test_setup_phase.py +491 -0
  111. fastmdxplora-2.0.0/tests/test_simulation_phase.py +588 -0
  112. fastmdxplora-2.0.0/tests/test_sub3_analyses.py +389 -0
@@ -0,0 +1,83 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ jobs:
9
+ build:
10
+ name: Build distributions
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+ with:
15
+ fetch-depth: 0
16
+
17
+ - name: Set up Python
18
+ uses: actions/setup-python@v5
19
+ with:
20
+ python-version: "3.11"
21
+
22
+ - name: Install build
23
+ run: python -m pip install --upgrade pip build
24
+
25
+ - name: Build the canonical package (fastmdxplora)
26
+ run: python -m build
27
+
28
+ - name: Build the fastmdx alias
29
+ run: cd shim-package && python -m build
30
+
31
+ - name: Verify fastmdx alias version matches the release tag
32
+ run: |
33
+ TAG="${GITHUB_REF_NAME#v}"
34
+ VER=$(python -c "import tomllib; print(tomllib.load(open('shim-package/pyproject.toml','rb'))['project']['version'])")
35
+ echo "fastmdx version: $VER (tag: $TAG)"
36
+ if [ "$TAG" != "$VER" ]; then
37
+ echo "::error::fastmdx alias version ($VER) does not match release tag ($TAG). Bump shim-package/pyproject.toml before tagging."
38
+ exit 1
39
+ fi
40
+
41
+ - name: Upload fastmdxplora artifacts
42
+ uses: actions/upload-artifact@v4
43
+ with:
44
+ name: dist-fastmdxplora
45
+ path: dist/
46
+
47
+ - name: Upload fastmdx artifacts
48
+ uses: actions/upload-artifact@v4
49
+ with:
50
+ name: dist-fastmdx
51
+ path: shim-package/dist/
52
+
53
+ publish-fastmdxplora:
54
+ name: Publish fastmdxplora to PyPI
55
+ needs: build
56
+ runs-on: ubuntu-latest
57
+ environment: pypi
58
+ permissions:
59
+ id-token: write
60
+ steps:
61
+ - uses: actions/download-artifact@v4
62
+ with:
63
+ name: dist-fastmdxplora
64
+ path: dist/
65
+ - uses: pypa/gh-action-pypi-publish@release/v1
66
+ with:
67
+ skip-existing: true
68
+
69
+ publish-fastmdx:
70
+ name: Publish fastmdx (alias) to PyPI
71
+ needs: publish-fastmdxplora
72
+ runs-on: ubuntu-latest
73
+ environment: pypi
74
+ permissions:
75
+ id-token: write
76
+ steps:
77
+ - uses: actions/download-artifact@v4
78
+ with:
79
+ name: dist-fastmdx
80
+ path: dist/
81
+ - uses: pypa/gh-action-pypi-publish@release/v1
82
+ with:
83
+ skip-existing: true
@@ -0,0 +1,49 @@
1
+ name: Tests
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ${{ matrix.os }}
12
+ strategy:
13
+ fail-fast: false
14
+ matrix:
15
+ os: [ubuntu-latest, macos-latest, windows-latest]
16
+ python-version: ["3.9", "3.10", "3.11", "3.12"]
17
+
18
+ steps:
19
+ - uses: actions/checkout@v4
20
+ with:
21
+ fetch-depth: 0 # full history for setuptools-scm
22
+
23
+ - name: Set up Python ${{ matrix.python-version }}
24
+ uses: actions/setup-python@v5
25
+ with:
26
+ python-version: ${{ matrix.python-version }}
27
+
28
+ - name: Install package and test dependencies
29
+ run: |
30
+ python -m pip install --upgrade pip
31
+ python -m pip install -e ".[test,report]"
32
+
33
+ - name: Run tests
34
+ run: |
35
+ pytest --cov=fastmdxplora --cov-report=term-missing --cov-report=xml
36
+
37
+ - name: CLI smoke test
38
+ shell: bash
39
+ run: |
40
+ fastmdx --version
41
+ fastmdx info
42
+ fastmdx --cite
43
+
44
+ - name: Upload coverage
45
+ uses: codecov/codecov-action@v4
46
+ if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.11'
47
+ with:
48
+ files: ./coverage.xml
49
+ fail_ci_if_error: false
@@ -0,0 +1,50 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # Distribution / packaging
7
+ .Python
8
+ build/
9
+ dist/
10
+ *.egg-info/
11
+ *.egg
12
+ wheels/
13
+ pip-wheel-metadata/
14
+
15
+ # Versioning artifact from setuptools-scm
16
+ src/fastmdxplora/_version.py
17
+ shim-package/src/fastmdx/_version.py
18
+
19
+ # Test / coverage artifacts
20
+ .pytest_cache/
21
+ .coverage
22
+ htmlcov/
23
+ coverage.xml
24
+ .tox/
25
+ .cache/
26
+
27
+ # Virtual environments
28
+ .venv/
29
+ venv/
30
+ env/
31
+ .env
32
+
33
+ # uv
34
+ .uv-cache/
35
+
36
+ # Editor / OS
37
+ .vscode/
38
+ .idea/
39
+ *.swp
40
+ *.swo
41
+ .DS_Store
42
+ Thumbs.db
43
+
44
+ # Documentation builds
45
+ docs/_build/
46
+ docs/build/
47
+ site/
48
+
49
+ # FastMDXplora run outputs (do not commit user data)
50
+ fastmdxplora_output_*/
@@ -0,0 +1,19 @@
1
+ version: 2
2
+
3
+ build:
4
+ os: ubuntu-22.04
5
+ tools:
6
+ python: "3.11"
7
+
8
+ sphinx:
9
+ configuration: docs/conf.py
10
+
11
+ python:
12
+ install:
13
+ - method: pip
14
+ path: .
15
+ extra_requirements:
16
+ - docs
17
+
18
+ formats:
19
+ - htmlzip
@@ -0,0 +1,100 @@
1
+ # Changelog
2
+
3
+ All notable changes to FastMDXplora are documented in this file.
4
+
5
+ Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) ·
6
+ Versioning: [SemVer 2.0.0](https://semver.org/spec/v2.0.0.html)
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [2.0.0] — 2026-05-25
11
+
12
+ **FastMDXplora** — Fully Automated SysTem for Molecular Dynamics eXploration.
13
+ A single command takes a structure (and optional bound ligand) from input to
14
+ publication-quality deliverable across four phases: setup, simulation
15
+ (including enhanced sampling), analysis (protein and protein-ligand), and
16
+ reporting.
17
+
18
+ ### Packaging
19
+ - Canonical package: **`fastmdxplora`** (`import fastmdxplora`). The CLI
20
+ command is **`fastmdx`**.
21
+ - `fastmdx` remains available on PyPI as a short alias that installs and
22
+ re-exports `fastmdxplora`.
23
+
24
+ ### Features
25
+ - End-to-end MD orchestration across four phases (setup, simulation, analysis, report).
26
+ - Named force-field selector; OpenFF ligand/cofactor parameterization with a setup-time pose clash check.
27
+ - Protein-ligand analyses: ligand pose RMSD, protein-ligand contacts + binding-site fingerprint, protein-ligand H-bonds, ligand RMSF — auto-detected for complexes.
28
+ - Analysis scope (`solute`/`protein`/`ligand`/`all`) keeping analyses off solvent.
29
+ - PLUMED enhanced sampling on the production stage (`--simulate-plumed-script`).
30
+ - Cross-platform CI (Linux/macOS/Windows); parallel batch execution and cross-run comparison.
31
+
32
+ ## [0.3.0] — 2026-05-25
33
+
34
+ Enhanced sampling. FastMDXplora can now drive PLUMED collective-variable
35
+ biasing (metadynamics, umbrella sampling, steered MD, …) on the production
36
+ stage of a run, with equilibration left unbiased per standard protocol.
37
+
38
+ ### Added
39
+ - **PLUMED enhanced sampling** (optional): supply a PLUMED script via `simulation.plumed` (config: `{enabled: true, script: "<inline or path to .dat>"}`) or `--simulate-plumed-script PATH` (CLI) to add collective-variable biasing — metadynamics, umbrella sampling, steered MD, etc. — to the **production** stage. Equilibration (NVT/NPT) runs unbiased, matching standard enhanced-sampling protocol; the biasing force is added just before production and the context reinitialized. PLUMED output files (COLVAR, HILLS, …) are redirected into the run's output directory, and the resolved script is saved as `plumed.dat` for reproducibility. Requires the `plumed` extra (`openmm-plumed`, installed via `conda install -c conda-forge openmm-plumed`); absent, enabling PLUMED raises a clear, actionable error.
40
+
41
+ ### Changed
42
+ - Renamed the `test_md_parity.py` test module to `test_md_engine_controls.py` to match its content (MD engine controls). Trimmed the README (removed the Status and Project-family sections).
43
+
44
+ ## [0.2.0] — 2026-05-25
45
+
46
+ End-to-end protein-ligand molecular dynamics. FastMDXplora can now set up,
47
+ simulate, and analyze a protein-ligand complex from a feasible bound pose:
48
+ named force fields with an OpenFF small-molecule path, a setup-time pose
49
+ sanity check, and the standard protein-ligand analysis suite, all detected
50
+ and wired automatically.
51
+
52
+ ### Added
53
+ - **Protein-ligand analyses** (run automatically when a ligand is detected; `include`/`exclude` apply): in addition to ligand pose RMSD, three more commonly-reported analyses now run on protein-ligand complexes:
54
+ - `contacts` — protein-ligand contacts, reported two ways: a per-frame count of protein residues within a cutoff (default 0.4 nm) of the ligand (`contacts.dat`), and a per-residue contact-frequency "interaction fingerprint" identifying the binding-site residues (`contacts_per_residue.csv`, also shown as the figure)
55
+ - `pl_hbonds` — hydrogen bonds formed specifically between protein and ligand (per frame), distinct from the general intra-solute `hbonds` analysis
56
+ - `ligand_rmsf` — per-ligand-atom fluctuation after protein alignment: the ligand's internal flexibility in the pocket
57
+ - **Ligand pose RMSD** analysis (`ligand_rmsd`): the headline protein-ligand stability metric. Each frame is rigidly aligned onto the reference using the protein (Cα by default), then RMSD is measured on the ligand atoms of the aligned coordinates — i.e. how far the ligand has moved *relative to the protein frame*, which tells you whether it holds its binding pose or drifts/unbinds. This is distinct from the standard RMSD (which aligns and measures on the same atoms). It runs automatically when a ligand is detected (from `resolved_forcefield.ligand` in the setup manifest) and is skipped for protein-only runs; `include`/`exclude` still apply. Ligand-only analyses are marked with a `requires_ligand` flag on the analysis class, and the orchestrator supplies the detected ligand residue name automatically
58
+ - **Analysis scope** (`analysis.scope` / `--analyze-scope`): a single setting controls which atoms analyses operate on — `solute` (protein + ligand, the default), `protein`, `ligand`, or `all`. It resolves to a default atom selection applied to analyses that don't set their own (the solvent-blind ones: Rg, SASA, secondary structure, Q-value, hydrogen bonds), so they no longer run on solvent/ions by accident. Analyses with a meaningful own default (the Cα-based RMSD, RMSF, clustering, dimensionality reduction) keep it. An explicit per-analysis or orchestrator-wide `selection` still overrides the scope. When a ligand is present (detected from `resolved_forcefield.ligand` in the setup manifest), `solute` and `ligand` scopes include it automatically by residue name
59
+ - **Ligand / cofactor parameterization** (protein-ligand systems): supply a small-molecule ligand as an SDF or MOL2 file via `setup.ligand` (config) or `--setup-ligand` (CLI), parameterized with an OpenFF small-molecule force field through `openmmforcefields`' `SystemGenerator`. Selected with the ligand-capable `amber-openff` named force field (AMBER ff14SB protein + TIP3P water + OpenFF Sage 2.2.1 for the ligand). Net charge is inferred from the SDF formal charges unless set explicitly via `ligand_net_charge`; the ligand residue name (`ligand_name`, default `LIG`) and small-molecule force field (`ligand_forcefield`, e.g. `openff-2.2.1` or `gaff-2.2.20`) are configurable. The supplied ligand coordinates must be a feasible bound pose (from a co-crystal structure or docking); a setup-time clash check (`check_ligand_clashes`, `ligand_clash_threshold_nm`) fails with a clear message if the pose severely overlaps the protein, rather than letting it surface as a divergent simulation later. Incoherent combinations are rejected early with clear errors (a ligand with a non-ligand-capable force field, or with a raw XML list). The resolved ligand parameterization is recorded under `resolved_forcefield.ligand` in `setup_parameters.json`. Requires the `ligand` extra (`pip install 'fastmdxplora[ligand]'`); absent, the phase degrades with an actionable install message. Ligand input is list-shaped in config for future multi-ligand support; single-ligand parameterization is implemented now
60
+ - **Named force-field selector**: pick a force field by a short, documented name via `setup.forcefield` (config) or `--setup-forcefield` (CLI) — `charmm36` (default), `amber14`, `amber-fb15`, or `amber-openff` (ligand-capable) — instead of listing raw OpenMM XML filenames. Each name resolves to the correct protein/water XML set and default water model through a single registry (`setup/forcefields.py`). The raw `force_field` XML list remains as a power-user escape hatch; specifying both a named selector and a raw list is rejected with a clear error, as is an unknown force-field name (the message lists valid choices). The resolved force field (actual XMLs + water model) is recorded under `resolved_forcefield` in `setup_parameters.json` for reproducibility, regardless of which form the user chose
61
+
62
+ ### Fixed
63
+ - The ligand residue in the prepared/solvated topology is now named with the configured ligand name (default `LIG`) instead of OpenFF's default `UNK`. Previously the written `topology.pdb` labelled the ligand `UNK` while the manifest recorded `LIG`, so resname-based selection silently failed — ligand-aware analyses found no ligand atoms, and the `solute`/`ligand` analysis scopes silently excluded the ligand. The name is now set on both the ligand topology and the merged topology so it survives `Modeller.add()` across OpenMM versions
64
+ - Clustering on a trajectory with fewer frames than the requested number of clusters now fails with a clear, actionable message ("Clustering needs at least n_clusters=N frames, but the trajectory has only M...") instead of an opaque scikit-learn internals error. k-means and hierarchical clustering are guarded; DBSCAN (which doesn't take a cluster count) is unaffected
65
+ - Analyses that operate on all atoms by default (Rg, SASA, secondary structure, Q-value, hydrogen bonds) now slice the trajectory to the resolved scope/selection *before* computing, rather than processing the full solvated system. Previously several of these passed the whole trajectory straight to the underlying calculation regardless of the selection — so on a solvated complex the Q-value analysis enumerated residue pairs across ~10k water residues (tens of millions of pairs) and effectively hung, and Rg/SASA were computed over water. With the new `solute` default scope and per-analysis slicing they operate on protein (+ ligand) only — a correctness fix for any solvated run and a large speedup
66
+ - **Named force-field selector**: pick a force field by a short, documented name via `setup.forcefield` (config) or `--setup-forcefield` (CLI) — `charmm36` (default), `amber14`, `amber-fb15`, or `amber-openff` (ligand-capable) — instead of listing raw OpenMM XML filenames. Each name resolves to the correct protein/water XML set and default water model through a single registry (`setup/forcefields.py`). The raw `force_field` XML list remains as a power-user escape hatch; specifying both a named selector and a raw list is rejected with a clear error, as is an unknown force-field name (the message lists valid choices). The resolved force field (actual XMLs + water model) is recorded under `resolved_forcefield` in `setup_parameters.json` for reproducibility, regardless of which form the user chose
67
+
68
+ ## [0.1.0] — 2026-05-XX
69
+
70
+ Initial claim-staking release. Establishes the project-level orchestrator
71
+ scaffolding, the four-phase API (setup, simulation, analysis, report), and
72
+ the `fastmdx` CLI.
73
+
74
+ ### Added
75
+ - **Robust auto platform selection**: when `platform=auto`, the simulation runner now verifies a GPU platform (CUDA/OpenCL) can actually create a Context before committing to it, and falls back to the next candidate (ultimately CPU) if not — instead of selecting a *registered-but-unusable* platform that then fails at Context construction with a confusing error. An explicit `platform=CUDA`/`OpenCL` request is still honored as-is (the user sees the real error if their choice is broken)
76
+ - **Clear periodic-box / cutoff guard**: `prepare_system` now raises an actionable error when the nonbonded cutoff exceeds half the smallest periodic box dimension (instead of OpenMM's cryptic `NonbondedForce` message), naming the cutoff, the box, and how to fix it (increase `solvent_padding_nm` or decrease `nonbonded_cutoff_nm`)
77
+ - **`environment.yml` + git install path** — clone the repo and `mamba env create -f environment.yml || conda env create -f environment.yml` then `pip install .` to get all four phases (the OpenMM/PDBFixer chemistry stack from conda-forge) without waiting on the conda-forge package. Plain `pip install fastmdxplora` still gives the analysis + report phases on their own
78
+
79
+ ### Fixed
80
+ - **Parallel execution on Windows**: spawned worker processes now reconfigure their stdout/stderr to UTF-8 (as the CLI entry point does). Previously, because workers are spawned (not forked) on Windows and bypass the CLI entry, their streams stayed on the platform codec (cp1252) and crashed with `UnicodeEncodeError` the moment the presenter printed a status glyph (✓, ▸) — so every run in `mode: parallel` failed on Windows while sequential mode succeeded
81
+ - **Headless plotting**: the analysis package now forces matplotlib's non-interactive `Agg` backend before pyplot is imported (respecting an explicit `MPLBACKEND`). Previously the backend was only forced off-Windows with no `DISPLAY`, so analyses crashed on headless machines that didn't match that gate (notably headless Windows CI) with "Can't find a usable init.tcl". FastMDXplora always writes figures to files, so a non-interactive backend is always correct
82
+ - **Cross-platform paths in reports/manifests**: figure links in the Markdown report, zip archive entry names, and the relative artifact paths recorded in manifests now use forward slashes (`as_posix()`) on every OS. Previously, on Windows these were emitted with backslashes, breaking Markdown/HTML image links and producing non-portable manifests
83
+ - **UTF-8 file/stream encoding everywhere**: all text written by FastMDXplora (reports, comparison markdown, config templates, manifests, PDB/XML artifacts) now specifies `encoding="utf-8"` explicitly, and the CLI reconfigures stdout/stderr to UTF-8 at entry. Previously, on a machine whose default locale encoding was ASCII, writing the comparison report's `→` or the config template's `—` (or printing the banner) raised `UnicodeEncodeError`
84
+ - **FastMDXplora orchestrator class** (`fastmdxplora.FastMDXplora`) — project-level coordinator following a seven-phase orchestration pattern (Aina & Kwan, JCC 2026)
85
+ - **Four phases** under `fastmdxplora.setup`, `.simulation`, `.analysis`, `.report` — each with a `run(orchestrator, output_dir, **options)` entry point and a structured parameters manifest
86
+ - **`fastmdx` CLI** with subcommands `explore` (canonical), `xplore` (X-themed alias), `setup`, `simulate`, `analyze`, `report`, `info`, plus `--version` and `--cite` flags
87
+ - **Report phase artifacts**: Markdown study report, .pptx slide deck, self-contained .zip project bundle
88
+ - **YAML configuration files**: a single config captures an entire study — input is given as a canonical `systems:` list (always a list, even for one system), plus phase selection and all per-phase options; drives both the CLI (`--config` / `-c`) and the Python API (`FastMDXplora(config=...).explore()`); `fastmdx init-config` writes a fully-commented template; strict schema validation rejects typos with did-you-mean suggestions; command-line flags override file values; every run writes a re-runnable `resolved_config.yml` for reproducibility
89
+ - **Full MD engine controls**: integrator selection (`langevin_middle`, `langevin`, `brownian`, `verlet`, `variable_langevin`, `variable_verlet`); pressure in either `pressure_bar` or `pressure_atm` (auto-converted); GPU `device_index` selection; `checkpoint_interval_steps` writing a restart-ready `.chk`; `ForceField.createSystem` pass-throughs (`nonbonded_method`, `ewald_error_tolerance`, `use_switching_function`, `switch_distance_nm`, `dispersion_correction`, `remove_cm_motion`); and `fixed_pdb` to skip PDBFixer when a prepared structure is supplied
90
+ - **Many-system & parameter-sweep mode**: the `systems:` list can hold several systems, and an optional `sweep:` of parameter axes (dotted `phase.option` keys) runs the full cross-product (systems × sweep), each as a complete self-contained study. One run writes the flat output layout; multiple runs go in `runs/<id>/` indexed by a top-level `batch_manifest.json`. Per-system option overrides and swept values merge with correct precedence (base < per-system < sweep); typo'd sweep axes are rejected with the valid-option list. An optional `execution:` block runs studies in parallel (process pool) with round-robin GPU device pinning (one run per device)
91
+ - **Cross-run comparison report**: after a multi-run study, a `comparison/` report is built automatically at the batch root — per-frame **overlays** (RMSD, Rg, Q-value, total SASA across all runs on one axes), **trend** plots of each run's summary scalar against the swept parameter, a `comparison_summary.csv`, and a written `comparison_report.md` with a quantitative takeaway per property. Degrades gracefully (errored runs / missing analyses skipped); disable with `report: { comparison: false }`; (re)build via `FastMDXplora(...).compare()` (optionally `compare(output_dir=…)` for a batch that finished earlier)
92
+ - **Dry-run / plan-only mode**: `fastmdx explore --config … --dry-run` (or `explore(dry_run=True)`) prints every run, its system, swept values, target output directory, and the phases that would execute — then exits without running anything or writing to disk
93
+ - **Uniform return shape**: `FastMDXplora.explore()` always returns a `list[RunResult]` — a single study is a list of one, a sweep is a list of many. Each `RunResult` carries `run_id`, `system`, `status`, `output_dir`, `sweep_values`, and its per-phase `PhaseResult` list in `.phases` (with a `.phase(name)` lookup helper). The single user-facing entry point is always `FastMDXplora`; the batch machinery underneath is private
94
+ - **Reproducibility manifest** (`manifest.json`) written at the project root summarizing phases executed, parameters, software versions, and DOI
95
+ - **Datasets namespace** (`fastmdxplora.datasets`) with a TrpCage placeholder
96
+ - **CI**: matrix tests on ubuntu/macos/windows × Python 3.9–3.12 (GitHub Actions)
97
+ - **PyPI**: dual-name publishing — `fastmdxplora` is the primary package, `fastmdx` is a thin alias that depends on it
98
+
99
+ ### Notes
100
+ - The analysis and report phases are self-contained (no heavy runtime dependencies); the setup and simulation phases require OpenMM + PDBFixer.
@@ -0,0 +1,35 @@
1
+ cff-version: 1.2.0
2
+ message: >-
3
+ If you use FastMDXplora in your work, please cite the foundational
4
+ FastMDAnalysis paper below.
5
+ title: "FastMDXplora: Fully Automated SysTem for Molecular Dynamics eXploration"
6
+ type: software
7
+ authors:
8
+ - family-names: Aina
9
+ given-names: Adekunle
10
+ affiliation: "AAI Research Lab, California State University Dominguez Hills"
11
+ - family-names: Kwan
12
+ given-names: Derrick
13
+ affiliation: "AAI Research Lab, California State University Dominguez Hills"
14
+ repository-code: "https://github.com/aai-research-lab/FastMDXplora"
15
+ url: "https://github.com/aai-research-lab/FastMDXplora"
16
+ license: MIT
17
+ keywords:
18
+ - molecular-dynamics
19
+ - orchestrator
20
+ - automation
21
+ - computational-chemistry
22
+ - reproducibility
23
+ preferred-citation:
24
+ type: article
25
+ title: "FastMDAnalysis: Software for Automated Analysis of Molecular Dynamics Trajectories"
26
+ authors:
27
+ - family-names: Aina
28
+ given-names: Adekunle
29
+ - family-names: Kwan
30
+ given-names: Derrick
31
+ journal: "Journal of Computational Chemistry"
32
+ year: 2026
33
+ volume: 47
34
+ issue: 8
35
+ doi: "10.1002/jcc.70350"
@@ -0,0 +1,43 @@
1
+ # Code of Conduct
2
+
3
+ ## Our pledge
4
+
5
+ We as members, contributors, and leaders pledge to make participation in
6
+ our community a harassment-free experience for everyone, regardless of
7
+ age, body size, visible or invisible disability, ethnicity, sex
8
+ characteristics, gender identity and expression, level of experience,
9
+ education, socio-economic status, nationality, personal appearance,
10
+ race, religion, or sexual identity and orientation.
11
+
12
+ We pledge to act and interact in ways that contribute to an open,
13
+ welcoming, diverse, inclusive, and healthy community.
14
+
15
+ ## Our standards
16
+
17
+ Examples of behavior that contributes to a positive environment:
18
+
19
+ - Using welcoming and inclusive language
20
+ - Being respectful of differing viewpoints and experiences
21
+ - Gracefully accepting constructive criticism
22
+ - Focusing on what is best for the community
23
+
24
+ Examples of unacceptable behavior:
25
+
26
+ - Trolling, insulting or derogatory comments, and personal or political attacks
27
+ - Public or private harassment
28
+ - Publishing others' private information without explicit permission
29
+ - Other conduct which could reasonably be considered inappropriate in a
30
+ professional setting
31
+
32
+ ## Enforcement
33
+
34
+ Project maintainers are responsible for clarifying and enforcing the
35
+ standards above. Instances of abusive or unacceptable behavior may be
36
+ reported to the project lead at the email listed on the AAI Research
37
+ Lab website. All complaints will be reviewed and investigated promptly
38
+ and fairly.
39
+
40
+ ## Attribution
41
+
42
+ This Code of Conduct is adapted from the
43
+ [Contributor Covenant](https://www.contributor-covenant.org), version 2.1.
@@ -0,0 +1,67 @@
1
+ # Contributing to FastMDXplora
2
+
3
+ Thank you for your interest in contributing to FastMDXplora. We welcome
4
+ contributions of all kinds — bug reports, feature requests, documentation
5
+ improvements, and code.
6
+
7
+ ## Getting started
8
+
9
+ ```bash
10
+ # Clone the repository
11
+ git clone https://github.com/aai-research-lab/FastMDXplora.git
12
+ cd FastMDXplora
13
+
14
+ # Create and activate a virtual environment
15
+ python -m venv .venv
16
+ source .venv/bin/activate # On Windows: .venv\Scripts\activate
17
+
18
+ # Install in editable mode with development dependencies
19
+ pip install -e ".[dev]"
20
+
21
+ # Verify the install
22
+ fastmdx --version
23
+ fastmdx info
24
+ pytest
25
+ ```
26
+
27
+ ## Development workflow
28
+
29
+ 1. Open an issue describing the change you'd like to make (skip this for
30
+ trivial fixes such as typos).
31
+ 2. Fork the repository and create a topic branch from `main`.
32
+ 3. Make your changes. Write or update tests under `tests/`.
33
+ 4. Run the test suite locally (`pytest`).
34
+ 5. Run the linter (`ruff check src tests`) and ensure it passes.
35
+ 6. Open a pull request against `main`.
36
+
37
+ ## Coding conventions
38
+
39
+ - **Python ≥ 3.9.** Use modern type hints and the standard library where possible.
40
+ - **`src/` layout.** All package code lives under `src/fastmdxplora/`.
41
+ - **Docstrings.** Public functions and classes get NumPy-style docstrings.
42
+ - **Tests required for new functionality.** Smoke tests at minimum; full
43
+ numerical/equivalence tests for any analytical code migrated from
44
+ FastMDAnalysis (which FastMDXplora is the successor to).
45
+ - **Lazy imports for heavy optional dependencies** (OpenMM, PDBFixer,
46
+ python-pptx, etc.).
47
+ - **Consistent output structure.** Every phase writes its outputs to
48
+ `output_dir/<phase>/`, including a `*_parameters.json` manifest.
49
+
50
+ ## Reporting issues
51
+
52
+ Please include:
53
+
54
+ - The output of `fastmdx info`
55
+ - The command line you ran (or the Python code snippet)
56
+ - The full error message and traceback
57
+ - A minimal reproducing example if possible
58
+
59
+ ## Code of conduct
60
+
61
+ By participating in this project, you agree to abide by our
62
+ [Code of Conduct](CODE_OF_CONDUCT.md).
63
+
64
+ ## License
65
+
66
+ By contributing, you agree that your contributions will be licensed under
67
+ the project's [MIT License](LICENSE).
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Adekunle Aina, Derrick Kwan, and FastMDXplora contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.