Skip to content

Commit

Permalink
Restrictions on auto-adding amplifiers into ROADMs
Browse files Browse the repository at this point in the history
This feature is intended to support designs such as OpenROADM where the
line degree integrates a specific preamp/booster pair. In that case, it
does not make sense for our autodesign to "pick an amplifier". The
restrictions can be activated by:

- Listing them in `eqpt_config.json`, so that they are effective for all
ROADM instances.
- On a per-ROADM basis within the Excel sheet or the JSON definitions.

Restrictions apply to an entire ROADM as a whole, not to the individual
degrees.

If a per-degree exception is needed, the amplifier of this degree can be
defined in the equipment sheet or in the network definition.

If no booster amplifier should be placed on a degree, use the `Fused`
node in place of an amplifier.

Signed-off-by: Esther Le Rouzic <esther.lerouzic@orange.com>
Co-authored-by: Jan Kundrát <jan.kundrat@telecominfraproject.com>
  • Loading branch information
EstherLerouzic and jktjkt committed Jun 6, 2019
1 parent 22acd88 commit b07efa4
Show file tree
Hide file tree
Showing 18 changed files with 1,132 additions and 258 deletions.
8 changes: 6 additions & 2 deletions Excel_userguide.rst
Expand Up @@ -19,8 +19,8 @@ In order to work the excel file MUST contain at least 2 sheets:
Nodes sheet
-----------

Nodes sheet contains seven columns.
Each line represents a 'node' (ROADM site or an in line amplifier site ILA)::
Nodes sheet contains nine columns.
Each line represents a 'node' (ROADM site or an in line amplifier site ILA or a Fused)::

City (Mandatory) ; State ; Country ; Region ; Latitude ; Longitude ; Type

Expand All @@ -38,6 +38,9 @@ Each line represents a 'node' (ROADM site or an in line amplifier site ILA)::

- *Longitude*, *Latitude* are not mandatory. If filled they should contain numbers.

- **Booster_restriction** and **Preamp_restriction** are not mandatory.
If used, they must contain one or several amplifier type_variety names separated by ' | '. This information is used to restrict types of amplifiers used in a ROADM node during autodesign. If a ROADM booster or preamp is already specified in the Eqpt sheet , the field is ignored. The field is also ignored if the node is not a ROADM node.

**There MUST NOT be empty line(s) between two nodes lines**


Expand Down Expand Up @@ -166,6 +169,7 @@ This generates a text file meshTopologyExampleV2_eqt_sheet.txt whose content ca
- **amp type** is not mandatory.
If filled it must contain types listed in `eqpt_config.json <examples/eqpt_config.json>`_ in "Edfa" list "type_variety".
If not filled it takes "std_medium_gain" as default value.
If filled with fused, a fused element with 0.0 dB loss will be placed instead of an amplifier. This might be used to avoid booster amplifier on a ROADM direction.

- **amp_gain** is not mandatory. It is the value to be set on the amplifier (in dB).
If not filled, it will be determined with design rules in the convert.py file.
Expand Down
13 changes: 9 additions & 4 deletions README.rst
Expand Up @@ -408,10 +408,15 @@ existing parameters:
+--------------------------+-----------+---------------------------------------------+
| ``add_drop_osnr`` | (number) | OSNR contribution from the add/drop ports |
+--------------------------+-----------+---------------------------------------------+
| ``restrictions`` | (strings) | Authorized type_variety of amplifier for |
| | | booster or preamp. |
| | | Listed type_variety MUST be defined in the |
| | | Edfa catalog. |
| ``restrictions`` | (dict of | If non-empty, keys ``preamp_variety_list`` |
| | strings) | and ``booster_variety_list`` represent |
| | | list of ``type_variety`` amplifiers which |
| | | are allowed for auto-design within ROADM's |
| | | line degrees. |
| | | |
| | | If no booster should be placed on a degree, |
| | | insert a ``Fused`` node on the degree |
| | | output. |
+--------------------------+-----------+---------------------------------------------+

