Skip to content

Commit

Permalink
Merge pull request #5 from HarrisonKramer/feat/robust_visualization
Browse files Browse the repository at this point in the history
Feat/robust visualization
  • Loading branch information
HarrisonKramer authored Oct 15, 2024
2 parents 0f1f27a + 8332b54 commit 3cb337a
Show file tree
Hide file tree
Showing 22 changed files with 1,370 additions and 550 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<summary>Table of Contents</summary>
<ol>
<li><a href="#introduction">Introduction</a></li>
<li><a href="#documentation">Documentation</a></li>
<li><a href="#installation">Installation</a></li>
<li><a href="#functionalities">Functionalities</a></li>
<li><a href="#learning-guide">Learning Guide</a></li>
Expand Down Expand Up @@ -41,6 +42,8 @@ lens.draw3D()
## Documentation
The full documentation for Optiland is hosted on [Read the Docs](https://optiland.readthedocs.io/).

Explore the [Example Gallery](https://optiland.readthedocs.io/en/latest/example_gallery.html) for a wide range of lens designs and analyses created with Optiland.


## Installation

Expand Down
36 changes: 30 additions & 6 deletions docs/examples/Tutorial_2b_Tilting_&_Decentering_Components.ipynb

Large diffs are not rendered by default.

45 changes: 45 additions & 0 deletions optiland/coordinate_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
Kramer Harrison, 2024
"""
import numpy as np
from scipy.spatial.transform import Rotation as R
from optiland.rays import RealRays


Expand Down Expand Up @@ -95,3 +97,46 @@ def position_in_gcs(self):
vector = RealRays(0, 0, 0, 0, 0, 1, 1, 1)
self.globalize(vector)
return vector.x, vector.y, vector.z

def get_rotation_matrix(self):
"""Get the rotation matrix of the coordinate system
Returns:
np.ndarray: The rotation matrix of the coordinate system.
"""
rotation = np.array([self.rx, self.ry, self.rz])
return R.from_euler('xyz', rotation).as_matrix()

def get_effective_transform(self):
"""Get the effective translation and rotation matrix of the CS
Returns:
tuple: The effective translation and rotation matrix
"""
translation = np.array([self.x, self.y, self.z])
if self.reference_cs is None:
# No reference coordinate system, return the local transform
return translation, self.get_rotation_matrix()

else:
# Get the effective transform of the reference coordinate system
ref_translation, ref_rot_mat = \
self.reference_cs.get_effective_transform()

# Combine translations
eff_translation = ref_translation + ref_rot_mat @ translation

# Combine rotations by multiplying the rotation matrices
eff_rot_mat = ref_rot_mat @ self.get_rotation_matrix()

return eff_translation, eff_rot_mat

def get_effective_rotation_euler(self):
"""Get the effective rotation in Euler angles
Returns:
np.ndarray: The effective rotation in Euler angles
"""
_, eff_rot_mat = self.get_effective_transform()
# Convert the effective rotation matrix back to Euler angles
return R.from_matrix(eff_rot_mat).as_euler('xyz')
1 change: 1 addition & 0 deletions optiland/geometries/chebyshev.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ def __init__(self, coordinate_system, radius, conic=0.0,
self.c = np.atleast_2d(coefficients)
self.norm_x = norm_x
self.norm_y = norm_y
self.is_symmetric = False

def sag(self, x=0, y=0):
"""
Expand Down
1 change: 1 addition & 0 deletions optiland/geometries/even_asphere.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ def __init__(self, coordinate_system, radius, conic=0.0,
tol=1e-10, max_iter=100, coefficients=[]):
super().__init__(coordinate_system, radius, conic, tol, max_iter)
self.c = coefficients
self.is_symmetric = True

def sag(self, x=0, y=0):
"""
Expand Down
1 change: 1 addition & 0 deletions optiland/geometries/plane.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class Plane(BaseGeometry):
def __init__(self, coordinate_system):
super().__init__(coordinate_system)
self.radius = np.inf
self.is_symmetric = True

def sag(self, x=0, y=0):
"""Calculate the surface sag of the plane geometry.
Expand Down
1 change: 1 addition & 0 deletions optiland/geometries/polynomial.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ def __init__(self, coordinate_system, radius, conic=0.0,
tol=1e-10, max_iter=100, coefficients=[]):
super().__init__(coordinate_system, radius, conic, tol, max_iter)
self.c = coefficients
self.is_symmetric = False

if len(self.c) == 0:
self.c = np.zeros((1, 1))
Expand Down
1 change: 1 addition & 0 deletions optiland/geometries/standard.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ def __init__(self, coordinate_system, radius, conic=0.0):
super().__init__(coordinate_system)
self.radius = radius
self.k = conic
self.is_symmetric = True

def sag(self, x=0, y=0):
"""Calculate the surface sag of the geometry at the given coordinates.
Expand Down
6 changes: 3 additions & 3 deletions optiland/optic.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from optiland.distribution import create_distribution
from optiland.geometries import Plane, StandardGeometry
from optiland.materials import IdealMaterial
from optiland.visualization import LensViewer, LensViewer3D, LensInfoViewer
from optiland.visualization import OpticViewer, OpticViewer3D, LensInfoViewer
from optiland.pickup import Pickup
from optiland.solves import SolveFactory

Expand Down Expand Up @@ -355,7 +355,7 @@ def draw(self, fields='all', wavelengths='primary', num_rays=3,
ylim (tuple, optional): The y-axis limits of the plot. Defaults to
None.
"""
viewer = LensViewer(self)
viewer = OpticViewer(self)
viewer.view(fields, wavelengths, num_rays, distribution='line_y',
figsize=figsize, xlim=xlim, ylim=ylim)

Expand All @@ -374,7 +374,7 @@ def draw3D(self, fields='all', wavelengths='primary', num_rays=2,
figsize (tuple, optional): The size of the figure. Defaults to
(1200, 800).
"""
viewer = LensViewer3D(self)
viewer = OpticViewer3D(self)
viewer.view(fields, wavelengths, num_rays,
distribution='hexapolar', figsize=figsize)

Expand Down
13 changes: 13 additions & 0 deletions optiland/surfaces/standard_surface.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,3 +234,16 @@ def _trace_real(self, rays: RealRays):
self._record(rays)

return rays

def is_rotationally_symmetric(self):
"""
Returns True if the surface is rotationally symmetric, False otherwise.
"""
if not self.geometry.is_symmetric:
return False

cs = self.geometry.cs
if cs.rx != 0 or cs.ry != 0 or cs.x != 0 or cs.y != 0:
return False

return True
3 changes: 2 additions & 1 deletion optiland/surfaces/surface_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,8 @@ def _configure_cs(self, index, thickness, **kwargs):
elif index == 1:
z = 0 # first surface, always at zero
else:
z = self._surface_group.positions[index-1] + self.last_thickness
z = float(self._surface_group.positions[index-1]) + \
self.last_thickness

return CoordinateSystem(x=dx, y=dy, z=z, rx=rx, ry=ry)

Expand Down
Loading

0 comments on commit 3cb337a

Please sign in to comment.