Simulation of signal propagation in the DWDM network

Optical signals, as defined via info.SpectralInformation, enter elements which compute how these signals are affected as they travel through the network. The simulation is controlled via parameters and implemented mainly via science_utils.


A random subset of ANSI terminal escape codes for colored messages


Standard network elements which propagate optical spectrum

A network element is a Python callable. It takes a info.SpectralInformation object and returns a copy with appropriate fields affected. This structure represents spectral information that is “propogated” by this network element. Network elements must have only a local “view” of the network and propogate info.SpectralInformation using only this information. They should be independent and self-contained.

Network elements MUST implement two attributes uid and name representing a unique identifier and a printable name, and provide the __call__() method taking a SpectralInformation as an input and returning another SpectralInformation instance as a result.

class gnpy.core.elements.Edfa(*args, params=None, operational=None, **kwargs)

Bases: _Node


nf calculation based on 2 models: self.params.nf_model.enabled from json import: True => 2 stages amp modelling based on precalculated nf1, nf2 and delta_p in build_OA_json False => polynomial fit based on self.params.nf_fit_coeff

_gain_profile(pin, err_tolerance=1e-11, simple_opt=True)

Pin : input power / channel in W

  • gain_ripple (numpy.ndarray) – design flat gain

  • dgt (numpy.ndarray) – design gain tilt

  • Pin (numpy.ndarray) – total input power in W

  • gp (float) – Average gain setpoint in dB units (provisioned gain)

  • gtp (float) – gain tilt setting (provisioned tilt)


gain profile in dBm, per channel or spectral slice

Return type


Checking of output power clamping is implemented in interpol_params().

Based on:

R. di Muro, “The Er3+ fiber gain coefficient derived from a dynamic gain tilt technique”, Journal of Lightwave Technology, Vol. 18, Iss. 3, Pp. 343-347, 2000.

Ported from Matlab version written by David Boerges at Ciena.

_nf(type_def, nf_model, nf_fit_coeff, gain_min, gain_flatmax, gain_target)

interpolate SI channel frequencies with the edfa dgt and gain_ripple frquencies from JSON :param spectral_info: instance of :return: None

noise_profile(spectral_info: SpectralInformation)

Computes amplifier ASE noise integrated over the signal bandwidth. This is calculated at amplifier input.


the asepower in W in the signal bandwidth bw for 96 channels

Return type

numpy array of float

ASE power using per channel gain profile inputs:

NF_dB - Noise figure in dB, vector of length number of channels or

spectral slices

G_dB - Actual gain calculated for the EDFA, vector of length number of

channels or spectral slices

ffs - Center frequency grid of the channels or spectral slices in

THz, vector of length number of channels or spectral slices

dF - width of each channel or spectral slice in THz,

vector of length number of channels or spectral slices


ase_dBm - ase in dBm per channel or spectral slice


The output is the total ASE in the channel or spectral slice. For 50GHz channels the ASE BW is effectively 0.4nm. To get to noise power in 0.1nm, subtract 6dB.

ONSR is usually quoted as channel power divided by the ASE power in 0.1nm RBW, regardless of the width of the actual channel. This is a historical convention from the days when optical signals were much smaller (155Mbps, 2.5Gbps, … 10Gbps) than the resolution of the OSAs that were used to measure spectral power which were set to 0.1nm resolution for convenience. Moving forward into flexible grid and high baud rate signals, it may be convenient to begin quoting power spectral density in the same BW for both signal and ASE, e.g. 12.5GHz.


add ASE noise to the propagating carriers of info.SpectralInformation

property to_json
class gnpy.core.elements.Fiber(*args, params=None, **kwargs)

Bases: _Node


Returns the linear exponent attenuation coefficient such that :math: lin_attenuation = e^{- alpha length}


frequency – the frequency at which alpha is computed [Hz]


alpha: power attenuation coefficient for f in frequency [Neper/m]


Returns the beta2 chromatic dispersion coefficient as the second order term of the beta function expanded as a Taylor series evaluated at the given frequency


frequency – the frequency at which alpha is computed [Hz]


beta2: beta2 chromatic dispersion coefficient for f in frequency # 1/(m * Hz^2)


Returns the beta3 chromatic dispersion coefficient as the third order term of the beta function expanded as a Taylor series evaluated at the given frequency


frequency – the frequency at which alpha is computed [Hz]


beta3: beta3 chromatic dispersion coefficient for f in frequency # 1/(m * Hz^3)


Returns accumulated chromatic dispersion (CD).


