mdprep 0.2.0__tar.gz → 0.4.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 (392) hide show
  1. {mdprep-0.2.0 → mdprep-0.4.0}/.gitignore +10 -0
  2. {mdprep-0.2.0 → mdprep-0.4.0}/AGENTS.md +3 -2
  3. mdprep-0.4.0/CHANGELOG.md +367 -0
  4. mdprep-0.4.0/CONTRIBUTING.md +115 -0
  5. {mdprep-0.2.0 → mdprep-0.4.0}/PKG-INFO +62 -9
  6. {mdprep-0.2.0 → mdprep-0.4.0}/README.md +52 -6
  7. {mdprep-0.2.0 → mdprep-0.4.0}/docs/README.md +4 -0
  8. mdprep-0.4.0/docs/guided_manifests.md +173 -0
  9. {mdprep-0.2.0 → mdprep-0.4.0}/docs/installation.md +42 -9
  10. mdprep-0.4.0/docs/ligands.md +91 -0
  11. {mdprep-0.2.0 → mdprep-0.4.0}/docs/manifest_reference.md +49 -3
  12. {mdprep-0.2.0 → mdprep-0.4.0}/docs/metals.md +243 -4
  13. mdprep-0.4.0/docs/molecular_dynamics.md +166 -0
  14. mdprep-0.4.0/docs/oligomers.md +169 -0
  15. mdprep-0.4.0/docs/predicted_structures.md +170 -0
  16. mdprep-0.4.0/docs/protonation.md +181 -0
  17. {mdprep-0.2.0 → mdprep-0.4.0}/docs/qmmm_refinement.md +58 -7
  18. mdprep-0.4.0/docs/quickstart.md +75 -0
  19. mdprep-0.4.0/docs/tleap_and_validation.md +110 -0
  20. {mdprep-0.2.0 → mdprep-0.4.0}/docs/troubleshooting.md +70 -0
  21. mdprep-0.4.0/environment-minimal.yml +17 -0
  22. mdprep-0.4.0/environment.yml +45 -0
  23. mdprep-0.4.0/examples/16_besd_halogenase_gfn2_mcpb.yaml +163 -0
  24. mdprep-0.4.0/examples/17_syrb2_bound_water_mcpb.yaml +216 -0
  25. mdprep-0.4.0/examples/18_syrb2_dimer_shared_mcpb.yaml +345 -0
  26. mdprep-0.4.0/examples/README.md +108 -0
  27. mdprep-0.4.0/examples/colab/mdprep_colab_pipeline.py +1618 -0
  28. mdprep-0.4.0/examples/colab_smoke_test.ipynb +114 -0
  29. mdprep-0.4.0/examples/mdprep_colab.ipynb +1080 -0
  30. mdprep-0.4.0/examples/mdprep_colab_run.ipynb +30 -0
  31. mdprep-0.4.0/examples/mdprep_interactive_colab.ipynb +2189 -0
  32. {mdprep-0.2.0 → mdprep-0.4.0}/pyproject.toml +47 -3
  33. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/__init__.py +1 -1
  34. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/ambertools/mol2.py +69 -3
  35. mdprep-0.4.0/src/mdprep/analysis/__init__.py +6 -0
  36. mdprep-0.4.0/src/mdprep/analysis/charges.py +209 -0
  37. mdprep-0.4.0/src/mdprep/analysis/dcd.py +112 -0
  38. mdprep-0.4.0/src/mdprep/analysis/equilibration.py +90 -0
  39. mdprep-0.4.0/src/mdprep/analysis/metal_site.py +78 -0
  40. mdprep-0.4.0/src/mdprep/analysis/prmtop.py +236 -0
  41. mdprep-0.4.0/src/mdprep/analysis/trajectory.py +365 -0
  42. mdprep-0.4.0/src/mdprep/cli.py +896 -0
  43. mdprep-0.4.0/src/mdprep/config/decisions.py +3054 -0
  44. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/config/models.py +374 -16
  45. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/leap/builder.py +24 -4
  46. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/leap/log_parser.py +15 -0
  47. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/leap/report.py +15 -0
  48. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/leap/residues.py +98 -30
  49. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/ligands/extract.py +30 -0
  50. mdprep-0.4.0/src/mdprep/ligands/hydrogenate.py +420 -0
  51. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/ligands/workflow.py +108 -9
  52. mdprep-0.4.0/src/mdprep/md/imaging.py +146 -0
  53. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/md/roe_brooks.py +278 -36
  54. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/metals/coordination.py +11 -4
  55. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/metals/gxtb_hessian.py +45 -8
  56. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/metals/hydrogenate.py +9 -18
  57. mdprep-0.4.0/src/mdprep/metals/mcpb.py +1775 -0
  58. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/metals/nonbonded.py +25 -4
  59. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/metals/pyscf_mcpb.py +174 -12
  60. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/metals/report.py +25 -0
  61. mdprep-0.4.0/src/mdprep/metals/through_metal.py +135 -0
  62. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/metals/workflow.py +31 -11
  63. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/protonation/apply.py +45 -23
  64. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/protonation/histidine_geometry.py +98 -10
  65. mdprep-0.4.0/src/mdprep/protonation/histidine_qmmm.py +597 -0
  66. mdprep-0.4.0/src/mdprep/protonation/histidine_xtb.py +983 -0
  67. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/protonation/propka_parser.py +11 -3
  68. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/protonation/report.py +3 -0
  69. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/protonation/temporary_hydrogenation.py +194 -22
  70. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/protonation/xtb_runner.py +47 -3
  71. mdprep-0.4.0/src/mdprep/qm/xtb_esp.py +357 -0
  72. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/refinement/coordinates.py +2 -18
  73. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/refinement/mapping.py +4 -0
  74. mdprep-0.4.0/src/mdprep/refinement/openmm_minimizer.py +327 -0
  75. mdprep-0.4.0/src/mdprep/refinement/report.py +116 -0
  76. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/refinement/selection.py +66 -3
  77. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/refinement/workflow.py +55 -19
  78. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/reports/structure_report.py +5 -0
  79. mdprep-0.4.0/src/mdprep/structure/classify.py +291 -0
  80. mdprep-0.4.0/src/mdprep/structure/closest_xray.py +301 -0
  81. mdprep-0.4.0/src/mdprep/structure/completeness.py +169 -0
  82. mdprep-0.4.0/src/mdprep/structure/coordination.py +70 -0
  83. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/structure/inspect.py +17 -2
  84. mdprep-0.4.0/src/mdprep/structure/mmcif.py +248 -0
  85. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/structure/models.py +37 -0
  86. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/structure/normalize.py +177 -6
  87. mdprep-0.4.0/src/mdprep/structure/oligomer.py +713 -0
  88. mdprep-0.4.0/src/mdprep/structure/pdb.py +726 -0
  89. mdprep-0.4.0/src/mdprep/structure/pdb_fields.py +341 -0
  90. mdprep-0.4.0/src/mdprep/structure/reader.py +47 -0
  91. mdprep-0.4.0/src/mdprep/structure/rename.py +105 -0
  92. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/structure/repair.py +168 -13
  93. mdprep-0.4.0/src/mdprep/structure/waters.py +868 -0
  94. mdprep-0.4.0/src/mdprep/structure/writer.py +272 -0
  95. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/validation/topology.py +63 -5
  96. mdprep-0.4.0/src/mdprep/workflows/doctor.py +304 -0
  97. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/workflows/prepare.py +58 -16
  98. mdprep-0.4.0/src/mdprep/workflows/runtime.py +389 -0
  99. mdprep-0.4.0/src/mdprep/workflows/wizard.py +230 -0
  100. mdprep-0.4.0/tests/besd_structure.py +68 -0
  101. mdprep-0.4.0/tests/browser/launch.mjs +58 -0
  102. mdprep-0.4.0/tests/browser/smoke.mjs +216 -0
  103. mdprep-0.4.0/tests/browser/student_flow.mjs +117 -0
  104. mdprep-0.4.0/tests/conftest.py +3 -0
  105. mdprep-0.4.0/tests/data/amber/README.md +13 -0
  106. mdprep-0.4.0/tests/data/amber/ace_ala_gly_nme.inpcrd +17 -0
  107. mdprep-0.4.0/tests/data/amber/ace_ala_gly_nme.prmtop +286 -0
  108. mdprep-0.4.0/tests/data/boltz_far_donor.cif +50 -0
  109. mdprep-0.4.0/tests/data/boltz_model.cif +41 -0
  110. mdprep-0.4.0/tests/data/boltz_smiles_ligands.cif +47 -0
  111. mdprep-0.4.0/tests/data/boltz_wide_names.cif +50 -0
  112. mdprep-0.4.0/tests/data/protein_with_hydrogenated_free_lysine.pdb +54 -0
  113. mdprep-0.4.0/tests/data/protein_zinc_aqua.pdb +22 -0
  114. mdprep-0.4.0/tests/test_analysis.py +435 -0
  115. mdprep-0.4.0/tests/test_besd_halogenase_case.py +415 -0
  116. mdprep-0.4.0/tests/test_browser_planning_path.py +120 -0
  117. mdprep-0.4.0/tests/test_build_residues_is_defined_once.py +96 -0
  118. mdprep-0.4.0/tests/test_cli.py +49 -0
  119. mdprep-0.4.0/tests/test_closest_xray.py +256 -0
  120. mdprep-0.4.0/tests/test_colab_official_notebook.py +164 -0
  121. mdprep-0.4.0/tests/test_colab_smoke_notebook.py +15 -0
  122. mdprep-0.4.0/tests/test_colab_wizard_notebook.py +416 -0
  123. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_config_validation.py +27 -0
  124. mdprep-0.4.0/tests/test_coordinating_ions.py +200 -0
  125. mdprep-0.4.0/tests/test_crystal_ions.py +215 -0
  126. mdprep-0.4.0/tests/test_doctor.py +263 -0
  127. mdprep-0.4.0/tests/test_external_dcd_openmm.py +42 -0
  128. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_external_gxtb_hessian.py +33 -0
  129. mdprep-0.4.0/tests/test_external_md_restraint_frame.py +97 -0
  130. mdprep-0.4.0/tests/test_external_md_snapshot_box.py +131 -0
  131. mdprep-0.4.0/tests/test_external_oligomer_mcpb.py +112 -0
  132. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_external_structure_repair.py +88 -0
  133. mdprep-0.4.0/tests/test_external_water_transplant.py +61 -0
  134. mdprep-0.4.0/tests/test_external_xtb_embedding.py +113 -0
  135. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_gxtb_hessian.py +70 -13
  136. mdprep-0.4.0/tests/test_histidine_cluster_metal.py +166 -0
  137. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_histidine_geometry.py +53 -5
  138. mdprep-0.4.0/tests/test_histidine_qmmm.py +293 -0
  139. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_leap_builder.py +23 -0
  140. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_leap_input_pdb.py +7 -23
  141. mdprep-0.4.0/tests/test_leap_ligand_residue_names.py +272 -0
  142. mdprep-0.4.0/tests/test_ligand_hydrogenation.py +405 -0
  143. mdprep-0.4.0/tests/test_ligand_mol2_validation.py +0 -0
  144. mdprep-0.4.0/tests/test_manifest_decisions.py +977 -0
  145. mdprep-0.4.0/tests/test_manifest_wizard.py +371 -0
  146. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_mcpb_pyscf_fixed_geometry.py +5 -0
  147. mdprep-0.4.0/tests/test_md_imaging.py +180 -0
  148. mdprep-0.4.0/tests/test_metal_bound_water.py +223 -0
  149. mdprep-0.4.0/tests/test_metal_hydrogenation_preservation.py +88 -0
  150. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_metals.py +57 -0
  151. mdprep-0.4.0/tests/test_mmcif.py +406 -0
  152. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_mol2_validation.py +39 -0
  153. mdprep-0.4.0/tests/test_oligomers.py +925 -0
  154. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_packaging_metadata.py +1 -1
  155. mdprep-0.4.0/tests/test_pdb_large_serials.py +154 -0
  156. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_pdb_parser.py +26 -0
  157. mdprep-0.4.0/tests/test_pdb_roundtrip_property.py +285 -0
  158. mdprep-0.4.0/tests/test_pdb_writer.py +236 -0
  159. mdprep-0.4.0/tests/test_prediction_pdb_quirks.py +123 -0
  160. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_prepare_refinement_stage.py +7 -0
  161. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_prepare_tleap_stage.py +1 -1
  162. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_protonation_xtb_workflow.py +39 -8
  163. mdprep-0.4.0/tests/test_qm_region_spin_state.py +172 -0
  164. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_refinement_config.py +46 -2
  165. mdprep-0.4.0/tests/test_refinement_openmm.py +190 -0
  166. mdprep-0.4.0/tests/test_refinement_platform.py +153 -0
  167. mdprep-0.4.0/tests/test_refinement_report.py +156 -0
  168. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_refinement_selection.py +7 -0
  169. mdprep-0.4.0/tests/test_residue_rename.py +148 -0
  170. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_roe_brooks.py +26 -0
  171. mdprep-0.4.0/tests/test_roe_brooks_restraints.py +162 -0
  172. mdprep-0.4.0/tests/test_runtime_requirements.py +514 -0
  173. mdprep-0.4.0/tests/test_runtime_requirements_cover_every_option.py +324 -0
  174. mdprep-0.4.0/tests/test_structure_completeness.py +366 -0
  175. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_structure_normalize.py +32 -0
  176. mdprep-0.4.0/tests/test_structure_repair_inputs.py +183 -0
  177. mdprep-0.4.0/tests/test_syrb2_bound_water_case.py +99 -0
  178. mdprep-0.4.0/tests/test_temporary_hydrogenation_hold_back.py +145 -0
  179. mdprep-0.4.0/tests/test_through_metal.py +100 -0
  180. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_validation_helpers.py +56 -0
  181. mdprep-0.4.0/tests/test_validation_topology.py +28 -0
  182. mdprep-0.4.0/tests/test_water_transplant.py +382 -0
  183. mdprep-0.4.0/tests/test_web_builder_bound_water_case.py +130 -0
  184. mdprep-0.4.0/tests/test_web_builder_browser.py +341 -0
  185. mdprep-0.4.0/tests/test_web_builder_oligomer_case.py +165 -0
  186. mdprep-0.4.0/tests/test_web_builder_reference_case.py +235 -0
  187. mdprep-0.4.0/tests/test_web_bundle_zip.py +116 -0
  188. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_xtb_command_builder.py +27 -0
  189. mdprep-0.4.0/tests/test_xtb_esp.py +150 -0
  190. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_xtb_water_hydrogens.py +14 -2
  191. mdprep-0.4.0/web/.gitignore +1 -0
  192. mdprep-0.4.0/web/README.md +129 -0
  193. mdprep-0.4.0/web/app.js +997 -0
  194. mdprep-0.4.0/web/build.py +79 -0
  195. mdprep-0.4.0/web/index.html +165 -0
  196. mdprep-0.4.0/web/style.css +343 -0
  197. mdprep-0.4.0/web/zip.js +154 -0
  198. mdprep-0.2.0/.github/workflows/tests.yml +0 -52
  199. mdprep-0.2.0/CHANGELOG.md +0 -54
  200. mdprep-0.2.0/CONTRIBUTING.md +0 -58
  201. mdprep-0.2.0/MANIFEST.in +0 -11
  202. mdprep-0.2.0/Roe_and_Brooks.py +0 -41
  203. mdprep-0.2.0/Roe_and_Brooks_corrected.py +0 -587
  204. mdprep-0.2.0/docs/ligands.md +0 -48
  205. mdprep-0.2.0/docs/molecular_dynamics.md +0 -78
  206. mdprep-0.2.0/docs/protonation.md +0 -70
  207. mdprep-0.2.0/docs/quickstart.md +0 -41
  208. mdprep-0.2.0/docs/tleap_and_validation.md +0 -41
  209. mdprep-0.2.0/environment.yml +0 -24
  210. mdprep-0.2.0/examples/README.md +0 -28
  211. mdprep-0.2.0/examples/tutorials/7E07.pdb +0 -5271
  212. mdprep-0.2.0/examples/tutorials/7E07_bonded_fe3/README.md +0 -121
  213. mdprep-0.2.0/examples/tutorials/7E07_bonded_fe3/input.pdb +0 -2384
  214. mdprep-0.2.0/examples/tutorials/7E07_bonded_fe3/optimized_small_model.pdb +0 -55
  215. mdprep-0.2.0/examples/tutorials/7E07_bonded_fe3/reference/large_embedded_cdiis150_restart.chk +0 -0
  216. mdprep-0.2.0/examples/tutorials/7E07_bonded_fe3/system.yaml +0 -239
  217. mdprep-0.2.0/examples/tutorials/7E07_prepared.pdb +0 -2382
  218. mdprep-0.2.0/examples/tutorials/minimal_user_mol2/README.md +0 -15
  219. mdprep-0.2.0/examples/tutorials/minimal_user_mol2/input.pdb +0 -3
  220. mdprep-0.2.0/examples/tutorials/minimal_user_mol2/ligand.frcmod +0 -11
  221. mdprep-0.2.0/examples/tutorials/minimal_user_mol2/ligand.mol2 +0 -11
  222. mdprep-0.2.0/examples/tutorials/minimal_user_mol2/system.yaml +0 -71
  223. mdprep-0.2.0/scripts/run_smoke_tests.sh +0 -17
  224. mdprep-0.2.0/src/mdprep/cli.py +0 -451
  225. mdprep-0.2.0/src/mdprep/metals/mcpb.py +0 -949
  226. mdprep-0.2.0/src/mdprep/protonation/histidine_xtb.py +0 -390
  227. mdprep-0.2.0/src/mdprep/refinement/report.py +0 -66
  228. mdprep-0.2.0/src/mdprep/structure/classify.py +0 -92
  229. mdprep-0.2.0/src/mdprep/structure/pdb.py +0 -511
  230. mdprep-0.2.0/src/mdprep/structure/writer.py +0 -84
  231. mdprep-0.2.0/tests/test_cli.py +0 -23
  232. mdprep-0.2.0/tests/test_pdb_writer.py +0 -55
  233. {mdprep-0.2.0 → mdprep-0.4.0}/CITATION.cff +0 -0
  234. {mdprep-0.2.0 → mdprep-0.4.0}/LICENSE +0 -0
  235. {mdprep-0.2.0 → mdprep-0.4.0}/docs/developer_notes.md +0 -0
  236. {mdprep-0.2.0 → mdprep-0.4.0}/docs/mcpb_xtb_benchmark.md +0 -0
  237. {mdprep-0.2.0 → mdprep-0.4.0}/docs/qmmesp_pyscf.md +0 -0
  238. {mdprep-0.2.0 → mdprep-0.4.0}/environment-dev.yml +0 -0
  239. {mdprep-0.2.0 → mdprep-0.4.0}/examples/00_basic_protein.yaml +0 -0
  240. {mdprep-0.2.0 → mdprep-0.4.0}/examples/01_protein_only_ff19sb.yaml +0 -0
  241. {mdprep-0.2.0 → mdprep-0.4.0}/examples/02_manual_catalytic_protonation.yaml +0 -0
  242. {mdprep-0.2.0 → mdprep-0.4.0}/examples/03_multi_ligand_am1bcc.yaml +0 -0
  243. {mdprep-0.2.0 → mdprep-0.4.0}/examples/04_qmmesp_pyscf_ligand.yaml +0 -0
  244. {mdprep-0.2.0 → mdprep-0.4.0}/examples/05_histidine_gxtb_sp.yaml +0 -0
  245. {mdprep-0.2.0 → mdprep-0.4.0}/examples/06_disulfide_manual.yaml +0 -0
  246. {mdprep-0.2.0 → mdprep-0.4.0}/examples/07_gas_resp_pyscf_ligand.yaml +0 -0
  247. {mdprep-0.2.0 → mdprep-0.4.0}/examples/08_nonbonded_zinc_1264.yaml +0 -0
  248. {mdprep-0.2.0 → mdprep-0.4.0}/examples/09_bonded_zinc_mcpb_prepare.yaml +0 -0
  249. {mdprep-0.2.0 → mdprep-0.4.0}/examples/10_qmmm_refinement_ash.yaml +0 -0
  250. {mdprep-0.2.0 → mdprep-0.4.0}/examples/11_qmmm_metal_gfn2_mcpb.yaml +0 -0
  251. {mdprep-0.2.0 → mdprep-0.4.0}/examples/12_qmmm_metal_mace_polar1_mcpb.yaml +0 -0
  252. {mdprep-0.2.0 → mdprep-0.4.0}/examples/13_qmmm_refinement_gxtb_mechanical.yaml +0 -0
  253. {mdprep-0.2.0 → mdprep-0.4.0}/examples/14_qmmm_refinement_mace_polar1_mechanical.yaml +0 -0
  254. {mdprep-0.2.0 → mdprep-0.4.0}/examples/15_roe_brooks_openmm.yaml +0 -0
  255. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/_selftest_data/basic_protein.yaml +0 -0
  256. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/_selftest_data/ligand_sub.mol2 +0 -0
  257. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/ambertools/__init__.py +0 -0
  258. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/ambertools/antechamber.py +0 -0
  259. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/ambertools/commands.py +0 -0
  260. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/ambertools/parmchk2.py +0 -0
  261. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/ambertools/resp.py +0 -0
  262. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/charges/__init__.py +0 -0
  263. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/charges/esp_grid.py +0 -0
  264. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/config/__init__.py +0 -0
  265. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/config/loader.py +0 -0
  266. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/external/__init__.py +0 -0
  267. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/external/discovery.py +0 -0
  268. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/external/runner.py +0 -0
  269. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/leap/__init__.py +0 -0
  270. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/leap/forcefields.py +0 -0
  271. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/leap/ions.py +0 -0
  272. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/leap/runner.py +0 -0
  273. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/ligands/__init__.py +0 -0
  274. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/ligands/identity.py +0 -0
  275. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/ligands/pyscf_charges.py +0 -0
  276. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/ligands/report.py +0 -0
  277. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/md/__init__.py +0 -0
  278. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/metals/__init__.py +0 -0
  279. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/metals/c4.py +0 -0
  280. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/metals/mace_polar1_hessian.py +0 -0
  281. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/metals/mace_polar1_worker.py +0 -0
  282. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/metals/mcpb_compat.py +0 -0
  283. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/metals/parameter_comparison.py +0 -0
  284. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/protonation/__init__.py +0 -0
  285. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/protonation/disulfide_states.py +0 -0
  286. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/protonation/overrides.py +0 -0
  287. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/protonation/pka_rules.py +0 -0
  288. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/protonation/propka.py +0 -0
  289. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/protonation/states.py +0 -0
  290. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/protonation/xtb_parser.py +0 -0
  291. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/qm/__init__.py +0 -0
  292. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/qm/point_charges.py +0 -0
  293. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/qm/pyscf_esp.py +0 -0
  294. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/qm/pyscf_runner.py +0 -0
  295. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/refinement/__init__.py +0 -0
  296. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/refinement/ash.py +0 -0
  297. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/reports/__init__.py +0 -0
  298. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/structure/__init__.py +0 -0
  299. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/structure/disulfides.py +0 -0
  300. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/structure/selectors.py +0 -0
  301. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/validation/__init__.py +0 -0
  302. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/validation/openmm_check.py +0 -0
  303. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/validation/parmed_check.py +0 -0
  304. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/workflows/__init__.py +0 -0
  305. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/workflows/init.py +0 -0
  306. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/workflows/inspect.py +0 -0
  307. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/workflows/selftest.py +0 -0
  308. {mdprep-0.2.0 → mdprep-0.4.0}/src/mdprep/workflows/validate.py +0 -0
  309. {mdprep-0.2.0 → mdprep-0.4.0}/tests/__init__.py +0 -0
  310. {mdprep-0.2.0 → mdprep-0.4.0}/tests/data/ligands/ligand_cof.frcmod +0 -0
  311. {mdprep-0.2.0 → mdprep-0.4.0}/tests/data/ligands/ligand_cof.good.mol2 +0 -0
  312. {mdprep-0.2.0 → mdprep-0.4.0}/tests/data/ligands/ligand_sub.atom_count_mismatch.mol2 +0 -0
  313. {mdprep-0.2.0 → mdprep-0.4.0}/tests/data/ligands/ligand_sub.bad_charge.mol2 +0 -0
  314. {mdprep-0.2.0 → mdprep-0.4.0}/tests/data/ligands/ligand_sub.frcmod +0 -0
  315. {mdprep-0.2.0 → mdprep-0.4.0}/tests/data/ligands/ligand_sub.good.mol2 +0 -0
  316. {mdprep-0.2.0 → mdprep-0.4.0}/tests/data/ligands/ligand_sub.pdb +0 -0
  317. {mdprep-0.2.0 → mdprep-0.4.0}/tests/data/ligands/ligand_sub.renamed.mol2 +0 -0
  318. {mdprep-0.2.0 → mdprep-0.4.0}/tests/data/ligands/ligand_sub.shifted_coords.mol2 +0 -0
  319. {mdprep-0.2.0 → mdprep-0.4.0}/tests/data/ligands/ligand_sub.small_residual.mol2 +0 -0
  320. {mdprep-0.2.0 → mdprep-0.4.0}/tests/data/propka_sample.pka +0 -0
  321. {mdprep-0.2.0 → mdprep-0.4.0}/tests/data/protein_altloc.pdb +0 -0
  322. {mdprep-0.2.0 → mdprep-0.4.0}/tests/data/protein_atom_record_ligand_blank_chain.pdb +0 -0
  323. {mdprep-0.2.0 → mdprep-0.4.0}/tests/data/protein_blank_chain.pdb +0 -0
  324. {mdprep-0.2.0 → mdprep-0.4.0}/tests/data/protein_cyx_disulfide.pdb +0 -0
  325. {mdprep-0.2.0 → mdprep-0.4.0}/tests/data/protein_disulfide.pdb +0 -0
  326. {mdprep-0.2.0 → mdprep-0.4.0}/tests/data/protein_histidine_ring.pdb +0 -0
  327. {mdprep-0.2.0 → mdprep-0.4.0}/tests/data/protein_histidine_ring_hydrogenated.pdb +0 -0
  328. {mdprep-0.2.0 → mdprep-0.4.0}/tests/data/protein_histidine_water_oxygen.pdb +0 -0
  329. {mdprep-0.2.0 → mdprep-0.4.0}/tests/data/protein_histidine_zinc.pdb +0 -0
  330. {mdprep-0.2.0 → mdprep-0.4.0}/tests/data/protein_insertion_code.pdb +0 -0
  331. {mdprep-0.2.0 → mdprep-0.4.0}/tests/data/protein_two_ligands.pdb +0 -0
  332. {mdprep-0.2.0 → mdprep-0.4.0}/tests/data/protein_with_hydrogens.pdb +0 -0
  333. {mdprep-0.2.0 → mdprep-0.4.0}/tests/data/protein_with_waters.pdb +0 -0
  334. {mdprep-0.2.0 → mdprep-0.4.0}/tests/data/xtb_hid_stdout.txt +0 -0
  335. {mdprep-0.2.0 → mdprep-0.4.0}/tests/data/xtb_hie_stdout.txt +0 -0
  336. {mdprep-0.2.0 → mdprep-0.4.0}/tests/data/zinc_only.pdb +0 -0
  337. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_altloc.py +0 -0
  338. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_amber_resp.py +0 -0
  339. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_ambertools_commands.py +0 -0
  340. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_classify.py +0 -0
  341. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_config_examples.py +0 -0
  342. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_disulfide_assignment.py +0 -0
  343. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_disulfide_leap_mapping.py +0 -0
  344. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_disulfides.py +0 -0
  345. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_esp_grid.py +0 -0
  346. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_external_amber_resp.py +0 -0
  347. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_external_ambertools.py +0 -0
  348. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_external_mace_polar1.py +0 -0
  349. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_external_metals.py +0 -0
  350. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_external_propka_xtb.py +0 -0
  351. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_external_pyscf.py +0 -0
  352. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_external_tleap.py +0 -0
  353. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_import.py +0 -0
  354. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_init_cli.py +0 -0
  355. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_init_ligand_placeholders.py +0 -0
  356. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_inspect_cli.py +0 -0
  357. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_ions.py +0 -0
  358. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_leap_forcefields.py +0 -0
  359. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_leap_log_parser.py +0 -0
  360. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_ligand_extraction.py +0 -0
  361. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_ligand_workflow_mocked.py +0 -0
  362. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_mace_polar1_hessian.py +0 -0
  363. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_manifest_paths.py +0 -0
  364. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_manual_protonation.py +0 -0
  365. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_mcpb_compat.py +0 -0
  366. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_mcpb_parameter_comparison.py +0 -0
  367. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_md_config.py +0 -0
  368. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_mol2_parser.py +0 -0
  369. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_no_openbabel.py +0 -0
  370. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_pka_rules.py +0 -0
  371. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_point_charges.py +0 -0
  372. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_prepare_ligands_stage.py +0 -0
  373. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_prepare_protonation_stage.py +0 -0
  374. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_prepare_pyscf_ligands_stage.py +0 -0
  375. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_prepare_structure_stage.py +0 -0
  376. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_propka_parser.py +0 -0
  377. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_protonation_propka_workflow.py +0 -0
  378. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_protonation_reuse_refined.py +0 -0
  379. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_protonation_states.py +0 -0
  380. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_pyscf_esp_mocked.py +0 -0
  381. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_pyscf_runner_config.py +0 -0
  382. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_qmmesp_correctness.py +0 -0
  383. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_qmmesp_final_mol2_usage.py +0 -0
  384. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_qmmesp_no_environment_fit.py +0 -0
  385. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_readme_example.py +0 -0
  386. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_refinement_ash.py +0 -0
  387. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_refinement_coordinates.py +0 -0
  388. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_remove_hydrogens.py +0 -0
  389. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_selectors.py +0 -0
  390. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_selftest_installed.py +0 -0
  391. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_tleap_workflow_mocked.py +0 -0
  392. {mdprep-0.2.0 → mdprep-0.4.0}/tests/test_xtb_parser.py +0 -0
