用命题的形式调整Netgraph中的字体大小?

发布于 2025-01-22 21:29:50 字数 1089 浏览 2 评论 0原文

我正在使用NetGraph可视化我的网络图。我现在的问题是,公式的可视化自然方式不像我预期的那样漂亮。这里我的示例图:

import networkx as nx
from netgraph import Graph # pip install netgraph
import matplotlib.pyplot as plt

node_labels = {1: 'p→q', 2: '¬q', 3: '¬ (¬p)', 4: '¬p', 5: '¬p∧ ¬ (¬p)', 6: 'p', 7: 'q', 8: 'q∧ ¬q', 9: '¬p'}
color_map = {1: 'red', 2: 'red', 3: 'red', 4: 'red', 5: 'lightblue', 6: 'lightblue', 7: 'lightblue', 8: 'lightblue', 9: 'blue'}
edge_labels = {(3, 5): '∧I', (4, 5): '∧I', (4, 6): '¬E', (5, 6): '¬E', (1, 7): '→E', (6, 7): '→E', (2, 8): '∧I', (7, 8): '∧I', (8, 9): '¬E', (3, 9): '¬E'}

graph = nx.from_edgelist(edge_labels, nx.DiGraph())


Graph(graph, node_labels=node_labels, edge_labels=edge_labels,
      node_color=color_map, node_edge_color=color_map, arrows=True)

plt.show()

输出(Direct/Zoom in):

“在此处输入图像说明”

我现在的问题:

  • 它们是否是调整节点字体大小的方法?
  • 是否可以以这种方式旋转边缘标签?

I am using netgraph to visualize my networkx graphs. My problem now is, the visualisation of formulas are in natural way not as pretty as I would expect. Here my example graph:

import networkx as nx
from netgraph import Graph # pip install netgraph
import matplotlib.pyplot as plt

node_labels = {1: 'p→q', 2: '¬q', 3: '¬ (¬p)', 4: '¬p', 5: '¬p∧ ¬ (¬p)', 6: 'p', 7: 'q', 8: 'q∧ ¬q', 9: '¬p'}
color_map = {1: 'red', 2: 'red', 3: 'red', 4: 'red', 5: 'lightblue', 6: 'lightblue', 7: 'lightblue', 8: 'lightblue', 9: 'blue'}
edge_labels = {(3, 5): '∧I', (4, 5): '∧I', (4, 6): '¬E', (5, 6): '¬E', (1, 7): '→E', (6, 7): '→E', (2, 8): '∧I', (7, 8): '∧I', (8, 9): '¬E', (3, 9): '¬E'}

graph = nx.from_edgelist(edge_labels, nx.DiGraph())


Graph(graph, node_labels=node_labels, edge_labels=edge_labels,
      node_color=color_map, node_edge_color=color_map, arrows=True)

plt.show()

Output (direct / after zoom in):

enter image description hereenter image description here:

My questions now:

  • Is their a way to adjust the font size of the nodes?
  • Is it possible to rotate the edge labels in that way they are aligned horizontally?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

○愚か者の日 2025-01-29 21:29:50

默认情况下,iff节点标签绘制在节点顶部(即没有偏移),NetGraph缩放节点标签字体大小,以使所有标签都适合其各自的节点艺术家。但是,可以通过明确指定字体大小,例如使用node_label_fontdict(size = 20)来覆盖此行为。

边缘标签的旋转可以关闭设置edge_label_rotate = false flag。

#!/usr/bin/env python
# coding: utf-8

import matplotlib.pyplot as plt
import networkx as nx

from netgraph import Graph # pip install netgraph

node_labels = {1: 'p→q', 2: '¬q', 3: '¬ (¬p)', 4: '¬p', 5: '¬p∧ ¬ (¬p)', 6: 'p', 7: 'q', 8: 'q∧ ¬q', 9: '¬p'}
color_map = {1: 'red', 2: 'red', 3: 'red', 4: 'red', 5: 'lightblue', 6: 'lightblue', 7: 'lightblue', 8: 'lightblue', 9: 'blue'}
edge_labels = {(3, 5): '∧I', (4, 5): '∧I', (4, 6): '¬E', (5, 6): '¬E', (1, 7): '→E', (6, 7): '→E', (2, 8): '∧I', (7, 8): '∧I', (8, 9): '¬E', (3, 9): '¬E'}

