Skip to content

Raman scattering

Time/frequency-domain response h_R(t), gain spectra, material comparisons, SQLite database. Docstrings are the source of truth, rendered with mkdocstrings (numpydoc style).

photonics_helper.raman

Raman scattering subpackage.

Public re-export surface preserving the historical photonics_helper.raman.<Name> import paths. The implementation is split by responsibility:

  • :mod:~photonics_helper.raman.reference — hardcoded material tables
  • :mod:~photonics_helper.raman.spec — :class:RamanSpec
  • :mod:~photonics_helper.raman.db — :class:RamanDatabase
  • :mod:~photonics_helper.raman.response — time/frequency response physics
  • :mod:~photonics_helper.raman.explorer — explorer and comparison helpers
  • :mod:~photonics_helper.raman.dashboard — Dash app factory

RamanDatabase module-attribute

RamanDatabase = MaterialsDatabase

COMMON_COMPARISONS module-attribute

COMMON_COMPARISONS = {'glass_vs_chalcogenide': ['Silica', 'As2Se3'], 'semiconductor': ['CdS', 'GaAs', 'Si', 'Ge'], 'high_n2': ['Silica', 'As2Se3', 'Diamond'], 'high_shift': ['Silica', 'Diamond', 'Si'], 'nitride_semiconductor': ['GaN', 'AlN', 'Si3N4'], 'nonlinear_crystal': ['LiNbO3', 'KTP', 'LBO', 'BaTiO3'], 'high_gain': ['Diamond', 'As2Se3', 'YAG'], 'wide_bandgap': ['Diamond', 'GaN', 'SiC_4H', 'AlN', 'Ga2O3'], 'iii_v': ['GaAs', 'InP', 'AlGaAs', 'InGaAs'], 'laser_host': ['YAG', 'Al2O3', 'YLF'], 'nlo_crystal': ['LBO', 'KTP', 'AgGaS2', 'AgGaSe2', 'LiNbO3'], 'chalcogenide': ['As2S3', 'As2Se3'], 'ferroelectric': ['LiNbO3', 'LiTaO3', 'BaTiO3', 'KTP'], 'negative_n2': ['ZnO', 'CdTe']}

RAMAN_MATERIALS module-attribute