freq – the frequency at which the chromatic dispersion is computed


chromatic dispersion: the accumulated dispersion [s/m]


Returns the raman gain coefficient matrix including the vibrational loss


frequency – the frequency at which cr is computed [Hz]


cr: raman gain coefficient matrix [1 / (W m)]


Returns the nonlinear interference coefficient such that :math: gamma(f) = 2 pi f n_2 c^{-1} A_{eff}^{-1}


frequency – the frequency at which gamma is computed [Hz]


gamma: nonlinear interference coefficient for f in frequency [1/(W m)]

interpolate_parameter_over_spectrum(parameter, ref_frequency, spectrum_frequency, name)
property loss

total loss including padding att_in: useful for polymorphism with roadm loss

property pmd

differential group delay (PMD) [s]

propagate(spectral_info: SpectralInformation)

Modifies the spectral information computing the attenuation, the non-linear interference generation, the CD and PMD accumulation.

property to_json
class gnpy.core.elements.Fused(*args, params=None, **kwargs)

Bases: _Node

property to_json
class gnpy.core.elements.Location(latitude=0, longitude=0, city=None, region=None)

Bases: Location

class gnpy.core.elements.RamanFiber(*args, params=None, **kwargs)

Bases: Fiber

propagate(spectral_info: SpectralInformation)

Modifies the spectral information computing the attenuation, the non-linear interference generation, the CD and PMD accumulation.

property to_json
class gnpy.core.elements.Roadm(*args, params=None, **kwargs)

Bases: _Node


returns the path_type of the impairment if the is is defined

get_per_degree_impairment_id(from_degree, to_degree)

returns the id of the impairment if the degrees are in the per_degree tab

get_per_degree_power(degree, spectral_info)

Get the target power in dBm out of ROADM degree for the spectral information If no equalization is defined on this degree use the ROADM level one.


Get the target power in dBm out of ROADM degree for the reference bandwidth If no equalization is defined on this degree use the ROADM level one.

get_roadm_path(from_degree, to_degree)

Get internal path type impairment

get_roadm_target_power(spectral_info: SpectralInformation = None) Union[float, ndarray]

Computes the power in dBm for a reference carrier or for a spectral information. power is computed based on equalization target. if spectral_info baud_rate is baud_rate = [32e9, 42e9, 64e9, 42e9, 32e9], and target_pch_out_dbm is defined to -20 dbm, then the function returns an array of powers [-20, -20, -20, -20, -20] if target_psd_out_mWperGHz is defined instead with 3.125e-4mW/GHz then it returns [-20, -18.819, -16.9897, -18.819, -20] if instead a reference_baud_rate is defined, the functions computes the result for a single reference carrier whose baud_rate is reference_baudrate

propagate(spectral_info, degree, from_degree)

Equalization targets are read from topology file if defined and completed with default definition of the library. If the input power is lower than the target one, use the input power minus the ROADM loss if is exists, because a ROADM doesn’t amplify, it can only attenuate. There is no difference for add or express : the same target is applied. For the moment propagate operates with spectral info carriers all having the same source or destination.

set_roadm_paths(from_degree, to_degree, path_type, impairment_id=None)

set internal path type: express, drop or add with corresponding impairment

If no impairment id is defined, then use the first profile that matches the path_type in the profile dictionnary.

property to_json
class gnpy.core.elements.Transceiver(*args, **kwargs)

Bases: _Node


Updates the Transceiver property with the CD of the received channels. CD in ps/nm.


Updates the Transceiver property with the latency of the received channels. Latency in ms.


Updates the Transceiver property with the PDL of the received channels. PDL in dB.

_calc_penalty(impairment_value, boundary_list)

Updates the Transceiver property with the PMD of the received channels. PMD in ps.


Updates the Transceiver property with penalties (CD, PMD, etc.) of the received channels in dB. Penalties are linearly interpolated between given points and set to ‘inf’ outside interval.

property to_json

snr_added in 0.1nm compute SNR penalties such as transponder Tx_osnr or Roadm add_drop_osnr only applied in / propagate on the last Trasceiver node of the path all penalties are added in a single call because to avoid uncontrolled cumul

class gnpy.core.elements._Node(uid, name=None, params=None, metadata=None, operational=None, type_variety=None)

Bases: object

Convenience class for providing common functionality of all network elements

This class is just an internal implementation detail; do not assume that all network elements inherit from _Node.

property lat
property latitude
property lng
property loc
property location
property longitude

This module contains functionality for specifying equipment., trx_type_variety='', trx_mode='', error_message=False)

