Glass Catalog Spreadsheets and Python

Optical glass manufacturers have settled on Excel spreadsheets as a means of documenting the technical details of their glass products. The formats are broadly similar but different in the details.

A major goal of the OpticalGlass package is to make the data in these vendor spreadsheets accessible to the Python user. OpticalGlass uses the pandas package to import and save the glass catalog in a DataFrame. These Excel spreadsheet catalogs are added to the ‘xls’ library, og_glass_libs[‘xls’].

Common data categories across all vendors include:

  • ‘refractive indices’

  • ‘dispersion coefficients’

  • ‘internal transmission mm, 10’

  • ‘chemical properties’

  • ‘thermal properties’

  • ‘mechanical properties’

These queries on the glass catalog dataframe return pandas Series with the data and (typically) the wavelengths used for sampling. These can be easily accessed as numpy arrays and can be plotted using matplotlib style capabilities.

The catalogs also contain single items of interest. The 2 that are supported across all catalogs currently include:

  • ‘abbe number’

  • ‘specific gravity’

A higher level interface is available as a set of catalog-specific subclasses of GlassPandas.

%matplotlib inline

Import glass and catalog factory functions.

import numpy as np
import matplotlib.pyplot as plt

from opticalglass.glassfactory import create_glass, og_glass_libs
catalog = 'Hoya'
gname = 'FCD1'
gname1 = 'E-F2'
gname2 = 'MC-TAF1'

Importing a catalog spreadsheet

The initialization of the global variable og_glass_libs reads the Excel spreadsheet into a DataFrame. A requirement for the import process is that the spreadsheet data be copied untouched into the catalog DataFrame. Only the spreadsheet row and column headers are changed in creating the catalog DataFrame.

The GlassCatalogPandas.df attribute has the glass catalog DataFrame.

hoya_xls = og_glass_libs['xls']['Hoya']
hoya_df = hoya_xls.df

Listing a catalog’s data categories

The column categories can be listed using the get_level_values() method and eliminating duplicates. Categories defined by OpticalGlass are all lower case.

hoya_df.columns.get_level_values(0).drop_duplicates()
Index([                                                                  'Code',
                                                             'refractive index',
                                                                  'abbe number',
                                                           'refractive indices',
                                                                        'blank',
                                                      'dispersion coefficients',
                                                          'Partial Dispersions',
                                                    'Partial Dispersion Ratio ',
                                    'Deviation of Relative Partial Dispersions',
                                                          'chemical properties',
                                                           'thermal properties',
                                                        'mechanical properties',
                                  'Temperature Coefficient of Refractive Index',
                                                                            nan,
          'Temperature Coefficient of Refractive Index  nh  404.66   (×10-6/℃)',
          'Temperature Coefficient of Refractive Index  ng  435.84   (×10-6/℃)',
          'Temperature Coefficient of Refractive Index  nF' 479.99   (×10-6/℃)',
          'Temperature Coefficient of Refractive Index  nF  486.13   (×10-6/℃)',
          'Temperature Coefficient of Refractive Index  ne  546.07   (×10-6/℃)',
          'Temperature Coefficient of Refractive Index  nd  587.56   (×10-6/℃)',
       'Temperature Coefficient of Refractive Index  nHe-Ne  632.8   (×10-6/℃)',
          'Temperature Coefficient of Refractive Index  nC' 643.85   (×10-6/℃)',
          'Temperature Coefficient of Refractive Index  nC  656.27   (×10-6/℃)',
           'Temperature Coefficient of Refractive Index  nr 706.52   (×10-6/℃)',
            'Temperature Coefficient of Abbe number  dνd/dT 587.56   (×10-3/℃)',
            'Temperature Coefficient of Abbe number  dνe/dT 546.07   (×10-3/℃)',
                             'Refractive index change to the cooling velocity ',
                                                  'Stress Optical Coefficient ',
                                                             'specific gravity',
                                                      'Spectral Transmittance ',
                                                  'internal transmission mm, 2',
                                                  'internal transmission mm, 5',
                                                 'internal transmission mm, 10',
                                                  'Glass Cross Reference Index',
                                                                      'Remarks',
                                                                       'Update'],
      dtype='object', name='category')

The glass_data() method returns a Series of the catalog data for the specified glass name.

fcd1_pd = hoya_xls.glass_data('FCD1')

The standard data categories can then be used to access the specific glass’s data.

The 'dispersion coefficients' category give the glass’s dispersion polynomial coefficients.

fcd1_pd['dispersion coefficients']
data item
A0       2.218113
A0pow           0
A1      -5.799427
A1pow          -3
A2       8.347068
A2pow          -3
A3       6.504652
A3pow          -5
A4       8.514219
A4pow          -6
A5      -5.885227
A5pow          -7
Name: FCD1, dtype: object

The 'refractive indices' category gives the measured refractive indices at measurement wavelengths.

fcd1_pd['refractive indices']
data item
1529.6     1.48598
1128.64    1.48907
t          1.49008
s          1.49182
A'           1.493
r          1.49408
C          1.49514
C'         1.49543
He-Ne      1.49571
D          1.49694
d            1.497
e          1.49845
F          1.50123
F'         1.50157
g          1.50451
h          1.50721
i          1.51175
Name: FCD1, dtype: object

