# Models and Representations¶

## Optical Model¶

### Overview¶

The OpticalModel serves as a top level container of model properties. Key aspects are built-in sequential surface, paraxial and element based representations of the optical model. Each representation can be used build and modify the optical model.

For design and analysis of image forming systems, the sequential surface model is often the most direct method for specifying an optical system. The SequentialModel describes a sequence of Interfaces and Gaps that light propagates through to form an image. First order properties and ray tracing can be done directly with this representation. It is straightforward to produce an element based representation from the SequentialModel in many cases. Changes in the SequentialModel can be propagated to the peer models in the OpticalModel by calling update_model() on OpticalModel.

A SequentialModel is a high fidelity representation of the geometry and optical properties of the optical model. In contrast, the ParaxialModel is obtained by assuming all optical ray angles are small so that trigonometric relationships can be replaced by the angles themselves. This enables deriving the constructional parameters from paraxial ray specifications. This can be done using paraxial ray solves and/or $$y-\overline{y}$$ and $$\omega-\overline{\omega}$$ diagrams.

Finally, the physical model of the components is represented by Part and groups of Part, i.e. Assembly. The PartTree embodies the relationships between Part, Assembly, and the sequence of Interface and Gap managed by the SequentialModel. The ElementModel major requirement is the elements be able to render themselves in a 2D drawing view. The grouping of interfaces into elements and assemblies allows the $$y-\overline{y}$$ diagram to collapse individual nodes for interfaces into a single node for elements or groups of elements.

The use of Assembly and the PartTree can be used, with the add_from_file() method, to build up an optical layout from commercial parts catalogs.

It should also be possible in the future to ray trace the ElementModel to generate a SequentialModel corresponding to a ray’s path through the elements.

The OpticalSpecs class holds the optical usage definition of the model. Aperture, field of view, wavelength, and focal position are all aspects of the OpticalSpecs. The first order properties are in opm['analysis_results']['parax_data']. The usage specification of the optical model is given by the SpecSheet class in combination with the OpticalSpecs class.

Paraxial layout operations are handled via the ParaxialModel. This enables model manipulation via the $$y-\overline{y}$$ or $$\omega-\overline{\omega}$$ diagrams. The goal is to smoothly integrate the information in the SpecSheet with constraints on movement in the $$y-\overline{y}$$ diagram or changes to the paraxial rays in the Optical Layout.

The system units and other information is contained in the SystemSpec class. It is the system_spec attribute in OpticalModel.

## Sequential Model¶

### Overview¶

The SequentialModel abstracts the essential parts of a physical optical system when using ray tracing to compute imaging performance. For rotationally symmetric optical systems, this requires a minimum of information: a list of curvature, thickness, and refractive index. Similarly, the needs of ray tracing for performance evaluation is satisfied by the sequence of optical surfaces involved in image formation.

A sequential optical model is a sequence of interfaces and gaps. The first interface is the object surface and the last is the image surface. Light propagates sequentially through the interfaces and gaps.

### Structure¶

The sequential model has this structure:

IfcObj  Ifc1  Ifc2  Ifc3 ... IfcN-1   IfcN  IfcImg
\  /  \  /  \  /             \   /  \  /
GObj   G1    G2              GN-1   GImg


where

A complete SequentialModel mates a top level assembly with an Object space and Image space. An advantage of this structure is that it facilitates the substitution of one set of interfaces for another. A top level view of a SequentialModel looks like this:

IfcObj  System  IfcImg
\  /    \  /
GObj    GImg


The Object space consists of an object interface and object gap, with Image space similarly constituted. Note that the Image gap is associated with the Image surface, not the final System interface. This makes editing operations such as inserting or replacing elements straightforward. The user view (e.g. list_model() still groups the image thickness with the final interface, with no loss of generality.

Sub-assemblies are defined by N interfaces and N-1 gaps. The low level view of System looks like this:

Ifc1  Ifc2  Ifc3 ... IfcN-1   IfcN
\  /  \  /             \  /
G1    G2              GN-1


The low level view might be easier to manipulate at an intermediate level of detail. For example, a Telescope might be represented as:

IfcObj  Telescope  IfcImg
\  /       \  /
GObj       GImg


where the Telescope is:

Objective  Eyepiece
\  /
GSep


and GSep is the gap separating the Objective and the Eyepiece.

### Constituents¶

The Interface API supports implementation of an optical action, such as refraction, reflection, scatter, diffraction, etc. The Interface may be realized as a physical profile separating the adjacent gaps or an idealized object, such as a thin lens or 2 point HOE.

The Gap class maintains a simple separation (z translation) and the medium filling the gap. More complex coordinate transformations are handled through the Interface API.

The medium in the Gap is provided via classes that implement rindex(). For simple modeling, the medium provides constant refractive index classes for Air and Glass.

If you have a list of refractive indices and their corresponding wavelengths (in nm), you can use the InterpolatedGlass class. This uses the scipy routine scipy.interpolate.interp1d to interpolate the data.

Commercial optical glasses are supported by the opticalglass package.

### Sequential Paths¶

The combination of Interfaces and Gaps completely define the path of a ray through the optical model. For convenience and efficiency when doing optical calculations, it is useful to extract a subset of data that is required for ray tracing. The method path() in SequentialModel returns a Python generator that is used to drive the ray tracing process.

## Optical Usage Specification¶

### Overview¶

The OpticalSpecs class holds the optical usage definition of the model. Aperture, field of view, wavelength, and focal position are all aspects of the OpticalSpecs.

The optical configuration is broken into four parts:

* aperture
* field of view
* spectral region
* focus range


The pupil and field specifications can be specified in a variety of ways. The key keyword argument takes a list of 2 strings. The first string indicates whether the specification is in object or image space. The second one indicates which parameter is the defining specification.

#### Pupil Specification¶

The PupilSpec class maintains the aperture specification. The PupilSpec can be defined in object or image space. The defining parameters can be pupil, f/# or NA, where pupil is the pupil diameter.

osp.pupil = PupilSpec(osp, key=['object', 'pupil'], value=12.5)


The PupilSpec class allows rays to be specified as fractions of the pupil dimension. A list of pupil_rays and ray_labels define rays to be used to establish clear aperture dimensions on optical elements and rays to be drawn for the lens layout. A default set of pupil rays is provided that is appropriate for circular pupil systems with plane symmetry.

#### Field Specification¶

The FieldSpec can be defined in object or image space. The defining parameters can be height or angle, where angle is given in degrees.

osp.field_of_view = FieldSpec(osp, key=['object', 'angle'], flds=[0., 20.0])


The FieldSpec maintains a list of Field instances. Each Field contains an absolute field specification of the type specified in FieldSpec. It can also have attributes set for the chief ray data at the field (chief_ray) as well as the definition of the reference sphere for OPD calculations (ref_sphere). These are calculated by trace.get_chief_ray_pkg() and trace.setup_pupil_coords() respectively.

#### Wavelength Specification¶

The WvlSpec defines the wavelengths and weights to use when evaluating the model. The wavelength values can be given in either nanometers or a spectral line designation.

osp.spectral_region = WvlSpec([('F', 0.5), (587.5618, 1.0), ('C', 0.5)], ref_wl=1)


The FocusRange defines the amount of defocus and, optionally, focal range to use when evaluating the model.

osp.defocus = FocusRange(focus_shift=0.01)