Advanced xls input support: Nodes & Links reading

Parse advanced fiber parameters from xls into json format:
accept a .xls or a .json input parameter
creates the corresponding .json file
read east/west directions for fiber parameters (fber type, distance...)
read node type (ILA or ROADM)
provide default values if fields are missing
    => full backward compatibility to read the original CORONET xls

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
This commit is contained in:
Jean-Luc Auge
2018-04-06 15:29:48 +02:00
committed by James Powell
parent 8d6f69eb05
commit 1b808afd5d
6 changed files with 10519 additions and 141 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -6,62 +6,164 @@ try:
except ModuleNotFoundError:
exit('Required: `pip install xlrd`')
from argparse import ArgumentParser
from collections import namedtuple, Counter
from collections import namedtuple, Counter, defaultdict
from itertools import chain
from json import dumps
from uuid import uuid4
import math
import numpy as np
output_json_file_name = 'coronet_conus_example.json'
Node = namedtuple('Node', 'city state country region latitude longitude')
class Link(namedtuple('Link', 'from_city to_city distance distance_units')):
def __new__(cls, from_city, to_city, distance, distance_units='km'):
return super().__new__(cls, from_city, to_city, distance, distance_units)
#output_json_file_name = 'coronet_conus_example.json'
parser = ArgumentParser()
parser.add_argument('workbook', nargs='?', default='meshTopologyExampleV2.xls')
parser.add_argument('-f', '--filter-region', action='append', default=[])
all_rows = lambda sh, start=0: (sh.row(x) for x in range(start, sh.nrows))
def define_span_range(min_span, max_span, nspans):
srange = (max_span - min_span) + min_span*np.random.rand(nspans)
return srange
class Node(namedtuple('Node', 'city state country region latitude longitude node_type')):
def __new__(cls, city, state, country, region, latitude, longitude, node_type='ROADM'):
return super().__new__(cls, city, state, country, region, latitude, longitude, node_type)
def amp_spacings(min_span,max_span,length):
nspans = math.ceil(length/100)
spans = define_span_range(min_span, max_span, nspans)
tot = spans.sum()
delta = length -tot
if delta > 0 and delta < 25:
ind = np.where(np.min(spans))
spans[ind] = spans[ind] + delta
elif delta >= 25 and delta < 40:
spans = spans + delta/float(nspans)
elif delta > 40 and delta < 100:
spans = np.append(spans,delta)
elif delta > 100:
spans = np.append(spans, [delta/2, delta/2])
elif delta < 0:
spans = spans + delta/float(nspans)
return list(spans)
class Link(namedtuple('Link', 'from_city to_city \
east_distance east_fiber east_lineic east_con_in east_con_out east_pmd east_cable \
west_distance west_fiber west_lineic west_con_in west_con_out west_pmd west_cable \
distance_units')):
def __new__(cls, from_city, to_city,
east_distance, east_fiber='SSMF', east_lineic=0.2,
east_con_in=0.5, east_con_out=0.5, east_pmd=0.1, east_cable='',
west_distance=-100, west_fiber='SSMF', west_lineic=0.2,
west_con_in=0.5, west_con_out=0.5, west_pmd=0.1, west_cable='',
distance_units='km'):
if west_distance == -100:
west_distance = east_distance
return super().__new__(cls, from_city, to_city,
east_distance, east_fiber, east_lineic, east_con_in, east_con_out, east_pmd, east_cable,
west_distance, west_fiber, west_lineic, west_con_in, west_con_out, west_pmd, west_cable,
distance_units)
def parse_excel(args):
with open_workbook(args.workbook) as wb:
def convert_file(input_filename, filter_region=[]):
nodes, links = parse_excel(input_filename)
if filter_region:
nodes = [n for n in nodes if n.region.lower() in filter_region]
cities = {n.city for n in nodes}
links = [lnk for lnk in links if lnk.from_city in cities and
lnk.to_city in cities]
cities = {lnk.from_city for lnk in links} | {lnk.to_city for lnk in links}
nodes = [n for n in nodes if n.city in cities]
nodes_by_city = {n.city: n for n in nodes}
links_by_city = defaultdict(list)
for l in links:
if nodes_by_city[l.from_city].node_type.lower() == 'ila':
links_by_city[f'{l.from_city}'].append(l)
if nodes_by_city[l.to_city].node_type.lower() == 'ila':
links_by_city[f'{l.to_city}'].append(l)
repeat = False
for city,link in links_by_city.items():
if len(link) != 2:
#wrong input: ILA sites can only be Degree 2
# => correct to make it a ROADM and remove entry in links_by_city
nodes_by_city[city].node_type = 'ROADM'
del links_by_city[city]
data = {
'elements':
[{'uid': f'trx {x.city}',
'metadata': {'location': {'city': x.city,
'region': x.region,
'latitude': x.latitude,
'longitude': x.longitude}},
'type': 'Transceiver'}
for x in nodes if x.node_type.lower() == 'roadm'] +
[{'uid': f'roadm {x.city}',
'metadata': {'location': {'city': x.city,
'region': x.region,
'latitude': x.latitude,
'longitude': x.longitude}},
'type': 'Roadm'}
for x in nodes if x.node_type.lower() == 'roadm'] +
[{'uid': f'fiber ({x.from_city}{x.to_city})-{x.east_cable}',
'metadata': {'location': midpoint(nodes_by_city[x.from_city],
nodes_by_city[x.to_city])},
'type': 'Fiber',
'type_variety': x.east_fiber,
'params': {'length': round(x.east_distance, 3),
'length_units': x.distance_units,
'loss_coef': x.east_lineic}
}
for x in links]+
[{'uid': f'fiber ({x.to_city}{x.from_city})-{x.west_cable}',
'metadata': {'location': midpoint(nodes_by_city[x.from_city],
nodes_by_city[x.to_city])},
'type': 'Fiber',
'type_variety': x.west_fiber,
'params': {'length': round(x.west_distance, 3),
'length_units': x.distance_units,
'loss_coef': x.west_lineic}
}
for x in links],
'connections':
list(chain.from_iterable(zip( # put bidi next to each other
[{'from_node': f'roadm {x.from_city}',
'to_node': f'fiber ({x.from_city}{x.to_city})-{x.east_cable}'}
for x in links if nodes_by_city[x.from_city].node_type.lower()=='roadm'],
[{'from_node': f'fiber ({x.to_city}{x.from_city})-{x.west_cable}',
'to_node': f'roadm {x.from_city}'}
for x in links if nodes_by_city[x.from_city].node_type.lower()=='roadm'])))
+
list(chain.from_iterable(zip( # put bidi next to each other
[{'from_node': f'roadm {x.to_city}',
'to_node': f'fiber ({x.to_city}{x.from_city})-{x.west_cable}'}
for x in links if nodes_by_city[x.to_city].node_type.lower()=='roadm'],
[{'from_node': f'fiber ({x.from_city}{x.to_city})-{x.east_cable}',
'to_node': f'roadm {x.to_city}'}
for x in links if nodes_by_city[x.to_city].node_type.lower()=='roadm'])))
+
list(chain.from_iterable([fiber_connection_by_node(links_by_city[n.city], f'{n.city}')
for n in nodes if n.node_type.lower() == 'ila']))
+
list(chain.from_iterable(zip(
[{'from_node': f'trx {x.city}',
'to_node': f'roadm {x.city}'}
for x in nodes if x.node_type.lower()=='roadm'],
[{'from_node': f'roadm {x.city}',
'to_node': f'trx {x.city}'}
for x in nodes if x.node_type.lower()=='roadm'])))
}
#print(dumps(data, indent=2))
output_json_file_name = input_filename.split(".")[0]+".json"
with open(output_json_file_name,'w') as edfa_json_file:
edfa_json_file.write(dumps(data, indent=2))
def parse_excel(input_filename):
with open_workbook(input_filename) as wb:
nodes_sheet = wb.sheet_by_name('Nodes')
links_sheet = wb.sheet_by_name('Links')
"""
# sanity check
header = [x.value.strip() for x in nodes_sheet.row(4)]
expected = ['City', 'State', 'Country', 'Region', 'Latitude', 'Longitude']
if header != expected:
raise ValueError(f'Malformed header on Nodes sheet: {header} != {expected}')
"""
nodes = []
for row in all_rows(nodes_sheet, start=5):
nodes.append(Node(*(x.value for x in row)))
# sanity check
"""
header = [x.value.strip() for x in links_sheet.row(4)]
expected = ['Node A', 'Node Z', 'Distance (km)']
expected = ['Node A', 'Node Z',
'Distance (km)', 'Fiber type', 'lineic att', 'Con_in', 'Con_out', 'PMD', 'Cable id',
'Distance (km)', 'Fiber type', 'lineic att', 'Con_in', 'Con_out', 'PMD', 'Cable id']
if header != expected:
raise ValueError(f'Malformed header on Nodes sheet: {header} != {expected}')
"""
links = []
for row in all_rows(links_sheet, start=5):
links.append(Link(*(x.value for x in row)))
@@ -76,85 +178,45 @@ def parse_excel(args):
return nodes, links
parser = ArgumentParser()
parser.add_argument('workbook', nargs='?', default='CORONET_Global_Topology.xls')
parser.add_argument('-f', '--filter-region', action='append', default=[])
all_rows = lambda sh, start=0: (sh.row(x) for x in range(start, sh.nrows))
def fiber_connection_by_node(link, node_name):
subdata = [{'from_node': fiber_link_by_dest(link[0], node_name),
'to_node': fiber_link_by_source(link[1], node_name)},
{'from_node': fiber_link_by_dest(link[1], node_name),
'to_node': fiber_link_by_source(link[0], node_name)}]
return subdata
def fiber_link_by_dest(link, dest_node):
fiber_link_name = ''
if dest_node == link.to_city:
fiber_link_name = f'fiber ({link.from_city}{link.to_city})-{link.east_cable}'
elif dest_node == link.from_city:
fiber_link_name = f'fiber ({link.to_city}{link.from_city})-{link.west_cable}'
return fiber_link_name
def fiber_link_by_source(link, source_node):
fiber_link_name = ''
if source_node == link.from_city:
fiber_link_name = f'fiber ({link.from_city}{link.to_city})-{link.east_cable}'
elif source_node == link.to_city :
fiber_link_name = f'fiber ({link.to_city}{link.from_city})-{link.west_cable}'
return fiber_link_name
def midpoint(city_a, city_b):
lats = city_a.latitude, city_b.latitude
longs = city_a.longitude, city_b.longitude
return {
try:
result = {
'latitude': sum(lats) / 2,
'longitude': sum(longs) / 2,
}
'longitude': sum(longs) / 2
}
except :
result = {
'latitude': 0,
'longitude': 0
}
return result
if __name__ == '__main__':
args = parser.parse_args()
nodes, links = parse_excel(args)
if args.filter_region:
nodes = [n for n in nodes if n.region.lower() in args.filter_region]
cities = {n.city for n in nodes}
links = [lnk for lnk in links if lnk.from_city in cities and
lnk.to_city in cities]
cities = {lnk.from_city for lnk in links} | {lnk.to_city for lnk in links}
nodes = [n for n in nodes if n.city in cities]
nodes_by_city = {n.city: n for n in nodes}
data = {
'elements':
[{'uid': f'trx {x.city}',
'metadata': {'location': {'city': x.city,
'region': x.region,
'latitude': x.latitude,
'longitude': x.longitude}},
'type': 'Transceiver'}
for x in nodes] +
[{'uid': f'roadm {x.city}',
'metadata': {'location': {'city': x.city,
'region': x.region,
'latitude': x.latitude,
'longitude': x.longitude}},
'type': 'Roadm'}
for x in nodes] +
[{'uid': f'fiber ({x.from_city}{x.to_city})',
'metadata': {'location': midpoint(nodes_by_city[x.from_city],
nodes_by_city[x.to_city])},
'type': 'Fiber',
'params': {'length': round(x.distance, 3),
'length_units': x.distance_units,
'type_variety': "SSMF"}
}
for x in links],
'connections':
list(chain.from_iterable(zip( # put bidi next to each other
[{'from_node': f'roadm {x.from_city}',
'to_node': f'fiber ({x.from_city}{x.to_city})'}
for x in links],
[{'from_node': f'fiber ({x.from_city}{x.to_city})',
'to_node': f'roadm {x.from_city}'}
for x in links])))
+
list(chain.from_iterable(zip(
[{'from_node': f'fiber ({x.from_city}{x.to_city})',
'to_node': f'roadm {x.to_city}'}
for x in links],
[{'from_node': f'roadm {x.to_city}',
'to_node': f'fiber ({x.from_city}{x.to_city})'}
for x in links])))
+
list(chain.from_iterable(zip(
[{'from_node': f'trx {x.city}',
'to_node': f'roadm {x.city}'}
for x in nodes],
[{'from_node': f'roadm {x.city}',
'to_node': f'trx {x.city}'}
for x in nodes])))
}
print(dumps(data, indent=2))
with open(output_json_file_name,'w') as edfa_json_file:
edfa_json_file.write(dumps(data, indent=2))
convert_file(args.workbook, args.filter_region)

