diff --git a/examples/test_wl_del_freq.py b/examples/test_wl_del_freq.py new file mode 100644 index 0000000..0839a04 --- /dev/null +++ b/examples/test_wl_del_freq.py @@ -0,0 +1,98 @@ +""" +This example presents potential of new plot functions. +Especially: + -different scales(linear and logarithmic) + -different x arguments(delay, frequency, wavelength) + -color map as argument of plot function + -slice plot for chosen z(propagation) distances + or z=0 and z=end if no specific z were chosen. +Data used in this example are taken from test_Dudley.py file from examples. +""" + +import numpy as np +import matplotlib.pyplot as plt + +import gnlse + +if __name__ == '__main__': + setup = gnlse.GNLSESetup() + + # Numerical parameters + setup.resolution = 2**14 + setup.time_window = 12.5 # ps + setup.z_saves = 200 + + # Physical parameters + setup.wavelength = 835 # nm + setup.fiber_length = 0.15 # m + setup.nonlinearity = 0.11 # 1/W/m + setup.raman_model = gnlse.raman_blowwood + setup.self_steepening = True + + # The dispersion model is built from a Taylor expansion with coefficients + # given below. + loss = 0 + betas = np.array([ + -11.830e-3, 8.1038e-5, -9.5205e-8, 2.0737e-10, -5.3943e-13, 1.3486e-15, + -2.5495e-18, 3.0524e-21, -1.7140e-24 + ]) + setup.dispersion_model = gnlse.DispersionFiberFromTaylor(loss, betas) + + # Input pulse parameters + power = 10000 + # pulse duration [ps] + tfwhm = 0.05 + # hyperbolic secant + setup.pulse_model = gnlse.SechEnvelope(power, tfwhm) + solver = gnlse.GNLSE(setup) + solution = solver.run() + + plt.figure(figsize=(14, 8), facecolor='w', edgecolor='k') + + plt.subplot(4, 3, 1) + gnlse.plot_delay_vs_distance(solution, time_range=[-.5, 5], cmap="jet") + + plt.subplot(4, 3, 2) + gnlse.plot_frequency_vs_distance(solution, frequency_range=[-300, 200], + cmap="plasma") + + plt.subplot(4, 3, 3) + gnlse.plot_wavelength_vs_distance(solution, WL_range=[400, 1400]) + + plt.subplot(4, 3, 4) + gnlse.plot_delay_vs_distance_logarithmic(solution, time_range=[-.5, 5], + cmap="jet") + + plt.subplot(4, 3, 5) + gnlse.plot_frequency_vs_distance_logarithmic(solution, + frequency_range=[-300, 200], + cmap="plasma") + + plt.subplot(4, 3, 6) + gnlse.plot_wavelength_vs_distance_logarithmic(solution, + WL_range=[400, 1400]) + + plt.subplot(4, 3, 7) + gnlse.plot_delay_for_distance_slice(solution, time_range=[-.5, 5]) + + plt.subplot(4, 3, 8) + gnlse.plot_frequency_for_distance_slice(solution, + frequency_range=[-300, 200]) + + plt.subplot(4, 3, 9) + gnlse.plot_wavelength_for_distance_slice(solution, WL_range=[400, 1400]) + + plt.subplot(4, 3, 10) + gnlse.plot_delay_for_distance_slice_logarithmic( + solution, time_range=[-.5, 5]) + + plt.subplot(4, 3, 11) + gnlse.plot_frequency_for_distance_slice_logarithmic( + solution, frequency_range=[-300, 200]) + + plt.subplot(4, 3, 12) + gnlse.plot_wavelength_for_distance_slice_logarithmic(solution, + WL_range=[400, 1400]) + + plt.tight_layout() + plt.show() diff --git a/gnlse/__init__.py b/gnlse/__init__.py index ae8f056..720c85b 100644 --- a/gnlse/__init__.py +++ b/gnlse/__init__.py @@ -7,14 +7,37 @@ from gnlse.nonlinearity import NonlinearityFromEffectiveArea from gnlse.raman_response import (raman_blowwood, raman_holltrell, raman_linagrawal) -from gnlse.visualization import (plot_delay_vs_distance, - plot_wavelength_vs_distance, quick_plot) +from gnlse.visualization import ( + plot_delay_vs_distance, + plot_delay_vs_distance_logarithmic, + plot_delay_for_distance_slice, + plot_delay_for_distance_slice_logarithmic, + plot_frequency_vs_distance, + plot_frequency_vs_distance_logarithmic, + plot_frequency_for_distance_slice, + plot_frequency_for_distance_slice_logarithmic, + plot_wavelength_vs_distance, + plot_wavelength_vs_distance_logarithmic, + plot_wavelength_for_distance_slice, + plot_wavelength_for_distance_slice_logarithmic, + quick_plot) __all__ = [ 'DispersionFiberFromTaylor', 'DispersionFiberFromInterpolation', 'SechEnvelope', 'GaussianEnvelope', 'LorentzianEnvelope', 'GNLSESetup', 'GNLSE', 'Solution', 'read_mat', 'write_mat', 'raman_blowwood', - 'raman_holltrell', 'raman_linagrawal', 'plot_delay_vs_distance', - 'plot_wavelength_vs_distance', 'quick_plot', - 'NonlinearityFromEffectiveArea', 'CWEnvelope' + 'raman_holltrell', 'raman_linagrawal', + 'plot_delay_vs_distance', + 'plot_delay_vs_distance_logarithmic', + 'plot_delay_for_distance_slice', + 'plot_delay_for_distance_slice_logarithmic', + 'plot_frequency_vs_distance', + 'plot_frequency_vs_distance_logarithmic', + 'plot_frequency_for_distance_slice', + 'plot_frequency_for_distance_slice_logarithmic', + 'plot_wavelength_vs_distance', + 'plot_wavelength_vs_distance_logarithmic', + 'plot_wavelength_for_distance_slice', + 'plot_wavelength_for_distance_slice_logarithmic', + 'quick_plot', 'NonlinearityFromEffectiveArea', 'CWEnvelope' ] diff --git a/gnlse/gnlse.py b/gnlse/gnlse.py index a714b21..888064f 100644 --- a/gnlse/gnlse.py +++ b/gnlse/gnlse.py @@ -79,10 +79,11 @@ class Solution: Intermediate steps in the frequency domain. """ - def __init__(self, t=None, W=None, Z=None, At=None, AW=None, + def __init__(self, t=None, W=None, w_0=None, Z=None, At=None, AW=None, Aty=None, AWy=None): self.t = t self.W = W + self.w_0 = w_0 self.Z = Z self.At = At self.AW = AW @@ -163,26 +164,26 @@ def __init__(self, setup): self.N / 2 ) / (self.N * (self.t[1] - self.t[0])) # Central angular frequency [10^12 rad] - w_0 = (2.0 * np.pi * c) / setup.wavelength - self.Omega = self.V + w_0 + self.w_0 = (2.0 * np.pi * c) / setup.wavelength + self.Omega = self.V + self.w_0 # Absolute angular frequency grid - if setup.self_steepening and np.abs(w_0) > np.finfo(float).eps: - W = self.V + w_0 + if setup.self_steepening and np.abs(self.w_0) > np.finfo(float).eps: + W = self.V + self.w_0 else: - W = np.full(self.V.shape, w_0) + W = np.full(self.V.shape, self.w_0) self.W = np.fft.fftshift(W) # Nonlinearity if hasattr(setup.nonlinearity, 'gamma'): # in case in of frequency dependent nonlinearity gamma, self.scale = setup.nonlinearity.gamma(self.V) - self.gamma = gamma / w_0 + self.gamma = gamma / self.w_0 self.gamma = np.fft.fftshift(self.gamma) self.scale = np.fft.fftshift(self.scale) else: # in case in of direct introduced value - self.gamma = setup.nonlinearity / w_0 + self.gamma = setup.nonlinearity / self.w_0 self.scale = 1 # Raman scattering @@ -276,4 +277,4 @@ def rhs(z, AW): At[i, :] = np.fft.fft(AW[i, :]) AW[i, :] = np.fft.fftshift(AW[i, :]) * self.N * dt - return Solution(self.t, self.Omega, Z, At, AW) + return Solution(self.t, self.Omega, self.w_0, Z, At, AW) diff --git a/gnlse/visualization.py b/gnlse/visualization.py index 6dc2ab6..56f3784 100644 --- a/gnlse/visualization.py +++ b/gnlse/visualization.py @@ -10,9 +10,224 @@ from gnlse.common import c -def plot_wavelength_vs_distance(solver, WL_range=[400, 1350], ax=None, - norm=None): - """Plotting results in frequency (wavelength) domain. +def plot_frequency_vs_distance_logarithmic(solver, ax=None, norm=None, + frequency_range=None, cmap="magma"): + """Plotting results in logarithmic scale in frequency domain. + + Parameters + ---------- + solver : Solution + Model outputs in the form of a ``Solution`` object. + frequency_range : list, (2, ) + frequency range. Set [-150, 150] as default. + ax : :class:`~matplotlib.axes.Axes` + :class:`~matplotlib.axes.Axes` instance for plotting + norm : float + Normalization factor for output spectrum. As default maximum of + square absolute of ``solver.AW`` variable is taken. + + Returns + ------- + ax : :class:`~matplotlib.axes.Axes` + Used :class:`~matplotlib.axes.Axes` instance. + """ + + if ax is None: + ax = plt.gca() + + if norm is None: + norm = np.max(np.abs(solver.AW)**2) + + lIW = np.fliplr( + 10 * np.log10(np.abs(solver.AW)**2 / norm, + where=(np.abs(solver.AW)**2 > 0))) + frequency = (solver.W - solver.w_0) / 2 / np.pi # frequency grid + + if frequency_range is not None: + iis = np.logical_and(frequency >= frequency_range[0], + frequency <= frequency_range[1]) + # indices of interest + + frequency = frequency[iis] + lIW = lIW[:, iis] + + ax.imshow(lIW, origin='lower', aspect='auto', cmap=cmap, + extent=[np.min(frequency), np.max(frequency), + 0, np.max(solver.Z)], vmin=-40) + ax.set_xlabel("Frequency [THz]") + ax.set_ylabel("Distance [m]") + return ax + + +def plot_frequency_vs_distance(solver, frequency_range=None, + ax=None, norm=None, cmap="magma"): + """Plotting results in frequency domain. Linear scale. + + Parameters + ---------- + solver : Solution + Model outputs in the form of a ``Solution`` object. + frequency_range : list, (2, ) + frequency range. Set [-150, 150] as default. + ax : :class:`~matplotlib.axes.Axes` + :class:`~matplotlib.axes.Axes` instance for plotting + norm : float + Normalization factor for output spectrum. As default maximum of + square absolute of ``solver.AW`` variable is taken. + + Returns + ------- + ax : :class:`~matplotlib.axes.Axes` + Used :class:`~matplotlib.axes.Axes` instance. + """ + + if ax is None: + ax = plt.gca() + + if norm is None: + norm = np.max(np.abs(solver.AW)**2) + + IW = np.fliplr( + np.abs(solver.AW)**2 / norm) + frequency = (solver.W - solver.w_0) / 2 / np.pi # frequency grid + + if frequency_range is not None: + iis = np.logical_and(frequency >= frequency_range[0], + frequency <= frequency_range[1]) + # indices of interest + + frequency = frequency[iis] + IW = IW[:, iis] + + ax.imshow(IW, origin='lower', aspect='auto', cmap=cmap, + extent=[np.min(frequency), np.max(frequency), + 0, np.max(solver.Z)], vmin=0) + ax.set_xlabel("Frequency [THz]") + ax.set_ylabel("Distance [m]") + return ax + + +def plot_delay_for_distance_slice(solver, time_range=None, ax=None, + z_slice=None, norm=None): + """Plotting intensity in linear scale in time domain. + + Parameters + ---------- + solver : Solution + Model outputs in the form of a ``Solution`` object. + time_range : list, (2, ) + Time range. Set [min(``solver.t``), max(``solver.t``)] as default. + ax : :class:`~matplotlib.axes.Axes` + :class:`~matplotlib.axes.Axes` instance for plotting. + norm : float + Normalization factor for output spectrum. As default maximum of + square absolute of ``solver.At`` variable is taken. + + Returns + ------- + ax : :class:`~matplotlib.axes.Axes` + Used :class:`~matplotlib.axes.Axes` instance. + """ + + if ax is None: + ax = plt.gca() + + if time_range is None: + time_range = [np.min(solver.t), np.max(solver.t)] + + if norm is None: + norm = np.max(np.abs(solver.At[0][:])**2) + + It = np.abs(solver.At)**2 / norm + + # indices of interest if no z_slice positions were given + if z_slice is None: + iis = [0, -1] + # indices of interest nearest to given z_slice positions + else: + iis = [np.nonzero( + np.min(np.abs(solver.Z - z)) == np.abs(solver.Z - z) + )[0][0] for z in z_slice] + + for i in iis: + label_i = "z = " + str(solver.Z[i]) + "m" + ax.plot(solver.t, It[i][:], label=label_i) + + ax.set_xlim(time_range) + ax.set_xlabel("Delay [ps]") + ax.set_ylabel("Normalized Power") + ax.legend() + return ax + + +def plot_wavelength_for_distance_slice(solver, WL_range=None, ax=None, + z_slice=None, norm=None): + """Plotting chosen slices of intensity + in linear scale in wavelength domain. + + Parameters + ---------- + solver : Solution + Model outputs in the form of a ``Solution`` object. + WL_range : list, (2, ) + Wavelength range. Set [400, 1350] as default. + ax : :class:`~matplotlib.axes.Axes` + :class:`~matplotlib.axes.Axes` instance for plotting + norm : float + Normalization factor for output spectrum. As default maximum of + square absolute of ``solver.AW`` variable is taken. + + Returns + ------- + ax : :class:`~matplotlib.axes.Axes` + Used :class:`~matplotlib.axes.Axes` instance. + """ + + if ax is None: + ax = plt.gca() + + if WL_range is None: + WL_range = [np.min(c / (solver.W / 2 / np.pi)), + np.max(c / (solver.W / 2 / np.pi))] + + if norm is None: + norm = np.max(np.abs(solver.AW)**2) + + IW = np.fliplr( + np.abs(solver.AW)**2 / norm) + WL = 2 * np.pi * c / solver.W # wavelength grid + WL_asc = np.flip(WL, ) # ascending order for interpolation + iio = np.logical_and(WL_asc > WL_range[0], + WL_asc < WL_range[1]) # indices in order + + WL_asc = WL_asc[iio] + IW = IW[:, iio] + + # indices of interest if no z_slice positions were given + if z_slice is None: + iis = [0, -1] + # indices of interest nearest to given z_slice positions + else: + iis = [np.nonzero( + np.min(np.abs(solver.Z - z)) == np.abs(solver.Z - z) + )[0][0] for z in z_slice] + + for i in iis: + label_i = "z = " + str(solver.Z[i]) + "m" + ax.plot(WL_asc, IW[i][:], label=label_i) + + ax.set_xlim([np.min(WL_asc), np.max(WL_asc)]) + ax.set_xlabel("Wavelength [nm]") + ax.set_ylabel("Normalized Spectral Density") + ax.legend() + return ax + + +def plot_wavelength_for_distance_slice_logarithmic(solver, WL_range=None, + ax=None, + z_slice=None, norm=None): + """Plotting chosen slices of intensity + in linear scale in wavelength domain. Parameters ---------- @@ -35,6 +250,10 @@ def plot_wavelength_vs_distance(solver, WL_range=[400, 1350], ax=None, if ax is None: ax = plt.gca() + if WL_range is None: + WL_range = [np.min(c / (solver.W / 2 / np.pi)), + np.max(c / (solver.W / 2 / np.pi))] + if norm is None: norm = np.max(np.abs(solver.AW)**2) @@ -43,26 +262,206 @@ def plot_wavelength_vs_distance(solver, WL_range=[400, 1350], ax=None, where=(np.abs(solver.AW)**2 > 0))) WL = 2 * np.pi * c / solver.W # wavelength grid WL_asc = np.flip(WL, ) # ascending order for interpolation - iis = np.logical_and(WL_asc > WL_range[0], - WL_asc < WL_range[1]) # indices of interest + iio = np.logical_and(WL_asc > WL_range[0], + WL_asc < WL_range[1]) # indices in order - WL_asc = WL_asc[iis] - lIW = lIW[:, iis] + WL_asc = WL_asc[iio] + lIW = lIW[:, iio] - interpolator = interp2d(WL_asc, solver.Z, lIW) - newWL = np.linspace(np.min(WL_asc), np.max(WL_asc), lIW.shape[1]) - toshow = interpolator(newWL, solver.Z) + # indices of interest if no z_slice positions were given + if z_slice is None: + iis = [0, -1] + # indices of interest nearest to given z_slice positions + else: + iis = [np.nonzero( + np.min(np.abs(solver.Z - z)) == np.abs(solver.Z - z) + )[0][0] for z in z_slice] - ax.imshow(toshow, origin='lower', aspect='auto', cmap="magma", - extent=[np.min(WL_asc), np.max(WL_asc), 0, np.max(solver.Z)], - vmin=-40) + for i in iis: + label_i = "z = " + str(solver.Z[i]) + "m" + ax.plot(WL_asc, lIW[i][:], label=label_i) + + ax.set_xlim([np.min(WL_asc), np.max(WL_asc)]) + ax.set_ylim(-40) ax.set_xlabel("Wavelength [nm]") - ax.set_ylabel("Distance [m]") + ax.set_ylabel("Normalized Spectral Density") + ax.legend() + return ax + + +def plot_delay_for_distance_slice_logarithmic(solver, time_range=None, ax=None, + z_slice=None, norm=None): + """Plotting chosen slices of intensity in linear scale in time domain. + + Parameters + ---------- + solver : Solution + Model outputs in the form of a ``Solution`` object. + time_range : list, (2, ) + Time range. Set [min(``solver.t``), max(``solver.t``)] as default. + ax : :class:`~matplotlib.axes.Axes` + :class:`~matplotlib.axes.Axes` instance for plotting. + norm : float + Normalization factor for output spectrum. As default maximum of + square absolute of ``solver.At`` variable is taken. + + Returns + ------- + ax : :class:`~matplotlib.axes.Axes` + Used :class:`~matplotlib.axes.Axes` instance. + """ + + if ax is None: + ax = plt.gca() + + if time_range is None: + time_range = [np.min(solver.t), np.max(solver.t)] + + if norm is None: + norm = np.max(np.abs(solver.At)**2) + + lIt = 10 * np.log10(np.abs(solver.At)**2 / norm, + where=(np.abs(solver.At)**2 > 0)) + + # indices of interest if no z_slice positions were given + if z_slice is None: + iis = [0, -1] + # indices of interest nearest to given z_slice positions + else: + iis = [np.nonzero( + np.min(np.abs(solver.Z - z)) == np.abs(solver.Z - z) + )[0][0] for z in z_slice] + + for i in iis: + label_i = "z = " + str(solver.Z[i]) + "m" + ax.plot(solver.t, lIt[i][:], label=label_i) + + ax.set_xlim(time_range) + ax.set_ylim(-40) + ax.set_xlabel("Delay [ps]") + ax.set_ylabel("Normalized Power") + ax.legend() + return ax + + +def plot_frequency_for_distance_slice(solver, frequency_range=None, ax=None, + z_slice=None, norm=None): + """Plotting chosen slices of intensity in linear scale in frequency domain. + + Parameters + ---------- + solver : Solution + Model outputs in the form of a ``Solution`` object. + frequency_range : list, (2, ) + frequency range. Set [-150, 150] as default. + ax : :class:`~matplotlib.axes.Axes` + :class:`~matplotlib.axes.Axes` instance for plotting + norm : float + Normalization factor for output spectrum. As default maximum of + square absolute of ``solver.AW`` variable is taken. + + Returns + ------- + ax : :class:`~matplotlib.axes.Axes` + Used :class:`~matplotlib.axes.Axes` instance. + """ + + if ax is None: + ax = plt.gca() + + if frequency_range is None: + frequency_range = [np.min((solver.W - solver.w_0) / 2 / np.pi), + np.max((solver.W - solver.w_0) / 2 / np.pi)] + + if norm is None: + norm = np.max(np.abs(solver.AW)**2) + + IW = np.fliplr( + np.abs(solver.AW)**2 / norm) + + # indices of interest if no z_slice positions were given + if z_slice is None: + iis = [0, -1] # beginning, end + # indices of interest nearest to given z_slice positions + else: + iis = [np.nonzero( + np.min(np.abs(solver.Z - z)) == np.abs(solver.Z - z) + )[0][0] for z in z_slice] + + for i in iis: + label_i = "z = " + str(solver.Z[i]) + "m" + ax.plot((solver.W - solver.w_0) / 2 / np.pi, IW[i][:], label=label_i) + + ax.set_xlim(frequency_range) + ax.set_xlabel("Frequency [Thz]") + ax.set_ylabel("Normalized Spectral Density") + ax.legend() return ax -def plot_delay_vs_distance(solver, time_range=None, ax=None, norm=None): - """Plotting results in time domain. +def plot_frequency_for_distance_slice_logarithmic(solver, frequency_range=None, + ax=None, z_slice=None, + norm=None): + """Plotting chosen slices of intensity + in logarithmic scale in frequency domain. + + Parameters + ---------- + solver : Solution + Model outputs in the form of a ``Solution`` object. + frequency_range : list, (2, ) + frequency range. Set [-150, 150] as default. + ax : :class:`~matplotlib.axes.Axes` + :class:`~matplotlib.axes.Axes` instance for plotting + norm : float + Normalization factor for output spectrum. As default maximum of + square absolute of ``solver.AW`` variable is taken. + + Returns + ------- + ax : :class:`~matplotlib.axes.Axes` + Used :class:`~matplotlib.axes.Axes` instance. + """ + + if ax is None: + ax = plt.gca() + + if frequency_range is None: + frequency_range = [np.min((solver.W - solver.w_0) / 2 / np.pi), + np.max((solver.W - solver.w_0) / 2 / np.pi)] + + if norm is None: + norm = np.max(np.abs(solver.AW)**2) + + lIW = np.fliplr( + 10 * np.log10(np.abs(solver.AW)**2 / norm, + where=(np.abs(solver.AW)**2 > 0))) + + # indices of interest if no z_slice positions were given + if z_slice is None: + iis = [0, -1] # beginning, end + + # indices of interest nearest to given z_slice positions + else: + iis = [np.nonzero( + np.min(np.abs(solver.Z - z)) == np.abs(solver.Z - z) + )[0][0] for z in z_slice] + + for i in iis: + label_i = "z = " + str(solver.Z[i]) + "m" + ax.plot((solver.W - solver.w_0) / 2 / np.pi, lIW[i][:], label=label_i) + + ax.set_xlim(frequency_range) + ax.set_ylim(-40) + ax.set_xlabel("Frequency [Thz]") + ax.set_ylabel("Normalized Spectral Density") + ax.legend() + return ax + + +def plot_delay_vs_distance_logarithmic(solver, time_range=None, ax=None, + norm=None, cmap="magma"): + """Plotting intensity in logarithmic scale in time domain. Parameters ---------- @@ -94,13 +493,162 @@ def plot_delay_vs_distance(solver, time_range=None, ax=None, norm=None): where=(np.abs(solver.At)**2 > 0)) ax.pcolormesh(solver.t, solver.Z, lIT, shading="auto", vmin=-40, - cmap="magma") + cmap=cmap) ax.set_xlim(time_range) ax.set_xlabel("Delay [ps]") ax.set_ylabel("Distance [m]") return ax +def plot_delay_vs_distance(solver, time_range=None, ax=None, norm=None, + cmap="magma"): + """Plotting normalized intensity in linear scale in time domain. + + Parameters + ---------- + solver : Solution + Model outputs in the form of a ``Solution`` object. + time_range : list, (2, ) + Time range. Set [min(``solver.t``), max(``solver.t``)] as default. + ax : :class:`~matplotlib.axes.Axes` + :class:`~matplotlib.axes.Axes` instance for plotting. + norm : float + Normalization factor for output spectrum. As default maximum of + square absolute of ``solver.At`` variable is taken. + + Returns + ------- + ax : :class:`~matplotlib.axes.Axes` + Used :class:`~matplotlib.axes.Axes` instance. + """ + if ax is None: + ax = plt.gca() + + if time_range is None: + time_range = [np.min(solver.t), np.max(solver.t)] + + if norm is None: + norm = np.max(np.abs(solver.At)**2) + + lIT = np.abs(solver.At)**2 / norm + + ax.pcolormesh(solver.t, solver.Z, lIT, shading="auto", vmin=0, + cmap=cmap) + ax.set_xlim(time_range) + ax.set_xlabel("Delay [ps]") + ax.set_ylabel("Distance [m]") + return ax + + +def plot_wavelength_vs_distance(solver, WL_range=None, ax=None, + norm=None, cmap="magma"): + """Plotting results in linear scale in wavelength domain. + + Parameters + ---------- + solver : Solution + Model outputs in the form of a ``Solution`` object. + WL_range : list, (2, ) + Wavelength range. Set [400, 1350] as default. + ax : :class:`~matplotlib.axes.Axes` + :class:`~matplotlib.axes.Axes` instance for plotting + norm : float + Normalization factor for output spectrum. As default maximum of + square absolute of ``solver.AW`` variable is taken. + + Returns + ------- + ax : :class:`~matplotlib.axes.Axes` + Used :class:`~matplotlib.axes.Axes` instance. + """ + + if ax is None: + ax = plt.gca() + + if WL_range is None: + WL_range = [np.min(c / (solver.W / 2 / np.pi)), + np.max(c / (solver.W / 2 / np.pi))] + + if norm is None: + norm = np.max(np.abs(solver.AW)**2) + + IW = np.fliplr( + np.abs(solver.AW)**2 / norm) + WL = 2 * np.pi * c / solver.W # wavelength grid + WL_asc = np.flip(WL, ) # ascending order for interpolation + iis = np.logical_and(WL_asc > WL_range[0], + WL_asc < WL_range[1]) # indices of interest + + WL_asc = WL_asc[iis] + IW = IW[:, iis] + + interpolator = interp2d(WL_asc, solver.Z, IW) + newWL = np.linspace(np.min(WL_asc), np.max(WL_asc), IW.shape[1]) + toshow = interpolator(newWL, solver.Z) + + ax.imshow(toshow, origin='lower', aspect='auto', cmap=cmap, + extent=[np.min(WL_asc), np.max(WL_asc), 0, np.max(solver.Z)], + vmin=0) + ax.set_xlabel("Wavelength [nm]") + ax.set_ylabel("Distance [m]") + return ax + + +def plot_wavelength_vs_distance_logarithmic(solver, WL_range=None, + ax=None, norm=None, cmap="magma"): + """Plotting results in logarithmic scale in wavelength domain. + + Parameters + ---------- + solver : Solution + Model outputs in the form of a ``Solution`` object. + WL_range : list, (2, ) + Wavelength range. Set [400, 1350] as default. + ax : :class:`~matplotlib.axes.Axes` + :class:`~matplotlib.axes.Axes` instance for plotting + norm : float + Normalization factor for output spectrum. As default maximum of + square absolute of ``solver.AW`` variable is taken. + + Returns + ------- + ax : :class:`~matplotlib.axes.Axes` + Used :class:`~matplotlib.axes.Axes` instance. + """ + + if ax is None: + ax = plt.gca() + + if WL_range is None: + WL_range = [np.min(c / (solver.W / 2 / np.pi)), + np.max(c / (solver.W / 2 / np.pi))] + + if norm is None: + norm = np.max(np.abs(solver.AW)**2) + + lIW = np.fliplr( + 10 * np.log10(np.abs(solver.AW)**2 / norm, + where=(np.abs(solver.AW)**2 > 0))) + WL = 2 * np.pi * c / solver.W # wavelength grid + WL_asc = np.flip(WL, ) # ascending order for interpolation + iis = np.logical_and(WL_asc > WL_range[0], + WL_asc < WL_range[1]) # indices of interest + + WL_asc = WL_asc[iis] + lIW = lIW[:, iis] + + interpolator = interp2d(WL_asc, solver.Z, lIW) + newWL = np.linspace(np.min(WL_asc), np.max(WL_asc), lIW.shape[1]) + toshow = interpolator(newWL, solver.Z) + + ax.imshow(toshow, origin='lower', aspect='auto', cmap=cmap, + extent=[np.min(WL_asc), np.max(WL_asc), 0, np.max(solver.Z)], + vmin=-40) + ax.set_xlabel("Wavelength [nm]") + ax.set_ylabel("Distance [m]") + return ax + + def quick_plot(solution): """Plotting results in time and frequency domain for default value of parameters.