MoleditPy 2.2.0a1__py3-none-any.whl → 2.2.0a3__py3-none-any.whl

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 (28) hide show
  1. moleditpy/modules/constants.py +1 -1
  2. moleditpy/modules/main_window_main_init.py +31 -13
  3. moleditpy/modules/main_window_ui_manager.py +21 -2
  4. moleditpy/modules/plugin_interface.py +1 -10
  5. moleditpy/modules/plugin_manager.py +0 -3
  6. {moleditpy-2.2.0a1.dist-info → moleditpy-2.2.0a3.dist-info}/METADATA +1 -1
  7. {moleditpy-2.2.0a1.dist-info → moleditpy-2.2.0a3.dist-info}/RECORD +11 -28
  8. moleditpy/plugins/Analysis/ms_spectrum_neo.py +0 -919
  9. moleditpy/plugins/File/animated_xyz_giffer.py +0 -583
  10. moleditpy/plugins/File/cube_viewer.py +0 -689
  11. moleditpy/plugins/File/gaussian_fchk_freq_analyzer.py +0 -1148
  12. moleditpy/plugins/File/mapped_cube_viewer.py +0 -552
  13. moleditpy/plugins/File/orca_out_freq_analyzer.py +0 -1226
  14. moleditpy/plugins/File/paste_xyz.py +0 -336
  15. moleditpy/plugins/Input Generator/gaussian_input_generator_neo.py +0 -930
  16. moleditpy/plugins/Input Generator/orca_input_generator_neo.py +0 -1028
  17. moleditpy/plugins/Input Generator/orca_xyz2inp_gui.py +0 -286
  18. moleditpy/plugins/Optimization/all-trans_optimizer.py +0 -65
  19. moleditpy/plugins/Optimization/complex_molecule_untangler.py +0 -268
  20. moleditpy/plugins/Optimization/conf_search.py +0 -224
  21. moleditpy/plugins/Utility/atom_colorizer.py +0 -547
  22. moleditpy/plugins/Utility/console.py +0 -163
  23. moleditpy/plugins/Utility/pubchem_ressolver.py +0 -244
  24. moleditpy/plugins/Utility/vdw_radii_overlay.py +0 -303
  25. {moleditpy-2.2.0a1.dist-info → moleditpy-2.2.0a3.dist-info}/WHEEL +0 -0
  26. {moleditpy-2.2.0a1.dist-info → moleditpy-2.2.0a3.dist-info}/entry_points.txt +0 -0
  27. {moleditpy-2.2.0a1.dist-info → moleditpy-2.2.0a3.dist-info}/licenses/LICENSE +0 -0
  28. {moleditpy-2.2.0a1.dist-info → moleditpy-2.2.0a3.dist-info}/top_level.txt +0 -0
