Пример #1
0
    def predictions_structure_comparison(self, structure_dict, comparator=ElementComparator()):
    
        ''' Compares the entries in the same dictionary containing structures '''
        ''' Returns a dictionary of structures that aren't repeated in the dictionary '''

        sm = StructureMatcher(comparator=comparator, primitive_cell=False)
        filtered_structures = {} # new filtered dictionary
        seen_structures = {} # list of all seen structures, grouped by chemical system

        for chemsys in structure_dict:
            filtered_structures[chemsys] = []
            seen_structures[chemsys] = []

            for struct in structure_dict[chemsys]:
                found = False

                for seen_struct in seen_structures[chemsys]:
                    if sm.fit(struct.final_structure, seen_struct.final_structure):
                        found = True
                        break

                if not found:
                    filtered_structures[chemsys].append(struct)
                    seen_structures[chemsys].append(struct)

        return filtered_structures
Пример #2
0
    def filter_and_group_tasks(self, tasks):
        """
        Groups tasks by structure matching
        """

        filtered_tasks = [t for t in tasks if task_type(
            t['input']['incar']) in self.allowed_tasks]

        structures = [Structure.from_dict(
            t["output"]['structure']) for t in filtered_tasks]

        if self.separate_mag_orderings:
            for structure in structures:
                if has(structure.site_properties,"magmom"):
                    structure.add_spin_by_site(structure.site_properties['magmom'])
                    structure.remove_site_property('magmom')

        for idx, s in enumerate(structures):
            s.index = idx

        sm = StructureMatcher(ltol=self.ltol, stol=self.stol, angle_tol=self.angle_tol,
                              primitive_cell=True, scale=True,
                              attempt_supercell=False, allow_subset=False,
                              comparator=ElementComparator())

        grouped_structures = sm.group_structures(structures)

        grouped_tasks = [[filtered_tasks[struc.index]
                          for struc in group] for group in grouped_structures]

        return grouped_tasks
Пример #3
0
    def MP_structure_comparison(self, structure_dict1, structure_dict2, comparator=ElementComparator()):
    
        ''' Compares the entries between two different dictionaries containing structures '''
        ''' Returns a dictionary of structures that aren't present in both dictionaries '''

        sm = StructureMatcher(comparator=comparator, primitive_cell=False)
        final_filtered_structs = {}

        for chemsys in structure_dict1.keys():
            final_filtered_structs[chemsys] = []

            if chemsys in structure_dict2.keys():
                found = False

                for struct1 in structure_dict1[chemsys]:
                    for struct2 in structure_dict2[chemsys]:
                        if sm.fit(struct1.final_structure, struct2):
                            found = True
                            break 

                    if not found:
                        final_filtered_structs[chemsys].append(struct1)

            else:
                final_filtered_structs[chemsys] = structure_dict1[chemsys]
        
        removed_empty_structs = {k: v for k, v in final_filtered_structs.items() if v != []}
        
        return removed_empty_structs
Пример #4
0
    def _match_material(self, doc, ltol=0.2, stol=0.3, angle_tol=5):
        """
        Returns the material_id that has the same structure as this doc as
         determined by the structure matcher. Returns None if no match.

        Args:
            doc (dict): a JSON-like document
            ltol (float): StructureMatcher tuning parameter 
            stol (float): StructureMatcher tuning parameter 
            angle_tol (float): StructureMatcher tuning parameter 

        Returns:
            (int) matching material_id or None
        """
        formula = doc["formula_reduced_abc"]
        sgnum = doc["spacegroup"]["number"]

        for m in self._materials.find({"formula_reduced_abc": formula, "sg_number": sgnum},
                                      {"structure": 1, "material_id": 1}):

            m_struct = Structure.from_dict(m["structure"])
            t_struct = Structure.from_dict(doc["structure"])

            sm = StructureMatcher(ltol=ltol, stol=stol, angle_tol=angle_tol,
                                  primitive_cell=True, scale=True,
                                  attempt_supercell=False, allow_subset=False,
                                  comparator=ElementComparator())

            if sm.fit(m_struct, t_struct):
                return m["material_id"]

        return None
Пример #5
0
    def __init__(
        self,
        existing_structures,
        structure_matcher=StructureMatcher(comparator=ElementComparator()),
        symprec=None,
    ):
        """
        Remove existing structures based on the structure matcher
        and symmetry (if symprec is given).

        Args:
            existing_structures: List of existing structures to compare with
            structure_matcher: Provides a structure matcher to be used for
                structure comparison.
            symprec: The precision in the symmetry finder algorithm if None (
                default value), no symmetry check is performed and only the
                structure matcher is used. A recommended value is 1e-5.
        """
        self.symprec = symprec
        self.structure_list = []
        self.existing_structures = existing_structures
        if isinstance(structure_matcher, dict):
            self.structure_matcher = StructureMatcher.from_dict(structure_matcher)
        else:
            self.structure_matcher = structure_matcher
