Source code for pyvcad_attribute_resolver.modules.j750_shore_hardness

"""J750 shore-hardness to volume-fractions conversion registrations."""

import pyvcad as pv

from pyvcad_attribute_resolver.registry import register_conversion

from .fitted_model import (
    J750_AGILUS_FRACTION_EXPRESSION,
    J750_AGILUS_FRACTION_RUNTIME_EXPRESSION,
    J750_VERO_FRACTION_RUNTIME_EXPRESSION,
)


def _first_material_id_with_prefix(material_defs, prefix):
    for material_id in range(material_defs.num_materials() + 1):
        try:
            name = material_defs.name(material_id)
        except Exception:
            continue

        if name.startswith(prefix):
            return material_id

    raise ValueError("No material found with prefix '{}'".format(prefix))


def _resolve_material_ids(material_defs, agilus_material, vero_material):
    if agilus_material is None:
        agilus_id = _first_material_id_with_prefix(material_defs, "Agilus30")
    else:
        agilus_id = material_defs.id(agilus_material)

    if vero_material is None:
        vero_id = _first_material_id_with_prefix(material_defs, "Vero")
    else:
        vero_id = material_defs.id(vero_material)

    return agilus_id, vero_id


def _curve_fit_factory(agilus_id, vero_id):
    def _factory():
        return pv.VolumeFractionsExpressionConverter(
            [pv.DefaultAttributes.SHORE_HARDNESS],
            [agilus_id, vero_id],
            [
                J750_AGILUS_FRACTION_RUNTIME_EXPRESSION,
                J750_VERO_FRACTION_RUNTIME_EXPRESSION,
            ],
        )

    return _factory


def fit_j750_shore_hardness_curve(polynomial_degree=6):
    """Fit the source CSV and return the expression data.

    This helper is intentionally lazy so the runtime converter does not import
    NumPy or read the CSV while adapting a design.
    """
    from .fit_curve import build_expression
    from .fit_curve import fit_j750_shore_hardness_curve as _fit_curve

    fit = _fit_curve(polynomial_degree)
    fit["expression"] = build_expression(fit)
    return fit


def generate_j750_shore_hardness_fit_plot(output_path=None, polynomial_degree=6):
    """Generate the out-of-loop J750 hardness fit SVG figure."""
    from .fit_curve import generate_j750_shore_hardness_fit_plot as _generate_plot

    return _generate_plot(output_path, polynomial_degree)


[docs] def register_j750_shore_hardness_conversions( material_defs=None, agilus_material=None, vero_material=None, ): """Register the J750 shore-hardness to volume-fractions conversion. By default this resolves the first J750 materials whose names begin with ``Agilus30`` and ``Vero``. Callers can override the representative material names when they want a specific color variant. """ if material_defs is None: material_defs = pv.j750_materials agilus_id, vero_id = _resolve_material_ids( material_defs, agilus_material, vero_material, ) register_conversion( source="shore_hardness", target="volume_fractions", converter_factory=_curve_fit_factory(agilus_id, vero_id), name="j750_shore_hardness_to_volume_fractions", priority=0, tags=["j750_shore_hardness"], )
__all__ = [ "J750_AGILUS_FRACTION_EXPRESSION", "fit_j750_shore_hardness_curve", "generate_j750_shore_hardness_fit_plot", "register_j750_shore_hardness_conversions", ]