mirror of
				https://github.com/Telecominfraproject/oopt-gnpy.git
				synced 2025-10-31 01:57:54 +00:00 
			
		
		
		
	Compare commits
	
		
			106 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 28871c6f2d | ||
|   | 5a5bed56c2 | ||
|   | 22de1b1281 | ||
|   | 73e1485b47 | ||
|   | 22ee05ea6f | ||
|   | 31824f318d | ||
|   | b0cb604e91 | ||
|   | 79102e283a | ||
|   | db5e63d51b | ||
|   | af42699133 | ||
|   | 4ba77d0a0a | ||
|   | 064d3af8e0 | ||
|   | 4ab5bac45f | ||
|   | bbe5fb7821 | ||
|   | edf1eec072 | ||
|   | 88ac41f721 | ||
|   | c20e6fb320 | ||
|   | 05500c7047 | ||
|   | 86a39f4b5e | ||
|   | 2b25609255 | ||
|   | 7e0b95bcfd | ||
|   | f0a52dcc8a | ||
|   | 3bea4b3c9f | ||
|   | f2cc9f7225 | ||
|   | e79f9f51b6 | ||
|   | 7fd7f94efe | ||
|   | 0acdf9d9f6 | ||
|   | a3edb20142 | ||
|   | 33cc11b85c | ||
|   | 5d079ab261 | ||
|   | a3b1157e38 | ||
|   | 70731b64d6 | ||
|   | 4ea0180caf | ||
|   | eb2363a3d4 | ||
|   | 41b94cc888 | ||
|   | 1eeb6a0583 | ||
|   | 215c20e245 | ||
|   | 76e9146043 | ||
|   | 2a07eec966 | ||
|   | cc994bf118 | ||
|   | 37e70e622c | ||
|   | 7d9a508955 | ||
|   | 185adabd77 | ||
|   | 8f9cf8ccc7 | ||
|   | 0c797a254c | ||
|   | 2cdeeabfa6 | ||
|   | 5e874798cb | ||
|   | ff8f044064 | ||
|   | d84ee4e76c | ||
|   | 521d27ffac | ||
|   | 35e759212e | ||
|   | f6dede2b5f | ||
|   | 0d0019f627 | ||
|   | 06fe1c2f63 | ||
|   | 092316a9d7 | ||
|   | 48e3f96967 | ||
|   | e9e8956caf | ||
|   | 0ae341c2a5 | ||
|   | 0c2f6372f8 | ||
|   | 97e80b4445 | ||
|   | 5e4c9b7d73 | ||
|   | e96f821cce | ||
|   | 5f7e61e255 | ||
|   | 682b5c5691 | ||
|   | 11e5117505 | ||
|   | 50603420fc | ||
|   | 125264f265 | ||
|   | b1067a6266 | ||
|   | 50d4ecd700 | ||
|   | 9f37e0371e | ||
|   | 9bd303db05 | ||
|   | 1bcb3ce25c | ||
|   | e381138320 | ||
|   | b450677709 | ||
|   | 54a3725e17 | ||
|   | 8889c2437a | ||
|   | 8bf8b2947b | ||
|   | cb85b8fe2b | ||
|   | 18610fb7a9 | ||
|   | bd6b278dd1 | ||
|   | e143d25339 | ||
|   | ffc7dbc241 | ||
|   | b842898baf | ||
|   | 7ea9e3b341 | ||
|   | fcf168b361 | ||
|   | a7ec7e2ed6 | ||
|   | 00ee102b3a | ||
|   | ce11524ad9 | ||
|   | 74be14562a | ||
|   | 16694d0a09 | ||
|   | 33c6038921 | ||
|   | 119c9eda90 | ||
|   | b63e146bf4 | ||
|   | 09dba8a166 | ||
|   | 7f5043622b | ||
|   | 6ad4593f41 | ||
|   | 706661d801 | ||
|   | a408d28911 | ||
|   | b86fe96032 | ||
|   | 43926518ad | ||
|   | 128a6e816b | ||
|   | 44db951261 | ||
|   | 3c3d919b77 | ||
|   | 2079d2bc5b | ||
|   | 062e2076ed | ||
|   | 1dd1bad273 | 
| @@ -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 |  | ||||||
							
								
								
									
										65
									
								
								.github/workflows/main.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										65
									
								
								.github/workflows/main.yml
									
									
									
									
										vendored
									
									
								
							| @@ -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" | ||||||