return the trx and SI parameters from eqpt_config for a given type_variety and mode (ie format)

if the type or mode do no match an existing transceiver in the library, then the function raises an error if error_message is True else returns a default mode based on equipment[‘SI’][‘default’] If trx_mode is None (but type is valid), it returns an undetermined mode whatever the error message: this is a special case for automatic mode selection.


Exceptions thrown by other gnpy modules

exception gnpy.core.exceptions.ConfigurationError

Bases: Exception

User-provided configuration contains an error

exception gnpy.core.exceptions.DisjunctionError

Bases: ServiceError

Disjunction of user-provided request can not be satisfied

exception gnpy.core.exceptions.EquipmentConfigError

Bases: ConfigurationError

Incomplete or wrong configuration within the equipment library

exception gnpy.core.exceptions.NetworkTopologyError

Bases: ConfigurationError

Topology of user-provided network is wrong

exception gnpy.core.exceptions.ParametersError

Bases: ConfigurationError

Incomplete or wrong configurations within parameters json

exception gnpy.core.exceptions.ServiceError

Bases: Exception

Service of user-provided request is wrong

exception gnpy.core.exceptions.SpectrumError

Bases: Exception

Spectrum errors of the program

This module contains classes for modelling SpectralInformation.

class float, baud_rate: float, slot_width: float, roll_off: float, tx_osnr: float, tx_power: float, label: str)

Bases: object

One channel in the initial mixed-type spectrum definition, each type being defined by its delta_pdb (power offset with respect to reference power), baud rate, slot_width, roll_off tx_power, and tx_osnr. delta_pdb offset is applied to target power out of Roadm. Label is used to group carriers which belong to the same partition when printing results.

baud_rate: float
delta_pdb: float
label: str
roll_off: float
slot_width: float
tx_osnr: float
tx_power: float
class, frequency, baud_rate, slot_width, roll_off, power, chromatic_dispersion, pmd, pdl, latency)

Bases: Channel

Class containing the parameters of a WDM signal.

  • channel_number – channel number in the WDM grid

  • frequency – central frequency of the signal (Hz)

  • baud_rate – the symbol rate of the signal (Baud)

  • slot_width – the slot width (Hz)

  • roll_off – the roll off of the signal. It is a pure number between 0 and 1

  • ( (power) – power of signal, ASE noise and NLI (W)

  • chromatic_dispersion – chromatic dispersion (s/m)

  • pmd – polarization mode dispersion (s)

  • pdl – polarization dependent loss (dB)

  • latency – propagation latency (s) = 12500000000.0

Channels with unspecified slot width will have their slot width evaluated as the baud rate rounded up to the minimum multiple of the DEFAULT_SLOT_WIDTH_STEP (the baud rate is extended including the roll off in this evaluation)

class, nli, ase)

Bases: Power

carriers power in W

class float, slot_width: float)

Bases: object

Reference channel type is used to determine target power out of ROADM for the reference channel when constant power spectral density (PSD) equalization is set. Reference channel is the type that has been defined in SI block and used for the initial design of the network. Computing the power out of ROADM for the reference channel is required to correctly compute the loss experienced by reference channel in Roadm element.

Baud rate is required to find the target power in constant PSD: power = PSD_target * baud_rate. For example, if target PSD is 3.125e4mW/GHz and reference carrier type a 32 GBaud channel then output power should be -20 dBm and for a 64 GBaud channel power target would need 3 dB more: -17 dBm.

Slot width is required to find the target power in constant PSW (constant power per slot width equalization): power = PSW_target * slot_width. For example, if target PSW is 2e4mW/GHz and reference carrier type a 32 GBaud channel in a 50GHz slot width then output power should be -20 dBm and for a 64 GBaud channel in a 75 GHz slot width, power target would be -18.24 dBm.

Other attributes (like roll-off) may be added there for future equalization purpose.

baud_rate: float
slot_width: float
class array, baud_rate: array, slot_width: array, signal: array, nli: array, ase: array, roll_off: array, chromatic_dispersion: array, pmd: array, pdl: array, latency: array, delta_pdb_per_channel: array, tx_osnr: array, tx_power: array, label: array)

Bases: object

Class containing the parameters of the entire WDM comb.

delta_pdb_per_channel: (per frequency) per channel delta power in dbm for the actual mix of channels

property ase
property baud_rate
property carriers
property channel_number
property chromatic_dispersion
property delta_pdb_per_channel
property df

Matrix of relative frequency distances between all channels. Positive elements in the upper right side.

