Source code for MagmaPandas.configuration

"""
Global configuration of MagmaPandas settings.
"""

from typing import Tuple, Union

from MagmaPandas.Fe_redox.Fe3Fe2_models import Fe3Fe2_models_dict
from MagmaPandas.Kd.Ol_melt.FeMg.Kd_models import Kd_olmelt_FeMg_models_dict
from MagmaPandas.parse_io.validate import _check_setter
from MagmaPandas.thermometers.melt import melt_thermometers_dict
from MagmaPandas.volatile_solubility.volatile_solubility_models import (
    volatile_solubility_models_dict,
)

Fe3Fe2_models = list(Fe3Fe2_models_dict.keys())
Kd_ol_FeMg_models = list(Kd_olmelt_FeMg_models_dict.keys())
fO2_buffers = ["QFM", "IW"]
melt_thermometers = list(melt_thermometers_dict.keys())
volatile_solubility_models = list(volatile_solubility_models_dict.keys())
volatile_species_options = ["co2", "h2o", "mixed"]

_variables = {
    "fO2 buffers": fO2_buffers,
    "Melt Fe3+/Fe2+ models": Fe3Fe2_models,
    "Ol-melt Fe-Mg Kd models": Kd_ol_FeMg_models,
    "Melt thermometers": melt_thermometers,
    "Volatile solubility models": volatile_solubility_models,
    "Volatile species": volatile_species_options,
}

# _variables = {
#     "fO2 buffers": fO2_buffers,
#     "Melt Fe3+/Fe2+ models": list(Fe3Fe2_models.keys()),
#     "Ol-melt Fe-Mg Kd models": list(Kd_olmelt_FeMg_models.keys),  # Kd_ol_FeMg_models,
#     "Melt thermometers": list(thermometers_melt.keys()),  # melt_thermometers,
#     "Volatile solubility models": list(
#         volatile_solubility_models.keys()
#     ),  # volatile_solubility_models,
#     "Volatile species": volatile_species_options,
# }

_names_length = max([len(i) for i in _variables.keys()]) + 5
_pad_right = max([len(", ".join(i)) for i in _variables.values()])
# _pad_total = _names_length + _pad_right

[len(", ".join(i)) for i in _variables.values()]
_pad_total = 70
_pad_right = _pad_total - _names_length
_new_line = "\n"

configuration_options = (
    f"{_new_line}{' MagmaPandas ':#^{_pad_total}}"
    f"{_new_line}{'':#^{_pad_total}}"
    f"{_new_line}{'Configuration options':_<{_pad_total}}"
)

for param, values in _variables.items():

    val_string_2 = ""
    idxs = [0, 0]
    start_idx = 0
    while idxs[-1] < len(values):

        for i, _ in enumerate(values):
            if len(", ".join(values[start_idx : i + 1])) > (_pad_total - _names_length):
                idxs.insert(-1, i)
                start_idx = i
                continue
            idxs[-1] = i + 1

    if len(idxs) > 2:
        val_string_1 = ", ".join(values[: idxs[1]])
        val_string_2 = f""
        for i, idx in enumerate(idxs[2:]):
            val_string_2 += (
                f"{_new_line}{', '.join(values[idxs[i+1]:idx]):>{_pad_total}}"
            )
        val_string_2 += f"{_new_line}"
    else:
        val_string_1 = ", ".join(values)

    line = f"{_new_line}{param:.<{_names_length}}{val_string_1:.>{_pad_right}}{val_string_2}"
    configuration_options += line

configuration_options += f"{_new_line}{'':#^{_pad_total}}"


