Sources Module

Sources Module - Ray Generation for Raytracing

This module provides ray source classes for generating initial ray conditions. Each source type generates rays with specific spatial and angular distributions.

Available Sources

RaySourceABC

Abstract base class defining the source interface.

PointSource

Isotropic point source emitting in all directions.

CollimatedBeam

Parallel beam with uniform or Gaussian intensity profile.

DivergingBeam

Beam with angular divergence (fiber output, LED).

UniformDivergingBeam

Diverging beam with uniform solid angle distribution.

GaussianBeam

Gaussian beam following paraxial optics.

ParallelBeamFromPositions

Parallel rays from explicit position array (atmospheric studies).

CustomRaySource

Fully customizable rays with per-ray position, direction, wavelength, and intensity (chromatic dispersion, custom setups).

Interface

All sources implement the generate() method:

>>> rays = source.generate()

Returns a RayBatch with initialized positions, directions, wavelengths, and intensities.

Examples

>>> from surface_roughness.sources import CollimatedBeam, PointSource
>>>
>>> # Create a collimated laser beam
>>> beam = CollimatedBeam(
...     center=(0, 0, -10),
...     direction=(0, 0, 1),
...     radius=0.001,
...     num_rays=10000,
...     wavelength=633e-9,
...     power=5e-3
... )
>>> rays = beam.generate()
>>>
>>> # Create an isotropic point source
>>> point = PointSource(
...     position=(0, 0, 0),
...     num_rays=5000,
...     wavelength=532e-9,
...     power=1e-3
... )
>>> rays = point.generate()
>>>
>>> # Create parallel rays from explicit positions (for atmospheric studies)
>>> import numpy as np
>>> positions = np.array([
...     [-1000, 0, 100],
...     [-1000, 0, 200],
...     [-1000, 0, 300],
... ])
>>> source = ParallelBeamFromPositions(
...     positions=positions,
...     direction=(1, 0, 0),
...     wavelength=532e-9,
... )
>>> rays = source.generate()
class lsurf.sources.RaySource(num_rays, wavelength, power=1.0)[source]

Bases: ABC

Abstract base class for ray sources.

A ray source defines initial conditions for a ray batch, including spatial distribution, angular distribution, wavelength spectrum, and intensity distribution.

Parameters:
  • num_rays (int) – Number of rays to generate. Must be positive.

  • wavelength (float or tuple of float) – Single wavelength in meters for monochromatic source, or (min, max) tuple for polychromatic source.

  • power (float, optional) – Total source power in watts. Default is 1.0.

num_rays

Number of rays generated by this source.

Type:

int

wavelength

Wavelength specification.

Type:

float or tuple

power

Total source power.

Type:

float

Notes

Derived classes must implement the generate() method which returns a fully initialized RayBatch.

The ray intensities should sum to the total power (conservation of energy). When generating rays, use _allocate_rays() to create the batch with proper initialization and _assign_wavelengths() to set wavelengths.

Examples

Creating a custom source:

>>> class MySource(RaySource):
...     def __init__(self, position, num_rays, wavelength, power=1.0):
...         super().__init__(num_rays, wavelength, power)
...         self.position = np.array(position)
...
...     def generate(self):
...         rays = self._allocate_rays()
...         rays.positions[:] = self.position
...         # Set directions...
...         self._assign_wavelengths(rays)
...         return rays
__init__(num_rays, wavelength, power=1.0)[source]

Initialize ray source.

Parameters:
  • num_rays (int) – Number of rays to generate. Must be positive.

  • wavelength (float or tuple of float) – Single wavelength (m) or (min, max) range.

  • power (float, optional) – Total source power in watts. Default is 1.0.

Raises:

ValueError – If num_rays <= 0, power <= 0, wavelength <= 0, or wavelength range is invalid.

abstractmethod generate()[source]

Generate ray batch with initial conditions.

Creates and initializes a RayBatch with positions, directions, wavelengths, and intensities according to the source configuration.

Returns:

