davinci( 'optical_layout', 'Layout', my_layout )
davinci( 'optical_layout', 'Layout', my_layout, 'AttachDataForRetrievalByOutsideCode', <true or [false]> )
h = davinci( ___ )
[ h, next_beam_launch ] = davinci( ___ )


Draw a 2-D layout corresponding to one beam path in an optical system. In addition to the beam itself, draw optical components the beam encounters during propagation. This may include one or more lenses (thin only), mirrors (flat only), and/or beamsplitters (flat, thin only), as well as an absorber (flat only). The system is axial, apart from beam folds.

The output variable h is a struct that contains the Matlab graphics handles for the drawing. Each field of the struct corresponds to a particular component type (lens, etc.). Each field is a vector of handles ordered the same as the components are encountered by the beam. For example, if a beam encounters two lenses, h.lens(1) is the handle for the first lens encountered by the beam and h.lens(2) is the handle for the second lens.

After the optical layout is drawn, the line graphic objects corresponding to the rays are moved to the bottom of Matlab's visual stacking order to provide consistency across the drawing. For example, if the rays are drawn in black and lenses are drawn in red, the red will always appear on top of the black in places where the two overlap.

To draw a system in which beamsplitter(s) send light down more than one path, more than one call to davinci('optical_layout',...) is required since each call draws along only a single beam path. However, the later call(s) use output from the earlier call(s) (see the output variable next_beam_launch), which makes the process very simple.

Ray Tracing And Optical Component Placement

The beam is drawn as two "edge rays" that propagate through the system. But internally davinci() also tracks a "gut ray" down the middle of the beam, along the optical axis. The two "edge rays" are symmetric about the "gut ray."

Optical Components

Each of the 5 available optical components (lens, mirror, etc.) is associated with a corresponding optical_layout "sub-shape," as listed here:

optical_layout "sub-shape" (click name for details)

Sub-shapes are specified with the same syntax as all DaVinci shapes. For example:

MyLens = davinci( 'optical_layout.lens', ___ );

The difference is that nothing gets drawn with this command. Instead, davinci() outputs a variable (MyLens in this case) that contains the parameters for the optical component (a lens in this case). The output variable is an object of the class @davinci_optical_layout, which is discussed in a separate section below.

The parameters for the optical components, and other parameters (such as distances between components), are merged together into a single object using the 3 overloaded operators discussed below. Nothing is drawn until that single object is passed to davinci() using the syntax given above. In the following example the variable MyLayout contains that single object:

davinci( 'optical_layout', 'Layout', MyLayout )

Thus davinci() must be called more than once to generate a drawing of an optical layout, even for layouts that contain only one beam and no beamsplitters.

Overloaded Operators

The 3 overloaded operators in the table below help specify the optical layout. This allows for user code that is significantly more compact and readable.

Operator Description
> Merge objects that specify different parts of the optical layout.
/ Apply tilt to an optical component.
: Name an optical component.

The > Operator

The figure below illustrates how to use the > operator. Since the specification of the present shape is organized around the propagation of a (single) beam, one may think of the specification as specifying a series of actions that occur as the beam propagates. In the figure below, each box represents an action. The first action is always the launch of the beam. What follows is one or more pairs of actions, where beam "travel" is always the first action in the pair and "strike component" is always the second action.

In software, each action (each box in the figure below) is represented by a Matlab object, and the objects are merged using the > operator. (The > operator was chosen in part because the symbol looks like an arrow, pointing in the direction of beam travel.) The "travel" objects are scalar numbers that represent travel distances (in data units) for the "gut ray." All the other objects are the objects of class @davinci_optical_layout output by calling davinci() on the optical_layout "sub-shapes."

The / Operator

The / operator is used to specify that a component is tilted relative to the incoming beam's "gut ray." (The / operator was chosen in part because the symbol looks like a tilted object.) Only beamsplitters, mirrors, and absorbers may be tilted. Lenses may not (a helpful error message is issued if you try). The tilt angle is specified in degrees. A positive value for the tilt angle means an observer who rides along the gut ray facing forward as the beam approaches the tilted component will see left side of the component as closer than the right side. If the tilt angle for a component is not specified, the component is taken to be oriented normal to the "gut ray." The / operator gets placed between an object of class @davinci_optical_layout on the operator's left and a numeric scalar (the tilt angle) on the operator's right. The output of this operation is another object of class @davinci_optical_layout. Parentheses are recommended for readability, as shown in the following example:

LAYOUT = LAUNCH > 10 > LENS > 5 > (MIRROR/45) > 3;

The : Operator