RAMAN_MATERIALS: dict[str, dict] = {'Silica': {'name': 'Silica', 'crystal': 'Amorphous SiO2', 'bandgap_eV': 9.0, 'n2': 3.2e-20, 'raman_shift_cm': 440, 'raman_linewidth_cm': 45, 'fR': 0.18, 'gain_coeff': 1e-13, 'lo_phonon_cm': None, 'to_phonon_cm': None, 'references': 'Agrawal, Nonlinear Fiber Optics, 5th ed.'}, 'CdS': {'name': 'CdS', 'crystal': 'Wurtzite', 'bandgap_eV': 2.42, 'n2': 1.5e-18, 'raman_shift_cm': 305, 'raman_linewidth_cm': 12, 'fR': 0.35, 'gain_coeff': None, 'lo_phonon_cm': 302, 'to_phonon_cm': 293, 'references': 'Pankove, Optical Processes in Semiconductors'}, 'GaAs': {'name': 'GaAs', 'crystal': 'Zincblende', 'bandgap_eV': 1.42, 'n2': 2.5e-18, 'raman_shift_cm': 292, 'raman_linewidth_cm': 5, 'fR': 0.07, 'gain_coeff': None, 'lo_phonon_cm': 292, 'to_phonon_cm': 268, 'references': 'Adachi, Optical Properties of Crystalline and Amorphous Semiconductors'}, 'Diamond': {'name': 'Diamond', 'crystal': 'Diamond cubic', 'bandgap_eV': 5.5, 'n2': 1.1e-19, 'raman_shift_cm': 1332, 'raman_linewidth_cm': 4, 'fR': 0.0, 'gain_coeff': 0.11, 'lo_phonon_cm': None, 'to_phonon_cm': None, 'references': 'Ferrari, Raman spectroscopy of graphene and graphite'}, 'LiNbO3': {'name': 'LiNbO3', 'crystal': 'Rhombohedral', 'bandgap_eV': 3.7, 'n2': 3e-20, 'raman_shift_cm': 254, 'raman_linewidth_cm': 14, 'fR': 0.0, 'gain_coeff': None, 'lo_phonon_cm': None, 'to_phonon_cm': None, 'references': 'Fejer, Quasi-phase-matched nonlinear optics'}, 'As2Se3': {'name': 'As2Se3', 'crystal': 'Amorphous', 'bandgap_eV': 1.8, 'n2': 3.5e-18, 'raman_shift_cm': 310, 'raman_linewidth_cm': 60, 'fR': 0.55, 'gain_coeff': None, 'lo_phonon_cm': None, 'to_phonon_cm': None, 'references': 'Richardson, Chalcogenide glass fibers for nonlinear optics'}, 'Si': {'name': 'Si', 'crystal': 'Diamond cubic', 'bandgap_eV': 1.12, 'n2': 6e-19, 'raman_shift_cm': 520, 'raman_linewidth_cm': 4, 'fR': 0.0, 'gain_coeff': None, 'lo_phonon_cm': None, 'to_phonon_cm': None, 'references': 'Burstein, Infrared and Raman studies of silicon'}, 'Ge': {'name': 'Ge', 'crystal': 'Diamond cubic', 'bandgap_eV': 0.67, 'n2': 1.2e-18, 'raman_shift_cm': 300, 'raman_linewidth_cm': 8, 'fR': 0.0, 'gain_coeff': None, 'lo_phonon_cm': None, 'to_phonon_cm': None, 'references': 'Nakamura, Raman scattering in germanium'}, 'As2S3': {'name': 'As2S3', 'crystal': 'Amorphous', 'bandgap_eV': 2.0, 'n2': 4e-18, 'raman_shift_cm': 345, 'raman_linewidth_cm': 56, 'fR': 0.15, 'gain_coeff': 4.3e-12, 'lo_phonon_cm': None, 'to_phonon_cm': None, 'references': 'Xiong et al., Appl. Opt. 48, 5467 (2009); Slusher et al., JOSA B 21, 1146 (2004)'}, 'Si3N4': {'name': 'Si3N4', 'crystal': 'Amorphous/hexagonal', 'bandgap_eV': 4.9, 'n2': 2.4e-19, 'raman_shift_cm': 206, 'raman_linewidth_cm': 50, 'fR': None, 'gain_coeff': None, 'lo_phonon_cm': None, 'to_phonon_cm': None, 'references': 'Zymla et al., J. Raman Spectrosc. (2025); Lacava et al., Sci. Rep. 7, 41598 (2017)'}, 'Si3N4-Ligentec': {'name': 'Si3N4-Ligentec', 'crystal': 'Amorphous (LPCVD stoichiometric, Ligentec platform)', 'bandgap_eV': 4.9, 'n2': 2.4e-19, 'raman_shift_cm': 206, 'raman_linewidth_cm': 50, 'fR': None, 'gain_coeff': None, 'lo_phonon_cm': None, 'to_phonon_cm': None, 'references': 'Rehan et al., ACS Photonics (2025), arXiv:2501.10575 (n≈2.0 @1550nm); base Sellmeier fit Luke et al., Opt. Express 23, 22808 (2015)'}, 'SiC_4H': {'name': 'SiC_4H', 'crystal': 'Hexagonal (4H)', 'bandgap_eV': 3.23, 'n2': 8e-19, 'raman_shift_cm': 777, 'raman_linewidth_cm': 5, 'fR': 0.0, 'gain_coeff': None, 'lo_phonon_cm': 983, 'to_phonon_cm': 777, 'references': 'Feldman et al., Phys. Rev. 173, 787 (1968); Li et al., Phys. Rev. Appl. 19, 034083 (2023)'}, 'YAG': {'name': 'YAG', 'crystal': 'Cubic garnet', 'bandgap_eV': 6.5, 'n2': 7e-20, 'raman_shift_cm': 784, 'raman_linewidth_cm': 8, 'fR': 0.0, 'gain_coeff': None, 'lo_phonon_cm': None, 'to_phonon_cm': None, 'references': 'Hurrell et al., Phys. Rev. 173, 851 (1968); Lamaignere et al., Opt. Mater. X 8, 100068 (2020)'}, 'BaTiO3': {'name': 'BaTiO3', 'crystal': 'Tetragonal perovskite', 'bandgap_eV': 3.2, 'n2': 1.8e-18, 'raman_shift_cm': 520, 'raman_linewidth_cm': 45, 'fR': 0.0, 'gain_coeff': None, 'lo_phonon_cm': None, 'to_phonon_cm': None, 'references': 'Scalabrin et al., Phys. Status Solidi B 79, 731 (1977); Chaves et al., Phys. Rev. B 10, 3522 (1974)'}, 'ZBLAN': {'name': 'ZBLAN', 'crystal': 'Amorphous fluoride', 'bandgap_eV': 4.5, 'n2': 1.5e-20, 'raman_shift_cm': 580, 'raman_linewidth_cm': 23, 'fR': 0.06, 'gain_coeff': 4e-14, 'lo_phonon_cm': None, 'to_phonon_cm': None, 'references': 'Petersen et al., JOSA B 28, 2310 (2011); Yan et al., JOSA B 29, 238 (2012)'}, 'GaN': {'name': 'GaN', 'crystal': 'Wurtzite', 'bandgap_eV': 3.4, 'n2': 9e-19, 'raman_shift_cm': 568, 'raman_linewidth_cm': 4, 'fR': 0.0, 'gain_coeff': None, 'lo_phonon_cm': 736, 'to_phonon_cm': 532, 'references': 'Zeng et al., Appl. Sci. 10, 8814 (2020); Almeida et al., Photonics 6, 69 (2019)'}, 'AlN': {'name': 'AlN', 'crystal': 'Wurtzite', 'bandgap_eV': 6.2, 'n2': 2.3e-19, 'raman_shift_cm': 658, 'raman_linewidth_cm': 1, 'fR': 0.0, 'gain_coeff': None, 'lo_phonon_cm': 895, 'to_phonon_cm': 615, 'references': 'Pandit et al., J. Appl. Phys. 102, 113508 (2007); Jung, Tang, Nanophotonics 5, 264 (2016)'}, 'InP': {'name': 'InP', 'crystal': 'Zincblende', 'bandgap_eV': 1.34, 'n2': 2e-17, 'raman_shift_cm': 345, 'raman_linewidth_cm': 3, 'fR': 0.05, 'gain_coeff': None, 'lo_phonon_cm': 345, 'to_phonon_cm': 307, 'references': 'Artus et al., Phys. Rev. B 50, 11552 (1994); Mobini et al., J. Phys. Photonics (2026)'}, 'LiTaO3': {'name': 'LiTaO3', 'crystal': 'Rhombohedral', 'bandgap_eV': 4.0, 'n2': 3e-20, 'raman_shift_cm': 255, 'raman_linewidth_cm': 12, 'fR': 0.0, 'gain_coeff': None, 'lo_phonon_cm': None, 'to_phonon_cm': None, 'references': 'Raptis, Phys. Rev. B 38, 10007 (1988); Margueron et al., J. Appl. Phys. 111, 104105 (2012)'}, 'KTP': {'name': 'KTP', 'crystal': 'Orthorhombic (Pna2_1)', 'bandgap_eV': 3.5, 'n2': 5e-20, 'raman_shift_cm': 270, 'raman_linewidth_cm': 20, 'fR': 0.0, 'gain_coeff': None, 'lo_phonon_cm': None, 'to_phonon_cm': None, 'references': 'Neufeld et al., Crystals 13, 1423 (2023)'}, 'AlGaAs': {'name': 'AlGaAs', 'crystal': 'Zincblende', 'bandgap_eV': 1.65, 'n2': 2e-17, 'raman_shift_cm': 284, 'raman_linewidth_cm': 5, 'fR': None, 'gain_coeff': None, 'lo_phonon_cm': 284, 'to_phonon_cm': 262, 'references': 'Feng et al., Phys. Rev. B 47, 13466 (1993); Villeneuve et al., Appl. Phys. Lett. 62, 2465 (1993)'}, 'Al2O3': {'name': 'Al2O3', 'crystal': 'Corundum', 'bandgap_eV': 8.8, 'n2': 3.1e-20, 'raman_shift_cm': 418, 'raman_linewidth_cm': 5, 'fR': 0.0, 'gain_coeff': None, 'lo_phonon_cm': None, 'to_phonon_cm': None, 'references': 'Watson et al., J. Chem. Phys. 74, 2023 (1981); Major et al., Opt. Lett. 29, 602 (2004)'}, 'YLF': {'name': 'YLF', 'crystal': 'Scheelite (tetragonal)', 'bandgap_eV': 10.0, 'n2': 1.7e-20, 'raman_shift_cm': 262, 'raman_linewidth_cm': 5, 'fR': 0.0, 'gain_coeff': None, 'lo_phonon_cm': None, 'to_phonon_cm': None, 'references': 'Miller et al., J. Chem. Phys. 52, 4172 (1970); Salaun et al., J. Phys. Condens. Matter 9, 6941 (1997)'}, 'ZnO': {'name': 'ZnO', 'crystal': 'Wurtzite', 'bandgap_eV': 3.37, 'n2': -9e-19, 'raman_shift_cm': 439, 'raman_linewidth_cm': 7, 'fR': None, 'gain_coeff': None, 'lo_phonon_cm': 574, 'to_phonon_cm': 380, 'references': 'Cusco et al., Phys. Rev. B 75, 165202 (2007); Zhang et al., JOSA B 14, 1951 (1997)'}, 'CdTe': {'name': 'CdTe', 'crystal': 'Zincblende', 'bandgap_eV': 1.44, 'n2': -3e-17, 'raman_shift_cm': 166, 'raman_linewidth_cm': 15, 'fR': None, 'gain_coeff': None, 'lo_phonon_cm': 166, 'to_phonon_cm': 141, 'references': 'Tivanov et al., J. Mater. Sci. (2025); Sayadov et al., JOSA B 9, 405 (1992)'}, 'Ga2O3': {'name': 'Ga2O3', 'crystal': 'Monoclinic (beta)', 'bandgap_eV': 4.85, 'n2': 4e-19, 'raman_shift_cm': 767, 'raman_linewidth_cm': 5, 'fR': None, 'gain_coeff': None, 'lo_phonon_cm': None, 'to_phonon_cm': None, 'references': 'Kranert et al., Sci. Rep. 6, 35964 (2016); Sun et al., Appl. Phys. Lett. (2022)'}, 'LBO': {'name': 'LBO', 'crystal': 'Orthorhombic', 'bandgap_eV': 7.8, 'n2': 1e-20, 'raman_shift_cm': 938, 'raman_linewidth_cm': 15, 'fR': 0.0, 'gain_coeff': None, 'lo_phonon_cm': None, 'to_phonon_cm': None, 'references': 'Chen et al., JOSA B 6, 616 (1989)'}, 'AgGaS2': {'name': 'AgGaS2', 'crystal': 'Chalcopyrite (tetragonal)', 'bandgap_eV': 2.73, 'n2': 3e-18, 'raman_shift_cm': 295, 'raman_linewidth_cm': 5, 'fR': 0.0, 'gain_coeff': None, 'lo_phonon_cm': None, 'to_phonon_cm': None, 'references': 'Lockwood, Montgomery, J. Phys. C 8 (1975); Qiao et al., Opt. Mater. 119, 111300 (2021)'}, 'AgGaSe2': {'name': 'AgGaSe2', 'crystal': 'Chalcopyrite (tetragonal)', 'bandgap_eV': 1.82, 'n2': 5e-18, 'raman_shift_cm': 180, 'raman_linewidth_cm': 5, 'fR': 0.0, 'gain_coeff': None, 'lo_phonon_cm': None, 'to_phonon_cm': None, 'references': 'Miller et al., Phys. Status Solidi B 78, 569 (1976)'}, 'InGaAs': {'name': 'InGaAs', 'crystal': 'Zincblende', 'bandgap_eV': 0.75, 'n2': 5e-17, 'raman_shift_cm': 269, 'raman_linewidth_cm': 5, 'fR': None, 'gain_coeff': None, 'lo_phonon_cm': 269, 'to_phonon_cm': 255, 'references': 'Estrera et al., J. Appl. Phys. 72, 3692 (1992); Zhang et al., Appl. Phys. Lett. 123, 011103 (2023)'}, 'GeO2': {'name': 'GeO2', 'crystal': 'Amorphous', 'bandgap_eV': 5.5, 'n2': 6e-20, 'raman_shift_cm': 420, 'raman_linewidth_cm': 135, 'fR': 0.2, 'gain_coeff': None, 'lo_phonon_cm': None, 'to_phonon_cm': None, 'references': 'Davey et al., IEE Proc. J 136, 301 (1989); Bromage et al., IEEE Photon. Technol. Lett. 14, 24 (2002)'}, 'GeAsSe': {'name': 'GeAsSe', 'crystal': 'Amorphous', 'bandgap_eV': 1.6, 'n2': 6e-18, 'raman_shift_cm': 250, 'raman_linewidth_cm': 50, 'fR': 0.5, 'gain_coeff': None, 'lo_phonon_cm': None, 'to_phonon_cm': None, 'references': 'Richardson, Chalcogenide glass fibers for nonlinear optics; ~2× As2Se3 (Slusher et al., JOSA B 21, 1146)'}}