The refractive index at a particular spectral line can be obtained with an additional level of indexing.

fcd1_pd['refractive indices']["F'"]
np.float64(1.50157)

Data can be returned in numpy arrays using the pandas conversion function to_numpy()

indices = fcd1_pd['refractive indices'].to_numpy(dtype=float); indices
array([1.48598, 1.48907, 1.49008, 1.49182, 1.493  , 1.49408, 1.49514,
       1.49543, 1.49571, 1.49694, 1.497  , 1.49845, 1.50123, 1.50157,
       1.50451, 1.50721, 1.51175])

Transmission data for 10mm thick samples is available.

fcd1_pd['internal transmission mm, 10']
data item
2500      0.999
2400.0    0.999
2200.0    0.999
2000.0    0.999
1800.0    0.999
1600.0    0.999
1550.0    0.999
1500.0    0.999
1400.0    0.999
1300.0    0.999
1200.0    0.999
1100      0.999
1060.0    0.999
1050.0    0.999
1000.0    0.999
950.0     0.998
900.0     0.997
850.0     0.998
830.0     0.999
800.0     0.999
780.0     0.999
750.0     0.999
700       0.999
650.0     0.998
600.0     0.999
550.0     0.999
500.0     0.998
480.0     0.998
460.0     0.997
440.0     0.996
420.0     0.996
400.0     0.998
390.0     0.997
380       0.996
370.0     0.992
360.0     0.981
350.0     0.958
340.0     0.907
330.0     0.826
320.0      0.68
310.0     0.486
300.0     0.284
290.0     0.133
280.0     0.052
Name: FCD1, dtype: object

The transmission data may be plotted directly from the Series via plot()

fcd1_pd['internal transmission mm, 10'].T.plot()
<Axes: xlabel='data item'>
../_images/output_22_1.png

All of the glasses in the catalog DataFrame may be plotted on the same graph.

hoya_df['internal transmission mm, 10'].T.plot(legend=False)
<Axes: xlabel='data item'>
../_images/output_24_1.png

Transmission data for a list of glasses can be plotted as well.

hoya_df.loc[['FCD1', 'E-F2']]['internal transmission mm, 10'].T.plot()
<Axes: xlabel='data item'>
../_images/output_26_1.png

OpticalMedium subclasses

The glass data Series gives access to all of the vendor’s glass data, but doesn’t address the important case of using the dispersion coefficients to calculate the refractive index at an arbitrary wavelength. This is provided by catalog-specific subclasses of OpticalMedium.

fcd1 = create_glass('FCD1', 'Hoya', 'xls')
ef2 = create_glass('E-F2', 'Hoya', 'xls')

Compare measured values vs. the dispersion equation

Get the measured wavelengths. These are the indices of the 'refractive indices' category

wvls = fcd1.glass_data()['refractive indices'].index; wvls
Index([ 1529.6, 1128.64,     't',     's',    'A'',     'r',     'C',    'C'',
       'He-Ne',     'D',     'd',     'e',     'F',    'F'',     'g',     'h',
           'i'],
      dtype='object', name='data item')

The meas_rindex() method queries the refractive indices at the catalog wavelengths (the indices of the ‘refractive indices’ category).

The rindex() method uses the ‘dispersion coefficients’ to calculate the refractive index at the specified wavelength.

The following produces a table comparing the measured values to the output from the dispersion equation.

print(" wvl     meas n   interp n    delta")
for w_str in wvls:
    n_line = fcd1.meas_rindex(w_str)
    try:
        n_intrp = fcd1.rindex(w_str)
    except KeyError:
        print(f'{w_str}: {n_line}, Key error')
    else:
        print(f'{str(w_str):7s} {n_line:8.5f}  {n_intrp:8.5f}  {n_intrp-n_line:8.2g}')
 wvl     meas n   interp n    delta
1529.6   1.48598   1.48598    -4e-06
1128.64  1.48907   1.48907  -2.4e-06
t        1.49008   1.49008    -2e-07
s        1.49182   1.49182   4.9e-06
A'       1.49300   1.49300   3.3e-06
r        1.49408   1.49408  -4.9e-06
C        1.49514   1.49514  -2.5e-06
C'       1.49543   1.49543   4.1e-06
He-Ne    1.49571   1.49571   9.4e-07
D        1.49694   1.49694   2.9e-06
d        1.49700   1.49700  -2.8e-06
e        1.49845   1.49845   4.7e-07
F        1.50123   1.50123  -2.5e-06
F'       1.50157   1.50157   2.4e-06
g        1.50451   1.50451  -8.7e-07
h        1.50721   1.50721   1.2e-06
i        1.51175   1.51175  -6.4e-07

An alternative way to create an glass object

Call create_glass() on the glass catalog itself.

fcd1_v2 = hoya_xls.create_glass('FCD1')
fcd1_v2.meas_rindex('F')
np.float64(1.50123)
fcd1_v2.glass_code()
'497.816'

Plotting transmission data

The transmission_data() method returns the material transmission data for a 10mm thick sample, as well as the sample wavelengths. The data may be passed directly into matplotlib plot routines.

plt.plot(*ef2.transmission_data())
[<matplotlib.lines.Line2D at 0x175d521b0>]
../_images/output_38_1.png