View File

@@ -0,0 +1,566 @@
{
"elements": [
{
"uid": "trx Lannion_CAS",
"metadata": {
"location": {
"city": "Lannion_CAS",
"region": "RLD",
"latitude": "",
"longitude": ""
}
},
"type": "Transceiver"
},
{
"uid": "trx Lorient_KMA",
"metadata": {
"location": {
"city": "Lorient_KMA",
"region": "RLD",
"latitude": "",
"longitude": ""
}
},
"type": "Transceiver"
},
{
"uid": "trx Vannes_KBE",
"metadata": {
"location": {
"city": "Vannes_KBE",
"region": "RLD",
"latitude": "",
"longitude": ""
}
},
"type": "Transceiver"
},
{
"uid": "trx Rennes_STA",
"metadata": {
"location": {
"city": "Rennes_STA",
"region": "RLD",
"latitude": "",
"longitude": ""
}
},
"type": "Transceiver"
},
{
"uid": "trx Brest_KLA",
"metadata": {
"location": {
"city": "Brest_KLA",
"region": "RLD",
"latitude": "",
"longitude": ""
}
},
"type": "Transceiver"
},
{
"uid": "roadm Lannion_CAS",
"metadata": {
"location": {
"city": "Lannion_CAS",
"region": "RLD",
"latitude": "",
"longitude": ""
}
},
"type": "Roadm"
},
{
"uid": "roadm Lorient_KMA",
"metadata": {
"location": {
"city": "Lorient_KMA",
"region": "RLD",
"latitude": "",
"longitude": ""
}
},
"type": "Roadm"
},
{
"uid": "roadm Vannes_KBE",
"metadata": {
"location": {
"city": "Vannes_KBE",
"region": "RLD",
"latitude": "",
"longitude": ""
}
},
"type": "Roadm"
},
{
"uid": "roadm Rennes_STA",
"metadata": {
"location": {
"city": "Rennes_STA",
"region": "RLD",
"latitude": "",
"longitude": ""
}
},
"type": "Roadm"
},
{
"uid": "roadm Brest_KLA",
"metadata": {
"location": {
"city": "Brest_KLA",
"region": "RLD",
"latitude": "",
"longitude": ""
}
},
"type": "Roadm"
},
{
"uid": "fiber (Lannion_CAS \u2192 Corlay)-F061",
"metadata": {
"location": {
"latitude": 0,
"longitude": 0
}
},
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 20.0,
"length_units": "km",
"loss_coef": 0.2
}
},
{
"uid": "fiber (Corlay \u2192 Loudeac)-F010",
"metadata": {
"location": {
"latitude": 0,
"longitude": 0
}
},
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 50.0,
"length_units": "km",
"loss_coef": 0.2
}
},
{
"uid": "fiber (Loudeac \u2192 Lorient_KMA)-F010",
"metadata": {
"location": {
"latitude": 0,
"longitude": 0
}
},
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 90.0,
"length_units": "km",
"loss_coef": 0.2
}
},
{
"uid": "fiber (Lorient_KMA \u2192 Vannes_KBE)-F054",
"metadata": {
"location": {
"latitude": 0,
"longitude": 0
}
},
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 10.0,
"length_units": "km",
"loss_coef": 0.2
}
},
{
"uid": "fiber (Lorient_KMA \u2192 Vannes_KBE)-F055",
"metadata": {
"location": {
"latitude": 0,
"longitude": 0
}
},
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 20.0,
"length_units": "km",
"loss_coef": 0.2
}
},
{
"uid": "fiber (Lannion_CAS \u2192 Stbrieuc)-F056",
"metadata": {
"location": {
"latitude": 0,
"longitude": 0
}
},
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 60.0,
"length_units": "km",
"loss_coef": 0.2
}
},
{
"uid": "fiber (Stbrieuc \u2192 Rennes_STA)-F057",
"metadata": {
"location": {
"latitude": 0,
"longitude": 0
}
},
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 65.0,
"length_units": "km",
"loss_coef": 0.2
}
},
{
"uid": "fiber (Lannion_CAS \u2192 Morlaix)-F059",
"metadata": {
"location": {
"latitude": 0,
"longitude": 0
}
},
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 75.0,
"length_units": "km",
"loss_coef": 0.2
}
},
{
"uid": "fiber (Morlaix \u2192 Brest_KLA)-F060",
"metadata": {
"location": {
"latitude": 0,
"longitude": 0
}
},
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 80.0,
"length_units": "km",
"loss_coef": 0.2
}
},
{
"uid": "fiber (Corlay \u2192 Lannion_CAS)-F061",
"metadata": {
"location": {
"latitude": 0,
"longitude": 0
}
},
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 20.0,
"length_units": "km",
"loss_coef": 0.2
}
},
{
"uid": "fiber (Loudeac \u2192 Corlay)-F010",
"metadata": {
"location": {
"latitude": 0,
"longitude": 0
}
},
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 50.0,
"length_units": "km",
"loss_coef": 0.2
}
},
{
"uid": "fiber (Lorient_KMA \u2192 Loudeac)-F010",
"metadata": {
"location": {
"latitude": 0,
"longitude": 0
}
},
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 90.0,
"length_units": "km",
"loss_coef": 0.2
}
},
{
"uid": "fiber (Vannes_KBE \u2192 Lorient_KMA)-F054",
"metadata": {
"location": {
"latitude": 0,
"longitude": 0
}
},
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 10.0,
"length_units": "km",
"loss_coef": 0.2
}
},
{
"uid": "fiber (Vannes_KBE \u2192 Lorient_KMA)-F055",
"metadata": {
"location": {
"latitude": 0,
"longitude": 0
}
},
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 20.0,
"length_units": "km",
"loss_coef": 0.2
}
},
{
"uid": "fiber (Stbrieuc \u2192 Lannion_CAS)-F056",
"metadata": {
"location": {
"latitude": 0,
"longitude": 0
}
},
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 60.0,
"length_units": "km",
"loss_coef": 0.2
}
},
{
"uid": "fiber (Rennes_STA \u2192 Stbrieuc)-F057",
"metadata": {
"location": {
"latitude": 0,
"longitude": 0
}
},
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 65.0,
"length_units": "km",
"loss_coef": 0.2
}
},
{
"uid": "fiber (Morlaix \u2192 Lannion_CAS)-F059",
"metadata": {
"location": {
"latitude": 0,
"longitude": 0
}
},
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 70.0,
"length_units": "km",
"loss_coef": 0.2
}
},
{
"uid": "fiber (Brest_KLA \u2192 Morlaix)-F060",
"metadata": {
"location": {
"latitude": 0,
"longitude": 0
}
},
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 70.0,
"length_units": "km",
"loss_coef": 0.2
}
}
],
"connections": [
{
"from_node": "roadm Lannion_CAS",
"to_node": "fiber (Lannion_CAS \u2192 Corlay)-F061"
},
{
"from_node": "fiber (Corlay \u2192 Lannion_CAS)-F061",
"to_node": "roadm Lannion_CAS"
},
{
"from_node": "roadm Lorient_KMA",
"to_node": "fiber (Lorient_KMA \u2192 Vannes_KBE)-F054"
},
{
"from_node": "fiber (Vannes_KBE \u2192 Lorient_KMA)-F054",
"to_node": "roadm Lorient_KMA"
},
{
"from_node": "roadm Lorient_KMA",
"to_node": "fiber (Lorient_KMA \u2192 Vannes_KBE)-F055"
},
{
"from_node": "fiber (Vannes_KBE \u2192 Lorient_KMA)-F055",
"to_node": "roadm Lorient_KMA"
},
{
"from_node": "roadm Lannion_CAS",
"to_node": "fiber (Lannion_CAS \u2192 Stbrieuc)-F056"
},
{
"from_node": "fiber (Stbrieuc \u2192 Lannion_CAS)-F056",
"to_node": "roadm Lannion_CAS"
},
{
"from_node": "roadm Lannion_CAS",
"to_node": "fiber (Lannion_CAS \u2192 Morlaix)-F059"
},
{
"from_node": "fiber (Morlaix \u2192 Lannion_CAS)-F059",
"to_node": "roadm Lannion_CAS"
},
{
"from_node": "roadm Lorient_KMA",
"to_node": "fiber (Lorient_KMA \u2192 Loudeac)-F010"
},
{
"from_node": "fiber (Loudeac \u2192 Lorient_KMA)-F010",
"to_node": "roadm Lorient_KMA"
},
{
"from_node": "roadm Vannes_KBE",
"to_node": "fiber (Vannes_KBE \u2192 Lorient_KMA)-F054"
},
{
"from_node": "fiber (Lorient_KMA \u2192 Vannes_KBE)-F054",
"to_node": "roadm Vannes_KBE"
},
{
"from_node": "roadm Vannes_KBE",
"to_node": "fiber (Vannes_KBE \u2192 Lorient_KMA)-F055"
},
{
"from_node": "fiber (Lorient_KMA \u2192 Vannes_KBE)-F055",
"to_node": "roadm Vannes_KBE"
},
{
"from_node": "roadm Rennes_STA",
"to_node": "fiber (Rennes_STA \u2192 Stbrieuc)-F057"
},
{
"from_node": "fiber (Stbrieuc \u2192 Rennes_STA)-F057",
"to_node": "roadm Rennes_STA"
},
{
"from_node": "roadm Brest_KLA",
"to_node": "fiber (Brest_KLA \u2192 Morlaix)-F060"
},
{
"from_node": "fiber (Morlaix \u2192 Brest_KLA)-F060",
"to_node": "roadm Brest_KLA"
},
{
"from_node": "fiber (Lannion_CAS \u2192 Corlay)-F061",
"to_node": "fiber (Corlay \u2192 Loudeac)-F010"
},
{
"from_node": "fiber (Loudeac \u2192 Corlay)-F010",
"to_node": "fiber (Corlay \u2192 Lannion_CAS)-F061"
},
{
"from_node": "fiber (Corlay \u2192 Loudeac)-F010",
"to_node": "fiber (Loudeac \u2192 Lorient_KMA)-F010"
},
{
"from_node": "fiber (Lorient_KMA \u2192 Loudeac)-F010",
"to_node": "fiber (Loudeac \u2192 Corlay)-F010"
},
{
"from_node": "fiber (Lannion_CAS \u2192 Stbrieuc)-F056",
"to_node": "fiber (Stbrieuc \u2192 Rennes_STA)-F057"
},
{
"from_node": "fiber (Rennes_STA \u2192 Stbrieuc)-F057",
"to_node": "fiber (Stbrieuc \u2192 Lannion_CAS)-F056"
},
{
"from_node": "fiber (Lannion_CAS \u2192 Morlaix)-F059",
"to_node": "fiber (Morlaix \u2192 Brest_KLA)-F060"
},
{
"from_node": "fiber (Brest_KLA \u2192 Morlaix)-F060",
"to_node": "fiber (Morlaix \u2192 Lannion_CAS)-F059"
},
{
"from_node": "trx Lannion_CAS",
"to_node": "roadm Lannion_CAS"
},
{
"from_node": "roadm Lannion_CAS",
"to_node": "trx Lannion_CAS"
},
{
"from_node": "trx Lorient_KMA",
"to_node": "roadm Lorient_KMA"
},
{
"from_node": "roadm Lorient_KMA",
"to_node": "trx Lorient_KMA"
},
{
"from_node": "trx Vannes_KBE",
"to_node": "roadm Vannes_KBE"
},
{
"from_node": "roadm Vannes_KBE",
"to_node": "trx Vannes_KBE"
},
{
"from_node": "trx Rennes_STA",
"to_node": "roadm Rennes_STA"
},
{
"from_node": "roadm Rennes_STA",
"to_node": "trx Rennes_STA"
},
{
"from_node": "trx Brest_KLA",
"to_node": "roadm Brest_KLA"
},
{
"from_node": "roadm Brest_KLA",
"to_node": "trx Brest_KLA"
}
]
}

