Source code for rayoptics.oprops.thinlens

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright © 2018 Michael J. Hayford
""" Module for thin lens interface type

.. Created on Wed May 16 14:05:38 2018

.. codeauthor: Michael J. Hayford
"""


import numpy as np
from rayoptics.seq.interface import Interface
from rayoptics.oprops.doe import HolographicElement


[docs]class ThinLens(Interface): def __init__(self, lbl='', power=0.0, ref_index=1.5, **kwargs): super().__init__(interact_mode='transmit', phase_element=HolographicElement(), **kwargs) self.label = lbl self.optical_power = power self.ref_index = ref_index self.bending = 0.0
[docs] def list_thinlens(self): if len(self.label) > 0: print(self.label) print("power: {:12.6g}".format(self.optical_power)) self.phase_element.list_hoe()
def __repr__(self): if len(self.label) > 0: return "{!s}(lbl={!r}, power={!r}, ref_index={!r})" \ .format(type(self).__name__, self.label, self.optical_power, self.ref_index) else: return "{!s}(power={!r}, ref_index={!r})" \ .format(type(self).__name__, self.optical_power, self.ref_index)
[docs] def listobj_str(self): o_str = f"{self.label}: " if self.label != "" else "" o_str += f"{self.interact_mode}\n" o_str += f"thinlens: power={self.optical_power}, ref_index={self.ref_index}\n" o_str += f"surface_od={self.surface_od()}\n" return o_str
[docs] def update(self): super().update()
[docs] def full_profile(self, sd, flat_id=None, dir=1, steps=6): prf = [] if len(sd) == 1: sd_lwr = -sd[0] sd_upr = sd[0] else: sd_lwr = sd[0] sd_upr = sd[1] prf.append([0, dir*sd_lwr]) prf.append([0, dir*sd_upr]) return prf
@property def profile_cv(self): return self._power @profile_cv.setter def profile_cv(self, cv): self._power = cv
[docs] def surface_od(self): return self.max_aperture
[docs] def set_max_aperture(self, max_ap): super().set_max_aperture(max_ap)
@property def optical_power(self): return self._power @optical_power.setter def optical_power(self, pwr): # print("optical_power {}: pwr={}, {} obj={}, {}".format(self.label, # self._power, pwr, self.phase_element.obj_pt[2], 1./pwr)) self._power = pwr try: self.phase_element.obj_pt[2] = 1./pwr except ZeroDivisionError: self.phase_element.obj_pt[2] = 1e+10 finally: self.phase_element.obj_virtual = True if pwr > 0. else False
[docs] def set_optical_power(self, pwr, n_before, n_after): self.delta_n = n_after - n_before self.optical_power = pwr
[docs] def apply_scale_factor(self, scale_factor): super().apply_scale_factor(scale_factor) self.optical_power = self.optical_power/scale_factor
[docs] def from_first_order(self, nu_before, nu_after, y): # nu_before used for reference point ref = -y/nu_before if nu_before != 0.0 else 1e+10 obj = -y/nu_after if nu_after != 0.0 else 1e+10 # pm = self.phase_element # print("from_first_order {}:\n pwr={}, {}\n ref={} ({}), {} ({})" # "\n obj={} ({}), {} ({})" # .format(self.label, # self._power, (nu_before - nu_after)/y, # pm.ref_pt[2], pm.ref_virtual, ref, ref > 0., # pm.obj_pt[2], pm.obj_virtual, obj, obj > 0.)) self.phase_element.ref_pt[2] = ref self.phase_element.ref_virtual = True if ref > 0. else False self.phase_element.obj_pt[2] = obj self.phase_element.obj_virtual = True if obj > 0. else False self._power = (nu_before - nu_after)/y
[docs] def normal(self, p): return np.array([0., 0., 1.])
[docs] def intersect(self, p0, d, **kwargs): s1 = -p0[2]/d[2] p = p0 + s1*d return s1, p
[docs] def phase(self, pt, d_in, normal, ifc_cntxt): return self.phase_element.phase(pt, d_in, normal, ifc_cntxt)