Example #1
0
def make_graph(r_path, nodes):
    """
    Call shortest_path, which reads links_distance.txt and creates networkx
    graph object.
    Adds degrees for nodes with 0 connections, returns graph object.
    """
    gg = shortest_path(r_path)

    # add degrees for nodes with 0 connections
    for i in range(nodes):
        if str(i) not in list(gg.nodes()):
            gg.add_node(str(i), weight=0)
    return gg
Example #2
0
def make_graph(results_path, nodes):
    """
    Call shortest_path, which reads links_distance.txt and creates networkx
    graph object.
    Adds degrees for nodes with 0 connections, returns graph object.
    """
    G = shortest_path(results_path)

    # get nodes and degrees in dictionary
    node_and_degree = {}
    for node, val in G.degree():
        node_and_degree[node] = val
    # add degrees for nodes with 0 connections
    for i in range(nodes):
        if str(i) not in node_and_degree:
            node_and_degree[str(i)] = 0
            G.add_node(str(i), weight=0)
    return G
Example #3
0
def plot_3d(data_name, center_node, n_hop, colormap):
    current_file_path = Path(__file__)
    results_path = str(current_file_path.parents[1]) + f'/results/{data_name}/'

    # open xyz text file and extract values
    xyz = open(results_path + 'xyz.txt', 'r')
    pos = {}
    for i, line in enumerate(xyz):
        a = line.split()
        pos[str(i)] = (float(a[0]), float(a[1]), float(a[2]))
    xyz.close()

    n_nodes = len(pos)
    # Create graph object based on links and distances txt files
    G = shortest_path(results_path)

    # get node degrees in sorted list
    node_and_degree = {}
    for node, val in G.degree():
        node_and_degree[node] = val
    # add degrees for nodes with 0 connections
    for i in range(n_nodes):
        if str(i) not in node_and_degree:
            node_and_degree[str(i)] = 0
            G.add_node(str(i), weight=0)

    x_center = pos[str(center_node)][0]
    y_center = pos[str(center_node)][1]
    z_center = pos[str(center_node)][2]

    frontier_list = []
    local_n_list = []
    local_n_list_reduced = []
    ext_n_list = []

    # Each frontier is a dictionary of local neighborhood
    for i in range(n_hop + 1):       # includes 0-hop neighborhood
        frontier_list.append(nx.single_source_shortest_path(G, str(center_node), cutoff=i))
        # get frontier keys, which are local neighborhood nodes
        local_n_list.append([str(x) for x in list(frontier_list[i].keys())])
    local_n_size = len(local_n_list[-1])

    # get list of external nodes
    for i in range(n_nodes):
        if str(i) not in local_n_list[-1]:
            ext_n_list.append(str(i))

    # Create 'reduced' list, manually add 0, 1 hop neighbor nodes
    for i in range(0, 2):
        local_n_list_reduced.append(local_n_list[i])
    # Remove lower level (-2 levels) hop nodes so each frontier only includes 'growth'
    for i in range(2, n_hop + 1):
        local_n_list_reduced.append([x for x in local_n_list[i] if
                                    x not in local_n_list[i - 2]])

    # Plotting
    # Iterate over local nbrhood list to extract the xyz coordinates of each neighborhood node
    xi = []
    yi = []
    zi = []
    for i in local_n_list[-1]:
        xi.append(pos[i][0])
        yi.append(pos[i][1])
        zi.append(pos[i][2])
    # mode='markers+text' for labels
    nbr_nodes = go.Scatter3d(x=xi, y=yi, z=zi, mode='markers',
                             marker=dict(color='red', size=1.7),
                             text=local_n_list[-1], hoverinfo='text')
    nbr_nodes['showlegend'] = False

    # center node
    center = go.Scatter3d(x=[x_center], y=[y_center], z=[z_center], mode='markers',
                             marker=dict(color='azure', size=4.5, line=dict(color='black', width=0.2)),
                             text=str(center_node), hoverinfo='text', name=f'Center node')
    center['showlegend'] = False

    # Plot nodes external to local neighborhood
    xo = []
    yo = []
    zo = []
    for i in ext_n_list:
        xo.append(pos[i][0])
        yo.append(pos[i][1])
        zo.append(pos[i][2])
    ext_nodes = go.Scatter3d(x=xo, y=yo, z=zo, mode='markers',
                             marker=dict(color='white', size=3,
                             line=dict(color='blue', width=0.2)),
                             text=ext_n_list, hoverinfo='text', name='External nodes')
    ext_nodes['showlegend'] = True

    # get link colors by hop path length
    link_colors = []
    cmap = cm.get_cmap(colormap, n_hop)
    for i in range(cmap.N):
        rgb = cmap(i)[:3]
        link_colors.append(colors.rgb2hex(rgb))
    link_colors.insert(0, '#000000')    # insert color for 0-hop neighborhood

    # Plot local neighborhood edges
    # Iterate over list of edges to get the xyz, coordinates of connected nodes
    grow_edges = []
    existing_links = []
    for i, frontier in enumerate(local_n_list_reduced):
        x_grow = []
        y_grow = []
        z_grow = []
        for j in G.edges(frontier):
            x = [pos[j[0]][0], pos[j[1]][0], None]
            y = [pos[j[0]][1], pos[j[1]][1], None]
            z = [pos[j[0]][2], pos[j[1]][2], None]
            if j[0] in frontier and j[1] in frontier and nx.shortest_path_length(G, str(center_node), j[0]) == i-1:
                x_grow += x
                y_grow += y
                z_grow += z
                existing_links.append([j[0], j[1]])
        grow_edges.append(go.Scatter3d(x=x_grow, y=y_grow, z=z_grow,
                                       mode='lines', line=dict(color=link_colors[i], width=1.5),
                                       name=f'{i}-hop', hoverinfo='none'))

    # Plot edges not in local neighborhood
    x_ext = []
    y_ext = []
    z_ext = []

    for j in G.edges([str(i) for i in range(n_nodes)]):
        x = [pos[j[0]][0], pos[j[1]][0], None]
        y = [pos[j[0]][1], pos[j[1]][1], None]
        z = [pos[j[0]][2], pos[j[1]][2], None]
        if [j[0], j[1]] not in existing_links and [j[1], j[0]] not in existing_links:
            x_ext += x
            y_ext += y
            z_ext += z
    ext_edges = go.Scatter3d(x=x_ext, y=y_ext, z=z_ext, mode='lines',
                             line=dict(color='rgb(0, 0, 0)', width=0.4),
                             hoverinfo='none', name='External links')

    # Plot earth
    u, v = np.mgrid[0:2*np.pi:30j, 0:np.pi:30j]
    X = 6371 * np.cos(u) * np.sin(v)
    Y = 6371 * np.sin(u) * np.sin(v)
    Z = 6371 * np.cos(v)

    cscale = [[0.0, "rgb(240, 240, 240)"],
              [0.111, "rgb(225, 225, 225)"],
              [0.222, "rgb(210, 210, 210)"],
              [0.333, "rgb(195, 195, 195)"],
              [0.444, "rgb(180, 180, 180)"],
              [0.555, "rgb(165, 165, 165)"],
              [0.666, "rgb(150, 150, 150)"],
              [0.777, "rgb(135, 135, 135)"],
              [0.888, "rgb(120, 120, 120)"],
              [1.0, "rgb(105, 105, 105)"]]

    contours = dict(x=dict(highlight=False), y=dict(highlight=False),
                    z=dict(highlight=False))
    sphere = go.Surface(x=X, y=Y, z=Z, colorscale=cscale, showscale=False,
                        hoverinfo='none', contours=contours, reversescale=True)
    
    # Plot layout
    noaxis = dict(showbackground=False, showgrid=False, showticklabels=False,
                  ticks='', title='', zeroline=False, showspikes=False)
    layout3d = dict(title=f'{data_name} network<br>'
                    f'Node {center_node}: {local_n_size} nodes in local neighborhood',
                    font=dict(family='Arial'),
                    scene=dict(xaxis=noaxis, yaxis=noaxis, zaxis=noaxis))

    data = [sphere, ext_nodes]#, ext_edges] #nbr_nodes, center,
    # data += grow_edges
    fig = dict(data=data, layout=layout3d)

    plotly.offline.plot(fig, filename=f'{results_path}/{data_name}_network.html')