Пример #6
0
 def get_items(self):
     materials, jobs = self.sources
     matcher = StructureMatcher(ltol=LTOL,
                                stol=STOL,
                                angle_tol=ANGLE_TOL,
                                primitive_cell=True,
                                scale=True,
                                attempt_supercell=False,
                                comparator=ElementComparator())
     jobs = list(jobs.query({"wflow.status": "release-ready"}))
     self.total = len(jobs)
     for job in jobs:
         structure = Structure.from_dict(job)
         criteria = {
             "pretty_formula": structure.composition.reduced_formula
         }
         material_id = next(
             (r['task_id']
              for r in materials.query(criteria, ['structure', 'task_id'])
              if matcher.fit(structure, Structure.from_dict(r['structure']))
              ), None)
         if material_id:
             yield ({
                 "snl_id": job["snl_id"]
             }, {
                 "wflow.status": "released",
                 "wflow.material_id": material_id
             })
Пример #7
0
    def run_task(self, fw_spec):
        db = SPStructuresMongoAdapter.auto_load()
        tstructs = []
        species = fw_spec['species']
        t = fw_spec['threshold']
        for p in SubstitutionPredictor(threshold=t).list_prediction(species):
            subs = p['substitutions']
            if len(set(subs.values())) < len(species):
                continue
            st = SubstitutionTransformation(subs)
            target = map(str, subs.keys())
            for snl in db.get_snls(target):
                ts = TransformedStructure.from_snl(snl)
                ts.append_transformation(st)
                if ts.final_structure.charge == 0:
                    tstructs.append(ts)

        transmuter = StandardTransmuter(tstructs)
        f = RemoveDuplicatesFilter(structure_matcher=StructureMatcher(
            comparator=ElementComparator(), primitive_cell=False))
        transmuter.apply_filter(f)
        results = []
        for ts in transmuter.transformed_structures:
            results.append(ts.to_snl([]).to_dict)
        submissions = SPSubmissionsMongoAdapter.auto_load()
        submissions.insert_results(fw_spec['submission_id'], results)
Пример #8
0
def compare_structures(args):
    """
    Compare structures in files for similarity using structure matcher.

    Args:
        args (dict): Args from argparse.
    """
    filenames = args.filenames
    if len(filenames) < 2:
        print("You need more than one structure to compare!")
        sys.exit(-1)
    try:
        structures = [Structure.from_file(fn) for fn in filenames]
    except Exception as ex:
        print("Error converting file. Are they in the right format?")
        print(str(ex))
        sys.exit(-1)

    m = (StructureMatcher() if args.group == "species" else StructureMatcher(
        comparator=ElementComparator()))
    for i, grp in enumerate(m.group_structures(structures)):
        print("Group {}: ".format(i))
        for s in grp:
            print("- {} ({})".format(filenames[structures.index(s)],
                                     s.formula))
        print()
Пример #9
0
 def __init__(self,
              materials,
              electro,
              working_ion,
              query=None,
              compatibility=MaterialsProjectCompatibility("Advanced"),
              **kwargs):
     """
     Calculates physical parameters of battery materials the battery entries using
     groups of ComputedStructureEntry and the entry for the most stable version of the working_ion in the system
     Args:
         materials (Store): Store of materials documents that contains the structures
         electro (Store): Store of insertion electrodes data such as voltage and capacity
         query (dict): dictionary to limit materials to be analyzed --- only applied to the materials when we need to group structures
                         the phase diagram is still constructed with the entire set
         compatibility (PymatgenCompatability): Compatability module
             to ensure energies are compatible
     """
     self.sm = StructureMatcher(comparator=ElementComparator(),
                                primitive_cell=False)
     self.materials = materials
     self.electro = electro
     self.working_ion = working_ion
     self.query = query if query else {}
     self.compatibility = compatibility
     self.completed_tasks = set()
     self.working_ion_entry = None
     super().__init__(sources=[materials], targets=[electro], **kwargs)
Пример #10
0
    def match(self, task, mats):
        """ 
        Finds a material doc that matches with the given task
        
        Args:
            task (dict): the task doc
            mats ([dict]): the materials docs to match against
        
        Returns:
            dict: a materials doc if one is found otherwise returns None
        """
        sm = StructureMatcher(ltol=self.ltol,
                              stol=self.stol,
                              angle_tol=self.angle_tol,
                              primitive_cell=True,
                              scale=True,
                              attempt_supercell=False,
                              allow_subset=False,
                              comparator=ElementComparator())
        t_struct = Structure.from_dict(task["output"]["structure"])

        for m in mats:
            m_struct = Structure.from_dict(m["structure"])
            if task["output"]["spacegroup"]["number"] == m["spacegroup"]["number"] and \
                    sm.fit(m_struct, t_struct):
                return m

        return None