Initialized rays ready for propagation.

Return type:

RayBatch

Notes

Implementations should ensure: - All rays are marked as active - Directions are normalized - Intensities sum to total power - Wavelengths are set appropriately

__repr__()[source]

Return string representation.

class lsurf.sources.PointSource(position, num_rays, wavelength, power=1.0)[source]

Bases: RaySource

Isotropic point source emitting in all directions.

Generates rays from a single point with directions uniformly distributed over the unit sphere.

Parameters:
  • position (tuple of float) – Source position (x, y, z) in meters.

  • num_rays (int) – Number of rays to generate.

  • wavelength (float or tuple of float) – Single wavelength (m) or (min, max) range.

  • power (float, optional) – Total source power in watts. Default is 1.0.

position

Source position in meters.

Type:

ndarray, shape (3,)

Notes

The angular distribution is uniform over the full 4π steradians. Each ray carries equal intensity (power / num_rays).

Examples

>>> # Monochromatic point source
>>> source = PointSource(
...     position=(0, 0, 0),
...     num_rays=10000,
...     wavelength=532e-9,
...     power=1e-3
... )
>>> rays = source.generate()
>>> # Polychromatic source (white light LED)
>>> source = PointSource(
...     position=(0, 0.1, 0),
...     num_rays=5000,
...     wavelength=(400e-9, 700e-9),
...     power=0.5
... )
__init__(position, num_rays, wavelength, power=1.0)[source]

Initialize point source.

Parameters:
  • position (tuple of float) – Source position (x, y, z) in meters.

  • num_rays (int) – Number of rays to generate.

  • wavelength (float or tuple of float) – Wavelength in meters or (min, max) range.

  • power (float, optional) – Total source power in watts. Default is 1.0.

generate()[source]

Generate isotropic ray distribution.

Creates rays emanating from the source position with directions uniformly distributed over the unit sphere.

Returns:

Ray batch with isotropic direction distribution.

Return type:

RayBatch

Notes

Uses the standard method for uniform sphere sampling: - θ uniformly distributed in [0, 2π) - cos(φ) uniformly distributed in [-1, 1]

__repr__()[source]

Return string representation.

class lsurf.sources.CollimatedBeam(center, direction, radius, num_rays, wavelength, power=1.0, profile='uniform')[source]

Bases: RaySource

Collimated beam with parallel rays.

Generates rays with identical directions and positions distributed in a circular cross-section. Supports uniform and Gaussian intensity profiles.

Parameters:
  • center (tuple of float) – Beam center position (x, y, z) in meters.

  • direction (tuple of float) – Beam propagation direction (dx, dy, dz), will be normalized.

  • radius (float) – Beam radius in meters.

  • num_rays (int) – Number of rays to generate.

  • wavelength (float or tuple of float) – Single wavelength (m) or (min, max) range.

  • power (float, optional) – Total beam power in watts. Default is 1.0.

  • profile ({'uniform', 'gaussian'}, optional) – Spatial intensity profile. Default is ‘uniform’.

center

Beam center position.

Type:

ndarray, shape (3,)

direction

Normalized beam direction.

Type:

ndarray, shape (3,)

radius

Beam radius.

Type:

float

profile

Intensity profile type.

Type:

str

Notes

For Gaussian profile, the radius corresponds to 2σ (where σ is the standard deviation of the Gaussian). Ray intensities are weighted according to the Gaussian distribution.

Ray timing is initialized so that all rays cross the reference plane (at center) at time=0. This ensures coherent phase fronts.

Examples

>>> # Uniform circular beam
>>> source = CollimatedBeam(
...     center=(0, 0, 0),
...     direction=(0, 0, 1),
...     radius=1e-3,
...     num_rays=5000,
...     wavelength=633e-9,
...     power=5e-3
... )
>>> # Gaussian beam profile
>>> source = CollimatedBeam(
...     center=(0, 0, 0),
...     direction=(0, 0, 1),
...     radius=2e-3,
...     num_rays=10000,
...     wavelength=1064e-9,
...     power=1.0,
...     profile='gaussian'
... )
__init__(center, direction, radius, num_rays, wavelength, power=1.0, profile='uniform')[source]