Example #4
0
def network(true_xyz, true_anchors, abs_xyz, abs_anchors, anchors, rmse,
            ln_size, results_path, hop_lim):

    anchors_str = [str(x) for x in anchors]

    n_nodes = true_xyz.shape[0]
    node_list = [str(i) for i in range(n_nodes)]

    # Create graph object based on links and distances txt files
    g = shortest_path(results_path)

    # get node degrees in sorted list
    node_and_degree = {node: val for node, val in g.degree()}
    # add degrees for nodes with 0 connections
    for i in range(n_nodes):
        if str(i) not in node_and_degree:
            node_and_degree[str(i)] = 0
            g.add_node(str(i), weight=0)

    # Plotting
    # Iterate over local nbrhood list to extract the xyz coordinates of each
    # neighborhood node
    xa = []
    ya = []
    za = []
    for i in true_anchors:
        xa.append(i[0])
        ya.append(i[1])
        za.append(i[2])
    t_anchors = go.Scatter3d(x=xa,
                             y=ya,
                             z=za,
                             mode='markers',
                             marker=dict(color='dodgerblue',
                                         size=4,
                                         line=dict(color='black', width=0.2)),
                             hoverinfo='text',
                             name='True anchors',
                             text=anchors_str)
    t_anchors['showlegend'] = True

    xr = []
    yr = []
    zr = []
    for i in abs_anchors:
        xr.append(i[0])
        yr.append(i[1])
        zr.append(i[2])
    m_anchors = go.Scatter3d(x=xr,
                             y=yr,
                             z=zr,
                             mode='markers',
                             marker=dict(color='salmon',
                                         size=4,
                                         line=dict(color='black', width=0.2)),
                             hoverinfo='text',
                             name='Mapped anchors',
                             text=anchors_str)
    m_anchors['showlegend'] = True

    xo = []
    yo = []
    zo = []
    for i in true_xyz:
        xo.append(i[0])
        yo.append(i[1])
        zo.append(i[2])
    true_nodes = go.Scatter3d(x=xo,
                              y=yo,
                              z=zo,
                              mode='markers',
                              marker=dict(color='white',
                                          size=4,
                                          line=dict(color='darkblue',
                                                    width=0.2)),
                              text=node_list,
                              hoverinfo='text',
                              name='True nodes')
    true_nodes['showlegend'] = True

    # xo = []
    # yo = []
    # zo = []
    # for i in abs_xyz:
    #     xo.append(i[0])
    #     yo.append(i[1])
    #     zo.append(i[2])
    # m_nodes = go.Scatter3d(x=xo, y=yo, z=zo, mode='markers',
    #                          marker=dict(color='white', size=4,
    #                                      line=dict(color='red', width=0.2)),
    #                          text=node_list, hoverinfo='text',
    #                          name='Mapped nodes')
    # m_nodes['showlegend'] = True

    x_stem = []
    y_stem = []
    z_stem = []
    for j in range(n_nodes):
        x = [true_xyz[j][0], abs_xyz[j][0], None]
        y = [true_xyz[j][1], abs_xyz[j][1], None]
        z = [true_xyz[j][2], abs_xyz[j][2], None]

        x_stem += x
        y_stem += y
        z_stem += z

    stems = go.Scatter3d(x=x_stem,
                         y=y_stem,
                         z=z_stem,
                         mode='lines',
                         line=dict(color='red', width=0.75),
                         hoverinfo='none',
                         name='Error')

    # # Plot edges
    x_ext = []
    y_ext = []
    z_ext = []
    for j in g.edges([str(i) for i in range(n_nodes)]):
        x = [true_xyz[int(j[0])][0], true_xyz[int(j[1])][0], None]
        y = [true_xyz[int(j[0])][1], true_xyz[int(j[1])][1], None]
        z = [true_xyz[int(j[0])][2], true_xyz[int(j[1])][2], None]

        x_ext += x
        y_ext += y
        z_ext += z
    edges = go.Scatter3d(x=x_ext,
                         y=y_ext,
                         z=z_ext,
                         mode='lines',
                         line=dict(color='rgb(0, 0, 0)', width=0.4),
                         hoverinfo='none',
                         name='Links')

    # Plot earth
    u, v = np.mgrid[0:2 * np.pi:30j, 0:np.pi:30j]
    xx = 6371 * np.cos(u) * np.sin(v)
    yy = 6371 * np.sin(u) * np.sin(v)
    zz = 6371 * np.cos(v)

    cscale = [[0.0, "rgb(240, 240, 240)"], [0.111, "rgb(225, 225, 225)"],
              [0.222, "rgb(210, 210, 210)"], [0.333, "rgb(195, 195, 195)"],
              [0.444, "rgb(180, 180, 180)"], [0.555, "rgb(165, 165, 165)"],
              [0.666, "rgb(150, 150, 150)"], [0.777, "rgb(135, 135, 135)"],
              [0.888, "rgb(120, 120, 120)"], [1.0, "rgb(105, 105, 105)"]]

    contours = dict(x=dict(highlight=False),
                    y=dict(highlight=False),
                    z=dict(highlight=False))
    sphere = go.Surface(x=xx,
                        y=yy,
                        z=zz,
                        colorscale=cscale,
                        showscale=False,
                        hoverinfo='none',
                        contours=contours,
                        reversescale=True,
                        name='Surface')
    sphere['showlegend'] = True

    # Plot layout
    noaxis = dict(showbackground=False,
                  showticklabels=False,
                  title='',
                  showspikes=False)
    layout3d = dict(font=dict(family='Arial'),
                    scene=dict(xaxis=noaxis, yaxis=noaxis, zaxis=noaxis))

    data = [sphere, stems, true_nodes, t_anchors]

    fig = go.Figure(data=data, layout=layout3d)

    t_ = f'True and Mapped Positions<br>RMSE: {rmse:.2f} km<br>Anchors ' \
         f'nodes: [{anchors[0]} - {anchors[1]} - {anchors[2]} - ' \
         f'{anchors[3]}]<br> Average ln size: {ln_size:.2f} nodes'
    fig.update_layout(title_text=t_, title_font_size=20, title_x=0.5)

    plotly.offline.plot(
        fig, filename=f'{results_path}/{hop_lim}hop_map-p-refine.html')
