示例#1
0
def braket2float(s):
    try:
        return float(s)
    except ValueError:
        if isinstance(s, str):
            return str2float(s)
        raise TypeError('cannot parse {} into float'.format(s))
示例#2
0
 def get_symme(self):
     for d in self._cif.data.values():
         data = d
         # Try to parse International number
         for symmetry_label in [
                 "_space_group_IT_number", "_space_group_IT_number_",
                 "_symmetry_Int_Tables_number",
                 "_symmetry_Int_Tables_number_"
         ]:
             if data.data.get(symmetry_label):
                 symm_number = int(str2float(data.data.get(symmetry_label)))
                 break
         for symmetry_label in [
                 "_symmetry_space_group_name_H-M",
                 "_symmetry_space_group_name_H_M",
                 "_symmetry_space_group_name_H-M_",
                 "_symmetry_space_group_name_H_M_",
                 "_space_group_name_Hall", "_space_group_name_Hall_",
                 "_space_group_name_H-M_alt", "_space_group_name_H-M_alt_",
                 "_symmetry_space_group_name_hall",
                 "_symmetry_space_group_name_hall_",
                 "_symmetry_space_group_name_h-m",
                 "_symmetry_space_group_name_h-m_"
         ]:
             if data.data.get(symmetry_label):
                 sg = data.data.get(symmetry_label)
                 break
     return symm_number, sg