Initialize collimated beam.

Parameters:
  • center (tuple of float) – Beam center position (x, y, z) in meters.

  • direction (tuple of float) – Beam propagation direction, will be normalized.

  • radius (float) – Beam radius in meters.

  • num_rays (int) – Number of rays to generate.

  • wavelength (float or tuple of float) – Wavelength in meters or (min, max) range.

  • power (float, optional) – Total beam power in watts. Default is 1.0.

  • profile ({'uniform', 'gaussian'}, optional) – Spatial intensity profile. Default is ‘uniform’.

Raises:

ValueError – If radius <= 0 or profile not in {‘uniform’, ‘gaussian’}.

generate()[source]

Generate collimated beam.

Creates rays with parallel directions and positions sampled in a disk perpendicular to the beam direction.

Returns:

Ray batch with collimated ray directions.

Return type:

RayBatch

Notes

For uniform profile, positions are uniformly distributed in a disk. For Gaussian profile, positions follow a 2D Gaussian distribution and intensities are weighted accordingly.

__repr__()[source]

Return string representation.

class lsurf.sources.DivergingBeam(origin, mean_direction, divergence_angle, num_rays, wavelength, power=1.0)[source]

Bases: RaySource

Beam with angular divergence.

Generates rays from a single point with directions distributed within a cone around the mean direction. Suitable for modeling fiber optic outputs, LEDs, and similar diverging sources.

Parameters:
  • origin (tuple of float) – Source position (x, y, z) in meters.

  • mean_direction (tuple of float) – Mean beam direction (dx, dy, dz), will be normalized.

  • divergence_angle (float) – Half-angle divergence in radians (cone half-angle). Must be in range (0, π/2).

  • num_rays (int) – Number of rays to generate.

  • wavelength (float or tuple of float) – Single wavelength (m) or (min, max) range.

  • power (float, optional) – Total source power in watts. Default is 1.0.

origin

Source position.

Type:

ndarray, shape (3,)

mean_direction

Normalized mean beam direction.

Type:

ndarray, shape (3,)

divergence_angle

Cone half-angle in radians.

Type:

float

Notes

The angular distribution is uniform within the cone. For Lambertian sources (cosine distribution), a different implementation would be needed.

Examples

>>> # Fiber output with 0.1 rad NA
>>> source = DivergingBeam(
...     origin=(0, 0, 0),
...     mean_direction=(0, 0, 1),
...     divergence_angle=0.1,
...     num_rays=5000,
...     wavelength=1550e-9,
...     power=1e-3
... )
>>> # LED with wide angle
>>> source = DivergingBeam(
...     origin=(0, 0.1, 0),
...     mean_direction=(0, 0, 1),
...     divergence_angle=np.radians(30),  # 30 degrees
...     num_rays=10000,
...     wavelength=(400e-9, 700e-9),
...     power=0.5
... )
__init__(origin, mean_direction, divergence_angle, num_rays, wavelength, power=1.0)[source]

Initialize diverging beam.

Parameters:
  • origin (tuple of float) – Source position (x, y, z) in meters.

  • mean_direction (tuple of float) – Mean beam direction, will be normalized.

  • divergence_angle (float) – Cone half-angle in radians.

  • num_rays (int) – Number of rays to generate.

  • wavelength (float or tuple of float) – Wavelength in meters or (min, max) range.

  • power (float, optional) – Total source power in watts. Default is 1.0.

Raises:

ValueError – If divergence_angle not in (0, π/2).

generate()[source]

Generate diverging beam.

Creates rays from the origin with directions uniformly distributed within a cone around the mean direction.

Returns:

Ray batch with diverging direction distribution.

Return type:

RayBatch

Notes

Uses spherical coordinates relative to the mean direction to generate uniformly distributed directions within the cone.

