# SPDX-FileCopyrightText: 2023-present Rohit Goswami <rog32@hi.is>
#
# SPDX-License-Identifier: MIT
"""Stable public library entry points for chemparseplot.
Prefer this module for new consumers (cookbooks, wailord, notebooks).
**Representative in-process path (parse → typed result):**
.. code-block:: python
from chemparseplot.api import extract_orca_geomscan_energy
dist_bohr, energy_Eh = extract_orca_geomscan_energy(orca_out_text, "Actual Energy")
# dist_bohr, energy_Eh are pint Quantities (bohr, hartree)
Heavy plot stacks still live under ``chemparseplot.plot`` (optional deps /
transitional extras until suite uv design fully covers them).
Suite pins/config: use ``rgpycrumbs.api`` (shared rgpkgs TOML) — this package
does **not** invent ``~/.config/chemparseplot``.
.. versionadded:: 1.9.8
.. versionchanged:: 1.9.9
Expose ORCA geomscan energy parse as the stable library path.
"""
from __future__ import annotations
from typing import TYPE_CHECKING
from chemparseplot.parse.orca.geomscan import extract_energy_data
from chemparseplot.units import (
ENERGY_UNITS,
convert_energy_magnitude,
energy_quantity,
normalize_energy_unit,
)
if TYPE_CHECKING:
from chemparseplot.units import Q_
__all__ = [
"ENERGY_UNITS",
"convert_energy_magnitude",
"energy_quantity",
"extract_orca_geomscan_energy",
"grammar_available",
"normalize_energy_unit",
"parse_orca_final_energy",
"parse_xyz",
"suite_pins",
]
[docs]
def grammar_available() -> bool:
"""True if the optional parsimonious grammar track is importable."""
from chemparseplot.parse.grammar import grammar_available as _ga
return _ga()
[docs]
def _looks_like_path(s: str) -> bool:
"""True for short path-like strings (avoid Path on multi-line blobs)."""
if "\n" in s or len(s) > 4096:
return False
from pathlib import Path
try:
return Path(s).is_file()
except OSError:
return False
[docs]
def parse_xyz(path_or_text: str):
"""Parse XYZ via grammar track (file path if exists, else text).
Requires ``chemparseplot[grammar]``.
"""
from chemparseplot.parse.grammar.xyz import parse_xyz_file, parse_xyz_text
if _looks_like_path(path_or_text):
return parse_xyz_file(path_or_text)
return parse_xyz_text(path_or_text)
[docs]
def parse_orca_final_energy(path_or_text: str):
"""Last ``FINAL SINGLE POINT ENERGY`` as a hartree Quantity.
Grammar track; requires ``chemparseplot[grammar]``.
"""
from chemparseplot.parse.grammar.orca_text import (
parse_orca_text_file,
parse_orca_text_summary,
)
if _looks_like_path(path_or_text):
summary = parse_orca_text_file(path_or_text)
else:
summary = parse_orca_text_summary(path_or_text)
return summary.final_energy
[docs]
def suite_pins() -> dict[str, str]:
"""Return suite package pins from rgpkgs config + env (soft on old hub).
Empty dict if rgpycrumbs is missing or too old.
"""
try:
from rgpycrumbs.api import load_config, pins_from_env
except ImportError:
return {}
pins = dict(pins_from_env())
try:
cfg = load_config()
pins.update(cfg.merged_package_pins_normalized())
except Exception:
pass
return pins