THORLABS_SUBSTRATE_MATERIALS module-attribute

THORLABS_SUBSTRATE_MATERIALS: dict[str, dict] = {'N-BK7': {'name': 'N-BK7', 'crystal': 'Borosilicate crown glass', 'bandgap_eV': None, 'n2': None, 'raman_shift_cm': None, 'raman_linewidth_cm': None, 'fR': 0.0, 'gain_coeff': None, 'lo_phonon_cm': None, 'to_phonon_cm': None, 'references': 'Thorlabs Optical Substrates; SCHOTT N-BK7 (refractiveindex.info)'}, 'N-SF11': {'name': 'N-SF11', 'crystal': 'Dense flint glass', 'bandgap_eV': None, 'n2': None, 'raman_shift_cm': None, 'raman_linewidth_cm': None, 'fR': 0.0, 'gain_coeff': None, 'lo_phonon_cm': None, 'to_phonon_cm': None, 'references': 'Thorlabs Optical Substrates; SCHOTT N-SF11 (refractiveindex.info)'}, 'N-F2': {'name': 'N-F2', 'crystal': 'Flint glass', 'bandgap_eV': None, 'n2': None, 'raman_shift_cm': None, 'raman_linewidth_cm': None, 'fR': 0.0, 'gain_coeff': None, 'lo_phonon_cm': None, 'to_phonon_cm': None, 'references': 'Thorlabs Optical Substrates; SCHOTT N-F2 (refractiveindex.info)'}, 'F2': {'name': 'F2', 'crystal': 'Flint glass', 'bandgap_eV': None, 'n2': None, 'raman_shift_cm': None, 'raman_linewidth_cm': None, 'fR': 0.0, 'gain_coeff': None, 'lo_phonon_cm': None, 'to_phonon_cm': None, 'references': 'Thorlabs Optical Substrates; SCHOTT F2 (refractiveindex.info)'}, 'CaF2': {'name': 'CaF2', 'crystal': 'Cubic (fluorite)', 'bandgap_eV': 12.1, 'n2': None, 'raman_shift_cm': None, 'raman_linewidth_cm': None, 'fR': 0.0, 'gain_coeff': None, 'lo_phonon_cm': None, 'to_phonon_cm': None, 'references': 'Thorlabs Optical Substrates; Daimon & Masumura, Appl. Opt. 41, 5275 (2002)'}, 'BaF2': {'name': 'BaF2', 'crystal': 'Cubic', 'bandgap_eV': 10.2, 'n2': None, 'raman_shift_cm': None, 'raman_linewidth_cm': None, 'fR': 0.0, 'gain_coeff': None, 'lo_phonon_cm': None, 'to_phonon_cm': None, 'references': 'Thorlabs Optical Substrates; Malitson, JOSA 54, 628 (1964)'}, 'MgF2': {'name': 'MgF2', 'crystal': 'Tetragonal (o-ray, c-axis oriented)', 'bandgap_eV': 12.0, 'n2': None, 'raman_shift_cm': None, 'raman_linewidth_cm': None, 'fR': 0.0, 'gain_coeff': None, 'lo_phonon_cm': None, 'to_phonon_cm': None, 'references': 'Thorlabs Optical Substrates; Dodge, Appl. Opt. 23, 1980 (1984)'}, 'ZnSe': {'name': 'ZnSe', 'crystal': 'Zincblende', 'bandgap_eV': 2.7, 'n2': None, 'raman_shift_cm': None, 'raman_linewidth_cm': None, 'fR': 0.0, 'gain_coeff': None, 'lo_phonon_cm': None, 'to_phonon_cm': None, 'references': 'Thorlabs Optical Substrates; Marple, J. Appl. Phys. 35, 539 (1964)'}, 'YVO4': {'name': 'YVO4', 'crystal': 'Tetragonal (o-ray)', 'bandgap_eV': None, 'n2': None, 'raman_shift_cm': None, 'raman_linewidth_cm': None, 'fR': 0.0, 'gain_coeff': None, 'lo_phonon_cm': None, 'to_phonon_cm': None, 'references': 'Thorlabs Optical Substrates; Birnbaum & DeShazer, NASA CR (1976)'}, 'KBr': {'name': 'KBr', 'crystal': 'Cubic', 'bandgap_eV': 7.5, 'n2': None, 'raman_shift_cm': None, 'raman_linewidth_cm': None, 'fR': 0.0, 'gain_coeff': None, 'lo_phonon_cm': None, 'to_phonon_cm': None, 'references': 'Thorlabs Optical Substrates; Li, J. Phys. Chem. Ref. Data 5, 329 (1976)'}, 'Zerodur': {'name': 'Zerodur', 'crystal': 'Glass ceramic', 'bandgap_eV': None, 'n2': None, 'raman_shift_cm': None, 'raman_linewidth_cm': None, 'fR': 0.0, 'gain_coeff': None, 'lo_phonon_cm': None, 'to_phonon_cm': None, 'references': 'Thorlabs Optical Substrates; SCHOTT ZERODUR (refractiveindex.info)'}, 'PMMA': {'name': 'PMMA', 'crystal': 'Amorphous (acrylic)', 'bandgap_eV': None, 'n2': None, 'raman_shift_cm': None, 'raman_linewidth_cm': None, 'fR': 0.0, 'gain_coeff': None, 'lo_phonon_cm': None, 'to_phonon_cm': None, 'references': 'Thorlabs Optical Substrates; Szczurowski (refractiveindex.info)'}}

