Example #1
0
    def CIFopen(self, ciffile=None, cifblkname=None):
        from CifFile import ReadCif  # part of the PycifRW module
        try:
            # the following is a trick to avoid that urllib.URLopen.open
            # used by ReadCif misinterprets the url when a drive:\ is
            # present (Win)
            ciffile = ciffile.replace(':', '|')
            cf = ReadCif(ciffile)
        except:
            logging.error('File %s could not be accessed' % ciffile)

        if cifblkname == None:
            #Try to guess blockname
            blocks = list(cf.keys())
            if len(blocks) > 1:
                if len(blocks) == 2 and 'global' in blocks:
                    cifblkname = blocks[abs(blocks.index('global') - 1)]
                else:
                    logging.error('More than one possible data set:')
                    logging.error(
                        'The following data block names are in the file:')
                    for block in blocks:
                        logging.error(block)
                    raise Exception
            else:
                # Only one available
                cifblkname = blocks[0]
        #Extract block
        try:
            self.cifblk = cf[cifblkname]
        except:
            logging.error('Block - %s - not found in %s' %
                          (blockname, ciffile))
            raise IOError
        return self.cifblk
Example #2
0
    def CIFopen(self, ciffile=None, cifblkname=None):
        from CifFile import ReadCif # part of the PycifRW module
        try:
            # the following is a trick to avoid that urllib.URLopen.open
            # used by ReadCif misinterprets the url when a drive:\ is 
            # present (Win)
            ciffile = ciffile.replace(':','|')
            cf = ReadCif(ciffile)
        except:
            logging.error('File %s could not be accessed' %ciffile)        

        if cifblkname == None:   
            #Try to guess blockname                                                     
            blocks = cf.keys()
            if len(blocks) > 1:
                if len(blocks) == 2 and 'global' in blocks:
                    cifblkname = blocks[abs(blocks.index('global') - 1)]
                else:
                    logging.error('More than one possible data set:')
                    logging.error('The following data block names are in the file:')
                    for block in blocks:
                        logging.error(block)
                    raise Exception
            else:
                # Only one available
                cifblkname = blocks[0]
        #Extract block
        try:
            self.cifblk = cf[cifblkname]
        except:
            logging.error('Block - %s - not found in %s' % (blockname, ciffile))
            raise IOError
        return self.cifblk
Example #3
0
    def test_calculating_xrd_pattern_from_cif_file(self):
        fcc_cif = ReadCif(get_cif_url('fcc.cif'))
        cif_phase = CifPhase(fcc_cif[fcc_cif.keys()[0]])
        cif_converter = CifConverter(0.31)
        jcpds_phase = cif_converter.convert_cif_phase_to_jcpds(cif_phase)

        self.assertAlmostEqual(jcpds_phase.reflections[0].intensity, 100, places=4)
        self.assertAlmostEqual(jcpds_phase.reflections[0].d0, 2.814, places=4)
        self.assertAlmostEqual(jcpds_phase.reflections[1].d0, 2.437, places=4)
Example #4
0
    def test_calculating_xrd_pattern_from_cif_file(self):
        fcc_cif = ReadCif(get_cif_url('fcc.cif'))
        cif_phase = CifPhase(fcc_cif[fcc_cif.keys()[0]])
        cif_converter = CifConverter(0.31)
        jcpds_phase = cif_converter.convert_cif_phase_to_jcpds(cif_phase)

        self.assertAlmostEqual(jcpds_phase.reflections[0].intensity, 100, places=4)
        self.assertAlmostEqual(jcpds_phase.reflections[0].d0, 2.814, places=4)
        self.assertAlmostEqual(jcpds_phase.reflections[1].d0, 2.437, places=4)
Example #5
0
def import_cif(file_path, occupancy_tolerance=100):
    """
    Import cif with pymatgen. This is the current default.
    
    Aruments
    --------
    occupancy_tolerance: int
        Occupancy tolerance for pymatgen.io.cif.CifParser. Files from the 
        CSD can contain multiple atoms which sit on the same site when 
        PBC are taken into account. Pymatgen correctly recognizes these as the
        same atom, however, it has a tolerance for the number of atoms which it
        will assume are the same. This is the occupancy tolerance. I don't 
        believe this value should be limited and thus it's set at 100.
    """
    try:
        pycif = CifParser(file_path, occupancy_tolerance=occupancy_tolerance)
        pstruct_list = pycif.get_structures(primitive=False)
        struct = Structure.from_pymatgen(pstruct_list[0])
    except:
        struct = import_cif_ase(file_path)

    file_name = os.path.basename(file_path)
    struct.struct_id = file_name.replace('.cif', '')

    #### Read in data that may be stored as a CIF property
    if read_cif_data:
        ### Wrap in try except in case of PyCIFRW errors
        try:
            cif = ReadCif(file_path)
        except:
            print("Error in reading CIF data for {}".format(file_path))
            return struct

        if len(cif) > 1:
            raise Exception("Must only have one structure per CIF file.")

        cif_struct = [x for x in cif.keys()]
        cif_data = cif[cif_struct[0]]
        for key, value in cif_data.items():
            ## Skip over geometry information
            if "_atom_" == key[0:len("_atom_")]:
                continue
            elif "_cell_" == key[0:len("_cell_")]:
                continue
            elif "_symmetry_equiv" == key[0:len("_symmetry_equiv")]:
                continue
            else:
                pass

            ## Otherwise add info to structure property information
            struct.properties[key] = value

    return struct
Example #6
0
    def import_cif_file(self):
        file = self.ui.cif_file.text()

        if not os.path.isfile(file):
            return

        try:
            cf = ReadCif(file)

            search_params = {
                '_cell_length_a': InterplanarSpacing.PARAMETER_A,
                '_cell_length_b': InterplanarSpacing.PARAMETER_B,
                '_cell_length_c': InterplanarSpacing.PARAMETER_C,
                '_cell_angle_alpha': InterplanarSpacing.PARAMETER_ALPHA,
                '_cell_angle_beta': InterplanarSpacing.PARAMETER_BETA,
                '_cell_angle_gamma': InterplanarSpacing.PARAMETER_GAMMA,
            }

            ui_mapping = self.get_parameter_mapping()
            import re
            # find the lattice parameters in the cif file
            for key, entry in cf.items():
                for search_key, search_mapping in search_params.items():
                    if entry.has_key(search_key):
                        try:
                            number = float(entry[search_key])
                        except:
                            number = re.findall(r"[-+]?\d*\.\d+|\d+",
                                                entry[search_key])
                            if len(number) == 0:
                                continue
                            number = number[0]
                        ui_mapping[search_mapping].setText(str(number))

            self.system.set_parameter(self.get_lattice_parameters())

            system_class = self.system.detect_system()
            # Now set the input text field for the crystal system
            crystal_family = None
            for key, crystal_class in self.CLASS_MAPPING.items():
                if crystal_class == system_class:
                    crystal_family = key

            self.set_crystal_family(crystal_family)

            self.update_view()

        except BaseException as e:
            print(e)