The ``SpectralInformation`` object can be configured as follows. The user can
Expand Down
4 changes: 2 additions & 2 deletions examples/eqpt_config.json
Expand Up @@ -177,8 +177,8 @@
"target_pch_out_db": -20,
"add_drop_osnr": 38,
"restrictions": {
"preamp_variety_list":["low_gain_preamp", "high_gain_preamp"],
"booster_variety_list":["std_booster"]
"preamp_variety_list":[],
"booster_variety_list":[]
}
}],
"SI":[{
Expand Down
34 changes: 15 additions & 19 deletions examples/meshTopologyExampleV2.json
Expand Up @@ -681,25 +681,6 @@
"out_voa": null
}
},
{
"uid": "east edfa in Lorient_KMA to Vannes_KBE",
"metadata": {
"location": {
"city": "Lorient_KMA",
"region": "RLD",
"latitude": 2.0,
"longitude": 3.0
}
},
"type": "Edfa",
"type_variety": "std_low_gain",
"operational": {
"gain_target": null,
"delta_p": 1.0,
"tilt_target": 0,
"out_voa": null
}
},
{
"uid": "east edfa in Lannion_CAS to Stbrieuc",
"metadata": {
Expand Down Expand Up @@ -1041,6 +1022,21 @@
"tilt_target": 0,
"out_voa": null
}
},
{
"uid": "east edfa in Lorient_KMA to Vannes_KBE",
"metadata": {
"location": {
"city": "Lorient_KMA",
"region": "RLD",
"latitude": 2.0,
"longitude": 3.0
}
},
"type": "Fused",
"params": {
"loss": 0
}
}
],
"connections": [
Expand Down
Binary file modified examples/meshTopologyExampleV2.xls
Binary file not shown.
63 changes: 52 additions & 11 deletions gnpy/core/convert.py
Expand Up @@ -31,6 +31,7 @@
from json import dumps
from pathlib import Path
from difflib import get_close_matches
from gnpy.core.utils import silent_remove
import time

all_rows = lambda sh, start=0: (sh.row(x) for x in range(start, sh.nrows))
Expand All @@ -54,7 +55,9 @@ def update_attr(self, kwargs):
'region': '',
'latitude': 0,
'longitude': 0,
'node_type': 'ILA'
'node_type': 'ILA',
'booster_restriction' : '',
'preamp_restriction' : ''
}

class Link(object):
Expand Down Expand Up @@ -235,7 +238,6 @@ def sanity_check(nodes, links, nodes_by_city, links_by_city, eqpts_by_city):

def convert_file(input_filename, names_matching=False, filter_region=[]):
nodes, links, eqpts = 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}
Expand All @@ -244,10 +246,8 @@ def convert_file(input_filename, names_matching=False, 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}

#create matching dictionary for node name mismatch analysis

