Skip to content
This repository has been archived by the owner on Oct 23, 2022. It is now read-only.

Commit

Permalink
BrianGun/issue367 (#374)
Browse files Browse the repository at this point in the history
* Change code so eyebox subdivision can be passed as a parameter rather than computed by choosecluster
Fixes #367

removed redundant arguments from pixel_redundancy. Also removed call to choose_cluster in pixel_redundancy.

* removed call to lensletsangles in pixelredundancy.

removed default clusterproperties argument assignment from lensletangles

* Change code so eyebox subdivision can be passed as a parameter rather than computed by choosecluster
Fixes #367
  • Loading branch information
BrianGun authored Feb 25, 2022
1 parent 57f4e23 commit b5c2bf1
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 36 deletions.
53 changes: 22 additions & 31 deletions src/RepeatingStructures/Multilens/Analysis.jl
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ const ρ_quartervalue = 2.21509 # value of ρ at which the airy disk function ha
export ρ_quartervalue
const ρ_zerovalue = 3.832 # value of ρ at which the airy disk function has magnitude 0

"""given pixelpitch and angular subtense (in degrees) of pixel returns focal length"""
"""compute focal length given maximum display size, fov, etc."""
function compute_focal_length(fov,lensletdiameter, minfnumber, maxdisplaysize)
maxangle = deg2rad(max(fov...)) #leaving angles as degrees caused trouble for not obvious reason

Expand All @@ -50,6 +50,15 @@ function compute_focal_length(fov,lensletdiameter, minfnumber, maxdisplaysize)
end
export compute_focal_length


"""compute focal length required for a given pixel pitch and angular size of the pixel"""
compute_focal_length(pixel_pitch::Unitful.Length,pixel_angle) = .5*pixel_pitch/tan(.5*pixel_angle)

"""minimum lenslet diameter given `ppd`, `fov`, and `pixel_pitch` assuming a Bayer pattern 2x2 pixel. `pixel_pitch` is the distance between individual pixels. The pitch for the Bayer pattern is 2*`pixel_pitch``."""
minimum_lenslet_diameter(ppd,fov::Tuple{T,T},pixel_pitch::Unitful.Length) where{T} = norm(ppd .* fov .* 2 .* pixel_pitch)
export minimum_lenslet_diameter


pixelsperdegree(focal_length,pixelpitch) = 1/(2.0*atand(uconvert(Unitful.NoUnits,pixelpitch/(2.0*focal_length))))
export pixelsperdegree

Expand Down Expand Up @@ -194,38 +203,16 @@ function anglesubdivisions(pupildiameter::Unitful.Length, λ::Unitful.Length, mt
end
export anglesubdivisions


"""Computes the approximate fov required of each lenslet for the given constraints. This is strictly correct only for a lenslet centered in front of the eyebox, but the approximation is good enough for high level analysis"""
function lensletangles(eyerelief::Unitful.Length, eyebox::NTuple{2,Unitful.Length}, pupildiameter::Unitful.Length; clusterproperties=defaultclusterproperties(), RGB=true)
return eyeboxangles(eyebox, eyerelief) ./ anglesubdivisions(pupildiameter, clusterproperties.λ, clusterproperties.mtf, clusterproperties.cyclesperdegree, RGB=RGB)
end
export lensletangles


"""Multilens displays tradeoff pixel redundancy for a reduction in total track of the display, by using many short focal length lenses to cover the eyebox. This function computes the ratio of pixels in the multilens display vs. a conventional display of the same nominal resolution"""
function pixelredundancy(fov, eyerelief::Unitful.Length, eyebox::NTuple{2,Unitful.Length}, pupildiameter::Unitful.Length, ppd; RGB=true)
lensprops = defaultclusterproperties()
clusterdata = choosecluster(pupildiameter, lensprops.λ, lensprops.mtf, lensprops.cyclesperdegree)
nominalresolution = ustrip.(°, fov) .* ppd #remove degree units so pixel redundancy doesn't have units of °^-2
angles = lensletangles(eyerelief, eyebox, pupildiameter, RGB=RGB)
pixelsperlenslet = angles .* ppd
numlenses = numberoflenslets(fov, eyerelief, clusterdata.lensletdiameter)
return (numlenses * pixelsperlenslet[1] * pixelsperlenslet[2]) / ( nominalresolution[1] * nominalresolution[2])
function pixelredundancy(fov, eyerelief::Unitful.Length, eyebox::NTuple{2,Unitful.Length}, pupildiameter::Unitful.Length, lensletdiameter,angles; RGB=true)
nominalresolution = ustrip.(°, fov) #remove degree units so pixel redundancy doesn't have units of °^-2
numlenses = numberoflenslets(fov, eyerelief, lensletdiameter)
return (numlenses * angles[1] * angles[2]) / ( nominalresolution[1] * nominalresolution[2])
end
export pixelredundancy

label(color) = color ? "RGB" : "Monochrome"

"""generates a contour plot showing pixel redundancy as a function of ppd and pupil diameter"""
function redundancy_ppdvspupildiameter()
x = 20:2:45
y = 3.0:.05:4

RGB = true
Plots.plot(Plots.contour(x, y, (x, y) -> pixelredundancy((50, 35), 18mm, (10mm, 6mm), y * mm, x, RGB=RGB), fill=true, xlabel="pixels per degree", ylabel="pupil diameter", legendtitle="pixel redundancy", title="$(label(RGB)) lenslets"))
end
export redundancy_ppdvspupildiameter

"""generates a contour plot of lenslet display size as a function of ppd and pupil diameter"""
function displaysize_ppdvspupildiameter()
x = 20:2:45
Expand Down Expand Up @@ -271,15 +258,19 @@ Dict{Symbol, Any} with 14 entries:
```
"""
function system_properties(eyerelief::Unitful.Length, eyebox::NTuple{2,Unitful.Length}, fov, pupildiameter::Unitful.Length, mtf, cyclesperdegree; minfnumber=2.0,RGB=true=530nm,pixelpitch=.9μm, maxdisplaysize = 250μm)::Dict{Symbol,Any}
function system_properties(eyerelief::Unitful.Length, eyebox::NTuple{2,Unitful.Length}, fov, pupildiameter::Unitful.Length, mtf, cyclesperdegree; minfnumber=2.0,RGB=true=530nm,pixelpitch=.9μm, maxdisplaysize = 250μm,eyebox_subdivisions::Union{Nothing,Tuple{Int,Int}} = nothing)::Dict{Symbol,Any}
diameter = diameter_for_cycles_deg(mtf, cyclesperdegree, λ)
clusterdata = choosecluster(pupildiameter, diameter)
difflimit = diffractionlimit(λ, clusterdata.lensletdiameter)
numlenses = numberoflenslets(fov, eyerelief, clusterdata.lensletdiameter)
redundancy = pixelredundancy(fov, eyerelief, eyebox, pupildiameter, difflimit, RGB=RGB)
subdivisions = anglesubdivisions(pupildiameter, λ, mtf, cyclesperdegree, RGB=RGB)
if eyebox_subdivisions === nothing
subdivisions = anglesubdivisions(pupildiameter, λ, mtf, cyclesperdegree, RGB=RGB)
else
subdivisions = eyebox_subdivisions
end
eyebox_angles = eyeboxangles(eyebox,eyerelief)
angles = lensletangles(eyerelief, eyebox, pupildiameter, clusterproperties=(mtf = mtf, minfnumber = minfnumber, cyclesperdegree = cyclesperdegree, λ = λ, pixelpitch = pixelpitch))
angles = eyebox_angles ./ subdivisions
redundancy = pixelredundancy(fov, eyerelief, eyebox, pupildiameter,clusterdata.lensletdiameter, angles, RGB=RGB)

focal_length = compute_focal_length(angles,clusterdata.lensletdiameter,minfnumber,maxdisplaysize)
dispsize = lensletdisplaysize(angles,focal_length)
Expand Down
6 changes: 3 additions & 3 deletions src/RepeatingStructures/Multilens/Example.jl
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ end
export test_paraxial_lens

"""Example that shows how to call setup_system with typical values"""
function setup_nominal_system()::LensletSystem
function setup_nominal_system(;eyebox_subdivisions = nothing)::LensletSystem
(;eye_relief,fov,eyebox,display_radius,pupil_diameter,minfnumber,pixel_pitch) = nominal_system_inputs()
setup_system(eyebox,fov,eye_relief,pupil_diameter,display_radius,minfnumber,pixel_pitch)
setup_system(eyebox,fov,eye_relief,pupil_diameter,display_radius,minfnumber,pixel_pitch,eyebox_subdivisions = eyebox_subdivisions)
end
export setup_nominal_system

Expand Down Expand Up @@ -227,7 +227,7 @@ end
export draw_system

"""draw subdivided eyeboxes to make sure they are in the right place"""
function draw_subdivided_eyeboxes(system = setup_nominal_system, clear_screen = true)
function draw_subdivided_eyeboxes(system = setup_nominal_system(), clear_screen = true)
(;subdivided_eyebox_polys) = system

colors = distinguishable_colors(length(subdivided_eyebox_polys))
Expand Down
4 changes: 2 additions & 2 deletions src/RepeatingStructures/Multilens/LensletAssignment.jl
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ If you do this
setup_system(eye_box,(1,1.2),...)
```
the system will assume the angle is in radians."""
function setup_system(eye_box,fov,eye_relief,pupil_diameter,display_sphere_radius,min_fnumber,pixel_pitch)
function setup_system(eye_box,fov,eye_relief,pupil_diameter,display_sphere_radius,min_fnumber,pixel_pitch;eyebox_subdivisions = nothing)
#All coordinates are ultimately transformed into the eyeball_frame coordinate systems
(eyeball_frame,eye_box_frame) = setup_coordinate_frames()

Expand All @@ -220,7 +220,7 @@ function setup_system(eye_box,fov,eye_relief,pupil_diameter,display_sphere_radiu
eyeboxz = (eye_box_frame*SVector(0.0,0.0,0.0))[3]
eyebox_plane = Plane([0.0,0.0,1.0],[0.0,0.0,eyeboxz])
#get system properties
props = system_properties(eye_relief,eye_box,fov,pupil_diameter,.2,11,pixelpitch = pixel_pitch, minfnumber = min_fnumber)
props = system_properties(eye_relief,eye_box,fov,pupil_diameter,.2,11,pixelpitch = pixel_pitch, minfnumber = min_fnumber,eyebox_subdivisions = eyebox_subdivisions)

subdivisions = props[:subdivisions] #tuple representing how the eyebox can be subdivided given the cluster used for the lenslets

Expand Down

0 comments on commit b5c2bf1

Please sign in to comment.