106 Commits
v2.5 ... v2.8

Author SHA1 Message Date
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
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
89 changed files with 7497 additions and 2407 deletions

View File

@@ -1,47 +0,0 @@
#!/bin/bash
set -e
IMAGE_NAME=telecominfraproject/oopt-gnpy
IMAGE_TAG=$(git describe --tags)
ALREADY_FOUND=0
docker pull ${IMAGE_NAME}:${IMAGE_TAG} && ALREADY_FOUND=1
if [[ $ALREADY_FOUND == 0 ]]; then
docker build . -t ${IMAGE_NAME}
docker tag ${IMAGE_NAME} ${IMAGE_NAME}:${IMAGE_TAG}
# shared directory setup: do not clobber the real data
mkdir trash
cd trash
docker run -it --rm --volume $(pwd):/shared ${IMAGE_NAME} gnpy-transmission-example
else
echo "Image ${IMAGE_NAME}:${IMAGE_TAG} already available, will just update the other tags"
fi
docker images
do_docker_login() {
echo "${DOCKER_PASSWORD}" | docker login -u "${DOCKER_USERNAME}" --password-stdin
}
if [[ "${TRAVIS_PULL_REQUEST}" == "false" ]]; then
if [[ "${TRAVIS_BRANCH}" == "develop" || "${TRAVIS_BRANCH}" == "docker" ]]; then
echo "Publishing latest"
docker tag ${IMAGE_NAME}:${IMAGE_TAG} ${IMAGE_NAME}:latest
do_docker_login
if [[ $ALREADY_FOUND == 0 ]]; then
docker push ${IMAGE_NAME}:${IMAGE_TAG}
fi
docker push ${IMAGE_NAME}:latest
elif [[ "${TRAVIS_BRANCH}" == "master" ]]; then
echo "Publishing stable"
docker tag ${IMAGE_NAME}:${IMAGE_TAG} ${IMAGE_NAME}:stable
do_docker_login
if [[ $ALREADY_FOUND == 0 ]]; then
docker push ${IMAGE_NAME}:${IMAGE_TAG}
fi
docker push ${IMAGE_NAME}:stable
fi
fi

View File

@@ -11,23 +11,26 @@ jobs:
name: Tox test name: Tox test
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
with: with:
fetch-depth: 0 fetch-depth: 0
- uses: fedora-python/tox-github-action@v0.4 - uses: fedora-python/tox-github-action@v0.4
with: with:
tox_env: ${{ matrix.tox_env }} tox_env: ${{ matrix.tox_env }}
dnf_install: ${{ matrix.dnf_install }} dnf_install: ${{ matrix.dnf_install }}
- uses: codecov/codecov-action@29386c70ef20e286228c72b668a06fd0e8399192 - uses: codecov/codecov-action@v3.1.1
if: ${{ endswith(matrix.tox_env, '-cover') }} if: ${{ endswith(matrix.tox_env, '-cover') }}
with: with:
files: ${{ github.workspace }}/cover/coverage.xml files: ${{ github.workspace }}/cover/coverage.xml
strategy: strategy:
fail-fast: false
matrix: matrix:
tox_env: tox_env:
- py38 - py38
- py39 - py39
- py310-cover - py310
- py311
- py312-cover
include: include:
- tox_env: docs - tox_env: docs
dnf_install: graphviz dnf_install: graphviz
@@ -38,13 +41,13 @@ jobs:
name: PyPI packaging name: PyPI packaging
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
with: with:
fetch-depth: 0 fetch-depth: 0
- uses: actions/setup-python@v2 - uses: actions/setup-python@v4
name: Install Python name: Install Python
with: with:
python-version: '3.10' python-version: '3.12'
- uses: casperdcl/deploy-pypi@bb869aafd89f657ceaafe9561d3b5584766c0f95 - uses: casperdcl/deploy-pypi@bb869aafd89f657ceaafe9561d3b5584766c0f95
with: with:
password: ${{ secrets.PYPI_API_TOKEN }} password: ${{ secrets.PYPI_API_TOKEN }}
@@ -62,7 +65,7 @@ jobs:
with: with:
username: jktjkt username: jktjkt
password: ${{ secrets.DOCKERHUB_TOKEN }} password: ${{ secrets.DOCKERHUB_TOKEN }}
- uses: actions/checkout@v2 - uses: actions/checkout@v3
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Extract tag name - name: Extract tag name
@@ -92,21 +95,53 @@ jobs:
telecominfraproject/oopt-gnpy:${{ steps.extract_tag_name.outputs.GIT_DESC }} telecominfraproject/oopt-gnpy:${{ steps.extract_tag_name.outputs.GIT_DESC }}
telecominfraproject/oopt-gnpy:latest telecominfraproject/oopt-gnpy:latest
windows: other-platforms:
name: Tests on Windows name: Tests on other platforms
runs-on: windows-2019 runs-on: ${{ matrix.os }}
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
with: with:
fetch-depth: 0 fetch-depth: 0
- uses: actions/setup-python@v2 - uses: actions/setup-python@v4
with: with:
python-version: ${{ matrix.python_version }} python-version: ${{ matrix.python_version }}
- run: | - run: |
pip install -r tests/requirements.txt
pip install --editable . pip install --editable .
pip install 'pytest>=6.2.5,<7'
pytest -vv pytest -vv
strategy: strategy:
fail-fast: false
matrix: matrix:
python_version: include:
- "3.10" - os: windows-2019
python_version: "3.10"
- os: windows-2022
python_version: "3.11"
- os: windows-2022
python_version: "3.12"
- os: macos-12
python_version: "3.11"
- os: macos-13
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 -r tests/requirements.txt
pip install --editable .
pytest -vv
strategy:
fail-fast: false
matrix:
include:
- os: macos-13-xlarge # Apple M1 CPU
python_version: "3.12"

View File

@@ -1,27 +0,0 @@
dist: focal
os: linux
language: python
services: docker
python:
- "3.8"
- "3.9"
before_install:
- sudo apt-get -y install graphviz
install: skip
script:
- pip install --editable .
- pip install pytest-cov rstcheck
- pytest --cov-report=xml --cov=gnpy -v
- pip install -r docs/requirements.txt
- rstcheck --ignore-roles cite *.rst
- sphinx-build -W --keep-going docs/ x-throwaway-location
after_success:
- bash <(curl -s https://codecov.io/bash)
jobs:
include:
- stage: test
name: Docker image
script:
- git fetch --unshallow
- ./.docker-travis.sh
- docker images

View File

@@ -2,10 +2,18 @@
- project: - project:
check: check:
jobs: jobs:
- tox-py38 - tox-py38:
- tox-py39 vars:
- tox-py310-cover ensure_tox_version: '<4'
- tox-docs-f35 - 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: - coverage-diff:
voting: false voting: false
dependencies: dependencies:
@@ -16,7 +24,11 @@
coverage_job_name_current: tox-py310-cover coverage_job_name_current: tox-py310-cover
- tox-linters-diff-n-report: - tox-linters-diff-n-report:
voting: false voting: false
- tox-py310-cover-previous vars:
ensure_tox_version: '<4'
- tox-py310-cover-previous:
vars:
ensure_tox_version: '<4'
tag: tag:
jobs: jobs:
- oopt-release-python: - oopt-release-python:

View File

@@ -11,18 +11,21 @@ To learn how to contribute, please see CONTRIBUTING.md
- Brian Taylor (Facebook) <briantaylor@fb.com> - Brian Taylor (Facebook) <briantaylor@fb.com>
- David Boertjes (Ciena) <dboertje@ciena.com> - David Boertjes (Ciena) <dboertje@ciena.com>
- Diego Landa (Facebook) <dlanda@fb.com> - Diego Landa (Facebook) <dlanda@fb.com>
- Emmanuelle Delfour (Orange) <WEDE7391@orange.com>
- Esther Le Rouzic (Orange) <esther.lerouzic@orange.com> - Esther Le Rouzic (Orange) <esther.lerouzic@orange.com>
- Gabriele Galimberti (Cisco) <ggalimbe@cisco.com> - Gabriele Galimberti (Cisco) <ggalimbe@cisco.com>
- Gert Grammel (Juniper Networks) <ggrammel@juniper.net> - Gert Grammel (Juniper Networks) <ggrammel@juniper.net>
- Giacomo Borraccini (Politecnico di Torino) <giacomo.borraccini@polito.it>
- Gilad Goldfarb (Facebook) <giladg@fb.com> - Gilad Goldfarb (Facebook) <giladg@fb.com>
- James Powell (Telecom Infra Project) <james.powell@telecominfraproject.com> - James Powell (Telecom Infra Project) <james.powell@telecominfraproject.com>
- Jan Kundrát (Telecom Infra Project) <jan.kundrat@telecominfraproject.com> - Jan Kundrát (Telecom Infra Project) <jkt@jankundrat.com>
- Jeanluc Augé (Orange) <jeanluc.auge@orange.com> - Jeanluc Augé (Orange) <jeanluc.auge@orange.com>
- Jonas Mårtensson (RISE) <jonas.martensson@ri.se> - Jonas Mårtensson (RISE) <jonas.martensson@ri.se>
- Mattia Cantono (Politecnico di Torino) <mattia.cantono@polito.it> - Mattia Cantono (Politecnico di Torino) <mattia.cantono@polito.it>
- Miguel Garrich (University Catalunya) <miquel.garrich@upct.es> - Miguel Garrich (University Catalunya) <miquel.garrich@upct.es>
- Raj Nagarajan (Lumentum) <raj.nagarajan@lumentum.com> - Raj Nagarajan (Lumentum) <raj.nagarajan@lumentum.com>
- Roberts Miculens (Lattelecom) <roberts.miculens@lattelecom.lv> - Roberts Miculens (Lattelecom) <roberts.miculens@lattelecom.lv>
- Sami Alavi (NUST) <sami.mansooralavi1999@gmail.com>
- Shengxiang Zhu (University of Arizona) <szhu@email.arizona.edu> - Shengxiang Zhu (University of Arizona) <szhu@email.arizona.edu>
- Stefan Melin (Telia Company) <Stefan.Melin@teliacompany.com> - Stefan Melin (Telia Company) <Stefan.Melin@teliacompany.com>
- Vittorio Curri (Politecnico di Torino) <vittorio.curri@polito.it> - Vittorio Curri (Politecnico di Torino) <vittorio.curri@polito.it>

View File

@@ -3,12 +3,12 @@
[![Install via pip](https://img.shields.io/pypi/v/gnpy)](https://pypi.org/project/gnpy/) [![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/) [![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) [![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/workflow/status/Telecominfraproject/oopt-gnpy/build)](https://github.com/Telecominfraproject/oopt-gnpy/actions/workflows/main.yml) [![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) [![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) [![Contributors](https://img.shields.io/github/contributors-anon/Telecominfraproject/oopt-gnpy)](https://github.com/Telecominfraproject/oopt-gnpy/graphs/contributors)
[![Code Quality via LGTM.com](https://img.shields.io/lgtm/grade/python/github/Telecominfraproject/oopt-gnpy)](https://lgtm.com/projects/g/Telecominfraproject/oopt-gnpy/)
[![Code Coverage via codecov](https://img.shields.io/codecov/c/github/Telecominfraproject/oopt-gnpy)](https://codecov.io/gh/Telecominfraproject/oopt-gnpy) [![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) [![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. 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. 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.
@@ -26,4 +26,6 @@ This example demonstrates how GNPy can be used to check the expected SNR at the
![Running a simple simulation example](https://telecominfraproject.github.io/oopt-gnpy/docs/images/transmission_main_example.svg) ![Running a simple simulation example](https://telecominfraproject.github.io/oopt-gnpy/docs/images/transmission_main_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. 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/). 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/)

View File

@@ -12,7 +12,7 @@ We encourage all interested people outside the TIP to [join the project](https:/
`gnpy` is looking for additional contributors, especially those with experience planning and maintaining large-scale, real-world mesh optical networks. `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 [Jan Kundrát](mailto:jan.kundrat@telecominfraproject.com) or [Gert Grammel](mailto:ggrammel@juniper.net). To get involved, please contact [Jan Kundrát](mailto:jkt@jankundrat.com) or [Gert Grammel](mailto:ggrammel@juniper.net).
`gnpy` contributions are currently limited to members of [TIP](http://telecominfraproject.com). `gnpy` contributions are currently limited to members of [TIP](http://telecominfraproject.com).
Membership is free and open to all. Membership is free and open to all.

View File

@@ -1848,3 +1848,15 @@ month={Sept},}
title = {Telecom Infra Project}, title = {Telecom Infra Project},
url = {https://www.telecominfraproject.com}, url = {https://www.telecominfraproject.com},
} }
@ARTICLE{DAmicoJLT2022,
author={DAmico, Andrea and Correia, Bruno and London, Elliot and Virgillito,
Emanuele and Borraccini, Giacomo and Napoli, Antonio and Curri, Vittorio},
journal={Journal of Lightwave Technology},
title={Scalable and Disaggregated GGN Approximation Applied to a C+L+S Optical Network},
year={2022},
volume={40},
number={11},
pages={3499-3511},
doi={10.1109/JLT.2022.3162134}
}

View File

@@ -29,7 +29,7 @@ This path is directional, and all "GNPy elements" along the path match the unidi
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. 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**. 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<json>`. The topology is specified via :ref:`XLS files<excel>` or via :ref:`JSON<legacy-json>`.
.. _complete-vs-incomplete: .. _complete-vs-incomplete:

View File

@@ -100,10 +100,10 @@ Raman Amplifiers
An accurate simulation of Raman amplification requires knowledge of: An accurate simulation of Raman amplification requires knowledge of:
- the *power* and *wavelength* of all Raman pumping lasers, * the *power* and *wavelength* of all Raman pumping lasers,
- the *direction*, whether it is co-propagating or counter-propagating, * the *direction*, whether it is co-propagating or counter-propagating,
- the Raman efficiency of the fiber, * the Raman efficiency of the fiber,
- the fiber temperature. * the fiber temperature.
Under certain scenarios it is useful to be able to run a simulation without an accurate Raman description. 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`. 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`.

Binary file not shown.

After

Width:  |  Height:  |  Size: 288 KiB

View File

@@ -10,7 +10,7 @@ fully-functional programs.
**Note**: *If you are a network operator or involved in route planning and **Note**: *If you are a network operator or involved in route planning and
optimization for your organization, please contact project maintainer Jan optimization for your organization, please contact project maintainer Jan
Kundrát <jan.kundrat@telecominfraproject.com>. gnpy is looking for users with Kundrát <jkt@jankundrat.com>. gnpy is looking for users with
specific, delineated use cases to drive requirements for future specific, delineated use cases to drive requirements for future
development.* development.*

View File

@@ -1,4 +1,4 @@
.. _json: .. _legacy-json:
JSON Input Files JSON Input Files
================ ================
@@ -44,7 +44,7 @@ For all amplifier models:
| ``type_variety`` | (string) | a unique name to ID the amplifier in the| | ``type_variety`` | (string) | a unique name to ID the amplifier in the|
| | | JSON/Excel template topology input file | | | | JSON/Excel template topology input file |
+------------------------+-----------+-----------------------------------------+ +------------------------+-----------+-----------------------------------------+
| ``out_voa_auto`` | (boolean) | auto_design feature to optimize the | | ``out_voa_auto`` | (boolean) | auto-design feature to optimize the |
| | | amplifier output VOA. If true, output | | | | amplifier output VOA. If true, output |
| | | VOA is present and will be used to push | | | | VOA is present and will be used to push |
| | | amplifier gain to its maximum, within | | | | amplifier gain to its maximum, within |
@@ -61,40 +61,69 @@ Fiber
The fiber library currently describes SSMF and NZDF but additional fiber types can be entered by the user following the same model: The fiber library currently describes SSMF and NZDF but additional fiber types can be entered by the user following the same model:
+----------------------+-----------+------------------------------------------+ +------------------------------+-----------------+------------------------------------------------+
| field | type | description | | field | type | description |
+======================+===========+==========================================+ +==============================+=================+================================================+
| ``type_variety`` | (string) | a unique name to ID the fiber in the | | ``type_variety`` | (string) | a unique name to ID the fiber in the |
| | | JSON or Excel template topology input | | | | JSON or Excel template topology input |
| | | file | | | | file |
+----------------------+-----------+------------------------------------------+ +------------------------------+-----------------+------------------------------------------------+
| ``dispersion`` | (number) | In :math:`s \times m^{-1} \times m^{-1}`.| | ``dispersion`` | (number) | In :math:`s \times m^{-1} \times m^{-1}`. |
+----------------------+-----------+------------------------------------------+ +------------------------------+-----------------+------------------------------------------------+
| ``dispersion_slope`` | (number) | In :math:`s \times m^{-1} \times m^{-1} | | ``dispersion_slope`` | (number) | In :math:`s \times m^{-1} \times m^{-1} |
| | | \times m^{-1}` | | | | \times m^{-1}` |
+----------------------+-----------+------------------------------------------+ +------------------------------+-----------------+------------------------------------------------+
| ``effective_area`` | (number) | Effective area of the fiber (not just | | ``dispersion_per_frequency`` | (dict) | Dictionary of dispersion values evaluated at |
| | | the MFD circle). This is the | | | | various frequencies, as follows: |
| | | :math:`A_{eff}`, see e.g., the | | | | ``{"value": [], "frequency": []}``. |
| | | `Corning whitepaper on MFD/EA`_. | | | | ``value`` in |
| | | Specified in :math:`m^{2}`. | | | | :math:`s \times m^{-1} \times m^{-1}` and |
+----------------------+-----------+------------------------------------------+ | | | ``frequency`` in Hz. |
| ``gamma`` | (number) | Coefficient :math:`\gamma = 2\pi\times | +------------------------------+-----------------+------------------------------------------------+
| | | n^2/(\lambda*A_{eff})`. | | ``effective_area`` | (number) | Effective area of the fiber (not just |
| | | If not provided, this will be derived | | | | the MFD circle). This is the |
| | | from the ``effective_area`` | | | | :math:`A_{eff}`, see e.g., the |
| | | :math:`A_{eff}`. | | | | `Corning whitepaper on MFD/EA`_. |
| | | In :math:`w^{-1} \times m^{-1}`. | | | | Specified in :math:`m^{2}`. |
+----------------------+-----------+------------------------------------------+ +------------------------------+-----------------+------------------------------------------------+
| ``pmd_coef`` | (number) | Polarization mode dispersion (PMD) | | ``gamma`` | (number) | Coefficient :math:`\gamma = 2\pi\times |
| | | coefficient. In | | | | n^2/(\lambda*A_{eff})`. |
| | | :math:`s\times\sqrt{m}^{-1}`. | | | | If not provided, this will be derived |
+----------------------+-----------+------------------------------------------+ | | | from the ``effective_area`` |
| ``lumped_losses`` | (array) | Places along the fiber length with extra | | | | :math:`A_{eff}`. |
| | | losses. Specified as a loss in dB at | | | | In :math:`w^{-1} \times m^{-1}`. |
| | | each relevant position (in km): | | | | This quantity is evaluated at the |
| | | ``{"position": 10, "loss": 1.5}``) | | | | reference frequency and it is scaled |
+----------------------+-----------+------------------------------------------+ | | | along frequency accordingly to the |
| | | effective area scaling. |
+------------------------------+-----------------+------------------------------------------------+
| ``pmd_coef`` | (number) | Polarization mode dispersion (PMD) |
| | | coefficient. In |
| | | :math:`s\times\sqrt{m}^{-1}`. |
+------------------------------+-----------------+------------------------------------------------+
| ``lumped_losses`` | (array) | Places along the fiber length with extra |
| | | losses. Specified as a loss in dB at |
| | | each relevant position (in km): |
| | | ``{"position": 10, "loss": 1.5}``) |
+------------------------------+-----------------+------------------------------------------------+
| ``raman_coefficient`` | (dict) | The fundamental parameter that describes |
| | | the regulation of the power transfer |
| | | between channels during fiber propagation |
| | | is the Raman gain coefficient (see |
| | | :cite:`DAmicoJLT2022` for further |
| | | details); :math:`f_{ref}` represents the |
| | | pump reference frequency used for the |
| | | Raman gain coefficient profile |
| | | measurement ("reference_frequency"), |
| | | :math:`\Delta f` is the frequency shift |
| | | between the pump and the specific Stokes |
| | | wave, the Raman gain coefficient |
| | | in terms of optical power |
| | | :math:`g_0`, expressed in |
| | | :math:`1/(m\;W)`. |
| | | Default values measured for a SSMF are |
| | | considered when not specified. |
+------------------------------+-----------------+------------------------------------------------+
.. _Corning whitepaper on MFD/EA: https://www.corning.com/microsites/coc/oem/documents/specialty-fiber/WP7071-Mode-Field-Diam-and-Eff-Area.pdf .. _Corning whitepaper on MFD/EA: https://www.corning.com/microsites/coc/oem/documents/specialty-fiber/WP7071-Mode-Field-Diam-and-Eff-Area.pdf
@@ -176,36 +205,36 @@ ROADM
The user can only modify the value of existing parameters: The user can only modify the value of existing parameters:
+--------------------------+-----------+---------------------------------------------+ +-------------------------------+-----------+----------------------------------------------------+
| field | type | description | | field | type | description |
+==========================+===========+=============================================+ +===============================+===========+====================================================+
| ``target_pch_out_db`` | (number) | Auto-design sets the ROADM egress channel | | ``target_pch_out_db`` | (number) | Default :ref:`equalization strategy<equalization>` |
| | | power. This reflects typical control loop | | or | | for this ROADM type. |
| | | algorithms that adjust ROADM losses to | | ``target_psd_out_mWperGHz`` | | |
| | | equalize channels (eg coming from different | | or | | Auto-design sets the ROADM egress channel |
| | | ingress direction or add ports) | | ``target_out_mWperSlotWidth`` | | power. This reflects typical control loop |
| | | This is the default value | | (mutually exclusive) | | algorithms that adjust ROADM losses to |
| | | Roadm/params/target_pch_out_db if no value | | | | equalize channels (e.g., coming from |
| | | is given in the ``Roadm`` element in the | | | | different ingress direction or add ports). |
| | | topology input description. | | | | |
| | | This default value is ignored if a | | | | These values are used as defaults when no |
| | | params/target_pch_out_db value is input in | | | | overrides are set per each ``Roadm`` |
| | | the topology for a given ROADM. | | | | element in the network topology. |
+--------------------------+-----------+---------------------------------------------+ +-------------------------------+-----------+----------------------------------------------------+
| ``add_drop_osnr`` | (number) | OSNR contribution from the add/drop ports | | ``add_drop_osnr`` | (number) | OSNR contribution from the add/drop ports |
+--------------------------+-----------+---------------------------------------------+ +-------------------------------+-----------+----------------------------------------------------+
| ``pmd`` | (number) | Polarization mode dispersion (PMD). (s) | | ``pmd`` | (number) | Polarization mode dispersion (PMD). (s) |
+--------------------------+-----------+---------------------------------------------+ +-------------------------------+-----------+----------------------------------------------------+
| ``restrictions`` | (dict of | If non-empty, keys ``preamp_variety_list`` | | ``restrictions`` | (dict of | If non-empty, keys ``preamp_variety_list`` |
| | strings) | and ``booster_variety_list`` represent | | | strings) | and ``booster_variety_list`` represent |
| | | list of ``type_variety`` amplifiers which | | | | list of ``type_variety`` amplifiers which |
| | | are allowed for auto-design within ROADM's | | | | are allowed for auto-design within ROADM's |
| | | line degrees. | | | | line degrees. |
| | | | | | | |
| | | If no booster should be placed on a degree, | | | | If no booster should be placed on a degree, |
| | | insert a ``Fused`` node on the degree | | | | insert a ``Fused`` node on the degree |
| | | output. | | | | output. |
+--------------------------+-----------+---------------------------------------------+ +-------------------------------+-----------+----------------------------------------------------+
Global parameters Global parameters
----------------- -----------------
@@ -223,6 +252,9 @@ For amplifiers defined in the topology JSON input but whose ``gain = 0`` (placeh
The file ``sim_params.json`` contains the tuning parameters used within both the ``gnpy.science_utils.RamanSolver`` and 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 ``gnpy.science_utils.NliSolver`` for the evaluation of the Raman profile and the NLI generation, respectively.
If amplifiers don't have settings, auto-design also sets amplifiers gain, output VOA and target powers according to [J. -L. Auge, V. Curri and E. Le Rouzic, Open Design for Multi-Vendor Optical Networks, OFC 2019](https://ieeexplore.ieee.org/document/8696699), equation 4.
See ``delta_power_range_db`` for more explaination.
+---------------------------------------------+-----------+---------------------------------------------+ +---------------------------------------------+-----------+---------------------------------------------+
| field | type | description | | field | type | description |
+=============================================+===========+=============================================+ +=============================================+===========+=============================================+
@@ -283,23 +315,27 @@ Span configuration is not a list (which may change in later releases) and the us
+-------------------------------------+-----------+---------------------------------------------+ +-------------------------------------+-----------+---------------------------------------------+
| field | type | description | | field | type | description |
+=====================================+===========+=============================================+ +=====================================+===========+=============================================+
| ``power_mode`` | (boolean) | If false, gain mode. Auto-design sets | | ``power_mode`` | (boolean) | If false, **gain mode**. In the gain mode, |
| | | amplifier gain = preceding span loss, | | | | only gain settings are used for |
| | | unless the amplifier exists and its | | | | propagation, and ``delta_p`` is ignored. |
| | | gain > 0 in the topology input JSON. | | | | If no ``gain_target`` is set in an |
| | | If true, power mode (recommended for | | | | amplifier, auto-design computes one |
| | | auto-design and power sweep.) | | | | according to the ``delta_power_range`` |
| | | Auto-design sets amplifier power | | | | optimisation range. |
| | | according to delta_power_range. If the | | | | The gain mode |
| | | amplifier exists with gain > 0 in the | | | | is recommended if all the amplifiers |
| | | topology JSON input, then its gain is | | | | have already consistent gain settings in |
| | | translated into a power target/channel. | | | | the topology input file. |
| | | Moreover, when performing a power sweep | | | | |
| | | (see ``power_range_db`` in the SI | | | | If true, **power mode**. In the power mode, |
| | | configuration library) the power sweep | | | | only the ``delta_p`` is used for |
| | | is performed w/r/t this power target, | | | | propagation, and ``gain_target`` is |
| | | regardless of preceding amplifiers | | | | ignored. |
| | | power saturation/limitations. | | | | The power mode is recommended for |
| | | auto-design and power sweep. |
| | | If no ``delta_p`` is set, |
| | | auto-design sets an amplifier power target |
| | | according to delta_power_range_db. |
+-------------------------------------+-----------+---------------------------------------------+ +-------------------------------------+-----------+---------------------------------------------+
| ``delta_power_range_db`` | (number) | Auto-design only, power-mode | | ``delta_power_range_db`` | (number) | Auto-design only, power-mode |
| | | only. Specifies the [min, max, step] | | | | only. Specifies the [min, max, step] |
@@ -404,9 +440,9 @@ Span configuration is not a list (which may change in later releases) and the us
SpectralInformation SpectralInformation
~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~
The user can only modify the value of existing parameters. GNPy requires a description of all channels that are propagated through the network.
It defines a spectrum of N identical carriers. Flexgrid channel partitioning is available since the 2.7 release via the extra ``--spectrum`` option.
While the code libraries allow for different carriers and power levels, the current user parametrization only allows one carrier type and one power/channel definition. In the simplest case, homogeneous channel allocation can be defined via the ``SpectralInformation`` construct which defines a spectrum of N identical carriers:
+----------------------+-----------+-------------------------------------------+ +----------------------+-----------+-------------------------------------------+
| field | type | description | | field | type | description |
@@ -427,11 +463,20 @@ While the code libraries allow for different carriers and power levels, the curr
+----------------------+-----------+-------------------------------------------+ +----------------------+-----------+-------------------------------------------+
| ``tx_osnr`` | (number) | In dB. OSNR out from transponder. | | ``tx_osnr`` | (number) | In dB. OSNR out from transponder. |
+----------------------+-----------+-------------------------------------------+ +----------------------+-----------+-------------------------------------------+
| ``power_dbm`` | (number) | Reference channel power. In gain mode | | ``power_dbm`` | (number) | Reference channel power, in dBm. |
| | | (see spans/power_mode = false), all gain | | | | In gain mode |
| | | settings are offset w/r/t this reference | | | | (see spans/power_mode = false), if no |
| | | power. In power mode, it is the | | | | gain is set in an amplifier, auto-design |
| | | reference power for | | | | sets gain to meet this reference |
| | | power. If amplifiers gain is set, |
| | | ``power_dbm`` is |
| | | ignored. |
| | | |
| | | In power mode, the ``power_dbm`` |
| | | is the reference power for |
| | | the ``delta_p`` settings in amplifiers. |
| | | It is also the reference power for |
| | | auto-design power optimisation range |
| | | Spans/delta_power_range_db. For example, | | | | Spans/delta_power_range_db. For example, |
| | | if delta_power_range_db = `[0,0,0]`, the | | | | if delta_power_range_db = `[0,0,0]`, the |
| | | same power=power_dbm is launched in every | | | | same power=power_dbm is launched in every |
@@ -439,12 +484,166 @@ While the code libraries allow for different carriers and power levels, the curr
| | | with the power_dbm value: even if a | | | | with the power_dbm value: even if a |
| | | power sweep is defined (see after) the | | | | power sweep is defined (see after) the |
| | | design is not repeated. | | | | design is not repeated. |
| | | |
| | | If the ``--power`` CLI option is used, |
| | | its value replaces this parameter. |
+----------------------+-----------+-------------------------------------------+ +----------------------+-----------+-------------------------------------------+
| ``power_range_db`` | (number) | Power sweep excursion around power_dbm. | | ``power_range_db`` | (number) | Power sweep excursion around |
| | | It is not the min and max channel power | | | | ``power_dbm``. |
| | | values! The reference power becomes: | | | | This defines a list of reference powers |
| | | to run the propagation, in the range |
| | | power_range_db + power_dbm. | | | | power_range_db + power_dbm. |
| | | Power sweep uses the ``delta_p`` targets |
| | | or, if they have not been set, the ones |
| | | computed by auto-design, regardless of |
| | | of preceding amplifiers' power |
| | | saturation. |
| | | |
| | | Power sweep is an easy way to find the |
| | | optimal reference power. |
| | | |
| | | Power sweep excursion is ignored in case |
| | | of gain mode. |
+----------------------+-----------+-------------------------------------------+ +----------------------+-----------+-------------------------------------------+
| ``sys_margins`` | (number) | In dB. Added margin on min required | | ``sys_margins`` | (number) | In dB. Added margin on min required |
| | | transceiver OSNR. | | | | transceiver OSNR. |
+----------------------+-----------+-------------------------------------------+ +----------------------+-----------+-------------------------------------------+
.. _mixed-rate:
Arbitrary channel definition
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Non-uniform channels are defined via a list of spectrum "partitions" which are defined in an extra JSON file via the ``--spectrum`` option.
In this approach, each partition is internally homogeneous, but different partitions might use different channel widths, power targets, modulation rates, etc.
+----------------------+-----------+-------------------------------------------+
| field | type | description |
+======================+===========+===========================================+
| ``f_min``, | (number) | In Hz. Mandatory. |
| ``f_max`` | | Define partition :math:`f_{min}` is |
| | | the first carrier central frequency |
| | | :math:`f_{max}` is the last one. |
| | | :math:`f_{min}` -:math:`f_{max}` |
| | | partitions must not overlap. |
| | | |
| | | Note that the meaning of ``f_min`` and |
| | | ``f_max`` is different than the one in |
| | | ``SpectralInformation``. |
+----------------------+-----------+-------------------------------------------+
| ``baud_rate`` | (number) | In Hz. Mandatory. Simulated baud rate. |
+----------------------+-----------+-------------------------------------------+
| ``slot_width`` | (number) | In Hz. Carrier spectrum occupation. |
| | | Carriers of this partition are spaced at |
| | | ``slot_width`` offsets. |
+----------------------+-----------+-------------------------------------------+
| ``roll_off`` | (number) | Pure number between 0 and 1. Mandatory |
| | | TX signal roll-off shape. Used by |
| | | Raman-aware simulation code. |
+----------------------+-----------+-------------------------------------------+
| ``tx_osnr`` | (number) | In dB. Optional. OSNR out from |
| | | transponder. Default value is 40 dB. |
+----------------------+-----------+-------------------------------------------+
| ``delta_pdb`` | (number) | In dB. Optional. Power offset compared to |
| | | the reference power used for design |
| | | (SI block in equipment library) to be |
| | | applied by ROADM to equalize the carriers |
| | | in this partition. Default value is 0 dB. |
+----------------------+-----------+-------------------------------------------+
For example this example:
.. code-block:: json
{
"SI":[
{
"f_min": 191.4e12,
"f_max":193.1e12,
"baud_rate": 32e9,
"slot_width": 50e9,
"roll_off": 0.15,
"tx_osnr": 40
},
{
"f_min": 193.1625e12,
"f_max":195e12,
"baud_rate": 64e9,
"delta_pdb": 3,
"slot_width": 75e9,
"roll_off": 0.15,
"tx_osnr": 40
}
]
}
...defines a spectrum split into two parts.
Carriers with central frequencies ranging from 191.4 THz to 193.1 THz will have 32 GBaud rate and will be spaced by 50 Ghz.
Carriers with central frequencies ranging from 193.1625 THz to 195 THz will have 64 GBaud rate and will be spaced by 75 GHz with 3 dB power offset.
If the SI reference carrier is set to ``power_dbm`` = 0dBm, and the ROADM has ``target_pch_out_db`` set to -20 dBm, then all channels ranging from 191.4 THz to 193.1 THz will have their power equalized to -20 + 0 dBm (due to the 0 dB power offset).
All channels ranging from 193.1625 THz to 195 THz will have their power equalized to -20 + 3 = -17 dBm (total power signal + noise).
Note that first carrier of the second partition has center frequency 193.1625 THz (its spectrum occupation ranges from 193.125 THz to 193.2 THz).
The last carrier of the second partition has center frequency 193.1 THz and spectrum occupation ranges from 193.075 THz to 193.125 THz.
There is no overlap of the occupation and both share the same boundary.
.. _equalization:
Equalization choices
~~~~~~~~~~~~~~~~~~~~
ROADMs typically equalize the optical power across multiple channels using one of the available equalization strategies — either targeting a specific output power, or a specific power spectral density (PSD), or a spectfic power spectral density using slot_width as spectrum width reference (PSW).
All of these strategies can be adjusted by a per-channel power offset.
The equalization strategy can be defined globally per a ROADM model, or per each ROADM instance in the topology, and within a ROADM also on a per-degree basis.
Let's consider some example for the equalization. Suppose that the types of signal to be propagated are the following:
.. code-block:: json
{
"baud_rate": 32e9,
"f_min":191.3e12,
"f_max":192.3e12,
"spacing": 50e9,
"label": 1
},
{
"baud_rate": 64e9,
"f_min":193.3e12,
"f_max":194.3e12,
"spacing": 75e9,
"label": 2
}
with the PSD equalization in a ROADM:
.. code-block:: json
{
"uid": "roadm A",
"type": "Roadm",
"params": {
"target_psd_out_mWperGHz": 3.125e-4,
}
},
This means that power out of the ROADM will be computed as 3.125e-4 * 32 = 0.01 mW ie -20 dBm for label 1 types of carriers
and 3.125e4 * 64 = 0.02 mW ie -16.99 dBm for label2 channels. So a ratio of ~ 3 dB between target powers for these carriers.
With the PSW equalization:
.. code-block:: json
{
"uid": "roadm A",
"type": "Roadm",
"params": {
"target_out_mWperSlotWidth": 2.0e-4,
}
},
the power out of the ROADM will be computed as 2.0e-4 * 50 = 0.01 mW ie -20 dBm for label 1 types of carriers
and 2.0e4 * 75 = 0.015 mW ie -18.24 dBm for label2 channels. So a ratio of ~ 1.76 dB between target powers for these carriers.

View File

@@ -126,9 +126,9 @@ 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 tones - the standard FWM theory introduced back in the 90s by Inoue
:cite:`Innoue-FWM`- to a continuity of tones, possibly spectrally shaped. :cite:`Innoue-FWM`- to a continuity of tones, possibly spectrally shaped.
Signals propagating in the fiber are not equivalent to Gaussian noise, but Signals propagating in the fiber are not equivalent to Gaussian noise, but
thanks to the absence of in-line compensation for choromatic dispersion, the thanks to the absence of in-line compensation for chromatic dispersion, the
become so, over short distances. So, the Gaussian noise model with incoherent become so, over short distances. So, the Gaussian noise model with incoherent
accumulation of NLI has estensively proved to be a quick yet accurate and accumulation of NLI has extensively proved to be a quick yet accurate and
conservative tool to estimate propagation impairments of fiber propagation. conservative tool to estimate propagation impairments of fiber propagation.
Note that the GN-model has not been derived with the aim of an *exact* Note that the GN-model has not been derived with the aim of an *exact*
performance estimation, but to pursue a conservative performance prediction. performance estimation, but to pursue a conservative performance prediction.

View File

@@ -1,8 +1,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. 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.
Signal propagation is implemented in :py:mod:`.core`. Signal propagation is implemented in :py:mod:`.core`.
Path finding and spectrum assignment is in :py:mod:`.topology`. Path finding and spectrum assignment is in :py:mod:`.topology`.
Various tools and auxiliary code, including the JSON I/O handling, is in Various tools and auxiliary code, including the JSON I/O handling, is in
:py:mod:`.tools`. :py:mod:`.tools`.
''' """

View File

@@ -1,4 +1,4 @@
''' """
Simulation of signal propagation in the DWDM network Simulation of signal propagation in the DWDM network
Optical signals, as defined via :class:`.info.SpectralInformation`, enter Optical signals, as defined via :class:`.info.SpectralInformation`, enter
@@ -6,4 +6,4 @@ Optical signals, as defined via :class:`.info.SpectralInformation`, enter
through the :py:mod:`.network`. through the :py:mod:`.network`.
The simulation is controlled via :py:mod:`.parameters` and implemented mainly The simulation is controlled via :py:mod:`.parameters` and implemented mainly
via :py:mod:`.science_utils`. via :py:mod:`.science_utils`.
''' """

View File

@@ -1,12 +1,12 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
''' """
gnpy.core.ansi_escapes gnpy.core.ansi_escapes
====================== ======================
A random subset of ANSI terminal escape codes for colored messages A random subset of ANSI terminal escape codes for colored messages
''' """
red = '\x1b[1;31;40m' red = '\x1b[1;31;40m'
blue = '\x1b[1;34;40m' blue = '\x1b[1;34;40m'

View File

@@ -21,16 +21,22 @@ instance as a result.
""" """
from numpy import abs, array, errstate, ones, interp, mean, pi, polyfit, polyval, sum, sqrt, log10, exp, asarray, full,\ from numpy import abs, array, errstate, ones, interp, mean, pi, polyfit, polyval, sum, sqrt, log10, exp, asarray, full,\
squeeze, zeros, append, flip, outer squeeze, zeros, append, flip, outer, ndarray
from scipy.constants import h, c from scipy.constants import h, c
from scipy.interpolate import interp1d from scipy.interpolate import interp1d
from collections import namedtuple from collections import namedtuple
from typing import Union
from logging import getLogger
from gnpy.core.utils import lin2db, db2lin, arrange_frequencies, snr_sum from gnpy.core.utils import lin2db, db2lin, arrange_frequencies, snr_sum, per_label_average, pretty_summary_print, \
watt2dbm, psd2powerdbm
from gnpy.core.parameters import RoadmParams, FusedParams, FiberParams, PumpParams, EdfaParams, EdfaOperational from gnpy.core.parameters import RoadmParams, FusedParams, FiberParams, PumpParams, EdfaParams, EdfaOperational
from gnpy.core.science_utils import NliSolver, RamanSolver from gnpy.core.science_utils import NliSolver, RamanSolver
from gnpy.core.info import SpectralInformation from gnpy.core.info import SpectralInformation, ReferenceCarrier
from gnpy.core.exceptions import NetworkTopologyError, SpectrumError from gnpy.core.exceptions import NetworkTopologyError, SpectrumError, ParametersError
_logger = getLogger(__name__)
class Location(namedtuple('Location', 'latitude longitude city region')): class Location(namedtuple('Location', 'latitude longitude city region')):
@@ -39,11 +45,11 @@ class Location(namedtuple('Location', 'latitude longitude city region')):
class _Node: class _Node:
'''Convenience class for providing common functionality of all network elements """Convenience class for providing common functionality of all network elements
This class is just an internal implementation detail; do **not** assume that all network elements This class is just an internal implementation detail; do **not** assume that all network elements
inherit from :class:`_Node`. inherit from :class:`_Node`.
''' """
def __init__(self, uid, name=None, params=None, metadata=None, operational=None, type_variety=None): def __init__(self, uid, name=None, params=None, metadata=None, operational=None, type_variety=None):
if name is None: if name is None:
name = uid name = uid
@@ -84,11 +90,13 @@ class Transceiver(_Node):
self.chromatic_dispersion = None self.chromatic_dispersion = None
self.pmd = None self.pmd = None
self.pdl = None self.pdl = None
self.latency = None
self.penalties = {} self.penalties = {}
self.total_penalty = 0 self.total_penalty = 0
self.propagated_labels = [""]
def _calc_cd(self, spectral_info): def _calc_cd(self, spectral_info):
""" Updates the Transceiver property with the CD of the received channels. CD in ps/nm. """Updates the Transceiver property with the CD of the received channels. CD in ps/nm.
""" """
self.chromatic_dispersion = spectral_info.chromatic_dispersion * 1e3 self.chromatic_dispersion = spectral_info.chromatic_dispersion * 1e3
@@ -102,6 +110,11 @@ class Transceiver(_Node):
""" """
self.pdl = spectral_info.pdl self.pdl = spectral_info.pdl
def _calc_latency(self, spectral_info):
"""Updates the Transceiver property with the latency of the received channels. Latency in ms.
"""
self.latency = spectral_info.latency * 1e3
def _calc_penalty(self, impairment_value, boundary_list): def _calc_penalty(self, impairment_value, boundary_list):
return interp(impairment_value, boundary_list['up_to_boundary'], boundary_list['penalty_value'], return interp(impairment_value, boundary_list['up_to_boundary'], boundary_list['penalty_value'],
left=float('inf'), right=float('inf')) left=float('inf'), right=float('inf'))
@@ -116,6 +129,7 @@ class Transceiver(_Node):
def _calc_snr(self, spectral_info): def _calc_snr(self, spectral_info):
with errstate(divide='ignore'): with errstate(divide='ignore'):
self.propagated_labels = spectral_info.label
self.baud_rate = spectral_info.baud_rate self.baud_rate = spectral_info.baud_rate
ratio_01nm = lin2db(12.5e9 / self.baud_rate) ratio_01nm = lin2db(12.5e9 / self.baud_rate)
# set raw values to record original calculation, before update_snr() # set raw values to record original calculation, before update_snr()
@@ -167,29 +181,31 @@ class Transceiver(_Node):
f'chromatic_dispersion={self.chromatic_dispersion!r}, ' f'chromatic_dispersion={self.chromatic_dispersion!r}, '
f'pmd={self.pmd!r}, ' f'pmd={self.pmd!r}, '
f'pdl={self.pdl!r}, ' f'pdl={self.pdl!r}, '
f'latency={self.latency!r}, '
f'penalties={self.penalties!r})') f'penalties={self.penalties!r})')
def __str__(self): def __str__(self):
if self.snr is None or self.osnr_ase is None: if self.snr is None or self.osnr_ase is None:
return f'{type(self).__name__} {self.uid}' return f'{type(self).__name__} {self.uid}'
snr = round(mean(self.snr), 2) snr = per_label_average(self.snr, self.propagated_labels)
osnr_ase = round(mean(self.osnr_ase), 2) osnr_ase = per_label_average(self.osnr_ase, self.propagated_labels)
osnr_ase_01nm = round(mean(self.osnr_ase_01nm), 2) osnr_ase_01nm = per_label_average(self.osnr_ase_01nm, self.propagated_labels)
snr_01nm = round(mean(self.snr_01nm), 2) snr_01nm = per_label_average(self.snr_01nm, self.propagated_labels)
cd = mean(self.chromatic_dispersion) cd = mean(self.chromatic_dispersion)
pmd = mean(self.pmd) pmd = mean(self.pmd)
pdl = mean(self.pdl) pdl = mean(self.pdl)
latency = mean(self.latency)
result = '\n'.join([f'{type(self).__name__} {self.uid}', result = '\n'.join([f'{type(self).__name__} {self.uid}',
f' GSNR (0.1nm, dB): {pretty_summary_print(snr_01nm)}',
f' GSNR (0.1nm, dB): {snr_01nm:.2f}', f' GSNR (signal bw, dB): {pretty_summary_print(snr)}',
f' GSNR (signal bw, dB): {snr:.2f}', f' OSNR ASE (0.1nm, dB): {pretty_summary_print(osnr_ase_01nm)}',
f' OSNR ASE (0.1nm, dB): {osnr_ase_01nm:.2f}', f' OSNR ASE (signal bw, dB): {pretty_summary_print(osnr_ase)}',
f' OSNR ASE (signal bw, dB): {osnr_ase:.2f}', f' CD (ps/nm): {cd:.2f}',
f' CD (ps/nm): {cd:.2f}', f' PMD (ps): {pmd:.2f}',
f' PMD (ps): {pmd:.2f}', f' PDL (dB): {pdl:.2f}',
f' PDL (dB): {pdl:.2f}']) f' Latency (ms): {latency:.2f}'])
cd_penalty = self.penalties.get('chromatic_dispersion') cd_penalty = self.penalties.get('chromatic_dispersion')
if cd_penalty is not None: if cd_penalty is not None:
@@ -208,6 +224,7 @@ class Transceiver(_Node):
self._calc_cd(spectral_info) self._calc_cd(spectral_info)
self._calc_pmd(spectral_info) self._calc_pmd(spectral_info)
self._calc_pdl(spectral_info) self._calc_pdl(spectral_info)
self._calc_latency(spectral_info)
return spectral_info return spectral_info
@@ -215,63 +232,188 @@ class Roadm(_Node):
def __init__(self, *args, params=None, **kwargs): def __init__(self, *args, params=None, **kwargs):
if not params: if not params:
params = {} params = {}
super().__init__(*args, params=RoadmParams(**params), **kwargs) try:
self.pch_out_db = self.params.target_pch_out_db super().__init__(*args, params=RoadmParams(**params), **kwargs)
except ParametersError as e:
msg = f'Config error in {kwargs["uid"]}: {e}'
raise ParametersError(msg) from e
# Target output power for the reference carrier, can only be computed on the fly, because it depends
# on the path, since it depends on the equalization definition on the degree.
self.ref_pch_out_dbm = None
self.loss = 0 # auto-design interest self.loss = 0 # auto-design interest
self.effective_loss = None
# Optical power of carriers are equalized by the ROADM, so that the experienced loss is not the same for
# different carriers. The ref_effective_loss records the loss for a reference carrier.
self.ref_effective_loss = None
self.passive = True self.passive = True
self.restrictions = self.params.restrictions self.restrictions = self.params.restrictions
self.per_degree_pch_out_db = self.params.per_degree_pch_out_db self.propagated_labels = [""]
# element contains the two types of equalisation parameters, but only one is not None or empty
# target for equalization for the ROADM only one must be not None
self.target_pch_out_dbm = self.params.target_pch_out_db
self.target_psd_out_mWperGHz = self.params.target_psd_out_mWperGHz
self.target_out_mWperSlotWidth = self.params.target_out_mWperSlotWidth
self.per_degree_pch_out_dbm = self.params.per_degree_pch_out_db
self.per_degree_pch_psd = self.params.per_degree_pch_psd
self.per_degree_pch_psw = self.params.per_degree_pch_psw
@property @property
def to_json(self): def to_json(self):
return {'uid': self.uid, if self.target_pch_out_dbm is not None:
'type': type(self).__name__, equalisation, value = 'target_pch_out_db', self.target_pch_out_dbm
'params': { elif self.target_psd_out_mWperGHz is not None:
'target_pch_out_db': self.pch_out_db, equalisation, value = 'target_psd_out_mWperGHz', self.target_psd_out_mWperGHz
'restrictions': self.restrictions, elif self.target_out_mWperSlotWidth is not None:
'per_degree_pch_out_db': self.per_degree_pch_out_db equalisation, value = 'target_out_mWperSlotWidth', self.target_out_mWperSlotWidth
}, else:
'metadata': { assert False, 'There must be one default equalization defined in ROADM'
'location': self.metadata['location']._asdict() to_json = {
} 'uid': self.uid,
} 'type': type(self).__name__,
'params': {
equalisation: value,
'restrictions': self.restrictions,
},
'metadata': {
'location': self.metadata['location']._asdict()
}
}
# several per_degree equalization may coexist on different degrees
if self.per_degree_pch_out_dbm:
to_json['params']['per_degree_pch_out_db'] = self.per_degree_pch_out_dbm
if self.per_degree_pch_psd:
to_json['params']['per_degree_psd_out_mWperGHz'] = self.per_degree_pch_psd
if self.per_degree_pch_psw:
to_json['params']['per_degree_psd_out_mWperSlotWidth'] = self.per_degree_pch_psw
return to_json
def __repr__(self): def __repr__(self):
return f'{type(self).__name__}(uid={self.uid!r}, loss={self.loss!r})' return f'{type(self).__name__}(uid={self.uid!r}, loss={self.loss!r})'
def __str__(self): def __str__(self):
if self.effective_loss is None: if self.ref_effective_loss is None:
return f'{type(self).__name__} {self.uid}' return f'{type(self).__name__} {self.uid}'
total_pch = pretty_summary_print(per_label_average(self.pch_out_dbm, self.propagated_labels))
return '\n'.join([f'{type(self).__name__} {self.uid}', return '\n'.join([f'{type(self).__name__} {self.uid}',
f' effective loss (dB): {self.effective_loss:.2f}', f' effective loss (dB): {self.ref_effective_loss:.2f}',
f' pch out (dBm): {self.pch_out_db:.2f}']) f' reference pch out (dBm): {self.ref_pch_out_dbm:.2f}',
f' actual pch out (dBm): {total_pch}'])
def get_roadm_target_power(self, ref_carrier: ReferenceCarrier = None,
spectral_info: SpectralInformation = None) -> Union[float, ndarray]:
"""Computes the power in dBm for a reference carrier or for a spectral information.
power is computed based on equalization target.
if spectral_info baud_rate is baud_rate = [32e9, 42e9, 64e9, 42e9, 32e9], and
target_pch_out_dbm is defined to -20 dbm, then the function returns an array of powers
[-20, -20, -20, -20, -20]
if target_psd_out_mWperGHz is defined instead with 3.125e-4mW/GHz then it returns
[-20, -18.819, -16.9897, -18.819, -20]
if instead a reference_baud_rate is defined, the functions computes the result for a
single reference carrier whose baud_rate is reference_baudrate
"""
if spectral_info:
if self.target_pch_out_dbm is not None:
return full(len(spectral_info.channel_number), self.target_pch_out_dbm)
if self.target_psd_out_mWperGHz is not None:
return psd2powerdbm(self.target_psd_out_mWperGHz, spectral_info.baud_rate)
if self.target_out_mWperSlotWidth is not None:
return psd2powerdbm(self.target_out_mWperSlotWidth, spectral_info.slot_width)
else:
if self.target_pch_out_dbm is not None:
return self.target_pch_out_dbm
if self.target_psd_out_mWperGHz is not None:
return psd2powerdbm(self.target_psd_out_mWperGHz, ref_carrier.baud_rate)
if self.target_out_mWperSlotWidth is not None:
return psd2powerdbm(self.target_out_mWperSlotWidth, ref_carrier.slot_width)
return None
def get_per_degree_ref_power(self, degree, ref_carrier):
"""Get the target power in dBm out of ROADM degree for the reference bandwidth
If no equalization is defined on this degree use the ROADM level one.
"""
if degree in self.per_degree_pch_out_dbm:
return self.per_degree_pch_out_dbm[degree]
elif degree in self.per_degree_pch_psd:
return psd2powerdbm(self.per_degree_pch_psd[degree], ref_carrier.baud_rate)
elif degree in self.per_degree_pch_psw:
return psd2powerdbm(self.per_degree_pch_psw[degree], ref_carrier.slot_width)
return self.get_roadm_target_power(ref_carrier)
def get_per_degree_power(self, degree, spectral_info):
"""Get the target power in dBm out of ROADM degree for the spectral information
If no equalization is defined on this degree use the ROADM level one.
"""
if degree in self.per_degree_pch_out_dbm:
return self.per_degree_pch_out_dbm[degree]
elif degree in self.per_degree_pch_psd:
return psd2powerdbm(self.per_degree_pch_psd[degree], spectral_info.baud_rate)
elif degree in self.per_degree_pch_psw:
return psd2powerdbm(self.per_degree_pch_psw[degree], spectral_info.slot_width)
return self.get_roadm_target_power(spectral_info=spectral_info)
def propagate(self, spectral_info, degree): def propagate(self, spectral_info, degree):
# pin_target and loss are read from eqpt_config.json['Roadm'] """Equalization targets are read from topology file if defined and completed with default
# all ingress channels in xpress are set to this power level definition of the library.
# but add channels are not, so we define an effective loss If the input power is lower than the target one, use the input power instead because
# in the case of add channels a ROADM doesn't amplify, it can only attenuate.
# find the target power on this degree: There is no difference for add or express : the same target is applied. For the moment
# if a target power has been defined for this degree use it else use the global one. propagates operates with spectral info carriers all having the same source or destination.
# if the input power is lower than the target one, use the input power instead because """
# a ROADM doesn't amplify, it can only attenuate
# TODO maybe add a minimum loss for the ROADM # TODO maybe add a minimum loss for the ROADM
per_degree_pch = self.per_degree_pch_out_db[degree] \
if degree in self.per_degree_pch_out_db else self.pch_out_db # find the target power for the reference carrier
self.pch_out_db = min(spectral_info.pref.p_spani, per_degree_pch) ref_per_degree_pch = self.get_per_degree_ref_power(degree, spectral_info.pref.ref_carrier)
self.effective_loss = spectral_info.pref.p_spani - self.pch_out_db # find the target powers for each signal carrier
per_degree_pch = self.get_per_degree_power(degree, spectral_info=spectral_info)
# Definition of ref_pch_out_dbm for the reference channel:
# Depending on propagation upstream from this ROADM, the input power (p_spani) might be smaller than
# the target power out configured for this ROADM degree's egress. Since ROADM does not amplify,
# the power out of the ROADM for the ref channel is the min value between target power and input power.
# (TODO add a minimum loss for the ROADM crossing)
self.ref_pch_out_dbm = min(spectral_info.pref.p_spani, ref_per_degree_pch)
# Definition of effective_loss:
# Optical power of carriers are equalized by the ROADM, so that the experienced loss is not the same for
# different carriers. effective_loss records the loss for the reference carrier.
self.ref_effective_loss = spectral_info.pref.p_spani - self.ref_pch_out_dbm
input_power = spectral_info.signal + spectral_info.nli + spectral_info.ase input_power = spectral_info.signal + spectral_info.nli + spectral_info.ase
min_power = min(lin2db(input_power * 1e3)) target_power_per_channel = per_degree_pch + spectral_info.delta_pdb_per_channel
per_degree_pch = per_degree_pch if per_degree_pch < min_power else min_power # Computation of the per channel target power according to equalization policy
delta_power = lin2db(input_power * 1e3) - per_degree_pch # 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. 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]
# note that this changes the previous behaviour that equalized all identical channels based on the one
# that had the min power.
# 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
correction = (abs(watt2dbm(input_power) - target_power_per_channel)
- (watt2dbm(input_power) - target_power_per_channel)) / 2
new_target = target_power_per_channel - correction
delta_power = watt2dbm(input_power) - new_target
spectral_info.apply_attenuation_db(delta_power) spectral_info.apply_attenuation_db(delta_power)
spectral_info.pmd = sqrt(spectral_info.pmd ** 2 + self.params.pmd ** 2) spectral_info.pmd = sqrt(spectral_info.pmd ** 2 + self.params.pmd ** 2)
spectral_info.pdl = sqrt(spectral_info.pdl ** 2 + self.params.pdl ** 2) spectral_info.pdl = sqrt(spectral_info.pdl ** 2 + self.params.pdl ** 2)
self.pch_out_dbm = watt2dbm(spectral_info.signal + spectral_info.nli + spectral_info.ase)
self.propagated_labels = spectral_info.label
def update_pref(self, spectral_info): def update_pref(self, spectral_info):
spectral_info.pref = spectral_info.pref._replace(p_span0=spectral_info.pref.p_span0, p_spani=self.pch_out_db) """Update Reference power
This modifies the spectral info in-place. Only the `pref` is updated with new p_spani,
while p_span0 is not changed.
"""
spectral_info.pref = spectral_info.pref._replace(p_spani=self.ref_pch_out_dbm)
def __call__(self, spectral_info, degree): def __call__(self, spectral_info, degree):
self.propagate(spectral_info, degree=degree) self.propagate(spectral_info, degree=degree)
@@ -323,21 +465,14 @@ class Fiber(_Node):
def __init__(self, *args, params=None, **kwargs): def __init__(self, *args, params=None, **kwargs):
if not params: if not params:
params = {} params = {}
super().__init__(*args, params=FiberParams(**params), **kwargs) try:
super().__init__(*args, params=FiberParams(**params), **kwargs)
except ParametersError as e:
msg = f'Config error in {kwargs["uid"]}: {e}'
raise ParametersError(msg) from e
self.pch_out_db = None self.pch_out_db = None
self.passive = True self.passive = True
self.propagated_labels = [""]
# Raman efficiency matrix function of the delta frequency constructed such that each row is related to a
# fixed frequency: positive elements represent a gain (from higher frequency) and negative elements represent
# a loss (to lower frequency)
if self.params.raman_efficiency:
frequency_offset = self.params.raman_efficiency['frequency_offset']
frequency_offset = append(-flip(frequency_offset[1:]), frequency_offset)
cr = self.params.raman_efficiency['cr']
cr = append(- flip(cr[1:]), cr)
self._cr_function = lambda frequency: interp(frequency, frequency_offset, cr)
else:
self._cr_function = lambda frequency: zeros(squeeze(frequency).shape)
# Lumped losses # Lumped losses
z_lumped_losses = array([lumped['position'] for lumped in self.params.lumped_losses]) # km z_lumped_losses = array([lumped['position'] for lumped in self.params.lumped_losses]) # km
@@ -376,6 +511,7 @@ class Fiber(_Node):
if self.pch_out_db is None: if self.pch_out_db is None:
return f'{type(self).__name__} {self.uid}' return f'{type(self).__name__} {self.uid}'
total_pch = pretty_summary_print(per_label_average(self.pch_out_dbm, self.propagated_labels))
return '\n'.join([f'{type(self).__name__} {self.uid}', return '\n'.join([f'{type(self).__name__} {self.uid}',
f' type_variety: {self.type_variety}', f' type_variety: {self.type_variety}',
f' length (km): {self.params.length * 1e-3:.2f}', f' length (km): {self.params.length * 1e-3:.2f}',
@@ -383,30 +519,35 @@ class Fiber(_Node):
f' total loss (dB): {self.loss:.2f}', f' total loss (dB): {self.loss:.2f}',
f' (includes conn loss (dB) in: {self.params.con_in:.2f} out: {self.params.con_out:.2f})', f' (includes conn loss (dB) in: {self.params.con_in:.2f} out: {self.params.con_out:.2f})',
f' (conn loss out includes EOL margin defined in eqpt_config.json)', f' (conn loss out includes EOL margin defined in eqpt_config.json)',
f' pch out (dBm): {self.pch_out_db:.2f}']) f' reference pch out (dBm): {self.pch_out_db:.2f}',
f' actual pch out (dBm): {total_pch}'])
def interpolate_parameter_over_spectrum(self, parameter, ref_frequency, spectrum_frequency, name):
try:
interpolation = interp1d(ref_frequency, parameter)(spectrum_frequency)
return interpolation
except ValueError:
raise SpectrumError('The spectrum bandwidth exceeds the frequency interval used to define the fiber '
f'{name} in "{type(self).__name__} {self.uid}".'
f'\nSpectrum f_min-f_max: {round(spectrum_frequency[0] * 1e-12, 2)}-'
f'{round(spectrum_frequency[-1] * 1e-12, 2)}'
f'\n{name} f_min-f_max: {round(ref_frequency[0] * 1e-12, 2)}-'
f'{round(ref_frequency[-1] * 1e-12, 2)}')
def loss_coef_func(self, frequency): def loss_coef_func(self, frequency):
frequency = asarray(frequency) frequency = asarray(frequency)
if self.params.loss_coef.size > 1: if self.params.loss_coef.size > 1:
try: loss_coef = self.interpolate_parameter_over_spectrum(self.params.loss_coef, self.params.f_loss_ref,
loss_coef = interp1d(self.params.f_loss_ref, self.params.loss_coef)(frequency) frequency, 'Loss Coefficient')
except ValueError:
raise SpectrumError('The spectrum bandwidth exceeds the frequency interval used to define the fiber '
f'loss coefficient in "{type(self).__name__} {self.uid}".'
f'\nSpectrum f_min-f_max: {round(frequency[0]*1e-12,2)}-'
f'{round(frequency[-1]*1e-12,2)}'
f'\nLoss coefficient f_min-f_max: {round(self.params.f_loss_ref[0]*1e-12,2)}-'
f'{round(self.params.f_loss_ref[-1]*1e-12,2)}')
else: else:
loss_coef = full(frequency.size, self.params.loss_coef) loss_coef = full(frequency.size, self.params.loss_coef)
return squeeze(loss_coef) return squeeze(loss_coef)
@property @property
def loss(self): def loss(self):
"""total loss including padding att_in: useful for polymorphism with roadm loss""" """total loss including padding att_in: useful for polymorphism with roadm loss"""
return self.loss_coef_func(self.params.ref_frequency) * self.params.length + \ return self.loss_coef_func(self.params.ref_frequency) * self.params.length + \
self.params.con_in + self.params.con_out + self.params.att_in self.params.con_in + self.params.con_out + self.params.att_in + sum(lin2db(1 / self.lumped_losses))
def alpha(self, frequency): def alpha(self, frequency):
"""Returns the linear exponent attenuation coefficient such that """Returns the linear exponent attenuation coefficient such that
@@ -417,16 +558,71 @@ class Fiber(_Node):
""" """
return self.loss_coef_func(frequency) / (10 * log10(exp(1))) return self.loss_coef_func(frequency) / (10 * log10(exp(1)))
def beta2(self, frequency=None):
"""Returns the beta2 chromatic dispersion coefficient as the second order term of the beta function
expanded as a Taylor series evaluated at the given frequency
:param frequency: the frequency at which alpha is computed [Hz]
:return: beta2: beta2 chromatic dispersion coefficient for f in frequency # 1/(m * Hz^2)
"""
frequency = asarray(self.params.ref_frequency if frequency is None else frequency)
if self.params.dispersion.size > 1:
dispersion = self.interpolate_parameter_over_spectrum(self.params.dispersion, self.params.f_dispersion_ref,
frequency, 'Chromatic Dispersion')
else:
if self.params.dispersion_slope is None:
dispersion = (frequency / self.params.f_dispersion_ref) ** 2 * self.params.dispersion
else:
wavelength = c / frequency
dispersion = self.params.dispersion + self.params.dispersion_slope * \
(wavelength - c / self.params.f_dispersion_ref)
beta2 = -((c / frequency) ** 2 * dispersion) / (2 * pi * c)
return beta2
def beta3(self, frequency=None):
"""Returns the beta3 chromatic dispersion coefficient as the third order term of the beta function
expanded as a Taylor series evaluated at the given frequency
:param frequency: the frequency at which alpha is computed [Hz]
:return: beta3: beta3 chromatic dispersion coefficient for f in frequency # 1/(m * Hz^3)
"""
frequency = asarray(self.params.ref_frequency if frequency is None else frequency)
if self.params.dispersion.size > 1:
beta3 = polyfit(self.params.f_dispersion_ref - self.params.ref_frequency,
self.beta2(self.params.f_dispersion_ref), 2)[1] / (2*pi)
beta3 = full(frequency.size, beta3)
else:
if self.params.dispersion_slope is None:
beta3 = zeros(frequency.size)
else:
dispersion_slope = self.params.dispersion_slope
beta2 = self.beta2(frequency)
beta3 = (dispersion_slope - (4 * pi * frequency ** 3 / c ** 2) * beta2) / (
2 * pi * frequency ** 2 / c) ** 2
return beta3
def gamma(self, frequency=None):
"""Returns the nonlinear interference coefficient such that
:math: `gamma(f) = 2 pi f n_2 c^{-1} A_{eff}^{-1}`
:param frequency: the frequency at which gamma is computed [Hz]
:return: gamma: nonlinear interference coefficient for f in frequency [1/(W m)]
"""
frequency = self.params.ref_frequency if frequency is None else frequency
return self.params.gamma_scaling(frequency)
def cr(self, frequency): def cr(self, frequency):
"""Returns the raman efficiency matrix including the vibrational loss """Returns the raman gain coefficient matrix including the vibrational loss
:param frequency: the frequency at which cr is computed [Hz] :param frequency: the frequency at which cr is computed [Hz]
:return: cr: raman efficiency matrix [1 / (W m)] :return: cr: raman gain coefficient matrix [1 / (W m)]
""" """
df = outer(ones(frequency.shape), frequency) - outer(frequency, ones(frequency.shape)) df = outer(ones(frequency.shape), frequency) - outer(frequency, ones(frequency.shape))
cr = self._cr_function(df) effective_area_overlap = self.params.effective_area_overlap(frequency, frequency)
cr = interp(df, self.params.raman_coefficient.frequency_offset,
self.params.raman_coefficient.normalized_gamma_raman) * frequency / effective_area_overlap
vibrational_loss = outer(frequency, ones(frequency.shape)) / outer(ones(frequency.shape), frequency) vibrational_loss = outer(frequency, ones(frequency.shape)) / outer(ones(frequency.shape), frequency)
return cr * (cr >= 0) + cr * (cr < 0) * vibrational_loss # Raman efficiency [1/(W m)] return cr * (cr >= 0) + cr * (cr < 0) * vibrational_loss # [1/(W m)]
def chromatic_dispersion(self, freq=None): def chromatic_dispersion(self, freq=None):
"""Returns accumulated chromatic dispersion (CD). """Returns accumulated chromatic dispersion (CD).
@@ -435,8 +631,8 @@ class Fiber(_Node):
:return: chromatic dispersion: the accumulated dispersion [s/m] :return: chromatic dispersion: the accumulated dispersion [s/m]
""" """
freq = self.params.ref_frequency if freq is None else freq freq = self.params.ref_frequency if freq is None else freq
beta2 = self.params.beta2 beta2 = self.beta2(freq)
beta3 = self.params.beta3 beta3 = self.beta3(freq)
ref_f = self.params.ref_frequency ref_f = self.params.ref_frequency
length = self.params.length length = self.params.length
beta = beta2 + 2 * pi * beta3 * (freq - ref_f) beta = beta2 + 2 * pi * beta3 * (freq - ref_f)
@@ -466,6 +662,9 @@ class Fiber(_Node):
spectral_info.chromatic_dispersion += self.chromatic_dispersion(spectral_info.frequency) spectral_info.chromatic_dispersion += self.chromatic_dispersion(spectral_info.frequency)
spectral_info.pmd = sqrt(spectral_info.pmd ** 2 + self.pmd ** 2) spectral_info.pmd = sqrt(spectral_info.pmd ** 2 + self.pmd ** 2)
# latency
spectral_info.latency += self.params.latency
# apply the attenuation due to the fiber losses # apply the attenuation due to the fiber losses
attenuation_fiber = stimulated_raman_scattering.loss_profile[:, -1] attenuation_fiber = stimulated_raman_scattering.loss_profile[:, -1]
spectral_info.apply_attenuation_lin(attenuation_fiber) spectral_info.apply_attenuation_lin(attenuation_fiber)
@@ -473,6 +672,8 @@ class Fiber(_Node):
# apply the attenuation due to the output connector loss # apply the attenuation due to the output connector loss
attenuation_out_db = self.params.con_out attenuation_out_db = self.params.con_out
spectral_info.apply_attenuation_db(attenuation_out_db) spectral_info.apply_attenuation_db(attenuation_out_db)
self.pch_out_dbm = watt2dbm(spectral_info.signal + spectral_info.nli + spectral_info.ase)
self.propagated_labels = spectral_info.label
def update_pref(self, spectral_info): def update_pref(self, spectral_info):
# in case of Raman, the resulting loss of the fiber is not equivalent to self.loss # in case of Raman, the resulting loss of the fiber is not equivalent to self.loss
@@ -537,6 +738,9 @@ class RamanFiber(Fiber):
spectral_info.chromatic_dispersion += self.chromatic_dispersion(spectral_info.frequency) spectral_info.chromatic_dispersion += self.chromatic_dispersion(spectral_info.frequency)
spectral_info.pmd = sqrt(spectral_info.pmd ** 2 + self.pmd ** 2) spectral_info.pmd = sqrt(spectral_info.pmd ** 2 + self.pmd ** 2)
# latency
spectral_info.latency += self.params.latency
# apply the attenuation due to the fiber losses # apply the attenuation due to the fiber losses
attenuation_fiber = stimulated_raman_scattering.loss_profile[:spectral_info.number_of_channels, -1] attenuation_fiber = stimulated_raman_scattering.loss_profile[:spectral_info.number_of_channels, -1]
@@ -545,6 +749,8 @@ class RamanFiber(Fiber):
# apply the attenuation due to the output connector loss # apply the attenuation due to the output connector loss
attenuation_out_db = self.params.con_out attenuation_out_db = self.params.con_out
spectral_info.apply_attenuation_db(attenuation_out_db) spectral_info.apply_attenuation_db(attenuation_out_db)
self.pch_out_dbm = watt2dbm(spectral_info.signal + spectral_info.nli + spectral_info.ase)
self.propagated_labels = spectral_info.label
class Edfa(_Node): class Edfa(_Node):
@@ -573,6 +779,7 @@ class Edfa(_Node):
self.delta_p = self.operational.delta_p # delta P with Pref (power swwep) in power mode self.delta_p = self.operational.delta_p # delta P with Pref (power swwep) in power mode
self.tilt_target = self.operational.tilt_target self.tilt_target = self.operational.tilt_target
self.out_voa = self.operational.out_voa self.out_voa = self.operational.out_voa
self.propagated_labels = [""]
@property @property
def to_json(self): def to_json(self):
@@ -580,7 +787,7 @@ class Edfa(_Node):
'type': type(self).__name__, 'type': type(self).__name__,
'type_variety': self.params.type_variety, 'type_variety': self.params.type_variety,
'operational': { 'operational': {
'gain_target': round(self.effective_gain, 6), 'gain_target': round(self.effective_gain, 6) if self.effective_gain else None,
'delta_p': self.delta_p, 'delta_p': self.delta_p,
'tilt_target': self.tilt_target, 'tilt_target': self.tilt_target,
'out_voa': self.out_voa 'out_voa': self.out_voa
@@ -606,6 +813,7 @@ class Edfa(_Node):
if self.pin_db is None or self.pout_db is None: if self.pin_db is None or self.pout_db is None:
return f'{type(self).__name__} {self.uid}' return f'{type(self).__name__} {self.uid}'
nf = mean(self.nf) nf = mean(self.nf)
total_pch = pretty_summary_print(per_label_average(self.pch_out_dbm, self.propagated_labels))
return '\n'.join([f'{type(self).__name__} {self.uid}', return '\n'.join([f'{type(self).__name__} {self.uid}',
f' type_variety: {self.params.type_variety}', f' type_variety: {self.params.type_variety}',
f' effective gain(dB): {self.effective_gain:.2f}', f' effective gain(dB): {self.effective_gain:.2f}',
@@ -618,6 +826,7 @@ class Edfa(_Node):
f' Delta_P (dB): ' + (f'{self.delta_p:.2f}' if self.delta_p is not None else 'None'), f' Delta_P (dB): ' + (f'{self.delta_p:.2f}' if self.delta_p is not None else 'None'),
f' target pch (dBm): ' + (f'{self.target_pch_out_db:.2f}' if self.target_pch_out_db is not None else 'None'), f' target pch (dBm): ' + (f'{self.target_pch_out_db:.2f}' if self.target_pch_out_db is not None else 'None'),
f' effective pch (dBm): {self.effective_pch_out_db:.2f}', f' effective pch (dBm): {self.effective_pch_out_db:.2f}',
f' actual pch out (dBm): {total_pch}',
f' output VOA (dB): {self.out_voa:.2f}']) f' output VOA (dB): {self.out_voa:.2f}'])
def interpol_params(self, spectral_info): def interpol_params(self, spectral_info):
@@ -639,7 +848,7 @@ class Edfa(_Node):
self.nch = spectral_info.number_of_channels self.nch = spectral_info.number_of_channels
pin = spectral_info.signal + spectral_info.ase + spectral_info.nli pin = spectral_info.signal + spectral_info.ase + spectral_info.nli
self.pin_db = lin2db(sum(pin * 1e3)) self.pin_db = watt2dbm(sum(pin))
# The following should be changed when we have the new spectral information including slot widths. # The following should be changed when we have the new spectral information including slot widths.
# For now, with homogeneous spectrum, we can calculate it as the difference between neighbouring channels. # For now, with homogeneous spectrum, we can calculate it as the difference between neighbouring channels.
self.slot_width = self.channel_freq[1] - self.channel_freq[0] self.slot_width = self.channel_freq[1] - self.channel_freq[0]
@@ -652,15 +861,14 @@ class Edfa(_Node):
self.effective_gain = self.target_pch_out_db - pref.p_spani self.effective_gain = self.target_pch_out_db - pref.p_spani
"""check power saturation and correct effective gain & power accordingly:""" """check power saturation and correct effective gain & power accordingly:"""
# Compute the saturation accounting for actual power at the input of the amp
self.effective_gain = min( self.effective_gain = min(
self.effective_gain, self.effective_gain,
self.params.p_max - (pref.p_spani + pref.neq_ch) self.params.p_max - self.pin_db
) )
#print(self.uid, self.effective_gain, self.operational.gain_target)
self.effective_pch_out_db = round(pref.p_spani + self.effective_gain, 2) self.effective_pch_out_db = round(pref.p_spani + self.effective_gain, 2)
"""check power saturation and correct target_gain accordingly:""" """check power saturation and correct target_gain accordingly:"""
#print(self.uid, self.effective_gain, self.pin_db, pref.p_spani)
self.nf = self._calc_nf() self.nf = self._calc_nf()
self.gprofile = self._gain_profile(pin) self.gprofile = self._gain_profile(pin)
@@ -891,6 +1099,8 @@ class Edfa(_Node):
spectral_info.apply_gain_db(self.gprofile - self.out_voa) spectral_info.apply_gain_db(self.gprofile - self.out_voa)
spectral_info.pmd = sqrt(spectral_info.pmd ** 2 + self.params.pmd ** 2) spectral_info.pmd = sqrt(spectral_info.pmd ** 2 + self.params.pmd ** 2)
spectral_info.pdl = sqrt(spectral_info.pdl ** 2 + self.params.pdl ** 2) spectral_info.pdl = sqrt(spectral_info.pdl ** 2 + self.params.pdl ** 2)
self.pch_out_dbm = watt2dbm(spectral_info.signal + spectral_info.nli + spectral_info.ase)
self.propagated_labels = spectral_info.label
def update_pref(self, spectral_info): def update_pref(self, spectral_info):
spectral_info.pref = \ spectral_info.pref = \

View File

@@ -1,12 +1,12 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
''' """
gnpy.core.equipment gnpy.core.equipment
=================== ===================
This module contains functionality for specifying equipment. This module contains functionality for specifying equipment.
''' """
from gnpy.core.utils import automatic_nch, db2lin from gnpy.core.utils import automatic_nch, db2lin
from gnpy.core.exceptions import EquipmentConfigError from gnpy.core.exceptions import EquipmentConfigError
@@ -29,8 +29,11 @@ def trx_mode_params(equipment, trx_type_variety='', trx_mode='', error_message=F
trx_params = {**mode_params} trx_params = {**mode_params}
# sanity check: spacing baudrate must be smaller than min spacing # sanity check: spacing baudrate must be smaller than min spacing
if trx_params['baud_rate'] > trx_params['min_spacing']: if trx_params['baud_rate'] > trx_params['min_spacing']:
raise EquipmentConfigError(f'Inconsistency in equipment library:\n Transpoder "{trx_type_variety}" mode "{trx_params["format"]}" ' + raise EquipmentConfigError(f'Inconsistency in equipment library:\n Transponder "{trx_type_variety}"'
f'has baud rate {trx_params["baud_rate"]*1e-9} GHz greater than min_spacing {trx_params["min_spacing"]*1e-9}.') + f' mode "{trx_params["format"]}" has baud rate'
+ f' {trx_params["baud_rate"] * 1e-9:.3f} GHz greater than min_spacing'
+ f' {trx_params["min_spacing"] * 1e-9:.3f}.')
trx_params['equalization_offset_db'] = trx_params.get('equalization_offset_db', 0)
else: else:
mode_params = {"format": "undetermined", mode_params = {"format": "undetermined",
"baud_rate": None, "baud_rate": None,
@@ -40,7 +43,8 @@ def trx_mode_params(equipment, trx_type_variety='', trx_mode='', error_message=F
"roll_off": None, "roll_off": None,
"tx_osnr": None, "tx_osnr": None,
"min_spacing": None, "min_spacing": None,
"cost": None} "cost": None,
"equalization_offset_db": 0}
trx_params = {**mode_params} trx_params = {**mode_params}
trx_params['f_min'] = equipment['Transceiver'][trx_type_variety].frequency['min'] trx_params['f_min'] = equipment['Transceiver'][trx_type_variety].frequency['min']
trx_params['f_max'] = equipment['Transceiver'][trx_type_variety].frequency['max'] trx_params['f_max'] = equipment['Transceiver'][trx_type_variety].frequency['max']
@@ -66,9 +70,7 @@ def trx_mode_params(equipment, trx_type_variety='', trx_mode='', error_message=F
trx_params['roll_off'] = default_si_data.roll_off trx_params['roll_off'] = default_si_data.roll_off
trx_params['tx_osnr'] = default_si_data.tx_osnr trx_params['tx_osnr'] = default_si_data.tx_osnr
trx_params['min_spacing'] = None trx_params['min_spacing'] = None
nch = automatic_nch(trx_params['f_min'], trx_params['f_max'], trx_params['spacing']) trx_params['equalization_offset_db'] = 0
trx_params['nb_channel'] = nch
print(f'There are {nch} channels propagating')
trx_params['power'] = db2lin(default_si_data.power_dbm) * 1e-3 trx_params['power'] = db2lin(default_si_data.power_dbm) * 1e-3

View File

@@ -12,9 +12,10 @@ from __future__ import annotations
from collections import namedtuple from collections import namedtuple
from collections.abc import Iterable from collections.abc import Iterable
from typing import Union from typing import Union
from dataclasses import dataclass
from numpy import argsort, mean, array, append, ones, ceil, any, zeros, outer, full, ndarray, asarray from numpy import argsort, mean, array, append, ones, ceil, any, zeros, outer, full, ndarray, asarray
from gnpy.core.utils import automatic_nch, lin2db, db2lin from gnpy.core.utils import automatic_nch, db2lin, watt2dbm
from gnpy.core.exceptions import SpectrumError from gnpy.core.exceptions import SpectrumError
DEFAULT_SLOT_WIDTH_STEP = 12.5e9 # Hz DEFAULT_SLOT_WIDTH_STEP = 12.5e9 # Hz
@@ -26,33 +27,41 @@ class Power(namedtuple('Power', 'signal nli ase')):
"""carriers power in W""" """carriers power in W"""
class Channel(namedtuple('Channel', class Channel(
'channel_number frequency baud_rate slot_width roll_off power chromatic_dispersion pmd pdl')): namedtuple('Channel',
""" Class containing the parameters of a WDM signal. 'channel_number frequency baud_rate slot_width roll_off power chromatic_dispersion pmd pdl latency')):
:param channel_number: channel number in the WDM grid """Class containing the parameters of a WDM signal.
:param frequency: central frequency of the signal (Hz)
:param baud_rate: the symbol rate of the signal (Baud) :param channel_number: channel number in the WDM grid
:param slot_width: the slot width (Hz) :param frequency: central frequency of the signal (Hz)
:param roll_off: the roll off of the signal. It is a pure number between 0 and 1 :param baud_rate: the symbol rate of the signal (Baud)
:param power (gnpy.core.info.Power): power of signal, ASE noise and NLI (W) :param slot_width: the slot width (Hz)
:param chromatic_dispersion: chromatic dispersion (s/m) :param roll_off: the roll off of the signal. It is a pure number between 0 and 1
:param pmd: polarization mode dispersion (s) :param power (gnpy.core.info.Power): power of signal, ASE noise and NLI (W)
:param pdl: polarization dependent loss (dB) :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 Pref(namedtuple('Pref', 'p_span0, p_spani, neq_ch ')): class Pref(namedtuple('Pref', 'p_span0, p_spani, ref_carrier')):
"""noiseless reference power in dBm: """noiseless reference power in dBm:
p_span0: inital target carrier power
p_spani: carrier power after element i p_span0: inital target carrier power for a reference channel defined by user
neq_ch: equivalent channel count in dB""" p_spani: carrier power after element i for a reference channel defined by user
ref_carrier records the baud rate of the reference channel
"""
class SpectralInformation(object): class SpectralInformation(object):
""" Class containing the parameters of the entire WDM comb.""" """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, 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): roll_off: array, chromatic_dispersion: array, pmd: array, pdl: array, latency: array,
delta_pdb_per_channel: array, tx_osnr: array, ref_power: Pref, label: array):
indices = argsort(frequency) indices = argsort(frequency)
self._frequency = frequency[indices] self._frequency = frequency[indices]
self._df = outer(ones(frequency.shape), frequency) - outer(frequency, ones(frequency.shape)) self._df = outer(ones(frequency.shape), frequency) - outer(frequency, ones(frequency.shape))
@@ -77,8 +86,11 @@ class SpectralInformation(object):
self._chromatic_dispersion = chromatic_dispersion[indices] self._chromatic_dispersion = chromatic_dispersion[indices]
self._pmd = pmd[indices] self._pmd = pmd[indices]
self._pdl = pdl[indices] self._pdl = pdl[indices]
pref = lin2db(mean(signal) * 1e3) self._latency = latency[indices]
self._pref = Pref(pref, pref, lin2db(self._number_of_channels)) self._delta_pdb_per_channel = delta_pdb_per_channel[indices]
self._tx_osnr = tx_osnr[indices]
self._pref = ref_power
self._label = label[indices]
@property @property
def pref(self): def pref(self):
@@ -155,6 +167,10 @@ class SpectralInformation(object):
def pmd(self): def pmd(self):
return self._pmd return self._pmd
@property
def label(self):
return self._label
@pmd.setter @pmd.setter
def pmd(self, pmd): def pmd(self, pmd):
self._pmd = pmd self._pmd = pmd
@@ -167,6 +183,30 @@ class SpectralInformation(object):
def pdl(self, pdl): def pdl(self, pdl):
self._pdl = 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 @property
def channel_number(self): def channel_number(self):
return self._channel_number return self._channel_number
@@ -174,7 +214,7 @@ class SpectralInformation(object):
@property @property
def carriers(self): def carriers(self):
entries = zip(self.channel_number, self.frequency, self.baud_rate, self.slot_width, 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.roll_off, self.powers, self.chromatic_dispersion, self.pmd, self.pdl, self.latency)
return [Channel(*entry) for entry in entries] return [Channel(*entry) for entry in entries]
def apply_attenuation_lin(self, attenuation_lin): def apply_attenuation_lin(self, attenuation_lin):
@@ -197,6 +237,12 @@ class SpectralInformation(object):
def __add__(self, other: SpectralInformation): def __add__(self, other: SpectralInformation):
try: try:
# Note that pref.p_spanx from "self" and "other" must be identical for a given simulation (correspond to the
# the simulation setup):
# - for a given simulation there is only one design (one p_span0),
# - and p_spani is the propagation result of p_span0 so there should not be different p_spani either.
if (self.pref.p_span0 != other.pref.p_span0) or (self.pref.p_spani != other.pref.p_spani):
raise SpectrumError('reference powers of the spectrum are not identical')
return SpectralInformation(frequency=append(self.frequency, other.frequency), return SpectralInformation(frequency=append(self.frequency, other.frequency),
slot_width=append(self.slot_width, other.slot_width), slot_width=append(self.slot_width, other.slot_width),
signal=append(self.signal, other.signal), nli=append(self.nli, other.nli), signal=append(self.signal, other.signal), nli=append(self.nli, other.nli),
@@ -206,14 +252,22 @@ class SpectralInformation(object):
chromatic_dispersion=append(self.chromatic_dispersion, chromatic_dispersion=append(self.chromatic_dispersion,
other.chromatic_dispersion), other.chromatic_dispersion),
pmd=append(self.pmd, other.pmd), pmd=append(self.pmd, other.pmd),
pdl=append(self.pdl, other.pdl)) 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),
ref_power=Pref(self.pref.p_span0, self.pref.p_spani, self.pref.ref_carrier),
label=append(self.label, other.label))
except SpectrumError: except SpectrumError:
raise SpectrumError('Spectra cannot be summed: channels overlapping.') raise SpectrumError('Spectra cannot be summed: channels overlapping.')
def _replace(self, carriers, pref): def _replace(self, carriers, pref):
self.chromatic_dispersion = array([c.chromatic_dispersion for c in carriers]) self.chromatic_dispersion = array([c.chromatic_dispersion for c in carriers])
self.pmd = array([c.pmd for c in carriers]) self.pmd = array([c.pmd for c in carriers])
self.pdl = array([c.pdl 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.signal = array([c.power.signal for c in carriers])
self.nli = array([c.power.nli for c in carriers]) self.nli = array([c.power.nli for c in carriers])
self.ase = array([c.power.ase for c in carriers]) self.ase = array([c.power.ase for c in carriers])
@@ -221,14 +275,19 @@ class SpectralInformation(object):
return self return self
def create_arbitrary_spectral_information(frequency: Union[ndarray, Iterable, int, float], def create_arbitrary_spectral_information(frequency: Union[ndarray, Iterable, float],
signal: Union[int, float, ndarray, Iterable], signal: Union[float, ndarray, Iterable],
baud_rate: Union[int, float, ndarray, Iterable], baud_rate: Union[float, ndarray, Iterable],
slot_width: Union[int, float, ndarray, Iterable] = None, tx_osnr: Union[float, ndarray, Iterable],
roll_off: Union[int, float, ndarray, Iterable] = 0., delta_pdb_per_channel: Union[float, ndarray, Iterable] = 0.,
chromatic_dispersion: Union[int, float, ndarray, Iterable] = 0., slot_width: Union[float, ndarray, Iterable] = None,
pmd: Union[int, float, ndarray, Iterable] = 0., roll_off: Union[float, ndarray, Iterable] = 0.,
pdl: Union[int, 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.,
ref_power: Pref = None,
label: Union[str, ndarray, Iterable] = None):
"""This is just a wrapper around the SpectralInformation.__init__() that simplifies the creation of """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.""" a non-uniform spectral information with NLI and ASE powers set to zero."""
frequency = asarray(frequency) frequency = asarray(frequency)
@@ -242,13 +301,20 @@ def create_arbitrary_spectral_information(frequency: Union[ndarray, Iterable, in
chromatic_dispersion = full(number_of_channels, chromatic_dispersion) chromatic_dispersion = full(number_of_channels, chromatic_dispersion)
pmd = full(number_of_channels, pmd) pmd = full(number_of_channels, pmd)
pdl = full(number_of_channels, pdl) pdl = full(number_of_channels, pdl)
latency = full(number_of_channels, latency)
nli = zeros(number_of_channels) nli = zeros(number_of_channels)
ase = 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)
label = full(number_of_channels, label)
return SpectralInformation(frequency=frequency, slot_width=slot_width, return SpectralInformation(frequency=frequency, slot_width=slot_width,
signal=signal, nli=nli, ase=ase, signal=signal, nli=nli, ase=ase,
baud_rate=baud_rate, roll_off=roll_off, baud_rate=baud_rate, roll_off=roll_off,
chromatic_dispersion=chromatic_dispersion, chromatic_dispersion=chromatic_dispersion,
pmd=pmd, pdl=pdl) pmd=pmd, pdl=pdl, latency=latency,
delta_pdb_per_channel=delta_pdb_per_channel,
tx_osnr=tx_osnr,
ref_power=ref_power, label=label)
except ValueError as e: except ValueError as e:
if 'could not broadcast' in str(e): if 'could not broadcast' in str(e):
raise SpectrumError('Dimension mismatch in input fields.') raise SpectrumError('Dimension mismatch in input fields.')
@@ -256,9 +322,83 @@ def create_arbitrary_spectral_information(frequency: Union[ndarray, Iterable, in
raise raise
def create_input_spectral_information(f_min, f_max, roll_off, baud_rate, power, spacing): def create_input_spectral_information(f_min, f_max, roll_off, baud_rate, power, spacing, tx_osnr, delta_pdb=0,
""" Creates a fixed slot width spectral information with flat power """ ref_carrier=None):
nb_channel = automatic_nch(f_min, f_max, spacing) """Creates a fixed slot width spectral information with flat power.
frequency = [(f_min + spacing * i) for i in range(1, nb_channel + 1)] 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)]
p_span0 = watt2dbm(power)
p_spani = watt2dbm(power)
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=power, baud_rate=baud_rate, return create_arbitrary_spectral_information(frequency, slot_width=spacing, signal=power, baud_rate=baud_rate,
roll_off=roll_off) roll_off=roll_off, delta_pdb_per_channel=delta_pdb_per_channel,
tx_osnr=tx_osnr,
ref_power=Pref(p_span0=p_span0, p_spani=p_spani,
ref_carrier=ref_carrier),
label=label)
def carriers_to_spectral_information(initial_spectrum: dict[float, Carrier], power: float,
ref_carrier: ReferenceCarrier) -> 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 and roll off.
:param power: power of the request
:param ref_carrier: reference carrier (baudrate) used for the reference channel
"""
frequency = list(initial_spectrum.keys())
signal = [power * db2lin(c.delta_pdb) 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()]
label = [c.label for c in initial_spectrum.values()]
p_span0 = watt2dbm(power)
p_spani = watt2dbm(power)
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,
ref_power=Pref(p_span0=p_span0, p_spani=p_spani,
ref_carrier=ref_carrier),
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
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
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 p_span_i 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 slot_width or roll-off) may be added there for future equalization purpose.
"""
baud_rate: float
slot_width: float

View File

@@ -1,18 +1,25 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
''' """
gnpy.core.network gnpy.core.network
================= =================
Working with networks which consist of network elements Working with networks which consist of network elements
''' """
from operator import attrgetter from operator import attrgetter
from gnpy.core import ansi_escapes, elements from collections import namedtuple
from logging import getLogger
from gnpy.core import elements
from gnpy.core.exceptions import ConfigurationError, NetworkTopologyError from gnpy.core.exceptions import ConfigurationError, NetworkTopologyError
from gnpy.core.utils import round2float, convert_length from gnpy.core.utils import round2float, convert_length
from collections import namedtuple from gnpy.core.info import ReferenceCarrier
from gnpy.tools.json_io import Amp
logger = getLogger(__name__)
def edfa_nf(gain_target, variety_type, equipment): def edfa_nf(gain_target, variety_type, equipment):
@@ -103,10 +110,9 @@ def select_edfa(raman_allowed, gain_target, power_target, equipment, uid, restri
please increase span fiber padding') please increase span fiber padding')
else: else:
# TODO: convert to logging # TODO: convert to logging
print( logger.warning(f'\n\tWARNING: target gain in node {uid} is below all available amplifiers min gain: '
f'{ansi_escapes.red}WARNING:{ansi_escapes.reset} target gain in node {uid} is below all available amplifiers min gain: \ + '\n\tamplifier input padding will be assumed, consider increase span fiber padding '
amplifier input padding will be assumed, consider increase span fiber padding instead' + 'instead.\n')
)
acceptable_gain_min_list = edfa_list acceptable_gain_min_list = edfa_list
# filter on gain+power limitation: # filter on gain+power limitation:
@@ -128,12 +134,9 @@ def select_edfa(raman_allowed, gain_target, power_target, equipment, uid, restri
# check what are the gain and power limitations of this amp # check what are the gain and power limitations of this amp
power_reduction = round(min(selected_edfa.power, 0), 2) power_reduction = round(min(selected_edfa.power, 0), 2)
if power_reduction < -0.5: if power_reduction < -0.5:
print( logger.warning(f'\n\tWARNING: target gain and power in node {uid}\n'
f'{ansi_escapes.red}WARNING:{ansi_escapes.reset} target gain and power in node {uid}\n \ + '\tis beyond all available amplifiers capabilities and/or extended_gain_range:\n'
is beyond all available amplifiers capabilities and/or extended_gain_range:\n\ + f'\ta power reduction of {power_reduction} is applied\n')
a power reduction of {power_reduction} is applied\n'
)
return selected_edfa.variety, power_reduction return selected_edfa.variety, power_reduction
@@ -234,25 +237,22 @@ def set_amplifier_voa(amp, power_target, power_mode):
def set_egress_amplifier(network, this_node, equipment, pref_ch_db, pref_total_db): def set_egress_amplifier(network, this_node, equipment, pref_ch_db, pref_total_db):
""" this node can be a transceiver or a ROADM (same function called in both cases) """this node can be a transceiver or a ROADM (same function called in both cases)"""
"""
power_mode = equipment['Span']['default'].power_mode power_mode = equipment['Span']['default'].power_mode
ref_carrier = ReferenceCarrier(baud_rate=equipment['SI']['default'].baud_rate,
slot_width=equipment['SI']['default'].spacing)
next_oms = (n for n in network.successors(this_node) if not isinstance(n, elements.Transceiver)) next_oms = (n for n in network.successors(this_node) if not isinstance(n, elements.Transceiver))
this_node_degree = {k: v for k, v in this_node.per_degree_pch_out_db.items()} if hasattr(this_node, 'per_degree_pch_out_db') else {}
for oms in next_oms: for oms in next_oms:
# go through all the OMS departing from the ROADM # go through all the OMS departing from the ROADM
prev_node = this_node prev_node = this_node
node = oms node = oms
# if isinstance(next_node, elements.Fused): #support ROADM wo egress amp for metro applications if isinstance(this_node, elements.Transceiver):
# node = find_last_node(next_node) this_node_out_power = 0.0 # default value if this_node is a transceiver
# next_node = next(n for n in network.successors(node)) if isinstance(this_node, elements.Roadm):
# next_node = find_last_node(next_node) # get target power out from ROADM for the reference carrier based on equalization settings
if node.uid not in this_node_degree: this_node_out_power = this_node.get_per_degree_ref_power(degree=node.uid, ref_carrier=ref_carrier)
# if no target power is defined on this degree or no per degree target power is given use the global one
# if target_pch_out_db is not an attribute, then the element must be a transceiver
this_node_degree[node.uid] = getattr(this_node.params, 'target_pch_out_db', 0)
# use the target power on this degree # use the target power on this degree
prev_dp = this_node_degree[node.uid] - pref_ch_db prev_dp = this_node_out_power - pref_ch_db
dp = prev_dp dp = prev_dp
prev_voa = 0 prev_voa = 0
voa = 0 voa = 0
@@ -284,7 +284,7 @@ def set_egress_amplifier(network, this_node, equipment, pref_ch_db, pref_total_d
if isinstance(prev_node, elements.Fiber): if isinstance(prev_node, elements.Fiber):
max_fiber_lineic_loss_for_raman = \ max_fiber_lineic_loss_for_raman = \
equipment['Span']['default'].max_fiber_lineic_loss_for_raman * 1e-3 # dB/m equipment['Span']['default'].max_fiber_lineic_loss_for_raman * 1e-3 # dB/m
raman_allowed = prev_node.params.loss_coef < max_fiber_lineic_loss_for_raman raman_allowed = (prev_node.params.loss_coef < max_fiber_lineic_loss_for_raman).all()
else: else:
raman_allowed = False raman_allowed = False
@@ -307,21 +307,21 @@ def set_egress_amplifier(network, this_node, equipment, pref_ch_db, pref_total_d
else: else:
if node.params.raman and not raman_allowed: if node.params.raman and not raman_allowed:
if isinstance(prev_node, elements.Fiber): if isinstance(prev_node, elements.Fiber):
print(f'{ansi_escapes.red}WARNING{ansi_escapes.reset}: raman is used in node {node.uid}\n ' logger.warning(f'\n\tWARNING: raman is used in node {node.uid}\n '
'but fiber lineic loss is above threshold\n') + '\tbut fiber lineic loss is above threshold\n')
else: else:
print(f'{ansi_escapes.red}WARNING{ansi_escapes.reset}: raman is used in node {node.uid}\n ' logger.critical(f'\n\tWARNING: raman is used in node {node.uid}\n '
'but previous node is not a fiber\n') + '\tbut previous node is not a fiber\n')
# if variety is imposed by user, and if the gain_target (computed or imposed) is also above # if variety is imposed by user, and if the gain_target (computed or imposed) is also above
# variety max gain + extended range, then warn that gain > max_gain + extended range # variety max gain + extended range, then warn that gain > max_gain + extended range
if gain_target - equipment['Edfa'][node.params.type_variety].gain_flatmax - \ if gain_target - equipment['Edfa'][node.params.type_variety].gain_flatmax - \
equipment['Span']['default'].target_extended_gain > 1e-2: equipment['Span']['default'].target_extended_gain > 1e-2:
# 1e-2 to allow a small margin according to round2float min step # 1e-2 to allow a small margin according to round2float min step
print(f'{ansi_escapes.red}WARNING{ansi_escapes.reset}: ' logger.warning(f'\n\tWARNING: effective gain in Node {node.uid}\n'
f'WARNING: effective gain in Node {node.uid} is above user ' + f'\tis above user specified amplifier {node.params.type_variety}\n'
f'specified amplifier {node.params.type_variety}\n' + '\tmax flat gain: '
f'max flat gain: {equipment["Edfa"][node.params.type_variety].gain_flatmax}dB ; ' + f'{equipment["Edfa"][node.params.type_variety].gain_flatmax}dB ; '
f'required gain: {gain_target}dB. Please check amplifier type.') + f'required gain: {gain_target}dB. Please check amplifier type.\n')
node.delta_p = dp if power_mode else None node.delta_p = dp if power_mode else None
node.effective_gain = gain_target node.effective_gain = gain_target
@@ -331,10 +331,28 @@ def set_egress_amplifier(network, this_node, equipment, pref_ch_db, pref_total_d
prev_voa = voa prev_voa = voa
prev_node = node prev_node = node
node = next_node node = next_node
# print(f'{node.uid}')
if isinstance(this_node, elements.Roadm):
this_node.per_degree_pch_out_db = {k: v for k, v in this_node_degree.items()} def set_roadm_per_degree_targets(roadm, network):
"""Set target powers/PSD on all degrees
This is needed to populate per_degree_pch_out_dbm or per_degree_pch_psd or per_degree_pch_psw dicts when
they are not initialized by users.
"""
next_oms = (n for n in network.successors(roadm) if not isinstance(n, elements.Transceiver))
for node in next_oms:
# go through all the OMS departing from the ROADM
if node.uid not in roadm.per_degree_pch_out_dbm and node.uid not in roadm.per_degree_pch_psd and \
node.uid not in roadm.per_degree_pch_psw:
# if no target power is defined on this degree or no per degree target power is given use the global one
if roadm.params.target_pch_out_db:
roadm.per_degree_pch_out_dbm[node.uid] = roadm.params.target_pch_out_db
elif roadm.params.target_psd_out_mWperGHz:
roadm.per_degree_pch_psd[node.uid] = roadm.params.target_psd_out_mWperGHz
elif roadm.params.target_out_mWperSlotWidth:
roadm.per_degree_pch_psw[node.uid] = roadm.params.target_out_mWperSlotWidth
else:
raise ConfigurationError(roadm.uid, 'needs an equalization target')
def add_roadm_booster(network, roadm): def add_roadm_booster(network, roadm):
@@ -345,7 +363,7 @@ def add_roadm_booster(network, roadm):
network.remove_edge(roadm, next_node) network.remove_edge(roadm, next_node)
amp = elements.Edfa( amp = elements.Edfa(
uid=f'Edfa_booster_{roadm.uid}_to_{next_node.uid}', uid=f'Edfa_booster_{roadm.uid}_to_{next_node.uid}',
params={}, params=Amp.default_values,
metadata={ metadata={
'location': { 'location': {
'latitude': roadm.lat, 'latitude': roadm.lat,
@@ -371,7 +389,7 @@ def add_roadm_preamp(network, roadm):
network.remove_edge(prev_node, roadm) network.remove_edge(prev_node, roadm)
amp = elements.Edfa( amp = elements.Edfa(
uid=f'Edfa_preamp_{roadm.uid}_from_{prev_node.uid}', uid=f'Edfa_preamp_{roadm.uid}_from_{prev_node.uid}',
params={}, params=Amp.default_values,
metadata={ metadata={
'location': { 'location': {
'latitude': roadm.lat, 'latitude': roadm.lat,
@@ -400,7 +418,7 @@ def add_inline_amplifier(network, fiber):
network.remove_edge(fiber, next_node) network.remove_edge(fiber, next_node)
amp = elements.Edfa( amp = elements.Edfa(
uid=f'Edfa_{fiber.uid}', uid=f'Edfa_{fiber.uid}',
params={}, params=Amp.default_values,
metadata={ metadata={
'location': { 'location': {
'latitude': (fiber.lat + next_node.lat) / 2, 'latitude': (fiber.lat + next_node.lat) / 2,
@@ -432,10 +450,10 @@ def calculate_new_length(fiber_length, bounds, target_length):
return (length1, n_spans1) return (length1, n_spans1)
elif (bounds.start <= length2 <= bounds.stop) and not(bounds.start <= length1 <= bounds.stop): elif (bounds.start <= length2 <= bounds.stop) and not(bounds.start <= length1 <= bounds.stop):
return (length2, n_spans2) return (length2, n_spans2)
elif target_length - length1 < length2 - target_length: elif length2 - target_length <= target_length - length1 and length2 <= bounds.stop:
return (length1, n_spans1)
else:
return (length2, n_spans2) return (length2, n_spans2)
else:
return (length1, n_spans1)
def split_fiber(network, fiber, bounds, target_length, equipment): def split_fiber(network, fiber, bounds, target_length, equipment):
@@ -547,6 +565,7 @@ def build_network(network, equipment, pref_ch_db, pref_total_db, no_insert_edfas
add_fiber_padding(network, fibers, default_span_data.padding) add_fiber_padding(network, fibers, default_span_data.padding)
for roadm in roadms: for roadm in roadms:
set_roadm_per_degree_targets(roadm, network)
set_egress_amplifier(network, roadm, equipment, pref_ch_db, pref_total_db) set_egress_amplifier(network, roadm, equipment, pref_ch_db, pref_total_db)
trx = [t for t in network.nodes() if isinstance(t, elements.Transceiver)] trx = [t for t in network.nodes() if isinstance(t, elements.Transceiver)]

View File

@@ -7,9 +7,10 @@ gnpy.core.parameters
This module contains all parameters to configure standard network elements. This module contains all parameters to configure standard network elements.
""" """
from collections import namedtuple
from scipy.constants import c, pi from scipy.constants import c, pi
from numpy import asarray, array 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.utils import convert_length
from gnpy.core.exceptions import ParametersError from gnpy.core.exceptions import ParametersError
@@ -35,7 +36,8 @@ class PumpParams(Parameters):
class RamanParams(Parameters): class RamanParams(Parameters):
def __init__(self, flag=False, result_spatial_resolution=10e3, solver_spatial_resolution=50): def __init__(self, flag=False, result_spatial_resolution=10e3, solver_spatial_resolution=50):
""" Simulation parameters used within the Raman Solver """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 flag: boolean for enabling/disable the evaluation of the Raman power profile in frequency and position
:params result_spatial_resolution: spatial resolution of the evaluated Raman power profile :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 :params solver_spatial_resolution: spatial step for the iterative solution of the first order ode
@@ -48,7 +50,8 @@ class RamanParams(Parameters):
class NLIParams(Parameters): class NLIParams(Parameters):
def __init__(self, method='gn_model_analytic', dispersion_tolerance=1, phase_shift_tolerance=0.1, def __init__(self, method='gn_model_analytic', dispersion_tolerance=1, phase_shift_tolerance=0.1,
computed_channels=None): computed_channels=None):
""" Simulation parameters used within the Nli Solver """Simulation parameters used within the Nli Solver
:params method: formula for NLI calculation :params method: formula for NLI calculation
:params dispersion_tolerance: tuning parameter for ggn model solution :params dispersion_tolerance: tuning parameter for ggn model solution
:params phase_shift_tolerance: tuning parameter for ggn model solution :params phase_shift_tolerance: tuning parameter for ggn model solution
@@ -63,20 +66,11 @@ class NLIParams(Parameters):
class SimParams(Parameters): class SimParams(Parameters):
_shared_dict = {'nli_params': NLIParams(), 'raman_params': RamanParams()} _shared_dict = {'nli_params': NLIParams(), 'raman_params': RamanParams()}
def __init__(self):
if type(self) == SimParams:
raise NotImplementedError('Instances of SimParams cannot be generated')
@classmethod @classmethod
def set_params(cls, sim_params): def set_params(cls, sim_params):
cls._shared_dict['nli_params'] = NLIParams(**sim_params.get('nli_params', {})) cls._shared_dict['nli_params'] = NLIParams(**sim_params.get('nli_params', {}))
cls._shared_dict['raman_params'] = RamanParams(**sim_params.get('raman_params', {})) cls._shared_dict['raman_params'] = RamanParams(**sim_params.get('raman_params', {}))
@classmethod
def get(cls):
self = cls.__new__(cls)
return self
@property @property
def nli_params(self): def nli_params(self):
return self._shared_dict['nli_params'] return self._shared_dict['nli_params']
@@ -88,13 +82,22 @@ class SimParams(Parameters):
class RoadmParams(Parameters): class RoadmParams(Parameters):
def __init__(self, **kwargs): 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: try:
self.target_pch_out_db = kwargs['target_pch_out_db']
self.add_drop_osnr = kwargs['add_drop_osnr'] self.add_drop_osnr = kwargs['add_drop_osnr']
self.pmd = kwargs['pmd'] self.pmd = kwargs['pmd']
self.pdl = kwargs['pdl'] self.pdl = kwargs['pdl']
self.restrictions = kwargs['restrictions'] self.restrictions = kwargs['restrictions']
self.per_degree_pch_out_db = kwargs['per_degree_pch_out_db'] if 'per_degree_pch_out_db' in kwargs else {}
except KeyError as e: except KeyError as e:
raise ParametersError(f'ROADM configurations must include {e}. Configuration: {kwargs}') raise ParametersError(f'ROADM configurations must include {e}. Configuration: {kwargs}')
@@ -104,26 +107,50 @@ class FusedParams(Parameters):
self.loss = kwargs['loss'] if 'loss' in kwargs else 1 self.loss = kwargs['loss'] if 'loss' in kwargs else 1
# SSMF Raman coefficient profile normalized with respect to the effective area (Cr * A_eff) DEFAULT_RAMAN_COEFFICIENT = {
CR_NORM = array([ # SSMF Raman coefficient profile normalized with respect to the effective area overlap (g0 * A_eff(f_probe, f_pump))
0., 7.802e-16, 2.4236e-15, 4.0504e-15, 5.6606e-15, 6.8973e-15, 7.802e-15, 8.4162e-15, 8.8727e-15, 9.2877e-15, 'g0': array(
1.01011e-14, 1.05244e-14, 1.13295e-14, 1.2367e-14, 1.3695e-14, 1.5023e-14, 1.64091e-14, 1.81936e-14, 2.04927e-14, [0.00000000e+00, 1.12351610e-05, 3.47838074e-05, 5.79356636e-05, 8.06921680e-05, 9.79845709e-05, 1.10454361e-04,
2.28167e-14, 2.48917e-14, 2.66098e-14, 2.82615e-14, 2.98136e-14, 3.1042e-14, 3.17558e-14, 3.18803e-14, 3.17558e-14, 1.18735302e-04, 1.24736889e-04, 1.30110053e-04, 1.41001273e-04, 1.46383247e-04, 1.57011792e-04, 1.70765865e-04,
3.15566e-14, 3.11748e-14, 2.94567e-14, 3.14985e-14, 2.8552e-14, 2.43439e-14, 1.67992e-14, 9.6114e-15, 7.02180e-15, 1.88408911e-04, 2.05914127e-04, 2.24074028e-04, 2.47508283e-04, 2.77729174e-04, 3.08044243e-04, 3.34764439e-04,
5.9262e-15, 5.6938e-15, 7.055e-15, 7.4119e-15, 7.4783e-15, 6.7645e-15, 5.5361e-15, 3.6271e-15, 2.7224e-15, 3.56481704e-04, 3.77127256e-04, 3.96269124e-04, 4.10955175e-04, 4.18718761e-04, 4.19511263e-04, 4.17025384e-04,
2.4568e-15, 2.1995e-15, 2.1331e-15, 2.3323e-15, 2.5564e-15, 3.0461e-15, 4.8555e-15, 5.5029e-15, 5.2788e-15, 4.13565369e-04, 4.07726048e-04, 3.83671291e-04, 4.08564283e-04, 3.69571936e-04, 3.14442090e-04, 2.16074535e-04,
4.565e-15, 3.3698e-15, 2.2991e-15, 2.0086e-15, 1.5521e-15, 1.328e-15, 1.162e-15, 9.379e-16, 8.715e-16, 8.134e-16, 1.23097823e-04, 8.95457457e-05, 7.52470400e-05, 7.19806145e-05, 8.87961158e-05, 9.30812065e-05, 9.37058268e-05,
8.134e-16, 9.379e-16, 1.3612e-15, 1.6185e-15, 1.9754e-15, 1.8758e-15, 1.6849e-15, 1.2284e-15, 9.047e-16, 8.134e-16, 8.45719619e-05, 6.90585286e-05, 4.50407159e-05, 3.36521245e-05, 3.02292475e-05, 2.69376939e-05, 2.60020897e-05,
8.715e-16, 9.711e-16, 1.0375e-15, 1.0043e-15, 9.047e-16, 8.134e-16, 6.806e-16, 5.478e-16, 3.901e-16, 2.241e-16, 2.82958958e-05, 3.08667558e-05, 3.66024657e-05, 5.80610307e-05, 6.54797937e-05, 6.25022715e-05, 5.37806442e-05,
1.577e-16, 9.96e-17, 3.32e-17, 1.66e-17, 8.3e-18]) 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]
), # [m/W]
# Note the non-uniform spacing of this range; this is required for properly capturing the Raman peak shape. # Note the non-uniform spacing of this range; this is required for properly capturing the Raman peak shape.
FREQ_OFFSET = array([ '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., 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.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., 12.,
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, 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.,
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., 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.,
40.5, 41., 41.5, 42.]) * 1e12 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': 206184634112792 # [Hz] (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): class FiberParams(Parameters):
@@ -137,6 +164,8 @@ class FiberParams(Parameters):
# with default values from eqpt_config.json[Spans] # with default values from eqpt_config.json[Spans]
self._con_in = kwargs.get('con_in') self._con_in = kwargs.get('con_in')
self._con_out = kwargs.get('con_out') self._con_out = kwargs.get('con_out')
# Reference frequency (unique for all parameters: beta2, beta3, gamma, effective_area)
if 'ref_wavelength' in kwargs: if 'ref_wavelength' in kwargs:
self._ref_wavelength = kwargs['ref_wavelength'] self._ref_wavelength = kwargs['ref_wavelength']
self._ref_frequency = c / self._ref_wavelength self._ref_frequency = c / self._ref_wavelength
@@ -146,35 +175,70 @@ class FiberParams(Parameters):
else: else:
self._ref_wavelength = 1550e-9 # conventional central C band wavelength [m] self._ref_wavelength = 1550e-9 # conventional central C band wavelength [m]
self._ref_frequency = c / self._ref_wavelength self._ref_frequency = c / self._ref_wavelength
self._dispersion = kwargs['dispersion'] # s/m/m
self._dispersion_slope = \ # Chromatic Dispersion
kwargs.get('dispersion_slope', -2 * self._dispersion / self.ref_wavelength) # s/m/m/m if 'dispersion_per_frequency' in kwargs:
self._beta2 = -(self.ref_wavelength ** 2) * self.dispersion / (2 * pi * c) # 1/(m * Hz^2) # Frequency-dependent dispersion
# Eq. (3.23) in Abramczyk, Halina. "Dispersion phenomena in optical fibers." Virtual European University self._dispersion = asarray(kwargs['dispersion']['value']) # s/m/m
# on Lasers. Available online: http://mitr.p.lodz.pl/evu/lectures/Abramczyk3.pdf self._f_dispersion_ref = asarray(kwargs['dispersion']['frequency']) # Hz
# (accessed on 25 March 2018) (2005). self._dispersion_slope = None
self._beta3 = ((self.dispersion_slope - (4*pi*c/self.ref_wavelength**3) * self.beta2) / elif 'dispersion' in kwargs:
(2*pi*c/self.ref_wavelength**2)**2) # 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._effective_area = kwargs.get('effective_area') # m^2
n2 = 2.6e-20 # m^2/W self._n1 = 1.468
if self._effective_area: self._core_radius = 4.2e-6 # m
self._gamma = kwargs.get('gamma', 2 * pi * n2 / (self.ref_wavelength * self._effective_area)) # 1/W/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: elif 'gamma' in kwargs:
self._gamma = kwargs['gamma'] # 1/W/m self._gamma = kwargs['gamma'] # 1/W/m
self._effective_area = 2 * pi * n2 / (self.ref_wavelength * self._gamma) # m^2 self._effective_area = 2 * pi * self._n2 / (self._ref_wavelength * self._gamma) # m^2
else: else:
self._gamma = 0 # 1/W/m
self._effective_area = 83e-12 # m^2 self._effective_area = 83e-12 # m^2
default_raman_efficiency = {'cr': CR_NORM / self._effective_area, 'frequency_offset': FREQ_OFFSET} self._gamma = 2 * pi * self._n2 / (self._ref_wavelength * self._effective_area) # 1/W/m
self._raman_efficiency = kwargs.get('raman_efficiency', default_raman_efficiency) 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', DEFAULT_RAMAN_COEFFICIENT)
self._g0 = asarray(raman_coefficient['g0'])
raman_reference_frequency = raman_coefficient['reference_frequency']
frequency_offset = asarray(raman_coefficient['frequency_offset'])
stokes_wave = raman_reference_frequency - frequency_offset
gamma_raman = self._g0 * self.effective_area_overlap(stokes_wave, raman_reference_frequency)
normalized_gamma_raman = gamma_raman / raman_reference_frequency # 1 / m / W / Hz
self._raman_reference_frequency = raman_reference_frequency
# 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 = kwargs['pmd_coef'] # s/sqrt(m)
if type(kwargs['loss_coef']) == dict:
# Loss Coefficient
if isinstance(kwargs['loss_coef'], dict):
self._loss_coef = asarray(kwargs['loss_coef']['value']) * 1e-3 # lineic loss dB/m self._loss_coef = asarray(kwargs['loss_coef']['value']) * 1e-3 # lineic loss dB/m
self._f_loss_ref = asarray(kwargs['loss_coef']['frequency']) # Hz self._f_loss_ref = asarray(kwargs['loss_coef']['frequency']) # Hz
else: else:
self._loss_coef = asarray(kwargs['loss_coef']) * 1e-3 # lineic loss dB/m self._loss_coef = asarray(kwargs['loss_coef']) * 1e-3 # lineic loss dB/m
self._f_loss_ref = asarray(self._ref_frequency) # Hz self._f_loss_ref = asarray(self._ref_frequency) # Hz
self._lumped_losses = kwargs['lumped_losses'] if 'lumped_losses' in kwargs else [] # 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: except KeyError as e:
raise ParametersError(f'Fiber configurations json must include {e}. Configuration: {kwargs}') raise ParametersError(f'Fiber configurations json must include {e}. Configuration: {kwargs}')
@@ -219,6 +283,10 @@ class FiberParams(Parameters):
def dispersion(self): def dispersion(self):
return self._dispersion return self._dispersion
@property
def f_dispersion_ref(self):
return self._f_dispersion_ref
@property @property
def dispersion_slope(self): def dispersion_slope(self):
return self._dispersion_slope return self._dispersion_slope
@@ -227,6 +295,20 @@ class FiberParams(Parameters):
def gamma(self): def gamma(self):
return self._gamma 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 @property
def pmd_coef(self): def pmd_coef(self):
return self._pmd_coef return self._pmd_coef
@@ -239,14 +321,6 @@ class FiberParams(Parameters):
def ref_frequency(self): def ref_frequency(self):
return self._ref_frequency return self._ref_frequency
@property
def beta2(self):
return self._beta2
@property
def beta3(self):
return self._beta3
@property @property
def loss_coef(self): def loss_coef(self):
return self._loss_coef return self._loss_coef
@@ -256,36 +330,125 @@ class FiberParams(Parameters):
return self._f_loss_ref return self._f_loss_ref
@property @property
def raman_efficiency(self): def raman_coefficient(self):
return self._raman_efficiency return self._raman_coefficient
@property
def latency(self):
return self._latency
def asdict(self): def asdict(self):
dictionary = super().asdict() dictionary = super().asdict()
dictionary['loss_coef'] = self.loss_coef * 1e3 dictionary['loss_coef'] = self.loss_coef * 1e3
dictionary['length_units'] = 'm' dictionary['length_units'] = 'm'
if not self.lumped_losses: if len(self.lumped_losses) == 0:
dictionary.pop('lumped_losses') dictionary.pop('lumped_losses')
if not self.raman_efficiency: if not self.raman_coefficient:
dictionary.pop('raman_efficiency') 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 return dictionary
class EdfaParams: class EdfaParams:
def __init__(self, **params): def __init__(self, **params):
self.update_params(params) try:
if params == {}: self.type_variety = params['type_variety']
self.type_variety = '' self.type_def = params['type_def']
self.type_def = ''
# self.gain_flatmax = 0 # Bandwidth
# self.gain_min = 0 self.f_min = params['f_min']
# self.p_max = 0 self.f_max = params['f_max']
# self.nf_model = None self.bandwidth = self.f_max - self.f_min
# self.nf_fit_coeff = None self.f_cent = (self.f_max + self.f_min) / 2
# self.nf_ripple = None self.f_ripple_ref = params['f_ripple_ref']
# self.dgt = None
# self.gain_ripple = None # Gain
# self.out_voa_auto = False self.gain_flatmax = params['gain_flatmax']
# self.allowed_for_design = None 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.")
# 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): def update_params(self, kwargs):
for k, v in kwargs.items(): for k, v in kwargs.items():

View File

@@ -10,9 +10,9 @@ Solver definitions to calculate the Raman effect and the nonlinear interference
The solvers take as input instances of the spectral information, the fiber and the simulation parameters The solvers take as input instances of the spectral information, the fiber and the simulation parameters
""" """
from numpy import interp, pi, zeros, shape, where, cos, array, append, ones, exp, arange, sqrt, empty, trapz, arcsinh, \ from numpy import interp, pi, zeros, cos, array, append, ones, exp, arange, sqrt, trapz, arcsinh, clip, abs, sum, \
clip, abs, sum, concatenate, flip, outer, inner, transpose, max, format_float_scientific, diag, prod, argwhere, \ concatenate, flip, outer, inner, transpose, max, format_float_scientific, diag, sort, unique, argsort, cumprod, \
unique, argsort, cumprod polyfit
from logging import getLogger from logging import getLogger
from scipy.constants import k, h from scipy.constants import k, h
from scipy.interpolate import interp1d from scipy.interpolate import interp1d
@@ -24,31 +24,30 @@ from gnpy.core.parameters import SimParams
from gnpy.core.info import SpectralInformation from gnpy.core.info import SpectralInformation
logger = getLogger(__name__) logger = getLogger(__name__)
sim_params = SimParams.get() sim_params = SimParams()
def raised_cosine_comb(f, *carriers):
""" Returns an array storing the PSD of a WDM comb of raised cosine shaped
channels at the input frequencies defined in array f
:param f: numpy array of frequencies in Hz def raised_cosine(frequency, channel_frequency, channel_baud_rate, channel_roll_off):
:param carriers: namedtuple describing the WDM comb """Returns a unitary raised cosine profile for the given parame
:return: PSD of the WDM comb evaluated over f
: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
""" """
psd = zeros(shape(f)) raised_cosine_mask = zeros(frequency.size)
for carrier in carriers: base_frequency = frequency - channel_frequency
f_nch = carrier.frequency ts = 1 / channel_baud_rate
g_ch = carrier.power.signal / carrier.baud_rate pass_band = (1 - channel_roll_off) * channel_baud_rate / 2
ts = 1 / carrier.baud_rate stop_band = (1 + channel_roll_off) * channel_baud_rate / 2
pass_band = (1 - carrier.roll_off) / (2 / carrier.baud_rate)
stop_band = (1 + carrier.roll_off) / (2 / carrier.baud_rate) flat_condition = (abs(base_frequency) <= pass_band) == 1
ff = abs(f - f_nch) cosine_condition = (pass_band < abs(base_frequency)) * (abs(base_frequency) < stop_band) == 1
tf = ff - pass_band
if carrier.roll_off == 0: raised_cosine_mask[flat_condition] = 1
psd = where(tf <= 0, g_ch, 0.) + psd raised_cosine_mask[cosine_condition] = \
else: 0.5 * (1 + cos(pi * ts / channel_roll_off * (abs(base_frequency[cosine_condition]) - pass_band)))
psd = g_ch * (where(tf <= 0, 1., 0.) + 1 / 2 * (1 + cos(pi * ts / carrier.roll_off * tf)) * return raised_cosine_mask
where(tf > 0, 1., 0.) * where(abs(ff) <= stop_band, 1., 0.)) + psd
return psd
class StimulatedRamanScattering: class StimulatedRamanScattering:
@@ -110,6 +109,7 @@ class RamanSolver:
z_step = sim_params.raman_params.solver_spatial_resolution z_step = sim_params.raman_params.solver_spatial_resolution
z = append(arange(0, fiber.params.length, z_step), fiber.params.length) 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 = 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 # Lumped losses array definition
z, lumped_losses = RamanSolver._create_lumped_losses(z, fiber.lumped_losses, fiber.z_lumped_losses) z, lumped_losses = RamanSolver._create_lumped_losses(z, fiber.lumped_losses, fiber.z_lumped_losses)
@@ -131,20 +131,20 @@ class RamanSolver:
cnt_frequency = array([pump.frequency for pump in fiber.raman_pumps cnt_frequency = array([pump.frequency for pump in fiber.raman_pumps
if pump.propagation_direction == 'counterprop']) if pump.propagation_direction == 'counterprop'])
# Co-propagating profile initialization # Co-propagating profile initialization
co_power_profile = empty([co_frequency.size, z.size]) co_power_profile = zeros([co_frequency.size, z.size])
if co_frequency.size: if co_frequency.size:
co_cr = fiber.cr(co_frequency) co_cr = fiber.cr(co_frequency)
co_alpha = fiber.alpha(co_frequency) co_alpha = fiber.alpha(co_frequency)
co_power_profile = \ co_power_profile = \
RamanSolver.first_order_derivative_solution(co_power, co_alpha, co_cr, z, lumped_losses) RamanSolver.first_order_derivative_solution(co_power, co_alpha, co_cr, z, lumped_losses)
# Counter-propagating profile initialization # Counter-propagating profile initialization
cnt_power_profile = empty([co_frequency.size, z.size]) cnt_power_profile = zeros([cnt_frequency.size, z.size])
if cnt_frequency.size: if cnt_frequency.size:
cnt_cr = fiber.cr(cnt_frequency) cnt_cr = fiber.cr(cnt_frequency)
cnt_alpha = fiber.alpha(cnt_frequency) cnt_alpha = fiber.alpha(cnt_frequency)
cnt_power_profile = \ cnt_power_profile = \
flip(RamanSolver.first_order_derivative_solution(cnt_power, cnt_alpha, cnt_cr, flip(RamanSolver.first_order_derivative_solution(cnt_power, cnt_alpha, cnt_cr,
z[-1] - flip(z), flip(lumped_losses))) z[-1] - flip(z), flip(lumped_losses)), axis=1)
# Co-propagating and Counter-propagating Profile Computation # Co-propagating and Counter-propagating Profile Computation
if co_frequency.size and cnt_frequency.size: if co_frequency.size and cnt_frequency.size:
co_power_profile, cnt_power_profile = \ co_power_profile, cnt_power_profile = \
@@ -190,13 +190,13 @@ class RamanSolver:
# calculate ase power # calculate ase power
ase = zeros(spectral_info.number_of_channels) 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): for i, pump in enumerate(fiber.raman_pumps):
pump_power = srs.power_profile[spectral_info.number_of_channels + i, :] pump_power = srs.power_profile[spectral_info.number_of_channels + i, :]
df = pump.frequency - frequency df = pump.frequency - frequency
eta = - 1 / (1 - exp(h * df / (k * fiber.temperature))) eta = - 1 / (1 - exp(h * df / (k * fiber.temperature)))
cr = fiber._cr_function(df)
integral = trapz(pump_power / channels_loss, z, axis=1) integral = trapz(pump_power / channels_loss, z, axis=1)
ase += 2 * h * baud_rate * frequency * (1 + eta) * cr * (df > 0) * integral # 2 factor for double pol ase += 2 * h * baud_rate * frequency * (1 + eta) * cr[:, i] * (df > 0) * integral # 2 factor for double pol
return ase return ase
@staticmethod @staticmethod
@@ -271,13 +271,16 @@ class RamanSolver:
class NliSolver: class NliSolver:
""" This class implements the NLI models. """This class implements the NLI models.
Model and method can be specified in `sim_params.nli_params.method`. Model and method can be specified in `sim_params.nli_params.method`.
List of implemented methods: List of implemented methods:
'gn_model_analytic': eq. 120 from arXiv:1209.0394 'gn_model_analytic': eq. 120 from arXiv:1209.0394
'ggn_spectrally_separated': eq. 21 from arXiv: 1710.02225 spectrally separated 'ggn_spectrally_separated': eq. 21 from arXiv: 1710.02225
""" """
SPM_WEIGHT = (16.0 / 27.0)
XPM_WEIGHT = 2 * (16.0 / 27.0)
@staticmethod @staticmethod
def effective_length(alpha, length): def effective_length(alpha, length):
"""The effective length identify the region in which the NLI has a significant contribution to """The effective length identify the region in which the NLI has a significant contribution to
@@ -287,58 +290,81 @@ class NliSolver:
@staticmethod @staticmethod
def compute_nli(spectral_info: SpectralInformation, srs: StimulatedRamanScattering, fiber): def compute_nli(spectral_info: SpectralInformation, srs: StimulatedRamanScattering, fiber):
""" Compute NLI power generated by the WDM comb `*carriers` on the channel under test `carrier` """Compute NLI power generated by the WDM comb `*carriers` on the channel under test `carrier`
at the end of the fiber span. at the end of the fiber span.
""" """
logger.debug('Start computing fiber NLI noise') logger.debug('Start computing fiber NLI noise')
# Physical fiber parameters
alpha = fiber.alpha(spectral_info.frequency)
beta2 = fiber.params.beta2
beta3 = fiber.params.beta3
f_ref_beta = fiber.params.ref_frequency
gamma = fiber.params.gamma
length = fiber.params.length
if 'gn_model_analytic' == sim_params.nli_params.method: if 'gn_model_analytic' == sim_params.nli_params.method:
nli = NliSolver._gn_analytic(spectral_info, alpha, beta2, gamma, length) 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: elif 'ggn_spectrally_separated' in sim_params.nli_params.method:
nli = NliSolver._ggn_spectrally_separated(spectral_info, srs, alpha, beta2, beta3, f_ref_beta, gamma) if sim_params.nli_params.computed_channels is not None:
cut_indices = array(sim_params.nli_params.computed_channels) - 1
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
else: else:
raise ValueError(f'Method {sim_params.nli_params.method} not implemented.') raise ValueError(f'Method {sim_params.nli_params.method} not implemented.')
return nli return nli
# Methods for computing GN-model # Methods for computing GN-model eta matrix
@staticmethod @staticmethod
def _gn_analytic(spectral_info: SpectralInformation, alpha, beta2, gamma, length): def _gn_analytic(spectral_info, fiber, spm_weight=SPM_WEIGHT, xpm_weight=XPM_WEIGHT):
""" Computes the nonlinear interference power evaluated at the fiber input. """Computes the nonlinear interference power evaluated at the fiber input.
The method uses eq. 120 from arXiv:1209.0394 The method uses eq. 120 from arXiv:1209.0394
""" """
spm_weight = (16.0 / 27.0) * gamma ** 2 # Spectral Features
xpm_weight = 2 * (16.0 / 27.0) * gamma ** 2
nch = spectral_info.number_of_channels 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)) identity = diag(ones(nch))
weight = spm_weight * identity + xpm_weight * (ones([nch, nch]) - identity) weight = spm_weight * identity + xpm_weight * (ones([nch, nch]) - identity)
effective_length = NliSolver.effective_length(alpha, length) effective_length = NliSolver.effective_length(alpha, length)
asymptotic_length = 1 / alpha asymptotic_length = 1 / alpha
df = spectral_info.df cut_baud_rate = outer(baud_rate, ones(nch))
baud_rate = spectral_info.baud_rate pump_baud_rate = outer(ones(nch), baud_rate)
psd = spectral_info.signal / baud_rate psi = NliSolver._psi(delta_frequency, baud_rate, beta2, effective_length, asymptotic_length)
ggg = outer(psd, psd**2) 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
psi = NliSolver._psi(df, baud_rate, beta2, effective_length, asymptotic_length) return eta
g_nli = sum(weight * ggg * psi, 1)
nli = spectral_info.baud_rate * g_nli # Local white noise
return nli
@staticmethod @staticmethod
def _psi(df, baud_rate, beta2, effective_length, asymptotic_length): def _psi(df, baud_rate, beta2, effective_length, asymptotic_length):
"""Calculates eq. 123 from `arXiv:1209.0394 <https://arxiv.org/abs/1209.0394>`__""" """Calculates eq. 123 from `arXiv:1209.0394 <https://arxiv.org/abs/1209.0394>`__"""
cut_baud_rate = outer(baud_rate, ones(baud_rate.size)) cut_baud_rate = outer(baud_rate, ones(baud_rate.size))
cut_beta = outer(beta2, ones(baud_rate.size))
pump_baud_rate = baud_rate 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 right_extreme = df + pump_baud_rate / 2
left_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) - psi = (arcsinh(pi ** 2 * asymptotic_length * abs(beta2) * cut_baud_rate * right_extreme) -
@@ -346,112 +372,133 @@ class NliSolver:
psi *= effective_length ** 2 / (2 * pi * abs(beta2) * asymptotic_length) psi *= effective_length ** 2 / (2 * pi * abs(beta2) * asymptotic_length)
return psi return psi
# Methods for computing the GGN-model # Methods for computing the GGN-model eta matrix
@staticmethod @staticmethod
def _ggn_spectrally_separated(spectral_info: SpectralInformation, srs: StimulatedRamanScattering, def _ggn_spectrally_separated(cut_indices, spectral_info, fiber, srs, spm_weight=SPM_WEIGHT, xpm_weight=XPM_WEIGHT):
alpha, beta2, beta3, f_ref_beta, gamma): """Computes the nonlinear interference power evaluated at the fiber input.
""" Computes the nonlinear interference power evaluated at the fiber input.
The method uses eq. 21 from arXiv: 1710.02225 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 dispersion_tolerance = sim_params.nli_params.dispersion_tolerance
phase_shift_tolerance = sim_params.nli_params.phase_shift_tolerance phase_shift_tolerance = sim_params.nli_params.phase_shift_tolerance
slot_width = max(spectral_info.slot_width) max_slot_width = max(slot_width)
delta_z = sim_params.raman_params.result_spatial_resolution delta_z = sim_params.raman_params.result_spatial_resolution
spm_weight = (16.0 / 27.0) * gamma ** 2
xpm_weight = 2 * (16.0 / 27.0) * gamma ** 2
cuts = [carrier for carrier in spectral_info.carriers if carrier.channel_number
in sim_params.nli_params.computed_channels] if sim_params.nli_params.computed_channels \
else spectral_info.carriers
g_nli = array([]) psi_cut_central_frequency = zeros([cut_indices.size, nch])
f_nli = array([]) for i, cut_index in enumerate(cut_indices):
for cut_carrier in cuts: logger.debug(f'Start computing fiber NLI noise of cut: {cut_index + 1}')
logger.debug(f'Start computing fiber NLI noise of cut: {cut_carrier}') cut_frequency = frequency[cut_index]
f_eval = cut_carrier.frequency cut_baud_rate = baud_rate[cut_index]
g_nli_computed = 0 cut_roll_off = roll_off[cut_index]
g_cut = (cut_carrier.power.signal / cut_carrier.baud_rate) cut_number = cut_index + 1
for j, pump_carrier in enumerate(spectral_info.carriers): cut_beta2 = beta2[cut_index]
dn = abs(pump_carrier.channel_number - cut_carrier.channel_number) cut_base_frequency = frequency - cut_frequency
delta_f = abs(cut_carrier.frequency - pump_carrier.frequency) cut_beta_coefficients = polyfit(cut_base_frequency, beta2, 2)
k_tol = dispersion_tolerance * abs(alpha[j]) 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 phi_tol = phase_shift_tolerance / delta_z
f_cut_resolution = min(k_tol, phi_tol) / abs(beta2) / (4 * pi ** 2 * (1 + dn) * slot_width) 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(beta2) / (4 * pi ** 2 * slot_width) f_pump_resolution = min(k_tol, phi_tol) / abs(cut_beta2) / (4 * pi ** 2 * max_slot_width)
if dn == 0: # SPM if cut_index == pump_index: # SPM
ggg = g_cut ** 3 psi_cut_central_frequency[i, pump_index] = \
g_nli_computed += \ NliSolver._generalized_psi(cut_frequency, cut_frequency, cut_baud_rate, cut_roll_off,
spm_weight * ggg * NliSolver._generalized_psi(f_eval, cut_carrier, pump_carrier, pump_frequency, pump_baud_rate, pump_roll_off, f_cut_resolution,
f_cut_resolution, f_pump_resolution, f_pump_resolution, srs, pump_alpha, cut_beta2, cut_beta3,
srs, alpha[j], beta2, beta3, f_ref_beta) cut_frequency)
else: # XPM else: # XPM
g_pump = (pump_carrier.power.signal / pump_carrier.baud_rate) frequency_offset_threshold = NliSolver._frequency_offset_threshold(cut_beta2, pump_baud_rate)
ggg = g_cut * g_pump ** 2
frequency_offset_threshold = NliSolver._frequency_offset_threshold(beta2, pump_carrier.baud_rate)
if abs(delta_f) <= frequency_offset_threshold: if abs(delta_f) <= frequency_offset_threshold:
g_nli_computed += \ psi_cut_central_frequency[i, pump_index] = \
xpm_weight * ggg * NliSolver._generalized_psi(f_eval, cut_carrier, pump_carrier, NliSolver._generalized_psi(cut_frequency, cut_frequency, cut_baud_rate, cut_roll_off,
f_cut_resolution, f_pump_resolution, pump_frequency, pump_baud_rate, pump_roll_off, f_cut_resolution,
srs, alpha[j], beta2, beta3, f_ref_beta) f_pump_resolution, srs, pump_alpha, cut_beta2, cut_beta3,
cut_frequency)
else: else:
g_nli_computed += \ psi_cut_central_frequency[i, pump_index] = \
xpm_weight * ggg * NliSolver._fast_generalized_psi(f_eval, cut_carrier, pump_carrier, NliSolver._fast_generalized_psi(cut_frequency, cut_frequency, cut_baud_rate, cut_roll_off,
f_cut_resolution, srs, alpha[j], beta2, pump_frequency, pump_baud_rate, pump_roll_off,
beta3, f_ref_beta) f_cut_resolution, srs, pump_alpha, cut_beta2, cut_beta3,
f_nli = append(f_nli, cut_carrier.frequency) cut_frequency)
g_nli = append(g_nli, g_nli_computed)
g_nli = interp(spectral_info.frequency, f_nli, g_nli) cut_baud_rate = outer(baud_rate[cut_indices], ones(nch))
nli = spectral_info.baud_rate * g_nli # Local white noise pump_baud_rate = outer(ones(cut_indices.size), baud_rate)
return nli
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 @staticmethod
def _fast_generalized_psi(f_eval, cut_carrier, pump_carrier, f_cut_resolution, srs, alpha, beta2, beta3, def _fast_generalized_psi(f_eval, cut_frequency, cut_baud_rate, cut_roll_off, pump_frequency, pump_baud_rate,
f_ref_beta): 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_carrier.frequency)
f1_array = array([pump_carrier.frequency - (pump_carrier.baud_rate * (1 + pump_carrier.roll_off) / 2),
pump_carrier.frequency + (pump_carrier.baud_rate * (1 + pump_carrier.roll_off) / 2)])
f2_array = arange(cut_carrier.frequency,
cut_carrier.frequency + (cut_carrier.baud_rate * (1 + cut_carrier.roll_off) / 2),
f_cut_resolution) # Only positive f2 is used since integrand_f2 is symmetric
integrand_f1 = zeros(len(f1_array))
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_carrier.baud_rate
return generalized_psi
@staticmethod
def _generalized_psi(f_eval, cut_carrier, pump_carrier, 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.""" """Computes the generalized psi function similarly to the one used in the GN model."""
z = srs.z z = srs.z
rho_norm = srs.rho * exp(outer(alpha / 2, z)) rho_norm = srs.rho * exp(outer(alpha / 2, z))
rho_pump = interp1d(srs.frequency, rho_norm, axis=0)(pump_carrier.frequency) rho_pump = interp1d(srs.frequency, rho_norm, axis=0)(pump_frequency)
f1_array = arange(pump_carrier.frequency - (pump_carrier.baud_rate * (1 + pump_carrier.roll_off) / 2), f1_array = array([pump_frequency - (pump_baud_rate * (1 + pump_roll_off) / 2),
pump_carrier.frequency + (pump_carrier.baud_rate * (1 + pump_carrier.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) f_pump_resolution)
f2_array = arange(cut_carrier.frequency - (cut_carrier.baud_rate * (1 + cut_carrier.roll_off) / 2), f2_array = arange(cut_frequency - (cut_baud_rate * (1 + cut_roll_off) / 2),
cut_carrier.frequency + (cut_carrier.baud_rate * (1 + cut_carrier.roll_off) / 2), cut_frequency + (cut_baud_rate * (1 + cut_roll_off) / 2),
f_cut_resolution) f_cut_resolution)
psd1 = raised_cosine_comb(f1_array, pump_carrier) * (pump_carrier.baud_rate / pump_carrier.power.signal) rc1 = raised_cosine(f1_array, pump_frequency, pump_baud_rate, pump_roll_off)
integrand_f1 = zeros(len(f1_array)) integrand_f1 = zeros(f1_array.size)
for f1_index, (f1, psd1_sample) in enumerate(zip(f1_array, psd1)): for i in range(f1_array.size):
f3_array = f1 + f2_array - f_eval f3_array = f1_array[i] + f2_array - f_eval
psd2 = raised_cosine_comb(f2_array, cut_carrier) * (cut_carrier.baud_rate / cut_carrier.power.signal) rc2 = raised_cosine(f2_array, cut_frequency, cut_baud_rate, cut_roll_off)
psd3 = raised_cosine_comb(f3_array, pump_carrier) * (pump_carrier.baud_rate / pump_carrier.power.signal) rc3 = raised_cosine(f3_array, pump_frequency, pump_baud_rate, pump_roll_off)
ggg = psd1_sample * psd2 * psd3 delta_beta = 4 * pi ** 2 * (f1_array[i] - f_eval) * (f2_array - f_eval) * (
delta_beta = 4 * pi**2 * (f1 - f_eval) * (f2_array - f_eval) * \ beta2 + pi * beta3 * (f1_array[i] + f2_array - 2 * f_ref_beta))
(beta2 + pi * beta3 * (f1 + f2_array - 2 * f_ref_beta)) integrand_f2 = rc1[i] * rc2 * rc3 * NliSolver._generalized_rho_nli(delta_beta, rho_pump, z, alpha)
integrand_f2 = ggg * NliSolver._generalized_rho_nli(delta_beta, rho_pump, z, alpha) integrand_f1[i] = trapz(integrand_f2, f2_array)
integrand_f1[f1_index] = trapz(integrand_f2, f2_array)
generalized_psi = trapz(integrand_f1, f1_array) generalized_psi = trapz(integrand_f1, f1_array)
return generalized_psi return generalized_psi

View File

@@ -9,8 +9,9 @@ This module contains utility functions that are used with gnpy.
""" """
from csv import writer from csv import writer
from numpy import pi, cos, sqrt, log10, linspace, zeros, shape, where, logical_and from numpy import pi, cos, sqrt, log10, linspace, zeros, shape, where, logical_and, mean
from scipy import constants from scipy import constants
from copy import deepcopy
from gnpy.core.exceptions import ConfigurationError from gnpy.core.exceptions import ConfigurationError
@@ -106,6 +107,69 @@ def db2lin(value):
return 10**(value / 10) 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): def round2float(number, step):
"""Round a floating point number so that its "resolution" is not bigger than 'step' """Round a floating point number so that its "resolution" is not bigger than 'step'
@@ -150,7 +214,7 @@ freq2wavelength = constants.nu2lambda
def freq2wavelength(value): def freq2wavelength(value):
""" Converts frequency units to wavelength units. """Converts frequency units to wavelength units.
>>> round(freq2wavelength(191.35e12) * 1e9, 3) >>> round(freq2wavelength(191.35e12) * 1e9, 3)
1566.723 1566.723
@@ -166,8 +230,33 @@ def snr_sum(snr, bw, snr_added, bw_added=12.5e9):
return snr 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): def deltawl2deltaf(delta_wl, wavelength):
""" deltawl2deltaf(delta_wl, wavelength): """deltawl2deltaf(delta_wl, wavelength):
delta_wl is BW in wavelength units delta_wl is BW in wavelength units
wavelength is the center wl wavelength is the center wl
units for delta_wl and wavelength must be same units for delta_wl and wavelength must be same
@@ -185,9 +274,9 @@ def deltawl2deltaf(delta_wl, wavelength):
def deltaf2deltawl(delta_f, frequency): def deltaf2deltawl(delta_f, frequency):
""" deltawl2deltaf(delta_f, frequency): """convert delta frequency to delta wavelength
converts delta frequency to delta wavelength
units for delta_wl and wavelength must be same Units for delta_wl and wavelength must be same.
:param delta_f: delta frequency in same units as frequency :param delta_f: delta frequency in same units as frequency
:param frequency: frequency BW is relevant for :param frequency: frequency BW is relevant for
@@ -202,8 +291,7 @@ def deltaf2deltawl(delta_f, frequency):
def rrc(ffs, baud_rate, alpha): def rrc(ffs, baud_rate, alpha):
""" rrc(ffs, baud_rate, alpha): computes the root-raised cosine filter """compute the root-raised cosine filter function
function.
:param ffs: A numpy array of frequencies :param ffs: A numpy array of frequencies
:param baud_rate: The Baud Rate of the System :param baud_rate: The Baud Rate of the System
@@ -229,7 +317,7 @@ def rrc(ffs, baud_rate, alpha):
def merge_amplifier_restrictions(dict1, dict2): def merge_amplifier_restrictions(dict1, dict2):
"""Updates contents of dicts recursively """Update contents of dicts recursively
>>> d1 = {'params': {'restrictions': {'preamp_variety_list': [], 'booster_variety_list': []}}} >>> d1 = {'params': {'restrictions': {'preamp_variety_list': [], 'booster_variety_list': []}}}
>>> d2 = {'params': {'target_pch_out_db': -20}} >>> d2 = {'params': {'target_pch_out_db': -20}}
@@ -324,3 +412,43 @@ def convert_length(value, units):
return value * 1e3 return value * 1e3
else: else:
raise ConfigurationError(f'Cannot convert length in "{units}" into meters') 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]

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"
}
]
}

View File

@@ -1,5 +1,5 @@
''' """
Processing of data via :py:mod:`.json_io`. Processing of data via :py:mod:`.json_io`.
Utilities for Excel conversion in :py:mod:`.convert` and :py:mod:`.service_sheet`. Utilities for Excel conversion in :py:mod:`.convert` and :py:mod:`.service_sheet`.
Example code in :py:mod:`.cli_examples` and :py:mod:`.plots`. Example code in :py:mod:`.cli_examples` and :py:mod:`.plots`.
''' """

View File

@@ -1,12 +1,12 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
''' """
gnpy.tools.cli_examples gnpy.tools.cli_examples
======================= =======================
Common code for CLI examples Common code for CLI examples
''' """
import argparse import argparse
import logging import logging
@@ -14,6 +14,7 @@ import sys
from math import ceil from math import ceil
from numpy import linspace, mean from numpy import linspace, mean
from pathlib import Path from pathlib import Path
import gnpy.core.ansi_escapes as ansi_escapes import gnpy.core.ansi_escapes as ansi_escapes
from gnpy.core.elements import Transceiver, Fiber, RamanFiber from gnpy.core.elements import Transceiver, Fiber, RamanFiber
from gnpy.core.equipment import trx_mode_params from gnpy.core.equipment import trx_mode_params
@@ -26,8 +27,8 @@ from gnpy.topology.request import (ResultElement, jsontocsv, compute_path_dsjctn
deduplicate_disjunctions, compute_path_with_disjunction, deduplicate_disjunctions, compute_path_with_disjunction,
PathRequest, compute_constrained_path, propagate) PathRequest, compute_constrained_path, propagate)
from gnpy.topology.spectrum_assignment import build_oms_list, pth_assign_spectrum from gnpy.topology.spectrum_assignment import build_oms_list, pth_assign_spectrum
from gnpy.tools.json_io import load_equipment, load_network, load_json, load_requests, save_network, \ from gnpy.tools.json_io import (load_equipment, load_network, load_json, load_requests, save_network,
requests_from_json, disjunctions_from_json, save_json requests_from_json, disjunctions_from_json, save_json, load_initial_spectrum)
from gnpy.tools.plots import plot_baseline, plot_results from gnpy.tools.plots import plot_baseline, plot_results
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
@@ -47,7 +48,7 @@ def show_example_data_dir():
def load_common_data(equipment_filename, topology_filename, simulation_filename, save_raw_network_filename): def load_common_data(equipment_filename, topology_filename, simulation_filename, save_raw_network_filename):
'''Load common configuration from JSON files''' """Load common configuration from JSON files"""
try: try:
equipment = load_equipment(equipment_filename) equipment = load_equipment(equipment_filename)
@@ -84,7 +85,7 @@ def load_common_data(equipment_filename, topology_filename, simulation_filename,
def _setup_logging(args): def _setup_logging(args):
logging.basicConfig(level={2: logging.DEBUG, 1: logging.INFO, 0: logging.CRITICAL}.get(args.verbose, logging.DEBUG)) logging.basicConfig(level={2: logging.DEBUG, 1: logging.INFO, 0: logging.WARNING}.get(args.verbose, logging.DEBUG))
def _add_common_options(parser: argparse.ArgumentParser, network_default: Path): def _add_common_options(parser: argparse.ArgumentParser, network_default: Path):
@@ -118,6 +119,7 @@ def transmission_main_example(args=None):
parser.add_argument('-pl', '--plot', action='store_true') parser.add_argument('-pl', '--plot', action='store_true')
parser.add_argument('-l', '--list-nodes', action='store_true', help='list all transceiver nodes') parser.add_argument('-l', '--list-nodes', action='store_true', help='list all transceiver nodes')
parser.add_argument('-po', '--power', default=0, help='channel ref power in dBm') parser.add_argument('-po', '--power', default=0, help='channel ref power in dBm')
parser.add_argument('--spectrum', type=Path, help='user defined mixed rate spectrum JSON file')
parser.add_argument('source', nargs='?', help='source node') parser.add_argument('source', nargs='?', help='source node')
parser.add_argument('destination', nargs='?', help='destination node') parser.add_argument('destination', nargs='?', help='destination node')
@@ -194,12 +196,21 @@ def transmission_main_example(args=None):
if args.power: if args.power:
trx_params['power'] = db2lin(float(args.power)) * 1e-3 trx_params['power'] = db2lin(float(args.power)) * 1e-3
params.update(trx_params) params.update(trx_params)
initial_spectrum = None
nb_channels = automatic_nch(trx_params['f_min'], trx_params['f_max'], trx_params['spacing'])
if args.spectrum:
initial_spectrum = load_initial_spectrum(args.spectrum)
nb_channels = len(initial_spectrum)
print('User input for spectrum used for propagation instead of SI')
params['nb_channel'] = nb_channels
req = PathRequest(**params) req = PathRequest(**params)
req.initial_spectrum = initial_spectrum
print(f'There are {nb_channels} channels propagating')
power_mode = equipment['Span']['default'].power_mode power_mode = equipment['Span']['default'].power_mode
print('\n'.join([f'Power mode is set to {power_mode}', print('\n'.join([f'Power mode is set to {power_mode}',
f'=> it can be modified in eqpt_config.json - Span'])) f'=> it can be modified in eqpt_config.json - Span']))
# Keep the reference channel for design: the one from SI, with full load same channels
pref_ch_db = lin2db(req.power * 1e3) # reference channel power / span (SL=20dB) pref_ch_db = lin2db(req.power * 1e3) # reference channel power / span (SL=20dB)
pref_total_db = pref_ch_db + lin2db(req.nb_channel) # reference total power / span (SL=20dB) pref_total_db = pref_ch_db + lin2db(req.nb_channel) # reference total power / span (SL=20dB)
try: try:
@@ -226,9 +237,13 @@ def transmission_main_example(args=None):
power_range = list(linspace(p_start, p_stop, p_num)) power_range = list(linspace(p_start, p_stop, p_num))
except TypeError: except TypeError:
print('invalid power range definition in eqpt_config, should be power_range_db: [lower, upper, step]') print('invalid power range definition in eqpt_config, should be power_range_db: [lower, upper, step]')
for dp_db in power_range: for dp_db in power_range:
req.power = db2lin(pref_ch_db + dp_db) * 1e-3 req.power = db2lin(pref_ch_db + dp_db) * 1e-3
# if initial spectrum did not contain any power, now we need to use this one.
# note the initial power defines a differential wrt req.power so that if req.power is set to 2mW (3dBm)
# and initial spectrum was set to 0, this sets a initial per channel delta power to -3dB, so that
# whatever the equalization, -3 dB is applied on all channels (ie initial power in initial spectrum pre-empts
# "--power" option)
if power_mode: if power_mode:
print(f'\nPropagating with input power = {ansi_escapes.cyan}{lin2db(req.power*1e3):.2f} dBm{ansi_escapes.reset}:') print(f'\nPropagating with input power = {ansi_escapes.cyan}{lin2db(req.power*1e3):.2f} dBm{ansi_escapes.reset}:')
else: else:
@@ -264,9 +279,9 @@ def transmission_main_example(args=None):
ch_freq = final_carrier.frequency * 1e-12 ch_freq = final_carrier.frequency * 1e-12
ch_power = lin2db(final_carrier.power.signal * 1e3) ch_power = lin2db(final_carrier.power.signal * 1e3)
print( print(
'{:5}{:26.2f}{:26.2f}{:28.2f}{:28.2f}{:28.2f}' .format( '{:5}{:26.5f}{:26.2f}{:28.2f}{:28.2f}{:28.2f}' .format(
final_carrier.channel_number, round( final_carrier.channel_number, round(
ch_freq, 2), round( ch_freq, 5), round(
ch_power, 2), round( ch_power, 2), round(
ch_osnr, 2), round( ch_osnr, 2), round(
ch_snr_nl, 2), round( ch_snr_nl, 2), round(
@@ -308,7 +323,7 @@ def path_requests_run(args=None):
args = parser.parse_args(args if args is not None else sys.argv[1:]) args = parser.parse_args(args if args is not None else sys.argv[1:])
_setup_logging(args) _setup_logging(args)
_logger.info(f'Computing path requests {args.service_filename} into JSON format') _logger.info(f'Computing path requests {args.service_filename.name} into JSON format')
(equipment, network) = load_common_data(args.equipment, args.topology, args.sim_params, args.save_network_before_autodesign) (equipment, network) = load_common_data(args.equipment, args.topology, args.sim_params, args.save_network_before_autodesign)
@@ -316,7 +331,6 @@ def path_requests_run(args=None):
# TODO power density: db2linp(ower_dbm": 0)/power_dbm": 0 * nb channels as defined by # TODO power density: db2linp(ower_dbm": 0)/power_dbm": 0 * nb channels as defined by
# spacing, f_min and f_max # spacing, f_min and f_max
p_db = equipment['SI']['default'].power_dbm p_db = equipment['SI']['default'].power_dbm
p_total_db = p_db + lin2db(automatic_nch(equipment['SI']['default'].f_min, p_total_db = p_db + lin2db(automatic_nch(equipment['SI']['default'].f_min,
equipment['SI']['default'].f_max, equipment['SI']['default'].spacing)) equipment['SI']['default'].f_max, equipment['SI']['default'].spacing))
try: try:

View File

@@ -21,18 +21,22 @@ the "east" information so that it is possible to input undirected data.
""" """
from xlrd import open_workbook from xlrd import open_workbook
from logging import getLogger
from argparse import ArgumentParser from argparse import ArgumentParser
from collections import namedtuple, Counter, defaultdict from collections import namedtuple, Counter, defaultdict
from itertools import chain from itertools import chain
from json import dumps from json import dumps
from pathlib import Path from pathlib import Path
from copy import copy from copy import copy
from gnpy.core import ansi_escapes
from gnpy.core.utils import silent_remove from gnpy.core.utils import silent_remove
from gnpy.core.exceptions import NetworkTopologyError from gnpy.core.exceptions import NetworkTopologyError
from gnpy.core.elements import Edfa, Fused, Fiber from gnpy.core.elements import Edfa, Fused, Fiber
_logger = getLogger(__name__)
def all_rows(sh, start=0): def all_rows(sh, start=0):
return (sh.row(x) for x in range(start, sh.nrows)) return (sh.row(x) for x in range(start, sh.nrows))
@@ -183,18 +187,18 @@ def parse_headers(my_sheet, input_headers_dict, headers, start_line, slice_in):
slice_out = read_slice(my_sheet, start_line + iteration, slice_in, h0) slice_out = read_slice(my_sheet, start_line + iteration, slice_in, h0)
iteration += 1 iteration += 1
if slice_out == (-1, -1): if slice_out == (-1, -1):
msg = f'missing header {h0}'
if h0 in ('east', 'Node A', 'Node Z', 'City'): if h0 in ('east', 'Node A', 'Node Z', 'City'):
print(f'{ansi_escapes.red}CRITICAL{ansi_escapes.reset}: missing _{h0}_ header: EXECUTION ENDS') raise NetworkTopologyError(msg)
raise NetworkTopologyError(f'Missing _{h0}_ header')
else: else:
print(f'missing header {h0}') _logger.warning(msg)
elif not isinstance(input_headers_dict[h0], dict): elif not isinstance(input_headers_dict[h0], dict):
headers[slice_out[0]] = input_headers_dict[h0] headers[slice_out[0]] = input_headers_dict[h0]
else: else:
headers = parse_headers(my_sheet, input_headers_dict[h0], headers, start_line + 1, slice_out) headers = parse_headers(my_sheet, input_headers_dict[h0], headers, start_line + 1, slice_out)
if headers == {}: if headers == {}:
print(f'{ansi_escapes.red}CRITICAL ERROR{ansi_escapes.reset}: could not find any header to read _ ABORT') msg = 'CRITICAL ERROR: could not find any header to read _ ABORT'
raise NetworkTopologyError('Could not find any header to read') raise NetworkTopologyError(msg)
return headers return headers
@@ -219,40 +223,76 @@ def sanity_check(nodes, links, nodes_by_city, links_by_city, eqpts_by_city):
for l1 in links: for l1 in links:
for l2 in links: for l2 in links:
if l1 is not l2 and l1 == l2 and l2 not in duplicate_links: if l1 is not l2 and l1 == l2 and l2 not in duplicate_links:
print(f'\nWARNING\n \ _logger.warning(f'\nWARNING\n \
link {l1.from_city}-{l1.to_city} is duplicate \ link {l1.from_city}-{l1.to_city} is duplicate \
\nthe 1st duplicate link will be removed but you should check Links sheet input') \nthe 1st duplicate link will be removed but you should check Links sheet input')
duplicate_links.append(l1) duplicate_links.append(l1)
for l in duplicate_links: if duplicate_links:
links.remove(l) msg = 'XLS error: ' \
links_by_city[l.from_city].remove(l) + f'links {_format_items([(d.from_city, d.to_city) for d in duplicate_links])} are duplicate'
links_by_city[l.to_city].remove(l) raise NetworkTopologyError(msg)
unreferenced_nodes = [n for n in nodes_by_city if n not in links_by_city] unreferenced_nodes = [n for n in nodes_by_city if n not in links_by_city]
if unreferenced_nodes: if unreferenced_nodes:
raise NetworkTopologyError(f'{ansi_escapes.red}XLS error:{ansi_escapes.reset} The following nodes are not ' msg = 'XLS error: The following nodes are not ' \
f'referenced from the {ansi_escapes.cyan}Links{ansi_escapes.reset} sheet. ' + 'referenced from the Links sheet. ' \
f'If unused, remove them from the {ansi_escapes.cyan}Nodes{ansi_escapes.reset} ' + 'If unused, remove them from the Nodes sheet:\n' \
f'sheet:\n' + _format_items(unreferenced_nodes)
+ _format_items(unreferenced_nodes)) raise NetworkTopologyError(msg)
# no need to check "Links" for invalid nodes because that's already in parse_excel() # no need to check "Links" for invalid nodes because that's already in parse_excel()
wrong_eqpt_from = [n for n in eqpts_by_city if n not in nodes_by_city] wrong_eqpt_from = [n for n in eqpts_by_city if n not in nodes_by_city]
wrong_eqpt_to = [n.to_city for destinations in eqpts_by_city.values() wrong_eqpt_to = [n.to_city for destinations in eqpts_by_city.values()
for n in destinations if n.to_city not in nodes_by_city] for n in destinations if n.to_city not in nodes_by_city]
wrong_eqpt = wrong_eqpt_from + wrong_eqpt_to wrong_eqpt = wrong_eqpt_from + wrong_eqpt_to
if wrong_eqpt: if wrong_eqpt:
raise NetworkTopologyError(f'{ansi_escapes.red}XLS error:{ansi_escapes.reset} ' msg = 'XLS error: ' \
f'The {ansi_escapes.cyan}Eqpt{ansi_escapes.reset} sheet refers to nodes that ' + 'The Eqpt sheet refers to nodes that ' \
f'are not defined in the {ansi_escapes.cyan}Nodes{ansi_escapes.reset} sheet:\n' + 'are not defined in the Nodes sheet:\n'\
+ _format_items(wrong_eqpt)) + _format_items(wrong_eqpt)
raise NetworkTopologyError(msg)
# Now check links that are not listed in Links sheet, and duplicates
bad_eqpt = []
possible_links = [f'{e.from_city}|{e.to_city}' for e in links] + [f'{e.to_city}|{e.from_city}' for e in links]
possible_eqpt = []
duplicate_eqpt = []
duplicate_ila = []
for city, eqpts in eqpts_by_city.items():
for eqpt in eqpts:
# Check that each node_A-node_Z exists in links
nodea_nodez = f'{eqpt.from_city}|{eqpt.to_city}'
nodez_nodea = f'{eqpt.to_city}|{eqpt.from_city}'
if nodea_nodez not in possible_links \
or nodez_nodea not in possible_links:
bad_eqpt.append([eqpt.from_city, eqpt.to_city])
else:
# Check that there are no duplicate lines in the Eqpt sheet
if nodea_nodez in possible_eqpt:
duplicate_eqpt.append([eqpt.from_city, eqpt.to_city])
else:
possible_eqpt.append(nodea_nodez)
# check that there are no two lines defining an ILA with different directions
if nodes_by_city[city].node_type == 'ILA' and len(eqpts) > 1:
duplicate_ila.append(city)
if bad_eqpt:
msg = 'XLS error: ' \
+ 'The Eqpt sheet references links that ' \
+ 'are not defined in the Links sheet:\n' \
+ _format_items(f'{item[0]} -> {item[1]}' for item in bad_eqpt)
raise NetworkTopologyError(msg)
if duplicate_eqpt:
msg = 'XLS error: Duplicate lines in Eqpt sheet:' \
+ _format_items(f'{item[0]} -> {item[1]}' for item in duplicate_eqpt)
raise NetworkTopologyError(msg)
if duplicate_ila:
msg = 'XLS error: Duplicate ILA eqpt definition in Eqpt sheet:' \
+ _format_items(duplicate_ila)
raise NetworkTopologyError(msg)
for city, link in links_by_city.items(): for city, link in links_by_city.items():
if nodes_by_city[city].node_type.lower() == 'ila' and len(link) != 2: if nodes_by_city[city].node_type.lower() == 'ila' and len(link) != 2:
# wrong input: ILA sites can only be Degree 2 # wrong input: ILA sites can only be Degree 2
# => correct to make it a ROADM and remove entry in links_by_city # => correct to make it a ROADM and remove entry in links_by_city
# TODO: put in log rather than print _logger.warning(f'invalid node type ({nodes_by_city[city].node_type}) '
print(f'invalid node type ({nodes_by_city[city].node_type})\ + f'specified in {city}, replaced by ROADM')
specified in {city}, replaced by ROADM')
nodes_by_city[city].node_type = 'ROADM' nodes_by_city[city].node_type = 'ROADM'
for n in nodes: for n in nodes:
if n.city == city: if n.city == city:
@@ -642,17 +682,19 @@ def parse_excel(input_filename):
# sanity check # sanity check
all_cities = Counter(n.city for n in nodes) all_cities = Counter(n.city for n in nodes)
if len(all_cities) != len(nodes): if len(all_cities) != len(nodes):
raise ValueError(f'Duplicate city: {all_cities}') msg = f'Duplicate city: {all_cities}'
raise NetworkTopologyError(msg)
bad_links = [] bad_links = []
for lnk in links: for lnk in links:
if lnk.from_city not in all_cities or lnk.to_city not in all_cities: if lnk.from_city not in all_cities or lnk.to_city not in all_cities:
bad_links.append([lnk.from_city, lnk.to_city]) bad_links.append([lnk.from_city, lnk.to_city])
if bad_links: if bad_links:
raise NetworkTopologyError(f'{ansi_escapes.red}XLS error:{ansi_escapes.reset} ' msg = 'XLS error: ' \
f'The {ansi_escapes.cyan}Links{ansi_escapes.reset} sheet references nodes that ' + 'The Links sheet references nodes that ' \
f'are not defined in the {ansi_escapes.cyan}Nodes{ansi_escapes.reset} sheet:\n' + 'are not defined in the Nodes sheet:\n' \
+ _format_items(f'{item[0]} -> {item[1]}' for item in bad_links)) + _format_items(f'{item[0]} -> {item[1]}' for item in bad_links)
raise NetworkTopologyError(msg)
return nodes, links, eqpts, roadms return nodes, links, eqpts, roadms

View File

@@ -1,24 +1,29 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
''' """
gnpy.tools.json_io gnpy.tools.json_io
================== ==================
Loading and saving data from JSON files in GNPy's internal data format Loading and saving data from JSON files in GNPy's internal data format
''' """
from networkx import DiGraph from networkx import DiGraph
from logging import getLogger from logging import getLogger
from pathlib import Path from pathlib import Path
import json import json
from collections import namedtuple from collections import namedtuple
from gnpy.core import ansi_escapes, elements from numpy import arange
from gnpy.core import elements
from gnpy.core.equipment import trx_mode_params from gnpy.core.equipment import trx_mode_params
from gnpy.core.exceptions import ConfigurationError, EquipmentConfigError, NetworkTopologyError, ServiceError from gnpy.core.exceptions import ConfigurationError, EquipmentConfigError, NetworkTopologyError, ServiceError
from gnpy.core.science_utils import estimate_nf_model from gnpy.core.science_utils import estimate_nf_model
from gnpy.core.info import Carrier
from gnpy.core.utils import automatic_nch, automatic_fmax, merge_amplifier_restrictions from gnpy.core.utils import automatic_nch, automatic_fmax, merge_amplifier_restrictions
from gnpy.core.parameters import DEFAULT_RAMAN_COEFFICIENT
from gnpy.topology.request import PathRequest, Disjunction, compute_spectrum_slot_vs_bandwidth from gnpy.topology.request import PathRequest, Disjunction, compute_spectrum_slot_vs_bandwidth
from gnpy.topology.spectrum_assignment import mvalue_to_slots
from gnpy.tools.convert import xls_to_json_data from gnpy.tools.convert import xls_to_json_data
from gnpy.tools.service_sheet import read_service_sheet from gnpy.tools.service_sheet import read_service_sheet
@@ -47,10 +52,9 @@ class _JsonThing:
for k, v in default_values.items(): for k, v in default_values.items():
setattr(self, k, clean_kwargs.get(k, v)) setattr(self, k, clean_kwargs.get(k, v))
if k not in clean_kwargs and name != 'Amp': if k not in clean_kwargs and name != 'Amp':
print(ansi_escapes.red + msg = f'\n WARNING missing {k} attribute in eqpt_config.json[{name}]' \
f'\n WARNING missing {k} attribute in eqpt_config.json[{name}]' + + f'\n default value is {k} = {v}'
f'\n default value is {k} = {v}' + _logger.warning(msg)
ansi_escapes.reset)
class SI(_JsonThing): class SI(_JsonThing):
@@ -91,7 +95,6 @@ class Span(_JsonThing):
class Roadm(_JsonThing): class Roadm(_JsonThing):
default_values = { default_values = {
'target_pch_out_db': -17,
'add_drop_osnr': 100, 'add_drop_osnr': 100,
'pmd': 0, 'pmd': 0,
'pdl': 0, 'pdl': 0,
@@ -102,6 +105,21 @@ class Roadm(_JsonThing):
} }
def __init__(self, **kwargs): def __init__(self, **kwargs):
# If equalization is not defined in equipment, then raise an error.
# Only one type of equalization must be defined.
allowed_equalisations = ['target_pch_out_db', 'target_psd_out_mWperGHz', 'target_out_mWperSlotWidth']
requested_eq_mask = [eq in kwargs for eq in allowed_equalisations]
if sum(requested_eq_mask) > 1:
msg = 'Only one equalization type should be set in ROADM, found: ' \
+ ', '.join(eq for eq in allowed_equalisations if eq in kwargs)
raise EquipmentConfigError(msg)
if not any(requested_eq_mask):
msg = 'No equalization type set in ROADM'
raise EquipmentConfigError(msg)
for key in allowed_equalisations:
if key in kwargs:
setattr(self, key, kwargs[key])
break
self.update_attr(self.default_values, kwargs, 'Roadm') self.update_attr(self.default_values, kwargs, 'Roadm')
@@ -117,6 +135,7 @@ class Transceiver(_JsonThing):
for mode_params in self.mode: for mode_params in self.mode:
penalties = mode_params.get('penalties') penalties = mode_params.get('penalties')
mode_params['penalties'] = {} mode_params['penalties'] = {}
mode_params['equalization_offset_db'] = mode_params.get('equalization_offset_db', 0)
if not penalties: if not penalties:
continue continue
for impairment in ('chromatic_dispersion', 'pmd', 'pdl'): for impairment in ('chromatic_dispersion', 'pmd', 'pdl'):
@@ -146,9 +165,14 @@ class Fiber(_JsonThing):
def __init__(self, **kwargs): def __init__(self, **kwargs):
self.update_attr(self.default_values, kwargs, self.__class__.__name__) self.update_attr(self.default_values, kwargs, self.__class__.__name__)
for optional in ['gamma', 'raman_efficiency']: if 'gamma' in kwargs:
if optional in kwargs: setattr(self, 'gamma', kwargs['gamma'])
setattr(self, optional, kwargs[optional]) if 'raman_efficiency' in kwargs:
raman_coefficient = kwargs['raman_efficiency']
cr = raman_coefficient.pop('cr')
raman_coefficient['g0'] = cr
raman_coefficient['reference_frequency'] = DEFAULT_RAMAN_COEFFICIENT['reference_frequency']
setattr(self, 'raman_coefficient', raman_coefficient)
class RamanFiber(Fiber): class RamanFiber(Fiber):
@@ -166,15 +190,24 @@ class Amp(_JsonThing):
'p_max': None, 'p_max': None,
'nf_model': None, 'nf_model': None,
'dual_stage_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_fit_coeff': None,
'nf_ripple': None, 'nf_ripple': 0,
'dgt': None, 'dgt': None,
'gain_ripple': None, 'gain_ripple': 0,
'tilt_ripple': 0,
'f_ripple_ref': None,
'out_voa_auto': False, 'out_voa_auto': False,
'allowed_for_design': False, 'allowed_for_design': False,
'raman': False, 'raman': False,
'pmd': 0, 'pmd': 0,
'pdl': 0 'pdl': 0,
'advance_configurations_from_json': None
} }
def __init__(self, **kwargs): def __init__(self, **kwargs):
@@ -193,7 +226,8 @@ class Amp(_JsonThing):
try: try:
nf0 = kwargs.pop('nf0') nf0 = kwargs.pop('nf0')
except KeyError: # nf0 is expected for a fixed gain amp except KeyError: # nf0 is expected for a fixed gain amp
raise EquipmentConfigError(f'missing nf0 value input for amplifier: {type_variety} in equipment config') msg = f'missing nf0 value input for amplifier: {type_variety} in equipment config'
raise EquipmentConfigError(msg)
for k in ('nf_min', 'nf_max'): for k in ('nf_min', 'nf_max'):
try: try:
del kwargs[k] del kwargs[k]
@@ -208,7 +242,8 @@ class Amp(_JsonThing):
nf_min = kwargs.pop('nf_min') nf_min = kwargs.pop('nf_min')
nf_max = kwargs.pop('nf_max') nf_max = kwargs.pop('nf_max')
except KeyError: except KeyError:
raise EquipmentConfigError(f'missing nf_min or nf_max value input for amplifier: {type_variety} in equipment config') msg = f'missing nf_min or nf_max value input for amplifier: {type_variety} in equipment config'
raise EquipmentConfigError(msg)
try: # remove all remaining nf inputs try: # remove all remaining nf inputs
del kwargs['nf0'] del kwargs['nf0']
except KeyError: except KeyError:
@@ -230,7 +265,8 @@ class Amp(_JsonThing):
preamp_variety = kwargs.pop('preamp_variety') preamp_variety = kwargs.pop('preamp_variety')
booster_variety = kwargs.pop('booster_variety') booster_variety = kwargs.pop('booster_variety')
except KeyError: except KeyError:
raise EquipmentConfigError(f'missing preamp/booster variety input for amplifier: {type_variety} in equipment config') msg = f'missing preamp/booster variety input for amplifier: {type_variety} in equipment config'
raise EquipmentConfigError(msg)
dual_stage_def = Model_dual_stage(preamp_variety, booster_variety) dual_stage_def = Model_dual_stage(preamp_variety, booster_variety)
else: else:
raise EquipmentConfigError(f'Edfa type_def {type_def} does not exist') raise EquipmentConfigError(f'Edfa type_def {type_def} does not exist')
@@ -249,11 +285,89 @@ def _automatic_spacing(baud_rate):
return min((s[1] for s in spacing_list if s[0] > baud_rate), default=baud_rate * 1.2) return min((s[1] for s in spacing_list if s[0] > baud_rate), default=baud_rate * 1.2)
def _spectrum_from_json(json_data):
"""JSON_data is a list of spectrum partitions each with
{f_min, f_max, baud_rate, roll_off, delta_pdb, slot_width, tx_osnr, label}
Creates the per freq Carrier's dict.
f_min, f_max, baud_rate, slot_width and roll_off are mandatory
label, tx_osnr and delta_pdb are created if not present
label should be different for each partition
>>> json_data = {'spectrum': \
[{'f_min': 193.2e12, 'f_max': 193.4e12, 'slot_width': 50e9, 'baud_rate': 32e9, 'roll_off': 0.15, \
'delta_pdb': 1, 'tx_osnr': 45},\
{'f_min': 193.4625e12, 'f_max': 193.9875e12, 'slot_width': 75e9, 'baud_rate': 64e9, 'roll_off': 0.15},\
{'f_min': 194.075e12, 'f_max': 194.075e12, 'slot_width': 100e9, 'baud_rate': 90e9, 'roll_off': 0.15},\
{'f_min': 194.2e12, 'f_max': 194.35e12, 'slot_width': 50e9, 'baud_rate': 32e9, 'roll_off': 0.15}]}
>>> spectrum = _spectrum_from_json(json_data['spectrum'])
>>> for k, v in spectrum.items():
... print(f'{k}: {v}')
...
193200000000000.0: Carrier(delta_pdb=1, baud_rate=32000000000.0, slot_width=50000000000.0, roll_off=0.15, tx_osnr=45, label='0-32.00G')
193250000000000.0: Carrier(delta_pdb=1, baud_rate=32000000000.0, slot_width=50000000000.0, roll_off=0.15, tx_osnr=45, label='0-32.00G')
193300000000000.0: Carrier(delta_pdb=1, baud_rate=32000000000.0, slot_width=50000000000.0, roll_off=0.15, tx_osnr=45, label='0-32.00G')
193350000000000.0: Carrier(delta_pdb=1, baud_rate=32000000000.0, slot_width=50000000000.0, roll_off=0.15, tx_osnr=45, label='0-32.00G')
193400000000000.0: Carrier(delta_pdb=1, baud_rate=32000000000.0, slot_width=50000000000.0, roll_off=0.15, tx_osnr=45, label='0-32.00G')
193462500000000.0: Carrier(delta_pdb=0, baud_rate=64000000000.0, slot_width=75000000000.0, roll_off=0.15, tx_osnr=40, label='1-64.00G')
193537500000000.0: Carrier(delta_pdb=0, baud_rate=64000000000.0, slot_width=75000000000.0, roll_off=0.15, tx_osnr=40, label='1-64.00G')
193612500000000.0: Carrier(delta_pdb=0, baud_rate=64000000000.0, slot_width=75000000000.0, roll_off=0.15, tx_osnr=40, label='1-64.00G')
193687500000000.0: Carrier(delta_pdb=0, baud_rate=64000000000.0, slot_width=75000000000.0, roll_off=0.15, tx_osnr=40, label='1-64.00G')
193762500000000.0: Carrier(delta_pdb=0, baud_rate=64000000000.0, slot_width=75000000000.0, roll_off=0.15, tx_osnr=40, label='1-64.00G')
193837500000000.0: Carrier(delta_pdb=0, baud_rate=64000000000.0, slot_width=75000000000.0, roll_off=0.15, tx_osnr=40, label='1-64.00G')
193912500000000.0: Carrier(delta_pdb=0, baud_rate=64000000000.0, slot_width=75000000000.0, roll_off=0.15, tx_osnr=40, label='1-64.00G')
193987500000000.0: Carrier(delta_pdb=0, baud_rate=64000000000.0, slot_width=75000000000.0, roll_off=0.15, tx_osnr=40, label='1-64.00G')
194075000000000.0: Carrier(delta_pdb=0, baud_rate=90000000000.0, slot_width=100000000000.0, roll_off=0.15, tx_osnr=40, label='2-90.00G')
194200000000000.0: Carrier(delta_pdb=0, baud_rate=32000000000.0, slot_width=50000000000.0, roll_off=0.15, tx_osnr=40, label='3-32.00G')
194250000000000.0: Carrier(delta_pdb=0, baud_rate=32000000000.0, slot_width=50000000000.0, roll_off=0.15, tx_osnr=40, label='3-32.00G')
194300000000000.0: Carrier(delta_pdb=0, baud_rate=32000000000.0, slot_width=50000000000.0, roll_off=0.15, tx_osnr=40, label='3-32.00G')
194350000000000.0: Carrier(delta_pdb=0, baud_rate=32000000000.0, slot_width=50000000000.0, roll_off=0.15, tx_osnr=40, label='3-32.00G')
"""
spectrum = {}
json_data = sorted(json_data, key=lambda x: x['f_min'])
# min freq of occupation is f_min - slot_width/2 (numbering starts at 0)
previous_part_max_freq = 0.0
for index, part in enumerate(json_data):
# default delta_pdb is 0 dB
if 'delta_pdb' not in part:
part['delta_pdb'] = 0
# add a label to the partition for the printings
if 'label' not in part:
part['label'] = f'{index}-{part["baud_rate"] * 1e-9 :.2f}G'
# default tx_osnr is set to 40 dB
if 'tx_osnr' not in part:
part['tx_osnr'] = 40
# starting freq is exactly f_min to be consistent with utils.automatic_nch
# first partition min occupation is f_min - slot_width / 2 (central_frequency is f_min)
# supposes that carriers are centered on frequency
if previous_part_max_freq > (part['f_min'] - part['slot_width'] / 2):
# check that previous part last channel does not overlap on next part first channel
# max center of the part should be below part['f_max'] and aligned on the slot_width
msg = 'Not a valid initial spectrum definition:\nprevious spectrum last carrier max occupation ' +\
f'{previous_part_max_freq * 1e-12 :.5f}GHz ' +\
'overlaps on next spectrum first carrier occupation ' +\
f'{(part["f_min"] - part["slot_width"] / 2) * 1e-12 :.5f}GHz'
raise ValueError(msg)
max_range = ((part['f_max'] - part['f_min']) // part['slot_width'] + 1) * part['slot_width']
for current_freq in arange(part['f_min'],
part['f_min'] + max_range,
part['slot_width']):
spectrum[current_freq] = Carrier(delta_pdb=part['delta_pdb'], baud_rate=part['baud_rate'],
slot_width=part['slot_width'], roll_off=part['roll_off'],
tx_osnr=part['tx_osnr'], label=part['label'])
previous_part_max_freq = current_freq + part['slot_width'] / 2
return spectrum
def load_equipment(filename): def load_equipment(filename):
json_data = load_json(filename) json_data = load_json(filename)
return _equipment_from_json(json_data, filename) return _equipment_from_json(json_data, filename)
def load_initial_spectrum(filename):
json_data = load_json(filename)
return _spectrum_from_json(json_data['spectrum'])
def _update_dual_stage(equipment): def _update_dual_stage(equipment):
edfa_dict = equipment['Edfa'] edfa_dict = equipment['Edfa']
for edfa in edfa_dict.values(): for edfa in edfa_dict.values():
@@ -274,9 +388,7 @@ def _update_dual_stage(equipment):
def _roadm_restrictions_sanity_check(equipment): def _roadm_restrictions_sanity_check(equipment):
""" verifies that booster and preamp restrictions specified in roadm equipment are listed """verifies that booster and preamp restrictions specified in roadm equipment are listed in the edfa."""
in the edfa.
"""
restrictions = equipment['Roadm']['default'].restrictions['booster_variety_list'] + \ restrictions = equipment['Roadm']['default'].restrictions['booster_variety_list'] + \
equipment['Roadm']['default'].restrictions['preamp_variety_list'] equipment['Roadm']['default'].restrictions['preamp_variety_list']
for amp_name in restrictions: for amp_name in restrictions:
@@ -346,11 +458,11 @@ def load_network(filename, equipment):
def save_network(network: DiGraph, filename: str): def save_network(network: DiGraph, filename: str):
'''Dump the network into a JSON file """Dump the network into a JSON file
:param network: network to work on :param network: network to work on
:param filename: file to write to :param filename: file to write to
''' """
save_json(network_to_json(network), filename) save_json(network_to_json(network), filename)
@@ -384,14 +496,28 @@ def network_from_json(json_data, equipment):
# well, there's no variety for the 'Fused' node type # well, there's no variety for the 'Fused' node type
pass pass
elif variety in equipment[typ]: elif variety in equipment[typ]:
extra_params = equipment[typ][variety] extra_params = equipment[typ][variety].__dict__
temp = el_config.setdefault('params', {}) temp = el_config.setdefault('params', {})
temp = merge_amplifier_restrictions(temp, extra_params.__dict__) if typ == 'Roadm':
# if equalization is defined, remove default equalization from the extra_params
# If equalisation is not defined in the element config, then use the default one from equipment
# if more than one equalization was defined in element config, then raise an error
extra_params = merge_equalization(temp, extra_params)
if not extra_params:
msg = f'ROADM {el_config["uid"]}: invalid equalization settings'
raise ConfigurationError(msg)
temp = merge_amplifier_restrictions(temp, extra_params)
el_config['params'] = temp el_config['params'] = temp
el_config['type_variety'] = variety el_config['type_variety'] = variety
elif (typ in ['Fiber', 'RamanFiber']) or (typ == 'Edfa' and variety not in ['default', '']): elif (typ in ['Fiber', 'RamanFiber']):
raise ConfigurationError(f'The {typ} of variety type {variety} was not recognized:' raise ConfigurationError(f'The {typ} of variety type {variety} was not recognized:'
'\nplease check it is properly defined in the eqpt_config json file') '\nplease check it is properly defined in the eqpt_config json file')
elif typ == 'Edfa':
if variety in ['default', '']:
el_config['params'] = Amp.default_values
else:
raise ConfigurationError(f'The Edfa of variety type {variety} was not recognized:'
'\nplease check it is properly defined in the eqpt_config json file')
el = cls(**el_config) el = cls(**el_config)
g.add_node(el) g.add_node(el)
@@ -406,7 +532,8 @@ def network_from_json(json_data, equipment):
edge_length = 0.01 edge_length = 0.01
g.add_edge(nodes[from_node], nodes[to_node], weight=edge_length) g.add_edge(nodes[from_node], nodes[to_node], weight=edge_length)
except KeyError: except KeyError:
raise NetworkTopologyError(f'can not find {from_node} or {to_node} defined in {cx}') msg = f'can not find {from_node} or {to_node} defined in {cx}'
raise NetworkTopologyError(msg)
return g return g
@@ -437,15 +564,13 @@ def save_json(obj, filename):
def load_requests(filename, eqpt, bidir, network, network_filename): def load_requests(filename, eqpt, bidir, network, network_filename):
""" loads the requests from a json or an excel file into a data string """loads the requests from a json or an excel file into a data string"""
"""
if filename.suffix.lower() in ('.xls', '.xlsx'): if filename.suffix.lower() in ('.xls', '.xlsx'):
_logger.info('Automatically converting requests from XLS to JSON') _logger.info('Automatically converting requests from XLS to JSON')
try: try:
return convert_service_sheet(filename, eqpt, network, network_filename=network_filename, bidir=bidir) return convert_service_sheet(filename, eqpt, network, network_filename=network_filename, bidir=bidir)
except ServiceError as this_e: except ServiceError as this_e:
print(f'{ansi_escapes.red}Service error:{ansi_escapes.reset} {this_e}') raise ServiceError(f'Service error: {this_e}')
exit(1)
else: else:
return load_json(filename) return load_json(filename)
@@ -457,16 +582,19 @@ def requests_from_json(json_data, equipment):
for req in json_data['path-request']: for req in json_data['path-request']:
# init all params from request # init all params from request
params = {} params = {}
params['request_id'] = req['request-id'] params['request_id'] = f'{req["request-id"]}'
params['source'] = req['source'] params['source'] = req['source']
params['bidir'] = req['bidirectional'] params['bidir'] = req['bidirectional']
params['destination'] = req['destination'] params['destination'] = req['destination']
params['trx_type'] = req['path-constraints']['te-bandwidth']['trx_type'] params['trx_type'] = req['path-constraints']['te-bandwidth']['trx_type']
params['trx_mode'] = req['path-constraints']['te-bandwidth']['trx_mode'] if params['trx_type'] is None:
msg = f'Request {req["request-id"]} has no transceiver type defined.'
raise ServiceError(msg)
params['trx_mode'] = req['path-constraints']['te-bandwidth'].get('trx_mode', None)
params['format'] = params['trx_mode'] params['format'] = params['trx_mode']
params['spacing'] = req['path-constraints']['te-bandwidth']['spacing'] params['spacing'] = req['path-constraints']['te-bandwidth']['spacing']
try: try:
nd_list = req['explicit-route-objects']['route-object-include-exclude'] nd_list = sorted(req['explicit-route-objects']['route-object-include-exclude'], key=lambda x: x['index'])
except KeyError: except KeyError:
nd_list = [] nd_list = []
params['nodes_list'] = [n['num-unnum-hop']['node-id'] for n in nd_list] params['nodes_list'] = [n['num-unnum-hop']['node-id'] for n in nd_list]
@@ -474,9 +602,12 @@ def requests_from_json(json_data, equipment):
# recover trx physical param (baudrate, ...) from type and mode # recover trx physical param (baudrate, ...) from type and mode
# in trx_mode_params optical power is read from equipment['SI']['default'] and # in trx_mode_params optical power is read from equipment['SI']['default'] and
# nb_channel is computed based on min max frequency and spacing # nb_channel is computed based on min max frequency and spacing
trx_params = trx_mode_params(equipment, params['trx_type'], params['trx_mode'], True) try:
trx_params = trx_mode_params(equipment, params['trx_type'], params['trx_mode'], True)
except EquipmentConfigError as e:
msg = f'Equipment Config error in {req["request-id"]}: {e}'
raise EquipmentConfigError(msg) from e
params.update(trx_params) params.update(trx_params)
# print(trx_params['min_spacing'])
# optical power might be set differently in the request. if it is indicated then the # optical power might be set differently in the request. if it is indicated then the
# params['power'] is updated # params['power'] is updated
try: try:
@@ -497,7 +628,8 @@ def requests_from_json(json_data, equipment):
params['nb_channel'] = automatic_nch(f_min, f_max_from_si, params['spacing']) params['nb_channel'] = automatic_nch(f_min, f_max_from_si, params['spacing'])
except KeyError: except KeyError:
params['nb_channel'] = automatic_nch(f_min, f_max_from_si, params['spacing']) params['nb_channel'] = automatic_nch(f_min, f_max_from_si, params['spacing'])
params['effective_freq_slot'] = req['path-constraints']['te-bandwidth'].get('effective-freq-slot', [None])[0] params['effective_freq_slot'] = \
req['path-constraints']['te-bandwidth'].get('effective-freq-slot', [{'N': None, 'M': None}])
try: try:
params['path_bandwidth'] = req['path-constraints']['te-bandwidth']['path_bandwidth'] params['path_bandwidth'] = req['path-constraints']['te-bandwidth']['path_bandwidth']
except KeyError: except KeyError:
@@ -511,44 +643,66 @@ def _check_one_request(params, f_max_from_si):
"""Checks that the requested parameters are consistant (spacing vs nb channel vs transponder mode...)""" """Checks that the requested parameters are consistant (spacing vs nb channel vs transponder mode...)"""
f_min = params['f_min'] f_min = params['f_min']
f_max = params['f_max'] f_max = params['f_max']
max_recommanded_nb_channels = automatic_nch(f_min, f_max, params['spacing']) max_recommanded_nb_channels = automatic_nch(f_min, f_max_from_si, params['spacing'])
if params['baud_rate'] is not None: if params['baud_rate'] is not None:
# implicitly means that a mode is defined with min_spacing # implicitly means that a mode is defined with min_spacing
if params['min_spacing'] > params['spacing']: if params['min_spacing'] > params['spacing']:
msg = f'Request {params["request_id"]} has spacing below transponder ' +\ msg = f'Request {params["request_id"]} has spacing below transponder ' +\
f'{params["trx_type"]} {params["trx_mode"]} min spacing value ' +\ f'{params["trx_type"]} {params["trx_mode"]} min spacing value ' +\
f'{params["min_spacing"]*1e-9}GHz.\nComputation stopped' f'{params["min_spacing"]*1e-9}GHz.\nComputation stopped'
print(msg)
_logger.critical(msg)
raise ServiceError(msg) raise ServiceError(msg)
if f_max > f_max_from_si: if f_max > f_max_from_si:
msg = f'''Requested channel number {params["nb_channel"]}, baud rate {params["baud_rate"]} GHz msg = f'Requested channel number {params["nb_channel"]}, baud rate {params["baud_rate"] * 1e-9} GHz' \
and requested spacing {params["spacing"]*1e-9}GHz is not consistent with frequency range + f' and requested spacing {params["spacing"]*1e-9}GHz is not consistent with frequency range' \
{f_min*1e-12} THz, {f_max*1e-12} THz, min recommanded spacing {params["min_spacing"]*1e-9}GHz. + f' {f_min*1e-12} THz, {f_max_from_si*1e-12} THz.' \
max recommanded nb of channels is {max_recommanded_nb_channels}.''' + f' Max recommanded nb of channels is {max_recommanded_nb_channels}.'
_logger.critical(msg)
raise ServiceError(msg) raise ServiceError(msg)
# Transponder mode already selected; will it fit to the requested bandwidth? # Transponder mode already selected; will it fit to the requested bandwidth?
if params['trx_mode'] is not None and params['effective_freq_slot'] is not None \ if params['trx_mode'] is not None and params['effective_freq_slot'] is not None:
and params['effective_freq_slot']['M'] is not None: required_nb_of_channels, requested_m = compute_spectrum_slot_vs_bandwidth(params['path_bandwidth'],
_, requested_m = compute_spectrum_slot_vs_bandwidth(params['path_bandwidth'], params['spacing'],
params['spacing'], params['bit_rate'])
params['bit_rate']) _, per_channel_m = compute_spectrum_slot_vs_bandwidth(params['bit_rate'],
# params['effective_freq_slot']['M'] value should be bigger than the computed requested_m (simple estimate) params['spacing'],
params['bit_rate'])
# each M should fit one or more channels if it is not None
# spectrum slots should not overlap
# resulting nb of channels should be bigger than the nb computed with path_bandwidth
# without being splitted
# TODO: elaborate a more accurate estimate with nb_wl * tx_osnr + possibly guardbands in case of # TODO: elaborate a more accurate estimate with nb_wl * tx_osnr + possibly guardbands in case of
# superchannel closed packing. # superchannel closed packing.
nb_of_channels = 0
if requested_m > params['effective_freq_slot']['M']: # order slots
msg = f'requested M {params["effective_freq_slot"]["M"]} number of slots for request' +\ slots = sorted(params['effective_freq_slot'], key=lambda x: float('inf') if x['N'] is None else x['N'])
f'{params["request_id"]} should be greater than {requested_m} to support request' +\ for slot in slots:
f'{params["path_bandwidth"] * 1e-9} Gbit/s with {params["trx_type"]} {params["trx_mode"]}' nb_of_channels = nb_of_channels + slot['M'] // per_channel_m if slot['M'] is not None \
_logger.critical(msg) and nb_of_channels is not None else None
if slot['M'] is not None and slot['M'] < per_channel_m:
msg = f'Requested M {slot} number of slots for request' +\
f' {params["request_id"]} should be greater than {per_channel_m} to support request' +\
f'with {params["trx_type"]} {params["trx_mode"]}'
_logger.critical(msg)
if nb_of_channels is not None and nb_of_channels < required_nb_of_channels:
msg = f'Requested M {slots} number of slots for request {params["request_id"]} support {nb_of_channels}' +\
f' nb of channels while {required_nb_of_channels} are required to support request' +\
f' {params["path_bandwidth"] * 1e-9} Gbit/s with {params["trx_type"]} {params["trx_mode"]}'
raise ServiceError(msg) raise ServiceError(msg)
if nb_of_channels is not None:
_, stop0n = mvalue_to_slots(slots[0]['N'], slots[0]['M'])
i = 1
while i < len(slots):
slot = slots[i]
startn, stopn = mvalue_to_slots(slot['N'], slot['M'])
if startn <= stop0n:
msg = f'Requested M {slots} for request {params["request_id"]} overlap'
raise ServiceError(msg)
_, stop0n = startn, stopn
i += 1
def disjunctions_from_json(json_data): def disjunctions_from_json(json_data):
""" reads the disjunction requests from the json dict and create the list """reads the disjunction requests from the json dict and create the list
of requested disjunctions for this set of requests of requested disjunctions for this set of requests
""" """
disjunctions_list = [] disjunctions_list = []
if 'synchronization' in json_data: if 'synchronization' in json_data:
@@ -576,3 +730,42 @@ def convert_service_sheet(
data = read_service_sheet(input_filename, eqpt, network, network_filename, bidir) data = read_service_sheet(input_filename, eqpt, network, network_filename, bidir)
save_json(data, output_filename) save_json(data, output_filename)
return data return data
def find_equalisation(params, equalization_types):
"""Find the equalization(s) defined in params. params can be a dict or a Roadm object.
>>> roadm = {'add_drop_osnr': 100, 'pmd': 1, 'pdl': 0.5,
... 'restrictions': {'preamp_variety_list': ['a'], 'booster_variety_list': ['b']},
... 'target_psd_out_mWperGHz': 4e-4}
>>> equalization_types = ['target_pch_out_db', 'target_psd_out_mWperGHz']
>>> find_equalisation(roadm, equalization_types)
{'target_pch_out_db': False, 'target_psd_out_mWperGHz': True}
"""
equalization = {e: False for e in equalization_types}
for equ in equalization_types:
if equ in params:
equalization[equ] = True
return equalization
def merge_equalization(params, extra_params):
"""params contains ROADM element config and extra_params default values from equipment library.
If equalization is not defined in ROADM element use the one defined in equipment library.
Only one type of equalization must be defined: power (target_pch_out_db) or PSD (target_psd_out_mWperGHz)
or PSW (target_out_mWperSlotWidth)
params and extra_params are dict
"""
equalization_types = ['target_pch_out_db', 'target_psd_out_mWperGHz', 'target_out_mWperSlotWidth']
roadm_equalizations = find_equalisation(params, equalization_types)
if sum(roadm_equalizations.values()) > 1:
# if ROADM config contains more than one equalization type then this is an error
return None
if sum(roadm_equalizations.values()) == 1:
# if ROADM config contains one equalization
# don't use the default equalization
return {k: v for k, v in extra_params.items() if k not in equalization_types}
if sum(roadm_equalizations.values()) == 0:
# If ROADM config doesn't contain any equalization type, keep the default one
return extra_params
return None

View File

@@ -1,12 +1,12 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
''' """
gnpy.tools.plots gnpy.tools.plots
================ ================
Graphs and plots usable from a CLI application Graphs and plots usable from a CLI application
''' """
from matplotlib.pyplot import show, axis, figure, title, text from matplotlib.pyplot import show, axis, figure, title, text
from networkx import draw_networkx from networkx import draw_networkx

View File

@@ -18,7 +18,6 @@ from copy import deepcopy
from gnpy.core.utils import db2lin from gnpy.core.utils import db2lin
from gnpy.core.exceptions import ServiceError from gnpy.core.exceptions import ServiceError
from gnpy.core.elements import Transceiver, Roadm, Edfa, Fiber from gnpy.core.elements import Transceiver, Roadm, Edfa, Fiber
import gnpy.core.ansi_escapes as ansi_escapes
from gnpy.tools.convert import corresp_names, corresp_next_node from gnpy.tools.convert import corresp_names, corresp_next_node
SERVICES_COLUMN = 12 SERVICES_COLUMN = 12
@@ -68,24 +67,21 @@ class Request_element(Element):
if [mode for mode in equipment['Transceiver'][Request.trx_type].mode if mode['format'] == Requestmode]: if [mode for mode in equipment['Transceiver'][Request.trx_type].mode if mode['format'] == Requestmode]:
self.mode = Requestmode self.mode = Requestmode
else: else:
msg = f'Request Id: {self.request_id} - could not find tsp : \'{Request.trx_type}\' with mode: \'{Requestmode}\' in eqpt library \nComputation stopped.' msg = f'Request Id: {self.request_id} - could not find tsp : \'{Request.trx_type}\' ' \
# print(msg) + f'with mode: \'{Requestmode}\' in eqpt library \nComputation stopped.'
logger.critical(msg)
raise ServiceError(msg) raise ServiceError(msg)
else: else:
Requestmode = None Requestmode = None
self.mode = Request.mode self.mode = Request.mode
except KeyError: except KeyError:
msg = f'Request Id: {self.request_id} - could not find tsp : \'{Request.trx_type}\' with mode: \'{Request.mode}\' in eqpt library \nComputation stopped.' msg = f'Request Id: {self.request_id} - could not find tsp : \'{Request.trx_type}\' ' \
# print(msg) + f'with mode: \'{Request.mode}\' in eqpt library \nComputation stopped.'
logger.critical(msg)
raise ServiceError(msg) raise ServiceError(msg)
# excel input are in GHz and dBm # excel input are in GHz and dBm
if Request.spacing is not None: if Request.spacing is not None:
self.spacing = Request.spacing * 1e9 self.spacing = Request.spacing * 1e9
else: else:
msg = f'Request {self.request_id} missing spacing: spacing is mandatory.\ncomputation stopped' msg = f'Request {self.request_id} missing spacing: spacing is mandatory.\ncomputation stopped'
logger.critical(msg)
raise ServiceError(msg) raise ServiceError(msg)
if Request.power is not None: if Request.power is not None:
self.power = db2lin(Request.power) * 1e-3 self.power = db2lin(Request.power) * 1e-3
@@ -225,7 +221,7 @@ def parse_excel(input_filename):
def parse_service_sheet(service_sheet): def parse_service_sheet(service_sheet):
""" reads each column according to authorized fieldnames. order is not important. """ reads each column according to authorized fieldnames. order is not important.
""" """
logger.info(f'Validating headers on {service_sheet.name!r}') logger.debug(f'Validating headers on {service_sheet.name!r}')
# add a test on field to enable the '' field case that arises when columns on the # add a test on field to enable the '' field case that arises when columns on the
# right hand side are used as comments or drawing in the excel sheet # right hand side are used as comments or drawing in the excel sheet
header = [x.value.strip() for x in service_sheet.row(4)[0:SERVICES_COLUMN] header = [x.value.strip() for x in service_sheet.row(4)[0:SERVICES_COLUMN]
@@ -245,7 +241,6 @@ def parse_service_sheet(service_sheet):
service_fieldnames = [authorized_fieldnames[e] for e in header] service_fieldnames = [authorized_fieldnames[e] for e in header]
except KeyError: except KeyError:
msg = f'Malformed header on Service sheet: {header} field not in {authorized_fieldnames}' msg = f'Malformed header on Service sheet: {header} field not in {authorized_fieldnames}'
logger.critical(msg)
raise ValueError(msg) raise ValueError(msg)
for row in all_rows(service_sheet, start=5): for row in all_rows(service_sheet, start=5):
yield Request(**parse_row(row[0:SERVICES_COLUMN], service_fieldnames)) yield Request(**parse_row(row[0:SERVICES_COLUMN], service_fieldnames))
@@ -273,15 +268,13 @@ def correct_xls_route_list(network_filename, network, pathreqlist):
for pathreq in pathreqlist: for pathreq in pathreqlist:
# first check that source and dest are transceivers # first check that source and dest are transceivers
if pathreq.source not in transponders: if pathreq.source not in transponders:
msg = f'{ansi_escapes.red}Request: {pathreq.request_id}: could not find' +\ msg = f'Request: {pathreq.request_id}: could not find' +\
f' transponder source : {pathreq.source}.{ansi_escapes.reset}' f' transponder source : {pathreq.source}.'
logger.critical(msg)
raise ServiceError(msg) raise ServiceError(msg)
if pathreq.destination not in transponders: if pathreq.destination not in transponders:
msg = f'{ansi_escapes.red}Request: {pathreq.request_id}: could not find' +\ msg = f'Request: {pathreq.request_id}: could not find' +\
f' transponder destination: {pathreq.destination}.{ansi_escapes.reset}' f' transponder destination: {pathreq.destination}.'
logger.critical(msg)
raise ServiceError(msg) raise ServiceError(msg)
# silently pop source and dest nodes from the list if they were added by the user as first # silently pop source and dest nodes from the list if they were added by the user as first
# and last elem in the constraints respectively. Other positions must lead to an error # and last elem in the constraints respectively. Other positions must lead to an error
@@ -333,17 +326,16 @@ def correct_xls_route_list(network_filename, network, pathreqlist):
# too much ambiguity, 'b' is an ila, its name can be: # too much ambiguity, 'b' is an ila, its name can be:
# Edfa0_fiber (a → b)-xx if next node is c or # Edfa0_fiber (a → b)-xx if next node is c or
# Edfa0_fiber (c → b)-xx if next node is a # Edfa0_fiber (c → b)-xx if next node is a
msg = f'{ansi_escapes.yellow}Invalid route node specified:' +\ msg = f'Request {pathreq.request_id}: Invalid route node specified:' \
f'\n\t\'{n_id}\', replaced with \'{new_n}\'{ansi_escapes.reset}' + f'\n\t\'{n_id}\', replaced with \'{new_n}\''
logger.info(msg) logger.warning(msg)
pathreq.nodes_list[pathreq.nodes_list.index(n_id)] = new_n pathreq.nodes_list[pathreq.nodes_list.index(n_id)] = new_n
except StopIteration: except StopIteration:
# shall not come in this case, unless requested direction does not exist # shall not come in this case, unless requested direction does not exist
msg = f'{ansi_escapes.yellow}Invalid route specified {n_id}: could' +\ msg = f'Request {pathreq.request_id}: Invalid route specified {n_id}: could' \
f' not decide on direction, skipped!.\nPlease add a valid' +\ + ' not decide on direction, skipped!.\nPlease add a valid' \
f' direction in constraints (next neighbour node){ansi_escapes.reset}' + ' direction in constraints (next neighbour node)'
print(msg) logger.warning(msg)
logger.info(msg)
pathreq.loose_list.pop(pathreq.nodes_list.index(n_id)) pathreq.loose_list.pop(pathreq.nodes_list.index(n_id))
pathreq.nodes_list.remove(n_id) pathreq.nodes_list.remove(n_id)
else: else:
@@ -351,28 +343,24 @@ def correct_xls_route_list(network_filename, network, pathreqlist):
# if no matching can be found in the network just ignore this constraint # if no matching can be found in the network just ignore this constraint
# if it is a loose constraint # if it is a loose constraint
# warns the user that this node is not part of the topology # warns the user that this node is not part of the topology
msg = f'{ansi_escapes.yellow}Invalid node specified:\n\t\'{n_id}\'' +\ msg = f'Request {pathreq.request_id}: Invalid node specified:\n\t\'{n_id}\'' \
f', could not use it as constraint, skipped!{ansi_escapes.reset}' + ', could not use it as constraint, skipped!'
print(msg) logger.warning(msg)
logger.info(msg)
pathreq.loose_list.pop(pathreq.nodes_list.index(n_id)) pathreq.loose_list.pop(pathreq.nodes_list.index(n_id))
pathreq.nodes_list.remove(n_id) pathreq.nodes_list.remove(n_id)
else: else:
msg = f'{ansi_escapes.red}Could not find node:\n\t\'{n_id}\' in network' +\ msg = f'Request {pathreq.request_id}: Could not find node:\n\t\'{n_id}\' in network' \
f' topology. Strict constraint can not be applied.{ansi_escapes.reset}' + ' topology. Strict constraint can not be applied.'
logger.critical(msg)
raise ServiceError(msg) raise ServiceError(msg)
else: else:
if temp.loose_list[i] == 'LOOSE': if temp.loose_list[i] == 'LOOSE':
print(f'{ansi_escapes.yellow}Invalid route node specified:\n\t\'{n_id}\'' + logger.warning(f'Request {pathreq.request_id}: Invalid route node specified:\n\t\'{n_id}\''
f' type is not supported as constraint with xls network input,' + + ' type is not supported as constraint with xls network input, skipped!')
f' skipped!{ansi_escapes.reset}')
pathreq.loose_list.pop(pathreq.nodes_list.index(n_id)) pathreq.loose_list.pop(pathreq.nodes_list.index(n_id))
pathreq.nodes_list.remove(n_id) pathreq.nodes_list.remove(n_id)
else: else:
msg = f'{ansi_escapes.red}Invalid route node specified \n\t\'{n_id}\'' +\ msg = f'Invalid route node specified \n\t\'{n_id}\'' \
f' type is not supported as constraint with xls network input,' +\ + ' type is not supported as constraint with xls network input,' \
f', Strict constraint can not be applied.{ansi_escapes.reset}' + ', Strict constraint can not be applied.'
logger.critical(msg)
raise ServiceError(msg) raise ServiceError(msg)
return pathreqlist return pathreqlist

View File

@@ -1,3 +1,3 @@
''' """
Tracking :py:mod:`.request` for spectrum and their :py:mod:`.spectrum_assignment`. Tracking :py:mod:`.request` for spectrum and their :py:mod:`.spectrum_assignment`.
''' """

View File

@@ -23,9 +23,8 @@ from networkx.utils import pairwise
from numpy import mean, argmin from numpy import mean, argmin
from gnpy.core.elements import Transceiver, Roadm from gnpy.core.elements import Transceiver, Roadm
from gnpy.core.utils import lin2db from gnpy.core.utils import lin2db
from gnpy.core.info import create_input_spectral_information from gnpy.core.info import create_input_spectral_information, carriers_to_spectral_information, ReferenceCarrier
from gnpy.core.exceptions import ServiceError, DisjunctionError from gnpy.core.exceptions import ServiceError, DisjunctionError
import gnpy.core.ansi_escapes as ansi_escapes
from copy import deepcopy from copy import deepcopy
from csv import writer from csv import writer
from math import ceil from math import ceil
@@ -35,15 +34,14 @@ LOGGER = getLogger(__name__)
RequestParams = namedtuple('RequestParams', 'request_id source destination bidir trx_type' RequestParams = namedtuple('RequestParams', 'request_id source destination bidir trx_type'
' trx_mode nodes_list loose_list spacing power nb_channel f_min' ' trx_mode nodes_list loose_list spacing power nb_channel f_min'
' f_max format baud_rate OSNR penalties bit_rate' ' f_max format baud_rate OSNR penalties bit_rate'
' roll_off tx_osnr min_spacing cost path_bandwidth effective_freq_slot') ' roll_off tx_osnr min_spacing cost path_bandwidth effective_freq_slot'
' equalization_offset_db')
DisjunctionParams = namedtuple('DisjunctionParams', 'disjunction_id relaxable link_diverse' DisjunctionParams = namedtuple('DisjunctionParams', 'disjunction_id relaxable link_diverse'
' node_diverse disjunctions_req') ' node_diverse disjunctions_req')
class PathRequest: class PathRequest:
""" the class that contains all attributes related to a request """the class that contains all attributes related to a request"""
"""
def __init__(self, *args, **params): def __init__(self, *args, **params):
params = RequestParams(**params) params = RequestParams(**params)
self.request_id = params.request_id self.request_id = params.request_id
@@ -70,8 +68,10 @@ class PathRequest:
self.cost = params.cost self.cost = params.cost
self.path_bandwidth = params.path_bandwidth self.path_bandwidth = params.path_bandwidth
if params.effective_freq_slot is not None: if params.effective_freq_slot is not None:
self.N = params.effective_freq_slot['N'] self.N = [s['N'] for s in params.effective_freq_slot]
self.M = params.effective_freq_slot['M'] self.M = [s['M'] for s in params.effective_freq_slot]
self.initial_spectrum = None
self.offset_db = params.equalization_offset_db
def __str__(self): def __str__(self):
return '\n\t'.join([f'{type(self).__name__} {self.request_id}', return '\n\t'.join([f'{type(self).__name__} {self.request_id}',
@@ -103,8 +103,7 @@ class PathRequest:
class Disjunction: class Disjunction:
""" the class that contains all attributes related to disjunction constraints """the class that contains all attributes related to disjunction constraints"""
"""
def __init__(self, *args, **params): def __init__(self, *args, **params):
params = DisjunctionParams(**params) params = DisjunctionParams(**params)
@@ -149,8 +148,7 @@ class ResultElement:
@property @property
def detailed_path_json(self): def detailed_path_json(self):
""" a function that builds path object for normal and blocking cases """a function that builds path object for normal and blocking cases"""
"""
index = 0 index = 0
pro_list = [] pro_list = []
for element in self.computed_path: for element in self.computed_path:
@@ -174,10 +172,10 @@ class ResultElement:
temp = { temp = {
'path-route-object': { 'path-route-object': {
'index': index, 'index': index,
"label-hop": { "label-hop": [{
"N": self.path_request.N, "N": n,
"M": self.path_request.M "M": m
}, } for n, m in zip(self.path_request.N, self.path_request.M)],
} }
} }
pro_list.append(temp) pro_list.append(temp)
@@ -206,11 +204,9 @@ class ResultElement:
@property @property
def path_properties(self): def path_properties(self):
""" a function that returns the path properties (metrics, crossed elements) into a dict """a function that returns the path properties (metrics, crossed elements) into a dict"""
"""
def path_metric(pth, req): def path_metric(pth, req):
""" creates the metrics dictionary """creates the metrics dictionary"""
"""
return [ return [
{ {
'metric-type': 'SNR-bandwidth', 'metric-type': 'SNR-bandwidth',
@@ -252,8 +248,7 @@ class ResultElement:
@property @property
def pathresult(self): def pathresult(self):
""" create the result dictionnary (response for a request) """create the result dictionnary (response for a request)"""
"""
try: try:
if self.path_request.blocking_reason in BLOCKING_NOPATH: if self.path_request.blocking_reason in BLOCKING_NOPATH:
response = { response = {
@@ -291,7 +286,6 @@ def compute_constrained_path(network, req):
# been corrected and harmonized before # been corrected and harmonized before
msg = (f'Request {req.request_id} malformed list of nodes: last node should ' msg = (f'Request {req.request_id} malformed list of nodes: last node should '
'be destination trx') 'be destination trx')
LOGGER.critical(msg)
raise ValueError() raise ValueError()
trx = [n for n in network if isinstance(n, Transceiver)] trx = [n for n in network if isinstance(n, Transceiver)]
@@ -306,10 +300,9 @@ def compute_constrained_path(network, req):
path_generator = shortest_simple_paths(network, source, destination, weight='weight') path_generator = shortest_simple_paths(network, source, destination, weight='weight')
total_path = next(path for path in path_generator if ispart(nodes_list, path)) total_path = next(path for path in path_generator if ispart(nodes_list, path))
except NetworkXNoPath: except NetworkXNoPath:
msg = (f'{ansi_escapes.yellow}Request {req.request_id} could not find a path from' msg = (f'Request {req.request_id} could not find a path from'
f' {source.uid} to node: {destination.uid} in network topology{ansi_escapes.reset}') f' {source.uid} to node: {destination.uid} in network topology')
LOGGER.critical(msg) LOGGER.critical(msg)
print(msg)
req.blocking_reason = 'NO_PATH' req.blocking_reason = 'NO_PATH'
total_path = [] total_path = []
except StopIteration: except StopIteration:
@@ -318,69 +311,88 @@ def compute_constrained_path(network, req):
# last node which is the transceiver) # last node which is the transceiver)
# if all nodes i n node_list are LOOSE constraint, skip the constraints and find # if all nodes i n node_list are LOOSE constraint, skip the constraints and find
# a path w/o constraints, else there is no possible path # a path w/o constraints, else there is no possible path
print(f'{ansi_escapes.yellow}Request {req.request_id} could not find a path crossing ' LOGGER.warning(f'Request {req.request_id} could not find a path crossing '
f'{[el.uid for el in nodes_list[:-1]]} in network topology{ansi_escapes.reset}') f'{[el.uid for el in nodes_list[:-1]]} in network topology')
if 'STRICT' not in req.loose_list[:-1]: if 'STRICT' not in req.loose_list[:-1]:
msg = (f'{ansi_escapes.yellow}Request {req.request_id} could not find a path with user_' msg = (f'Request {req.request_id} could not find a path with user_'
f'include node constraints{ansi_escapes.reset}') f'include node constraints. Constraint ignored')
LOGGER.info(msg) LOGGER.warning(msg)
print(f'constraint ignored')
total_path = dijkstra_path(network, source, destination, weight='weight') total_path = dijkstra_path(network, source, destination, weight='weight')
else: else:
# one STRICT makes the whole list STRICT # one STRICT makes the whole list STRICT
msg = (f'{ansi_escapes.yellow}Request {req.request_id} could not find a path with user ' msg = (f'Request {req.request_id} could not find a path with user '
f'include node constraints.\nNo path computed{ansi_escapes.reset}') f'include node constraints.\nNo path computed')
LOGGER.critical(msg) LOGGER.critical(msg)
print(msg)
req.blocking_reason = 'NO_PATH_WITH_CONSTRAINT' req.blocking_reason = 'NO_PATH_WITH_CONSTRAINT'
total_path = [] total_path = []
return total_path return total_path
def ref_carrier(equipment):
"""Create a reference carier based SI information with the specified request's power:
req_power records the power in W that the user has defined for a given request
(which might be different from the one used for the design).
"""
return ReferenceCarrier(baud_rate=equipment['SI']['default'].baud_rate,
slot_width=equipment['SI']['default'].spacing)
def propagate(path, req, equipment): def propagate(path, req, equipment):
si = create_input_spectral_information( """propagates signals in each element according to initial spectrum set by user"""
req.f_min, req.f_max, req.roll_off, req.baud_rate, if req.initial_spectrum is not None:
req.power, req.spacing) si = carriers_to_spectral_information(initial_spectrum=req.initial_spectrum,
power=req.power, ref_carrier=ref_carrier(equipment))
else:
si = create_input_spectral_information(
f_min=req.f_min, f_max=req.f_max, roll_off=req.roll_off, baud_rate=req.baud_rate,
power=req.power, spacing=req.spacing, tx_osnr=req.tx_osnr, delta_pdb=req.offset_db,
ref_carrier=ref_carrier(equipment))
for i, el in enumerate(path): for i, el in enumerate(path):
if isinstance(el, Roadm): if isinstance(el, Roadm):
si = el(si, degree=path[i+1].uid) si = el(si, degree=path[i+1].uid)
else: else:
si = el(si) si = el(si)
path[0].update_snr(req.tx_osnr) path[0].update_snr(si.tx_osnr)
path[0].calc_penalties(req.penalties) path[0].calc_penalties(req.penalties)
if any(isinstance(el, Roadm) for el in path): if any(isinstance(el, Roadm) for el in path):
path[-1].update_snr(req.tx_osnr, equipment['Roadm']['default'].add_drop_osnr) path[-1].update_snr(si.tx_osnr, equipment['Roadm']['default'].add_drop_osnr)
else: else:
path[-1].update_snr(req.tx_osnr) path[-1].update_snr(si.tx_osnr)
path[-1].calc_penalties(req.penalties) path[-1].calc_penalties(req.penalties)
return si return si
def propagate_and_optimize_mode(path, req, equipment): def propagate_and_optimize_mode(path, req, equipment):
# if mode is unknown : loops on the modes starting from the highest baudrate fiting in the # if mode is unknown : loops on the modes starting from the highest baudrate fiting in the
# step 1: create an ordered list of modes based on baudrate # step 1: create an ordered list of modes based on baudrate and power offset
baudrate_to_explore = list(set([this_mode['baud_rate'] # order higher baudrate with higher power offset first
for this_mode in equipment['Transceiver'][req.tsp].mode baudrate_offset_to_explore = list(set([(this_mode['baud_rate'], this_mode['equalization_offset_db'])
if float(this_mode['min_spacing']) <= req.spacing])) for this_mode in equipment['Transceiver'][req.tsp].mode
if float(this_mode['min_spacing']) <= req.spacing]))
# TODO be carefull on limits cases if spacing very close to req spacing eg 50.001 50.000 # TODO be carefull on limits cases if spacing very close to req spacing eg 50.001 50.000
baudrate_to_explore = sorted(baudrate_to_explore, reverse=True) baudrate_offset_to_explore = sorted(baudrate_offset_to_explore, reverse=True)
if baudrate_to_explore: if baudrate_offset_to_explore:
# at least 1 baudrate can be tested wrt spacing # at least 1 baudrate can be tested wrt spacing
for this_br in baudrate_to_explore: for (this_br, this_offset) in baudrate_offset_to_explore:
modes_to_explore = [this_mode for this_mode in equipment['Transceiver'][req.tsp].mode modes_to_explore = [this_mode for this_mode in equipment['Transceiver'][req.tsp].mode
if this_mode['baud_rate'] == this_br and if this_mode['baud_rate'] == this_br
float(this_mode['min_spacing']) <= req.spacing] and float(this_mode['min_spacing']) <= req.spacing]
modes_to_explore = sorted(modes_to_explore, modes_to_explore = sorted(modes_to_explore,
key=lambda x: x['bit_rate'], reverse=True) key=lambda x: (x['bit_rate'], x['equalization_offset_db']), reverse=True)
# print(modes_to_explore)
# step2: computes propagation for each baudrate: stop and select the first that passes # step2: computes propagation for each baudrate: stop and select the first that passes
# TODO: the case of roll of is not included: for now use SI one # TODO: the case of roll off is not included: for now use SI one
# TODO: if the loop in mode optimization does not have a feasible path, then bugs # TODO: if the loop in mode optimization does not have a feasible path, then bugs
spc_info = create_input_spectral_information(req.f_min, req.f_max, if req.initial_spectrum is not None:
equipment['SI']['default'].roll_off, # this case is not yet handled: spectrum can not be defined for the path-request-run function
this_br, req.power, req.spacing) # and this function is only called in this case. so coming here should not be considered yet.
msg = f'Request: {req.request_id} contains a unexpected initial_spectrum.'
raise ServiceError(msg)
spc_info = create_input_spectral_information(f_min=req.f_min, f_max=req.f_max,
roll_off=equipment['SI']['default'].roll_off,
baud_rate=this_br, power=req.power, spacing=req.spacing,
delta_pdb=this_offset,
tx_osnr=req.tx_osnr, ref_carrier=ref_carrier(equipment))
for i, el in enumerate(path): for i, el in enumerate(path):
if isinstance(el, Roadm): if isinstance(el, Roadm):
spc_info = el(spc_info, degree=path[i+1].uid) spc_info = el(spc_info, degree=path[i+1].uid)
@@ -407,22 +419,19 @@ def propagate_and_optimize_mode(path, req, equipment):
# returns the last propagated path and mode # returns the last propagated path and mode
msg = f'\tWarning! Request {req.request_id}: no mode satisfies path SNR requirement.\n' msg = f'\tWarning! Request {req.request_id}: no mode satisfies path SNR requirement.\n'
print(msg) LOGGER.warning(msg)
LOGGER.info(msg)
req.blocking_reason = 'NO_FEASIBLE_MODE' req.blocking_reason = 'NO_FEASIBLE_MODE'
return path, last_explored_mode return path, last_explored_mode
else: else:
# no baudrate satisfying spacing # no baudrate satisfying spacing
msg = f'\tWarning! Request {req.request_id}: no baudrate satisfies spacing requirement.\n' msg = f'\tWarning! Request {req.request_id}: no baudrate satisfies spacing requirement.\n'
print(msg) LOGGER.warning(msg)
LOGGER.info(msg)
req.blocking_reason = 'NO_FEASIBLE_BAUDRATE_WITH_SPACING' req.blocking_reason = 'NO_FEASIBLE_BAUDRATE_WITH_SPACING'
return [], None return [], None
def jsontopath_metric(path_metric): def jsontopath_metric(path_metric):
""" a functions that reads resulting metric from json string """a functions that reads resulting metric from json string"""
"""
output_snr = next(e['accumulative-value'] output_snr = next(e['accumulative-value']
for e in path_metric if e['metric-type'] == 'SNR-0.1nm') for e in path_metric if e['metric-type'] == 'SNR-0.1nm')
output_snrbandwidth = next(e['accumulative-value'] output_snrbandwidth = next(e['accumulative-value']
@@ -440,9 +449,7 @@ def jsontopath_metric(path_metric):
def jsontoparams(my_p, tsp, mode, equipment): def jsontoparams(my_p, tsp, mode, equipment):
""" a function that derives optical params from transponder type and mode """a function that derives optical params from transponder type and mode supports the no mode case"""
supports the no mode case
"""
temp = [] temp = []
for elem in my_p['path-properties']['path-route-objects']: for elem in my_p['path-properties']['path-route-objects']:
if 'num-unnum-hop' in elem['path-route-object']: if 'num-unnum-hop' in elem['path-route-object']:
@@ -452,8 +459,8 @@ def jsontoparams(my_p, tsp, mode, equipment):
temp2 = [] temp2 = []
for elem in my_p['path-properties']['path-route-objects']: for elem in my_p['path-properties']['path-route-objects']:
if 'label-hop' in elem['path-route-object'].keys(): if 'label-hop' in elem['path-route-object'].keys():
temp2.append(f'{elem["path-route-object"]["label-hop"]["N"]}, ' + temp2.append(f'{[e["N"] for e in elem["path-route-object"]["label-hop"]]}, '
f'{elem["path-route-object"]["label-hop"]["M"]}') + f'{[e["M"] for e in elem["path-route-object"]["label-hop"]]}')
# OrderedDict.fromkeys returns the unique set of strings. # OrderedDict.fromkeys returns the unique set of strings.
# TODO: if spectrum changes along the path, we should be able to give the segments # TODO: if spectrum changes along the path, we should be able to give the segments
# eg for regeneration case # eg for regeneration case
@@ -477,10 +484,10 @@ def jsontoparams(my_p, tsp, mode, equipment):
def jsontocsv(json_data, equipment, fileout): def jsontocsv(json_data, equipment, fileout):
""" reads json path result file in accordance with: """reads json path result file in accordance with:
Yang model for requesting Path Computation Yang model for requesting Path Computation
draft-ietf-teas-yang-path-computation-01.txt. draft-ietf-teas-yang-path-computation-01.txt.
and write results in an CSV file and write results in an CSV file
""" """
mywriter = writer(fileout) mywriter = writer(fileout)
mywriter.writerow(('response-id', 'source', 'destination', 'path_bandwidth', 'Pass?', mywriter.writerow(('response-id', 'source', 'destination', 'path_bandwidth', 'Pass?',
@@ -815,13 +822,13 @@ def compute_path_dsjctn(network, equipment, pathreqlist, disjunctions_list):
if not ispart(allpaths[id(pth)].req.nodes_list, pth): if not ispart(allpaths[id(pth)].req.nodes_list, pth):
testispartok = False testispartok = False
if 'STRICT' in allpaths[id(pth)].req.loose_list: if 'STRICT' in allpaths[id(pth)].req.loose_list:
LOGGER.info(f'removing solution from candidate paths\n{pth}') LOGGER.debug(f'removing solution from candidate paths\n{pth}')
testispartnokloose = False testispartnokloose = False
break break
if testispartok: if testispartok:
temp.append(sol) temp.append(sol)
elif testispartnokloose: elif testispartnokloose:
LOGGER.info(f'Adding solution as alternate solution not satisfying constraint\n{pth}') LOGGER.debug(f'Adding solution as alternate solution not satisfying constraint\n{pth}')
alternatetemp.append(sol) alternatetemp.append(sol)
if temp: if temp:
candidates[this_d.disjunction_id] = temp candidates[this_d.disjunction_id] = temp
@@ -843,9 +850,7 @@ def compute_path_dsjctn(network, equipment, pathreqlist, disjunctions_list):
# remove duplicated candidates # remove duplicated candidates
candidates = remove_candidate(candidates, allpaths, allpaths[id(pth)].req, pth) candidates = remove_candidate(candidates, allpaths, allpaths[id(pth)].req, pth)
else: else:
msg = f'No disjoint path found with added constraint' msg = 'No disjoint path found with added constraint\nComputation stopped.'
LOGGER.critical(msg)
print(f'{msg}\nComputation stopped.')
# TODO in this case: replay step 5 with the candidate without constraints # TODO in this case: replay step 5 with the candidate without constraints
raise DisjunctionError(msg) raise DisjunctionError(msg)
@@ -866,8 +871,7 @@ def compute_path_dsjctn(network, equipment, pathreqlist, disjunctions_list):
def isdisjoint(pth1, pth2): def isdisjoint(pth1, pth2):
""" returns 0 if disjoint """returns 0 if disjoint"""
"""
edge1 = list(pairwise(pth1)) edge1 = list(pairwise(pth1))
edge2 = list(pairwise(pth2)) edge2 = list(pairwise(pth2))
for edge in edge1: for edge in edge1:
@@ -877,9 +881,9 @@ def isdisjoint(pth1, pth2):
def find_reversed_path(pth): def find_reversed_path(pth):
""" select of intermediate roadms and find the path between them """select of intermediate roadms and find the path between them
note that this function may not give an exact result in case of multiple note that this function may not give an exact result in case of multiple
links between two adjacent nodes. links between two adjacent nodes.
""" """
# TODO add some indication on elements to indicate from which other they # TODO add some indication on elements to indicate from which other they
# are the reversed direction. This is partly done with oms indication # are the reversed direction. This is partly done with oms indication
@@ -902,9 +906,8 @@ def find_reversed_path(pth):
# concatenation should be [roadma el1 el2 roadmb el3 el4 roadmc] # concatenation should be [roadma el1 el2 roadmb el3 el4 roadmc]
reversed_path = list(OrderedDict.fromkeys(reversed_path)) reversed_path = list(OrderedDict.fromkeys(reversed_path))
else: else:
msg = f'Error while handling reversed path {pth[-1].uid} to {pth[0].uid}:' +\ msg = f'Error while handling reversed path {pth[-1].uid} to {pth[0].uid}:' \
' can not handle unidir topology. TO DO.' + ' can not handle unidir topology. TO DO.'
LOGGER.critical(msg)
raise ValueError(msg) raise ValueError(msg)
reversed_path.append(pth[0]) reversed_path.append(pth[0])
@@ -912,9 +915,7 @@ def find_reversed_path(pth):
def ispart(ptha, pthb): def ispart(ptha, pthb):
""" the functions takes two paths a and b and retrns True """the functions takes two paths a and b and retrns True if all a elements are part of b and in the same order"""
if all a elements are part of b and in the same order
"""
j = 0 j = 0
for elem in ptha: for elem in ptha:
if elem in pthb: if elem in pthb:
@@ -928,8 +929,7 @@ def ispart(ptha, pthb):
def remove_candidate(candidates, allpaths, rqst, pth): def remove_candidate(candidates, allpaths, rqst, pth):
""" filter duplicate candidates """filter duplicate candidates"""
"""
# print(f'coucou {rqst.request_id}') # print(f'coucou {rqst.request_id}')
for key, candidate in candidates.items(): for key, candidate in candidates.items():
temp = candidate.copy() temp = candidate.copy()
@@ -944,8 +944,7 @@ def remove_candidate(candidates, allpaths, rqst, pth):
def compare_reqs(req1, req2, disjlist): def compare_reqs(req1, req2, disjlist):
""" compare two requests: returns True or False """compare two requests: returns True or False"""
"""
dis1 = [d for d in disjlist if req1.request_id in d.disjunctions_req] dis1 = [d for d in disjlist if req1.request_id in d.disjunctions_req]
dis2 = [d for d in disjlist if req2.request_id in d.disjunctions_req] dis2 = [d for d in disjlist if req2.request_id in d.disjunctions_req]
same_disj = False same_disj = False
@@ -978,28 +977,31 @@ def compare_reqs(req1, req2, disjlist):
req1.format == req2.format and \ req1.format == req2.format and \
req1.OSNR == req2.OSNR and \ req1.OSNR == req2.OSNR and \
req1.roll_off == req2.roll_off and \ req1.roll_off == req2.roll_off and \
same_disj and \ same_disj:
getattr(req1, 'N', None) is None and getattr(req2, 'N', None) is None and \
getattr(req1, 'M', None) is None and getattr(req2, 'M', None) is None:
return True return True
else: else:
return False return False
def requests_aggregation(pathreqlist, disjlist): def requests_aggregation(pathreqlist, disjlist):
""" this function aggregates requests so that if several requests """this function aggregates requests so that if several requests
exist between same source and destination and with same transponder type exist between same source and destination and with same transponder type
If transponder mode is defined and identical, then also agregates demands.
""" """
# todo maybe add conditions on mode ??, spacing ... # todo maybe add conditions on mode ??, spacing ...
# currently if undefined takes the default values # currently if undefined takes the default values
local_list = pathreqlist.copy() local_list = pathreqlist.copy()
for req in pathreqlist: for req in pathreqlist:
for this_r in local_list: for this_r in local_list:
if req.request_id != this_r.request_id and compare_reqs(req, this_r, disjlist): if req.request_id != this_r.request_id and compare_reqs(req, this_r, disjlist) and\
this_r.tsp_mode is not None:
# aggregate # aggregate
this_r.path_bandwidth += req.path_bandwidth this_r.path_bandwidth += req.path_bandwidth
this_r.N = this_r.N + req.N
this_r.M = this_r.M + req.M
temp_r_id = this_r.request_id temp_r_id = this_r.request_id
this_r.request_id = ' | '.join((this_r.request_id, req.request_id)) this_r.request_id = ' | '.join((this_r.request_id, req.request_id))
# remove request from list # remove request from list
local_list.remove(req) local_list.remove(req)
# todo change also disjunction req with new demand # todo change also disjunction req with new demand
@@ -1016,23 +1018,22 @@ def requests_aggregation(pathreqlist, disjlist):
def correct_json_route_list(network, pathreqlist): def correct_json_route_list(network, pathreqlist):
""" all names in list should be exact name in the network, and there is no ambiguity """all names in list should be exact name in the network, and there is no ambiguity
This function only checks that list is correct, warns user if the name is incorrect and
suppresses the constraint it it is loose or raises an error if it is strict This function only checks that list is correct, warns user if the name is incorrect and
suppresses the constraint it it is loose or raises an error if it is strict
""" """
all_uid = [n.uid for n in network.nodes()] all_uid = [n.uid for n in network.nodes()]
transponders = [n.uid for n in network.nodes() if isinstance(n, Transceiver)] transponders = [n.uid for n in network.nodes() if isinstance(n, Transceiver)]
for pathreq in pathreqlist: for pathreq in pathreqlist:
if pathreq.source not in transponders: if pathreq.source not in transponders:
msg = f'{ansi_escapes.red}Request: {pathreq.request_id}: could not find transponder' +\ msg = f'Request: {pathreq.request_id}: could not find transponder' \
f' source : {pathreq.source}.{ansi_escapes.reset}' + f' source : {pathreq.source}.'
LOGGER.critical(msg)
raise ServiceError(msg) raise ServiceError(msg)
if pathreq.destination not in transponders: if pathreq.destination not in transponders:
msg = f'{ansi_escapes.red}Request: {pathreq.request_id}: could not find transponder' +\ msg = f'Request: {pathreq.request_id}: could not find transponder' \
f' destination : {pathreq.destination}.{ansi_escapes.reset}' + f' destination : {pathreq.destination}.'
LOGGER.critical(msg)
raise ServiceError(msg) raise ServiceError(msg)
# silently remove source and dest nodes from the list # silently remove source and dest nodes from the list
@@ -1051,24 +1052,21 @@ def correct_json_route_list(network, pathreqlist):
# if no matching can be found in the network just ignore this constraint # if no matching can be found in the network just ignore this constraint
# if it is a loose constraint # if it is a loose constraint
# warns the user that this node is not part of the topology # warns the user that this node is not part of the topology
msg = f'{ansi_escapes.yellow}invalid route node specified:\n\t\'{n_id}\',' +\ msg = f'invalid route node specified:\n\t\'{n_id}\',' \
f' could not use it as constraint, skipped!{ansi_escapes.reset}' + ' could not use it as constraint, skipped!'
print(msg) LOGGER.warning(msg)
LOGGER.info(msg)
pathreq.loose_list.pop(pathreq.nodes_list.index(n_id)) pathreq.loose_list.pop(pathreq.nodes_list.index(n_id))
pathreq.nodes_list.remove(n_id) pathreq.nodes_list.remove(n_id)
else: else:
msg = f'{ansi_escapes.red}could not find node:\n\t \'{n_id}\' in network' +\ msg = f'could not find node:\n\t \'{n_id}\' in network' \
f' topology. Strict constraint can not be applied.{ansi_escapes.reset}' + ' topology. Strict constraint can not be applied.'
LOGGER.critical(msg)
raise ServiceError(msg) raise ServiceError(msg)
return pathreqlist return pathreqlist
def deduplicate_disjunctions(disjn): def deduplicate_disjunctions(disjn):
""" clean disjunctions to remove possible repetition """clean disjunctions to remove possible repetition"""
"""
local_disjn = disjn.copy() local_disjn = disjn.copy()
for elem in local_disjn: for elem in local_disjn:
for dis_elem in local_disjn: for dis_elem in local_disjn:
@@ -1079,8 +1077,9 @@ def deduplicate_disjunctions(disjn):
def compute_path_with_disjunction(network, equipment, pathreqlist, pathlist): def compute_path_with_disjunction(network, equipment, pathreqlist, pathlist):
""" use a list but a dictionnary might be helpful to find path based on request_id """use a list but a dictionnary might be helpful to find path based on request_id
TODO change all these req, dsjct, res lists into dict !
TODO change all these req, dsjct, res lists into dict !
""" """
path_res_list = [] path_res_list = []
reversed_path_res_list = [] reversed_path_res_list = []
@@ -1091,10 +1090,10 @@ def compute_path_with_disjunction(network, equipment, pathreqlist, pathlist):
# use the power specified in requests but might be different from the one # use the power specified in requests but might be different from the one
# specified for design the power is an optional parameter for requests # specified for design the power is an optional parameter for requests
# definition if optional, use the one defines in eqt_config.json # definition if optional, use the one defines in eqt_config.json
print(f'request {pathreq.request_id}') msg = f'\n\trequest {pathreq.request_id}\n' \
print(f'Computing path from {pathreq.source} to {pathreq.destination}') + f'\tComputing path from {pathreq.source} to {pathreq.destination}\n' \
# adding first node to be clearer on the output + f'\twith path constraint: {[pathreq.source] + pathreq.nodes_list}'
print(f'with path constraint: {[pathreq.source] + pathreq.nodes_list}') # # adding first node to be clearer on the output
# pathlist[i] contains the whole path information for request i # pathlist[i] contains the whole path information for request i
# last element is a transciver and where the result of the propagation is # last element is a transciver and where the result of the propagation is
@@ -1104,7 +1103,8 @@ def compute_path_with_disjunction(network, equipment, pathreqlist, pathlist):
# may use the same transponder for the performance simulation. This is why # may use the same transponder for the performance simulation. This is why
# we use deepcopy: to ensure that each propagation is recorded and not overwritten # we use deepcopy: to ensure that each propagation is recorded and not overwritten
total_path = deepcopy(pathlist[i]) total_path = deepcopy(pathlist[i])
print(f'Computed path (roadms):{[e.uid for e in total_path if isinstance(e, Roadm)]}') msg = msg + f'\n\tComputed path (roadms):{[e.uid for e in total_path if isinstance(e, Roadm)]}'
LOGGER.info(msg)
# for debug # for debug
# print(f'{pathreq.baud_rate} {pathreq.power} {pathreq.spacing} {pathreq.nb_channel}') # print(f'{pathreq.baud_rate} {pathreq.power} {pathreq.spacing} {pathreq.nb_channel}')
if total_path: if total_path:
@@ -1115,14 +1115,12 @@ def compute_path_with_disjunction(network, equipment, pathreqlist, pathlist):
snr01nm_with_penalty = total_path[-1].snr_01nm - total_path[-1].total_penalty snr01nm_with_penalty = total_path[-1].snr_01nm - total_path[-1].total_penalty
min_ind = argmin(snr01nm_with_penalty) min_ind = argmin(snr01nm_with_penalty)
if round(snr01nm_with_penalty[min_ind], 2) < pathreq.OSNR + equipment['SI']['default'].sys_margins: if round(snr01nm_with_penalty[min_ind], 2) < pathreq.OSNR + equipment['SI']['default'].sys_margins:
msg = f'\tWarning! Request {pathreq.request_id} computed path from' +\ msg = f'\tWarning! Request {pathreq.request_id} computed path from' \
f' {pathreq.source} to {pathreq.destination} does not pass with {pathreq.tsp_mode}' +\ + f' {pathreq.source} to {pathreq.destination} does not pass with {pathreq.tsp_mode}' \
f'\n\tcomputed SNR in 0.1nm = {round(total_path[-1].snr_01nm[min_ind], 2)}' +\ + f'\n\tcomputed SNR in 0.1nm = {round(total_path[-1].snr_01nm[min_ind], 2)}'
f'\n\tCD penalty = {round(total_path[-1].penalties["chromatic_dispersion"][min_ind], 2)}' +\ msg = _penalty_msg(total_path, msg, min_ind) \
f'\n\tPMD penalty = {round(total_path[-1].penalties["pmd"][min_ind], 2)}' +\ + f'\n\trequired osnr = {pathreq.OSNR}' \
f'\n\trequired osnr = {pathreq.OSNR}' +\ + f'\n\tsystem margin = {equipment["SI"]["default"].sys_margins}'
f'\n\tsystem margin = {equipment["SI"]["default"].sys_margins}'
print(msg)
LOGGER.warning(msg) LOGGER.warning(msg)
pathreq.blocking_reason = 'MODE_NOT_FEASIBLE' pathreq.blocking_reason = 'MODE_NOT_FEASIBLE'
else: else:
@@ -1142,6 +1140,7 @@ def compute_path_with_disjunction(network, equipment, pathreqlist, pathlist):
pathreq.OSNR = mode['OSNR'] pathreq.OSNR = mode['OSNR']
pathreq.tx_osnr = mode['tx_osnr'] pathreq.tx_osnr = mode['tx_osnr']
pathreq.bit_rate = mode['bit_rate'] pathreq.bit_rate = mode['bit_rate']
pathreq.penalties = mode['penalties']
# other blocking reason should not appear at this point # other blocking reason should not appear at this point
except AttributeError: except AttributeError:
pathreq.baud_rate = mode['baud_rate'] pathreq.baud_rate = mode['baud_rate']
@@ -1150,28 +1149,27 @@ def compute_path_with_disjunction(network, equipment, pathreqlist, pathlist):
pathreq.OSNR = mode['OSNR'] pathreq.OSNR = mode['OSNR']
pathreq.tx_osnr = mode['tx_osnr'] pathreq.tx_osnr = mode['tx_osnr']
pathreq.bit_rate = mode['bit_rate'] pathreq.bit_rate = mode['bit_rate']
pathreq.penalties = mode['penalties']
# reversed path is needed for correct spectrum assignment # reversed path is needed for correct spectrum assignment
reversed_path = find_reversed_path(pathlist[i]) reversed_path = find_reversed_path(pathlist[i])
if pathreq.bidir and pathreq.baud_rate is not None: if pathreq.bidir and pathreq.baud_rate is not None:
# Both directions requested, and a feasible mode was found # Both directions requested, and a feasible mode was found
rev_p = deepcopy(reversed_path) rev_p = deepcopy(reversed_path)
msg = f'\n\tPropagating Z to A direction {pathreq.destination} to {pathreq.source}\n' \
print(f'\n\tPropagating Z to A direction {pathreq.destination} to {pathreq.source}') + f'\tPath (roadms) {[r.uid for r in rev_p if isinstance(r,Roadm)]}\n'
print(f'\tPath (roadsm) {[r.uid for r in rev_p if isinstance(r,Roadm)]}\n') LOGGER.info(msg)
propagate(rev_p, pathreq, equipment) propagate(rev_p, pathreq, equipment)
propagated_reversed_path = rev_p propagated_reversed_path = rev_p
snr01nm_with_penalty = rev_p[-1].snr_01nm - rev_p[-1].total_penalty snr01nm_with_penalty = rev_p[-1].snr_01nm - rev_p[-1].total_penalty
min_ind = argmin(snr01nm_with_penalty) min_ind = argmin(snr01nm_with_penalty)
if round(snr01nm_with_penalty[min_ind], 2) < pathreq.OSNR + equipment['SI']['default'].sys_margins: if round(snr01nm_with_penalty[min_ind], 2) < pathreq.OSNR + equipment['SI']['default'].sys_margins:
msg = f'\tWarning! Request {pathreq.request_id} computed path from' +\ msg = f'\tWarning! Request {pathreq.request_id} computed path from' \
f' {pathreq.source} to {pathreq.destination} does not pass with {pathreq.tsp_mode}' +\ + f' {pathreq.destination} to {pathreq.source} does not pass with {pathreq.tsp_mode}' \
f'\n\tcomputed SNR in 0.1nm = {round(rev_p[-1].snr_01nm[min_ind], 2)}' +\ + f'\n\tcomputed SNR in 0.1nm = {round(rev_p[-1].snr_01nm[min_ind], 2)}'
f'\n\tCD penalty = {round(rev_p[-1].penalties["chromatic_dispersion"][min_ind], 2)}' +\ msg = _penalty_msg(rev_p, msg, min_ind) \
f'\n\tPMD penalty = {round(rev_p[-1].penalties["pmd"][min_ind], 2)}' +\ + f'\n\trequired osnr = {pathreq.OSNR}' \
f'\n\trequired osnr = {pathreq.OSNR}' +\ + f'\n\tsystem margin = {equipment["SI"]["default"].sys_margins}'
f'\n\tsystem margin = {equipment["SI"]["default"].sys_margins}'
print(msg)
LOGGER.warning(msg) LOGGER.warning(msg)
# TODO selection of mode should also be on reversed direction !! # TODO selection of mode should also be on reversed direction !!
if not hasattr(pathreq, 'blocking_reason'): if not hasattr(pathreq, 'blocking_reason'):
@@ -1179,9 +1177,8 @@ def compute_path_with_disjunction(network, equipment, pathreqlist, pathlist):
else: else:
propagated_reversed_path = [] propagated_reversed_path = []
else: else:
msg = 'Total path is empty. No propagation' msg = f'Request {pathreq.request_id}: Total path is empty. No propagation'
print(msg) LOGGER.warning(msg)
LOGGER.info(msg)
reversed_path = [] reversed_path = []
propagated_reversed_path = [] propagated_reversed_path = []
@@ -1189,12 +1186,12 @@ def compute_path_with_disjunction(network, equipment, pathreqlist, pathlist):
reversed_path_res_list.append(reversed_path) reversed_path_res_list.append(reversed_path)
propagated_reversed_path_res_list.append(propagated_reversed_path) propagated_reversed_path_res_list.append(propagated_reversed_path)
# print to have a nice output # print to have a nice output
print('')
return path_res_list, reversed_path_res_list, propagated_reversed_path_res_list return path_res_list, reversed_path_res_list, propagated_reversed_path_res_list
def compute_spectrum_slot_vs_bandwidth(bandwidth, spacing, bit_rate, slot_width=0.0125e12): def compute_spectrum_slot_vs_bandwidth(bandwidth, spacing, bit_rate, slot_width=0.0125e12):
""" Compute the number of required wavelengths and the M value (number of consumed slots) """Compute the number of required wavelengths and the M value (number of consumed slots)
Each wavelength consumes one `spacing`, and the result is rounded up to consume a natural number of slots. Each wavelength consumes one `spacing`, and the result is rounded up to consume a natural number of slots.
>>> compute_spectrum_slot_vs_bandwidth(400e9, 50e9, 200e9) >>> compute_spectrum_slot_vs_bandwidth(400e9, 50e9, 200e9)
@@ -1203,3 +1200,19 @@ def compute_spectrum_slot_vs_bandwidth(bandwidth, spacing, bit_rate, slot_width=
number_of_wavelengths = ceil(bandwidth / bit_rate) number_of_wavelengths = ceil(bandwidth / bit_rate)
total_number_of_slots = ceil(spacing / slot_width) * number_of_wavelengths total_number_of_slots = ceil(spacing / slot_width) * number_of_wavelengths
return number_of_wavelengths, total_number_of_slots return number_of_wavelengths, total_number_of_slots
def _penalty_msg(total_path, msg, min_ind):
"""formatting helper for reporting unfeasible paths
The penalty info are optional, so this checks that penalty exists before creating a message."""
penalty_dict = {
'pdl': 'PDL',
'chromatic_dispersion': 'CD',
'pmd': 'PMD'}
for key, pretty in penalty_dict.items():
if key in total_path[-1].penalties:
msg += f'\n\t{pretty} penalty = {round(total_path[-1].penalties[key][min_ind], 2)}'
else:
msg += f'\n\t{pretty} penalty not evaluated'
return msg

View File

@@ -17,14 +17,14 @@ from collections import namedtuple
from logging import getLogger from logging import getLogger
from gnpy.core.elements import Roadm, Transceiver from gnpy.core.elements import Roadm, Transceiver
from gnpy.core.exceptions import ServiceError, SpectrumError from gnpy.core.exceptions import ServiceError, SpectrumError
from gnpy.core.utils import order_slots, restore_order
from gnpy.topology.request import compute_spectrum_slot_vs_bandwidth from gnpy.topology.request import compute_spectrum_slot_vs_bandwidth
LOGGER = getLogger(__name__) LOGGER = getLogger(__name__)
class Bitmap: class Bitmap:
""" records the spectrum occupation """records the spectrum occupation"""
"""
def __init__(self, f_min, f_max, grid, guardband=0.15e12, bitmap=None): def __init__(self, f_min, f_max, grid, guardband=0.15e12, bitmap=None):
# n is the min index including guardband. Guardband is require to be sure # n is the min index including guardband. Guardband is require to be sure
@@ -45,26 +45,22 @@ class Bitmap:
raise SpectrumError(f'bitmap is not consistant with f_min{f_min} - n: {n_min} and f_max{f_max}- n :{n_max}') raise SpectrumError(f'bitmap is not consistant with f_min{f_min} - n: {n_min} and f_max{f_max}- n :{n_max}')
def getn(self, i): def getn(self, i):
""" converts the n (itu grid) into a local index """converts the n (itu grid) into a local index"""
"""
return self.freq_index[i] return self.freq_index[i]
def geti(self, nvalue): def geti(self, nvalue):
""" converts the local index into n (itu grid) """converts the local index into n (itu grid)"""
"""
return self.freq_index.index(nvalue) return self.freq_index.index(nvalue)
def insert_left(self, newbitmap): def insert_left(self, newbitmap):
""" insert bitmap on the left to align oms bitmaps if their start frequencies are different """insert bitmap on the left to align oms bitmaps if their start frequencies are different"""
"""
self.bitmap = newbitmap + self.bitmap self.bitmap = newbitmap + self.bitmap
temp = list(range(self.n_min - len(newbitmap), self.n_min)) temp = list(range(self.n_min - len(newbitmap), self.n_min))
self.freq_index = temp + self.freq_index self.freq_index = temp + self.freq_index
self.n_min = self.freq_index[0] self.n_min = self.freq_index[0]
def insert_right(self, newbitmap): def insert_right(self, newbitmap):
""" insert bitmap on the right to align oms bitmaps if their stop frequencies are different """insert bitmap on the right to align oms bitmaps if their stop frequencies are different"""
"""
self.bitmap = self.bitmap + newbitmap self.bitmap = self.bitmap + newbitmap
self.freq_index = self.freq_index + list(range(self.n_max, self.n_max + len(newbitmap))) self.freq_index = self.freq_index + list(range(self.n_max, self.n_max + len(newbitmap)))
self.n_max = self.freq_index[-1] self.n_max = self.freq_index[-1]
@@ -75,8 +71,8 @@ OMSParams = namedtuple('OMSParams', 'oms_id el_id_list el_list')
class OMS: class OMS:
""" OMS class is the logical container that represent a link between two adjacent ROADMs and """OMS class is the logical container that represent a link between two adjacent ROADMs and
records the crossed elements and the occupied spectrum records the crossed elements and the occupied spectrum
""" """
def __init__(self, *args, **params): def __init__(self, *args, **params):
@@ -98,36 +94,28 @@ class OMS:
f'{self.el_id_list[0]} - {self.el_id_list[-1]}', '\n']) f'{self.el_id_list[0]} - {self.el_id_list[-1]}', '\n'])
def add_element(self, elem): def add_element(self, elem):
""" records oms elements """records oms elements"""
"""
self.el_id_list.append(elem.uid) self.el_id_list.append(elem.uid)
self.el_list.append(elem) self.el_list.append(elem)
def update_spectrum(self, f_min, f_max, guardband=0.15e12, existing_spectrum=None, def update_spectrum(self, f_min, f_max, guardband=0.15e12, existing_spectrum=None, grid=0.00625e12):
grid=0.00625e12): """Frequencies expressed in Hz.
""" frequencies expressed in Hz Add 150 GHz margin to enable a center channel on f_min
Use ITU-T G694.1 Flexible DWDM grid definition
For the flexible DWDM grid, the allowed frequency slots have a nominal central frequency (in THz) defined by:
193.1 + n × 0.00625 where n is a positive or negative integer including 0
and 0.00625 is the nominal central frequency granularity in THz
and a slot width defined by:
12.5 × m where m is a positive integer and 12.5 is the slot width granularity in GHz.
Any combination of frequency slots is allowed as long as no two frequency slots overlap.
If bitmap is not None, then use it: Bitmap checks its consistency with f_min f_max
else a brand new bitmap is created
""" """
if existing_spectrum is None: self.spectrum_bitmap = Bitmap(f_min=f_min, f_max=f_max, grid=grid, guardband=guardband,
# add some 150 GHz margin to enable a center channel on f_min bitmap=existing_spectrum)
# use ITU-T G694.1
# Flexible DWDM grid definition
# For the flexible DWDM grid, the allowed frequency slots have a nominal
# central frequency (in THz) defined by:
# 193.1 + n × 0.00625 where n is a positive or negative integer including 0
# and 0.00625 is the nominal central frequency granularity in THz
# and a slot width defined by:
# 12.5 × m where m is a positive integer and 12.5 is the slot width granularity in
# GHz.
# Any combination of frequency slots is allowed as long as no two frequency
# slots overlap.
# TODO : add explaination on that / parametrize ....
self.spectrum_bitmap = Bitmap(f_min, f_max, grid, guardband)
# print(len(self.spectrum_bitmap.bitmap))
def assign_spectrum(self, nvalue, mvalue): def assign_spectrum(self, nvalue, mvalue):
""" change oms spectrum to mark spectrum assigned """change oms spectrum to mark spectrum assigned"""
"""
if not isinstance(nvalue, int): if not isinstance(nvalue, int):
raise SpectrumError(f'N must be a signed integer, got {nvalue}') raise SpectrumError(f'N must be a signed integer, got {nvalue}')
if not isinstance(mvalue, int): if not isinstance(mvalue, int):
@@ -146,16 +134,16 @@ class OMS:
self.spectrum_bitmap.bitmap[self.spectrum_bitmap.geti(startn):self.spectrum_bitmap.geti(stopn) + 1] = [0] * (stopn - startn + 1) self.spectrum_bitmap.bitmap[self.spectrum_bitmap.geti(startn):self.spectrum_bitmap.geti(stopn) + 1] = [0] * (stopn - startn + 1)
def add_service(self, service_id, nb_wl): def add_service(self, service_id, nb_wl):
""" record service and mark spectrum as occupied """record service and mark spectrum as occupied"""
"""
self.service_list.append(service_id) self.service_list.append(service_id)
self.nb_channels += nb_wl self.nb_channels += nb_wl
def frequency_to_n(freq, grid=0.00625e12): def frequency_to_n(freq, grid=0.00625e12):
""" converts frequency into the n value (ITU grid) """converts frequency into the n value (ITU grid)
reference to Recommendation G.694.1 (02/12), Figure I.3
https://www.itu.int/rec/T-REC-G.694.1-201202-I/en reference to Recommendation G.694.1 (02/12), Figure I.3
https://www.itu.int/rec/T-REC-G.694.1-201202-I/en
>>> frequency_to_n(193.1375e12) >>> frequency_to_n(193.1375e12)
6 6
@@ -167,9 +155,10 @@ def frequency_to_n(freq, grid=0.00625e12):
def nvalue_to_frequency(nvalue, grid=0.00625e12): def nvalue_to_frequency(nvalue, grid=0.00625e12):
""" converts n value into a frequency """converts n value into a frequency
reference to Recommendation G.694.1 (02/12), Table 1
https://www.itu.int/rec/T-REC-G.694.1-201202-I/en reference to Recommendation G.694.1 (02/12), Table 1
https://www.itu.int/rec/T-REC-G.694.1-201202-I/en
>>> nvalue_to_frequency(6) >>> nvalue_to_frequency(6)
193137500000000.0 193137500000000.0
@@ -181,17 +170,17 @@ def nvalue_to_frequency(nvalue, grid=0.00625e12):
def mvalue_to_slots(nvalue, mvalue): def mvalue_to_slots(nvalue, mvalue):
""" convert center n an m into start and stop n """convert center n an m into start and stop n"""
"""
startn = nvalue - mvalue startn = nvalue - mvalue
stopn = nvalue + mvalue - 1 stopn = nvalue + mvalue - 1
return startn, stopn return startn, stopn
def slots_to_m(startn, stopn): def slots_to_m(startn, stopn):
""" converts the start and stop n values to the center n and m value """converts the start and stop n values to the center n and m value
reference to Recommendation G.694.1 (02/12), Figure I.3
https://www.itu.int/rec/T-REC-G.694.1-201202-I/en reference to Recommendation G.694.1 (02/12), Figure I.3
https://www.itu.int/rec/T-REC-G.694.1-201202-I/en
>>> nval, mval = slots_to_m(6, 20) >>> nval, mval = slots_to_m(6, 20)
>>> nval >>> nval
@@ -206,10 +195,11 @@ def slots_to_m(startn, stopn):
def m_to_freq(nvalue, mvalue, grid=0.00625e12): def m_to_freq(nvalue, mvalue, grid=0.00625e12):
""" converts m into frequency range """converts m into frequency range
spectrum(13,7) is (193137500000000.0, 193225000000000.0)
reference to Recommendation G.694.1 (02/12), Figure I.3 spectrum(13,7) is (193137500000000.0, 193225000000000.0)
https://www.itu.int/rec/T-REC-G.694.1-201202-I/en reference to Recommendation G.694.1 (02/12), Figure I.3
https://www.itu.int/rec/T-REC-G.694.1-201202-I/en
>>> fstart, fstop = m_to_freq(13, 7) >>> fstart, fstop = m_to_freq(13, 7)
>>> fstart >>> fstart
@@ -225,9 +215,7 @@ def m_to_freq(nvalue, mvalue, grid=0.00625e12):
def align_grids(oms_list): def align_grids(oms_list):
""" used to apply same grid to all oms : same starting n, stop n and slot size """Used to apply same grid to all oms : same starting n, stop n and slot size. Out of grid slots are set to 0."""
out of grid slots are set to 0
"""
n_min = min([o.spectrum_bitmap.n_min for o in oms_list]) n_min = min([o.spectrum_bitmap.n_min for o in oms_list])
n_max = max([o.spectrum_bitmap.n_max for o in oms_list]) n_max = max([o.spectrum_bitmap.n_max for o in oms_list])
for this_o in oms_list: for this_o in oms_list:
@@ -239,12 +227,13 @@ def align_grids(oms_list):
def build_oms_list(network, equipment): def build_oms_list(network, equipment):
""" initialization of OMS list in the network """initialization of OMS list in the network
an oms is build reading all intermediate nodes between two adjacent ROADMs
each element within the list is being added an oms and oms_id to record the an oms is build reading all intermediate nodes between two adjacent ROADMs
oms it belongs to. each element within the list is being added an oms and oms_id to record the
the function supports different spectrum width and supposes that the whole network oms it belongs to.
works with the min range among OMSs the function supports different spectrum width and supposes that the whole network
works with the min range among OMSs
""" """
oms_id = 0 oms_id = 0
oms_list = [] oms_list = []
@@ -296,8 +285,9 @@ def build_oms_list(network, equipment):
def reversed_oms(oms_list): def reversed_oms(oms_list):
""" identifies reversed OMS """identifies reversed OMS
only applicable for non parallel OMS
only applicable for non parallel OMS
""" """
for oms in oms_list: for oms in oms_list:
has_reversed = False has_reversed = False
@@ -322,28 +312,41 @@ def bitmap_sum(band1, band2):
return res return res
def spectrum_selection(pth, oms_list, requested_m, requested_n=None): def build_path_oms_id_list(pth):
"""Collects spectrum availability and call the select_candidate function"""
# use indexes instead of ITU-T n values
path_oms = [] path_oms = []
for elem in pth: for elem in pth:
if not isinstance(elem, Roadm) and not isinstance(elem, Transceiver): if not isinstance(elem, Roadm) and not isinstance(elem, Transceiver):
# only edfa, fused and fibers have oms_id attribute # only edfa, fused and fibers have oms_id attribute
path_oms.append(elem.oms_id) path_oms.append(elem.oms_id)
# remove duplicate oms_id, order is not important # remove duplicate oms_id, order is not important
path_oms = list(set(path_oms)) return list(set(path_oms))
# assuming all oms have same freq index
if not path_oms:
candidate = (None, None, None)
return candidate, path_oms
freq_index = oms_list[path_oms[0]].spectrum_bitmap.freq_index
freq_index_min = oms_list[path_oms[0]].spectrum_bitmap.freq_index_min
freq_index_max = oms_list[path_oms[0]].spectrum_bitmap.freq_index_max
freq_availability = oms_list[path_oms[0]].spectrum_bitmap.bitmap
def aggregate_oms_bitmap(path_oms, oms_list):
spectrum = oms_list[path_oms[0]].spectrum_bitmap
bitmap = spectrum.bitmap
# assuming all oms have same freq indices
for oms in path_oms[1:]: for oms in path_oms[1:]:
freq_availability = bitmap_sum(oms_list[oms].spectrum_bitmap.bitmap, freq_availability) bitmap = bitmap_sum(oms_list[oms].spectrum_bitmap.bitmap, bitmap)
params = {
'oms_id': 0,
'el_id_list': 0,
'el_list': []
}
freq_min = nvalue_to_frequency(spectrum.freq_index_min)
freq_max = nvalue_to_frequency(spectrum.freq_index_max)
aggregate_oms = OMS(**params)
aggregate_oms.update_spectrum(freq_min, freq_max, grid=0.00625e12, existing_spectrum=bitmap)
return aggregate_oms
def spectrum_selection(test_oms, requested_m, requested_n=None):
"""Collects spectrum availability and call the select_candidate function"""
freq_index = test_oms.spectrum_bitmap.freq_index
freq_index_min = test_oms.spectrum_bitmap.freq_index_min
freq_index_max = test_oms.spectrum_bitmap.freq_index_max
freq_availability = test_oms.spectrum_bitmap.bitmap
if requested_n is None: if requested_n is None:
# avoid slots reserved on the edge 0.15e-12 on both sides -> 24 # avoid slots reserved on the edge 0.15e-12 on both sides -> 24
candidates = [(freq_index[i] + requested_m, freq_index[i], freq_index[i] + 2 * requested_m - 1) candidates = [(freq_index[i] + requested_m, freq_index[i], freq_index[i] + 2 * requested_m - 1)
@@ -354,29 +357,36 @@ def spectrum_selection(pth, oms_list, requested_m, requested_n=None):
candidate = select_candidate(candidates, policy='first_fit') candidate = select_candidate(candidates, policy='first_fit')
else: else:
i = oms_list[path_oms[0]].spectrum_bitmap.geti(requested_n) i = test_oms.spectrum_bitmap.geti(requested_n)
# print(f'N {requested_n} i {i}') if (freq_availability[i - requested_m:i + requested_m] == [1] * (2 * requested_m)
# print(freq_availability[i-m:i+m] ) and freq_index[i - requested_m] >= freq_index_min
# print(freq_index[i-m:i+m])
if (freq_availability[i - requested_m:i + requested_m] == [1] * (2 * requested_m) and
freq_index[i - requested_m] >= freq_index_min
and freq_index[i + requested_m - 1] <= freq_index_max): and freq_index[i + requested_m - 1] <= freq_index_max):
# candidate is the triplet center_n, startn and stopn # candidate is the triplet center_n, startn and stopn
candidate = (requested_n, requested_n - requested_m, requested_n + requested_m - 1) candidate = (requested_n, requested_n - requested_m, requested_n + requested_m - 1)
else: else:
candidate = (None, None, None) candidate = (None, None, None)
# print("coucou11") return candidate
# print(candidate)
# print(freq_availability[321:321+2*m])
# a = [i+321 for i in range(2*m)] def determine_slot_numbers(test_oms, requested_n, required_m, per_channel_m):
# print(a) """determines max availability around requested_n. requested_n should not be None"""
# print(candidate) bitmap = test_oms.spectrum_bitmap
return candidate, path_oms freq_index = bitmap.freq_index
freq_index_min = bitmap.freq_index_min
freq_index_max = bitmap.freq_index_max
freq_availability = bitmap.bitmap
center_i = bitmap.geti(requested_n)
i = per_channel_m
while (freq_availability[center_i - i:center_i + i] == [1] * (2 * i)
and freq_index[center_i - i] >= freq_index_min
and freq_index[center_i + i - 1] <= freq_index_max
and i <= required_m):
i += per_channel_m
return i - per_channel_m
def select_candidate(candidates, policy): def select_candidate(candidates, policy):
""" selects a candidate among all available spectrum """selects a candidate among all available spectrum"""
"""
if policy == 'first_fit': if policy == 'first_fit':
if candidates: if candidates:
return candidates[0] return candidates[0]
@@ -386,44 +396,112 @@ def select_candidate(candidates, policy):
raise ServiceError('Only first_fit spectrum assignment policy is implemented.') raise ServiceError('Only first_fit spectrum assignment policy is implemented.')
def compute_n_m(required_m, rq, path_oms, oms_list, per_channel_m, policy='first_fit'):
""" based on requested path_bandwidth fill in M=None values with uint values, using per_channel_m
and center frequency, with first fit strategy. The function checks the available spectrum but check
consistencies among M values of the request, but not with other requests.
For example, if request is for 32 slots corresponding to 8 x 4 slots of 32Gbauds channels,
the following frequency slots will result in the following assignment
N = 0, 8, 16, 32 -> 0, 8, 16, 32
M = 8, None, 8, None -> 8, 8, 8, 8
N = 0, 8, 16, 32 -> 0, , 16
M = None, None, 8, None -> 24, , 8
"""
selected_m = []
selected_n = []
remaining_slots_to_serve = required_m
# order slots for the computation: assign biggest m first
rq_N, rq_M, order = order_slots([{'N': n, 'M': m} for n, m in zip(rq.N, rq.M)])
# Create an oms that represents current assignments of all oms listed in path_oms, and test N and M on it.
# If M is defined, checks that proposed N, M is free
test_oms = aggregate_oms_bitmap(path_oms, oms_list)
for n, m in zip(rq_N, rq_M):
if m is not None and n is not None:
# check availabilityfor this n, m
available_slots = determine_slot_numbers(test_oms, n, m, m)
if available_slots == 0:
# if n, m are not feasible, break at this point no have non zero remaining_slots_to_serve
# in order to blocks the request (even is other N,M where feasible)
break
elif m is not None and n is None:
# find a candidate n
n, _, _ = spectrum_selection(test_oms, m, None)
if n is None:
# if no n is feasible for the m, block the request
break
elif m is None and n is not None:
# find a feasible m for this n. If None is found, then block the request
m = determine_slot_numbers(test_oms, n, remaining_slots_to_serve, per_channel_m)
if m == 0 or remaining_slots_to_serve == 0:
break
else:
# if n and m are not defined, try to find a single assignment to fits the remaining slots to serve
# (first fit strategy)
n, _, _ = spectrum_selection(test_oms, remaining_slots_to_serve, None)
if n is None or remaining_slots_to_serve == 0:
break
else:
m = remaining_slots_to_serve
selected_m.append(m)
selected_n.append(n)
test_oms.assign_spectrum(n, m)
remaining_slots_to_serve = remaining_slots_to_serve - m
# re-order selected_m and selected_n according to initial request N, M order, ignoring None values
not_selected = [None for i in range(len(rq_N) - len(selected_n))]
selected_m = restore_order(selected_m + not_selected, order)
selected_n = restore_order(selected_n + not_selected, order)
return selected_n, selected_m, remaining_slots_to_serve
def pth_assign_spectrum(pths, rqs, oms_list, rpths): def pth_assign_spectrum(pths, rqs, oms_list, rpths):
""" basic first fit assignment """basic first fit assignment
if reversed path are provided, means that occupation is bidir
if reversed path are provided, means that occupation is bidir
""" """
for pth, rq, rpth in zip(pths, rqs, rpths): for pth, rq, rpth in zip(pths, rqs, rpths):
# computes the number of channels required
if hasattr(rq, 'blocking_reason'): if hasattr(rq, 'blocking_reason'):
rq.N = None rq.N = None
rq.M = None rq.M = None
else: else:
nb_wl, requested_m = compute_spectrum_slot_vs_bandwidth(rq.path_bandwidth, # computes the number of channels required for path_bandwidth and the min required nb of slots
rq.spacing, rq.bit_rate) # for one channel (corresponds to the spacing)
if getattr(rq, 'M', None) is not None: nb_wl, required_m = compute_spectrum_slot_vs_bandwidth(rq.path_bandwidth,
# Consistency check between the requested M and path_bandwidth rq.spacing, rq.bit_rate)
# M value should be bigger than the computed requested_m (simple estimate) _, per_channel_m = compute_spectrum_slot_vs_bandwidth(rq.bit_rate,
# TODO: elaborate a more accurate estimate with nb_wl * tx_osnr + possibly guardbands in case of rq.spacing, rq.bit_rate)
# find oms ids that are concerned both by pth and rpth
path_oms = build_path_oms_id_list(pth + rpth)
if getattr(rq, 'M', None) is not None and all(rq.M):
# if all M are well defined: Consistency check that the requested M are enough to carry the nb_wl:
# check that the integer number of per_channel_m carried in each M value is enough to carry nb_wl.
# if not, blocks the demand
nb_channels_of_request = sum([m // per_channel_m for m in rq.M])
# TODO: elaborate a more accurate estimate with nb_wl * min_spacing + possibly guardbands in case of
# superchannel closed packing. # superchannel closed packing.
if requested_m > rq.M: if nb_wl > nb_channels_of_request:
rq.N = None rq.N = None
rq.M = None rq.M = None
rq.blocking_reason = 'NOT_ENOUGH_RESERVED_SPECTRUM' rq.blocking_reason = 'NOT_ENOUGH_RESERVED_SPECTRUM'
# need to stop here for this request and not go though spectrum selection process with requested_m # need to stop here for this request and not go though spectrum selection process
continue continue
# use the req.M even if requested_m is smaller # Use the req.M even if nb_wl and required_m are smaller.
requested_m = rq.M # first fit strategy: assign as many lambda as possible in the None remaining N, M values
requested_n = getattr(rq, 'N', None) selected_n, selected_m, remaining_slots_to_serve = \
(center_n, startn, stopn), path_oms = spectrum_selection(pth + rpth, oms_list, requested_m, compute_n_m(required_m, rq, path_oms, oms_list, per_channel_m)
requested_n) # if there are some remaining_slots_to_serve, this means that provided rq.M and rq.N values were
# if requested n and m concern already occupied spectrum the previous function returns a None candidate # not possible. Then do not go though spectrum assignment process and blocks the demand
# if not None, center_n and start, stop frequencies are applicable to all oms of pth if remaining_slots_to_serve > 0:
# checks that spectrum is not None else indicate blocking reason
if center_n is not None:
for oms_elem in path_oms:
oms_list[oms_elem].assign_spectrum(center_n, requested_m)
oms_list[oms_elem].add_service(rq.request_id, nb_wl)
rq.N = center_n
rq.M = requested_m
else:
rq.N = None rq.N = None
rq.M = None rq.M = None
rq.blocking_reason = 'NO_SPECTRUM' rq.blocking_reason = 'NO_SPECTRUM'
continue
for oms_elem in path_oms:
for this_n, this_m in zip(selected_n, selected_m):
if this_m is not None:
oms_list[oms_elem].assign_spectrum(this_n, this_m)
oms_list[oms_elem].add_service(rq.request_id, nb_wl)
rq.N = selected_n
rq.M = selected_m

View File

@@ -1,7 +1,11 @@
matplotlib>=3.5.1,<4 # matplotlib 3.8 removed support for Python 3.8
networkx>=2.6,<3 matplotlib>=3.7.3,<4
numpy>=1.22.0,<2 # networkx 3.2 removed support for Python 3.8
pandas>=1.3.5,<2 networkx>=3.1,<4
pbr>=5.7.0,<6 # numpy 1.25 removed support for Python 3.8
scipy>=1.7.3,<2 numpy>=1.24.4,<2
pbr>=6.0.0,<7
# scipy 1.11 removed support for Python 3.8
scipy>=1.10.1,<2
# xlrd 2.x removed support for .xlsx, it's only .xls now
xlrd>=1.2.0,<2 xlrd>=1.2.0,<2

View File

@@ -3,7 +3,7 @@ name = gnpy
description-file = README.md description-file = README.md
description-content-type = text/markdown; variant=GFM description-content-type = text/markdown; variant=GFM
author = Telecom Infra Project author = Telecom Infra Project
author-email = jan.kundrat@telecominfraproject.com author-email = jkt@jankundrat.com
license = BSD-3-Clause license = BSD-3-Clause
home-page = https://github.com/Telecominfraproject/oopt-gnpy home-page = https://github.com/Telecominfraproject/oopt-gnpy
project_urls = project_urls =
@@ -22,6 +22,8 @@ classifier =
Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.8
Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10 Programming Language :: Python :: 3.10
Programming Language :: Python :: 3.11
Programming Language :: Python :: 3.12
Programming Language :: Python :: Implementation :: CPython Programming Language :: Python :: Implementation :: CPython
Topic :: Scientific/Engineering Topic :: Scientific/Engineering
Topic :: Scientific/Engineering :: Physics Topic :: Scientific/Engineering :: Physics

View File

@@ -0,0 +1,21 @@
{
"path-request": [
{
"request-id": "0",
"source": "trx Abilene",
"destination": "trx Albany",
"src-tp-id": "trx Abilene",
"dst-tp-id": "trx Albany",
"bidirectional": false,
"path-constraints": {
"te-bandwidth": {
"technology": "flexi-grid",
"trx_type": "Voyager",
"trx_mode": "mode 3",
"spacing": 62500000000.0,
"path_bandwidth": 100000000000.0
}
}
}
]
}

View File

@@ -196,101 +196,101 @@
0.0 0.0
], ],
"dgt": [ "dgt": [
2.714526681131686, 1.0,
2.705443819238505,
2.6947834587664494,
2.6841217449620203,
2.6681935771243177,
2.6521732021128046,
2.630396440815385,
2.602860350286428,
2.5696460593920065,
2.5364027376452056,
2.499446286796604,
2.4587748041127506,
2.414398437185221,
2.3699990328716107,
2.322373696229342,
2.271520771371253,
2.2174389328192197,
2.16337565384239,
2.1183028432496016,
2.082225099873648,
2.055100772005235,
2.0279625371819305,
2.0008103857988204,
1.9736443063300082,
1.9482128147680253,
1.9245345552113182,
1.9026104247588487,
1.8806927939516411,
1.862235672444246,
1.847275503201129,
1.835814081380705,
1.824381436842932,
1.8139629377087627,
1.8045606557581335,
1.7961751115773796,
1.7877868031023945,
1.7793941781790852,
1.7709972329654864,
1.7625959636196327,
1.7541903672600494,
1.7459181197626403,
1.737780757913635,
1.7297783508684146,
1.7217732861435076,
1.7137640932265894,
1.7057507692361864,
1.6918150918099673,
1.6719047669939942,
1.6460167077689267,
1.6201194134191075,
1.5986915141218316,
1.5817353179379183,
1.569199764184379,
1.5566577309558969,
1.545374152761467,
1.5353620432989845,
1.5266220576235803,
1.5178910621476225,
1.5097346239790443,
1.502153039909686,
1.495145456062699,
1.488134243479226,
1.48111939735681,
1.474100442252211,
1.4670307626366115,
1.4599103316162523,
1.45273959485914,
1.445565137158368,
1.4340878115214444,
1.418273806730323,
1.3981208704326855,
1.3779439775587023,
1.3598972673004606,
1.3439818461440451,
1.3301807335621048,
1.316383926863083,
1.3040618749785347,
1.2932153453410835,
1.2838336236692311,
1.2744470198196236,
1.2650555289898042,
1.2556591482982988,
1.2428104897182262,
1.2264996957264114,
1.2067249615595257,
1.1869318618366975,
1.1672278304018044,
1.1476135933863398,
1.1280891949729075,
1.108555289615659,
1.0895983485572227,
1.0712204022764056,
1.0534217504465226,
1.0356155337864215,
1.017807767853702, 1.017807767853702,
1.0 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
] ]
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
response-id,source,destination,path_bandwidth,Pass?,nb of tsp pairs,total cost,transponder-type,transponder-mode,OSNR-0.1nm,SNR-0.1nm,SNR-bandwidth,baud rate (Gbaud),input power (dBm),path,"spectrum (N,M)",reversed path OSNR-0.1nm,reversed path SNR-0.1nm,reversed path SNR-bandwidth response-id,source,destination,path_bandwidth,Pass?,nb of tsp pairs,total cost,transponder-type,transponder-mode,OSNR-0.1nm,SNR-0.1nm,SNR-bandwidth,baud rate (Gbaud),input power (dBm),path,"spectrum (N,M)",reversed path OSNR-0.1nm,reversed path SNR-0.1nm,reversed path SNR-bandwidth
0,trx Lorient_KMA,trx Vannes_KBE,100.0,True,1,1,Voyager,mode 1,30.84,30.84,26.75,32.0,0.0,trx Lorient_KMA | roadm Lorient_KMA | east edfa in Lorient_KMA to Vannes_KBE | fiber (Lorient_KMA → Vannes_KBE)-F055 | west edfa in Vannes_KBE to Lorient_KMA | roadm Vannes_KBE | trx Vannes_KBE,"-284, 4",,, 0,trx Lorient_KMA,trx Vannes_KBE,100.0,True,1,1,Voyager,mode 1,30.84,30.84,26.75,32.0,0.0,trx Lorient_KMA | roadm Lorient_KMA | east edfa in Lorient_KMA to Vannes_KBE | fiber (Lorient_KMA → Vannes_KBE)-F055 | west edfa in Vannes_KBE to Lorient_KMA | roadm Vannes_KBE | trx Vannes_KBE,"[-284], [4]",,,
1,trx Brest_KLA,trx Vannes_KBE,10.0,True,1,1,Voyager,mode 1,22.65,22.11,18.03,32.0,1.0,trx Brest_KLA | roadm Brest_KLA | east edfa in Brest_KLA to Morlaix | fiber (Brest_KLA → Morlaix)-F060 | east fused spans in Morlaix | fiber (Morlaix → Lannion_CAS)-F059 | west edfa in Lannion_CAS to Morlaix | roadm Lannion_CAS | east edfa in Lannion_CAS to Corlay | fiber (Lannion_CAS → Corlay)-F061 | west fused spans in Corlay | fiber (Corlay → Loudeac)-F010 | west fused spans in Loudeac | fiber (Loudeac → Lorient_KMA)-F054 | west edfa in Lorient_KMA to Loudeac | roadm Lorient_KMA | east edfa in Lorient_KMA to Vannes_KBE | fiber (Lorient_KMA → Vannes_KBE)-F055 | west edfa in Vannes_KBE to Lorient_KMA | roadm Vannes_KBE | trx Vannes_KBE,"-276, 4",,, 1,trx Brest_KLA,trx Vannes_KBE,10.0,True,1,1,Voyager,mode 1,22.65,22.11,18.03,32.0,1.0,trx Brest_KLA | roadm Brest_KLA | east edfa in Brest_KLA to Morlaix | fiber (Brest_KLA → Morlaix)-F060 | east fused spans in Morlaix | fiber (Morlaix → Lannion_CAS)-F059 | west edfa in Lannion_CAS to Morlaix | roadm Lannion_CAS | east edfa in Lannion_CAS to Corlay | fiber (Lannion_CAS → Corlay)-F061 | west fused spans in Corlay | fiber (Corlay → Loudeac)-F010 | west fused spans in Loudeac | fiber (Loudeac → Lorient_KMA)-F054 | west edfa in Lorient_KMA to Loudeac | roadm Lorient_KMA | east edfa in Lorient_KMA to Vannes_KBE | fiber (Lorient_KMA → Vannes_KBE)-F055 | west edfa in Vannes_KBE to Lorient_KMA | roadm Vannes_KBE | trx Vannes_KBE,"[-276], [4]",,,
3,trx Lannion_CAS,trx Rennes_STA,60.0,True,1,1,vendorA_trx-type1,mode 1,28.29,25.85,21.77,32.0,1.0,trx Lannion_CAS | roadm Lannion_CAS | east edfa in Lannion_CAS to Stbrieuc | fiber (Lannion_CAS → Stbrieuc)-F056 | east edfa in Stbrieuc to Rennes_STA | fiber (Stbrieuc → Rennes_STA)-F057 | west edfa in Rennes_STA to Stbrieuc | roadm Rennes_STA | trx Rennes_STA,"-284, 4",,, 3,trx Lannion_CAS,trx Rennes_STA,60.0,True,1,1,vendorA_trx-type1,mode 1,28.29,25.85,21.77,32.0,1.0,trx Lannion_CAS | roadm Lannion_CAS | east edfa in Lannion_CAS to Stbrieuc | fiber (Lannion_CAS → Stbrieuc)-F056 | east edfa in Stbrieuc to Rennes_STA | fiber (Stbrieuc → Rennes_STA)-F057 | west edfa in Rennes_STA to Stbrieuc | roadm Rennes_STA | trx Rennes_STA,"[-284], [4]",,,
4,trx Rennes_STA,trx Lannion_CAS,150.0,True,1,1,vendorA_trx-type1,mode 2,22.27,22.15,15.05,64.0,0.0,trx Rennes_STA | roadm Rennes_STA | east edfa in Rennes_STA to Ploermel | fiber (Rennes_STA → Ploermel)- | east edfa in Ploermel to Vannes_KBE | fiber (Ploermel → Vannes_KBE)- | west edfa in Vannes_KBE to Ploermel | roadm Vannes_KBE | east edfa in Vannes_KBE to Lorient_KMA | fiber (Vannes_KBE → Lorient_KMA)-F055 | west edfa in Lorient_KMA to Vannes_KBE | roadm Lorient_KMA | east edfa in Lorient_KMA to Loudeac | fiber (Lorient_KMA → Loudeac)-F054 | east fused spans in Loudeac | fiber (Loudeac → Corlay)-F010 | east fused spans in Corlay | fiber (Corlay → Lannion_CAS)-F061 | west edfa in Lannion_CAS to Corlay | roadm Lannion_CAS | trx Lannion_CAS,"-266, 6",,, 4,trx Rennes_STA,trx Lannion_CAS,150.0,True,1,1,vendorA_trx-type1,mode 2,22.27,22.14,15.05,64.0,0.0,trx Rennes_STA | roadm Rennes_STA | east edfa in Rennes_STA to Ploermel | fiber (Rennes_STA → Ploermel)- | east edfa in Ploermel to Vannes_KBE | fiber (Ploermel → Vannes_KBE)- | west edfa in Vannes_KBE to Ploermel | roadm Vannes_KBE | east edfa in Vannes_KBE to Lorient_KMA | fiber (Vannes_KBE → Lorient_KMA)-F055 | west edfa in Lorient_KMA to Vannes_KBE | roadm Lorient_KMA | east edfa in Lorient_KMA to Loudeac | fiber (Lorient_KMA → Loudeac)-F054 | east fused spans in Loudeac | fiber (Loudeac → Corlay)-F010 | east fused spans in Corlay | fiber (Corlay → Lannion_CAS)-F061 | west edfa in Lannion_CAS to Corlay | roadm Lannion_CAS | trx Lannion_CAS,"[-266], [6]",,,
5,trx Rennes_STA,trx Lannion_CAS,20.0,True,1,1,vendorA_trx-type1,mode 2,30.79,28.77,21.68,64.0,3.0,trx Rennes_STA | roadm Rennes_STA | east edfa in Rennes_STA to Stbrieuc | fiber (Rennes_STA → Stbrieuc)-F057 | west edfa in Stbrieuc to Rennes_STA | fiber (Stbrieuc → Lannion_CAS)-F056 | west edfa in Lannion_CAS to Stbrieuc | roadm Lannion_CAS | trx Lannion_CAS,"-274, 6",,, 5,trx Rennes_STA,trx Lannion_CAS,20.0,True,1,1,vendorA_trx-type1,mode 2,30.79,28.76,21.67,64.0,3.0,trx Rennes_STA | roadm Rennes_STA | east edfa in Rennes_STA to Stbrieuc | fiber (Rennes_STA → Stbrieuc)-F057 | west edfa in Stbrieuc to Rennes_STA | fiber (Stbrieuc → Lannion_CAS)-F056 | west edfa in Lannion_CAS to Stbrieuc | roadm Lannion_CAS | trx Lannion_CAS,"[-274], [6]",,,
6,,,,NO_PATH,,,,,,,,,,,,,, 6,,,,NO_PATH,,,,,,,,,,,,,,
1 response-id source destination path_bandwidth Pass? nb of tsp pairs total cost transponder-type transponder-mode OSNR-0.1nm SNR-0.1nm SNR-bandwidth baud rate (Gbaud) input power (dBm) path spectrum (N,M) reversed path OSNR-0.1nm reversed path SNR-0.1nm reversed path SNR-bandwidth
2 0 trx Lorient_KMA trx Vannes_KBE 100.0 True 1 1 Voyager mode 1 30.84 30.84 26.75 32.0 0.0 trx Lorient_KMA | roadm Lorient_KMA | east edfa in Lorient_KMA to Vannes_KBE | fiber (Lorient_KMA → Vannes_KBE)-F055 | west edfa in Vannes_KBE to Lorient_KMA | roadm Vannes_KBE | trx Vannes_KBE -284, 4 [-284], [4]
3 1 trx Brest_KLA trx Vannes_KBE 10.0 True 1 1 Voyager mode 1 22.65 22.11 18.03 32.0 1.0 trx Brest_KLA | roadm Brest_KLA | east edfa in Brest_KLA to Morlaix | fiber (Brest_KLA → Morlaix)-F060 | east fused spans in Morlaix | fiber (Morlaix → Lannion_CAS)-F059 | west edfa in Lannion_CAS to Morlaix | roadm Lannion_CAS | east edfa in Lannion_CAS to Corlay | fiber (Lannion_CAS → Corlay)-F061 | west fused spans in Corlay | fiber (Corlay → Loudeac)-F010 | west fused spans in Loudeac | fiber (Loudeac → Lorient_KMA)-F054 | west edfa in Lorient_KMA to Loudeac | roadm Lorient_KMA | east edfa in Lorient_KMA to Vannes_KBE | fiber (Lorient_KMA → Vannes_KBE)-F055 | west edfa in Vannes_KBE to Lorient_KMA | roadm Vannes_KBE | trx Vannes_KBE -276, 4 [-276], [4]
4 3 trx Lannion_CAS trx Rennes_STA 60.0 True 1 1 vendorA_trx-type1 mode 1 28.29 25.85 21.77 32.0 1.0 trx Lannion_CAS | roadm Lannion_CAS | east edfa in Lannion_CAS to Stbrieuc | fiber (Lannion_CAS → Stbrieuc)-F056 | east edfa in Stbrieuc to Rennes_STA | fiber (Stbrieuc → Rennes_STA)-F057 | west edfa in Rennes_STA to Stbrieuc | roadm Rennes_STA | trx Rennes_STA -284, 4 [-284], [4]
5 4 trx Rennes_STA trx Lannion_CAS 150.0 True 1 1 vendorA_trx-type1 mode 2 22.27 22.15 22.14 15.05 64.0 0.0 trx Rennes_STA | roadm Rennes_STA | east edfa in Rennes_STA to Ploermel | fiber (Rennes_STA → Ploermel)- | east edfa in Ploermel to Vannes_KBE | fiber (Ploermel → Vannes_KBE)- | west edfa in Vannes_KBE to Ploermel | roadm Vannes_KBE | east edfa in Vannes_KBE to Lorient_KMA | fiber (Vannes_KBE → Lorient_KMA)-F055 | west edfa in Lorient_KMA to Vannes_KBE | roadm Lorient_KMA | east edfa in Lorient_KMA to Loudeac | fiber (Lorient_KMA → Loudeac)-F054 | east fused spans in Loudeac | fiber (Loudeac → Corlay)-F010 | east fused spans in Corlay | fiber (Corlay → Lannion_CAS)-F061 | west edfa in Lannion_CAS to Corlay | roadm Lannion_CAS | trx Lannion_CAS -266, 6 [-266], [6]
6 5 trx Rennes_STA trx Lannion_CAS 20.0 True 1 1 vendorA_trx-type1 mode 2 30.79 28.77 28.76 21.68 21.67 64.0 3.0 trx Rennes_STA | roadm Rennes_STA | east edfa in Rennes_STA to Stbrieuc | fiber (Rennes_STA → Stbrieuc)-F057 | west edfa in Stbrieuc to Rennes_STA | fiber (Stbrieuc → Lannion_CAS)-F056 | west edfa in Lannion_CAS to Stbrieuc | roadm Lannion_CAS | trx Lannion_CAS -274, 6 [-274], [6]
7 6 NO_PATH

View File

@@ -1,97 +1,97 @@
signal,nli signal,nli
1.9952623149688793e-05,1.1158426495504604e-08 1.9952623149688796e-05,1.0570305869494063e-08
1.9952623149688793e-05,1.263949624403159e-08 1.9952623149688796e-05,1.1989102199581664e-08
1.9952623149688793e-05,1.3358478621325285e-08 1.9952623149688796e-05,1.2687787891259665e-08
1.9952623149688793e-05,1.3830775406251184e-08 1.9952623149688796e-05,1.3153676763101585e-08
1.9952623149688793e-05,1.4180462471172083e-08 1.9952623149688796e-05,1.3504001312414315e-08
1.9952623149688793e-05,1.4456701012984246e-08 1.9952623149688796e-05,1.378517965356758e-08
1.9952623149688793e-05,1.4683973899785875e-08 1.9952623149688796e-05,1.4020312829929705e-08
1.9952623149688793e-05,1.487624147046227e-08 1.9952623149688796e-05,1.4222564206194578e-08
1.9952623149688793e-05,1.5042217041806274e-08 1.9952623149688796e-05,1.440014394542033e-08
1.9952623149688793e-05,1.5187703614492153e-08 1.9952623149688796e-05,1.4558516068269932e-08
1.9952623149688793e-05,1.5316759790785317e-08 1.9952623149688796e-05,1.4701499315172012e-08
1.9952623149688793e-05,1.543233485150211e-08 1.9952623149688796e-05,1.4831866587815758e-08
1.9952623149688793e-05,1.553663885878994e-08 1.9952623149688796e-05,1.4951694168451522e-08
1.9952623149688793e-05,1.5631370249579246e-08 1.9952623149688796e-05,1.506257639956634e-08
1.9952623149688793e-05,1.5717862065800704e-08 1.9952623149688796e-05,1.5165763570833366e-08
1.9952623149688793e-05,1.57971793985894e-08 1.9952623149688796e-05,1.5262253772723937e-08
1.9952623149688793e-05,1.5870186356579704e-08 1.9952623149688796e-05,1.535285600134073e-08
1.9952623149688793e-05,1.593759332223716e-08 1.9952623149688796e-05,1.543823467328411e-08
1.9952623149688793e-05,1.5999991070923486e-08 1.9952623149688796e-05,1.551894175425445e-08
1.9952623149688793e-05,1.6057875903450682e-08 1.9952623149688796e-05,1.5595440417063968e-08
1.9952623149688793e-05,1.6111668489205982e-08 1.9952623149688796e-05,1.5668122772822936e-08
1.9952623149688793e-05,1.6161728217386366e-08 1.9952623149688796e-05,1.5737323370281063e-08
1.9952623149688793e-05,1.6208364281630228e-08 1.9952623149688796e-05,1.5803329618444796e-08
1.9952623149688793e-05,1.6251844350226973e-08 1.9952623149688796e-05,1.5866389935670908e-08
1.9952623149688793e-05,1.629240142540359e-08 1.9952623149688796e-05,1.592672019391794e-08
1.9952623149688793e-05,1.6330239326114482e-08 1.9952623149688796e-05,1.598450886742589e-08
1.9952623149688793e-05,1.6365537111728e-08 1.9952623149688796e-05,1.6039921184766554e-08
1.9952623149688793e-05,1.6398452681655655e-08 1.9952623149688796e-05,1.609310250559421e-08
1.9952623149688793e-05,1.642912572715412e-08 1.9952623149688796e-05,1.61441810880001e-08
1.9952623149688793e-05,1.6457680168940455e-08 1.9952623149688796e-05,1.6193270372246937e-08
1.9952623149688793e-05,1.6484226183026747e-08 1.9952623149688796e-05,1.6240470877236143e-08
1.9952623149688793e-05,1.6508861894003893e-08 1.9952623149688796e-05,1.6285871784230113e-08
1.9952623149688793e-05,1.6531674797617433e-08 1.9952623149688796e-05,1.6329552265978812e-08
1.9952623149688793e-05,1.655274296130114e-08 1.9952623149688796e-05,1.6371582606990462e-08
1.9952623149688793e-05,1.657213604125123e-08 1.9952623149688796e-05,1.641202515119326e-08
1.9952623149688793e-05,1.6589916146838222e-08 1.9952623149688796e-05,1.6450935105904177e-08
1.9952623149688793e-05,1.660613857708963e-08 1.9952623149688796e-05,1.6488361225310858e-08
1.9952623149688793e-05,1.6620852449214096e-08 1.9952623149688796e-05,1.6524346392188574e-08
1.9952623149688793e-05,1.6634101235366932e-08 1.9952623149688796e-05,1.6558928113022246e-08
1.9952623149688793e-05,1.664592322084737e-08 1.9952623149688796e-05,1.6592138938867027e-08
1.9952623149688793e-05,1.6656351894496074e-08 1.9952623149688796e-05,1.6624006821997905e-08
1.9952623149688793e-05,1.666541628009631e-08 1.9952623149688796e-05,1.665455541654349e-08
1.9952623149688793e-05,1.6673141215973025e-08 1.9952623149688796e-05,1.668380432977811e-08
1.9952623149688793e-05,1.6679547588653583e-08 1.9952623149688796e-05,1.6711769329485368e-08
1.9952623149688793e-05,1.6684652525341145e-08 1.9952623149688796e-05,1.6738462511750264e-08
1.9952623149688793e-05,1.668846954900963e-08 1.9952623149688796e-05,1.6763892432637406e-08
1.9952623149688793e-05,1.66910086991187e-08 1.9952623149688796e-05,1.6788064206436675e-08
1.9952623149688793e-05,1.6692276620238304e-08 1.9952623149688796e-05,1.681097957247311e-08
1.9952623149688793e-05,1.6692276620238304e-08 1.9952623149688796e-05,1.6832636931862217e-08
1.9952623149688793e-05,1.6691008699118703e-08 1.9952623149688796e-05,1.6853031355021186e-08
1.9952623149688793e-05,1.6688469549009633e-08 1.9952623149688796e-05,1.687215456020574e-08
1.9952623149688793e-05,1.6684652525341148e-08 1.9952623149688796e-05,1.688999486281053e-08
1.9952623149688793e-05,1.6679547588653586e-08 1.9952623149688796e-05,1.690653709463382e-08
1.9952623149688793e-05,1.6673141215973028e-08 1.9952623149688796e-05,1.6921762491746848e-08
1.9952623149688793e-05,1.666541628009631e-08 1.9952623149688796e-05,1.6935648549006222e-08
1.9952623149688793e-05,1.6656351894496084e-08 1.9952623149688796e-05,1.6948168838584662e-08
1.9952623149688793e-05,1.6645923220847374e-08 1.9952623149688796e-05,1.695929278914847e-08
1.9952623149688793e-05,1.6634101235366935e-08 1.9952623149688796e-05,1.696898542145055e-08
1.9952623149688793e-05,1.66208524492141e-08 1.9952623149688796e-05,1.6977207035104874e-08
1.9952623149688793e-05,1.6606138577089633e-08 1.9952623149688796e-05,1.6983912840119302e-08
1.9952623149688793e-05,1.6589916146838225e-08 1.9952623149688796e-05,1.6989052525338295e-08
1.9952623149688793e-05,1.6572136041251237e-08 1.9952623149688796e-05,1.699256975421989e-08
1.9952623149688793e-05,1.6552742961301146e-08 1.9952623149688796e-05,1.6994401576260005e-08
1.9952623149688793e-05,1.653167479761744e-08 1.9952623149688796e-05,1.6994477739772384e-08
1.9952623149688793e-05,1.6508861894003893e-08 1.9952623149688796e-05,1.699271988849318e-08
1.9952623149688793e-05,1.648422618302675e-08 1.9952623149688796e-05,1.6989040620420942e-08
1.9952623149688793e-05,1.645768016894046e-08 1.9952623149688796e-05,1.6983342382173362e-08
1.9952623149688793e-05,1.6429125727154126e-08 1.9952623149688796e-05,1.6975516165613388e-08
1.9952623149688793e-05,1.6398452681655658e-08 1.9952623149688796e-05,1.6965439965112504e-08
1.9952623149688793e-05,1.6365537111728004e-08 1.9952623149688796e-05,1.6952976942961452e-08
1.9952623149688793e-05,1.6330239326114482e-08 1.9952623149688796e-05,1.693797323625088e-08
1.9952623149688793e-05,1.6292401425403594e-08 1.9952623149688796e-05,1.6920255319826076e-08
1.9952623149688793e-05,1.6251844350226973e-08 1.9952623149688796e-05,1.6899626814970685e-08
1.9952623149688793e-05,1.6208364281630228e-08 1.9952623149688796e-05,1.6875864599859146e-08
1.9952623149688793e-05,1.616172821738637e-08 1.9952623149688796e-05,1.6848714031984708e-08
1.9952623149688793e-05,1.6111668489205982e-08 1.9952623149688796e-05,1.6817883029489423e-08
1.9952623149688793e-05,1.605787590345069e-08 1.9952623149688796e-05,1.6783034669737056e-08
1.9952623149688793e-05,1.5999991070923493e-08 1.9952623149688796e-05,1.674377783759437e-08
1.9952623149688793e-05,1.5937593322237167e-08 1.9952623149688796e-05,1.669965527407164e-08
1.9952623149688793e-05,1.5870186356579704e-08 1.9952623149688796e-05,1.6650128108596616e-08
1.9952623149688793e-05,1.5797179398589402e-08 1.9952623149688796e-05,1.6594555557112625e-08
1.9952623149688793e-05,1.571786206580071e-08 1.9952623149688796e-05,1.6532167853144137e-08
1.9952623149688793e-05,1.5631370249579252e-08 1.9952623149688796e-05,1.6462029512327026e-08
1.9952623149688793e-05,1.5536638858789946e-08 1.9952623149688796e-05,1.6382988469074245e-08
1.9952623149688793e-05,1.5432334851502114e-08 1.9952623149688796e-05,1.6293604020234886e-08
1.9952623149688793e-05,1.531675979078532e-08 1.9952623149688796e-05,1.619204201130206e-08
1.9952623149688793e-05,1.5187703614492156e-08 1.9952623149688796e-05,1.607591759753518e-08
1.9952623149688793e-05,1.5042217041806274e-08 1.9952623149688796e-05,1.5942050594874486e-08
1.9952623149688793e-05,1.4876241470462273e-08 1.9952623149688796e-05,1.578606776895102e-08
1.9952623149688793e-05,1.4683973899785879e-08 1.9952623149688796e-05,1.5601720601345105e-08
1.9952623149688793e-05,1.4456701012984246e-08 1.9952623149688796e-05,1.5379633197361104e-08
1.9952623149688793e-05,1.4180462471172086e-08 1.9952623149688796e-05,1.5104793671989548e-08
1.9952623149688793e-05,1.3830775406251184e-08 1.9952623149688796e-05,1.4750892345803154e-08
1.9952623149688793e-05,1.3358478621325285e-08 1.9952623149688796e-05,1.4265134295425351e-08
1.9952623149688793e-05,1.2639496244031593e-08 1.9952623149688796e-05,1.3514359541675816e-08
1.9952623149688793e-05,1.1158426495504613e-08 1.9952623149688796e-05,1.194579997186553e-08
1 signal nli
2 1.9952623149688793e-05 1.9952623149688796e-05 1.1158426495504604e-08 1.0570305869494063e-08
3 1.9952623149688793e-05 1.9952623149688796e-05 1.263949624403159e-08 1.1989102199581664e-08
4 1.9952623149688793e-05 1.9952623149688796e-05 1.3358478621325285e-08 1.2687787891259665e-08
5 1.9952623149688793e-05 1.9952623149688796e-05 1.3830775406251184e-08 1.3153676763101585e-08
6 1.9952623149688793e-05 1.9952623149688796e-05 1.4180462471172083e-08 1.3504001312414315e-08
7 1.9952623149688793e-05 1.9952623149688796e-05 1.4456701012984246e-08 1.378517965356758e-08
8 1.9952623149688793e-05 1.9952623149688796e-05 1.4683973899785875e-08 1.4020312829929705e-08
9 1.9952623149688793e-05 1.9952623149688796e-05 1.487624147046227e-08 1.4222564206194578e-08
10 1.9952623149688793e-05 1.9952623149688796e-05 1.5042217041806274e-08 1.440014394542033e-08
11 1.9952623149688793e-05 1.9952623149688796e-05 1.5187703614492153e-08 1.4558516068269932e-08
12 1.9952623149688793e-05 1.9952623149688796e-05 1.5316759790785317e-08 1.4701499315172012e-08
13 1.9952623149688793e-05 1.9952623149688796e-05 1.543233485150211e-08 1.4831866587815758e-08
14 1.9952623149688793e-05 1.9952623149688796e-05 1.553663885878994e-08 1.4951694168451522e-08
15 1.9952623149688793e-05 1.9952623149688796e-05 1.5631370249579246e-08 1.506257639956634e-08
16 1.9952623149688793e-05 1.9952623149688796e-05 1.5717862065800704e-08 1.5165763570833366e-08
17 1.9952623149688793e-05 1.9952623149688796e-05 1.57971793985894e-08 1.5262253772723937e-08
18 1.9952623149688793e-05 1.9952623149688796e-05 1.5870186356579704e-08 1.535285600134073e-08
19 1.9952623149688793e-05 1.9952623149688796e-05 1.593759332223716e-08 1.543823467328411e-08
20 1.9952623149688793e-05 1.9952623149688796e-05 1.5999991070923486e-08 1.551894175425445e-08
21 1.9952623149688793e-05 1.9952623149688796e-05 1.6057875903450682e-08 1.5595440417063968e-08
22 1.9952623149688793e-05 1.9952623149688796e-05 1.6111668489205982e-08 1.5668122772822936e-08
23 1.9952623149688793e-05 1.9952623149688796e-05 1.6161728217386366e-08 1.5737323370281063e-08
24 1.9952623149688793e-05 1.9952623149688796e-05 1.6208364281630228e-08 1.5803329618444796e-08
25 1.9952623149688793e-05 1.9952623149688796e-05 1.6251844350226973e-08 1.5866389935670908e-08
26 1.9952623149688793e-05 1.9952623149688796e-05 1.629240142540359e-08 1.592672019391794e-08
27 1.9952623149688793e-05 1.9952623149688796e-05 1.6330239326114482e-08 1.598450886742589e-08
28 1.9952623149688793e-05 1.9952623149688796e-05 1.6365537111728e-08 1.6039921184766554e-08
29 1.9952623149688793e-05 1.9952623149688796e-05 1.6398452681655655e-08 1.609310250559421e-08
30 1.9952623149688793e-05 1.9952623149688796e-05 1.642912572715412e-08 1.61441810880001e-08
31 1.9952623149688793e-05 1.9952623149688796e-05 1.6457680168940455e-08 1.6193270372246937e-08
32 1.9952623149688793e-05 1.9952623149688796e-05 1.6484226183026747e-08 1.6240470877236143e-08
33 1.9952623149688793e-05 1.9952623149688796e-05 1.6508861894003893e-08 1.6285871784230113e-08
34 1.9952623149688793e-05 1.9952623149688796e-05 1.6531674797617433e-08 1.6329552265978812e-08
35 1.9952623149688793e-05 1.9952623149688796e-05 1.655274296130114e-08 1.6371582606990462e-08
36 1.9952623149688793e-05 1.9952623149688796e-05 1.657213604125123e-08 1.641202515119326e-08
37 1.9952623149688793e-05 1.9952623149688796e-05 1.6589916146838222e-08 1.6450935105904177e-08
38 1.9952623149688793e-05 1.9952623149688796e-05 1.660613857708963e-08 1.6488361225310858e-08
39 1.9952623149688793e-05 1.9952623149688796e-05 1.6620852449214096e-08 1.6524346392188574e-08
40 1.9952623149688793e-05 1.9952623149688796e-05 1.6634101235366932e-08 1.6558928113022246e-08
41 1.9952623149688793e-05 1.9952623149688796e-05 1.664592322084737e-08 1.6592138938867027e-08
42 1.9952623149688793e-05 1.9952623149688796e-05 1.6656351894496074e-08 1.6624006821997905e-08
43 1.9952623149688793e-05 1.9952623149688796e-05 1.666541628009631e-08 1.665455541654349e-08
44 1.9952623149688793e-05 1.9952623149688796e-05 1.6673141215973025e-08 1.668380432977811e-08
45 1.9952623149688793e-05 1.9952623149688796e-05 1.6679547588653583e-08 1.6711769329485368e-08
46 1.9952623149688793e-05 1.9952623149688796e-05 1.6684652525341145e-08 1.6738462511750264e-08
47 1.9952623149688793e-05 1.9952623149688796e-05 1.668846954900963e-08 1.6763892432637406e-08
48 1.9952623149688793e-05 1.9952623149688796e-05 1.66910086991187e-08 1.6788064206436675e-08
49 1.9952623149688793e-05 1.9952623149688796e-05 1.6692276620238304e-08 1.681097957247311e-08
50 1.9952623149688793e-05 1.9952623149688796e-05 1.6692276620238304e-08 1.6832636931862217e-08
51 1.9952623149688793e-05 1.9952623149688796e-05 1.6691008699118703e-08 1.6853031355021186e-08
52 1.9952623149688793e-05 1.9952623149688796e-05 1.6688469549009633e-08 1.687215456020574e-08
53 1.9952623149688793e-05 1.9952623149688796e-05 1.6684652525341148e-08 1.688999486281053e-08
54 1.9952623149688793e-05 1.9952623149688796e-05 1.6679547588653586e-08 1.690653709463382e-08
55 1.9952623149688793e-05 1.9952623149688796e-05 1.6673141215973028e-08 1.6921762491746848e-08
56 1.9952623149688793e-05 1.9952623149688796e-05 1.666541628009631e-08 1.6935648549006222e-08
57 1.9952623149688793e-05 1.9952623149688796e-05 1.6656351894496084e-08 1.6948168838584662e-08
58 1.9952623149688793e-05 1.9952623149688796e-05 1.6645923220847374e-08 1.695929278914847e-08
59 1.9952623149688793e-05 1.9952623149688796e-05 1.6634101235366935e-08 1.696898542145055e-08
60 1.9952623149688793e-05 1.9952623149688796e-05 1.66208524492141e-08 1.6977207035104874e-08
61 1.9952623149688793e-05 1.9952623149688796e-05 1.6606138577089633e-08 1.6983912840119302e-08
62 1.9952623149688793e-05 1.9952623149688796e-05 1.6589916146838225e-08 1.6989052525338295e-08
63 1.9952623149688793e-05 1.9952623149688796e-05 1.6572136041251237e-08 1.699256975421989e-08
64 1.9952623149688793e-05 1.9952623149688796e-05 1.6552742961301146e-08 1.6994401576260005e-08
65 1.9952623149688793e-05 1.9952623149688796e-05 1.653167479761744e-08 1.6994477739772384e-08
66 1.9952623149688793e-05 1.9952623149688796e-05 1.6508861894003893e-08 1.699271988849318e-08
67 1.9952623149688793e-05 1.9952623149688796e-05 1.648422618302675e-08 1.6989040620420942e-08
68 1.9952623149688793e-05 1.9952623149688796e-05 1.645768016894046e-08 1.6983342382173362e-08
69 1.9952623149688793e-05 1.9952623149688796e-05 1.6429125727154126e-08 1.6975516165613388e-08
70 1.9952623149688793e-05 1.9952623149688796e-05 1.6398452681655658e-08 1.6965439965112504e-08
71 1.9952623149688793e-05 1.9952623149688796e-05 1.6365537111728004e-08 1.6952976942961452e-08
72 1.9952623149688793e-05 1.9952623149688796e-05 1.6330239326114482e-08 1.693797323625088e-08
73 1.9952623149688793e-05 1.9952623149688796e-05 1.6292401425403594e-08 1.6920255319826076e-08
74 1.9952623149688793e-05 1.9952623149688796e-05 1.6251844350226973e-08 1.6899626814970685e-08
75 1.9952623149688793e-05 1.9952623149688796e-05 1.6208364281630228e-08 1.6875864599859146e-08
76 1.9952623149688793e-05 1.9952623149688796e-05 1.616172821738637e-08 1.6848714031984708e-08
77 1.9952623149688793e-05 1.9952623149688796e-05 1.6111668489205982e-08 1.6817883029489423e-08
78 1.9952623149688793e-05 1.9952623149688796e-05 1.605787590345069e-08 1.6783034669737056e-08
79 1.9952623149688793e-05 1.9952623149688796e-05 1.5999991070923493e-08 1.674377783759437e-08
80 1.9952623149688793e-05 1.9952623149688796e-05 1.5937593322237167e-08 1.669965527407164e-08
81 1.9952623149688793e-05 1.9952623149688796e-05 1.5870186356579704e-08 1.6650128108596616e-08
82 1.9952623149688793e-05 1.9952623149688796e-05 1.5797179398589402e-08 1.6594555557112625e-08
83 1.9952623149688793e-05 1.9952623149688796e-05 1.571786206580071e-08 1.6532167853144137e-08
84 1.9952623149688793e-05 1.9952623149688796e-05 1.5631370249579252e-08 1.6462029512327026e-08
85 1.9952623149688793e-05 1.9952623149688796e-05 1.5536638858789946e-08 1.6382988469074245e-08
86 1.9952623149688793e-05 1.9952623149688796e-05 1.5432334851502114e-08 1.6293604020234886e-08
87 1.9952623149688793e-05 1.9952623149688796e-05 1.531675979078532e-08 1.619204201130206e-08
88 1.9952623149688793e-05 1.9952623149688796e-05 1.5187703614492156e-08 1.607591759753518e-08
89 1.9952623149688793e-05 1.9952623149688796e-05 1.5042217041806274e-08 1.5942050594874486e-08
90 1.9952623149688793e-05 1.9952623149688796e-05 1.4876241470462273e-08 1.578606776895102e-08
91 1.9952623149688793e-05 1.9952623149688796e-05 1.4683973899785879e-08 1.5601720601345105e-08
92 1.9952623149688793e-05 1.9952623149688796e-05 1.4456701012984246e-08 1.5379633197361104e-08
93 1.9952623149688793e-05 1.9952623149688796e-05 1.4180462471172086e-08 1.5104793671989548e-08
94 1.9952623149688793e-05 1.9952623149688796e-05 1.3830775406251184e-08 1.4750892345803154e-08
95 1.9952623149688793e-05 1.9952623149688796e-05 1.3358478621325285e-08 1.4265134295425351e-08
96 1.9952623149688793e-05 1.9952623149688796e-05 1.2639496244031593e-08 1.3514359541675816e-08
97 1.9952623149688793e-05 1.9952623149688796e-05 1.1158426495504613e-08 1.194579997186553e-08

View File

@@ -1,6 +1,6 @@
signal,nli signal,nli
1.9952623149688793e-05,5.522326183599433e-09 1.9952623149688796e-05,5.183134799604202e-09
1.7957360834719913e-05,4.5606601423111315e-09 1.7957360834719913e-05,4.286200408629989e-09
2.593841009459543e-05,6.633717697038881e-09 2.593841009459543e-05,6.2510001955285065e-09
1.5962098519751036e-05,4.3237017878447286e-09 1.5962098519751036e-05,4.082332034495425e-09
2.3943147779626553e-05,8.311382502260195e-09 2.3943147779626556e-05,7.857762167195498e-09
1 signal nli
2 1.9952623149688793e-05 1.9952623149688796e-05 5.522326183599433e-09 5.183134799604202e-09
3 1.7957360834719913e-05 4.5606601423111315e-09 4.286200408629989e-09
4 2.593841009459543e-05 6.633717697038881e-09 6.2510001955285065e-09
5 1.5962098519751036e-05 4.3237017878447286e-09 4.082332034495425e-09
6 2.3943147779626553e-05 2.3943147779626556e-05 8.311382502260195e-09 7.857762167195498e-09

View File

@@ -0,0 +1,809 @@
{
"network_name": "Example Network - long path",
"elements": [{
"uid": "Site_A",
"type": "Transceiver",
"metadata": {
"location": {
"city": "Site A",
"region": "",
"latitude": 0,
"longitude": 0
}
}
},
{
"uid": "roadm Site A",
"metadata": {
"location": {
"city": "Site A",
"region": "RLD",
"latitude": 0.0,
"longitude": 0.0
}
},
"type": "Roadm"
},
{
"uid": "booster A",
"type": "Edfa",
"type_variety": "std_medium_gain",
"operational": {
"gain_target": 16,
"tilt_target": 0
},
"metadata": {
"location": {
"region": "",
"latitude": 0,
"longitude": 0
}
}
},
{
"uid": "Span1",
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 80,
"loss_coef": 0.2,
"length_units": "km"
},
"metadata": {
"location": {
"region": "",
"latitude": 1,
"longitude": 0
}
}
},
{
"uid": "Edfa1",
"type": "Edfa",
"type_variety": "test",
"operational": {
"gain_target": 16,
"tilt_target": 0
},
"metadata": {
"location": {
"region": "",
"latitude": 2,
"longitude": 0
}
}
},
{
"uid": "Span2",
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 80,
"loss_coef": 0.2,
"length_units": "km"
},
"metadata": {
"location": {
"region": "",
"latitude": 1,
"longitude": 0
}
}
},
{
"uid": "Edfa2",
"type": "Edfa",
"type_variety": "test_fixed_gain",
"operational": {
"gain_target": 16,
"tilt_target": 0
},
"metadata": {
"location": {
"region": "",
"latitude": 2,
"longitude": 0
}
}
},
{
"uid": "Span3",
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 80,
"loss_coef": 0.2,
"length_units": "km"
},
"metadata": {
"location": {
"region": "",
"latitude": 1,
"longitude": 0
}
}
},
{
"uid": "Edfa3",
"type": "Edfa",
"type_variety": "test",
"operational": {
"gain_target": 16,
"tilt_target": 0
},
"metadata": {
"location": {
"region": "",
"latitude": 2,
"longitude": 0
}
}
},
{
"uid": "Span4",
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 80,
"loss_coef": 0.2,
"length_units": "km"
},
"metadata": {
"location": {
"region": "",
"latitude": 1,
"longitude": 0
}
}
},
{
"uid": "Edfa4",
"type": "Edfa",
"type_variety": "test_fixed_gain",
"operational": {
"gain_target": 16,
"tilt_target": 0
},
"metadata": {
"location": {
"region": "",
"latitude": 2,
"longitude": 0
}
}
},
{
"uid": "Span5",
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 80,
"loss_coef": 0.2,
"length_units": "km"
},
"metadata": {
"location": {
"region": "",
"latitude": 1,
"longitude": 0
}
}
},
{
"uid": "Edfa5",
"type": "Edfa",
"type_variety": "test",
"operational": {
"gain_target": 16,
"tilt_target": 0
},
"metadata": {
"location": {
"region": "",
"latitude": 2,
"longitude": 0
}
}
},
{
"uid": "roadm Site C",
"metadata": {
"location": {
"city": "Site A",
"region": "RLD",
"latitude": 0.0,
"longitude": 0.0
}
},
"type": "Roadm"
},
{
"uid": "booster C",
"type": "Edfa",
"type_variety": "std_medium_gain",
"operational": {
"gain_target": 16,
"tilt_target": 0
},
"metadata": {
"location": {
"region": "",
"latitude": 0,
"longitude": 0
}
}
},
{
"uid": "Span6",
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 80,
"loss_coef": 0.2,
"length_units": "km"
},
"metadata": {
"location": {
"region": "",
"latitude": 1,
"longitude": 0
}
}
},
{
"uid": "Edfa6",
"type": "Edfa",
"type_variety": "test_fixed_gain",
"operational": {
"gain_target": 16,
"tilt_target": 0
},
"metadata": {
"location": {
"region": "",
"latitude": 2,
"longitude": 0
}
}
},
{
"uid": "Span7",
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 80,
"loss_coef": 0.2,
"length_units": "km"
},
"metadata": {
"location": {
"region": "",
"latitude": 1,
"longitude": 0
}
}
},
{
"uid": "Edfa7",
"type": "Edfa",
"type_variety": "test",
"operational": {
"gain_target": 16,
"tilt_target": 0
},
"metadata": {
"location": {
"region": "",
"latitude": 2,
"longitude": 0
}
}
},
{
"uid": "Span8",
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 80,
"loss_coef": 0.2,
"length_units": "km"
},
"metadata": {
"location": {
"region": "",
"latitude": 1,
"longitude": 0
}
}
},
{
"uid": "Edfa8",
"type": "Edfa",
"type_variety": "test_fixed_gain",
"operational": {
"gain_target": 16,
"tilt_target": 0
},
"metadata": {
"location": {
"region": "",
"latitude": 2,
"longitude": 0
}
}
},
{
"uid": "Span9",
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 80,
"loss_coef": 0.2,
"length_units": "km"
},
"metadata": {
"location": {
"region": "",
"latitude": 1,
"longitude": 0
}
}
},
{
"uid": "Edfa9",
"type": "Edfa",
"type_variety": "test",
"operational": {
"gain_target": 16,
"tilt_target": 0
},
"metadata": {
"location": {
"region": "",
"latitude": 2,
"longitude": 0
}
}
},
{
"uid": "Span10",
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 80,
"loss_coef": 0.2,
"length_units": "km"
},
"metadata": {
"location": {
"region": "",
"latitude": 1,
"longitude": 0
}
}
},
{
"uid": "Edfa10",
"type": "Edfa",
"type_variety": "test_fixed_gain",
"operational": {
"gain_target": 16,
"tilt_target": 0
},
"metadata": {
"location": {
"region": "",
"latitude": 2,
"longitude": 0
}
}
},
{
"uid": "roadm Site D",
"metadata": {
"location": {
"city": "Site A",
"region": "RLD",
"latitude": 0.0,
"longitude": 0.0
}
},
"type": "Roadm"
},
{
"uid": "booster D",
"type": "Edfa",
"type_variety": "std_medium_gain",
"operational": {
"gain_target": 16,
"tilt_target": 0
},
"metadata": {
"location": {
"region": "",
"latitude": 0,
"longitude": 0
}
}
},
{
"uid": "Span11",
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 80,
"loss_coef": 0.2,
"length_units": "km"
},
"metadata": {
"location": {
"region": "",
"latitude": 1,
"longitude": 0
}
}
},
{
"uid": "Edfa11",
"type": "Edfa",
"type_variety": "test",
"operational": {
"gain_target": 16,
"tilt_target": 0
},
"metadata": {
"location": {
"region": "",
"latitude": 2,
"longitude": 0
}
}
},
{
"uid": "Span12",
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 80,
"loss_coef": 0.2,
"length_units": "km"
},
"metadata": {
"location": {
"region": "",
"latitude": 1,
"longitude": 0
}
}
},
{
"uid": "Edfa12",
"type": "Edfa",
"type_variety": "test_fixed_gain",
"operational": {
"gain_target": 16,
"tilt_target": 0
},
"metadata": {
"location": {
"region": "",
"latitude": 2,
"longitude": 0
}
}
},
{
"uid": "roadm Site E",
"metadata": {
"location": {
"city": "Site A",
"region": "RLD",
"latitude": 0.0,
"longitude": 0.0
}
},
"type": "Roadm"
},
{
"uid": "booster E",
"type": "Edfa",
"type_variety": "std_medium_gain",
"operational": {
"gain_target": 16,
"tilt_target": 0
},
"metadata": {
"location": {
"region": "",
"latitude": 0,
"longitude": 0
}
}
},
{
"uid": "Span13",
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 80,
"loss_coef": 0.2,
"length_units": "km"
},
"metadata": {
"location": {
"region": "",
"latitude": 1,
"longitude": 0
}
}
},
{
"uid": "Edfa13",
"type": "Edfa",
"type_variety": "test",
"operational": {
"gain_target": 16,
"tilt_target": 0
},
"metadata": {
"location": {
"region": "",
"latitude": 2,
"longitude": 0
}
}
},
{
"uid": "Span14",
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 80,
"loss_coef": 0.2,
"length_units": "km"
},
"metadata": {
"location": {
"region": "",
"latitude": 1,
"longitude": 0
}
}
},
{
"uid": "Edfa14",
"type": "Edfa",
"type_variety": "test_fixed_gain",
"operational": {
"gain_target": 16,
"tilt_target": 0
},
"metadata": {
"location": {
"region": "",
"latitude": 2,
"longitude": 0
}
}
},
{
"uid": "Span15",
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 80,
"loss_coef": 0.2,
"length_units": "km"
},
"metadata": {
"location": {
"region": "",
"latitude": 1,
"longitude": 0
}
}
},
{
"uid": "Edfa15",
"type": "Edfa",
"type_variety": "test",
"operational": {
"gain_target": 16,
"tilt_target": 0
},
"metadata": {
"location": {
"region": "",
"latitude": 2,
"longitude": 0
}
}
},
{
"uid": "roadm Site B",
"metadata": {
"location": {
"city": "Site B",
"region": "RLD",
"latitude": 0.0,
"longitude": 0.0
}
},
"type": "Roadm"
},
{
"uid": "Site_B",
"type": "Transceiver",
"metadata": {
"location": {
"city": "Site B",
"region": "",
"latitude": 3,
"longitude": 0
}
}
}
],
"connections": [{
"from_node": "Site_A",
"to_node": "roadm Site A"
},
{
"from_node": "roadm Site A",
"to_node": "booster A"
},
{
"from_node": "booster A",
"to_node": "Span1"
},
{
"from_node": "Span1",
"to_node": "Edfa1"
},
{
"from_node": "Edfa1",
"to_node": "Span2"
},
{
"from_node": "Span2",
"to_node": "Edfa2"
},
{
"from_node": "Edfa2",
"to_node": "Span3"
},
{
"from_node": "Span3",
"to_node": "Edfa3"
},
{
"from_node": "Edfa3",
"to_node": "Span4"
},
{
"from_node": "Span4",
"to_node": "Edfa4"
},
{
"from_node": "Edfa4",
"to_node": "Span5"
},
{
"from_node": "Span5",
"to_node": "Edfa5"
},
{
"from_node": "Edfa5",
"to_node": "roadm Site C"
},
{
"from_node": "roadm Site C",
"to_node": "booster C"
},
{
"from_node": "booster C",
"to_node": "Span6"
},
{
"from_node": "Span6",
"to_node": "Edfa6"
},
{
"from_node": "Edfa6",
"to_node": "Span7"
},
{
"from_node": "Span7",
"to_node": "Edfa7"
},
{
"from_node": "Edfa7",
"to_node": "Span8"
},
{
"from_node": "Span8",
"to_node": "Edfa8"
},
{
"from_node": "Edfa8",
"to_node": "Span9"
},
{
"from_node": "Span9",
"to_node": "Edfa9"
},
{
"from_node": "Edfa9",
"to_node": "Span10"
},
{
"from_node": "Span10",
"to_node": "Edfa10"
},
{
"from_node": "Edfa10",
"to_node": "roadm Site D"
},
{
"from_node": "roadm Site D",
"to_node": "booster D"
},
{
"from_node": "booster D",
"to_node": "Span11"
},
{
"from_node": "Span11",
"to_node": "Edfa11"
},
{
"from_node": "Edfa11",
"to_node": "Span12"
},
{
"from_node": "Span12",
"to_node": "Edfa12"
},
{
"from_node": "Edfa12",
"to_node": "roadm Site E"
},
{
"from_node": "roadm Site E",
"to_node": "booster E"
},
{
"from_node": "booster E",
"to_node": "Span13"
},
{
"from_node": "Span13",
"to_node": "Edfa13"
},
{
"from_node": "Edfa13",
"to_node": "Span14"
},
{
"from_node": "Span14",
"to_node": "Edfa14"
},
{
"from_node": "Edfa14",
"to_node": "Span15"
},
{
"from_node": "Span15",
"to_node": "Edfa15"
},
{
"from_node": "Edfa15",
"to_node": "roadm Site B"
},
{
"from_node": "roadm Site B",
"to_node": "Site_B"
}
]
}

View File

@@ -1,96 +1,96 @@
1.000000000000000021e-03,5.915557166626927424e-04,3.840877221245049653e-04,2.466727384040633977e-04,1.573474629975438242e-04,9.994300566924636483e-05,6.331217828438720550e-05,4.004003600460594289e-05,2.529553013238426405e-05 0.001,0.0007537739940510926,0.0005921033539224395,0.000384643453726324,0.00024710943492700773,0.00015765779381207088,0.00010015276356884663,6.345008665672524e-05,4.012925332336102e-05,2.535268958174273e-05
1.000000000000000021e-03,5.910087140881509866e-04,3.835259923737136521e-04,2.462279833344210639e-04,1.570298910751132091e-04,9.972770370845923681e-05,6.317035443958771254e-05,3.994817502675088248e-05,2.523663218966317481e-05 0.001,0.0007532443480762404,0.0005915606741358828,0.00038408573214392957,0.00024666764094038643,0.00015734224135307426,9.993879038586218e-05,6.330912140259024e-05,4.003794165686942e-05,2.529414108865862e-05
1.000000000000000021e-03,5.904624672772724710e-04,3.829653846278134621e-04,2.457842903404500092e-04,1.567131560243821098e-04,9.951300275831494635e-05,6.302894048828063141e-05,3.985658526347281646e-05,2.517791045472703461e-05 0.001,0.0007527148738848327,0.0005910183036445593,0.0003835286706438232,0.0002462265418760313,0.00015702726304657165,9.972523988324127e-05,6.316844848796591e-05,3.994682503096186e-05,2.5235719950422228e-05
1.000000000000000021e-03,5.899169734839467818e-04,3.824058950962419133e-04,2.453416557234028707e-04,1.563972548287988369e-04,9.929890059644241613e-05,6.288793488850426760e-05,3.976526568300959219e-05,2.511936425240675192e-05 0.001,0.0007521855703345118,0.0005904762413907948,0.00038297226807207136,0.0002457861365766504,0.00015671285789580896,9.9512111295817e-05,6.302806736731544e-05,3.985590307420444e-05,2.5177425921282973e-05
1.000000000000000021e-03,5.893722299298780965e-04,3.818475199355363483e-04,2.449000757332959262e-04,1.560821844312877747e-04,9.908539497140619857e-05,6.274733607851797545e-05,3.967421524053715842e-05,2.506099289905929403e-05 0.001,0.0007516564362539944,0.0005899344862777934,0.00038241652320864807,0.0002453464238190796,0.00015639902485083639,9.929940381972637e-05,6.288797746852316e-05,3.976517539750482e-05,2.511925874398998e-05
1.000000000000000021e-03,5.888282338048204554e-04,3.812902552499899305e-04,2.444595465697163919e-04,1.557679417349789946e-04,9.887248360327203632e-05,6.260714247720703990e-05,3.958343287844485109e-05,2.500279570274922987e-05 0.001,0.0007511274704431355,0.0005893930371697809,0.0003818614347679428,0.0002449074023149522,0.00015608576280913723,9.908711661290977e-05,6.27481781932559e-05,3.967464159435973e-05,2.5061218149955632e-05
1.000000000000000021e-03,5.882849822668304897e-04,3.807340970923119234e-04,2.440200643826254091e-04,1.554545236039297650e-04,9.866016418416755746e-05,6.246735248448248958e-05,3.949291752660743311e-05,2.494477196342878550e-05 0.001,0.0007505986716729718,0.0005888518928921378,0.00038130700139925517,0.0002444690707113658,0.00015577307061625246,9.887524879560432e-05,6.260866891731864e-05,3.958430124109855e-05,2.5003303859417958e-05
1.000000000000000021e-03,5.877403241312353140e-04,3.801768826891299322e-04,2.435799392795756472e-04,1.551407333476893054e-04,9.844762961169771281e-05,6.232743618144160702e-05,3.940232665622856909e-05,2.488670234861411131e-05 0.001,0.0007500678710880661,0.0005883088511431218,0.000380751009486411,0.0002440296996901373,0.00015545972380501664,9.866297459432463e-05,6.246890748950651e-05,3.949380391318895e-05,2.4945291488462056e-05
1.000000000000000021e-03,5.871942634186000593e-04,3.796186190022559433e-04,2.431391779090945110e-04,1.548265761463755335e-04,9.823488356157069126e-05,6.218739605181586088e-05,3.931166190013138108e-05,2.482858791458364441e-05 0.001,0.0007495350705096461,0.0005877639154939723,0.000380193466563788,0.00024358929686534952,0.00015514572847430736,9.8450298405315e-05,6.232889690863924e-05,3.9403151593579556e-05,2.4887182324516918e-05
1.000000000000000021e-03,5.866468041173980141e-04,3.790593129257516128e-04,2.426977868451053722e-04,1.545120571165502460e-04,9.802192966180839372e-05,6.204723454596646772e-05,3.922092486871354988e-05,2.477042970290643410e-05 0.001,0.0007490002717484986,0.0005872170894971442,0.00037963438011605534,0.00024314786979147204,0.00015483109067004745,9.823722458416644e-05,6.218864014470764e-05,3.931234624568946e-05,2.4828977642138712e-05
1.000000000000000021e-03,5.860979501842715923e-04,3.784989712866057847e-04,2.422557725877665796e-04,1.541971813119806349e-04,9.780877149334107738e-05,6.190695408131255699e-05,3.913011715023943305e-05,2.471222874063606835e-05 0.001,0.0007484634766050366,0.000586668376686434,0.0003790737575785661,0.00024270542596389042,0.0001545158163857142,9.802375744622405e-05,6.204814013916893e-05,3.9221389813611975e-05,2.4770678703146694e-05
1.000000000000000021e-03,5.855428054911818777e-04,3.779325362214322600e-04,2.418091152720060536e-04,1.538790714407033914e-04,9.759345536126727376e-05,6.176526646718061210e-05,3.903840385562048950e-05,2.465344951928800295e-05 0.001,0.0007479199274773811,0.0005861128912299699,0.0003785065486556895,0.00024225795000622747,0.0001541970308568484,9.780794472023814e-05,6.190610951865765e-05,3.9129447888412384e-05,2.471175028700643e-05
1.000000000000000021e-03,5.849813875456967485e-04,3.773600382625630725e-04,2.413578451141304101e-04,1.535577517356502032e-04,9.737599881379701964e-05,6.162218372343696363e-05,3.894579295722817337e-05,2.459409722576532997e-05 0.001,0.0007473696306726699,0.0005855506450602122,0.0003779327791658341,0.00024180546890527417,0.0001538747562360148,9.758980264023896e-05,6.176255947727244e-05,3.903652792388679e-05,2.4652197254708885e-05
1.000000000000000021e-03,5.844137140093277807e-04,3.767815081401627831e-04,2.409019924922280132e-04,1.532332465435331354e-04,9.715641947446165209e-05,6.147771791853056712e-05,3.885229245840823961e-05,2.453417706661341544e-05 0.001,0.0007468125926679213,0.0005849816503235855,0.0003773524752207052,0.00024134800990073543,0.00015354901486124996,9.736934756691086e-05,6.161750129261558e-05,3.8942637427869684e-05,2.459202450185328e-05
1.000000000000000021e-03,5.838398026969793654e-04,3.761969767804803125e-04,2.404415879440078890e-04,1.529055803229076760e-04,9.693473504062415536e-05,6.133188116843621776e-05,3.875791039276530608e-05,2.447369426754818325e-05 0.001,0.0007462488201102061,0.0005844059193804029,0.00037676566322402907,0.00024088560048334876,0.0001532198292542639,9.714659598616437e-05,6.147094632476142e-05,3.884778396152801e-05,2.4531236958179027e-05
1.000000000000000021e-03,5.832596715764015120e-04,3.756064753041117783e-04,2.399766621646476654e-04,1.525747776422469490e-04,9.671096328199675835e-05,6.118468563560254894e-05,3.866265482344967213e-05,2.441265407298631344e-05 0.001,0.0007456783198168171,0.0005838234648047683,0.00037617236987025305,0.00024041826839299018,0.00015288722211863548,9.692156450770277e-05,6.132290601522212e-05,3.875197513865345e-05,2.4469839587096592e-05
1.000000000000000021e-03,5.826733387676383139e-04,3.750100350242446291e-04,2.395072460046293692e-04,1.522408631780071723e-04,9.648512203915507620e-05,6.103614352789890607e-05,3.856653384244465896e-05,2.435106174557538284e-05 0.001,0.0007451010987754332,0.0005832342993844907,0.0003755726221432343,0.0002399460416167659,0.00015255121633799497,9.66942698635831e-05,6.11733918859104e-05,3.8655218624953314e-05,2.4407837385217267e-05
1.000000000000000021e-03,5.820810441807425326e-04,3.744079089136845458e-04,2.390335428197917333e-04,1.519039834472631588e-04,9.625731118926498641e-05,6.088632085792882825e-05,3.846959029618343478e-05,2.428894479270876788e-05 0.001,0.0007445173992825126,0.0005826386743528757,0.00037496668540476865,0.00023946913369259697,0.00015221196586566552,9.646481704279825e-05,6.102247334575324e-05,3.85575594785277e-05,2.4345259282747418e-05
1.000000000000000021e-03,5.814828054675655030e-04,3.738001274474016776e-04,2.385555825972570808e-04,1.515641624143126585e-04,9.602754804766522702e-05,6.073522946956701240e-05,3.837183203343020677e-05,2.422630831805138899e-05 0.001,0.0007439272282773631,0.0005820366023339485,0.0003743545861363169,0.00023898757201912962,0.00015186949307274757,9.623322238874437e-05,6.0870161643097905e-05,3.845900518061352e-05,2.4282110155051444e-05
1.000000000000000021e-03,5.808786404289665358e-04,3.731867212872194738e-04,2.380733954737781241e-04,1.512214241469207320e-04,9.579584999731260704e-05,6.058288124990010364e-05,3.827326693032387752e-05,2.416315744255338838e-05 0.001,0.0007433305928659832,0.0005814280961601982,0.00037373635109929905,0.0002385013842326201,0.0001515238205025659,9.599950236146117e-05,6.071646810276464e-05,3.835956326175255e-05,2.4218394908993806e-05
1.000000000000000021e-03,5.802685670142343878e-04,3.725677212800349654e-04,2.375870117335689917e-04,1.508757928143868079e-04,9.556223448729982074e-05,6.042928812817623899e-05,3.817390288966712009e-05,2.409949730398197492e-05 0.001,0.0007427275003211868,0.0005808131688724332,0.0003731120073337174,0.00023801059820498021,0.0001511749708688244,9.576367353617374e-05,6.05614041249978e-05,3.825924130107498e-05,2.4154118482464792e-05
1.000000000000000021e-03,5.796526968519212725e-04,3.719432545624587992e-04,2.370965379259533010e-04,1.505273470495264228e-04,9.532675589286383365e-05,6.027448635812982831e-05,3.807376356963088358e-05,2.403534314190221437e-05 0.001,0.0007421180800523362,0.0005801919587229117,0.00037248171070273063,0.0002375153439047009,0.00015082303982525373,9.55258019540184e-05,6.0405013700224733e-05,3.815806798909622e-05,2.4089299350133826e-05
1.000000000000000021e-03,5.790310479093865609e-04,3.713133518665244839e-04,2.366020041460938778e-04,1.501761108339581341e-04,9.508943151110322721e-05,6.011848775803337427e-05,3.797285679655886708e-05,2.397070004317041725e-05 0.001,0.0007415023395254894,0.0005795644789202474,0.00037184548827748576,0.0002370156491221818,0.00015046804996987382,9.528590408468248e-05,6.0247308147258e-05,3.8056050847170796e-05,2.4023942410771268e-05
1.000000000000000021e-03,5.784036383121742876e-04,3.706780441238009577e-04,2.361034406501071276e-04,1.498221082613785163e-04,9.485027871279472060e-05,5.996130419345521918e-05,3.787119042685209972e-05,2.390557311366359151e-05 0.001,0.0007408802863797739,0.000578930742889133,0.00037120336741830446,0.00023651154189285886,0.00015011002407818366,9.504399651802114e-05,6.008829886368558e-05,3.7953197447440844e-05,2.395805259559495e-05
1.000000000000000021e-03,5.777704863433433301e-04,3.700373624633735868e-04,2.356008778526011383e-04,1.494653635353745394e-04,9.460931494071504256e-05,5.980294757607067669e-05,3.776877234616485572e-05,2.383996747774973522e-05 0.001,0.0007402519284274773,0.00057829076427012,0.0003705553757730914,0.00023600305049498863,0.0001497489851010917,9.480009596242987e-05,5.992799732470356e-05,3.784951541204015e-05,2.389163486774317e-05
1.000000000000000021e-03,5.771316104427772061e-04,3.693913382097967039e-04,2.350943463241932639e-04,1.491059009672212558e-04,9.436655770795449559e-05,5.964342986246977532e-05,3.766561046859827219e-05,2.377388827775711285e-05 0.001,0.0007396172736541335,0.0005776445569193926,0.0003699015412757306,0.000235490203447419,0.00014938495616282697,9.455421924320194e-05,5.976641508193571e-05,3.774501241228877e-05,2.38246942217421e-05
1.000000000000000021e-03,5.764870292064976651e-04,3.687400028810397501e-04,2.345838767890191692e-04,1.487437449736715462e-04,9.412202459622686095e-05,5.948276305296108525e-05,3.756171273589169023e-05,2.370734067344167480e-05 0.001,0.0007389763302186035,0.0005769921349085269,0.00036924189214444916,0.00023497302950733012,0.00014901796055883247,9.4306383300876e-05,5.960356376224896e-05,3.763969616788547e-05,2.37572356829714e-05
1.000000000000000021e-03,5.758375946234993610e-04,3.680842155919215072e-04,2.340701414876563216e-04,1.483793719498717782e-04,9.387603703510192111e-05,5.932115823520561543e-05,3.745721560837426419e-05,2.364041205155829344e-05 0.001,0.000738329973009011,0.0005763343882557762,0.00036857732657886674,0.00023445223185895243,0.00014864849677321228,9.40569245366171e-05,5.943966431343476e-05,3.753370952478887e-05,2.3689350732036766e-05
1.000000000000000021e-03,5.751833223951592329e-04,3.674240032104748388e-04,2.335531666416808738e-04,1.480128027327277474e-04,9.362861002461524574e-05,5.915862564500113025e-05,3.735212585887714390e-05,2.357310681190604310e-05 0.001,0.0007376782088319843,0.0005756713289449496,0.0003679078688863157,0.00023392783529630037,0.00014827658488585004,9.38058575472753e-05,5.927472675087035e-05,3.7427059131368685e-05,2.362104369630353e-05
1.000000000000000021e-03,5.745242283439769499e-04,3.667593927483133397e-04,2.330329785818580578e-04,1.476440582313571256e-04,9.337975861033522300e-05,5.899517554647101613e-05,3.724645027783519551e-05,2.350542936525477225e-05 0.001,0.0007370210446325295,0.0005750029691304239,0.000367233543593211,0.00023339986479263558,0.00014790224510292775,9.355319701349314e-05,5.910876114408311e-05,3.7319751670569666e-05,2.3552318925085614e-05
1.000000000000000021e-03,5.738603284130473379e-04,3.660904113590355527e-04,2.325096037462197861e-04,1.472731594253864234e-04,9.312949788206356194e-05,5.883081823114703288e-05,3.714019567266727830e-05,2.343738413293735195e-05 0.001,0.0007363584874940915,0.0005743293211369546,0.0003665543754437431,0.00023286834549865966,0.00014752549775524457,9.329895769838934e-05,5.8941777615809794e-05,3.721179385927125e-05,2.348318078922229e-05
1.000000000000000021e-03,5.731917314000997948e-04,3.654171810067180655e-04,2.319831433530600859e-04,1.469001805571756218e-04,9.287787898176902846e-05,5.866558771451522606e-05,3.703338420706373603e-05,2.336898537810763873e-05 0.001,0.0007356906659117175,0.0005736505214206793,0.00036587051603697917,0.00023233340267585003,0.00014714643450378646,9.30432026577021e-05,5.8773818072131705e-05,3.710321298927822e-05,2.3413646846771747e-05
1.000000000000000021e-03,5.725184531760584700e-04,3.647397285916569422e-04,2.314536235223777264e-04,1.465251423190001693e-04,9.262491677678542706e-05,5.849949412959568328e-05,3.692602258076439168e-05,2.330023745100291859e-05 0.001,0.0007350175870680764,0.0005729665823498456,0.00036518198995355594,0.00023179506120909636,0.00014676507541963834,9.278594644638945e-05,5.8604892484780656e-05,3.699401567385024e-05,2.3343721399750524e-05
1.000000000000000021e-03,5.718405097346714646e-04,3.640580811583470273e-04,2.309210704829702432e-04,1.461480654746279682e-04,9.237062617930094123e-05,5.833254763720848617e-05,3.681811751074023914e-05,2.323114471257928647e-05 0.001,0.000734339258284937,0.0005722775164633901,0.0003644888219905243,0.00023125334615855053,0.0001463814406964208,9.252720370024704e-05,5.8435010877524154e-05,3.688420855938328e-05,2.327340877117354e-05
1.000000000000000021e-03,5.711579171919053044e-04,3.633722658937428313e-04,2.303855105703487465e-04,1.457689708574830614e-04,9.211502214495855044e-05,5.816475842498649012e-05,3.670967573052717390e-05,2.316171153407365905e-05 0.001,0.0007336556870231954,0.0005715833364706749,0.00036379103715988533,0.00023070828275766533,0.00014599555064848363,9.226698913450141e-05,5.82641833251609e-05,3.677379832472749e-05,2.320271330460301e-05
1.000000000000000021e-03,5.704706917853448337e-04,3.626823101255147543e-04,2.298469702246577707e-04,1.453878793688169360e-04,9.185811967146480901e-05,5.799613670639434487e-05,3.660070398956385041e-05,2.309194229656875218e-05 0.001,0.0007329668808828947,0.0005708840552512191,0.00036308866068712113,0.00023015989641122435,0.00014560742570909416,9.200531754239911e-05,5.8092419952513674e-05,3.666279168050168e-05,2.313163936369656e-05
1.000000000000000021e-03,5.697788498735841109e-04,3.619882413202942504e-04,2.293054759885765847e-04,1.450048119758659754e-04,9.159993379718755254e-05,5.782669271974067121e-05,3.649120905252569737e-05,2.302184139055488024e-05 0.001,0.000732272847603227,0.0005701796858544125,0.000362381718009681,0.0002296082126933358,0.00014521708642859763,9.174220379377606e-05,5.791973093340874e-05,3.6551195368400524e-05,2.3060191331749373e-05
1.000000000000000021e-03,5.690839249361781711e-04,3.612915831986411477e-04,2.287622092282637863e-04,1.446206010588695675e-04,9.134102410651873409e-05,5.765679311500335815e-05,3.638142760462866287e-05,2.295156024783083523e-05 0.001,0.0007315751779154508,0.0005694718366517781,0.00036167180797618383,0.00022905447155647377,0.00014482540661409508,9.147823538482221e-05,5.774650123146614e-05,3.643925790598459e-05,2.2988528215049473e-05
1.000000000000000021e-03,5.683859273133331363e-04,3.605923537461036641e-04,2.282171874164802170e-04,1.442352604283837097e-04,9.108140050118301682e-05,5.748644463023418617e-05,3.627136409615889481e-05,2.288110175599186700e-05 0.001,0.0007308738763564251,0.0005687605159526348,0.00036095894758939165,0.00022849869020493823,0.00014443240010265552,9.121342232553745e-05,5.7572737692798364e-05,3.6326983828340116e-05,2.2916652961499898e-05
1.000000000000000021e-03,5.676848674169825831e-04,3.598905710243090802e-04,2.276704280772651710e-04,1.438488039249314222e-04,9.082107289971861372e-05,5.731565401294060850e-05,3.616102298282374168e-05,2.281046880581413228e-05 0.001,0.0007301689475478705,0.0005680457321686527,0.00036024315397386176,0.00022794088593578913,0.00014403808079282816,9.094777466478586e-05,5.739844718775089e-05,3.6214377685641065e-05,2.2844568528419092e-05
1.000000000000000021e-03,5.669807557304629327e-04,3.591862531699841626e-04,2.271219487847658911e-04,1.434612454179789358e-04,9.056005123670258442e-05,5.714442801953895405e-05,3.605040872538299508e-05,2.273966429101268041e-05 0.001,0.0007294603961963875,0.0005673274938137002,0.0003595244443750873,0.00022738107613769066,0.00014364246264358423,9.068130248947494e-05,5.72236366103174e-05,3.610144404275241e-05,2.2772277882278848e-05
1.000000000000000021e-03,5.662756696284717943e-04,3.584815135619230891e-04,2.265734124911083147e-04,1.430737675597642188e-04,9.029913524493678829e-05,5.697329258726415482e-05,3.593986162522089478e-05,2.266890625682277028e-05 0.001,0.0007287502876018436,0.0005666079096289159,0.00035880496633647314,0.00022682095171468864,0.00014324674865159545,9.041481948469436e-05,5.7048841153261715e-05,3.598852922211342e-05,2.270000293927642e-05
1.000000000000000021e-03,5.655696121370722921e-04,3.577763576655677066e-04,2.260248242651153531e-04,1.426863741861267136e-04,9.003832758694041048e-05,5.680224948786493348e-05,3.582938283523433764e-05,2.259819544408493697e-05 0.001,0.0007280386231103084,0.0005658869826353605,0.0003580847262718071,0.00022626051891339797,0.00014285094367250402,9.014832907727154e-05,5.687406312117876e-05,3.587563473352017e-05,2.2627744673782604e-05
1.000000000000000021e-03,5.648625863181645518e-04,3.570707909872514684e-04,2.254761892066869196e-04,1.422990691538204475e-04,8.977763093872482745e-05,5.663130050166089515e-05,3.571897351373497692e-05,2.252753259705453904e-05 0.001,0.0007273254041056322,0.0005651647158992671,0.00035736373064750184,0.00022569978402038908,0.00014245505258865028,8.988183471111395e-05,5.669930482943582e-05,3.5762762093538084e-05,2.2555504064421286e-05
1.000000000000000021e-03,5.641545952693012783e-04,3.563648190736888295e-04,2.249275124461922067e-04,1.419118563399853763e-04,8.951704798938974166e-05,5.646044741725799208e-05,3.560863482425828067e-05,2.245691846327665519e-05 0.001,0.0007266106320094578,0.0005644411125319691,0.00035664198598218,0.00022513875336164715,0.0001420590803085807,8.961533984682783e-05,5.652456860390248e-05,3.564991282531874e-05,2.2483282093948716e-05
1.000000000000000021e-03,5.634456421235028989e-04,3.556584475114634488e-04,2.243787991438712611e-04,1.415247396416227112e-04,8.925658144072659398e-05,5.628969203126926030e-05,3.549836793537420297e-05,2.238635379346144160e-05 0.001,0.000725894308281204,0.0005637161756897977,0.0003559194988462394,0.00022457743330201225,0.00014166303176654256,8.934884796133105e-05,5.634985678067539e-05,3.5537088458413665e-05,2.2411079749130865e-05
1.000000000000000021e-03,5.627357300490819225e-04,3.549516819265270164e-04,2.238300544892383743e-04,1.411377229750731741e-04,8.899623400682166435e-05,5.611903614803531905e-05,3.538817402049950172e-05,2.231583934136070575e-05 0.001,0.0007251764344180624,0.0005629899085739927,0.00035519627586142176,0.0002240158302446243,0.00014126691192198565,8.90823625474685e-05,5.6175171705805915e-05,3.542429052859005e-05,2.233889802062196e-05
1.000000000000000021e-03,5.620265745740795878e-04,3.542462045793823072e-04,2.232825718355581747e-04,1.407517127660701999e-04,8.873661298955798349e-05,5.594887683102661642e-05,3.527830905094599801e-05,2.224553873809700179e-05 0.001,0.0007244588135748975,0.0005622641246704724,0.00035447409591105305,0.0002234553120905153,0.00014087167955905718,8.881652603390643e-05,5.600093342830372e-05,3.531178983274928e-05,2.2266910019981595e-05
1.000000000000000021e-03,5.613181716914067464e-04,3.535420099674467737e-04,2.227363458317740963e-04,1.403667046661989041e-04,8.847771519474716161e-05,5.577921186868756777e-05,3.516877154903826080e-05,2.217545101761858074e-05 0.001,0.000723741443178776,0.000561538821268995,0.0003537529553873339,0.00022289587522719752,0.00014047733166655684,8.855133617099835e-05,5.5827140373801375e-05,3.519958531186087e-05,2.219511505192651e-05
1.000000000000000021e-03,5.606105174362018646e-04,3.528390926567629869e-04,2.221913711948466166e-04,1.399826943822104249e-04,8.821953746856249804e-05,5.561003907731979445e-05,3.505956005567386572e-05,2.210557522599888898e-05 0.001,0.0007230243206833482,0.0005608139956950427,0.00035303285074046774,0.00022233751609917817,0.00014008386527925162,8.82867907426191e-05,5.565379099102327e-05,3.508767592227262e-05,2.212351243120618e-05
1.000000000000000021e-03,5.599036078855734169e-04,3.521374472813410678e-04,2.216476427089692435e-04,1.395996776753266513e-04,8.796207669700402236e-05,5.544135630070159596e-05,3.495067313006486022e-05,2.203591042126611129e-05 0.001,0.0007223074435688039,0.0005600896453097011,0.0003523137784782074,0.00022178023120736695,0.00013969127747733319,8.802288756574066e-05,5.5480883751481105e-05,3.4976060635503277e-05,2.2052101482465692e-05
1.000000000000000021e-03,5.591992581819900257e-04,3.514388991464684675e-04,2.211065862108586844e-04,1.392186639199167455e-04,8.770601346645835294e-05,5.527361030479937100e-05,3.484239951455165907e-05,2.196664147854661471e-05 0.001,0.0007215926247557181,0.0005593676122940626,0.00035159759247597197,0.00022122546934306127,0.00013930059415776796,8.776031848020719e-05,5.5308872854303e-05,3.486503301641155e-05,2.198107017600086e-05
1.000000000000000021e-03,5.584974577369657654e-04,3.507434317312190116e-04,2.205681855748304113e-04,1.388396401724235928e-04,8.745133837595373525e-05,5.510679463338290224e-05,3.473473491875524963e-05,2.189776560286087024e-05 0.001,0.0007208798585848073,0.0005586478889723664,0.0003508842795507963,0.0002206732171528304,0.00013891180440309996,8.749907547557891e-05,5.513775276548628e-05,3.475458937431628e-05,2.1910416102241813e-05
1.000000000000000021e-03,5.577981960279812567e-04,3.500510286412654524e-04,2.200324248112712805e-04,1.384625936044855835e-04,8.719804211084999142e-05,5.494090289064881491e-05,3.462767509292537455e-05,2.182928002589032757e-05 0.001,0.0007201691394257483,0.000557930467712979,0.00035017382661216696,0.00022012346138632064,0.00013852489738482468,8.723915060881119e-05,5.49675179985075e-05,3.464472605058592e-05,2.184013687270143e-05
1.000000000000000021e-03,5.571014625980537805e-04,3.493616736077873519e-04,2.194992880653100025e-04,1.380875115017372141e-04,8.694611544190507637e-05,5.477592874055209164e-05,3.452121582748434684e-05,2.176118200567564087e-05 0.001,0.0007194604616770773,0.00055721534092818,0.00034946622066134466,0.00021957618889536463,0.00013813986236255893,8.698053600359808e-05,5.4798163113848986e-05,3.453543941831367e-05,2.177023011975932e-05
1.000000000000000021e-03,5.564072470552914543e-04,3.486753504863699662e-04,2.189687596154907018e-04,1.377143812626113696e-04,8.669554922434540153e-05,5.461186590614181566e-05,3.441535295257522900e-05,2.169346882631773742e-05 0.001,0.0007187538197660722,0.0005565025010739346,0.00034876144879066544,0.00021903138663308575,0.0001377566886832086,8.672322384971475e-05,5.462968271852315e-05,3.442672588199151e-05,2.1700693496445714e-05
1.000000000000000021e-03,5.557155390724777657e-04,3.479920432559456848e-04,2.184408238724854000e-04,1.373431903971786034e-04,8.644633439696230146e-05,5.444870816891464747e-05,3.431008233762035268e-05,2.162613779768559453e-05 0.001,0.0007180492081486484,0.0005557919406496801,0.00034805949818288173,0.0002184890416530366,0.00013737536578016266,8.646720640237894e-05,5.446207146561145e-05,3.431858187719449e-05,2.1631524676231647e-05
1.000000000000000021e-03,5.550282308874212147e-04,3.473135853761227104e-04,2.179168797741835634e-04,1.369749146289257855e-04,8.619912270820690987e-05,5.428688083545962664e-05,3.420567782931384528e-05,2.155936384410790980e-05 0.001,0.000717348639431565,0.0005550856739198547,0.00034736232071304855,0.00021795064331956514,0.00013699693247692832,8.621317757037385e-05,5.429578217858938e-05,3.421129897003673e-05,2.1562909902755936e-05
1.000000000000000021e-03,5.543453044039096641e-04,3.466399489498413807e-04,2.173969005859271932e-04,1.366095327799803094e-04,8.595389890905566596e-05,5.412637349122350694e-05,3.410213253115887156e-05,2.149314248283782383e-05 0.001,0.0007166521035756881,0.0005543836868927082,0.0003466698924934393,0.00021741616794755068,0.00013662136971116798,8.596112351100096e-05,5.413080535731451e-05,3.410487085131832e-05,2.1494845067789903e-05
1.000000000000000021e-03,5.536667416543260278e-04,3.459711063207645686e-04,2.168808598269340415e-04,1.362470238846985658e-04,8.571064790824490891e-05,5.396717583150281386e-05,3.399943962027434491e-05,2.142746927933548718e-05 0.001,0.0007159595906065037,0.0005536859656730149,0.00034598218983055497,0.0002168855920630381,0.0001362486585998701,8.571103051605296e-05,5.396713159578493e-05,3.399929127512844e-05,2.142732610463052e-05
1.000000000000000021e-03,5.529925247987736454e-04,3.453070300711248903e-04,2.163687312677279435e-04,1.358873671873677324e-04,8.546935477049620155e-05,5.380927766017944798e-05,3.389759234653519571e-05,2.136233984669994517e-05 0.001,0.0007152710906138687,0.0005529924964615861,0.00034529918922366796,0.00021635889240138666,0.0001358787804376394,8.546288501047042e-05,5.380475158117202e-05,3.389455405818364e-05,2.1360348987661796e-05
1.000000000000000021e-03,5.523242123557685823e-04,3.446492679875326503e-04,2.158617145497228296e-04,1.355314077800207832e-04,8.523058755788532964e-05,5.365305115434923267e-05,3.379683095199963850e-05,2.129790788796336886e-05 0.001,0.0007145881681833736,0.0005523048607339887,0.0003446224616264519,0.00021583728670966556,0.00013551259312919557,8.521726369129195e-05,5.364404315662281e-05,3.379090310339315e-05,2.129406976339983e-05
1.000000000000000021e-03,5.516617811459008413e-04,3.439977838203789025e-04,2.153597748770509342e-04,1.351791181086447731e-04,8.499432644189092710e-05,5.349848277838686991e-05,3.369714647650299112e-05,2.123416758034315385e-05 0.001,0.0007139108109389651,0.0005516230407004492,0.0003439519758859039,0.00021532074399295122,0.00013515007172518374,8.497414844816332e-05,5.3484993898260945e-05,3.368833016244125e-05,2.122848306212633e-05
1.000000000000000021e-03,5.510052081904127453e-04,3.433525416882428740e-04,2.148628778379304833e-04,1.348304709382760146e-04,8.476055183025699440e-05,5.334555916079864168e-05,3.359853006971443923e-05,2.117111317291617240e-05 0.001,0.0007132390066148024,0.0005509470187317473,0.00034328770115903844,0.00021480923358720733,0.0001347911915544671,8.473352137819455e-05,5.3327591526929936e-05,3.358682708410006e-05,2.1163583577742056e-05
1.000000000000000021e-03,5.503544707098636342e-04,3.427135060745518090e-04,2.143709894006651793e-04,1.344854393494213974e-04,8.452924436422564868e-05,5.319426709225049006e-05,3.350097298979682009e-05,2.110873898573355285e-05 0.001,0.0007125727430549207,0.0005502767773585094,0.000342629606910633,0.00021430272515636744,0.0001344359282214269,8.449536478383494e-05,5.317182390666476e-05,3.348638581318404e-05,2.109936606707349e-05
1.000000000000000021e-03,5.497095461228062706e-04,3.420806418242862412e-04,2.138840759097000895e-04,1.341439967345312348e-04,8.430038491581448882e-05,5.304459352362807473e-05,3.340446660208796169e-05,2.104703940894962140e-05 0.001,0.0007119120082129148,0.0005496122992705212,0.0003419776629110174,0.0002138011886894788,0.00013408425760331254,8.425966117078749e-05,5.3017679043188334e-05,3.3386998389521964e-05,2.1035825349191292e-05
1.000000000000000021e-03,5.490704120444732210e-04,3.414539141407250565e-04,2.134021040817290626e-04,1.338061167945246396e-04,8.407395458513211085e-05,5.289652556412503305e-05,3.330900237780223545e-05,2.098600890196449472e-05 0.001,0.000711256790151613,0.0005489535673160376,0.0003413318392338714,0.00021330459449785352,0.00013373615584760944,8.40263932459383e-05,5.286514508242194e-05,3.3288656946938245e-05,2.0972956304734848e-05
1.000000000000000021e-03,5.484371298422446297e-04,3.408333692467681113e-04,2.129251024270059081e-04,1.334718163299163942e-04,8.384996326436759272e-05,5.275006911363530105e-05,3.321458388816914869e-05,2.092564965374723430e-05 0.001,0.0007106071943639499,0.0005483006816957998,0.00034069221933208274,0.0002128129992904075,0.00013339165932644894,8.379558393280961e-05,5.271423641048183e-05,3.31913705135711e-05,2.091076460544407e-05
1.000000000000000021e-03,5.478096771889333057e-04,3.402189725469309967e-04,2.124530379214265854e-04,1.331410692793207290e-04,8.362839223924152716e-05,5.260521141428185532e-05,3.312120269498457291e-05,2.086595618361951373e-05 0.001,0.000709963208882901,0.0005476536252143895,0.0003400587732671483,0.0002123263734210078,0.00013305074425072359,8.356721599784782e-05,5.256494122003263e-05,3.3095131256746724e-05,2.0849245154782437e-05
1.000000000000000021e-03,5.471880319478338028e-04,3.396106897916775086e-04,2.119858778995733334e-04,1.328138498781884043e-04,8.340922301478033581e-05,5.246193986031627375e-05,3.302885046175365648e-05,2.080692307740899109e-05 0.001,0.0007093248218486061,0.0005470123808316875,0.00033943147139689077,0.0002118446875576196,0.00013271338709432742,8.334127240311385e-05,5.241724783997488e-05,3.299993143509595e-05,2.0788392916005465e-05
1.000000000000000021e-03,5.465721721714859958e-04,3.390084870743713592e-04,2.115235900510876890e-04,1.324901326555763298e-04,8.319243731282516567e-05,5.232024199634728476e-05,3.293751895248773966e-05,2.074854498665493433e-05 0.001,0.0007086920215080653,0.0005463769316622218,0.0003388102843733889,0.00021136791267964032,0.0001323795645916927,8.311773630434548e-05,5.2271144734051514e-05,3.290576339760186e-05,2.07282029115292e-05
1.000000000000000021e-03,5.459629241404544706e-04,3.384131725428774743e-04,2.110667946787101129e-04,1.321703518944146796e-04,8.297832591380873519e-05,5.218030786215170435e-05,3.284733064718059383e-05,2.069090019482566404e-05 0.001,0.0007080656480431051,0.0005457481216341828,0.0003381960373995552,0.00021089668206097172,0.0001320497200486003,8.289690449717853e-05,5.2126825862102536e-05,3.2812752146082854e-05,2.0668755034757233e-05
1.000000000000000021e-03,5.453602635114507746e-04,3.378247083723790616e-04,2.106154557101209946e-04,1.318544791589579420e-04,8.276686841524559784e-05,5.204212355675735553e-05,3.275827635494999894e-05,2.063398273378693265e-05 0.001,0.0007074456886869565,0.0005451259321489777,0.0003375886977799707,0.0002104309633113142,0.00013172382748945162,8.26787581753205e-05,5.198427834496719e-05,3.2720889139431744e-05,2.061004372929991e-05
1.000000000000000021e-03,5.447641661727002649e-04,3.372430571518834691e-04,2.101695374983407439e-04,1.315424863636820575e-04,8.255804467261116894e-05,5.190567535780167048e-05,3.267034700418964161e-05,2.057778671334094953e-05 0.001,0.0007068321308093747,0.0005445103448031184,0.0003369882331820464,0.00020997072442018424,0.00013140186125447996,8.246327876643199e-05,5.18434894660219e-05,3.2630165945308436e-05,2.055206350992823e-05
1.000000000000000021e-03,5.441746082424759419e-04,3.366681818805845774e-04,2.097290048174083239e-04,1.312343457694375884e-04,8.235183479637930588e-05,5.177094971942625129e-05,3.258353364113958107e-05,2.052230632028256941e-05 0.001,0.0007062249619162967,0.0005439013413874698,0.00033639461163356655,0.00020951593375373114,0.00013108379599680725,8.225044792981545e-05,5.170444666951808e-05,3.254057423900392e-05,2.0494808961820763e-05
1.000000000000000021e-03,5.435915660676414983e-04,3.361000459642789163e-04,2.092938228581225045e-04,1.309300299796617602e-04,8.214821914910500468e-05,5.163793327020207291e-05,3.249782742847867687e-05,2.046753581747058517e-05 0.001,0.00070562416964951,0.0005432989038865089,0.00033580780152024723,0.000209066560051587,0.00013076960667953474,8.204024755412909e-05,5.156713755893784e-05,3.2452105802317056e-05,2.0438274739819433e-05
1.000000000000000021e-03,5.430150162222109568e-04,3.355386132118161487e-04,2.088639572238308215e-04,1.306295119366350911e-04,8.194717834254394587e-05,5.150661281108238069e-05,3.241321964393507540e-05,2.041346954291065543e-05 0.001,0.0007050297417863318,0.0005427030144775926,0.0003352277715833316,0.00020862257242375786,0.00013045926857287288,8.183265975513502e-05,5.143154989537623e-05,3.236475252244954e-05,2.038245556769746e-05
1.000000000000000021e-03,5.424450181544462771e-04,3.349839271155603902e-04,2.084394340599780252e-04,1.303328067075743425e-04,8.174872108664715700e-05,5.137699346328779477e-05,3.232971335519106785e-05,2.036010936323692981e-05 0.001,0.0007044417829621171,0.000542113771820027,0.0003346546023905152,0.00020818402485557293,0.00013015281596227648,8.162770599537212e-05,5.129769708700084e-05,3.227852278867728e-05,2.032735670561579e-05
1.000000000000000021e-03,5.418815485793469040e-04,3.344359518126675877e-04,2.080202193468776877e-04,1.300398875631312602e-04,8.155282824274543232e-05,5.124906220377890154e-05,3.224729995882103797e-05,2.030744969463951815e-05 0.001,0.0007038602809995153,0.0005415311581470623,0.00033408826282687573,0.00020775088664703998,0.00012985022429639665,8.142536853201701e-05,5.116556699709043e-05,3.219340855821242e-05,2.0272972923816322e-05
1.000000000000000021e-03,5.413245844265015877e-04,3.338946518213946552e-04,2.076062794549138172e-04,1.297507280942760690e-04,8.135948090770286575e-05,5.112280617242197348e-05,3.216597096011364272e-05,2.025548502431296445e-05 0.001,0.0007032852238493367,0.0005409551558747416,0.0003335287221154158,0.00020732312745044945,0.00012955146931603386,8.122562983828357e-05,5.103514763884953e-05,3.2109401888525124e-05,2.0219299058105656e-05
1.000000000000000021e-03,5.407741028387587183e-04,3.333599920378552692e-04,2.071975811406991498e-04,1.294653022088876294e-04,8.116866041129419294e-05,5.099821267012491396e-05,3.208571797180734118e-05,2.020420990962221080e-05 0.001,0.0007027165995902542,0.0005403857476012292,0.00033297594981485264,0.00020690071726752732,0.0001292565270515082,8.102847260135871e-05,5.090642717392409e-05,3.202649493632917e-05,2.0166330009182866e-05
1.000000000000000021e-03,5.402303025747014556e-04,3.328321561526745862e-04,2.067942601549091974e-04,1.291837026153304184e-04,8.098042783792958120e-05,5.087532120941394917e-05,3.200656629292941073e-05,2.015364045325785942e-05 0.001,0.0007021546252265139,0.0005398231466905069,0.00033243014325207994,0.00020648380199548492,0.0001289654971719027,8.083396250547584e-05,5.077944809587575e-05,3.194471491165552e-05,2.0114083097018264e-05
1.000000000000000021e-03,5.396931605409548225e-04,3.323111087173311550e-04,2.063962829591101838e-04,1.289059030082810651e-04,8.079476437365657295e-05,5.075411899733799342e-05,3.192850747587867838e-05,2.010377117411100997e-05 0.001,0.0007015992888126556,0.0005392673356287205,0.0003318912717105927,0.00020607235137144977,0.0001286783555062261,8.06420820982489e-05,5.065419847368218e-05,3.186405391103787e-05,2.006255318369691e-05
1.000000000000000021e-03,5.391626538584482192e-04,3.317968146613820609e-04,2.060036164003212873e-04,1.286318773981824648e-04,8.061165143636152362e-05,5.063459340114707095e-05,3.185153317990099749e-05,2.005459666083220688e-05 0.001,0.0007010505785332368,0.0005387182970867077,0.00033135930481238495,0.00020566633548374424,0.0001283950781739038,8.04528141416734e-05,5.053066652493675e-05,3.1784504130324826e-05,2.001173519622426e-05
1.000000000000000021e-03,5.386387598611086340e-04,3.312892392892789490e-04,2.056162277072543561e-04,1.283616001079104806e-04,8.043107067321031531e-05,5.051673194647494236e-05,3.177563516985718072e-05,2.000611157101859271e-05 0.001,0.000700508482702546,0.0005381760139193414,0.00033083421251577956,0.00020526572476908743,0.000128115641582197,8.026614161010359e-05,5.040884061439589e-05,3.170605786368809e-05,1.9961624125869314e-05
1.000000000000000021e-03,5.381214560945620949e-04,3.307883482772016118e-04,2.052340844865845515e-04,1.280950457694747437e-04,8.025300395811590449e-05,5.040052231554306949e-05,3.170080531500530551e-05,1.995831063041139523e-05 0.001,0.0006999729897643184,0.0005376404691648787,0.00033031596511327947,0.00020487049000982136,0.00012784002242364822,8.008204768824872e-05,5.028870925253973e-05,3.1628707502639986e-05,1.9912215027513866e-05
1.000000000000000021e-03,5.376107203148404326e-04,3.302941076699326679e-04,2.048571547192701043e-04,1.278321893207613302e-04,8.007743338923888358e-05,5.028595234538581714e-05,3.162703558779804923e-05,1.991118863210237610e-05 0.001,0.0006994440882914515,0.0005371116460443127,0.0003298045332294241,0.0002044806023311588,0.0001275681976735486,7.990051576919067e-05,5.0170261094149856e-05,3.155244553506268e-05,1.9863503019009735e-05
1.000000000000000021e-03,5.371022748594453389e-04,3.298024246812891291e-04,2.044823390252625600e-04,1.275708788891961756e-04,7.990292563076895462e-05,5.017208832604374468e-05,3.155372544493714152e-05,1.986436223028797206e-05 0.001,0.0006989172535560769,0.0005365850419669894,0.000329295612913881,0.00020409280438264766,0.00012729790663346764,7.972004038787022e-05,5.0052515589855926e-05,3.147664135129994e-05,1.9815085586326718e-05
1.000000000000000021e-03,5.365961117498912114e-04,3.293132869081722108e-04,2.041096254707852251e-04,1.273111050031557620e-04,7.972947385597059739e-05,5.005892559260894715e-05,3.148087179640124731e-05,1.981782941609088261e-05 0.001,0.0006983924815322933,0.0005360606511477293,0.0003287891938968759,0.00020370708584067882,0.00012702914094133737,7.954061545150935e-05,4.993546855036179e-05,3.140129216611291e-05,1.9766960914662127e-05
1.000000000000000021e-03,5.360922230056120808e-04,3.288266819633119922e-04,2.037390021489647173e-04,1.270528582181514683e-04,7.955707126027152540e-05,4.994645949643470906e-05,3.140847156340457124e-05,1.977158818812822943e-05 0.001,0.0006978697681747856,0.000535538467781285,0.000328285265898271,0.00020332343638453147,0.00012676189224377013,7.936223487646896e-05,4.981911579385119e-05,3.1326395199731696e-05,1.971912719297887e-05
1.000000000000000021e-03,5.355906006439992324e-04,3.283425974753378354e-04,2.033704571798752555e-04,1.267961291168465381e-04,7.938571106126265876e-05,4.983468540512894492e-05,3.133652167839010846e-05,1.972563655250571181e-05 0.001,0.0006973491094188342,0.0005350184860423863,0.0003277838186277228,0.0002029418456965422,0.0001264961521961901,7.918489258833681e-05,4.970345314604528e-05,3.125194767789152e-05,1.967158261402843e-05
1.000000000000000021e-03,5.350891259362026411e-04,3.278589502113704612e-04,2.030023855884717748e-04,1.265397912200834861e-04,7.921463777328526478e-05,4.972310904903239575e-05,3.126470337114675132e-05,1.967977067875568528e-05 0.001,0.0006968284099289676,0.000534498597351666,0.00032728277956097635,0.00020256071739357045,0.0001262308004979493,7.900783730702533e-05,4.958798911408524e-05,3.1177632631488905e-05,1.9624124503146986e-05
1.000000000000000021e-03,5.345877966909636306e-04,3.273757374134148111e-04,2.026347848040474173e-04,1.262838424862170036e-04,7.904384991646645146e-05,4.961172941171763403e-05,3.119301596587686584e-05,1.963399012641590455e-05 0.001,0.0006963076677967887,0.0005339787996978908,0.00032678214616920946,0.00020218004908417888,0.0001259658352285323,7.883106763041168e-05,4.947272273059253e-05,3.110344941552445e-05,1.957675243920473e-05
1.000000000000000021e-03,5.340866106918126799e-04,3.268929562877650259e-04,2.022676522245876859e-04,1.260282808504260116e-04,7.887334599501782170e-05,4.950054546622813158e-05,3.112145877995456692e-05,1.958829445064508602e-05 0.001,0.0006957868810888677,0.0005334590910383602,0.00032628191587964447,0.00020179983833834103,0.00012570125443876325,7.865458213663353e-05,4.935765301510161e-05,3.102939737649859e-05,1.9529465995615212e-05
1.000000000000000021e-03,5.335855656972701092e-04,3.264106040054970534e-04,2.019009852173301103e-04,1.257731042251948573e-04,7.870312449759831505e-05,4.938955617533215942e-05,3.105003112409614148e-05,1.954268320233478379e-05 0.001,0.0006952660478468047,0.0005329394692990367,0.0003257820860759608,0.00020142008268794192,0.0001254370561512512,7.847837938443003e-05,4.924277897429975e-05,3.0955475852573814e-05,1.94822647404421e-05
1.000000000000000021e-03,5.330846594410641130e-04,3.259286777029715004e-04,2.015347811193284109e-04,1.255183105007985753e-04,7.853318389767883849e-05,4.927876049177821896e-05,3.097873230253197569e-05,1.949715592822227211e-05 0.001,0.00069474516608728,0.0005324199323746772,0.00032528265409871067,0.0002010407796272818,0.0001251732383608348,7.830245791348127e-05,4.91280996022673e-05,3.088168417373684e-05,1.943514823650581e-05
1 1.000000000000000021e-03 0.001 5.915557166626927424e-04 0.0007537739940510926 3.840877221245049653e-04 0.0005921033539224395 2.466727384040633977e-04 0.000384643453726324 1.573474629975438242e-04 0.00024710943492700773 9.994300566924636483e-05 0.00015765779381207088 6.331217828438720550e-05 0.00010015276356884663 4.004003600460594289e-05 6.345008665672524e-05 2.529553013238426405e-05 4.012925332336102e-05 2.535268958174273e-05
2 1.000000000000000021e-03 0.001 5.910087140881509866e-04 0.0007532443480762404 3.835259923737136521e-04 0.0005915606741358828 2.462279833344210639e-04 0.00038408573214392957 1.570298910751132091e-04 0.00024666764094038643 9.972770370845923681e-05 0.00015734224135307426 6.317035443958771254e-05 9.993879038586218e-05 3.994817502675088248e-05 6.330912140259024e-05 2.523663218966317481e-05 4.003794165686942e-05 2.529414108865862e-05
3 1.000000000000000021e-03 0.001 5.904624672772724710e-04 0.0007527148738848327 3.829653846278134621e-04 0.0005910183036445593 2.457842903404500092e-04 0.0003835286706438232 1.567131560243821098e-04 0.0002462265418760313 9.951300275831494635e-05 0.00015702726304657165 6.302894048828063141e-05 9.972523988324127e-05 3.985658526347281646e-05 6.316844848796591e-05 2.517791045472703461e-05 3.994682503096186e-05 2.5235719950422228e-05
4 1.000000000000000021e-03 0.001 5.899169734839467818e-04 0.0007521855703345118 3.824058950962419133e-04 0.0005904762413907948 2.453416557234028707e-04 0.00038297226807207136 1.563972548287988369e-04 0.0002457861365766504 9.929890059644241613e-05 0.00015671285789580896 6.288793488850426760e-05 9.9512111295817e-05 3.976526568300959219e-05 6.302806736731544e-05 2.511936425240675192e-05 3.985590307420444e-05 2.5177425921282973e-05
5 1.000000000000000021e-03 0.001 5.893722299298780965e-04 0.0007516564362539944 3.818475199355363483e-04 0.0005899344862777934 2.449000757332959262e-04 0.00038241652320864807 1.560821844312877747e-04 0.0002453464238190796 9.908539497140619857e-05 0.00015639902485083639 6.274733607851797545e-05 9.929940381972637e-05 3.967421524053715842e-05 6.288797746852316e-05 2.506099289905929403e-05 3.976517539750482e-05 2.511925874398998e-05
6 1.000000000000000021e-03 0.001 5.888282338048204554e-04 0.0007511274704431355 3.812902552499899305e-04 0.0005893930371697809 2.444595465697163919e-04 0.0003818614347679428 1.557679417349789946e-04 0.0002449074023149522 9.887248360327203632e-05 0.00015608576280913723 6.260714247720703990e-05 9.908711661290977e-05 3.958343287844485109e-05 6.27481781932559e-05 2.500279570274922987e-05 3.967464159435973e-05 2.5061218149955632e-05
7 1.000000000000000021e-03 0.001 5.882849822668304897e-04 0.0007505986716729718 3.807340970923119234e-04 0.0005888518928921378 2.440200643826254091e-04 0.00038130700139925517 1.554545236039297650e-04 0.0002444690707113658 9.866016418416755746e-05 0.00015577307061625246 6.246735248448248958e-05 9.887524879560432e-05 3.949291752660743311e-05 6.260866891731864e-05 2.494477196342878550e-05 3.958430124109855e-05 2.5003303859417958e-05
8 1.000000000000000021e-03 0.001 5.877403241312353140e-04 0.0007500678710880661 3.801768826891299322e-04 0.0005883088511431218 2.435799392795756472e-04 0.000380751009486411 1.551407333476893054e-04 0.0002440296996901373 9.844762961169771281e-05 0.00015545972380501664 6.232743618144160702e-05 9.866297459432463e-05 3.940232665622856909e-05 6.246890748950651e-05 2.488670234861411131e-05 3.949380391318895e-05 2.4945291488462056e-05
9 1.000000000000000021e-03 0.001 5.871942634186000593e-04 0.0007495350705096461 3.796186190022559433e-04 0.0005877639154939723 2.431391779090945110e-04 0.000380193466563788 1.548265761463755335e-04 0.00024358929686534952 9.823488356157069126e-05 0.00015514572847430736 6.218739605181586088e-05 9.8450298405315e-05 3.931166190013138108e-05 6.232889690863924e-05 2.482858791458364441e-05 3.9403151593579556e-05 2.4887182324516918e-05
10 1.000000000000000021e-03 0.001 5.866468041173980141e-04 0.0007490002717484986 3.790593129257516128e-04 0.0005872170894971442 2.426977868451053722e-04 0.00037963438011605534 1.545120571165502460e-04 0.00024314786979147204 9.802192966180839372e-05 0.00015483109067004745 6.204723454596646772e-05 9.823722458416644e-05 3.922092486871354988e-05 6.218864014470764e-05 2.477042970290643410e-05 3.931234624568946e-05 2.4828977642138712e-05
11 1.000000000000000021e-03 0.001 5.860979501842715923e-04 0.0007484634766050366 3.784989712866057847e-04 0.000586668376686434 2.422557725877665796e-04 0.0003790737575785661 1.541971813119806349e-04 0.00024270542596389042 9.780877149334107738e-05 0.0001545158163857142 6.190695408131255699e-05 9.802375744622405e-05 3.913011715023943305e-05 6.204814013916893e-05 2.471222874063606835e-05 3.9221389813611975e-05 2.4770678703146694e-05
12 1.000000000000000021e-03 0.001 5.855428054911818777e-04 0.0007479199274773811 3.779325362214322600e-04 0.0005861128912299699 2.418091152720060536e-04 0.0003785065486556895 1.538790714407033914e-04 0.00024225795000622747 9.759345536126727376e-05 0.0001541970308568484 6.176526646718061210e-05 9.780794472023814e-05 3.903840385562048950e-05 6.190610951865765e-05 2.465344951928800295e-05 3.9129447888412384e-05 2.471175028700643e-05
13 1.000000000000000021e-03 0.001 5.849813875456967485e-04 0.0007473696306726699 3.773600382625630725e-04 0.0005855506450602122 2.413578451141304101e-04 0.0003779327791658341 1.535577517356502032e-04 0.00024180546890527417 9.737599881379701964e-05 0.0001538747562360148 6.162218372343696363e-05 9.758980264023896e-05 3.894579295722817337e-05 6.176255947727244e-05 2.459409722576532997e-05 3.903652792388679e-05 2.4652197254708885e-05
14 1.000000000000000021e-03 0.001 5.844137140093277807e-04 0.0007468125926679213 3.767815081401627831e-04 0.0005849816503235855 2.409019924922280132e-04 0.0003773524752207052 1.532332465435331354e-04 0.00024134800990073543 9.715641947446165209e-05 0.00015354901486124996 6.147771791853056712e-05 9.736934756691086e-05 3.885229245840823961e-05 6.161750129261558e-05 2.453417706661341544e-05 3.8942637427869684e-05 2.459202450185328e-05
15 1.000000000000000021e-03 0.001 5.838398026969793654e-04 0.0007462488201102061 3.761969767804803125e-04 0.0005844059193804029 2.404415879440078890e-04 0.00037676566322402907 1.529055803229076760e-04 0.00024088560048334876 9.693473504062415536e-05 0.0001532198292542639 6.133188116843621776e-05 9.714659598616437e-05 3.875791039276530608e-05 6.147094632476142e-05 2.447369426754818325e-05 3.884778396152801e-05 2.4531236958179027e-05
16 1.000000000000000021e-03 0.001 5.832596715764015120e-04 0.0007456783198168171 3.756064753041117783e-04 0.0005838234648047683 2.399766621646476654e-04 0.00037617236987025305 1.525747776422469490e-04 0.00024041826839299018 9.671096328199675835e-05 0.00015288722211863548 6.118468563560254894e-05 9.692156450770277e-05 3.866265482344967213e-05 6.132290601522212e-05 2.441265407298631344e-05 3.875197513865345e-05 2.4469839587096592e-05
17 1.000000000000000021e-03 0.001 5.826733387676383139e-04 0.0007451010987754332 3.750100350242446291e-04 0.0005832342993844907 2.395072460046293692e-04 0.0003755726221432343 1.522408631780071723e-04 0.0002399460416167659 9.648512203915507620e-05 0.00015255121633799497 6.103614352789890607e-05 9.66942698635831e-05 3.856653384244465896e-05 6.11733918859104e-05 2.435106174557538284e-05 3.8655218624953314e-05 2.4407837385217267e-05
18 1.000000000000000021e-03 0.001 5.820810441807425326e-04 0.0007445173992825126 3.744079089136845458e-04 0.0005826386743528757 2.390335428197917333e-04 0.00037496668540476865 1.519039834472631588e-04 0.00023946913369259697 9.625731118926498641e-05 0.00015221196586566552 6.088632085792882825e-05 9.646481704279825e-05 3.846959029618343478e-05 6.102247334575324e-05 2.428894479270876788e-05 3.85575594785277e-05 2.4345259282747418e-05
19 1.000000000000000021e-03 0.001 5.814828054675655030e-04 0.0007439272282773631 3.738001274474016776e-04 0.0005820366023339485 2.385555825972570808e-04 0.0003743545861363169 1.515641624143126585e-04 0.00023898757201912962 9.602754804766522702e-05 0.00015186949307274757 6.073522946956701240e-05 9.623322238874437e-05 3.837183203343020677e-05 6.0870161643097905e-05 2.422630831805138899e-05 3.845900518061352e-05 2.4282110155051444e-05
20 1.000000000000000021e-03 0.001 5.808786404289665358e-04 0.0007433305928659832 3.731867212872194738e-04 0.0005814280961601982 2.380733954737781241e-04 0.00037373635109929905 1.512214241469207320e-04 0.0002385013842326201 9.579584999731260704e-05 0.0001515238205025659 6.058288124990010364e-05 9.599950236146117e-05 3.827326693032387752e-05 6.071646810276464e-05 2.416315744255338838e-05 3.835956326175255e-05 2.4218394908993806e-05
21 1.000000000000000021e-03 0.001 5.802685670142343878e-04 0.0007427275003211868 3.725677212800349654e-04 0.0005808131688724332 2.375870117335689917e-04 0.0003731120073337174 1.508757928143868079e-04 0.00023801059820498021 9.556223448729982074e-05 0.0001511749708688244 6.042928812817623899e-05 9.576367353617374e-05 3.817390288966712009e-05 6.05614041249978e-05 2.409949730398197492e-05 3.825924130107498e-05 2.4154118482464792e-05
22 1.000000000000000021e-03 0.001 5.796526968519212725e-04 0.0007421180800523362 3.719432545624587992e-04 0.0005801919587229117 2.370965379259533010e-04 0.00037248171070273063 1.505273470495264228e-04 0.0002375153439047009 9.532675589286383365e-05 0.00015082303982525373 6.027448635812982831e-05 9.55258019540184e-05 3.807376356963088358e-05 6.0405013700224733e-05 2.403534314190221437e-05 3.815806798909622e-05 2.4089299350133826e-05
23 1.000000000000000021e-03 0.001 5.790310479093865609e-04 0.0007415023395254894 3.713133518665244839e-04 0.0005795644789202474 2.366020041460938778e-04 0.00037184548827748576 1.501761108339581341e-04 0.0002370156491221818 9.508943151110322721e-05 0.00015046804996987382 6.011848775803337427e-05 9.528590408468248e-05 3.797285679655886708e-05 6.0247308147258e-05 2.397070004317041725e-05 3.8056050847170796e-05 2.4023942410771268e-05
24 1.000000000000000021e-03 0.001 5.784036383121742876e-04 0.0007408802863797739 3.706780441238009577e-04 0.000578930742889133 2.361034406501071276e-04 0.00037120336741830446 1.498221082613785163e-04 0.00023651154189285886 9.485027871279472060e-05 0.00015011002407818366 5.996130419345521918e-05 9.504399651802114e-05 3.787119042685209972e-05 6.008829886368558e-05 2.390557311366359151e-05 3.7953197447440844e-05 2.395805259559495e-05
25 1.000000000000000021e-03 0.001 5.777704863433433301e-04 0.0007402519284274773 3.700373624633735868e-04 0.00057829076427012 2.356008778526011383e-04 0.0003705553757730914 1.494653635353745394e-04 0.00023600305049498863 9.460931494071504256e-05 0.0001497489851010917 5.980294757607067669e-05 9.480009596242987e-05 3.776877234616485572e-05 5.992799732470356e-05 2.383996747774973522e-05 3.784951541204015e-05 2.389163486774317e-05
26 1.000000000000000021e-03 0.001 5.771316104427772061e-04 0.0007396172736541335 3.693913382097967039e-04 0.0005776445569193926 2.350943463241932639e-04 0.0003699015412757306 1.491059009672212558e-04 0.000235490203447419 9.436655770795449559e-05 0.00014938495616282697 5.964342986246977532e-05 9.455421924320194e-05 3.766561046859827219e-05 5.976641508193571e-05 2.377388827775711285e-05 3.774501241228877e-05 2.38246942217421e-05
27 1.000000000000000021e-03 0.001 5.764870292064976651e-04 0.0007389763302186035 3.687400028810397501e-04 0.0005769921349085269 2.345838767890191692e-04 0.00036924189214444916 1.487437449736715462e-04 0.00023497302950733012 9.412202459622686095e-05 0.00014901796055883247 5.948276305296108525e-05 9.4306383300876e-05 3.756171273589169023e-05 5.960356376224896e-05 2.370734067344167480e-05 3.763969616788547e-05 2.37572356829714e-05
28 1.000000000000000021e-03 0.001 5.758375946234993610e-04 0.000738329973009011 3.680842155919215072e-04 0.0005763343882557762 2.340701414876563216e-04 0.00036857732657886674 1.483793719498717782e-04 0.00023445223185895243 9.387603703510192111e-05 0.00014864849677321228 5.932115823520561543e-05 9.40569245366171e-05 3.745721560837426419e-05 5.943966431343476e-05 2.364041205155829344e-05 3.753370952478887e-05 2.3689350732036766e-05
29 1.000000000000000021e-03 0.001 5.751833223951592329e-04 0.0007376782088319843 3.674240032104748388e-04 0.0005756713289449496 2.335531666416808738e-04 0.0003679078688863157 1.480128027327277474e-04 0.00023392783529630037 9.362861002461524574e-05 0.00014827658488585004 5.915862564500113025e-05 9.38058575472753e-05 3.735212585887714390e-05 5.927472675087035e-05 2.357310681190604310e-05 3.7427059131368685e-05 2.362104369630353e-05
30 1.000000000000000021e-03 0.001 5.745242283439769499e-04 0.0007370210446325295 3.667593927483133397e-04 0.0005750029691304239 2.330329785818580578e-04 0.000367233543593211 1.476440582313571256e-04 0.00023339986479263558 9.337975861033522300e-05 0.00014790224510292775 5.899517554647101613e-05 9.355319701349314e-05 3.724645027783519551e-05 5.910876114408311e-05 2.350542936525477225e-05 3.7319751670569666e-05 2.3552318925085614e-05
31 1.000000000000000021e-03 0.001 5.738603284130473379e-04 0.0007363584874940915 3.660904113590355527e-04 0.0005743293211369546 2.325096037462197861e-04 0.0003665543754437431 1.472731594253864234e-04 0.00023286834549865966 9.312949788206356194e-05 0.00014752549775524457 5.883081823114703288e-05 9.329895769838934e-05 3.714019567266727830e-05 5.8941777615809794e-05 2.343738413293735195e-05 3.721179385927125e-05 2.348318078922229e-05
32 1.000000000000000021e-03 0.001 5.731917314000997948e-04 0.0007356906659117175 3.654171810067180655e-04 0.0005736505214206793 2.319831433530600859e-04 0.00036587051603697917 1.469001805571756218e-04 0.00023233340267585003 9.287787898176902846e-05 0.00014714643450378646 5.866558771451522606e-05 9.30432026577021e-05 3.703338420706373603e-05 5.8773818072131705e-05 2.336898537810763873e-05 3.710321298927822e-05 2.3413646846771747e-05
33 1.000000000000000021e-03 0.001 5.725184531760584700e-04 0.0007350175870680764 3.647397285916569422e-04 0.0005729665823498456 2.314536235223777264e-04 0.00036518198995355594 1.465251423190001693e-04 0.00023179506120909636 9.262491677678542706e-05 0.00014676507541963834 5.849949412959568328e-05 9.278594644638945e-05 3.692602258076439168e-05 5.8604892484780656e-05 2.330023745100291859e-05 3.699401567385024e-05 2.3343721399750524e-05
34 1.000000000000000021e-03 0.001 5.718405097346714646e-04 0.000734339258284937 3.640580811583470273e-04 0.0005722775164633901 2.309210704829702432e-04 0.0003644888219905243 1.461480654746279682e-04 0.00023125334615855053 9.237062617930094123e-05 0.0001463814406964208 5.833254763720848617e-05 9.252720370024704e-05 3.681811751074023914e-05 5.8435010877524154e-05 2.323114471257928647e-05 3.688420855938328e-05 2.327340877117354e-05
35 1.000000000000000021e-03 0.001 5.711579171919053044e-04 0.0007336556870231954 3.633722658937428313e-04 0.0005715833364706749 2.303855105703487465e-04 0.00036379103715988533 1.457689708574830614e-04 0.00023070828275766533 9.211502214495855044e-05 0.00014599555064848363 5.816475842498649012e-05 9.226698913450141e-05 3.670967573052717390e-05 5.82641833251609e-05 2.316171153407365905e-05 3.677379832472749e-05 2.320271330460301e-05
36 1.000000000000000021e-03 0.001 5.704706917853448337e-04 0.0007329668808828947 3.626823101255147543e-04 0.0005708840552512191 2.298469702246577707e-04 0.00036308866068712113 1.453878793688169360e-04 0.00023015989641122435 9.185811967146480901e-05 0.00014560742570909416 5.799613670639434487e-05 9.200531754239911e-05 3.660070398956385041e-05 5.8092419952513674e-05 2.309194229656875218e-05 3.666279168050168e-05 2.313163936369656e-05
37 1.000000000000000021e-03 0.001 5.697788498735841109e-04 0.000732272847603227 3.619882413202942504e-04 0.0005701796858544125 2.293054759885765847e-04 0.000362381718009681 1.450048119758659754e-04 0.0002296082126933358 9.159993379718755254e-05 0.00014521708642859763 5.782669271974067121e-05 9.174220379377606e-05 3.649120905252569737e-05 5.791973093340874e-05 2.302184139055488024e-05 3.6551195368400524e-05 2.3060191331749373e-05
38 1.000000000000000021e-03 0.001 5.690839249361781711e-04 0.0007315751779154508 3.612915831986411477e-04 0.0005694718366517781 2.287622092282637863e-04 0.00036167180797618383 1.446206010588695675e-04 0.00022905447155647377 9.134102410651873409e-05 0.00014482540661409508 5.765679311500335815e-05 9.147823538482221e-05 3.638142760462866287e-05 5.774650123146614e-05 2.295156024783083523e-05 3.643925790598459e-05 2.2988528215049473e-05
39 1.000000000000000021e-03 0.001 5.683859273133331363e-04 0.0007308738763564251 3.605923537461036641e-04 0.0005687605159526348 2.282171874164802170e-04 0.00036095894758939165 1.442352604283837097e-04 0.00022849869020493823 9.108140050118301682e-05 0.00014443240010265552 5.748644463023418617e-05 9.121342232553745e-05 3.627136409615889481e-05 5.7572737692798364e-05 2.288110175599186700e-05 3.6326983828340116e-05 2.2916652961499898e-05
40 1.000000000000000021e-03 0.001 5.676848674169825831e-04 0.0007301689475478705 3.598905710243090802e-04 0.0005680457321686527 2.276704280772651710e-04 0.00036024315397386176 1.438488039249314222e-04 0.00022794088593578913 9.082107289971861372e-05 0.00014403808079282816 5.731565401294060850e-05 9.094777466478586e-05 3.616102298282374168e-05 5.739844718775089e-05 2.281046880581413228e-05 3.6214377685641065e-05 2.2844568528419092e-05
41 1.000000000000000021e-03 0.001 5.669807557304629327e-04 0.0007294603961963875 3.591862531699841626e-04 0.0005673274938137002 2.271219487847658911e-04 0.0003595244443750873 1.434612454179789358e-04 0.00022738107613769066 9.056005123670258442e-05 0.00014364246264358423 5.714442801953895405e-05 9.068130248947494e-05 3.605040872538299508e-05 5.72236366103174e-05 2.273966429101268041e-05 3.610144404275241e-05 2.2772277882278848e-05
42 1.000000000000000021e-03 0.001 5.662756696284717943e-04 0.0007287502876018436 3.584815135619230891e-04 0.0005666079096289159 2.265734124911083147e-04 0.00035880496633647314 1.430737675597642188e-04 0.00022682095171468864 9.029913524493678829e-05 0.00014324674865159545 5.697329258726415482e-05 9.041481948469436e-05 3.593986162522089478e-05 5.7048841153261715e-05 2.266890625682277028e-05 3.598852922211342e-05 2.270000293927642e-05
43 1.000000000000000021e-03 0.001 5.655696121370722921e-04 0.0007280386231103084 3.577763576655677066e-04 0.0005658869826353605 2.260248242651153531e-04 0.0003580847262718071 1.426863741861267136e-04 0.00022626051891339797 9.003832758694041048e-05 0.00014285094367250402 5.680224948786493348e-05 9.014832907727154e-05 3.582938283523433764e-05 5.687406312117876e-05 2.259819544408493697e-05 3.587563473352017e-05 2.2627744673782604e-05
44 1.000000000000000021e-03 0.001 5.648625863181645518e-04 0.0007273254041056322 3.570707909872514684e-04 0.0005651647158992671 2.254761892066869196e-04 0.00035736373064750184 1.422990691538204475e-04 0.00022569978402038908 8.977763093872482745e-05 0.00014245505258865028 5.663130050166089515e-05 8.988183471111395e-05 3.571897351373497692e-05 5.669930482943582e-05 2.252753259705453904e-05 3.5762762093538084e-05 2.2555504064421286e-05
45 1.000000000000000021e-03 0.001 5.641545952693012783e-04 0.0007266106320094578 3.563648190736888295e-04 0.0005644411125319691 2.249275124461922067e-04 0.00035664198598218 1.419118563399853763e-04 0.00022513875336164715 8.951704798938974166e-05 0.0001420590803085807 5.646044741725799208e-05 8.961533984682783e-05 3.560863482425828067e-05 5.652456860390248e-05 2.245691846327665519e-05 3.564991282531874e-05 2.2483282093948716e-05
46 1.000000000000000021e-03 0.001 5.634456421235028989e-04 0.000725894308281204 3.556584475114634488e-04 0.0005637161756897977 2.243787991438712611e-04 0.0003559194988462394 1.415247396416227112e-04 0.00022457743330201225 8.925658144072659398e-05 0.00014166303176654256 5.628969203126926030e-05 8.934884796133105e-05 3.549836793537420297e-05 5.634985678067539e-05 2.238635379346144160e-05 3.5537088458413665e-05 2.2411079749130865e-05
47 1.000000000000000021e-03 0.001 5.627357300490819225e-04 0.0007251764344180624 3.549516819265270164e-04 0.0005629899085739927 2.238300544892383743e-04 0.00035519627586142176 1.411377229750731741e-04 0.0002240158302446243 8.899623400682166435e-05 0.00014126691192198565 5.611903614803531905e-05 8.90823625474685e-05 3.538817402049950172e-05 5.6175171705805915e-05 2.231583934136070575e-05 3.542429052859005e-05 2.233889802062196e-05
48 1.000000000000000021e-03 0.001 5.620265745740795878e-04 0.0007244588135748975 3.542462045793823072e-04 0.0005622641246704724 2.232825718355581747e-04 0.00035447409591105305 1.407517127660701999e-04 0.0002234553120905153 8.873661298955798349e-05 0.00014087167955905718 5.594887683102661642e-05 8.881652603390643e-05 3.527830905094599801e-05 5.600093342830372e-05 2.224553873809700179e-05 3.531178983274928e-05 2.2266910019981595e-05
49 1.000000000000000021e-03 0.001 5.613181716914067464e-04 0.000723741443178776 3.535420099674467737e-04 0.000561538821268995 2.227363458317740963e-04 0.0003537529553873339 1.403667046661989041e-04 0.00022289587522719752 8.847771519474716161e-05 0.00014047733166655684 5.577921186868756777e-05 8.855133617099835e-05 3.516877154903826080e-05 5.5827140373801375e-05 2.217545101761858074e-05 3.519958531186087e-05 2.219511505192651e-05
50 1.000000000000000021e-03 0.001 5.606105174362018646e-04 0.0007230243206833482 3.528390926567629869e-04 0.0005608139956950427 2.221913711948466166e-04 0.00035303285074046774 1.399826943822104249e-04 0.00022233751609917817 8.821953746856249804e-05 0.00014008386527925162 5.561003907731979445e-05 8.82867907426191e-05 3.505956005567386572e-05 5.565379099102327e-05 2.210557522599888898e-05 3.508767592227262e-05 2.212351243120618e-05
51 1.000000000000000021e-03 0.001 5.599036078855734169e-04 0.0007223074435688039 3.521374472813410678e-04 0.0005600896453097011 2.216476427089692435e-04 0.0003523137784782074 1.395996776753266513e-04 0.00022178023120736695 8.796207669700402236e-05 0.00013969127747733319 5.544135630070159596e-05 8.802288756574066e-05 3.495067313006486022e-05 5.5480883751481105e-05 2.203591042126611129e-05 3.4976060635503277e-05 2.2052101482465692e-05
52 1.000000000000000021e-03 0.001 5.591992581819900257e-04 0.0007215926247557181 3.514388991464684675e-04 0.0005593676122940626 2.211065862108586844e-04 0.00035159759247597197 1.392186639199167455e-04 0.00022122546934306127 8.770601346645835294e-05 0.00013930059415776796 5.527361030479937100e-05 8.776031848020719e-05 3.484239951455165907e-05 5.5308872854303e-05 2.196664147854661471e-05 3.486503301641155e-05 2.198107017600086e-05
53 1.000000000000000021e-03 0.001 5.584974577369657654e-04 0.0007208798585848073 3.507434317312190116e-04 0.0005586478889723664 2.205681855748304113e-04 0.0003508842795507963 1.388396401724235928e-04 0.0002206732171528304 8.745133837595373525e-05 0.00013891180440309996 5.510679463338290224e-05 8.749907547557891e-05 3.473473491875524963e-05 5.513775276548628e-05 2.189776560286087024e-05 3.475458937431628e-05 2.1910416102241813e-05
54 1.000000000000000021e-03 0.001 5.577981960279812567e-04 0.0007201691394257483 3.500510286412654524e-04 0.000557930467712979 2.200324248112712805e-04 0.00035017382661216696 1.384625936044855835e-04 0.00022012346138632064 8.719804211084999142e-05 0.00013852489738482468 5.494090289064881491e-05 8.723915060881119e-05 3.462767509292537455e-05 5.49675179985075e-05 2.182928002589032757e-05 3.464472605058592e-05 2.184013687270143e-05
55 1.000000000000000021e-03 0.001 5.571014625980537805e-04 0.0007194604616770773 3.493616736077873519e-04 0.00055721534092818 2.194992880653100025e-04 0.00034946622066134466 1.380875115017372141e-04 0.00021957618889536463 8.694611544190507637e-05 0.00013813986236255893 5.477592874055209164e-05 8.698053600359808e-05 3.452121582748434684e-05 5.4798163113848986e-05 2.176118200567564087e-05 3.453543941831367e-05 2.177023011975932e-05
56 1.000000000000000021e-03 0.001 5.564072470552914543e-04 0.0007187538197660722 3.486753504863699662e-04 0.0005565025010739346 2.189687596154907018e-04 0.00034876144879066544 1.377143812626113696e-04 0.00021903138663308575 8.669554922434540153e-05 0.0001377566886832086 5.461186590614181566e-05 8.672322384971475e-05 3.441535295257522900e-05 5.462968271852315e-05 2.169346882631773742e-05 3.442672588199151e-05 2.1700693496445714e-05
57 1.000000000000000021e-03 0.001 5.557155390724777657e-04 0.0007180492081486484 3.479920432559456848e-04 0.0005557919406496801 2.184408238724854000e-04 0.00034805949818288173 1.373431903971786034e-04 0.0002184890416530366 8.644633439696230146e-05 0.00013737536578016266 5.444870816891464747e-05 8.646720640237894e-05 3.431008233762035268e-05 5.446207146561145e-05 2.162613779768559453e-05 3.431858187719449e-05 2.1631524676231647e-05
58 1.000000000000000021e-03 0.001 5.550282308874212147e-04 0.000717348639431565 3.473135853761227104e-04 0.0005550856739198547 2.179168797741835634e-04 0.00034736232071304855 1.369749146289257855e-04 0.00021795064331956514 8.619912270820690987e-05 0.00013699693247692832 5.428688083545962664e-05 8.621317757037385e-05 3.420567782931384528e-05 5.429578217858938e-05 2.155936384410790980e-05 3.421129897003673e-05 2.1562909902755936e-05
59 1.000000000000000021e-03 0.001 5.543453044039096641e-04 0.0007166521035756881 3.466399489498413807e-04 0.0005543836868927082 2.173969005859271932e-04 0.0003466698924934393 1.366095327799803094e-04 0.00021741616794755068 8.595389890905566596e-05 0.00013662136971116798 5.412637349122350694e-05 8.596112351100096e-05 3.410213253115887156e-05 5.413080535731451e-05 2.149314248283782383e-05 3.410487085131832e-05 2.1494845067789903e-05
60 1.000000000000000021e-03 0.001 5.536667416543260278e-04 0.0007159595906065037 3.459711063207645686e-04 0.0005536859656730149 2.168808598269340415e-04 0.00034598218983055497 1.362470238846985658e-04 0.0002168855920630381 8.571064790824490891e-05 0.0001362486585998701 5.396717583150281386e-05 8.571103051605296e-05 3.399943962027434491e-05 5.396713159578493e-05 2.142746927933548718e-05 3.399929127512844e-05 2.142732610463052e-05
61 1.000000000000000021e-03 0.001 5.529925247987736454e-04 0.0007152710906138687 3.453070300711248903e-04 0.0005529924964615861 2.163687312677279435e-04 0.00034529918922366796 1.358873671873677324e-04 0.00021635889240138666 8.546935477049620155e-05 0.0001358787804376394 5.380927766017944798e-05 8.546288501047042e-05 3.389759234653519571e-05 5.380475158117202e-05 2.136233984669994517e-05 3.389455405818364e-05 2.1360348987661796e-05
62 1.000000000000000021e-03 0.001 5.523242123557685823e-04 0.0007145881681833736 3.446492679875326503e-04 0.0005523048607339887 2.158617145497228296e-04 0.0003446224616264519 1.355314077800207832e-04 0.00021583728670966556 8.523058755788532964e-05 0.00013551259312919557 5.365305115434923267e-05 8.521726369129195e-05 3.379683095199963850e-05 5.364404315662281e-05 2.129790788796336886e-05 3.379090310339315e-05 2.129406976339983e-05
63 1.000000000000000021e-03 0.001 5.516617811459008413e-04 0.0007139108109389651 3.439977838203789025e-04 0.0005516230407004492 2.153597748770509342e-04 0.0003439519758859039 1.351791181086447731e-04 0.00021532074399295122 8.499432644189092710e-05 0.00013515007172518374 5.349848277838686991e-05 8.497414844816332e-05 3.369714647650299112e-05 5.3484993898260945e-05 2.123416758034315385e-05 3.368833016244125e-05 2.122848306212633e-05
64 1.000000000000000021e-03 0.001 5.510052081904127453e-04 0.0007132390066148024 3.433525416882428740e-04 0.0005509470187317473 2.148628778379304833e-04 0.00034328770115903844 1.348304709382760146e-04 0.00021480923358720733 8.476055183025699440e-05 0.0001347911915544671 5.334555916079864168e-05 8.473352137819455e-05 3.359853006971443923e-05 5.3327591526929936e-05 2.117111317291617240e-05 3.358682708410006e-05 2.1163583577742056e-05
65 1.000000000000000021e-03 0.001 5.503544707098636342e-04 0.0007125727430549207 3.427135060745518090e-04 0.0005502767773585094 2.143709894006651793e-04 0.000342629606910633 1.344854393494213974e-04 0.00021430272515636744 8.452924436422564868e-05 0.0001344359282214269 5.319426709225049006e-05 8.449536478383494e-05 3.350097298979682009e-05 5.317182390666476e-05 2.110873898573355285e-05 3.348638581318404e-05 2.109936606707349e-05
66 1.000000000000000021e-03 0.001 5.497095461228062706e-04 0.0007119120082129148 3.420806418242862412e-04 0.0005496122992705212 2.138840759097000895e-04 0.0003419776629110174 1.341439967345312348e-04 0.0002138011886894788 8.430038491581448882e-05 0.00013408425760331254 5.304459352362807473e-05 8.425966117078749e-05 3.340446660208796169e-05 5.3017679043188334e-05 2.104703940894962140e-05 3.3386998389521964e-05 2.1035825349191292e-05
67 1.000000000000000021e-03 0.001 5.490704120444732210e-04 0.000711256790151613 3.414539141407250565e-04 0.0005489535673160376 2.134021040817290626e-04 0.0003413318392338714 1.338061167945246396e-04 0.00021330459449785352 8.407395458513211085e-05 0.00013373615584760944 5.289652556412503305e-05 8.40263932459383e-05 3.330900237780223545e-05 5.286514508242194e-05 2.098600890196449472e-05 3.3288656946938245e-05 2.0972956304734848e-05
68 1.000000000000000021e-03 0.001 5.484371298422446297e-04 0.0007106071943639499 3.408333692467681113e-04 0.0005483006816957998 2.129251024270059081e-04 0.00034069221933208274 1.334718163299163942e-04 0.0002128129992904075 8.384996326436759272e-05 0.00013339165932644894 5.275006911363530105e-05 8.379558393280961e-05 3.321458388816914869e-05 5.271423641048183e-05 2.092564965374723430e-05 3.31913705135711e-05 2.091076460544407e-05
69 1.000000000000000021e-03 0.001 5.478096771889333057e-04 0.000709963208882901 3.402189725469309967e-04 0.0005476536252143895 2.124530379214265854e-04 0.0003400587732671483 1.331410692793207290e-04 0.0002123263734210078 8.362839223924152716e-05 0.00013305074425072359 5.260521141428185532e-05 8.356721599784782e-05 3.312120269498457291e-05 5.256494122003263e-05 2.086595618361951373e-05 3.3095131256746724e-05 2.0849245154782437e-05
70 1.000000000000000021e-03 0.001 5.471880319478338028e-04 0.0007093248218486061 3.396106897916775086e-04 0.0005470123808316875 2.119858778995733334e-04 0.00033943147139689077 1.328138498781884043e-04 0.0002118446875576196 8.340922301478033581e-05 0.00013271338709432742 5.246193986031627375e-05 8.334127240311385e-05 3.302885046175365648e-05 5.241724783997488e-05 2.080692307740899109e-05 3.299993143509595e-05 2.0788392916005465e-05
71 1.000000000000000021e-03 0.001 5.465721721714859958e-04 0.0007086920215080653 3.390084870743713592e-04 0.0005463769316622218 2.115235900510876890e-04 0.0003388102843733889 1.324901326555763298e-04 0.00021136791267964032 8.319243731282516567e-05 0.0001323795645916927 5.232024199634728476e-05 8.311773630434548e-05 3.293751895248773966e-05 5.2271144734051514e-05 2.074854498665493433e-05 3.290576339760186e-05 2.07282029115292e-05
72 1.000000000000000021e-03 0.001 5.459629241404544706e-04 0.0007080656480431051 3.384131725428774743e-04 0.0005457481216341828 2.110667946787101129e-04 0.0003381960373995552 1.321703518944146796e-04 0.00021089668206097172 8.297832591380873519e-05 0.0001320497200486003 5.218030786215170435e-05 8.289690449717853e-05 3.284733064718059383e-05 5.2126825862102536e-05 2.069090019482566404e-05 3.2812752146082854e-05 2.0668755034757233e-05
73 1.000000000000000021e-03 0.001 5.453602635114507746e-04 0.0007074456886869565 3.378247083723790616e-04 0.0005451259321489777 2.106154557101209946e-04 0.0003375886977799707 1.318544791589579420e-04 0.0002104309633113142 8.276686841524559784e-05 0.00013172382748945162 5.204212355675735553e-05 8.26787581753205e-05 3.275827635494999894e-05 5.198427834496719e-05 2.063398273378693265e-05 3.2720889139431744e-05 2.061004372929991e-05
74 1.000000000000000021e-03 0.001 5.447641661727002649e-04 0.0007068321308093747 3.372430571518834691e-04 0.0005445103448031184 2.101695374983407439e-04 0.0003369882331820464 1.315424863636820575e-04 0.00020997072442018424 8.255804467261116894e-05 0.00013140186125447996 5.190567535780167048e-05 8.246327876643199e-05 3.267034700418964161e-05 5.18434894660219e-05 2.057778671334094953e-05 3.2630165945308436e-05 2.055206350992823e-05
75 1.000000000000000021e-03 0.001 5.441746082424759419e-04 0.0007062249619162967 3.366681818805845774e-04 0.0005439013413874698 2.097290048174083239e-04 0.00033639461163356655 1.312343457694375884e-04 0.00020951593375373114 8.235183479637930588e-05 0.00013108379599680725 5.177094971942625129e-05 8.225044792981545e-05 3.258353364113958107e-05 5.170444666951808e-05 2.052230632028256941e-05 3.254057423900392e-05 2.0494808961820763e-05
76 1.000000000000000021e-03 0.001 5.435915660676414983e-04 0.00070562416964951 3.361000459642789163e-04 0.0005432989038865089 2.092938228581225045e-04 0.00033580780152024723 1.309300299796617602e-04 0.000209066560051587 8.214821914910500468e-05 0.00013076960667953474 5.163793327020207291e-05 8.204024755412909e-05 3.249782742847867687e-05 5.156713755893784e-05 2.046753581747058517e-05 3.2452105802317056e-05 2.0438274739819433e-05
77 1.000000000000000021e-03 0.001 5.430150162222109568e-04 0.0007050297417863318 3.355386132118161487e-04 0.0005427030144775926 2.088639572238308215e-04 0.0003352277715833316 1.306295119366350911e-04 0.00020862257242375786 8.194717834254394587e-05 0.00013045926857287288 5.150661281108238069e-05 8.183265975513502e-05 3.241321964393507540e-05 5.143154989537623e-05 2.041346954291065543e-05 3.236475252244954e-05 2.038245556769746e-05
78 1.000000000000000021e-03 0.001 5.424450181544462771e-04 0.0007044417829621171 3.349839271155603902e-04 0.000542113771820027 2.084394340599780252e-04 0.0003346546023905152 1.303328067075743425e-04 0.00020818402485557293 8.174872108664715700e-05 0.00013015281596227648 5.137699346328779477e-05 8.162770599537212e-05 3.232971335519106785e-05 5.129769708700084e-05 2.036010936323692981e-05 3.227852278867728e-05 2.032735670561579e-05
79 1.000000000000000021e-03 0.001 5.418815485793469040e-04 0.0007038602809995153 3.344359518126675877e-04 0.0005415311581470623 2.080202193468776877e-04 0.00033408826282687573 1.300398875631312602e-04 0.00020775088664703998 8.155282824274543232e-05 0.00012985022429639665 5.124906220377890154e-05 8.142536853201701e-05 3.224729995882103797e-05 5.116556699709043e-05 2.030744969463951815e-05 3.219340855821242e-05 2.0272972923816322e-05
80 1.000000000000000021e-03 0.001 5.413245844265015877e-04 0.0007032852238493367 3.338946518213946552e-04 0.0005409551558747416 2.076062794549138172e-04 0.0003335287221154158 1.297507280942760690e-04 0.00020732312745044945 8.135948090770286575e-05 0.00012955146931603386 5.112280617242197348e-05 8.122562983828357e-05 3.216597096011364272e-05 5.103514763884953e-05 2.025548502431296445e-05 3.2109401888525124e-05 2.0219299058105656e-05
81 1.000000000000000021e-03 0.001 5.407741028387587183e-04 0.0007027165995902542 3.333599920378552692e-04 0.0005403857476012292 2.071975811406991498e-04 0.00033297594981485264 1.294653022088876294e-04 0.00020690071726752732 8.116866041129419294e-05 0.0001292565270515082 5.099821267012491396e-05 8.102847260135871e-05 3.208571797180734118e-05 5.090642717392409e-05 2.020420990962221080e-05 3.202649493632917e-05 2.0166330009182866e-05
82 1.000000000000000021e-03 0.001 5.402303025747014556e-04 0.0007021546252265139 3.328321561526745862e-04 0.0005398231466905069 2.067942601549091974e-04 0.00033243014325207994 1.291837026153304184e-04 0.00020648380199548492 8.098042783792958120e-05 0.0001289654971719027 5.087532120941394917e-05 8.083396250547584e-05 3.200656629292941073e-05 5.077944809587575e-05 2.015364045325785942e-05 3.194471491165552e-05 2.0114083097018264e-05
83 1.000000000000000021e-03 0.001 5.396931605409548225e-04 0.0007015992888126556 3.323111087173311550e-04 0.0005392673356287205 2.063962829591101838e-04 0.0003318912717105927 1.289059030082810651e-04 0.00020607235137144977 8.079476437365657295e-05 0.0001286783555062261 5.075411899733799342e-05 8.06420820982489e-05 3.192850747587867838e-05 5.065419847368218e-05 2.010377117411100997e-05 3.186405391103787e-05 2.006255318369691e-05
84 1.000000000000000021e-03 0.001 5.391626538584482192e-04 0.0007010505785332368 3.317968146613820609e-04 0.0005387182970867077 2.060036164003212873e-04 0.00033135930481238495 1.286318773981824648e-04 0.00020566633548374424 8.061165143636152362e-05 0.0001283950781739038 5.063459340114707095e-05 8.04528141416734e-05 3.185153317990099749e-05 5.053066652493675e-05 2.005459666083220688e-05 3.1784504130324826e-05 2.001173519622426e-05
85 1.000000000000000021e-03 0.001 5.386387598611086340e-04 0.000700508482702546 3.312892392892789490e-04 0.0005381760139193414 2.056162277072543561e-04 0.00033083421251577956 1.283616001079104806e-04 0.00020526572476908743 8.043107067321031531e-05 0.000128115641582197 5.051673194647494236e-05 8.026614161010359e-05 3.177563516985718072e-05 5.040884061439589e-05 2.000611157101859271e-05 3.170605786368809e-05 1.9961624125869314e-05
86 1.000000000000000021e-03 0.001 5.381214560945620949e-04 0.0006999729897643184 3.307883482772016118e-04 0.0005376404691648787 2.052340844865845515e-04 0.00033031596511327947 1.280950457694747437e-04 0.00020487049000982136 8.025300395811590449e-05 0.00012784002242364822 5.040052231554306949e-05 8.008204768824872e-05 3.170080531500530551e-05 5.028870925253973e-05 1.995831063041139523e-05 3.1628707502639986e-05 1.9912215027513866e-05
87 1.000000000000000021e-03 0.001 5.376107203148404326e-04 0.0006994440882914515 3.302941076699326679e-04 0.0005371116460443127 2.048571547192701043e-04 0.0003298045332294241 1.278321893207613302e-04 0.0002044806023311588 8.007743338923888358e-05 0.0001275681976735486 5.028595234538581714e-05 7.990051576919067e-05 3.162703558779804923e-05 5.0170261094149856e-05 1.991118863210237610e-05 3.155244553506268e-05 1.9863503019009735e-05
88 1.000000000000000021e-03 0.001 5.371022748594453389e-04 0.0006989172535560769 3.298024246812891291e-04 0.0005365850419669894 2.044823390252625600e-04 0.000329295612913881 1.275708788891961756e-04 0.00020409280438264766 7.990292563076895462e-05 0.00012729790663346764 5.017208832604374468e-05 7.972004038787022e-05 3.155372544493714152e-05 5.0052515589855926e-05 1.986436223028797206e-05 3.147664135129994e-05 1.9815085586326718e-05
89 1.000000000000000021e-03 0.001 5.365961117498912114e-04 0.0006983924815322933 3.293132869081722108e-04 0.0005360606511477293 2.041096254707852251e-04 0.0003287891938968759 1.273111050031557620e-04 0.00020370708584067882 7.972947385597059739e-05 0.00012702914094133737 5.005892559260894715e-05 7.954061545150935e-05 3.148087179640124731e-05 4.993546855036179e-05 1.981782941609088261e-05 3.140129216611291e-05 1.9766960914662127e-05
90 1.000000000000000021e-03 0.001 5.360922230056120808e-04 0.0006978697681747856 3.288266819633119922e-04 0.000535538467781285 2.037390021489647173e-04 0.000328285265898271 1.270528582181514683e-04 0.00020332343638453147 7.955707126027152540e-05 0.00012676189224377013 4.994645949643470906e-05 7.936223487646896e-05 3.140847156340457124e-05 4.981911579385119e-05 1.977158818812822943e-05 3.1326395199731696e-05 1.971912719297887e-05
91 1.000000000000000021e-03 0.001 5.355906006439992324e-04 0.0006973491094188342 3.283425974753378354e-04 0.0005350184860423863 2.033704571798752555e-04 0.0003277838186277228 1.267961291168465381e-04 0.0002029418456965422 7.938571106126265876e-05 0.0001264961521961901 4.983468540512894492e-05 7.918489258833681e-05 3.133652167839010846e-05 4.970345314604528e-05 1.972563655250571181e-05 3.125194767789152e-05 1.967158261402843e-05
92 1.000000000000000021e-03 0.001 5.350891259362026411e-04 0.0006968284099289676 3.278589502113704612e-04 0.000534498597351666 2.030023855884717748e-04 0.00032728277956097635 1.265397912200834861e-04 0.00020256071739357045 7.921463777328526478e-05 0.0001262308004979493 4.972310904903239575e-05 7.900783730702533e-05 3.126470337114675132e-05 4.958798911408524e-05 1.967977067875568528e-05 3.1177632631488905e-05 1.9624124503146986e-05
93 1.000000000000000021e-03 0.001 5.345877966909636306e-04 0.0006963076677967887 3.273757374134148111e-04 0.0005339787996978908 2.026347848040474173e-04 0.00032678214616920946 1.262838424862170036e-04 0.00020218004908417888 7.904384991646645146e-05 0.0001259658352285323 4.961172941171763403e-05 7.883106763041168e-05 3.119301596587686584e-05 4.947272273059253e-05 1.963399012641590455e-05 3.110344941552445e-05 1.957675243920473e-05
94 1.000000000000000021e-03 0.001 5.340866106918126799e-04 0.0006957868810888677 3.268929562877650259e-04 0.0005334590910383602 2.022676522245876859e-04 0.00032628191587964447 1.260282808504260116e-04 0.00020179983833834103 7.887334599501782170e-05 0.00012570125443876325 4.950054546622813158e-05 7.865458213663353e-05 3.112145877995456692e-05 4.935765301510161e-05 1.958829445064508602e-05 3.102939737649859e-05 1.9529465995615212e-05
95 1.000000000000000021e-03 0.001 5.335855656972701092e-04 0.0006952660478468047 3.264106040054970534e-04 0.0005329394692990367 2.019009852173301103e-04 0.0003257820860759608 1.257731042251948573e-04 0.00020142008268794192 7.870312449759831505e-05 0.0001254370561512512 4.938955617533215942e-05 7.847837938443003e-05 3.105003112409614148e-05 4.924277897429975e-05 1.954268320233478379e-05 3.0955475852573814e-05 1.94822647404421e-05
96 1.000000000000000021e-03 0.001 5.330846594410641130e-04 0.00069474516608728 3.259286777029715004e-04 0.0005324199323746772 2.015347811193284109e-04 0.00032528265409871067 1.255183105007985753e-04 0.0002010407796272818 7.853318389767883849e-05 0.0001251732383608348 4.927876049177821896e-05 7.830245791348127e-05 3.097873230253197569e-05 4.91280996022673e-05 1.949715592822227211e-05 3.088168417373684e-05 1.943514823650581e-05

View File

@@ -1,98 +1,98 @@
1.000000000000000021e-03,6.059428294303585358e-04,4.124436878765448634e-04,2.874462507798667202e-04,2.103923932407651741e-04,1.678414792051835720e-04,1.547359756068614396e-04,1.816771264024174659e-04,3.223716208702616772e-04 0.001,0.0007651928200015371,0.0006070713937965498,0.00041423535558437785,0.0002897888610631573,0.00021340907299884933,0.00017198131811953097,0.00016127923791982795,0.00019503601408127412,0.00036549739730595273
1.000000000000000021e-03,6.053134417926274479e-04,4.117055522849718272e-04,2.867345754340725936e-04,2.097129658661858059e-04,1.671408382188599656e-04,1.538980727463440737e-04,1.804148897825019347e-04,3.196786917797407482e-04 0.001,0.0007645995806173374,0.0006064422887178694,0.00041349144049413134,0.00028906380160320487,0.00021270693331134475,0.0001712438796411692,0.0001603765556252246,0.00019363496213474675,0.00036239423700181427
1.000000000000000021e-03,6.046849734433535663e-04,4.109690875237402238e-04,2.860250085842350751e-04,2.090360511584246736e-04,1.664434237997556567e-04,1.530650313352837862e-04,1.791618737991747007e-04,3.170092948646618079e-04 0.001,0.0007640065772643761,0.0006058136176614386,0.00041274866023030733,0.0002883403899406645,0.0002120069527025505,0.00017050944162049183,0.000159478716966613,0.00019224364342300643,0.0003593168093314386
1.000000000000000021e-03,6.040574211994215528e-04,4.102342878398261821e-04,2.853175420730359193e-04,2.083616379079277403e-04,1.657492189637676920e-04,1.522368203677859210e-04,1.779180061767344980e-04,3.143632101370558260e-04 0.001,0.0007634138087852742,0.000605185379478,0.0004120070127662441,0.0002876186224176594,0.00021130912485491145,0.00016977799240843955,0.0001585856969223786,0.00019086199210672448,0.0003562649023666937
1.000000000000000021e-03,6.034068048547004811e-04,4.094522032835132145e-04,2.845379038962591819e-04,2.075849237814657072e-04,1.649065028354379026e-04,1.511673145690444625e-04,1.761800891032866087e-04,3.101696013411107001e-04 0.001,0.0007628028346998721,0.0006045332187986192,0.0004112166712442958,0.0002868226029691562,0.00021050564591298308,0.0001688917074786142,0.00015743651373617922,0.00018893812235512526,0.0003514029291704815
1.000000000000000021e-03,6.027571485450614400e-04,4.086719523190792173e-04,2.837607352174946669e-04,2.068114158243908936e-04,1.640683639230874002e-04,1.501056331894667201e-04,1.744595725998800725e-04,3.060328853710948794e-04 0.001,0.0007621921143131398,0.0006038815297458003,0.00041042762231867933,0.00028602858816935265,0.00020970502628600424,0.00016800982241073787,0.00015629534163924753,0.00018703308452519017,0.00034660591682276115
1.000000000000000021e-03,6.021084488423111532e-04,4.078935283235860985e-04,2.829860258399657913e-04,2.060410983394430761e-04,1.632347745793864737e-04,1.490517152618393740e-04,1.727562758069566841e-04,3.019522704750103072e-04 0.001,0.0007615816463554626,0.0006032303109890501,0.0004096398633263614,0.0002852365728026657,0.00020890725596775628,0.00016713231600712825,0.00015516212643578583,0.00018514669874176095,0.00034187301148734186
1.000000000000000021e-03,6.014584946769776846e-04,4.071145901524401327e-04,2.822117789926256531e-04,2.052723360542508288e-04,1.624043320606193702e-04,1.480041851535097400e-04,1.710684425093964716e-04,2.979241342510260699e-04 0.001,0.0007609692265548555,0.000602577299493926,0.0004088509941253184,0.00028444450359523985,0.00020811064471691694,0.00016625772561605027,0.00015403541161623416,0.00018327705284413884,0.00033720006213702974
1.000000000000000021e-03,6.008072907871274187e-04,4.063351463691671850e-04,2.814380028310788616e-04,2.045051334722086352e-04,1.615770319309204608e-04,1.469630126571907884e-04,1.693959447695294284e-04,2.939478272988644745e-04 0.001,0.0007603548574442921,0.0006019224999904981,0.0004080610253035772,0.00028365239238410656,0.0002073152021201705,0.00016538605339556675,0.00015291517504370476,0.00018142402424673905,0.0003325863766610152
1.000000000000000021e-03,6.001497788207915121e-04,4.055445944921290597e-04,2.806482406689155018e-04,2.037157793952982566e-04,1.607178158735042268e-04,1.458699426620449350e-04,1.676159912510077627e-04,2.896237141368235984e-04 0.001,0.0007597350402439383,0.0006012612395706585,0.0004072600935672035,0.0002828447987841907,0.00020649842223713097,0.00016448344741808307,0.00015174362495246272,0.00017946021794659197,0.00032758319657592714
1.000000000000000021e-03,5.994910374944025042e-04,4.047535948218318100e-04,2.798590565363265966e-04,2.029281739019909579e-04,1.598620980598530251e-04,1.447840125437445142e-04,1.658536074234625343e-04,2.853613427461420497e-04 0.001,0.0007591132829776185,0.0006005982088110791,0.0004064581175876688,0.00028203726728774387,0.00020568299547110922,0.00016358411213968798,0.00015057934813125987,0.00017751539893581778,0.00032265060787650516
1.000000000000000021e-03,5.988260139740232213e-04,4.039566207302157830e-04,2.790656268334378021e-04,2.021383019157014865e-04,1.590064003284783227e-04,1.437018088215471850e-04,1.641044980680633682e-04,2.811520890672289147e-04 0.001,0.000758484736453085,0.0005999283660908604,0.0004056495676510805,0.00028122495212139567,0.00020486486304104927,0.00016268449575399985,0.00014941879820841596,0.00017558496339953558,0.0003177787884410679
1.000000000000000021e-03,5.981547295973556680e-04,4.031537149116132062e-04,2.782680029999613086e-04,2.013462168991827844e-04,1.581507747250400562e-04,1.426233730149128554e-04,1.623686402996199669e-04,2.769954674673250896e-04 0.001,0.0007578494094215417,0.0005992517275730322,0.0004048344831924046,0.000280407904430663,0.00020404408117776887,0.0001617846565020927,0.00014826202727426984,0.00017366890284920263,0.0003129672376410902
1.000000000000000021e-03,5.974772058480589884e-04,4.023449202032754039e-04,2.774662364916018848e-04,2.005519721420980883e-04,1.572952728586730247e-04,1.415487458023807841e-04,1.606460099014084351e-04,2.728909933446289080e-04 0.001,0.0007572073108060312,0.0005985683096346821,0.0004040129039083478,0.0002795861755026316,0.00020322070604404603,0.00016088465224596546,0.00014710908652278506,0.00017176720707727308,0.00030821545426856767
1.000000000000000021e-03,5.967924602151245417e-04,4.015280354275974962e-04,2.766567170422079059e-04,1.997501120648868605e-04,1.564314572956195643e-04,1.404632320601022135e-04,1.589039550526354799e-04,2.687258582080010155e-04 0.001,0.0007565575890478602,0.00059787696153193,0.0004031823074325593,0.00027875567967892653,0.00020238859856737548,0.00015997497741322437,0.00014594324831107206,0.00016984173084389243,0.0003033838449669414
1.000000000000000021e-03,5.961015210291329552e-04,4.007053572943599577e-04,2.758431797434220318e-04,1.989462429758611403e-04,1.555679612182393453e-04,1.393818318435550562e-04,1.571757793000612348e-04,2.646152969711955188e-04 0.001,0.0007559011152632264,0.0005971788697390111,0.00040234530612592536,0.0002779206290242912,0.00020155405878687617,0.00015906535701622418,0.0001447815990558725,0.00016793142878541938,0.0002986152551090434
1.000000000000000021e-03,5.954044103428367566e-04,3.998769294251378363e-04,2.750256766566040972e-04,1.981404183299118591e-04,1.547048355449558708e-04,1.383045830163869136e-04,1.554614480121203164e-04,2.605587686095252363e-04 0.001,0.000755237898986442,0.000596474051424026,0.00040150194087318277,0.00027708107588917086,0.00020071714346489746,0.00015815584855490808,0.00014362418708307366,0.00016603627832169687,0.00029390910930431773
1.000000000000000021e-03,5.947013777400173224e-04,3.990430339362700481e-04,2.742044609070656662e-04,1.973328535702731791e-04,1.538422664307762401e-04,1.372316495983985922e-04,1.537610729441031576e-04,2.565559887984316962e-04 0.001,0.0007545681886825906,0.0005957627683701927,0.00040065250958751827,0.00027623729012494873,0.00019987808563904174,0.00015724665811831285,0.0001424712015659587,0.00016415642490307197,0.0002892651425802985
1.000000000000000021e-03,5.939924446448691022e-04,3.982037130272156897e-04,2.733795825341983144e-04,1.965235995659166514e-04,1.529803013963573505e-04,1.361630645638145173e-04,1.520746117923915490e-04,2.526064078268458078e-04 0.001,0.0007538919937536639,0.0005950450374279253,0.0003997970520738093,0.0002753893223189692,0.00019903693960802692,0.00015633783972296886,0.0001413226854400146,0.00016229183664828758,0.0002846827650697017
1.000000000000000021e-03,5.932708072008613994e-04,3.973448313523968048e-04,2.725292879585060313e-04,1.956816407574392804e-04,1.520737532268283138e-04,1.350253536692922732e-04,1.502520417395671493e-04,2.482429369311983419e-04 0.001,0.0007532045557665671,0.0005943145247994342,0.0003989223236188871,0.00027451662339635243,0.0001981640806362608,0.00015538551594067732,0.00014010540813129958,0.00016028630721570607,0.00027963581042999
1.000000000000000021e-03,5.925433291275937313e-04,3.964806700993557770e-04,2.716755655440644093e-04,1.948383564731119815e-04,1.511684275731327428e-04,1.338932464840604031e-04,1.484467502756363724e-04,2.439468427807235304e-04 0.001,0.0007525106592079478,0.0005935776116184588,0.00039804170193550713,0.0002736399653899091,0.00019728948692008958,0.00015443417816766013,0.00013889388158999866,0.0001582996284854468,0.0002746667454821644
1.000000000000000021e-03,5.918101288584805405e-04,3.956113769664689763e-04,2.708185566039283476e-04,1.939938721213093850e-04,1.502644330979066827e-04,1.327668256867655240e-04,1.466587172007617287e-04,2.397173806066686273e-04 0.001,0.0007518104383956622,0.000592834444449282,0.0003971553683797481,0.0002727595219957832,0.00019641331428482412,0.00015348396557824612,0.00013768822268133468,0.000156331819705631,0.00026977480754699626
1.000000000000000021e-03,5.910712282476807177e-04,3.947369945531709078e-04,2.699583111402765676e-04,1.931482375169864133e-04,1.493618135415682949e-04,1.316461114156967569e-04,1.448878476419733323e-04,2.355536787532183434e-04 0.001,0.0007511039033537896,0.0005920850408658466,0.0003962633635582371,0.00027187534416274955,0.00019553561634171146,0.00015253492870981108,0.00013648846139846028,0.00015438279270990136,0.0002649590347362105
1.000000000000000021e-03,5.903266492974269808e-04,3.938575655934699066e-04,2.690948791496987824e-04,1.923015022699072797e-04,1.484606121781560119e-04,1.305311230155930472e-04,1.431340460611192763e-04,2.314548735305102924e-04 0.001,0.0007503910642803073,0.0005913294186556257,0.0003953657283217157,0.0002709874829437419,0.00019465644657888978,0.0001515871176567501,0.0001352946268320504,0.0001524524582210848,0.0002602184722292356
1.000000000000000021e-03,5.895916361077759233e-04,3.930015889157450278e-04,2.682679585446747167e-04,1.915046725018171748e-04,1.476265343831741983e-04,1.295122987364192039e-04,1.415403000102364922e-04,2.277048762028301403e-04 0.001,0.0007496855573046408,0.0005905851062898704,0.00039449552403657745,0.00027014241927282736,0.0001938361803657908,0.0001507194393001951,0.00013421767536698768,0.000150722476765932,0.0002559376038022294
1.000000000000000021e-03,5.888509505821538188e-04,3.921405251235485093e-04,2.674377005486313469e-04,1.907064029438769275e-04,1.467931904457939435e-04,1.284977589807231727e-04,1.399600943498011466e-04,2.240084844157824847e-04 0.001,0.0007489737467556278,0.0005898345737440663,0.000393619635985906,0.00026929349394052985,0.00019301404332913125,0.00014985216957655317,0.00013314488789598826,0.00014900672746282064,0.00025171693602497907
1.000000000000000021e-03,5.881046147353881284e-04,3.912744162777674595e-04,2.666041537474170709e-04,1.899067416692393098e-04,1.459606238177286390e-04,1.274875313353729649e-04,1.383933775516596422e-04,2.203650745808937968e-04 0.001,0.0007482556429977025,0.0005890778388714725,0.00039273810426086416,0.0002684407562332248,0.0001921900867993824,0.00014898535811302548,0.00013207630234912348,0.00014730517414690737,0.000247555825445753
1.000000000000000021e-03,5.873535041835053691e-04,3.904041908037584924e-04,2.657681073335506784e-04,1.891063272435359547e-04,1.451293640595985746e-04,1.264820875947550167e-04,1.368405966876043531e-04,2.167748460671411873e-04 0.001,0.000747532135526673,0.0005883158165865031,0.0003918519024244402,0.00026758503804540166,0.0001913649895279964,0.00014811957577380352,0.00013101244041258906,0.0001456183389249714,0.00024345460151209766
1.000000000000000021e-03,5.865976375297720377e-04,3.895298843642901903e-04,2.649296021207307814e-04,1.883051991594097421e-04,1.442994447916011967e-04,1.254814426573682665e-04,1.353016807452276011e-04,2.132371421364682767e-04 0.001,0.0007468032330641541,0.0005875485221384682,0.0003909610648762846,0.00026672638132361175,0.0001905387943939666,0.00014725486211264363,0.00012995332641946747,0.00014394616337354944,0.00023941257691738652
1.000000000000000021e-03,5.858370334908887412e-04,3.886515327161476187e-04,2.640886789067201177e-04,1.875033967487228748e-04,1.434708992929061271e-04,1.244856108614830043e-04,1.337765582492128895e-04,2.097513117892475961e-04 0.001,0.0007460689444707028,0.0005867759709451519,0.0003900656262003575,0.00026586482808789615,0.00018971154418348472,0.00014639125636754904,0.00012889898406950181,0.00014228858823944247,0.00023542906884335907
1.000000000000000021e-03,5.850717109173866415e-04,3.877691717638952012e-04,2.632453785571107932e-04,1.867009592919541521e-04,1.426437606415217971e-04,1.234946061839636009e-04,1.322651576281378186e-04,2.063167108712882474e-04 0.001,0.0007453292787585437,0.0005859981786120694,0.0003891656212152682,0.00026500042051039684,0.000188883281693472,0.0001455287975953345,0.000127849436626481,0.0001406455538271199,0.00023150340029334736
1.000000000000000021e-03,5.843017841779564719e-04,3.868829399849727933e-04,2.623998297381095117e-04,1.858979973489535589e-04,1.418181214209275826e-04,1.225084976697060233e-04,1.307674705482058720e-04,2.029328092689827875e-04 0.001,0.0007445843685250069,0.0005852152884984452,0.0003882612223549495,0.00026413331906842847,0.00018805414639063353,0.00014466760638632992,0.00012680478406473458,0.00013901709088191773,0.00022763506393382832
1.000000000000000021e-03,5.835272719783185817e-04,3.859928727352694559e-04,2.615520723807220407e-04,1.850945488934469029e-04,1.409940129261724197e-04,1.215272967897141737e-04,1.292834223062770812e-04,1.995989685833853672e-04 0.001,0.0007438342228409441,0.0005844273161744179,0.0003873524639441998,0.00026326356496406687,0.00018722417962072503,0.0001438077197030893,0.00012576504647438162,0.00013740313489262333,0.00022382338328436597
1.000000000000000021e-03,5.827481931390192209e-04,3.850990054645316799e-04,2.607021463995574332e-04,1.842906517410432266e-04,1.401714661235729505e-04,1.205510144929276286e-04,1.278129378421479238e-04,1.963145562589016025e-04 0.001,0.0007430788509165626,0.0005836342773781009,0.0003864393804873395,0.0002623911994661588,0.00018639342263244998,0.00014294917419819004,0.000124730243348245,0.00013580362065026603,0.00022006768669446508
1.000000000000000021e-03,5.819741190680906414e-04,3.842186528659996786e-04,2.598733678747139103e-04,1.835150990942780922e-04,1.393856353878371876e-04,1.196241043053028848e-04,1.264157249384978508e-04,1.931533527071859933e-04 0.001,0.000742327254060605,0.0005828476385639736,0.00038554300530339766,0.00026154496076193957,0.00018559797011481673,0.0001421370333657246,0.00012375932796391997,0.00013430279846409174,0.00021649152387618443
1.000000000000000021e-03,5.811954906857532679e-04,3.833344911530978875e-04,2.590423495637437460e-04,1.827389251971546448e-04,1.386010231640464696e-04,1.187014313463915350e-04,1.250305871218520724e-04,1.900379005692562904e-04 0.001,0.0007415704350109161,0.0005820559385468977,0.00038464228372291103,0.0002606960153281244,0.00018480150743526303,0.00014132579578003348,0.000122792459010487,0.0001328143978658426,0.0002129659469511457
1.000000000000000021e-03,5.804123268686601621e-04,3.824465553881609072e-04,2.582091305240798466e-04,1.819621668943112273e-04,1.378176602140172575e-04,1.177830097537161525e-04,1.236574657124121280e-04,1.869676369318762604e-04 0.001,0.0007408084031449065,0.0005812591931755618,0.00038373724983374976,0.00025984440338310303,0.0001840040745362742,0.0001405154975809745,0.00012182965960439977,0.00013133837476817992,0.00020949038404752677
1.000000000000000021e-03,5.796261981805348861e-04,3.815564763513873891e-04,2.573750710547324729e-04,1.811859034357266680e-04,1.370364232713841633e-04,1.168696105278517803e-04,1.222971239749574140e-04,1.839432835829867073e-04 0.001,0.0007400427720784002,0.0005804590496942265,0.00038282961864956994,0.0002589915613698488,0.00018320681873232144,0.00013970708155515462,0.00012087177639736769,0.00012987560432955444,0.00020606578076074432
1.000000000000000021e-03,5.788371166298537929e-04,3.806642767897665215e-04,2.565401959245502722e-04,1.804101566728638260e-04,1.362573268495191094e-04,1.159612279572367423e-04,1.209494737333099285e-04,1.809642226433420603e-04 0.001,0.0007392735475065714,0.0005796555183614057,0.00038191941292656456,0.0002581375157328154,0.0001824097650442608,0.00013890056717630873,0.00011991881140841177,0.0001284260094133047,0.00020269149646849757
1.000000000000000021e-03,5.780450942923127944e-04,3.797699794962239458e-04,2.557045298790712744e-04,1.796349483543752492e-04,1.354803852765658562e-04,1.150578560981921263e-04,1.196144270262388971e-04,1.780298433107154344e-04 0.001,0.0007385007352097838,0.0005788486095364762,0.00038100665551987393,0.00025728229294257515,0.00018161293842329387,0.00013809597373520515,0.00011897076635433426,0.0001269895128043655,0.00019936689671873207
1.000000000000000021e-03,5.772501433097143196e-04,3.788736073065085246e-04,2.548680976361037374e-04,1.788603001211915217e-04,1.347056126906417029e-04,1.141594887707218423e-04,1.182918961012392148e-04,1.751395417672447184e-04 0.001,0.0007377243410529983,0.0005780383336785572,0.0003800913693799712,0.0002564259194903244,0.00018081636374445108,0.00013729332033271256,0.00011802764264291933,0.00012556603720150224,0.00019609135315036536
1.000000000000000021e-03,5.764543993312114430e-04,3.779774418763772749e-04,2.540328419678222955e-04,1.780877776040980329e-04,1.339342982068885400e-04,1.132672798320007770e-04,1.169830787460522149e-04,1.722947974180976999e-04 0.001,0.0007369464655998592,0.0005772268587748353,0.0003791758785432219,0.0002555703831979673,0.00018002165393456068,0.00013649394990366146,0.00011709066577140669,0.00012415690240967774,0.0001928666431485617
1.000000000000000021e-03,5.756578658699793754e-04,3.770814893242558957e-04,2.531987675065141240e-04,1.773173809352787060e-04,1.331664323570320042e-04,1.123811939733057949e-04,1.156878429947367658e-04,1.694949148917899182e-04 0.001,0.0007361671107233329,0.000576414188654825,0.000378260191109379,0.00025471569177879693,0.0001792288130669198,0.00013569785799734456,0.00011615980704210183,0.00012276198311838844,0.00018969202938803596
1.000000000000000021e-03,5.748605464740858808e-04,3.761857558021953151e-04,2.523658789003789082e-04,1.765491102506614579e-04,1.324020056947932127e-04,1.115011960644554309e-04,1.144060580710201219e-04,1.667392091004694466e-04 0.001,0.0007353862783344302,0.000575600327192691,0.00037734431522203,0.00025386185296321013,0.00017843784520433673,0.00013490504014296103,0.00011523503783001357,0.00012138115492992521,0.0001865667844236815
1.000000000000000021e-03,5.740605208264367093e-04,3.752860221900411030e-04,2.515274179172670150e-04,1.757730484194969538e-04,1.316262968484167275e-04,1.106031805667756002e-04,1.130890327345630944e-04,1.638824360782746060e-04 0.001,0.0007346027258369329,0.0005747835721418604,0.00037642443290667116,0.0002530026346493095,0.000177639416207763,0.0001341012793025371,0.0001142922256260196,0.00011996295037667013,0.00018332302768968173
1.000000000000000021e-03,5.732597217139582440e-04,3.743865400085843336e-04,2.506901966657434509e-04,1.749991992264989145e-04,1.308541788026545852e-04,1.097115653341001649e-04,1.117862964715498958e-04,1.610733229285059244e-04 0.001,0.0007338177018431625,0.0005739656376861859,0.00037550439543261463,0.0002521443237629474,0.00017684294734265143,0.00013330094534015117,0.00011335582519792064,0.00011855974750452474,0.00018013280630154984
1.000000000000000021e-03,5.724581527307928295e-04,3.734873153380866809e-04,2.498542195054800734e-04,1.742275621656188764e-04,1.300856406740597557e-04,1.088263113284397853e-04,1.104977038827086933e-04,1.583110954216201049e-04 0.001,0.0007330312083387708,0.0005731465277735759,0.000374584210907019,0.00025128692777751636,0.0001760484420635206,0.00013250403238709868,0.00011242580398299235,0.00011717140625198769,0.000176995286763841
1.000000000000000021e-03,5.716575664778975139e-04,3.725901351223118402e-04,2.490209518882956956e-04,1.734592774731394025e-04,1.293215843757922266e-04,1.079481792373105579e-04,1.092239503861538297e-04,1.555962288273640454e-04 0.001,0.0007322450716827681,0.0005723280950701311,0.00037366577307640326,0.00025043200586833656,0.00017525712146802507,0.00013171151729665014,0.00011150300328069361,0.00011579873047427355,0.00017391111613739919
1.000000000000000021e-03,5.708579584178212615e-04,3.716949912014026899e-04,2.481903820156593069e-04,1.726943281050015661e-04,1.285619816677677630e-04,1.070771097820554131e-04,1.079648627815312081e-04,1.529279069228532445e-04 0.001,0.0007314592892342591,0.0005715103366354928,0.0003727490765712826,0.00024957954955556494,0.0001744689721973381,0.00013092337604814113,0.00011058736861417956,0.00011444154833756723,0.0001708794064250159
1.000000000000000021e-03,5.700593240595020362e-04,3.708018755033176054e-04,2.473624982033243466e-04,1.719326971657234189e-04,1.278068045492097274e-04,1.062130442456755448e-04,1.067202699871894330e-04,1.503053277730467872e-04 0.001,0.0007306738583803173,0.0005706932495677312,0.00037183411609277345,0.00024872955044744495,0.00017368398100343736,0.0001301395848004509,0.00010967884595770732,0.00011309968990727626,0.00016789928423747183
1.000000000000000021e-03,5.692616589508734098e-04,3.699107800243283187e-04,2.465372888514933574e-04,1.711743678703278799e-04,1.270560252111956913e-04,1.053559244063845252e-04,1.054900029091859618e-04,1.477277031714797602e-04 0.001,0.0007298887765314699,0.0005698768309963597,0.00037092088639398746,0.0002478820002115871,0.00017290213471209804,0.00012936011984533696,0.0001087773816703527,0.00011177298701463364,0.00016496989019036454
1.000000000000000021e-03,5.684668249800580104e-04,3.690236622787805977e-04,2.457163959794073484e-04,1.704206404911772779e-04,1.263106878677109810e-04,1.045066466916437628e-04,1.042749156168111009e-04,1.451958181660296986e-04 0.001,0.0007291058850619836,0.0005690629705872476,0.0003700113801847071,0.0002470385774678141,0.00017212477134492983,0.0001285860674779147,0.00010788392632853856,0.00011046237940908493,0.00016209217355659912
1.000000000000000021e-03,5.676748100054150635e-04,3.681404996529084395e-04,2.448997907163580324e-04,1.696714800685054925e-04,1.255707452244580493e-04,1.036651297187654374e-04,1.030748062779383314e-04,1.427088285865420875e-04 0.001,0.0007283251776795193,0.0005682516594285885,0.0003691055790623401,0.0002461992575642169,0.00017135185999287266,0.00012781738439880834,0.00010699840217906239,0.00010916766306641233,0.00015926520709064215
1.000000000000000021e-03,5.668856019606317766e-04,3.672612697075048303e-04,2.440874444423345342e-04,1.689268519744038289e-04,1.248361504800705925e-04,1.028312930702206035e-04,1.018894759794533339e-04,1.402659065748177792e-04 0.001,0.000727546648123048,0.000567442888658507,0.0003682034647519281,0.00024536401604150686,0.00017058337001160307,0.00012705402771768452,0.00010612073231230378,0.0001078886367084761,0.00015648808062028533
1.000000000000000021e-03,5.660978860040193896e-04,3.663833351346186431e-04,2.432754355983019401e-04,1.681813812071888568e-04,1.240994738987429935e-04,1.019939514788640786e-04,1.006986246362622330e-04,1.378144424939918523e-04 0.001,0.0007267691175258129,0.0005666351120658079,0.00036730194585451363,0.00024452825978826814,0.00016981299319253088,0.00012628722374912656,0.00010523753204397677,0.00010660034638564814,0.00015369233245141463
1.000000000000000021e-03,5.653129566917403656e-04,3.655093013788168949e-04,2.424676550876819162e-04,1.674404214250226010e-04,1.233681396595080271e-04,1.011643116013039457e-04,9.952262825359122704e-05,1.354072260989254840e-04 0.001,0.0007259937543683618,0.0005658298620581495,0.00036640409142867466,0.00024369656281803695,0.0001690470312136919,0.00012552576286196436,0.00010436224908854787,0.00010532792661952348,0.00015094700928094292
1.000000000000000021e-03,5.645308021917731225e-04,3.646391464999218838e-04,2.416640749146854532e-04,1.667039386446287719e-04,1.226421015627000995e-04,1.003422934745905857e-04,9.836128786277046102e-05,1.330434286087782230e-04 0.001,0.0007252205525006216,0.0005650271299429238,0.0003655098835814395,0.0002428689011484816,0.0001682854538881413,0.00012476960247399048,0.00010349480634605481,0.00010407117393308648,0.00014825118806841486
1.000000000000000021e-03,5.637533512715803535e-04,3.637748048842355184e-04,2.408662573039999728e-04,1.659731272165147797e-04,1.219222820499958832e-04,9.952864742131557339e-05,9.721524794079934454e-05,1.307234068834026641e-04 0.001,0.0007244515476870691,0.0005642289688561167,0.00036462138604045246,0.00024204694758546622,0.00016752954803985582,0.00012401974721449815,0.00010263603739686231,0.00010283083470852359,0.0001456053538142381
1.000000000000000021e-03,5.629805832911210584e-04,3.629162394326295588e-04,2.400741573155354143e-04,1.652479360999081315e-04,1.212086174287677493e-04,9.872327382660381703e-05,9.608428430098295324e-05,1.284463004684426848e-04 0.001,0.0007236867286572494,0.0005634353625294562,0.0003637385663464586,0.00024123066115747858,0.00016677926586679636,0.00012327613591461942,0.00010178584352378332,0.00010160667618634935,0.0001430085413998934
1.000000000000000021e-03,5.622124777547171659e-04,3.620634133660168507e-04,2.392877304473862261e-04,1.645283148026117340e-04,1.205010447638324016e-04,9.792607442008048754e-05,9.496817636981473815e-05,1.262112668660531425e-04 0.001,0.0007229260842094953,0.0005626462948017631,0.0003628613922977866,0.00024042000126051454,0.00016603456004153966,0.00012253870808207087,0.0001009441272602465,0.00010039846917127745,0.000140459805170444
1.000000000000000021e-03,5.614490142952067260e-04,3.612162901840461500e-04,2.385069325732311319e-04,1.638142133018547766e-04,1.197995017798251111e-04,9.713695214164584071e-05,9.386670693673759554e-05,1.240174806289624668e-04 0.001,0.0007221696032014468,0.000561861749604344,0.00036198983191176377,0.0002396149275989645,0.00016529538363567852,0.00012180740380654271,0.00010011079225737115,9.920598777483068e-05,0.00013795821792425024
1.000000000000000021e-03,5.606917876274927293e-04,3.603765175920537237e-04,2.377331235014221514e-04,1.631066878653574946e-04,1.191048135885559178e-04,9.635658300529022745e-05,9.278045936752733660e-05,1.218652818497198865e-04 0.001,0.0007214188723728384,0.00056108334509554,0.0003611255610840681,0.0002388168283348348,0.00016456282140960994,0.00012108307905286178,9.928655238677393e-05,9.802986918413655e-05,0.0001355041849544529
1.000000000000000021e-03,5.599407711882442139e-04,3.595440474626148916e-04,2.369662455139816704e-04,1.624056743525901679e-04,1.184169030927857740e-04,9.558485302446070387e-05,9.170919453133945438e-05,1.197538170918552259e-04 0.001,0.0007206738776295639,0.0005603110603628828,0.0003602685373417506,0.00023802565027806571,0.00016383681258690845,0.00012036565891864721,9.847129356381268e-05,9.686986333449523e-05,0.0001330967445342526
1.000000000000000021e-03,5.591959386362445371e-04,3.587188321446053963e-04,2.362062415256148103e-04,1.617111093879153761e-04,1.177356942042864595e-04,9.482164989506947420e-05,9.065267746151001182e-05,1.176822517560764241e-04 0.001,0.0007199346049934109,0.0005595448746691314,0.00035941871861020354,0.00023724134078502595,0.00016311729706930416,0.00011965506942237431,9.7664903298557e-05,9.57257243308077e-05,0.00013073495556510661
1.000000000000000021e-03,5.584679347085343051e-04,3.579204847030152616e-04,2.354801209260217886e-04,1.610571916563278928e-04,1.171042314833950021e-04,9.412413419793498636e-05,8.969710985766721223e-05,1.158171674873524301e-04 0.001,0.0007192103057281418,0.0005587965882928195,0.000358597914203722,0.00023649404923234267,0.0001624426539507404,0.00011900000933912548,9.693290327537121e-05,9.469853254875163e-05,0.0001286228242214262
1.000000000000000021e-03,5.577460350040716044e-04,3.571292104088583889e-04,2.347605938090600918e-04,1.604093154405005178e-04,1.164788453357124725e-04,9.343405219685640224e-05,8.875393403591714169e-05,1.139848385910069905e-04 0.001,0.0007184916860834766,0.000558054333130965,0.0003577841401235257,0.0002357533416394368,0.00016177407584741055,0.00011835110239617177,9.620855295571759e-05,9.368449216343134e-05,0.0001265476735456528
1.000000000000000021e-03,5.570302142000897652e-04,3.563449642017089015e-04,2.340476072540025119e-04,1.597674235279283352e-04,1.158594695166401697e-04,9.275131062844492946e-05,8.782296490203555085e-05,1.121846347113116888e-04 0.001,0.000717778732645577,0.0005573180893469085,0.0003569773567342285,0.0002350191694371068,0.0001611115088719043,0.00011770828481211398,9.549176022876216e-05,9.268341301362701e-05,0.00012450880618841231
1.000000000000000021e-03,5.563205323021954991e-04,3.555677864531773679e-04,2.333411773810724506e-04,1.591315117132938270e-04,1.152460793074575203e-04,9.207585166649024939e-05,8.690405384945894284e-05,1.104159825692847303e-04 0.001,0.0007170715507844816,0.0005565879566941514,0.0003561776441627035,0.00023429158098135867,0.00016045497378223205,0.00011707155159443024,9.47824835635146e-05,9.169515755193108e-05,0.00012250560759307665
1.000000000000000021e-03,5.556169640414684949e-04,3.547976323593042547e-04,2.326412517183593022e-04,1.585015234268918286e-04,1.146386094395640093e-04,9.140758389001004606e-05,8.599702078916069998e-05,1.086782756746748250e-04 0.001,0.0007163701270344053,0.0005558639152622166,0.0003553849627325309,0.00023357052778616886,0.00015980441694230793,0.00011644083951173604,9.408063218207804e-05,9.071953997714039e-05,0.00012053740486430812
1.000000000000000021e-03,5.549194843577821444e-04,3.540344575531629255e-04,2.319477783590319386e-04,1.578774027587701891e-04,1.140369954748351631e-04,9.074641718074756330e-05,8.510168863112195785e-05,1.069709201912467553e-04 0.001,0.0007156744480415676,0.0005551459453084167,0.00035459927313802623,0.00023285596185845654,0.00015915978530381373,0.00011581608608941654,9.338611653058621e-05,8.975637744384618e-05,0.00011860353870291344
1.000000000000000021e-03,5.542280683854123842e-04,3.532782180675540329e-04,2.312607059053527040e-04,1.572590943887706505e-04,1.134411737206307899e-04,9.009226260907148270e-05,8.421788308143062266e-05,1.052933342707317640e-04 0.001,0.0007149845005557793,0.0005544340272448129,0.0003538205364097734,0.0002321478356456351,0.0001585210263398076,0.00011519722952770958,9.269884816673769e-05,8.880548985453175e-05,0.00011670336266552508
1.000000000000000021e-03,5.535435592528614506e-04,3.525297669260542646e-04,2.305807244353639423e-04,1.566471216497641210e-04,1.128515385449576329e-04,8.944542244330133641e-05,8.334582247054855841e-05,1.036454797753234207e-04 0.001,0.0007143011352806332,0.0005537290222260827,0.0003530496254918224,0.00023144685778402562,0.00015788868071804074,0.00011458468167101622,9.20191492389152e-05,8.786712068874325e-05,0.00011483685132763588
1.000000000000000021e-03,5.528659293179593237e-04,3.517890550472092793e-04,2.299077767025847687e-04,1.560414233076215052e-04,1.122680202866636689e-04,8.880580140054516926e-05,8.248532556564376009e-05,1.020267728319692934e-04 0.001,0.0007136243377311475,0.0005530309085687206,0.00035228649684153725,0.0002307529751854999,0.00015726269010384348,0.00011397837465469773,9.134692457668887e-05,8.694108196461404e-05,0.00011300335424584403
1.000000000000000021e-03,5.521951511907441769e-04,3.510560338657343622e-04,2.292418061160320900e-04,1.554419388795865483e-04,1.116905502099227850e-04,8.817330560855271690e-05,8.163621425685595255e-05,1.004366420798761639e-04 0.001,0.0007129540935643617,0.0005523396647985742,0.000351531107363628,0.0002300661353432777,0.0001566429968410848,0.00011337824146720777,9.06820803490277e-05,8.602718880727694e-05,0.00011120223452206596
1.000000000000000021e-03,5.515357570680511773e-04,3.503384240935171457e-04,2.285926195257032088e-04,1.548599664871607589e-04,1.111316359132737570e-04,8.756139732097920178e-05,8.081143045355856274e-05,9.887558842870256459e-05 0.001,0.0007122949300063586,0.0005516609446370161,0.0003507932546232374,0.0002293990178082647,0.00015604454205901748,0.00011280134646728481,9.004396195380538e-05,8.514641523915274e-05,0.00010944396621311202
1.000000000000000021e-03,5.508831499695134287e-04,3.496283778737561509e-04,2.279502431225978031e-04,1.542840041018178729e-04,1.105785086338880569e-04,8.695624145470242240e-05,7.999741899881025698e-05,9.734197099681332458e-05 0.001,0.0007116422850379047,0.0005509890404263221,0.00035006301886912226,0.00022873877079420107,0.00015545216193435095,0.00011223032450910806,8.941277122627028e-05,8.427699754143763e-05,0.00010771649233683978
1.000000000000000021e-03,5.502373034395177318e-04,3.489258487042028742e-04,2.273146231686837553e-04,1.537139948092133693e-04,1.100311043442569531e-04,8.635775141128424154e-05,7.919401605398894981e-05,9.583525507692383649e-05 0.001,0.0007109961448775265,0.0005503239315436604,0.00034934035900275196,0.00022808534468017605,0.00015486580256638324,0.00011166511373672321,8.878842266662507e-05,8.341876815036907e-05,0.00010601922394974779
1.000000000000000021e-03,5.495982753581815606e-04,3.482308738101717264e-04,2.266857730549029851e-04,1.531499327576744506e-04,1.094893985055618503e-04,8.576587362490598130e-05,7.840109070036870779e-05,9.435495486246966317e-05 0.001,0.0007103566138672342,0.0005496657159311855,0.0003486253516297722,0.00022743878433373037,0.00015428548213839886,0.00011110570832676001,8.81708780194749e-05,8.25716070442755e-05,0.00010435164299643007
1.000000000000000021e-03,5.489660394111083985e-04,3.475434070850742167e-04,2.260636396270461598e-04,1.525917617808240120e-04,1.089533281238570496e-04,8.518052329278025009e-05,7.761848365092111231e-05,9.290055631012179708e-05 0.001,0.0007097236782517396,0.0005490143729973408,0.0003479179557857281,0.0002267990403962617,0.0001537111471536449,0.00011055204708289399,8.756005313455197e-05,8.173535064610718e-05,0.0001027131817052566
1.000000000000000021e-03,5.483405695169031721e-04,3.468634028939242666e-04,2.254481703234268038e-04,1.520394263837190755e-04,1.084228310216190315e-04,8.460161684084565312e-05,7.684603831721497692e-05,9.147155629123523643e-05 0.001,0.0007090973244087274,0.0005483698823458906,0.00034721813091834777,0.000226166064037726,0.00015314274472297157,0.00011000406955950422,8.695586501935841e-05,8.090983803329783e-05,0.00010110328401062253
1.000000000000000021e-03,5.477218398160970184e-04,3.461908160447295835e-04,2.248393131323322177e-04,1.514928716901747189e-04,1.078978457743454979e-04,8.402907183940372035e-05,7.608360066029366266e-05,9.006746210081428210e-05 0.001,0.0007084775388425413,0.0005477322237660661,0.0003465258368613831,0.00022553980691704316,0.00015258022251510344,0.00010946171600087524,8.635823175652435e-05,8.00949107862898e-05,9.952140501322636e-05
1.000000000000000021e-03,5.471100509830739483e-04,3.455258336641454844e-04,2.242372067336963117e-04,1.509521904405796073e-04,1.073784265457052923e-04,8.346290305268591516e-05,7.533111218717854750e-05,8.868791149478115541e-05 0.001,0.0007078645400735427,0.0005471016129101978,0.0003458412757255009,0.00022492042013778988,0.00015202368335334558,0.00010892504915290583,8.57671759148139e-05,7.929051589048381e-05,9.796715152670613e-05
1.000000000000000021e-03,5.465051768578450733e-04,3.448684100639811626e-04,2.236417986238402995e-04,1.504173273640432558e-04,1.068645117117092864e-04,8.290302835464549746e-05,7.458842111919879593e-05,8.733242665255502488e-05 0.001,0.0007072583145347741,0.0005464780293804963,0.00034516440688163317,0.00022430785483116316,0.0001514730744232032,0.00010839400891826328,8.518261565996433e-05,7.84964968569563e-05,9.643999410136803e-05
1.000000000000000021e-03,5.459071915129861232e-04,3.442185000233075119e-04,2.230530368831633737e-04,1.498882278486614187e-04,1.063560404456327061e-04,8.234936680962616474e-05,7.385537825478157199e-05,8.600053991717240256e-05 0.001,0.0007066588487940405,0.000545861452976259,0.0003444951901125997,0.00022370206265319418,0.00015092834351042303,0.00010786853593723236,8.460447028623623e-05,7.771269974698105e-05,9.493941424410264e-05
1.000000000000000021e-03,5.453277270883248422e-04,3.435968835063559607e-04,2.224987019123045480e-04,1.493989071766017103e-04,1.058939742146122178e-04,8.185283432112488435e-05,7.320083692872619591e-05,8.480120525436834187e-05 0.001,0.0007060768113835355,0.0005452653567881146,0.00034385780916102886,0.0002231355522451839,0.0001504295746545273,0.00010739737531972382,8.409424224945842e-05,7.702434963545377e-05,9.360618912201228e-05
1.000000000000000021e-03,5.447550756300442850e-04,3.429826158632724655e-04,2.219507707465509202e-04,1.489150144895505707e-04,1.054368625228528346e-04,8.136171358212484941e-05,7.255437084770181432e-05,8.362138199130290570e-05 0.001,0.0007055014939207988,0.0005446762036784223,0.00034322791998477503,0.0002225755642266546,0.00014993632274793293,0.00010693123855410087,8.358951092264173e-05,7.634435339541097e-05,9.22944227993744e-05
1.000000000000000021e-03,5.441892122953419404e-04,3.423756544954533452e-04,2.214091954721005766e-04,1.484365007267826825e-04,1.049846526338566485e-04,8.087593753205775274e-05,7.191586230794716592e-05,8.246071125248328093e-05 0.001,0.0007049328836329239,0.0005440939744776738,0.0003426054850001757,0.00022202205441602206,0.000149448541485554,0.00010647007505716636,8.309021096715739e-05,7.567259318109089e-05,9.100372969350909e-05
1.000000000000000021e-03,5.436257869834306257e-04,3.417717090501741430e-04,2.208705585733095858e-04,1.479607869104501987e-04,1.045353737048878776e-04,8.039389156994272538e-05,7.128377081045688692e-05,8.131715986317171246e-05 0.001,0.0007043664108869901,0.0005435140913972429,0.00034198598587466614,0.00022147141590047654,0.00014896349766232102,0.00010601178096740148,8.259459730216135e-05,7.500736724232048e-05,8.973176442333615e-05
1.000000000000000021e-03,5.430647907230928004e-04,3.411707635569704330e-04,2.203348411819341208e-04,1.474878525008424264e-04,1.040890016129762040e-04,7.991554062444546221e-05,7.065802258502740848e-05,8.019045690600123673e-05 0.001,0.0007038020712072354,0.0005429365478183962,0.00034136940918446675,0.0002209236320980648,0.00014848117283038098,0.00010555633431743894,8.210263744821714e-05,7.434860458126827e-05,8.847824135377829e-05
1.000000000000000021e-03,5.425062145452035425e-04,3.405728020832017003e-04,2.198020245085192449e-04,1.470176770797095381e-04,1.036455124224165388e-04,7.944084996986793814e-05,7.003854478529189314e-05,7.908033605497744685e-05 0.001,0.0007032398600991381,0.0005423613371043419,0.00034075574151016483,0.0002203786864681782,0.00014800154862415601,0.00010510371328265478,8.161429921011451e-05,7.369623501807121e-05,8.724287943554497e-05
1.000000000000000021e-03,5.419500494783734655e-04,3.399778087230425684e-04,2.192720898259863408e-04,1.465502403299397984e-04,1.032048823605461293e-04,7.896978519468913008e-05,6.942526543493823701e-05,7.798653539704048551e-05 0.001,0.0007026797730466592,0.0005417884525961108,0.00034014496942632764,0.0002198365624959981,0.00014752460674093983,0.00010465389615779026,8.112955064604149e-05,7.305018913687007e-05,8.602540201539488e-05
1.000000000000000021e-03,5.413941311127808435e-04,3.393835756573481376e-04,2.187432334857416756e-04,1.460841531649274296e-04,1.027660304092932323e-04,7.850144313387483587e-05,6.881729624423716459e-05,7.690779566810491681e-05 0.001,0.0007021196874055633,0.0005412157406692665,0.0003395348927353949,0.00021929545761274023,0.00014704895219343257,0.00010420578859113516,8.064746506639534e-05,7.240953347459202e-05,8.482441661675139e-05
1.000000000000000021e-03,5.408384570747234218e-04,3.387900992487282684e-04,2.182154508640741402e-04,1.456194096560940569e-04,1.023289477092565169e-04,7.803580657419308998e-05,6.821458972979072498e-05,7.584390730667668775e-05 0.001,0.0007015596012323657,0.0005406431992153213,0.0003389255082691921,0.00021875536780717296,0.00014657457987728414,0.00010375938295149973,8.016802726693694e-05,7.17742234562459e-05,8.363970356449741e-05
1.000000000000000021e-03,5.402830249660243826e-04,3.381973758275843189e-04,2.176887373150658610e-04,1.451560038709627043e-04,1.018936254270842219e-04,7.757285840469518032e-05,6.761709884283491779e-05,7.479466373034050742e-05 0.001,0.0007009995125587165,0.0005400708260946051,0.0003383168128172846,0.00021821628903476192,0.00014610148467187763,0.0001033146716169485,7.969122211456026e-05,7.114421486558773e-05,8.247104609297546e-05
1.000000000000000021e-03,5.397131798668998448e-04,3.375789411508863902e-04,2.171273238640323091e-04,1.446496280566233409e-04,1.014059885387841374e-04,7.704415358894297196e-05,6.692941074150365747e-05,7.359880640935691578e-05 0.001,0.000700426120570031,0.0005394817717340144,0.00033767827777106695,0.00021763678242090514,0.00014557802543177205,0.00010280805245363877,7.913535785684264e-05,7.040274681183516e-05,8.111172191387726e-05
1.000000000000000021e-03,5.391436022217508317e-04,3.369613465901344558e-04,2.165671485747253328e-04,1.441448734692186333e-04,1.009205829600201576e-04,7.651897498112265308e-05,6.624864922679121694e-05,7.242198835523922060e-05 0.001,0.0006998527383823768,0.0005388929110101418,0.0003370405259007354,0.00021705847496470142,0.00014505616500334602,0.00010230367256069614,7.858312049704058e-05,6.966868896041247e-05,7.977423771714316e-05
1.223599761281599736e-03,2.870574988594920204e-03,5.410558860144323162e-03,9.740321680379944794e-03,1.718226620812626088e-02,3.032327552654904765e-02,5.460894525232919822e-02,1.025522470341594938e-01,2.059999999999999887e-01 0.0010496228983614124,0.002020602352332682,0.0024834354692445607,0.004712247621156641,0.00854174709233096,0.015197203876184536,0.027142477151470907,0.049749449744480465,0.09589624880110185,0.2
4.083745694274921144e-03,8.369042825128880300e-03,1.439530071705045523e-02,2.397223043565064812e-02,3.897486419880552555e-02,6.202545653148217042e-02,9.626510461383173956e-02,1.437785279168776742e-01,2.000000000000000111e-01 0.004235602571438949,0.007336805952289255,0.008714058005603317,0.015024716476258112,0.025061770718850837,0.04079161627542227,0.0649508755581543,0.10074574737193842,0.14993445055894863,0.206
1 1.000000000000000021e-03 0.001 6.059428294303585358e-04 0.0007651928200015371 4.124436878765448634e-04 0.0006070713937965498 2.874462507798667202e-04 0.00041423535558437785 2.103923932407651741e-04 0.0002897888610631573 1.678414792051835720e-04 0.00021340907299884933 1.547359756068614396e-04 0.00017198131811953097 1.816771264024174659e-04 0.00016127923791982795 3.223716208702616772e-04 0.00019503601408127412 0.00036549739730595273
2 1.000000000000000021e-03 0.001 6.053134417926274479e-04 0.0007645995806173374 4.117055522849718272e-04 0.0006064422887178694 2.867345754340725936e-04 0.00041349144049413134 2.097129658661858059e-04 0.00028906380160320487 1.671408382188599656e-04 0.00021270693331134475 1.538980727463440737e-04 0.0001712438796411692 1.804148897825019347e-04 0.0001603765556252246 3.196786917797407482e-04 0.00019363496213474675 0.00036239423700181427
3 1.000000000000000021e-03 0.001 6.046849734433535663e-04 0.0007640065772643761 4.109690875237402238e-04 0.0006058136176614386 2.860250085842350751e-04 0.00041274866023030733 2.090360511584246736e-04 0.0002883403899406645 1.664434237997556567e-04 0.0002120069527025505 1.530650313352837862e-04 0.00017050944162049183 1.791618737991747007e-04 0.000159478716966613 3.170092948646618079e-04 0.00019224364342300643 0.0003593168093314386
4 1.000000000000000021e-03 0.001 6.040574211994215528e-04 0.0007634138087852742 4.102342878398261821e-04 0.000605185379478 2.853175420730359193e-04 0.0004120070127662441 2.083616379079277403e-04 0.0002876186224176594 1.657492189637676920e-04 0.00021130912485491145 1.522368203677859210e-04 0.00016977799240843955 1.779180061767344980e-04 0.0001585856969223786 3.143632101370558260e-04 0.00019086199210672448 0.0003562649023666937
5 1.000000000000000021e-03 0.001 6.034068048547004811e-04 0.0007628028346998721 4.094522032835132145e-04 0.0006045332187986192 2.845379038962591819e-04 0.0004112166712442958 2.075849237814657072e-04 0.0002868226029691562 1.649065028354379026e-04 0.00021050564591298308 1.511673145690444625e-04 0.0001688917074786142 1.761800891032866087e-04 0.00015743651373617922 3.101696013411107001e-04 0.00018893812235512526 0.0003514029291704815
6 1.000000000000000021e-03 0.001 6.027571485450614400e-04 0.0007621921143131398 4.086719523190792173e-04 0.0006038815297458003 2.837607352174946669e-04 0.00041042762231867933 2.068114158243908936e-04 0.00028602858816935265 1.640683639230874002e-04 0.00020970502628600424 1.501056331894667201e-04 0.00016800982241073787 1.744595725998800725e-04 0.00015629534163924753 3.060328853710948794e-04 0.00018703308452519017 0.00034660591682276115
7 1.000000000000000021e-03 0.001 6.021084488423111532e-04 0.0007615816463554626 4.078935283235860985e-04 0.0006032303109890501 2.829860258399657913e-04 0.0004096398633263614 2.060410983394430761e-04 0.0002852365728026657 1.632347745793864737e-04 0.00020890725596775628 1.490517152618393740e-04 0.00016713231600712825 1.727562758069566841e-04 0.00015516212643578583 3.019522704750103072e-04 0.00018514669874176095 0.00034187301148734186
8 1.000000000000000021e-03 0.001 6.014584946769776846e-04 0.0007609692265548555 4.071145901524401327e-04 0.000602577299493926 2.822117789926256531e-04 0.0004088509941253184 2.052723360542508288e-04 0.00028444450359523985 1.624043320606193702e-04 0.00020811064471691694 1.480041851535097400e-04 0.00016625772561605027 1.710684425093964716e-04 0.00015403541161623416 2.979241342510260699e-04 0.00018327705284413884 0.00033720006213702974
9 1.000000000000000021e-03 0.001 6.008072907871274187e-04 0.0007603548574442921 4.063351463691671850e-04 0.0006019224999904981 2.814380028310788616e-04 0.0004080610253035772 2.045051334722086352e-04 0.00028365239238410656 1.615770319309204608e-04 0.0002073152021201705 1.469630126571907884e-04 0.00016538605339556675 1.693959447695294284e-04 0.00015291517504370476 2.939478272988644745e-04 0.00018142402424673905 0.0003325863766610152
10 1.000000000000000021e-03 0.001 6.001497788207915121e-04 0.0007597350402439383 4.055445944921290597e-04 0.0006012612395706585 2.806482406689155018e-04 0.0004072600935672035 2.037157793952982566e-04 0.0002828447987841907 1.607178158735042268e-04 0.00020649842223713097 1.458699426620449350e-04 0.00016448344741808307 1.676159912510077627e-04 0.00015174362495246272 2.896237141368235984e-04 0.00017946021794659197 0.00032758319657592714
11 1.000000000000000021e-03 0.001 5.994910374944025042e-04 0.0007591132829776185 4.047535948218318100e-04 0.0006005982088110791 2.798590565363265966e-04 0.0004064581175876688 2.029281739019909579e-04 0.00028203726728774387 1.598620980598530251e-04 0.00020568299547110922 1.447840125437445142e-04 0.00016358411213968798 1.658536074234625343e-04 0.00015057934813125987 2.853613427461420497e-04 0.00017751539893581778 0.00032265060787650516
12 1.000000000000000021e-03 0.001 5.988260139740232213e-04 0.000758484736453085 4.039566207302157830e-04 0.0005999283660908604 2.790656268334378021e-04 0.0004056495676510805 2.021383019157014865e-04 0.00028122495212139567 1.590064003284783227e-04 0.00020486486304104927 1.437018088215471850e-04 0.00016268449575399985 1.641044980680633682e-04 0.00014941879820841596 2.811520890672289147e-04 0.00017558496339953558 0.0003177787884410679
13 1.000000000000000021e-03 0.001 5.981547295973556680e-04 0.0007578494094215417 4.031537149116132062e-04 0.0005992517275730322 2.782680029999613086e-04 0.0004048344831924046 2.013462168991827844e-04 0.000280407904430663 1.581507747250400562e-04 0.00020404408117776887 1.426233730149128554e-04 0.0001617846565020927 1.623686402996199669e-04 0.00014826202727426984 2.769954674673250896e-04 0.00017366890284920263 0.0003129672376410902
14 1.000000000000000021e-03 0.001 5.974772058480589884e-04 0.0007572073108060312 4.023449202032754039e-04 0.0005985683096346821 2.774662364916018848e-04 0.0004040129039083478 2.005519721420980883e-04 0.0002795861755026316 1.572952728586730247e-04 0.00020322070604404603 1.415487458023807841e-04 0.00016088465224596546 1.606460099014084351e-04 0.00014710908652278506 2.728909933446289080e-04 0.00017176720707727308 0.00030821545426856767
15 1.000000000000000021e-03 0.001 5.967924602151245417e-04 0.0007565575890478602 4.015280354275974962e-04 0.00059787696153193 2.766567170422079059e-04 0.0004031823074325593 1.997501120648868605e-04 0.00027875567967892653 1.564314572956195643e-04 0.00020238859856737548 1.404632320601022135e-04 0.00015997497741322437 1.589039550526354799e-04 0.00014594324831107206 2.687258582080010155e-04 0.00016984173084389243 0.0003033838449669414
16 1.000000000000000021e-03 0.001 5.961015210291329552e-04 0.0007559011152632264 4.007053572943599577e-04 0.0005971788697390111 2.758431797434220318e-04 0.00040234530612592536 1.989462429758611403e-04 0.0002779206290242912 1.555679612182393453e-04 0.00020155405878687617 1.393818318435550562e-04 0.00015906535701622418 1.571757793000612348e-04 0.0001447815990558725 2.646152969711955188e-04 0.00016793142878541938 0.0002986152551090434
17 1.000000000000000021e-03 0.001 5.954044103428367566e-04 0.000755237898986442 3.998769294251378363e-04 0.000596474051424026 2.750256766566040972e-04 0.00040150194087318277 1.981404183299118591e-04 0.00027708107588917086 1.547048355449558708e-04 0.00020071714346489746 1.383045830163869136e-04 0.00015815584855490808 1.554614480121203164e-04 0.00014362418708307366 2.605587686095252363e-04 0.00016603627832169687 0.00029390910930431773
18 1.000000000000000021e-03 0.001 5.947013777400173224e-04 0.0007545681886825906 3.990430339362700481e-04 0.0005957627683701927 2.742044609070656662e-04 0.00040065250958751827 1.973328535702731791e-04 0.00027623729012494873 1.538422664307762401e-04 0.00019987808563904174 1.372316495983985922e-04 0.00015724665811831285 1.537610729441031576e-04 0.0001424712015659587 2.565559887984316962e-04 0.00016415642490307197 0.0002892651425802985
19 1.000000000000000021e-03 0.001 5.939924446448691022e-04 0.0007538919937536639 3.982037130272156897e-04 0.0005950450374279253 2.733795825341983144e-04 0.0003997970520738093 1.965235995659166514e-04 0.0002753893223189692 1.529803013963573505e-04 0.00019903693960802692 1.361630645638145173e-04 0.00015633783972296886 1.520746117923915490e-04 0.0001413226854400146 2.526064078268458078e-04 0.00016229183664828758 0.0002846827650697017
20 1.000000000000000021e-03 0.001 5.932708072008613994e-04 0.0007532045557665671 3.973448313523968048e-04 0.0005943145247994342 2.725292879585060313e-04 0.0003989223236188871 1.956816407574392804e-04 0.00027451662339635243 1.520737532268283138e-04 0.0001981640806362608 1.350253536692922732e-04 0.00015538551594067732 1.502520417395671493e-04 0.00014010540813129958 2.482429369311983419e-04 0.00016028630721570607 0.00027963581042999
21 1.000000000000000021e-03 0.001 5.925433291275937313e-04 0.0007525106592079478 3.964806700993557770e-04 0.0005935776116184588 2.716755655440644093e-04 0.00039804170193550713 1.948383564731119815e-04 0.0002736399653899091 1.511684275731327428e-04 0.00019728948692008958 1.338932464840604031e-04 0.00015443417816766013 1.484467502756363724e-04 0.00013889388158999866 2.439468427807235304e-04 0.0001582996284854468 0.0002746667454821644
22 1.000000000000000021e-03 0.001 5.918101288584805405e-04 0.0007518104383956622 3.956113769664689763e-04 0.000592834444449282 2.708185566039283476e-04 0.0003971553683797481 1.939938721213093850e-04 0.0002727595219957832 1.502644330979066827e-04 0.00019641331428482412 1.327668256867655240e-04 0.00015348396557824612 1.466587172007617287e-04 0.00013768822268133468 2.397173806066686273e-04 0.000156331819705631 0.00026977480754699626
23 1.000000000000000021e-03 0.001 5.910712282476807177e-04 0.0007511039033537896 3.947369945531709078e-04 0.0005920850408658466 2.699583111402765676e-04 0.0003962633635582371 1.931482375169864133e-04 0.00027187534416274955 1.493618135415682949e-04 0.00019553561634171146 1.316461114156967569e-04 0.00015253492870981108 1.448878476419733323e-04 0.00013648846139846028 2.355536787532183434e-04 0.00015438279270990136 0.0002649590347362105
24 1.000000000000000021e-03 0.001 5.903266492974269808e-04 0.0007503910642803073 3.938575655934699066e-04 0.0005913294186556257 2.690948791496987824e-04 0.0003953657283217157 1.923015022699072797e-04 0.0002709874829437419 1.484606121781560119e-04 0.00019465644657888978 1.305311230155930472e-04 0.0001515871176567501 1.431340460611192763e-04 0.0001352946268320504 2.314548735305102924e-04 0.0001524524582210848 0.0002602184722292356
25 1.000000000000000021e-03 0.001 5.895916361077759233e-04 0.0007496855573046408 3.930015889157450278e-04 0.0005905851062898704 2.682679585446747167e-04 0.00039449552403657745 1.915046725018171748e-04 0.00027014241927282736 1.476265343831741983e-04 0.0001938361803657908 1.295122987364192039e-04 0.0001507194393001951 1.415403000102364922e-04 0.00013421767536698768 2.277048762028301403e-04 0.000150722476765932 0.0002559376038022294
26 1.000000000000000021e-03 0.001 5.888509505821538188e-04 0.0007489737467556278 3.921405251235485093e-04 0.0005898345737440663 2.674377005486313469e-04 0.000393619635985906 1.907064029438769275e-04 0.00026929349394052985 1.467931904457939435e-04 0.00019301404332913125 1.284977589807231727e-04 0.00014985216957655317 1.399600943498011466e-04 0.00013314488789598826 2.240084844157824847e-04 0.00014900672746282064 0.00025171693602497907
27 1.000000000000000021e-03 0.001 5.881046147353881284e-04 0.0007482556429977025 3.912744162777674595e-04 0.0005890778388714725 2.666041537474170709e-04 0.00039273810426086416 1.899067416692393098e-04 0.0002684407562332248 1.459606238177286390e-04 0.0001921900867993824 1.274875313353729649e-04 0.00014898535811302548 1.383933775516596422e-04 0.00013207630234912348 2.203650745808937968e-04 0.00014730517414690737 0.000247555825445753
28 1.000000000000000021e-03 0.001 5.873535041835053691e-04 0.000747532135526673 3.904041908037584924e-04 0.0005883158165865031 2.657681073335506784e-04 0.0003918519024244402 1.891063272435359547e-04 0.00026758503804540166 1.451293640595985746e-04 0.0001913649895279964 1.264820875947550167e-04 0.00014811957577380352 1.368405966876043531e-04 0.00013101244041258906 2.167748460671411873e-04 0.0001456183389249714 0.00024345460151209766
29 1.000000000000000021e-03 0.001 5.865976375297720377e-04 0.0007468032330641541 3.895298843642901903e-04 0.0005875485221384682 2.649296021207307814e-04 0.0003909610648762846 1.883051991594097421e-04 0.00026672638132361175 1.442994447916011967e-04 0.0001905387943939666 1.254814426573682665e-04 0.00014725486211264363 1.353016807452276011e-04 0.00012995332641946747 2.132371421364682767e-04 0.00014394616337354944 0.00023941257691738652
30 1.000000000000000021e-03 0.001 5.858370334908887412e-04 0.0007460689444707028 3.886515327161476187e-04 0.0005867759709451519 2.640886789067201177e-04 0.0003900656262003575 1.875033967487228748e-04 0.00026586482808789615 1.434708992929061271e-04 0.00018971154418348472 1.244856108614830043e-04 0.00014639125636754904 1.337765582492128895e-04 0.00012889898406950181 2.097513117892475961e-04 0.00014228858823944247 0.00023542906884335907
31 1.000000000000000021e-03 0.001 5.850717109173866415e-04 0.0007453292787585437 3.877691717638952012e-04 0.0005859981786120694 2.632453785571107932e-04 0.0003891656212152682 1.867009592919541521e-04 0.00026500042051039684 1.426437606415217971e-04 0.000188883281693472 1.234946061839636009e-04 0.0001455287975953345 1.322651576281378186e-04 0.000127849436626481 2.063167108712882474e-04 0.0001406455538271199 0.00023150340029334736
32 1.000000000000000021e-03 0.001 5.843017841779564719e-04 0.0007445843685250069 3.868829399849727933e-04 0.0005852152884984452 2.623998297381095117e-04 0.0003882612223549495 1.858979973489535589e-04 0.00026413331906842847 1.418181214209275826e-04 0.00018805414639063353 1.225084976697060233e-04 0.00014466760638632992 1.307674705482058720e-04 0.00012680478406473458 2.029328092689827875e-04 0.00013901709088191773 0.00022763506393382832
33 1.000000000000000021e-03 0.001 5.835272719783185817e-04 0.0007438342228409441 3.859928727352694559e-04 0.0005844273161744179 2.615520723807220407e-04 0.0003873524639441998 1.850945488934469029e-04 0.00026326356496406687 1.409940129261724197e-04 0.00018722417962072503 1.215272967897141737e-04 0.0001438077197030893 1.292834223062770812e-04 0.00012576504647438162 1.995989685833853672e-04 0.00013740313489262333 0.00022382338328436597
34 1.000000000000000021e-03 0.001 5.827481931390192209e-04 0.0007430788509165626 3.850990054645316799e-04 0.0005836342773781009 2.607021463995574332e-04 0.0003864393804873395 1.842906517410432266e-04 0.0002623911994661588 1.401714661235729505e-04 0.00018639342263244998 1.205510144929276286e-04 0.00014294917419819004 1.278129378421479238e-04 0.000124730243348245 1.963145562589016025e-04 0.00013580362065026603 0.00022006768669446508
35 1.000000000000000021e-03 0.001 5.819741190680906414e-04 0.000742327254060605 3.842186528659996786e-04 0.0005828476385639736 2.598733678747139103e-04 0.00038554300530339766 1.835150990942780922e-04 0.00026154496076193957 1.393856353878371876e-04 0.00018559797011481673 1.196241043053028848e-04 0.0001421370333657246 1.264157249384978508e-04 0.00012375932796391997 1.931533527071859933e-04 0.00013430279846409174 0.00021649152387618443
36 1.000000000000000021e-03 0.001 5.811954906857532679e-04 0.0007415704350109161 3.833344911530978875e-04 0.0005820559385468977 2.590423495637437460e-04 0.00038464228372291103 1.827389251971546448e-04 0.0002606960153281244 1.386010231640464696e-04 0.00018480150743526303 1.187014313463915350e-04 0.00014132579578003348 1.250305871218520724e-04 0.000122792459010487 1.900379005692562904e-04 0.0001328143978658426 0.0002129659469511457
37 1.000000000000000021e-03 0.001 5.804123268686601621e-04 0.0007408084031449065 3.824465553881609072e-04 0.0005812591931755618 2.582091305240798466e-04 0.00038373724983374976 1.819621668943112273e-04 0.00025984440338310303 1.378176602140172575e-04 0.0001840040745362742 1.177830097537161525e-04 0.0001405154975809745 1.236574657124121280e-04 0.00012182965960439977 1.869676369318762604e-04 0.00013133837476817992 0.00020949038404752677
38 1.000000000000000021e-03 0.001 5.796261981805348861e-04 0.0007400427720784002 3.815564763513873891e-04 0.0005804590496942265 2.573750710547324729e-04 0.00038282961864956994 1.811859034357266680e-04 0.0002589915613698488 1.370364232713841633e-04 0.00018320681873232144 1.168696105278517803e-04 0.00013970708155515462 1.222971239749574140e-04 0.00012087177639736769 1.839432835829867073e-04 0.00012987560432955444 0.00020606578076074432
39 1.000000000000000021e-03 0.001 5.788371166298537929e-04 0.0007392735475065714 3.806642767897665215e-04 0.0005796555183614057 2.565401959245502722e-04 0.00038191941292656456 1.804101566728638260e-04 0.0002581375157328154 1.362573268495191094e-04 0.0001824097650442608 1.159612279572367423e-04 0.00013890056717630873 1.209494737333099285e-04 0.00011991881140841177 1.809642226433420603e-04 0.0001284260094133047 0.00020269149646849757
40 1.000000000000000021e-03 0.001 5.780450942923127944e-04 0.0007385007352097838 3.797699794962239458e-04 0.0005788486095364762 2.557045298790712744e-04 0.00038100665551987393 1.796349483543752492e-04 0.00025728229294257515 1.354803852765658562e-04 0.00018161293842329387 1.150578560981921263e-04 0.00013809597373520515 1.196144270262388971e-04 0.00011897076635433426 1.780298433107154344e-04 0.0001269895128043655 0.00019936689671873207
41 1.000000000000000021e-03 0.001 5.772501433097143196e-04 0.0007377243410529983 3.788736073065085246e-04 0.0005780383336785572 2.548680976361037374e-04 0.0003800913693799712 1.788603001211915217e-04 0.0002564259194903244 1.347056126906417029e-04 0.00018081636374445108 1.141594887707218423e-04 0.00013729332033271256 1.182918961012392148e-04 0.00011802764264291933 1.751395417672447184e-04 0.00012556603720150224 0.00019609135315036536
42 1.000000000000000021e-03 0.001 5.764543993312114430e-04 0.0007369464655998592 3.779774418763772749e-04 0.0005772268587748353 2.540328419678222955e-04 0.0003791758785432219 1.780877776040980329e-04 0.0002555703831979673 1.339342982068885400e-04 0.00018002165393456068 1.132672798320007770e-04 0.00013649394990366146 1.169830787460522149e-04 0.00011709066577140669 1.722947974180976999e-04 0.00012415690240967774 0.0001928666431485617
43 1.000000000000000021e-03 0.001 5.756578658699793754e-04 0.0007361671107233329 3.770814893242558957e-04 0.000576414188654825 2.531987675065141240e-04 0.000378260191109379 1.773173809352787060e-04 0.00025471569177879693 1.331664323570320042e-04 0.0001792288130669198 1.123811939733057949e-04 0.00013569785799734456 1.156878429947367658e-04 0.00011615980704210183 1.694949148917899182e-04 0.00012276198311838844 0.00018969202938803596
44 1.000000000000000021e-03 0.001 5.748605464740858808e-04 0.0007353862783344302 3.761857558021953151e-04 0.000575600327192691 2.523658789003789082e-04 0.00037734431522203 1.765491102506614579e-04 0.00025386185296321013 1.324020056947932127e-04 0.00017843784520433673 1.115011960644554309e-04 0.00013490504014296103 1.144060580710201219e-04 0.00011523503783001357 1.667392091004694466e-04 0.00012138115492992521 0.0001865667844236815
45 1.000000000000000021e-03 0.001 5.740605208264367093e-04 0.0007346027258369329 3.752860221900411030e-04 0.0005747835721418604 2.515274179172670150e-04 0.00037642443290667116 1.757730484194969538e-04 0.0002530026346493095 1.316262968484167275e-04 0.000177639416207763 1.106031805667756002e-04 0.0001341012793025371 1.130890327345630944e-04 0.0001142922256260196 1.638824360782746060e-04 0.00011996295037667013 0.00018332302768968173
46 1.000000000000000021e-03 0.001 5.732597217139582440e-04 0.0007338177018431625 3.743865400085843336e-04 0.0005739656376861859 2.506901966657434509e-04 0.00037550439543261463 1.749991992264989145e-04 0.0002521443237629474 1.308541788026545852e-04 0.00017684294734265143 1.097115653341001649e-04 0.00013330094534015117 1.117862964715498958e-04 0.00011335582519792064 1.610733229285059244e-04 0.00011855974750452474 0.00018013280630154984
47 1.000000000000000021e-03 0.001 5.724581527307928295e-04 0.0007330312083387708 3.734873153380866809e-04 0.0005731465277735759 2.498542195054800734e-04 0.000374584210907019 1.742275621656188764e-04 0.00025128692777751636 1.300856406740597557e-04 0.0001760484420635206 1.088263113284397853e-04 0.00013250403238709868 1.104977038827086933e-04 0.00011242580398299235 1.583110954216201049e-04 0.00011717140625198769 0.000176995286763841
48 1.000000000000000021e-03 0.001 5.716575664778975139e-04 0.0007322450716827681 3.725901351223118402e-04 0.0005723280950701311 2.490209518882956956e-04 0.00037366577307640326 1.734592774731394025e-04 0.00025043200586833656 1.293215843757922266e-04 0.00017525712146802507 1.079481792373105579e-04 0.00013171151729665014 1.092239503861538297e-04 0.00011150300328069361 1.555962288273640454e-04 0.00011579873047427355 0.00017391111613739919
49 1.000000000000000021e-03 0.001 5.708579584178212615e-04 0.0007314592892342591 3.716949912014026899e-04 0.0005715103366354928 2.481903820156593069e-04 0.0003727490765712826 1.726943281050015661e-04 0.00024957954955556494 1.285619816677677630e-04 0.0001744689721973381 1.070771097820554131e-04 0.00013092337604814113 1.079648627815312081e-04 0.00011058736861417956 1.529279069228532445e-04 0.00011444154833756723 0.0001708794064250159
50 1.000000000000000021e-03 0.001 5.700593240595020362e-04 0.0007306738583803173 3.708018755033176054e-04 0.0005706932495677312 2.473624982033243466e-04 0.00037183411609277345 1.719326971657234189e-04 0.00024872955044744495 1.278068045492097274e-04 0.00017368398100343736 1.062130442456755448e-04 0.0001301395848004509 1.067202699871894330e-04 0.00010967884595770732 1.503053277730467872e-04 0.00011309968990727626 0.00016789928423747183
51 1.000000000000000021e-03 0.001 5.692616589508734098e-04 0.0007298887765314699 3.699107800243283187e-04 0.0005698768309963597 2.465372888514933574e-04 0.00037092088639398746 1.711743678703278799e-04 0.0002478820002115871 1.270560252111956913e-04 0.00017290213471209804 1.053559244063845252e-04 0.00012936011984533696 1.054900029091859618e-04 0.0001087773816703527 1.477277031714797602e-04 0.00011177298701463364 0.00016496989019036454
52 1.000000000000000021e-03 0.001 5.684668249800580104e-04 0.0007291058850619836 3.690236622787805977e-04 0.0005690629705872476 2.457163959794073484e-04 0.0003700113801847071 1.704206404911772779e-04 0.0002470385774678141 1.263106878677109810e-04 0.00017212477134492983 1.045066466916437628e-04 0.0001285860674779147 1.042749156168111009e-04 0.00010788392632853856 1.451958181660296986e-04 0.00011046237940908493 0.00016209217355659912
53 1.000000000000000021e-03 0.001 5.676748100054150635e-04 0.0007283251776795193 3.681404996529084395e-04 0.0005682516594285885 2.448997907163580324e-04 0.0003691055790623401 1.696714800685054925e-04 0.0002461992575642169 1.255707452244580493e-04 0.00017135185999287266 1.036651297187654374e-04 0.00012781738439880834 1.030748062779383314e-04 0.00010699840217906239 1.427088285865420875e-04 0.00010916766306641233 0.00015926520709064215
54 1.000000000000000021e-03 0.001 5.668856019606317766e-04 0.000727546648123048 3.672612697075048303e-04 0.000567442888658507 2.440874444423345342e-04 0.0003682034647519281 1.689268519744038289e-04 0.00024536401604150686 1.248361504800705925e-04 0.00017058337001160307 1.028312930702206035e-04 0.00012705402771768452 1.018894759794533339e-04 0.00010612073231230378 1.402659065748177792e-04 0.0001078886367084761 0.00015648808062028533
55 1.000000000000000021e-03 0.001 5.660978860040193896e-04 0.0007267691175258129 3.663833351346186431e-04 0.0005666351120658079 2.432754355983019401e-04 0.00036730194585451363 1.681813812071888568e-04 0.00024452825978826814 1.240994738987429935e-04 0.00016981299319253088 1.019939514788640786e-04 0.00012628722374912656 1.006986246362622330e-04 0.00010523753204397677 1.378144424939918523e-04 0.00010660034638564814 0.00015369233245141463
56 1.000000000000000021e-03 0.001 5.653129566917403656e-04 0.0007259937543683618 3.655093013788168949e-04 0.0005658298620581495 2.424676550876819162e-04 0.00036640409142867466 1.674404214250226010e-04 0.00024369656281803695 1.233681396595080271e-04 0.0001690470312136919 1.011643116013039457e-04 0.00012552576286196436 9.952262825359122704e-05 0.00010436224908854787 1.354072260989254840e-04 0.00010532792661952348 0.00015094700928094292
57 1.000000000000000021e-03 0.001 5.645308021917731225e-04 0.0007252205525006216 3.646391464999218838e-04 0.0005650271299429238 2.416640749146854532e-04 0.0003655098835814395 1.667039386446287719e-04 0.0002428689011484816 1.226421015627000995e-04 0.0001682854538881413 1.003422934745905857e-04 0.00012476960247399048 9.836128786277046102e-05 0.00010349480634605481 1.330434286087782230e-04 0.00010407117393308648 0.00014825118806841486
58 1.000000000000000021e-03 0.001 5.637533512715803535e-04 0.0007244515476870691 3.637748048842355184e-04 0.0005642289688561167 2.408662573039999728e-04 0.00036462138604045246 1.659731272165147797e-04 0.00024204694758546622 1.219222820499958832e-04 0.00016752954803985582 9.952864742131557339e-05 0.00012401974721449815 9.721524794079934454e-05 0.00010263603739686231 1.307234068834026641e-04 0.00010283083470852359 0.0001456053538142381
59 1.000000000000000021e-03 0.001 5.629805832911210584e-04 0.0007236867286572494 3.629162394326295588e-04 0.0005634353625294562 2.400741573155354143e-04 0.0003637385663464586 1.652479360999081315e-04 0.00024123066115747858 1.212086174287677493e-04 0.00016677926586679636 9.872327382660381703e-05 0.00012327613591461942 9.608428430098295324e-05 0.00010178584352378332 1.284463004684426848e-04 0.00010160667618634935 0.0001430085413998934
60 1.000000000000000021e-03 0.001 5.622124777547171659e-04 0.0007229260842094953 3.620634133660168507e-04 0.0005626462948017631 2.392877304473862261e-04 0.0003628613922977866 1.645283148026117340e-04 0.00024042000126051454 1.205010447638324016e-04 0.00016603456004153966 9.792607442008048754e-05 0.00012253870808207087 9.496817636981473815e-05 0.0001009441272602465 1.262112668660531425e-04 0.00010039846917127745 0.000140459805170444
61 1.000000000000000021e-03 0.001 5.614490142952067260e-04 0.0007221696032014468 3.612162901840461500e-04 0.000561861749604344 2.385069325732311319e-04 0.00036198983191176377 1.638142133018547766e-04 0.0002396149275989645 1.197995017798251111e-04 0.00016529538363567852 9.713695214164584071e-05 0.00012180740380654271 9.386670693673759554e-05 0.00010011079225737115 1.240174806289624668e-04 9.920598777483068e-05 0.00013795821792425024
62 1.000000000000000021e-03 0.001 5.606917876274927293e-04 0.0007214188723728384 3.603765175920537237e-04 0.00056108334509554 2.377331235014221514e-04 0.0003611255610840681 1.631066878653574946e-04 0.0002388168283348348 1.191048135885559178e-04 0.00016456282140960994 9.635658300529022745e-05 0.00012108307905286178 9.278045936752733660e-05 9.928655238677393e-05 1.218652818497198865e-04 9.802986918413655e-05 0.0001355041849544529
63 1.000000000000000021e-03 0.001 5.599407711882442139e-04 0.0007206738776295639 3.595440474626148916e-04 0.0005603110603628828 2.369662455139816704e-04 0.0003602685373417506 1.624056743525901679e-04 0.00023802565027806571 1.184169030927857740e-04 0.00016383681258690845 9.558485302446070387e-05 0.00012036565891864721 9.170919453133945438e-05 9.847129356381268e-05 1.197538170918552259e-04 9.686986333449523e-05 0.0001330967445342526
64 1.000000000000000021e-03 0.001 5.591959386362445371e-04 0.0007199346049934109 3.587188321446053963e-04 0.0005595448746691314 2.362062415256148103e-04 0.00035941871861020354 1.617111093879153761e-04 0.00023724134078502595 1.177356942042864595e-04 0.00016311729706930416 9.482164989506947420e-05 0.00011965506942237431 9.065267746151001182e-05 9.7664903298557e-05 1.176822517560764241e-04 9.57257243308077e-05 0.00013073495556510661
65 1.000000000000000021e-03 0.001 5.584679347085343051e-04 0.0007192103057281418 3.579204847030152616e-04 0.0005587965882928195 2.354801209260217886e-04 0.000358597914203722 1.610571916563278928e-04 0.00023649404923234267 1.171042314833950021e-04 0.0001624426539507404 9.412413419793498636e-05 0.00011900000933912548 8.969710985766721223e-05 9.693290327537121e-05 1.158171674873524301e-04 9.469853254875163e-05 0.0001286228242214262
66 1.000000000000000021e-03 0.001 5.577460350040716044e-04 0.0007184916860834766 3.571292104088583889e-04 0.000558054333130965 2.347605938090600918e-04 0.0003577841401235257 1.604093154405005178e-04 0.0002357533416394368 1.164788453357124725e-04 0.00016177407584741055 9.343405219685640224e-05 0.00011835110239617177 8.875393403591714169e-05 9.620855295571759e-05 1.139848385910069905e-04 9.368449216343134e-05 0.0001265476735456528
67 1.000000000000000021e-03 0.001 5.570302142000897652e-04 0.000717778732645577 3.563449642017089015e-04 0.0005573180893469085 2.340476072540025119e-04 0.0003569773567342285 1.597674235279283352e-04 0.0002350191694371068 1.158594695166401697e-04 0.0001611115088719043 9.275131062844492946e-05 0.00011770828481211398 8.782296490203555085e-05 9.549176022876216e-05 1.121846347113116888e-04 9.268341301362701e-05 0.00012450880618841231
68 1.000000000000000021e-03 0.001 5.563205323021954991e-04 0.0007170715507844816 3.555677864531773679e-04 0.0005565879566941514 2.333411773810724506e-04 0.0003561776441627035 1.591315117132938270e-04 0.00023429158098135867 1.152460793074575203e-04 0.00016045497378223205 9.207585166649024939e-05 0.00011707155159443024 8.690405384945894284e-05 9.47824835635146e-05 1.104159825692847303e-04 9.169515755193108e-05 0.00012250560759307665
69 1.000000000000000021e-03 0.001 5.556169640414684949e-04 0.0007163701270344053 3.547976323593042547e-04 0.0005558639152622166 2.326412517183593022e-04 0.0003553849627325309 1.585015234268918286e-04 0.00023357052778616886 1.146386094395640093e-04 0.00015980441694230793 9.140758389001004606e-05 0.00011644083951173604 8.599702078916069998e-05 9.408063218207804e-05 1.086782756746748250e-04 9.071953997714039e-05 0.00012053740486430812
70 1.000000000000000021e-03 0.001 5.549194843577821444e-04 0.0007156744480415676 3.540344575531629255e-04 0.0005551459453084167 2.319477783590319386e-04 0.00035459927313802623 1.578774027587701891e-04 0.00023285596185845654 1.140369954748351631e-04 0.00015915978530381373 9.074641718074756330e-05 0.00011581608608941654 8.510168863112195785e-05 9.338611653058621e-05 1.069709201912467553e-04 8.975637744384618e-05 0.00011860353870291344
71 1.000000000000000021e-03 0.001 5.542280683854123842e-04 0.0007149845005557793 3.532782180675540329e-04 0.0005544340272448129 2.312607059053527040e-04 0.0003538205364097734 1.572590943887706505e-04 0.0002321478356456351 1.134411737206307899e-04 0.0001585210263398076 9.009226260907148270e-05 0.00011519722952770958 8.421788308143062266e-05 9.269884816673769e-05 1.052933342707317640e-04 8.880548985453175e-05 0.00011670336266552508
72 1.000000000000000021e-03 0.001 5.535435592528614506e-04 0.0007143011352806332 3.525297669260542646e-04 0.0005537290222260827 2.305807244353639423e-04 0.0003530496254918224 1.566471216497641210e-04 0.00023144685778402562 1.128515385449576329e-04 0.00015788868071804074 8.944542244330133641e-05 0.00011458468167101622 8.334582247054855841e-05 9.20191492389152e-05 1.036454797753234207e-04 8.786712068874325e-05 0.00011483685132763588
73 1.000000000000000021e-03 0.001 5.528659293179593237e-04 0.0007136243377311475 3.517890550472092793e-04 0.0005530309085687206 2.299077767025847687e-04 0.00035228649684153725 1.560414233076215052e-04 0.0002307529751854999 1.122680202866636689e-04 0.00015726269010384348 8.880580140054516926e-05 0.00011397837465469773 8.248532556564376009e-05 9.134692457668887e-05 1.020267728319692934e-04 8.694108196461404e-05 0.00011300335424584403
74 1.000000000000000021e-03 0.001 5.521951511907441769e-04 0.0007129540935643617 3.510560338657343622e-04 0.0005523396647985742 2.292418061160320900e-04 0.000351531107363628 1.554419388795865483e-04 0.0002300661353432777 1.116905502099227850e-04 0.0001566429968410848 8.817330560855271690e-05 0.00011337824146720777 8.163621425685595255e-05 9.06820803490277e-05 1.004366420798761639e-04 8.602718880727694e-05 0.00011120223452206596
75 1.000000000000000021e-03 0.001 5.515357570680511773e-04 0.0007122949300063586 3.503384240935171457e-04 0.0005516609446370161 2.285926195257032088e-04 0.0003507932546232374 1.548599664871607589e-04 0.0002293990178082647 1.111316359132737570e-04 0.00015604454205901748 8.756139732097920178e-05 0.00011280134646728481 8.081143045355856274e-05 9.004396195380538e-05 9.887558842870256459e-05 8.514641523915274e-05 0.00010944396621311202
76 1.000000000000000021e-03 0.001 5.508831499695134287e-04 0.0007116422850379047 3.496283778737561509e-04 0.0005509890404263221 2.279502431225978031e-04 0.00035006301886912226 1.542840041018178729e-04 0.00022873877079420107 1.105785086338880569e-04 0.00015545216193435095 8.695624145470242240e-05 0.00011223032450910806 7.999741899881025698e-05 8.941277122627028e-05 9.734197099681332458e-05 8.427699754143763e-05 0.00010771649233683978
77 1.000000000000000021e-03 0.001 5.502373034395177318e-04 0.0007109961448775265 3.489258487042028742e-04 0.0005503239315436604 2.273146231686837553e-04 0.00034934035900275196 1.537139948092133693e-04 0.00022808534468017605 1.100311043442569531e-04 0.00015486580256638324 8.635775141128424154e-05 0.00011166511373672321 7.919401605398894981e-05 8.878842266662507e-05 9.583525507692383649e-05 8.341876815036907e-05 0.00010601922394974779
78 1.000000000000000021e-03 0.001 5.495982753581815606e-04 0.0007103566138672342 3.482308738101717264e-04 0.0005496657159311855 2.266857730549029851e-04 0.0003486253516297722 1.531499327576744506e-04 0.00022743878433373037 1.094893985055618503e-04 0.00015428548213839886 8.576587362490598130e-05 0.00011110570832676001 7.840109070036870779e-05 8.81708780194749e-05 9.435495486246966317e-05 8.25716070442755e-05 0.00010435164299643007
79 1.000000000000000021e-03 0.001 5.489660394111083985e-04 0.0007097236782517396 3.475434070850742167e-04 0.0005490143729973408 2.260636396270461598e-04 0.0003479179557857281 1.525917617808240120e-04 0.0002267990403962617 1.089533281238570496e-04 0.0001537111471536449 8.518052329278025009e-05 0.00011055204708289399 7.761848365092111231e-05 8.756005313455197e-05 9.290055631012179708e-05 8.173535064610718e-05 0.0001027131817052566
80 1.000000000000000021e-03 0.001 5.483405695169031721e-04 0.0007090973244087274 3.468634028939242666e-04 0.0005483698823458906 2.254481703234268038e-04 0.00034721813091834777 1.520394263837190755e-04 0.000226166064037726 1.084228310216190315e-04 0.00015314274472297157 8.460161684084565312e-05 0.00011000406955950422 7.684603831721497692e-05 8.695586501935841e-05 9.147155629123523643e-05 8.090983803329783e-05 0.00010110328401062253
81 1.000000000000000021e-03 0.001 5.477218398160970184e-04 0.0007084775388425413 3.461908160447295835e-04 0.0005477322237660661 2.248393131323322177e-04 0.0003465258368613831 1.514928716901747189e-04 0.00022553980691704316 1.078978457743454979e-04 0.00015258022251510344 8.402907183940372035e-05 0.00010946171600087524 7.608360066029366266e-05 8.635823175652435e-05 9.006746210081428210e-05 8.00949107862898e-05 9.952140501322636e-05
82 1.000000000000000021e-03 0.001 5.471100509830739483e-04 0.0007078645400735427 3.455258336641454844e-04 0.0005471016129101978 2.242372067336963117e-04 0.0003458412757255009 1.509521904405796073e-04 0.00022492042013778988 1.073784265457052923e-04 0.00015202368335334558 8.346290305268591516e-05 0.00010892504915290583 7.533111218717854750e-05 8.57671759148139e-05 8.868791149478115541e-05 7.929051589048381e-05 9.796715152670613e-05
83 1.000000000000000021e-03 0.001 5.465051768578450733e-04 0.0007072583145347741 3.448684100639811626e-04 0.0005464780293804963 2.236417986238402995e-04 0.00034516440688163317 1.504173273640432558e-04 0.00022430785483116316 1.068645117117092864e-04 0.0001514730744232032 8.290302835464549746e-05 0.00010839400891826328 7.458842111919879593e-05 8.518261565996433e-05 8.733242665255502488e-05 7.84964968569563e-05 9.643999410136803e-05
84 1.000000000000000021e-03 0.001 5.459071915129861232e-04 0.0007066588487940405 3.442185000233075119e-04 0.000545861452976259 2.230530368831633737e-04 0.0003444951901125997 1.498882278486614187e-04 0.00022370206265319418 1.063560404456327061e-04 0.00015092834351042303 8.234936680962616474e-05 0.00010786853593723236 7.385537825478157199e-05 8.460447028623623e-05 8.600053991717240256e-05 7.771269974698105e-05 9.493941424410264e-05
85 1.000000000000000021e-03 0.001 5.453277270883248422e-04 0.0007060768113835355 3.435968835063559607e-04 0.0005452653567881146 2.224987019123045480e-04 0.00034385780916102886 1.493989071766017103e-04 0.0002231355522451839 1.058939742146122178e-04 0.0001504295746545273 8.185283432112488435e-05 0.00010739737531972382 7.320083692872619591e-05 8.409424224945842e-05 8.480120525436834187e-05 7.702434963545377e-05 9.360618912201228e-05
86 1.000000000000000021e-03 0.001 5.447550756300442850e-04 0.0007055014939207988 3.429826158632724655e-04 0.0005446762036784223 2.219507707465509202e-04 0.00034322791998477503 1.489150144895505707e-04 0.0002225755642266546 1.054368625228528346e-04 0.00014993632274793293 8.136171358212484941e-05 0.00010693123855410087 7.255437084770181432e-05 8.358951092264173e-05 8.362138199130290570e-05 7.634435339541097e-05 9.22944227993744e-05
87 1.000000000000000021e-03 0.001 5.441892122953419404e-04 0.0007049328836329239 3.423756544954533452e-04 0.0005440939744776738 2.214091954721005766e-04 0.0003426054850001757 1.484365007267826825e-04 0.00022202205441602206 1.049846526338566485e-04 0.000149448541485554 8.087593753205775274e-05 0.00010647007505716636 7.191586230794716592e-05 8.309021096715739e-05 8.246071125248328093e-05 7.567259318109089e-05 9.100372969350909e-05
88 1.000000000000000021e-03 0.001 5.436257869834306257e-04 0.0007043664108869901 3.417717090501741430e-04 0.0005435140913972429 2.208705585733095858e-04 0.00034198598587466614 1.479607869104501987e-04 0.00022147141590047654 1.045353737048878776e-04 0.00014896349766232102 8.039389156994272538e-05 0.00010601178096740148 7.128377081045688692e-05 8.259459730216135e-05 8.131715986317171246e-05 7.500736724232048e-05 8.973176442333615e-05
89 1.000000000000000021e-03 0.001 5.430647907230928004e-04 0.0007038020712072354 3.411707635569704330e-04 0.0005429365478183962 2.203348411819341208e-04 0.00034136940918446675 1.474878525008424264e-04 0.0002209236320980648 1.040890016129762040e-04 0.00014848117283038098 7.991554062444546221e-05 0.00010555633431743894 7.065802258502740848e-05 8.210263744821714e-05 8.019045690600123673e-05 7.434860458126827e-05 8.847824135377829e-05
90 1.000000000000000021e-03 0.001 5.425062145452035425e-04 0.0007032398600991381 3.405728020832017003e-04 0.0005423613371043419 2.198020245085192449e-04 0.00034075574151016483 1.470176770797095381e-04 0.0002203786864681782 1.036455124224165388e-04 0.00014800154862415601 7.944084996986793814e-05 0.00010510371328265478 7.003854478529189314e-05 8.161429921011451e-05 7.908033605497744685e-05 7.369623501807121e-05 8.724287943554497e-05
91 1.000000000000000021e-03 0.001 5.419500494783734655e-04 0.0007026797730466592 3.399778087230425684e-04 0.0005417884525961108 2.192720898259863408e-04 0.00034014496942632764 1.465502403299397984e-04 0.0002198365624959981 1.032048823605461293e-04 0.00014752460674093983 7.896978519468913008e-05 0.00010465389615779026 6.942526543493823701e-05 8.112955064604149e-05 7.798653539704048551e-05 7.305018913687007e-05 8.602540201539488e-05
92 1.000000000000000021e-03 0.001 5.413941311127808435e-04 0.0007021196874055633 3.393835756573481376e-04 0.0005412157406692665 2.187432334857416756e-04 0.0003395348927353949 1.460841531649274296e-04 0.00021929545761274023 1.027660304092932323e-04 0.00014704895219343257 7.850144313387483587e-05 0.00010420578859113516 6.881729624423716459e-05 8.064746506639534e-05 7.690779566810491681e-05 7.240953347459202e-05 8.482441661675139e-05
93 1.000000000000000021e-03 0.001 5.408384570747234218e-04 0.0007015596012323657 3.387900992487282684e-04 0.0005406431992153213 2.182154508640741402e-04 0.0003389255082691921 1.456194096560940569e-04 0.00021875536780717296 1.023289477092565169e-04 0.00014657457987728414 7.803580657419308998e-05 0.00010375938295149973 6.821458972979072498e-05 8.016802726693694e-05 7.584390730667668775e-05 7.17742234562459e-05 8.363970356449741e-05
94 1.000000000000000021e-03 0.001 5.402830249660243826e-04 0.0007009995125587165 3.381973758275843189e-04 0.0005400708260946051 2.176887373150658610e-04 0.0003383168128172846 1.451560038709627043e-04 0.00021821628903476192 1.018936254270842219e-04 0.00014610148467187763 7.757285840469518032e-05 0.0001033146716169485 6.761709884283491779e-05 7.969122211456026e-05 7.479466373034050742e-05 7.114421486558773e-05 8.247104609297546e-05
95 1.000000000000000021e-03 0.001 5.397131798668998448e-04 0.000700426120570031 3.375789411508863902e-04 0.0005394817717340144 2.171273238640323091e-04 0.00033767827777106695 1.446496280566233409e-04 0.00021763678242090514 1.014059885387841374e-04 0.00014557802543177205 7.704415358894297196e-05 0.00010280805245363877 6.692941074150365747e-05 7.913535785684264e-05 7.359880640935691578e-05 7.040274681183516e-05 8.111172191387726e-05
96 1.000000000000000021e-03 0.001 5.391436022217508317e-04 0.0006998527383823768 3.369613465901344558e-04 0.0005388929110101418 2.165671485747253328e-04 0.0003370405259007354 1.441448734692186333e-04 0.00021705847496470142 1.009205829600201576e-04 0.00014505616500334602 7.651897498112265308e-05 0.00010230367256069614 6.624864922679121694e-05 7.858312049704058e-05 7.242198835523922060e-05 6.966868896041247e-05 7.977423771714316e-05
97 1.223599761281599736e-03 0.0010496228983614124 2.870574988594920204e-03 0.002020602352332682 5.410558860144323162e-03 0.0024834354692445607 9.740321680379944794e-03 0.004712247621156641 1.718226620812626088e-02 0.00854174709233096 3.032327552654904765e-02 0.015197203876184536 5.460894525232919822e-02 0.027142477151470907 1.025522470341594938e-01 0.049749449744480465 2.059999999999999887e-01 0.09589624880110185 0.2
98 4.083745694274921144e-03 0.004235602571438949 8.369042825128880300e-03 0.007336805952289255 1.439530071705045523e-02 0.008714058005603317 2.397223043565064812e-02 0.015024716476258112 3.897486419880552555e-02 0.025061770718850837 6.202545653148217042e-02 0.04079161627542227 9.626510461383173956e-02 0.0649508755581543 1.437785279168776742e-01 0.10074574737193842 2.000000000000000111e-01 0.14993445055894863 0.206

View File

@@ -0,0 +1,224 @@
{
"uid": "Span1",
"params": {
"length": 80,
"loss_coef": 0.2,
"length_units": "km",
"att_in": 0,
"con_in": 0.5,
"con_out": 0.5,
"type_variety": "SSMF",
"dispersion": 0.0000167,
"effective_area": 83e-12,
"pmd_coef": 1.265e-15,
"raman_efficiency": {
"cr": [
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
],
"frequency_offset": [
0.0e12,
0.5e12,
1.0e12,
1.5e12,
2.0e12,
2.5e12,
3.0e12,
3.5e12,
4.0e12,
4.5e12,
5.0e12,
5.5e12,
6.0e12,
6.5e12,
7.0e12,
7.5e12,
8.0e12,
8.5e12,
9.0e12,
9.5e12,
10.0e12,
10.5e12,
11.0e12,
11.5e12,
12.0e12,
12.5e12,
12.75e12,
13.0e12,
13.25e12,
13.5e12,
14.0e12,
14.5e12,
14.75e12,
15.0e12,
15.5e12,
16.0e12,
16.5e12,
17.0e12,
17.5e12,
18.0e12,
18.25e12,
18.5e12,
18.75e12,
19.0e12,
19.5e12,
20.0e12,
20.5e12,
21.0e12,
21.5e12,
22.0e12,
22.5e12,
23.0e12,
23.5e12,
24.0e12,
24.5e12,
25.0e12,
25.5e12,
26.0e12,
26.5e12,
27.0e12,
27.5e12,
28.0e12,
28.5e12,
29.0e12,
29.5e12,
30.0e12,
30.5e12,
31.0e12,
31.5e12,
32.0e12,
32.5e12,
33.0e12,
33.5e12,
34.0e12,
34.5e12,
35.0e12,
35.5e12,
36.0e12,
36.5e12,
37.0e12,
37.5e12,
38.0e12,
38.5e12,
39.0e12,
39.5e12,
40.0e12,
40.5e12,
41.0e12,
41.5e12,
42.0e12
]
}
},
"operational": {
"temperature": 283,
"raman_pumps": [
{
"power": 224.403e-3,
"frequency": 205e12,
"propagation_direction": "counterprop"
},
{
"power": 231.135e-3,
"frequency": 201e12,
"propagation_direction": "counterprop"
}
]
},
"metadata": {
"location": {
"latitude": 1,
"longitude": 0,
"city": null,
"region": ""
}
}
}

View File

@@ -0,0 +1,225 @@
{
"uid": "Span1",
"params": {
"length": 80,
"loss_coef": 0.2,
"length_units": "km",
"att_in": 0,
"con_in": 0.5,
"con_out": 0.5,
"type_variety": "SSMF",
"dispersion": 0.0000167,
"effective_area": 83e-12,
"pmd_coef": 1.265e-15,
"raman_coefficient": {
"g0": [
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
],
"frequency_offset": [
0.0e12,
0.5e12,
1.0e12,
1.5e12,
2.0e12,
2.5e12,
3.0e12,
3.5e12,
4.0e12,
4.5e12,
5.0e12,
5.5e12,
6.0e12,
6.5e12,
7.0e12,
7.5e12,
8.0e12,
8.5e12,
9.0e12,
9.5e12,
10.0e12,
10.5e12,
11.0e12,
11.5e12,
12.0e12,
12.5e12,
12.75e12,
13.0e12,
13.25e12,
13.5e12,
14.0e12,
14.5e12,
14.75e12,
15.0e12,
15.5e12,
16.0e12,
16.5e12,
17.0e12,
17.5e12,
18.0e12,
18.25e12,
18.5e12,
18.75e12,
19.0e12,
19.5e12,
20.0e12,
20.5e12,
21.0e12,
21.5e12,
22.0e12,
22.5e12,
23.0e12,
23.5e12,
24.0e12,
24.5e12,
25.0e12,
25.5e12,
26.0e12,
26.5e12,
27.0e12,
27.5e12,
28.0e12,
28.5e12,
29.0e12,
29.5e12,
30.0e12,
30.5e12,
31.0e12,
31.5e12,
32.0e12,
32.5e12,
33.0e12,
33.5e12,
34.0e12,
34.5e12,
35.0e12,
35.5e12,
36.0e12,
36.5e12,
37.0e12,
37.5e12,
38.0e12,
38.5e12,
39.0e12,
39.5e12,
40.0e12,
40.5e12,
41.0e12,
41.5e12,
42.0e12
],
"reference_frequency": 206184634112792
}
},
"operational": {
"temperature": 283,
"raman_pumps": [
{
"power": 224.403e-3,
"frequency": 205e12,
"propagation_direction": "counterprop"
},
{
"power": 231.135e-3,
"frequency": 201e12,
"propagation_direction": "counterprop"
}
]
},
"metadata": {
"location": {
"latitude": 1,
"longitude": 0,
"city": null,
"region": ""
}
}
}

View File

@@ -1,97 +1,97 @@
,signal,ase,nli signal,ase,nli
0,0.0002866683470642085,3.455694800734997e-08,2.1767706055953313e-07 0.000325019416624,3.8827360617812335e-08,2.397604591245591e-07
1,0.0002842930902246378,3.4445260342151434e-08,2.20064716108892e-07 0.0003222815415358,3.8702821151814216e-08,2.4267833614138976e-07
2,0.00028193841273409963,3.4334217950641774e-08,2.2239856929822977e-07 0.0003195661748689,3.8578942925493807e-08,2.455296149641726e-07
3,0.0002796041237984927,3.422381587730477e-08,2.2467937700272344e-07 0.000316873132879,3.8455721305309324e-08,2.483151861322029e-07
4,0.00027589218358262,3.3956266402003705e-08,2.2576401766047814e-07 0.0003125687708988,3.815158818797417e-08,2.497308542349044e-07
5,0.0002722303444814487,3.3690926476196685e-08,2.2678094635121413e-07 0.0003083216327341,3.784989647314237e-08,2.5106122773764815e-07
6,0.00026861791294303266,3.342777134334201e-08,2.2773179097640802e-07 0.0003041309702107,3.755062053762566e-08,2.523083160653813e-07
7,0.00026505174756069215,3.316675429137828e-08,2.2861602718115889e-07 0.0002999931829076,3.725370771318225e-08,2.534716728592015e-07
8,0.0002615312775878486,3.290785186664305e-08,2.294352005376256e-07 0.0002959076621852,3.695913382975532e-08,2.545532047834699e-07
9,0.0002577007690018081,3.26092154155734e-08,2.2987401053105823e-07 0.0002914749637887,3.6620413511505286e-08,2.5520557429118934e-07
10,0.00025392474812815994,3.231329178154223e-08,2.3024928325076607e-07 0.0002871045786391,3.62847038107824e-08,2.557776344401253e-07
11,0.0002501957390130402,3.201993265117851e-08,2.3055653947072044e-07 0.0002827879891071,3.5951828869209396e-08,2.5626453052593257e-07
12,0.0002465133077961936,3.172911082648897e-08,2.3079745224174315e-07 0.0002785247470154,3.562176113110911e-08,2.5666832208790035e-07
13,0.00024287702172285261,3.144079924487205e-08,2.309736700807475e-07 0.0002743144039041,3.5294473123494e-08,2.569910409348857e-07
14,0.00023918644496802598,3.1142660565561954e-08,2.3099023972100006e-07 0.000270032675166,3.4954880805048256e-08,2.571167784361306e-07
15,0.00023554415781363666,3.084719002003063e-08,2.3094533745656626e-07 0.0002658067200554,3.4618272391047544e-08,2.571652788509227e-07
16,0.0002319496781605366,3.0554358283826426e-08,2.3084061926161906e-07 0.000261636025157,3.428461757057609e-08,2.5713860104931033e-07
17,0.000228402746264896,3.026413819712743e-08,2.306779372506828e-07 0.00025752034599,3.395388872366444e-08,2.570390408700655e-07
18,0.00022490287297566154,2.997650061885732e-08,2.2679314039447925e-07 0.000253459157096,3.362605558722993e-08,2.5284986247287787e-07
19,0.0002210339853226993,2.9639081336421986e-08,2.225476971173533e-07 0.000248983782073,3.3242702224575744e-08,2.48252059976888e-07
20,0.00021722472675673681,2.9305156366940595e-08,2.1837424228396343e-07 0.0002445773493265,3.286328176612301e-08,2.437277481862015e-07
21,0.00021347443350916938,2.8974683300060073e-08,2.1427183120915025e-07 0.0002402391773459,3.2487750441670215e-08,2.392761376865807e-07
22,0.00020978233224910872,2.864761802749998e-08,2.1023941353936252e-07 0.0002359684123723,3.2116061418127753e-08,2.3489626905665574e-07
23,0.0002061476568412488,2.832391679540816e-08,2.0627595093585302e-07 0.0002317642070805,3.174816817069829e-08,2.3058719110264335e-07
24,0.0002028237056285935,2.8034565895618217e-08,2.0263423697267893e-07 0.0002279695550926,3.1424928539548144e-08,2.2668986526609113e-07
25,0.00019954715529254185,2.7748013284124615e-08,1.9905015325521452e-07 0.0002242281358436,3.1104729317697146e-08,2.228495045304229e-07
26,0.0001963174528000437,2.7464226779716075e-08,1.9552292765090665e-07 0.0002205393783222,3.078753835343166e-08,2.190654562751529e-07
27,0.00019313475803109547,2.718318103861899e-08,1.920525003885138e-07 0.0002169035545525,3.047333197100547e-08,2.1533790605165431e-07
28,0.00018999848980183525,2.6904843987797665e-08,1.8863807494364378e-07 0.0002133200561122,3.01620779209974e-08,2.1166616520930645e-07
29,0.00018690807208013476,2.6629183784477213e-08,1.852788635171717e-07 0.0002097882786443,2.9853744125792176e-08,2.080495504306458e-07
30,0.00018386293497138034,2.635616888672288e-08,1.8197408797080072e-07 0.0002063076230434,2.9548298767727423e-08,2.0448738489666716e-07
31,0.0001808626075954048,2.608576967648626e-08,1.7872307155753016e-07 0.0002028776374913,2.9245712991289203e-08,2.009791389793126e-07
32,0.00017790652540681915,2.5817954962418864e-08,1.7552504805064169e-07 0.0001994977236946,2.8945955168147914e-08,1.975241389908885e-07
33,0.00017499412908771533,2.5552693765056307e-08,1.723792598876346e-07 0.0001961672877059,2.8648993828553545e-08,1.9412171682473827e-07
34,0.0001721914205512116,2.529821177538242e-08,1.69350416018518e-07 0.0001929967738963,2.8368195292008612e-08,1.9088102669437356e-07
35,0.00016942913344260413,2.5046172734840803e-08,1.663699885487624e-07 0.0001898709450753,2.8090002575266257e-08,1.8768789971552863e-07
36,0.0001667067703020692,2.4796549229968703e-08,1.6343730102750106e-07 0.0001867892958482,2.7814389032455363e-08,1.8454176486632323e-07
37,0.00016402494737034808,2.4549324625938814e-08,1.602954566731582e-07 0.000183752636707,2.754134148447891e-08,1.8115002092564538e-07
38,0.0001613831201060569,2.430447139995257e-08,1.5720933628441338e-07 0.0001807604032471,2.7270832946920812e-08,1.7781492252546064e-07
39,0.00015878075021906192,2.406196225171638e-08,1.541780421866172e-07 0.0001778120365192,2.7002836607760232e-08,1.745356369687972e-07
40,0.00015621730558753943,2.3821770097360405e-08,1.5120068940449393e-07 0.0001749069829579,2.673732582084065e-08,1.7131134159682263e-07
41,0.000153694061439545,2.3583901792213434e-08,1.4827814327673852e-07 0.0001720467771106,2.6474316260529432e-08,1.6814325920632144e-07
42,0.00015121040694331307,2.3348329147104765e-08,1.4540943949658482e-07 0.0001692307716138,2.6213779758633963e-08,1.6503047175593728e-07
43,0.00014876574026315321,2.3115024224465226e-08,1.425936300160931e-07 0.0001664583277393,2.5955688359138642e-08,1.619720751255672e-07
44,0.00014623043935025647,2.2864250993313975e-08,1.397065102093322e-07 0.0001635796256227,2.5677295228672648e-08,1.588223280583729e-07
45,0.00014373723010448477,2.2616046400344574e-08,1.3687531950007013e-07 0.0001607481963598,2.540169810843596e-08,1.557306487644946e-07
46,0.0001412854316913198,2.2370377299191064e-08,1.3409901704421416e-07 0.0001579633073114,2.512886316325068e-08,1.526960267832303e-07
47,0.00013887544742801196,2.2127221340618422e-08,1.313775961274423e-07 0.0001552255108883,2.4858770138402143e-08,1.4971869736122287e-07
48,0.0001365065605420479,2.1886545482453933e-08,1.2870998887773554e-07 0.000152534027681,2.4591385101783997e-08,1.467976093017761e-07
49,0.00013417806673897108,2.164831702445933e-08,1.2609514810979993e-07 0.0001498880910245,2.432667443532368e-08,1.439317302908228e-07
50,0.00013188927370907155,2.1412503578881085e-08,1.2353204666803017e-07 0.0001472869464661,2.4064604800471338e-08,1.411200462508912e-07
51,0.00012964085531237725,2.117909919147538e-08,1.2102094138348867e-07 0.0001447314108795,2.3805175801260087e-08,1.3836305172259211e-07
52,0.00012743207116500861,2.094807084934547e-08,1.1856076487337955e-07 0.0001422206714078,2.3548353146553164e-08,1.3565967973526553e-07
53,0.0001252621950917354,2.0719385892834214e-08,1.161504721855161e-07 0.0001397539300508,2.3294102880186107e-08,1.3300888438790536e-07
54,0.00012308423338164536,2.0485363383535514e-08,1.1374627006340893e-07 0.0001372700286953,2.3032485432340423e-08,1.3035230831596558e-07
55,0.00012094535834842106,2.0253755300794944e-08,1.1139168040879032e-07 0.0001348306664569,2.2773547798807564e-08,1.277485195296911e-07
56,0.00011884484242431182,2.0024527468430072e-08,1.0897675288127846e-07 0.0001324350333325,2.2517253805739807e-08,1.2505815113074245e-07
57,0.00011678298769107047,1.9797656169961167e-08,1.0661409941810817e-07 0.0001300835425363,2.2263580536243144e-08,1.2242454150816991e-07
58,0.0001147590394591346,1.9573107382367898e-08,1.0430256532408603e-07 0.0001277753479236,2.2012491805819457e-08,1.1984647647989558e-07
59,0.00011277225867179729,1.935084744632288e-08,1.0204102225018314e-07 0.0001255096202792,2.1763951788812352e-08,1.1732276843747534e-07
60,0.00011082192110664448,1.913084301808743e-08,9.982836715827351e-08 0.0001232855464269,2.1517924960982367e-08,1.148522552473446e-07
61,0.00010890831555726861,1.8913080844667903e-08,9.76644171489201e-08 0.0001211034718808,2.1274400813402842e-08,1.1243486085670634e-07
62,0.00010703069380321927,1.8697527263494167e-08,9.554805889434612e-08 0.0001189625537742,2.1033343271785093e-08,1.100694052812587e-07
63,0.00010518832400867466,1.8484148971365717e-08,9.347820572370307e-08 0.0001168619671686,2.0794716623616593e-08,1.0775473577456182e-07
64,0.00010353027948847247,1.8300360477604286e-08,9.158630538270034e-08 0.0001149842862687,2.0591381044652174e-08,1.056582342233035e-07
65,0.00010190114820620951,1.8118339508838893e-08,8.97332684173061e-08 0.0001131392424142,2.038998454906055e-08,1.0360354473279054e-07
66,0.00010030037817345079,1.7938063167097722e-08,8.791826040657302e-08 0.0001113262252932,2.0190503422606346e-08,1.0158979943539652e-07
67,9.872746699919663e-05,1.775950920143011e-08,8.614049912759125e-08 0.0001095446965516,1.9992914861970927e-08,9.961620365200192e-08
68,9.718188342878233e-05,1.7582655209782296e-08,8.439918541238176e-08 0.0001077940670993,1.9797195630879305e-08,9.768192356581421e-08
69,9.566310719955732e-05,1.740747903977101e-08,8.269353818341506e-08 0.0001060737596438,1.9603322741072024e-08,9.578614349620901e-08
70,9.417062845393912e-05,1.7233958752991638e-08,8.102279372648069e-08 0.0001043832080373,1.9411273409584944e-08,9.392806512410292e-08
71,9.27044102709892e-05,1.7062082036004708e-08,7.938660156523957e-08 0.0001027223865858,1.922103688152168e-08,9.210738192714242e-08
72,9.12639411274833e-05,1.6891826998956218e-08,7.778420731697601e-08 0.0001010907257366,1.9032590330084783e-08,9.032330177845482e-08
73,8.984872036936478e-05,1.6723171993235663e-08,7.621487408851861e-08 9.948766769187398e-05,1.8845911172333032e-08,8.857505025129074e-08
74,8.845926525396718e-05,1.6557077218868872e-08,7.467873241780861e-08 9.792267601599324e-05,1.8663442661346744e-08,8.687075031773093e-08
75,8.709405706837696e-05,1.6392620086127443e-08,7.352620174175576e-08 9.638489299064336e-05,1.848276820506329e-08,8.550652733411691e-08
76,8.575262707251024e-05,1.6229781230847938e-08,7.239374499535451e-08 9.48738026587305e-05,1.830386814585904e-08,8.416598440502352e-08
77,8.44345490553445e-05,1.6068541919248203e-08,7.128100236441453e-08 9.338895072626004e-05,1.8126723701740663e-08,8.284871850980459e-08
78,8.313937224726923e-05,1.5908883354530017e-08,7.018759330199112e-08 9.192983962632808e-05,1.7951315790883015e-08,8.155428823884958e-08
79,8.18666553697718e-05,1.5750787028460176e-08,6.91131452736768e-08 9.049598195913348e-05,1.7777625631449783e-08,8.028226120215297e-08
80,8.061596620368467e-05,1.5594234699428168e-08,6.80572933931087e-08 8.908690001727453e-05,1.7605634715742614e-08,7.903221360818749e-08
81,7.93869860927298e-05,1.54392105845737e-08,6.701976864553917e-08 8.77022482135352e-05,1.743532764682425e-08,7.780383887402493e-08
82,7.81792957880057e-05,1.528569691328632e-08,6.600021709431229e-08 8.634156228069215e-05,1.7266686393258476e-08,7.659672513140668e-08
83,7.69924848842345e-05,1.5133676199095668e-08,6.499829226870119e-08 8.50043874741986e-05,1.7099693224424935e-08,7.541046895998541e-08
84,7.592423495462984e-05,1.5006007729453082e-08,6.40964585216171e-08 8.381694660770028e-05,1.6962933489525264e-08,7.43570471865261e-08
85,7.487323130273564e-05,1.4879695488874347e-08,6.320918435915818e-08 8.26484651987276e-05,1.682764479561346e-08,7.33204450340972e-08
86,7.383915942693816e-05,1.475473179887786e-08,6.233620427401105e-08 8.149860566615124e-05,1.6693821025332528e-08,7.230036302225977e-08
87,7.282024738915393e-05,1.4631093950979863e-08,6.147602236758762e-08 8.036532369463753e-05,1.6561436760581683e-08,7.129498756488483e-08
88,7.181625694043332e-05,1.4508775744557438e-08,6.062843750629826e-08 7.924836834130927e-05,1.6430487594212236e-08,7.030409604146297e-08
89,7.082695384072487e-05,1.4387771381868581e-08,5.979325194092954e-08 7.814749266035204e-05,1.6300969571299207e-08,6.932746937742372e-08
90,6.985210770121701e-05,1.4268075471622408e-08,5.8970271173546604e-08 7.706245353522453e-05,1.6172879193985398e-08,6.836489189528336e-08
91,6.889061932028676e-05,1.414966436041678e-08,5.8158567240485706e-08 7.599203524832233e-05,1.6046190191322708e-08,6.741528508795074e-08
92,6.79423037538828e-05,1.4032534237451406e-08,5.7357984009008465e-08 7.493604414299442e-05,1.5920900877281144e-08,6.647847715560108e-08
93,6.700697867481953e-05,1.3916681725635683e-08,5.656836755557654e-08 7.389428911314724e-05,1.57970100612018e-08,6.555429856110159e-08
94,6.594003301527265e-05,1.3765768410137306e-08,5.5667634894222326e-08 7.268136514077581e-05,1.5628904744452727e-08,6.447826980203191e-08
95,6.489000516837228e-05,1.3616343300622314e-08,5.4781184522010985e-08 7.148784598320314e-05,1.5462487634551132e-08,6.341945575654982e-08
1 signal ase nli
2 0 0.0002866683470642085 0.000325019416624 3.455694800734997e-08 3.8827360617812335e-08 2.1767706055953313e-07 2.397604591245591e-07
3 1 0.0002842930902246378 0.0003222815415358 3.4445260342151434e-08 3.8702821151814216e-08 2.20064716108892e-07 2.4267833614138976e-07
4 2 0.00028193841273409963 0.0003195661748689 3.4334217950641774e-08 3.8578942925493807e-08 2.2239856929822977e-07 2.455296149641726e-07
5 3 0.0002796041237984927 0.000316873132879 3.422381587730477e-08 3.8455721305309324e-08 2.2467937700272344e-07 2.483151861322029e-07
6 4 0.00027589218358262 0.0003125687708988 3.3956266402003705e-08 3.815158818797417e-08 2.2576401766047814e-07 2.497308542349044e-07
7 5 0.0002722303444814487 0.0003083216327341 3.3690926476196685e-08 3.784989647314237e-08 2.2678094635121413e-07 2.5106122773764815e-07
8 6 0.00026861791294303266 0.0003041309702107 3.342777134334201e-08 3.755062053762566e-08 2.2773179097640802e-07 2.523083160653813e-07
9 7 0.00026505174756069215 0.0002999931829076 3.316675429137828e-08 3.725370771318225e-08 2.2861602718115889e-07 2.534716728592015e-07
10 8 0.0002615312775878486 0.0002959076621852 3.290785186664305e-08 3.695913382975532e-08 2.294352005376256e-07 2.545532047834699e-07
11 9 0.0002577007690018081 0.0002914749637887 3.26092154155734e-08 3.6620413511505286e-08 2.2987401053105823e-07 2.5520557429118934e-07
12 10 0.00025392474812815994 0.0002871045786391 3.231329178154223e-08 3.62847038107824e-08 2.3024928325076607e-07 2.557776344401253e-07
13 11 0.0002501957390130402 0.0002827879891071 3.201993265117851e-08 3.5951828869209396e-08 2.3055653947072044e-07 2.5626453052593257e-07
14 12 0.0002465133077961936 0.0002785247470154 3.172911082648897e-08 3.562176113110911e-08 2.3079745224174315e-07 2.5666832208790035e-07
15 13 0.00024287702172285261 0.0002743144039041 3.144079924487205e-08 3.5294473123494e-08 2.309736700807475e-07 2.569910409348857e-07
16 14 0.00023918644496802598 0.000270032675166 3.1142660565561954e-08 3.4954880805048256e-08 2.3099023972100006e-07 2.571167784361306e-07
17 15 0.00023554415781363666 0.0002658067200554 3.084719002003063e-08 3.4618272391047544e-08 2.3094533745656626e-07 2.571652788509227e-07
18 16 0.0002319496781605366 0.000261636025157 3.0554358283826426e-08 3.428461757057609e-08 2.3084061926161906e-07 2.5713860104931033e-07
19 17 0.000228402746264896 0.00025752034599 3.026413819712743e-08 3.395388872366444e-08 2.306779372506828e-07 2.570390408700655e-07
20 18 0.00022490287297566154 0.000253459157096 2.997650061885732e-08 3.362605558722993e-08 2.2679314039447925e-07 2.5284986247287787e-07
21 19 0.0002210339853226993 0.000248983782073 2.9639081336421986e-08 3.3242702224575744e-08 2.225476971173533e-07 2.48252059976888e-07
22 20 0.00021722472675673681 0.0002445773493265 2.9305156366940595e-08 3.286328176612301e-08 2.1837424228396343e-07 2.437277481862015e-07
23 21 0.00021347443350916938 0.0002402391773459 2.8974683300060073e-08 3.2487750441670215e-08 2.1427183120915025e-07 2.392761376865807e-07
24 22 0.00020978233224910872 0.0002359684123723 2.864761802749998e-08 3.2116061418127753e-08 2.1023941353936252e-07 2.3489626905665574e-07
25 23 0.0002061476568412488 0.0002317642070805 2.832391679540816e-08 3.174816817069829e-08 2.0627595093585302e-07 2.3058719110264335e-07
26 24 0.0002028237056285935 0.0002279695550926 2.8034565895618217e-08 3.1424928539548144e-08 2.0263423697267893e-07 2.2668986526609113e-07
27 25 0.00019954715529254185 0.0002242281358436 2.7748013284124615e-08 3.1104729317697146e-08 1.9905015325521452e-07 2.228495045304229e-07
28 26 0.0001963174528000437 0.0002205393783222 2.7464226779716075e-08 3.078753835343166e-08 1.9552292765090665e-07 2.190654562751529e-07
29 27 0.00019313475803109547 0.0002169035545525 2.718318103861899e-08 3.047333197100547e-08 1.920525003885138e-07 2.1533790605165431e-07
30 28 0.00018999848980183525 0.0002133200561122 2.6904843987797665e-08 3.01620779209974e-08 1.8863807494364378e-07 2.1166616520930645e-07
31 29 0.00018690807208013476 0.0002097882786443 2.6629183784477213e-08 2.9853744125792176e-08 1.852788635171717e-07 2.080495504306458e-07
32 30 0.00018386293497138034 0.0002063076230434 2.635616888672288e-08 2.9548298767727423e-08 1.8197408797080072e-07 2.0448738489666716e-07
33 31 0.0001808626075954048 0.0002028776374913 2.608576967648626e-08 2.9245712991289203e-08 1.7872307155753016e-07 2.009791389793126e-07
34 32 0.00017790652540681915 0.0001994977236946 2.5817954962418864e-08 2.8945955168147914e-08 1.7552504805064169e-07 1.975241389908885e-07
35 33 0.00017499412908771533 0.0001961672877059 2.5552693765056307e-08 2.8648993828553545e-08 1.723792598876346e-07 1.9412171682473827e-07
36 34 0.0001721914205512116 0.0001929967738963 2.529821177538242e-08 2.8368195292008612e-08 1.69350416018518e-07 1.9088102669437356e-07
37 35 0.00016942913344260413 0.0001898709450753 2.5046172734840803e-08 2.8090002575266257e-08 1.663699885487624e-07 1.8768789971552863e-07
38 36 0.0001667067703020692 0.0001867892958482 2.4796549229968703e-08 2.7814389032455363e-08 1.6343730102750106e-07 1.8454176486632323e-07
39 37 0.00016402494737034808 0.000183752636707 2.4549324625938814e-08 2.754134148447891e-08 1.602954566731582e-07 1.8115002092564538e-07
40 38 0.0001613831201060569 0.0001807604032471 2.430447139995257e-08 2.7270832946920812e-08 1.5720933628441338e-07 1.7781492252546064e-07
41 39 0.00015878075021906192 0.0001778120365192 2.406196225171638e-08 2.7002836607760232e-08 1.541780421866172e-07 1.745356369687972e-07
42 40 0.00015621730558753943 0.0001749069829579 2.3821770097360405e-08 2.673732582084065e-08 1.5120068940449393e-07 1.7131134159682263e-07
43 41 0.000153694061439545 0.0001720467771106 2.3583901792213434e-08 2.6474316260529432e-08 1.4827814327673852e-07 1.6814325920632144e-07
44 42 0.00015121040694331307 0.0001692307716138 2.3348329147104765e-08 2.6213779758633963e-08 1.4540943949658482e-07 1.6503047175593728e-07
45 43 0.00014876574026315321 0.0001664583277393 2.3115024224465226e-08 2.5955688359138642e-08 1.425936300160931e-07 1.619720751255672e-07
46 44 0.00014623043935025647 0.0001635796256227 2.2864250993313975e-08 2.5677295228672648e-08 1.397065102093322e-07 1.588223280583729e-07
47 45 0.00014373723010448477 0.0001607481963598 2.2616046400344574e-08 2.540169810843596e-08 1.3687531950007013e-07 1.557306487644946e-07
48 46 0.0001412854316913198 0.0001579633073114 2.2370377299191064e-08 2.512886316325068e-08 1.3409901704421416e-07 1.526960267832303e-07
49 47 0.00013887544742801196 0.0001552255108883 2.2127221340618422e-08 2.4858770138402143e-08 1.313775961274423e-07 1.4971869736122287e-07
50 48 0.0001365065605420479 0.000152534027681 2.1886545482453933e-08 2.4591385101783997e-08 1.2870998887773554e-07 1.467976093017761e-07
51 49 0.00013417806673897108 0.0001498880910245 2.164831702445933e-08 2.432667443532368e-08 1.2609514810979993e-07 1.439317302908228e-07
52 50 0.00013188927370907155 0.0001472869464661 2.1412503578881085e-08 2.4064604800471338e-08 1.2353204666803017e-07 1.411200462508912e-07
53 51 0.00012964085531237725 0.0001447314108795 2.117909919147538e-08 2.3805175801260087e-08 1.2102094138348867e-07 1.3836305172259211e-07
54 52 0.00012743207116500861 0.0001422206714078 2.094807084934547e-08 2.3548353146553164e-08 1.1856076487337955e-07 1.3565967973526553e-07
55 53 0.0001252621950917354 0.0001397539300508 2.0719385892834214e-08 2.3294102880186107e-08 1.161504721855161e-07 1.3300888438790536e-07
56 54 0.00012308423338164536 0.0001372700286953 2.0485363383535514e-08 2.3032485432340423e-08 1.1374627006340893e-07 1.3035230831596558e-07
57 55 0.00012094535834842106 0.0001348306664569 2.0253755300794944e-08 2.2773547798807564e-08 1.1139168040879032e-07 1.277485195296911e-07
58 56 0.00011884484242431182 0.0001324350333325 2.0024527468430072e-08 2.2517253805739807e-08 1.0897675288127846e-07 1.2505815113074245e-07
59 57 0.00011678298769107047 0.0001300835425363 1.9797656169961167e-08 2.2263580536243144e-08 1.0661409941810817e-07 1.2242454150816991e-07
60 58 0.0001147590394591346 0.0001277753479236 1.9573107382367898e-08 2.2012491805819457e-08 1.0430256532408603e-07 1.1984647647989558e-07
61 59 0.00011277225867179729 0.0001255096202792 1.935084744632288e-08 2.1763951788812352e-08 1.0204102225018314e-07 1.1732276843747534e-07
62 60 0.00011082192110664448 0.0001232855464269 1.913084301808743e-08 2.1517924960982367e-08 9.982836715827351e-08 1.148522552473446e-07
63 61 0.00010890831555726861 0.0001211034718808 1.8913080844667903e-08 2.1274400813402842e-08 9.76644171489201e-08 1.1243486085670634e-07
64 62 0.00010703069380321927 0.0001189625537742 1.8697527263494167e-08 2.1033343271785093e-08 9.554805889434612e-08 1.100694052812587e-07
65 63 0.00010518832400867466 0.0001168619671686 1.8484148971365717e-08 2.0794716623616593e-08 9.347820572370307e-08 1.0775473577456182e-07
66 64 0.00010353027948847247 0.0001149842862687 1.8300360477604286e-08 2.0591381044652174e-08 9.158630538270034e-08 1.056582342233035e-07
67 65 0.00010190114820620951 0.0001131392424142 1.8118339508838893e-08 2.038998454906055e-08 8.97332684173061e-08 1.0360354473279054e-07
68 66 0.00010030037817345079 0.0001113262252932 1.7938063167097722e-08 2.0190503422606346e-08 8.791826040657302e-08 1.0158979943539652e-07
69 67 9.872746699919663e-05 0.0001095446965516 1.775950920143011e-08 1.9992914861970927e-08 8.614049912759125e-08 9.961620365200192e-08
70 68 9.718188342878233e-05 0.0001077940670993 1.7582655209782296e-08 1.9797195630879305e-08 8.439918541238176e-08 9.768192356581421e-08
71 69 9.566310719955732e-05 0.0001060737596438 1.740747903977101e-08 1.9603322741072024e-08 8.269353818341506e-08 9.578614349620901e-08
72 70 9.417062845393912e-05 0.0001043832080373 1.7233958752991638e-08 1.9411273409584944e-08 8.102279372648069e-08 9.392806512410292e-08
73 71 9.27044102709892e-05 0.0001027223865858 1.7062082036004708e-08 1.922103688152168e-08 7.938660156523957e-08 9.210738192714242e-08
74 72 9.12639411274833e-05 0.0001010907257366 1.6891826998956218e-08 1.9032590330084783e-08 7.778420731697601e-08 9.032330177845482e-08
75 73 8.984872036936478e-05 9.948766769187398e-05 1.6723171993235663e-08 1.8845911172333032e-08 7.621487408851861e-08 8.857505025129074e-08
76 74 8.845926525396718e-05 9.792267601599324e-05 1.6557077218868872e-08 1.8663442661346744e-08 7.467873241780861e-08 8.687075031773093e-08
77 75 8.709405706837696e-05 9.638489299064336e-05 1.6392620086127443e-08 1.848276820506329e-08 7.352620174175576e-08 8.550652733411691e-08
78 76 8.575262707251024e-05 9.48738026587305e-05 1.6229781230847938e-08 1.830386814585904e-08 7.239374499535451e-08 8.416598440502352e-08
79 77 8.44345490553445e-05 9.338895072626004e-05 1.6068541919248203e-08 1.8126723701740663e-08 7.128100236441453e-08 8.284871850980459e-08
80 78 8.313937224726923e-05 9.192983962632808e-05 1.5908883354530017e-08 1.7951315790883015e-08 7.018759330199112e-08 8.155428823884958e-08
81 79 8.18666553697718e-05 9.049598195913348e-05 1.5750787028460176e-08 1.7777625631449783e-08 6.91131452736768e-08 8.028226120215297e-08
82 80 8.061596620368467e-05 8.908690001727453e-05 1.5594234699428168e-08 1.7605634715742614e-08 6.80572933931087e-08 7.903221360818749e-08
83 81 7.93869860927298e-05 8.77022482135352e-05 1.54392105845737e-08 1.743532764682425e-08 6.701976864553917e-08 7.780383887402493e-08
84 82 7.81792957880057e-05 8.634156228069215e-05 1.528569691328632e-08 1.7266686393258476e-08 6.600021709431229e-08 7.659672513140668e-08
85 83 7.69924848842345e-05 8.50043874741986e-05 1.5133676199095668e-08 1.7099693224424935e-08 6.499829226870119e-08 7.541046895998541e-08
86 84 7.592423495462984e-05 8.381694660770028e-05 1.5006007729453082e-08 1.6962933489525264e-08 6.40964585216171e-08 7.43570471865261e-08
87 85 7.487323130273564e-05 8.26484651987276e-05 1.4879695488874347e-08 1.682764479561346e-08 6.320918435915818e-08 7.33204450340972e-08
88 86 7.383915942693816e-05 8.149860566615124e-05 1.475473179887786e-08 1.6693821025332528e-08 6.233620427401105e-08 7.230036302225977e-08
89 87 7.282024738915393e-05 8.036532369463753e-05 1.4631093950979863e-08 1.6561436760581683e-08 6.147602236758762e-08 7.129498756488483e-08
90 88 7.181625694043332e-05 7.924836834130927e-05 1.4508775744557438e-08 1.6430487594212236e-08 6.062843750629826e-08 7.030409604146297e-08
91 89 7.082695384072487e-05 7.814749266035204e-05 1.4387771381868581e-08 1.6300969571299207e-08 5.979325194092954e-08 6.932746937742372e-08
92 90 6.985210770121701e-05 7.706245353522453e-05 1.4268075471622408e-08 1.6172879193985398e-08 5.8970271173546604e-08 6.836489189528336e-08
93 91 6.889061932028676e-05 7.599203524832233e-05 1.414966436041678e-08 1.6046190191322708e-08 5.8158567240485706e-08 6.741528508795074e-08
94 92 6.79423037538828e-05 7.493604414299442e-05 1.4032534237451406e-08 1.5920900877281144e-08 5.7357984009008465e-08 6.647847715560108e-08
95 93 6.700697867481953e-05 7.389428911314724e-05 1.3916681725635683e-08 1.57970100612018e-08 5.656836755557654e-08 6.555429856110159e-08
96 94 6.594003301527265e-05 7.268136514077581e-05 1.3765768410137306e-08 1.5628904744452727e-08 5.5667634894222326e-08 6.447826980203191e-08
97 95 6.489000516837228e-05 7.148784598320314e-05 1.3616343300622314e-08 1.5462487634551132e-08 5.4781184522010985e-08 6.341945575654982e-08

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
tests/data/wrong_service.xlsx Executable file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
tests/data/wrong_topo_eqpt.xlsx Executable file

Binary file not shown.

BIN
tests/data/wrong_topo_link.xlsx Executable file

Binary file not shown.

Binary file not shown.

BIN
tests/data/wrong_topo_node.xlsx Executable file

Binary file not shown.

View File

@@ -0,0 +1,37 @@
INFO gnpy.tools.cli_examples:cli_examples.py Computing path requests meshTopologyExampleV2.xls into JSON format
INFO gnpy.tools.json_io:json_io.py Automatically converting requests from XLS to JSON
INFO gnpy.topology.request:request.py
request 0
Computing path from trx Lorient_KMA to trx Vannes_KBE
with path constraint: ['trx Lorient_KMA', 'trx Vannes_KBE']
Computed path (roadms):['roadm Lorient_KMA', 'roadm Vannes_KBE']
INFO gnpy.topology.request:request.py
request 1
Computing path from trx Brest_KLA to trx Vannes_KBE
with path constraint: ['trx Brest_KLA', 'roadm Brest_KLA', 'roadm Lannion_CAS', 'roadm Lorient_KMA', 'roadm Vannes_KBE', 'trx Vannes_KBE']
Computed path (roadms):['roadm Brest_KLA', 'roadm Lannion_CAS', 'roadm Lorient_KMA', 'roadm Vannes_KBE']
INFO gnpy.topology.request:request.py
request 3
Computing path from trx Lannion_CAS to trx Rennes_STA
with path constraint: ['trx Lannion_CAS', 'trx Rennes_STA']
Computed path (roadms):['roadm Lannion_CAS', 'roadm Rennes_STA']
INFO gnpy.topology.request:request.py
request 4
Computing path from trx Rennes_STA to trx Lannion_CAS
with path constraint: ['trx Rennes_STA', 'trx Lannion_CAS']
Computed path (roadms):['roadm Rennes_STA', 'roadm Vannes_KBE', 'roadm Lorient_KMA', 'roadm Lannion_CAS']
INFO gnpy.topology.request:request.py
request 5
Computing path from trx Rennes_STA to trx Lannion_CAS
with path constraint: ['trx Rennes_STA', 'trx Lannion_CAS']
Computed path (roadms):['roadm Rennes_STA', 'roadm Lannion_CAS']
INFO gnpy.topology.request:request.py
request 7 | 6
Computing path from trx Lannion_CAS to trx Lorient_KMA
with path constraint: ['trx Lannion_CAS', 'trx Lorient_KMA']
Computed path (roadms):['roadm Lannion_CAS', 'roadm Lorient_KMA']
INFO gnpy.topology.request:request.py
request 7b
Computing path from trx Lannion_CAS to trx Lorient_KMA
with path constraint: ['trx Lannion_CAS', 'trx Lorient_KMA']
Computed path (roadms):['roadm Lannion_CAS', 'roadm Lorient_KMA']

View File

@@ -0,0 +1,13 @@
INFO gnpy.tools.cli_examples:cli_examples.py Computing path requests CORONET_services.json into JSON format
INFO gnpy.topology.request:request.py
request 0
Computing path from trx Abilene to trx Albany
with path constraint: ['trx Abilene', 'trx Albany']
Computed path (roadms):['roadm Abilene', 'roadm Dallas', 'roadm Little_Rock', 'roadm Memphis', 'roadm Nashville', 'roadm Louisville', 'roadm Cincinnati', 'roadm Columbus', 'roadm Cleveland', 'roadm Buffalo', 'roadm Rochester', 'roadm Syracuse', 'roadm Albany']
WARNING gnpy.topology.request:request.py Warning! Request 0 computed path from trx Abilene to trx Albany does not pass with mode 3
computed SNR in 0.1nm = 14.44
PDL penalty not evaluated
CD penalty not evaluated
PMD penalty not evaluated
required osnr = 18
system margin = 2

View File

@@ -0,0 +1,307 @@
INFO gnpy.tools.cli_examples:cli_examples.py source = 'lannion'
INFO gnpy.tools.cli_examples:cli_examples.py destination = 'lorient'
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node west edfa in Lorient_KMA to Loudeac
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: effective gain in Node east edfa in Lannion_CAS to Stbrieuc
is above user specified amplifier std_low_gain
max flat gain: 16dB ; required gain: 23.0dB. Please check amplifier type.
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node west edfa in Rennes_STA to Stbrieuc
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: effective gain in Node east edfa in Lannion_CAS to Morlaix
is above user specified amplifier std_low_gain
max flat gain: 16dB ; required gain: 23.5dB. Please check amplifier type.
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node west edfa in Brest_KLA to Morlaix
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node east edfa in Lorient_KMA to Loudeac
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: effective gain in Node west edfa in Lannion_CAS to Corlay
is above user specified amplifier test
max flat gain: 25dB ; required gain: 29.82dB. Please check amplifier type.
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node east edfa in Lorient_KMA to Vannes_KBE
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node west edfa in Vannes_KBE to Lorient_KMA
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node east edfa in Lorient_KMA to Quimper
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node west edfa in Quimper to Lorient_KMA
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node west edfa in Brest_KLA to Quimper
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node east edfa in Vannes_KBE to Lorient_KMA
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node west edfa in Lorient_KMA to Vannes_KBE
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node east edfa in Vannes_KBE to Ploermel
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node west edfa in Ploermel to Vannes_KBE
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node west edfa in Rennes_STA to Ploermel
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node east edfa in Rennes_STA to Stbrieuc
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node west edfa in Stbrieuc to Rennes_STA
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node west edfa in Lannion_CAS to Stbrieuc
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node east edfa in Rennes_STA to Ploermel
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node west edfa in Vannes_KBE to Ploermel
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node east edfa in Brest_KLA to Morlaix
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: effective gain in Node east edfa in Brest_KLA to Quimper
is above user specified amplifier std_low_gain
max flat gain: 16dB ; required gain: 23.0dB. Please check amplifier type.
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node east edfa in Quimper to Lorient_KMA
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node west edfa in Lorient_KMA to Quimper
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node east edfa in a to b
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node west edfa in b to a
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node east edfa in a to c
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node west edfa in c to a
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node east edfa in b to a
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node west edfa in a to b
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node east edfa in b to f
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node west edfa in f to b
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node east edfa in c to a
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node west edfa in a to c
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node west edfa in d to c
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node east edfa in c to f
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node west edfa in f to c
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node east edfa in d to c
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node west edfa in c to d
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node east edfa in d to e
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node west edfa in e to d
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node east edfa in e to d
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node west edfa in d to e
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node east edfa in e to g
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node west edfa in g to e
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node east edfa in f to c
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node west edfa in c to f
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node east edfa in f to b
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node west edfa in b to f
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node east edfa in f to h
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node west edfa in h to f
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node east edfa in g to e
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node west edfa in e to g
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node east edfa in g to h
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node west edfa in h to g
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node east edfa in h to f
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node west edfa in f to h
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node east edfa in h to g
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING gnpy.core.network:network.py
WARNING: target gain and power in node west edfa in g to h
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied

View File

@@ -15,9 +15,11 @@ Transceiver trx_Stockholm
CD (ps/nm): 0.00 CD (ps/nm): 0.00
PMD (ps): 0.00 PMD (ps): 0.00
PDL (dB): 0.00 PDL (dB): 0.00
Latency (ms): 0.00
Roadm roadm_Stockholm Roadm roadm_Stockholm
effective loss (dB): 22.00 effective loss (dB): 22.00
pch out (dBm): -20.00 reference pch out (dBm): -20.00
actual pch out (dBm): -20.00
Edfa Edfa_booster_roadm_Stockholm_to_fiber (Stockholm → Norrköping)_(1/2) Edfa Edfa_booster_roadm_Stockholm_to_fiber (Stockholm → Norrköping)_(1/2)
type_variety: openroadm_mw_mw_booster type_variety: openroadm_mw_mw_booster
effective gain(dB): 22.00 effective gain(dB): 22.00
@@ -30,6 +32,7 @@ Edfa Edfa_booster_roadm_Stockholm_to_fiber (Stockholm → Norrköping)_(1/2)
Delta_P (dB): 0.00 Delta_P (dB): 0.00
target pch (dBm): 2.00 target pch (dBm): 2.00
effective pch (dBm): 2.00 effective pch (dBm): 2.00
actual pch out (dBm): 2.00
output VOA (dB): 0.00 output VOA (dB): 0.00
Fiber fiber (Stockholm → Norrköping)_(1/2) Fiber fiber (Stockholm → Norrköping)_(1/2)
type_variety: SSMF type_variety: SSMF
@@ -38,7 +41,8 @@ Fiber fiber (Stockholm → Norrköping)_(1/2)
total loss (dB): 16.33 total loss (dB): 16.33
(includes conn loss (dB) in: 0.00 out: 0.00) (includes conn loss (dB) in: 0.00 out: 0.00)
(conn loss out includes EOL margin defined in eqpt_config.json) (conn loss out includes EOL margin defined in eqpt_config.json)
pch out (dBm): -14.33 reference pch out (dBm): -14.33
actual pch out (dBm): -14.31
Edfa Edfa_fiber (Stockholm → Norrköping)_(1/2) Edfa Edfa_fiber (Stockholm → Norrköping)_(1/2)
type_variety: openroadm_ila_low_noise type_variety: openroadm_ila_low_noise
effective gain(dB): 16.33 effective gain(dB): 16.33
@@ -51,6 +55,7 @@ Edfa Edfa_fiber (Stockholm → Norrköping)_(1/2)
Delta_P (dB): 0.00 Delta_P (dB): 0.00
target pch (dBm): 2.00 target pch (dBm): 2.00
effective pch (dBm): 2.00 effective pch (dBm): 2.00
actual pch out (dBm): 2.02
output VOA (dB): 0.00 output VOA (dB): 0.00
Fiber fiber (Stockholm → Norrköping)_(2/2) Fiber fiber (Stockholm → Norrköping)_(2/2)
type_variety: SSMF type_variety: SSMF
@@ -59,7 +64,8 @@ Fiber fiber (Stockholm → Norrköping)_(2/2)
total loss (dB): 16.33 total loss (dB): 16.33
(includes conn loss (dB) in: 0.00 out: 0.00) (includes conn loss (dB) in: 0.00 out: 0.00)
(conn loss out includes EOL margin defined in eqpt_config.json) (conn loss out includes EOL margin defined in eqpt_config.json)
pch out (dBm): -14.33 reference pch out (dBm): -14.33
actual pch out (dBm): -14.29
Edfa Edfa_preamp_roadm_Norrköping_from_fiber (Stockholm → Norrköping)_(2/2) Edfa Edfa_preamp_roadm_Norrköping_from_fiber (Stockholm → Norrköping)_(2/2)
type_variety: openroadm_mw_mw_preamp type_variety: openroadm_mw_mw_preamp
effective gain(dB): 16.33 effective gain(dB): 16.33
@@ -72,10 +78,12 @@ Edfa Edfa_preamp_roadm_Norrköping_from_fiber (Stockholm → Norrköping)_(2/2)
Delta_P (dB): 0.00 Delta_P (dB): 0.00
target pch (dBm): 2.00 target pch (dBm): 2.00
effective pch (dBm): 2.00 effective pch (dBm): 2.00
actual pch out (dBm): 2.04
output VOA (dB): 0.00 output VOA (dB): 0.00
Roadm roadm_Norrköping Roadm roadm_Norrköping
effective loss (dB): 22.00 effective loss (dB): 22.00
pch out (dBm): -20.00 reference pch out (dBm): -20.00
actual pch out (dBm): -20.00
Edfa Edfa_booster_roadm_Norrköping_to_fiber (Norrköping → Linköping) Edfa Edfa_booster_roadm_Norrköping_to_fiber (Norrköping → Linköping)
type_variety: openroadm_mw_mw_booster type_variety: openroadm_mw_mw_booster
effective gain(dB): 22.00 effective gain(dB): 22.00
@@ -88,6 +96,7 @@ Edfa Edfa_booster_roadm_Norrköping_to_fiber (Norrköping → Linköping)
Delta_P (dB): 0.00 Delta_P (dB): 0.00
target pch (dBm): 2.00 target pch (dBm): 2.00
effective pch (dBm): 2.00 effective pch (dBm): 2.00
actual pch out (dBm): 2.00
output VOA (dB): 0.00 output VOA (dB): 0.00
Fiber fiber (Norrköping → Linköping) Fiber fiber (Norrköping → Linköping)
type_variety: SSMF type_variety: SSMF
@@ -96,7 +105,8 @@ Fiber fiber (Norrköping → Linköping)
total loss (dB): 11.00 total loss (dB): 11.00
(includes conn loss (dB) in: 0.00 out: 0.00) (includes conn loss (dB) in: 0.00 out: 0.00)
(conn loss out includes EOL margin defined in eqpt_config.json) (conn loss out includes EOL margin defined in eqpt_config.json)
pch out (dBm): -9.00 reference pch out (dBm): -9.00
actual pch out (dBm): -9.00
Edfa Edfa_preamp_roadm_Linköping_from_fiber (Norrköping → Linköping) Edfa Edfa_preamp_roadm_Linköping_from_fiber (Norrköping → Linköping)
type_variety: openroadm_mw_mw_preamp type_variety: openroadm_mw_mw_preamp
effective gain(dB): 11.00 effective gain(dB): 11.00
@@ -109,10 +119,12 @@ Edfa Edfa_preamp_roadm_Linköping_from_fiber (Norrköping → Linköping)
Delta_P (dB): 0.00 Delta_P (dB): 0.00
target pch (dBm): 2.00 target pch (dBm): 2.00
effective pch (dBm): 2.00 effective pch (dBm): 2.00
actual pch out (dBm): 2.01
output VOA (dB): 0.00 output VOA (dB): 0.00
Roadm roadm_Linköping Roadm roadm_Linköping
effective loss (dB): 22.00 effective loss (dB): 22.00
pch out (dBm): -20.00 reference pch out (dBm): -20.00
actual pch out (dBm): -20.00
Edfa Edfa_booster_roadm_Linköping_to_fiber (Linköping → Jönköping) Edfa Edfa_booster_roadm_Linköping_to_fiber (Linköping → Jönköping)
type_variety: openroadm_mw_mw_booster type_variety: openroadm_mw_mw_booster
effective gain(dB): 22.00 effective gain(dB): 22.00
@@ -125,6 +137,7 @@ Edfa Edfa_booster_roadm_Linköping_to_fiber (Linköping → Jönköping)
Delta_P (dB): 0.00 Delta_P (dB): 0.00
target pch (dBm): 2.00 target pch (dBm): 2.00
effective pch (dBm): 2.00 effective pch (dBm): 2.00
actual pch out (dBm): 2.00
output VOA (dB): 0.00 output VOA (dB): 0.00
Fiber fiber (Linköping → Jönköping) Fiber fiber (Linköping → Jönköping)
type_variety: SSMF type_variety: SSMF
@@ -133,7 +146,8 @@ Fiber fiber (Linköping → Jönköping)
total loss (dB): 26.80 total loss (dB): 26.80
(includes conn loss (dB) in: 0.00 out: 0.00) (includes conn loss (dB) in: 0.00 out: 0.00)
(conn loss out includes EOL margin defined in eqpt_config.json) (conn loss out includes EOL margin defined in eqpt_config.json)
pch out (dBm): -24.80 reference pch out (dBm): -24.80
actual pch out (dBm): -24.79
Edfa Edfa_preamp_roadm_Jönköping_from_fiber (Linköping → Jönköping) Edfa Edfa_preamp_roadm_Jönköping_from_fiber (Linköping → Jönköping)
type_variety: openroadm_mw_mw_preamp type_variety: openroadm_mw_mw_preamp
effective gain(dB): 26.80 effective gain(dB): 26.80
@@ -146,10 +160,12 @@ Edfa Edfa_preamp_roadm_Jönköping_from_fiber (Linköping → Jönköping)
Delta_P (dB): 0.00 Delta_P (dB): 0.00
target pch (dBm): 2.00 target pch (dBm): 2.00
effective pch (dBm): 2.00 effective pch (dBm): 2.00
actual pch out (dBm): 2.04
output VOA (dB): 0.00 output VOA (dB): 0.00
Roadm roadm_Jönköping Roadm roadm_Jönköping
effective loss (dB): 22.00 effective loss (dB): 22.00
pch out (dBm): -20.00 reference pch out (dBm): -20.00
actual pch out (dBm): -20.00
Edfa Edfa_booster_roadm_Jönköping_to_fiber (Jönköping → Borås) Edfa Edfa_booster_roadm_Jönköping_to_fiber (Jönköping → Borås)
type_variety: openroadm_mw_mw_booster type_variety: openroadm_mw_mw_booster
effective gain(dB): 22.00 effective gain(dB): 22.00
@@ -162,6 +178,7 @@ Edfa Edfa_booster_roadm_Jönköping_to_fiber (Jönköping → Borås)
Delta_P (dB): 0.00 Delta_P (dB): 0.00
target pch (dBm): 2.00 target pch (dBm): 2.00
effective pch (dBm): 2.00 effective pch (dBm): 2.00
actual pch out (dBm): 2.00
output VOA (dB): 0.00 output VOA (dB): 0.00
Fiber fiber (Jönköping → Borås) Fiber fiber (Jönköping → Borås)
type_variety: SSMF type_variety: SSMF
@@ -170,7 +187,8 @@ Fiber fiber (Jönköping → Borås)
total loss (dB): 17.82 total loss (dB): 17.82
(includes conn loss (dB) in: 0.00 out: 0.00) (includes conn loss (dB) in: 0.00 out: 0.00)
(conn loss out includes EOL margin defined in eqpt_config.json) (conn loss out includes EOL margin defined in eqpt_config.json)
pch out (dBm): -15.82 reference pch out (dBm): -15.82
actual pch out (dBm): -15.81
Edfa Edfa_preamp_roadm_Borås_from_fiber (Jönköping → Borås) Edfa Edfa_preamp_roadm_Borås_from_fiber (Jönköping → Borås)
type_variety: openroadm_mw_mw_preamp type_variety: openroadm_mw_mw_preamp
effective gain(dB): 17.82 effective gain(dB): 17.82
@@ -183,10 +201,12 @@ Edfa Edfa_preamp_roadm_Borås_from_fiber (Jönköping → Borås)
Delta_P (dB): 0.00 Delta_P (dB): 0.00
target pch (dBm): 2.00 target pch (dBm): 2.00
effective pch (dBm): 2.00 effective pch (dBm): 2.00
actual pch out (dBm): 2.02
output VOA (dB): 0.00 output VOA (dB): 0.00
Roadm roadm_Borås Roadm roadm_Borås
effective loss (dB): 22.00 effective loss (dB): 22.00
pch out (dBm): -20.00 reference pch out (dBm): -20.00
actual pch out (dBm): -20.00
Edfa Edfa_booster_roadm_Borås_to_fiber (Borås → Gothenburg) Edfa Edfa_booster_roadm_Borås_to_fiber (Borås → Gothenburg)
type_variety: openroadm_mw_mw_booster type_variety: openroadm_mw_mw_booster
effective gain(dB): 22.00 effective gain(dB): 22.00
@@ -199,6 +219,7 @@ Edfa Edfa_booster_roadm_Borås_to_fiber (Borås → Gothenburg)
Delta_P (dB): 0.00 Delta_P (dB): 0.00
target pch (dBm): 2.00 target pch (dBm): 2.00
effective pch (dBm): 2.00 effective pch (dBm): 2.00
actual pch out (dBm): 2.00
output VOA (dB): 0.00 output VOA (dB): 0.00
Fiber fiber (Borås → Gothenburg) Fiber fiber (Borås → Gothenburg)
type_variety: SSMF type_variety: SSMF
@@ -207,7 +228,8 @@ Fiber fiber (Borås → Gothenburg)
total loss (dB): 13.53 total loss (dB): 13.53
(includes conn loss (dB) in: 0.00 out: 0.00) (includes conn loss (dB) in: 0.00 out: 0.00)
(conn loss out includes EOL margin defined in eqpt_config.json) (conn loss out includes EOL margin defined in eqpt_config.json)
pch out (dBm): -11.53 reference pch out (dBm): -11.53
actual pch out (dBm): -11.52
Edfa Edfa_preamp_roadm_Gothenburg_from_fiber (Borås → Gothenburg) Edfa Edfa_preamp_roadm_Gothenburg_from_fiber (Borås → Gothenburg)
type_variety: openroadm_mw_mw_preamp type_variety: openroadm_mw_mw_preamp
effective gain(dB): 13.53 effective gain(dB): 13.53
@@ -220,21 +242,24 @@ Edfa Edfa_preamp_roadm_Gothenburg_from_fiber (Borås → Gothenburg)
Delta_P (dB): 0.00 Delta_P (dB): 0.00
target pch (dBm): 2.00 target pch (dBm): 2.00
effective pch (dBm): 2.00 effective pch (dBm): 2.00
actual pch out (dBm): 2.02
output VOA (dB): 0.00 output VOA (dB): 0.00
Roadm roadm_Gothenburg Roadm roadm_Gothenburg
effective loss (dB): 22.00 effective loss (dB): 22.00
pch out (dBm): -20.00 reference pch out (dBm): -20.00
actual pch out (dBm): -20.00
Transceiver trx_Gothenburg Transceiver trx_Gothenburg
GSNR (0.1nm, dB): 18.90 GSNR (0.1nm, dB): 18.89
GSNR (signal bw, dB): 14.88 GSNR (signal bw, dB): 14.86
OSNR ASE (0.1nm, dB): 21.20 OSNR ASE (0.1nm, dB): 21.20
OSNR ASE (signal bw, dB): 17.18 OSNR ASE (signal bw, dB): 17.18
CD (ps/nm): 8350.42 CD (ps/nm): 8350.42
PMD (ps): 7.99 PMD (ps): 7.99
PDL (dB): 3.74 PDL (dB): 3.74
Latency (ms): 2.45
Transmission result for input power = 2.00 dBm: Transmission result for input power = 2.00 dBm:
Final GSNR (0.1 nm): 18.90 dB Final GSNR (0.1 nm): 18.89 dB
(No source node specified: picked trx_Stockholm) (No source node specified: picked trx_Stockholm)

View File

@@ -15,9 +15,11 @@ Transceiver trx_Stockholm
CD (ps/nm): 0.00 CD (ps/nm): 0.00
PMD (ps): 0.00 PMD (ps): 0.00
PDL (dB): 0.00 PDL (dB): 0.00
Latency (ms): 0.00
Roadm roadm_Stockholm Roadm roadm_Stockholm
effective loss (dB): 22.00 effective loss (dB): 22.00
pch out (dBm): -20.00 reference pch out (dBm): -20.00
actual pch out (dBm): -20.00
Edfa Edfa_booster_roadm_Stockholm_to_fiber (Stockholm → Norrköping)_(1/2) Edfa Edfa_booster_roadm_Stockholm_to_fiber (Stockholm → Norrköping)_(1/2)
type_variety: openroadm_mw_mw_booster type_variety: openroadm_mw_mw_booster
effective gain(dB): 22.00 effective gain(dB): 22.00
@@ -30,6 +32,7 @@ Edfa Edfa_booster_roadm_Stockholm_to_fiber (Stockholm → Norrköping)_(1/2)
Delta_P (dB): 0.00 Delta_P (dB): 0.00
target pch (dBm): 2.00 target pch (dBm): 2.00
effective pch (dBm): 2.00 effective pch (dBm): 2.00
actual pch out (dBm): 2.00
output VOA (dB): 0.00 output VOA (dB): 0.00
Fiber fiber (Stockholm → Norrköping)_(1/2) Fiber fiber (Stockholm → Norrköping)_(1/2)
type_variety: SSMF type_variety: SSMF
@@ -38,7 +41,8 @@ Fiber fiber (Stockholm → Norrköping)_(1/2)
total loss (dB): 16.33 total loss (dB): 16.33
(includes conn loss (dB) in: 0.00 out: 0.00) (includes conn loss (dB) in: 0.00 out: 0.00)
(conn loss out includes EOL margin defined in eqpt_config.json) (conn loss out includes EOL margin defined in eqpt_config.json)
pch out (dBm): -14.33 reference pch out (dBm): -14.33
actual pch out (dBm): -14.31
Edfa Edfa_fiber (Stockholm → Norrköping)_(1/2) Edfa Edfa_fiber (Stockholm → Norrköping)_(1/2)
type_variety: openroadm_ila_low_noise type_variety: openroadm_ila_low_noise
effective gain(dB): 16.33 effective gain(dB): 16.33
@@ -51,6 +55,7 @@ Edfa Edfa_fiber (Stockholm → Norrköping)_(1/2)
Delta_P (dB): 0.00 Delta_P (dB): 0.00
target pch (dBm): 2.00 target pch (dBm): 2.00
effective pch (dBm): 2.00 effective pch (dBm): 2.00
actual pch out (dBm): 2.02
output VOA (dB): 0.00 output VOA (dB): 0.00
Fiber fiber (Stockholm → Norrköping)_(2/2) Fiber fiber (Stockholm → Norrköping)_(2/2)
type_variety: SSMF type_variety: SSMF
@@ -59,7 +64,8 @@ Fiber fiber (Stockholm → Norrköping)_(2/2)
total loss (dB): 16.33 total loss (dB): 16.33
(includes conn loss (dB) in: 0.00 out: 0.00) (includes conn loss (dB) in: 0.00 out: 0.00)
(conn loss out includes EOL margin defined in eqpt_config.json) (conn loss out includes EOL margin defined in eqpt_config.json)
pch out (dBm): -14.33 reference pch out (dBm): -14.33
actual pch out (dBm): -14.29
Edfa Edfa_preamp_roadm_Norrköping_from_fiber (Stockholm → Norrköping)_(2/2) Edfa Edfa_preamp_roadm_Norrköping_from_fiber (Stockholm → Norrköping)_(2/2)
type_variety: openroadm_mw_mw_preamp_worstcase_ver5 type_variety: openroadm_mw_mw_preamp_worstcase_ver5
effective gain(dB): 16.33 effective gain(dB): 16.33
@@ -72,10 +78,12 @@ Edfa Edfa_preamp_roadm_Norrköping_from_fiber (Stockholm → Norrköping)_(2/2)
Delta_P (dB): 0.00 Delta_P (dB): 0.00
target pch (dBm): 2.00 target pch (dBm): 2.00
effective pch (dBm): 2.00 effective pch (dBm): 2.00
actual pch out (dBm): 2.04
output VOA (dB): 0.00 output VOA (dB): 0.00
Roadm roadm_Norrköping Roadm roadm_Norrköping
effective loss (dB): 22.00 effective loss (dB): 22.00
pch out (dBm): -20.00 reference pch out (dBm): -20.00
actual pch out (dBm): -20.00
Edfa Edfa_booster_roadm_Norrköping_to_fiber (Norrköping → Linköping) Edfa Edfa_booster_roadm_Norrköping_to_fiber (Norrköping → Linköping)
type_variety: openroadm_mw_mw_booster type_variety: openroadm_mw_mw_booster
effective gain(dB): 22.00 effective gain(dB): 22.00
@@ -88,6 +96,7 @@ Edfa Edfa_booster_roadm_Norrköping_to_fiber (Norrköping → Linköping)
Delta_P (dB): 0.00 Delta_P (dB): 0.00
target pch (dBm): 2.00 target pch (dBm): 2.00
effective pch (dBm): 2.00 effective pch (dBm): 2.00
actual pch out (dBm): 2.00
output VOA (dB): 0.00 output VOA (dB): 0.00
Fiber fiber (Norrköping → Linköping) Fiber fiber (Norrköping → Linköping)
type_variety: SSMF type_variety: SSMF
@@ -96,7 +105,8 @@ Fiber fiber (Norrköping → Linköping)
total loss (dB): 11.00 total loss (dB): 11.00
(includes conn loss (dB) in: 0.00 out: 0.00) (includes conn loss (dB) in: 0.00 out: 0.00)
(conn loss out includes EOL margin defined in eqpt_config.json) (conn loss out includes EOL margin defined in eqpt_config.json)
pch out (dBm): -9.00 reference pch out (dBm): -9.00
actual pch out (dBm): -9.00
Edfa Edfa_preamp_roadm_Linköping_from_fiber (Norrköping → Linköping) Edfa Edfa_preamp_roadm_Linköping_from_fiber (Norrköping → Linköping)
type_variety: openroadm_mw_mw_preamp_worstcase_ver5 type_variety: openroadm_mw_mw_preamp_worstcase_ver5
effective gain(dB): 11.00 effective gain(dB): 11.00
@@ -109,10 +119,12 @@ Edfa Edfa_preamp_roadm_Linköping_from_fiber (Norrköping → Linköping)
Delta_P (dB): 0.00 Delta_P (dB): 0.00
target pch (dBm): 2.00 target pch (dBm): 2.00
effective pch (dBm): 2.00 effective pch (dBm): 2.00
actual pch out (dBm): 2.01
output VOA (dB): 0.00 output VOA (dB): 0.00
Roadm roadm_Linköping Roadm roadm_Linköping
effective loss (dB): 22.00 effective loss (dB): 22.00
pch out (dBm): -20.00 reference pch out (dBm): -20.00
actual pch out (dBm): -20.00
Edfa Edfa_booster_roadm_Linköping_to_fiber (Linköping → Jönköping) Edfa Edfa_booster_roadm_Linköping_to_fiber (Linköping → Jönköping)
type_variety: openroadm_mw_mw_booster type_variety: openroadm_mw_mw_booster
effective gain(dB): 22.00 effective gain(dB): 22.00
@@ -125,6 +137,7 @@ Edfa Edfa_booster_roadm_Linköping_to_fiber (Linköping → Jönköping)
Delta_P (dB): 0.00 Delta_P (dB): 0.00
target pch (dBm): 2.00 target pch (dBm): 2.00
effective pch (dBm): 2.00 effective pch (dBm): 2.00
actual pch out (dBm): 2.00
output VOA (dB): 0.00 output VOA (dB): 0.00
Fiber fiber (Linköping → Jönköping) Fiber fiber (Linköping → Jönköping)
type_variety: SSMF type_variety: SSMF
@@ -133,7 +146,8 @@ Fiber fiber (Linköping → Jönköping)
total loss (dB): 26.80 total loss (dB): 26.80
(includes conn loss (dB) in: 0.00 out: 0.00) (includes conn loss (dB) in: 0.00 out: 0.00)
(conn loss out includes EOL margin defined in eqpt_config.json) (conn loss out includes EOL margin defined in eqpt_config.json)
pch out (dBm): -24.80 reference pch out (dBm): -24.80
actual pch out (dBm): -24.79
Edfa Edfa_preamp_roadm_Jönköping_from_fiber (Linköping → Jönköping) Edfa Edfa_preamp_roadm_Jönköping_from_fiber (Linköping → Jönköping)
type_variety: openroadm_mw_mw_preamp_worstcase_ver5 type_variety: openroadm_mw_mw_preamp_worstcase_ver5
effective gain(dB): 26.80 effective gain(dB): 26.80
@@ -146,10 +160,12 @@ Edfa Edfa_preamp_roadm_Jönköping_from_fiber (Linköping → Jönköping)
Delta_P (dB): 0.00 Delta_P (dB): 0.00
target pch (dBm): 2.00 target pch (dBm): 2.00
effective pch (dBm): 2.00 effective pch (dBm): 2.00
actual pch out (dBm): 2.04
output VOA (dB): 0.00 output VOA (dB): 0.00
Roadm roadm_Jönköping Roadm roadm_Jönköping
effective loss (dB): 22.00 effective loss (dB): 22.00
pch out (dBm): -20.00 reference pch out (dBm): -20.00
actual pch out (dBm): -20.00
Edfa Edfa_booster_roadm_Jönköping_to_fiber (Jönköping → Borås) Edfa Edfa_booster_roadm_Jönköping_to_fiber (Jönköping → Borås)
type_variety: openroadm_mw_mw_booster type_variety: openroadm_mw_mw_booster
effective gain(dB): 22.00 effective gain(dB): 22.00
@@ -162,6 +178,7 @@ Edfa Edfa_booster_roadm_Jönköping_to_fiber (Jönköping → Borås)
Delta_P (dB): 0.00 Delta_P (dB): 0.00
target pch (dBm): 2.00 target pch (dBm): 2.00
effective pch (dBm): 2.00 effective pch (dBm): 2.00
actual pch out (dBm): 2.00
output VOA (dB): 0.00 output VOA (dB): 0.00
Fiber fiber (Jönköping → Borås) Fiber fiber (Jönköping → Borås)
type_variety: SSMF type_variety: SSMF
@@ -170,7 +187,8 @@ Fiber fiber (Jönköping → Borås)
total loss (dB): 17.82 total loss (dB): 17.82
(includes conn loss (dB) in: 0.00 out: 0.00) (includes conn loss (dB) in: 0.00 out: 0.00)
(conn loss out includes EOL margin defined in eqpt_config.json) (conn loss out includes EOL margin defined in eqpt_config.json)
pch out (dBm): -15.82 reference pch out (dBm): -15.82
actual pch out (dBm): -15.81
Edfa Edfa_preamp_roadm_Borås_from_fiber (Jönköping → Borås) Edfa Edfa_preamp_roadm_Borås_from_fiber (Jönköping → Borås)
type_variety: openroadm_mw_mw_preamp_worstcase_ver5 type_variety: openroadm_mw_mw_preamp_worstcase_ver5
effective gain(dB): 17.82 effective gain(dB): 17.82
@@ -183,10 +201,12 @@ Edfa Edfa_preamp_roadm_Borås_from_fiber (Jönköping → Borås)
Delta_P (dB): 0.00 Delta_P (dB): 0.00
target pch (dBm): 2.00 target pch (dBm): 2.00
effective pch (dBm): 2.00 effective pch (dBm): 2.00
actual pch out (dBm): 2.01
output VOA (dB): 0.00 output VOA (dB): 0.00
Roadm roadm_Borås Roadm roadm_Borås
effective loss (dB): 22.00 effective loss (dB): 22.00
pch out (dBm): -20.00 reference pch out (dBm): -20.00
actual pch out (dBm): -20.00
Edfa Edfa_booster_roadm_Borås_to_fiber (Borås → Gothenburg) Edfa Edfa_booster_roadm_Borås_to_fiber (Borås → Gothenburg)
type_variety: openroadm_mw_mw_booster type_variety: openroadm_mw_mw_booster
effective gain(dB): 22.00 effective gain(dB): 22.00
@@ -199,6 +219,7 @@ Edfa Edfa_booster_roadm_Borås_to_fiber (Borås → Gothenburg)
Delta_P (dB): 0.00 Delta_P (dB): 0.00
target pch (dBm): 2.00 target pch (dBm): 2.00
effective pch (dBm): 2.00 effective pch (dBm): 2.00
actual pch out (dBm): 2.00
output VOA (dB): 0.00 output VOA (dB): 0.00
Fiber fiber (Borås → Gothenburg) Fiber fiber (Borås → Gothenburg)
type_variety: SSMF type_variety: SSMF
@@ -207,7 +228,8 @@ Fiber fiber (Borås → Gothenburg)
total loss (dB): 13.53 total loss (dB): 13.53
(includes conn loss (dB) in: 0.00 out: 0.00) (includes conn loss (dB) in: 0.00 out: 0.00)
(conn loss out includes EOL margin defined in eqpt_config.json) (conn loss out includes EOL margin defined in eqpt_config.json)
pch out (dBm): -11.53 reference pch out (dBm): -11.53
actual pch out (dBm): -11.52
Edfa Edfa_preamp_roadm_Gothenburg_from_fiber (Borås → Gothenburg) Edfa Edfa_preamp_roadm_Gothenburg_from_fiber (Borås → Gothenburg)
type_variety: openroadm_mw_mw_preamp_worstcase_ver5 type_variety: openroadm_mw_mw_preamp_worstcase_ver5
effective gain(dB): 13.53 effective gain(dB): 13.53
@@ -220,21 +242,24 @@ Edfa Edfa_preamp_roadm_Gothenburg_from_fiber (Borås → Gothenburg)
Delta_P (dB): 0.00 Delta_P (dB): 0.00
target pch (dBm): 2.00 target pch (dBm): 2.00
effective pch (dBm): 2.00 effective pch (dBm): 2.00
actual pch out (dBm): 2.02
output VOA (dB): 0.00 output VOA (dB): 0.00
Roadm roadm_Gothenburg Roadm roadm_Gothenburg
effective loss (dB): 22.00 effective loss (dB): 22.00
pch out (dBm): -20.00 reference pch out (dBm): -20.00
actual pch out (dBm): -20.00
Transceiver trx_Gothenburg Transceiver trx_Gothenburg
GSNR (0.1nm, dB): 19.27 GSNR (0.1nm, dB): 19.25
GSNR (signal bw, dB): 15.24 GSNR (signal bw, dB): 15.23
OSNR ASE (0.1nm, dB): 21.84 OSNR ASE (0.1nm, dB): 21.84
OSNR ASE (signal bw, dB): 17.82 OSNR ASE (signal bw, dB): 17.82
CD (ps/nm): 8350.42 CD (ps/nm): 8350.42
PMD (ps): 7.99 PMD (ps): 7.99
PDL (dB): 3.74 PDL (dB): 3.74
Latency (ms): 2.45
Transmission result for input power = 2.00 dBm: Transmission result for input power = 2.00 dBm:
Final GSNR (0.1 nm): 19.27 dB Final GSNR (0.1 nm): 19.25 dB
(No source node specified: picked trx_Stockholm) (No source node specified: picked trx_Stockholm)

View File

@@ -106,48 +106,13 @@
] ]
Computing all paths with constraints Computing all paths with constraints
Propagating on selected path Propagating on selected path
request 0
Computing path from trx Lorient_KMA to trx Vannes_KBE
with path constraint: ['trx Lorient_KMA', 'trx Vannes_KBE']
Computed path (roadms):['roadm Lorient_KMA', 'roadm Vannes_KBE']
request 1
Computing path from trx Brest_KLA to trx Vannes_KBE
with path constraint: ['trx Brest_KLA', 'roadm Brest_KLA', 'roadm Lannion_CAS', 'roadm Lorient_KMA', 'roadm Vannes_KBE', 'trx Vannes_KBE']
Computed path (roadms):['roadm Brest_KLA', 'roadm Lannion_CAS', 'roadm Lorient_KMA', 'roadm Vannes_KBE']
request 3
Computing path from trx Lannion_CAS to trx Rennes_STA
with path constraint: ['trx Lannion_CAS', 'trx Rennes_STA']
Computed path (roadms):['roadm Lannion_CAS', 'roadm Rennes_STA']
request 4
Computing path from trx Rennes_STA to trx Lannion_CAS
with path constraint: ['trx Rennes_STA', 'trx Lannion_CAS']
Computed path (roadms):['roadm Rennes_STA', 'roadm Vannes_KBE', 'roadm Lorient_KMA', 'roadm Lannion_CAS']
request 5
Computing path from trx Rennes_STA to trx Lannion_CAS
with path constraint: ['trx Rennes_STA', 'trx Lannion_CAS']
Computed path (roadms):['roadm Rennes_STA', 'roadm Lannion_CAS']
request 7 | 6
Computing path from trx Lannion_CAS to trx Lorient_KMA
with path constraint: ['trx Lannion_CAS', 'trx Lorient_KMA']
Computed path (roadms):['roadm Lannion_CAS', 'roadm Lorient_KMA']
request 7b
Computing path from trx Lannion_CAS to trx Lorient_KMA
with path constraint: ['trx Lannion_CAS', 'trx Lorient_KMA']
Computed path (roadms):['roadm Lannion_CAS', 'roadm Lorient_KMA']
Result summary Result summary
req id demand GSNR@bandwidth A-Z (Z-A) GSNR@0.1nm A-Z (Z-A) Receiver minOSNR mode Gbit/s nb of tsp pairs N,M or blocking reason req id demand GSNR@bandwidth A-Z (Z-A) GSNR@0.1nm A-Z (Z-A) Receiver minOSNR mode Gbit/s nb of tsp pairs N,M or blocking reason
0 trx Lorient_KMA to trx Vannes_KBE : 24.83 28.92 14 mode 1 100.0 1 (-284,4) 0 trx Lorient_KMA to trx Vannes_KBE : 24.83 28.92 14 mode 1 100.0 1 ([-284],[4])
1 trx Brest_KLA to trx Vannes_KBE : 17.75 21.83 14 mode 1 200.0 2 (-272,8) 1 trx Brest_KLA to trx Vannes_KBE : 17.74 21.82 14 mode 1 200.0 2 ([-272],[8])
3 trx Lannion_CAS to trx Rennes_STA : 22.21 26.29 13 mode 1 60.0 1 (-284,4) 3 trx Lannion_CAS to trx Rennes_STA : 22.19 26.28 13 mode 1 60.0 1 ([-284],[4])
4 trx Rennes_STA to trx Lannion_CAS : 16.07 23.29 17 mode 2 150.0 1 (-258,6) 4 trx Rennes_STA to trx Lannion_CAS : 16.06 23.29 17 mode 2 150.0 1 ([-258],[6])
5 trx Rennes_STA to trx Lannion_CAS : 20.31 27.54 17 mode 2 20.0 1 (-274,6) 5 trx Rennes_STA to trx Lannion_CAS : 20.3 27.53 17 mode 2 20.0 1 ([-274],[6])
7 | 6 trx Lannion_CAS to trx Lorient_KMA : 19.52 23.61 14 mode 1 700.0 7 (-224,28) 7 | 6 trx Lannion_CAS to trx Lorient_KMA : 19.52 23.61 14 mode 1 700.0 7 ([-224],[28])
7b trx Lannion_CAS to trx Lorient_KMA : 19.61 23.69 14 mode 1 400.0 4 (-172,24) 7b trx Lannion_CAS to trx Lorient_KMA : 19.61 23.69 14 mode 1 400.0 4 ([-172],[24])
Result summary shows mean GSNR and OSNR (average over all channels) Result summary shows mean GSNR and OSNR (average over all channels)

View File

@@ -0,0 +1,24 @@
List of disjunctions
[]
Aggregating similar requests
The following services have been requested:
[PathRequest 0
source: trx Abilene
destination: trx Albany
trx type: Voyager
trx mode: mode 3
baud_rate: 44.0 Gbaud
bit_rate: 300.0 Gb/s
spacing: 62.50000000000001 GHz
power: 0.0 dBm
nb channels: 76
path_bandwidth: 100.0 Gbit/s
nodes-list: []
loose-list: []
]
Computing all paths with constraints
Propagating on selected path
Result summary
req id demand GSNR@bandwidth A-Z (Z-A) GSNR@0.1nm A-Z (Z-A) Receiver minOSNR mode Gbit/s nb of tsp pairs N,M or blocking reason
0 trx Abilene to trx Albany : 9.04 14.5 - mode 3 100.0 - MODE_NOT_FEASIBLE
Result summary shows mean GSNR and OSNR (average over all channels)

View File

@@ -0,0 +1,102 @@
User input for spectrum used for propagation instead of SI
There are 76 channels propagating
Power mode is set to True
=> it can be modified in eqpt_config.json - Span
There are 3 fiber spans over 130 km between trx Lannion_CAS and trx Lorient_KMA
Now propagating between trx Lannion_CAS and trx Lorient_KMA:
Propagating with input power = 0.00 dBm:
Transceiver trx Lannion_CAS
GSNR (0.1nm, dB): 40.00
GSNR (signal bw, dB): 35.92
OSNR ASE (0.1nm, dB): 40.00
OSNR ASE (signal bw, dB): 35.92
CD (ps/nm): 0.00
PMD (ps): 0.00
PDL (dB): 0.00
Latency (ms): 0.00
Roadm roadm Lannion_CAS
effective loss (dB): 20.00
reference pch out (dBm): -20.00
actual pch out (dBm): -20.00
Edfa east edfa in Lannion_CAS to Corlay
type_variety: std_medium_gain
effective gain(dB): 21.00
(before att_in and before output VOA)
noise figure (dB): 6.36
(including att_in)
pad att_in (dB): 0.00
Power In (dBm): -1.19
Power Out (dBm): 19.82
Delta_P (dB): 1.00
target pch (dBm): 1.00
effective pch (dBm): 1.00
actual pch out (dBm): 1.01
output VOA (dB): 0.00
Fiber fiber (Lannion_CAS → Corlay)-F061
type_variety: SSMF
length (km): 20.00
pad att_in (dB): 0.00
total loss (dB): 4.00
(includes conn loss (dB) in: 0.00 out: 0.00)
(conn loss out includes EOL margin defined in eqpt_config.json)
reference pch out (dBm): -3.00
actual pch out (dBm): -2.99
Fused west fused spans in Corlay
loss (dB): 1.00
Fiber fiber (Corlay → Loudeac)-F010
type_variety: SSMF
length (km): 50.00
pad att_in (dB): 0.00
total loss (dB): 10.00
(includes conn loss (dB) in: 0.00 out: 0.00)
(conn loss out includes EOL margin defined in eqpt_config.json)
reference pch out (dBm): -14.00
actual pch out (dBm): -13.99
Fused west fused spans in Loudeac
loss (dB): 1.00
Fiber fiber (Loudeac → Lorient_KMA)-F054
type_variety: SSMF
length (km): 60.00
pad att_in (dB): 0.00
total loss (dB): 12.00
(includes conn loss (dB) in: 0.00 out: 0.00)
(conn loss out includes EOL margin defined in eqpt_config.json)
reference pch out (dBm): -27.00
actual pch out (dBm): -26.99
Edfa west edfa in Lorient_KMA to Loudeac
type_variety: std_high_gain
effective gain(dB): 28.00
(before att_in and before output VOA)
noise figure (dB): 5.92
(including att_in)
pad att_in (dB): 0.00
Power In (dBm): -8.18
Power Out (dBm): 19.85
Delta_P (dB): 1.00
target pch (dBm): 1.00
effective pch (dBm): 1.00
actual pch out (dBm): 1.05
output VOA (dB): 0.00
Roadm roadm Lorient_KMA
effective loss (dB): 21.00
reference pch out (dBm): -20.00
actual pch out (dBm): -20.00
Transceiver trx Lorient_KMA
GSNR (0.1nm, dB): 23.61
GSNR (signal bw, dB): 19.53
OSNR ASE (0.1nm, dB): 23.89
OSNR ASE (signal bw, dB): 19.81
CD (ps/nm): 2171.00
PMD (ps): 0.46
PDL (dB): 0.00
Latency (ms): 0.64
Transmission result for input power = 0.00 dBm:
Final GSNR (0.1 nm): 23.61 dB
(No source node specified: picked trx Lannion_CAS)
(No destination node specified: picked trx Lorient_KMA)

View File

@@ -0,0 +1,165 @@
User input for spectrum used for propagation instead of SI
There are 60 channels propagating
Power mode is set to True
=> it can be modified in eqpt_config.json - Span
There are 3 fiber spans over 130 km between trx Lannion_CAS and trx Lorient_KMA
Now propagating between trx Lannion_CAS and trx Lorient_KMA:
Propagating with input power = 0.00 dBm:
Transceiver trx Lannion_CAS
GSNR (0.1nm, dB): mode_1: 40.00, mode_2: 40.00
GSNR (signal bw, dB): mode_1: 35.92, mode_2: 32.91
OSNR ASE (0.1nm, dB): mode_1: 40.00, mode_2: 40.00
OSNR ASE (signal bw, dB): mode_1: 35.92, mode_2: 32.91
CD (ps/nm): 0.00
PMD (ps): 0.00
PDL (dB): 0.00
Latency (ms): 0.00
Roadm roadm Lannion_CAS
effective loss (dB): 20.00
reference pch out (dBm): -20.00
actual pch out (dBm): mode_1: -20.00, mode_2: -20.00
Edfa east edfa in Lannion_CAS to Corlay
type_variety: std_medium_gain
effective gain(dB): 21.00
(before att_in and before output VOA)
noise figure (dB): 6.36
(including att_in)
pad att_in (dB): 0.00
Power In (dBm): -2.22
Power Out (dBm): 18.79
Delta_P (dB): 1.00
target pch (dBm): 1.00
effective pch (dBm): 1.00
actual pch out (dBm): mode_1: 1.01, mode_2: 1.02
output VOA (dB): 0.00
Fiber fiber (Lannion_CAS → Corlay)-F061
type_variety: SSMF
length (km): 20.00
pad att_in (dB): 0.00
total loss (dB): 4.00
(includes conn loss (dB) in: 0.00 out: 0.00)
(conn loss out includes EOL margin defined in eqpt_config.json)
reference pch out (dBm): -3.00
actual pch out (dBm): mode_1: -2.99, mode_2: -2.98
Fused west fused spans in Corlay
loss (dB): 1.00
Fiber fiber (Corlay → Loudeac)-F010
type_variety: SSMF
length (km): 50.00
pad att_in (dB): 0.00
total loss (dB): 10.00
(includes conn loss (dB) in: 0.00 out: 0.00)
(conn loss out includes EOL margin defined in eqpt_config.json)
reference pch out (dBm): -14.00
actual pch out (dBm): mode_1: -13.99, mode_2: -13.98
Fused west fused spans in Loudeac
loss (dB): 1.00
Fiber fiber (Loudeac → Lorient_KMA)-F054
type_variety: SSMF
length (km): 60.00
pad att_in (dB): 0.00
total loss (dB): 12.00
(includes conn loss (dB) in: 0.00 out: 0.00)
(conn loss out includes EOL margin defined in eqpt_config.json)
reference pch out (dBm): -27.00
actual pch out (dBm): mode_1: -26.99, mode_2: -26.98
Edfa west edfa in Lorient_KMA to Loudeac
type_variety: std_high_gain
effective gain(dB): 28.00
(before att_in and before output VOA)
noise figure (dB): 5.92
(including att_in)
pad att_in (dB): 0.00
Power In (dBm): -9.21
Power Out (dBm): 18.84
Delta_P (dB): 1.00
target pch (dBm): 1.00
effective pch (dBm): 1.00
actual pch out (dBm): mode_1: 1.04, mode_2: 1.09
output VOA (dB): 0.00
Roadm roadm Lorient_KMA
effective loss (dB): 21.00
reference pch out (dBm): -20.00
actual pch out (dBm): mode_1: -20.00, mode_2: -20.00
Transceiver trx Lorient_KMA
GSNR (0.1nm, dB): mode_1: 23.66, mode_2: 23.81
GSNR (signal bw, dB): mode_1: 19.58, mode_2: 16.72
OSNR ASE (0.1nm, dB): mode_1: 23.91, mode_2: 23.87
OSNR ASE (signal bw, dB): mode_1: 19.83, mode_2: 16.78
CD (ps/nm): 2171.00
PMD (ps): 0.46
PDL (dB): 0.00
Latency (ms): 0.64
Transmission result for input power = 0.00 dBm:
Final GSNR (0.1 nm): 23.72 dB
The GSNR per channel at the end of the line is:
Ch. # Channel frequency (THz) Channel power (dBm) OSNR ASE (signal bw, dB) SNR NLI (signal bw, dB) GSNR (signal bw, dB)
1 191.40000 -20.04 19.85 33.52 19.66
2 191.45000 -20.04 19.85 32.93 19.64
3 191.50000 -20.04 19.84 32.67 19.62
4 191.55000 -20.04 19.84 32.50 19.61
5 191.60000 -20.04 19.84 32.39 19.61
6 191.65000 -20.04 19.84 32.30 19.60
7 191.70000 -20.04 19.84 32.22 19.60
8 191.75000 -20.04 19.84 32.16 19.59
9 191.80000 -20.04 19.84 32.11 19.59
10 191.85000 -20.04 19.84 32.07 19.59
11 191.90000 -20.04 19.84 32.04 19.58
12 191.95000 -20.04 19.84 32.00 19.58
13 192.00000 -20.04 19.83 31.98 19.58
14 192.05000 -20.04 19.83 31.95 19.57
15 192.10000 -20.04 19.83 31.93 19.57
16 192.15000 -20.04 19.83 31.91 19.57
17 192.20000 -20.04 19.83 31.90 19.57
18 192.25000 -20.04 19.83 31.88 19.57
19 192.30000 -20.04 19.83 31.87 19.56
20 192.35000 -20.04 19.83 31.87 19.56
21 192.40000 -20.04 19.83 31.86 19.56
22 192.45000 -20.04 19.82 31.86 19.56
23 192.50000 -20.04 19.82 31.86 19.56
24 192.55000 -20.04 19.82 31.86 19.56
25 192.60000 -20.04 19.82 31.87 19.56
26 192.65000 -20.04 19.82 31.88 19.56
27 192.70000 -20.04 19.82 31.89 19.56
28 192.75000 -20.04 19.82 31.91 19.56
29 192.80000 -20.04 19.82 31.93 19.56
30 192.85000 -20.04 19.82 31.97 19.56
31 192.90000 -20.04 19.82 32.01 19.56
32 192.95000 -20.04 19.81 32.07 19.56
33 193.00000 -20.04 19.81 32.16 19.57
34 193.05000 -20.04 19.81 32.31 19.57
35 193.10000 -20.04 19.81 32.65 19.59
36 193.16250 -20.09 16.80 33.73 16.71
37 193.23750 -20.09 16.80 34.22 16.72
38 193.31250 -20.09 16.80 34.47 16.72
39 193.38750 -20.09 16.79 34.63 16.72
40 193.46250 -20.09 16.79 34.75 16.72
41 193.53750 -20.09 16.79 34.84 16.72
42 193.61250 -20.09 16.79 34.92 16.72
43 193.68750 -20.09 16.79 34.99 16.72
44 193.76250 -20.09 16.79 35.04 16.72
45 193.83750 -20.09 16.78 35.10 16.72
46 193.91250 -20.09 16.78 35.15 16.72
47 193.98750 -20.09 16.78 35.19 16.72
48 194.06250 -20.09 16.78 35.24 16.72
49 194.13750 -20.09 16.78 35.28 16.72
50 194.21250 -20.09 16.78 35.33 16.72
51 194.28750 -20.09 16.78 35.37 16.72
52 194.36250 -20.09 16.77 35.42 16.72
53 194.43750 -20.09 16.77 35.47 16.71
54 194.51250 -20.09 16.77 35.53 16.71
55 194.58750 -20.09 16.77 35.59 16.71
56 194.66250 -20.09 16.77 35.67 16.71
57 194.73750 -20.09 16.77 35.77 16.71
58 194.81250 -20.09 16.76 35.90 16.71
59 194.88750 -20.09 16.76 36.11 16.71
60 194.96250 -20.09 16.76 36.58 16.72
(No source node specified: picked trx Lannion_CAS)
(No destination node specified: picked trx Lorient_KMA)

View File

@@ -15,6 +15,7 @@ Transceiver Site_A
CD (ps/nm): 0.00 CD (ps/nm): 0.00
PMD (ps): 0.00 PMD (ps): 0.00
PDL (dB): 0.00 PDL (dB): 0.00
Latency (ms): 0.00
Fiber Span1 Fiber Span1
type_variety: SSMF type_variety: SSMF
length (km): 80.00 length (km): 80.00
@@ -22,7 +23,8 @@ Fiber Span1
total loss (dB): 17.00 total loss (dB): 17.00
(includes conn loss (dB) in: 0.50 out: 0.50) (includes conn loss (dB) in: 0.50 out: 0.50)
(conn loss out includes EOL margin defined in eqpt_config.json) (conn loss out includes EOL margin defined in eqpt_config.json)
pch out (dBm): -17.00 reference pch out (dBm): -17.00
actual pch out (dBm): -17.00
Edfa Edfa1 Edfa Edfa1
type_variety: std_low_gain type_variety: std_low_gain
effective gain(dB): 15.00 effective gain(dB): 15.00
@@ -35,18 +37,20 @@ Edfa Edfa1
Delta_P (dB): -2.00 Delta_P (dB): -2.00
target pch (dBm): -2.00 target pch (dBm): -2.00
effective pch (dBm): -2.00 effective pch (dBm): -2.00
actual pch out (dBm): -1.99
output VOA (dB): 0.00 output VOA (dB): 0.00
Transceiver Site_B Transceiver Site_B
GSNR (0.1nm, dB): 31.17 GSNR (0.1nm, dB): 31.18
GSNR (signal bw, dB): 27.09 GSNR (signal bw, dB): 27.10
OSNR ASE (0.1nm, dB): 33.30 OSNR ASE (0.1nm, dB): 33.30
OSNR ASE (signal bw, dB): 29.21 OSNR ASE (signal bw, dB): 29.21
CD (ps/nm): 1336.00 CD (ps/nm): 1336.00
PMD (ps): 0.36 PMD (ps): 0.36
PDL (dB): 0.00 PDL (dB): 0.00
Latency (ms): 0.39
Transmission result for input power = 0.00 dBm: Transmission result for input power = 0.00 dBm:
Final GSNR (0.1 nm): 31.17 dB Final GSNR (0.1 nm): 31.18 dB
(No source node specified: picked Site_A) (No source node specified: picked Site_A)

View File

@@ -15,6 +15,7 @@ Transceiver Site_A
CD (ps/nm): 0.00 CD (ps/nm): 0.00
PMD (ps): 0.00 PMD (ps): 0.00
PDL (dB): 0.00 PDL (dB): 0.00
Latency (ms): 0.00
RamanFiber Span1 RamanFiber Span1
type_variety: SSMF type_variety: SSMF
length (km): 80.00 length (km): 80.00
@@ -22,112 +23,115 @@ RamanFiber Span1
total loss (dB): 17.00 total loss (dB): 17.00
(includes conn loss (dB) in: 0.50 out: 0.50) (includes conn loss (dB) in: 0.50 out: 0.50)
(conn loss out includes EOL margin defined in eqpt_config.json) (conn loss out includes EOL margin defined in eqpt_config.json)
pch out (dBm): -7.71 reference pch out (dBm): -7.20
actual pch out (dBm): -7.47
Fused Fused1 Fused Fused1
loss (dB): 0.00 loss (dB): 0.00
Edfa Edfa1 Edfa Edfa1
type_variety: std_low_gain type_variety: std_low_gain
effective gain(dB): 5.71 effective gain(dB): 5.20
(before att_in and before output VOA) (before att_in and before output VOA)
noise figure (dB): 13.29 noise figure (dB): 13.80
(including att_in) (including att_in)
pad att_in (dB): 2.29 pad att_in (dB): 2.80
Power In (dBm): 11.11 Power In (dBm): 11.61
Power Out (dBm): 16.82 Power Out (dBm): 16.81
Delta_P (dB): -2.00 Delta_P (dB): -2.00
target pch (dBm): -2.00 target pch (dBm): -2.00
effective pch (dBm): -2.00 effective pch (dBm): -2.00
actual pch out (dBm): -2.26
output VOA (dB): 0.00 output VOA (dB): 0.00
Transceiver Site_B Transceiver Site_B
GSNR (0.1nm, dB): 31.44 GSNR (0.1nm, dB): 31.42
GSNR (signal bw, dB): 27.36 GSNR (signal bw, dB): 27.34
OSNR ASE (0.1nm, dB): 34.22 OSNR ASE (0.1nm, dB): 34.21
OSNR ASE (signal bw, dB): 30.14 OSNR ASE (signal bw, dB): 30.13
CD (ps/nm): 1336.00 CD (ps/nm): 1336.00
PMD (ps): 0.36 PMD (ps): 0.36
PDL (dB): 0.00 PDL (dB): 0.00
Latency (ms): 0.39
Transmission result for input power = 0.00 dBm: Transmission result for input power = 0.00 dBm:
Final GSNR (0.1 nm): 31.44 dB Final GSNR (0.1 nm): 31.42 dB
The GSNR per channel at the end of the line is: The GSNR per channel at the end of the line is:
Ch. # Channel frequency (THz) Channel power (dBm) OSNR ASE (signal bw, dB) SNR NLI (signal bw, dB) GSNR (signal bw, dB) Ch. # Channel frequency (THz) Channel power (dBm) OSNR ASE (signal bw, dB) SNR NLI (signal bw, dB) GSNR (signal bw, dB)
1 191.35 0.18 31.61 31.43 28.51 1 191.35000 0.22 31.64 31.55 28.58
2 191.40 0.14 31.59 31.34 28.45 2 191.40000 0.18 31.62 31.46 28.53
3 191.45 0.11 31.57 31.26 28.40 3 191.45000 0.15 31.60 31.37 28.47
4 191.50 0.07 31.55 31.17 28.35 4 191.50000 0.11 31.58 31.28 28.42
5 191.55 0.02 31.52 31.09 28.29 5 191.55000 0.05 31.54 31.20 28.36
6 191.60 -0.04 31.49 31.02 28.24 6 191.60000 -0.01 31.51 31.11 28.30
7 191.65 -0.10 31.46 30.94 28.18 7 191.65000 -0.07 31.48 31.03 28.24
8 191.70 -0.16 31.43 30.86 28.13 8 191.70000 -0.12 31.45 30.95 28.18
9 191.75 -0.21 31.40 30.79 28.07 9 191.75000 -0.18 31.42 30.87 28.13
10 191.80 -0.28 31.36 30.71 28.02 10 191.80000 -0.25 31.38 30.79 28.07
11 191.85 -0.34 31.33 30.64 27.96 11 191.85000 -0.31 31.35 30.72 28.01
12 191.90 -0.40 31.29 30.57 27.91 12 191.90000 -0.38 31.31 30.64 27.95
13 191.95 -0.47 31.26 30.50 27.85 13 191.95000 -0.44 31.27 30.57 27.90
14 192.00 -0.53 31.22 30.43 27.80 14 192.00000 -0.51 31.24 30.50 27.84
15 192.05 -0.60 31.18 30.36 27.74 15 192.05000 -0.58 31.20 30.42 27.78
16 192.10 -0.66 31.15 30.30 27.69 16 192.10000 -0.64 31.16 30.35 27.73
17 192.15 -0.73 31.11 30.23 27.64 17 192.15000 -0.71 31.12 30.29 27.67
18 192.20 -0.79 31.07 30.16 27.58 18 192.20000 -0.78 31.08 30.22 27.62
19 192.25 -0.86 31.04 30.17 27.57 19 192.25000 -0.85 31.04 30.22 27.60
20 192.30 -0.94 30.99 30.18 27.56 20 192.30000 -0.93 31.00 30.22 27.58
21 192.35 -1.01 30.95 30.19 27.54 21 192.35000 -1.00 30.96 30.23 27.57
22 192.40 -1.08 30.91 30.20 27.53 22 192.40000 -1.08 30.91 30.23 27.55
23 192.45 -1.16 30.86 30.20 27.51 23 192.45000 -1.16 30.87 30.23 27.53
24 192.50 -1.23 30.82 30.21 27.49 24 192.50000 -1.23 30.82 30.24 27.51
25 192.55 -1.30 30.78 30.22 27.48 25 192.55000 -1.30 30.78 30.24 27.49
26 192.60 -1.37 30.74 30.23 27.46 26 192.60000 -1.37 30.74 30.24 27.47
27 192.65 -1.44 30.70 30.23 27.45 27 192.65000 -1.44 30.70 30.25 27.46
28 192.70 -1.51 30.65 30.24 27.43 28 192.70000 -1.52 30.65 30.25 27.44
29 192.75 -1.58 30.61 30.25 27.42 29 192.75000 -1.59 30.61 30.25 27.42
30 192.80 -1.65 30.57 30.26 27.40 30 192.80000 -1.66 30.57 30.26 27.40
31 192.85 -1.72 30.53 30.27 27.38 31 192.85000 -1.73 30.52 30.26 27.38
32 192.90 -1.79 30.48 30.27 27.37 32 192.90000 -1.80 30.48 30.26 27.36
33 192.95 -1.86 30.44 30.28 27.35 33 192.95000 -1.87 30.43 30.27 27.34
34 193.00 -1.93 30.40 30.29 27.33 34 193.00000 -1.94 30.39 30.27 27.32
35 193.05 -2.00 30.35 30.30 27.32 35 193.05000 -2.01 30.35 30.27 27.30
36 193.10 -2.07 30.31 30.30 27.30 36 193.10000 -2.08 30.30 30.28 27.28
37 193.15 -2.14 30.27 30.31 27.28 37 193.15000 -2.15 30.26 30.28 27.26
38 193.20 -2.20 30.22 30.33 27.27 38 193.20000 -2.22 30.22 30.29 27.24
39 193.25 -2.27 30.18 30.35 27.25 39 193.25000 -2.29 30.17 30.31 27.23
40 193.30 -2.34 30.14 30.37 27.24 40 193.30000 -2.36 30.13 30.32 27.21
41 193.35 -2.41 30.09 30.38 27.23 41 193.35000 -2.43 30.08 30.33 27.19
42 193.40 -2.48 30.05 30.40 27.21 42 193.40000 -2.50 30.04 30.35 27.18
43 193.45 -2.55 30.00 30.42 27.20 43 193.45000 -2.56 29.99 30.36 27.16
44 193.50 -2.61 29.96 30.44 27.18 44 193.50000 -2.63 29.95 30.37 27.14
45 193.55 -2.69 29.91 30.46 27.16 45 193.55000 -2.71 29.90 30.39 27.12
46 193.60 -2.76 29.86 30.47 27.15 46 193.60000 -2.78 29.85 30.40 27.11
47 193.65 -2.83 29.82 30.49 27.13 47 193.65000 -2.85 29.80 30.41 27.09
48 193.70 -2.90 29.77 30.51 27.11 48 193.70000 -2.93 29.75 30.43 27.07
49 193.75 -2.98 29.72 30.53 27.10 49 193.75000 -3.00 29.70 30.44 27.05
50 193.80 -3.05 29.67 30.55 27.08 50 193.80000 -3.07 29.65 30.45 27.02
51 193.85 -3.12 29.62 30.57 27.06 51 193.85000 -3.15 29.60 30.47 27.00
52 193.90 -3.19 29.58 30.58 27.04 52 193.90000 -3.22 29.55 30.48 26.98
53 193.95 -3.26 29.53 30.60 27.02 53 193.95000 -3.29 29.50 30.50 26.96
54 194.00 -3.33 29.48 30.62 27.00 54 194.00000 -3.37 29.45 30.51 26.94
55 194.05 -3.41 29.43 30.64 26.98 55 194.05000 -3.44 29.40 30.52 26.92
56 194.10 -3.48 29.38 30.66 26.96 56 194.10000 -3.52 29.35 30.54 26.89
57 194.15 -3.55 29.33 30.72 26.96 57 194.15000 -3.59 29.30 30.59 26.89
58 194.20 -3.63 29.28 30.78 26.95 58 194.20000 -3.66 29.25 30.64 26.88
59 194.25 -3.70 29.23 30.83 26.95 59 194.25000 -3.74 29.19 30.70 26.87
60 194.30 -3.77 29.18 30.89 26.94 60 194.30000 -3.81 29.14 30.75 26.86
61 194.35 -3.85 29.12 30.96 26.93 61 194.35000 -3.89 29.09 30.81 26.86
62 194.40 -3.92 29.07 31.02 26.93 62 194.40000 -3.96 29.04 30.87 26.85
63 194.45 -3.99 29.02 31.08 26.92 63 194.45000 -4.04 28.98 30.93 26.84
64 194.50 -4.06 28.97 31.14 26.91 64 194.50000 -4.11 28.93 30.98 26.83
65 194.55 -4.13 28.92 31.21 26.91 65 194.55000 -4.18 28.88 31.04 26.82
66 194.60 -4.19 28.88 31.27 26.90 66 194.60000 -4.25 28.83 31.10 26.81
67 194.65 -4.26 28.83 31.34 26.89 67 194.65000 -4.31 28.78 31.17 26.80
68 194.70 -4.33 28.78 31.41 26.89 68 194.70000 -4.38 28.74 31.23 26.79
69 194.75 -4.39 28.73 31.47 26.88 69 194.75000 -4.45 28.69 31.29 26.79
70 194.80 -4.46 28.68 31.54 26.87 70 194.80000 -4.51 28.64 31.35 26.78
71 194.85 -4.52 28.64 31.61 26.86 71 194.85000 -4.58 28.59 31.42 26.77
72 194.90 -4.59 28.59 31.68 26.86 72 194.90000 -4.65 28.54 31.48 26.76
73 194.95 -4.65 28.54 31.76 26.85 73 194.95000 -4.71 28.49 31.55 26.74
74 195.00 -4.72 28.49 31.83 26.84 74 195.00000 -4.78 28.44 31.62 26.73
75 195.05 -4.78 28.44 31.91 26.83 75 195.05000 -4.85 28.39 31.69 26.72
76 195.10 -4.85 28.39 31.91 26.79 76 195.10000 -4.91 28.34 31.69 26.69
(No source node specified: picked Site_A) (No source node specified: picked Site_A)

View File

@@ -0,0 +1,455 @@
There are 96 channels propagating
Power mode is set to True
=> it can be modified in eqpt_config.json - Span
There are 15 fiber spans over 1200 km between Site_A and Site_B
Now propagating between Site_A and Site_B:
Propagating with input power = 0.00 dBm:
Transceiver Site_A
GSNR (0.1nm, dB): 100.00
GSNR (signal bw, dB): 95.92
OSNR ASE (0.1nm, dB): 100.00
OSNR ASE (signal bw, dB): 95.92
CD (ps/nm): 0.00
PMD (ps): 0.00
PDL (dB): 0.00
Latency (ms): 0.00
Roadm roadm Site A
effective loss (dB): 20.00
reference pch out (dBm): -20.00
actual pch out (dBm): -20.00
Edfa booster A
type_variety: std_medium_gain
effective gain(dB): 20.00
(before att_in and before output VOA)
noise figure (dB): 6.58
(including att_in)
pad att_in (dB): 0.00
Power In (dBm): -0.18
Power Out (dBm): 19.83
Delta_P (dB): 0.00
target pch (dBm): 0.00
effective pch (dBm): 0.00
actual pch out (dBm): 0.01
output VOA (dB): 0.00
Fiber Span1
type_variety: SSMF
length (km): 80.00
pad att_in (dB): 0.00
total loss (dB): 16.00
(includes conn loss (dB) in: 0.00 out: 0.00)
(conn loss out includes EOL margin defined in eqpt_config.json)
reference pch out (dBm): -16.00
actual pch out (dBm): -15.99
Edfa Edfa1
type_variety: test
effective gain(dB): 16.00
(before att_in and before output VOA)
noise figure (dB): 8.86
(including att_in)
pad att_in (dB): 0.00
Power In (dBm): 3.84
Power Out (dBm): 19.84
Delta_P (dB): 0.00
target pch (dBm): 0.00
effective pch (dBm): 0.00
actual pch out (dBm): 0.02
output VOA (dB): 0.00
Fiber Span2
type_variety: SSMF
length (km): 80.00
pad att_in (dB): 0.00
total loss (dB): 16.00
(includes conn loss (dB) in: 0.00 out: 0.00)
(conn loss out includes EOL margin defined in eqpt_config.json)
reference pch out (dBm): -16.00
actual pch out (dBm): -15.98
Edfa Edfa2
type_variety: test_fixed_gain
effective gain(dB): 16.00
(before att_in and before output VOA)
noise figure (dB): 9.00
(including att_in)
pad att_in (dB): 4.00
Power In (dBm): 3.84
Power Out (dBm): 19.85
Delta_P (dB): 0.00
target pch (dBm): 0.00
effective pch (dBm): 0.00
actual pch out (dBm): 0.03
output VOA (dB): 0.00
Fiber Span3
type_variety: SSMF
length (km): 80.00
pad att_in (dB): 0.00
total loss (dB): 16.00
(includes conn loss (dB) in: 0.00 out: 0.00)
(conn loss out includes EOL margin defined in eqpt_config.json)
reference pch out (dBm): -16.00
actual pch out (dBm): -15.97
Edfa Edfa3
type_variety: test
effective gain(dB): 16.00
(before att_in and before output VOA)
noise figure (dB): 8.86
(including att_in)
pad att_in (dB): 0.00
Power In (dBm): 3.85
Power Out (dBm): 19.86
Delta_P (dB): 0.00
target pch (dBm): 0.00
effective pch (dBm): 0.00
actual pch out (dBm): 0.04
output VOA (dB): 0.00
Fiber Span4
type_variety: SSMF
length (km): 80.00
pad att_in (dB): 0.00
total loss (dB): 16.00
(includes conn loss (dB) in: 0.00 out: 0.00)
(conn loss out includes EOL margin defined in eqpt_config.json)
reference pch out (dBm): -16.00
actual pch out (dBm): -15.96
Edfa Edfa4
type_variety: test_fixed_gain
effective gain(dB): 16.00
(before att_in and before output VOA)
noise figure (dB): 9.00
(including att_in)
pad att_in (dB): 4.00
Power In (dBm): 3.86
Power Out (dBm): 19.87
Delta_P (dB): 0.00
target pch (dBm): 0.00
effective pch (dBm): 0.00
actual pch out (dBm): 0.05
output VOA (dB): 0.00
Fiber Span5
type_variety: SSMF
length (km): 80.00
pad att_in (dB): 0.00
total loss (dB): 16.00
(includes conn loss (dB) in: 0.00 out: 0.00)
(conn loss out includes EOL margin defined in eqpt_config.json)
reference pch out (dBm): -16.00
actual pch out (dBm): -15.95
Edfa Edfa5
type_variety: test
effective gain(dB): 16.00
(before att_in and before output VOA)
noise figure (dB): 8.86
(including att_in)
pad att_in (dB): 0.00
Power In (dBm): 3.87
Power Out (dBm): 19.88
Delta_P (dB): 0.00
target pch (dBm): 0.00
effective pch (dBm): 0.00
actual pch out (dBm): 0.06
output VOA (dB): 0.00
Roadm roadm Site C
effective loss (dB): 20.00
reference pch out (dBm): -20.00
actual pch out (dBm): -20.00
Edfa booster C
type_variety: std_medium_gain
effective gain(dB): 20.00
(before att_in and before output VOA)
noise figure (dB): 6.58
(including att_in)
pad att_in (dB): 0.00
Power In (dBm): -0.18
Power Out (dBm): 19.83
Delta_P (dB): 0.00
target pch (dBm): 0.00
effective pch (dBm): 0.00
actual pch out (dBm): 0.01
output VOA (dB): 0.00
Fiber Span6
type_variety: SSMF
length (km): 80.00
pad att_in (dB): 0.00
total loss (dB): 16.00
(includes conn loss (dB) in: 0.00 out: 0.00)
(conn loss out includes EOL margin defined in eqpt_config.json)
reference pch out (dBm): -16.00
actual pch out (dBm): -15.99
Edfa Edfa6
type_variety: test_fixed_gain
effective gain(dB): 16.00
(before att_in and before output VOA)
noise figure (dB): 9.00
(including att_in)
pad att_in (dB): 4.00
Power In (dBm): 3.84
Power Out (dBm): 19.84
Delta_P (dB): 0.00
target pch (dBm): 0.00
effective pch (dBm): 0.00
actual pch out (dBm): 0.02
output VOA (dB): 0.00
Fiber Span7
type_variety: SSMF
length (km): 80.00
pad att_in (dB): 0.00
total loss (dB): 16.00
(includes conn loss (dB) in: 0.00 out: 0.00)
(conn loss out includes EOL margin defined in eqpt_config.json)
reference pch out (dBm): -16.00
actual pch out (dBm): -15.98
Edfa Edfa7
type_variety: test
effective gain(dB): 16.00
(before att_in and before output VOA)
noise figure (dB): 8.86
(including att_in)
pad att_in (dB): 0.00
Power In (dBm): 3.84
Power Out (dBm): 19.85
Delta_P (dB): 0.00
target pch (dBm): 0.00
effective pch (dBm): 0.00
actual pch out (dBm): 0.03
output VOA (dB): 0.00
Fiber Span8
type_variety: SSMF
length (km): 80.00
pad att_in (dB): 0.00
total loss (dB): 16.00
(includes conn loss (dB) in: 0.00 out: 0.00)
(conn loss out includes EOL margin defined in eqpt_config.json)
reference pch out (dBm): -16.00
actual pch out (dBm): -15.97
Edfa Edfa8
type_variety: test_fixed_gain
effective gain(dB): 16.00
(before att_in and before output VOA)
noise figure (dB): 9.00
(including att_in)
pad att_in (dB): 4.00
Power In (dBm): 3.85
Power Out (dBm): 19.86
Delta_P (dB): 0.00
target pch (dBm): 0.00
effective pch (dBm): 0.00
actual pch out (dBm): 0.04
output VOA (dB): 0.00
Fiber Span9
type_variety: SSMF
length (km): 80.00
pad att_in (dB): 0.00
total loss (dB): 16.00
(includes conn loss (dB) in: 0.00 out: 0.00)
(conn loss out includes EOL margin defined in eqpt_config.json)
reference pch out (dBm): -16.00
actual pch out (dBm): -15.96
Edfa Edfa9
type_variety: test
effective gain(dB): 16.00
(before att_in and before output VOA)
noise figure (dB): 8.86
(including att_in)
pad att_in (dB): 0.00
Power In (dBm): 3.86
Power Out (dBm): 19.87
Delta_P (dB): 0.00
target pch (dBm): 0.00
effective pch (dBm): 0.00
actual pch out (dBm): 0.05
output VOA (dB): 0.00
Fiber Span10
type_variety: SSMF
length (km): 80.00
pad att_in (dB): 0.00
total loss (dB): 16.00
(includes conn loss (dB) in: 0.00 out: 0.00)
(conn loss out includes EOL margin defined in eqpt_config.json)
reference pch out (dBm): -16.00
actual pch out (dBm): -15.95
Edfa Edfa10
type_variety: test_fixed_gain
effective gain(dB): 16.00
(before att_in and before output VOA)
noise figure (dB): 9.00
(including att_in)
pad att_in (dB): 4.00
Power In (dBm): 3.87
Power Out (dBm): 19.88
Delta_P (dB): 0.00
target pch (dBm): 0.00
effective pch (dBm): 0.00
actual pch out (dBm): 0.06
output VOA (dB): 0.00
Roadm roadm Site D
effective loss (dB): 20.00
reference pch out (dBm): -20.00
actual pch out (dBm): -20.00
Edfa booster D
type_variety: std_medium_gain
effective gain(dB): 20.00
(before att_in and before output VOA)
noise figure (dB): 6.58
(including att_in)
pad att_in (dB): 0.00
Power In (dBm): -0.18
Power Out (dBm): 19.83
Delta_P (dB): 0.00
target pch (dBm): 0.00
effective pch (dBm): 0.00
actual pch out (dBm): 0.01
output VOA (dB): 0.00
Fiber Span11
type_variety: SSMF
length (km): 80.00
pad att_in (dB): 0.00
total loss (dB): 16.00
(includes conn loss (dB) in: 0.00 out: 0.00)
(conn loss out includes EOL margin defined in eqpt_config.json)
reference pch out (dBm): -16.00
actual pch out (dBm): -15.99
Edfa Edfa11
type_variety: test
effective gain(dB): 16.00
(before att_in and before output VOA)
noise figure (dB): 8.86
(including att_in)
pad att_in (dB): 0.00
Power In (dBm): 3.83
Power Out (dBm): 19.84
Delta_P (dB): 0.00
target pch (dBm): 0.00
effective pch (dBm): 0.00
actual pch out (dBm): 0.02
output VOA (dB): 0.00
Fiber Span12
type_variety: SSMF
length (km): 80.00
pad att_in (dB): 0.00
total loss (dB): 16.00
(includes conn loss (dB) in: 0.00 out: 0.00)
(conn loss out includes EOL margin defined in eqpt_config.json)
reference pch out (dBm): -16.00
actual pch out (dBm): -15.98
Edfa Edfa12
type_variety: test_fixed_gain
effective gain(dB): 16.00
(before att_in and before output VOA)
noise figure (dB): 9.00
(including att_in)
pad att_in (dB): 4.00
Power In (dBm): 3.84
Power Out (dBm): 19.85
Delta_P (dB): 0.00
target pch (dBm): 0.00
effective pch (dBm): 0.00
actual pch out (dBm): 0.03
output VOA (dB): 0.00
Roadm roadm Site E
effective loss (dB): 20.00
reference pch out (dBm): -20.00
actual pch out (dBm): -20.00
Edfa booster E
type_variety: std_medium_gain
effective gain(dB): 20.00
(before att_in and before output VOA)
noise figure (dB): 6.58
(including att_in)
pad att_in (dB): 0.00
Power In (dBm): -0.18
Power Out (dBm): 19.83
Delta_P (dB): 0.00
target pch (dBm): 0.00
effective pch (dBm): 0.00
actual pch out (dBm): 0.01
output VOA (dB): 0.00
Fiber Span13
type_variety: SSMF
length (km): 80.00
pad att_in (dB): 0.00
total loss (dB): 16.00
(includes conn loss (dB) in: 0.00 out: 0.00)
(conn loss out includes EOL margin defined in eqpt_config.json)
reference pch out (dBm): -16.00
actual pch out (dBm): -15.99
Edfa Edfa13
type_variety: test
effective gain(dB): 16.00
(before att_in and before output VOA)
noise figure (dB): 8.86
(including att_in)
pad att_in (dB): 0.00
Power In (dBm): 3.83
Power Out (dBm): 19.84
Delta_P (dB): 0.00
target pch (dBm): 0.00
effective pch (dBm): 0.00
actual pch out (dBm): 0.02
output VOA (dB): 0.00
Fiber Span14
type_variety: SSMF
length (km): 80.00
pad att_in (dB): 0.00
total loss (dB): 16.00
(includes conn loss (dB) in: 0.00 out: 0.00)
(conn loss out includes EOL margin defined in eqpt_config.json)
reference pch out (dBm): -16.00
actual pch out (dBm): -15.98
Edfa Edfa14
type_variety: test_fixed_gain
effective gain(dB): 16.00
(before att_in and before output VOA)
noise figure (dB): 9.00
(including att_in)
pad att_in (dB): 4.00
Power In (dBm): 3.84
Power Out (dBm): 19.85
Delta_P (dB): 0.00
target pch (dBm): 0.00
effective pch (dBm): 0.00
actual pch out (dBm): 0.03
output VOA (dB): 0.00
Fiber Span15
type_variety: SSMF
length (km): 80.00
pad att_in (dB): 0.00
total loss (dB): 16.00
(includes conn loss (dB) in: 0.00 out: 0.00)
(conn loss out includes EOL margin defined in eqpt_config.json)
reference pch out (dBm): -16.00
actual pch out (dBm): -15.97
Edfa Edfa15
type_variety: test
effective gain(dB): 16.00
(before att_in and before output VOA)
noise figure (dB): 8.86
(including att_in)
pad att_in (dB): 0.00
Power In (dBm): 3.85
Power Out (dBm): 19.86
Delta_P (dB): 0.00
target pch (dBm): 0.00
effective pch (dBm): 0.00
actual pch out (dBm): 0.04
output VOA (dB): 0.00
Roadm roadm Site B
effective loss (dB): 20.00
reference pch out (dBm): -20.00
actual pch out (dBm): -20.00
Transceiver Site_B
GSNR (0.1nm, dB): 17.84
GSNR (signal bw, dB): 13.76
OSNR ASE (0.1nm, dB): 19.70
OSNR ASE (signal bw, dB): 15.62
CD (ps/nm): 20040.00
PMD (ps): 1.39
PDL (dB): 0.00
Latency (ms): 5.88
Transmission result for input power = 0.00 dBm:
Final GSNR (0.1 nm): 17.84 dB
(No source node specified: picked Site_A)
(No destination node specified: picked Site_B)

View File

@@ -1,242 +1,6 @@
There are 96 channels propagating There are 96 channels propagating
Power mode is set to True Power mode is set to True
=> it can be modified in eqpt_config.json - Span => it can be modified in eqpt_config.json - Span
WARNING: target gain and power in node west edfa in Lorient_KMA to Loudeac
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: WARNING: effective gain in Node east edfa in Lannion_CAS to Stbrieuc is above user specified amplifier std_low_gain
max flat gain: 16dB ; required gain: 23.0dB. Please check amplifier type.
WARNING: target gain and power in node west edfa in Rennes_STA to Stbrieuc
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: WARNING: effective gain in Node east edfa in Lannion_CAS to Morlaix is above user specified amplifier std_low_gain
max flat gain: 16dB ; required gain: 23.5dB. Please check amplifier type.
WARNING: target gain and power in node west edfa in Brest_KLA to Morlaix
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: target gain and power in node east edfa in Lorient_KMA to Loudeac
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: WARNING: effective gain in Node west edfa in Lannion_CAS to Corlay is above user specified amplifier test
max flat gain: 25dB ; required gain: 29.82dB. Please check amplifier type.
WARNING: target gain and power in node east edfa in Lorient_KMA to Vannes_KBE
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: target gain and power in node west edfa in Vannes_KBE to Lorient_KMA
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: target gain and power in node east edfa in Lorient_KMA to Quimper
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: target gain and power in node west edfa in Quimper to Lorient_KMA
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: target gain and power in node west edfa in Brest_KLA to Quimper
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: target gain and power in node east edfa in Vannes_KBE to Lorient_KMA
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: target gain and power in node west edfa in Lorient_KMA to Vannes_KBE
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: target gain and power in node east edfa in Vannes_KBE to Ploermel
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: target gain and power in node west edfa in Ploermel to Vannes_KBE
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: target gain and power in node west edfa in Rennes_STA to Ploermel
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: target gain and power in node east edfa in Rennes_STA to Stbrieuc
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: target gain and power in node west edfa in Stbrieuc to Rennes_STA
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: target gain and power in node west edfa in Lannion_CAS to Stbrieuc
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: target gain and power in node east edfa in Rennes_STA to Ploermel
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: target gain and power in node west edfa in Vannes_KBE to Ploermel
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: target gain and power in node east edfa in Brest_KLA to Morlaix
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: WARNING: effective gain in Node east edfa in Brest_KLA to Quimper is above user specified amplifier std_low_gain
max flat gain: 16dB ; required gain: 23.0dB. Please check amplifier type.
WARNING: target gain and power in node east edfa in Quimper to Lorient_KMA
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: target gain and power in node west edfa in Lorient_KMA to Quimper
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: target gain and power in node east edfa in a to b
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: target gain and power in node west edfa in b to a
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: target gain and power in node east edfa in a to c
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: target gain and power in node west edfa in c to a
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: target gain and power in node east edfa in b to a
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: target gain and power in node west edfa in a to b
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: target gain and power in node east edfa in b to f
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: target gain and power in node west edfa in f to b
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: target gain and power in node east edfa in c to a
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: target gain and power in node west edfa in a to c
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: target gain and power in node west edfa in d to c
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: target gain and power in node east edfa in c to f
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: target gain and power in node west edfa in f to c
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: target gain and power in node east edfa in d to c
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: target gain and power in node west edfa in c to d
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: target gain and power in node east edfa in d to e
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: target gain and power in node west edfa in e to d
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: target gain and power in node east edfa in e to d
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: target gain and power in node west edfa in d to e
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: target gain and power in node east edfa in e to g
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: target gain and power in node west edfa in g to e
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: target gain and power in node east edfa in f to c
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: target gain and power in node west edfa in c to f
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: target gain and power in node east edfa in f to b
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: target gain and power in node west edfa in b to f
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: target gain and power in node east edfa in f to h
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: target gain and power in node west edfa in h to f
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: target gain and power in node east edfa in g to e
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: target gain and power in node west edfa in e to g
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: target gain and power in node east edfa in g to h
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: target gain and power in node west edfa in h to g
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: target gain and power in node east edfa in h to f
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: target gain and power in node west edfa in f to h
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: target gain and power in node east edfa in h to g
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
WARNING: target gain and power in node west edfa in g to h
is beyond all available amplifiers capabilities and/or extended_gain_range:
a power reduction of -1.82 is applied
There are 3 fiber spans over 130 km between trx Lannion_CAS and trx Lorient_KMA There are 3 fiber spans over 130 km between trx Lannion_CAS and trx Lorient_KMA
@@ -251,9 +15,11 @@ Transceiver trx Lannion_CAS
CD (ps/nm): 0.00 CD (ps/nm): 0.00
PMD (ps): 0.00 PMD (ps): 0.00
PDL (dB): 0.00 PDL (dB): 0.00
Latency (ms): 0.00
Roadm roadm Lannion_CAS Roadm roadm Lannion_CAS
effective loss (dB): 23.00 effective loss (dB): 23.00
pch out (dBm): -20.00 reference pch out (dBm): -20.00
actual pch out (dBm): -20.00
Edfa east edfa in Lannion_CAS to Corlay Edfa east edfa in Lannion_CAS to Corlay
type_variety: test type_variety: test
effective gain(dB): 21.18 effective gain(dB): 21.18
@@ -266,6 +32,7 @@ Edfa east edfa in Lannion_CAS to Corlay
Delta_P (dB): 0.00 Delta_P (dB): 0.00
target pch (dBm): 3.00 target pch (dBm): 3.00
effective pch (dBm): 1.18 effective pch (dBm): 1.18
actual pch out (dBm): 1.18
output VOA (dB): 0.00 output VOA (dB): 0.00
Fiber fiber (Lannion_CAS → Corlay)-F061 Fiber fiber (Lannion_CAS → Corlay)-F061
type_variety: SSMF type_variety: SSMF
@@ -274,7 +41,8 @@ Fiber fiber (Lannion_CAS → Corlay)-F061
total loss (dB): 4.00 total loss (dB): 4.00
(includes conn loss (dB) in: 0.00 out: 0.00) (includes conn loss (dB) in: 0.00 out: 0.00)
(conn loss out includes EOL margin defined in eqpt_config.json) (conn loss out includes EOL margin defined in eqpt_config.json)
pch out (dBm): -2.82 reference pch out (dBm): -2.82
actual pch out (dBm): -2.81
Fused west fused spans in Corlay Fused west fused spans in Corlay
loss (dB): 1.00 loss (dB): 1.00
Fiber fiber (Corlay → Loudeac)-F010 Fiber fiber (Corlay → Loudeac)-F010
@@ -284,7 +52,8 @@ Fiber fiber (Corlay → Loudeac)-F010
total loss (dB): 10.00 total loss (dB): 10.00
(includes conn loss (dB) in: 0.00 out: 0.00) (includes conn loss (dB) in: 0.00 out: 0.00)
(conn loss out includes EOL margin defined in eqpt_config.json) (conn loss out includes EOL margin defined in eqpt_config.json)
pch out (dBm): -13.82 reference pch out (dBm): -13.82
actual pch out (dBm): -13.81
Fused west fused spans in Loudeac Fused west fused spans in Loudeac
loss (dB): 1.00 loss (dB): 1.00
Fiber fiber (Loudeac → Lorient_KMA)-F054 Fiber fiber (Loudeac → Lorient_KMA)-F054
@@ -294,34 +63,38 @@ Fiber fiber (Loudeac → Lorient_KMA)-F054
total loss (dB): 12.00 total loss (dB): 12.00
(includes conn loss (dB) in: 0.00 out: 0.00) (includes conn loss (dB) in: 0.00 out: 0.00)
(conn loss out includes EOL margin defined in eqpt_config.json) (conn loss out includes EOL margin defined in eqpt_config.json)
pch out (dBm): -26.82 reference pch out (dBm): -26.82
actual pch out (dBm): -26.81
Edfa west edfa in Lorient_KMA to Loudeac Edfa west edfa in Lorient_KMA to Loudeac
type_variety: test type_variety: test
effective gain(dB): 28.00 effective gain(dB): 27.99
(before att_in and before output VOA) (before att_in and before output VOA)
noise figure (dB): 5.76 noise figure (dB): 5.76
(including att_in) (including att_in)
pad att_in (dB): 0.00 pad att_in (dB): 0.00
Power In (dBm): -6.99 Power In (dBm): -6.99
Power Out (dBm): 21.04 Power Out (dBm): 21.03
Delta_P (dB): -1.82 Delta_P (dB): -1.82
target pch (dBm): 1.18 target pch (dBm): 1.18
effective pch (dBm): 1.18 effective pch (dBm): 1.17
actual pch out (dBm): 1.21
output VOA (dB): 0.00 output VOA (dB): 0.00
Roadm roadm Lorient_KMA Roadm roadm Lorient_KMA
effective loss (dB): 21.18 effective loss (dB): 21.17
pch out (dBm): -20.00 reference pch out (dBm): -20.00
actual pch out (dBm): -20.00
Transceiver trx Lorient_KMA Transceiver trx Lorient_KMA
GSNR (0.1nm, dB): 23.94 GSNR (0.1nm, dB): 23.93
GSNR (signal bw, dB): 19.85 GSNR (signal bw, dB): 19.85
OSNR ASE (0.1nm, dB): 24.29 OSNR ASE (0.1nm, dB): 24.29
OSNR ASE (signal bw, dB): 20.20 OSNR ASE (signal bw, dB): 20.20
CD (ps/nm): 2171.00 CD (ps/nm): 2171.00
PMD (ps): 0.46 PMD (ps): 0.46
PDL (dB): 0.00 PDL (dB): 0.00
Latency (ms): 0.64
Transmission result for input power = 3.00 dBm: Transmission result for input power = 3.00 dBm:
Final GSNR (0.1 nm): 23.94 dB Final GSNR (0.1 nm): 23.93 dB
(Invalid source node 'lannion' replaced with trx Lannion_CAS) (Invalid source node 'lannion' replaced with trx Lannion_CAS)

7
tests/requirements.txt Normal file
View File

@@ -0,0 +1,7 @@
build>=1.0.3,<2
pytest>=7.4.3,<8
# pandas 2.1 removed support for Python 3.8
pandas>=2.0.3,<3
# flake v6 killed the --diff option
flake8>=5.0.4,<6

View File

@@ -6,7 +6,7 @@
from numpy import zeros, array from numpy import zeros, array
from gnpy.core.elements import Transceiver, Edfa from gnpy.core.elements import Transceiver, Edfa
from gnpy.core.utils import automatic_fmax, lin2db, db2lin, merge_amplifier_restrictions from gnpy.core.utils import automatic_fmax, lin2db, db2lin, merge_amplifier_restrictions
from gnpy.core.info import create_input_spectral_information, Pref from gnpy.core.info import create_input_spectral_information, ReferenceCarrier
from gnpy.core.network import build_network from gnpy.core.network import build_network
from gnpy.tools.json_io import load_network, load_equipment from gnpy.tools.json_io import load_network, load_equipment
from pathlib import Path from pathlib import Path
@@ -73,7 +73,9 @@ def si(nch_and_spacing, bw):
nb_channel, spacing = nch_and_spacing nb_channel, spacing = nch_and_spacing
f_min = 191.3e12 f_min = 191.3e12
f_max = automatic_fmax(f_min, spacing, nb_channel) f_max = automatic_fmax(f_min, spacing, nb_channel)
return create_input_spectral_information(f_min, f_max, 0.15, bw, 1e-3, spacing) return create_input_spectral_information(f_min=f_min, f_max=f_max, roll_off=0.15, baud_rate=bw, power=1e-3,
spacing=spacing, tx_osnr=40.0,
ref_carrier=ReferenceCarrier(baud_rate=32e9, slot_width=50e9))
@pytest.mark.parametrize("gain, nf_expected", [(10, 15), (15, 10), (25, 5.8)]) @pytest.mark.parametrize("gain, nf_expected", [(10, 15), (15, 10), (25, 5.8)])
@@ -84,7 +86,7 @@ def test_variable_gain_nf(gain, nf_expected, setup_edfa_variable_gain, si):
si.nli /= db2lin(gain) si.nli /= db2lin(gain)
si.ase /= db2lin(gain) si.ase /= db2lin(gain)
edfa.operational.gain_target = gain edfa.operational.gain_target = gain
si.pref = si.pref._replace(p_span0=0, p_spani=-gain, neq_ch=lin2db(si.number_of_channels)) si.pref = si.pref._replace(p_span0=0, p_spani=-gain)
edfa.interpol_params(si) edfa.interpol_params(si)
result = edfa.nf result = edfa.nf
assert pytest.approx(nf_expected, abs=0.01) == result[0] assert pytest.approx(nf_expected, abs=0.01) == result[0]
@@ -98,7 +100,7 @@ def test_fixed_gain_nf(gain, nf_expected, setup_edfa_fixed_gain, si):
si.nli /= db2lin(gain) si.nli /= db2lin(gain)
si.ase /= db2lin(gain) si.ase /= db2lin(gain)
edfa.operational.gain_target = gain edfa.operational.gain_target = gain
si.pref = si.pref._replace(p_span0=0, p_spani=-gain, neq_ch=lin2db(si.number_of_channels)) si.pref = si.pref._replace(p_span0=0, p_spani=-gain)
edfa.interpol_params(si) edfa.interpol_params(si)
assert pytest.approx(nf_expected, abs=0.01) == edfa.nf[0] assert pytest.approx(nf_expected, abs=0.01) == edfa.nf[0]
@@ -113,7 +115,7 @@ def test_si(si, nch_and_spacing):
@pytest.mark.parametrize("gain", [17, 19, 21, 23]) @pytest.mark.parametrize("gain", [17, 19, 21, 23])
def test_compare_nf_models(gain, setup_edfa_variable_gain, si): def test_compare_nf_models(gain, setup_edfa_variable_gain, si):
""" compare the 2 amplifier models (polynomial and estimated from nf_min and max) """compare the 2 amplifier models (polynomial and estimated from nf_min and max)
=> nf_model vs nf_poly_fit for intermediate gain values: => nf_model vs nf_poly_fit for intermediate gain values:
between gain_min and gain_flatmax some discrepancy is expected but target < 0.5dB between gain_min and gain_flatmax some discrepancy is expected but target < 0.5dB
=> unitary test for Edfa._calc_nf (and Edfa.interpol_params)""" => unitary test for Edfa._calc_nf (and Edfa.interpol_params)"""
@@ -123,7 +125,7 @@ def test_compare_nf_models(gain, setup_edfa_variable_gain, si):
si.ase /= db2lin(gain) si.ase /= db2lin(gain)
edfa.operational.gain_target = gain edfa.operational.gain_target = gain
# edfa is variable gain type # edfa is variable gain type
si.pref = si.pref._replace(p_span0=0, p_spani=-gain, neq_ch=lin2db(si.number_of_channels)) si.pref = si.pref._replace(p_span0=0, p_spani=-gain)
edfa.interpol_params(si) edfa.interpol_params(si)
nf_model = edfa.nf[0] nf_model = edfa.nf[0]
@@ -178,7 +180,7 @@ def test_ase_noise(gain, si, setup_trx, bw):
si = span(si) si = span(si)
print(span) print(span)
si.pref = si.pref._replace(p_span0=0, p_spani=-gain, neq_ch=lin2db(si.number_of_channels)) si.pref = si.pref._replace(p_span0=0, p_spani=-gain)
edfa.interpol_params(si) edfa.interpol_params(si)
nf = edfa.nf nf = edfa.nf
print('nf', nf) print('nf', nf)

View File

@@ -4,12 +4,12 @@
# License: BSD 3-Clause Licence # License: BSD 3-Clause Licence
# Copyright (c) 2018, Telecom Infra Project # Copyright (c) 2018, Telecom Infra Project
''' """
@author: esther.lerouzic @author: esther.lerouzic
checks that computed paths are disjoint as specified in the json service file checks that computed paths are disjoint as specified in the json service file
that computed paths do not loop that computed paths do not loop
that include node constraints are correctly taken into account that include node constraints are correctly taken into account
''' """
from pathlib import Path from pathlib import Path
import pytest import pytest
@@ -19,7 +19,7 @@ from gnpy.core.exceptions import ServiceError, DisjunctionError
from gnpy.core.utils import automatic_nch, lin2db from gnpy.core.utils import automatic_nch, lin2db
from gnpy.core.elements import Roadm from gnpy.core.elements import Roadm
from gnpy.topology.request import (compute_path_dsjctn, isdisjoint, find_reversed_path, PathRequest, from gnpy.topology.request import (compute_path_dsjctn, isdisjoint, find_reversed_path, PathRequest,
correct_json_route_list) correct_json_route_list, requests_aggregation, Disjunction)
from gnpy.topology.spectrum_assignment import build_oms_list from gnpy.topology.spectrum_assignment import build_oms_list
from gnpy.tools.json_io import requests_from_json, load_requests, load_network, load_equipment, disjunctions_from_json from gnpy.tools.json_io import requests_from_json, load_requests, load_network, load_equipment, disjunctions_from_json
@@ -31,8 +31,7 @@ EQPT_LIBRARY_NAME = Path(__file__).parent.parent / 'tests/data/eqpt_config.json'
@pytest.fixture() @pytest.fixture()
def serv(test_setup): def serv(test_setup):
''' common setup for service list """common setup for service list"""
'''
network, equipment = test_setup network, equipment = test_setup
data = load_requests(SERVICE_FILE_NAME, equipment, bidir=False, network=network, network_filename=NETWORK_FILE_NAME) data = load_requests(SERVICE_FILE_NAME, equipment, bidir=False, network=network, network_filename=NETWORK_FILE_NAME)
rqs = requests_from_json(data, equipment) rqs = requests_from_json(data, equipment)
@@ -43,8 +42,7 @@ def serv(test_setup):
@pytest.fixture() @pytest.fixture()
def test_setup(): def test_setup():
''' common setup for tests: builds network, equipment and oms only once """common setup for tests: builds network, equipment and oms only once"""
'''
equipment = load_equipment(EQPT_LIBRARY_NAME) equipment = load_equipment(EQPT_LIBRARY_NAME)
network = load_network(NETWORK_FILE_NAME, equipment) network = load_network(NETWORK_FILE_NAME, equipment)
# Build the network once using the default power defined in SI in eqpt config # Build the network once using the default power defined in SI in eqpt config
@@ -61,9 +59,10 @@ def test_setup():
def test_disjunction(serv): def test_disjunction(serv):
''' service_file contains sevaral combination of disjunction constraint. The test checks """service_file contains sevaral combination of disjunction constraint
that computed paths with disjunction constraint are effectively disjoint
''' The test checks that computed paths with disjunction constraint are effectively disjoint.
"""
network, equipment, rqs, dsjn = serv network, equipment, rqs, dsjn = serv
pths = compute_path_dsjctn(network, equipment, rqs, dsjn) pths = compute_path_dsjctn(network, equipment, rqs, dsjn)
print(dsjn) print(dsjn)
@@ -86,8 +85,7 @@ def test_disjunction(serv):
def test_does_not_loop_back(serv): def test_does_not_loop_back(serv):
''' check that computed paths do not loop back ie each element appears only once """check that computed paths do not loop back ie each element appears only once"""
'''
network, equipment, rqs, dsjn = serv network, equipment, rqs, dsjn = serv
pths = compute_path_dsjctn(network, equipment, rqs, dsjn) pths = compute_path_dsjctn(network, equipment, rqs, dsjn)
test = True test = True
@@ -108,8 +106,7 @@ def test_does_not_loop_back(serv):
def create_rq(equipment, srce, dest, bdir, node_list, loose_list, rqid='test_request'): def create_rq(equipment, srce, dest, bdir, node_list, loose_list, rqid='test_request'):
''' create the usual request list according to parameters """create the usual request list according to parameters"""
'''
requests_list = [] requests_list = []
params = { params = {
'request_id': rqid, 'request_id': rqid,
@@ -151,19 +148,20 @@ def create_rq(equipment, srce, dest, bdir, node_list, loose_list, rqid='test_req
['trx a', 'trx h', 'pass', 'found_path', ['trx h'], ['STRICT']], ['trx a', 'trx h', 'pass', 'found_path', ['trx h'], ['STRICT']],
['trx a', 'trx h', 'pass', 'found_path', ['roadm a'], ['STRICT']]]) ['trx a', 'trx h', 'pass', 'found_path', ['roadm a'], ['STRICT']]])
def test_include_constraints(test_setup, srce, dest, result, pth, node_list, loose_list): def test_include_constraints(test_setup, srce, dest, result, pth, node_list, loose_list):
''' check that all combinations of constraints are correctly handled: """check that all combinations of constraints are correctly handled:
- STRICT/LOOSE
- correct names/incorrect names -> pass/fail - STRICT/LOOSE
- possible include/impossible include - correct names/incorrect names -> pass/fail
if incorrect name -> fail - possible include/impossible include
else: if incorrect name -> fail
constraint |one or more STRICT | all LOOSE else:
---------------------------------------------------------------------------------- constraint |one or more STRICT | all LOOSE
>1 path from s to d | can be applied | found_path | found_path ----------------------------------------------------------------------------------
| cannot be applied | no_path | found_path >1 path from s to d | can be applied | found_path | found_path
---------------------------------------------------------------------------------- | cannot be applied | no_path | found_path
0 | | computation stops ----------------------------------------------------------------------------------
''' 0 | | computation stops
"""
network, equipment = test_setup network, equipment = test_setup
dsjn = [] dsjn = []
bdir = False bdir = False
@@ -201,7 +199,7 @@ def test_include_constraints(test_setup, srce, dest, result, pth, node_list, loo
['roadm c', 'roadm f'], ['roadm c', 'roadm f'],
['roadm a', 'roadm b', 'roadm f', 'roadm h']]]]) ['roadm a', 'roadm b', 'roadm f', 'roadm h']]]])
def test_create_disjunction(test_setup, dis1, dis2, node_list1, loose_list1, result, expected_paths): def test_create_disjunction(test_setup, dis1, dis2, node_list1, loose_list1, result, expected_paths):
""" verifies that the expected result is obtained for a set of particular constraints: """verifies that the expected result is obtained for a set of particular constraints:
in particular, verifies that: in particular, verifies that:
- multiple disjunction constraints are correcly handled - multiple disjunction constraints are correcly handled
- in case a loose constraint can not be met, the first alternate candidate is selected - in case a loose constraint can not be met, the first alternate candidate is selected
@@ -242,3 +240,91 @@ def test_create_disjunction(test_setup, dis1, dis2, node_list1, loose_list1, res
path_names.append(roadm_names) path_names.append(roadm_names)
assert path_names == expected_paths assert path_names == expected_paths
# if loose, one path can be returned # if loose, one path can be returned
@pytest.fixture()
def request_set():
""" creates default request dict
"""
return {
# 'request_id': '0',
'source': 'trx a',
'bidir': False,
'destination': 'trx g',
'trx_type': 'Voyager',
'spacing': 50e9,
'nodes_list': [],
'loose_list': [],
'f_min': 191.1e12,
'f_max': 196.3e12,
'nb_channel': None,
'power': 0,
'path_bandwidth': 200e9}
@pytest.mark.parametrize(
'ids, modes, req_n, req_m, disjunction, final_ids, final_ns, final_ms, final_path_bandwidths',
# requests that should be correctly aggregated:
[(['a', 'b', 'c', 'd'], ['mode 1', 'mode 1', 'mode 1', 'mode 1'],
[[0], [16], [32], [48]], [[8], [8], [8], [8]], [[]],
['d | c | b | a'], [[48, 32, 16, 0]], [[8, 8, 8, 8]], [800e9]),
(['a', 'b', 'c', 'd'], ['mode 1', 'mode 1', 'mode 1', 'mode 1'],
[[0, 8], [16, 24], [32, 40], [48]], [[4, 4], [4, 4], [4, 4], [8]], [[]],
['d | c | b | a'], [[48, 32, 40, 16, 24, 0, 8]], [[8, 4, 4, 4, 4, 4, 4]], [800e9]),
(['a', 'b', 'c', 'd'], ['mode 1', 'mode 1', 'mode 1', 'mode 1'],
[[0, 8], [None, 24], [32, 40], [None]], [[4, 4], [4, 4], [4, 4], [None]], [[]],
['d | c | b | a'], [[None, 32, 40, None, 24, 0, 8]], [[None, 4, 4, 4, 4, 4, 4]], [800e9]),
# 'a' and 'b' have same constraint and can be aggregated
(['a', 'b', 'c', 'd'], ['mode 1', 'mode 1', 'mode 1', 'mode 1'],
[[0], [16], [32], [48]], [[8], [8], [8], [8]], [['c', 'd']],
['b | a', 'c', 'd'], [[16, 0], [32], [48]], [[8, 8], [8], [8]], [400e9, 200e9, 200e9]),
(['a', 'b', 'c', 'd'], ['mode 1', 'mode 1', 'mode 1', 'mode 1'],
[[0], [16], [32], [48]], [[8], [8], [8], [8]], [['a', 'd'], ['b', 'd']],
['b | a', 'c', 'd'], [[16, 0], [32], [48]], [[8, 8], [8], [8]], [400e9, 200e9, 200e9]),
# requests that should not be aggregated:
(['a', 'b', 'c', 'd'], [None, None, None, 'mode 1'],
[[0, 8], [None, 24], [32, 40], [None]], [[4, 4], [4, 4], [4, 4], [None]], [[]],
['a', 'b', 'c', 'd'], [[0, 8], [None, 24], [32, 40], [None]], [[4, 4], [4, 4], [4, 4], [None]],
[200e9, 200e9, 200e9, 200e9]),
(['a', 'b', 'c', 'd'], ['mode 1', 'mode 1', 'mode 1', 'mode 1'],
[[0], [16], [32], [48]], [[8], [8], [8], [8]], [['c', 'd', 'a']],
['a', 'b', 'c', 'd'], [[0], [16], [32], [48]], [[8], [8], [8], [8]], [200e9, 200e9, 200e9, 200e9]), ])
def test_aggregation(ids, modes, req_n, req_m, disjunction, final_ids, final_ns, final_ms, final_path_bandwidths,
request_set):
""" tests that identical requests are correctly aggregated (included frequency slots merging)
if mode is not defined, requests must not be merged,
if requests are in a synchronization vector, they should not be merged
"""
equipment = load_equipment(EQPT_LIBRARY_NAME)
requests = []
for request_id, mode, req_n, req_m in zip(ids, modes, req_n, req_m):
params = request_set
params['request_id'] = request_id
params['trx_mode'] = mode
params['effective_freq_slot'] = [{'N': n, 'M': m} for n, m in zip(req_n, req_m)]
trx_params = trx_mode_params(equipment, params['trx_type'], params['trx_mode'], True)
params.update(trx_params)
requests.append(PathRequest(**params))
params = {
'relaxable': False,
'link_diverse': True,
'node_diverse': True
}
disjunctions = []
i = 0
for vector in disjunction:
params['disjunctions_req'] = vector
params['disjunction_id'] = i
disjunctions.append(Disjunction(**params))
i += 1
requests, disjunctions = requests_aggregation(requests, disjunctions)
print(disjunctions)
print(requests)
i = 0
for final_id, final_n, final_m, final_path_bandwidth in zip(final_ids, final_ns, final_ms, final_path_bandwidths):
assert requests[i].request_id == final_id
assert requests[i].N == final_n
assert requests[i].M == final_m
assert requests[i].path_bandwidth == final_path_bandwidth
i += 1

837
tests/test_equalization.py Normal file
View File

@@ -0,0 +1,837 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Author: Esther Le Rouzic
# @Date: 2019-05-22
"""
@author: esther.lerouzic
checks that new equalization option give the same output as old one:
"""
from pathlib import Path
import pytest
from numpy.testing import assert_allclose, assert_array_equal, assert_raises
from numpy import array
from copy import deepcopy
from gnpy.core.utils import lin2db, automatic_nch, dbm2watt, power_dbm_to_psd_mw_ghz, watt2dbm, psd2powerdbm
from gnpy.core.network import build_network
from gnpy.core.elements import Roadm
from gnpy.core.info import create_input_spectral_information, Pref, create_arbitrary_spectral_information, \
ReferenceCarrier
from gnpy.core.equipment import trx_mode_params
from gnpy.core.exceptions import ConfigurationError
from gnpy.tools.json_io import network_from_json, load_equipment, load_network, _spectrum_from_json, load_json, \
Transceiver, requests_from_json
from gnpy.topology.request import PathRequest, compute_constrained_path, propagate, propagate_and_optimize_mode
TEST_DIR = Path(__file__).parent
EQPT_FILENAME = TEST_DIR / 'data/eqpt_config.json'
NETWORK_FILENAME = TEST_DIR / 'data/testTopology_expected.json'
@pytest.mark.parametrize('degree, equalization_type, target, expected_pch_out_dbm, expected_si',
[('east edfa in Lannion_CAS to Morlaix', 'target_pch_out_db', -20, -20, [-20, -20, -20, -20, -20]),
('east edfa in Lannion_CAS to Morlaix', 'target_psd_out_mWperGHz', 5e-4, -17.9588,
[-17.9588, -16.7778, -14.9485, -16.7778, -17.9588]),
('east edfa in Lannion_CAS to Morlaix', 'target_out_mWperSlotWidth', 3e-4, -18.2390,
[-19.4885, -18.2390, -16.4781, -18.2390, -19.4885]),
('east edfa in Lannion_CAS to Corlay', 'target_pch_out_db', -20, -16, [-16, -16, -16, -16, -16]),
('east edfa in Lannion_CAS to Corlay', 'target_psd_out_mWperGHz', 5e-4, -16, [-16, -16, -16, -16, -16]),
('east edfa in Lannion_CAS to Corlay', 'target_out_mWperSlotWidth', 5e-4, -16, [-16, -16, -16, -16, -16]),
('east edfa in Lannion_CAS to Stbrieuc', 'target_pch_out_db', -20, -17.16699,
[-17.16698771, -15.98599459, -14.15668776, -15.98599459, -17.16698771]),
('east edfa in Lannion_CAS to Stbrieuc', 'target_psd_out_mWperGHz', 5e-4, -17.16699,
[-17.16698771, -15.98599459, -14.15668776, -15.98599459, -17.16698771]),
('east edfa in Lannion_CAS to Stbrieuc', 'target_out_mWperSlotWidth', 5e-4, -17.16699,
[-17.16698771, -15.98599459, -14.15668776, -15.98599459, -17.16698771])])
@pytest.mark.parametrize('delta_pdb_per_channel', [[0, 0, 0, 0, 0], [1, 3, 0, -5, 0]])
def test_equalization_combination_degree(delta_pdb_per_channel, degree, equalization_type, target,
expected_pch_out_dbm, expected_si):
"""Check that ROADM correctly computes power of thr reference channel based on different
combination of equalization for ROADM and per degree
"""
roadm_config = {
"uid": "roadm Lannion_CAS",
"params": {
"per_degree_pch_out_db": {
"east edfa in Lannion_CAS to Corlay": -16
},
"per_degree_psd_out_mWperGHz": {
"east edfa in Lannion_CAS to Stbrieuc": 6e-4
},
equalization_type: target,
"add_drop_osnr": 38,
"pmd": 0,
"pdl": 0,
"restrictions": {
"preamp_variety_list": [],
"booster_variety_list": []
}
}
}
roadm = Roadm(**roadm_config)
frequency = 191e12 + array([0, 50e9, 150e9, 225e9, 275e9])
slot_width = array([37.5e9, 50e9, 75e9, 50e9, 37.5e9])
baud_rate = array([32e9, 42e9, 64e9, 42e9, 32e9])
signal = dbm2watt(array([-20.0, -18.0, -22.0, -25.0, -16.0]))
ref_carrier = ReferenceCarrier(baud_rate=32e9, slot_width=50e9)
pref = Pref(p_span0=0, p_spani=0, ref_carrier=ref_carrier)
si = create_arbitrary_spectral_information(frequency=frequency, slot_width=slot_width,
signal=signal, baud_rate=baud_rate, roll_off=0.15,
delta_pdb_per_channel=delta_pdb_per_channel,
tx_osnr=None, ref_power=pref)
to_json_before_propagation = {
'uid': 'roadm Lannion_CAS',
'type': 'Roadm',
'params': {
equalization_type: target,
'restrictions': {'preamp_variety_list': [], 'booster_variety_list': []},
'per_degree_pch_out_db': {
'east edfa in Lannion_CAS to Corlay': -16},
"per_degree_psd_out_mWperGHz": {
"east edfa in Lannion_CAS to Stbrieuc": 6e-4
}
},
'metadata': {'location': {'latitude': 0, 'longitude': 0, 'city': None, 'region': None}}
}
assert roadm.to_json == to_json_before_propagation
si = roadm(si, degree)
assert roadm.ref_pch_out_dbm == pytest.approx(expected_pch_out_dbm, rel=1e-4)
assert_allclose(expected_si, roadm.get_per_degree_power(degree, spectral_info=si), rtol=1e-3)
@pytest.mark.parametrize('equalization_type', ["target_psd_out_mWperGHz", "target_out_mWperSlotWidth"])
def test_wrong_element_config(equalization_type):
"""Check that 2 equalization correcty raise a config error
"""
roadm_config = {
"uid": "roadm Brest_KLA",
"params": {
"per_degree_pch_out_db": {},
"target_pch_out_db": -20,
equalization_type: 3.125e-4,
"add_drop_osnr": 38,
"pmd": 0,
"pdl": 0,
"restrictions": {
"preamp_variety_list": [],
"booster_variety_list": []
}
},
"metadata": {
"location": {
"city": "Brest_KLA",
"region": "RLD",
"latitude": 4.0,
"longitude": 0.0
}
}
}
with pytest.raises(ConfigurationError):
_ = Roadm(**roadm_config)
def test_merge_equalization():
"""Check that if equalization is not defined default one is correctly take and
else that it is not overwritten
"""
json_data = {
"elements": [{
"uid": "roadm Brest_KLA",
"type": "Roadm"}],
"connections": []
}
equipment = load_equipment(EQPT_FILENAME)
network = network_from_json(json_data, equipment)
roadm = [n for n in network.nodes()][0]
assert roadm.target_pch_out_dbm == -20
delattr(equipment['Roadm']['default'], 'target_pch_out_db')
setattr(equipment['Roadm']['default'], 'target_psd_out_mWperGHz', power_dbm_to_psd_mw_ghz(-20, 32e9))
# json_data is changed (type is popped from json_data with network_from_json_function). Create a new one:
json_data = {
"elements": [{
"uid": "roadm Brest_KLA",
"type": "Roadm"}],
"connections": []
}
network = network_from_json(json_data, equipment)
roadm = [n for n in network.nodes()][0]
assert roadm.target_pch_out_dbm is None
assert roadm.target_psd_out_mWperGHz == 3.125e-4
assert roadm.target_out_mWperSlotWidth is None
json_data = {
"elements": [{
"uid": "roadm Brest_KLA",
"type": "Roadm",
"params": {"target_pch_out_db": -18}}],
"connections": []
}
network = network_from_json(json_data, equipment)
roadm = [n for n in network.nodes()][0]
assert roadm.target_pch_out_dbm == -18
assert roadm.target_psd_out_mWperGHz is None
assert roadm.target_out_mWperSlotWidth is None
json_data = {
"elements": [{
"uid": "roadm Brest_KLA",
"type": "Roadm",
"params": {"target_psd_out_mWperGHz": 5e-4}}],
"connections": []
}
network = network_from_json(json_data, equipment)
roadm = [n for n in network.nodes()][0]
assert roadm.target_pch_out_dbm is None
assert roadm.target_psd_out_mWperGHz == 5e-4
assert roadm.target_out_mWperSlotWidth is None
json_data = {
"elements": [{
"uid": "roadm Brest_KLA",
"type": "Roadm",
"params": {"target_out_mWperSlotWidth": 3e-4}}],
"connections": []
}
network = network_from_json(json_data, equipment)
roadm = [n for n in network.nodes()][0]
assert roadm.target_pch_out_dbm is None
assert roadm.target_psd_out_mWperGHz is None
assert roadm.target_out_mWperSlotWidth == 3e-4
@pytest.mark.parametrize('target_out, delta_pdb_per_channel, correction',
[(-20, [0, 1, 3, 0.5, -2], [0, 0, 5, 5.5, 0]),
(-20, [0, 0, 0, 0, 0], [0, 0, 2, 5, 0]),
(-20, [-2, -2, -2, -2, -2], [0, 0, 0, 3, 0]),
(-20, [0, 2, -2, -5, 4], [0, 0, 0, 0, 0]),
(-25.5, [0, 1, 3, 0.5, -2], [0, 0, 0, 0, 0]), ])
def test_low_input_power(target_out, delta_pdb_per_channel, correction):
"""check that ROADM correctly equalizes on small examples, assumes p_span_0 = 0
case of power equalisation
"""
frequency = 191e12 + array([0, 50e9, 150e9, 225e9, 275e9])
slot_width = array([37.5e9, 50e9, 75e9, 50e9, 37.5e9])
baud_rate = array([32e9, 42e9, 64e9, 42e9, 32e9])
signal = dbm2watt(array([-20.0, -18.0, -22.0, -25.0, -16.0]))
target = target_out + array(delta_pdb_per_channel)
ref_carrier = ReferenceCarrier(baud_rate=32e9, slot_width=50e9)
pref = Pref(p_span0=0, p_spani=-20, ref_carrier=ref_carrier)
si = create_arbitrary_spectral_information(frequency=frequency, slot_width=slot_width,
signal=signal, baud_rate=baud_rate, roll_off=0.15,
delta_pdb_per_channel=delta_pdb_per_channel,
tx_osnr=None, ref_power=pref)
roadm_config = {
"uid": "roadm Brest_KLA",
"params": {
"per_degree_pch_out_db": {},
"target_pch_out_db": target_out,
"add_drop_osnr": 38,
"pmd": 0,
"pdl": 0,
"restrictions": {
"preamp_variety_list": [],
"booster_variety_list": []
}
},
"metadata": {
"location": {
"city": "Brest_KLA",
"region": "RLD",
"latitude": 4.0,
"longitude": 0.0
}
}
}
roadm = Roadm(**roadm_config)
si = roadm(si, 'toto')
assert_allclose(watt2dbm(si.signal), target - correction, rtol=1e-5)
# in other words check that if target is below input power, target is applied else power is unchanged
assert_allclose((watt2dbm(signal) >= target) * target + (watt2dbm(signal) < target) * watt2dbm(signal),
watt2dbm(si.signal), rtol=1e-5)
@pytest.mark.parametrize('target_out, delta_pdb_per_channel, correction',
[(3.125e-4,
[0, 0, 0, 0, 0],
[0, 0, 2 + lin2db(64 / 32), 5 + lin2db(42 / 32), 0]),
(3.125e-4,
[1, 3, 0, -5, 0],
[1, 1 + lin2db(42 / 32), 2 + lin2db(64 / 32), 0 + lin2db(42 / 32), 0]), ])
def test_2low_input_power(target_out, delta_pdb_per_channel, correction):
"""check that ROADM correctly equalizes on small examples, assumes p_span_0 = 0
case of PSD equalisation
"""
frequency = 191e12 + array([0, 50e9, 150e9, 225e9, 275e9])
slot_width = array([37.5e9, 50e9, 75e9, 50e9, 37.5e9])
baud_rate = array([32e9, 42e9, 64e9, 42e9, 32e9])
signal = dbm2watt(array([-20.0, -18.0, -22.0, -25.0, -16.0]))
target = psd2powerdbm(target_out, baud_rate) + array(delta_pdb_per_channel)
ref_carrier = ReferenceCarrier(baud_rate=32e9, slot_width=50e9)
pref = Pref(p_span0=0, p_spani=-20, ref_carrier=ref_carrier)
si = create_arbitrary_spectral_information(frequency=frequency, slot_width=slot_width,
signal=signal, baud_rate=baud_rate, roll_off=0.15,
delta_pdb_per_channel=delta_pdb_per_channel,
tx_osnr=None, ref_power=pref)
roadm_config = {
"uid": "roadm Brest_KLA",
"params": {
"per_degree_pch_out_db": {},
"target_psd_out_mWperGHz": target_out,
"add_drop_osnr": 38,
"pmd": 0,
"pdl": 0,
"restrictions": {
"preamp_variety_list": [],
"booster_variety_list": []
}
},
"metadata": {
"location": {
"city": "Brest_KLA",
"region": "RLD",
"latitude": 4.0,
"longitude": 0.0
}
}
}
roadm = Roadm(**roadm_config)
si = roadm(si, 'toto')
assert_allclose(watt2dbm(si.signal), target - correction, rtol=1e-5)
def net_setup(equipment):
"""common setup for tests: builds network, equipment and oms only once"""
network = load_network(NETWORK_FILENAME, equipment)
spectrum = equipment['SI']['default']
p_db = spectrum.power_dbm
p_total_db = p_db + lin2db(automatic_nch(spectrum.f_min, spectrum.f_max, spectrum.spacing))
build_network(network, equipment, p_db, p_total_db)
return network
def create_voyager_req(equipment, source, dest, bidir, nodes_list, loose_list, mode, spacing, power_dbm):
"""create the usual request list according to parameters"""
params = {'request_id': 'test_request',
'source': source,
'bidir': bidir,
'destination': dest,
'trx_type': 'Voyager',
'trx_mode': mode,
'format': mode,
'spacing': spacing,
'nodes_list': nodes_list,
'loose_list': loose_list,
'path_bandwidth': 100.0e9,
'effective_freq_slot': None}
trx_params = trx_mode_params(equipment, params['trx_type'], params['trx_mode'], True)
params.update(trx_params)
params['power'] = dbm2watt(power_dbm) if power_dbm else dbm2watt(equipment['SI']['default'].power_dbm)
f_min = params['f_min']
f_max_from_si = params['f_max']
params['nb_channel'] = automatic_nch(f_min, f_max_from_si, params['spacing'])
return PathRequest(**params)
@pytest.mark.parametrize('power_dbm', [0, 1, -2, None])
@pytest.mark.parametrize('mode, slot_width', (['mode 1', 50e9], ['mode 2', 75e9]))
def test_initial_spectrum(mode, slot_width, power_dbm):
"""checks that propagation using the user defined spectrum identical to SI, gives same result as SI"""
# first propagate without any req.initial_spectrum attribute
equipment = load_equipment(EQPT_FILENAME)
req = create_voyager_req(equipment, 'trx Brest_KLA', 'trx Vannes_KBE', False, ['trx Vannes_KBE'], ['STRICT'],
mode, slot_width, power_dbm)
network = net_setup(equipment)
path = compute_constrained_path(network, req)
infos_expected = propagate(path, req, equipment)
# then creates req.initial_spectrum attribute exactly corresponding to -spectrum option files
temp = [{
"f_min": 191.35e12 + slot_width,
"f_max": 196.15e12 - slot_width,
"baud_rate": req.baud_rate,
"slot_width": slot_width,
"roll_off": 0.15,
"tx_osnr": 40
}]
req.initial_spectrum = _spectrum_from_json(temp)
infos_actual = propagate(path, req, equipment)
print(infos_actual.frequency[0], infos_actual.frequency[-1])
print(infos_expected.frequency[0], infos_expected.frequency[-1])
assert_array_equal(infos_expected.frequency, infos_actual.frequency)
assert_array_equal(infos_expected.baud_rate, infos_actual.baud_rate)
assert_array_equal(infos_expected.slot_width, infos_actual.slot_width)
assert_array_equal(infos_expected.signal, infos_actual.signal)
assert_array_equal(infos_expected.nli, infos_actual.nli)
assert_array_equal(infos_expected.ase, infos_actual.ase)
assert_array_equal(infos_expected.roll_off, infos_actual.roll_off)
assert_array_equal(infos_expected.chromatic_dispersion, infos_actual.chromatic_dispersion)
assert_array_equal(infos_expected.pmd, infos_actual.pmd)
assert_array_equal(infos_expected.channel_number, infos_actual.channel_number)
assert_array_equal(infos_expected.number_of_channels, infos_actual.number_of_channels)
def test_initial_spectrum_not_identical():
"""checks that user defined spectrum overrides spectrum defined in SI
"""
# first propagate without any req.initial_spectrum attribute
equipment = load_equipment(EQPT_FILENAME)
req = create_voyager_req(equipment, 'trx Brest_KLA', 'trx Vannes_KBE', False, ['trx Vannes_KBE'], ['STRICT'],
'mode 1', 50e9, 0)
network = net_setup(equipment)
path = compute_constrained_path(network, req)
infos_expected = propagate(path, req, equipment)
# then creates req.initial_spectrum attribute exactly corresponding to -spectrum option files
temp = [{
"f_min": 191.4e12, # align f_min , f_max on Voyager f_min, f_mix and not SI !
"f_max": 196.1e12,
"baud_rate": 40e9,
"slot_width": 62.5e9,
"roll_off": 0.15,
"tx_osnr": 40
}]
req.initial_spectrum = _spectrum_from_json(temp)
infos_actual = propagate(path, req, equipment)
assert_raises(AssertionError, assert_array_equal, infos_expected.frequency, infos_actual.frequency)
assert_raises(AssertionError, assert_array_equal, infos_expected.baud_rate, infos_actual.baud_rate)
assert_raises(AssertionError, assert_array_equal, infos_expected.slot_width, infos_actual.slot_width)
assert_raises(AssertionError, assert_array_equal, infos_expected.signal, infos_actual.signal)
assert_raises(AssertionError, assert_array_equal, infos_expected.nli, infos_actual.nli)
assert_raises(AssertionError, assert_array_equal, infos_expected.ase, infos_actual.ase)
assert_raises(AssertionError, assert_array_equal, infos_expected.channel_number, infos_actual.channel_number)
assert_raises(AssertionError, assert_array_equal, infos_expected.number_of_channels, infos_actual.number_of_channels)
@pytest.mark.parametrize('equalization, target_value', [
('target_out_mWperSlotWidth', power_dbm_to_psd_mw_ghz(-20, 50e9)),
('target_psd_out_mWperGHz', power_dbm_to_psd_mw_ghz(-20, 32e9))])
@pytest.mark.parametrize('power_dbm', [0, 2, -0.5])
def test_target_psd_or_psw(power_dbm, equalization, target_value):
"""checks that if target_out_mWperSlotWidth or target_psd_out_mWperGHz is defined, it is used as equalization
and it gives same result if computed target is the same
"""
equipment = load_equipment(EQPT_FILENAME)
network = net_setup(equipment)
req = create_voyager_req(equipment, 'trx Brest_KLA', 'trx Vannes_KBE', False, ['trx Vannes_KBE'], ['STRICT'],
'mode 1', 50e9, power_dbm)
path = compute_constrained_path(network, req)
infos_expected = propagate(path, req, equipment)
# change default equalization to power spectral density
delattr(equipment['Roadm']['default'], 'target_pch_out_db')
setattr(equipment['Roadm']['default'], equalization, target_value)
# create a second instance with this roadm settings,
network2 = net_setup(equipment)
path2 = compute_constrained_path(network2, req)
infos_actual = propagate(path2, req, equipment)
# since baudrate is the same, resulting propagation should be the same as for power equalization
assert_array_equal(infos_expected.baud_rate, infos_actual.baud_rate)
assert_array_equal(infos_expected.slot_width, infos_actual.slot_width)
assert_array_equal(infos_expected.signal, infos_actual.signal)
assert_array_equal(infos_expected.nli, infos_actual.nli)
assert_array_equal(infos_expected.ase, infos_actual.ase)
assert_array_equal(infos_expected.roll_off, infos_actual.roll_off)
assert_array_equal(infos_expected.chromatic_dispersion, infos_actual.chromatic_dispersion)
assert_array_equal(infos_expected.pmd, infos_actual.pmd)
assert_array_equal(infos_expected.channel_number, infos_actual.channel_number)
assert_array_equal(infos_expected.number_of_channels, infos_actual.number_of_channels)
def ref_network():
"""Create a network instance with a instance of propagated path"""
equipment = load_equipment(EQPT_FILENAME)
network = net_setup(equipment)
req0 = create_voyager_req(equipment, 'trx Brest_KLA', 'trx Vannes_KBE', False, ['trx Vannes_KBE'], ['STRICT'],
'mode 1', 50e9, 0)
path0 = compute_constrained_path(network, req0)
_ = propagate(path0, req0, equipment)
return network
@pytest.mark.parametrize('deltap', [0, +1.2, -0.5])
def test_target_psd_out_mwperghz_deltap(deltap):
"""checks that if target_psd_out_mWperGHz is defined, delta_p of amps is correctly updated
Power over 1.2dBm saturate amp with this test: TODO add a test on this saturation
"""
equipment = load_equipment(EQPT_FILENAME)
network = net_setup(equipment)
req = create_voyager_req(equipment, 'trx Brest_KLA', 'trx Vannes_KBE', False, ['trx Vannes_KBE'], ['STRICT'],
'mode 1', 50e9, deltap)
temp = [{
"f_min": 191.35e12, # align f_min , f_max on Voyager f_min, f_mix and not SI !
"f_max": 196.05e12,
"baud_rate": req.baud_rate,
"slot_width": 50e9,
"roll_off": 0.15,
"tx_osnr": 40
}]
req.initial_spectrum = _spectrum_from_json(temp)
path = compute_constrained_path(network, req)
_ = propagate(path, req, equipment)
# check that gain of booster is changed accordingly whereas gain of preamp and ila is not (no saturation case)
boosters = ['east edfa in Brest_KLA to Quimper', 'east edfa in Lorient_KMA to Vannes_KBE']
ila_preamps = ['east edfa in Quimper to Lorient_KMA', 'west edfa in Lorient_KMA to Quimper',
'west edfa in Vannes_KBE to Lorient_KMA']
for amp in boosters + ila_preamps:
expected_amp = next(n for n in ref_network() if n.uid == amp)
actual_amp = next(n for n in network.nodes() if n.uid == amp)
expected_gain = expected_amp.pout_db - expected_amp.pin_db
actual_gain = actual_amp.pout_db - actual_amp.pin_db
print(actual_amp)
if amp in boosters:
assert expected_gain + deltap == pytest.approx(actual_gain, rel=1e-3)
if amp in ila_preamps:
assert expected_gain == pytest.approx(actual_gain, rel=1e-3)
@pytest.mark.parametrize('equalization', ['target_psd_out_mWperGHz', 'target_out_mWperSlotWidth'])
@pytest.mark.parametrize('case', ['SI', 'nodes'])
@pytest.mark.parametrize('deltap', [0, +2, -0.5])
@pytest.mark.parametrize('target', [-20, -21, -18])
@pytest.mark.parametrize('mode, slot_width', (['mode 1', 50e9], ['mode 2', 75e9]))
def test_equalization(case, deltap, target, mode, slot_width, equalization):
"""check that power target on roadm is correct for these cases; check on booster
- SI : target_pch_out_db / target_psd_out_mWperGHz
- node : target_pch_out_db / target_psd_out_mWperGHz
- per degree : target_pch_out_db / target_psd_out_mWperGHz
for these cases with and without power from user
"""
equipment = load_equipment(EQPT_FILENAME)
setattr(equipment['Roadm']['default'], 'target_pch_out_db', target)
req = create_voyager_req(equipment, 'trx Brest_KLA', 'trx Rennes_STA', False,
['east edfa in Brest_KLA to Quimper', 'roadm Lannion_CAS', 'trx Rennes_STA'],
['STRICT', 'STRICT', 'STRICT'],
mode, slot_width, deltap)
roadms = ['roadm Brest_KLA', 'roadm Lorient_KMA', 'roadm Lannion_CAS', 'roadm Rennes_STA']
# degree = {'roadm Brest_KLA': 'east edfa in Brest_KLA to Quimper',
# 'roadm Lorient_KMA': 'east edfa in Lorient_KMA to Loudeac'}
# boosters = ['east edfa in Brest_KLA to Quimper', 'east edfa in Lorient_KMA to Loudeac',
# 'east edfa in Lannion_CAS to Stbrieuc']
target_psd = power_dbm_to_psd_mw_ghz(target, 32e9)
ref = ReferenceCarrier(baud_rate=32e9, slot_width=50e9)
if case == 'SI':
delattr(equipment['Roadm']['default'], 'target_pch_out_db')
setattr(equipment['Roadm']['default'], equalization, target_psd)
network = net_setup(equipment)
elif case == 'nodes':
json_data = load_json(NETWORK_FILENAME)
for el in json_data['elements']:
if el['uid'] in roadms:
el['params'] = {equalization: target_psd}
network = network_from_json(json_data, equipment)
spectrum = equipment['SI']['default']
p_db = spectrum.power_dbm
p_total_db = p_db + lin2db(automatic_nch(spectrum.f_min, spectrum.f_max, spectrum.spacing))
build_network(network, equipment, p_db, p_total_db)
# check that nodes not in roadms have target_pch_out_db not None
pw_roadms = [r for r in network.nodes() if r.uid not in roadms and isinstance(r, Roadm)]
for roadm in pw_roadms:
assert roadm.target_psd_out_mWperGHz is None
assert roadm.target_pch_out_dbm == target
for roadm in [r for r in network.nodes() if r.uid in roadms and isinstance(r, Roadm)]:
assert roadm.target_pch_out_dbm is None
assert getattr(roadm, equalization) == target_psd
path = compute_constrained_path(network, req)
si = create_input_spectral_information(
f_min=req.f_min, f_max=req.f_max, roll_off=req.roll_off, baud_rate=req.baud_rate, power=req.power,
spacing=req.spacing, tx_osnr=req.tx_osnr, ref_carrier=ref)
for i, el in enumerate(path):
if isinstance(el, Roadm):
si = el(si, degree=path[i + 1].uid)
if case in ['SI', 'nodes', 'degrees']:
if equalization == 'target_psd_out_mWperGHz':
assert_allclose(power_dbm_to_psd_mw_ghz(watt2dbm(si.signal + si.ase + si.nli), si.baud_rate),
target_psd, rtol=1e-3)
if equalization == 'target_out_mWperSlotWidth':
assert_allclose(power_dbm_to_psd_mw_ghz(watt2dbm(si.signal + si.ase + si.nli), si.slot_width),
target_psd, rtol=1e-3)
else:
si = el(si)
print(el.uid)
@pytest.mark.parametrize('req_power', [0, 2, -1.5])
def test_power_option(req_power):
"""check that --po option adds correctly power with spectral information
"""
equipment = load_equipment(EQPT_FILENAME)
setattr(equipment['Roadm']['default'], 'target_pch_out_db', None)
setattr(equipment['Roadm']['default'], 'target_psd_out_mWperGHz', power_dbm_to_psd_mw_ghz(-20, 32e9))
network = net_setup(equipment)
req = create_voyager_req(equipment, 'trx Brest_KLA', 'trx Vannes_KBE', False, ['trx Vannes_KBE'], ['STRICT'],
'mode 1', 50e9, req_power)
path = compute_constrained_path(network, req)
infos_expected = propagate(path, req, equipment)
temp = [{
"f_min": 191.4e12, # align f_min , f_max on Voyager f_min, f_max and not SI !
"f_max": 196.1e12,
"baud_rate": req.baud_rate,
"slot_width": 50e9,
"roll_off": 0.15,
"tx_osnr": 40
}]
req.initial_spectrum = _spectrum_from_json(temp)
network2 = net_setup(equipment)
path2 = compute_constrained_path(network2, req)
infos_actual = propagate(path2, req, equipment)
assert_array_equal(infos_expected.baud_rate, infos_actual.baud_rate)
assert_array_equal(infos_expected.slot_width, infos_actual.slot_width)
assert_array_equal(infos_expected.signal, infos_actual.signal)
assert_array_equal(infos_expected.nli, infos_actual.nli)
assert_array_equal(infos_expected.ase, infos_actual.ase)
assert_array_equal(infos_expected.roll_off, infos_actual.roll_off)
assert_array_equal(infos_expected.chromatic_dispersion, infos_actual.chromatic_dispersion)
assert_array_equal(infos_expected.pmd, infos_actual.pmd)
assert_array_equal(infos_expected.channel_number, infos_actual.channel_number)
assert_array_equal(infos_expected.number_of_channels, infos_actual.number_of_channels)
def transceiver(slot_width, value):
return {
"type_variety": "test_offset",
"frequency": {
"min": 191.3e12,
"max": 196.1e12
},
"mode": [
{
"format": "mode 1",
"baud_rate": 64e9,
"OSNR": 18,
"bit_rate": 100e9,
"roll_off": 0.15,
"tx_osnr": 40,
"min_spacing": 75e9,
"cost": 1
},
{
"format": "mode 3",
"baud_rate": 64e9,
"OSNR": 18,
"bit_rate": 100e9,
"roll_off": 0.15,
"tx_osnr": 40,
"min_spacing": slot_width,
"equalization_offset_db": value,
"cost": 1
}
]
}
def some_requests():
route = {
"route-object-include-exclude": [
{
"explicit-route-usage": "route-include-ero",
"index": 0,
"num-unnum-hop": {
"node-id": "trx Brest_KLA",
"link-tp-id": "link-tp-id is not used",
"hop-type": "STRICT"
}
},
{
"explicit-route-usage": "route-include-ero",
"index": 1,
"num-unnum-hop": {
"node-id": "trx Vannes_KBE",
"link-tp-id": "link-tp-id is not used",
"hop-type": "STRICT"
}
}
]
}
return {
"path-request": [{
"request-id": "2",
"source": "trx Brest_KLA",
"destination": "trx Vannes_KBE",
"src-tp-id": "trx Brest_KLA",
"dst-tp-id": "trx Vannes_KBE",
"bidirectional": False,
"path-constraints": {
"te-bandwidth": {
"technology": "flexi-grid",
"trx_type": "test_offset",
"trx_mode": "mode 1",
"spacing": 75000000000.0,
"path_bandwidth": 100000000000.0
}
},
"explicit-route-objects": route
}, {
"request-id": "3",
"source": "trx Brest_KLA",
"destination": "trx Vannes_KBE",
"src-tp-id": "trx Brest_KLA",
"dst-tp-id": "trx Vannes_KBE",
"bidirectional": False,
"path-constraints": {
"te-bandwidth": {
"technology": "flexi-grid",
"trx_type": "test_offset",
"trx_mode": "mode 3",
"spacing": 87500000000.0,
"path_bandwidth": 100000000000.0
}
},
"explicit-route-objects": route
}, {
"request-id": "4",
"source": "trx Brest_KLA",
"destination": "trx Vannes_KBE",
"src-tp-id": "trx Brest_KLA",
"dst-tp-id": "trx Vannes_KBE",
"bidirectional": False,
"path-constraints": {
"te-bandwidth": {
"technology": "flexi-grid",
"trx_type": "test_offset",
"trx_mode": "mode 1",
"spacing": 87500000000.0,
"path_bandwidth": 100000000000.0
}
},
"explicit-route-objects": route
}]
}
@pytest.mark.parametrize('slot_width, value', [(75e9, lin2db(75 / 87.5)),
(87.5e9, lin2db(75 / 87.5))])
def test_power_offset_trx_equalization_psw(slot_width, value):
"""Check that the equalization with the offset is giving the same result as with reference slot_width
Check that larger slot width but no offset takes larger slot width for equalization
"""
equipment = load_equipment(EQPT_FILENAME)
trx = transceiver(slot_width, value)
equipment['Transceiver'][trx['type_variety']] = Transceiver(**trx)
setattr(equipment['Roadm']['default'], 'target_pch_out_db', None)
setattr(equipment['Roadm']['default'], 'target_out_mWperSlotWidth', power_dbm_to_psd_mw_ghz(-20, 50e9))
network = net_setup(equipment)
json_data = some_requests()
ref_request, request, other = requests_from_json(json_data, equipment)
# ref_request (_expected) has no offset, equalization on 75GH basis
path_expected = compute_constrained_path(network, ref_request)
_ = propagate(path_expected, ref_request, equipment)
roadm1_expected = deepcopy(path_expected[1])
# request has an offset either defined in power and a larger slot width.
# The defined offset is "equalize as if it was a 75 GHz channel" although slot_width is 87.5GHz
path = compute_constrained_path(network, request)
_ = propagate(path, request, equipment)
roadm1 = deepcopy(path[1])
# the other request has a larger slot width (spacing) but no offset. so equalization uses this slot width
path_other = compute_constrained_path(network, other)
_ = propagate(path, other, equipment)
roadm1_other = path_other[1]
# check the first frequency since all cariers have the same equalization
# Check that the power is equalized as if it was for a 75GHz channel (mode 1) instead of a 87.5GHz
assert roadm1.pch_out_dbm[0] == roadm1_expected.pch_out_dbm[0]
# Check that equalization instead uses 87.5GHz basis
assert roadm1_other.pch_out_dbm[0] == roadm1_expected.pch_out_dbm[0] + lin2db(87.5 / 75)
@pytest.mark.parametrize('slot_width, value', [(75e9, lin2db(75 / 50)),
(87.5e9, lin2db(75 / 50))])
def test_power_offset_trx_equalization_p(slot_width, value):
"""Check that the constant power equalization with the offset is applied
"""
equipment = load_equipment(EQPT_FILENAME)
trx = transceiver(slot_width, value)
equipment['Transceiver'][trx['type_variety']] = Transceiver(**trx)
setattr(equipment['Roadm']['default'], 'target_pch_out_db', -20)
network = net_setup(equipment)
json_data = some_requests()
ref_request, request, _ = requests_from_json(json_data, equipment)
path_expected = compute_constrained_path(network, ref_request)
_ = propagate(path_expected, ref_request, equipment)
roadm1_expected = deepcopy(path_expected[1])
path = compute_constrained_path(network, request)
_ = propagate(path, request, equipment)
roadm1 = deepcopy(path[1])
assert roadm1.pch_out_dbm[0] == roadm1_expected.pch_out_dbm[0] + lin2db(75 / 50)
@pytest.mark.parametrize('equalization, target_value',
[('target_pch_out_db', -20),
('target_psd_out_mWperGHz', power_dbm_to_psd_mw_ghz(-20, 64e9)),
('target_out_mWperSlotWidth', power_dbm_to_psd_mw_ghz(-20, 50e9))])
@pytest.mark.parametrize('slot_width, value, expected_mode', [(75e9, 3.0, 'mode 3')])
def test_power_offset_automatic_mode_selection(slot_width, value, equalization,
target_value, expected_mode):
"""Check that the same result is obtained if the mode is user defined or if it is
automatically selected
"""
equipment = load_equipment(EQPT_FILENAME)
trx = transceiver(slot_width, value)
equipment['Transceiver'][trx['type_variety']] = Transceiver(**trx)
setattr(equipment['Roadm']['default'], 'target_pch_out_db', None)
setattr(equipment['Roadm']['default'], equalization, target_value)
network = net_setup(equipment)
route = {
"route-object-include-exclude": [
{
"explicit-route-usage": "route-include-ero",
"index": 0,
"num-unnum-hop": {
"node-id": "trx Brest_KLA",
"link-tp-id": "link-tp-id is not used",
"hop-type": "STRICT"
}
},
{
"explicit-route-usage": "route-include-ero",
"index": 1,
"num-unnum-hop": {
"node-id": "trx Vannes_KBE",
"link-tp-id": "link-tp-id is not used",
"hop-type": "STRICT"
}
}
]
}
json_data = {
"path-request": [{
"request-id": "imposed_mode",
"source": "trx Brest_KLA",
"destination": "trx Vannes_KBE",
"src-tp-id": "trx Brest_KLA",
"dst-tp-id": "trx Vannes_KBE",
"bidirectional": False,
"path-constraints": {
"te-bandwidth": {
"technology": "flexi-grid",
"trx_type": "test_offset",
"trx_mode": "mode 3",
"spacing": 75000000000.0,
"path_bandwidth": 100000000000.0
}
},
"explicit-route-objects": route
}, {
"request-id": "free_mode",
"source": "trx Brest_KLA",
"destination": "trx Vannes_KBE",
"src-tp-id": "trx Brest_KLA",
"dst-tp-id": "trx Vannes_KBE",
"bidirectional": False,
"path-constraints": {
"te-bandwidth": {
"technology": "flexi-grid",
"trx_type": "test_offset",
"spacing": 75000000000.0,
"path_bandwidth": 100000000000.0
}
},
"explicit-route-objects": route
}]}
imposed_req, free_req, = requests_from_json(json_data, equipment)
assert free_req.tsp_mode is None
path_expected = compute_constrained_path(network, imposed_req)
_ = propagate(path_expected, imposed_req, equipment)
path = compute_constrained_path(network, free_req)
_, mode = propagate_and_optimize_mode(path, free_req, equipment)
assert mode['format'] == expected_mode
assert_allclose(path_expected[-1].snr_01nm, path[-1].snr_01nm, rtol=1e-5)

View File

@@ -4,47 +4,56 @@
import pytest import pytest
from numpy import array, zeros, ones from numpy import array, zeros, ones
from numpy.testing import assert_array_equal from numpy.testing import assert_array_equal
from gnpy.core.info import create_arbitrary_spectral_information, Pref
from gnpy.core.info import create_arbitrary_spectral_information
from gnpy.core.exceptions import SpectrumError from gnpy.core.exceptions import SpectrumError
def test_create_arbitrary_spectral_information(): def test_create_arbitrary_spectral_information():
si = create_arbitrary_spectral_information(frequency=[193.25e12, 193.3e12, 193.35e12], si = create_arbitrary_spectral_information(frequency=[193.25e12, 193.3e12, 193.35e12],
baud_rate=32e9, signal=[1, 1, 1]) baud_rate=32e9, signal=[1, 1, 1],
delta_pdb_per_channel=[1, 1, 1],
tx_osnr=40.0,
ref_power=Pref(1, 1, None))
assert_array_equal(si.baud_rate, array([32e9, 32e9, 32e9])) assert_array_equal(si.baud_rate, array([32e9, 32e9, 32e9]))
assert_array_equal(si.slot_width, array([37.5e9, 37.5e9, 37.5e9])) assert_array_equal(si.slot_width, array([37.5e9, 37.5e9, 37.5e9]))
assert_array_equal(si.signal, ones(3)) assert_array_equal(si.signal, ones(3))
assert_array_equal(si.nli, zeros(3)) assert_array_equal(si.nli, zeros(3))
assert_array_equal(si.ase, zeros(3)) assert_array_equal(si.ase, zeros(3))
assert_array_equal(si.delta_pdb_per_channel, ones(3))
assert_array_equal(si.roll_off, zeros(3)) assert_array_equal(si.roll_off, zeros(3))
assert_array_equal(si.chromatic_dispersion, zeros(3)) assert_array_equal(si.chromatic_dispersion, zeros(3))
assert_array_equal(si.pmd, zeros(3)) assert_array_equal(si.pmd, zeros(3))
assert_array_equal(si.channel_number, array([1, 2, 3])) assert_array_equal(si.channel_number, array([1, 2, 3]))
assert_array_equal(si.number_of_channels, 3) assert_array_equal(si.number_of_channels, 3)
assert_array_equal(si.df, array([[0, 50e9, 100e9], [-50e9, 0, 50e9], [-100e9, -50e9, 0]])) assert_array_equal(si.df, array([[0, 50e9, 100e9], [-50e9, 0, 50e9], [-100e9, -50e9, 0]]))
assert_array_equal(si.tx_osnr, array([40.0, 40.0, 40.0]))
with pytest.raises(SpectrumError, match='Spectra cannot be summed: channels overlapping.'): with pytest.raises(SpectrumError, match='Spectra cannot be summed: channels overlapping.'):
si += si si += si
si = create_arbitrary_spectral_information(frequency=array([193.35e12, 193.3e12, 193.25e12]), si = create_arbitrary_spectral_information(frequency=array([193.35e12, 193.3e12, 193.25e12]),
slot_width=array([50e9, 50e9, 50e9]), slot_width=array([50e9, 50e9, 50e9]),
baud_rate=32e9, signal=array([1, 2, 3])) baud_rate=32e9, signal=array([1, 2, 3]),
tx_osnr=40.0,
ref_power=Pref(1, 1, None))
assert_array_equal(si.signal, array([3, 2, 1])) assert_array_equal(si.signal, array([3, 2, 1]))
with pytest.raises(SpectrumError, match='Spectrum baud rate, including the roll off, ' with pytest.raises(SpectrumError, match='Spectrum baud rate, including the roll off, '
r'larger than the slot width for channels: \[1, 3\].'): r'larger than the slot width for channels: \[1, 3\].'):
create_arbitrary_spectral_information(frequency=[193.25e12, 193.3e12, 193.35e12], signal=1, create_arbitrary_spectral_information(frequency=[193.25e12, 193.3e12, 193.35e12], signal=1,
baud_rate=[64e9, 32e9, 64e9], slot_width=50e9) baud_rate=[64e9, 32e9, 64e9], slot_width=50e9,
tx_osnr=40.0,
ref_power=Pref(1, 1, None))
with pytest.raises(SpectrumError, match='Spectrum required slot widths larger than the frequency spectral ' with pytest.raises(SpectrumError, match='Spectrum required slot widths larger than the frequency spectral '
r'distances between channels: \[\(1, 2\), \(3, 4\)\].'): r'distances between channels: \[\(1, 2\), \(3, 4\)\].'):
create_arbitrary_spectral_information(frequency=[193.26e12, 193.3e12, 193.35e12, 193.39e12], signal=1, create_arbitrary_spectral_information(frequency=[193.26e12, 193.3e12, 193.35e12, 193.39e12], signal=1,
baud_rate=32e9, slot_width=50e9) tx_osnr=40.0, baud_rate=32e9, slot_width=50e9, ref_power=Pref(1, 1, None))
with pytest.raises(SpectrumError, match='Spectrum required slot widths larger than the frequency spectral ' with pytest.raises(SpectrumError, match='Spectrum required slot widths larger than the frequency spectral '
r'distances between channels: \[\(1, 2\), \(2, 3\)\].'): r'distances between channels: \[\(1, 2\), \(2, 3\)\].'):
create_arbitrary_spectral_information(frequency=[193.25e12, 193.3e12, 193.35e12], signal=1, baud_rate=49e9, create_arbitrary_spectral_information(frequency=[193.25e12, 193.3e12, 193.35e12], signal=1, baud_rate=49e9,
roll_off=0.1) tx_osnr=40.0, roll_off=0.1, ref_power=Pref(1, 1, None))
with pytest.raises(SpectrumError, with pytest.raises(SpectrumError,
match='Dimension mismatch in input fields.'): match='Dimension mismatch in input fields.'):
create_arbitrary_spectral_information(frequency=[193.25e12, 193.3e12, 193.35e12], signal=[1, 2], baud_rate=49e9) create_arbitrary_spectral_information(frequency=[193.25e12, 193.3e12, 193.35e12], signal=[1, 2], baud_rate=49e9,
tx_osnr=40.0, ref_power=Pref(1, 1, None))

View File

@@ -2,6 +2,7 @@
from pathlib import Path from pathlib import Path
import os import os
from logging import INFO, Formatter
import pytest import pytest
import subprocess import subprocess
from gnpy.tools.cli_examples import transmission_main_example, path_requests_run from gnpy.tools.cli_examples import transmission_main_example, path_requests_run
@@ -9,31 +10,46 @@ from gnpy.tools.cli_examples import transmission_main_example, path_requests_run
SRC_ROOT = Path(__file__).parent.parent SRC_ROOT = Path(__file__).parent.parent
@pytest.mark.parametrize("output, handler, args", ( @pytest.mark.parametrize("output, log, handler, args", (
('transmission_main_example', transmission_main_example, []), ('transmission_main_example', None, transmission_main_example, []),
('transmission_saturated', transmission_main_example, ('transmission_saturated', 'logs_transmission_saturated', transmission_main_example,
['tests/data/testTopology_expected.json', 'lannion', 'lorient', '-e', 'tests/data/eqpt_config.json', '--pow', '3']), ['tests/data/testTopology_expected.json', 'lannion', 'lorient', '-e', 'tests/data/eqpt_config.json', '--pow', '3']),
('path_requests_run', path_requests_run, []), ('path_requests_run', 'logs_path_request', path_requests_run, ['-v']),
('transmission_main_example__raman', transmission_main_example, ('transmission_main_example__raman', None, transmission_main_example,
['gnpy/example-data/raman_edfa_example_network.json', '--sim', 'gnpy/example-data/sim_params.json', '--show-channels', ]), ['gnpy/example-data/raman_edfa_example_network.json', '--sim', 'gnpy/example-data/sim_params.json', '--show-channels', ]),
('openroadm-v4-Stockholm-Gothenburg', transmission_main_example, ('openroadm-v4-Stockholm-Gothenburg', None, transmission_main_example,
['-e', 'gnpy/example-data/eqpt_config_openroadm_ver4.json', 'gnpy/example-data/Sweden_OpenROADMv4_example_network.json', ]), ['-e', 'gnpy/example-data/eqpt_config_openroadm_ver4.json', 'gnpy/example-data/Sweden_OpenROADMv4_example_network.json', ]),
('openroadm-v5-Stockholm-Gothenburg', transmission_main_example, ('openroadm-v5-Stockholm-Gothenburg', None, transmission_main_example,
['-e', 'gnpy/example-data/eqpt_config_openroadm_ver5.json', 'gnpy/example-data/Sweden_OpenROADMv5_example_network.json', ]), ['-e', 'gnpy/example-data/eqpt_config_openroadm_ver5.json', 'gnpy/example-data/Sweden_OpenROADMv5_example_network.json', ]),
('transmission_main_example_long', None, transmission_main_example,
['-e', 'tests/data/eqpt_config.json', 'tests/data/test_long_network.json']),
('spectrum1_transmission_main_example', None, transmission_main_example,
['--spectrum', 'gnpy/example-data/initial_spectrum1.json', 'gnpy/example-data/meshTopologyExampleV2.xls', ]),
('spectrum2_transmission_main_example', None, transmission_main_example,
['--spectrum', 'gnpy/example-data/initial_spectrum2.json', 'gnpy/example-data/meshTopologyExampleV2.xls', '--show-channels', ]),
('path_requests_run_CD_PMD_PDL_missing', 'logs_path_requests_run_CD_PMD_PDL_missing', path_requests_run,
['tests/data/CORONET_Global_Topology_expected.json', 'tests/data/CORONET_services.json', '-v']),
)) ))
def test_example_invocation(capfd, output, handler, args): def test_example_invocation(capfd, caplog, output, log, handler, args):
'''Make sure that our examples produce useful output''' """Make sure that our examples produce useful output"""
os.chdir(SRC_ROOT) os.chdir(SRC_ROOT)
expected = open(SRC_ROOT / 'tests' / 'invocation' / output, mode='r', encoding='utf-8').read() expected = open(SRC_ROOT / 'tests' / 'invocation' / output, mode='r', encoding='utf-8').read()
formatter = Formatter('%(levelname)-9s%(name)s:%(filename)s %(message)s')
caplog.handler.setFormatter(formatter)
# keep INFO level to at least test those logs once
caplog.set_level(INFO)
handler(args) handler(args)
captured = capfd.readouterr() captured = capfd.readouterr()
assert captured.out == expected assert captured.out == expected
assert captured.err == '' assert captured.err == ''
if log:
expected_log = open(SRC_ROOT / 'tests' / 'invocation' / log, mode='r', encoding='utf-8').read()
assert expected_log == caplog.text
@pytest.mark.parametrize('program', ('gnpy-transmission-example', 'gnpy-path-request')) @pytest.mark.parametrize('program', ('gnpy-transmission-example', 'gnpy-path-request'))
def test_run_wrapper(program): def test_run_wrapper(program):
'''Ensure that our wrappers really, really work''' """Ensure that our wrappers really, really work"""
proc = subprocess.run((program, '--help'), stdout=subprocess.PIPE, stderr=subprocess.PIPE, proc = subprocess.run((program, '--help'), stdout=subprocess.PIPE, stderr=subprocess.PIPE,
check=True, universal_newlines=True) check=True, universal_newlines=True)
assert proc.stderr == '' assert proc.stderr == ''
@@ -45,5 +61,5 @@ def test_conversion_xls():
proc = subprocess.run( proc = subprocess.run(
('gnpy-convert-xls', SRC_ROOT / 'tests' / 'data' / 'testTopology.xls', '--output', os.path.devnull), ('gnpy-convert-xls', SRC_ROOT / 'tests' / 'data' / 'testTopology.xls', '--output', os.path.devnull),
stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True, universal_newlines=True) stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True, universal_newlines=True)
assert proc.stderr == '' assert proc.stderr == 'missing header delta p\nmissing header delta p\n'
assert os.path.devnull in proc.stdout assert os.path.devnull in proc.stdout

422
tests/test_logger.py Normal file
View File

@@ -0,0 +1,422 @@
# SPDX-License-Identifier: BSD-3-Clause
#
# Copyright (C) 2020 Telecom Infra Project and GNPy contributors
# see LICENSE.md for a list of contributors
#
from pathlib import Path
import re
import pytest
from gnpy.core.exceptions import ConfigurationError, ServiceError, EquipmentConfigError, ParametersError, \
NetworkTopologyError
from gnpy.tools.json_io import SI, Roadm, Amp, load_equipment, requests_from_json, network_from_json, \
load_network, load_requests
from gnpy.tools.convert import xls_to_json_data
TEST_DIR = Path(__file__).parent
EQPT_FILENAME = TEST_DIR / 'data/eqpt_config.json'
DATA_DIR = TEST_DIR / 'data'
def test_jsonthing(caplog):
"""Check that a missing key correctly raises an info
"""
json_data = {
"baud_rate": 32e9,
"f_max": 196.1e12,
"spacing": 50e9,
"power_dbm": 0,
"power_range_db": [0, 0, 1],
"roll_off": 0.15,
"tx_osnr": 40,
"sys_margins": 2
}
_ = SI(**json_data)
expected_msg = 'WARNING missing f_min attribute in eqpt_config.json[SI]\n ' \
+ 'default value is f_min = 191350000000000.0'
assert expected_msg in caplog.text
def wrong_equipment():
"""Creates list of malformed equipments
"""
data = []
data.append({
"error": EquipmentConfigError,
"equipment": Roadm,
"json_data": {
"target_pch_out_db": -20,
"target_out_mWperSlotWidth": 3.125e-4,
"add_drop_osnr": 38,
"pmd": 0,
"pdl": 0,
"restrictions": {
"preamp_variety_list": [],
"booster_variety_list": []
}
},
"expected_msg": "Only one equalization type should be set in ROADM, found: target_pch_out_db,"
+ " target_out_mWperSlotWidth"
})
data.append({
"error": EquipmentConfigError,
"equipment": Roadm,
"json_data": {
"add_drop_osnr": 38,
"pmd": 0,
"pdl": 0,
"restrictions": {
"preamp_variety_list": [],
"booster_variety_list": []
}
},
"expected_msg": "No equalization type set in ROADM"
})
return data
@pytest.mark.parametrize('error, equipment, json_data, expected_msg',
[(e['error'], e['equipment'], e['json_data'], e['expected_msg']) for e in wrong_equipment()])
def test_wrong_equipment(caplog, error, equipment, json_data, expected_msg):
"""
"""
with pytest.raises(EquipmentConfigError, match=expected_msg):
_ = equipment(**json_data)
@pytest.mark.parametrize('xls_service_filename, xls_topo_filename, expected_msg',
[('wrong_service.xlsx', 'testTopology.xls',
"Service error: Request Id: 0 - could not find tsp : 'Voyager' with mode: 'Mode 10' "
+ "in eqpt library \nComputation stopped."),
('wrong_service_type.xlsx', 'testTopology.xls',
"Service error: Request Id: 0 - could not find tsp : 'Galileo' with mode: 'mode 1' "
+ "in eqpt library \nComputation stopped.")])
def test_wrong_xls_service(xls_service_filename, xls_topo_filename, expected_msg):
"""
"""
equipment = load_equipment(EQPT_FILENAME)
network = load_network(DATA_DIR / xls_topo_filename, equipment)
with pytest.raises(ServiceError, match=expected_msg):
_ = load_requests(DATA_DIR / xls_service_filename, equipment, False, network, DATA_DIR / xls_topo_filename)
def wrong_amp():
"""Creates list of malformed equipments
"""
data = []
data.append({
"error": EquipmentConfigError,
"json_data": {
"type_variety": "test_fixed_gain",
"type_def": "fixed_gain",
"gain_flatmax": 21,
"gain_min": 20,
"p_max": 21,
"allowed_for_design": True
},
"expected_msg": "missing nf0 value input for amplifier: test_fixed_gain in equipment config"
})
data.append({
"error": EquipmentConfigError,
"json_data": {
"type_variety": "test",
"type_def": "variable_gain",
"gain_flatmax": 25,
"gain_min": 15,
"p_max": 21,
"nf_min": 5.8,
"out_voa_auto": False,
"allowed_for_design": True
},
"expected_msg": "missing nf_min or nf_max value input for amplifier: test in equipment config"
})
data.append({
"error": EquipmentConfigError,
"json_data": {
"type_variety": "medium+high_power",
"type_def": "dual_stage",
"gain_min": 25,
"preamp_variety": "std_medium_gain",
"allowed_for_design": False
},
"expected_msg": "missing preamp/booster variety input for amplifier: medium+high_power in equipment config"
})
return data
@pytest.mark.parametrize('error, json_data, expected_msg',
[(e['error'], e['json_data'], e['expected_msg']) for e in wrong_amp()])
def test_wrong_amp(error, json_data, expected_msg):
"""
"""
with pytest.raises(error, match=re.escape(expected_msg)):
_ = Amp.from_json(EQPT_FILENAME, **json_data)
def wrong_requests():
"""Creates list of malformed requests
"""
data = []
data.append({
'error': ConfigurationError,
'json_data': {
"path-request": [{
"request-id": "imposed_mode",
"source": "trx Brest_KLA",
"destination": "trx Vannes_KBE",
"src-tp-id": "trx Brest_KLA",
"dst-tp-id": "trx Vannes_KBE",
"bidirectional": False,
"path-constraints": {
"te-bandwidth": {
"technology": "flexi-grid",
"trx_type": "test_offset",
"trx_mode": "mode 3",
"spacing": 75000000000.0,
"path_bandwidth": 100000000000.0
}
}
}]
},
'expected_msg': 'Equipment Config error in imposed_mode: '
+ 'Could not find transponder "test_offset" with mode "mode 3" in equipment library'
})
data.append({
'error': ServiceError,
'json_data': {
"path-request": [{
"request-id": "Missing_type",
"source": "trx Brest_KLA",
"destination": "trx Vannes_KBE",
"src-tp-id": "trx Brest_KLA",
"dst-tp-id": "trx Vannes_KBE",
"bidirectional": False,
"path-constraints": {
"te-bandwidth": {
"technology": "flexi-grid",
"trx_type": None,
"spacing": 75000000000.0,
"path_bandwidth": 100000000000.0
}
}
}]},
'expected_msg': 'Request Missing_type has no transceiver type defined'
})
data.append({
'error': ServiceError,
'json_data': {
"path-request": [{
"request-id": "wrong_spacing",
"source": "trx Brest_KLA",
"destination": "trx Vannes_KBE",
"src-tp-id": "trx Brest_KLA",
"dst-tp-id": "trx Vannes_KBE",
"bidirectional": False,
"path-constraints": {
"te-bandwidth": {
"technology": "flexi-grid",
"trx_type": "Voyager",
"trx_mode": "mode 2",
"spacing": 50000000000.0,
"path_bandwidth": 100000000000.0
}
}
}]},
'expected_msg': 'Request wrong_spacing has spacing below transponder Voyager mode 2 min spacing'
+ ' value 75.0GHz.\nComputation stopped'
})
data.append({
'error': ServiceError,
'json_data': {
"path-request": [{
"request-id": "Wrong_nb_channel",
"source": "trx Brest_KLA",
"destination": "trx Vannes_KBE",
"src-tp-id": "trx Brest_KLA",
"dst-tp-id": "trx Vannes_KBE",
"bidirectional": False,
"path-constraints": {
"te-bandwidth": {
"technology": "flexi-grid",
"trx_type": "Voyager",
"trx_mode": "mode 2",
"spacing": 75000000000.0,
"max-nb-of-channel": 150,
"path_bandwidth": 100000000000.0
}
}
}]},
'expected_msg': 'Requested channel number 150, baud rate 66.0 GHz'
+ ' and requested spacing 75.0GHz is not consistent with frequency range'
+ ' 191.35 THz, 196.1 THz.'
+ ' Max recommanded nb of channels is 63.'
})
data.append({
'error': ServiceError,
'json_data': {
"path-request": [{
"request-id": "Wrong_M",
"source": "trx Brest_KLA",
"destination": "trx Vannes_KBE",
"src-tp-id": "trx Brest_KLA",
"dst-tp-id": "trx Vannes_KBE",
"bidirectional": False,
"path-constraints": {
"te-bandwidth": {
"technology": "flexi-grid",
"trx_type": "Voyager",
"trx_mode": "mode 2",
"spacing": 75000000000.0,
"effective-freq-slot": [
{
"N": -208,
"M": 4
}
],
"path_bandwidth": 100000000000.0
}
}
}]},
'expected_msg': 'Requested M [{\'N\': -208, \'M\': 4}] number of slots for request Wrong_M '
+ 'support 0 nb of channels while 1 are required to support request 100.0 Gbit/s'
+ ' with Voyager mode 2'
})
return data
@pytest.mark.parametrize('error, json_data, expected_msg',
[(e['error'], e['json_data'], e['expected_msg']) for e in wrong_requests()])
def test_json_request(error, json_data, expected_msg):
"""
Check that a missing key is correctly raisong the logger
"""
equipment = load_equipment(EQPT_FILENAME)
with pytest.raises(error, match=re.escape(expected_msg)):
_ = requests_from_json(json_data, equipment)
def wrong_element():
"""
"""
data = []
data.append({
"error": ConfigurationError,
"json_data": {
"elements": [{
"uid": "roadm SITE2",
"type": "Roadm",
"params": {
"target_pch_out_db": -20,
"target_out_mWperSlotWidth": 3.125e-4,
},
"metadata": {
"location": {
"latitude": 2.0,
"longitude": 3.0,
"city": "SITE2",
"region": "RLD"
}
}
}],
"connections": []
},
"expected_msg": "ROADM roadm SITE2: invalid equalization settings"
})
data.append({
"error": ConfigurationError,
"json_data": {
"elements": [{
"uid": "east edfa in ILA2 to SITE2",
"type": "Edfa",
"type_variety": "not_valid_variety",
"metadata": {
"location": {
"latitude": 2.0,
"longitude": 0.0,
"city": "ILA2",
"region": "RLD"
}
}
}],
"connections": []
},
"expected_msg": "The Edfa of variety type not_valid_variety was not recognized:"
+ "\nplease check it is properly defined in the eqpt_config json file"
})
data.append({
"error": ParametersError,
"json_data": {
"elements": [{
"uid": "fiber (ILA2 → ILA1)",
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 100.0,
"loss_coef": 0.2,
"att_in": 0,
"con_in": 0,
"con_out": 0
},
"metadata": {
"location": {
"latitude": 2.0,
"longitude": 1.5,
"city": None,
"region": None
}
}
}],
"connections": []
},
"expected_msg": "Config error in fiber (ILA2 → ILA1): "
+ "Fiber configurations json must include \'length_units\'. Configuration: "
+ "{\'length\': 100.0, \'loss_coef\': 0.2, \'att_in\': 0, \'con_in\': 0, \'con_out\': 0, "
+ "\'type_variety\': \'SSMF\', \'dispersion\': 1.67e-05, \'effective_area\': 8.3e-11, "
+ "\'pmd_coef\': 1.265e-15}"
})
return data
@pytest.mark.parametrize('error, json_data, expected_msg',
[(e['error'], e['json_data'], e['expected_msg']) for e in wrong_element()])
def test_json_network(error, json_data, expected_msg):
"""
Check that a missing key is correctly raisong the logger
"""
equipment = load_equipment(EQPT_FILENAME)
with pytest.raises(error, match=re.escape(expected_msg)):
_ = network_from_json(json_data, equipment)
@pytest.mark.parametrize('input_filename, expected_msg',
[(DATA_DIR / 'wrong_topo_node.xlsx', 'XLS error: The following nodes are not referenced from the Links sheet.'
+ ' If unused, remove them from the Nodes sheet:\n - toto'),
(DATA_DIR / 'wrong_topo_link.xlsx', 'XLS error: The Links sheet references nodes that are not defined in the '
+ 'Nodes sheet:\n - ALB -> toto'),
(DATA_DIR / 'wrong_topo_link_header.xlsx', 'missing header Node Z'),
(DATA_DIR / 'wrong_topo_eqpt.xlsx', 'XLS error: The Eqpt sheet refers to nodes that are not defined in the '
+ 'Nodes sheet:\n - toto'),
(DATA_DIR / 'wrong_topo_duplicate_node.xlsx', 'Duplicate city: Counter({\'ALB\': 2, \'CHA_3\': 1})'),
(DATA_DIR / 'wrong_topo_duplicate_eqpt.xlsx', 'XLS error: Duplicate lines in Eqpt sheet: - ALB -> CHA_3'),
(DATA_DIR / 'wrong_topo_bad_eqpt.xlsx', 'XLS error: The Eqpt sheet references links that are not defined '
+ 'in the Links sheet:\n - toto -> CHA_3'),
(DATA_DIR / 'wrong_duplicate_link_reverse.xlsx', 'XLS error: links - (\'ila\', \'siteb\') are duplicate'),
(DATA_DIR / 'wrong_duplicate_eqpt_ila_reverse.xlsx', 'XLS error: Duplicate ILA eqpt definition in Eqpt sheet:'
+ ' - ila')])
def test_wrong_xlsx(input_filename, expected_msg):
"""Check that error and logs are correctly working
"""
with pytest.raises(NetworkTopologyError, match=re.escape(expected_msg)):
_ = xls_to_json_data(input_filename)
@pytest.mark.parametrize('input_filename, expected_msg',
[(DATA_DIR / 'wrong_node_type.xlsx', 'invalid node type (ILA) specified in Lannion_CAS, replaced by ROADM\n')])
def test_log_wrong_xlsx(caplog, input_filename, expected_msg):
"""Check that logs are correctly working
"""
_ = xls_to_json_data(input_filename)
assert expected_msg in caplog.text

View File

@@ -6,18 +6,51 @@ Checks that the class SimParams behaves as a mutable Singleton.
""" """
import pytest import pytest
from gnpy.core.parameters import SimParams from pathlib import Path
from numpy.testing import assert_allclose
from gnpy.core.parameters import SimParams, FiberParams
from gnpy.tools.json_io import load_json, Fiber
TEST_DIR = Path(__file__).parent
@pytest.mark.usefixtures('set_sim_params') @pytest.mark.usefixtures('set_sim_params')
def test_sim_parameters(): def test_sim_parameters():
sim_params = {'nli_params': {}, 'raman_params': {}} sim_params = {'nli_params': {}, 'raman_params': {}}
SimParams.set_params(sim_params) SimParams.set_params(sim_params)
s1 = SimParams.get() s1 = SimParams()
assert s1.nli_params.method == 'gn_model_analytic' assert s1.nli_params.method == 'gn_model_analytic'
s2 = SimParams.get() s2 = SimParams()
assert not s1.raman_params.flag assert not s1.raman_params.flag
sim_params['raman_params']['flag'] = True sim_params['raman_params']['flag'] = True
SimParams.set_params(sim_params) SimParams.set_params(sim_params)
assert s2.raman_params.flag assert s2.raman_params.flag
assert s1.raman_params.flag assert s1.raman_params.flag
def test_fiber_parameters():
fiber_dict_explicit_g0 = load_json(TEST_DIR/'data'/'test_parameters_fiber_config.json')['params']
fiber_params_explicit_g0 = FiberParams(**fiber_dict_explicit_g0)
fiber_dict_default_g0 = load_json(TEST_DIR/'data'/'test_science_utils_fiber_config.json')['params']
fiber_params_default_g0 = FiberParams(**fiber_dict_default_g0)
fiber_dict_cr = load_json(TEST_DIR/'data'/'test_old_parameters_fiber_config.json')['params']
fiber_dict_cr.update(Fiber(**fiber_dict_cr).__dict__)
fiber_params_cr = FiberParams(**fiber_dict_cr)
raman_coefficient_explicit_g0 = fiber_params_explicit_g0.raman_coefficient
raman_coefficient_explicit_g0 =\
raman_coefficient_explicit_g0.normalized_gamma_raman * fiber_params_explicit_g0._raman_reference_frequency
raman_coefficient_default_g0 = fiber_params_default_g0.raman_coefficient
raman_coefficient_default_g0 = \
raman_coefficient_default_g0.normalized_gamma_raman * fiber_params_default_g0._raman_reference_frequency
raman_coefficient_cr = fiber_params_cr.raman_coefficient
raman_coefficient_cr = \
raman_coefficient_cr.normalized_gamma_raman * fiber_params_cr._raman_reference_frequency
assert_allclose(raman_coefficient_explicit_g0, raman_coefficient_default_g0, rtol=1e-10)
assert_allclose(raman_coefficient_explicit_g0, raman_coefficient_cr, rtol=1e-10)

View File

@@ -3,16 +3,17 @@
# @Author: Esther Le Rouzic # @Author: Esther Le Rouzic
# @Date: 2018-06-15 # @Date: 2018-06-15
""" Adding tests to check the parser non regression """Adding tests to check the parser non regression
convention of naming of test files:
- ..._expected.json for the reference output convention of naming of test files:
tests: - ..._expected.json for the reference output
- generation of topology json tests:
- reading of Eqpt sheet w and W/ power mode - generation of topology json
- consistency of autodesign - reading of Eqpt sheet w and W/ power mode
- generation of service list based on service sheet - consistency of autodesign
- writing of results in csv - generation of service list based on service sheet
- writing of results in json (same keys) - writing of results in csv
- writing of results in json (same keys)
""" """
from pathlib import Path from pathlib import Path
@@ -46,8 +47,7 @@ equipment = load_equipment(eqpt_filename)
}.items()) }.items())
def test_excel_json_generation(tmpdir, xls_input, expected_json_output): def test_excel_json_generation(tmpdir, xls_input, expected_json_output):
""" tests generation of topology json """tests generation of topology json"""
"""
xls_copy = Path(tmpdir) / xls_input.name xls_copy = Path(tmpdir) / xls_input.name
shutil.copyfile(xls_input, xls_copy) shutil.copyfile(xls_input, xls_copy)
convert_file(xls_copy) convert_file(xls_copy)
@@ -68,9 +68,7 @@ def test_excel_json_generation(tmpdir, xls_input, expected_json_output):
DATA_DIR / 'testTopology_auto_design_expected.json', DATA_DIR / 'testTopology_auto_design_expected.json',
}.items()) }.items())
def test_auto_design_generation_fromxlsgainmode(tmpdir, xls_input, expected_json_output): def test_auto_design_generation_fromxlsgainmode(tmpdir, xls_input, expected_json_output):
""" tests generation of topology json """tests generation of topology json and that the build network gives correct results in gain mode"""
test that the build network gives correct results in gain mode
"""
equipment = load_equipment(eqpt_filename) equipment = load_equipment(eqpt_filename)
network = load_network(xls_input, equipment) network = load_network(xls_input, equipment)
# in order to test the Eqpt sheet and load gain target, # in order to test the Eqpt sheet and load gain target,
@@ -100,8 +98,7 @@ def test_auto_design_generation_fromxlsgainmode(tmpdir, xls_input, expected_json
True True
}.items()) }.items())
def test_auto_design_generation_fromjson(tmpdir, json_input, power_mode): def test_auto_design_generation_fromjson(tmpdir, json_input, power_mode):
"""test that autodesign creates same file as an input file already autodesigned """test that autodesign creates same file as an input file already autodesigned"""
"""
equipment = load_equipment(eqpt_filename) equipment = load_equipment(eqpt_filename)
network = load_network(json_input, equipment) network = load_network(json_input, equipment)
# in order to test the Eqpt sheet and load gain target, # in order to test the Eqpt sheet and load gain target,
@@ -127,8 +124,7 @@ def test_auto_design_generation_fromjson(tmpdir, json_input, power_mode):
DATA_DIR / 'testService.xls': DATA_DIR / 'testService_services_expected.json' DATA_DIR / 'testService.xls': DATA_DIR / 'testService_services_expected.json'
}.items()) }.items())
def test_excel_service_json_generation(xls_input, expected_json_output): def test_excel_service_json_generation(xls_input, expected_json_output):
""" test services creation """test services creation"""
"""
equipment = load_equipment(eqpt_filename) equipment = load_equipment(eqpt_filename)
network = load_network(DATA_DIR / 'testTopology.xls', equipment) network = load_network(DATA_DIR / 'testTopology.xls', equipment)
# Build the network once using the default power defined in SI in eqpt config # Build the network once using the default power defined in SI in eqpt config
@@ -148,9 +144,7 @@ def test_excel_service_json_generation(xls_input, expected_json_output):
(DATA_DIR / 'testTopology_response.json', ) (DATA_DIR / 'testTopology_response.json', )
) )
def test_csv_response_generation(tmpdir, json_input): def test_csv_response_generation(tmpdir, json_input):
""" tests if generated csv is consistant with expected generation """tests if generated csv is consistant with expected generation same columns (order not important)"""
same columns (order not important)
"""
json_data = load_json(json_input) json_data = load_json(json_input)
equipment = load_equipment(eqpt_filename) equipment = load_equipment(eqpt_filename)
csv_filename = Path(tmpdir / json_input.name).with_suffix('.csv') csv_filename = Path(tmpdir / json_input.name).with_suffix('.csv')
@@ -215,8 +209,7 @@ def test_csv_response_generation(tmpdir, json_input):
DATA_DIR / 'testTopology.xls': DATA_DIR / 'testTopology_response.json', DATA_DIR / 'testTopology.xls': DATA_DIR / 'testTopology_response.json',
}.items()) }.items())
def test_json_response_generation(xls_input, expected_response_file): def test_json_response_generation(xls_input, expected_response_file):
""" tests if json response is correctly generated for all combinations of requests """tests if json response is correctly generated for all combinations of requests"""
"""
equipment = load_equipment(eqpt_filename) equipment = load_equipment(eqpt_filename)
network = load_network(xls_input, equipment) network = load_network(xls_input, equipment)
@@ -323,8 +316,7 @@ def test_json_response_generation(xls_input, expected_response_file):
('trx Brest_KLA', 'trx Rennes_STA', 'Brest_KLA | trx Lannion_CAS', 'STRICT', 'Fail') ('trx Brest_KLA', 'trx Rennes_STA', 'Brest_KLA | trx Lannion_CAS', 'STRICT', 'Fail')
]) ])
def test_excel_ila_constraints(source, destination, route_list, hoptype, expected_correction): def test_excel_ila_constraints(source, destination, route_list, hoptype, expected_correction):
""" add different kind of constraints to test all correct_route cases """add different kind of constraints to test all correct_route cases"""
"""
service_xls_input = DATA_DIR / 'testTopology.xls' service_xls_input = DATA_DIR / 'testTopology.xls'
network_json_input = DATA_DIR / 'testTopology_auto_design_expected.json' network_json_input = DATA_DIR / 'testTopology_auto_design_expected.json'
equipment = load_equipment(eqpt_filename) equipment = load_equipment(eqpt_filename)
@@ -363,7 +355,8 @@ def test_excel_ila_constraints(source, destination, route_list, hoptype, expecte
'nb_channel': 0, 'nb_channel': 0,
'power': 0, 'power': 0,
'path_bandwidth': 0, 'path_bandwidth': 0,
'effective_freq_slot': None 'effective_freq_slot': None,
'equalization_offset_db': 0
} }
request = PathRequest(**params) request = PathRequest(**params)
@@ -376,8 +369,7 @@ def test_excel_ila_constraints(source, destination, route_list, hoptype, expecte
def setup_per_degree(case): def setup_per_degree(case):
""" common setup for degree: returns the dict network for different cases """common setup for degree: returns the dict network for different cases"""
"""
json_network = load_json(DATA_DIR / 'testTopology_expected.json') json_network = load_json(DATA_DIR / 'testTopology_expected.json')
json_network_auto = load_json(DATA_DIR / 'testTopology_auto_design_expected.json') json_network_auto = load_json(DATA_DIR / 'testTopology_auto_design_expected.json')
if case == 'no': if case == 'no':
@@ -401,8 +393,7 @@ def setup_per_degree(case):
@pytest.mark.parametrize('case', ['no', 'all', 'Lannion_CAS and all', 'Lannion_CAS and one']) @pytest.mark.parametrize('case', ['no', 'all', 'Lannion_CAS and all', 'Lannion_CAS and one'])
def test_target_pch_out_db_global(case): def test_target_pch_out_db_global(case):
""" check that per degree attributes are correctly created with global values if none are given """check that per degree attributes are correctly created with global values if none are given"""
"""
json_network = setup_per_degree(case) json_network = setup_per_degree(case)
per_degree = {} per_degree = {}
for elem in json_network['elements']: for elem in json_network['elements']:
@@ -442,14 +433,12 @@ def test_target_pch_out_db_global(case):
def all_rows(sh, start=0): def all_rows(sh, start=0):
""" reads excel sheet row per row """reads excel sheet row per row"""
"""
return (sh.row(x) for x in range(start, sh.nrows)) return (sh.row(x) for x in range(start, sh.nrows))
class Amp: class Amp:
""" Node element contains uid, list of connected nodes and eqpt type """Node element contains uid, list of connected nodes and eqpt type"""
"""
def __init__(self, uid, to_node, eqpt=None, west=None): def __init__(self, uid, to_node, eqpt=None, west=None):
self.uid = uid self.uid = uid
@@ -459,7 +448,7 @@ class Amp:
def test_eqpt_creation(tmpdir): def test_eqpt_creation(tmpdir):
""" tests that convert correctly creates equipment according to equipment sheet """tests that convert correctly creates equipment according to equipment sheet
including all cominations in testTopologyconvert.xls: if a line exists the amplifier including all cominations in testTopologyconvert.xls: if a line exists the amplifier
should be created even if no values are provided. should be created even if no values are provided.
""" """
@@ -506,3 +495,71 @@ def test_eqpt_creation(tmpdir):
# check that all amp in the converted files corresponds to an eqpt line # check that all amp in the converted files corresponds to an eqpt line
for ampuid in jsonconverted.keys(): for ampuid in jsonconverted.keys():
assert ampuid in possiblename assert ampuid in possiblename
def test_service_json_constraint_order():
"""test that the constraints are read in correct order"""
unsorted_request = {
"request-id": "unsorted",
"source": "trx Brest_KLA",
"destination": "trx Vannes_KBE",
"src-tp-id": "trx Brest_KLA",
"dst-tp-id": "trx Vannes_KBE",
"bidirectional": False,
"path-constraints": {
"te-bandwidth": {
"technology": "flexi-grid",
"trx_type": "Voyager",
"trx_mode": "mode 1",
"spacing": 50000000000.0,
"output-power": 0.001,
"path_bandwidth": 10000000000.0
}
},
"explicit-route-objects": {
"route-object-include-exclude": [
{
"explicit-route-usage": "route-include-ero",
"index": 2,
"num-unnum-hop": {
"node-id": "roadm Lorient_KMA",
"link-tp-id": "link-tp-id is not used",
"hop-type": "STRICT"
}
},
{
"explicit-route-usage": "route-include-ero",
"index": 3,
"num-unnum-hop": {
"node-id": "roadm Vannes_KBE",
"link-tp-id": "link-tp-id is not used",
"hop-type": "STRICT"
}
},
{
"explicit-route-usage": "route-include-ero",
"index": 1,
"num-unnum-hop": {
"node-id": "roadm Lannion_CAS",
"link-tp-id": "link-tp-id is not used",
"hop-type": "LOOSE"
}
},
{
"explicit-route-usage": "route-include-ero",
"index": 0,
"num-unnum-hop": {
"node-id": "roadm Brest_KLA",
"link-tp-id": "link-tp-id is not used",
"hop-type": "STRICT"
}
}
]
}
}
data = {'path-request': [unsorted_request]}
rqs = requests_from_json(data, equipment)
assert rqs[0].nodes_list == ['roadm Brest_KLA', 'roadm Lannion_CAS', 'roadm Lorient_KMA', 'roadm Vannes_KBE']
assert rqs[0].loose_list == ['STRICT', 'LOOSE', 'STRICT', 'STRICT']

View File

@@ -6,7 +6,7 @@
import pytest import pytest
from gnpy.core.elements import Transceiver, Fiber, Edfa, Roadm from gnpy.core.elements import Transceiver, Fiber, Edfa, Roadm
from gnpy.core.utils import db2lin from gnpy.core.utils import db2lin
from gnpy.core.info import create_input_spectral_information from gnpy.core.info import create_input_spectral_information, ReferenceCarrier
from gnpy.core.network import build_network from gnpy.core.network import build_network
from gnpy.tools.json_io import load_network, load_equipment from gnpy.tools.json_io import load_network, load_equipment
from pathlib import Path from pathlib import Path
@@ -45,7 +45,9 @@ def propagation(input_power, con_in, con_out, dest):
p = input_power p = input_power
p = db2lin(p) * 1e-3 p = db2lin(p) * 1e-3
spacing = 50e9 # THz spacing = 50e9 # THz
si = create_input_spectral_information(191.3e12, 191.3e12 + 79 * spacing, 0.15, 32e9, p, spacing) si = create_input_spectral_information(f_min=191.3e12, f_max=191.3e12 + 79 * spacing, roll_off=0.15,
baud_rate=32e9, power=p, spacing=spacing, tx_osnr=None,
ref_carrier=ReferenceCarrier(baud_rate=32e9, slot_width=50e9))
source = next(transceivers[uid] for uid in transceivers if uid == 'trx A') source = next(transceivers[uid] for uid in transceivers if uid == 'trx A')
sink = next(transceivers[uid] for uid in transceivers if uid == dest) sink = next(transceivers[uid] for uid in transceivers if uid == dest)
path = dijkstra_path(network, source, sink) path = dijkstra_path(network, source, sink)

View File

@@ -19,7 +19,7 @@ from gnpy.core.elements import Fused, Roadm, Edfa
from gnpy.core.network import build_network from gnpy.core.network import build_network
from gnpy.tools.json_io import network_from_json, load_equipment, load_json, Amp from gnpy.tools.json_io import network_from_json, load_equipment, load_json, Amp
from gnpy.core.equipment import trx_mode_params from gnpy.core.equipment import trx_mode_params
from gnpy.topology.request import PathRequest, compute_constrained_path from gnpy.topology.request import PathRequest, compute_constrained_path, ref_carrier
from gnpy.core.info import create_input_spectral_information from gnpy.core.info import create_input_spectral_information
from gnpy.core.utils import db2lin from gnpy.core.utils import db2lin
@@ -31,10 +31,10 @@ NETWORK_FILE_NAME = TEST_DIR / 'data/testTopology_expected.json'
# mark node_uid amps as fused for testing purpose # mark node_uid amps as fused for testing purpose
@pytest.mark.parametrize("node_uid", ['east edfa in Lannion_CAS to Stbrieuc']) @pytest.mark.parametrize("node_uid", ['east edfa in Lannion_CAS to Stbrieuc'])
def test_no_amp_feature(node_uid): def test_no_amp_feature(node_uid):
''' Check that booster is not placed on a roadm if fused is specified """Check that booster is not placed on a roadm if fused is specified
test_parser covers partly this behaviour. This test should guaranty that the test_parser covers partly this behaviour. This test should guaranty that the
feature is preserved even if convert is changed feature is preserved even if convert is changed
''' """
equipment = load_equipment(EQPT_LIBRARY_NAME) equipment = load_equipment(EQPT_LIBRARY_NAME)
json_network = load_json(NETWORK_FILE_NAME) json_network = load_json(NETWORK_FILE_NAME)
@@ -145,9 +145,9 @@ def equipment():
'booster_variety_list':[] 'booster_variety_list':[]
}]) }])
def test_restrictions(restrictions, equipment): def test_restrictions(restrictions, equipment):
''' test that restriction is correctly applied if provided in eqpt_config and if no Edfa type """test that restriction is correctly applied if provided in eqpt_config and if no Edfa type
were provided in the network json were provided in the network json
''' """
# add restrictions # add restrictions
equipment['Roadm']['default'].restrictions = restrictions equipment['Roadm']['default'].restrictions = restrictions
# build network # build network
@@ -212,11 +212,11 @@ def test_restrictions(restrictions, equipment):
@pytest.mark.parametrize('power_dbm', [0, +1, -2]) @pytest.mark.parametrize('power_dbm', [0, +1, -2])
@pytest.mark.parametrize('prev_node_type, effective_pch_out_db', [('edfa', -20.0), ('fused', -22.0)]) @pytest.mark.parametrize('prev_node_type, effective_pch_out_db', [('edfa', -20.0), ('fused', -22.0)])
def test_roadm_target_power(prev_node_type, effective_pch_out_db, power_dbm): def test_roadm_target_power(prev_node_type, effective_pch_out_db, power_dbm):
''' Check that egress power of roadm is equal to target power if input power is greater """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 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, so that the target for the test where the prev_node in ROADM B is either an amplifier or a fused, so that the target
power can not be met in this last case. power can not be met in this last case.
''' """
equipment = load_equipment(EQPT_LIBRARY_NAME) equipment = load_equipment(EQPT_LIBRARY_NAME)
json_network = load_json(TEST_DIR / 'data/twohops_roadm_power_test.json') json_network = load_json(TEST_DIR / 'data/twohops_roadm_power_test.json')
prev_node = next(n for n in json_network['elements'] if n['uid'] == 'west edfa in node B to ila2') prev_node = next(n for n in json_network['elements'] if n['uid'] == 'west edfa in node B to ila2')
@@ -228,9 +228,9 @@ def test_roadm_target_power(prev_node_type, effective_pch_out_db, power_dbm):
prev_node['params'] = {'loss': 0} prev_node['params'] = {'loss': 0}
json_network['elements'].append(prev_node) json_network['elements'].append(prev_node)
network = network_from_json(json_network, equipment) network = network_from_json(json_network, equipment)
p_total_db = power_dbm + lin2db(automatic_nch(equipment['SI']['default'].f_min, nb_channel = automatic_nch(equipment['SI']['default'].f_min, equipment['SI']['default'].f_max,
equipment['SI']['default'].f_max, equipment['SI']['default'].spacing)
equipment['SI']['default'].spacing)) p_total_db = power_dbm + lin2db(nb_channel)
build_network(network, equipment, power_dbm, p_total_db) build_network(network, equipment, power_dbm, p_total_db)
@@ -245,6 +245,7 @@ def test_roadm_target_power(prev_node_type, effective_pch_out_db, power_dbm):
'format': '', 'format': '',
'path_bandwidth': 100e9, 'path_bandwidth': 100e9,
'effective_freq_slot': None, 'effective_freq_slot': None,
'nb_channel': nb_channel
} }
trx_params = trx_mode_params(equipment) trx_params = trx_mode_params(equipment)
params.update(trx_params) params.update(trx_params)
@@ -252,15 +253,14 @@ def test_roadm_target_power(prev_node_type, effective_pch_out_db, power_dbm):
req.power = db2lin(power_dbm - 30) req.power = db2lin(power_dbm - 30)
path = compute_constrained_path(network, req) path = compute_constrained_path(network, req)
si = create_input_spectral_information( si = create_input_spectral_information(
req.f_min, req.f_max, req.roll_off, req.baud_rate, f_min=req.f_min, f_max=req.f_max, roll_off=req.roll_off, baud_rate=req.baud_rate,
req.power, req.spacing) power=req.power, spacing=req.spacing, tx_osnr=req.tx_osnr, ref_carrier=ref_carrier(equipment))
for i, el in enumerate(path): for i, el in enumerate(path):
if isinstance(el, Roadm): if isinstance(el, Roadm):
min_power_in_roadm = min(si.signal + si.ase + si.nli) power_in_roadm = si.signal + si.ase + si.nli
si = el(si, degree=path[i + 1].uid) si = el(si, degree=path[i + 1].uid)
power_out_roadm = si.signal + si.ase + si.nli power_out_roadm = si.signal + si.ase + si.nli
if el.uid == 'roadm node B': if el.uid == 'roadm node B':
print('input', min_power_in_roadm)
# if previous was an EDFA, power level at ROADM input is enough for the ROADM to apply its # if previous was an EDFA, power level at ROADM input is enough for the ROADM to apply its
# target power (as specified in equipment ie -20 dBm) # target power (as specified in equipment ie -20 dBm)
# if it is a Fused, the input power to the ROADM is smaller than the target power, and the # if it is a Fused, the input power to the ROADM is smaller than the target power, and the
@@ -271,15 +271,15 @@ def test_roadm_target_power(prev_node_type, effective_pch_out_db, power_dbm):
if prev_node_type == 'edfa': if prev_node_type == 'edfa':
# edfa prev_node sets input power to roadm to a high enough value: # edfa prev_node sets input power to roadm to a high enough value:
# check that target power is correctly set in the ROADM # check that target power is correctly set in the ROADM
assert_allclose(el.pch_out_db, effective_pch_out_db, rtol=1e-3) assert_allclose(el.ref_pch_out_dbm, effective_pch_out_db, rtol=1e-3)
# Check that egress power of roadm is equal to target power # Check that egress power of roadm is equal to target power
assert_allclose(power_out_roadm, db2lin(effective_pch_out_db - 30), rtol=1e-3) assert_allclose(power_out_roadm, db2lin(effective_pch_out_db - 30), rtol=1e-3)
elif prev_node_type == 'fused': elif prev_node_type == 'fused':
# fused prev_node does reamplfy power after fiber propagation, so input power # fused prev_node does reamplfy power after fiber propagation, so input power
# to roadm is low. # to roadm is low.
# check that target power correctly reports power_dbm from previous propagation # check that target power correctly reports power_dbm from previous propagation
assert_allclose(el.pch_out_db, effective_pch_out_db + power_dbm, rtol=1e-3) assert_allclose(el.ref_pch_out_dbm, effective_pch_out_db + power_dbm, rtol=1e-3)
# Check that egress power of roadm is equalized to the min carrier input power. # Check that egress power of roadm is not equalized power out is the same as power in.
assert_allclose(power_out_roadm, min_power_in_roadm, rtol=1e-3) assert_allclose(power_out_roadm, power_in_roadm, rtol=1e-3)
else: else:
si = el(si) si = el(si)

View File

@@ -9,10 +9,11 @@ are tested.
from pathlib import Path from pathlib import Path
from pandas import read_csv from pandas import read_csv
from numpy.testing import assert_allclose from numpy.testing import assert_allclose
from numpy import array, genfromtxt from numpy import array
import pytest import pytest
from gnpy.core.info import create_input_spectral_information, create_arbitrary_spectral_information from gnpy.core.info import create_input_spectral_information, create_arbitrary_spectral_information, Pref, \
ReferenceCarrier
from gnpy.core.elements import Fiber, RamanFiber from gnpy.core.elements import Fiber, RamanFiber
from gnpy.core.parameters import SimParams from gnpy.core.parameters import SimParams
from gnpy.tools.json_io import load_json from gnpy.tools.json_io import load_json
@@ -23,12 +24,14 @@ TEST_DIR = Path(__file__).parent
def test_fiber(): def test_fiber():
""" Test the accuracy of propagating the Fiber.""" """Test the accuracy of propagating the Fiber."""
fiber = Fiber(**load_json(TEST_DIR / 'data' / 'test_science_utils_fiber_config.json')) fiber = Fiber(**load_json(TEST_DIR / 'data' / 'test_science_utils_fiber_config.json'))
# fix grid spectral information generation # fix grid spectral information generation
spectral_info_input = create_input_spectral_information(f_min=191.3e12, f_max=196.1e12, roll_off=0.15, spectral_info_input = create_input_spectral_information(f_min=191.3e12, f_max=196.1e12, roll_off=0.15,
baud_rate=32e9, power=1e-3, spacing=50e9) baud_rate=32e9, power=1e-3, spacing=50e9, tx_osnr=40.0,
ref_carrier=
ReferenceCarrier(baud_rate=32e9, slot_width=50e9))
# propagation # propagation
spectral_info_out = fiber(spectral_info_input) spectral_info_out = fiber(spectral_info_input)
@@ -44,8 +47,12 @@ def test_fiber():
slot_width = array([37.5e9, 50e9, 75e9, 50e9, 37.5e9]) slot_width = array([37.5e9, 50e9, 75e9, 50e9, 37.5e9])
baud_rate = array([32e9, 42e9, 64e9, 42e9, 32e9]) baud_rate = array([32e9, 42e9, 64e9, 42e9, 32e9])
signal = 1e-3 + array([0, -1e-4, 3e-4, -2e-4, +2e-4]) signal = 1e-3 + array([0, -1e-4, 3e-4, -2e-4, +2e-4])
delta_pdb_per_channel = [0, 0, 0, 0, 0]
pref = Pref(p_span0=0, p_spani=0, ref_carrier=None)
spectral_info_input = create_arbitrary_spectral_information(frequency=frequency, slot_width=slot_width, spectral_info_input = create_arbitrary_spectral_information(frequency=frequency, slot_width=slot_width,
signal=signal, baud_rate=baud_rate, roll_off=0.15) signal=signal, baud_rate=baud_rate, roll_off=0.15,
delta_pdb_per_channel=delta_pdb_per_channel,
tx_osnr=40.0, ref_power=pref)
# propagation # propagation
spectral_info_out = fiber(spectral_info_input) spectral_info_out = fiber(spectral_info_input)
@@ -60,10 +67,11 @@ def test_fiber():
@pytest.mark.usefixtures('set_sim_params') @pytest.mark.usefixtures('set_sim_params')
def test_raman_fiber(): def test_raman_fiber():
""" Test the accuracy of propagating the RamanFiber.""" """Test the accuracy of propagating the RamanFiber."""
# spectral information generation # spectral information generation
spectral_info_input = create_input_spectral_information(f_min=191.3e12, f_max=196.1e12, roll_off=0.15, spectral_info_input = create_input_spectral_information(f_min=191.3e12, f_max=196.1e12, roll_off=0.15,
baud_rate=32e9, power=1e-3, spacing=50e9) baud_rate=32e9, power=1e-3, spacing=50e9, tx_osnr=40.0,
ref_carrier=ReferenceCarrier(baud_rate=32e9, slot_width=50e9))
SimParams.set_params(load_json(TEST_DIR / 'data' / 'sim_params.json')) SimParams.set_params(load_json(TEST_DIR / 'data' / 'sim_params.json'))
fiber = RamanFiber(**load_json(TEST_DIR / 'data' / 'test_science_utils_fiber_config.json')) fiber = RamanFiber(**load_json(TEST_DIR / 'data' / 'test_science_utils_fiber_config.json'))
@@ -86,7 +94,7 @@ def test_raman_fiber():
(0.5, 81, "Lumped loss positions must be between 0 and the fiber length (80.0 km), boundaries excluded."))) (0.5, 81, "Lumped loss positions must be between 0 and the fiber length (80.0 km), boundaries excluded.")))
@pytest.mark.usefixtures('set_sim_params') @pytest.mark.usefixtures('set_sim_params')
def test_fiber_lumped_losses(loss, position, errmsg, set_sim_params): def test_fiber_lumped_losses(loss, position, errmsg, set_sim_params):
""" Lumped losses length sanity checking.""" """Lumped losses length sanity checking."""
SimParams.set_params(load_json(TEST_DIR / 'data' / 'sim_params.json')) SimParams.set_params(load_json(TEST_DIR / 'data' / 'sim_params.json'))
fiber_dict = load_json(TEST_DIR / 'data' / 'test_lumped_losses_raman_fiber_config.json') fiber_dict = load_json(TEST_DIR / 'data' / 'test_lumped_losses_raman_fiber_config.json')
fiber_dict['params']['lumped_losses'] = [{'position': position, 'loss': loss}] fiber_dict['params']['lumped_losses'] = [{'position': position, 'loss': loss}]
@@ -97,10 +105,12 @@ def test_fiber_lumped_losses(loss, position, errmsg, set_sim_params):
@pytest.mark.usefixtures('set_sim_params') @pytest.mark.usefixtures('set_sim_params')
def test_fiber_lumped_losses_srs(set_sim_params): def test_fiber_lumped_losses_srs(set_sim_params):
""" Test the accuracy of Fiber with lumped losses propagation.""" """Test the accuracy of Fiber with lumped losses propagation."""
# spectral information generation # spectral information generation
spectral_info_input = create_input_spectral_information(f_min=191.3e12, f_max=196.1e12, roll_off=0.15, spectral_info_input = create_input_spectral_information(f_min=191.3e12, f_max=196.1e12, roll_off=0.15,
baud_rate=32e9, power=1e-3, spacing=50e9) baud_rate=32e9, power=1e-3, spacing=50e9, tx_osnr=40.0,
ref_carrier=
ReferenceCarrier(baud_rate=32e9, slot_width=50e9))
SimParams.set_params(load_json(TEST_DIR / 'data' / 'sim_params.json')) SimParams.set_params(load_json(TEST_DIR / 'data' / 'sim_params.json'))
fiber = Fiber(**load_json(TEST_DIR / 'data' / 'test_lumped_losses_raman_fiber_config.json')) fiber = Fiber(**load_json(TEST_DIR / 'data' / 'test_lumped_losses_raman_fiber_config.json'))
@@ -111,18 +121,18 @@ def test_fiber_lumped_losses_srs(set_sim_params):
stimulated_raman_scattering = RamanSolver.calculate_stimulated_raman_scattering( stimulated_raman_scattering = RamanSolver.calculate_stimulated_raman_scattering(
spectral_info_input, fiber) spectral_info_input, fiber)
power_profile = stimulated_raman_scattering.power_profile power_profile = stimulated_raman_scattering.power_profile
expected_power_profile = genfromtxt(TEST_DIR / 'data' / 'test_lumped_losses_fiber_no_pumps.csv', delimiter=',') expected_power_profile = read_csv(TEST_DIR / 'data' / 'test_lumped_losses_fiber_no_pumps.csv', header=None)
assert_allclose(power_profile, expected_power_profile, rtol=1e-3) assert_allclose(power_profile, expected_power_profile, rtol=1e-3)
# with Raman pumps # with Raman pumps
expected_power_profile = genfromtxt(TEST_DIR / 'data' / 'test_lumped_losses_raman_fiber.csv', delimiter=',') expected_power_profile = read_csv(TEST_DIR / 'data' / 'test_lumped_losses_raman_fiber.csv', header=None)
stimulated_raman_scattering = RamanSolver.calculate_stimulated_raman_scattering( stimulated_raman_scattering = RamanSolver.calculate_stimulated_raman_scattering(
spectral_info_input, raman_fiber) spectral_info_input, raman_fiber)
power_profile = stimulated_raman_scattering.power_profile power_profile = stimulated_raman_scattering.power_profile
assert_allclose(power_profile, expected_power_profile, rtol=1e-3) assert_allclose(power_profile, expected_power_profile, rtol=1e-3)
# without Stimulated Raman Scattering # without Stimulated Raman Scattering
expected_power_profile = genfromtxt(TEST_DIR / 'data' / 'test_lumped_losses_fiber_no_raman.csv', delimiter=',') expected_power_profile = read_csv(TEST_DIR / 'data' / 'test_lumped_losses_fiber_no_raman.csv', header=None)
stimulated_raman_scattering = RamanSolver.calculate_attenuation_profile(spectral_info_input, fiber) stimulated_raman_scattering = RamanSolver.calculate_attenuation_profile(spectral_info_input, fiber)
power_profile = stimulated_raman_scattering.power_profile power_profile = stimulated_raman_scattering.power_profile
assert_allclose(power_profile, expected_power_profile, rtol=1e-3) assert_allclose(power_profile, expected_power_profile, rtol=1e-3)

View File

@@ -20,7 +20,8 @@ from gnpy.core.elements import Roadm, Transceiver
from gnpy.core.exceptions import ServiceError, SpectrumError from gnpy.core.exceptions import ServiceError, SpectrumError
from gnpy.topology.request import compute_path_dsjctn, find_reversed_path, deduplicate_disjunctions, PathRequest from gnpy.topology.request import compute_path_dsjctn, find_reversed_path, deduplicate_disjunctions, PathRequest
from gnpy.topology.spectrum_assignment import (build_oms_list, align_grids, nvalue_to_frequency, from gnpy.topology.spectrum_assignment import (build_oms_list, align_grids, nvalue_to_frequency,
bitmap_sum, Bitmap, spectrum_selection, pth_assign_spectrum) bitmap_sum, Bitmap, spectrum_selection, pth_assign_spectrum,
build_path_oms_id_list, aggregate_oms_bitmap)
from gnpy.tools.json_io import (load_equipment, load_network, requests_from_json, disjunctions_from_json, from gnpy.tools.json_io import (load_equipment, load_network, requests_from_json, disjunctions_from_json,
_check_one_request) _check_one_request)
@@ -45,8 +46,7 @@ def equipment():
@pytest.fixture() @pytest.fixture()
def setup(equipment): def setup(equipment):
""" common setup for tests: builds network, equipment and oms only once """common setup for tests: builds network, equipment and oms only once"""
"""
network = load_network(NETWORK_FILENAME, equipment) network = load_network(NETWORK_FILENAME, equipment)
spectrum = equipment['SI']['default'] spectrum = equipment['SI']['default']
p_db = spectrum.power_dbm p_db = spectrum.power_dbm
@@ -57,9 +57,9 @@ def setup(equipment):
def test_oms(setup): def test_oms(setup):
""" tests that the OMS is between two ROADMs, that there is no ROADM or transceivers in the OMS """tests that the OMS is between two ROADMs, that there is no ROADM or transceivers in the OMS
except end points, checks that the id of OMS is present in the element and that the element except end points, checks that the id of OMS is present in the element and that the element
OMS id is consistant OMS id is consistant
""" """
network, oms_list = setup network, oms_list = setup
for oms in oms_list: for oms in oms_list:
@@ -150,8 +150,7 @@ def test_aligned(nmin, nmax, setup):
@pytest.mark.parametrize('nval1', [0, 15, 24]) @pytest.mark.parametrize('nval1', [0, 15, 24])
@pytest.mark.parametrize('nval2', [8, 12]) @pytest.mark.parametrize('nval2', [8, 12])
def test_assign_and_sum(nval1, nval2, setup): def test_assign_and_sum(nval1, nval2, setup):
""" checks that bitmap sum gives correct result """checks that bitmap sum gives correct result"""
"""
network, oms_list = setup network, oms_list = setup
guardband = grid guardband = grid
mval = 4 # slot in 12.5GHz mval = 4 # slot in 12.5GHz
@@ -198,8 +197,7 @@ def test_assign_and_sum(nval1, nval2, setup):
def test_bitmap_assignment(setup): def test_bitmap_assignment(setup):
""" test that a bitmap can be assigned """test that a bitmap can be assigned"""
"""
network, oms_list = setup network, oms_list = setup
random_oms = oms_list[2] random_oms = oms_list[2]
random_oms.assign_spectrum(13, 7) random_oms.assign_spectrum(13, 7)
@@ -216,8 +214,7 @@ def test_bitmap_assignment(setup):
@pytest.fixture() @pytest.fixture()
def services(equipment): def services(equipment):
""" common setup for service list: builds service only once """common setup for service list: builds service only once"""
"""
with open(SERVICE_FILENAME, encoding='utf-8') as my_f: with open(SERVICE_FILENAME, encoding='utf-8') as my_f:
services = json.loads(my_f.read()) services = json.loads(my_f.read())
return services return services
@@ -225,25 +222,24 @@ def services(equipment):
@pytest.fixture() @pytest.fixture()
def requests(equipment, services): def requests(equipment, services):
""" common setup for requests, builds requests list only once """common setup for requests, builds requests list only once"""
"""
requests = requests_from_json(services, equipment) requests = requests_from_json(services, equipment)
return requests return requests
def test_spectrum_assignment_on_path(equipment, setup, requests): def test_spectrum_assignment_on_path(equipment, setup, requests):
""" test assignment functions on path and network """test assignment functions on path and network"""
"""
network, oms_list = setup network, oms_list = setup
req = [deepcopy(requests[1])] req = [deepcopy(requests[1])]
paths = compute_path_dsjctn(network, equipment, req, []) paths = compute_path_dsjctn(network, equipment, req, [])
first_path_oms = build_path_oms_id_list(paths[0])
print(req) print(req)
for nval in range(100): for nval in range(100):
req = [deepcopy(requests[1])] req = [deepcopy(requests[1])]
(center_n, startn, stopn), path_oms = spectrum_selection(paths[0], oms_list, 4) test_oms = aggregate_oms_bitmap(first_path_oms, oms_list)
center_n, startn, stopn = spectrum_selection(test_oms, 4)
pth_assign_spectrum(paths, req, oms_list, [find_reversed_path(paths[0])]) pth_assign_spectrum(paths, req, oms_list, [find_reversed_path(paths[0])])
print(f'testing on following oms {path_oms}') print(f'testing on following oms {first_path_oms}')
# check that only 96 channels are feasible # check that only 96 channels are feasible
if nval >= 96: if nval >= 96:
print(center_n, startn, stopn) print(center_n, startn, stopn)
@@ -256,13 +252,15 @@ def test_spectrum_assignment_on_path(equipment, setup, requests):
req = [requests[2]] req = [requests[2]]
paths = compute_path_dsjctn(network, equipment, req, []) paths = compute_path_dsjctn(network, equipment, req, [])
(center_n, startn, stopn), path_oms = spectrum_selection(paths[0], oms_list, 4, 478) second_path_oms = build_path_oms_id_list(paths[0])
test_oms = aggregate_oms_bitmap(second_path_oms, oms_list)
center_n, startn, stopn = spectrum_selection(test_oms, 4, 478)
print(oms_list[0].spectrum_bitmap.freq_index_max) print(oms_list[0].spectrum_bitmap.freq_index_max)
print(oms_list[0]) print(oms_list[0])
print(center_n, startn, stopn) print(center_n, startn, stopn)
print('spectrum selection error: should be None') print('spectrum selection error: should be None')
assert center_n is None and startn is None and stopn is None assert center_n is None and startn is None and stopn is None
(center_n, startn, stopn), path_oms = spectrum_selection(paths[0], oms_list, 4, 477) center_n, startn, stopn = spectrum_selection(test_oms, 4, 477)
print(center_n, startn, stopn) print(center_n, startn, stopn)
print('spectrum selection error should not be None') print('spectrum selection error should not be None')
assert center_n is not None and startn is not None and stopn is not None assert center_n is not None and startn is not None and stopn is not None
@@ -270,8 +268,7 @@ def test_spectrum_assignment_on_path(equipment, setup, requests):
@pytest.fixture() @pytest.fixture()
def request_set(): def request_set():
""" creates default request dict """creates default request dict"""
"""
return { return {
'request_id': '0', 'request_id': '0',
'source': 'trx a', 'source': 'trx a',
@@ -295,29 +292,28 @@ def request_set():
'min_spacing': 37.5e9, 'min_spacing': 37.5e9,
'nb_channel': None, 'nb_channel': None,
'power': 0, 'power': 0,
'path_bandwidth': 800e9} 'path_bandwidth': 800e9,
'equalization_offset_db': 0}
def test_freq_slot_exist(setup, equipment, request_set): def test_freq_slot_exist(setup, equipment, request_set):
""" test that assignment works even if effective_freq_slot is not populated """test that assignment works even if effective_freq_slot is not populated"""
"""
network, oms_list = setup network, oms_list = setup
params = request_set params = request_set
params['effective_freq_slot'] = None params['effective_freq_slot'] = [{'N': None, 'M': None}]
rqs = [PathRequest(**params)] rqs = [PathRequest(**params)]
paths = compute_path_dsjctn(network, equipment, rqs, []) paths = compute_path_dsjctn(network, equipment, rqs, [])
pth_assign_spectrum(paths, rqs, oms_list, [find_reversed_path(paths[0])]) pth_assign_spectrum(paths, rqs, oms_list, [find_reversed_path(paths[0])])
assert rqs[0].N == -256 assert rqs[0].N == [-256]
assert rqs[0].M == 32 assert rqs[0].M == [32]
def test_inconsistant_freq_slot(setup, equipment, request_set): def test_inconsistant_freq_slot(setup, equipment, request_set):
""" test that an inconsistant M correctly raises an error """test that an inconsistant M correctly raises an error"""
"""
network, oms_list = setup network, oms_list = setup
params = request_set params = request_set
# minimum required nb of slots is 32 (800Gbit/100Gbit/s channels each occupying 50GHz ie 4 slots) # minimum required nb of slots is 32 (800Gbit/100Gbit/s channels each occupying 50GHz ie 4 slots)
params['effective_freq_slot'] = {'N': 0, 'M': 4} params['effective_freq_slot'] = [{'N': 0, 'M': 4}]
with pytest.raises(ServiceError): with pytest.raises(ServiceError):
_check_one_request(params, 196.05e12) _check_one_request(params, 196.05e12)
params['trx_mode'] = None params['trx_mode'] = None
@@ -327,27 +323,59 @@ def test_inconsistant_freq_slot(setup, equipment, request_set):
assert rqs[0].blocking_reason == 'NOT_ENOUGH_RESERVED_SPECTRUM' assert rqs[0].blocking_reason == 'NOT_ENOUGH_RESERVED_SPECTRUM'
@pytest.mark.parametrize('n, m, final_n, final_m, blocking_reason', [ @pytest.mark.parametrize('req_n, req_m, final_n, final_m, blocking_reason, raises_error', [
# regular requests that should be correctly assigned: # regular requests that should be correctly assigned:
(-100, 32, -100, 32, None), ([-100], [32], [-100], [32], None, False),
(150, 50, 150, 50, None), ([150], [50], [150], [50], None, False),
# if n is None, there should be an assignment (enough spectrum cases) # if n is None, there should be an assignment (enough spectrum cases)
# and the center frequency should be set on the lower part of the spectrum based on m value if it exists # and the center frequency should be set on the lower part of the spectrum based on m value if it exists
# or based on 32 # or based on 32
(None, 32, -256, 32, None), ([None], [32], [-256], [32], None, False),
(None, 40, -248, 40, None), ([None], [40], [-248], [40], None, False),
(-100, None, -100, 32, None), ([-100], [None], [-100], [32], None, False),
(None, None, -256, 32, None), ([None], [None], [-256], [32], None, False),
# -280 and 60 center indexes should result in unfeasible spectrum, either out of band or # -280 and 60 center indexes should result in unfeasible spectrum, either out of band or
# overlapping with occupied spectrum. The requested spectrum is not available # overlapping with occupied spectrum. The requested spectrum is not available
(-280, None, None, None, 'NO_SPECTRUM'), ([None], [300], None, None, 'NO_SPECTRUM', False),
(-60, 40, None, None, 'NO_SPECTRUM'), ([-280], [None], None, None, 'NO_SPECTRUM', False),
([-60], [40], None, None, 'NO_SPECTRUM', False),
# raises service error: M value too small
([-60], [3], None, None, 'NOT_ENOUGH_RESERVED_SPECTRUM', True),
# 20 is smaller than min 32 required nb of slots so should also be blocked # 20 is smaller than min 32 required nb of slots so should also be blocked
(-60, 20, None, None, 'NOT_ENOUGH_RESERVED_SPECTRUM') ([-60], [20], None, None, 'NOT_ENOUGH_RESERVED_SPECTRUM', False),
]) # multiple assignments
def test_n_m_requests(setup, equipment, n, m, final_n, final_m, blocking_reason, request_set): ([-100, -164], [16, 16], [-100, -164], [16, 16], None, False),
""" test that various N and M values for a request end up with the correct path assgnment ([-100, -164], [32, 32], [-100, -164], [32, 32], None, False),
""" ([-100, -164], [None, None], [-164], [32], None, False),
([None, None], [16, 16], [-272, -240], [16, 16], None, False),
([None, None, None], [16, 16, None], [-272, -240], [16, 16], None, False),
([None, None], [None, None], [-256], [32], None, False),
([-272, None], [16, 16], [-272, -240], [16, 16], None, False),
([-272, 100], [None, 16], [-272, 100], [16, 16], None, False),
# first assign defined Ms whatever the N (but order them), and then uses imposed N. Fill in with the max
# available nb of slots (centered on N).
([-88, -100, -116, None], [8, None, 12, None], [-88, -100, -116, -280], [8, 4, 12, 8], None, False),
# If no M is defined, uses th Ns to fill in with the max possible nb of slots (with respecte to request,
# here it is 32 slots)
([-88, -106, -116, None], [None, None, None, None], [-116], [32], None, False),
# if one defined N, M is not applicable then blocks the spectrum (even f other slots are OK)
# only 2 slots remains between -104 (-100 - 4) and -108 (-112 + 4). So (-106, None) is not feasible, because min
# required M is 4 for Voyager, Mode 1
([-100, -106, -112], [4, None, 4], None, None, 'NO_SPECTRUM', False),
# required nb of channels is 8 with 4 slots each. Next two spectrum are not providing enough spectrum
# raises service error: not enough nb of channels
([-88, -100, -116], [4, 4, 4], None, None, 'NOT_ENOUGH_RESERVED_SPECTRUM', True),
([-88, -100, -116], [4, None, 4], None, None, 'NO_SPECTRUM', False),
# only 4 slots remains between -96 (-88 -8) and -104 (-116 + 12), and centered on -100, so N = -101 is not
# feasible whatever the M.
([-88, -101, -116, None], [8, 4, 12, None], None, None, 'NO_SPECTRUM', False),
([-88, -101, -116, -250], [4, 4, 12, 12], None, None, 'NO_SPECTRUM', False),
([-88, -101, -116, None], [8, None, 12, None], None, None, 'NO_SPECTRUM', False),
# raises service error: slots overlap
([-88, -81, -116, -136], [8, 8, 12, 8], None, None, 'NO_SPECTRUM', True),
])
def test_n_m_requests(setup, equipment, req_n, req_m, final_n, final_m, blocking_reason, raises_error, request_set):
"""test that various N and M values for a request end up with the correct path assignment"""
network, oms_list = setup network, oms_list = setup
# add an occupation on one of the span of the expected path OMS list on both directions # add an occupation on one of the span of the expected path OMS list on both directions
# as defined by its offsets within the OMS list: [17, 20, 13, 22] and reversed path [19, 16, 21, 26] # as defined by its offsets within the OMS list: [17, 20, 13, 22] and reversed path [19, 16, 21, 26]
@@ -356,7 +384,10 @@ def test_n_m_requests(setup, equipment, n, m, final_n, final_m, blocking_reason,
some_oms = oms_list[expected_oms[3]] some_oms = oms_list[expected_oms[3]]
some_oms.assign_spectrum(-30, 32) # means that spectrum is occupied from indexes -62 to 1 on reversed path some_oms.assign_spectrum(-30, 32) # means that spectrum is occupied from indexes -62 to 1 on reversed path
params = request_set params = request_set
params['effective_freq_slot'] = {'N': n, 'M': m} params['effective_freq_slot'] = [{'N': n, 'M': m} for n, m in zip(req_n, req_m)]
if raises_error:
with pytest.raises(ServiceError):
_check_one_request(params, 196.3e12)
rqs = [PathRequest(**params)] rqs = [PathRequest(**params)]
paths = compute_path_dsjctn(network, equipment, rqs, []) paths = compute_path_dsjctn(network, equipment, rqs, [])
@@ -372,9 +403,7 @@ def test_n_m_requests(setup, equipment, n, m, final_n, final_m, blocking_reason,
def test_reversed_direction(equipment, setup, requests, services): def test_reversed_direction(equipment, setup, requests, services):
""" checks that if spectrum is selected on one direction it is also selected on reversed """checks that if spectrum is selected on one direction it is also selected on reversed direction"""
direction
"""
network, oms_list = setup network, oms_list = setup
dsjn = disjunctions_from_json(services) dsjn = disjunctions_from_json(services)
dsjn = deduplicate_disjunctions(dsjn) dsjn = deduplicate_disjunctions(dsjn)
@@ -392,8 +421,9 @@ def test_reversed_direction(equipment, setup, requests, services):
if pth: if pth:
number_wl = ceil(requests[i].path_bandwidth / requests[i].bit_rate) number_wl = ceil(requests[i].path_bandwidth / requests[i].bit_rate)
requested_m = ceil(requests[i].spacing / slot) * number_wl requested_m = ceil(requests[i].spacing / slot) * number_wl
(center_n, startn, stopn), path_oms = spectrum_selection(pth, oms_list, requested_m, path_oms = build_path_oms_id_list(pth)
requested_n=None) test_oms = aggregate_oms_bitmap(path_oms, oms_list)
center_n, startn, stopn = spectrum_selection(test_oms, requested_m, requested_n=None)
spectrum_list.append([center_n, startn, stopn]) spectrum_list.append([center_n, startn, stopn])
else: else:
spectrum_list.append([]) spectrum_list.append([])

View File

@@ -4,7 +4,7 @@ skipsdist = True
[testenv] [testenv]
deps = deps =
-r{toxinidir}/requirements.txt -r{toxinidir}/requirements.txt
pytest>=6.2.5,<7 -r{toxinidir}/tests/requirements.txt
cover: pytest-cov cover: pytest-cov
linters: flake8 linters: flake8
linters: pep8-naming linters: pep8-naming
@@ -19,7 +19,7 @@ commands =
pytest {env:CI_COVERAGE_OPTS:} -vv {posargs} pytest {env:CI_COVERAGE_OPTS:} -vv {posargs}
cover: coverage html -d cover cover: coverage html -d cover
cover: coverage xml -o cover/coverage.xml cover: coverage xml -o cover/coverage.xml
python setup.py bdist_wheel python -m build
[testenv:docs] [testenv:docs]
deps = deps =
@@ -43,4 +43,4 @@ commands =
[flake8] [flake8]
max-line-length = 120 max-line-length = 120
max-complexity = 15 max-complexity = 15
ignore = N806 ignore = N806 W503