profiles.base.build_dynamic_profile_class#

profiles.base.build_dynamic_profile_class(func: Callable, unit_func: Callable, variables: list[str], parameters: dict[str, str] | None = None, base: type[BaseProfile] | None = None) type[BaseProfile][source]#

Dynamically construct a new profile class from a symbolic function and associated metadata.

This utility allows users to define fully functional profile classes at runtime without writing boilerplate class definitions. The constructed class inherits from the specified base and provides a complete, ready-to-use implementation for models requiring analytical expressions.

Parameters:
  • func (Callable) – Callable that generates the symbolic expression for the profile. Must have signature func(*variables, **parameters) and return a valid Expr or compatible symbolic object defining the profile.

  • unit_func (Callable) – Callable that determines the units of the derived profile expression. Must have signature unit_func(*variable_units, **parameter_units) and return a unyt.unit_object.Unit instance representing the result’s units.

  • variables (list of str) – Ordered list of the independent variables for the profile, provided as strings. This list defines the argument order for both func and unit_func, and must match the symbolic variables used in the expression.

  • parameters (dict of str, float, optional) – Dictionary mapping parameter names (as strings) to their default values. These parameters define required inputs for the derived profile and are exposed as class attributes. Defaults to an empty dictionary if no parameters are required. Derived profiles do not inherit parameters from the base class automatically; all parameters must be explicitly defined here.

  • base (type, optional) – The base class to inherit from when constructing the profile. Defaults to BaseProfile. Alternative base classes can be specified for advanced subclassing behavior, as long as they follow the expected profile interface.

Returns:

A new dynamically constructed class inheriting from base, with all necessary attributes and methods to function as a profile within modeling frameworks.

Return type:

type

Notes

  • The generated profile class defines class attributes:
    • __VARIABLES__ : list of str — The symbolic variables for the expression.

    • __PARAMETERS__ : dict of str, float — Parameters and their defaults.

    • __function__ : Callable — Class method returning the symbolic expression.

    • __function_units__ : Callable — Class method returning the units.

  • Parameters defined in parameters are automatically added to the derived profile, but are not inherited from the base class unless explicitly included.

  • The argument order in variables must exactly match the order expected by both func and unit_func.

  • The derived class will not register globally and is intended for localized or temporary use unless manually registered in a broader framework.

Examples

As an example, one can define a gaussian profile in either a dynamic framework or a static framework:

from sympy import symbols, exp
from unyt import Unit
from your_module.profiles import (
    build_dynamic_profile_class,
)

r, sigma = symbols("r sigma")

def gaussian_expr(r, sigma):
    return exp(-(r**2) / (2 * sigma**2))


def gaussian_units(r_unit, sigma_unit):
    return Unit("dimensionless")


GaussianProfile = build_dynamic_profile_class(
    func=gaussian_expr,
    unit_func=gaussian_units,
    variables=["r"],
    parameters={"sigma": 1.0},
)

profile = GaussianProfile()
expr = profile.__function__(r, sigma=2)
units = profile.__function_units__(
    Unit("kpc"), sigma_unit=Unit("kpc")
)
from sympy import symbols, exp
from unyt import Unit
from your_module.profiles import BaseProfile

r, sigma = symbols("r sigma")


class GaussianProfile(BaseProfile):
    __IS_ABSTRACT__ = False
    __REGISTER__ = False
    __VARIABLES__ = ["r"]
    __PARAMETERS__ = {"sigma": 1.0}

    @classmethod
    def __function__(cls, r, sigma):
        return exp(-(r**2) / (2 * sigma**2))

    @classmethod
    def __function_units__(
        cls, r_unit, sigma_unit
    ):
        return Unit("dimensionless")


profile = GaussianProfile()
expr = profile.__function__(r, sigma=2)
units = profile.__function_units__(
    Unit("kpc"), sigma_unit=Unit("kpc")
)