Пример #1
0
def robocrystallographer(
    structure: Structure,
    condenser_kwargs: Optional[dict] = None,
    describer_kwargs: Optional[dict] = None,
) -> str:
    """Gets the robocrystallographer description of a structure.

    Args:
        structure: A structure.
        condenser_kwargs: Keyword arguments that will be passed to
            :obj:`robocrys.condense.StructureCondenser`.
        describer_kwargs: Keyword arguments that will be passed to
            :obj:`robocrys.describe.StructureDescriber`.

    Returns:
        The description.
    """
    condenser_kwargs = condenser_kwargs if condenser_kwargs else {}
    describer_kwargs = describer_kwargs if describer_kwargs else {}

    sc = StructureCondenser(**condenser_kwargs)
    describer = StructureDescriber(**describer_kwargs)

    if not any(
        [hasattr(s, "oxi_state") for s in structure.composition.elements]):
        try:
            structure.add_oxidation_state_by_guess(max_sites=-80)
        except ValueError:
            warnings.warn("Could not add oxidation states!")

    condensed_structure = sc.condense_structure(structure)
    description = describer.describe(condensed_structure)
    print(description)
    return description
Пример #2
0
        def run_robocrys_analysis(new_store_contents):

            print("Robocrys callback fired")

            struct = self.from_data(new_store_contents)

            try:

                condenser = StructureCondenser()
                describer = StructureDescriber()

                condensed_structure = condenser.condense_structure(struct)

                description = describer.describe(condensed_structure)

            except Exception as exc:

                description = str(exc)

            return MessageContainer(
                MessageBody([
                    f"{description} – ",
                    html.A(
                        f"🤖 robocrys v{robocrys_version}",
                        href=
                        "https://github.com/hackingmaterials/robocrystallographer",
                        style={"white-space": "nowrap"},
                    ),
                ]),
                kind="dark",
            )
Пример #3
0
class RobocrysBuilder(MapBuilder):
    def __init__(self, materials, robocrys, **kwargs):
        """Runs robocrystallographer to get the condensed structure and
        structure description.

        Args:
            materials (Store): Store of materials documents.
            robocrys (Store): Store of condensed structure and
                text structure description.
            **kwargs: Keyword arguments that will get passed to the builder
                super method.
        """
        self.materials = materials
        self.robocrys = robocrys

        self.condenser = StructureCondenser()
        self.describer = StructureDescriber(describe_symmetry_labels=False)

        super().__init__(source=materials,
                         target=robocrys,
                         ufn=self.calc,
                         projection=["structure"],
                         **kwargs)

    def calc(self, item):
        """Calculates robocrystallographer on an item.

        Args:
            item (dict): A dict with a task_id and a structure.

        Returns:
            dict: The robocrystallographer information dict with they keys:

            - ``"condensed_structure"``: The condensed structure dictionary.
            - ``"description"``: The text description.
        """
        self.logger.debug("Running robocrys on {}".format(
            item[self.materials.key]))

        structure = Structure.from_dict(item["structure"])
        doc = {"_robocrys_version": robocrys_version}

        try:
            self.logger.debug("Adding oxidation states for {}".format(
                item[self.materials.key]))
            structure.add_oxidation_state_by_guess(max_sites=-80)
        except ValueError:
            self.logger.warning("Could not add oxidation states for {}".format(
                item[self.materials.key]))

        condensed_structure = self.condenser.condense_structure(structure)
        description = self.describer.describe(condensed_structure)
        doc.update({
            "condensed_structure": condensed_structure,
            "description": description
        })

        return doc
Пример #4
0
    def update_contents(self, new_store_contents):

        struct = self.from_data(new_store_contents)

        condenser = StructureCondenser()
        describer = StructureDescriber()

        condensed_structure = condenser.condense_structure(struct)

        description = describer.describe(condensed_structure)

        return MessageContainer(MessageBody([
            f"{description} – ",
            html.A(
                f"🤖 robocrys v{robocrys_version}",
                href="https://github.com/hackingmaterials/robocrystallographer",
                style={"white-space": "nowrap"},
            ),
        ]),
                                kind="dark")
Пример #5
0
    def update_contents(self, new_store_contents):

        struct = self.from_data(new_store_contents)

        condenser = StructureCondenser()
        describer = StructureDescriber()

        condensed_structure = condenser.condense_structure(struct)

        description = describer.describe(condensed_structure)

        return html.Blockquote(
            [
                f"{description} – ",
                html.A(
                    f"🤖 robocrys v{robocrys_version}",
                    href="https://github.com/hackingmaterials/robocrystallographer",
                    style={"white-space": "nowrap"},
                ),
            ],
            className="mpc-blockquote",
        )
