Source

class diffinytrace.source.RaySource(transform)[source]

Bases: PhysicalObject

The RaySource is a the base class off all Objects emitting rays. It has a sample function which samples points. These points are used to initialize the rays with the forward function.

sample(num_points, method)[source]

Samples points in the parameter space of the ray source. :param num_points: The number of points to sample. :type num_points: int :param method: The sampling method to use. Can be “sobol”, “monte_carlo”, etc. :type method: str

Returns:

A tuple containing the sampled points and their weights.

Return type:

tuple

forward(x, n_func_enviroment)[source]

Define the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

get_plot_points_2D(resolution)[source]
get_plot_points_3D(resolution)[source]
get_volume()[source]
get_transform()[source]

Returns the transformation object associated with this physical object.

Raises:

NotImplementedError – If not implemented in subclass.

Returns:

Transformation object.

Return type:

object

class diffinytrace.source.LightSource(transform, integrator, flux_func=None, total_power=1.0, num_points_normalize=700000, method_normalize='sobol')[source]

Bases: RaySource, Plotable

In our model of an optical system, the light source is composed of the following components:

1. Light Source Domain The light source domain \(\Omega \subseteq \mathbb{R}^N\) represents the spatial domain of the light source.

2. Global Ray Initialization Function The global ray initialization function \(f: \mathbb{R}^N \times \mathbb{R}^{4 \times 4} \to \mathbb{R}^7\) is responsible for initializing the ray’s position \(O\), direction \(D\), and wavelength \(\lambda\) using a point \(x \in \Omega\) from the light source domain \(\Omega\). It consists of:

  • An affine transformation \(M \in \mathbb{R}^{4 \times 4}\).

  • A local ray initialization function \(\hat{f}: \mathbb{R}^N \to \mathbb{R}^7\).

The global ray initialization function is defined by:

\[\begin{split}f(x, M) := \begin{bmatrix} M \begin{bmatrix}\hat{O} \\ 1\end{bmatrix} \\ M \begin{bmatrix}\hat{D} \\ 0\end{bmatrix} \\ \lambda \end{bmatrix},\end{split}\]

where:

\[\begin{split}\begin{bmatrix}\hat{O} \\ \hat{D} \\ \lambda \end{bmatrix} = \hat{f}(x).\end{split}\]

3. Flux Function The flux function \(Q: \mathbb{R}^N \to \mathbb{R}\) assigns a flux weight to each point \(x \in \Omega\).

The ray initialization function bridges the gap between the light source domain and the actual ray tracer. This abstraction is also very helpful for implementation, as it allows for modular design. Following this principle, one does not sample rays in our library, but points and weights according to an integration rule. The light source classes also implement a forward function which is equivalent to the ray initialization function.

Example

>>> import diffinytrace as dit
>>> wave_len = 1.0
>>> radius = 8.0
>>> num_rays = 100
>>> transform = dit.transforms.Identity()
>>> light_source = dit.source.CollimatedMonochromatic(transform, radius, wave_len)
>>> x, weights = light_source.sample(num_rays, "sobol")
>>> O, D, wls, _, meta_data = light_source(x, n_func_enviroment=dit.materials["AIR"])

In the following, we introduce two types of light source models along with their corresponding light source domains and local ray initialization functions.

1. Collimated Monochromatic Light Source For this light source model, rays originate from a planar aperture with a uniform direction and a single wavelength. An example for light sources which can be modeled as collimated monochromatic light sources are lasers (see [Dic18]).

  • The light source domain \(\Omega_{CO} \subseteq \mathbb{R}^2\) can take various shapes.

  • The local ray initialization function is, given a single wavelength \(\lambda\), always in the form of:

    \[\begin{split}\hat{f}(x, \lambda)_{CO} = \begin{bmatrix} x_1 \\ x_2 \\ 0 \\ 0 \\ 0 \\ 1 \\ \lambda \end{bmatrix}.\end{split}\]
  • The flux function must align with the light source domain \(\Omega_{CO}\).

