1538 Commits

Author SHA1 Message Date
EstherLerouzic
c744a97d83 Prepare release notes for v2.13
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Iff07dcd6e98b4e4abd79ec8f97d09df2cf2c0e24
2025-09-26 11:56:02 +02:00
EstherLerouzic
09221504d7 Add yang trees
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I98a16ebea347ff4913840cf6f563c34ebcf8f8d9
2025-09-26 11:52:56 +02:00
EstherLerouzic
f2039fbe1c fix: use loaded json instead of Path for extra configs
In order to be used by API.

Co-authored-by: Renato Ambrosone <renato.ambrosone@polito.it>

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I12111427c8a90b85b3158cdd95f4ee771cb39316
2025-09-26 11:17:45 +02:00
EstherLerouzic
78227e65da fix documentation and release notes
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I18457b1bdebd92bdd547877760a039706ad995a3
2025-09-26 11:17:45 +02:00
EstherLerouzic
e27e6d5c7b chore: add release notes
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ia561105ac5b3fa246bbd26a37e495e0d2ae92041
2025-09-26 11:17:45 +02:00
EstherLerouzic
e3445e1066 Update maintainer names
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I9122bfcf91a6cb55a6c50f98c6944086a21b1b73
2025-09-26 11:17:45 +02:00
EstherLerouzic
a0758d0da5 Move and refactor create_eqpt_sheet.py and add tests on it
Co-authored-by: Rodrigo Sasse David <rodrigo.sassedavid@orange.com>

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ib961c5c0e203f2225a0f1e2e7a091485567189c3
2025-09-26 11:17:45 +02:00
EstherLerouzic
0bc1fb3bf8 fix: Use openpyxl for xlsx reading and move to latest xlrd version
Create a set of excel utils to be used for .xls and .xlsx files, for
reading workbook, reading sheets, ... optimize openpyxl access to
sheet to save computation time.

Use this opportunity to refactor service sheet without namedtuple
and simplify code

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ibaf3aac40b3f6ca4829d8ea8cd506523d318103a
2025-09-26 11:17:45 +02:00
Arturo Mayoral
cd9d4c55b2 Publish calendar at docs/calendar.html and update README link to GitHub Pages
Change-Id: I0381b8d8ebcf3b40d15d1e80fa22bbc3613348e3
2025-09-17 13:13:51 +02:00
EstherLerouzic
62889bf6af feat: add a console script for yang conversion
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: If5ec36beec9d90b2f3d8c08c7fb5b629ad722245
2025-09-03 12:58:21 +02:00
EstherLerouzic
61787d5052 feat: parametrize the function that computes power targets
enable changing the reference span loss and the ratio of the
loss deviation to this reference that should be reported on
the span input.

Initial target used a hardcoded 20dB loss span with
0.3 power slope.

update documentation accordingly.

requires yang updates
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ib763db6be2bd7e947057176f3246f19ac7e6ac0d
2025-09-03 10:34:16 +02:00
Florian FRANK
6612a46a9e Fix to_json()-function of Multiband_amplifier when gain is missing
Signed-off-by: Florian FRANK <florian1.frank@orange.com>
Change-Id: I2a0c249c7e3278e282c2c45ea8be52073f014de3
2025-09-03 10:34:16 +02:00
EstherLerouzic
f30515ba9d fix: do not replace 0 with None
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I02ee8f4f1148873fd19f1c312578bc1f15355667
2025-09-03 10:34:16 +02:00
EstherLerouzic
6f9897fe40 fix: do not crash if type_variety is not defined when saving network
before autodesign type_variety may not be created yet, while ther is one default in params:
use type_variety from params

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I556bc8fa1a8241054c81cee386cf52b94a76a0bc
2025-09-03 10:34:16 +02:00
EstherLerouzic
56e615c713 Feat: Use a reference channel per OMS instead of total power for design
Correctly uses the oms band and spacing for computing the nb of channel
and total power for design per band.
In order to keep the SI values as reference, introduce a new parameter
in SI to indicate wether to use this feature or not.

If "use_si_channel_count_for_design": true, then the f_min, f_max and spacing
from SI are used for all OMSes
else, the f_min, f_max, spacing defined per OMS (design_bands) is used.

This impacts tests where the artificial C-band boudaries were hardcoded, and
it also has an impact on performances when SI's defined nb of channels is larger
than the one defined per OMS. In this case the design was considering a larger
total power than the one finally propagated which resulted in reduced performance.
This feature now corrects this case (if "use_si_channel_count_for_design": false
which is the default setting). Overall autodesign are thus improved.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I471a2c45200894ca354c90b46b662f42414b48ad

tous les test marche et les jeu de tests aussi.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: If25b47aa10f97301fde7f17daa2a9478aed46db2
2025-09-03 10:34:15 +02:00
EstherLerouzic
f447c908bc Feat: Add spacing info in the design_band info
This will be used to compute the max total power for design per OMS.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I392f06c792af9f32d4a14324c683bd3fae655de8
2025-09-03 10:34:15 +02:00
EstherLerouzic
4df6cc6b23 fix bug: use preselected restrictions also for raman flag true
otherwise restrictions that include raman are not correctly selected
eg for preamp with raman restriction in ROADM

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ie0215ca430cf463a5422d9236745710ab92ade59
2025-09-03 10:34:15 +02:00
EstherLerouzic
6c5d11d86c Implement in_voa of amplifiers
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I24feed756586a104e829275244f0868a272e5f6b
2025-09-03 10:34:15 +02:00
EstherLerouzic
1a795639c7 feat: Add conversion utilities for YANG and legacy formats in GNPy
This commit introduces new functions for converting between YANG formatted files and
legacy formats. The conversion processes adhere to RFC7951 for encoding YANG data.

Key changes include:
- Conversion of float and empty type representations.
- Transformation of Span and SI lists xx_power_range into dictionaries.
- Addition of necessary namespaces.
- use of oopt-gnpy-libyang to enforce compliancy to yang models

These utilities enable full compatibility with GNPy.

Co-authored-by: Renato Ambrosone <renato.ambrosone@polito.it>

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ia004113bca2b0631d1648564e5ccb60504fe80f8
2025-09-03 10:34:14 +02:00
EstherLerouzic
ee5e6f9b9e fix(CI): remove windows 2019, add windows 2025 support
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I133f5603f00d03e33add8842d34d692ab8fb1804
2025-09-03 10:34:14 +02:00
EstherLerouzic
ea4ab1d61b fix: place index first in the request-list because of libyang bug
libyang does not find key in data if not placed first in the data

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I63b9aa619e15d770e2dcb59010223318d2518eb7
2025-06-30 09:21:42 +02:00
EstherLerouzic
d43fee5945 fix: save network_name
network_name was not correctly exported in json output.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ia4ae6bf82e5d147d3c99e195151942abc21be3f3
2025-06-30 09:21:42 +02:00
EstherLerouzic
6603a50e78 chore: gnpy yang models
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I68502e76e27b43d2a6f6a5741045df3095fc7ccd
2025-06-30 09:21:39 +02:00
EstherLerouzic
b76c529c0c chore: import external ietf modules
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I02ed156105736ab538e4d5708d38b497f9479658
2025-06-11 15:05:51 +02:00
EstherLerouzic
7a1b15a916 chore: make sure all python files have the correct header
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ifdd6a566fda74c5b7d417f9d61c51d4d3da07bfd
2025-06-11 15:05:51 +02:00
EstherLerouzic
7bc9461547 chore: make sure commits authors are in th AUTHORS list
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I721957b59746738426f2356056c553d9876bcf22
2025-06-04 12:22:33 -04:00
EstherLerouzic
b0ac41e2d5 fix: PMD was not correctly read from excel or exported from json
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I1069b07dfb62bf94d4f591908c034df4e49ce22a
2025-03-21 15:42:45 +01:00
EstherLerouzic
bce42331c4 fix: improve core.networks module docstrings
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I883987bd8c1b966b9fcab6a87a62d14607d8548d
2025-03-21 10:46:43 +01:00
EstherLerouzic
d5491c9ace fix documentation: harmonize titles
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I827b4dcd1418017d925b63e50f95514dc1a0eed8
2025-03-21 10:00:25 +01:00
EstherLerouzic
689c2fb038 fix minor linter issues
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I22154752198d9c9186d185885ca83d82e8870107
2025-03-21 10:00:25 +01:00
EstherLerouzic
15c912bd72 fix improve docstring for tools.cli_examples
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Id368cb52791090d985e67be09edcc7580939524b
2025-03-21 10:00:25 +01:00
EstherLerouzic
d0c10e8537 fix: improve dosctring and typing in tools.convert
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I6640737f2255867120f829bb9709abce77693147
2025-03-21 10:00:25 +01:00
EstherLerouzic
93186b26fb fix link to example-data files in the documentation
and of the class referenced in the documentation
example-data folder is not accessible from the
generated pages on readthedocs. So use hyperlinks
to the files  github repo.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I135e2cb0b0d28fecffcbcbfec9a9d6c8cb5c7347
2025-03-21 10:00:25 +01:00
EstherLerouzic
49aee5a4e8 feat: improve elements docstring and typing
use sphinx notation for params , attributes and type

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ife5cde24f3f8dfad9f14dccc6e9b41a13ba370f3
2025-03-21 10:00:21 +01:00
EstherLerouzic
1c4da4794d fix: update excel documentation
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I34ae7e7a60d46482df1af538e6977ba9afd09f3a
2025-03-21 09:57:34 +01:00
EstherLerouzic
de42dd4a93 fix: restore rtd theme
and fix the table with the custom css

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ib16c08451aa3faaa06ea85c2b9359fc4e7a015da
2025-03-21 09:57:34 +01:00
JennyLescop
57a5e9732b fix integrate tilt data into conversion
add some tests

Signed-off-by: JennyLescop <jenny.lescop@orange.com>
Change-Id: I4bb9a16b5db7890247568cce9d4b4f81ad2f7d34
2025-03-21 08:22:37 +00:00
Renato Ambrosone
101eb8f969 Define functions for results conversion and load eqpt/topology from dict
Change-Id: I4111f20f59aeef1e25fc8b44028922bbb94dea91
2025-03-10 16:13:10 +01:00
EstherLerouzic
7ce6650109 feat: move and update documentation on equipment types
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I0f85a059e2393d2d573938bd0804fe49596bbc2d
2025-01-30 17:23:18 +01:00
EstherLerouzic
252e67a71e fix: move amp documentation to the docs folder and update it
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ie6c207e3335cbf30b1f5858c21672dff420b9c51
2025-01-30 17:23:18 +01:00
EstherLerouzic
f83869392b feat: improve documentation of the scripts options
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ic68ded41b188cd07cf87f83e31e6d4eea5af5ed9
2025-01-30 17:23:18 +01:00
EstherLerouzic
94a3714aba fix: documentation missing the worker_utils section
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I832b0f0bfdd255396e6c9809273b1171d08c9f60
2025-01-30 17:23:18 +01:00
EstherLerouzic
ccab4835fc fix: Refactor the methods to avoid returning the same value
equipment being a dict, no need to use 'return' to have the changes
applied.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ic5a4247bbaa0b4af3fca5b6cb0a74a2f434b1b6a
2025-01-30 17:23:18 +01:00
EstherLerouzic
e55f7a5d4c Define default in common parts to be used both by cli and API
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I1e9c6aa99fd2896789c73340ccf5c8adf51a5f13
2025-01-30 17:23:18 +01:00
EstherLerouzic
4fda8c6002 use explicit file arguments for additional configs
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I133bb6a2d21d573cf819e1d92b1912dfa87dbfa4
2025-01-30 17:23:18 +01:00
EstherLerouzic
8717156712 feat: Read a list of optional extra equipement files
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ic521bbacd38b3bb60da3a364a069abfd1895d337
2025-01-30 17:23:18 +01:00
EstherLerouzic
d2c0836164 Remove default_edfa_config.json dictionary and use parameters.py
But enable the user to still input its own default file with a new
'default_config_from_json' attribute useable in fixed and variable gain
amplifiers.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I773682ae6daa1025007fc051582e779986982838
2025-01-29 18:27:51 +00:00
AndreaDAmico
eac4ba80ea List of collaborative PSE publications added in the docs
Change-Id: I1db6d9fe86004cd5bc8135577421117679cb9965
2025-01-24 08:49:48 +00:00
EstherLerouzic
4ef01d54a5 fix plot bug: do not overwrite the path used for plot
The plot function failed to recognize 'path' as part
of the network due to the reuse of the 'path' variable.
This led to errors when attempting to plot.

Solution is to use a different name for the deepcopy of
path elements used to record the propagation results
'propagated_path'.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I0351c37de0d74391ebeb68e974b777b1f51572aa
2025-01-10 11:08:04 +01:00
EstherLerouzic
4b50ee0c2d fix: do not assume 0 dB default value for tilt-target
Instead keep the None value, it user has not stated anything

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I45fcff92caabbfbe514fbe30deac60426b7eb16b
2024-12-06 16:35:46 +01:00
EstherLerouzic
33a289e22b fix: restore uid info in warning logs
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I2fdd29a4461b250661b1ccaa9737836fc3fe8695
2024-12-06 16:35:46 +01:00
EstherLerouzic
e593b8c9ec fix case where there are multiple multiband amps matching the sub amp type
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ibe86499866f2f9e3dfd70b51a33b919d584b812b
2024-12-06 16:35:46 +01:00
EstherLerouzic
94a6f922cd fix typing
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I0f1621b669b4db833d0760368cd834f3186ee2db
2024-12-06 16:35:46 +01:00
EstherLerouzic
fbe387915b fix: offset was not correctly taken into account on reversed path
TODO: write a test!

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I7ac909bb9b8c9700c3841f133245f17f49ba3467
2024-12-06 16:35:46 +01:00
EstherLerouzic
fce9d1d293 chore: refactor json_io
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: If764ba7b520a060deb855c0b55e17c78fa22f841
2024-12-06 16:35:46 +01:00
EstherLerouzic
a59db8fd12 fix: cli_examples linter issues
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Id7e2f8b7282913b885062a01f1bd018bbc85e39c
2024-12-06 16:35:46 +01:00
EstherLerouzic
de509139b3 fix: linter issues on json_io
add docstrings, typing, small fixes

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I01d0fabe5e34103077ec2de829e96829e6202e1e
2024-12-06 16:35:46 +01:00
EstherLerouzic
bb77b3f4a8 fix: remove unused _automatic_spacing
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ie3c2fc226f8a549622933cbd1ba8a6b8be213f92
2024-12-06 16:35:46 +01:00
EstherLerouzic
34c7fd1b60 fix: save autodesign file after autodesign!
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: If1c82c8cb7ff9dbb8bf5c2d5c4b96beaa59dc402
2024-12-06 16:35:46 +01:00
EstherLerouzic
89a962ffaf fix remove unnecessary else after return
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I61dc58f15c8f03a686437e19a36ac0afe35904e9
2024-12-06 16:35:46 +01:00
EstherLerouzic
1722fbec13 feat: add more warnings on amplifiers
when user settings do not match library

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Id387b7781d9637f1d18c453dae75330962229902
2024-12-06 16:35:46 +01:00
EstherLerouzic
e48aa57c35 Improve error reporting by including uid of elements
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ief4125322e4db02765974c43159a014749cdab2e
2024-12-06 16:35:46 +01:00
EstherLerouzic
e3e37b1986 feat: skip path computation when path is explicit
and add tests for explicit path

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I95aaf5b56a7ea04f24153d5cb6612cd09401401c
2024-12-06 16:35:46 +01:00
EstherLerouzic
abf42afaf8 fix ci: The macOS-12 environment is deprecated
remove this check and add one for The macOS-14 instead

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ief1c990cbc67ec4d7912404c24d67f9f2fa6d96e
2024-12-06 16:35:46 +01:00
EstherLerouzic
310995045e fix: linter issues in convert and service_sheet
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I5f7490ed61b53cea8d2923a8a54d38b3fbb5fa0a
2024-12-06 16:35:43 +01:00
EstherLerouzic
c840bb1a44 Improve test coverage on ila constraint cases
explicitely check the corrections for all cases
ila defined in eqpt or not,
ila defined on the link with same direction as request or not
constraint loose or strict
several or one ila in the OMS

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I4d4b5167e7327c9aea4b13879f4e00d30e60d643
2024-11-25 17:07:36 +01:00
EstherLerouzic
4b6f4af3a5 Refactor to reduce cognitive complexity
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ia9992ebbe06498ed53b3987edd4eb139d960ff75
2024-11-25 17:07:33 +01:00
EstherLerouzic
dc68d38293 fix ila names
auto design were changed long ago and these functions did not
apply the changes. Besides there was a confusion between request_element
class where loose is a string, and PathRequest from topology.requests
where loose_list is a list of strings.
This patch corrects the naming and also the tests,
because it used the wrong class to gererate xls services

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I564b77576459d6cb47767398a2db8138ba6ad1e4
2024-11-25 16:55:25 +01:00
EstherLerouzic
defe3bee5c feat: documentation for ROADM excel sheet input
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ie662015c9cd0a90aff46c63fce47d678ffe1d4db
2024-11-25 12:09:14 +01:00
EstherLerouzic
32adc0fc53 feat: enables reading per degree impairment from xls input
- read per degre roadm-path impairment from roadm sheet
add additional optional columns: type_variety and 'from degrees'
and 'from degree to degree impairment id'
'from degrees' can contain a list of degrees separated with ' | ', then the
'from degree to degree impairment id' must contain a list of ids of the same
length.
Impairment ids are expected to be in the ROADM equipment spec and
from degree must be the previous node (no verification of user input).

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I7d326bb3d4f366835249089e9537747c7d3ec2fd
2024-11-25 12:09:09 +01:00
EstherLerouzic
4796266657 fix bug in roadm to_json: move per_degree_impairments in params
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I75ed610f201608a3cb651e8c0604de444113bc25
2024-11-25 08:55:00 +01:00
EstherLerouzic
c35104c184 Add documentation for multiband
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Iadf6d9edd8c67c1389c4a0d482466a8c52198621
2024-11-21 09:26:51 +01:00
AndreaDAmico
7b1354ee24 fix: avoid using cumtrapz from scipy
cumtrapz has been replaced with cumulative_trapezoid in the scipy version currently required by GNPy.

Change-Id: I6790f7aa8d8e8d171faa48db4b20e6a93141c471
2024-11-15 22:25:27 +00:00
AndreaDAmico
39d3f0f483 Perturbative Raman Solver
Raman effect evaluation based on a perturbative solution for faster computation

Change-Id: Ie6d4ea4d9f95d8755dc8dfd004c954d4c2c5f759
2024-11-08 19:55:20 +00:00
AndreaDAmico
bbe9ef7356 Increasing precision in Raman tests
Change-Id: I7a4de449a673d2e2ac23376d7fe64399c65e1246
2024-11-08 18:12:49 +00:00
AndreaDAmico
42a8f018cd GGN approximation formula defined
An approximated version of the GGN is implemented to reduce the computational time enabling fast multi-band transmission simulations

Change-Id: I2951a878aa04b5eb4a33ba86d626a788c4cbb100
2024-11-08 18:09:44 +00:00
EstherLerouzic
29f5dd1dc4 Add frequency dependency on ROADM impairments
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Icb88bf9c42c09deb0064e3299b78b080462fef79
2024-10-16 17:49:00 +00:00
EstherLerouzic
03da959724 insert multiband_amplifier if needed
the automatic add_missing_elements function is updated to insert
multiband booster, preamp or inline amplifiers based on the OMS
nature. If nothing is stated, then uses Edfas.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I968a2fc0a3da97aecb7b513ff211491b20cdd4f2
2024-10-16 17:47:29 +00:00
EstherLerouzic
f621ca6fe7 Add tilt computation for design targets
Compute the tilts only if raman-flag in sim_params is turned on.
Use actual input power in fiber (according to expected propagation
during design).
Creates a function that computes the expected tilt after propagation
in a span, and returns the normalized power difference at the center
frequency of each band, and the tilt experenced between lower and
upper frequency in each band.
Include the expected tilt when computing target gains of amplifiers.
Current function requires that the bands remain in the same order.
(ordering is ensured when creating the objects).

Change-Id: I28bdf13f2010153175e8b6d199fd8eea15d7b292
2024-10-16 17:46:59 +00:00
EstherLerouzic
24f4503020 Preselect multiband amplifiers based on band gain and power targets
To ensure that the multiband amplifier meets the required gain and
power targets for each band, this commit introduces a preselection
process for the amplifiers type variety. The preselection ensures
that only compatible amplifiers are considered, avoiding that
an amplifier is selected for one band that is not part of the same
multiband amplifier type variety of the amplifier selected for the
other band(s).

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I8de7e0b7c165e6edfe47d7f4cda80db23924a9c9
2024-10-16 17:46:34 +00:00
EstherLerouzic
520c3615e4 Refactor select_edfa
Objective is to reuse the functions that lists suitable type variety candidates
for each amplifier of the multiband amplifier

restrictions are processed before entering select_edfa.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I8c784cef6bfed9a2e95bc39434a32191678db81f
2024-10-16 17:40:29 +00:00
EstherLerouzic
548626a9f2 preselect amplifiers based on restrictions and bands
make sure that selected amplifiers (single or multiband) have a band
that encompasses design_band.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I8b66755efbe8413f32328b9e02099ffdedd4b7ed
2024-10-16 17:40:01 +00:00
EstherLerouzic
7a26833a5a Add some test on select_edfa
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ia54c62fe76175f16048992ca1f67439dd32c6e5e
2024-10-16 17:39:39 +00:00
EstherLerouzic
c2f6f9c6a0 Add an invocation test with multiband case
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I0a98175f0c6b4333fae6bea40dac826032a25233
2024-10-16 17:39:13 +00:00
EstherLerouzic
64a91256fc Propagate power per band during autodesign
Target setting computation is done going through each element of the OMS
and computing resulting delta power after each amplifier element. In order
to account for different delta power per band (multi band autodesign), the
computation must be made per band. The previous introduction of a standard
name for bands ("CBAND", "LBAND") ensures a stable key to index these
delta power computation.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ida4b2486ebde4f2a1fb21a44458d1fe34a788d1f
2024-10-16 17:37:35 +00:00
EstherLerouzic
bdcffc2a5e Refactor: define a separate function to compute targets
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I5698feb059f13b90c1ab3d0843fb000c4e0b6b59
2024-10-16 17:36:52 +00:00
EstherLerouzic
c384af8062 Refactor: create a function to set one single band amplifier
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I00018c38b0cc0ceefcd21d50dd0cdc639019cc70
2024-10-16 17:36:25 +00:00
EstherLerouzic
0813332adc Enable differentiated design band per OMS
Introduce a design_band parameter in ROADM and Transceiver.
- if nothing is defined, use SI band(s)
- if design band is defined in ROADM, use this one for all degrees
- if per degree design band is defined, use this one instead

unsupported case: single band OMS with default multiband design band.
Check that these definitions are consistent with actual amplifiers

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ibea4ce6e72d2b1e96ef8cf4efaf499530d24179c
2024-10-16 17:31:33 +00:00
EstherLerouzic
22fe9ead55 Introduce multi band amps
Introduce a new multi-band element that contains a list of Edfa element:
- reads multiple amps out of the element config.
- deduces frequency band from the amp in the list.

no autodesign yet: multi-band amps must have type_variety.

- checks that type variety of individual EDFAs is consistent with multiband
type variety
- demux and mux spectrum when propagate in multiband
- don't add a preamp or booster if a multiband amp is already defined.

The print of channel number is removed from equipment, since the channel number
may now depend on the path's amplifiers. This changes invocation results layout.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I44e77ff82e622cdee4021a7984d660317cb90cf9
2024-10-16 17:26:11 +00:00
EstherLerouzic
920ac30aa5 Refactor and simplify network functions
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ifa0949a8b7739036639e1a4b006ceb08804558ce
2024-10-16 17:24:52 +00:00
EstherLerouzic
ac8fd770ab Only propagates carriers that belong to Amp bandwidth
The commit introduces mux/demux functions in amps and ensures that the
propagation is only done on carriers that are in the Amp bandwitdh, ie
with all their spectrum including slot width is in bandwidth.

For consistency, default amp f_min is changed:
Objective is to use amplifiers' band to bound the possible frequencies
to be propagated. Since the current default f_min of Amp in json_io.py is
higher than the SI one, this would result in a different nb of channels
than currently used in tests, and a change in all tests. In order to
avoid this, I preferred to change this value and have consistency
between SI f_min and Amp f_min.

The commits adds a set of functions to make amps band the useable
spectrum on each OMS. Thee OMS generation is changed to use the amp band.

The commit adds filtering functions (demux and mux) to filter out spectrum
which is not in the amplifier band.

Spectrum assignment is also corrected to correctly match the amp bandwidth
constraint with guardband: center frequency index must be within the
usable part of the amp band. This changes a bit the notion of freq_index
and guardband in the functions, but this is transparent to user:
f_min, f_max represent the amp band, while self.freq_index_min/max
represent the center frequency boundary for a reference 50GHz channel.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I225b2b2dc0e1f1992c0460f6e08fa9c9bc641edf
2024-10-16 17:16:21 +00:00
EstherLerouzic
5277ae2005 Add a redesign option
redesign True means that network is redesigned using each request
as reference channel. When False it means that the design is made
once and successive propagation use the settings computed with this
design.

Default propogation is without redesign, so that path-request-script
must use the ----redesign-per-request option to behave as before this
commit.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I0084185106d14659a846136620cd17791d551a7d
2024-10-16 17:15:20 +00:00
EstherLerouzic
30ead40e76 Creates a set of functions to be called by CLI and API
Instead of copying the CLI script in API code, use functions shared
by CLI and API

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I3f9b30b8700b68237d0e80768db015d8dec3deb5
2024-10-16 17:13:25 +00:00
EstherLerouzic
ae858b911a fix: capture warning to show the ROADM uid
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ie13bf4c3436a5a0b8ec730698920eee2c7fb81e8
2024-10-16 17:10:34 +00:00
EstherLerouzic
0d236fd31e fix: remove unused invocation test file
Wrongly added by commit #4a071c5

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I337b8d4560cd7f2634fca7d242783da327127de5
2024-10-16 16:42:09 +00:00
EstherLerouzic
9a84e29433 fix: remove freq2wavelength that is already defined
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I8ef480460e689bfcb33116cd393ad92ed0e03338
2024-10-08 11:07:13 +00:00
‘Renato
143f63170e FIX: json indentation in example-data
Change-Id: If3585fc554638cb1e5f7e4564d10af29420b6159
2024-09-20 13:49:26 +00:00
EstherLerouzic
b2d7f883a1 Add documentation for topology, service and sim-params files
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I0d917b742acd91aa52403f1ac96a378bb3cd8497
2024-06-02 19:26:33 +02:00
EstherLerouzic
73dbdf3042 Add documentation for the roadm impairment feature
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ief7e79ef10edf098c49ab1a0164284e5ae604961
2024-06-02 19:26:33 +02:00
EstherLerouzic
4a071c53d7 feat: transform roadm-paths into list indexed with frequency band
to be conformed with ietf + to prepare for next multiband case

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: If71857ef7dff9eaaa4c16e3837d3500bcef2fa72
2024-06-02 19:26:33 +02:00
EstherLerouzic
dcde64a8db clean some leftover from previous refactor
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ibd6e32090155433d7b1aa5b6572f1fe07a4cbe4a
2024-06-02 19:26:33 +02:00
EstherLerouzic
38cc0e3cc5 feat: separate span power from tx power
gnpy currently uses the same parameter for tx output power and span
input power: this prevents from modelling low tx power effect.
This patch introduces a new tx-cannel-power and uses it to
propagate in ROADM.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Id3ac75e2cb617b513bdb38b51a52e05d15af46f5
2024-06-02 19:26:33 +02:00
EstherLerouzic
fb70413784 Refactor equipment and add some tests
This fixes error message for wrong trx type,  catches the case of
KeyError when trx_type is not part of the library.

removes power setting from this function: power out of transceiver or
at the input of span is nor defined in equipment Transceiver

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I15fa7cc772ab5c1a8c7637738eb83c2ddffa1219
2024-06-02 19:26:33 +02:00
EstherLerouzic
87e10c240e Add test on blocking due to PDL penalty
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I2d6a7f9ed0ff8ad6977bcfe1b78ed620bb0e848d
2024-06-02 19:26:33 +02:00
EstherLerouzic
43c1085be6 feat: apply per path_type ROADM OSNR
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I2b0838c9a217a7f918b2cf08c233aacdbf686a72
2024-06-02 19:26:33 +02:00
EstherLerouzic
4ace60bea2 Feat: apply roadm-path loss
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I87e27d5b653bdce814f43e4c9c1183fb51fbcc1e
2024-06-02 19:26:33 +02:00
EstherLerouzic
f950a6aee8 Feat: add detailed ROADM impairments per roadm-path
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I09c55dcff53ffb264609654cde0f1d8b9dc7fe9b
2024-06-02 19:26:33 +02:00
EstherLerouzic
fb4195c775 Feat: Enable multiple type_varieties for ROADM
This commit introduces the 'type_variety' attribute for ROADM elements,
allowing the use of different types of ROADM specifications instead of
being limited to the default one.

If no type variety name is provided in the eqpt_config, the 'default'
name is used for backward compatibility with libraries. Additionally,
if no type variety is defined in the ROADM element in the topology,
the default one is used for backward compatibility with topologies.

The 'type_variety' attribute is included in the 'to_json' and
'display' methods for ROADM elements.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I61a2491f994e47ad0b08cf8eaef30d6d855aa706
2024-06-02 19:26:33 +02:00
EstherLerouzic
29f42666e5 remove whites spaces and align parentheses
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I0f5f389a3cf20155ceb0e9d9f071d1334a5ad688
2024-06-02 19:26:33 +02:00
EstherLerouzic
9bf7f336e3 Update release notes of v2.9
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ib949ff81fa818886a69339117bc66290dc2685b0
2024-06-02 19:26:27 +02:00
EstherLerouzic
eed6564f11 Add power sweep functionality description in documentation
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ic8db566bc168f120ddb0016c91bcc1d24263548c
2024-06-02 19:17:07 +02:00
EstherLerouzic
fbb2f2c587 fix missing to_json export of computed_number_of_channels
The parameter was introduced in commit 9736f7c032
but the export to_json was not added.

In the next commits, it is necessary to compute Raman gain during the design
phase. The sim-params used for this computation are updated during the
design phase for speed reasons. To ensure the proper restoration of user
settings for propagation, the export must include all parameters. Therefore,
this commit adds 'computed_number_of_channels' to the JSON export. This allows
for the accurate recording of all user settings locally and enables their
restoration.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I221a6f614010edea9cf46c3a7d43c5be064ff09c
2024-06-01 19:17:50 +02:00
EstherLerouzic
44040c4d06 fix missing description of computed_number_of_channels
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I5c8d057dcdab535617eee8de3eccdd806cec403e
2024-06-01 09:11:56 +02:00
EstherLerouzic
ee9af69558 Improve doc to state when tilt is vs wavelength
add some text in the docs to explain that tilt can be expressed
vs freq or lambda depending on context:
advanced_model expresses dgt as a function of frequency,
while tilt target is still defined vs wavelength (common usage).

Change the variable to have explicit name when it is per wavelength,
or add a comment to help identifyper wavelength or per frequency
variables.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I7727f00b38244152b95954e981cc9da096bb3d1d
2024-05-24 07:11:02 +00:00
Esther Le Rouzic
ce21609fec Merge "fix: image of the script and documentation" 2024-05-22 14:24:26 +00:00
Esther Le Rouzic
a1289e6a9b Merge "feat: enable different sim_param vectors for multiple requests" 2024-05-22 14:19:35 +00:00
AndreaDAmico
138115e1d7 Frequency scaling description in release notes v2.8
Change-Id: I74f3d52a3cbc087b914ff18075869d2162b693ac
2024-05-16 01:23:27 -04:00
EstherLerouzic
ed41305f55 fix: image of the script and documentation
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ib022320efd36a2d912f7b443686d7fee137e48b1
2024-04-26 18:19:53 +02:00
EstherLerouzic
9736f7c032 feat: enable different sim_param vectors for multiple requests
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ia800a7b98b33b795cc3553500116be61c612e45c
2024-04-26 17:12:43 +02:00
EstherLerouzic
be7ae35db3 Refactor amp default in parameters
default parameters are shared between json and network function,
so it is better to have them on the parameters to avoid circular
dependency when importing modules

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ib9d41852e394586d36f74992c91f67f3330cc552
2024-04-25 17:51:56 +02:00
EstherLerouzic
2b4a4ab72c fix Raman gain estimation during design
- Replaced multiple calls to the span_loss function
  with recording the span loss result in the fiber elements,
  reducing computation time.
- Updated Raman gain estimation based on design target powers to ensure
  accurate Edfa gain calculation or gain reduction during design.
- display the computed and design Raman gain in RamanFiber string output
- do not add padding on Raman fibers
- Added to_json function to preserve user input SimParams values,
  which were previously overwritten by initializing SimParams
  with fake values during design.

Next step is to allow users to balance computation time and
target accuracy of the design by inputing their own SimParams
and ref channels design values.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I1ca4954d0621858cefb3d776a538131992cae3e3
2024-04-12 08:58:16 +02:00
EstherLerouzic
426c88432d fix: update README script animation
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I31381ddf3e372f34836416162c080a5205ef969d
2024-04-12 08:41:27 +02:00
AndreaDAmico
2a800b781f Bug fix: Raman coefficient properly scaled in non SSMF case
Before the Raman coefficient was normalized with respect the given effective area, instead of the reference.

Change-Id: I4c0547db4fbd0f823a9058022b93c1ca37d67b51
2024-04-11 01:21:02 -04:00
Jan Kundrát
8d1d3677ed docs: fix graphs on RTD
At OFC I was talking with the OpenROADM people, and it turned out that
our docs stopped rendering properly at RTD. It turned out that the build
started skipping the bindep.txt file at some (unknown) point in time.

Reported-by: Aparaajitha G L <aparaajitha.gomathinayakamlatha@utdallas.edu>
Change-Id: Ie9a4b61f36fb979fb5c109d02de06e0b2cbf270e
2024-03-29 19:23:08 +01:00
Jan Kundrát
5b6f8c60cf docs: use the default theme on ReadTheDocs.org as well
Historically, we've been using the RTD theme on the RTD site which hosts
the docs for us, and a Sphinx-default, "Alabaster" theme for other docs
builds. Doing that however started failing:

 Traceback (most recent call last):
   File "/home/docs/checkouts/readthedocs.org/user_builds/gnpy/envs/499/lib/python3.12/site-packages/sphinx/builders/html/__init__.py", line 1096, in handle_page
     output = self.templates.render(templatename, ctx)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   File "/home/docs/checkouts/readthedocs.org/user_builds/gnpy/envs/499/lib/python3.12/site-packages/readthedocs_ext/readthedocs.py", line 181, in rtd_render
     content = old_render(template, render_context)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   File "/home/docs/checkouts/readthedocs.org/user_builds/gnpy/envs/499/lib/python3.12/site-packages/sphinx/jinja2glue.py", line 194, in render
     return self.environment.get_template(template).render(context)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   File "/home/docs/checkouts/readthedocs.org/user_builds/gnpy/envs/499/lib/python3.12/site-packages/jinja2/environment.py", line 1301, in render
     self.environment.handle_exception()
   File "/home/docs/checkouts/readthedocs.org/user_builds/gnpy/envs/499/lib/python3.12/site-packages/jinja2/environment.py", line 936, in handle_exception
     raise rewrite_traceback_stack(source=source)
   File "/home/docs/checkouts/readthedocs.org/user_builds/gnpy/envs/499/lib/python3.12/site-packages/sphinx/themes/basic/page.html", line 10, in top-level template code
     {%- extends "layout.html" %}
     ^^^^^^^^^^^^^^^^^^^^^^^^^
   File "/home/docs/checkouts/readthedocs.org/user_builds/gnpy/envs/499/lib/python3.12/site-packages/sphinx/themes/classic/layout.html", line 10, in top-level template code
     {%- extends "basic/layout.html" %}
     ^^^^^^^^^^^^^^^^^^^^^^^^^
   File "/home/docs/checkouts/readthedocs.org/user_builds/gnpy/envs/499/lib/python3.12/site-packages/sphinx/themes/default/../basic/layout.html", line 170, in top-level template code
     {%- block content %}
   File "/home/docs/checkouts/readthedocs.org/user_builds/gnpy/envs/499/lib/python3.12/site-packages/sphinx/themes/default/../basic/layout.html", line 189, in block 'content'
     {%- block sidebar2 %}{{ sidebar() }}{% endblock %}
     ^^^^^^^^^^^^^^^^^^^^^^^^^
   File "/home/docs/checkouts/readthedocs.org/user_builds/gnpy/envs/499/lib/python3.12/site-packages/sphinx/themes/default/../basic/layout.html", line 189, in block 'sidebar2'
     {%- block sidebar2 %}{{ sidebar() }}{% endblock %}
     ^^^^^^^^^^^^^^^^^^^^^^^^^
   File "/home/docs/checkouts/readthedocs.org/user_builds/gnpy/envs/499/lib/python3.12/site-packages/jinja2/sandbox.py", line 393, in call
     return __context.call(__obj, *args, **kwargs)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   File "/home/docs/checkouts/readthedocs.org/user_builds/gnpy/envs/499/lib/python3.12/site-packages/jinja2/runtime.py", line 777, in _invoke
     rv = self._func(*arguments)
          ^^^^^^^^^^^^^^^^^^^^^^
   File "/home/docs/checkouts/readthedocs.org/user_builds/gnpy/envs/499/lib/python3.12/site-packages/sphinx/themes/default/../basic/layout.html", line 63, in template
     {%- include sidebartemplate %}
     ^^^^^^^^^^^^^^^^^^^^^^^^^
   File "/home/docs/checkouts/readthedocs.org/user_builds/gnpy/envs/499/lib/python3.12/site-packages/sphinx/jinja2glue.py", line 215, in get_source
     raise TemplateNotFound(template)
 jinja2.exceptions.TemplateNotFound: about.html

 The above exception was the direct cause of the following exception:

 Traceback (most recent call last):
   File "/home/docs/checkouts/readthedocs.org/user_builds/gnpy/envs/499/lib/python3.12/site-packages/sphinx/cmd/build.py", line 281, in build_main
     app.build(args.force_all, args.filenames)
   File "/home/docs/checkouts/readthedocs.org/user_builds/gnpy/envs/499/lib/python3.12/site-packages/sphinx/application.py", line 347, in build
     self.builder.build_update()
   File "/home/docs/checkouts/readthedocs.org/user_builds/gnpy/envs/499/lib/python3.12/site-packages/sphinx/builders/__init__.py", line 310, in build_update
     self.build(to_build,
   File "/home/docs/checkouts/readthedocs.org/user_builds/gnpy/envs/499/lib/python3.12/site-packages/sphinx/builders/__init__.py", line 376, in build
     self.write(docnames, list(updated_docnames), method)
   File "/home/docs/checkouts/readthedocs.org/user_builds/gnpy/envs/499/lib/python3.12/site-packages/sphinx/builders/__init__.py", line 571, in write
     self._write_serial(sorted(docnames))
   File "/home/docs/checkouts/readthedocs.org/user_builds/gnpy/envs/499/lib/python3.12/site-packages/sphinx/builders/__init__.py", line 581, in _write_serial
     self.write_doc(docname, doctree)
   File "/home/docs/checkouts/readthedocs.org/user_builds/gnpy/envs/499/lib/python3.12/site-packages/sphinx/builders/html/__init__.py", line 672, in write_doc
     self.handle_page(docname, ctx, event_arg=doctree)
   File "/home/docs/checkouts/readthedocs.org/user_builds/gnpy/envs/499/lib/python3.12/site-packages/sphinx/builders/html/__init__.py", line 1103, in handle_page
     raise ThemeError(__("An error happened in rendering the page %s.\nReason: %r") %
 sphinx.errors.ThemeError: An error happened in rendering the page about-project.
 Reason: TemplateNotFound('about.html')

 Theme error:
 An error happened in rendering the page about-project.
 Reason: TemplateNotFound('about.html')

I have no clue what that means because we have never requested this
`about.html`, nor do we reference that file from anywhere. Chances are
that it's "just" some version pinning/compatibility issue, but hey --
why mess with that when there's a perfectly good default theme that
we're using for other purposes already.

As a side effect, this also solves that long-standing issue that Esther
reported where the tables have overly long lines. Apparently, it's a
theme-specific misfeature (readthedocs/sphinx_rtd_theme/#117), and the
Alabaster one doesn't suffer from that.

All hail alabaster!

Change-Id: I857890f29f14b7c0f66bca201c9a9c1b1cbf8841
2024-03-13 21:30:20 +01:00
Jan Kundrát
3a733b1fd5 docs: try to unbreak the readthedocs.io build
It was failing with a message:

  Config validation error in build.os. Value os not found.

Apparently, the v2 config file is mandatory, so let's do that.

Change-Id: I267d5314db026de532b2b6644f500d25de08e343
2024-03-13 21:30:20 +01:00
Jan Kundrát
2d68b94a46 build: specify dependencies directly in setup.cfg
In tox v4, "reuse of environments" was disabled [1]. This is then later
explained [2] to refer to exactly that thing which we were using for
inheriting the dependencies from the top-level testenv all the way to
the docs build. That's why the docs build in GitHub CI started failing.

IMHO, The Correct Way™ of specifying what dependencies are used for
which feature are the so-called "extra dependencies". Once they are in
place, it is be possible to install gnpy via, e.g., `pip install
oopt-gnpy[docs]`. However, this process is (as far as I can tell)
incompatible with `requirements.txt`; all my attempts at using the
standard dependency syntax in that file have failed for me.

So, in order to make this happen, let's move all the dependencies from a
more-or-less ad-hoc collection of files to this declarative approach
right in setup.cfg. That way, the deps are listed on a single place, in
a declarative manner, and as a result, the installation is now a trivial
pip oneliner.

As a result, one can also remove that duplication of dependencies in
docs requirements.

[1] https://tox.wiki/en/4.11.4/upgrading.html#reuse-of-environments
[2] https://tox.wiki/en/4.11.4/upgrading.html#packaging-configuration-and-inheritance

Change-Id: I34aa0c71e993b39e2b805a7de40e133b4d290318
Fixes: 47c89626 fix docs requirements
2024-03-13 21:28:01 +01:00
EstherLerouzic
bc71823bd0 docs: add a release-note section and update documentation for penalties and SI
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I12a5747df3cee6df79c24dd6261f7be17aa77fcf
2024-02-09 18:59:40 +01:00
EstherLerouzic
5481b93728 Fix frequency scaling for fiber
- wrong parameter was used in parameter
- error message could not read 0-dimensional arrey for 0 and -1 element
- add a test that makes use of the feature

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Id7f6d6766d5b91a4b9410ad23aaa5e472b8ebb6f
2024-01-16 09:10:31 +00:00
EstherLerouzic
05e301182d Change fedora-python in action
"Until version 0.4, this action always used the
latest fedora-python-tox image"
https://github.com/fedora-python/tox-github-action

So let's use one that supports python 3.8

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ibf3e0baa715da70b4c2af6e2cde6efccfab50311
2024-01-15 20:02:13 +01:00
EstherLerouzic
47c89626e3 fix docs requirements
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I9d151b842a38380b0368e099c67957ec36b78250
2024-01-15 13:53:44 +01:00
EstherLerouzic
7a032a63b5 ci change allow_whitelist which is deprecated
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ic62050d351eb5bb2f8be2b8d9e0088bd965dc71d
2024-01-15 13:12:35 +01:00
EstherLerouzic
f195d5f496 fix: use ref power on transceiver to Roadm (or transceivers) links
The recent refactor removed a default pref in case of transceivers-OMS
(amplified links starting with a transceiver).
This resulted in a mismatch between input power during design
(default 0 forced in the function) and the design ref power using SI
power_dbm.

This change ensures that the same power is used for the input power
and for the design ref power, and avoid inconsistent gain computatiion.

The code has been using the same power input (SI power_dbm) to define the
power target out of a transceiver and the target out of amplifiers
(at the input of fibers). This will be changed in a future patch.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I610c8df19039bcf156a8ba77c79114b22913a538
2023-12-08 12:27:05 +01:00
Esther Le Rouzic
56569f866f Merge changes from topics "mixed-rate", "refactor_remove_pref"
* changes:
  Add a test on EOL
  add invocation test with the 3 equalization settings
  Add a test on out_voa optimisation function
  Clean a bit, add docstrings
  Remove Pref, and move ref_carrier definition
  Remove p_span0 from SI
  Remove p_spani from Pref
  Use design delta_p and gains instead of p_spani
  restore initial power sweep behaviour
  refactor cli to use a common design function
  Parametrize verbose in autodesign
  refactor build_network: create a separate function to add elements
  Computes reference input power in fiber during design
  Computes reference input power in ROADM during design
  Add a variable to hold delta_p even if gain mode is selected
  Add frequency range in default_edfa profile
  Add a test on gain mode behaviour
  Check element setting before and after propagation
  Correct design: apply saturation in all cases
  Add more tests on amp saturation
2023-12-04 16:09:37 +00:00
Esther Le Rouzic
bf1f293043 Merge "Add test in amplifier behaviour" 2023-12-04 16:08:14 +00:00
Esther Le Rouzic
28871c6f2d Merge pull request #480 from jktjkt/python-3.12
CI: Python 3.12 and extended platform coverage
2023-11-23 17:54:02 +01:00
EstherLerouzic
d7c1a6b75e Add a test on EOL
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Iddce655a64623a42cdaeaa2e8c269e3a737dd935
2023-11-20 17:07:53 +01:00
EstherLerouzic
c69c2a3af2 add invocation test with the 3 equalization settings
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I0aee8da7bbf71991c68e163c7188efe1ddf29ff9
2023-11-20 17:07:53 +01:00
EstherLerouzic
fb29d72906 Add a test on out_voa optimisation function
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I36d71d85e5837965f6d5ae47820506d06b3cb94e
2023-11-20 17:07:53 +01:00
EstherLerouzic
30a06da6b1 Clean a bit, add docstrings
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I8639d458ebb090761846387921f9da4fc65a9f64
2023-11-20 17:07:53 +01:00
EstherLerouzic
139c8cc1e7 Remove Pref, and move ref_carrier definition
Finally, ref_carrier is not meant to change after design since
it is the carrier used for design. So let's move its definition
to networks function. Only ROADM need the ref_carrier baud rate
so let's define a dedicated variable in ROADM to hold it.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ida7e42dd534a04c8df8792b44980f3fd2165ecb6
2023-11-20 17:07:53 +01:00
EstherLerouzic
7034d4c686 Remove p_span0 from SI
reference channel is defined during design. No need to convey it
anymore during propagation.

move target_pch_out_db definition to the design phase and change
its name to be consistent with what it contains (dbm)

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I350e4557e8488a614674042de26152ab89b2d245
2023-11-20 17:07:53 +01:00
EstherLerouzic
10164495b9 Remove p_spani from Pref
next step: remove Pref

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I7cc17253a2d7ab3fb42e3d07c1665991cffa6222
2023-11-20 17:07:53 +01:00
EstherLerouzic
87211b35e9 Use design delta_p and gains instead of p_spani
Remove the visualisation of the effective_pch in amp because actual
and target are the relevant ones. effective_pch was artificially
related to a mix of reference channel and noisy channel (mixed between
on the fly redesign but using actual ROADM equalisation which includes noise
in its actual loss).

the change does no more rely on the target power (which is rounded)
but on the designed gain, which is not rounded.

Propagations are slightly changed for openroadm simulations because of that.
(I verified)

The gain of amp was estimated on the fly with p_spni also in case of
RamanFiber preceding elements. removing p_spani requies that an estimation
of Raman gain be done during design.

This commit also adds this estimation.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I960b85e99f85a7d168ac5349e325c4928fa5673b
2023-11-20 17:07:46 +01:00
EstherLerouzic
e9f9ddb4d6 restore initial power sweep behaviour
if user define a delta_p that is reduced because of saturation,
then this initial setting is still kept for power sweep to be sure
that the full amplitude of sweep is used.

SI power = 0 dBm
max power amp1 = 20 dBm,
user_defined_delta_p set by user = 3
80 channels, so pch_max = 20 - 10log10(80) = 0.96 dBm
power_sweep -> power range [-3, 0] dBm

then for initial design,
   pref = 0 dBm
   computed_delta_p =
      min(pch_max, pref + user_defined_delta_p) - pref = 0.96

but for -3 power sweep
   pref = -3 dBm
   computed_delta_p =
      min(pch_max, pref + user_defined_delta_p) - pref =
      min(0.96,    -3 + 3) - (-3) = 3
   so the user defined delta_p is applied as much as possible

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I8fd459c29aa9754ff9d4868af1d8be8642a31913
2023-11-20 11:10:07 +01:00
EstherLerouzic
8ea13bb4d6 refactor cli to use a common design function
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I029d8c7fc29b1e86e1e3b2b64933bae5da134226
2023-11-20 10:27:43 +01:00
EstherLerouzic
b45829d2df Parametrize verbose in autodesign
transmission-main-example and path-request-run functions implement an
on-the-fly redesign based on p_span_i.
Since we remove p_span_i from elements, we will need to properly call
redesign several times before each propagation, to keep the same
behaviour of these functions.

in this commit we simply enable the possibility to mute warnings.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I3aa3d8fc87325033ef69641078bdd7213e0409eb
2023-11-20 10:27:41 +01:00
EstherLerouzic
6ac3a517cf refactor build_network: create a separate function to add elements
separate function that adds element, from function that configure them

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ica332223bdf7fc599cb007d7513d7cd62d9c5f9c
2023-11-20 10:25:07 +01:00
EstherLerouzic
2f2920a716 Computes reference input power in fiber during design
input power is computed at design time: so let's record it and
use it instead of p_span_i for reference channel fiber loss computation.
Note that this loss parameter is only used for visualisation purpose.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I16bd792bd6079ce521aafadcf5e21922aa3b4c81
2023-11-20 10:23:21 +01:00
EstherLerouzic
07fd89351b Computes reference input power in ROADM during design
input power is computed at design time: so let's record it and
use it instead of p_span_i for ROADM reference channel loss computation.
Note that this loss parameter is only used for visualisation purpose.
No impact on propagation.

Since this loss is computed for the reference channel used for
design, we need to record input power based on input degrees,
and indicate this information within the call function.

Note that this will be also usefull later on to implement ROADM
parameters

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I64d510fc20df72f07158f400964d592d76dc0ce4
2023-11-20 10:23:21 +01:00
EstherLerouzic
7c60b000b5 Add a variable to hold delta_p even if gain mode is selected
Let's use a clean convention to hold values that are configured,
autodesigned or resulting from propagation.

- edfa.operational.delta_p: holds the value set by the user if any.
  This is needed in case of redesign for power sweep for example.
  It is never changed.
- edfa.delta_p:
  o if power_mode is true, records the value computed by the design.
      Applies user defined value except:
      If the user has set non possible values (eg leading to saturation),
      then the value is corrected at design phase.
      If the element is propagated for different conditions than
      design, for example leading to saturation,  then delta_p might be
      different than the value initially computed during design.
  o if power_mode is False, it is set to None
- edfa._delta_p: records the value computed during design whatever
  the power mode

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I4e130a3abe0a5e3f6c057d89360e50531c168123
2023-11-20 10:23:21 +01:00
EstherLerouzic
537eb017b5 Add frequency range in default_edfa profile
This range is the property of amps and is independant from user propagation range.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ib89f1987910aa3121a3b8c859a0a785f7d5e27eb
2023-11-20 10:23:21 +01:00
EstherLerouzic
9c514e8086 Add a test on gain mode behaviour
This test checks that setting in gain mode forces amp to the gain settings
and ignores any power requirements. Change in SI in eqpt config and change
in req power (eg power sweep) should have no effect on the propagation.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Iad826f30010fe3110d105b5206d99f502fbf98ff
2023-11-20 10:23:21 +01:00
EstherLerouzic
78efb6c650 Check element setting before and after propagation
In power mode, all elements design attributes should not change except
amplifiers' gain in case of power saturation.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I2fec00232c80dd395e4dec20ec531c9c2e127760
2023-11-20 10:23:18 +01:00
EstherLerouzic
3510d59250 Correct design: apply saturation in all cases
Previously saturation was not checked during design if amp type was set.
This commit also applies saturation for these amplifiers.

This changes some of the autodesign result (since range for selection
is changed). For example, this changes some of the gains, or type variety
of amplifier of test files.

The commit also removes one of the rounding in the design phase, and
applies rounding only for printing purpose.

It also adds minor refactor on a function

In order to keep power sweep behaviour in case of saturation, the saturation
check in amplifier element uses initial power targets set by user instead
of a possible autodesign delta_p result.

Note that gain_mode is unchanged: design in gain mode means that delta_p
is set to None during the build process, even if the user defined a value
in operational.delta_p.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Idc5cfc8263cf678473acb6ec490207d9d6ba5c0a
2023-11-20 10:21:38 +01:00
EstherLerouzic
41d9d156a6 Add more tests on amp saturation
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ibba18bed646748d59cfe906b403a9b100c58bb7e
2023-11-20 10:21:35 +01:00
EstherLerouzic
e9d5e748e4 Add test in amplifier behaviour
Check that amp correctly applies saturation, when there is tilt.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I3e7623e9d5b28bdc12eae24766588645781c2827
2023-11-20 10:21:06 +01:00
EstherLerouzic
5a5bed56c2 Add test on _check_one_request function
Add the call to the function, and creates additional test cases to raise the
different situations related to spectrum slots:
- M value too small
- total nb of channels too small
- overlapping

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I7ab3923deef2ff154ee1be21dcaeb3d9e4b84375
2023-11-17 16:26:12 +01:00
EstherLerouzic
22de1b1281 Add tests on aggregation
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I5409d847657fbe14f7963ff56546d0bedbf6c941
2023-11-17 16:26:12 +01:00
EstherLerouzic
73e1485b47 aggregate demands with defined mode and spectrum
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Id9fc2e0fe6f6ff5a3996700f6db7dfa6222dc3ca
2023-11-17 16:26:12 +01:00
EstherLerouzic
22ee05ea6f Add more tests for multiple slots spectrum assignment
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Id773f0f14cfe80b7ebcf07370170ad425faf0919
2023-11-17 16:23:48 +01:00
EstherLerouzic
31824f318d Enable multiple slots assignment
list of slot may include (N, M) values such as
(int, uint>0)
(int, None)
(None, uint>0)
(None, None)

Demands will be splitted into requested slots according to first fit strategy.
For example, if request is for 32 slots corresponding to 8 x 4slots 32Gbauds
channels, the following frequency slots will result in the following
assignments:
example 1
N = 0, 8,    16, 32           -> 0,   8,   16,   32
M = 8, None, 8,  None         -> 8,   8,    8,    8
example 2
N = 0,    8,    16, 32        -> 0,   , 16
M = None, None, 8,  None      -> 24,  , 8

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ice9bb4b5700d23bcf30db25aa4882e74853169ac
2023-11-17 16:23:48 +01:00
EstherLerouzic
b0cb604e91 Remove old commented code
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Idd2fcca0fe757eb801ab575953828c6df0521bb4
2023-11-17 16:23:48 +01:00
EstherLerouzic
79102e283a Refactor function to simplify the process
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I362d23a969c338ccd70caecc4e59e991d2a8d8a2
2023-11-17 16:23:48 +01:00
EstherLerouzic
db5e63d51b Refactor spectrum selection function
Cut some functions into smaller pieces to be easily re-used afterwards.
This step to prepare multiple slots assignment.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: If0fa2df7f6174e54405f92a57d60289d560c1166
2023-11-17 16:23:48 +01:00
EstherLerouzic
af42699133 Enable the loading of a bitmap
OMS are currently built with a brand new spectrum bitmap using f_min, f_max,
guard band and grid values. This changes enables to load an existing bitmap.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: If0547bc337c863a3510ad9e43928e6f64701d295
2023-11-17 16:23:48 +01:00
EstherLerouzic
4ba77d0a0a Change rq.N and rq.M from scalar to list
Prepare for the next step, to be able to handle lists of candidate assignment

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I2bd78606ce4502f68efb60f85892df5f76d52bb5
2023-11-17 16:23:48 +01:00
EstherLerouzic
064d3af8e0 Remove line number from invocation logs
line numbers are useful for debugging, but the benefit does not
compensate for the painful update of lines in files at each commit
that changes line numbers.
So I have removed those lines only for the test_invocation logs case.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ic1f628d80b204a9a098f3902ebdfd10b480c7613
2023-11-17 11:56:06 +01:00
AndreaDAmico
4ab5bac45f EDFA Parameters restructuring
The parameters of the EDFA are explicitely retrieved in the EDFAParams class.
All the defaults are set instead in the gnpy.tool.json_io.AMP class.
Where required, the AMP.default_values are used instead of an empty dictionary.

Change-Id: Iba80a6a56bc89feb7e959b54b9bd424ec9b0bf06
Co-authored-by: Vittorio Gatto <vittoriogatto98@gmail.com>
2023-11-17 09:08:00 +01:00
AndreaDAmico
bbe5fb7821 Chromatic Dispersion scaling along frequency
The chromatic dispersion and dispersion slope can be provided as a single values evaluated at the fiber reference frequency or in a dictionary containing the dispersion values evaluated at multiple frequencies:
"dispersion": {"value": [], "frequency": []}

Change-Id: I81429484dd373cc49bd9baf013247782ba1912fd
2023-11-17 09:04:44 +01:00
AndreaDAmico
edf1eec072 Nonlinear coefficient scaling along frequency
The nonlinear coefficient can be expressed at the reference frequency and will be scaled in frequency using the scaling rule of the effective area

Change-Id: Id103b227472702776bda17ab0a2a120ecfbf7473
2023-11-17 08:53:58 +01:00
AndreaDAmico
88ac41f721 Seprating the eta matrix evaluation in compute nli
The evaluation of the eta matrix is reintroduced for nli evaluation and validation purposes. Also, the parameters for cut and pump are separated explicitelly.

Change-Id: Id3844fa8ba41a5d4f5a72d281d758136ee983f45
2023-11-17 08:51:35 +01:00
AndreaDAmico
c20e6fb320 Effective Area and Raman Gain Coefficient Scaling
1. Effective area scaling along frequency is implemented by means of a technological model.
2. Raman gain coefficient is extended coherently, including the scaling due to the pump frequency.

Change-Id: I4e8b79697500ef0f73ba2f969713d9bdb3e9949c
Co-authored-by: Giacomo Borraccini <giacomo.borraccini@polito.it>
2023-11-17 08:51:26 +01:00
Jan Kundrát
05500c7047 CI: run tests on Apple M1 CPUs as well (64bit ARM)
Note that on GitHub, this currently targets a "runner" that's behind a
paywall. TIP does have a payment setup in place AFAICT, so we make sure
that this job does not run on forks.

Change-Id: I50c556424d86a1ce47e59911b9e39f336df34ce5
2023-11-15 20:37:26 +01:00
Jan Kundrát
86a39f4b5e packaging: mark Python 3.12 as supported
Change-Id: If3c8ea7d5a7651b71379a71e5dfde6b464aa5b4a
2023-11-15 20:06:55 +01:00
Jan Kundrát
2b25609255 CI: test on Python 3.12 and some new platforms
Change-Id: Ice5c3ca21245c4ac87cb2bf4f0fd062596615a2e
2023-11-15 20:06:55 +01:00
Jan Kundrát
7e0b95bcfd Bump all dependencies
Change-Id: Id08b7722880b992b1bb70f53ad243d4f40ffe387
2023-11-15 20:06:54 +01:00
Jan Kundrát
f0a52dcc8a tests: upgrade pandas
There are no binary wheels for Python 3.12 prior to pandas v2.1.1. Our
previous pin requested the 1.x branch, and that resulted in building
Pandas from source, which takes time. We cannot pin to 2.1.1 because
they removed support of Python 3.8 in 2.1, so 2.0.3 it is.

Change-Id: Ia9a567e54f4dda19a0a6b67d0c295a9a079892de
2023-11-15 20:05:54 +01:00
EstherLerouzic
3bea4b3c9f Feat: improve sanity check for eqpt sheet
add cases of wrong sheets that were not captured and
generate errors later in propagation:
- if the eqpt line is duplicated
- if the eqpt contains a link that is not present in Links sheet,
  but Nodes are OK
- if the same link is defined but with opposite directions
- if the ila is defined twice with opposite directions
- if the service type or mode are not in the library

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I4715886e19f07380bf02ed0e664559972bb39b71
2023-11-02 10:14:03 +01:00
EstherLerouzic
f2cc9f7225 Add more logs
and test them

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I05ffc3a75354fa8d8f3a668973ab7f4cbcfa1a98
2023-11-02 10:01:38 +01:00
Esther Le Rouzic
e79f9f51b6 Merge "Feat: add offset power option for transceivers" 2023-10-31 08:30:13 +00:00
Esther Le Rouzic
7fd7f94efe Merge "Refactor error message" 2023-10-31 08:29:58 +00:00
Esther Le Rouzic
0acdf9d9f6 Merge "docs: rename the Matrix channel" 2023-10-27 15:09:16 +00:00
EstherLerouzic
a3edb20142 Feat: add offset power option for transceivers
Offset power is used for equalization purpose to correct for the
generic equalization target set in ROADM for this particular transceiver.
This is usefull to handle exception to the general equalization rule.
For example in the case of constant power equalization, the user might
want to apply particular power offsets unrelated to slot width or baudrate.
or in constant PSW, the user might want to have a given mode equalized for
a different value than the one computed based on the request bandwidth.

For example consider that a transceiver mode is meant to be equalized with
75 GHz whatever the spacing specified in request. then the user may specify
2 flavours depending on used spacing:

  service 1 : mode 3, spacing 75GHz
  service 2 : mode 4, spacing 87.5Ghz
avec
  {
    "format": "mode 3",
    "baud_rate": 64e9,
    "OSNR": 18,
    "bit_rate": 200e9,
    "roll_off": 0.15,
    "tx_osnr": 40,
    "min_spacing": 75e9,
    "cost": 1
  }

  {
    "format": "mode 4",
    "baud_rate": 64e9,
    "OSNR": 18,
    "bit_rate": 200e9,
    "roll_off": 0.15,
    "tx_osnr": 40,
    "min_spacing": 87.5e9,
    "equalization_offset_db": -0.67,
    "cost": 1
  }

then the same target power would be considered for mode3 and mode4
despite using a different slot width

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I437f75c42f257b88b24207260ef9ec9b1ab7066e
2023-10-24 13:20:00 +02:00
EstherLerouzic
33cc11b85c Refactor error message
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ie8fc6bedcdbce26e2e80759c6c56d2c7429bf560
2023-10-24 13:20:00 +02:00
Jan Kundrát
5d079ab261 docs: rename the Matrix channel
It seems that the Matrix server at `foss.wtf` disappeared some time ago
with no details posted anywhere. I've marked the long-existing channel
alias `#oopt-gnpy:matrix.org` as the primary one, so let's adjust the
docs so that new people can actually join this channel.

This should have no consequences on people who have already joined.

Change-Id: Idee9c050ff5cb1c3926e5d4cf751002ad1541e71
2023-10-03 01:50:11 +02:00
AndreaDAmico
a3b1157e38 Fiber latency calculation
Fiber latency evaluated during propagation. The speed of ligth in fiber is evaluated as the vacuum speed of ligth  divided by the core reflective index n1.
The latency in the transceiver is evaluated in ms.

Change-Id: I7a3638c49f346aecaf1d4897cecf96d345fdb26c
2023-08-07 18:29:03 +02:00
AndreaDAmico
70731b64d6 fix: include position of lumped losses in Raman profile
In the previous version, the position of the lumped losses were not
included in the result Raman profile. As the latter is then used to
evaluate the NLI, including the lumped loss positions is required for
accurate estimations.

Change-Id: I683f48ceb7139d1a8be03d2e7ca7e3abffecbe85
2023-07-24 17:13:15 +02:00
AndreaDAmico
4ea0180caf tests: prefer pandas.read_csv over numpy.genfromtext
Change-Id: Icc9618afc4cad0c7a07f3a785c99b6b438e0c6cc
2023-07-24 17:12:25 +02:00
AndreaDAmico
eb2363a3d4 Fix: lumped losses included in total fiber loss
In previous version, the lumped losses where not included in the fiber loss, creating an inaccurate overall power balance.

Change-Id: I98a4d37b9cc0526218fe3c6f2b9318b6fa797901
2023-07-06 15:19:07 +02:00
EstherLerouzic
41b94cc888 fix: don't crash if PMD, PDL or CD penalties are missing in transceivers
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Iafc248af3ecfcd4da4c1135fd3a37da796cdfb5f
2023-05-09 10:11:26 +02:00
Jan Kundrát
1eeb6a0583 Merge changes Icd0b4fbd,I3ca81bcd,Ia33315f0
* changes:
  docs: docstring formatting
  SimParams: less boilerplate
  python: prefer isinstance(foo, Bar) over type(foo) == Bar
2023-04-18 23:01:30 +00:00
Jan Kundrát
215c20e245 Merge "fix: add missing PSW case for power computation" 2023-04-18 00:41:45 +00:00
Jan Kundrát
76e9146043 docs: docstring formatting
Let's use the pythonic indenting, quoting and structure in general as
specified in PEP 0257.

Change-Id: Icd0b4fbd94dabd9a163ae3f6887b236e76c486ab
2023-04-18 01:34:19 +02:00
Jan Kundrát
2a07eec966 SimParams: less boilerplate
The code look as if it was trying to prevent direct instantiation of the
SimParams class. However, instance *creation* in Python is actually
handled via `__new__` which was not overridden. In addition, the
`get()` accessor was invoking `SimParams.__new__()` directly, which
meant that this class was instantiated each time it was needed.

Let's cut the boilerplate by getting rid of the extra step and just use
the regular constructor.

This patch doesn't change anything in actual observable behavior. I
still do not like this implicit singleton design pattern, but nuking
that will have to wait until some other time.

Change-Id: I3ca81bcd0042e91b4f6b7581879922611f18febe
2023-04-17 23:06:31 +02:00
Jan Kundrát
cc994bf118 python: prefer isinstance(foo, Bar) over type(foo) == Bar
Use of isinstance() is more Python and it also allows inheritance to
work properly.

Change-Id: Ia33315f0e3faf6638334bec85d0fa92ea8ac81f0
2023-04-17 23:02:51 +02:00
EstherLerouzic
37e70e622c fix: add missing PSW case for power computation
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I5fa9135cdde1735ec142bc88d8fdf0aa03b13a41
2023-04-13 16:48:21 +02:00
Florian FRANK
7d9a508955 Fix 2 minor typos in docs/model.rst
Signed-off-by: Florian FRANK <florian1.frank@orange.com>
Change-Id: Ic2160f554b120b011c941aca36b69a0f032cf45f
2023-04-13 09:33:19 +02:00
Florian FRANK
185adabd77 Fix bug of comparison dimension when Raman is allowed and loss_coef is a vector instead of a scalar
Signed-off-by: Florian FRANK <florian1.frank@orange.com>
Change-Id: I0b39d102b9200ec25ed62e6f53b1e0addcc66f67
2023-04-11 17:30:24 +02:00
Jan Kundrát
8f9cf8ccc7 docs: sync the author list from git history
I don't have a script for this because it requires some manual fixups.

Change-Id: I19f36b953c98d6bc0c09040c27b964b288360c0e
2023-03-06 01:31:41 +01:00
Sami Alavi
0c797a254c simplify type annotations
PEP 484 says that `float` also implicitly allows `int`, so there's no
need to use `Union[int | float]`.

Fixes: #450
Change-Id: Ib1aeda4c13ffabd47719c1e0886e9ebcf21a64e0
2023-03-03 21:12:57 +05:00
Jan Kundrát
2cdeeabfa6 Mark Python 3.11 as supported
Change-Id: I2dedd942c92959e1f891194f6234376b9ecad6e5
2023-03-02 14:28:12 +01:00
Jan Kundrát
5e874798cb CI: GitHub: add builds on 3.11
...and also switch various jobs to use that by default.

Change-Id: I9170fc305bfd9bea6b5dde5741f912c6ed455e3e
2023-03-02 14:28:12 +01:00
Jan Kundrát
ff8f044064 Merge changes from topic "mixed-rate"
* changes:
  complete tests with the --power option tests
  Add Roadm uid when raising error
  add equalization per constant ratio power/slot_width
2023-02-14 09:59:20 +00:00
Jan Kundrát
d84ee4e76c Merge "doc: add a link to our public chat room" 2023-02-07 17:09:15 +00:00
Jan Kundrát
521d27ffac docs: fix a nasty typo
Fixes: b1067a62 docs: flexgrid
Change-Id: I44613d8ef4a27e7791db81509a56efa7ee29b4ff
2023-02-07 00:36:14 +01:00
Jan Kundrát
35e759212e doc: add a link to our public chat room
Change-Id: Id5323ad01ff0705efb9c9335e2c1f61227e5b73b
2023-02-02 17:29:19 +01:00
Jan Kundrát
f6dede2b5f docs: remove LGTM.com code-quality badge
...which no longer works since they got acquired by GitHub. Setting up
that CodeQL will need a bit more time I'm afraid.

Change-Id: I2f2bf21d31df643b25e931b2aadf60406bba683b
2023-02-02 17:28:40 +01:00
Jan Kundrát
0d0019f627 Update my e-mail address
I was informed that my TIP-specific e-mail address won't be coming back.

Change-Id: Ic2ee4986203490d90143a89dc49d7fca71a84c73
2023-02-02 17:13:23 +01:00
EstherLerouzic
06fe1c2f63 complete tests with the --power option tests
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ia7be6b86b82cc0317a5ba48086ef63f67d490990
2023-01-30 18:05:41 +01:00
EstherLerouzic
092316a9d7 Add Roadm uid when raising error
in case parameters are not correct, catch the ParameterError
and raises it again with the uid of the ROADM to ease debug

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I1f85f0e9e9226fc613d35611774c739adb2104c7
2023-01-30 18:05:37 +01:00
EstherLerouzic
48e3f96967 add equalization per constant ratio power/slot_width
Constant power per slot_width uses the slot width instead of
baud rate compared to PSD.

This is the equalization used in OpenROADM

add tests for constant power per slot width equalization

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ie350e4c15cb6b54c15e418556fe33e72486cb134
2023-01-30 18:03:58 +01:00
Jan Kundrát
e9e8956caf docs: fix the GitHub CI (actions) badge
Bug: https://github.com/badges/shields/issues/8671
Change-Id: I9cb15b762710cae7c3c37ed95d08aee2ca7b2457
2023-01-18 22:57:17 +01:00
Jan Kundrát
0ae341c2a5 tests: update to flake8 v5
flake8-html is now compatible with the v5 of this package, so let's use
it. Unfortunately, they killed the `--diff` option in v6, so we cannot
use it right now. I understand the reasoning as well as the fact that
it's easy to be broken, but I don't like broken CI that much.

Change-Id: I70dd686e097f411c39bfc53f83d519540687dd64
2023-01-18 22:25:48 +01:00
Jan Kundrát
0c2f6372f8 tests: switch to PEP517-compliant build process
...mainly to be in sync with oopt-gnpy-libyang that I've been working on
recently, and to allow us to modernize this infrastructure later on.

Change-Id: Id0ed1d7620762fc204300ebe8a190de8e42ae9df
2023-01-18 22:20:39 +01:00
Jan Kundrát
97e80b4445 Merge changes from topic "enable-multiple-slots-assignment"
* changes:
  record request_id as string, not integer
  support missing trx_mode in request instead of null value
2023-01-18 21:20:03 +00:00
Jan Kundrát
5e4c9b7d73 Merge "Respect fiber max_length when splitting fibers" 2023-01-18 21:19:39 +00:00
Jan Kundrát
e96f821cce CI: Switch to Fedora 36
...because Vexxhost pulled the plug on the F35 mirroring infrastructure,
and as a result, all jobs started failing.

Change-Id: Ib5d795397e907de3eff6cdb9c4145353400793ab
Depends-on: https://review.gerrithub.io/c/Telecominfraproject/oopt-zuul-jobs/+/548583
2023-01-18 21:35:08 +01:00
Jan Kundrát
5f7e61e255 CI: temporarily remove Fedora 35 jobs
...since the hosting provider pulled the plug on the mirroring
infrastructure. See the rest of these commits in this serie for
details.

Change-Id: Iac1d5f1c6f557458194deafe441564afc4851d94
2023-01-18 21:32:11 +01:00
Jonas Mårtensson
682b5c5691 Respect fiber max_length when splitting fibers
According to the documentation, auto-design will
"Split fiber lengths > max_length", which also makes sense based on the
name of the parameter but with the existing implementation fiber
length could still be longer than max_length after splitting. This
patch makes auto-design respect the specified max_length.

Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
Change-Id: Ifd83aa4d77206bf10796579df73632fe405e2d54
2023-01-18 11:59:06 +00:00
Jan Kundrát
11e5117505 tests: do not compare floating point numbers for equality
GitHub CI started failing with the following error:

  assert (watt2dbm(si.signal) == target - correction).all()
  assert False
   +  where False = <built-in method all of numpy.ndarray object at 0x7f01c0ca94d0>()
   +    where <built-in method all of numpy.ndarray object at 0x7f01c0ca94d0> = array([-25.5, -24.5, -22.5, -25. , -27.5]) == array([-25.5, -24.5, -22.5, -25. , -27.5])
        +array([-25.5, -24.5, -22.5, -25. , -27.5])
        -array([-25.5, -24.5, -22.5, -25. , -27.5])
        Full diff:
          array([-25.5, -24.5, -22.5, -25. , -27.5]).all

This is with code which has passed in the Zuul/Vexxhost CI.

It looks very similar to a regression that hit numpy 1.24.0, but the
GitHub action log shows that this happens with numpy 1.24.1. Weird, and
I'm not getting these differences locally, and also not on an ARM64
cloud VM.

Anyway, comparing floating point numbers for strict equality is futile,
so let's use this opportunity to use a proper check for these.

Change-Id: I05683f3116cad78d067bddde2780fe25b5caf768
2023-01-18 00:27:53 +01:00
EstherLerouzic
50603420fc ROADM: rework equalization
On a ROADM, the code would previously set the same per-carrier power
regardless of the channel spectrum width. With this patch, carriers are
equalized either by their:

- absolute power (same as before),
- power spectral density (PSD).

Also, it's possible to apply a per-channel power offset (in dB) which
will be applied to a specified channel on top of the selected
power-level or PSD strategy. The same offset can be also selected
through the `--spectrum` option via the `default_pdb` parameter.

The equalization policy can be set via the ROADM model (in the equipment
config) as well as on a per-instance basis.

The PSD is defined as the absolute power over a spectral bandwidth,
where the spectral bandwidth corresponds to the actual spectrum
occupation (without any applicable guard bands), as approximated by the
symbol rate. PSD is specified in mW/GHz. As an example, for a 32 GBaud
signal at 0.01 mW, the PSD is 0.01/32 = 3.125e-4 mW/GHz.

This has some implications on the power sweep and ROADM behavior. Same
as previously (with absolute power targets), the ROADM design determines
the power set points. Target power is usually the best (highest) power
that can be supported by the ROADMs, especially the Add/Drop and express
stages' losses, with the goal to maximize the power at the booster's
input. As such, the `--power` option (or the power sweep) doesn't
manipulate with ROADM's target output power, but only with the output
power of the amplifiers. With PSD equalization, the `--power` option is
interpreted as the power of the reference channel defined in equipment
config's `SI` container, and its PSD is used for propagation. Power
sweep is interpreted in the same way, e.g.:

      "SI":[{
            "f_min": 191.3e12,
            "baud_rate": 32e9,
            "f_max":195.1e12,
            "spacing": 50e9,
            "power_dbm": 0,
            "power_range_db": [-1,1,1],
            "roll_off": 0.15,
            "tx_osnr": 40,
            "sys_margins": 2
            }],

...and with the PSD equalization in a ROADM:

    {
      "uid": "roadm A",
      "type": "Roadm",
      "params": {
        "target_psd_out_mWperGHz": 3.125e-4,
      }
    },
    {
      "uid": "edfa in roadm A to toto",
      "type": "Edfa",
      "type_variety": "standard_medium_gain",
      "operational": {
        "gain_target": 22,
        "delta_p": 2,
        "tilt_target": 0.0,
        "out_voa": 0
      }
    },

then we use the power steps of the power_range_db to compute resulting
powers of each carrier out of the booster amp:

 power_db = psd2powerdbm(target_psd_out_mWperGHz, baud_rate)
 sweep = power_db + delta_power for delta_power in power_range_db

Assuming one 32Gbaud and one 64Gbaud carriers:

                   32 Gbaud        64 Gbaud
roadmA out power
(sig+ase+nli)      -20dBm         -17dBm

EDFA out power
range[
        -1          1dBm            4dBm
         0          2dBm            5dBm
         1          3dBm            6dBm
]

Design case:

Design is performed based on the reference channel set defined in SI
in equipment config (independantly of equalization process):

      "SI":[{
            "f_min": 191.3e12,
            "baud_rate": 32e9,
            "f_max":195.1e12,
            "spacing": 50e9,
            "power_dbm": -1,
            "power_range_db": [0,0,1],
            "roll_off": 0.15,
            "tx_osnr": 40,
            "sys_margins": 2
            }],

`delta_p` values of amps refer to this reference channel, but are applicable
for any baudrate during propagation, e.g.:

    {
      "uid": "roadm A",
      "type": "Roadm",
      "params": {
        "target_psd_out_mWperGHz": 2.717e-4,
      }
    },
    {
      "uid": "edfa in roadm A to toto",
      "type": "Edfa",
      "type_variety": "standard_medium_gain",
      "operational": {
        "gain_target": 22,
        "delta_p": 2,
        "tilt_target": 0.0,
        "out_voa": 0
      }
    },

Then the output power for a 64 Gbaud carrier will be +4 =
= lin2db(db2lin(power_dbm + delta_p)/32e9 * 64e9)
= lin2db(db2lin(power_dbm + delta_p) * 2)
= powerdbm + delta + 3 = 4 dBm

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I28bcfeb72b0e74380b087762bb92ba5d39219eb3
2023-01-17 12:26:50 +01:00
Jan Kundrát
125264f265 coding style: don't yell when using the recommended newline-vs-operator
Fun stuff -- PEP8 used to recommend against this pattern, but back in
2016 the Pythonic Truth got reversed to actually recommend the pattern
which we're using. Unfortunately, W503 is still a thing, and even though
it's supposed to be ignored, it really ain't.

Change-Id: I99f42548d236f05d1050fd78cb81b3b20a78013c
2023-01-17 12:26:50 +01:00
Jan Kundrát
b1067a6266 docs: flexgrid
Co-authored-by: Esther Lerouzic <esther.lerouzic@orange.com>
Change-Id: If38b56a39e083deec0563f25a2b575788dcedc43
2023-01-17 09:48:15 +00:00
EstherLerouzic
50d4ecd700 docs: fix power mode vs. gain mode and power sweep
Change-Id: Ibef9a49123767d6e2ce73081485833f281711e04
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Co-authored-by: Jan Kundrát <jan.kundrat@telecominfraproject.com>
2023-01-17 09:47:58 +00:00
Jan Kundrát
9f37e0371e CI: temporarily require tox 3.x
Upstream introduced some breaking changes, one of which is a different
installation process. As a result, the builds won't perform a full
package installation, which means that there are no console entry points
(shell wrappers), which means that the test suite fails.

Hotfix this by temporarily requiring an older version of tox.

Change-Id: I0466c70f2024d35d87606d9ad738284a143a574f
2023-01-17 01:31:33 +01:00
Jan Kundrát
9bd303db05 CI: github: upgrade deprecated actions
...because the GitHub infrastructure is deprecating Node 12 actions:

 https: //github.blog/changelog/2022-09-22-github-actions-all-actions-will-begin-running-on-node16-instead-of-node12/

Change-Id: I2d4a28be37a407aa26e79a1755eb5c3b0ec36a87
2023-01-10 12:27:50 +01:00
EstherLerouzic
1bcb3ce25c JSON: ensure that node constraints use correct indexing
The program currently ignores the explicit `index` and reads the
constraints in the JSON order of the list. However in general, it is not
guaranteed that constraints are listed in order.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Icefe271f5801cf9f7b43311c6666556564587c65
Signed-off-by: Jan Kundrát <jan.kundrat@telecominfraproject.com>
2022-11-22 01:53:24 +01:00
Jan Kundrát
e381138320 move test-only dependencies from main requirements
Pandas is only used from the test suite.

Bug: https://github.com/Telecominfraproject/oopt-gnpy/issues/451
Change-Id: Iafd02c800e5b7772e180979d19b81a2eda0e588f
2022-11-15 10:01:31 +00:00
EstherLerouzic
b450677709 Minor refactor: use watt2dbm function
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I09c3e923a8e1565d2ab07596c393bb5b2dc30f6c
2022-11-09 14:39:27 +01:00
EstherLerouzic
54a3725e17 Add a -spectrum option to input external file to define spectrum
The option is only set for gnpy-transmission-main.

The spectrum file is a list of spectrum objects, each defining
f_min, f_max and spectrum attributes using the same meaning as SI
in eqpt_config.json for baud_rate, roll_off, tx_osnr. slot_width is
used for the occupation of each carrier around their central frequency,
so slot_width corresponds to spacing of SI.
Unlike SI, the frequencies are defined includint f_min and f_max.
The partitions must be contiguous not overlapping.

Pref.p_span0 object records the req_power, while
ref_carrier records info that will be useful for equalization ie baud_rate.

For now, I have not integrated the possibility to directly use
transceivers type and mode in the list.

User can define sets of contiguous channels and a label to identify
the spectrum bands. If no label are defined, the program justs uses
the index + baud rate of the spectrum bands as label.

Print results per spectrum label

If propagated spectrum has mixed rates, then prints results (GSNR and OSNR)
for each propagated spectrum type according to its label.

Print per label channel power of elements

Per channel power prints were previously only showing the noiseless
reference channel power and only an average power.
With this change, we add a new information on the print:
the average total power (signal + noise + non-linear noise).
If there are several spectrum types propagating, the average per
spectrum is displayed using the label.
For this purpose, label and total power are recorded in each element
upon propagation

Note that the difference between this total power and the existing
channel power represents the added noise for the considered OMS.
Indeed ROADMs equalize per channel total power, so that power displayed
in 'actual pch (dBm)' may contain some noise contribution accumulated
with previous propagation.
Because 'reference pch out (dBm)' is for the noiseless reference,
it is exactly set to the target power and 'actual pch (dBm)' is always
matching 'reference pch out (dBm)' in ROADM prints.

Add examples and tests for -spectrum option

initial_spectrum1.json reproduces exactly the case of SI
initial_spectrum2.json sets half of the spectrum with 50GHz 32Gbauds and
half with 75GHz 64 Gbauds. Power setting is not set for the second half,
So that equalization will depend on ROADM settings.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ibc01e59e461e5e933e95d23dacbc5289e275ccf7
2022-11-09 14:39:25 +01:00
Jan Kundrát
8889c2437a refactoring: ROADM: clarify effective_loss and improve the docs
Move the docs to a place where that variable is declared, not to the
place where it's computed.

Co-authored-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-id: I17dff12c1e81827dfb4be869e59c9be85797dba4
2022-11-03 10:24:42 +01:00
Jan Kundrát
8bf8b2947b tests: pass the reference carrier when constructing SI
Co-authored-by: EstherLerouzic <esther.lerouzic@orange.com>
Fixes: 18610fb7 Add ref_carrier to Pref and remove req_power from ReferenceCarrier
Change-Id: I8ac2a7ca7c6d866170e564771c6cb78dcf3754d8
2022-11-03 10:24:38 +01:00
EstherLerouzic
cb85b8fe2b Add a test with long propagation
Existing tests only cover short distances, and effect on accumulated
noise, especially when crossing ROADMs with equalization, are not well
reported on elements power prints.
With this long path, I can catch more printing inconsistencies.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I2d0e8ccbbd387a2cd6c645c07f4b5f75e4617c30
2022-11-02 12:05:26 +01:00
EstherLerouzic
18610fb7a9 Add ref_carrier to Pref and remove req_power from ReferenceCarrier
ref_carrier is added in Pref conveys the reference channel type
information ie the channel that was used for design (would it be
auto-design or for a given design). Other attributes (like
slot_width or roll-off) may be added here for future equalization
types.

Pref object already records the req_power, so let's remove it
from ReferenceCarrier and only use ref_carrier to record info that
will be useful for PSD equalization ie baud_rate.

This reference baud_rate is required to compute reference target power
based on spectral density values during propagation. It is thus required
because of on-the-fly evaluation of loss for p_span_i and for printing
loss and target power of ROADM during propagation.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ic7441afa12ca5273ff99dea0268e439276107257
2022-11-02 12:05:26 +01:00
EstherLerouzic
bd6b278dd1 Add tx_osnr in spectral information
This change enables to use a different tx_osnr per carrier.

If tx_osnr is defined via spectrum then use it to define a tx_osnr per
carrier in si else use the tx_osnr of request to set tx_osnr of si.

Then, the propagate function for requests is changed to update OSNR with
tx_OSNR per carrier defined in si.

TODO: The tx_osnr defined in spectrum is not yet taken into account for
the propagate_and_optimize function, because the loop that optimizes
the choice for the mode only loops on baudrate.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I0fcdf559d4f1f8f0047faa257076084ec7adcc77
2022-10-31 16:04:46 +01:00
EstherLerouzic
e143d25339 Add a user defined initial spectrum in propagation functions
A new function is added to build spectrum information based on
the actual mixture of channels to be simulated (baud rate, slot width,
power per frequency).

Propagation function is changed so that, if the user defines a
specific distribution, then it uses it, else it uses as before,
all identical channels based on the initial request. In this case,
as before this change, we assume full load, with same channel for
the spectral info and not the resulting mixt of channels after
routing.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Icf56396837b77009e98accd27fcebd2dded6d112
2022-10-31 16:03:15 +01:00
EstherLerouzic
ffc7dbc241 Change pref from a scalar to a list of per channel delta power
The idea behind this change is to reproduce the exact same behaviour as
with the scalar, but accounting for variable levels of powers.

- delete the  neq_ch: equivalent channel count in dB because with mixed
  rates and power such a value has limited utility
- instead creates a vector that records the 'user defined' distribution
  of power.

This vector is used as a reference for channel equalization out of the
ROADM. If target_power_per_channel has some channels power above
input power, then the whole target is reduced.
For example, if user specifies delta_pdb_per_channel:
   freq1: 1dB, freq2: 3dB, freq3: -3dB, and target is -20dBm out of the
ROADM, then the target power for each channel uses the specified
delta_pdb_per_channel.
   target_power_per_channel[f1, f2, f3] = -19, -17, -23
However if input_signal = -23, -16, -26, then the target can not be
applied, because -23 < -19dBm and -26 < -23dBm, and a reduction must be
applied (ROADM can not amplify).
Then the target is only applied to signals whose power is above the
threshold. others are left unchanged and unequalized.
the new target is [-23, -17, -26]
and the attenuation to apply is [-23, -16, -26] - [-23, -17, -26] = [0, 1, 0]

Important note:
This changes the previous behaviour that equalized all identical channels
based on the one that had the min power !!

TODO: in coming refactor where transmission and design will be properly
separated, the initial behaviour may be set again as a design choice.

This change corresponds to a discussion held during coders call. Please look at this document for
a reference: https://telecominfraproject.atlassian.net/wiki/spaces/OOPT/pages/669679645/PSE+Meeting+Minutes

- in amplifier: the saturation is computed based on this vector
delta_pdb_per_channel, instead of the nb of channels.
The target of the future refactor will be to use the effective
carrier's power. I prefer to have this first step, because this is
how it is implemented today (ie based on the noiseless reference),
and I would like first to add more behaviour tests before doing
this refactor (would it be needed).

- in spectralInfo class, change pref to a Pref object to enable both
p_span0 and p_spani to be conveyed during propagation of
spectral_information in elements. No refactor of them at this point.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I591027cdd08e89098330c7d77d6f50212f4d4724
2022-10-28 09:13:24 +02:00
EstherLerouzic
b842898baf Change precision of --show-channels to 5 digits
Flexgrid precision is 6.25GHz so --show-channels should be at least 5 digits

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I7de4254ab18508320133371e0d8cc8b5e08f0d2f
2022-10-28 00:38:28 +00:00
EstherLerouzic
7ea9e3b341 Fix bug when gain is not initialized
If gain is not initialized, save_networks does not work properly
trying to round a None value

Change-Id: I614859f16e0019a2f6fe680c04159398c9b1eb51
2022-10-20 15:38:12 +00:00
Jan Kundrát
fcf168b361 tests: fix flake8 and flake8-html incompatibility
Test runs (`linters-diff-ci`) end up with an error:

 Traceback (most recent call last):
   File "/home/zuul/src/gerrithub.io/Telecominfraproject/oopt-gnpy/.tox/linters-diff-ci/bin/flake8", line 8, in <module>
     sys.exit(main())
   File "/home/zuul/src/gerrithub.io/Telecominfraproject/oopt-gnpy/.tox/linters-diff-ci/lib/python3.10/site-packages/flake8/main/cli.py", line 22, in main
     app.run(argv)
   File "/home/zuul/src/gerrithub.io/Telecominfraproject/oopt-gnpy/.tox/linters-diff-ci/lib/python3.10/site-packages/flake8/main/application.py", line 336, in run
     self._run(argv)
   File "/home/zuul/src/gerrithub.io/Telecominfraproject/oopt-gnpy/.tox/linters-diff-ci/lib/python3.10/site-packages/flake8/main/application.py", line 326, in _run
     self.report()
   File "/home/zuul/src/gerrithub.io/Telecominfraproject/oopt-gnpy/.tox/linters-diff-ci/lib/python3.10/site-packages/flake8/main/application.py", line 321, in report
     self.formatter.stop()
   File "/home/zuul/src/gerrithub.io/Telecominfraproject/oopt-gnpy/.tox/linters-diff-ci/lib/python3.10/site-packages/flake8_html/plugin.py", line 245, in stop
     self.write_index()
   File "/home/zuul/src/gerrithub.io/Telecominfraproject/oopt-gnpy/.tox/linters-diff-ci/lib/python3.10/site-packages/flake8_html/plugin.py", line 281, in write_index
     versions=self.option_manager.generate_versions(),
 AttributeError: 'OptionManager' object has no attribute 'generate_versions'
 ERROR: InvocationError for command /home/zuul/src/gerrithub.io/Telecominfraproject/oopt-gnpy/.tox/linters-diff-ci/bin/flake8 --format html --htmldir linters --exit-zero (exited with code 1)

Bug: https://github.com/lordmauve/flake8-html/issues/30
Change-Id: I755877341dec2d9cd9bdcdab098e2067f783cc27
2022-10-20 15:37:12 +02:00
Jan Kundrát
a7ec7e2ed6 Merge changes from topic "mixed-rate"
* changes:
  Change saturation verification to total input power
  Prepare for Pref definition
  Add utilities
2022-09-19 09:30:59 +00:00
Jan Kundrát
00ee102b3a docs: fix RST formatting
...of a bullet list. This ain't markdown, apparently.

Change-Id: I4f7a55a4084eda6463636c1dd5c41ef43ef78921
2022-09-18 12:46:19 +02:00
EstherLerouzic
ce11524ad9 Correct dgt vector: listed in the reversed order
This was corrected for example-data but not for tests data
(in commit 3a72ce84d0, related
to issue #390)

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I929beeb034166d30aa994439a1d6a26350f5c3e9
2022-09-14 05:35:15 +00:00
EstherLerouzic
74be14562a record request_id as string, not integer
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I59416a6d69a5989d0c152461ca9e264abcf09ea8
2022-08-24 16:45:56 +02:00
EstherLerouzic
16694d0a09 support missing trx_mode in request instead of null value
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I5c05b17b0b134c7782a08e86015dc30c7c9b3713
2022-08-24 16:43:57 +02:00
EstherLerouzic
33c6038921 Change saturation verification to total input power
Previous check was made on reference channel computation.
Now we use the actual total input power to compute the actual gain.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I3e0db72fdb030a49e2b06cdcfb442b5e642c1777
2022-08-17 14:13:38 +02:00
EstherLerouzic
119c9eda90 Prepare for Pref definition
Mainly changes self.pch_out_db to self.ref_pch_out_dbm in order
to reflect real unit for the value and to remind that this value
is defined for a reference noiseless channel (whose power is recorded
in p_spani in Pref).

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: If0e008c3efc36ce73c9df01c76cf46985543d9fa
2022-08-17 14:13:38 +02:00
EstherLerouzic
b63e146bf4 Add utilities
to convert from/to watt, mW, dBm, power spectral density ...

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I9b9684c1ad096aa54d01ef3f0242ecd2dcae79aa
2022-08-17 14:13:38 +02:00
gborrach
09dba8a166 Fix: Raman pumps SRS solver
In the previous version, when the values of the counter-propagating Raman pump profiles were flipped, the pumps resulted flipped also in frequency.

Change-Id: I66f7c2aff35c72f5dcb4fb11f7a82fe1df2ee3f2
Co-authored-by: Andrea D'Amico <andrea.damico@polito.it>
2022-07-27 00:20:47 +02:00
Jan Kundrát
7f5043622b CI: GitHub: show all build failures
Change-Id: I4a5aeb123aa89a30371a36788188964ca924ca12
2022-07-07 16:32:13 +02:00
Jan Kundrát
6ad4593f41 CI: GitHub: test on Mac OS as well
Change-Id: Ifb8ba470765fc02e3367beeaf8f048da6fdad6d7
2022-07-05 13:18:37 +02:00
Jan Kundrát
706661d801 CI: GitHub: use new test-requirements
Follow-up: b86fe960 I8d2e610c91da728d72c7d19590b25bbd8713f0de tests: Easier installation of test requirements via PIP
Change-Id: I870ed27af7301829ced572214f517ca76a94a0dc
2022-07-05 13:07:18 +02:00
Jan Kundrát
a408d28911 Merge "Remove Travis-CI leftovers" 2022-07-05 11:07:08 +00:00
Jan Kundrát
b86fe96032 tests: Easier installation of test requirements via PIP
Burying these behind the tox.ini works fine on CI, but it means that
someone has to ask the users to run an extra `pip install pytest` for
the test suite. Not nice.

This will need a follow-up commit to adjust the GitHub action to use
this new simplified way. That cannot land via Gerrit due to GitHub's
permission model.

Change-Id: I8d2e610c91da728d72c7d19590b25bbd8713f0de
2022-07-05 12:45:19 +02:00
Jan Kundrát
43926518ad Remove Travis-CI leftovers
These builds have not been running for about an year. Now that we have
Zuul for day-to-day CI and GitHub actions for some auxiliary package
building, remove Travis.

Change-Id: I1dd7f70045fd24d2f73f0d2086cb49edde2093c7
2022-07-05 10:14:18 +02:00
Jan Kundrát
128a6e816b docs: better anchor for legacy JSON
Change-Id: I410a4c0cdd34dd9aa5d8e34bb859746236fffdd2
2022-07-03 01:03:26 +02:00
Jan Kundrát
44db951261 docs: show gnpy.app
Change-Id: I7ec5eec72fb0f07e277ac849da09003d376eec17
2022-04-12 11:42:06 +02:00
Jonas Mårtensson
3c3d919b77 Merge "Fix: penalties are not correctly initialized" 2022-04-11 18:55:42 +00:00
EstherLerouzic
2079d2bc5b Fix: penalties are not correctly initialized
When mode is not given and propagation is performed bidir, penalties
corresponding to automatically  selected mode are not correctly
initialized in request, and gnpy-path-request fails.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: If045624ff5dad7f0dfdec93eaa05bb5eae86e643
2022-04-06 17:17:21 +02:00
Jonas Mårtensson
062e2076ed Properly initialize power profiles for Raman calculation
numpy.empty should not be used for initializing arrays without manually
setting values since it does not initialize entries. Use numpy.zeros
instead.

Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
Change-Id: I4e85eb39bdce00663c0cab9582ea7ae25eb90986
2022-03-29 21:41:57 +02:00
Jonas Mårtensson
1dd1bad273 Fix bug in Raman calculation without counterpropagating pumps
The counterpropagating power profile was initialized based on number of
copropagating frequencies, which caused simulation to crash when no
counterpropagating pumps were present.

Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
Change-Id: I685e5438fda06058f0757ff51fdd67bc68aa1352
2022-03-29 21:27:18 +02:00
Jan Kundrát
5b104af296 packaging: cleanup: remove non-existing paths
The examples have lived below gnpy/example-data/ for a few releases
already, and I've checked that these files are included in release
tarballs and wheels.

Change-Id: I782fc56a171f4cbc08f6698ac5d339e4cacecbb4
2022-03-09 00:13:43 +01:00
Jan Kundrát
f170574abf CI: retire gate
We have not started using this one, so let's not pretend that it's
active.

Change-Id: I806a76e2c6e0dc1d1fb76796cfea8eb37bfa39ca
2022-02-15 13:27:24 +01:00
Jan Kundrát
a68e8ff8d2 CI: Use default VMs for Python 3.8
Since the mirror infra for Fedora 34 is now gone on Vexxhost, let's try
to use the default options.

Change-Id: I6e4cc07705287666a772c6b1b70e981b24da6670
2022-02-15 13:18:31 +01:00
AndreaDAmico
d5a52d1b2b Restructure Transceiver with new spectral information
Change-Id: Iec9a6e4a510b8020aed8804d4a594b2b0429e28d
2022-02-10 17:38:39 +01:00
AndreaDAmico
7ac6e058ec EDFA new spectral information restructuring
Change-Id: Ia30e0e9bd666e83394c7a0740b2117a2d9c9d485
2022-02-10 17:37:03 +01:00
AndreaDAmico
74ab3c1bcd Fused new spectral information restructuring
Change-Id: Ie4dd989e2fd72682820845d21c43afed177f0f2f
2022-02-10 17:36:35 +01:00
AndreaDAmico
1a2ff2d215 Roadm new spectral information restructuring
Change-Id: I5c7c615e8278bff79dc74af10810589a15cc7535
2022-02-10 17:34:28 +01:00
Giacomo Borraccini
aaf0480e9c Management of lumped losses along a fiber span
The lumped losses are used in the computation of the loss/gain profile
through the fiber whether the Raman effect is considered or not. The
computed power profile is used to calculate the related NLI impairment.

Using the 'gn_model_analytic' method, the lumped losses are taken into
account as the contribution of an additional total loss at the end of
the fiber span. In case the 'ggn_spectrally_separated' is selected, the
method uses the computed power profile according to the specified z and
frequency arrays. The lumped losses are so considered within the NLI
power evolution along the fiber.

Change-Id: I73a6baa321aca4d041cafa180f47afed824ce267
Signed-off-by: Jan Kundrát <jan.kundrat@telecominfraproject.com>
2022-02-10 17:33:34 +01:00
Jan Kundrát
5e50ffbbf6 CI: check patches on Python 3.10 as well
Depends-on: https://review.gerrithub.io/c/Telecominfraproject/oopt-zuul-jobs/+/531900
Change-Id: I975c38b2f287aa07b68cc37500c7022feb4ae3e2
2022-02-02 02:13:23 +01:00
Jan Kundrát
243b701391 docs: update dependencies
Python 3.10 builds require a fix in Sphinx, so let's update all docs
dependencies while we're at this.

Unfortunately, the myst-parser requires docutils<0.18,>=0.15 so we
cannot take the latest and greatest of that one.

After this update, sphinxcontrib-bibtex now requires an explicit
reference to the .bib files directly in the config file. Let's remove
the one in the actual docs, then.

Bug: https://github.com/sphinx-doc/sphinx/pull/9513
Change-Id: I80f62131b25f3afa23351646001f6ce381723487
2022-02-02 02:13:04 +01:00
Jan Kundrát
bdbfe76aed Mark Python 3.10 as supported
The CI is (so far) only post-merge via the GitHub CI. The Zuul CI is
pending on Fedora 35 images within nodepool; I've requested that via a
ticket at Vexxhost, our hosted CI provider.

Change-Id: I81c9867792f972db8fcb2bf902f5f8d1ed7ffeea
2022-01-20 18:51:02 +01:00
Jan Kundrát
541ec04444 GitHub CI: Python 3.10
Add a new target, and switch those builds where a specific version is
not that important to the latest and greatest.

Change-Id: I6f62a08c671a98b3663c7a8cf0099947457f1e4d
2022-01-20 18:50:54 +01:00
Jan Kundrát
bf1522b047 Merge changes Iff561600,I60f951e9
* changes:
  tests: update pytest
  Update dependencies
2022-01-20 17:50:09 +00:00
Jan Kundrát
3f4188a0fd Merge changes I79611db3,Ib0ab383b,I3745eba4,Ic19aff08,Ic255f35d
* changes:
  Add PMD and PDL in amplifiers
  Introduce PDL accumulation and penalty calculation
  Calculate CD and PMD penalty
  Set PMD for ROADMs in OpenROADM eqpt_config according to MSA spec
  Fix formatting of OpenROADM eqpt files
2022-01-20 16:48:11 +00:00
Jan Kundrát
8b387ef722 tests: update pytest
Let's switch to this new major version; it's not wise to stay on a
previous major release indefinitely. In practical terms, version 6.x is
a requirement for supporting Python 3.10.

I'm not updating the CI configuration yet because GitHub disallows
pushes via Gerrit when GitHub CI Actions are modified. The version will
have to be bumped in there as well.

Change-Id: Iff5616007b51e6098f53810a28fef5b839dadec2
2022-01-19 16:25:38 +01:00
Jan Kundrát
cad9a0f18e Update dependencies
Updating everything to the latest versions which are available on PIP --
apart from xlrd, which decided to stop supporting XLSX files in their
newest version. Since we have some XLSX files in this repo, I think we
cannot update now.

Change-Id: I60f951e9f17cc62f0dcdc6b6d0cfce0cb5f891fa
2022-01-19 16:23:18 +01:00
Jonas Mårtensson
ab84c77363 Restore RamanFiber to_json method with operational parameters
The recent commit 77925b2 removed the to_json method from RamanFiber
class, which means that operational parameters (temperature and
raman_pumps) were not included when converting a topology to json and
saving it. This patch restores it.

Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
Change-Id: Icbea349c1ffaa2f216533b84c8edf5c8b59765f9
2022-01-18 19:07:28 +01:00
Jonas Mårtensson
62fa9ab0b0 Add PMD and PDL in amplifiers
Both PMD and PDL is set to 0 by default. Values from the OpenROADM MSA
for ILAs are included in corresponding eqpt files.

Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
Change-Id: I79611db3ae798e9dadc47ee39161dc1e242f2595
2022-01-18 12:35:59 +01:00
Jonas Mårtensson
14591c7a11 Introduce PDL accumulation and penalty calculation
This fixes #421

As a first step PDL is specified in the eqpt library for ROADMs only.
In a later step, PDL (as well as PMD) should be specified also for amps
and possibly for fibers. PDL values from the OpenROADM MSA for ROADMs
are included in the corresponding eqpt files.

The acculumation rule for PDL is the same as for PMD as shown in:

"The statistics of polarization-dependent loss in optical communication
systems", A. Mecozzi and M. Shtaif, IEEE Photon. Technol. Lett., vol.
14, pp. 313-315, Mar 2002.

PDL penalty is specified and calculated in the same way as for CD and
PMD, i.e. linear interpolation between impairment_value/penalty_value
pairs. This patch includes penalty specification for OpenROADM trx
modes according to the MSA.

Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
Change-Id: Ib0ab383bcaee7d7523ffc3fa9a949d76c8c86ff7
2022-01-18 12:35:59 +01:00
Jonas Mårtensson
587932290d Calculate CD and PMD penalty
The penalties are calculated and presented separately from the GSNR.

They are also taken into account when optimizing trx mode and verifying
path feasibility in path_requests_run processing.

Penalties are specified in the eqpt_config file as part of trx modes.
This patch includes specifications for OpenROADM trx modes.

Penalties are defined by a list of
impairment_value/penalty_value pairs, for example:

"penalties": [
    {
        "chromatic_dispersion": 4e3,
        "penalty_value": 0
    },
    {
        "chromatic_dispersion": 18e3,
        "penalty_value": 0.5
    },
    {
        "pmd": 10,
        "penalty_value": 0
    },
    {
        "pmd": 30,
        "penalty_value": 0.5
    }
]

- Between given pairs, penalty is linearly interpolated.
- Below min and above max up_to_boundary, transmission is considered
  not feasible.

This is in line with how penalties are specified in OpenROADM and
compatible with specifications from most other organizations and
vendors.

The implementation makes it easy to add other penalties (PDL, etc.) in
the future.

The input format is flexible such that it can easily be extended to
accept combined penalty entries (e.g. CD and PMD) in the future.

Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
Change-Id: I3745eba48ca60c0e4c904839a99b59104eae9216
2022-01-18 12:35:59 +01:00
Jonas Mårtensson
82b148eb87 Set PMD for ROADMs in OpenROADM eqpt_config according to MSA spec
Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
Change-Id: Ic19aff08ea0da51656ba81e04f34a405413f7b54
2022-01-18 12:35:59 +01:00
Jonas Mårtensson
8393daf67d Fix formatting of OpenROADM eqpt files
Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
Change-Id: Ic255f35d32ce996724a547962efc44d7950bac4d
2022-01-18 12:35:57 +01:00
Jan Kundrát
be61dfd094 Merge changes from topic "mixed-rate"
* changes:
  Raman Solver restructuring and speed up
  Effective area included in fiber parameters
  Fiber propagation of new Spectral Information.
  Small change on Fiber parameters
2022-01-18 09:58:07 +00:00
AndreaDAmico
77925b218e Raman Solver restructuring and speed up
In this change, the RamanSolver is completely restructured in order to obtain a simplified and faster solution of the Raman equation. Additionally, the inter-channel Raman effect can be evaluated also in the standard fiber, when no Raman pumping is present. The same is true for the GGN model.

The Raman pump parameter pumps_loss_coef has been removed as it was not used. The loss coefficient value evaluated at the pump frequency can be included within the fiber loss_coef parameter.

This change induces variations in some expected test results as the Raman profile solution is calculated by a completely distinct algorithm. Nevertheless, these variations are negligible being lower than 0.1dB.

Change-Id: Iaa40fbb23c555571497e1ff3bf19dbcbfcadf96b
2022-01-12 19:37:10 +01:00
AndreaDAmico
4621ac12bf Effective area included in fiber parameters
Gamma and the raman efficiency are calculated using the effective area if not provided. Both these parameters are managed as optional in json_io.py for backward compatibility.

Change-Id: Id7f1403ae33aeeff7ec464e4c7f9c1dcfa946827
2022-01-06 12:00:00 +01:00
AndreaDAmico
09920c0af2 Fiber propagation of new Spectral Information.
Modification of the Fiber and the NliSolver in order to properly propagate the new definition of the spectral information taking advantage of the numpy array structures.

In the previous version, the propagation of the spectral information was implemented by means of for cycles over each channel, in turn.
In this change the propagation is applied directly on the newly defined spectral information attributes as numpy arrays.

Additional changes:
- Simplification of the FiberParameters and the NliParameters;
- Previous issues regarding the loss_coef definition along the frequency are solved;
- New test in test_science_utils.py verifing that the fiber propagation provides the correct values in case of a few cases of flex grid spectra.

Change-Id: Id71f36effba35fc3ed4bbf2481a3cf6566ccb51c
2022-01-06 12:00:00 +01:00
AndreaDAmico
e6a3d9ce5b Small change on Fiber parameters
Squeeze function has been replaced by asarray. Using 'get' function
instead of if condition for the dictionaries.  Frequency reference
derived from wavelength reference of 1550 nm.

Change-Id: I815ad8591c9e238f3fc9322ca0946ea469ff448f
2022-01-06 12:00:00 +01:00
Jonas Mårtensson
b9645702c8 Add fiber padding after splitting fibers
Since splitting fibers may result in fibers with loss lower than
specifed padding, the padding should be added after splitting.

Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
Change-Id: Id75ddf5d81c4c1c52f8f8becfdb005d2fe04c1f8
2021-12-19 21:20:08 +01:00
Jan Kundrát
9c2095b138 remove unused import
Change-Id: I08d31eab16f0c4195c4431f339c60ac694788d22
2021-12-07 16:49:40 +01:00
Jan Kundrát
cb42115230 LGTM: exclude more harmless "errors"
The {node.uid} pattern is used also when exporting some data to a file,
and once again it is not an antipattern for us.

Change-Id: Ib4441155b5ca42fad7dd6cf8554a0302a69ef136
2021-12-07 16:47:30 +01:00
Jan Kundrát
5909da4bbf remove an unused import
Change-Id: I4d719813b647424c20cc7fc990c36a57490b7f5b
2021-12-07 12:49:46 +01:00
Jan Kundrát
2ba1e86b28 Silence an irrelevant warning on LGTM.com
By default, this service issues a warning for strings which format data
like {uid}, flagging this pattern as related to antipatterns CWE-312,
CWE-315 and CWE-359. This warning is not relevant for us because we
never process sensitive information (if there are some NDA-covered data
in the input, well, the user already has them, we're just using these).

Silence this warning (it's currently getting us an B rating,
apparently).

See-also: https://lgtm.com/rules/1510014536001/
Change-Id: Id5cdd2c62e61a8329760d3fb79665737beb22378
2021-12-07 12:49:46 +01:00
Jan Kundrát
3358c5eeb5 Merge "docs: a beginner-friendly way of reaching out to vendors" 2021-11-25 14:53:57 +00:00
Jan Kundrát
13e4c29bc1 Merge "tests: rely on pytest's native comparisons of nested dicts" 2021-11-11 16:17:14 +00:00
Jan Kundrát
4becc9060c docs: a beginner-friendly way of reaching out to vendors
As Gert proposed on the latest call, submitting patches could be a bit
high of a barrier to go over. Let's make it clear that we're here to
help those vendors who are willing to collaborate.

Change-Id: Ieac1c91480143c553ffb25dd1c46e94022bf5ba3
2021-11-04 18:45:05 +01:00
AndreaDAmico
32d8b2a4d8 Simulation Parameters
This change siplifies the structure of the simulation parameters,
removing the gnpy.science_utils.simulation layer, provides some
documentation of the parameters and define a mock fixture for testing in
safe mode.

Jan: while I'm not thrilled by this concept of hidden global state, we
agreed to let it in as a temporary measure (so as not to hold merging of
Andrea's flexgrid/multirate patches). I've refactored this to a more
pytest-ish way of dealing with fixtures. In the end, it was also
possible to remove the MockSimParams class because it was not adding any
features on top of what SimParams can do already (and to what was
tested).

Change-Id: If5ef341e0585586127d5dae3f39dca2c232236f1
Signed-off-by: Jan Kundrát <jan.kundrat@telecominfraproject.com>
2021-10-29 13:14:22 +02:00
Jan Kundrát
399eb9700f tests: rely on pytest's native comparisons of nested dicts
In my opinion, this actually produces more useful output *if* pytest is
invoked with `-vv` (which the CI is already doing). When I deliberately
change the expected result of services like this:

 --- a/tests/data/testService_services_expected.json
 +++ b/tests/data/testService_services_expected.json
 @@ -45,7 +45,7 @@
            ],
            "spacing": 50000000000.0,
            "max-nb-of-channel": null,
 -          "output-power": 0.0012589254117941673,
 +          "output-power": 0.001258925411791673,
            "path_bandwidth": 10000000000.0
          }
        }

...the old code would just say:

 >       assert not results.requests.different
 E       AssertionError: assert not [({'bidirectional': False, 'destination': 'trx Vannes_KBE', 'dst-tp-id': 'trx Vannes_KBE', 'path-constraints': {'te-ba......}], 'max-nb-of-channel': None, 'output-power': 0.0012589254117941673, 'path_bandwidth': 10000000000.0, ...}}, ...})]
 E        +  where [({'bidirectional': False, 'destination': 'trx Vannes_KBE', 'dst-tp-id': 'trx Vannes_KBE', 'path-constraints': {'te-ba......}], 'max-nb-of-channel': None, 'output-power': 0.0012589254117941673, 'path_bandwidth': 10000000000.0, ...}}, ...})] = Results(missing=set(), extra=set(), different=[({'request-id': '1', 'source': 'trx Brest_KLA', 'destination': 'trx Van...g': 50000000000.0, 'max-nb-of-channel': 80, 'output-power': 0.0012589254117941673, 'path_bandwidth': 60000000000.0}}}}).different
 E        +    where Results(missing=set(), extra=set(), different=[({'request-id': '1', 'source': 'trx Brest_KLA', 'destination': 'trx Van...g': 50000000000.0, 'max-nb-of-channel': 80, 'output-power': 0.0012589254117941673, 'path_bandwidth': 60000000000.0}}}}) = ServicesResults(requests=Results(missing=set(), extra=set(), different=[({'request-id': '1', 'source': 'trx Brest_KLA'...': 50000000000.0, 'max-nb-of-channel': 80, 'output-power': 0.0012589254117941673, 'path_bandwidth': 60000000000.0}}}})).requests

 tests/test_parser.py:147: AssertionError
 ...
 FAILED tests/test_parser.py::test_excel_service_json_generation[xls_input1-expected_json_output1] - AssertionError: assert not [({'bidirectional': False, 'destination': 'trx Vannes_KBE', 'dst-tp-id': 'trx Vannes_KBE', 'path-constraints': {'te-ba......}], 'max-nb-of-channel': None, 'output-power': 0.0012589254117941673, 'path_bandwidth': 10000000000.0, ...}}, ...})]

With this change in place, the report becomes more useful:

 >       assert from_xls == load_json(expected_json_output)
 E       AssertionError: assert {'path-request': [{'bidirectional': False,\n                   'destination': 'trx Vannes_KBE',\n                   'dst-tp-id': 'trx Vannes_KBE',\n                   'path-constraints': {'te-bandwidth': {'effective-freq-slot': [{'M': None,\n                                                                                  'N': None}],\n                                                         'max-nb-of-channel': 80,\n                                                         'output-power': None,\n                                                         'path_bandwidth': 100000000000.0,\n                                                         'spacing': 50000000000.0,\n                                                         'technology': 'flexi-grid',\n                                                         'trx_mode': 'mode 1',\n                                                         'trx_type': 'Voyager'}},\n                   'request-id': '0',\n                   'source': 'trx Lorient_KMA',\n                   'src-tp-id': 'trx Lorient_KMA'},\n                  {'bidirectional': False,\n                   'destination': 'trx Vannes_KBE',\n                   'dst-tp-id': 'trx Vannes_KBE',\n                   'path-constraints': {'te-bandwidth': {'effective-freq-slot': [{'M': None,\n                                                                                  'N': None}],\n                                                         'max-nb-of-channel': None,\n                                                         'output-power': 0.0012589254117941673,\n                                                         'path_bandwidth': 10000000000.0,\n                                                         'spacing': 50000000000.0,\n                                                         'technology': 'flexi-grid',\n                                                         'trx_mode': 'mode 1',\n                                                         'trx_type': 'Voyager'}},\n                   'request-id': '1',\n                   'source': 'trx Brest_KLA',\n                   'src-tp-id': 'trx Brest_KLA'},\n                  {'bidirectional': False,\n                   'destination': 'trx Rennes_STA',\n                   'dst-tp-id': 'trx Rennes_STA',\n                   'path-constraints': {'te-bandwidth': {'effective-freq-slot': [{'M': None,\n                                                                                  'N': None}],\n                                                         'max-nb-of-channel': 80,\n                                                         'output-power': 0.0012589254117941673,\n                                                         'path_bandwidth': 60000000000.0,\n                                                         'spacing': 50000000000.0,\n                                                         'technology': 'flexi-grid',\n                                                         'trx_mode': 'mode 1',\n                                                         'trx_type': 'vendorA_trx-type1'}},\n                   'request-id': '3',\n                   'source': 'trx Lannion_CAS',\n                   'src-tp-id': 'trx Lannion_CAS'}]} == {'path-request': [{'bidirectional': False,\n                   'destination': 'trx Vannes_KBE',\n                   'dst-tp-id': 'trx Vannes_KBE',\n                   'path-constraints': {'te-bandwidth': {'effective-freq-slot': [{'M': None,\n                                                                                  'N': None}],\n                                                         'max-nb-of-channel': 80,\n                                                         'output-power': None,\n                                                         'path_bandwidth': 100000000000.0,\n                                                         'spacing': 50000000000.0,\n                                                         'technology': 'flexi-grid',\n                                                         'trx_mode': 'mode 1',\n                                                         'trx_type': 'Voyager'}},\n                   'request-id': '0',\n                   'source': 'trx Lorient_KMA',\n                   'src-tp-id': 'trx Lorient_KMA'},\n                  {'bidirectional': False,\n                   'destination': 'trx Vannes_KBE',\n                   'dst-tp-id': 'trx Vannes_KBE',\n                   'path-constraints': {'te-bandwidth': {'effective-freq-slot': [{'M': None,\n                                                                                  'N': None}],\n                                                         'max-nb-of-channel': None,\n                                                         'output-power': 0.001258925411791673,\n                                                         'path_bandwidth': 10000000000.0,\n                                                         'spacing': 50000000000.0,\n                                                         'technology': 'flexi-grid',\n                                                         'trx_mode': 'mode 1',\n                                                         'trx_type': 'Voyager'}},\n                   'request-id': '1',\n                   'source': 'trx Brest_KLA',\n                   'src-tp-id': 'trx Brest_KLA'},\n                  {'bidirectional': False,\n                   'destination': 'trx Rennes_STA',\n                   'dst-tp-id': 'trx Rennes_STA',\n                   'path-constraints': {'te-bandwidth': {'effective-freq-slot': [{'M': None,\n                                                                                  'N': None}],\n                                                         'max-nb-of-channel': 80,\n                                                         'output-power': 0.0012589254117941673,\n                                                         'path_bandwidth': 60000000000.0,\n                                                         'spacing': 50000000000.0,\n                                                         'technology': 'flexi-grid',\n                                                         'trx_mode': 'mode 1',\n                                                         'trx_type': 'vendorA_trx-type1'}},\n                   'request-id': '3',\n                   'source': 'trx Lannion_CAS',\n                   'src-tp-id': 'trx Lannion_CAS'}]}
 E         Differing items:
 E         {'path-request': [{'bidirectional': False, 'destination': 'trx Vannes_KBE', 'dst-tp-id': 'trx Vannes_KBE', 'path-const...[{...}], 'max-nb-of-channel': 80, 'output-power': 0.0012589254117941673, 'path_bandwidth': 60000000000.0, ...}}, ...}]} != {'path-request': [{'bidirectional': False, 'destination': 'trx Vannes_KBE', 'dst-tp-id': 'trx Vannes_KBE', 'path-const...[{...}], 'max-nb-of-channel': 80, 'output-power': 0.0012589254117941673, 'path_bandwidth': 60000000000.0, ...}}, ...}]}
 E         Full diff:
 E           {
 E            'path-request': [{'bidirectional': False,
 E                              'destination': 'trx Vannes_KBE',
 E                              'dst-tp-id': 'trx Vannes_KBE',
 E                              'path-constraints': {'te-bandwidth': {'effective-freq-slot': [{'M': None,
 E                                                                                             'N': None}],
 E                                                                    'max-nb-of-channel': 80,
 E                                                                    'output-power': None,
 E                                                                    'path_bandwidth': 100000000000.0,
 E                                                                    'spacing': 50000000000.0,
 E                                                                    'technology': 'flexi-grid',
 E                                                                    'trx_mode': 'mode 1',
 E                                                                    'trx_type': 'Voyager'}},
 E                              'request-id': '0',
 E                              'source': 'trx Lorient_KMA',
 E                              'src-tp-id': 'trx Lorient_KMA'},
 E                             {'bidirectional': False,
 E                              'destination': 'trx Vannes_KBE',
 E                              'dst-tp-id': 'trx Vannes_KBE',
 E                              'path-constraints': {'te-bandwidth': {'effective-freq-slot': [{'M': None,
 E                                                                                             'N': None}],
 E                                                                    'max-nb-of-channel': None,
 E         -                                                          'output-power': 0.001258925411791673,
 E         +                                                          'output-power': 0.0012589254117941673,
 E         ?                                                                                          +
 E                                                                    'path_bandwidth': 10000000000.0,
 E                                                                    'spacing': 50000000000.0,
 E                                                                    'technology': 'flexi-grid',
 E                                                                    'trx_mode': 'mode 1',
 E                                                                    'trx_type': 'Voyager'}},
 E                              'request-id': '1',
 E                              'source': 'trx Brest_KLA',
 E                              'src-tp-id': 'trx Brest_KLA'},
 E                             {'bidirectional': False,
 E                              'destination': 'trx Rennes_STA',
 E                              'dst-tp-id': 'trx Rennes_STA',
 E                              'path-constraints': {'te-bandwidth': {'effective-freq-slot': [{'M': None,
 E                                                                                             'N': None}],
 E                                                                    'max-nb-of-channel': 80,
 E                                                                    'output-power': 0.0012589254117941673,
 E                                                                    'path_bandwidth': 60000000000.0,
 E                                                                    'spacing': 50000000000.0,
 E                                                                    'technology': 'flexi-grid',
 E                                                                    'trx_mode': 'mode 1',
 E                                                                    'trx_type': 'vendorA_trx-type1'}},
 E                              'request-id': '3',
 E                              'source': 'trx Lannion_CAS',
 E                              'src-tp-id': 'trx Lannion_CAS'}],
 E           }

 tests/test_parser.py:140: AssertionError

Change-Id: I30eafb3c7c0f2e800fb0983371eaa5058e78b029
2021-10-28 17:16:11 +02:00
AndreaDAmico
82f83e1462 Add documentation of simulation parameters
Jan: only add those parameter which are not being removed in future
patches and which have useful documentation that the user can plausibly
act on.

Change-Id: I02173f500fed8c065a30de5d23e318bce2a90c33
Co-authored-by: Jan Kundrát <jan.kundrat@telecominfraproject.com>
2021-10-28 16:18:25 +02:00
Jonas Mårtensson
171450fa54 Update documentation of polynomial NF to match the code
This fixes #422.

Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
Change-Id: I39af6767e41723b23dd61a832860fc66f21dbf17
2021-10-28 08:41:14 +02:00
AndreaDAmico
9f9f4c78fc Small change on Raman pump parameters
Getter and setter removed from the class PumpParams. The propagation
direction is cast to lower case string within the PumpParams
constructor.

Change-Id: Ice28affe8bcffbf8adcebb5cb096be8100081511
2021-10-26 16:33:35 +02:00
AndreaDAmico
c469a8d9ba New definition of spectral information
It allows the definition of an arbitrary spectral information.
It is fully back-compatible.

Change-Id: Id050e9f0a0d30780a49ecfbe8b96271fe47bcedc
2021-10-26 15:59:20 +02:00
Jonas Mårtensson
99b2a554dc Correct calculation of NF for OpenROADM amps
This fixes #420.

In order to be consistent with the OpenROADM MSA, the input power per
channel used for calculating incremental OSNR and NF should be scaled to
50 GHz slot width.

Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
Change-Id: I64ca3e4cad6399f308827f4161d7c6b89be9d2ca
2021-10-19 12:02:48 +02:00
Jan Kundrát
57e98d7173 CI: linters: don't complain about non-lowercase variable names
...as agreed during today's coders call. It turned out that we do not
have a strong opinion, and it appeared that this limits us bit. The
rationale was that sometimes there's a loss of information when we
force-lowercase (such as milli- vs. mega-). So let's hope we're gonna be
smarter than a rigid set of rules :).

See-also: https://review.gerrithub.io/c/Telecominfraproject/oopt-gnpy/+/525660/2/gnpy/core/elements.py#681
Change-Id: If88abfa8383a437cc42e9196c612897fae6c96a0
2021-10-19 12:00:07 +02:00
Jan Kundrát
78b45a3958 Merge "Fix warnings for raman amp type varieties" 2021-10-11 19:32:03 +00:00
Jan Kundrát
64b6b486a9 Merge "Fix unit for max_fiber_lineic_loss_for_raman" 2021-10-11 19:15:59 +00:00
Jonas Mårtensson
65cb46f479 Fix unit for max_fiber_lineic_loss_for_raman
See GitHub issue #419.

The unit of max_fiber_lineic_loss_for_raman in the default equipment
config file is dB/km but it was compared with Fiber.params.loss_coef
which is in units of dB/m.

Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
Change-Id: I27c8ab03845a72fcda97415843c007078b7b9d06
2021-10-11 21:03:17 +02:00
Jonas Mårtensson
f94d06f124 Fix warnings for raman amp type varieties
Currently, a warning about fiber lineic loss being above threshold is
printed even when the warning is triggered by that the previous node is
not a fiber, which is confusing. Additionally, when a warning about
raman is triggered, the code in the following else clause is not
executed, which means that a potential warning about gain level is
disabled. These two warnings are independent and the second one should
not be disabled by the first one.

Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
Change-Id: I8ad58b4ebf6e7df1a949a77d67ed948ef385c47e
2021-09-28 13:08:57 +02:00
EstherLerouzic
e1f2c55942 Remove the representation error due to floating point
On certain values of loss_coef, the computation loss_coef * 1e-3 * 1e3
results in x.0000000000000000y values:
eg if 0.21 is provided in the topology file, then parameters.FiberParams
changes this to _loss_coef = 0.00021
and elements.Fiber.to_json prints 0.21000000000000002
This is a normal floating point behaviour, but is rather confusing.
In order to remove this unwanted decimal, I propose to round the printings
in to_json

https://docs.python.org/3/tutorial/floatingpoint.html

The change also add this round for gain, because in power mode
the gain is computed based on loss and loss may have this floating value.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ib3287a794e7da985eabf0af914c0e1ef4914e857
2021-09-16 15:41:25 +02:00
Jan Kundrát
d28c67143e docs: remove link to asciinema
This image needs changing, so let's prepare by not linking to asciinema
anymore.

Change-Id: I15567325139fdf02bcca2bf2b1f1460d689cbfa4
2021-09-15 16:21:10 +02:00
Jan Kundrát
6bb9ae8336 tests: Fix after merging two incompatible changes
Oops. We are not using gating, which means that changes are tested
against the "current tip of the branch" and might pass fine there, but
once they are merged, there can well be a conflict between them. This
has just happened.

The EDFA which reported a difference had its VOA set to 0.5. Previously,
this was not taken into assumption.

Fixes: ce51a4d1 Take explicitly set out_voa value into account in power calculation
Fixes: 280443f1 add an invocation test with power saturation
Change-Id: Icebbb16d2ef5886d2c9c04cc9a300a6aa08bf245
2021-09-15 15:31:20 +02:00
Jan Kundrát
0dc7d853ef Merge changes I7f6cc553,I0a6a8442,I34fe2dcf
* changes:
  requests: avoid TypeError
  add an invocation test with power saturation
  Update a roadm test to include more cases for power handling
2021-09-15 13:09:32 +00:00
Jan Kundrát
dec9388416 Merge changes from topic "openroadm-v5"
* changes:
  tests: add OpenROADMv5 example propagation
  OpenROADM: mark example config files as v4 explicitly
  Add an eqpt config file matching latest OpenROADM MSA version
  Add updated openroadm amp specifications to eqpt config
2021-09-15 13:08:40 +00:00
Jan Kundrát
017b35fa33 Merge changes I4e407484,Id35aeffe
* changes:
  examples: json-to-csv: fix invocation
  examples: fix JSON-to-CSV description
2021-09-15 13:06:27 +00:00
Jan Kundrát
cb0a410418 Merge "Take explicitly set out_voa value into account in power calculation" 2021-09-15 13:05:12 +00:00
Jan Kundrát
f250990a49 requests: avoid TypeError
When printing a Request which had its baud_rate set and bit_rate unset,
the code would hit a TypeError.

Fixes: https://review.gerrithub.io/c/Telecominfraproject/oopt-gnpy/+/521471
Change-Id: I7f6cc553c07fd8e7d1ef32866d9f711a32016744
2021-09-15 14:59:59 +02:00
EstherLerouzic
280443f17f add an invocation test with power saturation
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I0a6a8442326fdfb9c9922abf05aeee52cfa42090
2021-09-15 14:59:59 +02:00
EstherLerouzic
6f62251cb4 Update a roadm test to include more cases for power handling
add several power reference setting tests to the existing test

the test only checks the  power level out of roadm B.
if previous node is a preamp, power level is the one specified in
target_pch_out_db.
if previous node is a fused , power level at roadm input is below
target_pch_out_db and roadm can not increase this power (no amp).
then expected outpower is in_power, which should be equal to -22 + power_dBm
on this particular node.

nota bene
currently, no minimum losss is coded on roadm, so that the applied loss
is 0 dB, and roadm does not affect power in this case.
This behaviour is not correct and should be changed in the future.
But for now, I am only concentrating on existing behaviour tests.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I34fe2dcf2d355b291c27745ab511d3d77057dd94
2021-09-15 13:04:09 +02:00
Jan Kundrát
5ad54879b1 Merge "docs: cross-reference topology section with XLS/JSON" 2021-09-15 10:39:46 +00:00
Jan Kundrát
825d37c05c tests: add OpenROADMv5 example propagation
These numbers "appear to look sane" as per [1]. Let's make sure that the
config files are CI-tested.

[1] https://review.gerrithub.io/c/Telecominfraproject/oopt-gnpy/+/522340/1#message-b40ac2c839f138237139407374452f254c3b0b0d

Change-Id: Iad346a14ed12b984f90a40629c0339fa0823290e
2021-09-15 12:33:18 +02:00
Jan Kundrát
3ac9f90914 OpenROADM: mark example config files as v4 explicitly
The recent commit has added support for OpenROADM v5, the latest
published optical spec sheet. Given that the upstream project has
released v10 YANG files (but still just v3, v4 and v5 XLS sheets with
optical performance numbers), I think it would be rather misleading to
have both versioned and non-versioned config files -- especially when
the unversioned one refers to the oldest release, not the newest one.

Change-Id: I04109341724b51d276660d400c923dc28561aef2
2021-09-15 12:31:05 +02:00
Jan Kundrát
dbfbf115ff examples: json-to-csv: fix invocation
The two filenames are actually mandatory, not optional.

Reported-by: 张路 <luzhang@bupt.edu.cn>
Change-Id: I4e40748430a602a2c06eb35c96e0a8267519b8b3
2021-09-15 12:14:19 +02:00
Jan Kundrát
ad2590962b examples: fix JSON-to-CSV description
Change-Id: Id35aeffe4e71da663f3c91298cb166cee5646c98
2021-09-15 12:13:10 +02:00
Jan Kundrát
a9d530c776 Merge "Check for non-existing N or M values when comparing requests" 2021-09-14 14:39:12 +00:00
Jan Kundrát
f255c31f1f Merge "Add option to cli examples for disabling auto-insertion of EDFAs" 2021-09-14 13:15:14 +00:00
Jan Kundrát
80ec05f84c Merge "Limit target length when splitting fibers to max_length in eqpt config" 2021-09-07 09:29:15 +00:00
Jonas Mårtensson
22541d65e4 Check for non-existing N or M values when comparing requests
The compare_reqs function checks if N and M values of the requests are
None but these attributes may not exist e.g. if a service file does not
define an "effective-freq-slot" for a request.

Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
Change-Id: I786aad97ed658cd703694f164a87525d77b51fe1
2021-08-31 22:52:10 +02:00
Jan Kundrát
26fcf0ff6e CI: docker: releases should update the latest tag
We've been accidentally not updating the `latest` tag on Docker hub
after switching from Travis CI to GitHub actions. Traditionally, we've
assumed the `latest` points to the "latest release", so this patch makes
it simple and will call any pushed "version tag" as the `latest`. This
will become a problem if/when we start maintaining multiple releases,
but I think it's a safe approach for now.

As before, there's also the `master` tag which always points to the,
well, master branch of the repo.

Change-Id: I14c08b12010986d4327bd9d685619a98cfec370f
2021-08-31 16:16:01 +02:00
Jan Kundrát
1c32e437a2 docs: README: link to pretty installation docs
The docs used to point to in-the-tree source code of the documentation
in the RST format. When navigating from the landing page on GitHub, this
led to GitHub's rendering of the RST, which is rather incomplete. Just
point to readthedocs to get a nice doc format.

Change-Id: I985a8fd1688337b4e0e47cdb09b666cf4e96cc1b
2021-08-31 12:59:01 +02:00
EstherLerouzic
718007b3de Do not agregate requests which have non None N,M spectrum values
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ib103e3292887c863e7c1cd785ffbffba629d0d02
2021-08-31 11:31:16 +02:00
EstherLerouzic
4d6c06340f Add a complementary set of tests on the N and M values
- if specified, they must be used except:
    - if N and M are not consistant (eg M smaller than the required
      spectrum for the demand)
    - if N value and M value lead to occupation outside of the band
    - if spectrum is occupied
- if any of them is None, the program uses the first fit strategy for M and
the path_bandwidth value to compute minimum required M

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I9160ffb116dd9d7d53ad80638826b609a1367446
2021-08-31 11:31:16 +02:00
EstherLerouzic
bad893bf86 Remove this test which should never happen
this sort of verification should be covered by automatic tests
since this is a verification of the correct behaviour of the
spectrum_selection function

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I76dd3bcad74085e1cd36ecb6503dad0271b61b80
2021-08-31 11:31:16 +02:00
EstherLerouzic
75e7fca8e4 change M value from 0 to None in case of blocking
Change tests based on M==0 value for response creation and use
instead the blocking_reason attribute existence
result element should have non null M value if request is not blocked.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I67e4222cf9d014201e91d3aefd3624b001264e03
2021-08-31 11:31:16 +02:00
EstherLerouzic
4e38ba98ab Change N value from 0 to None in case of NO_SPECTRUM
in case spectrum can not be assigned default value for N
was set to 0, which is not correct (N is a meaningfull value for
center frequency index). This changes replaces this default
value with None

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ibe642682e48d09f340d53e2092f172de6aa7cc90
2021-08-31 11:31:16 +02:00
EstherLerouzic
fdcdfca589 refactor spectrum assignment
use the new function compute_spectrum_slot_vs_bandwidth

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: If045fe53550dbde57c56fd4e8b99275c0757ea2b
2021-08-31 11:31:16 +02:00
EstherLerouzic
299ca10a47 Add a consistency check on request before any propagation is performed
In case user defines trx_mode, it is possible to check consistency of
nb of required slots and the total requested path_bandwidth and raise
a service error, before staring any propagation computation.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I543cab581280faef5d6072eb172da136f2542492
2021-08-31 11:31:16 +02:00
EstherLerouzic
c0b7bf714e Remove "null" entries of effective-freq-slot
before 'effective-freq-slot' was just ignored, and filled with "null" strings.
this is no longer supported

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I24d30de91b8b29d37f6ba81220d3cad5aabb6781
2021-08-31 11:31:16 +02:00
EstherLerouzic
7f7c568160 Enabling the reading of N and M value from the json request
For this commit only the first element from the {N, M} list is read
and assigned.

This is better than not reading this value at all.

the commit also updates test_files and test data files with correct
values for the effective_freq_slot attribute

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I1e60fe833ca1092b40de27c8cbfb13083810414e
2021-08-31 11:31:07 +02:00
EstherLerouzic
9bf6ed953a Add a new cause of blocking
if the user has specified a nb of slot and has not specified a mode
it may happen that the nb of slot is finally not large enough to support
the requested traffic: then blocking reason is 'NOT_ENOUGH_RESERVED_SPECTRUM'

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I8d4c4df5fa97e37aefac8d9ee0d93c901505fa55
2021-08-31 11:23:08 +02:00
EstherLerouzic
e68dc39ddd Avoid overwriting blocking reason
When a path is blocked for 'NO_FEASIBLE_MODE' reason, and bidir is true,
the request attributes are filled with the last explored mode values
(baudrate notably), and the reversed path is propagated with this last
explored mode specs. if this reversed path is also not feasible the blocking
reason was overwritten with a 'MODE_NOT_FESIBLE' reasonn, because
baudrate is filled in the request attribute.

This change ensure that the blocking reason (if it exists) is not overwritten.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: If80a37d77e2b967a327562c733a44e7f78f1c544
2021-08-31 11:23:08 +02:00
Jan Kundrát
f8007b41d1 Merge changes from topic "refactor disjunction"
* changes:
  adding another set of test for disjunction
  Minor refactor
  Refactor step4 of the compute_path_dsjctn
2021-08-31 09:19:57 +00:00
Jonas Mårtensson
228125029e Add an eqpt config file matching latest OpenROADM MSA version
This adds a separate OpenROADM eqpt config file corresponding to the
latest version of the MSA:

https://0201.nccdn.net/4_2/000/000/071/260/20210629_open-roadm_msa_specification_ver5.0.xlsx

The existing config file corresponding to the old version is kept for
backward compatibility. The new version introduces the following
changes:

* New definition of incremental OSNR for a ROADM based on polynomial
  (see also previous commit).

* ROADM add path OSNR changed from 30 dB to 33 dB

* New transceiver mode: 200 Gbit/s, 31.57 Gbaud, DP-16QAM

* Tx OSNR for transceiver mode 100 Gbit/s, 31.57 Gbaud, DP-QPSK changed
  from 35 dB to 36 dB

Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
Change-Id: Ieb7d33bd448ed9d0cb8320ed190019c9aa94c9ef
2021-08-16 22:10:21 +02:00
Jonas Mårtensson
d185e0c241 Add updated openroadm amp specifications to eqpt config
The latest version 5.0 of the OpenROADM MSA changes the definition
of the incremental OSNR mask of a ROADM to a polynomial:

https://0201.nccdn.net/4_2/000/000/071/260/20210629_open-roadm_msa_specification_ver5.0.xlsx

A new preamp type variety corresponding to the updated specification is
added to the default eqpt config file while also keeping the type
variety corresponding to the old specification for backward
compatibility.

The updated specification includes both typical and worst case values.
These are added as separate type varieties to let the user choose which
values to use. Note that the specification with typical values is
identical to the existing OpenROADM ILA standard type variety but a new
type variety is still added for clarity.

Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
Change-Id: I2de5e9db69f9ae3b218e30a3b246bd9b83cef458
2021-08-16 20:57:42 +02:00
Jonas Mårtensson
357bbec257 Limit target length when splitting fibers to max_length in eqpt config
Auto-design tries to split fibers longer than the max_length parameter
specified in the eqpt config file. When calculating new fiber lengths,
it uses a target_length parameter, which is currently hardcoded to 90
km. If the user specifies a max_length that is shorter than the
target_length and the topology includes any fiber that is longer than
the max_length but shorter than the hardcoded target_length, the
calculation crashes with a ZeroDivisionError. This patch limits the
target_length parameter so that it can't be longer than max_length.

Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
Change-Id: Id0851fcf79ab0b1a05832e22ee7e9cf63691446c
2021-08-10 14:10:25 +02:00
EstherLerouzic
d25e98c567 adding another set of test for disjunction
Previous set of tests did not correctly check the combinations of
disjunction and route constraint. This new set tests specific cases
with several demands in one synchronization vector with and without
route constraint, and the case where both disjunction constraint and
route can not be met (STRICT and LOOSE cases)

+ minor refactor on test_disjunction

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Id5a5902e6945185922ce5743ac97d15dbc777af2
2021-08-02 18:02:14 +02:00
Jan Kundrát
397411690e Merge "Nicer printing of Edfa elements when parameters are None" 2021-06-29 16:06:02 +00:00
Jonas Mårtensson
4ab6f8cb1b Nicer printing of Edfa elements when parameters are None
When delta_p or target_pch_out_db is None (resulting e.g. from
operating in gain mode) the current logic replaces a whole printed
line with 'None' which does not look very nice in the script outputs.
With this patch, the parameter information is kept in the printout
like this:

  Delta_P (dB):           None
  target pch (dBm):       None

Change-Id: Ie52ce7353a708a174cf9d769918a6136eefbf444
Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
Fixes: 225cafa8 (Floating point formatting of elements' operational parameters)
2021-06-29 11:37:05 +00:00
Jan Kundrát
44aff147db Merge pull request #410 from jktjkt/ci-on-windows
CI: test on Windows
2021-06-29 13:33:48 +02:00
Jan Kundrát
a36b139065 CI: GitHub: push coverage reports to codecov
Since Travis CI builds stopped, nothing was pushing updates to codecov.

Change-Id: Ia9a15a1a956c41586eda9ab85bd1f22fa798e960
2021-06-17 20:32:50 +02:00
Jan Kundrát
141fc66d47 CI: GitHub: fix conditional syntax
This is strange because the docs say that it's required [1], but during
my testing it appeared to work just fine without this wrapping. Anyway,
let's follow the docs.

[1] https://docs.github.com/en/actions/reference/context-and-expression-syntax-for-github-actions#about-contexts-and-expressions

Change-Id: I6a03f9423d7f10d03687759de71f25aed15bd172
2021-06-17 19:52:43 +02:00
Jan Kundrát
53f29957fd CI: GitHub: don't fail pushing PyPI releases from forks
...and also unify the condition with what syntax that the Docker build
job is using.

Change-Id: Ia6e3fe308093bac144441f4d9a33df93ffdca06f
2021-06-17 19:05:52 +02:00
Jan Kundrát
9f3995ee20 CI: GitHub: don't try to access Docker Hub without proper credentials
Change-Id: I9dccb2d12ad97d54fa0f5bfa0d8db63cc5deb2ec
2021-06-17 18:49:07 +02:00
Jan Kundrát
0cf45bd102 CI: test on Windows
I've been getting reports that the test suite is broken on Windows (the
usual set of problems such as CRLF line endings and backslashes in path
names), so let's make sure we have a way of reproducing this.
Unfortunately, we don't have a Windows image in Zuul, so this will be a
post-merge CI I'm afraid :(.

Change-Id: Ibd539764d6e40693b95a9b231324bd0216e4a207
2021-06-17 18:18:16 +02:00
Jan Kundrát
55932ee3e9 tests: handle Unicode properly for "expected console output"
Let's use the text mode everywhere because Unicode codepoints is what
matters. The only catch on Windows turned out to be the default file IO
encoding; forcing UTF-8 there fixes all issues in the CI (and it makes
sense because that file was written out in a UTF-8 locale, and the
system which runs the test suite might be set to something else.

This was a rather interesting debugging experience; passing logs over
the web and handling "strange" characters as utf-8 did not help.

Change-Id: I1fdbe3a115458558b27a81f9eab8e58c9605bae7
Bug: https://github.com/Telecominfraproject/oopt-gnpy/issues/358
2021-06-17 18:14:36 +02:00
Jan Kundrát
797a0856ec tests: Use a portable /dev/null file name
Bug: https://github.com/Telecominfraproject/oopt-gnpy/issues/358
Change-Id: Icbca94682ce0ded860ba6397e4445651b6a61f32
2021-06-17 16:20:49 +02:00
Jan Kundrát
3fa53adc4d Don't print file name when handling requests
We have a test which compares the raw output of GNPy against a fixed
expected output. That comparison of course chokes when forward slashes
and backslashes are used, which breaks the test suite on Windows. Let's
try to solve this by always using forward slashes if possible. The way
to go is via pathlib's as_posix(), but that one can possibly return an
absolute path -- which cannot work in a test suite, obviously. So one
can workaround that via calling a Path.relative_to(), but that one
chokes on paths which require at least one "path up" component (`..`).
I posted a patch which use brute force here, but Jonas is right, better
just don't print that output in the test suite in the first place.

Change-Id: I762ddb58a2042120c7b20414152a06a3ed72048d
Bug: https://github.com/Telecominfraproject/oopt-gnpy/issues/358
2021-06-17 16:20:38 +02:00
Jan Kundrát
bcb5e6bb60 Merge changes I60b4e3bf,I2bb3b5a0,I344c4a03
* changes:
  tests: requests: rely on pytest's own dict support
  tests: enable pytest's builtin multiline diffing
  utils: document round2float
2021-06-17 14:15:32 +00:00
Jan Kundrát
6380f8f37a Merge "CI: Zuul: Introduce Python 3.9, and switch all to Fedora 34" 2021-06-11 13:44:58 +00:00
Jan Kundrát
93869d6cb5 CI: Zuul: Introduce Python 3.9, and switch all to Fedora 34
Change-Id: I40e66ca0eca21b91809ea0f94291f3bd77bc53d2
Depends-on: https://review.gerrithub.io/c/Telecominfraproject/oopt-zuul-jobs/+/518622
2021-06-11 15:35:46 +02:00
Jonas Mårtensson
ce51a4d160 Take explicitly set out_voa value into account in power calculation
As mentioned in GitHub issue #409, an out_voa value for an EDFA
explicitly set in the topology file is not taken into account by
auto-design when calculating target power and gain. I think it is
more logical if the target power resulting from the optimization
algorithm represents the desired power into the fiber. This is also
more consistent with the behaviour for an automatically set out_voa
value when out_voa_auto is set to true.

Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
Change-Id: I7e58b61d0bf30728c39d36404619dbe370c12f2b
2021-06-11 08:32:00 +02:00
Jan Kundrát
601e228bb6 tests: requests: rely on pytest's own dict support
When `pytest` is run with `-vv`, it shows a diff of multiline strings
and dict just fine. The only drawback is that there's the raw string
with newlines shown as "\n", however, *then* the nice diff pretty
printing kicks in, and the result is:

 E                 Common items:
 E                 {'response-id': '5'}
 E                 Differing items:
 E                 {'path-properties': {'path-metric': [{'accumulative-value': 21.68, 'metric-type': 'SNR-bandwidth'}, {'accumulative-val...EDFA', 'link-tp-id': 'east edfa in Rennes_STA to Stbrieuc', 'node-id': 'east edfa in Rennes_STA to Stbrieuc'}}}, ...]}} != {'path-properties': {'path-metric': [{'accumulative-value': 21.68, 'metric-type': 'SNR-bandwidth'}, {'accumulative-val...EDFA', 'link-tp-id': 'east edfa in Rennes_STA to Stbrieuc', 'node-id': 'east edfa in Rennes_STA to Stbrieuc'}}}, ...]}}
 E                 Full diff:
 E                   {
 E                    'path-properties': {'path-metric': [{'accumulative-value': 21.68,
 E                                                         'metric-type': 'SNR-bandwidth'},
 E                                                        {'accumulative-value': 28.77,
 E                                                         'metric-type': 'SNR-0.1nm'},
 E                                                        {'accumulative-value': 23.7,
 E                                                         'metric-type': 'OSNR-bandwidth'},
 E                                                        {'accumulative-value': 30.79,
 E                                                         'metric-type': 'OSNR-0.1nm'},
 E                                                        {'accumulative-value': 0.0019952623149688794,
 E                                                         'metric-type': 'reference_power'},
 E                                                        {'accumulative-value': 20000000000.0,
 E                                                         'metric-type': 'path_bandwidth'}],
 ...
 ... now, it's a bit annoying that there's too much output, but
 ... that's just for context; the offending lines will be properly
 ... marked, see --\
 ...               |
 ...               v
 ...
 E                                                               {'path-route-object': {'index': 17,
 E                 -                                                                    'num-unnum-hop': {'gnpy-node-type': 'transceiver',
 E                 ?                                                                                       ^ ^^^^^^^  - ^      ^^^^^^^^^ -
 E                 +                                                                    'num-unnum-hop': {'link-tp-id': 'trx '
 E                 ?                                                                                       ^^ ^   ^^^      ^^
 E                 -                                                                                      'link-tp-id': 'trx '
 E                                                                                                                      'Lannion_CAS',
 E                                                                                                        'node-id': 'trx '
 E                                                                                                                   'Lannion_CAS'}}},
 E                                                               {'path-route-object': {'index': 18,
 E                                                                                      'label-hop': {'M': 6,
 E                                                                                                    'N': -274}}},
 E                                                               {'path-route-object': {'index': 19,
 E                                                                                      'transponder': {'transponder-mode': 'mode '
 E                                                                                                                          '2',
 E                                                                                                      'transponder-type': 'vendorA_trx-type1'}}}]},
 E                    'response-id': '5',
 E                   }

 tests/test_parser.py:312: AssertionError

Change-Id: I60b4e3bfa432a720a381bf2c0a9f0288e989dab2
2021-06-09 21:17:21 +02:00
Jan Kundrát
3f58cbd559 tests: enable pytest's builtin multiline diffing
...because it works on strings while doesn't work on byte arrays.

Change-Id: I2bb3b5a0a3d6ad965321c58fb90a02341db66d0f
2021-06-09 21:17:21 +02:00
Jan Kundrát
2e3274ac78 utils: document round2float
Change-Id: I344c4a03e7d3e0614e0fc3307b12af359c61b882
2021-06-09 21:17:21 +02:00
Jan Kundrát
e33144f8cc Merge "refactoring: OpenROADM: store the NF model of a premp/booster" 2021-06-09 18:54:56 +00:00
Jan Kundrát
fd1e3f0f61 Merge "Do not load equipment['SI']['default'].power_range_db in the gain mode" 2021-06-09 18:31:48 +00:00
Jan Kundrát
80c41264cf CI: Docker: remove the dev- prefix
We have never used that one before, so let's not introduce it now.
Noise, noise, noise, sorry.

Change-Id: I336b3e73f7dd61b14615412ea52ec90986468fcf
2021-06-09 20:22:58 +02:00
Jan Kundrát
a051a5723b Merge tag 'v2.3.1'
GNPy 2.3.1

Just some release automation on top of v2.3. If you're already on v2.3,
there's no need to update; this release does not contain any
user-visible changes.

Change-Id: I0473a0bb43be596cf376cf18eb8a546b53aa0214
2021-06-09 20:14:11 +02:00
Jan Kundrát
72f300ab94 CI: Build and upload a PyPI package upon tagging
Change-Id: Idcd84a9f8e03ffc4ea27b37add8e5e59d1da7509
2021-06-09 20:03:57 +02:00
Jan Kundrát
2c3b0d8c82 CI: GitHub: build Docker images
Pushes to master should create a "development" tag. Tags should create
something prettier.

We need the git checkout for proper package versioning, hence that magic
`context` thing, and also that magic `echo`.

Change-Id: I79fcb800cc079e8486c3795f36aa1993676cee49
2021-06-09 19:53:53 +02:00
Jan Kundrát
11dab614a9 CI: GitHub: prevent duplicate runs
Change-Id: I09d55937d553d097b0440bb3c7d0f7dcc709abe3
2021-06-09 19:53:53 +02:00
Jan Kundrát
11d88bf09a CI: random bikeshedding about the name
Change-Id: I7ce2b32cb30f2b1a5e402c1dc999b02d2a1588de
2021-06-09 19:46:23 +02:00
Jan Kundrát
af3cc4736e setup metadata: fix description
Our landing page on PyPI was not displaying the longer version of the
README, just a one-sentence summary. It turns out that `pbr` can indeed
read the README file, but specifying the `description` overrides that
with no warning. Yay.

Change-Id: Ic03412928fe09f5edab4a7b9f4297a485a740cd0
2021-06-09 16:34:24 +02:00
Jan Kundrát
50cb82ee18 packaging: fix the long description
Fixes: e45a54c2 (README: rewrite in Markdown)
Change-Id: Ifefd78ba1008f0a37299dca07b53b5481ebeac27
2021-06-09 16:34:17 +02:00
Jan Kundrát
c80aca6696 CI: GitHub: ensure tags are present
We're using PBR, so let's make sure we don't get a package that's marked
as version 0.0.0.

Bug: https://github.com/actions/checkout/issues/217
Change-Id: Icd8264a798f9a1a404e21a9b64317c57662d53fe
2021-06-09 16:34:11 +02:00
Jan Kundrát
dfca35d4ae CI: always try to build a release wheel
This might be a wee bit controversial, I guess, because the Zuul jobs
look like there's a dedicated playbook for that
(playbooks/python/release.yaml). However, that would be one extra VM
launch, which feels wasteful. Let's waste the CPU cycles elsewhere --
during each "regular test build", produce a wheel as well.

It looks that these "wheels" are *the* format for distributing Python
packages now -- including the source code, of course. Since there's no
real support for tag review in Gerrit, I don't think I need Zuul for
release management, either, so I'll just rely on GitHub actions for
release upload, I guess. And for that, I need to "somehow" create a
wheel anyway, so let's just do this all the time to ensure that it
really works and never stops working.

Change-Id: Ib86852a386673cd4929a8059b19fa527cd4d5955
2021-06-09 16:34:02 +02:00
Jan Kundrát
1fbdaef58a CI: Run on GitHub Actions
We have Zuul, and we're happy with it; however, every now and then
there's a problem with the managed infrastructure, and there's also
people who contribute patches as GitHub PRs.

Change-Id: I405c5806ed9ad2e7f59f9b2394daf068b373e425
2021-06-09 16:33:50 +02:00
Jan Kundrát
bd025f3af4 setup metadata: fix description
Our landing page on PyPI was not displaying the longer version of the
README, just a one-sentence summary. It turns out that `pbr` can indeed
read the README file, but specifying the `description` overrides that
with no warning. Yay.

Change-Id: Ic03412928fe09f5edab4a7b9f4297a485a740cd0
2021-06-09 16:30:38 +02:00
Jan Kundrát
c3e546abe3 packaging: fix the long description
Fixes: e45a54c2 (README: rewrite in Markdown)
Change-Id: Ifefd78ba1008f0a37299dca07b53b5481ebeac27
2021-06-09 02:32:48 +02:00
Jan Kundrát
9427d0b139 CI: GitHub: ensure tags are present
We're using PBR, so let's make sure we don't get a package that's marked
as version 0.0.0.

Bug: https://github.com/actions/checkout/issues/217
Change-Id: Icd8264a798f9a1a404e21a9b64317c57662d53fe
2021-06-09 01:17:34 +02:00
Jan Kundrát
89f5b12f7e CI: always try to build a release wheel
This might be a wee bit controversial, I guess, because the Zuul jobs
look like there's a dedicated playbook for that
(playbooks/python/release.yaml). However, that would be one extra VM
launch, which feels wasteful. Let's waste the CPU cycles elsewhere --
during each "regular test build", produce a wheel as well.

It looks that these "wheels" are *the* format for distributing Python
packages now -- including the source code, of course. Since there's no
real support for tag review in Gerrit, I don't think I need Zuul for
release management, either, so I'll just rely on GitHub actions for
release upload, I guess. And for that, I need to "somehow" create a
wheel anyway, so let's just do this all the time to ensure that it
really works and never stops working.

Change-Id: Ib86852a386673cd4929a8059b19fa527cd4d5955
2021-06-09 00:49:52 +02:00
Jan Kundrát
9d2c10e267 CI: Run on GitHub Actions
We have Zuul, and we're happy with it; however, every now and then
there's a problem with the managed infrastructure, and there's also
people who contribute patches as GitHub PRs.

Change-Id: I405c5806ed9ad2e7f59f9b2394daf068b373e425
2021-06-08 22:34:00 +02:00
Jan Kundrát
305620e5dd Do not load equipment['SI']['default'].power_range_db in the gain mode
It is not used, so don't check it.

Change-Id: I309638ac8e647ed9f507016a116d9c8d0342c32d
2021-06-07 13:51:40 +00:00
Jan Kundrát
c91c5d622f Bump the minimal required Python to 3.8
We discussed this at one of the recent coder calls; the motivation
includes better mypy type hint support, especially in numpy, but also in
the language core, and of course the dataclasses.

Change-Id: I8ffee28c33f167cbcba978c85486e58a1b8c99be
2021-06-07 10:01:49 +00:00
Jan Kundrát
24e7f4a5a1 refactoring: OpenROADM: store the NF model of a premp/booster
All other noise models set the `nf_def` variable, so let's make the YANG
code simpler by remembering the amplifier NF model like that.

Change-Id: I341e4ac296c25bf9f27a98a7e4e92e0fd1546021
2021-06-04 23:10:30 +02:00
Jan Kundrát
225cafa8b7 Floating point formatting of elements' operational parameters
The current JSON data loader preserves (some) integers as integers. When
printed, the value might not contain any decimal points. The YANG patch
series, however, forces floats when floats are expected (while still
allowing None). This makes the output subtly different.

Change-Id: I0e0c013eb3abddb4aeac1ba43bf0d473fed731d4
2021-06-04 23:10:09 +02:00
Jan Kundrát
ad9cbb8a93 Merge "Use the term GSNR in result outputs" 2021-06-04 20:54:58 +00:00
Jonas Mårtensson
581b4a726f Use the term GSNR in result outputs
The term "GSNR" is well established by now. I think it's time we start
using it in our own result outputs instead of alternatives like "total
SNR" or just "SNR".

Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
Change-Id: I1fc65f6db1e3b2d7cfe974875174132fe5b28d3b
2021-06-04 12:48:50 +02:00
Jan Kundrát
ce92d4e1b8 JSON: don't sleep when there are warnings in the input topology
Well, sleeping ain't fun. A red warning is plenty. In case of API
access, there's none, but that's just the APIs are.

Change-Id: I2fb0c051a9c3bb7f2ef2264083686e929c27ec2c
Fixes: 6a6591e4 (Add a warning message when attributes are missing in eqpt_config.json)
2021-06-04 00:04:16 +02:00
Jan Kundrát
eb17b74ea4 Merge "Fix behavior when there's no EDFA DGT" 2021-06-03 21:58:52 +00:00
Jan Kundrát
051359ad77 Merge changes I7596efae,I3633a59d
* changes:
  Remove unused property Fiber.fiber_loss
  Remove unused property
2021-06-03 21:49:58 +00:00
Jan Kundrát
912eb712c3 Fix behavior when there's no EDFA DGT
We ship "some" DGT values which effectively mask this, but it's possible
to provide a "trivial" DGT vector such as [0, 0]. When that happens, the
code was failing with a numpy-level warning related to a division by
zero.

The code tried to be ready for this by trying to catch an exception, but
this relied on a particular numpy behavior upon zero division which was
not set up properly. For the added fun, there are two possible cases of
division by zero:

- on a zero tilt, it's a case of `0.0 / np.float64(0.)`, which is
controlled via "invalid",
- on a non-zero tilt, it's a case of `<float> / np.float64(0.)`, which
leads to "divide".

Let's just check for zero instead of wrestling exceptions.

Change-Id: I7a3c0b6b9b85e90a8a7201b7c7a56a5a44c27d69
2021-06-03 10:57:25 +02:00
Jan Kundrát
ce4ea9d6e3 README: shuffle elements around a wee bit
Let's start with some brief introduction, and only then push the picture
with the schematics.

Change-Id: I7e8662c3afe5076c73411def97d0fcb1f1a03e7f
2021-06-03 02:22:46 +02:00
Jan Kundrát
39c894bb6a Remove unused property Fiber.fiber_loss
Change-Id: I7596efaeaa1c6cdef15118521662e54db34fd9e6
2021-06-03 01:54:06 +02:00
Jan Kundrát
be95496f85 Remove unused property
I dig through the git log, and it looks like something which was never
used after some refactorings 3+ years ago.

Change-Id: I3633a59d8f2720932fa32c885ee5be643e640a46
2021-06-03 01:52:44 +02:00
Jan Kundrát
d38dabc824 Merge changes I8523fb93,Ia832cd8f,Id92bda62
* changes:
  Remove unused variables
  remove unused variable
  remove unused import
2021-06-02 21:55:34 +00:00
Jan Kundrát
5ad6336fda Docker: use a newer Python
Change-Id: I2e6725f7a009690f1a49a77d9ec4ff696141d5b5
2021-06-02 23:22:32 +02:00
Jan Kundrát
8ec9aca559 equipment: remember NF_min, NF_max when using the operator model
...so that these original values are accessible to the YANG conversion
later on, if needed.

Change-Id: I254127f9641a39a0478d0ef27b9f2e524bf60bda
2021-06-02 23:18:54 +02:00
Jan Kundrát
9abec6c9b7 docs: convert something into MarkDown
Change-Id: I5880e6675657dfc52d01cce529aba6563f9ca75f
2021-06-02 23:18:54 +02:00
Jan Kundrát
e3b904fb06 docs: allow writing Sphinx docs in Markdown
...because it's less annoying than the ReStructuredText.

Change-Id: Ic3db1fe1834580b0f31190b3bf96d6ab95c3b40e
2021-06-02 23:18:54 +02:00
Jan Kundrát
5d13b9bfb6 docs: remove a dependency on PBR
In the past, we had some manual version info in this file, but
apparently it never got updated past the 0.1 release (yay). The, in
4d5d10935 I changed this to retrieve the version information via PBR's
existing magic. That worked well, showing the abbreviated commit hash at
the footer on ReadTheDocs, but I don't think it was terribly useful:

- it was just a hash, nothing like the output of `git describe` (i.e.,
no tag info was there),
- it wasn't showing up in local docs builds which use the Alabaster
default theme.

Now, in 1b2eb9a5 I split the dependency handling. The idea was to make
sure that a "regular installation" would not pull the docs in
needlessly. Unfortunately, the way I set up the RTD builds, the common
dependencies were skipped, and as a result, the `pbr` package was not
available to RTD, and stuff failed.

I could have configured RTD to *also* install from the main deps, but I
don't think this is actually needed. Given that the version info is
rather subtle, let's skip it altogether. Instead, it's better to use
RTD's built-in features for switching between docs for a particular
release (via a git tag) and for the generic "master branch".

Change-Id: Iab0cc9608fa6c24eba93d772370ecd379cf65b1e
Fixes: 1b2eb9a5 (docs: separate out dependencies)
2021-06-02 23:10:05 +02:00
Jan Kundrát
0c26fd24b5 Travis: fix the build
Builds on Travis-CI do not use Tox, and I forgot to fix the dependencies
there.

Change-Id: I8a75e82dd0832d6a1e55257722e7e98b5ed57655
2021-06-02 22:36:48 +02:00
Jonas Mårtensson
08c922a5e5 Add option to cli examples for disabling auto-insertion of EDFAs
The auto-design feature inserts EDFAs after ROADMs and fibers when they
are not already present in the input topology file. This functionality
can be locally disabled by manually adding a Fused element in the
topology. This patch adds an option to the cli example scripts,
"--no-insert-edfas", which globally disables insertion of EDFAs as well
as automatic splitting of fibers.

Change-Id: If40aa6ac6d8b47d5e7b6f8eabfe389e8258cbce6
Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
2021-06-01 16:18:13 +02:00
Jan Kundrát
1b2eb9a5a8 docs: separate out dependencies
The intention is to separate "stuff that's needed by this package" from
"stuff that's needed to build the docs".

Change-Id: I7baf27e6f814880ea241ccbd3de4b87a6e7c4d1b
2021-06-01 01:26:53 +02:00
Jan Kundrát
219204e320 docs: use a newer Python on readthedocs
They do not seem [1] to support 3.9 yet, so let's stick with the 3.8
version for now.

[1] https://docs.readthedocs.io/en/stable/config-file/v1.html#python-version

Change-Id: I581bde3057a2a33b1ac419cdca3d110d196bdcfe
2021-05-31 20:28:29 +02:00
Jan Kundrát
38fc1fdc6d Remove unused variables
Change-Id: I8523fb938123ec9767eb9f540b229ddca23b9da5
2021-05-31 20:15:25 +02:00
Jan Kundrát
e25e1fbe50 remove unused variable
It was only assigned to in `read_service_sheet`, and it's safe to remove
it also in `convert_service_sheet`.

Change-Id: Ia832cd8fea2d864e920907e455e834a3c3a724dd
2021-05-31 20:13:38 +02:00
Jan Kundrát
8a96ff563e remove unused import
Change-Id: Id92bda6263a1b8db70d9142970522c504c10126d
2021-05-31 20:11:28 +02:00
Jan Kundrát
27d4fb0811 docs: add a blurb about OpenROADM
The discoverability can be improved, but hey, I guess this is better
than nothing.

Change-Id: I57792b50adb93321eff7bf301107f67cb9a8747d
2021-05-31 20:01:46 +02:00
Jan Kundrát
b5a8ae3f06 badges: link to Gerrit
Change-Id: I7e9e72bdae304f5b96567c98d12aa9564f126fb5
2021-05-31 19:58:58 +02:00
Jan Kundrát
e45a54c2b5 README: rewrite in Markdown
I find this about 666x more readable than the ReStructuredText.

Change-Id: Ic07cf129e0052b0083fff6899650e54b627efde7
2021-05-31 19:50:14 +02:00
Jan Kundrát
172697a2aa docs: move the introduction from the README to an extra docs chapter
Change-Id: Ifefbcb35e0e53f5d664b5720943f90fab34e1380
2021-05-31 19:37:36 +02:00
Jan Kundrát
9762b6e610 docs: move the project meta-stuff into the docs
The README should be just that, a README. Ours was about four pages
long, that's a bit too much I'm afraid.

Change-Id: I646e9d09e512384898271e10ff628906299b75a9
2021-05-31 19:37:36 +02:00
Jan Kundrát
4675a74e02 docs: tweak the shields on the landing page
Change-Id: I8cb320c0c10390af4f7d209ded5f3acee34b9790
2021-05-31 19:37:36 +02:00
Jan Kundrát
a268c219ed docs: show the Python versions used on the latest release
Change-Id: I028166bf830d3229066cb04f7c6ed9d4028b9644
2021-05-31 19:05:49 +02:00
Jan Kundrát
a47f069d97 PyPI: Python 3.9 is supported as well
We've been testing with Python 3.9 via Travis since this February, so
let's mark the project accordingly. Once a release which contains this
commit gets uploaded to PyPI, it will be propagated to the pip's web
interface.

Change-Id: I84635157565f1dbe9936231fa32ef3f6a0605e2f
2021-05-31 19:02:19 +02:00
Jan Kundrát
8fcead4294 docs: add some latex fanciness
Change-Id: I39348e0994fe576ce33d8b241ab9cedd0fd184c8
2021-05-31 18:56:17 +02:00
Jan Kundrát
b6daa15356 tests: include the OpenROADM amplifiers
Change-Id: I26d6ad422917fa6fd5943ffaa5da933c2acec80e
2021-05-31 16:41:13 +02:00
Jan Kundrát
469c0f5218 Merge changes If2545b5d,I3b182f1a,I77494833
* changes:
  Add OpenROADM example network
  Add OpenROADM equipment config file
  Update gain_min of OpenROADM ILAs in eqpt_config.json to match MSA spec
2021-05-31 14:38:15 +00:00
Jonas Mårtensson
830ed22690 Add OpenROADM example network
Change-Id: If2545b5d102778404b44a11576054284eb52bea6
Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
2021-05-31 15:59:48 +02:00
Jonas Mårtensson
a386262bfd Add OpenROADM equipment config file
The config file has the following properties:

* Includes only OpenROADM EDFA types (ILA / booster / preamp) and sets
allowed_for_design to true for ILAs.

* Sets ROADM restrictions to OpenROADM booster and preamp.

* Adds an OpenROADM transceiver type_variety with mode parameters
following the MSA spec.

* Sets other parameters (power_dbm, padding, add_drop_osnr, etc.)
according to OpenROADM MSA spec.

Using this config file together with auto-design should result in an
"OpenROADM compliant" network. Specifically, compliant fiber input
power levels for 50 GHz spacing are obtained by setting power_dbm = 2
and padding = 11. For other spacings than 50 GHz, power_dbm should be
changed accordingly.

Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
Change-Id: I3b182f1abcc22fd77d7ec073a6c87fad320957ae
2021-05-31 15:59:48 +02:00
Jan Kundrát
ede3c1a943 Merge changes I58d7e13a,Icf9a33db
* changes:
  CI: produce a HTML report with all linter warnings
  tox: do not pass envlist
2021-05-28 19:50:18 +00:00
Jan Kundrát
af767dd38a CI: produce a HTML report with all linter warnings
Change-Id: I58d7e13a20bd114277c6267653d44897c221526b
Depends-on: https://review.gerrithub.io/c/Telecominfraproject/oopt-zuul-jobs/+/517864
2021-05-28 20:36:39 +02:00
Jan Kundrát
6dcc5a8524 docs: document the f_min/f_max idiosyncrasies
Thanks to Jonas for pointing this out during the review of the OpenROADM
patches.

Change-Id: I4e3f973c9a4d4d01565210dd22bfec84794f0a26
2021-05-28 19:21:59 +02:00
Jan Kundrát
7b5878e2f2 tox: do not pass envlist
...because it's ignored by the CI, and it's kind of up to the invoker to
specify which env they want. We have not relied upon the multiple
environment feature of tox.

Change-Id: Icf9a33dbb5e3df641bd85e3aa7482dfb85f13e5f
2021-05-27 19:41:55 +02:00
Jan Kundrát
8c0eac1bdc Merge changes If02e7f18,I9eec3a10
* changes:
  tests: activate mccabe the complexity checker
  CI: flake8: check invalid "noqa" comments
2021-05-26 23:56:52 +00:00
Jan Kundrát
d09938c1b8 Merge "Fix wrong parameter name in error message raised in compute_nli" 2021-05-26 23:56:41 +00:00
Jonas Mårtensson
dba4da0169 Fix wrong parameter name in error message raised in compute_nli
The error message was refering to method_nli which does not exist. The
correct parameter name is nli_method_name.

Change-Id: I24f24a2c5251317e1a80dda60aa27ec151628172
Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
2021-05-26 22:29:34 +02:00
Jan Kundrát
998249be61 Merge "Round fiber length to two decimal places in Fiber string representation" 2021-05-26 09:32:53 +00:00
Jonas Mårtensson
ebdba47660 Round fiber length to two decimal places in Fiber string representation
The __str__ method of the Fiber element class rounded the fiber length
to an integer but then formatted it with two decimal places, which
doesn't make sense. With this patch, two decimal places are kept.

Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
Change-Id: I03b886dff7ba624929ccc85b4d77d8d6a7cbcfb4
2021-05-26 10:47:21 +02:00
AndreaDAmico
6072203afb Fix z position array creation within Raman solver
The Raman solver gave the wrong loss profile when the fiber length was
not a multiple of the simulation parameter space_resolution as,
in this case, the fiber termination position was not included within
the considered z position array and the output loss profile was
evaluated at the wrong position.

Additionally, the Raman solver failed when the simulation parameter
space_resolution was greater than the fiber length as the z position
array contained only one element.

With this version the fiber termination position is always included
in the z position array and is composed of multiple uniformly spaced
positions and the final position (in general, the latter is not
uniformly spaced).

Example:
* fiber_length = 5, space_resolution = 4 => old version z = [0, 4]
                                          => new version z = [0, 4, 5]

* fiber_length = 5, space_resolution = 6 => old version z = [0]
                                          => new version z = [0, 5]

Alternative:

z = linespace(0, fiber_length, int(ceil(fiber_length/space_resolution)))

PROS
* Solves the first issue
* Returns a uniformly spaced z position array (there is not a
  straightforward advantage in the simulation)

CONS
* Does not solve the second issue
* It is slightly more involved

Change-Id: I8886c3563ac7305c49cb5915712777ef561c5d4f
Bug: https://github.com/Telecominfraproject/oopt-gnpy/discussions/400
2021-05-25 16:16:39 +00:00
EstherLerouzic
b867c57bee bugfix: don't check a reversed path that has no baudrate
without this change if a request was blocked on main path due to 'NO_FEASIBLE_BAUDRATE_WITH_SPACING'
and if the request was bidir, there was a propagation tentative on the reversed path
despite the fact that no baudrate was selected, which ended up with a program crash.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ie4e578aab944e534d8b2d99fb02c4e28a242e717
2021-05-20 16:53:16 +02:00
Jan Kundrát
4396a4efe9 docs: link to patches-in-progress in GerritHub from the README
Change-Id: Ie0e302c96973e26fafe61d4160e135fee23e7bc1
2021-05-20 16:24:55 +02:00
Jan Kundrát
afe686c666 GitHub: link to a faster landing page in GerritHub
The dashboards have changed in Gerrit 3.4 which got deployed to
GerritHub earlier today. Now there's no pagination and no is:mergeable
operator. Let's just link to a (paginated) list of all open changes,
that's probably better value for now.

Change-Id: I22ad68becfc33d3829bcd8aaccb5203e76faeded
2021-05-20 15:31:49 +02:00
Jonas Mårtensson
e0faf6107d Fix order of except clauses in cli_examples.py
ParametersError is a sub class of ConfigurationError so the
corresponding except clause should be placed before. Otherwise the
ConfigurationError will be matched first instead of the more specific
ParametersError.

Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
Change-Id: I67156dd7321101693fdf061d77937d4e75462593
2021-05-20 11:43:56 +02:00
Jan Kundrát
441f566964 tests: activate mccabe the complexity checker
It turns out that my text editor has been warning about "excessive code
complexity" via the python-language-server plugin that uses pycodestyle
underneath. As the test suite is configured to use `flake8` instead,
let's make sure that the results are consistent, and configure the code
complexity threshold for the CI linter run as well.

I'm not sure if this is usable when run incrementally, though (such as
in the CI). I *think* that `flake8 --diff` disregards warnings issued on
lines which have not been changed in the corresponding diff, while
mccabe reports its warnings for the line with the function signature --
and that one is not included in the output of `git diff -U0`. As a
result, I suspect that if a patch increases the code complexity of a
function over the threshold, our CI setup might not report that.

However, a non-diff run of the linters via `flake8` will now start
reporting C901 warnings. For those using `python-language-server` to
integrate with their IDEs and text editors, install `pyls-flake8` to
preserve the existing functionality.

Change-Id: If02e7f189514077aca3e865e1882a4a3fabb4dba
2021-05-16 18:21:22 +02:00
Jan Kundrát
2ca92f1aaa CI: flake8: check invalid "noqa" comments
There are some (unmerged) patches which selectively mute some linter
warnings via the `# noqa: something` stanza. It makes sense to configure
the linter in such a way that it checks the format of that `something`
to make sure that the linter override is valid and selective.

Change-Id: I9eec3a1024d3df88f4f44d4df746ff514670f71f
2021-05-16 18:21:22 +02:00
EstherLerouzic
c4235fa61c Add a test case for the case of 2 adjacent fibers
make sure that their loss is not concatenated

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I63678dd5b72f7f6984101c4367320f3f981cb573
2021-05-12 13:07:47 +02:00
Jonas Mårtensson
41c53fbc5a Update gain_min of OpenROADM ILAs in eqpt_config.json to match MSA spec
Change-Id: I77494833d76cad6759e791ee1de6de025024f114
Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
2021-05-12 09:40:29 +02:00
Jonas Mårtensson
44f8cdbf20 Fix span loss calculation for auto-design
I believe a previous commit, 3ac08f5, changed the behaviour of span
loss calculation in an unintended way, since now it adds the loss of
consecutive fiber elements even when there is no fused element in
between. This means for example that no padding is added when the loss
of consecutive fibers is higher than the padding specified in the
equipment file even though inline amplifiers will be added between the
fibers in a later step. This patch changes the conditions in the next_
and prev_node_generator so that they stop when two consecutive fibers
are found.

Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
Change-Id: I42c9188c789a98a9b3d7e51d5aae15774d40dde7
2021-05-12 09:19:05 +02:00
Jan Kundrát
07ef8e4e10 Fix (some) pep8 warnings
Change-Id: I3fd709b0b12617d534ce9edd5b287539ee036b38
2021-05-11 11:48:36 +02:00
Jonas Mårtensson
bf0e435542 Include ILA nodes when converting from xls to json
Fix GitHub issue #217

Currently, if a user specifies an ILA node in an xls file, including
city name and coordinates, but does not specify type of amplifier,
etc., in the Eqpt sheet, the ILA node is not preserved when converting
to json. This patch proposes to include all ILA nodes to prevent loss
of information.

Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
Change-Id: Id169348cce185e4d33d5b80068270b36043e3353
2021-05-11 11:35:00 +02:00
Jan Kundrát
b688493e98 Merge "Specifying a list of EDFA type varieties for auto-design" 2021-05-11 09:27:58 +00:00
Jan Kundrát
1ad01963c8 Merge "Better positioning of fibers after splitting" 2021-05-07 14:56:15 +00:00
Jan Kundrát
493de58e65 Merge changes Ifc3ec5f9,I7344ff53,I2971b975,Ia2ee3fdd,Ie57340d4, ...
* changes:
  equipment: make sure all OpenROADM EDFAs have "openroadm" in their names
  Introduce OpenROADM preamp and booster models
  The "openroadm" NF model only applies to inline amps
  docs: OpenROADM-ILA parameters in the JSON equipment library
  docs: JSON: do not claim that the default NF implementation is "advanced_model"
  docs: line wrapping
2021-05-07 14:03:51 +00:00
Jonas Mårtensson
7e97547774 Better positioning of fibers after splitting
Currently, calculated new fiber coordinates, after splitting a fiber by
auto-design, are evenly distibuted. Since coordinates for added inline
edfas are the midpoint between neighboring nodes, this makes the edfas
"look" non-equidistant even if all spans have the same length. I think
it would make more sense to have the fiber coordinates represent the
midpoint of the fiber. That way, the edfa positions will look more
"natural". Here is an attempt to illustrate the difference for a link
with three fiber spans:

Before this patch:

r-----f--e--f--e--f-----r

After this patch:
r---f---e---f---e---f---r

r = roadm
e = edfa
f = fiber

Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
Change-Id: I6eafe3fcd4c718b0b995a046dbff0fd04bdc42d7
2021-05-07 08:53:16 +02:00
Jan Kundrát
0f73a8f810 equipment: make sure all OpenROADM EDFAs have "openroadm" in their names
This could be (potentially) annoying to those users who rely on the
default equipment library. However, it brings at least some order into
the current state -- which was rather disorganized.

Suggested-by: Jonas Mårtensson <jonas.martensson@ri.se>
Change-Id: Ifc3ec5f9e0e2526b8621d905160fc82af6a469f2
2021-05-06 21:10:43 +02:00
Jonas Mårtensson
fa834338ab Introduce OpenROADM preamp and booster models
The NF calculated by the preamp model is compliant with the MW-MW noise
mask in the OpenROADM MSA spec. The booster is noise-free, which is
modeled by setting the NF to zero (-inf in dB units). This is obviously
unphysical but it is the simplest way to model the total noise
contribution from a ROADM, including preamp and booster, that is
compliant with the the OpenROADM MSA.

This also introduces two new EDFA type varieties,
"openroadm_mw_mw_preamp" and "openroadm_mw_mw_booster" in the equipment
library. I would prefer to also change the names of the existing
"openroadm" type_def and "standard"/"low_noise" type_variety,
representing an OpenROADM inline-amplifier, for better consistency but
this probably needs to be discussed first.

Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
Change-Id: I7344ff53623f166649efb389c95c04ff92718e35
Signed-off-by: Jan Kundrát <jan.kundrat@telecominfraproject.com>
Co-authored-by: Jan Kundrát <jan.kundrat@telecominfraproject.com>
2021-05-06 19:54:59 +02:00
Jan Kundrát
fc82f43b89 The "openroadm" NF model only applies to inline amps
Change-Id: I2971b97506c8d0a778b3007fd5bd092c3ba83601
2021-05-06 19:54:19 +02:00
Jan Kundrát
3d9d5d7a8d docs: OpenROADM-ILA parameters in the JSON equipment library
Change-Id: Ia2ee3fdde1c4eed0b7ef1de77153959230ba1c01
2021-05-06 19:54:17 +02:00
Jan Kundrát
eef2cdc81c docs: JSON: do not claim that the default NF implementation is "advanced_model"
As Jonas pointed out in Ia2ee3fdde1c4eed0b7ef1de77153959230ba1c01, the
documentation was wrong and the default NF implementation was not the
advanced_model. Let's not describe what the backwards-compatible
behavior is (we do not want our users to rely on that), and instead just
say that "adavnced_model" activates, well, the advanced model.

Change-Id: Ie57340d491a6f73d696d77c07091f85952cb4a08
2021-05-06 19:53:32 +02:00
Jan Kundrát
487ca8c2d6 docs: line wrapping
The numbered list was very hard to read; split that into one sentence
per line. Also do that everywhere else but in the tables (in RST I'm
afraid this would be super-painful).

Change-Id: Ib80c05b66cbc98af2d0dda612943f91d923425b0
2021-05-06 19:51:45 +02:00
Jan Kundrát
ec66d628f0 CI: do not "fail" branches upon coverage decrease
Right now the project homepage on GitHub shows an red failure due to
[1]. While I agree that coverage reports are a useful metric, they are
most relevant when considering patches (or changes) on their own. I do
not think it makes any sense to show them on branches. When we merged
that commit, the reviewer had the info about the coverage change, and we
just do not have 100% coverage. Let's not pretend that that is a
blocker.

[1] 924c56850d

Change-Id: I652ada3357e521c9a3351faac2f9c2e8e4aa5773
2021-05-06 17:02:33 +02:00
Jan Kundrát
924c56850d Merge "Properly remove duplicate links in XLS conversion" 2021-05-04 09:32:55 +00:00
Jan Kundrát
21385cbf03 Merge "docs: Fix a typo" 2021-05-04 08:14:20 +00:00
Jan Kundrát
87c617b602 Merge "Better naming and location of Roadm preamp/booster Edfas in auto-design" 2021-05-04 08:13:40 +00:00
Jonas Mårtensson
4fce4ea7d8 Simplify plotting code
Remove unused code.

Change-Id: I2d3dc62d578912b69d3b5d45634ba5d3f271538d
2021-05-02 23:11:44 +02:00
Jonas Mårtensson
2ddbd961ff Fix plotting bug
See GitHub issue #391

There has been a change in the networkx drawing API, which means
'figure' is no longer an accepted keyword argument.

Change-Id: I8600e8cd5eb2cb378a529c7857f664c1ebed8337
Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
2021-05-02 11:28:18 +02:00
Jan Kundrát
05a044dc2c Merge changes I6962b9f1,I41a65e89
* changes:
  Detect unconnected nodes via span generators
  Fix bug on iteration within a span
2021-04-30 15:01:32 +00:00
Jan Kundrát
340840840f Detect unconnected nodes via span generators
Change-Id: I6962b9f193723dc7856b324d5da94d2f46b21c06
2021-04-30 16:33:44 +02:00
EstherLerouzic
3ac08f59e2 Fix bug on iteration within a span
The old code assumed that the Fused node only connects Fiber nodes. In a
sequence of Fused - Amplifier - Fused - Fiber, the Amplifier would be
included by a mistake. In addition, the code was not that easy to read,
and it just instantiated StopIteration without raising that (which would
be an error in a generator context). It was also rather strict, failing
if the iterator was requested for an "edge node" (a transponder), and
one of the exceptions was not actually an f-string.

Finally, the span_loss function would occasionally report wrong values
(for example in the provided test case, span_loss("fused7") would say 1
instead of 17).

Fix this by making sure that prev_node_generator() and
next_node_generator() never return anything but Fiber and Fused nodes,
which made it possible to simplify the span_loss() function. This should
now properly account for the accumulated losses of an arbitrary sequence
of Fiber and Fused elements.

I went over this a few times because set_egress_amplifier() calls
span_loss() on a *ROADM* node type. That does not make any sense, and
the code deals with this "properly" by returning a loss of 0 dB. It was
a bit confusing for me to see that it's actually OK to ask for a "span
loss" that's identified by a ROADM.

A side effect of this code is that Fused instances that are isolated
from the rest of the topology no longer raise an exception. I was
thinking about preserving this (because for GNPy, the only element with
no previous or no next nodes are the transceivers, but then Esther's
test topology contains an isolated `fused4` element. If we want to make
this strict, we can do that easily like this:

 --- a/gnpy/core/network.py
 +++ b/gnpy/core/network.py
 @@ -162,10 +162,12 @@ _fiber_fused_types = (elements.Fused, elements.Fiber)
  def prev_node_generator(network, node):
      """fused spans interest:
      iterate over all predecessors while they are Fused or Fiber type"""
      try:
          prev_node = next(network.predecessors(node))
      except StopIteration:
 -        return
 +        if isinstance(node, elements.Transceiver):
 +            return
 +        raise NetworkTopologyError(f'Node {node.uid} is not properly connected, please check network topology')
      if isinstance(prev_node, _fiber_fused_types) and isinstance(node, _fiber_fused_types):
          yield prev_node
          yield from prev_node_generator(network, prev_node)

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Co-authored-by: Jan Kundrát <jan.kundrat@telecominfraproject.com>
Change-Id: I41a65e89eef763f82e41e52bc325ed2d488cb601
2021-04-30 16:03:21 +02:00
Jonas Mårtensson
3bcafc2345 Add some documentation about amplifier tilt setting
It is added to the Excel input files documentation.
(We should also have a topology json input file documentation but it
currently does not exist.)

Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
Change-Id: I3184e36090388155e826d1b09bc9c6bf28d623d0
2021-04-22 15:19:48 +02:00
Jonas Mårtensson
b58c089945 Change sign convention for amplifier tilt
As pointed out in GitHub issue #390, the normal convention for the sign
of amplifier tilt is to define it with regard to wavelength, i.e.
negative tilt means lower gain for longer wavelengths (lower
frequencies). Currently GNPy uses the opposite convention, which this
patch proposes to change.

Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
Change-Id: I8f7829a3b0b0b710f7da013c525630a60b22a2b5
2021-04-21 13:19:56 +02:00
Jonas Mårtensson
a211e305c3 Define tilt target over the full amplifier bandwidth
Currently the tilt_target defined by a user is applied over the band of
propagating channels. This means for example that if only two channels
are propagated, the difference in gain between the two channels will be
equal to the tilt_target, independently of how close the two channels
are in frequency. I think it makes more sense to always define the
tilt_target over the full operational bandwidth of the amplifier.

Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
Change-Id: I4f29de2edc4d0de239b34e0d8d678d964b6a0af3
2021-04-21 12:59:24 +02:00
Jonas Mårtensson
3a72ce84d0 Reverse order of values in example amplifier config files
As identified in GitHub issue #390, the dgt values (as well as gain and
nf ripple values) in example config json files are listed in order of
increasing wavelength (decreasing frequency) while the code assumes
values listed in the opposite order. This patch reverses the order of
values in affected files so that they are consistent with existing use
in the code.

Also, the f_min value in the Juniper-BoosterHG.json file is updated to
match measurement data so that interpolation is performed correctly.

Change-Id: I97a9d2f9be81380d1658bee5fa1ef4def3e1c537
Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
2021-04-20 21:17:26 +02:00
Jan Kundrát
de09b4f8ce docs: Fix a typo
Change-Id: I370f6887872c268416623e93141fca3eb902499a
2021-04-20 17:58:18 +02:00
Jonas Mårtensson
be5519455f Change example file meshTopologyExampleV2.json
Following the change of the corresponding xls file in 60b9256 we should
change also this json file for consistency and to avoid unnecessary
confusion.

Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
Change-Id: Iab12002544ad6b8489d8dfa0511fdce762cc1d7a
2021-04-06 16:06:56 +02:00
Jan Kundrát
f98eb2c10c Merge changes from topic "warning on gain"
* changes:
  Change example file meshTopologyExampleV2.xls
  add warning in case gain over max_flat_gain + extended_gain_range
2021-04-06 10:29:11 +00:00
EstherLerouzic
60b9256f22 Change example file meshTopologyExampleV2.xls
Previous file imposed equipment types inconsistantly with required gain

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: If19c5a0a710edf280fde146bca94c431bb5fe836
2021-04-06 11:53:07 +02:00
EstherLerouzic
94b9c16d67 add warning in case gain over max_flat_gain + extended_gain_range
This is an old pull request rebased and restricted to only raising warning.
The initial work also limited gain, which is finally not a desired behaviour:
an advanced user might want to have this high gain.

the only impact on test is that it raises warnings on almost all amplifiers
on the mesh_topology_exampleV2.xls: indeed all of them are set to low_gain
but without gain specified and the result of autodesign results in higher gains
than supported by this amplifier variety.

This may be confusing for users to see these warnings on an example from gnpy
so I will push a new commit changing the amp types to avoid this.
The alternative would be to push the warnings into the logger, so they
remain invisible, but I think that the example change makes more sense.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Idf0c67137b5b466b07ddc7817f53a82f92a21a5b
2021-04-06 11:52:36 +02:00
Jan Kundrát
eaccd63739 Update minimal required version of Pygments for CVE-2021-27291
Change-Id: I2e3a7f2bf2ef05b318e787909e6e7ec33e72717e
2021-03-30 11:31:24 +02:00
Jan Kundrát
8fcb61f12c docs: fix link to an example file
Relative links within the source tree work, but they were not being
turned into nice usable hyperlink that go back to GitHub under the
generated documentation.

Reported-by: Melin, Stefan M. <Stefan.Melin@teliacompany.com>
Change-Id: I137ad95fa75a6ee5e1b03a252782e6357d36a3af
2021-02-16 20:00:19 +00:00
Jan Kundrát
efd7468d42 docs: cross-reference topology section with XLS/JSON
Suggested-by: Melin, Stefan M. <Stefan.Melin@teliacompany.com>
Change-Id: I01defca88e0355af39fd6f97e5a69fc1bb5f8f73
2021-02-16 18:04:21 +01:00
Jan Kundrát
8e62955bb0 docs: Remove '%3' from graphviz mouse hover tooltips
In the generated SVG files, there was a '%3' shown as a mouseover
tooltip on mouse hover. Apparently that's what ended up in the <title>
of the whole generated SVG document.

This turned out to be an internal thingy in graphviz/dot. In Sphinx
there's already some support for catching element IDs with this '%3'
madness, but apparently titles are not handled like that.

Solve this simply by providing a title for the whole `graph {}` stanza
in the embedded dot graphs.

Reported-by: Melin, Stefan M. <Stefan.Melin@teliacompany.com>
Bug: https://gitlab.com/graphviz/graphviz/-/issues/1327
See-also: https://github.com/sphinx-doc/sphinx/commit/8494638e45
Change-Id: Ia9f39d13748cdffe74f2cb5032f92c77babb20d8
2021-02-16 18:04:21 +01:00
Jan Kundrát
561fd76a20 Upgrade Sphinx
I wanted to make sure that that funny SVG rendering is not a problem of
an outdated Sphinx. It is not, see the next commit. However, there's no
need to stay on a release from 2017, there's 3.5.0 already.

Change-Id: I181cc5d96eae3fadbf93711063e8f969a2f451cb
2021-02-16 00:26:32 +01:00
Jan Kundrát
ccb6653f50 docs: improve Raman description for vendors
Suggested-by: Melin, Stefan M. <Stefan.Melin@teliacompany.com>
Change-Id: Ib8a1b66cc28bddc512ac529f9326490b1092be79
2021-02-16 00:10:21 +01:00
EstherLerouzic
902cfa11a7 Minor refactor
Correct comments

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I99874f08625bade15223cfbbd3cd933419fb5c66
2021-02-04 10:02:51 +01:00
EstherLerouzic
24c6acc027 Refactor step4 of the compute_path_dsjctn
Previous implementation selected last candidate in case both routing
and disjunction constraints could not be applied. The new implementation
elaborates an alternate list where each feasible paths satisfyng
disjunction constraint but not route constraint is recorded. The algorithm
then preferably selects a feasible path that satisfies all constraints and
if none is found and route constraint is LOOSE, the first set of paths
that satisfy disjunction is selected (instead of the last one).

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Iba44397d105006a98539494d821cc83dc3e3bbd9
2021-02-04 10:02:51 +01:00
Jan Kundrát
3a31d458ee Merge "Minor refactor in disjunctions_from_json" 2021-02-03 15:48:35 +00:00
Jan Kundrát
22d55ae881 CI: travis: also test on Python 3.9
Change-Id: I9ee55daacc8ebba1736ad1b6fa5d8888c9daf90d
2021-02-03 16:11:59 +01:00
Jan Kundrát
3324645f78 CI: travis: upgrade to a newer base image
Change-Id: I4c6ee2e894c58a07eea89dd20414b87436e977c2
2021-02-03 16:11:46 +01:00
Jan Kundrát
3014a881f5 CI: Unbreak Travis
...because that one obviously doesn't read bindep.txt, but it has its
own way of installing these dependencies.

Change-Id: I6c2a70095c57686228ae697a06bb82b8c6d47459
2021-02-03 16:10:44 +01:00
Jan Kundrát
35877022ec docs: explain general concepts and the equipment library
Change-Id: I3b18b9695f417a3e9b747fc5ce6fe41946fa55f3
2021-02-03 15:23:04 +01:00
Jan Kundrát
9b985d1fc5 docs: fix copyright string
Change-Id: Ie74216e78861e6f32772177cffd8d51e5029152f
2021-02-03 13:56:43 +01:00
Jan Kundrát
cd95c83bbf sphinx: fix coding style
Change-Id: I01c3b81d9fd5eee5942509fc9e462f0495cab6f1
2021-01-25 11:43:50 +01:00
Jonas Mårtensson
f9dbf7d132 Fix github bug #380
Patch 503833 (Fix calculation of gain for first Edfa after Roadm)
introduced a bug when it was rebased on top of the per degree power
feature since per_degree_pch_out_db used for propagation was actually
updated based on calculated prev_dp value.

Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
Change-Id: I39e8f5945d5035b99c70ef577011bba79bb89a72
2021-01-21 18:28:23 +01:00
Jonas Mårtensson
b37248077c Specifying a list of EDFA type varieties for auto-design
This allows users to limit the choice of type_variety by auto-design
for an EDFA node by setting a "variety_list" attribute in the input
topology json file. One use-case is switchable gain EDFAs where the
two gain ranges can be modeled by two separate type varieties in the
equipment library. A user may know that such an EDFA will be used in
a node but not which gain range is optimal. The choice of gain range
can then be left to auto-design while not allowing any other
type_variety by specifying the node e.g. like this in the topology:

{
  "uid": "Edfa1",
  "type": "Edfa",
  "variety_list": ["foo_gain_range_1", "foo_gain_range_2"],
  ...
}

Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
Change-Id: Ia69ef78f885e3a61310530b6b80da64e43758211
2021-01-21 13:09:48 +01:00
Jan Kundrát
d2a8d8e887 Merge "Support Trx non-Roadm nodes in topology with Roadms" 2021-01-14 17:39:56 +00:00
Jonas Mårtensson
35c4073292 Minor refactor in disjunctions_from_json
Improve code clarity and readability.

Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
Change-Id: I73f0b8c15769b689f35d9e8dc6fee4ee07f7cade
2021-01-13 17:46:14 +01:00
Jonas Mårtensson
b8e72511de Properly remove duplicate links in XLS conversion
The sanity_check function in convert.py removes duplicate links in the
input XLS file. However, it doesn't remove them from the links_by_city
dict. This has two consequences. Firstly, the output json will still
have duplicate connections. Since networkx.DiGraph.add_edge will only
add one edge anyway, this has no major impact. Secondly, sanity_check
will think that a degree-2 ILA node with duplicate links is higher
degree and change it to a ROADM node.

With this patch, duplicate links are removed also from links_by_city.

Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
Change-Id: I4be9ab225bc89277aec467a5bd60216b4aa31993
2021-01-09 17:39:33 +01:00
Jonas Mårtensson
120c326e77 Merge "Bump all dependencies" 2021-01-08 11:16:48 +00:00
Jan Kundrát
01115f9852 Merge "Raise error when type_def for Edfa is not recognized" 2021-01-01 19:52:45 +00:00
Jan Kundrát
b91ea1828f Bump all dependencies
I think it's "healthy" to sync up the list of minimal versions of our
dependencies with what the CI is actually checking, at least every now
and then. We're getting some variance via the list of different Python
interpreters, but still -- let's make sure that our dependencies match
what we're testing.

The only interesting case is scipy where the 1.6 release started
requiring Python 3.7. Let's stick with 1.5.x, which is the last version
supported on Python 3.6.

Change-Id: I4aa0a89e7c615f2095a951ff522a4838ef50178e
2021-01-01 20:16:51 +01:00
Jan Kundrát
d2a294ac5a Bumpy numpy for Travis CI
On Travis, builds with Python 3.7 started failing recently:

```
 ERROR: pandas 1.2.0 has requirement numpy>=1.16.5, but you'll have numpy 1.16.4 which is incompatible.
 ERROR: scipy 1.6.0 has requirement numpy>=1.16.5, but you'll have numpy 1.16.4 which is incompatible.
```

Apparently the version of numpy that gets used when under Travis is
rather different among their Python versions, and we get:

- numpy-1.19.4 in their Python 3.8.6 env,
- numpy-1.19.0 on 3.6.7,
- numpy-1.16.4 on 3.7.1

That's a bit insane to my liking, perhaps they're preloading popular
libs such as numpy into their images for speed ups? For comparison, on
Zuul CI we have this:

- numpy-1.19.4 with Python 3.8.6 on Fedora 32,
- numpy-1.19.4 with Python 3.6.8 on CentOS 8

Let's start requiring numpy 1.19.4 everywhere. This is the cost we're
paying for https://github.com/Telecominfraproject/oopt-gnpy/pull/268 .

Change-Id: I6f1167096cfadc415cf456ad09ff0a08b535fc08
2021-01-01 19:55:13 +01:00
Jan Kundrát
f41acf31f6 Merge "Don't call sys.exit() from library functions" 2021-01-01 18:41:41 +00:00
Jan Kundrát
8cef09158f Merge "Error out on conflicting Fiber and RamanFiber definitions" 2021-01-01 18:16:30 +00:00
Jonas Mårtensson
549e04e925 Better naming and location of Roadm preamp/booster Edfas in auto-design
Currently when an Edfa is inserted by auto-design after a Roadm (i.e.
booster) it gets the same city attribute as the Roadm while an Edfa
inserted before a Roadm (preamp) gets the city attribute from the
preceding fiber. This is illogical and confusing. Also both the Edfa
preamp and booster get coordinates different from the Roadm (halfway
between the Roadm and the neighbor node). Since in practice the preamp
and booster are always colocated with the Roadm I think it makes more
sense to give them the same coordinates.

Also change how uid is assigned to an Edfa connected to a Roadm so that
it indicates whether it is a booster or a preamp.

Change-Id: I98718fe1e2914b5628e7cfd23fc28fb5708a8889
Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
2020-12-28 21:00:44 +01:00
Jonas Mårtensson
918c19b1bc Raise error when type_def for Edfa is not recognized
When loading the equipment file in json_io.py we should raise an error
if an Edfa type_variety specifies a NF type_def that is not
implemented. This should also allow to remove the assert statement in
the _nf method in the Edfa class.

Change-Id: Ida0bb19829c0ee54ecbe3e2f74ea7c22eb24f6a2
Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
2020-12-21 22:25:44 +01:00
Jonas Mårtensson
6820a3fc36 Don't call sys.exit() from library functions
I think it's better to raise an exception instead like we do for other
errors.

Change-Id: If6dd795bd76471b2534d873772e991d9ae0a4271
Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
2020-12-21 14:38:50 +01:00
Jonas Mårtensson
7e8ed590eb Support Trx non-Roadm nodes in topology with Roadms
Currently, auto-design does not work for an OMS starting from a Trx
that is not connected through a Roadm if the topology also contains one
or more Roadms. I don't see a good reason not to support this case,
since a Trx not connected through a Roadm can make sense, e.g. for a
degree-1 node. This is a proposal to remove the restriction.

Change-Id: I14686521a838b30249126b9bd403fa26c848875a
Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
2020-12-21 14:10:35 +01:00
Esther Le Rouzic
4218b7ef44 Merge "correction of the excel to json conversion of per degree" 2020-12-17 13:57:45 +00:00
Jan Kundrát
87af343b38 Merge "Include operational parameters in RamanFiber to_json method" 2020-12-17 10:44:59 +00:00
Jonas Mårtensson
26cd33b4dc Include operational parameters in RamanFiber to_json method
Currently, the RamanFiber class does not implement its own to_json
method but inherits it from the parent Fiber class. This means that
operational parameters (temperature and raman_pumps) are not included
(and therefore not picked up by the network_to_json method in
json_io.py). So if a user saves the topology, e.g. using the
--save-network option, and later uses that saved topology as input,
the result will be wrong.

This patch includes the operational parameters in to_json.

Change-Id: I07c09a4d122858ff412373623d8c0a087a3e11ec
Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
2020-12-14 09:28:29 +01:00
Jonas Mårtensson
861724ef4f Detect loops in network topology
Currently, if an input topology contains a loop in an OMS, the
set_egress_amplifier method in network.py will go into an infinite
loop. With this patch, such a loop is detected and an error is raised.

Change-Id: Id7cd0cc6d7eaff3af1d9e0309b5c2eb90aeb7454
Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
2020-12-11 11:08:54 +01:00
Jonas Mårtensson
86492cff60 Check that nodes are properly connected in network topology
In network.py we are already checking that fibers are properly
connected. Let's check Edfas and other node types as well.

Change-Id: I224b9046729197fef3eb172e9631969a2da13ab5
Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
2020-12-11 09:12:34 +01:00
Jan Kundrát
27fd5cdad6 Error out on conflicting Fiber and RamanFiber definitions
The equipment library has, so far, used completely different namespaces
for `Fiber` and `RamanFiber` definitions. It was possible to define a
"SSMF" fiber whose properties, such as CD or PMD, would differ when used
as a Fiber vs. the RamanFiber object in the networking topology. That is
likely a bug of the equipment library, so this patch makes sure that a
configuration like that cannot be used.

I came across this when working on the YANG support where both fiber
types are defined in a common namespace, and the difference between them
is determined by lack or presence of a sub-container with the Raman
properties.

Change-Id: I8e86bed80eb1794b8abd4e1ecd96398d395f81f2
2020-12-03 15:08:55 +01:00
EstherLerouzic
2fc444be4b correction of the excel to json conversion of per degree
The patch correction changing the params
from
per_degree_params: { to_node: xx , target_pch_out_db: yy}
to
per_degree_pch_out_db: {xx: yy}

had not been updated on convert.py for reading the excel input.

the commit also fixes the automatic tests with the correct version

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I17a5cfad18e1b570a7aaa218e932368fa80f2d37
2020-12-03 14:49:53 +01:00
Jonas Mårtensson
d3490ae30c Raise error if specified Edfa type_variety is missing in eqpt config
A recent patch introduced the possibility to define an Edfa in the
topology file without specifying its type_variety:

https://review.gerrithub.io/c/Telecominfraproject/oopt-gnpy/+/488967

But with the current implementation, if a user specifies a type_variety
that is missing from the equipment configuration file (e.g. because of
a spelling mistake) this is silently ignored and the type_variety is
instead selected by auto design. I think this is not desired since it
can lead to confusing results. This patch proposes to raise an error
when the specified type_variety is missing while still allowing the user
to not specify type_variety or set type_variety = '' for selection by
auto design.

A recently introduced test actually does exactly this, i.e. it defines
Edfas with type_variety = 'std_high_gain' even though this type variety
does not exist in the equipment config file used by the test. Therefore
this patch also modifies the topology file used by that test.

Change-Id: I7d2a1aa6d633b62d51a99b07e8270cafcbad505f
Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
2020-12-01 21:58:56 +01:00
Jan Kundrát
59c3895a51 Merge "Remove while loop to avoid infinite loop" 2020-11-24 16:27:22 +00:00
Jan Kundrát
11bc41b941 Merge "cleaning: minor changes and specific numpy imports in utils and science_utils." 2020-11-19 15:22:02 +00:00
AndreaDAmico
9a7f94a391 cleaning: minor changes and specific numpy imports in utils and science_utils.
Change-Id: I57cd9075dd0a523a90131fbd8747519cf6554900
2020-11-19 14:57:57 +00:00
Jan Kundrát
6487b98136 Merge changes Idc473762,I004de102
* changes:
  Fix calculation of power target for Edfa in gain mode
  Fix calculation of gain for first Edfa after Roadm
2020-11-17 13:35:26 +00:00
Jan Kundrát
15df99510f plot: Show something useful for missing city names
This makes it possible to render at least something on tiny topologies
now that YANG doesn't support city labels.

Change-Id: I1431b557b2eecd34bf24557fdee0da0f2c2c0487
2020-11-10 14:43:52 +00:00
Jonas Mårtensson
3d5b1fcf64 Fix calculation of power target for Edfa in gain mode
See GitHub issue #368

The out_voa attenuation of the previous Edfa is currently not taken
into account when calculating power target for an Edfa in gain mode.
This makes the calculated gain target (in case of autodesign) for
the following Edfa in the chain incorrect and also impacts automatic
amplifier selection.

Change-Id: Idc473762ccf7b021a0885c7ce20de1abb66eb075
Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
2020-11-03 21:40:38 +01:00
Jonas Mårtensson
928bc42cb9 Fix calculation of gain for first Edfa after Roadm
See issue reported in #360

In autodesign, currently the calculation of gain for the first Edfa
after a Roadm is incorrect when the reference channel power is
different from 0 dBm. The bug is somewhat hidden by the fact that the
gain is anyway updated during propagation in power mode, taking the
reference channel power into account. But the gain reported by the
to_json function of Edfa elements before propagation will be wrong.
And more seriously, the incorrect gain will impact the Edfa selection
in autodesign.

Change-Id: I004de102832c3a0786435e21e71b0444d8901604
Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
2020-11-03 21:34:45 +01:00
EstherLerouzic
643680ec47 add a set of test to check power equalization of roadm
Check that egress power of roadm is equal to target power if input power
is greater than target power else, that it is equal to input power.
Use a simple two hops A-B-C topology for the test where the prev_node
in ROADM B is either an amplifier or a fused. If it is a fused, the target
power can not be met.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I3388f060a4f364055d58c8ca7c2b59143f784fa8
2020-11-03 16:44:28 +01:00
EstherLerouzic
a4a144a319 Add tests for the per degree feature
- add a test on the json conversion in case of a ROADM sheet
- test the per per_degree_pch_out_db is correctly created with specified
  values or default.
- also tests that the convert correctly creates the correct equipment
  only if the entry exists in eqpt sheet.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ic006d9c741404b185d15678953d2801cd17bab97
2020-11-03 16:44:28 +01:00
EstherLerouzic
093085fba8 adding a roadm sheet to handle per degree info in roadms
This part only targets conversion from an xls input topology file.
In order to define per degree power, the convert function needs to know
the booster final name.
However before this change, the booster name may not be known if there
is no defined amplifier in eqpt sheet at this stage.
In order to solve this ambiguity, the final name are defined in the convert
function provided that the direction is defined in eqpt sheet and
even if the amp type is not defined.

Then the per degrre target power is defined in a new roadm sheet using
the same direction naming as for Eqpt sheet.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I8f279aa880aa0a8ceb60e48e43bddb0f6ff06147
2020-11-03 16:44:28 +01:00
EstherLerouzic
c56ea898a6 Add per degree channel power target out
- add the per degree info using the EXACT next node uid as identifier
  of the degree when a node is a roadm
- add the degree identifier on the propagate and on the call functions
- use the per degree target_pch_out_db defined in json entry for the
  target power in network build
- verifies existence of the per degree power target in order to support
  partial per degree target power definition
- correct test data files for expected auto design results that now
  should include the per degree information, even if it is the same
  for all degree.
- in order to enable per degree power definition on direction where
  booster is not defined, enable the declaration of edfas in json without
  specifying type variety

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I5004cbb250ca5fd6b6498ac9d4b9c4f28a65efee
2020-11-03 16:44:21 +01:00
Jan Kundrát
a5398a5c57 docs: fix a broken link
Reported-by: Melin, Stefan M. <Stefan.Melin@teliacompany.com>
Change-Id: I8b9b6939c340b1856f1304f56880526b0f578914
2020-11-02 19:54:56 +01:00
EstherLerouzic
6dd40935b7 Remove while loop to avoid infinite loop
In the previous implementation, when a constraint was added on top of
the disjunction, there could be an infinite loop because the test was
not correctly performed on the request_id but on a request class.
Moreover, there the loop was not needed since the first feasible
candidate is selected if it exist.
This patch removes the loop and adds some comments to explain the code.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Icdbee9032f28214b3e03cb62d55ea353477d94bf
2020-10-21 15:17:08 +02:00
Jan Kundrát
e6ee512001 Explicitly consider "system margins" instead of stashing them to transponder modes
Since 30234f913c, the code just added the
"system margins" to each transponder's minimal required OSNR. That's
simple and straightforward, but I think that mutating "equipment
library" in response to a "global simulation parameter" is not really
the right way to go.

Make this explicit; always check the resulting OSNR against the
transponder's minimum plus the margin.

I got into this when checking the fixups that are performed within the
JSON loader. I don't think that the JSON loader is an appropriate place
for this.

Change-Id: Ic8f8385cbbb29dc0d769462f17caad47c2b36940
2020-09-15 10:04:15 +02:00
Jan Kundrát
e13d27c1f5 Merge "docs: link to a Gerrit tutorial for contributors" 2020-09-08 18:32:13 +00:00
Jan Kundrát
bb552fbdd6 Merge "XLS: improve consistency checks" 2020-09-08 18:22:36 +00:00
Jan Kundrát
ed8a3dd933 Merge "docs: distinguish "equipment parameters" from "simulation parameters"" 2020-09-08 14:51:30 +00:00
Jan Kundrát
3204077a6c XLS: improve consistency checks
- do not talk about just "Nodes" and "Links" when also checking "Eqpt"
- don't check for non-existing "Nodes" from "Links" when that's already
  done elsewhere (and improve that check's error message)
- when checking "Eqpt", verify not just "from_city", but also "to_city"

Change-Id: I2e926049fa5e3c4dcb08cc29f18970a3b3b077d8
2020-09-08 16:48:26 +02:00
Jan Kundrát
85d1bf4e1e docs: distinguish "equipment parameters" from "simulation parameters"
This was identified during today's coders call where Andrea asked what
the best place for documentation of `sim_params.json` is. Let's split
docs about tangible equipment from those of global "simulation options".
Of course these options are still done in `eqpt_config.json`, which
might get super-confusing to the user -- so please make sure that this
is correctly explained when adding docs for `sim_params.json` in future.

Change-Id: If43894e8f562ca8a768b0efb6cc6c1afeb4aa514
2020-09-02 00:52:20 +02:00
Jan Kundrát
42edb2e6b9 docs: XLS: improve description of the "Eqpt" sheet
Change-Id: I57288798298563cfcc7d014a716bf549721db035
2020-09-02 00:45:42 +02:00
Jan Kundrát
21174a4190 Merge "Fix bug when calculating new coordinates in split_fiber" 2020-08-31 21:21:42 +00:00
Jan Kundrát
f6c2da24cd docs: link to a Gerrit tutorial for contributors
I've already updated the wiki pages, so the onboarding guide is
"correct", but a bit verbose. Let's just try to make the contributor
experience streamlined a wee bit.

Let's also use a GitHub PR template so that people are aware of Gerrit.

Change-Id: I44fb095f14396c7ba49494c32b6215f6a29ade2b
2020-08-31 23:08:59 +02:00
Jonas Mårtensson
9f16aaac61 Fix bug when calculating new coordinates in split_fiber
The current implementation based on scipy interp1d fails when
predecessor and successor of the fiber to be split have the same
longitude. In this case the new latitudes become NaN. This patch
fixes the bug.

Change-Id: I7c5dc4d410630a6b4b773d36cc192db8271a4346
Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
2020-08-24 21:55:33 +02:00
Jonas Mårtensson
29fc9d7dac Handle exceptions in cli_examples when calling build_network
Since build_network can raise NetworkTopologyError and
ConfigurationError we should handle these in cli_examples instead of
crashing.

Change-Id: I4b84831c74be7f1c88253c938f3f67b2d204630e
Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
2020-07-28 23:06:18 +02:00
Jonas Mårtensson
be3af5c2e5 Handle network topology error in add_connector_loss function
Other functions used be build_network raises NetworkTopologyError when
a fiber is not properly connected but this handling was missing from
add_connector_loss.

Change-Id: Id08cd4a9bad15f755d364a31ff3d38993d034447
Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
2020-07-28 22:56:21 +02:00
Jan Kundrát
e0e9ebde28 CI: Prefer Python 3.8 and Fedora 32 over EL8
The first build was much faster, there was about 50s in the actual
pytest invocation time. Overall, the total time is about a minute
quicker, which is nice. I cannot qualify whether the improvement is due
to a 1g-1c -> 2g-2c VM flavor underneath, or if it's that newer Python
*and* updated compile options in Fedora -- but it's a nice improvement.
The downside is twice the cost of the VM hour.

Depends-on: https://review.gerrithub.io/c/Telecominfraproject/oopt-zuul-jobs/+/497370
See-also: https://fedoraproject.org/wiki/Changes/PythonNoSemanticInterpositionSpeedup
Change-Id: I6f5db61e9481170515b2f7ff4f3358fae5daa68e
2020-07-09 13:39:55 +02:00
Jan Kundrát
5dc16a39c5 CI: Build with Python 3.8
Now that we're using new enough Pandas, it is actually safe to start
building on Python 3.8 as well.

Depends-on: https://review.gerrithub.io/c/Telecominfraproject/oopt-zuul-jobs/+/497368
Change-Id: I9b0371e9fc0a094f064c7e978bbcce984facfb30
2020-07-09 13:24:59 +02:00
Jan Kundrát
416da5c60b Update Pandas for better Python 3.8 compatibility
I kept wondering why installations on Python 3.8+ kept failing in the
CI, and I assumed that it was because the Pandas project somehow got
their homework wrong and did not provide a "wheel", which is a Python
thingy for prebuilt binaries. That's however not the case, and the
reason was simply that our Pandas version pin was too low, predating the
time when Python 3.8 was released.

Solve this by updating the Pandas requirement to the most recent one,
and now there's no need to mess with anything. Yay!

Thanks-to: https://github.com/mars-project/mars/pull/1332
Change-Id: Iceb31ae16aa911ebef67a938a3d2a524faad164f
2020-07-08 12:18:33 +02:00
Jan Kundrát
f8047f9afe docs: remind users that the pip command ends with a dot
Thanks to Tomáš Horváth from CESNET for volunteering for a test install.

Change-Id: Ieaa4baa92df19b8e39e2d33176a5a2af9685d40f
2020-07-08 11:56:55 +02:00
Jan Kundrát
9e91933106 Merge "network.py code cleaning and minor optimizations" 2020-07-06 23:42:26 +00:00
Jan Kundrát
7407e6809b docs: Fix a non-existing link
Thanks to Stefan for reporting this.

Reported-by: Melin, Stefan M. <Stefan.Melin@teliacompany.com>
Change-Id: I9ab3aa5f829ffe3ef722df2d46f1393f748a52dc
2020-07-02 17:29:28 +02:00
Jan Kundrát
56f66779f9 docs: fix a typo
Change-Id: I75448f00dcd1b77e30860dc3fee9524b100a8cb8
2020-07-02 17:27:10 +02:00
Jonas Mårtensson
2704c56e50 network.py code cleaning and minor optimizations
Change-Id: I9228c661df97552af3fbdbd6f58b2432ada7b6ef
Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
2020-06-26 17:29:17 +00:00
Jan Kundrát
ba4cc1ceef trove: let's stop calling us "alpha" when we consider ourselves as stable
Change-Id: I2c497e4804e3c521e23a0501876a61dbbef27fe6
2020-06-26 18:58:55 +02:00
Jan Kundrát
8396cea652 trove: add more target categories for this SW
Change-Id: Ic565196a6272190845d58dab3b6c06d128bea192
2020-06-26 18:58:25 +02:00
Jan Kundrát
2b1029f3b6 trove: indicate all Python versions that we're currently testing for
Change-Id: Ifeb6690c46e036f902137bd1e63e49a94f4ac3f2
2020-06-26 18:57:31 +02:00
Jan Kundrát
8e2709490f CI: Travis: test on Python 3.8 as well
Change-Id: I57841e200628410f9edcea481548eee25d550543
2020-06-26 18:19:06 +02:00
Jan Kundrát
ebf8249154 CI: travis: fix some warnings
sudo is a no-op these days, and let's put in that default linux OS
thingy to silence an info message, too.

Change-Id: I95d5b842932345025adbe20bd8775fb6dd83030e
2020-06-26 18:19:06 +02:00
Jan Kundrát
aaddffcb2e Install via PIP
There are several differences between `python setup.py develop` and `pip
install --editable .` ; one which became relevant a few days ago is the
fact that `python setup.py develop` is apparently happy to pull in
pre-releases of our dependencies -- perhaps due to the fact that this
package, when installed from git, is also considered a pre-release. This
has led to CI failures in Travis, and for some reason just on Python
3.7, not on Python 3.6.

This is of course rather ugly, and there's no need to start pulling in
pre-releases of various pieces of software that we're using, anyway. Fix
this by asking our users to use PIP, and adjusting the CI accordingly.
Zuul CI uses tox which is documented to call PIP behind the scenes, so
there's no change in there.

Fixes: https://travis-ci.com/github/Telecominfraproject/oopt-gnpy/jobs/353680894
Change-Id: I254066b8dc345e23c061a69d55546d48bac6761d
2020-06-26 18:18:55 +02:00
Jan Kundrát
29d1f8c666 Merge "Remove unused "carrier probing"" 2020-06-25 19:01:09 +00:00
Jan Kundrát
0126645c4d Merge "docs: badges: link to PyPI" 2020-06-25 18:58:37 +00:00
Jonas Mårtensson
1d657d6819 Return spectral info from propagate function
There are two propagation functions in request.py, propagate and
propagate2. The propagate2 function saves and returns spectral infos
from before and after every element of the path. In most cases only the
final spectral info after propagation is needed (there is currently
nothing in the code using anything more). On the other hand, the
propagate function just returns the path which is unnecessary since that
is modified in place. This patch proposes to instead return the final
spectral info from the propagate function.

Since propagate2 is now redundant, it can be removed.

Change-Id: I3a0f7310a7d5f9c93dc5f257e051c7d45e20c6fe
Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
2020-06-25 19:41:03 +02:00
Jonas Mårtensson
0b965d931c Don't include add_drop_osnr when there is no ROADM in path
The parameter add_drop_osnr is specified in the Roadm section of
eqpt_config.json and represents noise added by amplifiers within the
add/drop block of ROADMs. Currently this noise is added to the signal
whether the propagation path includes any ROADMs or not, which does not
make sense to me. This patch proposes to only add the add_drop_osnr when
a path actually includes ROADMs.

See GitHub issue #274.

Change-Id: I58961772c049578eff8879dfb2e53265866d12c4
Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
2020-06-22 10:06:04 +02:00
Jonas Mårtensson
d3eaa4d7ba Include tx_osnr when printing first transceiver
(Migrated from GitHub PR #311)

Currently the output of transmission_main_example shows the first
transceiver having ONSR = +inf even when a tx_osnr has been specified,
which is confusing.

This patch proposes to update the SNR of the first transceiver with
tx_osnr.

Change-Id: Idab7c92c2f5a12cc92ce5c1c551e5710f30e6a02
Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
2020-06-18 21:39:44 +02:00
Jan Kundrát
1dbbc6273b Point the gerrit-review to master
Change-Id: I03d53a69ea529f3b8534a0752b5ee7cabb240c89
2020-06-18 20:30:34 +02:00
Jan Kundrát
efa8b83249 docs: badges: link to PyPI
Change-Id: I3479d0b60a1e411793b81d0c263a51c1db35905b
2020-06-18 16:11:36 +02:00
Jan Kundrát
30599bf63a Merge "coding style: remove dead code, fix up sphinx" 2020-06-18 13:19:55 +00:00
Jan Kundrát
7c14fe02ab docs: badges: Use the stable DOI for the GNPy project
Zenodo offers two kinds of DOIs for GitHub projects:

- a per-release one, always assigned automatically upon tagging a new
release in GitHub,
- a stable one which [always resolves to the latest version at time of
access](https://help.zenodo.org/#versioning).

I think there's value in people citing us as "GNPy", not "GNPy 2.2", for
example, so let's make sure we include this magic-always-newest-but-stable
DOI for this software.

Change-Id: Ia57a94882c74d605e21f55c87b0a74b1d734b5ed
2020-06-18 13:09:44 +02:00
Jan Kundrát
ee92011b21 docs: fix description of gnpy-path-request
Since about f9e0d18 and 94a8f35, we've changed the way how the equipment
config (and also the network topology) is passed around. Update the
README to reflect this.

Change-Id: I338b790fd4d54914c49e5e0aac3f44f2bc9d00ee
2020-06-18 12:14:24 +02:00
Jan Kundrát
9861a22ef9 docs: do not talk about branches anymore
We talked about this during the coders call on 2020-06-02. When this
project started, it was decided to keep the `master` branch essentially
frozen between releases, and concentrate development into the `develop`
branch. Since that time, we've got a decent CI coverage and end-to-end
tests which should guard us against regressions and inaccurate
simulation results. It also seems that our users have a preference to
use tagged releases anyway, so we can get by by deprecating the
`develop` branch.

As agreed during the conf call, from this release on we'll be merging
approved changes directly into the `master` branch, and the `develop`
branch will be retired. We have measures in place that ought to limit
the risk of regression within `master` to an acceptable level.

Change-Id: I0048ba8e36810237667e6930380a9c8570090a26
2020-06-18 11:48:01 +02:00
Jan Kundrát
59f9f35817 CI: provision secrets for uploads to PyPI
Originally I was hoping that this is possible via the parent job
collection (oopt-zuul-jobs), but that's not the case, unfortunately, and
I have to do this in this project.

I created the token at PyPI's own web UI for my account, and saved the
secret to a file. Then I executed Zuul's helper script:

  $ ~/work/prog/openstack/zuul/zuul/tools/encrypt_secret.py \
    --infile secret-pypi --tenant TelecomInfraProject \
    https://zuul.vexxhost.dev/ Telecominfraproject/oopt-gnpy

Change-Id: I05ab853ae26a449212e832e0f7e261c9ed71e364
2020-06-17 23:01:33 +02:00
Jan Kundrát
1bb475671d docs: badges: show code coverage as well
One yellowish item among the badges, now that should make it look legit
and real 🌈.

Change-Id: I13adadb1edc538428d24cc9d50c0569f49c5d7a3
2020-06-17 21:52:09 +02:00
Jan Kundrát
566dedbdbb docs: badges: show code quality via LGTM.com
It gives us an A, so we can link there :).

Change-Id: I0613394e135bf3de3dfd9e984f970328a5aa2fa4
2020-06-17 21:43:08 +02:00
Jan Kundrát
b44c4cec16 docs: boast about the contributor count
...because why not, right?

Change-Id: Ib853d7b3496f2b7d915785e72bfa314bf82a2802
2020-06-17 21:31:06 +02:00
Jan Kundrát
93d11ba408 docs: badges: prepare for a future link to Zuul
Change-Id: Iff5ffa1f6d1623c8d5b612f7d899c4e8f3f7cb85
2020-06-17 21:20:57 +02:00
Jan Kundrát
637670fcfa docs: Move the gnpy-path-requests into README
This looks like something that's been "always" part of the Excel guide.
I think it is better placed in the README. After the releae we migth
want to improve the docs even more, but hey, that's something which
should be done after some discussion, not via these commits that I'm
going to self-approve shortly.

Change-Id: Icd73f4bb3a43f1a684ec7a364e4ebcc9b8e6af88
2020-06-17 21:19:13 +02:00
Jan Kundrát
7836297708 README: point all badges to the master branch
We want to deprecate `develop`, so let's start pointing to master now.

Change-Id: Ibf69c36f44fde7081238508d55137c8df21cfa60
2020-06-17 21:02:21 +02:00
Jan Kundrát
1f8b4ab9a2 docs: Move install instructions into the generated docs
The PowerShellSessionLexer within pygments has troubles parsing the
example as something valid, so let's revert to a generic one.

Change-Id: I188e1d7bf2f7229ad15c1f0443584344fd11bf84
2020-06-17 20:43:37 +02:00
Jan Kundrát
05eb312f4a docs: Do not run rstcheck on sphinx-consumed docs
Turns out that we're already running Sphinx with options that are strict
enough to perform all sorts of checks. The `rstcheck` standalone tool is
too strict, it warns about legitimate Sphinx constructs (hence the
ignore list), and also happens to issue false warnings. Let's rely on
Sphinx for stuff below docs/, but still invoke rstcheck for the
top-level README (and anything that's not included in the Sphinx docs,
really, which is right now the README, AUTHORS, and a JSON-specific doc
that I have yet to convert).

Bug: https://github.com/myint/rstcheck/issues/19
Change-Id: Ib787d11e7d21452570618288acdf15b3e85270a7
2020-06-17 20:43:37 +02:00
Jan Kundrát
a98e244abd docs: Fix Pygments highlighting
This will make it possible to use this document within Sphinx without
warnings.

Change-Id: I069cdc42b451102d4e731c8d848716126b0e518a
2020-06-17 20:23:58 +02:00
Jan Kundrát
c945bc40fe docs: move JSON and XLS instructions into the generated docs
Change-Id: I659dd8e53663286b1382d1786f46c5341bf7ea44
2020-06-17 20:23:58 +02:00
Jan Kundrát
749b9287a9 Merge remote-tracking branch 'origin/develop' in preparation of release 2.2
Change-Id: I3d503a9c1609e174f8b0a2e11afb646c879099cc
2020-06-17 12:55:12 +02:00
Jan Kundrát
202c76bd6e CI: enable Zuul builds
I'm hoping that merging this change will make Zuul handle that merge
commit.

Change-Id: I31fcc353ee6044355ebbd3ff61bc2ba1b33eb2c7
2020-06-17 12:50:15 +02:00
Jan Kundrát
eec0943ca2 Merge "Upload releases to PyPI upon tagging" into develop 2020-06-13 14:12:19 +00:00
Jan Kundrát
cd0415e523 coding style: remove dead code, fix up sphinx
Change-Id: I80479959d551915ddb12d14ef94ed77042b000ef
2020-06-12 09:08:49 +02:00
Alessio Ferrari
06d59a5834 Introduce polarization mode dispersion (PMD)
Change-Id: I687591df4662884b734ec945e9968713019ea0fc
2020-06-12 09:08:22 +02:00
Jan Kundrát
33dcdde422 Remove unused "carrier probing"
This is effectively a revert of commit 771af49 which added a
commented-out feature for printing out carrier info of the first hop.

On one hand, I'm reluctant to remove this, because apparently this was
not added by an accident, the PR #193 explicitly speaks about a
suggestion from Dave Boertjes for this feature -- and the git history
with merges looks like this one was actually pulled in as a single
commit. On the other hand, it is apparently not used anywhere, and all
of the required information is already available in some other manner --
for example, one can easily follow the path and add these prints to the
propagation, or just walk the path manually.

Digging further, I removed some of similar print() statements in
acafc78, and then restored some commented-out print()s via ec9eb8d (also
see the discussion in #299), which were then removed by Esther in
8107dde. So my TL;DR version is that this is dead code, and that
apparently the *real* use case is having total insight into the spectrum
info along the path (e.g., #246). That should, IMHO, be handled by
proper processing of the resulting data in a nice UI.

Change-Id: I366d33f98e230f4cb60a6d4b791707f7604f8d65
2020-06-12 06:54:07 +00:00
Alessio Ferrari
94949d955b Introduce computation of the chromatic dispersion
Change-Id: I3ee039154568d4255444fa8db5e89945851010f4
2020-06-12 08:45:46 +02:00
Alessio Ferrari
b74d0a4919 Add dispersion slope
Change-Id: Iced385787896793437be410a189c67e05da87714
2020-06-12 08:38:51 +02:00
Alessio Ferrari
c8fa7635e0 Bug fix in converting the dispersion D in beta2
The actual conversion formula includes the minus (-), not the absolute
value. We never noticed it as GNPy simulates only modern networks
based on uncompensated transmission which have not DCUs. In this case,
the sign of beta2 along a path is the same for all the spans and,
in this case, the actual amount of NLI does not change.

Change-Id: I60a61d00c578a1a0436231a2bda8e3b6256fc8b3
2020-06-12 07:35:40 +02:00
Jan Kundrát
4c6cfbda5d Merge changes from topic "moving-examples" into develop
* changes:
  Enable saving the network as converted from XLS
  Save either to JSON or to CSV, not to both
  CLI: Allow Raman in path_requests_run
  CLI: Unify handling of the network topology
  Remove unused variables
  CLI: show default values in --help
  Unify handling of the --equipment option in examples
  CLI: specify shared code options just once
  Tweak the --help output
  Remove unused statements
  XLS -> JSON conversion: add a nice program for this
  transmission_main_example: Do not write out a CSV file
  tests: don't clutter up the source dir with generated CSVs
  use load_json instead of open coding
  tests: Do not produce JSON files in the source tree
  Split JSON export from service XLS reading
  tests: Do not create JSON files in the source tree
  Do not always write out JSON data when reading XLS files
  Remove incomplete support for "fuzzy name matching"
  distribute example data along GNPy
  Do not create *_auto_design.json by default
  tests: remove something which looks like a path, but is not a valid path
  tests: show that the examples still work when directly invoked
  examples: add some additional descriptions help context
  Distribute our examples via setuptools
  tests: call our example entry points via functions
  examples: prepare for overriding sys.args
  examples: move path_requests_run to gnpy.tools
  examples: move transmission_main_example into gnpy.tools
  examples: use ansi_escapes
  examples: manual coding style tweaks
  examples: autopep8 -aaaaaaaaaa
  examples: autopep8
2020-06-11 20:31:54 +00:00
Jan Kundrát
80e9423590 Upload releases to PyPI upon tagging
Change-Id: Ia0543a5a091069e9503c8ba6a09930c35a0104f7
2020-06-10 16:39:09 +02:00
Jan Kundrát
78010aaaef Enable saving the network as converted from XLS
This is a feature that was requested by Esther due to their workflows at
Orange. There's also a standalone converter avaialable as
`gnpy-convert-xls`.

Change-Id: I1a483d168db0744fbf115e05e679e13b57d79398
2020-06-10 14:27:05 +02:00
Jan Kundrát
3857ab1dbb Save either to JSON or to CSV, not to both
I don't see a reason for that; the old debug texts were actively
misleading.

Change-Id: I2089bf8f87ec994770cc272e054650e18da4ef2a
2020-06-10 14:15:50 +02:00
Jan Kundrát
dbb09e4108 CLI: Allow Raman in path_requests_run
There's no need to limit this to just the transmission_main_example, so
let's unify this handling.

Change-Id: I585f407c7f80da12fd33baf7261c35c736d78df2
2020-06-10 14:11:44 +02:00
Jan Kundrát
94a8f3568a CLI: Unify handling of the network topology
Change-Id: I51c98ae13218715862fe9f585b2cc4b079498bee
2020-06-10 14:11:42 +02:00
Jan Kundrát
ae7c9321d0 Remove unused variables
They are ever read from, not even in any commented-out debugging code,
so let's nuke these.

Change-Id: I3188511adb28242dc40418cb3bb90b38bc4fdb14
2020-06-10 14:09:52 +02:00
Jan Kundrát
648cc3a8e5 CLI: show default values in --help
I think this is a little bit cleaner that duplicating the info about the
default for some of these options.

Change-Id: If218a26ede3e71628f4839b4e505c4f4aa217699
2020-06-10 14:09:52 +02:00
Jan Kundrát
f9e0d18a9d Unify handling of the --equipment option in examples
Let's use the --option format instead of positional arguments; that way
it's more obvious that it can be omitted. Note that this constitutes a
change of behavior for the path_requests_run example.

Change-Id: Ic6653cf419e1a8573c3585190a88fc51500f549d
2020-06-10 14:09:52 +02:00
Jan Kundrát
2d57fd9f85 CLI: specify shared code options just once
Change-Id: I79d2c9dfd630ee72ff1b87d4b24025a20d1e2ce2
2020-06-10 14:09:49 +02:00
Jan Kundrát
f053f32301 Tweak the --help output
Try to indicate whether an option takes just JSON, or a JSON or an XLS
file. Also add some extra descriptions.

Change-Id: Ifb81d46f6ac659da79b08201a414822e9c318a1e
2020-06-10 14:07:40 +02:00
Jan Kundrát
8e9d715e9f Remove unused statements
Change-Id: Ib859254468f02f7384d736fa9d7120a0ad1aaa15
2020-06-10 12:14:41 +02:00
Jan Kundrát
9fd55a5289 XLS -> JSON conversion: add a nice program for this
Esther mentioned that it is useful for her to be able to convert from
XLS files to JSON files. Let's add a full blown script for this.

I've also taken the liberty to refactor the code a bit so that there's
no default value, and to modernize everything with pathlib a little bit.

Change-Id: I80e50fc1280003910242ce1ff9fc9ae66e6d275b
2020-06-10 12:14:41 +02:00
Jan Kundrát
914d0dbecd transmission_main_example: Do not write out a CSV file
We talked about this earlier today on a call, and agreed with Esther and
Alessio that this is probably a relict from the past. The file does not
appear to contain much useful information, anyway, so let's try to
remove it and wait if someone complains.

Change-Id: I215eeb37498b28b15ece2300f4bbdd184ac52f4a
2020-06-10 12:14:41 +02:00
Jan Kundrát
c38fe72ff7 tests: don't clutter up the source dir with generated CSVs
Change-Id: Ice9287dea2ed16ece2594e21eeab4c69e927947e
2020-06-08 20:35:58 +02:00
Jan Kundrát
80f63d32ed use load_json instead of open coding
Change-Id: I43cfbb7272bfdd834fad63e6715932ff45aeac0b
2020-06-08 20:06:11 +02:00
Jan Kundrát
9030f8f84f tests: Do not produce JSON files in the source tree
Change-Id: I7b9c65b93ba2ce64beef4de050b44c49a85163b7
2020-06-08 19:43:51 +02:00
Jan Kundrát
0d5f1c7d80 Split JSON export from service XLS reading
We have a better module for this.

Change-Id: Id4b68d3ddb119f27df3dfac52277981558fc5e50
2020-06-08 18:47:15 +02:00
Jan Kundrát
5bc42332cd tests: Do not create JSON files in the source tree
Change-Id: I5ef71cc82466367fa9e9eea4d3f02453a4d2f469
2020-06-08 18:31:24 +02:00
Jan Kundrát
093b85d4a3 Do not always write out JSON data when reading XLS files
There's no reason for this, in fact, the code got easier to read when
that detour to disk gets removed.

Change-Id: I45db215898da962e625a7fea6eda57744e21ff8a
2020-06-08 18:31:21 +02:00
Jan Kundrát
0efa0d310d Remove incomplete support for "fuzzy name matching"
This is something which got added in bc9eee32, but it never got
finalized to have a user-visible effect. To the best of my knowledge, it
only created a file which was never used.

I removed code which created that file in 0d542f22, so let's clean up
the rest.

I think this should also restore functionality of running convert.py in
a standalone mode. Looking at the ArgParser, the invocation never
considered the names_matching parameter.

Change-Id: Id0f4aa1db2d22233f74fb273176168a16ace4072
2020-06-08 18:30:38 +02:00
Jan Kundrát
8eb5980ca9 distribute example data along GNPy
I would like to create a package for distribution to PIP, and this seems
like the path of least resistance.

This is, apparently, the way for shippign arbitrary data with Python
[1]. I've at least tried to make it user-firendly via adding a simple
utility which just prints out whatever that data path is.

[1] https://python-packaging.readthedocs.io/en/latest/non-code-files.html

Change-Id: I220ecad84b1d57d01e3f98f15befc700bd97c0b8
2020-06-08 18:30:36 +02:00
Jan Kundrát
754be7ca08 Do not create *_auto_design.json by default
It's a bad habit to write files into the source code repository. It will
also become impossible if gnpy is installed into a systemwide, possible
read-only location.

The old behavior can be reactivated by using an extra option to tell
GNPy where to put the generated file.

Change-Id: I9ad43890ca5886f516885de5938a4778870a06c5
2020-06-08 18:28:59 +02:00
Jan Kundrát
c5c5b693f2 tests: remove something which looks like a path, but is not a valid path
As I'm moving the top-level directory `examples/` to another place, I
wanted to clear the source of any mentions of examples which are not
actually valid paths.

Change-Id: If6cce20feacfbbb79549e865d06aa00fd2dcd08d
2020-06-08 18:28:59 +02:00
Jan Kundrát
7f816eb6e7 tests: show that the examples still work when directly invoked
Since Ic4a124a5cbe2bd24c56e4565d27d313fe4da703f, there was no automated
test which would check if the generated examples *really* work. When I
was playing with this, I managed to break it at least once (especially
when working on overriding sys.args, i.e.,
I53833a5513abae0abd57065a49c0f357890e0820).

This now requires an equivalent of `pip install` before the tests can be
run.

Change-Id: I595a3efe29b3ee13800c5cb71f28a5f370988617
2020-06-08 18:28:59 +02:00
Jan Kundrát
1009b44d2a examples: add some additional descriptions help context
The main reason for doing this is becasue of the next commit which
re-adds testing of the generated wrappers.

Change-Id: I7137c6cf7a5b414fc708a15b125eaf88e996366c
2020-06-08 18:28:56 +02:00
Jan Kundrát
3b61c6ca4c Distribute our examples via setuptools
Cc issue #352.

Change-Id: I31e67130540fabeb2666dea38da6c435236e7f5b
2020-06-05 18:04:53 +02:00
Jonas Mårtensson
cc11bd186c Update compute_constrained_path
This patch proposes a new implementation of the compute_constrained_path function based on the same method as the newly proposed compute_k_constrained_paths function, i.e. using shortest_simple_paths instead of all_simple_paths. This method is more efficient and avoids having to set a cutoff parameter. The new implementation should be identical to the old one from an external perspective, except that it finds a path with include node constraints in more cases.

Change-Id: Ia93b61c0af27076ed5088013bc87787a2920b629
Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
2020-06-03 20:57:39 +02:00
Jan Kundrát
0d1225824e tests: call our example entry points via functions
I would like to avoid that extra fork to a child Python interpreter (it
looks like something that can be easily avoided). It's something that's
possible now that the code ships just some trivial wrappers (which are,
in turn, needed for setuptools' `console_scripts`).

This cannot use the `capsysbinary` fixture for wrapping of stdout/stderr
due to something in pytest which already got fixed, but has not been
released yet (May 2020). Let's use `capfdbinary` which works fine.

Change-Id: Ic4a124a5cbe2bd24c56e4565d27d313fe4da703f
See-also: https://github.com/pytest-dev/pytest/pull/6926
2020-06-03 19:29:17 +02:00
Jan Kundrát
a2ecfd924c examples: prepare for overriding sys.args
...which will be done in the next commit. One has to be careful with
sys.argv here because it uses different indexing than when passing args
explicitly.

Change-Id: I53833a5513abae0abd57065a49c0f357890e0820
2020-06-03 19:29:03 +02:00
Jan Kundrát
95c3c9c488 examples: move path_requests_run to gnpy.tools
Change-Id: Id23dfa81bf9a9b347ea9c99f77d5735b62911d67
2020-06-03 19:22:53 +02:00
Jan Kundrát
11033a284f examples: move transmission_main_example into gnpy.tools
This converts our first free-standing example entry point into a
function. It will become very handy when we start distributing these
entry points via setuptools.

Change-Id: Icd2e4658337f93cd0b0301978e2dc640de0cc72b
2020-06-03 19:06:31 +02:00
Jan Kundrát
357e6cbf18 examples: use ansi_escapes
Change-Id: I958b00a7d7c079d9330cc0f4aec1f72b4a102223
2020-06-03 18:32:16 +02:00
Jan Kundrát
bfa6d29908 examples: manual coding style tweaks
Change-Id: Ie0ac42561afad331b8d22df0576ef071f358c5ed
2020-06-03 18:29:07 +02:00
Jan Kundrát
21e0589e7f examples: autopep8 -aaaaaaaaaa
Change-Id: I811bc80d9eca9df34c554362de62f98a897cbb05
2020-06-03 18:18:19 +02:00
Jan Kundrát
4d836246ec examples: autopep8
Change-Id: Ieed050fdfb9db57722b2b8de642c25ad2e4a50eb
2020-06-03 18:17:47 +02:00
Jan Kundrát
566943a099 Merge "Support propagation of single channel" into develop 2020-05-30 10:17:38 +00:00
Jan Kundrát
a4c1ea1f55 CI: Restore functionality via running on Python 3.6 on native packages
We have declared that we're supporting Python 3.6 as the minimal
required version of Python. Let's enforce this via testing. Let's also
do it via a long-term supported distro (CentOS8 in this case) so that we
can have someone else maintain stuff for us; it's easier to rely on
these prebuilt packages instead of downloading Python from upstream all
the time.

Also, Python 3.7 builds are currently broken in the CI because of some
breakage, either in the upstream zuul-jobs repo, or in Vexxhost's VM
images. So, now that we have Python 3.6 VMs available, use this to
restore CI functionality. That part can be reverted in future when
Debian Buster-based builds are working again.

I've also tried to use Python 3.8 on latest Fedora (version 32). There
were a couple of gotchas, including /tmp on tmpfs with not enough space
for building all required packages. Also, there's another issue with
building Pandas from scratch, so let's defer using Python 3.8 until
later. It's something that I will definitely look into, though, because
of significant speed improvements in that distro.

Change-Id: Ic19bf58875ba6d6afaee77f5c9b467261ec686d0
Depends-on: https://review.gerrithub.io/c/Telecominfraproject/oopt-zuul-jobs/+/494597
2020-05-30 11:55:43 +02:00
Jan Kundrát
6b10ed15f8 Restructuring and reorganization of the library structure
Change-Id: I111922113858526c21b848b28c86a80d5c013d65
2020-05-26 19:32:38 +02:00
Jan Kundrát
c8daa5ed8c docs: basic stuff about the module structure
As a bonus, in the Python shell, `help(gnpy)`, `help(gnpy.core)`, etc,
now produce at least some useful information.

Change-Id: I76ade6f2456fcebd3c0a147374815dd245dc4b10
2020-05-26 18:36:30 +02:00
Jan Kundrát
0b03725295 tests: fix import of correct_json_route_list
It got moved in de58d7d7c2, let's import
it directly, not via examples/.

Change-Id: I0c36fcfdb775baac6fafc05ecd41ac39bafd750d
2020-05-23 22:14:52 +02:00
Jan Kundrát
ee5e64408d examples: common code for data loading
This also moves SimParams handling to a single place. As a result,
path_requests_run has just become Raman-aware (to the minimal possible
extent, OK).

Change-Id: I4e31af5c67335963ddab567d304f48a899cd569e
2020-05-23 22:03:23 +02:00
Jan Kundrát
b96ffe6c7b examples: unify exception handling
Change-Id: I7a6ac6ba54c597214bb85ee0dda2d6313b677730
2020-05-23 22:03:23 +02:00
Jan Kundrát
3b981853d4 SimParams: pretty exceptions upon a misconfiguration
Change-Id: I69f47925dd08c492b295b6824618a4595d142954
2020-05-23 22:03:23 +02:00
Jan Kundrát
6fa3ef8df1 params: Remove extra if
`kwargs` is always a dict, so it's still safe to prove individual
elements in there.

Change-Id: I2dea3159764807a2ff6a96d613ff69c68a7ba3ce
2020-05-23 22:03:23 +02:00
Jan Kundrát
1b2b048b47 reorganization: move request processing and request disjunction handling into topology.requests
Change-Id: I14902a2e15cc5fd27530cb294f4f549f6974fd49
2020-05-23 22:03:23 +02:00
Jan Kundrát
94c5281260 flake8: Remove unused variables
Change-Id: I67ff11f2580690f58dbe9909a92f8725a65bd7c7
2020-05-23 21:29:59 +02:00
Jan Kundrát
7da4ec08d8 reorganization: move JSON-specific bits from path_requests_run to tools.json_io
Change-Id: I03cf4e298300387ee5d56251e2e552e111b59f65
2020-05-23 21:28:06 +02:00
Jan Kundrát
2b473d26d3 reorganization: move example plotting into an extra submodule
Change-Id: Ibb7a81f360493ad8c1b7e58303e2e256c64dd755
2020-05-23 20:44:51 +02:00
Jan Kundrát
9e74e8b0a0 De-JSONify gnpy.core
Change-Id: I2657f3174209bef5912c7d0809fee876830ad11c
2020-05-23 20:44:51 +02:00
Jan Kundrát
648039521e reorganization: move all JSON processing into an extra module
We agreed that `gnpy.core` should only contain stuff for propagating
wavelengths. Conceptually, JSON parsing and even instantiating these
network elements from data obtained through JSON is *not* something that
is on the same level -- and this will become more important when we move
into YANG format in future.

Also, instead of former `gnpy.core.equipment.common`, use
`gnpy.tools.json_io._JsonThing`. It is not really an awesome name :),
but I think it sucks less than a thing called "common" which would be no
really longer any "common" in that new file.

Change-Id: Ifd85ea4423d418c14c8fae3d5054c5cb5638d283
2020-05-23 20:44:47 +02:00
Jan Kundrát
24bc023a07 refactoring: reduce amount of Python magic in network building
Similarly to I7ab9f64d7ac2042e8a16d031ba5562a6eb412471, it's better to
be explicit about what's going on. It makes it easier to reason about
the code.

Change-Id: Ic7f4a590567f1f5903222be8dae53521424d8f77
2020-05-23 18:14:41 +02:00
Jan Kundrát
19c2ae7f7a Qualify all usages of classes from gnpy.core.elements
This will be needed by one of the follow-up commits which move JSON
manipulation into a single file. We have to distinguish between "Roadm"
the JSON representation and "Roadm" the network element which propagates
spectrum.

Change-Id: I6888842c57c3a57849fabe75d0ff6f5bbfab426a
2020-05-23 18:11:08 +02:00
Jan Kundrát
9f6894a176 Remove extra indirection -- just instantiate Edfa directly
Change-Id: Ib957063d3333597fd58ba97bb78a187559f42d86
2020-05-23 17:52:39 +02:00
Jan Kundrát
a094568d6e equipment: move NF estimation into science_utils
I envision equipment.py as something which deals exclusively with the
traditional GNPy's JSON-formatted data, so make sure we do not include
any computation in that file.

Change-Id: I8473cccd84243147181a7195ba39fc6c9db3c42f
2020-05-23 16:37:56 +02:00
Jan Kundrát
f728d96d07 equipment: mark internal functions as such
Change-Id: I3cbed25568c0e85685caf3e279f3c3a8e37247f1
2020-05-23 16:37:56 +02:00
Jan Kundrát
6b1fb7061f Move placeholder EDFA NF calculation to where it gets used
I think that equipment.py should be only concerned with constructing
network elements from JSON data.

Change-Id: I777835b02a23b76fb1d40c3a966e72b606e9c205
2020-05-23 16:19:05 +02:00
Jan Kundrát
7ef505f259 Do not perform magic when reading equipment config
I think that being explicit about what gets instantiated is much easier
to read. For one, it enables "find usages of this thing" in IDEs.

The original code was also insecure because it would happily invoke any
function available in the global context with user-supplied data(!).

Change-Id: I7ab9f64d7ac2042e8a16d031ba5562a6eb412471
2020-05-23 16:07:48 +02:00
Jan Kundrát
c8d394348d Tweak error messages a bit
Change-Id: I49af7ea0d40a901cee271f21306288337f6b041f
2020-05-23 16:07:17 +02:00
Jan Kundrát
0daa1c3e8c Rely on pip for missing dependency detection
We have some docs on how to install this, and we rely on the
requirements.txt file for specifying what packages are required. There's
no point in arbitrarily handling the `xlrd` package in a different
manner.

Change-Id: I2355440ada7fd0cc4868aeff5a8956729655c96b
2020-05-23 15:45:10 +02:00
Jan Kundrát
60bafd114d examples: remove unused imports
Change-Id: I5c60243ecf7cdb56bf1060e2630e35ffb5f3548f
2020-05-23 15:33:18 +02:00
Jan Kundrát
11509f5686 requests: simplify ResultElement inheritance
This has been the only place where content from gnyp.tools.service_sheet
was being used outside of tests and examples. It looks like something
which is actually *not* used anywhere (the ResultElement instances are
only ever apended to a list which gets used as-is, so we do not need any
custom comparisons or hashing).

Change-Id: Ib6ddcf55779218d602620e77973d88ad62d0ec7b
2020-05-23 15:23:27 +02:00
Jan Kundrát
785c823fa2 coding style: separate property definitions from each other
While not strictly needed in Python, it's much clearer this way.

Change-Id: I5f8caccde6440cb4032aae5deae577d328834a75
2020-05-23 15:23:27 +02:00
Jan Kundrát
9faf6430a5 reorganization: gnpy/{core => tools}/service_sheet.py
Change-Id: I88559cc718536f222b8ea9829bcc72a425c062ca
2020-05-23 15:23:27 +02:00
Jan Kundrát
01c566a325 reorganization: gnpy/{core => topology}/spectrum_assignment.py
Change-Id: Ic6194ce639dcb2f9419372febe0f2b58473edb38
2020-05-23 15:05:42 +02:00
Jan Kundrát
baa9171315 docs: improve docs markup a bit
Change-Id: Ic1f60dbdfbe08111026cc3bdcd8d56293cb4555d
2020-05-23 14:59:35 +02:00
Jan Kundrát
2e50337f38 docs: remove implementation details from the documentation
Change-Id: Ic5ff20b16cc932953729f9cae2e8e3d96058e92d
2020-05-23 14:59:18 +02:00
Jan Kundrát
8daa298699 Import referenced exceptions
Change-Id: Iba0dc2682edc59e211bd8bbe638ce0bc1f4917fe
2020-05-23 14:58:49 +02:00
Jan Kundrát
76cdd5dc71 parameters: remove unused logger
Change-Id: I2d51081c8e1f7315861c2280ceb92304327c2ac6
2020-05-23 14:30:15 +02:00
Jan Kundrát
07eb2dd13a Refactoring: conversion functions instead of gnpy.core.units.UNITS
The TL;DR behind this patch is that it's better to have a utility
conversion function instead of having multiplier LUT and open code which
implements the conversion.

The FiberParams handling looked fishy -- apparently, it was keeping the
multiplier around, but it was unconditionally setting the units to
meters, anyway. Given that the units were not being preserved anyway
(everything got converted to meters), and that the multipler was not
used anywhere, let's refactor the code to just convert to meters using
our new utility function, and remove the unused argument.

Change-Id: Id886d409a4046f980eed569265baefd97db841bd
2020-05-23 13:50:25 +02:00
Jan Kundrát
04e764d024 FiberParams: print out the configuration upon failure
Apparently it's sometimes not obvious where the input data come from
(see next commit), so let's show the data which caused this excpetion to
the user.

Change-Id: Id333903a0549c4ef5dc37c2f6ff340bd357279ea
2020-05-23 13:50:25 +02:00
Jan Kundrát
05ccb14e5d Remove unused gnpy.core.execute submodule
Change-Id: I3972f8321547bc596c018fa04232edfa23b97581
2020-05-23 13:30:19 +02:00
Jan Kundrát
f60d035e66 Ensure that automatic_fmax gets used and not reinvented
Change-Id: I1f77f47eec3a3f0e6f22a073a98edca20958d321
2020-05-23 13:13:22 +02:00
Jan Kundrát
0823f8de46 Move automatic_nch, automatic_fmax into utils
I think that gnpy/core/equipment.py should contain only stuff which
prepares the equipment_config, not anything "lower level" that is reused
from other places.

Change-Id: I0cd593fd3e5558178ddd0ad8fff5c596e022894a
2020-05-23 13:08:24 +02:00
Jan Kundrát
a453c57996 document and test automatic_nch and automatic_fmax
Change-Id: Ib6a5e5f8278456725c810a9f7f0c7f5cafd78bd2
2020-05-23 13:03:23 +02:00
Jan Kundrát
2f84bb5286 Merge "Zuul: test with Python 3.6 as well" into develop 2020-05-23 09:03:20 +00:00
Jan Kundrát
7b8e68aea9 Zuul: test with Python 3.6 as well
We're saying that Python 3.6 is the minimal version that we support, so
let's make sure there's CI coverage for that.

I also tried enabling Python 3.8, but somehow the build of Pandas
failed. I don't feel like debugging a Pandas build failure today, so
let's postpone this thing until later. Just having 3.6 is a net
improvement, and we can play with even newer Python later -- and perhaps
on a newer distro, anyway.

Change-Id: I28a8c282225b7070ed3dddba56cccc8def313a77
2020-05-23 10:24:33 +02:00
Jan Kundrát
8d553a255f Merge "docs: brand the generated docs with our shiny logo" into develop 2020-05-22 13:04:13 +00:00
Jan Kundrát
2766e37438 CI: do not clutter up Zuul's failure display with the coverage report
Just ask pytest-gcov to not generate any test report. The coverage data
are still generated and will be used in later steps of the build
pipeline.

Change-Id: Ic5bb6a48e2abf6ee52e1c2650727ce4170611171
2020-05-21 12:52:19 +02:00
Jan Kundrát
f56e64410b docs: brand the generated docs with our shiny logo
Image source: I took the existing banner, cropped it and resized to
200px width as per the theme docs.

Change-Id: Ic79b6164d557298746fe878de31ee0a9b0d93923
2020-05-19 18:11:29 +02:00
Jan Kundrát
15ea7218e9 Merge gnpy.core.node.Node into gnpy.core.elements
That class is an internal implementation detail, so mark it with a
leading underscore as per Python idioms.

Also, tweak the docs so that there's less duplicate information and
more cross-references.

Change-Id: Ieb1c8034ab5b442032396d7c4bbd0a697c7eb492
2020-05-19 17:29:11 +02:00
Jan Kundrát
db28011c61 coding style: manual tweaks
This mainly reverts some auto-fix-ups done in
I2f0fca5aa1314f9bb546a3e6dc712a42580cd562 which do not make that much
sense. By reverting them by hand, it's (hopefully) easy to see what is
just a tool work and what is an opinionated preference.

Change-Id: I6cb479e34b552fadc85c41b4b06b24e60c87b4a3
2020-05-19 13:59:56 +02:00
Jan Kundrát
faccc23018 Always use our ansi_escapes module
Change-Id: I27bac671caa7544f51e7935ee120c9fcd6c942a7
2020-05-19 13:59:56 +02:00
Jan Kundrát
49514c0c70 flake8: fix F401 (unused imports)
Change-Id: I6f79f3a4c071b332e45033f4189a2af6c66a6e05
2020-05-19 13:45:05 +02:00
Jan Kundrát
0b1557fdf1 flake8: fix F841 (local variable is assigned to but never used)
Change-Id: Ic79d0189bf4e97b953604edd0a6932f28c71a071
2020-05-19 13:30:04 +02:00
Jan Kundrát
46f89aa770 coding style: autopep8 in an aggressive mode (-aaaaaaaaaa)
I decided to skip the following chunk of the diff because I think that
it would actually made the code a bit harder to read:

diff --git gnpy/core/service_sheet.py gnpy/core/service_sheet.py
index 9965840..9834111 100644
--- gnpy/core/service_sheet.py
+++ gnpy/core/service_sheet.py
@@ -41,8 +41,22 @@ logger = getLogger(__name__)

 class Request(namedtuple('Request', 'request_id source destination trx_type mode \
     spacing power nb_channel disjoint_from nodes_list is_loose path_bandwidth')):
-    def __new__(cls, request_id, source, destination, trx_type,  mode=None, spacing=None, power=None, nb_channel=None, disjoint_from='',  nodes_list=None, is_loose='', path_bandwidth=None):
-        return super().__new__(cls, request_id, source, destination, trx_type, mode, spacing, power, nb_channel, disjoint_from,  nodes_list, is_loose, path_bandwidth)
+    def __new__(
+            cls,
+            request_id,
+            source,
+            destination,
+            trx_type,
+            mode=None,
+            spacing=None,
+            power=None,
+            nb_channel=None,
+            disjoint_from='',
+            nodes_list=None,
+            is_loose='',
+            path_bandwidth=None):
+        return super().__new__(cls, request_id, source, destination, trx_type, mode, spacing,
+                               power, nb_channel, disjoint_from, nodes_list, is_loose, path_bandwidth)

 # Type for output data:  // from dutc

diff --git tests/test_automaticmodefeature.py tests/test_automaticmodefeature.py
index 0e5f633..5ba5881 100644
--- tests/test_automaticmodefeature.py
+++ tests/test_automaticmodefeature.py
@@ -32,7 +32,26 @@ eqpt_library_name = Path(__file__).parent.parent / 'tests/data/eqpt_config.json'
 @pytest.mark.parametrize("net", [network_file_name])
 @pytest.mark.parametrize("eqpt", [eqpt_library_name])
 @pytest.mark.parametrize("serv", [service_file_name])
-@pytest.mark.parametrize("expected_mode", [['16QAM', 'PS_SP64_1', 'PS_SP64_1', 'PS_SP64_1', 'mode 2 - fake', 'mode 2', 'PS_SP64_1', 'mode 3', 'PS_SP64_1', 'PS_SP64_1', '16QAM', 'mode 1', 'PS_SP64_1', 'PS_SP64_1', 'mode 1', 'mode 2', 'mode 1', 'mode 2', 'nok']])
+@pytest.mark.parametrize("expected_mode",
+                         [['16QAM',
+                           'PS_SP64_1',
+                           'PS_SP64_1',
+                           'PS_SP64_1',
+                           'mode 2 - fake',
+                           'mode 2',
+                           'PS_SP64_1',
+                           'mode 3',
+                           'PS_SP64_1',
+                           'PS_SP64_1',
+                           '16QAM',
+                           'mode 1',
+                           'PS_SP64_1',
+                           'PS_SP64_1',
+                           'mode 1',
+                           'mode 2',
+                           'mode 1',
+                           'mode 2',
+                           'nok']])
 def test_automaticmodefeature(net, eqpt, serv, expected_mode):
     equipment = load_equipment(eqpt)
     network = load_network(net, equipment)

Change-Id: I522c45c079b3a9540568657e2ae0a4bfc5fb1272
2020-05-19 12:53:11 +02:00
Jan Kundrát
3548ed74e2 coding style: autopep --in-place --recursive --jobs 4 --max-line-length 120 gnpy/ tests/
Change-Id: I2f0fca5aa1314f9bb546a3e6dc712a42580cd562
2020-05-19 12:40:00 +02:00
Jan Kundrát
145653df6e reorganization: gnpy/{core => topology}/request.py
Change-Id: Ib399549479b56634c681930aa444b657e5f58ca7
2020-05-19 11:56:02 +02:00
Jan Kundrát
c7589e0bca linters: remove unused variables
Change-Id: I16cb9fab7996efcd01eec1f5dee7be12adae43c2
2020-05-19 11:55:26 +02:00
Jan Kundrát
531810cc85 Remove unused class import
Change-Id: I3e0b7174f6ff60a632bbcde56178499755b8b7df
2020-05-19 11:55:17 +02:00
Jan Kundrát
63a6256b5e pep8: rename classes to use CamelCase
Change-Id: Ia696e05b72f1bc5feb570996f492042dafab262d
2020-05-19 11:54:27 +02:00
Jan Kundrát
c3febb6db4 gnpy/core/request.py: autopep8
Change-Id: I8790f67e6d7993b50d6fc0295f3a8a88439ac9ae
2020-05-19 11:54:27 +02:00
Jan Kundrát
8b1d8b3479 reorganization: XLS conversion goes to gnpy.tools
Change-Id: Ibbaddacd24a2d0f6f6d98fdc30d57da3be188338
2020-05-19 11:54:23 +02:00
Jan Kundrát
3168603908 gnpy/core/convert.py: coding style fixes
Change-Id: I760ff33813e916b33cb7cb3f6cef470200587acf
2020-05-19 11:49:55 +02:00
Jan Kundrát
a2128227bd gnpy/core/convert.py: run autopep8
Change-Id: Ib1a70a4f7bf8ab36aa1ec9265e2afaf69ca59d94
2020-05-19 11:49:50 +02:00
Jan Kundrát
376826b3ae Merge "Remove debug dumping of "city mapping"" into develop 2020-05-19 09:32:43 +00:00
Jan Kundrát
4b258cdf2e Merge changes from topic "namespaces-and-modules" into develop
* changes:
  docs: emphasise the API reference over bits which are duplicated in the README
  docs: remove list of authors
2020-05-19 08:01:41 +00:00
Jonas Mårtensson
fbdd132a3d Support propagation of single channel
It always seemed like a strange restriction to not allow this.

Change-Id: Ice3ed3ecc08f42b6ef8b74d4a6bc3b1794ff078a
Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
2020-05-14 21:14:12 +02:00
Jan Kundrát
eebcebb33d Remove extra elements from default EDFA parameters
Since Ia8c8d734c7045062ce123360f4a1432490384118, the lists no longer
have to have the same length.

Change-Id: I43ff10defa414cde0d6ff26a4d238b8680e39899
2020-05-14 16:43:51 +02:00
Jonas Mårtensson
20152036ff Allow different lengths of EDFA config lists
Currently interpolation of nf_ripple or gain_ripple fails if the length
of the input list is different from the dgt input list since the amplier
frequencies used for interpolation are calculated based on the length of
the dgt input list. There seems to be no good reason for this restriction
so I propose to calculate amplifier frequencies separately for the
different inputs. This also allows to specify a flat ripple with just one
number and a flat dgt with two numbers.

Change-Id: Ia8c8d734c7045062ce123360f4a1432490384118
Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
2020-05-14 15:30:57 +02:00
Jan Kundrát
2a477071a0 docs: emphasise the API reference over bits which are duplicated in the README
Also make sure that all modules are covered. It seems that there's no
automatic way for doing this, aargh. On the other hand, there's
apparently no need to repeat all the Sphinx markup blurb, and even
sectioning works nicely (read, "as I expect it to work") now :). I think
that it's still necessary to keep these "intermediate files" that only
trigger package-level and module-level autodocs, but hey, I can live
with this.

Change-Id: I705e0054cd7cd4350171770795d69f5c15c226d6
2020-05-07 19:54:55 +02:00
Jan Kundrát
f02d11e8bc docs: remove list of authors
The documentation is something which our users see as one of the first
things when they go and try GNPy. With all respect to people who have
contributed over the years, there are more important information to
convey to a first-time user instead of a list of authors.

Change-Id: Ibe5f6477f9736b9ab71effcf0eccef7c7fdfdde5
2020-05-07 19:05:50 +02:00
Jan Kundrát
0d542f22a7 Remove debug dumping of "city mapping"
This JSON file is never used by the rest of the code. Let's get rid of
one of these files which are put into the source code directory during
unit test execution.

Also remove other dead code; thanks to Esther for catching this.

Change-Id: I30a4e7edcf638162ec438fbf7f00d26d78944ac3
2020-05-05 19:20:00 +02:00
Jan Kundrát
5af195bd2b Remove unused imports
Change-Id: I66174048a9eaab0f79ba4c3b1d31ef4dc9c2009b
2020-04-30 17:30:55 +02:00
Jan Kundrát
7ab93e7cd9 tests: frequency to wavelength
I decided to keep it around because I know that some people would like
to see those nanometers. Let's make sure it works.

Change-Id: Ib279cc8380a77f478da7a2bbc1e045a718446404
2020-04-30 17:30:55 +02:00
Jan Kundrát
0aec47ddeb tests: remove dead code
Change-Id: Id8bc0cae7d91b2a80032890b2e30c70be566d052
2020-04-30 17:30:55 +02:00
Jan Kundrát
9a54dbab43 Remove unused functions
Given that everything else just uses these constants as imported from
numpy, there's no point keeping these wrappers around.

Change-Id: I0e19e05f40dc79d8005e915cf3ffb5e36328421a
2020-04-30 17:30:55 +02:00
Jan Kundrát
fc03be8bbe tests: use doctest instead of an explicit runner
...and expand the coverage a wee bit while we're at it as well.

Change-Id: I0de8445dc29f46e5f238bff0ca0e1f63fe19712d
2020-04-30 17:30:55 +02:00
Jan Kundrát
32f10a4507 tests: show how much *test* code is actually executed
Change-Id: Iba05c8b212b7217fe3d45a50f3d24f017ab09a74
2020-04-30 17:30:55 +02:00
Jan Kundrát
04544d41f6 Merge "Fix #353 - String representation of network elements" into develop 2020-04-30 15:29:07 +00:00
Jonas Mårtensson
c87be89e07 Fix #353 - String representation of network elements
Currently the string representation of some elements in elements.py refer to parameters that are not assigned until the propagate function runs.
Printing an element or trying to access its string representation before propagation therefore raises a TypeError.

This patch should fix the issue.

Change-Id: I29962f3c00e1f4fb7935535d4514a9579bc0c918
Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
2020-04-29 10:29:44 +02:00
Jan Kundrát
efa05f0653 Merge "Find paths with include nodes constraint" into develop 2020-04-28 16:42:10 +00:00
Jan Kundrát
4cf4db9bc2 Merge changes If9ebdfad,I9bc7e5bb,Ia7cf2026 into develop
* changes:
  include all 'no' Capital/non capital combination in test
  small refactor
  Enable ILA and FUSED type in routing constraints with xls input
2020-04-27 11:10:24 +00:00
Jonas Mårtensson
16434c5737 Find paths with include nodes constraint
The compute_constrained_path function in request.py handles include nodes constraint by first finding all simple paths shorter
then a cutoff length and then checking if any of the paths meet the constraint. The cutoff is currently set to 120 which is
too small for large networks. For the CORONET_CONUS_Topology.json topology, for example, the shortest path between some node
pairs is longer than the cutoff.

This is a small proposed change to first compute the length of the shortest path and then set the cutoff to at least 20% (a
conservative number) higher than this. I also propose to increase the minimum cutoff from 120 to 150.

Change-Id: I97ff2915fb38e4681bd64d60f2cd6dfd422afd4f
Signed-off-by: Jonas Mårtensson <jonas.martensson@ri.se>
2020-04-24 16:22:20 +02:00
EstherLerouzic
14ee9c9a91 Removing exit(1) and using exception instead
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I13bb8c87a7f764bda6e13f233c7b70909b9ee035
2020-04-24 10:41:17 +00:00
Jan Kundrát
7cfc4bd1ec linters: activate more checkers
"naming" with the "N" prefix looks reasonable, and it looks like my venv
has already had mccabe for that cyclomatic complexity. Let's get these
in.

Change-Id: Ie0cf4d8c20486f0f561db01903b3aa93cbebdb12
2020-04-24 12:22:32 +02:00
Jan Kundrát
9d55cde50d linters: Increase maximum line length
The code is already using long lines, so I think we can avoid a
discussion whether to raise this limit, and instead we can focus on
another discussion :) on what that limit should be.

Random googling suggests that GitHub's code renderer operates at 119
chars per line. A random style guide mentions going to 100 or 120. Prior
to this change, there has been 712 violations of PEP8 check E501.
Picking 119 would bring us down to 21 violations, and using 120 reduces
it further to 16. I think that 120 is a cuter number than 119, so 120 it
is unless someone objects hard enough to propose another cutoff in a
follow-up patch.

Change-Id: I57f48fcb6846fea35223daac91aa2e8c7afabc63
2020-04-24 12:21:18 +02:00
Jan Kundrát
72183c24da Merge changes from topics "coverage", "examples-via-tests" into develop
* changes:
  CI: run flake8 for coding style nagging in changes
  Fix syntax of the bandit config file
  Upgrade pytest, and list it as a test-only dependency
  CI: Activate coverage diffing
  tests: simplify tox setup
  CI: Run both non-coverage and coverage build/test jobs
  tests: Check if example code provides exact same output
  tests: Run examples via pytest
  Show more details upon a test failure
2020-04-24 09:32:03 +00:00
Jan Kundrát
4d1a628488 CI: run flake8 for coding style nagging in changes
This combines a few pieces of magic:

- Zuul merges speculatively, but in the git trees that the build VMs
see, the "current branch" is always the state as-if the currently tested
change was merged, while origin/"current branch" is the result of all
previous changes, if any, applied to the current tip of the target
branch.

- flake8 has a --diff option which appears to work correctly, *but* it
reports on all lines that are present in its input, including the
context -> hence the -U0 option.

Change-Id: I28403ff0132fac0b52696c82306732a4f81fa66a
See-also: https://gitlab.com/pycqa/flake8/issues/58
2020-04-24 00:14:02 +02:00
Jan Kundrát
fdeaf75361 Fix syntax of the bandit config file
Unlike codacy, it seems that bandit the CLI tool complains about these:

  Unable to parse config file: File contains no section headers.
  file: '/home/jkt/work/TIP/oopt-gnpy/.bandit', line: 1
  "skips: ['B101']\n"

Change-Id: Iab93052fd8aaf1754571a3c66796cfe3026f6a63
2020-04-23 18:38:36 +02:00
Esther Le Rouzic
5695fafac6 Merge "Adding a set of tests on spectrum_assignment functions" into develop 2020-04-23 13:17:31 +00:00
Jan Kundrát
0fe1d195a3 Merge "Update Excel userguide" into develop 2020-04-23 12:53:40 +00:00
EstherLerouzic
ed1aa0aa03 Update Excel userguide
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I9ef3d26c8363526d14fb00a17c31176925488abd
2020-04-23 14:45:39 +02:00
EstherLerouzic
3fc024f5ba include all 'no' Capital/non capital combination in test
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: If9ebdfad62d10b63856652d094ef459d68973f7c
2020-04-23 12:43:11 +00:00
EstherLerouzic
4f8177908f small refactor
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I9bc7e5bb171864ee385fb2e59631943f2a65d235
2020-04-23 12:42:59 +00:00
EstherLerouzic
ad64595d75 Adding a set of tests on spectrum_assignment functions
- test oms building:
  o there should not be roadm or transceivers between end points except endpoints
  o the element oms is must correspond to the correct oms id
  o the element uid in the oms must match the id list

- test the alignment function
  this function enables to have different grid end points in different parts
  of the network. The grid used in the network must cover all these grids, so
  some bit stuffing is needed on the oms that have different sizes.
  The test checks that
    o min and max attribute are correctly updated
    o min and max n or freq values are consistent and consistent with bitmap
    o alignment is correct

- test that the assignment of n and m values is correct
  o check that assign_spectrum has returned an error code if the requested
    assignment is not possible and that the bitmap has not been set to 0
  o check that the bitmap sum works correctly when assignment is feasible
    and that all range of spectrum has been set to zero. eg:
    [1 1 0 0 0 0 1 1 1 1 1 1] and [1 1 1 1 1 0 0 0 0 1 1] must be:
    [1 1 0 0 0 0 0 0 0 0 1 1]

- Check that spectrum assignment of 13,7 is correct in Hz

    This example has been extracted from ITU-T G694.1
    expected value in Hz for 13,7 is 193137500000000.0,193225000000000.0 in Hz
    see fig I.3 of this document https://www.itu.int/rec/T-REC-G.694.1-201202-I/fr

- test assignment limits

  o verify that inconsistent values raise error: ie with defined fmin fmax
    n and m have limited values.
    combine valid and non valid data for n and m
  o verify that Bitmap created with a 0/1 list is consistent with fmin,
    fmax, grid and guard band

- Test with a path configuration

  o loop on assignment on a given path. assignment should be OK until n = 96
    at that value the assignment is no more feasible (exceed grid) and the selection
    function should return None value for all center_n, startn and stopn
  o select an arbitrary request and try to assign 1 slot more than the whole
    spectrum or exactly the whole spectrum and check that function correctly
    return None or not None values

- Test assignment with reversed path

  o add data and requests fixtures to reduce test time
  o test that if spectrum is assigned on one direction it is also
    assigned on reversed direction (bitmaps must be identical)

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Co-authored-by: Jan Kundrát <jan.kundrat@telecominfraproject.com>
Change-Id: I96dd15452cc2e59086d4022ec4b026be845f4355
2020-04-23 14:36:09 +02:00
Jan Kundrát
80133e9521 Merge "Better explain the source of error in exception message" into develop 2020-04-23 12:22:05 +00:00
EstherLerouzic
de58d7d7c2 Enable ILA and FUSED type in routing constraints with xls input
- builds correspondance dicts between input name from excel
  and names created with convert.py and autodesign in network.py
- correct the corresp_name dicts according to the effective
  network autodesign. This supports the case of fiber splitting
  and of fused elements
- include the case of parrallel links with only one hop
- interpret the node list constraint given by the user with the dict
- filter the constraints that are not applicable
- add tests for constraints
- correct equipment sheet of mesh_example_topologyv2.xls: morlaix and
  loudeac should not appear in node A column since they are fused

ILA and FUSED constraints must be filled with the next node
information in order to avoid confusion on the direction.
for example
     eg    a----b-----c
           |    |     |
           i    j     k
           |    |     |
           e----f-----g

a constraint 'j' given for service i to k leads to 2 possible direction:
i-a-b-j-f-g-k
i-e-f-j-b-c-k
the user must indicate the chossen direction. This ambiguity does not
exist with network input in json format (names are unique).

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ia7cf2026e569c8b566459791fc89546b91fb117c
2020-04-23 11:15:37 +02:00
Jan Kundrát
491a05c5a7 Upgrade pytest, and list it as a test-only dependency
Change-Id: Id1cbfb88d3034fc01f302af53bbd689afe54ffa5
2020-04-22 14:53:48 +02:00
Jan Kundrát
1d791aa295 CI: Activate coverage diffing
Depends-on: https://review.gerrithub.io/c/Telecominfraproject/oopt-zuul-jobs/+/489964
Change-Id: Icce2c2b11f4253e2400dcfe0055373f9d6bc7d14
2020-04-22 13:18:46 +02:00
Jan Kundrát
58921bc346 tests: simplify tox setup
I was not happy with duplicating the "test command" section among
several tox test environments. I was not successful when using just
`.coveragerc` or via `addopts` in `[tool.pytest]`, but these
conditionals appear to work.

Also replace `pip install -e .` or `python setup.py develop` with tox'
native `usedevelop`.

Change-Id: I4986a3d14f38b7f6ed9b6a04f773eb222a53a827
2020-04-22 13:18:46 +02:00
Jan Kundrát
ab6a91692b CI: Run both non-coverage and coverage build/test jobs
Change-Id: Ia58112b745a0b34d2dcef782ad729f165629eb22
2020-04-22 13:18:46 +02:00
Jan Kundrát
3b45968799 tests: Check if example code provides exact same output
Change-Id: I5938f85337e4254092683dadc806a0a419cb2a04
2020-04-22 13:18:46 +02:00
Jan Kundrát
c7d69b9a99 tests: Run examples via pytest
This will make it simpler to update coverage info. The pytest-cov plugin
that we're already using apparently makes this behavior supported, nice.

Change-Id: Ieafc0da99a8c325f5f2286ed11e66069e244e43b
2020-04-22 13:18:46 +02:00
Jan Kundrát
1eeed78430 Show more details upon a test failure
With -vv, we can at least have access to the full output -- if not in
its prettiest form.

Change-Id: I950bb4c2f59a9f582e53e48c78458bb47ab7d832
2020-04-22 13:18:06 +02:00
Jan Kundrát
1cdafbae0f docs: explain what the roll_off parameter means
Co-authored-by: Alessio Ferrari <alessio.ferrari@polito.it>

Change-Id: I4930dc5fdd9d4f60cef753f2d2e9674dce8aeb52
2020-04-21 21:27:14 +02:00
EstherLerouzic
47b4f87bc5 Better explain the source of error in exception message
If user forgets to fill in the path_bandwidth, error message was
not explicit enough to help to correct.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I776e95b6f859c3b643786b6e802f3c0bcbc1de76
2020-04-06 11:15:36 +02:00
Jan Kundrát
e24b766cdc Merge "Add an explanation for delta_p in excel user guide" into develop 2020-04-02 12:02:05 +00:00
Jan Kundrát
51fb6bd68e Merge "Correct the unit of gamma in Readme file" into develop 2020-03-30 13:37:03 +00:00
EstherLerouzic
7e405a0514 Correct the unit of gamma in Readme file
The units can be found in several papers from the documentation
for example
A. Carena, G. Bosco, V. Curri, P. Poggiolini, M. Tapia Taiba, and
F. Forghieri. Statistical characterization of PM-QPSK signals after
propagation in uncompensated fiber links. In European Conference on
Optical Communications, 2010, 1–3. IEEE, 2010-09.
URL: http://ieeexplore.ieee.org/document/5621509/,
doi:10.1109/ECOC.2010.5621509.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: If70b57a28ee108c4b8dbe341075e12169efbe14c
2020-03-30 15:29:29 +02:00
EstherLerouzic
194a13e607 Add an explanation for delta_p in excel user guide
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I0e3380abd494dd99a30bee00b55ec427d48c45ef
2020-03-30 15:22:43 +02:00
Jan Kundrát
856f07e707 Merge "Zuul CI: remove manual workaround for Python3 and TOX" into develop 2020-03-30 13:19:01 +00:00
Jan Kundrát
4582aed895 Merge "docs: Fix all sphinx warnings" into develop 2020-03-30 13:17:44 +00:00
Jan Kundrát
734b6dfef4 Zuul CI: remove manual workaround for Python3 and TOX
Now that https://review.opendev.org/712804 has been merged, we can just
use upstream jobs without that extra workaround.

Change-Id: Ia113caaea41bdd440dcb615c02ad95eba6da7543
2020-03-27 16:06:06 +01:00
Jan Kundrát
da6e4f33a4 Merge "Fix dependency installation with PBR" into develop 2020-03-27 15:04:10 +00:00
Jan Kundrát
5a1e3f30b3 docs: Fix all sphinx warnings
...and also enforce a warning-free build within the CI.

Change-Id: Ia406a0a1ca2e89ceaa0288ae82128fa9427fe066
2020-03-27 15:07:19 +01:00
Jan Kundrát
094af16792 CI: build documentation, too
I've bumped Sphinx because this might be needed for proper support of
pbr-provided version numbers. In the end I also had to re-run `pip
install -e .` locally, quite likely due to a different format of version
numbers now that pbr is being used, but let's make sure that we're using
a version of Sphinx that is now known to work.

Change-Id: I451b4b17bb8097eb7f2f0f0956cc1c956a531828
2020-03-27 12:46:53 +00:00
Jan Kundrát
9474ff17de Fix dependency installation with PBR
Ouch, this one hurts. It turns out that PBR-based setup does *not*
install all dependencies when running `python setup.py install`. On the
other hand, running any of:

- `pip install .`
- `pip install --editable .`
- `python setup.py develop`

...makes everything work. So, let's change the instructions and all the
build scripts (including the Docker file) to make sure this thing still
works. Sorry for noise.

This is a significant change, it means that people will have "in-place
installations" of GNPy. Changes to their git checkouts, if used, will
apply, etc. I think this is actually a good change.

fixes #287

TL;DR: package installation with Python is still a mess.

Change-Id: I422b889b599e0b7cae36f160d1548cef7fb50a4e
2020-03-27 13:41:55 +01:00
Jan Kundrát
c675f5bd38 docs: do not reference a non-existing directory
Change-Id: I197956d3b55f0ebcf20cee54d5f2887bbd821fa3
2020-03-25 19:34:42 +01:00
Jan Kundrát
2556658e68 CI: build and test this under Python 3.7 and Vexxhost's Zuul
Change-Id: Ifa849ab8182596dc0285c18365ead806ea9d0bc9
Co-authored-by: Mohammed Naser <mnaser@vexxhost.com>
2020-03-25 19:34:42 +01:00
Jan Kundrát
4d5d10935a Convert to pbr setup
It turns out that our current setup does not really support the `sdist`
Python packaging step. I'm trying to increase automation, both for
making releases for upload to pypi.org, and also for CI via Zuul. As it
turns out, Zuul comes with a set of predefined jobs which -- by default
-- use `tox`, and tox was having troubles dealing with our `setup.py`
because it also assumes that the `sdist` step works. It is also supposed
to:

- fix version number duplication in `setup.py`,
- fix version number duplication in Sphinx docs,
- prevent the need to write a `MANIFEST.in` manually.

TL;DR: insetad of having to deal with a ton of other creative
boilerplate, use tools for lazy people like me, and PBR ("Python Build
Reasonableness") appears to check the marks here.

Change-Id: I27c36c4f6b0e76857d16f7819ec237e9b811476a
2020-03-25 19:34:42 +01:00
Jan Kundrát
eb87e36781 Configuration for git-review
We're still primarily a GitHub project, so it is necessary to add a
pointer for git-review to point to GerritHub (which is our Gerrit
hosting site).

See-also: https://docs.openstack.org/infra/git-review/
Change-Id: I6fe8da2358ae50340fbe384b038ab097ab229b59
2020-03-25 12:50:23 +01:00
Jan Kundrát
14d8d793f3 Fix test failure due to mishandled merge
In commit 80eced8, the structure of parameters to `elements.Fiber` was
changed. Options such as fiber length are now passed in via
`self.parameters.*` instead of `self.*`. Commit 639b379 which fixed a
test failure precedes that change, and when we merge both as I did in
commit bc4b664, the test no longer works. My bad. On the other hand,
this will be caught by trunk gating which is something that Zuul can do,
and therefore something that we'll have in our upcoming CI, yay!

Fixes: bc4b664
Change-Id: Ifcd8f0bf01e9d91dbef3da1aa7f56f89132d6f48
2020-03-24 19:50:24 +01:00
Jan Kundrát
bc4b6642a0 Merge pull request #340 from Orange-OpenSource/correction_test_amplifier
Correction test amplifier

Fixes #324, #321
2020-03-24 16:59:30 +01:00
Jan Kundrát
fe2b39ee3b Merge pull request #342 from jktjkt/pr-337-339
Cleaned-up PRs #337 and #339 which are related to parsing of `STRICT` path requirements in service requests.
2020-03-24 13:51:59 +01:00
EstherLerouzic
d56c91ca7f small linter fixes
(Jan: cherry-picked relevant parts of c6be21f36f)

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ib84f452a15a20a88ea186ceef64712eb967d46a7
2020-03-24 12:07:33 +01:00
EstherLerouzic
25819fadf5 refactor test and add test on constraints
(Jan: cherry-picked relevant changes from commit
44e8936f04d6eb334cea2e5643d8ddceb6a0a5a8)

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Signed-off-by: Jan Kundrát <jan.kundrat@telecominfraproject.com>
Change-Id: Ibeeaa42b35e23075618c8543a857f47fac48df27
2020-03-24 12:05:56 +01:00
EstherLerouzic
0cacb8851d Fix node_list and "STRICT" checking
The check on node_list constraint has to be be done on all elements except the last one,
and the last one is always a "STRICT" value. this means that if no constraints are given
this list is equals to ["STRICT"]. Previous code was using len("STRICT") ie 6 instead of
len(["STRICT"]) ie 1.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2020-03-24 12:00:20 +01:00
Jan Kundrát
14f98836ed Merge pull request #341 from ojnas/import-xlsx
Enable import from .xlsx files
2020-03-23 11:17:34 +01:00
Jan Kundrát
82ce3384ba tests: Use XLSX for the CORONET topology
Now that XLSX is officially supported, it should be tested as well.

Change-Id: I9286d3cb56950d554582d2eaf8153da5ffdd771a
2020-03-21 13:19:24 +01:00
Jan Kundrát
1f1877f7a9 tests: do not hardcode file suffix lengths
This will become useful for XLS -> XLSX conversion.

Change-Id: I025e4c24d00526d3bb48c23dcbdc82a65be9a477
2020-03-21 13:19:24 +01:00
Jonas Mårtensson
db26ce07db Enable import from .xlsx files
Fixes issue #336
2020-03-20 18:17:02 +01:00
Jan Kundrát
e08ae9c959 Merge PR #329 into develop
This is a continuation from #319. The singleton-ish interface has not
been changed yet.

Change-Id: I93c8f1145561184f6e91f7e8f7debd3b48936205
2020-03-19 17:15:14 +01:00
EstherLerouzic
2de1b5567a updating test_compare_nf_models to correctly compare variable gain with polynomial
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2020-02-24 09:53:08 +01:00
EstherLerouzic
639b379a5b Updating ase test to handle the variable gain setup
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2020-02-21 16:23:11 +01:00
Mohammed Naser
0465397b1d Add empty Zuul configuration
In order for Zuul to start self-testing, it must actually have
a project entry listed.  This is the initial commit.

Change-Id: I017cb036f3191e46446d82b96a6acd35f2adcd0e
2020-01-28 20:20:41 +01:00
Jan Kundrát
d3ec39d506 Bump version to 2.1
Change-Id: I9f27fc87c5ca43e473fe212d2ee3dad7b12d4061
2020-01-15 00:09:48 +01:00
Jan Kundrát
bfe68a5948 Merge branch 'develop'
Change-Id: If7860b243cb504613a7fffafad2d601510000af7
2020-01-15 00:09:18 +01:00
Esther Le Rouzic
2ea3363613 Merge pull request #331 from Orange-OpenSource/pr_test
update version setup.py
2020-01-14 13:02:32 +00:00
DELFOUR Emmanuelle TGI/DATA-IA
89cce6e6a3 update version setup.py 2020-01-14 10:22:21 +01:00
Jan Kundrát
0f10ac706c Merge pull request #267 from Orange-OpenSource/capacity_planning-part2
This brings in the concept of OMS (so far created implicitly based on the input topology), spectrum assignment, etc.
2020-01-13 09:30:45 +00:00
EstherLerouzic
66d26f0ffa add the missing else to handle non first_fit policy
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2020-01-10 18:46:24 +00:00
EstherLerouzic
3c96914482 replace todo with TODO
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2020-01-10 18:41:40 +00:00
EstherLerouzic
61b1e73362 remove unused testing piece of code
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2020-01-10 18:40:18 +00:00
Jan Kundrát
03435079cc refactoring: simplify code flow a bit
- no need to explicitly log exceptions that are about to be raised
- kill some extra commented-out prints

Change-Id: I73bae5a2456644c4d4ff45bd984d44c27bc22ec4
2020-01-10 18:17:44 +00:00
Jan Kundrát
6661907c1d fix typos
Change-Id: I0a4d2c14c5e873dd521736525bb9b10c9b70975b
2020-01-10 18:17:17 +00:00
Jan Kundrát
fe811f725c tests: use native pytest features for exception handling
Using `with pytest.raises` is better than open coding the equivalent
feature. Similarly, when a block is not expected to raise an exception,
let's just let it run outside of a `try` block and rely on the test
framework to report a possible failure when hitting an unhandled
exception.

Change-Id: Icb1bb83e649733b56fcdc9168cabf88c9cf8d478
2020-01-10 18:16:53 +00:00
AndreaDAmico
80eced85ec Refactoring with some incompatible changes
Please be advised that there were incompatible changes in the Raman
options, including a `s/phase_shift_tollerance/phase_shift_tolerance/`.

Signed-off-by: AndreaDAmico <andrea.damico@polito.it>
Co-authored-by: EstherLerouzic <esther.lerouzic@orange.com>
Co-authored-by: Jan Kundrát <jan.kundrat@telecominfraproject.com>
2019-12-17 11:51:09 +01:00
AndreaDAmico
2960d307fa Unrelated changes
linter changes

Signed-off-by: AndreaDAmico <andrea.damico@polito.it>
Co-authored-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-12-17 11:13:00 +01:00
AndreaDAmico
c41cddfff5 Introduce new parameter structure for all Fibers
The Polito team wanted to have a single object with all parameters
required for each `Fiber` instance -- apparently for better code
readability.

Signed-off-by: AndreaDAmico <andrea.damico@polito.it>
Co-authored-by: Alessio Ferrari <alessio.ferrari@polito.it>
Co-authored-by: EstherLerouzic <esther.lerouzic@orange.com>
Signed-off-by: Jan Kundrát <jan.kundrat@telecominfraproject.com>
2019-12-17 11:12:52 +01:00
Jan Kundrát
8598e6591f Merge pull request #304 from Orange-OpenSource/user_error_catching_improvment
Give more useful comment for user to correct topology
2019-12-12 16:11:54 +00:00
EstherLerouzic
5e2259062c Give more useful comment for user to correct topology
when a node name used in link does not correspond to listed
node names, Bad link msg was thrown without info on which link
causes the problem.
This change gives additional info on link and catch the user error
more cleanly.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-12-12 15:55:33 +00:00
Alessio Ferrari
d483802a86 Edn-to-end test for Raman amplification 2019-12-12 12:52:59 +00:00
Jan Kundrát
9a0eece69c Merge pull request #322 from jktjkt/master
docs: Link to the updated meeting event
2019-12-09 20:46:06 +00:00
Jan Kundrát
1657bfd05f build: workaround Sphinx doc build failure
Upstream bugreport at sphinx-doc/sphinx#6887 suggests that this is due
to pip picking up the 0.16b0.dev0 pre-release...

Bug: https://github.com/sphinx-doc/sphinx/issues/6887
2019-12-09 16:05:56 +01:00
Jan Kundrát
49bf558916 docs: Link to the updated meeting event 2019-12-09 14:31:59 +01:00
Jan Kundrát
99f44a597b Merge remote-tracking branch 'origin/develop' 2019-11-13 19:59:35 +01:00
Jan Kundrát
a21f3fe6ee Merge pull request #312 from jktjkt/fixes
Small refactoring for itufs/utifl
2019-10-16 05:38:37 +00:00
Jan Kundrát
0ccbb2960c Merge pull request #277 from Orange-OpenSource/capacity_planning-part1
Capacity planning part1
2019-10-16 05:36:56 +00:00
EstherLerouzic
c577a75725 second set of modification due to codacy report
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-10 09:02:19 +01:00
EstherLerouzic
8827e0cf6f Codacy report: minor changes (trailing spaces, ...)
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-10 09:02:19 +01:00
EstherLerouzic
b0012fe399 SA: process also the case when pth is empty
TODO: a path containing only transceivers and no roadms leads to no oms
this has not been properly taken into account. (single link w/o ROADM
has no SA complexity and is out of the scope)

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-10 09:02:19 +01:00
EstherLerouzic
31e634615b Complete test on response comparison
If request is bidir and 'z-a-path-metric' is missing, raises an error
If present, should not raise an error

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-10 09:02:19 +01:00
EstherLerouzic
8300a55e39 Update test file with correct SA (due to bidir correction)
reversed path must be taken into account for spectrum assignment

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-10 09:02:19 +01:00
EstherLerouzic
5b939bc57a Improve compare_response function
remove some prints, indicate which from actual or expected key
is printed.
preceise that test is also performed on values

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-10 09:02:19 +01:00
EstherLerouzic
2f1ab9cc50 Create a SpectrumError(Exception)
Create an exception in case of an error due to spectrum problem
eg if spectrum request is not correct
if values are not correct.
use it instead of exit

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-10 09:02:19 +01:00
EstherLerouzic
42ba3eb98d Add a test to go through the new added code in spectrum_assignment
Verify that there is no raised error if M=0 and the blocking attribute is there

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-10 09:02:19 +01:00
EstherLerouzic
9eb87fc8e1 raise error instead of exit in assignment
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-10 09:02:19 +01:00
EstherLerouzic
8fab9bb945 Raise exceptions instead of exit()
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-10 09:02:19 +01:00
EstherLerouzic
1ead232a78 Do not block computation if M=0
When a request is blocked and its M value is set to 0. This should not raise
an error in pth_assign_spectrum. This test verify that the function
does not raise an error.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-10 09:02:19 +01:00
EstherLerouzic
b15c8c60ab Add a DisjunctionError exception and use it
in case there is no possible disjoint path with the added constraints
(most of the time due to an inconsistant user request)

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-10 09:02:19 +01:00
EstherLerouzic
66bdeb0e4d Catch Service error exception in the main program
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-10 09:02:19 +01:00
EstherLerouzic
1a2e090104 Move all main program into a main function in path_requests_run.py
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-10 09:02:19 +01:00
EstherLerouzic
a8e280e29b Remove exit and use ServiceError exception instead
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-10 09:02:19 +01:00
EstherLerouzic
edb54b02ac Another time improving formatting (codacy report)
removing unused import
change short variable names to conform to [a-z_][a-z0-9_]{2,30}$
change main variable names to conform to [A-Z_][A-Z0-9_]{2,30}$
add or remove spaces
add docstrings
correct comments and indents of cut lines

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-10 09:02:02 +01:00
EstherLerouzic
83d3f32fe0 Precise type of exception (codacy report)
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 19:17:35 +01:00
EstherLerouzic
085a379592 improving formatting (codacy report) of path_requests_run, request and service_sheet
remove unused imports
add docstrings
conform to '[A-Z_][A-Z0-9_]{2,30}$' pattern in main
remove trailing spaces
add/remove extra spaces

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 19:17:35 +01:00
EstherLerouzic
37bd5d0404 Code coverage improvement test service creation w/o sync vector
add one service  only excel file + changes on compare.py to support
no synchronization vector case

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 19:17:35 +01:00
EstherLerouzic
f788b81d21 Code coverage improvement test json generation with Z to A direction
add aa bidir request to test service error handling
TODO: write more detailed test on the bidir case

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 19:17:35 +01:00
EstherLerouzic
2ff1ce6b34 Code coverage improvement test ServiceError handling
For this purpose we create a wrong request with M=0 and verify
that serviceError is correctly raised when calling Result_element class

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 19:17:35 +01:00
EstherLerouzic
41a1e40d14 Update test data files
- add the bidir information on json expected services,
- add the label object in json responses
- add the spectrum on csv responses
- add the no-path container when relevant

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 19:17:35 +01:00
EstherLerouzic
921e8d2d3c Call build_oms_list in test_disjunction
Call bbuild_oms_list in the test to correctly build all attributes
of network elements

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 19:17:35 +01:00
EstherLerouzic
c009d28f7d Update test_disjunction and test_automaticmodefeature
Add bidir argument on load_requests calls

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 19:17:35 +01:00
EstherLerouzic
898eada097 Update test_parser
function compute_path_with_disjunction needs an additional reversed path
and results must contain wavelength assignment

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 19:17:35 +01:00
EstherLerouzic
bdfc55e801 Add a ServiceError(Exception) for malformed user requests
For example requested bandwidth should be >0

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 19:17:35 +01:00
EstherLerouzic
57f264bedb Change name of br and pw variables to brate and pwr
To conform to [a-z_][a-z0-9_]{2,30}$

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 19:17:35 +01:00
EstherLerouzic
fbe4fa3cf0 add docstring to functions
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 19:17:35 +01:00
EstherLerouzic
b2ef345f35 Cut long lines over 100 char
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 19:17:35 +01:00
EstherLerouzic
471ea7dfba Correct indentation due to linter report
using pylinter3
recommends having cut lines with same indent as starting [ or (

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 19:16:36 +01:00
EstherLerouzic
1b52f638ff other time: Correct indentation due to linter report
using pylinter3
recommends having cut lines with same indent as starting [ or (

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 19:16:36 +01:00
EstherLerouzic
84ab38a75f Another time: removing extra spaces, trailing spaces and adding missing spaces
for codacy report:
     removing extra spces before , and :
     adding spaces after , :
     adding spaces around < > =

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 19:16:36 +01:00
EstherLerouzic
916e5377f8 change variables d, el to conform to '[a-z_][a-z0-9_]{2,30}$' pattern
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 19:16:36 +01:00
EstherLerouzic
534bfd881e correction of the assignment: SA must be bidir
reversed path must be computed even if bidir is not requested
because in WDM system service are all bidir.
bidir option is only to avoid lengthy propagation of reversed
path when it is not needed

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 19:16:36 +01:00
EstherLerouzic
7c4015324d Moving reversed path computation and propagation to compute_path_with_disjunction function
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 19:16:36 +01:00
EstherLerouzic
8499ee52f4 Removing extra spaces, trailing spaces and adding missing spaces
for codacy report:
 removing extra spces before , and :
 adding spaces after , :
 adding spaces around < > =

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 19:16:36 +01:00
EstherLerouzic
cc1123863c Cut long lines to 100char max due to linter report
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 19:16:36 +01:00
EstherLerouzic
ca382806f6 Reordering imports due to codacy report
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 19:16:36 +01:00
EstherLerouzic
3559fc61c2 Introduce reversed path on CSV output
- use a new jsontopath_metric function to collect metrics
  out of a json response.
- path metrics must be shown also for reversed path if this
  is requested. This function avoids repeading code here
- add reversed metrics on the last columns of the CSV

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 19:16:36 +01:00
EstherLerouzic
33581cdcc9 Add bidir as a parameter in path_requests_run.py
if --bidir option is used on the main program, the field is set
  to true for all demands in case demands are expressed in an excel
  sheet. --bidir option does not change bidir field if the service
  file is in json format.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 19:16:36 +01:00
EstherLerouzic
991eb02964 Add the bidir parameter in transmission_main_example.py
Update the program because the same Path_request class is called
that now includes this bidir field

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 19:16:36 +01:00
EstherLerouzic
286e321a2d Add "bidirectional" field in the json service file example
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 19:16:36 +01:00
EstherLerouzic
56f158113d Implementation of bidirectional field per request
- Instead applying bidir option independantly from service demands (json or xls)
  the "bidirectional" attribute is introduced per request in the json.
  This enables bidirectional option per requests.
  if --bidir option is used on the main program, the field is set
  to true for all demands in case demands are expressed in an excel
  sheet. --bidir option does not change bidir field if the service
  file is in json format.
  Default value of "bidirectional" attribute is False.
- As a result the reversed path is propagated only if the birectional
  field of the request is True. (remember that the reversed path must
  be computed whatever the option because it is needed to compute
  spectral occupation on both directions).

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 19:16:36 +01:00
EstherLerouzic
024f6ff963 Simplification de stdout
all BLOCKING_NOMODE requests have the same type of response
so the test is simplified to account for this

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 19:16:36 +01:00
EstherLerouzic
8118a0f4f4 Second minor cosmetic changes
- add some help input for the main program arguments
- move and correct comments
- add empty lines on stdout to have a nice printing

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 19:16:36 +01:00
EstherLerouzic
eb89d8fd86 Minor cosmetic changes
correct typos in comments and precise that results show the
mean value of SNR of all channels on stdout

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 19:16:36 +01:00
EstherLerouzic
a938c1738b add reversed path information on stdout
the information on reversed path snr is shown in parenthesis

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 19:16:36 +01:00
EstherLerouzic
4f88882513 Use reversed path as a constraint for spectrum assignment
in path assignment function, path elements and reversed path
elements are concatenated to compute the overall spectrum
availability on all elements

in main program, assignment is performed after computing reversed paths

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 19:16:36 +01:00
EstherLerouzic
4e8d8b7ddd adding reversed path in the main program
add a bidir argument to make bidir propagation as optional.
Reversed path computation is not optional because it is needed
for spectrum assignment.
for all requests, if a path could be computed  a reversed path is
computed and propagation is performed on it if bidir option is on.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 19:16:36 +01:00
EstherLerouzic
afb7d75749 Add the reversed path as an attribute of Result_element
the objects contains also the information of reversed path if
the path is not None

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 19:16:36 +01:00
EstherLerouzic
488d0e1fe8 Change find_reversed_path function using the reversed_oms
reversed_oms was introdused in order to identify which oms correspond
to the reversed direction of a given oms.
with this commit we make use of this functionality and avoid the cumbersome
way that recovered the reversed path by computing shortest path in the
reversed way for each roadm. This function could not support multiple links
in parallel between two roadms, and was adding computation time.

The function first lists the oms of the pth in the reversed order and then
appends all its elements to the path. the first and last elements are transponder
and are append separately.

Unidir topology are not supported: if there is no reversed path, this raises an error

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 19:16:36 +01:00
EstherLerouzic
708442e4cd Introduce a reverse_oms function to identify bidir oms
reversed_oms is introdused in order to identify which oms correspond
to the reversed direction of a given oms. Indeed for spectrum assignment
it is mandatory to mark spectrum resources occupation on both directions
(requests are supposed bidirectional in WDM).

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 19:16:36 +01:00
EstherLerouzic
a2d905dfb1 Add N and M info in the stdout
the couple (N,M) is displayed only when a request is not blocked

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 19:16:36 +01:00
EstherLerouzic
d564fe3e2a Add N and M info in the CSV
The couple (N,M) is added on the last column only for non blocked requests
an empty string is used instead

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 19:16:36 +01:00
EstherLerouzic
ea21cce1c0 Add N and M in the json response
The label object is added in the response. It contains center index N value
and number of slots M, required by the request according to the computation.

The label object directly follows the hop attribute as detailed in
draft-ietf-teas-yang-path-computation.

If the path is not blocked this changes the index of the last hop information
(-3 instead of -2) and the index of the transponder for the first hop
(2 instead of 1)

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 19:16:36 +01:00
EstherLerouzic
aa9b4aefbe Add the N and M information in request when spectrum is assigned
N is the center frequency index (on G694.1 grid) and M the number of slots M,
required by the request according to the computation.
for convenience, we use N and M = 0 when request are blocked. Note that N= 0 is
a valid index when M is not 0.

If the number of slot required by a request is not feasible, the request is marked
as blocked with 'NO_SPECTRUM' as blocking reason

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 19:16:36 +01:00
EstherLerouzic
8655030e59 Add blocking reason on stdout
previous way only check path existence to know if the request was blocked
or not.
Now the printing checks if the blocking_reason attribute exist, and if so
adapts the printing accordingly. The reason for blocking is added on the
output.

if no path could be computed, snr, osnr and other metrics depending on path
are replaced by empty strings
else, the metrics corresponding to the computed path are shown

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 19:16:36 +01:00
EstherLerouzic
8107ddeb79 Change the processing of blocking case in main program
In compute_path_with_disjunction, and in case user mode is not feasible
returns the blocking reason instead of an empty path.
If the user does not give the mode and the automatic selection does not
give any feasible mode instead of checking if a mode exists, the function
now checks the presence of a blocking reason.

if the blocking reason is among BLOCKING_NOPATH reasons, than an empty
path is returned
if the blocking reason is among BLOCKING_NOMODE, then a path could be computed
and the mode information correspond to the last explored mode.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 19:16:36 +01:00
EstherLerouzic
76c8e55f06 CSV generation is adapted to include blocking info
creation of a function to avoid code duplication: json_param creates
the relevant parameters to show on the csv based on json input

replace try/except by a test on keys:
previous way tried to get pth_el['no-path'] and is the path was
not blocked this raised a key error. Now the there is a simple check if
the key is present.

Besides, as the no-path has been change to 'no-path' container containing
a 'no-path' attribute with the blocking reason, the test is made on the
attribute so on pth_el['no-path']['no-path'].

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 19:16:36 +01:00
EstherLerouzic
a7b1ab47d8 adapt response from the compute_constrained_path to return info in case of blocking
if the path is empty NO_PATH reason or NO_PATH_WITH_CONSTRAINT reason
is returned in the blocking_reason attribute

if no mode is feasible, the last explored mode is returned with the path (and
implicitly the last computed SNR). The baud_rate is derived from this last
mode

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 19:16:36 +01:00
EstherLerouzic
879f587ab9 Adapt json response to include information in case of blocking
if path could be computed: gives details of the path and on the propagation.
  - the 'no-path' attribute is changed to a 'no-path' container that contains:
      o the 'response-id' attribute
      o a 'no-path' attribute with blocking reason
      o if a path could be computed, the 'path-properties' of the path that
        was computed with the metrics

Note that this proposal to add information for blocking in the json output (instead
of a bare NO PATH) corresponds to the way PCEp is working in general, but is not yet
integrated in draft-ietf-teas-yang-path-computation model. Returning the whole path
in case of blocking in addition to blocking reason is a novelty from GNPy and was a
request from the users
        TODO : use correct ietf model when ready

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 19:16:36 +01:00
EstherLerouzic
8af2d80219 Add reasons for blocking in the response
Before continuing on spectrum assignment we need to clearly identify blocking reasons:
implicit previous way (a path is missing) is not satisfactory because in case of
spectrum blocking a path was possible. So we introduce a 'blocking_reason' attribute
on requests, that will only exist if the path is blocked during the process.
The 'blocking_reason' attribute refflects the blocking reason.
Commit defines blocking types and group them depending on the existence of path or
feasibility:
    'NO_PATH': no path was computed,
    'NO_PATH_WITH_CONSTRAINT': no path was computed with this constraint
    'NO_FEASIBLE_BAUDRATE_WITH_SPACING': no path was computed due to the spacing constraint
    'NO_COMPUTED_SNR': the computed path could not give any SNR result
    'NO_FEASIBLE_MODE': the user let the program choose a mode and path was computed but
                        no mode was feasible for the set of constraints
    'MODE_NOT_FEASIBLE': the user imposed a mode, a path was computed but this mode
                         is not feasible
    'NO_SPECTRUM': a path, a mode were selected but there is not enough spectrum available on
                   this path

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 19:16:36 +01:00
EstherLerouzic
315eea1f55 Calling assignment in main program path_requests_run.py
function is called to assign spectrum to each request
result shows an additionnal column for blocking reason

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 19:16:36 +01:00
EstherLerouzic
b61e541e15 pth_assign_spectrum function assigns wl for all demands
this is a first function that assigns spectrum following the order
of requests according to the selected mode and nb of channels computed
based on requested path_bandwidth

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 19:16:36 +01:00
EstherLerouzic
81f88e78c7 Creation of the OMS structure to record spectrum assignment
oms_list contains the list of OMS and each OMS contains the list
of uid of each crossed elements (ordered)
each element is updated with the oms_id to which it belongs
each oms contains a bitmap with frequency slots according to
frequency min max defined in eqpt_config.json (SI) and in case oms
are defined elsewhere, there is an alignment of grids to ease computation
the build_OMS_list function builds the OMS list and implements oms attributes
in all network elements
Commit also contains basic functions to handle spectrum bitmap and indexes

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 19:16:36 +01:00
EstherLerouzic
87cc3dac00 Corrections with respect to second review
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 19:09:39 +01:00
EstherLerouzic
89e28cc7be Correct bug in parser: csv header comparison
previous comparison was done on the result from .sort(), ie None.
list.sort() method modifies the list in-place and returns None.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:42 +01:00
EstherLerouzic
2ba29a78c5 Bug: constraint not correctly interpreted
if name of the constraint input from user is not part of networks names
(typically in the case of excel input), then the program try to find a
name that is clode to the user name and  that is in the network list of
names. This list must not include trnasponder names (because transponder
end points are already listed as constraints and transponder in the
middle of a path are not supported yet)
This will be improved in the PR Ila names in constraints #278
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:42 +01:00
EstherLerouzic
f990a6c1be Correct some remaining strict loose into STRICT LOOSE
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:42 +01:00
EstherLerouzic
424e5a4786 change variable n to nel to conform to '[a-z_][a-z0-9_]{2,30}$' pattern
from codacy report

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:42 +01:00
EstherLerouzic
6a7a04ebb1 syntax correction
reordering imports call according to pylint3 + extra line removed

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:42 +01:00
EstherLerouzic
0366fc2956 Adding a no-path case for test coverage
add a no path case (request 6) in requests and expected responses.
response is also generated if path is not feasible: checks
that it is correctly handled in csv and json responses

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:42 +01:00
EstherLerouzic
48b7d71f02 add a test on json response generation
create a json response based on test file and compare it to expected
response.
comparison first checks that there is no missing or extra key
and then compares keys

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:42 +01:00
EstherLerouzic
715baf2a1c correct compare response header test to support any order
previous test assumed same order for header fields.
order the headers in the same way in order to support different
types of order

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:42 +01:00
EstherLerouzic
e55cea776e improve code quality
remove unused import, use correct indents, remove extra spaces
add function description

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:42 +01:00
EstherLerouzic
b388d143fd change assert to raise AssertionError
use
  if not condition:
  raise AssertionError()
instead of
  assert condition
according to codacy recommendation

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:42 +01:00
EstherLerouzic
c592c572d8 adding a test for the csv creation
using pandas package to have an easy ordering of response column:
- test that the generated header is as expected
- read the response. In order to support different orders wrt
  response answer and field answer, test function frst orders lines
  according to response index and then to columns (fields of the answer).
check that the answers are as expected

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:42 +01:00
EstherLerouzic
dfa0a26a28 changes to improve quality
minor name refactor
indent corrections
minor fixes for spacing

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:42 +01:00
EstherLerouzic
609cd94798 Remove @ in path-metric names and extend type to decimal64
@ character not correctly read with OpenDayLight yang tool used
for transportPCE project.
https://docs.opendaylight.org/en/stable-nitrogen/developer-guide/yang-tools.html#working-with-yang-model.
Changed the names of path metrics from osnr@ to osnr-

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:42 +01:00
EstherLerouzic
022f743db1 Change the exception handling if sync vector is absent
previous try section encompass errors that should not be silently
ignored. Correction pointed a default in a test file.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:42 +01:00
EstherLerouzic
1957beb1b6 Remove the filtering on transponders for correcting explicit route
anytype supported including transponder in order to accept well formed
route list from user (if user enters 'trx Lannion_CAS' this should be
accepted even if it repeats the source name)

A later PR better handles route list names

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:42 +01:00
EstherLerouzic
9ca72d6105 Correct csv creation in case of no path
previously reported the requested bandwidth, now fill it with an
empty string, same as the other fields.

This will be updated in a later PR when different kind of blocking
will be supported

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:42 +01:00
EstherLerouzic
e8e126a6ce update existing test files and examples according to ietf yang model
- 'loose' and 'strict' changed to 'LOOSE' and 'STRICT'
    - n, m changed to N, M
    - unused objects removed
    - ...
Also correct templates for service and response

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:42 +01:00
EstherLerouzic
7849782173 Change content of source and destination to transponder end-points
previously contained the user-given source name in excel file,
but could differ from effective transponder source/destination

now both source and src-tp-id contain the same info (gnpy does
not make difference between node and ports)

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:42 +01:00
EstherLerouzic
149a0da8c9 update csv creation according to all model changes
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:42 +01:00
EstherLerouzic
1e7c70a59b remove the restriction on fiber for the constraint
restriction was placed on fiber type because when using excel input
autodesign create fiber names with syntax not explicit to the user, so that
entering a node name as constraint may end up to a wrong interpretation eg
aa -bb  -> create names such as 'fiber aa to bb', fiber bb to aa' .
If user constraint is bb there is a ambiguity on the fiber direction.
However this is not a problem for user using json format.
So I preferred to removed this constraint now.
a later PR solves this naming ambiguity

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:42 +01:00
EstherLerouzic
c9d8282e7f enable power and nch to be optional in requests definition
since empty attributes have been removed from the requests with
previous changes, some aditional tests are needed to continue supporting
optional power and nch. (previous objects were created with null
or default values)
user may enter requests without specifying these fields, in this
case the object 'output-power' or 'max-nb-of-channel' do not exist.
the try /except form handles the corresponding exception and
default values are kept else.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:42 +01:00
EstherLerouzic
e7084a2c29 correction to support empty vectors of constraints
change the naming according to model update +
previous changes authorize empty list of nodes.
This new test supports this case

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:41 +01:00
EstherLerouzic
d79d2e0724 change the way transponder and mode are returned in the response
previous way used a wrong interpretation of hop-type. in ietf model,
hop-type is reserved for LOOSE or STRICT constraint description.
Instead, transponder info , according to ietf usual way, should be
included aas a new path-route-object type. such object is not yet
defined in IETF so this is a GNPY proposal to use a 'transponder' object
with type and mode attributes.
this is what has been ecncoded in reques.py for requests and for answers

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:41 +01:00
EstherLerouzic
402155c225 change the 'no path' case answer
in case no path could be computed, the answer is changed according to
ietf path-computation model to a simple 'no-path' object

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:41 +01:00
EstherLerouzic
e5ec669419 applying changes in the request dict creation
+ removing (currently) unused direction attribute.
This will be added again in a later PR when it will be used

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:41 +01:00
EstherLerouzic
8f424e8c9d correction of json generation: removing unused objects
- removing empty objects (if no content , removes the object),
    especially
  - removing empty synchronization vector if no disjunction
    constraint exists
  - removing optional power and nb of channel fields, if user
    did not specify any
when reading, first try if the object exists : try:/except to catch
this case
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:41 +01:00
EstherLerouzic
fea2b84bb9 correction of the json generation for path computation
- changes concerning names due to ietf path-computation draft changes:
        - 'unnumbered-hop' changed to 'num-unnum-hop'
        - suppression of 'label-hop'
        - 'link-diverse' and 'node-diverse' changed to 'disjointness'
      - correction because of previously wrong interpretation of the model:
        - detailed succession on include nodes moved from
          'optimisation /explicit-route-include-objects'
          to 'route-object-include-exclude'
          in 'explicit-route-objects' attribute
      - correction of keywords
        - n and m replaced by N and M
        - strict and loose replaces by STRICT and LOOSE strings
        - change the name of respponse from 'path' to 'response'
    example service file  corrected accordingly

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:41 +01:00
Jan Kundrát
0c918940c4 Merge pull request #313 from jktjkt/codacy-assert
codacy: do not complain about asserts in the test suite
2019-10-06 21:49:22 +00:00
Jan Kundrát
a63a6ac0ec codacy: do not complain about asserts in the test suite
Writing an explicit comparison followed by argument printing *and*
handling the final error is just backwards. Let the tool be quiet, this
nonsense does not really add any value.
2019-10-06 23:12:09 +02:00
Jan Kundrát
9f58b914d2 Merge pull request #308 from jktjkt/osnr-bw-printing
Rework OSNR printing
2019-10-06 19:17:46 +00:00
Jan Kundrát
029bac4b03 utils: more descriptive name for itufl
This might have nothing to do with the ITU frequency grid (it's really
just about a uniform distribution), so let's give it a more readable
name and more readable parameters.
2019-10-06 20:43:50 +02:00
Jan Kundrát
a27ad57220 Do not use confusing default values
This looks like the root cause of bug #243, the default values suggested
that this function works in THz.

These defaults are not used anywhere, so let's get rid of something
which adds no value and actively confuses people.
2019-10-06 20:38:31 +02:00
Jan Kundrát
8d31d924f2 Remove unused function 2019-10-06 20:37:24 +02:00
Jan Kundrát
8c3b514f90 Only print out "pretty summary" when not doing the power sweep 2019-10-01 15:24:40 +02:00
Jan Kundrát
3df27fe315 Print both ASE-OSNR and final GSNR for both 0.1nm and signal-bw in power sweep
As agreed upon during today's coders call, this is something that is
needed by actual users in the field, so let's prioritize their needs
over clarity of output for demo purposes.
2019-10-01 15:21:34 +02:00
Jan Kundrát
a6087ce354 Highlight OSNR @ 0.1nm
Esther and Jonas pointed out that it is much more common to work with
OSNR measurements per 0.1nm rather than per signal bandwidth. This is in
line with what OSAs usually report and what transponder datasheets
specify.

cc #307
2019-09-27 09:22:08 +02:00
Jan Kundrát
aae0382523 docs: show a DOI
As per Alessio's request, this adds a DOI and makes this software
citeable. DOIs are assigned automatically via Zenodo in a process that's
integrated with GitHub.
2019-09-23 18:11:44 +01:00
Jan Kundrát
b0c2acb1b5 Merge pull request #302 from Telecominfraproject/develop
Merge develop into master in preparation for the 1.8 release

Highlights for the upcoming release:

- Raman simulation
- automatic building of Docker images
- bugfixes, refactoring, CI and docs improvements
2019-09-23 16:51:28 +00:00
Jan Kundrát
a52c96ae2e Merge pull request #301 from jktjkt/develop
docs: Explain how to use Docker
2019-09-22 23:36:44 +00:00
Jan Kundrát
bf28821b5b Merge pull request #299 from jktjkt/cleanup-printing
(This replaces #261 by me and #293 by Jonas.)

##     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

## 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: 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.
2019-09-22 23:32:36 +00:00
Jan Kundrát
328bd6ea71 docs: Explain how to use Docker 2019-09-23 00:29:59 +01:00
Jan Kundrát
ec9eb8d054 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.
2019-09-23 00:14:56 +01:00
Jan Kundrát
f8c8526045 docs: remove duplicate cd
This whole section should be nuked, but that will have to wait until
after the next release for simplicity.

fix #283
2019-09-23 01:03:30 +02:00
Jan Kundrát
d8c236bb44 examples: do not measure time taken
This is an equivalent of 9c9e3be967 for
the other example.
2019-09-22 16:44:00 +01:00
Jan Kundrát
33ff0910b8 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.
2019-09-22 12:20:11 +02:00
Jan Kundrát
faa69917d9 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.
2019-09-20 17:11:42 +02:00
Jan Kundrát
d9f5ca9827 docs: Document Transceiver.mode.OSNR
I am not changing the JSON key name now because of the plan to go with a
full-blown YANG model (see #266).

fixes #298
2019-09-19 09:44:56 +02:00
Jan Kundrát
c817ef7335 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.
2019-09-19 09:25:31 +02:00
Jan Kundrát
07de489d6b 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.
2019-09-19 09:25:31 +02:00
Jan Kundrát
acafc78456 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
2019-09-19 09:25:31 +02:00
Jan Kundrát
325721545e Docker: array for CMD is more idiomatic
Co-Authored-By: Jonas Mårtensson <jonas.martensson@ri.se>
2019-09-18 13:15:20 +02:00
Jan Kundrát
dbe2bf560c Travis: Docker: Fix version numbers
This is due to travis-ci/travis-ci@7422.
2019-09-17 21:03:58 +02:00
Jan Kundrát
7872cc2203 Merge pull request #295 from jktjkt/docker
Automatic building of Docker images
2019-09-17 18:44:50 +00:00
Jan Kundrát
25b4d0e755 Automatic building of Docker images
A third, independent job in Travis CI just for building a container
image (and testing it a little bit). Here's how to use it once it is
built and published and pulled:

  $ docker run -it --rm --volume $(pwd):/shared telecominfraproject/oopt-gnpy

One can also pass commands to it directly. Note that the *relative* path
specifier given as `./` is required. One could possibly get around it by
$PATH manipulation, but hey, I have to stop somewhere.

  $ docker run -it --rm --volume $(pwd):/shared telecominfraproject/oopt-gnpy ./transmission_main_example.py

Thanks to Jonas for the --volume option trick and for that early
non-overwriting copying for the example directory.

The `install` phase in Travis CI is apparently common for all jobs in
the build matrix (it's rather confusing what they call a "stage" and
what is a "job" for them, and what their mutual relation is). Because
there's no point in doing any kind of installation in case when we're
building for Docker, let's just move the old `install` block into
`script`. With just that, however, Travis adds an implicit `pip install
-r requirements.txt` in an attempt at being helpful. In short, having
completely different "stuff to be done as a check" is very painful with
Travis.

The individual "script lines" in a job's `script` section are always
executed, all of them, even if a previous one failed. That's why I moved
the actual Docker invocation into an external shell script. When they
were not in a shell script and the script lines contained `set -e`, then
a failure of a particular command would cause the build to be marked as
"errored" instead of "failed" within Travis. Also, the multiline if
conditionals were rather painful to write.

One commit might end up in different branches. If that happens, the
second build would overwrite the image tag in the docker registry, which
is rather suboptimal. Let's try to fetch that image first, and only
update the latest/stable tags if the image was already available
beforehand.

fixes #260
2019-09-17 20:37:45 +02:00
Jan Kundrát
9af1c90664 Merge pull request #249 from jktjkt/bug-243
Do not mix THz and Hz
2019-09-04 08:18:49 +00:00
Jan Kundrát
6b4d44a3f1 Merge pull request #292 from ojnas/fix-snr-per-channel
Fix per-channel SNR output
2019-09-03 08:23:28 +00:00
Jonas Mårtensson
2faf8d2cdd - Fix output per-channel SNR to include contribution from add_drop_sonr and tx_osnr
- Avoid recalculating SNRs in transmission main example since they are already calculated and stored in the Transceiver class
- Also include per channel power (useful for checking tilt) and OSNR ASE in the output
2019-09-03 09:25:09 +02:00
Jan Kundrát
676c94ddf2 Merge pull request #289 from jktjkt/raman-nli-interpolation 2019-09-02 21:02:58 +00:00
Jan Kundrát
6f93b64f84 Simplify logic for showing per-channel results
As Jonas pointed out, the code used to contain a check for non-nan
values, effectively skipping channels where the Raman gain was not
explicitly computed.

Now that we do not introduce NaNs into some channels anymore, this
shortcut no longer works. We could either add explicit filtering for
only showing those channels which are covered by the Raman engine, but
then the result would be rather confusing in the non-Raman case. One
could also add another column with the simulated vs. approximated NLI,
but when I tried this, the output looked a bit cluttered.

I think that the best course of action for now is to just show info
about all channels (if asked by the user). So this is just a cleanup for
a condition which is now always on.
2019-09-02 21:10:20 +02:00
Jan Kundrát
54bf426472 Raman: linear interpolation of channel NLI
The Raman engine computes NLI just for a subset of channels; this is an
important speed optimization because the computation is rather CPU
heavy. However, the code just left NaNs in place for NLI of those
channels which were not explicitly simulated.

This is wrong because these NaNs propagate all the way to the total
input/output powers per the whole spectrum, etc, leading to NaNs being
shown to the user.

This patch uses a very simple linear approximation just in order to
prevent these NaNs.

fixes #288
2019-09-02 21:10:20 +02:00
Jan Kundrát
1862ce9104 Merge pull request #263 from aleFerrari/raman_feature
Raman feature

I've added some very basic documentation (really, just usage instructions). What is still missing:

- more specific docs
- test coverage (right now, there's none!)

We've agreed to merge this sooner rather than later so that more people can reasonably test it. There's a bunch of things that I'm not happy with, such as the default example showing NaNs as the OSNR to the user at the end transponders, etc (I suspect this is due to simulating just some channels and no approximation, right?), but let's solve these based on feedback from testing.

As proposed in my earlier comments, I went ahead and merged the wrapper example code into the `transmission_main_example.py`. So here's what needs to be done in order to "use Raman amplifiers" in a basic example, with no autodesign:

- replace some `Fiber` elements with a `RamanFiber` in the network topology JSON
- invoke the example with a `--sim examples/sim_params.json` which activates the Raman engine
- pass the `--show-channels` flag so that the actual results are visible

This is more or less covered by the docs skeleton.
2019-08-08 12:05:53 +00:00
Jan Kundrát
3771c13d32 docs: basic usage instructions for Raman 2019-08-08 13:38:23 +02:00
Jan Kundrát
f1d0230dad docs: skeleton of Raman-specific properties
What I'm including here are comments from Vittorio (thanks!). It seems
that the majority of actual numeric parameters which drive the
simulation are undocumented, so this one will have to wait for Alessio
or someone else from the Polito team to fill the blanks.
2019-08-08 13:38:23 +02:00
Jan Kundrát
182929cc96 Unify transmission_main_example and the Raman wrapper
There were just these substantial differences:

- the Raman code showed a per-channel SNR summary, this is now
  controlled via the `--show-channels` option

- when a Raman fiber is used the `--sim` option for specifying input
  simulation parameters is now mandatory

I'm therefore merging these two files even though we've rpeviously
decided not to do this -- consult the review comment at
https://github.com/Telecominfraproject/oopt-gnpy/pull/263#discussion_r310506082
and the discussion during this Tuesday's coders call). If this turns out
to be a problem for autodesign, we can always revert this.

One possible catch is that the final "SNR total" shows NaN for the
default Raman example. That's just the way the simulation engine works
right now, I'm afraid. The `--show-channels` options helps a lot.
2019-08-08 13:38:23 +02:00
Jan Kundrát
81585c5a86 Unify implementations of psi computation
Both of these places referred to "eq. 123 from arXiv:1209.0394", the
only difference (apart from the source of the input parameters, beta2
and asymptotic_length) was calling the two branches "SCI" and "XCI" vs.
"SPM" and "XPM".

In this commit I've only moved the code to a single implementation. The
input data are still being read from the same parameters, of course.
2019-08-08 13:38:23 +02:00
Jan Kundrát
2f52c11589 More intuitive name for list of channels where Raman gain is computed 2019-08-08 11:34:33 +02:00
Jan Kundrát
0f4d8573cf Move Raman parameter propagation to gnpy.core.network
Conceptually, this is just about propagating the input parameters (which
drive the simulation) into all RamanFiber instances. The network module
already contains similar functions, let's move it there.
2019-08-08 11:19:25 +02:00
Jan Kundrát
660b8b3c6e Use lin2db() when we have it 2019-08-08 11:16:26 +02:00
Jan Kundrát
71d6a1138c Fix a typo in my e-mail address
This has been around since before 1a104956, but I haven't noticed the
missing `.com`.
2019-08-08 10:53:52 +02:00
Jan Kundrát
a6e741d8fe Do not copy the whole Fiber class 2019-08-08 09:55:23 +02:00
Jan Kundrát
58bcf65cf6 Raman: do not introduce a new copy of the equipment library
Compared to `eqpt_config.json`, the only extra content in the new copy
was the `RamanFiber` block. There's no disadvantage in just using one
equipment library; the traditional code can easily ignore the RamanFiber
stanza.
2019-08-07 23:45:44 +02:00
Jan Kundrát
27ce55de38 diagnostics: Correctly report all spans, not just the Raman ones
It's just a harmless message, the path traversal was still using all
connections as defined in the topology JSON.
2019-08-07 23:41:30 +02:00
Jan Kundrát
36ca22db9b Raman: use logging instead of debugging print()s 2019-08-07 23:31:20 +02:00
Jan Kundrát
33a8de9b39 Raman: stricter validation of input parameters
The goal here is to try to prevent typos in configuration from slipping
in undetected.
2019-08-07 13:36:21 +02:00
Jan Kundrát
22b76e36db Fix typos in Raman's frequency offset
This is a typo, the parameters were clearly supposed to be uniformly
spaced. It doesn't affect the results (much), because the remaining
values are "close enough" for a reasonable interpolation.

Using the existing Raman example, the difference in OSNR ASE at the
signal bandwidth is 0.01 dB (31.46 -> 31.47 dB).

Perhaps it would make sense to enforce that these offsets are a
monotonic sequence.
2019-08-07 13:19:17 +02:00
Jan Kundrát
528ff31590 CI: Run the Raman example as well 2019-08-06 11:56:01 +02:00
Jan Kundrát
4d6966cbd3 Remove unused imports 2019-08-06 11:51:25 +02:00
Jan Kundrát
9c9e3be967 Do not measure time from the example directly
Let users wrap this with the Unix `time` command if they are interested
in the time spent.
2019-08-06 11:49:32 +02:00
Jan Kundrát
2dd4745ef7 Merge pull request #281 from jktjkt/no-convenience-access
Remove property aliases
2019-08-06 09:46:36 +00:00
Jan Kundrát
4e786a32b5 Merge branch 'no-convenience-access' into raman
This required some adaptations in the new Raman code now that the
property aliases are gone.
2019-08-06 11:43:16 +02:00
Jan Kundrát
6ecb2c85e2 Merge remote-tracking branch 'origin/develop' into raman
Required fix-ups:
- ROADM restrictions
2019-08-06 11:34:39 +02:00
Jan Kundrát
cd234a909b Remove unimplemented and unused code 2019-08-06 11:22:56 +02:00
Jan Kundrát
c249f44ea1 Remove property aliases
For some reason, the code allowed using "convenience names" for
accessing properties since commit 58ac717f. To me, this looks like an
obvious anti-pattern because accessing a single property via three
different names only makes the code less readable. Let's kill this
"feature".

In case of the `Power` class, the code used "ase" and "nli" on the
majority of places, so let's use these abbreviations instead of their
spelt-out variants.

SpectralInformation was "clean" already, but there were calls to the
`update()` wrapper around the `namedtuple._replace`.  Given that there
were no property aliases, it's safe to just call `_replace()` directly.

In case of the `Pref` class, once again always use `p_span0`, `p_spani`
instead of `p0` and `pi` -- it's a trivial change.
2019-08-06 11:14:28 +02:00
Alessio Ferrari
ed1f51393a method name for computing NLI updated in sim_params.json 2019-08-01 14:54:33 +02:00
Alessio Ferrari
8bd43130ab modified Raman pumps in the example raman_edfa_example_network.json to make Raman effect more evident 2019-08-01 14:48:16 +02:00
Alessio Ferrari
6c975a53a1 minor fix to eqpt_with_raman_config.json 2019-08-01 14:45:17 +02:00
Alessio Ferrari
8a1001cd40 dynamic evaluation of threshold frequency between near XPM and far XPM 2019-08-01 14:42:47 +02:00
Alessio Ferrari
beb2b576aa changed output of propagate_raman_fiber to return a list 2019-08-01 14:41:40 +02:00
Alessio Ferrari
8f3923046b alpha0 computation moved from NLI solver to Fiber Params 2019-08-01 11:36:32 +02:00
Alessio Ferrari
88c68d2065 introduced classes for the parameters 2019-08-01 11:32:07 +02:00
Alessio Ferrari
8bcde72a10 changes on variable names to be more clear 2019-08-01 10:49:25 +02:00
Alessio Ferrari
4653dbcf4b introduced a faster computation for XPM 2019-08-01 10:48:02 +02:00
Alessio Ferrari
cde08b32a4 output fixes on transmission_with_raman_main_example.py 2019-08-01 10:45:20 +02:00
Alessio Ferrari
2eed891f8d new variable names for SPM and XPM 2019-07-31 11:29:25 +02:00
Alessio Ferrari
c0b84e84c8 double underscore replaced with single one for some attributes 2019-07-31 11:24:16 +02:00
Alessio Ferrari
2c20fd3f9f strings 'XPM' and 'SPM' removed while computing NLI, now it is implicit 2019-07-31 11:20:34 +02:00
Alessio Ferrari
f4db56ca29 minor fix to comments 2019-07-31 11:18:46 +02:00
Alessio Ferrari
5b6d58ac7d minor fix to printed text 2019-07-29 14:45:32 +02:00
Alessio Ferrari
ecb8bd9fbe new print of final propagation 2019-07-29 14:17:27 +02:00
Alessio Ferrari
2f9385451f removed old printing of spectral information 2019-07-29 14:16:49 +02:00
Alessio Ferrari
1a1346461b self.pch_out_db in RamanFiber now takes into account Raman gain 2019-07-29 12:33:05 +02:00
Jan Kundrát
27dcd29074 CI: Attempt to builds docs during regular CI, too
Since ReadTheDocs does not support [1] running as a CI check on GitHub
yet, let's make sure that we at least run sphinx. This would have caught
a recent docs breakage (see parent commit).

[1] https://github.com/readthedocs/readthedocs.org/issues/1340
2019-07-04 00:37:58 +02:00
Jan Kundrát
93986f36c3 docs: Fix docs building
Docs building started failing after our dependency update. The reason is
that the updated sphinx bibtex extension started being a bit stricter in
their interpretation of bibliography files:

  parsing bibtex file /home/jkt/work/TIP/oopt-gnpy/docs/biblio.bib...
  Exception occurred:
    File "/home/jkt/work/TIP/_py/lib64/python3.6/site-packages/pybtex/errors.py", line 78, in report_error
      raise exception
  pybtex.database.input.bibtex.DuplicatePersonField: entry with key bononi_modeling_2012 has a duplicate year field

Fix this by using `date` as field name when a full date is given.
2019-07-04 00:37:23 +02:00
Jan Kundrát
a6ab8055b1 CI: do not attempt to cd twice
I misunderstood how Travis CI works; it's not a subshell, it's something
which affects the other commands. Let's just run everything from the
top-level directory.
2019-07-04 00:28:33 +02:00
Jan Kundrát
31ea479d7f Merge pull request #268 from jktjkt/prune-dependencies
Update and rework dependency handling

fixes #269
2019-06-25 15:25:48 +02:00
Jan Kundrát
89fb2e047b Update dependencies
Pinning dependencies to a specific version is safe in terms of
preventing accidental breakage, but it has a cost of possibly using
outdated dependencies.

Let's see if we can rely on the semantic versioning of our dependencies
here.

I'm doing this instead of other approaches (such as splitting the
top-level deps from "the rest of the dep chain" [1][2]) because I require
additional tools in my venv, such as the python-lnaguage-server. There
would be little point in injecting these into requirements to be used by
other people.

[1] https://www.kennethreitz.org/essays/a-better-pip-workflow
[2] 59eb51c026
2019-06-21 12:13:38 +02:00
Jan Kundrát
8f705e6173 requirements: only list what we really need
Listing all transitive dependencies, including their respective versions
(as done by `pip freeze`, for example) is something which effectively
leads to installing outdated and possibly vulnerable software.

Let's get rid of the transitive dependencies.

Thanks to Esther for noticing.
2019-06-21 11:46:17 +02:00
Jan Kundrát
8f735316f5 Merge pull request #264 from Telecominfraproject/master
Merge master into develop

...so that the docs are updated and synced.
2019-06-19 14:28:45 +02:00
Jan Kundrát
0d7a1871a1 Merge pull request #259 from jktjkt/docs
docs: Show a pretty picture of GNPy in action

Thanks to Esther for suggesting this, and to Gert and Esther for their reviews.
2019-06-19 11:57:55 +02:00
Jan Kundrát
33832b3d25 docs: Animated invocation of transmission_main_example.py
Tools used:
- [asciinema](https://asciinema.org/) for recording the session
- `$EDITOR` for a few simple fix-ups
- [termtosvg](https://github.com/nbedos/termtosvg) for creating the
resulting SVG so that it's fully self-contained
- pushing the results to the `gh-pages` so that it's available and not
subject to [random filtering and
breakage](https://stackoverflow.com/questions/13808020/include-an-svg-hosted-on-github-in-markdown),
such as the animated SVG not actually animating

I'm still linking to asciinema.org because that site offers nice
cut-and-oaste capabilities, playback control, etc.

Co-Authored-By: Gert Grammel <ggrammel@juniper.net>
2019-06-19 11:54:44 +02:00
Alessio Ferrari
4da7f0cc38 added evaluation of the SNR at the end of the line 2019-06-18 13:31:50 +02:00
Alessio Ferrari
e29f8485ea integration of the GGN-model with spectral separation 2019-06-18 13:31:01 +02:00
Alessio Ferrari
2da344a563 sim_params now include GGN model 2019-06-18 13:27:02 +02:00
Alessio Ferrari
2a0cb8e14f raman pump powers reduced in raman_edfa_example_network.json 2019-06-18 13:21:05 +02:00
Jan Kundrát
e1dc3dc357 docs: no need to cd examples first
The code determines these paths relative to the actual example .py file
already. Given that `pytest` and other bits expect to run from the
top-levle directory, let's remove this misleading instruction from the
docs.
2019-06-17 20:01:36 +02:00
Jan Kundrát
8259124f73 docs: Show a pretty picture of GNPy in action
I do not have a vector image of this one, unfortunately. The data
apparently comes from "someone at TIP", perhaps a hired graphic
designer. It was passed to me by Diego Landa when I asked for the
original dataset.
2019-06-17 19:55:00 +02:00
Alessio Ferrari
0422956ac6 RamanFiber propagate method now call the propagate_raman_fiber in the science_utils module 2019-06-11 13:40:42 +02:00
Alessio Ferrari
ff82c5171b propagate_raman_fiber function introduced 2019-06-11 13:39:41 +02:00
Alessio Ferrari
f9bd6310f1 introcude NLI solver 2019-06-11 13:38:39 +02:00
Alessio Ferrari
471eab126e fix raman solver parameters 2019-06-11 13:38:05 +02:00
Alessio Ferrari
6ad011d12d raman_efficiency included in RamanFiber equipment 2019-06-11 13:28:39 +02:00
Alessio Ferrari
561c8aff85 modified sim_params for transmission_with_raman_main_example.py 2019-06-11 13:27:40 +02:00
Alessio Ferrari
5cf5dd2234 add temperature parameter in fiber 2019-06-11 13:24:12 +02:00
Alessio Ferrari
fb9915d301 add raman efficiency in SSMF equipment 2019-06-11 13:23:38 +02:00
Jan Kundrát
7ab67194d6 Merge a3778dfe8b into 603ac9d8c5 2019-06-11 08:47:09 +00:00
Jan Kundrát
603ac9d8c5 Merge pull request #257 from jktjkt/fixes
Python: do not use a mutable default value
2019-06-11 10:46:25 +02:00
Jan Kundrát
a3c7811e9d Merge pull request #256 from jktjkt/docs
Documentation fixes (plus an equipment.Fiber.beta2 change)
2019-06-11 10:45:23 +02:00
Jan Kundrát
a3778dfe8b Merge pull request #255 from jktjkt/weekly-calls
Encourage people to join us and to join the VCs
2019-06-11 10:45:00 +02:00
Jan Kundrát
2dff934612 CI: run the examples as well
We are not checking their results or anything, but it is nice to be able
to say "hey, these still work".
2019-06-07 00:02:53 +02:00
Jan Kundrát
89d666948e Fiber: beta2: use a default value directly
Rather than do the None-dance and document the default value within a
docstring, let's use the default value directly. This is safe because
numbers are immutable.
2019-06-06 23:55:16 +02:00
Jan Kundrát
c3499142b0 doc: hyperlinks++ 2019-06-06 23:47:52 +02:00
Jan Kundrát
d8feccc715 Python: do not use a mutable default value
Because default arguments are evaluated *once*, not every time they are
called, a mutable default value is not "reset", and this happens:

>>> from gnpy.core.node import Node
>>> x=Node('123')
>>> y=Node('456')
>>> print(x.metadata)
{'location': Location(latitude=0, longitude=0, city=None, region=None)}
>>> print(y.metadata)
{'location': Location(latitude=0, longitude=0, city=None, region=None)}
>>> y.metadata['foo']=123
>>> print(x.metadata)
{'location': Location(latitude=0, longitude=0, city=None, region=None), 'foo': 123}

This is easily fixable by using an immutable value as a placeholder
here.
2019-06-06 23:29:07 +02:00
Jan Kundrát
16173355f3 docs: random improvements and Sphinxiation 2019-06-06 23:26:12 +02:00
Jan Kundrát
f46134fda5 docs: document the _private methods
This is a reference documentation, so it makes sense for it to be
reasonably complete.
2019-06-06 23:05:42 +02:00
Jan Kundrát
bfecff0412 docs: use a default preset here to prevent extra repetitions 2019-06-06 23:04:34 +02:00
Jan Kundrát
168f1891cf docs: ensure that all modules are documented 2019-06-06 22:55:56 +02:00
Jan Kundrát
862845b4ac docs: minor grammar fixes 2019-06-06 21:51:48 +02:00
Jan Kundrát
b7a5dbff49 Encourage people to join us and to join the VCs
This was suggested by Esther on today's PSE group call.
2019-06-06 18:39:21 +02:00
Jan Kundrát
5be30d89a7 Merge pull request #230 from Orange-OpenSource/build_no_amp_in_roadm
ROADMs can now specify which amplifiers can be used as their preamps and boosters.
2019-06-06 12:47:06 +02:00
Esther Le Rouzic
d94dc51d88 Restrictions on auto-adding amplifiers into ROADMs
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>
2019-06-06 11:58:45 +02:00
Jan Kundrát
22acd88d44 Utility functions for pruning and merging
Co-authored-by: Esther Le Rouzic <esther.lerouzic@orange.com>
2019-06-06 11:42:05 +02:00
Alessio Ferrari
fd406c106b gn model introduced in the science utils module 2019-06-03 16:33:26 +02:00
Alessio Ferrari
16134b5caf +1 and -1 replaced with coporop and counterprop strings for Raman pumps description 2019-06-03 16:27:58 +02:00
Jan Kundrát
2c485efced Merge pull request #252 from Orange-OpenSource/bug_fixes_create_eqpt_sheet
Refactoring and bug fixes in an auxiliary transformation tool.
2019-05-31 16:26:10 +02:00
EstherLerouzic
279d08a0e8 Correct testTopology file
testTopology listed corlay twice in Eqpt although it is a ILA.
should appear only once in node A column

update expected parser results for this change in tests/data

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-05-31 11:31:46 +01:00
EstherLerouzic
1d4a8998e1 Bug fix on create_eqpt_sheet.py
program was not correctly listing nodes when links duplicate EDFA entries.
I refactored it to make it simpler to understand.

I added coordinates on ../tests/data/testTopology.xls for plot purpose

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-05-31 11:31:46 +01:00
Jan Kundrát
47a41e7980 Merge pull request #251 from jktjkt/json-parsing-exceptions
Use exceptions instead of `sys.exit()` when reporting configuration errors
2019-05-31 11:24:55 +02:00
Jan Kundrát
ecfc4a8cb2 One fewer exit() in a library scope 2019-05-30 13:58:33 +02:00
Jan Kundrát
2d66b6266b Add a missing FIXME for direct-printing of diagnostics 2019-05-30 12:39:42 +02:00
Jan Kundrát
b7afb5f9d2 Exceptions for errors in network topologies 2019-05-30 12:39:10 +02:00
Jan Kundrát
58c16a59ac Distinguish between "equipment library errors" and other "config errors"
And because no code for these "other config errors" has been merged yet,
this is just a placeholder for future work.
2019-05-30 12:28:47 +02:00
Jan Kundrát
f09789f5ef Refactor color temrinal escaping into a common module
I have no idea which one of the existing pypi modules is best for these,
and given that we're using just two escape codes, I think it makes sense
not to bother with a more capable third-party module just for two magic
strings.
2019-05-30 12:25:53 +02:00
Jan Kundrát
b2e12cd3e0 Use exceptions instead of direct-exit when parsing equipment JSON 2019-05-30 12:06:54 +02:00
Jan Kundrát
71b157a8ba Infrastructure for reporting configuration errors via exceptions
Once the actual config-parsing code start raising these exceptions
instead of directly calling sys.exit(), the user experience would
deteriorate due to raw exception traces. There's little value in the
trace itself, so just wrap the whole config loading with pretty error
formatting.

We still do not point to a specific place where that error is defined
(such as a line/column in a given JSON file) because that information is
already lost by the time we perform these checks.

Also, these checks are largely open-coded ad-hoc stuff. Some required
items are not covered, raising KeyError instead. We should get a formal
schema for these...
2019-05-30 12:06:54 +02:00
Alessio Ferrari
cb8affe9b2 transmission with raman integrated with sim_params configuration 2019-05-28 12:19:01 +02:00
Alessio Ferrari
3f7180c706 configure_network function created to configure the RamanFiber.sim_params in a network 2019-05-28 11:35:42 +02:00
Alessio Ferrari
f0bc2dc62f attribute sim_params added to RamanFiber 2019-05-28 11:11:40 +02:00
Jan Kundrát
9c95fd6b69 Do not mix THz and Hz
While the `itufl()` function uses THz by default, its values depend on
the frequency range that is passed via arguments. In this context, the
f_min and f_max come from the default SpectralInformation which is in
Hz.

Thanks to @ojnas for reporting this.

fixes #243
2019-05-27 18:35:14 +02:00
Alessio Ferrari
c0fda8c3a2 fix to Raman solver 2019-05-27 17:09:34 +02:00
Alessio Ferrari
bac20af381 eqpt_with_raman_config.json copied from eqpt_config.json and RamanFiber added into it 2019-05-27 17:08:36 +02:00
Alessio Ferrari
626211a320 Introduce RamanFiber in equipment 2019-05-27 17:04:33 +02:00
Jan Kundrát
783aaa8cb4 Merge remote-tracking branch 'origin/master' into develop 2019-05-27 12:27:23 +02:00
Jan Kundrát
768bd8af19 Merge pull request #247 from jktjkt/rst-fixes
docs: fix RST formatting and introduce CI coverage
2019-05-27 12:26:42 +02:00
Jan Kundrát
3894f52194 CI: test the RST files for validity
fixes #245
2019-05-27 12:08:02 +02:00
Jan Kundrát
dcfa9edb1c docs: Fix JSON syntax 2019-05-27 11:36:02 +02:00
Jan Kundrát
4ebdb5629c docs: specify code-block highlighter 2019-05-27 11:35:56 +02:00
Jan Kundrát
75b0668fc2 docs: Fix JSON syntax -- standard ASCII quotes 2019-05-27 11:35:52 +02:00
Jan Kundrát
5fe94ed463 docs: specify a correct markup language for JSON snippets
Some of these are "pseudo-JSON" with `...` etc, so one has to use `none`
for these.
2019-05-27 11:35:49 +02:00
Jan Kundrát
db21b97603 docs: fix table markup syntax
Oh boy, this is annoying.
2019-05-27 11:35:47 +02:00
Jan Kundrát
8074d0c548 docs: fix code markup
- use a correct highlighter
- ensure that the code is not parsed as RST code-block options
2019-05-27 11:07:53 +02:00
Jan Kundrát
2d611afbb0 Merge pull request #241 from Telecominfraproject/master
Merge master into develop
2019-05-24 11:36:46 +02:00
Jan Kundrát
bc42507724 Merge pull request #239 from jktjkt/spectrial-info-fixes
docs: Fix rendering of the SpectralInformation docs
2019-05-24 11:24:00 +02:00
Jan Kundrát
ff82ab5718 docs: Fix rendering of the SpectralInformation docs
Due to a misaligned |, the table was not rendered at all in the GitHub
overview.

Thanks to Gert for catching this in his brownfield doc.
2019-05-24 11:00:14 +02:00
Alessio Ferrari
62fe374e15 modified fiber type in raman_edfa_example_network.json to use new class RamanFiber 2019-05-24 10:38:24 +02:00
Alessio Ferrari
e519a3bc39 add class RamanFiber 2019-05-24 10:36:29 +02:00
Jan Kundrát
4f146d12ee Merge branch 'pytest-warnings' into develop 2019-05-24 01:45:53 +02:00
Jan Kundrát
46d6074ad5 Merge branch 'trivial-bugfixes' into develop 2019-05-24 01:40:07 +02:00
Jan Kundrát
cbb61f1240 tests: consult the doctests as well
There are no doctests right now, but they will (might?) be added (see
PR #230).
2019-05-24 01:38:12 +02:00
Jan Kundrát
0e9f3c3576 tests: re-enable warnings
For some reason, warnings were disabled in commit 07de78c, but it is not
clear to me what the purpose was back then. It passes without warnings
locally, and I think that warnings are useful in general, so let's give
the CI a try.
2019-05-24 01:37:49 +02:00
Alessio Ferrari
92f11dc075 add an example of json including Raman pumps in fiber 2019-05-23 15:05:08 +02:00
Jan Kundrát
3aa0a0999b Update networkx and xlrd
...in an attempt to kill some deprecation warnings under Python 3.7.
2019-05-22 17:46:41 +02:00
Jan Kundrát
e86fbcfa5b CI: Disable Codecov comments
The results are still perfectly visible within the *Checks* tab, so
let's cut the comment spam a little bit.

I've already done the same for lgtm.com; for that app, it's done in
their service's configuration within the web app.
2019-05-22 17:33:13 +02:00
Alessio Ferrari
0b2ee6fdaf add Raman solver 2019-05-22 12:05:51 +02:00
Alessio Ferrari
35f3866882 load_sim_params used to parse sim_params.json and new default filename 2019-05-22 11:06:58 +02:00
Alessio Ferrari
d86bea80d3 fix load_sim_params 2019-05-22 11:00:02 +02:00
Alessio Ferrari
13b4b5072f fix sim params 2019-05-22 10:59:00 +02:00
Alessio Ferrari
efae43f122 utility to load sim params from json 2019-05-22 10:26:24 +02:00
Alessio Ferrari
45e8c8692b add science utils module 2019-05-22 10:09:27 +02:00
Alessio Ferrari
f8fc2a5050 simparams enriched with Raman and NLI parameters 2019-05-22 10:02:45 +02:00
Jan Kundrát
3c20d57cc4 Be sure that both nf_min and nf_max are removed
If `nf_min` was not present, then `nf_max` would be left remaining
because an attempt to nuke `nf_min` raised an exception.

Thanks to codecov.io for making it easy to spot this on the coverage
page.
2019-05-21 16:29:09 +02:00
Jan Kundrát
2cb3858330 Exceptions must be raised, not just instantiated
Found by lgtm.com code scanner, thanks!
2019-05-21 16:20:26 +02:00
Jan Kundrát
925d36a561 CI: do not require sudo
...which might give us a faster, container-based build environment as
long as some legacy, several-years-old docs are still correct. Let's
give it a try.
2019-05-21 13:04:44 +02:00
Jan Kundrát
0ffaca91cc CI: Test on Python 3.7 as well
According to the Travis-CI docs, this requires switching to a newer base
OS image. It might not require an explicit pin like this in near future
as the default is, apparently, being migrated at this very time, but I
do not feel like working with a random rolling-update process of a
third-party service, thank you.
2019-05-21 12:27:41 +02:00
Jan Kundrát
d3a0f1d969 CI: remove unused section 2019-05-21 12:17:33 +02:00
Jan Kundrát
37704db583 CI: Report test code coverage to codecov.io 2019-05-21 12:09:24 +02:00
Alessio Ferrari
aadd038bbe transmission w Raman gets sim params 2019-05-20 17:17:34 +02:00
diegolaunch
6d601b4267 Merge pull request #232 from jktjkt/unify-authors-list
Add all missing authors and sync the two lists of contributors
2019-05-20 08:10:24 -07:00
Jan Kundrát
194798d881 Add all missing authors and sync the two lists of contributors
These two lists were not synced with each other, and some contributors
whose commits have been merged in git were missing. The resulting list
is a bit longer because not everybody who contributes does that strictly
via commits pushed to GitHub.
2019-05-20 12:31:07 +02:00
Jan Kundrát
1a10495645 Replace James with myself as a maintainer
The credits/attributions have not been touched of course.
2019-05-20 12:31:04 +02:00
Alessio Ferrari
0e2316513e add raman transmission 2019-05-18 15:41:59 +02:00
Alessio Ferrari
72ce4e2fad add json sim_params 2019-05-18 15:39:48 +02:00
Jan Kundrát
4ad7311e18 Merge branch 'develop' 2019-05-17 21:25:08 +02:00
Jan Kundrát
fa2b0e8fad docs: use github for release management
Teh changelog is available over GitHub (and also within the git tags,
now that I added the missing v1.2 tag), so let's cut the verbosity a bit
by just linking to a dedicated page for this trivia.
2019-05-17 20:57:38 +02:00
Jan Kundrát
78eb926693 docs: prune the list of branches
The README is way too long already. Welcoming potential users and
contributors with an overview of the project's history does not help,
IMHO.
2019-05-17 20:46:37 +02:00
Jan Kundrát
3613efbaab docs: there's the --power argument for launch power config 2019-05-17 20:31:50 +02:00
Jan Kundrát
2e732854b3 docs: Improve typography and fix typos in the README
It's quite common to use a ``monospace font`` for referring to
identifiers, so let's use that for GitHub's rendering of the main
project's README.
2019-05-17 20:29:14 +02:00
Jan Kundrát
f9560d6b1d Merge branch 'master' into develop
This is mainly to resolve one conflict in README and to have CI run its
tasks.
2019-05-16 13:09:42 +02:00
Jan Kundrát
51b0826398 Merge pull request #226 from Orange-OpenSource/bugs_correction
correction of 2 bugs
2019-05-16 13:06:09 +02:00
Jan Kundrát
af0adb454d Fix RST syntax in the ROADM table
The table was completely hidden from the HTML rendering at GitHub. The
space between the "left edge" of the table and the text content appears
to be substantial.
2019-05-16 12:41:01 +02:00
EstherLerouzic
cdd4c571b0 correction of bugs
exception KeyError type in service sheet not correctly catched
print Request.mode instead of Requestmode (not defined at this point)

selection of modes did not respect min spacing criterium:
constraint added

transmission_main did not give SNR in 0.1 nm: added in std out

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-05-07 12:28:28 +01:00
James
9c440764c7 Merge pull request #224 from Orange-OpenSource/auto_design3
Auto design3
2019-04-18 11:42:09 -04:00
James
6e94834033 Merge pull request #223 from Orange-OpenSource/addWeightEdge
Add weight edge
2019-04-18 11:41:46 -04:00
EstherLerouzic
1720ed23c9 Sort all simple paths using length instead of hop
when constraints such as include noe or disjuntion is applied
the candidates are sorted with shortest path in length first

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-04-18 11:16:07 +01:00
EstherLerouzic
137fab1d92 Adding weights on edges to have shortest path in length instead of hops
add weight = length of fiber nodes on connections wher from_node is a fiber
add weight = 0.01 km on other edges

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-04-18 11:16:07 +01:00
Jean-Luc Auge
0fee63fa81 manage empty edfa requirement list in auto_design
code exit if no edfa are available and raman do not fill min gain
requirement

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-04-18 12:02:57 +02:00
Jean-Luc Auge
d5f0d80eed clean up auto_design code
replace lambdas, filter and map functions with comprehension list

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-04-18 12:02:57 +02:00
Jean-Luc Auge
b7d4d43f56 improve auto_design selection of raman
-separate edfa and raman_list of acceptable amplifiers to better
customize criteria between edfa and raman amplifiers
for example min gian requirement: no extended min gain range for raman
amplifiers because there is always an edfa solution, which is better for
small gains.

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-04-18 12:02:57 +02:00
Jean-Luc Auge
c0379a1981 verbose possibility for paht_request_run
Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-04-18 12:02:57 +02:00
Jean-Luc Auge
e5db8e42d1 Display warning when Raman is used above max fiber lineic loss
- in auto-design, Raman is already not used if lineic fiber loss >
eqpt_config.json [Span][max_fiber_lineic_loss_for_raman]
- this commit ensures that a warning is displayed even when auto-desing
is not used (when the network equipment configuration is imported from
json or xls topology)

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-04-18 12:02:57 +02:00
Jean-Luc Auge
27cf9806f0 bug fix in mixed auto/imported design with output voa
non zero voa values were transferd to the following node

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-04-18 12:02:57 +02:00
Jean-Luc Auge
5dbb5cd112 bug fix with FUSED spans and EOL
EOL span ageing was added for each connector "to be fused" span
=> now, EOL ageing is only added to the last span of the fused spans
section.

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-04-18 12:02:57 +02:00
Jean-Luc Auge
af75569eb8 clarify code on connector and EOL default loss
Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-04-18 12:02:57 +02:00
James
aebf2ff270 Merge pull request #216 from Orange-OpenSource/automatic_design_test
Automatic design test
2019-04-16 12:21:29 -04:00
EstherLerouzic
3bcdeda3e9 Small fix
Coordinates in files changed during the autodesign compared
to previous autodesign version: autodesign_expeted test
files updated

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-04-09 17:55:19 +01:00
EstherLerouzic
7433667243 Update of README.rst wrt Roadm equalization feature and addresses issue #210
TODO update README with dual stage Edfa type_def
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-04-09 17:13:40 +01:00
EstherLerouzic
d7c009167f add units on the stdout answer given by transmission_main_example.py (issue 201)
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-04-09 17:13:40 +01:00
EstherLerouzic
79f198d6fe reduce the number of test files
- use the same file to test different configuration: with and without Eqpt sheet defined,
   add the abcdfgh topo for disjunction tests in the same file
 - change the name of files to avoid mixing with examples/meshTopologyExampleV2.xxx

TODO: test if examples/ files pass for both path_requests_run and trasmission_main_example

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-04-09 17:13:40 +01:00
EstherLerouzic
315a12b9df Update parser test files in order wrt novel road_equalization branch
- update eqpt_config.json to power-mode : false to take into account gain target
    of the eqpt sheet
  - correct eqpt-config.json with new parameters
  - add gain target in meshTopolgyExampleV2Eqpt.xls
  - correct test_parser.py test function names
  - suppress Exceltestfile
  - change power_mode in test_parser to True in eqpt_config.json for all tests
    except for parser: changed in the function to False to enable
    Eqpt files gain target reading

Next: reduce the number of test files and include examples/ files in the tests

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-04-09 17:13:40 +01:00
EstherLerouzic
e14d145f2c Adding a test on autodesign self consistency
tests it the autodesign applied on an autodesigned file gives exactly the same result

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-04-09 17:13:29 +01:00
EstherLerouzic
f839da39f0 adding a test on autodesign verfication
- tests if networ autodesign does not change some reference files
- changed the meshTopologyExampleV2 files to account for newest features:
  empty columns in mode, power, nb channels, disjuntion examples ...
- added a tsp type with more modes for diversification of tests

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-04-09 17:13:29 +01:00
James
45ca7a63ed Merge pull request #222 from Orange-OpenSource/edfa_model_doc
Edfa model doc
2019-04-09 11:01:42 -04:00
James
5d187255ae Merge pull request #215 from Orange-OpenSource/roadm_equalization
Roadm equalization
2019-04-09 11:00:48 -04:00
Jean-Luc Auge
7adf6aed59 doc file description of all amplifier models!!
Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-04-08 15:03:30 +02:00
Jean-Luc Auge
b22a7a0234 refactor amplifier build build_OA_json.py
update the advanced json model generator

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-04-05 16:06:08 +02:00
Jean-Luc Auge
8805723114 clean edfa_model repo
remove unused obsolete files

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-04-05 10:59:03 +02:00
Jean-Luc Auge
88db4358f5 import Juniper amp model example
Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-04-04 17:25:53 +02:00
Jean-Luc Auge
a5d9685caf modify std_medium_gain_advanced_config.json
reflect interpolation code changes

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-04-04 17:17:47 +02:00
Jean-Luc Auge
94ff8e6beb Advanced amplifier model improvement
-add f_min & f_max frequency definition in amplifier json
-improve interpolation algorithm to support length differences between the spectrum information and the amplifier ripple and dgt frequency definition

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-04-04 17:14:25 +02:00
Jean-Luc Auge
f3400d9bc1 update eqpt_config.json
Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-04-03 14:51:12 +02:00
Jean-Luc Auge
6a6591e41d Add a warning message when attributes are missing in eqpt_config.json
new code provides default values when attribute is missing in the
eqpt_config.json, which can cause unexpected beahaviour
=> provide a warning message when a missing attribute is set to a
default value.

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-04-03 14:51:12 +02:00
Jean-Luc Auge
a3a53f3b06 info message in gain mode
Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-04-03 14:51:12 +02:00
Jean-Luc Auge
2f39abfdb8 power reduction warning message in auto-design
warning message when extended gain range or power requirements cannot be met
and power is reduced

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-04-03 14:09:45 +02:00
Jean-Luc Auge
92239d66fc pass tests
Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-04-03 14:09:45 +02:00
Jean-Luc Auge
178813806f update eqpt_config and example files
Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-04-03 14:09:45 +02:00
Jean-Luc Auge
265dbffc53 Roadm channels power equalization
set individual channel powers wrto the target reference power
tilt and ripple is eliminated after the Roadm

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-04-03 14:08:34 +02:00
Jean-Luc Auge
a67a08a4d0 Power reference tracking to roadm target power
Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-04-03 14:08:34 +02:00
Jean-Luc Auge
6d15f55304 bug fix : Roadms & Spans vs Roadm & Span
discrepancy between topology and eqpt_config json descriptions

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-04-03 14:08:34 +02:00
Jean-Luc Auge
0dbcd1f265 manage operational vs calculated values
Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-04-03 14:08:34 +02:00
Jean-Luc Auge
a0f6380f90 improve power mode and gain mode
power mode no longer reads operational_gain:
	now reads operational.dp_db
	or calculate optimum dp_db from next span loss
gain_mode:
	reads operational.gain_target
	or use gain_from_dp

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>

squash to dp

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-04-03 14:08:34 +02:00
Jean-Luc Auge
ab69cf5bf4 improve Edfa class element
manage default values

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>

squash to improve edfa element

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-04-03 14:08:34 +02:00
Jean-Luc Auge
3e55a5526a improve power saturation handling
fix issue with low power level (after very long spans) where signal gian
was depleted

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-04-03 14:08:34 +02:00
Jean-Luc Auge
b6216bb701 operational amplifier delta P target power support
Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-04-03 14:08:34 +02:00
Jean-Luc Auge
fa3ea3aaa7 convert headers restriction management
Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-04-03 14:08:34 +02:00
Jean-Luc Auge
7b56e3a6c3 bug fix in dual stage NF calculation
Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-04-03 14:08:34 +02:00
Jean-Luc Auge
00ad542a11 auto-design: relax min_gain restriction
tolerate 3dB below min gain in amplifier selection
this is to allow selection of high power amps even if they are below min
gain

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-04-03 14:08:34 +02:00
Jean-Luc Auge
c3e00eea2c manage inter-stage padding for dual stage typedef
Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-04-03 14:08:34 +02:00
Jean-Luc Auge
5c8dd911e3 reduce power when the extended_gain_range limit is reached
Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-04-03 14:08:34 +02:00
Jean-Luc Auge
407fd62da5 improve auto_design algorithm for amplifier selection
remove gain_max limit and use gain+power limit selection instead

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-04-03 14:08:34 +02:00
Jean-Luc Auge
c92f7ca0d8 parametrization of amplifier extended_gain_range
used for amplifier selection in auto-design
but it is possible to manually use and set an amplifier beyond its
extended_gain_range

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-04-03 14:08:34 +02:00
Jean-Luc Auge
676901e113 remove hybrid type_def implementation
replaced by dual_stage type_def

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-04-03 14:08:34 +02:00
Jean-Luc Auge
c099b53a03 parametrization of the max_fiber_lineic_loss_for_raman
Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-04-03 14:08:34 +02:00
Jean-Luc Auge
fd065e4e7c raman tag in eqpt description
manage raman restrictions

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-04-03 14:08:34 +02:00
Jean-Luc Auge
fd97527561 raman restrictions
Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-04-03 14:08:34 +02:00
Jean-Luc Auge
7b9647a063 dual stage
Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-04-03 14:08:34 +02:00
Jean-Luc Auge
bf943f1347 insert a raman hybrid example in eqpt_config.json
auto_design over meshTopologyToy.xls will show raman use
run:
python transmission_main.py meshTopologyToy.xls

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-04-03 14:08:34 +02:00
Jean-Luc Auge
dbff610d77 Improve auto-design amplifier selection algorithm
support min gain for raman auto-design:
raman amplification is only considered for a span if its gain > specified
min gain of the raman hybrid in eqpt_config

auto-design was checked succesfully when enabling a mix of 6 possible different
amplifiers: low gain, medium gain, hybrid ramans, high power and high
gain amplifiers. They were picked as expected.

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-04-03 14:05:45 +02:00
Jean-Luc Auge
46aae9486e update raman model to work in auto-design
Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-04-03 14:05:45 +02:00
Jean-Luc Auge
70066de390 remove namedtuple class structure for network elements
Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-04-03 14:05:45 +02:00
Jean-Luc Auge
106af9d444 hybrid raman/edfa model
quick & dirty 1st implementation:
-fixed raman nf and gain,
-no tilt, no ripple,
-no nonlinear contribution,
-no pump power reduction from egress con loss

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-04-03 14:05:45 +02:00
James Powell
f0be267f9f Merge branch 'develop' 2019-03-05 19:31:28 -05:00
James Powell
edbaec7265 small fixes 2019-03-05 19:11:17 -05:00
James Powell
f4537a538b interpolate fiber positions 2019-03-05 01:07:05 -05:00
James Powell
d6eb6f33d2 fixed ordering, display of SI details 2019-03-04 17:05:56 -05:00
James Powell
7a139c261a removed redundant files 2019-03-04 17:01:34 -05:00
James Powell
2e7aa213ed add units to OSNR 2019-03-04 17:00:41 -05:00
James Powell
d9344287e4 tweaks for OFC 2019-03-04 13:58:09 -05:00
James Powell
b9768a81e9 update README for v1.2 2019-03-04 12:50:35 -05:00
James Powell
3418c07512 changes for OFC demo 2019-03-04 12:35:12 -05:00
James Powell
5f8621c224 changes for OFC demo 2019-03-04 12:32:26 -05:00
James
c05f3555a3 Merge pull request #213 from Orange-OpenSource/features-description
more precise description on README for v1.1
2019-03-04 11:18:08 -05:00
EstherLerouzic
f21827395b update of the descriptioon json structure
- adding the different types of amplifiers

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-02-27 10:26:15 +00:00
EstherLerouzic
894c7bb17a update Excel_userguide.rst wrt convert-service_sheet issue #214
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-02-26 14:33:39 +00:00
Esther LE ROUZIC
2028cfae4d more precise description on README for v1.
Signed-off-by: Esther LE ROUZIC <esther.lerouzic@orange.com>
2019-02-04 09:59:58 +01:00
James Powell
2064f65c04 Merge branch 'develop' 2019-01-30 16:00:38 -05:00
James Powell
1de4a4eaa2 README table fix 2019-01-30 15:59:27 -05:00
James
06ff45d0c2 Merge pull request #208 from Telecominfraproject/develop
Merge Develop to Master for v1.1 Release
2019-01-30 15:52:50 -05:00
James
81474e252e Merge branch 'master' into develop 2019-01-30 15:47:50 -05:00
James
0069265905 Merge pull request #207 from Telecominfraproject/dutc-patch-1
Update README.rst
2019-01-30 15:45:36 -05:00
James
dec15f6797 Update README.rst 2019-01-30 15:40:38 -05:00
Gert Grammel
f6041cd844 Update Contributors
Adding Contributors to the list
2019-01-30 19:35:42 +00:00
James
ec20d3981b Merge pull request #200 from ojnas/fix-readme-coronet
Correct README
2019-01-28 10:39:38 -05:00
James
08a867ef5a Merge pull request #199 from Orange-OpenSource/sys_margins
Sys margins
2019-01-28 10:39:19 -05:00
Jean-Luc Auge
76c8296a5d remove osnr_nli update when adding add_drop_osnr or tx_osnr
Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-01-23 14:52:02 +01:00
jonas
f65059dd7f correct README 2019-01-23 14:16:43 +01:00
Jean-Luc Auge
e23fef3f64 update and pass tests
Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-01-23 10:31:42 +01:00
Jean-Luc Auge
30234f913c system margins implementation
-read sys_margins in equipment['SI']
-add sys_margins to all Transceivers OSNR for path feasibility check
(path_request_run only)

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-01-23 10:31:42 +01:00
Jean-Luc Auge
2dd017bddc code speed improvement (-30% computation time)
remove path propagation for each mode
path propogation is only done for each baud rate

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-01-23 10:31:42 +01:00
Jean-Luc Auge
b25a298087 NEW add_drop OSNR in Roadms model
add_drop_osnr contribution is added at the end of the transmission
propagation, at the same time as Tx_osnr

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-01-23 10:31:31 +01:00
Jean-Luc Auge
8635a7c182 Code fix: non cumulative osnr penalties
add Tx_osnr or add_drop_osnr on raw snr values to avoid cumulated adding

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>

bug fix: forgot to add add_drop_osnr with tx_osnr

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-01-23 10:29:30 +01:00
Jean-Luc Auge
46d25df241 add Tx_osnr at the end of the transmission
Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-01-22 18:05:19 +01:00
Jean-Luc Auge
0338ccb08f restore SI basic parameters f_min f_max & spacing
remove unnecessary SI parameters in eqpt config.json:
-rx osnr
-bit rate
-min spacing
-cost
remove nb_channel parameter when calling SI

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-01-22 18:05:19 +01:00
James
8899a575b8 Merge pull request #144 from ojnas/fix-crash-source-dest
Change source and destination logic in transmission_main_example.py
2019-01-22 10:12:58 -05:00
James
b4407b1ff3 Merge branch 'develop' into fix-crash-source-dest 2019-01-22 10:12:18 -05:00
James
75f0aebe8f Merge pull request #193 from Orange-OpenSource/carrier_probe
Carrier probe
2019-01-22 10:09:47 -05:00
James
5a2dd53636 Merge pull request #195 from Orange-OpenSource/name_matching
Name matching dictionary
2019-01-22 10:09:16 -05:00
James
3555154c3e Merge pull request #194 from Orange-OpenSource/xls_parser_enhance
Xls parser enhance
2019-01-22 10:08:51 -05:00
James
6c92c282e7 Merge pull request #192 from Orange-OpenSource/roadms_openroadm
openroadm noise models and ROADM improvement
2019-01-22 10:07:21 -05:00
James
bd1847e5ba Merge branch 'develop' into roadms_openroadm 2019-01-22 10:04:45 -05:00
James
38727d6203 Merge pull request #188 from Orange-OpenSource/tsp_min_spacing
Tsp min spacing
2019-01-22 10:04:03 -05:00
James
7e6d557d01 Merge pull request #187 from Orange-OpenSource/fourth_correction
Fourth correction
2019-01-22 10:03:25 -05:00
James
5d3ce91839 Merge branch 'develop' into fourth_correction 2019-01-22 10:00:54 -05:00
James
1f34e3005e Merge pull request #186 from Orange-OpenSource/tx_osnr_bug_correction
bug fix due to tx_osnr add
2019-01-22 09:59:57 -05:00
James
8e27437086 Merge branch 'develop' into tx_osnr_bug_correction 2019-01-22 09:56:19 -05:00
James
b4cbe8029e Merge pull request #191 from davidBoertjes/davidBoertjes-node-coord-fix
fix for issue #190
2019-01-15 11:33:35 -05:00
James
92f3fd2063 Update node.py 2019-01-15 11:33:17 -05:00
James
1112b331ef Merge pull request #183 from Orange-OpenSource/second_corrections
Fixes concerning service sheet reading
2019-01-15 11:32:32 -05:00
James
ec34e84a3a Merge pull request #182 from Orange-OpenSource/corrections
Corrections
2019-01-15 11:31:48 -05:00
Jean-Luc Auge
bc9eee326a parametrization of the name matching dictionary
-names argument

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-01-14 17:17:58 +01:00
Jean-Luc Auge
c9106c3a6f enhance name matching dictionary
Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-01-14 17:17:45 +01:00
Jean-Luc Auge
fa949f977a add name find closest match in xls parser convert.py
Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>

output node name gestalt matching to a json

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-01-14 17:17:33 +01:00
Jean-Luc Auge
4c2d61bb9b update test files
Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-01-14 17:14:17 +01:00
Jean-Luc Auge
ec7b14da8c convert.py xls to json parser class enhancement
improve default values handling
update xls examples with east/west headers

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-01-14 17:11:07 +01:00
Jean-Luc Auge
771af4991c carrier probe point for Edfa and Fiber elements
save and be able to retrieve the carrier information processed by Edfa
and Fiber elements:
@ input & output of the element
- channel power: ase, nli, signal and total

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-01-14 12:20:45 +01:00
Jean-Luc Auge
a08ce9ecb7 gain mode fix
Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-01-14 12:16:16 +01:00
Jean-Luc Auge
4d84a4f528 replace egress/ingress by east/west denomination
xls parser

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-01-14 12:16:16 +01:00
Jean-Luc Auge
5d92baf35e Add link duplication check for the xls parser
Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>

Check and remove duplicate links

a warning is issued when a duplicate link is dicovered
the execution is paused for the user ot see the warning
the duplicate link is removed and the execution resumed

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-01-14 12:16:16 +01:00
Jean-Luc Auge
ac5171e95e Improve Excel Node parser
-read headers in any order
-possible hierarchical implementation

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-01-14 12:16:16 +01:00
Jean-Luc Auge
697ac311fe Improve excel link sheet parser
-implement hierarchical headers
-can read headers in any order

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-01-14 12:16:16 +01:00
Jean-Luc Auge
c22d1173af update test eqpt_config
Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-01-11 12:28:39 +01:00
Jean-Luc Auge
c0cc5fa9fd Improve ROADM loss calculation in power mode
Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-01-11 12:28:39 +01:00
Jean-Luc Auge
4bd9a9cdda final openroadm models implementation
Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2019-01-11 12:26:48 +01:00
EstherLerouzic
63f8139dbc Adding min_spacing parameter in transponder mode library
with this feature, spacing is checked with respect to eqpt library
instead of hard coded values in equipment +
mode selection is based on the minspacing instead of a coef or margin on baudrate value
some sanity check are introduced:
 - request spacing must be greater than min spacing
 - tsp baudrate must be smaller than min spacing

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-01-11 11:11:56 +00:00
EstherLerouzic
be731a5977 cosmetic changes
add colors on messages to highlight them
add messages explaining program steps
update readme and excel user guide with latest fetures

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-01-11 11:09:19 +00:00
EstherLerouzic
dd4ce4cea4 small fixes on stdout
- indicate when a mode is selected if the selected path does not pass
  + some reformatting of columns

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-01-11 11:09:19 +00:00
EstherLerouzic
2548a2eee8 small fix on test eqpt_config file
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-01-11 11:09:19 +00:00
EstherLerouzic
03948d6785 Fixes concerning service sheet reading
- indicate which request has incorrect tsp type or mode
- correct wrong reading from excel : if string values contain only a number
  xlrd interprets as a float eg 1 -> 1.0  . A function is used to correct this
  when filling the Request class

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-01-11 10:41:16 +00:00
EstherLerouzic
4c1c17eea6 adding some exception handling to help user debugging
exception handling add some info on which element (uid) is causing a problem
this can help the user to identify where he must correct the input files

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-01-11 10:41:16 +00:00
EstherLerouzic
b258d22d25 add a limit cutoff for path search
all_simple_path search leads to a very long time process in case of large network
a cutoff parameters has been added to avoid this. Value needs to be parametrized:
right now correspond to my experience

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-01-11 10:41:16 +00:00
EstherLerouzic
aef43e6bca Corrections of some bugs
- output file of -o option in path_requests_run.py was not correctly
  handled in case of path indirection eg ../../bar.foo
- fiber constraint is not correctly handled in case of several parrallel directions
  of same fiber name. remove if from the set of constraint till problem is not solved
- loose_list was not correctly indexed in request.py. assume the first element attribute (except
  of the transceiver) applies for the whole list. This will need further corrections
- handle the case when path.snr is none in the optimization of mode process
2019-01-11 10:41:11 +00:00
David Boertjes
3d7362743d Update node.py
Fix return value error in *coords* property which was intended to build a tuple from two values for latitude and longitude.
2019-01-10 13:15:59 -05:00
EstherLerouzic
96f3d5a805 Adding min_spacing parameter in transponder mode library
with this feature, spacing is checked with respect to eqpt library
instead of hard coded values in equipment +
mode selection is based on the minspacing instead of a coef or margin on baudrate value
some sanity check are introduced:
 - request spacing must be greater than min spacing
 - tsp baudrate must be smaller than min spacing

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-12-21 16:57:08 +00:00
EstherLerouzic
2df500e027 cosmetic changes
add colors on messages to highlight them
add messages explaining program steps
update readme and excel user guide with latest fetures

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-12-19 18:24:22 +00:00
EstherLerouzic
346f24022a small fixes on stdout
- indicate when a mode is selected if the selected path does not pass
  + some reformatting of columns

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-12-19 18:21:51 +00:00
EstherLerouzic
cb45c7ef16 new test to check all combination of service specifications
add combination of [mode, pow, nb channel] filled or empty
leading to feasible path or not, and check the propagate and propagate_and_optimize_mode
functions work as expected on a reference toy example

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-12-19 18:17:29 +00:00
EstherLerouzic
9cfb57dc4b bug fix due to tx_osnr add
tx_osnr was impacting automatic mode selection feature : this commit solves the error
+ add a novel version of the excel example with an empty mode cases

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-12-19 16:32:54 +00:00
EstherLerouzic
020d852758 adding some exception handling to help user debugging
exception handling add some info on which element (uid) is causing a problem
this can help the user to identify where he must correct the input files

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-12-19 10:49:31 +00:00
James
8d97fcd735 Merge pull request #177 from ojnas/add-tx-osnr
Add Tx OSNR
2018-12-18 11:57:35 -05:00
James
097fe3114e Merge pull request #156 from ojnas/power-range
improve power range handling - revised version
2018-12-18 11:56:47 -05:00
James
5e0fd265ff Merge pull request #180 from ojnas/fix-osnr-calculation
Fix OSNR calculation when ASE or NLI is zero
2018-12-18 11:55:43 -05:00
EstherLerouzic
6af137a085 Fixes concerning service sheet reading
- indicate which request has incorrect tsp type or mode
- correct wrong reading from excel : if string values contain only a number
  xlrd interprets as a float eg 1 -> 1.0  . A function is used to correct this
  when filling the Request class

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-12-17 09:27:05 +00:00
EstherLerouzic
3cdc8511a8 add a limit cutoff for path search
all_simple_path search leads to a very long time process in case of large network
a cutoff parameters has been added to avoid this. Value needs to be parametrized:
right now correspond to my experience

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-12-13 11:37:26 +00:00
EstherLerouzic
2d515eea4c Corrections of some bugs
- output file of -o option in path_requests_run.py was not correctly
  handled in case of path indirection eg ../../bar.foo
- fiber constraint is not correctly handled in case of several parrallel directions
  of same fiber name. remove if from the set of constraint till problem is not solved
- loose_list was not correctly indexed in request.py. assume the first element attribute (except
  of the transceiver) applies for the whole list. This will need further corrections
- handle the case when path.snr is none in the optimization of mode process
2018-12-13 11:28:42 +00:00
Jonas Mårtensson
61289119cb fix OSNR calculation when ASE or NLI is zero 2018-12-13 11:07:16 +01:00
Jonas Mårtensson
b6bc995e40 fix OSNR test 2018-12-11 21:29:17 +01:00
Jonas Mårtensson
b0bb41bac6 fix eqpt_config test file 2018-12-11 20:48:53 +01:00
Jonas Mårtensson
0927a92652 fix amplifier test 2018-12-11 17:25:26 +01:00
Jonas Mårtensson
f51061d650 Add support for Tx OSNR. 2018-12-11 16:59:05 +01:00
James
74314f00ca Merge pull request #175 from MiquelGA/develop
Few minor details and typos in README
2018-12-11 10:07:09 -05:00
miquelgarr
81c5ef4a23 Adding "transmission_main_example.py -h" 2018-11-30 12:16:22 +01:00
miquelgarr
72e329b08e Now applying corrections to the README 2018-11-30 10:28:41 +01:00
miquelgarr
50f884663f Minor typo changes in README 2018-11-30 10:25:17 +01:00
miquelgarr
0d81eb4b29 Minor typos solved in README 2018-11-30 09:59:51 +01:00
James
978a9407fa Merge pull request #171 from szhu3210/patch-1
Fix a typo of log message in transmission_main_example.py
2018-11-27 12:22:01 -05:00
James
2c3b74cdc1 Merge pull request #168 from Orange-OpenSource/service_aggregation_clean_rebased
Service aggregation clean rebased
2018-11-27 11:31:41 -05:00
Shengxiang Zhu (Troy)
448e0f54be Update transmission_main_example.py
Seems a typo.
2018-11-23 17:32:58 -07:00
EstherLerouzic
17f638e991 New mesh example with correct inputs + small fix
small fix: correct wrong numbering of request in json and csv
           output when -o is used ; correct example files

signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-11-21 09:56:00 +00:00
EstherLerouzic
b78d3d8eda small fixes
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-11-21 09:20:25 +00:00
EstherLerouzic
02a7e467e2 Major correction on mode optimization behaviour + small fixes
- this version handles special cases: if no baudrate satisfies the spacing
  , if no mode satisfies the OSNR threshold from transponders
- template of service corrected wih the novel path_bandwidth
- some ideas TODO added for testing

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-11-21 09:20:25 +00:00
EstherLerouzic
15304890f5 Corrections related to tests and cost feature
- adding cost in every config files including tests files,
- correcting wrong usage reactions (if value is not correct)
- correction of orthograph

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-11-21 09:20:19 +00:00
EstherLerouzic
9ea96e431c Test disjunction file corrected to include novel path_bandwidth parameter
Correction of data file for test_parser.py + adding a test on path non looping

- service json files now include path_nadwidth value
- previous constrained routing did not ensure loop free path. This has been
  corrected in A test has been added to avoid loosing this feature in future
  versions.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-11-21 09:16:23 +00:00
EstherLerouzic
7b3bfea614 correction on aggregation to support disjunction feature
- correction of json to csv function
- small correction on disjunction format to avoid double (double crash the program)
- adding time stamp to measure perf
- demands with all the same disjunction can be aggregated
- a new set of disjunction list is created to avoid inconsistancy
  with the aggregated request-ids

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-11-21 09:16:17 +00:00
Jean-Luc Auge
d68637c2c8 clean eqpt_config.json, add low noise openroadm amp
Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-11-21 09:14:17 +00:00
Jean-Luc Auge
f009306030 small fix
Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-11-21 09:12:58 +00:00
Jean-Luc Auge
ca97cba18b display channel count information when running transmission_main
Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-11-21 09:12:58 +00:00
Jean-Luc Auge
a46c8c5398 OpenRoadm amplifier model!
nf = f(Pin)

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-11-21 09:12:58 +00:00
EstherLerouzic
88c2e2bd70 adding the example file used for disjunction testing
adding the counting feature on standard output
adding tsp nb in csv + small bug fixes
small fixes to improve stdout and csv printing
small bug fixes on service aggregation and automatic correction of names

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-11-21 09:12:52 +00:00
EstherLerouzic
1bbcee8715 First version of mode optimization
if mode is not given, the program automatically choses the first mode of the tsp
that has the highest bitrate and baudrate
- propagation for each loop on baudrate, no proppag in the loop on the mode
  (same propoagation applies for identical baudrate)
- starts with the highest baudrate
- Make power and nb-channel optional fields
  - power uses defaulf power in SI
  - nb channel computed based on min max frequency and spacing

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-11-21 09:06:38 +00:00
EstherLerouzic
39a8fa3335 Adding aggregation feature
- add bitrate in the json service file and enable to support both with and without bitrate
- change mode to optional
- add an aggregation function that groups identical demands (except for id and bitrate)
  TODO : check which mode can satisfy the request or how many transponders  -> going towards
  dimensionning
- Correcting some bug on loose parameter: hop-type attribute was forced to be always 'loose'
  -> now reads the excel entry
- service sheets checks on header if field names are corrects, but any order is
  now feasible.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-11-21 09:06:32 +00:00
James
fe067e5367 Merge pull request #167 from ojnas/verbosity
handling of --verbose
2018-11-20 09:57:26 -05:00
Jonas Mårtensson
5efbd17829 add help text 2018-11-20 15:27:54 +01:00
Jonas Mårtensson
fa3e54a747 change handling of verbosity argument 2018-11-20 14:57:28 +01:00
James
603beccb01 Merge pull request #151 from ojnas/gain-mode-fix
gain-mode fix
2018-11-19 18:18:35 -05:00
James
4b20afd599 Merge pull request #165 from ojnas/fix-broken-links
fix broken links in readme
2018-11-19 18:16:46 -05:00
Jonas Mårtensson
adbe283c83 fix broken links in readme 2018-11-19 13:03:32 +01:00
James
1908d7e29a Merge pull request #161 from Orange-OpenSource/correcting_example
correcting example file
2018-11-16 11:08:38 -05:00
James
7c6e16cfbc Merge pull request #164 from ojnas/fix-encoding
fix utf-8 encoding
2018-11-16 11:07:27 -05:00
Jonas Mårtensson
1480d23088 fix utf-8 encoding 2018-11-16 13:38:07 +01:00
EstherLerouzic
4be3522209 change for meshTopologyToy.xls
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-11-16 11:14:37 +00:00
EstherLerouzic
5381e0300f correcting example file
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-11-16 11:04:52 +00:00
James
cde822ebf8 Merge pull request #157 from ojnas/missing-imports
add a couple of missing imports
2018-11-15 12:39:31 -05:00
Jonas Mårtensson
72d3525da1 add a couple of missing imports 2018-11-14 15:24:25 +01:00
Jonas Mårtensson
dc867fa051 improve power range handling 2018-11-14 09:08:14 +01:00
James
eaf3fcade8 Merge pull request #153 from dutc/develop
fix changed spelling & misspellings in meshTopolgyExampleV2_Services.json for "synchronize/synchronization"
2018-11-13 11:49:01 -05:00
James Powell
3df270e4ac fix changed spelling & misspellings in meshTopolgyExampleV2_Services.json for "synchronize/synchronization" 2018-11-13 10:24:15 -05:00
Jonas Mårtensson
7937392dfc fix bug in gain mode 2018-11-13 13:33:21 +01:00
James
9c1c0f8d1f Merge pull request #137 from Orange-OpenSource/path_disjunction
Path disjunction
2018-11-12 10:11:08 -05:00
James
ad2ab0d164 Merge pull request #143 from ojnas/coronet-all-nodes-roadm
Explicitly set all nodes in CORONET example to ROADM
2018-11-12 10:10:45 -05:00
James
c4bed94eb0 Merge branch 'develop' into coronet-all-nodes-roadm 2018-11-12 10:10:23 -05:00
James
edc8eb55de Merge pull request #145 from ojnas/split-fiber
Some modifications in split_fiber function
2018-11-12 10:09:15 -05:00
Jonas Mårtensson
f4f9868381 Change span numbering in split_fiber. 2018-11-05 17:43:14 +01:00
Jonas Mårtensson
f103bebe05 Some modifications in split_fiber function. 2018-11-05 17:13:03 +01:00
Jonas Mårtensson
c168af46bc Update transmission_main_example.py 2018-10-30 17:37:50 +01:00
EstherLerouzic
7d82248903 Small fix
obsolete text not removed in the message made an error: I removed them

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-10-30 16:36:44 +00:00
James Powell
e6cb269754 Merge branch 'master' into develop 2018-10-30 12:05:44 -04:00
James
ac8a96398a Update issue templates 2018-10-30 12:03:36 -04:00
EstherLerouzic
86c79c7c60 Merge branch 'develop' into path_disjunction solving conflict
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-10-30 16:01:06 +00:00
James Powell
0c47b3f3ea small fix in case spacing_list is not sorted 2018-10-30 12:00:47 -04:00
James
b2b500c5dc Merge pull request #141 from ojnas/automatic-spacing
Simplify automatic spacing
2018-10-30 11:59:20 -04:00
ojnas
efc8468268 Set type of all nodes to ROADM in CORONET Glabal. 2018-10-30 09:48:59 +01:00
ojnas
205baebd48 Merge remote-tracking branch 'upstream/develop' into develop 2018-10-30 09:37:27 +01:00
James
af9ba2750d Update examples/path_requests_run.py
Co-Authored-By: EstherLerouzic <EstherLerouzic@users.noreply.github.com>
2018-10-30 09:27:52 +01:00
James
e04afdbe4c Update examples/path_requests_run.py
Co-Authored-By: EstherLerouzic <EstherLerouzic@users.noreply.github.com>
2018-10-30 09:27:12 +01:00
James
e94fd9590e Merge pull request #142 from dutc/develop
Fix encoding issues
2018-10-29 20:02:28 -04:00
James Powell
4f4f05abdf allow JSON to encode UTF-8 2018-10-29 11:17:13 -04:00
James Powell
bcf93e1d9f enforce utf-8 encoding for reading/writing JSON 2018-10-29 11:14:31 -04:00
ojnas
48198bdd89 Simplify automatic spacing. 2018-10-28 08:11:22 +01:00
EstherLerouzic
fbb4f3e5dd small fixes to comply with test files
- re-changing to to \u2192 in convert.py to comply with test files
- changing route constraint in data file : the constraint had a too ambiguous
  naming in the service file
- test on None was incorrect in convert_sheet

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-10-26 10:43:27 +01:00
James
cefd1cf030 Merge pull request #136 from ojnas/main-source-dest
source and destination handling i transmission main example
2018-10-25 10:47:00 -04:00
James
f8fa544e31 Merge pull request #135 from ojnas/add-fiber-types
Update eqpt_config.json
2018-10-25 10:46:02 -04:00
EstherLerouzic
27885a4cbc Correction of route constraint to support any type of node
correct loose or strict constraint in the new function correct_route_list
correct test to find the name with existing uids
remove the \u2192 char that was not well supported with excel reading

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-10-25 15:42:09 +01:00
EstherLerouzic
185a62958f adding safe check on baudrate and spacing
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-10-25 15:42:02 +01:00
EstherLerouzic
1ba748f2a4 Changing optical power and nb channels as optional input for requests
- normal way is usually to apply the design optical power for all channels.
  This change uses the default power (same power as used for design) but enables to
  force an arbitrary power if needed. TODO : introduce spectral power density
  to apply power depending on baudrate.
- definition of min max frequency and spacing define the nb of channels:
  uses min max frequencies and spacing to determine nb-channels. It is possible
  to force a different spacing for the request. TODO: check that the value is
  consistant with baudrate and min max values.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-10-25 15:36:53 +01:00
EstherLerouzic
90a75a9b3d Removing the duplicate convert_service_sheet.py in examples directory
service_sheet.py contains exactly the same function: I suggest to remove this file
to clean the examples directory

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-10-25 15:36:36 +01:00
ojnas
215295efb1 changed source and destination handling 2018-10-25 15:25:28 +02:00
Jonas Mårtensson
2413bd9e0d Update eqpt_config.json
Add fiber types.
2018-10-25 11:31:39 +02:00
James
356ae650fd Update issue templates 2018-10-23 17:09:56 -04:00
James
2444c24545 Update issue templates 2018-10-23 17:09:10 -04:00
James
7727708a3a Merge pull request #131 from ojnas/equipment-refactoring
Equipment refactoring
2018-10-23 14:15:39 -04:00
Jonas Mårtensson
0bfacd84f4 Update equipment.py 2018-10-23 17:16:51 +02:00
Jonas Mårtensson
b271c1ca3c Update equipment.py 2018-10-23 17:13:08 +02:00
EstherLerouzic
75660febc1 Create test_disjunction
- create some test to check that produced paths are really disjoint
- add some TODOs on optical power for requests computation

First check of disjunction feature added to tests

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-10-23 11:53:57 +01:00
EstherLerouzic
13aaa174e1 Adding this toy example network for disjunction testing
1     1
     a----b-------c
     |    |       |
     |1   |0.5    |1
     |    |       |
     e----f---h---g
       1   0.5 0.5

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-10-23 09:30:20 +01:00
EstherLerouzic
d112c728fc Moving the disjunction function into core functions
and minor corrections

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-10-23 09:25:07 +01:00
EstherLerouzic
826af4a9fd Minor corrections of tests due to orthograph change
- "synchronisation" replaced with synchronization
- "synchonzation" replaced with synchronization

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-10-22 16:41:56 +01:00
EstherLerouzic
c9693d355f some cleaning and renaming
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-10-22 16:26:58 +01:00
EstherLerouzic
9f37cb8ce6 Corrections, cleanup and debugging
Added (partly):
- relax one constraint when no more path are available

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-10-22 16:25:52 +01:00
EstherLerouzic
d99e8ca565 routing constraint added on top of disjunction feature : step 4
select disjoint routes that satisfy route constraint

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-10-22 16:25:52 +01:00
EstherLerouzic
44312125ab Disjunction feature step 3
- select the first path that is satisfying disjunction
not finished:
- constraints on nodes not taken into account
- modification on the build network not added
- not clean, need some refactoring

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-10-22 16:25:49 +01:00
EstherLerouzic
7558721642 Disjunction feature step 2
- selection of disjoint path set for each synchronization vector

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-10-22 16:23:11 +01:00
EstherLerouzic
fb49f7fb5d Implementing disjunction in path_requests_run.py
- Implementing a conflict table for path disjoint choices
 - adding disjunction in the parser and json (read and write)

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-10-22 16:23:00 +01:00
James
ee7f2c2f47 Merge pull request #129 from ojnas/minor-readme-fixes
Update README.rst
2018-10-22 10:19:04 -04:00
Jonas Mårtensson
833fe006af Update README.rst 2018-10-22 14:19:52 +02:00
James Powell
9be0607b2e add authors 2018-10-17 09:25:14 -04:00
James Powell
6dc3f2ffa6 small updates 2018-10-16 05:58:42 -04:00
James Powell
df7cbf0b76 small README fix 2018-10-16 05:50:26 -04:00
James
19b6378b1a Merge pull request #126 from dutc/develop
add tagged version table
2018-10-16 05:46:12 -04:00
James
29cb2b50a8 Merge pull request #125 from ojnas/ojnas-minor-fixes-edfa
Update elements.py
2018-10-16 05:43:36 -04:00
James Powell
5932c014a0 add tagged version table 2018-10-16 05:42:31 -04:00
Jonas Mårtensson
a3f75e9af0 Update elements.py
Minor fixes to Edfa class
2018-10-16 11:05:34 +02:00
James
9ed31e2c4e Merge pull request #124 from dutc/develop
small fixes
2018-10-16 04:51:50 -04:00
James Powell
8599f63fbf remove redundant directory 2018-10-16 04:51:14 -04:00
James Powell
07de78cb05 small fixes 2018-10-16 04:50:33 -04:00
James Powell
f764bbe080 small changes 2018-10-16 04:48:22 -04:00
James Powell
7aa343b767 small fixes 2018-10-16 04:43:25 -04:00
James Powell
69198779a7 Merge branch 'develop' 2018-10-15 22:44:39 -04:00
James
3088032ad8 Merge pull request #123 from dutc/develop
Readme fixes
2018-10-15 22:37:22 -04:00
James
dfaa12598d Merge pull request #121 from dutc/master
Fixes
2018-10-14 20:59:05 -04:00
James Powell
1c724cdc6c Merge branch 'master' into develop 2018-10-14 20:58:42 -04:00
James
b59423fb01 Merge pull request #120 from dutc/develop
Develop
2018-10-14 20:58:02 -04:00
James
96bceed102 Merge pull request #119 from dutc/fixes
Fixes
2018-10-14 20:55:15 -04:00
James Powell
f8e146b9b9 duplicate service sheet to simplify structure 2018-10-14 20:55:25 -04:00
James Powell
c54ddb644a fix headers 2018-10-14 20:55:12 -04:00
James Powell
2be616411f fix headers 2018-10-14 20:55:00 -04:00
James Powell
7415744807 small formatting 2018-10-14 20:54:48 -04:00
James Powell
23905a90f4 strip whitespace 2018-10-14 20:54:35 -04:00
James Powell
83444b329e strip whitespace 2018-10-14 20:54:22 -04:00
James Powell
9898dc85a9 remove notebook and binder 2018-10-14 20:54:10 -04:00
James Powell
661287f600 perms 2018-10-14 20:53:56 -04:00
James Powell
353c6a77e9 make package 2018-10-14 20:53:41 -04:00
James Powell
8c006fec3f README fixes 2018-10-10 13:37:49 -04:00
James Powell
5896b7ce6a README fixes 2018-10-10 13:25:56 -04:00
James Powell
f831f6cb2c README fixes 2018-10-10 13:25:12 -04:00
James Powell
b505a1ae01 README fixes 2018-10-10 13:23:47 -04:00
James
a0fac17c0e Merge pull request #110 from dutc/master
v0.9 release
2018-09-24 12:56:49 -07:00
James Powell
851f606fc0 Merge branch 'develop' 2018-09-24 15:55:09 -04:00
James
8940430ee0 Merge pull request #108 from Orange-OpenSource/develop
auto_design saving to json and README update
2018-09-24 12:51:38 -07:00
James
06d3927275 Merge branch 'develop' into develop 2018-09-24 12:49:45 -07:00
James
7cea13e90d Merge pull request #104 from Orange-OpenSource/path_resquest_rundemo
Path resquest rundemo
2018-09-24 12:47:12 -07:00
Jean-Luc Auge
de2a504078 README.rst update
Add auto_design and equipment library description!

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-09-18 17:41:54 +02:00
Jean-Luc Auge
df14b441a3 improve code clarity of auto_design power setting
>network>target_power

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-09-18 17:12:58 +02:00
Jean-Luc Auge
ab1391440f Fix bug in padding and EOL and Roadm power
take into account manual padding input, i.e. att_in defined in fiber params
add EOL even if con_out is not None
Force Roadm input power to 0 in power_mode even if the ingress amplifier
gain is not null

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-09-17 13:16:38 +02:00
Jean-Luc Auge
310d32dcea Generic write_csv in utils to save simulation results
tranmsission_main simulation results are saved to simulation_result.csv

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-09-13 14:30:33 +02:00
EstherLerouzic
f8cd822c92 update of test files with respect to the use of string id instead of integer id
update Excel_userguide.rst for the services uid: now accepts strings

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-09-12 11:24:55 +01:00
EstherLerouzic
3ade885e41 improving path_request_run robustness to wrong excel input
- adding a test to check that transponder types and modes are part of the eqpt library
- adding a formating on numeical value input for path request ids
- automatically printing the results into a csv file in addition to the json file
  and with the saime name+.csv
- printing results in a more pretty way for demo

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-09-11 11:09:28 +01:00
EstherLerouzic
008a88192c small update of toy topology file + comment of a proont in network.py
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-09-10 13:44:56 +01:00
EstherLerouzic
639e7f012c some improvement of std out printing, to ease user understanding
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-09-06 11:04:42 +01:00
James
c8ecc16648 Merge pull request #102 from Orange-OpenSource/userGuideImprovement
User guide improvement
2018-09-04 09:06:16 -07:00
Jean-Luc Auge
225fb1ec0c Save network to json after build (auto design)
-Promote incremental and iterative network design
-Automatic saving of a "network-name_auto_design.json" file
-Results of the autodesign (additional amplifiers, configuration) are
saved to this ..._auto_design.json file
-This file can then be used to run a new simulation just like a normal
json input file

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-09-04 09:34:57 +02:00
EstherLerouzic
c943e0e9b4 writing json results from path_requests_run.py into csv
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-09-03 15:10:32 +01:00
EstherLerouzic
3d8ac83fcc - Reference to path_requests_run.py added in README.rst file
- adding a program to convert json result file into a CSV file
- adding some more metrics in the results

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-08-31 17:16:48 +01:00
EstherLerouzic
06399ca8af Excel user guide modifications according to issue 95
- typos corrections
- explanations on cable id, create_eqt_sheet.py, dimensionning
- adding updates in user guide
- harmonisation of naming _eqpt instead of eqt in create_eqt_sheet.py
- improving standard output, removing pi ref power print on standard output

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-08-31 09:41:42 +01:00
James
8f8fc13ded Merge pull request #101 from Orange-OpenSource/auto_design
Auto design features
2018-08-30 08:27:57 -07:00
James
2b018cb9a5 Merge pull request #96 from Orange-OpenSource/develop
fixed gain amplifier model and default values implementation from eqpt_config json
2018-08-23 07:05:02 -07:00
James
9577f4c9a3 Update README.rst 2018-08-21 11:47:49 -04:00
James
771d98cc10 Update README.rst 2018-08-21 11:31:28 -04:00
Jean-Luc Auge
91e875d54c Update untary test_amplifier
test_amplifier.py now works in power mode, which is the reommended mode
for auto-design

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-08-10 11:36:33 +02:00
Jean-Luc Auge
da39f1489f power range fix for power sweep
align the behaviour of
	eqpt_config[SI].power_range_db
with
	eqpt_config[Spans].delta_power_range_db
so that the min and max excursions are taken into account (which was not the case
when using range or arange for the SI power excursion)

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>

power range sweep fix

fix behaviour when power range length = 0
update eqpt_config json default values

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>

restore verbose off for power sweep

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-08-10 11:36:29 +02:00
Jean-Luc Auge
2940576681 Output VOA in EDFA implementation
new field 'out_voa_auto': true/false in eqpt_config json for elligible
amplifiers
if the field is set to true and the power_mode (in
eqpt_config[Spans]) is also set to true, a VOA value is calculated based
on available gain and power margins (EOL) to maximize amplifier gain and
improve its NF

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-08-08 17:52:53 +02:00
Jean-Luc Auge
a49c137b78 Improve Select_edfa algorithm
can pick up the best NF amplifier among several amplifiers
sharing the same gain and/or power requirements when these requirements
are not satisfied (used to take the highest gain or the highest power)

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-08-08 15:11:59 +02:00
Jean-Luc Auge
87e748cd83 Remove nf calculation duplication
align edfa_nf calculation in equipment.py to _calc_nf in elements.py

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-08-08 14:56:19 +02:00
Jean-Luc Auge
94c2e332bb update amplifier tests
readd CORONET xls

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-08-08 14:29:01 +02:00
Jean-Luc Auge
1437b6010e Small fixes
code cleanning
	consistency wiht path request
	generator bug fix
	select_edfa readibility enhancement
	set roadm_loss before design in power mode

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-08-08 14:24:12 +02:00
Jean-Luc Auge
5fc203482d Amplifier selection with power constraints
amplifier selection in autodesign now takes into account
-required design gain
-required design power
-lowest NF among amplifiers satisfying the requirements

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-08-07 17:03:18 +02:00
Jean-Luc Auge
ff6d81b749 Power setting refactor
separate in the code:
	* add egress amplifier
	* vs setting the amplifier parameters
=> prepare improvments in select_edfa and target_power code
regroup all network optimization operations in network.py (remove from
transmission_main)

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-08-07 13:39:08 +02:00
Jean-Luc Auge
167e644bd0 Amplifier disable field
* toggle true/false in eqpt_config json file to allow the use of a given amplifier type in automatic design: eqpt_config[Edfa][allowed_for_design] : true/false
* automatic design is picking the best amplifier (gain, NF constraints)
among the available ones: if toggle to false, the type is deemed non
available. Only alternative before this feature was to remove the
amplifier from eqpt_config library.
* if set to false, the amplifier type can still be input in the network
topology file: it will be recongized.

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-08-02 12:57:09 +02:00
Jean-Luc Auge
d1c7489768 Automatic design Delta power / span
* automatic design (when amplifiers are missing from network topology
input) finds the optimum power difference between spans
* The range of this optimum power difference is defined in
eqpt_config[Spans][delta_power_range_db] = [min, max, step]

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-08-02 12:30:05 +02:00
Jean-Luc Auge
a783e165dd Add fixed gain amplifier unitary test
update pytest test_amplifier.py test file
correct test_network.json

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-08-01 15:01:10 +02:00
Jean-Luc Auge
45bdd82864 Add padding support for Fused spans
=>small span padding now looks at the total loss of all spans spliced
together instead of individual span losses
=>the att_in padding attenuator is placed at the input of the 1st span
(the 1st of the serie of spans spliced together with Fused ne)

squashed with the fix to implement att_in attenuation in Fiber.propagate

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>

intermediate bug fix to be squashed

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-08-01 14:44:03 +02:00
Jean-Luc Auge
79c5cb6b78 PADDING of small spans
read [Spans][padding] in eqpt_config json file
    * add input attenuator on all fibers in the network with loss < padding
    * create new Fiber attribute: att_in, which is a fixed attenuator for
    padding purposes
    * define "padding" : 0 in eqpt_config will disable the feature
    effectively

    improve fiber splitting to take into account the padding target in the
    min fiber length and the target length is set accordingly to this min
    length

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-08-01 12:15:36 +02:00
Jean-Luc Auge
63ade5fdef Fix bug when splitting fiber in calculated length
Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-08-01 12:13:08 +02:00
Jean-Luc Auge
853b8c7aa3 Code improvement: catch eqpt errors/remove outdated files
* Fiber or Edfa type_variety in the the network topology that are not
    defined in the eqpt_config json (for example Fiber ELEAF) no longer
    crash the code: instead there is a clear error message and the code exit
    gracioulsy
    * remove outdated network topology json files

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-08-01 11:26:51 +02:00
Jean-Luc Auge
0655fb60de read fiber con_in, con_out, EOL & max_length default values
read fiber spans default values from eqpt_config.json[Spans]
	=>if con_in/con_out is None or not defined in params
Rename connector_loss_in/out to con_in/out for consistency
update parser tests to accept the new con_in/out syntax and the new default
values

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-08-01 11:24:28 +02:00
Jean-Luc Auge
69b28e3508 Update and pass amplifier tests
Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-08-01 11:18:50 +02:00
Jean-Luc Auge
5c16d9539f new fixed gain amp in nf_model
new type_def attribute for nf_model amplifiers
variable gain: requires nf_min & nf_max input
fixed_gain: requires nf0 input
	=> NF=nf0 in the [gain_min, gain_flatmax] range
	=> NF=nf0+pad if gain < gain_min: automatic input padding

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-08-01 11:18:39 +02:00
Jean-Luc Auge
e3acf02bde Error message handling and code exit
Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-08-01 11:18:21 +02:00
Jean-Luc Auge
10268e82d4 Power sweep parametrization
=>  read power range [lower, upper, step] in eqpt_config.json
            do not display intermediate NE info if range > 1
=>  update eqpt_config.json data

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-08-01 11:02:57 +02:00
Jean-Luc Auge
bc44bf726a Fix bug in setting the Roadm egress reference power
* apply to power_mode only
* bug caused by the previous merge

restore default connector loss in excel to json parser (convert.py) to
0dB

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-08-01 10:59:00 +02:00
James
9839681bc0 Merge pull request #92 from Orange-OpenSource/fix-tests
Fix tests
2018-07-17 07:24:38 -07:00
James
beb292cb07 Merge pull request #91 from berahtlv/docs
network and equipment JSON descriptions added
2018-07-17 06:55:52 -07:00
EstherLerouzic
29c4134f60 Add roll of factor in transponders library
roll_off is a characteristic of a given mode of a transponder: it is now
integrated in the Transceiver library in eqpt_config.json. Default value is
provided in the SI field if no specific transponder type is input

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-07-16 18:11:02 +01:00
EstherLerouzic
a6157f328d Work contnued on fixing dutc merge with power feature of jla
- adding relevant call in path_request_run
- unifying variable name: baudrat -> baud_rate
- correcting test with the new power features
- unifying naming of variables n_ch-> nb_channel, sink -> destination (this
  follows the usual naming in yang path computation models)
- bug fix in novel trx_mode_params function , use of the function in
  path_requests_un
- TODO : place roll-off in the tsp lib instead of SI

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-07-16 17:43:56 +01:00
Jean-Luc Auge
c6432e2c28 restore power management in transmission main
Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-07-13 18:15:21 +02:00
Jean-Luc Auge
4a756bf2a9 Read trx parameters and find channel spacing&count
Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-07-13 13:45:05 +02:00
Roberts Miculens
b77cc5cd40 file extension changed 2018-07-10 21:53:14 +03:00
James Powell
9f94af6ff7 add test_propagation 2018-07-10 10:47:27 -04:00
James Powell
7aba40cd5b fixed merge conflicts; added default pref value for SI 2018-07-10 10:35:42 -04:00
James Powell
fb6c17c5ff fixed merge conflict 2018-07-10 10:27:24 -04:00
James Powell
4504d80c80 fixed merge conflict 2018-07-10 10:16:13 -04:00
James
8a8c8989cb Merge pull request #85 from dutc/improve-tests
Test Cleanup
2018-07-10 06:47:09 -07:00
Roberts Miculens
20731dbe4b network and equipment JSON descriptions added 2018-07-09 17:46:15 +03:00
EstherLerouzic
55393ca9eb implement the use of TSP f_min
- tsp fmin is used instead of default SI value

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-07-09 10:24:34 +01:00
EstherLerouzic
e9aa4d5601 Integration of Path_request_run functionalities into transmisson_main_example
creation of modular functions to be called
use of the same propagate function in both examples

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-07-06 17:32:56 +01:00
EstherLerouzic
6d49769df9 Refactor path_request_run and integration of functions to transmission
- use load_equipment instead of load_SI
- integrate the pathrequest class into transmission main

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-07-05 18:33:04 +01:00
Jean-Luc Auge
0333e9d094 update amplifier test
Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-07-05 19:21:48 +02:00
Jean-Luc Auge
53bedca50a parametrize and format power mode
Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-07-05 17:07:59 +02:00
EstherLerouzic
b9518ca987 Starting: adding path_requests_run functions to the "core" package
- Path_request class is updated to be more generic and reuseable
  in transmission main example. json processing linked to the yang
  modelling is kept in the pat_request_run, while path_request class
  only contains useful attributes
- adding functions in info and request python files in core directory

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-07-05 15:48:11 +01:00
Jean-Luc Auge
794e713d6d small fix source & node input in transmission main
enhance default value support
run global coronet network in the same US region

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-07-05 12:51:39 +02:00
Jean-Luc Auge
5e1fd7501e bug fix in amplifier extended gain range
NF_calc gain clamping to max gain in extended gain range

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-07-05 12:51:22 +02:00
Jean-Luc Auge
c86ea206d9 bug fix CORONET_GLOBAL_Topology example
bugs from the last refactor merge
- fix #1: update fiber length after split
- fix #2: add egress amp after fiber split

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-07-05 12:50:48 +02:00
Jean-Luc Auge
b810cf84c2 Power mode implementation
Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-07-05 12:50:23 +02:00
EstherLerouzic
15bc5db2ed adding test on the propagation on a link example
test verifies that OSNR and SNR computed values are consistant
including connector loss and input power variation
onto 2 example links: 1 and 5 spans

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-07-04 16:45:28 +01:00
EstherLerouzic
4845d9005e Update tests after having inserted connector losses in json
previous json did not have connector losses input:
this commits updates the json expected files with the additional
connector losse in parameters .

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-07-03 12:52:50 +01:00
James Powell
bed4e9f1e1 clean up JSON comparator & remove redundant files 2018-07-02 17:48:57 -04:00
James Powell
7b20db10cc remove duplicate CORONET file 2018-07-02 16:38:43 -04:00
James Powell
d59b3e8c46 small test fixes 2018-07-02 16:36:10 -04:00
James Powell
8fccbb0ac2 rename test files 2018-07-02 16:28:06 -04:00
EstherLerouzic
f36a610e52 adding connector loss on the "loss" property of fiber class
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-07-02 18:30:40 +01:00
James Powell
479a2f358e clean-up test files/locations 2018-07-02 12:37:13 -04:00
EstherLerouzic
8795c357ae Implementation of connector losses in the propagation function
- connector losses can be part of the json description or not
  in any case a connector loss in and out is now part of the fiber class.
  if not present the default value is 0.0 dB

- propagate function in Fiber class now has a first attenuation
  propagation step. output conn loos is integrated in the
  initial loop function.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-07-02 17:23:58 +01:00
James Powell
d8cb7526bb remove redundant import 2018-07-02 12:10:14 -04:00
James
6ead8e391b Merge pull request #83 from berahtlv/losses
parameterized ROADM and FUSED losses
2018-06-27 17:19:00 -04:00
Roberts Miculens
362f45083d parametrized ROADM and FUSED losses 2018-06-27 18:16:18 +03:00
James Powell
36218037ec fix link 2018-06-22 19:06:10 -04:00
James
584b56bc83 Merge pull request #82 from dutc/fix-tests
small test fixes
2018-06-22 19:01:25 -04:00
James Powell
d33602e131 small test fixes 2018-06-22 18:55:26 -04:00
James
4304b49bf0 Merge pull request #81 from Orange-OpenSource/test_update
Test update
2018-06-22 11:24:44 -04:00
Jean-Luc Auge
4f5325acac small fixes
Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-06-21 16:14:25 +02:00
EstherLerouzic
f8a40bfaf0 correct path
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-06-19 17:34:28 +01:00
EstherLerouzic
52dfb20a2b try with .travis.yml to set the path to examples
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-06-19 17:27:17 +01:00
EstherLerouzic
34b20cdfe0 adding exaples directory as a place to find programs
to test with travis CI

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-06-19 16:57:34 +01:00
EstherLerouzic
f462201499 Update of test for automatic testing
- Separating test python files for different purposes
      convert_file and convert_service_sheet now tested in a dedicated
      file testing parsers_test.py
- Correction of tests due to previous major refactor (especially introducing
      load_network)
- adding test files and references (expected json files)
- adding a test on service json file
- adapting the compare module to generated files

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-06-19 16:38:56 +01:00
EstherLerouzic
5106bdf634 Excel_userguide update + bugfixes
Excel_userguide has been updated with a description of how to use the service sheet
documentation on convert_service_sheet has been added

bugfix on convert_service_sheet to avoid multiple file writing

bugfix on create_eqpt_sheet.py to avoid the creation of a line when site is FUSED type

Completing README and adding templates for json files

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-06-15 13:54:06 +01:00
EstherLerouzic
b93c6dbcbd Merge: merge completed
Path_requests_run and convert_service_sheet.py now use funtions from transmission main

ISSUE from develop refactor : the json generation of the topology is missing all amplifiers !
- ILA are not included
- some edfa appear in the json topo when Eqpt sheet is used, but not all of them (only for
the requested path when running transmission_main_example)

TODO : identify if this is a new behaviour or if this is a regression

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-06-13 16:42:10 +01:00
EstherLerouzic
2ca141baba Merge work : Transceiver type added in equipment library
Transceiver type added to include this equipment in the building of the
library

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-06-13 15:52:55 +01:00
EstherLerouzic
01fe5d2147 path_requests_run now generates a json file if -o is used
the format of path results follows the yang model of ietf

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-06-13 11:39:28 +01:00
EstherLerouzic
74830cede4 path_requests_run.py now can use the route constraint
convert_services_sheet. py reads all columns and creat adhoc attributes.
Route constraint is saved in the "optimisation" field of the json format.
it is used as strict constraint for path computation. automatic decision
on node type is made based on the name.

Spacing, nb of channel and input power have been set in the requests json,
however this may not be inline with the ietf way: they should instead be
link attributes. However the objective of the program currently diverges
from this control oriented description , since requests explore whatif
scenarios for each request with its specific transponder type.

Introduction of loose case for the route constraint , input power,
spacing, nb of channel, per service entry

If no path exist to a loose node it is skipped. else a critical error is raised

Minor corrections on convert and path request
- convert: remove source and destination from intermediate list of nodes if
they are listed
- correction on the header of the sheet (column names)
- path-request: removing debug printings for a nice demo :)

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-06-13 11:36:45 +01:00
EstherLerouzic
2f21cc29f7 Adding a verification on the trx_type entry of service sheet
verify that the trx_type is in the eqpt library
+ correction on the convert_service_sheet (use a list instead of multiple classes initialization)

Parametrisation of networkfile and spectril information in path_requests_run.py
addition of a second input file so that input can be with 2 excel files,
or with 2 json files , or a mix
utilisation of SI attribute in Eqpt_config.json for the input of spectral
information.

Implementation of transceiver_variety and parametrisation of eqpt_config.json
each request now reads the tranceiver type and convert it into
baudrate (assuming a mode).
eqpt_config file is now an argument of the path_requests_run.py

Adding additionnal columns in service sheet for mode, system and route

Transponder selection now includes the tsp modin the eqpt sheet now
also relies on mode name.
additional columns have been defined to input system values such as
channel spacing, input power, nb of channels. TODO :  This enables to compute
the spectral information vector according to the transponder features
for each service in the list...
2 optional columns to define the path as input (with a loose attribute):
if present the path must contain the ordered list of nodes to be crossed
TODO : use path input instead of the internal path computed

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-06-13 11:34:01 +01:00
EstherLerouzic
05f8d97d68 module convert_service_sheet.py and path_requests_run.py
Modules converts the service sheet into json file:
initial definition of classes.
Completing the json template of path computation request
Adding sync vector : but not in the correct form
should avoid multiple sync entries with same info

Treating multiple requests:
path_request_run.py allows computing snr from a list of requests
TODO: integrate into transmission_main_example and enable
feasiblility computation without path computation

Using transceiver class structure to export path computation feasibility
the output of the function now exports a list of tranceiver element,
each containing the result from spectral information propagation.

Adding transceiver type in eqpt library + correct form of xls sevice sheet
eqt library includes information abour transceivers and their modes
(baudrate, bitrate, OSNR threshold, and short name)
service sheet must not have annotation or comments outside of the useful row/column

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-06-13 11:30:23 +01:00
James
04c4795192 Merge pull request #77 from Orange-OpenSource/refactor_merge_2
Refactor merge 2
2018-06-07 11:56:57 -04:00
Jean-Luc Auge
ff6e379b6f Use load_json utility
Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-06-07 11:56:20 +02:00
Jean-Luc Auge
25cfc375bc Amplifier selection
network design when no amplifiers are input in the json file
select_edfa chose the best amplifier in equipment list _from
eqpt_config.json_ wiht the following criteria in order:
1-amplifier wih sufficient gain
2-amplifier wiht sufficient power TODO
3-best NF amplifier staisfying 1 & 2

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-06-07 11:39:09 +02:00
Jean-Luc Auge
627184ef2d restore transmission main power sweep and format
Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-06-07 10:59:33 +02:00
Jean-Luc Auge
180e1178ef restore xls to json file parser-execute from json
xls topology is parsed automatically to json
transmission_main reads from the json generated topology
transmission_main should not read from convert.py data output
This way there is consistency between json and xls inputs

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-06-07 09:36:07 +02:00
James
1c33454ce3 Merge pull request #76 from dutc/develop
Develop
2018-06-05 09:52:55 -04:00
James Powell
c7abe11dd8 Merge branch 'refactor_merge' into develop 2018-06-05 09:52:13 -04:00
James
7a6feccc8b Merge pull request #74 from Orange-OpenSource/refactor_merge
Refactor merge
2018-06-05 09:50:00 -04:00
James Powell
f05e578f51 small fixes 2018-06-05 09:46:48 -04:00
James
277ebea2b5 Merge pull request #75 from berahtlv/readme_links
fixed README broken hyperlinks
2018-06-05 09:35:24 -04:00
Roberts Miculens
4982c5e147 fixed README broken hyperlinks 2018-05-30 20:47:55 +03:00
Jean-Luc Auge
726e217205 merge debug
Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-05-24 16:06:15 +02:00
James Powell
695c538ee5 merge of major refactor
cherry pick of the major refactor commit
many conflicts resolved and code re-written
2018-05-24 12:35:39 +02:00
James Powell
e9b287ceac small readme fix 2018-05-22 11:20:13 -04:00
James Powell
ecdae68b62 small readme fix 2018-05-22 11:10:06 -04:00
James Powell
e737564b32 add lat-long
jla cherry-picked in develop
2018-05-18 10:38:18 +02:00
James Powell
75c4a8d96d gnpy JSON comparison tool 2018-05-18 10:27:15 +02:00
James Powell
28dc1b050f remove redundant imports
jla cherry picked to merge with develop
2018-05-18 10:21:33 +02:00
James
4a9a7e31ba Merge pull request #71 from Orange-OpenSource/useability_improvement_3
Useability improvement 3
2018-05-03 11:33:48 -04:00
EstherLerouzic
92da31f905 file testing correction
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-05-03 15:25:45 +01:00
EstherLerouzic
afd264c816 new test files added
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-05-03 15:23:10 +01:00
EstherLerouzic
d676e3e217 removing a last config file
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-05-03 13:24:25 +01:00
EstherLerouzic
4af117aacf Simplification of tests
removing multiple excel files
adding a test amplifier in eqpt_library

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-05-03 13:20:40 +01:00
EstherLerouzic
b27e567a5e adding tests on excel parsint in amplifier_test.py
6 files are tested: if the converted json file constructed
based on the excel files provided in the test folder are not
identical to expected result, the test fails.
For future creation of test files:
excel name file should start with excelTest.
reference json file should be identical to the excelTest
eg excelTestFilefoo.xls -> testFilefoo.json

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-05-02 17:35:04 +01:00
EstherLerouzic
8ec9a5bf99 putting correct Path for input files in amplfier_test.py
json files paths should be indicated from gnpy/

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-05-02 14:50:30 +01:00
EstherLerouzic
f129f92cfd Enabling input files indirection for excel and json parser + pytest update
replacing bare string reading with Path object and split nam based on
Path structure in convert.py and in transmission_main_example.py

Update of pytest tests

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-05-02 14:28:49 +01:00
James
ef87373d4b Merge pull request #70 from Orange-OpenSource/useability_improvements_2
Useability improvements 2
2018-05-02 08:55:57 -04:00
James
ff938d4ced Merge pull request #66 from Orange-OpenSource/fused_spans
Fused spans, source/sink nodes suggestion, eqpt sheet support in xls parser
2018-05-02 08:55:38 -04:00
EstherLerouzic
ae555e0ce1 Formating Excel_userguide.rst and adding a section for the optional Eqpt sheet
Typos correction
Explanations added on how to fill in the excel Eqpt sheet
Removing verbose printing for debug of create_eqpt_sheet.py
Bug correction : blank removed when copying city names with creat_eqpt_sheet.py
Typos correction on README and Excel_userguide

adding some line for the export PYTHONPATH in the readme
typos corrections

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-04-30 15:37:46 +01:00
EstherLerouzic
44db6093f5 Adding a user guide to explain the excel input format
The README now points to a user guide file explaining the sheets and column format
the guide is not finished

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-04-30 15:04:01 +01:00
EstherLerouzic
d4bf6ce201 Program that creates the list of entries for the Eqpt xls sheet
The program reads the xls Nodes and Links Sheet and create the
mandatory city column as a text file.
If not present in Nodes the Type column is implicitely derived
from node degree (degree 2 means ILA, other means ROADM)

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>

Text file path and name copied from excel input file for create_eqpt_sheet.py

input file name is used for the txt file creation
file is saved at the same place as the input file

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2018-04-30 15:02:08 +01:00
Jean-Luc Auge
0b1c7bfa30 Merge branch 'fused_spans-fixes' of https://github.com/dutc/gnpy into dutc-fused_spans
Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-04-27 12:17:41 +02:00
Jean-Luc Auge
80f8a345b5 Sanity checks and small code fix
xls convert:
	 sanity check Nodes vs Links sheets
	 column parsing limitation so user can add non code related
fields/information
code fix and eqpt_exists to check if an equipment is defined in the eqpt_config.json library

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-04-27 11:36:25 +02:00
James
c929ce0257 Merge pull request #69 from dutc/develop
quick demo section & command-line parameter for plotting in transmission_main_example.py
2018-04-26 12:20:25 -04:00
James Powell
7d3ab357d0 command-line parameter for plotting 2018-04-26 12:05:22 -04:00
James Powell
84d87602b8 quick demo section 2018-04-26 12:04:59 -04:00
James Powell
14938ea7dd small fixes 2018-04-25 02:42:08 -04:00
Jean-Luc Auge
be0c052e5e source/destination nodes suggestion
fix bug in Fused span: adding ingress and egress directions
=> do not share the same NE between 2 directions

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-04-24 15:16:20 +02:00
Jean-Luc Auge
af90a6658e Fused spans class and edfa gain adaptation
*new Fused spans class to support the connection between 2 fibers
without amplification
*add_egress_amplifier adjust the edfa gain to compensate the loss
of n fused spans
*eqpt not found in eqpt library is caught and stop the code

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>

code fix for the eqpt sheet reading in xls parser

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>

amplifier design and eqpt parser code fix

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-04-24 15:15:59 +02:00
James
9720c979b3 fix sys.path for notebook (when running from repo or Binder) (#65) 2018-04-22 20:23:21 -04:00
James
7c86186416 Merge pull request #64 from dutc/develop
notebook version of transmission main example with Binder link
2018-04-22 20:12:24 -04:00
James Powell
404dbfe725 notebook version of transmission main example with Binder link 2018-04-22 20:10:09 -04:00
James Powell
02eac208dd Merge branch 'develop' 2018-04-22 19:11:42 -04:00
James Powell
bc9a0432cd update readme 2018-04-22 19:06:35 -04:00
James Powell
dba7846d6c equipment json paths use relative directories 2018-04-22 19:06:35 -04:00
Jean-Luc Auge
238d7723bb Read eqpt sheet in (convert.py) xls parser
*eqpt sheet is optional: no error message if missing
*All nodes description is not needed
  => only read the node eqpt config when amp_type is input
  => if amp_type = '', the node ingress or egress eqpt is ignored
  => the network.py add_egress_amplifier will fill in missing edfa

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-04-22 19:06:35 -04:00
Jean-Luc Auge
d2724bb1a5 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>
2018-04-22 19:06:35 -04:00
Jean-Luc Auge
8e046a9b50 Implement default values in xls parser for empty cells
*namedtuple default values are only applied if the cell is not read
*if the cell is read but is empty '', there is a need to provide default
values: which is what this fix does
*sanity checks are reinforced :
	-node_type is replaced by ROADM if degree <> 2: notify user
(print)
	-check that node type is in ('ILA','ROADM','FUSED')

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-04-22 19:06:35 -04:00
Jean-Luc Auge
1b808afd5d Advanced xls input support: Nodes & Links reading
Parse advanced fiber parameters from xls into json format:
accept a .xls or a .json input parameter
creates the corresponding .json file
read east/west directions for fiber parameters (fber type, distance...)
read node type (ILA or ROADM)
provide default values if fields are missing
    => full backward compatibility to read the original CORONET xls

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-04-22 19:06:35 -04:00
Jean-Luc Auge
8d6f69eb05 Equipment library implementation
-read eqpt_config.json with various EDFA and fiber type definitions
-std low gain and medium gain EDFA available
-clearer differentiation between the 2 edfa models:
	is the advanced_config_from_json field present or not?

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-04-22 19:06:35 -04:00
Jean-Luc Auge
c4562df955 Add source sink arguments, restore convert.py
demonstrate mesh routing capability with source & sink options
readd CORONET xls and convert.py parser from xls to json

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-04-22 19:06:35 -04:00
James Powell
8e1e8a8be3 re-add coronet files 2018-04-10 00:10:54 -04:00
Mattia Cantono
363e92e072 change RTD python version (#47) 2018-03-28 15:34:01 -04:00
James Powell
c5a52fdb6d small setup.py fixes 2018-03-22 13:17:06 -04:00
James Powell
2dd096cfab bump version to v0.1.2 2018-03-22 13:07:58 -04:00
James Powell
80e1ce12ce bump version to v0.1.1 2018-03-22 13:04:00 -04:00
James Powell
2777d957e4 add long_description_content_type 2018-03-22 13:00:47 -04:00
James Powell
898aa4f41a space align __str__ output 2018-03-20 22:44:32 -04:00
James Powell
c9ece6ad7c use scipy.constants 2018-03-20 22:44:17 -04:00
James Powell
a6265c1b8d document modules 2018-03-20 21:32:02 -04:00
James Powell
5646714c13 small setup.py fixes 2018-03-16 16:45:18 -04:00
James Powell
8ab13537a9 prettier printing 2018-03-15 19:09:29 -04:00
James Powell
25e14e4846 fixed __repr__
__repr__ "should look like a valid Python expression that could be used
to recreate an object with the same value" - https://docs.python.org/3/reference/datamodel.html#object.__repr__
2018-03-15 18:29:26 -04:00
James Powell
55d67f890d clean up examples/ directory 2018-03-15 15:52:39 -04:00
James Powell
9b3d7614f5 remove unused network files 2018-03-15 15:50:17 -04:00
James Powell
a3273d24b5 doc fixes 2018-03-15 14:46:24 -04:00
James Powell
ffd7bec485 docs fix 2018-03-15 14:42:36 -04:00
James Powell
0aef76407d small documentation fixes 2018-03-15 14:35:34 -04:00
James Powell
f2ad236863 fix authors 2018-03-15 14:26:16 -04:00
James Powell
487237638e Merge branch 'develop' 2018-03-15 14:25:26 -04:00
James Powell
3a78ccafce add AUTHORS.rst 2018-03-15 14:18:34 -04:00
James Powell
e99b9c286c first release 2018-03-14 20:14:30 -04:00
James Powell
8c3ffdfd4e fix spelling 2018-03-12 18:19:29 -04:00
James Powell
a4c7395cfe updated readme 2018-03-12 14:43:58 -04:00
James Powell
398124e841 enable graphing of result 2018-03-12 14:43:58 -04:00
James Powell
07cc3fc079 add location metadata 2018-03-12 14:43:58 -04:00
James Powell
27bae162d6 remove non-CONUS elements 2018-03-12 14:43:58 -04:00
James
d4392e5a7a Create LICENSE (#42) 2018-03-12 14:43:58 -04:00
Jean-Luc Augé
a0aab0918a README.rst Instructions and tests path for CI (#41)
* clean transmission_main_example.py

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>

* Add Instructions in README.rst and pytest path for CI

Instructions to run transmission_main_example.py
change config files path in ampliier_test to enable
Travis CI build

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-03-12 14:43:58 -04:00
Jean-Luc Augé
2461385a94 add Roadm, coronet_conus support and amplifier pytests (#35)
* Add EDFA unitary pytests

check nf calculation, nf models comparison, ase noise profile
elements.py edfa _gain_profile: add div 0 checks when no ripple

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>

* support of coronet.conus network and add class __repr__

adaptation of convert.py to new code json formating
add_egress_amplifier, split_fiber and calculate_new_length
subs in network.py
elements.py:
code cleaning
adding new attributes in Edfa class (pin_db, pout_db...)
adding or augmenting class __repr__

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>

* augment amplifier unitary tests and code cleaning

add new tests in amplifier_test.py for pytest
Edfa class code cleaning in elements.py
recheck code coherence and results

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>

* ROADM support in network.py, convert.py, coronet json, ROADM class

creation of a ROADM class with 20dB loss
convert.py json parser modification to include roadms
network.py modification to automate amplifier placing after roadm
elements.py inclusion of Roadm class

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-03-12 14:43:58 -04:00
Mattia Cantono
ba06a0e104 Add NLI Evaluation in Fiber class (#33)
* Add Travis-CI configuration for continous integration
* Add GN-Model Documentation and auto-doc integration
* Add GN model to Fiber
* Unit of measure conversion adapted to SI
2018-02-28 11:53:58 -05:00
GGrammel
48f9c448e4 Merge branch 'develop' of https://github.com/Telecominfraproject/gnpy into develop 2018-02-20 20:26:46 +01:00
GGrammel
2e0d01bc0b Added some TExt about TIP, OOPT, PSE 2018-02-20 20:26:16 +01:00
Jean-Luc Augé
0d3a86f1d8 code wrap up and edfa model augmentation v2 (#30)
* JSON file based on Orange operator typical input
Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>

* update of the standalone edfa model

creation of a new amlifier2.py = v2
creation of a json parser build_oa_json.py
the parser takes OA.json as input and newOA.json as output
creation of a pytest verification module amplifier_pytest.py

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>

* put the code together and transmission example script

-basic dijkstra propagation
-ase noise propagation based on amplifier model
-fake nli noise propagation
-integration of the amplifier model
-interpolation function in the edfa class
-code cleaning and units harmonization

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>

* mv transmission_main_example and rm _main__

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>

* 2nd edfa model and build_oa_json file

add a dual coil stages edfa model in case the nf polynomial fit is not known
add a build_oa_json file that convert the input files in
edfa_config.json file and pre-calculate the nf_model nf1, nf2 and
delta_p parameters
adding power violation check and input padding (below minimum gain) in the edfa model
class

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-02-20 12:51:53 -05:00
GGrammel
a30cd0f721 Contributors alphabetically
List of Contributors
2018-02-19 16:52:57 +01:00
Gert Grammel
1491c2361f updated Contributors list (#27)
completing list
2018-02-13 18:38:26 -05:00
Gilad Goldfarb
ca7b993d95 edfa model, json config loading, added utils (#26) 2018-02-13 12:11:10 -05:00
Gert Grammel
8c75c4f9d7 Created Contributors.md 2018-02-10 13:36:24 +01:00
Gert Grammel
b730b1a4f4 adding License owner "Telecom Infra Project , Inc." 2018-02-01 15:25:39 +01:00
Gilad Goldfarb
a7d3c00e5b setup.py for package (#21) 2018-01-30 11:49:59 -05:00
Mattia Cantono
9146290ecd Add License File (#22) 2018-01-30 11:49:08 -05:00
Mattia Cantono
3fae7210d8 Add Sphinx Documentation and ReadTheDocs integration (#18)
* Add sphinx documentation for readthedocs integration
* Edit README
* Edit README
* Update README formatting
* Update HTML template in conf.py
* Add .travis.yml
2018-01-10 19:50:18 -05:00
Jean-Luc Augé
002f1dfa36 JSON file based on Orange operator typical input (#15)
Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
2018-01-10 19:49:45 -05:00
Xufeng Liu
b3c1e6af95 Create OperatorInputNetworkv3-xufeng.json (#17) 2018-01-10 19:49:33 -05:00
James
58ac717f8d Develop (#14)
* adding rrc filter, temporarily putting it in utilities.py
* added some docstring stuff
* added a simple loss class for fiber and cleaned up some duplicate convenience access properties
* Changed Carrier to Channel to reflect correct nomenclature for multi-carrier/superchannels
* in process fixes for main.py.  adding in amp spacings and spans to convert to start adding additional noded to Coronet network
* some simple additions to utilites
* adding stand alone edfa model
2017-12-06 22:04:24 -05:00
James Powell
f193fb261a Merge remote-tracking branch 'upstream/develop' into develop 2017-12-05 22:57:57 -05:00
James
55d8d23b25 Merge pull request #6 from giladg-FB/develop
adding base node class
2017-12-05 22:40:43 -05:00
Gilad Goldfarb
ca642e3dfc adding base node class 2017-12-05 19:35:34 -08:00
James Powell
bfb7b466eb implemented "path closing" algorithm 2017-11-09 17:30:08 -05:00
James Powell
6467cb5819 sample network propagation 2017-11-09 02:22:45 -05:00
Gilad Goldfarb
ba215d8a07 spectral_info 2017-11-08 17:25:00 -08:00
James Powell
4dc0913825 improve data format 2017-11-08 19:39:00 -05:00
James Powell
fedebc7038 update requirements.txt 2017-11-08 19:07:10 -05:00
James Powell
b42715f003 Merge branch 'fix-make-example-network-bidi' into develop 2017-11-08 19:02:08 -05:00
James Powell
48ae4252db move network management code to network.py 2017-11-08 19:00:29 -05:00
James Powell
0b4dd58c2a make CORONET network connections bidirectional 2017-11-08 18:57:15 -05:00
James Powell
81b863122d simple Makefile for building CORONET input JSON 2017-11-08 18:53:48 -05:00
James
732749d459 Merge pull request #7 from dutc/master
Phase 2
2017-11-08 15:09:02 -05:00
James Powell
014e5fd966 merged phase-2 into master 2017-11-08 15:07:51 -05:00
James Powell
dc7a459697 example network visualisation 2017-11-08 14:54:58 -05:00
James Powell
7f378e5479 requirements.txt 2017-11-08 14:54:42 -05:00
James Powell
d91e279294 example CORONET networks (broken down by region) 2017-11-08 14:54:27 -05:00
James Powell
c5abc4109f example network (CORONET CONUS) 2017-10-31 19:39:13 -04:00
James Powell
c8ce640a2a start fresh 2017-10-31 19:39:10 -04:00
James
029877604e Merge pull request #5 from dutc/fix-consolidated-cleanup
Consolidated cleanup
2017-10-30 09:32:57 -07:00
James Powell
7ee1ad2a92 cleanup 2017-09-30 12:20:03 -04:00
Gilad Goldfarb
24f3e135ad Merge branch 'giladg-FB-fb_network' into fb_network 2017-08-09 12:04:01 -07:00
Gilad Goldfarb
a5718911c5 Merge branch 'fb_network' of https://github.com/giladg-FB/gnpy into giladg-FB-fb_network 2017-08-09 12:03:22 -07:00
Gert Grammel
660d9c8c49 Update README.rst
Documenting WG Goals
Documenting Features
2017-08-07 20:46:31 +02:00
Gilad Goldfarb
2ec50c4e07 with NW graph plots 2017-07-28 15:29:29 -07:00
Gilad Goldfarb
32b4eda3f9 JP initial commit refactoring base classes, utils 2017-07-28 14:58:33 -07:00
Gilad Goldfarb
d5f5ee5595 printout OSNR 2017-07-28 11:09:08 -07:00
Gilad Goldfarb
f0545c57a8 rearranging files 2017-07-27 13:19:56 -07:00
Gilad Goldfarb
815f4d2810 rearrange propagation so it's path-driven from Opath 2017-07-27 11:53:53 -07:00
Gilad Goldfarb
bd474151ab element-based propagation, not via edges 2017-07-27 00:20:48 -07:00
Gilad Goldfarb
2c585faef6 osnr calculation 2017-07-25 23:31:45 -07:00
Gilad Goldfarb
b15be2cf0d network builder 2017-07-25 15:46:26 -07:00
Gilad Goldfarb
3cc98ae388 edges from topology into utils 2017-07-24 23:33:54 -07:00
Gilad Goldfarb
09d1dbf927 working graph with topology 2017-07-24 23:24:21 -07:00
Gilad Goldfarb
cda7f5d50b adding config reading and topology builder 2017-07-24 18:14:23 -07:00
Brian Taylor
1047bbc37c adding some boilerplate for ign 2017-07-24 15:47:45 -07:00
Brian Taylor
b1cb759164 adding several example json configuration files for route and for transmitter 2017-07-24 15:43:24 -07:00
Gilad Goldfarb
2640912baa integrating networkX and Edfa, Span classes 2017-07-21 13:07:06 -07:00
Brian Taylor
8676daed3a Adding skeleton of network elments 2017-07-21 09:14:31 -07:00
Gilad Goldfarb
db31986d28 with JP's architecture.py 2017-07-21 08:50:31 -07:00
Gilad Goldfarb
7823eca871 Merge pull request #3 from Telecominfraproject/develop
Fix gnpy packaging
2017-07-18 11:33:01 -07:00
Gilad Goldfarb
572d7d6999 Merge pull request #1 from Telecominfraproject/develop
__init__.py to gnpy.py
2017-07-11 12:27:57 -07:00
340 changed files with 348755 additions and 3676 deletions

2
.bandit Normal file
View File

@@ -0,0 +1,2 @@
[bandit]
skips: B101

9
.codecov.yml Normal file
View File

@@ -0,0 +1,9 @@
comment: off
coverage:
status:
project:
default:
threshold: 5%
patch:
default:
only_pulls: true

3
.docker-entry.sh Executable file
View File

@@ -0,0 +1,3 @@
#!/bin/bash
cp -nr /oopt-gnpy/gnpy/example-data /shared
exec "$@"

View File

@@ -1,21 +0,0 @@
# http://editorconfig.org
root = true
[*]
indent_style = space
indent_size = 4
trim_trailing_whitespace = true
insert_final_newline = true
charset = utf-8
end_of_line = lf
[*.bat]
indent_style = tab
end_of_line = crlf
[LICENSE]
insert_final_newline = false
[Makefile]
indent_style = tab

View File

@@ -1,15 +0,0 @@
* gnpy version:
* Python version:
* Operating System:
### Description
Describe what you were trying to get done.
Tell us what happened, what went wrong, and what you expected to happen.
### What I Did
```
Paste the command(s) you ran and the output.
If there was a crash, please include the traceback here.
```

29
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,29 @@
---
name: Bug report
about: Create a report to help us improve
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Environment:**
- OS: [e.g. Windows]
- Python Version [e.g, 3.7]
- Anaconda Version [e.g. 3.7]
**Additional context**
Add any other context about the problem here.

View File

@@ -0,0 +1,17 @@
---
name: Feature request
about: Suggest an idea for this project
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

7
.github/pull_request_template.md vendored Normal file
View File

@@ -0,0 +1,7 @@
# Thanks for contributing to GNPy
If it isn't much trouble, please send your contribution as patches to our Gerrit.
Here's [how to submit patches](https://review.gerrithub.io/Documentation/intro-gerrit-walkthrough-github.html), and here's a [list of stuff we are currently working on](https://review.gerrithub.io/q/project:Telecominfraproject/oopt-gnpy+status:open).
Just sign in via your existing GitHub account.
However, if you feel more comfortable with filing GitHub PRs, we can work with that too.

147
.github/workflows/main.yml vendored Normal file
View File

@@ -0,0 +1,147 @@
on:
push:
pull_request:
branches:
- master
name: CI
jobs:
build:
name: Tox test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: fedora-python/tox-github-action@v37.0
with:
tox_env: ${{ matrix.tox_env }}
dnf_install: ${{ matrix.dnf_install }}
- uses: codecov/codecov-action@v3.1.1
if: ${{ endswith(matrix.tox_env, '-cover') }}
with:
files: ${{ github.workspace }}/cover/coverage.xml
strategy:
fail-fast: false
matrix:
tox_env:
- py38
- py39
- py310
- py311
- py312-cover
include:
- tox_env: docs
dnf_install: graphviz
pypi:
needs: build
if: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') && github.repository_owner == 'Telecominfraproject' }}
name: PyPI packaging
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: actions/setup-python@v4
name: Install Python
with:
python-version: '3.12'
- uses: casperdcl/deploy-pypi@bb869aafd89f657ceaafe9561d3b5584766c0f95
with:
password: ${{ secrets.PYPI_API_TOKEN }}
pip: wheel -w dist/ --no-deps .
upload: true
docker:
needs: build
if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/v')) && github.repository_owner == 'Telecominfraproject' }}
name: Docker image
runs-on: ubuntu-latest
steps:
- name: Log in to Docker Hub
uses: docker/login-action@v1
with:
username: jktjkt
password: ${{ secrets.DOCKERHUB_TOKEN }}
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Extract tag name
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
id: extract_pretty_git
run: echo ::set-output name=GIT_DESC::$(git describe --tags)
- name: Build and push a container
uses: docker/build-push-action@v2
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
with:
context: .
push: true
tags: |
telecominfraproject/oopt-gnpy:${{ steps.extract_pretty_git.outputs.GIT_DESC }}
telecominfraproject/oopt-gnpy:master
- name: Extract tag name
if: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') }}
id: extract_tag_name
run: echo ::set-output name=GIT_DESC::${GITHUB_REF/refs\/tags\//}
- name: Build and push a container
uses: docker/build-push-action@v2
if: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') }}
with:
context: .
push: true
tags: |
telecominfraproject/oopt-gnpy:${{ steps.extract_tag_name.outputs.GIT_DESC }}
telecominfraproject/oopt-gnpy:latest
other-platforms:
name: Tests on other platforms
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python_version }}
- run: |
pip install --editable .[tests]
pytest -vv
strategy:
fail-fast: false
matrix:
include:
- os: windows-2022
python_version: "3.11"
- os: windows-2022
python_version: "3.12"
- os: windows-2025
python_version: "3.11"
- os: windows-2025
python_version: "3.12"
- os: macos-13
python_version: "3.12"
- os: macos-14
python_version: "3.12"
paywalled-platforms:
name: Tests on paywalled platforms
if: github.repository_owner == 'Telecominfraproject'
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python_version }}
- run: |
pip install --editable .[tests]
pytest -vv
strategy:
fail-fast: false
matrix:
include:
- os: macos-13-xlarge # Apple M1 CPU
python_version: "3.12"

5
.gitignore vendored
View File

@@ -2,6 +2,8 @@
__pycache__/
*.py[cod]
*$py.class
.ipynb_checkpoints
.idea
# C extensions
*.so
@@ -60,3 +62,6 @@ target/
# pyenv python configuration file
.python-version
# MacOS DS_store
.DS_Store

4
.gitreview Normal file
View File

@@ -0,0 +1,4 @@
[gerrit]
host=review.gerrithub.io
project=Telecominfraproject/oopt-gnpy
defaultrebase=0

3
.lgtm.yml Normal file
View File

@@ -0,0 +1,3 @@
queries:
- exclude: py/clear-text-logging-sensitive-data
- exclude: py/clear-text-storage-sensitive-data

17
.readthedocs.yml Normal file
View File

@@ -0,0 +1,17 @@
version: 2
build:
os: ubuntu-22.04
tools:
python: "3.12"
apt_packages:
- graphviz
python:
install:
- method: pip
path: .
extra_requirements:
- docs
sphinx:
configuration: docs/conf.py

View File

@@ -1,29 +0,0 @@
# Config file for automatic testing at travis-ci.org
# This file will be regenerated if you run travis_pypi_setup.py
language: python
python:
- 3.5
- 3.4
- 3.3
- 2.7
- 2.6
# command to install dependencies, e.g. pip install -r requirements.txt --use-mirrors
install: pip install -U tox-travis
# command to run tests, e.g. python setup.py test
script: tox
# After you create the Github repo and add it to Travis, run the
# travis_pypi_setup.py script to finish PyPI deployment setup
deploy:
provider: pypi
distributions: sdist bdist_wheel
user: <TBD>
password:
secure: PLEASE_REPLACE_ME
on:
tags: true
repo: <TBD>/gnpy
python: 2.7

54
.zuul.yaml Normal file
View File

@@ -0,0 +1,54 @@
---
- project:
check:
jobs:
- tox-py38:
vars:
ensure_tox_version: '<4'
- tox-py39:
vars:
ensure_tox_version: '<4'
- tox-py310-cover:
vars:
ensure_tox_version: '<4'
- tox-docs-f36:
vars:
ensure_tox_version: '<4'
- coverage-diff:
voting: false
dependencies:
- tox-py310-cover-previous
- tox-py310-cover
vars:
coverage_job_name_previous: tox-py310-cover-previous
coverage_job_name_current: tox-py310-cover
- tox-linters-diff-n-report:
voting: false
vars:
ensure_tox_version: '<4'
- tox-py310-cover-previous:
vars:
ensure_tox_version: '<4'
tag:
jobs:
- oopt-release-python:
secrets:
- secret: pypi-oopt-gnpy
name: pypi_info
pass-to-parent: true
- secret:
name: pypi-oopt-gnpy
data:
username: __token__
password: !encrypted/pkcs1-oaep
- Taod9JmSMtVAvC5ShSbB3UWuccktQvutdySrj0G7a1Nk4tKFQIdwDXEnBuLpHsZVvsU9Q
6uk4wRVQABDSdNNI/+M/1FwmZfoxuOXa02U5S1deuxW/rBHTxzYcuB8xriwhArBvTiDMk
zyWHVysgDsjlR+85h/DkEhvsaMRDLYWqFwYgXizMoGNKVkwDVIH+qkhBmbggQfDpcYPKT
1gq0d6fw0eKVJtO8+vonMEcE0sWZvHmZvSSu0H++gxoe1W/JtzbCteH3Ak0zktwBHI8Qt
WBqFvY3laad335tpkFJN5b949N+DP8svCWwRwXmkZlHplPYZWF6QpYbEEXL/6Q0H6VwL+
om4f7ybYpKe9Gl939uv2INnXaKe5EU6CMsSw40r2XZCjnSTjWOTgh9pUn2PsoHnqUlALW
VR4Z+ipnCrEbu8aTmX3ROcnwYNS7OXkq4uhwDU1u9QjzyMHet6NQQhwhGtimsTo9KhL4E
TEUNiRlbAgow9WOwM5r3vRzddO8T2HZZSGaWj75qNRX46XPQWRWgB7ItAwyXgwLZ8UzWl
HdztjS3D7Hlsqno3zxNOVlhA5/vl9uVnhFbJnMtUOJAB07YoTJOeR+LjQ0avx/VzopxXc
RA/WvJXVZSBrlAHY0+ip4wPZvdi4Ph90gpmvHJvoH82KVfp2j5jxzUhsage94I=

View File

@@ -1,13 +1,37 @@
=======
Credits
=======
gnpy is written and maintained by the Telecom Infra Project with work
contributed by the following TIP members.
Development Lead
----------------
To learn how to contribute, please see CONTRIBUTING.md
* <TBD> <<TBD>@<TBD>.com>
(*in alphabetical order*)
Contributors
------------
None yet. Why not be the first?
- Alessio Ferrari (Politecnico di Torino) <alessio.ferrari@polito.it>
- Anders Lindgren (Telia Company) <Anders.X.Lindgren@teliacompany.com>
- Andrea D'Amico (NEC) <adamico@nec-labs.com>
- Arturo Mayoral (Telecom Infra Project) <amayoral@telecominfraproject.com>
- Brian Taylor (Facebook) <briantaylor@fb.com>
- David Boertjes (Ciena) <dboertje@ciena.com>
- Diego Landa (Facebook) <dlanda@fb.com>
- Emmanuelle Delfour (Orange) <WEDE7391@orange.com>
- Esther Le Rouzic (Orange) <esther.lerouzic@orange.com>
- Florian Frank (Orange) <florian1.frank@orange.com>
- Gabriele Galimberti (Cisco) <ggalimbe@cisco.com>
- Gert Grammel (Juniper Networks) <ggrammel@juniper.net>
- Giacomo Borraccini (NEC Laboratories America) <gborraccini@nec-labs.com>
- Gilad Goldfarb (Facebook) <giladg@fb.com>
- James Powell (Telecom Infra Project) <james.powell@telecominfraproject.com>
- Jan Kundrát (Telecom Infra Project) <jkt@jankundrat.com>
- Jeanluc Augé (Orange) <jeanluc.auge@orange.com>
- Jenny L'Escop (Orange) <jenny.lescop@orange.com>
- Jonas Mårtensson (RISE) <jonas.martensson@ri.se>
- Mattia Cantono (Politecnico di Torino) <mattia.cantono@polito.it>
- Miguel Garrich (University Catalunya) <miquel.garrich@upct.es>
- Raj Nagarajan (Lumentum) <raj.nagarajan@lumentum.com>
- Renato Ambrosone (Politecnico di Torino) <renato.ambrosone@polito.it>
- Roberts Miculens (Lattelecom) <roberts.miculens@lattelecom.lv>
- Rodrigo Sasse David (Orange) <rodrigo.sassedavid@orange.com>
- Sami Alavi (NUST) <sami.mansooralavi1999@gmail.com>
- Shengxiang Zhu (University of Arizona) <szhu@email.arizona.edu>
- Stefan Melin (Telia Company) <Stefan.Melin@teliacompany.com>
- Vittorio Curri (Politecnico di Torino) <vittorio.curri@polito.it>
- Xufeng Liu (Jabil) <xufeng_liu@jabil.com>

View File

@@ -1,114 +0,0 @@
.. highlight:: shell
============
Contributing
============
Contributions are welcome, and they are greatly appreciated! Every
little bit helps, and credit will always be given.
You can contribute in many ways:
Types of Contributions
----------------------
Report Bugs
~~~~~~~~~~~
Report bugs at https://github.com/<TBD>/gnpy/issues.
If you are reporting a bug, please include:
* Your operating system name and version.
* Any details about your local setup that might be helpful in troubleshooting.
* Detailed steps to reproduce the bug.
Fix Bugs
~~~~~~~~
Look through the GitHub issues for bugs. Anything tagged with "bug"
and "help wanted" is open to whoever wants to implement it.
Implement Features
~~~~~~~~~~~~~~~~~~
Look through the GitHub issues for features. Anything tagged with "enhancement"
and "help wanted" is open to whoever wants to implement it.
Write Documentation
~~~~~~~~~~~~~~~~~~~
gnpy could always use more documentation, whether as part of the
official gnpy docs, in docstrings, or even on the web in blog posts,
articles, and such.
Submit Feedback
~~~~~~~~~~~~~~~
The best way to send feedback is to file an issue at https://github.com/<TBD>/gnpy/issues.
If you are proposing a feature:
* Explain in detail how it would work.
* Keep the scope as narrow as possible, to make it easier to implement.
* Remember that this is a volunteer-driven project, and that contributions
are welcome :)
Get Started!
------------
Ready to contribute? Here's how to set up `gnpy` for local development.
1. Fork the `gnpy` repo on GitHub.
2. Clone your fork locally::
$ git clone git@github.com:your_name_here/gnpy.git
3. Install your local copy into a virtualenv. Assuming you have virtualenvwrapper installed, this is how you set up your fork for local development::
$ mkvirtualenv gnpy
$ cd gnpy/
$ python setup.py develop
4. Create a branch for local development::
$ git checkout -b name-of-your-bugfix-or-feature
Now you can make your changes locally.
5. When you're done making changes, check that your changes pass flake8 and the tests, including testing other Python versions with tox::
$ flake8 gnpy tests
$ python setup.py test or py.test
$ tox
To get flake8 and tox, just pip install them into your virtualenv.
6. Commit your changes and push your branch to GitHub::
$ git add .
$ git commit -m "Your detailed description of your changes."
$ git push origin name-of-your-bugfix-or-feature
7. Submit a pull request through the GitHub website.
Pull Request Guidelines
-----------------------
Before you submit a pull request, check that it meets these guidelines:
1. The pull request should include tests.
2. If the pull request adds functionality, the docs should be updated. Put
your new functionality into a function with a docstring, and add the
feature to the list in README.rst.
3. The pull request should work for Python 2.6, 2.7, 3.3, 3.4 and 3.5, and for PyPy. Check
https://travis-ci.org/<TBD>/gnpy/pull_requests
and make sure that the tests pass for all supported Python versions.
Tips
----
To run a subset of tests::
$ py.test tests.test_gnpy

8
Dockerfile Normal file
View File

@@ -0,0 +1,8 @@
FROM python:3.9-slim
COPY . /oopt-gnpy
WORKDIR /oopt-gnpy
RUN apt update; apt install -y git
RUN pip install .
WORKDIR /shared/example-data
ENTRYPOINT ["/oopt-gnpy/.docker-entry.sh"]
CMD ["/bin/bash"]

View File

@@ -1,8 +0,0 @@
=======
History
=======
0.1.0 (2017-06-29)
------------------
* First release on PyPI.

40
LICENSE
View File

@@ -1,31 +1,29 @@
BSD 3-Clause License
BSD License
Copyright (c) 2017, <TBD>
Copyright (c) 2018, Telecom Infra Project
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -1,11 +0,0 @@
include AUTHORS.rst
include CONTRIBUTING.rst
include HISTORY.rst
include LICENSE
include README.rst
recursive-include tests *
recursive-exclude * __pycache__
recursive-exclude * *.py[co]
recursive-include docs *.rst conf.py Makefile make.bat *.jpg *.png *.gif

View File

@@ -1,87 +0,0 @@
.PHONY: clean clean-test clean-pyc clean-build docs help
.DEFAULT_GOAL := help
define BROWSER_PYSCRIPT
import os, webbrowser, sys
try:
from urllib import pathname2url
except:
from urllib.request import pathname2url
webbrowser.open("file://" + pathname2url(os.path.abspath(sys.argv[1])))
endef
export BROWSER_PYSCRIPT
define PRINT_HELP_PYSCRIPT
import re, sys
for line in sys.stdin:
match = re.match(r'^([a-zA-Z_-]+):.*?## (.*)$$', line)
if match:
target, help = match.groups()
print("%-20s %s" % (target, help))
endef
export PRINT_HELP_PYSCRIPT
BROWSER := python -c "$$BROWSER_PYSCRIPT"
help:
@python -c "$$PRINT_HELP_PYSCRIPT" < $(MAKEFILE_LIST)
clean: clean-build clean-pyc clean-test ## remove all build, test, coverage and Python artifacts
clean-build: ## remove build artifacts
rm -fr build/
rm -fr dist/
rm -fr .eggs/
find . -name '*.egg-info' -exec rm -fr {} +
find . -name '*.egg' -exec rm -f {} +
clean-pyc: ## remove Python file artifacts
find . -name '*.pyc' -exec rm -f {} +
find . -name '*.pyo' -exec rm -f {} +
find . -name '*~' -exec rm -f {} +
find . -name '__pycache__' -exec rm -fr {} +
clean-test: ## remove test and coverage artifacts
rm -fr .tox/
rm -f .coverage
rm -fr htmlcov/
lint: ## check style with flake8
flake8 gnpy tests
test: ## run tests quickly with the default Python
py.test
test-all: ## run tests on every Python version with tox
tox
coverage: ## check code coverage quickly with the default Python
coverage run --source gnpy -m pytest
coverage report -m
coverage html
$(BROWSER) htmlcov/index.html
docs: ## generate Sphinx HTML documentation, including API docs
rm -f docs/gnpy.rst
rm -f docs/modules.rst
sphinx-apidoc -o docs/ gnpy
$(MAKE) -C docs clean
$(MAKE) -C docs html
$(BROWSER) docs/_build/html/index.html
servedocs: docs ## compile the docs watching for changes
watchmedo shell-command -p '*.rst' -c '$(MAKE) -C docs html' -R -D .
release: clean ## package and upload a release
python setup.py sdist upload
python setup.py bdist_wheel upload
dist: clean ## builds source and wheel package
python setup.py sdist
python setup.py bdist_wheel
ls -l dist
install: clean ## install the package to the active Python's site-packages
python setup.py install

35
README.md Normal file
View File

@@ -0,0 +1,35 @@
# GNPy: Optical Route Planning and DWDM Network Optimization
[![Install via pip](https://img.shields.io/pypi/v/gnpy)](https://pypi.org/project/gnpy/)
[![Python versions](https://img.shields.io/pypi/pyversions/gnpy)](https://pypi.org/project/gnpy/)
[![Documentation status](https://readthedocs.org/projects/gnpy/badge/?version=master)](http://gnpy.readthedocs.io/en/master/?badge=master)
[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/Telecominfraproject/oopt-gnpy/main.yml)](https://github.com/Telecominfraproject/oopt-gnpy/actions/workflows/main.yml)
[![Gerrit](https://img.shields.io/badge/patches-via%20Gerrit-blue)](https://review.gerrithub.io/q/project:Telecominfraproject/oopt-gnpy+is:open)
[![Contributors](https://img.shields.io/github/contributors-anon/Telecominfraproject/oopt-gnpy)](https://github.com/Telecominfraproject/oopt-gnpy/graphs/contributors)
[![Code Coverage via codecov](https://img.shields.io/codecov/c/github/Telecominfraproject/oopt-gnpy)](https://codecov.io/gh/Telecominfraproject/oopt-gnpy)
[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.3458319.svg)](https://doi.org/10.5281/zenodo.3458319)
[![Matrix chat](https://img.shields.io/matrix/oopt-gnpy:matrix.org)](https://matrix.to/#/%23oopt-gnpy%3Amatrix.org?via=matrix.org)
GNPy is an open-source, community-developed library for building route planning and optimization tools in real-world mesh optical networks.
We are a consortium of operators, vendors, and academic researchers sponsored via the [Telecom Infra Project](http://telecominfraproject.com)'s [OOPT/PSE](https://telecominfraproject.com/open-optical-packet-transport) working group.
Together, we are building this tool for rapid development of production-grade route planning tools which is easily extensible to include custom network elements and performant to the scale of real-world mesh optical networks.
![GNPy with an OLS system](docs/images/GNPy-banner.png)
## Quick Start
Install either via [Docker](https://gnpy.readthedocs.io/en/master/install.html#using-prebuilt-docker-images), or as a [Python package](https://gnpy.readthedocs.io/en/master/install.html#using-python-on-your-computer).
Read our [documentation](https://gnpy.readthedocs.io/), learn from the demos, and [get in touch with us](https://github.com/Telecominfraproject/oopt-gnpy/discussions).
This example demonstrates how GNPy can be used to check the expected SNR at the end of the line by varying the channel input power:
![Running a simple simulation example](docs/images/gnpy-transmission-example.svg)
GNPy can do much more, including acting as a Path Computation Engine, tracking bandwidth requests, or advising the SDN controller about a best possible path through a large DWDM network.
Learn more about this [in the documentation](https://gnpy.readthedocs.io/), or give it a [try online at `gnpy.app`](https://gnpy.app/):
[![Path propagation at gnpy.app](docs/images/2022-04-12-gnpy-app.png)](https://gnpy.app/)
## Project Calendar
See upcoming meetings on the [Project Calendar](https://telecominfraproject.github.io/oopt-gnpy/calendar.html). The calendar is embedded from Google Calendar and updates automatically.

View File

@@ -1,32 +0,0 @@
====
gnpy
====
.. image:: https://img.shields.io/pypi/v/gnpy.svg
:target: https://pypi.python.org/pypi/gnpy
.. image:: https://img.shields.io/travis/<TBD>/gnpy.svg
:target: https://travis-ci.org/<TBD>/gnpy
.. image:: https://readthedocs.org/projects/gnpy/badge/?version=latest
:target: https://gnpy.readthedocs.io/en/latest/?badge=latest
:alt: Documentation Status
.. image:: https://pyup.io/repos/github/<TBD>/gnpy/shield.svg
:target: https://pyup.io/repos/github/<TBD>/gnpy/
:alt: Updates
Gaussian Noise (GN) modeling library
* Free software: BSD license
* Documentation: https://gnpy.readthedocs.io.
Features
--------
* TODO

1
bindep.txt Normal file
View File

@@ -0,0 +1 @@
graphviz

3
docs/.gitignore vendored
View File

@@ -1,3 +0,0 @@
/gnpy.rst
/gnpy.*.rst
/modules.rst

View File

@@ -1,177 +1,20 @@
# Makefile for Sphinx documentation
# Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
SPHINXBUILD = python -msphinx
SPHINXPROJ = GNpy
SOURCEDIR = .
BUILDDIR = _build
# User-friendly check for sphinx-build
ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
endif
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
# the i18n builder cannot share the environment and doctrees with the others
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
# Put it first so that "make" without argument is like "make help".
help:
@echo "Please use \`make <target>' where <target> is one of"
@echo " html to make standalone HTML files"
@echo " dirhtml to make HTML files named index.html in directories"
@echo " singlehtml to make a single large HTML file"
@echo " pickle to make pickle files"
@echo " json to make JSON files"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " qthelp to make HTML files and a qthelp project"
@echo " devhelp to make HTML files and a Devhelp project"
@echo " epub to make an epub"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " latexpdf to make LaTeX files and run them through pdflatex"
@echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
@echo " text to make text files"
@echo " man to make manual pages"
@echo " texinfo to make Texinfo files"
@echo " info to make Texinfo files and run them through makeinfo"
@echo " gettext to make PO message catalogs"
@echo " changes to make an overview of all changed/added/deprecated items"
@echo " xml to make Docutils-native XML files"
@echo " pseudoxml to make pseudoxml-XML files for display purposes"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
clean:
rm -rf $(BUILDDIR)/*
.PHONY: help Makefile
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
singlehtml:
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
@echo
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
json:
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
qthelp:
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/gnpy.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/gnpy.qhc"
devhelp:
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
@echo
@echo "Build finished."
@echo "To view the help file:"
@echo "# mkdir -p $$HOME/.local/share/devhelp/gnpy"
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/gnpy"
@echo "# devhelp"
epub:
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
@echo
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make' in that directory to run these through (pdf)latex" \
"(use \`make latexpdf' here to do that automatically)."
latexpdf:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through pdflatex..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
latexpdfja:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through platex and dvipdfmx..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
text:
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
@echo
@echo "Build finished. The text files are in $(BUILDDIR)/text."
man:
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
@echo
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
texinfo:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
@echo "Run \`make' in that directory to run these through makeinfo" \
"(use \`make info' here to do that automatically)."
info:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo "Running Texinfo files through makeinfo..."
make -C $(BUILDDIR)/texinfo info
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
gettext:
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
@echo
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."
xml:
$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
@echo
@echo "Build finished. The XML files are in $(BUILDDIR)/xml."
pseudoxml:
$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
@echo
@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

4
docs/_static/custom.css vendored Normal file
View File

@@ -0,0 +1,4 @@
.wy-table-responsive table td, .wy-table-responsive table th {
white-space: normal;
}

60
docs/about-project.md Normal file
View File

@@ -0,0 +1,60 @@
(about-gnpy)=
# About the project
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).
There are weekly calls about our progress.
Newcomers, users and telecom operators are especially welcome there.
We encourage all interested people outside the TIP to [join the project](https://telecominfraproject.com/apply-for-membership/) and especially to [get in touch with us](https://github.com/Telecominfraproject/oopt-gnpy/discussions).
(contributing)=
## Contributing
`gnpy` is looking for additional contributors, especially those with experience planning and maintaining large-scale, real-world mesh optical networks.
To get involved, please contact [Esther Le Rouzic](mailto:esther.lerouzic@orange.com) or
[Andrea d'Amico](mailto:adamico@nec-labs.com) or [Gert Grammel](mailto:ggrammel@juniper.net).
`gnpy` contributions are currently limited to members of [TIP](http://telecominfraproject.com).
Membership is free and open to all.
See the [Onboarding Guide](https://github.com/Telecominfraproject/gnpy/wiki/Onboarding-Guide) for specific details on code contributions, or just [upload patches to our Gerrit](https://review.gerrithub.io/Documentation/intro-gerrit-walkthrough-github.html).
Here is [what we are currently working on](https://review.gerrithub.io/q/project:Telecominfraproject/oopt-gnpy+status:open).
## Project Background
Data Centers are built upon interchangeable, highly standardized node and network architectures rather than a sum of isolated solutions.
This also translates to optical networking.
It leads to a push in enabling multi-vendor optical network by disaggregating HW and SW functions and focusing on interoperability.
In this paradigm, the burden of responsibility for ensuring the performance of such disaggregated open optical systems falls on the operators.
Consequently, operators and vendors are collaborating in defining control models that can be readily used by off-the-shelf controllers.
However, node and network models are only part of the answer.
To take reasonable decisions, controllers need to incorporate logic to simulate and assess optical performance.
Hence, a vendor-independent optical quality estimator is required.
Given its vendor-agnostic nature, such an estimator needs to be driven by a consortium of operators, system and component suppliers.
Founded in February 2016, the Telecom Infra Project (TIP) is an engineering-focused initiative which is operator driven, but features collaboration across operators, suppliers, developers, integrators, and startups with the goal of disaggregating the traditional network deployment approach.
The groups ultimate goal is to help provide better connectivity for communities all over the world as more people come on-line and demand more bandwidth-intensive experiences like video, virtual reality and augmented reality.
Within TIP, the Open Optical Packet Transport (OOPT) project group is chartered with unbundling monolithic packet-optical network technologies in order to unlock innovation and support new, more flexible connectivity paradigms.
The key to unbundling is the ability to accurately plan and predict the performance of optical line systems based on an accurate simulation of optical parameters.
Under that OOPT umbrella, the Physical Simulation Environment (PSE) working group set out to disrupt the planning landscape by providing an open source simulation model which can be used freely across multiple vendor implementations.
## TIP OOPT/PSE & PSE WG Charter
We believe that openly sharing ideas, specifications, and other intellectual property is the key to maximizing innovation and reducing complexity
TIP OOPT/PSE's goal is to build an end-to-end simulation environment which defines the network models of the optical device transfer functions and their parameters.
This environment will provide validation of the optical performance requirements for the TIP OLS building blocks.
- The model may be approximate or complete depending on the network complexity.
Each model shall be validated against the proposed network scenario.
- The environment must be able to process network models from multiple vendors, and also allow users to pick any implementation in an open source framework.
- The PSE will influence and benefit from the innovation of the DTC, API, and OLS working groups.
- The PSE represents a step along the journey towards multi-layer optimization.
License
-------
GNPy is distributed under a standard BSD 3-Clause License.

View File

@@ -0,0 +1,318 @@
.. _amp_models:
**********************************
Amplifier models and Configuration
**********************************
1. Equipment configuration description
======================================
Equipment description defines equipment types and parameters.
It takes place in the equipment library such as **eqpt_config.json** file defined in example-data folder.
By default **gnpy-transmission-example** uses **eqpt_config.json** file and that
can be changed with **-e** or **--equipment** command line parameter.
2. Amplifier parameters and subtypes
====================================
Several amplifiers can be used by GNpy, so they are defined as an array of equipment parameters in **eqpt_config.json** file.
- *"type_variety"*:
Each amplifier is identified by its unique *"type_variety"*, which is used in the topology files input to reference a specific amplifier. It is a user free defined id.
For each amplifier *type_variety*, specific parameters are describing its attributes and performance:
- *"type_def"*:
Sets the amplifier model that the simulation will use to calculate the ase noise contribution. 5 models are defined with reserved words:
- *"advanced_model"*
- *"variable_gain"*
- *"fixed_gain"*
- *"dual_stage"*
- *"multi_band"*
- *"openroadm"*
*see next section for a full description of these models*
- *"default_config_from_json"*:
Use a custom per frequency dynamic gain tilt, gain and noise ripple arrays defined in the file specified with
this option, instead of the default values from GNPy.
- *"advanced_config_from_json"*:
**This parameter is only applicable to the _"advanced_model"_ model**
json file name describing:
- nf_fit_coeff
- f_min/max
- gain_ripple
- nf_ripple
- dgt
*see next section for a full description*
- *"gain_flatmax"*:
amplifier maximum gain in dB before its extended gain range: flat or nominal tilt output.
If gain > gain_flatmax, the amplifier will tilt, based on its dgt function
If gain > gain_flatmax + target_extended_gain, the amplifier output power is reduced to not exceed the extended gain range.
- *"gain_min"*:
amplifier minimum gain in dB.
If gain < gain_min, the amplifier input is automatically padded, which results in
NF += gain_min - gain
- *"p_max"*:
amplifier max output power, full load
Total signal output power will not be allowed beyond this value
- *"nf_min/max"*:
**These parameters are only applicable to the _"variable_gain"_ model**
min & max NF values in dB
NF_min is the amplifier NF @ gain_max
NF_max is the amplifier NF @ gain_min
- *"nf_coef"*:
**This parameter is only applicable to the *"openroadm"* model**
[a, b, c, d] 3rd order polynomial coefficients list to define the incremental OSNR vs Pin
Incremental OSNR is the amplifier OSNR contribution
Pin is the amplifier channel input power defined in a 50GHz bandwidth
Incremental OSNR = a*Pin³ + b*Pin² + c*Pin + d
- *"preamp_variety"*:
**This parameter is only applicable to the _"dual_stage"_ model**
1st stage type_variety
- *"booster_variety"*:
**This parameter is only applicable to the *"dual_stage"* model**
2nd stage type_variety
- *"out_voa_auto"*: true/false
**power_mode only**
**This parameter is only applicable to the *"advanced_model"* and *"variable_gain"* models**
If "out_voa_auto": true, auto_design will chose the output_VOA value that maximizes the amplifier gain within its power capability and therefore minimizes its NF.
- *"allowed_for_design"*: true/false
**auto_design only**
Tells auto_design if this amplifier can be picked for the design (deactivates unwanted amplifiers)
It does not prevent the use of an amplifier if it is placed in the topology input.
.. code-block:: json
{"Edfa": [{
"type_variety": "std_medium_gain",
"type_def": "variable_gain",
"gain_flatmax": 26,
"gain_min": 15,
"p_max": 23,
"nf_min": 6,
"nf_max": 10,
"out_voa_auto": false,
"allowed_for_design": true
},
{
"type_variety": "std_low_gain",
"type_def": "variable_gain",
"gain_flatmax": 16,
"gain_min": 8,
"p_max": 23,
"nf_min": 6.5,
"nf_max": 11,
"out_voa_auto": false,
"allowed_for_design": true
}
]}
3. Amplifier models
===================
In an opensource and multi-vendor environnement, it is needed to support different use cases and context. Therefore several models are supported for amplifiers.
5 types of EDFA definition are possible and referenced by the *"type_def"* parameter with the following reserved words:
- *"advanced_model"*
This model is refered as a whitebox model because of the detailed level of knowledge that is required. The amplifier NF model and ripple definition are described by a json file referenced with *"advanced_config_from_json"*: json filename. This json file contains:
- nf_fit_coeff: [a,b,c,d]
3rd order polynomial NF = f(-dg) coeficients list
dg = gain - gain_max
- f_min/max: amplifier frequency range in Hz
- gain_ripple : [...]
amplifier gain ripple excursion comb list in dB across the frequency range.
- nf_ripple : [...]
amplifier nf ripple excursion comb list in dB across the frequency range.
- dgt : [...]
amplifier dynamic gain tilt comb list across the frequency range.
*See next section for the generation of this json file*
.. code-block:: json-object
"Edfa":[{
"type_variety": "high_detail_model_example",
"type_def": "advanced_model",
"gain_flatmax": 25,
"gain_min": 15,
"p_max": 21,
"advanced_config_from_json": "std_medium_gain_advanced_config.json",
"out_voa_auto": false,
"allowed_for_design": false
}
]
- *"variable_gain"*
This model is refered as an operator model because a lower level of knowledge is required. A full polynomial description of the NF cross the gain range is not required. Instead, NF_min and NF_max values are required and used by the code to model a dual stage amplifier with an internal mid stage VOA. NF_min and NF_max values are typically available from equipment suppliers data-sheet.
There is a default configuration to enforce 0 tilt and ripple values because GNPy core algorithm is a multi-carrier propagation.
- gain_ripple =[0,...,0]
- nf_ripple = [0,...,0]
- dgt = [...] generic dgt comb
.. code-block:: json-object
"Edfa":[{
"type_variety": "std_medium_gain",
"type_def": "variable_gain",
"gain_flatmax": 26,
"gain_min": 15,
"p_max": 23,
"nf_min": 6,
"nf_max": 10,
"out_voa_auto": false,
"allowed_for_design": true
}
]
- *"fixed_gain"*
This model is also an operator model with a single NF value that emulates basic single coil amplifiers without internal VOA.
if gain_min < gain < gain_max, NF == nf0
if gain < gain_min, the amplifier input is automatically padded, which results in
NF += gain_min - gain
.. code-block:: json-object
"Edfa":[{
"type_variety": "std_fixed_gain",
"type_def": "fixed_gain",
"gain_flatmax": 21,
"gain_min": 20,
"p_max": 21,
"nf0": 5.5,
"allowed_for_design": false
}
]
- *"openroadm"*
This model is a black box model replicating OpenRoadm MSA spec for ILA.
.. code-block:: json-object
"Edfa":[{
"type_variety": "openroadm_ila_low_noise",
"type_def": "openroadm",
"gain_flatmax": 27,
"gain_min": 12,
"p_max": 22,
"nf_coef": [-8.104e-4,-6.221e-2,-5.889e-1,37.62],
"allowed_for_design": false
}
]
- *"dual_stage"*
This model allows the cascade (pre-defined combination) of any 2 amplifiers already described in the eqpt_config.json library.
- preamp_variety defines the 1st stge type variety
- booster variety defines the 2nd stage type variety
Both preamp and booster variety must exist in the eqpt libray
The resulting NF is the sum of the 2 amplifiers
The preamp is operated to its maximum gain
- gain_min indicates to auto_design when this dual_stage should be used
But unlike other models the 1st stage input will not be padded: it is always operated to its maximum gain and min NF. Therefore if gain adaptation and padding is needed it will be performed by the 2nd stage.
.. code-block:: json
{
"type_variety": "medium+low_gain",
"type_def": "dual_stage",
"gain_min": 25,
"preamp_variety": "std_medium_gain",
"booster_variety": "std_low_gain",
"allowed_for_design": true
}
- *"multiband"*
This model enables the definition of multiband amplifiers that consist of multiple single-band
amplifier elements, with each amplifier responsible for amplifying a different portion of the spectrum.
The types of single-band amplifiers that can be included in these multiband amplifiers are specified,
allowing for multiple options to be available for the same spectrum band (for instance, providing
several permitted type varieties for both the C-band and the L-band). The actual element utilizing the
type_variety must implement only one option for each band.
4. advanced_config_from_json
============================
The build_oa_json.py library in ``gnpy/example-data/edfa_model/`` can be used to build the json file required for the amplifier advanced_model type_def:
Update an existing json file with all the 96ch txt files for a given amplifier type
amplifier type 'OA_type1' is hard coded but can be modified and other types added
returns an updated amplifier json file: output_json_file_name = 'edfa_config.json'
amplifier file names
Convert a set of amplifier files + input json definiton file into a valid edfa_json_file:
nf_fit_coeff: NF 3rd order polynomial coefficients txt file
nf = f(dg) with dg = gain_operational - gain_max
nf_ripple: NF ripple excursion txt file
gain_ripple: gain ripple txt file
dgt: dynamic gain txt file
input json file in argument (defult = 'OA.json')
the json input file should have the following fields:
.. code-block:: json
{
"nf_fit_coeff": "nf_filename.txt",
"nf_ripple": "nf_ripple_filename.txt",
"gain_ripple": "DFG_filename.txt",
"dgt": "DGT_filename.txt"
}

View File

@@ -1 +0,0 @@
.. include:: ../AUTHORS.rst

2024
docs/biblio.bib Normal file

File diff suppressed because it is too large Load Diff

29
docs/calendar.html Normal file
View File

@@ -0,0 +1,29 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Project Calendar</title>
<style>
body { font-family: system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, sans-serif; margin: 20px; }
.container { max-width: 1000px; margin: 0 auto; }
h1 { font-size: 1.8rem; margin-bottom: 1rem; }
iframe { border: 0; width: 100%; height: 800px; }
.note { color: #555; margin-top: 1rem; font-size: 0.9rem; }
</style>
</head>
<body>
<div class="container">
<h1>Project Calendar</h1>
<p>This page embeds the public project calendar. It updates automatically when events change in Google Calendar.</p>
<iframe
src="https://calendar.google.com/calendar/embed?src=c_0895d13d880537c3e54db61ba95e9df167db19a49b96d41e42e2c6d842f30a6a%40group.calendar.google.com&ctz=Europe%2FMadrid"
frameborder="0"
scrolling="no"
></iframe>
<p class="note">Timezone: Europe/Madrid. If you prefer your local timezone, add <code>&amp;ctz=Your%2FTimezone</code> to the URL.</p>
</div>
</body>
</html>

297
docs/cli_options.rst Normal file
View File

@@ -0,0 +1,297 @@
.. _cli-options:
***********************************************************
`gnpy-path-request` and `gnpy-transmission-example` scripts
***********************************************************
Common options
==============
**Option**: `--no-insert-edfas`
-------------------------------
**Purpose**: Disables the automatic insertion of EDFAs after ROADMs and fibers, as well as the splitting
of fibers during the auto-design process.
The `--no-insert-edfas` option is a command-line argument available in GNPy that allows users to control the
automatic insertion of amplifiers during the network design process. This option provides flexibility for
users who may want to manually manage amplifier placements or who have specific design requirements that
do not necessitate automatic amplification.
To use the `--no-insert-edfas` option, simply include it in the command line when running your GNPy program. For example:
.. code-block:: shell-session
gnpy-transmission-example my_network.json --no-insert-edfas
When the `--no-insert-edfas` option is specified:
1. **No Automatic Amplifiers**: The program will not automatically add EDFAs to the network topology after
ROADMs or fiber elements. This means that if the network design requires amplification, users must ensure
that amplifiers are manually defined in the network topology file. Users should be aware that disabling
automatic amplifier insertion may lead to insufficient amplification in the network if not managed properly.
It is essential to ensure that the network topology includes the necessary amplifiers to meet performance requirements.
2. **No Fiber Splitting**: The option also prevents the automatic splitting of fibers during the design process.
This is particularly useful for users who want to maintain specific fiber lengths or configurations without
the program altering them.
**Option**: `--equipment`, `-e`
-------------------------------
**Description**: Specifies the equipment library file.
**Usage**:
.. code-block:: shell-session
gnpy-transmission-example my_network.json --equipment <FILE.json>
**Default**: Uses the default equipment configuration in the example-data folder if not specified.
**Functionality**: This option allows users to load a specific equipment configuration that defines the characteristics of the network elements.
**Option**: `--extra-equipment` and `--extra-config`
----------------------------------------------------
The `--extra-equipment` and `--extra-config` options allow users to extend the default equipment library and configuration
settings used by the GNPy program. This feature is particularly useful for users who need to incorporate additional
equipment types or specific configurations that are not included in the standard equipment library (such as third party pluggables).
**Usage**:
.. code-block:: shell-session
--extra-equipment <file1.json> [<file2.json> ...]
**Parameters**:
- `<file1.json>`: Path to the first additional equipment file.
- `<file2.json>`: Path to any subsequent additional equipment files (optional).
**Functionality**:
- The program will merge the equipment definitions from the specified files into the main equipment library.
- If an equipment type defined in the additional files has the same name as one in the main library, the program
will issue a warning about the duplicate entry and will include ony the last definition.
- This allows for flexibility in defining equipment that may be specific to certain use cases or vendor-specific models.
**`--extra-config`**:
**Description**: This option allows users to specify additional configuration files that can override
or extend the default configuration settings used by the program. This is useful for customizing simulation
parameters or equipment settings. To set an amplifier with a specific such config, it must be defined in the
library with the keyword "default_config_from_json" filled with the file name containing the config in the case of
"variable_gain" amplifier or with the "advanced_config_from_json" for the "advanced_model" amplifier.
**Usage**:
.. code-block:: shell-session
--extra-config <file1.json> [<file2.json> ...]
**Parameters**:
- `<file1.json>`: Path to the first additional configuration file.
- `<file2.json>`: Path to any subsequent additional configuration files (optional).
**Functionality**:
The program will load the configurations from the specified files and consider them instead of the
default configurations for the amplifiers that use the "default_config_from_json" or "advanced_config_from_json" keywords.
To run the program with additional equipment and configuration files, you can use the following command:
.. code-block:: shell-session
gnpy-transmission-example --equipment main_equipment.json \
--extra-equipment additional_equipment1.json additional_equipment2.json \
--extra-config additional_config1.json
In this example:
- `main_equipment.json` is the primary equipment file.
- `additional_equipment1.json` and `additional_equipment2.json` are additional equipment files that will be merged into the main library.
- `additional_config1.json` is an additional configuration file that will override the default settings for the amplifiers pointing to it.
**Option**: `--save-network`
----------------------------
**Description**: Saves the final network configuration to a specified JSON file.
**Usage**:
.. code-block:: shell-session
--save-network <FILE.json>
**Functionality**: This option allows users to save the network state after the simulation, which can be useful for future reference or analysis.
**Option**: `--save-network-before-autodesign`
----------------------------------------------
**Description**: Dumps the network into a JSON file prior to autodesign.
**Usage**:
.. code-block:: shell-session
gnpy-path-request my_network.json my_services.json --save-network-before-autodesign <FILE.json>
**Functionality**: This option is useful for users who want to inspect the network configuration before any automatic design adjustments are made.
**Option**: `--sim-params`
--------------------------
**Description**: Path to the JSON file containing simulation parameters.
**Usage**:
.. code-block:: shell-session
gnpy-transmission-example my_network.json --sim-params <FILE.json>
**Functionality**: The `--sim-params` option is a command-line argument available in GNPy that allows users to specify a
JSON file containing simulation parameters. This option is crucial for customizing the behavior of the simulation:
the file ``sim_params.json`` contains the tuning parameters used within both the ``gnpy.science_utils.RamanSolver`` and
the ``gnpy.science_utils.NliSolver`` for the evaluation of the Raman profile and the NLI generation, respectively.
The tuning of the parameters is detailed here: :ref:`json input sim-params<sim-params>`.
`gnpy-transmission-example` options
===================================
**Option**: `--show-channels`
-----------------------------
**Description**: Displays the final per-channel OSNR and GSNR summary.
**Usage**:
.. code-block:: shell-session
gnpy-transmission-example my_network.json --show-channels
**Functionality**: This option provides a summary of the optical signal-to-noise ratio (OSNR)
and generalized signal-to-noise ratio (GSNR) for each channel after the simulation.
**Option**: `-pl`, `--plot`
---------------------------
**Description**: Generates plots of the results.
**Usage**:
.. code-block:: shell-session
gnpy-transmission-example my_network.json -pl
**Functionality**: This option allows users to visualize the results of the simulation through graphical plots.
**Option**: `-l`, `--list-nodes`
--------------------------------
**Description**: Lists all transceiver nodes in the network.
**Usage**:
.. code-block:: shell-session
gnpy-transmission-example my_network.json -l
**Functionality**: This option provides a quick way to view all transceiver nodes present in the network topology.
**Option**: `-po`, `--power`
----------------------------
**Description**: Specifies the reference channel power in span in dBm.
**Usage**:
.. code-block:: shell-session
gnpy-transmission-example my_network.json -po <value>
**Functionality**: This option allows users to set the input power level for the reference channel used in the simulation.
It replaces the value specified in the `SI` section of the equipment library (:ref:`power_dbm<spectral_info>`).
**Option**: `--spectrum`
------------------------
**Description**: Specifies a user-defined mixed rate spectrum JSON file for propagation.
**Usage**:
.. code-block:: shell-session
gnpy-transmission-example my_network.json --spectrum <FILE.json>
**Functionality**: This option allows users to define a custom spectrum for the simulation, which can
include varying channel rates and configurations. More details here: :ref:`mixed-rate<mixed-rate>`.
Options for `path_requests_run`
===============================
The `gnpy-path-request` script provides a simple path computation function that supports routing, transceiver mode selection, and spectrum assignment.
It supports include and disjoint constraints for the path computation, but does not provide any optimisation.
It requires two mandatory arguments: network file and service file (see :ref:`XLS files<excel-service-sheet>` or :ref:`JSON files<legacy-json>`).
The `gnpy-path-request` computes:
- design network once and propagate the service requests on this design
- computes performance of each request defined in the service file independently from each other, considering full load (based on the request settings),
- assigns spectrum for each request according to the remaining spectrum, on a first arrived first served basis.
Lack of spectrum leads to blocking, but performance estimation is still returned for information.
**Option**: `-bi`, `--bidir`
----------------------------
**Description**: Indicates that all demands are bidirectional.
**Usage**:
.. code-block:: shell-session
gnpy-path-request my_network.json my_service.json -e my_equipment.json -bi
**Functionality**: This option allows users to specify that the performance of the service requests should be
computed in both directions (source to destination and destination to source). This forces the 'bidirectional'
attribute to true in the service file, possibly affecting feasibility if one direction is not feasible.
**Option**: `-o`, `--output`
----------------------------
**Description**: Stores computation results requests into a JSON or CSV file.
**Usage**:
.. code-block:: shell-session
gnpy-path-request my_network.json my_service.json -o <FILE.json|FILE.csv>
**Functionality**: This option allows users to save the results of the path requests into a specified output file
for further analysis.
**Option**: `--redesign-per-request`
------------------------------------
**Description**: Redesigns the network for each request using the request as the reference channel
(replaces the `SI` section of the equipment library with the request specifications).
**Usage**:
.. code-block:: shell-session
gnpy-path-request my_network.json my_services.json --redesign-per-request
**Functionality**: This option enables checking different scenarios for design.

271
docs/concepts.rst Normal file
View File

@@ -0,0 +1,271 @@
.. _concepts:
*****************************
Simulating networks with GNPy
*****************************
Running simulations with GNPy requires three pieces of information:
- the :ref:`network topology<concepts-topology>`, which describes how the network looks like, what are the fiber lengths, what amplifiers are used, etc.,
- the :ref:`equipment library<concepts-equipment>`, which holds machine-readable datasheets of the equipment used in the network,
- the :ref:`simulation options<concepts-simulation>` holding instructions about what to simulate, and under which conditions.
.. _concepts-topology:
Network Topology
================
The *topology* acts as a "digital self" of the simulated network.
When given a network topology, GNPy can either run a specific simulation as-is, or it can *optimize* the topology before performing the simulation.
A network topology for GNPy is often a generic, mesh network.
This enables GNPy to take into consideration the current spectrum allocation as well as availability and resiliency considerations.
When the time comes to run a particular *propagation* of a signal and its impairments are computed, though, a linear path through the network is used.
For this purpose, the *path* through the network refers to an ordered, acyclic sequence of *nodes* that are processed.
This path is directional, and all "GNPy elements" along the path match the unidirectional part of a real-world network equipment.
.. note::
In practical terms, an amplifier in GNPy refers to an entity with a single input port and a single output port.
A real-world inline EDFA enclosed in a single chassis will be therefore represented as two GNPy-level amplifiers.
The network topology contains not just the physical topology of the network, but also references to the :ref:`equipment library<concepts-equipment>` and a set of *operating parameters* for each entity.
These parameters include the **fiber length** of each fiber, the connector **attenutation losses**, or an amplifier's specific **gain setting**.
The topology is specified via :ref:`XLS files<excel>` or via :ref:`JSON<legacy-json>`.
.. _complete-vs-incomplete:
Fully Specified vs. Partially Designed Networks
-----------------------------------------------
Let's consider a simple triangle topology with three :abbr:`PoPs (Points of Presence)` covering three cities:
.. graphviz::
:layout: neato
:align: center
graph "High-level topology with three PoPs" {
A -- B
B -- C
C -- A
}
In the real world, each city would probably host a ROADM and some transponders:
.. graphviz::
:layout: neato
:align: center
graph "Simplified topology with transponders" {
"ROADM A" [pos="2,2!"]
"ROADM B" [pos="4,2!"]
"ROADM C" [pos="3,1!"]
"Transponder A" [shape=box, pos="0,2!"]
"Transponder B" [shape=box, pos="6,2!"]
"Transponder C" [shape=box, pos="3,0!"]
"ROADM A" -- "ROADM B"
"ROADM B" -- "ROADM C"
"ROADM C" -- "ROADM A"
"Transponder A" -- "ROADM A"
"Transponder B" -- "ROADM B"
"Transponder C" -- "ROADM C"
}
GNPy simulation works by propagating the optical signal over a sequence of elements, which means that one has to add some preamplifiers and boosters.
The amplifiers are, by definition, unidirectional, so the graph becomes quite complex:
.. _topo-roadm-preamp-booster:
.. graphviz::
:layout: neato
:align: center
digraph "Preamps and boosters are explicitly modeled in GNPy" {
"ROADM A" [pos="2,4!"]
"ROADM B" [pos="6,4!"]
"ROADM C" [pos="4,0!"]
"Transponder A" [shape=box, pos="1,5!"]
"Transponder B" [shape=box, pos="7,5!"]
"Transponder C" [shape=box, pos="4,-1!"]
"Transponder A" -> "ROADM A"
"Transponder B" -> "ROADM B"
"Transponder C" -> "ROADM C"
"ROADM A" -> "Transponder A"
"ROADM B" -> "Transponder B"
"ROADM C" -> "Transponder C"
"Booster A C" [shape=triangle, orientation=-150, fixedsize=true, width=0.5, height=0.5, pos="2.2,3.2!", color=red, label=""]
"Preamp A C" [shape=triangle, orientation=0, fixedsize=true, width=0.5, height=0.5, pos="1.5,3.0!", color=red, label=""]
"ROADM A" -> "Booster A C"
"Preamp A C" -> "ROADM A"
"Booster A B" [shape=triangle, orientation=-90, fixedsize=true, width=0.5, height=0.5, pos="3,4.3!", color=red, fontcolor=red, labelloc=b, label="\N\n\n"]
"Preamp A B" [shape=triangle, orientation=90, fixedsize=true, width=0.5, height=0.5, pos="3,3.6!", color=red, fontcolor=red, labelloc=t, label="\n \N"]
"ROADM A" -> "Booster A B"
"Preamp A B" -> "ROADM A"
"Booster C B" [shape=triangle, orientation=-30, fixedsize=true, width=0.5, height=0.5, pos="4.7,0.9!", color=red, label=""]
"Preamp C B" [shape=triangle, orientation=120, fixedsize=true, width=0.5, height=0.5, pos="5.4,0.7!", color=red, label=""]
"ROADM C" -> "Booster C B"
"Preamp C B" -> "ROADM C"
"Booster C A" [shape=triangle, orientation=30, fixedsize=true, width=0.5, height=0.5, pos="2.6,0.7!", color=red, label=""]
"Preamp C A" [shape=triangle, orientation=-30, fixedsize=true, width=0.5, height=0.5, pos="3.3,0.9!", color=red, label=""]
"ROADM C" -> "Booster C A"
"Preamp C A" -> "ROADM C"
"Booster B A" [shape=triangle, orientation=90, fixedsize=true, width=0.5, height=0.5, pos="5,3.6!", labelloc=t, color=red, fontcolor=red, label="\n\N "]
"Preamp B A" [shape=triangle, orientation=-90, fixedsize=true, width=0.5, height=0.5, pos="5,4.3!", labelloc=b, color=red, fontcolor=red, label="\N\n\n"]
"ROADM B" -> "Booster B A"
"Preamp B A" -> "ROADM B"
"Booster B C" [shape=triangle, orientation=-180, fixedsize=true, width=0.5, height=0.5, pos="6.5,3.0!", color=red, label=""]
"Preamp B C" [shape=triangle, orientation=-20, fixedsize=true, width=0.5, height=0.5, pos="5.8,3.2!", color=red, label=""]
"ROADM B" -> "Booster B C"
"Preamp B C" -> "ROADM B"
"Booster A C" -> "Preamp C A"
"Booster A B" -> "Preamp B A"
"Booster C A" -> "Preamp A C"
"Booster C B" -> "Preamp B C"
"Booster B C" -> "Preamp C B"
"Booster B A" -> "Preamp A B"
}
In many regions, the ROADMs are not placed physically close to each other, so the long-haul fiber links (:abbr:`OMS (Optical Multiplex Section)`) are split into individual spans (:abbr:`OTS (Optical Transport Section)`) by in-line amplifiers, resulting in an even more complicated topology graphs:
.. graphviz::
:layout: neato
:align: center
digraph "A subset of a real topology with inline amplifiers" {
"ROADM A" [pos="2,4!"]
"ROADM B" [pos="6,4!"]
"ROADM C" [pos="4,-3!"]
"Transponder A" [shape=box, pos="1,5!"]
"Transponder B" [shape=box, pos="7,5!"]
"Transponder C" [shape=box, pos="4,-4!"]
"Transponder A" -> "ROADM A"
"Transponder B" -> "ROADM B"
"Transponder C" -> "ROADM C"
"ROADM A" -> "Transponder A"
"ROADM B" -> "Transponder B"
"ROADM C" -> "Transponder C"
"Booster A C" [shape=triangle, orientation=-166, fixedsize=true, width=0.5, height=0.5, pos="2.2,3.2!", label=""]
"Preamp A C" [shape=triangle, orientation=0, fixedsize=true, width=0.5, height=0.5, pos="1.5,3.0!", label=""]
"ROADM A" -> "Booster A C"
"Preamp A C" -> "ROADM A"
"Booster A B" [shape=triangle, orientation=-90, fixedsize=true, width=0.5, height=0.5, pos="3,4.3!", label=""]
"Preamp A B" [shape=triangle, orientation=90, fixedsize=true, width=0.5, height=0.5, pos="3,3.6!", label=""]
"ROADM A" -> "Booster A B"
"Preamp A B" -> "ROADM A"
"Booster C B" [shape=triangle, orientation=-30, fixedsize=true, width=0.5, height=0.5, pos="4.7,-2.1!", label=""]
"Preamp C B" [shape=triangle, orientation=10, fixedsize=true, width=0.5, height=0.5, pos="5.4,-2.3!", label=""]
"ROADM C" -> "Booster C B"
"Preamp C B" -> "ROADM C"
"Booster C A" [shape=triangle, orientation=20, fixedsize=true, width=0.5, height=0.5, pos="2.6,-2.3!", label=""]
"Preamp C A" [shape=triangle, orientation=-30, fixedsize=true, width=0.5, height=0.5, pos="3.3,-2.1!", label=""]
"ROADM C" -> "Booster C A"
"Preamp C A" -> "ROADM C"
"Booster B A" [shape=triangle, orientation=90, fixedsize=true, width=0.5, height=0.5, pos="5,3.6!", label=""]
"Preamp B A" [shape=triangle, orientation=-90, fixedsize=true, width=0.5, height=0.5, pos="5,4.3!", label=""]
"ROADM B" -> "Booster B A"
"Preamp B A" -> "ROADM B"
"Booster B C" [shape=triangle, orientation=-180, fixedsize=true, width=0.5, height=0.5, pos="6.5,3.0!", label=""]
"Preamp B C" [shape=triangle, orientation=-20, fixedsize=true, width=0.5, height=0.5, pos="5.8,3.2!", label=""]
"ROADM B" -> "Booster B C"
"Preamp B C" -> "ROADM B"
"Inline A C 1" [shape=triangle, orientation=-166, fixedsize=true, width=0.5, pos="2.4,2.2!", label=" \N", color=red, fontcolor=red]
"Inline A C 2" [shape=triangle, orientation=-166, fixedsize=true, width=0.5, pos="2.6,1.2!", label=" \N", color=red, fontcolor=red]
"Inline A C 3" [shape=triangle, orientation=-166, fixedsize=true, width=0.5, pos="2.8,0.2!", label=" \N", color=red, fontcolor=red]
"Inline A C n" [shape=triangle, orientation=-166, fixedsize=true, width=0.5, pos="3.0,-1.1!", label=" \N", color=red, fontcolor=red]
"Booster A C" -> "Inline A C 1"
"Inline A C 1" -> "Inline A C 2"
"Inline A C 2" -> "Inline A C 3"
"Inline A C 3" -> "Inline A C n" [style=dotted]
"Inline A C n" -> "Preamp C A"
"Booster A B" -> "Preamp B A" [style=dotted]
"Booster C A" -> "Preamp A C" [style=dotted]
"Booster C B" -> "Preamp B C" [style=dotted]
"Booster B C" -> "Preamp C B" [style=dotted]
"Booster B A" -> "Preamp A B" [style=dotted]
}
In such networks, GNPy's autodesign features becomes very useful.
It is possible to connect ROADMs via "tentative links" which will be replaced by a sequence of actual fibers and specific amplifiers.
In other cases where the location of amplifier huts is already known, but the specific EDFA models have not yet been decided, one can put in amplifier placeholders and let GNPy assign the best amplifier.
.. _concepts-equipment:
The Equipment Library
=====================
In order to produce an accurate simulation, GNPy needs to know the physical properties of each entity which affects the optical signal.
Entries in the equipment library correspond to actual real-world, tangible entities.
Unlike a typical :abbr:`NMS (Network Management System)`, GNPy considers not just the active :abbr:`NEs (Network Elements)` such as amplifiers and :abbr:`ROADMs (Reconfigurable Optical Add/Drop Multiplexers)`, but also the passive ones, such as the optical fiber.
As the signal propagates through the network, the largest source of optical impairments is the noise introduced from amplifiers.
An accurate description of the :abbr:`EDFA (Erbium-Doped Fiber Amplifier)` and especially its noise characteristics is required.
GNPy describes this property in terms of the **Noise Figure (NF)** of an amplifier model as a function of its operating point.
The amplifiers compensate power losses induced on the signal in the optical fiber.
The linear losses, however, are just one phenomenon of a multitude of effects that affect the signals in a long fiber run.
While a more detailed description is available :ref:`in the literature<physical-model>`, for the purpose of the equipment library, the description of the *optical fiber* comprises its **linear attenutation coefficient**, a set of parameters for the **Raman effect**, optical **dispersion**, etc.
Signals are introduced into the network via *transponders*.
The set of parameters that are required describe the physical properties of each supported *mode* of the transponder, including its **symbol rate**, spectral **width**, etc.
In the junctions of the network, *ROADMs* are used for spectrum routing.
GNPy currently does not take into consideration the spectrum filtering penalties of the :abbr:`WSSes (Wavelength Selective Switches)`, but the equipment library nonetheless contains a list of required parameters, such as the attenuation options, so that the network can be properly simulated.
.. _concepts-nf-model:
Amplifier Noise Figure Models
-----------------------------
One of the key parameters of an amplifier is the method to use for computing the Noise Figure (NF).
GNPy supports several different noise models with varying level of accuracy.
When in doubt, contact your vendor's technical support and ask them to :ref:`contribute their equipment descriptions<extending-edfa>` to GNPy.
The most accurate noise models describe the resulting NF of an EDFA as a third-degree polynomial.
GNPy understands polynomials as a NF-yielding function of the :ref:`gain difference from the optimal gain<ext-nf-model-polynomial-NF>`, or as a function of the input power resulting in an incremental OSNR as used in :ref:`OpenROADM inline amplifiers<ext-nf-model-polynomial-OSNR-OpenROADM>` and :ref:`OpenROADM booster/preamps in the ROADMs<ext-nf-model-noise-mask-OpenROADM>`.
For scenarios where the vendor has not yet contributed an accurate EDFA NF description to GNPy, it is possible to approximate the characteristics via an operator-focused, min-max NF model.
.. _nf-model-min-max-NF:
Min-max NF
^^^^^^^^^^
This is an operator-focused model where performance is defined by the *minimal* and *maximal NF*.
These are especially suited to model a dual-coil EDFA with a VOA in between.
In these amplifiers, the minimal NF is achieved when the EDFA operates at its maximal (and usually optimal, in terms of flatness) gain.
The worst (maximal) NF applies when the EDFA operates at its minimal gain.
This model is suitable for use when the vendor has not provided a more accurate performance description of the EDFA.
Raman Approximation
^^^^^^^^^^^^^^^^^^^
While GNPy is fully Raman-aware, under certain scenarios it is useful to be able to run a simulation without an accurate Raman description.
For these purposes the :ref:`polynomial NF<ext-nf-model-polynomial-NF>` model with :math:`\text{a} = \text{b} = \text{c} = 0`, and :math:`\text{d} = NF` can be used.
.. _concepts-simulation:
Simulation
==========
When the network model has been instantiated and the physical properties and operational settings of the actual physical devices are known, GNPy can start simulating how the signal propagate through the optical fiber.
This set of input parameters include options such as the *spectrum allocation*, i.e., the number of channels and their spacing.
Various strategies for network optimization can be provided as well.

300
docs/conf.py Executable file → Normal file
View File

@@ -1,8 +1,8 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# gnpy documentation build configuration file, created by
# sphinx-quickstart on Tue Jul 9 22:26:36 2013.
# sphinx-quickstart on Mon Dec 18 14:41:01 2017.
#
# This file is execfile()d with the current directory set to its
# containing dir.
@@ -13,263 +13,193 @@
# All configuration values have a default; values that are commented out
# serve to show the default.
import sys
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
import os
import sys
# If extensions (or modules to document with autodoc) are in another
# directory, add these directories to sys.path here. If the directory is
# relative to the documentation root, use os.path.abspath to make it
# absolute, like shown here.
#sys.path.insert(0, os.path.abspath('.'))
# Get the project root dir, which is the parent dir of this
cwd = os.getcwd()
project_root = os.path.dirname(cwd)
sys.path.insert(0, os.path.abspath('../'))
# Insert the project root dir as the first element in the PYTHONPATH.
# This lets us ensure that the source package is imported, and that its
# version is used.
sys.path.insert(0, project_root)
import gnpy
# -- General configuration ---------------------------------------------
# -- General configuration ------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'
#
# needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode']
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = ['sphinx.ext.autodoc',
'sphinx.ext.mathjax',
'sphinx.ext.githubpages',
'sphinxcontrib.bibtex',
'sphinx.ext.graphviz',
'myst_parser',
'sphinx_rtd_theme',
]
myst_enable_extensions = [
"deflist",
"dollarmath",
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix of source filenames.
source_suffix = '.rst'
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
#
source_suffix = ['.rst', '.md']
# The encoding of source files.
#source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'gnpy'
copyright = u"2017, <TBD>"
# The version info for the project you're documenting, acts as replacement
# for |version| and |release|, also used in various other places throughout
# the built documents.
#
# The short X.Y version.
version = gnpy.__version__
# The full version, including alpha/beta/rc tags.
release = gnpy.__version__
project = 'gnpy'
copyright = '2018 - 2021, Telecom Infra Project - OOPT PSE Group'
author = 'Telecom Infra Project - OOPT PSE Group'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None
# There are two options for replacing |today|: either, you set today to
# some non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = 'en'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = ['_build']
# The reST default role (used for this markup: `text`) to use for all
# documents.
#default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False
# This patterns also effect to html_static_path and html_extra_path
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# If true, keep warnings as "system message" paragraphs in the built
# documents.
#keep_warnings = False
# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = False
# -- Options for HTML output -------------------------------------------
# -- Options for HTML output ----------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
html_theme = 'default'
#
html_theme = "sphinx_rtd_theme"
html_theme_options = {
'logo': 'images/GNPy-logo.png',
'logo_name': False,
'prev_next_buttons_location': 'bottom',
# Toc options
'collapse_navigation': True,
'sticky_navigation': True,
'navigation_depth': 4,
'includehidden': True,
'titles_only': False
}
html_theme_options = {
'navigation_depth': 4,
}
html_favicon = 'images/GNPy-logo.png'
# Theme options are theme-specific and customize the look and feel of a
# theme further. For a list of options available for each theme, see the
html_logo = 'images/GNPy-logo.png'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}
#
# html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
#html_title = None
# A shorter title for the navigation bar. Default is the same as
# html_title.
#html_short_title = None
# The name of an image file (relative to this directory) to place at the
# top of the sidebar.
#html_logo = None
# The name of an image file (within the static path) to use as favicon
# of the docs. This file should be a Windows icon file (.ico) being
# 16x16 or 32x32 pixels large.
#html_favicon = None
# Add any paths that contain custom static files (such as style sheets)
# here, relative to this directory. They are copied after the builtin
# static files, so a file named "default.css" will overwrite the builtin
# "default.css".
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
html_css_files = [
'custom.css', # Inclure votre fichier CSS personnalisé
]
# If not '', a 'Last updated on:' timestamp is inserted at every page
# bottom, using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names
# Custom sidebar templates, must be a dictionary that maps document names
# to template names.
#html_additional_pages = {}
#
# This is required for the alabaster theme
# refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars
html_sidebars = {
'**': [
'about.html',
'navigation.html',
'relations.html', # needs 'show_related': True theme option to display
'searchbox.html',
'donate.html',
]
}
# If false, no module index is generated.
#html_domain_indices = True
html_secnum_depth = 4
# If false, no index is generated.
#html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer.
# Default is True.
#html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer.
# Default is True.
#html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages
# will contain a <link> tag referring to it. The value of this option
# must be the base URL from which the finished HTML is served.
#html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None
# -- Options for HTMLHelp output ------------------------------------------
# Output file base name for HTML help builder.
htmlhelp_basename = 'gnpydoc'
# -- Options for LaTeX output ------------------------------------------
# -- Options for LaTeX output ---------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper',
#
# 'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#'pointsize': '10pt',
#
# 'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#'preamble': '',
#
# 'preamble': '',
# Latex figure (float) alignment
#
# 'figure_align': 'htbp',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass
# [howto/manual]).
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
('index', 'gnpy.tex',
u'gnpy Documentation',
u'<TBD>', 'manual'),
(master_doc, 'gnpy.tex', 'gnpy Documentation',
'Telecom Infra Project - OOPT PSE Group', 'manual'),
]
# The name of an image file (relative to this directory) to place at
# the top of the title page.
#latex_logo = None
# For "manual" documents, if this is true, then toplevel headings
# are parts, not chapters.
#latex_use_parts = False
# If true, show page references after internal links.
#latex_show_pagerefs = False
# If true, show URL addresses after external links.
#latex_show_urls = False
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# If false, no module index is generated.
#latex_domain_indices = True
# -- Options for manual page output ------------------------------------
# -- Options for manual page output ---------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
('index', 'gnpy',
u'gnpy Documentation',
[u'<TBD>'], 1)
(master_doc, 'gnpy', 'gnpy Documentation',
[author], 1)
]
# If true, show URL addresses after external links.
#man_show_urls = False
# -- Options for Texinfo output ----------------------------------------
# -- Options for Texinfo output -------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
('index', 'gnpy',
u'gnpy Documentation',
u'<TBD>',
'gnpy',
'One line description of project.',
(master_doc, 'gnpy', 'gnpy Documentation',
author, 'gnpy', 'One line description of project.',
'Miscellaneous'),
]
# Documents to append as an appendix to all manuals.
#texinfo_appendices = []
autodoc_default_options = {
'members': True,
'undoc-members': True,
'private-members': True,
'show-inheritance': True,
}
# If false, no module index is generated.
#texinfo_domain_indices = True
graphviz_output_format = 'svg'
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#texinfo_show_urls = 'footnote'
# If true, do not generate a @detailmenu in the "Top" node's menu.
#texinfo_no_detailmenu = False
bibtex_bibfiles = ['biblio.bib']

View File

@@ -1 +0,0 @@
.. include:: ../CONTRIBUTING.rst

269
docs/excel.rst Normal file
View File

@@ -0,0 +1,269 @@
.. _excel:
*****************************
Excel (XLS, XLSX) input files
*****************************
``gnpy-transmission-example`` gives the possibility to use an excel input file instead of a json file. The program then will generate the corresponding json file for you.
The file named 'meshTopologyExampleV2.xls' is an example.
In order to work the excel file MUST contain at least 2 sheets:
- `Nodes`
- `Links`
(In progress) The File MAY contain additional sheets:
- `Eqpt`
- `Service`
- `Roadms`
.. _excel-nodes-sheet:
`Nodes` sheet
=============
`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
- **City** is used for the name of a node of the graph. It accepts letters, numbers,underscore,dash, blank... (not exhaustive). The user may want to avoid commas for future CSV exports.
**City name MUST be unique**
- **Type** is not mandatory.
- If not filled, it will be interpreted as an 'ILA' site if node degree is 2 and as a ROADM otherwise.
- If filled, it can take "ROADM", "FUSED" or "ILA" values. If another string is used, it will be considered as not filled. FUSED means that ingress and egress spans will be fused together.
- *State*, *Country*, *Region* are not mandatory.
"Region" is a holdover from the CORONET topology reference file `CORONET_Global_Topology.xlsx <gnpy/example-data/CORONET_Global_Topology.xlsx>`_. CORONET separates its network into geographical regions (Europe, Asia, Continental US.) This information is not used by gnpy.
- *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**
.. _excel-links-sheet:
Links sheet
===========
Links sheet must contain sixteen columns::
<-- east cable from a to z --> <-- west from z to a -->
NodeA ; NodeZ ; Distance km ; Fiber type ; Lineic att ; Con_in ; Con_out ; PMD ; Cable Id ; Distance km ; Fiber type ; Lineic att ; Con_in ; Con_out ; PMD ; Cable Id
`Links` sheet MUST contain all links between nodes defined in Nodes sheet.
Each line represents a 'bidir link' between two nodes. The two directions are represented on a single line with "east cable from a to z" fields and "west from z to a" fields. Values for 'a to z' may be different from values from 'z to a'.
Since both direction of a bidir 'a-z' link are described on the same line (east and west), 'z to a' direction MUST NOT be repeated in a different line. If repeated, it will generate another parrallel bidir link between the same end nodes.
Parameters for "east cable from a to z" and "west from z to a" are detailed in 2x7 columns. If not filled, "west from z to a" is copied from "east cable from a to z".
For example, a line filled with::
node6 ; node3 ; 80 ; SSMF ; 0.2 ; 0.5 ; 0.5 ; 0.1 ; cableB ; ; ; 0.21 ; 0.2 ; ; ;
will generate a unidir fiber span from node6 to node3 with::
[node6 node3 80 SSMF 0.2 0.5 0.5 0.1 cableB]
and a fiber span from node3 to node6::
[node6 node3 80 SSMF 0.21 0.2 0.5 0.1 cableB] attributes.
- **NodeA** and **NodeZ** are Mandatory.
They are the two endpoints of the link. They MUST contain a node name from the **City** names listed in Nodes sheet.
- **Distance km** is not mandatory.
It is the link length.
- If filled it MUST contain numbers. If empty it is replaced by a default "80" km value.
- If value is below 150 km, it is considered as a single (bidirectional) fiber span.
- If value is over 150 km or if the loss is greater than 28 dB, the autodesign program
will automatically split the span with "_1","_2", ... trailing strings in names.
Splitting threshold can be tuned in ["Span"]["max_length"] and ["Span"]["max_loss"] in
equipment library.
- **Fiber type** is not mandatory.
If filled it must contain types listed in `eqpt_config.json <gnpy/example-data/eqpt_config.json>`_ in "Fiber" list "type_variety".
If not filled it takes "SSMF" as default value.
- **Lineic att** is not mandatory.
It is the lineic attenuation expressed in dB/km.
If filled it must contain positive numbers.
If not filled it takes "0.2" dB/km value
- **Con_in**, **Con_out** are not mandatory.
They are the connector loss in dB at ingress and egress of the fiber spans.
If filled they must contain positive numbers.
If not filled they take "0.5" dB default value.
- **PMD** is not mandatory.
It is the PMD value of the link in ps.
If filled they must contain positive numbers.
If not filled, it takes "0.1" ps value.
- **Cable Id** is not mandatory.
If filled they must contain strings with the same constraint as "City" names. Its value is used to differenate links having the same end points. In this case different Id should be used. Cable Ids are not meant to be unique in general.
.. _excel-equipment-sheet:
Eqpt sheet
==========
The equipment sheet (named "Eqpt") is optional.
If provided, it specifies types of boosters and preamplifiers for all ROADM degrees of all ROADM nodes, and for all ILA nodes.
This sheet contains twelve columns::
<-- east cable from a to z --> <-- west from z to a -->
Node A ; Node Z ; amp type ; att_in ; amp gain ; tilt ; att_out ; delta_p ; amp type ; att_in ; amp gain ; tilt ; att_out ; delta_p
If the sheet is present, it MUST have as many lines as there are egress directions of ROADMs defined in Links Sheet, and all ILAs.
For example, consider the following list of links (A, B and C being a ROADM and amp# ILAs):
::
A - amp1
amp1 - amp2
Amp2 - B
A - amp3
amp3 - C
then Eqpt sheet should contain:
- one line for each ILAs: amp1, amp2, amp3
- one line for each one-degree ROADM (B and C in this example)
- two lines for each two-degree ROADM (just the ROADM A)
::
A - amp1
amp1 - amp2
Amp2 - B
A - amp3
amp3 - C
B - amp2
C - amp3
In case you already have filled Nodes and Links sheets `create_eqpt_sheet.py <gnpy/example-data/create_eqpt_sheet.py>`_ can be used to automatically create a template for the mandatory entries of the list.
.. code-block:: shell
$ cd $(gnpy-example-data)
$ python create_eqpt_sheet.py meshTopologyExampleV2.xls
This generates a text file meshTopologyExampleV2_eqt_sheet.txt whose content can be directly copied into the Eqt sheet of the excel file. The user then can fill the values in the rest of the columns.
- **Node A** is mandatory. It is the name of the node (as listed in Nodes sheet).
If Node A is a 'ROADM' (Type attribute in sheet Node), its number of occurence must be equal to its degree.
If Node A is an 'ILA' it should appear only once.
- **Node Z** is mandatory. It is the egress direction from the *Node A* site. Multiple Links between the same Node A and NodeZ is not supported.
- **amp type** is not mandatory.
If filled it must contain types listed in the equipment librairie like in the example `eqpt_config.json <gnpy/example-data/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.
If filled, it must contain positive numbers.
- **att_in** and **att_out** are not mandatory. They are the value of the attenuator at input and output of amplifier (in dB).
If filled they must contain positive numbers.
- **tilt**, in dB, is not mandatory. It is the target gain tilt over the full amplfifier bandwidth and is defined with regard to wavelength, i.e. negative tilt means lower gain
for higher wavelengths (lower frequencies). If not filled, the default value is 0.
- **delta_p**, in dB, is not mandatory. If filled it is used to set the output target power per channel at the output of the amplifier, if power_mode is True. The output power is then set to power_dbm + delta_power.
.. _excel-roadms-sheet:
Roadms sheet
============
The ROADM sheet (named "Roadms") is optional.
If provided, it can be used to specify:
- per channel power target on a specific ROADM degree (*per_degree_pch_out_db*),
- ROADM type variety,
- impairment ID (identifier) on a particular ROADM path (from degree - to degree).
This sheet contains six columns:
Node A ; Node Z ; per degree target power (dBm) ; type_variety ; from degrees ; from degree to degree impairment id
- **Node A** is mandatory. Name of the ROADM node (as listed in Nodes sheet).
Must be a 'ROADM' (Type attribute in Node sheet), its number of occurence may be equal to its degree.
- **Node Z** is mandatory. Egress direction from the *Node A* ROADM site. Multiple Links between the same Node A
and NodeZ is not supported.
- **per degree target power (dBm)** (optional).
If filled it must contain a value in dBm corresponding to :ref:`per_degree_pch_out_db<roadm_json_instance>` on the **Node Z** degree.
Defaults to equipment library value if not filled.
- **type_variety** (optional). Must be the same for all ROADM entries if filled,
and defined in the :ref:`equipment library<roadm>`. Defaults to 'default' if not filled.
- **from degrees** (optional): List of Node names separated by ' | '. Names must be present in Node sheet.
Together with Node Z, they define a list of internal path in ROADM for which the impairment ID applies
- **from degree to degree impairment id** (optional):List of impairment IDs separated by ' | '. Must be filled
if **from degrees** is defined.
The impairment ID must be defined in the equipment library and be of "express" type.
(in progress)
.. _excel-service-sheet:
Service sheet
=============
Service sheet is optional. It lists the services for which path and feasibility must be computed with ``gnpy-path-request``.
Service sheet must contain 11 columns::
route id ; Source ; Destination ; TRX type ; Mode ; System: spacing ; System: input power (dBm) ; System: nb of channels ; routing: disjoint from ; routing: path ; routing: is loose?
- **route id** is mandatory. It must be unique. It is the identifier of the request. It can be an integer or a string (do not use blank or dash or coma)
- **Source** is mandatory. It is the name of the source node (as listed in Nodes sheet). Source MUST be a ROADM node. (TODO: relax this and accept trx entries)
- **Destination** is mandatory. It is the name of the destination node (as listed in Nodes sheet). Source MUST be a ROADM node. (TODO: relax this and accept trx entries)
- **TRX type** is mandatory. It is the variety type of the transceiver to be used for the propagation simulation. These modes MUST be defined in the equipment library. The format of the mode is used as the name of the mode. (TODO: maybe add another mode id on Transceiver library ?). In particular the mode selection defines the channel baudrate to be used for the propagation simulation.
- **mode** is optional. If not specified, the program will search for the mode of the defined transponder with the highest baudrate fitting within the spacing value.
- **System: spacing** is mandatory. Spacing is the channel spacing defined in GHz difined for the feasibility propagation simulation, assuming system full load.
- **System: input power (dBm) ; System: nb of channels** are optional input defining the system parameters for the propagation simulation.
- input power is the channel optical input power in dBm
- nb of channels is the number of channels to be used for the simulation.
- **routing: disjoint from ; routing: path ; routing: is loose?** are optional.
- disjoint from: identifies the requests from which this request must be disjoint. If filled it must contain request ids separated by ' | '
- path: is the set of ROADM nodes that must be used by the path. It must contain the list of ROADM names that the path must cross. TODO : only ROADM nodes are accepted in this release. Relax this with any type of nodes. If filled it must contain ROADM ids separated by ' | '. Exact names are required.
- is loose? 'no' value means that the list of nodes should be strictly followed, while any other value means that the constraint may be relaxed if the node is not reachable.
- **path bandwidth** is mandatory. It is the amount of capacity required between source and destination in Gbit/s. Value should be positive (non zero). It is used to compute the amount of required spectrum for the service.

173
docs/extending.rst Normal file
View File

@@ -0,0 +1,173 @@
.. _extending:
****************************************
Extending GNPy with vendor-specific data
****************************************
GNPy ships with an :ref:`equipment library<concepts-equipment>` containing machine-readable datasheets of networking equipment.
Vendors who are willing to contribute descriptions of their supported products are encouraged to `submit a patch <https://review.gerrithub.io/Documentation/intro-gerrit-walkthrough-github.html>`__ -- or just :ref:`get in touch with us directly<contributing>`.
This chapter discusses option for modeling performance of :ref:`EDFA amplifiers<extending-edfa>`, :ref:`Raman amplifiers<extending-raman>`, :ref:`transponders<extending-transponder>` and :ref:`ROADMs<extending-roadm>`.
.. _extending-edfa:
EDFAs
=====
An accurate description of the :abbr:`EDFA (Erbium-Doped Fiber Amplifier)` and especially its noise characteristics is required.
GNPy describes this property in terms of the **Noise Figure (NF)** of an amplifier model as a function of its operating point.
GNPy supports several different :ref:`noise models<concepts-nf-model>`, and vendors are encouraged to pick one which describes performance of their equipment most accurately.
.. _ext-nf-model-polynomial-NF:
Polynomial NF
-------------
This model computes the NF as a function of the difference between the optimal gain and the current gain.
The NF is expressed as a third-degree polynomial:
.. math::
f(x) &= \text{a}x^3 + \text{b}x^2 + \text{c}x + \text{d}
\text{NF} &= f(G - G_\text{max})
This model can be also used for fixed-gain fixed-NF amplifiers.
In that case, use:
.. math::
a = b = c &= 0
d &= \text{NF}
.. _ext-nf-model-polynomial-OSNR-OpenROADM:
Polynomial OSNR (OpenROADM-style for inline amplifier)
------------------------------------------------------
This model is useful for amplifiers compliant to the OpenROADM specification for ILA (an in-line amplifier).
The amplifier performance is evaluated via its incremental OSNR, which is a function of the input power.
.. math::
\text{OSNR}_\text{inc}(P_\text{in}) = \text{a}P_\text{in}^3 + \text{b}P_\text{in}^2 + \text{c}P_\text{in} + \text{d}
.. _ext-nf-model-noise-mask-OpenROADM:
Noise mask (OpenROADM-style for combined preamp and booster)
------------------------------------------------------------
Unlike GNPy which simluates the preamplifier and the booster separately as two amplifiers for best accuracy, the OpenROADM specification mandates a certain performance level for a combination of these two amplifiers.
For the express path, the effective noise mask comprises the preamplifier and the booster.
When terminating a channel, the same effective noise mask is mandated for a combination of the preamplifier and the drop stage.
GNPy emulates this specification via two special NF models:
- The ``openroadm_preamp`` NF model for preamplifiers.
This NF model provides all of the linear impairments to the signal, including those which are incured by the booster in a real network.
- The ``openroadm_booster`` NF model is a special "zero noise" faux amplifier in place of the booster.
.. _ext-nf-model-min-max-NF:
Min-max NF
----------
When the vendor prefers not to share the amplifier description in full detail, GNPy also supports describing the NF characteristics via the *minimal* and *maximal NF*.
This approximates a more accurate polynomial description reasonably well for some models of a dual-coil EDFA with a VOA in between.
In these amplifiers, the minimal NF is achieved when the EDFA operates at its maximal (and usually optimal, in terms of flatness) gain.
The worst (maximal) NF applies when the EDFA operates at the minimal gain.
.. _ext-nf-model-dual-stage-amplifier:
Dual-stage
----------
Dual-stage amplifier combines two distinct amplifiers.
Vendors which provide an accurate description of their preamp and booster stages separately can use the dual-stage model for an aggregate description of the whole amplifier.
.. _ext-nf-model-advanced:
Advanced Specification
----------------------
The amplifier performance can be further described in terms of gain ripple, NF ripple, and the dynamic gain tilt.
When provided, the amplifier characteristic is fine-tuned as a function of carrier frequency. Note that in this advanced
specification tilt is defined vs frequency while tilt_target specified in EDFA instances is defined vs wavelength.
.. _extending-raman:
Raman Amplifiers
================
An accurate simulation of Raman amplification requires knowledge of:
* the *power* and *wavelength* of all Raman pumping lasers,
* the *direction*, whether it is co-propagating or counter-propagating,
* the Raman efficiency of the fiber,
* the fiber temperature.
Under certain scenarios it is useful to be able to run a simulation without an accurate Raman description.
For these purposes, it is possible to approximate a Raman amplifier via a fixed-gain EDFA with the :ref:`polynomial NF<ext-nf-model-polynomial-NF>` model using :math:`\text{a} = \text{b} = \text{c} = 0`, and a desired effective :math:`\text{d} = NF`.
This is also useful to quickly approximate a hybrid EDFA+Raman amplifier.
.. _extending-transponder:
Transponders
============
Since transponders are usually capable of operating in a variety of modes, these are described separately.
A *mode* usually refers to a particular performance point that is defined by a combination of the symbol rate, modulation format, and :abbr:`FEC (Forward Error Correction)`.
The following data are required for each mode:
``bit_rate``
Data bit rate, in :math:`\text{bits}\times s^{-1}`.
``baud_rate``
Symbol modulation rate, in :math:`\text{baud}`.
``OSNR``
Minimal required OSNR for the receiver. In :math:`\text{dB}`
``tx-osnr``
Initial OSNR at the transmitter's output. In :math:`\text{dB}`
``min-spacing``
Minimal grid spacing, i.e., an effective channel spectral bandwidth.
In :math:`\text{Hz}`.
``roll-off``
Roll-off parameter (:math:`\beta`) of the TX pulse shaping filter.
This assumes a raised-cosine filter.
``rx-power-min`` and ``rx-power-max``
(work in progress) The allowed range of power at the receiver.
In :math:`\text{dBm}`.
``penalties``
Impairments such as Chromatic Dispersion (CD), Polarization Mode Dispersion (PMD), and Polarization Dispersion Loss (PDL)
result in penalties at the receiver. The receiver's ability to handle these impairments can be defined for each mode as
a list of {impairment: in defined units, 'penalty_value' in dB} (see `transceiver section here <json.rst#_transceiver>`).
Maximum allowed CD, maximum allowed PMD, and maximum allowed PDL should be listed there with corresponding penalties.
Impairments experienced during propagation are linearly interpolated between given points to obtain the corresponding penalty.
The accumulated penalties are subtracted from the path GSNR before comparing with the minimum required OSNR.
Impairments: PMD in :math:`\text{ps}`, CD in :math:`\text{ps/nm}`, PDL in :math:`\text{dB}`, penalty_value in :math:`\text{dB}`
GNPy does not directly track the FEC performance, so the type of chosen FEC is likely indicated in the *name* of the selected transponder mode alone.
.. _extending-roadm:
ROADMs
======
In a :abbr:`ROADM (Reconfigurable Add/Drop Multiplexer)`, GNPy simulates the impairments of the preamplifiers and boosters of line degrees :ref:`separately<topo-roadm-preamp-booster>`.
The set of parameters for each ROADM model therefore includes:
``add-drop-osnr``
OSNR penalty introduced by the Add and Drop stages of this ROADM type.
``target-channel-out-power``
Per-channel target TX power towards the egress amplifier.
Within GNPy, a ROADM is expected to attenuate any signal that enters the ROADM node to this level.
This can be overridden on a per-link in the network topology.
Targets can be set using power or power spectral density (see `roadm section here <json.rst#__roadm>`)
``pmd``
Polarization mode dispersion (PMD) penalty of the express path.
In :math:`\text{ps}`.
Provisions are in place to define the list of all allowed booster and preamplifier types.
This is useful for specifying constraints on what amplifier modules fit into ROADM chassis, and when using fully disaggregated ROADM topologies as well.

13
docs/gnpy-api-core.rst Normal file
View File

@@ -0,0 +1,13 @@
``gnpy.core``
-------------
.. automodule:: gnpy.core
.. automodule:: gnpy.core.ansi_escapes
.. automodule:: gnpy.core.elements
.. automodule:: gnpy.core.equipment
.. automodule:: gnpy.core.exceptions
.. automodule:: gnpy.core.info
.. automodule:: gnpy.core.network
.. automodule:: gnpy.core.parameters
.. automodule:: gnpy.core.science_utils
.. automodule:: gnpy.core.utils

10
docs/gnpy-api-tools.rst Normal file
View File

@@ -0,0 +1,10 @@
``gnpy.tools``
--------------
.. automodule:: gnpy.tools
.. automodule:: gnpy.tools.cli_examples
.. automodule:: gnpy.tools.convert
.. automodule:: gnpy.tools.json_io
.. automodule:: gnpy.tools.plots
.. automodule:: gnpy.tools.service_sheet
.. automodule:: gnpy.tools.worker_utils

View File

@@ -0,0 +1,6 @@
``gnpy.topology``
-----------------
.. automodule:: gnpy.topology
.. automodule:: gnpy.topology.request
.. automodule:: gnpy.topology.spectrum_assignment

14
docs/gnpy-api.rst Normal file
View File

@@ -0,0 +1,14 @@
***************************
API Reference Documentation
***************************
GNPy package
============
.. automodule:: gnpy
.. toctree::
gnpy-api-core
gnpy-api-topology
gnpy-api-tools

View File

@@ -1 +0,0 @@
.. include:: ../HISTORY.rst

Binary file not shown.

After

Width:  |  Height:  |  Size: 288 KiB

BIN
docs/images/GNPy-banner.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 518 KiB

BIN
docs/images/GNPy-logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 478 KiB

View File

@@ -1,22 +1,36 @@
Welcome to gnpy's documentation!
======================================
************************************
GNPy: Optical Route Planning Library
************************************
Contents:
`GNPy <http://github.com/telecominfraproject/gnpy>`_ is an open-source,
community-developed library for building route planning and optimization tools
in real-world mesh optical networks. It is based on the Gaussian Noise Model.
.. toctree::
:maxdepth: 2
:maxdepth: 4
:caption: Contents
readme
installation
usage
modules
contributing
authors
history
intro
concepts
install
cli_options
amplifier_models_description
json
json_instance_examples
excel
extending
about-project
model
gnpy-api
release-notes
publications
genindex
modindex
Indices and tables
==================
------------------
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

112
docs/install.rst Normal file
View File

@@ -0,0 +1,112 @@
***************
Installing GNPy
***************
There are several methods on how to obtain GNPy.
The easiest option for a non-developer is probably going via our :ref:`Docker images<install-docker>`.
Developers are encouraged to install the :ref:`Python package in the same way as any other Python package<install-pip>`.
Note that this needs a :ref:`working installation of Python<install-python>`, for example :ref:`via Anaconda<install-anaconda>`.
.. _install-docker:
Using prebuilt Docker images
============================
Our `Docker images <https://hub.docker.com/r/telecominfraproject/oopt-gnpy>`_ contain everything needed to run all examples from this guide.
Docker transparently fetches the image over the network upon first use.
On Linux and Mac, run:
.. code-block:: shell-session
$ docker run -it --rm --volume $(pwd):/shared telecominfraproject/oopt-gnpy
root@bea050f186f7:/shared/example-data#
On Windows, launch from Powershell as:
.. code-block:: console
PS C:\> docker run -it --rm --volume ${PWD}:/shared telecominfraproject/oopt-gnpy
root@89784e577d44:/shared/example-data#
In both cases, a directory named ``example-data/`` will appear in your current working directory.
GNPy automaticallly populates it with example files from the current release.
Remove that directory if you want to start from scratch.
.. _install-python:
Using Python on your computer
=============================
**Note**: `gnpy` supports Python 3 only. Python 2 is not supported.
`gnpy` requires Python ≥3.8
**Note**: the `gnpy` maintainers strongly recommend the use of Anaconda for
managing dependencies.
It is recommended that you use a "virtual environment" when installing `gnpy`.
Do not install `gnpy` on your system Python.
.. _install-anaconda:
We recommend the use of the `Anaconda Python distribution <https://www.anaconda.com/download>`_ which comes with many scientific computing
dependencies pre-installed. Anaconda creates a base "virtual environment" for
you automatically. You can also create and manage your ``conda`` "virtual
environments" yourself (see:
https://conda.io/docs/user-guide/tasks/manage-environments.html)
To activate your Anaconda virtual environment, you may need to do the
following:
.. code-block:: shell-session
$ source /path/to/anaconda/bin/activate # activate Anaconda base environment
(base) $ # note the change to the prompt
You can check which Anaconda environment you are using with:
.. code-block:: shell-session
(base) $ conda env list # list all environments
# conda environments:
#
base * /src/install/anaconda3
(base) $ echo $CONDA_DEFAULT_ENV # show default environment
base
You can check your version of Python with the following. If you are using
Anaconda's Python 3, you should see similar output as below. Your results may
be slightly different depending on your Anaconda installation path and the
exact version of Python you are using.
.. code-block:: shell-session
$ which python # check which Python executable is used
/path/to/anaconda/bin/python
$ python -V # check your Python version
Python 3.8.0 :: Anaconda, Inc.
.. _install-pip:
Installing the Python package
-----------------------------
From within your Anaconda Python 3 environment, you can clone the master branch
of the `gnpy` repo and install it with:
.. code-block:: shell-session
$ git clone https://github.com/Telecominfraproject/oopt-gnpy # clone the repo
$ cd oopt-gnpy
$ pip install --editable . # note the trailing dot
To test that `gnpy` was successfully installed, you can run this command. If it
executes without a ``ModuleNotFoundError``, you have successfully installed
`gnpy`.
.. code-block:: shell-session
$ python -c 'import gnpy' # attempt to import gnpy
$ pytest # run tests

View File

@@ -1,51 +0,0 @@
.. highlight:: shell
============
Installation
============
Stable release
--------------
To install gnpy, run this command in your terminal:
.. code-block:: console
$ pip install gnpy
This is the preferred method to install gnpy, as it will always install the most recent stable release.
If you don't have `pip`_ installed, this `Python installation guide`_ can guide
you through the process.
.. _pip: https://pip.pypa.io
.. _Python installation guide: http://docs.python-guide.org/en/latest/starting/installation/
From sources
------------
The sources for gnpy can be downloaded from the `Github repo`_.
You can either clone the public repository:
.. code-block:: console
$ git clone git://github.com/<TBD>/gnpy
Or download the `tarball`_:
.. code-block:: console
$ curl -OL https://github.com/<TBD>/gnpy/tarball/master
Once you have a copy of the source, you can install it with:
.. code-block:: console
$ python setup.py install
.. _Github repo: https://github.com/<TBD>/gnpy
.. _tarball: https://github.com/<TBD>/gnpy/tarball/master

97
docs/intro.rst Normal file
View File

@@ -0,0 +1,97 @@
.. _intro:
************
Introduction
************
``gnpy`` is a library for building route planning and optimization tools.
It ships with a number of example programs. Release versions will ship with
fully-functional programs.
**Note**: *If you are a network operator or involved in route planning and
optimization for your organization, please contact project maintainers
esther Le Rouzic <esther.lerouzic@orange.com>, Andrea D'Amico <adamico@nec-labs.com>.
gnpy is looking for users with
specific, delineated use cases to drive requirements for future
development.*
This example demonstrates how GNPy can be used to check the expected SNR at the end of the line by varying the channel input power,
or to run a planning script to check SNR of several services:
.. image:: images/gnpy-transmission-example.svg
:width: 100%
:align: left
:alt: Running a simple simulation example
By default, the gnpy-transmission-example script operates on a single span network defined in
`gnpy/example-data/edfa_example_network.json <https://github.com/Telecominfraproject/oopt-gnpy/blob/master/gnpy/example-data/edfa_example_network.json>`_
You can specify a different network at the command line as follows. For
example, to use the CORONET Global network defined in
`gnpy/example-data/CORONET_Global_Topology.json <https://github.com/Telecominfraproject/oopt-gnpy/blob/master/gnpy/example-data/CORONET_Global_Topology.json>`_:
.. code-block:: shell-session
$ gnpy-transmission-example $(gnpy-example-data)/CORONET_Global_Topology.json
It is also possible to use an Excel file input (for example
`gnpy/example-data/CORONET_Global_Topology.xls <https://github.com/Telecominfraproject/oopt-gnpy/blob/master/gnpy/example-data/CORONET_Global_Topology.xls>`_).
The Excel file will be processed into a JSON file with the same prefix.
Further details about the Excel data structure are available `in the documentation <excel.rst>`__.
The main transmission example will calculate the average signal OSNR and SNR
across network elements (transceiver, ROADMs, fibers, and amplifiers)
between two transceivers selected by the user. Additional details are provided by doing ``gnpy-transmission-example -h``. (By default, for the CORONET Global
network, it will show the transmission of spectral information between Abilene and Albany)
This script calculates the average signal OSNR = |OSNR| and SNR = |SNR|.
.. |OSNR| replace:: P\ :sub:`ch`\ /P\ :sub:`ase`
.. |SNR| replace:: P\ :sub:`ch`\ /(P\ :sub:`nli`\ +\ P\ :sub:`ase`)
|Pase| is the amplified spontaneous emission noise, and |Pnli| the non-linear
interference noise.
.. |Pase| replace:: P\ :sub:`ase`
.. |Pnli| replace:: P\ :sub:`nli`
Further Instructions for Use
============================
Simulations are driven by a set of `JSON <json.rst>`__ or `XLS <excel.rst>`__ files.
The ``gnpy-transmission-example`` script propagates a spectrum of channels at 32 Gbaud, 50 GHz spacing and 0 dBm/channel.
Launch power in fiber spans can be overridden by using the ``--power`` argument.
Spectrum information is not yet parametrized but can be modified directly in the ``eqpt_config.json`` (via the ``SpectralInformation`` -SI- structure) to accommodate any baud rate or spacing.
The number of channel is computed based on ``spacing`` and ``f_min``, ``f_max`` values.
An experimental support for Raman amplification is available:
.. code-block:: shell-session
$ gnpy-transmission-example \
$(gnpy-example-data)/raman_edfa_example_network.json \
--sim $(gnpy-example-data)/sim_params.json --show-channels
Configuration of Raman pumps (their frequencies, power and pumping direction) is done via the `RamanFiber element in the network topology <https://github.com/Telecominfraproject/oopt-gnpy/blob/master/gnpy/example-data/raman_edfa_example_network.json>`_.
General numeric parameters for simulation control are provided in the `gnpy/example-data/sim_params.json <https://github.com/Telecominfraproject/oopt-gnpy/blob/master/gnpy/example-data/sim_params.json>`_.
Use ``gnpy-path-request`` to request several paths at once:
.. code-block:: shell-session
$ cd $(gnpy-example-data)
$ gnpy-path-request -o output_file.json \
meshTopologyExampleV2.xls meshTopologyExampleV2_services.json
This program operates on a network topology (`JSON <json.rst>`__ or `Excel <excel.rst>`__ format), processing the list of service requests (JSON or XLS again).
The service requests and reply formats are based on the `draft-ietf-teas-yang-path-computation-01 <https://tools.ietf.org/html/draft-ietf-teas-yang-path-computation-01>`__ with custom extensions (e.g., for transponder modes).
An example of the JSON input is provided in file `service-template.json`, while results are shown in `path_result_template.json`.
Important note: ``gnpy-path-request`` is not a network dimensionning tool: each service does not reserve spectrum, or occupy ressources such as transponders. It only computes path feasibility assuming the spectrum (between defined frequencies) is loaded with "nb of channels" spaced by "spacing" values as specified in the system parameters input in the service file, each cannel having the same characteristics in terms of baudrate, format,... as the service transponder. The transceiver element acts as a "logical starting/stopping point" for the spectral information propagation. At that point it is not meant to represent the capacity of add drop ports.
As a result transponder type is not part of the network info. it is related to the list of services requests.
The current version includes a spectrum assigment features that enables to compute a candidate spectrum assignment for each service based on a first fit policy. Spectrum is assigned based on service specified spacing value, path_bandwidth value and selected mode for the transceiver. This spectrum assignment includes a basic capacity planning capability so that the spectrum resource is limited by the frequency min and max values defined for the links. If the requested services reach the link spectrum capacity, additional services feasibility are computed but marked as blocked due to spectrum reason.
OpenROADM networks can be simulated via ``gnpy/example-data/eqpt_config_openroadm_*.json`` -- see ``gnpy/example-data/Sweden_OpenROADM*_example_network.json`` as an example.

1604
docs/json.rst Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,242 +1,36 @@
@ECHO OFF
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set BUILDDIR=_build
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
set I18NSPHINXOPTS=%SPHINXOPTS% .
if NOT "%PAPER%" == "" (
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
)
if "%1" == "" goto help
if "%1" == "help" (
:help
echo.Please use `make ^<target^>` where ^<target^> is one of
echo. html to make standalone HTML files
echo. dirhtml to make HTML files named index.html in directories
echo. singlehtml to make a single large HTML file
echo. pickle to make pickle files
echo. json to make JSON files
echo. htmlhelp to make HTML files and a HTML help project
echo. qthelp to make HTML files and a qthelp project
echo. devhelp to make HTML files and a Devhelp project
echo. epub to make an epub
echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
echo. text to make text files
echo. man to make manual pages
echo. texinfo to make Texinfo files
echo. gettext to make PO message catalogs
echo. changes to make an overview over all changed/added/deprecated items
echo. xml to make Docutils-native XML files
echo. pseudoxml to make pseudoxml-XML files for display purposes
echo. linkcheck to check all external links for integrity
echo. doctest to run all doctests embedded in the documentation if enabled
goto end
)
if "%1" == "clean" (
for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
del /q /s %BUILDDIR%\*
goto end
)
%SPHINXBUILD% 2> nul
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.http://sphinx-doc.org/
exit /b 1
)
if "%1" == "html" (
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/html.
goto end
)
if "%1" == "dirhtml" (
%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
goto end
)
if "%1" == "singlehtml" (
%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
goto end
)
if "%1" == "pickle" (
%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the pickle files.
goto end
)
if "%1" == "json" (
%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the JSON files.
goto end
)
if "%1" == "htmlhelp" (
%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run HTML Help Workshop with the ^
.hhp project file in %BUILDDIR%/htmlhelp.
goto end
)
if "%1" == "qthelp" (
%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run "qcollectiongenerator" with the ^
.qhcp project file in %BUILDDIR%/qthelp, like this:
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\gnpy.qhcp
echo.To view the help file:
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\gnpy.ghc
goto end
)
if "%1" == "devhelp" (
%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished.
goto end
)
if "%1" == "epub" (
%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The epub file is in %BUILDDIR%/epub.
goto end
)
if "%1" == "latex" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
if errorlevel 1 exit /b 1
echo.
echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "latexpdf" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
cd %BUILDDIR%/latex
make all-pdf
cd %BUILDDIR%/..
echo.
echo.Build finished; the PDF files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "latexpdfja" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
cd %BUILDDIR%/latex
make all-pdf-ja
cd %BUILDDIR%/..
echo.
echo.Build finished; the PDF files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "text" (
%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The text files are in %BUILDDIR%/text.
goto end
)
if "%1" == "man" (
%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The manual pages are in %BUILDDIR%/man.
goto end
)
if "%1" == "texinfo" (
%SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
goto end
)
if "%1" == "gettext" (
%SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
goto end
)
if "%1" == "changes" (
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
if errorlevel 1 exit /b 1
echo.
echo.The overview file is in %BUILDDIR%/changes.
goto end
)
if "%1" == "linkcheck" (
%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
if errorlevel 1 exit /b 1
echo.
echo.Link check complete; look for any errors in the above output ^
or in %BUILDDIR%/linkcheck/output.txt.
goto end
)
if "%1" == "doctest" (
%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
if errorlevel 1 exit /b 1
echo.
echo.Testing of doctests in the sources finished, look at the ^
results in %BUILDDIR%/doctest/output.txt.
goto end
)
if "%1" == "xml" (
%SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The XML files are in %BUILDDIR%/xml.
goto end
)
if "%1" == "pseudoxml" (
%SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml.
goto end
)
:end
@ECHO OFF
pushd %~dp0
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=python -msphinx
)
set SOURCEDIR=.
set BUILDDIR=_build
set SPHINXPROJ=GNpy
if "%1" == "" goto help
%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
echo.
echo.The Sphinx module was not found. Make sure you have Sphinx installed,
echo.then set the SPHINXBUILD environment variable to point to the full
echo.path of the 'sphinx-build' executable. Alternatively you may add the
echo.Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.http://sphinx-doc.org/
exit /b 1
)
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
goto end
:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
:end
popd

149
docs/model.rst Normal file
View File

@@ -0,0 +1,149 @@
.. _physical-model:
***************************
Physical Model used in GNPy
***************************
QoT-E including ASE noise and NLI accumulation
==============================================
The operations of PSE simulative framework are based on the capability to
estimate the QoT of one or more channels operating lightpaths over a given
network route. For backbone transport networks, we can suppose that
transceivers are operating polarization-division-multiplexed multilevel
modulation formats with DSP-based coherent receivers, including equalization.
For the optical links, we focus on state-of-the-art amplified and uncompensated
fiber links, connecting network nodes including ROADMs, where add and drop
operations on data traffic are performed. In such a transmission scenario, it
is well accepted
:cite:`vacondio_nonlinear_2012,bononi_modeling_2012,carena_modeling_2012,mecozzi_nonlinear_2012,secondini_analytical_2012,johannisson_perturbation_2013,dar_properties_2013,serena_alternative_2013,secondini_achievable_2013,poggiolini_gn-model_2014,dar_accumulation_2014,poggiolini_analytical_2011,savory_approximations_2013,bononi_single-_2013,johannisson_modeling_2014`
to assume that transmission performances are limited by the amplified
spontaneous emission (ASE) noise generated by optical amplifiers and and
by nonlinear propagation effects: accumulation of a Gaussian disturbance
defined as nonlinear interference (NLI) and generation of phase noise.
State-of-the-art DSP in commercial transceivers are typically able to
compensate for most of the phase noise through carrier-phase estimator
(CPE) algorithms, for modulation formats with cardinality up to 16, per
polarization state
:cite:`poggiolini_recent_2017,schmidt_experimental_2015,fehenberger_experimental_2016`.
So, for backbone networks covering medium-to-wide geographical areas, we
can suppose that propagation is limited by the accumulation of two
Gaussian disturbances: the ASE noise and the NLI. Additional impairments
such as filtering effects introduced by ROADMs can be considered as
additional equivalent power penalties depending on the ratio between the
channel bandwidth and the ROADMs filters and the number of traversed
ROADMs (hops) of the route under analysis. Modeling the two major
sources of impairments as Gaussian disturbances, and being the receivers
*coherent*, the unique QoT parameter determining the bit error rate
(BER) for the considered transmission scenario is the generalized
signal-to-noise ratio (SNR) defined as
.. math::
{\text{SNR}}= L_F \frac{P_{\text{ch}}}{P_{\text{ASE}}+P_{\text{NLI}}} = L_F \left(\frac{1}{{\text{SNR}}_{\text{LIN}}}+\frac{1}{{\text{SNR}}_{\text{NL}}}\right)^{-1}
where :math:`P_{\text{ch}}` is the channel power,
:math:`P_{\text{ASE}}` and :math:`P_{\text{NLI}}` are the power levels of the disturbances
in the channel bandwidth for ASE noise and NLI, respectively.
:math:`L_F` is a parameter assuming values smaller or equal than one
that summarizes the equivalent power penalty loss such as
filtering effects. Note that for state-of-the art equipment, filtering
effects can be typically neglected over routes with few hops
:cite:`rahman_mitigation_2014,foggi_overcoming_2015`.
To properly estimate :math:`P_{\text{ch}}` and :math:`P_{\text{ASE}}`
the transmitted power at the beginning of the considered route must be
known, and losses and amplifiers gain and noise figure, including their
variation with frequency, must be characterized. So, the evaluation of
:math:`{\text{SNR}}_{\text{LIN}}` *just* requires an accurate
knowledge of equipment, which is not a trivial aspect, but it is not
related to physical-model issues. For the evaluation of the NLI, several
models have been proposed and validated in the technical literature
:cite:`vacondio_nonlinear_2012,bononi_modeling_2012,carena_modeling_2012,mecozzi_nonlinear_2012,secondini_analytical_2012,johannisson_perturbation_2013,dar_properties_2013,serena_alternative_2013,secondini_achievable_2013,poggiolini_gn-model_2014,dar_accumulation_2014,poggiolini_analytical_2011,savory_approximations_2013,bononi_single-_2013,johannisson_modeling_2014`.
The decision about which model to test within the PSE activities was
driven by requirements of the entire PSE framework:
i. the model must be *local*, i.e., related individually to each network
element (i.e. fiber span) generating NLI, independently of preceding and
subsequent elements; and ii. the related computational time must be compatible
with interactive operations.
So, the choice fell on the Gaussian Noise
(GN) model with incoherent accumulation of NLI over fiber spans
:cite:`poggiolini_gn-model_2014`. We implemented both the
exact GN-model evaluation of NLI based on a double integral (Eq. (11) of
:cite:`poggiolini_gn-model_2014`) and its analytical
approximation (Eq. (120-121) of
:cite:`poggiolini_analytical_2011`). We performed several
validation analyses comparing results of the two implementations with
split-step simulations over wide bandwidths
:cite:`pilori_ffss_2017`, and results clearly showed that
for fiber types with chromatic dispersion roughly larger than 4
ps/nm/km, the analytical approximation ensures an excellent accuracy
with a computational time compatible with real-time operations.
The Gaussian Noise Model to evaluate the NLI
============================================
As previously stated, fiber propagation of multilevel modulation formats
relying on the polarization-division-multiplexing generates impairments that
can be summarized as a disturbance called nonlinear interference (NLI), when
exploiting a DSP-based coherent receiver, as in all state-of-the-art equipment.
From a practical point of view, the NLI can be modeled as an additive Gaussian
random process added by each fiber span, and whose strength depends on the cube
of the input power spectral density and on the fiber-span parameters.
Since the introduction in the market in 2007 of the first transponder based on
such a transmission technique, the scientific community has intensively worked
to define the propagation behavior of such a trasnmission technique. First,
the role of in-line chromatic dispersion compensation has been investigated,
deducing that besides being not essential, it is indeed detrimental for
performances :cite:`curri_dispersion_2008`. Then, it has been observed that
the fiber propagation impairments are practically summarized by the sole NLI,
being all the other phenomena compensated for by the blind equalizer
implemented in the receiver DSP :cite:`carena_statistical_2010`. Once these
assessments have been accepted by the community, several prestigious research
groups have started to work on deriving analytical models able to estimating
the NLI accumulation, and consequentially the generalized SNR that sets the
BER, according to the transponder BER vs. SNR performance. Many models
delivering different levels of accuracy have been developed and validated. As
previously clarified, for the purposes of the PSE framework, the GN-model with
incoherent accumulation of NLI over fiber spans has been selected as adequate.
The reason for such a choice is first such a model being a "local" model, so
related to each fiber spans, independently of the preceding and succeeding
network elements. The other model characteristic driving the choice is the
availability of a closed form for the model, so permitting a real-time
evaluation, as required by the PSE framework. For a detailed derivation of the
model, please refer to :cite:`poggiolini_analytical_2011`, while a qualitative
description can be summarized as in the following. The GN-model assumes that
the channel comb propagating in the fiber is well approximated by unpolarized
spectrally shaped Gaussian noise. In such a scenario, supposing to rely - as in
state-of-the-art equipment - on a receiver entirely compensating for linear
propagation effects, propagation in the fiber only excites the four-wave mixing
(FWM) process among the continuity of the tones occupying the bandwidth. Such a
FWM generates an unpolarized complex Gaussian disturbance in each spectral slot
that can be easily evaluated extending the FWM theory from a set of discrete
tones - the standard FWM theory introduced back in the 90s by Inoue
:cite:`Innoue-FWM`- to a continuity of tones, possibly spectrally shaped.
Signals propagating in the fiber are not equivalent to Gaussian noise, but
thanks to the absence of in-line compensation for chromatic dispersion, the
become so, over short distances. So, the Gaussian noise model with incoherent
accumulation of NLI has extensively proved to be a quick yet accurate and
conservative tool to estimate propagation impairments of fiber propagation.
Note that the GN-model has not been derived with the aim of an *exact*
performance estimation, but to pursue a conservative performance prediction.
So, considering these characteristics, and the fact that the NLI is always a
secondary effect with respect to the ASE noise accumulation, and - most
importantly - that typically linear propagation parameters (losses, gains and
noise figures) are known within a variation range, a QoT estimator based on the
GN model is adequate to deliver performance predictions in terms of a
reasonable SNR range, rather than an exact value. As final remark, it must be
clarified that the GN-model is adequate to be used when relying on a relatively
narrow bandwidth up to few THz. When exceeding such a bandwidth occupation, the
GN-model must be generalized introducing the interaction with the Stimulated
Raman Scattering in order to give a proper estimation for all channels
:cite:`cantono2018modeling`. This will be the main upgrade required within the
PSE framework.
.. bibliography::

25
docs/publications.rst Normal file
View File

@@ -0,0 +1,25 @@
.. _publications:
************
Publications
************
Below is a chronological list of notable publications that emerged from the PSE group's collaborative work.
These articles detail the evolution of GNPy and confirm its performance through experimental trials:
- `G. Grammel, V. Curri, and J. Auge, "Physical Simulation Environment of The Telecommunications Infrastructure Project (TIP)," in Optical Fiber Communication Conference, OSA Technical Digest (online) (Optica Publishing Group, 2018), paper M1D.3. <https://opg.optica.org/abstract.cfm?uri=OFC-2018-M1D.3>`_
- `B. D. Taylor, G. Goldfarb, S. Bandyopadhyay, V. Curri, and H. Schmidtke, "Towards a Route Planning Tool for Open Optical Networks in the Telecom Infrastructure Project," in Optical Fiber Communication Conference, OSA Technical Digest (online) (Optica Publishing Group, 2018), paper Tu3E.4. <https://opg.optica.org/abstract.cfm?uri=OFC-2018-Tu3E.4>`_
- `M. Filer, M. Cantono, A. Ferrari, G. Grammel, G. Galimberti, and V. Curri, "Multi-Vendor Experimental Validation of an Open Source QoT Estimator for Optical Networks," J. Lightwave Technol. 36, 3073-3082 (2018). <https://opg.optica.org/jlt/abstract.cfm?uri=jlt-36-15-3073>`_
- `J. Auge, G. Grammel, E. le Rouzic, V. Curri, G. Galimberti, and J. Powell, "Open optical network planning demonstration," in Optical Fiber Communication Conference (OFC) 2019, OSA Technical Digest (Optica Publishing Group, 2019), paper M3Z.9. <https://opg.optica.org/abstract.cfm?uri=OFC-2019-M3Z.9>`_
- `J. Kundrát, A. Campanella, E. Le Rouzic, A. Ferrari, O. Havliš, M. Hažlinský, G. Grammel, G. Galimberti, and V. Curri, "Physical-Layer Awareness: GNPy and ONOS for End-to-End Circuits in Disaggregated Networks," in Optical Fiber Communication Conference (OFC) 2020, OSA Technical Digest (Optica Publishing Group, 2020), paper M3Z.17. <https://opg.optica.org/abstract.cfm?uri=ofc-2020-m3z.17>`_
- `A. Ferrari, M. Filer, K. Balasubramanian, Y. Yin, E. Le Rouzic, J. Kundrát, G. Grammel, G. Galimberti, and V. Curri, "Experimental Validation of an Open Source Quality of Transmission Estimator for Open Optical Networks," in Optical Fiber Communication Conference (OFC) 2020, OSA Technical Digest (Optica Publishing Group, 2020), paper W3C.2. <https://opg.optica.org/abstract.cfm?uri=ofc-2020-W3C.2>`_
- `A. Ferrari, M. Filer, K. Balasubramanian, Y. Yin, E. Le Rouzic, J. Kundrát, G. Grammel, G. Galimberti, and V. Curri, "GNPy: an open source application for physical layer aware open optical networks," J. Opt. Commun. Netw. 12, C31-C40 (2020). <https://opg.optica.org/jocn/fulltext.cfm?uri=jocn-12-6-C31&id=429003>`_
- `A. Ferrari, K. Balasubramanian, M. Filer, Y. Yin, E. Le Rouzic, J. Kundrát, G. Grammel, G. Galimberti, and V. Curri, "Softwarized Optical Transport QoT in Production Optical Network: a Brownfield Validation," 2020 European Conference on Optical Communications (ECOC), Brussels, Belgium, 2020. <https://ieeexplore.ieee.org/document/9333280>`_
- `A. Ferrari, K. Balasubramanian, M. Filer, Y. Yin, E. Le Rouzic, J. Kundrát, G. Grammel, G. Galimberti, and V. Curri, "Assessment on the in-field lightpath QoT computation including connector loss uncertainties," in Journal of Optical Communications and Networking, vol. 13, no. 2, pp. A156-A164, February 2021. <https://ieeexplore.ieee.org/document/9308057>`_
- `J. Kundrát, E. Le Rouzic, J. Mårtensson, A. Campanella, O. Havliš, A. DAmico, G. Grammel, G. Galimberti, V. Curri, and J. Vojtěch, "GNPy & YANG: Open APIs for End-to-End Service Provisioning in Optical Networks," in Optical Fiber Communication Conference (OFC) 2021, P. Dong, J. Kani, C. Xie, R. Casellas, C. Cole, and M. Li, eds., OSA Technical Digest (Optica Publishing Group, 2021), paper M1B.6. <https://opg.optica.org/abstract.cfm?uri=ofc-2021-M1B.6>`_
- `A. DAmico, E. London, B. Le Guyader, F. Frank, E. Le Rouzic, E. Pincemin, N. Brochier, and V. Curri, "GNPy experimental validation on flex-grid, flex-rate WDM optical transport scenarios," in Optical Fiber Communication Conference (OFC) 2021, P. Dong, J. Kani, C. Xie, R. Casellas, C. Cole, and M. Li, eds., OSA Technical Digest (Optica Publishing Group, 2021), paper W1G.2. <https://opg.optica.org/abstract.cfm?uri=ofc-2021-W1G.2>`_
- `E. Virgillito, R. Braun, D. Breuer, A. Gladisch, V. Curri, and G. Grammel, "Testing TIP Open Source Solutions in Deployed Optical Networks," in Optical Fiber Communication Conference (OFC) 2021, P. Dong, J. Kani, C. Xie, R. Casellas, C. Cole, and M. Li, eds., OSA Technical Digest (Optica Publishing Group, 2021), paper F1C.3. <https://opg.optica.org/abstract.cfm?uri=ofc-2021-F1C.3>`_
- `A. DAmico, E. London, B. Le Guyader, F. Frank, E. Le Rouzic, E. Pincemin, N. Brochier, and V. Curri, "Experimental validation of GNPy in a multi-vendor flex-grid flex-rate WDM optical transport scenario," J. Opt. Commun. Netw. 14, 79-88 (2022). <https://opg.optica.org/jocn/fulltext.cfm?uri=jocn-14-3-79&id=466355>`_
- `J. Kundrát, E. Le Rouzic, J. Mårtensson, S. Melin, A. DAmico, G. Grammel, G. Galimberti, and V. Curri, "GNPy: Lessons Learned and Future Plans [Invited]," in European Conference on Optical Communication (ECOC) 2022, J. Leuthold, C. Harder, B. Offrein, and H. Limberger, eds., Technical Digest Series (Optica Publishing Group, 2022), paper We3B.6. <https://opg.optica.org/abstract.cfm?uri=ECEOC-2022-We3B.6>`_
- `G. Grammel, J. Kundrat, E. Le Rouzic, S. Melin, V. Curri, A. D'Amico, R. Manzotti, "Open Optical Networks: the good, the bad and the ugly," 49th European Conference on Optical Communications (ECOC 2023), Hybrid Conference, Glasgow, UK, 2023. <https://ieeexplore.ieee.org/document/10484723>`_
- `A. DAmico, V. Gatto, A. Nespola, G. Borraccini, Y. Jiang, P. Poggiolini, E. Le Rouzic, A. M. L. de Lerma, G. Grammel, R. Manzotti, V. Curri, "GNPy Experimental Validation in a C+L Multiband Optical Multiplex Section," 2024 24th International Conference on Transparent Optical Networks (ICTON), Bari, Italy, 2024. <https://ieeexplore.ieee.org/document/10648172>`_

View File

@@ -1 +0,0 @@
.. include:: ../README.rst

527
docs/release-notes.rst Normal file
View File

@@ -0,0 +1,527 @@
.. _release-notes:
******************
Release change log
******************
Each release introduces some changes and new features.
(prepare text for next release)
v2.13
=====
**Environment**
The windows-2019 environment is no more supported.
**Yang Conversion Utilities**
This release introduces new conversion utilities to facilitate conversion between YANG and legacy formats,
ensuring full compatibility with GNPy. The "legacy" format also benefit from the YANG validation for
a stricter verification of input files.
Console Script for Yang Conversion: Added a new command-line script to perform Yang format conversions easily.
**Design Enhancements**
This release adds the ability to parametrize power target calculations, allowing customization of reference
span loss and deviation ratios. It implements the use of a reference channel per OMS (Optical Multiplex Section)
instead of total power for design calculations, improving accuracy and performance.
It also includes spacing information in design band data to assist in maximum power computation for EDFA
targets compution during autodesign.
**Excel handling**
XLSX files are now read with openpyxl library (while XLS files are still read with xlrd library). Latest release of
xlrd is supported, which solves compatibility issues with anaconda install.
v2.12
=====
**Important Changes:**
The default values for EDFA configuration, including frequency range, gain ripple, noise figure ripple, or dynamic gain tilt
are now hardcoded in parameters.py and are no longer read from the default_edfa_config.json file (the file has been removed).
However, users can define their own custom parameters using the default_config_from_json variable, which should be populated with a file name containing the desired parameter description. This applies to both variable_gain and fixed_gain amplifier types.
This change streamlines the configuration process but requires users to explicitly set parameters through the new
model if the default values do not suit their needs via the --extra-config option.
v2.11.1
-------
**Environment**
The macOS-12 environment is no more supported.
**per degree impairment enabled in xls input**
This release now read per degre roadm-path impairment from roadm sheet
Several optional columns are added: 'type_variety' and 'from degrees'
and 'from degree to degree impairment id'.
- 'from degrees' can contain a list of degrees separated with ' | ', then the
'from degree to degree impairment id' must contain a list of ids of the same
length.
Impairment ids are expected to be defined in the ROADM equipment library and
from degree must be among the previous node from this ROADM.
**optimizing computation speed**
The computation of path is skipped if the provided include nodes provides
a complete explicit path (speeds simulation time).
v2.11
=====
**New feature**
A new type_def for amplifiers has been introduced: multi_band. This allows the definition of a
multiband amplifier site composed of several amplifiers per band (a typical application is C+L transmission). The
release also includes autodesign for links (Optical Multiplex Section, OMS) composed of multi_band amplifiers.
Multi_band autodesign includes basic tilt and tilt_target calculation when the Raman flag is enabled with the
--sim-params option. The spectrum is demultiplexed before propagation in the amplifier and multiplexed in the output
fiber at the amplifier output.
In the library:
.. code-block:: json
{
"type_variety": "std_medium_gain_C",
"f_min": 191.225e12,
"f_max": 196.125e12,
"type_def": "variable_gain",
"gain_flatmax": 26,
"gain_min": 15,
"p_max": 21,
"nf_min": 6,
"nf_max": 10,
"out_voa_auto": false,
"allowed_for_design": false
},
{
"type_variety": "std_medium_gain_L",
"f_min": 186.5e12,
"f_max": 190.1e12,
"type_def": "variable_gain",
"gain_flatmax": 26,
"gain_min": 15,
"p_max": 21,
"nf_min": 6,
"nf_max": 10,
"out_voa_auto": false,
"allowed_for_design": true
},
{
"type_variety": "std_medium_gain_multiband",
"type_def": "multi_band",
"amplifiers": [
"std_medium_gain_C",
"std_medium_gain_L"
],
"allowed_for_design": false
},
In the network topology:
.. code-block:: json
{
"uid": "east edfa in Site_A to Site_B",
"type": "Multiband_amplifier",
"type_variety": "std_medium_gain_multiband",
"amplifiers": [{
"type_variety": "std_medium_gain_C",
"operational": {
"gain_target": 22.55,
"delta_p": 0.9,
"out_voa": 3.0,
"tilt_target": 0.0
}
}, {
"type_variety": "std_medium_gain_L",
"operational": {
"gain_target": 21,
"delta_p": 3.0,
"out_voa": 3.0,
"tilt_target": 0.0
}
}
]
}
**Network design**
Optionally, users can define a design target per OMS (single or multi-band), with specific frequency ranges.
Default design bands are defined in the SI.
.. code-block:: json
{
"uid": "roadm Site_A",
"type": "Roadm",
"params": {
"target_pch_out_db": -20,
"design_bands": [{"f_min": 191.3e12, "f_max": 195.1e12}]
}
}
It is possible to define a set of bands in the SI block instead of a single Spectrum Information.
In this case type_variety must be used.
Each set defines a reference channel used for design functions and autodesign.
The default design settings for the path-request-run script have been modified.
Now, design is performed once for the reference channel defined in the SI block of the eqpt_config,
and requests are propagated based on this design.
The --redesign-per-request option can be used to restore previous behaviour
(design using request channel types).
The autodesign function has been updated to insert multiband booster, preamp or inline amplifiers based on the OMS
nature. If nothing is stated (no amplifier defined in the OMS, no design_bands attribute in the ROADM), then
it uses single band Edfas.
**Propagation**
Only carriers within the amplifier bandwidth are propagated, improving system coherence. This more rigorous checking
of the spectrum to be propagated and the amplifier bandwidth may lead to changes in the total number of channels
compared to previous releases. The range can be adjusted by changing the values of ``f_min`` and ``f_max``
in the amplifier library.
``f_min`` and ``f_max`` represent the boundary frequencies of the amplification bandwidth (the entire channel must fit
within this range).
In the example below, a signal center frequency of 190.05THz with a 50GHz width cannot fit within the amplifier band.
Note that this has a different meaning in the SI or Transceiver blocks, where ``f_min`` and ``f_max`` refers to the
minimum / maximum values of the carrier center frequency.
.. code-block:: json
{
"type_variety": "std_booster_L",
"f_min": 186.55e12,
"f_max": 190.05e12,
"type_def": "fixed_gain",
"gain_flatmax": 21,
"gain_min": 20,
"p_max": 21,
"nf0": 5,
"allowed_for_design": false
}
**Display**
The CLI output for the transmission_main_example now displays the channels used for design and simulation,
as well as the tilt target of amplifiers.
.. code-block:: text
Reference used for design: (Input optical power reference in span = 0.00dBm,
spacing = 50.00GHz
nb_channels = 76)
Channels propagating: (Input optical power deviation in span = 0.00dB,
spacing = 50.00GHz,
transceiver output power = 0.00dBm,
nb_channels = 76)
The CLI output displays the settings of each amplifier:
.. code-block:: text
Multiband_amplifier east edfa in Site_A to Site_B
type_variety: std_medium_gain_multiband
type_variety: std_medium_gain_C type_variety: std_medium_gain_L
effective gain(dB): 20.90 effective gain(dB): 22.19
(before att_in and before output VOA) (before att_in and before output VOA)
tilt-target(dB) 0.00 tilt-target(dB) 0.00
noise figure (dB): 6.38 noise figure (dB): 6.19
(including att_in) (including att_in)
pad att_in (dB): 0.00 pad att_in (dB): 0.00
Power In (dBm): -1.08 Power In (dBm): -1.49
Power Out (dBm): 19.83 Power Out (dBm): 20.71
Delta_P (dB): 0.90 Delta_P (dB): 2.19
target pch (dBm): 0.90 target pch (dBm): 3.00
actual pch out (dBm): -2.09 actual pch out (dBm): -0.80
output VOA (dB): 3.00 output VOA (dB): 3.00
**New feature**
The preturbative Raman and the approximated GGN models are introduced for a faster evaluation of the Raman and
Kerr effects, respectively.
These implementation are intended to reduce the computational effort required by multiband transmission scenarios.
Both the novel models have been validated with exstensive simulations
(see `arXiv:2304.11756 <https://arxiv.org/abs/2304.11756>`_ for the new Raman model and
`jlt:9741324 <https://eeexplore.ieee.org/document/9741324>`_ for the new NLI model).
Additionally, they have been experimentally validated in a laboratory setup composed of commertial equipment
(see `icton:10648172 <https://eeexplore.ieee.org/document/10648172>`_).
v2.10
=====
ROADM impairments can be defined per degree and roadm-path type (add, drop or express).
Minimum loss when crossing a ROADM is no more 0 dB. It can be set per ROADM degree with roadm-path-impairments.
The transceiver output power, which was previously set using the same parameter as the input span power (power_dbm),
can now be set using a different parameter. It can be set as:
- for all channels, with tx_power_dbm using SI similarly to tx_osnr (gnpy-transmission-example script)
.. code-block:: json
"SI": [{
"f_min": 191.35e12,
"baud_rate": 32e9,
"f_max": 196.1e12,
"spacing": 50e9,
"power_dbm": 3,
"power_range_db": [0, 0, 1],
"roll_off": 0.15,
"tx_osnr": 40,
"tx_power_dbm": -10,
"sys_margins": 2
}
]
- for certain channels, using -spectrum option and tx_channel_power_dbm option (gnpy-transmission-example script).
.. code-block:: json
{
"spectrum": [
{
"f_min": 191.35e12,
"f_max":193.1e12,
"baud_rate": 32e9,
"slot_width": 50e9,
"power_dbm": 0,
"roll_off": 0.15,
"tx_osnr": 40
},
{
"f_min": 193.15e12,
"f_max":193.15e12,
"baud_rate": 32e9,
"slot_width": 50e9,
"power_dbm": 0,
"roll_off": 0.15,
"tx_osnr": 40,
"tx_power_dbm": -10
},
{
"f_min": 193.2e12,
"f_max":195.1e12,
"baud_rate": 32e9,
"slot_width": 50e9,
"power_dbm": 0,
"roll_off": 0.15,
"tx_osnr": 40
}
]
}
- per service using the additional parameter ``tx_power`` which similarly to ``power`` should be defined in Watt (gnpy-path-request script)
.. code-block:: json
{
"path-request": [
{
"request-id": "0",
"source": "trx SITE1",
"destination": "trx SITE2",
"src-tp-id": "trx SITE1",
"dst-tp-id": "trx SITE2",
"bidirectional": false,
"path-constraints": {
"te-bandwidth": {
"technology": "flexi-grid",
"trx_type": "Voyager",
"trx_mode": "mode 1",
"spacing": 50000000000.0,
"path_bandwidth": 100000000000.0
}
}
},
{
"request-id": "0 with tx_power",
"source": "trx SITE1",
"destination": "trx SITE2",
"src-tp-id": "trx SITE1",
"dst-tp-id": "trx SITE2",
"bidirectional": false,
"path-constraints": {
"te-bandwidth": {
"technology": "flexi-grid",
"trx_type": "Voyager",
"trx_mode": "mode 1",
"tx_power": 0.0001,
"spacing": 50000000000.0,
"path_bandwidth": 100000000000.0
}
}
}
]
}
v2.9
====
The revision introduces a major refactor that separates design and propagation. Most of these changes have no impact
on the user experience, except the following ones:
**Network design - amplifiers**: amplifier saturation is checked during design in all cases, even if type_variety is
set; amplifier gain is no more computed on the fly but only at design phase.
Before, the design did not consider amplifier power saturation during design if amplifier type_variety was stated.
With this revision, the saturation is always applied:
If design is made for a per channel power that leads to saturation, the target are properly reduced and the design
is freezed. So that when a new simulation is performed on the same network for lower levels of power per channel
the same gain target is applied. Before these were recomputed, changing the gain targets, so the simulation was
not considering the exact same working points for amplifiers in case of saturation.
Note that this case (working with saturation settings) is not recommended.
The gain of amplifiers was estimated on the fly also in case of RamanFiber preceding elements. The refactor now
requires that an estimation of Raman gain of the RamanFiber is done during design to properly compute a gain target.
The Raman gain is estimated at design for every RamanFiber span and also during propagation instead of being only
estimated at propagation stage for those Raman Fiber spans concerned with the transmission. The auto-design is more
accurate for unpropagated spans, but this results in an increase overall computation time.
This will be improved in the future.
**Network design - ROADMs**: ROADM target power settings are verified during design.
Design checks that expected power coming from every directions ingress from a ROADM are consistent with output power
targets. The checks only considers the adjacent previous hop. If the expected power at the input of this ROADM is
lower than the target power on the out-degree of the ROADM, a warning is displayed, and user is asked to review the
input network to avoid this situation. This does not change the design or propagation behaviour.
**Propagation**: amplifier gain target is no more recomputed during propagation. It is now possible to freeze
the design and propagate without automatic changes.
In previous release, gain was recomputed during propagation based on an hypothetical reference noiseless channel
propagation. It was not possible to «freeze» the autodesign, and propagate without recomputing the gain target
of amplifiers.
With this new release, the design is freezed, so that it is possible to compare performances on same basis.
**Display**: "effective pch (dbm)" is removed. Display contains the target pch which is the target power per channel
in dBm, computed based on reference channel used for design and the amplifier delta_p in dB (and before out VOA
contribution). Note that "actual pch out (dBm)" is the actual propagated total power per channel averaged per spectrum
band definition at the output of the amplifier element, including noises and out VOA contribution.
v2.8
====
**Spectrum assignment**: requests can now support multiple slots.
The definition in service file supports multiple assignments (unchanged syntax):
.. code-block:: json
"effective-freq-slot": [
{
"N": 0,
"M": 4
}, {
"N": 50,
"M": 4
}
],
But in results, label-hop is now a list of slots and center frequency index:
.. code-block:: json
{
"path-route-object": {
"index": 4,
"label-hop": [
{
"N": 0,
"M": 4
}, {
"N": 50,
"M": 4
}
]
}
},
instead of
.. code-block:: json
{
"path-route-object": {
"index": 4,
"label-hop": {
"N": 0,
"M": 4
}
}
},
**change in display**: only warnings are displayed ; information are disabled and needs the -v (verbose)
option to be displayed on standard output.
**frequency scaling**: A more accurate description of fiber parameters is implemented, including frequency scaling of
chromatic dispersion, effective area, Raman gain coefficient, and nonlinear coefficient.
In particular:
1. Chromatic dispersion can be defined with ``'dispersion'`` and ``'dispersion_slope'``, as in previous versions, or
with ``'dispersion_per_frequency'``; the latter must be defined as a dictionary with two keys, ``'value'`` and
``'frequency'`` and it has higher priority than the entries ``'dispersion'`` and ``'dispersion_slope'``.
Essential change: In previous versions, when it was not provided the ``'dispersion_slope'`` was calculated in an
involute manner to get a vanishing beta3 , and this was a mere artifact for NLI evaluation purposes (namely to evaluate
beta2 and beta3, not for total dispersion accumulation). Now, the evaluation of beta2 and beta3 is performed explicitly
in the element.py module.
1. The effective area is provided as a scalar value evaluated at the Fiber reference frequency and properly scaled
considering the Fiber refractive indices n1 and n2, and the core radius. These quantities are assumed to be fixed and
are hard coded in the parameters.py module. Essential change: The effective area is always scaled along the frequency.
1. The Raman gain coefficient is properly scaled considering the overlapping of fiber effective area values scaled at
the interacting frequencies. Essential change: In previous version the Raman gain coefficient depends only on
the frequency offset.
1. The nonlinear coefficient ``'gamma'`` is properly scaled considering the refractive index n2 and the scaling
effective area. Essential change: As the effective area, the nonlinear coefficient is always scaled along the
frequency.
**power offset**: Power equalization now enables defining a power offset in transceiver library to represent
the deviation from the general equalisation strategy defined in ROADMs.
.. code-block:: json
"mode": [{
"format": "100G",
"baud_rate": 32.0e9,
"tx_osnr": 35.0,
"min_spacing": 50.0e9,
"cost": 1,
"OSNR": 10.0,
"bit_rate": 100.0e9,
"roll_off": 0.2,
"equalization_offset_db": 0.0
}, {
"format": "200G",
"baud_rate": 64.0e9,
"tx_osnr": 35.0,
"min_spacing": 75.0e9,
"cost": 1,
"OSNR": 13.0,
"bit_rate": 200.0e9,
"roll_off": 0.2,
"equalization_offset_db": 1.76
}
]
v2.7
====

View File

@@ -1,7 +0,0 @@
=====
Usage
=====
To use gnpy in a project::
import gnpy

View File

@@ -1,7 +1,8 @@
# -*- coding: utf-8 -*-
"""
GNPy is an open-source, community-developed library for building route planning and optimization tools in real-world mesh optical networks. It is based on the Gaussian Noise Model.
from .gnpy import (raised_cosine_comb, analytic_formula, compute_psi, fwm_eff,
get_f_computed_interp, get_freqarray, gn_analytic, gn_model,
interpolate_in_range, GN_integral)
__all__ = ['gnpy']
Signal propagation is implemented in :py:mod:`.core`.
Path finding and spectrum assignment is in :py:mod:`.topology`.
Various tools and auxiliary code, including the JSON I/O handling, is in
:py:mod:`.tools`.
"""

View File

@@ -1,75 +0,0 @@
import gnpy as gn
import numpy as np
import matplotlib.pyplot as plt
import time
def main():
# Accuracy parameters
flag_analytic = True
num_computed_values = 2
interp_method = 'linear'
threshold_fwm = 50
n_points = 500
n_points_min = 4
accuracy_param = {'is_analytic': flag_analytic, 'points_not_interp': num_computed_values, 'kind_interp': interp_method,
'th_fwm': threshold_fwm, 'n_points': n_points, 'n_points_min': n_points_min}
# Parallelization Parameters
n_cores = 1
# Spectrum parameters
num_ch = 95
rs = np.ones(num_ch) * 0.032
b_ch = rs # For root raised cosine shapes, the -3 dB band is equal to the symbol rate
roll_off = np.ones(num_ch) * 0.05
power = np.ones(num_ch) * 0.001
central_freq = 193.5
if num_ch % 2 == 1: # odd number of channels
fch = np.arange(-(num_ch // 2), (num_ch // 2) + 1, 1) * 0.05 # noqa: E501
else:
fch = (np.arange(0, num_ch) - (num_ch / 2.0) + 0.5) * 0.05
spectrum_param = {'num_ch': num_ch, 'f_ch': fch, 'b_ch': b_ch, 'roll_off': roll_off, 'power': power}
# Fiber Parameters
beta2 = 21.27
l_span = 100.0
loss = 0.2
gam = 1.27
fiber_param = {'alpha': loss, 'span_length': l_span, 'beta_2': beta2, 'gamma': gam}
# EDFA Parameters
noise_fig = 5.5
gain_zero = 25.0
gain_tilting = 0.5
# Compute the GN model
t = time.time()
nli_cmp, f_nli_cmp, nli_int, f_nli_int = gn.gn_model(spectrum_param, fiber_param, accuracy_param, n_cores) # noqa: E501
print('Elapsed: %s' % (time.time() - t))
# Compute the EDFA profile
gain, g_ase = gn.compute_edfa_profile(gain_zero, gain_tilting, noise_fig, central_freq, fch)
# Compute the raised cosine comb
f1_array = np.linspace(np.amin(fch), np.amax(fch), 1e3)
gtx = gn.raised_cosine_comb(f1_array, rs, roll_off, fch, power)
gtx = gtx + 10 ** -6 # To avoid log10 issues.
# Plot the results
plt.figure(1)
plt.plot(f1_array, 10 * np.log10(gtx), '-b', label='WDM comb')
plt.plot(f_nli_cmp, 10 * np.log10(nli_cmp), 'ro', label='GNLI computed')
plt.plot(f_nli_int, 10 * np.log10(nli_int), 'g+', label='GNLI interpolated')
plt.plot(fch, 10 * np.log10(g_ase), 'yo', label='GASE')
plt.ylabel('PSD [dB(W/THz)]')
plt.xlabel('f [THz]')
plt.legend(loc='upper left')
plt.grid()
plt.draw()
plt.show()
if __name__ == '__main__':
main()

View File

@@ -1,84 +0,0 @@
import os
import gnpy as gn
import numpy as np
import matplotlib.pyplot as plt
import time
def main_ole():
# String indicating the folder in which outputs will be saved
string_date_time = time.strftime("%Y-%m-%d") + '_' + time.strftime("%H-%M-%S")
output_path = './output/' + string_date_time + '/'
# Creates the directory if it doesn't exist
if not os.path.isdir(output_path):
os.makedirs(output_path)
from configuration.fiber_parameters import fibers
from configuration.general_parameters import sys_param, control_param
from configuration.link_description import link
from input.spectrum_in import spectrum
# adapt the laser position to the grid
if len(spectrum['laser_position']) < sys_param['ns']:
n = sys_param['ns'] - len(spectrum['laser_position'])
missing_zeros = [0 for _ in range(n)]
spectrum['laser_position'] += missing_zeros
elif len(spectrum['laser_position']) > sys_param['ns']:
print('Error: the spectrum definition requires a larger number of slots ns in the spectrum grid')
delta_f = 6.25E-3
f_0 = sys_param['f0']
f_cent = f_0 + ((sys_param['ns'] // 2.0) * delta_f)
n_ch = spectrum['laser_position'].count(1)
# Get comb parameters
f_ch = np.zeros(n_ch)
count = 0
for index, bool_laser in enumerate(spectrum['laser_position']):
if bool_laser:
f_ch[count] = delta_f * index + (f_0 - f_cent)
count += 1
t = time.time()
# It runs the OLE
osnr_nl_db, osnr_lin_db = gn.ole(spectrum, link, fibers, sys_param, control_param, output_path=output_path)
print('Elapsed: %s' % (time.time() - t))
# Compute the raised cosine comb
power, rs, roll_off, p_ase, p_nli, n_ch = gn.get_spectrum_param(spectrum)
f1_array = np.linspace(np.amin(f_ch), np.amax(f_ch), 1e3)
gtx = gn.raised_cosine_comb(f1_array, rs, roll_off, f_ch, power)
gtx = gtx + 10 ** -6 # To avoid log10 issues.
# OSNR at in the central channel
ind_c = n_ch // 2
osnr_lin_central_db = osnr_lin_db[ind_c]
osnr_nl_central_db = osnr_nl_db[ind_c]
print('The linear OSNR in the central channel is: ' + str(osnr_lin_central_db) + ' dB')
print('The non linear OSNR in the central channel is: ' + str(osnr_nl_central_db) + ' dB')
# Plot the results
plt.figure(1)
plt.plot(f1_array, 10 * np.log10(gtx), '-b', label='WDM comb PSD [dB(W/THz)]')
plt.plot(f_ch, 10 * np.log10(p_nli), 'ro', label='NLI [dBw]')
plt.plot(f_ch, 10 * np.log10(p_ase), 'g+', label='ASE noise [dBw]')
plt.ylabel('')
plt.xlabel('f [THz]')
plt.legend(loc='upper right')
plt.grid()
plt.draw()
plt.figure(2)
plt.plot(f_ch, osnr_nl_db, 'ro', label='non-linear OSNR')
plt.plot(f_ch, osnr_lin_db, 'g+', label='linear OSNR')
plt.ylabel('OSNR [dB]')
plt.xlabel('f [THz]')
plt.legend(loc='lower left')
plt.grid()
plt.show()
if __name__ == '__main__':
main_ole()

View File

@@ -1,17 +0,0 @@
# -*- coding: utf-8 -*-
"""Console script for gnpy."""
import click
@click.command()
def main(args=None):
"""Console script for gnpy."""
click.echo("Replace this message by putting your code into "
"gnpy.cli.main")
click.echo("See click documentation at http://click.pocoo.org/")
if __name__ == "__main__":
main()

View File

@@ -1 +0,0 @@

View File

@@ -1,32 +0,0 @@
# coding=utf-8
""" fiber_parameters.py describes the fiber parameters.
fibers is a dictionary containing a dictionary for each kind of fiber
each dictionary has to report:
reference_frequency: the frequency at which the parameters are evaluated [THz]
alpha: the attenuation coefficient [dB/km]
alpha_1st: the first derivative of alpha indicating the alpha slope [dB/km/THz]
if you assume a flat attenuation with respect to the frequency you put it as zero
beta_2: the dispersion coefficient [ps^2/km]
n_2: second-order nonlinear refractive index [m^2/W]
a typical value is 2.5E-20 m^2/W
a_eff: the effective area of the fiber [um^2]
"""
fibers = {
'SMF': {
'reference_frequency': 193.5,
'alpha': 0.2,
'alpha_1st': 0,
'beta_2': 21.27,
'n_2': 2.5E-20,
'a_eff': 77.77,
},
'NZDF': {
'reference_frequency': 193.5,
'alpha': 0.22,
'alpha_1st': 0,
'beta_2': 21,
'n_2': 2.5E-20,
'a_eff': 70,
}
}

View File

@@ -1,40 +0,0 @@
# -*- coding: utf-8 -*
"""general_parameters.py contains the general configuration settings
The sectings are subdivided in two dictionaries:
sys_param: a dictionary containing the general system parameters:
f0: the starting frequency of the laser grid used to describe the WDM system [THz]
ns: the number of 6.25 GHz slots in the grid
control_param:
save_each_comp: a boolean flag. If true, it saves in output folder one spectrum file at the output of each
component, otherwise it saves just the last spectrum
is_linear: a bool flag. If true, is doesn't compute NLI, if false, OLE will consider NLI
is_analytic: a boolean flag. If true, the NLI is computed through the analytic formula, otherwise it uses
the double integral. Warning: the double integral is very slow.
points_not_interp: if the double integral is used, it indicates how much points are calculated, others will
be interpolated
kind_interp: a string indicating the interpolation method for the double integral
th_fwm: the threshold of the four wave mixing efficiency for the double integral
n_points: number of points in which the double integral is computed in the high FWM efficiency region
n_points_min: number of points in which the double integral is computed in the low FWM efficiency region
n_cores: number of cores for parallel computation [not yet implemented]
"""
# System parameters
sys_param = {
'f0': 192.075,
'ns': 328
}
# control parameters
control_param = {
'save_each_comp': True,
'is_linear': False,
'is_analytic': True,
'points_not_interp': 2,
'kind_interp': 'linear',
'th_fwm': 50,
'n_points': 500,
'n_points_min': 4,
'n_cores': 1
}

View File

@@ -1,59 +0,0 @@
# coding=utf-8
""" link_description.py contains the full description of that OLE has to emulate.
It contains a list of dictionaries, following the structure of the link and each element of the list describes one
component.
'comp_cat': the kind of link component:
PC: a passive component defined by a loss at a certain frequency and a loss tilt
OA: an optical amplifier defined by a gain at a certain frequency, a gain tilt and a noise figure
fiber: a span of fiber described by the type and the length
'comp_id': is an id identifying the component. It has to be unique for each component!
extra fields for PC:
'ref_freq': the frequency at which the 'loss' parameter is evaluated [THz]
'loss': the loss at the frequency 'ref_freq' [dB]
'loss_tlt': the frequency dependent loss [dB/THz]
extra fields for OA:
'ref_freq': the frequency at which the 'gain' parameter is evaluated [THz]
'gain': the gain at the frequency 'ref_freq' [dB]
'gain_tlt': the frequency dependent gain [dB/THz]
'noise_figure': the noise figure of the optical amplifier [dB]
extra fields for fiber:
'fiber_type': a string calling the type of fiber described in the file fiber_parameters.py
'length': the fiber length [km]
"""
smf = {
'comp_cat': 'fiber',
'comp_id': '',
'fiber_type': 'SMF',
'length': 100
}
oa = {
'comp_cat': 'OA',
'comp_id': '',
'ref_freq': 193.5,
'gain': 20,
'gain_tlt': 0.0,
'noise_figure': 5
}
pc = {
'comp_cat': 'PC',
'comp_id': '04',
'ref_freq': 193.,
'loss': 2.0,
'loss_tlt': 0.0
}
link = []
for index in range(20):
smf['comp_id'] = '%03d' % (2 * index)
oa['comp_id'] = '%03d' % (2 * index + 1)
link += [dict(smf)]
link += [dict(oa)]
pc['comp_id'] = '%03d' % 40
link += [dict(pc)]

9
gnpy/core/__init__.py Normal file
View File

@@ -0,0 +1,9 @@
"""
Simulation of signal propagation in the DWDM network
Optical signals, as defined via :class:`.info.SpectralInformation`, enter
:py:mod:`.elements` which compute how these signals are affected as they travel
through the :py:mod:`.network`.
The simulation is controlled via :py:mod:`.parameters` and implemented mainly
via :py:mod:`.science_utils`.
"""

20
gnpy/core/ansi_escapes.py Normal file
View File

@@ -0,0 +1,20 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# SPDX-License-Identifier: BSD-3-Clause
# gnpy.core.ansi_escapes: A random subset of ANSI terminal escape codes for colored messages
# Copyright (C) 2025 Telecom Infra Project and GNPy contributors
# see AUTHORS.rst for a list of contributors
"""
gnpy.core.ansi_escapes
======================
A random subset of ANSI terminal escape codes for colored messages
"""
red = '\x1b[1;31;40m'
blue = '\x1b[1;34;40m'
cyan = '\x1b[1;36;40m'
yellow = '\x1b[1;33;40m'
reset = '\x1b[0m'

1816
gnpy/core/elements.py Normal file

File diff suppressed because it is too large Load Diff

137
gnpy/core/equipment.py Normal file
View File

@@ -0,0 +1,137 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# SPDX-License-Identifier: BSD-3-Clause
# gnpy.core.equipment: functionality for specifying equipment
# Copyright (C) 2025 Telecom Infra Project and GNPy contributors
# see AUTHORS.rst for a list of contributors
"""
gnpy.core.equipment
===================
This module contains functionality for specifying equipment.
"""
from collections import defaultdict
from functools import reduce
from typing import List
from gnpy.core.exceptions import EquipmentConfigError, ConfigurationError
def trx_mode_params(equipment, trx_type_variety='', trx_mode='', error_message=False):
"""return the trx and SI parameters from eqpt_config for a given type_variety and mode (ie format)
if the type or mode do no match an existing transceiver in the library, then the function
raises an error if error_message is True else returns a default mode based on equipment['SI']['default']
If trx_mode is None (but type is valid), it returns an undetermined mode whatever the error message:
this is a special case for automatic mode selection.
"""
trx_params = {}
default_si_data = equipment['SI']['default']
# default transponder characteristics
# mainly used with transmission_main_example.py
default_trx_params = {
'f_min': default_si_data.f_min,
'f_max': default_si_data.f_max,
'baud_rate': default_si_data.baud_rate,
'spacing': default_si_data.spacing,
'OSNR': None,
'penalties': {},
'bit_rate': None,
'cost': None,
'roll_off': default_si_data.roll_off,
'tx_osnr': default_si_data.tx_osnr,
'min_spacing': None,
'equalization_offset_db': 0
}
# Undetermined transponder characteristics
# mainly used with path_request_run.py for the automatic mode computation case
undetermined_trx_params = {
"format": "undetermined",
"baud_rate": None,
"OSNR": None,
"penalties": None,
"bit_rate": None,
"roll_off": None,
"tx_osnr": None,
"min_spacing": None,
"cost": None,
"equalization_offset_db": 0
}
trxs = equipment['Transceiver']
if trx_type_variety in trxs:
modes = {mode['format']: mode for mode in trxs[trx_type_variety].mode}
trx_frequencies = {'f_min': trxs[trx_type_variety].frequency['min'],
'f_max': trxs[trx_type_variety].frequency['max']}
if trx_mode in modes:
# if called from transmission_main.py, trx_mode is ''
trx_params = {**modes[trx_mode], **trx_frequencies}
if trx_params['baud_rate'] > trx_params['min_spacing']:
# sanity check: baudrate must be smaller than min spacing
raise EquipmentConfigError(f'Inconsistency in equipment library:\n Transponder "{trx_type_variety}" '
+ f'mode "{trx_params["format"]}" has baud rate '
+ f'{trx_params["baud_rate"] * 1e-9:.2f} GHz greater than min_spacing '
+ f'{trx_params["min_spacing"] * 1e-9:.2f}.')
trx_params['equalization_offset_db'] = trx_params.get('equalization_offset_db', 0)
return trx_params
if trx_mode is None:
# if called from path_requests_run.py, trx_mode is filled with None when not specified by user
trx_params = {**undetermined_trx_params, **trx_frequencies}
return trx_params
if trx_type_variety in trxs and error_message:
raise EquipmentConfigError(f'Could not find transponder "{trx_type_variety}" with mode "{trx_mode}" '
+ 'in equipment library')
if error_message:
raise EquipmentConfigError(f'Could not find transponder "{trx_type_variety}" in equipment library')
trx_params = {**default_trx_params}
return trx_params
def find_type_variety(amps: List[str], equipment: dict) -> List[str]:
"""Returns the multiband type_variety associated with a list of single band type_varieties
Args:
amps (List[str]): A list of single band type_varieties.
equipment (dict): A dictionary containing equipment information.
Returns:
str: an amplifier type variety
"""
listes = find_type_varieties(amps, equipment)
_found_type = list(reduce(lambda x, y: set(x) & set(y), listes))
# Given a list of single band amplifiers, find the multiband amplifier whose multi_band group
# matches. For example, if amps list contains ["a1_LBAND", "a2_CBAND"], with a1.multi_band = [a1_LBAND, a1_CBAND]
# and a2.multi_band = [a1_LBAND, a2_CBAND], then:
# possible_type_varieties = {"a1_LBAND": ["a1", "a2"], "a2_CBAND": ["a2"]}
# listes = [["a1", "a2"], ["a2"]]
# and _found_type = [a2]
if not _found_type:
msg = f'{amps} amps do not belong to the same amp type {listes}'
raise ConfigurationError(msg)
return _found_type
def find_type_varieties(amps: List[str], equipment: dict) -> List[List[str]]:
"""Returns the multiband list of type_varieties associated with a list of single band type_varieties
Args:
amps (List[str]): A list of single band type_varieties.
equipment (dict): A dictionary containing equipment information.
Returns:
List[List[str]]: A list of lists containing the multiband type_varieties
associated with each single band type_variety.
"""
possible_type_varieties = defaultdict(list)
for amp_name, amp in equipment['Edfa'].items():
if amp.multi_band is not None:
for elem in amp.multi_band:
# possible_type_varieties stores the list of multiband amp names that list this elem as
# a possible amplifier of the multiband group. For example, if "std_medium_gain_multiband"
# and "std_medium_gain_multiband_new" contain "std_medium_gain_C" in their "multi_band" list, then:
# possible_type_varieties["std_medium_gain_C"] =
# ["std_medium_gain_multiband", "std_medium_gain_multiband_new"]
possible_type_varieties[elem].append(amp_name)
return [possible_type_varieties[a] for a in amps]

42
gnpy/core/exceptions.py Normal file
View File

@@ -0,0 +1,42 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# SPDX-License-Identifier: BSD-3-Clause
# gnpy.core.exceptions: Exceptions thrown by other gnpy modules
# Copyright (C) 2025 Telecom Infra Project and GNPy contributors
# see AUTHORS.rst for a list of contributors
"""
gnpy.core.exceptions
====================
Exceptions thrown by other gnpy modules
"""
class ConfigurationError(Exception):
"""User-provided configuration contains an error"""
class EquipmentConfigError(ConfigurationError):
"""Incomplete or wrong configuration within the equipment library"""
class NetworkTopologyError(ConfigurationError):
"""Topology of user-provided network is wrong"""
class ServiceError(Exception):
"""Service of user-provided request is wrong"""
class DisjunctionError(ServiceError):
"""Disjunction of user-provided request can not be satisfied"""
class SpectrumError(Exception):
"""Spectrum errors of the program"""
class ParametersError(ConfigurationError):
"""Incomplete or wrong configurations within parameters json"""

433
gnpy/core/info.py Normal file
View File

@@ -0,0 +1,433 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# SPDX-License-Identifier: BSD-3-Clause
# gnpy.core.info: classes for modelling Spectral Information
# Copyright (C) 2025 Telecom Infra Project and GNPy contributors
# see AUTHORS.rst for a list of contributors
"""
gnpy.core.info
==============
This module contains classes for modelling :class:`SpectralInformation`.
"""
from __future__ import annotations
from collections import namedtuple
from collections.abc import Iterable
from typing import Union, List, Optional
from dataclasses import dataclass
from numpy import argsort, mean, array, append, ones, ceil, any, zeros, outer, full, ndarray, asarray
from gnpy.core.utils import automatic_nch, db2lin, watt2dbm
from gnpy.core.exceptions import SpectrumError
DEFAULT_SLOT_WIDTH_STEP = 12.5e9 # Hz
"""Channels with unspecified slot width will have their slot width evaluated as the baud rate rounded up to the minimum
multiple of the DEFAULT_SLOT_WIDTH_STEP (the baud rate is extended including the roll off in this evaluation)"""
class Power(namedtuple('Power', 'signal nli ase')):
"""carriers power in W"""
class Channel(
namedtuple('Channel',
'channel_number frequency baud_rate slot_width roll_off power chromatic_dispersion pmd pdl latency')):
"""Class containing the parameters of a WDM signal.
:param channel_number: channel number in the WDM grid
:param frequency: central frequency of the signal (Hz)
:param baud_rate: the symbol rate of the signal (Baud)
:param slot_width: the slot width (Hz)
:param roll_off: the roll off of the signal. It is a pure number between 0 and 1
:param power (gnpy.core.info.Power): power of signal, ASE noise and NLI (W)
:param chromatic_dispersion: chromatic dispersion (s/m)
:param pmd: polarization mode dispersion (s)
:param pdl: polarization dependent loss (dB)
:param latency: propagation latency (s)
"""
class SpectralInformation(object):
"""Class containing the parameters of the entire WDM comb.
delta_pdb_per_channel: (per frequency) per channel delta power in dbm for the actual mix of channels"""
def __init__(self, frequency: array, baud_rate: array, slot_width: array, signal: array, nli: array, ase: array,
roll_off: array, chromatic_dispersion: array, pmd: array, pdl: array, latency: array,
delta_pdb_per_channel: array, tx_osnr: array, tx_power: array, label: array):
indices = argsort(frequency)
self._frequency = frequency[indices]
self._df = outer(ones(frequency.shape), frequency) - outer(frequency, ones(frequency.shape))
self._number_of_channels = len(self._frequency)
self._channel_number = [*range(1, self._number_of_channels + 1)]
self._slot_width = slot_width[indices]
self._baud_rate = baud_rate[indices]
overlap = self._frequency[:-1] + self._slot_width[:-1] / 2 > self._frequency[1:] - self._slot_width[1:] / 2
if any(overlap):
overlap = [pair for pair in zip(overlap * self._channel_number[:-1], overlap * self._channel_number[1:])
if pair != (0, 0)]
raise SpectrumError(f'Spectrum required slot widths larger than the frequency spectral distances '
f'between channels: {overlap}.')
exceed = self._baud_rate > self._slot_width
if any(exceed):
raise SpectrumError(f'Spectrum baud rate, including the roll off, larger than the slot width for channels: '
f'{[ch for ch in exceed * self._channel_number if ch]}.')
self._signal = signal[indices]
self._nli = nli[indices]
self._ase = ase[indices]
self._roll_off = roll_off[indices]
self._chromatic_dispersion = chromatic_dispersion[indices]
self._pmd = pmd[indices]
self._pdl = pdl[indices]
self._latency = latency[indices]
self._delta_pdb_per_channel = delta_pdb_per_channel[indices]
self._tx_osnr = tx_osnr[indices]
self._tx_power = tx_power[indices]
self._label = label[indices]
@property
def frequency(self):
return self._frequency
@property
def df(self):
"""Matrix of relative frequency distances between all channels. Positive elements in the upper right side."""
return self._df
@property
def slot_width(self):
return self._slot_width
@property
def baud_rate(self):
return self._baud_rate
@property
def number_of_channels(self):
return self._number_of_channels
@property
def powers(self):
powers = zip(self.signal, self.nli, self.ase)
return [Power(*p) for p in powers]
@property
def signal(self):
return self._signal
@signal.setter
def signal(self, signal):
self._signal = signal
@property
def nli(self):
return self._nli
@nli.setter
def nli(self, nli):
self._nli = nli
@property
def ase(self):
return self._ase
@ase.setter
def ase(self, ase):
self._ase = ase
@property
def roll_off(self):
return self._roll_off
@property
def chromatic_dispersion(self):
return self._chromatic_dispersion
@chromatic_dispersion.setter
def chromatic_dispersion(self, chromatic_dispersion):
self._chromatic_dispersion = chromatic_dispersion
@property
def pmd(self):
return self._pmd
@property
def label(self):
return self._label
@pmd.setter
def pmd(self, pmd):
self._pmd = pmd
@property
def pdl(self):
return self._pdl
@pdl.setter
def pdl(self, pdl):
self._pdl = pdl
@property
def latency(self):
return self._latency
@latency.setter
def latency(self, latency):
self._latency = latency
@property
def delta_pdb_per_channel(self):
return self._delta_pdb_per_channel
@delta_pdb_per_channel.setter
def delta_pdb_per_channel(self, delta_pdb_per_channel):
self._delta_pdb_per_channel = delta_pdb_per_channel
@property
def tx_osnr(self):
return self._tx_osnr
@tx_osnr.setter
def tx_osnr(self, tx_osnr):
self._tx_osnr = tx_osnr
@property
def tx_power(self):
return self._tx_power
@tx_power.setter
def tx_power(self, tx_power):
self._tx_power = tx_power
@property
def channel_number(self):
return self._channel_number
@property
def carriers(self):
entries = zip(self.channel_number, self.frequency, self.baud_rate, self.slot_width,
self.roll_off, self.powers, self.chromatic_dispersion, self.pmd, self.pdl, self.latency)
return [Channel(*entry) for entry in entries]
def apply_attenuation_lin(self, attenuation_lin):
self.signal *= attenuation_lin
self.nli *= attenuation_lin
self.ase *= attenuation_lin
def apply_attenuation_db(self, attenuation_db):
attenuation_lin = 1 / db2lin(attenuation_db)
self.apply_attenuation_lin(attenuation_lin)
def apply_gain_lin(self, gain_lin):
self.signal *= gain_lin
self.nli *= gain_lin
self.ase *= gain_lin
def apply_gain_db(self, gain_db):
gain_lin = db2lin(gain_db)
self.apply_gain_lin(gain_lin)
def __add__(self, other: SpectralInformation):
try:
return SpectralInformation(frequency=append(self.frequency, other.frequency),
slot_width=append(self.slot_width, other.slot_width),
signal=append(self.signal, other.signal), nli=append(self.nli, other.nli),
ase=append(self.ase, other.ase),
baud_rate=append(self.baud_rate, other.baud_rate),
roll_off=append(self.roll_off, other.roll_off),
chromatic_dispersion=append(self.chromatic_dispersion,
other.chromatic_dispersion),
pmd=append(self.pmd, other.pmd),
pdl=append(self.pdl, other.pdl),
latency=append(self.latency, other.latency),
delta_pdb_per_channel=append(self.delta_pdb_per_channel,
other.delta_pdb_per_channel),
tx_osnr=append(self.tx_osnr, other.tx_osnr),
tx_power=append(self.tx_power, other.tx_power),
label=append(self.label, other.label))
except SpectrumError:
raise SpectrumError('Spectra cannot be summed: channels overlapping.')
def _replace(self, carriers):
self.chromatic_dispersion = array([c.chromatic_dispersion for c in carriers])
self.pmd = array([c.pmd for c in carriers])
self.pdl = array([c.pdl for c in carriers])
self.latency = array([c.latency for c in carriers])
self.signal = array([c.power.signal for c in carriers])
self.nli = array([c.power.nli for c in carriers])
self.ase = array([c.power.ase for c in carriers])
return self
def create_arbitrary_spectral_information(frequency: Union[ndarray, Iterable, float],
signal: Union[float, ndarray, Iterable],
baud_rate: Union[float, ndarray, Iterable],
tx_osnr: Union[float, ndarray, Iterable],
tx_power: Union[float, ndarray, Iterable] = None,
delta_pdb_per_channel: Union[float, ndarray, Iterable] = 0.,
slot_width: Union[float, ndarray, Iterable] = None,
roll_off: Union[float, ndarray, Iterable] = 0.,
chromatic_dispersion: Union[float, ndarray, Iterable] = 0.,
pmd: Union[float, ndarray, Iterable] = 0.,
pdl: Union[float, ndarray, Iterable] = 0.,
latency: Union[float, ndarray, Iterable] = 0.,
label: Union[str, ndarray, Iterable] = None):
"""This is just a wrapper around the SpectralInformation.__init__() that simplifies the creation of
a non-uniform spectral information with NLI and ASE powers set to zero."""
frequency = asarray(frequency)
number_of_channels = frequency.size
try:
signal = full(number_of_channels, signal)
baud_rate = full(number_of_channels, baud_rate)
roll_off = full(number_of_channels, roll_off)
slot_width = full(number_of_channels, slot_width) if slot_width is not None else \
ceil((1 + roll_off) * baud_rate / DEFAULT_SLOT_WIDTH_STEP) * DEFAULT_SLOT_WIDTH_STEP
chromatic_dispersion = full(number_of_channels, chromatic_dispersion)
pmd = full(number_of_channels, pmd)
pdl = full(number_of_channels, pdl)
latency = full(number_of_channels, latency)
nli = zeros(number_of_channels)
ase = zeros(number_of_channels)
delta_pdb_per_channel = full(number_of_channels, delta_pdb_per_channel)
tx_osnr = full(number_of_channels, tx_osnr)
tx_power = full(number_of_channels, tx_power)
label = full(number_of_channels, label)
return SpectralInformation(frequency=frequency, slot_width=slot_width,
signal=signal, nli=nli, ase=ase,
baud_rate=baud_rate, roll_off=roll_off,
chromatic_dispersion=chromatic_dispersion,
pmd=pmd, pdl=pdl, latency=latency,
delta_pdb_per_channel=delta_pdb_per_channel,
tx_osnr=tx_osnr, tx_power=tx_power, label=label)
except ValueError as e:
if 'could not broadcast' in str(e):
raise SpectrumError('Dimension mismatch in input fields.')
else:
raise
def create_input_spectral_information(f_min, f_max, roll_off, baud_rate, spacing, tx_osnr, tx_power,
delta_pdb=0):
"""Creates a fixed slot width spectral information with flat power.
all arguments are scalar values"""
number_of_channels = automatic_nch(f_min, f_max, spacing)
frequency = [(f_min + spacing * i) for i in range(1, number_of_channels + 1)]
delta_pdb_per_channel = delta_pdb * ones(number_of_channels)
label = [f'{baud_rate * 1e-9 :.2f}G' for i in range(number_of_channels)]
return create_arbitrary_spectral_information(frequency, slot_width=spacing, signal=tx_power, baud_rate=baud_rate,
roll_off=roll_off, delta_pdb_per_channel=delta_pdb_per_channel,
tx_osnr=tx_osnr, tx_power=tx_power, label=label)
def is_in_band(frequency: float, band: dict) -> bool:
"""band has {"f_min": value, "f_max": value} format
"""
if frequency >= band['f_min'] and frequency <= band['f_max']:
return True
return False
def demuxed_spectral_information(input_si: SpectralInformation, band: dict) -> Optional[SpectralInformation]:
"""extract a si based on band
"""
filtered_indices = [i for i, f in enumerate(input_si.frequency)
if is_in_band(f - input_si.slot_width[i] / 2, band)
and is_in_band(f + input_si.slot_width[i] / 2, band)]
if filtered_indices:
frequency = input_si.frequency[filtered_indices]
baud_rate = input_si.baud_rate[filtered_indices]
slot_width = input_si.slot_width[filtered_indices]
signal = input_si.signal[filtered_indices]
nli = input_si.nli[filtered_indices]
ase = input_si.ase[filtered_indices]
roll_off = input_si.roll_off[filtered_indices]
chromatic_dispersion = input_si.chromatic_dispersion[filtered_indices]
pmd = input_si.pmd[filtered_indices]
pdl = input_si.pdl[filtered_indices]
latency = input_si.latency[filtered_indices]
delta_pdb_per_channel = input_si.delta_pdb_per_channel[filtered_indices]
tx_osnr = input_si.tx_osnr[filtered_indices]
tx_power = input_si.tx_power[filtered_indices]
label = input_si.label[filtered_indices]
return SpectralInformation(frequency=frequency, baud_rate=baud_rate, slot_width=slot_width, signal=signal,
nli=nli, ase=ase, roll_off=roll_off, chromatic_dispersion=chromatic_dispersion,
pmd=pmd, pdl=pdl, latency=latency, delta_pdb_per_channel=delta_pdb_per_channel,
tx_osnr=tx_osnr, tx_power=tx_power, label=label)
return None
def muxed_spectral_information(input_si_list: List[SpectralInformation]) -> SpectralInformation:
"""return the assembled spectrum
"""
if input_si_list and len(input_si_list) > 1:
si = input_si_list[0] + muxed_spectral_information(input_si_list[1:])
return si
elif input_si_list and len(input_si_list) == 1:
return input_si_list[0]
else:
raise ValueError('liste vide')
def carriers_to_spectral_information(initial_spectrum: dict[float, Carrier],
power: float) -> SpectralInformation:
"""Initial spectrum is a dict with key = carrier frequency, and value a Carrier object.
:param initial_spectrum: indexed by frequency in Hz, with power offset (delta_pdb), baudrate, slot width,
tx_osnr, tx_power and roll off.
:param power: power of the request
"""
frequency = list(initial_spectrum.keys())
signal = [c.tx_power for c in initial_spectrum.values()]
roll_off = [c.roll_off for c in initial_spectrum.values()]
baud_rate = [c.baud_rate for c in initial_spectrum.values()]
delta_pdb_per_channel = [c.delta_pdb for c in initial_spectrum.values()]
slot_width = [c.slot_width for c in initial_spectrum.values()]
tx_osnr = [c.tx_osnr for c in initial_spectrum.values()]
tx_power = [c.tx_power for c in initial_spectrum.values()]
label = [c.label for c in initial_spectrum.values()]
return create_arbitrary_spectral_information(frequency=frequency, signal=signal, baud_rate=baud_rate,
slot_width=slot_width, roll_off=roll_off,
delta_pdb_per_channel=delta_pdb_per_channel, tx_osnr=tx_osnr,
tx_power=tx_power, label=label)
@dataclass
class Carrier:
"""One channel in the initial mixed-type spectrum definition, each type being defined by
its delta_pdb (power offset with respect to reference power), baud rate, slot_width, roll_off
tx_power, and tx_osnr. delta_pdb offset is applied to target power out of Roadm.
Label is used to group carriers which belong to the same partition when printing results.
"""
delta_pdb: float
baud_rate: float
slot_width: float
roll_off: float
tx_osnr: float
tx_power: float
label: str
@dataclass
class ReferenceCarrier:
"""Reference channel type is used to determine target power out of ROADM for the reference channel when
constant power spectral density (PSD) equalization is set. Reference channel is the type that has been defined
in SI block and used for the initial design of the network.
Computing the power out of ROADM for the reference channel is required to correctly compute the loss
experienced by reference channel in Roadm element.
Baud rate is required to find the target power in constant PSD: power = PSD_target * baud_rate.
For example, if target PSD is 3.125e4mW/GHz and reference carrier type a 32 GBaud channel then
output power should be -20 dBm and for a 64 GBaud channel power target would need 3 dB more: -17 dBm.
Slot width is required to find the target power in constant PSW (constant power per slot width equalization):
power = PSW_target * slot_width.
For example, if target PSW is 2e4mW/GHz and reference carrier type a 32 GBaud channel in a 50GHz slot width then
output power should be -20 dBm and for a 64 GBaud channel in a 75 GHz slot width, power target would be -18.24 dBm.
Other attributes (like roll-off) may be added there for future equalization purpose.
"""
baud_rate: float
slot_width: float

2164
gnpy/core/network.py Normal file

File diff suppressed because it is too large Load Diff

731
gnpy/core/parameters.py Normal file
View File

@@ -0,0 +1,731 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# SPDX-License-Identifier: BSD-3-Clause
# gnpy.core.parameters: parameters to configure standard network elements
# Copyright (C) 2025 Telecom Infra Project and GNPy contributors
# see AUTHORS.rst for a list of contributors
"""
gnpy.core.parameters
====================
This module contains all parameters to configure standard network elements.
"""
from collections import namedtuple
from copy import deepcopy
from dataclasses import dataclass
from scipy.constants import c, pi
from numpy import asarray, array, exp, sqrt, log, outer, ones, squeeze, append, flip, linspace, full
from gnpy.core.utils import convert_length
from gnpy.core.exceptions import ParametersError
class Parameters:
def asdict(self):
class_dict = self.__class__.__dict__
instance_dict = self.__dict__
new_dict = {}
for key in class_dict:
if isinstance(class_dict[key], property):
new_dict[key] = instance_dict['_' + key]
return new_dict
class PumpParams(Parameters):
def __init__(self, power, frequency, propagation_direction):
self.power = power
self.frequency = frequency
self.propagation_direction = propagation_direction.lower()
class RamanParams(Parameters):
def __init__(self, flag=False, method='perturbative', order=2, result_spatial_resolution=10e3,
solver_spatial_resolution=10e3):
"""Simulation parameters used within the Raman Solver
:params flag: boolean for enabling/disable the evaluation of the Raman power profile in frequency and position
:params method: Raman solver method
:params order: solution order for perturbative method
:params result_spatial_resolution: spatial resolution of the evaluated Raman power profile
:params solver_spatial_resolution: spatial step for the iterative solution of the first order ode
"""
self.flag = flag
self.method = method
self.order = order
self.result_spatial_resolution = result_spatial_resolution # [m]
self.solver_spatial_resolution = solver_spatial_resolution # [m]
def to_json(self):
return {"flag": self.flag,
"method": self.method,
"order": self.order,
"result_spatial_resolution": self.result_spatial_resolution,
"solver_spatial_resolution": self.solver_spatial_resolution}
class NLIParams(Parameters):
def __init__(self, method='gn_model_analytic', dispersion_tolerance=4, phase_shift_tolerance=0.1,
computed_channels=None, computed_number_of_channels=None):
"""Simulation parameters used within the Nli Solver
:params method: formula for NLI calculation
:params dispersion_tolerance: tuning parameter for ggn model solution
:params phase_shift_tolerance: tuning parameter for ggn model solution
:params computed_channels: the NLI is evaluated for these channels and extrapolated for the others
:params computed_number_of_channels: the NLI is evaluated for this number of channels equally distributed
in the spectrum and extrapolated for the others
"""
self.method = method.lower()
self.dispersion_tolerance = dispersion_tolerance
self.phase_shift_tolerance = phase_shift_tolerance
self.computed_channels = computed_channels
self.computed_number_of_channels = computed_number_of_channels
def to_json(self):
return {"method": self.method,
"dispersion_tolerance": self.dispersion_tolerance,
"phase_shift_tolerance": self.phase_shift_tolerance,
"computed_channels": self.computed_channels,
"computed_number_of_channels": self.computed_number_of_channels}
class SimParams(Parameters):
_shared_dict = {'nli_params': NLIParams(), 'raman_params': RamanParams()}
@classmethod
def set_params(cls, sim_params):
cls._shared_dict['nli_params'] = NLIParams(**sim_params.get('nli_params', {}))
cls._shared_dict['raman_params'] = RamanParams(**sim_params.get('raman_params', {}))
@property
def nli_params(self):
return self._shared_dict['nli_params']
@property
def raman_params(self):
return self._shared_dict['raman_params']
class RoadmParams(Parameters):
def __init__(self, **kwargs):
self.target_pch_out_db = kwargs.get('target_pch_out_db')
self.target_psd_out_mWperGHz = kwargs.get('target_psd_out_mWperGHz')
self.target_out_mWperSlotWidth = kwargs.get('target_out_mWperSlotWidth')
equalisation_type = ['target_pch_out_db', 'target_psd_out_mWperGHz', 'target_out_mWperSlotWidth']
temp = [kwargs.get(k) is not None for k in equalisation_type]
if sum(temp) > 1:
raise ParametersError('ROADM config contains more than one equalisation type.'
+ 'Please choose only one', kwargs)
self.per_degree_pch_out_db = kwargs.get('per_degree_pch_out_db', {})
self.per_degree_pch_psd = kwargs.get('per_degree_psd_out_mWperGHz', {})
self.per_degree_pch_psw = kwargs.get('per_degree_psd_out_mWperSlotWidth', {})
try:
self.add_drop_osnr = kwargs['add_drop_osnr']
self.pmd = kwargs['pmd']
self.pdl = kwargs['pdl']
self.restrictions = kwargs['restrictions']
self.roadm_path_impairments = self.get_roadm_path_impairments(kwargs['roadm-path-impairments'])
except KeyError as e:
raise ParametersError(f'ROADM configurations must include {e}. Configuration: {kwargs}')
self.per_degree_impairments = kwargs.get('per_degree_impairments', [])
self.design_bands = kwargs.get('design_bands', [])
self.per_degree_design_bands = kwargs.get('per_degree_design_bands', {})
def get_roadm_path_impairments(self, path_impairments_list):
"""Get the ROADM list of profiles for impairments definition
transform the ietf model into gnpy internal model: add a path-type in the attributes
"""
if not path_impairments_list:
return {}
authorized_path_types = {
'roadm-express-path': 'express',
'roadm-add-path': 'add',
'roadm-drop-path': 'drop',
}
roadm_path_impairments = {}
for path_impairment in path_impairments_list:
index = path_impairment['roadm-path-impairments-id']
path_type = next(key for key in path_impairment if key in authorized_path_types.keys())
impairment_dict = {'path-type': authorized_path_types[path_type], 'impairment': path_impairment[path_type]}
roadm_path_impairments[index] = RoadmImpairment(impairment_dict)
return roadm_path_impairments
class RoadmPath:
def __init__(self, from_degree, to_degree, path_type, impairment_id=None, impairment=None):
"""Records roadm internal paths, types and impairment
path_type must be in "express", "add", "drop"
impairment_id must be one of the id detailed in equipement
"""
self.from_degree = from_degree
self.to_degree = to_degree
self.path_type = path_type
self.impairment_id = impairment_id
self.impairment = impairment
class RoadmImpairment:
"""Generic definition of impairments for express, add and drop"""
default_values = {
'roadm-pmd': None,
'roadm-cd': None,
'roadm-pdl': None,
'roadm-inband-crosstalk': None,
'roadm-maxloss': 0,
'roadm-osnr': None,
'roadm-pmax': None,
'roadm-noise-figure': None,
'minloss': None,
'typloss': None,
'pmin': None,
'ptyp': None
}
def __init__(self, params):
self.path_type = params.get('path-type')
self.impairments = params['impairment']
class FusedParams(Parameters):
def __init__(self, **kwargs):
self.loss = kwargs['loss'] if 'loss' in kwargs else 1
DEFAULT_RAMAN_COEFFICIENT = {
# SSMF Raman coefficient profile in terms of mode intensity (g0 * A_ff_overlap)
'gamma_raman': array(
[0.0, 8.524419934705497e-16, 2.643567866245371e-15, 4.410548410941305e-15, 6.153422961291078e-15,
7.484924703044943e-15, 8.452060808349209e-15, 9.101549322698156e-15, 9.57837595158966e-15,
1.0008642675474562e-14, 1.0865773569905647e-14, 1.1300776305865833e-14, 1.2143238647099625e-14,
1.3231065750676068e-14, 1.4624900971525384e-14, 1.6013330554840492e-14, 1.7458119359310242e-14,
1.9320241330434762e-14, 2.1720395392873534e-14, 2.4137337406734775e-14, 2.628163218460466e-14,
2.8041019963285974e-14, 2.9723155447089933e-14, 3.129353531005888e-14, 3.251796163324624e-14,
3.3198839487612773e-14, 3.329527690685666e-14, 3.313155691238456e-14, 3.289013852154548e-14,
3.2458917188506916e-14, 3.060684277937575e-14, 3.2660349473783173e-14, 2.957419109657689e-14,
2.518894321396672e-14, 1.734560485857344e-14, 9.902860761605233e-15, 7.219176385099358e-15,
6.079565990401311e-15, 5.828373065963427e-15, 7.20580801091692e-15, 7.561924351387493e-15,
7.621152352332206e-15, 6.8859886780643254e-15, 5.629181047471162e-15, 3.679727598966185e-15,
2.7555869742500355e-15, 2.4810133942597675e-15, 2.2160080532403624e-15, 2.1440626024765557e-15,
2.33873070799544e-15, 2.557317929858713e-15, 3.039839048226572e-15, 4.8337165515610065e-15,
5.4647431818257436e-15, 5.229187813711269e-15, 4.510768525811313e-15, 3.3213473130607794e-15,
2.2602577027996455e-15, 1.969576495866441e-15, 1.5179853954188527e-15, 1.2953988551200156e-15,
1.1304672156251838e-15, 9.10004390675213e-16, 8.432919922183503e-16, 7.849224069008326e-16,
7.827568196032024e-16, 9.000514440646232e-16, 1.3025926460013665e-15, 1.5444108938497558e-15,
1.8795594063060786e-15, 1.7796130169921014e-15, 1.5938159865046653e-15, 1.1585522355108287e-15,
8.507044444633358e-16, 7.625404663756823e-16, 8.14510750925789e-16, 9.047944693473188e-16,
9.636431901702084e-16, 9.298633899602105e-16, 8.349739503637023e-16, 7.482901278066085e-16,
6.240794767134268e-16, 5.00652535687506e-16, 3.553373263685851e-16, 2.0344217706119682e-16,
1.4267522642294203e-16, 8.980016576743517e-17, 2.9829068181832594e-17, 1.4861959129014824e-17,
7.404482113326137e-18]
), # m/W
# SSMF Raman coefficient profile
'g0': array(
[0.00000000e+00, 1.12351610e-05, 3.47838074e-05, 5.79356636e-05, 8.06921680e-05, 9.79845709e-05, 1.10454361e-04,
1.18735302e-04, 1.24736889e-04, 1.30110053e-04, 1.41001273e-04, 1.46383247e-04, 1.57011792e-04, 1.70765865e-04,
1.88408911e-04, 2.05914127e-04, 2.24074028e-04, 2.47508283e-04, 2.77729174e-04, 3.08044243e-04, 3.34764439e-04,
3.56481704e-04, 3.77127256e-04, 3.96269124e-04, 4.10955175e-04, 4.18718761e-04, 4.19511263e-04, 4.17025384e-04,
4.13565369e-04, 4.07726048e-04, 3.83671291e-04, 4.08564283e-04, 3.69571936e-04, 3.14442090e-04, 2.16074535e-04,
1.23097823e-04, 8.95457457e-05, 7.52470400e-05, 7.19806145e-05, 8.87961158e-05, 9.30812065e-05, 9.37058268e-05,
8.45719619e-05, 6.90585286e-05, 4.50407159e-05, 3.36521245e-05, 3.02292475e-05, 2.69376939e-05, 2.60020897e-05,
2.82958958e-05, 3.08667558e-05, 3.66024657e-05, 5.80610307e-05, 6.54797937e-05, 6.25022715e-05, 5.37806442e-05,
3.94996621e-05, 2.68120644e-05, 2.33038554e-05, 1.79140757e-05, 1.52472424e-05, 1.32707565e-05, 1.06541760e-05,
9.84649374e-06, 9.13999627e-06, 9.08971012e-06, 1.04227525e-05, 1.50419271e-05, 1.77838232e-05, 2.15810815e-05,
2.03744008e-05, 1.81939341e-05, 1.31862121e-05, 9.65352116e-06, 8.62698322e-06, 9.18688016e-06, 1.01737784e-05,
1.08017817e-05, 1.03903588e-05, 9.30040333e-06, 8.30809173e-06, 6.90650401e-06, 5.52238029e-06, 3.90648708e-06,
2.22908227e-06, 1.55796177e-06, 9.77218716e-07, 3.23477236e-07, 1.60602454e-07, 7.97306386e-08]
), # [1 / (W m)]
# Note the non-uniform spacing of this range; this is required for properly capturing the Raman peak shape.
'frequency_offset': array([
0., 0.5, 1., 1.5, 2., 2.5, 3., 3.5, 4., 4.5, 5., 5.5, 6., 6.5, 7., 7.5, 8., 8.5, 9., 9.5, 10., 10.5, 11., 11.5,
12., 12.5, 12.75, 13., 13.25, 13.5, 14., 14.5, 14.75, 15., 15.5, 16., 16.5, 17., 17.5, 18., 18.25, 18.5, 18.75,
19., 19.5, 20., 20.5, 21., 21.5, 22., 22.5, 23., 23.5, 24., 24.5, 25., 25.5, 26., 26.5, 27., 27.5, 28., 28.5,
29., 29.5, 30., 30.5, 31., 31.5, 32., 32.5, 33., 33.5, 34., 34.5, 35., 35.5, 36., 36.5, 37., 37.5, 38., 38.5,
39., 39.5, 40., 40.5, 41., 41.5, 42.]) * 1e12, # [Hz]
# Raman profile reference frequency
'reference_frequency': 206.184634112792e12, # [Hz] (1454 nm)
# Raman profile reference effective area
'reference_effective_area': 75.74659443542413e-12 # [m^2] (@1454 nm)
}
class RamanGainCoefficient(namedtuple('RamanGainCoefficient', 'normalized_gamma_raman frequency_offset')):
""" Raman Gain Coefficient Parameters
Based on:
Andrea DAmico, Bruno Correia, Elliot London, Emanuele Virgillito, Giacomo Borraccini, Antonio Napoli,
and Vittorio Curri, "Scalable and Disaggregated GGN Approximation Applied to a C+L+S Optical Network,"
J. Lightwave Technol. 40, 3499-3511 (2022)
Section III.D
"""
class FiberParams(Parameters):
def __init__(self, **kwargs):
try:
self._length = convert_length(kwargs['length'], kwargs['length_units'])
# fixed attenuator for padding
self._att_in = kwargs.get('att_in', 0)
# if not defined in the network json connector loss in/out
# the None value will be updated in network.py[build_network]
# with default values from eqpt_config.json[Spans]
self._con_in = kwargs.get('con_in')
self._con_out = kwargs.get('con_out')
# Reference frequency (unique for all parameters: beta2, beta3, gamma, effective_area)
if 'ref_wavelength' in kwargs:
self._ref_wavelength = kwargs['ref_wavelength']
self._ref_frequency = c / self._ref_wavelength
elif 'ref_frequency' in kwargs:
self._ref_frequency = kwargs['ref_frequency']
self._ref_wavelength = c / self._ref_frequency
else:
self._ref_wavelength = 1550e-9 # conventional central C band wavelength [m]
self._ref_frequency = c / self._ref_wavelength
# Chromatic Dispersion
if 'dispersion_per_frequency' in kwargs:
# Frequency-dependent dispersion
self._dispersion = asarray(kwargs['dispersion_per_frequency']['value']) # s/m/m
self._f_dispersion_ref = asarray(kwargs['dispersion_per_frequency']['frequency']) # Hz
self._dispersion_slope = None
elif 'dispersion' in kwargs:
# Single value dispersion
self._dispersion = asarray(kwargs['dispersion']) # s/m/m
self._dispersion_slope = kwargs.get('dispersion_slope') # s/m/m/m
self._f_dispersion_ref = asarray(self._ref_frequency) # Hz
else:
# Default single value dispersion
self._dispersion = asarray(1.67e-05) # s/m/m
self._dispersion_slope = None
self._f_dispersion_ref = asarray(self.ref_frequency) # Hz
# Effective Area and Nonlinear Coefficient
self._effective_area = kwargs.get('effective_area') # m^2
self._n1 = 1.468
self._core_radius = 4.2e-6 # m
self._n2 = 2.6e-20 # m^2/W
if self._effective_area is not None:
default_gamma = 2 * pi * self._n2 / (self._ref_wavelength * self._effective_area)
self._gamma = kwargs.get('gamma', default_gamma) # 1/W/m
elif 'gamma' in kwargs:
self._gamma = kwargs['gamma'] # 1/W/m
self._effective_area = 2 * pi * self._n2 / (self._ref_wavelength * self._gamma) # m^2
else:
self._effective_area = 83e-12 # m^2
self._gamma = 2 * pi * self._n2 / (self._ref_wavelength * self._effective_area) # 1/W/m
self._contrast = 0.5 * (c / (2 * pi * self._ref_frequency * self._core_radius * self._n1) * exp(
pi * self._core_radius ** 2 / self._effective_area)) ** 2
# Raman Gain Coefficient
raman_coefficient = kwargs.get('raman_coefficient')
if raman_coefficient is None:
self._raman_reference_frequency = DEFAULT_RAMAN_COEFFICIENT['reference_frequency']
frequency_offset = asarray(DEFAULT_RAMAN_COEFFICIENT['frequency_offset'])
gamma_raman = asarray(DEFAULT_RAMAN_COEFFICIENT['gamma_raman'])
stokes_wave = self._raman_reference_frequency - frequency_offset
normalized_gamma_raman = gamma_raman / self._raman_reference_frequency # 1 / m / W / Hz
self._g0 = gamma_raman / self.effective_area_overlap(stokes_wave, self._raman_reference_frequency)
else:
self._raman_reference_frequency = raman_coefficient['reference_frequency']
frequency_offset = asarray(raman_coefficient['frequency_offset'])
stokes_wave = self._raman_reference_frequency - frequency_offset
self._g0 = asarray(raman_coefficient['g0'])
gamma_raman = self._g0 * self.effective_area_overlap(stokes_wave, self._raman_reference_frequency)
normalized_gamma_raman = gamma_raman / self._raman_reference_frequency # 1 / m / W / Hz
# Raman gain coefficient array of the frequency offset constructed such that positive frequency values
# represent a positive power transfer from higher frequency and vice versa
frequency_offset = append(-flip(frequency_offset[1:]), frequency_offset)
normalized_gamma_raman = append(- flip(normalized_gamma_raman[1:]), normalized_gamma_raman)
self._raman_coefficient = RamanGainCoefficient(normalized_gamma_raman, frequency_offset)
# Polarization Mode Dispersion
self._pmd_coef = kwargs['pmd_coef'] # s/sqrt(m)
self._pmd_coef_defined = kwargs.get('pmd_coef_defined', kwargs['pmd_coef'] is True)
# Loss Coefficient
if isinstance(kwargs['loss_coef'], dict):
self._loss_coef = asarray(kwargs['loss_coef']['value']) * 1e-3 # lineic loss dB/m
self._f_loss_ref = asarray(kwargs['loss_coef']['frequency']) # Hz
else:
self._loss_coef = asarray(kwargs['loss_coef']) * 1e-3 # lineic loss dB/m
self._f_loss_ref = asarray(self._ref_frequency) # Hz
# Lumped Losses
self._lumped_losses = kwargs['lumped_losses'] if 'lumped_losses' in kwargs else array([])
self._latency = self._length / (c / self._n1) # s
except KeyError as e:
raise ParametersError(f'Fiber configurations json must include {e}. Configuration: {kwargs}')
@property
def length(self):
return self._length
@length.setter
def length(self, length):
"""length must be in m"""
self._length = length
@property
def att_in(self):
return self._att_in
@att_in.setter
def att_in(self, att_in):
self._att_in = att_in
@property
def con_in(self):
return self._con_in
@con_in.setter
def con_in(self, con_in):
self._con_in = con_in
@property
def con_out(self):
return self._con_out
@property
def lumped_losses(self):
return self._lumped_losses
@con_out.setter
def con_out(self, con_out):
self._con_out = con_out
@property
def dispersion(self):
return self._dispersion
@property
def f_dispersion_ref(self):
return self._f_dispersion_ref
@property
def dispersion_slope(self):
return self._dispersion_slope
@property
def gamma(self):
return self._gamma
def effective_area_scaling(self, frequency):
V = 2 * pi * frequency / c * self._core_radius * self._n1 * sqrt(2 * self._contrast)
w = self._core_radius / sqrt(log(V))
return asarray(pi * w ** 2)
def effective_area_overlap(self, frequency_stokes_wave, frequency_pump):
effective_area_stokes_wave = self.effective_area_scaling(frequency_stokes_wave)
effective_area_pump = self.effective_area_scaling(frequency_pump)
return squeeze(outer(effective_area_stokes_wave, ones(effective_area_pump.size)) + outer(
ones(effective_area_stokes_wave.size), effective_area_pump)) / 2
def gamma_scaling(self, frequency):
return asarray(2 * pi * self._n2 * frequency / (c * self.effective_area_scaling(frequency)))
@property
def pmd_coef(self):
return self._pmd_coef
@property
def pmd_coef_defined(self):
return self._pmd_coef_defined
@property
def ref_wavelength(self):
return self._ref_wavelength
@property
def ref_frequency(self):
return self._ref_frequency
@property
def loss_coef(self):
return self._loss_coef
@property
def f_loss_ref(self):
return self._f_loss_ref
@property
def raman_coefficient(self):
return self._raman_coefficient
@property
def latency(self):
return self._latency
def asdict(self):
dictionary = super().asdict()
dictionary['loss_coef'] = self.loss_coef * 1e3
dictionary['length_units'] = 'm'
if len(self.lumped_losses) == 0:
dictionary.pop('lumped_losses')
if not self.raman_coefficient:
dictionary.pop('raman_coefficient')
else:
raman_frequency_offset = \
self.raman_coefficient.frequency_offset[self.raman_coefficient.frequency_offset >= 0]
dictionary['raman_coefficient'] = {'g0': self._g0.tolist(),
'frequency_offset': raman_frequency_offset.tolist(),
'reference_frequency': self._raman_reference_frequency}
return dictionary
class EdfaParams:
default_values = {
'f_min': None,
'f_max': None,
'multi_band': None,
'bands': None,
'type_variety': '',
'type_def': '',
'gain_flatmax': None,
'gain_min': None,
'p_max': None,
'nf_model': None,
'dual_stage_model': None,
'preamp_variety': None,
'booster_variety': None,
'nf_min': None,
'nf_max': None,
'nf_coef': None,
'nf0': None,
'nf_fit_coeff': None,
'nf_ripple': 0,
'dgt': None,
'gain_ripple': 0,
'tilt_ripple': 0,
'f_ripple_ref': None,
'out_voa_auto': False,
'allowed_for_design': False,
'raman': False,
'pmd': 0,
'pdl': 0,
'advance_configurations_from_json': None
}
def __init__(self, **params):
try:
self.type_variety = params['type_variety']
self.type_def = params['type_def']
# Bandwidth
self.f_min = params['f_min']
self.f_max = params['f_max']
self.bandwidth = self.f_max - self.f_min if self.f_max and self.f_min else None
self.f_cent = (self.f_max + self.f_min) / 2 if self.f_max and self.f_min else None
self.f_ripple_ref = params['f_ripple_ref']
self.bands = [{'f_min': params['f_min'],
'f_max': params['f_max']}]
# Gain
self.gain_flatmax = params['gain_flatmax']
self.gain_min = params['gain_min']
gain_ripple = params['gain_ripple']
if gain_ripple == 0:
self.gain_ripple = asarray([0, 0])
self.f_ripple_ref = asarray([self.f_min, self.f_max])
else:
self.gain_ripple = asarray(gain_ripple)
if self.f_ripple_ref is not None:
if (self.f_ripple_ref[0] != self.f_min) or (self.f_ripple_ref[-1] != self.f_max):
raise ParametersError("The reference ripple frequency maximum and minimum have to coincide "
"with the EDFA frequency maximum and minimum.")
elif self.gain_ripple.size != self.f_ripple_ref.size:
raise ParametersError("The reference ripple frequency and the gain ripple must have the same "
"size.")
else:
self.f_ripple_ref = linspace(self.f_min, self.f_max, self.gain_ripple.size)
tilt_ripple = params['tilt_ripple']
if tilt_ripple == 0:
self.tilt_ripple = full(self.gain_ripple.size, 0)
else:
self.tilt_ripple = asarray(tilt_ripple)
if self.tilt_ripple.size != self.gain_ripple.size:
raise ParametersError("The tilt ripple and the gain ripple must have the same size.")
# Power
self.p_max = params['p_max']
# Noise Figure
self.nf_model = params['nf_model']
self.nf_min = params['nf_min']
self.nf_max = params['nf_max']
self.nf_coef = params['nf_coef']
self.nf0 = params['nf0']
self.nf_fit_coeff = params['nf_fit_coeff']
nf_ripple = params['nf_ripple']
if nf_ripple == 0:
self.nf_ripple = full(self.gain_ripple.size, 0)
else:
self.nf_ripple = asarray(nf_ripple)
if self.nf_ripple.size != self.gain_ripple.size:
raise ParametersError(
"The noise figure ripple and the gain ripple must have the same size. %s, %s",
self.nf_ripple.size, self.gain_ripple.size)
# VOA
self.out_voa_auto = params['out_voa_auto']
# Dual Stage
self.dual_stage_model = params['dual_stage_model']
if self.dual_stage_model is not None:
# Preamp
self.preamp_variety = params['preamp_variety']
self.preamp_type_def = params['preamp_type_def']
self.preamp_nf_model = params['preamp_nf_model']
self.preamp_nf_fit_coeff = params['preamp_nf_fit_coeff']
self.preamp_gain_min = params['preamp_gain_min']
self.preamp_gain_flatmax = params['preamp_gain_flatmax']
# Booster
self.booster_variety = params['booster_variety']
self.booster_type_def = params['booster_type_def']
self.booster_nf_model = params['booster_nf_model']
self.booster_nf_fit_coeff = params['booster_nf_fit_coeff']
self.booster_gain_min = params['booster_gain_min']
self.booster_gain_flatmax = params['booster_gain_flatmax']
# Others
self.pmd = params['pmd']
self.pdl = params['pdl']
self.raman = params['raman']
self.dgt = params['dgt']
self.advance_configurations_from_json = params['advance_configurations_from_json']
# Design
self.allowed_for_design = params['allowed_for_design']
except KeyError as e:
raise ParametersError(f'Edfa configurations json must include {e}. Configuration: {params}')
def update_params(self, kwargs):
for k, v in kwargs.items():
setattr(self, k, v)
class EdfaOperational:
default_values = {
'gain_target': None,
'delta_p': None,
'out_voa': None,
'in_voa': 0,
'tilt_target': None
}
def __init__(self, **operational):
self.update_attr(operational)
def update_attr(self, kwargs):
clean_kwargs = {k: v for k, v in kwargs.items() if v != ''}
for k, v in self.default_values.items():
setattr(self, k, clean_kwargs.get(k, v))
def __repr__(self):
return (f'{type(self).__name__}('
f'gain_target={self.gain_target!r}, '
f'tilt_target={self.tilt_target!r})')
DEFAULT_EDFA_CONFIG = {
"nf_ripple": [
0.0
],
"gain_ripple": [
0.0
],
"f_min": 191.275e12,
"f_max": 196.125e12,
"dgt": [
1.0, 1.017807767853702, 1.0356155337864215, 1.0534217504465226, 1.0712204022764056, 1.0895983485572227,
1.108555289615659, 1.1280891949729075, 1.1476135933863398, 1.1672278304018044, 1.1869318618366975,
1.2067249615595257, 1.2264996957264114, 1.2428104897182262, 1.2556591482982988, 1.2650555289898042,
1.2744470198196236, 1.2838336236692311, 1.2932153453410835, 1.3040618749785347, 1.316383926863083,
1.3301807335621048, 1.3439818461440451, 1.3598972673004606, 1.3779439775587023, 1.3981208704326855,
1.418273806730323, 1.4340878115214444, 1.445565137158368, 1.45273959485914, 1.4599103316162523,
1.4670307626366115, 1.474100442252211, 1.48111939735681, 1.488134243479226, 1.495145456062699,
1.502153039909686, 1.5097346239790443, 1.5178910621476225, 1.5266220576235803, 1.5353620432989845,
1.545374152761467, 1.5566577309558969, 1.569199764184379, 1.5817353179379183, 1.5986915141218316,
1.6201194134191075, 1.6460167077689267, 1.6719047669939942, 1.6918150918099673, 1.7057507692361864,
1.7137640932265894, 1.7217732861435076, 1.7297783508684146, 1.737780757913635, 1.7459181197626403,
1.7541903672600494, 1.7625959636196327, 1.7709972329654864, 1.7793941781790852, 1.7877868031023945,
1.7961751115773796, 1.8045606557581335, 1.8139629377087627, 1.824381436842932, 1.835814081380705,
1.847275503201129, 1.862235672444246, 1.8806927939516411, 1.9026104247588487, 1.9245345552113182,
1.9482128147680253, 1.9736443063300082, 2.0008103857988204, 2.0279625371819305, 2.055100772005235,
2.082225099873648, 2.1183028432496016, 2.16337565384239, 2.2174389328192197, 2.271520771371253,
2.322373696229342, 2.3699990328716107, 2.414398437185221, 2.4587748041127506, 2.499446286796604,
2.5364027376452056, 2.5696460593920065, 2.602860350286428, 2.630396440815385, 2.6521732021128046,
2.6681935771243177, 2.6841217449620203, 2.6947834587664494, 2.705443819238505, 2.714526681131686
]
}
class MultiBandParams:
default_values = {
'bands': [],
'type_variety': '',
'type_def': None,
'allowed_for_design': False
}
def __init__(self, **params):
try:
self.update_attr(params)
except KeyError as e:
raise ParametersError(f'Multiband configurations json must include {e}. Configuration: {params}')
def update_attr(self, kwargs):
clean_kwargs = {k: v for k, v in kwargs.items() if v != ''}
for k, v in self.default_values.items():
# use deepcopy to avoid sharing same object amongst all instance when v is a list or a dict!
if isinstance(v, (list, dict)):
setattr(self, k, clean_kwargs.get(k, deepcopy(v)))
else:
setattr(self, k, clean_kwargs.get(k, v))
class TransceiverParams:
def __init__(self, **params):
self.design_bands = params.get('design_bands', [])
self.per_degree_design_bands = params.get('per_degree_design_bands', {})
@dataclass
class FrequencyBand:
"""Frequency band
"""
f_min: float
f_max: float
DEFAULT_BANDS_DEFINITION = {
"LBAND": FrequencyBand(f_min=187e12, f_max=189e12),
"CBAND": FrequencyBand(f_min=191.3e12, f_max=196.0e12)
}
# use this definition to index amplifiers'element of a multiband amplifier.
# this is not the design band
def find_band_name(band: FrequencyBand) -> str:
"""return the default band name (CBAND, LBAND, ...) that corresponds to the band frequency range
Use the band center frequency: if center frequency is inside the band then returns CBAND.
This is to flexibly encompass all kind of bands definitions.
returns the first matching band name.
"""
for band_name, frequency_range in DEFAULT_BANDS_DEFINITION.items():
center_frequency = (band.f_min + band.f_max) / 2
if center_frequency >= frequency_range.f_min and center_frequency <= frequency_range.f_max:
return band_name
return 'unknown_band'

735
gnpy/core/science_utils.py Normal file
View File

@@ -0,0 +1,735 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# SPDX-License-Identifier: BSD-3-Clause
# gnpy.core.science_utils: Solver definitions to calculate the Raman effect and the nonlinear interference noise
# Copyright (C) 2025 Telecom Infra Project and GNPy contributors
# see AUTHORS.rst for a list of contributors
"""
gnpy.core.science_utils
=======================
Solver definitions to calculate the Raman effect and the nonlinear interference noise
The solvers take as input instances of the spectral information, the fiber and the simulation parameters
"""
from numpy import interp, pi, zeros, cos, array, append, ones, exp, arange, sqrt, trapz, arcsinh, clip, abs, sum, \
concatenate, flip, outer, inner, transpose, max, format_float_scientific, diag, sort, unique, argsort, cumprod, \
polyfit, log, reshape, swapaxes, full, nan, cumsum
from logging import getLogger
from scipy.constants import k, h
from scipy.interpolate import interp1d
from math import isclose, factorial
from gnpy.core.utils import db2lin, lin2db
from gnpy.core.exceptions import EquipmentConfigError, ParametersError
from gnpy.core.parameters import SimParams
from gnpy.core.info import SpectralInformation
logger = getLogger(__name__)
sim_params = SimParams()
def raised_cosine(frequency, channel_frequency, channel_baud_rate, channel_roll_off):
"""Returns a unitary raised cosine profile for the given parame
:param frequency: numpy array of frequencies in Hz for the resulting raised cosine
:param channel_frequency: channel frequencies in Hz
:param channel_baud_rate: channel baud rate in Hz
:param channel_roll_off: channel roll off
"""
raised_cosine_mask = zeros(frequency.size)
base_frequency = frequency - channel_frequency
ts = 1 / channel_baud_rate
pass_band = (1 - channel_roll_off) * channel_baud_rate / 2
stop_band = (1 + channel_roll_off) * channel_baud_rate / 2
flat_condition = (abs(base_frequency) <= pass_band) == 1
cosine_condition = (pass_band < abs(base_frequency)) * (abs(base_frequency) < stop_band) == 1
raised_cosine_mask[flat_condition] = 1
raised_cosine_mask[cosine_condition] = \
0.5 * (1 + cos(pi * ts / channel_roll_off * (abs(base_frequency[cosine_condition]) - pass_band)))
return raised_cosine_mask
class StimulatedRamanScattering:
def __init__(self, power_profile, loss_profile, frequency, z):
"""
:params power_profile: power profile matrix along frequency and z [W]
:params loss_profile: power profile matrix along frequency and z [linear units]
:params frequency: channels frequencies array [Hz]
:params z: positions array [m]
"""
self.power_profile = power_profile
self.loss_profile = loss_profile
# Field loss profile matrix along frequency and z
self.rho = sqrt(loss_profile)
self.frequency = frequency
self.z = z
class RamanSolver:
"""This class contains the methods to calculate the Raman scattering effect."""
@staticmethod
def _create_lumped_losses(z, lumped_losses, z_lumped_losses):
lumped_losses = concatenate((lumped_losses, ones(z.size)))
z, unique_indices = unique(concatenate((z_lumped_losses, z)), return_index=True)
order = argsort(z)
lumped_losses = (lumped_losses[unique_indices])[order]
z = z[order]
return z, lumped_losses
@staticmethod
def calculate_attenuation_profile(spectral_info: SpectralInformation, fiber):
"""Evaluates the attenuation profile along the z axis for all the frequency propagating in the
fiber without considering the stimulated Raman scattering.
"""
# z array definition
z = array([0, fiber.params.length])
# Lumped losses array definition
z, lumped_losses = RamanSolver._create_lumped_losses(z, fiber.lumped_losses, fiber.z_lumped_losses)
lumped_loss_acc = cumprod(lumped_losses)
frequency = spectral_info.frequency
alpha = fiber.alpha(frequency)
loss_profile = exp(- outer(alpha, z)) * lumped_loss_acc
power_profile = outer(spectral_info.signal, ones(z.size)) * loss_profile
return StimulatedRamanScattering(power_profile, loss_profile, spectral_info.frequency, z)
@staticmethod
def calculate_stimulated_raman_scattering(spectral_info: SpectralInformation, fiber):
"""Evaluates the Raman profile along the z axis for all the frequency propagated in the fiber
including the Raman pumps co- and counter-propagating
"""
logger.debug('Start computing fiber Stimulated Raman Scattering')
if sim_params.raman_params.flag:
# Raman parameters
z_resolution = sim_params.raman_params.result_spatial_resolution
z_step = sim_params.raman_params.solver_spatial_resolution
z = append(arange(0, fiber.params.length, z_step), fiber.params.length)
z_final = append(arange(0, fiber.params.length, z_resolution), fiber.params.length)
z_final = sort(unique(concatenate((fiber.z_lumped_losses, z_final))))
# Lumped losses array definition
z, lumped_losses = RamanSolver._create_lumped_losses(z, fiber.lumped_losses, fiber.z_lumped_losses)
if hasattr(fiber, 'raman_pumps'):
# TODO: verify co-propagating pumps computation and in general unsorted frequency
# Co-propagating spectrum definition
co_raman_pump_power = array([pump.power for pump in fiber.raman_pumps
if pump.propagation_direction == 'coprop'])
co_raman_pump_frequency = array([pump.frequency for pump in fiber.raman_pumps
if pump.propagation_direction == 'coprop'])
co_power = concatenate((spectral_info.signal, co_raman_pump_power))
co_frequency = concatenate((spectral_info.frequency, co_raman_pump_frequency))
# Counter-propagating spectrum definition
cnt_power = array([pump.power for pump in fiber.raman_pumps
if pump.propagation_direction == 'counterprop'])
cnt_frequency = array([pump.frequency for pump in fiber.raman_pumps
if pump.propagation_direction == 'counterprop'])
# Co-propagating profile initialization
co_power_profile = zeros([co_frequency.size, z.size])
if co_frequency.size:
co_cr = fiber.cr(co_frequency)
co_alpha = fiber.alpha(co_frequency)
co_power_profile = \
RamanSolver.calculate_unidirectional_stimulated_raman_scattering(co_power, co_alpha, co_cr, z,
lumped_losses)
# Counter-propagating profile initialization
cnt_power_profile = zeros([cnt_frequency.size, z.size])
if cnt_frequency.size:
cnt_cr = fiber.cr(cnt_frequency)
cnt_alpha = fiber.alpha(cnt_frequency)
cnt_power_profile = flip(
RamanSolver.calculate_unidirectional_stimulated_raman_scattering(cnt_power, cnt_alpha, cnt_cr,
z[-1] - flip(z),
flip(lumped_losses)), axis=1)
# Co-propagating and Counter-propagating Profile Computation
if co_frequency.size and cnt_frequency.size:
co_power_profile, cnt_power_profile = \
RamanSolver.iterative_algorithm(co_power_profile, cnt_power_profile,
co_frequency, cnt_frequency, z, fiber, lumped_losses)
# Complete Power Profile
power_profile = concatenate((co_power_profile, cnt_power_profile), axis=0)
# Complete Loss Profile
co_loss_profile = co_power_profile / outer(co_power, ones(z.size))
cnt_loss_profile = cnt_power_profile / outer(cnt_power, ones(z.size))
loss_profile = concatenate((co_loss_profile, cnt_loss_profile), axis=0)
# Complete frequency
frequency = concatenate((co_frequency, cnt_frequency))
else:
# Without Raman pumps
alpha = fiber.alpha(spectral_info.frequency)
cr = fiber.cr(spectral_info.frequency)
# Power profile
power_profile = (
RamanSolver.calculate_unidirectional_stimulated_raman_scattering(spectral_info.signal, alpha, cr, z,
lumped_losses))
# Loss profile
loss_profile = power_profile / outer(spectral_info.signal, ones(z.size))
frequency = spectral_info.frequency
power_profile = interp1d(z, power_profile, axis=1)(z_final)
loss_profile = interp1d(z, loss_profile, axis=1)(z_final)
stimulated_raman_scattering = StimulatedRamanScattering(power_profile, loss_profile, frequency, z_final)
else:
stimulated_raman_scattering = \
RamanSolver.calculate_attenuation_profile(spectral_info, fiber)
return stimulated_raman_scattering
@staticmethod
def calculate_spontaneous_raman_scattering(spectral_info: SpectralInformation, srs: StimulatedRamanScattering,
fiber):
"""Evaluates the Raman profile along the z axis for all the frequency propagated in the fiber
including the Raman pumps co- and counter-propagating.
"""
logger.debug('Start computing fiber Spontaneous Raman Scattering')
z = srs.z
baud_rate = spectral_info.baud_rate
frequency = spectral_info.frequency
channels_loss = srs.loss_profile[:spectral_info.number_of_channels, :]
# calculate ase power
ase = zeros(spectral_info.number_of_channels)
cr = fiber.cr(srs.frequency)[:spectral_info.number_of_channels, spectral_info.number_of_channels:]
for i, pump in enumerate(fiber.raman_pumps):
pump_power = srs.power_profile[spectral_info.number_of_channels + i, :]
df = pump.frequency - frequency
eta = - 1 / (1 - exp(h * df / (k * fiber.temperature)))
integral = trapz(pump_power / channels_loss, z, axis=1)
ase += 2 * h * baud_rate * frequency * (1 + eta) * cr[:, i] * (df > 0) * integral # 2 factor for double pol
return ase
@staticmethod
def calculate_unidirectional_stimulated_raman_scattering(power_in, alpha, cr, z, lumped_losses):
"""Solves the Raman equation
:param power_in: launch power array
:param alpha: loss coefficient array
:param cr: Raman efficiency coefficients matrix
:param z: z position array
:param lumped_losses: concentrated losses array along the fiber span
:return: power profile matrix
"""
if sim_params.raman_params.method == 'perturbative':
if sim_params.raman_params.order > 4:
raise ValueError(f'Order {sim_params.raman_params.order} not implemented in Raman Solver.')
z_lumped_losses = append(z[lumped_losses != 1], z[-1])
llumped_losses = append(1, lumped_losses[lumped_losses != 1])
power = outer(power_in, ones(z.size))
last_position = 0
z_indices = arange(0, z.size)
for z_lumped_loss, lumped_loss in zip(z_lumped_losses, llumped_losses):
if last_position < z[-1]:
interval = z_indices[(z >= last_position) * (z <= z_lumped_loss) == 1]
z_interval = z[interval] - last_position
dz = z_interval[1:] - z_interval[:-1]
last_position = z[interval][-1]
p0 = power_in * lumped_loss
power_interval = outer(p0, ones(z_interval.size))
alphaz = outer(alpha, z_interval)
expz = exp(- alphaz)
eff_length = 1 / outer(alpha, ones(z_interval.size)) * (1 - expz)
crpz = transpose(ones([z_interval.size, cr.shape[0], cr.shape[1]]) * cr * p0, (1, 2, 0))
exponent = - alphaz
if sim_params.raman_params.order >= 1:
gamma1 = sum(crpz * eff_length, 1)
exponent += gamma1
if sim_params.raman_params.order >= 2:
z_integrand = expz * gamma1
z_integral = cumsum((z_integrand[:, :-1] + z_integrand[:, 1:]) / 2 * dz, 1)
gamma2 = zeros(gamma1.shape)
gamma2[:, 1:] = sum(crpz[:, :, 1:] * z_integral, 1)
exponent += gamma2
if sim_params.raman_params.order >= 3:
z_integrand = expz * (gamma2 + 1/2 * gamma1**2)
z_integral = cumsum((z_integrand[:, :-1] + z_integrand[:, 1:]) / 2 * dz, 1)
gamma3 = zeros(gamma1.shape)
gamma3[:, 1:] = sum(crpz[:, :, 1:] * z_integral, 1)
exponent += gamma3
if sim_params.raman_params.order >= 4:
z_integrand = expz * (gamma3 + gamma1 * gamma2 + 1/factorial(3) * gamma1**3)
z_integral = cumsum((z_integrand[:, :-1] + z_integrand[:, 1:]) / 2 * dz, 1)
gamma4 = zeros(gamma1.shape)
gamma4[:, 1:] = sum(crpz[:, :, 1:] * z_integral, 1)
exponent += gamma4
power_interval *= exp(exponent)
power[:, interval[1:]] = power_interval[:, 1:]
power_in = power_interval[:, -1]
elif sim_params.raman_params.method == 'numerical':
dz = z[1:] - z[:-1]
power = outer(power_in, ones(z.size))
for i in range(1, z.size):
power[:, i] = (power[:, i - 1] * (1 + (- alpha + sum(cr * power[:, i - 1], 1)) * dz[i - 1]) *
lumped_losses[i - 1])
else:
raise ValueError(f'Method {sim_params.raman_params.method} not implemented in Raman Solver.')
return power
@staticmethod
def iterative_algorithm(co_initial_guess_power, cnt_initial_guess_power, co_frequency, cnt_frequency, z, fiber,
lumped_losses):
"""Solves the Raman equation in case of both co- and counter-propagating frequencies
:param co_initial_guess_power: co-propagationg Raman first order derivative equation solution
:param cnt_initial_guess_power: counter-propagationg Raman first order derivative equation solution
:param co_frequency: co-propagationg frequencies
:param cnt_frequency: counter-propagationg frequencies
:param z: z position array
:param fiber: instance of gnpy.core.elements.Fiber or gnpy.core.elements.RamanFiber
:param lumped_losses: concentrated losses array along the fiber span
:return: co- and counter-propagatng power profile matrix
"""
logger.debug(' Start iterative algorithm')
residue = 1
residue_tol = 1e-6
accuracy = 1
accuracy_tol = 1e-3
iteration = 0
num_max_iter = 1000
prev_power = concatenate((co_initial_guess_power, cnt_initial_guess_power))
frequency = concatenate((co_frequency, cnt_frequency))
dz = z[1:] - z[:-1]
cr = fiber.cr(frequency)
alpha = fiber.alpha(frequency)
next_power = array(prev_power)
while residue > residue_tol and accuracy > accuracy_tol and iteration < num_max_iter:
iteration += 1
for i in range(1, z.size):
dpdz = - alpha + sum(cr * next_power[:, i - 1], 1)
next_power[:co_frequency.size, i] = \
next_power[:co_frequency.size, i - 1] * (1 + dpdz[:co_frequency.size] * dz[i - 1]) * \
lumped_losses[i - 1]
for i in range(1, z.size):
dpdz = - alpha + sum(cr * next_power[:, -i], 1)
next_power[co_frequency.size:, -i - 1] = \
next_power[co_frequency.size:, -i] * (1 + dpdz[co_frequency.size:] * dz[-i]) * \
lumped_losses[-i]
dpdz_num = (next_power[:co_frequency.size, 1:] - next_power[:co_frequency.size, :-1]) / dz
dpdz_exp = next_power[:co_frequency.size, :-1] * \
(- outer(alpha, ones(z.size)) + inner(cr, transpose(next_power)))[:co_frequency.size, :-1] * \
lumped_losses[:-1]
residue = max(abs((next_power - prev_power) / next_power))
accuracy = max(abs((dpdz_exp - dpdz_num) / dpdz_exp))
prev_power = array(next_power)
logger.debug(f' Iteration: {iteration} Accuracy: {format_float_scientific(accuracy, precision=3)}')
return next_power[:co_frequency.size, :], next_power[co_frequency.size:, :]
class NliSolver:
"""This class implements the NLI models.
Model and method can be specified in `sim_params.nli_params.method`.
List of implemented methods:
'gn_model_analytic': eq. 120 from arXiv:1209.0394
'ggn_spectrally_separated': eq. 21 from arXiv: 1710.02225
'ggn_approx': eq. 24-25 jlt:9741324
"""
SPM_WEIGHT = (16.0 / 27.0)
XPM_WEIGHT = 2 * (16.0 / 27.0)
@staticmethod
def effective_length(alpha, length):
"""The effective length identify the region in which the NLI has a significant contribution to
the signal degradation.
"""
return (1 - exp(- alpha * length)) / alpha
@staticmethod
def compute_nli(spectral_info: SpectralInformation, srs: StimulatedRamanScattering, fiber):
"""Compute NLI power generated by the WDM comb `*carriers` on the channel under test `carrier`
at the end of the fiber span.
"""
logger.debug('Start computing fiber NLI noise')
if 'gn_model_analytic' == sim_params.nli_params.method:
eta = NliSolver._gn_analytic(spectral_info, fiber)
cut_power = outer(spectral_info.signal, ones(spectral_info.number_of_channels))
pump_power = outer(ones(spectral_info.number_of_channels), spectral_info.signal)
nli_matrix = cut_power * pump_power ** 2 * eta
nli = sum(nli_matrix, 1)
elif 'ggn_spectrally_separated' in sim_params.nli_params.method:
if sim_params.nli_params.computed_channels is not None:
cut_indices = array(sim_params.nli_params.computed_channels) - 1
elif sim_params.nli_params.computed_number_of_channels is not None:
nb_ch_computed = sim_params.nli_params.computed_number_of_channels
nb_ch = len(spectral_info.channel_number)
cut_indices = array([round(i * (nb_ch - 1) / (nb_ch_computed - 1)) for i in range(0, nb_ch_computed)])
else:
cut_indices = array(spectral_info.channel_number) - 1
eta = NliSolver._ggn_spectrally_separated(cut_indices, spectral_info, fiber, srs)
# Interpolation over the channels not indicated as compted channels in simulation parameters
cut_power = outer(spectral_info.signal[cut_indices], ones(spectral_info.number_of_channels))
cut_frequency = spectral_info.frequency[cut_indices]
pump_power = outer(ones(cut_indices.size), spectral_info.signal)
cut_baud_rate = outer(spectral_info.baud_rate[cut_indices], ones(spectral_info.number_of_channels))
g_nli = eta * cut_power * pump_power**2 / cut_baud_rate
g_nli = sum(g_nli, 1)
g_nli = interp(spectral_info.frequency, cut_frequency, g_nli)
nli = spectral_info.baud_rate * g_nli # Local white noise
elif 'ggn_approx' in sim_params.nli_params.method:
if sim_params.nli_params.computed_channels is not None:
cut_indices = array(sim_params.nli_params.computed_channels) - 1
elif sim_params.nli_params.computed_number_of_channels is not None:
nb_ch_computed = sim_params.nli_params.computed_number_of_channels
nb_ch = len(spectral_info.channel_number)
cut_indices = array([round(i * (nb_ch - 1) / (nb_ch_computed - 1)) for i in range(0, nb_ch_computed)])
else:
cut_indices = array(spectral_info.channel_number) - 1
eta = NliSolver._ggn_approx(cut_indices, spectral_info, fiber, srs)
# Interpolation over the channels not indicated as computed channels in simulation parameters
cut_power = outer(spectral_info.signal[cut_indices], ones(spectral_info.number_of_channels))
cut_frequency = spectral_info.frequency[cut_indices]
pump_power = outer(ones(cut_indices.size), spectral_info.signal)
cut_baud_rate = outer(spectral_info.baud_rate[cut_indices], ones(spectral_info.number_of_channels))
g_nli = eta * cut_power * pump_power ** 2 / cut_baud_rate
g_nli = sum(g_nli, 1)
g_nli = interp(spectral_info.frequency, cut_frequency, g_nli)
nli = spectral_info.baud_rate * g_nli # Local white noise
else:
raise ValueError(f'Method {sim_params.nli_params.method} not implemented.')
return nli
# Methods for computing GN-model eta matrix
@staticmethod
def _gn_analytic(spectral_info, fiber, spm_weight=SPM_WEIGHT, xpm_weight=XPM_WEIGHT):
"""Computes the nonlinear interference power evaluated at the fiber input.
The method uses eq. 120 from arXiv:1209.0394
"""
# Spectral Features
nch = spectral_info.number_of_channels
frequency = spectral_info.frequency
baud_rate = spectral_info.baud_rate
delta_frequency = spectral_info.df
# Physical fiber parameters
alpha = fiber.alpha(frequency)
beta2 = fiber.beta2(frequency)
gamma = outer(fiber.gamma(frequency), ones(nch))
length = fiber.params.length
identity = diag(ones(nch))
weight = spm_weight * identity + xpm_weight * (ones([nch, nch]) - identity)
effective_length = NliSolver.effective_length(alpha, length)
asymptotic_length = 1 / alpha
cut_baud_rate = outer(baud_rate, ones(nch))
pump_baud_rate = outer(ones(nch), baud_rate)
psi = NliSolver._psi(delta_frequency, baud_rate, beta2, effective_length, asymptotic_length)
eta_cut_central_frequency = gamma ** 2 * weight * psi / (cut_baud_rate * pump_baud_rate ** 2)
eta = cut_baud_rate * eta_cut_central_frequency # Local white noise
return eta
@staticmethod
def _psi(df, baud_rate, beta2, effective_length, asymptotic_length):
"""Calculates eq. 123 from `arXiv:1209.0394 <https://arxiv.org/abs/1209.0394>`__"""
cut_baud_rate = outer(baud_rate, ones(baud_rate.size))
cut_beta = outer(beta2, ones(baud_rate.size))
pump_baud_rate = baud_rate
pump_beta = outer(ones(baud_rate.size), beta2)
beta2 = (cut_beta + pump_beta) / 2
right_extreme = df + pump_baud_rate / 2
left_extreme = df - pump_baud_rate / 2
psi = (arcsinh(pi ** 2 * asymptotic_length * abs(beta2) * cut_baud_rate * right_extreme) -
arcsinh(pi ** 2 * asymptotic_length * abs(beta2) * cut_baud_rate * left_extreme)) / 2
psi *= effective_length ** 2 / (2 * pi * abs(beta2) * asymptotic_length)
return psi
# Methods for computing the GGN-model eta matrix
@staticmethod
def _ggn_spectrally_separated(cut_indices, spectral_info, fiber, srs, spm_weight=SPM_WEIGHT, xpm_weight=XPM_WEIGHT):
"""Computes the nonlinear interference power evaluated at the fiber input.
The method uses eq. 21 from arXiv: 1710.02225
"""
# Spectral Features
nch = spectral_info.number_of_channels
frequency = spectral_info.frequency
baud_rate = spectral_info.baud_rate
slot_width = spectral_info.slot_width
roll_off = spectral_info.roll_off
# Physical fiber parameters
alpha = fiber.alpha(frequency)
beta2 = fiber.beta2(frequency)
gamma = outer(fiber.gamma(frequency[cut_indices]), ones(nch))
identity = diag(ones(nch))
weight = spm_weight * identity + xpm_weight * (ones([nch, nch]) - identity)
weight = weight[cut_indices, :]
dispersion_tolerance = sim_params.nli_params.dispersion_tolerance
phase_shift_tolerance = sim_params.nli_params.phase_shift_tolerance
max_slot_width = max(slot_width)
delta_z = sim_params.raman_params.result_spatial_resolution
psi_cut_central_frequency = zeros([cut_indices.size, nch])
for i, cut_index in enumerate(cut_indices):
logger.debug(f'Start computing fiber NLI noise of cut: {cut_index + 1}')
cut_frequency = frequency[cut_index]
cut_baud_rate = baud_rate[cut_index]
cut_roll_off = roll_off[cut_index]
cut_number = cut_index + 1
cut_beta2 = beta2[cut_index]
cut_base_frequency = frequency - cut_frequency
cut_beta_coefficients = polyfit(cut_base_frequency, beta2, 2)
cut_beta3 = cut_beta_coefficients[1] / (2 * pi)
for pump_index in range(nch):
pump_frequency = frequency[pump_index]
pump_baud_rate = baud_rate[pump_index]
pump_roll_off = roll_off[pump_index]
pump_number = pump_index + 1
pump_alpha = alpha[pump_index]
dn = abs(pump_number - cut_number)
delta_f = abs(cut_frequency - pump_frequency)
k_tol = dispersion_tolerance * abs(alpha[pump_index])
phi_tol = phase_shift_tolerance / delta_z
f_cut_resolution = min(k_tol, phi_tol) / abs(cut_beta2) / (4 * pi ** 2 * (1 + dn) * max_slot_width)
f_pump_resolution = min(k_tol, phi_tol) / abs(cut_beta2) / (4 * pi ** 2 * max_slot_width)
if cut_index == pump_index: # SPM
psi_cut_central_frequency[i, pump_index] = \
NliSolver._generalized_psi(cut_frequency, cut_frequency, cut_baud_rate, cut_roll_off,
pump_frequency, pump_baud_rate, pump_roll_off, f_cut_resolution,
f_pump_resolution, srs, pump_alpha, cut_beta2, cut_beta3,
cut_frequency)
else: # XPM
frequency_offset_threshold = NliSolver._frequency_offset_threshold(cut_beta2, pump_baud_rate)
if abs(delta_f) <= frequency_offset_threshold:
psi_cut_central_frequency[i, pump_index] = \
NliSolver._generalized_psi(cut_frequency, cut_frequency, cut_baud_rate, cut_roll_off,
pump_frequency, pump_baud_rate, pump_roll_off, f_cut_resolution,
f_pump_resolution, srs, pump_alpha, cut_beta2, cut_beta3,
cut_frequency)
else:
psi_cut_central_frequency[i, pump_index] = \
NliSolver._fast_generalized_psi(cut_frequency, cut_frequency, cut_baud_rate, cut_roll_off,
pump_frequency, pump_baud_rate, pump_roll_off,
f_cut_resolution, srs, pump_alpha, cut_beta2, cut_beta3,
cut_frequency)
cut_baud_rate = outer(baud_rate[cut_indices], ones(nch))
pump_baud_rate = outer(ones(cut_indices.size), baud_rate)
eta_cut_central_frequency = \
gamma ** 2 * weight * psi_cut_central_frequency / (cut_baud_rate * pump_baud_rate ** 2)
eta = cut_baud_rate * eta_cut_central_frequency # Local white noise
return eta
@staticmethod
def _fast_generalized_psi(f_eval, cut_frequency, cut_baud_rate, cut_roll_off, pump_frequency, pump_baud_rate,
pump_roll_off, f_cut_resolution, srs, alpha, beta2, beta3, f_ref_beta):
"""Computes the generalized psi function similarly to the one used in the GN model."""
z = srs.z
rho_norm = srs.rho * exp(outer(alpha / 2, z))
rho_pump = interp1d(srs.frequency, rho_norm, axis=0)(pump_frequency)
f1_array = array([pump_frequency - (pump_baud_rate * (1 + pump_roll_off) / 2),
pump_frequency + (pump_baud_rate * (1 + pump_roll_off) / 2)])
f2_array = arange(cut_frequency, cut_frequency + (cut_baud_rate * (1 + cut_roll_off) / 2),
f_cut_resolution) # Only positive f2 is used since integrand_f2 is symmetric
integrand_f1 = zeros(f1_array.size)
for f1_index, f1 in enumerate(f1_array):
delta_beta = 4 * pi ** 2 * (f1 - f_eval) * (f2_array - f_eval) * (
beta2 + pi * beta3 * (f1 + f2_array - 2 * f_ref_beta))
integrand_f2 = NliSolver._generalized_rho_nli(delta_beta, rho_pump, z, alpha)
integrand_f1[f1_index] = 2 * trapz(integrand_f2, f2_array) # 2x since integrand_f2 is symmetric in f2
generalized_psi = 0.5 * sum(integrand_f1) * pump_baud_rate
return generalized_psi
@staticmethod
def _generalized_psi(f_eval, cut_frequency, cut_baud_rate, cut_roll_off, pump_frequency, pump_baud_rate,
pump_roll_off, f_cut_resolution, f_pump_resolution, srs, alpha, beta2, beta3, f_ref_beta):
"""Computes the generalized psi function similarly to the one used in the GN model."""
z = srs.z
rho_norm = srs.rho * exp(outer(alpha / 2, z))
rho_pump = interp1d(srs.frequency, rho_norm, axis=0)(pump_frequency)
f1_array = arange(pump_frequency - (pump_baud_rate * (1 + pump_roll_off) / 2),
pump_frequency + (pump_baud_rate * (1 + pump_roll_off) / 2),
f_pump_resolution)
f2_array = arange(cut_frequency - (cut_baud_rate * (1 + cut_roll_off) / 2),
cut_frequency + (cut_baud_rate * (1 + cut_roll_off) / 2),
f_cut_resolution)
rc1 = raised_cosine(f1_array, pump_frequency, pump_baud_rate, pump_roll_off)
integrand_f1 = zeros(f1_array.size)
for i in range(f1_array.size):
f3_array = f1_array[i] + f2_array - f_eval
rc2 = raised_cosine(f2_array, cut_frequency, cut_baud_rate, cut_roll_off)
rc3 = raised_cosine(f3_array, pump_frequency, pump_baud_rate, pump_roll_off)
delta_beta = 4 * pi ** 2 * (f1_array[i] - f_eval) * (f2_array - f_eval) * (
beta2 + pi * beta3 * (f1_array[i] + f2_array - 2 * f_ref_beta))
integrand_f2 = rc1[i] * rc2 * rc3 * NliSolver._generalized_rho_nli(delta_beta, rho_pump, z, alpha)
integrand_f1[i] = trapz(integrand_f2, f2_array)
generalized_psi = trapz(integrand_f1, f1_array)
return generalized_psi
@staticmethod
def _generalized_rho_nli(delta_beta, rho_pump, z, alpha):
w = 1j * delta_beta - alpha
generalized_rho_nli = (rho_pump[-1]**2 * exp(w * z[-1]) - rho_pump[0]**2 * exp(w * z[0])) / w
for z_ind in range(0, len(z) - 1):
derivative_rho = (rho_pump[z_ind + 1]**2 - rho_pump[z_ind]**2) / (z[z_ind + 1] - z[z_ind])
generalized_rho_nli -= derivative_rho * (exp(w * z[z_ind + 1]) - exp(w * z[z_ind])) / (w**2)
generalized_rho_nli = abs(generalized_rho_nli)**2
return generalized_rho_nli
@staticmethod
def _frequency_offset_threshold(beta2, symbol_rate):
k_ref = 5
beta2_ref = 21.3e-27
delta_f_ref = 50e9
rs_ref = 32e9
beta2 = abs(beta2)
freq_offset_th = ((k_ref * delta_f_ref) * rs_ref * beta2_ref) / (beta2 * symbol_rate)
return freq_offset_th
@staticmethod
def _ggn_approx(cut_indices, spectral_info: SpectralInformation, fiber, srs, spm_weight=SPM_WEIGHT,
xpm_weight=XPM_WEIGHT):
"""Computes the nonlinear interference power evaluated at the fiber input.
The method uses eq. 24-25 of https://ieeexplore.ieee.org/document/9741324
"""
# Spectral Features
nch = spectral_info.number_of_channels
frequency = spectral_info.frequency
baud_rate = spectral_info.baud_rate
slot_width = spectral_info.slot_width
roll_off = spectral_info.roll_off
df = spectral_info.df + diag(full(nch, nan))
# Physical fiber parameters
alpha = fiber.alpha(frequency)
beta2 = fiber.beta2(frequency)
gamma = outer(fiber.gamma(frequency[cut_indices]), ones(nch))
identity = diag(ones(nch))
weight = spm_weight * identity + xpm_weight * (ones([nch, nch]) - identity)
weight = weight[cut_indices, :]
dispersion_tolerance = sim_params.nli_params.dispersion_tolerance
phase_shift_tolerance = sim_params.nli_params.phase_shift_tolerance
max_slot_width = max(slot_width)
max_beta2 = max(abs(beta2))
delta_z = sim_params.raman_params.result_spatial_resolution
# Approximation psi
loss_profile = srs.loss_profile[:nch]
z = srs.z
psi = NliSolver._approx_psi(df=df, frequency=frequency, beta2=beta2, baud_rate=baud_rate,
loss_profile=loss_profile, z=z)
# GGN for SPM
for cut_index in cut_indices:
dn = 0
cut_frequency = frequency[cut_index]
cut_baud_rate = baud_rate[cut_index]
cut_roll_off = roll_off[cut_index]
cut_beta2 = beta2[cut_index]
cut_alpha = alpha[cut_index]
k_tol = dispersion_tolerance * abs(cut_alpha)
phi_tol = phase_shift_tolerance / delta_z
f_cut_resolution = min(k_tol, phi_tol) / abs(max_beta2) / (4 * pi ** 2 * (1 + dn) * max_slot_width)
f_pump_resolution = min(k_tol, phi_tol) / abs(max_beta2) / (4 * pi ** 2 * max_slot_width)
psi[cut_index, cut_index] = NliSolver._generalized_psi(cut_frequency, cut_frequency, cut_baud_rate,
cut_roll_off, cut_frequency, cut_baud_rate,
cut_roll_off, f_cut_resolution, f_pump_resolution,
srs, cut_alpha, cut_beta2, 0, cut_frequency)
psi = psi[cut_indices, :]
cut_baud_rate = outer(baud_rate[cut_indices], ones(nch))
pump_baud_rate = outer(ones(cut_indices.size), baud_rate)
eta_cut_central_frequency = \
gamma ** 2 * weight * psi / (cut_baud_rate * pump_baud_rate ** 2)
eta = cut_baud_rate * eta_cut_central_frequency # Local white noise
return eta
@staticmethod
def _approx_psi(df, frequency, baud_rate, beta2, loss_profile, z):
"""Computes the approximated psi function similarly to the one used in the GN model.
The method uses eq. 25 of https://ieeexplore.ieee.org/document/9741324"""
pump_baud_rate = outer(ones(frequency.size), baud_rate)
cut_beta = outer(beta2, ones(frequency.size))
pump_beta = outer(ones(frequency.size), beta2)
delta_z = abs(z[:-1] - z[1:])
loss_lin = log(loss_profile)
pump_alpha = (loss_lin[:, 1:] - loss_lin[:, :-1]) / delta_z
leff = abs((loss_profile[:, 1:] - loss_profile[:, :-1]) / sqrt(abs(pump_alpha))) * pump_alpha / abs(pump_alpha)
leff = reshape(outer(leff, ones(z.size - 1)), newshape=[leff.shape[0], leff.shape[1], leff.shape[1]])
leff2 = leff * swapaxes(leff, 2, 1)
leff2 = sum(leff2, axis=(1, 2))
z_int = outer(ones(frequency.size), leff2)
delta_beta = (cut_beta + pump_beta) / 2
psi = z_int * pump_baud_rate / (4 * pi * abs(delta_beta * df))
return psi
def estimate_nf_model(type_variety, gain_min, gain_max, nf_min, nf_max):
if nf_min < -10:
raise EquipmentConfigError(f'Invalid nf_min value {nf_min!r} for amplifier {type_variety}')
if nf_max < -10:
raise EquipmentConfigError(f'Invalid nf_max value {nf_max!r} for amplifier {type_variety}')
# NF estimation model based on nf_min and nf_max
# delta_p: max power dB difference between first and second stage coils
# dB g1a: first stage gain - internal VOA attenuation
# nf1, nf2: first and second stage coils
# calculated by solving nf_{min,max} = nf1 + nf2 / g1a{min,max}
delta_p = 5
g1a_min = gain_min - (gain_max - gain_min) - delta_p
g1a_max = gain_max - delta_p
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))
if nf1 < 4:
raise EquipmentConfigError(f'First coil value too low {nf1} for amplifier {type_variety}')
# Check 1 dB < delta_p < 6 dB to ensure nf_min and nf_max values make sense.
# There shouldn't be high nf differences between the two coils:
# nf2 should be nf1 + 0.3 < nf2 < nf1 + 2
# If not, recompute and check delta_p
if not nf1 + 0.3 < nf2 < nf1 + 2:
nf2 = clip(nf2, nf1 + 0.3, nf1 + 2)
g1a_max = lin2db(db2lin(nf2) / (db2lin(nf_min) - db2lin(nf1)))
delta_p = gain_max - g1a_max
g1a_min = gain_min - (gain_max - gain_min) - delta_p
if not 1 < delta_p < 11:
raise EquipmentConfigError(f'Computed \N{greek capital letter delta}P invalid \
\n 1st coil vs 2nd coil calculated DeltaP {delta_p:.2f} for \
\n amplifier {type_variety} is not valid: revise inputs \
\n calculated 1st coil NF = {nf1:.2f}, 2nd coil NF = {nf2:.2f}')
# Check calculated values for nf1 and nf2
calc_nf_min = lin2db(db2lin(nf1) + db2lin(nf2) / db2lin(g1a_max))
if not isclose(nf_min, calc_nf_min, abs_tol=0.01):
raise EquipmentConfigError(f'nf_min does not match calc_nf_min, {nf_min} vs {calc_nf_min} for amp {type_variety}')
calc_nf_max = lin2db(db2lin(nf1) + db2lin(nf2) / db2lin(g1a_min))
if not isclose(nf_max, calc_nf_max, abs_tol=0.01):
raise EquipmentConfigError(f'nf_max does not match calc_nf_max, {nf_max} vs {calc_nf_max} for amp {type_variety}')
return nf1, nf2, delta_p

825
gnpy/core/utils.py Normal file
View File

@@ -0,0 +1,825 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# SPDX-License-Identifier: BSD-3-Clause
# gnpy.core.utils: utility functions that are used with gnpy
# Copyright (C) 2025 Telecom Infra Project and GNPy contributors
# see AUTHORS.rst for a list of contributors
"""
gnpy.core.utils
===============
This module contains utility functions that are used with gnpy.
"""
from csv import writer
from numpy import pi, cos, sqrt, log10, linspace, zeros, shape, where, logical_and, mean, array
from scipy import constants
from copy import deepcopy
from typing import List, Union, Dict
from gnpy.core.exceptions import ConfigurationError
def write_csv(obj, filename):
"""
Convert dictionary items to a CSV file the dictionary format:
::
{'result category 1':
[
# 1st line of results
{'header 1' : value_xxx,
'header 2' : value_yyy},
# 2nd line of results: same headers, different results
{'header 1' : value_www,
'header 2' : value_zzz}
],
'result_category 2':
[
{},{}
]
}
The generated csv file will be:
::
result_category 1
header 1 header 2
value_xxx value_yyy
value_www value_zzz
result_category 2
...
"""
with open(filename, 'w', encoding='utf-8') as f:
w = writer(f)
for data_key, data_list in obj.items():
# main header
w.writerow([data_key])
# sub headers:
headers = [_ for _ in data_list[0].keys()]
w.writerow(headers)
for data_dict in data_list:
w.writerow([_ for _ in data_dict.values()])
def arrange_frequencies(length, start, stop):
"""Create an array of frequencies
:param length: number of elements
:param start: Start frequency in THz
:param stop: Stop frequency in THz
:type length: integer
:type start: float
:type stop: float
:return: an array of frequencies determined by the spacing parameter
:rtype: numpy.ndarray
"""
return linspace(start, stop, length)
def lin2db(value):
"""Convert linear unit to logarithmic (dB)
>>> lin2db(0.001)
-30.0
>>> round(lin2db(1.0), 2)
0.0
>>> round(lin2db(1.26), 2)
1.0
>>> round(lin2db(10.0), 2)
10.0
>>> round(lin2db(100.0), 2)
20.0
"""
return 10 * log10(value)
def db2lin(value):
"""Convert logarithimic units to linear
>>> round(db2lin(10.0), 2)
10.0
>>> round(db2lin(20.0), 2)
100.0
>>> round(db2lin(1.0), 2)
1.26
>>> round(db2lin(0.0), 2)
1.0
>>> round(db2lin(-10.0), 2)
0.1
"""
return 10**(value / 10)
def watt2dbm(value):
"""Convert Watt units to dBm
>>> round(watt2dbm(0.001), 1)
0.0
>>> round(watt2dbm(0.02), 1)
13.0
"""
return lin2db(value * 1e3)
def dbm2watt(value):
"""Convert dBm units to Watt
>>> round(dbm2watt(0), 4)
0.001
>>> round(dbm2watt(-3), 4)
0.0005
>>> round(dbm2watt(13), 4)
0.02
"""
return db2lin(value) * 1e-3
def psd2powerdbm(psd_mwperghz, baudrate_baud):
"""computes power in dBm based on baudrate in bauds and psd in mW/GHz
>>> round(psd2powerdbm(0.031176, 64e9),3)
3.0
>>> round(psd2powerdbm(0.062352, 32e9),3)
3.0
>>> round(psd2powerdbm(0.015625, 64e9),3)
0.0
"""
return lin2db(baudrate_baud * psd_mwperghz * 1e-9)
def power_dbm_to_psd_mw_ghz(power_dbm, baudrate_baud):
"""computes power spectral density in mW/GHz based on baudrate in bauds and power in dBm
>>> power_dbm_to_psd_mw_ghz(0, 64e9)
0.015625
>>> round(power_dbm_to_psd_mw_ghz(3, 64e9), 6)
0.031176
>>> round(power_dbm_to_psd_mw_ghz(3, 32e9), 6)
0.062352
"""
return db2lin(power_dbm) / (baudrate_baud * 1e-9)
def psd_mw_per_ghz(power_watt, baudrate_baud):
"""computes power spectral density in mW/GHz based on baudrate in bauds and power in W
>>> psd_mw_per_ghz(2e-3, 32e9)
0.0625
>>> psd_mw_per_ghz(1e-3, 64e9)
0.015625
>>> psd_mw_per_ghz(0.5e-3, 32e9)
0.015625
"""
return power_watt * 1e3 / (baudrate_baud * 1e-9)
def round2float(number, step):
"""Round a floating point number so that its "resolution" is not bigger than 'step'
The finest step is fixed at 0.01; smaller values are silently changed to 0.01.
>>> round2float(123.456, 1000)
0.0
>>> round2float(123.456, 100)
100.0
>>> round2float(123.456, 10)
120.0
>>> round2float(123.456, 1)
123.0
>>> round2float(123.456, 0.1)
123.5
>>> round2float(123.456, 0.01)
123.46
>>> round2float(123.456, 0.001)
123.46
>>> round2float(123.249, 0.5)
123.0
>>> round2float(123.250, 0.5)
123.0
>>> round2float(123.251, 0.5)
123.5
>>> round2float(123.300, 0.2)
123.2
>>> round2float(123.301, 0.2)
123.4
"""
step = round(step, 1)
if step >= 0.01:
number = round(number / step, 0)
number = round(number * step, 1)
else:
number = round(number, 2)
return number
wavelength2freq = constants.lambda2nu
freq2wavelength = constants.nu2lambda
def snr_sum(snr, bw, snr_added, bw_added=12.5e9):
snr_added = snr_added - lin2db(bw / bw_added)
snr = -lin2db(db2lin(-snr) + db2lin(-snr_added))
return snr
def per_label_average(values, labels):
"""computes the average per defined spectrum band, using labels
>>> labels = ['A', 'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'C', 'D', 'D', 'D', 'D']
>>> values = [28.51, 28.23, 28.15, 28.17, 28.36, 28.53, 28.64, 28.68, 28.7, 28.71, 28.72, 28.73, 28.74, 28.91, 27.96, 27.85, 27.87, 28.02]
>>> per_label_average(values, labels)
{'A': 28.28, 'B': 28.68, 'C': 28.91, 'D': 27.92}
"""
label_set = sorted(set(labels))
summary = {}
for label in label_set:
vals = [val for val, lab in zip(values, labels) if lab == label]
summary[label] = round(mean(vals), 2)
return summary
def pretty_summary_print(summary):
"""Build a prettty string that shows the summary dict values per label with 2 digits"""
if len(summary) == 1:
return f'{list(summary.values())[0]:.2f}'
text = ', '.join([f'{label}: {value:.2f}' for label, value in summary.items()])
return text
def deltawl2deltaf(delta_wl, wavelength):
"""deltawl2deltaf(delta_wl, wavelength):
delta_wl is BW in wavelength units
wavelength is the center wl
units for delta_wl and wavelength must be same
:param delta_wl: delta wavelength BW in same units as wavelength
:param wavelength: wavelength BW is relevant for
:type delta_wl: float or numpy.ndarray
:type wavelength: float
:return: The BW in frequency units
:rtype: float or ndarray
"""
f = wavelength2freq(wavelength)
return delta_wl * f / wavelength
def deltaf2deltawl(delta_f, frequency):
"""convert delta frequency to delta wavelength
Units for delta_wl and wavelength must be same.
:param delta_f: delta frequency in same units as frequency
:param frequency: frequency BW is relevant for
:type delta_f: float or numpy.ndarray
:type frequency: float
:return: The BW in wavelength units
:rtype: float or ndarray
"""
wl = freq2wavelength(frequency)
return delta_f * wl / frequency
def rrc(ffs, baud_rate, alpha):
"""compute the root-raised cosine filter function
:param ffs: A numpy array of frequencies
:param baud_rate: The Baud Rate of the System
:param alpha: The roll-off factor of the filter
:type ffs: numpy.ndarray
:type baud_rate: float
:type alpha: float
:return: hf a numpy array of the filter shape
:rtype: numpy.ndarray
"""
Ts = 1 / baud_rate
l_lim = (1 - alpha) / (2 * Ts)
r_lim = (1 + alpha) / (2 * Ts)
hf = zeros(shape(ffs))
slope_inds = where(
logical_and(abs(ffs) > l_lim, abs(ffs) < r_lim))
hf[slope_inds] = 0.5 * (1 + cos((pi * Ts / alpha) *
(abs(ffs[slope_inds]) - l_lim)))
p_inds = where(logical_and(abs(ffs) > 0, abs(ffs) < l_lim))
hf[p_inds] = 1
return sqrt(hf)
def merge_amplifier_restrictions(dict1, dict2):
"""Update contents of dicts recursively
>>> d1 = {'params': {'restrictions': {'preamp_variety_list': [], 'booster_variety_list': []}}}
>>> d2 = {'params': {'target_pch_out_db': -20}}
>>> merge_amplifier_restrictions(d1, d2)
{'params': {'restrictions': {'preamp_variety_list': [], 'booster_variety_list': []}, 'target_pch_out_db': -20}}
>>> d3 = {'params': {'restrictions': {'preamp_variety_list': ['foo'], 'booster_variety_list': ['bar']}}}
>>> merge_amplifier_restrictions(d1, d3)
{'params': {'restrictions': {'preamp_variety_list': [], 'booster_variety_list': []}}}
"""
copy_dict1 = dict1.copy()
for key in dict2:
if key in dict1:
if isinstance(dict1[key], dict):
copy_dict1[key] = merge_amplifier_restrictions(copy_dict1[key], dict2[key])
else:
copy_dict1[key] = dict2[key]
return copy_dict1
def use_pmd_coef(dict1: dict, dict2: dict):
"""If Fiber dict1 is missing the pmd_coef value then use the one of dict2.
In addition records in "pmd_coef_defined" key the pmd_coef if is was defined in dict1.
:param dict1: A dictionnary that contains "pmd_coef" key.
:type dict1: dict
:param dict2: Another dictionnary that contains "pmd_coef" key.
:type dict2: dict
>>> dict1 = {'a': 1, 'pmd_coef': 1.5e-15}
>>> dict2 = {'a': 2, 'pmd_coef': 2e-15}
>>> use_pmd_coef(dict1, dict2)
>>> dict1
{'a': 1, 'pmd_coef': 1.5e-15, 'pmd_coef_defined': True}
>>> dict1 = {'a': 1}
>>> use_pmd_coef(dict1, dict2)
>>> dict1
{'a': 1, 'pmd_coef_defined': False, 'pmd_coef': 2e-15}
"""
if 'pmd_coef' in dict1 and not dict1['pmd_coef'] \
or ('pmd_coef' not in dict1 and 'pmd_coef' in dict2):
dict1['pmd_coef_defined'] = False
dict1['pmd_coef'] = dict2['pmd_coef']
elif 'pmd_coef' in dict1 and dict1['pmd_coef']:
dict1['pmd_coef_defined'] = True
# all other case do not need any change
def silent_remove(this_list, elem):
"""Remove matching elements from a list without raising ValueError
>>> li = [0, 1]
>>> li = silent_remove(li, 1)
>>> li
[0]
>>> li = silent_remove(li, 1)
>>> li
[0]
"""
try:
this_list.remove(elem)
except ValueError:
pass
return this_list
def automatic_nch(f_min, f_max, spacing):
"""How many channels are available in the spectrum
:param f_min Lowest frequenecy [Hz]
:param f_max Highest frequency [Hz]
:param spacing Channel width [Hz]
:return Number of uniform channels
>>> automatic_nch(191.325e12, 196.125e12, 50e9)
96
>>> automatic_nch(193.475e12, 193.525e12, 50e9)
1
"""
return int((f_max - f_min) // spacing)
def automatic_fmax(f_min, spacing, nch):
"""Find the high-frequenecy boundary of a spectrum
:param f_min Start of the spectrum (lowest frequency edge) [Hz]
:param spacing Grid/channel spacing [Hz]
:param nch Number of channels
:return End of the spectrum (highest frequency) [Hz]
>>> automatic_fmax(191.325e12, 50e9, 96)
196125000000000.0
"""
return f_min + spacing * nch
def convert_length(value, units):
"""Convert length into basic SI units
>>> convert_length(1, 'km')
1000.0
>>> convert_length(2.0, 'km')
2000.0
>>> convert_length(123, 'm')
123.0
>>> convert_length(123.0, 'm')
123.0
>>> convert_length(42.1, 'km')
42100.0
>>> convert_length(666, 'yards')
Traceback (most recent call last):
...
gnpy.core.exceptions.ConfigurationError: Cannot convert length in "yards" into meters
"""
if units == 'm':
return value * 1e0
elif units == 'km':
return value * 1e3
else:
raise ConfigurationError(f'Cannot convert length in "{units}" into meters')
def replace_none(dictionary):
""" Replaces None with inf values in a frequency slots dict
>>> replace_none({'N': 3, 'M': None})
{'N': 3, 'M': inf}
"""
for key, val in dictionary.items():
if val is None:
dictionary[key] = float('inf')
if val == float('inf'):
dictionary[key] = None
return dictionary
def order_slots(slots):
""" Order frequency slots from larger slots to smaller ones up to None
>>> l = [{'N': 3, 'M': None}, {'N': 2, 'M': 1}, {'N': None, 'M': None},{'N': 7, 'M': 2},{'N': None, 'M': 1} , {'N': None, 'M': 0}]
>>> order_slots(l)
([7, 2, None, None, 3, None], [2, 1, 1, 0, None, None], [3, 1, 4, 5, 0, 2])
"""
slots_list = deepcopy(slots)
slots_list = [replace_none(e) for e in slots_list]
for i, e in enumerate(slots_list):
e['i'] = i
slots_list = sorted(slots_list, key=lambda x: (-x['M'], x['N']) if x['M'] != float('inf') else (x['M'], x['N']))
slots_list = [replace_none(e) for e in slots_list]
return [e['N'] for e in slots_list], [e['M'] for e in slots_list], [e['i'] for e in slots_list]
def restore_order(elements, order):
""" Use order to re-order the element of the list, and ignore None values
>>> restore_order([7, 2, None, None, 3, None], [3, 1, 4, 5, 0, 2])
[3, 2, 7]
"""
return [elements[i[0]] for i in sorted(enumerate(order), key=lambda x:x[1]) if elements[i[0]] is not None]
def unique_ordered(elements):
"""
"""
unique_elements = []
for element in elements:
if element not in unique_elements:
unique_elements.append(element)
return unique_elements
def convert_empty_to_none(json_data: Union[list, dict]) -> dict:
"""Convert all instances of "a": [None] into "a": None
:param json_data: the input data.
:type json_data: dict
:return: the converted data.
:rtype: dict
>>> json_data = {
... "uid": "[east edfa in Lannion",
... "type_variety": "multiband_booster",
... "metadata": {
... "location": {
... "latitude": 0.000000,
... "longitude": 0.000000,
... "city": "Zion",
... "region": ""
... }
... },
... "type": "Multiband_amplifier",
... "amplifiers": [{
... "type_variety": "multiband_booster_LOW_C",
... "operational": {
... "gain_target": 12.22,
... "delta_p": 4.19,
... "out_voa": [None],
... "tilt_target": 0.00,
... "f_min": 191.3,
... "f_max": 196.1
... }
... }, {
... "type_variety": "multiband_booster_LOW_L",
... "operational": {
... "gain_target": 12.05,
... "delta_p": 4.19,
... "out_voa": [None],
... "tilt_target": 0.00,
... "f_min": 186.1,
... "f_max": 190.9
... }
... }
... ]
... }
>>> convert_empty_to_none(json_data)
{'uid': '[east edfa in Lannion', 'type_variety': 'multiband_booster', \
'metadata': {'location': {'latitude': 0.0, 'longitude': 0.0, 'city': 'Zion', 'region': ''}}, \
'type': 'Multiband_amplifier', 'amplifiers': [{'type_variety': 'multiband_booster_LOW_C', \
'operational': {'gain_target': 12.22, 'delta_p': 4.19, 'out_voa': None, 'tilt_target': 0.0, \
'f_min': 191.3, 'f_max': 196.1}}, {'type_variety': 'multiband_booster_LOW_L', \
'operational': {'gain_target': 12.05, 'delta_p': 4.19, 'out_voa': None, 'tilt_target': 0.0, \
'f_min': 186.1, 'f_max': 190.9}}]}
"""
if isinstance(json_data, dict):
for key, value in json_data.items():
json_data[key] = convert_empty_to_none(value)
elif isinstance(json_data, list):
if len(json_data) == 1 and json_data[0] is None:
return None
for i, elem in enumerate(json_data):
json_data[i] = convert_empty_to_none(elem)
return json_data
def convert_none_to_empty(json_data: Union[list, dict]) -> dict:
"""Convert all instances of "a": None into "a": [None], to be compliant with RFC7951.
:param json_data: the input data.
:type json_data: dict
:return: the converted data.
:rtype: dict
>>> a = {'uid': '[east edfa in Lannion', 'type_variety': 'multiband_booster',
... 'metadata': {'location': {'latitude': 0.0, 'longitude': 0.0, 'city': 'Zion', 'region': ''}},
... 'type': 'Multiband_amplifier', 'amplifiers': [{'type_variety': 'multiband_booster_LOW_C',
... 'operational': {'gain_target': 12.22, 'delta_p': 4.19, 'out_voa': None, 'tilt_target': 0.0,
... 'f_min': 191.3, 'f_max': 196.1}}, {'type_variety': 'multiband_booster_LOW_L',
... 'operational': {'gain_target': 12.05, 'delta_p': 4.19, 'out_voa': None, 'tilt_target': 0.0,
... 'f_min': 186.1, 'f_max': 190.9}}]}
>>> convert_none_to_empty(a)
{'uid': '[east edfa in Lannion', 'type_variety': 'multiband_booster', \
'metadata': {'location': {'latitude': 0.0, 'longitude': 0.0, 'city': 'Zion', 'region': ''}}, \
'type': 'Multiband_amplifier', 'amplifiers': [{'type_variety': 'multiband_booster_LOW_C', \
'operational': {'gain_target': 12.22, 'delta_p': 4.19, 'out_voa': [None], 'tilt_target': 0.0, \
'f_min': 191.3, 'f_max': 196.1}}, {'type_variety': 'multiband_booster_LOW_L', \
'operational': {'gain_target': 12.05, 'delta_p': 4.19, 'out_voa': [None], 'tilt_target': 0.0, \
'f_min': 186.1, 'f_max': 190.9}}]}
"""
if json_data == [None]:
# already conformed
return json_data
if isinstance(json_data, dict):
for key, value in json_data.items():
json_data[key] = convert_none_to_empty(value)
elif isinstance(json_data, list):
for i, elem in enumerate(json_data):
json_data[i] = convert_none_to_empty(elem)
elif json_data is None:
return [None]
return json_data
def calculate_absolute_min_or_zero(x: array) -> array:
"""Calculates the element-wise absolute minimum between the x and zero.
Parameters:
x (array): The first input array.
Returns:
array: The element-wise absolute minimum between x and zero.
Example:
>>> x = array([-1, 2, -3])
>>> calculate_absolute_min_or_zero(x)
array([1., 0., 3.])
"""
return (abs(x) - x) / 2
def nice_column_str(data: List[List[str]], max_length: int = 30, padding: int = 1) -> str:
"""data is a list of rows, creates strings with nice alignment per colum and padding with spaces
letf justified
>>> table_data = [['aaa', 'b', 'c'], ['aaaaaaaa', 'bbb', 'c'], ['a', 'bbbbbbbbbb', 'c']]
>>> print(nice_column_str(table_data))
aaa b c
aaaaaaaa bbb c
a bbbbbbbbbb c
"""
# transpose data to determine size of columns
transposed_data = list(map(list, zip(*data)))
column_width = [max(len(word) for word in column) + padding for column in transposed_data]
nice_str = []
for row in data:
column = ''.join(word[0:max_length].ljust(min(width, max_length)) for width, word in zip(column_width, row))
nice_str.append(f'{column}')
return '\n'.join(nice_str)
def filter_valid_amp_bands(amp_bands: List[List[dict]]) -> List[List[dict]]:
"""Filter out invalid amplifier bands that lack f_min or f_max.
:param amp_bands: A list of lists containing amplifier band dictionaries.
:type amp_bands: List[List[dict]]
:return: A filtered list of amplifier bands that contain valid f_min and f_max.
:rtype: List[List[dict]]
"""
return [amp for amp in amp_bands if all(band.get('f_min') is not None and band.get('f_max') is not None
for band in amp)]
def remove_duplicates(amp_bands: List[List[dict]]) -> List[List[dict]]:
"""Remove duplicate amplifier bands.
:param amp_bands: A list of lists containing amplifier band dictionaries.
:type amp_bands: List[List[dict]]
:return: A list of unique amplifier bands.
:rtype: List[List[dict]]
"""
unique_amp_bands = []
for amp in amp_bands:
if amp not in unique_amp_bands:
unique_amp_bands.append(amp)
return unique_amp_bands
def calculate_spacing(first: dict, second: dict, default_spacing: float, default_design_bands: Union[List[Dict], None],
f_min: float, f_max: float) -> float:
"""Calculate the spacing for the given frequency range.
:param first: The first amplifier band dictionary.
:type first: dict
:param second: The second amplifier band dictionary.
:type second: dict
:param default_spacing: The default spacing to use if no specific spacing can be determined.
:type default_spacing: float
:param default_design_bands: Optional list of design bands to determine spacing from.
:type default_design_bands: Union[List[Dict], None]
:param f_min: The minimum frequency of the range.
:type f_min: float
:param f_max: The maximum frequency of the range.
:type f_max: float
:return: The calculated spacing for the given frequency range.
:rtype: float
"""
if first.get('spacing') is not None and second.get('spacing') is not None:
return max(first['spacing'], second['spacing'])
elif first.get('spacing') is not None:
return first['spacing']
elif second.get('spacing') is not None:
return second['spacing']
elif default_design_bands:
temp = get_spacing_from_band(default_design_bands, f_min, f_max)
return temp if temp is not None else default_spacing
return default_spacing
def find_common_range(amp_bands: List[List[dict]], default_band_f_min: Union[float, None],
default_band_f_max: Union[float, None], default_spacing: float,
default_design_bands: Union[List[Dict], None] = None) -> List[dict]:
"""
Find the common frequency range of amplifier bands.
If there are no amplifiers in the path, then use the default band parameters.
:param amp_bands: A list of lists containing amplifier band dictionaries, each with 'f_min', 'f_max',
and optionally 'spacing'.
:type amp_bands: List[List[dict]]
:param default_band_f_min: The minimum frequency of the default band.
:type default_band_f_min: Union[float, None]
:param default_band_f_max: The maximum frequency of the default band.
:type default_band_f_max: Union[float, None]
:param default_spacing: The default spacing to use if no specific spacing can be determined.
:type default_spacing: float
:param default_design_bands: Optional list of design bands to determine spacing from.
:type default_design_bands: Union[List[Dict], None]
:return: A list of dictionaries representing the common frequency ranges with their respective spacings.
:rtype: List[dict]
>>> amp_bands = [[{'f_min': 191e12, 'f_max' : 195e12, 'spacing': 70e9}, {'f_min': 186e12, 'f_max' : 190e12}], \
[{'f_min': 185e12, 'f_max' : 189e12}, {'f_min': 192e12, 'f_max' : 196e12}], \
[{'f_min': 186e12, 'f_max': 193e12}]]
>>> find_common_range(amp_bands, 190e12, 195e12, 50e9)
[{'f_min': 186000000000000.0, 'f_max': 189000000000000.0, 'spacing': 50000000000.0}, \
{'f_min': 192000000000000.0, 'f_max': 193000000000000.0, 'spacing': 70000000000.0}]
>>> amp_bands = [[{'f_min': 191e12, 'f_max' : 195e12}, {'f_min': 186e12, 'f_max' : 190e12}], \
[{'f_min': 185e12, 'f_max' : 189e12}, {'f_min': 192e12, 'f_max' : 196e12}], \
[{'f_min': 186e12, 'f_max': 192e12}]]
>>> find_common_range(amp_bands, 190e12, 195e12, 50e9)
[{'f_min': 186000000000000.0, 'f_max': 189000000000000.0, 'spacing': 50000000000.0}]
"""
# Step 1: Filter and sort amplifier bands
_amp_bands = [sorted(amp, key=lambda x: x['f_min']) for amp in filter_valid_amp_bands(amp_bands)]
unique_amp_bands = remove_duplicates(_amp_bands)
# Step 2: Handle cases with no valid bands
if unique_amp_bands:
common_range = unique_amp_bands[0]
else:
if default_band_f_min is None or default_band_f_max is None:
return []
return [{'f_min': default_band_f_min, 'f_max': default_band_f_max, 'spacing': None}]
# Step 3: Calculate common frequency range
for bands in unique_amp_bands:
new_common_range = []
for first in common_range:
for second in bands:
f_min = max(first['f_min'], second['f_min'])
f_max = min(first['f_max'], second['f_max'])
if f_min < f_max:
spacing = calculate_spacing(first, second, default_spacing, default_design_bands, f_min, f_max)
new_common_range.append({'f_min': f_min, 'f_max': f_max, 'spacing': spacing})
common_range = new_common_range
return sorted(common_range, key=lambda x: x['f_min'])
def transform_data(data: str) -> Union[List[int], None]:
"""Transforms a float into an list of one integer or a string separated by "|" into a list of integers.
Args:
data (float or str): The data to transform.
Returns:
list of int: The transformed data as a list of integers.
Examples:
>>> transform_data(5.0)
[5]
>>> transform_data('1 | 2 | 3')
[1, 2, 3]
"""
if isinstance(data, float):
return [int(data)]
if isinstance(data, str):
return [int(x) for x in data.split(' | ')]
return None
def convert_pmd_lineic(pmd: Union[float, None], length: float, length_unit: str) -> Union[float, None]:
"""Convert PMD value of the span in ps into pmd_lineic in s/sqrt(km)
:param pmd: value in ps
:type pmd: Union[float, None]
:param length: value in length_unit
:type length: float
:param length_unit: 'km' or 'm'
:type length_unit: str
:return: lineic PMD s/sqrt(m)
:rtype: Union[float, None]
>>> convert_pmd_lineic(10, 0.001, 'km')
1e-11
"""
if pmd:
return pmd * 1e-12 / sqrt(convert_length(length, length_unit))
return None
def get_spacing_from_band(design_bands: List[Dict], f_min, f_max):
"""Retrieve the spacing for a frequency range based on design bands.
This function checks if the midpoint of the provided frequency range (f_min, f_max)
falls within any of the design bands. If it does, the corresponding spacing is returned.
:param design_bands: A list of design band dictionaries, each containing 'f_min', 'f_max', and 'spacing'.
:type design_bands: List[Dict]
:param f_min: The minimum frequency of the range.
:type f_min: float
:param f_max: The maximum frequency of the range.
:type f_max: float
:return: The spacing corresponding to the design band that contains the midpoint of the range,
or None if no such band exists.
:rtype: Union[float, None]
"""
midpoint = (f_min + f_max) / 2
for band in design_bands:
if midpoint >= band['f_min'] and midpoint <= band['f_max']:
return band['spacing']
return None
def reorder_per_degree_design_bands(per_degree_design_bands: dict):
"""Sort the design bands for each degree by their minimum frequency (f_min).
This function modifies the input dictionary in place, sorting the design bands for each unique identifier.
:param per_degree_design_bands: A dictionary where keys are unique identifiers and values are lists of design band dictionaries.
:type per_degree_design_bands: Dict[str, List[Dict]]
"""
for uid, design_bands in per_degree_design_bands.items():
per_degree_design_bands[uid] = sorted(design_bands, key=lambda x: x['f_min'])

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@@ -0,0 +1,160 @@
{
"nf_fit_coeff": [
0.0008,
0.0272,
-0.2249,
6.4902
],
"f_min": 191.4e12,
"f_max": 196.1e12,
"nf_ripple": [
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0
],
"gain_ripple": [
-0.15656302345061,
-0.22244242043552,
-0.25188965661642,
-0.23575900335007,
-0.20897508375209,
-0.19440221943049,
-0.18324644053602,
-0.18053287269681,
-0.17113588777219,
-0.15460322445561,
-0.13550774706866,
-0.10606051088777,
-0.0765630234506,
-0.04962835008375,
-0.01319618927973,
0.01027114740367,
0.03378873534338,
0.04961788107202,
0.04494451423784,
0.0399193886097,
0.01584903685091,
-0.00420121440538,
-0.01847257118928,
-0.02475397822447,
-0.01053287269681,
0.01509526800668,
0.05921587102177,
0.1191656197655,
0.18147717755444,
0.23579878559464,
0.26941687604691,
0.27836159966498,
0.26956762981574,
0.23826109715241,
0.18936662479061,
0.1204721524288,
0.0453465242881,
-0.00877407872698,
-0.02199015912898,
0.00107516750419,
0.02795958961474,
0.02740682579566,
-0.01028161641541,
-0.05982935510889,
-0.06701528475711,
0.00223094639866,
0.14157768006701,
0.15017064489112
],
"dgt": [
1.0,
1.03941448941778,
1.07773189112355,
1.11575888725852,
1.15209185089701,
1.18632744096844,
1.21911100318577,
1.24931318255134,
1.27657903892303,
1.30069883494415,
1.32210817897091,
1.3405812000038,
1.35690844654118,
1.3710092503689,
1.38430337205545,
1.3966294751726,
1.40864903907609,
1.42089447397912,
1.43476940680732,
1.44977369463316,
1.46637521309853,
1.48420288841848,
1.50335352244996,
1.5242627235492,
1.54578500307573,
1.56750088631614,
1.58973304612691,
1.61073904908309,
1.63068023161292,
1.64799163036252,
1.66286684904577,
1.6761448370895,
1.68845480656382,
1.70379790088896,
1.72461030013125,
1.75428006928365,
1.79748596476494,
1.85543800978691,
1.92915262384742,
2.01414465424155,
2.10336369905543,
2.19013043016015,
2.26678136721453,
2.33147727493671,
2.38192717604575,
2.41879254989742,
2.44342862248888,
2.4553191172498
]
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,109 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# SPDX-License-Identifier: BSD-3-Clause
# Utility functions that creates an Eqpt sheet template
# Copyright (C) 2025 Telecom Infra Project and GNPy contributors
# see AUTHORS.rst for a list of contributors
"""
create_eqpt_sheet.py
====================
XLS parser that can be called to create a "City" column in the "Eqpt" sheet.
If not present in the "Nodes" sheet, the "Type" column will be implicitly
determined based on the topology.
"""
from xlrd import open_workbook
from argparse import ArgumentParser
PARSER = ArgumentParser()
PARSER.add_argument('workbook', nargs='?', default='meshTopologyExampleV2.xls',
help='create the mandatory columns in Eqpt sheet')
def ALL_ROWS(sh, start=0):
return (sh.row(x) for x in range(start, sh.nrows))
class Node:
""" Node element contains uid, list of connected nodes and eqpt type
"""
def __init__(self, uid, to_node):
self.uid = uid
self.to_node = to_node
self.eqpt = None
def __repr__(self):
return f'uid {self.uid} \nto_node {[node for node in self.to_node]}\neqpt {self.eqpt}\n'
def __str__(self):
return f'uid {self.uid} \nto_node {[node for node in self.to_node]}\neqpt {self.eqpt}\n'
def read_excel(input_filename):
""" read excel Nodes and Links sheets and create a dict of nodes with
their to_nodes and type of eqpt
"""
with open_workbook(input_filename) as wobo:
# reading Links sheet
links_sheet = wobo.sheet_by_name('Links')
nodes = {}
for row in ALL_ROWS(links_sheet, start=5):
try:
nodes[row[0].value].to_node.append(row[1].value)
except KeyError:
nodes[row[0].value] = Node(row[0].value, [row[1].value])
try:
nodes[row[1].value].to_node.append(row[0].value)
except KeyError:
nodes[row[1].value] = Node(row[1].value, [row[0].value])
nodes_sheet = wobo.sheet_by_name('Nodes')
for row in ALL_ROWS(nodes_sheet, start=5):
node = row[0].value
eqpt = row[6].value
try:
if eqpt == 'ILA' and len(nodes[node].to_node) != 2:
print(f'Inconsistancy ILA node with degree > 2: {node} ')
exit()
if eqpt == '' and len(nodes[node].to_node) == 2:
nodes[node].eqpt = 'ILA'
elif eqpt == '' and len(nodes[node].to_node) != 2:
nodes[node].eqpt = 'ROADM'
else:
nodes[node].eqpt = eqpt
except KeyError:
print(f'inconsistancy between nodes and links sheet: {node} is not listed in links')
exit()
return nodes
def create_eqt_template(nodes, input_filename):
""" writes list of node A node Z corresponding to Nodes and Links sheets in order
to help user populating Eqpt
"""
output_filename = f'{input_filename[:-4]}_eqpt_sheet.txt'
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) \
\nNode A \tNode Z \tamp type \tatt_in \tamp gain \ttilt \tatt_out\
amp type \tatt_in \tamp gain \ttilt \tatt_out\n')
for node in nodes.values():
if node.eqpt == 'ILA':
my_file.write(f'{node.uid}\t{node.to_node[0]}\n')
if node.eqpt == 'ROADM':
for to_node in node.to_node:
my_file.write(f'{node.uid}\t{to_node}\n')
print(f'File {output_filename} successfully created with Node A - Node Z entries for Eqpt sheet in excel file.')
if __name__ == '__main__':
ARGS = PARSER.parse_args()
create_eqt_template(read_excel(ARGS.workbook), ARGS.workbook)

View File

@@ -0,0 +1,81 @@
{
"network_name": "EDFA Example Network - P2P",
"elements": [
{
"uid": "Site_A",
"type": "Transceiver",
"metadata": {
"location": {
"city": "Site A",
"region": "",
"latitude": 0,
"longitude": 0
}
}
},
{
"uid": "Span1",
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 80,
"loss_coef": 0.2,
"length_units": "km",
"att_in": 0,
"con_in": 0.5,
"con_out": 0.5,
"pmd_coef": 3.0e-15
},
"metadata": {
"location": {
"region": "",
"latitude": 1,
"longitude": 0
}
}
},
{
"uid": "Edfa1",
"type": "Edfa",
"type_variety": "std_low_gain",
"operational": {
"gain_target": 17,
"tilt_target": 0,
"out_voa": 0
},
"metadata": {
"location": {
"region": "",
"latitude": 2,
"longitude": 0
}
}
},
{
"uid": "Site_B",
"type": "Transceiver",
"metadata": {
"location": {
"city": "Site B",
"region": "",
"latitude": 2,
"longitude": 0
}
}
}
],
"connections": [
{
"from_node": "Site_A",
"to_node": "Span1"
},
{
"from_node": "Span1",
"to_node": "Edfa1"
},
{
"from_node": "Edfa1",
"to_node": "Site_B"
}
]
}

View File

@@ -0,0 +1 @@
2.5135969849999999e+01 2.5118228139999999e+01 2.5095421330000001e+01 2.5062457710000000e+01 2.5026027650000000e+01 2.4996379529999999e+01 2.4981672549999999e+01 2.4975306679999999e+01 2.4983207260000000e+01 2.4997185649999999e+01 2.5017572470000001e+01 2.5038327809999998e+01 2.5054955849999999e+01 2.5067071899999998e+01 2.5070914110000000e+01 2.5070943650000000e+01 2.5071143240000001e+01 2.5075336270000001e+01 2.5087310179999999e+01 2.5103139360000000e+01 2.5122762040000001e+01 2.5142394790000001e+01 2.5159456330000001e+01 2.5173927039999999e+01 2.5176737670000001e+01 2.5170371410000001e+01 2.5152162539999999e+01 2.5131143099999999e+01 2.5108023350000000e+01 2.5085487770000000e+01 2.5069166750000001e+01 2.5058481759999999e+01 2.5054473130000002e+01 2.5051544410000002e+01 2.5049460589999999e+01 2.5047178490000000e+01 2.5045516559999999e+01 2.5044676490000001e+01 2.5040729200000001e+01 2.5032854080000000e+01 2.5023488300000000e+01 2.5016592339999999e+01 2.5013321359999999e+01 2.5011234340000001e+01 2.5010300149999999e+01 2.5009365480000000e+01 2.5008739640000002e+01 2.5008425350000000e+01 2.5006964660000001e+01 2.5004043100000001e+01 2.5000709980000000e+01 2.4998423200000001e+01 2.4993063320000001e+01 2.4983524209999999e+01 2.4971251030000001e+01 2.4960381080000001e+01 2.4948887209999999e+01 2.4935314890000001e+01 2.4921319270000001e+01 2.4908986970000001e+01 2.4898965140000001e+01 2.4889584630000002e+01 2.4880838700000002e+01 2.4872100920000001e+01 2.4864620259999999e+01 2.4858397730000000e+01 2.4854458380000001e+01 2.4851554430000000e+01 2.4851766009999999e+01 2.4854080140000001e+01 2.4859096240000000e+01 2.4864744580000000e+01 2.4872034859999999e+01 2.4880365200000000e+01 2.4889106689999998e+01 2.4897213130000001e+01 2.4902826040000001e+01 2.4906566900000001e+01 2.4908650800000000e+01 2.4910939440000000e+01 2.4913430790000000e+01 2.4915923440000000e+01 2.4921553509999999e+01 2.4930318610000000e+01 2.4940528120000000e+01 2.4949046689999999e+01 2.4957571229999999e+01 2.4967818449999999e+01 2.4981800929999999e+01 2.4997826860000000e+01 2.5013931830000001e+01 2.5028098459999999e+01 2.5040325750000001e+01 2.5052569810000001e+01 2.5064797009999999e+01 2.5077046970000001e+01

View File

@@ -0,0 +1 @@
2.7145266811316859e+00 2.7054438192385049e+00 2.6947834587664494e+00 2.6841217449620203e+00 2.6681935771243177e+00 2.6521732021128046e+00 2.6303964408153848e+00 2.6028603502864280e+00 2.5696460593920065e+00 2.5364027376452056e+00 2.4994462867966041e+00 2.4587748041127506e+00 2.4143984371852212e+00 2.3699990328716107e+00 2.3223736962293420e+00 2.2715207713712529e+00 2.2174389328192197e+00 2.1633756538423898e+00 2.1183028432496016e+00 2.0822250998736478e+00 2.0551007720052352e+00 2.0279625371819305e+00 2.0008103857988204e+00 1.9736443063300082e+00 1.9482128147680253e+00 1.9245345552113182e+00 1.9026104247588487e+00 1.8806927939516411e+00 1.8622356724442459e+00 1.8472755032011290e+00 1.8358140813807049e+00 1.8243814368429321e+00 1.8139629377087627e+00 1.8045606557581335e+00 1.7961751115773796e+00 1.7877868031023945e+00 1.7793941781790852e+00 1.7709972329654864e+00 1.7625959636196327e+00 1.7541903672600494e+00 1.7459181197626403e+00 1.7377807579136351e+00 1.7297783508684146e+00 1.7217732861435076e+00 1.7137640932265894e+00 1.7057507692361864e+00 1.6918150918099673e+00 1.6719047669939942e+00 1.6460167077689267e+00 1.6201194134191075e+00 1.5986915141218316e+00 1.5817353179379183e+00 1.5691997641843789e+00 1.5566577309558969e+00 1.5453741527614671e+00 1.5353620432989845e+00 1.5266220576235803e+00 1.5178910621476225e+00 1.5097346239790443e+00 1.5021530399096861e+00 1.4951454560626991e+00 1.4881342434792260e+00 1.4811193973568100e+00 1.4741004422522110e+00 1.4670307626366115e+00 1.4599103316162523e+00 1.4527395948591399e+00 1.4455651371583680e+00 1.4340878115214444e+00 1.4182738067303231e+00 1.3981208704326855e+00 1.3779439775587023e+00 1.3598972673004606e+00 1.3439818461440451e+00 1.3301807335621048e+00 1.3163839268630830e+00 1.3040618749785347e+00 1.2932153453410835e+00 1.2838336236692311e+00 1.2744470198196236e+00 1.2650555289898042e+00 1.2556591482982988e+00 1.2428104897182262e+00 1.2264996957264114e+00 1.2067249615595257e+00 1.1869318618366975e+00 1.1672278304018044e+00 1.1476135933863398e+00 1.1280891949729075e+00 1.1085552896156590e+00 1.0895983485572227e+00 1.0712204022764056e+00 1.0534217504465226e+00 1.0356155337864215e+00 1.0178077678537021e+00 1.0000000000000000e+00

View File

@@ -0,0 +1 @@
-3.1537433199999998e-01 -3.1537433199999998e-01 -3.1540091571002721e-01 -3.1849146117510951e-01 -3.2158358425400546e-01 -3.2467728615499991e-01 -3.2762368641496226e-01 -3.2054138461232762e-01 -3.1345546385118733e-01 -3.0636592135697482e-01 -2.9920267890990127e-01 -2.7061972852631744e-01 -2.4202215770774693e-01 -2.1340995523361256e-01 -1.8478227130158695e-01 -1.4809761118389625e-01 -1.1139416731807622e-01 -7.4671925273579881e-02 -3.8026748965679924e-02 -1.9958469399422092e-02 -1.8809287980157928e-03 1.6205879960573561e-02 3.4301964005709673e-02 5.2407330474054062e-02 7.0521986509597359e-02 7.9578036683472006e-02 8.8546647361909522e-02 9.7519863231965306e-02 1.0649768784154924e-01 9.7741380449907406e-02 8.8803437172660038e-02 7.9860899732845866e-02 7.0913764587403796e-02 6.3335892740565308e-02 5.5756212252058776e-02 4.8172631747863209e-02 4.0585148217162359e-02 3.3381591675710129e-02 2.6178308595650738e-02 1.8971315351761126e-02 1.1760609076833628e-02 1.6950294922759991e-02 2.2274991357701439e-02 2.7602433189104329e-02 3.2932622540790261e-02 3.8265561538776145e-02 4.3601252311271169e-02 3.4856990743481552e-02 2.5991055149117932e-02 1.7120541224980364e-02 8.2757587359203223e-03 1.9423214065246042e-03 -4.3943890171043590e-03 -1.0734375072893196e-02 -1.7077639301414434e-02 -2.4679702899572852e-02 -3.2297970403821680e-02 -3.9920180090477250e-02 -4.7534566327530239e-02 -4.9234003141433724e-02 -5.0934320036547187e-02 -5.2635517696692252e-02 -5.4337596806402461e-02 -5.6040558050919301e-02 -5.7718452237076875e-02 -5.6840590379175944e-02 -5.5962273198734966e-02 -5.5083500341416583e-02 -5.4204271452516814e-02 -5.8396088726955113e-02 -6.2627330169715334e-02 -6.6860769089203700e-02 -7.0901736256069450e-02 -5.2096097309052243e-02 -3.3280684121412940e-02 -1.4455489070928059e-02 4.3150387579057158e-03 1.4839202394482527e-02 2.5368841662503576e-02 3.5903960836465652e-02 4.6444564195321399e-02 5.6990656022467459e-02 6.7542240605774059e-02 1.0002709623672751e-01 1.3258013095133617e-01 1.6515013362773309e-01 1.9773711753599391e-01 2.3194802687829724e-01 2.6618779883837107e-01 3.0044543658085349e-01 3.3472095409250663e-01 3.5929034770587287e-01 3.8384389188855605e-01 4.0841026111391787e-01 4.3298946543290784e-01 4.3298946543290784e-01

View File

@@ -0,0 +1,6 @@
{
"nf_ripple": "NFR_96.txt",
"gain_ripple": "DFG_96.txt",
"dgt": "DGT_96.txt",
"nf_fit_coeff": "pNFfit3.txt"
}

View File

@@ -0,0 +1,95 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# SPDX-License-Identifier: BSD-3-Clause
# update an existing json file with all the 96ch txt files for a given amplifier type
# Copyright (C) 2025 Telecom Infra Project and GNPy contributors
# see AUTHORS.rst for a list of contributors
"""
Created on Tue Jan 30 12:32:00 2018
@author: jeanluc-auge
update an existing json file with all the 96ch txt files for a given amplifier type
amplifier type 'OA_type1' is hard coded but can be modified and other types added
returns an updated amplifier json file: output_json_file_name = 'edfa_config.json'
"""
import re
import sys
import json
import numpy as np
"""amplifier file names
convert a set of amplifier files + input json definiton file into a valid edfa_json_file:
nf_fit_coeff: NF 3rd order polynomial coefficients txt file
nf = f(dg)
with dg = gain_operational - gain_max
nf_ripple: NF ripple excursion txt file
gain_ripple: gain ripple txt file
dgt: dynamic gain txt file
input json file in argument (defult = 'OA.json')
the json input file should have the following fields:
{
"nf_fit_coeff": "nf_filename.txt",
"nf_ripple": "nf_ripple_filename.txt",
"gain_ripple": "DFG_filename.txt",
"dgt": "DGT_filename.txt",
}
"""
input_json_file_name = "OA.json" # default path
output_json_file_name = "default_edfa_config.json"
gain_ripple_field = "gain_ripple"
nf_ripple_field = "nf_ripple"
nf_fit_coeff = "nf_fit_coeff"
def read_file(field, file_name):
"""read and format the 96 channels txt files describing the amplifier NF and ripple
convert dfg into gain ripple by removing the mean component
"""
# with open(path + file_name,'r') as this_file:
# data = this_file.read()
# data.strip()
#data = re.sub(r"([0-9])([ ]{1,3})([0-9-+])",r"\1,\3",data)
#data = list(data.split(","))
#data = [float(x) for x in data]
data = np.loadtxt(file_name)
print(len(data), file_name)
if field == gain_ripple_field or field == nf_ripple_field:
# consider ripple excursion only to avoid redundant information
# because the max flat_gain is already given by the 'gain_flat' field in json
# remove the mean component
print(file_name, ', mean value =', data.mean(), ' is substracted')
data = data - data.mean()
data = data.tolist()
return data
def input_json(path):
"""read the json input file and add all the 96 channels txt files
create the output json file with output_json_file_name"""
with open(path, 'r') as edfa_json_file:
amp_text = edfa_json_file.read()
amp_dict = json.loads(amp_text)
for k, v in amp_dict.items():
if re.search(r'.txt$', str(v)):
amp_dict[k] = read_file(k, v)
amp_text = json.dumps(amp_dict, indent=4)
# print(amp_text)
with open(output_json_file_name, 'w') as edfa_json_file:
edfa_json_file.write(amp_text)
if __name__ == '__main__':
if len(sys.argv) == 2:
path = sys.argv[1]
else:
path = input_json_file_name
input_json(path)

View File

@@ -0,0 +1 @@
1.6824099999999999e-04 4.6996099999999999e-02 3.5954899999999998e-02 5.8285099999999996e+00

View File

@@ -0,0 +1,444 @@
{
"Edfa": [
{
"type_variety": "high_detail_model_example",
"type_def": "advanced_model",
"gain_flatmax": 25,
"gain_min": 15,
"p_max": 21,
"advanced_config_from_json": "std_medium_gain_advanced_config.json",
"out_voa_auto": false,
"allowed_for_design": false
},
{
"type_variety": "Juniper_BoosterHG",
"type_def": "advanced_model",
"gain_flatmax": 25,
"gain_min": 10,
"p_max": 21,
"advanced_config_from_json": "Juniper-BoosterHG.json",
"out_voa_auto": false,
"allowed_for_design": false
},
{
"type_variety": "operator_model_example",
"type_def": "variable_gain",
"gain_flatmax": 26,
"gain_min": 15,
"p_max": 23,
"nf_min": 6,
"nf_max": 10,
"out_voa_auto": false,
"allowed_for_design": false
},
{
"type_variety": "openroadm_ila_low_noise",
"type_def": "openroadm",
"gain_flatmax": 27,
"gain_min": 0,
"p_max": 22,
"nf_coef": [
-8.104e-4,
-6.221e-2,
-5.889e-1,
37.62
],
"allowed_for_design": false
},
{
"type_variety": "openroadm_ila_standard",
"type_def": "openroadm",
"gain_flatmax": 27,
"gain_min": 0,
"p_max": 22,
"nf_coef": [
-5.952e-4,
-6.250e-2,
-1.071,
28.99
],
"allowed_for_design": false
},
{
"type_variety": "openroadm_mw_mw_preamp",
"type_def": "openroadm_preamp",
"gain_flatmax": 27,
"gain_min": 0,
"p_max": 22,
"allowed_for_design": false
},
{
"type_variety": "openroadm_mw_mw_preamp_typical_ver5",
"type_def": "openroadm",
"gain_flatmax": 27,
"gain_min": 0,
"p_max": 22,
"nf_coef": [
-5.952e-4,
-6.250e-2,
-1.071,
28.99
],
"allowed_for_design": false
},
{
"type_variety": "openroadm_mw_mw_preamp_worstcase_ver5",
"type_def": "openroadm",
"gain_flatmax": 27,
"gain_min": 0,
"p_max": 22,
"nf_coef": [
-5.952e-4,
-6.250e-2,
-1.071,
27.99
],
"allowed_for_design": false
},
{
"type_variety": "openroadm_mw_mw_booster",
"type_def": "openroadm_booster",
"gain_flatmax": 32,
"gain_min": 0,
"p_max": 22,
"allowed_for_design": false
},
{
"type_variety": "std_high_gain",
"type_def": "variable_gain",
"gain_flatmax": 35,
"gain_min": 25,
"p_max": 21,
"nf_min": 5.5,
"nf_max": 7,
"out_voa_auto": false,
"allowed_for_design": true
},
{
"type_variety": "std_medium_gain",
"type_def": "variable_gain",
"gain_flatmax": 26,
"gain_min": 15,
"p_max": 23,
"nf_min": 6,
"nf_max": 10,
"out_voa_auto": false,
"allowed_for_design": true
},
{
"type_variety": "std_low_gain",
"type_def": "variable_gain",
"gain_flatmax": 16,
"gain_min": 8,
"p_max": 23,
"nf_min": 6.5,
"nf_max": 11,
"out_voa_auto": false,
"allowed_for_design": true
},
{
"type_variety": "high_power",
"type_def": "variable_gain",
"gain_flatmax": 16,
"gain_min": 8,
"p_max": 25,
"nf_min": 9,
"nf_max": 15,
"out_voa_auto": false,
"allowed_for_design": false
},
{
"type_variety": "std_fixed_gain",
"type_def": "fixed_gain",
"gain_flatmax": 21,
"gain_min": 20,
"p_max": 21,
"nf0": 5.5,
"allowed_for_design": false
},
{
"type_variety": "4pumps_raman",
"type_def": "fixed_gain",
"gain_flatmax": 12,
"gain_min": 12,
"p_max": 21,
"nf0": -1,
"allowed_for_design": false
},
{
"type_variety": "hybrid_4pumps_lowgain",
"type_def": "dual_stage",
"raman": true,
"gain_min": 25,
"preamp_variety": "4pumps_raman",
"booster_variety": "std_low_gain",
"allowed_for_design": true
},
{
"type_variety": "hybrid_4pumps_mediumgain",
"type_def": "dual_stage",
"raman": true,
"gain_min": 25,
"preamp_variety": "4pumps_raman",
"booster_variety": "std_medium_gain",
"allowed_for_design": true
},
{
"type_variety": "medium+low_gain",
"type_def": "dual_stage",
"gain_min": 25,
"preamp_variety": "std_medium_gain",
"booster_variety": "std_low_gain",
"allowed_for_design": true
},
{
"type_variety": "medium+high_power",
"type_def": "dual_stage",
"gain_min": 25,
"preamp_variety": "std_medium_gain",
"booster_variety": "high_power",
"allowed_for_design": false
}
],
"Fiber": [
{
"type_variety": "SSMF",
"dispersion": 1.67e-05,
"effective_area": 83e-12,
"pmd_coef": 1.265e-15
},
{
"type_variety": "NZDF",
"dispersion": 0.5e-05,
"effective_area": 72e-12,
"pmd_coef": 1.265e-15
},
{
"type_variety": "LOF",
"dispersion": 2.2e-05,
"effective_area": 125e-12,
"pmd_coef": 1.265e-15
}
],
"RamanFiber": [
{
"type_variety": "SSMF",
"dispersion": 1.67e-05,
"effective_area": 83e-12,
"pmd_coef": 1.265e-15
}
],
"Span": [
{
"power_mode": true,
"delta_power_range_db": [
-2,
3,
0.5
],
"max_fiber_lineic_loss_for_raman": 0.25,
"target_extended_gain": 2.5,
"max_length": 150,
"length_units": "km",
"max_loss": 28,
"padding": 10,
"EOL": 0,
"con_in": 0,
"con_out": 0
}
],
"Roadm": [
{
"target_pch_out_db": -20,
"add_drop_osnr": 38,
"pmd": 0,
"pdl": 0,
"restrictions": {
"preamp_variety_list": [],
"booster_variety_list": []
}
},
{
"type_variety": "roadm_type_1",
"target_pch_out_db": -18,
"add_drop_osnr": 35,
"pmd": 0,
"pdl": 0,
"restrictions": {
"preamp_variety_list": [],
"booster_variety_list": []
},
"roadm-path-impairments": []
},
{
"type_variety": "detailed_impairments",
"target_pch_out_db": -20,
"add_drop_osnr": 38,
"pmd": 0,
"pdl": 0,
"restrictions": {
"preamp_variety_list": [],
"booster_variety_list": []
},
"roadm-path-impairments": [
{
"roadm-path-impairments-id": 0,
"roadm-express-path": [
{
"frequency-range": {
"lower-frequency": 191.3e12,
"upper-frequency": 196.1e12
},
"roadm-pmd": 0,
"roadm-cd": 0,
"roadm-pdl": 0,
"roadm-inband-crosstalk": 0,
"roadm-maxloss": 16.5
}
]
},
{
"roadm-path-impairments-id": 1,
"roadm-add-path": [
{
"frequency-range": {
"lower-frequency": 191.3e12,
"upper-frequency": 196.1e12
},
"roadm-pmd": 0,
"roadm-cd": 0,
"roadm-pdl": 0,
"roadm-inband-crosstalk": 0,
"roadm-maxloss": 11.5,
"roadm-pmax": 2.5,
"roadm-osnr": 41,
"roadm-noise-figure": 23
}
]
},
{
"roadm-path-impairments-id": 2,
"roadm-drop-path": [
{
"frequency-range": {
"lower-frequency": 191.3e12,
"upper-frequency": 196.1e12
},
"roadm-pmd": 0,
"roadm-cd": 0,
"roadm-pdl": 0,
"roadm-inband-crosstalk": 0,
"roadm-maxloss": 11.5,
"roadm-minloss": 7.5,
"roadm-typloss": 10,
"roadm-pmin": -13.5,
"roadm-pmax": -9.5,
"roadm-ptyp": -12,
"roadm-osnr": 41,
"roadm-noise-figure": 15
}
]
}
]
}
],
"SI": [
{
"f_min": 191.3e12,
"baud_rate": 32e9,
"f_max": 195.1e12,
"spacing": 50e9,
"power_dbm": 0,
"power_range_db": [
0,
0,
1
],
"tx_power_dbm": 0,
"roll_off": 0.15,
"tx_osnr": 40,
"sys_margins": 2,
"use_si_channel_count_for_design": true
}
],
"Transceiver": [
{
"type_variety": "vendorA_trx-type1",
"frequency": {
"min": 191.35e12,
"max": 196.1e12
},
"mode": [
{
"format": "mode 1",
"baud_rate": 32e9,
"OSNR": 11,
"bit_rate": 100e9,
"roll_off": 0.15,
"tx_osnr": 40,
"min_spacing": 37.5e9,
"cost": 1
},
{
"format": "mode 2",
"baud_rate": 66e9,
"OSNR": 15,
"bit_rate": 200e9,
"roll_off": 0.15,
"tx_osnr": 40,
"min_spacing": 75e9,
"cost": 1
}
]
},
{
"type_variety": "Voyager",
"frequency": {
"min": 191.35e12,
"max": 196.1e12
},
"mode": [
{
"format": "mode 1",
"baud_rate": 32e9,
"OSNR": 12,
"bit_rate": 100e9,
"roll_off": 0.15,
"tx_osnr": 40,
"min_spacing": 37.5e9,
"cost": 1
},
{
"format": "mode 3",
"baud_rate": 44e9,
"OSNR": 18,
"bit_rate": 300e9,
"roll_off": 0.15,
"tx_osnr": 40,
"min_spacing": 62.5e9,
"cost": 1
},
{
"format": "mode 2",
"baud_rate": 66e9,
"OSNR": 21,
"bit_rate": 400e9,
"roll_off": 0.15,
"tx_osnr": 40,
"min_spacing": 75e9,
"cost": 1
},
{
"format": "mode 4",
"baud_rate": 66e9,
"OSNR": 16,
"bit_rate": 200e9,
"roll_off": 0.15,
"tx_osnr": 40,
"min_spacing": 75e9,
"cost": 1
}
]
}
]
}

View File

@@ -0,0 +1,479 @@
{
"Edfa": [
{
"type_variety": "std_high_gain",
"type_def": "variable_gain",
"gain_flatmax": 35,
"gain_min": 25,
"p_max": 21,
"nf_min": 5.5,
"nf_max": 7,
"out_voa_auto": false,
"allowed_for_design": true
},
{
"type_variety": "std_medium_gain",
"type_def": "variable_gain",
"gain_flatmax": 26,
"gain_min": 15,
"p_max": 23,
"nf_min": 6,
"nf_max": 10,
"out_voa_auto": false,
"allowed_for_design": true
},
{
"type_variety": "std_low_gain_reduced",
"type_def": "variable_gain",
"gain_flatmax": 16,
"gain_min": 8,
"p_max": 23,
"nf_min": 6.5,
"nf_max": 11,
"out_voa_auto": false,
"allowed_for_design": true
},
{
"type_variety": "high_power",
"type_def": "variable_gain",
"gain_flatmax": 16,
"gain_min": 8,
"p_max": 25,
"nf_min": 9,
"nf_max": 15,
"out_voa_auto": false,
"allowed_for_design": false
},
{
"type_variety": "std_fixed_gain",
"type_def": "fixed_gain",
"gain_flatmax": 21,
"gain_min": 20,
"p_max": 21,
"nf0": 5.5,
"allowed_for_design": false
},
{
"type_variety": "4pumps_raman",
"type_def": "fixed_gain",
"gain_flatmax": 12,
"gain_min": 12,
"p_max": 21,
"nf0": -1,
"allowed_for_design": false
},
{
"type_variety": "hybrid_4pumps_lowgain",
"type_def": "dual_stage",
"raman": true,
"gain_min": 25,
"preamp_variety": "4pumps_raman",
"booster_variety": "std_low_gain",
"allowed_for_design": true
},
{
"type_variety": "hybrid_4pumps_mediumgain",
"type_def": "dual_stage",
"raman": true,
"gain_min": 25,
"preamp_variety": "4pumps_raman",
"booster_variety": "std_medium_gain",
"allowed_for_design": true
},
{
"type_variety": "medium+low_gain",
"type_def": "dual_stage",
"gain_min": 25,
"preamp_variety": "std_medium_gain",
"booster_variety": "std_low_gain",
"allowed_for_design": true
},
{
"type_variety": "medium+high_power",
"type_def": "dual_stage",
"gain_min": 25,
"preamp_variety": "std_medium_gain",
"booster_variety": "high_power",
"allowed_for_design": false
},
{
"type_variety": "std_medium_gain_C",
"f_min": 191.225e12,
"f_max": 196.125e12,
"type_def": "variable_gain",
"gain_flatmax": 26,
"gain_min": 15,
"p_max": 21,
"nf_min": 6,
"nf_max": 10,
"out_voa_auto": false,
"allowed_for_design": false
},
{
"type_variety": "std_medium_gain_L",
"f_min": 186.5e12,
"f_max": 190.1e12,
"type_def": "variable_gain",
"gain_flatmax": 26,
"gain_min": 15,
"p_max": 21,
"nf_min": 6,
"nf_max": 10,
"out_voa_auto": false,
"allowed_for_design": true
},
{
"type_variety": "std_low_gain",
"f_min": 191.25e12,
"f_max": 196.15e12,
"type_def": "variable_gain",
"gain_flatmax": 16,
"gain_min": 8,
"p_max": 21,
"nf_min": 7,
"nf_max": 11,
"out_voa_auto": false,
"allowed_for_design": true
},
{
"type_variety": "std_low_gain_reduced_band",
"f_min": 192.25e12,
"f_max": 196.15e12,
"type_def": "variable_gain",
"gain_flatmax": 16,
"gain_min": 8,
"p_max": 21,
"nf_min": 7,
"nf_max": 11,
"out_voa_auto": false,
"allowed_for_design": true
},
{
"type_variety": "std_low_gain_bis",
"f_min": 191.25e12,
"f_max": 196.15e12,
"type_def": "variable_gain",
"gain_flatmax": 16,
"gain_min": 8,
"p_max": 21,
"nf_min": 6,
"nf_max": 10,
"out_voa_auto": false,
"allowed_for_design": true
},
{
"type_variety": "std_low_gain_L_ter",
"f_min": 186.55e12,
"f_max": 190.05e12,
"type_def": "variable_gain",
"gain_flatmax": 16,
"gain_min": 8,
"p_max": 16,
"nf_min": 7,
"nf_max": 11,
"out_voa_auto": false,
"allowed_for_design": true
},
{
"type_variety": "std_low_gain_L",
"f_min": 186.55e12,
"f_max": 190.05e12,
"type_def": "variable_gain",
"gain_flatmax": 16,
"gain_min": 8,
"p_max": 21,
"nf_min": 7,
"nf_max": 11,
"out_voa_auto": false,
"allowed_for_design": true
},
{
"type_variety": "std_low_gain_L_reduced_band",
"f_min": 187.3e12,
"f_max": 190.05e12,
"type_def": "variable_gain",
"gain_flatmax": 16,
"gain_min": 8,
"p_max": 21,
"nf_min": 7,
"nf_max": 11,
"out_voa_auto": false,
"allowed_for_design": true
},
{
"type_variety": "test",
"type_def": "variable_gain",
"gain_flatmax": 25,
"gain_min": 15,
"p_max": 21,
"nf_min": 5.8,
"nf_max": 10,
"out_voa_auto": false,
"allowed_for_design": true
},
{
"type_variety": "test_fixed_gain",
"type_def": "fixed_gain",
"gain_flatmax": 21,
"gain_min": 20,
"p_max": 21,
"nf0": 5,
"allowed_for_design": true
},
{
"type_variety": "std_booster",
"type_def": "fixed_gain",
"gain_flatmax": 21,
"gain_min": 20,
"p_max": 21,
"nf0": 5,
"allowed_for_design": false
},
{
"type_variety": "std_booster_L",
"f_min": 186.55e12,
"f_max": 190.05e12,
"type_def": "fixed_gain",
"gain_flatmax": 21,
"gain_min": 20,
"p_max": 21,
"nf0": 5,
"allowed_for_design": false
},
{
"type_variety": "std_booster_multiband",
"type_def": "multi_band",
"amplifiers": [
"std_booster",
"std_booster_L"
],
"allowed_for_design": false
},
{
"type_variety": "std_medium_gain_multiband",
"type_def": "multi_band",
"amplifiers": [
"std_medium_gain_C",
"std_medium_gain_L"
],
"allowed_for_design": false
},
{
"type_variety": "std_low_gain_multiband",
"type_def": "multi_band",
"amplifiers": [
"std_low_gain",
"std_low_gain_L"
],
"allowed_for_design": false
},
{
"type_variety": "std_low_gain_multiband_ter",
"type_def": "multi_band",
"amplifiers": [
"std_low_gain",
"std_low_gain_L_ter"
],
"allowed_for_design": false
},
{
"type_variety": "std_low_gain_multiband_bis",
"type_def": "multi_band",
"amplifiers": [
"std_low_gain_bis",
"std_low_gain_L"
],
"allowed_for_design": true
},
{
"type_variety": "std_low_gain_multiband_reduced",
"type_def": "multi_band",
"amplifiers": [
"std_low_gain_reduced",
"std_low_gain_L"
],
"allowed_for_design": true
},
{
"type_variety": "std_low_gain_multiband_reduced_bis",
"type_def": "multi_band",
"amplifiers": [
"std_low_gain_bis",
"std_low_gain_L_reduced_band"
],
"allowed_for_design": true
}
],
"Fiber": [
{
"type_variety": "SSMF",
"dispersion": 1.67e-05,
"effective_area": 83e-12,
"pmd_coef": 1.265e-15
},
{
"type_variety": "NZDF",
"dispersion": 0.5e-05,
"effective_area": 72e-12,
"pmd_coef": 1.265e-15
},
{
"type_variety": "LOF",
"dispersion": 2.2e-05,
"effective_area": 125e-12,
"pmd_coef": 1.265e-15
}
],
"RamanFiber": [
{
"type_variety": "SSMF",
"dispersion": 1.67e-05,
"effective_area": 83e-12,
"pmd_coef": 1.265e-15
}
],
"Span": [
{
"power_mode": true,
"delta_power_range_db": [
-2,
3,
0.5
],
"max_fiber_lineic_loss_for_raman": 0.25,
"target_extended_gain": 2.5,
"max_length": 150,
"length_units": "km",
"max_loss": 28,
"padding": 10,
"EOL": 0,
"con_in": 0,
"con_out": 0
}
],
"Roadm": [
{
"target_pch_out_db": -20,
"add_drop_osnr": 38,
"pmd": 0,
"pdl": 0,
"restrictions": {
"preamp_variety_list": [],
"booster_variety_list": []
}
}
],
"SI": [
{
"f_min": 191.3e12,
"baud_rate": 32e9,
"f_max": 195.1e12,
"spacing": 50e9,
"power_dbm": 0,
"power_range_db": [
0,
0,
1
],
"roll_off": 0.15,
"tx_osnr": 40,
"sys_margins": 2
},
{
"type_variety": "lband",
"f_min": 186.3e12,
"baud_rate": 32e9,
"f_max": 190.1e12,
"spacing": 50e9,
"power_dbm": 0,
"power_range_db": [
0,
0,
1
],
"roll_off": 0.15,
"tx_osnr": 40,
"sys_margins": 2
}
],
"Transceiver": [
{
"type_variety": "vendorA_trx-type1",
"frequency": {
"min": 191.35e12,
"max": 196.1e12
},
"mode": [
{
"format": "mode 1",
"baud_rate": 32e9,
"OSNR": 11,
"bit_rate": 100e9,
"roll_off": 0.15,
"tx_osnr": 40,
"min_spacing": 37.5e9,
"cost": 1
},
{
"format": "mode 2",
"baud_rate": 66e9,
"OSNR": 15,
"bit_rate": 200e9,
"roll_off": 0.15,
"tx_osnr": 40,
"min_spacing": 75e9,
"cost": 1
}
]
},
{
"type_variety": "Voyager",
"frequency": {
"min": 191.35e12,
"max": 196.1e12
},
"mode": [
{
"format": "mode 1",
"baud_rate": 32e9,
"OSNR": 12,
"bit_rate": 100e9,
"roll_off": 0.15,
"tx_osnr": 40,
"min_spacing": 37.5e9,
"cost": 1
},
{
"format": "mode 3",
"baud_rate": 44e9,
"OSNR": 18,
"bit_rate": 300e9,
"roll_off": 0.15,
"tx_osnr": 40,
"min_spacing": 62.5e9,
"cost": 1
},
{
"format": "mode 2",
"baud_rate": 66e9,
"OSNR": 21,
"bit_rate": 400e9,
"roll_off": 0.15,
"tx_osnr": 40,
"min_spacing": 75e9,
"cost": 1
},
{
"format": "mode 4",
"baud_rate": 66e9,
"OSNR": 16,
"bit_rate": 200e9,
"roll_off": 0.15,
"tx_osnr": 40,
"min_spacing": 75e9,
"cost": 1
}
]
}
]
}

View File

@@ -0,0 +1,371 @@
{
"Edfa": [
{
"type_variety": "openroadm_ila_low_noise",
"type_def": "openroadm",
"gain_flatmax": 27,
"gain_min": 0,
"p_max": 22,
"nf_coef": [
-8.104e-4,
-6.221e-2,
-5.889e-1,
37.62
],
"pmd": 3e-12,
"pdl": 0.7,
"allowed_for_design": true
},
{
"type_variety": "openroadm_ila_standard",
"type_def": "openroadm",
"gain_flatmax": 27,
"gain_min": 0,
"p_max": 22,
"nf_coef": [
-5.952e-4,
-6.250e-2,
-1.071,
28.99
],
"pmd": 3e-12,
"pdl": 0.7,
"allowed_for_design": true
},
{
"type_variety": "openroadm_mw_mw_preamp",
"type_def": "openroadm_preamp",
"gain_flatmax": 27,
"gain_min": 0,
"p_max": 22,
"pmd": 0,
"pdl": 0,
"allowed_for_design": false
},
{
"type_variety": "openroadm_mw_mw_booster",
"type_def": "openroadm_booster",
"gain_flatmax": 32,
"gain_min": 0,
"p_max": 22,
"pmd": 0,
"pdl": 0,
"allowed_for_design": false
}
],
"Fiber": [
{
"type_variety": "SSMF",
"dispersion": 1.67e-05,
"effective_area": 83e-12,
"pmd_coef": 1.265e-15
},
{
"type_variety": "NZDF",
"dispersion": 0.5e-05,
"effective_area": 72e-12,
"pmd_coef": 1.265e-15
},
{
"type_variety": "LOF",
"dispersion": 2.2e-05,
"effective_area": 125e-12,
"pmd_coef": 1.265e-15
}
],
"RamanFiber": [
{
"type_variety": "SSMF",
"dispersion": 1.67e-05,
"effective_area": 83e-12,
"pmd_coef": 1.265e-15
}
],
"Span": [
{
"power_mode": true,
"delta_power_range_db": [
0,
0,
0
],
"max_fiber_lineic_loss_for_raman": 0.25,
"target_extended_gain": 0,
"max_length": 135,
"length_units": "km",
"max_loss": 28,
"padding": 11,
"EOL": 0,
"con_in": 0,
"con_out": 0
}
],
"Roadm": [
{
"target_pch_out_db": -20,
"add_drop_osnr": 30,
"pmd": 3e-12,
"pdl": 1.5,
"restrictions": {
"preamp_variety_list": [
"openroadm_mw_mw_preamp"
],
"booster_variety_list": [
"openroadm_mw_mw_booster"
]
}
}
],
"SI": [
{
"f_min": 191.3e12,
"baud_rate": 31.57e9,
"f_max": 196.1e12,
"spacing": 50e9,
"power_dbm": 2,
"power_range_db": [
0,
0,
1
],
"roll_off": 0.15,
"tx_osnr": 35,
"sys_margins": 2
}
],
"Transceiver": [
{
"type_variety": "OpenROADM MSA ver. 4.0",
"frequency": {
"min": 191.35e12,
"max": 196.1e12
},
"mode": [
{
"format": "100 Gbit/s, 27.95 Gbaud, DP-QPSK",
"baud_rate": 27.95e9,
"OSNR": 17,
"bit_rate": 100e9,
"roll_off": null,
"tx_osnr": 33,
"penalties": [
{
"chromatic_dispersion": 4e3,
"penalty_value": 0
},
{
"chromatic_dispersion": 18e3,
"penalty_value": 0.5
},
{
"pmd": 10,
"penalty_value": 0
},
{
"pmd": 30,
"penalty_value": 0.5
},
{
"pdl": 1,
"penalty_value": 0.5
},
{
"pdl": 2,
"penalty_value": 1
},
{
"pdl": 4,
"penalty_value": 2.5
},
{
"pdl": 6,
"penalty_value": 4
}
],
"min_spacing": 50e9,
"cost": 1
},
{
"format": "100 Gbit/s, 31.57 Gbaud, DP-QPSK",
"baud_rate": 31.57e9,
"OSNR": 12,
"bit_rate": 100e9,
"roll_off": 0.15,
"tx_osnr": 35,
"penalties": [
{
"chromatic_dispersion": -1e3,
"penalty_value": 0
},
{
"chromatic_dispersion": 4e3,
"penalty_value": 0
},
{
"chromatic_dispersion": 40e3,
"penalty_value": 0.5
},
{
"pmd": 10,
"penalty_value": 0
},
{
"pmd": 30,
"penalty_value": 0.5
},
{
"pdl": 1,
"penalty_value": 0.5
},
{
"pdl": 2,
"penalty_value": 1
},
{
"pdl": 4,
"penalty_value": 2.5
},
{
"pdl": 6,
"penalty_value": 4
}
],
"min_spacing": 50e9,
"cost": 1
},
{
"format": "200 Gbit/s, DP-QPSK",
"baud_rate": 63.1e9,
"OSNR": 17,
"bit_rate": 200e9,
"roll_off": 0.15,
"tx_osnr": 36,
"penalties": [
{
"chromatic_dispersion": -1e3,
"penalty_value": 0
},
{
"chromatic_dispersion": 4e3,
"penalty_value": 0
},
{
"chromatic_dispersion": 24e3,
"penalty_value": 0.5
},
{
"pmd": 10,
"penalty_value": 0
},
{
"pmd": 25,
"penalty_value": 0.5
},
{
"pdl": 1,
"penalty_value": 0.5
},
{
"pdl": 2,
"penalty_value": 1
},
{
"pdl": 4,
"penalty_value": 2.5
}
],
"min_spacing": 87.5e9,
"cost": 1
},
{
"format": "300 Gbit/s, DP-8QAM",
"baud_rate": 63.1e9,
"OSNR": 21,
"bit_rate": 300e9,
"roll_off": 0.15,
"tx_osnr": 36,
"penalties": [
{
"chromatic_dispersion": -1e3,
"penalty_value": 0
},
{
"chromatic_dispersion": 4e3,
"penalty_value": 0
},
{
"chromatic_dispersion": 18e3,
"penalty_value": 0.5
},
{
"pmd": 10,
"penalty_value": 0
},
{
"pmd": 25,
"penalty_value": 0.5
},
{
"pdl": 1,
"penalty_value": 0.5
},
{
"pdl": 2,
"penalty_value": 1
},
{
"pdl": 4,
"penalty_value": 2.5
}
],
"min_spacing": 87.5e9,
"cost": 1
},
{
"format": "400 Gbit/s, DP-16QAM",
"baud_rate": 63.1e9,
"OSNR": 24,
"bit_rate": 400e9,
"roll_off": 0.15,
"tx_osnr": 36,
"penalties": [
{
"chromatic_dispersion": -1e3,
"penalty_value": 0
},
{
"chromatic_dispersion": 4e3,
"penalty_value": 0
},
{
"chromatic_dispersion": 12e3,
"penalty_value": 0.5
},
{
"pmd": 10,
"penalty_value": 0
},
{
"pmd": 20,
"penalty_value": 0.5
},
{
"pdl": 1,
"penalty_value": 0.5
},
{
"pdl": 2,
"penalty_value": 1
},
{
"pdl": 4,
"penalty_value": 2.5
}
],
"min_spacing": 87.5e9,
"cost": 1
}
]
}
]
}

View File

@@ -0,0 +1,441 @@
{
"Edfa": [
{
"type_variety": "openroadm_ila_low_noise",
"type_def": "openroadm",
"gain_flatmax": 27,
"gain_min": 0,
"p_max": 22,
"nf_coef": [
-8.104e-4,
-6.221e-2,
-5.889e-1,
37.62
],
"pmd": 3e-12,
"pdl": 0.7,
"allowed_for_design": true
},
{
"type_variety": "openroadm_ila_standard",
"type_def": "openroadm",
"gain_flatmax": 27,
"gain_min": 0,
"p_max": 22,
"nf_coef": [
-5.952e-4,
-6.250e-2,
-1.071,
28.99
],
"pmd": 3e-12,
"pdl": 0.7,
"allowed_for_design": true
},
{
"type_variety": "openroadm_mw_mw_preamp_typical_ver5",
"type_def": "openroadm",
"gain_flatmax": 27,
"gain_min": 0,
"p_max": 22,
"nf_coef": [
-5.952e-4,
-6.250e-2,
-1.071,
28.99
],
"pmd": 0,
"pdl": 0,
"allowed_for_design": false
},
{
"type_variety": "openroadm_mw_mw_preamp_worstcase_ver5",
"type_def": "openroadm",
"gain_flatmax": 27,
"gain_min": 0,
"p_max": 22,
"nf_coef": [
-5.952e-4,
-6.250e-2,
-1.071,
27.99
],
"pmd": 0,
"pdl": 0,
"allowed_for_design": false
},
{
"type_variety": "openroadm_mw_mw_booster",
"type_def": "openroadm_booster",
"gain_flatmax": 32,
"gain_min": 0,
"p_max": 22,
"pmd": 0,
"pdl": 0,
"allowed_for_design": false
}
],
"Fiber": [
{
"type_variety": "SSMF",
"dispersion": 1.67e-05,
"effective_area": 83e-12,
"pmd_coef": 1.265e-15
},
{
"type_variety": "NZDF",
"dispersion": 0.5e-05,
"effective_area": 72e-12,
"pmd_coef": 1.265e-15
},
{
"type_variety": "LOF",
"dispersion": 2.2e-05,
"effective_area": 125e-12,
"pmd_coef": 1.265e-15
}
],
"RamanFiber": [
{
"type_variety": "SSMF",
"dispersion": 1.67e-05,
"effective_area": 83e-12,
"pmd_coef": 1.265e-15
}
],
"Span": [
{
"power_mode": true,
"delta_power_range_db": [
0,
0,
0
],
"max_fiber_lineic_loss_for_raman": 0.25,
"target_extended_gain": 0,
"max_length": 135,
"length_units": "km",
"max_loss": 28,
"padding": 11,
"EOL": 0,
"con_in": 0,
"con_out": 0
}
],
"Roadm": [
{
"target_pch_out_db": -20,
"add_drop_osnr": 33,
"pmd": 3e-12,
"pdl": 1.5,
"restrictions": {
"preamp_variety_list": [
"openroadm_mw_mw_preamp_worstcase_ver5"
],
"booster_variety_list": [
"openroadm_mw_mw_booster"
]
}
}
],
"SI": [
{
"f_min": 191.3e12,
"baud_rate": 31.57e9,
"f_max": 196.1e12,
"spacing": 50e9,
"power_dbm": 2,
"power_range_db": [
0,
0,
1
],
"roll_off": 0.15,
"tx_osnr": 35,
"sys_margins": 2
}
],
"Transceiver": [
{
"type_variety": "OpenROADM MSA ver. 5.0",
"frequency": {
"min": 191.35e12,
"max": 196.1e12
},
"mode": [
{
"format": "100 Gbit/s, 27.95 Gbaud, DP-QPSK",
"baud_rate": 27.95e9,
"OSNR": 17,
"bit_rate": 100e9,
"roll_off": null,
"tx_osnr": 33,
"penalties": [
{
"chromatic_dispersion": 4e3,
"penalty_value": 0
},
{
"chromatic_dispersion": 18e3,
"penalty_value": 0.5
},
{
"pmd": 10,
"penalty_value": 0
},
{
"pmd": 30,
"penalty_value": 0.5
},
{
"pdl": 1,
"penalty_value": 0.5
},
{
"pdl": 2,
"penalty_value": 1
},
{
"pdl": 4,
"penalty_value": 2.5
},
{
"pdl": 6,
"penalty_value": 4
}
],
"min_spacing": 50e9,
"cost": 1
},
{
"format": "100 Gbit/s, 31.57 Gbaud, DP-QPSK",
"baud_rate": 31.57e9,
"OSNR": 12,
"bit_rate": 100e9,
"roll_off": 0.15,
"tx_osnr": 36,
"penalties": [
{
"chromatic_dispersion": -1e3,
"penalty_value": 0
},
{
"chromatic_dispersion": 4e3,
"penalty_value": 0
},
{
"chromatic_dispersion": 48e3,
"penalty_value": 0.5
},
{
"pmd": 10,
"penalty_value": 0
},
{
"pmd": 30,
"penalty_value": 0.5
},
{
"pdl": 1,
"penalty_value": 0.5
},
{
"pdl": 2,
"penalty_value": 1
},
{
"pdl": 4,
"penalty_value": 2.5
},
{
"pdl": 6,
"penalty_value": 4
}
],
"min_spacing": 50e9,
"cost": 1
},
{
"format": "200 Gbit/s, 31.57 Gbaud, DP-16QAM",
"baud_rate": 31.57e9,
"OSNR": 20.5,
"bit_rate": 100e9,
"roll_off": 0.15,
"tx_osnr": 36,
"penalties": [
{
"chromatic_dispersion": -1e3,
"penalty_value": 0
},
{
"chromatic_dispersion": 4e3,
"penalty_value": 0
},
{
"chromatic_dispersion": 24e3,
"penalty_value": 0.5
},
{
"pmd": 10,
"penalty_value": 0
},
{
"pmd": 30,
"penalty_value": 0.5
},
{
"pdl": 1,
"penalty_value": 0.5
},
{
"pdl": 2,
"penalty_value": 1
},
{
"pdl": 4,
"penalty_value": 2.5
},
{
"pdl": 6,
"penalty_value": 4
}
],
"min_spacing": 50e9,
"cost": 1
},
{
"format": "200 Gbit/s, DP-QPSK",
"baud_rate": 63.1e9,
"OSNR": 17,
"bit_rate": 200e9,
"roll_off": 0.15,
"tx_osnr": 36,
"penalties": [
{
"chromatic_dispersion": -1e3,
"penalty_value": 0
},
{
"chromatic_dispersion": 4e3,
"penalty_value": 0
},
{
"chromatic_dispersion": 24e3,
"penalty_value": 0.5
},
{
"pmd": 10,
"penalty_value": 0
},
{
"pmd": 25,
"penalty_value": 0.5
},
{
"pdl": 1,
"penalty_value": 0.5
},
{
"pdl": 2,
"penalty_value": 1
},
{
"pdl": 4,
"penalty_value": 2.5
}
],
"min_spacing": 87.5e9,
"cost": 1
},
{
"format": "300 Gbit/s, DP-8QAM",
"baud_rate": 63.1e9,
"OSNR": 21,
"bit_rate": 300e9,
"roll_off": 0.15,
"tx_osnr": 36,
"penalties": [
{
"chromatic_dispersion": -1e3,
"penalty_value": 0
},
{
"chromatic_dispersion": 4e3,
"penalty_value": 0
},
{
"chromatic_dispersion": 18e3,
"penalty_value": 0.5
},
{
"pmd": 10,
"penalty_value": 0
},
{
"pmd": 25,
"penalty_value": 0.5
},
{
"pdl": 1,
"penalty_value": 0.5
},
{
"pdl": 2,
"penalty_value": 1
},
{
"pdl": 4,
"penalty_value": 2.5
}
],
"min_spacing": 87.5e9,
"cost": 1
},
{
"format": "400 Gbit/s, DP-16QAM",
"baud_rate": 63.1e9,
"OSNR": 24,
"bit_rate": 400e9,
"roll_off": 0.15,
"tx_osnr": 36,
"penalties": [
{
"chromatic_dispersion": -1e3,
"penalty_value": 0
},
{
"chromatic_dispersion": 4e3,
"penalty_value": 0
},
{
"chromatic_dispersion": 12e3,
"penalty_value": 0.5
},
{
"pmd": 10,
"penalty_value": 0
},
{
"pmd": 20,
"penalty_value": 0.5
},
{
"pdl": 1,
"penalty_value": 0.5
},
{
"pdl": 2,
"penalty_value": 1
},
{
"pdl": 4,
"penalty_value": 2.5
}
],
"min_spacing": 87.5e9,
"cost": 1
}
]
}
]
}

View File

@@ -0,0 +1,74 @@
{
"Edfa": [
{
"type_variety": "user_defined",
"type_def": "variable_gain",
"f_min": 192.0e12,
"f_max": 195.9e12,
"gain_flatmax": 25,
"gain_min": 15,
"p_max": 21,
"nf_min": 6,
"nf_max": 10,
"default_config_from_json": "user_edfa_config.json",
"out_voa_auto": false,
"allowed_for_design": true
}, {
"type_variety": "user_high_detail_model_example",
"type_def": "advanced_model",
"gain_flatmax": 25,
"gain_min": 15,
"p_max": 21,
"advanced_config_from_json": "std_medium_gain_advanced_config.json",
"out_voa_auto": false,
"allowed_for_design": false
}
],
"Transceiver": [
{
"type_variety": "ZR400G",
"frequency": {
"min": 191.3e12,
"max": 196.1e12
},
"mode": [
{
"format": "SFF-ID:70",
"baud_rate": 60138546798,
"OSNR": 24,
"bit_rate": 400e9,
"roll_off": 0.2,
"tx_osnr": 34,
"min_spacing": 75e9,
"penalties": [
{
"chromatic_dispersion": 20e3,
"penalty_value": 0.5
},
{
"chromatic_dispersion": 0,
"penalty_value": 0
},
{
"pmd": 20,
"penalty_value": 0.5
},
{
"pdl": 1.5,
"penalty_value": 0
},
{
"pdl": 3.5,
"penalty_value": 1.8
},
{
"pdl": 3,
"penalty_value": 1.3
}
],
"cost": 1
}
]
}
]
}

View File

@@ -0,0 +1,196 @@
{
"elements": [
{
"uid": "trx Site_A",
"metadata": {
"location": {
"city": "Site_A",
"region": "",
"latitude": 0,
"longitude": 0
}
},
"type": "Transceiver"
},
{
"uid": "trx Site_C",
"metadata": {
"location": {
"city": "Site_C",
"region": "",
"latitude": 0,
"longitude": 0
}
},
"type": "Transceiver"
},
{
"uid": "roadm Site_A",
"metadata": {
"location": {
"city": "Site_A",
"region": "",
"latitude": 0,
"longitude": 0
}
},
"type": "Roadm",
"params": {
"loss": 17
}
},
{
"uid": "roadm Site_C",
"metadata": {
"location": {
"city": "Site_C",
"region": "",
"latitude": 0,
"longitude": 0
}
},
"type": "Roadm"
},
{
"uid": "ingress fused spans in Site_B",
"metadata": {
"location": {
"city": "Site_B",
"region": "",
"latitude": 0,
"longitude": 0
}
},
"type": "Fused",
"params": {
"loss": 0.5
}
},
{
"uid": "egress fused spans in Site_B",
"metadata": {
"location": {
"city": "Site_B",
"region": "",
"latitude": 0,
"longitude": 0
}
},
"type": "Fused"
},
{
"uid": "fiber (Site_A \u2192 Site_B)-",
"metadata": {
"location": {
"latitude": 0.0,
"longitude": 0.0
}
},
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 40.0,
"length_units": "km",
"loss_coef": 0.2
}
},
{
"uid": "fiber (Site_B \u2192 Site_C)-",
"metadata": {
"location": {
"latitude": 0.0,
"longitude": 0.0
}
},
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 50.0,
"length_units": "km",
"loss_coef": 0.2
}
},
{
"uid": "fiber (Site_B \u2192 Site_A)-",
"metadata": {
"location": {
"latitude": 0.0,
"longitude": 0.0
}
},
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 40.0,
"length_units": "km",
"loss_coef": 0.2
}
},
{
"uid": "fiber (Site_C \u2192 Site_B)-",
"metadata": {
"location": {
"latitude": 0.0,
"longitude": 0.0
}
},
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 50.0,
"length_units": "km",
"loss_coef": 0.2
}
}
],
"connections": [
{
"from_node": "roadm Site_A",
"to_node": "fiber (Site_A \u2192 Site_B)-"
},
{
"from_node": "fiber (Site_B \u2192 Site_A)-",
"to_node": "roadm Site_A"
},
{
"from_node": "fiber (Site_A \u2192 Site_B)-",
"to_node": "ingress fused spans in Site_B"
},
{
"from_node": "ingress fused spans in Site_B",
"to_node": "fiber (Site_B \u2192 Site_C)-"
},
{
"from_node": "fiber (Site_C \u2192 Site_B)-",
"to_node": "egress fused spans in Site_B"
},
{
"from_node": "egress fused spans in Site_B",
"to_node": "fiber (Site_B \u2192 Site_A)-"
},
{
"from_node": "roadm Site_C",
"to_node": "fiber (Site_C \u2192 Site_B)-"
},
{
"from_node": "fiber (Site_B \u2192 Site_C)-",
"to_node": "roadm Site_C"
},
{
"from_node": "trx Site_A",
"to_node": "roadm Site_A"
},
{
"from_node": "roadm Site_A",
"to_node": "trx Site_A"
},
{
"from_node": "trx Site_C",
"to_node": "roadm Site_C"
},
{
"from_node": "roadm Site_C",
"to_node": "trx Site_C"
}
]
}

View File

@@ -0,0 +1,12 @@
{
"spectrum": [
{
"f_min": 191.35e12,
"f_max": 195.1e12,
"baud_rate": 32e9,
"slot_width": 50e9,
"roll_off": 0.15,
"tx_osnr": 40
}
]
}

View File

@@ -0,0 +1,23 @@
{
"spectrum": [
{
"f_min": 191.4e12,
"f_max": 193.1e12,
"baud_rate": 32e9,
"slot_width": 50e9,
"delta_pdb": 0,
"roll_off": 0.15,
"tx_osnr": 40,
"label": "mode_1"
},
{
"f_min": 193.1625e12,
"f_max": 195e12,
"baud_rate": 64e9,
"slot_width": 75e9,
"roll_off": 0.15,
"tx_osnr": 40,
"label": "mode_2"
}
]
}

Some files were not shown because too many files have changed in this diff Show More