graph = nx.from_edgelist(edge_labels, nx.DiGraph())

Graph(graph, node_layout='dot',
      node_labels=node_labels, node_label_fontdict=dict(size=21),
      edge_labels=edge_labels, edge_label_fontdict=dict(size=14), edge_label_rotate=False,
      node_color=color_map, node_edge_color=color_map, arrows=True
)

plt.show()

By default, iff node labels are plotted on top of nodes (i.e. without an offset), netgraph scales the node label font size such that all labels fit within their respective node artists. However, this behaviour can be overridden by specifying the font size explicitly , e.g. using node_label_fontdict(size=20).

The rotation of the edge labels can be turned off setting the edge_label_rotate = False flag.

enter image description here

#!/usr/bin/env python
# coding: utf-8

import matplotlib.pyplot as plt
import networkx as nx

from netgraph import Graph # pip install netgraph

node_labels = {1: 'p→q', 2: '¬q', 3: '¬ (¬p)', 4: '¬p', 5: '¬p∧ ¬ (¬p)', 6: 'p', 7: 'q', 8: 'q∧ ¬q', 9: '¬p'}
color_map = {1: 'red', 2: 'red', 3: 'red', 4: 'red', 5: 'lightblue', 6: 'lightblue', 7: 'lightblue', 8: 'lightblue', 9: 'blue'}
edge_labels = {(3, 5): '∧I', (4, 5): '∧I', (4, 6): '¬E', (5, 6): '¬E', (1, 7): '→E', (6, 7): '→E', (2, 8): '∧I', (7, 8): '∧I', (8, 9): '¬E', (3, 9): '¬E'}

graph = nx.from_edgelist(edge_labels, nx.DiGraph())

Graph(graph, node_layout='dot',
      node_labels=node_labels, node_label_fontdict=dict(size=21),
      edge_labels=edge_labels, edge_label_fontdict=dict(size=14), edge_label_rotate=False,
      node_color=color_map, node_edge_color=color_map, arrows=True
)

plt.show()
惜醉颜 2025-01-29 21:29:50

Plotly具有a 网络图的非常好的示例很容易根据您的需求阅读。

这是您任务的答案。

# Packages import
import networkx as nx
import plotly.graph_objs as go
# Your input data
node_labels = {1: 'p→q', 2: '¬q', 3: '¬ (¬p)', 4: '¬p', 5: '¬p∧ ¬ (¬p)', 6: 'p', 7: 'q', 8: 'q∧ ¬q', 9: '¬p'}
color_map = {1: 'red', 2: 'red', 3: 'red', 4: 'red', 5: 'lightblue', 6: 'lightblue', 7: 'lightblue', 8: 'lightblue', 9: 'blue'}
edge_labels = {(3, 5): '∧I', (4, 5): '∧I', (4, 6): '¬E', (5, 6): '¬E', (1, 7): '→E', (6, 7): '→E', (2, 8): '∧I', (7, 8): '∧I', (8, 9): '¬E', (3, 9): '¬E'}

# Create DiGraph
G=nx.DiGraph()
# Add nodes and edges
G.add_nodes_from(list(node_labels.keys()), weight=15)
G.add_edges_from(list(edge_labels.keys()))
# Create Positions
pos = nx.planar_layout(G)  # nx.random_layout(G), ...
# Create edges for plot and edge annotations
edge_x = []
edge_y = []
edge_label_x = []
edge_label_y = []
for edge in G.edges:
    x0, y0 = pos[edge[0]][0], pos[edge[0]][1]
    x1, y1 = pos[edge[1]][0], pos[edge[1]][1]
    edge_x.append(x0)
    edge_x.append(x1)
    edge_x.append(None)
    edge_y.append(y0)
    edge_y.append(y1)
    edge_y.append(None)
    edge_label_x.append((x0+x1)/2)
    edge_label_y.append((y0+y1)/2)
# Make go.Scatter for edges
edge_trace = go.Scatter(
    x=edge_x, y=edge_y,
    line=dict(width=0.5, color='#888'),
    hoverinfo='none',
    mode='lines'
)

# Create nodes for plot
node_x = []
node_y = []
node_color = []
for node in G.nodes:
    x, y = pos[node][0], pos[node][1]
    node_x.append(x)
    node_y.append(y)
    node_color.append(color_map[node])
