abmptools 2.0.0__tar.gz → 2.2.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.
- {abmptools-2.0.0/abmptools.egg-info → abmptools-2.2.0}/PKG-INFO +18 -1
- {abmptools-2.0.0 → abmptools-2.2.0}/README.md +5 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/addsolvfrag.py +10 -2
- abmptools-2.2.0/abmptools/amorphous/builder.py +466 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/amorphous/mdp_protocol.py +147 -90
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/amorphous/models.py +26 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/amorphous/molecule_prep.py +8 -1
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/amorphous/ndx_writer.py +9 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/amorphous/packing.py +29 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/amorphous/trajectory_ingest.py +71 -2
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/cg/dpd/__init__.py +4 -1
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/cg/dpd/__main__.py +30 -0
- abmptools-2.2.0/abmptools/cg/dpd/aij_assign.py +173 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/cg/dpd/orchestrator.py +7 -2
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/cg/dpd/udf_writer.py +12 -4
- abmptools-2.2.0/abmptools/cg/dpd/udf_writer_udfm.py +249 -0
- abmptools-2.2.0/abmptools/formulation/analysis/__init__.py +155 -0
- abmptools-2.2.0/abmptools/formulation/analysis/aggregate_transition.py +297 -0
- abmptools-2.2.0/abmptools/formulation/analysis/contact_map.py +253 -0
- abmptools-2.2.0/abmptools/formulation/analysis/plots.py +214 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/formulation/builder.py +355 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/formulation/cli.py +56 -7
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/formulation/models.py +6 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/formulation/ndx.py +7 -2
- abmptools-2.2.0/abmptools/formulation/peptide_atomistic_openff.py +245 -0
- abmptools-2.2.0/abmptools/formulation/small_molecule_openff.py +117 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/formulation/topology.py +81 -0
- abmptools-2.2.0/abmptools/formulation/topology_openff.py +571 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/fragmenter/cg_segmenter/__init__.py +10 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/fragmenter/cg_segmenter/__main__.py +51 -4
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/fragmenter/cg_segmenter/dpdgen_exporter.py +21 -8
- abmptools-2.2.0/abmptools/fragmenter/cg_segmenter/fcews_export.py +316 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/fragmenter/cg_segmenter/notebook_ui.py +5 -4
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/fragmenter/cg_segmenter/orchestrator.py +38 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/fragmenter/expand_to_system.py +40 -36
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/gro2udf/top_exporter.py +8 -3
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/gro2udf/udf_writer.py +12 -9
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/hbond/__init__.py +16 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/hbond/analyzer.py +104 -5
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/hbond/cli.py +33 -0
- abmptools-2.2.0/abmptools/hbond/distance_dist.py +322 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/molcalc.py +100 -5
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/setfmo.py +2 -1
- abmptools-2.2.0/abmptools/trajectory/__init__.py +41 -0
- abmptools-2.2.0/abmptools/trajectory/__main__.py +3 -0
- abmptools-2.2.0/abmptools/trajectory/cli.py +151 -0
- abmptools-2.2.0/abmptools/trajectory/postprocess.py +322 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/udf_io.py +113 -19
- abmptools-2.2.0/abmptools/udfcharge/__init__.py +28 -0
- abmptools-2.2.0/abmptools/udfcharge/__main__.py +63 -0
- abmptools-2.2.0/abmptools/udfcharge/core.py +279 -0
- {abmptools-2.0.0 → abmptools-2.2.0/abmptools.egg-info}/PKG-INFO +18 -1
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools.egg-info/SOURCES.txt +15 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools.egg-info/requires.txt +13 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/pyproject.toml +24 -1
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_builder_integration.py +11 -5
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_builder_mocked.py +8 -6
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_charge_method.py +15 -4
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_formulation_ndx.py +23 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_mdp_protocol.py +27 -31
- abmptools-2.2.0/tests/test_trajectory_postprocess.py +287 -0
- abmptools-2.0.0/abmptools/amorphous/builder.py +0 -260
- abmptools-2.0.0/abmptools/formulation/analysis/__init__.py +0 -61
- abmptools-2.0.0/abmptools/formulation/analysis/aggregate_transition.py +0 -153
- abmptools-2.0.0/abmptools/formulation/analysis/contact_map.py +0 -115
- abmptools-2.0.0/abmptools/formulation/analysis/plots.py +0 -66
- {abmptools-2.0.0 → abmptools-2.2.0}/LICENSE +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/NOTICE +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/__init__.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/abinit_io.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/ajf2config.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/ajfserial.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/amorphous/__init__.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/amorphous/__main__.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/amorphous/cli.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/amorphous/density.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/amorphous/parameterizer.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/amorphous/pubchem.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/amorphous/system_model_adapter.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/anlfmo.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/cg/__init__.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/cg/dpd/aij_io.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/cg/dpd/calc_sett_io.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/cg/dpd/dpm_writer.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/cg/dpd/models.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/cg/dpd/monomer_io.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/cg/dpd/notebook_ui.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/cg/membrane/__init__.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/cg/membrane/__main__.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/cg/membrane/_subprocess.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/cg/membrane/builder.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/cg/membrane/cli.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/cg/membrane/forcefield_check.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/cg/membrane/insane_runner.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/cg/membrane/mdp_templates.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/cg/membrane/models.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/cg/membrane/pmf.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/cg/membrane/pulling.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/cg/membrane/system_packer.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/cg/membrane/topology_composer.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/cg/membrane/umbrella.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/cg/peptide/__init__.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/cg/peptide/__main__.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/cg/peptide/_subprocess.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/cg/peptide/builder.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/cg/peptide/cli.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/cg/peptide/forcefield_check.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/cg/peptide/martinize_runner.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/cg/peptide/mdp_templates.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/cg/peptide/models.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/cg/peptide/peptide_atomistic.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/cg/peptide/system_packer.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/cg/peptide/top_writer.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/cg/peptide/water_box.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/convertcpf.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/core/__init__.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/core/system_model.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/cpf2ifielist.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/cpfmanager.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/crystal/__init__.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/crystal/__main__.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/crystal/_subprocess.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/crystal/atom_distance.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/crystal/builder.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/crystal/cif_engine_ase.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/crystal/cif_engine_legacy.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/crystal/cli.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/crystal/forcefield_check.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/crystal/job_templates.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/crystal/legacy/__init__.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/crystal/models.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/crystal/postproc.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/f90/bin/readifiepiedalib.so +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/formulation/__init__.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/formulation/__main__.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/formulation/_subprocess.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/formulation/analysis/hbond.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/formulation/analysis/sasa.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/formulation/analysis/secondary_structure.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/formulation/mdp_templates.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/formulation/packer.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/formulation/peptide_atomistic.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/formulation/small_molecule.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/formulation/umbrella_release.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/fragmenter/__init__.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/fragmenter/__main__.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/fragmenter/auto_split.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/fragmenter/cg_segmenter/cap_attach.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/fragmenter/cg_segmenter/chain_splitter.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/fragmenter/cg_segmenter/exporter.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/fragmenter/cg_segmenter/models.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/fragmenter/cg_segmenter/ring_detector.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/fragmenter/cut_apply.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/fragmenter/grouping.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/fragmenter/headless_io.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/fragmenter/models.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/fragmenter/notebook_ui.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/fragmenter/pdb_loader.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/fragmenter/polymer.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/generate_difie.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/generateajf.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/genesis/__init__.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/genesis/grest/__init__.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/genesis/grest/__main__.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/genesis/grest/_subprocess.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/genesis/grest/analysis.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/genesis/grest/builder.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/genesis/grest/cli.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/genesis/grest/forcefield_check.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/genesis/grest/grest_runner.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/genesis/grest/inp_writer.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/genesis/grest/models.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/genesis/grest/replica_temperatures.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/genesis/grest/rest_selection.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/genesis/grest/system_builder.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/genesis/mmgbsa/__init__.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/genesis/mmgbsa/__main__.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/genesis/mmgbsa/_subprocess.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/genesis/mmgbsa/analysis.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/genesis/mmgbsa/builder.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/genesis/mmgbsa/cli.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/genesis/mmgbsa/forcefield_check.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/genesis/mmgbsa/gbsa_runner.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/genesis/mmgbsa/inp_writer.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/genesis/mmgbsa/ligand_parameterize.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/genesis/mmgbsa/models.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/genesis/mmgbsa/pdb_splitter.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/genesis/mmgbsa/system_builder.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/geomopt/__init__.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/geomopt/mace_optimizer.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/geomopt/openff_openmm_minimizer.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/geomopt/pyscf_optimizer.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/getcharge.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/getifiepieda.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/gro2udf/__init__.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/gro2udf/__main__.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/gro2udf/cli.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/gro2udf/default_template.udf +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/gro2udf/default_template_cognac101.udf +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/gro2udf/exporter.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/gro2udf/gro_adapter.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/gro2udf/gro_parser.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/gro2udf/mdp_parser.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/gro2udf/top_adapter.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/gro2udf/top_model.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/gro2udf/top_parser.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/gro2udf/trajectory_io.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/hbond/__main__.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/hbond/bdf_reader.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/hbond/classifier.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/hbond/colorizer.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/hbond/func_tags.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/hbond/functional_groups.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/hbond/hbond_detector.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/hbond/lifetime.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/hbond/notebook_ui.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/hbond/pair_type_stats.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/log2config.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/log2cpf.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/logmanager.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/membrane/__init__.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/membrane/bilayer.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/membrane/builder.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/membrane/lipid_info.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/membrane/mdp_us_protocol.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/membrane/models.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/membrane/parameterize_amber.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/membrane/parameterize_charmm.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/membrane/pmf.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/membrane/pulling.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/membrane/topology_sanity.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/membrane/umbrella.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/mol_io.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/pdb2fmo.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/pdb_io.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/pdbmodify.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/readcif.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/udf2fmo.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/udf2gro/__init__.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/udf2gro/__main__.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/udf2gro/cli.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/udf2gro/exporter.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/udf2gro/gromacs/__init__.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/udf2gro/gromacs/writers/__init__.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/udf2gro/gromacs/writers/_validator.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/udf2gro/gromacs/writers/gro_writer.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/udf2gro/gromacs/writers/itp_writer.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/udf2gro/gromacs/writers/mdp_writer.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/udf2gro/gromacs/writers/top_writer.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/udf2gro/udf_adapter.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/udfcreate.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/udfcreate_v2.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools/udfrm_io.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools.egg-info/dependency_links.txt +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools.egg-info/entry_points.txt +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/abmptools.egg-info/top_level.txt +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/setup.cfg +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/setup.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_abinit_io.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_amorphous_models.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_anlfmo.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_cg_membrane_builder_mocked.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_cg_membrane_cli.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_cg_membrane_forcefield_check.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_cg_membrane_insane_runner.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_cg_membrane_integration.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_cg_membrane_mdp.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_cg_membrane_models.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_cg_membrane_packer.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_cg_membrane_pmf.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_cg_membrane_pulling.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_cg_membrane_topology_composer.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_cg_membrane_umbrella.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_cg_peptide_atomistic.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_cg_peptide_builder_mocked.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_cg_peptide_cli.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_cg_peptide_forcefield_check.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_cg_peptide_integration.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_cg_peptide_martinize_runner.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_cg_peptide_mdp.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_cg_peptide_models.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_cg_peptide_packer.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_cg_peptide_subprocess.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_cg_peptide_topwriter.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_cg_peptide_water_box.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_cli_scripts.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_cpfmanager.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_crystal_atom_distance.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_crystal_builder.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_crystal_cif_ase.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_crystal_cif_legacy.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_crystal_cli.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_crystal_job_templates.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_crystal_models.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_crystal_numeric_regression.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_crystal_regression.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_density.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_formulation_analysis.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_formulation_builder.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_formulation_mdp.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_formulation_models.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_formulation_packer.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_formulation_peptide_atomistic.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_formulation_small_molecule.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_formulation_topology.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_formulation_umbrella_release.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_getifiepieda.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_grest_analysis_mocked.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_grest_builder_mocked.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_grest_cli.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_grest_inp_writer.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_grest_integration.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_grest_models.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_grest_replica_temperatures.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_grest_rest_selection.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_grest_system_builder.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_gro_adapter.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_gro_parser.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_gro_writer.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_interchange_adapter.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_logmanager.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_mdp_parser.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_mdp_writer.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_membrane_charmm_translate.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_membrane_mixed_lipid.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_membrane_topology_sanity.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_mmgbsa_analysis.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_mmgbsa_builder_mocked.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_mmgbsa_cli.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_mmgbsa_forcefield_check.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_mmgbsa_inp_writer.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_mmgbsa_integration.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_mmgbsa_models.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_mmgbsa_pdb_splitter.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_mmgbsa_system_builder.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_mol_io.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_molcalc.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_ndx_writer.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_parameterizer.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_pdb_io.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_pubchem.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_pyscf_optimizer.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_pyscf_parsers.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_read_ifie_hf_fallback.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_readcif.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_regression.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_setfmo.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_system_model.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_system_model_extensions.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_top_exporter_frames_override.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_top_model.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_top_parser.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_top_writer.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_trajectory_ingest.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_udf_io.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_udfcreate.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_udfcreate_v2.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_udfcreate_v2_byte_equivalence.py +0 -0
- {abmptools-2.0.0 → abmptools-2.2.0}/tests/test_udfrm_io.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: abmptools
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.2.0
|
|
4
4
|
Summary: Pre/post-processing and analysis toolkit for ABINIT-MP Fragment Molecular Orbital calculations
|
|
5
5
|
Author-email: Koji Okuwaki <koujioku81@gmail.com>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -59,6 +59,18 @@ Provides-Extra: formulation-analysis
|
|
|
59
59
|
Requires-Dist: MDAnalysis<3.0,>=2.6; extra == "formulation-analysis"
|
|
60
60
|
Requires-Dist: networkx>=3.0; extra == "formulation-analysis"
|
|
61
61
|
Requires-Dist: matplotlib>=3.5; extra == "formulation-analysis"
|
|
62
|
+
Provides-Extra: formulation-openff
|
|
63
|
+
Requires-Dist: openff-toolkit>=0.14.0; extra == "formulation-openff"
|
|
64
|
+
Requires-Dist: openff-interchange>=0.3.0; extra == "formulation-openff"
|
|
65
|
+
Requires-Dist: openff-amber-ff-ports>=0.0.3; extra == "formulation-openff"
|
|
66
|
+
Requires-Dist: openff-nagl>=0.3; extra == "formulation-openff"
|
|
67
|
+
Requires-Dist: openff-nagl-models>=0.1; extra == "formulation-openff"
|
|
68
|
+
Requires-Dist: openmm>=8.0; extra == "formulation-openff"
|
|
69
|
+
Requires-Dist: pdbfixer>=1.9; extra == "formulation-openff"
|
|
70
|
+
Requires-Dist: rdkit-pypi>=2022.09; extra == "formulation-openff"
|
|
71
|
+
Requires-Dist: matplotlib>=3.5; extra == "formulation-openff"
|
|
72
|
+
Requires-Dist: PeptideBuilder>=1.1; extra == "formulation-openff"
|
|
73
|
+
Requires-Dist: biopython>=1.79; extra == "formulation-openff"
|
|
62
74
|
Provides-Extra: geomopt
|
|
63
75
|
Requires-Dist: pyscf; extra == "geomopt"
|
|
64
76
|
Requires-Dist: ase; extra == "geomopt"
|
|
@@ -109,6 +121,7 @@ A Python toolkit for pre-processing, post-processing, and analysis of Fragment M
|
|
|
109
121
|
|
|
110
122
|
- **udf2gro**: Convert OCTA UDF files to GROMACS format (`.gro`, `.top`, `.mdp`, `.itp`)
|
|
111
123
|
- **gro2udf**: Convert GROMACS files to OCTA UDF format (supports `--from-top` mode)
|
|
124
|
+
- **udfcharge**: Transfer per-atom partial charges from a single-molecule UDF to every same-named molecule in a bulk UDF
|
|
112
125
|
|
|
113
126
|
### Geometry Optimization (`geomopt`)
|
|
114
127
|
|
|
@@ -300,6 +313,9 @@ python -m abmptools.udf2gro.cli -i system.udf -o output
|
|
|
300
313
|
# Convert GROMACS to UDF
|
|
301
314
|
python -m abmptools.gro2udf.cli -i system.gro -t system.top -o output.udf
|
|
302
315
|
|
|
316
|
+
# Transfer charges from a single-molecule UDF to all same-named molecules in a bulk UDF
|
|
317
|
+
python -m abmptools.udfcharge --template mol.udf --bulk bulk.udf --out bulk_charged.udf
|
|
318
|
+
|
|
303
319
|
# Build an amorphous mixture from SMILES (50 ketoprofen molecules, density 0.8 g/cm^3)
|
|
304
320
|
python -m abmptools.amorphous --smiles "OC(=O)C(C)c1cccc(C(=O)c2ccccc2)c1" \
|
|
305
321
|
--name ketoprofen --n_mol 50 --density 0.8 --output_dir ./ketoprofen
|
|
@@ -349,6 +365,7 @@ Use `-h` with any module for full option details.
|
|
|
349
365
|
- **[Developer Quickstart](docs/dev_quickstart.md)** — Setup and code conventions
|
|
350
366
|
- **[I/O Spec](docs/io_spec.md)** — File format specifications
|
|
351
367
|
- **[gro2udf](docs/gro2udf.md)** / **[udf2gro](docs/udf2gro.md)** — GROMACS ↔ OCTA conversion
|
|
368
|
+
- **[udfcharge](docs/udfcharge.md)** / **[tutorial_udfcharge](docs/tutorial_udfcharge.md)** — single-molecule → bulk UDF charge transfer
|
|
352
369
|
- **[geomopt](docs/geomopt.md)** / **[amorphous](docs/amorphous.md)** — Optimization and structure building
|
|
353
370
|
- **[membrane](docs/membrane.md)** / **[tutorial_membrane_us](docs/tutorial_membrane_us.md)** — Peptide-bilayer umbrella-sampling PMF (AA, CHARMM36 / Lipid21)
|
|
354
371
|
- **[cg_membrane](docs/cg_membrane.md)** / **[tutorial_cg_membrane_us](docs/tutorial_cg_membrane_us.md)** — Martini 3 peptide-bilayer PMF (CG, 30-100× faster than AA, KGG-POPC smoke 5 min / production 45 min)
|
|
@@ -37,6 +37,7 @@ A Python toolkit for pre-processing, post-processing, and analysis of Fragment M
|
|
|
37
37
|
|
|
38
38
|
- **udf2gro**: Convert OCTA UDF files to GROMACS format (`.gro`, `.top`, `.mdp`, `.itp`)
|
|
39
39
|
- **gro2udf**: Convert GROMACS files to OCTA UDF format (supports `--from-top` mode)
|
|
40
|
+
- **udfcharge**: Transfer per-atom partial charges from a single-molecule UDF to every same-named molecule in a bulk UDF
|
|
40
41
|
|
|
41
42
|
### Geometry Optimization (`geomopt`)
|
|
42
43
|
|
|
@@ -228,6 +229,9 @@ python -m abmptools.udf2gro.cli -i system.udf -o output
|
|
|
228
229
|
# Convert GROMACS to UDF
|
|
229
230
|
python -m abmptools.gro2udf.cli -i system.gro -t system.top -o output.udf
|
|
230
231
|
|
|
232
|
+
# Transfer charges from a single-molecule UDF to all same-named molecules in a bulk UDF
|
|
233
|
+
python -m abmptools.udfcharge --template mol.udf --bulk bulk.udf --out bulk_charged.udf
|
|
234
|
+
|
|
231
235
|
# Build an amorphous mixture from SMILES (50 ketoprofen molecules, density 0.8 g/cm^3)
|
|
232
236
|
python -m abmptools.amorphous --smiles "OC(=O)C(C)c1cccc(C(=O)c2ccccc2)c1" \
|
|
233
237
|
--name ketoprofen --n_mol 50 --density 0.8 --output_dir ./ketoprofen
|
|
@@ -277,6 +281,7 @@ Use `-h` with any module for full option details.
|
|
|
277
281
|
- **[Developer Quickstart](docs/dev_quickstart.md)** — Setup and code conventions
|
|
278
282
|
- **[I/O Spec](docs/io_spec.md)** — File format specifications
|
|
279
283
|
- **[gro2udf](docs/gro2udf.md)** / **[udf2gro](docs/udf2gro.md)** — GROMACS ↔ OCTA conversion
|
|
284
|
+
- **[udfcharge](docs/udfcharge.md)** / **[tutorial_udfcharge](docs/tutorial_udfcharge.md)** — single-molecule → bulk UDF charge transfer
|
|
280
285
|
- **[geomopt](docs/geomopt.md)** / **[amorphous](docs/amorphous.md)** — Optimization and structure building
|
|
281
286
|
- **[membrane](docs/membrane.md)** / **[tutorial_membrane_us](docs/tutorial_membrane_us.md)** — Peptide-bilayer umbrella-sampling PMF (AA, CHARMM36 / Lipid21)
|
|
282
287
|
- **[cg_membrane](docs/cg_membrane.md)** / **[tutorial_cg_membrane_us](docs/tutorial_cg_membrane_us.md)** — Martini 3 peptide-bilayer PMF (CG, 30-100× faster than AA, KGG-POPC smoke 5 min / production 45 min)
|
|
@@ -156,7 +156,7 @@ def get_args():
|
|
|
156
156
|
)
|
|
157
157
|
|
|
158
158
|
parser.add_argument('-ma', '--manual',
|
|
159
|
-
help='manual table',
|
|
159
|
+
help='manual fragment table (already the default; kept for compatibility)',
|
|
160
160
|
action='store_true',
|
|
161
161
|
)
|
|
162
162
|
|
|
@@ -217,7 +217,13 @@ def main():
|
|
|
217
217
|
aobj.ajf_method = args.method
|
|
218
218
|
aobj.ajf_basis_set = args.basisset
|
|
219
219
|
aobj.abinit_ver = args.ajfversion
|
|
220
|
-
|
|
220
|
+
# addsolvfrag は「溶質を手動フラグメント分割した上で、スナップショット
|
|
221
|
+
# ごとの溶媒フラグメントをテーブルに追加する」ためのツール。よって
|
|
222
|
+
# 出力 AJF は常に AutoFrag='OFF' とし、溶質テンプレートの &FRAGMENT に
|
|
223
|
+
# 溶媒フラグメントを連結したテーブルを書き出す必要がある。
|
|
224
|
+
# autofrag=True にすると abinit_io 側で AutoFrag='ON' かつ &FRAGMENT が
|
|
225
|
+
# 空になり、本ツールの目的を満たさないため False を既定とする。
|
|
226
|
+
aobj.autofrag = False
|
|
221
227
|
aobj.piedaflag = args.nopieda
|
|
222
228
|
aobj.cpfflag = args.nocpf
|
|
223
229
|
aobj.cpfver = args.cpfver
|
|
@@ -241,6 +247,8 @@ def main():
|
|
|
241
247
|
aobj.mllimit = args.mllimit
|
|
242
248
|
|
|
243
249
|
|
|
250
|
+
# -ma/--manual は後方互換のため残置。autofrag は既定で False(手動分割)
|
|
251
|
+
# のため、本フラグは明示的に手動分割を指定するだけで挙動は変わらない。
|
|
244
252
|
if args.manual:
|
|
245
253
|
aobj.autofrag = False
|
|
246
254
|
|
|
@@ -0,0 +1,466 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
abmptools.amorphous.builder
|
|
4
|
+
-----------------------------
|
|
5
|
+
Orchestrator: integrates all stages of amorphous structure building.
|
|
6
|
+
|
|
7
|
+
Data flow:
|
|
8
|
+
SMILES/SDF → molecule_prep → density → packing → parameterizer → mdp/ndx
|
|
9
|
+
"""
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import json
|
|
13
|
+
import logging
|
|
14
|
+
import os
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
from typing import Any, Dict, List, Optional
|
|
17
|
+
|
|
18
|
+
from ..core.system_model import AnnealProtocol
|
|
19
|
+
from .models import BuildConfig, ComponentSpec
|
|
20
|
+
from .density import estimate_box_size_nm, weight_fractions_to_counts
|
|
21
|
+
from .molecule_prep import (
|
|
22
|
+
prepare_molecule,
|
|
23
|
+
get_molecular_weight,
|
|
24
|
+
write_single_mol_pdb,
|
|
25
|
+
)
|
|
26
|
+
from .packing import run_packmol
|
|
27
|
+
from .parameterizer import create_interchange, export_gromacs
|
|
28
|
+
from .mdp_protocol import (
|
|
29
|
+
write_all_mdp,
|
|
30
|
+
write_run_script,
|
|
31
|
+
write_udf_export_script,
|
|
32
|
+
write_wrap_script,
|
|
33
|
+
)
|
|
34
|
+
from .ndx_writer import write_ndx
|
|
35
|
+
|
|
36
|
+
logger = logging.getLogger(__name__)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class AmorphousBuilder:
|
|
40
|
+
"""Build an amorphous multi-component system for GROMACS MD.
|
|
41
|
+
|
|
42
|
+
Usage::
|
|
43
|
+
|
|
44
|
+
from abmptools.amorphous import AmorphousBuilder, BuildConfig, ComponentSpec
|
|
45
|
+
|
|
46
|
+
config = BuildConfig(
|
|
47
|
+
components=[
|
|
48
|
+
ComponentSpec(smiles="CCCCC", name="pentane", n_mol=200),
|
|
49
|
+
ComponentSpec(smiles="c1ccccc1", name="benzene", n_mol=50),
|
|
50
|
+
],
|
|
51
|
+
density_g_cm3=0.8,
|
|
52
|
+
temperature=300,
|
|
53
|
+
output_dir="./output",
|
|
54
|
+
)
|
|
55
|
+
builder = AmorphousBuilder(config)
|
|
56
|
+
result = builder.build()
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
def __init__(self, config: BuildConfig) -> None:
|
|
60
|
+
self.config = config
|
|
61
|
+
self._molecules: List[Any] = []
|
|
62
|
+
self._mol_weights: List[float] = []
|
|
63
|
+
self._counts: List[int] = []
|
|
64
|
+
self._box_nm: float = 0.0
|
|
65
|
+
self._pdb_paths: List[str] = []
|
|
66
|
+
|
|
67
|
+
def build(self) -> Dict[str, Any]:
|
|
68
|
+
"""Run the full build pipeline.
|
|
69
|
+
|
|
70
|
+
Returns
|
|
71
|
+
-------
|
|
72
|
+
dict
|
|
73
|
+
Keys: "output_dir", "gro", "top", "ndx", "mdp_files",
|
|
74
|
+
"run_script", "config_json", "box_nm", "counts".
|
|
75
|
+
"""
|
|
76
|
+
cfg = self.config
|
|
77
|
+
out = Path(cfg.output_dir)
|
|
78
|
+
input_dir = out / "input"
|
|
79
|
+
build_dir = out / "build"
|
|
80
|
+
md_dir = out / "md"
|
|
81
|
+
for d in [input_dir, build_dir, md_dir]:
|
|
82
|
+
d.mkdir(parents=True, exist_ok=True)
|
|
83
|
+
|
|
84
|
+
# Save config for reproducibility
|
|
85
|
+
config_json = str(input_dir / "config.json")
|
|
86
|
+
cfg.to_json(config_json)
|
|
87
|
+
|
|
88
|
+
# Stage 1: Prepare molecules
|
|
89
|
+
logger.info("=== Stage 1: Molecule preparation ===")
|
|
90
|
+
self._prepare_molecules(input_dir)
|
|
91
|
+
|
|
92
|
+
# Stage 2: Determine counts and box size
|
|
93
|
+
logger.info("=== Stage 2: Density / box estimation ===")
|
|
94
|
+
self._compute_counts_and_box()
|
|
95
|
+
|
|
96
|
+
# Stage 3: Packmol packing
|
|
97
|
+
logger.info("=== Stage 3: Packmol packing ===")
|
|
98
|
+
mixture_pdb = str(build_dir / "mixture.pdb")
|
|
99
|
+
self._run_packing(mixture_pdb, str(build_dir))
|
|
100
|
+
|
|
101
|
+
# Stage 4: Parameterize with OpenFF
|
|
102
|
+
logger.info("=== Stage 4: OpenFF parameterization ===")
|
|
103
|
+
gro_path = str(build_dir / "system.gro")
|
|
104
|
+
top_path = str(build_dir / "system.top")
|
|
105
|
+
gromacs_files = self._parameterize(mixture_pdb, gro_path, top_path)
|
|
106
|
+
|
|
107
|
+
# Stage 5: Write NDX
|
|
108
|
+
logger.info("=== Stage 5: NDX index groups ===")
|
|
109
|
+
ndx_path = str(build_dir / "system.ndx")
|
|
110
|
+
self._write_ndx(ndx_path)
|
|
111
|
+
|
|
112
|
+
# Stage 5b: position_restraints for trimer cluster center (if frozen
|
|
113
|
+
# atoms specified). freezegrps was tried first but failed Fugaku MPI:
|
|
114
|
+
# LINCS/SETTLE matrix inversion failed (`determinant = -inf`) because
|
|
115
|
+
# hard freeze + DD + rigid water constraints are incompatible. Switch
|
|
116
|
+
# to harmonic position_restraints (k=10000 kJ/mol/nm² default) which
|
|
117
|
+
# plays nice with all constraints and keeps atoms within ~0.01 Å of
|
|
118
|
+
# initial position — functionally equivalent for trimer center fix.
|
|
119
|
+
frozen = list(getattr(self.config, "frozen_atom_indices", []) or [])
|
|
120
|
+
define_posres = None
|
|
121
|
+
if frozen:
|
|
122
|
+
self._add_trimer_posres_to_top(top_path, frozen)
|
|
123
|
+
define_posres = "POSRES_TRIMER"
|
|
124
|
+
|
|
125
|
+
# Stage 6: Write MDP files and run script
|
|
126
|
+
logger.info("=== Stage 6: MDP protocol ===")
|
|
127
|
+
protocol = self._make_protocol()
|
|
128
|
+
tc_grps = self._tc_grps_string()
|
|
129
|
+
mdp_files = write_all_mdp(protocol, str(md_dir), tc_grps=tc_grps,
|
|
130
|
+
define_posres=define_posres)
|
|
131
|
+
run_script = write_run_script(str(md_dir))
|
|
132
|
+
wrap_script = write_wrap_script(str(md_dir))
|
|
133
|
+
udf_script = write_udf_export_script(str(md_dir))
|
|
134
|
+
|
|
135
|
+
logger.info("=== Build complete: %s ===", cfg.output_dir)
|
|
136
|
+
return {
|
|
137
|
+
"output_dir": str(out.resolve()),
|
|
138
|
+
"gro": gromacs_files["gro"],
|
|
139
|
+
"top": gromacs_files["top"],
|
|
140
|
+
"ndx": str(Path(ndx_path).resolve()),
|
|
141
|
+
"mdp_files": mdp_files,
|
|
142
|
+
"run_script": run_script,
|
|
143
|
+
"wrap_script": wrap_script,
|
|
144
|
+
"udf_script": udf_script,
|
|
145
|
+
"config_json": config_json,
|
|
146
|
+
"box_nm": self._box_nm,
|
|
147
|
+
"counts": list(self._counts),
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
# ---- internal stages ----
|
|
151
|
+
|
|
152
|
+
def _prepare_molecules(self, input_dir: Path) -> None:
|
|
153
|
+
"""Prepare OpenFF Molecules and write single-molecule PDBs."""
|
|
154
|
+
for i, comp in enumerate(self.config.components):
|
|
155
|
+
mol = prepare_molecule(
|
|
156
|
+
smiles=comp.smiles,
|
|
157
|
+
sdf_path=comp.sdf_path,
|
|
158
|
+
pdb_path=comp.pdb_path,
|
|
159
|
+
name=comp.name or f"comp_{i}",
|
|
160
|
+
charge_method=self.config.charge_method,
|
|
161
|
+
nagl_model=self.config.nagl_model,
|
|
162
|
+
)
|
|
163
|
+
mw = get_molecular_weight(mol)
|
|
164
|
+
comp.molecular_weight = mw
|
|
165
|
+
if not comp.name:
|
|
166
|
+
comp.name = mol.name
|
|
167
|
+
|
|
168
|
+
pdb_path = str(input_dir / f"component_{i}.pdb")
|
|
169
|
+
write_single_mol_pdb(mol, pdb_path)
|
|
170
|
+
|
|
171
|
+
self._molecules.append(mol)
|
|
172
|
+
self._mol_weights.append(mw)
|
|
173
|
+
self._pdb_paths.append(pdb_path)
|
|
174
|
+
|
|
175
|
+
def _compute_counts_and_box(self) -> None:
|
|
176
|
+
"""Determine molecule counts and box size."""
|
|
177
|
+
cfg = self.config
|
|
178
|
+
|
|
179
|
+
# Determine counts
|
|
180
|
+
has_n_mol = any(c.n_mol > 0 for c in cfg.components)
|
|
181
|
+
has_wf = any(c.weight_fraction > 0 for c in cfg.components)
|
|
182
|
+
|
|
183
|
+
if has_n_mol:
|
|
184
|
+
self._counts = [c.n_mol for c in cfg.components]
|
|
185
|
+
elif has_wf:
|
|
186
|
+
wfs = [c.weight_fraction for c in cfg.components]
|
|
187
|
+
total = cfg.total_molecules if cfg.total_molecules > 0 else 200
|
|
188
|
+
self._counts = weight_fractions_to_counts(
|
|
189
|
+
self._mol_weights, wfs, total
|
|
190
|
+
)
|
|
191
|
+
else:
|
|
192
|
+
raise ValueError(
|
|
193
|
+
"Specify either n_mol or weight_fraction for each component."
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
# Determine box size
|
|
197
|
+
if cfg.box_size_nm > 0:
|
|
198
|
+
self._box_nm = cfg.box_size_nm
|
|
199
|
+
else:
|
|
200
|
+
self._box_nm = estimate_box_size_nm(
|
|
201
|
+
self._mol_weights, self._counts, cfg.density_g_cm3
|
|
202
|
+
)
|
|
203
|
+
logger.info("Box size: %.4f nm, Counts: %s", self._box_nm, self._counts)
|
|
204
|
+
|
|
205
|
+
def _run_packing(self, output_pdb: str, build_dir: str) -> str:
|
|
206
|
+
# Optional pre-built cluster (UDF cluster_file equivalent).
|
|
207
|
+
# When cfg.cluster_pdb_path is set, packmol places the cluster
|
|
208
|
+
# rigidly at box center first. We reduce the first component's
|
|
209
|
+
# count by the cluster's mol count (n_trimer derived from
|
|
210
|
+
# frozen_atom_indices) so total mol count stays the same.
|
|
211
|
+
cluster_pdb = str(getattr(self.config, 'cluster_pdb_path', '') or '')
|
|
212
|
+
cluster_pdb = cluster_pdb if cluster_pdb else None
|
|
213
|
+
adjusted_counts = list(self._counts)
|
|
214
|
+
if cluster_pdb and self._molecules:
|
|
215
|
+
atoms_per_first = int(self._molecules[0].n_atoms)
|
|
216
|
+
frozen = list(getattr(self.config, 'frozen_atom_indices', []) or [])
|
|
217
|
+
if frozen:
|
|
218
|
+
n_cluster_mol = max((int(a) - 1) // atoms_per_first
|
|
219
|
+
for a in frozen) + 1
|
|
220
|
+
adjusted_counts[0] = max(0, adjusted_counts[0] - n_cluster_mol)
|
|
221
|
+
logger.info(
|
|
222
|
+
"cluster_pdb=%s placed as rigid block; first-component "
|
|
223
|
+
"count reduced by %d → %d", cluster_pdb, n_cluster_mol,
|
|
224
|
+
adjusted_counts[0],
|
|
225
|
+
)
|
|
226
|
+
return run_packmol(
|
|
227
|
+
pdb_paths=self._pdb_paths,
|
|
228
|
+
counts=adjusted_counts,
|
|
229
|
+
box_size_nm=self._box_nm,
|
|
230
|
+
output_pdb=output_pdb,
|
|
231
|
+
build_dir=build_dir,
|
|
232
|
+
tolerance=self.config.packmol_tolerance,
|
|
233
|
+
seed=self.config.seed,
|
|
234
|
+
packmol_path=self.config.packmol_path,
|
|
235
|
+
cluster_pdb=cluster_pdb,
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
def _parameterize(self, mixture_pdb: str,
|
|
239
|
+
gro_path: str, top_path: str) -> Dict[str, str]:
|
|
240
|
+
# When the user opted into nagl / gasteiger we pre-assigned charges
|
|
241
|
+
# on each molecule; tell Interchange to reuse them instead of
|
|
242
|
+
# invoking AM1-BCC via sqm (which has no Windows build).
|
|
243
|
+
use_precomputed = self.config.charge_method in ("nagl", "gasteiger")
|
|
244
|
+
interchange = create_interchange(
|
|
245
|
+
molecules=self._molecules,
|
|
246
|
+
counts=self._counts,
|
|
247
|
+
box_size_nm=self._box_nm,
|
|
248
|
+
mixture_pdb=mixture_pdb,
|
|
249
|
+
forcefield_name=self.config.forcefield,
|
|
250
|
+
use_precomputed_charges=use_precomputed,
|
|
251
|
+
)
|
|
252
|
+
return export_gromacs(interchange, gro_path, top_path)
|
|
253
|
+
|
|
254
|
+
def _write_ndx(self, ndx_path: str) -> str:
|
|
255
|
+
comp_names = [c.name or f"comp_{i}"
|
|
256
|
+
for i, c in enumerate(self.config.components)]
|
|
257
|
+
atom_counts = [mol.n_atoms for mol in self._molecules]
|
|
258
|
+
frozen = list(getattr(self.config, "frozen_atom_indices", []) or [])
|
|
259
|
+
return write_ndx(comp_names, atom_counts, self._counts, ndx_path,
|
|
260
|
+
frozen_atom_indices=frozen)
|
|
261
|
+
|
|
262
|
+
def _add_trimer_posres_to_top(self, top_path: str,
|
|
263
|
+
frozen_atoms_1based: list) -> None:
|
|
264
|
+
"""Add [ position_restraints ] for trimer cluster center to system.top.
|
|
265
|
+
|
|
266
|
+
Derives local atom indices and trimer molecule count from the global
|
|
267
|
+
1-based ``frozen_atoms_1based`` and the first component's atom count.
|
|
268
|
+
If the first moleculetype's molecule count > trimer count, splits the
|
|
269
|
+
moletype: a ``<name>_TRIMER`` copy (trimer count instances, with
|
|
270
|
+
posres) is inserted BEFORE the original moleculetype (now with
|
|
271
|
+
reduced count). Otherwise, the posres block is appended to the
|
|
272
|
+
existing first moletype.
|
|
273
|
+
|
|
274
|
+
The posres block is wrapped in ``#ifdef POSRES_TRIMER`` so anneal /
|
|
275
|
+
sampling mdp can toggle via ``define = -DPOSRES_TRIMER``.
|
|
276
|
+
|
|
277
|
+
Why posres (not freezegrps): hard freeze on rigid water O atoms
|
|
278
|
+
breaks LINCS / SETTLE matrix inversion under MPI Domain
|
|
279
|
+
Decomposition (`determinant = -inf`). Harmonic posres
|
|
280
|
+
(k = posres_force_constant, default 10000 kJ/mol/nm²) keeps the
|
|
281
|
+
atoms within ~0.01 Å of initial position without any constraint
|
|
282
|
+
conflict — functionally equivalent for trimer cluster fix.
|
|
283
|
+
"""
|
|
284
|
+
if not self._molecules:
|
|
285
|
+
return
|
|
286
|
+
atoms_per_first_mol = int(self._molecules[0].n_atoms)
|
|
287
|
+
# Local 1-based atom indices within the first moletype
|
|
288
|
+
local_atoms = sorted({(int(a) - 1) % atoms_per_first_mol + 1
|
|
289
|
+
for a in frozen_atoms_1based})
|
|
290
|
+
# Trimer mol count = max mol-index used + 1
|
|
291
|
+
n_trimer = max((int(a) - 1) // atoms_per_first_mol
|
|
292
|
+
for a in frozen_atoms_1based) + 1
|
|
293
|
+
fc = float(getattr(self.config, 'posres_force_constant', 10000.0))
|
|
294
|
+
|
|
295
|
+
text = Path(top_path).read_text()
|
|
296
|
+
|
|
297
|
+
# Find first [ moleculetype ] block. Block extends until next
|
|
298
|
+
# [ moleculetype ] OR [ system ] marker.
|
|
299
|
+
import re
|
|
300
|
+
starts = [m.start() for m in re.finditer(r'^\[ moleculetype \]',
|
|
301
|
+
text, flags=re.MULTILINE)]
|
|
302
|
+
if not starts:
|
|
303
|
+
return
|
|
304
|
+
end_match = re.search(r'^\[ (?:moleculetype|system) \]', text[starts[0] + 1:],
|
|
305
|
+
flags=re.MULTILINE)
|
|
306
|
+
if end_match is None:
|
|
307
|
+
block_end = len(text)
|
|
308
|
+
else:
|
|
309
|
+
block_end = starts[0] + 1 + end_match.start()
|
|
310
|
+
first_block = text[starts[0]:block_end]
|
|
311
|
+
|
|
312
|
+
# First non-comment line after [ moleculetype ] is "<name>\t<nrexcl>"
|
|
313
|
+
moltype_name = None
|
|
314
|
+
for line in first_block.split('\n')[1:]:
|
|
315
|
+
s = line.strip()
|
|
316
|
+
if not s or s.startswith(';'):
|
|
317
|
+
continue
|
|
318
|
+
moltype_name = s.split()[0]
|
|
319
|
+
break
|
|
320
|
+
if not moltype_name:
|
|
321
|
+
return
|
|
322
|
+
|
|
323
|
+
# Find first entry in [ molecules ] section
|
|
324
|
+
mol_section_match = re.search(r'^\[ molecules \]', text, flags=re.MULTILINE)
|
|
325
|
+
if mol_section_match is None:
|
|
326
|
+
return
|
|
327
|
+
mol_start = mol_section_match.end()
|
|
328
|
+
first_count = None
|
|
329
|
+
first_line_text = None
|
|
330
|
+
for line in text[mol_start:].split('\n'):
|
|
331
|
+
s = line.strip()
|
|
332
|
+
if not s or s.startswith(';') or s.startswith('['):
|
|
333
|
+
continue
|
|
334
|
+
parts = s.split()
|
|
335
|
+
if len(parts) >= 2 and parts[0] == moltype_name:
|
|
336
|
+
try:
|
|
337
|
+
first_count = int(parts[1])
|
|
338
|
+
first_line_text = line
|
|
339
|
+
break
|
|
340
|
+
except ValueError:
|
|
341
|
+
pass
|
|
342
|
+
if first_count is None:
|
|
343
|
+
return
|
|
344
|
+
|
|
345
|
+
# Build posres block
|
|
346
|
+
posres_lines = ['', '#ifdef POSRES_TRIMER',
|
|
347
|
+
'[ position_restraints ]',
|
|
348
|
+
'; ai funct kx ky kz']
|
|
349
|
+
for ai in local_atoms:
|
|
350
|
+
posres_lines.append(f' {ai} 1 {fc:g} {fc:g} {fc:g}')
|
|
351
|
+
posres_lines.append('#endif')
|
|
352
|
+
posres_str = '\n'.join(posres_lines) + '\n'
|
|
353
|
+
|
|
354
|
+
needs_split = (first_count > n_trimer)
|
|
355
|
+
if needs_split:
|
|
356
|
+
# Insert TRIMER copy BEFORE the original. Rename only the
|
|
357
|
+
# moltype declaration line (first non-comment line after the
|
|
358
|
+
# [ moleculetype ] marker).
|
|
359
|
+
trimer_block_lines = first_block.split('\n')
|
|
360
|
+
for i in range(1, len(trimer_block_lines)):
|
|
361
|
+
s = trimer_block_lines[i].strip()
|
|
362
|
+
if not s or s.startswith(';'):
|
|
363
|
+
continue
|
|
364
|
+
if s.split()[0] == moltype_name:
|
|
365
|
+
trimer_block_lines[i] = trimer_block_lines[i].replace(
|
|
366
|
+
moltype_name, moltype_name + '_TRIMER', 1)
|
|
367
|
+
break
|
|
368
|
+
trimer_block_text = '\n'.join(trimer_block_lines)
|
|
369
|
+
# GROMACS forbids 2 moltypes both having [ settles ]
|
|
370
|
+
# (`Only one such is allowed`). Convert TRIMER copy's settles
|
|
371
|
+
# to equivalent [ constraints ] (LINCS-based) so the original
|
|
372
|
+
# moltype keeps its faster SETTLE and TRIMER becomes
|
|
373
|
+
# constraint-based rigid water. For TIP3P/SPC 3-site water:
|
|
374
|
+
# [ settles ]
|
|
375
|
+
# 1 1 dOH dHH
|
|
376
|
+
# → [ constraints ]
|
|
377
|
+
# 1 2 1 dOH ; O-H1
|
|
378
|
+
# 1 3 1 dOH ; O-H2
|
|
379
|
+
# 2 3 1 dHH ; H1-H2
|
|
380
|
+
settles_block_pattern = re.compile(
|
|
381
|
+
r'(\[ settles \].*?)(?=\n\[ |\Z)', re.DOTALL,
|
|
382
|
+
)
|
|
383
|
+
settles_match = settles_block_pattern.search(trimer_block_text)
|
|
384
|
+
if settles_match:
|
|
385
|
+
settles_text = settles_match.group(1)
|
|
386
|
+
# Parse the first non-comment row: "i funct dOH dHH"
|
|
387
|
+
dOH = dHH = None
|
|
388
|
+
for line in settles_text.split('\n')[1:]:
|
|
389
|
+
s = line.strip()
|
|
390
|
+
if not s or s.startswith(';') or s.startswith('['):
|
|
391
|
+
continue
|
|
392
|
+
parts = s.split()
|
|
393
|
+
if len(parts) >= 4:
|
|
394
|
+
try:
|
|
395
|
+
dOH = float(parts[2])
|
|
396
|
+
dHH = float(parts[3])
|
|
397
|
+
break
|
|
398
|
+
except ValueError:
|
|
399
|
+
continue
|
|
400
|
+
if dOH is not None:
|
|
401
|
+
constraints_text = (
|
|
402
|
+
f'[ constraints ]\n'
|
|
403
|
+
f'; ai aj funct value (TIP3P/SPC rigid water, '
|
|
404
|
+
f'converted from [settles])\n'
|
|
405
|
+
f' 1 2 1 {dOH}\n'
|
|
406
|
+
f' 1 3 1 {dOH}\n'
|
|
407
|
+
f' 2 3 1 {dHH}\n'
|
|
408
|
+
)
|
|
409
|
+
trimer_block_text = trimer_block_text.replace(
|
|
410
|
+
settles_text, constraints_text, 1)
|
|
411
|
+
trimer_block = trimer_block_text.rstrip() + '\n' + posres_str + '\n'
|
|
412
|
+
text = text[:starts[0]] + trimer_block + text[starts[0]:]
|
|
413
|
+
# Update the [ molecules ] line
|
|
414
|
+
new_first_line = (
|
|
415
|
+
f'{moltype_name}_TRIMER\t{n_trimer}\n'
|
|
416
|
+
f'{moltype_name}\t{first_count - n_trimer}'
|
|
417
|
+
)
|
|
418
|
+
text = text.replace(first_line_text, new_first_line, 1)
|
|
419
|
+
else:
|
|
420
|
+
# No split — append posres at end of first moltype block
|
|
421
|
+
new_block = first_block.rstrip() + '\n' + posres_str + '\n'
|
|
422
|
+
text = text.replace(first_block, new_block, 1)
|
|
423
|
+
|
|
424
|
+
Path(top_path).write_text(text)
|
|
425
|
+
logger.info(
|
|
426
|
+
"added [ position_restraints ] (k=%g) for moltype %s (n_trimer=%d, "
|
|
427
|
+
"local_atoms=%s, split=%s)",
|
|
428
|
+
fc, moltype_name, n_trimer, local_atoms, needs_split,
|
|
429
|
+
)
|
|
430
|
+
|
|
431
|
+
def _make_protocol(self) -> AnnealProtocol:
|
|
432
|
+
cfg = self.config
|
|
433
|
+
return AnnealProtocol(
|
|
434
|
+
T_high=cfg.T_high,
|
|
435
|
+
T_low=cfg.temperature,
|
|
436
|
+
P_ref=cfg.pressure,
|
|
437
|
+
em_steps=cfg.em_steps,
|
|
438
|
+
em_tol=cfg.em_tol,
|
|
439
|
+
nvt_high_nsteps=cfg.nvt_high_nsteps,
|
|
440
|
+
npt_high_nsteps=cfg.npt_high_nsteps,
|
|
441
|
+
anneal_nsteps=cfg.anneal_nsteps,
|
|
442
|
+
npt_low_nsteps=cfg.npt_low_nsteps,
|
|
443
|
+
dt=cfg.dt,
|
|
444
|
+
tau_t=cfg.tau_t,
|
|
445
|
+
tau_p=cfg.tau_p,
|
|
446
|
+
nstxout_compressed=cfg.nstxout_compressed,
|
|
447
|
+
nstenergy=cfg.nstenergy,
|
|
448
|
+
gen_seed=cfg.seed,
|
|
449
|
+
)
|
|
450
|
+
|
|
451
|
+
def _tc_grps_string(self) -> str:
|
|
452
|
+
"""Build the tc-grps string for MDP (e.g. 'API Polymer').
|
|
453
|
+
|
|
454
|
+
Names are deduplicated while preserving first-seen order so that
|
|
455
|
+
pure-component pairs (e.g. ``ComponentSpec(name='B_water', ...)``
|
|
456
|
+
× 2) emit a single group, matching the single ``ref-t`` /
|
|
457
|
+
``tau-t`` value emitted by :func:`mdp_protocol._thermostat_block`.
|
|
458
|
+
Without dedup, grompp rejects the mdp with
|
|
459
|
+
``Invalid T coupling input: 2 groups, 1 ref-t values``.
|
|
460
|
+
"""
|
|
461
|
+
seen: dict[str, None] = {}
|
|
462
|
+
for i, c in enumerate(self.config.components):
|
|
463
|
+
name = c.name or f"comp_{i}"
|
|
464
|
+
if name not in seen:
|
|
465
|
+
seen[name] = None
|
|
466
|
+
return " ".join(seen.keys())
|