MaterialComparison

Multi-material Raman comparison overlay.

Overlays Raman spectra, time-domain responses, and frequency-domain responses for multiple materials on shared axes for direct comparison.

Attributes:

Name Type Description
materials list[RamanSpec]

List of RamanSpec instances to compare.

materials class-attribute instance-attribute

materials: list[RamanSpec] = Field(default_factory=list)

add

add(spec: RamanSpec) -> None

Add a material, replacing if a material with the same name exists.

Parameters:

Name Type Description Default
spec RamanSpec

Material to add.

required

remove

remove(name: str) -> None

Remove a material by name.

Parameters:

Name Type Description Default
name str

Material name to remove.

required

clear

clear() -> None

Remove all materials.

plot_spectra_overlay

plot_spectra_overlay(backend: Literal['matplotlib', 'plotly'] = 'matplotlib', shift_range_cm: float = 200, n_points: int = 1000, figsize: tuple[float, float] | None = None)

Overlay Raman spectra for all materials.

Each material is plotted as a Lorentzian lineshape centered at its Raman shift, normalized to unit peak height.

Parameters:

Name Type Description Default
backend 'matplotlib' or 'plotly'
'matplotlib'
shift_range_cm Range around 0 to plot (cm⁻¹)
200
n_points Number of points
1000
figsize Figure size for matplotlib
None

