mokka.channels
Module with channel model implementations.
Channels sub-module implemented within the PyTorch framework.
- class mokka.channels.torch.ComplexAWGN(N_0=None)
Bases:
Module
Complex AWGN channel defined with zero mean and variance N_0.
This converts to a setting of stddev sqrt(N_0/2) for real and imaginary parts of the distribution.
- __init__(N_0=None)
Construct ComplexAWGN.
- forward(x, N_0=None)
Apply Gaussian noise to a signal.
- Parameters:
x – input signal to apply noise to.
N_0 – noise variance
- Returns:
input signal distorted with AWGN
- class mokka.channels.torch.DPImpairments(samp_rate, tau_cd, tau_pmd, phi_IQ, theta, rho=0)
Bases:
Module
Apply a list of impairments experienced for dual pol. transmission.
This includes residual chromatic dispersion, polarization mode dispersion, polarization rotation and IQ shift
- __init__(samp_rate, tau_cd, tau_pmd, phi_IQ, theta, rho=0)
Initialize py:class:DPImpairments.
- Parameters:
samp_rate – sampling rate of the input signal
tau_cd – Residual chromatic dispersion coefficient tau_{cd}
tau_pmd – Residual polarization-mode dispersion coefficient tau_{pmd}
phi_IQ – Phase rotation phi_{IQ}
theta – Polarization angle theta
rho – Polarization angle rho
- forward(signal)
Apply DPImpairment to a dual polarization signal.
- Parameters:
signal – Must be a 2xN complex-valued PyTorch tensor
- class mokka.channels.torch.EDFAAmpDualPol(span_length: int, amp_gain: str, alphaa_db: Float[Tensor, '1'], alphab_db: Float[Tensor, '1'], amp_noise: bool, noise_figure: Float[Tensor, '1'], optical_carrier_frequency: float, bw: float, P_input_lin: float, padding: int)
Bases:
Module
Implement Gaussian noise EDFA model for dual polarization fiberoptical simulation.
- Parameters:
span_length – span_length
amp_gain – Which amplification gain model to use either ‘alpha_equalization’, ‘equal_power’
alphaa_db – power loss coeficient [dB/km] for eigenstate a
alphab_db – power loss coeficient [dB/km] for eigenstate b
amp_noise – Consider amplification noise
noise_figure – Amplifier noise figure in dB
optical_carrier_frequency – Optical carrier frequency (for PSD) [GHz]
bw – Bandwidth of baseband signal (for PSD)
P_input_lin – Input power
padding – Number of samples to ignore in the beginning and end
- P_input_lin: float
- __init__(span_length: int, amp_gain: str, alphaa_db: Float[Tensor, '1'], alphab_db: Float[Tensor, '1'], amp_noise: bool, noise_figure: Float[Tensor, '1'], optical_carrier_frequency: float, bw: float, P_input_lin: float, padding: int) None
Method generated by attrs for class EDFAAmpDualPol.
- alphaa_db: Float[Tensor, '1']
- alphaa_lin: Float[Tensor, '1']
- alphab_db: Float[Tensor, '1']
- alphab_lin: Float[Tensor, '1']
- amp_gain: str
- amp_noise: bool
- bw: float
- forward(u1, u2, segment)
Amplify the signal according to the selected method after each span.
attention: the noise depends on the amplification. if \(\alpha = 0\), no noise is added.
Parameters
- u1array_like
co-polarized signal before the amplifier
- u2array_like
cross-polarized signal before the amplifier
- segment: array_like
segment number
Returns
signal : signal after the amplifier
- noise_figure: Float[Tensor, '1']
- optical_carrier_frequency: float
- padding: int
- span_length: int
- class mokka.channels.torch.EDFAAmpSinglePol(span_length: int, amp_gain: str, alpha_db: Float[Tensor, '1'], amp_noise: bool, noise_figure: Float[Tensor, '1'], optical_carrier_frequency: float, bw: float, P_input_lin: float, padding: int)
Bases:
Module
Gaussian noise model of an EDFA for single polarization fiberoptics.
- Parameters:
span_length – span_length [km]
amp_gain – Either ‘alpha_equalization’ or ‘equal_power’
alpha_db – Attenuation of the fiber [dB/km]
amp_noise – Consider amplification noise [bool]
amp_gain – Which amplification gain model to use either ‘alpha_equalization’, ‘equal_power’
optical_carrier_frequency – Optical carrier frequency (for PSD) [GHz]
bw – Occupied bandwidth (for PSD) [Hz]
P_input_lin – Input power [W]
padding – Number of samples to ignore in the beginning and end
- P_input_lin: float
- __init__(span_length: int, amp_gain: str, alpha_db: Float[Tensor, '1'], amp_noise: bool, noise_figure: Float[Tensor, '1'], optical_carrier_frequency: float, bw: float, P_input_lin: float, padding: int) None
Method generated by attrs for class EDFAAmpSinglePol.
- alpha_db: Float[Tensor, '1']
- alpha_lin: Float[Tensor, '1']
- amp_gain: str
- amp_noise: bool
- bw: float
- forward(signal, segment)
Amplify the signal according to the selected method after each span.
Attention: the noise depends on the amplification. if \(\alpha = 0\), no noise is added.
Parameters
- signalarray_like
signal before the amplifier
- segment: array_like
segment number
Returns
signal : signal after the amplifier
- noise_figure: Float[Tensor, '1']
- optical_carrier_frequency: float
- padding: int
- span_length: int
- class mokka.channels.torch.FixedArbitraryChannelDP(impulse_response)
Bases:
Module
Apply a fixed 2x2 channel impulse response to a dual polarization signal.
This class only implements a time-invariant dual-polarization channel.
- __init__(impulse_response)
Initialize
FixedArbitraryChannelDP
.- Parameters:
impulse_response – arbitrary 2x2 impulse response.
- forward(tx_signal)
Apply arbitrary dual polarization channel to tx_signal.
- class mokka.channels.torch.FixedChannelDP(impulse_response)
Bases:
Module
Apply a fixed channel impulse response on both polarization separately.
- __init__(impulse_response)
Initialize
FixedChannelDP
.- Parameters:
impulse_response – single polarization impulse response
- forward(tx_signal)
Apply static dual polarization signal to tx_signal.
- Parameters:
tx_signal – dual polarization input signal
- class mokka.channels.torch.FixedChannelSP(impulse_response)
Bases:
Module
Apply a fixed channel impulse response to a single polarization input signal.
This class only implements a time-invariant single-polarization channel.
- __init__(impulse_response)
Initialize
FixedChannelSP
.- Parameters:
impulse_response – 1xN vector of complex time-domain samples of the impulse response
- forward(tx_signal)
Apply fixed single-polarization channel on tx_signal.
- Parameters:
tx_signal – Single polarization complex signal vector
- class mokka.channels.torch.OpticalNoise(dt: float, optical_carrier_wavelength: float, wavelength_bandwidth: float, OSNR: float)
Bases:
Module
Zero mean additive Gaussian noise based on given OSNR defined over certain wavelength.
- Parameters:
dt – Time step
optical_carrier_wavelength – Wavelength of optical carrier in nm
wavelength_bandwidth – Bandwidth in nm for which OSNR is given
OSNR – Optical SNR in dB
- OSNR: float
- __init__(dt: float, optical_carrier_wavelength: float, wavelength_bandwidth: float, OSNR: float) None
Method generated by attrs for class OpticalNoise.
- dt: float
- forward(signal)
Apply optical noise realization on signal.
- Parameters:
signal – input signal
- Returns:
noise impaired signal
- optical_carrier_wavelength: float
- wavelength_bandwidth: float
- class mokka.channels.torch.PDLElement(rho)
Bases:
Module
Simulate PDL in optical channels.
This class applies PDL which is randomly rotated w.r.t to the input signal.
- __init__(rho)
Construct a PDL element.
It exhibits a differential linear attenuation of rho. To get the attenuation matrix Gamma we first set attenuation of one polarization to sqrt(1+rho) and the other to sqrt(1-rho) and then rotate the matrix with a random rotation matrix uniform in Stokes space.
- Parameters:
rho – PDL in linear units
- forward(signal)
Apply time-invariant PDL by mutiplying input signal and Jones matrix.
- class mokka.channels.torch.PMDAngleElement(L, num_steps, pmd_parameter=None, dgd_tau=None, angles=None, trainable=False, theta=True, phi=True, psi=True, pmd_sigma=None)
Bases:
Module
Learn parameters of a single PMD Element (Rotation + DGD)
This implements the learning process based on Farsi paper on Learning to extract…
- property J_k1
- __init__(L, num_steps, pmd_parameter=None, dgd_tau=None, angles=None, trainable=False, theta=True, phi=True, psi=True, pmd_sigma=None)
Initialize internal Module state, shared by both nn.Module and ScriptModule.
- forward(signal)
Define the computation performed at every call.
Should be overridden by all subclasses.
Note
Although the recipe for forward pass needs to be defined within this function, one should call the
Module
instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.
- step()
- class mokka.channels.torch.PMDElement(sigma_p, span_length, steps_per_span, pmd_parameter=None, dgd_tau=None, method='static')
Bases:
Module
Static and dynamic PMD Element according to Czegledi (2016).
Note: for SSFM only static PMD is correct
- property J
Calculate the Jones matrix of the rotation portion.
- __init__(sigma_p, span_length, steps_per_span, pmd_parameter=None, dgd_tau=None, method='static')
Initialize
PMDElement
.- Parameters:
sigma_p – Variance of time-varying Wiener process
pmd_parameter – Calculate second moment of the DGD based on the PMD parameter
span_length – Length of each span of optical fiber
steps_per_span – Simulation steps per span
method – Either “static” or “dynamic” - sets the mode to either time-varying or fixed in time
- property a
Calculate and return parameters a.
- forward(signal: Tensor)
Process a dual polarization signal and apply PMD with a random walk to it.
- Parameters:
signal
- forward_dynamic(signal: Tensor)
Apply the time-varying PMD simulation to the input signal.
- forward_static(signal: Tensor)
Apply the static PMD simulation to the input signal.
- step()
Perform one time-step for the time-varying simulation and return J_k1.
- steps(k=1)
Perform k time-varying steps and return the Jones matrices.
- property theta
Calculate theta as norm of vector alpha.
- class mokka.channels.torch.PMDPDLChannel(L, num_steps, pmd_correlation_length, f_samp, dgd_tau=None, pmd_parameter=None, pmd_sigma=0.0, num_pdl_elements=0, pdl_max=0.8, pdl_min=0.1, method='freq', trainable=False, angles=False, rotation=True)
Bases:
Module
Optical channel with only PMD and PDL impairments.
- __init__(L, num_steps, pmd_correlation_length, f_samp, dgd_tau=None, pmd_parameter=None, pmd_sigma=0.0, num_pdl_elements=0, pdl_max=0.8, pdl_min=0.1, method='freq', trainable=False, angles=False, rotation=True)
Initialize
PMDPDLChannel
.- Parameters:
L – fiber length
num_steps – number of steps per span
pmd_parameter – PMD Parameter gamma
pmd_correlation_length – Length after which the SOP states are decorrelated
f_samp – sampling frequencey
pmd_sigma – pmd_parameter
num_pdl_elements – number of equally spaced pdl elements
pdl_max – maximum PDL
pdl_min – minimum PDL
method – simulation method (time or frequency)
- channel_transfer(length, pulse_shape=None, per_step=False, sample_interval=1)
Compute the 2x2 channel transfer function.
- Parameters:
length – One-sided length of the desired impulse response
pulse_shape – Shaping to apply to the window function
per_step – Return channel_transfer function after each step
- forward(u)
Apply Channel to input signal.
- Parameters:
u – Dual-polarization complex input signal
- forward_freq(u)
Apply channel in frequency domain.
- Parameters:
u – Dual-polarization complex input signal
- forward_time(u)
Apply channel in time domain.
- Parameters:
u – Dual-polarization complex input signal
- step()
Propagate the PMD Elements in time.
Only relevant for time-variant PMD.
- class mokka.channels.torch.PhasenoiseWiener(start_phase_width=6.283185307179586, start_phase_init=0)
Bases:
Module
Wiener phase noise channel.
Forward call takes N0 for AWGN and sigma_phi for Wiener phase noise.
- Parameters:
start_phase_width – upper bound for initialization with a uniform distribution.
start_phase_init – initial phase value at the start of the generation for each noise sequence.
- __init__(start_phase_width=6.283185307179586, start_phase_init=0)
Construct PhasenoiseWiener.
- apply(x, sigma_phi=None)
Apply only Wiener phase noise.
Parameters
- x: array_like
Input data
- sigma_phi: float
phase noise variance
- forward(x, N0=None, sigma_phi=None)
Apply Wiener phase noise to a complex signal.
- Parameters:
x – ipnut signal to apply noise to
N0 – noise variance for Gaussian noise
sigma_phi – standard deviation of Wiener phase noise process
- Returns:
noise impaired signal
- class mokka.channels.torch.PolyPhaseChannelizer(coeff, n_down)
Bases:
Module
Perform poly-phase channelization with variable filter coefficients.
- __init__(coeff, n_down)
Init PolyPhaseChannelizer.
- forward(signal)
Apply poly-phase channelization on a wideband signal.
- mokka.channels.torch.ProakisChannel(variant, sps=1)
Return impulse response for channels defined in [0].
- Parameters:
variant – Either “a”, “b”, “c” or “a_complex”. In the literature all channels are real-valued. The complex channel “a_complex” is an extension of the “a” channel by applying a phase rotation of the given samples.
sps – samples-per-symbol choosing an integer value greater than 1 will add sps-1 zeros in-between the channel given channel taps. No band-limiting filter is applied subsequently.
[0] Proakis, John G., and Masoud Salehi. Digital communications. McGraw-hill, 2008.
- class mokka.channels.torch.RamanAmpDualPol(amp_gain: str, alphaa_db: Float[Tensor, '1'], alphab_db: Float[Tensor, '1'], amp_noise: bool, noise_figure: Float[Tensor, '1'], optical_carrier_frequency: float, bw: float, P_input_lin: float, padding: int)
Bases:
Module
Implement a Gaussian model of the Raman dual polarization amp.
- Parameters:
amp_gain – Which amplification gain model to use either ‘alpha_equalization’, ‘equal_power’
alphaa_db – power loss coeficient [dB/km] for eigenstate a
alphab_db – power loss coeficient [dB/km] for eigenstate b
noise_figure – Amplifier noise figure in dB
optical_carrier_frequency – Optical carrier frequency (for PSD) [GHz]
bw – Bandwidth of baseband signal (for PSD)
P_input_lin – Input power
padding – Number of samples to ignore in the beginning and end
- P_input_lin: float
- __init__(amp_gain: str, alphaa_db: Float[Tensor, '1'], alphab_db: Float[Tensor, '1'], amp_noise: bool, noise_figure: Float[Tensor, '1'], optical_carrier_frequency: float, bw: float, P_input_lin: float, padding: int) None
Method generated by attrs for class RamanAmpDualPol.
- alphaa_db: Float[Tensor, '1']
- alphaa_lin: Float[Tensor, '1']
- alphab_db: Float[Tensor, '1']
- alphab_lin: Float[Tensor, '1']
- amp_gain: str
- amp_noise: bool
- bw: float
- forward(u1, u2, dz)
Amplify the signal according to the selected method after each span.
Attention: the noise depends on the amplification. if \(\alpha = 0\), no noise is added Parameters ———- signal : signal before the amplifier dz : step-size Returns ——- signal : signal after the amplifier
- noise_figure: Float[Tensor, '1']
- optical_carrier_frequency: float
- padding: int
- class mokka.channels.torch.ResidualPhaseNoise
Bases:
Module
Residual phase noise implementation.
This implements residual phase noise modeled with a zero mean phase noise process.
- __init__()
Construct ResidualPhaseNoise.
- forward(x, RPN)
Apply residual phase noise to signal.
- Parameters:
x – complex input signal
RPN – phase noise variance per input symbol
- Returns:
x with phase noise
- class mokka.channels.torch.SSFMPropagationDualPol(dt: Float[Tensor, '1'], dz: Float[Tensor, '1'], alphaa_db: Float[Tensor, '1'], alphab_db: Float[Tensor, '1'], betapa: Float[Tensor, '...'], betapb: Float[Tensor, '...'], gamma: Float[Tensor, '1'], length_span: Float[Tensor, '1'], num_span: Integer, delta_G: Float = 0.001, maxiter: Integer = 4, alphaa_pdl_lin: Float[Tensor, '1'] = tensor(0.), alphab_pdl_lin: Float[Tensor, '1'] = tensor(0.), psp: Float[Tensor, '2'] = tensor([0, 0]), solution_method: str = 'elliptical', amp: RamanAmpDualPol | EDFAAmpDualPol | None = None, solver_method: str = 'localerror', pmd_simulation: Bool = False, pmd_sigma: Float[Tensor, '1'] = tensor(0.), pmd_correlation_length: Float[Tensor, '1'] = tensor(0.1000), pmd_parameter: Float[Tensor, '1'] = tensor(0.), pdl_simulation: Bool = False, pdl_min: float = 0.07, pdl_max: float = 0.17)
Bases:
Module
Coupled NLS fibre propagation (with SSFM).
This class is adapted from Code written by Dominik Rimpf published under the MIT license [https://gitlab.com/domrim/bachelorarbeit-code]
This class solves the coupled nonlinear Schrodinger equation for pulse propagation in an optical fiber using the split-step Fourier method. The implementation and name are based on https://photonics.umd.edu/software/ssprop/vector-version/
- Parameters:
dt – time step between samples (sample time)
dz – propagation stepsize (delta z) of SSFM (segment length)
alphaa_db – power loss coeficient [dB/km] for eigenstate a
alphab_db – power loss coeficient [dB/km] for eigenstate b
betapa – dispersion polynomial coefficient vector for eigenstate a
betapb – dispersion polynomial coefficient vector for eigenstate b
gamma – nonlinearity coefficient
length_span – Length of span between amplifiers
num_span – Number of spans where num_span * length_span is full fiber channel length
delta_G – Goal local error (optional) (default 1e-3)
maxiter – Number of step-size iterations (optional) (default 4)
psp – Principal eigenstate of the fiber specified as a 2-vector containing the angles Psi and Chi (optional) (default [0,0])
solution_method – String that specifies which method to use when performing the split-step calculations. Supported methods elliptical and circular (optional) (default elliptical)
- __init__(dt: Float[Tensor, '1'], dz: Float[Tensor, '1'], alphaa_db: Float[Tensor, '1'], alphab_db: Float[Tensor, '1'], betapa: Float[Tensor, '...'], betapb: Float[Tensor, '...'], gamma: Float[Tensor, '1'], length_span: Float[Tensor, '1'], num_span: Integer, delta_G: Float = 0.001, maxiter: Integer = 4, alphaa_pdl_lin: Float[Tensor, '1'] = tensor(0.), alphab_pdl_lin: Float[Tensor, '1'] = tensor(0.), psp: Float[Tensor, '2'] = tensor([0, 0]), solution_method: str = 'elliptical', amp: RamanAmpDualPol | EDFAAmpDualPol | None = None, solver_method: str = 'localerror', pmd_simulation: Bool = False, pmd_sigma: Float[Tensor, '1'] = tensor(0.), pmd_correlation_length: Float[Tensor, '1'] = tensor(0.1000), pmd_parameter: Float[Tensor, '1'] = tensor(0.), pdl_simulation: Bool = False, pdl_min: float = 0.07, pdl_max: float = 0.17) None
Method generated by attrs for class SSFMPropagationDualPol.
- alphaa_db: Float[Tensor, '1']
- alphaa_lin: Float[Tensor, '1']
- alphaa_pdl_lin: Float[Tensor, '1']
- alphab_db: Float[Tensor, '1']
- alphab_lin: Float[Tensor, '1']
- alphab_pdl_lin: Float[Tensor, '1']
- amp: RamanAmpDualPol | EDFAAmpDualPol | None
- betapa: Float[Tensor, '...']
- betapb: Float[Tensor, '...']
- calculate_basis(w)
Calculate basis functions for linear step.
If any of the parameters alpha or beta change, this function needs to be executed again to recalculate parameters
- delta_G: Float
- dt: Float[Tensor, '1']
- dz: Float[Tensor, '1']
- forward(ux, uy)
Compute the progpagation for the dual polarization signal through the fiber optical channel.
- Parameters:
ux – input signal in x-polarization.
uy – input signal in y-polarization.
- Returns:
signal at the end of the fiber
- gamma: Float[Tensor, '1']
- get_operators(dz)
Obtain linear operators for given step length.
- length_span: Float[Tensor, '1']
- maxiter: Integer
- num_span: Integer
- pdl_max: float
- pdl_min: float
- pdl_simulation: Bool
- pmd_correlation_length: Float[Tensor, '1']
- pmd_parameter: Float[Tensor, '1']
- pmd_sigma: Float[Tensor, '1']
- pmd_simulation: Bool
- psp: Float[Tensor, '2']
- solution_method: str
- solver_method: str
- class mokka.channels.torch.SSFMPropagationSinglePol(dt: tensor, dz: tensor, alphadb: tensor, betap: tensor, gamma: tensor, length_span: tensor, num_span: tensor, delta_G: tensor = 0.001, maxiter: tensor = 4, amp: object = None, solver_method: str = 'localerror')
Bases:
Module
Non-linear fibre propagation (with SSFM).
This class is adapted from Code written by Dominik Rimpf published under the MIT license [https://gitlab.com/domrim/bachelorarbeit-code]
This class solves the nonlinear Schrodinger equation for pulse propagation in an optical fiber using the split-step Fourier method. The actual implementation is the local error method Sec II.E of Optimization of the Split-Step Fourier Method in Modeling Optical-Fiber Communications Systems https://doi.org/10.1109/JLT.2003.808628
- Parameters:
dt – time step between samples (sample time)
dz – propagation stepsize (delta z) of SSFM (segment length)
alphadb – power loss coeficient [dB/km]
beta2 – dispersion polynomial coefficient
gamma – nonlinearity coefficient
length_span – Length of span between amplifiers
num_span – Number of spans where num_span * length_span is full fiber channel length
delta_G – Goal local error
maxiter – Number of step-size iterations
- __init__(dt: tensor, dz: tensor, alphadb: tensor, betap: tensor, gamma: tensor, length_span: tensor, num_span: tensor, delta_G: tensor = 0.001, maxiter: tensor = 4, amp: object = None, solver_method: str = 'localerror') None
Method generated by attrs for class SSFMPropagationSinglePol.
- alphadb: tensor
- alphalin: tensor
- amp: object
- betap: tensor
- delta_G: tensor
- dt: tensor
- dz: tensor
- forward(u)
Compute the propagation through the configured fiber-optical channel.
- Parameters:
u0 – input signal (array)
- Returns:
array signal at the end of the fiber
- gamma: tensor
- get_operators(dz)
Calculate linear operators for given step length.
- length_span: tensor
- maxiter: tensor
- num_span: tensor
- solver_method: str
- mokka.channels.torch.SSFM_halfstep_end(signal, linear_op)
Calculate the final halfstep of the single polarization SSFM.
- mokka.channels.torch.SSFM_step(signal, linear_op, nonlinear_op)
Calculate single polarization SSFM step.
- class mokka.channels.torch.WDMDemux(n_channels, spacing, sym_rate, sim_rate, used_channels, method='classical')
Bases:
Module
WDM Demuxing for a configurable number of channels and system parameters.
- __init__(n_channels, spacing, sym_rate, sim_rate, used_channels, method='classical')
Initialize WDMDemux.
- classical_demux(signal)
Perform WDM Demuxing for each channel individually.
- forward(signal)
WDM Demux the wide-band signal.
- polyphase_demux(signal)
Peform WDM Demuxing with the Polyphase Channelizer method.
- class mokka.channels.torch.WDMMux(n_channels, spacing, samp_rate, sim_rate)
Bases:
Module
Perform configurable muxing of baseband channels to simulate WDM.
- __init__(n_channels, spacing, samp_rate, sim_rate)
Initialize WDMMux.
- forward(signals)
Modulate the signals on WDM channels in the digital baseband.
- mokka.channels.torch.decompose_stokes_rotation(J)
Decompose a rotation in Stokes’ space into angles.
Input Jones matrix must be unitary. We use the description of the rotation.
- Parameters:
J – Jones matrix to decompose
- Returns:
Tuple of (theta, phi, psi)
- mokka.channels.torch.symmetrical_SSFM_step(signal, half_linear_op, nonlinear_op)
Calculate symmetrical single polarization SSFM step.
- mokka.channels.torch.symmetrical_SSPROPV_step(u1, u2, h11, h12, h21, h22, NOP)
Calculate symmetrical dual polarization SSFM step.