Source code for rxn_network.network.entry
"""Entry objects used in a Network. These network entry objects hold multiple entries and
can be used as data for a node in the graph.
"""
from __future__ import annotations
from enum import Enum, auto
from typing import TYPE_CHECKING
from monty.json import MSONable
from monty.serialization import MontyDecoder
if TYPE_CHECKING:
from collections.abc import Collection
from pymatgen.core.periodic_table import Element
from pymatgen.entries import Entry
[docs]
class NetworkEntryType(Enum):
"""Describes the Network Entry Type."""
Precursors = auto()
Reactants = auto()
Products = auto()
Target = auto()
Dummy = auto()
[docs]
class NetworkEntry(MSONable):
"""Helper class for describing combinations of ComputedEntry-like objects in context
of a reaction network. This entry will represent a node in the network.
"""
def __init__(self, entries: Collection[Entry], description: NetworkEntryType):
"""Args:
entries: Collection of Entry-like objects
description: Node type (e.g., Precursors, Target... see NetworkEntryType
class).
"""
self._entries = set(entries)
self._elements = sorted({elem for entry in entries for elem in entry.composition.elements})
self._chemsys = "-".join([str(e) for e in self.elements])
self._dim = len(self.chemsys)
self._description = description
@property
def entries(self) -> set[Entry]:
"""Entries contained in this NetworkEntry."""
return self._entries
@property
def elements(self) -> list[Element]:
"""Elements contained in this NetworkEntry."""
return self._elements
@property
def chemsys(self) -> str:
"""Chemical system of this NetworkEntry."""
return self._chemsys
@property
def dim(self) -> int:
"""Number of elements in this NetworkEntry."""
return self._dim
@property
def description(self) -> NetworkEntryType:
"""A description of the NetworkEntry (given as NetworkEntryType)."""
return self._description
[docs]
def as_dict(self) -> dict:
"""MSONable dict representation."""
return {
"@module": self.__class__.__module__,
"@class": self.__class__.__name__,
"entries": list(self.entries),
"description": self.description.value,
}
[docs]
@classmethod
def from_dict(cls, d: dict) -> NetworkEntryType:
"""Load from MSONable dict."""
return cls(
MontyDecoder().process_decoded(d["entries"]),
NetworkEntryType(d["description"]),
)
def __repr__(self) -> str:
formulas = [entry.composition.reduced_formula for entry in self.entries]
formulas.sort()
return f"{self.description.name}: {','.join(formulas)}"
def __eq__(self, other) -> bool:
if (
isinstance(other, self.__class__)
and self.description == other.description
and self.chemsys == other.chemsys
):
return self.entries == other.entries
return False
def __hash__(self):
return hash((self.description, frozenset(self.entries)))
[docs]
class DummyEntry(NetworkEntry):
"""A Dummy Entry that doesn't hold any info. This maybe useful for serving as an empty
node to facilitate pathfinding to all nodes, etc.
"""
def __init__(self):
"""Dummy node doesn't need any parameters."""
self._entries = set()
self._elements = []
self._chemsys = ""
self._dim = 0
self._description = NetworkEntryType.Dummy
def __repr__(self) -> str:
return "Dummy Node"
def __eq__(self, other) -> bool:
return self is other
def __hash__(self):
return hash("Dummy")