Source code for rayoptics.parax.etendue

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright © 2019 Michael J. Hayford
""" functions to calculate etendue and imager parameters

.. Created on Tue Aug  6 18:08:16 2019

.. codeauthor: Michael J. Hayford
"""
import math

from rayoptics.util import dict2d
from rayoptics.util.dict2d import dict2D


obj_img_set = ['object', 'image']
fld_ape_set = ['field', 'aperture']
fld_labels = ['height', 'angle']
ap_labels = ['pupil', 'NA', 'f/#']


[docs]def create_etendue_dict(): """Returns an empty dict2D(fld_ape_set, obj_img_set).""" return dict2D(fld_ape_set, obj_img_set)
[docs]def na2slp(na, n=1.0): """ convert numerical aperture to slope """ return n*math.tan(math.asin(na/n))
[docs]def slp2na(slp, n=1.0): """ convert a ray slope to numerical aperture """ return n*math.sin(math.atan(slp/n))
[docs]def ang2slp(ang): """ convert an angle in degrees to a slope """ return math.tan(math.radians(ang))
[docs]def slp2ang(slp): """ convert a slope to an angle in degrees """ return math.degrees(math.atan(slp))
[docs]def get_aperture_from_slope(imager, slope, n=1): if slope == 0: return 0, 0, 0 fno = -1/(2*slope) na = slp2na(slope, n=n) pupil = imager.f/fno if imager.f is not None else None return na, fno, pupil
[docs]def get_slope_from_aperture(imager, input_cell, n=1): if 'NA' in input_cell: na = input_cell['NA'] slope = na2slp(na, n=n) elif 'f/#' in input_cell: fno = input_cell['f/#'] slope = -1/(2*fno) elif 'pupil' in input_cell: pupil = input_cell['pupil'] if imager.f is None or imager.f == 0: slope = 0 else: slope = -pupil/(2*imager.f) else: slope = None return slope
[docs]def calc_aperture_from_input(conj_type, imager, input_cell, n=1): """ conj_type is for the io_input space""" slope = get_slope_from_aperture(imager, input_cell, n=n) if conj_type == 'finite': na, fno, pupil = get_aperture_from_slope(imager, slope, n=n) else: na, fno, pupil = 0, 0, input_cell['pupil'] return na, fno, pupil
[docs]def do_etendue_via_imager(conj_type, imager, etendue_inputs, etendue_grid, n_0=1, n_k=1): imager_inputs = {} li = dict2d.num_items_by_type(etendue_inputs, fld_ape_set, obj_img_set) if li['field'] == 1: row = dict2d.row(etendue_inputs, 'field') obj_img_key = 'object' if len(row['object']) else 'image' do_field_via_imager(conj_type, imager, etendue_inputs, obj_img_key, etendue_grid, n_0=n_0, n_k=n_k) if li['aperture'] == 1: row = dict2d.row(etendue_inputs, 'aperture') obj_img_key = 'object' if len(row['object']) else 'image' do_aperture_via_imager(conj_type, imager, etendue_inputs, obj_img_key, etendue_grid) if li['field'] == 2 or li['aperture'] == 2: fld_ape_key = 'field' if li['field'] == 2 else 'aperture' # solve for imager imager_inputs = do_etendue_to_imager(fld_ape_key, etendue_inputs, etendue_grid, n_0=n_0, n_k=n_k) return imager_inputs
[docs]def do_field_via_imager(conj_type, imager, etendue_inputs, obj_img_key, etendue_grid, n_0=1, n_k=1): input_cell = etendue_inputs['field'][obj_img_key] if obj_img_key == 'object': output_cell = etendue_grid['field']['image'] if 'angle' in input_cell: efl = imager.f obj_ang = input_cell['angle'] obj_slp = ang2slp(obj_ang) output_cell['height'] = efl*obj_slp elif 'height' in input_cell: m = imager.m obj_ht = input_cell['height'] output_cell['height'] = m*obj_ht elif obj_img_key == 'image': output_cell = etendue_grid['field']['object'] if imager.m == 0: # infinite conjugate efl = imager.f if 'height' in input_cell: img_ht = input_cell['height'] obj_slp = img_ht/efl obj_ang = slp2ang(obj_slp) output_cell['angle'] = obj_ang else: # finite conjugate m = imager.m if 'height' in input_cell: img_ht = input_cell['height'] output_cell['height'] = img_ht/m
[docs]def do_aperture_via_imager(conj_type, imager, etendue_inputs, obj_img_key, etendue_grid, n_0=1, n_k=1): inpt = etendue_inputs['aperture'][obj_img_key] input_cell = etendue_grid['aperture'][obj_img_key] if conj_type == 'infinite': efl = imager.f if obj_img_key == 'object': epd = inpt['pupil'] slpk = (epd/2.0)/efl na, fno, pupil = get_aperture_from_slope(imager, slpk, n=n_k) output_cell = etendue_grid['aperture']['image'] output_cell['f/#'] = fno output_cell['NA'] = na output_cell['pupil'] = pupil elif obj_img_key == 'image': slpk = get_slope_from_aperture(imager, inpt, n=n_k) na, fno, pupil = get_aperture_from_slope(imager, slpk, n=n_k) input_cell['f/#'] = fno input_cell['NA'] = na input_cell['pupil'] = pupil epd = 2*slpk*efl output_cell = etendue_grid['aperture']['object'] output_cell['pupil'] = epd else: mag = imager.m if obj_img_key == 'object': slp0 = get_slope_from_aperture(imager, inpt, n=n_0) na, fno, pupil = get_aperture_from_slope(imager, slp0, n=n_0) input_cell['f/#'] = fno input_cell['NA'] = na input_cell['pupil'] = pupil slpk = slp0/mag na, fno, pupil = get_aperture_from_slope(imager, slpk, n=n_k) output_cell = etendue_grid['aperture']['image'] elif obj_img_key == 'image': slpk = get_slope_from_aperture(imager, inpt, n=n_k) na, fno, pupil = get_aperture_from_slope(imager, slpk, n=n_k) input_cell['f/#'] = fno input_cell['NA'] = na input_cell['pupil'] = pupil slp0 = mag*slpk na, fno, pupil = get_aperture_from_slope(imager, slp0, n=n_0) output_cell = etendue_grid['aperture']['object'] output_cell['f/#'] = fno output_cell['NA'] = na output_cell['pupil'] = pupil
[docs]def do_etendue_to_imager(fld_ape_key, etendue_inputs, etendue_grid, n_0=1.0, n_k=1.0): imager_inputs = None if fld_ape_key == 'field': obj_cell = etendue_inputs['field']['object'] img_cell = etendue_inputs['field']['image'] obj_grid = etendue_grid['field']['object'] img_grid = etendue_grid['field']['image'] obj_key = obj_cell.keys() img_key = img_cell.keys() if 'angle' in obj_key: obj_ang = obj_cell['angle'] obj_slp = ang2slp(obj_ang) if 'height' in img_key: img_ht = img_cell['height'] img_grid['height'] = img_ht efl = img_ht/obj_slp imager_inputs = 'f', efl else: return None elif 'height' in obj_key: obj_ht = obj_cell['height'] if 'height' in img_key: img_ht = img_cell['height'] img_grid['height'] = img_ht mag = img_ht/obj_ht imager_inputs = 'm', mag if fld_ape_key == 'aperture': obj_cell = etendue_inputs['aperture']['object'] img_cell = etendue_inputs['aperture']['image'] obj_grid = etendue_grid['aperture']['object'] img_grid = etendue_grid['aperture']['image'] obj_key = obj_cell.keys() img_key = img_cell.keys() if 'pupil' in obj_key: epd = obj_cell['pupil'] if 'f/#' in img_key: fno = img_cell['f/#'] img_grid['f/#'] = fno efl = epd * fno imager_inputs = 'f', efl if 'NA' in img_key: na = img_cell['NA'] img_grid['NA'] = na slpk = na2slp(na, n=n_k) efl = (epd/2.0)/slpk imager_inputs = 'f', efl else: if 'NA' in obj_key: nao = obj_cell['NA'] obj_grid['NA'] = nao slp0 = na2slp(nao, n=n_0) elif 'f/#' in obj_key: fno = obj_cell['f/#'] obj_grid['f/#'] = fno slp0 = -1/(2*fno) if 'NA' in img_key: na = img_cell['NA'] img_grid['NA'] = na slpk = na2slp(na, n=n_k) elif 'f/#' in img_key: fno = img_cell['f/#'] img_grid['f/#'] = fno slpk = -1/(2*fno) mag = slp0/slpk imager_inputs = 'm', mag return imager_inputs
[docs]def fill_in_etendue_data(conj_type, imager, fld_ape_key, inputs, values, n=1.0): if len(inputs) == 0: return if fld_ape_key == 'field': for key in inputs: values[key] = inputs[key] if fld_ape_key == 'aperture': na, fno, pupil = calc_aperture_from_input(conj_type, imager, inputs, n=n) values['NA'] = na values['f/#'] = fno values['pupil'] = pupil