__repr__()[source]

Return string representation.

class lsurf.sources.UniformDivergingBeam(origin, mean_direction, divergence_angle, num_rays, wavelength, power=1.0)[source]

Bases: RaySource

Beam with angular divergence and uniform solid angle distribution.

Generates rays from a single point with directions uniformly distributed over the solid angle of a cone around the mean direction. Each element of solid angle receives equal ray density.

This is physically correct for sources that emit uniformly over a cone (e.g., idealized point sources with angular limits).

Parameters:
  • origin (tuple of float) – Source position (x, y, z) in meters.

  • mean_direction (tuple of float) – Mean beam direction (dx, dy, dz), will be normalized.

  • divergence_angle (float) – Half-angle divergence in radians (cone half-angle). Must be in range (0, π/2).

  • num_rays (int) – Number of rays to generate.

  • wavelength (float or tuple of float) – Single wavelength (m) or (min, max) range.

  • power (float, optional) – Total source power in watts. Default is 1.0.

origin

Source position.

Type:

ndarray, shape (3,)

mean_direction

Normalized mean beam direction.

Type:

ndarray, shape (3,)

divergence_angle

Cone half-angle in radians.

Type:

float

solid_angle

Solid angle of the cone in steradians: Ω = 2π(1 - cos(θ))

Type:

float

Notes

The key difference from DivergingBeam is the sampling of the polar angle:

  • DivergingBeam: phi ~ Uniform(0, divergence_angle) This creates higher ray density near the cone axis.

  • UniformDivergingBeam: cos(phi) ~ Uniform(cos(divergence_angle), 1) This creates uniform ray density per solid angle.

The solid angle of a cone with half-angle θ is:

Ω = 2π(1 - cos(θ))

For uniform sampling over this solid angle, we need:

dN/dΩ = constant

This requires sampling cos(phi) uniformly, not phi.

Examples

>>> # Uniform emission over 10 degree cone
>>> source = UniformDivergingBeam(
...     origin=(0, 0, 0),
...     mean_direction=(0, 0, 1),
...     divergence_angle=np.radians(10),
...     num_rays=5000,
...     wavelength=1550e-9,
...     power=1e-3
... )
>>> # Compare solid angle coverage
>>> # Expected: uniform distribution in cos(phi)
__init__(origin, mean_direction, divergence_angle, num_rays, wavelength, power=1.0)[source]

Initialize uniform diverging beam.

Parameters:
  • origin (tuple of float) – Source position (x, y, z) in meters.

  • mean_direction (tuple of float) – Mean beam direction, will be normalized.

  • divergence_angle (float) – Cone half-angle in radians.

  • num_rays (int) – Number of rays to generate.

  • wavelength (float or tuple of float) – Wavelength in meters or (min, max) range.

  • power (float, optional) – Total source power in watts. Default is 1.0.

Raises:

ValueError – If divergence_angle not in (0, π/2).

property solid_angle: float

Solid angle of the cone in steradians.

Returns:

Ω = 2π(1 - cos(θ)) where θ is the divergence half-angle.

Return type:

float

generate()[source]

Generate uniformly diverging beam.

Creates rays from the origin with directions uniformly distributed over the solid angle of a cone around the mean direction.

Returns:

Ray batch with uniform solid angle distribution.

Return type:

RayBatch

Notes

The sampling uses: - theta ~ Uniform(0, 2π) for azimuthal angle - cos(phi) ~ Uniform(cos(divergence_angle), 1) for polar angle

This ensures dN/dΩ = constant over the cone.

__repr__()[source]

Return string representation.

class lsurf.sources.GaussianBeam(waist_position, direction, waist_radius, num_rays, wavelength, power=1.0)[source]

Bases: RaySource

Gaussian beam with specified waist and Rayleigh range.

Implements paraxial Gaussian beam using ray approximation. Each ray represents a wavefront normal, with intensity weighted according to the Gaussian profile.