Example #5
0
def stats(data_name, n_sat, show_plots, save_figs):
    current_file_path = Path(__file__)
    results_path = str(current_file_path.parents[1]) + f'/results/{data_name}/'

    G = shortest_path(results_path)
    node_list = [int(x) for x in list(G.nodes)]

    avg_local_n_size_list = [-3]
    ln_min = []
    ln_max = []
    i = 1
    while True:
        local_n_size_list = []
        for j in node_list:
            # frontier is dictionary of local neighborhood
            frontier = nx.single_source_shortest_path(G, str(j), cutoff=i)
            # get frontier keys, which are local neighborhood nodes
            local_n = [int(x) for x in list(frontier.keys())]

            size_local_n = len(local_n)
            local_n_size_list.append(size_local_n)

        # calculate average size of local neighborhood (averaged over all nodes)
        avg_local_n_size = sum(local_n_size_list) / n_sat

        # Bar labels
        ln_min.append(min(local_n_size_list))
        ln_max.append(max(local_n_size_list))

        # when the network saturates, exit loop
        if avg_local_n_size == avg_local_n_size_list[-1]:
            break
        # otherwise, append avg to list
        else:
            if i == 1:
                avg_local_n_size_list[0] = avg_local_n_size
            else:
                avg_local_n_size_list.append(avg_local_n_size)
            i += 1
    # avg_percent_list = [100*x/n_sat for x in avg_local_n_size_list]
    del ln_min[-1]
    del ln_max[-1]

    # Plotting
    plt.rcParams['axes.prop_cycle'] = plt.cycler(color=plt.cm.Set1.colors)
    plt.rcParams['font.sans-serif'] = 'Arial'
    # plt.rcParams.update({'font.size': 12})

    fig, ax = plt.subplots()
    n_hops = np.arange(1, i)
    ax.plot(n_hops, avg_local_n_size_list, marker='.', linewidth=0.5, label='Mean')
    ax.set_xlabel('Local neighborhood hop limit [# of hops]')
    ax.set_ylabel('Local neighborhood size [# of nodes]')
    ax.set_title('Local Neighborhood Size vs Hop Limit' + '\n' + data_name)
    ax.set_xticks(n_hops)
    ax.grid(linestyle='--')
    ax.scatter(n_hops, ln_max, color='C1', marker=10, label='Max')
    ax.scatter(n_hops, ln_min, color='C2', marker=11, label='Min')
    for i in range(len(ln_min)):
        ax.text(n_hops[i] + .1, ln_min[i] - 15, str(ln_min[i]), verticalalignment='center')
        ax.text(n_hops[i] + .1, ln_max[i] + 10, str(ln_max[i]), verticalalignment='center')
        ax.text(n_hops[i] + .1, avg_local_n_size_list[i], str(round(avg_local_n_size_list[i], 1)), verticalalignment='center')
    ax.legend()
    ax.fill_between(n_hops, ln_min, ln_max, color='C3', alpha=0.1)
    ax.set_axisbelow(True)

    if save_figs:
        plt.savefig(f'{results_path}/path_length.svg')
    if show_plots:
        plt.show()
