abmptools 2.2.0__tar.gz → 2.2.1__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 (355) hide show
  1. {abmptools-2.2.0/abmptools.egg-info → abmptools-2.2.1}/PKG-INFO +6 -3
  2. {abmptools-2.2.0 → abmptools-2.2.1}/README.md +5 -2
  3. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/hbond/analyzer.py +48 -2
  4. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/hbond/cli.py +4 -2
  5. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/udfcharge/__init__.py +4 -0
  6. abmptools-2.2.1/abmptools/udfcharge/__main__.py +117 -0
  7. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/udfcharge/core.py +186 -5
  8. {abmptools-2.2.0 → abmptools-2.2.1/abmptools.egg-info}/PKG-INFO +6 -3
  9. {abmptools-2.2.0 → abmptools-2.2.1}/pyproject.toml +1 -1
  10. abmptools-2.2.0/abmptools/udfcharge/__main__.py +0 -63
  11. {abmptools-2.2.0 → abmptools-2.2.1}/LICENSE +0 -0
  12. {abmptools-2.2.0 → abmptools-2.2.1}/NOTICE +0 -0
  13. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/__init__.py +0 -0
  14. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/abinit_io.py +0 -0
  15. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/addsolvfrag.py +0 -0
  16. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/ajf2config.py +0 -0
  17. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/ajfserial.py +0 -0
  18. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/amorphous/__init__.py +0 -0
  19. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/amorphous/__main__.py +0 -0
  20. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/amorphous/builder.py +0 -0
  21. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/amorphous/cli.py +0 -0
  22. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/amorphous/density.py +0 -0
  23. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/amorphous/mdp_protocol.py +0 -0
  24. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/amorphous/models.py +0 -0
  25. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/amorphous/molecule_prep.py +0 -0
  26. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/amorphous/ndx_writer.py +0 -0
  27. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/amorphous/packing.py +0 -0
  28. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/amorphous/parameterizer.py +0 -0
  29. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/amorphous/pubchem.py +0 -0
  30. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/amorphous/system_model_adapter.py +0 -0
  31. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/amorphous/trajectory_ingest.py +0 -0
  32. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/anlfmo.py +0 -0
  33. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/cg/__init__.py +0 -0
  34. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/cg/dpd/__init__.py +0 -0
  35. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/cg/dpd/__main__.py +0 -0
  36. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/cg/dpd/aij_assign.py +0 -0
  37. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/cg/dpd/aij_io.py +0 -0
  38. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/cg/dpd/calc_sett_io.py +0 -0
  39. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/cg/dpd/dpm_writer.py +0 -0
  40. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/cg/dpd/models.py +0 -0
  41. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/cg/dpd/monomer_io.py +0 -0
  42. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/cg/dpd/notebook_ui.py +0 -0
  43. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/cg/dpd/orchestrator.py +0 -0
  44. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/cg/dpd/udf_writer.py +0 -0
  45. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/cg/dpd/udf_writer_udfm.py +0 -0
  46. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/cg/membrane/__init__.py +0 -0
  47. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/cg/membrane/__main__.py +0 -0
  48. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/cg/membrane/_subprocess.py +0 -0
  49. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/cg/membrane/builder.py +0 -0
  50. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/cg/membrane/cli.py +0 -0
  51. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/cg/membrane/forcefield_check.py +0 -0
  52. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/cg/membrane/insane_runner.py +0 -0
  53. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/cg/membrane/mdp_templates.py +0 -0
  54. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/cg/membrane/models.py +0 -0
  55. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/cg/membrane/pmf.py +0 -0
  56. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/cg/membrane/pulling.py +0 -0
  57. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/cg/membrane/system_packer.py +0 -0
  58. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/cg/membrane/topology_composer.py +0 -0
  59. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/cg/membrane/umbrella.py +0 -0
  60. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/cg/peptide/__init__.py +0 -0
  61. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/cg/peptide/__main__.py +0 -0
  62. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/cg/peptide/_subprocess.py +0 -0
  63. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/cg/peptide/builder.py +0 -0
  64. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/cg/peptide/cli.py +0 -0
  65. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/cg/peptide/forcefield_check.py +0 -0
  66. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/cg/peptide/martinize_runner.py +0 -0
  67. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/cg/peptide/mdp_templates.py +0 -0
  68. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/cg/peptide/models.py +0 -0
  69. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/cg/peptide/peptide_atomistic.py +0 -0
  70. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/cg/peptide/system_packer.py +0 -0
  71. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/cg/peptide/top_writer.py +0 -0
  72. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/cg/peptide/water_box.py +0 -0
  73. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/convertcpf.py +0 -0
  74. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/core/__init__.py +0 -0
  75. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/core/system_model.py +0 -0
  76. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/cpf2ifielist.py +0 -0
  77. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/cpfmanager.py +0 -0
  78. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/crystal/__init__.py +0 -0
  79. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/crystal/__main__.py +0 -0
  80. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/crystal/_subprocess.py +0 -0
  81. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/crystal/atom_distance.py +0 -0
  82. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/crystal/builder.py +0 -0
  83. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/crystal/cif_engine_ase.py +0 -0
  84. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/crystal/cif_engine_legacy.py +0 -0
  85. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/crystal/cli.py +0 -0
  86. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/crystal/forcefield_check.py +0 -0
  87. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/crystal/job_templates.py +0 -0
  88. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/crystal/legacy/__init__.py +0 -0
  89. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/crystal/models.py +0 -0
  90. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/crystal/postproc.py +0 -0
  91. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/f90/bin/readifiepiedalib.so +0 -0
  92. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/formulation/__init__.py +0 -0
  93. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/formulation/__main__.py +0 -0
  94. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/formulation/_subprocess.py +0 -0
  95. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/formulation/analysis/__init__.py +0 -0
  96. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/formulation/analysis/aggregate_transition.py +0 -0
  97. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/formulation/analysis/contact_map.py +0 -0
  98. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/formulation/analysis/hbond.py +0 -0
  99. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/formulation/analysis/plots.py +0 -0
  100. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/formulation/analysis/sasa.py +0 -0
  101. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/formulation/analysis/secondary_structure.py +0 -0
  102. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/formulation/builder.py +0 -0
  103. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/formulation/cli.py +0 -0
  104. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/formulation/mdp_templates.py +0 -0
  105. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/formulation/models.py +0 -0
  106. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/formulation/ndx.py +0 -0
  107. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/formulation/packer.py +0 -0
  108. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/formulation/peptide_atomistic.py +0 -0
  109. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/formulation/peptide_atomistic_openff.py +0 -0
  110. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/formulation/small_molecule.py +0 -0
  111. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/formulation/small_molecule_openff.py +0 -0
  112. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/formulation/topology.py +0 -0
  113. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/formulation/topology_openff.py +0 -0
  114. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/formulation/umbrella_release.py +0 -0
  115. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/fragmenter/__init__.py +0 -0
  116. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/fragmenter/__main__.py +0 -0
  117. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/fragmenter/auto_split.py +0 -0
  118. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/fragmenter/cg_segmenter/__init__.py +0 -0
  119. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/fragmenter/cg_segmenter/__main__.py +0 -0
  120. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/fragmenter/cg_segmenter/cap_attach.py +0 -0
  121. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/fragmenter/cg_segmenter/chain_splitter.py +0 -0
  122. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/fragmenter/cg_segmenter/dpdgen_exporter.py +0 -0
  123. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/fragmenter/cg_segmenter/exporter.py +0 -0
  124. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/fragmenter/cg_segmenter/fcews_export.py +0 -0
  125. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/fragmenter/cg_segmenter/models.py +0 -0
  126. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/fragmenter/cg_segmenter/notebook_ui.py +0 -0
  127. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/fragmenter/cg_segmenter/orchestrator.py +0 -0
  128. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/fragmenter/cg_segmenter/ring_detector.py +0 -0
  129. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/fragmenter/cut_apply.py +0 -0
  130. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/fragmenter/expand_to_system.py +0 -0
  131. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/fragmenter/grouping.py +0 -0
  132. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/fragmenter/headless_io.py +0 -0
  133. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/fragmenter/models.py +0 -0
  134. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/fragmenter/notebook_ui.py +0 -0
  135. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/fragmenter/pdb_loader.py +0 -0
  136. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/fragmenter/polymer.py +0 -0
  137. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/generate_difie.py +0 -0
  138. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/generateajf.py +0 -0
  139. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/genesis/__init__.py +0 -0
  140. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/genesis/grest/__init__.py +0 -0
  141. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/genesis/grest/__main__.py +0 -0
  142. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/genesis/grest/_subprocess.py +0 -0
  143. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/genesis/grest/analysis.py +0 -0
  144. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/genesis/grest/builder.py +0 -0
  145. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/genesis/grest/cli.py +0 -0
  146. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/genesis/grest/forcefield_check.py +0 -0
  147. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/genesis/grest/grest_runner.py +0 -0
  148. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/genesis/grest/inp_writer.py +0 -0
  149. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/genesis/grest/models.py +0 -0
  150. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/genesis/grest/replica_temperatures.py +0 -0
  151. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/genesis/grest/rest_selection.py +0 -0
  152. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/genesis/grest/system_builder.py +0 -0
  153. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/genesis/mmgbsa/__init__.py +0 -0
  154. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/genesis/mmgbsa/__main__.py +0 -0
  155. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/genesis/mmgbsa/_subprocess.py +0 -0
  156. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/genesis/mmgbsa/analysis.py +0 -0
  157. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/genesis/mmgbsa/builder.py +0 -0
  158. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/genesis/mmgbsa/cli.py +0 -0
  159. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/genesis/mmgbsa/forcefield_check.py +0 -0
  160. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/genesis/mmgbsa/gbsa_runner.py +0 -0
  161. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/genesis/mmgbsa/inp_writer.py +0 -0
  162. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/genesis/mmgbsa/ligand_parameterize.py +0 -0
  163. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/genesis/mmgbsa/models.py +0 -0
  164. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/genesis/mmgbsa/pdb_splitter.py +0 -0
  165. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/genesis/mmgbsa/system_builder.py +0 -0
  166. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/geomopt/__init__.py +0 -0
  167. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/geomopt/mace_optimizer.py +0 -0
  168. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/geomopt/openff_openmm_minimizer.py +0 -0
  169. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/geomopt/pyscf_optimizer.py +0 -0
  170. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/getcharge.py +0 -0
  171. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/getifiepieda.py +0 -0
  172. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/gro2udf/__init__.py +0 -0
  173. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/gro2udf/__main__.py +0 -0
  174. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/gro2udf/cli.py +0 -0
  175. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/gro2udf/default_template.udf +0 -0
  176. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/gro2udf/default_template_cognac101.udf +0 -0
  177. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/gro2udf/exporter.py +0 -0
  178. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/gro2udf/gro_adapter.py +0 -0
  179. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/gro2udf/gro_parser.py +0 -0
  180. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/gro2udf/mdp_parser.py +0 -0
  181. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/gro2udf/top_adapter.py +0 -0
  182. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/gro2udf/top_exporter.py +0 -0
  183. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/gro2udf/top_model.py +0 -0
  184. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/gro2udf/top_parser.py +0 -0
  185. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/gro2udf/trajectory_io.py +0 -0
  186. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/gro2udf/udf_writer.py +0 -0
  187. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/hbond/__init__.py +0 -0
  188. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/hbond/__main__.py +0 -0
  189. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/hbond/bdf_reader.py +0 -0
  190. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/hbond/classifier.py +0 -0
  191. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/hbond/colorizer.py +0 -0
  192. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/hbond/distance_dist.py +0 -0
  193. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/hbond/func_tags.py +0 -0
  194. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/hbond/functional_groups.py +0 -0
  195. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/hbond/hbond_detector.py +0 -0
  196. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/hbond/lifetime.py +0 -0
  197. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/hbond/notebook_ui.py +0 -0
  198. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/hbond/pair_type_stats.py +0 -0
  199. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/log2config.py +0 -0
  200. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/log2cpf.py +0 -0
  201. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/logmanager.py +0 -0
  202. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/membrane/__init__.py +0 -0
  203. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/membrane/bilayer.py +0 -0
  204. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/membrane/builder.py +0 -0
  205. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/membrane/lipid_info.py +0 -0
  206. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/membrane/mdp_us_protocol.py +0 -0
  207. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/membrane/models.py +0 -0
  208. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/membrane/parameterize_amber.py +0 -0
  209. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/membrane/parameterize_charmm.py +0 -0
  210. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/membrane/pmf.py +0 -0
  211. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/membrane/pulling.py +0 -0
  212. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/membrane/topology_sanity.py +0 -0
  213. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/membrane/umbrella.py +0 -0
  214. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/mol_io.py +0 -0
  215. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/molcalc.py +0 -0
  216. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/pdb2fmo.py +0 -0
  217. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/pdb_io.py +0 -0
  218. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/pdbmodify.py +0 -0
  219. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/readcif.py +0 -0
  220. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/setfmo.py +0 -0
  221. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/trajectory/__init__.py +0 -0
  222. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/trajectory/__main__.py +0 -0
  223. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/trajectory/cli.py +0 -0
  224. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/trajectory/postprocess.py +0 -0
  225. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/udf2fmo.py +0 -0
  226. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/udf2gro/__init__.py +0 -0
  227. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/udf2gro/__main__.py +0 -0
  228. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/udf2gro/cli.py +0 -0
  229. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/udf2gro/exporter.py +0 -0
  230. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/udf2gro/gromacs/__init__.py +0 -0
  231. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/udf2gro/gromacs/writers/__init__.py +0 -0
  232. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/udf2gro/gromacs/writers/_validator.py +0 -0
  233. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/udf2gro/gromacs/writers/gro_writer.py +0 -0
  234. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/udf2gro/gromacs/writers/itp_writer.py +0 -0
  235. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/udf2gro/gromacs/writers/mdp_writer.py +0 -0
  236. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/udf2gro/gromacs/writers/top_writer.py +0 -0
  237. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/udf2gro/udf_adapter.py +0 -0
  238. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/udf_io.py +0 -0
  239. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/udfcreate.py +0 -0
  240. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/udfcreate_v2.py +0 -0
  241. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools/udfrm_io.py +0 -0
  242. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools.egg-info/SOURCES.txt +0 -0
  243. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools.egg-info/dependency_links.txt +0 -0
  244. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools.egg-info/entry_points.txt +0 -0
  245. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools.egg-info/requires.txt +0 -0
  246. {abmptools-2.2.0 → abmptools-2.2.1}/abmptools.egg-info/top_level.txt +0 -0
  247. {abmptools-2.2.0 → abmptools-2.2.1}/setup.cfg +0 -0
  248. {abmptools-2.2.0 → abmptools-2.2.1}/setup.py +0 -0
  249. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_abinit_io.py +0 -0
  250. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_amorphous_models.py +0 -0
  251. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_anlfmo.py +0 -0
  252. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_builder_integration.py +0 -0
  253. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_builder_mocked.py +0 -0
  254. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_cg_membrane_builder_mocked.py +0 -0
  255. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_cg_membrane_cli.py +0 -0
  256. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_cg_membrane_forcefield_check.py +0 -0
  257. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_cg_membrane_insane_runner.py +0 -0
  258. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_cg_membrane_integration.py +0 -0
  259. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_cg_membrane_mdp.py +0 -0
  260. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_cg_membrane_models.py +0 -0
  261. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_cg_membrane_packer.py +0 -0
  262. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_cg_membrane_pmf.py +0 -0
  263. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_cg_membrane_pulling.py +0 -0
  264. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_cg_membrane_topology_composer.py +0 -0
  265. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_cg_membrane_umbrella.py +0 -0
  266. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_cg_peptide_atomistic.py +0 -0
  267. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_cg_peptide_builder_mocked.py +0 -0
  268. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_cg_peptide_cli.py +0 -0
  269. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_cg_peptide_forcefield_check.py +0 -0
  270. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_cg_peptide_integration.py +0 -0
  271. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_cg_peptide_martinize_runner.py +0 -0
  272. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_cg_peptide_mdp.py +0 -0
  273. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_cg_peptide_models.py +0 -0
  274. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_cg_peptide_packer.py +0 -0
  275. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_cg_peptide_subprocess.py +0 -0
  276. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_cg_peptide_topwriter.py +0 -0
  277. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_cg_peptide_water_box.py +0 -0
  278. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_charge_method.py +0 -0
  279. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_cli_scripts.py +0 -0
  280. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_cpfmanager.py +0 -0
  281. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_crystal_atom_distance.py +0 -0
  282. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_crystal_builder.py +0 -0
  283. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_crystal_cif_ase.py +0 -0
  284. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_crystal_cif_legacy.py +0 -0
  285. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_crystal_cli.py +0 -0
  286. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_crystal_job_templates.py +0 -0
  287. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_crystal_models.py +0 -0
  288. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_crystal_numeric_regression.py +0 -0
  289. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_crystal_regression.py +0 -0
  290. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_density.py +0 -0
  291. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_formulation_analysis.py +0 -0
  292. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_formulation_builder.py +0 -0
  293. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_formulation_mdp.py +0 -0
  294. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_formulation_models.py +0 -0
  295. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_formulation_ndx.py +0 -0
  296. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_formulation_packer.py +0 -0
  297. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_formulation_peptide_atomistic.py +0 -0
  298. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_formulation_small_molecule.py +0 -0
  299. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_formulation_topology.py +0 -0
  300. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_formulation_umbrella_release.py +0 -0
  301. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_getifiepieda.py +0 -0
  302. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_grest_analysis_mocked.py +0 -0
  303. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_grest_builder_mocked.py +0 -0
  304. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_grest_cli.py +0 -0
  305. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_grest_inp_writer.py +0 -0
  306. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_grest_integration.py +0 -0
  307. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_grest_models.py +0 -0
  308. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_grest_replica_temperatures.py +0 -0
  309. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_grest_rest_selection.py +0 -0
  310. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_grest_system_builder.py +0 -0
  311. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_gro_adapter.py +0 -0
  312. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_gro_parser.py +0 -0
  313. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_gro_writer.py +0 -0
  314. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_interchange_adapter.py +0 -0
  315. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_logmanager.py +0 -0
  316. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_mdp_parser.py +0 -0
  317. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_mdp_protocol.py +0 -0
  318. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_mdp_writer.py +0 -0
  319. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_membrane_charmm_translate.py +0 -0
  320. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_membrane_mixed_lipid.py +0 -0
  321. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_membrane_topology_sanity.py +0 -0
  322. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_mmgbsa_analysis.py +0 -0
  323. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_mmgbsa_builder_mocked.py +0 -0
  324. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_mmgbsa_cli.py +0 -0
  325. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_mmgbsa_forcefield_check.py +0 -0
  326. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_mmgbsa_inp_writer.py +0 -0
  327. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_mmgbsa_integration.py +0 -0
  328. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_mmgbsa_models.py +0 -0
  329. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_mmgbsa_pdb_splitter.py +0 -0
  330. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_mmgbsa_system_builder.py +0 -0
  331. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_mol_io.py +0 -0
  332. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_molcalc.py +0 -0
  333. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_ndx_writer.py +0 -0
  334. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_parameterizer.py +0 -0
  335. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_pdb_io.py +0 -0
  336. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_pubchem.py +0 -0
  337. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_pyscf_optimizer.py +0 -0
  338. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_pyscf_parsers.py +0 -0
  339. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_read_ifie_hf_fallback.py +0 -0
  340. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_readcif.py +0 -0
  341. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_regression.py +0 -0
  342. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_setfmo.py +0 -0
  343. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_system_model.py +0 -0
  344. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_system_model_extensions.py +0 -0
  345. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_top_exporter_frames_override.py +0 -0
  346. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_top_model.py +0 -0
  347. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_top_parser.py +0 -0
  348. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_top_writer.py +0 -0
  349. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_trajectory_ingest.py +0 -0
  350. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_trajectory_postprocess.py +0 -0
  351. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_udf_io.py +0 -0
  352. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_udfcreate.py +0 -0
  353. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_udfcreate_v2.py +0 -0
  354. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_udfcreate_v2_byte_equivalence.py +0 -0
  355. {abmptools-2.2.0 → abmptools-2.2.1}/tests/test_udfrm_io.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: abmptools
