Example #1
0
 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())
Example #2
0
    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()))
Example #3
0
 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)))
Example #4
0
 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.'
         )
Example #5
0
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']))
Example #6
0
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
Example #7
0
 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)}
Example #8
0
    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
Example #9
0
 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()))
Example #10
0
 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))
Example #11
0
    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)
Example #12
0
 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())
Example #13
0
 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())
Example #14
0
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
Example #15
0
 def setUp(self) -> None:
     os.chdir(Path(__file__).absolute().parent.parent)
     self.cif = CifContainer(Path('test-data/DK_zucker2_0m.cif'))
Example #16
0
 def setUp(self) -> None:
     os.chdir(Path(__file__).absolute().parent.parent)
     self.cif = CifContainer(
         Path('tests/examples/work/cu_BruecknerJK_153F40_0m.cif'))
Example #17
0
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
Example #18
0
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())
Example #19
0

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)
Example #20
0
 def test_res_crc_without_res(self):
     self.assertEqual(
         0,
         CifContainer(Path('test-data/1000006.cif')).res_checksum_calcd)
Example #21
0
 def setUp(self) -> None:
     current_file_path()
     self.cif = CifContainer(Path('tests/examples/1979688.cif'))
Example #22
0
 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)
Example #23
0
                   '_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))
Example #24
0
            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)