Source code for rayoptics.optical.obench

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""Import files from `OpticalBenchHub` web page

    This module implements lens import from the `OpticalBenchHub <https://www.photonstophotos.net/GeneralTopics/Lenses/OpticalBench/OpticalBenchHub.htm>`_
    portion of Bill Claff's `PhotonsToPhotos <https://www.photonstophotos.net/>`_
    website.

    To import a file from the website, navigate to the lens you wish to import 
    and select the entire web address of the page. Paste this into the url
    argument of the :func:`~.read_obench_url` function.

.. Created on Sat Jul 24 21:34:49 2021

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

import rayoptics.parax.specsheet as ss
from rayoptics.optical.opticalmodel import OpticalModel
from rayoptics.elem.profiles import (EvenPolynomial, RadialPolynomial)
from rayoptics.oprops import doe
from rayoptics.oprops.doe import DiffractiveElement
from rayoptics.raytr.opticalspec import WvlSpec
from rayoptics.util.misc_math import isanumber

from opticalglass import util

_track_contents = None


[docs]def read_obench_url(url, **kwargs): ''' given a url to a OpticalBench file, return an OpticalModel and info. ''' global _track_contents url1 = url.replace('OpticalBench.htm#', '') url2 = url1.partition(',')[0] r = requests.get(url2, allow_redirects=True) apparent_encoding = r.apparent_encoding r.encoding = r.apparent_encoding inpt = r.text lines = inpt.splitlines() inpt = [l.split('\t') for l in lines] obench_dict = {} for line in inpt: if line[0][0] == '[': # process new section header, initialize input list key = line[0][1:-1] obench_dict[key] = [] else: # add input to the currect section's list of inputs obench_dict[key].append(line) opt_model = read_lens(obench_dict, **kwargs) _track_contents['obench db'] = obench_dict _track_contents['encoding'] = apparent_encoding return opt_model, _track_contents
[docs]def read_lens(inpts): global _track_contents def read_float(s): if s == 'Infinity': return float('inf') elif isanumber(s): return float(s) else: if s == 'undefined': return float('nan') elif s == 'AS': return 0. elif s == '': return 0. else: try: return float(read_float(var_dists[s][0])) except: return 0. _track_contents = util.Counter() constants_inpt = inpts['constants'] constants = {c_item[0]: c_item[1:] for c_item in constants_inpt} var_dists_inpt = inpts['variable distances'] var_dists = {var_dist[0]: var_dist[1:] for var_dist in var_dists_inpt} thi_obj = 0. if 'd0' in var_dists: thi_obj = read_float(var_dists['d0'][0]) if thi_obj == float('inf'): thi_obj = 1.0e10 conj_type = 'finite' if thi_obj > 1.0e8: conj_type = 'infinite' _track_contents['conj type'] = conj_type specsheet = ss.create_specsheet(conj_type) imager_inputs = dict(specsheet.imager_inputs) if conj_type == 'finite': imager_inputs['m'] = read_float(var_dists['Magnification'][0]) specsheet.frozen_imager_inputs = [False]*5 else: # conj_type == 'infinite' imager_inputs['s'] = -float('inf') efl = read_float(var_dists['Focal Length'][0]) if efl != 0: imager_inputs['f'] = efl specsheet.frozen_imager_inputs = [True, True, True, True, False] etendue_inputs = specsheet.etendue_inputs ape_key = ('aperture', 'image', 'f/#') ape_value = read_float(var_dists['F-Number'][0]) etendue_inputs[ape_key[0]][ape_key[1]][ape_key[2]] = ape_value fld_key = ('field', 'image', 'height') fld_value = read_float(var_dists['Image Height'][0])/2 etendue_inputs[fld_key[0]][fld_key[1]][fld_key[2]] = fld_value specsheet.generate_from_inputs(imager_inputs, etendue_inputs) opt_model = OpticalModel(do_init=True, radius_mode=True, specsheet=specsheet) sm = opt_model['sm'] sm.do_apertures = False sm.gaps[0].thi = thi_obj osp = opt_model['osp'] osp['fov'].is_relative = True osp['fov'].set_from_list([0., .707, 1.]) osp['wvls'] = WvlSpec(wlwts=[('F', .5), ('d', 1.), ('C', .5)], ref_wl=1) if 'lens data' in inpts: input_lines = inpts['lens data'] _track_contents['# surfs'] = len(input_lines) for line in input_lines: inpt = [] inpt.append(read_float(line[1])) # radius inpt.append(read_float(line[2])) # thi if line[3] == '': inpt.append('') inpt.append('') else: inpt.append(read_float(line[3])) # nd inpt.append(read_float(line[5])) # vd inpt.append(read_float(line[4])/2) # sd sm.add_surface(inpt) if line[1] == 'AS': sm.set_stop() if 'aspherical data' in inpts: if 'AsphericalOddCount' in constants: typ = 'AsphericalOddCount' elif 'AsphericalA2' in constants: typ = 'AsphericalA2' else: typ = 'Aspherical' input_lines = inpts['aspherical data'] _track_contents[typ] = len(input_lines) for line in input_lines: if typ == 'AsphericalOddCount': asp_coefs = [read_float(item) for item in line[3:]] asp_coefs = [0., 0.] + asp_coefs elif typ == 'AsphericalA2': asp_coefs = [read_float(item) for item in line[3:]] else: asp_coefs = [read_float(item) for item in line[2:]] asp_coefs[0] = 0. if typ == 'AsphericalOddCount': asp = RadialPolynomial(r=read_float(line[1]), cc=read_float(line[2]), coefs=asp_coefs) else: asp = EvenPolynomial(r=read_float(line[1]), cc=read_float(line[2]), coefs=asp_coefs) idx = int(line[0]) sm.ifcs[idx].profile = asp if 'diffractive data' in inpts: input_lines = inpts['diffractive data'] _track_contents['# doe'] = len(input_lines) for line in input_lines: coefs = [read_float(item) for item in line[3:]] dif_elem = DiffractiveElement(coefficients=coefs, ref_wl=read_float(line[1]), order=read_float(line[2]), phase_fct=doe.radial_phase_fct) idx = int(line[0]) sm.ifcs[idx].phase_element = dif_elem if 'descriptive data' in inpts: input_lines = inpts['descriptive data'] descripts = {input_line[0]: input_line[1:] for input_line in input_lines} if 'title' in descripts: opt_model['sys'].title = descripts['title'][0] opt_model.update_model() return opt_model