Example #6
0
def plot_3d(data_name, center_node, n_hop, colormap):
    current_file_path = Path(__file__)
    results_path = str(current_file_path.parents[1]) + f'/results/{data_name}/'

    # open xy text file and extract values
    xy = open(results_path + 'xy.txt', 'r')
    pos = {}
    for i, line in enumerate(xy):
        a = line.split()
        pos[str(i)] = (float(a[0]), float(a[1]))
    xy.close()

    n_nodes = len(pos)
    # Create graph object based on links and distances txt files
    G = shortest_path(results_path)

    # get node degrees in sorted list
    node_and_degree = {}
    for node, val in G.degree():
        node_and_degree[node] = val
    # add degrees for nodes with 0 connections
    for i in range(n_nodes):
        if str(i) not in node_and_degree:
            node_and_degree[str(i)] = 0
            G.add_node(str(i), weight=0)

    x_center = pos[str(center_node)][0]
    y_center = pos[str(center_node)][1]

    frontier_list = []
    local_n_list = []
    local_n_list_reduced = []

    # Each frontier is a dictionary of local neighborhood
    for i in range(n_hop + 1):  # includes 0-hop neighborhood
        frontier_list.append(
            nx.single_source_shortest_path(G, str(center_node), cutoff=i))
        # get frontier keys, which are local neighborhood nodes
        local_n_list.append([str(x) for x in list(frontier_list[i].keys())])
    local_n_size = len(local_n_list[-1])

    # Create 'reduced' list, manually add 0, 1 hop neighbor nodes
    for i in range(0, 2):
        local_n_list_reduced.append(local_n_list[i])
    # Remove lower level (-2 levels) hop nodes so each frontier only includes 'growth'
    for i in range(2, n_hop + 1):
        local_n_list_reduced.append(
            [x for x in local_n_list[i] if x not in local_n_list[i - 2]])

    # Plotting
    # Iterate over local nbrhood list to extract the xy coordinates of each neighborhood node
    xi = []
    yi = []
    zi = []
    for i in local_n_list[-1]:
        xi.append(pos[i][0])
        yi.append(pos[i][1])
    # mode='markers+text' for labels
    nbr_nodes = go.Scatter(x=xi,
                           y=yi,
                           mode='markers',
                           marker=dict(color='red', size=3),
                           text=local_n_list[-1],
                           hoverinfo='none',
                           name='LN nodes')
    nbr_nodes['showlegend'] = True

    # center node
    center = go.Scatter(x=[x_center],
                        y=[y_center],
                        mode='markers',
                        marker=dict(color='azure',
                                    size=6,
                                    line=dict(color='black', width=1)),
                        text=str(center_node),
                        hoverinfo='none',
                        name=f'Center node')
    center['showlegend'] = False

    # Plot nodes external to local neighborhood
    xo = []
    yo = []
    all_nodes = [str(x) for x in list(range(n_nodes))]
    for i in all_nodes:
        xo.append(pos[i][0])
        yo.append(pos[i][1])
    ext_nodes = go.Scatter(x=xo,
                           y=yo,
                           mode='markers',
                           marker=dict(color='black', size=2),
                           text=all_nodes,
                           hoverinfo='text',
                           name='External nodes')
    ext_nodes['showlegend'] = True

    # get link colors by hop path length
    link_colors = []
    cmap = cm.get_cmap(colormap, n_hop)
    for i in range(cmap.N):
        rgb = cmap(i)[:3]
        link_colors.append(colors.rgb2hex(rgb))
    link_colors.insert(0, '#000000')  # insert color for 0-hop neighborhood

    # Plot local neighborhood edges
    # Iterate over list of edges to get the xy, coordinates of connected nodes
    grow_edges = []
    existing_links = []
    for i, frontier in enumerate(local_n_list_reduced):
        x_grow = []
        y_grow = []
        for j in G.edges(frontier):
            x = [pos[j[0]][0], pos[j[1]][0], None]
            y = [pos[j[0]][1], pos[j[1]][1], None]
            if j[0] in frontier and j[
                    1] in frontier and nx.shortest_path_length(
                        G, str(center_node), j[0]) == i - 1:
                x_grow += x
                y_grow += y
                existing_links.append([j[0], j[1]])
        grow_edges.append(
            go.Scatter(x=x_grow,
                       y=y_grow,
                       mode='lines',
                       line=dict(color=link_colors[i], width=.7),
                       name=f'{i}-hop',
                       hoverinfo='none'))

    # Plot edges not in local neighborhood
    x_ext = []
    y_ext = []

    for j in G.edges([str(i) for i in range(n_nodes)]):
        x = [pos[j[0]][0], pos[j[1]][0], None]
        y = [pos[j[0]][1], pos[j[1]][1], None]
        # if [j[0], j[1]] not in existing_links and [j[1], j[0]] not in existing_links:
        x_ext += x
        y_ext += y
    ext_edges = go.Scatter(x=x_ext,
                           y=y_ext,
                           mode='lines',
                           line=dict(color='rgb(0, 0, 0)', width=0.2),
                           hoverinfo='none',
                           name='External links')

    # Plot layout
    xaxis = dict(ticks='outside',
                 title='',
                 zeroline=False,
                 showspikes=False,
                 linecolor='grey')
    yaxis = dict(
        ticks='outside',
        title='',
        zeroline=False,
        showspikes=False,
        linecolor='grey',
        scaleanchor='x',
        scaleratio=1,
    )
    layout = dict(
        title=f'{data_name} network<br>'
        f'Node {center_node}: {local_n_size} nodes in local neighborhood',
        font=dict(family='Arial'),
        plot_bgcolor='rgba(0, 0, 0, 0)',
        xaxis=xaxis,
        yaxis=yaxis)

    data = grow_edges
    # data = []
    data.append(ext_edges)
    data.append(ext_nodes)
    data.append(nbr_nodes)
    data.append(center)
    fig = dict(data=data, layout=layout)

    plotly.offline.plot(fig,
                        filename=f'{results_path}/{data_name}_network.html')