@@ -16,3 +16,13 @@ runs/
16
16
  *.tar.gz
17
17
  *.tar.gz.sha256
18
18
  .DS_Store
19
+ node_modules/
20
+ package-lock.json
21
+
22
+ # Worktrees created for spawned background tasks.
23
+ .claude/worktrees/
24
+
25
+ # Tutorial structures downloaded on demand.
26
+ tutorials/
27
+ web/vendor/
28
+ *.zip
@@ -65,8 +65,9 @@ Explicitly unsupported for v0.2:
65
65
  - covalent ligands
66
66
  - ORCA backend
67
67
  - Multiwfn dependency
68
- - multiple independent bonded MCPB sites
69
- - multi-chain MCPB protein inputs
68
+ - multiple independent bonded MCPB sites (copies of one site in an oligomer
69
+ share a single fit through `parameters_from`; see `docs/oligomers.md`)
70
+ - bonded MCPB sites bound by more than one protein chain
70
71
 
71
72
  ## Required Checks
72
73
 
@@ -0,0 +1,367 @@
1
+ # Changelog
2
+
3
+ ## 0.4.0 - 2026-10-20
4
+
5
+ ### Added
6
+
7
+ - Dimers, trimers and tetramers. Every protein chain can be prepared in one
8
+ system, and when the chains are copies of one protein the builder asks
9
+ whether every copy should get the same parameters. If so it asks about the
10
+ first copy only and gives each answer to the matching residue of the others,
11
+ matched by sequence and by position rather than by residue number, which
12
+ copies often do not share (2FCT numbers its two alpha-ketoglutarates 897 and
13
+ 898). A ligand is parameterised once; a bonded metal site is fitted once with
14
+ MCPB.py, and each copy's residues take the fit's templates and its metal the
15
+ fit's bonds. A copy whose site differs -- 6NIE's chains B and C bind
16
+ alpha-ketoglutarate through the other carboxylate oxygen -- is reported and
17
+ asked about on its own. See `docs/oligomers.md`.
18
+ - `parameters_from` on ligands and metal sites: a block built with another
19
+ block's parameters, checked by `config-check` to repeat its settings and, for
20
+ a bonded site, to list its residues in the reference's order.
21
+ - `examples/18_syrb2_dimer_shared_mcpb.yaml`: both copies of SyrB2, one fit.
22
+ - `mdprep.analysis.charges.metal_sites`: each metal site's charge on its own,
23
+ which the official notebook now shows one table per site.
24
+ - The web builder lists which chains are copies of one protein, shows the
25
+ chain and copy questions with each chain in its own colour, and names
26
+ residues with their chain.
27
+ - Refusals the answers already make certain are given at the question that
28
+ causes them, in the web builder and in `mdprep init --interactive`: a second
29
+ bonded metal site needing a fit of its own, or a cofactor whose charges were
30
+ to come from a site made nonbonded. Every `DecisionError` names the question
31
+ to go back to (`decision_id`), and the page goes there.
32
+
33
+ - The official Colab notebook, `examples/mdprep_colab.ipynb`: takes a bundle
34
+ from the web builder (or runs the SyrB2 example), prepares and equilibrates
35
+ the system, and shows every step -- the structure after each stage, the
36
+ protonation states, the charge on every atom in tables and in 3D, the metal
37
+ site's MCPB force constants, how temperature, density and volume
38
+ equilibrated, the structure after each Roe-Brooks step, and the trajectory
39
+ with its RMSD, RMSF and metal-site distances. The web builder links to it.
40
+ - `mdprep closest-xray`: the X-ray structures closest to a predicted model,
41
+ from the RCSB sequence search, with resolution, waters and bound ligands;
42
+ those holding the model's metal come first.
43
+ - `mdprep transplant-waters`: a reference structure's crystal waters on a
44
+ predicted model. PyMOL pairs the residues (by sequence, or by structure for a
45
+ distant homologue); each model chain takes its best reference chain; a water
46
+ bound to a metal moves with it onto the model's metal; clashing and bulk
47
+ waters are dropped; a reference of another fold is refused. Every decision
48
+ is in a JSON report.
49
+ - `mdprep.analysis`: reads a prmtop, inpcrd and OpenMM DCD with numpy alone,
50
+ and provides charge tables, the metal site's force constants, imaged and
51
+ superposed trajectories, RMSD, RMSF and distances, and the equilibration and
52
+ production logs.
53
+ - `equilibration.csv` in every Roe-Brooks run: every stage on one time axis,
54
+ with temperature, density, box volume and energies every 0.5 ps.
55
+ - `docs/predicted_structures.md`: from a Boltz or AlphaFold3 prediction to a
56
+ model with its crystal waters, with the worked SyrB2 example.
57
+ - `examples/17_syrb2_bound_water_mcpb.yaml` and the vendored 2FCT deposition.
58
+ - When a structure with a metal has no waters at all, the metal question says
59
+ so and points to `mdprep transplant-waters`.
60
+
61
+ - Waters bound to a bonded metal site, as the resting iron of an
62
+ alpha-ketoglutarate enzyme carries (SyrB2, PDB 2FCT). The decision engine
63
+ proposes the water as a donor; mdprep writes the TIP3P template MCPB.py
64
+ requires, supplies the H-O-H angle rigid TIP3P lacks, and counts the water as
65
+ neutral in the QM/MM refinement.
66
+ - `structure.keep_crystal_ions` and its question: free monatomic ions resolved
67
+ in the crystal (Cl-, Na+, Br-, ...) are kept or removed as a group, and
68
+ listed in the structure report either way.
69
+
70
+ ### Changed
71
+
72
+ - **Free crystal ions are kept by default.** A free monatomic ion in the input
73
+ used to count as an unknown heterogen, so a manifest with
74
+ `structure.remove_unknown_heterogens: true` dropped it. It is now governed by
75
+ `structure.keep_crystal_ions`, which defaults to `true`, so the same manifest
76
+ builds with the ion in place: 2FCT's free chloride, for one. Add
77
+ `keep_crystal_ions: false` to keep the old result. Every ion kept or removed
78
+ is listed in `reports/structure_report.md`.
79
+ - Two bonded metal sites are refused by `mdprep config-check`, where 0.3.0
80
+ refused them only once a run had started.
81
+
82
+ ### Fixed
83
+
84
+ - CUDA did not start on Colab's T4 GPUs (OpenCL did):
85
+ - conda-forge installed a CUDA runtime newer than the GPU driver, whose
86
+ kernels the driver refused (`CUDA_ERROR_UNSUPPORTED_PTX_VERSION`);
87
+ - the setup the notebook and the web builder run now caps `cuda-version`
88
+ at the driver's version, and rerunning section C repairs an existing
89
+ environment;
90
+ - `mdprep doctor` starts a CUDA system to check;
91
+ - a CUDA failure in the MD says what to do, and `auto` says which
92
+ platform it passed over.
93
+ - The official notebook drew the final structure (E3) from tleap's PDB, which
94
+ has no elements, so the viewer read hydrogens such as HG21 as mercury and
95
+ bonded them to everything near. It is now drawn from the topology, as E8
96
+ and H are. Each protein molecule is now its own chain in every view, so no
97
+ cartoon runs from one copy of a dimer into the next or across a missing
98
+ loop. A chloride on the iron, one atom with no bond to draw, now shows as a
99
+ sphere.
100
+ - Keeping one chain of a predicted oligomer kept every ligand chain too, so the
101
+ other copy's iron and cofactor floated in the box. A chain holding only
102
+ heterogens now goes with the protein chain it sits against.
103
+ - The spin of the QM region was asked of any structure with two metals, even
104
+ when neither turned out bonded; it is now asked once a bonded site is
105
+ confirmed, whichever site that is.
106
+ - `DecisionPlan.applicable` counted an answer whose own question was no longer
107
+ reachable -- a shell confirmed before the site was switched to nonbonded.
108
+ - The ligand coordinate check after tleap could not tell two copies of one
109
+ cofactor apart, since tleap renumbers residues; it now takes the copy nearest
110
+ the ligand it checks.
111
+ - The web builder and the wizard told a student to add a SMILES to a ligand
112
+ without hydrogens after asking for it and being given it.
113
+ - `mdprep init --interactive` re-asked a rejected answer without saying why.
114
+
115
+ - A residue name mdprep assigned (a predicted iron called `LIG1` read as `FE`)
116
+ lost that record when the structure was written and read back, and `FE` read
117
+ cold is the CCD code for Fe(III): the planner then proposed +3 for an Fe(II)
118
+ site. mdprep's PDB writer records assigned names in a remark its reader
119
+ honours.
120
+ - The model-charge proposal ignored an oxidation state accepted as proposed,
121
+ so a student added the terms up by hand.
122
+ - The old Colab run notebook ran the MD twice: `mdprep prepare` already runs it
123
+ when the manifest enables it. It now points to the official notebook, which
124
+ stops `prepare` before the MD.
125
+ - A free crystal chloride was offered as a ligand and then refused as a
126
+ reserved residue name, telling the user to rename it. tleap builds it from
127
+ its ion library like any counterion; it is no longer a ligand candidate, and
128
+ a histidine xTB cluster that contains one counts its charge.
129
+ - A topology with a water and a halide on the same metal went to NaN in
130
+ heating: their 1-4 pair through the metal had a Coulomb attraction and no
131
+ repulsion. Those 1-4 terms are now switched off in the prmtop and listed in
132
+ the tleap report.
133
+ - tleap bonded the two ends of an unresolved loop into one peptide bond, 6.08 A
134
+ long in 2FCT. A TER is now written wherever C(i)-N(i+1) exceeds 2 A.
135
+ - The crystal-water and unknown-heterogen questions disappeared whenever any
136
+ water coordinated any metal -- in 6NIE, three waters on a surface iron of
137
+ chain B hid the question for all 847. Both are asked now, and the
138
+ crystal-water question names the bound waters that are kept regardless.
139
+ - A water bound to a metal was dropped with the other crystal waters when
140
+ those were removed: for a bonded site that left an MCPB bond to a residue
141
+ that no longer existed, and for a nonbonded one it stripped the ion's first
142
+ shell, though the question had said it would stay. The question and
143
+ normalisation now share one definition of a bound water
144
+ (`mdprep.structure.coordination`).
145
+ - Declining a ligand while keeping unknown heterogens, dropping crystal waters
146
+ with a bonded site, or choosing OPC with a water bound to a bonded metal now
147
+ fail in the builder with what to change, instead of later in Colab.
148
+ - The QM-region spin proposal ignored defaults the user had accepted without
149
+ typing them, so a bonded iron with the default model got no proposal.
150
+
151
+ ## 0.3.0 - 2026-10-19
152
+
153
+ ### Added
154
+
155
+ - `mdprep plan` and `mdprep init --interactive`: a structure-aware decision
156
+ engine that reduces a 250+ setting schema to the questions one structure
157
+ actually needs, and asks them. Chemistry-sensitive values have no default and
158
+ cannot be skipped.
159
+ - Each decision carries viewer hints (`focus`, `targets`, `target_resnames`) so
160
+ a 3D front end can frame exactly the residues a question is about.
161
+ - `mdprep inspect` reports free monatomic metal ions.
162
+ - A static web input builder (`web/`) that runs mdprep in the browser under
163
+ Pyodide, shows a 3D view framed on whatever each question is about, and
164
+ produces a validated manifest plus runnable Colab cells.
165
+ - `mdprep.workflows.runtime.conda_packages_for` derives the external toolchain a
166
+ given manifest needs, so a generated setup cell installs PropKa, xTB or PySCF
167
+ only when the run will actually invoke them.
168
+
169
+ - `mdprep doctor` checks that the external tools a given manifest will invoke
170
+ are installed, and names the one command that installs what is missing.
171
+ - mmCIF and ModelCIF input: a structure predicted by Boltz or AlphaFold is read
172
+ directly, with no conversion step and no loss of the chain and residue
173
+ identifiers the manifest selects on.
174
+ - Four-character residue names, hybrid-36 serial and residue numbers, and
175
+ residues whose name does not fit a PDB column, which a predicted structure
176
+ written to PDB reaches routinely. A name mdprep has to assign is recorded as
177
+ assigned, so nothing downstream reads chemistry into a name it invented.
178
+ - `metals[].coordinating_ions` declares a non-metal ion bound in a metal site,
179
+ such as a coordinating halide, which previously had nowhere to live: it is
180
+ not a metal, and antechamber cannot treat a single atom.
181
+ - The setup cell downloads the g-xTB build of xtb from the Grimme group's
182
+ releases and checks it against the published checksum, because conda-forge
183
+ carries only the GFN-only build.
184
+
185
+ - `structure.keep_chains` restricts a build to named chains, which a bonded
186
+ MCPB site requires and a multi-copy crystal structure needs.
187
+ - The decision engine proposes a metal coordination sphere from interatomic
188
+ distances, requires it to be confirmed, and generates the bonded MCPB block
189
+ with a GFN2 Seminario Hessian and GFN2 QM/MM refinement geometry.
190
+ - `examples/16_besd_halogenase_gfn2_mcpb.yaml`, the BesD halogenase reference
191
+ case.
192
+ - Detection of incomplete residues and chain breaks, asked about before any
193
+ expensive stage runs, and protection for waters coordinating a metal.
194
+ - `examples/mdprep_colab_run.ipynb`, a Colab notebook that runs a manifest and
195
+ installs only the toolchain that manifest needs.
196
+
197
+ - `metals[].coordinating_ions` declares a non-metal ion bound in a metal site,
198
+ such as a coordinating halide, which previously had nowhere to live: it is
199
+ not a metal and antechamber cannot treat a single atom.
200
+
201
+ ### Changed
202
+
203
+ - The refinement stage defaults to `backend: openmm`, a force-field hydrogen
204
+ relaxation, instead of GFN2 QM/MM. The stage only ever moved hydrogens, and
205
+ a force field settles them in seconds. `backend: ash` keeps the QM/MM route
206
+ and is required to relax heavy atoms. `movable_atoms` and
207
+ `post_refinement_protonation` default to match the hydrogen-only backend.
208
+ - Histidine HID/HIE selection stays with xTB: force-field energies of the two
209
+ tautomers are not comparable, because they are different residue templates
210
+ rather than one molecule with a proton moved.
211
+
212
+ - Dropped the unused `scipy` and `pandas` runtime dependencies.
213
+ - A ligand that coordinates a bonded metal site now defaults to taking its
214
+ charges from that site's MCPB fit instead of AM1-BCC.
215
+ - A metal site's Hessian defaults to g-xTB rather than GFN2. GFN2 has no
216
+ parameters for most transition metals, and said so only after the run had
217
+ got as far as the Hessian.
218
+ - **A ligand whose residue name an Amber force field already defines is now
219
+ refused, where it used to be renamed for the build.** `LYS` became `LY1`,
220
+ which satisfied tleap and moved the problem: the prepared system then
221
+ described a residue under a name the input never used, and every later
222
+ reader had to know about the substitution. A manifest that declares such a
223
+ ligand now fails, in the GUI before it asks anything and on the command line
224
+ before any quantum chemistry, and says which residue to rename. The web
225
+ builder offers to make the change in the input.
226
+ - **`refinement.total_qm_multiplicity` is now required whenever any component
227
+ of the QM region is open-shell**, where it used to be taken from the first
228
+ open-shell component found. For a lone high-spin Fe(II) that is the right
229
+ answer and it was right by accident: it holds only while the ion is the
230
+ single unpaired centre and nothing couples to it, which nothing in a
231
+ manifest can check. Existing manifests that leave it out of an open-shell
232
+ region will fail validation and need the value added.
233
+ - Preparing the same system the same way twice now yields the same atom count.
234
+ MD starting velocities stay random and the seed drawn for each run is
235
+ recorded, so a replicate can be repeated by putting that number back.
236
+
237
+ ### Fixed
238
+
239
+ - Per-step MD snapshots are written in the box the manifest asked for. They
240
+ carried the pre-NPT cell, because `PDBFile` takes CRYST1 from the topology
241
+ and the topology was the one loaded at the start, and they were wrapped into
242
+ the parallelepiped OpenMM spans rather than imaged about the solute -- so a
243
+ truncated octahedron came back as a sheared prism with the protein off to
244
+ one side and its water drawn 70 A away instead of 54 A.
245
+ - The ESP grid survives an xTB crash on its last point, and the fit uses the
246
+ grid that was actually evaluated rather than the one that was requested.
247
+ - A metal in a predicted structure is named after its element, so a site is
248
+ not identified by a name the prediction never meant as one.
249
+ - CONECT records that cover only part of a ligand are ignored rather than
250
+ treated as its whole connectivity.
251
+ - tleap writes its own atom types into the element column of the PDB it
252
+ outputs; the reader no longer believes them.
253
+ - The setup cell installs PDBFixer whenever a run will need it, not only when
254
+ structure repair happens to pull it in, and the resolver is checked against
255
+ every combination of options rather than the one that was reported.
256
+ - A titratable side chain coordinating a metal is asked about, from the same
257
+ contact list the bonds come from, instead of refusing the run later.
258
+ - Guessed force-field parameters (`ATTN, need revision`) and the OpenMM energy
259
+ check are both checked when the manifest asks for them.
260
+ - Many GUI fixes: the Finish button reports what went wrong instead of doing
261
+ nothing, re-uploading a structure cannot leave the bundle describing the
262
+ previous one, a file that parses to no atoms is rejected, Start over clears
263
+ the answers, Enter fetches a PDB id, and an entry that is mmCIF-only is
264
+ fetched as `.cif`.
265
+
266
+ ## 0.2.1 - 2026-10-01
267
+
268
+ ### Fixed
269
+
270
+ - A ligand whose residue name is one the Amber force fields already define is
271
+ now built under a name they do not. `tleap` resolves residues by name and
272
+ maps an amino-acid name to its terminal form first, so the BesD free-lysine
273
+ substrate was built from the `NLYS` protein template and the run died with
274
+ "Atom .R<NLYS 252>.A<OXT 25> does not have a type" for every one of its
275
+ ligand-named atoms; binding the ligand unit to `LYS` instead would have
276
+ pointed every lysine in the protein at the ligand's parameters. The leap
277
+ input PDB, a copy of the fitted mol2, the `tleap` script and the final
278
+ validation all use the new name, and every rename is reported.
279
+ - The temporary xTB hydrogen environment no longer hydrogenates a residue
280
+ twice. OpenMM matches the hydrogens a residue already has through the bonds
281
+ its residue templates define, so hydrogens mdprep placed from
282
+ `ligands[].smiles`, named after their parent heavy atom, were invisible to it
283
+ and it built a second complete set beside them: the BesD free-lysine
284
+ substrate came out carrying both HB2/HB3 and HB/HBA. Such a residue is now
285
+ passed through untouched and reported, unless a protonation state was decided
286
+ for it, in which case OpenMM still rebuilds it in that state.
287
+ - Amber ion atom types were built as `element + charge + "+"`, which produced
288
+ `Na1+` for every monovalent cation and could not express an anion at all.
289
+
290
+ - Roe--Brooks stage 2 no longer fails with "Particle coordinate is NaN" on
291
+ solvated systems. Free ions were positionally restrained because Amber names
292
+ them `Na+`/`Cl-`, which match no bare element symbol, and coordinates handed
293
+ between stages were wrapped into the periodic box while the restraint
294
+ references stayed unwrapped, placing every wrapped restrained particle a full
295
+ box length from its reference. Stage hand-off and XML restarts now stay in
296
+ the unwrapped frame; only the per-step PDBs and the trajectory are wrapped.
297
+ - Final-output validation no longer rejects its own PDB with "PDB atom serials
298
+ must be unique when present" above 99,999 atoms. Serials are decoded for the
299
+ column-12 overflow `tleap`/`ambpdb` write, for hybrid-36, and for `*****`; a
300
+ genuine wrap-around is renumbered in file order with a warning, and stays
301
+ fatal only when `CONECT` records make the connectivity ambiguous. The PDB
302
+ writer uses the same convention it reads, so structures of that size
303
+ round-trip unchanged.
304
+ - `mdprep inspect --json` no longer emits unparseable JSON on a narrow
305
+ terminal, where rich reflowed long strings to the console width.
306
+
307
+ ### Changed
308
+
309
+ - xTB histidine calculations pin `OMP_NUM_THREADS`, `MKL_NUM_THREADS` and
310
+ `OPENBLAS_NUM_THREADS` to the new `protonation.histidine.xtb.num_threads`
311
+ (default `1`), with `OMP_STACKSIZE` from `omp_stacksize` (default `1G`).
312
+ xTB otherwise opened one thread per hardware thread for every tautomer
313
+ cluster, spending large amounts of CPU time without reducing wall time.
314
+ - `mdprep inspect` also reports free monatomic metal ions.
315
+
316
+ ## 0.2.0 - 2026-08-17
317
+
318
+ ### Added
319
+
320
+ - Explicit nonbonded and bonded MCPB.py metal-center workflows, including
321
+ PySCF QMMESP/RESP charges and PySCF, GFN2-xTB, g-xTB, or MACE-POLAR-1
322
+ Hessian sources for Seminario parameters.
323
+ - Optional ASH active-site QM/MM refinement with explicit QM components,
324
+ coordinating residues, 4 A residue and 8 A water active regions, and
325
+ hydrogen-only relaxation.
326
+ - Manifest-driven Roe--Brooks OpenMM minimization, heating, density
327
+ equilibration, and production MD with accelerator-first/CPU-fallback
328
+ platform selection.
329
+ - User-controlled production step and reporting/checkpoint intervals.
330
+ - Manifest-directory-relative input paths and portable executable discovery.
331
+ - GAFF/GAFF2, ff14SB/ff19SB, TIP3P/OPC, AM1-BCC, gas RESP, and embedded
332
+ QMMESP examples covering the supported preparation combinations.
333
+
334
+ ### Fixed
335
+
336
+ - Roe--Brooks positional restraints are installed before Context creation and
337
+ their reference coordinates are converted explicitly from input units to nm.
338
+ - Constraint-compatible heating handoff, evolving NPT box propagation, and
339
+ production progress totals.
340
+ - MCPB/tLEaP residue-index and renamed-residue coordinate validation.
341
+
342
+ ## 0.1.0 - 2026-06-15
343
+
344
+ Initial usable release.
345
+
346
+ ### Added
347
+
348
+ - YAML manifest validation with pydantic.
349
+ - PDB inspection, residue/atom selector parsing, altloc handling, water and heterogen classification, histidine/titratable residue detection, and possible disulfide detection.
350
+ - `mdprep init` starter-manifest generation and safe structure normalization.
351
+ - Manual protonation overrides, input-state preservation, disulfide `CYX` assignment, and input-hydrogen removal.
352
+ - PropKa-based residue-state assignment and xTB/GFN2 or g-xTB HID/HIE histidine tautomer selection.
353
+ - Ligand extraction and AmberTools parameter generation for `am1bcc` and `user_mol2`.
354
+ - PySCF gas-phase RESP/ESP-like ligand charges.
355
+ - PySCF QMMESP-like environment-polarized ligand charges with explicit target-ligand-only fitting.
356
+ - Final `tleap` build, optional solvation, neutralization/salt handling, final Amber files, and validation reports.
357
+ - External tests that skip cleanly when optional executables or libraries are unavailable.
358
+
359
+ ### Unsupported In 0.1.0
360
+
361
+ - Noncanonical amino acids inside polymer chains.
362
+ - Covalent ligands.
363
+ - Bonded metal-center parameterization and MCPB-like workflows.
364
+ - ORCA and Multiwfn backends.
365
+ - mmCIF input.
366
+ - Automatic loop modeling.
367
+ - Production minimization or MD.
@@ -0,0 +1,115 @@
1
+ # Contributing
2
+
3
+ ## Setup
4
+
5
+ ```bash
6
+ mamba env create -f environment.yml
7
+ conda activate mdprep
8
+ pip install -e .
9
+ mdprep selftest --quick
10
+ ```
11
+
12
+ For packaging and lint tooling, use `environment-dev.yml` or install the
13
+ `dev` extra in a suitable environment.
14
+
15
+ ## Tests
16
+
17
+ Default tests must not require AmberTools, xTB, PropKa, PySCF, ParmEd, or
18
+ OpenMM:
19
+
20
+ ```bash
21
+ pytest -q
22
+ python -m mdprep.cli config-check examples/*.yaml
23
+ python -m mdprep.cli selftest --quick
24
+ ```
25
+
26
+ External tests must skip cleanly when optional tools are unavailable:
27
+
28
+ ```bash
29
+ pytest -q -m "external"
30
+ pytest -q -m "external or ambertools or tleap or propka or xtb or pyscf or qmmesp"
31
+ ```
32
+
33
+ ## Chemistry Rules
34
+
35
+ - The legacy molecule-conversion toolkit identified by the dedicated ban test
36
+ is intentionally prohibited.
37
+ - Do not add molecule-conversion fallbacks.
38
+ - User overrides always win.
39
+ - Do not silently guess catalytic chemistry, ligand charge, protonation, or
40
+ metal-center behavior.
41
+ - Every chemical decision and every residue rename must be reported.
42
+ - Unsupported chemistry must fail with a clear error.
43
+ - External commands must go through `mdprep.external.runner`.
44
+
45
+ ## QMMESP Rules
46
+
47
+ - MM point charges polarize only the selected target ligand QM density.
48
+ - The RESP/ESP fit is performed only on target ligand atoms.
49
+ - Environment point charges must not be fitted.
50
+ - Environment point charges must not be written to ligand mol2 files.
51
+ - The final Amber system must use final PySCF-fitted mol2 charges, not
52
+ provisional charges.
53
+
54
+ ## Adding Features
55
+
56
+ New user-facing features need docs, tests, examples when practical, and clear
57
+ failure behavior for unsupported chemistry. Keep changes local to the relevant
58
+ workflow stage and avoid broad rewrites unless there is a tested reason.
59
+
60
+ ## Releasing
61
+
62
+ Publishing is automatic and tokenless. `.github/workflows/release.yml` fires
63
+ on a `v*` tag and uploads to PyPI through Trusted Publishing, so no API token
64
+ exists to leak or rotate. PyPI is configured to trust this repository, this
65
+ workflow file by name, and the `pypi` environment; renaming either breaks
66
+ publishing until the publisher at
67
+ <https://pypi.org/manage/project/mdprep/settings/publishing/> is updated.
68
+
69
+ To cut a release:
70
+
71
+ 1. Bump the version in `pyproject.toml` and `src/mdprep/__init__.py`, and in
72
+ the README's first line. `tests/test_packaging_metadata.py` fails if the
73
+ first two disagree.
74
+ 2. Retitle the changelog's `## Unreleased` section to `## <version> - <date>`.
75
+ The workflow refuses a tag with no such heading.
76
+ 3. Update the `mdprep[md,qm]==` pin in `examples/*.ipynb` and the assertion in
77
+ `tests/test_colab_smoke_notebook.py`. The web builder installs from git
78
+ master and needs no bump.
79
+ 4. Execute the official notebook end to end (below) and fix whatever it
80
+ finds: it is what students run, and nothing else exercises it whole.
81
+ 5. Merge, then `git tag -a vX.Y.Z` and push the tag.
82
+
83
+ The workflow then refuses a tag that does not match the version in the tree,
84
+ builds, checks that the sdist carries the project and nothing that was lying
85
+ in the working tree, installs the wheel and runs `mdprep selftest --quick`
86
+ from it, publishes to PyPI, and attaches the same two files to the GitHub
87
+ release -- creating one from the changelog section if you have not written
88
+ one by hand.
89
+
90
+ Use semantic versioning against the *manifest*, not just the API: a change
91
+ that makes an existing manifest stop validating is breaking, whatever it did
92
+ to the Python surface.
93
+
94
+ ### Executing the official notebook outside Colab
95
+
96
+ `examples/mdprep_colab.ipynb` runs anywhere with a Linux GPU. Its uploads and
97
+ installs are redirected by environment variables, so a Python with mdprep,
98
+ `pymol-open-source-whl`, `py3Dmol`, `pandas`, `matplotlib` and `nbclient`
99
+ can execute it against a micromamba runtime built once:
100
+
101
+ ```bash
102
+ MDPREP_COLAB_PREFIX=/scratch/colab \
103
+ MDPREP_SKIP_KERNEL_INSTALL=1 \
104
+ MDPREP_SPEC=$PWD \
105
+ MDPREP_TEST_UPLOAD_MODEL=/path/to/predicted_model.cif \
106
+ MDPREP_TEST_UPLOAD_BUNDLE=/path/to/mdprep-bundle.zip \
107
+ python -c "import nbformat; from nbclient import NotebookClient; \
108
+ nb = nbformat.read('examples/mdprep_colab.ipynb', 4); \
109
+ NotebookClient(nb, timeout=5400).execute(); nbformat.write(nb, 'executed.ipynb')"
110
+ ```
111
+
112
+ `MDPREP_COLAB_PREFIX` stands in for `/content` (micromamba goes in its `bin/`,
113
+ the environment in `mamba-root/`), and `MDPREP_TEST_EXAMPLE_DIR=examples`
114
+ makes the SyrB2 example read the manifest from the checkout instead of GitHub.
115
+
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: mdprep
3
- Version: 0.2.0
3
+ Version: 0.4.0
4
4
  Summary: Reproducible Amber preparation for proteins, ligands, metal centers, and OpenMM MD.
