示例#1
0
def transmission_main_example(args=None):
    parser = argparse.ArgumentParser(
        description=
        'Send a full spectrum load through the network from point A to point B',
        epilog=_help_footer,
        formatter_class=argparse.ArgumentDefaultsHelpFormatter,
    )
    _add_common_options(parser,
                        network_default=_examples_dir /
                        'edfa_example_network.json')
    parser.add_argument('--show-channels',
                        action='store_true',
                        help='Show final per-channel OSNR summary')
    parser.add_argument('-pl', '--plot', action='store_true')
    parser.add_argument('-l',
                        '--list-nodes',
                        action='store_true',
                        help='list all transceiver nodes')
    parser.add_argument('-po',
                        '--power',
                        default=0,
                        help='channel ref power in dBm')
    parser.add_argument('source', nargs='?', help='source node')
    parser.add_argument('destination', nargs='?', help='destination node')

    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)

    if args.plot:
        plot_baseline(network)

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

    if not transceivers:
        sys.exit('Network has no transceivers!')
    if len(transceivers) < 2:
        sys.exit('Network has only one transceiver!')

    if args.list_nodes:
        for uid in transceivers:
            print(uid)
        sys.exit()

    # First try to find exact match if source/destination provided
    if args.source:
        source = transceivers.pop(args.source, None)
        valid_source = True if source else False
    else:
        source = None
        _logger.info('No source node specified: picking random transceiver')

    if args.destination:
        destination = transceivers.pop(args.destination, None)
        valid_destination = True if destination else False
    else:
        destination = None
        _logger.info(
            'No destination node specified: picking random transceiver')

    # If no exact match try to find partial match
    if args.source and not source:
        # TODO code a more advanced regex to find nodes match
        source = next(
            (transceivers.pop(uid)
             for uid in transceivers if args.source.lower() in uid.lower()),
            None)

    if args.destination and not destination:
        # TODO code a more advanced regex to find nodes match
        destination = next((transceivers.pop(uid) for uid in transceivers
                            if args.destination.lower() in uid.lower()), None)

    # If no partial match or no source/destination provided pick random
    if not source:
        source = list(transceivers.values())[0]
        del transceivers[source.uid]

    if not destination:
        destination = list(transceivers.values())[0]

    _logger.info(f'source = {args.source!r}')
    _logger.info(f'destination = {args.destination!r}')

    params = {}
    params['request_id'] = 0
    params['trx_type'] = ''
    params['trx_mode'] = ''
    params['source'] = source.uid
    params['destination'] = destination.uid
    params['bidir'] = False
    params['nodes_list'] = [destination.uid]
    params['loose_list'] = ['strict']
    params['format'] = ''
    params['path_bandwidth'] = 0
    trx_params = trx_mode_params(equipment)
    #     Randomly generate input power
    input_power = round(random.random(), 2)
    input_power = -2 + (input_power * (8))
    args.power = input_power
    if args.power:
        trx_params['power'] = db2lin(float(args.power)) * 1e-3
    params.update(trx_params)
    req = PathRequest(**params)

    power_mode = equipment['Span']['default'].power_mode
    print('\n'.join([
        f'Power mode is set to {power_mode}',
        f'=> it can be modified in eqpt_config.json - Span'
    ]))

    pref_ch_db = lin2db(req.power *
                        1e3)  # reference channel power / span (SL=20dB)
    pref_total_db = pref_ch_db + lin2db(
        req.nb_channel)  # reference total power / span (SL=20dB)
    try:
        build_network(network, equipment, pref_ch_db, pref_total_db)
    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)
    path = compute_constrained_path(network, req)

    spans = [
        s.params.length for s in path
        if isinstance(s, RamanFiber) or isinstance(s, Fiber)
    ]
    print(
        f'\nThere are {len(spans)} fiber spans over {sum(spans)/1000:.0f} km between {source.uid} '
        f'and {destination.uid}')
    print(f'\nNow propagating between {source.uid} and {destination.uid}:')

    try:
        p_start, p_stop, p_step = equipment['SI']['default'].power_range_db
        p_num = abs(int(round(
            (p_stop - p_start) / p_step))) + 1 if p_step != 0 else 1
        power_range = list(linspace(p_start, p_stop, p_num))
    except TypeError:
        print(
            'invalid power range definition in eqpt_config, should be power_range_db: [lower, upper, step]'
        )
        power_range = [0]

    if not power_mode:
        # power cannot be changed in gain mode
        power_range = [0]
    for dp_db in power_range:
        req.power = db2lin(pref_ch_db + dp_db) * 1e-3
        if power_mode:
            print(
                f'\nPropagating with input power = {ansi_escapes.cyan}{lin2db(req.power*1e3):.2f} dBm{ansi_escapes.reset}:'
            )
        else:
            print(
                f'\nPropagating in {ansi_escapes.cyan}gain mode{ansi_escapes.reset}: power cannot be set manually'
            )
        infos = propagate(path, req, equipment)
        if len(power_range) == 1:
            for elem in path:
                print(elem)
            if power_mode:
                print(
                    f'\nTransmission result for input power = {lin2db(req.power*1e3):.2f} dBm:'
                )
            else:
                print(f'\nTransmission results:')
#             print('-------------')
#             print(destination.snr_01nm)
#             print('-------------')
            print(
                f'  Final SNR total (0.1 nm): {ansi_escapes.cyan}{mean(destination.snr_01nm):.02f} dB{ansi_escapes.reset}'
            )
        else:
            print(path[-1])

    if args.save_network is not None:
        save_network(network, args.save_network)
        print(
            f'{ansi_escapes.blue}Network (after autodesign) saved to {args.save_network}{ansi_escapes.reset}'
        )

    if args.show_channels:
        print('\nThe total SNR per channel at the end of the line is:')
        print('{:>5}{:>26}{:>26}{:>28}{:>28}{:>28}'.format(
            'Ch. #', 'Channel frequency (THz)', 'Channel power (dBm)',
            'OSNR ASE (signal bw, dB)', 'SNR NLI (signal bw, dB)',
            'SNR total (signal bw, dB)'))
        #         print(dir(info))
        for final_carrier, ch_osnr, ch_snr_nl, ch_snr in zip(
                infos.carriers, path[-1].osnr_ase, path[-1].osnr_nli,
                path[-1].snr):
            ch_freq = final_carrier.frequency * 1e-12
            ch_power = lin2db(final_carrier.power.signal * 1e3)
            print('{:5}{:26.2f}{:26.2f}{:28.2f}{:28.2f}{:28.2f}'.format(
                final_carrier.channel_number, round(ch_freq, 2),
                round(ch_power, 2), round(ch_osnr, 2), round(ch_snr_nl, 2),
                round(ch_snr, 2)))

    if not args.source:
        print(f'\n(No source node specified: picked {source.uid})')
    elif not valid_source:
        print(
            f'\n(Invalid source node {args.source!r} replaced with {source.uid})'
        )

    if not args.destination:
        print(f'\n(No destination node specified: picked {destination.uid})')
    elif not valid_destination:
        print(
            f'\n(Invalid destination node {args.destination!r} replaced with {destination.uid})'
        )

    if args.plot:
        plot_results(network, path, source, destination)

#     MY ADDITION
# just to see what the different contributions of ASE and NLI are
#     return input_power, path[-1].osnr_ase, path[-1].osnr_nli, path[-1].snr
# to test Raman
    return input_power, destination.snr_01nm, mean(destination.snr_01nm)
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