GlassCat
This submodule is used to download, parse, install and manage AGF glass specifications for use in OpticSim.
The central configuration file for GlassCat is located at src/GlassCat/data/sources.txt
, which ships with the following default entries.
NIKON a49714470fa875ad4fd8d11cbc0edbf1adfe877f42926d7612c1649dd9441e75 https://www.nikon.com/products/components/assets/pdf/nikon_zemax_data.zip
OHARA 0c9021bf11b8d4e660012191818685ad3110d4f9490699cabdc89aae1fd26d2e https://www.oharacorp.com/xls/OHARA_201130_CATALOG.zip
HOYA b02c203e5a5b7a8918cc786badf0a9db1fe2572372c1c163dc306b0a8a908854 http://www.hoya-opticalworld.com/common/agf/HOYA20210105.agf
SCHOTT e9aabbb8ebff116ba0c106a71afd86e72f2a397ac9bc447469129e325e795f4e https://www.schott.com/d/advanced_optics/6959f9a4-0e4f-4ef2-a302-2347468a82f5/1.31/schott-optical-glass-overview-zemax-format.zip
SUMITA c1093e42a1d08acbe30698aba730161e3b43f8f0d50533f65de8b6b11100fdc8 https://www.sumita-opt.co.jp/en/wp/wp-content/themes/sumita-opt-en/download-files.php files%5B%5D=new_sumita.agf&category=data
Each line corresponds to one AGF source, which is described by 2 to 4 space-delimited columns. The first column provides the installed module name for the catalog, e.g. GlassCat.NIKON
. The second column is the expected SHA256 checksum for the AGF file.
The final two columns are optional, specifying download instructions for acquiring the zipped AGF files automatically from the web. The fourth column allows us to use POST requests to acquire files from interactive sites.
When ] build OpticSim
is run, the sources are verified and parsed into corresponding Julia files. These are then included in OpticSim via AGFGlassCat.jl
. These steps are run automatically when the package is first installed using ] add OpticSim
, creating a sufficient working environment for our examples and tests.
Adding glass catalogs
sources.txt
can be edited freely to add more glass catalogs. However, this is a somewhat tedious process, so we have a convenience function for adding a locally downloaded AGF file to the source list.
OpticSim.GlassCat.add_agf
— Functionadd_agf(agffile; agfdir = AGF_DIR, sourcefile = SOURCES_PATH, name = nothing, rebuild = true)
Copies a file at agffile
(this can be either a download link or local path) to agfdir
and appends a corresponding entry to the source list at sourcefile
.
If a name
is not provided for the catalog, an implicit name is derived from agffile
.
If rebuild
is true, Pkg.build is called at the end to install the new catalog.
Using installed glasses
Glass types are accessed like so: OpticSim.GlassCat.CATALOG_NAME.GLASS_NAME
, e.g.
OpticSim.GlassCat.SUMITA.LAK7
OpticSim.GlassCat.SCHOTT.PK3
All glasses and catalogs are exported in their respective modules, so it is possible to invoke using
calls for convenience, e.g.
using OpticSim
GlassCat.SUMITA.LAK7
using OpticSim.GlassCat
SCHOTT.PK3
using OpticsSim.GlassCat.SCHOTT
N_BK7
Autocompletion can be used to see available catalogs and glasses. All catalog glasses are of type OpticSim.GlassCat.Glass
. Note that special characters in glass/catalog names are replaced with _
. There is a special type and constant value for air: OpticSim.GlassCat.Air
.
Unitful.jl is used to manage units, meaning any valid unit can be used for all arguments, e.g., wavelength can be passed in as μm or nm (or cm, mm, m, etc.). Non-unitful options are also available, in which case units are assumed to be μm, °C and Atm for length, temperature and pressure respectively.
TEMP_REF
and PRESSURE_REF
are constants:
const TEMP_REF = 20.0 # °C
const PRESSURE_REF = 1.0 # Atm
Types
OpticSim.GlassCat.AbstractGlass
— TypeAbstract type encapsulating all glasses.
OpticSim.GlassCat.Glass
— TypeStores all attributes relating to a glass type specified in an .AGF glass catalog.
Never used directly, instead created using catalog glasses, e.g. GlassCat.SCHOTT.N_BK7
.
In order to prevent type ambiguities in OpticSim.jl we can't have this type paramaterized.
OpticSim.GlassCat.Air
— ConstantSpecial glass to represent air. Refractive index is defined to always be 1.0 for any temperature and pressure (other indices are relative to this).
OpticSim.GlassCat.GlassID
— TypeObject identifying a glass, containing a type (e.g. MODEL
, MIL
, OTHER
or AGF
) depending on how the glass is defined, and an integer ID. Air is AIR:0
, others are on the form AGF:N
, for example.
Functions
OpticSim.GlassCat.index
— Functionindex(glass::AbstractGlass, wavelength; temperature=20°C, pressure=1Atm)
Compute the refractive index of glass
at wavelength
, optionally at specified temperature
and pressure
. Result is relative to the refractive index of air at given temperature and pressure.
If unitless, arguments are interpretted as μm, °C and Atm respectively.
This is defined to always equal 1.0 for Air at any temperature and pressure, use absairindex
for the absolute refractive index of air at a given temperature and pressure.
Examples
julia> index(GlassCat.SUMITA.LAK7, 700u"nm")
1.646494204478318
julia> index(GlassCat.SCHOTT.N_BK7, 0.55, temperature = 22.0)
1.51852824383283
julia> index(GlassCat.HOYA.FF1, 532u"nm", temperature = 25u"°C", pressure = 1.3)
1.5144848290944655
OpticSim.GlassCat.absairindex
— Functionabsairindex(wavelength; temperature=20°C, pressure=1Atm)
Compute the absolute refractive index of air at wavelength
, optionally at specified temperature
and pressure
. If unitless, arguments are interpretted as μm, °C and Atm respectively.
Examples
julia> absairindex(700u"nm")
1.000271074905147
julia> absairindex(0.7, temperature=27.0)
1.000264738846504
julia> absairindex(532u"nm", temperature = 25u"°C", pressure = 1.3)
1.0003494991178161
OpticSim.GlassCat.absorption
— Functionabsorption(glass::AbstractGlass, wavelength; temperature=20°C, pressure=1Atm)
Compute the intensity absorption per mm of glass
at wavelength
, optionally at specified temperature
and pressure
. Transmission values are linearly interpolated from the adjacent values in the data table of glass
, if wavelength
is below the minimum or above the maximum in the table then the nearest value is taken.
Absorption is defined as $\frac{-\log(t)}{\tau}$ where $t$ is the transmission value and $\tau$ is the thickness, both of which are provided in the data table.
If unitless, arguments are interpretted as μm, °C and Atm respectively.
Examples
julia> absorption(GlassCat.SUMITA.LAK7, 700u"nm")
0.0006018072325563021
julia> absorption(GlassCat.SCHOTT.N_BK7, 0.55, temperature = 22.0)
0.00016504471175660636
julia> absorption(GlassCat.SCHOTT.PSK3, 532u"nm", temperature = 25u"°C", pressure = 1.3)
0.00020855284788532435
OpticSim.GlassCat.glassfromMIL
— FunctionglassfromMIL(glasscode::Union{Float64,Int}) -> Glass
Generates a glass object for the given glass code based on U.S. military standard MIL-G-174, see the MIL specification for further details.
The glass code is a six-digit number specifying the glass according to its refractive index Nd
at d-light (587.5618nm), and its Abbe number Vd
also taken at d-light. The resulting glass code is the value of Nd - 1
rounded to three digits, followed by Vd
rounded to three digits, with all decimal points ignored. For example, N_BK7 has Nd = 1.5168
and Vd = 64.17
, giving a six-digit glass code of 517642
.
For Nd > 1.999
the format 1.123642
can be used representing Nd = 2.123
and Vd = 64.2
.
Accuracy is poor given the low precision of the input parameters, the mean error to measured data may be significant. Behavior may differ from other optical simulation tools when using MIL glasses. The approximate dispersion calculation used these glasses is generally only valid for visible wavelengths, in this case a limit of 360nm to 750nm is imposed.
Examples
julia> index(glassfromMIL(517642), 0.5875618)
1.5170003960064509
julia> index(glassfromMIL(1.134642), 0.5875618)
2.1340008686098946
OpticSim.GlassCat.modelglass
— Functionmodelglass(Nd::Float64, Vd::Float64, ΔPgF::Float64) -> Glass
Generates a glass object for the given refractive index at d-light (587.5618nm), Nd
, the Abbe number also at d-light, Vd
, and partial dispersion, ΔPgF
. The mean error to measured data for these models is typically small - usually < 0.0001. Behavior may differ from other optical simulation tools when using model glasses.
The approximate dispersion calculation used for these glasses is generally only valid for visible wavelengths, in this case a limit of 360nm to 750nm is imposed.
Examples
julia> index(modelglass(1.5168, 64.17, 0.0), 0.5875618)
1.5168003970108495
julia> index(modelglass(1.2344, 61.57, 0.003), 0.678)
1.2329425902693352
OpticSim.GlassCat.glasscatalogs
— Functionglasscatalogs()
Returns the complete list of glass catalogs available from GlassCat.
Example
julia> glasscatalogs()
41-element Array{Any,1}:
OpticSim.GlassCat.AMTIR
OpticSim.GlassCat.ANGSTROMLINK
OpticSim.GlassCat.APEL
OpticSim.GlassCat.ARCHER
OpticSim.GlassCat.ARTON
OpticSim.GlassCat.AUER_LIGHTING
OpticSim.GlassCat.BIREFRINGENT
⋮
OpticSim.GlassCat.glassnames
— Functionglassnames(catalog::Module)
Returns the glass names available from a given catalog.
Example
julia> glassnames(GlassCat.CARGILLE)
3-element Array{Any,1}:
"OG0607"
"OG0608"
"OG081160"
glassnames()
Returns the glass names available from all catalogs.
Example
julia> glassnames()
6-element Array{Pair{Module,Array{Any,1}},1}:
OpticSim.GlassCat.CARGILLE => ["OG0607", "OG0608", "OG081160"]
OpticSim.GlassCat.HOYA => ["BAC4", "BACD11" … "TAFD65"]
OpticSim.GlassCat.NIKON => ["BAF10", "BAF11" … "_7054"]
OpticSim.GlassCat.OHARA => ["L_BAL35", "L_BAL35P" … "S_TIM8"]
OpticSim.GlassCat.SCHOTT => ["AF32ECO", "BAFN6" … "SFL6"]
OpticSim.GlassCat.SUMITA => ["BAF1", "BAF10" … "ZNSF8"]
OpticSim.GlassCat.info
— Functioninfo([io::IO], glass::AbstractGlass)
Print out all data associated with glass
in an easily readable format.
Examples
julia> info(GlassCat.RPO.IG4)
ID: AGF:52
Dispersion formula: Schott (1)
Dispersion formula coefficients:
a₀: 6.91189161
a₁: -0.000787956404
a₂: -4.22296071
a₃: 142.900646
a₄: -1812.32748
a₅: 7766.33028
Valid wavelengths: 3.0μm to 12.0μm
Reference temperature: 20.0°C
Thermal ΔRI coefficients:
D₀: 3.24e-5
D₁: 0.0
D₂: 0.0
E₀: 0.0
E₁: 0.0
λₜₖ: 0.0
TCE (÷1e-6): 20.4
Ignore thermal expansion: false
Density (p): 4.47g/m³
ΔPgF: 0.0
RI at sodium D-Line (587nm): 1.0
Abbe Number: 0.0
Cost relative to N_BK7: ?
Status: Standard (0)
Melt frequency: 0
Exclude substitution: false
OpticSim.GlassCat.findglass
— Functionfindglass(condition::Function) -> Vector{Glass}
Returns the list of glasses which satisfy condition
where condition::(Glass -> Bool)
.
Example
julia> findglass(x -> (x.Nd > 2.3 && x.λmin < 0.5 && x.λmax > 0.9))
8-element Array{GlassCat.Glass,1}:
BIREFRINGENT.TEO2_E
BIREFRINGENT.PBMOO4
BIREFRINGENT.LINBO3
INFRARED.CLEARTRAN_OLD
INFRARED.CLEARTRAN
INFRARED.SRTIO3
INFRARED.ZNS_BROAD
INFRARED.ZNS_VIS
OpticSim.GlassCat.isair
— Functionisair(a) -> Bool
Tests if a is Air.
OpticSim.GlassCat.glassname
— Functionglassname(g::Union{AbstractGlass,GlassID})
Get the name (including catalog) of the glass, or glass with this ID.
OpticSim.GlassCat.glassid
— Functionglassid(g::AbstractGlass) -> GlassID
Get the ID of the glass, see GlassID
.
OpticSim.GlassCat.glassforid
— Functionglassforid(ID::GlassID)
Get the glass for a given ID.
OpticSim.GlassCat.polyfit_indices
— Functionpolyfit_indices(wavelengths, n_rel; degree=5)
Fit a polynomial to indices
at wavelengths
, optionally specifying the degree
of the polynomial. Returns tuple of array of fitted indices at wavelengths and the polynomial.
OpticSim.GlassCat.plot_indices
— Functionplot_indices(glass::AbstractGlass; polyfit=false, fiterror=false, degree=5, temperature=20°C, pressure=1Atm, nsamples=300, sampling_domain="wavelength")
Plot the refractive index for glass
for nsamples
within its valid range of wavelengths, optionally at temperature
and pressure
. polyfit
will show a polynomial of optionally specified degree
fitted to the data, fiterror
will also show the fitting error of the result. sampling_domain
specifies whether the samples will be spaced uniformly in "wavelength" or "wavenumber".
OpticSim.GlassCat.drawglassmap
— Functiondrawglassmap(glasscatalog::Module; λ::Length = 550nm, glassfontsize::Integer = 3, showprefixglasses::Bool = false)
Draw a scatter plot of index vs dispersion (the derivative of index with respect to wavelength). Both index and dispersion are computed at wavelength λ.
Choose glasses to graph using the glassfilterprediate argument. This is a function that receives a Glass object and returns true if the glass should be graphed.
If showprefixglasses is true then glasses with names like F_BAK7
will be displayed. Otherwise glasses that have a leading letter prefix followed by an underscore, such as F_
, will not be displayed.
The index formulas for some glasses may give incorrect results if λ is outside the valid range for that glass. This can give anomalous results, such as indices less than zero or greater than 6. To filter out these glasses set maximumindex to a reasonable value such as 3.0.
example: plot only glasses that do not contain the strings "E" and "J"
drawglassmap(NIKON,showprefixglasses = true,glassfilterpredicate = (x) -> !occursin("J",string(x)) && !occursin("E",string(x)))
OpticSim.GlassCat.verify_sources!
— Functionverify_sources!(sources::AbstractVector{<:AbstractVector{<:AbstractString}}, agfdir::AbstractString)
Verify a list of sources
located in agfdir
. If AGF files are missing or invalid, try to download them using the information provided in sources
.
Each source ∈ sources
is a collection of strings in the format name, sha256sum, url [, POST_data]
, where the last optional string is used to specify data to be sent in a POST request. This allows us to download a greater range of sources (e.g. SUMITA).
Modifies sources
in-place such that only verified sources remain.
OpticSim.GlassCat.verify_source
— Functionverify_source(agffile::AbstractString, expected_sha256sum::AbstractString)
Verify a source file using SHA256, returning true if successful. Otherwise, remove the file and return false.
OpticSim.GlassCat.download_source
— Functiondownload_source(dest::AbstractString, url::AbstractString, POST_data::Union{Nothing,AbstractString} = nothing)
Download and unzip an AGF glass catalog from a publicly available source. Supports POST requests.