5
5
  Project-URL: Homepage, https://github.com/miqueleg/mdprep
6
6
  Project-URL: Issues, https://github.com/miqueleg/mdprep/issues
@@ -19,13 +19,17 @@ Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
19
19
  Classifier: Topic :: Scientific/Engineering :: Chemistry
20
20
  Requires-Python: >=3.11
21
21
  Requires-Dist: numpy>=1.24
22
- Requires-Dist: pandas>=2
23
22
  Requires-Dist: pydantic-settings>=2
24
23
  Requires-Dist: pydantic>=2
25
24
  Requires-Dist: pyyaml>=6
26
25
  Requires-Dist: rich>=13
27
- Requires-Dist: scipy>=1.10
28
26
  Requires-Dist: typer>=0.12
27
+ Provides-Extra: all
28
+ Requires-Dist: openmm>=8.1; extra == 'all'
29
+ Requires-Dist: parmed>=4.2; extra == 'all'
30
+ Requires-Dist: pdbfixer>=1.9; extra == 'all'
31
+ Requires-Dist: pyscf>=2.6; extra == 'all'
32
+ Requires-Dist: rdkit>=2023.3; extra == 'all'
29
33
  Provides-Extra: dev
30
34
  Requires-Dist: build>=1; extra == 'dev'
31
35
  Requires-Dist: mypy>=1.10; extra == 'dev'