Пример #11
0
    def test_no_scaling(self):
        sm = StructureMatcher(ltol=0.1, stol=0.1, angle_tol=2,
                              scale=False, comparator=ElementComparator())
        self.assertTrue(sm.fit(self.struct_list[0], self.struct_list[1]))

        self.assertTrue(sm.get_rms_dist(self.struct_list[0],
                                        self.struct_list[1])[0] < 0.0008)
Пример #12
0
    def add_if_belongs(self, cand_snl):

        # no need to compare if different formulas or spacegroups
        if cand_snl.snlgroup_key != self.canonical_snl.snlgroup_key:
            return False, None

        # no need to compare if one is ordered, the other disordered
        if not (cand_snl.structure.is_ordered == self.canonical_structure.is_ordered):
            return False, None

        # filter out large C-Ce structures
        comp = cand_snl.structure.composition
        elsyms = sorted(set([e.symbol for e in comp.elements]))
        chemsys = '-'.join(elsyms)
        if (
                cand_snl.structure.num_sites > 1500 or self.canonical_structure.num_sites > 1500) and chemsys == 'C-Ce':
            print 'SKIPPING LARGE C-Ce'
            return False, None

        # make sure the structure is not already in all_structures
        if cand_snl.snl_id in self.all_snl_ids:
            print 'WARNING: add_if_belongs() has detected that you are trying to add the same SNL id twice!'
            return False, None

        #try a structure fit to the canonical structure

        # use default Structure Matcher params from April 24, 2013, as suggested by Shyue
        # we are using the ElementComparator() because this is how we want to group results
        sm = StructureMatcher(ltol=0.2, stol=0.3, angle_tol=5, primitive_cell=True, scale=True,
                              attempt_supercell=False, comparator=ElementComparator())

        if not sm.fit(cand_snl.structure, self.canonical_structure):
            return False, None

        # everything checks out, add to the group
        self.all_snl_ids.append(cand_snl.snl_id)

        # now that we are in the group, if there are site properties we need to check species_groups
        # e.g., if there is another SNL in the group with the same site properties, e.g. MAGMOM
        spec_group = None

        if has_species_properties(cand_snl.structure):
            for snl in self.species_snl:
                sms = StructureMatcher(ltol=0.2, stol=0.3, angle_tol=5, primitive_cell=True, scale=True,
                              attempt_supercell=False, comparator=SpeciesComparator())
                if sms.fit(cand_snl.structure, snl.structure):
                    spec_group = snl.snl_id
                    self.species_groups[snl.snl_id].append(cand_snl.snl_id)
                    break

            # add a new species group
            if not spec_group:
                self.species_groups[cand_snl.snl_id] = [cand_snl.snl_id]
                self.species_snl.append(cand_snl)
                spec_group = cand_snl.snl_id

        self.updated_at = datetime.datetime.utcnow()

        return True, spec_group
    def __init__(self,
                 base_struct_entry,
                 single_cat_entries,
                 migrating_specie,
                 base_aeccar=None,
                 max_path_length=4,
                 ltol=0.2,
                 stol=0.3,
                 angle_tol=5):
        """
        Pass in a entries for analysis

        Args:
          base_struct_entry: the structure without a working ion for us to analyze the migration
          single_cat_entries: list of structures containing a single cation at different positions
          base_aeccar: Chgcar object that contains the AECCAR0 + AECCAR2 (Default value = None)
          migration_specie: a String symbol or Element for the cation. (Default value = 'Li')
          ltol: parameter for StructureMatcher (Default value = 0.2)
          stol: parameter for StructureMatcher (Default value = 0.3)
          angle_tol: parameter for StructureMatcher (Default value = 5)
        """

        self.single_cat_entries = single_cat_entries
        self.base_struct_entry = base_struct_entry
        self.base_aeccar = base_aeccar
        self._tube_radius = 0
        self.sm = StructureMatcher(
            comparator=ElementComparator(),
            primitive_cell=False,
            ignored_species=[migrating_specie],
            ltol=ltol,
            stol=stol,
            angle_tol=angle_tol)

        logger.debug('See if the structures all match')
        for ent in self.single_cat_entries:
            assert (self.sm.fit(self.base_struct_entry.structure,
                                ent.structure))

        self.translated_single_cat_entries = list(
            map(self.match_ent_to_base, self.single_cat_entries))

        self.full_sites = self.get_full_sites()
        self.base_structure_full_sites = self.full_sites.copy()
        self.base_structure_full_sites.sites.extend(
            self.base_struct_entry.structure.sites)

        # Initialize
        super(ComputedEntryPath, self).__init__(
            structure=self.base_structure_full_sites,
            migrating_specie=migrating_specie,
            max_path_length=max_path_length,
            symprec=0.1,
            vac_mode=False)

        self.populate_edges_with_migration_paths()
        self.group_and_label_hops()
        self.get_unique_hops_dict()
        self._setup_grids()
