diff --git a/README.rst b/README.rst index 290c3b5d..2f1eb33f 100644 --- a/README.rst +++ b/README.rst @@ -9,7 +9,7 @@ planning and optimization tools in real-world mesh optical networks.** `gnpy `__ is: -- a sponsored project of the `OOPT/PSE `_ working group of the `Telecom Infra Project `_. +- a sponsored project of the `OOPT/PSE `_ working group of the `Telecom Infra Project `_ - 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 `_ 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 `_: +example, to use the CORONET Global network defined in +`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 `_. 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 `_ - Use `examples/path_requests_run.py `_ to run multiple optimizations as follows: .. code-block:: shell diff --git a/examples/create_eqpt_sheet.py b/examples/create_eqpt_sheet.py index f1e247f7..b0f7b4ca 100644 --- a/examples/create_eqpt_sheet.py +++ b/examples/create_eqpt_sheet.py @@ -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) \ diff --git a/examples/eqpt_config.json b/examples/eqpt_config.json index dc255f34..0e64a6e1 100644 --- a/examples/eqpt_config.json +++ b/examples/eqpt_config.json @@ -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":[{ diff --git a/examples/path_requests_run.py b/examples/path_requests_run.py index aced5885..4e132c7b 100755 --- a/examples/path_requests_run.py +++ b/examples/path_requests_run.py @@ -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) diff --git a/examples/transmission_main_example.py b/examples/transmission_main_example.py index 71edc5c6..f225e884 100755 --- a/examples/transmission_main_example.py +++ b/examples/transmission_main_example.py @@ -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') diff --git a/examples/write_path_jsontocsv.py b/examples/write_path_jsontocsv.py index 1a7584b3..b7b50dd2 100644 --- a/examples/write_path_jsontocsv.py +++ b/examples/write_path_jsontocsv.py @@ -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) diff --git a/gnpy/core/convert.py b/gnpy/core/convert.py index f07a288d..b356e03e 100755 --- a/gnpy/core/convert.py +++ b/gnpy/core/convert.py @@ -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): diff --git a/gnpy/core/equipment.py b/gnpy/core/equipment.py index 52ad2db4..e1991a75 100644 --- a/gnpy/core/equipment.py +++ b/gnpy/core/equipment.py @@ -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 diff --git a/gnpy/core/service_sheet.py b/gnpy/core/service_sheet.py index ecfbc0e1..d0822e60 100644 --- a/gnpy/core/service_sheet.py +++ b/gnpy/core/service_sheet.py @@ -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 diff --git a/gnpy/core/utils.py b/gnpy/core/utils.py index 96d1716f..44c4c099 100644 --- a/gnpy/core/utils.py +++ b/gnpy/core/utils.py @@ -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 diff --git a/tests/compare.py b/tests/compare.py index 90d03ce8..d11423c6 100644 --- a/tests/compare.py +++ b/tests/compare.py @@ -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)) diff --git a/tests/test_amplifier.py b/tests/test_amplifier.py index e6eceffb..ace6b094 100644 --- a/tests/test_amplifier.py +++ b/tests/test_amplifier.py @@ -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 diff --git a/tests/test_parser.py b/tests/test_parser.py index dbfe94b9..751bcb38 100644 --- a/tests/test_parser.py +++ b/tests/test_parser.py @@ -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) diff --git a/tests/test_propagation.py b/tests/test_propagation.py index 08400024..c2e77ec7 100644 --- a/tests/test_propagation.py +++ b/tests/test_propagation.py @@ -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