def check_if_loop_and_row_size_fit_together(self, gemmi_loop, row): if gemmi_loop.width() == len(row): gemmi_loop.add_row(row) else: show_general_warning( 'An author loop with different size is already in the CIF. Can not proceed.' )
def import_equipment_from_file(self, filename='') -> None: """ Import an equipment entry from a cif file. """ if not filename: filename = cif_file_open_dialog( filter="CIF file (*.cif *.cif_od *.cfx)") if not filename: print('No file given') return try: doc = cif.read_file(filename) except RuntimeError as e: show_general_warning(str(e)) return block = doc.sole_block() table_data = [] for item in block: if item.pair is not None: key, value = item.pair if filename.endswith( '.cif_od') and key not in include_equipment_imports: continue table_data.append([ key, retranslate_delimiter( cif.as_string(value).strip('\n\r ;')) ]) if filename.endswith('.cif_od'): name = Path(filename).stem else: name = block.name.replace('__', ' ') self.settings.save_settings_list('equipment', name, table_data) self.show_equipment()
def export_equipment_template(self, filename: str = None) -> None: """ Exports the currently selected equipment entry to a file. In order to export, we have to run self.edit_equipment_template() first! """ selected_template, table_data = self.get_equipment_entry_data() if not selected_template: return blockname = '__'.join(selected_template.split()) if not filename: filename = cif_file_save_dialog( blockname.replace('__', '_') + '.cif') if not filename.strip(): return equipment_cif = CifContainer(filename, new_block=blockname) for key, value in table_data: equipment_cif[key] = value.strip('\n\r ') try: equipment_cif.save(filename) # Path(filename).write_text(doc.as_string(cif.Style.Indent35)) except PermissionError: if Path(filename).is_dir(): return show_general_warning('No permission to write file to {}'.format( Path(filename).resolve()))
def _set_external_hkl_file(self) -> None: file = cif_file_open_dialog(filter="HKL file (*.hkl *.fcf)") if file.endswith('.hkl'): if self.cif.res_file_data: hklf = self.cif.hklf_number_from_shelxl_file() else: hklf = 4 self.hkl_file = io.StringIO( HKL(file, self.cif.block.name, hklf_type=hklf).hkl_as_cif) self.hkl_file.name = Path(file).name elif file.endswith('.fcf'): cif = CifContainer(file) list_code = cif['_shelx_refln_list_code'] if list_code != '4': show_general_warning( 'Only plain hkl or fcf (LIST 4 style) files should be uploaded.' ) return self.hkl_file = io.StringIO(Path(file).read_text()) self.hkl_file.name = Path(file).name elif file == '': self.hkl_file = None else: show_general_warning( 'Only plain hkl or fcf (LIST 4 style) files should be uploaded.' )
def import_author(self, filename=''): """ Import an author from a cif file. """ cif_auth_to_str = { '_publ_contact_author_name': 'name', '_publ_contact_author_address': 'address', '_publ_contact_author_email': 'email', '_publ_contact_author_phone': 'phone', '_publ_contact_author_id_orcid': 'orcid', # '_publ_author_name': 'name', '_publ_author_address': 'address', '_publ_author_email': 'email', '_publ_author_phone': 'phone', '_publ_author_id_orcid': 'orcid', '_publ_author_footnote': 'footnote', } if not filename: filename = cif_file_open_dialog(filter="CIF file (*.cif)") if not filename: return try: doc = read_file(filename) except RuntimeError as e: show_general_warning(str(e)) return block = doc.sole_block() table_data = {} for item in block: if item.pair is not None: key, value = item.pair if key not in cif_auth_to_str: continue key = cif_auth_to_str.get(key) table_data.update({ key: retranslate_delimiter(as_string(value).strip('\n\r ;')) }) name = block.name.replace('__', ' ') if 'contact author' in name: table_data.update({'contact': True}) if not table_data.get('name'): return None self.general_author_save(table_data) self.show_author_loops()
def import_property_from_file(self, filename: str = '') -> None: """ Imports a cif file as entry of the property templates list. """ if not filename: filename = cif_file_open_dialog(filter="CIF file (*.cif)") if not filename: return try: doc = cif.read_file(filename) except RuntimeError as e: show_general_warning(str(e)) return property_list = self.settings.settings.value('property_list') if not property_list: property_list = [''] block = doc.sole_block() template_list = [] loop_column_name = '' for i in block: if i.loop is not None: if len(i.loop.tags) > 0: loop_column_name = i.loop.tags[0] for n in range(i.loop.length()): value = i.loop.val(n, 0) template_list.append( retranslate_delimiter( cif.as_string(value).strip("\n\r ;"))) block_name = block.name.replace('__', ' ') # This is the list shown in the Main menu: property_list.append(block_name) table = self.app.ui.PropertiesEditTableWidget table.setRowCount(0) self.app.ui.cifKeywordLineEdit.setText(loop_column_name) newlist = [x for x in list(set(property_list)) if x] newlist.sort() # this list keeps track of the property items: self.settings.save_template_list('property_list', newlist) template_list.insert(0, '') template_list = list(set(template_list)) # save as dictionary for properties to have "_cif_key : itemlist" # for a table item as dropdown menu in the main table. table_data = [loop_column_name, template_list] self.settings.save_template_list('property/' + block_name, table_data) self.show_properties()
def export_property_template(self, filename: str = '') -> None: """ Exports the currently selected property entry to a file. """ selected_row_text = self.app.ui.PropertiesTemplatesListWidget.currentIndex( ).data() if not selected_row_text: return prop_data = self.settings.load_settings_list('property', selected_row_text) table_data = [] cif_key = '' if prop_data: cif_key = prop_data[0] with suppress(Exception): table_data = prop_data[1] if not cif_key: return doc = cif.Document() blockname = '__'.join(selected_row_text.split()) block = doc.add_new_block(blockname) try: loop = block.init_loop(cif_key, ['']) except RuntimeError: # Not a valid loop key show_general_warning( '"{}" is not a valid cif keyword.'.format(cif_key)) return for value in table_data: if value: loop.add_row([cif.quote(utf8_to_str(value))]) if not filename: filename = cif_file_save_dialog( blockname.replace('__', '_') + '.cif') if not filename.strip(): return try: doc.write_file(filename, style=cif.Style.Indent35) # Path(filename).write_text(doc.as_string(cif.Style.Indent35)) except PermissionError: if Path(filename).is_dir(): return show_general_warning('No permission to write file to {}'.format( Path(filename).resolve()))
def save_equipment_template(self) -> None: """ Saves the currently selected equipment template to the config file. """ selected_template_text, table_data = self.get_equipment_entry_data() # warn if key is not official: for key, _ in table_data: if key not in cif_all_dict: if not key.startswith('_'): show_general_warning( '"{}" is not a valid keyword! ' '\nChange the name in order to save.\n' 'Keys must start with an underscore.'.format(key)) return show_general_warning( '"{}" is not an official CIF keyword!'.format(key)) self.settings.save_settings_list('equipment', selected_template_text, table_data) self.app.ui.EquipmentTemplatesStackedWidget.setCurrentIndex(0) print('saved')
def export_author_template(self, filename: str = None) -> None: """ Exports the currently selected author to a file. """ author = self.get_author_info() selected_template = self.ui.LoopTemplatesListWidget.currentIndex( ).data() if not selected_template: return blockname = '__'.join(selected_template.split()) if not filename: filename = cif_file_save_dialog( blockname.replace('__', '_') + '.cif') if not filename.strip(): return author_cif = CifContainer(filename, new_block=blockname) contact_author: bool = author.get('contact') loop = self.get_author_loop(contact_author) data = [ author.get('name'), author.get('address'), author.get('email'), author.get('phone'), author.get('orcid'), author.get('footnote') ] if contact_author: del data[-1] for key, value in zip(loop, data): author_cif.set_pair_delimited(key, as_string(value)) try: author_cif.save(filename) except PermissionError: if Path(filename).is_dir(): return show_general_warning('No permission to write file to {}'.format( Path(filename).resolve()))
def __init__(self, app, cif: CifContainer): super(BrukerData, self).__init__() self.cif = cif self.app = app self.basename = cif.fileobj.stem.split('_0m')[0] self.saint_data = SaintListFile(name_patt='*_0*m._ls') # This is only in this list file, not in the global: saint_first_ls = SaintListFile(name_patt='*_01._ls') sol = SolutionProgram(cif) solution_program = None if 'shelx' in self.cif.block.find_value('_audit_creation_method').lower(): shelx = 'Sheldrick, G.M. (2015). Acta Cryst. A71, 3-8.\nSheldrick, G.M. (2015). Acta Cryst. C71, 3-8.\n' else: shelx = '' if cif.res_file_data: if cif.dsr_used: dsr = 'The program DSR was used for model building:\n' \ 'D. Kratzert, I. Krossing, J. Appl. Cryst. 2018, 51, 928-934. doi: 10.1107/S1600576718004508' shelx += dsr abstype = '?' t_min = '?' t_max = '?' # Going back from last dataset: for n in range(1, len(self.sadabs.datasets) + 1): try: abstype = 'numerical' if self.sadabs.dataset(-n).numerical else 'multi-scan' t_min = min(self.sadabs.dataset(-n).transmission) t_max = max(self.sadabs.dataset(-n).transmission) if all([abstype, t_min, t_max]): break except (KeyError, AttributeError, TypeError): pass # print('No .abs file found.') # no abs file found # the lower temp is more likely: try: temp1 = self.frame_header.temperature except (AttributeError, KeyError, FileNotFoundError): temp1 = 293 try: kilovolt = self.frame_header.kilovolts except (AttributeError, KeyError, FileNotFoundError): kilovolt = '' try: milliamps = self.frame_header.milliamps except (AttributeError, KeyError, FileNotFoundError): milliamps = '' try: frame_name = self.frame_header.filename.name except FileNotFoundError: frame_name = '' if self.cif.solution_program_details: solution_program = (self.cif.solution_program_details, self.cif.fileobj.name) if self.cif['_computing_structure_solution']: solution_program = (gcif.as_string(self.cif['_computing_structure_solution']), self.cif.fileobj.name) if not solution_program: solution_program = (sol.program.version, Path(sol.program.filename).name) if self.cif.absorpt_process_details: absdetails = (self.cif.absorpt_process_details, self.cif.fileobj.name) else: absdetails = (self.sadabs.version, self.sadabs.filename.name) if self.cif.absorpt_correction_type: abscorrtype = (self.cif.absorpt_correction_type, self.cif.fileobj.name) else: abscorrtype = (abstype, self.sadabs.filename.name) if self.cif.absorpt_correction_t_max: abs_tmax = (self.cif.absorpt_correction_t_max, self.cif.fileobj.name) else: abs_tmax = (str(t_max), self.sadabs.filename.name) if self.cif.absorpt_correction_t_min: abs_tmin = (self.cif.absorpt_correction_t_min, self.cif.fileobj.name) else: abs_tmin = (str(t_min), self.sadabs.filename.name) if self.sadabs.Rint: rint = (self.sadabs.Rint, self.sadabs.filename.name) self.sources['_diffrn_reflns_av_R_equivalents'] = rint temp2 = self.p4p.temperature temperature = round(min([temp1, temp2]), 1) if temperature < 0.01: temperature = '' if (self.cif['_diffrn_ambient_temperature'].split('(')[0] or self.cif['_cell_measurement_temperature']).split('(')[0] == '0': show_general_warning('<b>Warning of impossible temperature specification</b>:<br>' 'You probably entered −273.15 °C instead ' 'of −173.15 °C into the SHELX instruction file.<br>' 'A temperature of 0 K is likely to be wrong.') try: if abs(int(self.cif['_diffrn_ambient_temperature'].split('(')[0]) - int(temperature)) >= 2 and \ not self.app.temperature_warning_displayed: self.app.temperature_warning_displayed = True show_general_warning('<b>Warning</b>: The temperature from the measurement and ' 'from SHELX differ. Please double-check for correctness.<br><br>' 'SHELX says: {} K<br>' 'The P4P file says: {} K<br>' 'Frame header says: {} K<br><br>' 'You may add a ' '<a href="http://shelx.uni-goettingen.de/shelxl_html.php#TEMP">TEMP</a> ' 'instruction to your SHELX file (in °C).' .format(self.cif['_diffrn_ambient_temperature'].split('(')[0], round(temp2, 1), round(temp1, 1))) except ValueError: # most probably one value is '?' pass if not self.cif['_space_group_name_H-M_alt']: try: self.sources['_space_group_name_H-M_alt'] = ( self.cif.space_group, 'Calculated by gemmi: https://gemmi.readthedocs.io') except AttributeError: pass if not self.cif['_space_group_name_Hall']: with suppress(AttributeError): self.sources['_space_group_name_Hall'] = ( self.cif.hall_symbol, 'Calculated by gemmi: https://gemmi.readthedocs.io') if not self.cif['_space_group_IT_number']: with suppress(AttributeError): self.sources['_space_group_IT_number'] = ( self.cif.spgr_number_from_symmops, 'Calculated by gemmi: https://gemmi.readthedocs.io') if not self.cif['_space_group_crystal_system']: with suppress(AttributeError): csystem = self.cif.crystal_system self.sources['_space_group_crystal_system'] = ( csystem, 'calculated by gemmi: https://gemmi.readthedocs.io') if not self.cif.symmops and self.cif.symmops_from_spgr: loop = self.cif.block.init_loop('_space_group_symop_operation_', ['xyz']) for symmop in reversed(self.cif.symmops_from_spgr): loop.add_row([gcif.quote(symmop)]) # All sources that are not filled with data will be yellow in the main table # data tooltip self.sources['_cell_measurement_reflns_used'] = ( self.saint_data.cell_reflections, self.saint_data.filename.name) self.sources['_cell_measurement_theta_min'] = ( self.saint_data.cell_res_min_theta or '', self.saint_data.filename.name) self.sources['_cell_measurement_theta_max'] = ( self.saint_data.cell_res_max_theta or '', self.saint_data.filename.name) self.sources['_computing_data_collection'] = (saint_first_ls.aquire_software, saint_first_ls.filename.name) self.sources['_computing_cell_refinement'] = (self.saint_data.version, self.saint_data.filename.name) self.sources['_computing_data_reduction'] = (self.saint_data.version, self.saint_data.filename.name) self.sources['_exptl_absorpt_correction_type'] = abscorrtype self.sources['_exptl_absorpt_correction_T_min'] = abs_tmin self.sources['_exptl_absorpt_correction_T_max'] = abs_tmax self.sources['_exptl_absorpt_process_details'] = absdetails self.sources['_cell_measurement_temperature'] = (temperature, self.p4p.filename.name) self.sources['_diffrn_ambient_temperature'] = (temperature, self.p4p.filename.name) self.sources['_exptl_crystal_colour'] = (self.p4p.crystal_color, self.p4p.filename.name) self.sources['_exptl_crystal_description'] = (self.p4p.morphology, self.p4p.filename.name) self.sources['_exptl_crystal_size_min'] = (self.p4p.crystal_size[0] or '', self.p4p.filename.name) self.sources['_exptl_crystal_size_mid'] = (self.p4p.crystal_size[1] or '', self.p4p.filename.name) self.sources['_exptl_crystal_size_max'] = (self.p4p.crystal_size[2] or '', self.p4p.filename.name) self.sources['_computing_structure_solution'] = solution_program self.sources['_atom_sites_solution_primary'] = (sol.method, 'Inherited from solution program.') self.sources['_diffrn_source_voltage'] = (kilovolt or '', frame_name) self.sources['_diffrn_source_current'] = (milliamps or '', frame_name) self.sources['_chemical_formula_moiety'] = ('', '') self.sources['_publ_section_references'] = (shelx, '') self.sources['_refine_special_details'] = ('', '') self.sources['_exptl_crystal_recrystallization_method'] = ('', '') if not self.cif.is_centrosymm: self.sources['_chemical_absolute_configuration'] = ('', '') if self.saint_data.is_twin and self.saint_data.components_firstsample == 2: with suppress(Exception): law = self.saint_data.twinlaw[list(self.saint_data.twinlaw.keys())[0]] self.sources['_twin_individual_twin_matrix_11'] = (str(law[0][1]), self.saint_data.filename.name) self.sources['_twin_individual_twin_matrix_12'] = (str(law[0][2]), self.saint_data.filename.name) self.sources['_twin_individual_twin_matrix_13'] = (str(law[0][0]), self.saint_data.filename.name) self.sources['_twin_individual_twin_matrix_21'] = (str(law[1][1]), self.saint_data.filename.name) self.sources['_twin_individual_twin_matrix_22'] = (str(law[1][2]), self.saint_data.filename.name) self.sources['_twin_individual_twin_matrix_23'] = (str(law[1][0]), self.saint_data.filename.name) self.sources['_twin_individual_twin_matrix_31'] = (str(law[2][1]), self.saint_data.filename.name) self.sources['_twin_individual_twin_matrix_32'] = (str(law[2][2]), self.saint_data.filename.name) self.sources['_twin_individual_twin_matrix_33'] = (str(law[2][0]), self.saint_data.filename.name) self.sources['_twin_individual_id'] = ( str(self.saint_data.components_firstsample), self.saint_data.filename.name) self.sources['_twin_special_details'] = ( 'The data was integrated as a 2-component twin.', self.saint_data.filename.name)