Source code for rayoptics.parax.idealimager

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright © 2019 Michael J. Hayford
""" module to setup an ideal imager

.. Created on Thu May 16 19:57:47 2019

.. codeauthor: Michael J. Hayford
"""

import math
from collections import namedtuple


ideal_imager_keys = ['m', 's', 'sp', 'tt', 'f']
ideal_imager_labels = ["m", "s", "s'", "tt", "f"]
IdealImager = namedtuple('IdealImager', ideal_imager_keys)
IdealImager.m.__doc__ = "(lateral) magnification"
IdealImager.s.__doc__ = "object distance from first principal plane, P1->Obj"
IdealImager.sp.__doc__ = "image distance from second principal plane, P2->Img"
IdealImager.tt.__doc__ = "total track length, tt = sp - s"
IdealImager.f.__doc__ = "focal length"

""" tuple grouping together first order specifications

    Attributes:
        m: (lateral) magnification
        s: object distance from first principal plane, P1->Obj
        sp: image distance from second principal plane, P2->Img
        tt: total track length, tt = sp - s
        f: focal length
"""


[docs]def ideal_imager_setup(**inputs): """ Calculate the ideal imaging properties given two independent parameters Given 2 system parameters from the following list, this function calculates the remaining parameters. Note that if specifying ``tt`` and ``f``, their ratio, tt/f, must be greater than or equal to 4. A `ValueError` is raised otherwise. For a typical system, the value of ``s`` is negative, i.e. the object is to the left of the first principal plane. Example:: In [3]: m1s1 = ideal_imager_setup(m=-0.5, s=-10.0); m1s1 Out[3]: IdealImager(m=-0.5, s=-10.0, sp=5.0, tt=15.0, f=3.333333333333) In [4]: s_inf_efl = ideal_imager_setup(s=-math.inf, f=25.0); s_inf_efl Out[4]: IdealImager(m=-0.0, s=-inf, sp=25.0, tt=inf, f=25.0) Args: m: (lateral) magnification s: object distance from first principal plane, P1->Obj sp: image distance from second principal plane, P2->Img tt: total track length, tt = sp - s f: focal length Returns: :class:`IdealImager` namedtuple Raises: ValueError: if tt/f < 4 """ if 'm' in inputs: m = inputs['m'] if 's' in inputs: s = inputs['s'] sp = m*s tt = sp - s f = s*sp/(s - sp) elif 'sp' in inputs: sp = inputs['sp'] s = sp/m tt = sp - s f = s*sp/(s - sp) elif 'tt' in inputs: tt = inputs['tt'] s = tt/(m - 1) sp = m*s f = s*sp/(s - sp) elif 'f' in inputs: f = inputs['f'] tt = -f*(m - 1)**2/m s = -f*(m - 1)/m # = tt/(m - 1) sp = m*s else: return IdealImager(m, None, None, None, None) elif 's' in inputs: # arrange calculations so that s=-inf is handled gracefully s = inputs['s'] if 'sp' in inputs: sp = inputs['sp'] f = 1/(1/sp - 1/s) m = sp/s tt = sp - s elif 'tt' in inputs: tt = inputs['tt'] m = 1 + tt/s sp = m*s f = s*sp/(s - sp) elif 'f' in inputs: f = inputs['f'] m = f/(s + f) sp = 1/(1/f + 1/s) tt = sp - s else: return IdealImager(None, s, None, None, None) elif 'sp' in inputs: # arrange calculations so that sp=inf is handled gracefully sp = inputs['sp'] if 'tt' in inputs: tt = inputs['tt'] m = sp/(sp - tt) s = sp/m f = s*sp/(s - sp) elif 'f' in inputs: f = inputs['f'] m = (f - sp)/f s = 1/(1/sp - 1/f) tt = sp - s else: return IdealImager(None, None, sp, None, None) elif 'tt' in inputs: tt = inputs['tt'] if 'f' in inputs: f = inputs['f'] ttf = tt/f # tt/f >= 4, else no solution # pick root (+) that gives |s|>=|sp|, i.e. -1 <= m < 0 m = ((2 - ttf) + math.sqrt(ttf*(ttf - 4)))/2 s = tt/(m - 1) sp = m*s else: return IdealImager(None, None, None, tt, None) elif 'f' in inputs: f = inputs['f'] return IdealImager(None, None, None, None, f) else: return IdealImager(None, None, None, None, None) return IdealImager(m, s, sp, tt, f)