Пример #14
0
def filter_entries(structure_type, all_entries, species, return_removed=False):
    """
    Filter out the entry with exact same structure as queried entry among the
    entries in queried chemical space obtained from Materials Project.

    Used Pymatgen.analysis.structure_matcher.fit_anonymous to match the prototype
    of give structures.

    Args:
        structure_type(str): "garnet" or "perovskite"
         all_entries (list): entries in queried chemical space obtained from Materials Project
         composition (Composition): composition of queried entry
         return_removed (bool): If True, return the filtered entries

    Returns:
        filtered_entries (list)
    """
    global MATCHER, PROTO
    if not MATCHER:
        MATCHER = StructureMatcher(ltol=0.2,
                                   stol=0.3,
                                   angle_tol=5,
                                   primitive_cell=True,
                                   comparator=ElementComparator())

    if not PROTO:
        garnet_proto_path = os.path.join(DATA_DIR, "garnet/proto_mp-3050.cif")
        perov_proto_path = os.path.join(DATA_DIR,
                                        "perovskite/proto_mp-4019.cif")
        PROTO = {
            "garnet":
            Structure.from_file(garnet_proto_path).get_primitive_structure(),
            "perovskite":
            Structure.from_file(perov_proto_path).get_primitive_structure()
        }
        a_sites = [60, 61, 62, 63, 64, 65, 66, 67]
        for site_ind in a_sites:
            PROTO['garnet'].replace(site_ind, {"Ga": 1})

    P = PROTO[structure_type].copy()
    if structure_type == 'garnet:':
        P.replace_species({
            "Y": species['c'],
            "Ga": species['a'],
            "Al": species['d']
        })
    elif structure_type == 'perovskite':
        P.replace_species({"Ca": species['a'], "Ti": species['b']})
    composition = Composition(spe2form(structure_type, species))
    if not return_removed:
        return [e for e in all_entries \
                if e.name != composition.reduced_formula \
                and not MATCHER.fit(e.structure, P)]
    else:
        removed = [e for e in all_entries \
                   if e.name == composition.reduced_formula \
                   and MATCHER.fit(e.structure, P)]
        return removed, [e for e in all_entries if e not in removed]
Пример #15
0
def group_structures(
    structures,
    ltol=LTOL,
    stol=STOL,
    angle_tol=ANGLE_TOL,
    symprec=SYMPREC,
    separate_mag_orderings=False,
):
    """
    Groups structures according to space group and structure matching

    Args:
        structures ([Structure]): list of structures to group
        ltol (float): StructureMatcher tuning parameter for matching tasks to materials
        stol (float): StructureMatcher tuning parameter for matching tasks to materials
        angle_tol (float): StructureMatcher tuning parameter for matching tasks to materials
        symprec (float): symmetry tolerance for space group finding
        separate_mag_orderings (bool): Separate magnetic orderings into different materials
    """

    sm = StructureMatcher(
        ltol=ltol,
        stol=stol,
        angle_tol=angle_tol,
        primitive_cell=True,
        scale=True,
        attempt_supercell=False,
        allow_subset=False,
        comparator=ElementComparator(),
    )

    def get_sg(struc):
        # helper function to get spacegroup with a loose tolerance
        try:
            sg = struc.get_space_group_info(symprec=SYMPREC)[1]
        except:
            sg = -1

        return sg

    def get_mag_ordering(struc):
        # helperd function to get a label of the magnetic ordering type
        return np.around(np.abs(struc.total_magnetization) / struc.volume,
                         decimals=1)

    # First group by spacegroup number then by structure matching
    for sg, pregroup in groupby(sorted(structures, key=get_sg), key=get_sg):
        for group in sm.group_structures(list(pregroup)):

            # Match magnetic orderings here
            if separate_mag_orderings:
                for _, mag_group in groupby(sorted(group,
                                                   key=get_mag_ordering),
                                            key=get_mag_ordering):
                    yield list(mag_group)
            else:
                yield group