Example #7
0
def read_reference(cif_file):
    """
    Read a cif file and return a :mod:`~qmpy.Reference`.
    """
    cf = ReadCif(cif_file, grammar='1.1')
    cif_block = cf[cf.keys()[0]]
    reference = rx.Reference()
    reference.authors = _get_authors(cif_block)
    reference.journal = _get_journal(cif_block)
    reference.volume = _get_volume(cif_block)
    reference.year = _get_year(cif_block)
    reference.first_page = _get_first_page(cif_block)
    reference.last_page = _get_last_page(cif_block)
    reference.title = _get_title(cif_block)
    return reference
Example #8
0
def read_reference(cif_file):
    """
    Read a cif file and return a :mod:`~qmpy.Reference`.
    """
    cf = ReadCif(cif_file, grammar='1.1')
    cif_block = cf[cf.keys()[0]]
    reference = rx.Reference()
    reference.authors = _get_authors(cif_block)
    reference.journal = _get_journal(cif_block)
    reference.volume = _get_volume(cif_block)
    reference.year = _get_year(cif_block)
    reference.first_page = _get_first_page(cif_block)
    reference.last_page = _get_last_page(cif_block)
    reference.title = _get_title(cif_block)
    return reference
Example #9
0
def open_cif(param, phase):
    """
	Open a cif file a build a structure for phase number "phase"
	filename: param['structure_phase_%i' %phase]
	
	returns 
	- a structure with cif information
	
	sets
	- param['sgno_phase_%i' %phase] : space group number
	- param['sgname_phase_%i' %phase] : space group name
	- param['cell_choice_phase_%i' %phase] : not 100% sure
	- param['unit_cell_phase_%i' %phase] : unit cell parameters as [a,b,c,alpha,beta,gamma']
	
	Adapted from polyxsim.structure
	Created: 12/2019, S. Merkel, Univ. Lille, France
	"""
    file = param['structure_phase_%i' % phase]
    cf = ReadCif(
        file
    )  # Generate an error if reading cif fails which is not always true below
    struct = structure.build_atomlist()
    struct.CIFread(ciffile=file)
    param['sgno_phase_%i' % phase] = sg.sg(sgname=struct.atomlist.sgname).no
    param['sgname_phase_%i' % phase] = struct.atomlist.sgname
    param['cell_choice_phase_%i' %
          phase] = sg.sg(sgname=struct.atomlist.sgname).cell_choice
    param['unit_cell_phase_%i' % phase] = struct.atomlist.cell
    return struct
Example #10
0
    def convert_cif_to_jcpds(self, filename):
        """
        Reads a cif file and returns a jcpds with correct reflection and intensities
        :param filename:  cif filename
        :return: converted jcpds object
        :rtype: jcpds
        """
        file_url = 'file:' + pathname2url(filename)
        cif_file = ReadCif(file_url)
        cif_phase = CifPhase(cif_file[cif_file.keys()[0]])
        jcpds_phase = self.convert_cif_phase_to_jcpds(cif_phase)
        jcpds_phase.filename = filename
        jcpds_phase.name = os.path.splitext(os.path.basename(filename))[0]
        jcpds_phase.modified = False

        return jcpds_phase
Example #11
0
    def convert_cif_to_jcpds(self, filename):
        """
        Reads a cif file and returns a jcpds with correct reflection and intensities
        :param filename:  cif filename
        :return: converted jcpds object
        :rtype: jcpds
        """
        file_url = 'file:' + urllib.pathname2url(filename)
        cif_file = ReadCif(file_url)
        cif_phase = CifPhase(cif_file[cif_file.keys()[0]])
        jcpds_phase = self.convert_cif_phase_to_jcpds(cif_phase)
        jcpds_phase.filename = filename
        jcpds_phase.name = os.path.splitext(os.path.basename(filename))[0]
        jcpds_phase.modified = False

        return jcpds_phase
Example #12
0
    def test_reading_phase(self):
        fcc_cif = ReadCif(get_cif_url('fcc.cif'))

        cif_phase = CifPhase(fcc_cif[fcc_cif.keys()[0]])

        self.assertEqual(cif_phase.a, 4.874)
        self.assertEqual(cif_phase.b, 4.874)
        self.assertEqual(cif_phase.c, 4.874)

        self.assertEqual(cif_phase.alpha, 90)
        self.assertEqual(cif_phase.beta, 90)
        self.assertEqual(cif_phase.gamma, 90)

        self.assertEqual(cif_phase.volume, 115.79)
        self.assertEqual(cif_phase.space_group_number, 225)

        self.assertEqual(len(cif_phase.atoms), 8)
        self.assertEqual(cif_phase.comments, 'HoN, Fm-3m - NaCl structure type, ICSD 44776')
Example #13
0
    def test_reading_phase(self):
        fcc_cif = ReadCif(get_cif_url('fcc.cif'))

        cif_phase = CifPhase(fcc_cif[fcc_cif.keys()[0]])

        self.assertEqual(cif_phase.a, 4.874)
        self.assertEqual(cif_phase.b, 4.874)
        self.assertEqual(cif_phase.c, 4.874)

        self.assertEqual(cif_phase.alpha, 90)
        self.assertEqual(cif_phase.beta, 90)
        self.assertEqual(cif_phase.gamma, 90)

        self.assertEqual(cif_phase.volume, 115.79)
        self.assertEqual(cif_phase.space_group_number, 225)

        self.assertEqual(len(cif_phase.atoms), 8)
        self.assertEqual(cif_phase.comments, 'HoN, Fm-3m - NaCl structure type, ICSD 44776')
def main(name):
    mof = ReadCif(name)
    mof = mof[mof.visible_keys[0]]

    elements = mof["_atom_site_type_symbol"]
    n_atoms = len(elements)

    prop_dict = {}
    for a1, a2 in combinations_with_replacement(set(elements), 2):
        prop_arr = [prop[a1] * prop[a2] for prop in prop_list]
        prop_dict[(a1, a2)] = prop_arr
        if a1 != a2:
            prop_dict[(a2, a1)] = prop_arr

    la = float(mof["_cell_length_a"])
    lb = float(mof["_cell_length_b"])
    lc = float(mof["_cell_length_c"])
    aa = np.deg2rad(float(mof["_cell_angle_alpha"]))
    ab = np.deg2rad(float(mof["_cell_angle_beta"]))
    ag = np.deg2rad(float(mof["_cell_angle_gamma"]))
    # If volume is missing from .cif, calculate it.
    try:
        cv = float(mof["_cell_volume"])
    except KeyError:
        cv = la * lb * lc * math.sqrt(1 - (math.cos(aa))**2 -
                                      (math.cos(ab))**2 - (math.cos(ag))**2 +
                                      (2 * math.cos(aa) * math.cos(ab) *
                                       math.cos(ag)))

    frac2cart = np.zeros([3, 3], dtype=float)
    frac2cart[0, 0] = la
    frac2cart[0, 1] = lb * np.cos(ag)
    frac2cart[0, 2] = lc * np.cos(ab)
    frac2cart[1, 1] = lb * np.sin(ag)
    frac2cart[1, 2] = lc * (np.cos(aa) - np.cos(ab) * np.cos(ag)) / np.sin(ag)
    frac2cart[2, 2] = cv / (la * lb * np.sin(ag))

    frac = np.array([
        mof["_atom_site_fract_x"],
        mof["_atom_site_fract_y"],
        mof["_atom_site_fract_z"],
    ],
                    dtype=float).T

    apw_rdf = np.zeros([n_props, n_bins], dtype=np.float64)
    for i, j in combinations(range(n_atoms), 2):
        cart_i = frac2cart @ frac[i]
        cart_j = (frac2cart @ (super_cell + frac[j]).T).T
        dist_ij = min(np.linalg.norm(cart_j - cart_i, axis=1))
        rdf = np.exp(smooth * (bins - dist_ij)**2)
        rdf = rdf.repeat(n_props).reshape(n_bins, n_props)
        apw_rdf += (rdf * prop_dict[(elements[i], elements[j])]).T
    apw_rdf = np.round(apw_rdf.flatten() * factor / n_atoms, decimals=12)

    return ("{}," * len(apw_rdf) + "{}\n").format(
        name.split('/')[-1], *apw_rdf.tolist())
