Skip to content

API Reference

janaf.Table dataclass

Represents a NIST-JANAF Thermochemical Table.

Source code in src/janaf/table.py
Python
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
@dataclass(frozen=True)
class Table:
    """Represents a NIST-JANAF Thermochemical Table."""

    index: str
    units: ClassVar[Final[Mapping[str, str]]] = UNITS_MAPPING

    @cached_property
    def fname(self) -> str:  # noqa: D102
        return f"data/{self.index}.txt"

    @cached_property
    def raw(self) -> str:  # noqa: D102
        return resources.files("janaf").joinpath(self.fname).read_text("utf-8")

    @cached_property
    def header(self) -> list[str]:  # noqa: D102
        return self.raw.split("\n", 1)[0].split("\t", 1)

    @cached_property
    def name(self) -> str:  # noqa: D102
        return self.header[0]

    @cached_property
    def formula(self) -> str:  # noqa: D102
        return self.header[1]

    @cached_property
    def body(self) -> str:  # noqa: D102
        return self.raw.split("\n", 1)[1]

    @cached_property
    def df(self) -> pl.DataFrame:
        """
        The table as a polars DataFrame.

        Columns
        -------
        - `T(K)`: Temperature [K]
        - `Cp`: Molar heat capacity at constant pressure [J/(K*mol)]
        - `S`: Molar entropy [J/(K*mol)]
        - `-[G-H(Tr)]/T`: Gibbs energy function [J/(K*mol)]
        - `H-H(Tr)`: Enthalpy increment [kJ/mol]
        - `delta-f H`: Enthalpy of formation
        - `delta-f G`: Gibbs energy of formation
        - `log Kf`: Logarithm (base 10) of equilibrium constant of formation
        - `Note`: Note string
        """
        is_note = pl.col("delta-f H").str.contains(
            "<-->|TRANSITION|PRESSURE|FUGACITY|Cp|UNDEFINED"
        )
        return (
            pl.read_csv(
                io.StringIO(self.body),
                has_header=True,
                separator="\t",
                schema={
                    "T(K)": pl.Float64,
                    "Cp": pl.Float64,
                    "S": pl.Float64,
                    "-[G-H(Tr)]/T": pl.Float64,
                    "H-H(Tr)": pl.Float64,
                    "delta-f H": pl.String,
                    "delta-f G": pl.Float64,
                    "log Kf": pl.Float64,
                },
                truncate_ragged_lines=True,
            )
            .sort("T(K)")
            .with_columns(
                pl.when(is_note)
                .then(None)
                .otherwise(pl.col("delta-f H"))
                .cast(pl.Float64)
                .alias("delta-f H"),
                Note=pl.when(is_note).then(pl.col("delta-f H")),
            )
        )

    def to_xarray(self) -> xr.Dataset:
        """
        Convert the Table to a xarray Dataset.

        Returns
        -------
        xarray.Dataset
            The temperature coordinate is renamed from `"T(K)"` to `"T"`

        Raises
        ------
        ModuleNotFoundError
        """
        try:
            import xarray as xr
        except ModuleNotFoundError as e:
            msg = "`xarray` is required for `to_xarray()`"
            raise ModuleNotFoundError(msg) from e

        ds = (
            xr.Dataset(
                {
                    col.name: (
                        (
                            ("index",),
                            col,
                            (
                                {"units": units}
                                if (units := self.units.get(col.name)) is not None
                                else {}
                            ),
                        )
                    )
                    for col in self.df.with_row_index().iter_columns()
                }
            )
            .set_coords("T(K)")
            .rename({"T(K)": "T"})
        )

        return ds

df cached property

The table as a polars DataFrame.

Columns
  • T(K): Temperature [K]
  • Cp: Molar heat capacity at constant pressure [J/(K*mol)]
  • S: Molar entropy [J/(K*mol)]
  • -[G-H(Tr)]/T: Gibbs energy function [J/(K*mol)]
  • H-H(Tr): Enthalpy increment [kJ/mol]
  • delta-f H: Enthalpy of formation
  • delta-f G: Gibbs energy of formation
  • log Kf: Logarithm (base 10) of equilibrium constant of formation
  • Note: Note string

to_xarray()

Convert the Table to a xarray Dataset.

Returns:

Type Description
Dataset

The temperature coordinate is renamed from "T(K)" to "T"

Raises:

Type Description
ModuleNotFoundError
Source code in src/janaf/table.py
Python
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
def to_xarray(self) -> xr.Dataset:
    """
    Convert the Table to a xarray Dataset.

    Returns
    -------
    xarray.Dataset
        The temperature coordinate is renamed from `"T(K)"` to `"T"`

    Raises
    ------
    ModuleNotFoundError
    """
    try:
        import xarray as xr
    except ModuleNotFoundError as e:
        msg = "`xarray` is required for `to_xarray()`"
        raise ModuleNotFoundError(msg) from e

    ds = (
        xr.Dataset(
            {
                col.name: (
                    (
                        ("index",),
                        col,
                        (
                            {"units": units}
                            if (units := self.units.get(col.name)) is not None
                            else {}
                        ),
                    )
                )
                for col in self.df.with_row_index().iter_columns()
            }
        )
        .set_coords("T(K)")
        .rename({"T(K)": "T"})
    )

    return ds

janaf.search(*, formula=None, name=None, phase=None)

Search a compound.

Parameters:

Name Type Description Default
formula str | None

Regex for formula, by default None.

None
name str | None

Regex for name, by default None.

None
phase str | None

Regex for phase, by default None.

None

Returns:

Type Description
Table

The found table.

Raises:

Type Description
NotUnique

Occurs when search results are not unique.

Source code in src/janaf/index.py
Python
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
def search(
    *,
    formula: str | None = None,
    name: str | None = None,
    phase: str | None = None,
) -> Table:
    """
    Search a compound.

    Parameters
    ----------
    formula
        Regex for `formula`, by default None.
    name
        Regex for `name`, by default None.
    phase
        Regex for `phase`, by default None.

    Returns
    -------
    janaf.Table
        The found table.

    Raises
    ------
    NotUnique
        Occurs when search results are not unique.
    """
    expr = pl.lit(value=True)
    if formula:
        expr &= pl.col("formula").str.contains(
            formula if formula[0] == "^" else f"^{formula}"
        )
    if name:
        expr &= pl.col("name").str.contains(name if name[0] == "^" else f"^{name}")
    if phase:
        expr &= pl.col("phase").str.contains(phase if phase[0] == "^" else f"^{phase}")
    result = db().filter(expr)

    if len(result) != 1:
        raise NotUnique("\n" + str(result))
    return Table(index=result.select("index").item())