5. Data Handling in Rayica
5.2.1 Overview
5.2.2 DataToRayica
5.2.3 Search Criteria
5.2.4 SearchData
5.2.5 ReadData
5.3 Working with Optical Materials
5.3.1 Overview
5.3.2 ModelRefractiveIndex
5.3.3 GlassMap
GlassMap and its Variants
Using GlassMap to Display, Retrieve and Install Optical Material Models
5.3.4 CreateRefractiveIndexModel
Creating a New Material
Specifying a Different Index Model
5.3.5 Directly assigning your own refractive index models
5.4 Working with ModelIntensity
5.5 Modelling Optical Coatings
5.5.1 Overview
5.5.2 Reflective Optics
5.5.3 Refractive Optics
5.1 Introducion
Rayica has a built-in database of over 8,000 items. This database includes not only lenses but numerious other optical elements as shown in the table below.
Table of representative optical components from Rayica's database. (Look in the Library of Examples for how this table was generated.)
Much of Rayica's database system was already introduced in Section 0.17 of the GettingStarted Chapter. In this chapter, we will go into further detail on Rayica's data handling capabilities. Rayica's database has two categories of information: optical materials and optical components. There are four main functions used in accessing the data base of information: DataToRayica, ReadData, SearchData, and GlassMap. In Section 5.2, you will learn more about accessing Rayica's database of optical components and materials using DataToRayica, ReadData, and SearchData. Then, in Section 5.3, you will learn how to access Rayica's optical material database with the GlassMap function as well as learn how to use and create new optical material models of your own.
In total, there are eleven different functions for working with data in Rayica, as listed below. This chapter, however, will only cover the first five functions. To learn some details about the six remaining functions, you can use the ?functionname or by consulting the Library of Examples of the on-line user guide. Otherwise, you can learn more in the Rayica Reference Guide to be distributed from the Optica Software website (www.opticasoftware.com).
DataToRayica[selectionproperties, options] is used to build models in Rayica of optical components, light sources, coatings, and materials from the information given in databaselist. DataToRayica first calls SearchData to select for specific data items.
SearchData[selectionproperties, options] uses the internally loaded catalog database to give a selected listing of catalog entries.
ReadData[parameters, selectionproperties, options] uses the internally loaded database to give a selected listing of the specified data-related parameters.
GlassMap[selectionproperties, options] is used to illustrate dispersive properties of optical materials and to select new material models from the Rayica database.
LoadData[filenames] is used to load database information.
SaveData[databaselist, filename, directoryname, options] is used to save databaselist to the hard disk.
DataToExcel[filename, data, selectionproperties, options] is used to export database information from Mathematica to the Excel spreadsheet data format.
ExcelToData[stringdata, options] is used to import Excel spreadsheet data into a database format recognized by Mathematica.
CodeVToData[stringdata, options] is used to import CodeV lens data into Rayica's database format.
ZemaxToData[stringdata, options] is used to import Zemax lens data into Rayica's database format.
KDPToData[stringdata, options] is used to import KDP lens data into Rayica's database format.
Rayica's eleven data-base related functions.
To load Rayica's database into memory, you can use the LoadData function.
In[28]:=
LoadData[All]
Out[28]=
Normally, the database will automatically get loaded the first time that you evaluate DataToRayica, SearchData, or ReadData, so you generally will not need to call LoadData in advance. However, the GlassMap function loads only optical material data and not information about optical components. Therefore, you will need to use LoadData after you use GlassMap in order to access optical component information.
5.2 Using Rayica's Database
5.2.1 Overview
Rayica's search capabilities works as follows: you basically enter various selection criteria to be searched. Rayica tries to find a match. If you want a complete listing of searchable parameters, you can call either SearchData or ReadData as an empty list. Rayica then scans its database and returns a sorted list of the possible search-parameter headings. However, there are in fact many more settings than this that you can use in your search. We will examine how to do this in the following discussions.
SearchData[]
5.2.2 DataToRayica
The most important data-base function is DataToRayica. DataToRayica is used to turn the database information into an Rayica definition.
In[2]:=
?DataToRayica
DataToRayica can be used with both optical components and optical materials, as shown in what follows.
Retrieving a Database Component
Here are two examples that use DataToRayica to construct a lens model from Rayica's database.
In[62]:=
DataToRayica[FocalLength->145]
AnalyzeSystem[%];
Out[62]=
In[64]:=
lens = DataToRayica[FocalLength->145, PlanoConvexLens]
AnalyzeSystem[%];
Out[64]=
When you use a rule as a search selection criterica such as FocalLength->145 that has a numerical value on the right-hand side, Rayica tries to find the closest match in the database. Note that in the previous example, the closest match was a focal length of 141. Once you have built a component with DataToRayica, the catalog information is also stored in the created Component.
In[31]:=
CatalogInformation/.lens
Out[31]=
Retrieving a Database Material
DataToRayica can be used to load a new material into Rayica from the database.
DataToRayica[OpticalMedium->SF5]
Normally, however, you don't have to first load a new optical material with DataToRayica before using it in a component function for the first time because Rayica will do this for you automatically. Here we directly use the Diamond material in a plano-convex lens and Rayica automatically gets its definition from the database.
In[13]:=
PlanoConvexLens[100,50,10, ComponentMedium -> Diamond]
Out[13]=
In[14]:=
?Diamond
Note, however, that if we try to use a material name that does not exist in Rayica's database, then we get a error message.
In[15]:=
PlanoConvexLens[100,50,10, ComponentMedium -> wrongname]
Out[15]=
5.2.3 Search Criteria
Rayica is extremely flexible about searching for different types of data. For making searches, Rayica accepts strings, rules, symbols, and Boolian parameter functions. Here is how you can use a Boolian parameter function to search for data.
In[58]:=
DataToRayica[BeamSplitterCube,
Function[{ComponentBoundary},ComponentBoundary[[2]]>50]
]
AnalyzeSystem[%];
Out[58]=
Here are some additonal examples that show the use of different search criteria with DataToRayica. This next example searches for the PlanoConvexLens symbol.
In[32]:=
DataToRayica[PlanoConvexLens]
AnalyzeSystem[%];
Out[32]=
In the next example, we do a combined symbol and rule search. In this case, Rayica first looks for a FocalLength rule that has value as close as possible to 300. Then Rayica searches for the LensTriplet symbol that have the previously selected FocalLength criteria.
In[37]:=
DataToRayica[FocalLength->300,LensTriplet]
AnalyzeSystem[%];
Out[37]=
The following example searches for the presence of the CustomMirror symbol and then finds the CompanyName rule that matches with the "Coherent-Ealing" string.
In[52]:=
DataToRayica[CustomMirror,CompanyName->"Coherent-Ealing"]
AnalyzeSystem[%];
Out[52]=
This next example shows how you can search for a specific catalog item number by specifying the item number as a string. If you already know the catalog item that you wish to model, this is often the most effective way to obtain it.
In[43]:=
DataToRayica["A32600"]
AnalyzeSystem[%];
Out[43]=
Often times, it is not necessary to provide the entire information in your string search. We can demonstrate this by rerunning the previous search with the "A" omitted from the string.
In[34]:=
DataToRayica["32600"]
AnalyzeSystem[%];
Out[34]=
If you are wanting to create a specific optical material model, then it is best to use the OpticalMedium rule in your search. This is because the OpticalMedium rule is only present in material database entries. For example, lets say that we wanted to create a model for SF11 glass. One possibility would be to call DataToRayica with the SF11 symbol as a search criteria.
In[36]:=
DataToRayica[SF11]
Out[36]=
Doing this results in the unexpected result that a lens is found in the database that uses SF11 glass. However, this was not our intention because we wanted to create a refractive index model for SF11, not an optical component. This problem is resolved if we instead use OpticalMedium -> SF11.
In[37]:=
DataToRayica[OpticalMedium -> SF11]
Out[37]=
Now we see that we have indeed created a new optical material model. We can check this further by seeing if a usage message has been generated for SF11.
In[38]:=
?SF11
5.2.4 SearchData
If you are not certain of which parameters to use, a good starting point is to call ReadData or SearchData with the name of a built-in Rayica component function name that you want to build. Then choose the most important parameters for additional filtering. You can use ReportedInterval to limit the number of items printed. SearchData gives the raw data format stored by Rayica. Here we use SearchData to look up a Mirror.
SearchData[Mirror,ReportedInterval->1]
Here we decide that ComponentBoundary and SurfaceAccuracy are the most interesting to us.
DataToRayica[ComponentBoundary->50, SurfaceAccuracy->1/10]
Rayica automatically creates new material functions from the database as they are needed to create new components. Sometimes, however, an optical material is not present and Rayica makes a substitution automatically. Such substitutions are often not equivalent to the original, however.
5.2.5 ReadData
ReadData gives a formated table of information. Here we use ReadData to get info on LensDoublet components. All gives all parameters about the object.
ReadData[All,LensDoublet,ReportedInterval->10]
CatalogNumber | CenterThickness | CompanyName | ComponentBoundary | ComponentLabel | ComponentMedium | Date | DesignRefractiveIndex | DesignWaveLength | EntrancePupilDiameter | FileName | FocalLength | GlassCatalogs | OpticaFunction | RadiusOfCurvature | ReferenceWaveLengthNumber | StopPosition | SurfaceBoundary | SurfaceCurvature | SurfaceLabel | SurfaceSeparation |
23 - 9319 | 9.5 | Coherent - Ealing | 25.4 | 23 - 9319 ACHRO - DOUBLET LensDoublet | {BK7, SF5} | {1999, 4, 18} | RowBox[{{, RowBox[{RowBox[{{, RowBox[{1.5224, ,, , 1.5168, ,, , 1.5143}], }}], ,, , RowBox[{{, RowBox[{1.6875, ,, , 1.6727, ,, , 1.6666}], }}]}], }}] | RowBox[{{, RowBox[{0.4861, ,, , 0.5876, ,, , 0.6563}], }}] | RowBox[{{, 22.86, }}] | CoherentEaling . m | 25.4 | {SCHOTT, MISC, INFRARED} | LensDoublet | RowBox[{{, RowBox[{38.35, ,, , RowBox[{-, 26.81}], ,, , RowBox[{-, 71.89}]}], }}] | 2 | 1 | RowBox[{{, RowBox[{25.4, ,, , 25.4, ,, , 25.4}], }}] | RowBox[{{, RowBox[{0.0261, ,, , RowBox[{-, 0.0373}], ,, , RowBox[{-, 0.0139}]}], }}] | {SphericalShape, SphericalShape, SphericalShape} | RowBox[{{, RowBox[{7.5, ,, , 2.}], }}] |
23 - 9335 | 8.2 | Coherent - Ealing | 25.4 | 23 - 9335 ACHRO - DOUBLET LensDoublet | {BK7, SF5} | {1999, 4, 18} | RowBox[{{, RowBox[{RowBox[{{, RowBox[{1.5224, ,, , 1.5168, ,, , 1.5143}], }}], ,, , RowBox[{{, RowBox[{1.6875, ,, , 1.6727, ,, , 1.6666}], }}]}], }}] | RowBox[{{, RowBox[{0.4861, ,, , 0.5876, ,, , 0.6563}], }}] | RowBox[{{, 22.86, }}] | CoherentEaling . m | 25.4 | {SCHOTT, MISC, INFRARED} | LensDoublet | RowBox[{{, RowBox[{50.508, ,, , RowBox[{-, 35.37}], ,, , RowBox[{-, 98.26}]}], }}] | 2 | 1 | RowBox[{{, RowBox[{25.4, ,, , 25.4, ,, , 25.4}], }}] | RowBox[{{, RowBox[{0.0198, ,, , RowBox[{-, 0.0283}], ,, , RowBox[{-, 0.0102}]}], }}] | {SphericalShape, SphericalShape, SphericalShape} | RowBox[{{, RowBox[{6.2, ,, , 2.}], }}] |
23 - 9350 | 7.2 | Coherent - Ealing | 25.4 | 23 - 9350 ACHRO - DOUBLET LensDoublet | {BK7, SF5} | {1999, 4, 18} | RowBox[{{, RowBox[{RowBox[{{, RowBox[{1.5224, ,, , 1.5168, ,, , 1.5143}], }}], ,, , RowBox[{{, RowBox[{1.6875, ,, , 1.6727, ,, , 1.6666}], }}]}], }}] | RowBox[{{, RowBox[{0.4861, ,, , 0.5876, ,, , 0.6563}], }}] | RowBox[{{, 22.86, }}] | CoherentEaling . m | 25.4 | {SCHOTT, MISC, INFRARED} | LensDoublet | RowBox[{{, RowBox[{62.941, ,, , RowBox[{-, 43.927}], ,, , RowBox[{-, 123.78}]}], }}] | 2 | 1 | RowBox[{{, RowBox[{25.4, ,, , 25.4, ,, , 25.4}], }}] | RowBox[{{, RowBox[{0.0159, ,, , RowBox[{-, 0.0228}], ,, , RowBox[{-, 0.0081}]}], }}] | {SphericalShape, SphericalShape, SphericalShape} | RowBox[{{, RowBox[{5.2, ,, , 2.}], }}] |
23 - 9368 | 7.2 | Coherent - Ealing | 25.4 | 23 - 9368 ACHRO - DOUBLET LensDoublet | {BK7, SF5} | {1999, 4, 18} | RowBox[{{, RowBox[{RowBox[{{, RowBox[{1.5224, ,, , 1.5168, ,, , 1.5143}], }}], ,, , RowBox[{{, RowBox[{1.6875, ,, , 1.6727, ,, , 1.6666}], }}]}], }}] | RowBox[{{, RowBox[{0.4861, ,, , 0.5876, ,, , 0.6563}], }}] | RowBox[{{, 22.86, }}] | CoherentEaling . m | 25.4 | {SCHOTT, MISC, INFRARED} | LensDoublet | RowBox[{{, RowBox[{75.303, ,, , RowBox[{-, 52.35}], ,, , RowBox[{-, 148.88}]}], }}] | 2 | 1 | RowBox[{{, RowBox[{25.4, ,, , 25.4, ,, , 25.4}], }}] | RowBox[{{, RowBox[{0.0133, ,, , RowBox[{-, 0.0191}], ,, , RowBox[{-, 0.0067}]}], }}] | {SphericalShape, SphericalShape, SphericalShape} | RowBox[{{, RowBox[{5.2, ,, , 2.}], }}] |
23 - 9459 | 5. | Coherent - Ealing | 12.5 | 23 - 9459 ACHRO - DOUBLET LensDoublet | {BK7, SF5} | {1999, 4, 18} | RowBox[{{, RowBox[{RowBox[{{, RowBox[{1.5224, ,, , 1.5168, ,, , 1.5143}], }}], ,, , RowBox[{{, RowBox[{1.6875, ,, , 1.6727, ,, , 1.6666}], }}]}], }}] | RowBox[{{, RowBox[{0.4861, ,, , 0.5876, ,, , 0.6563}], }}] | RowBox[{{, 11.25, }}] | CoherentEaling . m | 12.5 | {SCHOTT, MISC, INFRARED} | LensDoublet | RowBox[{{, RowBox[{22.12, ,, , RowBox[{-, 15.24}], ,, , RowBox[{-, 42.1199}]}], }}] | 2 | 1 | RowBox[{{, RowBox[{12.5, ,, , 12.5, ,, , 12.5}], }}] | RowBox[{{, RowBox[{0.0452, ,, , RowBox[{-, 0.0656}], ,, , RowBox[{-, 0.0237}]}], }}] | {SphericalShape, SphericalShape, SphericalShape} | RowBox[{{, RowBox[{3.9, ,, , 1.1}], }}] |
23 - 9467 | 7. | Coherent - Ealing | 18. | 23 - 9467 ACHRO - DOUBLET LensDoublet | {BK7, SF5} | {1999, 4, 18} | RowBox[{{, RowBox[{RowBox[{{, RowBox[{1.5224, ,, , 1.5168, ,, , 1.5143}], }}], ,, , RowBox[{{, RowBox[{1.6875, ,, , 1.6727, ,, , 1.6666}], }}]}], }}] | RowBox[{{, RowBox[{0.4861, ,, , 0.5876, ,, , 0.6563}], }}] | RowBox[{{, 16.2, }}] | CoherentEaling . m | 18. | {SCHOTT, MISC, INFRARED} | LensDoublet | RowBox[{{, RowBox[{25.62, ,, , RowBox[{-, 18.02}], ,, , RowBox[{-, 47.836}]}], }}] | 2 | 1 | RowBox[{{, RowBox[{18., ,, , 18., ,, , 18.}], }}] | RowBox[{{, RowBox[{0.039, ,, , RowBox[{-, 0.0555}], ,, , RowBox[{-, 0.0209}]}], }}] | {SphericalShape, SphericalShape, SphericalShape} | RowBox[{{, RowBox[{5.4, ,, , 1.6}], }}] |
23 - 9475 | 6.5 | Coherent - Ealing | 18. | 23 - 9475 ACHRO - DOUBLET LensDoublet | {BK7, SF5} | {1999, 4, 18} | RowBox[{{, RowBox[{RowBox[{{, RowBox[{1.5224, ,, , 1.5168, ,, , 1.5143}], }}], ,, , RowBox[{{, RowBox[{1.6875, ,, , 1.6727, ,, , 1.6666}], }}]}], }}] | RowBox[{{, RowBox[{0.4861, ,, , 0.5876, ,, , 0.6563}], }}] | RowBox[{{, 16.2, }}] | CoherentEaling . m | 18. | {SCHOTT, MISC, INFRARED} | LensDoublet | RowBox[{{, RowBox[{31.7, ,, , RowBox[{-, 22.}], ,, , RowBox[{-, 60.45}]}], }}] | 2 | 1 | RowBox[{{, RowBox[{18., ,, , 18., ,, , 18.}], }}] | RowBox[{{, RowBox[{0.0315, ,, , RowBox[{-, 0.0455}], ,, , RowBox[{-, 0.0165}]}], }}] | {SphericalShape, SphericalShape, SphericalShape} | RowBox[{{, RowBox[{4.9, ,, , 1.6}], }}] |
23 - 9483 | 6. | Coherent - Ealing | 18. | 23 - 9483 ACHRO - DOUBLET LensDoublet | {BK7, SF5} | {1999, 4, 18} | RowBox[{{, RowBox[{RowBox[{{, RowBox[{1.5224, ,, , 1.5168, ,, , 1.5143}], }}], ,, , RowBox[{{, RowBox[{1.6875, ,, , 1.6727, ,, , 1.6666}], }}]}], }}] | RowBox[{{, RowBox[{0.4861, ,, , 0.5876, ,, , 0.6563}], }}] | RowBox[{{, 16.2, }}] | CoherentEaling . m | 18. | {SCHOTT, MISC, INFRARED} | LensDoublet | RowBox[{{, RowBox[{37.84, ,, , RowBox[{-, 26.47}], ,, , RowBox[{-, 73.75}]}], }}] | 2 | 1 | RowBox[{{, RowBox[{18., ,, , 18., ,, , 18.}], }}] | RowBox[{{, RowBox[{0.0264, ,, , RowBox[{-, 0.0378}], ,, , RowBox[{-, 0.0136}]}], }}] | {SphericalShape, SphericalShape, SphericalShape} | RowBox[{{, RowBox[{4.4, ,, , 1.6}], }}] |
23 - 9491 | 5.8 | Coherent - Ealing | 18. | 23 - 9491 ACHRO - DOUBLET LensDoublet | {BK7, SF5} | {1999, 4, 18} | RowBox[{{, RowBox[{RowBox[{{, RowBox[{1.5224, ,, , 1.5168, ,, , 1.5143}], }}], ,, , RowBox[{{, RowBox[{1.6875, ,, , 1.6727, ,, , 1.6666}], }}]}], }}] | RowBox[{{, RowBox[{0.4861, ,, , 0.5876, ,, , 0.6563}], }}] | RowBox[{{, 16.2, }}] | CoherentEaling . m | 18. | {SCHOTT, MISC, INFRARED} | LensDoublet | RowBox[{{, RowBox[{50., ,, , RowBox[{-, 34.9}], ,, , RowBox[{-, 99.55}]}], }}] | 2 | 1 | RowBox[{{, RowBox[{18., ,, , 18., ,, , 18.}], }}] | RowBox[{{, RowBox[{0.02, ,, , RowBox[{-, 0.0287}], ,, , RowBox[{-, 0.01}]}], }}] | {SphericalShape, SphericalShape, SphericalShape} | RowBox[{{, RowBox[{4., ,, , 1.8}], }}] |
23 - 9509 | 5.8 | Coherent - Ealing | 18. | 23 - 9509 ACHRO - DOUBLET LensDoublet | {BK7, SF5} | {1999, 4, 18} | RowBox[{{, RowBox[{RowBox[{{, RowBox[{1.5224, ,, , 1.5168, ,, , 1.5143}], }}], ,, , RowBox[{{, RowBox[{1.6875, ,, , 1.6727, ,, , 1.6666}], }}]}], }}] | RowBox[{{, RowBox[{0.4861, ,, , 0.5876, ,, , 0.6563}], }}] | RowBox[{{, 16.2, }}] | CoherentEaling . m | 18. | {SCHOTT, MISC, INFRARED} | LensDoublet | RowBox[{{, RowBox[{62.367, ,, , RowBox[{-, 43.323}], ,, , RowBox[{-, 124.685}]}], }}] | 2 | 1 | RowBox[{{, RowBox[{18., ,, , 18., ,, , 18.}], }}] | RowBox[{{, RowBox[{0.016, ,, , RowBox[{-, 0.0231}], ,, , RowBox[{-, 0.008}]}], }}] | {SphericalShape, SphericalShape, SphericalShape} | RowBox[{{, RowBox[{4., ,, , 1.8}], }}] |
Otherwise you can specify specific parameters.
ReadData[{FocalLength,ComponentBoundary,CompanyName},LensDoublet,ReportedInterval->5]
FocalLength | ComponentBoundary | CompanyName |
12.5 | 12.5 | Coherent - Ealing |
18. | 18. | Coherent - Ealing |
18. | 18. | Coherent - Ealing |
18. | 18. | Coherent - Ealing |
18. | 18. | Coherent - Ealing |
18. | 18. | Coherent - Ealing |
25.4 | 25.4 | Coherent - Ealing |
25.4 | 25.4 | Coherent - Ealing |
25.4 | 25.4 | Coherent - Ealing |
25.4 | 25.4 | Coherent - Ealing |
You can pass the Union -> True option to ReadData in order to remove any repeated information from its output. In this example, we use ReadData with RayicaFunction to get a listing of all types of optical functions represented in Rayica's database.
In[155]:=
ReadData[RayicaFunction, All, Union->True, ReportedInterval->Infinity]
Out[155]=
5.3 Working with Optical Materials
5.3.1 Overview
Rayica offers many possibilites to model optical materials. In what follows, you will learn about these methods.
5.3.2 ModelRefractiveIndex
Rayica uses ModelRefractiveIndex internally to store information about the refractive index models during ray-tracing.
ModelRefractiveIndex[materialname] is a ray-parameter-dependent function or list of rules that models the refractive properties of materials identified by materialname.
When you first start up Rayica, it automatically loads up a number of built-in refractive index models for the most common refractive materials. Most of Rayica's optical materials are stored in Rayica's database and Rayica will automatically retrieve these models on demand. The most commonly used material is BK7 glass. You can always find out about Rayica's definition for a material by calling ModelRefractiveIndex directly yourself:
In[46]:=
model = ModelRefractiveIndex[BK7]
Out[46]=
Finally, you can evaluate such a model to find out its value for a particular wavelength.
In[48]:=
model[WaveLength->.6]
Out[48]=
Here is another example that uses DataToRayica to retrieve the model for a Diamond crystal from Rayica's database.
In[19]:=
DataToRayica[OpticalMedium->Diamond]
Out[19]=
After DataToRayica has generated a model for Diamond, you can next find out how this model is defined as well as test it at specific wavelength values.
In[21]:=
ModelRefractiveIndex[Diamond]
Out[21]=
In[22]:=
ModelRefractiveIndex[Diamond][WaveLength->.7]
Out[22]=
5.3.3 GlassMap
GlassMap and its Variants
GlassMap is a kind of road map to Rayica's optical material database. It searches the database (by calling ReadData) and generates a graphical picture that shows each material as a point on a graph that is based on the dispersive quality of the material.
GlassMap[selectionproperties, options] is used to illustrate dispersive properties of optical materials and to select new material models from the Rayica database.
GlassMap has two different modes of operation: rendering of data and creation of new optical material models. GlassMap is initially used to create a plot of optical material points. In its plotting mode, GlassMap uses ShowLabels -> True to indicate display of the Schott glass boundaries and ShowText -> True to indicate display of the material names with their corresponding points. Finally, GlassMap can be used to create new refractive index models in Rayica for specific selected materials. Once a plot has been generated by a GlassMap function, the mouse-sampled coordinate points can then be copied and pasted as selectionproperties into a second GlassMap function to generate new optical material models. When GlassMap receives one or more sets of coordinate points in selectionproperties, GlassMap identifies the corresponding optical material types and creates a new refractive index model for each material.
To use GlassMap for plotting a map, you can simply call its name with an empty brackets.
In[21]:=
GlassMap[];
Note that the resulting picture has a series of points for each optical material present in the database. In addition, there is an overlay of letters and lines that show the different ranges of glasses manufactured by Schott. Along the vertical axis is the refractive index of the material at the d wavelength (0.5876 microns) and along the horizontal axis is the Abbe V-number for dispersion. In the default case, shown above, GlassMap returns a point on the map for every optical material present in the database. This includes not only glasses, but also optical crystals, liquids, and naturally occurring materials. Sometimes you might only be interested in the glasses present in the database. In this case, you can add a search criteria to GlassMap for glass materials. In our next example, we will search for a text string containing the word "glass".
In[24]:=
GlassMap["glass"];
This time, the illustration was rendered with a different labels for each database point. If you want, these labels can be switched off with the option ShowText -> Off. We can further reduce the database search by looking for a single manufacturer of optical glasses. In this case, we will only include materials manufactured by Schott.
In[25]:=
GlassMap["Schott"];
Finally, we have a result that is much easier to examine. We will use this chart for our remaining discussions on GlassMap. (Note that after you have used the GlassMap function, you may need to call LoadData in order to gain access to the optical component database information, since GlassMap does not load this information.)
Using GlassMap to Display, Retrieve and Install Optical Material Models
We can now use one of the point coordinates from the glass map to both identify and load the closest matching material from Rayica's database. Here are two such examples.
GlassMap[{-84.5403, 1.4884}]
In[4]:=
GlassMap[{-67.3533, 1.55921}]
Out[4]=
Here, GlassMap has actually retrieved a stored model from Rayica's database that is the closest fit to the specified glass map coordinates. In this last case, GlassMap has retrieved the PSK50 optical material from the database. DataToRayica is called internally by GlassMap to generate the refractive index model. You can find out the specific details of Rayica's model for PSK50 by calling ModelRefractiveIndex.
In[5]:=
?PSK50
In[45]:=
ModelRefractiveIndex[PSK50]
Out[45]=
You can also use GlassCodeFunction to create a linear index model from a chosen coordinate of the glass map.
GlassCodeFunction[input, options] takes variety of input formats and creates linear or second-order, wavelength-dependent, refractive index functions used in ray-trace calculations.
In[10]:=
GlassCodeFunction[{-67.3533, 1.55921}]
Out[10]=
Note, however, that GlassCodeFunction is not as accurate a model as the GlassMap function since it only contains a linear function. As such, GlassCodeFunction is rarely used in actual practice. In addition to the discussions provided, GlassMap has a number of options that offer different ways of plotting information and the like. You can learn more about GlassMap in the Rayica Reference Guide to be distributed from the Optica Software website (www.opticasoftware.com).
5.3.4 CreateRefractiveIndexModel
Creating a New Material
If you have some experimental measured data for refractive index as a function of wavelength and you wish to model this information in Rayica, you can use CreateRefractiveIndexModel to help you with this. CreateRefractiveIndexModel allows you to create a new optical material and even store it permanently in Rayica's database.
CreateRefractiveIndexModel[datalist, materiallabel] creates a wavelength-dependent model that is fitted to the data for the index model specified by the RayicaFunction option.
Note that the materiallabel is used for the purposes of referencing the particular material within Rayica. Although materiallabel can be given as a string (such as "NewName"), it is often given as a symbolic object (such as NewName). The datalist should have the following format: {{wavelength1, index1}, {wavelength2, index2}, {wavelength3, index3}, ...}. CreateRefractiveIndexModel plots the data points against the fitted function, revealing model deficiencies. Finally, CreateRefractiveIndexModel defines the refractive model in Rayica. With the SaveData->True setting, this model is also stored in Rayica's database on disk for future retrieval and use.
Next we use CreateRefractiveIndexModel with its default settings to create a new model for a material that we will call NewMaterial.
CreateRefractiveIndexModel[{{0.537657, 1.478918}, {0.623571, 1.475123}, {.486,1.4825},{.589,1.4763},{.656,1.4738}}, NewMaterial]
In its default mode, CreateRefractiveIndexModel does not create a data file and you will need to re-evaluate its definition every time you start Mathematica. However, you save this information in Rayica's database by including the SaveData -> True option.
Specifying a Different Index Model
Rayica has five built-in models for describing the refractive index that are discussed later in Section 5.3.5. These are: IndexFunction, IndexInterpolationFunction, SellmeierFunction, GlassCodeFunction, HerzbergerFunction. By default, CreateRefractiveIndexModel uses the IndexFunction model. However, CreateRefractiveIndexModel also can generate information for any of Rayica's built-in models with the exception of GlassCodeFunction. You can also specify a different model to be generated by CreateRefractiveIndexModel with the RayicaFunction option. Some of these models work better than others for a given set of data. Next we use RayicaFunction -> SellmeierFunction. Note that the resulting model from this data has two singularities. Other data-sets may not result in such singularities, but for this reason, SellmeierFunction is not as suitable as IndexFunction for some experimental data-sets. However, in general, the SellmeierFunction is often effective over a larger wavelength range than IndexFunction and is a more physical representation. For this reason, most of Rayica's built-in database uses the SellmeierFunction. For the built-in database materials, however, the Sellmeier coefficients have evidently been carefully tweeked to avoid any singularities over the working range of the data models.
In[39]:=
CreateRefractiveIndexModel[{{0.537657, 1.478918}, {0.623571, 1.475123}, {.486,1.4825},{.589,1.4763},{.656,1.4738}}, NewMaterial, RayicaFunction->SellmeierFunction]
Out[39]=
Here is RayicaFunction->IndexInterpolationFunction.
In[41]:=
CreateRefractiveIndexModel[{{0.537657, 1.478918}, {0.623571, 1.475123}, {.486,1.4825},{.589,1.4763},{.656,1.4738}}, NewMaterial, RayicaFunction->IndexInterpolationFunction]
Out[41]=
5.3.5 Directly assigning your own refractive index models
Instead to using CreateRefractiveIndexModel, you can directly assign your own functions to ModelRefractiveIndex. The simplest function is, of course, a constant value. Which ever function you choose, you always follow the same procedure, to be outlined as follows. First of all, you need to decide on a label for your new optical material. For this example, we will use NewName as a label. Then you must first unprotect the ModelRefractiveIndex function:
In[16]:=
Unprotect[ModelRefractiveIndex]
Out[16]=
After this, you can assign a new model to ModelRefractiveIndex, via your chosen label, as follows:
In[11]:=
ModelRefractiveIndex[NewName] = Function[1.5]
Out[11]=
In this case, we assigned a function that has a constant value of 1.5 for all wavelengths. Wavelength-dependent functions would instead include the WaveLength parameter. Here is one such example.
In[10]:=
ModelRefractiveIndex[NewName2] = Function[2+Sin[WaveLength*2*Pi]/.#]
Out[10]=
In this case, we used our own custom expression to model the refractive index. Otherwise, Rayica has five different built-in systems for modeling the refractive index of an optical material. These include: IndexFunction, IndexInterpolationFunction, SellmeierFunction, GlassCodeFunction, HerzbergerFunction.
IndexFunction[a0, a1, a2, a3, a4, a5] takes six terms and creates the pure function Function[Sqrt[a0 + a1*WaveLength^2 + a2*WaveLength^-2 + a3*WaveLength^-4 + a4*WaveLength^-6 + a5*WaveLength^-8]/.#] used to model the index of refraction versus wavelength for various materials.
IndexInterpolationFunction[{{wavelength, index}, ..}, options] is used to create an interpolating function to represent the index of refraction versus wavelength for various materials.
SellmeierFunction[a0, a1, a2, b0, b1, b2] takes six terms and creates the pure function Function[Sqrt[1 + a0*WaveLength^2/(WaveLength^2-b0) + a1*WaveLength^2/(WaveLength^2-b1) + a2*WaveLength^2/(WaveLength^2-b2)]/.#] used to model the index of refraction versus wavelength for various materials.
GlassCodeFunction[input, options] takes variety of input formats and creates linear or second-order, wavelength-dependent, refractive index functions used in ray-trace calculations.
HerzbergerFunction[a, b, c, d, e] takes five terms and creates the pure function Function[(a + b/(WaveLength^2-0.028) + c/(WaveLength^2-0.028)^2 + d*WaveLength^2 + e*WaveLength^4)/.#] used to model the index of refraction versus wavelength for various materials. HerzbergerFunction is traditionally used with infra-red wavelength materials.
Rayica's five built-in refractive index models.
You can use any of Rayica's five built-in functions to define a new ModelRefractiveIndex.
In[17]:=
ModelRefractiveIndex[NewName3] = GlassCodeFunction[{-67.3533, 1.55921}]
Out[17]=
In[19]:=
ModelRefractiveIndex[NewName4] = IndexFunction[1.03787,0.325594,1.10257,-0.468572,0.0928007,-0.00693601]
Out[19]=
Finally, when you are finished assigning new models, you can Protect the ModelRefractiveIndex function again.
In[12]:=
Protect[ModelRefractiveIndex]
Out[12]=
If you refractive index model is constant-valued, you can pass this value directly to your component function with the ComponentMedium option.
In[14]:=
lens2 = PlanoConvexLens[100,50,10,ComponentMedium->1.5];
When you work with LensSurface functions, you can also feed ComponentMedium two numerical values to represent the refractive index on each side of the optical surface.
In[14]:=
lenssurface = LensSurface[50,ComponentMedium->{1.,1.5}];
However, if you have a wavelength-dependent function, then you must make a new ModelRefractiveIndex assignment instead of calling ComponentMedium directly.
In[20]:=
lens3 = PlanoConvexLens[100,50,10,ComponentMedium->Function[2+WaveLength^2]];
Out[20]=
5.4 Working with ModelIntensity
ModelIntensity is used to model the attenuation or gain that occurs as a ray travels through a bulk material.
Although ModelIntensity is not limited to any particular formulation, in the following examples, we will let the ray intensity depend on the geometrical ray length inside an optical medium in the following way:
One way to use ModelIntensity is to create a new type of optical material. In this case you must define a new OpticaMedium name. In addition to defining a ModelIntensity for this material, you will also need to define a new refractive index function as well. Here is an example that uses the new name, testmaterial:
In[3]:=
Unprotect[ModelRefractiveIndex,ModelIntensity];
ModelRefractiveIndex[testmaterial] = Function[1.5];
ModelIntensity[testmaterial] = Function[(Intensity*Exp[-.01*RayLength])/.#];
Here we have given the material a fixed refractive index of 1.5. As an alternative, however, you could also use a pre-existing refractive index function to define a new material:
In[6]:=
ModelRefractiveIndex[testmaterial] = ModelRefractiveIndex[BK7];
To use these new ModelIntensity and ModelRefractiveIndex material definitions, you simply add ComponentMedium -> testmaterial to your optical component function.
In[7]:=
Here we can use ReadRays to see the intensity of the ray as it penatrates each optical surface.
In[15]:=
Out[15]=
If you are not interested in creating an entirely new optical material, but instead wish to assign an intensity model to an existing material, you can directly pass ModelIntensity as an option to a component function.
Here we use TurboPlot instead of AnalyzeSystem. to execute a ray trace.
tres = TurboPlot[{LineOfRays[45], Move[PlanoConvexLens[100,50,10,
ModelIntensity->Function[(Intensity*Exp[-.01*RayLength])/.#]],50],
Move[Screen[50],150]},PlotType->TopView];
This time we use ReadTurboRays to see the intensity of the ray as it penatrates each optical surface.
ReadTurboRays[tres,Intensity]
When ModelIntensity is assigned to particular optical component, it is assumed that the intensity action occurs in the space between the first and last optical surfaces of the component. However, in some cases, the component may contain only a single optical surface or, in other cases, the intended active region is in front of the optical component. These situations call for an additional specification with the ActiveRegion.
In[13]:=
?ActiveRegion
Here we check Options[ComponentFoundation] to learn the default ActiveRegion option setting of most optical components:
In[12]:=
ActiveRegion/.Options[ComponentFoundation]
Out[12]=
In the previous example, the default ActiveRegion -> Automatic option setting was used. When we rerun the example with ActiveRegion -> -1 instead, the absorption takes place in front of the lens.
tres = TurboPlot[{LineOfRays[45],
Move[PlanoConvexLens[100,50,10, ActiveRegion -> -1,
ModelIntensity->Function[(Intensity*Exp[-.01*RayLength])/.#]],50],
Move[Screen[50],150]},PlotType->TopView];
ReadTurboRays[tres,Intensity]
Here is an example that uses ModelIntensity with the single-surfaced Screen component.
In[16]:=
res = AnalyzeSystem[{SingleRay[],
Move[Screen[50,ModelIntensity->Function[(Intensity*Exp[-.01*RayLength])/.#]],50],
Move[Screen[50],150]},PlotType->TopView];
In[17]:=
ReadRays[res,Intensity]
Out[17]=
5.5 Modelling Optical Coatings
5.5.1 Overview
In[16]:=
?ModelCoating
5.5.2 Reflective Optics
In[10]:=
DrawSystem[{
SingleRay[],
Move[Mirror[50],50,45],
Boundary[100]},
PlotType->TopView, ShowText->Intensity];
In[17]:=
Unprotect[ModelCoating];
In[25]:=
ModelCoating[TestMirror] = Function[(100*WaveLength)/.#]
Out[25]=
In[26]:=
mirror = Mirror[50, CoatingMedium->TestMirror]
Out[26]=
In[20]:=
AnalyzeSystem[{
SingleRay[],
Move[mirror,50,45],
Boundary[100]},
PlotType->TopView, ShowText->Intensity];
In[27]:=
TurboPlot[{
SingleRay[],
Move[mirror,50,45],
Boundary[100]},
PlotType->TopView];
ReadTurboRays[%,Intensity]
Out[28]=
As an alternative, you can directly pass a function to the Reflectance of the Mirror.
In[29]:=
mirror1 = Mirror[50, Reflectance->70];
In[30]:=
DrawSystem[{
SingleRay[],
Move[mirror1,50,45],
Boundary[100]},
PlotType->TopView, ShowText->Intensity];
In[31]:=
mirror2 = Mirror[50, Reflectance->Function[100*WaveLength/.#]];
In[32]:=
TurboPlot[{
SingleRay[],
Move[mirror2,50,45],
Boundary[100]},
PlotType->TopView];
ReadTurboRays[%,Intensity]
Out[33]=
5.5.3 Refractive Optics
In[34]:=
lens = LensSurface[50]
Out[34]=
In[37]:=
DrawSystem[{
SingleRay[],
Move[lens,50,45],
Boundary[100]},
PlotType->TopView, ShowText->Intensity];
In[44]:=
lens1 = LensSurface[50, Transmittance->55]
Out[44]=
In[45]:=
DrawSystem[{
SingleRay[],
Move[lens1,50,45],
Boundary[100]},
PlotType->TopView, ShowText->Intensity];
In[46]:=
TurboPlot[{
SingleRay[],
Move[lens1,50,45],
Boundary[100]},
PlotType->TopView];
ReadTurboRays[%,Intensity]
Out[47]=
In[42]:=
lens2 = LensSurface[50, Transmittance->55, Reflectance->0]
Out[42]=
In[43]:=
DrawSystem[{
SingleRay[],
Move[lens2,50,45],
Boundary[100]},
PlotType->TopView, ShowText->Intensity];
In[48]:=
Unprotect[ModelCoating];
ModelCoating[TestCoat,___] = {Function[.7*Intensity/.#],Function[.3*Intensity/.#]}
Out[49]=
In[51]:=
lens3 = LensSurface[50, CoatingMedium->TestCoat]
Out[51]=
In[53]:=
DrawSystem[{
SingleRay[],
Move[lens3,50,45],
Boundary[100]},
PlotType->TopView, ShowText->Intensity];
In[54]:=
TurboPlot[{
SingleRay[],
Move[lens3,50,45],
Boundary[100]},
PlotType->TopView];
ReadTurboRays[%,Intensity]
Out[55]=
In[56]:=
?AntireflectionCoating
In[57]:=
?CoatingSpecification
In[58]:=
testlens2 = LensSurface[50, CoatingMedium->AntireflectionCoating, CoatingSpecification->20]
Out[58]=
In[59]:=
DrawSystem[{
SingleRay[],
Move[testlens2,50,45],
Boundary[100]},
PlotType->TopView, ShowText->Intensity];
In[60]:=
testlens3 = LensSurface[50, CoatingMedium->AntireflectionCoating, CoatingSpecification->100*WaveLength]
Out[60]=
In[61]:=
DrawSystem[{
SingleRay[],
Move[testlens3,50,45],
Boundary[100]},
PlotType->TopView, ShowText->Intensity];
Created by Mathematica (November 19, 2004)