mirror of
https://github.com/Telecominfraproject/oopt-gnpy.git
synced 2025-10-30 01:32:21 +00:00
Merge branch 'develop' into path_disjunction solving conflict
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
This commit is contained in:
29
README.rst
29
README.rst
@@ -9,7 +9,7 @@ planning and optimization tools in real-world mesh optical networks.**
|
||||
|
||||
`gnpy <http://github.com/telecominfraproject/oopt-gnpy>`__ is:
|
||||
|
||||
- a sponsored project of the `OOPT/PSE <https://telecominfraproject.com/open-optical-packet-transport/>`_ working group of the `Telecom Infra Project <http://telecominfraproject.com>`_.
|
||||
- a sponsored project of the `OOPT/PSE <https://telecominfraproject.com/open-optical-packet-transport/>`_ working group of the `Telecom Infra Project <http://telecominfraproject.com>`_
|
||||
- fully community-driven, fully open source library
|
||||
- driven by a consortium of operators, vendors, and academic researchers
|
||||
- intended for rapid development of production-grade route planning tools
|
||||
@@ -135,8 +135,8 @@ By default, this script operates on a single span network defined in
|
||||
`examples/edfa_example_network.json <examples/edfa_example_network.json>`_
|
||||
|
||||
You can specify a different network at the command line as follows. For
|
||||
example, to use the CORONET Continental US (CONUS) network defined in
|
||||
`examples/coronet_conus_example.json <examples/coronet_conus_example.json>`_:
|
||||
example, to use the CORONET Global network defined in
|
||||
`examples/CORONET_Global_Topology.json <examples/CORONET_Global_Topology.json>`_:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
@@ -150,10 +150,10 @@ further instructions on how to prepare the Excel input file, see
|
||||
`Excel_userguide.rst <Excel_userguide.rst>`_.
|
||||
|
||||
The main transmission example will calculate the average signal OSNR and SNR
|
||||
across 93 network elements (transceiver, ROADMs, fibers, and amplifiers)
|
||||
between two transceivers selected by the user. (By default, for the CORONET US
|
||||
network, it will show the transmission of spectral information between Abilene,
|
||||
Texas and Albany, New York.)
|
||||
across network elements (transceiver, ROADMs, fibers, and amplifiers)
|
||||
between two transceivers selected by the user. (By default, for the CORONET Global
|
||||
network, it will show the transmission of spectral information between Albuquerque,
|
||||
New Mexico and Atlanta, Georgia.)
|
||||
|
||||
This script calculates the average signal OSNR = |OSNR| and SNR = |SNR|.
|
||||
|
||||
@@ -209,7 +209,7 @@ The fiber library currently describes SSMF but additional fiber types can be ent
|
||||
+----------------------+-----------+-----------------------------------------+
|
||||
| field | type | description |
|
||||
+======================+===========+=========================================+
|
||||
| `type_variety` | (string) | a unique name to ID the amplifier in the|
|
||||
| `type_variety` | (string) | a unique name to ID the fiber in the |
|
||||
| | | JSON or Excel template topology input |
|
||||
| | | file |
|
||||
+----------------------+-----------+-----------------------------------------+
|
||||
@@ -226,7 +226,7 @@ path_request_run.py routine.
|
||||
+----------------------+-----------+-----------------------------------------+
|
||||
| field | type | description |
|
||||
+======================+===========+=========================================+
|
||||
| `type_variety` | (string) | a unique name to ID the amplifier in |
|
||||
| `type_variety` | (string) | a unique name to ID the transceiver in |
|
||||
| | | the JSON or Excel template topology |
|
||||
| | | input file |
|
||||
+----------------------+-----------+-----------------------------------------+
|
||||
@@ -252,7 +252,7 @@ The modes are defined as follows:
|
||||
+----------------------+-----------+-----------------------------------------+
|
||||
| `bit_rate` | (number) | in bit/s |
|
||||
+----------------------+-----------+-----------------------------------------+
|
||||
| `roll_off` | (number) | |
|
||||
| `roll_off` | (number) | Not used. |
|
||||
+----------------------+-----------+-----------------------------------------+
|
||||
|
||||
Simulation parameters are defined as follows.
|
||||
@@ -269,8 +269,8 @@ For amplifiers defined in the topology JSON input but whose gain = 0
|
||||
(placeholder), auto-design will set its gain automatically: see `power_mode` in
|
||||
the `Spans` library to find out how the gain is calculated.
|
||||
|
||||
Span configuration is performed as followws. It is not a list (which may change
|
||||
in later releases,) and the user can only modify the value of existing
|
||||
Span configuration is performed as follows. It is not a list (which may change
|
||||
in later releases) and the user can only modify the value of existing
|
||||
parameters:
|
||||
|
||||
+------------------------+-----------+---------------------------------------------+
|
||||
@@ -470,11 +470,6 @@ dBm/channel. These are not yet parametrized but can be modified directly in the
|
||||
script (via the SpectralInformation structure) to accomodate any baud rate,
|
||||
spacing, power or channel count demand.
|
||||
|
||||
The amplifier's gain is set to exactly compensate for the loss in each network
|
||||
element. The amplifier is currently defined with gain range of 15 dB to 25 dB
|
||||
and 21 dBm max output power. Ripple and NF models are defined in
|
||||
`examples/std_medium_gain_advanced_config.json <examples/std_medium_gain_advanced_config.json>`_
|
||||
|
||||
Use `examples/path_requests_run.py <examples/path_requests_run.py>`_ to run multiple optimizations as follows:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
@@ -70,7 +70,7 @@ def read_excel(input_filename):
|
||||
|
||||
def create_eqt_template(links,nodes, links_by_src , links_by_dest, input_filename):
|
||||
output_filename = f'{input_filename[:-4]}_eqpt_sheet.txt'
|
||||
with open(output_filename,'w') as my_file :
|
||||
with open(output_filename, 'w', encoding='utf-8') as my_file:
|
||||
# print header similar to excel
|
||||
my_file.write('OPTIONAL\n\n\n\
|
||||
\t\tNode a egress amp (from a to z)\t\t\t\t\tNode a ingress amp (from z to a) \
|
||||
|
||||
@@ -64,6 +64,16 @@
|
||||
"type_variety": "SSMF",
|
||||
"dispersion": 1.67e-05,
|
||||
"gamma": 0.00127
|
||||
},
|
||||
{
|
||||
"type_variety": "NZDF",
|
||||
"dispersion": 0.5e-05,
|
||||
"gamma": 0.00146
|
||||
},
|
||||
{
|
||||
"type_variety": "LOF",
|
||||
"dispersion": 2.2e-05,
|
||||
"gamma": 0.000843
|
||||
}
|
||||
],
|
||||
"Spans":[{
|
||||
|
||||
@@ -117,7 +117,7 @@ def load_requests(filename,eqpt_filename):
|
||||
logger.info('Automatically converting requests from XLS to JSON')
|
||||
json_data = convert_service_sheet(filename,eqpt_filename)
|
||||
else:
|
||||
with open(filename) as f:
|
||||
with open(filename, encoding='utf-8') as f:
|
||||
json_data = loads(f.read())
|
||||
return json_data
|
||||
|
||||
@@ -297,7 +297,7 @@ if __name__ == '__main__':
|
||||
for p in pths:
|
||||
result.append(Result_element(rqs[pths.index(p)],p))
|
||||
with open(args.output, 'w') as f:
|
||||
f.write(dumps(path_result_json(result), indent=2))
|
||||
f.write(dumps(path_result_json(result), indent=2, ensure_ascii=False))
|
||||
fnamecsv = next(s for s in args.output.split('.')) + '.csv'
|
||||
with open(fnamecsv,"w") as fcsv :
|
||||
jsontocsv(path_result_json(result),equipment,fcsv)
|
||||
|
||||
@@ -150,16 +150,14 @@ if __name__ == '__main__':
|
||||
exit()
|
||||
|
||||
if args.source:
|
||||
try:
|
||||
source = next(transceivers[uid] for uid in transceivers if uid == args.source)
|
||||
except StopIteration as e:
|
||||
source = transceivers.get(args.source)
|
||||
if not source:
|
||||
#TODO code a more advanced regex to find nodes match
|
||||
nodes_suggestion = [uid for uid in transceivers \
|
||||
if args.source.lower() in uid.lower()]
|
||||
source = transceivers[nodes_suggestion[0]] \
|
||||
if len(nodes_suggestion)>0 else list(transceivers.values())[0]
|
||||
print(f'invalid souce node specified, did you mean:\
|
||||
\n{nodes_suggestion}?\
|
||||
print(f'invalid souce node specified,\
|
||||
\n{args.source!r}, replaced with {source.uid}')
|
||||
del transceivers[source.uid]
|
||||
else:
|
||||
@@ -167,15 +165,13 @@ if __name__ == '__main__':
|
||||
source = list(transceivers.values())[0]
|
||||
|
||||
if args.destination:
|
||||
try:
|
||||
destination = next(transceivers[uid] for uid in transceivers if uid == args.destination)
|
||||
except StopIteration as e:
|
||||
destination = transceivers.get(args.destination)
|
||||
if not destination:
|
||||
nodes_suggestion = [uid for uid in transceivers \
|
||||
if args.destination.lower() in uid.lower()]
|
||||
destination = transceivers[nodes_suggestion[0]] \
|
||||
if len(nodes_suggestion)>0 else list(transceivers.values())[0]
|
||||
print(f'invalid destination node specified, did you mean:\
|
||||
\n{nodes_suggestion}?\
|
||||
print(f'invalid destination node specified,\
|
||||
\n{args.destination!r}, replaced with {destination.uid}')
|
||||
else:
|
||||
logger.info('No source node specified: picking random transceiver')
|
||||
|
||||
@@ -26,8 +26,8 @@ parser.add_argument('eqpt_filename', nargs='?', type = Path, default=Path(__file
|
||||
if __name__ == '__main__':
|
||||
args = parser.parse_args()
|
||||
|
||||
with open(args.output_filename,"w") as file :
|
||||
with open(args.filename) as f:
|
||||
with open(args.output_filename, 'w', encoding='utf-8') as file:
|
||||
with open(args.filename, encoding='utf-8') as f:
|
||||
print(f'Reading {args.filename}')
|
||||
json_data = loads(f.read())
|
||||
equipment = load_equipment(args.eqpt_filename)
|
||||
|
||||
@@ -214,14 +214,12 @@ def convert_file(input_filename, filter_region=[]):
|
||||
for x in nodes_by_city.values() if x.node_type.lower()=='roadm'])))
|
||||
}
|
||||
|
||||
#print(dumps(data, indent=2))
|
||||
# output_json_file_name = input_filename.split(".")[0]+".json"
|
||||
suffix_filename = str(input_filename.suffixes[0])
|
||||
full_input_filename = str(input_filename)
|
||||
split_filename = [full_input_filename[0:len(full_input_filename)-len(suffix_filename)] , suffix_filename[1:]]
|
||||
output_json_file_name = split_filename[0]+'.json'
|
||||
with open(output_json_file_name,'w') as edfa_json_file:
|
||||
edfa_json_file.write(dumps(data, indent=2))
|
||||
with open(output_json_file_name, 'w', encoding='utf-8') as edfa_json_file:
|
||||
edfa_json_file.write(dumps(data, indent=2, ensure_ascii=False))
|
||||
return output_json_file_name
|
||||
|
||||
def parse_excel(input_filename):
|
||||
|
||||
@@ -13,7 +13,7 @@ from sys import exit
|
||||
from operator import itemgetter
|
||||
from math import isclose
|
||||
from pathlib import Path
|
||||
from json import loads
|
||||
from json import load
|
||||
from gnpy.core.utils import lin2db, db2lin, load_json
|
||||
from collections import namedtuple
|
||||
from gnpy.core.elements import Edfa
|
||||
@@ -43,14 +43,14 @@ class Amp(AmpBase):
|
||||
|
||||
@classmethod
|
||||
def from_advanced_json(cls, filename, **kwargs):
|
||||
with open(filename) as f:
|
||||
json_data = loads(f.read())
|
||||
with open(filename, encoding='utf-8') as f:
|
||||
json_data = load(f)
|
||||
return cls(**{**kwargs, **json_data, 'type_def':None, 'nf_model':None})
|
||||
|
||||
@classmethod
|
||||
def from_default_json(cls, filename, **kwargs):
|
||||
with open(filename) as f:
|
||||
json_data = loads(f.read())
|
||||
with open(filename, encoding='utf-8') as f:
|
||||
json_data = load(f)
|
||||
type_variety = kwargs['type_variety']
|
||||
type_def = kwargs.get('type_def', 'variable_gain') #default compatibility with older json eqpt files
|
||||
nf_def = None
|
||||
@@ -211,17 +211,17 @@ def equipment_from_json(json_data, filename):
|
||||
"""
|
||||
equipment = {}
|
||||
for key, entries in json_data.items():
|
||||
equipment[key] = {}
|
||||
typ = globals()[key]
|
||||
for entry in entries:
|
||||
if key not in equipment:
|
||||
equipment[key] = {}
|
||||
subkey = entry.get('type_variety', 'default')
|
||||
typ = globals()[key]
|
||||
subkey = entry.get('type_variety', 'default')
|
||||
if key == 'Edfa':
|
||||
if 'advanced_config_from_json' in entry:
|
||||
config = Path(filename).parent / entry.pop('advanced_config_from_json')
|
||||
typ = lambda **kws: Amp.from_advanced_json(config, **kws)
|
||||
equipment[key][subkey] = Amp.from_advanced_json(config, **entry)
|
||||
else:
|
||||
config = Path(filename).parent / 'default_edfa_config.json'
|
||||
typ = lambda **kws: Amp.from_default_json(config, **kws)
|
||||
equipment[key][subkey] = typ(**entry)
|
||||
equipment[key][subkey] = Amp.from_default_json(config, **entry)
|
||||
else:
|
||||
equipment[key][subkey] = typ(**entry)
|
||||
return equipment
|
||||
|
||||
@@ -189,7 +189,7 @@ def convert_service_sheet(input_filename, eqpt_filename, output_filename='', fil
|
||||
if n.json[1] is not None]
|
||||
}
|
||||
with open(output_filename, 'w') as f:
|
||||
f.write(dumps(data, indent=2))
|
||||
f.write(dumps(data, indent=2, ensure_ascii=False))
|
||||
return data
|
||||
|
||||
# to be used from dutc
|
||||
|
||||
@@ -18,14 +18,14 @@ from scipy import constants
|
||||
|
||||
|
||||
def load_json(filename):
|
||||
with open(filename, 'r') as f:
|
||||
with open(filename, 'r', encoding='utf-8') as f:
|
||||
data = json.load(f)
|
||||
return data
|
||||
|
||||
|
||||
def save_json(obj, filename):
|
||||
with open(filename, 'w') as f:
|
||||
json.dump(obj, f, indent=2)
|
||||
with open(filename, 'w', encoding='utf-8') as f:
|
||||
json.dump(obj, f, indent=2, ensure_ascii=False)
|
||||
|
||||
def write_csv(obj, filename):
|
||||
"""
|
||||
@@ -55,7 +55,7 @@ def write_csv(obj, filename):
|
||||
result_category 2
|
||||
...
|
||||
"""
|
||||
with open(filename, 'w') as f:
|
||||
with open(filename, 'w', encoding='utf-8') as f:
|
||||
w = writer(f)
|
||||
for data_key, data_list in obj.items():
|
||||
#main header
|
||||
|
||||
@@ -105,16 +105,16 @@ def encode_sets(obj):
|
||||
if __name__ == '__main__':
|
||||
args = parser.parse_args()
|
||||
|
||||
with open(args.expected_output) as f:
|
||||
with open(args.expected_output, encoding='utf-8') as f:
|
||||
expected = load(f)
|
||||
|
||||
with open(args.actual_output) as f:
|
||||
with open(args.actual_output, encoding='utf-8') as f:
|
||||
actual = load(f)
|
||||
|
||||
result = COMPARISONS[args.comparison](expected, actual)
|
||||
|
||||
if args.output:
|
||||
with open(args.output, 'w') as f:
|
||||
dump(result, f, default=encode_sets, indent=2)
|
||||
with open(args.output, 'w', encoding='utf-8') as f:
|
||||
dump(result, f, default=encode_sets, indent=2, ensure_ascii=False)
|
||||
else:
|
||||
print(str(result))
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
from gnpy.core.elements import Edfa
|
||||
from numpy import zeros, array
|
||||
from json import load, dumps
|
||||
from json import load
|
||||
from gnpy.core.elements import Transceiver, Fiber, Edfa
|
||||
from gnpy.core.utils import lin2db, db2lin
|
||||
from gnpy.core.info import create_input_spectral_information, SpectralInformation, Channel, Power, Pref
|
||||
|
||||
@@ -37,11 +37,11 @@ def test_excel_json_generation(xls_input, expected_json_output):
|
||||
convert_file(xls_input)
|
||||
|
||||
actual_json_output = xls_input.with_suffix('.json')
|
||||
with open(actual_json_output) as f:
|
||||
with open(actual_json_output, encoding='utf-8') as f:
|
||||
actual = load(f)
|
||||
unlink(actual_json_output)
|
||||
|
||||
with open(expected_json_output) as f:
|
||||
with open(expected_json_output, encoding='utf-8') as f:
|
||||
expected = load(f)
|
||||
|
||||
results = compare_networks(expected, actual)
|
||||
@@ -65,11 +65,11 @@ def test_excel_service_json_generation(xls_input, expected_json_output):
|
||||
convert_service_sheet(xls_input, eqpt_filename)
|
||||
|
||||
actual_json_output = f'{str(xls_input)[:-4]}_services.json'
|
||||
with open(actual_json_output) as f:
|
||||
with open(actual_json_output, encoding='utf-8') as f:
|
||||
actual = load(f)
|
||||
unlink(actual_json_output)
|
||||
|
||||
with open(expected_json_output) as f:
|
||||
with open(expected_json_output, encoding='utf-8') as f:
|
||||
expected = load(f)
|
||||
|
||||
results = compare_services(expected, actual)
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
from gnpy.core.elements import Edfa
|
||||
import numpy as np
|
||||
from json import load, dumps
|
||||
from json import load
|
||||
import pytest
|
||||
from gnpy.core.elements import Transceiver, Fiber, Edfa
|
||||
from gnpy.core.utils import lin2db, db2lin
|
||||
|
||||
Reference in New Issue
Block a user