mirror of
https://github.com/Telecominfraproject/oopt-gnpy.git
synced 2025-10-30 17:47:50 +00:00
Compare commits
66 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e99b9c286c | ||
|
|
8c3ffdfd4e | ||
|
|
a4c7395cfe | ||
|
|
398124e841 | ||
|
|
07cc3fc079 | ||
|
|
27bae162d6 | ||
|
|
d4392e5a7a | ||
|
|
a0aab0918a | ||
|
|
2461385a94 | ||
|
|
ba06a0e104 | ||
|
|
48f9c448e4 | ||
|
|
2e0d01bc0b | ||
|
|
0d3a86f1d8 | ||
|
|
a30cd0f721 | ||
|
|
1491c2361f | ||
|
|
ca7b993d95 | ||
|
|
8c75c4f9d7 | ||
|
|
b730b1a4f4 | ||
|
|
a7d3c00e5b | ||
|
|
9146290ecd | ||
|
|
3fae7210d8 | ||
|
|
002f1dfa36 | ||
|
|
b3c1e6af95 | ||
|
|
58ac717f8d | ||
|
|
f193fb261a | ||
|
|
55d8d23b25 | ||
|
|
ca642e3dfc | ||
|
|
bfb7b466eb | ||
|
|
6467cb5819 | ||
|
|
ba215d8a07 | ||
|
|
4dc0913825 | ||
|
|
fedebc7038 | ||
|
|
b42715f003 | ||
|
|
48ae4252db | ||
|
|
0b4dd58c2a | ||
|
|
81b863122d | ||
|
|
732749d459 | ||
|
|
014e5fd966 | ||
|
|
dc7a459697 | ||
|
|
7f378e5479 | ||
|
|
d91e279294 | ||
|
|
c5abc4109f | ||
|
|
c8ce640a2a | ||
|
|
029877604e | ||
|
|
7ee1ad2a92 | ||
|
|
24f3e135ad | ||
|
|
a5718911c5 | ||
|
|
660d9c8c49 | ||
|
|
2ec50c4e07 | ||
|
|
32b4eda3f9 | ||
|
|
d5f5ee5595 | ||
|
|
f0545c57a8 | ||
|
|
815f4d2810 | ||
|
|
bd474151ab | ||
|
|
2c585faef6 | ||
|
|
b15be2cf0d | ||
|
|
3cc98ae388 | ||
|
|
09d1dbf927 | ||
|
|
cda7f5d50b | ||
|
|
1047bbc37c | ||
|
|
b1cb759164 | ||
|
|
2640912baa | ||
|
|
8676daed3a | ||
|
|
db31986d28 | ||
|
|
7823eca871 | ||
|
|
572d7d6999 |
@@ -1,21 +0,0 @@
|
||||
# http://editorconfig.org
|
||||
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
|
||||
[*.bat]
|
||||
indent_style = tab
|
||||
end_of_line = crlf
|
||||
|
||||
[LICENSE]
|
||||
insert_final_newline = false
|
||||
|
||||
[Makefile]
|
||||
indent_style = tab
|
||||
15
.github/ISSUE_TEMPLATE.md
vendored
15
.github/ISSUE_TEMPLATE.md
vendored
@@ -1,15 +0,0 @@
|
||||
* gnpy version:
|
||||
* Python version:
|
||||
* Operating System:
|
||||
|
||||
### Description
|
||||
|
||||
Describe what you were trying to get done.
|
||||
Tell us what happened, what went wrong, and what you expected to happen.
|
||||
|
||||
### What I Did
|
||||
|
||||
```
|
||||
Paste the command(s) you ran and the output.
|
||||
If there was a crash, please include the traceback here.
|
||||
```
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -60,3 +60,6 @@ target/
|
||||
|
||||
# pyenv python configuration file
|
||||
.python-version
|
||||
|
||||
# MacOS DS_store
|
||||
.DS_Store
|
||||
|
||||
34
.travis.yml
34
.travis.yml
@@ -1,29 +1,9 @@
|
||||
# Config file for automatic testing at travis-ci.org
|
||||
# This file will be regenerated if you run travis_pypi_setup.py
|
||||
|
||||
language: python
|
||||
python:
|
||||
- 3.5
|
||||
- 3.4
|
||||
- 3.3
|
||||
- 2.7
|
||||
- 2.6
|
||||
|
||||
# command to install dependencies, e.g. pip install -r requirements.txt --use-mirrors
|
||||
install: pip install -U tox-travis
|
||||
|
||||
# command to run tests, e.g. python setup.py test
|
||||
script: tox
|
||||
|
||||
# After you create the Github repo and add it to Travis, run the
|
||||
# travis_pypi_setup.py script to finish PyPI deployment setup
|
||||
deploy:
|
||||
provider: pypi
|
||||
distributions: sdist bdist_wheel
|
||||
user: <TBD>
|
||||
password:
|
||||
secure: PLEASE_REPLACE_ME
|
||||
on:
|
||||
tags: true
|
||||
repo: <TBD>/gnpy
|
||||
python: 2.7
|
||||
- "3.6"
|
||||
# command to install dependencies
|
||||
install:
|
||||
- pip install -r requirements.txt
|
||||
# command to run tests
|
||||
script:
|
||||
- pytest
|
||||
|
||||
13
AUTHORS.rst
13
AUTHORS.rst
@@ -1,13 +0,0 @@
|
||||
=======
|
||||
Credits
|
||||
=======
|
||||
|
||||
Development Lead
|
||||
----------------
|
||||
|
||||
* <TBD> <<TBD>@<TBD>.com>
|
||||
|
||||
Contributors
|
||||
------------
|
||||
|
||||
None yet. Why not be the first?
|
||||
114
CONTRIBUTING.rst
114
CONTRIBUTING.rst
@@ -1,114 +0,0 @@
|
||||
.. highlight:: shell
|
||||
|
||||
============
|
||||
Contributing
|
||||
============
|
||||
|
||||
Contributions are welcome, and they are greatly appreciated! Every
|
||||
little bit helps, and credit will always be given.
|
||||
|
||||
You can contribute in many ways:
|
||||
|
||||
Types of Contributions
|
||||
----------------------
|
||||
|
||||
Report Bugs
|
||||
~~~~~~~~~~~
|
||||
|
||||
Report bugs at https://github.com/<TBD>/gnpy/issues.
|
||||
|
||||
If you are reporting a bug, please include:
|
||||
|
||||
* Your operating system name and version.
|
||||
* Any details about your local setup that might be helpful in troubleshooting.
|
||||
* Detailed steps to reproduce the bug.
|
||||
|
||||
Fix Bugs
|
||||
~~~~~~~~
|
||||
|
||||
Look through the GitHub issues for bugs. Anything tagged with "bug"
|
||||
and "help wanted" is open to whoever wants to implement it.
|
||||
|
||||
Implement Features
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Look through the GitHub issues for features. Anything tagged with "enhancement"
|
||||
and "help wanted" is open to whoever wants to implement it.
|
||||
|
||||
Write Documentation
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
gnpy could always use more documentation, whether as part of the
|
||||
official gnpy docs, in docstrings, or even on the web in blog posts,
|
||||
articles, and such.
|
||||
|
||||
Submit Feedback
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
The best way to send feedback is to file an issue at https://github.com/<TBD>/gnpy/issues.
|
||||
|
||||
If you are proposing a feature:
|
||||
|
||||
* Explain in detail how it would work.
|
||||
* Keep the scope as narrow as possible, to make it easier to implement.
|
||||
* Remember that this is a volunteer-driven project, and that contributions
|
||||
are welcome :)
|
||||
|
||||
Get Started!
|
||||
------------
|
||||
|
||||
Ready to contribute? Here's how to set up `gnpy` for local development.
|
||||
|
||||
1. Fork the `gnpy` repo on GitHub.
|
||||
2. Clone your fork locally::
|
||||
|
||||
$ git clone git@github.com:your_name_here/gnpy.git
|
||||
|
||||
3. Install your local copy into a virtualenv. Assuming you have virtualenvwrapper installed, this is how you set up your fork for local development::
|
||||
|
||||
$ mkvirtualenv gnpy
|
||||
$ cd gnpy/
|
||||
$ python setup.py develop
|
||||
|
||||
4. Create a branch for local development::
|
||||
|
||||
$ git checkout -b name-of-your-bugfix-or-feature
|
||||
|
||||
Now you can make your changes locally.
|
||||
|
||||
5. When you're done making changes, check that your changes pass flake8 and the tests, including testing other Python versions with tox::
|
||||
|
||||
$ flake8 gnpy tests
|
||||
$ python setup.py test or py.test
|
||||
$ tox
|
||||
|
||||
To get flake8 and tox, just pip install them into your virtualenv.
|
||||
|
||||
6. Commit your changes and push your branch to GitHub::
|
||||
|
||||
$ git add .
|
||||
$ git commit -m "Your detailed description of your changes."
|
||||
$ git push origin name-of-your-bugfix-or-feature
|
||||
|
||||
7. Submit a pull request through the GitHub website.
|
||||
|
||||
Pull Request Guidelines
|
||||
-----------------------
|
||||
|
||||
Before you submit a pull request, check that it meets these guidelines:
|
||||
|
||||
1. The pull request should include tests.
|
||||
2. If the pull request adds functionality, the docs should be updated. Put
|
||||
your new functionality into a function with a docstring, and add the
|
||||
feature to the list in README.rst.
|
||||
3. The pull request should work for Python 2.6, 2.7, 3.3, 3.4 and 3.5, and for PyPy. Check
|
||||
https://travis-ci.org/<TBD>/gnpy/pull_requests
|
||||
and make sure that the tests pass for all supported Python versions.
|
||||
|
||||
Tips
|
||||
----
|
||||
|
||||
To run a subset of tests::
|
||||
|
||||
$ py.test tests.test_gnpy
|
||||
|
||||
17
Contributors.md
Normal file
17
Contributors.md
Normal file
@@ -0,0 +1,17 @@
|
||||
Contributors in alphabetical order
|
||||
==================================
|
||||
|
||||
Name | Surname | Affiliation | Contact
|
||||
-----|---------|-------------|--------
|
||||
Alessio | Ferrari | Politecnico di Torino | alessio.ferrari@polito.it
|
||||
Brian | Taylor | Facebook | briantaylor@fb.com
|
||||
David | Boertjes | Ciena | dboertje@ciena.com
|
||||
Esther | Le Rouzic | Orange | esther.lerouzic@orange.com
|
||||
Gabriele | Galimberti | Cisco | ggalimbe@cisco.com
|
||||
Gert | Grammel | Juniper Networks | ggrammel@juniper.net
|
||||
Gilad | Goldfarb | Facebook | giladg@fb.com
|
||||
James | Powell | Consultant | james@dontusethiscode.com
|
||||
Jeanluc | Auge | Orange | jeanluc.auge@orange.com
|
||||
Liu | Xufeng | Jabil | Xufeng_Liu@jabil.com
|
||||
Mattia | Cantono | Politecnico di Torino | mattia.cantono@polito.it
|
||||
Vittorio | Curri | Politecnico di Torino | vittorio.curri@polito.it
|
||||
@@ -1,8 +0,0 @@
|
||||
=======
|
||||
History
|
||||
=======
|
||||
|
||||
0.1.0 (2017-06-29)
|
||||
------------------
|
||||
|
||||
* First release on PyPI.
|
||||
40
LICENSE
40
LICENSE
@@ -1,31 +1,29 @@
|
||||
BSD 3-Clause License
|
||||
|
||||
BSD License
|
||||
|
||||
Copyright (c) 2017, <TBD>
|
||||
Copyright (c) 2018, Telecom Infra Project
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
11
MANIFEST.in
11
MANIFEST.in
@@ -1,11 +0,0 @@
|
||||
include AUTHORS.rst
|
||||
include CONTRIBUTING.rst
|
||||
include HISTORY.rst
|
||||
include LICENSE
|
||||
include README.rst
|
||||
|
||||
recursive-include tests *
|
||||
recursive-exclude * __pycache__
|
||||
recursive-exclude * *.py[co]
|
||||
|
||||
recursive-include docs *.rst conf.py Makefile make.bat *.jpg *.png *.gif
|
||||
87
Makefile
87
Makefile
@@ -1,87 +0,0 @@
|
||||
.PHONY: clean clean-test clean-pyc clean-build docs help
|
||||
.DEFAULT_GOAL := help
|
||||
define BROWSER_PYSCRIPT
|
||||
import os, webbrowser, sys
|
||||
try:
|
||||
from urllib import pathname2url
|
||||
except:
|
||||
from urllib.request import pathname2url
|
||||
|
||||
webbrowser.open("file://" + pathname2url(os.path.abspath(sys.argv[1])))
|
||||
endef
|
||||
export BROWSER_PYSCRIPT
|
||||
|
||||
define PRINT_HELP_PYSCRIPT
|
||||
import re, sys
|
||||
|
||||
for line in sys.stdin:
|
||||
match = re.match(r'^([a-zA-Z_-]+):.*?## (.*)$$', line)
|
||||
if match:
|
||||
target, help = match.groups()
|
||||
print("%-20s %s" % (target, help))
|
||||
endef
|
||||
export PRINT_HELP_PYSCRIPT
|
||||
BROWSER := python -c "$$BROWSER_PYSCRIPT"
|
||||
|
||||
help:
|
||||
@python -c "$$PRINT_HELP_PYSCRIPT" < $(MAKEFILE_LIST)
|
||||
|
||||
clean: clean-build clean-pyc clean-test ## remove all build, test, coverage and Python artifacts
|
||||
|
||||
|
||||
clean-build: ## remove build artifacts
|
||||
rm -fr build/
|
||||
rm -fr dist/
|
||||
rm -fr .eggs/
|
||||
find . -name '*.egg-info' -exec rm -fr {} +
|
||||
find . -name '*.egg' -exec rm -f {} +
|
||||
|
||||
clean-pyc: ## remove Python file artifacts
|
||||
find . -name '*.pyc' -exec rm -f {} +
|
||||
find . -name '*.pyo' -exec rm -f {} +
|
||||
find . -name '*~' -exec rm -f {} +
|
||||
find . -name '__pycache__' -exec rm -fr {} +
|
||||
|
||||
clean-test: ## remove test and coverage artifacts
|
||||
rm -fr .tox/
|
||||
rm -f .coverage
|
||||
rm -fr htmlcov/
|
||||
|
||||
lint: ## check style with flake8
|
||||
flake8 gnpy tests
|
||||
|
||||
test: ## run tests quickly with the default Python
|
||||
py.test
|
||||
|
||||
|
||||
test-all: ## run tests on every Python version with tox
|
||||
tox
|
||||
|
||||
coverage: ## check code coverage quickly with the default Python
|
||||
coverage run --source gnpy -m pytest
|
||||
coverage report -m
|
||||
coverage html
|
||||
$(BROWSER) htmlcov/index.html
|
||||
|
||||
docs: ## generate Sphinx HTML documentation, including API docs
|
||||
rm -f docs/gnpy.rst
|
||||
rm -f docs/modules.rst
|
||||
sphinx-apidoc -o docs/ gnpy
|
||||
$(MAKE) -C docs clean
|
||||
$(MAKE) -C docs html
|
||||
$(BROWSER) docs/_build/html/index.html
|
||||
|
||||
servedocs: docs ## compile the docs watching for changes
|
||||
watchmedo shell-command -p '*.rst' -c '$(MAKE) -C docs html' -R -D .
|
||||
|
||||
release: clean ## package and upload a release
|
||||
python setup.py sdist upload
|
||||
python setup.py bdist_wheel upload
|
||||
|
||||
dist: clean ## builds source and wheel package
|
||||
python setup.py sdist
|
||||
python setup.py bdist_wheel
|
||||
ls -l dist
|
||||
|
||||
install: clean ## install the package to the active Python's site-packages
|
||||
python setup.py install
|
||||
193
README.rst
193
README.rst
@@ -1,32 +1,191 @@
|
||||
====
|
||||
gnpy
|
||||
`gnpy`: mesh optical network route planning and optimization library
|
||||
====
|
||||
|
||||
|docs| |build|
|
||||
|
||||
.. image:: https://img.shields.io/pypi/v/gnpy.svg
|
||||
:target: https://pypi.python.org/pypi/gnpy
|
||||
**gnpy is an open-source, community-developed library for building route planning
|
||||
and optimization tools in real-world mesh optical networks.**
|
||||
|
||||
.. image:: https://img.shields.io/travis/<TBD>/gnpy.svg
|
||||
:target: https://travis-ci.org/<TBD>/gnpy
|
||||
`gnpy <http://github.com/telecominfraproject/gnpy>`_ is:
|
||||
|
||||
.. image:: https://readthedocs.org/projects/gnpy/badge/?version=latest
|
||||
:target: https://gnpy.readthedocs.io/en/latest/?badge=latest
|
||||
:alt: Documentation Status
|
||||
- a sponsored project of the `OOPT/PSE <http://telecominfraproject.com/project-groups-2/backhaul-projects/open-optical-packet-transport/>`_ working group of the `Telecom Infra Project <http://telecominfraproject.com>`_.
|
||||
- fully community-driven, fully open source library
|
||||
- driven by a consortium of operators, vendors, and academic researchers
|
||||
- intended for rapid development of production-grade route planning tools
|
||||
- easily extensible to include custom network elements
|
||||
- performant to the scale of real-world mesh optical networks
|
||||
|
||||
.. image:: https://pyup.io/repos/github/<TBD>/gnpy/shield.svg
|
||||
:target: https://pyup.io/repos/github/<TBD>/gnpy/
|
||||
:alt: Updates
|
||||
Documentation: https://gnpy.readthedocs.io
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
``gnpy`` is hosted in the `Python Package Index <http://pypi.org/>`_ (`gnpy <https://pypi.org/project/gnpy/>`_). It can be installed via:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ pip install gnpy
|
||||
|
||||
It can also be installed directly from the repo.
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ git clone https://github.com/telecominfraproject/gnpy
|
||||
$ cd gnpy
|
||||
$ python setup.py install
|
||||
|
||||
Both approaches above will handle installing any additional software dependencies.
|
||||
|
||||
**Note**: *We recommend the use of the Anaconda Python distribution
|
||||
(https://www.anaconda.com/download) which comes with many scientific
|
||||
computing dependencies pre-installed.*
|
||||
|
||||
Instructions for Use
|
||||
--------------------
|
||||
|
||||
``gnpy`` is a library for building route planning and optimization tools.
|
||||
|
||||
It ships with a number of example programs. Release versions will ship with
|
||||
fully-functional programs.
|
||||
|
||||
|
||||
Gaussian Noise (GN) modeling library
|
||||
**Note**: *If you are a network operator or involved in route planning and
|
||||
optimization for your organization, please contact project maintainer James
|
||||
Powell <james.powell@telecominfraproject>. gnpy is looking for users with
|
||||
specific, delineated use cases to drive requirements for future
|
||||
development.*
|
||||
|
||||
|
||||
* Free software: BSD license
|
||||
* Documentation: https://gnpy.readthedocs.io.
|
||||
**To get started, run the transmission example:**
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
Features
|
||||
--------
|
||||
$ python examples/transmission_main_example.py
|
||||
|
||||
* TODO
|
||||
By default, this script operates on a single span network defined in `examples/edfa/edfa_example_network.json <examples/edfa/edfa_example_network.json>`_
|
||||
|
||||
You can specify a different network at the command line as follows. For
|
||||
example, to use the CORONET Continental US (CONUS) network defined in `examples/coronet_conus_example.json <examples/coronet_conus_example.json>`_:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ python examples/transmission_main_example.py examples/coronet_conus_example.json
|
||||
|
||||
This script will calculate the average signal osnr and snr across 93 network
|
||||
elements (transceiver, ROADMs, fibers, and amplifiers) between Abilene, Texas
|
||||
and Albany, New York.
|
||||
|
||||
This script calculates the average signal OSNR = |OSNR| and SNR = |SNR|.
|
||||
|
||||
.. |OSNR| replace:: P\ :sub:`ch`\ /P\ :sub:`ase`
|
||||
.. |SNR| replace:: P\ :sub:`ch`\ /(P\ :sub:`nli`\ +\ P\ :sub:`ase`)
|
||||
|
||||
|Pase| is the amplified spontaneous emission noise, and |Pnli| the non-linear
|
||||
interference noise.
|
||||
|
||||
.. |Pase| replace:: P\ :sub:`ase`
|
||||
.. |Pnli| replace:: P\ :sub:`nli`
|
||||
|
||||
The `transmission_main_example.py <examples/transmission_main_example.py>`_
|
||||
script propagates a specrum of 96 channels at 32 Gbaud, 50 GHz spacing and 0
|
||||
dBm/channel. These are not yet parametrized but can be modified directly in the
|
||||
script (via the SpectralInformation tuple) to accomodate any baud rate,
|
||||
spacing, power or channel count demand.
|
||||
|
||||
The amplifier's gain is set to exactly compsenate for the loss in each network
|
||||
element. The amplifier is currently defined with gain range of 15 dB to 25 dB
|
||||
and 21 dBm max output power. Ripple and NF models are defined in
|
||||
`examples/edfa_config.json <examples/edfa_config.json>`_
|
||||
|
||||
Contributing
|
||||
------------
|
||||
|
||||
``gnpy`` is looking for additional contributors, especially those with experience
|
||||
planning and maintaining large-scale, real-world mesh optical networks.
|
||||
|
||||
To get involved, please contact James Powell
|
||||
<james.powell@telecominfraproject.com> or Gert Grammel <ggrammel@juniper.net>.
|
||||
|
||||
``gnpy`` contributions are currently limited to members of `TIP
|
||||
<http://telecominfraproject.com>`_. Membership is free and open to all.
|
||||
|
||||
See the `Onboarding Guide
|
||||
<https://github.com/Telecominfraproject/gnpy/wiki/Onboarding-Guide>`_ for
|
||||
specific details on code contribtions.
|
||||
|
||||
See `AUTHORS.Md <AUTHORS.Md>`_ for past and present contributors.
|
||||
|
||||
Project Background
|
||||
------------------
|
||||
|
||||
Data Centers are built upon interchangeable, highly standardized node and
|
||||
network architectures rather than a sum of isolated solutions. This also
|
||||
translates to optical networking. It leads to a push in enabling multi-vendor
|
||||
optical network by disaggregating HW and SW functions and focussing on
|
||||
interoperability. In this paradigm, the burden of responsibility for ensuring
|
||||
the performance of such disaggregated open optical systems falls on the
|
||||
operators. Consequently, operators and vendors are collaborating in defining
|
||||
control models that can be readily used by off-the-shelf controllers. However,
|
||||
node and network models are only part of the answer. To take reasonable
|
||||
decisions, controllers need to incorporate logic to simulate and assess optical
|
||||
performance. Hence, a vendor-independent optical quality estimator is required.
|
||||
Given its vendor-agnostic nature, such an estimator needs to be driven by a
|
||||
consortium of operators, system and component suppliers.
|
||||
|
||||
Founded in February 2016, the Telecom Infra Project (TIP) is an
|
||||
engineering-focused initiative which is operator driven, but features
|
||||
collaboration across operators, suppliers, developers, integrators, and
|
||||
startups with the goal of disaggregating the traditional network deployment
|
||||
approach. The group’s ultimate goal is to help provide better connectivity for
|
||||
communities all over the world as more people come on-line and demand more
|
||||
bandwidth- intensive experiences like video, virtual reality and augmented
|
||||
reality.
|
||||
|
||||
Within TIP, the Open Optical Packet Transport (OOPT) project group is chartered
|
||||
with unbundling monolithic packet-optical network technologies in order to
|
||||
unlock innovation and support new, more flexible connectivity paradigms.
|
||||
|
||||
The key to unbundling is the ability to accurately plan and predict the
|
||||
performance of optical line systems based on an accurate simulation of optical
|
||||
parameters. Under that OOPT umbrella, the Physical Simulation Environment (PSE)
|
||||
working group set out to disrupt the planning landscape by providing an open
|
||||
source simulation model which can be used freely across multiple vendor
|
||||
implementations.
|
||||
|
||||
.. |docs| image:: https://readthedocs.org/projects/gnpy/badge/?version=develop
|
||||
:target: http://gnpy.readthedocs.io/en/develop/?badge=develop
|
||||
:alt: Documentation Status
|
||||
:scale: 100%
|
||||
|
||||
.. |build| image:: https://travis-ci.org/mcantono/gnpy.svg?branch=develop
|
||||
:target: https://travis-ci.org/mcantono/gnpy
|
||||
:alt: Build Status
|
||||
:scale: 100%
|
||||
|
||||
TIP OOPT/PSE & PSE WG Charter
|
||||
-----------------------------
|
||||
|
||||
We believe that openly sharing ideas, specifications, and other intellectual
|
||||
property is the key to maximizing innovation and reducing complexity
|
||||
|
||||
TIP OOPT/PSE's goal is to build an end-to-end simulation environment which
|
||||
defines the network models of the optical device transfer functions and their
|
||||
parameters. This environment will provide validation of the optical
|
||||
performance requirements for the TIP OLS building blocks.
|
||||
|
||||
- The model may be approximate or complete depending on the network complexity.
|
||||
Each model shall be validated against the proposed network scenario.
|
||||
- The environment must be able to process network models from multiple vendors,
|
||||
and also allow users to pick any implementation in an open source framework.
|
||||
- The PSE will influence and benefit from the innovation of the DTC, API, and
|
||||
OLS working groups.
|
||||
- The PSE represents a step along the journey towards multi-layer optimization.
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
``gnpy`` is distributed under a standard BSD 3-Clause License.
|
||||
|
||||
See `LICENSE <LICENSE>`_ for more details.
|
||||
|
||||
|
||||
17
contributors.md
Normal file
17
contributors.md
Normal file
@@ -0,0 +1,17 @@
|
||||
Contributors in alphabetical order
|
||||
==================================
|
||||
|
||||
Name | Surname | Affiliation | Contact
|
||||
-----|---------|-------------|--------
|
||||
Alessio | Ferrari | Politecnico di Torino | alessio.ferrari@polito.it
|
||||
Brian | Taylor | Facebook | briantaylor@fb.com
|
||||
David | Boertjes | Ciena | dboertje@ciena.com
|
||||
Esther | Le Rouzic | Orange | esther.lerouzic@orange.com
|
||||
Gabriele | Galimberti | Cisco | ggalimbe@cisco.com
|
||||
Gert | Grammel | Juniper Networks | ggrammel@juniper.net
|
||||
Gilad | Goldfarb | Facebook | giladg@fb.com
|
||||
James | Powell | Consultant | james@dontusethiscode.com
|
||||
Jeanluc | Auge | Orange | jeanluc.auge@orange.com
|
||||
Liu | Xufeng | Jabil | Xufeng_Liu@jabil.com
|
||||
Mattia | Cantono | Politecnico di Torino | mattia.cantono@polito.it
|
||||
Vittorio | Curri | Politecnico di Torino | vittorio.curri@polito.it
|
||||
3
docs/.gitignore
vendored
3
docs/.gitignore
vendored
@@ -1,3 +0,0 @@
|
||||
/gnpy.rst
|
||||
/gnpy.*.rst
|
||||
/modules.rst
|
||||
179
docs/Makefile
179
docs/Makefile
@@ -1,177 +1,20 @@
|
||||
# Makefile for Sphinx documentation
|
||||
# Minimal makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
# You can set these variables from the command line.
|
||||
SPHINXOPTS =
|
||||
SPHINXBUILD = sphinx-build
|
||||
PAPER =
|
||||
SPHINXBUILD = python -msphinx
|
||||
SPHINXPROJ = GNpy
|
||||
SOURCEDIR = .
|
||||
BUILDDIR = _build
|
||||
|
||||
# User-friendly check for sphinx-build
|
||||
ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
|
||||
$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
|
||||
endif
|
||||
|
||||
# Internal variables.
|
||||
PAPEROPT_a4 = -D latex_paper_size=a4
|
||||
PAPEROPT_letter = -D latex_paper_size=letter
|
||||
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
|
||||
# the i18n builder cannot share the environment and doctrees with the others
|
||||
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
|
||||
|
||||
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
|
||||
|
||||
# Put it first so that "make" without argument is like "make help".
|
||||
help:
|
||||
@echo "Please use \`make <target>' where <target> is one of"
|
||||
@echo " html to make standalone HTML files"
|
||||
@echo " dirhtml to make HTML files named index.html in directories"
|
||||
@echo " singlehtml to make a single large HTML file"
|
||||
@echo " pickle to make pickle files"
|
||||
@echo " json to make JSON files"
|
||||
@echo " htmlhelp to make HTML files and a HTML help project"
|
||||
@echo " qthelp to make HTML files and a qthelp project"
|
||||
@echo " devhelp to make HTML files and a Devhelp project"
|
||||
@echo " epub to make an epub"
|
||||
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
|
||||
@echo " latexpdf to make LaTeX files and run them through pdflatex"
|
||||
@echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
|
||||
@echo " text to make text files"
|
||||
@echo " man to make manual pages"
|
||||
@echo " texinfo to make Texinfo files"
|
||||
@echo " info to make Texinfo files and run them through makeinfo"
|
||||
@echo " gettext to make PO message catalogs"
|
||||
@echo " changes to make an overview of all changed/added/deprecated items"
|
||||
@echo " xml to make Docutils-native XML files"
|
||||
@echo " pseudoxml to make pseudoxml-XML files for display purposes"
|
||||
@echo " linkcheck to check all external links for integrity"
|
||||
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
|
||||
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
|
||||
clean:
|
||||
rm -rf $(BUILDDIR)/*
|
||||
.PHONY: help Makefile
|
||||
|
||||
html:
|
||||
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
|
||||
|
||||
dirhtml:
|
||||
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
|
||||
|
||||
singlehtml:
|
||||
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
|
||||
@echo
|
||||
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
|
||||
|
||||
pickle:
|
||||
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
|
||||
@echo
|
||||
@echo "Build finished; now you can process the pickle files."
|
||||
|
||||
json:
|
||||
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
|
||||
@echo
|
||||
@echo "Build finished; now you can process the JSON files."
|
||||
|
||||
htmlhelp:
|
||||
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
|
||||
@echo
|
||||
@echo "Build finished; now you can run HTML Help Workshop with the" \
|
||||
".hhp project file in $(BUILDDIR)/htmlhelp."
|
||||
|
||||
qthelp:
|
||||
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
|
||||
@echo
|
||||
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
|
||||
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
|
||||
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/gnpy.qhcp"
|
||||
@echo "To view the help file:"
|
||||
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/gnpy.qhc"
|
||||
|
||||
devhelp:
|
||||
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
|
||||
@echo
|
||||
@echo "Build finished."
|
||||
@echo "To view the help file:"
|
||||
@echo "# mkdir -p $$HOME/.local/share/devhelp/gnpy"
|
||||
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/gnpy"
|
||||
@echo "# devhelp"
|
||||
|
||||
epub:
|
||||
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
|
||||
@echo
|
||||
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
|
||||
|
||||
latex:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo
|
||||
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
|
||||
@echo "Run \`make' in that directory to run these through (pdf)latex" \
|
||||
"(use \`make latexpdf' here to do that automatically)."
|
||||
|
||||
latexpdf:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo "Running LaTeX files through pdflatex..."
|
||||
$(MAKE) -C $(BUILDDIR)/latex all-pdf
|
||||
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
|
||||
|
||||
latexpdfja:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo "Running LaTeX files through platex and dvipdfmx..."
|
||||
$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
|
||||
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
|
||||
|
||||
text:
|
||||
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
|
||||
@echo
|
||||
@echo "Build finished. The text files are in $(BUILDDIR)/text."
|
||||
|
||||
man:
|
||||
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
|
||||
@echo
|
||||
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
|
||||
|
||||
texinfo:
|
||||
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
|
||||
@echo
|
||||
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
|
||||
@echo "Run \`make' in that directory to run these through makeinfo" \
|
||||
"(use \`make info' here to do that automatically)."
|
||||
|
||||
info:
|
||||
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
|
||||
@echo "Running Texinfo files through makeinfo..."
|
||||
make -C $(BUILDDIR)/texinfo info
|
||||
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
|
||||
|
||||
gettext:
|
||||
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
|
||||
@echo
|
||||
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
|
||||
|
||||
changes:
|
||||
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
|
||||
@echo
|
||||
@echo "The overview file is in $(BUILDDIR)/changes."
|
||||
|
||||
linkcheck:
|
||||
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
|
||||
@echo
|
||||
@echo "Link check complete; look for any errors in the above output " \
|
||||
"or in $(BUILDDIR)/linkcheck/output.txt."
|
||||
|
||||
doctest:
|
||||
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
|
||||
@echo "Testing of doctests in the sources finished, look at the " \
|
||||
"results in $(BUILDDIR)/doctest/output.txt."
|
||||
|
||||
xml:
|
||||
$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
|
||||
@echo
|
||||
@echo "Build finished. The XML files are in $(BUILDDIR)/xml."
|
||||
|
||||
pseudoxml:
|
||||
$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
|
||||
@echo
|
||||
@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
|
||||
# Catch-all target: route all unknown targets to Sphinx using the new
|
||||
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
||||
%: Makefile
|
||||
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
@@ -1 +0,0 @@
|
||||
.. include:: ../AUTHORS.rst
|
||||
1850
docs/biblio.bib
Normal file
1850
docs/biblio.bib
Normal file
File diff suppressed because it is too large
Load Diff
272
docs/conf.py
Executable file → Normal file
272
docs/conf.py
Executable file → Normal file
@@ -1,8 +1,8 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# gnpy documentation build configuration file, created by
|
||||
# sphinx-quickstart on Tue Jul 9 22:26:36 2013.
|
||||
# GNpy documentation build configuration file, created by
|
||||
# sphinx-quickstart on Mon Dec 18 14:41:01 2017.
|
||||
#
|
||||
# This file is execfile()d with the current directory set to its
|
||||
# containing dir.
|
||||
@@ -13,263 +13,165 @@
|
||||
# All configuration values have a default; values that are commented out
|
||||
# serve to show the default.
|
||||
|
||||
import sys
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#
|
||||
import os
|
||||
import sys
|
||||
sys.path.insert(0, os.path.abspath('../'))
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another
|
||||
# directory, add these directories to sys.path here. If the directory is
|
||||
# relative to the documentation root, use os.path.abspath to make it
|
||||
# absolute, like shown here.
|
||||
#sys.path.insert(0, os.path.abspath('.'))
|
||||
|
||||
# Get the project root dir, which is the parent dir of this
|
||||
cwd = os.getcwd()
|
||||
project_root = os.path.dirname(cwd)
|
||||
|
||||
# Insert the project root dir as the first element in the PYTHONPATH.
|
||||
# This lets us ensure that the source package is imported, and that its
|
||||
# version is used.
|
||||
sys.path.insert(0, project_root)
|
||||
|
||||
import gnpy
|
||||
|
||||
# -- General configuration ---------------------------------------------
|
||||
# -- General configuration ------------------------------------------------
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
#needs_sphinx = '1.0'
|
||||
#
|
||||
# needs_sphinx = '1.0'
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
|
||||
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode']
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = ['sphinx.ext.autodoc',
|
||||
'sphinx.ext.mathjax',
|
||||
'sphinx.ext.githubpages','sphinxcontrib.bibtex']
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
|
||||
# The suffix of source filenames.
|
||||
source_suffix = '.rst'
|
||||
# The suffix(es) of source filenames.
|
||||
# You can specify multiple suffix as a list of string:
|
||||
#
|
||||
source_suffix = ['.rst', '.md']
|
||||
|
||||
# The encoding of source files.
|
||||
#source_encoding = 'utf-8-sig'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = u'gnpy'
|
||||
copyright = u"2017, <TBD>"
|
||||
project = 'GNpy'
|
||||
copyright = '2017, Telecom InfraProject - OOPT PSE Group'
|
||||
author = 'Telecom InfraProject - OOPT PSE Group'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement
|
||||
# for |version| and |release|, also used in various other places throughout
|
||||
# the built documents.
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = gnpy.__version__
|
||||
version = '0.1'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = gnpy.__version__
|
||||
release = '0.1'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
#language = None
|
||||
|
||||
# There are two options for replacing |today|: either, you set today to
|
||||
# some non-false value, then it is used:
|
||||
#today = ''
|
||||
# Else, today_fmt is used as the format for a strftime call.
|
||||
#today_fmt = '%B %d, %Y'
|
||||
#
|
||||
# This is also used if you do content translation via gettext catalogs.
|
||||
# Usually you set "language" from the command line for these cases.
|
||||
language = None
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
exclude_patterns = ['_build']
|
||||
|
||||
# The reST default role (used for this markup: `text`) to use for all
|
||||
# documents.
|
||||
#default_role = None
|
||||
|
||||
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||
#add_function_parentheses = True
|
||||
|
||||
# If true, the current module name will be prepended to all description
|
||||
# unit titles (such as .. function::).
|
||||
#add_module_names = True
|
||||
|
||||
# If true, sectionauthor and moduleauthor directives will be shown in the
|
||||
# output. They are ignored by default.
|
||||
#show_authors = False
|
||||
# This patterns also effect to html_static_path and html_extra_path
|
||||
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'sphinx'
|
||||
|
||||
# A list of ignored prefixes for module index sorting.
|
||||
#modindex_common_prefix = []
|
||||
|
||||
# If true, keep warnings as "system message" paragraphs in the built
|
||||
# documents.
|
||||
#keep_warnings = False
|
||||
# If true, `todo` and `todoList` produce output, else they produce nothing.
|
||||
todo_include_todos = False
|
||||
|
||||
|
||||
# -- Options for HTML output -------------------------------------------
|
||||
# -- Options for HTML output ----------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
html_theme = 'default'
|
||||
#
|
||||
on_rtd = os.environ.get('READTHEDOCS') == 'True'
|
||||
if on_rtd:
|
||||
html_theme = 'default'
|
||||
else:
|
||||
html_theme = 'alabaster'
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a
|
||||
# theme further. For a list of options available for each theme, see the
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
# documentation.
|
||||
#html_theme_options = {}
|
||||
#
|
||||
# html_theme_options = {}
|
||||
|
||||
# Add any paths that contain custom themes here, relative to this directory.
|
||||
#html_theme_path = []
|
||||
|
||||
# The name for this set of Sphinx documents. If None, it defaults to
|
||||
# "<project> v<release> documentation".
|
||||
#html_title = None
|
||||
|
||||
# A shorter title for the navigation bar. Default is the same as
|
||||
# html_title.
|
||||
#html_short_title = None
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the
|
||||
# top of the sidebar.
|
||||
#html_logo = None
|
||||
|
||||
# The name of an image file (within the static path) to use as favicon
|
||||
# of the docs. This file should be a Windows icon file (.ico) being
|
||||
# 16x16 or 32x32 pixels large.
|
||||
#html_favicon = None
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets)
|
||||
# here, relative to this directory. They are copied after the builtin
|
||||
# static files, so a file named "default.css" will overwrite the builtin
|
||||
# "default.css".
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
||||
|
||||
# If not '', a 'Last updated on:' timestamp is inserted at every page
|
||||
# bottom, using the given strftime format.
|
||||
#html_last_updated_fmt = '%b %d, %Y'
|
||||
|
||||
# If true, SmartyPants will be used to convert quotes and dashes to
|
||||
# typographically correct entities.
|
||||
#html_use_smartypants = True
|
||||
|
||||
# Custom sidebar templates, maps document names to template names.
|
||||
#html_sidebars = {}
|
||||
|
||||
# Additional templates that should be rendered to pages, maps page names
|
||||
# Custom sidebar templates, must be a dictionary that maps document names
|
||||
# to template names.
|
||||
#html_additional_pages = {}
|
||||
#
|
||||
# This is required for the alabaster theme
|
||||
# refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars
|
||||
html_sidebars = {
|
||||
'**': [
|
||||
'about.html',
|
||||
'navigation.html',
|
||||
'relations.html', # needs 'show_related': True theme option to display
|
||||
'searchbox.html',
|
||||
'donate.html',
|
||||
]
|
||||
}
|
||||
|
||||
# If false, no module index is generated.
|
||||
#html_domain_indices = True
|
||||
|
||||
# If false, no index is generated.
|
||||
#html_use_index = True
|
||||
|
||||
# If true, the index is split into individual pages for each letter.
|
||||
#html_split_index = False
|
||||
|
||||
# If true, links to the reST sources are added to the pages.
|
||||
#html_show_sourcelink = True
|
||||
|
||||
# If true, "Created using Sphinx" is shown in the HTML footer.
|
||||
# Default is True.
|
||||
#html_show_sphinx = True
|
||||
|
||||
# If true, "(C) Copyright ..." is shown in the HTML footer.
|
||||
# Default is True.
|
||||
#html_show_copyright = True
|
||||
|
||||
# If true, an OpenSearch description file will be output, and all pages
|
||||
# will contain a <link> tag referring to it. The value of this option
|
||||
# must be the base URL from which the finished HTML is served.
|
||||
#html_use_opensearch = ''
|
||||
|
||||
# This is the file name suffix for HTML files (e.g. ".xhtml").
|
||||
#html_file_suffix = None
|
||||
# -- Options for HTMLHelp output ------------------------------------------
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'gnpydoc'
|
||||
htmlhelp_basename = 'GNpydoc'
|
||||
|
||||
|
||||
# -- Options for LaTeX output ------------------------------------------
|
||||
# -- Options for LaTeX output ---------------------------------------------
|
||||
|
||||
latex_elements = {
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#'papersize': 'letterpaper',
|
||||
#
|
||||
# 'papersize': 'letterpaper',
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#'pointsize': '10pt',
|
||||
#
|
||||
# 'pointsize': '10pt',
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#'preamble': '',
|
||||
#
|
||||
# 'preamble': '',
|
||||
|
||||
# Latex figure (float) alignment
|
||||
#
|
||||
# 'figure_align': 'htbp',
|
||||
}
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title, author, documentclass
|
||||
# [howto/manual]).
|
||||
# (source start file, target name, title,
|
||||
# author, documentclass [howto, manual, or own class]).
|
||||
latex_documents = [
|
||||
('index', 'gnpy.tex',
|
||||
u'gnpy Documentation',
|
||||
u'<TBD>', 'manual'),
|
||||
(master_doc, 'GNpy.tex', 'GNpy Documentation',
|
||||
'Telecom InfraProject - OOPT PSE Group', 'manual'),
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at
|
||||
# the top of the title page.
|
||||
#latex_logo = None
|
||||
|
||||
# For "manual" documents, if this is true, then toplevel headings
|
||||
# are parts, not chapters.
|
||||
#latex_use_parts = False
|
||||
|
||||
# If true, show page references after internal links.
|
||||
#latex_show_pagerefs = False
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
#latex_show_urls = False
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
#latex_appendices = []
|
||||
|
||||
# If false, no module index is generated.
|
||||
#latex_domain_indices = True
|
||||
|
||||
|
||||
# -- Options for manual page output ------------------------------------
|
||||
# -- Options for manual page output ---------------------------------------
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
('index', 'gnpy',
|
||||
u'gnpy Documentation',
|
||||
[u'<TBD>'], 1)
|
||||
(master_doc, 'gnpy', 'GNpy Documentation',
|
||||
[author], 1)
|
||||
]
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
#man_show_urls = False
|
||||
|
||||
|
||||
# -- Options for Texinfo output ----------------------------------------
|
||||
# -- Options for Texinfo output -------------------------------------------
|
||||
|
||||
# Grouping the document tree into Texinfo files. List of tuples
|
||||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
('index', 'gnpy',
|
||||
u'gnpy Documentation',
|
||||
u'<TBD>',
|
||||
'gnpy',
|
||||
'One line description of project.',
|
||||
(master_doc, 'GNpy', 'GNpy Documentation',
|
||||
author, 'GNpy', 'One line description of project.',
|
||||
'Miscellaneous'),
|
||||
]
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
#texinfo_appendices = []
|
||||
|
||||
# If false, no module index is generated.
|
||||
#texinfo_domain_indices = True
|
||||
|
||||
# How to display URL addresses: 'footnote', 'no', or 'inline'.
|
||||
#texinfo_show_urls = 'footnote'
|
||||
|
||||
# If true, do not generate a @detailmenu in the "Top" node's menu.
|
||||
#texinfo_no_detailmenu = False
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
.. include:: ../CONTRIBUTING.rst
|
||||
124
docs/gn_model.rst
Normal file
124
docs/gn_model.rst
Normal file
@@ -0,0 +1,124 @@
|
||||
The QoT estimation in the PSE framework of TIP-OOPT
|
||||
=======================================================
|
||||
|
||||
QoT-E including ASE noise and NLI accumulation
|
||||
----------------------------------------------
|
||||
|
||||
The operations of PSE simulative framework are based on the capability to estimate the QoT of one
|
||||
or more channels operating lightpaths over a given network route. For
|
||||
backbone transport networks, we can suppose that transceivers are
|
||||
operating polarization-division-multiplexed multilevel modulation
|
||||
formats with DSP-based coherent receivers, including equalization. For
|
||||
the optical links, we focus on state-of-the-art amplified and
|
||||
uncompensated fiber links, connecting network nodes including ROADMs,
|
||||
where add and drop operations on data traffic are performed. In such a
|
||||
transmission scenario, it is well accepted
|
||||
:cite:`vacondio_nonlinear_2012,bononi_modeling_2012,carena_modeling_2012,mecozzi_nonlinear_2012,secondini_analytical_2012,johannisson_perturbation_2013,dar_properties_2013,serena_alternative_2013,secondini_achievable_2013,poggiolini_gn-model_2014,dar_accumulation_2014,poggiolini_analytical_2011,savory_approximations_2013,bononi_single-_2013,johannisson_modeling_2014`
|
||||
to assume that transmission performances are limited by the amplified
|
||||
spontaneous emission (ASE) noise generated by optical amplifiers and and
|
||||
by nonlinear propagation effects: accumulation of a Gaussian disturbance
|
||||
defined as nonlinear interference (NLI) and generation of phase noise.
|
||||
State-of-the-art DSP in commercial transceivers are typically able to
|
||||
compensate for most of the phase noise through carrier-phase estimator
|
||||
(CPE) algorithms, for modulation formats with cardinality up to 16, per
|
||||
polarization state
|
||||
:cite:`poggiolini_recent_2017,schmidt_experimental_2015,fehenberger_experimental_2016`.
|
||||
So, for backbone networks covering medium-to-wide geographical areas, we
|
||||
can suppose that propagation is limited by the accumulation of two
|
||||
Gaussian disturbances: the ASE noise and the NLI. Additional impairments
|
||||
such as filtering effects introduced by ROADMs can be considered as
|
||||
additional equivalent power penalties depending on the ratio between the
|
||||
channel bandwidth and the ROADMs filters and the number of traversed
|
||||
ROADMs (hops) of the route under analysis. Modeling the two major
|
||||
sources of impairments as Gaussian disturbances, and being the receivers
|
||||
*coherent*, the unique QoT parameter determining the bit error rate
|
||||
(BER) for the considered transmission scenario is the generalized
|
||||
signal-to-noise ratio (SNR) defined as
|
||||
|
||||
.. math::
|
||||
|
||||
{\text{SNR}}= L_F \frac{P_{\text{ch}}}{P_{\text{ASE}}+P_{\text{NLI}}} = L_F \left(\frac{1}{{\text{SNR}}_{\text{LIN}}}+\frac{1}{{\text{SNR}}_{\text{NL}}}\right)^{-1}
|
||||
|
||||
|
||||
where :math:`P_{\text{ch}}` is the channel power,
|
||||
:math:`P_{\text{ASE}}` and :math:`P_{\text{NLI}}` are the power levels of the disturbances
|
||||
in the channel bandwidth for ASE noise and NLI, respectively.
|
||||
:math:`L_F` is a parameter assuming values smaller or equal than one
|
||||
that summarizes the equivalent power penalty loss such as
|
||||
filtering effects. Note that for state-of-the art equipment, filtering
|
||||
effects can be typically neglected over routes with few hops
|
||||
:cite:`rahman_mitigation_2014,foggi_overcoming_2015`.
|
||||
|
||||
|
||||
To properly estimate :math:`P_{\text{ch}}` and :math:`P_{\text{ASE}}`
|
||||
the transmitted power at the beginning of the considered route must be
|
||||
known, and losses and amplifiers gain and noise figure, including their
|
||||
variation with frequency, must be characterized. So, the evaluation of
|
||||
:math:`{\text{SNR}}_{\text{LIN}}` *just* requires an accurate
|
||||
knowledge of equipment, which is not a trivial aspect, but it is not
|
||||
related to physical-model issues. For the evaluation of the NLI, several
|
||||
models have been proposed and validated in the technical literature
|
||||
:cite:`vacondio_nonlinear_2012,bononi_modeling_2012,carena_modeling_2012,mecozzi_nonlinear_2012,secondini_analytical_2012,johannisson_perturbation_2013,dar_properties_2013,serena_alternative_2013,secondini_achievable_2013,poggiolini_gn-model_2014,dar_accumulation_2014,poggiolini_analytical_2011,savory_approximations_2013,bononi_single-_2013,johannisson_modeling_2014`.
|
||||
The decision about which model to test within the PSE activities was
|
||||
driven by requirements of the entire PSE framework:
|
||||
|
||||
i. the model must be *local*, i.e., related individually to each network element (i.e. fiber span) generating NLI, independently of preceding and subsequent elements; and
|
||||
ii. the related computational time must be compatible with interactive operations.
|
||||
|
||||
So, the choice fell on the Gaussian Noise
|
||||
(GN) model with incoherent accumulation of NLI over fiber spans
|
||||
:cite:`poggiolini_gn-model_2014`. We implemented both the
|
||||
exact GN-model evaluation of NLI based on a double integral (Eq. (11) of
|
||||
:cite:`poggiolini_gn-model_2014`) and its analytical
|
||||
approximation (Eq. (120-121) of
|
||||
:cite:`poggiolini_analytical_2011`). We performed several
|
||||
validation analyses comparing results of the two implementations with
|
||||
split-step simulations over wide bandwidths
|
||||
:cite:`pilori_ffss_2017`, and results clearly showed that
|
||||
for fiber types with chromatic dispersion roughly larger than 4
|
||||
ps/nm/km, the analytical approximation ensures an excellent accuracy
|
||||
with a computational time compatible with real-time operations.
|
||||
|
||||
|
||||
|
||||
The Gaussian Noise Model to evaluate the NLI
|
||||
--------------------------------------------
|
||||
As previously stated, fiber propagation of multilevel modulation formats relying on the polarization-division-multiplexing
|
||||
generates impairments that can be summarized as a disturbance called nonlinear interference (NLI),
|
||||
when exploiting a DSP-based coherent receiver, as in all state-of-the-art equipment.
|
||||
From a practical point of view, the NLI can be modeled as an additive
|
||||
Gaussian random process added by each fiber span, and whose strength depends on the cube of the input power spectral density and
|
||||
on the fiber-span parameters.
|
||||
|
||||
Since the introduction in the market in 2007 of the first transponder based on such a transmission technique, the scientific
|
||||
community has intensively worked to define the propagation behavior of such a trasnmission technique.
|
||||
First, the role of in-line chromatic dispersion compensation has been investigated, deducing that besides being
|
||||
not essential, it is indeed detrimental for performances :cite:`curri_dispersion_2008`.
|
||||
Then, it has been observed that the fiber propagation impairments are practically summarized by the sole NLI, being all the other
|
||||
phenomena compensated for by the blind equalizer implemented in the receiver DSP :cite:`carena_statistical_2010`.
|
||||
Once these assessments have been accepted by the community, several prestigious research groups have started to work
|
||||
on deriving analytical models able to estimating the NLI accumulation, and consequentially the generalized SNR that sets the BER,
|
||||
according to the transponder BER vs. SNR performance.
|
||||
Many models delivering different levels of accuracy have been developed and validated. As previously clarified, for the purposes
|
||||
of the PSE framework, the GN-model with incoherent accumulation of NLI over fiber spans has been selected as adequate.
|
||||
The reason for such a choice is first such a model being a "local" model, so related to each fiber spans, independently of
|
||||
the preceding and succeeding network elements. The other model characteristic driving the choice is
|
||||
the availability of a closed form for the model, so permitting a real-time evaluation, as required by the PSE framework.
|
||||
For a detailed derivation of the model, please refer to :cite:`poggiolini_analytical_2011`, while a qualitative description
|
||||
can be summarized as in the following.
|
||||
The GN-model assumes that the channel comb propagating in the fiber is well approximated by unpolarized spectrally shaped
|
||||
Gaussian noise. In such a scenario, supposing to rely - as in state-of-the-art equipment - on a receiver entirely compensating for linear propagation effects, propagation in the fiber only excites the four-wave mixing (FWM) process among the continuity of
|
||||
the tones occupying the bandwidth. Such a FWM generates an unpolarized complex Gaussian disturbance in each spectral slot
|
||||
that can be easily evaluated extending the FWM theory from a set of discrete tones - the standard FWM theory introduced back in the 90s by Inoue :cite:`Innoue-FWM`- to a continuity of tones, possibly spectrally shaped.
|
||||
Signals propagating in the fiber are not equivalent to Gaussian noise, but thanks to the absence of in-line compensation for choromatic dispersion,
|
||||
the 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 conservative tool
|
||||
to estimate propagation impairments of fiber propagation.
|
||||
Note that the GN-model has not been derived with the aim of an *exact* performance estimation, but to pursue a conservative performance prediction. So, considering these characteristics, and the fact that the NLI is always a secondary effect with respect to the ASE noise accumulation, and - most importantly - that typically linear propagation parameters (losses, gains and noise figures) are known within
|
||||
a variation range, a QoT estimator based on the GN model is adequate to deliver performance predictions in terms of a reasonable SNR range, rather than an exact value.
|
||||
As final remark, it must be clarified that the GN-model is adequate to be used when relying on a relatively narrow bandwidth up to few THz. When exceeding such a bandwidth occupation, the GN-model must be generalized introducing the interaction with the Stimulated
|
||||
Raman Scattering in order to give a proper estimation for all channels :cite:`cantono2018modeling`.
|
||||
This will be the main upgrade required within the PSE framework.
|
||||
|
||||
|
||||
.. bibliography:: biblio.bib
|
||||
@@ -1 +0,0 @@
|
||||
.. include:: ../HISTORY.rst
|
||||
@@ -1,18 +1,37 @@
|
||||
Welcome to gnpy's documentation!
|
||||
======================================
|
||||
.. GNpy documentation master file, created by
|
||||
sphinx-quickstart on Mon Dec 18 14:41:01 2017.
|
||||
You can adapt this file completely to your liking, but it should at least
|
||||
contain the root `toctree` directive.
|
||||
|
||||
Contents:
|
||||
Welcome to GNpy's documentation!
|
||||
================================
|
||||
|
||||
Gaussian Noise (GN) based modeling library for physical layer impairment evaluation in optical networks.
|
||||
|
||||
Summary
|
||||
--------
|
||||
|
||||
We believe that openly sharing ideas, specifications, and other intellectual property is the key to maximizing innovation and reducing complexity
|
||||
|
||||
PSE WG Charter
|
||||
--------------
|
||||
|
||||
- Goal is to build an end-to-end simulation environment which defines the network models of the optical device transfer functions and their parameters. This environment will provide validation of the optical performance requirements for the TIP OLS building blocks.
|
||||
- The model may be approximate or complete depending on the network complexity. Each model shall be validated against the proposed network scenario.
|
||||
- The environment must be able to process network models from multiple vendors, and also allow users to pick any implementation in an open source framework.
|
||||
- The PSE will influence and benefit from the innovation of the DTC, API, and OLS working groups.
|
||||
- The PSE represents a step along the journey towards multi-layer optimization.
|
||||
|
||||
|
||||
Documentation
|
||||
=============
|
||||
|
||||
The following pages are meant to describe specific implementation details and modeling assumptions behind GNpy.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
readme
|
||||
installation
|
||||
usage
|
||||
modules
|
||||
contributing
|
||||
authors
|
||||
history
|
||||
gn_model
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
@@ -20,3 +39,32 @@ Indices and tables
|
||||
* :ref:`genindex`
|
||||
* :ref:`modindex`
|
||||
* :ref:`search`
|
||||
|
||||
Contributors in alphabetical order
|
||||
==================================
|
||||
+----------+------------+-----------------------+----------------------------+
|
||||
| Name | Surname | Affiliation | Contact |
|
||||
+==========+============+=======================+============================+
|
||||
| Alessio | Ferrari | Politecnico di Torino | alessio.ferrari@polito.it |
|
||||
+----------+------------+-----------------------+----------------------------+
|
||||
| Brian | Taylor | Facebook | briantaylor@fb.com |
|
||||
+----------+------------+-----------------------+----------------------------+
|
||||
| David | Boertjes | Ciena | dboertje@ciena.com |
|
||||
+----------+------------+-----------------------+----------------------------+
|
||||
| Esther | Le Rouzic | Orange | esther.lerouzic@orange.com |
|
||||
+----------+------------+-----------------------+----------------------------+
|
||||
| Gabriele | Galimberti | Cisco | ggalimbe@cisco.com |
|
||||
+----------+------------+-----------------------+----------------------------+
|
||||
| Gert | Grammel | Juniper Networks | ggrammel@juniper.net |
|
||||
+----------+------------+-----------------------+----------------------------+
|
||||
| Gilad | Goldfarb | Facebook | giladg@fb.com |
|
||||
+----------+------------+-----------------------+----------------------------+
|
||||
| James | Powell | Consultant | james@dontusethiscode.com |
|
||||
+----------+------------+-----------------------+----------------------------+
|
||||
| Jeanluc | Auge | Orange | jeanluc.auge@orange.com |
|
||||
+----------+------------+-----------------------+----------------------------+
|
||||
| Mattia | Cantono | Politecnico di Torino | mattia.cantono@polito.it |
|
||||
+----------+------------+-----------------------+----------------------------+
|
||||
| Vittorio | Curri | Politecnico di Torino | vittorio.curri@polito.it |
|
||||
+----------+------------+-----------------------+----------------------------+
|
||||
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
.. highlight:: shell
|
||||
|
||||
============
|
||||
Installation
|
||||
============
|
||||
|
||||
|
||||
Stable release
|
||||
--------------
|
||||
|
||||
To install gnpy, run this command in your terminal:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ pip install gnpy
|
||||
|
||||
This is the preferred method to install gnpy, as it will always install the most recent stable release.
|
||||
|
||||
If you don't have `pip`_ installed, this `Python installation guide`_ can guide
|
||||
you through the process.
|
||||
|
||||
.. _pip: https://pip.pypa.io
|
||||
.. _Python installation guide: http://docs.python-guide.org/en/latest/starting/installation/
|
||||
|
||||
|
||||
From sources
|
||||
------------
|
||||
|
||||
The sources for gnpy can be downloaded from the `Github repo`_.
|
||||
|
||||
You can either clone the public repository:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ git clone git://github.com/<TBD>/gnpy
|
||||
|
||||
Or download the `tarball`_:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ curl -OL https://github.com/<TBD>/gnpy/tarball/master
|
||||
|
||||
Once you have a copy of the source, you can install it with:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ python setup.py install
|
||||
|
||||
|
||||
.. _Github repo: https://github.com/<TBD>/gnpy
|
||||
.. _tarball: https://github.com/<TBD>/gnpy/tarball/master
|
||||
278
docs/make.bat
278
docs/make.bat
@@ -1,242 +1,36 @@
|
||||
@ECHO OFF
|
||||
|
||||
REM Command file for Sphinx documentation
|
||||
|
||||
if "%SPHINXBUILD%" == "" (
|
||||
set SPHINXBUILD=sphinx-build
|
||||
)
|
||||
set BUILDDIR=_build
|
||||
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
|
||||
set I18NSPHINXOPTS=%SPHINXOPTS% .
|
||||
if NOT "%PAPER%" == "" (
|
||||
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
|
||||
set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
|
||||
)
|
||||
|
||||
if "%1" == "" goto help
|
||||
|
||||
if "%1" == "help" (
|
||||
:help
|
||||
echo.Please use `make ^<target^>` where ^<target^> is one of
|
||||
echo. html to make standalone HTML files
|
||||
echo. dirhtml to make HTML files named index.html in directories
|
||||
echo. singlehtml to make a single large HTML file
|
||||
echo. pickle to make pickle files
|
||||
echo. json to make JSON files
|
||||
echo. htmlhelp to make HTML files and a HTML help project
|
||||
echo. qthelp to make HTML files and a qthelp project
|
||||
echo. devhelp to make HTML files and a Devhelp project
|
||||
echo. epub to make an epub
|
||||
echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
|
||||
echo. text to make text files
|
||||
echo. man to make manual pages
|
||||
echo. texinfo to make Texinfo files
|
||||
echo. gettext to make PO message catalogs
|
||||
echo. changes to make an overview over all changed/added/deprecated items
|
||||
echo. xml to make Docutils-native XML files
|
||||
echo. pseudoxml to make pseudoxml-XML files for display purposes
|
||||
echo. linkcheck to check all external links for integrity
|
||||
echo. doctest to run all doctests embedded in the documentation if enabled
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "clean" (
|
||||
for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
|
||||
del /q /s %BUILDDIR%\*
|
||||
goto end
|
||||
)
|
||||
|
||||
|
||||
%SPHINXBUILD% 2> nul
|
||||
if errorlevel 9009 (
|
||||
echo.
|
||||
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
|
||||
echo.installed, then set the SPHINXBUILD environment variable to point
|
||||
echo.to the full path of the 'sphinx-build' executable. Alternatively you
|
||||
echo.may add the Sphinx directory to PATH.
|
||||
echo.
|
||||
echo.If you don't have Sphinx installed, grab it from
|
||||
echo.http://sphinx-doc.org/
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
if "%1" == "html" (
|
||||
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The HTML pages are in %BUILDDIR%/html.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "dirhtml" (
|
||||
%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "singlehtml" (
|
||||
%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "pickle" (
|
||||
%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; now you can process the pickle files.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "json" (
|
||||
%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; now you can process the JSON files.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "htmlhelp" (
|
||||
%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; now you can run HTML Help Workshop with the ^
|
||||
.hhp project file in %BUILDDIR%/htmlhelp.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "qthelp" (
|
||||
%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; now you can run "qcollectiongenerator" with the ^
|
||||
.qhcp project file in %BUILDDIR%/qthelp, like this:
|
||||
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\gnpy.qhcp
|
||||
echo.To view the help file:
|
||||
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\gnpy.ghc
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "devhelp" (
|
||||
%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "epub" (
|
||||
%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The epub file is in %BUILDDIR%/epub.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "latex" (
|
||||
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "latexpdf" (
|
||||
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
|
||||
cd %BUILDDIR%/latex
|
||||
make all-pdf
|
||||
cd %BUILDDIR%/..
|
||||
echo.
|
||||
echo.Build finished; the PDF files are in %BUILDDIR%/latex.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "latexpdfja" (
|
||||
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
|
||||
cd %BUILDDIR%/latex
|
||||
make all-pdf-ja
|
||||
cd %BUILDDIR%/..
|
||||
echo.
|
||||
echo.Build finished; the PDF files are in %BUILDDIR%/latex.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "text" (
|
||||
%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The text files are in %BUILDDIR%/text.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "man" (
|
||||
%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The manual pages are in %BUILDDIR%/man.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "texinfo" (
|
||||
%SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "gettext" (
|
||||
%SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "changes" (
|
||||
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.The overview file is in %BUILDDIR%/changes.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "linkcheck" (
|
||||
%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Link check complete; look for any errors in the above output ^
|
||||
or in %BUILDDIR%/linkcheck/output.txt.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "doctest" (
|
||||
%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Testing of doctests in the sources finished, look at the ^
|
||||
results in %BUILDDIR%/doctest/output.txt.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "xml" (
|
||||
%SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The XML files are in %BUILDDIR%/xml.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "pseudoxml" (
|
||||
%SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml.
|
||||
goto end
|
||||
)
|
||||
|
||||
:end
|
||||
@ECHO OFF
|
||||
|
||||
pushd %~dp0
|
||||
|
||||
REM Command file for Sphinx documentation
|
||||
|
||||
if "%SPHINXBUILD%" == "" (
|
||||
set SPHINXBUILD=python -msphinx
|
||||
)
|
||||
set SOURCEDIR=.
|
||||
set BUILDDIR=_build
|
||||
set SPHINXPROJ=GNpy
|
||||
|
||||
if "%1" == "" goto help
|
||||
|
||||
%SPHINXBUILD% >NUL 2>NUL
|
||||
if errorlevel 9009 (
|
||||
echo.
|
||||
echo.The Sphinx module was not found. Make sure you have Sphinx installed,
|
||||
echo.then set the SPHINXBUILD environment variable to point to the full
|
||||
echo.path of the 'sphinx-build' executable. Alternatively you may add the
|
||||
echo.Sphinx directory to PATH.
|
||||
echo.
|
||||
echo.If you don't have Sphinx installed, grab it from
|
||||
echo.http://sphinx-doc.org/
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
|
||||
goto end
|
||||
|
||||
:help
|
||||
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
|
||||
|
||||
:end
|
||||
popd
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
.. include:: ../README.rst
|
||||
70
docs/source/gnpy.core.rst
Normal file
70
docs/source/gnpy.core.rst
Normal file
@@ -0,0 +1,70 @@
|
||||
gnpy\.core package
|
||||
==================
|
||||
|
||||
Submodules
|
||||
----------
|
||||
|
||||
gnpy\.core\.elements module
|
||||
---------------------------
|
||||
|
||||
.. automodule:: gnpy.core.elements
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
gnpy\.core\.execute module
|
||||
--------------------------
|
||||
|
||||
.. automodule:: gnpy.core.execute
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
gnpy\.core\.info module
|
||||
-----------------------
|
||||
|
||||
.. automodule:: gnpy.core.info
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
gnpy\.core\.network module
|
||||
--------------------------
|
||||
|
||||
.. automodule:: gnpy.core.network
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
gnpy\.core\.node module
|
||||
-----------------------
|
||||
|
||||
.. automodule:: gnpy.core.node
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
gnpy\.core\.units module
|
||||
------------------------
|
||||
|
||||
.. automodule:: gnpy.core.units
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
gnpy\.core\.utils module
|
||||
------------------------
|
||||
|
||||
.. automodule:: gnpy.core.utils
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
|
||||
Module contents
|
||||
---------------
|
||||
|
||||
.. automodule:: gnpy.core
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
17
docs/source/gnpy.rst
Normal file
17
docs/source/gnpy.rst
Normal file
@@ -0,0 +1,17 @@
|
||||
gnpy package
|
||||
============
|
||||
|
||||
Subpackages
|
||||
-----------
|
||||
|
||||
.. toctree::
|
||||
|
||||
gnpy.core
|
||||
|
||||
Module contents
|
||||
---------------
|
||||
|
||||
.. automodule:: gnpy
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
7
docs/source/modules.rst
Normal file
7
docs/source/modules.rst
Normal file
@@ -0,0 +1,7 @@
|
||||
gnpy
|
||||
====
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 4
|
||||
|
||||
gnpy
|
||||
@@ -1,7 +0,0 @@
|
||||
=====
|
||||
Usage
|
||||
=====
|
||||
|
||||
To use gnpy in a project::
|
||||
|
||||
import gnpy
|
||||
BIN
examples/CORONET_Global_Topology.xls
Normal file
BIN
examples/CORONET_Global_Topology.xls
Normal file
Binary file not shown.
11
examples/Makefile
Normal file
11
examples/Makefile
Normal file
@@ -0,0 +1,11 @@
|
||||
REGIONS = europe asia conus
|
||||
TARGETS = $(foreach region,$(REGIONS),coronet.$(region).json)
|
||||
|
||||
all: $(TARGETS)
|
||||
|
||||
$(TARGETS): convert.py CORONET_Global_Topology.xls
|
||||
python $< -f $(subst .json,,$(subst coronet.,,$@)) > $@
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
-rm $(TARGETS) -f
|
||||
143
examples/OperatorInputNetworkv3-xufeng.json
Normal file
143
examples/OperatorInputNetworkv3-xufeng.json
Normal file
@@ -0,0 +1,143 @@
|
||||
{
|
||||
"networks": {
|
||||
"network": [
|
||||
{
|
||||
"network-types": {
|
||||
"tip-oopt-pse": {}
|
||||
},
|
||||
"network-id": "pt-to-pt",
|
||||
"node": [
|
||||
{
|
||||
"node-id": "M_KMA",
|
||||
"type":"roadm",
|
||||
"termination-point": [
|
||||
{
|
||||
"tp-id": "1-2-1"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"node-id": "T_CAS",
|
||||
"type":"roadm",
|
||||
"termination-point": [
|
||||
{
|
||||
"tp-id": "2-1-1"
|
||||
},
|
||||
{
|
||||
"tp-id": "2-3-1"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"node-id": "LA",
|
||||
"type":"ila",
|
||||
"termination-point": [
|
||||
{
|
||||
"tp-id": "3-2-1"
|
||||
},
|
||||
{
|
||||
"tp-id": "3-4-1"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"node-id": "SR",
|
||||
"type":"fused",
|
||||
"termination-point": [
|
||||
{
|
||||
"tp-id": "4-3-1"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"node-id": "C",
|
||||
"type":"ila",
|
||||
"termination-point": [
|
||||
{
|
||||
"tp-id": "5-6-1"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"node-id": "N_KBE",
|
||||
"type":"roadm",
|
||||
"termination-point": [
|
||||
{
|
||||
"tp-id": "6-5-1"
|
||||
},
|
||||
{
|
||||
"tp-id": "6-7-1"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"node-id": "N_KBA",
|
||||
"type":"roadm",
|
||||
"termination-point": [
|
||||
{
|
||||
"tp-id": "7-6-1"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"link": [
|
||||
{
|
||||
"link-id": "M_KMA,1-2-1,T_CAS,2-1-1",
|
||||
"source": {
|
||||
"source-node": "M_KMA",
|
||||
"source-tp": "1-2-1"
|
||||
}
|
||||
"destination": {
|
||||
"dest-node": "T_CAS",
|
||||
"dest-tp": "2-1-1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"link-id": "T_CAS,2-3-1,LA,3-2-1",
|
||||
"source": {
|
||||
"source-node": "T_CAS",
|
||||
"source-tp": "2-3-1"
|
||||
}
|
||||
"destination": {
|
||||
"dest-node": "LA",
|
||||
"dest-tp": "3-2-1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"link-id": "LA,3-4-1,SR,4-3-1",
|
||||
"source": {
|
||||
"source-node": "LA",
|
||||
"source-tp": "3-4-1"
|
||||
}
|
||||
"destination": {
|
||||
"dest-node": "SR",
|
||||
"dest-tp": "4-3-1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"link-id": "C,5-6-1,N_KBE,6-5-1",
|
||||
"source": {
|
||||
"source-node": "C",
|
||||
"source-tp": "5-6-1"
|
||||
}
|
||||
"destination": {
|
||||
"dest-node": "N_KBE",
|
||||
"dest-tp": "6-5-1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"link-id": "N_KBE,6-7-1,N_KBA,7-6-1",
|
||||
"source": {
|
||||
"source-node": "N_KBE",
|
||||
"source-tp": "6-7-1"
|
||||
}
|
||||
"destination": {
|
||||
"dest-node": "N_KBA",
|
||||
"dest-tp": "7-6-1"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
157
examples/OperatorInputNetworkv3.json
Normal file
157
examples/OperatorInputNetworkv3.json
Normal file
@@ -0,0 +1,157 @@
|
||||
{
|
||||
"network_name": "pt to pt",
|
||||
"nodes_elements":
|
||||
[
|
||||
{
|
||||
"id":"M_KMA",
|
||||
"type":"ROADM",
|
||||
"metadata": {
|
||||
"city":"M",
|
||||
"region":"RLD",
|
||||
"latitude":0,
|
||||
"longitude":0
|
||||
}
|
||||
},
|
||||
{
|
||||
"id":"T_CAS",
|
||||
"type":"ROADM",
|
||||
"metadata": {
|
||||
"city":"T",
|
||||
"region":"RLD",
|
||||
"latitude":0,
|
||||
"longitude":0
|
||||
}
|
||||
},
|
||||
{
|
||||
"id":"LA",
|
||||
"type":"ILA",
|
||||
"metadata": {
|
||||
"city":"LA",
|
||||
"region":"RLD",
|
||||
"latitude":0,
|
||||
"longitude":0
|
||||
}
|
||||
},
|
||||
{
|
||||
"id":"SR",
|
||||
"type":"fused",
|
||||
"metadata": {
|
||||
"city":"SR",
|
||||
"region":"RLD",
|
||||
"latitude":0,
|
||||
"longitude":0
|
||||
}
|
||||
},
|
||||
{
|
||||
"id":"C",
|
||||
"type":"ILA",
|
||||
"metadata": {
|
||||
"city":"C",
|
||||
"region":"RLD",
|
||||
"latitude":0,
|
||||
"longitude":0
|
||||
}
|
||||
},
|
||||
{
|
||||
"id":"N_KBE",
|
||||
"type":"ROADM",
|
||||
"metadata": {
|
||||
"city":"N",
|
||||
"region":"RLD",
|
||||
"latitude":0,
|
||||
"longitude":0
|
||||
}
|
||||
},
|
||||
{
|
||||
"id":"N_KBA",
|
||||
"type":"ROADM",
|
||||
"metadata": {
|
||||
"city":"N",
|
||||
"region":"RLD",
|
||||
"latitude":0,
|
||||
"longitude":0
|
||||
}
|
||||
},
|
||||
],
|
||||
"OTS_elements":[
|
||||
{
|
||||
"id":1,
|
||||
"source_id":"M_KMA",
|
||||
"dest_id":"T_CAS",
|
||||
"parameters_cable":{
|
||||
"units":"km",
|
||||
"length":60,
|
||||
"id":"F060",
|
||||
"type":"G652"
|
||||
},
|
||||
"parameters_east":{
|
||||
"con_in":0.5,
|
||||
"con_out":0.5,
|
||||
"loss":16,
|
||||
"pmd":2,
|
||||
"fo_id":5
|
||||
},
|
||||
"parameters_west":{
|
||||
"con_in":0.5,
|
||||
"con_out":0.5,
|
||||
"loss":15,
|
||||
"pmd":2,
|
||||
"fo_id":6
|
||||
}
|
||||
},
|
||||
{
|
||||
"id":2,
|
||||
"source_id":"T_CAS",
|
||||
"dest_id":"LA",
|
||||
"parameters_cable":{
|
||||
},
|
||||
"parameters_east":{
|
||||
},
|
||||
"parameters_west":{
|
||||
}
|
||||
},
|
||||
{
|
||||
"id":3,
|
||||
"source_id":"LA",
|
||||
"dest_id":"SR",
|
||||
"parameters_cable":{
|
||||
},
|
||||
"parameters_east":{
|
||||
},
|
||||
"parameters_west":{
|
||||
}
|
||||
},
|
||||
{
|
||||
"id":3,
|
||||
"source_id":"SR",
|
||||
"dest_id":"C",
|
||||
"parameters_cable":{
|
||||
},
|
||||
"parameters_east":{
|
||||
},
|
||||
"parameters_west":{
|
||||
}
|
||||
},
|
||||
{
|
||||
"id":5,
|
||||
"source_id":"C",
|
||||
"dest_id":"N_KBE",
|
||||
"parameters_cable":{
|
||||
},
|
||||
"parameters_east":{
|
||||
},
|
||||
"parameters_west":{
|
||||
}
|
||||
},
|
||||
{
|
||||
"id":6,
|
||||
"source_id":"N_KBE",
|
||||
"dest_id":"N_KBA",
|
||||
"parameters_cable":{
|
||||
},
|
||||
"parameters_east":{
|
||||
},
|
||||
"parameters_west":{
|
||||
}
|
||||
},
|
||||
]}
|
||||
162
examples/convert.py
Normal file
162
examples/convert.py
Normal file
@@ -0,0 +1,162 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from sys import exit
|
||||
try:
|
||||
from xlrd import open_workbook
|
||||
except ModuleNotFoundError:
|
||||
exit('Required: `pip install xlrd`')
|
||||
from argparse import ArgumentParser
|
||||
from collections import namedtuple, Counter
|
||||
from itertools import chain
|
||||
from json import dumps
|
||||
from uuid import uuid4
|
||||
import math
|
||||
import numpy as np
|
||||
|
||||
output_json_file_name = 'coronet_conus_example.json'
|
||||
Node = namedtuple('Node', 'city state country region latitude longitude')
|
||||
class Link(namedtuple('Link', 'from_city to_city distance distance_units')):
|
||||
def __new__(cls, from_city, to_city, distance, distance_units='km'):
|
||||
return super().__new__(cls, from_city, to_city, distance, distance_units)
|
||||
|
||||
def define_span_range(min_span, max_span, nspans):
|
||||
srange = (max_span - min_span) + min_span*np.random.rand(nspans)
|
||||
return srange
|
||||
|
||||
def amp_spacings(min_span,max_span,length):
|
||||
nspans = math.ceil(length/100)
|
||||
spans = define_span_range(min_span, max_span, nspans)
|
||||
tot = spans.sum()
|
||||
delta = length -tot
|
||||
if delta > 0 and delta < 25:
|
||||
ind = np.where(np.min(spans))
|
||||
spans[ind] = spans[ind] + delta
|
||||
elif delta >= 25 and delta < 40:
|
||||
spans = spans + delta/float(nspans)
|
||||
elif delta > 40 and delta < 100:
|
||||
spans = np.append(spans,delta)
|
||||
elif delta > 100:
|
||||
spans = np.append(spans, [delta/2, delta/2])
|
||||
elif delta < 0:
|
||||
spans = spans + delta/float(nspans)
|
||||
return list(spans)
|
||||
|
||||
def parse_excel(args):
|
||||
with open_workbook(args.workbook) as wb:
|
||||
nodes_sheet = wb.sheet_by_name('Nodes')
|
||||
links_sheet = wb.sheet_by_name('Links')
|
||||
|
||||
# sanity check
|
||||
header = [x.value.strip() for x in nodes_sheet.row(4)]
|
||||
expected = ['City', 'State', 'Country', 'Region', 'Latitude', 'Longitude']
|
||||
if header != expected:
|
||||
raise ValueError(f'Malformed header on Nodes sheet: {header} != {expected}')
|
||||
|
||||
nodes = []
|
||||
for row in all_rows(nodes_sheet, start=5):
|
||||
nodes.append(Node(*(x.value for x in row)))
|
||||
|
||||
# sanity check
|
||||
header = [x.value.strip() for x in links_sheet.row(4)]
|
||||
expected = ['Node A', 'Node Z', 'Distance (km)']
|
||||
if header != expected:
|
||||
raise ValueError(f'Malformed header on Nodes sheet: {header} != {expected}')
|
||||
|
||||
links = []
|
||||
for row in all_rows(links_sheet, start=5):
|
||||
links.append(Link(*(x.value for x in row)))
|
||||
|
||||
# sanity check
|
||||
all_cities = Counter(n.city for n in nodes)
|
||||
if len(all_cities) != len(nodes):
|
||||
ValueError(f'Duplicate city: {all_cities}')
|
||||
if any(ln.from_city not in all_cities or
|
||||
ln.to_city not in all_cities for ln in links):
|
||||
ValueError(f'Bad link.')
|
||||
|
||||
return nodes, links
|
||||
|
||||
parser = ArgumentParser()
|
||||
parser.add_argument('workbook', nargs='?', default='CORONET_Global_Topology.xls')
|
||||
parser.add_argument('-f', '--filter-region', action='append', default=[])
|
||||
|
||||
all_rows = lambda sh, start=0: (sh.row(x) for x in range(start, sh.nrows))
|
||||
|
||||
def midpoint(city_a, city_b):
|
||||
lats = city_a.latitude, city_b.latitude
|
||||
longs = city_a.longitude, city_b.longitude
|
||||
return {
|
||||
'latitude': sum(lats) / 2,
|
||||
'longitude': sum(longs) / 2,
|
||||
}
|
||||
|
||||
if __name__ == '__main__':
|
||||
args = parser.parse_args()
|
||||
nodes, links = parse_excel(args)
|
||||
|
||||
if args.filter_region:
|
||||
nodes = [n for n in nodes if n.region.lower() in args.filter_region]
|
||||
cities = {n.city for n in nodes}
|
||||
links = [lnk for lnk in links if lnk.from_city in cities and
|
||||
lnk.to_city in cities]
|
||||
cities = {lnk.from_city for lnk in links} | {lnk.to_city for lnk in links}
|
||||
nodes = [n for n in nodes if n.city in cities]
|
||||
|
||||
nodes_by_city = {n.city: n for n in nodes}
|
||||
|
||||
data = {
|
||||
'elements':
|
||||
[{'uid': f'trx {x.city}',
|
||||
'metadata': {'location': {'city': x.city,
|
||||
'region': x.region,
|
||||
'latitude': x.latitude,
|
||||
'longitude': x.longitude}},
|
||||
'type': 'Transceiver'}
|
||||
for x in nodes] +
|
||||
[{'uid': f'roadm {x.city}',
|
||||
'metadata': {'location': {'city': x.city,
|
||||
'region': x.region,
|
||||
'latitude': x.latitude,
|
||||
'longitude': x.longitude}},
|
||||
'type': 'Roadm'}
|
||||
for x in nodes] +
|
||||
[{'uid': f'fiber ({x.from_city} → {x.to_city})',
|
||||
'metadata': {'location': midpoint(nodes_by_city[x.from_city],
|
||||
nodes_by_city[x.to_city])},
|
||||
'type': 'Fiber',
|
||||
'params': {'length': round(x.distance, 3),
|
||||
'length_units': x.distance_units,
|
||||
'loss_coef': 0.2,
|
||||
'dispersion': 16.7E-6,
|
||||
'gamma': 1.27E-3}
|
||||
}
|
||||
for x in links],
|
||||
'connections':
|
||||
list(chain.from_iterable(zip( # put bidi next to each other
|
||||
[{'from_node': f'roadm {x.from_city}',
|
||||
'to_node': f'fiber ({x.from_city} → {x.to_city})'}
|
||||
for x in links],
|
||||
[{'from_node': f'fiber ({x.from_city} → {x.to_city})',
|
||||
'to_node': f'roadm {x.from_city}'}
|
||||
for x in links])))
|
||||
+
|
||||
list(chain.from_iterable(zip(
|
||||
[{'from_node': f'fiber ({x.from_city} → {x.to_city})',
|
||||
'to_node': f'roadm {x.to_city}'}
|
||||
for x in links],
|
||||
[{'from_node': f'roadm {x.to_city}',
|
||||
'to_node': f'fiber ({x.from_city} → {x.to_city})'}
|
||||
for x in links])))
|
||||
+
|
||||
list(chain.from_iterable(zip(
|
||||
[{'from_node': f'trx {x.city}',
|
||||
'to_node': f'roadm {x.city}'}
|
||||
for x in nodes],
|
||||
[{'from_node': f'roadm {x.city}',
|
||||
'to_node': f'trx {x.city}'}
|
||||
for x in nodes])))
|
||||
}
|
||||
|
||||
print(dumps(data, indent=2))
|
||||
with open(output_json_file_name,'w') as edfa_json_file:
|
||||
edfa_json_file.write(dumps(data, indent=2))
|
||||
542
examples/coronet.asia.json
Normal file
542
examples/coronet.asia.json
Normal file
@@ -0,0 +1,542 @@
|
||||
{
|
||||
"elements": [
|
||||
{
|
||||
"uid": "Bangkok",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Bangkok",
|
||||
"region": "Asia",
|
||||
"latitude": 13.73,
|
||||
"longitude": 100.5
|
||||
}
|
||||
},
|
||||
"type": "Transceiver"
|
||||
},
|
||||
{
|
||||
"uid": "Beijing",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Beijing",
|
||||
"region": "Asia",
|
||||
"latitude": 39.92999979,
|
||||
"longitude": 116.4000013
|
||||
}
|
||||
},
|
||||
"type": "Transceiver"
|
||||
},
|
||||
{
|
||||
"uid": "Delhi",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Delhi",
|
||||
"region": "Asia",
|
||||
"latitude": 28.6700003,
|
||||
"longitude": 77.2099989
|
||||
}
|
||||
},
|
||||
"type": "Transceiver"
|
||||
},
|
||||
{
|
||||
"uid": "Hong_Kong",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Hong_Kong",
|
||||
"region": "Asia",
|
||||
"latitude": 22.267,
|
||||
"longitude": 114.14
|
||||
}
|
||||
},
|
||||
"type": "Transceiver"
|
||||
},
|
||||
{
|
||||
"uid": "Honolulu",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Honolulu",
|
||||
"region": "Asia",
|
||||
"latitude": 21.3199996,
|
||||
"longitude": -157.800003
|
||||
}
|
||||
},
|
||||
"type": "Transceiver"
|
||||
},
|
||||
{
|
||||
"uid": "Mumbai",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Mumbai",
|
||||
"region": "Asia",
|
||||
"latitude": 18.9599987,
|
||||
"longitude": 72.8199999
|
||||
}
|
||||
},
|
||||
"type": "Transceiver"
|
||||
},
|
||||
{
|
||||
"uid": "Seoul",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Seoul",
|
||||
"region": "Asia",
|
||||
"latitude": 37.56000108,
|
||||
"longitude": 126.9899988
|
||||
}
|
||||
},
|
||||
"type": "Transceiver"
|
||||
},
|
||||
{
|
||||
"uid": "Shanghai",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Shanghai",
|
||||
"region": "Asia",
|
||||
"latitude": 31.23,
|
||||
"longitude": 121.47
|
||||
}
|
||||
},
|
||||
"type": "Transceiver"
|
||||
},
|
||||
{
|
||||
"uid": "Singapore",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Singapore",
|
||||
"region": "Asia",
|
||||
"latitude": 1.299999907,
|
||||
"longitude": 103.8499992
|
||||
}
|
||||
},
|
||||
"type": "Transceiver"
|
||||
},
|
||||
{
|
||||
"uid": "Sydney",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Sydney",
|
||||
"region": "Asia",
|
||||
"latitude": -33.86999896,
|
||||
"longitude": 151.2100066
|
||||
}
|
||||
},
|
||||
"type": "Transceiver"
|
||||
},
|
||||
{
|
||||
"uid": "Taipei",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Taipei",
|
||||
"region": "Asia",
|
||||
"latitude": 25.0200005,
|
||||
"longitude": 121.449997
|
||||
}
|
||||
},
|
||||
"type": "Transceiver"
|
||||
},
|
||||
{
|
||||
"uid": "Tokyo",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Tokyo",
|
||||
"region": "Asia",
|
||||
"latitude": 35.6699986,
|
||||
"longitude": 139.770004
|
||||
}
|
||||
},
|
||||
"type": "Transceiver"
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Bangkok \u2192 Delhi)",
|
||||
"metadata": {
|
||||
"length": 3505.95,
|
||||
"units": "km",
|
||||
"location": {
|
||||
"latitude": 21.20000015,
|
||||
"longitude": 88.85499945000001
|
||||
}
|
||||
},
|
||||
"type": "Fiber"
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Bangkok \u2192 Hong_Kong)",
|
||||
"metadata": {
|
||||
"length": 2070.724,
|
||||
"units": "km",
|
||||
"location": {
|
||||
"latitude": 17.9985,
|
||||
"longitude": 107.32
|
||||
}
|
||||
},
|
||||
"type": "Fiber"
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Beijing \u2192 Seoul)",
|
||||
"metadata": {
|
||||
"length": 1146.124,
|
||||
"units": "km",
|
||||
"location": {
|
||||
"latitude": 38.745000434999994,
|
||||
"longitude": 121.69500005
|
||||
}
|
||||
},
|
||||
"type": "Fiber"
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Beijing \u2192 Shanghai)",
|
||||
"metadata": {
|
||||
"length": 1284.465,
|
||||
"units": "km",
|
||||
"location": {
|
||||
"latitude": 35.579999895,
|
||||
"longitude": 118.93500065
|
||||
}
|
||||
},
|
||||
"type": "Fiber"
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Delhi \u2192 Mumbai)",
|
||||
"metadata": {
|
||||
"length": 1402.141,
|
||||
"units": "km",
|
||||
"location": {
|
||||
"latitude": 23.8149995,
|
||||
"longitude": 75.0149994
|
||||
}
|
||||
},
|
||||
"type": "Fiber"
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Hong_Kong \u2192 Shanghai)",
|
||||
"metadata": {
|
||||
"length": 1480.406,
|
||||
"units": "km",
|
||||
"location": {
|
||||
"latitude": 26.7485,
|
||||
"longitude": 117.805
|
||||
}
|
||||
},
|
||||
"type": "Fiber"
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Hong_Kong \u2192 Sydney)",
|
||||
"metadata": {
|
||||
"length": 8856.6,
|
||||
"units": "km",
|
||||
"location": {
|
||||
"latitude": -5.801499479999999,
|
||||
"longitude": 132.67500330000001
|
||||
}
|
||||
},
|
||||
"type": "Fiber"
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Hong_Kong \u2192 Taipei)",
|
||||
"metadata": {
|
||||
"length": 966.177,
|
||||
"units": "km",
|
||||
"location": {
|
||||
"latitude": 23.64350025,
|
||||
"longitude": 117.79499849999999
|
||||
}
|
||||
},
|
||||
"type": "Fiber"
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Honolulu \u2192 Sydney)",
|
||||
"metadata": {
|
||||
"length": 9808.616,
|
||||
"units": "km",
|
||||
"location": {
|
||||
"latitude": -6.274999679999999,
|
||||
"longitude": -3.294998199999995
|
||||
}
|
||||
},
|
||||
"type": "Fiber"
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Honolulu \u2192 Taipei)",
|
||||
"metadata": {
|
||||
"length": 9767.013,
|
||||
"units": "km",
|
||||
"location": {
|
||||
"latitude": 23.17000005,
|
||||
"longitude": -18.175003000000004
|
||||
}
|
||||
},
|
||||
"type": "Fiber"
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Mumbai \u2192 Singapore)",
|
||||
"metadata": {
|
||||
"length": 4692.708,
|
||||
"units": "km",
|
||||
"location": {
|
||||
"latitude": 10.1299993035,
|
||||
"longitude": 88.33499954999999
|
||||
}
|
||||
},
|
||||
"type": "Fiber"
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Seoul \u2192 Tokyo)",
|
||||
"metadata": {
|
||||
"length": 1391.085,
|
||||
"units": "km",
|
||||
"location": {
|
||||
"latitude": 36.614999839999996,
|
||||
"longitude": 133.3800014
|
||||
}
|
||||
},
|
||||
"type": "Fiber"
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Singapore \u2192 Sydney)",
|
||||
"metadata": {
|
||||
"length": 7562.331,
|
||||
"units": "km",
|
||||
"location": {
|
||||
"latitude": -16.2849995265,
|
||||
"longitude": 127.5300029
|
||||
}
|
||||
},
|
||||
"type": "Fiber"
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Taipei \u2192 Tokyo)",
|
||||
"metadata": {
|
||||
"length": 2537.345,
|
||||
"units": "km",
|
||||
"location": {
|
||||
"latitude": 30.344999549999997,
|
||||
"longitude": 130.6100005
|
||||
}
|
||||
},
|
||||
"type": "Fiber"
|
||||
}
|
||||
],
|
||||
"connections": [
|
||||
{
|
||||
"from_node": "Bangkok",
|
||||
"to_node": "fiber (Bangkok \u2192 Delhi)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Bangkok \u2192 Delhi)",
|
||||
"to_node": "Bangkok"
|
||||
},
|
||||
{
|
||||
"from_node": "Bangkok",
|
||||
"to_node": "fiber (Bangkok \u2192 Hong_Kong)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Bangkok \u2192 Hong_Kong)",
|
||||
"to_node": "Bangkok"
|
||||
},
|
||||
{
|
||||
"from_node": "Beijing",
|
||||
"to_node": "fiber (Beijing \u2192 Seoul)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Beijing \u2192 Seoul)",
|
||||
"to_node": "Beijing"
|
||||
},
|
||||
{
|
||||
"from_node": "Beijing",
|
||||
"to_node": "fiber (Beijing \u2192 Shanghai)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Beijing \u2192 Shanghai)",
|
||||
"to_node": "Beijing"
|
||||
},
|
||||
{
|
||||
"from_node": "Delhi",
|
||||
"to_node": "fiber (Delhi \u2192 Mumbai)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Delhi \u2192 Mumbai)",
|
||||
"to_node": "Delhi"
|
||||
},
|
||||
{
|
||||
"from_node": "Hong_Kong",
|
||||
"to_node": "fiber (Hong_Kong \u2192 Shanghai)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Hong_Kong \u2192 Shanghai)",
|
||||
"to_node": "Hong_Kong"
|
||||
},
|
||||
{
|
||||
"from_node": "Hong_Kong",
|
||||
"to_node": "fiber (Hong_Kong \u2192 Sydney)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Hong_Kong \u2192 Sydney)",
|
||||
"to_node": "Hong_Kong"
|
||||
},
|
||||
{
|
||||
"from_node": "Hong_Kong",
|
||||
"to_node": "fiber (Hong_Kong \u2192 Taipei)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Hong_Kong \u2192 Taipei)",
|
||||
"to_node": "Hong_Kong"
|
||||
},
|
||||
{
|
||||
"from_node": "Honolulu",
|
||||
"to_node": "fiber (Honolulu \u2192 Sydney)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Honolulu \u2192 Sydney)",
|
||||
"to_node": "Honolulu"
|
||||
},
|
||||
{
|
||||
"from_node": "Honolulu",
|
||||
"to_node": "fiber (Honolulu \u2192 Taipei)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Honolulu \u2192 Taipei)",
|
||||
"to_node": "Honolulu"
|
||||
},
|
||||
{
|
||||
"from_node": "Mumbai",
|
||||
"to_node": "fiber (Mumbai \u2192 Singapore)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Mumbai \u2192 Singapore)",
|
||||
"to_node": "Mumbai"
|
||||
},
|
||||
{
|
||||
"from_node": "Seoul",
|
||||
"to_node": "fiber (Seoul \u2192 Tokyo)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Seoul \u2192 Tokyo)",
|
||||
"to_node": "Seoul"
|
||||
},
|
||||
{
|
||||
"from_node": "Singapore",
|
||||
"to_node": "fiber (Singapore \u2192 Sydney)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Singapore \u2192 Sydney)",
|
||||
"to_node": "Singapore"
|
||||
},
|
||||
{
|
||||
"from_node": "Taipei",
|
||||
"to_node": "fiber (Taipei \u2192 Tokyo)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Taipei \u2192 Tokyo)",
|
||||
"to_node": "Taipei"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Bangkok \u2192 Delhi)",
|
||||
"to_node": "Delhi"
|
||||
},
|
||||
{
|
||||
"from_node": "Delhi",
|
||||
"to_node": "fiber (Bangkok \u2192 Delhi)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Bangkok \u2192 Hong_Kong)",
|
||||
"to_node": "Hong_Kong"
|
||||
},
|
||||
{
|
||||
"from_node": "Hong_Kong",
|
||||
"to_node": "fiber (Bangkok \u2192 Hong_Kong)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Beijing \u2192 Seoul)",
|
||||
"to_node": "Seoul"
|
||||
},
|
||||
{
|
||||
"from_node": "Seoul",
|
||||
"to_node": "fiber (Beijing \u2192 Seoul)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Beijing \u2192 Shanghai)",
|
||||
"to_node": "Shanghai"
|
||||
},
|
||||
{
|
||||
"from_node": "Shanghai",
|
||||
"to_node": "fiber (Beijing \u2192 Shanghai)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Delhi \u2192 Mumbai)",
|
||||
"to_node": "Mumbai"
|
||||
},
|
||||
{
|
||||
"from_node": "Mumbai",
|
||||
"to_node": "fiber (Delhi \u2192 Mumbai)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Hong_Kong \u2192 Shanghai)",
|
||||
"to_node": "Shanghai"
|
||||
},
|
||||
{
|
||||
"from_node": "Shanghai",
|
||||
"to_node": "fiber (Hong_Kong \u2192 Shanghai)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Hong_Kong \u2192 Sydney)",
|
||||
"to_node": "Sydney"
|
||||
},
|
||||
{
|
||||
"from_node": "Sydney",
|
||||
"to_node": "fiber (Hong_Kong \u2192 Sydney)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Hong_Kong \u2192 Taipei)",
|
||||
"to_node": "Taipei"
|
||||
},
|
||||
{
|
||||
"from_node": "Taipei",
|
||||
"to_node": "fiber (Hong_Kong \u2192 Taipei)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Honolulu \u2192 Sydney)",
|
||||
"to_node": "Sydney"
|
||||
},
|
||||
{
|
||||
"from_node": "Sydney",
|
||||
"to_node": "fiber (Honolulu \u2192 Sydney)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Honolulu \u2192 Taipei)",
|
||||
"to_node": "Taipei"
|
||||
},
|
||||
{
|
||||
"from_node": "Taipei",
|
||||
"to_node": "fiber (Honolulu \u2192 Taipei)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Mumbai \u2192 Singapore)",
|
||||
"to_node": "Singapore"
|
||||
},
|
||||
{
|
||||
"from_node": "Singapore",
|
||||
"to_node": "fiber (Mumbai \u2192 Singapore)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Seoul \u2192 Tokyo)",
|
||||
"to_node": "Tokyo"
|
||||
},
|
||||
{
|
||||
"from_node": "Tokyo",
|
||||
"to_node": "fiber (Seoul \u2192 Tokyo)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Singapore \u2192 Sydney)",
|
||||
"to_node": "Sydney"
|
||||
},
|
||||
{
|
||||
"from_node": "Sydney",
|
||||
"to_node": "fiber (Singapore \u2192 Sydney)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Taipei \u2192 Tokyo)",
|
||||
"to_node": "Tokyo"
|
||||
},
|
||||
{
|
||||
"from_node": "Tokyo",
|
||||
"to_node": "fiber (Taipei \u2192 Tokyo)"
|
||||
}
|
||||
]
|
||||
}
|
||||
3678
examples/coronet.conus.json
Normal file
3678
examples/coronet.conus.json
Normal file
File diff suppressed because it is too large
Load Diff
582
examples/coronet.europe.json
Normal file
582
examples/coronet.europe.json
Normal file
@@ -0,0 +1,582 @@
|
||||
{
|
||||
"elements": [
|
||||
{
|
||||
"uid": "Amsterdam",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Amsterdam",
|
||||
"region": "Europe",
|
||||
"latitude": 52.3699996,
|
||||
"longitude": 4.88999915
|
||||
}
|
||||
},
|
||||
"type": "Transceiver"
|
||||
},
|
||||
{
|
||||
"uid": "Berlin",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Berlin",
|
||||
"region": "Europe",
|
||||
"latitude": 52.520002,
|
||||
"longitude": 13.379995
|
||||
}
|
||||
},
|
||||
"type": "Transceiver"
|
||||
},
|
||||
{
|
||||
"uid": "Brussels",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Brussels",
|
||||
"region": "Europe",
|
||||
"latitude": 50.830002,
|
||||
"longitude": 4.330002
|
||||
}
|
||||
},
|
||||
"type": "Transceiver"
|
||||
},
|
||||
{
|
||||
"uid": "Bucharest",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Bucharest",
|
||||
"region": "Europe",
|
||||
"latitude": 44.44,
|
||||
"longitude": 26.1
|
||||
}
|
||||
},
|
||||
"type": "Transceiver"
|
||||
},
|
||||
{
|
||||
"uid": "Frankfurt",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Frankfurt",
|
||||
"region": "Europe",
|
||||
"latitude": 50.1199992,
|
||||
"longitude": 8.68000104
|
||||
}
|
||||
},
|
||||
"type": "Transceiver"
|
||||
},
|
||||
{
|
||||
"uid": "Istanbul",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Istanbul",
|
||||
"region": "Europe",
|
||||
"latitude": 41.1,
|
||||
"longitude": 29.0
|
||||
}
|
||||
},
|
||||
"type": "Transceiver"
|
||||
},
|
||||
{
|
||||
"uid": "London",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "London",
|
||||
"region": "Europe",
|
||||
"latitude": 51.5200005,
|
||||
"longitude": -0.100000296
|
||||
}
|
||||
},
|
||||
"type": "Transceiver"
|
||||
},
|
||||
{
|
||||
"uid": "Madrid",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Madrid",
|
||||
"region": "Europe",
|
||||
"latitude": 40.419998,
|
||||
"longitude": -3.7100002
|
||||
}
|
||||
},
|
||||
"type": "Transceiver"
|
||||
},
|
||||
{
|
||||
"uid": "Paris",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Paris",
|
||||
"region": "Europe",
|
||||
"latitude": 48.86,
|
||||
"longitude": 2.3399995
|
||||
}
|
||||
},
|
||||
"type": "Transceiver"
|
||||
},
|
||||
{
|
||||
"uid": "Rome",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Rome",
|
||||
"region": "Europe",
|
||||
"latitude": 41.8899996,
|
||||
"longitude": 12.5000004
|
||||
}
|
||||
},
|
||||
"type": "Transceiver"
|
||||
},
|
||||
{
|
||||
"uid": "Vienna",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Vienna",
|
||||
"region": "Europe",
|
||||
"latitude": 48.2200024,
|
||||
"longitude": 16.3700005
|
||||
}
|
||||
},
|
||||
"type": "Transceiver"
|
||||
},
|
||||
{
|
||||
"uid": "Warsaw",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Warsaw",
|
||||
"region": "Europe",
|
||||
"latitude": 52.2599987,
|
||||
"longitude": 21.0200005
|
||||
}
|
||||
},
|
||||
"type": "Transceiver"
|
||||
},
|
||||
{
|
||||
"uid": "Zurich",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Zurich",
|
||||
"region": "Europe",
|
||||
"latitude": 47.3800015,
|
||||
"longitude": 8.5399996
|
||||
}
|
||||
},
|
||||
"type": "Transceiver"
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Amsterdam \u2192 Berlin)",
|
||||
"metadata": {
|
||||
"length": 690.608,
|
||||
"units": "km",
|
||||
"location": {
|
||||
"latitude": 52.4450008,
|
||||
"longitude": 9.134997075
|
||||
}
|
||||
},
|
||||
"type": "Fiber"
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Amsterdam \u2192 Brussels)",
|
||||
"metadata": {
|
||||
"length": 210.729,
|
||||
"units": "km",
|
||||
"location": {
|
||||
"latitude": 51.600000800000004,
|
||||
"longitude": 4.610000575000001
|
||||
}
|
||||
},
|
||||
"type": "Fiber"
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Amsterdam \u2192 Frankfurt)",
|
||||
"metadata": {
|
||||
"length": 436.324,
|
||||
"units": "km",
|
||||
"location": {
|
||||
"latitude": 51.2449994,
|
||||
"longitude": 6.785000095000001
|
||||
}
|
||||
},
|
||||
"type": "Fiber"
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Berlin \u2192 Warsaw)",
|
||||
"metadata": {
|
||||
"length": 623.015,
|
||||
"units": "km",
|
||||
"location": {
|
||||
"latitude": 52.390000349999994,
|
||||
"longitude": 17.199997749999998
|
||||
}
|
||||
},
|
||||
"type": "Fiber"
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Brussels \u2192 London)",
|
||||
"metadata": {
|
||||
"length": 381.913,
|
||||
"units": "km",
|
||||
"location": {
|
||||
"latitude": 51.17500125,
|
||||
"longitude": 2.115000852
|
||||
}
|
||||
},
|
||||
"type": "Fiber"
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Bucharest \u2192 Istanbul)",
|
||||
"metadata": {
|
||||
"length": 528.58,
|
||||
"units": "km",
|
||||
"location": {
|
||||
"latitude": 42.769999999999996,
|
||||
"longitude": 27.55
|
||||
}
|
||||
},
|
||||
"type": "Fiber"
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Bucharest \u2192 Warsaw)",
|
||||
"metadata": {
|
||||
"length": 1136.2,
|
||||
"units": "km",
|
||||
"location": {
|
||||
"latitude": 48.34999935,
|
||||
"longitude": 23.56000025
|
||||
}
|
||||
},
|
||||
"type": "Fiber"
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Frankfurt \u2192 Vienna)",
|
||||
"metadata": {
|
||||
"length": 717.001,
|
||||
"units": "km",
|
||||
"location": {
|
||||
"latitude": 49.1700008,
|
||||
"longitude": 12.52500077
|
||||
}
|
||||
},
|
||||
"type": "Fiber"
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Istanbul \u2192 Rome)",
|
||||
"metadata": {
|
||||
"length": 1650.406,
|
||||
"units": "km",
|
||||
"location": {
|
||||
"latitude": 41.4949998,
|
||||
"longitude": 20.7500002
|
||||
}
|
||||
},
|
||||
"type": "Fiber"
|
||||
},
|
||||
{
|
||||
"uid": "fiber (London \u2192 Paris)",
|
||||
"metadata": {
|
||||
"length": 411.692,
|
||||
"units": "km",
|
||||
"location": {
|
||||
"latitude": 50.19000025,
|
||||
"longitude": 1.1199996019999998
|
||||
}
|
||||
},
|
||||
"type": "Fiber"
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Madrid \u2192 Paris)",
|
||||
"metadata": {
|
||||
"length": 1263.619,
|
||||
"units": "km",
|
||||
"location": {
|
||||
"latitude": 44.639999,
|
||||
"longitude": -0.6850003500000001
|
||||
}
|
||||
},
|
||||
"type": "Fiber"
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Madrid \u2192 Zurich)",
|
||||
"metadata": {
|
||||
"length": 1497.358,
|
||||
"units": "km",
|
||||
"location": {
|
||||
"latitude": 43.89999975,
|
||||
"longitude": 2.4149997
|
||||
}
|
||||
},
|
||||
"type": "Fiber"
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Rome \u2192 Vienna)",
|
||||
"metadata": {
|
||||
"length": 920.026,
|
||||
"units": "km",
|
||||
"location": {
|
||||
"latitude": 45.055001000000004,
|
||||
"longitude": 14.43500045
|
||||
}
|
||||
},
|
||||
"type": "Fiber"
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Rome \u2192 Zurich)",
|
||||
"metadata": {
|
||||
"length": 823.4,
|
||||
"units": "km",
|
||||
"location": {
|
||||
"latitude": 44.63500055,
|
||||
"longitude": 10.52
|
||||
}
|
||||
},
|
||||
"type": "Fiber"
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Vienna \u2192 Warsaw)",
|
||||
"metadata": {
|
||||
"length": 669.297,
|
||||
"units": "km",
|
||||
"location": {
|
||||
"latitude": 50.24000055,
|
||||
"longitude": 18.6950005
|
||||
}
|
||||
},
|
||||
"type": "Fiber"
|
||||
}
|
||||
],
|
||||
"connections": [
|
||||
{
|
||||
"from_node": "Amsterdam",
|
||||
"to_node": "fiber (Amsterdam \u2192 Berlin)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Amsterdam \u2192 Berlin)",
|
||||
"to_node": "Amsterdam"
|
||||
},
|
||||
{
|
||||
"from_node": "Amsterdam",
|
||||
"to_node": "fiber (Amsterdam \u2192 Brussels)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Amsterdam \u2192 Brussels)",
|
||||
"to_node": "Amsterdam"
|
||||
},
|
||||
{
|
||||
"from_node": "Amsterdam",
|
||||
"to_node": "fiber (Amsterdam \u2192 Frankfurt)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Amsterdam \u2192 Frankfurt)",
|
||||
"to_node": "Amsterdam"
|
||||
},
|
||||
{
|
||||
"from_node": "Berlin",
|
||||
"to_node": "fiber (Berlin \u2192 Warsaw)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Berlin \u2192 Warsaw)",
|
||||
"to_node": "Berlin"
|
||||
},
|
||||
{
|
||||
"from_node": "Brussels",
|
||||
"to_node": "fiber (Brussels \u2192 London)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Brussels \u2192 London)",
|
||||
"to_node": "Brussels"
|
||||
},
|
||||
{
|
||||
"from_node": "Bucharest",
|
||||
"to_node": "fiber (Bucharest \u2192 Istanbul)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Bucharest \u2192 Istanbul)",
|
||||
"to_node": "Bucharest"
|
||||
},
|
||||
{
|
||||
"from_node": "Bucharest",
|
||||
"to_node": "fiber (Bucharest \u2192 Warsaw)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Bucharest \u2192 Warsaw)",
|
||||
"to_node": "Bucharest"
|
||||
},
|
||||
{
|
||||
"from_node": "Frankfurt",
|
||||
"to_node": "fiber (Frankfurt \u2192 Vienna)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Frankfurt \u2192 Vienna)",
|
||||
"to_node": "Frankfurt"
|
||||
},
|
||||
{
|
||||
"from_node": "Istanbul",
|
||||
"to_node": "fiber (Istanbul \u2192 Rome)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Istanbul \u2192 Rome)",
|
||||
"to_node": "Istanbul"
|
||||
},
|
||||
{
|
||||
"from_node": "London",
|
||||
"to_node": "fiber (London \u2192 Paris)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (London \u2192 Paris)",
|
||||
"to_node": "London"
|
||||
},
|
||||
{
|
||||
"from_node": "Madrid",
|
||||
"to_node": "fiber (Madrid \u2192 Paris)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Madrid \u2192 Paris)",
|
||||
"to_node": "Madrid"
|
||||
},
|
||||
{
|
||||
"from_node": "Madrid",
|
||||
"to_node": "fiber (Madrid \u2192 Zurich)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Madrid \u2192 Zurich)",
|
||||
"to_node": "Madrid"
|
||||
},
|
||||
{
|
||||
"from_node": "Rome",
|
||||
"to_node": "fiber (Rome \u2192 Vienna)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Rome \u2192 Vienna)",
|
||||
"to_node": "Rome"
|
||||
},
|
||||
{
|
||||
"from_node": "Rome",
|
||||
"to_node": "fiber (Rome \u2192 Zurich)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Rome \u2192 Zurich)",
|
||||
"to_node": "Rome"
|
||||
},
|
||||
{
|
||||
"from_node": "Vienna",
|
||||
"to_node": "fiber (Vienna \u2192 Warsaw)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Vienna \u2192 Warsaw)",
|
||||
"to_node": "Vienna"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Amsterdam \u2192 Berlin)",
|
||||
"to_node": "Berlin"
|
||||
},
|
||||
{
|
||||
"from_node": "Berlin",
|
||||
"to_node": "fiber (Amsterdam \u2192 Berlin)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Amsterdam \u2192 Brussels)",
|
||||
"to_node": "Brussels"
|
||||
},
|
||||
{
|
||||
"from_node": "Brussels",
|
||||
"to_node": "fiber (Amsterdam \u2192 Brussels)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Amsterdam \u2192 Frankfurt)",
|
||||
"to_node": "Frankfurt"
|
||||
},
|
||||
{
|
||||
"from_node": "Frankfurt",
|
||||
"to_node": "fiber (Amsterdam \u2192 Frankfurt)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Berlin \u2192 Warsaw)",
|
||||
"to_node": "Warsaw"
|
||||
},
|
||||
{
|
||||
"from_node": "Warsaw",
|
||||
"to_node": "fiber (Berlin \u2192 Warsaw)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Brussels \u2192 London)",
|
||||
"to_node": "London"
|
||||
},
|
||||
{
|
||||
"from_node": "London",
|
||||
"to_node": "fiber (Brussels \u2192 London)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Bucharest \u2192 Istanbul)",
|
||||
"to_node": "Istanbul"
|
||||
},
|
||||
{
|
||||
"from_node": "Istanbul",
|
||||
"to_node": "fiber (Bucharest \u2192 Istanbul)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Bucharest \u2192 Warsaw)",
|
||||
"to_node": "Warsaw"
|
||||
},
|
||||
{
|
||||
"from_node": "Warsaw",
|
||||
"to_node": "fiber (Bucharest \u2192 Warsaw)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Frankfurt \u2192 Vienna)",
|
||||
"to_node": "Vienna"
|
||||
},
|
||||
{
|
||||
"from_node": "Vienna",
|
||||
"to_node": "fiber (Frankfurt \u2192 Vienna)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Istanbul \u2192 Rome)",
|
||||
"to_node": "Rome"
|
||||
},
|
||||
{
|
||||
"from_node": "Rome",
|
||||
"to_node": "fiber (Istanbul \u2192 Rome)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (London \u2192 Paris)",
|
||||
"to_node": "Paris"
|
||||
},
|
||||
{
|
||||
"from_node": "Paris",
|
||||
"to_node": "fiber (London \u2192 Paris)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Madrid \u2192 Paris)",
|
||||
"to_node": "Paris"
|
||||
},
|
||||
{
|
||||
"from_node": "Paris",
|
||||
"to_node": "fiber (Madrid \u2192 Paris)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Madrid \u2192 Zurich)",
|
||||
"to_node": "Zurich"
|
||||
},
|
||||
{
|
||||
"from_node": "Zurich",
|
||||
"to_node": "fiber (Madrid \u2192 Zurich)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Rome \u2192 Vienna)",
|
||||
"to_node": "Vienna"
|
||||
},
|
||||
{
|
||||
"from_node": "Vienna",
|
||||
"to_node": "fiber (Rome \u2192 Vienna)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Rome \u2192 Zurich)",
|
||||
"to_node": "Zurich"
|
||||
},
|
||||
{
|
||||
"from_node": "Zurich",
|
||||
"to_node": "fiber (Rome \u2192 Zurich)"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Vienna \u2192 Warsaw)",
|
||||
"to_node": "Warsaw"
|
||||
},
|
||||
{
|
||||
"from_node": "Warsaw",
|
||||
"to_node": "fiber (Vienna \u2192 Warsaw)"
|
||||
}
|
||||
]
|
||||
}
|
||||
3454
examples/coronet.json
Normal file
3454
examples/coronet.json
Normal file
File diff suppressed because it is too large
Load Diff
5738
examples/coronet_conus_example.json
Normal file
5738
examples/coronet_conus_example.json
Normal file
File diff suppressed because it is too large
Load Diff
8
examples/edfa/Pchan2D.txt
Executable file
8
examples/edfa/Pchan2D.txt
Executable file
@@ -0,0 +1,8 @@
|
||||
-1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01
|
||||
-2.0000000000000000e+01 -2.0000000000000000e+01 -2.0000000000000000e+01 -2.0000000000000000e+01 -2.0000000000000000e+01 -2.0000000000000000e+01 -2.0000000000000000e+01 -2.0000000000000000e+01 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02
|
||||
-1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -2.0000000000000000e+01 -2.0000000000000000e+01 -2.0000000000000000e+01 -2.0000000000000000e+01 -2.0000000000000000e+01 -2.0000000000000000e+01 -2.0000000000000000e+01 -2.0000000000000000e+01
|
||||
-2.0500000000000000e+01 -2.0489473680000000e+01 -2.0478947370000000e+01 -2.0468421050000000e+01 -2.0457894740000000e+01 -2.0447368420000000e+01 -2.0436842110000001e+01 -2.0426315790000000e+01 -2.0415789470000000e+01 -2.0405263160000001e+01 -2.0394736840000000e+01 -2.0384210530000001e+01 -2.0373684210000000e+01 -2.0363157890000000e+01 -2.0352631580000001e+01 -2.0342105260000000e+01 -2.0331578950000001e+01 -2.0321052630000001e+01 -2.0310526320000001e+01 -2.0300000000000001e+01 -2.0289473680000000e+01 -2.0278947370000001e+01 -2.0268421050000001e+01 -2.0257894740000001e+01 -2.0247368420000001e+01 -2.0236842110000001e+01 -2.0226315790000001e+01 -2.0215789470000001e+01 -2.0205263160000001e+01 -2.0194736840000001e+01 -2.0184210530000001e+01 -2.0173684210000001e+01 -2.0163157890000001e+01 -2.0152631580000001e+01 -2.0142105260000001e+01 -2.0131578950000002e+01 -2.0121052630000001e+01 -2.0110526320000002e+01 -2.0100000000000001e+01 -2.0089473680000001e+01 -2.0078947370000002e+01 -2.0068421050000001e+01 -2.0057894739999998e+01 -2.0047368420000002e+01 -2.0036842109999998e+01 -2.0026315790000002e+01 -2.0015789470000001e+01 -2.0005263159999998e+01 -1.9994736840000002e+01 -1.9984210529999999e+01 -1.9973684209999998e+01 -1.9963157890000002e+01 -1.9952631579999998e+01 -1.9942105260000002e+01 -1.9931578949999999e+01 -1.9921052629999998e+01 -1.9910526319999999e+01 -1.9899999999999999e+01 -1.9889473679999998e+01 -1.9878947369999999e+01 -1.9868421049999998e+01 -1.9857894739999999e+01 -1.9847368419999999e+01 -1.9836842109999999e+01 -1.9826315789999999e+01 -1.9815789469999999e+01 -1.9805263159999999e+01 -1.9794736839999999e+01 -1.9784210529999999e+01 -1.9773684209999999e+01 -1.9763157889999999e+01 -1.9752631579999999e+01 -1.9742105259999999e+01 -1.9731578949999999e+01 -1.9721052629999999e+01 -1.9710526320000000e+01 -1.9699999999999999e+01 -1.9689473679999999e+01 -1.9678947369999999e+01 -1.9668421049999999e+01 -1.9657894740000000e+01 -1.9647368419999999e+01 -1.9636842110000000e+01 -1.9626315790000000e+01 -1.9615789469999999e+01 -1.9605263160000000e+01 -1.9594736839999999e+01 -1.9584210530000000e+01 -1.9573684210000000e+01 -1.9563157889999999e+01 -1.9552631580000000e+01 -1.9542105260000000e+01 -1.9531578950000000e+01 -1.9521052630000000e+01 -1.9510526320000000e+01 -1.9500000000000000e+01
|
||||
-2.0500000000000000e+01 -2.0489473680000000e+01 -2.0478947370000000e+01 -2.0468421050000000e+01 -2.0457894740000000e+01 -2.0447368420000000e+01 -2.0436842110000001e+01 -2.0426315790000000e+01 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.9573684210000000e+01 -1.9563157889999999e+01 -1.9552631580000000e+01 -1.9542105260000000e+01 -1.9531578950000000e+01 -1.9521052630000000e+01 -1.9510526320000000e+01 -1.9500000000000000e+01
|
||||
-1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.4460000000000001e+01
|
||||
-1.4460000000000001e+01 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01
|
||||
-1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.4460000000000001e+01 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02
|
||||
8
examples/edfa/Pchan2DLegend.txt
Executable file
8
examples/edfa/Pchan2DLegend.txt
Executable file
@@ -0,0 +1,8 @@
|
||||
7.0000000000000000e+01 1.1700000000000000e+02 1.0800000000000000e+02 1.0800000000000000e+02 3.2000000000000000e+01 7.0000000000000000e+01 1.0800000000000000e+02 9.7000000000000000e+01 1.1600000000000000e+02 3.2000000000000000e+01 3.2000000000000000e+01 3.2000000000000000e+01 3.2000000000000000e+01 3.2000000000000000e+01 3.2000000000000000e+01
|
||||
7.9000000000000000e+01 1.1000000000000000e+02 1.0100000000000000e+02 3.2000000000000000e+01 7.1000000000000000e+01 1.1400000000000000e+02 1.1100000000000000e+02 1.1700000000000000e+02 1.1200000000000000e+02 3.2000000000000000e+01 6.6000000000000000e+01 1.0800000000000000e+02 1.1700000000000000e+02 1.0100000000000000e+02 3.2000000000000000e+01
|
||||
7.9000000000000000e+01 1.1000000000000000e+02 1.0100000000000000e+02 3.2000000000000000e+01 7.1000000000000000e+01 1.1400000000000000e+02 1.1100000000000000e+02 1.1700000000000000e+02 1.1200000000000000e+02 3.2000000000000000e+01 8.2000000000000000e+01 1.0100000000000000e+02 1.0000000000000000e+02 3.2000000000000000e+01 3.2000000000000000e+01
|
||||
7.0000000000000000e+01 1.1700000000000000e+02 1.0800000000000000e+02 1.0800000000000000e+02 3.2000000000000000e+01 1.1900000000000000e+02 3.2000000000000000e+01 8.3000000000000000e+01 8.2000000000000000e+01 8.3000000000000000e+01 3.2000000000000000e+01 3.2000000000000000e+01 3.2000000000000000e+01 3.2000000000000000e+01 3.2000000000000000e+01
|
||||
6.6000000000000000e+01 1.1100000000000000e+02 1.1600000000000000e+02 1.0400000000000000e+02 3.2000000000000000e+01 6.9000000000000000e+01 1.1000000000000000e+02 1.0000000000000000e+02 1.1500000000000000e+02 3.2000000000000000e+01 1.1900000000000000e+02 3.2000000000000000e+01 8.3000000000000000e+01 8.2000000000000000e+01 8.3000000000000000e+01
|
||||
1.0400000000000000e+02 1.0100000000000000e+02 9.7000000000000000e+01 1.1800000000000000e+02 1.2100000000000000e+02 3.2000000000000000e+01 9.8000000000000000e+01 1.0800000000000000e+02 1.1700000000000000e+02 1.0100000000000000e+02 3.2000000000000000e+01 3.2000000000000000e+01 3.2000000000000000e+01 3.2000000000000000e+01 3.2000000000000000e+01
|
||||
1.0400000000000000e+02 1.0100000000000000e+02 9.7000000000000000e+01 1.1800000000000000e+02 1.2100000000000000e+02 3.2000000000000000e+01 1.1400000000000000e+02 1.0100000000000000e+02 1.0000000000000000e+02 3.2000000000000000e+01 3.2000000000000000e+01 3.2000000000000000e+01 3.2000000000000000e+01 3.2000000000000000e+01 3.2000000000000000e+01
|
||||
1.1900000000000000e+02 1.1100000000000000e+02 1.1400000000000000e+02 1.1500000000000000e+02 1.1600000000000000e+02 3.2000000000000000e+01 9.9000000000000000e+01 9.7000000000000000e+01 1.1500000000000000e+02 1.0100000000000000e+02 3.2000000000000000e+01 3.2000000000000000e+01 3.2000000000000000e+01 3.2000000000000000e+01 3.2000000000000000e+01
|
||||
9
examples/edfa/edfa_config.json
Normal file
9
examples/edfa/edfa_config.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"params": {
|
||||
"dfg": [25.13596985, 25.11822814, 25.09542133, 25.06245771, 25.02602765, 24.99637953, 24.98167255, 24.97530668, 24.98320726, 24.99718565, 25.01757247, 25.03832781, 25.05495585, 25.0670719, 25.07091411, 25.07094365, 25.07114324, 25.07533627, 25.08731018, 25.10313936, 25.12276204, 25.14239479, 25.15945633, 25.17392704, 25.17673767, 25.17037141, 25.15216254, 25.1311431, 25.10802335, 25.08548777, 25.06916675, 25.05848176, 25.05447313, 25.05154441, 25.04946059, 25.04717849, 25.04551656, 25.04467649, 25.0407292, 25.03285408, 25.0234883, 25.01659234, 25.01332136, 25.01123434, 25.01030015, 25.00936548, 25.00873964, 25.00842535, 25.00696466, 25.0040431, 25.00070998, 24.9984232, 24.99306332, 24.98352421, 24.97125103, 24.96038108, 24.94888721, 24.93531489, 24.92131927, 24.90898697, 24.89896514, 24.88958463, 24.8808387, 24.87210092, 24.86462026, 24.85839773, 24.85445838, 24.85155443, 24.85176601, 24.85408014, 24.85909624, 24.86474458, 24.87203486, 24.8803652, 24.88910669, 24.89721313, 24.90282604, 24.9065669, 24.9086508, 24.91093944, 24.91343079, 24.91592344, 24.92155351, 24.93031861, 24.94052812, 24.94904669, 24.95757123, 24.96781845, 24.98180093, 24.99782686, 25.01393183, 25.02809846, 25.04032575, 25.05256981, 25.06479701, 25.07704697],
|
||||
"dgt": [2.714526681131686, 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.0],
|
||||
"nf_fit_coeff": [0.000168241, 0.0469961, 0.0359549, 5.82851],
|
||||
"nf_ripple": [-0.315374332, -0.315374332, -0.3154009157100272, -0.3184914611751095, -0.32158358425400546, -0.3246772861549999, -0.32762368641496226, -0.3205413846123276, -0.31345546385118733, -0.3063659213569748, -0.29920267890990127, -0.27061972852631744, -0.24202215770774693, -0.21340995523361256, -0.18478227130158695, -0.14809761118389625, -0.11139416731807622, -0.07467192527357988, -0.038026748965679924, -0.019958469399422092, -0.0018809287980157928, 0.01620587996057356, 0.03430196400570967, 0.05240733047405406, 0.07052198650959736, 0.079578036683472, 0.08854664736190952, 0.0975198632319653, 0.10649768784154924, 0.0977413804499074, 0.08880343717266004, 0.07986089973284587, 0.0709137645874038, 0.06333589274056531, 0.055756212252058776, 0.04817263174786321, 0.04058514821716236, 0.03338159167571013, 0.026178308595650738, 0.018971315351761126, 0.011760609076833628, 0.01695029492275999, 0.02227499135770144, 0.02760243318910433, 0.03293262254079026, 0.038265561538776145, 0.04360125231127117, 0.03485699074348155, 0.025991055149117932, 0.017120541224980364, 0.008275758735920322, 0.0019423214065246042, -0.004394389017104359, -0.010734375072893196, -0.017077639301414434, -0.02467970289957285, -0.03229797040382168, -0.03992018009047725, -0.04753456632753024, -0.049234003141433724, -0.05093432003654719, -0.05263551769669225, -0.05433759680640246, -0.0560405580509193, -0.057718452237076875, -0.056840590379175944, -0.055962273198734966, -0.05508350034141658, -0.054204271452516814, -0.05839608872695511, -0.06262733016971533, -0.0668607690892037, -0.07090173625606945, -0.05209609730905224, -0.03328068412141294, -0.014455489070928059, 0.004315038757905716, 0.014839202394482527, 0.025368841662503576, 0.03590396083646565, 0.0464445641953214, 0.05699065602246746, 0.06754224060577406, 0.10002709623672751, 0.13258013095133617, 0.1651501336277331, 0.1977371175359939, 0.23194802687829724, 0.26618779883837107, 0.3004454365808535, 0.33472095409250663, 0.35929034770587287, 0.38384389188855605, 0.40841026111391787, 0.43298946543290784, 0.43298946543290784],
|
||||
"frequencies": []
|
||||
}
|
||||
}
|
||||
77
examples/edfa/edfa_example_network.json
Normal file
77
examples/edfa/edfa_example_network.json
Normal file
@@ -0,0 +1,77 @@
|
||||
{
|
||||
"network_name": "EDFA Example Network - P2P",
|
||||
"elements": [{
|
||||
"uid": "Site A",
|
||||
"type": "Transceiver",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Site A",
|
||||
"region": "",
|
||||
"latitude": 0,
|
||||
"longitude": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "Span1",
|
||||
"type": "Fiber",
|
||||
"params": {
|
||||
"length": 80,
|
||||
"loss_coef": 0.2,
|
||||
"length_units": "km",
|
||||
"dispersion": 16.7E-6,
|
||||
"gamma": 1.27E-3
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"region": "",
|
||||
"latitude": 1,
|
||||
"longitude": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "Edfa1",
|
||||
"type": "Edfa",
|
||||
"operational": {
|
||||
"gain_target": 16,
|
||||
"tilt_target": 0
|
||||
},
|
||||
"config_from_json": "edfa_config.json",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"region": "",
|
||||
"latitude": 2,
|
||||
"longitude": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "Site B",
|
||||
"type": "Transceiver",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Site B",
|
||||
"region": "",
|
||||
"latitude": 3,
|
||||
"longitude": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
],
|
||||
"connections": [{
|
||||
"from_node": "Site A",
|
||||
"to_node": "Span1"
|
||||
},
|
||||
{
|
||||
"from_node": "Span1",
|
||||
"to_node": "Edfa1"
|
||||
},
|
||||
{
|
||||
"from_node": "Edfa1",
|
||||
"to_node": "Site B"
|
||||
}
|
||||
|
||||
]
|
||||
}
|
||||
72
examples/edfa/example.py
Normal file
72
examples/edfa/example.py
Normal file
@@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
|
||||
from gnpy.core.utils import (load_json,
|
||||
itufs,
|
||||
freq2wavelength,
|
||||
lin2db,
|
||||
db2lin)
|
||||
from gnpy.core import network
|
||||
|
||||
topology = load_json('edfa_example_network.json')
|
||||
nw = network.network_from_json(topology)
|
||||
pch2d_legend_data = np.loadtxt('Pchan2DLegend.txt')
|
||||
pch2d = np.loadtxt('Pchan2D.txt')
|
||||
|
||||
ch_spacing = 0.05
|
||||
fc = itufs(ch_spacing)
|
||||
lc = freq2wavelength(fc) / 1000
|
||||
nchan = np.arange(len(lc))
|
||||
df = np.ones(len(lc)) * ch_spacing
|
||||
|
||||
edfa1 = [n for n in nw.nodes() if n.uid == 'Edfa1'][0]
|
||||
edfa1.gain_target = 20.0
|
||||
edfa1.tilt_target = -0.7
|
||||
edfa1.calc_nf()
|
||||
|
||||
results = []
|
||||
for Pin in pch2d:
|
||||
chgain = edfa1.gain_profile(Pin)
|
||||
pase = edfa1.noise_profile(chgain, fc, df)
|
||||
pout = lin2db(db2lin(Pin + chgain) + db2lin(pase))
|
||||
results.append(pout)
|
||||
|
||||
# Generate legend text
|
||||
|
||||
pch2d_legend = []
|
||||
for ea in pch2d_legend_data:
|
||||
s = ''.join([chr(xx) for xx in ea.astype(dtype=int)]).strip()
|
||||
pch2d_legend.append(s)
|
||||
|
||||
# Plot
|
||||
axis_font = {'fontname': 'Arial', 'size': '16', 'fontweight': 'bold'}
|
||||
title_font = {'fontname': 'Arial', 'size': '17', 'fontweight': 'bold'}
|
||||
tic_font = {'fontname': 'Arial', 'size': '12'}
|
||||
plt.rcParams["font.family"] = "Arial"
|
||||
plt.figure()
|
||||
plt.plot(nchan, pch2d.T, '.-', lw=2)
|
||||
plt.xlabel('Channel Number', **axis_font)
|
||||
plt.ylabel('Channel Power [dBm]', **axis_font)
|
||||
plt.title('Input Power Profiles for Different Channel Loading', **title_font)
|
||||
plt.legend(pch2d_legend, loc=5)
|
||||
plt.grid()
|
||||
plt.ylim((-100, -10))
|
||||
plt.xlim((0, 110))
|
||||
plt.xticks(np.arange(0, 100, 10), **tic_font)
|
||||
plt.yticks(np.arange(-110, -10, 10), **tic_font)
|
||||
plt.figure()
|
||||
for result in results:
|
||||
plt.plot(nchan, result, '.-', lw=2)
|
||||
plt.title('Output Power w/ ASE for Different Channel Loading', **title_font)
|
||||
plt.xlabel('Channel Number', **axis_font)
|
||||
plt.ylabel('Channel Power [dBm]', **axis_font)
|
||||
plt.grid()
|
||||
plt.ylim((-50, 10))
|
||||
plt.xlim((0, 100))
|
||||
plt.xticks(np.arange(0, 100, 10), **tic_font)
|
||||
plt.yticks(np.arange(-50, 10, 10), **tic_font)
|
||||
plt.legend(pch2d_legend, loc=5)
|
||||
plt.show()
|
||||
313
examples/edfa_config.json
Normal file
313
examples/edfa_config.json
Normal file
@@ -0,0 +1,313 @@
|
||||
{
|
||||
"params": {
|
||||
"gain_flatmax": 25,
|
||||
"gain_min": 15,
|
||||
"p_max": 21,
|
||||
"nf_fit_coeff": [
|
||||
0.000168241,
|
||||
0.0469961,
|
||||
0.0359549,
|
||||
5.82851
|
||||
],
|
||||
"nf_ripple": [
|
||||
-0.3110761646066259,
|
||||
-0.3110761646066259,
|
||||
-0.31110274831665313,
|
||||
-0.31419329378173544,
|
||||
-0.3172854168606314,
|
||||
-0.32037911876162584,
|
||||
-0.3233255190215882,
|
||||
-0.31624321721895354,
|
||||
-0.30915729645781326,
|
||||
-0.30206775396360075,
|
||||
-0.2949045115165272,
|
||||
-0.26632156113294336,
|
||||
-0.23772399031437283,
|
||||
-0.20911178784023846,
|
||||
-0.18048410390821285,
|
||||
-0.14379944379052215,
|
||||
-0.10709599992470213,
|
||||
-0.07037375788020579,
|
||||
-0.03372858157230583,
|
||||
-0.015660302006048,
|
||||
0.0024172385953583004,
|
||||
0.020504047353947653,
|
||||
0.03860013139908377,
|
||||
0.05670549786742816,
|
||||
0.07482015390297145,
|
||||
0.0838762040768461,
|
||||
0.09284481475528361,
|
||||
0.1018180306253394,
|
||||
0.11079585523492333,
|
||||
0.1020395478432815,
|
||||
0.09310160456603413,
|
||||
0.08415906712621996,
|
||||
0.07521193198077789,
|
||||
0.0676340601339394,
|
||||
0.06005437964543287,
|
||||
0.052470799141237305,
|
||||
0.044883315610536455,
|
||||
0.037679759069084225,
|
||||
0.03047647598902483,
|
||||
0.02326948274513522,
|
||||
0.01605877647020772,
|
||||
0.021248462316134083,
|
||||
0.02657315875107553,
|
||||
0.03190060058247842,
|
||||
0.03723078993416436,
|
||||
0.04256372893215024,
|
||||
0.047899419704645264,
|
||||
0.03915515813685565,
|
||||
0.030289222542492025,
|
||||
0.021418708618354456,
|
||||
0.012573926129294415,
|
||||
0.006240488799898697,
|
||||
-9.622162373026585e-05,
|
||||
-0.006436207679519103,
|
||||
-0.012779471908040341,
|
||||
-0.02038153550619876,
|
||||
-0.027999803010447587,
|
||||
-0.035622012697103154,
|
||||
-0.043236398934156144,
|
||||
-0.04493583574805963,
|
||||
-0.04663615264317309,
|
||||
-0.048337350303318156,
|
||||
-0.050039429413028365,
|
||||
-0.051742390657545205,
|
||||
-0.05342028484370278,
|
||||
-0.05254242298580185,
|
||||
-0.05166410580536087,
|
||||
-0.05078533294804249,
|
||||
-0.04990610405914272,
|
||||
-0.05409792133358102,
|
||||
-0.05832916277634124,
|
||||
-0.06256260169582961,
|
||||
-0.06660356886269536,
|
||||
-0.04779792991567815,
|
||||
-0.028982516728038848,
|
||||
-0.010157321677553965,
|
||||
0.00861320615127981,
|
||||
0.01913736978785662,
|
||||
0.029667009055877668,
|
||||
0.04020212822983975,
|
||||
0.050742731588695494,
|
||||
0.061288823415841555,
|
||||
0.07184040799914815,
|
||||
0.1043252636301016,
|
||||
0.13687829834471027,
|
||||
0.1694483010211072,
|
||||
0.202035284929368,
|
||||
0.23624619427167134,
|
||||
0.27048596623174515,
|
||||
0.30474360397422756,
|
||||
0.3390191214858807,
|
||||
0.36358851509924695,
|
||||
0.38814205928193013,
|
||||
0.41270842850729195,
|
||||
0.4372876328262819,
|
||||
0.4372876328262819
|
||||
],
|
||||
"dgt": [
|
||||
2.714526681131686,
|
||||
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.0
|
||||
],
|
||||
"nf_model": {
|
||||
"enabled": true,
|
||||
"nf1": 5.727887800964238,
|
||||
"nf2": 7.727887800964238,
|
||||
"delta_p": 5.238350271545567
|
||||
},
|
||||
"gain_ripple": [
|
||||
0.1359703369791596,
|
||||
0.11822862697916037,
|
||||
0.09542181697916163,
|
||||
0.06245819697916133,
|
||||
0.02602813697916062,
|
||||
-0.0036199830208403228,
|
||||
-0.018326963020840026,
|
||||
-0.0246928330208398,
|
||||
-0.016792253020838643,
|
||||
-0.0028138630208403015,
|
||||
0.017572956979162058,
|
||||
0.038328296979159404,
|
||||
0.054956336979159914,
|
||||
0.0670723869791594,
|
||||
0.07091459697916136,
|
||||
0.07094413697916124,
|
||||
0.07114372697916238,
|
||||
0.07533675697916209,
|
||||
0.08731066697916035,
|
||||
0.10313984697916112,
|
||||
0.12276252697916235,
|
||||
0.14239527697916188,
|
||||
0.15945681697916214,
|
||||
0.1739275269791598,
|
||||
0.1767381569791624,
|
||||
0.17037189697916233,
|
||||
0.15216302697916007,
|
||||
0.13114358697916018,
|
||||
0.10802383697916085,
|
||||
0.08548825697916129,
|
||||
0.06916723697916183,
|
||||
0.05848224697916038,
|
||||
0.05447361697916264,
|
||||
0.05154489697916276,
|
||||
0.04946107697915991,
|
||||
0.04717897697916129,
|
||||
0.04551704697916037,
|
||||
0.04467697697916151,
|
||||
0.04072968697916224,
|
||||
0.03285456697916089,
|
||||
0.023488786979161347,
|
||||
0.01659282697915998,
|
||||
0.013321846979160057,
|
||||
0.011234826979162449,
|
||||
0.01030063697916006,
|
||||
0.00936596697916059,
|
||||
0.00874012697916271,
|
||||
0.00842583697916055,
|
||||
0.006965146979162284,
|
||||
0.0040435869791615175,
|
||||
0.0007104669791608842,
|
||||
-0.0015763130208377163,
|
||||
-0.006936193020838033,
|
||||
-0.016475303020840215,
|
||||
-0.028748483020837767,
|
||||
-0.039618433020837784,
|
||||
-0.051112303020840244,
|
||||
-0.06468462302083822,
|
||||
-0.07868024302083754,
|
||||
-0.09101254302083817,
|
||||
-0.10103437302083762,
|
||||
-0.11041488302083735,
|
||||
-0.11916081302083725,
|
||||
-0.12789859302083784,
|
||||
-0.1353792530208402,
|
||||
-0.14160178302083892,
|
||||
-0.1455411330208385,
|
||||
-0.1484450830208388,
|
||||
-0.14823350302084037,
|
||||
-0.14591937302083835,
|
||||
-0.1409032730208395,
|
||||
-0.13525493302083902,
|
||||
-0.1279646530208396,
|
||||
-0.11963431302083904,
|
||||
-0.11089282302084058,
|
||||
-0.1027863830208382,
|
||||
-0.09717347302083823,
|
||||
-0.09343261302083761,
|
||||
-0.0913487130208388,
|
||||
-0.08906007302083907,
|
||||
-0.0865687230208394,
|
||||
-0.08407607302083875,
|
||||
-0.07844600302084004,
|
||||
-0.06968090302083851,
|
||||
-0.05947139302083926,
|
||||
-0.05095282302083959,
|
||||
-0.042428283020839785,
|
||||
-0.03218106302083967,
|
||||
-0.01819858302084043,
|
||||
-0.0021726530208390216,
|
||||
0.01393231697916164,
|
||||
0.028098946979159933,
|
||||
0.040326236979161934,
|
||||
0.05257029697916238,
|
||||
0.06479749697916048,
|
||||
0.07704745697916238
|
||||
]
|
||||
}
|
||||
}
|
||||
1
examples/edfa_model/DFG_96.txt
Executable file
1
examples/edfa_model/DFG_96.txt
Executable file
@@ -0,0 +1 @@
|
||||
2.5135969849999999e+01 2.5118228139999999e+01 2.5095421330000001e+01 2.5062457710000000e+01 2.5026027650000000e+01 2.4996379529999999e+01 2.4981672549999999e+01 2.4975306679999999e+01 2.4983207260000000e+01 2.4997185649999999e+01 2.5017572470000001e+01 2.5038327809999998e+01 2.5054955849999999e+01 2.5067071899999998e+01 2.5070914110000000e+01 2.5070943650000000e+01 2.5071143240000001e+01 2.5075336270000001e+01 2.5087310179999999e+01 2.5103139360000000e+01 2.5122762040000001e+01 2.5142394790000001e+01 2.5159456330000001e+01 2.5173927039999999e+01 2.5176737670000001e+01 2.5170371410000001e+01 2.5152162539999999e+01 2.5131143099999999e+01 2.5108023350000000e+01 2.5085487770000000e+01 2.5069166750000001e+01 2.5058481759999999e+01 2.5054473130000002e+01 2.5051544410000002e+01 2.5049460589999999e+01 2.5047178490000000e+01 2.5045516559999999e+01 2.5044676490000001e+01 2.5040729200000001e+01 2.5032854080000000e+01 2.5023488300000000e+01 2.5016592339999999e+01 2.5013321359999999e+01 2.5011234340000001e+01 2.5010300149999999e+01 2.5009365480000000e+01 2.5008739640000002e+01 2.5008425350000000e+01 2.5006964660000001e+01 2.5004043100000001e+01 2.5000709980000000e+01 2.4998423200000001e+01 2.4993063320000001e+01 2.4983524209999999e+01 2.4971251030000001e+01 2.4960381080000001e+01 2.4948887209999999e+01 2.4935314890000001e+01 2.4921319270000001e+01 2.4908986970000001e+01 2.4898965140000001e+01 2.4889584630000002e+01 2.4880838700000002e+01 2.4872100920000001e+01 2.4864620259999999e+01 2.4858397730000000e+01 2.4854458380000001e+01 2.4851554430000000e+01 2.4851766009999999e+01 2.4854080140000001e+01 2.4859096240000000e+01 2.4864744580000000e+01 2.4872034859999999e+01 2.4880365200000000e+01 2.4889106689999998e+01 2.4897213130000001e+01 2.4902826040000001e+01 2.4906566900000001e+01 2.4908650800000000e+01 2.4910939440000000e+01 2.4913430790000000e+01 2.4915923440000000e+01 2.4921553509999999e+01 2.4930318610000000e+01 2.4940528120000000e+01 2.4949046689999999e+01 2.4957571229999999e+01 2.4967818449999999e+01 2.4981800929999999e+01 2.4997826860000000e+01 2.5013931830000001e+01 2.5028098459999999e+01 2.5040325750000001e+01 2.5052569810000001e+01 2.5064797009999999e+01 2.5077046970000001e+01
|
||||
1
examples/edfa_model/DGT_96.txt
Executable file
1
examples/edfa_model/DGT_96.txt
Executable file
@@ -0,0 +1 @@
|
||||
2.7145266811316859e+00 2.7054438192385049e+00 2.6947834587664494e+00 2.6841217449620203e+00 2.6681935771243177e+00 2.6521732021128046e+00 2.6303964408153848e+00 2.6028603502864280e+00 2.5696460593920065e+00 2.5364027376452056e+00 2.4994462867966041e+00 2.4587748041127506e+00 2.4143984371852212e+00 2.3699990328716107e+00 2.3223736962293420e+00 2.2715207713712529e+00 2.2174389328192197e+00 2.1633756538423898e+00 2.1183028432496016e+00 2.0822250998736478e+00 2.0551007720052352e+00 2.0279625371819305e+00 2.0008103857988204e+00 1.9736443063300082e+00 1.9482128147680253e+00 1.9245345552113182e+00 1.9026104247588487e+00 1.8806927939516411e+00 1.8622356724442459e+00 1.8472755032011290e+00 1.8358140813807049e+00 1.8243814368429321e+00 1.8139629377087627e+00 1.8045606557581335e+00 1.7961751115773796e+00 1.7877868031023945e+00 1.7793941781790852e+00 1.7709972329654864e+00 1.7625959636196327e+00 1.7541903672600494e+00 1.7459181197626403e+00 1.7377807579136351e+00 1.7297783508684146e+00 1.7217732861435076e+00 1.7137640932265894e+00 1.7057507692361864e+00 1.6918150918099673e+00 1.6719047669939942e+00 1.6460167077689267e+00 1.6201194134191075e+00 1.5986915141218316e+00 1.5817353179379183e+00 1.5691997641843789e+00 1.5566577309558969e+00 1.5453741527614671e+00 1.5353620432989845e+00 1.5266220576235803e+00 1.5178910621476225e+00 1.5097346239790443e+00 1.5021530399096861e+00 1.4951454560626991e+00 1.4881342434792260e+00 1.4811193973568100e+00 1.4741004422522110e+00 1.4670307626366115e+00 1.4599103316162523e+00 1.4527395948591399e+00 1.4455651371583680e+00 1.4340878115214444e+00 1.4182738067303231e+00 1.3981208704326855e+00 1.3779439775587023e+00 1.3598972673004606e+00 1.3439818461440451e+00 1.3301807335621048e+00 1.3163839268630830e+00 1.3040618749785347e+00 1.2932153453410835e+00 1.2838336236692311e+00 1.2744470198196236e+00 1.2650555289898042e+00 1.2556591482982988e+00 1.2428104897182262e+00 1.2264996957264114e+00 1.2067249615595257e+00 1.1869318618366975e+00 1.1672278304018044e+00 1.1476135933863398e+00 1.1280891949729075e+00 1.1085552896156590e+00 1.0895983485572227e+00 1.0712204022764056e+00 1.0534217504465226e+00 1.0356155337864215e+00 1.0178077678537021e+00 1.0000000000000000e+00
|
||||
1
examples/edfa_model/NFR_96.txt
Executable file
1
examples/edfa_model/NFR_96.txt
Executable file
@@ -0,0 +1 @@
|
||||
-3.1537433199999998e-01 -3.1537433199999998e-01 -3.1540091571002721e-01 -3.1849146117510951e-01 -3.2158358425400546e-01 -3.2467728615499991e-01 -3.2762368641496226e-01 -3.2054138461232762e-01 -3.1345546385118733e-01 -3.0636592135697482e-01 -2.9920267890990127e-01 -2.7061972852631744e-01 -2.4202215770774693e-01 -2.1340995523361256e-01 -1.8478227130158695e-01 -1.4809761118389625e-01 -1.1139416731807622e-01 -7.4671925273579881e-02 -3.8026748965679924e-02 -1.9958469399422092e-02 -1.8809287980157928e-03 1.6205879960573561e-02 3.4301964005709673e-02 5.2407330474054062e-02 7.0521986509597359e-02 7.9578036683472006e-02 8.8546647361909522e-02 9.7519863231965306e-02 1.0649768784154924e-01 9.7741380449907406e-02 8.8803437172660038e-02 7.9860899732845866e-02 7.0913764587403796e-02 6.3335892740565308e-02 5.5756212252058776e-02 4.8172631747863209e-02 4.0585148217162359e-02 3.3381591675710129e-02 2.6178308595650738e-02 1.8971315351761126e-02 1.1760609076833628e-02 1.6950294922759991e-02 2.2274991357701439e-02 2.7602433189104329e-02 3.2932622540790261e-02 3.8265561538776145e-02 4.3601252311271169e-02 3.4856990743481552e-02 2.5991055149117932e-02 1.7120541224980364e-02 8.2757587359203223e-03 1.9423214065246042e-03 -4.3943890171043590e-03 -1.0734375072893196e-02 -1.7077639301414434e-02 -2.4679702899572852e-02 -3.2297970403821680e-02 -3.9920180090477250e-02 -4.7534566327530239e-02 -4.9234003141433724e-02 -5.0934320036547187e-02 -5.2635517696692252e-02 -5.4337596806402461e-02 -5.6040558050919301e-02 -5.7718452237076875e-02 -5.6840590379175944e-02 -5.5962273198734966e-02 -5.5083500341416583e-02 -5.4204271452516814e-02 -5.8396088726955113e-02 -6.2627330169715334e-02 -6.6860769089203700e-02 -7.0901736256069450e-02 -5.2096097309052243e-02 -3.3280684121412940e-02 -1.4455489070928059e-02 4.3150387579057158e-03 1.4839202394482527e-02 2.5368841662503576e-02 3.5903960836465652e-02 4.6444564195321399e-02 5.6990656022467459e-02 6.7542240605774059e-02 1.0002709623672751e-01 1.3258013095133617e-01 1.6515013362773309e-01 1.9773711753599391e-01 2.3194802687829724e-01 2.6618779883837107e-01 3.0044543658085349e-01 3.3472095409250663e-01 3.5929034770587287e-01 3.8384389188855605e-01 4.0841026111391787e-01 4.3298946543290784e-01 4.3298946543290784e-01
|
||||
15
examples/edfa_model/OA.json
Normal file
15
examples/edfa_model/OA.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"gain_flatmax": 25,
|
||||
"gain_min": 15,
|
||||
"p_max": 21,
|
||||
"nf_fit_coeff": "pNFfit3.txt",
|
||||
"nf_ripple": "NFR_96.txt",
|
||||
"dfg": "DFG_96.txt",
|
||||
"dgt": "DGT_96.txt",
|
||||
"nf_model":
|
||||
{
|
||||
"enabled": true,
|
||||
"nf_min": 5.8,
|
||||
"nf_max": 10
|
||||
}
|
||||
}
|
||||
8
examples/edfa_model/Pchan2D.txt
Executable file
8
examples/edfa_model/Pchan2D.txt
Executable file
@@ -0,0 +1,8 @@
|
||||
-1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01
|
||||
-2.0000000000000000e+01 -2.0000000000000000e+01 -2.0000000000000000e+01 -2.0000000000000000e+01 -2.0000000000000000e+01 -2.0000000000000000e+01 -2.0000000000000000e+01 -2.0000000000000000e+01 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02
|
||||
-1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -2.0000000000000000e+01 -2.0000000000000000e+01 -2.0000000000000000e+01 -2.0000000000000000e+01 -2.0000000000000000e+01 -2.0000000000000000e+01 -2.0000000000000000e+01 -2.0000000000000000e+01
|
||||
-2.0500000000000000e+01 -2.0489473680000000e+01 -2.0478947370000000e+01 -2.0468421050000000e+01 -2.0457894740000000e+01 -2.0447368420000000e+01 -2.0436842110000001e+01 -2.0426315790000000e+01 -2.0415789470000000e+01 -2.0405263160000001e+01 -2.0394736840000000e+01 -2.0384210530000001e+01 -2.0373684210000000e+01 -2.0363157890000000e+01 -2.0352631580000001e+01 -2.0342105260000000e+01 -2.0331578950000001e+01 -2.0321052630000001e+01 -2.0310526320000001e+01 -2.0300000000000001e+01 -2.0289473680000000e+01 -2.0278947370000001e+01 -2.0268421050000001e+01 -2.0257894740000001e+01 -2.0247368420000001e+01 -2.0236842110000001e+01 -2.0226315790000001e+01 -2.0215789470000001e+01 -2.0205263160000001e+01 -2.0194736840000001e+01 -2.0184210530000001e+01 -2.0173684210000001e+01 -2.0163157890000001e+01 -2.0152631580000001e+01 -2.0142105260000001e+01 -2.0131578950000002e+01 -2.0121052630000001e+01 -2.0110526320000002e+01 -2.0100000000000001e+01 -2.0089473680000001e+01 -2.0078947370000002e+01 -2.0068421050000001e+01 -2.0057894739999998e+01 -2.0047368420000002e+01 -2.0036842109999998e+01 -2.0026315790000002e+01 -2.0015789470000001e+01 -2.0005263159999998e+01 -1.9994736840000002e+01 -1.9984210529999999e+01 -1.9973684209999998e+01 -1.9963157890000002e+01 -1.9952631579999998e+01 -1.9942105260000002e+01 -1.9931578949999999e+01 -1.9921052629999998e+01 -1.9910526319999999e+01 -1.9899999999999999e+01 -1.9889473679999998e+01 -1.9878947369999999e+01 -1.9868421049999998e+01 -1.9857894739999999e+01 -1.9847368419999999e+01 -1.9836842109999999e+01 -1.9826315789999999e+01 -1.9815789469999999e+01 -1.9805263159999999e+01 -1.9794736839999999e+01 -1.9784210529999999e+01 -1.9773684209999999e+01 -1.9763157889999999e+01 -1.9752631579999999e+01 -1.9742105259999999e+01 -1.9731578949999999e+01 -1.9721052629999999e+01 -1.9710526320000000e+01 -1.9699999999999999e+01 -1.9689473679999999e+01 -1.9678947369999999e+01 -1.9668421049999999e+01 -1.9657894740000000e+01 -1.9647368419999999e+01 -1.9636842110000000e+01 -1.9626315790000000e+01 -1.9615789469999999e+01 -1.9605263160000000e+01 -1.9594736839999999e+01 -1.9584210530000000e+01 -1.9573684210000000e+01 -1.9563157889999999e+01 -1.9552631580000000e+01 -1.9542105260000000e+01 -1.9531578950000000e+01 -1.9521052630000000e+01 -1.9510526320000000e+01 -1.9500000000000000e+01
|
||||
-2.0500000000000000e+01 -2.0489473680000000e+01 -2.0478947370000000e+01 -2.0468421050000000e+01 -2.0457894740000000e+01 -2.0447368420000000e+01 -2.0436842110000001e+01 -2.0426315790000000e+01 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.9573684210000000e+01 -1.9563157889999999e+01 -1.9552631580000000e+01 -1.9542105260000000e+01 -1.9531578950000000e+01 -1.9521052630000000e+01 -1.9510526320000000e+01 -1.9500000000000000e+01
|
||||
-1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.4460000000000001e+01
|
||||
-1.4460000000000001e+01 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01 -1.4460000000000001e+01
|
||||
-1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.4460000000000001e+01 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02 -1.0000000000000000e+02
|
||||
8
examples/edfa_model/Pchan2DLegend.txt
Executable file
8
examples/edfa_model/Pchan2DLegend.txt
Executable file
@@ -0,0 +1,8 @@
|
||||
7.0000000000000000e+01 1.1700000000000000e+02 1.0800000000000000e+02 1.0800000000000000e+02 3.2000000000000000e+01 7.0000000000000000e+01 1.0800000000000000e+02 9.7000000000000000e+01 1.1600000000000000e+02 3.2000000000000000e+01 3.2000000000000000e+01 3.2000000000000000e+01 3.2000000000000000e+01 3.2000000000000000e+01 3.2000000000000000e+01
|
||||
7.9000000000000000e+01 1.1000000000000000e+02 1.0100000000000000e+02 3.2000000000000000e+01 7.1000000000000000e+01 1.1400000000000000e+02 1.1100000000000000e+02 1.1700000000000000e+02 1.1200000000000000e+02 3.2000000000000000e+01 6.6000000000000000e+01 1.0800000000000000e+02 1.1700000000000000e+02 1.0100000000000000e+02 3.2000000000000000e+01
|
||||
7.9000000000000000e+01 1.1000000000000000e+02 1.0100000000000000e+02 3.2000000000000000e+01 7.1000000000000000e+01 1.1400000000000000e+02 1.1100000000000000e+02 1.1700000000000000e+02 1.1200000000000000e+02 3.2000000000000000e+01 8.2000000000000000e+01 1.0100000000000000e+02 1.0000000000000000e+02 3.2000000000000000e+01 3.2000000000000000e+01
|
||||
7.0000000000000000e+01 1.1700000000000000e+02 1.0800000000000000e+02 1.0800000000000000e+02 3.2000000000000000e+01 1.1900000000000000e+02 3.2000000000000000e+01 8.3000000000000000e+01 8.2000000000000000e+01 8.3000000000000000e+01 3.2000000000000000e+01 3.2000000000000000e+01 3.2000000000000000e+01 3.2000000000000000e+01 3.2000000000000000e+01
|
||||
6.6000000000000000e+01 1.1100000000000000e+02 1.1600000000000000e+02 1.0400000000000000e+02 3.2000000000000000e+01 6.9000000000000000e+01 1.1000000000000000e+02 1.0000000000000000e+02 1.1500000000000000e+02 3.2000000000000000e+01 1.1900000000000000e+02 3.2000000000000000e+01 8.3000000000000000e+01 8.2000000000000000e+01 8.3000000000000000e+01
|
||||
1.0400000000000000e+02 1.0100000000000000e+02 9.7000000000000000e+01 1.1800000000000000e+02 1.2100000000000000e+02 3.2000000000000000e+01 9.8000000000000000e+01 1.0800000000000000e+02 1.1700000000000000e+02 1.0100000000000000e+02 3.2000000000000000e+01 3.2000000000000000e+01 3.2000000000000000e+01 3.2000000000000000e+01 3.2000000000000000e+01
|
||||
1.0400000000000000e+02 1.0100000000000000e+02 9.7000000000000000e+01 1.1800000000000000e+02 1.2100000000000000e+02 3.2000000000000000e+01 1.1400000000000000e+02 1.0100000000000000e+02 1.0000000000000000e+02 3.2000000000000000e+01 3.2000000000000000e+01 3.2000000000000000e+01 3.2000000000000000e+01 3.2000000000000000e+01 3.2000000000000000e+01
|
||||
1.1900000000000000e+02 1.1100000000000000e+02 1.1400000000000000e+02 1.1500000000000000e+02 1.1600000000000000e+02 3.2000000000000000e+01 9.9000000000000000e+01 9.7000000000000000e+01 1.1500000000000000e+02 1.0100000000000000e+02 3.2000000000000000e+01 3.2000000000000000e+01 3.2000000000000000e+01 3.2000000000000000e+01 3.2000000000000000e+01
|
||||
301
examples/edfa_model/amplifier.py
Normal file
301
examples/edfa_model/amplifier.py
Normal file
@@ -0,0 +1,301 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Created on Mon Nov 27 12:32:04 2017
|
||||
|
||||
@author: briantaylor
|
||||
"""
|
||||
import numpy as np
|
||||
from numpy import polyfit, polyval, mean
|
||||
from utilities import lin2db, db2lin, itufs, freq2wavelength
|
||||
import matplotlib.pyplot as plt
|
||||
from scipy.constants import h
|
||||
|
||||
|
||||
def noise_profile(nf, gain, ffs, df):
|
||||
""" noise_profile(nf, gain, ffs, df) computes amplifier ase
|
||||
|
||||
:param nf: Noise figure in dB
|
||||
:param gain: Actual gain calculated for the EDFA in dB units
|
||||
:param ffs: A numpy array of frequencies
|
||||
:param df: the reference bw in THz
|
||||
:type nf: numpy.ndarray
|
||||
:type gain: numpy.ndarray
|
||||
:type ffs: numpy.ndarray
|
||||
:type df: float
|
||||
:return: the asepower in dBm
|
||||
:rtype: numpy.ndarray
|
||||
|
||||
ASE POWER USING PER CHANNEL GAIN PROFILE
|
||||
INPUTS:
|
||||
NF_dB - Noise figure in dB, vector of length number of channels or
|
||||
spectral slices
|
||||
G_dB - Actual gain calculated for the EDFA, vector of length number of
|
||||
channels or spectral slices
|
||||
ffs - Center frequency grid of the channels or spectral slices in THz,
|
||||
vector of length number of channels or spectral slices
|
||||
dF - width of each channel or spectral slice in THz,
|
||||
vector of length number of channels or spectral slices
|
||||
OUTPUT:
|
||||
ase_dBm - ase in dBm per channel or spectral slice
|
||||
NOTE: the output is the total ASE in the channel or spectral slice. For
|
||||
50GHz channels the ASE BW is effectively 0.4nm. To get to noise power in
|
||||
0.1nm, subtract 6dB.
|
||||
|
||||
ONSR is usually quoted as channel power divided by
|
||||
the ASE power in 0.1nm RBW, regardless of the width of the actual
|
||||
channel. This is a historical convention from the days when optical
|
||||
signals were much smaller (155Mbps, 2.5Gbps, ... 10Gbps) than the
|
||||
resolution of the OSAs that were used to measure spectral power which
|
||||
were set to 0.1nm resolution for convenience. Moving forward into
|
||||
flexible grid and high baud rate signals, it may be convenient to begin
|
||||
quoting power spectral density in the same BW for both signal and ASE,
|
||||
e.g. 12.5GHz."""
|
||||
|
||||
h_mWThz = 1e-3 * h * (1e14)**2
|
||||
nf_lin = db2lin(nf)
|
||||
g_lin = db2lin(gain)
|
||||
ase = h_mWThz * df * ffs * (nf_lin * g_lin - 1)
|
||||
asedb = lin2db(ase)
|
||||
|
||||
return asedb
|
||||
|
||||
|
||||
def gain_profile(dfg, dgt, Pin, gp, gtp):
|
||||
"""
|
||||
:param dfg: design flat gain
|
||||
:param dgt: design gain tilt
|
||||
:param Pin: channing input power profile
|
||||
:param gp: Average gain setpoint in dB units
|
||||
:param gtp: gain tilt setting
|
||||
:type dfg: numpy.ndarray
|
||||
:type dgt: numpy.ndarray
|
||||
:type Pin: numpy.ndarray
|
||||
:type gp: float
|
||||
:type gtp: float
|
||||
:return: gain profile in dBm
|
||||
:rtype: numpy.ndarray
|
||||
|
||||
AMPLIFICATION USING INPUT PROFILE
|
||||
INPUTS:
|
||||
DFG - vector of length number of channels or spectral slices
|
||||
DGT - vector of length number of channels or spectral slices
|
||||
Pin - input powers vector of length number of channels or
|
||||
spectral slices
|
||||
Gp - provisioned gain length 1
|
||||
GTp - provisioned tilt length 1
|
||||
|
||||
OUTPUT:
|
||||
amp gain per channel or spectral slice
|
||||
NOTE: there is no checking done for violations of the total output power
|
||||
capability of the amp.
|
||||
Ported from Matlab version written by David Boerges at Ciena.
|
||||
Based on:
|
||||
R. di Muro, "The Er3+ fiber gain coefficient derived from a dynamic
|
||||
gain
|
||||
tilt technique", Journal of Lightwave Technology, Vol. 18, Iss. 3,
|
||||
Pp. 343-347, 2000.
|
||||
"""
|
||||
err_tolerance = 1.0e-11
|
||||
simple_opt = True
|
||||
|
||||
# TODO make all values linear unit and convert to dB units as needed within
|
||||
# this function.
|
||||
nchan = list(range(len(Pin)))
|
||||
|
||||
# TODO find a way to use these or lose them. Primarily we should have a
|
||||
# way to determine if exceeding the gain or output power of the amp
|
||||
tot_in_power_db = lin2db(np.sum(db2lin(Pin)))
|
||||
avg_gain_db = lin2db(mean(db2lin(dfg)))
|
||||
|
||||
# Linear fit to get the
|
||||
p = polyfit(nchan, dgt, 1)
|
||||
dgt_slope = p[0]
|
||||
|
||||
# Calculate the target slope- Currently assumes equal spaced channels
|
||||
# TODO make it so that supports arbitrary channel spacing.
|
||||
targ_slope = gtp / (len(nchan) - 1)
|
||||
|
||||
# 1st estimate of DGT scaling
|
||||
dgts1 = targ_slope / dgt_slope
|
||||
|
||||
# when simple_opt is true code makes 2 attempts to compute gain and
|
||||
# the internal voa value. This is currently here to provide direct
|
||||
# comparison with original Matlab code. Will be removed.
|
||||
# TODO replace with loop
|
||||
|
||||
if simple_opt:
|
||||
|
||||
# 1st estimate of Er gain & voa loss
|
||||
g1st = dfg + dgt * dgts1
|
||||
voa = lin2db(mean(db2lin(g1st))) - gp
|
||||
|
||||
# 2nd estimate of Amp ch gain using the channel input profile
|
||||
g2nd = g1st - voa
|
||||
pout_db = lin2db(np.sum(db2lin(Pin + g2nd)))
|
||||
dgts2 = gp - (pout_db - tot_in_power_db)
|
||||
|
||||
# Center estimate of amp ch gain
|
||||
xcent = dgts2
|
||||
gcent = g1st - voa + dgt * xcent
|
||||
pout_db = lin2db(np.sum(db2lin(Pin + gcent)))
|
||||
gavg_cent = pout_db - tot_in_power_db
|
||||
|
||||
# Lower estimate of Amp ch gain
|
||||
deltax = np.max(g1st) - np.min(g1st)
|
||||
xlow = dgts2 - deltax
|
||||
glow = g1st - voa + xlow * dgt
|
||||
pout_db = lin2db(np.sum(db2lin(Pin + glow)))
|
||||
gavg_low = pout_db - tot_in_power_db
|
||||
|
||||
# Upper gain estimate
|
||||
xhigh = dgts2 + deltax
|
||||
ghigh = g1st - voa + xhigh * dgt
|
||||
pout_db = lin2db(np.sum(db2lin(Pin + ghigh)))
|
||||
gavg_high = pout_db - tot_in_power_db
|
||||
|
||||
# compute slope
|
||||
slope1 = (gavg_low - gavg_cent) / (xlow - xcent)
|
||||
slope2 = (gavg_cent - gavg_high) / (xcent - xhigh)
|
||||
|
||||
if np.abs(gp - gavg_cent) <= err_tolerance:
|
||||
dgts3 = xcent
|
||||
elif gp < gavg_cent:
|
||||
dgts3 = xcent - (gavg_cent - gp) / slope1
|
||||
else:
|
||||
dgts3 = xcent + (-gavg_cent + gp) / slope2
|
||||
|
||||
gprofile = g1st - voa + dgt * dgts3
|
||||
else:
|
||||
gprofile = None
|
||||
|
||||
return gprofile
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
plt.close('all')
|
||||
fc = itufs(0.05)
|
||||
lc = freq2wavelength(fc) / 1000
|
||||
nchan = list(range(len(lc)))
|
||||
df = np.array([0.05] * (nchan[-1] + 1))
|
||||
# TODO remove path dependence
|
||||
path = ''
|
||||
|
||||
"""
|
||||
DFG_96: Design flat gain at each wavelength in the 96 channel 50GHz ITU
|
||||
grid in dB. This can be experimentally determined by measuring the gain
|
||||
at each wavelength using a full, flat channel (or ASE) load at the input.
|
||||
The amplifier should be set to its maximum flat gain (tilt = 0dB). This
|
||||
measurement captures the ripple of the amplifier. If the amplifier was
|
||||
designed to be mimimum ripple at some other tilt value, then the ripple
|
||||
reflected in this measurement will not be that minimum. However, when
|
||||
the DGT gets applied through the provisioning of tilt, the model should
|
||||
accurately reproduce the expected ripple at that tilt value. One could
|
||||
also do the measurement at some expected tilt value and back-calculate
|
||||
this vector using the DGT method. Alternatively, one could re-write the
|
||||
algorithm to accept a nominal tilt and a tiled version of this vector.
|
||||
"""
|
||||
|
||||
dfg_96 = np.loadtxt(path + 'DFG_96.txt')
|
||||
|
||||
"""maximum gain for flat operation - the amp in the data file was designed
|
||||
for 25dB gain and has an internal VOA for setting the external gain
|
||||
"""
|
||||
|
||||
avg_dfg = dfg_96.mean()
|
||||
|
||||
"""
|
||||
DGT_96: This is the so-called Dynamic Gain Tilt of the EDFA in dB/dB. It
|
||||
is the change in gain at each wavelength corresponding to a 1dB change at
|
||||
the longest wavelength supported. The value can be obtained
|
||||
experimentally or through analysis of the cross sections or Giles
|
||||
parameters of the Er fibre. This is experimentally measured by changing
|
||||
the gain of the amplifier above the maximum flat gain while not changing
|
||||
the internal VOA (i.e. the mid-stage VOA is set to minimum and does not
|
||||
change during the measurement). Note that the measurement can change the
|
||||
gain by an arbitrary amount and divide by the gain change (in dB) which
|
||||
is measured at the reference wavelength (the red end of the band).
|
||||
"""
|
||||
|
||||
dgt_96 = np.loadtxt(path + 'DGT_96.txt')
|
||||
|
||||
"""
|
||||
pNFfit3: Cubic polynomial fit coefficients to noise figure in dB
|
||||
averaged across wavelength as a function of gain change from design flat:
|
||||
|
||||
NFavg = pNFfit3(1)*dG^3 + pNFfit3(2)*dG^2 pNFfit3(3)*dG + pNFfit3(4)
|
||||
where
|
||||
dG = GainTarget - average(DFG_96)
|
||||
note that dG will normally be a negative value.
|
||||
"""
|
||||
|
||||
nf_fitco = np.loadtxt(path + 'pNFfit3.txt')
|
||||
|
||||
"""NFR_96: Noise figure ripple in dB away from the average noise figure
|
||||
across the band. This captures the wavelength dependence of the NF. To
|
||||
calculate the NF across channels, one uses the cubic fit coefficients
|
||||
with the external gain target to get the average nosie figure, NFavg and
|
||||
then adds this to NFR_96:
|
||||
NF_96 = NFR_96 + NFavg
|
||||
"""
|
||||
|
||||
nf_ripple = np.loadtxt(path + 'NFR_96.txt')
|
||||
|
||||
# This is an example to set the provisionable gain and gain-tilt values
|
||||
# Tilt is in units of dB/THz
|
||||
gain_target = 20.0
|
||||
tilt_target = -0.7
|
||||
|
||||
# calculate the NF for the EDFA at this gain setting
|
||||
dg = gain_target - avg_dfg
|
||||
nf_avg = polyval(nf_fitco, dg)
|
||||
nf_96 = nf_ripple + nf_avg
|
||||
|
||||
# get the input power profiles to show
|
||||
pch2d = np.loadtxt(path + 'Pchan2D.txt')
|
||||
|
||||
# Load legend and assemble legend text
|
||||
pch2d_legend_data = np.loadtxt(path + 'Pchan2DLegend.txt')
|
||||
pch2d_legend = []
|
||||
for ea in pch2d_legend_data:
|
||||
s = ''.join([chr(xx) for xx in ea.astype(dtype=int)]).strip()
|
||||
pch2d_legend.append(s)
|
||||
|
||||
# assemble plot
|
||||
axis_font = {'fontname': 'Arial', 'size': '16', 'fontweight': 'bold'}
|
||||
title_font = {'fontname': 'Arial', 'size': '17', 'fontweight': 'bold'}
|
||||
tic_font = {'fontname': 'Arial', 'size': '12'}
|
||||
|
||||
plt.rcParams["font.family"] = "Arial"
|
||||
plt.figure()
|
||||
plt.plot(nchan, pch2d.T, '.-', lw=2)
|
||||
plt.xlabel('Channel Number', **axis_font)
|
||||
plt.ylabel('Channel Power [dBm]', **axis_font)
|
||||
plt.title('Input Power Profiles for Different Channel Loading',
|
||||
**title_font)
|
||||
plt.legend(pch2d_legend, loc=5)
|
||||
plt.grid()
|
||||
plt.ylim((-100, -10))
|
||||
plt.xlim((0, 110))
|
||||
plt.xticks(np.arange(0, 100, 10), **tic_font)
|
||||
plt.yticks(np.arange(-110, -10, 10), **tic_font)
|
||||
|
||||
plt.figure()
|
||||
ea = pch2d[1, :]
|
||||
for ea in pch2d:
|
||||
chgain = gain_profile(dfg_96, dgt_96, ea, gain_target, tilt_target)
|
||||
pase = noise_profile(nf_96, chgain, fc, df)
|
||||
pout = lin2db(db2lin(ea + chgain) + db2lin(pase))
|
||||
plt.plot(nchan, pout, '.-', lw=2)
|
||||
plt.title('Output Power with ASE for Different Channel Loading',
|
||||
**title_font)
|
||||
plt.xlabel('Channel Number', **axis_font)
|
||||
plt.ylabel('Channel Power [dBm]', **axis_font)
|
||||
plt.grid()
|
||||
plt.ylim((-50, 10))
|
||||
plt.xlim((0, 100))
|
||||
plt.xticks(np.arange(0, 100, 10), **tic_font)
|
||||
plt.yticks(np.arange(-50, 10, 10), **tic_font)
|
||||
plt.legend(pch2d_legend, loc=5)
|
||||
plt.show()
|
||||
164
examples/edfa_model/build_oa_json.py
Normal file
164
examples/edfa_model/build_oa_json.py
Normal file
@@ -0,0 +1,164 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Created on Tue Jan 30 12:32:00 2018
|
||||
|
||||
@author: jeanluc-auge
|
||||
@comments about amplifier input files from Brian Taylor & Dave Boertjes
|
||||
|
||||
update an existing json file with all the 96ch txt files for a given amplifier type
|
||||
amplifier type 'OA_type1' is hard coded but can be modified and other types added
|
||||
returns an updated amplifier json file: output_json_file_name = 'edfa_config.json'
|
||||
"""
|
||||
import re
|
||||
import sys
|
||||
import json
|
||||
import numpy as np
|
||||
from gnpy.core.utils import lin2db, db2lin
|
||||
|
||||
"""amplifier file names
|
||||
convert a set of amplifier files + input json definiton file into a valid edfa_json_file:
|
||||
nf_fit_coeff: NF polynomial coefficients txt file (optional)
|
||||
nf_ripple: NF ripple excursion txt file
|
||||
dfg: gain txt file
|
||||
dgt: dynamic gain txt file
|
||||
input json file in argument (defult = 'OA.json')
|
||||
the json input file should have the following fields:
|
||||
{
|
||||
"gain_flatmax": 25,
|
||||
"gain_min": 15,
|
||||
"p_max": 21,
|
||||
"nf_fit_coeff": "pNFfit3.txt",
|
||||
"nf_ripple": "NFR_96.txt",
|
||||
"dfg": "DFG_96.txt",
|
||||
"dgt": "DGT_96.txt",
|
||||
"nf_model":
|
||||
{
|
||||
"enabled": true,
|
||||
"nf_min": 5.8,
|
||||
"nf_max": 10
|
||||
}
|
||||
}
|
||||
gain_flat = max flat gain (dB)
|
||||
gain_min = min gain (dB) : will consider an input VOA if below (TBD vs throwing an exception)
|
||||
p_max = max power (dBm)
|
||||
nf_fit = boolean (True, False) :
|
||||
if False nf_fit_coeff are ignored and nf_model fields are used
|
||||
"""
|
||||
|
||||
input_json_file_name = "OA.json" #default path
|
||||
output_json_file_name = "edfa_config.json"
|
||||
param_field ="params"
|
||||
gain_min_field = "gain_min"
|
||||
gain_max_field = "gain_flatmax"
|
||||
gain_ripple_field = "dfg"
|
||||
nf_ripple_field = "nf_ripple"
|
||||
nf_fit_coeff = "nf_fit_coeff"
|
||||
nf_model_field = "nf_model"
|
||||
nf_model_enabled_field = "enabled"
|
||||
nf_min_field ="nf_min"
|
||||
nf_max_field = "nf_max"
|
||||
|
||||
def read_file(field, file_name):
|
||||
"""read and format the 96 channels txt files describing the amplifier NF and ripple
|
||||
convert dfg into gain ripple by removing the mean component
|
||||
"""
|
||||
|
||||
#with open(path + file_name,'r') as this_file:
|
||||
# data = this_file.read()
|
||||
#data.strip()
|
||||
#data = re.sub(r"([0-9])([ ]{1,3})([0-9-+])",r"\1,\3",data)
|
||||
#data = list(data.split(","))
|
||||
#data = [float(x) for x in data]
|
||||
data = np.loadtxt(file_name)
|
||||
if field == gain_ripple_field or field == nf_ripple_field:
|
||||
#consider ripple excursion only to avoid redundant information
|
||||
#because the max flat_gain is already given by the 'gain_flat' field in json
|
||||
#remove the mean component
|
||||
data = data - data.mean()
|
||||
data = data.tolist()
|
||||
return data
|
||||
|
||||
def nf_model(amp_dict):
|
||||
if amp_dict[nf_model_field][nf_model_enabled_field] == True:
|
||||
gain_min = amp_dict[gain_min_field]
|
||||
gain_max = amp_dict[gain_max_field]
|
||||
nf_min = amp_dict[nf_model_field][nf_min_field]
|
||||
nf_max = amp_dict[nf_model_field][nf_max_field]
|
||||
#use NF estimation model based on NFmin and NFmax in json OA file
|
||||
delta_p = 5 #max power dB difference between 1st and 2nd stage coils
|
||||
#dB g1a = (1st stage gain) - (internal voa attenuation)
|
||||
g1a_min = gain_min - (gain_max-gain_min) - delta_p
|
||||
g1a_max = gain_max - delta_p
|
||||
#nf1 and nf2 are the nf of the 1st and 2nd stage coils
|
||||
#calculate nf1 and nf2 values that solve nf_[min/max] = nf1 + nf2 / g1a[min/max]
|
||||
nf2 = lin2db((db2lin(nf_min) - db2lin(nf_max)) / (1/db2lin(g1a_max)-1/db2lin(g1a_min)))
|
||||
nf1 = lin2db(db2lin(nf_min)- db2lin(nf2)/db2lin(g1a_max)) #expression (1)
|
||||
|
||||
""" now checking and recalculating the results:
|
||||
recalculate delta_p to check it is within [1-6] boundaries
|
||||
This is to check that the nf_min and nf_max values from the json file
|
||||
make sense. If not a warning is printed """
|
||||
if nf1 < 4:
|
||||
print('1st coil nf calculated value {} is too low: revise inputs'.format(nf1))
|
||||
if nf2 < nf1 + 0.3 or nf2 > nf1 + 2:
|
||||
"""nf2 should be with [nf1+0.5 - nf1 +2] boundaries
|
||||
there shouldn't be very high nf differences between 2 coils
|
||||
=> recalculate delta_p
|
||||
"""
|
||||
nf2 = max(nf2, nf1+0.3)
|
||||
nf2 = min(nf2, nf1+2)
|
||||
g1a_max = lin2db(db2lin(nf2) / (db2lin(nf_min) - db2lin(nf1))) #use expression (1)
|
||||
delta_p = gain_max - g1a_max
|
||||
g1a_min = gain_min - (gain_max-gain_min) - delta_p
|
||||
if delta_p < 1 or delta_p > 6:
|
||||
#delta_p should be > 1dB and < 6dB => consider user warning if not
|
||||
print('1st coil vs 2nd coil calculated DeltaP {} is not valid: revise inputs'
|
||||
.format(delta_p))
|
||||
#check the calculated values for nf1 & nf2:
|
||||
nf_min_calc = lin2db(db2lin(nf1) + db2lin(nf2)/db2lin(g1a_max))
|
||||
nf_max_calc = lin2db(db2lin(nf1) + db2lin(nf2)/db2lin(g1a_min))
|
||||
if (abs(nf_min_calc-nf_min) > 0.01) or (abs(nf_max_calc-nf_max) > 0.01):
|
||||
print('nf model calculation failed with nf_min {} and nf_max {} calculated'
|
||||
.format(nf_min_calc, nf_max_calc))
|
||||
print('do not use the generated edfa_config.json file')
|
||||
else :
|
||||
(nf1, nf2, delta_p) = (0, 0, 0)
|
||||
|
||||
return (nf1, nf2, delta_p)
|
||||
|
||||
def input_json(path):
|
||||
"""read the json input file and add all the 96 channels txt files
|
||||
create the output json file with output_json_file_name"""
|
||||
with open(path,'r') as edfa_json_file:
|
||||
amp_text = edfa_json_file.read()
|
||||
amp_dict = json.loads(amp_text)
|
||||
|
||||
for k, v in amp_dict.items():
|
||||
if re.search(r'.txt$',str(v)) :
|
||||
amp_dict[k] = read_file(k, v)
|
||||
|
||||
#calculate nf of 1st and 2nd coil for the nf_model if 'enabled'==true
|
||||
(nf1, nf2, delta_p) = nf_model(amp_dict)
|
||||
#rename nf_min and nf_max in nf1 and nf2 after the nf model calculation:
|
||||
del amp_dict[nf_model_field][nf_min_field]
|
||||
del amp_dict[nf_model_field][nf_max_field]
|
||||
amp_dict[nf_model_field]['nf1'] = nf1
|
||||
amp_dict[nf_model_field]['nf2'] = nf2
|
||||
amp_dict[nf_model_field]['delta_p'] = delta_p
|
||||
#rename dfg into gain_ripple after removing the average part:
|
||||
amp_dict['gain_ripple'] = amp_dict.pop(gain_ripple_field)
|
||||
|
||||
new_amp_dict = {}
|
||||
new_amp_dict[param_field] = amp_dict
|
||||
amp_text = json.dumps(new_amp_dict, indent=4)
|
||||
#print(amp_text)
|
||||
with open(output_json_file_name,'w') as edfa_json_file:
|
||||
edfa_json_file.write(amp_text)
|
||||
|
||||
if __name__ == '__main__':
|
||||
if len(sys.argv) == 2:
|
||||
path = sys.argv[1]
|
||||
else:
|
||||
path = input_json_file_name
|
||||
input_json(path)
|
||||
313
examples/edfa_model/edfa_config.json
Normal file
313
examples/edfa_model/edfa_config.json
Normal file
@@ -0,0 +1,313 @@
|
||||
{
|
||||
"params": {
|
||||
"gain_flatmax": 25,
|
||||
"gain_min": 15,
|
||||
"p_max": 21,
|
||||
"nf_fit_coeff": [
|
||||
0.000168241,
|
||||
0.0469961,
|
||||
0.0359549,
|
||||
5.82851
|
||||
],
|
||||
"nf_ripple": [
|
||||
-0.3110761646066259,
|
||||
-0.3110761646066259,
|
||||
-0.31110274831665313,
|
||||
-0.31419329378173544,
|
||||
-0.3172854168606314,
|
||||
-0.32037911876162584,
|
||||
-0.3233255190215882,
|
||||
-0.31624321721895354,
|
||||
-0.30915729645781326,
|
||||
-0.30206775396360075,
|
||||
-0.2949045115165272,
|
||||
-0.26632156113294336,
|
||||
-0.23772399031437283,
|
||||
-0.20911178784023846,
|
||||
-0.18048410390821285,
|
||||
-0.14379944379052215,
|
||||
-0.10709599992470213,
|
||||
-0.07037375788020579,
|
||||
-0.03372858157230583,
|
||||
-0.015660302006048,
|
||||
0.0024172385953583004,
|
||||
0.020504047353947653,
|
||||
0.03860013139908377,
|
||||
0.05670549786742816,
|
||||
0.07482015390297145,
|
||||
0.0838762040768461,
|
||||
0.09284481475528361,
|
||||
0.1018180306253394,
|
||||
0.11079585523492333,
|
||||
0.1020395478432815,
|
||||
0.09310160456603413,
|
||||
0.08415906712621996,
|
||||
0.07521193198077789,
|
||||
0.0676340601339394,
|
||||
0.06005437964543287,
|
||||
0.052470799141237305,
|
||||
0.044883315610536455,
|
||||
0.037679759069084225,
|
||||
0.03047647598902483,
|
||||
0.02326948274513522,
|
||||
0.01605877647020772,
|
||||
0.021248462316134083,
|
||||
0.02657315875107553,
|
||||
0.03190060058247842,
|
||||
0.03723078993416436,
|
||||
0.04256372893215024,
|
||||
0.047899419704645264,
|
||||
0.03915515813685565,
|
||||
0.030289222542492025,
|
||||
0.021418708618354456,
|
||||
0.012573926129294415,
|
||||
0.006240488799898697,
|
||||
-9.622162373026585e-05,
|
||||
-0.006436207679519103,
|
||||
-0.012779471908040341,
|
||||
-0.02038153550619876,
|
||||
-0.027999803010447587,
|
||||
-0.035622012697103154,
|
||||
-0.043236398934156144,
|
||||
-0.04493583574805963,
|
||||
-0.04663615264317309,
|
||||
-0.048337350303318156,
|
||||
-0.050039429413028365,
|
||||
-0.051742390657545205,
|
||||
-0.05342028484370278,
|
||||
-0.05254242298580185,
|
||||
-0.05166410580536087,
|
||||
-0.05078533294804249,
|
||||
-0.04990610405914272,
|
||||
-0.05409792133358102,
|
||||
-0.05832916277634124,
|
||||
-0.06256260169582961,
|
||||
-0.06660356886269536,
|
||||
-0.04779792991567815,
|
||||
-0.028982516728038848,
|
||||
-0.010157321677553965,
|
||||
0.00861320615127981,
|
||||
0.01913736978785662,
|
||||
0.029667009055877668,
|
||||
0.04020212822983975,
|
||||
0.050742731588695494,
|
||||
0.061288823415841555,
|
||||
0.07184040799914815,
|
||||
0.1043252636301016,
|
||||
0.13687829834471027,
|
||||
0.1694483010211072,
|
||||
0.202035284929368,
|
||||
0.23624619427167134,
|
||||
0.27048596623174515,
|
||||
0.30474360397422756,
|
||||
0.3390191214858807,
|
||||
0.36358851509924695,
|
||||
0.38814205928193013,
|
||||
0.41270842850729195,
|
||||
0.4372876328262819,
|
||||
0.4372876328262819
|
||||
],
|
||||
"dgt": [
|
||||
2.714526681131686,
|
||||
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.0
|
||||
],
|
||||
"nf_model": {
|
||||
"enabled": true,
|
||||
"nf1": 5.727887800964238,
|
||||
"nf2": 7.727887800964238,
|
||||
"delta_p": 5.238350271545567
|
||||
},
|
||||
"gain_ripple": [
|
||||
0.1359703369791596,
|
||||
0.11822862697916037,
|
||||
0.09542181697916163,
|
||||
0.06245819697916133,
|
||||
0.02602813697916062,
|
||||
-0.0036199830208403228,
|
||||
-0.018326963020840026,
|
||||
-0.0246928330208398,
|
||||
-0.016792253020838643,
|
||||
-0.0028138630208403015,
|
||||
0.017572956979162058,
|
||||
0.038328296979159404,
|
||||
0.054956336979159914,
|
||||
0.0670723869791594,
|
||||
0.07091459697916136,
|
||||
0.07094413697916124,
|
||||
0.07114372697916238,
|
||||
0.07533675697916209,
|
||||
0.08731066697916035,
|
||||
0.10313984697916112,
|
||||
0.12276252697916235,
|
||||
0.14239527697916188,
|
||||
0.15945681697916214,
|
||||
0.1739275269791598,
|
||||
0.1767381569791624,
|
||||
0.17037189697916233,
|
||||
0.15216302697916007,
|
||||
0.13114358697916018,
|
||||
0.10802383697916085,
|
||||
0.08548825697916129,
|
||||
0.06916723697916183,
|
||||
0.05848224697916038,
|
||||
0.05447361697916264,
|
||||
0.05154489697916276,
|
||||
0.04946107697915991,
|
||||
0.04717897697916129,
|
||||
0.04551704697916037,
|
||||
0.04467697697916151,
|
||||
0.04072968697916224,
|
||||
0.03285456697916089,
|
||||
0.023488786979161347,
|
||||
0.01659282697915998,
|
||||
0.013321846979160057,
|
||||
0.011234826979162449,
|
||||
0.01030063697916006,
|
||||
0.00936596697916059,
|
||||
0.00874012697916271,
|
||||
0.00842583697916055,
|
||||
0.006965146979162284,
|
||||
0.0040435869791615175,
|
||||
0.0007104669791608842,
|
||||
-0.0015763130208377163,
|
||||
-0.006936193020838033,
|
||||
-0.016475303020840215,
|
||||
-0.028748483020837767,
|
||||
-0.039618433020837784,
|
||||
-0.051112303020840244,
|
||||
-0.06468462302083822,
|
||||
-0.07868024302083754,
|
||||
-0.09101254302083817,
|
||||
-0.10103437302083762,
|
||||
-0.11041488302083735,
|
||||
-0.11916081302083725,
|
||||
-0.12789859302083784,
|
||||
-0.1353792530208402,
|
||||
-0.14160178302083892,
|
||||
-0.1455411330208385,
|
||||
-0.1484450830208388,
|
||||
-0.14823350302084037,
|
||||
-0.14591937302083835,
|
||||
-0.1409032730208395,
|
||||
-0.13525493302083902,
|
||||
-0.1279646530208396,
|
||||
-0.11963431302083904,
|
||||
-0.11089282302084058,
|
||||
-0.1027863830208382,
|
||||
-0.09717347302083823,
|
||||
-0.09343261302083761,
|
||||
-0.0913487130208388,
|
||||
-0.08906007302083907,
|
||||
-0.0865687230208394,
|
||||
-0.08407607302083875,
|
||||
-0.07844600302084004,
|
||||
-0.06968090302083851,
|
||||
-0.05947139302083926,
|
||||
-0.05095282302083959,
|
||||
-0.042428283020839785,
|
||||
-0.03218106302083967,
|
||||
-0.01819858302084043,
|
||||
-0.0021726530208390216,
|
||||
0.01393231697916164,
|
||||
0.028098946979159933,
|
||||
0.040326236979161934,
|
||||
0.05257029697916238,
|
||||
0.06479749697916048,
|
||||
0.07704745697916238
|
||||
]
|
||||
}
|
||||
}
|
||||
1
examples/edfa_model/pNFfit3.txt
Executable file
1
examples/edfa_model/pNFfit3.txt
Executable file
@@ -0,0 +1 @@
|
||||
1.6824099999999999e-04 4.6996099999999999e-02 3.5954899999999998e-02 5.8285099999999996e+00
|
||||
90
examples/transmission_main_example.py
Normal file
90
examples/transmission_main_example.py
Normal file
@@ -0,0 +1,90 @@
|
||||
#!/usr/bin/env
|
||||
"""
|
||||
@author: briantaylor
|
||||
@author: giladgoldfarb
|
||||
@author: jeanluc-auge
|
||||
|
||||
Transmission setup example:
|
||||
reads from network json (default = examples/edfa/edfa_example_network.json)
|
||||
propagates a 96 channels comb
|
||||
"""
|
||||
from argparse import ArgumentParser
|
||||
from json import load
|
||||
from sys import exit
|
||||
from pathlib import Path
|
||||
from logging import getLogger, basicConfig, INFO, ERROR, DEBUG
|
||||
|
||||
from matplotlib.pyplot import show, axis, figure, title
|
||||
from networkx import (draw_networkx_nodes, draw_networkx_edges,
|
||||
draw_networkx_labels, dijkstra_path)
|
||||
|
||||
from gnpy.core import network_from_json, build_network
|
||||
from gnpy.core.elements import Transceiver, Fiber, Edfa
|
||||
from gnpy.core.info import SpectralInformation, Channel, Power
|
||||
#from gnpy.core.algorithms import closed_paths
|
||||
|
||||
logger = getLogger(__package__ or __file__)
|
||||
|
||||
def format_si(spectral_infos):
|
||||
return '\n'.join([
|
||||
f'#{idx} Carrier(frequency={c.frequency},\n power=Power(signal={c.power.signal}, nli={c.power.nli}, ase={c.power.ase}))'
|
||||
for idx, si in sorted(set(spectral_infos))
|
||||
for c in set(si.carriers)
|
||||
])
|
||||
|
||||
logger = getLogger('gnpy.core')
|
||||
|
||||
def main(args):
|
||||
with open(args.filename) as f:
|
||||
json_data = load(f)
|
||||
|
||||
network = network_from_json(json_data)
|
||||
build_network(network)
|
||||
|
||||
spacing = 0.05 #THz
|
||||
si = SpectralInformation() # !! SI units W, Hz
|
||||
si = si.update(carriers=tuple(Channel(f, (191.3+spacing*f)*1e12,
|
||||
32e9, 0.15, Power(1e-3, 0, 0)) for f in range(1,97)))
|
||||
|
||||
trx = [n for n in network.nodes() if isinstance(n, Transceiver)]
|
||||
source, sink = trx[0], trx[1]
|
||||
|
||||
path = dijkstra_path(network, source, sink)
|
||||
print(f'There are {len(path)} network elements between {source} and {sink}')
|
||||
|
||||
for el in path:
|
||||
si = el(si)
|
||||
print(el)
|
||||
|
||||
nodelist = [n for n in network.nodes() if isinstance(n, (Transceiver, Fiber))]
|
||||
pathnodes = [n for n in path if isinstance(n, (Transceiver, Fiber))]
|
||||
edgelist = [(u, v) for u, v in zip(pathnodes, pathnodes[1:])]
|
||||
node_color = ['#ff0000' if n is source or n is sink else
|
||||
'#900000' if n in path else '#ffdfdf'
|
||||
for n in nodelist]
|
||||
edge_color = ['#ff9090' if u in path and v in path else '#ababab'
|
||||
for u, v in edgelist]
|
||||
labels = {n: n.location.city if isinstance(n, Transceiver) else ''
|
||||
for n in pathnodes}
|
||||
|
||||
fig = figure()
|
||||
pos = {n: (n.lng, n.lat) for n in nodelist}
|
||||
kwargs = {'figure': fig, 'pos': pos}
|
||||
plot = draw_networkx_nodes(network, nodelist=nodelist, node_color=node_color, **kwargs)
|
||||
draw_networkx_edges(network, edgelist=edgelist, edge_color=edge_color, **kwargs)
|
||||
draw_networkx_labels(network, labels=labels, font_size=14, **kwargs)
|
||||
title(f'Propagating from {source.loc.city} to {sink.loc.city}')
|
||||
axis('off')
|
||||
show()
|
||||
|
||||
parser = ArgumentParser()
|
||||
parser.add_argument('filename', nargs='?', type=Path,
|
||||
default= Path(__file__).parent / 'edfa/edfa_example_network.json')
|
||||
parser.add_argument('-v', '--verbose', action='count')
|
||||
|
||||
if __name__ == '__main__':
|
||||
args = parser.parse_args()
|
||||
level = {1: INFO, 2: DEBUG}.get(args.verbose, ERROR)
|
||||
logger.setLevel(level)
|
||||
basicConfig()
|
||||
exit(main(args))
|
||||
@@ -1,7 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from .gnpy import (raised_cosine_comb, analytic_formula, compute_psi, fwm_eff,
|
||||
get_f_computed_interp, get_freqarray, gn_analytic, gn_model,
|
||||
interpolate_in_range, GN_integral)
|
||||
|
||||
__all__ = ['gnpy']
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
import gnpy as gn
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
import time
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
# Accuracy parameters
|
||||
flag_analytic = True
|
||||
num_computed_values = 2
|
||||
interp_method = 'linear'
|
||||
threshold_fwm = 50
|
||||
n_points = 500
|
||||
n_points_min = 4
|
||||
accuracy_param = {'is_analytic': flag_analytic, 'points_not_interp': num_computed_values, 'kind_interp': interp_method,
|
||||
'th_fwm': threshold_fwm, 'n_points': n_points, 'n_points_min': n_points_min}
|
||||
|
||||
# Parallelization Parameters
|
||||
n_cores = 1
|
||||
|
||||
# Spectrum parameters
|
||||
num_ch = 95
|
||||
rs = np.ones(num_ch) * 0.032
|
||||
b_ch = rs # For root raised cosine shapes, the -3 dB band is equal to the symbol rate
|
||||
roll_off = np.ones(num_ch) * 0.05
|
||||
power = np.ones(num_ch) * 0.001
|
||||
central_freq = 193.5
|
||||
if num_ch % 2 == 1: # odd number of channels
|
||||
fch = np.arange(-(num_ch // 2), (num_ch // 2) + 1, 1) * 0.05 # noqa: E501
|
||||
else:
|
||||
fch = (np.arange(0, num_ch) - (num_ch / 2.0) + 0.5) * 0.05
|
||||
spectrum_param = {'num_ch': num_ch, 'f_ch': fch, 'b_ch': b_ch, 'roll_off': roll_off, 'power': power}
|
||||
|
||||
# Fiber Parameters
|
||||
beta2 = 21.27
|
||||
l_span = 100.0
|
||||
loss = 0.2
|
||||
gam = 1.27
|
||||
fiber_param = {'alpha': loss, 'span_length': l_span, 'beta_2': beta2, 'gamma': gam}
|
||||
|
||||
# EDFA Parameters
|
||||
noise_fig = 5.5
|
||||
gain_zero = 25.0
|
||||
gain_tilting = 0.5
|
||||
|
||||
# Compute the GN model
|
||||
t = time.time()
|
||||
nli_cmp, f_nli_cmp, nli_int, f_nli_int = gn.gn_model(spectrum_param, fiber_param, accuracy_param, n_cores) # noqa: E501
|
||||
print('Elapsed: %s' % (time.time() - t))
|
||||
|
||||
# Compute the EDFA profile
|
||||
gain, g_ase = gn.compute_edfa_profile(gain_zero, gain_tilting, noise_fig, central_freq, fch)
|
||||
|
||||
# Compute the raised cosine comb
|
||||
f1_array = np.linspace(np.amin(fch), np.amax(fch), 1e3)
|
||||
gtx = gn.raised_cosine_comb(f1_array, rs, roll_off, fch, power)
|
||||
gtx = gtx + 10 ** -6 # To avoid log10 issues.
|
||||
|
||||
# Plot the results
|
||||
plt.figure(1)
|
||||
plt.plot(f1_array, 10 * np.log10(gtx), '-b', label='WDM comb')
|
||||
plt.plot(f_nli_cmp, 10 * np.log10(nli_cmp), 'ro', label='GNLI computed')
|
||||
plt.plot(f_nli_int, 10 * np.log10(nli_int), 'g+', label='GNLI interpolated')
|
||||
plt.plot(fch, 10 * np.log10(g_ase), 'yo', label='GASE')
|
||||
plt.ylabel('PSD [dB(W/THz)]')
|
||||
plt.xlabel('f [THz]')
|
||||
plt.legend(loc='upper left')
|
||||
plt.grid()
|
||||
plt.draw()
|
||||
plt.show()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -1,84 +0,0 @@
|
||||
import os
|
||||
import gnpy as gn
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
import time
|
||||
|
||||
|
||||
def main_ole():
|
||||
|
||||
# String indicating the folder in which outputs will be saved
|
||||
string_date_time = time.strftime("%Y-%m-%d") + '_' + time.strftime("%H-%M-%S")
|
||||
output_path = './output/' + string_date_time + '/'
|
||||
|
||||
# Creates the directory if it doesn't exist
|
||||
if not os.path.isdir(output_path):
|
||||
os.makedirs(output_path)
|
||||
|
||||
from configuration.fiber_parameters import fibers
|
||||
from configuration.general_parameters import sys_param, control_param
|
||||
from configuration.link_description import link
|
||||
from input.spectrum_in import spectrum
|
||||
|
||||
# adapt the laser position to the grid
|
||||
if len(spectrum['laser_position']) < sys_param['ns']:
|
||||
n = sys_param['ns'] - len(spectrum['laser_position'])
|
||||
missing_zeros = [0 for _ in range(n)]
|
||||
spectrum['laser_position'] += missing_zeros
|
||||
elif len(spectrum['laser_position']) > sys_param['ns']:
|
||||
print('Error: the spectrum definition requires a larger number of slots ns in the spectrum grid')
|
||||
|
||||
delta_f = 6.25E-3
|
||||
f_0 = sys_param['f0']
|
||||
f_cent = f_0 + ((sys_param['ns'] // 2.0) * delta_f)
|
||||
|
||||
n_ch = spectrum['laser_position'].count(1)
|
||||
# Get comb parameters
|
||||
f_ch = np.zeros(n_ch)
|
||||
count = 0
|
||||
for index, bool_laser in enumerate(spectrum['laser_position']):
|
||||
if bool_laser:
|
||||
f_ch[count] = delta_f * index + (f_0 - f_cent)
|
||||
count += 1
|
||||
|
||||
t = time.time()
|
||||
# It runs the OLE
|
||||
osnr_nl_db, osnr_lin_db = gn.ole(spectrum, link, fibers, sys_param, control_param, output_path=output_path)
|
||||
print('Elapsed: %s' % (time.time() - t))
|
||||
|
||||
# Compute the raised cosine comb
|
||||
power, rs, roll_off, p_ase, p_nli, n_ch = gn.get_spectrum_param(spectrum)
|
||||
f1_array = np.linspace(np.amin(f_ch), np.amax(f_ch), 1e3)
|
||||
gtx = gn.raised_cosine_comb(f1_array, rs, roll_off, f_ch, power)
|
||||
gtx = gtx + 10 ** -6 # To avoid log10 issues.
|
||||
|
||||
# OSNR at in the central channel
|
||||
ind_c = n_ch // 2
|
||||
osnr_lin_central_db = osnr_lin_db[ind_c]
|
||||
osnr_nl_central_db = osnr_nl_db[ind_c]
|
||||
print('The linear OSNR in the central channel is: ' + str(osnr_lin_central_db) + ' dB')
|
||||
print('The non linear OSNR in the central channel is: ' + str(osnr_nl_central_db) + ' dB')
|
||||
|
||||
# Plot the results
|
||||
plt.figure(1)
|
||||
plt.plot(f1_array, 10 * np.log10(gtx), '-b', label='WDM comb PSD [dB(W/THz)]')
|
||||
plt.plot(f_ch, 10 * np.log10(p_nli), 'ro', label='NLI [dBw]')
|
||||
plt.plot(f_ch, 10 * np.log10(p_ase), 'g+', label='ASE noise [dBw]')
|
||||
plt.ylabel('')
|
||||
plt.xlabel('f [THz]')
|
||||
plt.legend(loc='upper right')
|
||||
plt.grid()
|
||||
plt.draw()
|
||||
|
||||
plt.figure(2)
|
||||
plt.plot(f_ch, osnr_nl_db, 'ro', label='non-linear OSNR')
|
||||
plt.plot(f_ch, osnr_lin_db, 'g+', label='linear OSNR')
|
||||
plt.ylabel('OSNR [dB]')
|
||||
plt.xlabel('f [THz]')
|
||||
plt.legend(loc='lower left')
|
||||
plt.grid()
|
||||
plt.show()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main_ole()
|
||||
17
gnpy/cli.py
17
gnpy/cli.py
@@ -1,17 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""Console script for gnpy."""
|
||||
|
||||
import click
|
||||
|
||||
|
||||
@click.command()
|
||||
def main(args=None):
|
||||
"""Console script for gnpy."""
|
||||
click.echo("Replace this message by putting your code into "
|
||||
"gnpy.cli.main")
|
||||
click.echo("See click documentation at http://click.pocoo.org/")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1 +0,0 @@
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
# coding=utf-8
|
||||
""" fiber_parameters.py describes the fiber parameters.
|
||||
fibers is a dictionary containing a dictionary for each kind of fiber
|
||||
each dictionary has to report:
|
||||
reference_frequency: the frequency at which the parameters are evaluated [THz]
|
||||
alpha: the attenuation coefficient [dB/km]
|
||||
alpha_1st: the first derivative of alpha indicating the alpha slope [dB/km/THz]
|
||||
if you assume a flat attenuation with respect to the frequency you put it as zero
|
||||
beta_2: the dispersion coefficient [ps^2/km]
|
||||
n_2: second-order nonlinear refractive index [m^2/W]
|
||||
a typical value is 2.5E-20 m^2/W
|
||||
a_eff: the effective area of the fiber [um^2]
|
||||
"""
|
||||
|
||||
fibers = {
|
||||
'SMF': {
|
||||
'reference_frequency': 193.5,
|
||||
'alpha': 0.2,
|
||||
'alpha_1st': 0,
|
||||
'beta_2': 21.27,
|
||||
'n_2': 2.5E-20,
|
||||
'a_eff': 77.77,
|
||||
},
|
||||
'NZDF': {
|
||||
'reference_frequency': 193.5,
|
||||
'alpha': 0.22,
|
||||
'alpha_1st': 0,
|
||||
'beta_2': 21,
|
||||
'n_2': 2.5E-20,
|
||||
'a_eff': 70,
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
# -*- coding: utf-8 -*
|
||||
"""general_parameters.py contains the general configuration settings
|
||||
|
||||
The sectings are subdivided in two dictionaries:
|
||||
sys_param: a dictionary containing the general system parameters:
|
||||
f0: the starting frequency of the laser grid used to describe the WDM system [THz]
|
||||
ns: the number of 6.25 GHz slots in the grid
|
||||
|
||||
control_param:
|
||||
save_each_comp: a boolean flag. If true, it saves in output folder one spectrum file at the output of each
|
||||
component, otherwise it saves just the last spectrum
|
||||
is_linear: a bool flag. If true, is doesn't compute NLI, if false, OLE will consider NLI
|
||||
is_analytic: a boolean flag. If true, the NLI is computed through the analytic formula, otherwise it uses
|
||||
the double integral. Warning: the double integral is very slow.
|
||||
points_not_interp: if the double integral is used, it indicates how much points are calculated, others will
|
||||
be interpolated
|
||||
kind_interp: a string indicating the interpolation method for the double integral
|
||||
th_fwm: the threshold of the four wave mixing efficiency for the double integral
|
||||
n_points: number of points in which the double integral is computed in the high FWM efficiency region
|
||||
n_points_min: number of points in which the double integral is computed in the low FWM efficiency region
|
||||
n_cores: number of cores for parallel computation [not yet implemented]
|
||||
"""
|
||||
# System parameters
|
||||
sys_param = {
|
||||
'f0': 192.075,
|
||||
'ns': 328
|
||||
}
|
||||
|
||||
# control parameters
|
||||
control_param = {
|
||||
'save_each_comp': True,
|
||||
'is_linear': False,
|
||||
'is_analytic': True,
|
||||
'points_not_interp': 2,
|
||||
'kind_interp': 'linear',
|
||||
'th_fwm': 50,
|
||||
'n_points': 500,
|
||||
'n_points_min': 4,
|
||||
'n_cores': 1
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
# coding=utf-8
|
||||
""" link_description.py contains the full description of that OLE has to emulate.
|
||||
It contains a list of dictionaries, following the structure of the link and each element of the list describes one
|
||||
component.
|
||||
|
||||
'comp_cat': the kind of link component:
|
||||
PC: a passive component defined by a loss at a certain frequency and a loss tilt
|
||||
OA: an optical amplifier defined by a gain at a certain frequency, a gain tilt and a noise figure
|
||||
fiber: a span of fiber described by the type and the length
|
||||
'comp_id': is an id identifying the component. It has to be unique for each component!
|
||||
|
||||
extra fields for PC:
|
||||
'ref_freq': the frequency at which the 'loss' parameter is evaluated [THz]
|
||||
'loss': the loss at the frequency 'ref_freq' [dB]
|
||||
'loss_tlt': the frequency dependent loss [dB/THz]
|
||||
extra fields for OA:
|
||||
'ref_freq': the frequency at which the 'gain' parameter is evaluated [THz]
|
||||
'gain': the gain at the frequency 'ref_freq' [dB]
|
||||
'gain_tlt': the frequency dependent gain [dB/THz]
|
||||
'noise_figure': the noise figure of the optical amplifier [dB]
|
||||
extra fields for fiber:
|
||||
'fiber_type': a string calling the type of fiber described in the file fiber_parameters.py
|
||||
'length': the fiber length [km]
|
||||
|
||||
"""
|
||||
smf = {
|
||||
'comp_cat': 'fiber',
|
||||
'comp_id': '',
|
||||
'fiber_type': 'SMF',
|
||||
'length': 100
|
||||
}
|
||||
|
||||
oa = {
|
||||
'comp_cat': 'OA',
|
||||
'comp_id': '',
|
||||
'ref_freq': 193.5,
|
||||
'gain': 20,
|
||||
'gain_tlt': 0.0,
|
||||
'noise_figure': 5
|
||||
}
|
||||
|
||||
pc = {
|
||||
'comp_cat': 'PC',
|
||||
'comp_id': '04',
|
||||
'ref_freq': 193.,
|
||||
'loss': 2.0,
|
||||
'loss_tlt': 0.0
|
||||
}
|
||||
|
||||
link = []
|
||||
|
||||
for index in range(20):
|
||||
smf['comp_id'] = '%03d' % (2 * index)
|
||||
oa['comp_id'] = '%03d' % (2 * index + 1)
|
||||
link += [dict(smf)]
|
||||
link += [dict(oa)]
|
||||
|
||||
pc['comp_id'] = '%03d' % 40
|
||||
link += [dict(pc)]
|
||||
6
gnpy/core/__init__.py
Normal file
6
gnpy/core/__init__.py
Normal file
@@ -0,0 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from . import elements
|
||||
from .execute import *
|
||||
from .network import *
|
||||
from .utils import *
|
||||
445
gnpy/core/elements.py
Normal file
445
gnpy/core/elements.py
Normal file
@@ -0,0 +1,445 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Network elements class with SpectralInformation propagation using
|
||||
__call__ and propagate methods
|
||||
@author: Alessio Ferrari
|
||||
@author: Mattia Cantono
|
||||
@author: Vittorio Curri
|
||||
@author: giladgoldfarb
|
||||
@author: briantaylor
|
||||
@author: jeanluc-auge
|
||||
@acknowledgement : Dave Boertjes
|
||||
"""
|
||||
import numpy as np
|
||||
from scipy.constants import c, h
|
||||
|
||||
from gnpy.core.node import Node
|
||||
from gnpy.core.units import UNITS
|
||||
from gnpy.core.utils import lin2db, db2lin, itufs
|
||||
|
||||
|
||||
class Transceiver(Node):
|
||||
def __init__(self, config):
|
||||
super().__init__(config)
|
||||
self.osnr_ase_01nm = None
|
||||
self.osnr_ase = None
|
||||
self.osnr_nli = None
|
||||
self.snr = None
|
||||
|
||||
def _calc_snr(self, spectral_info):
|
||||
ase = [c.power.ase for c in spectral_info.carriers]
|
||||
nli = [c.power.nli for c in spectral_info.carriers]
|
||||
if min(ase)>1e-20:
|
||||
self.osnr_ase = [lin2db(c.power.signal/c.power.ase)
|
||||
for c in spectral_info.carriers]
|
||||
ratio_01nm = [lin2db(12.5e9/c.baud_rate) for c in spectral_info.carriers]
|
||||
self.osnr_ase_01nm = [ase - ratio for ase, ratio
|
||||
in zip(self.osnr_ase, ratio_01nm)]
|
||||
if min(nli)>1e-20:
|
||||
self.osnr_nli = [lin2db(c.power.signal/c.power.nli)
|
||||
for c in spectral_info.carriers]
|
||||
self.snr = [lin2db(c.power.signal/(c.power.nli+c.power.ase))
|
||||
for c in spectral_info.carriers]
|
||||
|
||||
def __repr__(self):
|
||||
if self.snr != None and self.osnr_ase != None:
|
||||
snr = round(np.mean(self.snr),2)
|
||||
osnr_ase = round(np.mean(self.osnr_ase),2)
|
||||
osnr_ase_01nm = round(np.mean(self.osnr_ase_01nm), 2)
|
||||
return f'{type(self).__name__}(uid={self.uid}, \
|
||||
osnr_ase(in 0.1nm)={osnr_ase_01nm}dB, osnr_ase(in signal bw)={osnr_ase}dB, \
|
||||
snr total(in signal bw)={snr})'
|
||||
else:
|
||||
return f'{type(self).__name__}(uid={self.uid})'
|
||||
|
||||
def __call__(self, spectral_info):
|
||||
self._calc_snr(spectral_info)
|
||||
return spectral_info
|
||||
|
||||
class Roadm(Node):
|
||||
def __init__(self, config):
|
||||
super().__init__(config)
|
||||
self.loss = 20 #dB
|
||||
|
||||
def __repr__(self):
|
||||
return f'{type(self).__name__}(uid={self.uid}, \
|
||||
loss={round(self.loss,1)}dB)'
|
||||
|
||||
def propagate(self, *carriers):
|
||||
attenuation = db2lin(self.loss)
|
||||
|
||||
for carrier in carriers:
|
||||
pwr = carrier.power
|
||||
pwr = pwr._replace(signal=pwr.signal/attenuation,
|
||||
nonlinear_interference=pwr.nli/attenuation,
|
||||
amplified_spontaneous_emission=pwr.ase/attenuation)
|
||||
yield carrier._replace(power=pwr)
|
||||
|
||||
def __call__(self, spectral_info):
|
||||
carriers = tuple(self.propagate(*spectral_info.carriers))
|
||||
return spectral_info.update(carriers=carriers)
|
||||
|
||||
class Fiber(Node):
|
||||
def __init__(self, config):
|
||||
super().__init__(config)
|
||||
self.length = self.params.length * \
|
||||
UNITS[self.params.length_units] #length in m
|
||||
self.loss_coef = self.params.loss_coef*1e-3 #lineic loss dB/m
|
||||
self.lin_loss_coef = self.params.loss_coef / (20*np.log10(np.exp(1)))
|
||||
self.dispersion = self.params.dispersion #s/m/m
|
||||
self.gamma = self.params.gamma #1/W/m
|
||||
self.loss = self.loss_coef * self.length #dB loss: useful for polymorphism (roadm, fiber, att)
|
||||
#TODO discuss factor 2 in the linear lineic attenuation
|
||||
|
||||
def __repr__(self):
|
||||
k = UNITS['km']
|
||||
return f'{type(self).__name__}(uid={self.uid}, \
|
||||
length={round(self.length/k, 1)}km, loss={round(self.loss,1)}dB)'
|
||||
|
||||
def lin_attenuation(self):
|
||||
attenuation = self.length * self.loss_coef
|
||||
return db2lin(attenuation)
|
||||
|
||||
@property
|
||||
def effective_length(self):
|
||||
alpha_dict = self.dbkm_2_lin()
|
||||
alpha = alpha_dict['alpha_acoef']
|
||||
leff = (1 - np.exp(-2 * alpha * self.length)) / (2*alpha)
|
||||
return leff
|
||||
|
||||
@property
|
||||
def asymptotic_length(self):
|
||||
alpha_dict = self.dbkm_2_lin()
|
||||
alpha = alpha_dict['alpha_acoef']
|
||||
aleff = 1 / (2 * alpha)
|
||||
return aleff
|
||||
|
||||
def beta2(self, ref_wavelength=None):
|
||||
""" Returns beta2 from dispersion parameter.
|
||||
Dispersion is entered in ps/nm/km.
|
||||
Disperion can be a numpy array or a single value. If a
|
||||
value ref_wavelength is not entered 1550e-9m will be assumed.
|
||||
ref_wavelength can be a numpy array.
|
||||
"""
|
||||
#TODO: discuss beta2 as method or attribute
|
||||
wl = 1550e-9 if ref_wavelength is None else ref_wavelength
|
||||
D = np.abs(self.dispersion)
|
||||
b2 = (wl**2) * D / (2 * np.pi * c) # 10^21 scales [ps^2/km]
|
||||
return b2 # s/Hz/m
|
||||
|
||||
def dbkm_2_lin(self):
|
||||
""" calculates the linear loss coefficient
|
||||
"""
|
||||
alpha_pcoef = self.loss_coef
|
||||
alpha_acoef = alpha_pcoef / (2 * 10*np.log10(np.exp(1)))
|
||||
s = 'alpha_pcoef is linear loss coefficient in [dB/km^-1] units'
|
||||
s = ''.join([s, "alpha_acoef is linear loss field amplitude \
|
||||
coefficient in [m^-1] units"])
|
||||
d = {'alpha_pcoef': alpha_pcoef,
|
||||
'alpha_acoef': alpha_acoef,
|
||||
'description:': s}
|
||||
return d
|
||||
|
||||
def _psi(self, carrier, interfering_carrier):
|
||||
""" Calculates eq. 123 from arXiv:1209.0394.
|
||||
"""
|
||||
if carrier.num_chan == interfering_carrier.num_chan: # SCI
|
||||
psi = np.arcsinh(0.5 * np.pi**2 * self.asymptotic_length
|
||||
* abs(self.beta2()) * carrier.baud_rate**2)
|
||||
else: # XCI
|
||||
delta_f = carrier.freq - interfering_carrier.freq
|
||||
psi = np.arcsinh(np.pi**2 * self.asymptotic_length * abs(self.beta2()) *
|
||||
carrier.baud_rate * (delta_f + 0.5 * interfering_carrier.baud_rate))
|
||||
psi -= np.arcsinh(np.pi**2 * self.asymptotic_length * abs(self.beta2()) *
|
||||
carrier.baud_rate * (delta_f - 0.5 * interfering_carrier.baud_rate))
|
||||
|
||||
return psi
|
||||
|
||||
def _gn_analytic(self, carrier, *carriers):
|
||||
""" Computes the nonlinear interference power on a single carrier.
|
||||
The method uses eq. 120 from arXiv:1209.0394.
|
||||
:param carrier: the signal under analysis
|
||||
:param carriers: the full WDM comb
|
||||
:return: carrier_nli: the amount of nonlinear interference in W on the under analysis
|
||||
"""
|
||||
|
||||
g_nli = 0
|
||||
for interfering_carrier in carriers:
|
||||
psi = self._psi(carrier, interfering_carrier)
|
||||
g_nli += (interfering_carrier.power.signal/interfering_carrier.baud_rate)**2 *\
|
||||
(carrier.power.signal/carrier.baud_rate) * psi
|
||||
|
||||
g_nli *= (16 / 27) * (self.gamma * self.effective_length)**2 /\
|
||||
(2 * np.pi * abs(self.beta2()) * self.asymptotic_length)
|
||||
|
||||
carrier_nli = carrier.baud_rate*g_nli
|
||||
return carrier_nli
|
||||
|
||||
def propagate(self, *carriers):
|
||||
|
||||
i=0
|
||||
for carrier in carriers:
|
||||
pwr = carrier.power
|
||||
carrier_nli = self._gn_analytic(carrier, *carriers)
|
||||
pwr = pwr._replace(signal=pwr.signal/self.lin_attenuation(),
|
||||
nonlinear_interference=(pwr.nli+carrier_nli)/self.lin_attenuation(),
|
||||
amplified_spontaneous_emission=pwr.ase/self.lin_attenuation())
|
||||
i+=1
|
||||
yield carrier._replace(power=pwr)
|
||||
|
||||
def __call__(self, spectral_info):
|
||||
carriers = tuple(self.propagate(*spectral_info.carriers))
|
||||
return spectral_info.update(carriers=carriers)
|
||||
|
||||
|
||||
class Edfa(Node):
|
||||
def __init__(self, config):
|
||||
super().__init__(config)
|
||||
self.interpol_dgt = None #inerpolated dynamic gain tilt: N numpy array
|
||||
self.interpol_gain_ripple = None #gain ripple: N numpy array
|
||||
self.interpol_nf_ripple = None #nf_ripple: N numpy array
|
||||
self.channel_freq = None #SI channel frequencies: N numpy array
|
||||
"""nf, gprofile, pin and pout attributs are set by interpol_params"""
|
||||
self.nf = None #dB edfa nf at operational.gain_target: N numpy array
|
||||
self.gprofile = None
|
||||
self.pin_db = None
|
||||
self.pout_db = None
|
||||
|
||||
def __repr__(self):
|
||||
if self.pin_db != None and self.pout_db != None:
|
||||
nf_avg = round(np.mean(self.nf),1)
|
||||
return f'{type(self).__name__}(uid={self.uid}, \
|
||||
gain={round(self.operational.gain_target,1)}dB, NF={nf_avg}dB, \
|
||||
Pin={round(self.pin_db, 1)}dBm, Pout={round(self.pout_db,1)}dBm)'
|
||||
else:
|
||||
return f'{type(self).__name__}(uid={self.uid}, \
|
||||
gain={self.operational.gain_target})'
|
||||
|
||||
def interpol_params(self, frequencies, pin, baud_rates):
|
||||
"""interpolate SI channel frequencies with the edfa dgt and gain_ripple frquencies from json
|
||||
set the edfa class __init__ None parameters :
|
||||
self.channel_freq, self.nf, self.interpol_dgt and self.interpol_gain_ripple
|
||||
"""
|
||||
#TODO read amplifier actual frequencies from additional params in json
|
||||
amplifier_freq = itufs(0.05)*1e12 # Hz
|
||||
self.channel_freq = frequencies
|
||||
self.interpol_dgt = np.interp(self.channel_freq, amplifier_freq, self.params.dgt)
|
||||
self.interpol_gain_ripple = np.interp(self.channel_freq, amplifier_freq, self.params.gain_ripple)
|
||||
self.interpol_nf_ripple = np.interp(self.channel_freq, amplifier_freq, self.params.nf_ripple)
|
||||
|
||||
self.pin_db = lin2db(np.sum(pin*1e3))
|
||||
"""check power saturation and correct target_gain accordingly:"""
|
||||
gain_target = min(self.operational.gain_target, self.params.p_max-self.pin_db)
|
||||
self.operational.gain_target = gain_target
|
||||
|
||||
self.nf = self._calc_nf()
|
||||
self.gprofile = self._gain_profile(pin)
|
||||
|
||||
pout = (pin + self.noise_profile(baud_rates))*db2lin(self.gprofile)
|
||||
self.pout_db = lin2db(np.sum(pout*1e3))
|
||||
# ! ase & nli are only calculated in signal bandwidth
|
||||
# => pout_db is not the absolute full ouput power (negligible if sufficient channels)
|
||||
|
||||
def _calc_nf(self):
|
||||
"""nf calculation based on 2 models: self.params.nf_model.enabled from json import:
|
||||
True => 2 stages amp modelling based on precalculated nf1, nf2 and delta_p in build_OA_json
|
||||
False => polynomial fit based on self.params.nf_fit_coeff"""
|
||||
#TODO : tbd alarm rising or input VOA padding in case
|
||||
#gain_min > gain_target TBD:
|
||||
pad = max(self.params.gain_min - self.operational.gain_target, 0)
|
||||
gain_target = self.operational.gain_target + pad
|
||||
dg = gain_target - self.params.gain_flatmax # ! <0
|
||||
if self.params.nf_model.enabled:
|
||||
g1a = gain_target - self.params.nf_model.delta_p + dg
|
||||
nf_avg = lin2db(db2lin(self.params.nf_model.nf1) + db2lin(self.params.nf_model.nf2)/db2lin(g1a))
|
||||
else:
|
||||
nf_avg = np.polyval(self.params.nf_fit_coeff, dg)
|
||||
|
||||
nf_array = self.interpol_nf_ripple + nf_avg + pad #input VOA = 1 for 1 NF degradation
|
||||
return nf_array
|
||||
|
||||
def noise_profile(self, df):
|
||||
""" noise_profile(bw) computes amplifier ase (W) in signal bw (Hz)
|
||||
noise is calculated at amplifier input
|
||||
|
||||
:bw: signal bandwidth = baud rate in Hz
|
||||
:type bw: float
|
||||
|
||||
:return: the asepower in W in the signal bandwidth bw for 96 channels
|
||||
:return type: numpy array of float
|
||||
|
||||
ASE POWER USING PER CHANNEL GAIN PROFILE
|
||||
INPUTS:
|
||||
NF_dB - Noise figure in dB, vector of length number of channels or
|
||||
spectral slices
|
||||
G_dB - Actual gain calculated for the EDFA, vector of length number of
|
||||
channels or spectral slices
|
||||
ffs - Center frequency grid of the channels or spectral slices in
|
||||
THz, vector of length number of channels or spectral slices
|
||||
dF - width of each channel or spectral slice in THz,
|
||||
vector of length number of channels or spectral slices
|
||||
OUTPUT:
|
||||
ase_dBm - ase in dBm per channel or spectral slice
|
||||
NOTE: the output is the total ASE in the channel or spectral slice. For
|
||||
50GHz channels the ASE BW is effectively 0.4nm. To get to noise power
|
||||
in 0.1nm, subtract 6dB.
|
||||
|
||||
ONSR is usually quoted as channel power divided by
|
||||
the ASE power in 0.1nm RBW, regardless of the width of the actual
|
||||
channel. This is a historical convention from the days when optical
|
||||
signals were much smaller (155Mbps, 2.5Gbps, ... 10Gbps) than the
|
||||
resolution of the OSAs that were used to measure spectral power which
|
||||
were set to 0.1nm resolution for convenience. Moving forward into
|
||||
flexible grid and high baud rate signals, it may be convenient to begin
|
||||
quoting power spectral density in the same BW for both signal and ASE,
|
||||
e.g. 12.5GHz."""
|
||||
|
||||
ase = h * df * self.channel_freq * db2lin(self.nf) #W
|
||||
return ase #in W, @amplifier input
|
||||
|
||||
def _gain_profile(self, pin):
|
||||
"""
|
||||
Pin : input power / channel in W
|
||||
|
||||
:param gain_ripple: design flat gain
|
||||
:param dgt: design gain tilt
|
||||
:param Pin: total input power in W
|
||||
:param gp: Average gain setpoint in dB units
|
||||
:param gtp: gain tilt setting
|
||||
:type gain_ripple: numpy.ndarray
|
||||
:type dgt: numpy.ndarray
|
||||
:type Pin: numpy.ndarray
|
||||
:type gp: float
|
||||
:type gtp: float
|
||||
:return: gain profile in dBm
|
||||
:rtype: numpy.ndarray
|
||||
|
||||
AMPLIFICATION USING INPUT PROFILE
|
||||
INPUTS:
|
||||
gain_ripple - vector of length number of channels or spectral slices
|
||||
DGT - vector of length number of channels or spectral slices
|
||||
Pin - input powers vector of length number of channels or
|
||||
spectral slices
|
||||
Gp - provisioned gain length 1
|
||||
GTp - provisioned tilt length 1
|
||||
|
||||
OUTPUT:
|
||||
amp gain per channel or spectral slice
|
||||
NOTE: there is no checking done for violations of the total output
|
||||
power capability of the amp.
|
||||
EDIT OF PREVIOUS NOTE: power violation now added in interpol_params
|
||||
Ported from Matlab version written by David Boerges at Ciena.
|
||||
Based on:
|
||||
R. di Muro, "The Er3+ fiber gain coefficient derived from a dynamic
|
||||
gain
|
||||
tilt technique", Journal of Lightwave Technology, Vol. 18, Iss. 3,
|
||||
Pp. 343-347, 2000.
|
||||
"""
|
||||
err_tolerance = 1.0e-11
|
||||
simple_opt = True
|
||||
|
||||
# TODO check what param should be used (currently length(dgt))
|
||||
nchan = np.arange(len(self.interpol_dgt))
|
||||
|
||||
# TODO find a way to use these or lose them. Primarily we should have
|
||||
# a way to determine if exceeding the gain or output power of the amp
|
||||
tot_in_power_db = lin2db(np.sum(pin*1e3)) # ! Pin expressed in W
|
||||
|
||||
# Linear fit to get the
|
||||
p = np.polyfit(nchan, self.interpol_dgt, 1)
|
||||
dgt_slope = p[0]
|
||||
|
||||
# Calculate the target slope- Currently assumes equal spaced channels
|
||||
# TODO make it so that supports arbitrary channel spacing.
|
||||
targ_slope = self.operational.tilt_target / (len(nchan) - 1)
|
||||
|
||||
# 1st estimate of DGT scaling
|
||||
if abs(dgt_slope) > 0.001: # add check for div 0 due to flat dgt
|
||||
dgts1 = targ_slope / dgt_slope
|
||||
else:
|
||||
dgts1 = 0
|
||||
# when simple_opt is true code makes 2 attempts to compute gain and
|
||||
# the internal voa value. This is currently here to provide direct
|
||||
# comparison with original Matlab code. Will be removed.
|
||||
# TODO replace with loop
|
||||
|
||||
if simple_opt:
|
||||
|
||||
# 1st estimate of Er gain & voa loss
|
||||
g1st = np.array(self.interpol_gain_ripple) + self.params.gain_flatmax + \
|
||||
np.array(self.interpol_dgt) * dgts1
|
||||
voa = lin2db(np.mean(db2lin(g1st))) - self.operational.gain_target
|
||||
|
||||
# 2nd estimate of Amp ch gain using the channel input profile
|
||||
g2nd = g1st - voa
|
||||
|
||||
pout_db = lin2db(np.sum(pin*1e3*db2lin(g2nd)))
|
||||
dgts2 = self.operational.gain_target - (pout_db - tot_in_power_db)
|
||||
|
||||
# Center estimate of amp ch gain
|
||||
xcent = dgts2
|
||||
gcent = g1st - voa + np.array(self.interpol_dgt) * xcent
|
||||
pout_db = lin2db(np.sum(pin*1e3*db2lin(gcent)))
|
||||
gavg_cent = pout_db - tot_in_power_db
|
||||
|
||||
# Lower estimate of Amp ch gain
|
||||
deltax = np.max(g1st) - np.min(g1st)
|
||||
# ! if no ripple deltax = 0 => xlow = xcent: div 0
|
||||
# add check for flat gain response :
|
||||
if abs(deltax) > 0.05: #enough ripple to consider calculation and avoid div 0
|
||||
xlow = dgts2 - deltax
|
||||
glow = g1st - voa + np.array(self.interpol_dgt) * xlow
|
||||
pout_db = lin2db(np.sum(pin*1e3*db2lin(glow)))
|
||||
gavg_low = pout_db - tot_in_power_db
|
||||
|
||||
# Upper gain estimate
|
||||
xhigh = dgts2 + deltax
|
||||
ghigh = g1st - voa + np.array(self.interpol_dgt) * xhigh
|
||||
pout_db = lin2db(np.sum(pin*1e3*db2lin(ghigh)))
|
||||
gavg_high = pout_db - tot_in_power_db
|
||||
|
||||
# compute slope
|
||||
slope1 = (gavg_low - gavg_cent) / (xlow - xcent)
|
||||
slope2 = (gavg_cent - gavg_high) / (xcent - xhigh)
|
||||
|
||||
if np.abs(self.operational.gain_target - gavg_cent) <= err_tolerance:
|
||||
dgts3 = xcent
|
||||
elif self.operational.gain_target < gavg_cent:
|
||||
dgts3 = xcent - (gavg_cent - self.operational.gain_target) / slope1
|
||||
else:
|
||||
dgts3 = xcent + (-gavg_cent + self.operational.gain_target) / slope2
|
||||
|
||||
gprofile = g1st - voa + np.array(self.interpol_dgt) * dgts3
|
||||
else: #not enough ripple
|
||||
gprofile = g1st - voa
|
||||
else: #simple_opt
|
||||
gprofile = None
|
||||
|
||||
return gprofile
|
||||
|
||||
def propagate(self, *carriers):
|
||||
"""add ase noise to the propagating carriers of SpectralInformation"""
|
||||
i = 0
|
||||
pin = np.array([c.power.signal+c.power.nli+c.power.ase for c in carriers]) #pin in W
|
||||
freq = np.array([c.frequency for c in carriers])
|
||||
brate = np.array([c.baud_rate for c in carriers])
|
||||
#interpolate the amplifier vectors with the carriers freq, calculate nf & gain profile
|
||||
self.interpol_params(freq, pin, brate)
|
||||
gain = db2lin(self.gprofile)
|
||||
carrier_ase = self.noise_profile(brate)
|
||||
|
||||
for carrier in carriers:
|
||||
|
||||
pwr = carrier.power
|
||||
bw = carrier.baud_rate
|
||||
pwr = pwr._replace(signal=pwr.signal*gain[i],
|
||||
nonlinear_interference=pwr.nli*gain[i],
|
||||
amplified_spontaneous_emission=(pwr.ase+carrier_ase[i])*gain[i])
|
||||
i += 1
|
||||
yield carrier._replace(power=pwr)
|
||||
|
||||
def __call__(self, spectral_info):
|
||||
carriers = tuple(self.propagate(*spectral_info.carriers))
|
||||
return spectral_info.update(carriers=carriers)
|
||||
2
gnpy/core/execute.py
Normal file
2
gnpy/core/execute.py
Normal file
@@ -0,0 +1,2 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
50
gnpy/core/info.py
Normal file
50
gnpy/core/info.py
Normal file
@@ -0,0 +1,50 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
class ConvenienceAccess:
|
||||
def __init_subclass__(cls):
|
||||
for abbrev, field in getattr(cls, '_ABBREVS', {}).items():
|
||||
setattr(cls, abbrev, property(lambda self, f=field: getattr(self, f)))
|
||||
|
||||
def update(self, **kwargs):
|
||||
for abbrev, field in getattr(self, '_ABBREVS', {}).items():
|
||||
if abbrev in kwargs:
|
||||
kwargs[field] = kwargs.pop(abbrev)
|
||||
return self._replace(**kwargs)
|
||||
|
||||
class Power(namedtuple('Power', 'signal nonlinear_interference amplified_spontaneous_emission'), ConvenienceAccess):
|
||||
_ABBREVS = {'nli': 'nonlinear_interference',
|
||||
'ase': 'amplified_spontaneous_emission',}
|
||||
|
||||
class Channel(namedtuple('Channel', 'channel_number frequency baud_rate roll_off power'), ConvenienceAccess):
|
||||
_ABBREVS = {'channel': 'channel_number',
|
||||
'num_chan': 'channel_number',
|
||||
'ffs': 'frequency',
|
||||
'freq': 'frequency',}
|
||||
|
||||
class SpectralInformation(namedtuple('SpectralInformation', 'carriers'), ConvenienceAccess):
|
||||
def __new__(cls, *carriers):
|
||||
return super().__new__(cls, carriers)
|
||||
|
||||
if __name__ == '__main__':
|
||||
si = SpectralInformation(
|
||||
Channel(1, 193.95e12, 32e9, 0.15, # 193.95 THz, 32 Gbaud
|
||||
Power(1e-3, 1e-6, 1e-6)), # 1 mW, 1uW, 1uW
|
||||
Channel(1, 195.95e12, 32e9, 0.15, # 195.95 THz, 32 Gbaud
|
||||
Power(1.2e-3, 1e-6, 1e-6)), # 1.2 mW, 1uW, 1uW
|
||||
)
|
||||
|
||||
si = SpectralInformation()
|
||||
spacing = 0.05 #THz
|
||||
|
||||
si = si.update(carriers=tuple(Channel(f+1, 191.3+spacing*(f+1), 32e9, 0.15, Power(1e-3, f, 1)) for f in range(96)))
|
||||
|
||||
print(f'si = {si}')
|
||||
print(f'si = {si.carriers[0].power.nli}')
|
||||
print(f'si = {si.carriers[20].power.nli}')
|
||||
"""
|
||||
si2 = si.update(carriers=tuple(c.update(power = c.power.update(nli = c.power.nli * 1e5))
|
||||
for c in si.carriers))
|
||||
print(f'si2 = {si2}')
|
||||
"""
|
||||
114
gnpy/core/network.py
Normal file
114
gnpy/core/network.py
Normal file
@@ -0,0 +1,114 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from networkx import DiGraph
|
||||
|
||||
from gnpy.core import elements
|
||||
from gnpy.core.elements import Fiber, Edfa, Transceiver, Roadm
|
||||
from gnpy.core.units import UNITS
|
||||
|
||||
MAX_SPAN_LENGTH = 125000
|
||||
TARGET_SPAN_LENGTH = 100000
|
||||
MIN_SPAN_LENGTH = 75000
|
||||
|
||||
def network_from_json(json_data):
|
||||
# NOTE|dutc: we could use the following, but it would tie our data format
|
||||
# too closely to the graph library
|
||||
# from networkx import node_link_graph
|
||||
g = DiGraph()
|
||||
for el_config in json_data['elements']:
|
||||
g.add_node(getattr(elements, el_config['type'])(el_config))
|
||||
|
||||
nodes = {k.uid: k for k in g.nodes()}
|
||||
|
||||
for cx in json_data['connections']:
|
||||
from_node, to_node = cx['from_node'], cx['to_node']
|
||||
g.add_edge(nodes[from_node], nodes[to_node])
|
||||
|
||||
return g
|
||||
|
||||
def calculate_new_length(fiber_length):
|
||||
result = (fiber_length, 1)
|
||||
if fiber_length > MAX_SPAN_LENGTH:
|
||||
n_spans = int(fiber_length // TARGET_SPAN_LENGTH)
|
||||
|
||||
length1 = fiber_length / (n_spans+1)
|
||||
result1 = (length1, n_spans+1)
|
||||
delta1 = TARGET_SPAN_LENGTH-length1
|
||||
|
||||
length2 = fiber_length / n_spans
|
||||
delta2 = length2-TARGET_SPAN_LENGTH
|
||||
result2 = (length2, n_spans)
|
||||
|
||||
if length1<MIN_SPAN_LENGTH and length2<MAX_SPAN_LENGTH:
|
||||
result = result2
|
||||
elif length2>MAX_SPAN_LENGTH and length1>MIN_SPAN_LENGTH:
|
||||
result = result1
|
||||
else:
|
||||
if delta1 < delta2:
|
||||
result = result1
|
||||
else:
|
||||
result = result2
|
||||
|
||||
return result
|
||||
|
||||
def split_fiber(network, fiber):
|
||||
new_length, n_spans = calculate_new_length(fiber.length)
|
||||
prev_node = fiber
|
||||
if n_spans > 1:
|
||||
next_nodes = [_ for _ in network.successors(fiber)]
|
||||
for next_node in next_nodes:
|
||||
network.remove_edge(fiber, next_node)
|
||||
|
||||
new_params_length = new_length / UNITS[fiber.params.length_units]
|
||||
config = {'uid':fiber.uid, 'type': 'Fiber', 'metadata': fiber.__dict__['metadata'], \
|
||||
'params': fiber.__dict__['params']}
|
||||
fiber.uid = config['uid'] + '_1'
|
||||
fiber.length = new_length
|
||||
fiber.loss = fiber.loss_coef * fiber.length
|
||||
|
||||
for i in range(2, n_spans+1):
|
||||
new_config = dict(config)
|
||||
new_config['uid'] = new_config['uid'] + '_' + str(i)
|
||||
new_config['params'].length = new_params_length
|
||||
new_node = Fiber(new_config)
|
||||
network.add_node(new_node)
|
||||
network.add_edge(prev_node, new_node)
|
||||
network = add_egress_amplifier(network, prev_node)
|
||||
prev_node = new_node
|
||||
|
||||
for next_node in next_nodes:
|
||||
network.add_edge(prev_node, next_node)
|
||||
|
||||
network = add_egress_amplifier(network, prev_node)
|
||||
return network
|
||||
|
||||
def add_egress_amplifier(network, node):
|
||||
next_nodes = [n for n in network.successors(node)
|
||||
if not (isinstance(n, Edfa) or isinstance(n, Transceiver))]
|
||||
i = 1
|
||||
for next_node in next_nodes:
|
||||
network.remove_edge(node, next_node)
|
||||
|
||||
uid = 'Edfa' + str(i)+ '_' + str(node.uid)
|
||||
metadata = next_node.metadata
|
||||
operational = {'gain_target': node.loss, 'tilt_target': 0}
|
||||
edfa_config_json = 'edfa_config.json'
|
||||
config = {'uid':uid, 'type': 'Edfa', 'metadata': metadata, \
|
||||
'config_from_json': edfa_config_json, 'operational': operational}
|
||||
new_edfa = Edfa(config)
|
||||
network.add_node(new_edfa)
|
||||
network.add_edge(node,new_edfa)
|
||||
network.add_edge(new_edfa, next_node)
|
||||
i +=1
|
||||
|
||||
return network
|
||||
|
||||
def build_network(network):
|
||||
fibers = [f for f in network.nodes() if isinstance(f, Fiber)]
|
||||
for fiber in fibers:
|
||||
network = split_fiber(network, fiber)
|
||||
|
||||
roadms = [r for r in network.nodes() if isinstance(r, Roadm)]
|
||||
for roadm in roadms:
|
||||
add_egress_amplifier(network, roadm)
|
||||
|
||||
60
gnpy/core/node.py
Normal file
60
gnpy/core/node.py
Normal file
@@ -0,0 +1,60 @@
|
||||
#! /bin/usr/python3
|
||||
|
||||
from uuid import uuid4
|
||||
from gnpy.core.utils import load_json
|
||||
|
||||
|
||||
class ConfigStruct:
|
||||
|
||||
def __init__(self, **config):
|
||||
if config is None:
|
||||
return None
|
||||
if 'config_from_json' in config:
|
||||
json_config = load_json(config['config_from_json'])
|
||||
self.set_config_attr(json_config)
|
||||
|
||||
self.set_config_attr(config)
|
||||
|
||||
def set_config_attr(self, config):
|
||||
for k, v in config.items():
|
||||
setattr(self, k, ConfigStruct(**v)
|
||||
if isinstance(v, dict) else v)
|
||||
|
||||
def __repr__(self):
|
||||
return f'{self.__dict__}'
|
||||
|
||||
|
||||
class Node:
|
||||
|
||||
def __init__(self, config=None):
|
||||
self.config = ConfigStruct(**config)
|
||||
if self.config is None or not hasattr(self.config, 'uid'):
|
||||
self.uid = uuid4()
|
||||
else:
|
||||
self.uid = self.config.uid
|
||||
if hasattr(self.config, 'params'):
|
||||
self.params = self.config.params
|
||||
if hasattr(self.config, 'metadata'):
|
||||
self.metadata = self.config.metadata
|
||||
if hasattr(self.config, 'operational'):
|
||||
self.operational = self.config.operational
|
||||
|
||||
@property
|
||||
def coords(self):
|
||||
return tuple(self.lng, self.lat)
|
||||
|
||||
@property
|
||||
def location(self):
|
||||
return self.config.metadata.location
|
||||
|
||||
@property
|
||||
def loc(self): # Aliases .location
|
||||
return self.location
|
||||
|
||||
@property
|
||||
def lng(self):
|
||||
return self.config.metadata.location.longitude
|
||||
|
||||
@property
|
||||
def lat(self):
|
||||
return self.config.metadata.location.latitude
|
||||
2
gnpy/core/units.py
Normal file
2
gnpy/core/units.py
Normal file
@@ -0,0 +1,2 @@
|
||||
UNITS = {'m': 1,
|
||||
'km': 1E3}
|
||||
130
gnpy/core/utils.py
Normal file
130
gnpy/core/utils.py
Normal file
@@ -0,0 +1,130 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import json
|
||||
|
||||
import numpy as np
|
||||
from numpy import pi, cos, sqrt, log10
|
||||
|
||||
|
||||
def load_json(filename):
|
||||
with open(filename, 'r') as f:
|
||||
data = json.load(f)
|
||||
return data
|
||||
|
||||
|
||||
def save_json(obj, filename):
|
||||
with open(filename, 'w') as f:
|
||||
json.dump(obj, f)
|
||||
|
||||
|
||||
def c():
|
||||
"""
|
||||
Returns the speed of light in meters per second
|
||||
"""
|
||||
return 299792458.0
|
||||
|
||||
|
||||
def itufs(spacing, startf=191.35, stopf=196.10):
|
||||
"""Creates an array of frequencies whose default range is
|
||||
191.35-196.10 THz
|
||||
|
||||
:param spacing: Frequency spacing in THz
|
||||
:param starf: Start frequency in THz
|
||||
:param stopf: Stop frequency in THz
|
||||
:type spacing: float
|
||||
:type startf: float
|
||||
:type stopf: float
|
||||
:return an array of frequnecies determined by the spacing parameter
|
||||
:rtype: numpy.ndarray
|
||||
"""
|
||||
return np.arange(startf, stopf + spacing / 2, spacing)
|
||||
|
||||
|
||||
def h():
|
||||
"""
|
||||
Returns plank's constant in J*s
|
||||
"""
|
||||
return 6.62607004e-34
|
||||
|
||||
|
||||
def lin2db(value):
|
||||
return 10 * log10(value)
|
||||
|
||||
|
||||
def db2lin(value):
|
||||
return 10**(value / 10)
|
||||
|
||||
|
||||
def wavelength2freq(value):
|
||||
""" Converts wavelength units to frequeuncy units.
|
||||
"""
|
||||
return c() / value
|
||||
|
||||
|
||||
def freq2wavelength(value):
|
||||
""" Converts frequency units to wavelength units.
|
||||
"""
|
||||
return c() / value
|
||||
|
||||
|
||||
def deltawl2deltaf(delta_wl, wavelength):
|
||||
""" deltawl2deltaf(delta_wl, wavelength):
|
||||
delta_wl is BW in wavelength units
|
||||
wavelength is the center wl
|
||||
units for delta_wl and wavelength must be same
|
||||
|
||||
:param delta_wl: delta wavelength BW in same units as wavelength
|
||||
:param wavelength: wavelength BW is relevant for
|
||||
:type delta_wl: float or numpy.ndarray
|
||||
:type wavelength: float
|
||||
:return: The BW in frequency units
|
||||
:rtype: float or ndarray
|
||||
|
||||
"""
|
||||
f = wavelength2freq(wavelength)
|
||||
return delta_wl * f / wavelength
|
||||
|
||||
|
||||
def deltaf2deltawl(delta_f, frequency):
|
||||
""" deltawl2deltaf(delta_f, frequency):
|
||||
converts delta frequency to delta wavelength
|
||||
units for delta_wl and wavelength must be same
|
||||
|
||||
:param delta_f: delta frequency in same units as frequency
|
||||
:param frequency: frequency BW is relevant for
|
||||
:type delta_f: float or numpy.ndarray
|
||||
:type frequency: float
|
||||
:return: The BW in wavelength units
|
||||
:rtype: float or ndarray
|
||||
|
||||
"""
|
||||
wl = freq2wavelength(frequency)
|
||||
return delta_f * wl / frequency
|
||||
|
||||
|
||||
def rrc(ffs, baud_rate, alpha):
|
||||
""" rrc(ffs, baud_rate, alpha): computes the root-raised cosine filter
|
||||
function.
|
||||
|
||||
:param ffs: A numpy array of frequencies
|
||||
:param baud_rate: The Baud Rate of the System
|
||||
:param alpha: The roll-off factor of the filter
|
||||
:type ffs: numpy.ndarray
|
||||
:type baud_rate: float
|
||||
:type alpha: float
|
||||
:return: hf a numpy array of the filter shape
|
||||
:rtype: numpy.ndarray
|
||||
|
||||
"""
|
||||
Ts = 1 / baud_rate
|
||||
l_lim = (1 - alpha) / (2 * Ts)
|
||||
r_lim = (1 + alpha) / (2 * Ts)
|
||||
hf = np.zeros(np.shape(ffs))
|
||||
slope_inds = np.where(
|
||||
np.logical_and(np.abs(ffs) > l_lim, np.abs(ffs) < r_lim))
|
||||
hf[slope_inds] = 0.5 * (1 + cos((pi * Ts / alpha) *
|
||||
(np.abs(ffs[slope_inds]) - l_lim)))
|
||||
p_inds = np.where(np.logical_and(np.abs(ffs) > 0, np.abs(ffs) < l_lim))
|
||||
hf[p_inds] = 1
|
||||
return sqrt(hf)
|
||||
904
gnpy/gnpy.py
904
gnpy/gnpy.py
@@ -1,904 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""Top-level package for gnpy."""
|
||||
|
||||
__author__ = """<TBD>"""
|
||||
__email__ = '<TBD>@<TBD>.com'
|
||||
__version__ = '0.1.0'
|
||||
|
||||
import numpy as np
|
||||
import multiprocessing as mp
|
||||
import scipy.interpolate as interp
|
||||
|
||||
"""
|
||||
GNPy: a Python 3 implementation of the Gaussian Noise (GN) Model of nonlinear
|
||||
propagation, developed by the OptCom group, Department of Electronics and
|
||||
Telecommunications, Politecnico di Torino, Italy
|
||||
"""
|
||||
|
||||
__credits__ = ["Mattia Cantono", "Vittorio Curri", "Alessio Ferrari"]
|
||||
|
||||
|
||||
def raised_cosine_comb(f, rs, roll_off, center_freq, power):
|
||||
""" 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: Array of frequencies in THz
|
||||
:param rs: Array of Symbol Rates in TBaud. One Symbol rate for each channel
|
||||
:param roll_off: Array of roll-off factors [0,1). One per channel
|
||||
:param center_freq: Array of channels central frequencies in THz. One per channel
|
||||
:param power: Array of channel powers in W. One per channel
|
||||
:return: PSD of the WDM comb evaluated over f
|
||||
"""
|
||||
ts_arr = 1.0 / rs
|
||||
passband_arr = (1.0 - roll_off) / (2.0 * ts_arr)
|
||||
stopband_arr = (1.0 + roll_off) / (2.0 * ts_arr)
|
||||
g = power / rs
|
||||
psd = np.zeros(np.shape(f))
|
||||
for ind in range(np.size(center_freq)):
|
||||
f_nch = center_freq[ind]
|
||||
g_ch = g[ind]
|
||||
ts = ts_arr[ind]
|
||||
passband = passband_arr[ind]
|
||||
stopband = stopband_arr[ind]
|
||||
ff = np.abs(f - f_nch)
|
||||
tf = ff - passband
|
||||
if roll_off[ind] == 0:
|
||||
psd = np.where(tf <= 0, g_ch, 0.) + psd
|
||||
else:
|
||||
psd = g_ch * (np.where(tf <= 0, 1., 0.) + 1.0 / 2.0 * (1 + np.cos(np.pi * ts / roll_off[ind] *
|
||||
tf)) * np.where(tf > 0, 1., 0.) *
|
||||
np.where(np.abs(ff) <= stopband, 1., 0.)) + psd
|
||||
|
||||
return psd
|
||||
|
||||
|
||||
def fwm_eff(a, Lspan, b2, ff):
|
||||
""" Computes the four-wave mixing efficiency given the fiber characteristics
|
||||
over a given frequency set ff
|
||||
:param a: Fiber loss coefficient in 1/km
|
||||
:param Lspan: Fiber length in km
|
||||
:param b2: Fiber Dispersion coefficient in ps/THz/km
|
||||
:param ff: Array of Frequency points in THz
|
||||
:return: FWM efficiency rho
|
||||
"""
|
||||
rho = np.power(np.abs((1.0 - np.exp(-2.0 * a * Lspan + 1j * 4.0 * np.pi * np.pi * b2 * Lspan * ff)) / (
|
||||
2.0 * a - 1j * 4.0 * np.pi * np.pi * b2 * ff)), 2)
|
||||
return rho
|
||||
|
||||
|
||||
def get_freqarray(f, Bopt, fmax, max_step, f_dense_low, f_dense_up, df_dense):
|
||||
""" Returns a non-uniformly spaced frequency array useful for fast GN-model.
|
||||
integration. The frequency array is made of a denser area, sided by two
|
||||
log-spaced arrays
|
||||
:param f: Central frequency at which NLI is evaluated in THz
|
||||
:param Bopt: Total optical bandwidth of the system in THz
|
||||
:param fmax: Upper limit of the integration domain in THz
|
||||
:param max_step: Maximum step size for frequency array definition in THz
|
||||
:param f_dense_low: Lower limit of denser frequency region in THz
|
||||
:param f_dense_up: Upper limit of denser frequency region in THz
|
||||
:param df_dense: Step size to be used in the denser frequency region in THz
|
||||
:return: Non uniformly defined frequency array
|
||||
"""
|
||||
f_dense = np.arange(f_dense_low, f_dense_up, df_dense)
|
||||
k = Bopt / 2.0 / (Bopt / 2.0 - max_step) # Compute Step ratio for log-spaced array definition
|
||||
if f < 0:
|
||||
Nlog_short = np.ceil(np.log(fmax / np.abs(f_dense_low)) / np.log(k) + 1.0)
|
||||
f1_short = -(np.abs(f_dense_low) * np.power(k, np.arange(Nlog_short, 0.0, -1.0) - 1.0))
|
||||
k = (Bopt / 2 + (np.abs(f_dense_up) - f_dense_low)) / (Bopt / 2.0 - max_step + (np.abs(f_dense_up) - f_dense_up))
|
||||
Nlog_long = np.ceil(np.log((fmax + (np.abs(f_dense_up) - f_dense_up)) / abs(f_dense_up)) * 1.0 / np.log(k) + 1.0)
|
||||
f1_long = np.abs(f_dense_up) * np.power(k, (np.arange(1, Nlog_long + 1) - 1.0)) - (
|
||||
np.abs(f_dense_up) - f_dense_up)
|
||||
f1_array = np.concatenate([f1_short, f_dense[1:], f1_long])
|
||||
else:
|
||||
Nlog_short = np.ceil(np.log(fmax / np.abs(f_dense_up)) / np.log(k) + 1.0)
|
||||
f1_short = f_dense_up * np.power(k, np.arange(1, Nlog_short + 1.0) - 1.0)
|
||||
k = (Bopt / 2.0 + (abs(f_dense_low) + f_dense_low)) / (Bopt / 2.0 - max_step + (abs(f_dense_low) + f_dense_low))
|
||||
Nlog_long = np.ceil(np.log((fmax + (np.abs(f_dense_low) + f_dense_low)) / np.abs(f_dense_low)) / np.log(k) + 1)
|
||||
f1_long = -(np.abs(f_dense_low) * np.power(k, np.arange(Nlog_long, 0, -1) - 1.0)) + (
|
||||
abs(f_dense_low) + f_dense_low)
|
||||
f1_array = np.concatenate([f1_long, f_dense[1:], f1_short])
|
||||
return f1_array
|
||||
|
||||
|
||||
def GN_integral(b2, Lspan, a_db, gam, f_ch, b_ch, roll_off, power, Nch, model_param):
|
||||
""" GN_integral computes the GN reference formula via smart brute force integration. The Gaussian Noise model is
|
||||
applied in its incoherent form (phased-array factor =1). The function computes the integral by columns: for each f1,
|
||||
a non-uniformly spaced f2 array is generated, and the integrand function is computed there. At the end of the loop
|
||||
on f1, the overall GNLI is computed. Accuracy can be tuned by operating on model_param argument.
|
||||
|
||||
:param b2: Fiber dispersion coefficient in ps/THz/km. Scalar
|
||||
:param Lspan: Fiber Span length in km. Scalar
|
||||
:param a_db: Fiber loss coeffiecient in dB/km. Scalar
|
||||
:param gam: Fiber nonlinear coefficient in 1/W/km. Scalar
|
||||
:param f_ch: Baseband channels center frequencies in THz. Array of size 1xNch
|
||||
:param b_ch: Channels' -3 dB bandwidth. Array of size 1xNch
|
||||
:param roll_off: Channels' Roll-off factors [0,1). Array of size 1xNch
|
||||
:param power: Channels' power values in W. Array of size 1xNch
|
||||
:param Nch: Number of channels. Scalar
|
||||
:param model_param: Dictionary with model parameters for accuracy tuning
|
||||
model_param['min_FWM_inv']: Minimum FWM efficiency value to be considered for high density
|
||||
integration in dB
|
||||
model_param['n_grid']: Maximum Number of integration points to be used in each frequency slot of
|
||||
the spectrum
|
||||
model_param['n_grid_min']: Minimum Number of integration points to be used in each frequency
|
||||
slot of the spectrum
|
||||
model_param['f_array']: Frequencies at which evaluate GNLI, expressed in THz
|
||||
:return: GNLI: power spectral density in W/THz of the nonlinear interference at frequencies model_param['f_array']
|
||||
"""
|
||||
alpha_lin = a_db / 20.0 / np.log10(np.e) # Conversion in linear units 1/km
|
||||
min_FWM_inv = np.power(10, model_param['min_FWM_inv'] / 10) # Conversion in linear units
|
||||
n_grid = model_param['n_grid']
|
||||
n_grid_min = model_param['n_grid_min']
|
||||
f_array = model_param['f_array']
|
||||
fmax = (f_ch[-1] - (b_ch[-1] / 2.0)) - (f_ch[0] - (b_ch[0] / 2.0)) # Get frequency limit
|
||||
f2eval = np.max(np.diff(f_ch))
|
||||
Bopt = f2eval * Nch # Overall optical bandwidth [THz]
|
||||
min_step = f2eval / n_grid # Minimum integration step
|
||||
max_step = f2eval / n_grid_min # Maximum integration step
|
||||
f_dense_start = np.abs(
|
||||
np.sqrt(np.power(alpha_lin, 2) / (4.0 * np.power(np.pi, 4) * b2 * b2) * (min_FWM_inv - 1.0)) / f2eval)
|
||||
f_ind_eval = 0
|
||||
GNLI = np.full(f_array.size, np.nan) # Pre-allocate results
|
||||
for f in f_array: # Loop over f
|
||||
f_dense_low = f - f_dense_start
|
||||
f_dense_up = f + f_dense_start
|
||||
if f_dense_low < -fmax:
|
||||
f_dense_low = -fmax
|
||||
if f_dense_low == 0.0:
|
||||
f_dense_low = -min_step
|
||||
if f_dense_up == 0.0:
|
||||
f_dense_up = min_step
|
||||
if f_dense_up > fmax:
|
||||
f_dense_up = fmax
|
||||
f_dense_width = np.abs(f_dense_up - f_dense_low)
|
||||
n_grid_dense = np.ceil(f_dense_width / min_step)
|
||||
df = f_dense_width / n_grid_dense
|
||||
# Get non-uniformly spaced f1 array
|
||||
f1_array = get_freqarray(f, Bopt, fmax, max_step, f_dense_low, f_dense_up, df)
|
||||
G1 = raised_cosine_comb(f1_array, b_ch, roll_off, f_ch, power) # Get corresponding spectrum
|
||||
Gpart = np.zeros(f1_array.size) # Pre-allocate partial result for inner integral
|
||||
f_ind = 0
|
||||
for f1 in f1_array: # Loop over f1
|
||||
if f1 != f:
|
||||
f_lim = np.sqrt(np.power(alpha_lin, 2) / (4.0 * np.power(np.pi, 4) * b2 * b2) * (min_FWM_inv - 1.0)) / (
|
||||
f1 - f) + f
|
||||
f2_dense_up = np.maximum(f_lim, -f_lim)
|
||||
f2_dense_low = np.minimum(f_lim, -f_lim)
|
||||
if f2_dense_low == 0:
|
||||
f2_dense_low = -min_step
|
||||
if f2_dense_up == 0:
|
||||
f2_dense_up = min_step
|
||||
if f2_dense_low < -fmax:
|
||||
f2_dense_low = -fmax
|
||||
if f2_dense_up > fmax:
|
||||
f2_dense_up = fmax
|
||||
else:
|
||||
f2_dense_up = fmax
|
||||
f2_dense_low = -fmax
|
||||
f2_dense_width = np.abs(f2_dense_up - f2_dense_low)
|
||||
n2_grid_dense = np.ceil(f2_dense_width / min_step)
|
||||
df2 = f2_dense_width / n2_grid_dense
|
||||
# Get non-uniformly spaced f2 array
|
||||
f2_array = get_freqarray(f, Bopt, fmax, max_step, f2_dense_low, f2_dense_up, df2)
|
||||
f2_array = f2_array[f2_array >= f1] # Do not consider points below the bisector of quadrants I and III
|
||||
if f2_array.size > 0:
|
||||
G2 = raised_cosine_comb(f2_array, b_ch, roll_off, f_ch, power) # Get spectrum there
|
||||
f3_array = f1 + f2_array - f # Compute f3
|
||||
G3 = raised_cosine_comb(f3_array, b_ch, roll_off, f_ch, power) # Get spectrum over f3
|
||||
G = G2 * G3 * G1[f_ind]
|
||||
if np.count_nonzero(G):
|
||||
FWM_eff = fwm_eff(alpha_lin, Lspan, b2, (f1 - f) * (f2_array - f)) # Compute FWM efficiency
|
||||
Gpart[f_ind] = 2.0 * np.trapz(FWM_eff * G, f2_array) # Compute inner integral
|
||||
f_ind += 1
|
||||
# Compute outer integral. Nominal span loss already compensated
|
||||
GNLI[f_ind_eval] = 16.0 / 27.0 * gam * gam * np.trapz(Gpart, f1_array)
|
||||
f_ind_eval += 1 # Next frequency
|
||||
return GNLI # Return GNLI array in W/THz and the array of the corresponding frequencies
|
||||
|
||||
|
||||
def compute_psi(b2, l_eff_a, f_ch, channel_index, interfering_index, b_ch):
|
||||
""" compute_psi computes the psi coefficient of the analytical formula.
|
||||
|
||||
:param b2: Fiber dispersion coefficient in ps/THz/km. Scalar
|
||||
:param l_eff_a: Asymptotic effective length in km. Scalar
|
||||
:param f_ch: Baseband channels center frequencies in THz. Array of size 1xNch
|
||||
:param channel_index: Index of the channel. Scalar
|
||||
:param interfering_index: Index of the interfering signal. Scalar
|
||||
:param b_ch: Channels' -3 dB bandwidth [THz]. Array of size 1xNch
|
||||
:return: psi: the coefficient
|
||||
"""
|
||||
b2 = np.abs(b2)
|
||||
|
||||
if channel_index == interfering_index: # The signal interferes with itself
|
||||
b_ch_sig = b_ch[channel_index]
|
||||
psi = np.arcsinh(0.5 * np.pi ** 2.0 * l_eff_a * b2 * b_ch_sig ** 2.0)
|
||||
else:
|
||||
f_sig = f_ch[channel_index]
|
||||
b_ch_sig = b_ch[channel_index]
|
||||
f_int = f_ch[interfering_index]
|
||||
b_ch_int = b_ch[interfering_index]
|
||||
del_f = f_sig - f_int
|
||||
psi = np.arcsinh(np.pi ** 2.0 * l_eff_a * b2 * b_ch_sig * (del_f + 0.5 * b_ch_int))
|
||||
psi -= np.arcsinh(np.pi ** 2.0 * l_eff_a * b2 * b_ch_sig * (del_f - 0.5 * b_ch_int))
|
||||
|
||||
return psi
|
||||
|
||||
|
||||
def analytic_formula(ind, b2, l_eff, l_eff_a, gam, f_ch, g_ch, b_ch, n_ch):
|
||||
""" analytic_formula computes the analytical formula.
|
||||
|
||||
:param ind: index of the channel at which g_nli is computed. Scalar
|
||||
:param b2: Fiber dispersion coefficient in ps/THz/km. Scalar
|
||||
:param l_eff: Effective length in km. Scalar
|
||||
:param l_eff_a: Asymptotic effective length in km. Scalar
|
||||
:param gam: Fiber nonlinear coefficient in 1/W/km. Scalar
|
||||
:param f_ch: Baseband channels center frequencies in THz. Array of size 1xNch
|
||||
:param g_ch: Power spectral density W/THz. Array of size 1xNch
|
||||
:param b_ch: Channels' -3 dB bandwidth [THz]. Array of size 1xNch
|
||||
:param n_ch: Number of channels. Scalar
|
||||
:return: g_nli: power spectral density in W/THz of the nonlinear interference
|
||||
"""
|
||||
ch_psd = g_ch[ind]
|
||||
b2 = abs(b2)
|
||||
|
||||
g_nli = 0.0
|
||||
for n in np.arange(0, n_ch):
|
||||
psi = compute_psi(b2, l_eff_a, f_ch, ind, n, b_ch)
|
||||
g_nli += g_ch[n] * ch_psd ** 2.0 * psi
|
||||
|
||||
g_nli *= (16.0 / 27.0) * (gam * l_eff) ** 2.0 / (2.0 * np.pi * b2 * l_eff_a)
|
||||
|
||||
return g_nli
|
||||
|
||||
|
||||
def gn_analytic(b2, l_span, a_db, gam, f_ch, b_ch, power, n_ch):
|
||||
""" gn_analytic computes the GN reference formula via analytical solution.
|
||||
|
||||
:param b2: Fiber dispersion coefficient in ps/THz/km. Scalar
|
||||
:param l_span: Fiber Span length in km. Scalar
|
||||
:param a_db: Fiber loss coefficient in dB/km. Scalar
|
||||
:param gam: Fiber nonlinear coefficient in 1/W/km. Scalar
|
||||
:param f_ch: Baseband channels center frequencies in THz. Array of size 1xNch
|
||||
:param b_ch: Channels' -3 dB bandwidth [THz]. Array of size 1xNch
|
||||
:param power: Channels' power values in W. Array of size 1xNch
|
||||
:param n_ch: Number of channels. Scalar
|
||||
:return: g_nli: power spectral density in W/THz of the nonlinear interference at frequencies model_param['f_array']
|
||||
"""
|
||||
g_ch = power / b_ch
|
||||
alpha_lin = a_db / 20.0 / np.log10(np.e) # Conversion in linear units 1/km
|
||||
l_eff = (1.0 - np.exp(-2.0 * alpha_lin * l_span)) / (2.0 * alpha_lin) # Effective length
|
||||
l_eff_a = 1.0 / (2.0 * alpha_lin) # Asymptotic effective length
|
||||
g_nli = np.zeros(f_ch.size)
|
||||
for ind in np.arange(0, f_ch.size):
|
||||
g_nli[ind] = analytic_formula(ind, b2, l_eff, l_eff_a, gam, f_ch, g_ch, b_ch, n_ch)
|
||||
|
||||
return g_nli
|
||||
|
||||
|
||||
def get_f_computed_interp(f_ch, n_not_interp):
|
||||
""" get_f_computed_array returns the arrays containing the frequencies at which g_nli is computed and interpolated.
|
||||
|
||||
:param f_ch: the overall frequency array. Array of size 1xnum_ch
|
||||
:param n_not_interp: the number of points at which g_nli has to be computed
|
||||
:return: f_nli_comp: the array containing the frequencies at which g_nli is computed
|
||||
:return: f_nli_interp: the array containing the frequencies at which g_nli is interpolated
|
||||
"""
|
||||
num_ch = len(f_ch)
|
||||
if num_ch < n_not_interp: # It's useless to compute g_nli in a number of points larger than num_ch
|
||||
n_not_interp = num_ch
|
||||
|
||||
# Compute f_nli_comp
|
||||
n_not_interp_left = np.ceil((n_not_interp - 1.0) / 2.0)
|
||||
n_not_interp_right = np.floor((n_not_interp - 1.0) / 2.0)
|
||||
central_index = len(f_ch) // 2
|
||||
print(central_index)
|
||||
|
||||
f_nli_central = np.array([f_ch[central_index]], copy=True)
|
||||
|
||||
if n_not_interp_left > 0:
|
||||
index = np.linspace(0, central_index - 1, n_not_interp_left, dtype='int')
|
||||
f_nli_left = np.array(f_ch[index], copy=True)
|
||||
else:
|
||||
f_nli_left = np.array([])
|
||||
|
||||
if n_not_interp_right > 0:
|
||||
index = np.linspace(-1, -central_index, n_not_interp_right, dtype='int')
|
||||
f_nli_right = np.array(f_ch[index], copy=True)
|
||||
f_nli_right = f_nli_right[::-1] # Reverse the order of the array
|
||||
else:
|
||||
f_nli_right = np.array([])
|
||||
|
||||
f_nli_comp = np.concatenate([f_nli_left, f_nli_central, f_nli_right])
|
||||
|
||||
# Compute f_nli_interp
|
||||
f_ch_sorted = np.sort(f_ch)
|
||||
index = np.searchsorted(f_ch_sorted, f_nli_comp)
|
||||
|
||||
f_nli_interp = np.array(f_ch, copy=True)
|
||||
f_nli_interp = np.delete(f_nli_interp, index)
|
||||
return f_nli_comp, f_nli_interp
|
||||
|
||||
|
||||
def interpolate_in_range(x, y, x_new, kind_interp):
|
||||
""" Given some samples y of the function y(x), interpolate_in_range returns the interpolation of values y(x_new)
|
||||
|
||||
:param x: The points at which y(x) is evaluated. Array
|
||||
:param y: The values of y(x). Array
|
||||
:param x_new: The values at which y(x) has to be interpolated. Array
|
||||
:param kind_interp: The interpolation method of the function scipy.interpolate.interp1d. String
|
||||
:return: y_new: the new interpolates samples
|
||||
"""
|
||||
if x.size == 1:
|
||||
y_new = y * np.ones(x_new.size)
|
||||
elif x.size == 2:
|
||||
x = np.append(x, x_new[-1])
|
||||
y = np.append(y, y[-1])
|
||||
func = interp.interp1d(x, y, kind=kind_interp, bounds_error=False)
|
||||
y_new = func(x_new)
|
||||
else:
|
||||
func = interp.interp1d(x, y, kind=kind_interp, bounds_error=False)
|
||||
y_new = func(x_new)
|
||||
|
||||
return y_new
|
||||
|
||||
|
||||
def gn_model(spectrum_param, fiber_param, accuracy_param, n_cores):
|
||||
""" gn_model can compute the gn model both analytically or through the smart brute force
|
||||
integral.
|
||||
|
||||
:param spectrum_param: Dictionary with spectrum parameters
|
||||
spectrum_param['num_ch']: Number of channels. Scalar
|
||||
spectrum_param['f_ch']: Baseband channels center frequencies in THz. Array of size 1xnum_ch
|
||||
spectrum_param['b_ch']: Channels' -3 dB band [THz]. Array of size 1xnum_ch
|
||||
spectrum_param['roll_off']: Channels' Roll-off factors [0,1). Array of size 1xnum_ch
|
||||
spectrum_param['power']: Channels' power values in W. Array of size 1xnum_ch
|
||||
:param fiber_param: Dictionary with the parameters of the fiber
|
||||
fiber_param['alpha']: Fiber loss coefficient in dB/km. Scalar
|
||||
fiber_param['span_length']: Fiber Span length in km. Scalar
|
||||
fiber_param['beta_2']: Fiber dispersion coefficient in ps/THz/km. Scalar
|
||||
fiber_param['gamma']: Fiber nonlinear coefficient in 1/W/km. Scalar
|
||||
:param accuracy_param: Dictionary with model parameters for accuracy tuning
|
||||
accuracy_param['is_analytic']: A boolean indicating if you want to compute the NLI through
|
||||
the analytic formula (is_analytic = True) of the smart brute force integration (is_analytic =
|
||||
False). Boolean
|
||||
accuracy_param['points_not_interp']: The number of NLI which will be calculated. Others are
|
||||
interpolated
|
||||
accuracy_param['kind_interp']: The kind of interpolation using the function
|
||||
scipy.interpolate.interp1d
|
||||
accuracy_param['th_fwm']: Minimum FWM efficiency value to be considered for high density
|
||||
integration in dB
|
||||
accuracy_param['n_points']: Maximum Number of integration points to be used in each frequency
|
||||
slot of the spectrum
|
||||
accuracy_param['n_points_min']: Minimum Number of integration points to be used in each
|
||||
frequency
|
||||
slot of the spectrum
|
||||
:return: g_nli_comp: the NLI power spectral density in W/THz computed through GN model
|
||||
:return: f_nli_comp: the frequencies at which g_nli_comp is evaluated
|
||||
:return: g_nli_interp: the NLI power spectral density in W/THz computed through interpolation of g_nli_comp
|
||||
:return: f_nli_interp: the frequencies at which g_nli_interp is estimated
|
||||
"""
|
||||
# Take signal parameters
|
||||
num_ch = spectrum_param['num_ch']
|
||||
f_ch = spectrum_param['f_ch']
|
||||
b_ch = spectrum_param['b_ch']
|
||||
roll_off = spectrum_param['roll_off']
|
||||
power = spectrum_param['power']
|
||||
|
||||
# Take fiber parameters
|
||||
a_db = fiber_param['alpha']
|
||||
l_span = fiber_param['span_length']
|
||||
beta2 = fiber_param['beta_2']
|
||||
gam = fiber_param['gamma']
|
||||
|
||||
# Take accuracy parameters
|
||||
is_analytic = accuracy_param['is_analytic']
|
||||
n_not_interp = accuracy_param['points_not_interp']
|
||||
kind_interp = accuracy_param['kind_interp']
|
||||
th_fwm = accuracy_param['th_fwm']
|
||||
n_points = accuracy_param['n_points']
|
||||
n_points_min = accuracy_param['n_points_min']
|
||||
|
||||
# Computing NLI
|
||||
if is_analytic: # Analytic solution
|
||||
g_nli_comp = gn_analytic(beta2, l_span, a_db, gam, f_ch, b_ch, power, num_ch)
|
||||
f_nli_comp = np.copy(f_ch)
|
||||
g_nli_interp = []
|
||||
f_nli_interp = []
|
||||
else: # Smart brute force integration
|
||||
f_nli_comp, f_nli_interp = get_f_computed_interp(f_ch, n_not_interp)
|
||||
|
||||
model_param = {'min_FWM_inv': th_fwm, 'n_grid': n_points, 'n_grid_min': n_points_min,
|
||||
'f_array': np.array(f_nli_comp, copy=True)}
|
||||
|
||||
g_nli_comp = GN_integral(beta2, l_span, a_db, gam, f_ch, b_ch, roll_off, power, num_ch, model_param)
|
||||
|
||||
# Interpolation
|
||||
g_nli_interp = interpolate_in_range(f_nli_comp, g_nli_comp, f_nli_interp, kind_interp)
|
||||
|
||||
a_zero = fiber_param['alpha'] * fiber_param['span_length']
|
||||
a_tilting = fiber_param['alpha_1st'] * fiber_param['span_length']
|
||||
|
||||
attenuation_db_comp = compute_attenuation_profile(a_zero, a_tilting, f_nli_comp)
|
||||
attenuation_lin_comp = 10 ** (-abs(attenuation_db_comp) / 10)
|
||||
|
||||
g_nli_comp *= attenuation_lin_comp
|
||||
|
||||
attenuation_db_interp = compute_attenuation_profile(a_zero, a_tilting, f_nli_interp)
|
||||
attenuation_lin_interp = 10 ** (-np.abs(attenuation_db_interp) / 10)
|
||||
|
||||
g_nli_interp *= attenuation_lin_interp
|
||||
|
||||
return g_nli_comp, f_nli_comp, g_nli_interp, f_nli_interp
|
||||
|
||||
|
||||
def compute_gain_profile(gain_zero, gain_tilting, freq):
|
||||
""" compute_gain_profile evaluates the gain at the frequencies freq.
|
||||
|
||||
:param gain_zero: the gain at f=0 in dB. Scalar
|
||||
:param gain_tilting: the gain tilt in dB/THz. Scalar
|
||||
:param freq: the baseband frequencies at which the gain profile is computed in THz. Array
|
||||
:return: gain: the gain profile in dB
|
||||
"""
|
||||
gain = gain_zero + gain_tilting * freq
|
||||
return gain
|
||||
|
||||
|
||||
def compute_ase_noise(noise_fig, gain, central_freq, freq):
|
||||
""" compute_ase_noise evaluates the ASE spectral density at the frequencies freq.
|
||||
|
||||
:param noise_fig: the amplifier noise figure in dB. Scalar
|
||||
:param gain: the gain profile in dB at the frequencies contained in freq array. Array
|
||||
:param central_freq: the central frequency of the WDM comb. Scalar
|
||||
:param freq: the baseband frequencies at which the ASE noise is computed in THz. Array
|
||||
:return: g_ase: the ase noise profile
|
||||
"""
|
||||
# the Planck constant in W/THz^2
|
||||
planck = (6.62607004 * 1e-34) * 1e24
|
||||
|
||||
# Conversion from dB to linear
|
||||
gain_lin = np.power(10, gain / 10.0)
|
||||
noise_fig_lin = np.power(10, noise_fig / 10.0)
|
||||
|
||||
g_ase = (gain_lin - 1) * noise_fig_lin * planck * (central_freq + freq)
|
||||
return g_ase
|
||||
|
||||
|
||||
def compute_edfa_profile(gain_zero, gain_tilting, noise_fig, central_freq, freq):
|
||||
""" compute_edfa_profile evaluates the gain profile and the ASE spectral density at the frequencies freq.
|
||||
|
||||
:param gain_zero: the gain at f=0 in dB. Scalar
|
||||
:param gain_tilting: the gain tilt in dB/THz. Scalar
|
||||
:param noise_fig: the amplifier noise figure in dB. Scalar
|
||||
:param central_freq: the central frequency of the WDM comb. Scalar
|
||||
:param freq: the baseband frequencies at which the ASE noise is computed in THz. Array
|
||||
:return: gain: the gain profile in dB
|
||||
:return: g_ase: the ase noise profile in W/THz
|
||||
"""
|
||||
gain = compute_gain_profile(gain_zero, gain_tilting, freq)
|
||||
g_ase = compute_ase_noise(noise_fig, gain, central_freq, freq)
|
||||
|
||||
return gain, g_ase
|
||||
|
||||
|
||||
def compute_attenuation_profile(a_zero, a_tilting, freq):
|
||||
"""compute_attenuation_profile returns the attenuation profile at the frequencies freq
|
||||
|
||||
:param a_zero: the attenuation [dB] @ the baseband central frequency. Scalar
|
||||
:param a_tilting: the attenuation tilt in dB/THz. Scalar
|
||||
:param freq: the baseband frequencies at which attenuation is computed [THz]. Array
|
||||
:return: attenuation: the attenuation profile in dB
|
||||
"""
|
||||
|
||||
if len(freq):
|
||||
attenuation = a_zero + a_tilting * freq
|
||||
|
||||
# abs in order to avoid ambiguity due to the sign convention
|
||||
attenuation = abs(attenuation)
|
||||
else:
|
||||
attenuation = []
|
||||
|
||||
return attenuation
|
||||
|
||||
|
||||
def passive_component(spectrum, a_zero, a_tilting, freq):
|
||||
"""passive_component updates the input spectrum with the attenuation described by a_zero and a_tilting
|
||||
|
||||
:param spectrum: the WDM spectrum to be attenuated. List of dictionaries
|
||||
:param a_zero: attenuation at the central frequency [dB]. Scalar
|
||||
:param a_tilting: attenuation tilting [dB/THz]. Scalar
|
||||
:param freq: the baseband frequency of each WDM channel [THz]. Array
|
||||
:return: None
|
||||
"""
|
||||
attenuation_db = compute_attenuation_profile(a_zero, a_tilting, freq)
|
||||
attenuation_lin = 10 ** np.divide(-abs(attenuation_db), 10.0)
|
||||
|
||||
for index, s in enumerate(spectrum['signals']):
|
||||
spectrum['signals'][index]['p_ch'] *= attenuation_lin[index]
|
||||
spectrum['signals'][index]['p_nli'] *= attenuation_lin[index]
|
||||
spectrum['signals'][index]['p_ase'] *= attenuation_lin[index]
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def optical_amplifier(spectrum, gain_zero, gain_tilting, noise_fig, central_freq, freq, b_eq):
|
||||
"""optical_amplifier updates the input spectrum with the gain described by gain_zero and gain_tilting plus ASE noise
|
||||
|
||||
:param spectrum: the WDM spectrum to be attenuated. List of dictionaries
|
||||
:param gain_zero: gain at the central frequency [dB]. Scalar
|
||||
:param gain_tilting: gain tilting [dB/THz]. Scalar
|
||||
:param noise_fig: the noise figure of the amplifier [dB]. Scalar
|
||||
:param central_freq: the central frequency of the optical band [THz]. Scalar
|
||||
:param freq: the central frequency of each WDM channel [THz]. Array
|
||||
:param b_eq: the equivalent -3 dB bandwidth of each WDM channel [THZ]. Array
|
||||
:return: None
|
||||
"""
|
||||
|
||||
gain_db, g_ase = compute_edfa_profile(gain_zero, gain_tilting, noise_fig, central_freq, freq)
|
||||
|
||||
p_ase = np.multiply(g_ase, b_eq)
|
||||
|
||||
gain_lin = 10 ** np.divide(gain_db, 10.0)
|
||||
|
||||
for index, s in enumerate(spectrum['signals']):
|
||||
spectrum['signals'][index]['p_ch'] *= gain_lin[index]
|
||||
spectrum['signals'][index]['p_nli'] *= gain_lin[index]
|
||||
spectrum['signals'][index]['p_ase'] *= gain_lin[index]
|
||||
spectrum['signals'][index]['p_ase'] += p_ase[index]
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def fiber(spectrum, fiber_param, fiber_length, f_ch, b_ch, roll_off, control_param):
|
||||
""" fiber updates spectrum with the effects of the fiber
|
||||
|
||||
:param spectrum: the WDM spectrum to be attenuated. List of dictionaries
|
||||
:param fiber_param: Dictionary with the parameters of the fiber
|
||||
fiber_param['alpha']: Fiber loss coeffiecient in dB/km. Scalar
|
||||
fiber_param['beta_2']: Fiber dispersion coefficient in ps/THz/km. Scalar
|
||||
fiber_param['n_2']: second-order nonlinear refractive index [m^2/W]. Scalar
|
||||
fiber_param['a_eff']: the effective area of the fiber [um^2]. Scalar
|
||||
:param fiber_length: the span length [km]. Scalar
|
||||
:param f_ch: the baseband frequencies of the WDM channels [THz]. Scalar
|
||||
:param b_ch: the -3 dB bandwidth of each WDM channel [THz]. Array
|
||||
:param roll_off: the roll off of each WDM channel. Array
|
||||
:param control_param: Dictionary with the control parameters
|
||||
control_param['save_each_comp']: a boolean flag. If true, it saves in output folder one spectrum file at
|
||||
the output of each component, otherwise it saves just the last spectrum. Boolean
|
||||
control_param['is_linear']: a bool flag. If true, is doesn't compute NLI, if false, OLE will consider
|
||||
NLI. Boolean
|
||||
control_param['is_analytic']: a boolean flag. If true, the NLI is computed through the analytic
|
||||
formula, otherwise it uses the double integral. Warning: the double integral is very slow. Boolean
|
||||
control_param['points_not_interp']: if the double integral is used, it indicates how much points are
|
||||
calculated, others will be interpolated. Scalar
|
||||
control_param['kind_interp']: the interpolation method when double integral is used. String
|
||||
control_param['th_fwm']: he threshold of the four wave mixing efficiency for the double integral. Scalar
|
||||
control_param['n_points']: number of points in the high FWM efficiency region in which the double
|
||||
integral is computed. Scalar
|
||||
control_param['n_points_min']: number of points in which the double integral is computed in the low FWM
|
||||
efficiency region. Scalar
|
||||
control_param['n_cores']: number of cores for parallel computation [not yet implemented]. Scalar
|
||||
:return: None
|
||||
"""
|
||||
|
||||
n_cores = control_param['n_cores']
|
||||
|
||||
# Evaluation of NLI
|
||||
if not control_param['is_linear']:
|
||||
num_ch = len(spectrum['signals'])
|
||||
spectrum_param = {
|
||||
'num_ch': num_ch,
|
||||
'f_ch': f_ch,
|
||||
'b_ch': b_ch,
|
||||
'roll_off': roll_off
|
||||
}
|
||||
|
||||
p_ch = np.zeros(num_ch)
|
||||
for index, signal in enumerate(spectrum['signals']):
|
||||
p_ch[index] = signal['p_ch']
|
||||
|
||||
spectrum_param['power'] = p_ch
|
||||
fiber_param['span_length'] = fiber_length
|
||||
|
||||
nli_cmp, f_nli_cmp, nli_int, f_nli_int = gn_model(spectrum_param, fiber_param, control_param, n_cores)
|
||||
f_nli = np.concatenate((f_nli_cmp, f_nli_int))
|
||||
order = np.argsort(f_nli)
|
||||
g_nli = np.concatenate((nli_cmp, nli_int))
|
||||
g_nli = np.array(g_nli)[order]
|
||||
|
||||
p_nli = np.multiply(g_nli, b_ch)
|
||||
|
||||
a_zero = fiber_param['alpha'] * fiber_length
|
||||
a_tilting = fiber_param['alpha_1st'] * fiber_length
|
||||
|
||||
# Apply attenuation
|
||||
passive_component(spectrum, a_zero, a_tilting, f_ch)
|
||||
|
||||
# Apply NLI
|
||||
if not control_param['is_linear']:
|
||||
for index, s in enumerate(spectrum['signals']):
|
||||
spectrum['signals'][index]['p_nli'] += p_nli[index]
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def get_frequencies_wdm(spectrum, sys_param):
|
||||
""" the function computes the central frequency of the WDM comb and the frequency of each channel.
|
||||
|
||||
:param spectrum: the WDM spectrum to be attenuated. List of dictionaries
|
||||
:param sys_param: a dictionary containing the system parameters:
|
||||
'f0': the starting frequency, i.e the frequency of the first spectral slot [THz]
|
||||
'ns': the number of spectral slots. The space between two slots is 6.25 GHz
|
||||
:return: f_cent: the central frequency of the WDM comb [THz]
|
||||
:return: f_ch: the baseband frequency of each WDM channel [THz]
|
||||
"""
|
||||
|
||||
delta_f = 6.25E-3
|
||||
# Evaluate the central frequency
|
||||
f0 = sys_param['f0']
|
||||
ns = sys_param['ns']
|
||||
|
||||
f_cent = f0 + ((ns // 2.0) * delta_f)
|
||||
|
||||
# Evaluate the baseband frequencies
|
||||
n_ch = spectrum['laser_position'].count(1)
|
||||
f_ch = np.zeros(n_ch)
|
||||
count = 0
|
||||
for index, bool_laser in enumerate(spectrum['laser_position']):
|
||||
if bool_laser:
|
||||
f_ch[count] = (f0 - f_cent) + delta_f * index
|
||||
count += 1
|
||||
|
||||
return f_cent, f_ch
|
||||
|
||||
|
||||
def get_spectrum_param(spectrum):
|
||||
""" the function returns the number of WDM channels and 3 arrays containing the power, the equivalent bandwidth
|
||||
and the roll off of each WDM channel.
|
||||
|
||||
:param spectrum: the WDM spectrum to be attenuated. List of dictionaries
|
||||
:return: power: the power of each WDM channel [W]
|
||||
:return: b_eq: the equivalent bandwidth of each WDM channel [THz]
|
||||
:return: roll_off: the roll off of each WDM channel
|
||||
:return: p_ase: the power of the ASE noise [W]
|
||||
:return: p_nli: the power of NLI [W]
|
||||
:return: n_ch: the number of WDM channels
|
||||
"""
|
||||
|
||||
n_ch = spectrum['laser_position'].count(1)
|
||||
roll_off = np.zeros(n_ch)
|
||||
b_eq = np.zeros(n_ch)
|
||||
power = np.zeros(n_ch)
|
||||
p_ase = np.zeros(n_ch)
|
||||
p_nli = np.zeros(n_ch)
|
||||
for index, signal in enumerate(spectrum['signals']):
|
||||
b_eq[index] = signal['b_ch']
|
||||
roll_off[index] = signal['roll_off']
|
||||
power[index] = signal['p_ch']
|
||||
p_ase[index] = signal['p_ase']
|
||||
p_nli[index] = signal['p_nli']
|
||||
|
||||
return power, b_eq, roll_off, p_ase, p_nli, n_ch
|
||||
|
||||
|
||||
def change_component_ref(f_ref, link, fibers):
|
||||
""" it updates the reference frequency of OA gain, PC attenuation and fiber attenuation coefficient
|
||||
|
||||
:param f_ref: the new reference frequency [THz]. Scalar
|
||||
:param link: the link structure. A list in which each element indicates one link component (PC, OA or fiber). List
|
||||
:param fibers: a dictionary containing the description of each fiber type. Dictionary
|
||||
:return: None
|
||||
"""
|
||||
|
||||
light_speed = 3e8 # [m/s]
|
||||
|
||||
# Change reference to the central frequency f_cent for OA and PC
|
||||
for index, component in enumerate(link):
|
||||
if component['comp_cat'] is 'PC':
|
||||
|
||||
old_loss = component['loss']
|
||||
delta_loss = component['loss_tlt']
|
||||
old_ref = component['ref_freq']
|
||||
new_loss = old_loss + delta_loss * (f_ref - old_ref)
|
||||
|
||||
link[index]['ref_freq'] = f_ref
|
||||
link[index]['loss'] = new_loss
|
||||
|
||||
elif component['comp_cat'] is 'OA':
|
||||
|
||||
old_gain = component['gain']
|
||||
delta_gain = component['gain_tlt']
|
||||
old_ref = component['ref_freq']
|
||||
new_gain = old_gain + delta_gain * (f_ref - old_ref)
|
||||
|
||||
link[index]['ref_freq'] = f_ref
|
||||
link[index]['gain'] = new_gain
|
||||
|
||||
elif not component['comp_cat'] is 'fiber':
|
||||
|
||||
error_string = 'Error in link structure: the ' + str(index+1) + '-th component have unknown category \n'\
|
||||
+ 'allowed values are (case sensitive): PC, OA and fiber'
|
||||
print(error_string)
|
||||
|
||||
# Change reference to the central frequency f_cent for fiber
|
||||
for fib_type in fibers:
|
||||
old_ref = fibers[fib_type]['reference_frequency']
|
||||
old_alpha = fibers[fib_type]['alpha']
|
||||
alpha_1st = fibers[fib_type]['alpha_1st']
|
||||
new_alpha = old_alpha + alpha_1st * (f_ref - old_ref)
|
||||
|
||||
fibers[fib_type]['reference_frequency'] = f_ref
|
||||
fibers[fib_type]['alpha'] = new_alpha
|
||||
|
||||
fibers[fib_type]['gamma'] = (2 * np.pi) * (f_ref / light_speed) * \
|
||||
(fibers[fib_type]['n_2'] / fibers[fib_type]['a_eff']) * 1e27
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def compute_and_save_osnr(spectrum, flag_save=False, file_name='00', output_path='./output/'):
|
||||
""" Given the spectrum structure, the function returns the linear and non linear OSNR. If the boolean variable
|
||||
flag_save is true, the function also saves the osnr values for the central channel, the osnr for each channel and
|
||||
spectrum in a file with the name file_name, in the folder indicated by output_path
|
||||
|
||||
:param spectrum: the spectrum dictionary containing the laser position (a list of boolean) and the list signals,
|
||||
which is a list of dictionaries (one for each channel) containing:
|
||||
'b_ch': the -3 dB bandwidth of the signal [THz]
|
||||
'roll_off': the roll off of the signal
|
||||
'p_ch': the signal power [W]
|
||||
'p_nli': the equivalent nli power [W]
|
||||
'p_ase': the ASE noise [W]
|
||||
:param flag_save: if True it saves all the data, otherwise it doesn't
|
||||
:param file_name: the name of the file in which the variables are saved
|
||||
:param output_path: the path in which you want to save the file
|
||||
:return: osnr_lin_db: the linear OSNR [dB]
|
||||
:return: osnr_nli_db: the non-linear equivalent OSNR (in linear units, NOT in [dB]
|
||||
"""
|
||||
|
||||
# Get the parameters from spectrum
|
||||
p_ch, b_eq, roll_off, p_ase, p_nli, n_ch = get_spectrum_param(spectrum)
|
||||
|
||||
# Compute the linear OSNR
|
||||
if (p_ase == 0).any():
|
||||
osnr_lin = np.zeros(n_ch)
|
||||
for index, p_noise in enumerate(p_ase):
|
||||
if p_noise == 0:
|
||||
osnr_lin[index] = float('inf')
|
||||
else:
|
||||
osnr_lin[index] = p_ch[index] / p_noise
|
||||
|
||||
else:
|
||||
osnr_lin = np.divide(p_ch, p_ase)
|
||||
|
||||
# Compute the non-linear OSNR
|
||||
if ((p_ase + p_nli) == 0).any():
|
||||
osnr_nli = np.zeros(n_ch)
|
||||
for index, p_noise in enumerate(p_ase + p_nli):
|
||||
|
||||
if p_noise == 0:
|
||||
osnr_nli[index] = float('inf')
|
||||
else:
|
||||
osnr_nli[index] = p_ch[index] / p_noise
|
||||
else:
|
||||
osnr_nli = np.divide(p_ch, p_ase + p_nli)
|
||||
|
||||
# Compute linear and non linear OSNR for the central channel
|
||||
ind_c = n_ch // 2
|
||||
osnr_lin_central_channel_db = 10 * np.log10(osnr_lin[ind_c])
|
||||
osnr_nl_central_channel_db = 10 * np.log10(osnr_nli[ind_c])
|
||||
|
||||
# Conversion in dB
|
||||
osnr_lin_db = 10 * np.log10(osnr_lin)
|
||||
osnr_nli_db = 10 * np.log10(osnr_nli)
|
||||
|
||||
# Save spectrum, the non linear OSNR and the linear OSNR
|
||||
out_fle_name = output_path + file_name
|
||||
|
||||
if flag_save:
|
||||
|
||||
f = open(out_fle_name, 'w')
|
||||
f.write(''.join(('# Output parameters. The values of OSNR are evaluated in the -3 dB channel band', '\n\n')))
|
||||
f.write(''.join(('osnr_lin_central_channel_db = ', str(osnr_lin_central_channel_db), '\n\n')))
|
||||
f.write(''.join(('osnr_nl_central_channel_db = ', str(osnr_nl_central_channel_db), '\n\n')))
|
||||
f.write(''.join(('osnr_lin_db = ', str(osnr_lin_db), '\n\n')))
|
||||
f.write(''.join(('osnr_nl_db = ', str(osnr_nli_db), '\n\n')))
|
||||
f.write(''.join(('spectrum = ', str(spectrum), '\n')))
|
||||
|
||||
f.close()
|
||||
|
||||
return osnr_nli_db, osnr_lin_db
|
||||
|
||||
|
||||
def ole(spectrum, link, fibers, sys_param, control_param, output_path='./output/'):
|
||||
""" The function takes the input spectrum, the link description, the fiber description, the system parameters,
|
||||
the control parameters and a string describing the destination folder of the output files. After the function is
|
||||
executed the spectrum is updated with all the impairments of the link. The function also returns the linear and
|
||||
non linear OSNR, computed in the equivalent bandwidth.
|
||||
|
||||
:param spectrum: the spectrum dictionary containing the laser position (a list of boolean) and the list signals,
|
||||
which is a list of dictionaries (one for each channel) containing:
|
||||
'b_ch': the -3 dB bandwidth of the signal [THz]
|
||||
'roll_off': the roll off of the signal
|
||||
'p_ch': the signal power [W]
|
||||
'p_nli': the equivalent nli power [W]
|
||||
'p_ase': the ASE noise [W]
|
||||
:param link: the link structure. A list in which each element is a dictionary and it indicates one link component
|
||||
(PC, OA or fiber). List
|
||||
:param fibers: fibers is a dictionary containing a dictionary for each kind of fiber. Each dictionary has to report:
|
||||
reference_frequency: the frequency at which the parameters are evaluated [THz]
|
||||
alpha: the attenuation coefficient [dB/km]
|
||||
alpha_1st: the first derivative of alpha indicating the alpha slope [dB/km/THz]
|
||||
if you assume a flat attenuation with respect to the frequency you put it as zero
|
||||
beta_2: the dispersion coefficient [ps^2/km]
|
||||
n_2: second-order nonlinear refractive index [m^2/W]
|
||||
a typical value is 2.5E-20 m^2/W
|
||||
a_eff: the effective area of the fiber [um^2]
|
||||
:param sys_param: a dictionary containing the general system parameters:
|
||||
f0: the starting frequency of the laser grid used to describe the WDM system
|
||||
ns: the number of 6.25 GHz slots in the grid
|
||||
:param control_param: a dictionary containing the following parameters:
|
||||
save_each_comp: a boolean flag. If true, it saves in output folder one spectrum file at the output of each
|
||||
component, otherwise it saves just the last spectrum
|
||||
is_linear: a bool flag. If true, is doesn't compute NLI, if false, OLE will consider NLI
|
||||
is_analytic: a boolean flag. If true, the NLI is computed through the analytic formula, otherwise it uses
|
||||
the double integral. Warning: the double integral is very slow.
|
||||
points_not_interp: if the double integral is used, it indicates how much points are calculated, others will
|
||||
be interpolated
|
||||
kind_interp: a string indicating the interpolation method for the double integral
|
||||
th_fwm: the threshold of the four wave mixing efficiency for the double integral
|
||||
n_points: number of points in which the double integral is computed in the high FWM efficiency region
|
||||
n_points_min: number of points in which the double integral is computed in the low FWM efficiency region
|
||||
n_cores: number of cores for parallel computation [not yet implemented]
|
||||
:param output_path: the path in which the output files are saved. String
|
||||
:return: osnr_nli_db: an array containing the non-linear OSNR [dB], one value for each WDM channel. Array
|
||||
:return: osnr_lin_db: an array containing the linear OSNR [dB], one value for each WDM channel. Array
|
||||
"""
|
||||
|
||||
# Take control parameters
|
||||
flag_save_each_comp = control_param['save_each_comp']
|
||||
|
||||
# Evaluate frequency parameters
|
||||
f_cent, f_ch = get_frequencies_wdm(spectrum, sys_param)
|
||||
|
||||
# Evaluate spectrum parameters
|
||||
power, b_eq, roll_off, p_ase, p_nli, n_ch = get_spectrum_param(spectrum)
|
||||
|
||||
# Change reference to the central frequency f_cent for OA, PC and fibers
|
||||
change_component_ref(f_cent, link, fibers)
|
||||
|
||||
# Emulate the link
|
||||
for component in link:
|
||||
if component['comp_cat'] is 'PC':
|
||||
a_zero = component['loss']
|
||||
a_tilting = component['loss_tlt']
|
||||
|
||||
passive_component(spectrum, a_zero, a_tilting, f_ch)
|
||||
|
||||
elif component['comp_cat'] is 'OA':
|
||||
gain_zero = component['gain']
|
||||
gain_tilting = component['gain_tlt']
|
||||
noise_fig = component['noise_figure']
|
||||
|
||||
optical_amplifier(spectrum, gain_zero, gain_tilting, noise_fig, f_cent, f_ch, b_eq)
|
||||
|
||||
elif component['comp_cat'] is 'fiber':
|
||||
fiber_type = component['fiber_type']
|
||||
fiber_param = fibers[fiber_type]
|
||||
fiber_length = component['length']
|
||||
|
||||
fiber(spectrum, fiber_param, fiber_length, f_ch, b_eq, roll_off, control_param)
|
||||
|
||||
else:
|
||||
error_string = 'Error in link structure: the ' + component['comp_cat'] + ' category is unknown \n' \
|
||||
+ 'allowed values are (case sensitive): PC, OA and fiber'
|
||||
print(error_string)
|
||||
|
||||
if flag_save_each_comp:
|
||||
f_name = 'Output from component ID #' + component['comp_id']
|
||||
osnr_nli_db, osnr_lin_db = \
|
||||
compute_and_save_osnr(spectrum, flag_save=True, file_name=f_name, output_path=output_path)
|
||||
|
||||
osnr_nli_db, osnr_lin_db = \
|
||||
compute_and_save_osnr(spectrum, flag_save=True, file_name='link_output', output_path=output_path)
|
||||
|
||||
return osnr_nli_db, osnr_lin_db
|
||||
@@ -1,29 +0,0 @@
|
||||
# coding=utf-8
|
||||
""" spectrum_in.py describes the input spectrum of OLE, i.e. spectrum.
|
||||
spectrum is a dictionary containing two fields:
|
||||
laser_position: a list of bool indicating if a laser is turned on or not
|
||||
signals: a list of dictionaries each of them, describing one channel in the WDM comb
|
||||
|
||||
The laser_position is defined respect to a frequency grid of 6.25 GHz space and the first slot is at the
|
||||
frequency described by the variable f0 in the dictionary sys_param in the file "general_parameters.py"
|
||||
|
||||
Each dictionary element of the list 'signals' describes the profile of a WDM channel:
|
||||
b_ch: the -3 dB channel bandwidth (for a root raised cosine, it is equal to the symbol rate)
|
||||
roll_off: the roll off parameter of the root raised cosine shape
|
||||
p_ch: the channel power [W]
|
||||
p_nli: power of accumulated NLI in b_ch [W]
|
||||
p_ase: power of accumulated ASE noise in b_ch [W]
|
||||
"""
|
||||
|
||||
n_ch = 41
|
||||
|
||||
spectrum = {
|
||||
'laser_position': [0, 0, 0, 1, 0, 0, 0, 0] * n_ch,
|
||||
'signals': [{
|
||||
'b_ch': 0.032,
|
||||
'roll_off': 0.15,
|
||||
'p_ch': 1E-3,
|
||||
'p_nli': 0,
|
||||
'p_ase': 0
|
||||
} for _ in range(n_ch)]
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user