Source code for spine.geo.manager

"""Manages a singleton instance of a Geometry class."""

from __future__ import annotations

import inspect

from .base import Geometry
from .factories import geo_factory
from .utils import version_matches


[docs] class GeoManager: """Manages a singleton instance of a Geometry class.""" _instance: Geometry | None = None
[docs] @classmethod def initialize( cls, detector: str, tag: str | None = None, version: str | int | float | None = None, ) -> Geometry: """Initialize the geometry module for a given detector. Parameters ---------- detector : str The name of the detector. tag : str, optional A tag to identify a specific configuration. version : str, optional A version number for the geometry configuration. Returns ------- Geometry The initialized geometry instance. """ if cls._instance is not None: raise ValueError("Geometry module already initialized.") cls._instance = geo_factory(detector, tag, version) return cls._instance
[docs] @classmethod def initialize_or_get( cls, detector: str, tag: str | None = None, version: str | int | float | None = None, ) -> Geometry: """Initialize the geometry if needed, or return the existing instance. Parameters ---------- detector : str The name of the detector. tag : str, optional A tag to identify a specific configuration. version : str, optional A version number for the geometry configuration. """ # If the geometry is not initialized, initialize it if cls._instance is None: cls._instance = geo_factory(detector, tag, version) return cls._instance # If the geometry is already initialized, check if it matches the # requested configuration. If it does not match, initialize it again current = cls._instance version_mismatch = not version_matches(current.version, version) tag_mismatch = tag is not None and current.tag != tag if current.name.lower() != detector.lower() or tag_mismatch or version_mismatch: cls._instance = geo_factory(detector, tag, version) return cls._instance
[docs] @classmethod def is_initialized(cls) -> bool: """Check if the geometry instance is initialized. Returns ------- bool True if the geometry instance is initialized, False otherwise. """ return cls._instance is not None
[docs] @classmethod def get_instance(cls) -> Geometry: """Get the current geometry instance. Parameters ---------- raise_error : bool, optional Whether to raise an error if the instance is not initialized. Returns ------- Geometry The current geometry instance. """ if cls._instance is None: # Raise an error with detailed information about the call site frame_info = inspect.stack()[1] frame = frame_info.frame func = frame.f_code.co_name cls_obj = frame.f_locals.get("self") class_name = cls_obj.__class__.__name__ if cls_obj else None location = f"{class_name}.{func}()" if class_name else f"{func}()" raise ValueError( "Geometry singleton instance is not initialized.\n" f"Attempted access from: {location}\n" f"File: {frame_info.filename}:{frame_info.lineno}\n\n" "If using the Driver, include a `geo` block in the configuration.\n" "If running standalone, initialize geometry with either:\n" " GeoManager.initialize(detector='your_detector_name')\n" " GeoManager.initialize_or_get(detector='your_detector_name')\n" "before calling geometry-dependent modules." ) return cls._instance
[docs] @classmethod def get_instance_if_initialized(cls) -> Geometry | None: """Get the current geometry instance if initialized. Returns ------- Optional[Geometry] The current geometry instance, or None if not initialized. """ return cls._instance
[docs] @classmethod def reset(cls) -> None: """Reset the geometry instance (useful for testing).""" cls._instance = None