@@ -34,8 +38,11 @@ Requires-Dist: ruff>=0.6; extra == 'dev'
34
38
  Requires-Dist: twine>=5; extra == 'dev'
35
39
  Provides-Extra: docs
36
40
  Requires-Dist: mkdocs>=1.6; extra == 'docs'
41
+ Provides-Extra: ligands
42
+ Requires-Dist: rdkit>=2023.3; extra == 'ligands'
37
43
  Provides-Extra: md
38
44
  Requires-Dist: openmm>=8.1; extra == 'md'
45
+ Requires-Dist: pdbfixer>=1.9; extra == 'md'
39
46
  Provides-Extra: qm
40
47
  Requires-Dist: parmed>=4.2; extra == 'qm'
41
48
  Requires-Dist: pyscf>=2.6; extra == 'qm'
@@ -45,7 +52,7 @@ Description-Content-Type: text/markdown
45
52
 
46
53
  # mdprep
47
54
 
48
- `mdprep` 0.2.0 prepares reproducible Amber molecular-dynamics systems from a
55
+ `mdprep` 0.4.0 prepares reproducible Amber molecular-dynamics systems from a
49
56
  PDB structure and a validated YAML manifest. It supports standard proteins,
50
57
  independent ligands and cofactors, explicit metal models, optional active-site
