solprop.optics#
Linear optical elements applied to a pulse outside a propagation.
Every element is a transfer function: a callable H(omega) giving the complex
amplitude response in the optics convention of docs/dev/conventions.md section 2,
so that a spectrum is multiplied by
the group delay is \(+d\varphi/d\omega\), and a positive second derivative chirps a
pulse positively, as in any textbook. A spectrum in the FFT convention needs
exp(-i phi) instead; that crossing is made once, in stored_factor(), through
solprop.fourier.to_internal(). A transfer function is diagonal in frequency, so it
commutes with the half-window origin shift of a stored spectrum and the conjugation is
all the crossing needs.
The elements are TaylorPhase (a polynomial spectral phase: GDD, TOD, …),
Material (a thickness of glass, or a path through a gas),
ChirpedMirror (reflections from a dispersive mirror known by its measured
group-delay dispersion), GratingPair, PrismPair and Chain.
docs/guide/workflows/compression.md describes each and how the compressors in
solprop.processing.compression use them.
Module Attributes
Functions
|
Return the external Brewster incidence angle in air. |
|
Return the apex angle for Brewster entry and minimum deviation. |
Return the names of the shipped chirped-mirror data sets. |
|
|
Return the signed Littrow incidence angle of a reflection grating. |
|
Return the factor that applies a transfer function to a stored spectrum. |
|
Return a Taylor spectral phase, in the optics convention. |
Classes
|
Several elements in series. |
|
Reflections from a dispersive mirror known by its measured dispersion. |
|
Apply the dispersion of parallel reflection gratings in air. |
|
A thickness of glass, or a path through a gas. |
|
Specify fixed first-prism geometry and two second-prism stage coordinates. |
|
Apply the exact central-ray dispersion of two identical prisms in air. |
|
Report central-ray paths for one traversal through two ideal wedges. |
|
A polynomial spectral phase about a reference wavelength. |
|
A linear optical element, as its complex amplitude response. |
- class solprop.optics.Chain(elements)[source]#
Bases:
DisplayedSeveral elements in series.
- Attributes:
- elementssequence of TransferFunction
The elements; their order does not matter, since each is diagonal in frequency.
Examples
>>> import numpy as np >>> from solprop.optics import Chain, TaylorPhase >>> pair = Chain((TaylorPhase((0, 0, 40e-30), 800e-9), ... TaylorPhase((0, 0, -40e-30), 800e-9))) >>> bool(np.allclose(pair(np.linspace(2e15, 3e15, 7)), 1.0)) True
- elements: Sequence[TransferFunction]#
- class solprop.optics.ChirpedMirror(omega, phase, reflectivity_omega, amplitude, band, reflections=1, name='')[source]#
Bases:
DisplayedReflections from a dispersive mirror known by its measured dispersion.
One reflection multiplies the spectrum by \(\sqrt{R(\omega)}\,e^{+i\varphi(\omega)}\,W(\omega)\), where \(\varphi\) is the double integral of the group-delay dispersion over angular frequency with its constant and linear parts removed (an arbitrary phase and an overall delay), and \(W\) is a Planck taper to zero outside the band the data are trusted on. Build one with
from_data()orlookup(); choose the number of bounces withbounces().- Attributes:
- omeganumpy.ndarray
Angular frequencies of the phase samples in rad/s, ascending.
- phasenumpy.ndarray
Phase per reflection in rad on omega.
- reflectivity_omeganumpy.ndarray
Angular frequencies of the reflectivity samples, ascending; empty for a phase-only mirror.
- amplitudenumpy.ndarray
Amplitude reflectivity
sqrt(R)on reflectivity_omega.- bandtuple of float
The taper’s four wavelengths in m: zero, one, one, zero.
- reflectionsint
Number of reflections. Negative is the phase-only inverse of that many: the amplitude is left alone inside the band and, like the forward mirror, zero outside it.
- namestr
A label for printing.
Examples
>>> from solprop.optics import ChirpedMirror >>> ChirpedMirror.lookup("PC70").bounces(4).reflections 4
- amplitude: Float[ndarray, 'n_reflectivity']#
- bounces(reflections)[source]#
Return the same mirror with another number of reflections.
- Parameters:
- reflectionsint
Number of reflections; negative for the phase-only inverse.
- Returns:
- ChirpedMirror
A copy sharing the data.
- classmethod from_data(wavelength, reflectivity, *, gdd=None, group_delay=None, reference_wavelength, band, taper_width=2e-08, fit_order=5, fit_window=None, name='')[source]#
Build a mirror from a data sheet’s columns.
- Parameters:
- wavelengthnumpy.ndarray
Wavelengths of the samples in m, strictly monotonic.
- reflectivitynumpy.ndarray or None
Power reflectivity per reflection in [0, 1] on wavelength, or
Nonefor a phase-only mirror.- gddnumpy.ndarray or None, optional
Group-delay dispersion per reflection in s^2. Exactly one of this and group_delay.
- group_delaynumpy.ndarray or None, optional
Group delay per reflection in s.
- reference_wavelengthfloat
Wavelength about which the constant and linear phase are removed, m.
- bandtuple of float
Shortest and longest wavelength in m the mirror is used over.
- taper_widthfloat, optional
Width in m of the taper to zero outside band.
- fit_orderint, optional
Order of the polynomial fitted to the integrated phase, of which only the constant and linear terms are subtracted.
- fit_windowtuple of float or None, optional
Angular-frequency window of that fit in rad/s;
Noneis all the data.- namestr, optional
A label.
- Returns:
- ChirpedMirror
One reflection; see
bounces().
- Raises:
- MaterialError
If both or neither dispersion column is given, a reflectivity lies outside [0, 1], or the wavelength axis is not monotonic.
Examples
>>> import numpy as np >>> from solprop.optics import ChirpedMirror >>> wavelength = np.linspace(600e-9, 1000e-9, 401) >>> mirror = ChirpedMirror.from_data( ... wavelength, None, gdd=np.full(401, -50e-30), ... reference_wavelength=800e-9, band=(650e-9, 950e-9)) >>> f"{mirror.gdd(np.array([2.355e15]))[0] * 1e30:.1f}" '-50.0'
- gdd(omega)[source]#
Return the group-delay dispersion of one reflection.
- Parameters:
- omeganumpy.ndarray
Angular frequencies in rad/s inside the data.
- Returns:
- numpy.ndarray
The second derivative of the stored phase in s^2; NaN outside the data.
- group_delay(omega)[source]#
Return the group delay of one reflection, less the removed constant.
- Parameters:
- omeganumpy.ndarray
Angular frequencies in rad/s inside the data.
- Returns:
- numpy.ndarray
The first derivative of the stored phase in s; NaN outside the data.
- classmethod lookup(name)[source]#
Return one reflection from a shipped data set.
- Parameters:
- namestr
One of
chirped_mirrors().
- Returns:
- ChirpedMirror
The mirror, reduced from its data file with the recorded reference wavelength, fit order and window, and band.
- Raises:
- MaterialError
If the name is unknown.
Examples
>>> from solprop.optics import ChirpedMirror >>> ChirpedMirror.lookup("HD120").name 'HD120'
- omega: Float[ndarray, 'n_phase']#
- phase: Float[ndarray, 'n_phase']#
- reflectivity_omega: Float[ndarray, 'n_reflectivity']#
- class solprop.optics.GratingPair(line_density, separation, incidence_angle, wavelength, order=-1, double_pass=True, band=None)[source]#
Bases:
DisplayedApply the dispersion of parallel reflection gratings in air.
Include the groove phase and remove phase and group delay at wavelength. The model describes sampled diffraction orders, with no efficiency, aperture, polarisation or spatial propagation. See the compression manual for Treacy’s construction and the meaning of a compensating return pass.
- Attributes:
- line_densityfloat
Grooves per metre, finite and positive.
- separationfloat
Normal distance between the grating surfaces in m, finite and nonnegative.
- incidence_anglefloat
Signed incidence in rad, strictly between -pi/2 and pi/2.
- wavelengthfloat
Explicit vacuum reference wavelength in m, finite and positive.
- orderint
Nonzero signed diffraction order, -1 by default.
- double_passbool
Two traversals (four diffractions) if true; one traversal otherwise.
- bandtuple of float or None
Fixed ascending vacuum wavelength band in m containing wavelength. The transfer is zero outside it. Endpoints and evaluated bins are checked; no continuous validity certificate is implied.
- Raises:
- MaterialError
If the parameters or fixed band are invalid.
- OpticsGeometryError
If an evaluated order is not real or is grazing.
- phase(omega)[source]#
Return phase after removing reference phase and group delay.
- Parameters:
- omegaarray_like
Positive in-band angular frequencies in rad/s, shape
(n_omega,).
- Returns:
- numpy.ndarray
Optics-convention residual phase in rad, shape
(n_omega,).
- Raises:
- MaterialError
If frequencies are invalid or the phase exceeds floating-point range.
- OpticsGeometryError
If any requested diffraction order is unavailable or grazing.
- class solprop.optics.Material(medium, thickness, wavelength=None, loss=False, pressure=None, temperature=293.15)[source]#
Bases:
DisplayedA thickness of glass, or a path through a gas.
\(H = \exp\{+i[\beta(\omega) - \beta_1(\omega_0)(\omega-\omega_0)]L\}\) with \(\beta = \omega\,{\rm Re}\,n/c\). The group delay at the reference wavelength is removed so that the pulse stays in its window; the constant \(\beta_0\) is kept, so the carrier-envelope phase does move with thickness.
- Attributes:
- mediumGlassIndex, Gas, str or Mixture
A glass model, a glass name (
solprop.physdata.glasses.glass(), optmat’s recommended model), a built-in gas (which needs pressure, and becomes its one-populationMixtureunder optmat’s models), or a mixture (which carries its own).- thicknessfloat
Path length in m. Negative removes material.
- wavelengthfloat or None
Wavelength at which the group delay is removed, m;
Nonekeeps it, and the pulse leaves its window after a few millimetres of glass.- lossbool
Whether to apply the absorption
exp(-omega Im(n) L / c). Off by default, which makes the element phase-only: right for a transparent window, wrong near an absorption edge.- pressurefloat or None
Gas pressure in bar; required for a built-in gas and refused otherwise.
- temperaturefloat
Gas temperature in K; ignored for a glass and a mixture.
Examples
>>> import numpy as np >>> from solprop.optics import Material >>> window = Material("SiO2", 1e-3, 800e-9) >>> response = window(2 * np.pi * 299792458.0 / np.array([700e-9, 900e-9])) >>> bool(np.allclose(np.abs(response), 1.0)) True
- medium: GlassIndex | Gas | str | Mixture#
- solprop.optics.Medium = solprop.physdata.glasses.GlassIndex | solprop.physdata.gases.Gas | str | solprop.physdata.mixtures.Mixture#
What a
Materialis made of: a glass model or name, a gas, or a mixture.
- class solprop.optics.PrismGeometry(separation, insertion, first_face_distance, apex_angle, incidence_angle)[source]#
Bases:
DisplayedSpecify fixed first-prism geometry and two second-prism stage coordinates.
The first apex is (0, 0), with its base horizontal below it. The inverted second apex is
R*u0 + (0, -H), whereu0is the reference inter-prism ray. Increasing insertion moves only the second prism down; increasing separation moves it alongu0. Neither coordinate is the physical tip distance.- Attributes:
- separationfloat
Stage coordinate R in m from formal zero insertion, finite and nonnegative.
- insertionfloat
Second-prism displacement H perpendicular to its base in m, nonnegative.
- first_face_distancefloat
Distance a along the first entry face from its apex in m, finite and positive.
- apex_anglefloat
Common apex angle in rad, strictly between zero and pi.
- incidence_anglefloat
Fixed external incidence in rad, strictly between zero and pi/2.
- Raises:
- MaterialError
If a length or angle is outside its domain. Ray feasibility is checked by
PrismPair; zero insertion with positive a does not describe a ray.
- class solprop.optics.PrismPair(medium, geometry, wavelength, double_pass=True, band=None)[source]#
Bases:
DisplayedApply the exact central-ray dispersion of two identical prisms in air.
Remove phase and analytic group delay at the explicit reference wavelength. Glass dispersion is already in the wavefront phase: do not add a separate slab. Use only the real index; loss, finite bases, apertures and beam clearance are outside this model. A single traversal retains spatial chirp. Doubling assumes a compensating return or four-prism arrangement, not an arbitrary return mirror.
- Attributes:
- mediumGlassIndex or str
Glass model or name in the existing glass registry; real index must exceed one.
- geometryPrismGeometry
Fixed first prism, incidence and apex angle, and second-prism R and H in m.
- wavelengthfloat
Explicit vacuum reference wavelength in m, finite and positive.
- double_passbool
Double the pair phase if true, the default.
- bandtuple of float or None
Fixed ascending vacuum wavelength band in m containing the reference. The response is zero outside it. Check endpoints and every evaluated bin; this does not prove validity between samples for an arbitrary index model.
- Raises:
- MaterialError
If a parameter, band or material model is invalid.
- OpticsGeometryError
If a sampled reference, endpoint or requested ray is infeasible.
- property apex_distance: float[source]#
Return the physical tip-to-tip distance in metres.
- Returns:
- float
norm(R*u0 + (0, -H)), which changes when either stage moves.
- geometry: PrismGeometry#
- medium: GlassIndex | str#
- phase(omega)[source]#
Return wavefront phase with reference phase and group delay removed.
- Parameters:
- omegaarray_like
Positive in-band angular frequencies in rad/s, shape
(n_omega,).
- Returns:
- numpy.ndarray
Optics-convention residual phase in rad, shape
(n_omega,).
- Raises:
- MaterialError
If frequencies or the material model are invalid, or the phase is not finite.
- OpticsGeometryError
If any requested central ray is infeasible.
- ray_paths(omega)[source]#
Trace positive central-ray paths through the two ideal wedges.
- Parameters:
- omegaarray_like
Positive in-band angular frequencies in rad/s, shape
(n_omega,).
- Returns:
- PrismPaths
New path and face-distance arrays in m, shape
(n_omega,).
- Raises:
- MaterialError
If frequencies or the real refractive index are invalid.
- OpticsGeometryError
If any ray is backwards, grazing, misses a face or undergoes TIR.
- class solprop.optics.PrismPaths(first_glass, air_gap, second_glass, first_exit_face_distance, second_entry_face_distance, second_exit_face_distance)[source]#
Bases:
DisplayedReport central-ray paths for one traversal through two ideal wedges.
- Attributes:
- first_glassnumpy.ndarray
First glass path in m, shape
(n_omega,).- air_gapnumpy.ndarray
Actual inter-prism ray length in m, shape
(n_omega,).- second_glassnumpy.ndarray
Second glass path in m, shape
(n_omega,).- first_exit_face_distancenumpy.ndarray
First exit distance along its face from the apex in m, shape
(n_omega,).- second_entry_face_distancenumpy.ndarray
Second entry distance along its face from the apex in m, shape
(n_omega,).- second_exit_face_distancenumpy.ndarray
Second exit distance along its face from the apex in m, shape
(n_omega,).
- air_gap: Float[ndarray, 'n_omega']#
- first_exit_face_distance: Float[ndarray, 'n_omega']#
- first_glass: Float[ndarray, 'n_omega']#
- second_entry_face_distance: Float[ndarray, 'n_omega']#
- second_exit_face_distance: Float[ndarray, 'n_omega']#
- second_glass: Float[ndarray, 'n_omega']#
- class solprop.optics.TaylorPhase(coefficients, wavelength)[source]#
Bases:
DisplayedA polynomial spectral phase about a reference wavelength.
- Attributes:
- coefficientssequence of float
c_0, c_1, c_2, ...ins**n: carrier-envelope phase in rad, group delay in s, group-delay dispersion in s^2, third-order dispersion in s^3. Zero-based, the same indexing as thephases=keyword of the run interfaces. A positivec_2chirps positively.c_1multiplies the detuning, so it delays the envelope and leaves the phase at the reference frequency where it was; a delay of the whole field, absolute frequency times a time, is a pulse’st0and thedelayoftaylor_phase().- wavelengthfloat
Wavelength the expansion is about, m, > 0.
Examples
>>> import numpy as np >>> from solprop.optics import TaylorPhase >>> gdd = TaylorPhase((0.0, 0.0, 50e-30), 800e-9) >>> bool(np.allclose(np.abs(gdd(np.linspace(2e15, 3e15, 5))), 1.0)) True
- class solprop.optics.TransferFunction(*args, **kwargs)[source]#
Bases:
ProtocolA linear optical element, as its complex amplitude response.
- solprop.optics.brewster_angle(medium, wavelength)[source]#
Return the external Brewster incidence angle in air.
- Parameters:
- mediumGlassIndex or str
Glass model or existing glass registry name; its real index is used.
- wavelengthfloat
Vacuum wavelength in m, finite and positive.
- Returns:
- float
Incidence angle in rad,
atan(real(n)).
- Raises:
- MaterialError
If the wavelength or glass is invalid, or its real index is not above one.
- solprop.optics.brewster_apex(medium, wavelength)[source]#
Return the apex angle for Brewster entry and minimum deviation.
- Parameters:
- mediumGlassIndex or str
Glass model or existing glass registry name; its real index is used.
- wavelengthfloat
Vacuum wavelength in m, finite and positive.
- Returns:
- float
Apex angle in rad,
pi - 2*brewster_angle(medium, wavelength).
- Raises:
- MaterialError
If the reference wavelength or glass index is invalid.
- solprop.optics.chirped_mirrors()[source]#
Return the names of the shipped chirped-mirror data sets.
- Returns:
- tuple of str
Names
ChirpedMirror.lookup()accepts. Where the data sets came from is not recorded (docs/guide/workflows/compression.md).
Examples
>>> from solprop.optics import chirped_mirrors >>> "PC70" in chirped_mirrors() True
- solprop.optics.littrow_angle(line_density, wavelength, order=-1)[source]#
Return the signed Littrow incidence angle of a reflection grating.
- Parameters:
- line_densityfloat
Grooves per metre, finite and positive; 1200 lines/mm is
1.2e6.- wavelengthfloat
Vacuum wavelength in m, finite and positive.
- orderint, optional
Nonzero signed order in
sin(theta_m) = sin(theta_i) + m*wavelength/d.
- Returns:
- float
Incidence angle in rad, strictly between -pi/2 and pi/2.
- Raises:
- MaterialError
If density, wavelength or order is invalid.
- OpticsGeometryError
If the Littrow order is unavailable or grazing.
- solprop.optics.stored_factor(grid, transfer)[source]#
Return the factor that applies a transfer function to a stored spectrum.
The response is evaluated on the grid’s active band only and is one elsewhere: the bins outside it hold no field, and asking a material model for an index there would only raise range warnings about frequencies nothing depends on. For an element that blocks light, such as a mirror outside its band, this means the little that a spectral collar leaves outside the active band is passed rather than blocked.
- Parameters:
- gridsolprop.grid.TimeGrid
The grid the stored spectrum lives on.
- transferTransferFunction
The element, in the optics convention.
- Returns:
- numpy.ndarray
The factor in the internal (FFT) convention, shape
(n_omega,):conj(H)on the active band, bysolprop.fourier.to_internal().
Examples
>>> import numpy as np >>> from solprop.optics import TaylorPhase, stored_factor >>> from solprop.processing._examples import example_grid >>> grid = example_grid() >>> factor = stored_factor(grid, TaylorPhase((0.0, 0.0, 100e-30), 800e-9)) >>> bool(np.allclose(np.abs(factor), 1.0)) True
- solprop.optics.taylor_phase(omega, coefficients, omega_ref, delay=0.0)[source]#
Return a Taylor spectral phase, in the optics convention.
\[\varphi(\omega) = \omega t_0 + \sum_n c_n\,(\omega-\omega_{\rm ref})^n / n!\]The one place the package writes this sum: the pulse builders and
TaylorPhaseboth call it, so a chirp put on a pulse at construction is removed exactly by the oppositeTaylorPhase.- Parameters:
- omeganumpy.ndarray
Absolute angular frequencies in rad/s, shape
(n_omega,).- coefficientsnumpy.ndarray
c_0, c_1, ...ins**nfor ordern: carrier-envelope phase, group delay, group-delay dispersion, third-order dispersion and so on.- omega_reffloat
Frequency the expansion is about, rad/s.
- delayfloat, optional
A pure delay \(t_0\) in s multiplying the absolute frequency, so that the whole field moves and not only its envelope; positive is later.
- Returns:
- numpy.ndarray
The phase in rad, shape
(n_omega,).
Examples
>>> import numpy as np >>> from solprop.optics import taylor_phase >>> taylor_phase(np.array([1.0, 3.0]), np.array([0.0, 0.0, 2.0]), 1.0).tolist() [0.0, 4.0]