Returns:

Type Description
fig or None — None if no materials.

plot_response_overlay

plot_response_overlay(backend: Literal['matplotlib', 'plotly'] = 'matplotlib', grid: TemporalGrid | None = None, figsize: tuple[float, float] | None = None, t_range_ps: tuple[float, float] | None = None)

Overlay h_R(t) for all materials.

Computes the delayed Raman response for each material and overlays them on a shared time axis.

Parameters:

Name Type Description Default
backend 'matplotlib' or 'plotly'
'matplotlib'
grid TemporalGrid — shared time grid. Auto-derived if None.
None
figsize Figure size for matplotlib
None
t_range_ps Time range in picoseconds as (t_min, t_max). Overrides grid.
None

Returns:

Type Description
fig or None — None if no materials.

plot_frequency_overlay

plot_frequency_overlay(backend: Literal['matplotlib', 'plotly'] = 'matplotlib', grid: TemporalGrid | None = None, figsize: tuple[float, float] | None = None)

Overlay Im(H(Ω)) for all materials.

The imaginary part of the Fourier transform gives the Raman gain spectrum. Overlapping multiple materials shows how their gain profiles compare.

Parameters:

Name Type Description Default
backend 'matplotlib' or 'plotly'
'matplotlib'
grid TemporalGrid — shared time grid. Auto-derived if None.
None
figsize Figure size for matplotlib
None

Returns:

Type Description
fig or None — None if no materials.

comparison_table

comparison_table() -> str

Text table comparing Raman properties across all materials.

Returns:

Type Description
str — formatted comparison table.

plot_all

plot_all(backend: Literal['matplotlib', 'plotly'] = 'matplotlib', grid: TemporalGrid | None = None, figsize: tuple[float, float] | None = None)

Full comparison: spectra + response + frequency for all materials.

3-panel layout: 1. Raman spectra overlay 2. Time-domain response overlay 3. Frequency-domain gain spectrum overlay

Parameters:

Name Type Description Default
backend 'matplotlib' or 'plotly'
'matplotlib'
grid TemporalGrid — shared time grid. Auto-derived if None.
None
figsize Figure size for matplotlib
None

Returns:

Type Description
fig or None — None if no materials.

PumpWavelengthExplorer

Stokes/Anti-Stokes analysis vs pump wavelength.

Demonstrates that the Raman frequency shift is constant, but the corresponding wavelength shift depends on the pump wavelength.

This is the key educational insight of Layer 5: equal frequency shifts produce unequal wavelength shifts because λ = c/ν (hyperbolic relationship).

Attributes:

Name Type Description
spec RamanSpec

Layer 1 material properties.

spec instance-attribute

spec: RamanSpec

pump_to_stokes

pump_to_stokes(pump_wl: Wavelength) -> Wavelength

Stokes wavelength for a given pump wavelength.

ν_stokes = ν_pump − ν_Raman λ_stokes = c / ν_stokes

Parameters:

Name Type Description Default
pump_wl Pump wavelength.
required

Returns:

Type Description
Wavelength — Stokes wavelength.

pump_to_anti_stokes

pump_to_anti_stokes(pump_wl: Wavelength) -> Wavelength

Anti-Stokes wavelength for a given pump wavelength.

ν_anti_stokes = ν_pump + ν_Raman λ_anti_stokes = c / ν_anti_stokes

Parameters:

Name Type Description Default
pump_wl Pump wavelength.
required

Returns:

Type Description
Wavelength — Anti-Stokes wavelength.

plot_frequency_axis

plot_frequency_axis(pump_wl: Wavelength, backend: Literal['matplotlib', 'plotly'] = 'matplotlib', freq_range_THz: float = 50, figsize: tuple[float, float] | None = None)

Plot frequency axis: Anti-Stokes | Pump | Stokes (equidistant).

The frequency axis shows equal spacing between Anti-Stokes, Pump, and Stokes because the Raman shift is a constant frequency.

Parameters:

Name Type Description Default
pump_wl Pump wavelength.
required
backend 'matplotlib' or 'plotly'
'matplotlib'
freq_range_THz Range in THz to display on each side of pump.
50
figsize Figure size for matplotlib.
None

plot_wavelength_axis

plot_wavelength_axis(pump_wl: Wavelength, backend: Literal['matplotlib', 'plotly'] = 'matplotlib', wl_range_nm: float = 200, figsize: tuple[float, float] | None = None)

Plot wavelength axis: Stokes — Pump — Anti-Stokes (unequal spacing).

Demonstrates that equal frequency shifts produce unequal wavelength shifts due to the hyperbolic λ = c/ν relationship.

Parameters:

Name Type Description Default
pump_wl Pump wavelength.
required
backend 'matplotlib' or 'plotly'
'matplotlib'
wl_range_nm Range in nm to display around pump.
200
figsize Figure size for matplotlib.
None

plot_both

plot_both(pump_wl: Wavelength, backend: Literal['matplotlib', 'plotly'] = 'matplotlib', freq_range_THz: float = 50, wl_range_nm: float = 200, figsize: tuple[float, float] | None = None)

Side-by-side: frequency axis vs wavelength axis.

Parameters:

Name Type Description Default
pump_wl Pump wavelength.
required
backend 'matplotlib' or 'plotly'
'matplotlib'
freq_range_THz Frequency range in THz.
50
wl_range_nm Wavelength range in nm.
200
figsize Figure size for matplotlib.
None

plot_vs_pump

plot_vs_pump(pump_range_um: tuple[float, float] = (0.4, 2.0), n_points: int = 100, backend: Literal['matplotlib', 'plotly'] = 'matplotlib', figsize: tuple[float, float] | None = None)

Sweep pump wavelength: show how Stokes/Anti-Stokes shift changes.

Parameters:

Name Type Description Default
pump_range_um (min, max) pump wavelength in μm.
(0.4, 2.0)
n_points Number of pump wavelengths to sweep.
100
backend 'matplotlib' or 'plotly'
'matplotlib'
figsize Figure size for matplotlib.
None

RamanFrequencyResponse

Frequency-domain Raman response H(Ω) = F{h_R(t)}.

Connects time-domain physics to measured Raman spectra via FFT.

Attributes:

Name Type Description
response RamanResponse

Layer 2 time-domain response.

grid TemporalGrid