51
58
  QM/MM refinement, final `tleap` assembly, validation, and an optional OpenMM
@@ -65,6 +72,10 @@ recorded in the output reports.
65
72
  PySCF gas-phase RESP, or electrostatically embedded PySCF QMMESP charges.
66
73
  - Amber nonbonded metal models or bonded MCPB.py models with explicit
67
74
  coordinating atoms, charges, and multiplicities.
75
+ - Dimers, trimers, tetramers: every protein chain in one system. Copies of one
76
+ protein can share parameters -- asked about once, matched residue for
77
+ residue by sequence and position rather than number, and a bonded metal site
78
+ fitted once and reused in every copy ([docs/oligomers.md](docs/oligomers.md)).
68
79
  - MCPB Seminario Hessians from PySCF, GFN2-xTB, g-xTB, or MACE-POLAR-1;
69
80
  PySCF supplies the embedded large-model ESP/RESP calculation.
70
81
  - Optional ASH/OpenMM active-site QM/MM refinement before final
@@ -73,6 +84,11 @@ recorded in the output reports.
73
84
  topology, coordinate, charge, and optional OpenMM energy validation.
74
85
  - Optional Roe–Brooks OpenMM minimization, heating, density equilibration, and
75
86
  manifest-sized production MD with GPU-first/CPU-fallback execution.