Example #7
0
def plot_path(data_name, pair, n_hop, showLN):
    current_file_path = Path(__file__)
    results_path = str(current_file_path.parents[1]) + f'/results/{data_name}/'

    # open xyz text file and extract values
    xyz = open(results_path + 'xyz.txt', 'r')
    pos = {}
    for i, line in enumerate(xyz):
        a = line.split()
        pos[str(i)] = (float(a[0]), float(a[1]), float(a[2]))
    xyz.close()

    n_nodes = len(pos)
    # Create graph object based on links and distances txt files
    G = shortest_path(results_path)

    # add degrees for nodes with 0 connections
    for i in range(n_nodes):
        if str(i) not in list(G):
            G.add_node(str(i), weight=0)

    src = pair[0]
    dst = pair[1]

    flag = False
    hops_file = open(results_path + 'hops.txt', 'r')
    for line in hops_file:
        if line.split()[0] == str(src) and line.split()[1] == str(dst):
            split1 = line.split('[')
            split2 = split1[1].split(']')
            hop_path = split2[0].split(', ')
            flag = True
            break
    hops_file.close()

    if flag is False:
        print(f'Error! There is no path between node {src} and {dst}')
        return

    # Plotting
    # Iterate over path list to get xyz coordinates
    xi = []
    yi = []
    zi = []
    for i in hop_path:
        xi.append(pos[i][0])
        yi.append(pos[i][1])
        zi.append(pos[i][2])
    path_nodes = go.Scatter3d(x=xi,
                              y=yi,
                              z=zi,
                              mode='markers',
                              marker=dict(color='cyan', size=2),
                              text=hop_path,
                              hoverinfo='text',
                              name='Path nodes',
                              textfont=dict(color='red'))
    path_nodes['showlegend'] = True

    # src node
    x_src = pos[str(src)][0]
    y_src = pos[str(src)][1]
    z_src = pos[str(src)][2]
    src_trace = go.Scatter3d(x=[x_src],
                             y=[y_src],
                             z=[z_src],
                             mode='markers',
                             marker=dict(color='azure',
                                         size=5,
                                         line=dict(color='black', width=0.2)),
                             text=str(src),
                             hoverinfo='text',
                             name='Source node')
    src_trace['showlegend'] = False
    # dst node
    x_dst = pos[str(dst)][0]
    y_dst = pos[str(dst)][1]
    z_dst = pos[str(dst)][2]
    dst_trace = go.Scatter3d(x=[x_dst],
                             y=[y_dst],
                             z=[z_dst],
                             mode='markers',
                             marker=dict(color='azure',
                                         size=5,
                                         line=dict(color='black', width=0.2)),
                             text=str(dst),
                             hoverinfo='text',
                             name='Destination node')
    dst_trace['showlegend'] = False

    # Plot nodes external to path
    xo = []
    yo = []
    zo = []
    node_list = list(range(n_nodes))
    for i in node_list:
        xo.append(pos[str(i)][0])
        yo.append(pos[str(i)][1])
        zo.append(pos[str(i)][2])
    ext_nodes = go.Scatter3d(x=xo,
                             y=yo,
                             z=zo,
                             mode='markers',
                             marker=dict(color='black', size=1.3),
                             text=node_list,
                             hoverinfo='text',
                             name='External nodes')
    ext_nodes['showlegend'] = True

    # get link colors by hop path length
    path_colors = []
    cmap = cm.get_cmap('plasma', len(hop_path))
    for i in range(cmap.N):
        rgb = cmap(i)[:3]
        path_colors.append(colors.rgb2hex(rgb))

    # Plot path edges
    # Iterate over list of edges to get the xyz, coordinates of connected nodes
    path_traces = []
    path_links = []

    for j in range(1, len(hop_path)):
        x = [pos[hop_path[j - 1]][0], pos[hop_path[j]][0], None]
        y = [pos[hop_path[j - 1]][1], pos[hop_path[j]][1], None]
        z = [pos[hop_path[j - 1]][2], pos[hop_path[j]][2], None]

        path_links.append([hop_path[j - 1], hop_path[j]])
        path_traces.append(
            go.Scatter3d(x=x,
                         y=y,
                         z=z,
                         mode='lines',
                         line=dict(color=path_colors[j], width=4),
                         name=f'Hop {j}',
                         hoverinfo='none'))

    # Plot edges not in path
    x_ext = []
    y_ext = []
    z_ext = []

    for j in G.edges([str(i) for i in range(n_nodes)]):
        x = [pos[j[0]][0], pos[j[1]][0], None]
        y = [pos[j[0]][1], pos[j[1]][1], None]
        z = [pos[j[0]][2], pos[j[1]][2], None]
        if [j[0], j[1]] not in path_links and [j[1], j[0]] not in path_links:
            x_ext += x
            y_ext += y
            z_ext += z
    ext_edges = go.Scatter3d(x=x_ext,
                             y=y_ext,
                             z=z_ext,
                             mode='lines',
                             line=dict(color='rgb(0, 0, 0)', width=0.4),
                             hoverinfo='none',
                             name='External links')

    # Plot earth
    u, v = np.mgrid[0:2 * np.pi:30j, 0:np.pi:30j]
    X = 6371 * np.cos(u) * np.sin(v)
    Y = 6371 * np.sin(u) * np.sin(v)
    Z = 6371 * np.cos(v)

    contours = dict(x=dict(highlight=False),
                    y=dict(highlight=False),
                    z=dict(highlight=False))
    sphere = go.Surface(x=X,
                        y=Y,
                        z=Z,
                        colorscale='Greys',
                        showscale=False,
                        hoverinfo='none',
                        contours=contours,
                        reversescale=True)

    # Plotting local neighborhood of destination node
    if showLN:
        frontier_list = []
        local_n_list = []
        local_n_list_reduced = []

        # Each frontier is a dictionary of local neighborhood
        for i in range(n_hop + 1):  # includes 0-hop neighborhood
            frontier_list.append(
                nx.single_source_shortest_path(G, str(dst), cutoff=i))
            # get frontier keys, which are local neighborhood nodes
            local_n_list.append(
                [str(x) for x in list(frontier_list[i].keys())])

        # Create 'reduced' list, manually add 0, 1 hop neighbor nodes
        for i in range(0, 2):
            local_n_list_reduced.append(local_n_list[i])
        # Remove lower level (-2 levels) hop nodes so each frontier only includes 'growth'
        for i in range(2, n_hop + 1):
            local_n_list_reduced.append(
                [x for x in local_n_list[i] if x not in local_n_list[i - 2]])

        # get link colors by hop
        link_colors = []
        cmap = cm.get_cmap('GnBu', n_hop)
        for i in range(cmap.N):
            rgb = cmap(i)[:3]
            link_colors.append(colors.rgb2hex(rgb))
        link_colors.insert(0, '#000000')  # insert color for 0-hop neighborhood

        # Iterate over local nbrhood list to extract the xyz coordinates of each
        # neighborhood node
        xi = []
        yi = []
        zi = []
        for i in local_n_list[-1]:
            xi.append(pos[i][0])
            yi.append(pos[i][1])
            zi.append(pos[i][2])
        # mode='markers+text' for labels
        nbr_nodes = go.Scatter3d(x=xi,
                                 y=yi,
                                 z=zi,
                                 mode='markers',
                                 marker=dict(color='red', size=2),
                                 text=local_n_list[-1],
                                 hoverinfo='text',
                                 name='LN nodes')
        nbr_nodes['showlegend'] = True

        # Plot local neighborhood edges
        # Iterate over list of edges to get the xyz, coordinates of connected nodes
        grow_edges = []
        for i, frontier in enumerate(local_n_list_reduced):
            x_grow = []
            y_grow = []
            z_grow = []
            for j in G.edges(frontier):
                x = [pos[j[0]][0], pos[j[1]][0], None]
                y = [pos[j[0]][1], pos[j[1]][1], None]
                z = [pos[j[0]][2], pos[j[1]][2], None]
                if j[0] in frontier and j[
                        1] in frontier and nx.shortest_path_length(
                            G, str(dst), j[0]) == i - 1:
                    x_grow += x
                    y_grow += y
                    z_grow += z
            grow_edges.append(
                go.Scatter3d(x=x_grow,
                             y=y_grow,
                             z=z_grow,
                             mode='lines',
                             line=dict(color=link_colors[i], width=1.5),
                             name=f'{i}-hop',
                             hoverinfo='none'))

    # Plot layout
    noaxis = dict(showbackground=False,
                  showgrid=False,
                  showticklabels=False,
                  ticks='',
                  title='',
                  zeroline=False,
                  showspikes=False)
    layout3d = dict(title=f'{data_name} network<br>'
                    f'Path from node {src} - {dst}: {len(hop_path)-1} hops',
                    font=dict(family='Arial'),
                    scene=dict(xaxis=noaxis, yaxis=noaxis, zaxis=noaxis))

    data = [
        sphere, ext_nodes, path_nodes, nbr_nodes, src_trace, dst_trace,
        ext_edges
    ]
    if showLN:
        data += grow_edges
    data += path_traces
    fig = dict(data=data, layout=layout3d)

    plotly.offline.plot(
        fig, filename=f'{results_path}/{data_name}_{src}-{dst}_path.html')