property frequency
property label
property latency
property nli
property number_of_channels
property pdl
property pmd
property powers
property roll_off
property signal
property slot_width
property tx_osnr
property tx_power dict[float,], power: float) SpectralInformation

Initial spectrum is a dict with key = carrier frequency, and value a Carrier object. :param initial_spectrum: indexed by frequency in Hz, with power offset (delta_pdb), baudrate, slot width, tx_osnr, tx_power and roll off. :param power: power of the request Union[ndarray, Iterable, float], signal: Union[float, ndarray, Iterable], baud_rate: Union[float, ndarray, Iterable], tx_osnr: Union[float, ndarray, Iterable], tx_power: Union[float, ndarray, Iterable] = None, delta_pdb_per_channel: Union[float, ndarray, Iterable] = 0.0, slot_width: Union[float, ndarray, Iterable] = None, roll_off: Union[float, ndarray, Iterable] = 0.0, chromatic_dispersion: Union[float, ndarray, Iterable] = 0.0, pmd: Union[float, ndarray, Iterable] = 0.0, pdl: Union[float, ndarray, Iterable] = 0.0, latency: Union[float, ndarray, Iterable] = 0.0, label: Union[str, ndarray, Iterable] = None)

This is just a wrapper around the SpectralInformation.__init__() that simplifies the creation of a non-uniform spectral information with NLI and ASE powers set to zero., f_max, roll_off, baud_rate, spacing, tx_osnr, tx_power, delta_pdb=0)

Creates a fixed slot width spectral information with flat power. all arguments are scalar values

Working with networks which consist of network elements, fibers, default_con_in, default_con_out, EOL)

Add default connector loss if no loss are defined. EOL repair margin is added as a connector loss, fibers, padding, equipment)

Add a padding att_in at the input of the 1st fiber of a succession of fibers and fused, fiber), equipment)

Autodesign network: add missing elements. split fibers if their length is too big add ROADM preamp or booster and inline amplifiers between fibers, equipment)

Fill in connector loss with default values. Add the padding loss is required. EOL is added as a connector loss, roadm), roadm), equipment, pref_ch_db, pref_total_db, set_connector_losses=True, verbose=True)

Set roadm equalization target and amplifier gain and power, bounds, target_length)

If fiber is over boundary, then assume this is a link “intent” and computes the set of identical fiber spans this link should be composed of., network, equipment, set_connector_losses=True, verbose=True)

Network is designed according to reference channel. Verbose indicate if the function should print all warnings or not, variety_type, equipment), equipment, power_dbm)

If node is RamanFiber, then estimate the possible Raman gain if any for this purpose computes stimulated_raman_scattering loss_profile. This may be time consuming., node)

Fused node interest: returns the 1st node at the origin of a succession of fused nodes (aka no amp in between), node)

Fused node interest: returns the last node in a succession of fused nodes (aka no amp in between), network)

get_next node else raise tha appropriate error, node)

fused spans interest: iterate over all predecessors while they are either Fused or Fibers preceded by Fused, node)

fused spans interest: iterate over all predecessors while they are either Fused or Fibers succeeded by Fused, gain_target, power_target, equipment, uid, restrictions=None, verbose=True)

amplifer selection algorithm @Orange Jean-Luc Augé, power_target, power_mode), this_node, equipment, pref_ch_db, pref_total_db, verbose)

This node can be a transceiver or a ROADM (same function called in both cases). go through each link staring from this_node until next Roadm or Transceiver and set gain and delta_p according to configurations set by user. power_mode = True, set amplifiers delta_p and effective_gain power_mode = False, set amplifiers effective_gain and ignore delta_p config: set it to None, fiber, equipment, pref_ch_db)

Set reference powers at fiber input for a reference channel. Supposes that target power out of ROADMs and amplifiers are consistent. This is only for visualisation purpose, roadm, equipment, pref_ch_db)

Set reference powers at ROADM input for a reference channel and based on the adjacent OMS. This supposes that there is no dependency on path. For example, the succession: node power out of element roadm A (target power -10dBm) -10dBm fiber A (16 dB loss) -26dBm roadm B (target power -12dBm) -26dBm fiber B (10 dB loss) -36dBm roadm C (target power -14dBm) -36dBm is not consistent because target powers in roadm B and roadm C can not be met. input power for the reference channel will be set -26 dBm in roadm B and -22dBm in roadm C, because at design time we can not know about path. The function raises a warning if target powers can not be met with the design. User should be aware that design was not successfull and that power reduction was applied. Note that this value is only used for visualisation purpose (to compute ROADM loss in elements)., network)

