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.LensAssembly — TypeLensAssembly{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
endWhere 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}Images
The detector image is stored within the system as a HierarchicalImage for memory efficiency.
OpticSim.HierarchicalImage — TypeHierarchicalImage{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.
OpticSim.reset! — Functionreset!(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.
OpticSim.sum! — Functionsum!(a::HierarchicalImage{T}, b::HierarchicalImage{T})Add the contents of b to a in an efficient way.
Systems
There are two types of AbstractOpticalSystem which can be used depending on the requirements.
OpticSim.AbstractOpticalSystem — TypeAbstractOpticalSystem{T<:Real}Abstract type for any optical system, must parameterized by the datatype of entities within the system T.
OpticSim.CSGOpticalSystem — TypeCSGOpticalSystem{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
)OpticSim.AxisymmetricOpticalSystem — TypeAxisymmetricOpticalSystem{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
)OpticSim.temperature — Functiontemperature(system::AbstractOpticalSystem{T}) -> TGet the temperature of system in °C.
OpticSim.pressure — Functionpressure(system::AbstractOpticalSystem{T}) -> TGet the pressure of system in Atm.
OpticSim.detectorimage — Functiondetectorimage(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.
OpticSim.resetdetector! — Functionresetdetector!(system::AbstractOpticalSystem{T})Reset the deterctor image of system to zero.
OpticSim.assembly — Functionassembly(system::AbstractOpticalSystem{T}) -> LensAssembly{T}Get the LensAssembly of system.
OpticSim.semidiameter — Functionsemidiameter(system::AxisymmetricOpticalSystem{T}) -> TGet the semidiameter of system, that is the semidiameter of the entrance pupil (i.e. first surface) of the system.
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.trace — Functiontrace(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.
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.
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.
OpticSim.traceMT — FunctiontraceMT(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.
OpticSim.tracehits — Functiontracehits(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.
OpticSim.tracehitsMT — FunctiontracehitsMT(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.
OpticSim.LensTrace — TypeLensTrace{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