# Make go.Scatter for nodes
node_trace = go.Scatter(
    x=node_x, y=node_y,
    mode='markers+text',
    hoverinfo='text',
    text=list(node_labels.values()),
    textposition="middle center",  # ['top left', 'top center', 'top right', 'middle left',
                                   # 'middle center', 'middle right', 'bottom left', 
                                   # 'bottom center', 'bottom right']
    textfont=dict(
        family="sans serif",
        size=10,  # <-- Here you change the node text size
        color="black"
    ),
    marker=dict(
        showscale=False,
        color=node_color,
        size=46,
        line_width=1
    )
)
# Make edge annotations
edge_annotations = []
for label, x, y in zip(list(edge_labels.values()), edge_label_x, edge_label_y):
    edge_annotations.append(
        dict(
            x=x, y=y,
            showarrow=False,
            hovertext='none',
            ax=0,
            ay=0,
            bgcolor="white",
            opacity=0.85,
            text=label,
            font=dict(
                family="sans serif",
                size=14,
                color="black",
            )
        )
    )

# Make go.Figure
fig = go.Figure(
    data=[edge_trace, node_trace],
    layout=go.Layout(
        paper_bgcolor='rgba(0,0,0,0)',
        plot_bgcolor='rgba(0,0,0,0)',
        title='<br>Network graph',
        titlefont_size=16,
        showlegend=False,
        hovermode='closest',
        xaxis=dict(showgrid=False, zeroline=False, showticklabels=False),
        yaxis=dict(showgrid=False, zeroline=False, showticklabels=False),
        autosize=False,
        width=700,
        height=700,
        margin=dict(l=50, r=50, b=100, t=100, pad=4),
    )
)
# Add edge annotations to go.Figure
for edge_annotation in edge_annotations:
    fig.add_annotation(edge_annotation)
# Show go.Figure
fig.show()

导致:

编辑:

用plotly添加边缘说明更加棘手(请参阅此问题)。幸运的是,有一个 github project 我们可以从中借用一个函数,通过保持箭头来通过保持边缘来保持边缘来保持边缘。考虑到节点大小。