Пример #6
0
    def __init__(self, materials, robocrys, **kwargs):
        """Runs robocrystallographer to get the condensed structure and
        structure description.

        Args:
            materials (Store): Store of materials documents.
            robocrys (Store): Store of condensed structure and
                text structure description.
            **kwargs: Keyword arguments that will get passed to the builder
                super method.
        """
        self.materials = materials
        self.robocrys = robocrys

        self.condenser = StructureCondenser()
        self.describer = StructureDescriber(describe_symmetry_labels=False)

        super().__init__(source=materials,
                         target=robocrys,
                         ufn=self.calc,
                         projection=["structure"],
                         **kwargs)
 def __init__(
     self, condenser_kwargs: Optional[dict] = None, distorted_tol: float = 0.6
 ):
     condenser_kwargs = condenser_kwargs if condenser_kwargs else {}
     self._sc = StructureCondenser(**condenser_kwargs)
     self._distorted_tol = distorted_tol
class RobocrysFeaturizer(BaseFeaturizer):
    """Class to generate structure features from robocrystallographer output.

    Args:
        condenser_kwargs: Keyword arguments that will be passed to
            :obj:`robocrys.condense.StructureCondenser`.
        distorted_tol: The value under which the site geometry will be
            classified as distorted.
    """

    def __init__(
        self, condenser_kwargs: Optional[dict] = None, distorted_tol: float = 0.6
    ):
        condenser_kwargs = condenser_kwargs if condenser_kwargs else {}
        self._sc = StructureCondenser(**condenser_kwargs)
        self._distorted_tol = distorted_tol

    def featurize(self, s: Structure) -> List[Union[float, bool, str]]:
        """Featurizes a structure using robocrystallographer.

        Args:
            s: A structure.

        Returns:
            The robocrystallographer features.
        """
        fa = FeaturizerAdapter(
            self._sc.condense_structure(s), distorted_tol=self._distorted_tol
        )

        # add general structure features
        features = [
            fa.mineral["type"],
            fa.spg_symbol,
            fa.crystal_system,
            fa.dimensionality,
            fa.is_vdw_heterostructure,
            fa.is_interpenetrated,
            fa.is_intercalated,
        ]

        # add dimensionality features
        features += [fa.is_dimensionality(d) for d in _dimensionalities]
        features += [fa.is_dimensionality(d) for d in _dimensionality_sets]
        features += [d in fa.component_dimensionalities for d in _dimensionalities]

        # add molecule features
        features += [fa.contains_named_molecule]
        features += [fa.contains_molecule(m) for m in _molecules]

        # add geometry features
        features += [fa.contains_geometry_type(g) for g in _geometries]
        features += [fa.contains_geometry_type(g, distorted=True) for g in _geometries]
        features += [
            fa.average_coordination_number,
            fa.average_cation_coordination_number,
            fa.average_anion_coordination_number,
        ]

        # add polyhedral features
        features += [
            fa.contains_polyhedra,
            fa.contains_corner_sharing_polyhedra,
            fa.contains_edge_sharing_polyhedra,
            fa.contains_face_sharing_polyhedra,
        ]

        # add connectivity features
        features += [
            fa.contains_connected_geometry(c, g)
            for c, g in product(_connectivities, connected_geometries)
        ]
        features += [fa.average_corner_sharing_octahedral_tilt_angle]

        # add fractional features
        features += [fa.frac_sites_polyhedra]
        features += [fa.frac_site_geometry(g) for g in _geometries]
        features += [fa.frac_sites_n_coordinate(n) for n in _cns]

        all_distances = fa.all_bond_lengths()
        # add bond length features
        features += [max(all_distances), min(all_distances), mean(all_distances)]

        return features

    def feature_labels(self):
        # general features
        labels = [
            "mineral_prototype",
            "spg_symbol",
            "crystal_system",
            "dimensionality",
            "is_vdw_heterostructure",
            "is_interpenetrated",
            "is_intercalated",
        ]

        # dimensionality features
        labels += [f"is_only_{d}d" for d in _dimensionalities]
        labels += [
            "is_{}".format("_".join([f"{d}d" for d in ds]))
            for ds in _dimensionality_sets
        ]
        labels += [f"contains_{d}d_component" for d in _dimensionalities]

        # molecule features
        labels += ["contains_named_molecule"]
        labels += [f"contains_{m}" for m in _molecules]

        # geometry features
        labels += [f"contains_{g}" for g in _geometries]
        labels += [f"contains_distorted_{g}" for g in _geometries]
        labels += ["average_site_cn", "average_cation_cn", "average_anion_cn"]

        # polyhedral features
        labels += [
            "contains_polyhedra",
            "contains_corner_sharing_polyhedra",
            "contains_edge_sharing_polyhedra",
            "contains_face_sharing_polyhedra",
        ]

        # connectivity features
        labels += [
            f"contains_{c}_{g}"
            for c, g in product(_connectivities, connected_geometries)
        ]
        labels += ["corner_sharing_octahedral_tilt_angle"]

        # fractional features
        labels += ["frac_site_polyhedra"]
        labels += [f"frac_sites_{g}" for g in _geometries]
        labels += [f"frac_sites_{n}_coordinate" for n in _cns]

        # bond length features
        labels += ["max_bond_length", "min_bond_length", "average_bond_length"]

        return labels

    def citations(self):
        return ["in prep."]

    def implementors(self):
        return ["Alex Ganose"]