3
- Version: 2.2.0
3
+ Version: 2.2.1
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
@@ -121,7 +121,7 @@ A Python toolkit for pre-processing, post-processing, and analysis of Fragment M
121
121
 
122
122
  - **udf2gro**: Convert OCTA UDF files to GROMACS format (`.gro`, `.top`, `.mdp`, `.itp`)
123
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
124
+ - **udfcharge**: Transfer per-atom partial charges from a single-molecule UDF to bulk molecules (`transfer`), or restore a neutralized UDF's charges to a target integer formal charge (`restore`)
125
125
 
126
126
  ### Geometry Optimization (`geomopt`)
127
127
 
@@ -314,7 +314,10 @@ python -m abmptools.udf2gro.cli -i system.udf -o output
314
314
  python -m abmptools.gro2udf.cli -i system.gro -t system.top -o output.udf
315
315
 
316
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
317
+ python -m abmptools.udfcharge transfer --template mol.udf --bulk bulk.udf --out bulk_charged.udf
318
+
319
+ # Restore a neutralized UDF's charges to a target integer formal charge
320
+ python -m abmptools.udfcharge restore --udf mol.udf --formal-charge 12 --out mol_q+12.udf
318
321
 
319
322
  # Build an amorphous mixture from SMILES (50 ketoprofen molecules, density 0.8 g/cm^3)