@@ -1,303 +0,0 @@
1
-
2
- import os
3
- import json
4
- import traceback
5
- import pyvista as pv
6
- import numpy as np
7
- import functools
8
- import types
9
- from PyQt6.QtWidgets import (QDialog, QVBoxLayout, QLabel,
10
- QSlider, QHBoxLayout, QPushButton)
11
- from PyQt6.QtGui import QAction
12
- from PyQt6.QtCore import Qt, QTimer
13
-
14
- # Try to import VDW radii from constants, fallback if needed
15
- try:
16
- from moleditpy.modules.constants import pt, CPK_COLORS_PV
17
- except ImportError:
18
- try:
19
- from modules.constants import pt, CPK_COLORS_PV
20
- except ImportError:
21
- try:
22
- from rdkit import Chem
23
- pt = Chem.GetPeriodicTable()
24
- except Exception:
25
- pt = None
26
- CPK_COLORS_PV = {} # Last resort fallback
27
-
28
-
29
- # Plugin Metadata
30
- __version__="2025.12.17"
31
- __author__="HiroYokoyama"
32
- PLUGIN_NAME = "VDW Radii Overlay"
33
- SETTINGS_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "vdw_radii_overlay.json")
34
-
35
- # Global State
36
- _config_window = None
37
- _vdw_settings = {
38
- "occupancy": 0.3 # Opacity (0.0 - 1.0)
39
- }
40
-
41
- def load_settings():
42
- global _vdw_settings
43
- try:
44
- if os.path.exists(SETTINGS_FILE):
45
- with open(SETTINGS_FILE, 'r') as f:
46
- saved = json.load(f)
47
- # Filter to only keep occupancy
48
- if "occupancy" in saved:
49
- _vdw_settings["occupancy"] = float(saved["occupancy"])
50
- except Exception as e:
51
- print(f"Error loading VDW settings: {e}")
52
-
53
- def save_settings():
54
- try:
55
- with open(SETTINGS_FILE, 'w') as f:
56
- json.dump(_vdw_settings, f, indent=4)
57
- except Exception as e:
58
- print(f"Error saving VDW settings: {e}")
59
-
60
- class VDWConfigWindow(QDialog):
61
- def __init__(self, main_window):
62
- super().__init__(parent=main_window)
63
- self.mw = main_window
64
- self.setWindowTitle("VDW Overlay Settings")
65
- self.setModal(False)
66
- self.resize(300, 100)
67
- self.init_ui()
68
-
69
- def init_ui(self):
70
- layout = QVBoxLayout()
71
-
72
- # Occupancy Slider
73
- occ_layout = QHBoxLayout()
74
- occ_layout.addWidget(QLabel("Occupancy:"))
75
- self.slider_occ = QSlider(Qt.Orientation.Horizontal)
76
- self.slider_occ.setRange(0, 100)
77
- current_occ = int(_vdw_settings.get("occupancy", 0.3) * 100)
78
- self.slider_occ.setValue(current_occ)
79
- self.slider_occ.valueChanged.connect(self.on_occupancy_changed)
80
- occ_layout.addWidget(self.slider_occ)
81
- self.lbl_occ_val = QLabel(f"{current_occ}%")
82
- occ_layout.addWidget(self.lbl_occ_val)
83
- layout.addLayout(occ_layout)
84
-
85
- # Close Button
86
- btn_close = QPushButton("Close")
87
- btn_close.clicked.connect(self.close)
88
- layout.addWidget(btn_close)
89
-
90
- self.setLayout(layout)
91
-
92
- def on_occupancy_changed(self, value):
93
- opacity = value / 100.0
94
- _vdw_settings["occupancy"] = opacity
95
- self.lbl_occ_val.setText(f"{value}%")
96
- save_settings()
97
- self.update_view()
98
-
99
- def update_view(self):
100
- # Trigger redraw if we are in the correct mode
101
- if hasattr(self.mw, 'current_3d_style') and self.mw.current_3d_style == "vdw_overlay":
102
- if getattr(self.mw, 'current_mol', None):
103
- # Trigger redraw
104
- if hasattr(self.mw, 'draw_molecule_3d'):
105
- self.mw.draw_molecule_3d(self.mw.current_mol)
106
-
107
- def draw_vdw_overlay(mw, mol):
108
- """
109
- Callback for drawing the VDW overlay style.
110
- Registered via context.register_3d_style.
111
- """
112
- # 1. Draw standard Ball & Stick
113
- # Attempt to locate the standard draw method
114
- draw_std = None
115
- if hasattr(mw, 'main_window_view_3d') and hasattr(mw.main_window_view_3d, 'draw_standard_3d_style'):
116
- draw_std = mw.main_window_view_3d.draw_standard_3d_style
117
- elif hasattr(mw, 'view3d') and hasattr(mw.view3d, 'draw_standard_3d_style'):
118
- draw_std = mw.view3d.draw_standard_3d_style
119
-
120
- if draw_std:
121
- draw_std(mol, style_override='ball_and_stick')
122
- else:
123
- print("VDW Plugin Error: could not find draw_standard_3d_style")
124
- return
125
-
126
- # 2. Draw VDW Surface Overlay
127
- if mol and mol.GetNumAtoms() > 0:
128
- try:
129
- positions = []
130
- radii = []
131
- atom_colors = []
132
-
133
- # Use custom colors if available, otherwise CPK
134
- custom_map = getattr(mw, 'custom_atom_colors', {})
135
-
136
- if mol.GetNumConformers() > 0:
137
- conf = mol.GetConformer()
138
- for i in range(mol.GetNumAtoms()):
139
- atom = mol.GetAtomWithIdx(i)
140
- pos = conf.GetAtomPosition(i)
141
- positions.append([pos.x, pos.y, pos.z])
142
-
143
- sym = atom.GetSymbol()
144
- # GetRvdw returns standard VDW radius.
145
- r = 1.5 # Default
146
- if pt:
147
- r = pt.GetRvdw(atom.GetAtomicNum())
148
- radii.append(r)
149
-
150
- # Color handling
151
- if i in custom_map:
152
- c = custom_map[i]
153
- # Normalize 0-255 to 0-1 if needed
154
- if any(x > 1.0 for x in c):
155
- c = [x/255.0 for x in c]
156
- else:
157
- c = CPK_COLORS_PV.get(sym, [0.8, 0.8, 0.8]) # Default grey if missing
158
- atom_colors.append(c)
159
-
160
- if positions:
161
- positions = np.array(positions)
162
- radii = np.array(radii)
163
- atom_colors = np.array(atom_colors)
164
-
165
- # --- Generate Merged Surface (SDF) ---
166
-
167
- # 1. Define Grid Bounds
168
- padding = radii.max() + 1.0
169
- min_bounds = positions.min(axis=0) - padding
170
- max_bounds = positions.max(axis=0) + padding
171
-
172
- # Resolution (voxel size in Angstroms)
173
- spacing = (0.125, 0.125, 0.125)
174
-
175
- dims = np.ceil((max_bounds - min_bounds) / spacing).astype(int)
176
-
177
- grid = pv.ImageData()
178
- grid.dimensions = dims
179
- grid.origin = min_bounds
180
- grid.spacing = spacing
181
-
182
- grid_points = grid.points
183
- n_points = grid_points.shape[0]
184
- values = np.empty(n_points)
185
-
186
- # Process in chunks of 100k points
187
- chunk_size = 100000
188
- for start_idx in range(0, n_points, chunk_size):
189
- end_idx = min(start_idx + chunk_size, n_points)
190
- chunk_pts = grid_points[start_idx:end_idx]
191
-
192
- d = np.linalg.norm(chunk_pts[:, np.newaxis, :] - positions[np.newaxis, :, :], axis=2)
193
- d_surface = d - radii[np.newaxis, :]
194
- values[start_idx:end_idx] = d_surface.min(axis=1)
195
-
196
- grid.point_data["values"] = values
197
-
198
- # 3. Contour at iso-value 0 to get the surface
199
- mesh = grid.contour([0], scalars="values")
200
-
201
- # 4. Map Colors to Surface Vertices
202
- mesh_points = mesh.points
203
- if mesh_points.shape[0] > 0:
204
- n_mesh_pts = mesh_points.shape[0]
205
- mesh_colors = np.zeros((n_mesh_pts, 3))
206
-
207
- chunk_size = 50000
208
- for start_idx in range(0, n_mesh_pts, chunk_size):
209
- end_idx = min(start_idx + chunk_size, n_mesh_pts)
210
- chunk_pts = mesh_points[start_idx:end_idx]
211
-
212
- d_center = np.linalg.norm(chunk_pts[:, np.newaxis, :] - positions[np.newaxis, :, :], axis=2)
213
- d_surface = d_center - radii[np.newaxis, :]
214
- nearest_atom_indices = np.argmin(d_surface, axis=1)
215
- mesh_colors[start_idx:end_idx] = atom_colors[nearest_atom_indices]
216
-
217
- mesh.point_data["AtomColors"] = mesh_colors
218
-
219
- opacity = _vdw_settings.get("occupancy", 0.3)
220
-
221
- # Assume mw.plotter is available
222
- if hasattr(mw, 'plotter'):
223
- mw.plotter.add_mesh(
224
- mesh,
225
- scalars="AtomColors",
226
- rgb=True,
227
- opacity=opacity,
228
- smooth_shading=True,
229
- specular=0.2,
230
- name="vdw_overlay_mesh"
231
- )
232
-
233
- except Exception as e:
234
- print(f"VDW Overlay Error: {e}")
235
- traceback.print_exc()
236
-
237
- def run(mw):
238
- global _config_window
239
- load_settings()
240
-
241
- if _config_window is None:
242
- _config_window = VDWConfigWindow(mw)
243
- _config_window.finished.connect(lambda: _cleanup_config())
244
-
245
- _config_window.show()
246
- _config_window.raise_()
247
- _config_window.activateWindow()
248
-
249
- def initialize(context):
250
- """
251
- New Plugin System Entry Point
252
- """
253
- mw = context.get_main_window()
254
- load_settings()
255
-
256
- # Register 3D Style
257
- if hasattr(context, 'register_3d_style'):
258
- context.register_3d_style("vdw_overlay", draw_vdw_overlay)
259
- else:
260
- print("Error: PluginContext does not support register_3d_style")
261
-
262
- # 1. Register Configuration Menu - REMOVED in favor of run()
263
- # (Managed by run() function now)
264
-
265
- # 2. Inject into Style Menu (Legacy behavior preserved via mw access)
266
- def add_menu_item():
267
- # Locate the "3D Style" tool button on the main toolbar
268
- style_button = getattr(mw, 'style_button', None)
269
-
270
- if style_button and style_button.menu():
271
- style_menu = style_button.menu()
272
-
273
- # Check if already added
274
- exists = False
275
- for a in style_menu.actions():
276
- if a.text() == "VDW Overlay":
277
- exists = True
278
- break
279
-
280
- if not exists:
281
- # Add to action group for mutual exclusion
282
- existing_actions = style_menu.actions()
283
- group = None
284
- if existing_actions:
285
- group = existing_actions[0].actionGroup()
286
-
287
- action = QAction("VDW Overlay", mw)
288
- action.setCheckable(True)
289
-
290
- if group:
291
- group.addAction(action)
292
-
293
- # Connect to set_3d_style
294
- action.triggered.connect(lambda: mw.set_3d_style("vdw_overlay"))
295
-
296
- style_menu.addAction(action)
297
-
298
- # Run after 2000ms to ensure UI is ready
299
- QTimer.singleShot(2000, add_menu_item)
300
-
301
- def _cleanup_config():
302
- global _config_window
303
- _config_window = None