Parameters:
  • waist_position (tuple of float) – Position of beam waist (x, y, z) in meters.

  • direction (tuple of float) – Beam axis direction (dx, dy, dz), will be normalized.

  • waist_radius (float) – Beam waist radius (w₀) in meters.

  • num_rays (int) – Number of rays to generate.

  • wavelength (float) – Wavelength in meters. Must be monochromatic for Gaussian beam.

  • power (float, optional) – Total beam power in watts. Default is 1.0.

waist_position

Beam waist position.

Type:

ndarray, shape (3,)

direction

Normalized beam direction.

Type:

ndarray, shape (3,)

waist_radius

Beam waist radius w₀.

Type:

float

rayleigh_range

Rayleigh range z_R = πw₀²/λ.

Type:

float

Notes

The Gaussian beam has intensity profile:

I(r) = I₀ exp(-2r²/w²)

where w is the beam radius at distance z from the waist:

w(z) = w₀ √(1 + (z/z_R)²)

and z_R = πw₀²/λ is the Rayleigh range.

This implementation generates rays at the waist position with parallel directions (plane wavefront at waist). Ray intensities are weighted according to the Gaussian profile.

Examples

>>> # 1 mm waist Nd:YAG laser
>>> source = GaussianBeam(
...     waist_position=(0, 0, 0),
...     direction=(0, 0, 1),
...     waist_radius=1e-3,
...     num_rays=5000,
...     wavelength=1064e-9,
...     power=10e-3
... )
>>> print(f"Rayleigh range: {source.rayleigh_range:.3f} m")
__init__(waist_position, direction, waist_radius, num_rays, wavelength, power=1.0)[source]

Initialize Gaussian beam.

Parameters:
  • waist_position (tuple of float) – Position of beam waist (x, y, z) in meters.

  • direction (tuple of float) – Beam axis direction, will be normalized.

  • waist_radius (float) – Beam waist radius w₀ in meters.

  • num_rays (int) – Number of rays to generate.

  • wavelength (float) – Wavelength in meters.

  • power (float, optional) – Total beam power in watts. Default is 1.0.

Raises:

ValueError – If wavelength is a tuple (polychromatic not supported), or if waist_radius <= 0.

generate()[source]

Generate Gaussian beam.

Creates rays at the waist position with Gaussian-distributed positions and parallel directions.

Returns:

Ray batch with Gaussian intensity distribution.

Return type:

RayBatch

Notes

Positions are sampled from a 2D Gaussian distribution with σ = w₀/2. Intensities are weighted by the Gaussian profile to accurately represent the beam’s energy distribution.

beam_radius_at(z)[source]

Compute beam radius at distance z from waist.

Parameters:

z (float) – Distance from waist along beam axis in meters.

Returns:

Beam radius w(z) in meters.

Return type:

float

Notes

w(z) = w₀ √(1 + (z/z_R)²)

divergence_angle()[source]

Compute far-field divergence angle.

Returns:

Half-angle divergence in radians.

Return type:

float

Notes

θ = λ / (π w₀)

__repr__()[source]

Return string representation.

class lsurf.sources.ParallelBeamFromPositions(positions, direction, wavelength=5.32e-07, power=1.0)[source]

Bases: RaySource

Parallel rays from explicitly specified positions.

All rays share the same direction, making this ideal for: - Atmospheric refraction studies with specific impact parameters - Plane wave propagation through inhomogeneous media - Grid-based ray launching for wavefront analysis

Unlike CollimatedBeam which generates positions in a disk, this source accepts arbitrary position arrays, enabling custom spatial distributions.

Parameters:
  • positions (array_like, shape (N, 3)) – Starting positions for each ray in meters.

  • direction (tuple of float) – Direction vector for all rays (will be normalized).

  • wavelength (float or tuple of float, optional) – Single wavelength (m) or (min, max) range. Default is 532 nm.

  • power (float, optional) – Total source power in watts. Default is 1.0.

positions

Ray starting positions.

Type:

ndarray, shape (N, 3)

