Code improvement in convert.py

improve code reading and clarity of topology parser:
*modify the connections binding
=>def fiber_dest_from_source to find all dest_city connected to a source_city
=>def fiber_link to return the fiber link from source_city to dest_city
*makes the parser algorithm more understandable
*prepare for the equipment parser

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
This commit is contained in:
Jean-Luc Auge
2018-04-10 17:59:41 +02:00
committed by James Powell
parent 8e046a9b50
commit d2724bb1a5
5 changed files with 1439 additions and 3406 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -51,7 +51,7 @@ class Link(namedtuple('Link', 'from_city to_city \
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)
distance_units)
def convert_file(input_filename, filter_region=[]):
nodes, links = parse_excel(input_filename)
@@ -64,18 +64,17 @@ def convert_file(input_filename, filter_region=[]):
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]
global nodes_by_city
nodes_by_city = {n.city: n for n in nodes}
global links_by_city
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 link in links:
links_by_city[link.from_city].append(link)
links_by_city[link.to_city].append(link)
for city,link in list(links_by_city.items()):
if len(link) != 2:
for city,link in links_by_city.items():
if nodes_by_city[city].node_type.lower()=='ila' and 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
#TODO : put in log rather than print
@@ -83,7 +82,6 @@ def convert_file(input_filename, filter_region=[]):
specified in {city}, replaced by ROADM')
nodes_by_city[city] = nodes_by_city[city]._replace(node_type='ROADM')
nodes = [n._replace(node_type='ROADM') if n.city==city else n for n in nodes]
del links_by_city[city]
data = {
'elements':
@@ -122,24 +120,8 @@ def convert_file(input_filename, filter_region=[]):
}
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([fiber_connection_by_city(n.city)
for n in nodes]))
+
list(chain.from_iterable(zip(
[{'from_node': f'trx {x.city}',
@@ -189,6 +171,7 @@ def parse_excel(input_filename):
for row in all_rows(links_sheet, start=5):
links.append(Link(*(x.value for x in row)))
# sanity check
all_cities = Counter(n.city for n in nodes)
if len(all_cities) != len(nodes):
@@ -200,28 +183,45 @@ def parse_excel(input_filename):
return nodes, links
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)}]
def fiber_connection_by_city(city_name):
other_cities = fiber_dest_from_source(city_name)
subdata = []
if nodes_by_city[city_name].node_type.lower() in ('ila', 'fused'):
# Then len(other_cities) == 2
subdata = [{'from_node': fiber_link(other_cities[0], city_name),
'to_node': fiber_link(city_name, other_cities[1])},
{'from_node': fiber_link(other_cities[1], city_name),
'to_node': fiber_link(city_name, other_cities[0])}]
elif nodes_by_city[city_name].node_type.lower() == 'roadm':
subdata = list(chain.from_iterable(zip(
[{'from_node': f'roadm {city_name}',
'to_node': fiber_link(city_name, other_city)}
for other_city in other_cities],
[{'from_node': fiber_link(other_city, city_name),
'to_node': f'roadm {city_name}'}
for other_city in other_cities])))
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_dest_from_source(city_name):
destinations = []
links_from_city = links_by_city[city_name]
for l in links_from_city:
if l.from_city == city_name:
destinations.append(l.to_city)
else:
destinations.append(l.from_city)
return destinations
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 fiber_link(from_city, to_city):
link = links_by_city[from_city]
source_dest = (from_city, to_city)
l = next(l for l in link if l.from_city in source_dest and l.to_city in source_dest)
if l.from_city == from_city:
fiber = f'fiber ({l.from_city}{l.to_city})-{l.east_cable}'
else:
fiber = f'fiber ({l.to_city}{l.from_city})-{l.west_cable}'
return fiber
def midpoint(city_a, city_b):
lats = city_a.latitude, city_b.latitude

View File

@@ -6,8 +6,8 @@
"location": {
"city": "Lannion_CAS",
"region": "RLD",
"latitude": "",
"longitude": ""
"latitude": 0,
"longitude": 0
}
},
"type": "Transceiver"
@@ -18,8 +18,8 @@
"location": {
"city": "Lorient_KMA",
"region": "RLD",
"latitude": "",
"longitude": ""
"latitude": 0,
"longitude": 0
}
},
"type": "Transceiver"
@@ -30,8 +30,8 @@
"location": {
"city": "Vannes_KBE",
"region": "RLD",
"latitude": "",
"longitude": ""
"latitude": 0,
"longitude": 0
}
},
"type": "Transceiver"
@@ -42,8 +42,8 @@
"location": {
"city": "Rennes_STA",
"region": "RLD",
"latitude": "",
"longitude": ""
"latitude": 0,
"longitude": 0
}
},
"type": "Transceiver"
@@ -54,8 +54,8 @@
"location": {
"city": "Brest_KLA",
"region": "RLD",
"latitude": "",
"longitude": ""
"latitude": 0,
"longitude": 0
}
},
"type": "Transceiver"
@@ -66,8 +66,8 @@
"location": {
"city": "Lannion_CAS",
"region": "RLD",
"latitude": "",
"longitude": ""
"latitude": 0,
"longitude": 0
}
},
"type": "Roadm"
@@ -78,8 +78,8 @@
"location": {
"city": "Lorient_KMA",
"region": "RLD",
"latitude": "",
"longitude": ""
"latitude": 0,
"longitude": 0
}
},
"type": "Roadm"
@@ -90,8 +90,8 @@
"location": {
"city": "Vannes_KBE",
"region": "RLD",
"latitude": "",
"longitude": ""
"latitude": 0,
"longitude": 0
}
},
"type": "Roadm"
@@ -102,8 +102,8 @@
"location": {
"city": "Rennes_STA",
"region": "RLD",
"latitude": "",
"longitude": ""
"latitude": 0,
"longitude": 0
}
},
"type": "Roadm"
@@ -114,8 +114,8 @@
"location": {
"city": "Brest_KLA",
"region": "RLD",
"latitude": "",
"longitude": ""
"latitude": 0,
"longitude": 0
}
},
"type": "Roadm"
@@ -124,8 +124,8 @@
"uid": "fiber (Lannion_CAS \u2192 Corlay)-F061",
"metadata": {
"location": {
"latitude": 0,
"longitude": 0
"latitude": 0.0,
"longitude": 0.0
}
},
"type": "Fiber",
@@ -140,8 +140,8 @@
"uid": "fiber (Corlay \u2192 Loudeac)-F010",
"metadata": {
"location": {
"latitude": 0,
"longitude": 0
"latitude": 0.0,
"longitude": 0.0
}
},
"type": "Fiber",
@@ -156,8 +156,8 @@
"uid": "fiber (Loudeac \u2192 Lorient_KMA)-F010",
"metadata": {
"location": {
"latitude": 0,
"longitude": 0
"latitude": 0.0,
"longitude": 0.0
}
},
"type": "Fiber",
@@ -172,8 +172,8 @@
"uid": "fiber (Lorient_KMA \u2192 Vannes_KBE)-F054",
"metadata": {
"location": {
"latitude": 0,
"longitude": 0
"latitude": 0.0,
"longitude": 0.0
}
},
"type": "Fiber",
@@ -188,8 +188,8 @@
"uid": "fiber (Lorient_KMA \u2192 Vannes_KBE)-F055",
"metadata": {
"location": {
"latitude": 0,
"longitude": 0
"latitude": 0.0,
"longitude": 0.0
}
},
"type": "Fiber",
@@ -204,8 +204,8 @@
"uid": "fiber (Lannion_CAS \u2192 Stbrieuc)-F056",
"metadata": {
"location": {
"latitude": 0,
"longitude": 0
"latitude": 0.0,
"longitude": 0.0
}
},
"type": "Fiber",
@@ -220,8 +220,8 @@
"uid": "fiber (Stbrieuc \u2192 Rennes_STA)-F057",
"metadata": {
"location": {
"latitude": 0,
"longitude": 0
"latitude": 0.0,
"longitude": 0.0
}
},
"type": "Fiber",
@@ -236,8 +236,8 @@
"uid": "fiber (Lannion_CAS \u2192 Morlaix)-F059",
"metadata": {
"location": {
"latitude": 0,
"longitude": 0
"latitude": 0.0,
"longitude": 0.0
}
},
"type": "Fiber",
@@ -252,8 +252,8 @@
"uid": "fiber (Morlaix \u2192 Brest_KLA)-F060",
"metadata": {
"location": {
"latitude": 0,
"longitude": 0
"latitude": 0.0,
"longitude": 0.0
}
},
"type": "Fiber",
@@ -268,8 +268,8 @@
"uid": "fiber (Corlay \u2192 Lannion_CAS)-F061",
"metadata": {
"location": {
"latitude": 0,
"longitude": 0
"latitude": 0.0,
"longitude": 0.0
}
},
"type": "Fiber",
@@ -284,8 +284,8 @@
"uid": "fiber (Loudeac \u2192 Corlay)-F010",
"metadata": {
"location": {
"latitude": 0,
"longitude": 0
"latitude": 0.0,
"longitude": 0.0
}
},
"type": "Fiber",
@@ -300,8 +300,8 @@
"uid": "fiber (Lorient_KMA \u2192 Loudeac)-F010",
"metadata": {
"location": {
"latitude": 0,
"longitude": 0
"latitude": 0.0,
"longitude": 0.0
}
},
"type": "Fiber",
@@ -316,8 +316,8 @@
"uid": "fiber (Vannes_KBE \u2192 Lorient_KMA)-F054",
"metadata": {
"location": {
"latitude": 0,
"longitude": 0
"latitude": 0.0,
"longitude": 0.0
}
},
"type": "Fiber",
@@ -332,8 +332,8 @@
"uid": "fiber (Vannes_KBE \u2192 Lorient_KMA)-F055",
"metadata": {
"location": {
"latitude": 0,
"longitude": 0
"latitude": 0.0,
"longitude": 0.0
}
},
"type": "Fiber",
@@ -348,8 +348,8 @@
"uid": "fiber (Stbrieuc \u2192 Lannion_CAS)-F056",
"metadata": {
"location": {
"latitude": 0,
"longitude": 0
"latitude": 0.0,
"longitude": 0.0
}
},
"type": "Fiber",
@@ -364,8 +364,8 @@
"uid": "fiber (Rennes_STA \u2192 Stbrieuc)-F057",
"metadata": {
"location": {
"latitude": 0,
"longitude": 0
"latitude": 0.0,
"longitude": 0.0
}
},
"type": "Fiber",
@@ -380,8 +380,8 @@
"uid": "fiber (Morlaix \u2192 Lannion_CAS)-F059",
"metadata": {
"location": {
"latitude": 0,
"longitude": 0
"latitude": 0.0,
"longitude": 0.0
}
},
"type": "Fiber",
@@ -396,8 +396,8 @@
"uid": "fiber (Brest_KLA \u2192 Morlaix)-F060",
"metadata": {
"location": {
"latitude": 0,
"longitude": 0
"latitude": 0.0,
"longitude": 0.0
}
},
"type": "Fiber",
@@ -418,22 +418,6 @@
"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"
@@ -450,46 +434,6 @@
"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"
@@ -506,6 +450,46 @@
"from_node": "fiber (Lorient_KMA \u2192 Loudeac)-F010",
"to_node": "fiber (Loudeac \u2192 Corlay)-F010"
},
{
"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 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)-F054"
},
{
"from_node": "fiber (Vannes_KBE \u2192 Lorient_KMA)-F054",
"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)-F054"
},
{
"from_node": "fiber (Lorient_KMA \u2192 Vannes_KBE)-F054",
"to_node": "roadm Vannes_KBE"
},
{
"from_node": "fiber (Lannion_CAS \u2192 Stbrieuc)-F056",
"to_node": "fiber (Stbrieuc \u2192 Rennes_STA)-F057"
@@ -514,6 +498,14 @@
"from_node": "fiber (Rennes_STA \u2192 Stbrieuc)-F057",
"to_node": "fiber (Stbrieuc \u2192 Lannion_CAS)-F056"
},
{
"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": "fiber (Lannion_CAS \u2192 Morlaix)-F059",
"to_node": "fiber (Morlaix \u2192 Brest_KLA)-F060"
@@ -522,6 +514,14 @@
"from_node": "fiber (Brest_KLA \u2192 Morlaix)-F060",
"to_node": "fiber (Morlaix \u2192 Lannion_CAS)-F059"
},
{
"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": "trx Lannion_CAS",
"to_node": "roadm Lannion_CAS"

View File

@@ -21,13 +21,10 @@ 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)
if nf_min<-10 or nf_max<-10:
raise ValueError(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
@@ -40,17 +37,16 @@ def nf_model(amp_dict):
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 """
#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 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)
@@ -58,16 +54,14 @@ def nf_model(amp_dict):
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'
print('!WARNING!: 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)
raise ValueError(f'nf model calculation failed with nf_min {nf_min_calc} and nf_max {nf_max_calc} calculated')
return nf1, nf2, delta_p
def read_eqpt_library(filename):
@@ -94,7 +88,7 @@ def read_eqpt_library(filename):
#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]))
dict_nf_model['nf_model'] = {"enabled": True, "nf1": nf1, "nf2": nf2, "delta_p": delta_p}
json_data = load_json(config_json_filename)
eqpt_library['Edfa'][i] = {**el, **json_data, **dict_nf_model}

View File

@@ -13,7 +13,6 @@ from networkx import DiGraph
from gnpy.core import elements
from gnpy.core.elements import Fiber, Edfa, Transceiver, Roadm
from gnpy.core.units import UNITS
from gnpy.core.equipment import *
MAX_SPAN_LENGTH = 125000