Example #15
0
def read_structure(path_to_file):

    cwd = os.getcwd()
    try:
        os.chdir(os.path.dirname(path_to_file))
        file_name = os.path.split(path_to_file)[-1]
        cif_data = ReadCif(file_name)
        os.chdir(cwd)
    except:
        os.chdir(cwd)
        raise ValueError("The reading or parsing of the " + file_name +
                         " is failed!")
    try:
        name, data = list(cif_data.items())[0]
        structure_data = StructureData(name, data)
        structure = Structure().build_structure(structure_data)
        structure.reamove_connectivity()
        return structure
    except:
        print("Reading structure is failed!")
Example #16
0
def read_structures(path_to_file):

    cwd = os.getcwd()
    try:
        os.chdir(os.path.dirname(path_to_file))
        file_name = os.path.split(path_to_file)[-1]
        cif_data = ReadCif(file_name)
        os.chdir(cwd)
    except:
        os.chdir(cwd)
        raise ValueError("The reading or parsing of the " + file_name +
                         " is failed!")
    for i, (name, data) in enumerate(cif_data.items()):
        try:
            structure_data = StructureData(name, data)
            structure = Structure().build_structure(structure_data)
            structure.reamove_connectivity()
            yield structure
        except:
            os.chdir(cwd)
            print("Reading " + str(i) + " structure is failed!")
Example #17
0
    def _loadFromCif(self):
        from CifFile import ReadCif

        cifFileUrl = self._getFileUrl()
        workspace = self.getProperty('Workspace').value

        # Try to parse cif file using PyCifRW
        parsedCifFile = ReadCif(cifFileUrl)

        self._setCrystalStructureFromCifFile(workspace, parsedCifFile)

        ubOption = self.getProperty('LoadUBMatrix').value
        if ubOption:
            self._setUBMatrixFromCifFile(workspace, parsedCifFile)
Example #18
0
def read(cif_file, grammar=None):
    """
    Takes a CIF format file, and returns a Structure object. Applies all
    symmetry operations in the CIF to the atoms supplied with the structure. If
    these are not correct, the structure will not be either. If the CIF
    contains more than one file, the return will be a list. If not, the return
    will be a single structure (not in a len-1 list).

    Examples::

        >>> s = io.cif.read(INSTALL_PATH+'io/files/fe3o4.cif')

    """
    if grammar:
        cf = ReadCif(cif_file, grammar=grammar)
    else:
        cf = ReadCif(cif_file)
    structures = []
    for key in cf.keys():
        structures.append(_read_cif_block(cf[key]))
    if len(structures) == 1:
        return structures[0]
    else:
        return structures
Example #19
0
def read(cif_file, grammar=None):
    """
    Takes a CIF format file, and returns a Structure object. Applies all
    symmetry operations in the CIF to the atoms supplied with the structure. If
    these are not correct, the structure will not be either. If the CIF
    contains more than one file, the return will be a list. If not, the return
    will be a single structure (not in a len-1 list).

    Examples::

        >>> s = io.cif.read(INSTALL_PATH+'io/files/fe3o4.cif')

    """
    if grammar:
        cf = ReadCif(cif_file, grammar=grammar)
    else:
        cf = ReadCif(cif_file)
    structures = []
    for key in cf.keys():
        structures.append(_read_cif_block(cf[key]))
    if len(structures) == 1:
        return structures[0]
    else:
        return structures
Example #20
0
    def test_sfcalc(self):  ## test method names begin 'test*'
        # Read the cif
        mylist =  structure.build_atomlist()
        mylist.CIFread('PPA.cif','oPPA')

        # Read the fcf
        fcf = ReadCif('oPPA.fcf')['oPPA']
        for i in range(500):# Consider only the first 500 reflections
            hkl =[eval(fcf['_refln_index_h'][i]),
                  eval(fcf['_refln_index_k'][i]),
                  eval(fcf['_refln_index_l'][i])]
            (Fr, Fi) = structure.StructureFactor(hkl, mylist.atomlist.cell,
                                                 mylist.atomlist.sgname,
                                                 mylist.atomlist.atom,
                                                 mylist.atomlist.dispersion)
            F2 = Fr**2 + Fi**2
            reldif = F2/eval(fcf['_refln_F_squared_calc'][i])-1
            print(i, reldif, F2)
            if F2 > 10: # Only compare those with an F^2 larger than ten 
                        # to avoid that the very weak reflections which
                        # have a relative difference that are slightly larger
                self.assertAlmostEqual(reldif,0,2)
Example #21
0
def star_reader(filename):
    """
    star_reader: reads a star file and returns a dictionary
    """
    key='data_'
    new_key='data_metadata'
    new_starfile='.tmp.star'
    #
    with open(filename) as f1:
        with open(new_starfile, 'w') as f2:
            lines = f1.readlines()
            for line in lines:
                if(line.startswith(key)):
                    f2.write(new_key)
                else:
                    f2.write(line)
    data = ReadCif(new_starfile, grammar='STAR2')
    os.remove(new_starfile)
    print('Number of particles in this star file: {}'.format(len(data['metadata'][data['metadata'].keys()[0]])))
    print("The entries in the returned dictionary are:")
    print("data['metadata'].keys(): {}".format(data['metadata'].keys()))
    return data