Set ROADM path types (express, add, drop)

Uses implicit guess if no information is set in ROADM, network)

Set target powers/PSD on all degrees This is needed to populate per_degree_pch_out_dbm or per_degree_pch_psd or per_degree_pch_psw dicts when they are not initialized by users., equipment)

ref_carrier records carrier information used for design and usefull for equalization, node, equipment, input_power=None)

Total loss of a span (Fiber and Fused nodes) which contains the given node Do not recompute, if it was already computed: records it in design_span_loss, fiber, bounds, target_length)

If fiber length exceeds boundary then assume this is a link “intent”, and replace this one-span link with an n_spans link, with identical fiber types., node, equipment)

Computes target power using J. -L. Auge, V. Curri and E. Le Rouzic, Open Design for Multi-Vendor Optical Networks, OFC 2019. equation 4


This module contains all parameters to configure standard network elements.

class gnpy.core.parameters.EdfaOperational(**operational)

Bases: object

default_values = {'delta_p': None, 'gain_target': None, 'out_voa': None, 'tilt_target': 0}
class gnpy.core.parameters.EdfaParams(**params)

Bases: object

default_values = {'advance_configurations_from_json': None, 'allowed_for_design': False, 'bands': [], 'booster_variety': None, 'dgt': None, 'dual_stage_model': None, 'f_max': 196100000000000.0, 'f_min': 191300000000000.0, 'f_ripple_ref': None, 'gain_flatmax': None, 'gain_min': None, 'gain_ripple': 0, 'multi_band': None, 'nf0': None, 'nf_coef': None, 'nf_fit_coeff': None, 'nf_max': None, 'nf_min': None, 'nf_model': None, 'nf_ripple': 0, 'out_voa_auto': False, 'p_max': None, 'pdl': 0, 'pmd': 0, 'preamp_variety': None, 'raman': False, 'tilt_ripple': 0, 'type_def': '', 'type_variety': ''}
class gnpy.core.parameters.FiberParams(**kwargs)

Bases: Parameters

property att_in
property con_in
property con_out
property dispersion
property dispersion_slope
effective_area_overlap(frequency_stokes_wave, frequency_pump)
property f_dispersion_ref
property f_loss_ref
property gamma
property latency
property length
property loss_coef
property lumped_losses
property pmd_coef
property raman_coefficient
property ref_frequency
property ref_wavelength
class gnpy.core.parameters.FusedParams(**kwargs)

Bases: Parameters

class gnpy.core.parameters.NLIParams(method='gn_model_analytic', dispersion_tolerance=1, phase_shift_tolerance=0.1, computed_channels=None, computed_number_of_channels=None)

Bases: Parameters

class gnpy.core.parameters.Parameters

Bases: object

class gnpy.core.parameters.PumpParams(power, frequency, propagation_direction)

Bases: Parameters

class gnpy.core.parameters.RamanGainCoefficient(normalized_gamma_raman, frequency_offset)

Bases: RamanGainCoefficient

Raman Gain Coefficient Parameters

Based on:

Andrea D’Amico, Bruno Correia, Elliot London, Emanuele Virgillito, Giacomo Borraccini, Antonio Napoli, and Vittorio Curri, “Scalable and Disaggregated GGN Approximation Applied to a C+L+S Optical Network,” J. Lightwave Technol. 40, 3499-3511 (2022) Section III.D

class gnpy.core.parameters.RamanParams(flag=False, result_spatial_resolution=10000.0, solver_spatial_resolution=50)

Bases: Parameters

class gnpy.core.parameters.RoadmImpairment(params)

Bases: object

Generic definition of impairments for express, add and drop

class gnpy.core.parameters.RoadmParams(**kwargs)

Bases: Parameters


Get the ROADM list of profiles for impairments definition

transform the ietf model into gnpy internal model: add a path-type in the attributes

class gnpy.core.parameters.RoadmPath(from_degree, to_degree, path_type, impairment_id=None, impairment=None)

Bases: object

class gnpy.core.parameters.SimParams

Bases: Parameters

_shared_dict = {'nli_params': <gnpy.core.parameters.NLIParams object>, 'raman_params': <gnpy.core.parameters.RamanParams object>}
property nli_params
property raman_params
classmethod set_params(sim_params)


Solver definitions to calculate the Raman effect and the nonlinear interference noise

The solvers take as input instances of the spectral information, the fiber and the simulation parameters

class gnpy.core.science_utils.NliSolver

Bases: object