Пример #16
0
    def test_get_mask(self):
        sm = StructureMatcher(comparator=ElementComparator())
        l = Lattice.cubic(1)
        s1 = Structure(l, ['Mg', 'Cu', 'Ag', 'Cu'], [[0] * 3] * 4)
        s2 = Structure(l, ['Cu', 'Cu', 'Ag'], [[0] * 3] * 3)

        result = [[True, False, True, False],
                  [True, False, True, False],
                  [True, True, False, True]]
        m, inds, i = sm._get_mask(s1, s2, 1, True)
        self.assertTrue(np.all(m == result))
        self.assertTrue(i == 2)
        self.assertEqual(inds, [2])

        # test supercell with match
        result = [[1, 1, 0, 0, 1, 1, 0, 0],
                  [1, 1, 0, 0, 1, 1, 0, 0],
                  [1, 1, 1, 1, 0, 0, 1, 1]]
        m, inds, i = sm._get_mask(s1, s2, 2, True)
        self.assertTrue(np.all(m == result))
        self.assertTrue(i == 2)
        self.assertTrue(np.allclose(inds, np.array([4])))

        # test supercell without match
        result = [[1, 1, 1, 1, 1, 1],
                  [0, 0, 0, 0, 1, 1],
                  [1, 1, 1, 1, 0, 0],
                  [0, 0, 0, 0, 1, 1]]
        m, inds, i = sm._get_mask(s2, s1, 2, True)
        self.assertTrue(np.all(m == result))
        self.assertTrue(i == 0)
        self.assertTrue(np.allclose(inds, np.array([])))

        # test s2_supercell
        result = [[1, 1, 1], [1, 1, 1],
                  [0, 0, 1], [0, 0, 1],
                  [1, 1, 0], [1, 1, 0],
                  [0, 0, 1], [0, 0, 1]]
        m, inds, i = sm._get_mask(s2, s1, 2, False)
        self.assertTrue(np.all(m == result))
        self.assertTrue(i == 0)
        self.assertTrue(np.allclose(inds, np.array([])))

        # test for multiple translation indices
        s1 = Structure(l, ['Cu', 'Ag', 'Cu', 'Ag', 'Ag'], [[0] * 3] * 5)
        s2 = Structure(l, ['Ag', 'Cu', 'Ag'], [[0] * 3] * 3)
        result = [[1, 0, 1, 0, 0],
                  [0, 1, 0, 1, 1],
                  [1, 0, 1, 0, 0]]
        m, inds, i = sm._get_mask(s1, s2, 1, True)

        self.assertTrue(np.all(m == result))
        self.assertTrue(i == 1)
        self.assertTrue(np.allclose(inds, [0, 2]))
Пример #17
0
    def _match_material(self, taskdoc, ltol=0.2, stol=0.3, angle_tol=5):
        """
        Returns the material_id that has the same structure as this task as
         determined by the structure matcher. Returns None if no match.

        Args:
            taskdoc (dict): a JSON-like task document
            ltol (float): StructureMatcher tuning parameter
            stol (float): StructureMatcher tuning parameter
            angle_tol (float): StructureMatcher tuning parameter

        Returns:
            (int) matching material_id or None
        """
        formula = taskdoc["formula_reduced_abc"]

        # handle the "parent structure" option, which is used to intentionally force slightly
        # different structures to contribute to the same "material", e.g. from an ordering scheme
        if "parent_structure" in taskdoc:
            t_struct = Structure.from_dict(
                taskdoc["parent_structure"]["structure"])
            q = {
                "formula_reduced_abc":
                formula,
                "parent_structure.spacegroup.number":
                taskdoc["parent_structure"]["spacegroup"]["number"]
            }
        else:
            sgnum = taskdoc["output"]["spacegroup"]["number"]
            t_struct = Structure.from_dict(taskdoc["output"]["structure"])
            q = {"formula_reduced_abc": formula, "sg_number": sgnum}

        for m in self._materials.find(q, {
                "parent_structure": 1,
                "structure": 1,
                "material_id": 1
        }):
            s_dict = m["parent_structure"][
                "structure"] if "parent_structure" in m else m["structure"]
            m_struct = Structure.from_dict(s_dict)
            sm = StructureMatcher(ltol=ltol,
                                  stol=stol,
                                  angle_tol=angle_tol,
                                  primitive_cell=True,
                                  scale=True,
                                  attempt_supercell=False,
                                  allow_subset=False,
                                  comparator=ElementComparator())

            if sm.fit(m_struct, t_struct):
                return m["material_id"]

        return None
Пример #18
0
 def test_mix(self):
     structures = []
     for fname in ["POSCAR.Li2O", "Li2O.cif", "Li2O2.cif", "LiFePO4.cif",
                   "POSCAR.LiFePO4"]:
         structures.append(read_structure(os.path.join(test_dir, fname)))
     sm = StructureMatcher(comparator=ElementComparator())
     groups = sm.group_structures(structures)
     for g in groups:
         formula = g[0].composition.reduced_formula
         if formula in ["Li2O", "LiFePO4"]:
             self.assertEqual(len(g), 2)
         else:
             self.assertEqual(len(g), 1)
