Source code for visualization.info.material_formatter

"""Material Formatter Module

This module provides a flexible mechanism for formatting material information
for display. It uses a registry pattern to allow different material types to
be formatted in specific ways without modifying the core visualization code.

Kramer Harrison, 2026
"""

from __future__ import annotations

import os
from typing import TYPE_CHECKING

from optiland import materials

if TYPE_CHECKING:
    from collections.abc import Callable

    from optiland.surfaces import Surface


[docs] class MaterialFormatter: """A registry-based formatter for material information.""" _formatters: dict[type, Callable[[Surface], str]] = {} _default_formatter: Callable[[Surface], str] | None = None
[docs] @classmethod def register(cls, material_type: type, formatter: Callable[[Surface], str]): """Registers a formatter function for a specific material type. Args: material_type: The class of the material to format. formatter: A function that takes a Surface object and returns a formatted string description of its material. """ cls._formatters[material_type] = formatter
[docs] @classmethod def set_default(cls, formatter: Callable[[Surface], str]): """Sets the default formatter for unknown material types.""" cls._default_formatter = formatter
[docs] @classmethod def format(cls, surface: Surface) -> str: """Formats the material information for a given surface. Args: surface: The surface whose material information is to be formatted. Returns: str: A formatted string description of the material. """ # specialized check for mirror if surface.interaction_model.is_reflective: return "Mirror" # specialized check for air (which might not be a class) if hasattr(surface, "material_post"): index = getattr(surface.material_post, "index", None) if index == 1: return "Air" if hasattr(surface, "material_post"): material = surface.material_post # check for exact match first formatter = cls._formatters.get(type(material)) # check for subclass match if no exact match if not formatter: for mat_type, fmt in cls._formatters.items(): if isinstance(material, mat_type): formatter = fmt break if formatter: return formatter(surface) if cls._default_formatter: return cls._default_formatter(surface) raise ValueError("Unknown material type")
# --- standard formatters --- def _format_material(surface: Surface) -> str: return surface.material_post.name def _format_material_file(surface: Surface) -> str: return os.path.basename(surface.material_post.filename) def _format_ideal_material(surface: Surface) -> str: return str(surface.material_post.index.item()) def _format_abbe_material(surface: Surface) -> str: return ( f"{surface.material_post.index.item():.4f}, " f"{surface.material_post.abbe.item():.2f}" ) def _format_abbe_material_e(surface: Surface) -> str: return ( f"{surface.material_post.index.item():.4f}, " f"{surface.material_post.abbe.item():.2f} (ne, Ve)" ) # --- registration --- MaterialFormatter.register(materials.Material, _format_material) MaterialFormatter.register(materials.MaterialFile, _format_material_file) MaterialFormatter.register(materials.IdealMaterial, _format_ideal_material) MaterialFormatter.register(materials.AbbeMaterial, _format_abbe_material) MaterialFormatter.register(materials.AbbeMaterialE, _format_abbe_material_e)