Optical Systems

Assemblies

All systems are made up of a LensAssembly which contains all the optical components in the system, excluding any sources (see Emitters) and the detector (see below).

OpticSim.LensAssemblyType
LensAssembly{T<:Real}

Structure which contains the elements of the optical system, these can be CSGTree or Surface objects.

In order to prevent type ambiguities bespoke structs are created for each possible number of elements e.g. LensAssembly3. These are parameterized by the types of the elements to prevent ambiguities. Basic surface types such as Rectangle (which can occur in large numbers) are stored independently in Vectors, so type paramters are only needed for CSG objects.

Each struct looks like this:

struct LensAssemblyN{T,T1,T2,...,TN} <: LensAssembly{T}
axis::SVector{3,T}
rectangles::Vector{Rectangle{T}}
ellipses::Vector{Ellipse{T}}
hexagons::Vector{Hexagon{T}}
paraxials::Vector{ParaxialLens{T}}
E1::T1
E2::T2
...
EN::TN
end

Where Ti <: Union{Surface{T},CSGTree{T}}.

To create a LensAssembly object the following functions can be used:

LensAssembly(elements::Vararg{Union{Surface{T},CSGTree{T},LensAssembly{T}}}; axis = SVector(0.0, 0.0, 1.0)) where {T<:Real}
source

Images

The detector image is stored within the system as a HierarchicalImage for memory efficiency.

OpticSim.HierarchicalImageType
HierarchicalImage{T<:Number} <: AbstractArray{T,2}

Image type which dynamically allocated memory for pixels when their value is set, the value of unset pixels is assumed to be zero.

This is used for the detector image of AbstractOpticalSystems which can typically be very high resolution, but often have a large proportion of the image blank.

source
OpticSim.reset!Function
reset!(a::HierarchicalImage{T})

Resets the pixels in the image to zero(T). Do this rather than image .= zero(T) because that will cause every pixel to be accessed, and therefore allocated. For large images this can cause huge memory traffic.

source
OpticSim.sum!Function
sum!(a::HierarchicalImage{T}, b::HierarchicalImage{T})

Add the contents of b to a in an efficient way.

source

Systems

There are two types of AbstractOpticalSystem which can be used depending on the requirements.

OpticSim.CSGOpticalSystemType
CSGOpticalSystem{T,D<:Real,S<:Surface{T},L<:LensAssembly{T}} <: AbstractOpticalSystem{T}

An optical system containing a lens assembly with all optical elements and a detector surface with associated image. The system can be at a specified temperature and pressure.

There are two number types in the type signature. The T type parameter is the numeric type for geometry in the optical system, the D type parameter is the numeric type of the pixels in the detector image. This way you can have Float64 geometry, where high precision is essential, but the pixels in the detector can be Float32 since precision is much less critical for image data, or Complex if doing wave optic simulations.

The detector can be any Surface which implements uv, uvtopix and onsurface, typically this is one of Rectangle, Ellipse or SphericalCap.

CSGOpticalSystem(
assembly::LensAssembly,
detector::Surface,
detectorpixelsx = 1000,
detectorpixelsy = 1000, ::Type{D} = Float32;
temperature = OpticSim.GlassCat.TEMP_REF,
pressure = OpticSim.GlassCat.PRESSURE_REF
)
source
OpticSim.AxisymmetricOpticalSystemType
AxisymmetricOpticalSystem{T,C<:CSGOpticalSystem{T}} <: AbstractOpticalSystem{T}

Optical system which has lens elements and an image detector, created from a DataFrame containing prescription data.

These tags are supported for columns: :Radius, :SemiDiameter, :SurfaceType, :Thickness, :Conic, :Parameters, :Reflectance, :Material.

These tags are supported for entries in a SurfaceType column: Object, Image, Stop. Assumes the Image row will be the last row in the DataFrame.

In practice a CSGOpticalSystem is generated automatically and stored within this system.

AxisymmetricOpticalSystem{T}(
prescription::DataFrame,
detectorpixelsx = 1000,
detectorpixelsy:: = 1000,
::Type{D} = Float32;
temperature = OpticSim.GlassCat.TEMP_REF,
pressure = OpticSim.GlassCat.PRESSURE_REF
)
source
OpticSim.detectorimageFunction
detectorimage(system::AbstractOpticalSystem{T}) -> HierarchicalImage{D}

