Python 3 + SQLite wrapper for the refractiveindex.info database of optical constants by Mikhail Polyanskiy.
YML parsing is based on a modified version of refractiveIndex.py from the PyTMM project by Pavel Dmitriev.
- Build a local SQLite database from the upstream YML folder or directly from a
.zipURL. - Search materials by name, shelf/book/page, refractive index (n), or extinction coefficient (k).
- Run arbitrary SQL queries against the database.
- Load a material and retrieve n, k, or ε at any wavelength — scalar or NumPy array input.
- Query in any wavelength unit: nm, µm, m, mm, Å, cm⁻¹, THz, or eV.
- Out-of-range wavelengths return NaN instead of raising exceptions, enabling clean vectorised workflows.
- Export optical data to NumPy arrays or CSV files.
- Use
Material.FromListsto wrap your own n/k data without a database.
pip install .Dependencies (declared in pyproject.toml, installed automatically):
| Package | Purpose |
|---|---|
numpy |
Array operations and interpolation |
scipy |
interp1d for tabulated data |
pyyaml |
Parsing the upstream YML files |
requests |
Downloading the database zip |
from refractivesqlite import Database
# 1. Create the database once (downloads ~30 MB)
db = Database("refractive.db")
db.create_database_from_url()
# 2. On subsequent runs just open it
db = Database("refractive.db")
# 3. Find a material
db.search_pages("BK7")
# 4. Load and query it
mat = db.get_material(pageid)
print(mat.get_refractiveindex(589)) # n at 589 nm
print(mat.get_refractiveindex(2.48, unit='eV')) # same point, eV input
print(mat.get_extinctioncoefficient(589)) # k at 589 nm
print(mat.get_epsilon(589)) # complex permittivity ε = (n+ik)²
# 5. Vectorised query over a wavelength array
import numpy as np
wls = np.linspace(400, 800, 200) # nm
n_arr = mat.get_refractiveindex(wls) # shape (200,), NaN outside range
# 6. Get everything as a NumPy array (shape N×2: wavelength µm, value)
n = np.array(mat.get_complete_refractive())
k = np.array(mat.get_complete_extinction())See examples/Tutorial.ipynb for a full walkthrough.
| Table | Columns |
|---|---|
pages |
pageid, shelf, book, page, filepath, hasrefractive, hasextinction, rangeMin, rangeMax, points |
refractiveindex |
pageid, wave (µm), refindex |
extcoeff |
pageid, wave (µm), coeff |
Open (or prepare to create) an SQLite database at path.
# From the default upstream URL
db.create_database_from_url()
# From a specific historical release
db.create_database_from_url(
riiurl="https://refractiveindex.info/download/database/rii-database-2019-02-11.zip"
)
# From a local YML folder (after manual download + unzip)
db.create_database_from_folder("database/", interpolation_points=200)interpolation_points controls how finely formula-based materials are sampled (default 100).
db.search_pages() # list everything
db.search_pages("gold") # fuzzy match on shelf/book/page/filepath
db.search_pages("Au", exact=True) # exact (case-insensitive) match
db.search_id(37) # look up one page by ID
db.search_n(n=1.5, delta_n=0.01) # materials where n ∈ [1.49, 1.51]
db.search_k(k=0.3, delta_k=0.01) # materials where k ∈ [0.29, 0.31]
db.search_nk(n=1.5, delta_n=0.1,
k=0.3, delta_k=0.1) # both constraints at the same wavelength
# Raw SQL — returns a list of tuples
results = db.search_custom(
'SELECT pageid, page FROM pages WHERE shelf="main" AND book="Au"'
)mat = db.get_material(37) # returns a Material object (tabulated)
# Load from YAML to access the original dispersion formula & coefficients
mat_yml = db.get_material_from_yml(37, yml_database_path="database")
print(mat_yml.refractiveIndex.formula) # e.g. 1 (Sellmeier)
print(mat_yml.refractiveIndex.coefficients) # list of floats
# NumPy arrays directly from the database (shape N×2)
n_arr = db.get_material_n_numpy(37)
k_arr = db.get_material_k_numpy(37)
# CSV export
db.get_material_csv(37, folder="output/")
db.get_material_csv_all(outputfolder="output/")Returned by db.get_material(), or built from your own data with Material.FromLists.
mat.has_refractive() # bool
mat.has_extinction() # bool
mat.get_page_info() # dict of database metadataAll query methods accept a scalar wavelength or a NumPy array. Values outside the valid range return NaN rather than raising an exception.
# Default unit: nm
mat.get_refractiveindex(550) # scalar
mat.get_extinctioncoefficient(550) # scalar
# Any supported unit (see table below)
mat.get_refractiveindex(0.55, unit='um') # µm
mat.get_refractiveindex(2.25, unit='eV') # electron-volts
mat.get_refractiveindex(18182, unit='cm-1') # wavenumbers
# Vectorised — returns ndarray, NaN outside valid range
import numpy as np
wls = np.linspace(400, 800, 200)
n = mat.get_refractiveindex(wls) # shape (200,)
k = mat.get_extinctioncoefficient(wls) # shape (200,)Supported units:
unit= |
Physical quantity |
|---|---|
'm' |
metres |
'mm' |
millimetres |
'um' |
micrometres (µm) |
'nm' (default) |
nanometres |
'A' |
ångströms |
'cm-1' |
wavenumbers (cm⁻¹) |
'THz' |
terahertz frequency |
'eV' |
electron-volts |
# ε = (n + ik)² — physics convention (exp(−iωt)), default
eps = mat.get_epsilon(550)
# ε = (n − ik)² — engineering convention (exp(+iωt))
eps = mat.get_epsilon(550, convention='exp_plus_i_omega_t')
# Works with any unit and array input
eps = mat.get_epsilon(np.linspace(400, 800, 200), unit='nm')If no extinction coefficient is available, k is taken as 0 and ε is real.
lo, hi = mat.get_wl_range() # (min, max) in nm
lo, hi = mat.get_wl_range(unit='um') # in µm
lo, hi = mat.get_wl_range(unit='eV') # in eVmat.get_complete_refractive() # list of [wavelength_µm, n]
mat.get_complete_extinction() # list of [wavelength_µm, k]
mat.to_csv("output.csv") # writes (n).csv, (k).csv, or (nk).csvfrom refractivesqlite import Material
pageinfo = {"pageid": 0, "shelf": "custom", "book": "MyMaterial", "page": "v1"}
mat = Material.FromLists(
pageinfo,
wavelengths_r=[0.4, 0.6, 0.8], refractive=[1.52, 1.50, 1.49],
wavelengths_e=[0.4, 0.6, 0.8], extinction=[1e-4, 8e-5, 6e-5],
)
print(mat.get_refractiveindex(500))
print(mat.get_epsilon(500))refractivesqlite/
├── __init__.py # public API: Database, Material
├── database.py # Database — search & retrieval
├── material.py # Material — per-entry interface
├── optical_data.py # RefractiveIndexData, FormulaRefractiveIndexData,
│ # TabulatedRefractiveIndexData, ExtinctionCoefficientData
├── builder.py # DB creation from YML folder (with catalog cache)
├── downloader.py # download_rii_zip
├── models.py # Shelf / Book / Page / Entry namedtuples
├── exceptions.py # NoExtinctionCoefficient, FormulaNotImplemented
├── _constants.py # RII_DATABASE_URL
└── _units.py # Wavelength unit registry (to_nm / from_nm)
examples/
└── Tutorial.ipynb # interactive walkthrough
tests/
├── test_database.py
├── test_material.py
└── test_optical_data.py
docs/
└── ER.PNG # database schema diagram
pip install pytest
pytest tests/Same as the refractiveindex.info webpage: NO GUARANTEE OF ACCURACY — use at your own risk.
- HugoGuillen — original author
- tnorth — formulas 4, 7, 8, and 9
- p-tillmann — database format update
- lyd1ng — PEP 8 compliance and docstrings