MoleditPy-linux 3.1.0__tar.gz → 3.3.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.
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/PKG-INFO +3 -5
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/README.md +2 -4
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/pyproject.toml +1 -1
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/MoleditPy_linux.egg-info/PKG-INFO +3 -5
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/MoleditPy_linux.egg-info/SOURCES.txt +1 -1
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/__main__.py +2 -2
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/core/mol_geometry.py +26 -17
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/core/molecular_data.py +20 -13
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/main.py +4 -3
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/plugins/plugin_interface.py +31 -24
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/plugins/plugin_manager.py +29 -17
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/plugins/plugin_manager_window.py +15 -9
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/ui/__init__.py +1 -1
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/ui/about_dialog.py +15 -7
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/ui/align_plane_dialog.py +28 -12
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/ui/alignment_dialog.py +30 -24
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/ui/analysis_window.py +14 -4
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/ui/angle_dialog.py +64 -31
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/ui/app_state.py +32 -24
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/ui/atom_item.py +3 -1
- moleditpy_linux-3.3.0/src/moleditpy_linux/ui/atom_picking.py +163 -0
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/ui/base_picking_dialog.py +33 -16
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/ui/bond_item.py +2 -2
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/ui/bond_length_dialog.py +43 -20
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/ui/calculation_worker.py +81 -48
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/ui/color_settings_dialog.py +13 -10
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/ui/compute_logic.py +17 -18
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/ui/constrained_optimization_dialog.py +152 -64
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/ui/custom_interactor_style.py +203 -165
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/ui/custom_qt_interactor.py +11 -5
- moleditpy_linux-3.3.0/src/moleditpy_linux/ui/dialog_3d_picking_mixin.py +260 -0
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/ui/dialog_logic.py +27 -23
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/ui/dihedral_dialog.py +83 -38
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/ui/edit_3d_logic.py +94 -74
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/ui/edit_actions_logic.py +39 -30
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/ui/export_logic.py +101 -108
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/ui/geometry_base_dialog.py +30 -8
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/ui/io_logic.py +9 -7
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/ui/main_window.py +27 -10
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/ui/main_window_init.py +176 -108
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/ui/mirror_dialog.py +11 -7
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/ui/molecular_scene_handler.py +31 -23
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/ui/molecule_scene.py +25 -21
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/ui/move_group_dialog.py +132 -130
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/ui/periodic_table_dialog.py +4 -2
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/ui/planarize_dialog.py +26 -9
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/ui/settings_dialog.py +9 -8
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/ui/settings_tabs/settings_2d_tab.py +15 -9
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/ui/settings_tabs/settings_3d_tabs.py +27 -15
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/ui/settings_tabs/settings_other_tab.py +20 -7
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/ui/settings_tabs/settings_tab_base.py +15 -8
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/ui/string_importers.py +13 -9
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/ui/template_preview_item.py +28 -12
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/ui/template_preview_view.py +12 -7
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/ui/translation_dialog.py +33 -23
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/ui/ui_manager.py +53 -30
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/ui/user_template_dialog.py +30 -26
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/ui/view_3d_logic.py +209 -147
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/ui/zoomable_view.py +24 -11
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/utils/constants.py +1 -1
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/utils/sip_isdeleted_safe.py +2 -2
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/utils/system_utils.py +6 -3
- moleditpy_linux-3.1.0/src/moleditpy_linux/ui/dialog_3d_picking_mixin.py +0 -252
- moleditpy_linux-3.1.0/src/moleditpy_linux/ui/sip_isdeleted_safe.py +0 -35
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/LICENSE +0 -0
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/setup.cfg +0 -0
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/MoleditPy_linux.egg-info/dependency_links.txt +0 -0
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/MoleditPy_linux.egg-info/entry_points.txt +0 -0
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/MoleditPy_linux.egg-info/requires.txt +0 -0
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/MoleditPy_linux.egg-info/top_level.txt +0 -0
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/__init__.py +0 -0
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/assets/file_icon.ico +0 -0
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/assets/icon.icns +0 -0
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/assets/icon.ico +0 -0
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/assets/icon.png +0 -0
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/core/__init__.py +0 -0
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/plugins/__init__.py +0 -0
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/ui/settings_tabs/__init__.py +0 -0
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/utils/__init__.py +0 -0
- {moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/utils/default_settings.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: MoleditPy-linux
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.3.0
|
|
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
|
|
@@ -703,16 +703,14 @@ Dynamic: license-file
|
|
|
703
703
|
|
|
704
704
|
# MoleditPy — A Python Molecular Editor
|
|
705
705
|
|
|
706
|
-
This is the Linux version of MoleditPy. The Open Babel fallback is disabled due to compatibility reasons.
|
|
707
|
-
|
|
708
706
|
[](https://doi.org/10.5281/zenodo.17268532)
|
|
709
707
|
[](https://www.rdkit.org/)
|
|
710
708
|
[](https://badge.fury.io/py/MoleditPy)
|
|
711
709
|
[](https://pypi.org/project/MoleditPy/)
|
|
712
710
|
[](https://www.gnu.org/licenses/gpl-3.0)
|
|
713
711
|
[](https://github.com/HiroYokoyama/python_molecular_editor/actions)
|
|
714
|
-

|
|
713
|
+

|
|
716
714
|

|
|
717
715
|

|
|
718
716
|
[](https://pepy.tech/projects/moleditpy)
|
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
# MoleditPy — A Python Molecular Editor
|
|
2
2
|
|
|
3
|
-
This is the Linux version of MoleditPy. The Open Babel fallback is disabled due to compatibility reasons.
|
|
4
|
-
|
|
5
3
|
[](https://doi.org/10.5281/zenodo.17268532)
|
|
6
4
|
[](https://www.rdkit.org/)
|
|
7
5
|
[](https://badge.fury.io/py/MoleditPy)
|
|
8
6
|
[](https://pypi.org/project/MoleditPy/)
|
|
9
7
|
[](https://www.gnu.org/licenses/gpl-3.0)
|
|
10
8
|
[](https://github.com/HiroYokoyama/python_molecular_editor/actions)
|
|
11
|
-

|
|
10
|
+

|
|
13
11
|

|
|
14
12
|

|
|
15
13
|
[](https://pepy.tech/projects/moleditpy)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: MoleditPy-linux
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.3.0
|
|
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
|
|
@@ -703,16 +703,14 @@ Dynamic: license-file
|
|
|
703
703
|
|
|
704
704
|
# MoleditPy — A Python Molecular Editor
|
|
705
705
|
|
|
706
|
-
This is the Linux version of MoleditPy. The Open Babel fallback is disabled due to compatibility reasons.
|
|
707
|
-
|
|
708
706
|
[](https://doi.org/10.5281/zenodo.17268532)
|
|
709
707
|
[](https://www.rdkit.org/)
|
|
710
708
|
[](https://badge.fury.io/py/MoleditPy)
|
|
711
709
|
[](https://pypi.org/project/MoleditPy/)
|
|
712
710
|
[](https://www.gnu.org/licenses/gpl-3.0)
|
|
713
711
|
[](https://github.com/HiroYokoyama/python_molecular_editor/actions)
|
|
714
|
-

|
|
713
|
+

|
|
716
714
|

|
|
717
715
|

|
|
718
716
|
[](https://pepy.tech/projects/moleditpy)
|
|
@@ -29,6 +29,7 @@ src/moleditpy_linux/ui/analysis_window.py
|
|
|
29
29
|
src/moleditpy_linux/ui/angle_dialog.py
|
|
30
30
|
src/moleditpy_linux/ui/app_state.py
|
|
31
31
|
src/moleditpy_linux/ui/atom_item.py
|
|
32
|
+
src/moleditpy_linux/ui/atom_picking.py
|
|
32
33
|
src/moleditpy_linux/ui/base_picking_dialog.py
|
|
33
34
|
src/moleditpy_linux/ui/bond_item.py
|
|
34
35
|
src/moleditpy_linux/ui/bond_length_dialog.py
|
|
@@ -55,7 +56,6 @@ src/moleditpy_linux/ui/move_group_dialog.py
|
|
|
55
56
|
src/moleditpy_linux/ui/periodic_table_dialog.py
|
|
56
57
|
src/moleditpy_linux/ui/planarize_dialog.py
|
|
57
58
|
src/moleditpy_linux/ui/settings_dialog.py
|
|
58
|
-
src/moleditpy_linux/ui/sip_isdeleted_safe.py
|
|
59
59
|
src/moleditpy_linux/ui/string_importers.py
|
|
60
60
|
src/moleditpy_linux/ui/template_preview_item.py
|
|
61
61
|
src/moleditpy_linux/ui/template_preview_view.py
|
|
@@ -15,9 +15,9 @@ print("MoleditPy - A Python-based molecular editing software")
|
|
|
15
15
|
print("-----------------------------------------------------\n")
|
|
16
16
|
|
|
17
17
|
try:
|
|
18
|
-
from .main import main
|
|
18
|
+
from .main import main # type: ignore
|
|
19
19
|
except ImportError:
|
|
20
|
-
from main import main
|
|
20
|
+
from main import main # type: ignore
|
|
21
21
|
|
|
22
22
|
# --- Application Execution ---
|
|
23
23
|
if __name__ == "__main__":
|
|
@@ -152,7 +152,7 @@ def rodrigues_rotate(v: np.ndarray, axis: np.ndarray, angle: float) -> np.ndarra
|
|
|
152
152
|
"""
|
|
153
153
|
cos_a = np.cos(angle)
|
|
154
154
|
sin_a = np.sin(angle)
|
|
155
|
-
return v * cos_a + np.cross(axis, v) * sin_a + axis * np.dot(axis, v) * (1 - cos_a)
|
|
155
|
+
return v * cos_a + np.cross(axis, v) * sin_a + axis * np.dot(axis, v) * (1 - cos_a) # type: ignore[no-any-return]
|
|
156
156
|
|
|
157
157
|
|
|
158
158
|
def adjust_bond_angle(
|
|
@@ -421,7 +421,9 @@ def is_problematic_valence(
|
|
|
421
421
|
# ------------------------------------------------------------------
|
|
422
422
|
|
|
423
423
|
|
|
424
|
-
def inject_ez_stereo_to_mol_block(
|
|
424
|
+
def inject_ez_stereo_to_mol_block(
|
|
425
|
+
mol_block: str, rdkit_mol: Any, bonds_data: Dict[Tuple[int, int], Any]
|
|
426
|
+
) -> str:
|
|
425
427
|
"""Generate a modified MOL block with 'M CFG' lines for E/Z stereochemistry.
|
|
426
428
|
|
|
427
429
|
Parameters
|
|
@@ -502,7 +504,7 @@ def identify_valence_problems(
|
|
|
502
504
|
problem_atom_ids = []
|
|
503
505
|
|
|
504
506
|
# Pre-calculate bond orders per atom
|
|
505
|
-
bond_orders = {}
|
|
507
|
+
bond_orders: Dict[int, int] = {}
|
|
506
508
|
for (id1, id2), bond in bonds_data.items():
|
|
507
509
|
order = bond.get("order", 1)
|
|
508
510
|
bond_orders[id1] = bond_orders.get(id1, 0) + order
|
|
@@ -534,15 +536,22 @@ def optimize_2d_coords(mol: Any) -> Dict[int, Tuple[float, float]]:
|
|
|
534
536
|
return new_positions
|
|
535
537
|
|
|
536
538
|
|
|
537
|
-
def calculate_best_fit_plane_projection(
|
|
539
|
+
def calculate_best_fit_plane_projection(
|
|
540
|
+
centered_positions: np.ndarray, normal: np.ndarray, centroid: np.ndarray
|
|
541
|
+
) -> np.ndarray:
|
|
538
542
|
"""Project centered points orthogonally onto the plane defined by normal and centroid."""
|
|
539
543
|
projections = centered_positions - np.outer(
|
|
540
544
|
np.dot(centered_positions, normal), normal
|
|
541
545
|
)
|
|
542
|
-
return projections + centroid
|
|
546
|
+
return projections + centroid # type: ignore[no-any-return]
|
|
543
547
|
|
|
544
548
|
|
|
545
|
-
def rotate_2d_points(
|
|
549
|
+
def rotate_2d_points(
|
|
550
|
+
points_map: Dict[int, Tuple[float, float]],
|
|
551
|
+
center_x: float,
|
|
552
|
+
center_y: float,
|
|
553
|
+
angle_degrees: float,
|
|
554
|
+
) -> Dict[int, Tuple[float, float]]:
|
|
546
555
|
"""Rotate 2D points (atom_id -> (x, y)) around a center."""
|
|
547
556
|
rad = math.radians(angle_degrees)
|
|
548
557
|
cos_a = math.cos(rad)
|
|
@@ -558,13 +567,13 @@ def rotate_2d_points(points_map, center_x, center_y, angle_degrees):
|
|
|
558
567
|
|
|
559
568
|
|
|
560
569
|
def resolve_2d_overlaps(
|
|
561
|
-
atom_ids,
|
|
562
|
-
positions_map,
|
|
563
|
-
adjacency_list,
|
|
564
|
-
overlap_threshold=0.5,
|
|
565
|
-
move_distance=20,
|
|
566
|
-
has_bond_check_func=None,
|
|
567
|
-
):
|
|
570
|
+
atom_ids: Iterable[int],
|
|
571
|
+
positions_map: Dict[int, Tuple[float, float]],
|
|
572
|
+
adjacency_list: Dict[int, List[int]],
|
|
573
|
+
overlap_threshold: float = 0.5,
|
|
574
|
+
move_distance: float = 20,
|
|
575
|
+
has_bond_check_func: Optional[Any] = None,
|
|
576
|
+
) -> List[Tuple[Set[int], Tuple[float, float]]]:
|
|
568
577
|
"""Detect and resolve overlapping atom groups in 2D.
|
|
569
578
|
|
|
570
579
|
Returns list of (atom_ids_set, translation_vector_tuple).
|
|
@@ -592,13 +601,13 @@ def resolve_2d_overlaps(
|
|
|
592
601
|
# Union-Find for overlap groups
|
|
593
602
|
parent = {aid: aid for aid in atom_ids}
|
|
594
603
|
|
|
595
|
-
def find_set(aid):
|
|
604
|
+
def find_set(aid: Any) -> Any:
|
|
596
605
|
if parent[aid] == aid:
|
|
597
606
|
return aid
|
|
598
607
|
parent[aid] = find_set(parent[aid])
|
|
599
608
|
return parent[aid]
|
|
600
609
|
|
|
601
|
-
def unite_sets(aid1, aid2):
|
|
610
|
+
def unite_sets(aid1: Any, aid2: Any) -> None:
|
|
602
611
|
root1 = find_set(aid1)
|
|
603
612
|
root2 = find_set(aid2)
|
|
604
613
|
if root1 != root2:
|
|
@@ -607,7 +616,7 @@ def resolve_2d_overlaps(
|
|
|
607
616
|
for id1, id2 in overlapping_pairs:
|
|
608
617
|
unite_sets(id1, id2)
|
|
609
618
|
|
|
610
|
-
groups_by_root = {}
|
|
619
|
+
groups_by_root: Dict[int, List[int]] = {}
|
|
611
620
|
for aid in atom_ids:
|
|
612
621
|
root = find_set(aid)
|
|
613
622
|
groups_by_root.setdefault(root, []).append(aid)
|
|
@@ -649,7 +658,7 @@ def resolve_2d_overlaps(
|
|
|
649
658
|
rep_id1, rep_id2 = i1, i2
|
|
650
659
|
break
|
|
651
660
|
|
|
652
|
-
if rep_id1 is None:
|
|
661
|
+
if rep_id1 is None or rep_id2 is None:
|
|
653
662
|
continue
|
|
654
663
|
|
|
655
664
|
frag1 = next((f for f in fragments if rep_id1 in f), None)
|
|
@@ -25,10 +25,10 @@ class PointTuple(tuple):
|
|
|
25
25
|
"""Backward-compatible tuple that allows .x() and .y() access like QPointF."""
|
|
26
26
|
|
|
27
27
|
def x(self) -> float:
|
|
28
|
-
return self[0]
|
|
28
|
+
return float(self[0])
|
|
29
29
|
|
|
30
30
|
def y(self) -> float:
|
|
31
|
-
return self[1]
|
|
31
|
+
return float(self[1])
|
|
32
32
|
|
|
33
33
|
|
|
34
34
|
class MolecularData:
|
|
@@ -248,10 +248,10 @@ class MolecularData:
|
|
|
248
248
|
if nbr.GetIdx() == exclude_idx:
|
|
249
249
|
continue
|
|
250
250
|
if nbr.GetAtomicNum() > 1:
|
|
251
|
-
return nbr.GetIdx()
|
|
251
|
+
return int(nbr.GetIdx())
|
|
252
252
|
for nbr in atom.GetNeighbors():
|
|
253
253
|
if nbr.GetIdx() != exclude_idx:
|
|
254
|
-
return nbr.GetIdx()
|
|
254
|
+
return int(nbr.GetIdx())
|
|
255
255
|
return None
|
|
256
256
|
|
|
257
257
|
# Overwrite based on labels (E/Z has highest priority) ---
|
|
@@ -275,7 +275,7 @@ class MolecularData:
|
|
|
275
275
|
begin_atom_idx = bond.GetBeginAtomIdx()
|
|
276
276
|
end_atom_idx = bond.GetEndAtomIdx()
|
|
277
277
|
|
|
278
|
-
bond_data = info.get("bond_data"
|
|
278
|
+
bond_data: dict[str, Any] = info.get("bond_data") or {} # type: ignore[assignment]
|
|
279
279
|
stereo_atoms_specified = bond_data.get("stereo_atoms")
|
|
280
280
|
|
|
281
281
|
if stereo_atoms_specified:
|
|
@@ -365,7 +365,10 @@ class MolecularData:
|
|
|
365
365
|
if key in self.bonds:
|
|
366
366
|
rdkit_bond_idx_to_item[bidx] = self.bonds[key].get("item")
|
|
367
367
|
|
|
368
|
-
# 5. Initialize/Reset all bond items
|
|
368
|
+
# 5. Initialize/Reset all bond items and track best ring size
|
|
369
|
+
bond_to_best_size: Dict[
|
|
370
|
+
int, int
|
|
371
|
+
] = {} # bond_item_id -> smallest_ring_size_found
|
|
369
372
|
for bond_data in self.bonds.values():
|
|
370
373
|
bond_item = bond_data.get("item")
|
|
371
374
|
if bond_item:
|
|
@@ -374,6 +377,7 @@ class MolecularData:
|
|
|
374
377
|
|
|
375
378
|
# 6. Apply ring information
|
|
376
379
|
for a_ring, b_ring in zip(atom_rings, bond_rings):
|
|
380
|
+
ring_size = len(a_ring)
|
|
377
381
|
# Calculate ring center (geometric mean of atom positions)
|
|
378
382
|
positions = []
|
|
379
383
|
for aidx in a_ring:
|
|
@@ -395,18 +399,21 @@ class MolecularData:
|
|
|
395
399
|
bond_item = rdkit_bond_idx_to_item.get(bidx)
|
|
396
400
|
if bond_item:
|
|
397
401
|
bond_item.is_in_ring = True
|
|
398
|
-
#
|
|
399
|
-
#
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
402
|
+
# Explicitly prioritize smaller rings for double bond shift logic.
|
|
403
|
+
# This ensures the double bond is drawn inside the smaller ring in fused systems.
|
|
404
|
+
item_id = id(bond_item)
|
|
405
|
+
if (
|
|
406
|
+
item_id not in bond_to_best_size
|
|
407
|
+
or ring_size < bond_to_best_size[item_id]
|
|
408
|
+
):
|
|
409
|
+
bond_item.ring_center = ring_center
|
|
410
|
+
bond_to_best_size[item_id] = ring_size
|
|
404
411
|
|
|
405
412
|
def to_mol_block(self) -> Optional[str]:
|
|
406
413
|
mol = self.to_rdkit_mol()
|
|
407
414
|
if mol:
|
|
408
415
|
try:
|
|
409
|
-
return Chem.MolToMolBlock(mol, includeStereo=True)
|
|
416
|
+
return Chem.MolToMolBlock(mol, includeStereo=True) # type: ignore[no-any-return]
|
|
410
417
|
except (RuntimeError, ValueError, TypeError) as e:
|
|
411
418
|
logging.warning(
|
|
412
419
|
f"RDKit MolBlock generation failed: {e}"
|
|
@@ -15,6 +15,7 @@ import sys
|
|
|
15
15
|
import argparse
|
|
16
16
|
import logging
|
|
17
17
|
import os
|
|
18
|
+
from typing import Any
|
|
18
19
|
|
|
19
20
|
try:
|
|
20
21
|
from .utils.constants import VERSION
|
|
@@ -35,7 +36,7 @@ except ImportError:
|
|
|
35
36
|
from moleditpy_linux.ui.main_window import MainWindow
|
|
36
37
|
|
|
37
38
|
|
|
38
|
-
def setup_logging():
|
|
39
|
+
def setup_logging() -> None:
|
|
39
40
|
logging.basicConfig(
|
|
40
41
|
level=logging.INFO,
|
|
41
42
|
format="%(asctime)s [%(levelname)s] %(name)s (%(pathname)s:%(lineno)d): %(message)s",
|
|
@@ -43,7 +44,7 @@ def setup_logging():
|
|
|
43
44
|
force=True,
|
|
44
45
|
)
|
|
45
46
|
|
|
46
|
-
def handle_exception(exc_type, exc_value, exc_traceback):
|
|
47
|
+
def handle_exception(exc_type: Any, exc_value: Any, exc_traceback: Any) -> None:
|
|
47
48
|
"""Log unhandled exceptions using the configured logging system."""
|
|
48
49
|
if issubclass(exc_type, KeyboardInterrupt):
|
|
49
50
|
# Allow keyboard interrupt to exit normally
|
|
@@ -57,7 +58,7 @@ def setup_logging():
|
|
|
57
58
|
sys.excepthook = handle_exception
|
|
58
59
|
|
|
59
60
|
|
|
60
|
-
def main():
|
|
61
|
+
def main() -> None:
|
|
61
62
|
# Setup logging as early as possible
|
|
62
63
|
setup_logging()
|
|
63
64
|
|
{moleditpy_linux-3.1.0 → moleditpy_linux-3.3.0}/src/moleditpy_linux/plugins/plugin_interface.py
RENAMED
|
@@ -19,7 +19,7 @@ class PluginContext:
|
|
|
19
19
|
It is passed to the `initialize(context)` function of the plugin.
|
|
20
20
|
"""
|
|
21
21
|
|
|
22
|
-
def __init__(self, manager, plugin_name: str):
|
|
22
|
+
def __init__(self, manager: Any, plugin_name: str) -> None:
|
|
23
23
|
self._manager = manager
|
|
24
24
|
self._plugin_name = plugin_name
|
|
25
25
|
|
|
@@ -30,7 +30,7 @@ class PluginContext:
|
|
|
30
30
|
text: Optional[str] = None,
|
|
31
31
|
icon: Optional[str] = None,
|
|
32
32
|
shortcut: Optional[str] = None,
|
|
33
|
-
):
|
|
33
|
+
) -> None:
|
|
34
34
|
"""
|
|
35
35
|
Register a menu action.
|
|
36
36
|
|
|
@@ -52,7 +52,7 @@ class PluginContext:
|
|
|
52
52
|
callback: Optional[Callable] = None,
|
|
53
53
|
icon: Optional[str] = None,
|
|
54
54
|
shortcut: Optional[str] = None,
|
|
55
|
-
):
|
|
55
|
+
) -> None:
|
|
56
56
|
"""Backward-compatible alias for add_menu_action.
|
|
57
57
|
Supports old 3-arg style: register_menu_action(path, text, callback).
|
|
58
58
|
"""
|
|
@@ -61,7 +61,8 @@ class PluginContext:
|
|
|
61
61
|
self.add_menu_action(path, text_or_callback, None, icon, shortcut)
|
|
62
62
|
else:
|
|
63
63
|
# Old style: (path, text, callback)
|
|
64
|
-
|
|
64
|
+
if callback is not None:
|
|
65
|
+
self.add_menu_action(path, callback, text_or_callback, icon, shortcut)
|
|
65
66
|
|
|
66
67
|
def add_plugin_menu(
|
|
67
68
|
self,
|
|
@@ -70,7 +71,7 @@ class PluginContext:
|
|
|
70
71
|
text: Optional[str] = None,
|
|
71
72
|
icon: Optional[str] = None,
|
|
72
73
|
shortcut: Optional[str] = None,
|
|
73
|
-
):
|
|
74
|
+
) -> None:
|
|
74
75
|
"""
|
|
75
76
|
Register an action nested inside the Plugin menu.
|
|
76
77
|
|
|
@@ -95,7 +96,7 @@ class PluginContext:
|
|
|
95
96
|
text: str,
|
|
96
97
|
icon: Optional[str] = None,
|
|
97
98
|
tooltip: Optional[str] = None,
|
|
98
|
-
):
|
|
99
|
+
) -> None:
|
|
99
100
|
"""
|
|
100
101
|
Register a toolbar action.
|
|
101
102
|
"""
|
|
@@ -103,7 +104,9 @@ class PluginContext:
|
|
|
103
104
|
self._plugin_name, callback, text, icon, tooltip
|
|
104
105
|
)
|
|
105
106
|
|
|
106
|
-
def register_drop_handler(
|
|
107
|
+
def register_drop_handler(
|
|
108
|
+
self, callback: Callable[[str], bool], priority: int = 0
|
|
109
|
+
) -> None:
|
|
107
110
|
"""
|
|
108
111
|
Register a handler for file drops.
|
|
109
112
|
|
|
@@ -132,7 +135,7 @@ class PluginContext:
|
|
|
132
135
|
Returns a list of RDKit atom indices currently selected in the 2D or 3D view.
|
|
133
136
|
Note: RDKit indices are returned, which map to the current_mol.
|
|
134
137
|
"""
|
|
135
|
-
return self._manager.get_selected_atom_indices()
|
|
138
|
+
return self._manager.get_selected_atom_indices() # type: ignore[no-any-return]
|
|
136
139
|
|
|
137
140
|
def register_window(self, window_id: str, window: Any) -> None:
|
|
138
141
|
"""
|
|
@@ -174,7 +177,7 @@ class PluginContext:
|
|
|
174
177
|
)
|
|
175
178
|
|
|
176
179
|
@current_mol.setter
|
|
177
|
-
def current_mol(self, mol: Any):
|
|
180
|
+
def current_mol(self, mol: Any) -> None:
|
|
178
181
|
mw = self.get_main_window()
|
|
179
182
|
if mw and hasattr(mw, "view_3d_manager"):
|
|
180
183
|
mw.view_3d_manager.current_mol = mol
|
|
@@ -186,7 +189,7 @@ class PluginContext:
|
|
|
186
189
|
return self.current_mol
|
|
187
190
|
|
|
188
191
|
@current_molecule.setter
|
|
189
|
-
def current_molecule(self, mol: Any):
|
|
192
|
+
def current_molecule(self, mol: Any) -> None:
|
|
190
193
|
self.current_mol = mol
|
|
191
194
|
|
|
192
195
|
@property
|
|
@@ -236,7 +239,7 @@ class PluginContext:
|
|
|
236
239
|
if mw and hasattr(mw, "view_3d_manager") and mw.view_3d_manager.plotter:
|
|
237
240
|
mw.view_3d_manager.plotter.reset_camera()
|
|
238
241
|
|
|
239
|
-
def add_export_action(self, label: str, callback: Callable):
|
|
242
|
+
def add_export_action(self, label: str, callback: Callable) -> None:
|
|
240
243
|
"""
|
|
241
244
|
Register a custom export action.
|
|
242
245
|
|
|
@@ -248,7 +251,7 @@ class PluginContext:
|
|
|
248
251
|
|
|
249
252
|
def register_optimization_method(
|
|
250
253
|
self, method_name: str, callback: Callable[[Any], bool]
|
|
251
|
-
):
|
|
254
|
+
) -> None:
|
|
252
255
|
"""
|
|
253
256
|
Register a custom 3D optimization method.
|
|
254
257
|
|
|
@@ -263,7 +266,7 @@ class PluginContext:
|
|
|
263
266
|
|
|
264
267
|
def register_file_opener(
|
|
265
268
|
self, extension: str, callback: Callable[[str], None], priority: int = 0
|
|
266
|
-
):
|
|
269
|
+
) -> None:
|
|
267
270
|
"""
|
|
268
271
|
Register a handler for opening a specific file extension.
|
|
269
272
|
|
|
@@ -277,7 +280,7 @@ class PluginContext:
|
|
|
277
280
|
self._plugin_name, extension, callback, priority
|
|
278
281
|
)
|
|
279
282
|
|
|
280
|
-
def add_analysis_tool(self, label: str, callback: Callable):
|
|
283
|
+
def add_analysis_tool(self, label: str, callback: Callable) -> None:
|
|
281
284
|
"""
|
|
282
285
|
Register a tool in the Analysis menu.
|
|
283
286
|
|
|
@@ -287,7 +290,7 @@ class PluginContext:
|
|
|
287
290
|
"""
|
|
288
291
|
self._manager.register_analysis_tool(self._plugin_name, label, callback)
|
|
289
292
|
|
|
290
|
-
def register_save_handler(self, callback: Callable[[], dict]):
|
|
293
|
+
def register_save_handler(self, callback: Callable[[], dict]) -> None:
|
|
291
294
|
"""
|
|
292
295
|
Register a callback to save state into the project file.
|
|
293
296
|
|
|
@@ -296,7 +299,7 @@ class PluginContext:
|
|
|
296
299
|
"""
|
|
297
300
|
self._manager.register_save_handler(self._plugin_name, callback)
|
|
298
301
|
|
|
299
|
-
def register_load_handler(self, callback: Callable[[dict], None]):
|
|
302
|
+
def register_load_handler(self, callback: Callable[[dict], None]) -> None:
|
|
300
303
|
"""
|
|
301
304
|
Register a callback to restore state from the project file.
|
|
302
305
|
|
|
@@ -305,13 +308,15 @@ class PluginContext:
|
|
|
305
308
|
"""
|
|
306
309
|
self._manager.register_load_handler(self._plugin_name, callback)
|
|
307
310
|
|
|
308
|
-
def register_3d_context_menu(self, callback: Callable, label: str):
|
|
311
|
+
def register_3d_context_menu(self, callback: Callable, label: str) -> None:
|
|
309
312
|
"""Deprecated: This method does nothing. Kept for backward compatibility."""
|
|
310
313
|
print(
|
|
311
314
|
f"Warning: Plugin '{self._plugin_name}' uses deprecated 'register_3d_context_menu'. This API has been removed."
|
|
312
315
|
)
|
|
313
316
|
|
|
314
|
-
def register_3d_style(
|
|
317
|
+
def register_3d_style(
|
|
318
|
+
self, style_name: str, callback: Callable[[Any, Any], None]
|
|
319
|
+
) -> None:
|
|
315
320
|
"""
|
|
316
321
|
Register a custom 3D rendering style.
|
|
317
322
|
|
|
@@ -322,7 +327,7 @@ class PluginContext:
|
|
|
322
327
|
"""
|
|
323
328
|
self._manager.register_3d_style(self._plugin_name, style_name, callback)
|
|
324
329
|
|
|
325
|
-
def register_document_reset_handler(self, callback: Callable[[], None]):
|
|
330
|
+
def register_document_reset_handler(self, callback: Callable[[], None]) -> None:
|
|
326
331
|
"""
|
|
327
332
|
Register a callback to be called when a new document is created (File→New).
|
|
328
333
|
|
|
@@ -370,14 +375,14 @@ class PluginContext:
|
|
|
370
375
|
class Plugin3DController:
|
|
371
376
|
"""Helper to manipulate the 3D scene."""
|
|
372
377
|
|
|
373
|
-
def __init__(self, main_window):
|
|
378
|
+
def __init__(self, main_window: Any) -> None:
|
|
374
379
|
self._mw = main_window
|
|
375
380
|
|
|
376
|
-
def _get_v3d(self):
|
|
381
|
+
def _get_v3d(self) -> Optional[Any]:
|
|
377
382
|
"""Helper to get the 3D manager."""
|
|
378
383
|
return getattr(self._mw, "view_3d_manager", None)
|
|
379
384
|
|
|
380
|
-
def set_atom_color(self, atom_index: int, color_hex: str):
|
|
385
|
+
def set_atom_color(self, atom_index: int, color_hex: str) -> None:
|
|
381
386
|
"""
|
|
382
387
|
Set the color of a specific atom in the 3D view.
|
|
383
388
|
Args:
|
|
@@ -390,7 +395,7 @@ class Plugin3DController:
|
|
|
390
395
|
if hasattr(self._mw, "plotter") and self._mw.plotter:
|
|
391
396
|
self._mw.plotter.render()
|
|
392
397
|
|
|
393
|
-
def set_bond_color(self, bond_index: int, color_hex: str):
|
|
398
|
+
def set_bond_color(self, bond_index: int, color_hex: str) -> None:
|
|
394
399
|
"""
|
|
395
400
|
Set the color of a specific bond in the 3D view.
|
|
396
401
|
|
|
@@ -404,7 +409,9 @@ class Plugin3DController:
|
|
|
404
409
|
if hasattr(self._mw, "plotter") and self._mw.plotter:
|
|
405
410
|
self._mw.plotter.render()
|
|
406
411
|
|
|
407
|
-
def set_bond_color_by_atoms(
|
|
412
|
+
def set_bond_color_by_atoms(
|
|
413
|
+
self, atom_idx1: int, atom_idx2: int, color_hex: str
|
|
414
|
+
) -> None:
|
|
408
415
|
"""
|
|
409
416
|
Set the color of the bond between two atoms.
|
|
410
417
|
|