现在的代码为:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Fri May 15 11:45:07 2020
@author: aransil
"""

import math

# Start and end are lists defining start and end points
# Edge x and y are lists used to construct the graph
# arrowAngle and arrowLength define properties of the arrowhead
# arrowPos is None, 'middle' or 'end' based on where on the edge you want the arrow to appear
# arrowLength is the length of the arrowhead
# arrowAngle is the angle in degrees that the arrowhead makes with the edge
# dotSize is the plotly scatter dot size you are using (used to even out line spacing when you have a mix of edge lengths)
def addEdge(start, end, edge_x, edge_y, lengthFrac=1, arrowPos = None, arrowLength=0.025, arrowAngle = 30, dotSize=20):

    # Get start and end cartesian coordinates
    x0, y0 = start
    x1, y1 = end

    # Incorporate the fraction of this segment covered by a dot into total reduction
    length = math.sqrt( (x1-x0)**2 + (y1-y0)**2 )
    dotSizeConversion = .0565/20 # length units per dot size
    convertedDotDiameter = dotSize * dotSizeConversion
    lengthFracReduction = convertedDotDiameter / length
    lengthFrac = lengthFrac - lengthFracReduction

    # If the line segment should not cover the entire distance, get actual start and end coords
    skipX = (x1-x0)*(1-lengthFrac)
    skipY = (y1-y0)*(1-lengthFrac)
    x0 = x0 + skipX/2
    x1 = x1 - skipX/2
    y0 = y0 + skipY/2
    y1 = y1 - skipY/2

    # Append line corresponding to the edge
    edge_x.append(x0)
    edge_x.append(x1)
    edge_x.append(None) # Prevents a line being drawn from end of this edge to start of next edge
    edge_y.append(y0)
    edge_y.append(y1)
    edge_y.append(None)

    # Draw arrow
    if not arrowPos == None:

        # Find the point of the arrow; assume is at end unless told middle
        pointx = x1
        pointy = y1

        eta = math.degrees(math.atan((x1-x0)/(y1-y0))) if y1!=y0 else 90.0

        if arrowPos == 'middle' or arrowPos == 'mid':
            pointx = x0 + (x1-x0)/2
            pointy = y0 + (y1-y0)/2

        # Find the directions the arrows are pointing
        signx = (x1-x0)/abs(x1-x0) if x1!=x0 else +1    #verify this once
        signy = (y1-y0)/abs(y1-y0) if y1!=y0 else +1    #verified

        # Append first arrowhead
        dx = arrowLength * math.sin(math.radians(eta + arrowAngle))
        dy = arrowLength * math.cos(math.radians(eta + arrowAngle))
        edge_x.append(pointx)
        edge_x.append(pointx - signx**2 * signy * dx)
        edge_x.append(None)
        edge_y.append(pointy)
        edge_y.append(pointy - signx**2 * signy * dy)
        edge_y.append(None)

        # And second arrowhead
        dx = arrowLength * math.sin(math.radians(eta - arrowAngle))
        dy = arrowLength * math.cos(math.radians(eta - arrowAngle))
        edge_x.append(pointx)
        edge_x.append(pointx - signx**2 * signy * dx)
        edge_x.append(None)
        edge_y.append(pointy)
        edge_y.append(pointy - signx**2 * signy * dy)
        edge_y.append(None)


    return edge_x, edge_y
# Packages import
import networkx as nx
import plotly.graph_objs as go
# Your input data
node_labels = {1: 'p→q', 2: '¬q', 3: '¬ (¬p)', 4: '¬p', 5: '¬p∧ ¬ (¬p)', 6: 'p', 7: 'q', 8: 'q∧ ¬q', 9: '¬p'}
color_map = {1: 'red', 2: 'red', 3: 'red', 4: 'red', 5: 'lightblue', 6: 'lightblue', 7: 'lightblue', 8: 'lightblue', 9: 'blue'}
edge_labels = {(3, 5): '∧I', (4, 5): '∧I', (4, 6): '¬E', (5, 6): '¬E', (1, 7): '→E', (6, 7): '→E', (2, 8): '∧I', (7, 8): '∧I', (8, 9): '¬E', (3, 9): '¬E'}

# General controls on the figure
NODE_SIZE = 46
LINE_WIDTH = 0.5
LINE_COLOR = '#888888'
FONT_FAMILY = 'serif'

# Create DiGraph
G=nx.DiGraph()
# Add nodes and edges
G.add_nodes_from(list(node_labels.keys()), weight=15)
G.add_edges_from(list(edge_labels.keys()))
# Create Positions
pos = nx.planar_layout(G)  # nx.random_layout(G), ...
pos[4][0] = -0.7  # <-- Changing the position of node 4 for readability
pos[9][0] = 0.9  # <-- Changing the position of node 9 for readability
for node in G.nodes:
    G.nodes[node]['pos'] = list(pos[node])

# Create Plot
# Create edges for plot and edge annotations
edge_x = []
edge_y = []
edge_label_x = []
edge_label_y = []
for edge in G.edges:
    start = G.nodes[edge[0]]['pos']
    end = G.nodes[edge[1]]['pos']
    edge_label_x.append((start[0]+end[0])/2)
    edge_label_y.append((start[1]+end[1])/2)
    edge_x, edge_y = addEdge(start, end, edge_x, edge_y, .95, 'end', .03, 20, NODE_SIZE)
# Make go.Scatter for edges
edge_trace = go.Scatter(
    x=edge_x, y=edge_y,
    mode='lines',
    line=dict(width=LINE_WIDTH, color=LINE_COLOR),
    hoverinfo='none',
)

# Create nodes for plot
node_x = []
node_y = []
node_color = []
for node in G.nodes:
    x, y = G.nodes[node]['pos']
    node_x.append(x)
    node_y.append(y)
    node_color.append(color_map[node])
# Make go.Scatter for nodes
node_trace = go.Scatter(
    x=node_x, y=node_y,
    mode='markers+text',
    hoverinfo='text',
    text=list(node_labels.values()),
    textposition="middle center",  # ['top left', 'top center', 'top right', 'middle left',
                                   # 'middle center', 'middle right', 'bottom left', 
                                   # 'bottom center', 'bottom right']
    textfont=dict(
        family=FONT_FAMILY,
        size=10,
        color="black"
    ),
    marker=dict(
        showscale=False,
        color=node_color,
        size=NODE_SIZE,
        line_width=1
    )
)
# Make edge annotations
edge_annotations = []
for label, x, y in zip(list(edge_labels.values()), edge_label_x, edge_label_y):
    edge_annotations.append(
        dict(
            x=x, y=y,
            showarrow=False,
            hovertext='none',
            ax=0,
            ay=0,
            bgcolor="white",
            opacity=0.95,
            text=label,
            font=dict(
                family=FONT_FAMILY,
                size=14,
                color="black",
            )
        )
    )

# Make go.Figure
fig = go.Figure(
    data=[edge_trace, node_trace],
    layout=go.Layout(
        paper_bgcolor='rgba(0,0,0,0)',
        plot_bgcolor='rgba(0,0,0,0)',
        title='<br>Network graph',
        titlefont_size=16,
        showlegend=False,
        hovermode='closest',
        xaxis=dict(showgrid=False, zeroline=False, showticklabels=False),
        yaxis=dict(showgrid=False, zeroline=False, showticklabels=False),
        autosize=False,
        width=700,
        height=700,
        margin=dict(l=50, r=50, b=100, t=100, pad=4),
    )
)
# Add edge annotations to go.Figure
for edge_annotation in edge_annotations:
    fig.add_annotation(edge_annotation)
# Show go.Figure
fig.show()

产生:

”带边缘箭头的网络图

Plotly has a very nice example of network graph that can be easily readapted to your needs.

Here's the answer to your quests.

# Packages import
import networkx as nx
import plotly.graph_objs as go
# Your input data
node_labels = {1: 'p→q', 2: '¬q', 3: '¬ (¬p)', 4: '¬p', 5: '¬p∧ ¬ (¬p)', 6: 'p', 7: 'q', 8: 'q∧ ¬q', 9: '¬p'}
color_map = {1: 'red', 2: 'red', 3: 'red', 4: 'red', 5: 'lightblue', 6: 'lightblue', 7: 'lightblue', 8: 'lightblue', 9: 'blue'}
edge_labels = {(3, 5): '∧I', (4, 5): '∧I', (4, 6): '¬E', (5, 6): '¬E', (1, 7): '→E', (6, 7): '→E', (2, 8): '∧I', (7, 8): '∧I', (8, 9): '¬E', (3, 9): '¬E'}

# Create DiGraph
G=nx.DiGraph()
# Add nodes and edges
G.add_nodes_from(list(node_labels.keys()), weight=15)
G.add_edges_from(list(edge_labels.keys()))
# Create Positions
pos = nx.planar_layout(G)  # nx.random_layout(G), ...
# Create edges for plot and edge annotations
edge_x = []
edge_y = []
edge_label_x = []
edge_label_y = []
for edge in G.edges:
    x0, y0 = pos[edge[0]][0], pos[edge[0]][1]
    x1, y1 = pos[edge[1]][0], pos[edge[1]][1]
    edge_x.append(x0)
    edge_x.append(x1)
    edge_x.append(None)
    edge_y.append(y0)
    edge_y.append(y1)
    edge_y.append(None)
    edge_label_x.append((x0+x1)/2)
    edge_label_y.append((y0+y1)/2)
# Make go.Scatter for edges
edge_trace = go.Scatter(
    x=edge_x, y=edge_y,
    line=dict(width=0.5, color='#888'),
    hoverinfo='none',
    mode='lines'
)

# Create nodes for plot
node_x = []
node_y = []
node_color = []
for node in G.nodes:
    x, y = pos[node][0], pos[node][1]
    node_x.append(x)
    node_y.append(y)
    node_color.append(color_map[node])
# Make go.Scatter for nodes
node_trace = go.Scatter(
    x=node_x, y=node_y,
    mode='markers+text',
    hoverinfo='text',
    text=list(node_labels.values()),
    textposition="middle center",  # ['top left', 'top center', 'top right', 'middle left',
                                   # 'middle center', 'middle right', 'bottom left', 
                                   # 'bottom center', 'bottom right']
    textfont=dict(
        family="sans serif",
        size=10,  # <-- Here you change the node text size
        color="black"
    ),
    marker=dict(
        showscale=False,
        color=node_color,
        size=46,
        line_width=1
    )
)
# Make edge annotations
edge_annotations = []
for label, x, y in zip(list(edge_labels.values()), edge_label_x, edge_label_y):
    edge_annotations.append(
        dict(
            x=x, y=y,
            showarrow=False,
            hovertext='none',
            ax=0,
            ay=0,
            bgcolor="white",
            opacity=0.85,
            text=label,
            font=dict(
                family="sans serif",
                size=14,
                color="black",
            )
        )
    )

# Make go.Figure
fig = go.Figure(
    data=[edge_trace, node_trace],
    layout=go.Layout(
        paper_bgcolor='rgba(0,0,0,0)',
        plot_bgcolor='rgba(0,0,0,0)',
        title='<br>Network graph',
        titlefont_size=16,
        showlegend=False,
        hovermode='closest',
        xaxis=dict(showgrid=False, zeroline=False, showticklabels=False),
        yaxis=dict(showgrid=False, zeroline=False, showticklabels=False),
        autosize=False,
        width=700,
        height=700,
        margin=dict(l=50, r=50, b=100, t=100, pad=4),
    )
)
# Add edge annotations to go.Figure
for edge_annotation in edge_annotations:
    fig.add_annotation(edge_annotation)
# Show go.Figure
fig.show()

Resulting in:
Network graph made with Plotly

Edit:

Adding edges directions with Plotly is a bit more tricky (see this question). Fortunately there is a github project from which we can borrow a function that adds arrowheads to edges by keeping into account node sizes.

The code now is:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Fri May 15 11:45:07 2020
@author: aransil
"""