Examples of light source domains for collimated monochromatic light sources include:

  • Round Domains

    Defined by:

    \[\Omega^{round(\hat{r})}_{CO} = \left\{x : ||x||_2 \leq \hat{r}\right\} \subseteq \mathbb{R}^2,\]

    where \(\hat{r}\) is the radius.

    Example:
    >>> import diffinytrace as dit
    >>> wl = 0.5
    >>> r = 8.0
    >>> transform = dit.transforms.Identity()
    >>> light_source = dit.source.CollimatedMonochromatic(transform, r, wl)
    
  • Square Domains

    Defined by:

    \[\Omega^{square(\hat{d})}_{CO} = \left\{x : ||x||_\infty \leq \hat{d}\right\} \subseteq \mathbb{R}^2,\]

    where \(\hat{d}\) is the half diameter.

2. Monochromatic Light Sources with Etendue Real-world physical light sources are characterized by a finite area-angle product, corresponding to a finite etendue (see [RRHT17]). In this model, rays originate from a planar surface with a specific wavelength, but the directions differ.

  • The light source domain \(\Omega_{ET} \subseteq \mathbb{R}^4\) has four dimensions.

  • The flux function maps a 4-dimensional vector to a single value.

  • The local ray initialization function maps a 4-dimensional vector to a 7-dimensional vector.

Example: Pillbox Sunlight Model The sun has an etendue, meaning both an angular and spatial extent. The sunshape describes how solar radiation is distributed across the solar disk, represented by the normalized radiance profile \(\hat{L}(\theta)\):

\[\begin{split}\hat{L}_{\text{pillbox}}(\theta) = \begin{cases} L_1 & \text{if } 0 \leq \theta \leq \theta_{disc}, \\ 0 & \text{if } \theta > \theta_{disc}. \end{cases}\end{split}\]

Here, \(\theta\) is the angular displacement of a ray compared to the general direction of the sun. Typically, \(\theta_{disc} = 4.65 \, \text{mrad}\) is used (see [WPA+20]).

The light source domain for the pillbox sunlight model is defined as:

\[\Omega^{pillbox(\hat{d})}_{ET} := \left\{x : ||[x_1, x_2]^T||_\infty \leq \hat{d}, ||[x_3, x_4]^T||_\infty \leq 1\right\} \subseteq \mathbb{R}^4,\]

where \(\hat{d}\) is the half diameter.

The local ray initialization function is:

\[\begin{split}\hat{f}(x)_{ET}^{pillbox} := \begin{bmatrix} x_1 \\ x_2 \\ 0 \\ \sin(\theta(x_3))\cos(\phi(x_4)) \\ \sin(\theta(x_3))\sin(\phi(x_4)) \\ \cos(\theta(x_3)) \\ \lambda \end{bmatrix},\end{split}\]

where:

\[\theta(x_3) := -\theta_{disc} + 2\theta_{disc}x_3, \quad \phi(x_4) := 2\pi x_4.\]

The flux function is:

\[Q_{ET}(x)_{pillbox} := \frac{1 \, \text{W}}{|\Omega^{pillbox(\hat{d})}_{ET}|}.\]
sample(num_points, method)[source]

Samples points in the parameter space of the ray source. :param num_points: The number of points to sample. :type num_points: int :param method: The sampling method to use. Can be “sobol”, “monte_carlo”, etc. :type method: str

Returns:

A tuple containing the sampled points and their weights.

Return type:

tuple

get_flux(x)[source]
get_volume()[source]
class diffinytrace.source.PlaneSource(transform, aperture_radius, integrator, is_square=False, flux_func=None, total_power=1.0, num_points_normalize=700000, method_normalize='sobol')[source]

Bases: LightSource

get_plot_points_2D(resolution)[source]

Returns a list of 2D plot points for the object.

Parameters:

resolution (int) – The resolution for the plot points.

Returns:

A list of 2D plot points.

Return type:

list

get_plot_points_3D(resolution)[source]

Returns a list of 3D plot points for the object.

Parameters:

resolution (int) – The resolution for the plot points.

Returns:

A list of 3D plot points.

Return type:

list

class diffinytrace.source.PlaneSource1D(transform, aperture_radius, integrator, flux_func, total_power=1.0, num_points_normalize=700000, method_normalize='sobol')[source]

Bases: LightSource

get_plot_points_2D(resolution)[source]

Returns a list of 2D plot points for the object.

Parameters:

resolution (int) – The resolution for the plot points.

Returns:

A list of 2D plot points.

Return type:

list

get_plot_points_3D(resolution)[source]

Returns a list of 3D plot points for the object.

Parameters:

resolution (int) – The resolution for the plot points.

Returns:

A list of 3D plot points.

Return type:

list

diffinytrace.source.make_cone_directions(num_rays, unif1, unif2, theta_max_rad)[source]

Sample directions uniformly within a cone of angular radius theta_max_rad centered on the z-axis.

Parameters: - num_rays (int): Number of direction vectors to sample within the cone. - unif1 (torch.Tensor): Tensor of uniform samples for cos(theta) sampling. - unif2 (torch.Tensor): Tensor of uniform samples for the azimuthal angle sampling. - theta_max_rad (float): Angular radius of the cone in radians.

Returns: - directions (torch.Tensor): Tensor of shape (num_rays, 3), with each row a direction vector.

class diffinytrace.source.VisibleSunlightSimpleMonochromatic(transform, aperture_radius, wl=0.5, is_square=True, total_power=1.0, theta_max_rad=0.0046500000000000005)[source]

Bases: PlaneSource

A class representing a visible sunlight source with a monochromatic spectrum. It also has a cone of 4.65 mrad.

sample(num_points, method='monte_carlo')[source]

Samples points in the parameter space of the ray source. :param num_points: The number of points to sample. :type num_points: int :param method: The sampling method to use. Can be “sobol”, “monte_carlo”, etc. :type method: str

Returns:

A tuple containing the sampled points and their weights.

Return type:

tuple

forward(x, n_func_enviroment)[source]

Define the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

class diffinytrace.source.VisibleSunlightSimple(transform, aperture_radius, is_square=True, total_power=1.0)[source]

Bases: PlaneSource

A class representing a visible sunlight source with a spectrum acording to the visble sunlight. It also has a an etendue with cone of 4.65 mrad.

sample(num_points, method='monte_carlo')[source]

Samples points in the parameter space of the ray source. :param num_points: The number of points to sample. :type num_points: int :param method: The sampling method to use. Can be “sobol”, “monte_carlo”, etc. :type method: str

Returns:

A tuple containing the sampled points and their weights.

Return type:

tuple

forward(x, n_func_enviroment)[source]

Define the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

class diffinytrace.source.CollimatedMonochromatic(transform, aperture_radius, wl, is_square=False, flux_func=None, total_power=1.0)[source]

Bases: PlaneSource

A class representing a collimated monochromatic light source. This class is a subclass of PlaneSource and is used to generate rays with a specific wavelength and a collimated beam profile.

sample(num_points, method='monte_carlo') Tensor[source]

Samples points in the parameter space of the ray source. :param num_points: The number of points to sample. :type num_points: int :param method: The sampling method to use. Can be “sobol”, “monte_carlo”, etc. :type method: str

Returns:

A tuple containing the sampled points and their weights.

Return type:

tuple

forward(x, n_func_enviroment)[source]

Define the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

class diffinytrace.source.CollimatedGaussianBeam(transform, aperture_radius, wl, gaussian_constant, total_power=1.0)[source]

Bases: CollimatedMonochromatic

class diffinytrace.source.CollimatedMonochromatic1D(transform, aperture_radius, wl, flux_func=None, total_power=1.0)[source]

Bases: PlaneSource1D

A class representing a collimated monochromatic light source. This class is a subclass of PlaneSource1D and is used to generate rays with a specific wavelength and a collimated beam profile.

sample(num_points, method='monte_carlo')[source]

Samples points in the parameter space of the ray source. :param num_points: The number of points to sample. :type num_points: int :param method: The sampling method to use. Can be “sobol”, “monte_carlo”, etc. :type method: str

Returns:

A tuple containing the sampled points and their weights.

Return type:

tuple

forward(x, n_func_enviroment)[source]

Define the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

class diffinytrace.source.CollimatedMonochromatic1DRotSym(transform, aperture_radius, wl, flux_func=None, total_power=1.0)[source]

Bases: PlaneSource1D

A class representing a collimated monochromatic light source. This class is a subclass of PlaneSource1D and is used to generate rays with a specific wavelength and a collimated beam profile.

sample(num_points, method='monte_carlo')[source]

Samples points in the parameter space of the ray source. :param num_points: The number of points to sample. :type num_points: int :param method: The sampling method to use. Can be “sobol”, “monte_carlo”, etc. :type method: str

Returns:

A tuple containing the sampled points and their weights.

Return type:

tuple

forward(x, n_func_enviroment)[source]

Define the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.