Source code for optika.propagators

"""Simulate light propagating through an optical system."""

from __future__ import annotations
from typing import Sequence
import abc
import dataclasses
import named_arrays as na
import optika

__all__ = [
    "propagate_rays",
    "accumulate_rays",
    "AbstractPropagator",
    "AbstractRayPropagator",
    "AbstractLightPropagator",
]


[docs] def propagate_rays( propagators: AbstractRayPropagator | Sequence[AbstractRayPropagator], rays: optika.rays.RayVectorArray, ) -> optika.rays.RayVectorArray: """ Iterate through a sequence of ray propagators, calling :meth:`~optika.propagators.AbstractRayPropagator.propagate_rays` on the given set of input rays. Parameters ---------- propagators a sequence of ray propagators to interact with ``rays`` rays the input rays to propagate through the sequence """ if isinstance(propagators, AbstractRayPropagator): propagators = [propagators] for propagator in propagators: rays = propagator.propagate_rays(rays) return rays
[docs] def accumulate_rays( propagators: AbstractRayPropagator | Sequence[AbstractRayPropagator], rays: optika.rays.RayVectorArray, axis: str, ) -> optika.rays.RayVectorArray: """ Iterate through a sequence of ray propagators, calling :meth:`~optika.propagators.AbstractRayPropagator.propagate_rays` on the given set of input rays, and store the resulting the rays at every propagator. Parameters ---------- propagators a sequence of ray propagators to interact with ``rays`` rays the input rays to propagate through the sequence axis the new axis representing the sequence of propagators """ if isinstance(propagators, AbstractRayPropagator): propagators = [propagators] result = [] for propagator in propagators: rays = propagator.propagate_rays(rays) result.append(rays) result = na.stack(result, axis=axis) return result
[docs] @dataclasses.dataclass(eq=False, repr=False) class AbstractPropagator( abc.ABC, ): """An interface for an object which can propagate information."""
[docs] @dataclasses.dataclass(eq=False, repr=False) class AbstractRayPropagator( AbstractPropagator, ): """An interface for an object that can interact with light rays."""
[docs] @abc.abstractmethod def propagate_rays( self, rays: optika.rays.AbstractRayVectorArray, ) -> optika.rays.AbstractRayVectorArray: """ For the given input rays, calculate new rays based off of their interation with this object. Parameters ---------- rays a set of input rays that will interact with this object """
[docs] @dataclasses.dataclass(eq=False, repr=False) class AbstractLightPropagator( AbstractRayPropagator, ): """An interface for an object which can interact with light."""