mirror of
				https://github.com/Telecominfraproject/oopt-gnpy.git
				synced 2025-10-31 01:57:54 +00:00 
			
		
		
		
	Compare commits
	
		
			10 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 7ce6650109 | ||
|   | 252e67a71e | ||
|   | f83869392b | ||
|   | 94a3714aba | ||
|   | ccab4835fc | ||
|   | e55f7a5d4c | ||
|   | 4fda8c6002 | ||
|   | 8717156712 | ||
|   | d2c0836164 | ||
|   | eac4ba80ea | 
| @@ -1,18 +1,19 @@ | ||||
| ********************************************* | ||||
| .. _amp_models: | ||||
| 
 | ||||
| Amplifier models and configuration | ||||
| ********************************************* | ||||
| ================================== | ||||
| 
 | ||||
| 
 | ||||
| 1. Equipment configuration description | ||||
| ####################################### | ||||
| -------------------------------------- | ||||
| 
 | ||||
| Equipment description defines equipment types and parameters. | ||||
| It takes place in the default **eqpt_config.json** file.  | ||||
| It takes place in the equipment library such as **eqpt_config.json** file defined in example-data folder. | ||||
| By default **gnpy-transmission-example** uses **eqpt_config.json** file and that | ||||
| can be changed with **-e** or **--equipment** command line parameter. | ||||
| 
 | ||||
| 2. Amplifier parameters and subtypes | ||||
| ####################################### | ||||
| ------------------------------------ | ||||
| 
 | ||||
| Several amplifiers can be used by GNpy, so they are defined as an array of equipment parameters in **eqpt_config.json** file. | ||||
| 
 | ||||
| @@ -28,9 +29,16 @@ Several amplifiers can be used by GNpy, so they are defined as an array of equip | ||||
|     - *"variable_gain"* | ||||
|     - *"fixed_gain"* | ||||
|     - *"dual_stage"* | ||||
|     - *"multi_band"* | ||||
|     - *"openroadm"* | ||||
|         *see next section for a full description of these models* | ||||
| 
 | ||||
| 
 | ||||
| - *"default_config_from_json"*: | ||||
|     Use a custom per frequency dynamic gain tilt, gain and noise ripple arrays defined in the file specified with | ||||
|     this option, instead of the default values from GNPy. | ||||
| 
 | ||||
| 
 | ||||
| - *"advanced_config_from_json"*: | ||||
|     **This parameter is only applicable to the _"advanced_model"_ model** | ||||
|      | ||||
| @@ -135,7 +143,7 @@ Several amplifiers can be used by GNpy, so they are defined as an array of equip | ||||
| 
 | ||||
| 
 | ||||
| 3. Amplifier models | ||||
| ####################################### | ||||
| ------------------- | ||||
| 
 | ||||
| In an opensource and multi-vendor environnement, it is needed to support different use cases and context. Therefore several models are supported for amplifiers. | ||||
| 
 | ||||
| @@ -179,7 +187,7 @@ In an opensource and multi-vendor environnement, it is needed to support differe | ||||
| - *"variable_gain"*  | ||||
|     This model is refered as an operator model because a lower level of knowledge is required. A full polynomial description of the NF cross the gain range is not required. Instead, NF_min and NF_max values are required and used by the code to model a dual stage amplifier with an internal mid stage VOA. NF_min and NF_max values are typically available from equipment suppliers data-sheet. | ||||
| 
 | ||||
|     There is a default JSON file ”default_edfa_config.json”* to enforce 0 tilt and ripple values because GNpy core algorithm is a multi-carrier propogation. | ||||
|     There is a default configuration to enforce 0 tilt and ripple values because GNPy core algorithm is a multi-carrier propagation. | ||||
|     - gain_ripple =[0,...,0] | ||||
|     - nf_ripple = [0,...,0] | ||||
|     - dgt = [...] generic dgt comb | ||||
| @@ -250,7 +258,7 @@ In an opensource and multi-vendor environnement, it is needed to support differe | ||||
|      | ||||
|     - gain_min indicates to auto_design when this dual_stage should be used | ||||
|      | ||||
|     But unlike other models the 1st stage input will not be padded: it is always operated to its maximu gain and min NF. Therefore if gain adaptation and padding is needed it will be performed by the 2nd stage. | ||||
|     But unlike other models the 1st stage input will not be padded: it is always operated to its maximum gain and min NF. Therefore if gain adaptation and padding is needed it will be performed by the 2nd stage. | ||||
| 
 | ||||
|     .. code-block:: json | ||||
| 
 | ||||
| @@ -263,8 +271,18 @@ In an opensource and multi-vendor environnement, it is needed to support differe | ||||
|                 "allowed_for_design": true | ||||
|                 } | ||||
| 
 | ||||
| 
 | ||||
| - *"multiband"* | ||||
|     This model enables the definition of multiband amplifiers that consist of multiple single-band | ||||
|     amplifier elements, with each amplifier responsible for amplifying a different portion of the spectrum. | ||||
|     The types of single-band amplifiers that can be included in these multiband amplifiers are specified, | ||||
|     allowing for multiple options to be available for the same spectrum band (for instance, providing | ||||
|     several permitted type varieties for both the C-band and the L-band). The actual element utilizing the | ||||
|     type_variety must implement only one option for each band. | ||||
| 
 | ||||
| 
 | ||||
| 4. advanced_config_from_json  | ||||
| ####################################### | ||||
| ---------------------------- | ||||
| 
 | ||||
| The build_oa_json.py library in ``gnpy/example-data/edfa_model/`` can be used to build the json file required for the amplifier advanced_model type_def: | ||||
| 
 | ||||
							
								
								
									
										162
									
								
								docs/biblio.bib
									
									
									
									
									
								
							
							
						
						
									
										162
									
								
								docs/biblio.bib
									
									
									
									
									
								
							| @@ -1860,3 +1860,165 @@ month={Sept},} | ||||