Пример #19
0
    def match(self, snls, mat):
        """
        Finds a material doc that matches with the given snl

        Args:
            snl ([dict]): the snls list
            mat (dict): a materials doc

        Returns:
            generator of materials doc keys
        """
        sm = StructureMatcher(ltol=LTOL,
                              stol=STOL,
                              angle_tol=ANGLE_TOL,
                              primitive_cell=True,
                              scale=True,
                              attempt_supercell=False,
                              allow_subset=False,
                              comparator=ElementComparator())

        m_strucs = [Structure.from_dict(mat["structure"])] + [
            Structure.from_dict(init_struc)
            for init_struc in mat["initial_structures"]
        ]
        for snl in snls:
            try:
                snl_struc = StructureNL.from_dict(snl).structure
                # Get SNL Spacegroup
                # This try-except fixes issues for some structures where space group data is not returned by spglib
                try:
                    snl_spacegroup = snl_struc.get_space_group_info(
                        symprec=0.1)[0]
                except:
                    snl_spacegroup = -1
                for struc in m_strucs:

                    # Get Materials Structure Spacegroup
                    try:
                        struc_sg = struc.get_space_group_info(symprec=0.1)[0]
                    except:
                        struc_sg = -1

                    # Match spacegroups
                    if struc_sg == snl_spacegroup and sm.fit(struc, snl_struc):
                        yield snl
                        break
            except:
                self.logger.warning("Bad SNL found : {}".format(
                    snl.get("task_id")))
Пример #20
0
    def _match_material(self, taskdoc):
        """
        Returns the material_id that has the same structure as this task as
         determined by the structure matcher. Returns None if no match.

        Args:
            taskdoc (dict): a JSON-like task document

        Returns:
            (int) matching material_id or None
        """
        formula = taskdoc["formula_reduced_abc"]

        if "parent_structure" in taskdoc:  # this is used to intentionally combine multiple data w/same formula but slightly different structure, e.g. from an ordering scheme
            t_struct = Structure.from_dict(
                taskdoc["parent_structure"]["structure"])
            q = {
                "formula_reduced_abc":
                formula,
                "parent_structure.spacegroup.number":
                taskdoc["parent_structure"]["spacegroup"]["number"]
            }
        else:
            sgnum = taskdoc["output"]["spacegroup"]["number"]
            t_struct = Structure.from_dict(taskdoc["output"]["structure"])
            q = {"formula_reduced_abc": formula, "sg_number": sgnum}

        for m in self._materials.find(q, {
                "parent_structure": 1,
                "structure": 1,
                "material_id": 1
        }):
            s_dict = m["parent_structure"][
                "structure"] if "parent_structure" in m else m["structure"]
            m_struct = Structure.from_dict(s_dict)
            sm = StructureMatcher(ltol=0.2,
                                  stol=0.3,
                                  angle_tol=5,
                                  primitive_cell=True,
                                  scale=True,
                                  attempt_supercell=False,
                                  allow_subset=False,
                                  comparator=ElementComparator())

            if sm.fit(m_struct, t_struct):
                return m["material_id"]

        return None
Пример #21
0
def group_structures(structures,
                     ltol=0.2,
                     stol=0.3,
                     angle_tol=5,
                     symprec=0.1,
                     separate_mag_orderings=False):
    """
    Groups structures according to space group and structure matching

    Args:
        structures ([Structure]): list of structures to group
        ltol (float): StructureMatcher tuning parameter for matching tasks to materials
        stol (float): StructureMatcher tuning parameter for matching tasks to materials
        angle_tol (float): StructureMatcher tuning parameter for matching tasks to materials
        symprec (float): symmetry tolerance for space group finding
        separate_mag_orderings (bool): Separate magnetic orderings into different materials
    """

    sm = StructureMatcher(ltol=ltol,
                          stol=stol,
                          angle_tol=angle_tol,
                          primitive_cell=True,
                          scale=True,
                          attempt_supercell=False,
                          allow_subset=False,
                          comparator=ElementComparator())

    def get_sg(struc):
        # helper function to get spacegroup with a loose tolerance
        return struc.get_space_group_info(symprec=symprec)[1]

    def get_mag_ordering(struc):
        # helperd function to get a label of the magnetic ordering type
        return CollinearMagneticStructureAnalyzer(struc).ordering.value

    # First group by spacegroup number then by structure matching
    for sg, pregroup in groupby(sorted(structures, key=get_sg), key=get_sg):
        for group in sm.group_structures(list(pregroup)):

            # Match magnetic orderings here
            if separate_mag_orderings:
                for _, mag_group in groupby(sorted(group,
                                                   key=get_mag_ordering),
                                            key=get_mag_ordering):
                    yield list(mag_group)
            else:
                yield group