|   | |||||||
							
								
								
									
										27
									
								
								.travis.yml
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								.travis.yml
									
									
									
									
									
								
							| @@ -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 |  | ||||||
							
								
								
									
										22
									
								
								.zuul.yaml
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								.zuul.yaml
									
									
									
									
									
								
							| @@ -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: | ||||||
|   | |||||||
| @@ -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> | ||||||
|   | |||||||
| @@ -3,12 +3,12 @@ | |||||||
| [](https://pypi.org/project/gnpy/) | [](https://pypi.org/project/gnpy/) | ||||||
| [](https://pypi.org/project/gnpy/) | [](https://pypi.org/project/gnpy/) | ||||||
| [](http://gnpy.readthedocs.io/en/master/?badge=master) | [](http://gnpy.readthedocs.io/en/master/?badge=master) | ||||||
| [](https://github.com/Telecominfraproject/oopt-gnpy/actions/workflows/main.yml) | [](https://github.com/Telecominfraproject/oopt-gnpy/actions/workflows/main.yml) | ||||||
| [](https://review.gerrithub.io/q/project:Telecominfraproject/oopt-gnpy+is:open) | [](https://review.gerrithub.io/q/project:Telecominfraproject/oopt-gnpy+is:open) | ||||||
| [](https://github.com/Telecominfraproject/oopt-gnpy/graphs/contributors) | [](https://github.com/Telecominfraproject/oopt-gnpy/graphs/contributors) | ||||||
| [](https://lgtm.com/projects/g/Telecominfraproject/oopt-gnpy/) |  | ||||||
| [](https://codecov.io/gh/Telecominfraproject/oopt-gnpy) | [](https://codecov.io/gh/Telecominfraproject/oopt-gnpy) | ||||||
| [](https://doi.org/10.5281/zenodo.3458319) | [](https://doi.org/10.5281/zenodo.3458319) | ||||||
|  | [](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 | |||||||
|  |  | ||||||
|  |  | ||||||
| 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/): | ||||||
|  |  | ||||||
|  | [](https://gnpy.app/) | ||||||
|   | |||||||
| @@ -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. | ||||||
|   | |||||||
| @@ -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={D’Amico, 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} | ||||||
|  | } | ||||||
|   | |||||||
| @@ -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: | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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`. | ||||||
|   | |||||||
							
								
								
									
										
											BIN
										
									
								
								docs/images/2022-04-12-gnpy-app.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								docs/images/2022-04-12-gnpy-app.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 288 KiB | 
| @@ -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.* | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										387
									
								
								docs/json.rst
									
									
									
									
									
								
							
							
						
						
									
										387
									
								
								docs/json.rst
									
									
									
									
									
								
							| @@ -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. | ||||||
|   | |||||||
| @@ -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. | ||||||
|   | |||||||
| @@ -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`. | ||||||
| ''' | """ | ||||||
|   | |||||||
| @@ -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`. | ||||||
| ''' | """ | ||||||
|   | |||||||
| @@ -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' | ||||||
|   | |||||||
| @@ -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 = \ | ||||||
|   | |||||||
| @@ -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 | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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)] | ||||||
|   | |||||||
| @@ -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 D’Amico, 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(): | ||||||
|   | |||||||
| @@ -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 | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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] | ||||||
|   | |||||||
							
								
								
									
										12
									
								
								gnpy/example-data/initial_spectrum1.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								gnpy/example-data/initial_spectrum1.json
									
									
									
									
									
										Normal 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 | ||||||
|  |             } | ||||||
|  |       ] | ||||||
|  | } | ||||||
							
								
								
									
										23
									
								
								gnpy/example-data/initial_spectrum2.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								gnpy/example-data/initial_spectrum2.json
									
									
									
									
									
										Normal 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" | ||||||
|  |             } | ||||||
|  |       ] | ||||||
|  | } | ||||||
| @@ -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`. | ||||||
| ''' | """ | ||||||
|   | |||||||
| @@ -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: | ||||||
|   | |||||||
| @@ -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 | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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`. | ||||||
| ''' | """ | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
							
								
								
									
										21
									
								
								tests/data/CORONET_services.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								tests/data/CORONET_services.json
									
									
									
									
									
										Normal 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 | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   ] | ||||||
|  | } | ||||||
| @@ -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
											
										
									
								
							| @@ -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,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,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 | ||||||
|   | |||||||
| 
 | 
							
								
								
									
										809
									
								
								tests/data/test_long_network.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										809
									
								
								tests/data/test_long_network.json
									
									
									
									
									
										Normal 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" | ||||||
|  |         } | ||||||
|  |     ] | ||||||
|  | } | ||||||
| @@ -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,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 | ||||||
|   | |||||||
| 
 | 
							
								
								
									
										224
									
								
								tests/data/test_old_parameters_fiber_config.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										224
									
								
								tests/data/test_old_parameters_fiber_config.json
									
									
									
									
									
										Normal 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": "" | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										225
									
								
								tests/data/test_parameters_fiber_config.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										225
									
								
								tests/data/test_parameters_fiber_config.json
									
									
									
									
									
										Normal 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": "" | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -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 | ||||||
|   | |||||||
| 
 | 
							
								
								
									
										
											BIN
										
									
								
								tests/data/wrong_duplicate_eqpt_ila_reverse.xlsx
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								tests/data/wrong_duplicate_eqpt_ila_reverse.xlsx
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								tests/data/wrong_duplicate_link_reverse.xlsx
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								tests/data/wrong_duplicate_link_reverse.xlsx
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								tests/data/wrong_node_type.xlsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								tests/data/wrong_node_type.xlsx
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								tests/data/wrong_service.xlsx
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								tests/data/wrong_service.xlsx
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								tests/data/wrong_service_type.xlsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								tests/data/wrong_service_type.xlsx
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								tests/data/wrong_topo_bad_eqpt.xlsx
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								tests/data/wrong_topo_bad_eqpt.xlsx
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								tests/data/wrong_topo_duplicate_eqpt.xlsx
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								tests/data/wrong_topo_duplicate_eqpt.xlsx
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								tests/data/wrong_topo_duplicate_node.xlsx
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								tests/data/wrong_topo_duplicate_node.xlsx
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								tests/data/wrong_topo_eqpt.xlsx
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								tests/data/wrong_topo_eqpt.xlsx
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								tests/data/wrong_topo_link.xlsx
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								tests/data/wrong_topo_link.xlsx
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								tests/data/wrong_topo_link_header.xlsx
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								tests/data/wrong_topo_link_header.xlsx
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								tests/data/wrong_topo_node.xlsx
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								tests/data/wrong_topo_node.xlsx
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										37
									
								
								tests/invocation/logs_path_request
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								tests/invocation/logs_path_request
									
									
									
									
									
										Normal 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'] | ||||||
							
								
								
									
										13
									
								
								tests/invocation/logs_path_requests_run_CD_PMD_PDL_missing
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								tests/invocation/logs_path_requests_run_CD_PMD_PDL_missing
									
									
									
									
									
										Normal 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 | ||||||
							
								
								
									
										307
									
								
								tests/invocation/logs_transmission_saturated
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										307
									
								
								tests/invocation/logs_transmission_saturated
									
									
									
									
									
										Normal 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 | ||||||
|  |  | ||||||
| @@ -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): [1;36;40m18.90 dB[0m |   Final GSNR (0.1 nm): [1;36;40m18.89 dB[0m | ||||||
|  |  | ||||||
| (No source node specified: picked trx_Stockholm) | (No source node specified: picked trx_Stockholm) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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): [1;36;40m19.27 dB[0m |   Final GSNR (0.1 nm): [1;36;40m19.25 dB[0m | ||||||
|  |  | ||||||
| (No source node specified: picked trx_Stockholm) | (No source node specified: picked trx_Stockholm) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -106,48 +106,13 @@ | |||||||
| ] | ] | ||||||
| [1;34;40mComputing all paths with constraints[0m | [1;34;40mComputing all paths with constraints[0m | ||||||
| [1;34;40mPropagating on selected path[0m | [1;34;40mPropagating on selected path[0m | ||||||
| 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'] |  | ||||||
|  |  | ||||||
| [1;34;40mResult summary[0m | [1;34;40mResult summary[0m | ||||||
| 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])       | ||||||
| [1;33;40mResult summary shows mean GSNR and OSNR (average over all channels)[0m | [1;33;40mResult summary shows mean GSNR and OSNR (average over all channels)[0m | ||||||
|   | |||||||
							
								
								
									
										24
									
								
								tests/invocation/path_requests_run_CD_PMD_PDL_missing
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								tests/invocation/path_requests_run_CD_PMD_PDL_missing
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | |||||||
|  | [1;34;40mList of disjunctions[0m | ||||||
|  | [] | ||||||
|  | [1;34;40mAggregating similar requests[0m | ||||||
|  | [1;34;40mThe following services have been requested:[0m | ||||||
|  | [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:	[] | ||||||
|  | ] | ||||||
|  | [1;34;40mComputing all paths with constraints[0m | ||||||
|  | [1;34;40mPropagating on selected path[0m | ||||||
|  | [1;34;40mResult summary[0m | ||||||
|  | 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     | ||||||
|  | [1;33;40mResult summary shows mean GSNR and OSNR (average over all channels)[0m | ||||||
							
								
								
									
										102
									
								
								tests/invocation/spectrum1_transmission_main_example
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								tests/invocation/spectrum1_transmission_main_example
									
									
									
									
									
										Normal 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 = [1;36;40m0.00 dBm[0m: | ||||||
|  | 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): [1;36;40m23.61 dB[0m | ||||||
|  |  | ||||||
|  | (No source node specified: picked trx Lannion_CAS) | ||||||
|  |  | ||||||
|  | (No destination node specified: picked trx Lorient_KMA) | ||||||
							
								
								
									
										165
									
								
								tests/invocation/spectrum2_transmission_main_example
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										165
									
								
								tests/invocation/spectrum2_transmission_main_example
									
									
									
									
									
										Normal 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 = [1;36;40m0.00 dBm[0m: | ||||||
|  | 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): [1;36;40m23.72 dB[0m | ||||||
|  |  | ||||||
|  | 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) | ||||||
| @@ -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): [1;36;40m31.17 dB[0m |   Final GSNR (0.1 nm): [1;36;40m31.18 dB[0m | ||||||
|  |  | ||||||
| (No source node specified: picked Site_A) | (No source node specified: picked Site_A) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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): [1;36;40m31.44 dB[0m |   Final GSNR (0.1 nm): [1;36;40m31.42 dB[0m | ||||||
|  |  | ||||||
| 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) | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										455
									
								
								tests/invocation/transmission_main_example_long
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										455
									
								
								tests/invocation/transmission_main_example_long
									
									
									
									
									
										Normal 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 = [1;36;40m0.00 dBm[0m: | ||||||
|  | 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): [1;36;40m17.84 dB[0m | ||||||
|  |  | ||||||
|  | (No source node specified: picked Site_A) | ||||||
|  |  | ||||||
|  | (No destination node specified: picked Site_B) | ||||||
| @@ -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 | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING[0m: 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. |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING[0m: 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. |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING[0m: 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. |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING[0m: 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. |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING:[0m 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 |  | ||||||
|  |  | ||||||
| [1;31;40mWARNING:[0m 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): [1;36;40m23.94 dB[0m |   Final GSNR (0.1 nm): [1;36;40m23.93 dB[0m | ||||||
|  |  | ||||||
| (Invalid source node 'lannion' replaced with trx Lannion_CAS) | (Invalid source node 'lannion' replaced with trx Lannion_CAS) | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										7
									
								
								tests/requirements.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								tests/requirements.txt
									
									
									
									
									
										Normal 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 | ||||||
| @@ -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) | ||||||
|   | |||||||
| @@ -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
									
								
							
							
						
						
									
										837
									
								
								tests/test_equalization.py
									
									
									
									
									
										Normal 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) | ||||||
| @@ -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)) | ||||||
|   | |||||||
| @@ -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
									
								
							
							
						
						
									
										422
									
								
								tests/test_logger.py
									
									
									
									
									
										Normal 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 | ||||||
| @@ -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) | ||||||
|   | |||||||
| @@ -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'] | ||||||
|   | |||||||
| @@ -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) | ||||||
|   | |||||||
| @@ -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) | ||||||
|   | |||||||
| @@ -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) | ||||||
|   | |||||||
| @@ -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([]) | ||||||
|   | |||||||
							
								
								
									
										6
									
								
								tox.ini
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								tox.ini
									
									
									
									
									
								
							| @@ -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 | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user