def test_checksum_test_without_checksum(self): self.assertEqual( True, CifContainer('test-data/1000006.cif').test_res_checksum()) self.assertEqual( True, CifContainer('test-data/1000006.cif').test_hkl_checksum())
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 test_loop_edit_one_single_field(self): model = self.myapp.ui.LoopsTabWidget.widget(self.get_index_of('Scattering')).model() print(self.myapp.ui.LoopsTabWidget.tabText(4)) model.setData(model.index(0, 2), 'foo bar', role=Qt.EditRole) self.myapp.ui.SaveCifButton.click() c = CifContainer(self.myapp.final_cif_file_name) self.assertEqual('foo bar', as_string(c.loops[3].val(0, 2)))
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.' )
class CifFileCRCTestCase(unittest.TestCase): def setUp(self) -> None: current_file_path() self.cif = CifContainer(Path('tests/examples/1979688.cif')) def test_calc_crc(self): self.assertEqual(20714, self.cif.calc_checksum(self.cif['_shelx_hkl_file']))
def open_cif_file(cif_fileobj) -> Union[None, CifContainer]: cif = None try: cif = CifContainer(cif_fileobj) except Exception as e: print('Unable to open file', cif_fileobj.name) print(e) return None return cif
def get_atomic_coordinates(self, cif: CifContainer): for at in cif.atoms(without_h=False): yield {'label': at.label, 'type' : at.type, 'x' : at.x.replace('-', minus_sign), 'y' : at.y.replace('-', minus_sign), 'z' : at.z.replace('-', minus_sign), 'part' : at.part.replace('-', minus_sign), 'occ' : at.occ.replace('-', minus_sign), 'u_eq' : at.u_eq.replace('-', minus_sign)}
def setUp(self) -> None: os.chdir(Path(__file__).absolute().parent.parent) self.cif1 = CifContainer('tests/examples/1979688.cif') self.cif2 = CifContainer( 'tests/examples/work/cu_BruecknerJK_153F40_0m.cif') self.first_result = """data_cu_BruecknerJK_153F40_0m loop_ _refln_index_h _refln_index_k _refln_index_l _refln_F_squared_meas _refln_F_squared_sigma _refln_scale_group_code 1 0 0 0.36031 0.34981 12 -1 0 0 -0.0279 0.03389 7 -1 0 0 0.09539 0.01993 4 2 0 0 267.703 5.73431 4 -""" self.last_result = """ 11.9484 0.44464 6
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 test_loop_no_edit(self): self.myapp.ui.SaveCifButton.click() c = CifContainer(self.myapp.final_cif_file_name) self.assertEqual('0.0181', c.loops[3].val(0, 2))
def make_templated_report(self, options: Options, file_obj: Path, output_filename: str, picfile: Path, template_path: Path): cif = CifContainer(file_obj) tpl_doc = DocxTemplate(Path(__file__).parent.parent.joinpath(template_path)) ba = BondsAndAngles(cif, without_h=options.without_h) t = TorsionAngles(cif, without_h=options.without_h) h = HydrogenBonds(cif) context = {'options' : options, # {'without_h': True, 'atoms_table': True, 'text': True, 'bonds_table': True}, 'cif' : cif, 'space_group' : self.space_group_subdoc(tpl_doc, cif), 'structure_figure' : self.make_picture(options, picfile, tpl_doc), 'crystallization_method': remove_line_endings(retranslate_delimiter( cif['_exptl_crystal_recrystallization_method'])) or '[No crystallization method given!]', 'sum_formula' : self.format_sum_formula(cif['_chemical_formula_sum'].replace(" ", "")), 'itnum' : cif['_space_group_IT_number'], 'crystal_size' : this_or_quest(cif['_exptl_crystal_size_min']) + timessym + this_or_quest(cif['_exptl_crystal_size_mid']) + timessym + this_or_quest(cif['_exptl_crystal_size_max']), 'crystal_colour' : this_or_quest(cif['_exptl_crystal_colour']), 'crystal_shape' : this_or_quest(cif['_exptl_crystal_description']), 'radiation' : self.get_radiation(cif), 'wavelength' : cif['_diffrn_radiation_wavelength'], 'theta_range' : self.get_from_to_theta_range(cif), 'diffr_type' : gstr(cif['_diffrn_measurement_device_type']) or '[No measurement device type given]', 'diffr_device' : gstr(cif['_diffrn_measurement_device']) or '[No measurement device given]', 'diffr_source' : gstr(cif['_diffrn_source']).strip('\n\r') or '[No radiation source given]', 'monochromator' : gstr(cif['_diffrn_radiation_monochromator']) \ or '[No monochromator type given]', 'detector' : gstr(cif['_diffrn_detector_type']) \ or '[No detector type given]', 'lowtemp_dev' : gstr(cif['_olex2_diffrn_ambient_temperature_device']) \ or '', 'index_ranges' : self.hkl_index_limits(cif), 'indepentent_refl' : this_or_quest(cif['_reflns_number_total']), 'r_int' : this_or_quest(cif['_diffrn_reflns_av_R_equivalents']), 'r_sigma' : this_or_quest(cif['_diffrn_reflns_av_unetI/netI']), 'completeness' : self.get_completeness(cif), 'theta_full' : cif['_diffrn_reflns_theta_full'], 'data' : this_or_quest(cif['_refine_ls_number_reflns']), 'restraints' : this_or_quest(cif['_refine_ls_number_restraints']), 'parameters' : this_or_quest(cif['_refine_ls_number_parameters']), 'goof' : this_or_quest(cif['_refine_ls_goodness_of_fit_ref']), 'ls_R_factor_gt' : this_or_quest(cif['_refine_ls_R_factor_gt']), 'ls_wR_factor_gt' : this_or_quest(cif['_refine_ls_wR_factor_gt']), 'ls_R_factor_all' : this_or_quest(cif['_refine_ls_R_factor_all']), 'ls_wR_factor_ref' : this_or_quest(cif['_refine_ls_wR_factor_ref']), 'diff_dens_min' : self.get_diff_density_min(cif).replace('-', minus_sign), 'diff_dens_max' : self.get_diff_density_max(cif).replace('-', minus_sign), 'exti' : self.get_exti(cif), 'flack_x' : self.get_flackx(cif), 'integration_progr' : self.get_integration_program(cif), 'abstype' : gstr(cif['_exptl_absorpt_correction_type']) or '??', 'abs_details' : self.get_absortion_correction_program(cif), 'solution_method' : self.solution_method(cif), 'solution_program' : self.solution_program(cif), 'refinement_prog' : self.refinement_prog(cif), 'atomic_coordinates' : self.get_atomic_coordinates(cif), 'bonds' : ba.bonds, 'angles' : ba.angles, 'ba_symminfo' : ba.symminfo, 'torsions' : t.torsion_angles, 'torsion_symminfo' : t.symminfo, 'hydrogen_bonds' : h.hydrogen_bonds, 'hydrogen_symminfo' : h.symminfo, 'literature' : self.literature } # Filter definition for {{foobar|filter}} things: jinja_env = jinja2.Environment() jinja_env.filters['inv_article'] = get_inf_article tpl_doc.render(context, jinja_env=jinja_env, autoescape=True) tpl_doc.save(output_filename)
def test_has_isotropic_displacement_parameters(self): cif = CifContainer('test-data/1923_Aminoff, G._Ni As_P 63.m m c_Nickel arsenide.cif') h = Hydrogens(cif, self.paragraph) self.assertEqual(2, h.number_of_isotropic_atoms())
def test_has_no_isotropic_displacement_parameters(self): cif = CifContainer('test-data/p21c.cif') h = Hydrogens(cif, self.paragraph) self.assertEqual(0, h.number_of_isotropic_atoms())
def add_coords_table(document: Document, cif: CifContainer, table_num: int): """ Adds the table with the atom coordinates. :param document: The current word document. :param cif: the cif object from CifContainer. :return: None """ atoms = list(cif.atoms()) table_num += 1 headline = "Table {}. Atomic coordinates and ".format(table_num) h = document.add_heading(headline, 2) h.add_run('U').font.italic = True h.add_run('eq').font.subscript = True h.add_run('{}[{}'.format(protected_space, angstrom)) h.add_run('2').font.superscript = True h.add_run('] for {}'.format(cif.block.name)) coords_table = document.add_table(rows=len(atoms) + 1, cols=5, style='Table Grid') # Atom x y z U(eq) head_row = coords_table.rows[0] head_row.cells[0].paragraphs[0].add_run('Atom').bold = True px = head_row.cells[1].paragraphs[0] ar = px.add_run('x') ar.bold = True ar.italic = True py = head_row.cells[2].paragraphs[0] ar = py.add_run('y') ar.bold = True ar.italic = True pz = head_row.cells[3].paragraphs[0] ar = pz.add_run('z') ar.bold = True ar.italic = True pu = head_row.cells[4].paragraphs[0] ar = pu.add_run('U') ar.bold = True ar.italic = True ar2 = pu.add_run('eq') ar2.bold = True ar2.font.subscript = True # having a list of column cells before is *much* faster! col0_cells = coords_table.columns[0].cells col1_cells = coords_table.columns[1].cells col2_cells = coords_table.columns[2].cells col3_cells = coords_table.columns[3].cells col4_cells = coords_table.columns[4].cells rowidx = 1 for at in atoms: c0, c1, c2, c3, c4 = col0_cells[rowidx], col1_cells[rowidx], col2_cells[rowidx], \ col3_cells[rowidx], col4_cells[rowidx] rowidx += 1 c0.text = at[0] # label c1.text = (str(at[2])) # x c2.text = (str(at[3])) # y c3.text = (str(at[4])) # z c4.text = (str(at[7])) # ueq p = document.add_paragraph() p.style = document.styles['tabunterschr'] p.add_run('U').font.italic = True p.add_run('eq').font.subscript = True p.add_run(' is defined as 1/3 of the trace of the orthogonalized ') p.add_run('U').font.italic = True ij = p.add_run('ij') ij.font.subscript = True ij.font.italic = True p.add_run(' tensor.') set_column_width(coords_table.columns[0], Cm(2.3)) set_column_width(coords_table.columns[1], Cm(2.8)) set_column_width(coords_table.columns[2], Cm(2.8)) set_column_width(coords_table.columns[3], Cm(2.8)) set_column_width(coords_table.columns[4], Cm(2.8)) document.add_paragraph() return table_num
def setUp(self) -> None: os.chdir(Path(__file__).absolute().parent.parent) self.cif = CifContainer(Path('test-data/DK_zucker2_0m.cif'))
def setUp(self) -> None: os.chdir(Path(__file__).absolute().parent.parent) self.cif = CifContainer( Path('tests/examples/work/cu_BruecknerJK_153F40_0m.cif'))
def make_report_from(options: Options, file_obj: Path, output_filename: str = None, picfile: Path = None) -> str: """ Creates a tabular cif report. :param file_obj: Input cif file. :param output_filename: the table is saved to this file. """ document = create_document() ref: Union[ReferenceList, None] = None if file_obj.exists(): try: cif = CifContainer(file_obj) except Exception as e: print('Unable to open cif file:') print(e) raise else: raise FileNotFoundError if not cif: print('Something failed during cif file saving.') return '' if not options.report_text: document.add_heading('Structure Tables for {}'.format(cif.block.name), 1) else: document.add_heading('Structure Tables', 1) make_columns_section(document, columns='2') if options.report_text: if picfile and picfile.exists(): add_picture(document, options, picfile) ref = make_report_text(cif, document) # -- The residuals table: table_num = 1 if options.report_text: # I have to do the header and styling here, otherwise I get another paragraph with a line break in front of the heading. p = document.add_paragraph(style='Heading 2') p.add_run().add_break(WD_BREAK.COLUMN) tab0_head = r"Table {}. Crystal data and structure refinement for {}".format( table_num, cif.block.name) p.add_run(text=tab0_head) table_num = add_residuals_table(document, cif, table_num) p = document.add_paragraph() p.add_run().add_break(WD_BREAK.PAGE) if options.report_text: make_columns_section(document, columns='1') table_num = add_coords_table(document, cif, table_num) if cif.symmops: if len(list(cif.bonds())) + len(list(cif.angles())) > 0: table_num += 1 document.add_heading( r"Table {}. Bond lengths and angles for {}".format( table_num, cif.block.name), 2) make_columns_section(document, columns='2') ba = BondsAndAngles(cif, without_h=options.without_h) table_num = add_bonds_and_angles_table(document, table_num, ba) if len(list(cif.torsion_angles())) > 0: make_columns_section(document, columns='1') table_num += 1 document.add_heading( r"Table {}. Torsion angles for {}".format( table_num, cif.block.name), 2) make_columns_section(document, columns='2') tors = TorsionAngles(cif, without_h=options.without_h) table_num = add_torsion_angles(document, table_num, tors) make_columns_section(document, columns='1') if len(list(cif.hydrogen_bonds())) > 0: table_num += 1 h = HydrogenBonds(cif) document.add_heading( r"Table {}. Hydrogen bonds for {}".format( table_num, cif.block.name), 2) table_num = add_hydrogen_bonds(document, table_num, h) document.add_paragraph('') else: make_columns_section(document, columns='1') document.add_paragraph( 'No further tables, because symmetry operators ' '(_space_group_symop_operation_xyz) are missing.') if options.report_text: # -- Bibliography: document.add_heading('Bibliography', 2) ref.make_literature_list(document) document.save(output_filename) print('\nTables finished - output file: {}'.format(output_filename)) return file_obj.name
class CifFileTestCase(unittest.TestCase): def setUp(self) -> None: current_file_path() self.cif = CifContainer(Path('tests/examples/1979688.cif')) def test_calc_crc(self): self.assertEqual(3583, self.cif.calc_checksum('hello world')) def test_res_crc(self): self.assertEqual(17612, self.cif.res_checksum_calcd) def test_hkl_crc(self): self.assertEqual(20714, self.cif.hkl_checksum_calcd) def test_res_crc_without_res(self): self.assertEqual( 0, CifContainer(Path('test-data/1000006.cif')).res_checksum_calcd) def test_get_unknown_value_from_key(self): self.assertEqual('', self.cif['_chemical_melting_point']) def test_get_known_value_from_key(self): self.assertEqual('702.70', self.cif['_chemical_formula_weight']) def test_get_spgr(self): self.assertEqual('P 21 21 2', self.cif.space_group) def test_symmops(self): self.assertEqual( ['x, y, z', '-x, -y, z', '-x+1/2, y+1/2, -z', 'x+1/2, -y+1/2, -z'], self.cif.symmops) def test_symmops_from_spgr(self): self.assertEqual( ['x,y,z', '-x,-y,z', 'x+1/2,-y+1/2,-z', '-x+1/2,y+1/2,-z'], self.cif.symmops_from_spgr) def test_centrosymm(self): self.assertEqual(False, self.cif.is_centrosymm) c = CifContainer(Path('test-data/DK_ML7-66-final.cif')) self.assertEqual(True, c.is_centrosymm) def test_ishydrogen(self): self.assertEqual(True, self.cif.ishydrogen('H18a')) self.assertEqual(True, self.cif.ishydrogen('H18A')) self.assertEqual(False, self.cif.ishydrogen('C2')) self.assertEqual(False, self.cif.ishydrogen('c2')) def test_cell(self): expected = [ round(x, 8) for x in (19.678, 37.02290000000001, 4.772, 90.0, 90.0, 90.0, 3476.576780226401) ] actual = [round(y, 8) for y in self.cif.cell] self.assertEqual(expected, actual) def test_natoms(self): self.assertEqual(94, self.cif.natoms()) self.assertEqual(52, self.cif.natoms(without_h=True)) def test_checksum_tests(self): self.assertEqual(True, self.cif.test_hkl_checksum()) self.assertEqual(True, self.cif.test_res_checksum()) def test_checksum_test_without_checksum(self): self.assertEqual( True, CifContainer('test-data/1000006.cif').test_res_checksum()) self.assertEqual( True, CifContainer('test-data/1000006.cif').test_hkl_checksum())
def make_molecule(cif: 'CifContainer') -> str: atoms = list(cif.atoms_fract) sdm = SDM(atoms, cif.symmops, cif.cell[:6], centric=cif.is_centrosymm) needsymm = sdm.calc_sdm() atoms = sdm.packer(sdm, needsymm) mol = mol_file_writer.MolFile(atoms, bonds=[]) mol = mol.make_mol() return mol if __name__ == "__main__": import sys from pathlib import Path from shutil import copy2 from tempfile import TemporaryDirectory from PyQt5.QtCore import QUrl from PyQt5.QtWebEngineWidgets import QWebEngineView from PyQt5.QtWidgets import QApplication from displaymol import mol_file_writer, write_html from pathlib import Path from cif.cif_file_io import CifContainer cif = CifContainer(Path('test-data/p21c.cif')) display_cif(cif) #make_molecule(cif)
def test_res_crc_without_res(self): self.assertEqual( 0, CifContainer(Path('test-data/1000006.cif')).res_checksum_calcd)
def setUp(self) -> None: current_file_path() self.cif = CifContainer(Path('tests/examples/1979688.cif'))
def test_centrosymm(self): self.assertEqual(False, self.cif.is_centrosymm) c = CifContainer(Path('test-data/DK_ML7-66-final.cif')) self.assertEqual(True, c.is_centrosymm)
'_journal_volume', '_journal_page_first', '_publ_section_title' ) return tocheck def list_missing_for_deposit(self, needs: Tuple) -> List[int]: """ Lists the index numbers of missing items from prepublication_needs. """ missing = [] for item in needs: if not any(self.needed_keywords_list(item)): missing.append(item) return missing def needed_keywords_list(self, item): return [item in self.cif, hasattr(self.cif.get_loop(item), 'values')] def is_complete_for_prepublication(self, needs: Tuple): if not self.list_missing_for_deposit(needs): return True return False if __name__ == '__main__': d = DepositCheck(CifContainer('tests/examples/1979688-finalcif.cif')) print(d.list_missing_for_deposit(d.prepublication_needs)) print(d.list_missing_for_deposit(d.published_needs)) print(d.list_missing_for_deposit(d.personal_needs))
if line.startswith('Summary of Data CCDC'): if linelen > 3: self.depnum = int(spline[4]) if line.startswith('Unit Cell Parameters:'): if linelen > 9: try: self.mail_cell = (float(spline[4].split('(')[0]), float(spline[6].split('(')[0]), float(spline[8].split('(')[0])) return True except (TypeError, ValueError): return False return True @staticmethod def is_same_cell(cif: CifContainer, cell: Union[list, tuple]): """ """ is_same = False for n in range(3): if round(cell[n], 4) == round(cif.cell[n], 4): is_same = True else: return False return is_same if __name__ == '__main__': cif = CifContainer(Path('test-data/DK_zucker2_0m.cif')) ccdc = CCDCMail(cif)