MoleditPy-linux 2.5.2__tar.gz → 2.6.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-2.5.2 → moleditpy_linux-2.6.0}/PKG-INFO +1 -1
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/pyproject.toml +2 -2
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/MoleditPy_linux.egg-info/PKG-INFO +1 -1
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/MoleditPy_linux.egg-info/SOURCES.txt +6 -5
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/modules/about_dialog.py +1 -1
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/modules/align_plane_dialog.py +4 -31
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/modules/alignment_dialog.py +1 -29
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/modules/angle_dialog.py +8 -84
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/modules/atom_item.py +2 -2
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/modules/bond_item.py +2 -4
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/modules/bond_length_dialog.py +7 -84
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/modules/color_settings_dialog.py +5 -3
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/modules/constants.py +1 -1
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/modules/constrained_optimization_dialog.py +1 -9
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/modules/dialog3_d_picking_mixin.py +69 -0
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/modules/dihedral_dialog.py +16 -99
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/modules/main_window.py +0 -20
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/modules/main_window_app_state.py +0 -15
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/modules/main_window_compute.py +5 -29
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/modules/main_window_dialog_manager.py +0 -16
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/modules/main_window_edit_3d.py +8 -55
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/modules/main_window_edit_actions.py +6 -32
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/modules/main_window_export.py +2 -16
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/modules/main_window_main_init.py +17 -22
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/modules/main_window_molecular_parsers.py +1 -17
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/modules/main_window_project_io.py +1 -16
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/modules/main_window_string_importers.py +1 -15
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/modules/main_window_ui_manager.py +0 -16
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/modules/main_window_view_3d.py +0 -16
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/modules/main_window_view_loaders.py +0 -17
- moleditpy_linux-2.6.0/src/moleditpy_linux/modules/mol_geometry.py +165 -0
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/modules/move_group_dialog.py +5 -6
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/modules/planarize_dialog.py +6 -24
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/modules/plugin_interface.py +0 -7
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/modules/plugin_manager_window.py +3 -3
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/modules/settings_dialog.py +7 -147
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/modules/translation_dialog.py +2 -8
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/LICENSE +0 -0
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/README.md +0 -0
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/setup.cfg +0 -0
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/MoleditPy_linux.egg-info/dependency_links.txt +0 -0
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/MoleditPy_linux.egg-info/entry_points.txt +0 -0
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/MoleditPy_linux.egg-info/requires.txt +0 -0
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/MoleditPy_linux.egg-info/top_level.txt +0 -0
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/__init__.py +0 -0
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/__main__.py +0 -0
- {moleditpy_linux-2.5.2/src/moleditpy_linux/modules → moleditpy_linux-2.6.0/src/moleditpy_linux}/assets/file_icon.ico +0 -0
- {moleditpy_linux-2.5.2/src/moleditpy_linux/modules → moleditpy_linux-2.6.0/src/moleditpy_linux}/assets/icon.icns +0 -0
- {moleditpy_linux-2.5.2/src/moleditpy_linux/modules → moleditpy_linux-2.6.0/src/moleditpy_linux}/assets/icon.ico +0 -0
- {moleditpy_linux-2.5.2/src/moleditpy_linux/modules → moleditpy_linux-2.6.0/src/moleditpy_linux}/assets/icon.png +0 -0
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/main.py +0 -0
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/modules/__init__.py +0 -0
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/modules/analysis_window.py +0 -0
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/modules/calculation_worker.py +0 -0
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/modules/custom_interactor_style.py +0 -0
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/modules/custom_qt_interactor.py +0 -0
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/modules/mirror_dialog.py +0 -0
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/modules/molecular_data.py +0 -0
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/modules/molecule_scene.py +0 -0
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/modules/periodic_table_dialog.py +0 -0
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/modules/plugin_manager.py +0 -0
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/modules/template_preview_item.py +0 -0
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/modules/template_preview_view.py +0 -0
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/modules/user_template_dialog.py +0 -0
- {moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/modules/zoomable_view.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: MoleditPy-linux
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.6.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
|
|
@@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "MoleditPy-linux"
|
|
7
7
|
|
|
8
|
-
version = "2.
|
|
8
|
+
version = "2.6.0"
|
|
9
9
|
|
|
10
10
|
license = {file = "LICENSE"}
|
|
11
11
|
|
|
@@ -48,5 +48,5 @@ Issues = "https://github.com/HiroYokoyama/python_molecular_editor/issues"
|
|
|
48
48
|
moleditpy = "moleditpy_linux.__main__:main"
|
|
49
49
|
|
|
50
50
|
[tool.setuptools.package-data]
|
|
51
|
-
"moleditpy_linux" = ["
|
|
51
|
+
"moleditpy_linux" = ["assets/*"]
|
|
52
52
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: MoleditPy-linux
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.6.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
|
|
@@ -10,6 +10,10 @@ src/MoleditPy_linux.egg-info/top_level.txt
|
|
|
10
10
|
src/moleditpy_linux/__init__.py
|
|
11
11
|
src/moleditpy_linux/__main__.py
|
|
12
12
|
src/moleditpy_linux/main.py
|
|
13
|
+
src/moleditpy_linux/assets/file_icon.ico
|
|
14
|
+
src/moleditpy_linux/assets/icon.icns
|
|
15
|
+
src/moleditpy_linux/assets/icon.ico
|
|
16
|
+
src/moleditpy_linux/assets/icon.png
|
|
13
17
|
src/moleditpy_linux/modules/__init__.py
|
|
14
18
|
src/moleditpy_linux/modules/about_dialog.py
|
|
15
19
|
src/moleditpy_linux/modules/align_plane_dialog.py
|
|
@@ -42,6 +46,7 @@ src/moleditpy_linux/modules/main_window_ui_manager.py
|
|
|
42
46
|
src/moleditpy_linux/modules/main_window_view_3d.py
|
|
43
47
|
src/moleditpy_linux/modules/main_window_view_loaders.py
|
|
44
48
|
src/moleditpy_linux/modules/mirror_dialog.py
|
|
49
|
+
src/moleditpy_linux/modules/mol_geometry.py
|
|
45
50
|
src/moleditpy_linux/modules/molecular_data.py
|
|
46
51
|
src/moleditpy_linux/modules/molecule_scene.py
|
|
47
52
|
src/moleditpy_linux/modules/move_group_dialog.py
|
|
@@ -55,8 +60,4 @@ src/moleditpy_linux/modules/template_preview_item.py
|
|
|
55
60
|
src/moleditpy_linux/modules/template_preview_view.py
|
|
56
61
|
src/moleditpy_linux/modules/translation_dialog.py
|
|
57
62
|
src/moleditpy_linux/modules/user_template_dialog.py
|
|
58
|
-
src/moleditpy_linux/modules/zoomable_view.py
|
|
59
|
-
src/moleditpy_linux/modules/assets/file_icon.ico
|
|
60
|
-
src/moleditpy_linux/modules/assets/icon.icns
|
|
61
|
-
src/moleditpy_linux/modules/assets/icon.ico
|
|
62
|
-
src/moleditpy_linux/modules/assets/icon.png
|
|
63
|
+
src/moleditpy_linux/modules/zoomable_view.py
|
|
@@ -37,7 +37,7 @@ class AboutDialog(QDialog): # pragma: no cover
|
|
|
37
37
|
self.image_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
|
38
38
|
|
|
39
39
|
# Load the original icon image
|
|
40
|
-
icon_path = os.path.join(os.path.dirname(__file__), 'assets', 'icon.png')
|
|
40
|
+
icon_path = os.path.join(os.path.dirname(__file__), '..', 'assets', 'icon.png')
|
|
41
41
|
if os.path.exists(icon_path):
|
|
42
42
|
original_pixmap = QPixmap(icon_path)
|
|
43
43
|
# Scale to 2x size (160x160)
|
{moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/modules/align_plane_dialog.py
RENAMED
|
@@ -163,39 +163,12 @@ class AlignPlaneDialog(Dialog3DPickingMixin, QDialog): # pragma: no cover
|
|
|
163
163
|
|
|
164
164
|
def show_atom_labels(self):
|
|
165
165
|
"""選択された原子にラベルを表示"""
|
|
166
|
-
# 既存のラベルをクリア
|
|
167
|
-
self.clear_atom_labels()
|
|
168
|
-
|
|
169
|
-
# 新しいラベルを表示
|
|
170
|
-
if not hasattr(self, 'selection_labels'):
|
|
171
|
-
self.selection_labels = []
|
|
172
|
-
|
|
173
166
|
if self.selected_atoms:
|
|
174
167
|
sorted_atoms = sorted(self.selected_atoms)
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
# ラベルを追加
|
|
181
|
-
label_actor = self.main_window.plotter.add_point_labels(
|
|
182
|
-
[pos], [label_text],
|
|
183
|
-
point_size=20,
|
|
184
|
-
font_size=12,
|
|
185
|
-
text_color='blue',
|
|
186
|
-
always_visible=True
|
|
187
|
-
)
|
|
188
|
-
self.selection_labels.append(label_actor)
|
|
189
|
-
|
|
190
|
-
def clear_atom_labels(self):
|
|
191
|
-
"""原子ラベルをクリア"""
|
|
192
|
-
if hasattr(self, 'selection_labels'):
|
|
193
|
-
for label_actor in self.selection_labels:
|
|
194
|
-
try:
|
|
195
|
-
self.main_window.plotter.remove_actor(label_actor)
|
|
196
|
-
except Exception:
|
|
197
|
-
pass
|
|
198
|
-
self.selection_labels = []
|
|
168
|
+
pairs = [(idx, f"#{i+1}") for i, idx in enumerate(sorted_atoms)]
|
|
169
|
+
self.show_atom_labels_for(pairs, color='blue')
|
|
170
|
+
else:
|
|
171
|
+
self.clear_atom_labels()
|
|
199
172
|
|
|
200
173
|
def apply_PlaneAlign(self):
|
|
201
174
|
"""alignを適用(回転ベース)"""
|
{moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/modules/alignment_dialog.py
RENAMED
|
@@ -13,7 +13,7 @@ DOI: 10.5281/zenodo.17268532
|
|
|
13
13
|
from PyQt6.QtWidgets import (
|
|
14
14
|
QDialog, QVBoxLayout, QLabel, QHBoxLayout, QPushButton
|
|
15
15
|
)
|
|
16
|
-
|
|
16
|
+
|
|
17
17
|
from PyQt6.QtWidgets import QMessageBox
|
|
18
18
|
import numpy as np
|
|
19
19
|
|
|
@@ -133,24 +133,6 @@ class AlignmentDialog(Dialog3DPickingMixin, QDialog): # pragma: no cover
|
|
|
133
133
|
self.selected_atoms.clear()
|
|
134
134
|
self.update_display()
|
|
135
135
|
|
|
136
|
-
def add_selection_label(self, atom_idx, label_text):
|
|
137
|
-
"""選択された原子にラベルを追加"""
|
|
138
|
-
if not hasattr(self, 'selection_labels'):
|
|
139
|
-
self.selection_labels = []
|
|
140
|
-
|
|
141
|
-
# 原子の位置を取得
|
|
142
|
-
pos = self.main_window.atom_positions_3d[atom_idx]
|
|
143
|
-
|
|
144
|
-
# ラベルを追加
|
|
145
|
-
label_actor = self.main_window.plotter.add_point_labels(
|
|
146
|
-
[pos], [label_text],
|
|
147
|
-
point_size=20,
|
|
148
|
-
font_size=12,
|
|
149
|
-
text_color='yellow',
|
|
150
|
-
always_visible=True
|
|
151
|
-
)
|
|
152
|
-
self.selection_labels.append(label_actor)
|
|
153
|
-
|
|
154
136
|
def remove_atom_label(self, atom_idx):
|
|
155
137
|
"""特定の原子のラベルを削除"""
|
|
156
138
|
# 簡単化のため、全ラベルをクリアして再描画
|
|
@@ -159,16 +141,6 @@ class AlignmentDialog(Dialog3DPickingMixin, QDialog): # pragma: no cover
|
|
|
159
141
|
if idx != atom_idx:
|
|
160
142
|
self.add_selection_label(idx, f"Atom {i}")
|
|
161
143
|
|
|
162
|
-
def clear_selection_labels(self):
|
|
163
|
-
"""選択ラベルをクリア"""
|
|
164
|
-
if hasattr(self, 'selection_labels'):
|
|
165
|
-
for label_actor in self.selection_labels:
|
|
166
|
-
try:
|
|
167
|
-
self.main_window.plotter.remove_actor(label_actor)
|
|
168
|
-
except Exception:
|
|
169
|
-
pass
|
|
170
|
-
self.selection_labels = []
|
|
171
|
-
|
|
172
144
|
def apply_alignment(self):
|
|
173
145
|
"""アライメントを適用"""
|
|
174
146
|
if len(self.selected_atoms) != 2:
|
|
@@ -16,8 +16,10 @@ from PyQt6.QtWidgets import (
|
|
|
16
16
|
|
|
17
17
|
try:
|
|
18
18
|
from .dialog3_d_picking_mixin import Dialog3DPickingMixin
|
|
19
|
+
from .mol_geometry import get_connected_group
|
|
19
20
|
except Exception:
|
|
20
21
|
from modules.dialog3_d_picking_mixin import Dialog3DPickingMixin
|
|
22
|
+
from modules.mol_geometry import get_connected_group
|
|
21
23
|
|
|
22
24
|
from PyQt6.QtCore import Qt
|
|
23
25
|
from PyQt6.QtWidgets import QMessageBox
|
|
@@ -169,69 +171,10 @@ class AngleDialog(Dialog3DPickingMixin, QDialog): # pragma: no cover
|
|
|
169
171
|
|
|
170
172
|
def show_atom_labels(self):
|
|
171
173
|
"""選択された原子にラベルを表示"""
|
|
172
|
-
# 既存のラベルをクリア
|
|
173
|
-
self.clear_atom_labels()
|
|
174
|
-
|
|
175
|
-
# 新しいラベルを表示
|
|
176
|
-
if not hasattr(self, 'selection_labels'):
|
|
177
|
-
self.selection_labels = []
|
|
178
|
-
|
|
179
174
|
selected_atoms = [self.atom1_idx, self.atom2_idx, self.atom3_idx]
|
|
180
175
|
labels = ["1st", "2nd (vertex)", "3rd"]
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
for i, atom_idx in enumerate(selected_atoms):
|
|
184
|
-
if atom_idx is not None:
|
|
185
|
-
pos = self.main_window.atom_positions_3d[atom_idx]
|
|
186
|
-
label_text = f"{labels[i]}"
|
|
187
|
-
|
|
188
|
-
# ラベルを追加
|
|
189
|
-
label_actor = self.main_window.plotter.add_point_labels(
|
|
190
|
-
[pos], [label_text],
|
|
191
|
-
point_size=20,
|
|
192
|
-
font_size=12,
|
|
193
|
-
text_color=colors[i],
|
|
194
|
-
always_visible=True
|
|
195
|
-
)
|
|
196
|
-
self.selection_labels.append(label_actor)
|
|
197
|
-
|
|
198
|
-
def clear_atom_labels(self):
|
|
199
|
-
"""原子ラベルをクリア"""
|
|
200
|
-
if hasattr(self, 'selection_labels'):
|
|
201
|
-
for label_actor in self.selection_labels:
|
|
202
|
-
try:
|
|
203
|
-
self.main_window.plotter.remove_actor(label_actor)
|
|
204
|
-
except Exception:
|
|
205
|
-
pass
|
|
206
|
-
self.selection_labels = []
|
|
207
|
-
|
|
208
|
-
def clear_selection_labels(self):
|
|
209
|
-
"""選択ラベルをクリア"""
|
|
210
|
-
if hasattr(self, 'selection_labels'):
|
|
211
|
-
for label_actor in self.selection_labels:
|
|
212
|
-
try:
|
|
213
|
-
self.main_window.plotter.remove_actor(label_actor)
|
|
214
|
-
except Exception:
|
|
215
|
-
pass
|
|
216
|
-
self.selection_labels = []
|
|
217
|
-
|
|
218
|
-
def add_selection_label(self, atom_idx, label_text):
|
|
219
|
-
"""選択された原子にラベルを追加"""
|
|
220
|
-
if not hasattr(self, 'selection_labels'):
|
|
221
|
-
self.selection_labels = []
|
|
222
|
-
|
|
223
|
-
# 原子の位置を取得
|
|
224
|
-
pos = self.main_window.atom_positions_3d[atom_idx]
|
|
225
|
-
|
|
226
|
-
# ラベルを追加
|
|
227
|
-
label_actor = self.main_window.plotter.add_point_labels(
|
|
228
|
-
[pos], [label_text],
|
|
229
|
-
point_size=20,
|
|
230
|
-
font_size=12,
|
|
231
|
-
text_color='yellow',
|
|
232
|
-
always_visible=True
|
|
233
|
-
)
|
|
234
|
-
self.selection_labels.append(label_actor)
|
|
176
|
+
pairs = [(idx, labels[i]) for i, idx in enumerate(selected_atoms) if idx is not None]
|
|
177
|
+
self.show_atom_labels_for(pairs)
|
|
235
178
|
|
|
236
179
|
def update_display(self):
|
|
237
180
|
"""表示を更新"""
|
|
@@ -372,8 +315,8 @@ class AngleDialog(Dialog3DPickingMixin, QDialog): # pragma: no cover
|
|
|
372
315
|
half_rotation = total_rotation_angle / 2
|
|
373
316
|
|
|
374
317
|
# Get both connected groups
|
|
375
|
-
group1_atoms =
|
|
376
|
-
group3_atoms =
|
|
318
|
+
group1_atoms = get_connected_group(self.mol, self.atom1_idx, exclude=self.atom2_idx)
|
|
319
|
+
group3_atoms = get_connected_group(self.mol, self.atom3_idx, exclude=self.atom2_idx)
|
|
377
320
|
|
|
378
321
|
# Rotate group 1 by -half_rotation
|
|
379
322
|
for atom_idx in group1_atoms:
|
|
@@ -401,7 +344,7 @@ class AngleDialog(Dialog3DPickingMixin, QDialog): # pragma: no cover
|
|
|
401
344
|
self.main_window.atom_positions_3d[self.atom3_idx] = new_pos3
|
|
402
345
|
else:
|
|
403
346
|
# Rotate the connected group around atom2 (vertex) - default behavior
|
|
404
|
-
atoms_to_move =
|
|
347
|
+
atoms_to_move = get_connected_group(self.mol, self.atom3_idx, exclude=self.atom2_idx)
|
|
405
348
|
|
|
406
349
|
for atom_idx in atoms_to_move:
|
|
407
350
|
current_pos = np.array(conf.GetAtomPosition(atom_idx))
|
|
@@ -417,23 +360,4 @@ class AngleDialog(Dialog3DPickingMixin, QDialog): # pragma: no cover
|
|
|
417
360
|
# Update the 3D view
|
|
418
361
|
self.main_window.draw_molecule_3d(self.mol)
|
|
419
362
|
|
|
420
|
-
|
|
421
|
-
"""指定された原子から連結されているグループを取得"""
|
|
422
|
-
visited = set()
|
|
423
|
-
to_visit = [start_atom]
|
|
424
|
-
|
|
425
|
-
while to_visit:
|
|
426
|
-
current = to_visit.pop()
|
|
427
|
-
if current in visited or current == exclude:
|
|
428
|
-
continue
|
|
429
|
-
|
|
430
|
-
visited.add(current)
|
|
431
|
-
|
|
432
|
-
# Get neighboring atoms
|
|
433
|
-
atom = self.mol.GetAtomWithIdx(current)
|
|
434
|
-
for bond in atom.GetBonds():
|
|
435
|
-
other_idx = bond.GetOtherAtomIdx(current)
|
|
436
|
-
if other_idx not in visited and other_idx != exclude:
|
|
437
|
-
to_visit.append(other_idx)
|
|
438
|
-
|
|
439
|
-
return visited
|
|
363
|
+
|
|
@@ -23,13 +23,13 @@ from PyQt6.QtCore import (
|
|
|
23
23
|
try:
|
|
24
24
|
from .constants import (
|
|
25
25
|
ATOM_RADIUS, DESIRED_ATOM_PIXEL_RADIUS,
|
|
26
|
-
FONT_FAMILY,
|
|
26
|
+
FONT_FAMILY, FONT_WEIGHT_BOLD,
|
|
27
27
|
CPK_COLORS,
|
|
28
28
|
)
|
|
29
29
|
except Exception:
|
|
30
30
|
from modules.constants import (
|
|
31
31
|
ATOM_RADIUS, DESIRED_ATOM_PIXEL_RADIUS,
|
|
32
|
-
FONT_FAMILY,
|
|
32
|
+
FONT_FAMILY, FONT_WEIGHT_BOLD,
|
|
33
33
|
CPK_COLORS,
|
|
34
34
|
)
|
|
35
35
|
|
|
@@ -24,18 +24,16 @@ from PyQt6.QtCore import (
|
|
|
24
24
|
try:
|
|
25
25
|
from .constants import (
|
|
26
26
|
EZ_LABEL_BOX_SIZE, EZ_LABEL_TEXT_OUTLINE, EZ_LABEL_MARGIN,
|
|
27
|
-
|
|
27
|
+
FONT_FAMILY, FONT_WEIGHT_BOLD,
|
|
28
28
|
HOVER_PEN_WIDTH, DESIRED_BOND_PIXEL_WIDTH,
|
|
29
29
|
)
|
|
30
30
|
except Exception:
|
|
31
31
|
from modules.constants import (
|
|
32
32
|
EZ_LABEL_BOX_SIZE, EZ_LABEL_TEXT_OUTLINE, EZ_LABEL_MARGIN,
|
|
33
|
-
|
|
33
|
+
FONT_FAMILY, FONT_WEIGHT_BOLD,
|
|
34
34
|
HOVER_PEN_WIDTH, DESIRED_BOND_PIXEL_WIDTH,
|
|
35
35
|
)
|
|
36
36
|
|
|
37
|
-
from rdkit import Chem
|
|
38
|
-
|
|
39
37
|
class BondItem(QGraphicsItem):
|
|
40
38
|
|
|
41
39
|
def get_ez_label_rect(self):
|
{moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/modules/bond_length_dialog.py
RENAMED
|
@@ -15,6 +15,7 @@ from PyQt6.QtWidgets import (
|
|
|
15
15
|
)
|
|
16
16
|
|
|
17
17
|
from .dialog3_d_picking_mixin import Dialog3DPickingMixin
|
|
18
|
+
from .mol_geometry import get_connected_group
|
|
18
19
|
|
|
19
20
|
from PyQt6.QtCore import Qt
|
|
20
21
|
import numpy as np
|
|
@@ -158,69 +159,10 @@ class BondLengthDialog(Dialog3DPickingMixin, QDialog): # pragma: no cover
|
|
|
158
159
|
|
|
159
160
|
def show_atom_labels(self):
|
|
160
161
|
"""選択された原子にラベルを表示"""
|
|
161
|
-
# 既存のラベルをクリア
|
|
162
|
-
self.clear_atom_labels()
|
|
163
|
-
|
|
164
|
-
# 新しいラベルを表示
|
|
165
|
-
if not hasattr(self, 'selection_labels'):
|
|
166
|
-
self.selection_labels = []
|
|
167
|
-
|
|
168
162
|
selected_atoms = [self.atom1_idx, self.atom2_idx]
|
|
169
163
|
labels = ["1st", "2nd"]
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
for i, atom_idx in enumerate(selected_atoms):
|
|
173
|
-
if atom_idx is not None:
|
|
174
|
-
pos = self.main_window.atom_positions_3d[atom_idx]
|
|
175
|
-
label_text = f"{labels[i]}"
|
|
176
|
-
|
|
177
|
-
# ラベルを追加
|
|
178
|
-
label_actor = self.main_window.plotter.add_point_labels(
|
|
179
|
-
[pos], [label_text],
|
|
180
|
-
point_size=20,
|
|
181
|
-
font_size=12,
|
|
182
|
-
text_color=colors[i],
|
|
183
|
-
always_visible=True
|
|
184
|
-
)
|
|
185
|
-
self.selection_labels.append(label_actor)
|
|
186
|
-
|
|
187
|
-
def clear_atom_labels(self):
|
|
188
|
-
"""原子ラベルをクリア"""
|
|
189
|
-
if hasattr(self, 'selection_labels'):
|
|
190
|
-
for label_actor in self.selection_labels:
|
|
191
|
-
try:
|
|
192
|
-
self.main_window.plotter.remove_actor(label_actor)
|
|
193
|
-
except Exception:
|
|
194
|
-
pass
|
|
195
|
-
self.selection_labels = []
|
|
196
|
-
|
|
197
|
-
def clear_selection_labels(self):
|
|
198
|
-
"""選択ラベルをクリア"""
|
|
199
|
-
if hasattr(self, 'selection_labels'):
|
|
200
|
-
for label_actor in self.selection_labels:
|
|
201
|
-
try:
|
|
202
|
-
self.main_window.plotter.remove_actor(label_actor)
|
|
203
|
-
except Exception:
|
|
204
|
-
pass
|
|
205
|
-
self.selection_labels = []
|
|
206
|
-
|
|
207
|
-
def add_selection_label(self, atom_idx, label_text):
|
|
208
|
-
"""選択された原子にラベルを追加"""
|
|
209
|
-
if not hasattr(self, 'selection_labels'):
|
|
210
|
-
self.selection_labels = []
|
|
211
|
-
|
|
212
|
-
# 原子の位置を取得
|
|
213
|
-
pos = self.main_window.atom_positions_3d[atom_idx]
|
|
214
|
-
|
|
215
|
-
# ラベルを追加
|
|
216
|
-
label_actor = self.main_window.plotter.add_point_labels(
|
|
217
|
-
[pos], [label_text],
|
|
218
|
-
point_size=20,
|
|
219
|
-
font_size=12,
|
|
220
|
-
text_color='yellow',
|
|
221
|
-
always_visible=True
|
|
222
|
-
)
|
|
223
|
-
self.selection_labels.append(label_actor)
|
|
164
|
+
pairs = [(idx, labels[i]) for i, idx in enumerate(selected_atoms) if idx is not None]
|
|
165
|
+
self.show_atom_labels_for(pairs)
|
|
224
166
|
|
|
225
167
|
def update_display(self):
|
|
226
168
|
"""表示を更新"""
|
|
@@ -317,8 +259,8 @@ class BondLengthDialog(Dialog3DPickingMixin, QDialog): # pragma: no cover
|
|
|
317
259
|
new_pos2 = bond_center + direction * half_distance
|
|
318
260
|
|
|
319
261
|
# Get both connected groups
|
|
320
|
-
group1_atoms =
|
|
321
|
-
group2_atoms =
|
|
262
|
+
group1_atoms = get_connected_group(self.mol, self.atom1_idx, exclude=self.atom2_idx)
|
|
263
|
+
group2_atoms = get_connected_group(self.mol, self.atom2_idx, exclude=self.atom1_idx)
|
|
322
264
|
|
|
323
265
|
# Calculate displacements
|
|
324
266
|
displacement1 = new_pos1 - pos1
|
|
@@ -346,7 +288,7 @@ class BondLengthDialog(Dialog3DPickingMixin, QDialog): # pragma: no cover
|
|
|
346
288
|
else:
|
|
347
289
|
# Move the connected group (default behavior)
|
|
348
290
|
new_pos2 = pos1 + direction * new_distance
|
|
349
|
-
atoms_to_move =
|
|
291
|
+
atoms_to_move = get_connected_group(self.mol, self.atom2_idx, exclude=self.atom1_idx)
|
|
350
292
|
displacement = new_pos2 - pos2
|
|
351
293
|
|
|
352
294
|
for atom_idx in atoms_to_move:
|
|
@@ -358,23 +300,4 @@ class BondLengthDialog(Dialog3DPickingMixin, QDialog): # pragma: no cover
|
|
|
358
300
|
# Update the 3D view
|
|
359
301
|
self.main_window.draw_molecule_3d(self.mol)
|
|
360
302
|
|
|
361
|
-
|
|
362
|
-
"""指定された原子から連結されているグループを取得"""
|
|
363
|
-
visited = set()
|
|
364
|
-
to_visit = [start_atom]
|
|
365
|
-
|
|
366
|
-
while to_visit:
|
|
367
|
-
current = to_visit.pop()
|
|
368
|
-
if current in visited or current == exclude:
|
|
369
|
-
continue
|
|
370
|
-
|
|
371
|
-
visited.add(current)
|
|
372
|
-
|
|
373
|
-
# Get neighboring atoms
|
|
374
|
-
atom = self.mol.GetAtomWithIdx(current)
|
|
375
|
-
for bond in atom.GetBonds():
|
|
376
|
-
other_idx = bond.GetOtherAtomIdx(current)
|
|
377
|
-
if other_idx not in visited and other_idx != exclude:
|
|
378
|
-
to_visit.append(other_idx)
|
|
379
|
-
|
|
380
|
-
return visited
|
|
303
|
+
|
{moleditpy_linux-2.5.2 → moleditpy_linux-2.6.0}/src/moleditpy_linux/modules/color_settings_dialog.py
RENAMED
|
@@ -227,10 +227,12 @@ class ColorSettingsDialog(QDialog): # pragma: no cover
|
|
|
227
227
|
# Refresh any open SettingsDialog instances so the ball & stick color preview updates
|
|
228
228
|
try:
|
|
229
229
|
# Avoid circular import at module level; import SettingsDialog on demand
|
|
230
|
+
import importlib
|
|
230
231
|
try:
|
|
231
|
-
|
|
232
|
-
except
|
|
233
|
-
|
|
232
|
+
mod = importlib.import_module('.settings_dialog', package='moleditpy.modules')
|
|
233
|
+
except ImportError:
|
|
234
|
+
mod = importlib.import_module('modules.settings_dialog')
|
|
235
|
+
SettingsDialog = mod.SettingsDialog
|
|
234
236
|
|
|
235
237
|
for w in QApplication.topLevelWidgets():
|
|
236
238
|
try:
|
|
@@ -585,15 +585,7 @@ class ConstrainedOptimizationDialog(Dialog3DPickingMixin, QDialog): # pragma: no
|
|
|
585
585
|
else:
|
|
586
586
|
self.selection_labels.append(label_actor)
|
|
587
587
|
|
|
588
|
-
|
|
589
|
-
"""選択ラベル(A1, A2...)をクリア"""
|
|
590
|
-
if hasattr(self, 'selection_labels'):
|
|
591
|
-
for label_actor in self.selection_labels:
|
|
592
|
-
try:
|
|
593
|
-
self.main_window.plotter.remove_actor(label_actor)
|
|
594
|
-
except Exception:
|
|
595
|
-
pass
|
|
596
|
-
self.selection_labels = []
|
|
588
|
+
|
|
597
589
|
|
|
598
590
|
def on_cell_changed(self, row, column):
|
|
599
591
|
"""テーブルのセルが編集されたときに内部データを更新する"""
|
|
@@ -134,3 +134,72 @@ class Dialog3DPickingMixin:
|
|
|
134
134
|
|
|
135
135
|
def try_alternative_picking(self, x, y):
|
|
136
136
|
"""代替のピッキング方法(使用しない)"""
|
|
137
|
+
|
|
138
|
+
# ------------------------------------------------------------------
|
|
139
|
+
# Label management (shared across dialogs)
|
|
140
|
+
# ------------------------------------------------------------------
|
|
141
|
+
|
|
142
|
+
def clear_atom_labels(self):
|
|
143
|
+
"""Remove all label actors from the plotter."""
|
|
144
|
+
if hasattr(self, 'selection_labels'):
|
|
145
|
+
for label_actor in self.selection_labels:
|
|
146
|
+
try:
|
|
147
|
+
self.main_window.plotter.remove_actor(label_actor)
|
|
148
|
+
except Exception:
|
|
149
|
+
pass
|
|
150
|
+
self.selection_labels = []
|
|
151
|
+
|
|
152
|
+
# Alias — some dialogs use this name instead.
|
|
153
|
+
clear_selection_labels = clear_atom_labels
|
|
154
|
+
|
|
155
|
+
def add_selection_label(self, atom_idx, label_text, color='yellow'):
|
|
156
|
+
"""Add a point label at the position of *atom_idx*.
|
|
157
|
+
|
|
158
|
+
Parameters
|
|
159
|
+
----------
|
|
160
|
+
atom_idx : int
|
|
161
|
+
Index into ``self.main_window.atom_positions_3d``.
|
|
162
|
+
label_text : str
|
|
163
|
+
Text shown next to the atom.
|
|
164
|
+
color : str, optional
|
|
165
|
+
Label colour (default ``'yellow'``).
|
|
166
|
+
"""
|
|
167
|
+
if not hasattr(self, 'selection_labels'):
|
|
168
|
+
self.selection_labels = []
|
|
169
|
+
|
|
170
|
+
pos = self.main_window.atom_positions_3d[atom_idx]
|
|
171
|
+
|
|
172
|
+
label_actor = self.main_window.plotter.add_point_labels(
|
|
173
|
+
[pos], [label_text],
|
|
174
|
+
point_size=20,
|
|
175
|
+
font_size=12,
|
|
176
|
+
text_color=color,
|
|
177
|
+
always_visible=True
|
|
178
|
+
)
|
|
179
|
+
self.selection_labels.append(label_actor)
|
|
180
|
+
|
|
181
|
+
def show_atom_labels_for(self, atoms_and_labels, color='yellow'):
|
|
182
|
+
"""Clear existing labels and add new ones for each *(idx, text)* pair.
|
|
183
|
+
|
|
184
|
+
Parameters
|
|
185
|
+
----------
|
|
186
|
+
atoms_and_labels : list[tuple[int, str]]
|
|
187
|
+
Each element is ``(atom_idx, label_text)``.
|
|
188
|
+
color : str, optional
|
|
189
|
+
Label colour (default ``'yellow'``).
|
|
190
|
+
"""
|
|
191
|
+
self.clear_atom_labels()
|
|
192
|
+
|
|
193
|
+
if not hasattr(self, 'selection_labels'):
|
|
194
|
+
self.selection_labels = []
|
|
195
|
+
|
|
196
|
+
for atom_idx, label_text in atoms_and_labels:
|
|
197
|
+
pos = self.main_window.atom_positions_3d[atom_idx]
|
|
198
|
+
label_actor = self.main_window.plotter.add_point_labels(
|
|
199
|
+
[pos], [label_text],
|
|
200
|
+
point_size=20,
|
|
201
|
+
font_size=12,
|
|
202
|
+
text_color=color,
|
|
203
|
+
always_visible=True
|
|
204
|
+
)
|
|
205
|
+
self.selection_labels.append(label_actor)
|