Ejemplo n.º 1
0
def test_auto_design_generation_fromxlsgainmode(tmpdir, xls_input,
                                                expected_json_output):
    """ tests generation of topology json
        test that the build network gives correct results in gain mode
    """
    equipment = load_equipment(eqpt_filename)
    network = load_network(xls_input, equipment)
    # in order to test the Eqpt sheet and load gain target,
    # change the power-mode to False (to be in gain mode)
    equipment['Span']['default'].power_mode = False
    # Build the network once using the default power defined in SI in eqpt config

    p_db = equipment['SI']['default'].power_dbm
    p_total_db = p_db + lin2db(
        automatic_nch(equipment['SI']['default'].f_min,
                      equipment['SI']['default'].f_max,
                      equipment['SI']['default'].spacing))
    build_network(network, equipment, p_db, p_total_db)
    actual_json_output = tmpdir / xls_input.with_name(
        xls_input.stem + '_auto_design').with_suffix('.json').name
    save_network(network, actual_json_output)
    actual = load_json(actual_json_output)
    unlink(actual_json_output)
    expected = load_json(expected_json_output)

    results = compare_networks(expected, actual)
    assert not results.elements.missing
    assert not results.elements.extra
    assert not results.elements.different
    assert not results.connections.missing
    assert not results.connections.extra
    assert not results.connections.different
Ejemplo n.º 2
0
def setup_trx():
    """init transceiver class to access snr and osnr calculations"""
    equipment = load_equipment(eqpt_library)
    network = load_network(test_network, equipment)
    build_network(network, equipment, 0, 20)
    trx = [n for n in network.nodes() if isinstance(n, Transceiver)][0]
    return trx
Ejemplo n.º 3
0
def test_excel_service_json_generation(xls_input, expected_json_output):
    """ test services creation
    """
    equipment = load_equipment(eqpt_filename)
    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
    p_total_db = p_db + lin2db(
        automatic_nch(equipment['SI']['default'].f_min,
                      equipment['SI']['default'].f_max,
                      equipment['SI']['default'].spacing))
    build_network(network, equipment, p_db, p_total_db)
    from_xls = read_service_sheet(xls_input,
                                  equipment,
                                  network,
                                  network_filename=DATA_DIR /
                                  'testTopology.xls')
    expected = load_json(expected_json_output)

    results = compare_services(expected, from_xls)
    assert not results.requests.missing
    assert not results.requests.extra
    assert not results.requests.different
    assert not results.synchronizations.missing
    assert not results.synchronizations.extra
    assert not results.synchronizations.different
Ejemplo n.º 4
0
def load_common_data(equipment_filename, topology_filename, simulation_filename, save_raw_network_filename):
    '''Load common configuration from JSON files'''

    try:
        equipment = load_equipment(equipment_filename)
        network = load_network(topology_filename, equipment)
        if save_raw_network_filename is not None:
            save_network(network, save_raw_network_filename)
            print(f'{ansi_escapes.blue}Raw network (no optimizations) saved to {save_raw_network_filename}{ansi_escapes.reset}')
        sim_params = SimParams(**load_json(simulation_filename)) if simulation_filename is not None else None
        if not sim_params:
            if next((node for node in network if isinstance(node, RamanFiber)), None) is not None:
                print(f'{ansi_escapes.red}Invocation error:{ansi_escapes.reset} '
                      f'RamanFiber requires passing simulation params via --sim-params')
                sys.exit(1)
        else:
            Simulation.set_params(sim_params)
    except exceptions.EquipmentConfigError as e:
        print(f'{ansi_escapes.red}Configuration error in the equipment library:{ansi_escapes.reset} {e}')
        sys.exit(1)
    except exceptions.NetworkTopologyError as e:
        print(f'{ansi_escapes.red}Invalid network definition:{ansi_escapes.reset} {e}')
        sys.exit(1)
    except exceptions.ConfigurationError as e:
        print(f'{ansi_escapes.red}Configuration error:{ansi_escapes.reset} {e}')
        sys.exit(1)
    except exceptions.ParametersError as e:
        print(f'{ansi_escapes.red}Simulation parameters error:{ansi_escapes.reset} {e}')
        sys.exit(1)
    except exceptions.ServiceError as e:
        print(f'{ansi_escapes.red}Service error:{ansi_escapes.reset} {e}')
        sys.exit(1)

    return (equipment, network)
Ejemplo n.º 5
0
def setup_edfa_fixed_gain():
    """init edfa class by reading the 2nd edfa in test_network.json file"""
    equipment = load_equipment(eqpt_library)
    network = load_network(test_network, equipment)
    build_network(network, equipment, 0, 20)
    edfa = [n for n in network.nodes() if isinstance(n, Edfa)][1]
    yield edfa