class _meta_configuration(type):
    def __init__(cls, *args, **kwargs):
        cls._fO2buffer = "QFM"
        cls._dfO2 = 1
        cls._Kd_model = "toplis2005"
        cls._Fe3Fe2_model = "sun2024"
        cls._melt_thermometer = "putirka2008_15"
        cls._volatile_solubility = "iaconomarziano2012"
        cls._volatile_species = "mixed"
        cls._Fe3Fe2_value = None
        cls._Fe3Fe2_error = None
        cls._Kd_value = None
        cls._Kd_error = None

    @property
    def fO2buffer(cls):
        return cls._fO2buffer

    @fO2buffer.setter
    @_check_setter(fO2_buffers)
    def fO2buffer(cls, value: str):
        cls._fO2buffer = value

    @property
    def dfO2(cls):
        return cls._dfO2

    @dfO2.setter
    def dfO2(cls, value: float | int):
        cls._dfO2 = value

    @property
    def Kd_model(cls):
        return cls._Kd_model

    @Kd_model.setter
    @_check_setter(Kd_ol_FeMg_models)
    def Kd_model(
        cls,
        model: Union[str, Tuple[str, Union[float, int], Union[float, int]]],
    ):
        if not isinstance(model, (tuple, list)):
            if model != "fixed":
                cls._Kd_model = model
                return
            raise ValueError(
                "Please provide Kd value and error as positive floats or ints in a tuple or list, as ('fixed', value, error) e.g. ('fixed', 0.3, 0.05)"
            )
        model, value, error = model
        cls._Kd_model = model
        if any(not isinstance(i, (float, int)) or i <= 0 for i in (value, error)):
            raise ValueError(
                "Please provide Kd value and error as positive floats or ints"
            )
        cls._Kd_value = value
        cls._Kd_error = error

    @property
    def Fe3Fe2_model(cls):
        return cls._Fe3Fe2_model

    @Fe3Fe2_model.setter
    @_check_setter(Fe3Fe2_models)
    def Fe3Fe2_model(
        cls,
        model: Union[str, Tuple[str, Union[float, int], Union[float, int]]],
    ):
        if not isinstance(model, (tuple, list)):
            if model != "fixed":
                cls._Fe3Fe2_model = model
                return
            raise ValueError(
                "Please provide Fe3Fe2 value and error as positive floats or ints in a tuple or list, as ('fixed', value, error) e.g. ('fixed', 0.3, 0.05)"
            )
        model, value, error = model
        cls._Fe3Fe2_model = model
        if any(not isinstance(i, (float, int)) or i <= 0 for i in (value, error)):
            raise ValueError(
                "Please provide Fe3Fe2 value and error as positive floats or ints"
            )
        cls._Fe3Fe2_value = value
        cls._Fe3Fe2_error = error

    @property
    def melt_thermometer(cls):
        return cls._melt_thermometer

    @melt_thermometer.setter
    @_check_setter(melt_thermometers)
    def melt_thermometer(cls, model: str):
        cls._melt_thermometer = model

    @property
    def volatile_solubility(cls):
        return cls._volatile_solubility

    @volatile_solubility.setter
    @_check_setter(volatile_solubility_models)
    def volatile_solubility(cls, model: str):
        cls._volatile_solubility = model

    @property
    def volatile_species(cls):
        return cls._volatile_species

    @volatile_species.setter
    @_check_setter(volatile_species_options)
    def volatile_species(cls, model: str):
        cls._volatile_species = model

    def __str__(cls):

        variables = {
            "fO2 buffer": cls._fO2buffer,
            "\u0394fO2": cls._dfO2,
            "Melt Fe3+/Fe2+": (
                cls._Fe3Fe2_model
                if cls._Fe3Fe2_model != "fixed"
                else f"{cls._Fe3Fe2_model} {cls._Fe3Fe2_value:.2f}\u00b1{cls._Fe3Fe2_error:.2f}"
            ),
            "Kd Fe-Mg ol-melt": (
                cls._Kd_model
                if cls._Kd_model != "fixed"
                else f"{cls._Kd_model} {cls._Kd_value:.2f}\u00b1{cls._Kd_error:.2f}"
            ),
            "Melt thermometer": cls._melt_thermometer,
            "Volatile solubility model": cls._volatile_solubility,
            "Volatile species": cls._volatile_species,
        }

        names_length = max([len(i) for i in variables.keys()]) + 5
        pad_right = max([max([len(j) for j in i]) for i in _variables.values()])
        pad_total = names_length + pad_right
        new_line = "\n"

        message = (
            f"{new_line}{' MagmaPandas ':#^{pad_total}}"
            f"{new_line}{'':#^{pad_total}}"
            f"{new_line}{'General settings':_<{pad_total}}"
            # f"{new_line}{'fO2 buffer':.<{names_length}}{'QFM':.>{pad_right}}"
        )

        parameter_settings = ""
        for param, value in variables.items():
            parameter_settings += (
                f"{new_line}{param:.<{names_length}}{value:.>{pad_right}}"
            )

        return message + parameter_settings + f"{new_line}{'':#^{pad_total}}{new_line}"


[docs] class configuration(metaclass=_meta_configuration): """ Class for configuring global settings in MagmaPandas. Attributes ---------- dQFM : int, float Log units shift of the QFM |fO2| buffer. Default value: 1 Kd_model : str Olivine-melt Fe-Mg partitioning model. Fe3Fe2_model : str Melt |Fe3Fe2| model. melt_thermometer : str Melt-only thermometer. volatily_solubility : str |CO2|-|H2O| solubility model. volatile_species : str Fluid phase species. Options: 'h2o', 'co2' or 'mixed'. Default value: 'mixed' """
[docs] @classmethod def available_models(cls): """ Show available models for all parameters """ print(configuration_options)
[docs] @classmethod def reset(cls): """ Reset to default values """ cls._fO2buffer = "QFM" cls._dfO2 = 1 cls._Kd_model = "toplis2005" cls._Fe3Fe2_model = "sun2024" cls._melt_thermometer = "putirka2008_15" cls._volatile_solubility = "iaconomarziano2012" cls._volatile_species = "mixed"