Example #22
0
class CIFParser(AbstractStructureParser):
    """
    Collection of methods that parses CIF files based on cif2cell. The preferred method
    of using this object is as a context manager.

    Parameters
    ----------
    filename : str or path-like
        Location of the CIF file.
    """
    def __init__(self, filename, **kwargs):
        # ReadCIF would get confused between local files and URLs
        # Therefore, more clear to pass an open file
        self._handle = open(filename, mode="r")
        self.file = ReadCif(self._handle, **kwargs)

    def __exit__(self, *args, **kwargs):
        self._handle.close()

    @property
    def filename(self):
        return self._handle.name

    @staticmethod
    def sym_ops_from_equiv(equiv_site):
        """ Parse a symmetry operator from an equivalent-site representation 
        
        Parameters
        ----------
        equiv_site : str or iterable of strings
            Either comma-separated string e.g. "+y, +x, -z + 1/2" or an
            iterable of the comma-separated values, e.g. ["+y", "+x", "-z + 1/2"] 
        
        Returns
        -------
        sym_ops : ndarray, shape (4,4)
            Symmetry operator as a 4x4 affine transformation on the FRACTIONAL
            coordinates.
        """
        symmetry = np.zeros((3, 3))
        translation = np.zeros((3, ))

        if isinstance(equiv_site, str):
            equiv_site = equiv_site.split(",")

        equiv_site = tuple(map(lambda s: s.strip().lower(), equiv_site))
        for j in range(3):
            xyz = equiv_site[j].replace("+", " +").replace("-", " -").split()
            for i in xyz:
                if i.strip("+-") == "x":
                    symmetry[0, j] = float(i.strip("x") + "1")
                elif i.strip("+-") == "y":
                    symmetry[1, j] = float(i.strip("y") + "1")
                elif i.strip("+-") == "z":
                    symmetry[2, j] = float(i.strip("z") + "1")

                if i.strip("+-xyz") != "":
                    translation[j] = eval(i)

        symmetry[:] = np.transpose(symmetry)

        # Combination of transform and translation into a single matrix
        # is done in a 4x4 affine transform
        symmetry_operation = affine_map(symmetry)
        symmetry_operation[:3, 3] = translation
        return symmetry_operation

    @property
    def structure_block(self):
        """ Retrieve which CIF block has the appropriate structural information """
        blocks = (self.file[key] for key in self.file.keys())
        for block in blocks:
            try:
                _, _ = get_number_with_esd(block["_cell_length_a"])
            except KeyError:
                continue
            else:
                return block

    @lru_cache(maxsize=1)
    def hall_symbol(self):
        """ Returns the Hall symbol """
        block = self.structure_block

        hall_symbol = block.get("_symmetry_space_group_name_Hall"
                                ) or block.get("_space_group_name_Hall")

        # In some rare cases, the given hall symbol in the file isn't standard,
        # otherwise it would be a key in SymOpsHall
        # Then, it is preferable to infer the conventional hall symbol from other info
        if (hall_symbol is None) or (hall_symbol not in SymOpsHall):
            h_m_symbol = block.get("_symmetry_space_group_name_H-M"
                                   ) or block.get("_space_group_name_H-M_alt")

            if h_m_symbol is not None:
                h_m_symbol = re.sub(r"\s+", "", h_m_symbol)
                with suppress(
                        KeyError
                ):  # Symbol could be meaningless, e.g. h_m_symbol = '?' (True story)
                    hall_symbol = HM2Hall[h_m_symbol]

        # Again, if hall_symbol is still missing OR invalid
        if (hall_symbol is None) or (hall_symbol not in SymOpsHall):
            table_number = block.get("_symmetry_Int_Tables_number"
                                     ) or block.get("_space_group_IT_number")

            if table_number is not None:
                hall_symbol = Number2Hall[int(table_number)]

        if hall_symbol is None:
            raise ParseError("Hall symbol could not be inferred")

        if hall_symbol[0] == "-":
            hall_symbol = "-" + hall_symbol[1].upper() + hall_symbol[2:].lower(
            )
        else:
            hall_symbol = hall_symbol[0].upper() + hall_symbol[1:].lower()

        return hall_symbol

    @lru_cache(maxsize=1)
    def lattice_parameters(self):
        """ 
        Returns the lattice parameters associated to a CIF structure.

        Returns
        ----------
        a, b, c : float
            Lengths of lattice vectors [Angstroms]
        alpha, beta, gamma : float
            Angles of lattice vectors [degrees]. 
        """
        block = self.structure_block

        try:
            a_with_err = block["_cell_length_a"]
        except KeyError:
            raise ParseError(
                f"No lattice information is present in {self.filename}")

        # In case where b and c are not listed, we use the value of a
        a, _ = get_number_with_esd(a_with_err)
        b, _ = get_number_with_esd(block.get("_cell_length_b", a_with_err))
        c, _ = get_number_with_esd(block.get("_cell_length_c", a_with_err))

        alpha, _ = get_number_with_esd(block["_cell_angle_alpha"])
        beta, _ = get_number_with_esd(block["_cell_angle_beta"])
        gamma, _ = get_number_with_esd(block["_cell_angle_gamma"])

        return a, b, c, alpha, beta, gamma

    @lru_cache(maxsize=1)
    def lattice_vectors(self):
        """ 
        Returns the lattice vectors associated to a CIF structure.
        
        Returns
        -------
        lv : list of ndarrays, shape (3,)
        """
        return Lattice.from_parameters(
            *self.lattice_parameters()).lattice_vectors

    def symmetry_operators(self):
        """
        Returns the symmetry operators that map the fractional atomic positions in a
        CIF file to the crystal *conventional* unit cell.

        Returns
        -------
        sym_ops : iterable of ndarray, shape (4,4)
            Transformation matrices. Since translations and rotation are combined,
            the transformation matrices are 4x4.
        """
        block = self.structure_block

        equivalent_sites_str = None
        for tag in [
                "_symmetry_equiv_pos_as_xyz",
                "_space_group_symop_operation_xyz"
        ]:
            with suppress(KeyError):
                equivalent_sites_str = block.GetLoop(tag).get(tag)

        # P1 space group only has a single equivalent site
        if isinstance(equivalent_sites_str, str):
            equivalent_sites_str = [equivalent_sites_str]

        with suppress(ParseError):
            if not equivalent_sites_str:
                equivalent_sites_str = SymOpsHall[self.hall_symbol()]
            elif len(equivalent_sites_str) != len(
                    SymOpsHall[self.hall_symbol()]):
                warnings.warn(
                    "The number of equivalent sites is not in line with the database. The file might be incomplete"
                )

        return list(map(self.sym_ops_from_equiv, equivalent_sites_str))

    def atoms(self):
        """
        Asymmetric unit cell. Combine with CIFParser.symmetry_operators() for a full unit cell.

        Returns
        -------
        atoms : iterable of Atom instance
        """
        block = self.structure_block

        try:
            tmpdata = block.GetLoop("_atom_site_fract_x")
            cartesian = False
        except:
            try:
                tmpdata = block.GetLoop("_atom_site_Cartn_x")
                cartesian = True
            except:
                raise ParseError(
                    "Atomic positions could not be found or inferred.")

            t11 = block.get("_atom_sites_Cartn_tran_matrix_11")
            t12 = block.get("_atom_sites_Cartn_tran_matrix_12")
            t13 = block.get("_atom_sites_Cartn_tran_matrix_13")
            t21 = block.get("_atom_sites_Cartn_tran_matrix_21")
            t22 = block.get("_atom_sites_Cartn_tran_matrix_22")
            t23 = block.get("_atom_sites_Cartn_tran_matrix_23")
            t31 = block.get("_atom_sites_Cartn_tran_matrix_13")
            t32 = block.get("_atom_sites_Cartn_tran_matrix_23")
            t33 = block.get("_atom_sites_Cartn_tran_matrix_33")
            cart_trans_matrix_inv = np.array([
                [float(t11), float(t12), float(t13)],
                [float(t21), float(t22), float(t23)],
                [float(t31), float(t32), float(t33)],
            ])
            cart_trans_matrix = inv(cart_trans_matrix_inv)

            if not all([t11, t12, t13, t21, t22, t23, t31, t32, t33]):
                raise ParseError(
                    "Cartesian coordinates in CIF but no transformation matrix given"
                )

        if cartesian:
            xs = tmpdata.get("_atom_site_Cartn_x")
            ys = tmpdata.get("_atom_site_Cartn_y")
            zs = tmpdata.get("_atom_site_Cartn_z")
        else:
            xs = tmpdata.get("_atom_site_fract_x")
            ys = tmpdata.get("_atom_site_fract_y")
            zs = tmpdata.get("_atom_site_fract_z")
        # TODO: handle wildcards like '?', '.' in xs, ys, zs

        elements = tmpdata.get("_atom_site_type_symbol")
        if not elements:
            elements = tmpdata.get("_atom_site_label")
            if not elements:
                raise ParseError(
                    "Atom symbols could not be found or inferred.")
        elements = map(lambda s: s.strip(punctuation + digits).title(),
                       elements)

        atoms = list()
        for e, x, y, z in zip(elements, xs, ys, zs):
            coords = np.array([
                get_number_with_esd(x)[0],
                get_number_with_esd(y)[0],
                get_number_with_esd(z)[0],
            ])

            # We normalize atom position to be within the unit cell
            # Therefore we need the fractional coordinates
            if cartesian:
                coords = transform(cart_trans_matrix, coords)
                coords[:] = frac_coords(coords, self.lattice_vectors())

            atoms.append(Atom(element=e, coords=np.mod(coords, 1)))

        return atoms
    '_cell_length_c', '_cell_angle_alpha', '_cell_angle_beta',
    '_cell_angle_gamma', '_cell_volume', '_exptl_crystal_density_diffrn',
    '_symmetry_space_group_name_h-m'
]