This class implements the NLI models. Model and method can be specified in sim_params.nli_params.method. List of implemented methods: ‘gn_model_analytic’: eq. 120 from arXiv:1209.0394 ‘ggn_spectrally_separated’: eq. 21 from arXiv: 1710.02225

SPM_WEIGHT = 0.5925925925925926
XPM_WEIGHT = 1.1851851851851851
static _fast_generalized_psi(f_eval, cut_frequency, cut_baud_rate, cut_roll_off, pump_frequency, pump_baud_rate, pump_roll_off, f_cut_resolution, srs, alpha, beta2, beta3, f_ref_beta)

Computes the generalized psi function similarly to the one used in the GN model.

static _frequency_offset_threshold(beta2, symbol_rate)
static _generalized_psi(f_eval, cut_frequency, cut_baud_rate, cut_roll_off, pump_frequency, pump_baud_rate, pump_roll_off, f_cut_resolution, f_pump_resolution, srs, alpha, beta2, beta3, f_ref_beta)

Computes the generalized psi function similarly to the one used in the GN model.

static _generalized_rho_nli(delta_beta, rho_pump, z, alpha)
static _ggn_spectrally_separated(cut_indices, spectral_info, fiber, srs, spm_weight=0.5925925925925926, xpm_weight=1.1851851851851851)

Computes the nonlinear interference power evaluated at the fiber input. The method uses eq. 21 from arXiv: 1710.02225

static _gn_analytic(spectral_info, fiber, spm_weight=0.5925925925925926, xpm_weight=1.1851851851851851)

Computes the nonlinear interference power evaluated at the fiber input. The method uses eq. 120 from arXiv:1209.0394

static _psi(df, baud_rate, beta2, effective_length, asymptotic_length)

Calculates eq. 123 from arXiv:1209.0394

static compute_nli(spectral_info: SpectralInformation, srs: StimulatedRamanScattering, fiber)

Compute NLI power generated by the WDM comb *carriers on the channel under test carrier at the end of the fiber span.

static effective_length(alpha, length)

The effective length identify the region in which the NLI has a significant contribution to the signal degradation.

class gnpy.core.science_utils.RamanSolver

Bases: object

This class contains the methods to calculate the Raman scattering effect.

static _create_lumped_losses(z, lumped_losses, z_lumped_losses)
static calculate_attenuation_profile(spectral_info: SpectralInformation, fiber)

Evaluates the attenuation profile along the z axis for all the frequency propagating in the fiber without considering the stimulated Raman scattering.

static calculate_spontaneous_raman_scattering(spectral_info: SpectralInformation, srs: StimulatedRamanScattering, fiber)

Evaluates the Raman profile along the z axis for all the frequency propagated in the fiber including the Raman pumps co- and counter-propagating.

static calculate_stimulated_raman_scattering(spectral_info: SpectralInformation, fiber)

Evaluates the Raman profile along the z axis for all the frequency propagated in the fiber including the Raman pumps co- and counter-propagating

static first_order_derivative_solution(power_in, alpha, cr, z, lumped_losses)

Solves the Raman first order derivative equation

  • power_in – launch power array

  • alpha – loss coefficient array

  • cr – Raman efficiency coefficients matrix

  • z – z position array

  • lumped_losses – concentrated losses array along the fiber span


power profile matrix

static iterative_algorithm(co_initial_guess_power, cnt_initial_guess_power, co_frequency, cnt_frequency, z, fiber, lumped_losses)

Solves the Raman first order derivative equation in case of both co- and counter-propagating frequencies

  • co_initial_guess_power – co-propagationg Raman first order derivative equation solution

  • cnt_initial_guess_power – counter-propagationg Raman first order derivative equation solution

  • co_frequency – co-propagationg frequencies

  • cnt_frequency – counter-propagationg frequencies

  • z – z position array

  • fiber – instance of gnpy.core.elements.Fiber or gnpy.core.elements.RamanFiber

  • lumped_losses – concentrated losses array along the fiber span


co- and counter-propagatng power profile matrix

class gnpy.core.science_utils.StimulatedRamanScattering(power_profile, loss_profile, frequency, z)

Bases: object

gnpy.core.science_utils.estimate_nf_model(type_variety, gain_min, gain_max, nf_min, nf_max)
gnpy.core.science_utils.raised_cosine(frequency, channel_frequency, channel_baud_rate, channel_roll_off)

Returns a unitary raised cosine profile for the given parame

  • frequency – numpy array of frequencies in Hz for the resulting raised cosine

  • channel_frequency – channel frequencies in Hz

  • channel_baud_rate – channel baud rate in Hz

  • channel_roll_off – channel roll off