Ejemplo n.º 6
0
def test_span_loss_unconnected(node):
    '''Fused node that has no next and no previous nodes should be detected'''
    equipment = load_equipment(EQPT_FILENAME)
    network = load_network(NETWORK_FILENAME, equipment)
    x = next(x for x in network.nodes() if x.uid == node)
    with pytest.raises(NetworkTopologyError):
        span_loss(network, x)
Ejemplo n.º 7
0
def test_span_loss(node, attenuation):
    equipment = load_equipment(EQPT_FILENAME)
    network = load_network(NETWORK_FILENAME, equipment)
    for x in network.nodes():
        if x.uid == node:
            assert attenuation == span_loss(network, x)
            return
    assert not f'node "{node}" referenced from test but not found in the topology'  # pragma: no cover
def setup(equipment):
    """ common setup for tests: builds network, equipment and oms only once
    """
    network = load_network(NETWORK_FILENAME, equipment)
    spectrum = equipment['SI']['default']
    p_db = spectrum.power_dbm
    p_total_db = p_db + lin2db(automatic_nch(spectrum.f_min, spectrum.f_max, spectrum.spacing))
    build_network(network, equipment, p_db, p_total_db)
    oms_list = build_oms_list(network, equipment)
    return network, oms_list
Ejemplo n.º 9
0
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)
    network = load_network(test_network, equipment)
    build_network(network, equipment, 0, 20)
    edfa = [n for n in network.nodes() if isinstance(n, Edfa)][0]
    edfa.gain_ripple = zeros(96)
    edfa.interpol_nf_ripple = zeros(96)
    yield edfa
Ejemplo n.º 10
0
def test_setup():
    """ common setup for tests: builds network, equipment and oms only once
    """
    equipment = load_equipment(EQPT_LIBRARY_NAME)
    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
    # spacing, f_min and f_max
    p_db = equipment['SI']['default'].power_dbm

    p_total_db = p_db + lin2db(automatic_nch(equipment['SI']['default'].f_min,
                                             equipment['SI']['default'].f_max, equipment['SI']['default'].spacing))
    build_network(network, equipment, p_db, p_total_db)
    build_oms_list(network, equipment)

    return network, equipment