320
323
  python -m abmptools.amorphous --smiles "OC(=O)C(C)c1cccc(C(=O)c2ccccc2)c1" \
@@ -37,7 +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
+ - **udfcharge**: Transfer per-atom partial charges from a single-molecule UDF to bulk molecules (`transfer`), or restore a neutralized UDF's charges to a target integer formal charge (`restore`)
41
41
 
42
42
  ### Geometry Optimization (`geomopt`)
43
43
 
@@ -230,7 +230,10 @@ python -m abmptools.udf2gro.cli -i system.udf -o output
230
230
  python -m abmptools.gro2udf.cli -i system.gro -t system.top -o output.udf
231
231
 
232
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
233
+ python -m abmptools.udfcharge transfer --template mol.udf --bulk bulk.udf --out bulk_charged.udf
234
+
235
+ # Restore a neutralized UDF's charges to a target integer formal charge
236
+ python -m abmptools.udfcharge restore --udf mol.udf --formal-charge 12 --out mol_q+12.udf
234
237
 
235
238
  # Build an amorphous mixture from SMILES (50 ketoprofen molecules, density 0.8 g/cm^3)
236
239
  python -m abmptools.amorphous --smiles "OC(=O)C(C)c1cccc(C(=O)c2ccccc2)c1" \
@@ -302,6 +302,36 @@ class Analyzer:
302
302
  meta_by_type["ether_O"] = [(s.mol_index, s.acceptor_a) for s in sites]