示例#3
0
    def _get_structure(self, data, primitive):
        """
        Generate structure from part of the cif.
        """
        def get_num_implicit_hydrogens(sym):
            num_h = {"Wat": 2, "wat": 2, "O-H": 1}
            return num_h.get(sym[:3], 0)

        lattice = self.get_lattice(data)

        # if magCIF, get magnetic symmetry moments and magmoms
        # else standard CIF, and use empty magmom dict
        if self.feature_flags["magcif_incommensurate"]:
            raise NotImplementedError(
                "Incommensurate structures not currently supported.")
        elif self.feature_flags["magcif"]:
            self.symmetry_operations = self.get_magsymops(data)
            magmoms = self.parse_magmoms(data, lattice=lattice)
        else:
            self.symmetry_operations = self.get_symops(data)
            magmoms = {}

        oxi_states = self.parse_oxi_states(data)
        coord_to_species = OrderedDict()
        coord_to_magmoms = OrderedDict()

        def get_matching_coord(coord):
            keys = list(coord_to_species.keys())
            coords = np.array(keys)
            for op in self.symmetry_operations:
                c = op.operate(coord)
                inds = find_in_coord_list_pbc(coords,
                                              c,
                                              atol=self._site_tolerance)
                # cant use if inds, because python is dumb and np.array([0]) evaluates
                # to False
                if len(inds):
                    return keys[inds[0]]
            return False

        label_el_dict = {}

        for i in range(len(data["_atom_site_label"])):
            try:
                # If site type symbol exists, use it. Otherwise, we use the
                # label.
                symbol = self._parse_symbol(data["_atom_site_type_symbol"][i])

                label = data["_atom_site_label"][i]

                num_h = get_num_implicit_hydrogens(
                    data["_atom_site_type_symbol"][i])

            except KeyError:
                symbol = self._parse_symbol(data["_atom_site_label"][i])

                label = data["_atom_site_label"][i]

                num_h = get_num_implicit_hydrogens(data["_atom_site_label"][i])
            if not symbol:
                continue

            if oxi_states is not None:
                o_s = oxi_states.get(symbol, 0)
                # use _atom_site_type_symbol if possible for oxidation state
                if "_atom_site_type_symbol" in data.data.keys():
                    oxi_symbol = data["_atom_site_type_symbol"][i]
                    o_s = oxi_states.get(oxi_symbol, o_s)
                try:
                    el = Specie(symbol, o_s)
                except:
                    el = DummySpecie(symbol, o_s)
            else:
                el = get_el_sp(symbol)

            x = str2float(data["_atom_site_fract_x"][i])
            y = str2float(data["_atom_site_fract_y"][i])
            z = str2float(data["_atom_site_fract_z"][i])
            magmom = magmoms.get(data["_atom_site_label"][i],
                                 np.array([0, 0, 0]))

            try:
                occu = str2float(data["_atom_site_occupancy"][i])
            except (KeyError, ValueError):
                occu = 1

            if occu > 0:
                coord = (x, y, z)
                match = get_matching_coord(coord)
                comp_d = {el: occu}

                if num_h > 0:
                    comp_d["H"] = num_h
                comp = Composition(comp_d)
                if not match:
                    coord_to_species[coord] = comp
                    coord_to_magmoms[coord] = magmom
                else:
                    coord_to_species[match] += comp
                    # disordered magnetic not currently supported
                    coord_to_magmoms[match] = None

            label_el_dict[coord] = label

        sum_occu = [
            sum(c.values()) for c in coord_to_species.values() if
            not set(c.elements) == {Element("O"), Element("H")}
        ]
        if any([o > 1 for o in sum_occu]):
            msg = "Some occupancies (%s) sum to > 1! If they are within " \
                    "the tolerance, they will be rescaled." % str(sum_occu)
            warnings.warn(msg)
            self.errors.append(msg)

        allspecies = []
        allcoords = []
        allmagmoms = []
        allhydrogens = []
        alllabels = []

        # check to see if magCIF file is disordered
        if self.feature_flags["magcif"]:
            for k, v in coord_to_magmoms.items():
                if v is None:
                    # Proposed solution to this is to instead store magnetic
                    # moments as Specie 'spin' property, instead of site
                    # property, but this introduces ambiguities for end user
                    # (such as unintended use of `spin` and Specie will have
                    # fictious oxidation state).
                    raise NotImplementedError(
                        'Disordered magnetic structures not currently supported.'
                    )
        if coord_to_species.items():
            for comp, group in groupby(sorted(list(coord_to_species.items()),
                                              key=lambda x: x[1]),
                                       key=lambda x: x[1]):
                tmp_coords = [site[0] for site in group]

                #print(tmp_coords)
                labels = []
                for i in tmp_coords:
                    labels.append(label_el_dict[i])

                #print(labels)
                tmp_magmom = [
                    coord_to_magmoms[tmp_coord] for tmp_coord in tmp_coords
                ]
                if self.feature_flags["magcif"]:
                    coords, magmoms, coords_num = self._unique_coords(
                        tmp_coords, magmoms_in=tmp_magmom, lattice=lattice)
                else:
                    coords, magmoms, coords_num = self._unique_coords(
                        tmp_coords)

                if set(comp.elements) == {Element("O"), Element("H")}:
                    # O with implicit hydrogens
                    im_h = comp["H"]
                    species = Composition({"O": comp["O"]})
                else:
                    im_h = 0
                    species = comp

                allhydrogens.extend(len(coords) * [im_h])
                allcoords.extend(coords)
                allspecies.extend(len(coords) * [species])
                allmagmoms.extend(magmoms)

                for i in range(len(coords_num)):

                    alllabels.extend(coords_num[i] * [labels[i]])

            # rescale occupancies if necessary
            for i, species in enumerate(allspecies):
                totaloccu = sum(species.values())
                if 1 < totaloccu <= self._occupancy_tolerance:
                    allspecies[i] = species / totaloccu

        if allspecies and len(allspecies) == len(allcoords) \
                and len(allspecies) == len(allmagmoms):
            site_properties = dict()
            if any(allhydrogens):
                assert len(allhydrogens) == len(allcoords)
                site_properties["implicit_hydrogens"] = allhydrogens

            if self.feature_flags["magcif"]:
                site_properties["magmom"] = allmagmoms

            if len(site_properties) == 0:
                site_properties = None

            struct = Structure(lattice,
                               allspecies,
                               allcoords,
                               site_properties=site_properties)
            #struct = struct.get_sorted_structure()

            if primitive and self.feature_flags['magcif']:
                struct = struct.get_primitive_structure(use_site_props=True)
            elif primitive:
                struct = struct.get_primitive_structure()
                struct = struct.get_reduced_structure()
            struct.add_site_property("_atom_site_label", alllabels)
            return struct