Пример #22
0
    def setUp(self):
        self.test_ents_MOF = loadfn(
            f'{dir_path}/full_path_files/Mn6O5F7_cat_migration.json')
        self.aeccar_MOF = Chgcar.from_file(
            f'{dir_path}/full_path_files/AECCAR_Mn6O5F7.vasp')
        self.cep = ComputedEntryPath(
            base_struct_entry=self.test_ents_MOF['ent_base'],
            migrating_specie='Li',
            single_cat_entries=self.test_ents_MOF['one_cation'],
            base_aeccar=self.aeccar_MOF)

        # structure matcher used for validation
        self.rough_sm = StructureMatcher(comparator=ElementComparator(),
                                         primitive_cell=False,
                                         ltol=0.5,
                                         stol=0.5,
                                         angle_tol=7)
Пример #23
0
    def test_get_supercells(self):
        sm = StructureMatcher(comparator=ElementComparator())
        l = Lattice.cubic(1)
        l2 = Lattice.cubic(0.5)
        s1 = Structure(l, ['Mg', 'Cu', 'Ag', 'Cu'], [[0] * 3] * 4)
        s2 = Structure(l2, ['Cu', 'Cu', 'Ag'], [[0] * 3] * 3)
        scs = list(sm._get_supercells(s1, s2, 8, False))
        for x in scs:
            self.assertAlmostEqual(abs(np.linalg.det(x[3])), 8)
            self.assertEqual(len(x[0]), 4)
            self.assertEqual(len(x[1]), 24)
        self.assertEqual(len(scs), 48)

        scs = list(sm._get_supercells(s2, s1, 8, True))
        for x in scs:
            self.assertAlmostEqual(abs(np.linalg.det(x[3])), 8)
            self.assertEqual(len(x[0]), 24)
            self.assertEqual(len(x[1]), 4)
        self.assertEqual(len(scs), 48)
Пример #24
0
def compare_structures(args):
    filenames = args.filenames
    if len(filenames) < 2:
        print "You need more than one structure to compare!"
        sys.exit(-1)
    try:
        structures = map(read_structure, filenames)
    except Exception as ex:
        print "Error converting file. Are they in the right format?"
        print str(ex)
        sys.exit(-1)

    from pymatgen.analysis.structure_matcher import StructureMatcher, \
        ElementComparator
    m = StructureMatcher() if args.oxi \
        else StructureMatcher(comparator=ElementComparator())
    for i, grp in enumerate(m.group_structures(structures)):
        print "Group {}: ".format(i)
        for s in grp:
            print "- {} ({})".format(filenames[structures.index(s)], s.formula)
        print
Пример #25
0
    def post_process(self, docs):

        s1 = Structure.from_dict(self.structure)

        m = StructureMatcher(
            ltol=self.ltol,
            stol=self.stol,
            angle_tol=self.angle_tol,
            primitive_cell=True,
            scale=True,
            attempt_supercell=False,
            comparator=ElementComparator(),
        )

        matches = []

        for doc in docs:

            s2 = Structure.from_dict(doc["structure"])
            matched = m.fit(s1, s2)

            if matched:
                rms = m.get_rms_dist(s1, s2)

                matches.append({
                    "material_id": doc["material_id"],
                    "normalized_rms_displacement": rms[0],
                    "max_distance_paired_sites": rms[1],
                })

        response = sorted(
            matches[:self.limit],
            key=lambda x: (
                x["normalized_rms_displacement"],
                x["max_distance_paired_sites"],
            ),
        )

        return response
Пример #26
0
    def match(self, snls, mat):
        """
        Finds a material doc that matches with the given snl

        Args:
            snl ([dict]): the snls list
            mat (dict): a materials doc

        Returns:
            generator of materials doc keys
        """
        sm = StructureMatcher(ltol=self.ltol,
                              stol=self.stol,
                              angle_tol=self.angle_tol,
                              primitive_cell=True,
                              scale=True,
                              attempt_supercell=False,
                              allow_subset=False,
                              comparator=ElementComparator())

        m_strucs = [Structure.from_dict(mat["structure"])] + [
            Structure.from_dict(init_struc)
            for init_struc in mat["initial_structures"]
        ]
        for snl in snls:
            snl_struc = StructureNL.from_dict(snl).structure
            try:
                snl_spacegroup = snl_struc.get_space_group_info()[0]
            except:
                snl_spacegroup = -1
            for struc in m_strucs:
                try:
                    struc_sg = struc.get_space_group_info()[0]
                except:
                    struc_sg = -1
                # The try-excepts are a temp fix to a spglib bug
                if struc_sg == snl_spacegroup and sm.fit(struc, snl_struc):
                    yield snl
                    break
