Example #1
0
def load_files(gnpy_topology):
    """ Load GNPy equipment Library and create network from topology"""
    eqpt_library = load_equipment(
        '../examples/default_equipment_data/eqpt_config.json')
    gnpy_network = network_from_json(topology_to_json(gnpy_topology),
                                     eqpt_library)

    return eqpt_library, gnpy_network
Example #2
0
def test_target_pch_out_db_global(case):
    """ check that per degree attributes are correctly created with global values if none are given
    """
    json_network = setup_per_degree(case)
    per_degree = {}
    for elem in json_network['elements']:
        if 'type' in elem.keys() and elem['type'] == 'Roadm' and 'params' in elem.keys() \
            and 'per_degree_pch_out_db' in elem['params']:
            # records roadms that have a per degree target
            per_degree[elem['uid']] = {
                k: v
                for k, v in elem['params']['per_degree_pch_out_db'].items()
            }
    network = network_from_json(json_network, 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)

    data = network_to_json(network)
    for elem in data['elements']:
        if 'type' in elem.keys() and elem['type'] == 'Roadm':
            # check that power target attributes exist and are filled with correct values
            # first check that global 'target_pch_out_db' is correctly filled
            assert elem['params']['target_pch_out_db'] == equipment['Roadm'][
                'default'].target_pch_out_db
            for degree, power in elem['params']['per_degree_pch_out_db'].items(
            ):
                if elem['uid'] not in per_degree.keys():
                    # second: check that per degree 'target_pch_out_db' is correctly filled with global value
                    # when there was no per degree specification on network input
                    assert power == equipment['Roadm'][
                        'default'].target_pch_out_db
                else:
                    if degree not in per_degree[elem['uid']].keys():
                        # third: check that per degree 'target_pch_out_db' is correctly filled with global value
                        # on degrees that had no specification when other degrees are filled
                        assert power == equipment['Roadm'][
                            'default'].target_pch_out_db
                    else:
                        # fourth: check that per degree 'target_pch_out_db' is correctly filled with specified values
                        assert power == per_degree[elem['uid']][degree]
def test_no_amp_feature(node_uid):
    ''' Check that booster is not placed on a roadm if fused is specified
        test_parser covers partly this behaviour. This test should guaranty that the
        feature is preserved even if convert is changed
    '''
    equipment = load_equipment(EQPT_LIBRARY_NAME)
    json_network = load_json(NETWORK_FILE_NAME)

    for elem in json_network['elements']:
        if elem['uid'] == node_uid:
            # replace edfa node by a fused node in the topology
            elem['type'] = 'Fused'
            elem.pop('type_variety')
            elem.pop('operational')
            elem['params'] = {'loss': 0}

            next_node_uid = next(conn['to_node']
                                 for conn in json_network['connections']
                                 if conn['from_node'] == node_uid)
            previous_node_uid = next(conn['from_node']
                                     for conn in json_network['connections']
                                     if conn['to_node'] == node_uid)

    network = network_from_json(json_network, 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)

    node = next(nd for nd in network.nodes() if nd.uid == node_uid)
    next_node = next(network.successors(node))
    previous_node = next(network.predecessors(node))

    if not isinstance(node, Fused):
        raise AssertionError()
    if not node.params.loss == 0.0:
        raise AssertionError()
    if not next_node_uid == next_node.uid:
        raise AssertionError()
    if not previous_node_uid == previous_node.uid:
        raise AssertionError()
