Source code for materials.catalog

"""MaterialCatalog — read-only view into one catalog within the MaterialRegistry.

Provides discovery and search UX for a specific manufacturer catalog.

Kramer Harrison, 2025
"""

from __future__ import annotations

import pathlib
from importlib import resources

from optiland.materials.material_spec import MatchPolicy
from optiland.materials.registry import MaterialRegistry


[docs] class MaterialCatalog: """Read-only view into one glass manufacturer catalog. Usage:: MaterialCatalog.groups() # ['3d', 'glass', 'main', 'organic', 'other'] MaterialCatalog.available() # glass manufacturers only MaterialCatalog("schott").list() # glass names in catalog MaterialCatalog("schott").search("bk7") # substring search MaterialCatalog("schott").get("N-BK7") # instantiate material Args: catalog: Glass manufacturer catalog name (e.g. ``"schott"``, ``"ohara"``). """ def __init__(self, catalog: str) -> None: self._catalog = catalog
[docs] @classmethod def groups(cls) -> list[str]: """Return sorted list of all group names in the database. Groups reflect the top-level organisation of the refractiveindex.info database: ``'glass'`` (manufacturer catalogs), ``'main'`` (elements and compounds), ``'organic'`` (organic species), ``'other'`` (miscellaneous), and ``'3d'`` (metamaterials/plasmonics). Non-glass groups are not exposed through :class:`MaterialCatalog`; use :meth:`~optiland.materials.registry.MaterialRegistry.list_catalogs` with a ``group`` argument to enumerate them. """ return MaterialRegistry.instance().list_groups()
[docs] @classmethod def available(cls) -> list[str]: """Return sorted list of glass manufacturer catalog names. The list is derived directly from the subdirectory names under the built-in ``data-nk/glass/`` directory, which is the authoritative source of manufacturer catalogs. To list species in non-glass groups use :meth:`~optiland.materials.registry.MaterialRegistry.list_catalogs` directly with ``group='main'``, ``'organic'``, or ``'other'``. """ glass_dir = pathlib.Path( str(resources.files("optiland.database").joinpath("data-nk/glass")) ) return sorted(d.name for d in glass_dir.iterdir() if d.is_dir())
[docs] def list(self) -> list[str]: """Return sorted list of material names in this catalog.""" return MaterialRegistry.instance().list_materials(self._catalog)
[docs] def search(self, query: str, n: int | None = None) -> list[str]: """Return material names whose name contains ``query`` (case-insensitive). Args: query: Substring to search for within glass names. n: Maximum number of results to return. ``None`` returns all matches. Returns: Sorted list of matching material names. """ q = query.lower() matches = [name for name in self.list() if q in name.lower()] return matches[:n] if n is not None else matches
[docs] def get(self, name: str, match_policy: MatchPolicy = MatchPolicy.WARN) -> object: """Instantiate a :class:`~optiland.materials.material.Material` from this catalog. Args: name: Exact (or close) material name. match_policy: Controls fuzzy-match behavior. Returns: A :class:`~optiland.materials.material.Material` instance. """ from optiland.materials.material import Material return Material(name, catalog=self._catalog, match_policy=match_policy)
def __repr__(self) -> str: return f"MaterialCatalog('{self._catalog}')"