import math

# Start and end are lists defining start and end points
# Edge x and y are lists used to construct the graph
# arrowAngle and arrowLength define properties of the arrowhead
# arrowPos is None, 'middle' or 'end' based on where on the edge you want the arrow to appear
# arrowLength is the length of the arrowhead
# arrowAngle is the angle in degrees that the arrowhead makes with the edge
# dotSize is the plotly scatter dot size you are using (used to even out line spacing when you have a mix of edge lengths)
def addEdge(start, end, edge_x, edge_y, lengthFrac=1, arrowPos = None, arrowLength=0.025, arrowAngle = 30, dotSize=20):

    # Get start and end cartesian coordinates
    x0, y0 = start
    x1, y1 = end

    # Incorporate the fraction of this segment covered by a dot into total reduction
    length = math.sqrt( (x1-x0)**2 + (y1-y0)**2 )
    dotSizeConversion = .0565/20 # length units per dot size
    convertedDotDiameter = dotSize * dotSizeConversion
    lengthFracReduction = convertedDotDiameter / length
    lengthFrac = lengthFrac - lengthFracReduction

    # If the line segment should not cover the entire distance, get actual start and end coords
    skipX = (x1-x0)*(1-lengthFrac)
    skipY = (y1-y0)*(1-lengthFrac)
    x0 = x0 + skipX/2
    x1 = x1 - skipX/2
    y0 = y0 + skipY/2
    y1 = y1 - skipY/2

    # Append line corresponding to the edge
    edge_x.append(x0)
    edge_x.append(x1)
    edge_x.append(None) # Prevents a line being drawn from end of this edge to start of next edge
    edge_y.append(y0)
    edge_y.append(y1)
    edge_y.append(None)

    # Draw arrow
    if not arrowPos == None:

        # Find the point of the arrow; assume is at end unless told middle
        pointx = x1
        pointy = y1

        eta = math.degrees(math.atan((x1-x0)/(y1-y0))) if y1!=y0 else 90.0

        if arrowPos == 'middle' or arrowPos == 'mid':
            pointx = x0 + (x1-x0)/2
            pointy = y0 + (y1-y0)/2

        # Find the directions the arrows are pointing
        signx = (x1-x0)/abs(x1-x0) if x1!=x0 else +1    #verify this once
        signy = (y1-y0)/abs(y1-y0) if y1!=y0 else +1    #verified

        # Append first arrowhead
        dx = arrowLength * math.sin(math.radians(eta + arrowAngle))
        dy = arrowLength * math.cos(math.radians(eta + arrowAngle))
        edge_x.append(pointx)
        edge_x.append(pointx - signx**2 * signy * dx)
        edge_x.append(None)
        edge_y.append(pointy)
        edge_y.append(pointy - signx**2 * signy * dy)
        edge_y.append(None)

        # And second arrowhead
        dx = arrowLength * math.sin(math.radians(eta - arrowAngle))
        dy = arrowLength * math.cos(math.radians(eta - arrowAngle))
        edge_x.append(pointx)
        edge_x.append(pointx - signx**2 * signy * dx)
        edge_x.append(None)
        edge_y.append(pointy)
        edge_y.append(pointy - signx**2 * signy * dy)
        edge_y.append(None)


    return edge_x, edge_y