303
303
  return sites_by_type, meta_by_type
304
304
 
305
+ def _auto_groups(self) -> Tuple[List[str], List[str]]:
306
+ """Auto-detect donor/acceptor group types present in the system.
307
+
308
+ Used by ``classify_mode='auto'``. Returns ``(donor_groups,
309
+ acceptor_groups)`` listing only the functional-group types actually
310
+ detected (carboxyl / amide / secondary-amide N-H / amine N-H /
311
+ hydroxyl). ``ether_O`` is NOT auto-listed because there is no reliable
312
+ ether detector yet (GAFF2 ``os``-tag only); pass ``--acceptor-groups
313
+ ether_O`` explicitly if needed.
314
+ """
315
+ if self.traj is None:
316
+ self.load()
317
+ from .functional_groups import detect_hydroxyls
318
+ donors: List[str] = []
319
+ acceptors: List[str] = []
320
+ if self.carboxyls:
321
+ donors.append("carboxyl")
322
+ acceptors.append("carboxyl_O")
323
+ if any(g.from_amide for g in self.amine_donors):
324
+ donors.append("amide_donor")
325
+ if any(not g.from_amide for g in self.amine_donors):
326
+ donors.append("amine_donor")
327
+ hydroxyls = detect_hydroxyls(self.traj.molecules, mapping=self.mapping)
328
+ if hydroxyls:
329
+ donors.append("hydroxyl")
330
+ acceptors.append("hydroxyl_O")
331
+ if self.amides:
332
+ acceptors.append("amide_O")
333
+ return donors, acceptors
334
+
305
335
  def run(self) -> List[FrameResult]:
306
336
  if self.traj is None:
307
337
  self.load()
@@ -309,12 +339,28 @@ class Analyzer:
309
339
  end = c.record_end if c.record_end >= 0 else self.traj.n_records
310
340
  criteria = c.get_criteria()
