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
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", )
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
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")
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", )
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"]