cities = {''.join(c.strip() for c in n.city.split('C+L')).lower(): n.city for n in nodes}
Expand Down Expand Up @@ -298,7 +298,22 @@ def convert_file(input_filename, names_matching=False, filter_region=[]):
'latitude': x.latitude,
'longitude': x.longitude}},
'type': 'Roadm'}
for x in nodes_by_city.values() if x.node_type.lower() == 'roadm'] +
for x in nodes_by_city.values() if x.node_type.lower() == 'roadm' \
and x.booster_restriction == '' and x.preamp_restriction == ''] +
[{'uid': f'roadm {x.city}',
'params' : {
'restrictions': {
'preamp_variety_list': silent_remove(x.preamp_restriction.split(' | '),''),
'booster_variety_list': silent_remove(x.booster_restriction.split(' | '),'')
}
},
'metadata': {'location': {'city': x.city,
'region': x.region,
'latitude': x.latitude,
'longitude': x.longitude}},
'type': 'Roadm'}
for x in nodes_by_city.values() if x.node_type.lower() == 'roadm' and \
(x.booster_restriction!='' or x.preamp_restriction != '')] +
[{'uid': f'west fused spans in {x.city}',
'metadata': {'location': {'city': x.city,
'region': x.region,
Expand Down Expand Up @@ -348,8 +363,9 @@ def convert_file(input_filename, names_matching=False, filter_region=[]):
'delta_p': e.east_amp_dp,
'tilt_target': e.east_tilt,
'out_voa' : e.east_att_out}
}
for e in eqpts if e.east_amp_type.lower() != ''] +
}
for e in eqpts if (e.east_amp_type.lower() != '' and \
e.east_amp_type.lower() != 'fused')] +
[{'uid': f'west edfa in {e.from_city} to {e.to_city}',
'metadata': {'location': {'city': nodes_by_city[e.from_city].city,
'region': nodes_by_city[e.from_city].region,
Expand All @@ -361,8 +377,31 @@ def convert_file(input_filename, names_matching=False, filter_region=[]):
'delta_p': e.west_amp_dp,
'tilt_target': e.west_tilt,
'out_voa' : e.west_att_out}
}
for e in eqpts if e.west_amp_type.lower() != ''],
}
for e in eqpts if (e.west_amp_type.lower() != '' and \
e.west_amp_type.lower() != 'fused')] +
# fused edfa variety is a hack to indicate that there should not be
# booster amplifier out the roadm.
# If user specifies ILA in Nodes sheet and fused in Eqpt sheet, then assumes that
# this is a fused nodes.
[{'uid': f'east edfa in {e.from_city} to {e.to_city}',
'metadata': {'location': {'city': nodes_by_city[e.from_city].city,
'region': nodes_by_city[e.from_city].region,
'latitude': nodes_by_city[e.from_city].latitude,
'longitude': nodes_by_city[e.from_city].longitude}},
'type': 'Fused',
'params': {'loss': 0}
}
for e in eqpts if e.east_amp_type.lower() == 'fused'] +
[{'uid': f'west edfa in {e.from_city} to {e.to_city}',
'metadata': {'location': {'city': nodes_by_city[e.from_city].city,
'region': nodes_by_city[e.from_city].region,
'latitude': nodes_by_city[e.from_city].latitude,
'longitude': nodes_by_city[e.from_city].longitude}},
'type': 'Fused',
'params': {'loss': 0}
}
for e in eqpts if e.west_amp_type.lower() == 'fused'],
'connections':
list(chain.from_iterable([eqpt_connection_by_city(n.city)
for n in nodes]))
Expand Down Expand Up @@ -414,7 +453,9 @@ def parse_excel(input_filename):
'Region': 'region',
'Latitude': 'latitude',
'Longitude': 'longitude',
'Type': 'node_type'
'Type': 'node_type',
'Booster_restriction' : 'booster_restriction',
'Preamp_restriction' : 'preamp_restriction'
}
eqpt_headers = \
{ 'Node A': 'from_city',
Expand Down Expand Up @@ -571,7 +612,7 @@ def midpoint(city_a, city_b):
#output_json_file_name = 'coronet_conus_example.json'
#TODO get column size automatically from tupple size

NODES_COLUMN = 8
NODES_COLUMN = 10
NODES_LINE = 4
LINKS_COLUMN = 16
LINKS_LINE = 3
Expand Down
13 changes: 10 additions & 3 deletions gnpy/core/elements.py
Expand Up @@ -117,7 +117,7 @@ def __call__(self, spectral_info):
self._calc_snr(spectral_info)
return spectral_info

RoadmParams = namedtuple('RoadmParams', 'target_pch_out_db add_drop_osnr')
RoadmParams = namedtuple('RoadmParams', 'target_pch_out_db add_drop_osnr restrictions')

class Roadm(Node):
def __init__(self, *args, params, **kwargs):
Expand All @@ -126,15 +126,19 @@ def __init__(self, *args, params, **kwargs):
self.effective_loss = None
self.effective_pch_out_db = self.params.target_pch_out_db
self.passive = True
self.restrictions = self.params.restrictions

@property
def to_json(self):
return {'uid' : self.uid,
'type' : type(self).__name__,
'params' : {'target_pch_out_db' : self.effective_pch_out_db},
'params' : {
'target_pch_out_db' : self.effective_pch_out_db,
'restrictions' : self.restrictions
},
'metadata' : {
'location': self.metadata['location']._asdict()
}
}
}

def __repr__(self):
Expand Down Expand Up @@ -186,6 +190,9 @@ def __init__(self, *args, params=None, **kwargs):
def to_json(self):
return {'uid' : self.uid,
'type' : type(self).__name__,
'params' :{
'loss': self.loss
},
'metadata' : {
'location': self.metadata['location']._asdict()
}
Expand Down

0 comments on commit b07efa4

Please sign in to comment.