MoleditPy-linux 1.18.0__tar.gz → 1.18.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.
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/PKG-INFO +1 -2
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/pyproject.toml +1 -2
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/MoleditPy_linux.egg-info/PKG-INFO +1 -2
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/align_plane_dialog.py +1 -1
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/alignment_dialog.py +1 -1
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/angle_dialog.py +2 -2
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/bond_length_dialog.py +2 -2
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/constants.py +1 -1
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/constrained_optimization_dialog.py +2 -2
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/dihedral_dialog.py +1 -1
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/main_window_app_state.py +1 -1
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/main_window_edit_3d.py +7 -7
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/main_window_export.py +106 -49
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/main_window_main_init.py +3 -3
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/main_window_molecular_parsers.py +4 -3
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/main_window_project_io.py +2 -2
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/main_window_view_3d.py +13 -12
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/main_window_view_loaders.py +1 -1
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/molecule_scene.py +7 -12
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/planarize_dialog.py +1 -1
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/settings_dialog.py +5 -23
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/user_template_dialog.py +9 -8
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/LICENSE +0 -0
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/README.md +0 -0
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/setup.cfg +0 -0
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/MoleditPy_linux.egg-info/SOURCES.txt +0 -0
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/MoleditPy_linux.egg-info/dependency_links.txt +0 -0
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/MoleditPy_linux.egg-info/entry_points.txt +0 -0
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/MoleditPy_linux.egg-info/requires.txt +0 -0
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/MoleditPy_linux.egg-info/top_level.txt +0 -0
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/__init__.py +0 -0
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/__main__.py +0 -0
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/main.py +0 -0
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/__init__.py +0 -0
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/about_dialog.py +0 -0
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/analysis_window.py +0 -0
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/assets/icon.icns +0 -0
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/assets/icon.ico +0 -0
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/assets/icon.png +0 -0
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/atom_item.py +0 -0
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/bond_item.py +0 -0
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/calculation_worker.py +0 -0
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/color_settings_dialog.py +0 -0
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/custom_interactor_style.py +0 -0
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/custom_qt_interactor.py +0 -0
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/dialog3_d_picking_mixin.py +0 -0
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/main_window.py +0 -0
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/main_window_compute.py +0 -0
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/main_window_dialog_manager.py +0 -0
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/main_window_edit_actions.py +0 -0
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/main_window_string_importers.py +0 -0
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/main_window_ui_manager.py +0 -0
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/mirror_dialog.py +0 -0
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/molecular_data.py +0 -0
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/move_group_dialog.py +0 -0
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/periodic_table_dialog.py +0 -0
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/template_preview_item.py +0 -0
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/template_preview_view.py +0 -0
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/translation_dialog.py +0 -0
- {moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/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: 1.18.
|
|
3
|
+
Version: 1.18.1
|
|
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
|
|
@@ -684,7 +684,6 @@ Classifier: Programming Language :: Python :: 3
|
|
|
684
684
|
Classifier: Operating System :: OS Independent
|
|
685
685
|
Classifier: Intended Audience :: Science/Research
|
|
686
686
|
Classifier: Topic :: Scientific/Engineering :: Chemistry
|
|
687
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
688
687
|
Classifier: Programming Language :: Python :: 3.9
|
|
689
688
|
Classifier: Programming Language :: Python :: 3.10
|
|
690
689
|
Classifier: Programming Language :: Python :: 3.11
|
|
@@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "MoleditPy-linux"
|
|
7
7
|
|
|
8
|
-
version = "1.18.
|
|
8
|
+
version = "1.18.1"
|
|
9
9
|
|
|
10
10
|
license = {file = "LICENSE"}
|
|
11
11
|
|
|
@@ -24,7 +24,6 @@ classifiers = [
|
|
|
24
24
|
"Operating System :: OS Independent",
|
|
25
25
|
"Intended Audience :: Science/Research",
|
|
26
26
|
"Topic :: Scientific/Engineering :: Chemistry",
|
|
27
|
-
"Programming Language :: Python :: 3.8",
|
|
28
27
|
"Programming Language :: Python :: 3.9",
|
|
29
28
|
"Programming Language :: Python :: 3.10",
|
|
30
29
|
"Programming Language :: Python :: 3.11",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: MoleditPy-linux
|
|
3
|
-
Version: 1.18.
|
|
3
|
+
Version: 1.18.1
|
|
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
|
|
@@ -684,7 +684,6 @@ Classifier: Programming Language :: Python :: 3
|
|
|
684
684
|
Classifier: Operating System :: OS Independent
|
|
685
685
|
Classifier: Intended Audience :: Science/Research
|
|
686
686
|
Classifier: Topic :: Scientific/Engineering :: Chemistry
|
|
687
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
688
687
|
Classifier: Programming Language :: Python :: 3.9
|
|
689
688
|
Classifier: Programming Language :: Python :: 3.10
|
|
690
689
|
Classifier: Programming Language :: Python :: 3.11
|
{moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/angle_dialog.py
RENAMED
|
@@ -202,7 +202,7 @@ class AngleDialog(Dialog3DPickingMixin, QDialog):
|
|
|
202
202
|
for label_actor in self.selection_labels:
|
|
203
203
|
try:
|
|
204
204
|
self.main_window.plotter.remove_actor(label_actor)
|
|
205
|
-
except:
|
|
205
|
+
except Exception:
|
|
206
206
|
pass
|
|
207
207
|
self.selection_labels = []
|
|
208
208
|
|
|
@@ -212,7 +212,7 @@ class AngleDialog(Dialog3DPickingMixin, QDialog):
|
|
|
212
212
|
for label_actor in self.selection_labels:
|
|
213
213
|
try:
|
|
214
214
|
self.main_window.plotter.remove_actor(label_actor)
|
|
215
|
-
except:
|
|
215
|
+
except Exception:
|
|
216
216
|
pass
|
|
217
217
|
self.selection_labels = []
|
|
218
218
|
|
{moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/bond_length_dialog.py
RENAMED
|
@@ -190,7 +190,7 @@ class BondLengthDialog(Dialog3DPickingMixin, QDialog):
|
|
|
190
190
|
for label_actor in self.selection_labels:
|
|
191
191
|
try:
|
|
192
192
|
self.main_window.plotter.remove_actor(label_actor)
|
|
193
|
-
except:
|
|
193
|
+
except Exception:
|
|
194
194
|
pass
|
|
195
195
|
self.selection_labels = []
|
|
196
196
|
|
|
@@ -200,7 +200,7 @@ class BondLengthDialog(Dialog3DPickingMixin, QDialog):
|
|
|
200
200
|
for label_actor in self.selection_labels:
|
|
201
201
|
try:
|
|
202
202
|
self.main_window.plotter.remove_actor(label_actor)
|
|
203
|
-
except:
|
|
203
|
+
except Exception:
|
|
204
204
|
pass
|
|
205
205
|
self.selection_labels = []
|
|
206
206
|
|
|
@@ -394,7 +394,7 @@ class ConstrainedOptimizationDialog(Dialog3DPickingMixin, QDialog):
|
|
|
394
394
|
for label_actor in self.constraint_labels:
|
|
395
395
|
try:
|
|
396
396
|
self.main_window.plotter.remove_actor(label_actor)
|
|
397
|
-
except:
|
|
397
|
+
except Exception:
|
|
398
398
|
pass
|
|
399
399
|
self.constraint_labels = []
|
|
400
400
|
|
|
@@ -595,7 +595,7 @@ class ConstrainedOptimizationDialog(Dialog3DPickingMixin, QDialog):
|
|
|
595
595
|
for label_actor in self.selection_labels:
|
|
596
596
|
try:
|
|
597
597
|
self.main_window.plotter.remove_actor(label_actor)
|
|
598
|
-
except:
|
|
598
|
+
except Exception:
|
|
599
599
|
pass
|
|
600
600
|
self.selection_labels = []
|
|
601
601
|
|
|
@@ -574,7 +574,7 @@ class MainWindowAppState(object):
|
|
|
574
574
|
inchi_key = Chem.MolToInchiKey(self.current_mol)
|
|
575
575
|
json_data["identifiers"]["inchi"] = inchi
|
|
576
576
|
json_data["identifiers"]["inchi_key"] = inchi_key
|
|
577
|
-
except:
|
|
577
|
+
except Exception:
|
|
578
578
|
pass # InChI生成に失敗した場合は無視
|
|
579
579
|
|
|
580
580
|
except Exception as e:
|
{moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/main_window_edit_3d.py
RENAMED
|
@@ -119,7 +119,7 @@ class MainWindowEdit3d(object):
|
|
|
119
119
|
for dialog in dialogs_to_close:
|
|
120
120
|
try:
|
|
121
121
|
dialog.close()
|
|
122
|
-
except:
|
|
122
|
+
except Exception:
|
|
123
123
|
pass
|
|
124
124
|
self.active_3d_dialogs.clear()
|
|
125
125
|
|
|
@@ -169,7 +169,7 @@ class MainWindowEdit3d(object):
|
|
|
169
169
|
try:
|
|
170
170
|
# 既存の測定ラベルを削除
|
|
171
171
|
self.plotter.remove_actor('measurement_labels')
|
|
172
|
-
except:
|
|
172
|
+
except Exception:
|
|
173
173
|
pass
|
|
174
174
|
|
|
175
175
|
if not self.measurement_labels or not self.current_mol:
|
|
@@ -208,7 +208,7 @@ class MainWindowEdit3d(object):
|
|
|
208
208
|
self.measurement_labels.clear()
|
|
209
209
|
try:
|
|
210
210
|
self.plotter.remove_actor('measurement_labels')
|
|
211
|
-
except:
|
|
211
|
+
except Exception:
|
|
212
212
|
pass
|
|
213
213
|
|
|
214
214
|
# 2Dビューの測定ラベルも削除
|
|
@@ -219,7 +219,7 @@ class MainWindowEdit3d(object):
|
|
|
219
219
|
try:
|
|
220
220
|
self.plotter.remove_actor(self.measurement_text_actor)
|
|
221
221
|
self.measurement_text_actor = None
|
|
222
|
-
except:
|
|
222
|
+
except Exception:
|
|
223
223
|
pass
|
|
224
224
|
|
|
225
225
|
self.plotter.render()
|
|
@@ -434,7 +434,7 @@ class MainWindowEdit3d(object):
|
|
|
434
434
|
if self.measurement_text_actor:
|
|
435
435
|
try:
|
|
436
436
|
self.plotter.remove_actor(self.measurement_text_actor)
|
|
437
|
-
except:
|
|
437
|
+
except Exception:
|
|
438
438
|
pass
|
|
439
439
|
|
|
440
440
|
if not measurement_lines:
|
|
@@ -453,7 +453,7 @@ class MainWindowEdit3d(object):
|
|
|
453
453
|
text_color = 'black' if luminance > 128 else 'white'
|
|
454
454
|
else:
|
|
455
455
|
text_color = 'white'
|
|
456
|
-
except:
|
|
456
|
+
except Exception:
|
|
457
457
|
text_color = 'white'
|
|
458
458
|
|
|
459
459
|
# 左上に表示(小さな等幅フォント)
|
|
@@ -496,7 +496,7 @@ class MainWindowEdit3d(object):
|
|
|
496
496
|
try:
|
|
497
497
|
# 既存の選択ハイライトを削除
|
|
498
498
|
self.plotter.remove_actor('selection_highlight')
|
|
499
|
-
except:
|
|
499
|
+
except Exception:
|
|
500
500
|
pass
|
|
501
501
|
|
|
502
502
|
if not self.selected_atoms_3d or not self.current_mol:
|
{moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/main_window_export.py
RENAMED
|
@@ -178,11 +178,6 @@ class MainWindowExport(object):
|
|
|
178
178
|
except Exception as e:
|
|
179
179
|
self.statusBar().showMessage(f"Error exporting OBJ/MTL: {e}")
|
|
180
180
|
|
|
181
|
-
return meshes_with_colors
|
|
182
|
-
|
|
183
|
-
except Exception:
|
|
184
|
-
return []
|
|
185
|
-
|
|
186
181
|
|
|
187
182
|
|
|
188
183
|
def create_multi_material_obj(self, meshes_with_colors, obj_path, mtl_path):
|
|
@@ -199,17 +194,17 @@ class MainWindowExport(object):
|
|
|
199
194
|
material_name = f"material_{i}_{mesh_data['name'].replace(' ', '_')}"
|
|
200
195
|
|
|
201
196
|
mtl_file.write(f"newmtl {material_name}\n")
|
|
202
|
-
mtl_file.write("Ka 0.2 0.2 0.2\n") # Ambient
|
|
197
|
+
mtl_file.write(f"Ka 0.2 0.2 0.2\n") # Ambient
|
|
203
198
|
mtl_file.write(f"Kd {color[0]/255.0:.3f} {color[1]/255.0:.3f} {color[2]/255.0:.3f}\n") # Diffuse
|
|
204
|
-
mtl_file.write("Ks 0.5 0.5 0.5\n") # Specular
|
|
205
|
-
mtl_file.write("Ns 32.0\n") # Specular exponent
|
|
206
|
-
mtl_file.write("illum 2\n") # Illumination model
|
|
207
|
-
mtl_file.write("\n")
|
|
199
|
+
mtl_file.write(f"Ks 0.5 0.5 0.5\n") # Specular
|
|
200
|
+
mtl_file.write(f"Ns 32.0\n") # Specular exponent
|
|
201
|
+
mtl_file.write(f"illum 2\n") # Illumination model
|
|
202
|
+
mtl_file.write(f"\n")
|
|
208
203
|
|
|
209
204
|
# OBJファイルを作成
|
|
210
205
|
with open(obj_path, 'w') as obj_file:
|
|
211
|
-
obj_file.write("# OBJ file with multiple materials\n")
|
|
212
|
-
obj_file.write("# Generated with individual object colors\n")
|
|
206
|
+
obj_file.write(f"# OBJ file with multiple materials\n")
|
|
207
|
+
obj_file.write(f"# Generated with individual object colors\n")
|
|
213
208
|
obj_file.write(f"mtllib {os.path.basename(mtl_path)}\n\n")
|
|
214
209
|
|
|
215
210
|
vertex_offset = 1 # OBJファイルの頂点インデックスは1から始まる
|
|
@@ -229,6 +224,7 @@ class MainWindowExport(object):
|
|
|
229
224
|
obj_file.write(f"v {point[0]:.6f} {point[1]:.6f} {point[2]:.6f}\n")
|
|
230
225
|
|
|
231
226
|
# 面を書き込み
|
|
227
|
+
faces_written = 0
|
|
232
228
|
for j in range(mesh.n_cells):
|
|
233
229
|
cell = mesh.get_cell(j)
|
|
234
230
|
if cell.type == 5: # VTK_TRIANGLE
|
|
@@ -237,6 +233,25 @@ class MainWindowExport(object):
|
|
|
237
233
|
v2 = points_in_cell[1] + vertex_offset
|
|
238
234
|
v3 = points_in_cell[2] + vertex_offset
|
|
239
235
|
obj_file.write(f"f {v1} {v2} {v3}\n")
|
|
236
|
+
faces_written += 1
|
|
237
|
+
elif cell.type == 6: # VTK_TRIANGLE_STRIP
|
|
238
|
+
# Triangle strips share vertices between adjacent triangles
|
|
239
|
+
# For n points, we get (n-2) triangles
|
|
240
|
+
points_in_cell = cell.point_ids
|
|
241
|
+
n_points = len(points_in_cell)
|
|
242
|
+
for k in range(n_points - 2):
|
|
243
|
+
if k % 2 == 0:
|
|
244
|
+
# Even triangles: use points k, k+1, k+2
|
|
245
|
+
v1 = points_in_cell[k] + vertex_offset
|
|
246
|
+
v2 = points_in_cell[k+1] + vertex_offset
|
|
247
|
+
v3 = points_in_cell[k+2] + vertex_offset
|
|
248
|
+
else:
|
|
249
|
+
# Odd triangles: reverse winding to maintain consistent orientation
|
|
250
|
+
v1 = points_in_cell[k+1] + vertex_offset
|
|
251
|
+
v2 = points_in_cell[k] + vertex_offset
|
|
252
|
+
v3 = points_in_cell[k+2] + vertex_offset
|
|
253
|
+
obj_file.write(f"f {v1} {v2} {v3}\n")
|
|
254
|
+
faces_written += 1
|
|
240
255
|
elif cell.type == 9: # VTK_QUAD
|
|
241
256
|
points_in_cell = cell.point_ids
|
|
242
257
|
v1 = points_in_cell[0] + vertex_offset
|
|
@@ -244,10 +259,12 @@ class MainWindowExport(object):
|
|
|
244
259
|
v3 = points_in_cell[2] + vertex_offset
|
|
245
260
|
v4 = points_in_cell[3] + vertex_offset
|
|
246
261
|
obj_file.write(f"f {v1} {v2} {v3} {v4}\n")
|
|
262
|
+
faces_written += 1
|
|
247
263
|
|
|
248
|
-
vertex_offset += mesh.n_points
|
|
249
|
-
obj_file.write("\n")
|
|
250
264
|
|
|
265
|
+
vertex_offset += mesh.n_points
|
|
266
|
+
obj_file.write(f"\n")
|
|
267
|
+
|
|
251
268
|
except Exception as e:
|
|
252
269
|
raise Exception(f"Failed to create multi-material OBJ: {e}")
|
|
253
270
|
|
|
@@ -310,24 +327,25 @@ class MainWindowExport(object):
|
|
|
310
327
|
# VTKアクターからポリデータを取得する複数の方法を試行
|
|
311
328
|
mesh = None
|
|
312
329
|
|
|
313
|
-
# 方法1: mapperのinputから取得
|
|
330
|
+
# 方法1: mapperのinputから取得 (Improved)
|
|
331
|
+
mapper = None
|
|
314
332
|
if hasattr(actor, 'mapper') and actor.mapper is not None:
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
333
|
+
mapper = actor.mapper
|
|
334
|
+
elif hasattr(actor, 'GetMapper'):
|
|
335
|
+
mapper = actor.GetMapper()
|
|
336
|
+
|
|
337
|
+
if mapper is not None:
|
|
338
|
+
if hasattr(mapper, 'input') and mapper.input is not None:
|
|
339
|
+
mesh = mapper.input
|
|
340
|
+
elif hasattr(mapper, 'GetInput') and mapper.GetInput() is not None:
|
|
341
|
+
mesh = mapper.GetInput()
|
|
342
|
+
elif hasattr(mapper, 'GetInputAsDataSet'):
|
|
343
|
+
mesh = mapper.GetInputAsDataSet()
|
|
319
344
|
|
|
320
345
|
# 方法2: PyVistaプロッターの内部データから取得
|
|
321
346
|
if mesh is None and actor_name in self.plotter.mesh:
|
|
322
347
|
mesh = self.plotter.mesh[actor_name]
|
|
323
348
|
|
|
324
|
-
# 方法3: PyVistaのメッシュデータベースから検索
|
|
325
|
-
if mesh is None:
|
|
326
|
-
for mesh_name, mesh_data in self.plotter.mesh.items():
|
|
327
|
-
if mesh_data is not None and mesh_data.n_points > 0:
|
|
328
|
-
mesh = mesh_data
|
|
329
|
-
break
|
|
330
|
-
|
|
331
349
|
if mesh is not None and hasattr(mesh, 'n_points') and mesh.n_points > 0:
|
|
332
350
|
# PyVistaメッシュに変換(必要な場合)
|
|
333
351
|
if not isinstance(mesh, pv.PolyData):
|
|
@@ -391,23 +409,26 @@ class MainWindowExport(object):
|
|
|
391
409
|
# VTKアクターからポリデータを取得する複数の方法を試行
|
|
392
410
|
mesh = None
|
|
393
411
|
|
|
394
|
-
# 方法1: mapperのinputから取得
|
|
412
|
+
# 方法1: mapperのinputから取得 (Improved)
|
|
413
|
+
mapper = None
|
|
395
414
|
if hasattr(actor, 'mapper') and actor.mapper is not None:
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
415
|
+
mapper = actor.mapper
|
|
416
|
+
elif hasattr(actor, 'GetMapper'):
|
|
417
|
+
mapper = actor.GetMapper()
|
|
418
|
+
|
|
419
|
+
if mapper is not None:
|
|
420
|
+
if hasattr(mapper, 'input') and mapper.input is not None:
|
|
421
|
+
mesh = mapper.input
|
|
422
|
+
elif hasattr(mapper, 'GetInput') and mapper.GetInput() is not None:
|
|
423
|
+
mesh = mapper.GetInput()
|
|
424
|
+
elif hasattr(mapper, 'GetInputAsDataSet'):
|
|
425
|
+
mesh = mapper.GetInputAsDataSet()
|
|
400
426
|
|
|
401
427
|
# 方法2: PyVistaプロッターの内部データから取得
|
|
402
428
|
if mesh is None and actor_name in self.plotter.mesh:
|
|
403
429
|
mesh = self.plotter.mesh[actor_name]
|
|
404
430
|
|
|
405
|
-
# 方法3:
|
|
406
|
-
if mesh is None:
|
|
407
|
-
for mesh_name, mesh_data in self.plotter.mesh.items():
|
|
408
|
-
if mesh_data is not None and mesh_data.n_points > 0:
|
|
409
|
-
mesh = mesh_data
|
|
410
|
-
break
|
|
431
|
+
# 方法3: Removed unsafe fallback
|
|
411
432
|
|
|
412
433
|
if mesh is not None and hasattr(mesh, 'n_points') and mesh.n_points > 0:
|
|
413
434
|
# PyVistaメッシュに変換(必要な場合)
|
|
@@ -447,17 +468,26 @@ class MainWindowExport(object):
|
|
|
447
468
|
actors = renderer.actors
|
|
448
469
|
|
|
449
470
|
actor_count = 0
|
|
471
|
+
|
|
450
472
|
for actor_name, actor in actors.items():
|
|
451
473
|
try:
|
|
452
474
|
# VTKアクターからポリデータを取得
|
|
453
475
|
mesh = None
|
|
454
476
|
|
|
455
|
-
# 方法1: mapperのinputから取得
|
|
477
|
+
# 方法1: mapperのinputから取得 (Improved)
|
|
478
|
+
mapper = None
|
|
456
479
|
if hasattr(actor, 'mapper') and actor.mapper is not None:
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
480
|
+
mapper = actor.mapper
|
|
481
|
+
elif hasattr(actor, 'GetMapper'):
|
|
482
|
+
mapper = actor.GetMapper()
|
|
483
|
+
|
|
484
|
+
if mapper is not None:
|
|
485
|
+
if hasattr(mapper, 'input') and mapper.input is not None:
|
|
486
|
+
mesh = mapper.input
|
|
487
|
+
elif hasattr(mapper, 'GetInput') and mapper.GetInput() is not None:
|
|
488
|
+
mesh = mapper.GetInput()
|
|
489
|
+
elif hasattr(mapper, 'GetInputAsDataSet'):
|
|
490
|
+
mesh = mapper.GetInputAsDataSet()
|
|
461
491
|
|
|
462
492
|
# 方法2: PyVistaプロッターの内部データから取得
|
|
463
493
|
if mesh is None and actor_name in self.plotter.mesh:
|
|
@@ -484,7 +514,7 @@ class MainWindowExport(object):
|
|
|
484
514
|
if prop is not None:
|
|
485
515
|
vtk_color = prop.GetColor()
|
|
486
516
|
color = [int(c * 255) for c in vtk_color]
|
|
487
|
-
except:
|
|
517
|
+
except Exception:
|
|
488
518
|
# 色取得に失敗した場合はデフォルト色をそのまま使用
|
|
489
519
|
pass
|
|
490
520
|
|
|
@@ -513,6 +543,16 @@ class MainWindowExport(object):
|
|
|
513
543
|
# 単一の colors 配列があればそれを使う
|
|
514
544
|
elif 'colors' in pd:
|
|
515
545
|
colors = np.asarray(pd['colors'])
|
|
546
|
+
|
|
547
|
+
# cell_dataのcolorsも確認(Tubeフィルタなどはcell_dataに色を持つ場合がある)
|
|
548
|
+
if colors is None and 'colors' in mesh_copy.cell_data:
|
|
549
|
+
try:
|
|
550
|
+
# cell_dataをpoint_dataに変換
|
|
551
|
+
temp_mesh = mesh_copy.cell_data_to_point_data()
|
|
552
|
+
if 'colors' in temp_mesh.point_data:
|
|
553
|
+
colors = np.asarray(temp_mesh.point_data['colors'])
|
|
554
|
+
except Exception:
|
|
555
|
+
pass
|
|
516
556
|
|
|
517
557
|
if colors is not None and colors.size > 0:
|
|
518
558
|
# 整数に変換。colors が 0-1 の float の場合は 255 倍して正規化する。
|
|
@@ -539,18 +579,26 @@ class MainWindowExport(object):
|
|
|
539
579
|
|
|
540
580
|
# 一意な色ごとにサブメッシュを抽出して追加
|
|
541
581
|
unique_colors, inverse = np.unique(colors_int, axis=0, return_inverse=True)
|
|
582
|
+
|
|
583
|
+
split_success = False
|
|
542
584
|
if unique_colors.shape[0] > 1:
|
|
543
585
|
for uc_idx, uc in enumerate(unique_colors):
|
|
544
586
|
point_inds = np.where(inverse == uc_idx)[0]
|
|
545
587
|
if point_inds.size == 0:
|
|
546
588
|
continue
|
|
547
589
|
try:
|
|
548
|
-
|
|
590
|
+
# Use temp_mesh if available (has point data), else mesh_copy
|
|
591
|
+
target_mesh = temp_mesh if 'temp_mesh' in locals() else mesh_copy
|
|
592
|
+
|
|
593
|
+
# extract_points with adjacent_cells=False to avoid pulling in neighbors
|
|
594
|
+
submesh = target_mesh.extract_points(point_inds, adjacent_cells=False)
|
|
595
|
+
|
|
549
596
|
except Exception:
|
|
550
597
|
# extract_points が利用できない場合はスキップ
|
|
551
598
|
continue
|
|
552
599
|
if submesh is None or getattr(submesh, 'n_points', 0) == 0:
|
|
553
600
|
continue
|
|
601
|
+
|
|
554
602
|
color_rgb = [int(uc[0]), int(uc[1]), int(uc[2])]
|
|
555
603
|
meshes_with_colors.append({
|
|
556
604
|
'mesh': submesh,
|
|
@@ -559,13 +607,22 @@ class MainWindowExport(object):
|
|
|
559
607
|
'type': 'display_actor',
|
|
560
608
|
'actor_name': actor_name
|
|
561
609
|
})
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
610
|
+
split_success = True
|
|
611
|
+
|
|
612
|
+
if split_success:
|
|
613
|
+
actor_count += 1
|
|
614
|
+
# 分割に成功したので以下の通常追加は行わない
|
|
615
|
+
continue
|
|
616
|
+
# If splitting failed (no submeshes added), fall through to default
|
|
617
|
+
else:
|
|
618
|
+
# 色が1色のみの場合は、その色を使用してメッシュ全体を出力
|
|
619
|
+
uc = unique_colors[0]
|
|
620
|
+
color = [int(uc[0]), int(uc[1]), int(uc[2])]
|
|
621
|
+
# ここでは continue せず、下のデフォルト追加処理に任せる(colorを更新したため)
|
|
565
622
|
except Exception:
|
|
566
623
|
# 分割処理に失敗した場合はフォールバックで単体メッシュを追加
|
|
567
624
|
pass
|
|
568
|
-
|
|
625
|
+
|
|
569
626
|
meshes_with_colors.append({
|
|
570
627
|
'mesh': mesh_copy,
|
|
571
628
|
'color': color,
|
|
@@ -577,9 +634,9 @@ class MainWindowExport(object):
|
|
|
577
634
|
actor_count += 1
|
|
578
635
|
|
|
579
636
|
except Exception as e:
|
|
580
|
-
print(f"Error processing actor {actor_name}: {e}")
|
|
581
637
|
continue
|
|
582
638
|
|
|
639
|
+
|
|
583
640
|
return meshes_with_colors
|
|
584
641
|
|
|
585
642
|
except Exception as e:
|
|
@@ -1563,7 +1563,6 @@ class MainWindowMainInit(object):
|
|
|
1563
1563
|
'wireframe_bond_radius': 0.01,
|
|
1564
1564
|
'wireframe_resolution': 6,
|
|
1565
1565
|
# Stick model parameters
|
|
1566
|
-
'stick_atom_radius': 0.15,
|
|
1567
1566
|
'stick_bond_radius': 0.15,
|
|
1568
1567
|
'stick_resolution': 16,
|
|
1569
1568
|
# Multiple bond offset parameters (per-model)
|
|
@@ -1573,12 +1572,13 @@ class MainWindowMainInit(object):
|
|
|
1573
1572
|
'ball_stick_triple_bond_radius_factor': 0.75,
|
|
1574
1573
|
'wireframe_double_bond_offset_factor': 3.0,
|
|
1575
1574
|
'wireframe_triple_bond_offset_factor': 3.0,
|
|
1576
|
-
'wireframe_double_bond_radius_factor':
|
|
1575
|
+
'wireframe_double_bond_radius_factor': 0.8,
|
|
1577
1576
|
'wireframe_triple_bond_radius_factor': 0.75,
|
|
1578
1577
|
'stick_double_bond_offset_factor': 1.5,
|
|
1579
1578
|
'stick_triple_bond_offset_factor': 1.0,
|
|
1580
1579
|
'stick_double_bond_radius_factor': 0.60,
|
|
1581
1580
|
'stick_triple_bond_radius_factor': 0.40,
|
|
1581
|
+
'aromatic_torus_thickness_factor': 0.6,
|
|
1582
1582
|
# Ensure conversion/optimization defaults are present
|
|
1583
1583
|
# If True, attempts to be permissive when RDKit raises chemical/sanitization errors
|
|
1584
1584
|
# during file import (useful for viewing malformed XYZ/MOL files).
|
|
@@ -1629,7 +1629,7 @@ class MainWindowMainInit(object):
|
|
|
1629
1629
|
('ball_stick_triple_bond_radius_factor', 'triple_bond_radius_factor', 0.75),
|
|
1630
1630
|
('wireframe_double_bond_offset_factor', 'double_bond_offset_factor', 3.0),
|
|
1631
1631
|
('wireframe_triple_bond_offset_factor', 'triple_bond_offset_factor', 3.0),
|
|
1632
|
-
('wireframe_double_bond_radius_factor', 'double_bond_radius_factor',
|
|
1632
|
+
('wireframe_double_bond_radius_factor', 'double_bond_radius_factor', 0.8),
|
|
1633
1633
|
('wireframe_triple_bond_radius_factor', 'triple_bond_radius_factor', 0.75),
|
|
1634
1634
|
('stick_double_bond_offset_factor', 'double_bond_offset_factor', 1.5),
|
|
1635
1635
|
('stick_triple_bond_offset_factor', 'triple_bond_offset_factor', 1.0),
|
|
@@ -22,6 +22,7 @@ import io
|
|
|
22
22
|
import os
|
|
23
23
|
import contextlib
|
|
24
24
|
import traceback
|
|
25
|
+
import logging
|
|
25
26
|
|
|
26
27
|
|
|
27
28
|
# RDKit imports (explicit to satisfy flake8 and used features)
|
|
@@ -59,7 +60,7 @@ if OBABEL_AVAILABLE:
|
|
|
59
60
|
# If import fails here, disable OBABEL locally; avoid raising
|
|
60
61
|
pybel = None
|
|
61
62
|
OBABEL_AVAILABLE = False
|
|
62
|
-
|
|
63
|
+
logging.warning("Warning: openbabel.pybel not available. Open Babel fallback and OBabel-based options will be disabled.")
|
|
63
64
|
else:
|
|
64
65
|
pybel = None
|
|
65
66
|
|
|
@@ -901,12 +902,12 @@ class MainWindowMolecularParsers(object):
|
|
|
901
902
|
try:
|
|
902
903
|
mol.AddBond(i, j, Chem.BondType.SINGLE)
|
|
903
904
|
bonds_added.append((i, j, distance))
|
|
904
|
-
except:
|
|
905
|
+
except Exception:
|
|
905
906
|
# 既に結合が存在する場合はスキップ
|
|
906
907
|
pass
|
|
907
908
|
|
|
908
909
|
# デバッグ情報(オプション)
|
|
909
|
-
#
|
|
910
|
+
# Added bonds based on distance analysis
|
|
910
911
|
|
|
911
912
|
return len(bonds_added)
|
|
912
913
|
|
|
@@ -430,9 +430,9 @@ class MainWindowProjectIo(object):
|
|
|
430
430
|
# 拡張子不明の場合はJSONとして試行
|
|
431
431
|
try:
|
|
432
432
|
self.load_json_data(file_path)
|
|
433
|
-
except:
|
|
433
|
+
except Exception:
|
|
434
434
|
try:
|
|
435
435
|
self.load_raw_data(file_path)
|
|
436
|
-
except:
|
|
436
|
+
except Exception:
|
|
437
437
|
self.statusBar().showMessage("Error: Unable to determine file format.")
|
|
438
438
|
|
{moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/main_window_view_3d.py
RENAMED
|
@@ -19,6 +19,7 @@ MainWindow (main_window.py) から分離されたモジュール
|
|
|
19
19
|
|
|
20
20
|
import numpy as np
|
|
21
21
|
import vtk
|
|
22
|
+
import logging
|
|
22
23
|
|
|
23
24
|
|
|
24
25
|
# RDKit imports (explicit to satisfy flake8 and used features)
|
|
@@ -58,7 +59,7 @@ if OBABEL_AVAILABLE:
|
|
|
58
59
|
# If import fails here, disable OBABEL locally; avoid raising
|
|
59
60
|
pybel = None
|
|
60
61
|
OBABEL_AVAILABLE = False
|
|
61
|
-
|
|
62
|
+
logging.warning("Warning: openbabel.pybel not available. Open Babel fallback and OBabel-based options will be disabled.")
|
|
62
63
|
else:
|
|
63
64
|
pybel = None
|
|
64
65
|
|
|
@@ -201,7 +202,7 @@ class MainWindowView3d(object):
|
|
|
201
202
|
resolution = self.settings.get('wireframe_resolution', 6)
|
|
202
203
|
rad = np.array([0.01 for s in sym]) # 極小値(使用されない)
|
|
203
204
|
elif self.current_3d_style == 'stick':
|
|
204
|
-
atom_radius = self.settings.get('
|
|
205
|
+
atom_radius = self.settings.get('stick_bond_radius', 0.15) # Use bond radius for atoms
|
|
205
206
|
resolution = self.settings.get('stick_resolution', 16)
|
|
206
207
|
rad = np.array([atom_radius for s in sym])
|
|
207
208
|
else: # ball_and_stick
|
|
@@ -278,7 +279,7 @@ class MainWindowView3d(object):
|
|
|
278
279
|
|
|
279
280
|
# 結合描画と同じ計算
|
|
280
281
|
sphere_radius = cyl_radius * radius_factor
|
|
281
|
-
except:
|
|
282
|
+
except Exception:
|
|
282
283
|
sphere_radius = 0.09 # デフォルト値
|
|
283
284
|
offset_distance = 0.15 # デフォルト値
|
|
284
285
|
|
|
@@ -437,7 +438,7 @@ class MainWindowView3d(object):
|
|
|
437
438
|
double_radius_factor = self.settings.get('ball_stick_double_bond_radius_factor', 0.8)
|
|
438
439
|
triple_radius_factor = self.settings.get('ball_stick_triple_bond_radius_factor', 0.75)
|
|
439
440
|
elif self.current_3d_style == 'wireframe':
|
|
440
|
-
double_radius_factor = self.settings.get('wireframe_double_bond_radius_factor',
|
|
441
|
+
double_radius_factor = self.settings.get('wireframe_double_bond_radius_factor', 0.8)
|
|
441
442
|
triple_radius_factor = self.settings.get('wireframe_triple_bond_radius_factor', 0.75)
|
|
442
443
|
elif self.current_3d_style == 'stick':
|
|
443
444
|
double_radius_factor = self.settings.get('stick_double_bond_radius_factor', 0.60)
|
|
@@ -660,7 +661,7 @@ class MainWindowView3d(object):
|
|
|
660
661
|
self.plotter.add_mesh(circle_line, color=torus_color, **mesh_props)
|
|
661
662
|
|
|
662
663
|
except Exception as e:
|
|
663
|
-
|
|
664
|
+
logging.error(f"Error rendering aromatic circles: {e}")
|
|
664
665
|
|
|
665
666
|
if getattr(self, 'show_chiral_labels', False):
|
|
666
667
|
try:
|
|
@@ -820,7 +821,7 @@ class MainWindowView3d(object):
|
|
|
820
821
|
try:
|
|
821
822
|
# 既存のE/Zラベルを削除
|
|
822
823
|
self.plotter.remove_actor('ez_labels')
|
|
823
|
-
except:
|
|
824
|
+
except Exception:
|
|
824
825
|
pass
|
|
825
826
|
|
|
826
827
|
pts, labels = [], []
|
|
@@ -837,7 +838,7 @@ class MainWindowView3d(object):
|
|
|
837
838
|
# 3D座標からステレオ化学を再計算 (molに対して行う)
|
|
838
839
|
# これにより、2Dでの描画状態に関わらず、現在の3D座標に基づいたE/Z判定が行われる
|
|
839
840
|
Chem.AssignStereochemistry(mol, cleanIt=True, force=True, flagPossibleStereoCenters=True)
|
|
840
|
-
except:
|
|
841
|
+
except Exception:
|
|
841
842
|
pass
|
|
842
843
|
|
|
843
844
|
for bond in mol.GetBonds():
|
|
@@ -1171,7 +1172,7 @@ class MainWindowView3d(object):
|
|
|
1171
1172
|
for nm in self.atom_label_legend_names:
|
|
1172
1173
|
try:
|
|
1173
1174
|
self.plotter.remove_actor(nm)
|
|
1174
|
-
except:
|
|
1175
|
+
except Exception:
|
|
1175
1176
|
pass
|
|
1176
1177
|
self.atom_label_legend_names = []
|
|
1177
1178
|
|
|
@@ -1237,12 +1238,12 @@ class MainWindowView3d(object):
|
|
|
1237
1238
|
for a in list(self.current_atom_info_labels):
|
|
1238
1239
|
try:
|
|
1239
1240
|
self.plotter.remove_actor(a)
|
|
1240
|
-
except:
|
|
1241
|
+
except Exception:
|
|
1241
1242
|
pass
|
|
1242
1243
|
else:
|
|
1243
1244
|
try:
|
|
1244
1245
|
self.plotter.remove_actor(self.current_atom_info_labels)
|
|
1245
|
-
except:
|
|
1246
|
+
except Exception:
|
|
1246
1247
|
pass
|
|
1247
1248
|
except Exception:
|
|
1248
1249
|
pass
|
|
@@ -1255,7 +1256,7 @@ class MainWindowView3d(object):
|
|
|
1255
1256
|
for nm in list(self.atom_label_legend_names):
|
|
1256
1257
|
try:
|
|
1257
1258
|
self.plotter.remove_actor(nm)
|
|
1258
|
-
except:
|
|
1259
|
+
except Exception:
|
|
1259
1260
|
pass
|
|
1260
1261
|
except Exception:
|
|
1261
1262
|
pass
|
|
@@ -1401,7 +1402,7 @@ class MainWindowView3d(object):
|
|
|
1401
1402
|
if renderer and hasattr(renderer, 'SetNumberOfLayers'):
|
|
1402
1403
|
try:
|
|
1403
1404
|
renderer.SetNumberOfLayers(2) # レイヤー0:3Dオブジェクト、レイヤー1:2Dオーバーレイ
|
|
1404
|
-
except:
|
|
1405
|
+
except Exception:
|
|
1405
1406
|
pass # PyVistaのバージョンによってはサポートされていない場合がある
|
|
1406
1407
|
|
|
1407
1408
|
# --- 3D軸ウィジェットの設定 ---
|
|
@@ -317,7 +317,7 @@ class MainWindowViewLoaders(object):
|
|
|
317
317
|
# Keep mol as-is (may lack conformer); downstream code checks for conformers
|
|
318
318
|
else:
|
|
319
319
|
raise
|
|
320
|
-
except:
|
|
320
|
+
except Exception:
|
|
321
321
|
self.statusBar().showMessage("Failed to generate 3D coordinates")
|
|
322
322
|
return
|
|
323
323
|
|
{moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/molecule_scene.py
RENAMED
|
@@ -11,6 +11,7 @@ DOI: 10.5281/zenodo.17268532
|
|
|
11
11
|
"""
|
|
12
12
|
|
|
13
13
|
import traceback
|
|
14
|
+
import logging
|
|
14
15
|
|
|
15
16
|
from PyQt6.QtWidgets import (
|
|
16
17
|
QApplication, QGraphicsScene, QGraphicsItem,
|
|
@@ -203,9 +204,7 @@ class MoleculeScene(QGraphicsScene):
|
|
|
203
204
|
self.window.push_undo_state()
|
|
204
205
|
data_changed = False # ここでundo済みなので以降で積まない
|
|
205
206
|
except Exception as e:
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
traceback.print_exc()
|
|
207
|
+
logging.error(f"Error clearing E/Z label: {e}", exc_info=True)
|
|
209
208
|
if hasattr(self.window, 'statusBar'):
|
|
210
209
|
self.window.statusBar().showMessage(f"Error clearing E/Z label: {e}", 5000)
|
|
211
210
|
# AtomItemは何もしない
|
|
@@ -387,9 +386,7 @@ class MoleculeScene(QGraphicsScene):
|
|
|
387
386
|
self.update_bond_stereo(b, new_stereo)
|
|
388
387
|
self.window.push_undo_state() # ここでUndo stackに積む
|
|
389
388
|
except Exception as e:
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
traceback.print_exc()
|
|
389
|
+
logging.error(f"Error in E/Z stereo toggle: {e}", exc_info=True)
|
|
393
390
|
if hasattr(self.window, 'statusBar'):
|
|
394
391
|
self.window.statusBar().showMessage(f"Error changing E/Z stereochemistry: {e}", 5000)
|
|
395
392
|
return # この後の処理は行わない
|
|
@@ -610,7 +607,7 @@ class MoleculeScene(QGraphicsScene):
|
|
|
610
607
|
def create_bond(self, start_atom, end_atom, bond_order=None, bond_stereo=None):
|
|
611
608
|
try:
|
|
612
609
|
if start_atom is None or end_atom is None:
|
|
613
|
-
|
|
610
|
+
logging.error("Error: Cannot create bond with None atoms")
|
|
614
611
|
return
|
|
615
612
|
|
|
616
613
|
exist_b = self.find_bond_between(start_atom, end_atom)
|
|
@@ -637,9 +634,7 @@ class MoleculeScene(QGraphicsScene):
|
|
|
637
634
|
end_atom.update_style()
|
|
638
635
|
|
|
639
636
|
except Exception as e:
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
traceback.print_exc()
|
|
637
|
+
logging.error(f"Error creating bond: {e}", exc_info=True)
|
|
643
638
|
|
|
644
639
|
def add_molecule_fragment(self, points, bonds_info, existing_items=None, symbol='C'):
|
|
645
640
|
"""
|
|
@@ -1668,9 +1663,9 @@ class MoleculeScene(QGraphicsScene):
|
|
|
1668
1663
|
elif key == Qt.Key.Key_1 and (bond.order != 1 or bond.stereo != 0):
|
|
1669
1664
|
bond.order = 1; bond.stereo = 0
|
|
1670
1665
|
elif key == Qt.Key.Key_2 and (bond.order != 2 or bond.stereo != 0):
|
|
1671
|
-
bond.order = 2; bond.stereo = 0
|
|
1666
|
+
bond.order = 2; bond.stereo = 0
|
|
1672
1667
|
elif key == Qt.Key.Key_3 and bond.order != 3:
|
|
1673
|
-
bond.order = 3; bond.stereo = 0
|
|
1668
|
+
bond.order = 3; bond.stereo = 0
|
|
1674
1669
|
|
|
1675
1670
|
# 4. 実際に変更があった場合のみデータモデルを更新
|
|
1676
1671
|
if old_order != bond.order or old_stereo != bond.stereo:
|
{moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/settings_dialog.py
RENAMED
|
@@ -53,7 +53,6 @@ class SettingsDialog(QDialog):
|
|
|
53
53
|
'wireframe_bond_radius': 0.01,
|
|
54
54
|
'wireframe_resolution': 6,
|
|
55
55
|
# Stick model parameters
|
|
56
|
-
'stick_atom_radius': 0.15,
|
|
57
56
|
'stick_bond_radius': 0.15,
|
|
58
57
|
'stick_resolution': 16,
|
|
59
58
|
# Multiple bond offset parameters (per-model)
|
|
@@ -278,8 +277,8 @@ class SettingsDialog(QDialog):
|
|
|
278
277
|
# Aromatic torus thickness factor
|
|
279
278
|
self.aromatic_torus_thickness_slider = QSlider(Qt.Orientation.Horizontal)
|
|
280
279
|
self.aromatic_torus_thickness_slider.setRange(10, 300) # 0.1x to 3.0x
|
|
281
|
-
self.aromatic_torus_thickness_slider.setValue(
|
|
282
|
-
self.aromatic_torus_thickness_label = QLabel("
|
|
280
|
+
self.aromatic_torus_thickness_slider.setValue(60) # Default 0.6x
|
|
281
|
+
self.aromatic_torus_thickness_label = QLabel("0.6")
|
|
283
282
|
self.aromatic_torus_thickness_slider.valueChanged.connect(
|
|
284
283
|
lambda v: self.aromatic_torus_thickness_label.setText(f"{v/100:.1f}")
|
|
285
284
|
)
|
|
@@ -564,17 +563,7 @@ class SettingsDialog(QDialog):
|
|
|
564
563
|
info_label.setStyleSheet("color: #666; font-style: italic; margin-top: 10px;")
|
|
565
564
|
form_layout.addRow(info_label)
|
|
566
565
|
|
|
567
|
-
#
|
|
568
|
-
self.stick_atom_radius_slider = QSlider(Qt.Orientation.Horizontal)
|
|
569
|
-
self.stick_atom_radius_slider.setRange(5, 50) # 0.05 ~ 0.5
|
|
570
|
-
self.stick_atom_radius_label = QLabel("0.15")
|
|
571
|
-
self.stick_atom_radius_slider.valueChanged.connect(lambda v: self.stick_atom_radius_label.setText(f"{v/100:.2f}"))
|
|
572
|
-
atom_radius_layout = QHBoxLayout()
|
|
573
|
-
atom_radius_layout.addWidget(self.stick_atom_radius_slider)
|
|
574
|
-
atom_radius_layout.addWidget(self.stick_atom_radius_label)
|
|
575
|
-
form_layout.addRow("Atom Radius:", atom_radius_layout)
|
|
576
|
-
|
|
577
|
-
# ボンド半径
|
|
566
|
+
# ボンド半径(原子半径も同じ値を使用)
|
|
578
567
|
self.stick_bond_radius_slider = QSlider(Qt.Orientation.Horizontal)
|
|
579
568
|
self.stick_bond_radius_slider.setRange(5, 50) # 0.05 ~ 0.5
|
|
580
569
|
self.stick_bond_radius_label = QLabel("0.15")
|
|
@@ -673,7 +662,7 @@ class SettingsDialog(QDialog):
|
|
|
673
662
|
'display_kekule_3d': self.default_settings.get('display_kekule_3d', False),
|
|
674
663
|
'always_ask_charge': self.default_settings.get('always_ask_charge', False),
|
|
675
664
|
'display_aromatic_circles_3d': self.default_settings.get('display_aromatic_circles_3d', False),
|
|
676
|
-
'aromatic_torus_thickness_factor': self.default_settings.get('aromatic_torus_thickness_factor',
|
|
665
|
+
'aromatic_torus_thickness_factor': self.default_settings.get('aromatic_torus_thickness_factor', 0.6),
|
|
677
666
|
},
|
|
678
667
|
"Ball & Stick": {
|
|
679
668
|
'ball_stick_atom_scale': self.default_settings['ball_stick_atom_scale'],
|
|
@@ -700,7 +689,6 @@ class SettingsDialog(QDialog):
|
|
|
700
689
|
'wireframe_triple_bond_radius_factor': self.default_settings.get('wireframe_triple_bond_radius_factor', 0.75)
|
|
701
690
|
},
|
|
702
691
|
"Stick": {
|
|
703
|
-
'stick_atom_radius': self.default_settings['stick_atom_radius'],
|
|
704
692
|
'stick_bond_radius': self.default_settings['stick_bond_radius'],
|
|
705
693
|
'stick_resolution': self.default_settings['stick_resolution'],
|
|
706
694
|
'stick_double_bond_offset_factor': self.default_settings.get('stick_double_bond_offset_factor', 1.5),
|
|
@@ -844,7 +832,6 @@ class SettingsDialog(QDialog):
|
|
|
844
832
|
'wireframe_bond_radius': self.wf_bond_radius_slider.value() / 100.0,
|
|
845
833
|
'wireframe_resolution': self.wf_resolution_slider.value(),
|
|
846
834
|
# Stick settings
|
|
847
|
-
'stick_atom_radius': self.stick_atom_radius_slider.value() / 100.0,
|
|
848
835
|
'stick_bond_radius': self.stick_bond_radius_slider.value() / 100.0,
|
|
849
836
|
'stick_resolution': self.stick_resolution_slider.value(),
|
|
850
837
|
# Multi-bond settings (per-model)
|
|
@@ -944,10 +931,6 @@ class SettingsDialog(QDialog):
|
|
|
944
931
|
self.wf_resolution_label.setText(str(settings_dict.get('wireframe_resolution', self.default_settings['wireframe_resolution'])))
|
|
945
932
|
|
|
946
933
|
# Stick設定
|
|
947
|
-
stick_atom_radius = int(settings_dict.get('stick_atom_radius', self.default_settings['stick_atom_radius']) * 100)
|
|
948
|
-
self.stick_atom_radius_slider.setValue(stick_atom_radius)
|
|
949
|
-
self.stick_atom_radius_label.setText(f"{stick_atom_radius/100:.2f}")
|
|
950
|
-
|
|
951
934
|
stick_bond_radius = int(settings_dict.get('stick_bond_radius', self.default_settings['stick_bond_radius']) * 100)
|
|
952
935
|
self.stick_bond_radius_slider.setValue(stick_bond_radius)
|
|
953
936
|
self.stick_bond_radius_label.setText(f"{stick_bond_radius/100:.2f}")
|
|
@@ -1019,7 +1002,7 @@ class SettingsDialog(QDialog):
|
|
|
1019
1002
|
self.always_ask_charge_checkbox.setChecked(settings_dict.get('always_ask_charge', self.default_settings.get('always_ask_charge', False)))
|
|
1020
1003
|
# Aromatic ring circle display and torus thickness factor
|
|
1021
1004
|
self.aromatic_circle_checkbox.setChecked(settings_dict.get('display_aromatic_circles_3d', self.default_settings.get('display_aromatic_circles_3d', False)))
|
|
1022
|
-
thickness_factor = float(settings_dict.get('aromatic_torus_thickness_factor', self.default_settings.get('aromatic_torus_thickness_factor',
|
|
1005
|
+
thickness_factor = float(settings_dict.get('aromatic_torus_thickness_factor', self.default_settings.get('aromatic_torus_thickness_factor', 0.6)))
|
|
1023
1006
|
try:
|
|
1024
1007
|
self.aromatic_torus_thickness_slider.setValue(int(thickness_factor * 100))
|
|
1025
1008
|
self.aromatic_torus_thickness_label.setText(f"{thickness_factor:.1f}")
|
|
@@ -1060,7 +1043,6 @@ class SettingsDialog(QDialog):
|
|
|
1060
1043
|
'wireframe_bond_radius': self.wf_bond_radius_slider.value() / 100.0,
|
|
1061
1044
|
'wireframe_resolution': self.wf_resolution_slider.value(),
|
|
1062
1045
|
# Stick settings
|
|
1063
|
-
'stick_atom_radius': self.stick_atom_radius_slider.value() / 100.0,
|
|
1064
1046
|
'stick_bond_radius': self.stick_bond_radius_slider.value() / 100.0,
|
|
1065
1047
|
'stick_resolution': self.stick_resolution_slider.value(),
|
|
1066
1048
|
# Multiple bond offset settings (per-model)
|
|
@@ -23,6 +23,7 @@ except Exception:
|
|
|
23
23
|
from modules.constants import VERSION, CPK_COLORS
|
|
24
24
|
import os
|
|
25
25
|
import json
|
|
26
|
+
import logging
|
|
26
27
|
|
|
27
28
|
class UserTemplateDialog(QDialog):
|
|
28
29
|
"""ユーザーテンプレート管理ダイアログ"""
|
|
@@ -106,7 +107,7 @@ class UserTemplateDialog(QDialog):
|
|
|
106
107
|
elif hasattr(child, 'refit_view'):
|
|
107
108
|
child.refit_view()
|
|
108
109
|
except Exception as e:
|
|
109
|
-
|
|
110
|
+
logging.warning(f"Warning: Failed to refit template previews: {e}")
|
|
110
111
|
|
|
111
112
|
def showEvent(self, event):
|
|
112
113
|
"""ダイアログ表示時にプレビューを適切にフィット"""
|
|
@@ -136,7 +137,7 @@ class UserTemplateDialog(QDialog):
|
|
|
136
137
|
template_data['filepath'] = filepath
|
|
137
138
|
self.user_templates.append(template_data)
|
|
138
139
|
except Exception as e:
|
|
139
|
-
|
|
140
|
+
logging.error(f"Error loading user templates: {e}")
|
|
140
141
|
|
|
141
142
|
self.update_template_grid()
|
|
142
143
|
|
|
@@ -146,7 +147,7 @@ class UserTemplateDialog(QDialog):
|
|
|
146
147
|
with open(filepath, 'r', encoding='utf-8') as f:
|
|
147
148
|
return json.load(f)
|
|
148
149
|
except Exception as e:
|
|
149
|
-
|
|
150
|
+
logging.error(f"Error loading template file {filepath}: {e}")
|
|
150
151
|
return None
|
|
151
152
|
|
|
152
153
|
def save_template_file(self, filepath, template_data):
|
|
@@ -156,7 +157,7 @@ class UserTemplateDialog(QDialog):
|
|
|
156
157
|
json.dump(template_data, f, indent=2, ensure_ascii=False)
|
|
157
158
|
return True
|
|
158
159
|
except Exception as e:
|
|
159
|
-
|
|
160
|
+
logging.error(f"Error saving template file {filepath}: {e}")
|
|
160
161
|
return False
|
|
161
162
|
|
|
162
163
|
def update_template_grid(self):
|
|
@@ -253,7 +254,7 @@ class UserTemplateDialog(QDialog):
|
|
|
253
254
|
if view and not rect.isEmpty():
|
|
254
255
|
view.fitInView(rect, Qt.AspectRatioMode.KeepAspectRatio)
|
|
255
256
|
except Exception as e:
|
|
256
|
-
|
|
257
|
+
logging.warning(f"Warning: Failed to fit preview view: {e}")
|
|
257
258
|
|
|
258
259
|
def draw_template_preview(self, scene, template_data, view_size=None):
|
|
259
260
|
"""テンプレートプレビューを描画 - fitInView縮小率に基づく動的スケーリング"""
|
|
@@ -303,7 +304,7 @@ class UserTemplateDialog(QDialog):
|
|
|
303
304
|
scale_factor = 4.0
|
|
304
305
|
|
|
305
306
|
# Debug info (can be removed in production)
|
|
306
|
-
#
|
|
307
|
+
# logging.debug(f"Mol size: {mol_size:.1f}, Fit scale: {fit_scale:.3f}, Scale factor: {scale_factor:.2f}")
|
|
307
308
|
else:
|
|
308
309
|
scale_factor = 1.0
|
|
309
310
|
|
|
@@ -481,7 +482,7 @@ class UserTemplateDialog(QDialog):
|
|
|
481
482
|
except Exception:
|
|
482
483
|
pass
|
|
483
484
|
except Exception as e:
|
|
484
|
-
|
|
485
|
+
logging.warning(f"Warning: Failed to switch main window to template mode: {e}")
|
|
485
486
|
|
|
486
487
|
def use_template(self, template_data):
|
|
487
488
|
"""テンプレートを使用(エディタに適用)"""
|
|
@@ -518,7 +519,7 @@ class UserTemplateDialog(QDialog):
|
|
|
518
519
|
# Mark selected and keep dialog open
|
|
519
520
|
self.selected_template = template_data
|
|
520
521
|
except Exception as e:
|
|
521
|
-
|
|
522
|
+
logging.warning(f"Warning: Failed to switch main window to template mode: {e}")
|
|
522
523
|
|
|
523
524
|
# Don't close dialog - keep it open for easy template switching
|
|
524
525
|
# self.accept()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/MoleditPy_linux.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/MoleditPy_linux.egg-info/entry_points.txt
RENAMED
|
File without changes
|
|
File without changes
|
{moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/MoleditPy_linux.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/about_dialog.py
RENAMED
|
File without changes
|
{moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/analysis_window.py
RENAMED
|
File without changes
|
{moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/assets/icon.icns
RENAMED
|
File without changes
|
{moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/assets/icon.ico
RENAMED
|
File without changes
|
{moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/assets/icon.png
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/calculation_worker.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/main_window.py
RENAMED
|
File without changes
|
{moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/main_window_compute.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/mirror_dialog.py
RENAMED
|
File without changes
|
{moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/molecular_data.py
RENAMED
|
File without changes
|
{moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/move_group_dialog.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/translation_dialog.py
RENAMED
|
File without changes
|
{moleditpy_linux-1.18.0 → moleditpy_linux-1.18.1}/src/moleditpy_linux/modules/zoomable_view.py
RENAMED
|
File without changes
|