# Packages import
import networkx as nx
import plotly.graph_objs as go
# Your input data
node_labels = {1: 'p→q', 2: '¬q', 3: '¬ (¬p)', 4: '¬p', 5: '¬p∧ ¬ (¬p)', 6: 'p', 7: 'q', 8: 'q∧ ¬q', 9: '¬p'}
color_map = {1: 'red', 2: 'red', 3: 'red', 4: 'red', 5: 'lightblue', 6: 'lightblue', 7: 'lightblue', 8: 'lightblue', 9: 'blue'}
edge_labels = {(3, 5): '∧I', (4, 5): '∧I', (4, 6): '¬E', (5, 6): '¬E', (1, 7): '→E', (6, 7): '→E', (2, 8): '∧I', (7, 8): '∧I', (8, 9): '¬E', (3, 9): '¬E'}

# General controls on the figure
NODE_SIZE = 46
LINE_WIDTH = 0.5
LINE_COLOR = '#888888'
FONT_FAMILY = 'serif'

# Create DiGraph
G=nx.DiGraph()
# Add nodes and edges
G.add_nodes_from(list(node_labels.keys()), weight=15)
G.add_edges_from(list(edge_labels.keys()))
# Create Positions
pos = nx.planar_layout(G)  # nx.random_layout(G), ...
pos[4][0] = -0.7  # <-- Changing the position of node 4 for readability
pos[9][0] = 0.9  # <-- Changing the position of node 9 for readability
for node in G.nodes:
    G.nodes[node]['pos'] = list(pos[node])