This module contains utility functions that are used with gnpy.

gnpy.core.utils.arrange_frequencies(length, start, stop)

Create an array of frequencies

  • length (integer) – number of elements

  • start (float) – Start frequency in THz

  • stop (float) – Stop frequency in THz


an array of frequencies determined by the spacing parameter

Return type


gnpy.core.utils.automatic_fmax(f_min, spacing, nch)

Find the high-frequenecy boundary of a spectrum

:param f_min Start of the spectrum (lowest frequency edge) [Hz] :param spacing Grid/channel spacing [Hz] :param nch Number of channels :return End of the spectrum (highest frequency) [Hz]

>>> automatic_fmax(191.325e12, 50e9, 96)
gnpy.core.utils.automatic_nch(f_min, f_max, spacing)

How many channels are available in the spectrum

:param f_min Lowest frequenecy [Hz] :param f_max Highest frequency [Hz] :param spacing Channel width [Hz] :return Number of uniform channels

>>> automatic_nch(191.325e12, 196.125e12, 50e9)
>>> automatic_nch(193.475e12, 193.525e12, 50e9)
gnpy.core.utils.calculate_absolute_min_or_zero(x: array) array

Calculates the element-wise absolute minimum between the x and zero.

Parameters: x (array): The first input array.

Returns: array: The element-wise absolute minimum between x and zero.

Example: >>> x = array([-1, 2, -3]) >>> calculate_absolute_min_or_zero(x) array([1., 0., 3.])

gnpy.core.utils.convert_length(value, units)

Convert length into basic SI units

>>> convert_length(1, 'km')
>>> convert_length(2.0, 'km')
>>> convert_length(123, 'm')
>>> convert_length(123.0, 'm')
>>> convert_length(42.1, 'km')
>>> convert_length(666, 'yards')
Traceback (most recent call last):
gnpy.core.exceptions.ConfigurationError: Cannot convert length in "yards" into meters

Convert logarithimic units to linear

>>> round(db2lin(10.0), 2)
>>> round(db2lin(20.0), 2)
>>> round(db2lin(1.0), 2)
>>> round(db2lin(0.0), 2)
>>> round(db2lin(-10.0), 2)

Convert dBm units to Watt

>>> round(dbm2watt(0), 4)
>>> round(dbm2watt(-3), 4)
>>> round(dbm2watt(13), 4)
gnpy.core.utils.deltaf2deltawl(delta_f, frequency)

convert delta frequency to delta wavelength

Units for delta_wl and wavelength must be same.

  • delta_f (float or numpy.ndarray) – delta frequency in same units as frequency

  • frequency (float) – frequency BW is relevant for


The BW in wavelength units

Return type

float or ndarray

gnpy.core.utils.deltawl2deltaf(delta_wl, wavelength)

deltawl2deltaf(delta_wl, wavelength): delta_wl is BW in wavelength units wavelength is the center wl units for delta_wl and wavelength must be same

  • delta_wl (float or numpy.ndarray) – delta wavelength BW in same units as wavelength

  • wavelength (float) – wavelength BW is relevant for


The BW in frequency units

Return type

float or ndarray


Converts frequency units to wavelength units.

>>> round(freq2wavelength(191.35e12) * 1e9, 3)
>>> round(freq2wavelength(196.1e12) * 1e9, 3)

Convert linear unit to logarithmic (dB)

>>> lin2db(0.001)
>>> round(lin2db(1.0), 2)
>>> round(lin2db(1.26), 2)
>>> round(lin2db(10.0), 2)
>>> round(lin2db(100.0), 2)
gnpy.core.utils.merge_amplifier_restrictions(dict1, dict2)

Update contents of dicts recursively

>>> d1 = {'params': {'restrictions': {'preamp_variety_list': [], 'booster_variety_list': []}}}
>>> d2 = {'params': {'target_pch_out_db': -20}}
>>> merge_amplifier_restrictions(d1, d2)
{'params': {'restrictions': {'preamp_variety_list': [], 'booster_variety_list': []}, 'target_pch_out_db': -20}}
>>> d3 = {'params': {'restrictions': {'preamp_variety_list': ['foo'], 'booster_variety_list': ['bar']}}}
>>> merge_amplifier_restrictions(d1, d3)
{'params': {'restrictions': {'preamp_variety_list': [], 'booster_variety_list': []}}}

Order frequency slots from larger slots to smaller ones up to None