Get the detector image of system. D is the datatype of the detector image and is not necessarily the same as the datatype of the system T.

source
OpticSim.semidiameterFunction
semidiameter(system::AxisymmetricOpticalSystem{T}) -> T

Get the semidiameter of system, that is the semidiameter of the entrance pupil (i.e. first surface) of the system.

source

Tracing

We can trace an individual OpticalRay through the system (or directly through a LensAssembly), or we can trace using an OpticalRayGenerator to create a large number of rays.

OpticSim.traceFunction
trace(assembly::LensAssembly{T}, r::OpticalRay{T}, temperature::T = 20.0, pressure::T = 1.0; trackrays = nothing, test = false)

Returns the ray as it exits the assembly in the form of a LensTrace object if it hits any element in the assembly, otherwise nothing. Recursive rays are offset by a small amount (RAY_OFFSET) to prevent it from immediately reintersecting the same lens element.

trackrays can be passed an empty vector to accumulate the LensTrace objects at each intersection of ray with a surface in the assembly.

source
trace(system::AbstractOpticalSystem{T}, ray::OpticalRay{T}; trackrays = nothing, test = false)

Traces system with ray, if test is enabled then fresnel reflections are disabled and the power distribution will not be correct. Returns either a LensTrace if the ray hits the detector or nothing otherwise.

trackrays can be passed an empty vector to accumulate the LensTrace objects at each intersection of ray with a surface in the system.

source
trace(system::AbstractOpticalSystem{T}, raygenerator::OpticalRayGenerator{T}; printprog = true, test = false)

Traces system with rays generated by raygenerator on a single thread. Optionally the progress can be printed to the REPL. If test is enabled then fresnel reflections are disabled and the power distribution will not be correct. If outpath is specified then the result will be saved to this path.

Returns the detector image of the system.

source
OpticSim.traceMTFunction
traceMT(system::AbstractOpticalSystem{T}, raygenerator::OpticalRayGenerator{T}; printprog = true, test = false)

Traces system with rays generated by raygenerator using as many threads as possible. Optionally the progress can be printed to the REPL. If test is enabled then fresnel reflections are disabled and the power distribution will not be correct. If outpath is specified then the result will be saved to this path.

Returns the accumulated detector image from all threads.

source
OpticSim.tracehitsFunction
tracehits(system::AbstractOpticalSystem{T}, raygenerator::OpticalRayGenerator{T}; printprog = true, test = false)

Traces system with rays generated by raygenerator on a single thread. Optionally the progress can be printed to the REPL. If test is enabled then fresnel reflections are disabled and the power distribution will not be correct.

Returns a list of LensTraces which hit the detector.

source
OpticSim.tracehitsMTFunction
tracehitsMT(system::AbstractOpticalSystem{T}, raygenerator::OpticalRayGenerator{T}; printprog = true, test = false)

Traces system with rays generated by raygenerator using as many threads as possible. Optionally the progress can be printed to the REPL. If test is enabled then fresnel reflections are disabled and the power distribution will not be correct.

Returns a list of LensTraces which hit the detector, accumulated from all threads.

source
OpticSim.LensTraceType
LensTrace{T<:Real,N}

Contains an intersection point and the ray segment leading to it from within an optical trace. The ray carries the path length, power, wavelength, number of intersections and source number, all of which are accessible directly on this class too.

Has the following accessor methods:

ray(a::LensTrace{T,N}) -> OpticalRay{T,N}
intersection(a::LensTrace{T,N}) -> Intersection{T,N}
power(a::LensTrace{T,N}) -> T
wavelength(a::LensTrace{T,N}) -> T
pathlength(a::LensTrace{T,N}) -> T
point(a::LensTrace{T,N}) -> SVector{N,T}
uv(a::LensTrace{T,N}) -> SVector{2,T}
sourcenum(a::LensTrace{T,N}) -> Int
nhits(a::LensTrace{T,N}) -> Int
source