# Create Plot
# Create edges for plot and edge annotations
edge_x = []
edge_y = []
edge_label_x = []
edge_label_y = []
for edge in G.edges:
    start = G.nodes[edge[0]]['pos']
    end = G.nodes[edge[1]]['pos']
    edge_label_x.append((start[0]+end[0])/2)
    edge_label_y.append((start[1]+end[1])/2)
    edge_x, edge_y = addEdge(start, end, edge_x, edge_y, .95, 'end', .03, 20, NODE_SIZE)
# Make go.Scatter for edges
edge_trace = go.Scatter(
    x=edge_x, y=edge_y,
    mode='lines',
    line=dict(width=LINE_WIDTH, color=LINE_COLOR),
    hoverinfo='none',
)

# Create nodes for plot
node_x = []
node_y = []
node_color = []
for node in G.nodes:
    x, y = G.nodes[node]['pos']
    node_x.append(x)
    node_y.append(y)
    node_color.append(color_map[node])
# Make go.Scatter for nodes
node_trace = go.Scatter(
    x=node_x, y=node_y,
    mode='markers+text',
    hoverinfo='text',
    text=list(node_labels.values()),
    textposition="middle center",  # ['top left', 'top center', 'top right', 'middle left',
                                   # 'middle center', 'middle right', 'bottom left', 
                                   # 'bottom center', 'bottom right']
    textfont=dict(
        family=FONT_FAMILY,
        size=10,
        color="black"
    ),
    marker=dict(
        showscale=False,
        color=node_color,
        size=NODE_SIZE,
        line_width=1
    )
)
# Make edge annotations
edge_annotations = []
for label, x, y in zip(list(edge_labels.values()), edge_label_x, edge_label_y):
    edge_annotations.append(
        dict(
            x=x, y=y,
            showarrow=False,
            hovertext='none',
            ax=0,
            ay=0,
            bgcolor="white",
            opacity=0.95,
            text=label,
            font=dict(
                family=FONT_FAMILY,
                size=14,
                color="black",
            )
        )
    )

# Make go.Figure
fig = go.Figure(
    data=[edge_trace, node_trace],
    layout=go.Layout(
        paper_bgcolor='rgba(0,0,0,0)',
        plot_bgcolor='rgba(0,0,0,0)',
        title='<br>Network graph',
        titlefont_size=16,
        showlegend=False,
        hovermode='closest',
        xaxis=dict(showgrid=False, zeroline=False, showticklabels=False),
        yaxis=dict(showgrid=False, zeroline=False, showticklabels=False),
        autosize=False,
        width=700,
        height=700,
        margin=dict(l=50, r=50, b=100, t=100, pad=4),
    )
)
# Add edge annotations to go.Figure
for edge_annotation in edge_annotations:
    fig.add_annotation(edge_annotation)
# Show go.Figure
fig.show()

Resulting in:

Network graph with edge arrows

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文