for i, row in dfMin.iterrows():

    cifFolder = os.path.join(base, row.MineralName)
    if os.path.exists(
            cifFolder):  #row.mineralName not in ['Angelaite','Arsenopyrite']:

        for cifFile in [
                f for f in os.listdir(cifFolder) if f.endswith(".cif")
        ]:
            try:
                cf = ReadCif(os.path.join(cifFolder, cifFile))

                # '_atom_site_label','_atom_site_fract_x','_atom_site_fract_y','_atom_site_fract_z','_atom_site_occupancy','_atom_site_u_iso_or_equiv'])
                cifDic = {key: cf['global'][key] for key in cifKeys}
                cifDic['Temperature'] = 'False'
                cifDic['Pressure'] = 'False'

                #remove new line from '_publ_section_title'
                cifDic['_publ_section_title'] = cifDic[
                    '_publ_section_title'].replace("\n",
                                                   " ").replace('\r',
                                                                " ").strip()
                # print(cifDic)
                #with multiplicity
                if '_atom_site_occupancy' in cf[
                        'global']:  #keep if it doesnt have multiple occupancies
Example #24
0
#! ./venv/bin/python

from CifFile import ReadCif
import sys

# I couldn't find a good way to read CIFs in ruby so we have to call this python script
# pip install PyCifRW

cf = ReadCif(sys.argv[1])
atoms = cf[cf.visible_keys[0]]["_atom_site_label"]
j = 0
while j < len(atoms):
    atoms[j] = ''.join([i for i in atoms[j] if not i.isdigit()])
    j = j + 1
atoms_no_dupes = []

for x in atoms:
    if x == "C1":
        y = 2
    if x not in atoms_no_dupes:
        atoms_no_dupes.append(x)
print(atoms_no_dupes)
Example #25
0
from CifFile import ReadCif

import os
from shutil import copy

d = '/home/kenneth/proj/proXtal/amcsd/cif/mineral/'

for f in os.listdir(d):
    cf = ReadCif(d + f)

    labels = cf['global']['_atom_site_label']

    subs = "Fe"

    if len(list(filter(lambda x: subs in x, labels))) > 0:

        copy(f, d + 'Fe/')
Example #26
0
if __name__ == '__main__':

    parser = argparse.ArgumentParser(
        prog='susViewer',
        description=
        'Convert chi-tensor to appropriate coordinate system for visualization in standard molecular viewers'
    )
    parser.add_argument('cifname')
    parser.add_argument('-b', '--blockname')
    parser.add_argument('-s', '--scale')
    parser.add_argument('-r', '--repr')

    _cmd_line_args = parser.parse_args()

    _cifname = _cmd_line_args.cifname
    cf = ReadCif(_cifname)

    _blockname = _cmd_line_args.blockname
    _type = _cmd_line_args.repr
    _scale = _cmd_line_args.scale
    structure = cc.crystalStructure(_cifname, blockname=_blockname)

    if _scale is None:
        _scale = 1
    else:
        _scale = float(_scale)
    # The following is not obsolete. It is used to find the right block, as not everything can be
    # done using the structure as loaded from the CIF.
    if _blockname is None:
        _blockname = structure.block
    if _type is None:
Example #27
0
#-------------------------------------------------------------------------------
# Name:        module1
# Purpose:
#
# Author:      Andrezio
#
# Created:     23/07/2017
# Copyright:   (c) Andrezio 2017
# Licence:     <your licence>
#-------------------------------------------------------------------------------

from CifFile import ReadCif
<<<<<<< HEAD
cf = ReadCif('UO2_STAR_246851.cif')
lambida=1.54
=======
cf = ReadCif('u308.cif')

>>>>>>> f26a11b75e998002824160efa1c337672e8cb21b
chave = cf.keys()


##for k,v in cf[chave[0]].items():
##    print k

<<<<<<< HEAD
value= cf[chave[0]]['_cell_length_a']

value=value.split('(')[0]