Ejemplo n.º 11
0
def test_ase_noise(gain, si, setup_trx, bw):
    """testing 3 different ways of calculating osnr:
    1-pin-edfa.nf+58 vs
    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)
    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')
    # update span1 and Edfa1 according to new gain before building network
    # updating span 1  avoids to overload amp
    span.params.length = gain * 1e3 / 0.2
    edfa.operational.gain_target = gain
    build_network(network, equipment, 0, 20)
    edfa.gain_ripple = zeros(96)
    edfa.interpol_nf_ripple = zeros(96)
    # propagate in span1 to have si with the correct power level
    si = span(si)
    print(span)

    frequencies = array([c.frequency for c in si.carriers])
    pin = array(
        [c.power.signal + c.power.nli + c.power.ase for c in si.carriers])
    baud_rates = array([c.baud_rate for c in si.carriers])
    pref = Pref(0, -gain, lin2db(len(frequencies)))
    edfa.interpol_params(frequencies, pin, baud_rates, pref)
    nf = edfa.nf
    print('nf', nf)
    pin = lin2db(pin[0] * 1e3)
    osnr_expected = pin - nf[0] + 58

    si = edfa(si)
    print(edfa)
    pout = array([c.power.signal for c in si.carriers])
    pase = array([c.power.ase for c in si.carriers])
    osnr = lin2db(pout[0] / pase[0]) - lin2db(12.5e9 / bw)
    assert pytest.approx(osnr_expected, abs=0.01) == osnr

    trx = setup_trx
    si = trx(si)
    osnr = trx.osnr_ase_01nm[0]
    assert pytest.approx(osnr_expected, abs=0.01) == osnr
Ejemplo n.º 12
0
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)
    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)
    equipment['Span']['default'].power_mode = power_mode
    # Build the network once using the default power defined in SI in eqpt config

    p_db = equipment['SI']['default'].power_dbm
    p_total_db = p_db + lin2db(
        automatic_nch(equipment['SI']['default'].f_min,
                      equipment['SI']['default'].f_max,
                      equipment['SI']['default'].spacing))
    build_network(network, equipment, p_db, p_total_db)
    actual_json_output = tmpdir / json_input.with_name(
        json_input.stem + '_auto_design').with_suffix('.json').name
    save_network(network, actual_json_output)
    actual = load_json(actual_json_output)
    unlink(actual_json_output)
    assert actual == load_json(json_input)
Ejemplo n.º 13
0
def propagation(input_power, con_in, con_out, dest):
    equipment = load_equipment(eqpt_library_name)
    network = load_network(network_file_name, equipment)
    build_network(network, equipment, 0, 20)

    # parametrize the network elements with the con losses and adapt gain
    # (assumes all spans are identical)
    for e in network.nodes():
        if isinstance(e, Fiber):
            loss = e.params.loss_coef * e.params.length
            e.params.con_in = con_in
            e.params.con_out = con_out
        if isinstance(e, Edfa):
            e.operational.gain_target = loss + con_in + con_out

    transceivers = {
        n.uid: n
        for n in network.nodes() if isinstance(n, Transceiver)
    }

    p = input_power
    p = db2lin(p) * 1e-3
    spacing = 50e9  # THz
    si = create_input_spectral_information(191.3e12, 191.3e12 + 79 * spacing,
                                           0.15, 32e9, p, spacing)
    source = next(transceivers[uid] for uid in transceivers if uid == 'trx A')
    sink = next(transceivers[uid] for uid in transceivers if uid == dest)
    path = dijkstra_path(network, source, sink)
    for el in path:
        si = el(si)
        print(el)  # remove this line when sweeping across several powers
    edfa_sample = next(el for el in path if isinstance(el, Edfa))
    nf = mean(edfa_sample.nf)

    print(f'pw: {input_power} conn in: {con_in} con out: {con_out}',
          f'[email protected]: {round(mean(sink.osnr_ase_01nm),2)}',
          f'SNR@bandwitdth: {round(mean(sink.snr),2)}')
    return sink, nf, path
Ejemplo n.º 14
0
def test_excel_ila_constraints(source, destination, route_list, hoptype,
                               expected_correction):
    """ add different kind of constraints to test all correct_route cases
    """
    service_xls_input = DATA_DIR / 'testTopology.xls'
    network_json_input = DATA_DIR / 'testTopology_auto_design_expected.json'
    equipment = load_equipment(eqpt_filename)
    network = load_network(network_json_input, equipment)
    # increase length of one span to trigger automatic fiber splitting included by autodesign
    # so that the test also covers this case
    next(node for node in network.nodes()
         if node.uid == 'fiber (Brest_KLA → Quimper)-').length = 200000
    next(node for node in network.nodes()
         if node.uid == 'fiber (Quimper → Brest_KLA)-').length = 200000
    default_si = equipment['SI']['default']
    p_db = default_si.power_dbm
    p_total_db = p_db + lin2db(
        automatic_nch(default_si.f_min, default_si.f_max, default_si.spacing))
    build_network(network, equipment, p_db, p_total_db)
    # create params for a request based on input
    nodes_list = route_list.split(' | ') if route_list is not None else []
    params = {
        'request_id':
        '0',
        'source':
        source,
        'bidir':
        False,
        'destination':
        destination,
        'trx_type':
        '',
        'trx_mode':
        '',
        'format':
        '',
        'spacing':
        '',
        'nodes_list':
        nodes_list,
        'loose_list':
        [hoptype for node in nodes_list] if route_list is not None else '',
        'f_min':
        0,
        'f_max':
        0,
        'baud_rate':
        0,
        'OSNR':
        None,
        'bit_rate':
        None,
        'cost':
        None,
        'roll_off':
        0,
        'tx_osnr':
        0,
        'min_spacing':
        None,
        'nb_channel':
        0,
        'power':
        0,
        'path_bandwidth':
        0,
    }
    request = PathRequest(**params)

    if expected_correction != 'Fail':
        [request] = correct_xls_route_list(service_xls_input, network,
                                           [request])
        assert request.nodes_list == expected_correction
    else:
        with pytest.raises(ServiceError):
            [request] = correct_xls_route_list(service_xls_input, network,
                                               [request])
Ejemplo n.º 15
0
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)
    network = load_network(xls_input, equipment)
    p_db = equipment['SI']['default'].power_dbm

    p_total_db = p_db + lin2db(
        automatic_nch(equipment['SI']['default'].f_min,
                      equipment['SI']['default'].f_max,
                      equipment['SI']['default'].spacing))
    build_network(network, equipment, p_db, p_total_db)

    data = read_service_sheet(xls_input, equipment, network)
    # change one of the request with bidir option to cover bidir case as well
    data['path-request'][2]['bidirectional'] = True

    oms_list = build_oms_list(network, equipment)
    rqs = requests_from_json(data, equipment)
    dsjn = disjunctions_from_json(data)
    dsjn = deduplicate_disjunctions(dsjn)
    rqs, dsjn = requests_aggregation(rqs, dsjn)
    pths = compute_path_dsjctn(network, equipment, rqs, dsjn)
    propagatedpths, reversed_pths, reversed_propagatedpths = \
        compute_path_with_disjunction(network, equipment, rqs, pths)
    pth_assign_spectrum(pths, rqs, oms_list, reversed_pths)

    result = []
    for i, pth in enumerate(propagatedpths):
        # test ServiceError handling : when M is zero at this point, the
        # json result should not be created if there is no blocking reason
        if i == 1:
            my_rq = deepcopy(rqs[i])
            my_rq.M = 0
            with pytest.raises(ServiceError):
                ResultElement(my_rq, pth, reversed_propagatedpths[i]).json

            my_rq.blocking_reason = 'NO_SPECTRUM'
            ResultElement(my_rq, pth, reversed_propagatedpths[i]).json

        result.append(ResultElement(rqs[i], pth, reversed_propagatedpths[i]))

    temp = {'response': [n.json for n in result]}

    expected = load_json(expected_response_file)

    for i, response in enumerate(temp['response']):
        if i == 2:
            # compare response must be False because z-a metric is missing
            # (request with bidir option to cover bidir case)
            assert not compare_response(expected['response'][i], response)
            print(f'response {response["response-id"]} should not match')
            expected['response'][2]['path-properties']['z-a-path-metric'] = [{
                'metric-type':
                'SNR-bandwidth',
                'accumulative-value':
                22.809999999999999
            }, {
                'metric-type':
                'SNR-0.1nm',
                'accumulative-value':
                26.890000000000001
            }, {
                'metric-type':
                'OSNR-bandwidth',
                'accumulative-value':
                26.239999999999998
            }, {
                'metric-type':
                'OSNR-0.1nm',
                'accumulative-value':
                30.32
            }, {
                'metric-type':
                'reference_power',
                'accumulative-value':
                0.0012589254117941673
            }, {
                'metric-type':
                'path_bandwidth',
                'accumulative-value':
                60000000000.0
            }]
            # test should be OK now
        else:
            assert compare_response(expected['response'][i], response)
            print(f'response {response["response-id"]} is not correct')
def test_automaticmodefeature(net, eqpt, serv, expected_mode):
    equipment = load_equipment(eqpt)
    network = load_network(net, equipment)
    data = load_requests(serv,
                         eqpt,
                         bidir=False,
                         network=network,
                         network_filename=net)

    # 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
    # spacing, f_min and f_max
    p_db = equipment['SI']['default'].power_dbm

    p_total_db = p_db + lin2db(
        automatic_nch(equipment['SI']['default'].f_min,
                      equipment['SI']['default'].f_max,
                      equipment['SI']['default'].spacing))
    build_network(network, equipment, p_db, p_total_db)

    rqs = requests_from_json(data, equipment)
    rqs = correct_json_route_list(network, rqs)
    dsjn = []
    pths = compute_path_dsjctn(network, equipment, rqs, dsjn)
    path_res_list = []

    for i, pathreq in enumerate(rqs):

        # use the power specified in requests but might be different from the one specified for design
        # the power is an optional parameter for requests definition
        # if optional, use the one defines in eqt_config.json
        p_db = lin2db(pathreq.power * 1e3)
        p_total_db = p_db + lin2db(pathreq.nb_channel)
        print(f'request {pathreq.request_id}')
        print(f'Computing path from {pathreq.source} to {pathreq.destination}')
        # adding first node to be clearer on the output
        print(f'with path constraint: {[pathreq.source]+pathreq.nodes_list}')

        total_path = pths[i]
        print(
            f'Computed path (roadms):{[e.uid for e in total_path  if isinstance(e, Roadm)]}\n'
        )
        # for debug
        # print(f'{pathreq.baud_rate}   {pathreq.power}   {pathreq.spacing}   {pathreq.nb_channel}')
        if pathreq.baud_rate is not None:
            print(pathreq.format)
            path_res_list.append(pathreq.format)
            total_path = propagate(total_path, pathreq, equipment)
        else:
            total_path, mode = propagate_and_optimize_mode(
                total_path, pathreq, equipment)
            # if no baudrate satisfies spacing, no mode is returned and an empty path is returned
            # a warning is shown in the propagate_and_optimize_mode
            if mode is not None:
                print(mode['format'])
                path_res_list.append(mode['format'])
            else:
                print('nok')
                path_res_list.append('nok')
    print(path_res_list)
    assert path_res_list == expected_mode