MoleditPy 3.0.0a4__tar.gz → 3.0.0a6__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.
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/PKG-INFO +4 -4
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/README.md +3 -3
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/pyproject.toml +1 -1
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/MoleditPy.egg-info/PKG-INFO +4 -4
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/MoleditPy.egg-info/SOURCES.txt +4 -6
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/core/mol_geometry.py +78 -5
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/core/molecular_data.py +15 -4
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/main.py +0 -1
- moleditpy-3.0.0a6/src/moleditpy/plugins/plugin_interface.py +400 -0
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/plugins/plugin_manager.py +110 -6
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/plugins/plugin_manager_window.py +313 -313
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/ui/about_dialog.py +2 -2
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/ui/align_plane_dialog.py +18 -96
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/ui/alignment_dialog.py +7 -9
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/ui/angle_dialog.py +404 -516
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/ui/app_state.py +245 -283
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/ui/atom_item.py +24 -14
- moleditpy-3.0.0a6/src/moleditpy/ui/base_picking_dialog.py +126 -0
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/ui/bond_item.py +73 -87
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/ui/bond_length_dialog.py +351 -456
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/ui/calculation_worker.py +32 -18
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/ui/color_settings_dialog.py +81 -31
- moleditpy-3.0.0a6/src/moleditpy/ui/compute_logic.py +673 -0
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/ui/constrained_optimization_dialog.py +43 -26
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/ui/custom_interactor_style.py +129 -101
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/ui/custom_qt_interactor.py +4 -4
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/ui/dialog_3d_picking_mixin.py +53 -34
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/ui/dialog_logic.py +176 -136
- moleditpy-3.0.0a6/src/moleditpy/ui/dihedral_dialog.py +406 -0
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/ui/edit_3d_logic.py +70 -46
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/ui/edit_actions_logic.py +382 -151
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/ui/export_logic.py +156 -144
- moleditpy-3.0.0a6/src/moleditpy/ui/geometry_base_dialog.py +113 -0
- moleditpy-3.0.0a6/src/moleditpy/ui/io_logic.py +1024 -0
- moleditpy-3.0.0a6/src/moleditpy/ui/main_window.py +99 -0
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/ui/main_window_init.py +696 -520
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/ui/mirror_dialog.py +3 -3
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/ui/molecular_scene_handler.py +75 -35
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/ui/molecule_scene.py +74 -21
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/ui/move_group_dialog.py +131 -211
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/ui/planarize_dialog.py +21 -66
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/ui/settings_dialog.py +41 -66
- {moleditpy-3.0.0a4/src/moleditpy/utils → moleditpy-3.0.0a6/src/moleditpy/ui/settings_tabs}/__init__.py +11 -11
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/ui/settings_tabs/settings_2d_tab.py +7 -36
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/ui/settings_tabs/settings_3d_tabs.py +28 -73
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/ui/settings_tabs/settings_other_tab.py +18 -6
- moleditpy-3.0.0a6/src/moleditpy/ui/settings_tabs/settings_tab_base.py +63 -0
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/ui/string_importers.py +56 -46
- moleditpy-3.0.0a6/src/moleditpy/ui/translation_dialog.py +193 -0
- moleditpy-3.0.0a6/src/moleditpy/ui/ui_manager.py +602 -0
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/ui/user_template_dialog.py +45 -33
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/ui/view_3d_logic.py +429 -208
- {moleditpy-3.0.0a4/src/moleditpy/plugins → moleditpy-3.0.0a6/src/moleditpy/utils}/__init__.py +11 -11
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/utils/constants.py +1 -1
- moleditpy-3.0.0a6/src/moleditpy/utils/default_settings.py +85 -0
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/utils/sip_isdeleted_safe.py +41 -41
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/utils/system_utils.py +71 -71
- moleditpy-3.0.0a4/src/moleditpy/modules/__init__.py +0 -122
- moleditpy-3.0.0a4/src/moleditpy/plugins/plugin_interface.py +0 -230
- moleditpy-3.0.0a4/src/moleditpy/ui/compute_engine.py +0 -880
- moleditpy-3.0.0a4/src/moleditpy/ui/compute_logic.py +0 -529
- moleditpy-3.0.0a4/src/moleditpy/ui/dialog_manager.py +0 -464
- moleditpy-3.0.0a4/src/moleditpy/ui/dihedral_dialog.py +0 -545
- moleditpy-3.0.0a4/src/moleditpy/ui/main_window.py +0 -218
- moleditpy-3.0.0a4/src/moleditpy/ui/molecular_parsers.py +0 -592
- moleditpy-3.0.0a4/src/moleditpy/ui/project_io.py +0 -387
- moleditpy-3.0.0a4/src/moleditpy/ui/settings_tabs/settings_tab_base.py +0 -33
- moleditpy-3.0.0a4/src/moleditpy/ui/translation_dialog.py +0 -347
- moleditpy-3.0.0a4/src/moleditpy/ui/ui_manager.py +0 -511
- moleditpy-3.0.0a4/src/moleditpy/ui/view_loaders.py +0 -274
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/LICENSE +0 -0
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/setup.cfg +0 -0
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/MoleditPy.egg-info/dependency_links.txt +0 -0
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/MoleditPy.egg-info/entry_points.txt +0 -0
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/MoleditPy.egg-info/requires.txt +0 -0
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/MoleditPy.egg-info/top_level.txt +0 -0
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/__init__.py +0 -0
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/__main__.py +0 -0
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/assets/file_icon.ico +0 -0
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/assets/icon.icns +0 -0
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/assets/icon.ico +0 -0
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/assets/icon.png +0 -0
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/core/__init__.py +0 -0
- {moleditpy-3.0.0a4/src/moleditpy/ui/settings_tabs → moleditpy-3.0.0a6/src/moleditpy/plugins}/__init__.py +0 -0
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/ui/__init__.py +0 -0
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/ui/analysis_window.py +0 -0
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/ui/periodic_table_dialog.py +0 -0
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/ui/sip_isdeleted_safe.py +0 -0
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/ui/template_preview_item.py +0 -0
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/ui/template_preview_view.py +0 -0
- {moleditpy-3.0.0a4 → moleditpy-3.0.0a6}/src/moleditpy/ui/zoomable_view.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: MoleditPy
|
|
3
|
-
Version: 3.0.
|
|
3
|
+
Version: 3.0.0a6
|
|
4
4
|
Summary: A cross-platform, simple, and intuitive molecular structure editor built in Python. It allows 2D molecular drawing and 3D structure visualization. It supports exporting structure files for input to DFT calculation software.
|
|
5
5
|
Author-email: HiroYokoyama <titech.yoko.hiro@gmail.com>
|
|
6
6
|
License: GNU GENERAL PUBLIC LICENSE
|
|
@@ -710,10 +710,10 @@ Dynamic: license-file
|
|
|
710
710
|
[](https://pypi.org/project/MoleditPy/)
|
|
711
711
|
[](https://www.gnu.org/licenses/gpl-3.0)
|
|
712
712
|
[](https://github.com/HiroYokoyama/python_molecular_editor/actions)
|
|
713
|
-

|
|
714
|
+

|
|
715
715
|

|
|
716
|
-

|
|
717
717
|
[](https://pepy.tech/projects/moleditpy)
|
|
718
718
|
|
|
719
719
|
[🇯🇵 日本語 (Japanese)](#japanese)
|
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
[](https://pypi.org/project/MoleditPy/)
|
|
7
7
|
[](https://www.gnu.org/licenses/gpl-3.0)
|
|
8
8
|
[](https://github.com/HiroYokoyama/python_molecular_editor/actions)
|
|
9
|
-

|
|
10
|
+

|
|
11
11
|

|
|
12
|
-

|
|
13
13
|
[](https://pepy.tech/projects/moleditpy)
|
|
14
14
|
|
|
15
15
|
[🇯🇵 日本語 (Japanese)](#japanese)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: MoleditPy
|
|
3
|
-
Version: 3.0.
|
|
3
|
+
Version: 3.0.0a6
|
|
4
4
|
Summary: A cross-platform, simple, and intuitive molecular structure editor built in Python. It allows 2D molecular drawing and 3D structure visualization. It supports exporting structure files for input to DFT calculation software.
|
|
5
5
|
Author-email: HiroYokoyama <titech.yoko.hiro@gmail.com>
|
|
6
6
|
License: GNU GENERAL PUBLIC LICENSE
|
|
@@ -710,10 +710,10 @@ Dynamic: license-file
|
|
|
710
710
|
[](https://pypi.org/project/MoleditPy/)
|
|
711
711
|
[](https://www.gnu.org/licenses/gpl-3.0)
|
|
712
712
|
[](https://github.com/HiroYokoyama/python_molecular_editor/actions)
|
|
713
|
-

|
|
714
|
+

|
|
715
715
|

|
|
716
|
-

|
|
717
717
|
[](https://pepy.tech/projects/moleditpy)
|
|
718
718
|
|
|
719
719
|
[🇯🇵 日本語 (Japanese)](#japanese)
|
|
@@ -23,7 +23,6 @@ src/moleditpy/assets/icon.png
|
|
|
23
23
|
src/moleditpy/core/__init__.py
|
|
24
24
|
src/moleditpy/core/mol_geometry.py
|
|
25
25
|
src/moleditpy/core/molecular_data.py
|
|
26
|
-
src/moleditpy/modules/__init__.py
|
|
27
26
|
src/moleditpy/plugins/__init__.py
|
|
28
27
|
src/moleditpy/plugins/plugin_interface.py
|
|
29
28
|
src/moleditpy/plugins/plugin_manager.py
|
|
@@ -36,32 +35,31 @@ src/moleditpy/ui/analysis_window.py
|
|
|
36
35
|
src/moleditpy/ui/angle_dialog.py
|
|
37
36
|
src/moleditpy/ui/app_state.py
|
|
38
37
|
src/moleditpy/ui/atom_item.py
|
|
38
|
+
src/moleditpy/ui/base_picking_dialog.py
|
|
39
39
|
src/moleditpy/ui/bond_item.py
|
|
40
40
|
src/moleditpy/ui/bond_length_dialog.py
|
|
41
41
|
src/moleditpy/ui/calculation_worker.py
|
|
42
42
|
src/moleditpy/ui/color_settings_dialog.py
|
|
43
|
-
src/moleditpy/ui/compute_engine.py
|
|
44
43
|
src/moleditpy/ui/compute_logic.py
|
|
45
44
|
src/moleditpy/ui/constrained_optimization_dialog.py
|
|
46
45
|
src/moleditpy/ui/custom_interactor_style.py
|
|
47
46
|
src/moleditpy/ui/custom_qt_interactor.py
|
|
48
47
|
src/moleditpy/ui/dialog_3d_picking_mixin.py
|
|
49
48
|
src/moleditpy/ui/dialog_logic.py
|
|
50
|
-
src/moleditpy/ui/dialog_manager.py
|
|
51
49
|
src/moleditpy/ui/dihedral_dialog.py
|
|
52
50
|
src/moleditpy/ui/edit_3d_logic.py
|
|
53
51
|
src/moleditpy/ui/edit_actions_logic.py
|
|
54
52
|
src/moleditpy/ui/export_logic.py
|
|
53
|
+
src/moleditpy/ui/geometry_base_dialog.py
|
|
54
|
+
src/moleditpy/ui/io_logic.py
|
|
55
55
|
src/moleditpy/ui/main_window.py
|
|
56
56
|
src/moleditpy/ui/main_window_init.py
|
|
57
57
|
src/moleditpy/ui/mirror_dialog.py
|
|
58
|
-
src/moleditpy/ui/molecular_parsers.py
|
|
59
58
|
src/moleditpy/ui/molecular_scene_handler.py
|
|
60
59
|
src/moleditpy/ui/molecule_scene.py
|
|
61
60
|
src/moleditpy/ui/move_group_dialog.py
|
|
62
61
|
src/moleditpy/ui/periodic_table_dialog.py
|
|
63
62
|
src/moleditpy/ui/planarize_dialog.py
|
|
64
|
-
src/moleditpy/ui/project_io.py
|
|
65
63
|
src/moleditpy/ui/settings_dialog.py
|
|
66
64
|
src/moleditpy/ui/sip_isdeleted_safe.py
|
|
67
65
|
src/moleditpy/ui/string_importers.py
|
|
@@ -71,7 +69,6 @@ src/moleditpy/ui/translation_dialog.py
|
|
|
71
69
|
src/moleditpy/ui/ui_manager.py
|
|
72
70
|
src/moleditpy/ui/user_template_dialog.py
|
|
73
71
|
src/moleditpy/ui/view_3d_logic.py
|
|
74
|
-
src/moleditpy/ui/view_loaders.py
|
|
75
72
|
src/moleditpy/ui/zoomable_view.py
|
|
76
73
|
src/moleditpy/ui/settings_tabs/__init__.py
|
|
77
74
|
src/moleditpy/ui/settings_tabs/settings_2d_tab.py
|
|
@@ -80,5 +77,6 @@ src/moleditpy/ui/settings_tabs/settings_other_tab.py
|
|
|
80
77
|
src/moleditpy/ui/settings_tabs/settings_tab_base.py
|
|
81
78
|
src/moleditpy/utils/__init__.py
|
|
82
79
|
src/moleditpy/utils/constants.py
|
|
80
|
+
src/moleditpy/utils/default_settings.py
|
|
83
81
|
src/moleditpy/utils/sip_isdeleted_safe.py
|
|
84
82
|
src/moleditpy/utils/system_utils.py
|
|
@@ -12,7 +12,6 @@ DOI: 10.5281/zenodo.17268532
|
|
|
12
12
|
|
|
13
13
|
from __future__ import annotations
|
|
14
14
|
import math
|
|
15
|
-
import logging
|
|
16
15
|
from collections import deque
|
|
17
16
|
from typing import Any, Dict, Iterable, List, Optional, Set, Tuple, Union
|
|
18
17
|
|
|
@@ -22,7 +21,11 @@ import numpy as np
|
|
|
22
21
|
# Primitive geometry helpers
|
|
23
22
|
# ------------------------------------------------------------------
|
|
24
23
|
|
|
25
|
-
|
|
24
|
+
|
|
25
|
+
def calc_distance(
|
|
26
|
+
pos1: Union[np.ndarray, Tuple[float, float, float], List[float]],
|
|
27
|
+
pos2: Union[np.ndarray, Tuple[float, float, float], List[float]],
|
|
28
|
+
) -> float:
|
|
26
29
|
"""Return the Euclidean distance between two 3-D positions.
|
|
27
30
|
|
|
28
31
|
Parameters
|
|
@@ -78,7 +81,9 @@ def calc_angle_deg(
|
|
|
78
81
|
# ------------------------------------------------------------------
|
|
79
82
|
|
|
80
83
|
|
|
81
|
-
def get_connected_group(
|
|
84
|
+
def get_connected_group(
|
|
85
|
+
mol: Any, start_atom: int, exclude: Optional[int] = None
|
|
86
|
+
) -> Set[int]:
|
|
82
87
|
"""Return the set of atom indices reachable from *start_atom*
|
|
83
88
|
without passing through *exclude*.
|
|
84
89
|
|
|
@@ -300,6 +305,70 @@ def calculate_dihedral(positions: Any, i1: int, i2: int, i3: int, i4: int) -> fl
|
|
|
300
305
|
return float(np.degrees(angle_rad))
|
|
301
306
|
|
|
302
307
|
|
|
308
|
+
def adjust_dihedral(
|
|
309
|
+
positions: np.ndarray,
|
|
310
|
+
i1: int,
|
|
311
|
+
i2: int,
|
|
312
|
+
i3: int,
|
|
313
|
+
i4: int,
|
|
314
|
+
target_dihedral_deg: float,
|
|
315
|
+
atom_indices_to_move: Iterable[int],
|
|
316
|
+
) -> float:
|
|
317
|
+
"""Adjust the dihedral angle defined by i1-i2-i3-i4 to target_dihedral_deg.
|
|
318
|
+
The rotation is performed around the i2-i3 bond axis.
|
|
319
|
+
|
|
320
|
+
Parameters
|
|
321
|
+
----------
|
|
322
|
+
positions : ndarray, shape (N, 3)
|
|
323
|
+
Atom coordinates. **Modified in-place.**
|
|
324
|
+
i1, i2, i3, i4 : int
|
|
325
|
+
Atom indices defining the dihedral.
|
|
326
|
+
target_dihedral_deg : float
|
|
327
|
+
Target dihedral angle in degrees.
|
|
328
|
+
atom_indices_to_move : iterable of int
|
|
329
|
+
Indices of atoms to be rotated.
|
|
330
|
+
|
|
331
|
+
Returns
|
|
332
|
+
-------
|
|
333
|
+
float
|
|
334
|
+
Applied rotation in radians.
|
|
335
|
+
"""
|
|
336
|
+
# Current dihedral
|
|
337
|
+
current_dihedral = calculate_dihedral(positions, i1, i2, i3, i4)
|
|
338
|
+
|
|
339
|
+
# Rotation angle needed
|
|
340
|
+
delta_deg = target_dihedral_deg - current_dihedral
|
|
341
|
+
|
|
342
|
+
# Shortest rotation path
|
|
343
|
+
if delta_deg > 180:
|
|
344
|
+
delta_deg -= 360
|
|
345
|
+
elif delta_deg < -180:
|
|
346
|
+
delta_deg += 360
|
|
347
|
+
|
|
348
|
+
delta_rad = np.radians(delta_deg)
|
|
349
|
+
|
|
350
|
+
if abs(delta_rad) < 1e-9:
|
|
351
|
+
return 0.0
|
|
352
|
+
|
|
353
|
+
# Rotation axis (i2 -> i3)
|
|
354
|
+
pos2 = positions[i2]
|
|
355
|
+
pos3 = positions[i3]
|
|
356
|
+
axis = pos3 - pos2
|
|
357
|
+
axis_norm = np.linalg.norm(axis)
|
|
358
|
+
|
|
359
|
+
if axis_norm < 1e-12:
|
|
360
|
+
return 0.0
|
|
361
|
+
|
|
362
|
+
axis_unit = axis / axis_norm
|
|
363
|
+
|
|
364
|
+
# Rotate each movable atom
|
|
365
|
+
for idx in atom_indices_to_move:
|
|
366
|
+
rel = positions[idx] - pos2
|
|
367
|
+
positions[idx] = pos2 + rodrigues_rotate(rel, axis_unit, delta_rad)
|
|
368
|
+
|
|
369
|
+
return float(delta_rad)
|
|
370
|
+
|
|
371
|
+
|
|
303
372
|
# ------------------------------------------------------------------
|
|
304
373
|
# Valence sanity check
|
|
305
374
|
# ------------------------------------------------------------------
|
|
@@ -319,7 +388,9 @@ _VALENCE_LIMITS = {
|
|
|
319
388
|
}
|
|
320
389
|
|
|
321
390
|
|
|
322
|
-
def is_problematic_valence(
|
|
391
|
+
def is_problematic_valence(
|
|
392
|
+
symbol: str, bond_count: Union[int, float], charge: int = 0
|
|
393
|
+
) -> bool:
|
|
323
394
|
"""Return ``True`` if the atom's total bond order exceeds its
|
|
324
395
|
typical maximum valence.
|
|
325
396
|
|
|
@@ -411,7 +482,9 @@ def inject_ez_stereo_to_mol_block(mol_block, rdkit_mol, bonds_data):
|
|
|
411
482
|
return "\n".join(mol_lines)
|
|
412
483
|
|
|
413
484
|
|
|
414
|
-
def identify_valence_problems(
|
|
485
|
+
def identify_valence_problems(
|
|
486
|
+
atoms_data: Dict[int, Any], bonds_data: Dict[Tuple[int, int], Any]
|
|
487
|
+
) -> List[int]:
|
|
415
488
|
"""Identify atoms with problematic valence.
|
|
416
489
|
|
|
417
490
|
Parameters
|
|
@@ -12,7 +12,7 @@ DOI: 10.5281/zenodo.17268532
|
|
|
12
12
|
|
|
13
13
|
from __future__ import annotations
|
|
14
14
|
import logging
|
|
15
|
-
from typing import Any, Dict, List, Optional,
|
|
15
|
+
from typing import Any, Dict, List, Optional, Tuple, Union
|
|
16
16
|
from rdkit import Chem
|
|
17
17
|
|
|
18
18
|
try:
|
|
@@ -43,7 +43,13 @@ class MolecularData:
|
|
|
43
43
|
self._next_atom_id = 0
|
|
44
44
|
self.adjacency_list = {}
|
|
45
45
|
|
|
46
|
-
def add_atom(
|
|
46
|
+
def add_atom(
|
|
47
|
+
self,
|
|
48
|
+
symbol: str,
|
|
49
|
+
pos: Union[Any, Tuple[float, float]],
|
|
50
|
+
charge: int = 0,
|
|
51
|
+
radical: int = 0,
|
|
52
|
+
) -> int:
|
|
47
53
|
atom_id = self._next_atom_id
|
|
48
54
|
# Internalize position as raw floats to decouple from UI types (QPointF)
|
|
49
55
|
if hasattr(pos, "x") and hasattr(pos, "y"):
|
|
@@ -72,7 +78,9 @@ class MolecularData:
|
|
|
72
78
|
else:
|
|
73
79
|
self.atoms[atom_id]["pos"] = PointTuple((float(pos[0]), float(pos[1])))
|
|
74
80
|
|
|
75
|
-
def add_bond(
|
|
81
|
+
def add_bond(
|
|
82
|
+
self, id1: int, id2: int, order: Union[int, float] = 1, stereo: int = 0
|
|
83
|
+
) -> Tuple[Tuple[int, int], str]:
|
|
76
84
|
# For stereo bonds, do not sort because ID order determines direction.
|
|
77
85
|
# For non-stereo bonds, sort to normalize the key.
|
|
78
86
|
if stereo == 0:
|
|
@@ -154,6 +162,7 @@ class MolecularData:
|
|
|
154
162
|
atom.SetFormalCharge(data.get("charge", 0))
|
|
155
163
|
atom.SetNumRadicalElectrons(data.get("radical", 0))
|
|
156
164
|
atom.SetIntProp("_original_atom_id", atom_id)
|
|
165
|
+
atom.SetNoImplicit(False) # Allow RDKit to perceive implicit valence
|
|
157
166
|
idx = mol.AddAtom(atom)
|
|
158
167
|
atom_id_to_idx_map[atom_id] = idx
|
|
159
168
|
|
|
@@ -456,7 +465,9 @@ class MolecularData:
|
|
|
456
465
|
mol_block += "M END\n"
|
|
457
466
|
return mol_block
|
|
458
467
|
|
|
459
|
-
def to_template_dict(
|
|
468
|
+
def to_template_dict(
|
|
469
|
+
self, name: str, version: str = "1.0", application_version: str = ""
|
|
470
|
+
) -> Dict[str, Any]:
|
|
460
471
|
"""Convert current structure to a dictionary for template storage."""
|
|
461
472
|
import datetime
|
|
462
473
|
|