=======
Example #28
0
    def read(self):
        """
        Read data from the CIF file
        """
        with open(self.filename, 'r') as f:
            ciffile = ReadCif(f)
            for block in ciffile:
                spacegroup = Spacegroup(int(block['_space_group_IT_number']))

                cellpar = np.array([
                    block['_cell_length_a'],
                    block['_cell_length_b'],
                    block['_cell_length_c'],
                    block['_cell_angle_alpha'],
                    block['_cell_angle_beta'],
                    block['_cell_angle_gamma'],
                ],
                                   dtype=float)

                try:
                    site_labels = block['_atom_site_label']
                except KeyError:
                    print('Could not get site labels from cif file')
                try:
                    occupancies = np.array(block['_atom_site_occupancy'],
                                           dtype=float)
                except KeyError:
                    print('Could not get occupancies from cif file')
                try:
                    fract_x = np.array(block['_atom_site_fract_x'],
                                       dtype=float)
                    fract_y = np.array(block['_atom_site_fract_y'],
                                       dtype=float)
                    fract_z = np.array(block['_atom_site_fract_z'],
                                       dtype=float)
                except KeyError:
                    warn(
                        'Could not get fractional coordinates from cif file, getting absolute coordinates instead.'
                    )
                    try:
                        x = np.array(block['_atom_site_cartn_x'], dtype=float)
                        y = np.array(block['_atom_site_cartn_y'], dtype=float)
                        z = np.array(block['_atom_site_cartn_z'], dtype=float)
                    except KeyError:
                        warn(
                            'Could not get absolute coordinates from cif file')
                        x = [np.nan] * len(block)
                        y = [np.nan] * len(block)
                        z = [np.nan] * len(block)
                    finally:
                        fract_x = x / cellpar[0]
                        fract_y = y / cellpar[1]
                        fract_z = z / cellpar[2]
                else:
                    x = fract_x * cellpar[0]
                    y = fract_y * cellpar[1]
                    z = fract_y * cellpar[2]
                finally:
                    x = x.T
                    y = y.T
                    z = z.T
                    fract_x = fract_x.T
                    fract_y = fract_y.T
                    fract_z = fract_z.T

                    positions = np.array([x, y, z])
                    fractional_positions = np.array(
                        [fract_x, fract_y, fract_z])
                try:
                    symbols = block['_atom_site_type_symbol']
                except KeyError:
                    print(
                        'Could not get atom site chemical symbols from cif file'
                    )
                try:
                    dwf = block['_atom_site_B_iso_or_equiv']
                except KeyError:
                    print('Could not get Debye-Waller factors from cif file')

                basis_atoms = []
                for label, occ, fx, fy, fz, symbol, B in zip(
                        site_labels, occupancies, fractional_positions[0],
                        fractional_positions[1], fractional_positions[2],
                        symbols, dwf):
                    atom = CIFAtom(cellpar,
                                   symbol=symbol,
                                   occupancy=occ,
                                   fractional_position=(fx, fy, fz),
                                   dwf=B,
                                   site_label=label)
                    basis_atoms.append(atom)

                atoms = []
                for atom in basis_atoms:
                    equivalent_sites, kinds = spacegroup.equivalent_sites(
                        atom.fractional_position,
                        onduplicates='warn',
                        occupancies=atom.occupancy)
                    for site in equivalent_sites:
                        position = site * cellpar[:3]
                        equivalent_atom = CIFAtom(cellpar,
                                                  fractional_position=site,
                                                  site_label=atom.site_label,
                                                  symbol=atom.symbol,
                                                  dwf=atom.dwf,
                                                  occupancy=atom.occupancy)
                        atoms.append(equivalent_atom)
                self.atoms = atoms
                self.crystal = Crystal(atoms, cellpar)
Example #29
0
    # ASE functions
    from ase.io import read as read_cif

elif package == 'pymatgen':
    # Pymatgen functions
    from pymatgen import Structure
    read_cif = Structure.from_file

elif package == 'pycifrw':
    # PyCifRW
    from CifFile import ReadCif as read_cif

elif package == 'pycifrw-fast':
    # PyCifRW
    from CifFile import ReadCif
    read_cif = lambda x: ReadCif(x, scantype="flex")

elif package == 'pycodcif':
    # pycodcif
    from pycodcif import parse

    def get_content(file):
        datablocks, error_count, error_messages = parse(file)
        return datablocks

    read_cif = get_content

extension = '.cif'
directory = 'structures_0108'
paths = glob.glob("{}/*{}".format(directory, extension))
Example #30
0
'''
Created on Mar 17, 2018

@author: Mammon
'''

from CifFile import ReadCif
cf = ReadCif("molecule.cif")
my_data = cf.first_block()

#print(my_data)
print(my_data)

columns = [
    "_atom_site_label", "_atom_site_type_symbol", "_atom_site_fract_x",
    "_atom_site_fract_y", "_atom_site_fract_z"
]

#store the loop inside excel
from openpyxl import Workbook
wb = Workbook()

#get current active sheet
ws = wb.active
#change title of the sheet
ws.title = "Sonification"

#change the background color of the tab hoding this title
ws.sheet_properties.tabColor = "1072BA"
for i in range(1, 6):
    ws.cell(row=1, column=i, value=columns[i - 1])
Example #31
0
 def __init__(self, filename, **kwargs):
     # ReadCIF would get confused between local files and URLs
     # Therefore, more clear to pass an open file
     self._handle = open(filename, mode="r")
     self.file = ReadCif(self._handle, **kwargs)
Example #32
0
    def finalise_parameters(self, file_name, index, current_temp):

        #Finalises the CIF with important parameters such as beamline parameters

        cif = ReadCif(file_name)

        try:
            data_block = cif[str(index + 1)]
        except TypeError as error:
            os.remove(file_name)
            self.logger.info(f'Cif empty due to poor refinement - {error}')
        else:

            self.C = data_block['_diffrn_reflns_number']
            self.A = data_block['_diffrn_reflns_theta_min']
            self.B = data_block['_diffrn_reflns_theta_max']

            beamline = self.cfg['User_Parameters_Full_Pipeline'][
                'Experiment_Configuration']['beamline']

            if beamline != '':

                data_block['_computing_data_collection'] = self.cfg[
                    'Instrument_Parameters'][beamline + '_data_collection']
                data_block['_exptl_absorp_correction_type'] = self.cfg[
                    'Instrument_Parameters'][beamline + '_absorp_correction']
                data_block['_diffrn_radiation_wavelength'] = self.cfg[
                    'User_Parameters_Full_Pipeline'][
                        'Experiment_Configuration']['wavelength']
                data_block['_diffrn_radiation_type'] = self.cfg[
                    'Instrument_Parameters'][beamline + '_radiation_type']
                data_block['_diffrn_source'] = self.cfg[
                    'Instrument_Parameters'][beamline + '_radiation_type']
                data_block['_diffrn_measurement_device_type'] = self.cfg[
                    'Instrument_Parameters'][beamline + '_detector']
                data_block['_diffrn_measurement_method'] = self.cfg[
                    'Instrument_Parameters'][beamline + '_measurement_method']
                data_block['_computing_cell_refinement'] = self.cfg[
                    'Instrument_Parameters'][beamline + '_cell_refinement']
                data_block['_computing_data_reduction'] = self.cfg[
                    'Instrument_Parameters'][beamline + '_cell_refinement']
                data_block['_computing_structure_solution'] = self.cfg[
                    'Instrument_Parameters'][beamline + '_structure_soln']
                data_block['_diffrn_radiation_monochromator'] = self.cfg[
                    'Instrument_Parameters'][beamline + '_monochromator']
                data_block['_diffrn_radiation_source'] = self.cfg[
                    'Instrument_Parameters'][beamline + '_source']

            data_block['_chemical_formula_moiety'] = self.cfg[
                'User_Parameters_Full_Pipeline']['Crystal_Descriptions'][
                    'chemical_formula']
            data_block['_exptl_crystal_colour'] = self.cfg[
                'User_Parameters_Full_Pipeline']['Crystal_Descriptions'][
                    'crystal_colour']
            data_block['_exptl_crystal_description'] = self.cfg[
                'User_Parameters_Full_Pipeline']['Crystal_Descriptions'][
                    'crystal_habit']
            data_block['_cell_measurement_temperature'] = current_temp
            data_block['_diffrn_ambient_temperature'] = current_temp
            data_block['_exptl_crystal_size_max'] = self.cfg[
                'User_Parameters_Full_Pipeline']['Crystal_Descriptions'][
                    'max_crystal_dimension']
            data_block['_exptl_crystal_size_mid'] = self.cfg[
                'User_Parameters_Full_Pipeline']['Crystal_Descriptions'][
                    'middle_crystal_dimension']
            data_block['_exptl_crystal_size_min'] = self.cfg[
                'User_Parameters_Full_Pipeline']['Crystal_Descriptions'][
                    'min_crystal_dimension']
            data_block['_cell_measurement_reflns_used'] = self.C
            data_block['_cell_measurement_theta_min'] = self.A
            data_block['_cell_measurement_theta_max'] = self.B

            with open('edited.cif', 'w') as updated:
                updated.write(cif.WriteOut())

            os.rename('edited.cif', file_name)
