"""
Base Source Class Module
This module defines the abstract base class for all source types in Optiland.
All concrete source implementations must inherit from BaseSource and implement
the generate_rays method.
"""
from __future__ import annotations
from abc import ABC, abstractmethod
from typing import TYPE_CHECKING
from optiland.coordinate_system import CoordinateSystem
if TYPE_CHECKING:
from matplotlib.axes import Axes
from matplotlib.figure import Figure
from optiland.rays import RealRays
[docs]
class BaseSource(ABC):
"""
Abstract base class for all source types in Optiland.
This class defines the interface that all source implementations must follow.
All concrete source classes must implement the generate_rays method.
The source includes a coordinate system for proper positioning in 3D space.
Rays generated by the source are automatically transformed from local
coordinates to global coordinates using this coordinate system.
Attributes:
cs (CoordinateSystem): The coordinate system defining the source's
position and orientation in 3D space.
"""
def __init__(self, position: tuple[float, float, float] = (0.0, 0.0, 0.0)):
"""
Initialize the BaseSource with positioning information.
Args:
position (tuple[float, float, float]): The (x, y, z) position of
the source in millimeters. Defaults to (0.0, 0.0, 0.0).
"""
self.cs = CoordinateSystem(x=position[0], y=position[1], z=position[2])
[docs]
@abstractmethod
def generate_rays(self, num_rays: int) -> RealRays:
"""
Generate a specified number of rays from this source.
Args:
num_rays (int): The number of rays to generate.
Returns:
RealRays: An object containing the generated rays with their
positions, directions, intensities, and wavelengths.
Raises:
ValueError: If num_rays is not a positive integer or if ray
generation fails.
"""
pass
@abstractmethod
def __repr__(self) -> str:
"""
Return a string representation of the source.
Returns:
str: A string describing the source and its parameters.
"""
pass
[docs]
def draw(
self,
num_rays: int = 5000,
propagation_distance: float = 0.1,
figsize: tuple[float, float] = (18, 8),
cross_spatial: tuple[str, str] = ("x", "y"),
cross_angular: tuple[str, str] = ("L", "M"),
) -> tuple[Figure, list[Axes]]:
"""
Visualize the extended source with a comprehensive 6-panel plot.
This method creates a visualization showing the spatial and angular
distributions and propagation characteristics of the rays generated by
this source. The plot consists of six panels arranged in a 2x3 grid:
Column 1: Spatial and Angular Distributions
- Panel (0,0): XY spatial distribution with intensity color-coding
- Panel (1,0): Angular distribution (L vs M direction cosines)
Column 2: Cross-sections
- Panel (0,1): Spatial cross-sections (X and Y profiles)
- Panel (1,1): Angular cross-sections (L and M profiles)
Column 3: Ray Propagation
- Panel (0,2): XZ ray propagation paths with intensity-based coloring
- Panel (1,2): YZ ray propagation paths with intensity-based coloring
Args:
num_rays (int, optional): Number of rays to generate for visualization.
Defaults to 5000.
propagation_distance (float, optional): Distance in mm to propagate
rays for path visualization. Defaults to 0.1.
figsize (tuple[float, float], optional): Figure size (width, height)
in inches. Defaults to (18, 8).
cross_spatial (tuple[str, str], optional): Spatial cross-section axes.
Defaults to ("x", "y").
cross_angular (tuple[str, str], optional): Angular cross-section axes.
Defaults to ("L", "M").
Returns:
tuple[Figure, list[Axes]]: Matplotlib figure and list of 6 axes objects.
"""
from optiland.sources.visualization import SourceViewer
viewer = SourceViewer(self)
return viewer.view(
num_rays=num_rays,
propagation_distance=propagation_distance,
figsize=figsize,
cross_spatial=cross_spatial,
cross_angular=cross_angular,
)