The : operator may be used to assign a name to an optical component, if desired. (The : operator was chosen in part because the symbol looks like it specifies an assignment.) When the component is drawn, the Tag property of the component's Matlab graphics object (patch or line) will be set to the name. (One can also name an optical_layout.beam_launch component, even though there is no graphics object associated with the optical source. This can be useful in conjunction with the AttachDataForRetrievalByOutsideCode parameter - see below.) This can be useful when accessing a component's graphics handle after the component is drawn, since one may use Matlab's findobj() function to find the handle. See the 4-f imaging system below for an example. The : operator gets placed between a char vector on the operator's left and an object of class @davinci_optical_layout on the operator's right. The output of this operation is another object of class @davinci_optical_layout. In the example below the name 'S1' is given to the beam launch, the name 'L1' is given to the lens, and the name 'M1' is given to the mirror. As an alternative to use of the : operator, one may assign a name to a component using the Name parameter/value pair as detailed on the documentation pages for the individual optical_layout "sub-shapes."

LAYOUT = 'S1':LAUNCH > 10 > 'L1':LENS > 5 > 'M1':(MIRROR/45) > 3;

Class @davinci_optical_layout

As mentioned throughout the present document, DaVinci uses a custom class named @davinci_optical_layout to help the user create a specification for the layout. One may use Matlab's standard class inspection tools to examine the class, and one may monitor the values davinci() stuffs into each object's class properties, if desired. However these steps are generally not necessary. And direct modification of a class object's property values by the user is not supported.

Layout With More Than One Beam

The code for the present component tracks light along only a single beam path. When the beam encounters a beamsplitter, the code draws the beamsplitter, then continues to follow the beam in transmission through the beamsplitter. At the end of execution, davinci() returns next_beam_launch, an array of objects of class @davinci_optical_layout, one for each beamsplitter that was encountered along the beam path. Each object contains the specification needed to launch the reflected beam from the beamsplitter. For the new beam (the beam reflected off the beamsplitter) use this specification as the launch action. (In other words, do not use the output from a separate call to the optical_layout.beam_launch "sub-shape.") An annotated example is given below for the case of a Mach-Zehnder interferometer.

Attach Data For Retrieval By Outside Code

When davinci() is called with the AttachDataForRetrievalByOutsideCode name-value pair set equal to true (see "Syntax" above), davinci() attaches a set of optical_layout data to the Matlab axes object in which the optical layout is drawn. This data is then accessible to other Matlab programs for further processing. This data includes items such as the positions and orientations of the various optical components.

Matlab's setappdata() function is what davinci() uses to attach the data to the axes object. Thus, other Matlab programs can use Matlab's getappdata() function to access the data. The data is stored as a scalar struct with setappdata() name identifier 'davinci'. The struct is organized as shown here and explained in the following table:


Fieldname Description
davinci_version char vector with the version of DaVinci used (irrespective of which version of Matlab is used). E.g., '2017A'. Letters are always capitalized here.
optical_layout Scalar struct with only one field, components.
components 1xN cell vector, where N is the number of optical components that are drawn. This includes absorbers, beamsplitters, lenses, and mirrors. It also includes beam launch components created directly by the user using the optical_layout.beam_launch sub-shape. It does not include beam launches associated with reflections off beamsplitters.
  • Data is included for all the optical components drawn on an optical layout, even when the optical layout includes more than one beam, so long as AttachDataForRetrievalByOutsideCode is set equal to true with each call to "davinci('optical_layout',...)".
    • Thus, the length N of the cell vector generally increases with each call to "davinci('optical_layout',...)" so long as the hold state of the axes object is on.
    • See How DaVinci Works (the section titled "appdata") for more detail on how the data attached to the axes object as appdata is affected by the hold state of the axes object.
  • Each of the N cells contains a Px2 cell array with P name/value pairs. Column #1 contains the parameter names (each name is stored as a char vector). Column #2 contains the corresponding parameter values. The list of name/value pairs included for each optical component is given on the documentation page for the corresponding optical_layout "sub-shape." DaVinci does not specify the order in which the name/value pairs are included in the Px2 cell array.
  • When the DrawFlag for an optical component is set to false, that component is not one of the N whose data is included in the cell vector.

An example of how to use the AttachDataForRetrievalByOutsideCode parameter/value pair is given below for the case of a Twyman-Green interferometer.


Click in the table below to see the code for each layout. As indicated, some of the figures are annotated to illustrate parameters.

Name Drawing Notes
Beam Expander Figure annotated.
4-f Imaging System

Illustrates use of ":" operator to name components.

Illustrates how to adjust graphics properties after layout is drawn.

Mach-Zehnder Interferometer

Figure annotated.

Illustrates how to draw a multi-beam system.

Illustrates use of "/" operator to tilt components.

Fizeau Interferometer

Illustrates how to draw a multi-beam system.

Illustrates use of "/" operator to tilt components.

Twyman-Green Interferometer

Illustrates how to draw a multi-beam system.

Illustrates use of "/" operator to tilt components.

Illustrates how to use the AttachDataForRetrievalByOutsideCode name/value pair.


Illustrates use of "/" operator to tilt components.

Illustrates how to colorize a beam after layout is drawn.

Copyright 2016-2017, Leonard R. Wayne, Washington, District of Columbia, United States of America. ALL RIGHTS RESERVED.