311
341
  mode = (c.classify_mode or "imc").lower()
312
- if mode not in {"imc", "generic"}:
342
+ if mode not in {"imc", "generic", "auto"}:
313
343
  raise ValueError(
314
344
  f"Unknown classify_mode={c.classify_mode!r}; "
315
- "must be 'imc' or 'generic'"
345
+ "must be 'imc', 'generic', or 'auto'"
316
346
  )
317
347
 
348
+ if mode == "auto":
349
+ # Detect which functional-group donor/acceptor types are present and
350
+ # run them through the generic pair-stats path. Explicit
351
+ # --donor-groups / --acceptor-groups still override the auto picks.
352
+ auto_donors, auto_acceptors = self._auto_groups()
353
+ if c.donor_groups is None:
354
+ c.donor_groups = auto_donors
355
+ if c.acceptor_groups is None:
356
+ c.acceptor_groups = auto_acceptors
357
+ if c.verbose:
358
+ print(f" [auto] donor groups : {c.donor_groups or '(none detected)'}")
359
+ print(f" [auto] acceptor groups: {c.acceptor_groups or '(none detected)'}")
360
+ # Resolve to generic so run()/write_outputs use the generic path.
361
+ c.classify_mode = "generic"
362
+ mode = "generic"
363
+
318
364
  donor_groups = c.donor_groups or (
319
365
  ["carboxyl"] if mode == "imc" else []
320
366
  )
@@ -62,9 +62,11 @@ def main(argv=None) -> int:
62
62
  help="Base molecule name for renamed groups (default: IMC)"
63
63
  )
64
64
  parser.add_argument(
65
- "--classify-mode", choices=["imc", "generic"], default="imc",
65
+ "--classify-mode", choices=["imc", "generic", "auto"], default="imc",
66
66
  help="imc: COOH-centric 4-species (dual/chain/single/free, IMC default). "
67
- "generic: donor-type x acceptor-type pair stats (PVA/peptide/etc.)"
67
+ "generic: donor-type x acceptor-type pair stats (PVA/peptide/etc.). "
68
+ "auto: detect functional groups present and run generic with them "
69
+ "(no need to pass --donor-groups/--acceptor-groups; ether_O excluded)"
68
70
  )