direction

Normalized ray direction.

Type:

ndarray, shape (3,)

Examples

>>> # Rays at different impact parameters for atmospheric study
>>> impact_params = np.linspace(0, 10000, 100)
>>> positions = np.column_stack([
...     -np.sqrt((R + 100e3)**2 - (R + impact_params)**2),  # x
...     np.zeros_like(impact_params),                       # y
...     impact_params                                       # z
... ])
>>> source = ParallelBeamFromPositions(positions, direction=(1, 0, 0))
>>> rays = source.generate()
>>> propagator.propagate(rays, total_distance=500e3, step_size=100)
>>> # Regular grid of rays
>>> x, y = np.meshgrid(np.linspace(-1, 1, 10), np.linspace(-1, 1, 10))
>>> positions = np.column_stack([x.ravel(), y.ravel(), np.zeros(100)])
>>> source = ParallelBeamFromPositions(positions, direction=(0, 0, 1))
__init__(positions, direction, wavelength=5.32e-07, power=1.0)[source]

Initialize parallel ray source.

Parameters:
  • positions (array_like, shape (N, 3)) – Starting positions for each ray in meters.

  • direction (tuple of float) – Direction vector for all rays (will be normalized).

  • wavelength (float or tuple of float, optional) – Wavelength in meters or (min, max) range. Default is 532 nm.

  • power (float, optional) – Total source power in watts. Default is 1.0.

Raises:

ValueError – If positions shape is invalid or direction is zero vector.

property positions: ndarray[tuple[Any, ...], dtype[float32]]

Ray starting positions, shape (N, 3).

generate()[source]

Generate parallel ray batch.

Creates rays at the specified positions, all with the same direction.

Returns:

Ray batch with parallel rays ready for propagation.

Return type:

RayBatch

__repr__()[source]

Return string representation.

class lsurf.sources.CustomRaySource(positions, directions, wavelengths, intensities=None)[source]

Bases: object

Fully customizable ray source with per-ray properties.

Each ray can have its own position, direction, wavelength, and intensity. This provides maximum flexibility for specialized simulations.

Parameters:
  • positions (array_like, shape (N, 3)) – Starting position for each ray in meters.

  • directions (array_like, shape (N, 3)) – Direction vector for each ray (will be normalized).

  • wavelengths (array_like, shape (N,)) – Wavelength for each ray in meters.

  • intensities (array_like, shape (N,), optional) – Intensity/power for each ray in watts. If None, defaults to uniform distribution with total power of 1.0.

num_rays

Number of rays.

Type:

int

positions

Ray starting positions.

Type:

ndarray, shape (N, 3)

directions

Normalized ray directions.

Type:

ndarray, shape (N, 3)

wavelengths

Per-ray wavelengths.

Type:

ndarray, shape (N,)

intensities

Per-ray intensities.

Type:

ndarray, shape (N,)

power

Total power (sum of intensities).

Type:

float

Examples

>>> # Chromatic dispersion study - same start, different wavelengths
>>> n_rays = 100
>>> positions = np.tile([0, 0, 1000], (n_rays, 1))  # All at same point
>>> directions = np.tile([1, 0, 0], (n_rays, 1))    # All same direction
>>> wavelengths = np.linspace(400e-9, 700e-9, n_rays)  # Visible spectrum
>>> source = CustomRaySource(positions, directions, wavelengths)
>>> rays = source.generate()
>>> # Fan of rays for refraction analysis
>>> angles = np.linspace(-0.1, 0.1, 50)  # +/- 5.7 degrees
>>> positions = np.zeros((50, 3))
>>> directions = np.column_stack([
...     np.cos(angles),
...     np.zeros(50),
...     np.sin(angles)
... ])
>>> wavelengths = np.full(50, 550e-9)
>>> source = CustomRaySource(positions, directions, wavelengths)
__init__(positions, directions, wavelengths, intensities=None)[source]

Initialize custom ray source.