Example #8
0
def stats(data_name, n_sat, show_plots):
    current_file_path = Path(__file__)
    results_path = str(current_file_path.parents[1]) + f'/results/{data_name}/'
    hops_path = results_path + 'hops.txt'

    G = shortest_path(results_path)

    path_length = []
    pairs = []
    hops_file = open(hops_path, 'r')
    for line in hops_file:
        path_length.append(int(line.split()[2]))
        pairs.append(line.split()[0:2])
    hops_file.close()

    test = 0
    for pair in pairs:
        test += nx.shortest_path_length(G, pair[0], pair[1])
    nx_avg_path_length = test / len(pairs)

    # Plotting
    plt.rcParams['axes.prop_cycle'] = plt.cycler(color=plt.cm.Paired.colors)
    plt.rcParams['font.sans-serif'] = 'Arial'

    # Path length distribution #
    fig, ax = plt.subplots()

    # histogram
    bins = np.arange(min(path_length), max(path_length) + 2) - 0.5
    ax.hist(path_length,
            bins,
            color='C0',
            rwidth=0.7,
            edgecolor='black',
            linewidth=0.5,
            alpha=0.8)
    ax.set_ylabel('Number of connections')
    ax.grid(linestyle=':')
    ax.set_axisbelow(True)

    # gaussian fit
    ax2 = ax.twinx()
    ax2.set_ylabel('Probability distribution')
    ax2.yaxis.label.set_color('C9')

    x = np.arange(min(path_length), max(path_length) + .1, .1)
    (mu, sigma) = norm.fit(path_length)
    # scale = len(path_length)
    y = norm.pdf(x, mu, sigma)
    ax2.set_ylim(bottom=0, top=max(y) * 1.2)
    ax2.plot(x, y, 'C9--')
    s = r'$\mu = $' + f'{mu:.3f}' + '\n' + r'$\sigma = $' + f'{sigma:.3f}'
    s2 = 'NetworkX routing:' + '\n' + r'$\mu = $' + f'{nx_avg_path_length:.3f}'
    ax2.text(.95,
             .85,
             s,
             transform=ax.transAxes,
             va='baseline',
             ha='right',
             bbox=dict(facecolor='C0', alpha=0.7))
    ax2.text(.95,
             .78,
             s2,
             transform=ax.transAxes,
             va='top',
             ha='right',
             bbox=dict(facecolor='C2', alpha=0.7))
    ax2.tick_params(axis='y', labelcolor='C9')

    plt.xticks(range(min(path_length), max(path_length) + 1))
    ax.set_xlabel('Number of hops')
    plt.title(f'Path length distribution: {data_name}')
    fig.tight_layout()  # otherwise right y-label is clipped

    if show_plots:
        plt.show()