87
+ - Predicted models: the closest X-ray structure from the RCSB, and its crystal
88
+ waters transplanted onto the model with PyMOL -- a water on the metal moves
89
+ with it.
90
+ - An official Colab notebook that prepares, equilibrates, and shows every step:
91
+ charges, metal-site parameters, the equilibration, the trajectory.
76
92
 
77
93
  ## Installation
78
94
 
@@ -105,9 +121,16 @@ Start from a standard protein PDB:
105
121
 
106
122
  ```bash
107
123
  mdprep inspect input.pdb
108
- mdprep init input.pdb -o system.yaml
124
+ mdprep plan input.pdb # what must you decide?
125
+ mdprep init input.pdb --interactive -o system.yaml
109
126
  ```
110
127
 
128
+ `mdprep plan` lists only the manifest decisions this structure actually
129
+ requires, and `--interactive` asks them and writes a validated manifest. See
130
+ [Guided manifest generation](docs/guided_manifests.md). The non-interactive
131
+ `mdprep init input.pdb -o system.yaml` still writes the commented starter
132
+ manifest.
133
+
111
134
  A minimal protein-only `system.yaml` is:
112
135
 
113
136
  ```yaml
@@ -177,6 +200,28 @@ Relative paths are resolved from the manifest directory. Unknown heterogens
177
200
  are not deleted or guessed: configure them under `ligands` or `metals`, or
178
201
  explicitly request their removal.
179
202
 
203
+ For a guided workflow, use the [web input builder](https://miqueleg.github.io/mdprep/):
204
+ it shows the structure in 3D, asks only the questions your structure needs, and
205
+ writes a validated manifest and a bundle. Then open the
206
+ [official Colab notebook](https://colab.research.google.com/github/miqueleg/mdprep/blob/master/examples/mdprep_colab.ipynb)
207
+ ([`examples/mdprep_colab.ipynb`](examples/mdprep_colab.ipynb)), upload the
208
+ bundle, and it installs what the manifest needs, prepares the system,
209
+ equilibrates it, and lets you investigate every step: the structure at each
210
+ stage, the protonation states, the charge on every atom, the metal site's
211
+ force constants, how the box equilibrated, and the MD trajectory.
212
+
213
+ No crystal structure of your protein? Predict the complex with its cofactors
214
+ (Boltz or AlphaFold3 in ColabFold), then let mdprep find the closest X-ray
215
+ structure and bring its crystal waters across -- including a water bound to
216
+ the metal, which a prediction never has:
217
+
218
+ ```bash
219
+ mdprep closest-xray model.cif
220
+ mdprep transplant-waters model.cif --reference 2FCT
221
+ ```
222
+
223
+ See [Predicted structures](docs/predicted_structures.md).
224
+
180
225
  ## Common workflows
181
226
 
182
227
  Generate a starter manifest using PropKa and ff19SB/OPC:
@@ -215,12 +260,18 @@ specified in steps in the manifest.
215
260
 
216
261
  | Task | Documentation | Example |
217
262
  | --- | --- | --- |
263
+ | Generating a manifest | [Guided manifest generation](docs/guided_manifests.md) | `mdprep plan`, `mdprep init --interactive` |
264
+ | Generating one in a browser | [Web input builder](web/README.md) | `python web/build.py` |
218
265
  | Manifest fields | [Manifest reference](docs/manifest_reference.md) | [All examples](examples/README.md) |
219
266
  | Protonation and histidines | [Protonation](docs/protonation.md) | `examples/02_manual_catalytic_protonation.yaml` |
220
267
  | Ligands, AM1-BCC, RESP, QMMESP | [Ligands](docs/ligands.md) and [QMMESP](docs/qmmesp_pyscf.md) | `examples/03_multi_ligand_am1bcc.yaml`, `04_qmmesp_pyscf_ligand.yaml` |
221
268
  | Metal centers and MCPB.py | [Metal centers](docs/metals.md) | `examples/08_nonbonded_zinc_1264.yaml`, `09_bonded_zinc_mcpb_prepare.yaml` |
222
269
  | Active-site QM/MM refinement | [QM/MM refinement](docs/qmmm_refinement.md) | `examples/10_qmmm_refinement_ash.yaml` |
223
270
  | Roe–Brooks OpenMM MD | [Molecular dynamics](docs/molecular_dynamics.md) | `examples/15_roe_brooks_openmm.yaml` |
271
+ | Predicted models: closest X-ray, crystal waters | [Predicted structures](docs/predicted_structures.md) | `mdprep closest-xray`, `mdprep transplant-waters` |
272
+ | A water bound to a metal | [Metal centers](docs/metals.md#waters-bound-in-a-metal-site) | `examples/17_syrb2_bound_water_mcpb.yaml` |
273
+ | Preparing, running and investigating in Colab | [Colab example notes](examples/README.md) | `examples/mdprep_colab.ipynb` |
274
+ | Guided Colab builder (legacy) | [Colab example notes](examples/README.md) | `examples/mdprep_interactive_colab.ipynb` |
224
275
  | Complete Fe(III) workflow | [7E07 tutorial](examples/tutorials/7E07_bonded_fe3/README.md) | `examples/tutorials/7E07_bonded_fe3/system.yaml` |
225
276
 
226
277
  All public example manifests are schema-validated in the test suite.
@@ -243,10 +294,12 @@ charge model, protonation, force field, QM method, or metal model.
243
294
 
244
295
  ## Current limitations
245
296
 
246
- Version 0.2.0 does not support noncanonical amino acids inside peptide chains,
247
- covalent ligands, mmCIF input, automatic loop modeling, ORCA, Multiwfn,
248
- multiple independent bonded MCPB sites, or multi-chain MCPB protein inputs.
249
- Unsupported chemistry fails explicitly.
297
+ mdprep does not support noncanonical amino acids inside peptide chains,
298
+ covalent ligands, automatic loop modeling (a missing loop is left as two
299
+ termini), a metal-bound hydroxide, ORCA, Multiwfn, more than one independently
300
+ fitted bonded MCPB site (copies of one site in an oligomer share a single
301
+ fit), or a bonded MCPB site bound by two chains. Unsupported chemistry fails
302
+ explicitly.
250
303
 
251
304
  ## Development and release checks
252
305