finalcif 153__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-153 → finalcif-154}/.gitignore +1 -0
- {finalcif-153 → finalcif-154}/PKG-INFO +1 -1
- finalcif-154/finalcif/__init__.py +2 -0
- {finalcif-153 → finalcif-154}/finalcif/appwindow.py +20 -0
- {finalcif-153 → finalcif-154}/finalcif/cif/atoms.py +3 -3
- {finalcif-153 → finalcif-154}/finalcif/cif/cif_file_io.py +36 -27
- {finalcif-153 → finalcif-154}/finalcif/equip_property/author_loop_templates.py +14 -23
- {finalcif-153 → finalcif-154}/finalcif/finalcif_start.py +1 -1
- {finalcif-153 → finalcif-154}/finalcif/report/templated_report.py +62 -39
- {finalcif-153 → finalcif-154}/finalcif/template/report.tmpl +7 -1
- {finalcif-153 → finalcif-154}/finalcif/tools/platon.py +10 -7
- {finalcif-153 → 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-153/finalcif/__init__.py +0 -2
- {finalcif-153 → finalcif-154}/.gitattributes +0 -0
- {finalcif-153 → finalcif-154}/.python-version +0 -0
- {finalcif-153 → finalcif-154}/.ruff.toml +0 -0
- {finalcif-153 → finalcif-154}/.run/Make Documentation MAC.run.xml +0 -0
- {finalcif-153 → finalcif-154}/.run/compile_ui_files.run.xml +0 -0
- {finalcif-153 → finalcif-154}/.run/make documentation Windows.run.xml +0 -0
- {finalcif-153 → finalcif-154}/CODE_OF_CONDUCT.md +0 -0
- {finalcif-153 → finalcif-154}/CONTRIBUTING.md +0 -0
- {finalcif-153 → finalcif-154}/Finalcif_installer_win.spec +0 -0
- {finalcif-153 → finalcif-154}/Finalcif_linux_onefile.spec +0 -0
- {finalcif-153 → finalcif-154}/Finalcif_mac.spec +0 -0
- {finalcif-153 → finalcif-154}/Hydrogen_solution_type.cif +0 -0
- {finalcif-153 → finalcif-154}/LICENSE +0 -0
- {finalcif-153 → finalcif-154}/README.md +0 -0
- {finalcif-153 → finalcif-154}/finalcif/app_path.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/cif/__init__.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/cif/all_cif_dicts.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/cif/checkcif/__init__.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/cif/checkcif/checkcif.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/cif/cif_dict_foo.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/cif/cif_order.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/cif/cod/__init__.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/cif/cod/deposit.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/cif/cod/deposit_check.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/cif/cod/deposition_list.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/cif/cod/doi.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/cif/cod/upload.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/cif/cod/website_parser.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/cif/core_dict.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/cif/hkl.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/cif/modulation_dict.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/cif/powder_dict.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/cif/reference.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/cif/restraints_dict.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/cif/text.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/cif/twin_dict.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/ciforder/__init__.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/ciforder/order.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/ciforder/order_ui.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/ciforder/order_ui.ui +0 -0
- {finalcif-153 → finalcif-154}/finalcif/datafiles/__init__.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/datafiles/bruker_data.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/datafiles/bruker_frame.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/datafiles/ccdc_mail.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/datafiles/data.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/datafiles/p4p_reader.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/datafiles/sadabs.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/datafiles/saint.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/datafiles/shelx_lst.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/datafiles/utils.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/displaymol/__init__.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/displaymol/molecule2D.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/displaymol/sdm.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/displaymol/vtk_molecule.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/equip_property/__init__.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/equip_property/equipment.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/equip_property/properties.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/equip_property/tools.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/gui/__init__.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/gui/block_combobox.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/gui/combobox.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/gui/custom_classes.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/gui/dialogs.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/gui/edit_button.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/gui/equipmenttable.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/gui/file_editor.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/gui/finalcif_gui_ui.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/gui/finalcif_gui_ui.ui +0 -0
- {finalcif-153 → finalcif-154}/finalcif/gui/import_selector.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/gui/import_selector_ui.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/gui/import_selector_ui.ui +0 -0
- {finalcif-153 → finalcif-154}/finalcif/gui/loop_creator.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/gui/loop_creator_ui.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/gui/loop_creator_ui.ui +0 -0
- {finalcif-153 → finalcif-154}/finalcif/gui/loops.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/gui/mainstackwidget.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/gui/mixins.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/gui/new_key_dialog.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/gui/new_key_dialog_ui.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/gui/new_key_dialog_ui.ui +0 -0
- {finalcif-153 → finalcif-154}/finalcif/gui/plaintextedit.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/gui/playground.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/gui/propertytable.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/gui/spell_check_edit.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/gui/text_templates_ui.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/gui/text_templates_ui.ui +0 -0
- {finalcif-153 → finalcif-154}/finalcif/gui/text_value_editor.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/gui/validators.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/gui/vrf_classes.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/icon/__init__.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/icon/finalcif.png +0 -0
- {finalcif-153 → finalcif-154}/finalcif/icon/finalcif2.ico +0 -0
- {finalcif-153 → finalcif-154}/finalcif/icon/finalcif2.png +0 -0
- {finalcif-153 → finalcif-154}/finalcif/icon/multitable.ico +0 -0
- {finalcif-153 → finalcif-154}/finalcif/icon/multitable.png +0 -0
- {finalcif-153 → finalcif-154}/finalcif/icon/multitable.xcf +0 -0
- {finalcif-153 → finalcif-154}/finalcif/report/__init__.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/report/archive_report.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/report/gui/__init__.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/report/gui/mainwindow.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/report/gui/mainwindow.ui +0 -0
- {finalcif-153 → finalcif-154}/finalcif/report/mtools.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/report/references.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/report/report_text.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/report/symm.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/report/tables.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/template/__init__.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/template/bootstrap/bootstrap.min.css +0 -0
- {finalcif-153 → finalcif-154}/finalcif/template/machines/D8_VENTURE.cif +0 -0
- {finalcif-153 → finalcif-154}/finalcif/template/mathml2omml.xsl +0 -0
- {finalcif-153 → finalcif-154}/finalcif/template/report_default.docx +0 -0
- {finalcif-153 → finalcif-154}/finalcif/template/template1.docx +0 -0
- {finalcif-153 → finalcif-154}/finalcif/template/template_for_multitable.docx +0 -0
- {finalcif-153 → finalcif-154}/finalcif/template/template_text.docx +0 -0
- {finalcif-153 → finalcif-154}/finalcif/template/template_without_text.docx +0 -0
- {finalcif-153 → finalcif-154}/finalcif/template/templates.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/template/xsl/convert.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/template/xsl/xmltohtml.xsl +0 -0
- {finalcif-153 → finalcif-154}/finalcif/tools/__init__.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/tools/chemparse.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/tools/download.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/tools/dsrmath.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/tools/misc.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/tools/options.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/tools/pupdate.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/tools/settings.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/tools/shred.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/tools/space_groups.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/tools/spgr_format.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif/tools/statusbar.py +0 -0
- {finalcif-153 → finalcif-154}/finalcif.exe +0 -0
- {finalcif-153 → finalcif-154}/install_requirements +0 -0
- {finalcif-153 → finalcif-154}/install_requirements.bat +0 -0
- {finalcif-153 → finalcif-154}/pyproject.toml +0 -0
- {finalcif-153 → finalcif-154}/requirements.txt +0 -0
- {finalcif-153 → finalcif-154}/requirements_devel.txt +0 -0
- {finalcif-153 → finalcif-154}/requirements_doku.txt +0 -0
- {finalcif-153 → finalcif-154}/run_finalcif +0 -0
- {finalcif-153 → finalcif-154}/run_finalcif.bat +0 -0
- {finalcif-153 → finalcif-154}/screenshots/finalcif_checkcif.png +0 -0
- {finalcif-153 → finalcif-154}/screenshots/finalcif_details.png +0 -0
- {finalcif-153 → finalcif-154}/screenshots/finalcif_loops.png +0 -0
- {finalcif-153 → finalcif-154}/screenshots/finalcif_loops2.png +0 -0
- {finalcif-153 → finalcif-154}/screenshots/finalcif_main.png +0 -0
- {finalcif-153 → finalcif-154}/screenshots/finalcif_report.png +0 -0
- {finalcif-153 → finalcif-154}/screenshots/finalcif_responses.png +0 -0
- {finalcif-153 → finalcif-154}/update.exe +0 -0
- {finalcif-153 → finalcif-154}/uv.lock +0 -0
|
@@ -127,6 +127,25 @@ class AppWindow(QMainWindow):
|
|
|
127
127
|
if file:
|
|
128
128
|
self.load_cif_file(file)
|
|
129
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
|
+
)
|
|
130
149
|
self.set_checkcif_output_font(self.ui.CheckcifPlaintextEdit)
|
|
131
150
|
# To make file drag&drop working:
|
|
132
151
|
self.setAcceptDrops(True)
|
|
@@ -1073,6 +1092,7 @@ class AppWindow(QMainWindow):
|
|
|
1073
1092
|
runner.finished.connect(lambda: self.ui.CheckcifButton.setEnabled(True))
|
|
1074
1093
|
runner.run_process()
|
|
1075
1094
|
runner.formula.connect(self.add_moiety_furmula)
|
|
1095
|
+
return None
|
|
1076
1096
|
|
|
1077
1097
|
def add_moiety_furmula(self, formula_moiety):
|
|
1078
1098
|
moiety = self.ui.cif_main_table.getTextFromKey(key='_chemical_formula_moiety', col=Column.CIF)
|
|
@@ -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')
|
|
@@ -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
|
|
@@ -13,6 +14,8 @@ from pathlib import Path
|
|
|
13
14
|
|
|
14
15
|
import gemmi
|
|
15
16
|
|
|
17
|
+
from finalcif.cif import atoms
|
|
18
|
+
|
|
16
19
|
if hasattr(gemmi, 'set_leak_warnings'):
|
|
17
20
|
gemmi.set_leak_warnings(False)
|
|
18
21
|
|
|
@@ -24,8 +27,7 @@ from finalcif.cif.cif_order import order, special_keys, essential_keys, non_cent
|
|
|
24
27
|
from finalcif.cif.hkl import HKL, Limit
|
|
25
28
|
from finalcif.cif.text import utf8_to_str, quote, retranslate_delimiter
|
|
26
29
|
from finalcif.datafiles.utils import DSRFind
|
|
27
|
-
from finalcif.tools.misc import isnumeric, grouper, strip_finalcif_of_name,
|
|
28
|
-
_angstrom_to_x
|
|
30
|
+
from finalcif.tools.misc import isnumeric, grouper, strip_finalcif_of_name, _angstrom_to_x
|
|
29
31
|
|
|
30
32
|
|
|
31
33
|
class GemmiError(Exception):
|
|
@@ -45,6 +47,7 @@ class CifContainer:
|
|
|
45
47
|
new_block: Create a new block (new file) if a name is given. Otherwise, just
|
|
46
48
|
the existing document is opened.
|
|
47
49
|
"""
|
|
50
|
+
self.chars_ok = True
|
|
48
51
|
self.picometer: bool = False
|
|
49
52
|
self._abs_hkl_details: dict[str, str] = {}
|
|
50
53
|
if isinstance(file, str):
|
|
@@ -72,6 +75,7 @@ class CifContainer:
|
|
|
72
75
|
self._on_load()
|
|
73
76
|
self.order = []
|
|
74
77
|
self.essential_keys = []
|
|
78
|
+
# May be overwritten later:
|
|
75
79
|
self.set_order_keys(order)
|
|
76
80
|
self.set_essential_keys(essential_keys)
|
|
77
81
|
|
|
@@ -123,7 +127,7 @@ class CifContainer:
|
|
|
123
127
|
for num, line in enumerate(filepath.read_bytes().splitlines(keepends=True)):
|
|
124
128
|
try:
|
|
125
129
|
line.decode('ascii')
|
|
126
|
-
except
|
|
130
|
+
except UnicodeDecodeError:
|
|
127
131
|
line_numbers.append(num)
|
|
128
132
|
return line_numbers
|
|
129
133
|
|
|
@@ -155,9 +159,8 @@ class CifContainer:
|
|
|
155
159
|
self.dsr_used = DSRFind(self.res_file_data).dsr_used
|
|
156
160
|
self.atomic_struct: gemmi.SmallStructure = gemmi.make_small_structure_from_block(self.block)
|
|
157
161
|
# A dictionary to convert Atom names like 'C1_2' or 'Ga3' into Element names like 'C' or 'Ga'
|
|
158
|
-
self._name2elements = dict(
|
|
159
|
-
|
|
160
|
-
[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))
|
|
161
164
|
self.check_hkl_min_max()
|
|
162
165
|
|
|
163
166
|
@property
|
|
@@ -211,8 +214,8 @@ class CifContainer:
|
|
|
211
214
|
return doc
|
|
212
215
|
|
|
213
216
|
def cif_as_string(self, without_hkl=False) -> str:
|
|
214
|
-
opt = gemmi.cif.WriteOptions(
|
|
215
|
-
|
|
217
|
+
opt = gemmi.cif.WriteOptions()
|
|
218
|
+
opt.align_pairs = 33
|
|
216
219
|
if without_hkl:
|
|
217
220
|
# return a copy, do not delete hkl from original:
|
|
218
221
|
doc = gemmi.cif.Document()
|
|
@@ -257,7 +260,6 @@ class CifContainer:
|
|
|
257
260
|
f", {self.nangles()} angles")
|
|
258
261
|
|
|
259
262
|
def file_is_there_and_writable(self) -> bool:
|
|
260
|
-
import os
|
|
261
263
|
return self.fileobj.exists() and self.fileobj.is_file() and os.access(self.fileobj, os.W_OK)
|
|
262
264
|
|
|
263
265
|
def set_pair_delimited(self, key: str, txt: str):
|
|
@@ -278,13 +280,13 @@ class CifContainer:
|
|
|
278
280
|
|
|
279
281
|
def save(self, filename: Path | None = None) -> None:
|
|
280
282
|
"""
|
|
281
|
-
Saves the current cif file.
|
|
282
|
-
: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.
|
|
283
285
|
"""
|
|
284
286
|
if not filename:
|
|
285
287
|
filename = self.finalcif_file
|
|
286
288
|
if self.is_empty():
|
|
287
|
-
print(f'
|
|
289
|
+
print(f'DBG> CIF file {filename} is empty.')
|
|
288
290
|
return
|
|
289
291
|
if not self.is_writable(filename):
|
|
290
292
|
raise PermissionError(f'Failed to open {filename.resolve()} for writing: Operation not permitted')
|
|
@@ -714,18 +716,18 @@ class CifContainer:
|
|
|
714
716
|
Atoms from the CIF where values are returned as string like in the CIF with esds.
|
|
715
717
|
"""
|
|
716
718
|
labels = self.block.find_loop('_atom_site_label')
|
|
717
|
-
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]
|
|
718
720
|
x = self.block.find_loop('_atom_site_fract_x')
|
|
719
721
|
y = self.block.find_loop('_atom_site_fract_y')
|
|
720
722
|
z = self.block.find_loop('_atom_site_fract_z')
|
|
721
723
|
part = self.block.find_loop('_atom_site_disorder_group') or ('0',) * len(labels)
|
|
722
724
|
occ = self.block.find_loop('_atom_site_occupancy') or ('1.000000',) * len(labels)
|
|
723
|
-
u_eq = self.block.find_loop('_atom_site_U_iso_or_equiv')
|
|
725
|
+
u_eq = self.block.find_loop('_atom_site_U_iso_or_equiv') or ('.',) * len(labels)
|
|
724
726
|
atom = namedtuple('atom', ('label', 'type', 'x', 'y', 'z', 'part', 'occ', 'u_eq'))
|
|
725
727
|
for label, type, x, y, z, part, occ, u_eq in zip(labels, types, x, y, z,
|
|
726
728
|
part,
|
|
727
729
|
occ,
|
|
728
|
-
u_eq, strict=
|
|
730
|
+
u_eq, strict=False):
|
|
729
731
|
if without_h and self.ishydrogen(label):
|
|
730
732
|
continue
|
|
731
733
|
if self.picometer:
|
|
@@ -761,7 +763,7 @@ class CifContainer:
|
|
|
761
763
|
u13 = self.block.find_loop('_atom_site_aniso_U_13')
|
|
762
764
|
u12 = self.block.find_loop('_atom_site_aniso_U_12')
|
|
763
765
|
adp = namedtuple('adp', ('label', 'U11', 'U22', 'U33', 'U23', 'U13', 'U12'))
|
|
764
|
-
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):
|
|
765
767
|
if self.picometer:
|
|
766
768
|
u11 = _angstrom_to_x(u11, factor=100 ** 2)
|
|
767
769
|
u22 = _angstrom_to_x(u22, factor=100 ** 2)
|
|
@@ -817,7 +819,7 @@ class CifContainer:
|
|
|
817
819
|
symm = self.block.find_loop('_geom_bond_site_symmetry_2')
|
|
818
820
|
publ_loop = self.block.find_loop('_geom_bond_publ_flag') or len(label1) * ['?']
|
|
819
821
|
bond = namedtuple('bond', ('label1', 'label2', 'dist', 'symm'))
|
|
820
|
-
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):
|
|
821
823
|
if (without_h and (self.ishydrogen(label1) or self.ishydrogen(label2))) or self.yes_not_set(publ):
|
|
822
824
|
continue
|
|
823
825
|
else:
|
|
@@ -855,17 +857,20 @@ class CifContainer:
|
|
|
855
857
|
symm2 = self.block.find_loop('_geom_angle_site_symmetry_3')
|
|
856
858
|
publ_loop = self.block.find_loop('_geom_angle_publ_flag') or len(label1) * ['?']
|
|
857
859
|
angle = namedtuple('angle', ('label1', 'label2', 'label3', 'angle_val', 'symm1', 'symm2'))
|
|
858
|
-
for label1, label2, label3, angle_val, symm1, symm2, publ in
|
|
859
|
-
|
|
860
|
-
if ((without_H and (self.ishydrogen(label1) or self.ishydrogen(label2) or
|
|
861
|
-
|
|
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)):
|
|
862
864
|
continue
|
|
863
865
|
else:
|
|
864
866
|
yield angle(label1=label1, label2=label2, label3=label3, angle_val=angle_val,
|
|
865
867
|
symm1=self.checksymm(symm1), symm2=self.checksymm(symm2))
|
|
866
868
|
|
|
867
869
|
def _iselement(self, name: str) -> str:
|
|
868
|
-
|
|
870
|
+
try:
|
|
871
|
+
return self._name2elements[name.upper()]
|
|
872
|
+
except KeyError:
|
|
873
|
+
return atoms.get_atomlabel(name)
|
|
869
874
|
|
|
870
875
|
def natoms(self, without_h: bool = False) -> int:
|
|
871
876
|
return len(tuple(self.atoms(without_h)))
|
|
@@ -902,12 +907,11 @@ class CifContainer:
|
|
|
902
907
|
tors = namedtuple('Torsion',
|
|
903
908
|
('label1', 'label2', 'label3', 'label4', 'torsang', 'symm1', 'symm2', 'symm3', 'symm4'))
|
|
904
909
|
for label1, label2, label3, label4, torsang, symm1, symm2, symm3, symm4, publ in zip(label1, label2, label3,
|
|
905
|
-
# noqa: B020
|
|
906
910
|
label4,
|
|
907
911
|
torsang, symm1, symm2,
|
|
908
912
|
symm3,
|
|
909
913
|
symm4, publ_loop,
|
|
910
|
-
strict=
|
|
914
|
+
strict=False):
|
|
911
915
|
if ((without_h and (self.ishydrogen(label1) or self.ishydrogen(label2)
|
|
912
916
|
or self.ishydrogen(label3) or self.ishydrogen(label3))) or self.yes_not_set(publ)):
|
|
913
917
|
continue
|
|
@@ -930,7 +934,7 @@ class CifContainer:
|
|
|
930
934
|
hydr = namedtuple('HydrogenBond', ('label_d', 'label_h', 'label_a', 'dist_dh', 'dist_ha', 'dist_da',
|
|
931
935
|
'angle_dha', 'symm'))
|
|
932
936
|
for label_d, label_h, label_a, dist_dh, dist_ha, dist_da, angle_dha, symm, publ in (
|
|
933
|
-
|
|
937
|
+
zip(label_d, label_h, label_a, dist_dh, dist_ha, dist_da, angle_dha, symm, publ_loop, strict=False)):
|
|
934
938
|
if self.yes_not_set(publ):
|
|
935
939
|
continue
|
|
936
940
|
if self.picometer:
|
|
@@ -947,7 +951,12 @@ class CifContainer:
|
|
|
947
951
|
Returns the key/value pairs of a cif file sorted by priority.
|
|
948
952
|
"""
|
|
949
953
|
keys_without_values, keys_with_values = self.keys_with_essentials()
|
|
950
|
-
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
|
|
951
960
|
|
|
952
961
|
def _is_centrokey(self, key) -> bool:
|
|
953
962
|
"""
|
|
@@ -973,7 +982,7 @@ class CifContainer:
|
|
|
973
982
|
# continue
|
|
974
983
|
if self._is_centrokey(key):
|
|
975
984
|
continue
|
|
976
|
-
if not value or value
|
|
985
|
+
if not value or value in {'?', "'?'"}:
|
|
977
986
|
questions.append((key, value))
|
|
978
987
|
else:
|
|
979
988
|
with_values.append((key, value))
|
|
@@ -171,34 +171,24 @@ class AuthorLoops:
|
|
|
171
171
|
def save_author_to_loop(self) -> None:
|
|
172
172
|
author = self.get_author_info()
|
|
173
173
|
row = [author.name, author.address, author.email, author.phone, author.orcid, author.iucr_id, author.footnote]
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
gemmi_loop: Loop = self.cif.block.find_loop(author_type).get_loop()
|
|
181
|
-
if tuple(row) in list(grouper(gemmi_loop.values, len(row))):
|
|
182
|
-
self.app.status_bar.show_message('This author already exists.', 10)
|
|
174
|
+
author_loop_tags = self.get_author_loop(author)
|
|
175
|
+
table: gemmi.cif.Table = self.cif.block.find(author_loop_tags)
|
|
176
|
+
if table.width():
|
|
177
|
+
gemmi_loop: Loop = table.loop
|
|
178
|
+
if tuple(row) in list(grouper(gemmi_loop.values, gemmi_loop.width())):
|
|
179
|
+
self.app.status_bar.show_message('This author already exists.', 15)
|
|
183
180
|
print('dbg> Author already exists.')
|
|
184
181
|
return
|
|
185
182
|
else:
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
183
|
+
gemmi_loop = self.cif.init_loop(author_loop_tags)
|
|
184
|
+
table = self.cif.block.find(author_loop_tags)
|
|
185
|
+
if gemmi_loop.width() < len(row):
|
|
186
|
+
row = row[:gemmi_loop.width()]
|
|
187
|
+
if row not in table:
|
|
188
|
+
table.append_row(row)
|
|
189
189
|
self.app.make_loops_tables()
|
|
190
190
|
self.show_authors_list()
|
|
191
191
|
|
|
192
|
-
def check_if_loop_and_row_size_fit_together(self, gemmi_loop: gemmi.cif.Loop, row: list[str]) -> None:
|
|
193
|
-
if gemmi_loop.width() < len(row):
|
|
194
|
-
cut_row = row[:gemmi_loop.width()]
|
|
195
|
-
if cut_row not in gemmi_loop.values:
|
|
196
|
-
gemmi_loop.add_row(cut_row)
|
|
197
|
-
elif gemmi_loop.width() > len(row):
|
|
198
|
-
show_general_warning(self, 'An author loop with larger size is already in the CIF. Can not proceed.')
|
|
199
|
-
elif row not in gemmi_loop.values:
|
|
200
|
-
gemmi_loop.add_row(row)
|
|
201
|
-
|
|
202
192
|
def get_author_info(self) -> Author:
|
|
203
193
|
if self.ui.authorEditTabWidget.currentWidget().objectName() == 'page_publication':
|
|
204
194
|
name = quote(utf8_to_str(self.ui.FullNameLineEdit.text()))
|
|
@@ -445,4 +435,5 @@ if __name__ == '__main__':
|
|
|
445
435
|
import pprint
|
|
446
436
|
|
|
447
437
|
l = AuthorLoops(Ui_FinalCifWindow(), CifContainer('test-data/1000007.cif'), None)
|
|
448
|
-
|
|
438
|
+
data = l.export_raw_data()
|
|
439
|
+
pprint.pprint(data)
|
|
@@ -53,7 +53,7 @@ def my_exception_hook(exctype: type[BaseException], value: BaseException, error_
|
|
|
53
53
|
|
|
54
54
|
logfile = Path.home().joinpath(Path(r'finalcif-crash.txt'))
|
|
55
55
|
try:
|
|
56
|
-
logfile.write_text(errortext)
|
|
56
|
+
logfile.write_text(errortext, encoding='utf-8', errors='ignore')
|
|
57
57
|
except PermissionError:
|
|
58
58
|
pass
|
|
59
59
|
sys.__excepthook__(exctype, value, error_traceback)
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import abc
|
|
3
4
|
import dataclasses
|
|
4
5
|
import enum
|
|
5
6
|
import itertools
|
|
6
7
|
import pathlib
|
|
7
8
|
import re
|
|
8
9
|
import sys
|
|
9
|
-
from abc import ABC
|
|
10
10
|
from collections import namedtuple
|
|
11
11
|
from collections.abc import Iterator
|
|
12
12
|
from contextlib import suppress
|
|
@@ -499,7 +499,7 @@ class Disorder:
|
|
|
499
499
|
return xml_to_html(self.rt)
|
|
500
500
|
|
|
501
501
|
|
|
502
|
-
class Formatter(ABC):
|
|
502
|
+
class Formatter(abc.ABC):
|
|
503
503
|
def __init__(self, options: Options, cif: CifContainer) -> None:
|
|
504
504
|
self.literature: dict[str, Reference] = {'finalcif' : ref.FinalCifReference(),
|
|
505
505
|
'ccdc' : ref.CCDCReference(),
|
|
@@ -513,17 +513,21 @@ class Formatter(ABC):
|
|
|
513
513
|
self._torsions = TorsionAngles(cif, without_h=options.without_h)
|
|
514
514
|
self._hydrogens = HydrogenBonds(cif)
|
|
515
515
|
|
|
516
|
+
@abc.abstractmethod
|
|
516
517
|
def get_bonds(self):
|
|
517
|
-
|
|
518
|
+
...
|
|
518
519
|
|
|
520
|
+
@abc.abstractmethod
|
|
519
521
|
def get_angles(self):
|
|
520
|
-
|
|
522
|
+
...
|
|
521
523
|
|
|
524
|
+
@abc.abstractmethod
|
|
522
525
|
def get_torsion_angles(self) -> list[dict[str, RichText]] | list[Torsion]:
|
|
523
|
-
|
|
526
|
+
...
|
|
524
527
|
|
|
528
|
+
@abc.abstractmethod
|
|
525
529
|
def get_hydrogen_bonds(self) -> list[dict[str, RichText]] | list[HydrogenBond]:
|
|
526
|
-
|
|
530
|
+
...
|
|
527
531
|
|
|
528
532
|
def get_bonds_angles_symminfo(self) -> str:
|
|
529
533
|
return self._bonds_angles.symminfo
|
|
@@ -537,8 +541,9 @@ class Formatter(ABC):
|
|
|
537
541
|
def get_crystallization_method(self, cif: CifContainer) -> str:
|
|
538
542
|
return string_to_utf8(gstr(cif['_exptl_crystal_recrystallization_method']))
|
|
539
543
|
|
|
544
|
+
@abc.abstractmethod
|
|
540
545
|
def get_radiation(self, cif: CifContainer) -> str | RichText:
|
|
541
|
-
|
|
546
|
+
...
|
|
542
547
|
|
|
543
548
|
def get_wavelength(self, cif: CifContainer) -> str:
|
|
544
549
|
try:
|
|
@@ -547,8 +552,9 @@ class Formatter(ABC):
|
|
|
547
552
|
except ValueError:
|
|
548
553
|
return ''
|
|
549
554
|
|
|
555
|
+
@abc.abstractmethod
|
|
550
556
|
def hkl_index_limits(self, cif: CifContainer) -> str:
|
|
551
|
-
|
|
557
|
+
...
|
|
552
558
|
|
|
553
559
|
def make_3d(self, cif: CifContainer, options: Options) -> str:
|
|
554
560
|
raise NotImplementedError
|
|
@@ -559,8 +565,9 @@ class Formatter(ABC):
|
|
|
559
565
|
def make_picture(self, options: Options, picfile: Path, tpl_doc: DocxTemplate):
|
|
560
566
|
raise NotImplementedError
|
|
561
567
|
|
|
568
|
+
@abc.abstractmethod
|
|
562
569
|
def format_sum_formula(self, sum_formula: str) -> str:
|
|
563
|
-
|
|
570
|
+
...
|
|
564
571
|
|
|
565
572
|
def hydrogen_atoms_refinement(self, cif: CifContainer) -> RichText | str:
|
|
566
573
|
"""
|
|
@@ -729,34 +736,45 @@ class Formatter(ABC):
|
|
|
729
736
|
self.literature['solution'] = ref.SHELXDReference()
|
|
730
737
|
return string_to_utf8(solution_prog.split('(')[0]).strip()
|
|
731
738
|
|
|
732
|
-
def
|
|
739
|
+
def t_minvalue(self, cif: CifContainer) -> str:
|
|
740
|
+
t_min = cif['_exptl_absorpt_correction_T_min']
|
|
741
|
+
with suppress(ValueError):
|
|
742
|
+
return f'{float(t_min):.4f}'
|
|
743
|
+
return '?'
|
|
744
|
+
|
|
745
|
+
def t_maxvalue(self, cif: CifContainer) -> str:
|
|
746
|
+
t_max = cif['_exptl_absorpt_correction_T_max']
|
|
733
747
|
with suppress(ValueError):
|
|
734
|
-
return f'{float(
|
|
735
|
-
return
|
|
748
|
+
return f'{float(t_max) :.4f}'
|
|
749
|
+
return '?'
|
|
736
750
|
|
|
737
|
-
def get_atomic_coordinates(self, cif: CifContainer) ->
|
|
751
|
+
def get_atomic_coordinates(self, cif: CifContainer) -> tuple[dict[str, str], ...]:
|
|
752
|
+
coords = []
|
|
738
753
|
for at in cif.atoms(without_h=False):
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
754
|
+
coords.append({
|
|
755
|
+
'label': at.label,
|
|
756
|
+
'type' : at.type,
|
|
757
|
+
'x' : at.x.replace('-', minus_sign),
|
|
758
|
+
'y' : at.y.replace('-', minus_sign),
|
|
759
|
+
'z' : at.z.replace('-', minus_sign),
|
|
760
|
+
'part' : at.part.replace('-', minus_sign),
|
|
761
|
+
'occ' : at.occ.replace('-', minus_sign),
|
|
762
|
+
'u_eq' : at.u_eq.replace('-', minus_sign)
|
|
763
|
+
})
|
|
764
|
+
return tuple(coords)
|
|
765
|
+
|
|
766
|
+
def get_displacement_parameters(self, cif: CifContainer) -> tuple[AdpWithMinus, ...]:
|
|
749
767
|
"""
|
|
750
|
-
|
|
768
|
+
Returns anisotropic displacement parameters with hyphens replaced by minus signs.
|
|
751
769
|
"""
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
770
|
+
return tuple(AdpWithMinus(label=label,
|
|
771
|
+
U11=u11.replace('-', minus_sign),
|
|
772
|
+
U22=u22.replace('-', minus_sign),
|
|
773
|
+
U33=u33.replace('-', minus_sign),
|
|
774
|
+
U12=u12.replace('-', minus_sign),
|
|
775
|
+
U13=u13.replace('-', minus_sign),
|
|
776
|
+
U23=u23.replace('-', minus_sign))
|
|
777
|
+
for label, u11, u22, u33, u23, u13, u12 in cif.displacement_parameters())
|
|
760
778
|
|
|
761
779
|
def get_completeness(self, cif: CifContainer) -> str:
|
|
762
780
|
try:
|
|
@@ -897,9 +915,13 @@ class HtmlFormatter(Formatter):
|
|
|
897
915
|
# spgrxml = s.to_mathml(cif.space_group)
|
|
898
916
|
except KeyError:
|
|
899
917
|
spgrxml = '<math xmlns="http://www.w3.org/1998/Math/MathML">?</math>'
|
|
900
|
-
|
|
918
|
+
try:
|
|
919
|
+
number = cif.spgr_number
|
|
920
|
+
except AttributeError:
|
|
921
|
+
return '?'
|
|
922
|
+
return f'{spgrxml} ({number})'
|
|
901
923
|
|
|
902
|
-
def make_picture(self, options: Options, picfile: Path, _: None):
|
|
924
|
+
def make_picture(self, options: Options, picfile: Path, _: None) -> str:
|
|
903
925
|
picture_path = ''
|
|
904
926
|
if options.report_text and picfile and picfile.exists():
|
|
905
927
|
picture_path = str(picfile.resolve())
|
|
@@ -1043,7 +1065,7 @@ class RichTextFormatter(Formatter):
|
|
|
1043
1065
|
radiation.add(radline, italic=True, subscript=True)
|
|
1044
1066
|
return radiation
|
|
1045
1067
|
|
|
1046
|
-
def make_picture(self, options: Options, picfile: Path, tpl_doc: DocxTemplate):
|
|
1068
|
+
def make_picture(self, options: Options, picfile: Path, tpl_doc: DocxTemplate) -> InlineImage | None:
|
|
1047
1069
|
if options.report_text and picfile and picfile.exists():
|
|
1048
1070
|
return InlineImage(tpl_doc, str(picfile.resolve()), width=Cm(options.picture_width))
|
|
1049
1071
|
return None
|
|
@@ -1138,6 +1160,7 @@ class TemplatedReport:
|
|
|
1138
1160
|
show_general_warning(parent=None, window_title='Warning', warn_text='Document generation failed',
|
|
1139
1161
|
info_text=str(e))
|
|
1140
1162
|
print(e)
|
|
1163
|
+
raise
|
|
1141
1164
|
return False
|
|
1142
1165
|
|
|
1143
1166
|
def make_templated_html_report(self,
|
|
@@ -1173,6 +1196,7 @@ class TemplatedReport:
|
|
|
1173
1196
|
except Exception as e:
|
|
1174
1197
|
show_general_warning(parent=None, window_title='Warning', warn_text='Document generation failed',
|
|
1175
1198
|
info_text=str(e))
|
|
1199
|
+
raise
|
|
1176
1200
|
return False
|
|
1177
1201
|
return True
|
|
1178
1202
|
|
|
@@ -1245,10 +1269,8 @@ class TemplatedReport:
|
|
|
1245
1269
|
'restraints' : this_or_quest(cif['_refine_ls_number_restraints']),
|
|
1246
1270
|
'parameters' : this_or_quest(cif['_refine_ls_number_parameters']),
|
|
1247
1271
|
'goof' : this_or_quest(cif['_refine_ls_goodness_of_fit_ref']),
|
|
1248
|
-
't_min' : self.text_formatter.
|
|
1249
|
-
|
|
1250
|
-
't_max' : self.text_formatter._tvalue(
|
|
1251
|
-
this_or_quest(cif['_exptl_absorpt_correction_T_max'])),
|
|
1272
|
+
't_min' : self.text_formatter.t_minvalue(cif),
|
|
1273
|
+
't_max' : self.text_formatter.t_maxvalue(cif),
|
|
1252
1274
|
'ls_R_factor_gt' : this_or_quest(cif['_refine_ls_R_factor_gt']),
|
|
1253
1275
|
'ls_wR_factor_gt' : this_or_quest(cif['_refine_ls_wR_factor_gt']),
|
|
1254
1276
|
'ls_R_factor_all' : this_or_quest(cif['_refine_ls_R_factor_all']),
|
|
@@ -1316,6 +1338,7 @@ if __name__ == '__main__':
|
|
|
1316
1338
|
data = Path('tests')
|
|
1317
1339
|
testcif = Path(data / 'examples/1979688.cif').absolute()
|
|
1318
1340
|
testcif = Path(r'test-data/p31c.cif').absolute()
|
|
1341
|
+
testcif = Path(r"D:\Downloads\9008564.cif").absolute()
|
|
1319
1342
|
cif = CifContainer(testcif)
|
|
1320
1343
|
|
|
1321
1344
|
pic = pathlib.Path("screenshots/finalcif_checkcif.png")
|
|
@@ -76,7 +76,13 @@
|
|
|
76
76
|
used {{ radiation }} radiation {% if wavelength %}(λ = {{ wavelength }} Å){% endif %}.
|
|
77
77
|
All data were integrated with {{ integration_progr }} yielding {{ cif._diffrn_reflns_number }}
|
|
78
78
|
reflections of which {{ cif._reflns_number_total }} where independent and
|
|
79
|
-
{
|
|
79
|
+
{% set gt = cif._reflns_number_gt | float %}
|
|
80
|
+
{% set total = cif._reflns_number_total | float %}
|
|
81
|
+
{% if total > 0 %}
|
|
82
|
+
{{ (gt / total * 100) | round(1) }} %
|
|
83
|
+
{% else %}
|
|
84
|
+
n/a
|
|
85
|
+
{% endif %}
|
|
80
86
|
were greater than 2σ(<i>F</i><sup>2</sup>).<sup>[{{ literature.integration|ref_num }}]</sup> A
|
|
81
87
|
{{ abstype }} absorption correction using {{ abs_details }} was applied.<sup>[{{ literature.absorption|ref_num }}]</sup>
|
|
82
88
|
The structure was solved by
|
|
@@ -43,7 +43,7 @@ class PlatonRunner(QtCore.QObject):
|
|
|
43
43
|
self.cif_file.with_suffix('.chk').unlink(missing_ok=True)
|
|
44
44
|
self.process.start(self.platon_exe, ["-U", str(self.cif_file.name)])
|
|
45
45
|
|
|
46
|
-
def _onfinished(self):
|
|
46
|
+
def _onfinished(self) -> None:
|
|
47
47
|
self._on_ready_read()
|
|
48
48
|
# os.chdir(self._origdir)
|
|
49
49
|
self._parse_chk_file()
|
|
@@ -51,11 +51,11 @@ class PlatonRunner(QtCore.QObject):
|
|
|
51
51
|
self.finished.emit(True)
|
|
52
52
|
self.delete_orphaned_files()
|
|
53
53
|
|
|
54
|
-
def _on_ready_read(self):
|
|
54
|
+
def _on_ready_read(self) -> None:
|
|
55
55
|
output = self.process.readAllStandardOutput().data().decode()
|
|
56
56
|
self.log_widget.appendPlainText(output)
|
|
57
57
|
|
|
58
|
-
def _monitor_output_log(self):
|
|
58
|
+
def _monitor_output_log(self) -> None:
|
|
59
59
|
while not self.is_stopped:
|
|
60
60
|
self.tick.emit('#')
|
|
61
61
|
time.sleep(0.3)
|
|
@@ -68,13 +68,13 @@ class PlatonRunner(QtCore.QObject):
|
|
|
68
68
|
except FileNotFoundError:
|
|
69
69
|
break
|
|
70
70
|
|
|
71
|
-
def _stop_program(self):
|
|
71
|
+
def _stop_program(self) -> None:
|
|
72
72
|
self.is_stopped = True
|
|
73
73
|
# if self.process and self.process.state() == QProcess.Running:
|
|
74
74
|
self.process.terminate()
|
|
75
75
|
self.finished.emit(True)
|
|
76
76
|
|
|
77
|
-
def _parse_chk_file(self):
|
|
77
|
+
def _parse_chk_file(self) -> None:
|
|
78
78
|
try:
|
|
79
79
|
self.chk_file_text = self.cif_file.with_suffix('.chk').read_text(encoding='latin1', errors='ignore')
|
|
80
80
|
except FileNotFoundError as e:
|
|
@@ -89,6 +89,9 @@ class PlatonRunner(QtCore.QObject):
|
|
|
89
89
|
|
|
90
90
|
@property
|
|
91
91
|
def platon_exe(self) -> str:
|
|
92
|
+
special_platon = Path(__file__).resolve().parent.parent.parent.joinpath('platon/platon_special.exe')
|
|
93
|
+
if special_platon.exists():
|
|
94
|
+
return str(special_platon)
|
|
92
95
|
if sys.platform.startswith('win'):
|
|
93
96
|
in_pwt = r'C:\pwt\platon.exe'
|
|
94
97
|
else:
|
|
@@ -103,10 +106,10 @@ class PlatonRunner(QtCore.QObject):
|
|
|
103
106
|
def kill(self):
|
|
104
107
|
if sys.platform.startswith('win'):
|
|
105
108
|
with suppress(FileNotFoundError):
|
|
106
|
-
subprocess.run(["taskkill", "/f", "/im", "platon.exe"], shell=False)
|
|
109
|
+
subprocess.run(["taskkill", "/f", "/im", "platon.exe"], check=False, shell=False)
|
|
107
110
|
if sys.platform[:5] in ('linux', 'darwi'):
|
|
108
111
|
with suppress(FileNotFoundError):
|
|
109
|
-
subprocess.run(["killall", "platon"], shell=False)
|
|
112
|
+
subprocess.run(["killall", "platon"], check=False, shell=False)
|
|
110
113
|
|
|
111
114
|
def delete_orphaned_files(self):
|
|
112
115
|
# delete orphaned files:
|