def test_roadm_target_power(prev_node_type, effective_pch_out_db, power_dbm):
    ''' Check that egress power of roadm is equal to target power if input power is greater
    than target power else, that it is equal to input power. Use a simple two hops A-B-C topology
    for the test where the prev_node in ROADM B is either an amplifier or a fused, so that the target
    power can not be met in this last case.
    '''
    equipment = load_equipment(EQPT_LIBRARY_NAME)
    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')
    json_network['elements'].remove(prev_node)
    if prev_node_type == 'edfa':
        prev_node = {'uid': 'west edfa in node B to ila2', 'type': 'Edfa'}
    elif prev_node_type == 'fused':
        prev_node = {'uid': 'west edfa in node B to ila2', 'type': 'Fused'}
        prev_node['params'] = {'loss': 0}
    json_network['elements'].append(prev_node)
    network = network_from_json(json_network, equipment)
    p_total_db = power_dbm + lin2db(
        automatic_nch(equipment['SI']['default'].f_min,
                      equipment['SI']['default'].f_max,
                      equipment['SI']['default'].spacing))

    build_network(network, equipment, power_dbm, p_total_db)

    params = {
        'request_id': 0,
        'trx_type': '',
        'trx_mode': '',
        'source': 'trx node A',
        'destination': 'trx node C',
        'bidir': False,
        'nodes_list': ['trx node C'],
        'loose_list': ['strict'],
        'format': '',
        'path_bandwidth': 100e9,
        'effective_freq_slot': None,
    }
    trx_params = trx_mode_params(equipment)
    params.update(trx_params)
    req = PathRequest(**params)
    req.power = db2lin(power_dbm - 30)
    path = compute_constrained_path(network, req)
    si = create_input_spectral_information(req.f_min, req.f_max, req.roll_off,
                                           req.baud_rate, req.power,
                                           req.spacing)
    for i, el in enumerate(path):
        if isinstance(el, Roadm):
            carriers_power_in_roadm = min([
                c.power.signal + c.power.nli + c.power.ase for c in si.carriers
            ])
            si = el(si, degree=path[i + 1].uid)
            if el.uid == 'roadm node B':
                print('input', carriers_power_in_roadm)
                # if previous was an EDFA, power level at ROADM input is enough for the ROADM to apply its
                # target power (as specified in equipment ie -20 dBm)
                # if it is a Fused, the input power to the ROADM is smaller than the target power, and the
                # ROADM cannot apply this target. In this case, it is assumed that the ROADM has 0 dB loss
                # so the output power will be the same as the input power, which for this particular case
                # corresponds to -22dBm + power_dbm
                # next step (for ROADM modelling) will be to apply a minimum loss for ROADMs !
                if prev_node_type == 'edfa':
                    assert el.effective_pch_out_db == effective_pch_out_db
                if prev_node_type == 'fused':
                    # then output power == input_power == effective_pch_out_db + power_dbm
                    assert effective_pch_out_db + power_dbm == \
                        pytest.approx(lin2db(carriers_power_in_roadm * 1e3), rel=1e-3)
                    assert el.effective_pch_out_db == effective_pch_out_db + power_dbm
                for carrier in si.carriers:
                    print(carrier.power.signal + carrier.power.nli +
                          carrier.power.ase)
                    power = carrier.power.signal + carrier.power.nli + carrier.power.ase
                    if prev_node_type == 'edfa':
                        # edfa prev_node sets input power to roadm to a high enough value:
                        # Check that egress power of roadm is equal to target power
                        assert power == pytest.approx(
                            db2lin(effective_pch_out_db - 30), rel=1e-3)
                    elif prev_node_type == 'fused':
                        # fused prev_node does reamplfy power after fiber propagation, so input power
                        # to roadm is low.
                        # Check that egress power of roadm is equalized to the min carrier input power.
                        assert power == pytest.approx(carriers_power_in_roadm,
                                                      rel=1e-3)
        else:
            si = el(si)
