Source code for tidy3d.components.apodization
"""Defines specification for apodization."""
import numpy as np
import pydantic.v1 as pd
from ..constants import SECOND
from ..exceptions import SetupError
from .base import Tidy3dBaseModel, skip_if_fields_missing
from .types import ArrayFloat1D, Ax
from .viz import add_ax_if_none
[docs]
class ApodizationSpec(Tidy3dBaseModel):
"""Stores specifications for the apodizaton of frequency-domain monitors.
Example
-------
>>> apod_spec = ApodizationSpec(start=1, end=2, width=0.2)
.. image:: ../../_static/img/apodization.png
:width: 80%
:align: center
"""
start: pd.NonNegativeFloat = pd.Field(
None,
title="Start Interval",
description="Defines the time at which the start apodization ends.",
units=SECOND,
)
end: pd.NonNegativeFloat = pd.Field(
None,
title="End Interval",
description="Defines the time at which the end apodization begins.",
units=SECOND,
)
width: pd.PositiveFloat = pd.Field(
None,
title="Apodization Width",
description="Characteristic decay length of the apodization function, i.e., the width of the ramping up of the scaling function from 0 to 1.",
units=SECOND,
)
[docs]
@pd.validator("end", always=True, allow_reuse=True)
@skip_if_fields_missing(["start"])
def end_greater_than_start(cls, val, values):
"""Ensure end is greater than or equal to start."""
start = values.get("start")
if val is not None and start is not None and val < start:
raise SetupError("End apodization begins before start apodization ends.")
return val
[docs]
@pd.validator("width", always=True, allow_reuse=True)
@skip_if_fields_missing(["start", "end"])
def width_provided(cls, val, values):
"""Check that width is provided if either start or end apodization is requested."""
start = values.get("start")
end = values.get("end")
if (start is not None or end is not None) and val is None:
raise SetupError("Apodization width must be set.")
return val
[docs]
@add_ax_if_none
def plot(self, times: ArrayFloat1D, ax: Ax = None) -> Ax:
"""Plot the apodization function.
Parameters
----------
times : np.ndarray
Array of times (seconds) to plot source at.
To see source time amplitude for a specific :class:`Simulation`,
pass ``simulation.tmesh``.
ax : matplotlib.axes._subplots.Axes = None
Matplotlib axes to plot on, if not specified, one is created.
Returns
-------
matplotlib.axes._subplots.Axes
The supplied or created matplotlib axes.
"""
times = np.array(times)
amp = np.ones_like(times)
if self.start is not None:
start_ind = times < self.start
time_scaled = (times[start_ind] - self.start) / self.width
amp[start_ind] *= np.exp(-0.5 * time_scaled**2)
if self.end is not None:
end_ind = times > self.end
time_scaled = (times[end_ind] - self.end) / self.width
amp[end_ind] *= np.exp(-0.5 * time_scaled**2)
ax.plot(times, amp, color="blueviolet")
ax.set_xlabel("time (s)")
ax.set_title("apodization function")
ax.set_aspect("auto")
return ax