Files
oopt-gnpy/gnpy/core/equipment.py
Jean-Luc Auge 8e046a9b50 Implement default values in xls parser for empty cells
*namedtuple default values are only applied if the cell is not read
*if the cell is read but is empty '', there is a need to provide default
values: which is what this fix does
*sanity checks are reinforced :
	-node_type is replaced by ROADM if degree <> 2: notify user
(print)
	-check that node type is in ('ILA','ROADM','FUSED')

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-04-22 19:06:35 -04:00

120 lines
5.2 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
'''
nf model parameters calculation
calculate nf1, nf2 and Delta_P of a 2 coils edfa with internal VOA
from nf_min and nf_max inputs
'''
import numpy as np
from gnpy.core.utils import lin2db, db2lin, load_json
GAIN_MIN_FIELD = "gain_min"
GAIN_MAX_FIELD = "gain_flatmax"
NF_MIN_FIELD ="nf_min"
NF_MAX_FIELD = "nf_max"
DEFAULT_CONFIG_JSON_FILENAME = 'default_edfa_config.json'
ADVANCED_CONFIG_JSON_FILENAME = 'advanced_config_from_json'
def nf_model(amp_dict):
gain_min = amp_dict[GAIN_MIN_FIELD]
gain_max = amp_dict[GAIN_MAX_FIELD]
try:
nf_min = amp_dict.get(NF_MIN_FIELD,-100)
nf_max = amp_dict.get(NF_MAX_FIELD,-100)
if nf_min<-10 or nf_max<-10:
raise ValueError
except ValueError:
print(f'invalid or missing nf_min or nf_max values in eqpt_config.json for {amp_dict["type_variety"]}')
nf_min = amp_dict.get(NF_MIN_FIELD,-100)
nf_max = amp_dict.get(NF_MAX_FIELD,-100)
#use NF estimation model based on NFmin and NFmax in json OA file
delta_p = 5 #max power dB difference between 1st and 2nd stage coils
#dB g1a = (1st stage gain) - (internal voa attenuation)
g1a_min = gain_min - (gain_max-gain_min) - delta_p
g1a_max = gain_max - delta_p
#nf1 and nf2 are the nf of the 1st and 2nd stage coils
#calculate nf1 and nf2 values that solve nf_[min/max] = nf1 + nf2 / g1a[min/max]
nf2 = lin2db((db2lin(nf_min) - db2lin(nf_max)) / (1/db2lin(g1a_max)-1/db2lin(g1a_min)))
nf1 = lin2db(db2lin(nf_min)- db2lin(nf2)/db2lin(g1a_max)) #expression (1)
""" now checking and recalculating the results:
recalculate delta_p to check it is within [1-6] boundaries
This is to check that the nf_min and nf_max values from the json file
make sense. If not a warning is printed """
if nf1 < 4:
print('1st coil nf calculated value {} is too low: revise inputs'.format(nf1))
if nf2 < nf1 + 0.3 or nf2 > nf1 + 2:
"""nf2 should be with [nf1+0.5 - nf1 +2] boundaries
there shouldn't be very high nf differences between 2 coils
=> recalculate delta_p
"""
nf2 = max(nf2, nf1+0.3)
nf2 = min(nf2, nf1+2)
g1a_max = lin2db(db2lin(nf2) / (db2lin(nf_min) - db2lin(nf1))) #use expression (1)
delta_p = gain_max - g1a_max
g1a_min = gain_min - (gain_max-gain_min) - delta_p
if delta_p < 1 or delta_p > 6:
#delta_p should be > 1dB and < 6dB => consider user warning if not
print('1st coil vs 2nd coil calculated DeltaP {} is not valid: revise inputs'
.format(delta_p))
#check the calculated values for nf1 & nf2:
nf_min_calc = lin2db(db2lin(nf1) + db2lin(nf2)/db2lin(g1a_max))
nf_max_calc = lin2db(db2lin(nf1) + db2lin(nf2)/db2lin(g1a_min))
if (abs(nf_min_calc-nf_min) > 0.01) or (abs(nf_max_calc-nf_max) > 0.01):
print('nf model calculation failed with nf_min {} and nf_max {} calculated'
.format(nf_min_calc, nf_max_calc))
return (nf1, nf2, delta_p)
def read_eqpt_library(filename):
"""build global dictionnary eqpt_library that stores all eqpt characteristics:
edfa type type_variety, fiber type_variety
from the eqpt_config.json (filename parameter)
also read advanced_config_from_json file parameters for edfa if they are available:
typically nf_ripple, dfg gain ripple, dgt and nf polynomial nf_fit_coeff
if advanced_config_from_json file parameter is not present: use nf_model:
requires nf_min and nf_max values boundaries of the edfa gain range
"""
global eqpt_library
eqpt_library = load_json(filename)
for i, el in enumerate(eqpt_library['Edfa']):
dict_nf_model = {}
if 'advanced_config_from_json' in el:
#use advanced amplifier model with full ripple characterization
config_json_filename = el.pop(ADVANCED_CONFIG_JSON_FILENAME)
dict_nf_model['nf_model'] = {'enabled': False}
else:
#use a default ripple model (only default dgt is defined)
config_json_filename = DEFAULT_CONFIG_JSON_FILENAME
(nf1, nf2, delta_p) = nf_model(el)
#remove nf_min and nf_max field and replace by nf1, nf2 & delta_p
nf_min = el.pop('nf_min','')
nf_max = el.pop('nf_max','')
dict_nf_model['nf_model'] = dict(zip(["enabled","nf1","nf2","delta_p"],[True,nf1,nf2,delta_p]))
json_data = load_json(config_json_filename)
eqpt_library['Edfa'][i] = {**el, **json_data, **dict_nf_model}
def get_eqpt_params(eqpt_name):
"""returns the params attributs of an Edfa or Fiber
by finding it in the eqpt_library
input parameter eqpt_name = type_variety of the eqpt
"""
eqpt_config={}
try:
#go through the eqpt library to find the demanded type_variety
eqpt = next(eqpt for eqpt_type in eqpt_library
for eqpt in eqpt_library[eqpt_type]
if eqpt.get('type_variety','') == eqpt_name)
eqpt_config = dict(eqpt)
del eqpt_config['type_variety']
except StopIteration as e:
print(f'cannot find eqpt {eqpt_name} in eqpt library')
#TODO log it
return eqpt_config