mirror of
https://github.com/Telecominfraproject/oopt-gnpy.git
synced 2025-11-01 18:47:48 +00:00
Let's use the pythonic indenting, quoting and structure in general as specified in PEP 0257. Change-Id: Icd0b4fbd94dabd9a163ae3f6887b236e76c486ab
199 lines
7.0 KiB
Python
199 lines
7.0 KiB
Python
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
# @Author: Jean-Luc Auge
|
|
# @Date: 2018-02-02 14:06:55
|
|
|
|
from numpy import zeros, array
|
|
from gnpy.core.elements import Transceiver, Edfa
|
|
from gnpy.core.utils import automatic_fmax, lin2db, db2lin, merge_amplifier_restrictions
|
|
from gnpy.core.info import create_input_spectral_information, ReferenceCarrier
|
|
from gnpy.core.network import build_network
|
|
from gnpy.tools.json_io import load_network, load_equipment
|
|
from pathlib import Path
|
|
import pytest
|
|
|
|
TEST_DIR = Path(__file__).parent
|
|
DATA_DIR = TEST_DIR / 'data'
|
|
test_network = DATA_DIR / 'test_network.json'
|
|
eqpt_library = DATA_DIR / 'eqpt_config.json'
|
|
|
|
# TODO in elements.py code: pytests doesn't pass with 1 channel: interpolate fail
|
|
|
|
|
|
@pytest.fixture(
|
|
params=[(96, 0.05e12), (60, 0.075e12), (45, 0.1e12), (2, 0.1e12)],
|
|
ids=['50GHz spacing', '75GHz spacing', '100GHz spacing', '2 channels'])
|
|
def nch_and_spacing(request):
|
|
"""parametrize channel count vs channel spacing (Hz)"""
|
|
yield request.param
|
|
|
|
|
|
@pytest.fixture()
|
|
def bw():
|
|
"""parametrize signal bandwidth (Hz)"""
|
|
return 45e9
|
|
|
|
|
|
@pytest.fixture()
|
|
def setup_edfa_variable_gain():
|
|
"""init edfa class by reading test_network.json file
|
|
remove all gain and nf ripple"""
|
|
equipment = load_equipment(eqpt_library)
|
|
network = load_network(test_network, equipment)
|
|
build_network(network, equipment, 0, 20)
|
|
edfa = [n for n in network.nodes() if isinstance(n, Edfa)][0]
|
|
edfa.gain_ripple = zeros(96)
|
|
edfa.interpol_nf_ripple = zeros(96)
|
|
yield edfa
|
|
|
|
|
|
@pytest.fixture()
|
|
def setup_edfa_fixed_gain():
|
|
"""init edfa class by reading the 2nd edfa in test_network.json file"""
|
|
equipment = load_equipment(eqpt_library)
|
|
network = load_network(test_network, equipment)
|
|
build_network(network, equipment, 0, 20)
|
|
edfa = [n for n in network.nodes() if isinstance(n, Edfa)][1]
|
|
yield edfa
|
|
|
|
|
|
@pytest.fixture()
|
|
def setup_trx():
|
|
"""init transceiver class to access snr and osnr calculations"""
|
|
equipment = load_equipment(eqpt_library)
|
|
network = load_network(test_network, equipment)
|
|
build_network(network, equipment, 0, 20)
|
|
trx = [n for n in network.nodes() if isinstance(n, Transceiver)][0]
|
|
return trx
|
|
|
|
|
|
@pytest.fixture()
|
|
def si(nch_and_spacing, bw):
|
|
"""parametrize a channel comb with nb_channel, spacing and signal bw"""
|
|
nb_channel, spacing = nch_and_spacing
|
|
f_min = 191.3e12
|
|
f_max = automatic_fmax(f_min, spacing, nb_channel)
|
|
return create_input_spectral_information(f_min=f_min, f_max=f_max, roll_off=0.15, baud_rate=bw, power=1e-3,
|
|
spacing=spacing, tx_osnr=40.0,
|
|
ref_carrier=ReferenceCarrier(baud_rate=32e9, slot_width=50e9))
|
|
|
|
|
|
@pytest.mark.parametrize("gain, nf_expected", [(10, 15), (15, 10), (25, 5.8)])
|
|
def test_variable_gain_nf(gain, nf_expected, setup_edfa_variable_gain, si):
|
|
"""=> unitary test for variable gain model Edfa._calc_nf() (and Edfa.interpol_params)"""
|
|
edfa = setup_edfa_variable_gain
|
|
si.signal /= db2lin(gain)
|
|
si.nli /= db2lin(gain)
|
|
si.ase /= db2lin(gain)
|
|
edfa.operational.gain_target = gain
|
|
si.pref = si.pref._replace(p_span0=0, p_spani=-gain)
|
|
edfa.interpol_params(si)
|
|
result = edfa.nf
|
|
assert pytest.approx(nf_expected, abs=0.01) == result[0]
|
|
|
|
|
|
@pytest.mark.parametrize("gain, nf_expected", [(15, 10), (20, 5), (25, 5)])
|
|
def test_fixed_gain_nf(gain, nf_expected, setup_edfa_fixed_gain, si):
|
|
"""=> unitary test for fixed gain model Edfa._calc_nf() (and Edfa.interpol_params)"""
|
|
edfa = setup_edfa_fixed_gain
|
|
si.signal /= db2lin(gain)
|
|
si.nli /= db2lin(gain)
|
|
si.ase /= db2lin(gain)
|
|
edfa.operational.gain_target = gain
|
|
si.pref = si.pref._replace(p_span0=0, p_spani=-gain)
|
|
edfa.interpol_params(si)
|
|
assert pytest.approx(nf_expected, abs=0.01) == edfa.nf[0]
|
|
|
|
|
|
def test_si(si, nch_and_spacing):
|
|
"""basic total power check of the channel comb generation"""
|
|
nb_channel = nch_and_spacing[0]
|
|
p_tot = sum(si.signal + si.ase + si.nli)
|
|
expected_p_tot = si.signal[0] * nb_channel
|
|
assert pytest.approx(expected_p_tot, abs=0.01) == p_tot
|
|
|
|
|
|
@pytest.mark.parametrize("gain", [17, 19, 21, 23])
|
|
def test_compare_nf_models(gain, setup_edfa_variable_gain, si):
|
|
"""compare the 2 amplifier models (polynomial and estimated from nf_min and max)
|
|
=> nf_model vs nf_poly_fit for intermediate gain values:
|
|
between gain_min and gain_flatmax some discrepancy is expected but target < 0.5dB
|
|
=> unitary test for Edfa._calc_nf (and Edfa.interpol_params)"""
|
|
edfa = setup_edfa_variable_gain
|
|
si.signal /= db2lin(gain)
|
|
si.nli /= db2lin(gain)
|
|
si.ase /= db2lin(gain)
|
|
edfa.operational.gain_target = gain
|
|
# edfa is variable gain type
|
|
si.pref = si.pref._replace(p_span0=0, p_spani=-gain)
|
|
edfa.interpol_params(si)
|
|
nf_model = edfa.nf[0]
|
|
|
|
# change edfa type variety to a polynomial
|
|
el_config = {
|
|
"uid": "Edfa1",
|
|
"operational": {
|
|
"gain_target": gain,
|
|
"tilt_target": 0
|
|
},
|
|
"metadata": {
|
|
"location": {
|
|
"region": "",
|
|
"latitude": 2,
|
|
"longitude": 0
|
|
}
|
|
}
|
|
}
|
|
equipment = load_equipment(eqpt_library)
|
|
extra_params = equipment['Edfa']['CienaDB_medium_gain']
|
|
temp = el_config.setdefault('params', {})
|
|
temp = merge_amplifier_restrictions(temp, extra_params.__dict__)
|
|
el_config['params'] = temp
|
|
edfa = Edfa(**el_config)
|
|
|
|
# edfa is variable gain type
|
|
edfa.interpol_params(si)
|
|
nf_poly = edfa.nf[0]
|
|
print(nf_poly, nf_model)
|
|
assert pytest.approx(nf_model, abs=0.5) == nf_poly
|
|
|
|
|
|
@pytest.mark.parametrize("gain", [13, 15, 17, 19, 21, 23, 25, 27])
|
|
def test_ase_noise(gain, si, setup_trx, bw):
|
|
"""testing 3 different ways of calculating osnr:
|
|
1-pin-edfa.nf+58 vs
|
|
2-pout/pase afet propagate
|
|
3-Transceiver osnr_ase_01nm
|
|
=> unitary test for Edfa.noise_profile (Edfa.interpol_params, Edfa.propagate)"""
|
|
equipment = load_equipment(eqpt_library)
|
|
network = load_network(test_network, equipment)
|
|
edfa = next(n for n in network.nodes() if n.uid == 'Edfa1')
|
|
span = next(n for n in network.nodes() if n.uid == 'Span1')
|
|
# update span1 and Edfa1 according to new gain before building network
|
|
# updating span 1 avoids to overload amp
|
|
span.params.length = gain * 1e3 / 0.2
|
|
edfa.operational.gain_target = gain
|
|
build_network(network, equipment, 0, 20)
|
|
edfa.gain_ripple = zeros(96)
|
|
edfa.interpol_nf_ripple = zeros(96)
|
|
# propagate in span1 to have si with the correct power level
|
|
si = span(si)
|
|
print(span)
|
|
|
|
si.pref = si.pref._replace(p_span0=0, p_spani=-gain)
|
|
edfa.interpol_params(si)
|
|
nf = edfa.nf
|
|
print('nf', nf)
|
|
pin = lin2db((si.signal[0] + si.ase[0] + si.nli[0]) * 1e3)
|
|
osnr_expected = pin - nf[0] + 58
|
|
|
|
si = edfa(si)
|
|
print(edfa)
|
|
osnr = lin2db(si.signal[0] / si.ase[0]) - lin2db(12.5e9 / bw)
|
|
assert pytest.approx(osnr_expected, abs=0.01) == osnr
|
|
|
|
trx = setup_trx
|
|
si = trx(si)
|
|
osnr = trx.osnr_ase_01nm[0]
|
|
assert pytest.approx(osnr_expected, abs=0.01) == osnr
|