Binary file not shown.

View File

@@ -10,6 +10,7 @@ propagates a 96 channels comb
"""
from gnpy.core.utils import load_json
from convert import convert_file
from gnpy.core.equipment import *
from argparse import ArgumentParser
from sys import exit
@@ -38,8 +39,43 @@ def format_si(spectral_infos):
logger = getLogger('gnpy.core')
def plot_network_graph(network, path, source, sink):
nodelist = [n for n in network.nodes() if isinstance(n, (Transceiver, Fiber))]
pathnodes = [n for n in path if isinstance(n, (Transceiver, Fiber))]
edgelist = [(u, v) for u, v in zip(pathnodes, pathnodes[1:])]
node_color = ['#ff0000' if n is source or n is sink else
'#900000' if n in path else '#ffdfdf'
for n in nodelist]
edge_color = ['#ff9090' if u in path and v in path else '#ababab'
for u, v in edgelist]
labels = {n: n.location.city if isinstance(n, Transceiver) else ''
for n in pathnodes}
fig = figure()
pos = {n: (n.lng, n.lat) for n in nodelist}
kwargs = {'figure': fig, 'pos': pos}
plot = draw_networkx_nodes(network, nodelist=nodelist, node_color=node_color, **kwargs)
draw_networkx_edges(network, edgelist=edgelist, edge_color=edge_color, **kwargs)
draw_networkx_labels(network, labels=labels, font_size=14, **kwargs)
title(f'Propagating from {source.loc.city} to {sink.loc.city}')
axis('off')
show()
def main(args):
json_data = load_json(args.filename)
input_filename = str(args.filename)
split_filename = input_filename.split(".")
json_filename = split_filename[0]+'.json'
try:
assert split_filename[1] in ('json','xls','csv','xlsm')
except AssertionError as e:
print(f'invalid file extension .{split_filename[1]}')
raise e
if split_filename[1] != 'json':
print(f'parse excel input to {json_filename}')
convert_file(input_filename)
json_data = load_json(json_filename)
read_eqpt_library(EQPT_LIBRARY_FILENAME)
network = network_from_json(json_data)
@@ -73,26 +109,7 @@ def main(args):
si = el(si)
print(el)
nodelist = [n for n in network.nodes() if isinstance(n, (Transceiver, Fiber))]
pathnodes = [n for n in path if isinstance(n, (Transceiver, Fiber))]
edgelist = [(u, v) for u, v in zip(pathnodes, pathnodes[1:])]
node_color = ['#ff0000' if n is source or n is sink else
'#900000' if n in path else '#ffdfdf'
for n in nodelist]
edge_color = ['#ff9090' if u in path and v in path else '#ababab'
for u, v in edgelist]
labels = {n: n.location.city if isinstance(n, Transceiver) else ''
for n in pathnodes}
fig = figure()
pos = {n: (n.lng, n.lat) for n in nodelist}
kwargs = {'figure': fig, 'pos': pos}
plot = draw_networkx_nodes(network, nodelist=nodelist, node_color=node_color, **kwargs)
draw_networkx_edges(network, edgelist=edgelist, edge_color=edge_color, **kwargs)
draw_networkx_labels(network, labels=labels, font_size=14, **kwargs)
title(f'Propagating from {source.loc.city} to {sink.loc.city}')
axis('off')
show()
#plot_network_graph(network, path, source, sink)
parser = ArgumentParser()
parser.add_argument('filename', nargs='?', type=Path,

View File

@@ -9,28 +9,27 @@ 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"
GAIN_MIN_FIELD = "gain_min"
GAIN_MAX_FIELD = "gain_flatmax"
NF_MIN_FIELD ="nf_min"
NF_MAX_FIELD = "nf_max"
gain_ripple_field = "dfg"
nf_ripple_field = "nf_ripple"
nf_fit_coeff = "nf_fit_coeff"
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]
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)
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)
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)
@@ -86,18 +85,18 @@ def read_eqpt_library(filename):
dict_nf_model = {}
if 'advanced_config_from_json' in el:
#use advanced amplifier model with full ripple characterization
config_json_file_name = el.pop('advanced_config_from_json')
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_file_name = 'default_edfa_config.json'
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_file_name)
json_data = load_json(config_json_filename)
eqpt_library['Edfa'][i] = {**el, **json_data, **dict_nf_model}