I need the program to draw a graph like the one in the picture. How to make the square into four parts? How to write text on the arrows?
I tried to make a circular graph, but unfortunately it didn't work because it doesn't allow to divide the circle into four parts
I posted this as a comment in your other question, but here's an example that starts building up the network that you picture using Matplotlib's Rectangle
patch, arrow
and text
functions which you can then build up from.
import numpy as np
from matplotlib import pyplot as plt
from matplotlib.patches import Rectangle
fig, ax = plt.subplots()
def draw_2x2_grid(ax, xy, bwidth=0.25, bheight=0.25, numbers=[]):
"""
Draw a 2x2 grid of squares with numbers in each box.
"""
for i in range(2):
x = xy[0] + i * bwidth
for j in range(2):
y = xy[1] + j * bheight
r = Rectangle((x, y), bwidth, bheight, facecolor="none", edgecolor="k", lw=3)
ax.add_patch(r)
ax.text(
x + bwidth / 2,
y + bheight / 2,
str(numbers[i * 2 + j]),
va="center",
ha="center",
fontsize=20,
)
def draw_arrow(ax, xystart, xyend, textabove=None, textbelow=None, arrowkwargs={}):
"""
Draw and annotate an arrow between two points.
"""
# get displacements dx, dy
dx = xyend[0] - xystart[0]
dy = xyend[1] - xystart[1]
angle = np.rad2deg(np.arctan2(dy, dx))
ax.arrow(xystart[0], xystart[1], dx, dy, **arrowkwargs)
# add text
if textabove is not None:
ax.text(
xystart[0] + dx / 2,
xystart[1] + dy / 2,
textabove,
ha="center",
va="bottom",
transform_rotates_text=True,
rotation=angle,
rotation_mode='anchor',
fontsize=12,
)
if textbelow is not None:
ax.text(
xystart[0] + dx / 2,
xystart[1] + dy / 2,
textbelow,
ha="center",
va="top",
transform_rotates_text=True,
rotation=angle,
rotation_mode='anchor',
fontsize=12,
)
# width and height of each subbox within a 2x2 grid
bwidth = 0.3
bheight = 0.3
# bottom left x, y positions of boxes
boxpositions = [
(0, 0),
(0 + 3.5 * bwidth, 0 - 3 * bheight),
(0 + 3.5 * bwidth, 0 + 2 * bheight),
]
# numbers in boxes
boxnumbers = [
[0, 1, 0, 0],
[2, 3, 2, 0],
[1, 2, 2, 1],
]
# draw boxes
for bpos, bnum in zip(boxpositions, boxnumbers):
draw_2x2_grid(ax, bpos, bwidth=bwidth, bheight=bheight, numbers=bnum)
# draw arrows
draw_arrow(
ax,
(boxpositions[0][0] + 2 * bwidth, boxpositions[0][1] + bheight),
(boxpositions[1][0], boxpositions[1][1] + bheight),
textbelow="$t = 2$",
textabove="$a_2(0)$",
arrowkwargs={"color": "r", "head_width": 0.05, "length_includes_head": True, "lw": 2},
)
draw_arrow(
ax,
(boxpositions[0][0] + 2 * bwidth, boxpositions[0][1] + bheight),
(boxpositions[2][0], boxpositions[2][1] + bheight),
textbelow="$t = 1$",
textabove="$a_1(1)$",
arrowkwargs={"color": "k", "head_width": 0.05, "length_includes_head": True, "lw": 2},
)
ax.axis("equal")
ax.set_axis_off()
fig.show()
This is relatively complicated and there may be easier ways with NetworkX or the ETEToolkit (as suggested in the comments). Personally, I'd just make a plot like that in PowerPoint (or equivalent).