Пример #27
0
    def remove_multiple_cif(self):
        structMatch = StructureMatcher(ltol=0.05,
                                       stol=0.05,
                                       angle_tol=2,
                                       primitive_cell=False,
                                       scale=False,
                                       attempt_supercell=False,
                                       allow_subset=False,
                                       comparator=ElementComparator(),
                                       supercell_size='num_sites',
                                       ignored_species=None)

        for input_cif_file_path in glob.glob(self.ctx.input_cif_folder):
            input_cif_file = os.path.basename(input_cif_file_path)
            use_cif = True
            try:
                structure = Structure.from_file(input_cif_file_path)
            except:
                print('Structure import from cif not successful.')
                continue

            structure.remove_oxidation_states()

            for element in structure.composition.element_composition.elements:
                if str(element) not in self.ctx.element_list:
                    use_cif = False

            for key in structures_used:
                if structMatch.fit(structure, structures_used[key]):
                    use_cif = False
                    self.ctx.structures_match_not_used[input_cif_file] = key

            if use_cif:
                self.ctx.structures_used[input_cif_file] = {}
                self.ctx.structures_used[input_cif_file][
                    'structure_original'] = structure

        self.out('structures_match_not_used',
                 ParameterData(dict=self.ctx.structures_match_not_used))
Пример #28
0
    def __init__(
            self,
            structure_matcher=StructureMatcher(comparator=ElementComparator()),
            symprec=None):
        """
        Remove duplicate structures based on the structure matcher
        and symmetry (if symprec is given).

        Args:
            structure_matcher:
                Provides a structure matcher to be used for structure
                comparison.
            symprec:
                The precision in the symmetry finder algorithm
                if None (default value), no symmetry check is performed and
                only the structure matcher is used. A recommended value is 1e-5
        """
        self._symprec = symprec
        self._structure_list = []
        if isinstance(structure_matcher, dict):
            self._sm = StructureMatcher.from_dict(structure_matcher)
        else:
            self._sm = structure_matcher
Пример #29
0
def group_structures(structures,
                     ltol=0.2,
                     stol=0.3,
                     angle_tol=5,
                     separate_mag_orderings=False):
    """
    Groups structures according to space group and structure matching

    Args:
        structures ([Structure]): list of structures to group
        ltol (float): StructureMatcher tuning parameter for matching tasks to materials
        stol (float): StructureMatcher tuning parameter for matching tasks to materials
        angle_tol (float): StructureMatcher tuning parameter for matching tasks to materials
        separate_mag_orderings (bool): Separate magnetic orderings into different materials
    """
    if separate_mag_orderings:
        for structure in structures:
            if has(structure.site_properties, "magmom"):
                structure.add_spin_by_site(structure.site_properties['magmom'])
                structure.remove_site_property('magmom')

    sm = StructureMatcher(ltol=ltol,
                          stol=stol,
                          angle_tol=angle_tol,
                          primitive_cell=True,
                          scale=True,
                          attempt_supercell=False,
                          allow_subset=False,
                          comparator=ElementComparator())

    def get_sg(struc):
        return struc.get_space_group_info(symprec=0.1)[1]

    # First group by spacegroup number then by structure matching
    for _, pregroup in groupby(sorted(structures, key=get_sg), key=get_sg):
        for group in sm.group_structures(sorted(pregroup, key=get_sg)):
            yield group
Пример #30
0
def compare_structures(options):
    """Inspired to a similar function in pmg_structure."""
    paths = options.paths
    if len(paths) < 2:
        print("You need more than one structure to compare!")
        return 1

    structures = []
    try:
        structures = [abilab.Structure.from_file(p) for p in paths]
    except Exception as ex:
        print(
            "Error reading structures from files. Are they in the right format?"
        )
        print(str(ex))
        return 1

    from pymatgen.analysis.structure_matcher import StructureMatcher, ElementComparator
    compareby = "species" if options.anonymous else "element"
    m = StructureMatcher() if compareby == "species" else StructureMatcher(
        comparator=ElementComparator())
    print("Grouping %s structures by `%s` with `anonymous: %s`" %
          (len(structures), compareby, options.anonymous))

    for i, grp in enumerate(
            m.group_structures(structures, anonymous=options.anonymous)):
        print("Group {}: ".format(i))
        for s in grp:
            spg_symbol, international_number = s.get_space_group_info()
            print("\t- {} ({}), vol: {:.2f} A^3, {} ({})".format(
                paths[structures.index(s)], s.formula, s.volume, spg_symbol,
                international_number))
        print()

    if options.verbose:
        pprint(m.as_dict())