Example #33
0
    def data_harvest(self, cif_file):

        #Resets the dataframes/dictionaries

        for item in self.search_items:
            self.results[item] = []
            self.errors[item] = []
        self.temp_df = pd.DataFrame()
        self.bond_df = pd.DataFrame()
        self.angle_df = pd.DataFrame()
        self.torsion_df = pd.DataFrame()

        #This notation is from the CifFile module and allows for easy searching of parameters

        cif = ReadCif(cif_file)

        #Identifies datablocks within the CIF file

        self.data_blocks = []

        with open(cif_file, 'rt') as f:
            for line in f:
                if line.startswith('data_'):
                    self.data_blocks.append(line.strip('\n').strip('data_'))

        number_of_structures = len(self.data_blocks)

        #For each search item in the config file, the cif file is searched

        for item in self.search_items:
            self.logger.info('File ' + pathlib.Path(cif_file.lower()).stem +
                             ' opened. Searching for parameter ' + item)

            #This parameter is blanked every loop because each cif is searched multiple times

            self.cif_list = []

            #Since the CifFile module works by looking at data-blocks, use the found list of data blocks to search through the CIF

            for experiment in self.data_blocks:
                try:
                    raw = cif[experiment][item]
                except:
                    self.logger.critical('Failed to find ' + item + ' in ' +
                                         pathlib.Path(cif_file.lower()).stem)
                    exit()

                self.logger.info('File ' +
                                 pathlib.Path(cif_file.lower()).stem +
                                 ' - found parameter ' + item)
                self.cif_list.append(pathlib.Path(cif_file.lower()).stem)

                #Check if an error value is present and separates the value and the error, converts the error to the correct decimal point, and assigns an error of 0 if no error present

                if type(raw) != list:
                    self.parameter_tidy(raw, item)
                else:
                    for param in raw:
                        self.parameter_tidy(param, item)

        #Creates a column in the data frame to include the file name of the CIF

        self.temp_df['CIF File'] = self.cif_list

        #Adds all of the data to one data frame

        bond_paras = [
            '_geom_bond_atom_site_label_1', '_geom_bond_atom_site_label_2',
            '_geom_bond_distance'
        ]
        angle_paras = [
            '_geom_angle_atom_site_label_1', '_geom_angle_atom_site_label_2',
            '_geom_angle_atom_site_label_3', '_geom_angle'
        ]
        torsion_paras = [
            '_geom_torsion_atom_site_label_1',
            '_geom_torsion_atom_site_label_2',
            '_geom_torsion_atom_site_label_3',
            '_geom_torsion_atom_site_label_4', '_geom_torsion'
        ]

        for para in self.search_items:
            if len(self.results[para]) == len(self.cif_list):
                self.temp_df[para] = self.results[para]
                self.temp_df[para + '_error'] = self.errors[para]
            elif len(self.results[para]) != 0 and para in bond_paras:
                self.bond_df[para] = self.results[para]
                self.bond_df[para + '_error'] = self.errors[para]
            elif len(self.results[para]) != 0 and para in angle_paras:
                self.angle_df[para] = self.results[para]
                self.angle_df[para + '_error'] = self.errors[para]
            elif len(self.results[para]) != 0 and para in torsion_paras:
                self.torsion_df[para] = self.results[para]
                self.torsion_df[para + '_error'] = self.errors[para]

        try:
            self.bond_df['Cif File'], self.bond_df[
                'Data Block'] = self.generate_cif_list(self.bond_df)
        except:
            pass
        try:
            self.angle_df['Cif File'], self.angle_df[
                'Data Block'] = self.generate_cif_list(self.angle_df)
        except:
            pass
        try:
            self.torsion_df['Cif File'], self.torsion_df[
                'Data Block'] = self.generate_cif_list(self.torsion_df)
        except:
            pass

        return self.temp_df, number_of_structures, self.data_blocks, self.bond_df, self.angle_df, self.torsion_df
Example #34
0
    def run(config, input, output):

        dir = config['xcDir']

        # Copy cif2cell related input to cif2cellInput here. Later we will be overriding some settings,
        # so we want to keep the original input intact.
        cif2cellInput = {
            key: input[key]
            for key in input if key.startswith('cif2cell.')
        }

        # Generate any data that is needed from generic input and populate cif2cellInput with
        # global data (needed for all feff runs.)
        cif2cellInput['cif2cell.cif_input'] = input['cif_input']

        # Set executable directory for this exchange
        cif2celldir = config['cif2cell']

        # Set input file - cif2cell takes input from command line, so no input file, however, maybe we can take commands from input file?
        #inpf = os.path.join(dir, 'cif2cell.in')

        # Loop over targets in output. Not sure if there will ever be more than one output target here.
        if set(output.keys()).issubset(
                set([
                    'cell_vectors', 'cell_struct_xyz_red', 'cell_scaling_iso',
                    'cell_scaling_abc', 'number_density', 'supercell'
                ])):
            # Set output and error files
            with open(os.path.join(dir, 'corvus.CIF2CELL.stdout'),
                      'wb') as out, open(
                          os.path.join(dir, 'corvus.CIF2CELL.stderr'),
                          'wb') as err:
                # Copy necessary files to dir
                cif_file = cif2cellInput['cif2cell.cif_input'][0][0]
                shutil.copy(cif_file, dir)

                # Loop over executables: This is specific to feff. Other codes
                # will more likely have only one executable.
                executables = ['cif2cell']

                args = [cif_file, '-p', 'cif', '-o', 'out.cif']
                iExec = 0
                for executable in executables:
                    runExecutable(cif2celldir, dir, executable, args, out, err)

                # For now, I am only passing the directory.
                print('Setting output')
                outCif = os.path.join(dir, 'out.cif')
                cifFile = ReadCif(outCif)
                # cifFile now contains an object that acts like a dictionary
                # of dictionaries, with the outer keys the data for each
                # structure listed in the cif, next the normal cif data, like
                # '_cell_angle_alpha', and '_atom_site_fract_[xyz]'.
                # Note that as indicated above, the cif can hold multiple
                # structures. For now I will assume that there is only one.
                cif_dict = cifFile[list(cifFile.keys())[0]]

                # Now lets make all of the data structures that we want out of
                # this. We are using the CellData structure from cif2cell's
                # uctools package. Right now, I have cif2cell write another
                # cif file first, then we read it in and analyze it. This is
                # because we don't want to reproduce all of the sanity check
                # that cif2cell already has in it.
                cell_data = CellData()
                # Fill the cell data object from the cif file.
                cell_data.getFromCIF(cif_dict)

                # Calculate cell structure for the primitive cell for now. Supercells are
                # represented as P1, so this will not harm that.
                cell_data.primitive()

                # The cell_data structure now has all cell data that we need
                # in it, or a method to get that data.
                if 'cell_vectors' in output:
                    output['cell_vectors'] = cell_data.latticevectors

                if 'cell_struct_xyz_red' in output:
                    xred = []
                    for atom in cell_data.atomdata:
                        if atom:
                            xred = xred + [atom[0].position]

                    output['cell_struct_xyz_red'] = xred

                if 'cell_scaling_iso' in output:
                    output['cell_scaling_iso'] = [[cell_data.lengthscale]]

                if 'cell_scaling_abc' in output:
                    # For now I will output cell_data_abc as 1, since cif2cell seems to put things into lengthscale
                    # and a,b,c are for convenience.
                    output['cell_scaling_abc'] = [[1.0, 1.0, 1.0]]

        elif 'cell_structure' in output:
            # Return path to cif file.
            output['cell_structure'] = [['Working']]