Frequency grid (from the temporal grid's fft).

response instance-attribute

response: RamanResponse

grid class-attribute instance-attribute

grid: TemporalGrid | None = None

H property

H: NDArray

Complex frequency response H(Ω).

H_real property

H_real: NDArray

Real part Re(H(Ω)).

H_imag property

H_imag: NDArray

Imaginary part Im(H(Ω)).

H_magnitude property

H_magnitude: NDArray

Magnitude |H(Ω)|.

H_phase property

H_phase: NDArray

Phase ∠H(Ω).

resonance_frequency_THz property

resonance_frequency_THz: float

Resonance frequency in THz (peak of |Im(H)|).

resonance_FWHM_THz property

resonance_FWHM_THz: float

FWHM of the resonance in THz.

quality_factor property

quality_factor: float

Quality factor Q = f_res / FWHM.

plot_real

plot_real(backend: Literal['matplotlib', 'plotly'] = 'matplotlib', figsize: tuple[float, float] | None = None)

Plot Re(H(Ω)).

plot_imag

plot_imag(backend: Literal['matplotlib', 'plotly'] = 'matplotlib', figsize: tuple[float, float] | None = None)

Plot Im(H(Ω)) — the Raman gain spectrum.

plot_magnitude

plot_magnitude(backend: Literal['matplotlib', 'plotly'] = 'matplotlib', figsize: tuple[float, float] | None = None)

Plot |H(Ω)|.

plot_phase

plot_phase(backend: Literal['matplotlib', 'plotly'] = 'matplotlib', figsize: tuple[float, float] | None = None)

Plot ∠H(Ω).

plot_all

plot_all(backend: Literal['matplotlib', 'plotly'] = 'matplotlib', figsize: tuple[float, float] | None = None)

4-panel plot: Re, Im, |H|, phase.

RamanPulseInteraction

Pulse interaction with Raman-active medium.

Computes the nonlinear polarization P_NL(t) = n₂ · (R(t) ⊗ I(t)) where I(t) = |E(t)|² is the pulse intensity and R(t) is the combined Raman response from Layer 2.

Attributes:

Name Type Description
pulse Wave

Input pulse (from pulse.py).

response RamanResponse

Layer 2 Raman response function.

spec RamanSpec

Layer 1 material properties (provides n₂).

n2 float

Nonlinear refractive index n₂ (m²/W). Overrides spec.n2 if set.

grid TemporalGrid

Time grid. Defaults to pulse.grid if not provided.

pulse instance-attribute

pulse: Wave

response instance-attribute

response: RamanResponse

spec instance-attribute

spec: RamanSpec

n2 class-attribute instance-attribute

n2: float | None = None

grid class-attribute instance-attribute

grid: TemporalGrid | None = None

nonlinear_polarization property

nonlinear_polarization: NDArray

Nonlinear polarization P_NL(t) = n₂ · (R(t) ⊗ I(t)).

Computed via FFT-based convolution on the FFTW backend (:func:photonics_helper._fftw.convolve_full), which reproduces scipy.signal.fftconvolve(..., mode='full'). The result is cropped to the central N points to match the grid.

Returns:

Type Description
NDArray — nonlinear polarization values.

plot_interaction

plot_interaction(backend: Literal['matplotlib', 'plotly'] = 'matplotlib', figsize: tuple[float, float] | None = None, t_range_ps: tuple[float, float] | None = None)

4-panel plot: input pulse, Raman response, delayed polarization, output.

Parameters:

Name Type Description Default
backend 'matplotlib' or 'plotly'
'matplotlib'
figsize Figure size for matplotlib
None
t_range_ps Time range in picoseconds as (t_min, t_max). Overrides grid.
None

animate

animate(backend: Literal['matplotlib', 'plotly'] = 'matplotlib', frames: int = 20, figsize: tuple[float, float] | None = None)

Animation: pulse enters → instantaneous response → lattice oscillation → pulse exits.

Shows the time evolution of the pulse and the induced nonlinear polarization.

Parameters:

Name Type Description Default
backend 'matplotlib' or 'plotly'
'matplotlib'
frames number of animation frames (default 20)
20
figsize figure size for matplotlib
None

RamanResponse

Time-domain Raman response function h_R(t).

Implements the standard Silica model (Agrawal): h_R(t) = (τ1² + τ2²) / (τ1·τ2²) · exp(-t/τ2) · sin(t/τ1) for t ≥ 0 h_R(t) = 0 for t < 0

Combined response: R(t) = (1 - fR)·δ(t) + fR·h_R(t) where δ(t) is approximated as a narrow Gaussian.

Attributes:

Name Type Description
spec RamanSpec

Material Raman properties.

fR float

Raman response fraction. Overrides spec.fR if set.

tau1 float

Oscillation period (s). Auto-derived from Raman shift if None.

tau2 float

Damping time (s). Auto-derived from linewidth if None.

grid TemporalGrid

Time grid for computations.

spec instance-attribute

spec: RamanSpec

fR class-attribute instance-attribute

fR: float | None = None

tau1 class-attribute instance-attribute

tau1: float | None = None

tau2 class-attribute instance-attribute

tau2: float | None = None

grid class-attribute instance-attribute

grid: TemporalGrid | None = None

h_R

h_R(t: NDArray) -> NDArray

Un-scaled delayed response h_R(t) (causal, unit integral).

Public entry point of the delayed-response contract the GNLSE consumes, so single-mode (this class) and multi-mode (:class:~photonics_helper.phonon.PhononResponse) responses are interchangeable. Equivalent to :meth:_h_R, which is kept for backwards compatibility.

References

Agrawal, Nonlinear Fiber Optics, 5th ed., Sec. 2.3.2; Blow & Wood, IEEE J. Quantum Electron. 25, 2665 (1989).

instantaneous_response

instantaneous_response(t: NDArray | None = None) -> NDArray

Electronic Kerr response: (1 - fR)·δ(t).

δ(t) approximated as a narrow Gaussian: exp(-t²/(2ε²)) / (ε·√(2π)).

Parameters:

Name Type Description Default
t array of time values (s). If None, uses self.grid.t.
None

Returns:

Type Description
NDArray — instantaneous response values.

delayed_response

delayed_response(t: NDArray | None = None) -> NDArray

Lattice oscillation: fR·h_R(t).

Parameters:

Name Type Description Default
t array of time values (s). If None, uses self.grid.t.
None

Returns:

Type Description
NDArray — delayed (Raman) response values.

combined_response

combined_response(t: NDArray | None = None) -> NDArray

Total Raman response R(t) = (1-fR)δ(t) + fR·h_R(t).

Parameters:

Name Type Description Default
t array of time values (s). If None, uses self.grid.t.
None

Returns:

Type Description
NDArray — combined response values.

plot_components

plot_components(backend: Literal['matplotlib', 'plotly'] = 'matplotlib', figsize: tuple[float, float] | None = None, t_range_ps: tuple[float, float] | None = None)

3-panel plot: instantaneous, delayed, combined response.

Parameters:

Name Type Description Default
backend 'matplotlib' or 'plotly'
'matplotlib'
figsize Figure size for matplotlib
None
t_range_ps Time range in picoseconds as (t_min, t_max). Overrides grid.
None

RamanSpec

Material Raman scattering properties.

Stores Raman parameters and auto-derives derived quantities.

Attributes:

Name Type Description
name Material name.
crystal Crystal structure (e.g. "Wurtzite", "Diamond cubic").
bandgap_eV Bandgap energy in eV.
n2 Nonlinear refractive index n₂ (m²/W).
raman_shift_cm Raman shift in cm⁻¹.
raman_linewidth_cm Raman linewidth (FWHM) in cm⁻¹.
fR Raman response fraction (0 to 1).
gain_coeff Raman gain coefficient (m/GW).
tau1 Oscillation period (s). Auto-derived if None.
tau2 Damping time (s). Auto-derived if None.
alpha Silica model parameter α (default 0.52).
lo_phonon_cm LO phonon wavenumber (cm⁻¹).
to_phonon_cm TO phonon wavenumber (cm⁻¹).
references Source citation.
phonon_modes List of PhononMode for multi-mode Raman materials.

name instance-attribute

name: str

raman_shift_cm class-attribute instance-attribute

raman_shift_cm: float | None = None

raman_linewidth_cm class-attribute instance-attribute

raman_linewidth_cm: float | None = None

crystal class-attribute instance-attribute

crystal: str | None = None

bandgap_eV class-attribute instance-attribute

bandgap_eV: Energy | None = None

n2 class-attribute instance-attribute

n2: float | None = None

fR class-attribute instance-attribute

fR: float | None = None

gain_coeff class-attribute instance-attribute

gain_coeff: float | None = None

tau1 class-attribute instance-attribute

tau1: Time | None = None

tau2 class-attribute instance-attribute

tau2: Time | None = None

alpha class-attribute instance-attribute

alpha: float = 0.52

lo_phonon_cm class-attribute instance-attribute

lo_phonon_cm: float | None = None

to_phonon_cm class-attribute instance-attribute

to_phonon_cm: float | None = None

references class-attribute instance-attribute

references: str | None = None

phonon_modes class-attribute instance-attribute

phonon_modes: list | None = None

raman_shift_Hz cached property

raman_shift_Hz: float

Raman shift in Hz.

raman_shift_THz cached property

raman_shift_THz: float

Raman shift in THz.

raman_shift_omega cached property

raman_shift_omega: float

Raman shift in rad/s.

linewidth_Hz cached property

linewidth_Hz: float

Raman linewidth (FWHM) in Hz.

linewidth_THz cached property

linewidth_THz: float

Raman linewidth (FWHM) in THz.

quality_factor cached property

quality_factor: float

Quality factor Q = shift / linewidth.

phonon_response property

phonon_response

Multi-mode phonon response, or None if no modes configured.

Returns:

Type Description
PhononResponse or None

stokes_wavelength

stokes_wavelength(pump_wl: Wavelength) -> Wavelength

Stokes wavelength for a given pump wavelength.

ν_stokes = ν_pump - ν_Raman λ_stokes = c / ν_stokes

anti_stokes_wavelength

anti_stokes_wavelength(pump_wl: Wavelength) -> Wavelength

Anti-Stokes wavelength for a given pump wavelength.

ν_anti_stokes = ν_pump + ν_Raman λ_anti_stokes = c / ν_anti_stokes

multi_stokes_wavelengths

multi_stokes_wavelengths(pump_wl) -> list

Stokes wavelength for each phonon mode.

Parameters:

Name Type Description Default
pump_wl Wavelength

Pump wavelength.

required

Returns:

Type Description
list[Wavelength]

Stokes wavelengths, one per mode.

summary

summary() -> str

Text summary of material Raman properties.

nk

nk(wavelength_um: float, source: str | None = None) -> complex

Interpolated complex refractive index at wavelength (μm).

Returns n + i·k from the nk_data table, or falls back to Sellmeier interpolation if tabulated data is absent.

Parameters:

Name Type Description Default
wavelength_um Wavelength in μm
required
source Optional ``material–author`` provenance key. When the material

has several tabulated datasets, one MUST be selected; when omitted and a single dataset exists it is used automatically.

None

Returns:

Name Type Description
complex n + i·k

Raises:

Type Description
ValueError : If no data available or wavelength outside valid range

nk_from_sellmeier

nk_from_sellmeier(wavelength_um: float, sellmeier_data: dict | None = None) -> complex

Compute n + ik from stored Sellmeier coefficients.

Parameters:

Name Type Description Default
wavelength_um Wavelength in μm
required
sellmeier_data Dict with keys: form, a0, coefficients, wavelengths, valid_from_um, valid_to_um
       If None, fetches from database
None

Returns:

Name Type Description
complex n + i·0 (k=0 for transparent region)

Raises:

Type Description
ValueError : If wavelength outside valid range or no data available

plot_spectrum

plot_spectrum(backend: Literal['matplotlib', 'plotly'] = 'matplotlib', shift_range_cm: float = 200, n_points: int = 1000, figsize: tuple[float, float] | None = None)

Plot Raman intensity vs Raman shift.

Parameters:

Name Type Description Default
backend 'matplotlib' or 'plotly'
'matplotlib'
shift_range_cm Range around 0 to plot (cm⁻¹)
200
n_points Number of points
1000
figsize Figure size for matplotlib
None

plot_phonons

plot_phonons(backend: Literal['matplotlib', 'plotly'] = 'matplotlib', figsize: tuple[float, float] | None = None)

Plot Raman-active phonon modes.

Displays LO, TO, and other Raman-active modes if available.

from_database classmethod

from_database(name: str, fallback: dict | None = None, db_path: Path | None = None) -> RamanSpec

Create RamanSpec from SQLite database or fallback.

Queries materials.db first, then falls back to the hardcoded RAMAN_MATERIALS dict, and finally to the provided fallback dict.

Parameters:

Name Type Description Default
name Material name
required
fallback Optional dict of fallback values if not in DB
None
db_path Optional explicit path to SQLite database
None

model_fields classmethod

model_fields() -> dict

Pydantic v2-style field introspection.

RamanSpec is a pydantic.dataclasses.dataclass, not a BaseModel, so the v2 model_fields attribute is absent. This classmethod provides the same interface by returning the dataclass fields dict, so callers can write RamanSpec.model_fields() uniformly across pydantic v1/v2 styles.

app

app() -> dash.Dash

Build the standalone Raman Explorer Dash app.

Returns:

Type Description
dash.Dash — configured Dash application object.
Notes

Requires dash to be installed. Run with::

if __name__ == "__main__":
    app().run(debug=True)