Source code for physicsnemo_curator.dashboard.widgets

# SPDX-FileCopyrightText: Copyright (c) 2025 - 2026 NVIDIA CORPORATION & AFFILIATES.
# SPDX-FileCopyrightText: All rights reserved.
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Widget registry mapping filter names to filter classes with dashboard widgets."""

from __future__ import annotations

import logging
from typing import Any

logger = logging.getLogger(__name__)


[docs] class WidgetRegistry: """Registry mapping filter names to filter classes for dashboard widgets. Filters that override :meth:`~physicsnemo_curator.core.base.Filter.dashboard_panel` are auto-discovered on construction. Additional filter classes can be registered at runtime via :meth:`register`. """ def __init__(self) -> None: """Initialize the registry and discover built-in filter widgets.""" self._filter_classes: dict[str, type] = {} self._auto_discover()
[docs] def register(self, filter_cls: type) -> None: """Register a filter class that provides a dashboard widget. Parameters ---------- filter_cls : type A :class:`~physicsnemo_curator.core.base.Filter` subclass whose ``dashboard_panel`` classmethod returns non-None. """ self._filter_classes[filter_cls.name] = filter_cls # ty: ignore[unresolved-attribute]
[docs] def get_panel( self, filter_name: str, artifact_paths: list[str], selected_index: int | None = None, ) -> Any: """Look up a filter class by name and render its dashboard widget. Parameters ---------- filter_name : str The filter's ``name`` class variable (as stored in the DB). artifact_paths : list[str] Paths to artifact files produced by the filter. selected_index : int or None Currently selected pipeline index, if any. Returns ------- pn.viewable.Viewable or None The rendered widget, or ``None`` if no widget is registered. """ cls = self._filter_classes.get(filter_name) if cls is None: return None return cls.dashboard_panel(artifact_paths, selected_index) # ty: ignore[unresolved-attribute]
[docs] def get_layout_hints(self, filter_name: str) -> dict[str, int]: """Look up layout hints for a filter name. Parameters ---------- filter_name : str The filter's ``name`` class variable. Returns ------- dict[str, int] Grid column and row span preferences. """ cls = self._filter_classes.get(filter_name) if cls is None: return {"cols": 6, "rows": 2} return cls.dashboard_layout_hints() # ty: ignore[unresolved-attribute]
[docs] def list_providers(self) -> dict[str, str]: """Return a mapping of filter name to filter name for all registered widgets. Returns ------- dict[str, str] ``{filter_name: filter_name}`` for all registered filters. """ return {name: name for name in self._filter_classes}
def _auto_discover(self) -> None: """Import known filter classes with dashboard widgets. Imports are deferred so the registry works even when optional domain dependencies are not installed. """ try: from physicsnemo_curator.domains.atm.filters.stats import AtomicStatsFilter self.register(AtomicStatsFilter) except Exception: # noqa: BLE001 logger.debug("AtomicStatsFilter not available", exc_info=True) try: from physicsnemo_curator.domains.mesh.filters.stats import MeshStatsFilter self.register(MeshStatsFilter) except Exception: # noqa: BLE001 logger.debug("MeshStatsFilter not available", exc_info=True) try: from physicsnemo_curator.domains.mesh.filters.mean import MeanFilter self.register(MeanFilter) except Exception: # noqa: BLE001 logger.debug("MeanFilter not available", exc_info=True) try: from physicsnemo_curator.domains.da.filters.stats import DataArrayStatsFilter self.register(DataArrayStatsFilter) except Exception: # noqa: BLE001 logger.debug("DataArrayStatsFilter not available", exc_info=True)