Parameters:
  • positions (array_like, shape (N, 3)) – Starting position for each ray in meters.

  • directions (array_like, shape (N, 3)) – Direction vector for each ray (will be normalized).

  • wavelengths (array_like, shape (N,)) – Wavelength for each ray in meters.

  • intensities (array_like, shape (N,), optional) – Intensity for each ray. If None, uniform distribution is used.

Raises:

ValueError – If array shapes are inconsistent or invalid.

property num_rays: int

Number of rays.

property positions: ndarray[tuple[Any, ...], dtype[float32]]

Ray starting positions, shape (N, 3).

property directions: ndarray[tuple[Any, ...], dtype[float32]]

Normalized ray directions, shape (N, 3).

property wavelengths: ndarray[tuple[Any, ...], dtype[float32]]

Per-ray wavelengths in meters, shape (N,).

property intensities: ndarray[tuple[Any, ...], dtype[float32]]

Per-ray intensities, shape (N,).

property power: float

Total power (sum of intensities).

generate()[source]

Generate ray batch with specified properties.

Creates a RayBatch with positions, directions, wavelengths, and intensities as specified in the constructor.

Returns:

Ray batch ready for propagation.

Return type:

RayBatch

__repr__()[source]

Return string representation.

classmethod from_spectral_fan(origin, direction, wavelength_range, num_rays, total_power=1.0)[source]

Create rays with same position/direction but varying wavelengths.

Convenience factory for chromatic dispersion studies.

Parameters:
  • origin (tuple of float) – Starting position for all rays (x, y, z) in meters.

  • direction (tuple of float) – Direction for all rays (will be normalized).

  • wavelength_range (tuple of float) – (min_wavelength, max_wavelength) in meters.

  • num_rays (int) – Number of rays to create.

  • total_power (float, optional) – Total power distributed uniformly. Default is 1.0 W.

Returns:

Source with spectral distribution.

Return type:

CustomRaySource

Examples

>>> # Visible spectrum from single point
>>> source = CustomRaySource.from_spectral_fan(
...     origin=(0, 0, 0),
...     direction=(1, 0, 0),
...     wavelength_range=(400e-9, 700e-9),
...     num_rays=100,
... )
classmethod from_angular_fan(origin, base_direction, angle_range, num_rays, wavelength=5.5e-07, total_power=1.0, fan_axis='vertical')[source]

Create rays from same position with varying angles.

Convenience factory for refraction/reflection studies.

Parameters:
  • origin (tuple of float) – Starting position for all rays (x, y, z) in meters.

  • base_direction (tuple of float) – Central direction of the fan (will be normalized).

  • angle_range (tuple of float) – (min_angle, max_angle) deviation from base direction in radians.

  • num_rays (int) – Number of rays to create.

  • wavelength (float, optional) – Wavelength for all rays. Default is 550 nm.

  • total_power (float, optional) – Total power distributed uniformly. Default is 1.0 W.

  • fan_axis (str, optional) – ‘vertical’ for z-rotation, ‘horizontal’ for y-rotation. Default is ‘vertical’.

Returns:

Source with angular distribution.

Return type:

CustomRaySource

Examples

>>> # Fan of rays spanning +/- 10 degrees
>>> source = CustomRaySource.from_angular_fan(
...     origin=(0, 0, 1000),
...     base_direction=(1, 0, 0),
...     angle_range=(-0.17, 0.17),  # ~10 degrees
...     num_rays=50,
... )

Source Classes

RaySource(num_rays, wavelength[, power])

Abstract base class for ray sources.

PointSource(position, num_rays, wavelength)

Isotropic point source emitting in all directions.

CollimatedBeam(center, direction, radius, ...)

Collimated beam with parallel rays.

DivergingBeam(origin, mean_direction, ...[, ...])

Beam with angular divergence.

GaussianBeam(waist_position, direction, ...)

Gaussian beam with specified waist and Rayleigh range.

ParallelBeamFromPositions(positions, direction)

Parallel rays from explicitly specified positions.