From 83e9bccd521c09b377503040b0eb9d69a08307a4 Mon Sep 17 00:00:00 2001 From: EstherLerouzic Date: Thu, 6 Jan 2022 15:07:20 +0100 Subject: [PATCH] Only propagates carriers that belong to Amp bandwidth The commit introduces mux/demux functions in amps and ensures that the propagation is only done on carriers that are in the Amp bandwitdh, ie with all their spectrum including slot width is in bandwidth. For consistency, default amp f_min is changed: Objective is to use amplifiers' band to bound the possible frequencies to be propagated. Since the current default f_min of Amp in json_io.py is higher than the SI one, this would result in a different nb of channels than currently used in tests, and a change in all tests. In order to avoid this, I preferred to change this value and have consistency between SI f_min and Amp f_min. The commits adds a set of functions to make amps band the useable spectrum on each OMS. Thee OMS generation is changed to use the amp band. The commit adds filtering functions (demux and mux) to filter out spectrum which is not in the amplifier band. Spectrum assignment is also corrected to correctly match the amp bandwidth constraint with guardband: center frequency index must be within the usable part of the amp band. This changes a bit the notion of freq_index and guardband in the functions, but this is transparent to user: f_min, f_max represent the amp band, while self.freq_index_min/max represent the center frequency boundary for a reference 50GHz channel. Signed-off-by: EstherLerouzic Change-Id: I225b2b2dc0e1f1992c0460f6e08fa9c9bc641edf --- gnpy/core/elements.py | 11 ++- gnpy/core/info.py | 52 ++++++++++++- gnpy/core/parameters.py | 12 +-- gnpy/core/utils.py | 47 +++++++++++ gnpy/example-data/default_edfa_config.json | 4 +- .../std_medium_gain_advanced_config.json | 4 +- gnpy/tools/json_io.py | 28 ++++++- gnpy/topology/request.py | 40 +++++++++- gnpy/topology/spectrum_assignment.py | 77 +++++++++++++++---- tests/data/default_edfa_config.json | 4 +- .../data/std_medium_gain_advanced_config.json | 5 +- tests/test_amplifier.py | 52 ++++++------- tests/test_spectrum_assignment.py | 23 +++--- 13 files changed, 286 insertions(+), 73 deletions(-) diff --git a/gnpy/core/elements.py b/gnpy/core/elements.py index 12eab02a5..cf0f91584 100644 --- a/gnpy/core/elements.py +++ b/gnpy/core/elements.py @@ -34,7 +34,7 @@ from gnpy.core.parameters import RoadmParams, FusedParams, FiberParams, PumpParams, EdfaParams, EdfaOperational, \ RoadmPath, RoadmImpairment from gnpy.core.science_utils import NliSolver, RamanSolver -from gnpy.core.info import SpectralInformation +from gnpy.core.info import SpectralInformation, demuxed_spectral_information from gnpy.core.exceptions import NetworkTopologyError, SpectrumError, ParametersError @@ -1204,5 +1204,10 @@ def propagate(self, spectral_info): self.propagated_labels = spectral_info.label def __call__(self, spectral_info): - self.propagate(spectral_info) - return spectral_info + # filter out carriers outside the amplifier band + band = next(b for b in self.params.bands) + spectral_info = demuxed_spectral_information(spectral_info, band) + if spectral_info.carriers: + self.propagate(spectral_info) + return spectral_info + raise ValueError(f'Amp {self.uid} Defined propagation band does not match amplifiers band.') diff --git a/gnpy/core/info.py b/gnpy/core/info.py index 684c96817..05c665156 100644 --- a/gnpy/core/info.py +++ b/gnpy/core/info.py @@ -11,7 +11,7 @@ from __future__ import annotations from collections import namedtuple from collections.abc import Iterable -from typing import Union +from typing import Union, List from dataclasses import dataclass from numpy import argsort, mean, array, append, ones, ceil, any, zeros, outer, full, ndarray, asarray @@ -317,6 +317,56 @@ def create_input_spectral_information(f_min, f_max, roll_off, baud_rate, spacing tx_osnr=tx_osnr, tx_power=tx_power, label=label) +def is_in_band(frequency: float, band: dict) -> bool: + """band has {"f_min": value, "f_max": value} format + """ + if frequency >= band['f_min'] and frequency <= band['f_max']: + return True + return False + + +def demuxed_spectral_information(input_si: SpectralInformation, band: dict) -> SpectralInformation: + """extract a si based on band + """ + filtered_indices = [i for i, f in enumerate(input_si.frequency) + if is_in_band(f - input_si.slot_width[i] / 2, band) + and is_in_band(f + input_si.slot_width[i] / 2, band)] + if filtered_indices: + frequency = input_si.frequency[filtered_indices] + baud_rate = input_si.baud_rate[filtered_indices] + slot_width = input_si.slot_width[filtered_indices] + signal = input_si.signal[filtered_indices] + nli = input_si.nli[filtered_indices] + ase = input_si.ase[filtered_indices] + roll_off = input_si.roll_off[filtered_indices] + chromatic_dispersion = input_si.chromatic_dispersion[filtered_indices] + pmd = input_si.pmd[filtered_indices] + pdl = input_si.pdl[filtered_indices] + latency = input_si.latency[filtered_indices] + delta_pdb_per_channel = input_si.delta_pdb_per_channel[filtered_indices] + tx_osnr = input_si.tx_osnr[filtered_indices] + tx_power = input_si.tx_power[filtered_indices] + label = input_si.label[filtered_indices] + + return SpectralInformation(frequency=frequency, baud_rate=baud_rate, slot_width=slot_width, signal=signal, + nli=nli, ase=ase, roll_off=roll_off, chromatic_dispersion=chromatic_dispersion, + pmd=pmd, pdl=pdl, latency=latency, delta_pdb_per_channel=delta_pdb_per_channel, + tx_osnr=tx_osnr, tx_power=tx_power, label=label) + return None + + +def muxed_spectral_information(input_si_list: List[SpectralInformation]) -> SpectralInformation: + """return the assembled spectrum + """ + if input_si_list and len(input_si_list) > 1: + si = input_si_list[0] + muxed_spectral_information(input_si_list[1:]) + return si + elif input_si_list and len(input_si_list) == 1: + return input_si_list[0] + else: + raise ValueError('liste vide') + + def carriers_to_spectral_information(initial_spectrum: dict[float, Carrier], power: float) -> SpectralInformation: """Initial spectrum is a dict with key = carrier frequency, and value a Carrier object. diff --git a/gnpy/core/parameters.py b/gnpy/core/parameters.py index 9dab48f99..2541241ed 100644 --- a/gnpy/core/parameters.py +++ b/gnpy/core/parameters.py @@ -463,10 +463,10 @@ def asdict(self): class EdfaParams: default_values = { - 'f_min': 191.3e12, - 'f_max': 196.1e12, + 'f_min': None, + 'f_max': None, 'multi_band': None, - 'bands': [], + 'bands': None, 'type_variety': '', 'type_def': '', 'gain_flatmax': None, @@ -502,9 +502,11 @@ def __init__(self, **params): # Bandwidth self.f_min = params['f_min'] self.f_max = params['f_max'] - self.bandwidth = self.f_max - self.f_min - self.f_cent = (self.f_max + self.f_min) / 2 + self.bandwidth = self.f_max - self.f_min if self.f_max and self.f_min else None + self.f_cent = (self.f_max + self.f_min) / 2 if self.f_max and self.f_min else None self.f_ripple_ref = params['f_ripple_ref'] + self.bands = [{'f_min': params['f_min'], + 'f_max': params['f_max']}] # Gain self.gain_flatmax = params['gain_flatmax'] diff --git a/gnpy/core/utils.py b/gnpy/core/utils.py index 5fc7b9d15..ea226765b 100644 --- a/gnpy/core/utils.py +++ b/gnpy/core/utils.py @@ -12,6 +12,7 @@ from numpy import pi, cos, sqrt, log10, linspace, zeros, shape, where, logical_and, mean, array from scipy import constants from copy import deepcopy +from typing import List from gnpy.core.exceptions import ConfigurationError @@ -469,3 +470,49 @@ def calculate_absolute_min_or_zero(x: array) -> array: array([1., 0., 3.]) """ return (abs(x) - x) / 2 + + +def find_common_range(amp_bands: List[List[dict]], default_band_f_min: float, default_band_f_max: float) \ + -> List[dict]: + """Find the common frequency range of bands + If there are no amplifiers in the path, then use default band + + >>> amp_bands = [[{'f_min': 191e12, 'f_max' : 195e12}, {'f_min': 186e12, 'f_max' : 190e12} ], \ + [{'f_min': 185e12, 'f_max' : 189e12}, {'f_min': 192e12, 'f_max' : 196e12}], \ + [{'f_min': 186e12, 'f_max': 193e12}]] + >>> find_common_range(amp_bands, 190e12, 195e12) + [{'f_min': 186000000000000.0, 'f_max': 189000000000000.0}, {'f_min': 192000000000000.0, 'f_max': 193000000000000.0}] + >>> amp_bands = [[{'f_min': 191e12, 'f_max' : 195e12}, {'f_min': 186e12, 'f_max' : 190e12} ], \ + [{'f_min': 185e12, 'f_max' : 189e12}, {'f_min': 192e12, 'f_max' : 196e12}], \ + [{'f_min': 186e12, 'f_max': 192e12}]] + >>> find_common_range(amp_bands, 190e12, 195e12) + [{'f_min': 186000000000000.0, 'f_max': 189000000000000.0}] + + """ + _amp_bands = [sorted(amp, key=lambda x: x['f_min']) for amp in amp_bands] + _temp = [] + # remove None bands + for amp in _amp_bands: + is_band = True + for band in amp: + if not (is_band and band['f_min'] and band['f_max']): + is_band = False + if is_band: + _temp.append(amp) + + # remove duplicate + unique_amp_bands = [] + for amp in _temp: + if amp not in unique_amp_bands: + unique_amp_bands.append(amp) + if unique_amp_bands: + common_range = unique_amp_bands[0] + else: + if default_band_f_min is None or default_band_f_max is None: + return [] + common_range = [{'f_min': default_band_f_min, 'f_max': default_band_f_max}] + for bands in unique_amp_bands: + common_range = [{'f_min': max(first['f_min'], second['f_min']), 'f_max': min(first['f_max'], second['f_max'])} + for first in common_range for second in bands + if max(first['f_min'], second['f_min']) < min(first['f_max'], second['f_max'])] + return sorted(common_range, key=lambda x: x['f_min']) diff --git a/gnpy/example-data/default_edfa_config.json b/gnpy/example-data/default_edfa_config.json index 8f2bc1c3d..bae7c115a 100644 --- a/gnpy/example-data/default_edfa_config.json +++ b/gnpy/example-data/default_edfa_config.json @@ -5,8 +5,8 @@ "gain_ripple": [ 0.0 ], - "f_min": 191.35e12, - "f_max": 196.1e12, + "f_min": 191.275e12, + "f_max": 196.125e12, "dgt": [ 1.0, 1.017807767853702, diff --git a/gnpy/example-data/std_medium_gain_advanced_config.json b/gnpy/example-data/std_medium_gain_advanced_config.json index 47db0fbbf..6c83a5316 100644 --- a/gnpy/example-data/std_medium_gain_advanced_config.json +++ b/gnpy/example-data/std_medium_gain_advanced_config.json @@ -5,8 +5,8 @@ 0.0359549, 5.82851 ], - "f_min": 191.35e12, - "f_max": 196.1e12, + "f_min": 191.275e12, + "f_max": 196.125e12, "nf_ripple": [ 0.4372876328262819, 0.4372876328262819, diff --git a/gnpy/tools/json_io.py b/gnpy/tools/json_io.py index 32d0b84f7..bd15f309e 100644 --- a/gnpy/tools/json_io.py +++ b/gnpy/tools/json_io.py @@ -192,7 +192,7 @@ def __init__(self, **kwargs): @classmethod def from_json(cls, filename, **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 type_variety = kwargs['type_variety'] type_def = kwargs.get('type_def', 'variable_gain') # default compatibility with older json eqpt files nf_def = None @@ -367,6 +367,31 @@ def _update_dual_stage(equipment): return equipment +def _update_band(equipment: dict) -> dict: + """Creates a list of bands for this amplifier, and remove other parameters which are not applicable + """ + amp_dict = equipment['Edfa'] + for amplifier in amp_dict.values(): + if amplifier.type_def != 'multi_band': + amplifier.bands = [{'f_min': amplifier.f_min, + 'f_max': amplifier.f_max}] + # updates band parameter + else: + _bands = [{'f_min': amp_dict[a].f_min, + 'f_max': amp_dict[a].f_max} for a in amp_dict[amplifier.type_variety].multi_band] + # remove duplicates + amplifier.bands = [] + for b in _bands: + if b not in amplifier.bands: + amplifier.bands.append(b) + # remove non applicable parameters + for key in ['f_min', 'f_max', 'gain_flatmax', 'gain_min', 'p_max', 'nf_model', 'dual_stage_model', + 'nf_fit_coeff', 'nf_ripple', 'dgt', 'gain_ripple']: + delattr(amplifier, key) + + return equipment + + def _roadm_restrictions_sanity_check(equipment): """verifies that booster and preamp restrictions specified in roadm equipment are listed in the edfa.""" for roadm_type, roadm_eqpt in equipment['Roadm'].items(): @@ -428,6 +453,7 @@ def _equipment_from_json(json_data, filename): raise EquipmentConfigError(f'Unrecognized network element type "{key}"') _check_fiber_vs_raman_fiber(equipment) equipment = _update_dual_stage(equipment) + equipment = _update_band(equipment) _roadm_restrictions_sanity_check(equipment) return equipment diff --git a/gnpy/topology/request.py b/gnpy/topology/request.py index 197ed2668..9d907e631 100644 --- a/gnpy/topology/request.py +++ b/gnpy/topology/request.py @@ -16,14 +16,17 @@ """ from collections import namedtuple, OrderedDict +from typing import List from logging import getLogger from networkx import (dijkstra_path, NetworkXNoPath, all_simple_paths, shortest_simple_paths) from networkx.utils import pairwise from numpy import mean, argmin -from gnpy.core.elements import Transceiver, Roadm -from gnpy.core.utils import lin2db -from gnpy.core.info import create_input_spectral_information, carriers_to_spectral_information + +from gnpy.core.elements import Transceiver, Roadm, Edfa +from gnpy.core.utils import lin2db, find_common_range +from gnpy.core.info import create_input_spectral_information, carriers_to_spectral_information, \ + demuxed_spectral_information, muxed_spectral_information, SpectralInformation from gnpy.core import network as network_module from gnpy.core.exceptions import ServiceError, DisjunctionError from copy import deepcopy @@ -332,14 +335,34 @@ def compute_constrained_path(network, req): return total_path +def filter_si(path: list, equipment: dict, si: SpectralInformation) -> SpectralInformation: + """Filter spectral information based on the amplifiers common range""" + # First retrieve f_min, f_max spectrum according to amplifiers' spectrum on the path + common_range = find_elements_common_range(path, equipment) + # filter out frequencies that should not be created + filtered_si = [] + for band in common_range: + temp = demuxed_spectral_information(si, band) + if temp: + filtered_si.append(temp) + if not filtered_si: + raise ValueError('Defined propagation band does not match amplifiers band.') + return muxed_spectral_information(filtered_si) + + def propagate(path, req, equipment): - """propagates signals in each element according to initial spectrum set by user""" + """propagates signals in each element according to initial spectrum set by user + Spectrum is specified in request through f_min, f_max and spacing, or initial_spectrum + and amps frequency band on the path is used to filter out frequencies""" + # generates spectrum based on request if req.initial_spectrum is not None: si = carriers_to_spectral_information(initial_spectrum=req.initial_spectrum, power=req.power) else: si = create_input_spectral_information( f_min=req.f_min, f_max=req.f_max, roll_off=req.roll_off, baud_rate=req.baud_rate, spacing=req.spacing, tx_osnr=req.tx_osnr, tx_power=req.tx_power, delta_pdb=req.offset_db) + # filter out frequencies that should not be created + si = filter_si(path, equipment, si) roadm_osnr = [] for i, el in enumerate(path): if isinstance(el, Roadm): @@ -385,6 +408,7 @@ def propagate_and_optimize_mode(path, req, equipment): baud_rate=this_br, spacing=req.spacing, delta_pdb=this_offset, tx_osnr=req.tx_osnr, tx_power=req.tx_power) + spc_info = filter_si(path, equipment, spc_info) roadm_osnr = [] for i, el in enumerate(path): if isinstance(el, Roadm): @@ -1225,3 +1249,11 @@ def _penalty_msg(total_path, msg, min_ind): else: msg += f'\n\t{pretty} penalty not evaluated' return msg + + +def find_elements_common_range(el_list: list, equipment: dict) -> List[dict]: + """Find the common frequency range of amps of a given list of elements (for example an OMS or a path) + If there are no amplifiers in the path, then use the SI + """ + amp_bands = [n.params.bands for n in el_list if isinstance(n, (Edfa))] + return find_common_range(amp_bands, equipment['SI']['default'].f_min, equipment['SI']['default'].f_max) diff --git a/gnpy/topology/spectrum_assignment.py b/gnpy/topology/spectrum_assignment.py index 5d6ceed3e..4caaeacaf 100644 --- a/gnpy/topology/spectrum_assignment.py +++ b/gnpy/topology/spectrum_assignment.py @@ -15,28 +15,30 @@ from collections import namedtuple from logging import getLogger -from gnpy.core.elements import Roadm, Transceiver +from gnpy.core.elements import Roadm, Transceiver, Edfa from gnpy.core.exceptions import ServiceError, SpectrumError from gnpy.core.utils import order_slots, restore_order -from gnpy.topology.request import compute_spectrum_slot_vs_bandwidth +from gnpy.topology.request import compute_spectrum_slot_vs_bandwidth, find_elements_common_range LOGGER = getLogger(__name__) +GUARDBAND = 25e9 class Bitmap: """records the spectrum occupation""" - def __init__(self, f_min, f_max, grid, guardband=0.15e12, bitmap=None): - # n is the min index including guardband. Guardband is require to be sure + def __init__(self, f_min, f_max, grid, guardband=GUARDBAND, bitmap=None): + # n is the min index including guardband. Guardband is required to be sure # that a channel can be assigned with center frequency fmin (means that its # slot occupation goes below freq_index_min - n_min = frequency_to_n(f_min - guardband, grid) - n_max = frequency_to_n(f_max + guardband, grid) - 1 + n_min = frequency_to_n(f_min, grid) + n_max = frequency_to_n(f_max, grid) self.n_min = n_min self.n_max = n_max - self.freq_index_min = frequency_to_n(f_min) - self.freq_index_max = frequency_to_n(f_max) + self.freq_index_min = frequency_to_n(f_min + guardband) + self.freq_index_max = frequency_to_n(f_max - guardband) self.freq_index = list(range(n_min, n_max + 1)) + self.guardband = guardband if bitmap is None: self.bitmap = [1] * (n_max - n_min + 1) elif len(bitmap) == len(self.freq_index): @@ -83,7 +85,6 @@ def __init__(self, *args, **params): self.spectrum_bitmap = [] self.nb_channels = 0 self.service_list = [] - # TODO def __str__(self): return '\n\t'.join([f'{type(self).__name__} {self.oms_id}', @@ -98,7 +99,7 @@ def add_element(self, elem): self.el_id_list.append(elem.uid) self.el_list.append(elem) - def update_spectrum(self, f_min, f_max, guardband=0.15e12, existing_spectrum=None, grid=0.00625e12): + def update_spectrum(self, f_min, f_max, guardband=GUARDBAND, existing_spectrum=None, grid=0.00625e12): """Frequencies expressed in Hz. Add 150 GHz margin to enable a center channel on f_min Use ITU-T G694.1 Flexible DWDM grid definition @@ -226,6 +227,40 @@ def align_grids(oms_list): return oms_list +def find_network_freq_range(network, equipment): + """Find the lowest freq from amps and highest freq among all amps to determine the resulting bitmap + """ + amp_bands = [band for n in network.nodes() if isinstance(n, Edfa) for band in n.params.bands] + min_frequencies = [a['f_min'] for a in amp_bands] + max_frequencies = [a['f_max'] for a in amp_bands] + return min(min_frequencies), max(max_frequencies) + + +def create_oms_bitmap(oms, equipment, f_min, f_max, guardband, grid): + """Find the highest low freq from oms amps and lowest high freq among oms amps to determine + the possible bitmap window. + f_min and f_max represent the useable spectrum (not the useable center frequencies) + ie n smaller than frequency_to_n(min_freq, grid) are not useable + """ + n_min = frequency_to_n(f_min, grid) + n_max = frequency_to_n(f_max, grid) - 1 + common_range = find_elements_common_range(oms.el_list, equipment) + band0 = common_range[0] + band0_n_min = frequency_to_n(band0['f_min'], grid) + band0_n_max = frequency_to_n(band0['f_max'], grid) + bitmap = [0] * (band0_n_min - n_min) + [1] * (band0_n_max - band0_n_min + 1) + i = 1 + while i < len(common_range): + band = common_range[i] + band_n_min = frequency_to_n(band['f_min'], grid) + band_n_max = frequency_to_n(band['f_max'], grid) + bitmap = bitmap + [0] * (band_n_min - band0_n_max - 1) + [1] * (band_n_max - band_n_min + 1) + band0_n_max = band_n_max + i += 1 + bitmap = bitmap + [0] * (n_max - band0_n_max) + return bitmap + + def build_oms_list(network, equipment): """initialization of OMS list in the network @@ -237,7 +272,15 @@ def build_oms_list(network, equipment): """ oms_id = 0 oms_list = [] - for node in [n for n in network.nodes() if isinstance(n, Roadm)]: + # identify all vertices of OMS: of course ROADM, but aso links to external chassis transponders + oms_vertices = [n for n in network.nodes() if isinstance(n, Roadm)] +\ + [n for n in network.nodes() if isinstance(n, Transceiver) + and not isinstance(next(network.successors(n)), Roadm)] + # determine the size of the bitmap common to all the omses: find min and max frequencies of all amps + # in the network. These gives the band not the center frequency. Thhen we use a reference channel + # slot width (50GHz) to set the f_min, f_max + f_min, f_max = find_network_freq_range(network, equipment) + for node in oms_vertices: for edge in network.edges([node]): if not isinstance(edge[1], Transceiver): nd_in = edge[0] # nd_in is a Roadm @@ -271,8 +314,9 @@ def build_oms_list(network, equipment): nd_out.oms_list = [] nd_out.oms_list.append(oms_id) - oms.update_spectrum(equipment['SI']['default'].f_min, - equipment['SI']['default'].f_max, grid=0.00625e12) + bitmap = create_oms_bitmap(oms, equipment, f_min=f_min, f_max=f_max, guardband=GUARDBAND, + grid=0.00625e12) + oms.update_spectrum(f_min, f_max, guardband=GUARDBAND, grid=0.00625e12, existing_spectrum=bitmap) # oms.assign_spectrum(13,7) gives back (193137500000000.0, 193225000000000.0) # as in the example in the standard # oms.assign_spectrum(13,7) @@ -333,10 +377,11 @@ def aggregate_oms_bitmap(path_oms, oms_list): 'el_id_list': 0, 'el_list': [] } - freq_min = nvalue_to_frequency(spectrum.freq_index_min) - freq_max = nvalue_to_frequency(spectrum.freq_index_max) + freq_min = nvalue_to_frequency(spectrum.n_min) + freq_max = nvalue_to_frequency(spectrum.n_max) aggregate_oms = OMS(**params) - aggregate_oms.update_spectrum(freq_min, freq_max, grid=0.00625e12, existing_spectrum=bitmap) + aggregate_oms.update_spectrum(freq_min, freq_max, grid=0.00625e12, guardband=spectrum.guardband, + existing_spectrum=bitmap) return aggregate_oms diff --git a/tests/data/default_edfa_config.json b/tests/data/default_edfa_config.json index f0acc864e..defde4985 100644 --- a/tests/data/default_edfa_config.json +++ b/tests/data/default_edfa_config.json @@ -1,6 +1,6 @@ { - "f_min": 191.35e12, - "f_max": 196.1e12, + "f_min": 191.275e12, + "f_max": 196.125e12, "nf_ripple": [ 0.0, 0.0, diff --git a/tests/data/std_medium_gain_advanced_config.json b/tests/data/std_medium_gain_advanced_config.json index 5e8e3afd1..d07bb328e 100644 --- a/tests/data/std_medium_gain_advanced_config.json +++ b/tests/data/std_medium_gain_advanced_config.json @@ -1,4 +1,7 @@ -{ "nf_fit_coeff": [ +{ + "f_min": 191.275e12, + "f_max": 196.125e12, + "nf_fit_coeff": [ 0.000168241, 0.0469961, 0.0359549, diff --git a/tests/test_amplifier.py b/tests/test_amplifier.py index 05e1113eb..8905d2175 100644 --- a/tests/test_amplifier.py +++ b/tests/test_amplifier.py @@ -251,35 +251,35 @@ def test_amp_behaviour(tilt_target, delta_p): else: if delta_p != 2: expected_sig_out = [ - -32.00529182, -31.93540907, -31.86554231, -31.79417979, -31.71903263, - -31.6424009, -31.56531159, -31.48775435, -31.41468382, -31.35973323, - -31.32286555, -31.28602346, -31.2472908, -31.20086569, -31.14671746, - -31.08702653, -31.01341963, -30.93430243, -30.87791656, -30.84413339, - -30.81605918, -30.78824936, -30.76071036, -30.73319161, -30.70494101, - -30.67368479, -30.63941012, -30.60178381, -30.55585766, -30.5066561, - -30.43426575, -30.33848379, -30.24471112, -30.18220815, -30.15076699, - -30.11934744, -30.08776718, -30.05548097, -30.02250068, -29.98954302, - -29.95661362, -29.92370274, -29.8854762, -29.84193785, -29.79238328, - -29.72452662, -29.6385071, -29.54788144, -29.44581202, -29.33924103, - -29.23276107, -29.10289365, -28.91425473, -28.70204648, -28.50670713, - -28.3282514, -28.15895225, -28.009065, -27.87864672, -27.76315964, - -27.68523133, -27.62260405, -27.58076622] + -31.95025022, -31.88168886, -31.81178634, -31.73838831, -31.66318631, + -31.58762141, -31.51156294, -31.43760161, -31.38124626, -31.34245197, + -31.30629475, -31.26970711, -31.22566555, -31.17412914, -31.11806869, + -31.05122228, -30.97358131, -30.90658619, -30.86616148, -30.83854197, + -30.81115028, -30.78403337, -30.7570206, -30.73002834, -30.70088634, + -30.66844432, -30.63427939, -30.59364514, -30.54659009, -30.49180643, + -30.41406352, -30.31434813, -30.22984104, -30.18249387, -30.1516453, + -30.12082034, -30.08970494, -30.05779424, -30.02543415, -29.99309889, + -29.96078803, -29.92798594, -29.89002127, -29.84689015, -29.79726968, + -29.72927112, -29.64485972, -29.55578693, -29.45569694, -29.35111795, + -29.24662471, -29.12148491, -28.94244964, -28.73421833, -28.53930479, + -28.36231261, -28.19361236, -28.04376778, -27.91280403, -27.79433658, + -27.7065072, -27.64495288, -27.59798975] else: expected_sig_out = [ - -30.00529182, -29.93540907, -29.86554231, -29.79417979, -29.71903263, - -29.6424009, -29.56531159, -29.48775435, -29.41468382, -29.35973323, - -29.32286555, -29.28602346, -29.2472908, -29.20086569, -29.14671746, - -29.08702653, -29.01341963, -28.93430243, -28.87791656, -28.84413339, - -28.81605918, -28.78824936, -28.76071036, -28.73319161, -28.70494101, - -28.67368479, -28.63941012, -28.60178381, -28.55585766, -28.5066561, - -28.43426575, -28.33848379, -28.24471112, -28.18220815, -28.15076699, - -28.11934744, -28.08776718, -28.05548097, -28.02250068, -27.98954302, - -27.95661362, -27.92370274, -27.8854762, -27.84193785, -27.79238328, - -27.72452662, -27.6385071, -27.54788144, -27.44581202, -27.33924103, - -27.23276107, -27.10289365, -26.91425473, -26.70204648, -26.50670713, - -26.3282514, -26.15895225, -26.009065, -25.87864672, -25.76315964, - -25.68523133, -25.62260405, -25.58076622] + -29.95025022, -29.88168886, -29.81178634, -29.73838831, -29.66318631, + -29.58762141, -29.51156294, -29.43760161, -29.38124626, -29.34245197, + -29.30629475, -29.26970711, -29.22566555, -29.17412914, -29.11806869, + -29.05122228, -28.97358131, -28.90658619, -28.86616148, -28.83854197, + -28.81115028, -28.78403337, -28.7570206, -28.73002834, -28.70088634, + -28.66844432, -28.63427939, -28.59364514, -28.54659009, -28.49180643, + -28.41406352, -28.31434813, -28.22984104, -28.18249387, -28.1516453, + -28.12082034, -28.08970494, -28.05779424, -28.02543415, -27.99309889, + -27.96078803, -27.92798594, -27.89002127, -27.84689015, -27.79726968, + -27.72927112, -27.64485972, -27.55578693, -27.45569694, -27.35111795, + -27.24662471, -27.12148491, -26.94244964, -26.73421833, -26.53930479, + -26.36231261, -26.19361236, -26.04376778, -25.91280403, -25.79433658, + -25.7065072, -25.64495288, -25.59798975] print(sig_out) assert_allclose(sig_out, expected_sig_out, rtol=1e-9) diff --git a/tests/test_spectrum_assignment.py b/tests/test_spectrum_assignment.py index d74f4d09d..b7a5cbe71 100644 --- a/tests/test_spectrum_assignment.py +++ b/tests/test_spectrum_assignment.py @@ -33,7 +33,7 @@ grid = 0.00625e12 slot = 0.0125e12 -guardband = 0.15e12 +guardband = 25.0e9 cband_freq_min = 191.3e12 cband_freq_max = 196.1e12 @@ -101,14 +101,15 @@ def test_wrong_values(nval, mval, setup): def test_aligned(nmin, nmax, setup): """Checks that the OMS grid is correctly aligned - Note that bitmap index uses guardband on both ends so that if nmin, nmax = -200, +200, + Note that bitmap index uses guardband on both ends so that if center frequencies nmin, nmax = -200, +200, min/max navalue in bitmap are -224, +223, which makes 223 -(-224) +1 frequencies. """ network, oms_list = setup nguard = guardband / grid center = 193.1e12 - freq_min = center + nmin * grid - freq_max = center + nmax * grid + # amplification band + freq_min = center + nmin * grid - guardband + freq_max = center + nmax * grid + guardband random_oms = oms_list[10] # We're always starting with full C-band @@ -116,9 +117,9 @@ def test_aligned(nmin, nmax, setup): assert pytest.approx(nvalue_to_frequency(random_oms.spectrum_bitmap.freq_index_max) * 1e-12, abs=1e-12) == 196.1 ind_max = len(random_oms.spectrum_bitmap.bitmap) - 1 - # "inner" frequencies, without the guard baand + # "inner" frequencies, without the guard band inner_n_min = random_oms.spectrum_bitmap.getn(0) + nguard - inner_n_max = random_oms.spectrum_bitmap.getn(ind_max) - nguard + 1 + inner_n_max = random_oms.spectrum_bitmap.getn(ind_max) - nguard assert inner_n_min == random_oms.spectrum_bitmap.freq_index_min assert inner_n_max == random_oms.spectrum_bitmap.freq_index_max assert inner_n_min == -288 @@ -136,7 +137,7 @@ def test_aligned(nmin, nmax, setup): ind_max = len(random_oms.spectrum_bitmap.bitmap) - 1 inner_n_min = random_oms.spectrum_bitmap.getn(0) + nguard - inner_n_max = random_oms.spectrum_bitmap.getn(ind_max) - nguard + 1 + inner_n_max = random_oms.spectrum_bitmap.getn(ind_max) - nguard assert inner_n_min == random_oms.spectrum_bitmap.freq_index_min assert inner_n_max == random_oms.spectrum_bitmap.freq_index_max @@ -198,18 +199,20 @@ def test_assign_and_sum(nval1, nval2, setup): def test_bitmap_assignment(setup): """test that a bitmap can be assigned""" - network, oms_list = setup + _, oms_list = setup random_oms = oms_list[2] random_oms.assign_spectrum(13, 7) btmp = deepcopy(random_oms.spectrum_bitmap.bitmap) # try a first assignment that must pass - spectrum_btmp = Bitmap(cband_freq_min, cband_freq_max, grid=0.00625e12, guardband=0.15e12, bitmap=btmp) + freq_min = nvalue_to_frequency(random_oms.spectrum_bitmap.n_min) + freq_max = nvalue_to_frequency(random_oms.spectrum_bitmap.n_max) + _ = Bitmap(freq_min, freq_max, grid=0.00625e12, guardband=guardband, bitmap=btmp) # try a wrong assignment that should not pass btmp = btmp[1:-1] with pytest.raises(SpectrumError): - spectrum_btmp = Bitmap(cband_freq_min, cband_freq_max, grid=0.00625e12, guardband=0.15e12, bitmap=btmp) + _ = Bitmap(cband_freq_min, cband_freq_max, grid=0.00625e12, guardband=guardband, bitmap=btmp) @pytest.fixture()