Example #9
0
def plot_range(data_name, hop_limit, range_limit, show_plots):

    current_file_path = Path(__file__)
    results_path = str(current_file_path.parents[1]) + f'/results/{data_name}/'

    # Get satellite distances
    distance_table = {}
    distance_file = open(results_path + 'distance.txt', 'r')
    for i, line in enumerate(distance_file):
        distance_table[i] = [float(x) for x in line.split()]
    distance_file.close()

    n_nodes = len(distance_table)
    G = shortest_path(results_path)

    # get node degrees in sorted list
    node_and_degree = {}
    for node, val in G.degree():
        node_and_degree[node] = val
    # add degrees for nodes with 0 connections
    for i in range(n_nodes):
        if str(i) not in node_and_degree:
            G.add_node(str(i), weight=0)
            # node_and_degree[str(i)] = 0

    range_range = list(range(0, range_limit + 1, 200))

    def percent_in_LN_range(node, hop_n):
        p_in_LN_range = []
        in_range = []
        for i in range_range:
            # get satellites within various ranges
            in_subrange = {
                j: dist
                for j, dist in enumerate(distance_table[node]) if dist <= i
            }

            # get local neighborhood nodes for n_hop limit
            frontier_list = nx.single_source_shortest_path(G,
                                                           str(node),
                                                           cutoff=hop_n)
            # get frontier keys, which are local neighborhood nodes
            frontier_keys = [int(x) for x in list(frontier_list.keys())]

            # get satellites that are in the LN AND within the range
            in_LN_subrange = [x for x in frontier_keys if x in in_subrange]

            p_in_LN_range.append(len(in_LN_subrange) / len(in_subrange) * 100)
            in_range.append(len(in_subrange))

        return p_in_LN_range, in_range

    results = []
    avg_results = []
    pir = []

    for h in range(hop_limit + 1):
        for node in range(n_nodes):
            rrr, pirrr = percent_in_LN_range(node, h)
            results.append(rrr)
            if h == 0:  # only need to to in_range count once
                pir.append(pirrr)
        np_results = np.asarray(results)
        avg_results.append(np.mean(np_results, axis=0))
    np_pir = np.asarray(pir)
    avg_np_pir = np.mean(np_pir, axis=0)

    # Plotting
    #
    plt.rcParams['axes.prop_cycle'] = plt.cycler(color=plt.cm.Set2.colors)
    plt.rcParams['font.sans-serif'] = 'Arial'

    fig, ax = plt.subplots()

    for i, curve in enumerate(avg_results):
        ax.plot(range_range,
                curve,
                linewidth=0.5,
                marker='.',
                label=f'{i}-hop local neighborhood')
    plt.xlabel('Range [km]')
    plt.ylabel('[Average %]')
    plt.title('Average percent nodes in LN and in range vs Range' + '\n' +
              data_name)
    ax.minorticks_on()
    ax.grid(which='major', linestyle='--')
    # ax.grid(which='minor', linestyle=':')
    ax.set_axisbelow(True)

    blank = [0] * len(range_range)
    ax.scatter(range_range,
               blank,
               c='r',
               marker=11,
               label='Average nodes in range')

    plt.legend()
    # axx = ax.twinx()
    # axx.set_ylabel('Average nodes in range')
    # axx.yaxis.label.set_color('red')
    # axx.tick_params(axis='y', labelcolor='red')
    # axx.scatter(range_range, avg_np_pir, marker='x', color='r')

    for i in range(len(range_range)):
        ax.text(range_range[i], blank[i] + 1, str(round(avg_np_pir[i], 1)))

    if show_plots:
        plt.show()