From acafc78456a2701cfed210a2d3037cc6a9e6e0a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Kundr=C3=A1t?= Date: Wed, 18 Sep 2019 20:04:17 +0200 Subject: [PATCH 1/7] Remove debug printing from propagate() This is inspired by #293. The original issue was that the transponder OSNR was not accounted for. Rather than making the propagate() and propagate2() more complex, let's move the actual path printing to the demo code. There's no secret sauce in there, it's just a simple for-each-print thingy, so let's remove it from the library code. fixes #262 --- examples/path_requests_run.py | 4 ++-- examples/transmission_main_example.py | 5 ++++- gnpy/core/request.py | 12 +++--------- tests/test_automaticmodefeature.py | 2 +- 4 files changed, 10 insertions(+), 13 deletions(-) diff --git a/examples/path_requests_run.py b/examples/path_requests_run.py index 32b28180f..e70fe0d2d 100755 --- a/examples/path_requests_run.py +++ b/examples/path_requests_run.py @@ -168,7 +168,7 @@ def compute_path(network, equipment, pathreqlist): print(f'Computed path (roadms):{[e.uid for e in total_path if isinstance(e, Roadm)]}\n') if total_path : - total_path = propagate(total_path,pathreq,equipment, show=False) + total_path = propagate(total_path,pathreq,equipment) else: total_path = [] # we record the last tranceiver object in order to have th whole @@ -205,7 +205,7 @@ def compute_path_with_disjunction(network, equipment, pathreqlist, pathlist): # print(f'{pathreq.baud_rate} {pathreq.power} {pathreq.spacing} {pathreq.nb_channel}') if total_path : if pathreq.baud_rate is not None: - total_path = propagate(total_path,pathreq,equipment, show=False) + total_path = propagate(total_path,pathreq,equipment) temp_snr01nm = round(mean(total_path[-1].snr+lin2db(pathreq.baud_rate/(12.5e9))),2) if temp_snr01nm < pathreq.OSNR : msg = f'\tWarning! Request {pathreq.request_id} computed path from {pathreq.source} to {pathreq.destination} does not pass with {pathreq.tsp_mode}\n' +\ diff --git a/examples/transmission_main_example.py b/examples/transmission_main_example.py index 12a417a84..eab66bd2a 100755 --- a/examples/transmission_main_example.py +++ b/examples/transmission_main_example.py @@ -153,7 +153,10 @@ def main(network, equipment, source, destination, sim_params, req=None): print(f'\nPropagating with input power = {lin2db(req.power*1e3):.2f}dBm :') else: print(f'\nPropagating in gain mode: power cannot be set manually') - infos = propagate2(path, req, equipment, show=len(power_range)==1) + infos = propagate2(path, req, equipment) + if len(power_range) == 1: + for elem in path[:-1]: + print(elem) if power_mode: print(f'\nTransmission result for input power = {lin2db(req.power*1e3):.2f}dBm :') else: diff --git a/gnpy/core/request.py b/gnpy/core/request.py index 7f2a1e350..ffbf071a7 100644 --- a/gnpy/core/request.py +++ b/gnpy/core/request.py @@ -393,18 +393,16 @@ def compute_constrained_path(network, req): return total_path -def propagate(path, req, equipment, show=False): +def propagate(path, req, equipment): si = create_input_spectral_information( req.f_min, req.f_max, req.roll_off, req.baud_rate, req.power, req.spacing) for el in path: si = el(si) - if show : - print(el) path[-1].update_snr(req.tx_osnr, equipment['Roadm']['default'].add_drop_osnr) return path -def propagate2(path, req, equipment, show=False): +def propagate2(path, req, equipment): si = create_input_spectral_information( req.f_min, req.f_max, req.roll_off, req.baud_rate, req.power, req.spacing) @@ -413,12 +411,10 @@ def propagate2(path, req, equipment, show=False): before_si = si after_si = si = el(si) infos[el] = before_si, after_si - if show : - print(el) path[-1].update_snr(req.tx_osnr, equipment['Roadm']['default'].add_drop_osnr) return infos -def propagate_and_optimize_mode(path, req, equipment, show=False): +def propagate_and_optimize_mode(path, req, equipment): # if mode is unknown : loops on the modes starting from the highest baudrate fiting in the # step 1: create an ordered list of modes based on baudrate baudrate_to_explore = list(set([m['baud_rate'] for m in equipment['Transceiver'][req.tsp].mode @@ -442,8 +438,6 @@ def propagate_and_optimize_mode(path, req, equipment, show=False): b, req.power, req.spacing) for el in path: si = el(si) - if show: - print(el) for m in modes_to_explore : if path[-1].snr is not None: path[-1].update_snr(m['tx_osnr'], equipment['Roadm']['default'].add_drop_osnr) diff --git a/tests/test_automaticmodefeature.py b/tests/test_automaticmodefeature.py index a5c34ea92..05cc9eaa5 100644 --- a/tests/test_automaticmodefeature.py +++ b/tests/test_automaticmodefeature.py @@ -72,7 +72,7 @@ def test_automaticmodefeature(net,eqpt,serv,expected_mode): if pathreq.baud_rate is not None: print(pathreq.format) path_res_list.append(pathreq.format) - total_path = propagate(total_path,pathreq,equipment, show=False) + total_path = propagate(total_path,pathreq,equipment) else: total_path,mode = propagate_and_optimize_mode(total_path,pathreq,equipment) # if no baudrate satisfies spacing, no mode is returned and an empty path is returned From 07de489d6b267f96357541db0bae17a98649b6fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Kundr=C3=A1t?= Date: Mon, 17 Jun 2019 19:26:15 +0200 Subject: [PATCH 2/7] doc: fiber length summary in km, not meters reading "80000m" is a bit more complex than just "80 km". Also let's add a space between the numebr and the unit for better readability. --- examples/transmission_main_example.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/transmission_main_example.py b/examples/transmission_main_example.py index eab66bd2a..f854cfaee 100755 --- a/examples/transmission_main_example.py +++ b/examples/transmission_main_example.py @@ -133,7 +133,7 @@ def main(network, equipment, source, destination, sim_params, req=None): configure_network(network, sim_params) spans = [s.length for s in path if isinstance(s, RamanFiber) or isinstance(s, Fiber)] - print(f'\nThere are {len(spans)} fiber spans over {sum(spans):.0f}m between {source.uid} and {destination.uid}') + print(f'\nThere are {len(spans)} fiber spans over {sum(spans)/1000:.0f} km between {source.uid} and {destination.uid}') print(f'\nNow propagating between {source.uid} and {destination.uid}:') try: From c817ef733520360f1f01aadf6145393ead4e3014 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Kundr=C3=A1t?= Date: Mon, 17 Jun 2019 19:28:12 +0200 Subject: [PATCH 3/7] examples: color highlighting of the "most interesting output" I think that this SNR value represents the most important output of this example. There's plenty of debugging info on display already, so let's make this one more prominent. I was thinking about moving the highlighting to elements' each __str__() function, but that felt a bit like layering violation to me. I could have also changed just the transponder's __str__(). In the end, I think that repeating just the final GSNR at the link-end transponder makes most sense here. This is aligned with what we talked about at yesterday's (on 2019-09-18 -- note that this is a backport from #261) demo for Microsoft, after all. --- examples/transmission_main_example.py | 14 ++++++-------- gnpy/core/ansi_escapes.py | 1 + 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/examples/transmission_main_example.py b/examples/transmission_main_example.py index f854cfaee..0ddfad084 100755 --- a/examples/transmission_main_example.py +++ b/examples/transmission_main_example.py @@ -150,19 +150,18 @@ def main(network, equipment, source, destination, sim_params, req=None): for dp_db in power_range: req.power = db2lin(pref_ch_db + dp_db)*1e-3 if power_mode: - print(f'\nPropagating with input power = {lin2db(req.power*1e3):.2f}dBm :') + print(f'\nPropagating with input power = {ansi_escapes.cyan}{lin2db(req.power*1e3):.2f} dBm{ansi_escapes.reset}:') else: - print(f'\nPropagating in gain mode: power cannot be set manually') + print(f'\nPropagating in {ansi_escapes.cyan}gain mode{ansi_escapes.reset}: power cannot be set manually') infos = propagate2(path, req, equipment) if len(power_range) == 1: - for elem in path[:-1]: + for elem in path: print(elem) if power_mode: - print(f'\nTransmission result for input power = {lin2db(req.power*1e3):.2f}dBm :') + print(f'\nTransmission result for input power = {lin2db(req.power*1e3):.2f} dBm:') else: print(f'\nTransmission results:') - #info message in gain mode - print(destination) + print(f' Final GSNR (signal bw): {ansi_escapes.cyan}{mean(destination.snr):.02f} dB{ansi_escapes.reset}') #print(f'\n !!!!!!!!!!!!!!!!! TEST POINT !!!!!!!!!!!!!!!!!!!!!') #print(f'carriers ase output of {path[1]} =\n {list(path[1].carriers("out", "nli"))}') @@ -183,8 +182,7 @@ def main(network, equipment, source, destination, sim_params, req=None): 'OSNR_ASE_signal_bw' : round(mean(destination.osnr_ase),2), 'SNR_nli_signal_bw' : round(mean(destination.osnr_nli),2), 'SNR_total_signal_bw' : round(mean(destination.snr),2) - }) - #info message in gain mode + }) write_csv(result_dicts, 'simulation_result.csv') return path, infos diff --git a/gnpy/core/ansi_escapes.py b/gnpy/core/ansi_escapes.py index 16812a382..072d75cba 100644 --- a/gnpy/core/ansi_escapes.py +++ b/gnpy/core/ansi_escapes.py @@ -9,4 +9,5 @@ ''' red = '\x1b[1;31;40m' +cyan = '\x1b[1;36;40m' reset = '\x1b[0m' From faa69917d91b5b8b636ce788fa5eb75f173b028b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Kundr=C3=A1t?= Date: Fri, 20 Sep 2019 17:11:42 +0200 Subject: [PATCH 4/7] example: Use "Total SNR", not "GSNR" Various presentations from Polito are slowly changing to use "GSNR" as a "Generalized SNR", but it's true that our code does not use this term anywhere, and that it is not properly explained. Let's wait a bit for this term to become a bit more mainstream and for updated docs on our side; then this commit can be safely reverted. Thanks to Jonas for reporting this. --- examples/transmission_main_example.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/transmission_main_example.py b/examples/transmission_main_example.py index 0ddfad084..340b3e07f 100755 --- a/examples/transmission_main_example.py +++ b/examples/transmission_main_example.py @@ -161,7 +161,7 @@ def main(network, equipment, source, destination, sim_params, req=None): print(f'\nTransmission result for input power = {lin2db(req.power*1e3):.2f} dBm:') else: print(f'\nTransmission results:') - print(f' Final GSNR (signal bw): {ansi_escapes.cyan}{mean(destination.snr):.02f} dB{ansi_escapes.reset}') + print(f' Final SNR total (signal bw): {ansi_escapes.cyan}{mean(destination.snr):.02f} dB{ansi_escapes.reset}') #print(f'\n !!!!!!!!!!!!!!!!! TEST POINT !!!!!!!!!!!!!!!!!!!!!') #print(f'carriers ase output of {path[1]} =\n {list(path[1].carriers("out", "nli"))}') From 33ff0910b892a0c0aa41f2ac72ece91a077f82a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Kundr=C3=A1t?= Date: Sun, 22 Sep 2019 12:20:11 +0200 Subject: [PATCH 5/7] Remove unused function This has been marked obsolete for 11 months. It's also one of the callers of the propagate(), so it's being touched by that change which removes the `show` parameter. This commit will make it easier to put debug path printing just where it's really needed. --- examples/path_requests_run.py | 38 ----------------------------------- 1 file changed, 38 deletions(-) diff --git a/examples/path_requests_run.py b/examples/path_requests_run.py index e70fe0d2d..d8dcbc338 100755 --- a/examples/path_requests_run.py +++ b/examples/path_requests_run.py @@ -144,44 +144,6 @@ def load_requests(filename,eqpt_filename): json_data = loads(f.read()) return json_data -def compute_path(network, equipment, pathreqlist): - - # This function is obsolete and not relevant with respect to network building: suggest either to correct - # or to suppress it - - path_res_list = [] - - for pathreq in pathreqlist: - #need to rebuid the network for each path because the total power - #can be different and the choice of amplifiers in autodesign is power dependant - #but the design is the same if the total power is the same - #TODO parametrize the total spectrum power so the same design can be shared - p_db = lin2db(pathreq.power*1e3) - p_total_db = p_db + lin2db(pathreq.nb_channel) - build_network(network, equipment, p_db, p_total_db) - pathreq.nodes_list.append(pathreq.destination) - #we assume that the destination is a strict constraint - pathreq.loose_list.append('strict') - print(f'Computing path from {pathreq.source} to {pathreq.destination}') - print(f'with path constraint: {[pathreq.source]+pathreq.nodes_list}') #adding first node to be clearer on the output - total_path = compute_constrained_path(network, pathreq) - print(f'Computed path (roadms):{[e.uid for e in total_path if isinstance(e, Roadm)]}\n') - - if total_path : - total_path = propagate(total_path,pathreq,equipment) - else: - total_path = [] - # we record the last tranceiver object in order to have th whole - # information about spectrum. Important Note: since transceivers - # attached to roadms are actually logical elements to simulate - # performance, several demands having the same destination may use - # the same transponder for the performance simaulation. This is why - # we use deepcopy: to ensure each propagation is recorded and not - # overwritten - - path_res_list.append(deepcopy(total_path)) - return path_res_list - def compute_path_with_disjunction(network, equipment, pathreqlist, pathlist): # use a list but a dictionnary might be helpful to find path bathsed on request_id From d8c236bb44473b98cef1993a9692bff0c6c67593 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Kundr=C3=A1t?= Date: Sun, 22 Sep 2019 16:44:00 +0100 Subject: [PATCH 6/7] examples: do not measure time taken This is an equivalent of 9c9e3be9675a78aefae555c32596e8faff3585f3 for the other example. --- examples/path_requests_run.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/examples/path_requests_run.py b/examples/path_requests_run.py index d8dcbc338..a5fc979cd 100755 --- a/examples/path_requests_run.py +++ b/examples/path_requests_run.py @@ -35,7 +35,6 @@ from copy import copy, deepcopy from textwrap import dedent from math import ceil -import time #EQPT_LIBRARY_FILENAME = Path(__file__).parent / 'eqpt_config.json' @@ -263,7 +262,6 @@ def path_result_json(pathresult): if __name__ == '__main__': - start = time.time() args = parser.parse_args() basicConfig(level={2: DEBUG, 1: INFO, 0: CRITICAL}.get(args.verbose, DEBUG)) logger.info(f'Computing path requests {args.service_filename} into JSON format') @@ -331,8 +329,6 @@ def path_result_json(pathresult): print('\x1b[1;34;40m'+f'Propagating on selected path'+ '\x1b[0m') propagatedpths = compute_path_with_disjunction(network, equipment, rqs, pths) - end = time.time() - print(f'computation time {end-start}') print('\x1b[1;34;40m'+f'Result summary'+ '\x1b[0m') header = ['req id', ' demand',' snr@bandwidth',' snr@0.1nm',' Receiver minOSNR', ' mode', ' Gbit/s' , ' nb of tsp pairs'] From ec9eb8d054f8809c4ef981fb1a3d90b5193faa6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Kundr=C3=A1t?= Date: Mon, 23 Sep 2019 00:14:56 +0100 Subject: [PATCH 7/7] examples: commented-out path printing for Esther I'm trying to clean up the core code while not causing too much trouble to our users. Esther pointed out that there's an internal use case at Orange where people are looking at the incremental results when computing paths. I strongly dislike commented-out debugging code, but for the sake of progress, let's put it in here. It's roughly as good as that unused `show` parameter, and it allowed a refactoring to make the code more readable. --- examples/path_requests_run.py | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/path_requests_run.py b/examples/path_requests_run.py index a5fc979cd..4b836e8a1 100755 --- a/examples/path_requests_run.py +++ b/examples/path_requests_run.py @@ -167,6 +167,7 @@ def compute_path_with_disjunction(network, equipment, pathreqlist, pathlist): if total_path : if pathreq.baud_rate is not None: total_path = propagate(total_path,pathreq,equipment) + # for el in total_path: print(el) temp_snr01nm = round(mean(total_path[-1].snr+lin2db(pathreq.baud_rate/(12.5e9))),2) if temp_snr01nm < pathreq.OSNR : msg = f'\tWarning! Request {pathreq.request_id} computed path from {pathreq.source} to {pathreq.destination} does not pass with {pathreq.tsp_mode}\n' +\