finalcif 152__tar.gz → 154__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.
- {finalcif-152 → finalcif-154}/.gitignore +2 -0
- finalcif-154/.python-version +1 -0
- {finalcif-152 → finalcif-154}/Finalcif_installer_win.spec +1 -0
- {finalcif-152 → finalcif-154}/PKG-INFO +6 -5
- finalcif-154/finalcif/__init__.py +2 -0
- {finalcif-152 → finalcif-154}/finalcif/appwindow.py +50 -22
- {finalcif-152 → finalcif-154}/finalcif/cif/atoms.py +3 -3
- {finalcif-152 → finalcif-154}/finalcif/cif/checkcif/checkcif.py +1 -1
- {finalcif-152 → finalcif-154}/finalcif/cif/cif_file_io.py +53 -36
- {finalcif-152 → finalcif-154}/finalcif/cif/cod/deposit.py +5 -5
- {finalcif-152 → finalcif-154}/finalcif/ciforder/order.py +1 -1
- {finalcif-152 → finalcif-154}/finalcif/ciforder/order_ui.py +3 -3
- {finalcif-152 → finalcif-154}/finalcif/datafiles/shelx_lst.py +21 -12
- {finalcif-152 → finalcif-154}/finalcif/displaymol/molecule2D.py +3 -3
- {finalcif-152 → finalcif-154}/finalcif/displaymol/vtk_molecule.py +2 -2
- {finalcif-152 → finalcif-154}/finalcif/equip_property/author_loop_templates.py +20 -26
- {finalcif-152 → finalcif-154}/finalcif/equip_property/equipment.py +2 -2
- {finalcif-152 → finalcif-154}/finalcif/equip_property/properties.py +2 -2
- {finalcif-152 → finalcif-154}/finalcif/finalcif_start.py +5 -3
- {finalcif-152 → finalcif-154}/finalcif/gui/block_combobox.py +1 -1
- {finalcif-152 → finalcif-154}/finalcif/gui/combobox.py +3 -3
- {finalcif-152 → finalcif-154}/finalcif/gui/custom_classes.py +4 -4
- {finalcif-152 → finalcif-154}/finalcif/gui/dialogs.py +19 -15
- {finalcif-152 → finalcif-154}/finalcif/gui/edit_button.py +1 -1
- {finalcif-152 → finalcif-154}/finalcif/gui/equipmenttable.py +2 -2
- {finalcif-152 → finalcif-154}/finalcif/gui/file_editor.py +5 -5
- {finalcif-152 → finalcif-154}/finalcif/gui/finalcif_gui_ui.py +3 -3
- {finalcif-152 → finalcif-154}/finalcif/gui/import_selector_ui.py +3 -3
- {finalcif-152 → finalcif-154}/finalcif/gui/loop_creator.py +2 -2
- {finalcif-152 → finalcif-154}/finalcif/gui/loop_creator_ui.py +3 -3
- {finalcif-152 → finalcif-154}/finalcif/gui/loops.py +4 -4
- {finalcif-152 → finalcif-154}/finalcif/gui/mainstackwidget.py +1 -1
- {finalcif-152 → finalcif-154}/finalcif/gui/new_key_dialog.py +3 -3
- {finalcif-152 → finalcif-154}/finalcif/gui/new_key_dialog_ui.py +3 -3
- {finalcif-152 → finalcif-154}/finalcif/gui/plaintextedit.py +6 -6
- {finalcif-152 → finalcif-154}/finalcif/gui/playground.py +4 -4
- {finalcif-152 → finalcif-154}/finalcif/gui/propertytable.py +1 -1
- {finalcif-152 → finalcif-154}/finalcif/gui/spell_check_edit.py +4 -4
- {finalcif-152 → finalcif-154}/finalcif/gui/text_templates_ui.py +3 -3
- {finalcif-152 → finalcif-154}/finalcif/gui/text_value_editor.py +4 -4
- {finalcif-152 → finalcif-154}/finalcif/gui/vrf_classes.py +4 -4
- {finalcif-152 → finalcif-154}/finalcif/report/gui/mainwindow.py +3 -3
- {finalcif-152 → finalcif-154}/finalcif/report/templated_report.py +63 -40
- {finalcif-152 → finalcif-154}/finalcif/template/report.tmpl +7 -1
- {finalcif-152 → finalcif-154}/finalcif/template/templates.py +7 -6
- {finalcif-152 → finalcif-154}/finalcif/tools/download.py +3 -3
- {finalcif-152 → finalcif-154}/finalcif/tools/platon.py +12 -9
- {finalcif-152 → finalcif-154}/finalcif/tools/settings.py +4 -3
- {finalcif-152 → finalcif-154}/finalcif/tools/sumformula.py +0 -2
- finalcif-154/platon/README.txt +29 -0
- finalcif-154/platon/compile_platon.bat +4 -0
- finalcif-154/platon/platon_special.exe +0 -0
- finalcif-154/platon/platon_special.f +167105 -0
- {finalcif-152 → finalcif-154}/pyproject.toml +6 -6
- {finalcif-152 → finalcif-154}/requirements.txt +2 -2
- finalcif-154/uv.lock +1273 -0
- finalcif-152/finalcif/__init__.py +0 -2
- finalcif-152/uv.lock +0 -1130
- {finalcif-152 → finalcif-154}/.gitattributes +0 -0
- {finalcif-152 → finalcif-154}/.ruff.toml +0 -0
- {finalcif-152 → finalcif-154}/.run/Make Documentation MAC.run.xml +0 -0
- {finalcif-152 → finalcif-154}/.run/compile_ui_files.run.xml +0 -0
- {finalcif-152 → finalcif-154}/.run/make documentation Windows.run.xml +0 -0
- {finalcif-152 → finalcif-154}/CODE_OF_CONDUCT.md +0 -0
- {finalcif-152 → finalcif-154}/CONTRIBUTING.md +0 -0
- {finalcif-152 → finalcif-154}/Finalcif_linux_onefile.spec +0 -0
- {finalcif-152 → finalcif-154}/Finalcif_mac.spec +0 -0
- {finalcif-152 → finalcif-154}/Hydrogen_solution_type.cif +0 -0
- {finalcif-152 → finalcif-154}/LICENSE +0 -0
- {finalcif-152 → finalcif-154}/README.md +0 -0
- {finalcif-152 → finalcif-154}/finalcif/app_path.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/cif/__init__.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/cif/all_cif_dicts.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/cif/checkcif/__init__.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/cif/cif_dict_foo.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/cif/cif_order.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/cif/cod/__init__.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/cif/cod/deposit_check.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/cif/cod/deposition_list.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/cif/cod/doi.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/cif/cod/upload.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/cif/cod/website_parser.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/cif/core_dict.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/cif/hkl.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/cif/modulation_dict.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/cif/powder_dict.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/cif/reference.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/cif/restraints_dict.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/cif/text.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/cif/twin_dict.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/ciforder/__init__.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/ciforder/order_ui.ui +0 -0
- {finalcif-152 → finalcif-154}/finalcif/datafiles/__init__.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/datafiles/bruker_data.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/datafiles/bruker_frame.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/datafiles/ccdc_mail.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/datafiles/data.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/datafiles/p4p_reader.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/datafiles/sadabs.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/datafiles/saint.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/datafiles/utils.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/displaymol/__init__.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/displaymol/sdm.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/equip_property/__init__.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/equip_property/tools.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/gui/__init__.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/gui/finalcif_gui_ui.ui +0 -0
- {finalcif-152 → finalcif-154}/finalcif/gui/import_selector.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/gui/import_selector_ui.ui +0 -0
- {finalcif-152 → finalcif-154}/finalcif/gui/loop_creator_ui.ui +0 -0
- {finalcif-152 → finalcif-154}/finalcif/gui/mixins.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/gui/new_key_dialog_ui.ui +0 -0
- {finalcif-152 → finalcif-154}/finalcif/gui/text_templates_ui.ui +0 -0
- {finalcif-152 → finalcif-154}/finalcif/gui/validators.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/icon/__init__.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/icon/finalcif.png +0 -0
- {finalcif-152 → finalcif-154}/finalcif/icon/finalcif2.ico +0 -0
- {finalcif-152 → finalcif-154}/finalcif/icon/finalcif2.png +0 -0
- {finalcif-152 → finalcif-154}/finalcif/icon/multitable.ico +0 -0
- {finalcif-152 → finalcif-154}/finalcif/icon/multitable.png +0 -0
- {finalcif-152 → finalcif-154}/finalcif/icon/multitable.xcf +0 -0
- {finalcif-152 → finalcif-154}/finalcif/report/__init__.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/report/archive_report.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/report/gui/__init__.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/report/gui/mainwindow.ui +0 -0
- {finalcif-152 → finalcif-154}/finalcif/report/mtools.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/report/references.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/report/report_text.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/report/symm.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/report/tables.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/template/__init__.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/template/bootstrap/bootstrap.min.css +0 -0
- {finalcif-152 → finalcif-154}/finalcif/template/machines/D8_VENTURE.cif +0 -0
- {finalcif-152 → finalcif-154}/finalcif/template/mathml2omml.xsl +0 -0
- {finalcif-152 → finalcif-154}/finalcif/template/report_default.docx +0 -0
- {finalcif-152 → finalcif-154}/finalcif/template/template1.docx +0 -0
- {finalcif-152 → finalcif-154}/finalcif/template/template_for_multitable.docx +0 -0
- {finalcif-152 → finalcif-154}/finalcif/template/template_text.docx +0 -0
- {finalcif-152 → finalcif-154}/finalcif/template/template_without_text.docx +0 -0
- {finalcif-152 → finalcif-154}/finalcif/template/xsl/convert.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/template/xsl/xmltohtml.xsl +0 -0
- {finalcif-152 → finalcif-154}/finalcif/tools/__init__.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/tools/chemparse.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/tools/dsrmath.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/tools/misc.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/tools/options.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/tools/pupdate.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/tools/shred.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/tools/space_groups.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/tools/spgr_format.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif/tools/statusbar.py +0 -0
- {finalcif-152 → finalcif-154}/finalcif.exe +0 -0
- {finalcif-152 → finalcif-154}/install_requirements +0 -0
- {finalcif-152 → finalcif-154}/install_requirements.bat +0 -0
- {finalcif-152 → finalcif-154}/requirements_devel.txt +0 -0
- {finalcif-152 → finalcif-154}/requirements_doku.txt +0 -0
- {finalcif-152 → finalcif-154}/run_finalcif +0 -0
- {finalcif-152 → finalcif-154}/run_finalcif.bat +0 -0
- {finalcif-152 → finalcif-154}/screenshots/finalcif_checkcif.png +0 -0
- {finalcif-152 → finalcif-154}/screenshots/finalcif_details.png +0 -0
- {finalcif-152 → finalcif-154}/screenshots/finalcif_loops.png +0 -0
- {finalcif-152 → finalcif-154}/screenshots/finalcif_loops2.png +0 -0
- {finalcif-152 → finalcif-154}/screenshots/finalcif_main.png +0 -0
- {finalcif-152 → finalcif-154}/screenshots/finalcif_report.png +0 -0
- {finalcif-152 → finalcif-154}/screenshots/finalcif_responses.png +0 -0
- {finalcif-152 → finalcif-154}/update.exe +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
cpython@3.12
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: finalcif
|
|
3
|
-
Version:
|
|
3
|
+
Version: 154
|
|
4
4
|
Summary: CIF file editor
|
|
5
5
|
Project-URL: Homepage, https://dkratzert.de/finalcif.html
|
|
6
6
|
Project-URL: Bug Tracker, https://github.com/dkratzert/FinalCif/issues
|
|
@@ -14,19 +14,20 @@ Classifier: Topic :: Scientific/Engineering :: Chemistry
|
|
|
14
14
|
Requires-Python: >=3.10
|
|
15
15
|
Requires-Dist: certifi
|
|
16
16
|
Requires-Dist: chardet
|
|
17
|
+
Requires-Dist: charset-normalizer
|
|
17
18
|
Requires-Dist: crossrefapi
|
|
18
19
|
Requires-Dist: docxtpl
|
|
19
20
|
Requires-Dist: gemmi
|
|
20
|
-
Requires-Dist: hatchling
|
|
21
|
+
Requires-Dist: hatchling
|
|
21
22
|
Requires-Dist: html2text
|
|
22
23
|
Requires-Dist: lxml
|
|
23
24
|
Requires-Dist: numpy
|
|
25
|
+
Requires-Dist: packaging
|
|
24
26
|
Requires-Dist: pefile
|
|
25
27
|
Requires-Dist: pybind11
|
|
26
28
|
Requires-Dist: pyenchant
|
|
27
|
-
Requires-Dist:
|
|
28
|
-
Requires-Dist:
|
|
29
|
-
Requires-Dist: pyside6<6.9
|
|
29
|
+
Requires-Dist: pyside6
|
|
30
|
+
Requires-Dist: pyside6-addons
|
|
30
31
|
Requires-Dist: python-docx
|
|
31
32
|
Requires-Dist: qtawesome
|
|
32
33
|
Requires-Dist: qtpy
|
|
@@ -14,12 +14,16 @@ from datetime import datetime
|
|
|
14
14
|
from math import sin, radians
|
|
15
15
|
from pathlib import Path, WindowsPath
|
|
16
16
|
|
|
17
|
-
import gemmi
|
|
17
|
+
import gemmi
|
|
18
|
+
|
|
19
|
+
if hasattr(gemmi, 'set_leak_warnings'):
|
|
20
|
+
gemmi.set_leak_warnings(False)
|
|
21
|
+
|
|
18
22
|
import requests
|
|
19
|
-
from
|
|
20
|
-
from
|
|
21
|
-
from
|
|
22
|
-
|
|
23
|
+
from qtpy import QtCore, QtGui, QtWebEngineWidgets, QtWidgets, compat
|
|
24
|
+
from qtpy.QtCore import Qt, QEvent
|
|
25
|
+
from qtpy.QtWidgets import (QMainWindow, QCheckBox, QListWidgetItem, QApplication,
|
|
26
|
+
QPlainTextEdit, QMessageBox, QScrollBar)
|
|
23
27
|
from gemmi import cif
|
|
24
28
|
|
|
25
29
|
from finalcif import VERSION
|
|
@@ -123,6 +127,25 @@ class AppWindow(QMainWindow):
|
|
|
123
127
|
if file:
|
|
124
128
|
self.load_cif_file(file)
|
|
125
129
|
self.load_recent_cifs_list()
|
|
130
|
+
self.ui.CheckcifPlaintextEdit.insertPlainText(
|
|
131
|
+
"\n"
|
|
132
|
+
" Offline CheckCIF uses PLATON from Anthony L. Spek, Utrecht University, The Netherlands."
|
|
133
|
+
"\n"
|
|
134
|
+
" https://platonsoft.nl\n"
|
|
135
|
+
" \n"
|
|
136
|
+
" Please cite PLATON in your publication if you use it.\n"
|
|
137
|
+
" \n"
|
|
138
|
+
" - PLATON References : \n"
|
|
139
|
+
" Spek, A.L. (2003). J. Appl. Cryst. 36, 7-13.\n"
|
|
140
|
+
" Spek, A.L. (2009). Acta Cryst. D65, 148-155.\n"
|
|
141
|
+
" Spek, A.L. (2015). Acta Cryst. C71, 9-18.\n"
|
|
142
|
+
" Spek, A.L. (2018). Inorg. Chim. Acta, 470, 232-237.\n"
|
|
143
|
+
" Spek, A.L. (2020). Acta Cryst. E76, 1-11.\n"
|
|
144
|
+
" \n"
|
|
145
|
+
" \n"
|
|
146
|
+
" - Recent versions of PLATON may be obtained from: https://platonsoft.nl/xraysoft\n"
|
|
147
|
+
" "
|
|
148
|
+
)
|
|
126
149
|
self.set_checkcif_output_font(self.ui.CheckcifPlaintextEdit)
|
|
127
150
|
# To make file drag&drop working:
|
|
128
151
|
self.setAcceptDrops(True)
|
|
@@ -417,11 +440,12 @@ class AppWindow(QMainWindow):
|
|
|
417
440
|
def export_all_templates(self, filename: Path | None = None):
|
|
418
441
|
import pickle
|
|
419
442
|
if not filename:
|
|
420
|
-
filename, _ =
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
443
|
+
filename, _ = compat.getsavefilename(parent=self,
|
|
444
|
+
basedir=str(Path(self.get_last_workdir()).joinpath(
|
|
445
|
+
f'finalcif_templates_{time.strftime("%Y-%m-%d")}.dat')),
|
|
446
|
+
selectedfilter="Template File (*.dat)",
|
|
447
|
+
filters="Template File (*.dat)",
|
|
448
|
+
caption='Save templates')
|
|
425
449
|
if not filename:
|
|
426
450
|
return
|
|
427
451
|
templates = {'text' : self.export_raw_text_templates(),
|
|
@@ -440,10 +464,11 @@ class AppWindow(QMainWindow):
|
|
|
440
464
|
def import_all_templates(self, filename: Path | None = None):
|
|
441
465
|
import pickle
|
|
442
466
|
if not filename:
|
|
443
|
-
filename, _ =
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
467
|
+
filename, _ = compat.getopenfilename(parent=self,
|
|
468
|
+
basedir=self.get_last_workdir(),
|
|
469
|
+
selectedfilter="Template File (*.dat)",
|
|
470
|
+
filters="Template File (*.dat)",
|
|
471
|
+
caption='Save templates')
|
|
447
472
|
if not filename:
|
|
448
473
|
return
|
|
449
474
|
try:
|
|
@@ -495,7 +520,7 @@ class AppWindow(QMainWindow):
|
|
|
495
520
|
"""
|
|
496
521
|
Imports a text template from a CIF file.
|
|
497
522
|
"""
|
|
498
|
-
filename = cif_file_open_dialog()
|
|
523
|
+
filename = cif_file_open_dialog(parent=self)
|
|
499
524
|
if not filename:
|
|
500
525
|
return
|
|
501
526
|
try:
|
|
@@ -536,7 +561,8 @@ class AppWindow(QMainWindow):
|
|
|
536
561
|
if not filename.strip():
|
|
537
562
|
return
|
|
538
563
|
try:
|
|
539
|
-
|
|
564
|
+
write_options = cif.WriteOptions(cif.Style.Indent35)
|
|
565
|
+
doc.write_file(filename, options=write_options)
|
|
540
566
|
# Path(filename).write_text(doc.as_string(cif.Style.Indent35))
|
|
541
567
|
except PermissionError:
|
|
542
568
|
if Path(filename).is_dir():
|
|
@@ -1066,6 +1092,7 @@ class AppWindow(QMainWindow):
|
|
|
1066
1092
|
runner.finished.connect(lambda: self.ui.CheckcifButton.setEnabled(True))
|
|
1067
1093
|
runner.run_process()
|
|
1068
1094
|
runner.formula.connect(self.add_moiety_furmula)
|
|
1095
|
+
return None
|
|
1069
1096
|
|
|
1070
1097
|
def add_moiety_furmula(self, formula_moiety):
|
|
1071
1098
|
moiety = self.ui.cif_main_table.getTextFromKey(key='_chemical_formula_moiety', col=Column.CIF)
|
|
@@ -1103,9 +1130,10 @@ class AppWindow(QMainWindow):
|
|
|
1103
1130
|
if file:
|
|
1104
1131
|
self.report_picture_path = Path(file)
|
|
1105
1132
|
else:
|
|
1106
|
-
filename, _ =
|
|
1107
|
-
|
|
1108
|
-
|
|
1133
|
+
filename, _ = compat.getopenfilename(parent=self,
|
|
1134
|
+
filters="Image Files (*.png *.jpg *.jpeg *.bmp "
|
|
1135
|
+
"*.gif *.tif *.tiff *.eps *.emf *.wmf)",
|
|
1136
|
+
caption='Open a Report Picture')
|
|
1109
1137
|
self.set_report_picture_path(filename)
|
|
1110
1138
|
|
|
1111
1139
|
def set_report_picture_path(self, filename: str):
|
|
@@ -1409,7 +1437,7 @@ class AppWindow(QMainWindow):
|
|
|
1409
1437
|
"""
|
|
1410
1438
|
imp_cif: CifContainer | None = None
|
|
1411
1439
|
if not filename:
|
|
1412
|
-
filename = cif_file_open_dialog(filter="CIF file (*.cif *.pcf *.cif_od *.cfx *.sqf)")
|
|
1440
|
+
filename = cif_file_open_dialog(parent=self, filter="CIF file (*.cif *.pcf *.cif_od *.cfx *.sqf)")
|
|
1413
1441
|
if not filename:
|
|
1414
1442
|
return
|
|
1415
1443
|
try:
|
|
@@ -1460,7 +1488,7 @@ class AppWindow(QMainWindow):
|
|
|
1460
1488
|
"""
|
|
1461
1489
|
self.ui.datanameComboBox.blockSignals(True)
|
|
1462
1490
|
if not filepath:
|
|
1463
|
-
filepath = Path(cif_file_open_dialog(last_dir=self.get_last_workdir()))
|
|
1491
|
+
filepath = Path(cif_file_open_dialog(parent=self, last_dir=self.get_last_workdir()))
|
|
1464
1492
|
if not filepath.is_file():
|
|
1465
1493
|
return
|
|
1466
1494
|
self.set_path_display_in_file_selector(str(filepath))
|
|
@@ -1669,7 +1697,7 @@ class AppWindow(QMainWindow):
|
|
|
1669
1697
|
self.load_cif_file(filepath=self.cif.fileobj, load_changes=False)
|
|
1670
1698
|
|
|
1671
1699
|
def get_file_from_dialog(self) -> Path | None:
|
|
1672
|
-
fp = cif_file_open_dialog(last_dir=self.get_last_workdir())
|
|
1700
|
+
fp = cif_file_open_dialog(parent=self, last_dir=self.get_last_workdir())
|
|
1673
1701
|
if not fp:
|
|
1674
1702
|
return None
|
|
1675
1703
|
filepath = Path(fp)
|
|
@@ -816,7 +816,7 @@ def get_atomlabel(input_atom: str) -> str:
|
|
|
816
816
|
else:
|
|
817
817
|
# print('*** {} is not a valid atom!! ***'.format(atom))
|
|
818
818
|
raise KeyError
|
|
819
|
-
except
|
|
819
|
+
except IndexError:
|
|
820
820
|
# print('*** {} is not a valid atom! ***'.format(atom))
|
|
821
821
|
raise KeyError
|
|
822
822
|
|
|
@@ -826,6 +826,6 @@ if __name__ == '__main__':
|
|
|
826
826
|
|
|
827
827
|
failed, attempted = doctest.testmod() # verbose=True)
|
|
828
828
|
if failed == 0:
|
|
829
|
-
print('passed all {} tests!'
|
|
829
|
+
print(f'passed all {attempted} tests!')
|
|
830
830
|
else:
|
|
831
|
-
print('{} of {} tests failed'
|
|
831
|
+
print(f'{failed} of {attempted} tests failed')
|
|
@@ -14,7 +14,7 @@ from html.parser import HTMLParser
|
|
|
14
14
|
from pathlib import Path
|
|
15
15
|
|
|
16
16
|
import requests
|
|
17
|
-
from
|
|
17
|
+
from qtpy.QtCore import QThread, Signal
|
|
18
18
|
from requests.exceptions import MissingSchema
|
|
19
19
|
|
|
20
20
|
from finalcif.cif.cif_file_io import CifContainer
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
# and you think this stuff is worth it, you can buy me a beer in return.
|
|
6
6
|
# Dr. Daniel Kratzert
|
|
7
7
|
# ----------------------------------------------------------------------------
|
|
8
|
+
import os
|
|
8
9
|
import re
|
|
9
10
|
from collections import namedtuple
|
|
10
11
|
from collections.abc import Generator
|
|
@@ -12,6 +13,12 @@ from contextlib import suppress
|
|
|
12
13
|
from pathlib import Path
|
|
13
14
|
|
|
14
15
|
import gemmi
|
|
16
|
+
|
|
17
|
+
from finalcif.cif import atoms
|
|
18
|
+
|
|
19
|
+
if hasattr(gemmi, 'set_leak_warnings'):
|
|
20
|
+
gemmi.set_leak_warnings(False)
|
|
21
|
+
|
|
15
22
|
from gemmi.cif import as_string, Document, Loop
|
|
16
23
|
from packaging.version import Version
|
|
17
24
|
from shelxfile import Shelxfile
|
|
@@ -20,8 +27,7 @@ from finalcif.cif.cif_order import order, special_keys, essential_keys, non_cent
|
|
|
20
27
|
from finalcif.cif.hkl import HKL, Limit
|
|
21
28
|
from finalcif.cif.text import utf8_to_str, quote, retranslate_delimiter
|
|
22
29
|
from finalcif.datafiles.utils import DSRFind
|
|
23
|
-
from finalcif.tools.misc import isnumeric, grouper, strip_finalcif_of_name,
|
|
24
|
-
_angstrom_to_x
|
|
30
|
+
from finalcif.tools.misc import isnumeric, grouper, strip_finalcif_of_name, _angstrom_to_x
|
|
25
31
|
|
|
26
32
|
|
|
27
33
|
class GemmiError(Exception):
|
|
@@ -41,6 +47,7 @@ class CifContainer:
|
|
|
41
47
|
new_block: Create a new block (new file) if a name is given. Otherwise, just
|
|
42
48
|
the existing document is opened.
|
|
43
49
|
"""
|
|
50
|
+
self.chars_ok = True
|
|
44
51
|
self.picometer: bool = False
|
|
45
52
|
self._abs_hkl_details: dict[str, str] = {}
|
|
46
53
|
if isinstance(file, str):
|
|
@@ -68,6 +75,7 @@ class CifContainer:
|
|
|
68
75
|
self._on_load()
|
|
69
76
|
self.order = []
|
|
70
77
|
self.essential_keys = []
|
|
78
|
+
# May be overwritten later:
|
|
71
79
|
self.set_order_keys(order)
|
|
72
80
|
self.set_essential_keys(essential_keys)
|
|
73
81
|
|
|
@@ -119,7 +127,7 @@ class CifContainer:
|
|
|
119
127
|
for num, line in enumerate(filepath.read_bytes().splitlines(keepends=True)):
|
|
120
128
|
try:
|
|
121
129
|
line.decode('ascii')
|
|
122
|
-
except
|
|
130
|
+
except UnicodeDecodeError:
|
|
123
131
|
line_numbers.append(num)
|
|
124
132
|
return line_numbers
|
|
125
133
|
|
|
@@ -151,9 +159,8 @@ class CifContainer:
|
|
|
151
159
|
self.dsr_used = DSRFind(self.res_file_data).dsr_used
|
|
152
160
|
self.atomic_struct: gemmi.SmallStructure = gemmi.make_small_structure_from_block(self.block)
|
|
153
161
|
# A dictionary to convert Atom names like 'C1_2' or 'Ga3' into Element names like 'C' or 'Ga'
|
|
154
|
-
self._name2elements = dict(
|
|
155
|
-
|
|
156
|
-
[x.upper() for x in self.block.find_loop('_atom_site_type_symbol')], strict=True))
|
|
162
|
+
self._name2elements = dict(zip([x.upper() for x in self.block.find_loop('_atom_site_label')],
|
|
163
|
+
[y.upper() for y in self.block.find_loop('_atom_site_type_symbol')], strict=False))
|
|
157
164
|
self.check_hkl_min_max()
|
|
158
165
|
|
|
159
166
|
@property
|
|
@@ -207,18 +214,20 @@ class CifContainer:
|
|
|
207
214
|
return doc
|
|
208
215
|
|
|
209
216
|
def cif_as_string(self, without_hkl=False) -> str:
|
|
217
|
+
opt = gemmi.cif.WriteOptions()
|
|
218
|
+
opt.align_pairs = 33
|
|
210
219
|
if without_hkl:
|
|
211
220
|
# return a copy, do not delete hkl from original:
|
|
212
221
|
doc = gemmi.cif.Document()
|
|
213
|
-
doc.parse_string(self.doc.as_string(
|
|
222
|
+
doc.parse_string(self.doc.as_string(options=opt))
|
|
214
223
|
for block in doc:
|
|
215
224
|
if block.find_pair_item('_shelx_hkl_file'):
|
|
216
225
|
block.find_pair_item('_shelx_hkl_file').erase()
|
|
217
226
|
if block.find_pair_item('_shelx_fcf_file'):
|
|
218
227
|
block.find_pair_item('_shelx_fcf_file').erase()
|
|
219
|
-
return doc.as_string(
|
|
228
|
+
return doc.as_string(options=opt)
|
|
220
229
|
else:
|
|
221
|
-
return self.doc.as_string(
|
|
230
|
+
return self.doc.as_string(options=opt)
|
|
222
231
|
|
|
223
232
|
def __getitem__(self, item: str) -> str:
|
|
224
233
|
"""
|
|
@@ -251,7 +260,6 @@ class CifContainer:
|
|
|
251
260
|
f", {self.nangles()} angles")
|
|
252
261
|
|
|
253
262
|
def file_is_there_and_writable(self) -> bool:
|
|
254
|
-
import os
|
|
255
263
|
return self.fileobj.exists() and self.fileobj.is_file() and os.access(self.fileobj, os.W_OK)
|
|
256
264
|
|
|
257
265
|
def set_pair_delimited(self, key: str, txt: str):
|
|
@@ -272,13 +280,13 @@ class CifContainer:
|
|
|
272
280
|
|
|
273
281
|
def save(self, filename: Path | None = None) -> None:
|
|
274
282
|
"""
|
|
275
|
-
Saves the current cif file.
|
|
276
|
-
:param filename: Name to save cif file to.
|
|
283
|
+
Saves the current cif file. It uses the '[basename]-finalcif.cif' suffix by default.
|
|
284
|
+
:param filename: Name to save cif file to if the default is not sufficient.
|
|
277
285
|
"""
|
|
278
286
|
if not filename:
|
|
279
287
|
filename = self.finalcif_file
|
|
280
288
|
if self.is_empty():
|
|
281
|
-
print(f'
|
|
289
|
+
print(f'DBG> CIF file {filename} is empty.')
|
|
282
290
|
return
|
|
283
291
|
if not self.is_writable(filename):
|
|
284
292
|
raise PermissionError(f'Failed to open {filename.resolve()} for writing: Operation not permitted')
|
|
@@ -708,18 +716,18 @@ class CifContainer:
|
|
|
708
716
|
Atoms from the CIF where values are returned as string like in the CIF with esds.
|
|
709
717
|
"""
|
|
710
718
|
labels = self.block.find_loop('_atom_site_label')
|
|
711
|
-
types = self.block.find_loop('_atom_site_type_symbol')
|
|
719
|
+
types = self.block.find_loop('_atom_site_type_symbol') or [atoms.get_atomlabel(x) for x in labels]
|
|
712
720
|
x = self.block.find_loop('_atom_site_fract_x')
|
|
713
721
|
y = self.block.find_loop('_atom_site_fract_y')
|
|
714
722
|
z = self.block.find_loop('_atom_site_fract_z')
|
|
715
|
-
part = self.block.find_loop('_atom_site_disorder_group')
|
|
716
|
-
occ = self.block.find_loop('_atom_site_occupancy')
|
|
717
|
-
u_eq = self.block.find_loop('_atom_site_U_iso_or_equiv')
|
|
723
|
+
part = self.block.find_loop('_atom_site_disorder_group') or ('0',) * len(labels)
|
|
724
|
+
occ = self.block.find_loop('_atom_site_occupancy') or ('1.000000',) * len(labels)
|
|
725
|
+
u_eq = self.block.find_loop('_atom_site_U_iso_or_equiv') or ('.',) * len(labels)
|
|
718
726
|
atom = namedtuple('atom', ('label', 'type', 'x', 'y', 'z', 'part', 'occ', 'u_eq'))
|
|
719
727
|
for label, type, x, y, z, part, occ, u_eq in zip(labels, types, x, y, z,
|
|
720
|
-
part
|
|
721
|
-
occ
|
|
722
|
-
u_eq, strict=
|
|
728
|
+
part,
|
|
729
|
+
occ,
|
|
730
|
+
u_eq, strict=False):
|
|
723
731
|
if without_h and self.ishydrogen(label):
|
|
724
732
|
continue
|
|
725
733
|
if self.picometer:
|
|
@@ -755,7 +763,7 @@ class CifContainer:
|
|
|
755
763
|
u13 = self.block.find_loop('_atom_site_aniso_U_13')
|
|
756
764
|
u12 = self.block.find_loop('_atom_site_aniso_U_12')
|
|
757
765
|
adp = namedtuple('adp', ('label', 'U11', 'U22', 'U33', 'U23', 'U13', 'U12'))
|
|
758
|
-
for label, u11, u22, u33, u23, u13, u12 in zip(labels, u11, u22, u33, u23, u13, u12):
|
|
766
|
+
for label, u11, u22, u33, u23, u13, u12 in zip(labels, u11, u22, u33, u23, u13, u12, strict=True):
|
|
759
767
|
if self.picometer:
|
|
760
768
|
u11 = _angstrom_to_x(u11, factor=100 ** 2)
|
|
761
769
|
u22 = _angstrom_to_x(u22, factor=100 ** 2)
|
|
@@ -809,9 +817,9 @@ class CifContainer:
|
|
|
809
817
|
label2 = self.block.find_loop('_geom_bond_atom_site_label_2')
|
|
810
818
|
dist = self.block.find_loop('_geom_bond_distance')
|
|
811
819
|
symm = self.block.find_loop('_geom_bond_site_symmetry_2')
|
|
812
|
-
publ_loop = self.block.find_loop('_geom_bond_publ_flag')
|
|
820
|
+
publ_loop = self.block.find_loop('_geom_bond_publ_flag') or len(label1) * ['?']
|
|
813
821
|
bond = namedtuple('bond', ('label1', 'label2', 'dist', 'symm'))
|
|
814
|
-
for label1, label2, dist, symm, publ in zip(label1, label2, dist, symm, publ_loop):
|
|
822
|
+
for label1, label2, dist, symm, publ in zip(label1, label2, dist, symm, publ_loop, strict=False):
|
|
815
823
|
if (without_h and (self.ishydrogen(label1) or self.ishydrogen(label2))) or self.yes_not_set(publ):
|
|
816
824
|
continue
|
|
817
825
|
else:
|
|
@@ -847,19 +855,22 @@ class CifContainer:
|
|
|
847
855
|
angle_val = self.block.find_loop('_geom_angle')
|
|
848
856
|
symm1 = self.block.find_loop('_geom_angle_site_symmetry_1')
|
|
849
857
|
symm2 = self.block.find_loop('_geom_angle_site_symmetry_3')
|
|
850
|
-
publ_loop = self.block.find_loop('_geom_angle_publ_flag')
|
|
858
|
+
publ_loop = self.block.find_loop('_geom_angle_publ_flag') or len(label1) * ['?']
|
|
851
859
|
angle = namedtuple('angle', ('label1', 'label2', 'label3', 'angle_val', 'symm1', 'symm2'))
|
|
852
|
-
for label1, label2, label3, angle_val, symm1, symm2, publ in
|
|
853
|
-
zip(label1, label2, label3, angle_val, symm1, symm2, publ_loop, strict=
|
|
854
|
-
if ((without_H and (self.ishydrogen(label1) or self.ishydrogen(label2) or
|
|
855
|
-
|
|
860
|
+
for label1, label2, label3, angle_val, symm1, symm2, publ in (
|
|
861
|
+
zip(label1, label2, label3, angle_val, symm1, symm2, publ_loop, strict=False)):
|
|
862
|
+
if ((without_H and (self.ishydrogen(label1) or self.ishydrogen(label2) or self.ishydrogen(label3))) or
|
|
863
|
+
self.yes_not_set(publ)):
|
|
856
864
|
continue
|
|
857
865
|
else:
|
|
858
866
|
yield angle(label1=label1, label2=label2, label3=label3, angle_val=angle_val,
|
|
859
867
|
symm1=self.checksymm(symm1), symm2=self.checksymm(symm2))
|
|
860
868
|
|
|
861
869
|
def _iselement(self, name: str) -> str:
|
|
862
|
-
|
|
870
|
+
try:
|
|
871
|
+
return self._name2elements[name.upper()]
|
|
872
|
+
except KeyError:
|
|
873
|
+
return atoms.get_atomlabel(name)
|
|
863
874
|
|
|
864
875
|
def natoms(self, without_h: bool = False) -> int:
|
|
865
876
|
return len(tuple(self.atoms(without_h)))
|
|
@@ -892,14 +903,15 @@ class CifContainer:
|
|
|
892
903
|
symm2 = self.block.find_loop('_geom_torsion_site_symmetry_2')
|
|
893
904
|
symm3 = self.block.find_loop('_geom_torsion_site_symmetry_3')
|
|
894
905
|
symm4 = self.block.find_loop('_geom_torsion_site_symmetry_4')
|
|
895
|
-
publ_loop = self.block.find_loop('_geom_torsion_publ_flag')
|
|
906
|
+
publ_loop = self.block.find_loop('_geom_torsion_publ_flag') or len(label1) * ['?']
|
|
896
907
|
tors = namedtuple('Torsion',
|
|
897
908
|
('label1', 'label2', 'label3', 'label4', 'torsang', 'symm1', 'symm2', 'symm3', 'symm4'))
|
|
898
|
-
for label1, label2, label3, label4, torsang, symm1, symm2, symm3, symm4, publ in zip(label1, label2, label3,
|
|
909
|
+
for label1, label2, label3, label4, torsang, symm1, symm2, symm3, symm4, publ in zip(label1, label2, label3,
|
|
899
910
|
label4,
|
|
900
911
|
torsang, symm1, symm2,
|
|
901
912
|
symm3,
|
|
902
|
-
symm4, publ_loop,
|
|
913
|
+
symm4, publ_loop,
|
|
914
|
+
strict=False):
|
|
903
915
|
if ((without_h and (self.ishydrogen(label1) or self.ishydrogen(label2)
|
|
904
916
|
or self.ishydrogen(label3) or self.ishydrogen(label3))) or self.yes_not_set(publ)):
|
|
905
917
|
continue
|
|
@@ -918,11 +930,11 @@ class CifContainer:
|
|
|
918
930
|
dist_da = self.block.find_loop('_geom_hbond_distance_DA')
|
|
919
931
|
angle_dha = self.block.find_loop('_geom_hbond_angle_DHA')
|
|
920
932
|
symm = self.block.find_loop('_geom_hbond_site_symmetry_A')
|
|
921
|
-
publ_loop = self.block.find_loop('_geom_hbond_publ_flag')
|
|
933
|
+
publ_loop = self.block.find_loop('_geom_hbond_publ_flag') or len(label_d) * ['?']
|
|
922
934
|
hydr = namedtuple('HydrogenBond', ('label_d', 'label_h', 'label_a', 'dist_dh', 'dist_ha', 'dist_da',
|
|
923
935
|
'angle_dha', 'symm'))
|
|
924
936
|
for label_d, label_h, label_a, dist_dh, dist_ha, dist_da, angle_dha, symm, publ in (
|
|
925
|
-
zip(label_d, label_h, label_a, dist_dh, dist_ha, dist_da, angle_dha, symm, publ_loop)):
|
|
937
|
+
zip(label_d, label_h, label_a, dist_dh, dist_ha, dist_da, angle_dha, symm, publ_loop, strict=False)):
|
|
926
938
|
if self.yes_not_set(publ):
|
|
927
939
|
continue
|
|
928
940
|
if self.picometer:
|
|
@@ -939,7 +951,12 @@ class CifContainer:
|
|
|
939
951
|
Returns the key/value pairs of a cif file sorted by priority.
|
|
940
952
|
"""
|
|
941
953
|
keys_without_values, keys_with_values = self.keys_with_essentials()
|
|
942
|
-
return keys_without_values
|
|
954
|
+
return [*keys_without_values, ('These below are already in:', '---------------------'), *keys_with_values]
|
|
955
|
+
|
|
956
|
+
def pairs(self):
|
|
957
|
+
for item in self.block:
|
|
958
|
+
if item.pair is not None:
|
|
959
|
+
yield item.pair
|
|
943
960
|
|
|
944
961
|
def _is_centrokey(self, key) -> bool:
|
|
945
962
|
"""
|
|
@@ -965,7 +982,7 @@ class CifContainer:
|
|
|
965
982
|
# continue
|
|
966
983
|
if self._is_centrokey(key):
|
|
967
984
|
continue
|
|
968
|
-
if not value or value
|
|
985
|
+
if not value or value in {'?', "'?'"}:
|
|
969
986
|
questions.append((key, value))
|
|
970
987
|
else:
|
|
971
988
|
with_values.append((key, value))
|
|
@@ -10,7 +10,7 @@ from pathlib import Path
|
|
|
10
10
|
from urllib.parse import urlparse
|
|
11
11
|
|
|
12
12
|
import requests
|
|
13
|
-
from
|
|
13
|
+
from qtpy.QtWidgets import QTableWidgetItem, QTextBrowser, QFrame
|
|
14
14
|
|
|
15
15
|
from finalcif.cif.cif_file_io import CifContainer
|
|
16
16
|
from finalcif.cif.cod.deposition_list import CODFetcher
|
|
@@ -210,7 +210,7 @@ class CODdeposit:
|
|
|
210
210
|
if f.authenticated:
|
|
211
211
|
self.token_valid = True
|
|
212
212
|
else:
|
|
213
|
-
self.ui.statusBar.showMessage('Unable to login. Check username/password.',
|
|
213
|
+
self.ui.statusBar.showMessage('Unable to login. Check username/password.', 12000)
|
|
214
214
|
f.get_table_data_by_token(self._cod_token)
|
|
215
215
|
parser = MyCODStructuresParser()
|
|
216
216
|
parser.feed(f.table_html)
|
|
@@ -346,14 +346,14 @@ class CODdeposit:
|
|
|
346
346
|
self.ui.depositionOptionsStackedWidget.setCurrentIndex(self.deposition_type_to_int(deposition_type))
|
|
347
347
|
|
|
348
348
|
def reset_deposit_button_state_to_initial(self):
|
|
349
|
-
self.ui.depositCIFpushButton.disconnect()
|
|
349
|
+
self.ui.depositCIFpushButton.clicked.disconnect()
|
|
350
350
|
self.ui.depositOutputTextBrowser.clear()
|
|
351
351
|
self.ui.depositCIFpushButton.setText("Deposit CIF")
|
|
352
352
|
self.ui.depositCIFpushButton.clicked.connect(self._init_deposit)
|
|
353
353
|
|
|
354
354
|
def set_deposit_button_to_try_again(self):
|
|
355
355
|
self.ui.depositCIFpushButton.setText("Try Again")
|
|
356
|
-
self.ui.depositCIFpushButton.disconnect()
|
|
356
|
+
self.ui.depositCIFpushButton.clicked.disconnect()
|
|
357
357
|
self.ui.depositCIFpushButton.clicked.connect(lambda: self.switch_to_page(self.deposition_type))
|
|
358
358
|
|
|
359
359
|
def log_response_text(self, resp: requests.Response, *args, **kwargs):
|
|
@@ -380,7 +380,7 @@ class CODdeposit:
|
|
|
380
380
|
self.user_email = text
|
|
381
381
|
|
|
382
382
|
def _set_external_hkl_file(self) -> None:
|
|
383
|
-
file = cif_file_open_dialog(filter="HKL file (*.hkl *.fcf)")
|
|
383
|
+
file = cif_file_open_dialog(parent=self, filter="HKL file (*.hkl *.fcf)")
|
|
384
384
|
if file.endswith('.hkl'):
|
|
385
385
|
if self.cif.res_file_data:
|
|
386
386
|
hklf = self.cif._hklf_number_from_shelxl_file()
|
|
@@ -6,14 +6,14 @@
|
|
|
6
6
|
##
|
|
7
7
|
################################################################################
|
|
8
8
|
|
|
9
|
-
from
|
|
9
|
+
from qtpy.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
|
|
10
10
|
QMetaObject, QObject, QPoint, QRect,
|
|
11
11
|
QSize, QTime, QUrl, Qt)
|
|
12
|
-
from
|
|
12
|
+
from qtpy.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
|
|
13
13
|
QFont, QFontDatabase, QGradient, QIcon,
|
|
14
14
|
QImage, QKeySequence, QLinearGradient, QPainter,
|
|
15
15
|
QPalette, QPixmap, QRadialGradient, QTransform)
|
|
16
|
-
from
|
|
16
|
+
from qtpy.QtWidgets import (QAbstractItemView, QApplication, QGridLayout, QHeaderView,
|
|
17
17
|
QLabel, QPushButton, QSizePolicy, QSpacerItem,
|
|
18
18
|
QTableWidget, QTableWidgetItem, QVBoxLayout, QWidget)
|
|
19
19
|
|
|
@@ -19,7 +19,7 @@ class SHELXTlistfile(ParserMixin):
|
|
|
19
19
|
self.solutions = {}
|
|
20
20
|
self.parse_file()
|
|
21
21
|
|
|
22
|
-
def parse_file(self):
|
|
22
|
+
def parse_file(self) -> None:
|
|
23
23
|
"""
|
|
24
24
|
+ SHELXT - CRYSTAL STRUCTURE SOLUTION - VERSION 2018/2 +
|
|
25
25
|
"""
|
|
@@ -29,11 +29,15 @@ class SHELXTlistfile(ParserMixin):
|
|
|
29
29
|
if 'SHELXTL' in line:
|
|
30
30
|
self.version = 'SHELXT ' + line.split()[-1]
|
|
31
31
|
if line.strip().startswith('R1 Rweak Alpha'):
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
try:
|
|
33
|
+
for n in range(100):
|
|
34
|
+
if not self._text[num + 1 + n]:
|
|
35
|
+
break
|
|
36
|
+
if self._text[num + 1]:
|
|
37
|
+
self.solutions[self._text[num + 1 + n][58:76].strip()] = self._text[num + 1 + n][37:51].strip()
|
|
38
|
+
except IndexError:
|
|
39
|
+
return None
|
|
40
|
+
return None
|
|
37
41
|
|
|
38
42
|
|
|
39
43
|
class SolutionProgram:
|
|
@@ -58,17 +62,22 @@ class SolutionProgram:
|
|
|
58
62
|
except (TypeError, AttributeError):
|
|
59
63
|
res = ''
|
|
60
64
|
byxt = res.find('REM SHELXT solution in')
|
|
61
|
-
for x in xt_files:
|
|
62
|
-
shelxt = SHELXTlistfile(x.as_posix())
|
|
63
|
-
if shelxt.version and byxt:
|
|
64
|
-
self.method = 'direct'
|
|
65
|
-
self.solution_listfile = 'foo' # x.name
|
|
66
|
-
return shelxt
|
|
67
65
|
if byxt > 0:
|
|
66
|
+
for x in xt_files:
|
|
67
|
+
shelxt = SHELXTlistfile(x.as_posix())
|
|
68
|
+
if shelxt.version and byxt:
|
|
69
|
+
self.method = 'direct'
|
|
70
|
+
self.solution_listfile = 'foo' # x.name
|
|
71
|
+
return shelxt
|
|
68
72
|
xt = SHELXTlistfile('')
|
|
69
73
|
xt.version = "SHELXT (G. Sheldrick)"
|
|
70
74
|
self.method = 'direct'
|
|
71
75
|
return xt
|
|
76
|
+
if res.find('Best SHELXD solution'):
|
|
77
|
+
xt = SHELXTlistfile('')
|
|
78
|
+
xt.version = "SHELXD (G. Sheldrick)"
|
|
79
|
+
self.method = 'dual space'
|
|
80
|
+
return xt
|
|
72
81
|
xt = SHELXTlistfile('')
|
|
73
82
|
xt.version = "SHELXS (G. Sheldrick)"
|
|
74
83
|
self.method = 'direct'
|
|
@@ -5,9 +5,9 @@ from math import sqrt, cos, sin, dist
|
|
|
5
5
|
from pathlib import Path
|
|
6
6
|
|
|
7
7
|
import numpy as np
|
|
8
|
-
from
|
|
9
|
-
from
|
|
10
|
-
from
|
|
8
|
+
from qtpy import QtWidgets, QtCore, QtGui
|
|
9
|
+
from qtpy.QtCore import Qt
|
|
10
|
+
from qtpy.QtGui import QPainter, QPen, QBrush, QColor, QMouseEvent, QPalette, QImage, QResizeEvent, QWheelEvent
|
|
11
11
|
|
|
12
12
|
from finalcif.cif.atoms import get_radius_from_element, element2color
|
|
13
13
|
from finalcif.cif.cif_file_io import CifContainer
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import sys
|
|
2
2
|
|
|
3
3
|
import vtk
|
|
4
|
-
from
|
|
5
|
-
from
|
|
4
|
+
from qtpy import QtWidgets, QtCore
|
|
5
|
+
from qtpy.QtGui import QSurfaceFormat
|
|
6
6
|
from vtkmodules.qt.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor
|
|
7
7
|
from vtkmodules.vtkCommonCore import vtkLookupTable
|
|
8
8
|
from vtkmodules.vtkDomainsChemistry import vtkPeriodicTable
|