From 25b8495a2ce8f6ce784347d1bbbaf61509b56ef2 Mon Sep 17 00:00:00 2001 From: Emily Boudreaux Date: Thu, 11 Jun 2026 07:42:17 -0400 Subject: [PATCH] feat(libcomposition): python bindings for standard solar compositions --- pyproject.toml | 2 +- src-pybind/composition/bindings.cpp | 124 +++++++++++++++++++++++++++- src-pybind/fourdst/__init__.py | 10 ++- subprojects/libcomposition.wrap | 2 +- 4 files changed, 133 insertions(+), 5 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 54c58f6..7176efd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,7 @@ build-backend = "mesonpy" [project] name = "fourdst" # Choose your Python package name -version = "v0.9.22" # Your project's version +dynamic = ["version"] description = "Python interface to the utility fourdst modules from the 4D-STAR project" readme = "readme.md" license = { file = "LICENSE.txt" } # Reference your license file [cite: 2] diff --git a/src-pybind/composition/bindings.cpp b/src-pybind/composition/bindings.cpp index d148565..3f993c5 100644 --- a/src-pybind/composition/bindings.cpp +++ b/src-pybind/composition/bindings.cpp @@ -3,6 +3,7 @@ #include // Needed for binding std::vector, std::map etc. if needed directly #include +#include #include "fourdst/composition/composition.h" #include "fourdst/atomic/atomicSpecies.h" @@ -10,9 +11,10 @@ #include "bindings.h" #include "fourdst/atomic/species.h" -#include "fourdst/composition/utils.h" +#include "fourdst/composition/utils/utils.h" #include "fourdst/composition/utils/composition_hash.h" #include "fourdst/composition/exceptions/exceptions_composition.h" +#include "fourdst/composition/io/standard_compositions.h" namespace py = pybind11; @@ -326,7 +328,127 @@ void register_comp_bindings(pybind11::module &m) { "Build a Composition object from a map of species to mass fractions." ); + auto io = m.def_submodule("io", "IO library for standard solar compositions"); + py::class_ (io, "CompositionData") + .def(py::init<>()) + .def_readwrite("comment_str", &fourdst::composition::io::CompositionData::comment_str) + .def_readwrite("he_abundance", &fourdst::composition::io::CompositionData::he_abundance) + .def_readwrite("requires_atomic_weight", &fourdst::composition::io::CompositionData::requires_atomic_weight) + .def_property("elements", + [](fourdst::composition::io::CompositionData &self) -> const std::vector& { + return self.elements; + }, + [](fourdst::composition::io::CompositionData &self, const std::vector &value) { + self.elements = value; + }, + py::return_value_policy::reference_internal + ) + .def_property("abundances", + [](fourdst::composition::io::CompositionData &self) -> const std::vector& { + return self.abundances; + }, + [](fourdst::composition::io::CompositionData &self, const std::vector &value) { + self.abundances = value; + }, + py::return_value_policy::reference_internal + ); + + py::class_(io, "IsotopicPercentage") + .def(py::init<>()) + .def_readwrite("comment_str", &fourdst::composition::io::IsotopicPercentage::comment_str) + .def_property("atomic_numbers", + [](fourdst::composition::io::IsotopicPercentage &self) -> const std::vector& { + return self.atomic_numbers; + }, + [](fourdst::composition::io::IsotopicPercentage &self, const std::vector &value) { + self.atomic_numbers = value; + }, + py::return_value_policy::reference_internal + ) + .def_property("elements", + [](fourdst::composition::io::IsotopicPercentage &self) -> const std::vector& { + return self.elements; + }, + [](fourdst::composition::io::IsotopicPercentage &self, const std::vector &value) { + self.elements = value; + }, + py::return_value_policy::reference_internal + ) + .def_property("mass_numbers", + [](fourdst::composition::io::IsotopicPercentage &self) -> const std::vector& { + return self.mass_numbers; + }, + [](fourdst::composition::io::IsotopicPercentage &self, const std::vector &value) { + self.mass_numbers = value; + }, + py::return_value_policy::reference_internal + ) + .def_property("percentages", + [](fourdst::composition::io::IsotopicPercentage &self) -> const std::vector& { + return self.percentages; + }, + [](fourdst::composition::io::IsotopicPercentage &self, const std::vector &value) { + self.percentages = value; + }, + py::return_value_policy::reference_internal + ); + + py::enum_(io,"SolarCompositions") + .value("AG89", fourdst::composition::io::SolarCompositions::AG89) + .value("GN93", fourdst::composition::io::SolarCompositions::GN93) + .value("GS98", fourdst::composition::io::SolarCompositions::GS98) + .value("L03", fourdst::composition::io::SolarCompositions::L03) + .value("AGS05", fourdst::composition::io::SolarCompositions::AGS05) + .value("AGSS09", fourdst::composition::io::SolarCompositions::AGSS09) + .value("A09_Przybilla", fourdst::composition::io::SolarCompositions::A09_Przybilla) + .value("MB22_photospheric", fourdst::composition::io::SolarCompositions::MB22_photospheric) + .value("AAG21_photospheric", fourdst::composition::io::SolarCompositions::AAG21_photospheric) + .value("L09", fourdst::composition::io::SolarCompositions::L09) + .export_values(); + + py::enum_(io,"IsotopicPercentages") + .value("L03", fourdst::composition::io::IsotopicPercentages::L03) + .value("L09", fourdst::composition::io::IsotopicPercentages::L09); + + io.attr("SolarCompositions_to_string_map") = fourdst::composition::io::SolarCompositions_to_string_map; + io.attr("IsotopicPercentages_to_string_map") = fourdst::composition::io::IsotopicPercentages_to_string_map; + + io.def("get_raw_standard_solar_composition_data", + []() -> std::vector { + std::span raw = fourdst::composition::io::get_raw_standard_solar_composition_data(); + return std::ranges::to>(raw); + } + ); + + py::class_(io,"ChemicalFileParser") + .def(py::init<>()) + .def_static("parse_composition_data", + &fourdst::composition::io::ChemicalFileParser::parse_composition_data, + py::arg("data"), + py::arg("scheme") + ) + .def_static("parse_isotopic_percentage", + &fourdst::composition::io::ChemicalFileParser::parse_isotopic_percentage, + py::arg("data"), + py::arg("scheme") + ); + + m.def("get_composition_record", + py::overload_cast(&fourdst::composition::get_composition_record), + py::arg("metal_fraction_scheme"), + py::arg("isotopic_percentage_scheme"), + py::arg("initial_z"), + py::arg("initial_y") + ); + + m.def("get_composition_record", + py::overload_cast(&fourdst::composition::get_composition_record), + py::arg("metal_fraction_scheme"), + py::arg("isotopic_percentage_scheme"), + py::arg("initial_z"), + py::arg("initial_y") + ); } void register_species_bindings(pybind11::module &chem_submodule) { diff --git a/src-pybind/fourdst/__init__.py b/src-pybind/fourdst/__init__.py index 815ea67..9f581a6 100644 --- a/src-pybind/fourdst/__init__.py +++ b/src-pybind/fourdst/__init__.py @@ -3,14 +3,20 @@ from __future__ import annotations import sys from ._phys import atomic, composition, constants, config -from ._phys.composition import utils +from ._phys.composition import utils, io sys.modules['fourdst.atomic'] = atomic sys.modules['fourdst.composition'] = composition sys.modules['fourdst.constants'] = constants sys.modules['fourdst.config'] = config sys.modules['fourdst.composition.utils'] = utils +sys.modules['fourdst.composition.io'] = io __all__ = ['atomic', 'composition', 'constants', 'config', 'core', 'cli'] -__version__ = 'v0.9.21' \ No newline at end of file +from importlib.metadata import version, PackageNotFoundError + +try: + __version__ = version("fourdst") +except PackageNotFoundError: + __version__ = "0.0.0+unknown" \ No newline at end of file diff --git a/subprojects/libcomposition.wrap b/subprojects/libcomposition.wrap index 9c4920b..77a0647 100644 --- a/subprojects/libcomposition.wrap +++ b/subprojects/libcomposition.wrap @@ -1,4 +1,4 @@ [wrap-git] url = https://github.com/4D-STAR/libcomposition.git -revision = v2.4.2 +revision = v2.4.3 depth = 1