Example #35
0
def read_cif(filename: str_PathLike, pps: muti_Dict = [{}], orbitals: muti_Dict = [{}], masses: muti_Dict = [{}], magmoms: muti_Dict = [{}], move: muti_Dict = [{}], abfs: muti_Dict = [{}]) -> List[Stru]:
    """Read CIF(Crystallographic Information Framework) file and return `Stru` object

    :params filename: name of cif file
    """


    raise UserWarning("Can only read direct positions, generating equivalent atoms based on site symmetry or Wackoff positions are not supported now")
    from CifFile import ReadCif
    strulist = []

    def list_elem2split(l):
        def list_split(s):
            return s.split('(')[0]
        return list(map(list_split, l))

    def get_elements(string):
        return re.search(r'([A-Z][a-z]?)', string).group(0)

    cf = ReadCif(filename)
    for index, name in enumerate(cf.keys()):
        data = cf[name]
        fract_x = list_elem2split(data["_atom_site_fract_x"])
        fract_y = list_elem2split(data["_atom_site_fract_y"])
        fract_z = list_elem2split(data["_atom_site_fract_z"])
        if "_atom_site_type_symbol" in data.keys():
            elements = list(map(get_elements, data["_atom_site_type_symbol"]))
        else:
            elements = list(map(get_elements, data["_atom_site_label"]))
        scaled_positions = defaultdict(list)
        for i, elem in enumerate(elements):
            scaled_positions[elem].append([np.array(fract_x[i], dtype=float), np.array(
                fract_y[i], dtype=float), np.array(fract_z[i], dtype=float)])

        la = float(data["_cell_length_a"].split('(')[0])
        lb = float(data["_cell_length_b"].split('(')[0])
        lc = float(data["_cell_length_c"].split('(')[0])
        alpha = float(data["_cell_angle_alpha"].split('(')[0])
        beta = float(data["_cell_angle_beta"].split('(')[0])
        gamma = float(data["_cell_angle_gamma"].split('(')[0])

        if "_symmetry_cell_setting" in data.keys():
            crystal_system = data["_symmetry_cell_setting"]
        elif "_symmetry_Int_Tables_number" in data.keys():
            crystal_system = Spacegroup().get_crystal_system(
                data["_symmetry_Int_Tables_number"])
        elif "_space_group_name_Hall" in data.keys():
            crystal_system = Spacegroup().get_crystal_system(
                Hall2Number[data["_space_group_name_Hall"]])
        elif "_symmetry_space_group_name_H-M" in data.keys():
            crystal_system = Spacegroup().get_crystal_system(
                Hall2Number[HM2Hall[data["_symmetry_space_group_name_H-M "]]])
        else:
            crystal_system = 'unknown'

        cell = conventional_cell(
            la, lb, lc, alpha, beta, gamma, crystal_system)

        strulist.append(Stru(lat0=1/BOHR_TO_A, cell=cell, pps=pps[index], scaled_positions=scaled_positions,
                             orbitals=orbitals[index], masses=masses[index], magmoms=magmoms[index], move=move[index], abfs=abfs[index]))

    return strulist
Example #36
0
 def data_harvest(self, cif_file):                
                 
     #Resets the dataframes/dictionaries            
                 
     for item in self.search_items:
         self.results[item] = []
         self.errors[item] = []
     self.temp_df = pd.DataFrame()
     
     #This notation is from the CifFile module and allows for easy searching of parameters
     
     cif = ReadCif(cif_file)
     
     #Identifies datablocks within the CIF file
     
     data_blocks = []
     
     with open (cif_file, 'rt') as f:
         for line in f:
             if line.startswith('data_'):
                 data_blocks.append(line.strip('\n').strip('data_'))
                 
     number_of_structures = len(data_blocks)
     
             
     #For each search item in the config file, the cif file is searched 
     
     for item in self.search_items:
         self.logger.info('File ' + pathlib.Path(cif_file.lower()).stem + ' opened. Searching for parameter ' + item)
         
         #This parameter is blanked every loop because each cif is searched multiple times
         
         self.cif_list = []
         
         #Since the CifFile module works by looking at data-blocks, use the found list of data blocks to search through the CIF
         
         for experiment in data_blocks:
             try:
                 raw = cif[experiment][item]
             except:
                 self.logger.critical('Failed to find ' + item + ' in ' + pathlib.Path(cif_file.lower()).stem)
                 exit()
             
             self.logger.info('File ' + pathlib.Path(cif_file.lower()).stem + ' - found parameter ' + item)
             self.cif_list.append(pathlib.Path(cif_file.lower()).stem)
             
             #Check if an error value is present and separates the value and the error, converts the error to the correct decimal point, and assigns an error of 0 if no error present 
             
             if '(' in raw:
                 temp = raw.split('(')
                 temp2 = temp[1].strip(')')
                 self.results[item].append(float(temp[0]))
                 if '.' in raw:
                     temp3 = temp[0].split('.')
                     self.errors[item].append(int(temp2)*10**-(int(len(temp3[1]))))
                 else:
                     self.errors[item].append(int(temp2))
             
             else:
                 self.results[item].append(float(raw))
                 self.errors[item].append(0)
      
     #Creates a column in the data frame to include the file name of the CIF
     
     self.temp_df['CIF File'] = self.cif_list
     
     #Adds all of the data to one data frame 
         
     for para in self.search_items:
         if len(self.results[para]) != 0:
             self.temp_df[para] = self.results[para]
             self.temp_df[para + '_error'] = self.errors[para]
     
     return self.temp_df, number_of_structures, data_blocks