|   pages={3499-3511}, | ||||
|   doi={10.1109/JLT.2022.3162134} | ||||
| } | ||||
|  | ||||
| @inproceedings{grammel2018physical, | ||||
|   title={Physical simulation environment of the telecommunications infrastructure project (TIP)}, | ||||
|   author={Grammel, Gert and Curri, Vittorio and Auge, Jean-Luc}, | ||||
|   booktitle={Optical Fiber Communication Conference}, | ||||
|   pages={M1D--3}, | ||||
|   year={2018}, | ||||
|   organization={Optica Publishing Group} | ||||
| } | ||||
|  | ||||
| @inproceedings{taylor2018towards, | ||||
|   title={Towards a route planning tool for open optical networks in the telecom infrastructure project}, | ||||
|   author={Taylor, Brian D and Goldfarb, Gilad and Bandyopadhyay, Saumil and Curri, Vittorio and Schmidtke, Hans-Juergen}, | ||||
|   booktitle={Optical Fiber Communication Conference}, | ||||
|   pages={Tu3E--4}, | ||||
|   year={2018}, | ||||
|   organization={Optica Publishing Group} | ||||
| } | ||||
|  | ||||
| @article{filer2018multi, | ||||
|   title={Multi-vendor experimental validation of an open source QoT estimator for optical networks}, | ||||
|   author={Filer, Mark and Cantono, Mattia and Ferrari, Alessio and Grammel, Gert and Galimberti, Gabriele and Curri, Vittorio}, | ||||
|   journal={Journal of Lightwave Technology}, | ||||
|   volume={36}, | ||||
|   number={15}, | ||||
|   pages={3073--3082}, | ||||
|   year={2018}, | ||||
|   publisher={IEEE} | ||||
| } | ||||
|  | ||||
| @inproceedings{auge2019open, | ||||
|   title={Open optical network planning demonstration}, | ||||
|   author={Auge, Jean-Luc and Grammel, Gert and Le Rouzic, Esther and Curri, Vittorio and Galimberti, Gabriele and Powell, James}, | ||||
|   booktitle={Optical Fiber Communication Conference}, | ||||
|   pages={M3Z--9}, | ||||
|   year={2019}, | ||||
|   organization={Optica Publishing Group} | ||||
| } | ||||
|  | ||||
| @inproceedings{kundrat2020physical, | ||||
|   title={Physical-layer awareness: GNPy and ONOS for end-to-end circuits in disaggregated networks}, | ||||
|   author={Kundr{\'a}t, Jan and Campanella, Andrea and Le Rouzic, Esther and Ferrari, Alessio and Havli{\v{s}}, Ond{\v{r}}ej and Ha{\v{z}}linsk{\`y}, Michal and Grammel, Gert and Galimberti, Gabriele and Curri, Vittorio}, | ||||
|   booktitle={2020 Optical Fiber Communications Conference and Exhibition (OFC)}, | ||||
|   pages={1--3}, | ||||
|   year={2020}, | ||||
|   organization={IEEE} | ||||
| } | ||||
|  | ||||
| @inproceedings{ferrari2020experimental, | ||||
|   title={Experimental validation of an open source quality of transmission estimator for open optical networks}, | ||||
|   author={Ferrari, Alessio and Filer, Mark and Balasubramanian, Karthikeyan and Yin, Yawei and Le Rouzic, Esther and Kundr{\'a}t, Jan and Grammel, Gert and Galimberti, Gabriele and Curri, Vittorio}, | ||||
|   booktitle={2020 Optical Fiber Communications Conference and Exhibition (OFC)}, | ||||
|   pages={1--3}, | ||||
|   year={2020}, | ||||
|   organization={IEEE} | ||||
| } | ||||
|  | ||||
| @article{ferrari2020gnpy, | ||||
|   title={GNPy: an open source application for physical layer aware open optical networks}, | ||||
|   author={Ferrari, Alessio and Filer, Mark and Balasubramanian, Karthikeyan and Yin, Yawei and Le Rouzic, Esther and Kundr{\'a}t, Jan and Grammel, Gert and Galimberti, Gabriele and Curri, Vittorio}, | ||||
|   journal={Journal of Optical Communications and Networking}, | ||||
|   volume={12}, | ||||
|   number={6}, | ||||
|   pages={C31--C40}, | ||||
|   year={2020}, | ||||
|   publisher={Optica Publishing Group} | ||||
| } | ||||
|  | ||||
| @inproceedings{ferrari2020softwarized, | ||||
|   title={Softwarized optical transport QoT in production optical network: a Brownfield validation}, | ||||
|   author={Ferrari, Alessio and Balasubramanian, Karthikeyan and Filer, Mark and Yin, Yawei and Le Rouzic, Esther and Kundr{\'a}t, Jan and Grammel, Gert and Galimberti, Gabriele and Curri, Vittorio}, | ||||
|   booktitle={2020 European Conference on Optical Communications (ECOC)}, | ||||
|   pages={1--4}, | ||||
|   year={2020}, | ||||
|   organization={IEEE} | ||||
| } | ||||
|  | ||||
| @article{ferrari2021assessment, | ||||
|   title={Assessment on the in-field lightpath QoT computation including connector loss uncertainties}, | ||||
|   author={Ferrari, Alessio and Balasubramanian, Karthikeyan and Filer, Mark and Yin, Yawei and Le Rouzic, Esther and Kundr{\'a}t, Jan and Grammel, Gert and Galimberti, Gabriele and Curri, Vittorio}, | ||||
|   journal={Journal of Optical Communications and Networking}, | ||||
|   volume={13}, | ||||
|   number={2}, | ||||
|   pages={A156--A164}, | ||||
|   year={2021}, | ||||
|   publisher={Optica Publishing Group} | ||||
| } | ||||
|  | ||||
| @inproceedings{kundrat2021gnpy, | ||||
|   title={GNPy \& YANG: open APIs for end-to-end service provisioning in optical networks}, | ||||
|   author={Kundr{\'a}t, Jan and Le Rouzic, Esther and M{\aa}rtensson, Jonas and Campanella, Andrea and Havli{\v{s}}, Ond{\v{r}}ej and D’Amico, Andrea and Grammel, Gert and Galimberti, Gabriele and Curri, Vittorio and Vojt{\v{e}}ch, Josef}, | ||||
|   booktitle={Optical Fiber Communication Conference}, | ||||
|   pages={M1B--6}, | ||||
|   year={2021}, | ||||
|   organization={Optica Publishing Group} | ||||
| } | ||||
|  | ||||
| @inproceedings{d2021gnpy, | ||||
|   title={GNPy experimental validation on flex-grid, flex-rate WDM optical transport scenarios}, | ||||
|   author={D’Amico, Andrea and London, Elliot and Le Guyader, Bertrand and Frank, Florian and Le Rouzic, Esther and Pincemin, Erwan and Brochier, Nicolas and Curri, Vittorio}, | ||||
|   booktitle={Optical fiber communication conference}, | ||||
|   pages={W1G--2}, | ||||
|   year={2021}, | ||||
|   organization={Optica Publishing Group} | ||||
| } | ||||
|  | ||||
| @inproceedings{virgillito2021testing, | ||||
|   title={Testing TIP open source solutions in deployed optical networks}, | ||||
|   author={Virgillito, Emanuele and Braun, Ralf-Peter and Breuer, Dirk and Gladisch, Andreas and Curri, Vittorio and Grammel, Gert}, | ||||
|   booktitle={Optical Fiber Communication Conference}, | ||||
|   pages={F1C--3}, | ||||
|   year={2021}, | ||||
|   organization={Optica Publishing Group} | ||||
| } | ||||
|  | ||||
| @article{d2022experimental, | ||||
|   title={Experimental validation of GNPy in a multi-vendor flex-grid flex-rate WDM optical transport scenario}, | ||||
|   author={D’Amico, Andrea and London, Elliot and Le Guyader, Bertrand and Frank, Florian and Le Rouzic, Esther and Pincemin, Erwan and Brochier, Nicolas and Curri, Vittorio}, | ||||
|   journal={Journal of Optical Communications and Networking}, | ||||
|   volume={14}, | ||||
|   number={3}, | ||||
|   pages={79--88}, | ||||
|   year={2022}, | ||||
|   publisher={Optica Publishing Group} | ||||
| } | ||||
|  | ||||
| @inproceedings{mano2022accuracy, | ||||
|   title={Accuracy of nonlinear interference estimation on launch power optimization in short-reach systems with field trial}, | ||||
|   author={Mano, Toru and D’Amico, Andrea and Virgillito, Emanuele and Borraccini, Giacomo and Huang, Yue-Kai and Kitamura, Kei and Anazawa, Kazuya and Masuda, Akira and Nishizawa, Hideki and Wang, Ting and others}, | ||||
|   booktitle={European Conference and Exhibition on Optical Communication}, | ||||
|   pages={We3B--1}, | ||||
|   year={2022}, | ||||
|   organization={Optica Publishing Group} | ||||
| } | ||||
|  | ||||
| @inproceedings{kundrat2022gnpy, | ||||
|   title={GNPy: Lessons learned and future plans}, | ||||
|   author={Kundr{\'a}t, Jan and Le Rouzic, Esther and M{\aa}rtensson, Jonas and Melin, Stefan and D’Amico, Andrea and Grammel, Gert and Galimberti, Gabriele and Curri, Vittorio}, | ||||
|   booktitle={European Conference and Exhibition on Optical Communication}, | ||||
|   pages={We3B--6}, | ||||
|   year={2022}, | ||||
|   organization={Optica Publishing Group} | ||||
| } | ||||
|  | ||||
| @inproceedings{grammel2023open, | ||||
|   title={Open Optical Networks: the good, the bad and the ugly}, | ||||
|   author={Grammel, Gert and Kundrat, Jan and Le Rouzic, Esther and Melin, Stefan and Curri, Vittorio and d'Amico, Andrea and Manzotti, Roberto}, | ||||
|   booktitle={49th European Conference on Optical Communications (ECOC 2023)}, | ||||
|   volume={2023}, | ||||
|   pages={1585--1588}, | ||||
|   year={2023}, | ||||
|   organization={IET} | ||||
| } | ||||
|  | ||||
| @inproceedings{d2024gnpy, | ||||
|   title={GNPy Experimental Validation in a C+ L Multiband Optical Multiplex Section}, | ||||
|   author={D’Amico, Andrea and Gatto, Vittorio and Nespola, Antonino and Borraccini, Giacomo and Jiang, Yanchao and Poggiolini, Pierluigi and Le Rouzic, Esther and de Lerma, Arturo Mayoral L{\'o}pez and Grammel, Gert and Manzotti, Roberto and others}, | ||||
|   booktitle={2024 24th International Conference on Transparent Optical Networks (ICTON)}, | ||||
|   pages={1--4}, | ||||
|   year={2024}, | ||||
|   organization={IEEE} | ||||
| } | ||||
|   | ||||
							
								
								
									
										298
									
								
								docs/cli_options.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										298
									
								
								docs/cli_options.rst
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,298 @@ | ||||
| .. _cli-options: | ||||
|  | ||||
| Options Documentation for `gnpy-path-request` and `gnpy-transmission-example` | ||||
| ============================================================================= | ||||
|  | ||||
| Common options | ||||
| -------------- | ||||
|  | ||||
| **Option**: `--no-insert-edfas` | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
|  | ||||
| **Purpose**: Disables the automatic insertion of EDFAs after ROADMs and fibers, as well as the splitting | ||||
| of fibers during the auto-design process. | ||||
|  | ||||
| The `--no-insert-edfas` option is a command-line argument available in GNPy that allows users to control the | ||||
| automatic insertion of amplifiers during the network design process. This option provides flexibility for | ||||
| users who may want to manually manage amplifier placements or who have specific design requirements that | ||||
| do not necessitate automatic amplification. | ||||
|  | ||||
| To use the `--no-insert-edfas` option, simply include it in the command line when running your GNPy program. For example: | ||||
|  | ||||
| .. code-block:: shell-session | ||||
|  | ||||
|   gnpy-transmission-example my_network.json --no-insert-edfas | ||||
|  | ||||
| When the `--no-insert-edfas` option is specified: | ||||
|  | ||||
| 1. **No Automatic Amplifiers**: The program will not automatically add EDFAs to the network topology after | ||||
|    ROADMs or fiber elements. This means that if the network design requires amplification, users must ensure | ||||
|    that amplifiers are manually defined in the network topology file. Users should be aware that disabling | ||||
|    automatic amplifier insertion may lead to insufficient amplification in the network if not managed properly. | ||||
|    It is essential to ensure that the network topology includes the necessary amplifiers to meet performance requirements. | ||||
|  | ||||
| 2. **No Fiber Splitting**: The option also prevents the automatic splitting of fibers during the design process. | ||||
|    This is particularly useful for users who want to maintain specific fiber lengths or configurations without | ||||
|    the program altering them. | ||||
|  | ||||
|  | ||||
| **Option**: `--equipment`, `-e` | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
|  | ||||
| **Description**: Specifies the equipment library file. | ||||
|  | ||||
| **Usage**:  | ||||
|  | ||||
| .. code-block:: shell-session | ||||
|  | ||||
|   gnpy-transmission-example my_network.json --equipment <FILE.json> | ||||
|  | ||||
| **Default**: Uses the default equipment configuration in the example-data folder if not specified. | ||||
|  | ||||
| **Functionality**: This option allows users to load a specific equipment configuration that defines the characteristics of the network elements. | ||||
|  | ||||
| **Option**: `--extra-equipment` and `--extra-config` | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
|  | ||||
| The `--extra-equipment` and `--extra-config` options allow users to extend the default equipment library and configuration | ||||
| settings used by the GNPy program. This feature is particularly useful for users who need to incorporate additional | ||||
| equipment types or specific configurations that are not included in the standard equipment library (such as third party pluggables). | ||||
|  | ||||
| **Usage**: | ||||
|    | ||||
| .. code-block:: shell-session | ||||
|  | ||||
|   --extra-equipment <file1.json> [<file2.json> ...] | ||||
|  | ||||
| **Parameters**: | ||||
|  | ||||
|   - `<file1.json>`: Path to the first additional equipment file. | ||||
|   - `<file2.json>`: Path to any subsequent additional equipment files (optional). | ||||
|  | ||||
| **Functionality**: | ||||
|  | ||||
|   - The program will merge the equipment definitions from the specified files into the main equipment library. | ||||
|   - If an equipment type defined in the additional files has the same name as one in the main library, the program | ||||
|     will issue a warning about the duplicate entry and will include ony the last definition. | ||||
|   - This allows for flexibility in defining equipment that may be specific to certain use cases or vendor-specific models. | ||||
|  | ||||
| **`--extra-config`**: | ||||
|  | ||||
| **Description**: This option allows users to specify additional configuration files that can override | ||||
|   or extend the default configuration settings used by the program. This is useful for customizing simulation | ||||
|   parameters or equipment settings. To set an amplifier with a specific such config, it must be defined in the | ||||
|   library with the keyword "default_config_from_json" filled with the file name containing the config in the case of | ||||
|   "variable_gain" amplifier or with the "advanced_config_from_json" for the "advanced_model" amplifier. | ||||
|  | ||||
| **Usage**: | ||||
|    | ||||
| .. code-block:: shell-session | ||||
|  | ||||
|   --extra-config <file1.json> [<file2.json> ...] | ||||
|  | ||||
| **Parameters**: | ||||
|   - `<file1.json>`: Path to the first additional configuration file. | ||||
|   - `<file2.json>`: Path to any subsequent additional configuration files (optional). | ||||
|  | ||||
| **Functionality**: | ||||
|   The program will load the configurations from the specified files and consider them instead of the | ||||
|   default configurations for the amplifiers that use the "default_config_from_json" or "advanced_config_from_json" keywords. | ||||
|  | ||||
| Example | ||||
| ------- | ||||
| To run the program with additional equipment and configuration files, you can use the following command: | ||||
|  | ||||
| .. code-block:: shell-session | ||||
|  | ||||
| gnpy-transmission-example --equipment main_equipment.json \ | ||||
|                           --extra-equipment additional_equipment1.json additional_equipment2.json \ | ||||
|                           --extra-config additional_config1.json | ||||
|  | ||||
|  | ||||
| In this example: | ||||
| - `main_equipment.json` is the primary equipment file. | ||||
| - `additional_equipment1.json` and `additional_equipment2.json` are additional equipment files that will be merged into the main library. | ||||
| - `additional_config1.json` is an additional configuration file that will override the default settings for the amplifiers pointing to it. | ||||
|  | ||||
|  | ||||
| **Option**: `--save-network` | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
|  | ||||
| **Description**: Saves the final network configuration to a specified JSON file. | ||||
|  | ||||
| **Usage**: | ||||
|  | ||||
| .. code-block:: shell-session | ||||
|  | ||||
|   --save-network <FILE.json> | ||||
|  | ||||
| **Functionality**: This option allows users to save the network state after the simulation, which can be useful for future reference or analysis. | ||||
|  | ||||
|  | ||||
| **Option**: `--save-network-before-autodesign` | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
|  | ||||
| **Description**: Dumps the network into a JSON file prior to autodesign. | ||||
|  | ||||
| **Usage**: | ||||
|  | ||||
| .. code-block:: shell-session | ||||
|  | ||||
|   gnpy-path-request my_network.json my_services.json --save-network-before-autodesign <FILE.json> | ||||
|  | ||||
| **Functionality**: This option is useful for users who want to inspect the network configuration before any automatic design adjustments are made. | ||||
|  | ||||
|  | ||||
| **Option**: `--sim-params` | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
|  | ||||
| **Description**: Path to the JSON file containing simulation parameters. | ||||
|  | ||||
| **Usage**: | ||||
|  | ||||
| .. code-block:: shell-session | ||||
|  | ||||
|   gnpy-transmission-example my_network.json --sim-params <FILE.json> | ||||
|  | ||||
| **Functionality**: The `--sim-params` option is a command-line argument available in GNPy that allows users to specify a | ||||
| JSON file containing simulation parameters. This option is crucial for customizing the behavior of the simulation: | ||||
| the file ``sim_params.json`` contains the tuning parameters used within both the ``gnpy.science_utils.RamanSolver`` and | ||||
| the ``gnpy.science_utils.NliSolver`` for the evaluation of the Raman profile and the NLI generation, respectively. | ||||
|  | ||||
| The tuning of the parameters is detailed here: :ref:`json input sim-params<sim-params>`. | ||||
|  | ||||
|  | ||||
| `gnpy-transmission-example` options | ||||
| ----------------------------------- | ||||
|  | ||||
| **Option**: `--show-channels` | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
|  | ||||
| **Description**: Displays the final per-channel OSNR and GSNR summary. | ||||
|  | ||||
| **Usage**:  | ||||
|  | ||||
| .. code-block:: shell-session | ||||
|  | ||||
|   gnpy-transmission-example my_network.json --show-channels | ||||
|  | ||||
| **Functionality**: This option provides a summary of the optical signal-to-noise ratio (OSNR) | ||||
| and generalized signal-to-noise ratio (GSNR) for each channel after the simulation. | ||||
|  | ||||
|  | ||||
| **Option**: `-pl`, `--plot` | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
|  | ||||
| **Description**: Generates plots of the results. | ||||
|  | ||||
| **Usage**:  | ||||
|  | ||||
| .. code-block:: shell-session | ||||
|  | ||||
|   gnpy-transmission-example my_network.json -pl | ||||
|    | ||||
| **Functionality**: This option allows users to visualize the results of the simulation through graphical plots. | ||||
|  | ||||
|  | ||||
| **Option**: `-l`, `--list-nodes` | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
|  | ||||
| **Description**: Lists all transceiver nodes in the network. | ||||
|  | ||||
| **Usage**:  | ||||
|  | ||||
| .. code-block:: shell-session | ||||
|  | ||||
|   gnpy-transmission-example my_network.json -l | ||||
|  | ||||
| **Functionality**: This option provides a quick way to view all transceiver nodes present in the network topology. | ||||
|  | ||||
| **Option**: `-po`, `--power` | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
|  | ||||
| **Description**: Specifies the reference channel power in span in dBm. | ||||
|  | ||||
| **Usage**: | ||||
|  | ||||
| .. code-block:: shell-session | ||||
|  | ||||
|   gnpy-transmission-example my_network.json -po <value> | ||||
|  | ||||
| **Functionality**: This option allows users to set the input power level for the reference channel used in the simulation. | ||||
| It replaces the value specified in the `SI` section of the equipment library (:ref:`power_dbm<spectral_info>`). | ||||
|  | ||||
|  | ||||
| **Option**: `--spectrum` | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
|  | ||||
| **Description**: Specifies a user-defined mixed rate spectrum JSON file for propagation. | ||||
|  | ||||
| **Usage**: | ||||
|  | ||||
| .. code-block:: shell-session | ||||
|  | ||||
|   gnpy-transmission-example my_network.json --spectrum <FILE.json> | ||||
|  | ||||
| **Functionality**: This option allows users to define a custom spectrum for the simulation, which can | ||||
| include varying channel rates and configurations. More details here: :ref:`mixed-rate<mixed-rate>`. | ||||
|  | ||||
|  | ||||
| Options for `path_requests_run` | ||||
| ------------------------------- | ||||
|  | ||||
| The `gnpy-path-request` script provides a simple path computation function that supports routing, transceiver mode selection, and spectrum assignment. | ||||
|  | ||||
| It supports include and disjoint constraints for the path computation, but does not provide any optimisation. | ||||
| It requires two mandatory arguments: network file and service file (see :ref:`XLS files<excel-service-sheet>` or :ref:`JSON files<legacy-json>`). | ||||
|  | ||||
| The `gnpy-path-request` computes: | ||||
|  | ||||
|   - design network once and propagate the service requests on this design | ||||
|   - computes performance of each request defined in the service file independently from each other, considering full load (based on the request settings), | ||||
|   - assigns spectrum for each request according to the remaining spectrum, on a first arrived first served basis. | ||||
|     Lack of spectrum leads to blocking, but performance estimation is still returned for information. | ||||
|  | ||||
|  | ||||
| **Option**: `-bi`, `--bidir` | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
|  | ||||
| **Description**: Indicates that all demands are bidirectional. | ||||
|  | ||||
| **Usage**: | ||||
|  | ||||
| .. code-block:: shell-session | ||||
|  | ||||
|   gnpy-path-request my_network.json my_service.json -e my_equipment.json -bi | ||||
|  | ||||
| **Functionality**: This option allows users to specify that the performance of the service requests should be | ||||
| computed in both directions (source to destination and destination to source). This forces the 'bidirectional' | ||||
| attribute to true in the service file, possibly affecting feasibility if one direction is not feasible. | ||||
|  | ||||
|  | ||||
| **Option**: `-o`, `--output` | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
|  | ||||
| **Description**: Stores computation results requests into a JSON or CSV file. | ||||
|  | ||||
| **Usage**:  | ||||
|  | ||||
| .. code-block:: shell-session | ||||
|  | ||||
|   gnpy-path-request my_network.json my_service.json -o <FILE.json|FILE.csv> | ||||
|  | ||||
| **Functionality**: This option allows users to save the results of the path requests into a specified output file | ||||
| for further analysis. | ||||
|  | ||||
|  | ||||
| **Option**: `--redesign-per-request` | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
|  | ||||
| **Description**: Redesigns the network for each request using the request as the reference channel | ||||
| (replaces the `SI` section of the equipment library with the request specifications). | ||||
|  | ||||
| **Usage**: | ||||
| .. code-block:: shell-session | ||||
|  | ||||
|   gnpy-path-request my_network.json my_services.json --redesign-per-request | ||||
|  | ||||
| **Functionality**: This option enables checking different scenarios for design. | ||||
| @@ -7,3 +7,4 @@ | ||||
| .. automodule:: gnpy.tools.json_io | ||||
| .. automodule:: gnpy.tools.plots | ||||
| .. automodule:: gnpy.tools.service_sheet | ||||
| .. automodule:: gnpy.tools.worker_utils | ||||
|   | ||||
| @@ -11,13 +11,17 @@ in real-world mesh optical networks. It is based on the Gaussian Noise Model. | ||||
|    intro | ||||
|    concepts | ||||
|    install | ||||
|    cli_options | ||||
|    amplifier_models_description | ||||
|    json | ||||
|    json_instance_examples | ||||
|    excel | ||||
|    extending | ||||
|    about-project | ||||
|    model | ||||
|    gnpy-api | ||||
|    release-notes | ||||
|    publications | ||||
|  | ||||
| Indices and tables | ||||
| ================== | ||||
|   | ||||
| @@ -11,9 +11,11 @@ Equipment Library | ||||
|  | ||||
| Design and transmission parameters are defined in a dedicated json file. | ||||
| By default, this information is read from `gnpy/example-data/eqpt_config.json <https://github.com/Telecominfraproject/oopt-gnpy/blob/master/gnpy/example-data/eqpt_config.json>`_. | ||||
| This file defines the equipment libraries that can be customized (EDFAs, fibers, and transceivers). | ||||
| This file defines the equipment libraries that can be customized (Amplifiers, ROADMs, fibers, and transceivers). | ||||
|  | ||||
| It also defines the simulation parameters (spans, ROADMs, and the spectral information to transmit.) | ||||
| It also defines the simulation parameters (spans and the spectral information to transmit.) | ||||
|  | ||||
| Examples of instances are commented here :ref:`json instances examples<json-instance-examples>`. | ||||
|  | ||||
| EDFA | ||||
| ~~~~ | ||||
| @@ -65,10 +67,16 @@ For all single band amplifier models: | ||||
| |                        |           | within this range (center frequency and | | ||||
| |                        |           | spectrum width).                        | | ||||
| |                        |           | Default is 191.275e-12 Hz and           | | ||||
| |                        |           | 196.125e-12 (tunable in                 | | ||||
| |                        |           | default_edfa_config.json)               | | ||||
| |                        |           | 196.125e-12.                            | | ||||
| +------------------------+-----------+-----------------------------------------+ | ||||
|  | ||||
| Default values are defined for the frequency range for: | ||||
| - noise figure ripple | ||||
| - gain ripple | ||||
| - dynamic gain tilt | ||||
|  | ||||
| Users can introduce custom values using ``default_config_from_json`` which should be populated with a file name containing the desired parameters. | ||||
|  | ||||
|  | ||||
| For multi_band amplifier models: | ||||
|  | ||||
| @@ -490,6 +498,8 @@ If nothing is stated for impairments on roadm-paths, the program identifies the | ||||
|  | ||||
| On the previous example, all «implicit» express roadm-path are assigned roadm-path-impairment-id = 0 | ||||
|  | ||||
| .. _sim-params: | ||||
|  | ||||
| Global parameters | ||||
| ----------------- | ||||
|  | ||||
|   | ||||
							
								
								
									
										1035
									
								
								docs/json_instance_examples.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1035
									
								
								docs/json_instance_examples.rst
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										24
									
								
								docs/publications.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								docs/publications.rst
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | ||||
| .. _publications: | ||||
|  | ||||
| Publications | ||||
| ============ | ||||
|  | ||||
| Below is a chronological list of notable publications that emerged from the PSE group's collaborative work. | ||||
| These articles detail the evolution of GNPy and confirm its performance through experimental trials: | ||||
|  | ||||
| - `G. Grammel, V. Curri, and J. Auge, "Physical Simulation Environment of The Telecommunications Infrastructure Project (TIP)," in Optical Fiber Communication Conference, OSA Technical Digest (online) (Optica Publishing Group, 2018), paper M1D.3. <https://opg.optica.org/abstract.cfm?uri=OFC-2018-M1D.3>`_ | ||||
| - `B. D. Taylor, G. Goldfarb, S. Bandyopadhyay, V. Curri, and H. Schmidtke, "Towards a Route Planning Tool for Open Optical Networks in the Telecom Infrastructure Project," in Optical Fiber Communication Conference, OSA Technical Digest (online) (Optica Publishing Group, 2018), paper Tu3E.4. <https://opg.optica.org/abstract.cfm?uri=OFC-2018-Tu3E.4>`_ | ||||
| - `M. Filer, M. Cantono, A. Ferrari, G. Grammel, G. Galimberti, and V. Curri, "Multi-Vendor Experimental Validation of an Open Source QoT Estimator for Optical Networks," J. Lightwave Technol. 36, 3073-3082 (2018). <https://opg.optica.org/jlt/abstract.cfm?uri=jlt-36-15-3073>`_ | ||||
| - `J. Auge, G. Grammel, E. le Rouzic, V. Curri, G. Galimberti, and J. Powell, "Open optical network planning demonstration," in Optical Fiber Communication Conference (OFC) 2019, OSA Technical Digest (Optica Publishing Group, 2019), paper M3Z.9. <https://opg.optica.org/abstract.cfm?uri=OFC-2019-M3Z.9>`_ | ||||
| - `J. Kundrát, A. Campanella, E. Le Rouzic, A. Ferrari, O. Havliš, M. Hažlinský, G. Grammel, G. Galimberti, and V. Curri, "Physical-Layer Awareness: GNPy and ONOS for End-to-End Circuits in Disaggregated Networks," in Optical Fiber Communication Conference (OFC) 2020, OSA Technical Digest (Optica Publishing Group, 2020), paper M3Z.17. <https://opg.optica.org/abstract.cfm?uri=ofc-2020-m3z.17>`_ | ||||
| - `A. Ferrari, M. Filer, K. Balasubramanian, Y. Yin, E. Le Rouzic, J. Kundrát, G. Grammel, G. Galimberti, and V. Curri, "Experimental Validation of an Open Source Quality of Transmission Estimator for Open Optical Networks," in Optical Fiber Communication Conference (OFC) 2020, OSA Technical Digest (Optica Publishing Group, 2020), paper W3C.2. <https://opg.optica.org/abstract.cfm?uri=ofc-2020-W3C.2>`_ | ||||
| - `A. Ferrari, M. Filer, K. Balasubramanian, Y. Yin, E. Le Rouzic, J. Kundrát, G. Grammel, G. Galimberti, and V. Curri, "GNPy: an open source application for physical layer aware open optical networks," J. Opt. Commun. Netw. 12, C31-C40 (2020). <https://opg.optica.org/jocn/fulltext.cfm?uri=jocn-12-6-C31&id=429003>`_ | ||||
| - `A. Ferrari, K. Balasubramanian, M. Filer, Y. Yin, E. Le Rouzic, J. Kundrát, G. Grammel, G. Galimberti, and V. Curri, "Softwarized Optical Transport QoT in Production Optical Network: a Brownfield Validation," 2020 European Conference on Optical Communications (ECOC), Brussels, Belgium, 2020. <https://ieeexplore.ieee.org/document/9333280>`_ | ||||
| - `A. Ferrari, K. Balasubramanian, M. Filer, Y. Yin, E. Le Rouzic, J. Kundrát, G. Grammel, G. Galimberti, and V. Curri, "Assessment on the in-field lightpath QoT computation including connector loss uncertainties," in Journal of Optical Communications and Networking, vol. 13, no. 2, pp. A156-A164, February 2021. <https://ieeexplore.ieee.org/document/9308057>`_ | ||||
| - `J. Kundrát, E. Le Rouzic, J. Mårtensson, A. Campanella, O. Havliš, A. D’Amico, G. Grammel, G. Galimberti, V. Curri, and J. Vojtěch, "GNPy & YANG: Open APIs for End-to-End Service Provisioning in Optical Networks," in Optical Fiber Communication Conference (OFC) 2021, P. Dong, J. Kani, C. Xie, R. Casellas, C. Cole, and M. Li, eds., OSA Technical Digest (Optica Publishing Group, 2021), paper M1B.6. <https://opg.optica.org/abstract.cfm?uri=ofc-2021-M1B.6>`_ | ||||
| - `A. D’Amico, E. London, B. Le Guyader, F. Frank, E. Le Rouzic, E. Pincemin, N. Brochier, and V. Curri, "GNPy experimental validation on flex-grid, flex-rate WDM optical transport scenarios," in Optical Fiber Communication Conference (OFC) 2021, P. Dong, J. Kani, C. Xie, R. Casellas, C. Cole, and M. Li, eds., OSA Technical Digest (Optica Publishing Group, 2021), paper W1G.2. <https://opg.optica.org/abstract.cfm?uri=ofc-2021-W1G.2>`_ | ||||
| - `E. Virgillito, R. Braun, D. Breuer, A. Gladisch, V. Curri, and G. Grammel, "Testing TIP Open Source Solutions in Deployed Optical Networks," in Optical Fiber Communication Conference (OFC) 2021, P. Dong, J. Kani, C. Xie, R. Casellas, C. Cole, and M. Li, eds., OSA Technical Digest (Optica Publishing Group, 2021), paper F1C.3. <https://opg.optica.org/abstract.cfm?uri=ofc-2021-F1C.3>`_ | ||||
| - `A. D’Amico, E. London, B. Le Guyader, F. Frank, E. Le Rouzic, E. Pincemin, N. Brochier, and V. Curri, "Experimental validation of GNPy in a multi-vendor flex-grid flex-rate WDM optical transport scenario," J. Opt. Commun. Netw. 14, 79-88 (2022). <https://opg.optica.org/jocn/fulltext.cfm?uri=jocn-14-3-79&id=466355>`_ | ||||
| - `J. Kundrát, E. Le Rouzic, J. Mårtensson, S. Melin, A. D’Amico, G. Grammel, G. Galimberti, and V. Curri, "GNPy: Lessons Learned and Future Plans [Invited]," in European Conference on Optical Communication (ECOC) 2022, J. Leuthold, C. Harder, B. Offrein, and H. Limberger, eds., Technical Digest Series (Optica Publishing Group, 2022), paper We3B.6. <https://opg.optica.org/abstract.cfm?uri=ECEOC-2022-We3B.6>`_ | ||||
| - `G. Grammel, J. Kundrat, E. Le Rouzic, S. Melin, V. Curri, A. D'Amico, R. Manzotti, "Open Optical Networks: the good, the bad and the ugly," 49th European Conference on Optical Communications (ECOC 2023), Hybrid Conference, Glasgow, UK, 2023. <https://ieeexplore.ieee.org/document/10484723>`_ | ||||
| - `A. D’Amico, V. Gatto, A. Nespola, G. Borraccini, Y. Jiang, P. Poggiolini, E. Le Rouzic,  A. M. L. de Lerma, G. Grammel, R. Manzotti, V. Curri, "GNPy Experimental Validation in a C+L Multiband Optical Multiplex Section," 2024 24th International Conference on Transparent Optical Networks (ICTON), Bari, Italy, 2024. <https://ieeexplore.ieee.org/document/10648172>`_ | ||||
| @@ -6,6 +6,14 @@ Release change log | ||||
| Each release introduces some changes and new features. | ||||
|  | ||||
| (prepare text for next release) | ||||
| **Important Changes:** | ||||
|  | ||||
| The default values for EDFA configuration, including frequency range, gain ripple, noise figure ripple, or dynamic gain tilt | ||||
| are now hardcoded in parameters.py and are no longer read from the default_edfa_config.json file (the file has been removed). | ||||
| However, users can define their own custom parameters using the default_config_from_json variable, which should be populated with a file name containing the desired parameter description. This applies to both variable_gain and fixed_gain amplifier types. | ||||
|  | ||||
| This change streamlines the configuration process but requires users to explicitly set parameters through the new | ||||
| model if the default values do not suit their needs. | ||||
|  | ||||
| v2.11 | ||||
| ----- | ||||
|   | ||||
| @@ -562,7 +562,9 @@ class EdfaParams: | ||||
|             else: | ||||
|                 self.nf_ripple = asarray(nf_ripple) | ||||
|                 if self.nf_ripple.size != self.gain_ripple.size: | ||||
|                     raise ParametersError("The noise figure ripple and the gain ripple must have the same size.") | ||||
|                     raise ParametersError( | ||||
|                         "The noise figure ripple and the gain ripple must have the same size. %s, %s", | ||||
|                         self.nf_ripple.size, self.gain_ripple.size) | ||||
|  | ||||
|             # VOA | ||||
|             self.out_voa_auto = params['out_voa_auto'] | ||||
| @@ -626,6 +628,39 @@ class EdfaOperational: | ||||
|                 f'tilt_target={self.tilt_target!r})') | ||||
|  | ||||
|  | ||||
| DEFAULT_EDFA_CONFIG = { | ||||
|     "nf_ripple": [ | ||||
|         0.0 | ||||
|     ], | ||||
|     "gain_ripple": [ | ||||
|         0.0 | ||||
|     ], | ||||
|     "f_min": 191.275e12, | ||||
|     "f_max": 196.125e12, | ||||
|     "dgt": [ | ||||
|         1.0, 1.017807767853702, 1.0356155337864215, 1.0534217504465226, 1.0712204022764056, 1.0895983485572227, | ||||
|         1.108555289615659, 1.1280891949729075, 1.1476135933863398, 1.1672278304018044, 1.1869318618366975, | ||||
|         1.2067249615595257, 1.2264996957264114, 1.2428104897182262, 1.2556591482982988, 1.2650555289898042, | ||||
|         1.2744470198196236, 1.2838336236692311, 1.2932153453410835, 1.3040618749785347, 1.316383926863083, | ||||
|         1.3301807335621048, 1.3439818461440451, 1.3598972673004606, 1.3779439775587023, 1.3981208704326855, | ||||
|         1.418273806730323, 1.4340878115214444, 1.445565137158368, 1.45273959485914, 1.4599103316162523, | ||||
|         1.4670307626366115, 1.474100442252211, 1.48111939735681, 1.488134243479226, 1.495145456062699, | ||||
|         1.502153039909686, 1.5097346239790443, 1.5178910621476225, 1.5266220576235803, 1.5353620432989845, | ||||
|         1.545374152761467, 1.5566577309558969, 1.569199764184379, 1.5817353179379183, 1.5986915141218316, | ||||
|         1.6201194134191075, 1.6460167077689267, 1.6719047669939942, 1.6918150918099673, 1.7057507692361864, | ||||
|         1.7137640932265894, 1.7217732861435076, 1.7297783508684146, 1.737780757913635, 1.7459181197626403, | ||||
|         1.7541903672600494, 1.7625959636196327, 1.7709972329654864, 1.7793941781790852, 1.7877868031023945, | ||||
|         1.7961751115773796, 1.8045606557581335, 1.8139629377087627, 1.824381436842932, 1.835814081380705, | ||||
|         1.847275503201129, 1.862235672444246, 1.8806927939516411, 1.9026104247588487, 1.9245345552113182, | ||||
|         1.9482128147680253, 1.9736443063300082, 2.0008103857988204, 2.0279625371819305, 2.055100772005235, | ||||
|         2.082225099873648, 2.1183028432496016, 2.16337565384239, 2.2174389328192197, 2.271520771371253, | ||||
|         2.322373696229342, 2.3699990328716107, 2.414398437185221, 2.4587748041127506, 2.499446286796604, | ||||
|         2.5364027376452056, 2.5696460593920065, 2.602860350286428, 2.630396440815385, 2.6521732021128046, | ||||
|         2.6681935771243177, 2.6841217449620203, 2.6947834587664494, 2.705443819238505, 2.714526681131686 | ||||
|     ] | ||||
| } | ||||
|  | ||||
|  | ||||
| class MultiBandParams: | ||||
|     default_values = { | ||||
|         'bands': [], | ||||
|   | ||||
| @@ -1,108 +0,0 @@ | ||||
| { | ||||
|   "nf_ripple": [ | ||||
|     0.0 | ||||
|   ], | ||||
|   "gain_ripple": [ | ||||
|     0.0 | ||||
|   ], | ||||
|   "f_min": 191.275e12, | ||||
|   "f_max": 196.125e12, | ||||
|   "dgt": [ | ||||
|     1.0, | ||||
|     1.017807767853702, | ||||
|     1.0356155337864215, | ||||
|     1.0534217504465226, | ||||
|     1.0712204022764056, | ||||
|     1.0895983485572227, | ||||
|     1.108555289615659, | ||||
|     1.1280891949729075, | ||||
|     1.1476135933863398, | ||||
|     1.1672278304018044, | ||||
|     1.1869318618366975, | ||||
|     1.2067249615595257, | ||||
|     1.2264996957264114, | ||||
|     1.2428104897182262, | ||||
|     1.2556591482982988, | ||||
|     1.2650555289898042, | ||||
|     1.2744470198196236, | ||||
|     1.2838336236692311, | ||||
|     1.2932153453410835, | ||||
|     1.3040618749785347, | ||||
|     1.316383926863083, | ||||
|     1.3301807335621048, | ||||
|     1.3439818461440451, | ||||
|     1.3598972673004606, | ||||
|     1.3779439775587023, | ||||
|     1.3981208704326855, | ||||
|     1.418273806730323, | ||||
|     1.4340878115214444, | ||||
|     1.445565137158368, | ||||
|     1.45273959485914, | ||||
|     1.4599103316162523, | ||||
|     1.4670307626366115, | ||||
|     1.474100442252211, | ||||
|     1.48111939735681, | ||||
|     1.488134243479226, | ||||
|     1.495145456062699, | ||||
|     1.502153039909686, | ||||
|     1.5097346239790443, | ||||
|     1.5178910621476225, | ||||
|     1.5266220576235803, | ||||
|     1.5353620432989845, | ||||
|     1.545374152761467, | ||||
|     1.5566577309558969, | ||||
|     1.569199764184379, | ||||
|     1.5817353179379183, | ||||
|     1.5986915141218316, | ||||
|     1.6201194134191075, | ||||
|     1.6460167077689267, | ||||
|     1.6719047669939942, | ||||
|     1.6918150918099673, | ||||
|     1.7057507692361864, | ||||
|     1.7137640932265894, | ||||
|     1.7217732861435076, | ||||
|     1.7297783508684146, | ||||
|     1.737780757913635, | ||||
|     1.7459181197626403, | ||||
|     1.7541903672600494, | ||||
|     1.7625959636196327, | ||||
|     1.7709972329654864, | ||||
|     1.7793941781790852, | ||||
|     1.7877868031023945, | ||||
|     1.7961751115773796, | ||||
|     1.8045606557581335, | ||||
|     1.8139629377087627, | ||||
|     1.824381436842932, | ||||
|     1.835814081380705, | ||||
|     1.847275503201129, | ||||
|     1.862235672444246, | ||||
|     1.8806927939516411, | ||||
|     1.9026104247588487, | ||||
|     1.9245345552113182, | ||||
|     1.9482128147680253, | ||||
|     1.9736443063300082, | ||||
|     2.0008103857988204, | ||||
|     2.0279625371819305, | ||||
|     2.055100772005235, | ||||
|     2.082225099873648, | ||||
|     2.1183028432496016, | ||||
|     2.16337565384239, | ||||
|     2.2174389328192197, | ||||
|     2.271520771371253, | ||||
|     2.322373696229342, | ||||
|     2.3699990328716107, | ||||
|     2.414398437185221, | ||||
|     2.4587748041127506, | ||||
|     2.499446286796604, | ||||
|     2.5364027376452056, | ||||
|     2.5696460593920065, | ||||
|     2.602860350286428, | ||||
|     2.630396440815385, | ||||
|     2.6521732021128046, | ||||
|     2.6681935771243177, | ||||
|     2.6841217449620203, | ||||
|     2.6947834587664494, | ||||
|     2.705443819238505, | ||||
|     2.714526681131686 | ||||
|   ] | ||||
| } | ||||
							
								
								
									
										74
									
								
								gnpy/example-data/extra_eqpt_config.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								gnpy/example-data/extra_eqpt_config.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,74 @@ | ||||
| { | ||||
|   "Edfa": [ | ||||
|     { | ||||
|       "type_variety": "user_defined", | ||||
|       "type_def": "variable_gain", | ||||
|       "f_min": 192.0e12, | ||||
|       "f_max": 195.9e12, | ||||
|       "gain_flatmax": 25, | ||||
|       "gain_min": 15, | ||||
|       "p_max": 21, | ||||
|       "nf_min": 6, | ||||
|       "nf_max": 10, | ||||
|       "default_config_from_json": "user_edfa_config.json", | ||||
|       "out_voa_auto": false, | ||||
|       "allowed_for_design": true | ||||
|     }, { | ||||
|       "type_variety": "user_high_detail_model_example", | ||||
|       "type_def": "advanced_model", | ||||
|       "gain_flatmax": 25, | ||||
|       "gain_min": 15, | ||||
|       "p_max": 21, | ||||
|       "advanced_config_from_json": "std_medium_gain_advanced_config.json", | ||||
|       "out_voa_auto": false, | ||||
|       "allowed_for_design": false | ||||
|     } | ||||
|   ], | ||||
|   "Transceiver": [ | ||||
|     { | ||||
|       "type_variety": "ZR400G", | ||||
|       "frequency": { | ||||
|         "min": 191.3e12, | ||||
|         "max": 196.1e12 | ||||
|       }, | ||||
|       "mode": [ | ||||
|         { | ||||
|           "format": "SFF-ID:70", | ||||
|           "baud_rate": 60138546798, | ||||
|           "OSNR": 24, | ||||
|           "bit_rate": 400e9, | ||||
|           "roll_off": 0.2, | ||||
|           "tx_osnr": 34, | ||||
|           "min_spacing": 75e9, | ||||
|           "penalties": [ | ||||
|             { | ||||
|               "chromatic_dispersion": 20e3, | ||||
|               "penalty_value": 0.5 | ||||
|             }, | ||||
|             { | ||||
|               "chromatic_dispersion": 0, | ||||
|               "penalty_value": 0 | ||||
|             }, | ||||
|             { | ||||
|               "pmd": 20, | ||||
|               "penalty_value": 0.5 | ||||
|             }, | ||||
|             { | ||||
|               "pdl": 1.5, | ||||
|               "penalty_value": 0 | ||||
|             }, | ||||
|             { | ||||
|               "pdl": 3.5, | ||||
|               "penalty_value": 1.8 | ||||
|             }, | ||||
|             { | ||||
|               "pdl": 3, | ||||
|               "penalty_value": 1.3 | ||||
|             } | ||||
|           ], | ||||
|           "cost": 1 | ||||
|         } | ||||
|       ] | ||||
|     } | ||||
|   ] | ||||
| } | ||||
							
								
								
									
										22
									
								
								gnpy/example-data/service_pluggable.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								gnpy/example-data/service_pluggable.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| { | ||||
|   "path-request": [ | ||||
|     { | ||||
|       "request-id": "0", | ||||
|       "source": "trx Brest_KLA", | ||||
|       "destination": "trx Lannion_CAS", | ||||
|       "src-tp-id": "trx Brest_KLA", | ||||
|       "dst-tp-id": "trx Lannion_CAS", | ||||
|       "bidirectional": false, | ||||
|       "path-constraints": { | ||||
|         "te-bandwidth": { | ||||
|           "technology": "flexi-grid", | ||||
|           "trx_type": "ZR400G", | ||||
|           "trx_mode": "SFF-ID:70", | ||||
|           "spacing": 100000000000.0, | ||||
|           "tx_power": 0.0015, | ||||
|           "path_bandwidth": 400000000000.0 | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   ] | ||||
| } | ||||
| @@ -12,6 +12,7 @@ import argparse | ||||
| import logging | ||||
| import sys | ||||
| from pathlib import Path | ||||
| from typing import List | ||||
| from math import ceil | ||||
| from numpy import mean | ||||
|  | ||||
| @@ -21,14 +22,17 @@ from gnpy.core import exceptions | ||||
| from gnpy.core.parameters import SimParams | ||||
| from gnpy.core.utils import lin2db, pretty_summary_print, per_label_average, watt2dbm | ||||
| from gnpy.topology.request import (ResultElement, jsontocsv, BLOCKING_NOPATH) | ||||
| from gnpy.tools.json_io import (load_equipment, load_network, load_json, load_requests, save_network, | ||||
|                                 requests_from_json, save_json, load_initial_spectrum) | ||||
| from gnpy.tools.json_io import (load_equipments_and_configs, load_network, load_json, load_requests, save_network, | ||||
|                                 requests_from_json, save_json, load_initial_spectrum, DEFAULT_EQPT_CONFIG) | ||||
| from gnpy.tools.plots import plot_baseline, plot_results | ||||
| from gnpy.tools.worker_utils import designed_network, transmission_simulation, planning | ||||
|  | ||||
|  | ||||
| _logger = logging.getLogger(__name__) | ||||
| _examples_dir = Path(__file__).parent.parent / 'example-data' | ||||
| _default_config_files = ['example-data/std_medium_gain_advanced_config.json', | ||||
|                          'example-data/Juniper-BoosterHG.json', | ||||
|                          'parameters.DEFAULT_EDFA_CONFIG'] | ||||
| _help_footer = ''' | ||||
| This program is part of GNPy, https://github.com/TelecomInfraProject/oopt-gnpy | ||||
|  | ||||
| @@ -43,11 +47,12 @@ def show_example_data_dir(): | ||||
|     print(f'{_examples_dir}/') | ||||
|  | ||||
|  | ||||
| def load_common_data(equipment_filename, topology_filename, simulation_filename, save_raw_network_filename): | ||||
|     """Load common configuration from JSON files""" | ||||
| def load_common_data(equipment_filename: Path, extra_equipment_filenames: List[Path], extra_config_filenames: List[Path], | ||||
|                      topology_filename: Path, simulation_filename: Path, save_raw_network_filename: Path): | ||||
|     """Load common configuration from JSON files, merging additional equipment if provided.""" | ||||
|  | ||||
|     try: | ||||
|         equipment = load_equipment(equipment_filename) | ||||
|         equipment = load_equipments_and_configs(equipment_filename, extra_equipment_filenames, extra_config_filenames) | ||||
|         network = load_network(topology_filename, equipment) | ||||
|         if save_raw_network_filename is not None: | ||||
|             save_network(network, save_raw_network_filename) | ||||
| @@ -91,7 +96,7 @@ def _add_common_options(parser: argparse.ArgumentParser, network_default: Path): | ||||
|     parser.add_argument('-v', '--verbose', action='count', default=0, | ||||
|                         help='Increase verbosity (can be specified several times)') | ||||
|     parser.add_argument('-e', '--equipment', type=Path, metavar=_help_fname_json, | ||||
|                         default=_examples_dir / 'eqpt_config.json', help='Equipment library') | ||||
|                         default=DEFAULT_EQPT_CONFIG, help='Equipment library') | ||||
|     parser.add_argument('--sim-params', type=Path, metavar=_help_fname_json, | ||||
|                         default=None, help='Path to the JSON containing simulation parameters (required for Raman). ' | ||||
|                                            f'Example: {_examples_dir / "sim_params.json"}') | ||||
| @@ -102,6 +107,16 @@ def _add_common_options(parser: argparse.ArgumentParser, network_default: Path): | ||||
|     parser.add_argument('--no-insert-edfas', action='store_true', | ||||
|                         help='Disable insertion of EDFAs after ROADMs and fibers ' | ||||
|                              'as well as splitting of fibers by auto-design.') | ||||
|     # Option for additional equipment files | ||||
|     parser.add_argument('--extra-equipment', nargs='+', type=Path, | ||||
|                         metavar=_help_fname_json, default=None, | ||||
|                         help='List of additional equipment files to complement the main equipment file.') | ||||
|     # Option for additional config files | ||||
|     parser.add_argument('--extra-config', nargs='+', type=Path, | ||||
|                         metavar=_help_fname_json, | ||||
|                         help='List of additional config files as referenced in equipment files with ' | ||||
|                              '"advanced_config_from_json" or "default_config_from_json".' | ||||
|                              f'Existing configs:\n{_default_config_files}') | ||||
|  | ||||
|  | ||||
| def transmission_main_example(args=None): | ||||
| @@ -125,7 +140,8 @@ def transmission_main_example(args=None): | ||||
|     args = parser.parse_args(args if args is not None else sys.argv[1:]) | ||||
|     _setup_logging(args) | ||||
|  | ||||
|     (equipment, network) = load_common_data(args.equipment, args.topology, args.sim_params, args.save_network_before_autodesign) | ||||
|     (equipment, network) = load_common_data(args.equipment, args.extra_equipment, args.extra_config, args.topology, | ||||
|                                             args.sim_params, args.save_network_before_autodesign) | ||||
|  | ||||
|     if args.plot: | ||||
|         plot_baseline(network) | ||||
| @@ -313,7 +329,8 @@ def path_requests_run(args=None): | ||||
|     _logger.info(f'Computing path requests {args.service_filename.name} into JSON format') | ||||
|  | ||||
|     (equipment, network) = \ | ||||
|         load_common_data(args.equipment, args.topology, args.sim_params, args.save_network_before_autodesign) | ||||
|         load_common_data(args.equipment, args.extra_equipment, args.extra_config, args.topology, args.sim_params, | ||||
|                          args.save_network_before_autodesign) | ||||
|  | ||||
|     # Build the network once using the default power defined in SI in eqpt config | ||||
|  | ||||
|   | ||||
| @@ -24,7 +24,7 @@ from gnpy.core.exceptions import ConfigurationError, EquipmentConfigError, Netwo | ||||
| from gnpy.core.science_utils import estimate_nf_model | ||||
| from gnpy.core.info import Carrier | ||||
| from gnpy.core.utils import automatic_nch, automatic_fmax, merge_amplifier_restrictions, dbm2watt | ||||
| from gnpy.core.parameters import DEFAULT_RAMAN_COEFFICIENT, EdfaParams, MultiBandParams | ||||
| from gnpy.core.parameters import DEFAULT_RAMAN_COEFFICIENT, EdfaParams, MultiBandParams, DEFAULT_EDFA_CONFIG | ||||
| from gnpy.topology.request import PathRequest, Disjunction, compute_spectrum_slot_vs_bandwidth | ||||
| from gnpy.topology.spectrum_assignment import mvalue_to_slots | ||||
| from gnpy.tools.convert import xls_to_json_data | ||||
| @@ -39,6 +39,10 @@ Model_fg = namedtuple('Model_fg', 'nf0') | ||||
| Model_openroadm_ila = namedtuple('Model_openroadm_ila', 'nf_coef') | ||||
| Model_hybrid = namedtuple('Model_hybrid', 'nf_ram gain_ram edfa_variety') | ||||
| Model_dual_stage = namedtuple('Model_dual_stage', 'preamp_variety booster_variety') | ||||
| _examples_dir = Path(__file__).parent.parent / 'example-data' | ||||
| DEFAULT_EXTRA_CONFIG = {"std_medium_gain_advanced_config.json": _examples_dir / "std_medium_gain_advanced_config.json", | ||||
|                         "Juniper-BoosterHG.json": _examples_dir / "Juniper-BoosterHG.json"} | ||||
| DEFAULT_EQPT_CONFIG = _examples_dir / "eqpt_config.json" | ||||
|  | ||||
|  | ||||
| class Model_openroadm_preamp: | ||||
| @@ -212,11 +216,13 @@ class Amp(_JsonThing): | ||||
|         self.update_attr(self.default_values, kwargs, 'Amp') | ||||
|  | ||||
|     @classmethod | ||||
|     def from_json(cls, filename, **kwargs): | ||||
|     def from_json(cls, extra_configs, **kwargs): | ||||
|         """ | ||||
|         """ | ||||
|         config = Path(filename).parent / 'default_edfa_config.json' | ||||
|         # default_edfa_config.json assumes a DGT profile independantly from fmin/fmax, that's a generic profile | ||||
|         # default EDFA DGT and ripples are defined in parameters DEFAULT_EDFA_CONFIG. copy these values when | ||||
|         # creating a new amplifier | ||||
|         config = {k: v for k, v in DEFAULT_EDFA_CONFIG.items()} | ||||
|         config_filename = 'default'    # default value to display in case of error | ||||
|         type_variety = kwargs['type_variety'] | ||||
|         type_def = kwargs.get('type_def', 'variable_gain')  # default compatibility with older json eqpt files | ||||
|         nf_def = None | ||||
| @@ -224,6 +230,10 @@ class Amp(_JsonThing): | ||||
|         amplifiers = None | ||||
|  | ||||
|         if type_def == 'fixed_gain': | ||||
|             if 'default_config_from_json' in kwargs: | ||||
|                 # use user defined default instead of DEFAULT_EDFA_CONFIG | ||||
|                 config_filename = extra_configs[kwargs.pop('default_config_from_json')] | ||||
|                 config = load_json(config_filename) | ||||
|             try: | ||||
|                 nf0 = kwargs.pop('nf0') | ||||
|             except KeyError as exc:  # nf0 is expected for a fixed gain amp | ||||
| @@ -236,8 +246,14 @@ class Amp(_JsonThing): | ||||
|                     pass | ||||
|             nf_def = Model_fg(nf0) | ||||
|         elif type_def == 'advanced_model': | ||||
|             config = Path(filename).parent / kwargs.pop('advanced_config_from_json') | ||||
|             # use the user file name define in library instead of default config | ||||
|             config_filename = extra_configs[kwargs.pop('advanced_config_from_json')] | ||||
|             config = load_json(config_filename) | ||||
|         elif type_def == 'variable_gain': | ||||
|             if 'default_config_from_json' in kwargs: | ||||
|                 # use user defined default instead of DEFAULT_EDFA_CONFIG | ||||
|                 config_filename = extra_configs[kwargs.pop('default_config_from_json')] | ||||
|                 config = load_json(config_filename) | ||||
|             gain_min, gain_max = kwargs['gain_min'], kwargs['gain_flatmax'] | ||||
|             try:  # nf_min and nf_max are expected for a variable gain amp | ||||
|                 nf_min = kwargs.pop('nf_min') | ||||
| @@ -274,16 +290,15 @@ class Amp(_JsonThing): | ||||
|         else: | ||||
|             raise EquipmentConfigError(f'Edfa type_def {type_def} does not exist') | ||||
|  | ||||
|         json_data = load_json(config) | ||||
|         # raise an error if config does not contain f_min, f_max | ||||
|         if 'f_min' not in json_data or 'f_max' not in json_data: | ||||
|             raise EquipmentConfigError('default Edfa config does not contain f_min and f_max values.' | ||||
|         if 'f_min' not in config or 'f_max' not in config: | ||||
|             raise EquipmentConfigError(f'Config file {config_filename} does not contain f_min and f_max values.' | ||||
|                                        + ' Please correct file.') | ||||
|         # use f_min, f_max from kwargs | ||||
|         if 'f_min' in kwargs: | ||||
|             json_data.pop('f_min', None) | ||||
|             json_data.pop('f_max', None) | ||||
|         return cls(**{**kwargs, **json_data, | ||||
|             config.pop('f_min', None) | ||||
|             config.pop('f_max', None) | ||||
|         return cls(**{**kwargs, **config, | ||||
|                       'nf_model': nf_def, 'dual_stage_model': dual_stage_def, 'multi_band': amplifiers}) | ||||
|  | ||||
|  | ||||
| @@ -361,11 +376,60 @@ def _spectrum_from_json(json_data: dict): | ||||
|     return spectrum | ||||
|  | ||||
|  | ||||
| def load_equipment(filename: Path) -> dict: | ||||
| def merge_equipment(equipment: dict, additional_filenames: List[Path], extra_configs: Dict[str, Path]): | ||||
|     """Merge additional equipment libraries into the base equipment dictionary. | ||||
|     Typical case is the use of third party transceivers which are not part of a the supplier library. | ||||
|  | ||||
|     raise warnings if the same reference is used on two different libraries | ||||
|     """ | ||||
|     for filename in additional_filenames: | ||||
|         extra_eqpt = load_equipment(filename, extra_configs) | ||||
|         # populate with default eqpt to streamline loading | ||||
|         for eqpt_type, extra_items in extra_eqpt.items(): | ||||
|             for type_variety, item in extra_items.items(): | ||||
|                 if type_variety not in equipment[eqpt_type]: | ||||
|                     equipment[eqpt_type][type_variety] = item | ||||
|                 else: | ||||
|                     msg = f'\n\tEquipment file {filename.name}: duplicate equipment entry found: {eqpt_type}-{type_variety}\n' | ||||
|                     _logger.warning(msg) | ||||
|  | ||||
|  | ||||
| def load_equipments_and_configs(equipment_filename: Path, | ||||
|                                 extra_equipment_filenames: List[Path], | ||||
|                                 extra_config_filenames: List[Path]) -> dict: | ||||
|     """Loads equipment configurations and merge with additional equipment and configuration files. | ||||
|  | ||||
|     Args: | ||||
|         equipment_filename (Path): The path to the primary equipment configuration file. | ||||
|         extra_equipment_filenames (List[Path]): A list of paths to additional equipment configuration files to merge. | ||||
|         extra_config_filenames (List[Path]): A list of paths to additional configuration files to include. | ||||
|  | ||||
|     Returns: | ||||
|         dict: A dictionary containing the loaded equipment configurations. | ||||
|  | ||||
|     Notes: | ||||
|         If no equipment filename is provided, a default equipment configuration will be used. | ||||
|         Additional configurations from `extra_config_filenames` will override the default configurations. | ||||
|         If `extra_equipment_filenames` are provided, their contents will be merged into the loaded equipment. | ||||
|     """ | ||||
|     extra_configs = DEFAULT_EXTRA_CONFIG | ||||
|     if not equipment_filename: | ||||
|         equipment_filename = DEFAULT_EQPT_CONFIG | ||||
|     if extra_config_filenames: | ||||
|         extra_configs = {f.name: f for f in extra_config_filenames} | ||||
|         for k, v in DEFAULT_EXTRA_CONFIG.items(): | ||||
|             extra_configs[k] = v | ||||
|     equipment = load_equipment(equipment_filename, extra_configs) | ||||
|     if extra_equipment_filenames: | ||||
|         merge_equipment(equipment, extra_equipment_filenames, extra_configs) | ||||
|     return equipment | ||||
|  | ||||
|  | ||||
| def load_equipment(filename: Path, extra_configs: Dict[str, Path] = DEFAULT_EXTRA_CONFIG) -> dict: | ||||
|     """Load equipment, returns equipment dict | ||||
|     """ | ||||
|     json_data = load_json(filename) | ||||
|     return _equipment_from_json(json_data, filename) | ||||
|     return _equipment_from_json(json_data, extra_configs) | ||||
|  | ||||
|  | ||||
| def load_initial_spectrum(filename: Path) -> dict: | ||||
| @@ -375,12 +439,14 @@ def load_initial_spectrum(filename: Path) -> dict: | ||||
|     return _spectrum_from_json(json_data['spectrum']) | ||||
|  | ||||
|  | ||||
| def _update_dual_stage(equipment: dict) -> dict: | ||||
| def _update_dual_stage(equipment: dict): | ||||
|     """Update attributes of all dual stage amps with the preamp and booster attributes | ||||
|     (defined in the equipment dictionary) | ||||
|  | ||||
|     Returns the updated equiment dictionary | ||||
|     """ | ||||
|     if 'Edfa' not in equipment: | ||||
|         return | ||||
|     edfa_dict = equipment['Edfa'] | ||||
|     for edfa in edfa_dict.values(): | ||||
|         if edfa.type_def == 'dual_stage': | ||||
| @@ -399,9 +465,11 @@ def _update_dual_stage(equipment: dict) -> dict: | ||||
|     return equipment | ||||
|  | ||||
|  | ||||
| def _update_band(equipment: dict) -> dict: | ||||
| def _update_band(equipment: dict): | ||||
|     """Creates a list of bands for this amplifier, and remove other parameters which are not applicable | ||||
|     """ | ||||
|     if 'Edfa' not in equipment: | ||||
|         return | ||||
|     amp_dict = equipment['Edfa'] | ||||
|     for amplifier in amp_dict.values(): | ||||
|         if amplifier.type_def != 'multi_band': | ||||
| @@ -421,11 +489,11 @@ def _update_band(equipment: dict) -> dict: | ||||
|                         'nf_fit_coeff', 'nf_ripple', 'dgt', 'gain_ripple']: | ||||
|                 delattr(amplifier, key) | ||||
|  | ||||
|     return equipment | ||||
|  | ||||
|  | ||||
| def _roadm_restrictions_sanity_check(equipment: dict): | ||||
|     """verifies that booster and preamp restrictions specified in roadm equipment are listed in the edfa.""" | ||||
|     if 'Roadm' not in equipment: | ||||
|         return equipment | ||||
|     for roadm_type, roadm_eqpt in equipment['Roadm'].items(): | ||||
|         restrictions = roadm_eqpt.restrictions['booster_variety_list'] + \ | ||||
|             roadm_eqpt.restrictions['preamp_variety_list'] | ||||
| @@ -450,7 +518,20 @@ def _check_fiber_vs_raman_fiber(equipment: dict): | ||||
|                                            f'disagrees for "{attr}": {a} != {b}') | ||||
|  | ||||
|  | ||||
| def _equipment_from_json(json_data: dict, filename: Path) -> dict: | ||||
| def _si_sanity_check(equipment): | ||||
|     """Check that 'default' key correctly exists in SI list. (There must be at list one element and it must be default) | ||||
|     If not create one entry in the list with this key. | ||||
|     """ | ||||
|     if 'SI' not in equipment: | ||||
|         return | ||||
|     possible_SI = list(equipment['SI'].keys()) | ||||
|     if 'default' not in possible_SI: | ||||
|         # Use "default" key in the equipment, using the first listed keys | ||||
|         equipment['SI']['default'] = equipment['SI'][possible_SI[0]] | ||||
|         del equipment['SI'][possible_SI[0]] | ||||
|  | ||||
|  | ||||
| def _equipment_from_json(json_data: dict, extra_configs: Dict[str, Path]) -> dict: | ||||
|     """build global dictionnary eqpt_library that stores all eqpt characteristics: | ||||
|     edfa type type_variety, fiber type_variety | ||||
|     from the eqpt_config.json (filename parameter) | ||||
| @@ -465,7 +546,7 @@ def _equipment_from_json(json_data: dict, filename: Path) -> dict: | ||||
|         for entry in entries: | ||||
|             subkey = entry.get('type_variety', 'default') | ||||
|             if key == 'Edfa': | ||||
|                 equipment[key][subkey] = Amp.from_json(filename, **entry) | ||||
|                 equipment[key][subkey] = Amp.from_json(extra_configs, **entry) | ||||
|             elif key == 'Fiber': | ||||
|                 equipment[key][subkey] = Fiber(**entry) | ||||
|             elif key == 'Span': | ||||
| @@ -484,14 +565,10 @@ def _equipment_from_json(json_data: dict, filename: Path) -> dict: | ||||
|             else: | ||||
|                 raise EquipmentConfigError(f'Unrecognized network element type "{key}"') | ||||
|     _check_fiber_vs_raman_fiber(equipment) | ||||
|     equipment = _update_dual_stage(equipment) | ||||
|     equipment = _update_band(equipment) | ||||
|     _update_dual_stage(equipment) | ||||
|     _update_band(equipment) | ||||
|     _roadm_restrictions_sanity_check(equipment) | ||||
|     possible_SI = list(equipment['SI'].keys()) | ||||
|     if 'default' not in possible_SI: | ||||
|         # Use "default" key in the equipment, using the first listed keys | ||||
|         equipment['SI']['default'] = equipment['SI'][possible_SI[0]] | ||||
|         del equipment['SI'][possible_SI[0]] | ||||
|     _si_sanity_check(equipment) | ||||
|     return equipment | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -1,559 +0,0 @@ | ||||
| ********************************************* | ||||
| Equipment and Network description definitions | ||||
| ********************************************* | ||||
|  | ||||
| 1. Equipment description | ||||
| ######################## | ||||
|  | ||||
| Equipment description defines equipment types and those parameters. | ||||
| Description is made in JSON file with predefined structure. By default | ||||
| **gnpy-transmission-example** uses **eqpt_config.json** file and that | ||||
| can be changed with **-e** or **--equipment** command line parameter. | ||||
| Parsing of JSON file is made with | ||||
| **gnpy.core.equipment.load_equipment(equipment_description)** and return | ||||
| value is a dictionary of format **dict[‘equipment | ||||
| type’][‘subtype’]=object** | ||||
|  | ||||
| 1.1. Structure definition | ||||
| ************************* | ||||
|  | ||||
| 1.1.1. Equipment types | ||||
| ************************* | ||||
|  | ||||
| Every equipment type is defined in JSON root with according name and | ||||
| array of parameters as value. | ||||
|  | ||||
| .. code-block:: none | ||||
|  | ||||
|     {"Edfa": [...], | ||||
|     "Fiber": [...] | ||||
|     } | ||||
|  | ||||
|  | ||||
| 1.1.2. Equipment parameters and subtypes | ||||
| ***************************************** | ||||
|  | ||||
|  | ||||
| Array of parameters is a list of objects with unordered parameter name | ||||
| and its value definition. In case of multiple equipment subtypes each | ||||
| object contains **"type_variety":”type name”** name:value combination, | ||||
| if only one subtype exists **"type_variety"** name is not mandatory and | ||||
| it will be marked with **”default”** value. | ||||
|  | ||||
| .. code-block:: json | ||||
|  | ||||
|     {"Edfa": [{ | ||||
|                 "type_variety": "std_medium_gain", | ||||
|                 "type_def": "variable_gain", | ||||
|                 "gain_flatmax": 26, | ||||
|                 "gain_min": 15, | ||||
|                 "p_max": 23, | ||||
|                 "nf_min": 6, | ||||
|                 "nf_max": 10, | ||||
|                 "out_voa_auto": false, | ||||
|                 "allowed_for_design": true | ||||
|                 }, | ||||
|                 { | ||||
|                 "type_variety": "std_low_gain", | ||||
|                 "type_def": "variable_gain", | ||||
|                 "gain_flatmax": 16, | ||||
|                 "gain_min": 8, | ||||
|                 "p_max": 23, | ||||
|                 "nf_min": 6.5, | ||||
|                 "nf_max": 11, | ||||
|                 "out_voa_auto": false, | ||||
|                 "allowed_for_design": true | ||||
|                 } | ||||
|         ], | ||||
|     "Fiber": [{ | ||||
|                 "type_variety": "SSMF", | ||||
|                 "dispersion": 1.67e-05, | ||||
|                 "gamma": 0.00127 | ||||
|                 } | ||||
|         ] | ||||
|     } | ||||
|  | ||||
|  | ||||
|  | ||||
| 1.2. Equipment parameters by type | ||||
| ********************************* | ||||
|  | ||||
| 1.2.1. EDFA element | ||||
| ******************* | ||||
|  | ||||
| Four types of EDFA definition are possible. Description JSON file | ||||
| location is in **gnpy-transmission-example** folder: | ||||
|  | ||||
| -  Advanced – with JSON file describing gain/noise figure tilt and | ||||
|    gain/noise figure ripple. **"advanced_config_from_json"** value | ||||
|    contains filename. | ||||
|  | ||||
| .. code-block:: json-object | ||||
|  | ||||
|     "Edfa":[{ | ||||
|             "type_variety": "high_detail_model_example", | ||||
|             "gain_flatmax": 25, | ||||
|             "gain_min": 15, | ||||
|             "p_max": 21, | ||||
|             "advanced_config_from_json": "std_medium_gain_advanced_config.json", | ||||
|             "out_voa_auto": false, | ||||
|             "allowed_for_design": false | ||||
|             } | ||||
|         ] | ||||
|  | ||||
| -  Variable gain – with JSON file describing gain figure tilt and gain/noise | ||||
|    figure ripple. **”default_edfa_config.json”** as source file. | ||||
|  | ||||
| .. code-block:: json-object | ||||
|  | ||||
|     "Edfa":[{ | ||||
|             "type_variety": "std_medium_gain", | ||||
|             "type_def": "variable_gain", | ||||
|             "gain_flatmax": 26, | ||||
|             "gain_min": 15, | ||||
|             "p_max": 23, | ||||
|             "nf_min": 6, | ||||
|             "nf_max": 10, | ||||
|             "out_voa_auto": false, | ||||
|             "allowed_for_design": true | ||||
|             } | ||||
|         ] | ||||
|  | ||||
| -  Fixed gain – with JSON file describing gain figure tilt and gain/noise | ||||
|    figure ripple. **”default_edfa_config.json”** as source file. | ||||
|  | ||||
| .. code-block:: json-object | ||||
|  | ||||
|     "Edfa":[{ | ||||
|             "type_variety": "std_fixed_gain", | ||||
|             "type_def": "fixed_gain", | ||||
|             "gain_flatmax": 21, | ||||
|             "gain_min": 20, | ||||
|             "p_max": 21, | ||||
|             "nf0": 5.5, | ||||
|             "allowed_for_design": false | ||||
|             } | ||||
|         ] | ||||
|  | ||||
| - openroadm – with JSON file describing gain figure tilt and gain/noise | ||||
|    figure ripple. **”default_edfa_config.json”** as source file.  | ||||
|  | ||||
| .. code-block:: json-object | ||||
|  | ||||
|     "Edfa":[{ | ||||
|             "type_variety": "openroadm_ila_low_noise", | ||||
|             "type_def": "openroadm", | ||||
|             "gain_flatmax": 27, | ||||
|             "gain_min": 12, | ||||
|             "p_max": 22, | ||||
|             "nf_coef": [-8.104e-4,-6.221e-2,-5.889e-1,37.62], | ||||
|             "allowed_for_design": false | ||||
|             } | ||||
|         ] | ||||
|  | ||||
| 1.2.2. Fiber element | ||||
| ******************** | ||||
|  | ||||
| Fiber element with its parameters: | ||||
|  | ||||
| .. code-block:: json-object | ||||
|  | ||||
|     "Fiber":[{ | ||||
|             "type_variety": "SSMF", | ||||
|             "dispersion": 1.67e-05, | ||||
|             "gamma": 0.00127 | ||||
|             } | ||||
|         ] | ||||
|  | ||||
| RamanFiber element | ||||
| ****************** | ||||
|  | ||||
| A special variant of the regular ``Fiber`` where the simulation engine accounts for the Raman effect. | ||||
| The newly added parameters are nested in the ``raman_efficiency`` dictionary. | ||||
| Its shape corresponds to typical properties of silica. | ||||
| More details are available from :cite:`curri_merit_2016`. | ||||
|  | ||||
| The ``cr`` property is the normailzed Raman efficiency, so it is is (almost) independent of the fiber type, while the coefficient actually giving Raman gain is g_R=C_R/Aeff. | ||||
|  | ||||
| The ``frequency_offset`` represents the spectral difference between the pumping photon and the one receiving energy. | ||||
|  | ||||
| .. code-block:: json-object | ||||
|  | ||||
|     "RamanFiber":[{ | ||||
|       "type_variety": "SSMF", | ||||
|       "dispersion": 1.67e-05, | ||||
|       "gamma": 0.00127, | ||||
|       "raman_efficiency": { | ||||
|         "cr":[ | ||||
|             0, 9.4E-06, 2.92E-05, 4.88E-05, 6.82E-05, 8.31E-05, 9.4E-05, 0.0001014, 0.0001069, 0.0001119, | ||||
|             0.0001217, 0.0001268, 0.0001365, 0.000149, 0.000165, 0.000181, 0.0001977, 0.0002192, 0.0002469, | ||||
|             0.0002749, 0.0002999, 0.0003206, 0.0003405, 0.0003592, 0.000374, 0.0003826, 0.0003841, 0.0003826, | ||||
|             0.0003802, 0.0003756, 0.0003549, 0.0003795, 0.000344, 0.0002933, 0.0002024, 0.0001158, 8.46E-05, | ||||
|             7.14E-05, 6.86E-05, 8.5E-05, 8.93E-05, 9.01E-05, 8.15E-05, 6.67E-05, 4.37E-05, 3.28E-05, 2.96E-05, | ||||
|             2.65E-05, 2.57E-05, 2.81E-05, 3.08E-05, 3.67E-05, 5.85E-05, 6.63E-05, 6.36E-05, 5.5E-05, 4.06E-05, | ||||
|             2.77E-05, 2.42E-05, 1.87E-05, 1.6E-05, 1.4E-05, 1.13E-05, 1.05E-05, 9.8E-06, 9.8E-06, 1.13E-05, | ||||
|             1.64E-05, 1.95E-05, 2.38E-05, 2.26E-05, 2.03E-05, 1.48E-05, 1.09E-05, 9.8E-06, 1.05E-05, 1.17E-05, | ||||
|             1.25E-05, 1.21E-05, 1.09E-05, 9.8E-06, 8.2E-06, 6.6E-06, 4.7E-06, 2.7E-06, 1.9E-06, 1.2E-06, 4E-07, | ||||
|             2E-07, 1E-07 | ||||
|         ], | ||||
|         "frequency_offset":[ | ||||
|           0, 0.5e12, 1e12, 1.5e12, 2e12, 2.5e12, 3e12, 3.5e12, 4e12, 4.5e12, 5e12, 5.5e12, 6e12, 6.5e12, 7e12, | ||||
|           7.5e12, 8e12, 8.5e12, 9e12, 9.5e12, 10e12, 10.5e12, 11e12, 11.5e12, 12e12, 12.5e12, 12.75e12, | ||||
|           13e12, 13.25e12, 13.5e12, 14e12, 14.5e12, 14.75e12, 15e12, 15.5e12, 16e12, 16.5e12, 17e12, | ||||
|           17.5e12, 18e12, 18.25e12, 18.5e12, 18.75e12, 19e12, 19.5e12, 20e12, 20.5e12, 21e12, 21.5e12, | ||||
|           22e12, 22.5e12, 23e12, 23.5e12, 24e12, 24.5e12, 25e12, 25.5e12, 26e12, 26.5e12, 27e12, 27.5e12, 28e12, | ||||
|           28.5e12, 29e12, 29.5e12, 30e12, 30.5e12, 31e12, 31.5e12, 32e12, 32.5e12, 33e12, 33.5e12, 34e12, 34.5e12, | ||||
|           35e12, 35.5e12, 36e12, 36.5e12, 37e12, 37.5e12, 38e12, 38.5e12, 39e12, 39.5e12, 40e12, 40.5e12, 41e12, | ||||
|           41.5e12, 42e12 | ||||
|         ] | ||||
|         } | ||||
|       } | ||||
|     ] | ||||
|  | ||||
|  | ||||
| 1.2.3 Roadm element | ||||
| ******************* | ||||
|  | ||||
| Roadm element with its parameters: | ||||
|  | ||||
| .. code-block:: json-object | ||||
|  | ||||
|       "Roadms":[{ | ||||
|             "gain_mode_default_loss": 20, | ||||
|             "power_mode_pout_target": -20, | ||||
|             "add_drop_osnr": 38 | ||||
|             } | ||||
|         ] | ||||
|  | ||||
| 1.2.3. Spans element | ||||
| ******************** | ||||
|  | ||||
| Spans element with its parameters: | ||||
|  | ||||
| .. code-block:: json-object | ||||
|  | ||||
|     "Spans":[{ | ||||
|             "power_mode":true, | ||||
|             "delta_power_range_db": [0,0,0.5], | ||||
|             "max_length": 150, | ||||
|             "length_units": "km", | ||||
|             "max_loss": 28, | ||||
|             "padding": 10, | ||||
|             "EOL": 0, | ||||
|             "con_in": 0, | ||||
|             "con_out": 0 | ||||
|             } | ||||
|         ] | ||||
|  | ||||
|  | ||||
| 1.2.4. Spectral Information | ||||
| *************************** | ||||
|  | ||||
| Spectral information with its parameters: | ||||
|  | ||||
| .. code-block:: json-object | ||||
|  | ||||
|     "SI":[{ | ||||
|             "f_min": 191.3e12, | ||||
|             "baud_rate": 32e9, | ||||
|             "f_max":195.1e12, | ||||
|             "spacing": 50e9, | ||||
|             "power_dbm": 0, | ||||
|             "power_range_db": [0,0,0.5], | ||||
|             "roll_off": 0.15, | ||||
|             "tx_osnr": 40, | ||||
|             "sys_margins": 0 | ||||
|             } | ||||
|         ] | ||||
|  | ||||
|  | ||||
| 1.2.5. Transceiver element | ||||
| ************************** | ||||
|  | ||||
| Transceiver element with its parameters. **”mode”** can contain multiple | ||||
| Transceiver operation formats. | ||||
|  | ||||
| Note that ``OSNR`` parameter refers to the receiver's minimal OSNR threshold for a given mode. | ||||
|  | ||||
| .. code-block:: json-object | ||||
|  | ||||
|     "Transceiver":[{ | ||||
|                     "frequency":{ | ||||
|                                 "min": 191.35e12, | ||||
|                                 "max": 196.1e12 | ||||
|                                 }, | ||||
|                     "mode":[ | ||||
|                             { | ||||
|                                "format": "mode 1", | ||||
|                                "baud_rate": 32e9, | ||||
|                                "OSNR": 11, | ||||
|                                "bit_rate": 100e9, | ||||
|                                "roll_off": 0.15, | ||||
|                                "tx_osnr": 40, | ||||
|                                "min_spacing": 37.5e9, | ||||
|                                "cost":1 | ||||
|                             }, | ||||
|                             { | ||||
|                               "format": "mode 2", | ||||
|                                "baud_rate": 66e9, | ||||
|                                "OSNR": 15, | ||||
|                                "bit_rate": 200e9, | ||||
|                                "roll_off": 0.15, | ||||
|                                "tx_osnr": 40, | ||||
|                                "min_spacing": 75e9, | ||||
|                                "cost":1 | ||||
|                             } | ||||
|                     ] | ||||
|                 } | ||||
|         ] | ||||
|  | ||||
| *********************** | ||||
| 2. Network description | ||||
| *********************** | ||||
|  | ||||
| Network description defines network elements with additional to | ||||
| equipment description parameters, metadata and elements interconnection. | ||||
| Description is made in JSON file with predefined structure. By default | ||||
| **gnpy-transmission-example** uses **edfa_example_network.json** file | ||||
| and can be changed from command line. Parsing of JSON file is made with | ||||
| **gnpy.core.network.load_network(network_description, | ||||
| equipment_description)** and return value is **DiGraph** object which | ||||
| mimics network description. | ||||
|  | ||||
| 2.1. Structure definition | ||||
| ########################## | ||||
|  | ||||
| 2.1.1. File root structure | ||||
| *************************** | ||||
|  | ||||
| Network description JSON file root consist of three unordered parts: | ||||
|  | ||||
| -  network_name – name of described network or service, is not used as | ||||
|    of now | ||||
|  | ||||
| -  elements - contains array of network element objects with their | ||||
|    respective parameters | ||||
|  | ||||
| -  connections – contains array of unidirectional connection objects | ||||
|  | ||||
| .. code-block:: none | ||||
|  | ||||
|     {"network_name": "Example Network", | ||||
|     "elements": [{...}, | ||||
|                 {...} | ||||
|                 ], | ||||
|     "connections": [{...}, | ||||
|                     {...} | ||||
|                     ] | ||||
|     } | ||||
|  | ||||
|  | ||||
| 2.1.2. Elements parameters and subtypes | ||||
| **************************************** | ||||
|  | ||||
| Array of network element objects consist of unordered parameter names | ||||
| and those values. In case of **"type_variety"** absence | ||||
| **"type_variety":”default”** name:value combination is used. As of the | ||||
| moment, existence of used **"type_variety"** in equipment description is | ||||
| obligatory. | ||||
|  | ||||
| 2.2. Element parameters by type | ||||
| ********************************* | ||||
|  | ||||
| 2.2.1. Transceiver element | ||||
| *************************** | ||||
|  | ||||
| Transceiver element with its parameters. | ||||
|  | ||||
| .. code-block:: json | ||||
|  | ||||
|     {"uid": "trx Site_A", | ||||
|     "metadata": { | ||||
|                 "location": { | ||||
|                             "city": "Site_A", | ||||
|                             "region": "", | ||||
|                             "latitude": 0, | ||||
|                             "longitude": 0 | ||||
|                             } | ||||
|                 }, | ||||
|     "type": "Transceiver" | ||||
|     } | ||||
|  | ||||
|  | ||||
|  | ||||
| 2.2.2. ROADM element | ||||
| ********************* | ||||
|  | ||||
| ROADM element with its parameters. **“params”** is optional, if not used | ||||
| default loss value of 20dB is used. | ||||
|  | ||||
| .. code-block:: json | ||||
|  | ||||
|     {"uid": "roadm Site_A", | ||||
|     "metadata": { | ||||
|                 "location": { | ||||
|                             "city": "Site_A", | ||||
|                             "region": "", | ||||
|                             "latitude": 0, | ||||
|                             "longitude": 0 | ||||
|                             } | ||||
|                 }, | ||||
|     "type": "Roadm", | ||||
|     "params": { | ||||
|                 "loss": 17 | ||||
|             } | ||||
|     } | ||||
|  | ||||
|  | ||||
| 2.2.3. Fused element | ||||
| ********************* | ||||
|  | ||||
| Fused element with its parameters. **“params”** is optional, if not used | ||||
| default loss value of 1dB is used. | ||||
|  | ||||
| .. code-block:: json | ||||
|  | ||||
|     {"uid": "ingress fused spans in Site_B", | ||||
|     "metadata": { | ||||
|                 "location": { | ||||
|                             "city": "Site_B", | ||||
|                             "region": "", | ||||
|                             "latitude": 0, | ||||
|                             "longitude": 0 | ||||
|                             } | ||||
|                 }, | ||||
|     "type": "Fused", | ||||
|     "params": { | ||||
|                 "loss": 0.5 | ||||
|         } | ||||
|     } | ||||
|  | ||||
|  | ||||
| 2.2.4. Fiber element | ||||
| ********************* | ||||
|  | ||||
| Fiber element with its parameters. | ||||
|  | ||||
| .. code-block:: json | ||||
|  | ||||
|     {"uid": "fiber (Site_A \\u2192 Site_B)", | ||||
|     "metadata": { | ||||
|                 "location": { | ||||
|                             "city": "", | ||||
|                             "region": "", | ||||
|                             "latitude": 0.0, | ||||
|                             "longitude": 0.0 | ||||
|                             } | ||||
|                 }, | ||||
|     "type": "Fiber", | ||||
|     "type_variety": "SSMF", | ||||
|     "params": { | ||||
|                 "length": 40.0, | ||||
|                 "length_units": "km", | ||||
|                 "loss_coef": 0.2 | ||||
|                 } | ||||
|     } | ||||
|  | ||||
| 2.2.5. RamanFiber element | ||||
| ************************* | ||||
|  | ||||
| .. code-block:: json | ||||
|  | ||||
|     { | ||||
|       "uid": "Span1", | ||||
|       "type": "RamanFiber", | ||||
|       "type_variety": "SSMF", | ||||
|       "operational": { | ||||
|         "temperature": 283, | ||||
|         "raman_pumps": [ | ||||
|           { | ||||
|             "power": 200e-3, | ||||
|             "frequency": 205e12, | ||||
|             "propagation_direction": "counterprop" | ||||
|           }, | ||||
|           { | ||||
|             "power": 206e-3, | ||||
|             "frequency": 201e12, | ||||
|             "propagation_direction": "counterprop" | ||||
|           } | ||||
|         ] | ||||
|       }, | ||||
|       "params": { | ||||
|         "type_variety": "SSMF", | ||||
|         "length": 80.0, | ||||
|         "loss_coef": 0.2, | ||||
|         "length_units": "km", | ||||
|         "att_in": 0, | ||||
|         "con_in": 0.5, | ||||
|         "con_out": 0.5 | ||||
|       }, | ||||
|       "metadata": { | ||||
|         "location": { | ||||
|           "latitude": 1, | ||||
|           "longitude": 0, | ||||
|           "city": null, | ||||
|           "region": "" | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|  | ||||
|  | ||||
| 2.2.6. EDFA element | ||||
| ******************** | ||||
|  | ||||
| EDFA element with its parameters. | ||||
|  | ||||
| .. code-block:: json | ||||
|  | ||||
|     {"uid": "Edfa1", | ||||
|     "type": "Edfa", | ||||
|     "type_variety": "std_low_gain", | ||||
|     "operational": { | ||||
|                     "gain_target": 16, | ||||
|                     "tilt_target": 0 | ||||
|                     }, | ||||
|     "metadata": { | ||||
|                 "location": { | ||||
|                             "city": "Site_A", | ||||
|                             "region": "", | ||||
|                             "latitude": 2, | ||||
|                             "longitude": 0 | ||||
|                             } | ||||
|                 } | ||||
|     } | ||||
|  | ||||
| 2.3. Connections objects | ||||
| ************************* | ||||
|  | ||||
| Each unidirectional connection object in connections array consist of | ||||
| two unordered **”from_node”** and **”to_node”** name pair with values | ||||
| corresponding to element **”uid”** | ||||
|  | ||||
| .. code-block:: json | ||||
|  | ||||
|     {"from_node": "roadm Site_C", | ||||
|     "to_node": "trx Site_C" | ||||
|     } | ||||
|  | ||||
| ************************ | ||||
| 3. Simulation Parameters | ||||
| ************************ | ||||
|  | ||||
| Additional details of the simulation are controlled via ``sim_params.json``: | ||||
|  | ||||
| .. code-block:: json | ||||
|  | ||||
|   { | ||||
|     "raman_parameters": { | ||||
|       "flag_raman": true, | ||||
|       "space_resolution": 10e3, | ||||
|       "tolerance": 1e-8 | ||||
|     }, | ||||
|     "nli_parameters": { | ||||
|       "nli_method_name": "ggn_spectrally_separated", | ||||
|       "wdm_grid_size": 50e9, | ||||
|       "dispersion_tolerance": 1, | ||||
|       "phase_shift_tolerance": 0.1, | ||||
|       "computed_channels": [1, 18, 37, 56, 75] | ||||
|     } | ||||
|   } | ||||
							
								
								
									
										31
									
								
								tests/data/copy_default_edfa_config.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								tests/data/copy_default_edfa_config.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | ||||
| { | ||||
|   "nf_ripple": [ | ||||
|       0.0 | ||||
|   ], | ||||
|   "gain_ripple": [ | ||||
|       0.0 | ||||
|   ], | ||||
|   "f_min": 191.275e12, | ||||
|   "f_max": 196.125e12, | ||||
|   "dgt": [ | ||||
|       1.0, 1.017807767853702, 1.0356155337864215, 1.0534217504465226, 1.0712204022764056, 1.0895983485572227, | ||||
|       1.108555289615659, 1.1280891949729075, 1.1476135933863398, 1.1672278304018044, 1.1869318618366975, | ||||
|       1.2067249615595257, 1.2264996957264114, 1.2428104897182262, 1.2556591482982988, 1.2650555289898042, | ||||
|       1.2744470198196236, 1.2838336236692311, 1.2932153453410835, 1.3040618749785347, 1.316383926863083, | ||||
|       1.3301807335621048, 1.3439818461440451, 1.3598972673004606, 1.3779439775587023, 1.3981208704326855, | ||||
|       1.418273806730323, 1.4340878115214444, 1.445565137158368, 1.45273959485914, 1.4599103316162523, | ||||
|       1.4670307626366115, 1.474100442252211, 1.48111939735681, 1.488134243479226, 1.495145456062699, | ||||
|       1.502153039909686, 1.5097346239790443, 1.5178910621476225, 1.5266220576235803, 1.5353620432989845, | ||||
|       1.545374152761467, 1.5566577309558969, 1.569199764184379, 1.5817353179379183, 1.5986915141218316, | ||||
|       1.6201194134191075, 1.6460167077689267, 1.6719047669939942, 1.6918150918099673, 1.7057507692361864, | ||||
|       1.7137640932265894, 1.7217732861435076, 1.7297783508684146, 1.737780757913635, 1.7459181197626403, | ||||
|       1.7541903672600494, 1.7625959636196327, 1.7709972329654864, 1.7793941781790852, 1.7877868031023945, | ||||
|       1.7961751115773796, 1.8045606557581335, 1.8139629377087627, 1.824381436842932, 1.835814081380705, | ||||
|       1.847275503201129, 1.862235672444246, 1.8806927939516411, 1.9026104247588487, 1.9245345552113182, | ||||
|       1.9482128147680253, 1.9736443063300082, 2.0008103857988204, 2.0279625371819305, 2.055100772005235, | ||||
|       2.082225099873648, 2.1183028432496016, 2.16337565384239, 2.2174389328192197, 2.271520771371253, | ||||
|       2.322373696229342, 2.3699990328716107, 2.414398437185221, 2.4587748041127506, 2.499446286796604, | ||||
|       2.5364027376452056, 2.5696460593920065, 2.602860350286428, 2.630396440815385, 2.6521732021128046, | ||||
|       2.6681935771243177, 2.6841217449620203, 2.6947834587664494, 2.705443819238505, 2.714526681131686 | ||||
|   ] | ||||
| } | ||||
| @@ -1,298 +0,0 @@ | ||||
| { | ||||
|     "f_min": 191.275e12, | ||||
|     "f_max": 196.125e12, | ||||
|     "nf_ripple": [ | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0 | ||||
|     ], | ||||
|     "gain_ripple": [ | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0 | ||||
|     ], | ||||
|     "dgt": [ | ||||
|         1.0, | ||||
|         1.017807767853702, | ||||
|         1.0356155337864215, | ||||
|         1.0534217504465226, | ||||
|         1.0712204022764056, | ||||
|         1.0895983485572227, | ||||
|         1.108555289615659, | ||||
|         1.1280891949729075, | ||||
|         1.1476135933863398, | ||||
|         1.1672278304018044, | ||||
|         1.1869318618366975, | ||||
|         1.2067249615595257, | ||||
|         1.2264996957264114, | ||||
|         1.2428104897182262, | ||||
|         1.2556591482982988, | ||||
|         1.2650555289898042, | ||||
|         1.2744470198196236, | ||||
|         1.2838336236692311, | ||||
|         1.2932153453410835, | ||||
|         1.3040618749785347, | ||||
|         1.316383926863083, | ||||
|         1.3301807335621048, | ||||
|         1.3439818461440451, | ||||
|         1.3598972673004606, | ||||
|         1.3779439775587023, | ||||
|         1.3981208704326855, | ||||
|         1.418273806730323, | ||||
|         1.4340878115214444, | ||||
|         1.445565137158368, | ||||
|         1.45273959485914, | ||||
|         1.4599103316162523, | ||||
|         1.4670307626366115, | ||||
|         1.474100442252211, | ||||
|         1.48111939735681, | ||||
|         1.488134243479226, | ||||
|         1.495145456062699, | ||||
|         1.502153039909686, | ||||
|         1.5097346239790443, | ||||
|         1.5178910621476225, | ||||
|         1.5266220576235803, | ||||
|         1.5353620432989845, | ||||
|         1.545374152761467, | ||||
|         1.5566577309558969, | ||||
|         1.569199764184379, | ||||
|         1.5817353179379183, | ||||
|         1.5986915141218316, | ||||
|         1.6201194134191075, | ||||
|         1.6460167077689267, | ||||
|         1.6719047669939942, | ||||
|         1.6918150918099673, | ||||
|         1.7057507692361864, | ||||
|         1.7137640932265894, | ||||
|         1.7217732861435076, | ||||
|         1.7297783508684146, | ||||
|         1.737780757913635, | ||||
|         1.7459181197626403, | ||||
|         1.7541903672600494, | ||||
|         1.7625959636196327, | ||||
|         1.7709972329654864, | ||||
|         1.7793941781790852, | ||||
|         1.7877868031023945, | ||||
|         1.7961751115773796, | ||||
|         1.8045606557581335, | ||||
|         1.8139629377087627, | ||||
|         1.824381436842932, | ||||
|         1.835814081380705, | ||||
|         1.847275503201129, | ||||
|         1.862235672444246, | ||||
|         1.8806927939516411, | ||||
|         1.9026104247588487, | ||||
|         1.9245345552113182, | ||||
|         1.9482128147680253, | ||||
|         1.9736443063300082, | ||||
|         2.0008103857988204, | ||||
|         2.0279625371819305, | ||||
|         2.055100772005235, | ||||
|         2.082225099873648, | ||||
|         2.1183028432496016, | ||||
|         2.16337565384239, | ||||
|         2.2174389328192197, | ||||
|         2.271520771371253, | ||||
|         2.322373696229342, | ||||
|         2.3699990328716107, | ||||
|         2.414398437185221, | ||||
|         2.4587748041127506, | ||||
|         2.499446286796604, | ||||
|         2.5364027376452056, | ||||
|         2.5696460593920065, | ||||
|         2.602860350286428, | ||||
|         2.630396440815385, | ||||
|         2.6521732021128046, | ||||
|         2.6681935771243177, | ||||
|         2.6841217449620203, | ||||
|         2.6947834587664494, | ||||
|         2.705443819238505, | ||||
|         2.714526681131686 | ||||
|     ] | ||||
| } | ||||
							
								
								
									
										37
									
								
								tests/data/extra_eqpt_config.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								tests/data/extra_eqpt_config.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | ||||
| { | ||||
|   "Transceiver": [ | ||||
|     { | ||||
|       "type_variety": "ZR400G", | ||||
|       "frequency": { | ||||
|         "min": 191.35e12, | ||||
|         "max": 196.1e12 | ||||
|       }, | ||||
|       "mode": [ | ||||
|         { | ||||
|           "format": "400G", | ||||
|           "baud_rate": 60e9, | ||||
|           "OSNR": 24, | ||||
|           "bit_rate": 400e9, | ||||
|           "roll_off": 0.2, | ||||
|           "tx_osnr": 38, | ||||
|           "min_spacing": 75e9, | ||||
|           "cost": 1 | ||||
|         } | ||||
|       ] | ||||
|     } | ||||
|   ], | ||||
|   "Edfa": [ | ||||
|     { | ||||
|       "type_variety": "user_defined_default_amplifier", | ||||
|       "type_def": "variable_gain", | ||||
|       "gain_flatmax": 25, | ||||
|       "gain_min": 15, | ||||
|       "p_max": 21, | ||||
|       "nf_min": 6, | ||||
|       "nf_max": 10, | ||||
|       "advanced_config_from_json": "default_edfa_config.json", | ||||
|       "out_voa_auto": false, | ||||
|       "allowed_for_design": false | ||||
|     } | ||||
|   ] | ||||
| } | ||||
							
								
								
									
										154
									
								
								tests/data/user_edfa_config.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										154
									
								
								tests/data/user_edfa_config.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,154 @@ | ||||
| { | ||||
|     "f_min": 193.0e12, | ||||
|     "f_max": 195.0e12, | ||||
|     "nf_ripple": [ | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0, | ||||
|         0.0 | ||||
|     ], | ||||
|     "gain_ripple": [ | ||||
|         -0.15656302345061, | ||||
|         -0.22244242043552, | ||||
|         -0.25188965661642, | ||||
|         -0.23575900335007, | ||||
|         -0.20897508375209, | ||||
|         -0.19440221943049, | ||||
|         -0.18324644053602, | ||||
|         -0.18053287269681, | ||||
|         -0.17113588777219, | ||||
|         -0.15460322445561, | ||||
|         -0.13550774706866, | ||||
|         -0.10606051088777, | ||||
|         -0.0765630234506, | ||||
|         -0.04962835008375, | ||||
|         -0.01319618927973, | ||||
|         0.01027114740367, | ||||
|         0.03378873534338, | ||||
|         0.04961788107202, | ||||
|         0.04494451423784, | ||||
|         0.0399193886097, | ||||
|         0.01584903685091, | ||||
|         -0.00420121440538, | ||||
|         -0.01847257118928, | ||||
|         -0.02475397822447, | ||||
|         -0.01053287269681, | ||||
|         0.01509526800668, | ||||
|         0.05921587102177, | ||||
|         0.1191656197655, | ||||
|         0.18147717755444, | ||||
|         0.23579878559464, | ||||
|         0.26941687604691, | ||||
|         0.27836159966498, | ||||
|         0.26956762981574, | ||||
|         0.23826109715241, | ||||
|         0.18936662479061, | ||||
|         0.1204721524288, | ||||
|         0.0453465242881, | ||||
|         -0.00877407872698, | ||||
|         -0.02199015912898, | ||||
|         0.00107516750419, | ||||
|         0.02795958961474, | ||||
|         0.02740682579566, | ||||
|         -0.01028161641541, | ||||
|         -0.05982935510889, | ||||
|         -0.06701528475711, | ||||
|         0.00223094639866, | ||||
|         0.14157768006701, | ||||
|         0.15017064489112 | ||||
|     ], | ||||
|     "dgt": [ | ||||
|         2.714526681131686, | ||||
|         2.6947834587664494, | ||||
|         2.630396440815385, | ||||
|         2.602860350286428, | ||||
|         2.5696460593920065, | ||||
|         2.5364027376452056, | ||||
|         2.414398437185221, | ||||
|         2.2174389328192197, | ||||
|         2.16337565384239, | ||||
|         2.1183028432496016, | ||||
|         2.082225099873648, | ||||
|         2.0279625371819305, | ||||
|         1.9245345552113182, | ||||
|         1.8806927939516411, | ||||
|         1.862235672444246, | ||||
|         1.847275503201129, | ||||
|         1.8045606557581335, | ||||
|         1.7793941781790852, | ||||
|         1.737780757913635, | ||||
|         1.7297783508684146, | ||||
|         1.7057507692361864, | ||||
|         1.6201194134191075, | ||||
|         1.5986915141218316, | ||||
|         1.5817353179379183, | ||||
|         1.5353620432989845, | ||||
|         1.5097346239790443, | ||||
|         1.4670307626366115, | ||||
|         1.445565137158368, | ||||
|         1.4340878115214444, | ||||
|         1.418273806730323, | ||||
|         1.3981208704326855, | ||||
|         1.3779439775587023, | ||||
|         1.3598972673004606, | ||||
|         1.3439818461440451, | ||||
|         1.316383926863083, | ||||
|         1.2932153453410835, | ||||
|         1.2744470198196236, | ||||
|         1.2650555289898042, | ||||
|         1.2556591482982988, | ||||
|         1.2428104897182262, | ||||
|         1.1672278304018044, | ||||
|         1.1476135933863398, | ||||
|         1.1280891949729075, | ||||
|         1.108555289615659, | ||||
|         1.0895983485572227, | ||||
|         1.0712204022764056, | ||||
|         1.017807767853702, | ||||
|         1.0 | ||||
|     ] | ||||
| } | ||||
							
								
								
									
										33
									
								
								tests/invocation/logs_path_requests_run_extra_equipment
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								tests/invocation/logs_path_requests_run_extra_equipment
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | ||||
| INFO     gnpy.tools.cli_examples:cli_examples.py Computing path requests service_pluggable.json into JSON format | ||||
| WARNING  gnpy.tools.json_io:json_io.py  | ||||
| 	WARNING missing type_variety attribute in eqpt_config.json[Roadm] | ||||
| 	default value is type_variety = default | ||||
|  | ||||
| WARNING  gnpy.tools.json_io:json_io.py  | ||||
| 	Equipment file extra_eqpt_config.json: duplicate equipment entry found: Transceiver-ZR400G | ||||
|  | ||||
| INFO     gnpy.tools.worker_utils:worker_utils.py List of disjunctions: | ||||
| [] | ||||
| INFO     gnpy.tools.worker_utils:worker_utils.py Aggregating similar requests | ||||
| INFO     gnpy.tools.worker_utils:worker_utils.py The following services have been requested: | ||||
| [PathRequest 0 | ||||
| 	source: 	trx Brest_KLA | ||||
| 	destination:	trx Lannion_CAS | ||||
| 	trx type:	ZR400G | ||||
| 	trx mode:	SFF-ID:70 | ||||
| 	baud_rate:	60.13854679800001 Gbaud | ||||
| 	bit_rate:	400.0 Gb/s | ||||
| 	spacing:	100.0 GHz | ||||
| 	power:  	0.0 dBm | ||||
| 	tx_power_dbm:  	1.76 dBm | ||||
| 	nb channels: 	48 | ||||
| 	path_bandwidth: 	400.0 Gbit/s | ||||
| 	nodes-list:	[] | ||||
| 	loose-list:	[] | ||||
| ] | ||||
| INFO     gnpy.tools.worker_utils:worker_utils.py Propagating on selected path | ||||
| INFO     gnpy.topology.request:request.py  | ||||
| 	request 0 | ||||
| 	Computing path from trx Brest_KLA to trx Lannion_CAS | ||||
| 	with path constraint: ['trx Brest_KLA', 'trx Lannion_CAS'] | ||||
| 	Computed path (roadms):['roadm Brest_KLA', 'roadm Lannion_CAS'] | ||||
							
								
								
									
										22
									
								
								tests/invocation/path_requests_run_extra_equipment
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								tests/invocation/path_requests_run_extra_equipment
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| [1;34;40mList of disjunctions[0m | ||||
| [] | ||||
| [1;34;40mThe following services have been requested:[0m | ||||
| [PathRequest 0 | ||||
| 	source: 	trx Brest_KLA | ||||
| 	destination:	trx Lannion_CAS | ||||
| 	trx type:	ZR400G | ||||
| 	trx mode:	SFF-ID:70 | ||||
| 	baud_rate:	60.13854679800001 Gbaud | ||||
| 	bit_rate:	400.0 Gb/s | ||||
| 	spacing:	100.0 GHz | ||||
| 	power:  	0.0 dBm | ||||
| 	tx_power_dbm:  	1.76 dBm | ||||
| 	nb channels: 	48 | ||||
| 	path_bandwidth: 	400.0 Gbit/s | ||||
| 	nodes-list:	[] | ||||
| 	loose-list:	[] | ||||
| ] | ||||
| [1;34;40mResult summary[0m | ||||
| req id   demand                              GSNR@bandwidth A-Z (Z-A)   GSNR@0.1nm A-Z (Z-A)        Receiver minOSNR               mode                    Gbit/s              nb of tsp pairs      N,M or blocking reason  | ||||
| 0       trx Brest_KLA to trx Lannion_CAS :             21.3                    28.12                      26                   SFF-ID:70                  400.0                      1                   ([-280],[8])       | ||||
| [1;33;40mResult summary shows mean GSNR and OSNR (average over all channels)[0m | ||||
| @@ -13,10 +13,12 @@ from gnpy.tools.json_io import load_network, load_equipment, load_json, _equipme | ||||
| from pathlib import Path | ||||
| import pytest | ||||
|  | ||||
| TEST_DIR = Path(__file__).parent | ||||
| TEST_DIR =  Path(__file__).parent | ||||
| DATA_DIR = TEST_DIR / 'data' | ||||
| test_network = DATA_DIR / 'test_network.json' | ||||
| eqpt_library = DATA_DIR / 'eqpt_config.json' | ||||
| extra_configs = {"std_medium_gain_advanced_config.json": DATA_DIR / "std_medium_gain_advanced_config.json", | ||||
|                  "Juniper-BoosterHG.json": DATA_DIR / "Juniper-BoosterHG.json"} | ||||
|  | ||||
| # TODO in elements.py code: pytests doesn't pass with 1 channel: interpolate fail | ||||
|  | ||||
| @@ -39,7 +41,7 @@ def bw(): | ||||
| def setup_edfa_variable_gain(): | ||||
|     """init edfa class by reading test_network.json file | ||||
|     remove all gain and nf ripple""" | ||||
|     equipment = load_equipment(eqpt_library) | ||||
|     equipment = load_equipment(eqpt_library, extra_configs) | ||||
|     network = load_network(test_network, equipment) | ||||
|     build_network(network, equipment, 0, 20) | ||||
|     edfa = [n for n in network.nodes() if isinstance(n, Edfa)][0] | ||||
| @@ -51,7 +53,7 @@ def setup_edfa_variable_gain(): | ||||
| @pytest.fixture() | ||||
| def setup_edfa_fixed_gain(): | ||||
|     """init edfa class by reading the 2nd edfa in test_network.json file""" | ||||
|     equipment = load_equipment(eqpt_library) | ||||
|     equipment = load_equipment(eqpt_library, extra_configs) | ||||
|     network = load_network(test_network, equipment) | ||||
|     build_network(network, equipment, 0, 20) | ||||
|     edfa = [n for n in network.nodes() if isinstance(n, Edfa)][1] | ||||
| @@ -61,7 +63,7 @@ def setup_edfa_fixed_gain(): | ||||
| @pytest.fixture() | ||||
| def setup_trx(): | ||||
|     """init transceiver class to access snr and osnr calculations""" | ||||
|     equipment = load_equipment(eqpt_library) | ||||
|     equipment = load_equipment(eqpt_library, extra_configs) | ||||
|     network = load_network(test_network, equipment) | ||||
|     build_network(network, equipment, 0, 20) | ||||
|     trx = [n for n in network.nodes() if isinstance(n, Transceiver)][0] | ||||
| @@ -144,7 +146,7 @@ def test_compare_nf_models(gain, setup_edfa_variable_gain, si): | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     equipment = load_equipment(eqpt_library) | ||||
|     equipment = load_equipment(eqpt_library, extra_configs) | ||||
|     extra_params = equipment['Edfa']['CienaDB_medium_gain'] | ||||
|     temp = el_config.setdefault('params', {}) | ||||
|     temp = merge_amplifier_restrictions(temp, extra_params.__dict__) | ||||
| @@ -165,7 +167,7 @@ def test_ase_noise(gain, si, setup_trx, bw): | ||||
|     2-pout/pase afet propagate | ||||
|     3-Transceiver osnr_ase_01nm | ||||
|     => unitary test for Edfa.noise_profile (Edfa.interpol_params, Edfa.propagate)""" | ||||
|     equipment = load_equipment(eqpt_library) | ||||
|     equipment = load_equipment(eqpt_library, extra_configs) | ||||
|     network = load_network(test_network, equipment) | ||||
|     edfa = next(n for n in network.nodes() if n.uid == 'Edfa1') | ||||
|     span = next(n for n in network.nodes() if n.uid == 'Span1') | ||||
| @@ -225,7 +227,7 @@ def test_amp_behaviour(tilt_target, delta_p): | ||||
|         }], | ||||
|         "connections": [] | ||||
|     } | ||||
|     equipment = load_equipment(eqpt_library) | ||||
|     equipment = load_equipment(eqpt_library, extra_configs) | ||||
|     network = network_from_json(json_data, equipment) | ||||
|     edfa = [n for n in network.nodes() if isinstance(n, Edfa)][0] | ||||
|     fiber = [n for n in network.nodes() if isinstance(n, Fiber)][0] | ||||
| @@ -310,7 +312,7 @@ def test_amp_saturation(delta_pdb_per_channel, base_power, delta_p): | ||||
|         }], | ||||
|         "connections": [] | ||||
|     } | ||||
|     equipment = load_equipment(eqpt_library) | ||||
|     equipment = load_equipment(eqpt_library, extra_configs) | ||||
|     network = network_from_json(json_data, equipment) | ||||
|     edfa = [n for n in network.nodes()][0] | ||||
|     frequency = 193e12 + array([0, 50e9, 150e9, 225e9, 275e9]) | ||||
| @@ -354,7 +356,7 @@ def test_set_out_voa(): | ||||
|         }], | ||||
|         "connections": [] | ||||
|     } | ||||
|     equipment = load_equipment(eqpt_library) | ||||
|     equipment = load_equipment(eqpt_library, extra_configs) | ||||
|     network = network_from_json(json_data, equipment) | ||||
|     amp = [n for n in network.nodes()][0] | ||||
|     print(amp.out_voa) | ||||
| @@ -408,7 +410,7 @@ def test_multiband(): | ||||
|     ] | ||||
|     equipment_json['Edfa'].extend(amps) | ||||
|  | ||||
|     equipment = _equipment_from_json(equipment_json, eqpt_library) | ||||
|     equipment = _equipment_from_json(equipment_json, extra_configs) | ||||
|  | ||||
|     el_config = { | ||||
|         "uid": "Edfa1", | ||||
| @@ -505,3 +507,165 @@ def test_multiband(): | ||||
|             assert freq >= 191.25e12 | ||||
|         if freq < 191.25e12: | ||||
|             assert freq <= 190.25e12 | ||||
|  | ||||
|  | ||||
| def test_user_defined_config(): | ||||
|     """Checks that a user defined config is correctly used instead of DEFAULT_EDFA_CONFIG | ||||
|     """ | ||||
|     extra_configs['user_edfa_config.json'] = DATA_DIR / 'user_edfa_config.json' | ||||
|     user_edfa = { | ||||
|         "type_variety": "user_defined", | ||||
|         "type_def": "variable_gain", | ||||
|         "gain_flatmax": 25, | ||||
|         "gain_min": 15, | ||||
|         "p_max": 21, | ||||
|         "nf_min": 6, | ||||
|         "nf_max": 10, | ||||
|         "default_config_from_json": "user_edfa_config.json", | ||||
|         "out_voa_auto": False, | ||||
|         "allowed_for_design": True | ||||
|     } | ||||
|  | ||||
|     # add the reference to | ||||
|     json_data = load_json(eqpt_library) | ||||
|     json_data['Edfa'].append(user_edfa) | ||||
|     equipment = _equipment_from_json(json_data, extra_configs) | ||||
|     json_data = { | ||||
|         "elements": [{ | ||||
|             "uid": "Edfa1", | ||||
|             "type": "Edfa", | ||||
|             "type_variety": "user_defined", | ||||
|             "operational": { | ||||
|                 "delta_p": -3, | ||||
|                 "gain_target": 20, | ||||
|                 "tilt_target": 0, | ||||
|                 "out_voa": 0 | ||||
|             } | ||||
|         }], | ||||
|         "connections": [] | ||||
|     } | ||||
|     network = network_from_json(json_data, equipment) | ||||
|     amp = [n for n in network.nodes()][0] | ||||
|     assert_allclose(amp.params.f_min, 193.0e12, rtol=1e-13) | ||||
|     assert_allclose(amp.params.f_max, 195.0e12, rtol=1e-13) | ||||
|     assert_allclose(amp.params.gain_ripple[15], 0.01027114740367, rtol=1e-13) | ||||
|     assert_allclose(amp.params.nf_ripple[15], 0.0, rtol=1e-13) | ||||
|     assert_allclose(amp.params.dgt[15], 1.847275503201129, rtol=1e-13) | ||||
|  | ||||
|  | ||||
| def test_default_config(): | ||||
|     """Checks that a config using a file gives the exact same result as the default config if values are identical | ||||
|     to DEFAULT_EDFA_CONFIG | ||||
|     """ | ||||
|     extra_configs['copy_default_edfa_config.json'] = DATA_DIR / 'copy_default_edfa_config.json' | ||||
|     user_edfa = { | ||||
|         "type_variety": "user_defined", | ||||
|         "type_def": "variable_gain", | ||||
|         "gain_flatmax": 25, | ||||
|         "gain_min": 15, | ||||
|         "p_max": 21, | ||||
|         "nf_min": 6, | ||||
|         "nf_max": 10, | ||||
|         "default_config_from_json": "copy_default_edfa_config.json", | ||||
|         "out_voa_auto": False, | ||||
|         "allowed_for_design": True | ||||
|     } | ||||
|  | ||||
|     default_edfa = { | ||||
|         "type_variety": "default", | ||||
|         "type_def": "variable_gain", | ||||
|         "gain_flatmax": 25, | ||||
|         "gain_min": 15, | ||||
|         "p_max": 21, | ||||
|         "nf_min": 6, | ||||
|         "nf_max": 10, | ||||
|         "out_voa_auto": False, | ||||
|         "allowed_for_design": True | ||||
|     } | ||||
|  | ||||
|     # add the reference to | ||||
|     json_data = load_json(eqpt_library) | ||||
|     json_data['Edfa'].append(user_edfa) | ||||
|     json_data['Edfa'].append(default_edfa) | ||||
|     equipment = _equipment_from_json(json_data, extra_configs) | ||||
|     json_data = { | ||||
|         "elements": [{ | ||||
|             "uid": "Edfa1", | ||||
|             "type": "Edfa", | ||||
|             "type_variety": "user_defined", | ||||
|             "operational": { | ||||
|                 "delta_p": -3, | ||||
|                 "gain_target": 20, | ||||
|                 "tilt_target": 0, | ||||
|                 "out_voa": 0 | ||||
|             } | ||||
|         }, { | ||||
|             "uid": "Edfa2", | ||||
|             "type": "Edfa", | ||||
|             "type_variety": "default", | ||||
|             "operational": { | ||||
|                 "delta_p": -3, | ||||
|                 "gain_target": 20, | ||||
|                 "tilt_target": 0, | ||||
|                 "out_voa": 0 | ||||
|             } | ||||
|         }], | ||||
|         "connections": [] | ||||
|     } | ||||
|     network = network_from_json(json_data, equipment) | ||||
|     amp1, amp2 = [n for n in network.nodes()] | ||||
|     assert_allclose(amp1.params.f_min, amp2.params.f_min, rtol=1e-13) | ||||
|     assert_allclose(amp1.params.f_max, amp2.params.f_max, rtol=1e-13) | ||||
|     assert_allclose(amp1.params.gain_ripple, amp2.params.gain_ripple, rtol=1e-13) | ||||
|     assert_allclose(amp1.params.nf_ripple, amp2.params.nf_ripple, rtol=1e-13) | ||||
|     assert_allclose(amp1.params.dgt, amp2.params.dgt, rtol=1e-13) | ||||
|  | ||||
|  | ||||
| @pytest.mark.parametrize("file", [None, {"name": "copy_default_edfa_config.json", | ||||
|                                          "path": DATA_DIR / "copy_default_edfa_config.json"}]) | ||||
| def test_frequency_range(file): | ||||
|     """Checks that a frequency range is correctly read from the library and pre-empts DEFAULT_EDFA_CONFIG | ||||
|     """ | ||||
|     user_edfa = { | ||||
|         "type_variety": "user_defined", | ||||
|         "type_def": "variable_gain", | ||||
|         "f_min": 192.0e12, | ||||
|         "f_max": 195.9e12, | ||||
|         "gain_flatmax": 25, | ||||
|         "gain_min": 15, | ||||
|         "p_max": 21, | ||||
|         "nf_min": 6, | ||||
|         "nf_max": 10, | ||||
|         "out_voa_auto": False, | ||||
|         "allowed_for_design": True | ||||
|     } | ||||
|     if file: | ||||
|         user_edfa["default_config_from_json"] = file['name'] | ||||
|         extra_configs[file['name']] = file['path'] | ||||
|     # add the reference to | ||||
|     json_data = load_json(eqpt_library) | ||||
|     json_data['Edfa'].append(user_edfa) | ||||
|     equipment = _equipment_from_json(json_data, extra_configs) | ||||
|     json_data = { | ||||
|         "elements": [{ | ||||
|             "uid": "Edfa1", | ||||
|             "type": "Edfa", | ||||
|             "type_variety": "user_defined", | ||||
|             "operational": { | ||||
|                 "delta_p": -3, | ||||
|                 "gain_target": 20, | ||||
|                 "tilt_target": 0, | ||||
|                 "out_voa": 0 | ||||
|             } | ||||
|         }], | ||||
|         "connections": [] | ||||
|     } | ||||
|     network = network_from_json(json_data, equipment) | ||||
|     amp = [n for n in network.nodes()][0] | ||||
|     si = create_input_spectral_information(f_min=191.3e12, f_max=196.05e12, roll_off=0.15, baud_rate=64e9, | ||||
|                                            spacing=75e9, tx_osnr=None, tx_power=1e-5) | ||||
|     si = amp(si) | ||||
|     assert_allclose(amp.params.f_min, 192.0e12, rtol=1e-13) | ||||
|     assert_allclose(amp.params.f_max, 195.9e12, rtol=1e-13) | ||||
|     assert si.frequency[0] >= 192.0e12 + 75e9 / 2 | ||||
|     assert si.frequency[-1] <= 195.9e12 - 75e9 / 2 | ||||
|   | ||||
| @@ -26,10 +26,13 @@ from gnpy.tools.json_io import load_network, load_equipment, requests_from_json, | ||||
|     _equipment_from_json | ||||
|  | ||||
|  | ||||
| network_file_name = Path(__file__).parent.parent / 'tests/data/testTopology_expected.json' | ||||
| service_file_name = Path(__file__).parent.parent / 'tests/data/testTopology_testservices.json' | ||||
| result_file_name = Path(__file__).parent.parent / 'tests/data/testTopology_testresults.json' | ||||
| eqpt_library_name = Path(__file__).parent.parent / 'tests/data/eqpt_config.json' | ||||
| data_dir = Path(__file__).parent.parent / 'tests/data' | ||||
| network_file_name = data_dir / 'testTopology_expected.json' | ||||
| service_file_name = data_dir / 'testTopology_testservices.json' | ||||
| result_file_name = data_dir / 'testTopology_testresults.json' | ||||
| eqpt_library_name = data_dir / 'eqpt_config.json' | ||||
| extra_configs = {"std_medium_gain_advanced_config.json": data_dir / "std_medium_gain_advanced_config.json", | ||||
|                  "Juniper-BoosterHG.json": data_dir / "Juniper-BoosterHG.json"} | ||||
|  | ||||
|  | ||||
| @pytest.mark.parametrize("net", [network_file_name]) | ||||
| @@ -39,7 +42,7 @@ eqpt_library_name = Path(__file__).parent.parent / 'tests/data/eqpt_config.json' | ||||
|                                             'PS_SP64_1', 'mode 3', 'PS_SP64_1', 'PS_SP64_1', '16QAM', 'mode 1', | ||||
|                                             'PS_SP64_1', 'PS_SP64_1', 'mode 1', 'mode 2', 'mode 1', 'mode 2', 'nok']]) | ||||
| def test_automaticmodefeature(net, eqpt, serv, expected_mode): | ||||
|     equipment = load_equipment(eqpt) | ||||
|     equipment = load_equipment(eqpt, extra_configs) | ||||
|     network = load_network(net, equipment) | ||||
|     data = load_requests(serv, eqpt, bidir=False, network=network, network_filename=net) | ||||
|  | ||||
| @@ -155,7 +158,7 @@ def test_propagate_and_optimize_mode(caplog): | ||||
|     # change default ROADM PDL so that crossing 2 ROADMs leasd to inifinte penalty for mode 1 | ||||
|     eqpt_roadm = next(r for r in json_data['Roadm'] if 'type_variety' not in r) | ||||
|     eqpt_roadm['pdl'] = 0.5 | ||||
|     equipment = _equipment_from_json(json_data, eqpt_library_name) | ||||
|     equipment = _equipment_from_json(json_data, extra_configs) | ||||
|     network = load_network(network_file_name, equipment) | ||||
|     data = load_requests(filename=Path(__file__).parent.parent / 'tests/data/testTopology_services_expected.json', | ||||
|                          eqpt=eqpt_library_name, bidir=False, network=network, network_filename=network_file_name) | ||||
|   | ||||
| @@ -23,10 +23,14 @@ from gnpy.topology.request import (compute_path_dsjctn, isdisjoint, find_reverse | ||||
| from gnpy.topology.spectrum_assignment import build_oms_list | ||||
| from gnpy.tools.json_io import requests_from_json, load_requests, load_network, load_equipment, disjunctions_from_json | ||||
|  | ||||
| NETWORK_FILE_NAME = Path(__file__).parent.parent / 'tests/data/testTopology_expected.json' | ||||
| SERVICE_FILE_NAME = Path(__file__).parent.parent / 'tests/data/testTopology_testservices.json' | ||||
| RESULT_FILE_NAME = Path(__file__).parent.parent / 'tests/data/testTopology_testresults.json' | ||||
| EQPT_LIBRARY_NAME = Path(__file__).parent.parent / 'tests/data/eqpt_config.json' | ||||
|  | ||||
| DATA_DIR = Path(__file__).parent.parent / 'tests/data' | ||||
| NETWORK_FILE_NAME = DATA_DIR / 'testTopology_expected.json' | ||||
| SERVICE_FILE_NAME = DATA_DIR / 'testTopology_testservices.json' | ||||
| RESULT_FILE_NAME = DATA_DIR / 'testTopology_testresults.json' | ||||
| EQPT_LIBRARY_NAME = DATA_DIR / 'eqpt_config.json' | ||||
| EXTRA_CONFIGS = {"std_medium_gain_advanced_config.json": DATA_DIR / "std_medium_gain_advanced_config.json", | ||||
|                  "Juniper-BoosterHG.json": DATA_DIR / "Juniper-BoosterHG.json"} | ||||
|  | ||||
|  | ||||
| @pytest.fixture() | ||||
| @@ -43,7 +47,7 @@ def serv(test_setup): | ||||
| @pytest.fixture() | ||||
| def test_setup(): | ||||
|     """common setup for tests: builds network, equipment and oms only once""" | ||||
|     equipment = load_equipment(EQPT_LIBRARY_NAME) | ||||
|     equipment = load_equipment(EQPT_LIBRARY_NAME, EXTRA_CONFIGS) | ||||
|     network = load_network(NETWORK_FILE_NAME, equipment) | ||||
|     # Build the network once using the default power defined in SI in eqpt config | ||||
|     # power density : db2linp(ower_dbm': 0)/power_dbm': 0 * nb channels as defined by | ||||
| @@ -297,7 +301,7 @@ def test_aggregation(ids, modes, req_n, req_m, disjunction, final_ids, final_ns, | ||||
|     if mode is not defined, requests must not be merged, | ||||
|     if requests are in a synchronization vector, they should not be merged | ||||
|     """ | ||||
|     equipment = load_equipment(EQPT_LIBRARY_NAME) | ||||
|     equipment = load_equipment(EQPT_LIBRARY_NAME, EXTRA_CONFIGS) | ||||
|     requests = [] | ||||
|     for request_id, mode, req_n, req_m in zip(ids, modes, req_n, req_m): | ||||
|         params = request_set | ||||
|   | ||||
| @@ -28,8 +28,11 @@ from gnpy.topology.spectrum_assignment import build_oms_list | ||||
|  | ||||
|  | ||||
| TEST_DIR = Path(__file__).parent | ||||
| EQPT_FILENAME = TEST_DIR / 'data/eqpt_config.json' | ||||
| NETWORK_FILENAME = TEST_DIR / 'data/testTopology_expected.json' | ||||
| DATA_DIR = TEST_DIR / 'data' | ||||
| EQPT_FILENAME = DATA_DIR / 'eqpt_config.json' | ||||
| NETWORK_FILENAME = DATA_DIR / 'testTopology_expected.json' | ||||
| EXTRA_CONFIGS = {"std_medium_gain_advanced_config.json": DATA_DIR / "std_medium_gain_advanced_config.json", | ||||
|                  "Juniper-BoosterHG.json": DATA_DIR / "Juniper-BoosterHG.json"} | ||||
|  | ||||
|  | ||||
| @pytest.mark.parametrize('degree, equalization_type, target, expected_pch_out_dbm, expected_si', | ||||
| @@ -151,7 +154,7 @@ def test_merge_equalization(): | ||||
|             "type": "Roadm"}], | ||||
|         "connections": [] | ||||
|     } | ||||
|     equipment = load_equipment(EQPT_FILENAME) | ||||
|     equipment = load_equipment(EQPT_FILENAME, EXTRA_CONFIGS) | ||||
|     network = network_from_json(json_data, equipment) | ||||
|     roadm = [n for n in network.nodes()][0] | ||||
|     assert roadm.target_pch_out_dbm == -20 | ||||
| @@ -352,7 +355,7 @@ def create_voyager_req(equipment, source, dest, bidir, nodes_list, loose_list, m | ||||
| def test_initial_spectrum(mode, slot_width, power_dbm): | ||||
|     """checks that propagation using the user defined spectrum identical to SI, gives same result as SI""" | ||||
|     # first propagate without any req.initial_spectrum attribute | ||||
|     equipment = load_equipment(EQPT_FILENAME) | ||||
|     equipment = load_equipment(EQPT_FILENAME, EXTRA_CONFIGS) | ||||
|     req = create_voyager_req(equipment, 'trx Brest_KLA', 'trx Vannes_KBE', False, ['trx Vannes_KBE'], ['STRICT'], | ||||
|                              mode, slot_width, power_dbm) | ||||
|     network = net_setup(equipment) | ||||
| @@ -389,7 +392,7 @@ def test_initial_spectrum_not_identical(): | ||||
|     """checks that user defined spectrum overrides spectrum defined in SI | ||||
|     """ | ||||
|     # first propagate without any req.initial_spectrum attribute | ||||
|     equipment = load_equipment(EQPT_FILENAME) | ||||
|     equipment = load_equipment(EQPT_FILENAME, EXTRA_CONFIGS) | ||||
|     req = create_voyager_req(equipment, 'trx Brest_KLA', 'trx Vannes_KBE', False, ['trx Vannes_KBE'], ['STRICT'], | ||||
|                              'mode 1', 50e9, 0) | ||||
|     network = net_setup(equipment) | ||||
| @@ -424,7 +427,7 @@ def test_target_psd_or_psw(power_dbm, equalization, target_value): | ||||
|     """checks that if target_out_mWperSlotWidth or target_psd_out_mWperGHz is defined, it is used as equalization | ||||
|     and it gives same result if computed target is the same | ||||
|     """ | ||||
|     equipment = load_equipment(EQPT_FILENAME) | ||||
|     equipment = load_equipment(EQPT_FILENAME, EXTRA_CONFIGS) | ||||
|     network = net_setup(equipment) | ||||
|     req = create_voyager_req(equipment, 'trx Brest_KLA', 'trx Vannes_KBE', False, ['trx Vannes_KBE'], ['STRICT'], | ||||
|                              'mode 1', 50e9, power_dbm) | ||||
| @@ -452,7 +455,7 @@ def test_target_psd_or_psw(power_dbm, equalization, target_value): | ||||
|  | ||||
| def ref_network(): | ||||
|     """Create a network instance with a instance of propagated path""" | ||||
|     equipment = load_equipment(EQPT_FILENAME) | ||||
|     equipment = load_equipment(EQPT_FILENAME, EXTRA_CONFIGS) | ||||
|     network = net_setup(equipment) | ||||
|     req0 = create_voyager_req(equipment, 'trx Brest_KLA', 'trx Vannes_KBE', False, ['trx Vannes_KBE'], ['STRICT'], | ||||
|                               'mode 1', 50e9, 0) | ||||
| @@ -467,7 +470,7 @@ def test_target_psd_out_mwperghz_deltap(deltap): | ||||
|  | ||||
|     Power over 1.18dBm saturate amp with this test: TODO add a test on this saturation | ||||
|     """ | ||||
|     equipment = load_equipment(EQPT_FILENAME) | ||||
|     equipment = load_equipment(EQPT_FILENAME, EXTRA_CONFIGS) | ||||
|     network = net_setup(equipment, deltap) | ||||
|     req = create_voyager_req(equipment, 'trx Brest_KLA', 'trx Vannes_KBE', False, ['trx Vannes_KBE'], ['STRICT'], | ||||
|                              'mode 1', 50e9, deltap) | ||||
| @@ -510,7 +513,7 @@ def test_equalization(case, deltap, target, mode, slot_width, equalization): | ||||
|     - per degree : target_pch_out_db / target_psd_out_mWperGHz | ||||
|     for these cases with and without power from user | ||||
|     """ | ||||
|     equipment = load_equipment(EQPT_FILENAME) | ||||
|     equipment = load_equipment(EQPT_FILENAME, EXTRA_CONFIGS) | ||||
|     setattr(equipment['Roadm']['default'], 'target_pch_out_db', target) | ||||
|     req = create_voyager_req(equipment, 'trx Brest_KLA', 'trx Rennes_STA', False, | ||||
|                              ['east edfa in Brest_KLA to Quimper', 'roadm Lannion_CAS', 'trx Rennes_STA'], | ||||
| @@ -567,7 +570,7 @@ def test_equalization(case, deltap, target, mode, slot_width, equalization): | ||||
| def test_power_option(req_power): | ||||
|     """check that --po option adds correctly power with spectral information | ||||
|     """ | ||||
|     equipment = load_equipment(EQPT_FILENAME) | ||||
|     equipment = load_equipment(EQPT_FILENAME, EXTRA_CONFIGS) | ||||
|     setattr(equipment['Roadm']['default'], 'target_pch_out_db', None) | ||||
|     setattr(equipment['Roadm']['default'], 'target_psd_out_mWperGHz', power_dbm_to_psd_mw_ghz(-20, 32e9)) | ||||
|     network = net_setup(equipment) | ||||
| @@ -718,7 +721,7 @@ def test_power_offset_trx_equalization_psw(slot_width, value): | ||||
|     """Check that the equalization with the offset is giving the same result as with reference slot_width | ||||
|     Check that larger slot width but no offset takes larger slot width for equalization | ||||
|     """ | ||||
|     equipment = load_equipment(EQPT_FILENAME) | ||||
|     equipment = load_equipment(EQPT_FILENAME, EXTRA_CONFIGS) | ||||
|     trx = transceiver(slot_width, value) | ||||
|     equipment['Transceiver'][trx['type_variety']] = Transceiver(**trx) | ||||
|     setattr(equipment['Roadm']['default'], 'target_pch_out_db', None) | ||||
| @@ -751,7 +754,7 @@ def test_power_offset_trx_equalization_psw(slot_width, value): | ||||
| def test_power_offset_trx_equalization_p(slot_width, value): | ||||
|     """Check that the constant power equalization with the offset is applied | ||||
|     """ | ||||
|     equipment = load_equipment(EQPT_FILENAME) | ||||
|     equipment = load_equipment(EQPT_FILENAME, EXTRA_CONFIGS) | ||||
|     trx = transceiver(slot_width, value) | ||||
|     equipment['Transceiver'][trx['type_variety']] = Transceiver(**trx) | ||||
|     setattr(equipment['Roadm']['default'], 'target_pch_out_db', -20) | ||||
| @@ -777,7 +780,7 @@ def test_power_offset_automatic_mode_selection(slot_width, value, equalization, | ||||
|     """Check that the same result is obtained if the mode is user defined or if it is | ||||
|     automatically selected | ||||
|     """ | ||||
|     equipment = load_equipment(EQPT_FILENAME) | ||||
|     equipment = load_equipment(EQPT_FILENAME, EXTRA_CONFIGS) | ||||
|     trx = transceiver(slot_width, value) | ||||
|     equipment['Transceiver'][trx['type_variety']] = Transceiver(**trx) | ||||
|     setattr(equipment['Roadm']['default'], 'target_pch_out_db', None) | ||||
| @@ -859,7 +862,7 @@ def test_tx_power(tx_power_dbm): | ||||
|     for el in json_data['elements']: | ||||
|         if el['uid'] == 'roadm Lannion_CAS': | ||||
|             el['type_variety'] = 'example_detailed_impairments' | ||||
|     equipment = load_equipment(EQPT_FILENAME) | ||||
|     equipment = load_equipment(EQPT_FILENAME, EXTRA_CONFIGS) | ||||
|     network = network_from_json(json_data, equipment) | ||||
|     default_spectrum = equipment['SI']['default'] | ||||
|     p_db = default_spectrum.power_dbm | ||||
|   | ||||
| @@ -22,8 +22,11 @@ from gnpy.topology.request import PathRequest, compute_constrained_path, propaga | ||||
|  | ||||
|  | ||||
| TEST_DIR = Path(__file__).parent | ||||
| EQPT_FILENAME = TEST_DIR / 'data/eqpt_config.json' | ||||
| NETWORK_FILENAME = TEST_DIR / 'data/perdegreemeshTopologyExampleV2_auto_design_expected.json' | ||||
| DATA_DIR = TEST_DIR / 'data' | ||||
| EQPT_FILENAME = DATA_DIR / 'eqpt_config.json' | ||||
| NETWORK_FILENAME = DATA_DIR / 'perdegreemeshTopologyExampleV2_auto_design_expected.json' | ||||
| EXTRA_CONFIGS = {"std_medium_gain_advanced_config.json": DATA_DIR / "std_medium_gain_advanced_config.json", | ||||
|                  "Juniper-BoosterHG.json": DATA_DIR / "Juniper-BoosterHG.json"} | ||||
|  | ||||
|  | ||||
| def net_setup(equipment): | ||||
| @@ -71,7 +74,7 @@ def test_gain_mode(req_power, power_dbm): | ||||
|     in gain mode, whatever the value of equipment power_dbm or request power, the network is unchanged | ||||
|     and the propagation remains the same as for power mode and 0dBm | ||||
|     """ | ||||
|     equipment = load_equipment(EQPT_FILENAME) | ||||
|     equipment = load_equipment(EQPT_FILENAME, EXTRA_CONFIGS) | ||||
|     network = net_setup(equipment) | ||||
|     req = create_rq(equipment, 'trx Brest_KLA', 'trx Rennes_STA', False, | ||||
|                     ['Edfa0_roadm Brest_KLA', 'roadm Lannion_CAS', 'trx Rennes_STA'], | ||||
|   | ||||
| @@ -18,11 +18,11 @@ SRC_ROOT = Path(__file__).parent.parent | ||||
|     ('transmission_main_example__raman', None, transmission_main_example, | ||||
|      ['gnpy/example-data/raman_edfa_example_network.json', '--sim', 'gnpy/example-data/sim_params.json', '--show-channels', ]), | ||||
|     ('openroadm-v4-Stockholm-Gothenburg', None, transmission_main_example, | ||||
|      ['-e', 'gnpy/example-data/eqpt_config_openroadm_ver4.json', 'gnpy/example-data/Sweden_OpenROADMv4_example_network.json', ]), | ||||
|      ['gnpy/example-data/Sweden_OpenROADMv4_example_network.json', '-e', 'gnpy/example-data/eqpt_config_openroadm_ver4.json', ]), | ||||
|     ('openroadm-v5-Stockholm-Gothenburg', None, transmission_main_example, | ||||
|      ['-e', 'gnpy/example-data/eqpt_config_openroadm_ver5.json', 'gnpy/example-data/Sweden_OpenROADMv5_example_network.json', ]), | ||||
|      ['gnpy/example-data/Sweden_OpenROADMv5_example_network.json', '-e', 'gnpy/example-data/eqpt_config_openroadm_ver5.json', ]), | ||||
|     ('transmission_main_example_long', None, transmission_main_example, | ||||
|      ['-e', 'tests/data/eqpt_config.json', 'tests/data/test_long_network.json']), | ||||
|      ['tests/data/test_long_network.json', '-e', 'tests/data/eqpt_config.json']), | ||||
|     ('spectrum1_transmission_main_example', None, transmission_main_example, | ||||
|      ['--spectrum', 'gnpy/example-data/initial_spectrum1.json', 'gnpy/example-data/meshTopologyExampleV2.xls', ]), | ||||
|     ('spectrum2_transmission_main_example', None, transmission_main_example, | ||||
| @@ -32,14 +32,17 @@ SRC_ROOT = Path(__file__).parent.parent | ||||
|     ('power_sweep_example', 'logs_power_sweep_example', transmission_main_example, | ||||
|      ['tests/data/testTopology_expected.json', 'brest', 'rennes', '-e', 'tests/data/eqpt_config_sweep.json', '--pow', '3']), | ||||
|     ('transmission_long_pow', None, transmission_main_example, | ||||
|      ['-e', 'tests/data/eqpt_config.json', 'tests/data/test_long_network.json', '--spectrum', 'gnpy/example-data/initial_spectrum2.json']), | ||||
|      ['tests/data/test_long_network.json', '-e', 'tests/data/eqpt_config.json', '--spectrum', 'gnpy/example-data/initial_spectrum2.json']), | ||||
|     ('transmission_long_psd', None, transmission_main_example, | ||||
|      ['-e', 'tests/data/eqpt_config_psd.json', 'tests/data/test_long_network.json', '--spectrum', 'gnpy/example-data/initial_spectrum2.json', ]), | ||||
|      ['tests/data/test_long_network.json', '-e', 'tests/data/eqpt_config_psd.json', '--spectrum', 'gnpy/example-data/initial_spectrum2.json', ]), | ||||
|     ('transmission_long_psw', None, transmission_main_example, | ||||
|      ['-e', 'tests/data/eqpt_config_psw.json', 'tests/data/test_long_network.json', '--spectrum', 'gnpy/example-data/initial_spectrum2.json', ]), | ||||
|      ['tests/data/test_long_network.json', '-e', 'tests/data/eqpt_config_psw.json', '--spectrum', 'gnpy/example-data/initial_spectrum2.json', ]), | ||||
|     ('multiband_transmission', None, transmission_main_example, | ||||
|      ['gnpy/example-data/multiband_example_network.json', 'Site_A', 'Site_D', '-e', 'gnpy/example-data/eqpt_config_multiband.json', | ||||
|       '--spectrum', 'gnpy/example-data/multiband_spectrum.json', '--show-channels']) | ||||
|       '--spectrum', 'gnpy/example-data/multiband_spectrum.json', '--show-channels']), | ||||
|     ('path_requests_run_extra_equipment', 'logs_path_requests_run_extra_equipment', path_requests_run, | ||||
|      ['gnpy/example-data/meshTopologyExampleV2.xls', 'gnpy/example-data/service_pluggable.json', '--extra-equipment', 'gnpy/example-data/extra_eqpt_config.json', 'tests/data/extra_eqpt_config.json', | ||||
|       '--extra-config', 'tests/data/user_edfa_config.json']) | ||||
| )) | ||||
| def test_example_invocation(capfd, caplog, output, log, handler, args): | ||||
|     """Make sure that our examples produce useful output""" | ||||
|   | ||||
| @@ -18,6 +18,8 @@ TEST_DIR = Path(__file__).parent | ||||
| EQPT_FILENAME = TEST_DIR / 'data/eqpt_config.json' | ||||
| MULTIBAND_EQPT_FILENAME = TEST_DIR / 'data/eqpt_config_multiband.json' | ||||
| DATA_DIR = TEST_DIR / 'data' | ||||
| EXTRA_CONFIGS = {"std_medium_gain_advanced_config.json": DATA_DIR / "std_medium_gain_advanced_config.json", | ||||
|                  "Juniper-BoosterHG.json": DATA_DIR / "Juniper-BoosterHG.json"} | ||||
|  | ||||
|  | ||||
| def test_jsonthing(caplog): | ||||
| @@ -97,7 +99,7 @@ def test_wrong_equipment(caplog, error, equipment, json_data, expected_msg): | ||||
| def test_wrong_xls_service(xls_service_filename, xls_topo_filename, expected_msg): | ||||
|     """ | ||||
|     """ | ||||
|     equipment = load_equipment(EQPT_FILENAME) | ||||
|     equipment = load_equipment(EQPT_FILENAME, EXTRA_CONFIGS) | ||||
|     network = load_network(DATA_DIR / xls_topo_filename, equipment) | ||||
|     with pytest.raises(ServiceError, match=expected_msg): | ||||
|         _ = load_requests(DATA_DIR / xls_service_filename, equipment, False, network, DATA_DIR / xls_topo_filename) | ||||
| @@ -293,7 +295,7 @@ def test_json_request(error, json_data, expected_msg): | ||||
|     """ | ||||
|     Check that a missing key is correctly raisong the logger | ||||
|     """ | ||||
|     equipment = load_equipment(EQPT_FILENAME) | ||||
|     equipment = load_equipment(EQPT_FILENAME, EXTRA_CONFIGS) | ||||
|  | ||||
|     with pytest.raises(error, match=re.escape(expected_msg)): | ||||
|         _ = requests_from_json(json_data, equipment) | ||||
| @@ -387,7 +389,7 @@ def test_json_network(error, json_data, expected_msg): | ||||
|     """ | ||||
|     Check that a missing key is correctly raisong the logger | ||||
|     """ | ||||
|     equipment = load_equipment(EQPT_FILENAME) | ||||
|     equipment = load_equipment(EQPT_FILENAME, EXTRA_CONFIGS) | ||||
|     with pytest.raises(error, match=re.escape(expected_msg)): | ||||
|         _ = network_from_json(json_data, equipment) | ||||
|  | ||||
| @@ -568,7 +570,7 @@ def wrong_configs(): | ||||
| @pytest.mark.parametrize('el_config, error_type', wrong_configs()) | ||||
| def test_wrong_multiband(el_config, error_type): | ||||
|  | ||||
|     equipment = load_equipment(MULTIBAND_EQPT_FILENAME) | ||||
|     equipment = load_equipment(MULTIBAND_EQPT_FILENAME, EXTRA_CONFIGS) | ||||
|     fused_config = { | ||||
|         "uid": "[83/WR-2-4-SIG=>930/WRT-1-2-SIG]-Tl/9300", | ||||
|         "type": "Fused", | ||||
|   | ||||
| @@ -18,9 +18,12 @@ from gnpy.core.parameters import SimParams, EdfaParams, MultiBandParams | ||||
|  | ||||
|  | ||||
| TEST_DIR = Path(__file__).parent | ||||
| EQPT_FILENAME = TEST_DIR / 'data/eqpt_config.json' | ||||
| EQPT_MULTBAND_FILENAME = TEST_DIR / 'data/eqpt_config_multiband.json' | ||||
| NETWORK_FILENAME = TEST_DIR / 'data/bugfixiteratortopo.json' | ||||
| DATA_DIR = TEST_DIR / 'data' | ||||
| EQPT_FILENAME = DATA_DIR / 'eqpt_config.json' | ||||
| EQPT_MULTBAND_FILENAME = DATA_DIR / 'eqpt_config_multiband.json' | ||||
| NETWORK_FILENAME = DATA_DIR / 'bugfixiteratortopo.json' | ||||
| EXTRA_CONFIGS = {"std_medium_gain_advanced_config.json": DATA_DIR / "std_medium_gain_advanced_config.json", | ||||
|                  "Juniper-BoosterHG.json": DATA_DIR / "Juniper-BoosterHG.json"} | ||||
|  | ||||
|  | ||||
| @pytest.mark.parametrize("node, attenuation", [ | ||||
| @@ -52,7 +55,7 @@ NETWORK_FILENAME = TEST_DIR / 'data/bugfixiteratortopo.json' | ||||
|     ['Site_B', 0], | ||||
| ]) | ||||
| def test_span_loss(node, attenuation): | ||||
|     equipment = load_equipment(EQPT_FILENAME) | ||||
|     equipment = load_equipment(EQPT_FILENAME, EXTRA_CONFIGS) | ||||
|     network = load_network(NETWORK_FILENAME, equipment) | ||||
|     for x in network.nodes(): | ||||
|         if x.uid == node: | ||||
| @@ -64,7 +67,7 @@ def test_span_loss(node, attenuation): | ||||
| @pytest.mark.parametrize("node", ['fused4']) | ||||
| def test_span_loss_unconnected(node): | ||||
|     '''Fused node that has no next and no previous nodes should be detected''' | ||||
|     equipment = load_equipment(EQPT_FILENAME) | ||||
|     equipment = load_equipment(EQPT_FILENAME, EXTRA_CONFIGS) | ||||
|     network = load_network(NETWORK_FILENAME, equipment) | ||||
|     x = next(x for x in network.nodes() if x.uid == node) | ||||
|     with pytest.raises(NetworkTopologyError): | ||||
| @@ -164,7 +167,7 @@ def test_eol(typ, expected_loss): | ||||
|             } | ||||
|         ] | ||||
|     } | ||||
|     equipment = load_equipment(EQPT_FILENAME) | ||||
|     equipment = load_equipment(EQPT_FILENAME, EXTRA_CONFIGS) | ||||
|     equipment['Span']['default'].EOL = 1 | ||||
|     network = network_from_json(json_data, equipment) | ||||
|     p_db = equipment['SI']['default'].power_dbm | ||||
| @@ -230,7 +233,7 @@ def test_design_non_amplified_link(elem1, elem2, expected_gain, expected_delta_p | ||||
|             } | ||||
|         ] | ||||
|     } | ||||
|     equipment = load_equipment(EQPT_FILENAME) | ||||
|     equipment = load_equipment(EQPT_FILENAME, EXTRA_CONFIGS) | ||||
|     equipment['Span']['default'].power_mode = power_mode | ||||
|     equipment['SI']['default'].power_dbm = p_db | ||||
|     equipment['SI']['default'].tx_power_dbm = p_db | ||||
| @@ -441,7 +444,7 @@ def test_design_band(case, site_type, amplifier_type, expected_design_bands, exp | ||||
|     EOL is then added on the first fiber only. | ||||
|     """ | ||||
|     json_data = network_base(case, site_type, amplifier_type=amplifier_type) | ||||
|     equipment = load_equipment(EQPT_MULTBAND_FILENAME) | ||||
|     equipment = load_equipment(EQPT_MULTBAND_FILENAME, EXTRA_CONFIGS) | ||||
|     network = network_from_json(json_data, equipment) | ||||
|     p_db = equipment['SI']['default'].power_dbm | ||||
|     p_total_db = p_db + lin2db(automatic_nch(equipment['SI']['default'].f_min, | ||||
| @@ -462,7 +465,7 @@ def test_design_band(case, site_type, amplifier_type, expected_design_bands, exp | ||||
| def test_select_edfa(caplog, raman_allowed, gain_target, power_target, target_extended_gain, warning, expected_selection): | ||||
|     """ | ||||
|     """ | ||||
|     equipment = load_equipment(EQPT_MULTBAND_FILENAME) | ||||
|     equipment = load_equipment(EQPT_MULTBAND_FILENAME, EXTRA_CONFIGS) | ||||
|     edfa_eqpt = {n: a for n, a in equipment['Edfa'].items() if a.type_def != 'multi_band'} | ||||
|     selection = select_edfa(raman_allowed, gain_target, power_target, edfa_eqpt, "toto", target_extended_gain, verbose=True) | ||||
|     assert selection == expected_selection | ||||
| @@ -499,7 +502,7 @@ def test_select_edfa(caplog, raman_allowed, gain_target, power_target, target_ex | ||||
| def test_get_node_restrictions(cls, defaultparams, variety_list, booster_list, band, expected_restrictions): | ||||
|     """Check that all combinations of restrictions are correctly captured | ||||
|     """ | ||||
|     equipment = load_equipment(EQPT_MULTBAND_FILENAME) | ||||
|     equipment = load_equipment(EQPT_MULTBAND_FILENAME, EXTRA_CONFIGS) | ||||
|     edfa_config = {"uid": "Edfa1"} | ||||
|     if cls == Multiband_amplifier: | ||||
|         edfa_config['amplifiers'] = {} | ||||
| @@ -570,7 +573,7 @@ def test_multiband(case, site_type, band, expected_gain, expected_tilt, expected | ||||
|     EOL is then added on the first fiber only. | ||||
|     """ | ||||
|     json_data = network_base(case, site_type) | ||||
|     equipment = load_equipment(EQPT_MULTBAND_FILENAME) | ||||
|     equipment = load_equipment(EQPT_MULTBAND_FILENAME, EXTRA_CONFIGS) | ||||
|     network = network_from_json(json_data, equipment) | ||||
|     p_db = equipment['SI']['default'].power_dbm | ||||
|     p_total_db = p_db + lin2db(automatic_nch(equipment['SI']['default'].f_min, | ||||
| @@ -600,12 +603,12 @@ def test_tilt_fused(): | ||||
|     SimParams.set_params(load_json(TEST_DIR / 'data' / 'sim_params.json')) | ||||
|     input_powers = {'CBAND': 0.001, 'LBAND': 0.001} | ||||
|     json_data = network_base("design", "Multiband_amplifier", length=100) | ||||
|     equipment = load_equipment(EQPT_MULTBAND_FILENAME) | ||||
|     equipment = load_equipment(EQPT_MULTBAND_FILENAME, EXTRA_CONFIGS) | ||||
|     network = network_from_json(json_data, equipment) | ||||
|     node = next(n for n in network.nodes() if n.uid == 'fiber (SITE1 → ILA1)') | ||||
|     tilt_db, tilt_target = estimate_srs_power_deviation(network, node, equipment, design_bands, input_powers) | ||||
|     json_data = network_base("design", "Fused", length=50) | ||||
|     equipment = load_equipment(EQPT_MULTBAND_FILENAME) | ||||
|     equipment = load_equipment(EQPT_MULTBAND_FILENAME, EXTRA_CONFIGS) | ||||
|     network = network_from_json(json_data, equipment) | ||||
|     node = next(n for n in network.nodes() if n.uid == 'fiber (ILA1 → ILA2)') | ||||
|     fused_tilt_db, fused_tilt_target = \ | ||||
| @@ -734,7 +737,7 @@ def test_insert_amp(site_type, expected_type, bands, expected_bands): | ||||
|     EOL is then added on the first fiber only. | ||||
|     """ | ||||
|     json_data = network_wo_booster(site_type, bands) | ||||
|     equipment = load_equipment(EQPT_MULTBAND_FILENAME) | ||||
|     equipment = load_equipment(EQPT_MULTBAND_FILENAME, EXTRA_CONFIGS) | ||||
|     network = network_from_json(json_data, equipment) | ||||
|     p_db = equipment['SI']['default'].power_dbm | ||||
|     p_total_db = p_db + lin2db(automatic_nch(equipment['SI']['default'].f_min, | ||||
|   | ||||
| @@ -36,8 +36,10 @@ from gnpy.tools.service_sheet import read_service_sheet, correct_xls_route_list, | ||||
|  | ||||
| TEST_DIR = Path(__file__).parent | ||||
| DATA_DIR = TEST_DIR / 'data' | ||||
| eqpt_filename = DATA_DIR / 'eqpt_config.json' | ||||
| equipment = load_equipment(eqpt_filename) | ||||
| EQPT_FILENAME = DATA_DIR / 'eqpt_config.json' | ||||
| EXTRA_CONFIGS = {"std_medium_gain_advanced_config.json": DATA_DIR / "std_medium_gain_advanced_config.json", | ||||
|                  "Juniper-BoosterHG.json": DATA_DIR / "Juniper-BoosterHG.json"} | ||||
| equipment = load_equipment(EQPT_FILENAME, EXTRA_CONFIGS) | ||||
|  | ||||
|  | ||||
| @pytest.mark.parametrize('xls_input,expected_json_output', { | ||||
| @@ -69,7 +71,7 @@ def test_excel_json_generation(tmpdir, xls_input, expected_json_output): | ||||
|                           }.items()) | ||||
| def test_auto_design_generation_fromxlsgainmode(tmpdir, xls_input, expected_json_output): | ||||
|     """tests generation of topology json and that the build network gives correct results in gain mode""" | ||||
|     equipment = load_equipment(eqpt_filename) | ||||
|     equipment = load_equipment(EQPT_FILENAME, EXTRA_CONFIGS) | ||||
|     network = load_network(xls_input, equipment) | ||||
|     add_missing_elements_in_network(network, equipment) | ||||
|     # in order to test the Eqpt sheet and load gain target, | ||||
| @@ -100,7 +102,7 @@ def test_auto_design_generation_fromxlsgainmode(tmpdir, xls_input, expected_json | ||||
|                           }.items()) | ||||
| def test_auto_design_generation_fromjson(tmpdir, json_input, power_mode): | ||||
|     """test that autodesign creates same file as an input file already autodesigned""" | ||||
|     equipment = load_equipment(eqpt_filename) | ||||
|     equipment = load_equipment(EQPT_FILENAME, EXTRA_CONFIGS) | ||||
|     network = load_network(json_input, equipment) | ||||
|     # in order to test the Eqpt sheet and load gain target, | ||||
|     # change the power-mode to False (to be in gain mode) | ||||
| @@ -127,7 +129,7 @@ def test_auto_design_generation_fromjson(tmpdir, json_input, power_mode): | ||||
| }.items()) | ||||
| def test_excel_service_json_generation(xls_input, expected_json_output): | ||||
|     """test services creation""" | ||||
|     equipment = load_equipment(eqpt_filename) | ||||
|     equipment = load_equipment(EQPT_FILENAME, EXTRA_CONFIGS) | ||||
|     network = load_network(DATA_DIR / 'testTopology.xls', equipment) | ||||
|     # Build the network once using the default power defined in SI in eqpt config | ||||
|     p_db = equipment['SI']['default'].power_dbm | ||||
| @@ -148,7 +150,7 @@ def test_excel_service_json_generation(xls_input, expected_json_output): | ||||
| def test_csv_response_generation(tmpdir, json_input): | ||||
|     """tests if generated csv is consistant with expected generation same columns (order not important)""" | ||||
|     json_data = load_json(json_input) | ||||
|     equipment = load_equipment(eqpt_filename) | ||||
|     equipment = load_equipment(EQPT_FILENAME, EXTRA_CONFIGS) | ||||
|     csv_filename = Path(tmpdir / json_input.name).with_suffix('.csv') | ||||
|     with open(csv_filename, 'w', encoding='utf-8') as fcsv: | ||||
|         jsontocsv(json_data, equipment, fcsv) | ||||
| @@ -213,7 +215,7 @@ def test_csv_response_generation(tmpdir, json_input): | ||||
| def test_json_response_generation(xls_input, expected_response_file): | ||||
|     """tests if json response is correctly generated for all combinations of requests""" | ||||
|  | ||||
|     equipment = load_equipment(eqpt_filename) | ||||
|     equipment = load_equipment(EQPT_FILENAME, EXTRA_CONFIGS) | ||||
|     network = load_network(xls_input, equipment) | ||||
|     p_db = equipment['SI']['default'].power_dbm | ||||
|  | ||||
| @@ -630,7 +632,7 @@ def test_roadm_type_variety(type_variety, target_pch_out_db, correct_variety): | ||||
|         # Do not add type variety in json_data to test that it creates a 'default' type_variety | ||||
|         expected_roadm['type_variety'] = 'default' | ||||
|     expected_roadm['params']['target_pch_out_db'] = target_pch_out_db | ||||
|     equipment = load_equipment(eqpt_filename) | ||||
|     equipment = load_equipment(EQPT_FILENAME, EXTRA_CONFIGS) | ||||
|     if correct_variety: | ||||
|         network = network_from_json(json_data, equipment) | ||||
|         roadm = [n for n in network.nodes()][0] | ||||
|   | ||||
| @@ -23,7 +23,9 @@ DATA_DIR = TEST_DIR / 'data' | ||||
| EQPT_FILENAME = DATA_DIR / 'eqpt_config.json' | ||||
| NETWORK_FILENAME = DATA_DIR / 'testTopology_auto_design_expected.json' | ||||
| SERVICE_FILENAME = DATA_DIR / 'testTopology_services_expected.json' | ||||
| equipment = load_equipment(EQPT_FILENAME) | ||||
| EXTRA_CONFIGS = {"std_medium_gain_advanced_config.json": DATA_DIR / "std_medium_gain_advanced_config.json", | ||||
|                  "Juniper-BoosterHG.json": DATA_DIR / "Juniper-BoosterHG.json"} | ||||
| equipment = load_equipment(EQPT_FILENAME, EXTRA_CONFIGS) | ||||
|  | ||||
|  | ||||
| @pytest.fixture() | ||||
|   | ||||
| @@ -18,8 +18,12 @@ from gnpy.core.network import build_network | ||||
| from gnpy.tools.json_io import load_network, load_equipment, network_from_json | ||||
|  | ||||
|  | ||||
| network_file_name = Path(__file__).parent.parent / 'tests/LinkforTest.json' | ||||
| eqpt_library_name = Path(__file__).parent.parent / 'tests/data/eqpt_config.json' | ||||
| TEST_DIR = Path(__file__).parent | ||||
| DATA_DIR = TEST_DIR / 'data' | ||||
| network_file_name = DATA_DIR / 'LinkforTest.json' | ||||
| eqpt_library_name = DATA_DIR / 'eqpt_config.json' | ||||
| EXTRA_CONFIGS = {"std_medium_gain_advanced_config.json": DATA_DIR / "std_medium_gain_advanced_config.json", | ||||
|                  "Juniper-BoosterHG.json": DATA_DIR / "Juniper-BoosterHG.json"} | ||||
|  | ||||
|  | ||||
| @pytest.fixture(params=[(96, 0.05e12), (60, 0.075e12), (45, 0.1e12), (2, 0.1e12)], | ||||
| @@ -31,7 +35,7 @@ def nch_and_spacing(request): | ||||
|  | ||||
|  | ||||
| def propagation(input_power, con_in, con_out, dest): | ||||
|     equipment = load_equipment(eqpt_library_name) | ||||
|     equipment = load_equipment(eqpt_library_name, EXTRA_CONFIGS) | ||||
|     network = load_network(network_file_name, equipment) | ||||
|  | ||||
|     # parametrize the network elements with the con losses and adapt gain | ||||
| @@ -178,7 +182,7 @@ def test_json_element(error, json_data, expected_msg): | ||||
|     """ | ||||
|     Check that a missing key is correctly raisong the logger | ||||
|     """ | ||||
|     equipment = load_equipment(eqpt_library_name) | ||||
|     equipment = load_equipment(eqpt_library_name, EXTRA_CONFIGS) | ||||
|     network = network_from_json(json_data, equipment) | ||||
|     elem = next(e for e in network.nodes() if e.uid == 'Elem') | ||||
|     si = create_input_spectral_information(f_min=191.3e12, f_max=196.1e12, roll_off=0.15, | ||||
|   | ||||
| @@ -28,8 +28,11 @@ from gnpy.core.exceptions import ConfigurationError, NetworkTopologyError | ||||
|  | ||||
|  | ||||
| TEST_DIR = Path(__file__).parent | ||||
| EQPT_LIBRARY_NAME = TEST_DIR / 'data/eqpt_config.json' | ||||
| NETWORK_FILE_NAME = TEST_DIR / 'data/testTopology_expected.json' | ||||
| DATA_DIR = TEST_DIR / 'data' | ||||
| EQPT_FILENAME = DATA_DIR / 'eqpt_config.json' | ||||
| NETWORK_FILE_NAME = DATA_DIR / 'testTopology_expected.json' | ||||
| EXTRA_CONFIGS = {"std_medium_gain_advanced_config.json": DATA_DIR / "std_medium_gain_advanced_config.json", | ||||
|                  "Juniper-BoosterHG.json": DATA_DIR / "Juniper-BoosterHG.json"} | ||||
| # adding tests to check the roadm restrictions | ||||
|  | ||||
| # mark node_uid amps as fused for testing purpose | ||||
| @@ -39,7 +42,7 @@ def test_no_amp_feature(node_uid): | ||||
|     test_parser covers partly this behaviour. This test should guaranty that the | ||||
|     feature is preserved even if convert is changed | ||||
|     """ | ||||
|     equipment = load_equipment(EQPT_LIBRARY_NAME) | ||||
|     equipment = load_equipment(EQPT_FILENAME, EXTRA_CONFIGS) | ||||
|     json_network = load_json(NETWORK_FILE_NAME) | ||||
|  | ||||
|     for elem in json_network['elements']: | ||||
| @@ -82,7 +85,7 @@ def test_no_amp_feature(node_uid): | ||||
| @pytest.fixture() | ||||
| def equipment(): | ||||
|     """init transceiver class to access snr and osnr calculations""" | ||||
|     equipment = load_equipment(EQPT_LIBRARY_NAME) | ||||
|     equipment = load_equipment(EQPT_FILENAME, EXTRA_CONFIGS) | ||||
|     # define some booster and preamps | ||||
|     restrictions_list = [ | ||||
|         { | ||||
| @@ -131,7 +134,7 @@ def equipment(): | ||||
|         }] | ||||
|     # add them to the library | ||||
|     for entry in restrictions_list: | ||||
|         equipment['Edfa'][entry['type_variety']] = Amp.from_json(EQPT_LIBRARY_NAME, **entry) | ||||
|         equipment['Edfa'][entry['type_variety']] = Amp.from_json(EXTRA_CONFIGS, **entry) | ||||
|     return equipment | ||||
|  | ||||
|  | ||||
| @@ -223,7 +226,7 @@ def test_roadm_target_power(prev_node_type, effective_pch_out_db, power_dbm, roa | ||||
|     for the test where the prev_node in ROADM B is either an amplifier or a fused, so that the target | ||||
|     power can not be met in this last case. | ||||
|     """ | ||||
|     equipment = load_equipment(EQPT_LIBRARY_NAME) | ||||
|     equipment = load_equipment(EQPT_FILENAME, EXTRA_CONFIGS) | ||||
|     equipment['SI']['default'].power_dbm = power_dbm | ||||
|     json_network = load_json(TEST_DIR / 'data/twohops_roadm_power_test.json') | ||||
|     prev_node = next(n for n in json_network['elements'] if n['uid'] == 'west edfa in node B to ila2') | ||||
| @@ -448,7 +451,7 @@ def test_compare_design_propagation_settings(power_dbm, req_power, amp_with_delt | ||||
|         This test also checks all the possible combinations and expected before/after propagation | ||||
|         gain differences. It also checks delta_p applied due to saturation during design. | ||||
|     """ | ||||
|     eqpt = load_equipment(EQPT_LIBRARY_NAME) | ||||
|     eqpt = load_equipment(EQPT_FILENAME, EXTRA_CONFIGS) | ||||
|     eqpt['SI']['default'].power_dbm = power_dbm | ||||
|     json_network = load_json(NETWORK_FILE_NAME) | ||||
|     for element in json_network['elements']: | ||||
| @@ -550,14 +553,14 @@ def test_wrong_restrictions(restrictions, fail): | ||||
|     """Check that sanity_check correctly raises an error when restriction is incorrect and that library | ||||
|     correctly includes restrictions. | ||||
|     """ | ||||
|     json_data = load_json(EQPT_LIBRARY_NAME) | ||||
|     json_data = load_json(EQPT_FILENAME) | ||||
|     # define wrong restriction | ||||
|     json_data['Roadm'][0]['restrictions'] = restrictions | ||||
|     if fail: | ||||
|         with pytest.raises(ConfigurationError): | ||||
|             _ = _equipment_from_json(json_data, EQPT_LIBRARY_NAME) | ||||
|             _ = _equipment_from_json(json_data, EXTRA_CONFIGS) | ||||
|     else: | ||||
|         equipment = _equipment_from_json(json_data, EQPT_LIBRARY_NAME) | ||||
|         equipment = _equipment_from_json(json_data, EXTRA_CONFIGS) | ||||
|         assert equipment['Roadm']['example_test'].restrictions == restrictions | ||||
|  | ||||
|  | ||||
| @@ -574,7 +577,7 @@ def test_roadm_impairments(roadm, from_degree, to_degree, expected_impairment_id | ||||
|     for el in json_data['elements']: | ||||
|         if el['uid'] == 'roadm Lannion_CAS': | ||||
|             el['type_variety'] = 'example_detailed_impairments' | ||||
|     equipment = load_equipment(EQPT_LIBRARY_NAME) | ||||
|     equipment = load_equipment(EQPT_FILENAME, EXTRA_CONFIGS) | ||||
|     network = network_from_json(json_data, equipment) | ||||
|     build_network(network, equipment, 0.0, 20.0) | ||||
|     roadm = next(n for n in network.nodes() if n.uid == roadm) | ||||
| @@ -590,7 +593,7 @@ def test_roadm_impairments(roadm, from_degree, to_degree, expected_impairment_id | ||||
| def test_roadm_per_degree_impairments(type_variety, from_degree, to_degree, impairment_id, expected_type): | ||||
|     """Check that impairment type is correct also if per degree impairment is defined | ||||
|     """ | ||||
|     json_data = load_json(EQPT_LIBRARY_NAME) | ||||
|     json_data = load_json(EQPT_FILENAME) | ||||
|     assert 'type_variety' not in json_data['Roadm'][2] | ||||
|     json_data['Roadm'][2]['roadm-path-impairments'] = [ | ||||
|         { | ||||
| @@ -614,7 +617,7 @@ def test_roadm_per_degree_impairments(type_variety, from_degree, to_degree, impa | ||||
|                 "roadm-noise-figure": 23 | ||||
|             }] | ||||
|         }] | ||||
|     equipment = _equipment_from_json(json_data, EQPT_LIBRARY_NAME) | ||||
|     equipment = _equipment_from_json(json_data, EXTRA_CONFIGS) | ||||
|     assert equipment['Roadm']['default'].type_variety == 'default' | ||||
|  | ||||
|     json_data = load_json(NETWORK_FILE_NAME) | ||||
| @@ -647,7 +650,7 @@ def test_roadm_per_degree_impairments(type_variety, from_degree, to_degree, impa | ||||
| def test_wrong_roadm_per_degree_impairments(from_degree, to_degree, impairment_id, error, message): | ||||
|     """Check that wrong per degree definitions are correctly catched | ||||
|     """ | ||||
|     equipment = load_equipment(EQPT_LIBRARY_NAME) | ||||
|     equipment = load_equipment(EQPT_FILENAME, EXTRA_CONFIGS) | ||||
|     json_data = load_json(NETWORK_FILE_NAME) | ||||
|     for el in json_data['elements']: | ||||
|         if el['uid'] == 'roadm Lannion_CAS': | ||||
| @@ -680,7 +683,7 @@ def test_impairment_initialization(path_type, type_variety, expected_pmd, expect | ||||
|     - use roadm detailed impairment for the corresponding path_type if roadm type_variety has detailed impairments | ||||
|     - use roadm per degree impairment if they are defined | ||||
|     """ | ||||
|     equipment = load_equipment(EQPT_LIBRARY_NAME) | ||||
|     equipment = load_equipment(EQPT_FILENAME, EXTRA_CONFIGS) | ||||
|     extra_params = equipment['Roadm'][type_variety].__dict__ | ||||
|     roadm_config = { | ||||
|         "uid": "roadm Lannion_CAS", | ||||
|   | ||||
| @@ -30,6 +30,8 @@ DATA_DIR = TEST_DIR / 'data' | ||||
| EQPT_FILENAME = DATA_DIR / 'eqpt_config.json' | ||||
| NETWORK_FILENAME = DATA_DIR / 'testTopology_auto_design_expected.json' | ||||
| SERVICE_FILENAME = DATA_DIR / 'testTopology_services_expected.json' | ||||
| EXTRA_CONFIGS = {"std_medium_gain_advanced_config.json": DATA_DIR / "std_medium_gain_advanced_config.json", | ||||
|                  "Juniper-BoosterHG.json": DATA_DIR / "Juniper-BoosterHG.json"} | ||||
|  | ||||
| grid = 0.00625e12 | ||||
| slot = 0.0125e12 | ||||
| @@ -40,7 +42,7 @@ cband_freq_max = 196.1e12 | ||||
|  | ||||
| @pytest.fixture() | ||||
| def equipment(): | ||||
|     equipment = load_equipment(EQPT_FILENAME) | ||||
|     equipment = load_equipment(EQPT_FILENAME, EXTRA_CONFIGS) | ||||
|     return equipment | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -17,8 +17,11 @@ from gnpy.tools.json_io import load_equipment, load_json, _equipment_from_json | ||||
|  | ||||
|  | ||||
| TEST_DIR = Path(__file__).parent | ||||
| EQPT_LIBRARY_NAME = TEST_DIR / 'data/eqpt_config.json' | ||||
| NETWORK_FILE_NAME = TEST_DIR / 'data/testTopology_expected.json' | ||||
| DATA_DIR = TEST_DIR / 'data' | ||||
| EQPT_LIBRARY_NAME = DATA_DIR / 'eqpt_config.json' | ||||
| NETWORK_FILE_NAME = DATA_DIR / 'testTopology_expected.json' | ||||
| EXTRA_CONFIGS = {"std_medium_gain_advanced_config.json": DATA_DIR / "std_medium_gain_advanced_config.json", | ||||
|                  "Juniper-BoosterHG.json": DATA_DIR / "Juniper-BoosterHG.json"} | ||||
|  | ||||
|  | ||||
| @pytest.mark.parametrize('trx_type, trx_mode, error_message, no_error, expected_result', | ||||
| @@ -91,7 +94,7 @@ def test_trx_mode_params(trx_type, trx_mode, error_message, no_error, expected_r | ||||
|         'penalties': None, | ||||
|         'cost': None | ||||
|     } | ||||
|     equipment = load_equipment(EQPT_LIBRARY_NAME) | ||||
|     equipment = load_equipment(EQPT_LIBRARY_NAME, EXTRA_CONFIGS) | ||||
|     if no_error: | ||||
|         trx_params = trx_mode_params(equipment, trx_type, trx_mode, error_message) | ||||
|         print(trx_params) | ||||
| @@ -150,7 +153,7 @@ def test_wrong_baudrate_spacing(baudrate, spacing, error_message): | ||||
|             'equalization_offset_db': 0}] | ||||
|     } | ||||
|     json_data['Transceiver'].append(wrong_transceiver) | ||||
|     equipment = _equipment_from_json(json_data, EQPT_LIBRARY_NAME) | ||||
|     equipment = _equipment_from_json(json_data, EXTRA_CONFIGS) | ||||
|  | ||||
|     with pytest.raises(EquipmentConfigError, match=error_message): | ||||
|         _ = trx_mode_params(equipment, 'vendorB_trx-type1', 'wrong mode', error_message=False) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user