69
71
  parser.add_argument(
70
72
  "--no-element-fallback", action="store_true",
@@ -14,8 +14,10 @@ from .core import (
14
14
  POINT_CHARGE,
15
15
  AssignResult,
16
16
  MoleculeChargeTemplate,
17
+ RestoreResult,
17
18
  assign_charges_to_bulk,
18
19
  read_molecule_charges,
20
+ restore_formal_charge,
19
21
  )
20
22
 
21
23
  __all__ = [
@@ -23,6 +25,8 @@ __all__ = [
23
25
  "POINT_CHARGE",
24
26
  "AssignResult",
25
27
  "MoleculeChargeTemplate",
28
+ "RestoreResult",
26
29
  "assign_charges_to_bulk",
27
30
  "read_molecule_charges",
31
+ "restore_formal_charge",
28
32
  ]
@@ -0,0 +1,117 @@
1
+ """CLI: OCTA/COGNAC UDF の per-atom 電荷操作。
2
+
3
+ # 単分子 UDF の電荷をバルク UDF の同名分子へ転写
4
+ python -m abmptools.udfcharge transfer --template mol.udf --bulk bulk.udf \
5
+ [--out bulk_charged.udf] [--mol-name NAME] [--mol-index I] \
6
+ [--no-verify-types] [--non-strict]
7
+
8
+ # 中和 (Σq≈0) された 1 分子 UDF の電荷を指定形式電荷に復元
9
+ python -m abmptools.udfcharge restore --udf mol.udf --formal-charge 12 \
10
+ [--out mol_q+12.udf] [--mol-index I] [--mol-name NAME]
11
+
12
+ 後方互換: サブコマンド省略時は ``transfer`` として解釈する。
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ import argparse
18
+ import logging
19
+ import sys
20
+
21
+ from .core import (
22
+ assign_charges_to_bulk,
23
+ read_molecule_charges,
24
+ restore_formal_charge,
25
+ )
26
+
27
+ _SUBCOMMANDS = {"transfer", "restore"}
28
+
29
+
30
+ def _run_transfer(args) -> int:
31
+ tmpl = read_molecule_charges(
32
+ args.template, mol_name=args.mol_name, mol_index=args.mol_index,
33
+ )
34
+ res = assign_charges_to_bulk(
35
+ args.bulk, tmpl, args.out,
36
+ verify_atom_types=not args.no_verify_types,
37
+ strict=not args.non_strict,
38
+ )
39
+ print(f"template : {tmpl.mol_name} (n_atoms={tmpl.n_atoms}, "
40
+ f"net_charge={tmpl.net_charge:+.4f})")
41
+ print(f"assigned : {res.n_molecules_assigned}/{res.n_molecules_total} molecules")
42
+ if res.skipped_indices:
43
+ print(f"skipped : {res.skipped_indices}")
44
+ print(f"output : {res.out_path}")
45
+ return 0
46
+
47
+
48
+ def _run_restore(args) -> int:
49
+ res = restore_formal_charge(
50
+ args.udf, args.formal_charge, args.out,
51
+ mol_index=args.mol_index, mol_name=args.mol_name, mode=args.mode,
52
+ )
53
+ detail = (f"λ={res.lam:.8f}" if res.mode == "proportional"
54
+ else f"shift=S/N={res.shift:.8f}")
55
+ print(f"molecule : {res.mol_name} (n_atoms={res.n_atoms})")
56
+ print(f"mode : {res.mode}")
57
+ print(f"input total : {res.input_total:+.6f} (中和済み想定)")
58
+ print(f"formal charge: {res.formal_charge:+d} ({detail})")
59
+ print(f"output total : {res.output_total:+.6f}")
60
+ print(f"output : {res.out_path}")
61
+ return 0
62
+
63
+
64
+ def main(argv=None) -> int:
65
+ argv = list(sys.argv[1:] if argv is None else argv)
66
+ # 後方互換: 旧フラット呼び出し (transfer の --template ...) を許容
67
+ if argv and argv[0] not in _SUBCOMMANDS and not argv[0].startswith("-"):
68
+ pass # 不明な位置引数 → そのまま argparse にエラーさせる
69
+ elif argv and argv[0].startswith("-") and "--template" in argv:
70
+ argv = ["transfer"] + argv
71
+
72
+ p = argparse.ArgumentParser(
73
+ prog="python -m abmptools.udfcharge",
74
+ description="OCTA/COGNAC UDF の per-atom 電荷操作 (転写 / 形式電荷復元)。",
75
+ )
76
+ sub = p.add_subparsers(dest="cmd")
77
+
78
+ pt = sub.add_parser("transfer",
79
+ help="単分子 UDF の電荷をバルク UDF の同名分子へ転写")
80
+ pt.add_argument("--template", required=True, help="電荷を持つ単分子 UDF")
81
+ pt.add_argument("--bulk", required=True, help="割り当て先のバルク UDF")
82
+ pt.add_argument("--out", default=None, help="出力 (省略時 <bulk>_charged.udf)")
83
+ pt.add_argument("--mol-name", default=None)
84
+ pt.add_argument("--mol-index", type=int, default=None)
85
+ pt.add_argument("--no-verify-types", action="store_true")
86
+ pt.add_argument("--non-strict", action="store_true")
87
+ pt.add_argument("-v", "--verbose", action="store_true")
88
+ pt.set_defaults(func=_run_transfer)
89
+
90
+ pr = sub.add_parser("restore",
91
+ help="中和済み 1 分子 UDF の電荷を指定形式電荷に復元")
92
+ pr.add_argument("--udf", required=True, help="中和 (Σq≈0) された 1 分子 UDF")
93
+ pr.add_argument("--formal-charge", type=int, required=True,
94
+ help="目標の形式電荷 (整数)")
95
+ pr.add_argument("--out", default=None, help="出力 (省略時 <udf>_q<±S>.udf)")
96
+ pr.add_argument("--mode", choices=["proportional", "uniform"],
97
+ default="proportional",
98
+ help="中和ルール: proportional (|q| 比例、 既定) / uniform (均等分配)")
99
+ pr.add_argument("--mol-name", default=None)
100
+ pr.add_argument("--mol-index", type=int, default=0)
101
+ pr.add_argument("-v", "--verbose", action="store_true")
102
+ pr.set_defaults(func=_run_restore)
103
+
104
+ args = p.parse_args(argv)
105
+ if not getattr(args, "cmd", None):
106
+ p.print_help()
107
+ return 2
108
+
109
+ logging.basicConfig(
110
+ level=logging.INFO if getattr(args, "verbose", False) else logging.WARNING,
111
+ format="%(levelname)s %(name)s: %(message)s",
112
+ )
113
+ return args.func(args)
114
+
115
+
116
+ if __name__ == "__main__":
117
+ sys.exit(main())
@@ -21,6 +21,7 @@ COGNAC UDF の電荷規約 (gro2udf / udf2gro と共通):
21
21
  from __future__ import annotations
22
22
 
23
23
  import logging
24
+ import math
24
25
  from dataclasses import dataclass, field
25
26
  from pathlib import Path
26
27
  from typing import List, Optional
@@ -32,8 +33,10 @@ __all__ = [
32
33
  "POINT_CHARGE",
33
34
  "MoleculeChargeTemplate",
34
35
  "AssignResult",
36
+ "RestoreResult",
35
37
  "read_molecule_charges",
36
38
  "assign_charges_to_bulk",
39
+ "restore_formal_charge",
37
40
  ]
38
41
 
39
42
  # COGNAC: ES_Element = charge[e] * CHARGE_UNIT (gro2udf/udf2gro と同一定数)
@@ -45,6 +48,17 @@ _ATOM = "Set_of_Molecules.molecule[].atom[]"
45
48
  _ES = "Set_of_Molecules.molecule[].electrostatic_Site[]"
46
49
 
47
50
 
51
+ def _put_molecule_charges(u, imol, charges) -> None:
52
+ """molecule[imol] の各 atom に electrostatic_Site (POINT_CHARGE) を書く。
53
+
54
+ float() cast 必須: numpy 値だと UDFManager が silent 0 化する。
55
+ """
56
+ for k, q in enumerate(charges):
57
+ u.put(POINT_CHARGE, f"{_ES}.Type_Name", [imol, k])
58
+ u.put(float(q) * CHARGE_UNIT, f"{_ES}.ES_Element", [imol, k])
59
+ u.put(int(k), f"{_ES}.atom[]", [imol, k, 0])
60
+
61
+
48
62
  def _open(udf_path) -> "object":
49
63
  """UDFManager を開いて static record (jump(-1)) に移動して返す。"""
50
64
  from UDFManager import UDFManager # OCTA 同梱 (PyPI 非配布)
@@ -251,11 +265,7 @@ def assign_charges_to_bulk(
251
265
  skipped.append(i)
252
266
  continue
253
267
 
254
- for k in range(n_atoms):
255
- u.put(POINT_CHARGE, f"{_ES}.Type_Name", [i, k])
256
- # float() cast 必須: numpy 値だと UDFManager が silent 0 化する
257
- u.put(float(template.charges[k] * CHARGE_UNIT), f"{_ES}.ES_Element", [i, k])
258
- u.put(int(k), f"{_ES}.atom[]", [i, k, 0])
268
+ _put_molecule_charges(u, i, template.charges)
259
269
  assigned.append(i)
260
270
 
261
271
  if not assigned and strict:
@@ -277,3 +287,174 @@ def assign_charges_to_bulk(
277
287
  res.n_molecules_assigned, res.n_molecules_total, res.mol_name, out_path.name,
278
288
  )
279
289
  return res
290
+
291
+
292
+ # ---------------------------------------------------------------------------
293
+ # 形式電荷の復元 (neutralize の逆変換)
294
+ # ---------------------------------------------------------------------------
295
+ #
296
+ # 前提となる中和ルール (forward): 元電荷 A_i (Σ A = S = 形式電荷) を、 過剰分 S を
297
+ # ``|A_i|`` 比例で各原子に分散して中和し、 B_i (Σ B ≈ 0) を得る:
298
+ #
299
+ # B_i = A_i - S·|A_i| / Σ|A| (λ = S/Σ|A| とおくと)
300
+ # B_i = (1-λ)A_i (A_i>0)
301
+ # B_i = (1+λ)A_i (A_i<0)
302
+ #
303
+ # reverse (本機能): B_i と目標形式電荷 S だけから A_i を復元する。 符号は保存される
304
+ # (λ<1 のとき) ので:
305
+ #
306
+ # A_i = B_i/(1-λ) (B_i>0)
307
+ # A_i = B_i/(1+λ) (B_i<0)
308
+ #
309
+ # λ は Σ A = S の制約から、 P=Σ_{B>0}B / N=Σ_{B<0}B を用いて
310
+ #
311
+ # S·λ² + (P-N)·λ + (P+N-S) = 0
312
+ #
313
+ # の |λ|<1 の根として求まる (詳細は docs/udfcharge.md / SI/A列再現方法.md)。
314
+ #
315
+ # もう一つの中和ルール ``mode="uniform"`` (均等分配): 過剰分 S を全原子に均等に
316
+ # 分散して中和する。
317
+ #
318
+ # forward: B_i = A_i - S/N (N = 原子数、 Σ B = 0)
319
+ # reverse: A_i = B_i + S/N
320
+ #
321
+ # こちらは二次方程式も符号反転問題も無く、 常に厳密・一意に復元できる。
322
+
323
+
324
+ @dataclass
325
+ class RestoreResult:
326
+ """:func:`restore_formal_charge` の結果サマリ。"""
327
+
328
+ out_path: str
329
+ mol_name: str
330
+ n_atoms: int
331
+ formal_charge: int
332
+ input_total: float # 入力 UDF の総電荷 (≈0 を想定)
333
+ output_total: float # 出力 UDF の総電荷 (= formal_charge)
334
+ mode: str = "proportional" # "proportional" | "uniform"
335
+ lam: Optional[float] = None # proportional 時の λ (uniform では None)
336
+ shift: Optional[float] = None # uniform 時の S/N (proportional では None)
337
+
338
+
339
+ def _solve_neutralization_lambda(charges: List[float], formal_charge: float) -> float:
340
+ """中和電荷 (B) と目標形式電荷 S から逆変換用 λ を解く。
341
+
342
+ ``S·λ² + (P-N)·λ + (P+N-S) = 0`` (P=Σ_{B>0}B, N=Σ_{B<0}B) の |λ|<1 の根。
343
+ S≈0 のときは線形に縮退する。
344
+ """
345
+ P = sum(b for b in charges if b > 0.0)
346
+ N = sum(b for b in charges if b < 0.0)
347
+ S = float(formal_charge)
348
+ a, b, c = S, (P - N), (P + N - S)
349
+
350
+ if abs(a) < 1e-12: # S ≈ 0 → 線形 (P-N)λ + (P+N) = 0
351
+ if abs(b) < 1e-12:
352
+ return 0.0
353
+ lam = -(P + N) / b
354
+ else:
355
+ disc = b * b - 4.0 * a * c
356
+ if disc < 0:
357
+ raise ValueError(
358
+ f"形式電荷 {S:g} は |q| 比例分配ルールで到達不能です (判別式 < 0)"
359
+ )
360
+ sq = math.sqrt(disc)
361
+ roots = [(-b + sq) / (2.0 * a), (-b - sq) / (2.0 * a)]
362
+ valid = [r for r in roots if abs(r) < 1.0]
363
+ if not valid:
364
+ raise ValueError(
365
+ f"|λ|<1 の根が無く電荷符号が反転します (formal_charge={S:g} が大きすぎ、 "
366
+ "B 列と総和だけからは一意に復元できないケース)"
367
+ )
368
+ lam = min(valid, key=abs)
369
+ return lam
370
+
371
+
372
+ def restore_formal_charge(
373
+ udf_path,
374
+ formal_charge: int,
375
+ out_path=None,
376
+ *,
377
+ mol_index: int = 0,
378
+ mol_name: Optional[str] = None,
379
+ mode: str = "proportional",
380
+ ) -> RestoreResult:
381
+ """中和 (Σq≈0) された 1 分子 UDF の電荷を、 指定形式電荷になるよう逆変換して出力。
382
+
383
+ 過剰電荷を分散して中和した UDF (Σ電荷≈0) を入力に、 目標の **形式電荷 (整数) S**
384
+ を与えると、 中和前の per-atom 電荷 (Σ=S) を復元して別 UDF に書き出す。
385
+ ``electrostatic_Site`` のみ更新し、 座標・結合等は無改変。
386
+
387
+ **中和ルール (``mode``) を正しく選ぶこと** — UDF を中和した方法に一致させる:
388
+
389
+ - ``"proportional"`` (既定): 過剰分 S を ``|q|`` 比例で分散
390
+ (`B_i = A_i − S·|A_i|/Σ|A|`)。 逆変換は二次方程式で λ を解く。
391
+ ``|S| ≥ Σ|q|`` (符号反転) のケースは ``ValueError``。
392
+ - ``"uniform"``: 過剰分 S を全原子に**均等**に分散 (`B_i = A_i − S/N`)。
393
+ 逆変換は `A_i = B_i + S/N` で常に厳密・一意 (符号問題なし)。
394
+
395
+ Parameters
396
+ ----------
397
+ udf_path
398
+ 中和済み電荷を持つ 1 分子 UDF。
399
+ formal_charge
400
+ 目標の形式電荷 (整数)。 出力 UDF の総電荷がこの値になる。
401
+ out_path
402
+ 出力 UDF。 省略時 ``<udf>_q<±S>.udf``。
403
+ mol_index / mol_name
404
+ 対象分子 (既定は先頭=0、 単分子 UDF を想定)。
405
+ mode
406
+ 中和ルール: ``"proportional"`` (既定) または ``"uniform"``。
407
+
408
+ Returns
409
+ -------
410
+ RestoreResult
411
+ """
412
+ udf_path = Path(udf_path)
413
+ S = int(formal_charge)
414
+ if out_path is None:
415
+ out_path = udf_path.with_name(f"{udf_path.stem}_q{S:+d}{udf_path.suffix}")
416
+ out_path = Path(out_path)
417
+
418
+ tmpl = read_molecule_charges(udf_path, mol_index=mol_index, mol_name=mol_name)
419
+ B = tmpl.charges
420
+ input_total = float(sum(B))
421
+
422
+ lam: Optional[float] = None
423
+ shift: Optional[float] = None
424
+ if mode == "proportional":
425
+ lam = _solve_neutralization_lambda(B, S)
426
+ A = [
427
+ (b / (1.0 - lam) if b > 0.0 else (b / (1.0 + lam) if b < 0.0 else 0.0))
428
+ for b in B
429
+ ]
430
+ elif mode == "uniform":
431
+ shift = float(S) / tmpl.n_atoms
432
+ A = [b + shift for b in B]
433
+ else:
434
+ raise ValueError(
435
+ f"mode={mode!r} は未対応です ('proportional' / 'uniform' から選択)"
436
+ )
437
+ output_total = float(sum(A))
438
+
439
+ u = _open(udf_path)
440
+ _put_molecule_charges(u, tmpl.source_index, A)
441
+ u.write(str(out_path))
442
+
443
+ res = RestoreResult(
444
+ out_path=str(out_path),
445
+ mol_name=tmpl.mol_name,
446
+ n_atoms=tmpl.n_atoms,
447
+ formal_charge=S,
448
+ input_total=input_total,
449
+ output_total=output_total,
450
+ mode=mode,
451
+ lam=lam,
452
+ shift=shift,
453
+ )
454
+ detail = f"λ={lam:.8f}" if mode == "proportional" else f"shift=S/N={shift:.8f}"
455
+ logger.info(
456
+ "restore[%s]: %r %d atoms, Σq %.6f → %.6f (target %d, %s) → %s",
457
+ mode, res.mol_name, res.n_atoms, input_total, output_total, S, detail,
458
+ out_path.name,
459
+ )
460
+ return res
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: abmptools
3
- Version: 2.2.0
3
+ Version: 2.2.1
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
@@ -121,7 +121,7 @@ A Python toolkit for pre-processing, post-processing, and analysis of Fragment M
121
121
 
122
122
  - **udf2gro**: Convert OCTA UDF files to GROMACS format (`.gro`, `.top`, `.mdp`, `.itp`)
123
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
124
+ - **udfcharge**: Transfer per-atom partial charges from a single-molecule UDF to bulk molecules (`transfer`), or restore a neutralized UDF's charges to a target integer formal charge (`restore`)
125
125
 
126
126
  ### Geometry Optimization (`geomopt`)
127
127
 
@@ -314,7 +314,10 @@ python -m abmptools.udf2gro.cli -i system.udf -o output
314
314
  python -m abmptools.gro2udf.cli -i system.gro -t system.top -o output.udf
315
315
 
316
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
317
+ python -m abmptools.udfcharge transfer --template mol.udf --bulk bulk.udf --out bulk_charged.udf
318
+
319
+ # Restore a neutralized UDF's charges to a target integer formal charge
320
+ python -m abmptools.udfcharge restore --udf mol.udf --formal-charge 12 --out mol_q+12.udf
318
321
 
319
322
  # Build an amorphous mixture from SMILES (50 ketoprofen molecules, density 0.8 g/cm^3)
320
323
  python -m abmptools.amorphous --smiles "OC(=O)C(C)c1cccc(C(=O)c2ccccc2)c1" \
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "abmptools"
7
- version = "2.2.0"
7
+ version = "2.2.1"
8
8
  description = "Pre/post-processing and analysis toolkit for ABINIT-MP Fragment Molecular Orbital calculations"
9
9
  readme = {file = "README.md", content-type = "text/markdown"}
10
10
  license = "Apache-2.0"
@@ -1,63 +0,0 @@
1
- """CLI: 単分子 UDF の電荷をバルク UDF の同名分子へ割り当てる。
2
-
3
- python -m abmptools.udfcharge --template mol.udf --bulk bulk.udf \
4
- [--out bulk_charged.udf] [--mol-name NAME] [--mol-index I] \
5
- [--no-verify-types] [--non-strict]
6
- """
7
-
8
- from __future__ import annotations
9
-
10
- import argparse
11
- import logging
12
- import sys
13
-
14
- from .core import assign_charges_to_bulk, read_molecule_charges
15
-
16
-
17
- def main(argv=None) -> int:
18
- p = argparse.ArgumentParser(
19
- prog="python -m abmptools.udfcharge",
20
- description="単分子 UDF (電荷あり) の per-atom 電荷を、 バルク UDF の同名分子"
21
- "すべてへ割り当てる (OCTA/COGNAC electrostatic_Site)。",
22
- )
23
- p.add_argument("--template", required=True,
24
- help="電荷を持つ単分子 UDF")
25
- p.add_argument("--bulk", required=True,
26
- help="割り当て先のバルク UDF (同名分子が複数、 電荷なし)")
27
- p.add_argument("--out", default=None,
28
- help="出力 UDF (省略時 <bulk>_charged.udf)")
29
- p.add_argument("--mol-name", default=None,
30
- help="template から抽出する分子の Mol_Name (省略時 先頭分子)")
31
- p.add_argument("--mol-index", type=int, default=None,
32
- help="template から抽出する分子の index (--mol-name より優先)")
33
- p.add_argument("--no-verify-types", action="store_true",
34
- help="Atom_Type_Name 列の一致検証を無効化")
35
- p.add_argument("--non-strict", action="store_true",
36
- help="検証不一致を例外でなく warning + skip で処理")
37
- p.add_argument("-v", "--verbose", action="store_true", help="INFO ログを出力")
38
- args = p.parse_args(argv)
39
-
40
- logging.basicConfig(
41
- level=logging.INFO if args.verbose else logging.WARNING,
42
- format="%(levelname)s %(name)s: %(message)s",
43
- )
44
-
45
- tmpl = read_molecule_charges(
46
- args.template, mol_name=args.mol_name, mol_index=args.mol_index,
47
- )
48
- res = assign_charges_to_bulk(
49
- args.bulk, tmpl, args.out,
50
- verify_atom_types=not args.no_verify_types,
51
- strict=not args.non_strict,
52
- )
53
- print(f"template : {tmpl.mol_name} (n_atoms={tmpl.n_atoms}, "
54
- f"net_charge={tmpl.net_charge:+.4f})")
55
- print(f"assigned : {res.n_molecules_assigned}/{res.n_molecules_total} molecules")
56
- if res.skipped_indices:
57
- print(f"skipped : {res.skipped_indices}")
58
- print(f"output : {res.out_path}")
59
- return 0
60
-
61
-
62
- if __name__ == "__main__":
63
- sys.exit(main())
File without changes
File without changes
File without changes