def test_restrictions(restrictions, equipment):
    ''' test that restriction is correctly applied if provided in eqpt_config and if no Edfa type
    were provided in the network json
    '''
    # add restrictions
    equipment['Roadm']['default'].restrictions = restrictions
    # build network
    json_network = load_json(NETWORK_FILE_NAME)
    network = network_from_json(json_network, equipment)

    amp_nodes_nobuild_uid = [
        nd.uid for nd in network.nodes() if isinstance(nd, Edfa)
        and isinstance(next(network.predecessors(nd)), Roadm)
    ]
    preamp_nodes_nobuild_uid = [
        nd.uid for nd in network.nodes() if isinstance(nd, Edfa)
        and isinstance(next(network.successors(nd)), Roadm)
    ]
    amp_nodes_nobuild = {
        nd.uid: nd
        for nd in network.nodes() if isinstance(nd, Edfa)
        and isinstance(next(network.predecessors(nd)), Roadm)
    }
    preamp_nodes_nobuild = {
        nd.uid: nd
        for nd in network.nodes() if isinstance(nd, Edfa)
        and isinstance(next(network.successors(nd)), Roadm)
    }
    # roadm dict with restrictions before build
    roadms = {nd.uid: nd for nd in network.nodes() if isinstance(nd, Roadm)}
    # 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)

    amp_nodes = [
        nd for nd in network.nodes() if isinstance(nd, Edfa)
        and isinstance(next(network.predecessors(nd)), Roadm)
        and next(network.predecessors(nd)).restrictions['booster_variety_list']
    ]

    preamp_nodes = [
        nd for nd in network.nodes() if isinstance(nd, Edfa)
        and isinstance(next(network.successors(nd)), Roadm)
        and next(network.successors(nd)).restrictions['preamp_variety_list']
    ]

    # check that previously existing amp are not changed
    for amp in amp_nodes:
        if amp.uid in amp_nodes_nobuild_uid:
            print(amp.uid, amp.params.type_variety)
            if not amp.params.type_variety == amp_nodes_nobuild[
                    amp.uid].params.type_variety:
                raise AssertionError()
    for amp in preamp_nodes:
        if amp.uid in preamp_nodes_nobuild_uid:
            if not amp.params.type_variety == preamp_nodes_nobuild[
                    amp.uid].params.type_variety:
                raise AssertionError()
    # check that restrictions are correctly applied
    for amp in amp_nodes:
        if amp.uid not in amp_nodes_nobuild_uid:
            # and if roadm had no restrictions before build:
            if restrictions['booster_variety_list'] and \
               not roadms[next(network.predecessors(amp)).uid]\
               .restrictions['booster_variety_list']:
                if amp.params.type_variety not in restrictions[
                        'booster_variety_list']:

                    raise AssertionError()
    for amp in preamp_nodes:
        if amp.uid not in preamp_nodes_nobuild_uid:
            if restrictions['preamp_variety_list'] and\
                    not roadms[next(network.successors(amp)).uid].restrictions['preamp_variety_list']:
                if amp.params.type_variety not in restrictions[
                        'preamp_variety_list']:
                    raise AssertionError()
def test_roadm_target_power(prev_node_type, effective_pch_out_db):
    ''' Check that egress power of roadm is equal to target power if input power is greater
    than target power else, that it is equal to input power. Use a simple two hops A-B-C topology
    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)
    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')
    json_network['elements'].remove(prev_node)
    if prev_node_type == 'edfa':
        prev_node = {'uid': 'west edfa in node B to ila2', 'type': 'Edfa'}
    elif prev_node_type == 'fused':
        prev_node = {'uid': 'west edfa in node B to ila2', 'type': 'Fused'}
        prev_node['params'] = {'loss': 0}
    json_network['elements'].append(prev_node)
    network = network_from_json(json_network, 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)

    params = {}
    params['request_id'] = 0
    params['trx_type'] = ''
    params['trx_mode'] = ''
    params['source'] = 'trx node A'
    params['destination'] = 'trx node C'
    params['bidir'] = False
    params['nodes_list'] = ['trx node C']
    params['loose_list'] = ['strict']
    params['format'] = ''
    params['path_bandwidth'] = 100e9
    trx_params = trx_mode_params(equipment)
    params.update(trx_params)
    req = PathRequest(**params)
    path = compute_constrained_path(network, req)
    si = create_input_spectral_information(req.f_min, req.f_max, req.roll_off,
                                           req.baud_rate, req.power,
                                           req.spacing)
    for i, el in enumerate(path):
        if isinstance(el, Roadm):
            carriers_power_in_roadm = min([
                c.power.signal + c.power.nli + c.power.ase for c in si.carriers
            ])
            si = el(si, degree=path[i + 1].uid)
            if el.uid == 'roadm node B':
                print('input', carriers_power_in_roadm)
                assert el.effective_pch_out_db == effective_pch_out_db
                for carrier in si.carriers:
                    print(carrier.power.signal + carrier.power.nli +
                          carrier.power.ase)
                    power = carrier.power.signal + carrier.power.nli + carrier.power.ase
                    if prev_node_type == 'edfa':
                        # edfa prev_node sets input power to roadm to a high enough value:
                        # Check that egress power of roadm is equal to target power
                        assert power == pytest.approx(
                            db2lin(effective_pch_out_db - 30), rel=1e-3)
                    elif prev_node_type == 'fused':
                        # fused prev_node does reamplfy power after fiber propagation, so input power
                        # to roadm is low.
                        # Check that egress power of roadm is equalized to the min carrier input power.
                        assert power == pytest.approx(carriers_power_in_roadm,
                                                      rel=1e-3)
        else:
            si = el(si)