>>> l = [{'N': 3, 'M': None}, {'N': 2, 'M': 1}, {'N': None, 'M': None},{'N': 7, 'M': 2},{'N': None, 'M': 1} , {'N': None, 'M': 0}]
>>> order_slots(l)
([7, 2, None, None, 3, None], [2, 1, 1, 0, None, None], [3, 1, 4, 5, 0, 2])
gnpy.core.utils.per_label_average(values, labels)

computes the average per defined spectrum band, using labels

>>> labels = ['A', 'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'C', 'D', 'D', 'D', 'D']
>>> values = [28.51, 28.23, 28.15, 28.17, 28.36, 28.53, 28.64, 28.68, 28.7, 28.71, 28.72, 28.73, 28.74, 28.91, 27.96, 27.85, 27.87, 28.02]
>>> per_label_average(values, labels)
{'A': 28.28, 'B': 28.68, 'C': 28.91, 'D': 27.92}
gnpy.core.utils.power_dbm_to_psd_mw_ghz(power_dbm, baudrate_baud)

computes power spectral density in mW/GHz based on baudrate in bauds and power in dBm

>>> power_dbm_to_psd_mw_ghz(0, 64e9)
>>> round(power_dbm_to_psd_mw_ghz(3, 64e9), 6)
>>> round(power_dbm_to_psd_mw_ghz(3, 32e9), 6)

Build a prettty string that shows the summary dict values per label with 2 digits

gnpy.core.utils.psd2powerdbm(psd_mwperghz, baudrate_baud)

computes power in dBm based on baudrate in bauds and psd in mW/GHz

>>> round(psd2powerdbm(0.031176, 64e9),3)
>>> round(psd2powerdbm(0.062352, 32e9),3)
>>> round(psd2powerdbm(0.015625, 64e9),3)
gnpy.core.utils.psd_mw_per_ghz(power_watt, baudrate_baud)

computes power spectral density in mW/GHz based on baudrate in bauds and power in W

>>> psd_mw_per_ghz(2e-3, 32e9)
>>> psd_mw_per_ghz(1e-3, 64e9)
>>> psd_mw_per_ghz(0.5e-3, 32e9)

Replaces None with inf values in a frequency slots dict

>>> replace_none({'N': 3, 'M': None})
{'N': 3, 'M': inf}
gnpy.core.utils.restore_order(elements, order)

Use order to re-order the element of the list, and ignore None values

>>> restore_order([7, 2, None, None, 3, None], [3, 1, 4, 5, 0, 2])
[3, 2, 7]
gnpy.core.utils.round2float(number, step)

Round a floating point number so that its “resolution” is not bigger than ‘step’

The finest step is fixed at 0.01; smaller values are silently changed to 0.01.

>>> round2float(123.456, 1000)
>>> round2float(123.456, 100)
>>> round2float(123.456, 10)
>>> round2float(123.456, 1)
>>> round2float(123.456, 0.1)
>>> round2float(123.456, 0.01)
>>> round2float(123.456, 0.001)
>>> round2float(123.249, 0.5)
>>> round2float(123.250, 0.5)
>>> round2float(123.251, 0.5)
>>> round2float(123.300, 0.2)
>>> round2float(123.301, 0.2)
gnpy.core.utils.rrc(ffs, baud_rate, alpha)

compute the root-raised cosine filter function

  • ffs (numpy.ndarray) – A numpy array of frequencies

  • baud_rate (float) – The Baud Rate of the System

  • alpha (float) – The roll-off factor of the filter


hf a numpy array of the filter shape

Return type


gnpy.core.utils.silent_remove(this_list, elem)

Remove matching elements from a list without raising ValueError

>>> li = [0, 1]
>>> li = silent_remove(li, 1)
>>> li
>>> li = silent_remove(li, 1)
>>> li
gnpy.core.utils.snr_sum(snr, bw, snr_added, bw_added=12500000000.0)

Convert Watt units to dBm

>>> round(watt2dbm(0.001), 1)
>>> round(watt2dbm(0.02), 1)
gnpy.core.utils.write_csv(obj, filename)

Convert dictionary items to a CSV file the dictionary format:

{'result category 1':
                # 1st line of results
                {'header 1' : value_xxx,
                 'header 2' : value_yyy},
                 # 2nd line of results: same headers, different results
                {'header 1' : value_www,
                 'header 2' : value_zzz}
'result_category 2':

The generated csv file will be:

result_category 1
header 1    header 2
value_xxx   value_yyy
value_www   value_zzz
result_category 2