# -*- coding: utf-8 -*-
'''
一.目的
1.动态显示计算图的运行状态(点或边是否已完成)
二.步骤:
1.定义计算图
2.asyncio 并行计算
3.networkx 显示计算图
4.FuncAnimation 动态更新
三.依赖:
conda install pygraphviz
'''
import networkx as nx
import matplotlib.pyplot as plt
import asyncio
from matplotlib.animation import FuncAnimation
import asyncio
import datetime
import numpy as np
import threading
from io import BytesIO
from PIL import Image
class Node:
'''
节点信息
'''
event_man = {}
node_refs = {}
def __init__(self, name, inputs,callback) -> None:
self.name = name
self.event_man = Node.event_man
self.callback = callback
self.node_refs = Node.node_refs
self.event_man[self.name] = None
self.node_refs[self.name] = inputs
self.delay = np.random.randint(1, 5)
async def run(self):
# 等待上游节点
for ev in self.node_refs[self.name]:
await self.event_man[ev].wait()
self.callback((ev, self.name), "edge")
# 模拟耗时
await asyncio.sleep(self.delay)
# 触发下游节点
self.callback(f"{self.name}", "node")
self.event_man[self.name].set()
if __name__ == "__main__":
G = nx.DiGraph()
node_colors = {}
edge_colors = {}
semaphore = threading.Semaphore(0)
def event_callback(name, event):
print(datetime.datetime.now().strftime("%H:%M:%S.%f"), name)
# 修改节点或边的颜色
if event == "node":
node_colors[name] = "red"
elif event == "edge":
edge_colors[name] = "red"
semaphore.release()
graph_nodes = []
graph_nodes.append(Node("A", [], event_callback))
graph_nodes.append(Node("B", ["A"], event_callback))
graph_nodes.append(Node("B1", ["B"], event_callback))
graph_nodes.append(Node("B2", ["B1"], event_callback))
graph_nodes.append(Node("B3", ["B2"], event_callback))
graph_nodes.append(Node("B4", ["B2"], event_callback))
graph_nodes.append(Node("C", ["A"], event_callback))
graph_nodes.append(Node("D", ["B4", "B3", "C"], event_callback))
# 添加节点
for x in graph_nodes:
G.add_node(x.name, name=x.name, color="green")
# 添加边
for k, v in Node.node_refs.items():
for j in v:
G.add_edge(j, k, name=f"{j}->{k}", color="green")
# 设置layout
for layer, nodes in enumerate(nx.topological_generations(G)):
for node in nodes:
G.nodes[node]["layer"] = layer
#pos = nx.multipartite_layout(G, subset_key="layer")
pos = nx.nx_agraph.pygraphviz_layout(G, prog='dot') #垂直布局
node_labels = nx.get_node_attributes(G, 'name')
edge_labels = nx.get_edge_attributes(G, 'name')
node_colors = nx.get_node_attributes(G, 'color')
edge_colors = nx.get_edge_attributes(G, 'color')
async def graph_forward(nodes):
global node_colors
global edge_colors
node_colors = nx.get_node_attributes(G, 'color')
edge_colors = nx.get_edge_attributes(G, 'color')
for k in Node.event_man.keys():
Node.event_man[k] = asyncio.Event()
await asyncio.gather(*[asyncio.create_task(x.run()) for x in nodes])
fig = plt.figure(figsize=(6,12))
snapshots = []
def fig_update(data):
semaphore.acquire() #有事件触发才更新
nx.draw_networkx_labels(G, pos, labels=node_labels)
nx.draw_networkx_edge_labels(G, pos, edge_labels=edge_labels)
nx.draw_networkx(G, pos,
nodelist=node_colors.keys(),
node_color=node_colors.values(),
edgelist=edge_colors.keys(),
edge_color=edge_colors.values())
# 截图
buf = BytesIO()
plt.savefig(buf, format='png')
buf.seek(0)
pil_image = Image.open(buf)
snapshots.append(pil_image)
ani = FuncAnimation(fig, fig_update, interval=100)
def trigger(snapshots):
while True:
asyncio.run(graph_forward(graph_nodes))
# 保存gif
snapshots[1].save("out.gif",save_all=True,
append_images=snapshots[2:],
duration=500,loop=0)
print("Finished")
break
t=threading.Thread(target=trigger, args=(snapshots,))
t.setDaemon(True)
t.start()
plt.show()
相关文章
- 05-04asyncio&networkx&FuncAnimation学习--动态显示计算图的运行情况-二.代码
- 05-04嵌入式物联网实战开发笔记-乐鑫ESP32开发环境ESP-IDF搭建【doc.yotill.com】- 图 3.2.1.1 ESP32-IDF 安装包(部分截图) 上图中 ESP32-IDF v5.1.2 - Offine Installer,5.1.2 是当前最新版本,如果没有 ESP32-IDF v5.1.2 - Offine Installer,说明官方有更新最新版本。我们建议使用离线 ESP32-IDF 安装包,因为使用在线 ESP32-IDF 安装包搭建环境需要网络的支持,所以我们不能保证网络下载过程中丢失某些文件,从而导致搭建环境失败。 下载成功后,在安装程序上单击右键选择<以管理员身份运行>运行 esp-idf-tools-setup- 图 3.2.1.2 以管理员身份运行 IDF 安装文件打开安装程序后选择简体中文安装,如下图所示: 图 3.2.1.3 选择简体中文 往下走就是许可协议,勾选“我同意此协议”,单击下一步,如下图所示: 图 3.2.1.4 勾选“我同意此协议” 如果是第一次安装,会出现如下图提示。 安装程序会检查你当前系统有没有打开"长路径支持",因为 GNU 编译器产生的编译文件会有非常深的目录结构,如果不支持长路径,编译可能出现文件不存在,目录不存在等奇怪的错误。这里单击应用修复按钮,可以修复这个问题。 在弹出的确认对话框中,选择是,开始修复。 图 3.2.1.6 在注册表中启用长路径如果修复不成功,一般情况是安装软件打开时没有使用管理员权限打开,可以手动修改注册表来支持长路径:打开注册表 HKLM\SYSTEM\CurrentControlSet\Control\FileSystem\LongPat hsEnabled 设置为 1。如下图所示: 修复完成之后,点击下一步。 接下来一步,开始选择安装目录,安装程序默认的安装位置为 C:\Espressif,但这里我是安装在 D 盘,如果全部源码编译后可能产生几十 G 的大小占用,我们在 D 盘下创建 ESP32\Espre ssif 文件夹来保存 ESP32-IDF 库安装过程中生成的文件,如下图所示: 图 3.2.1.8 设置安装路径 这个安装路径非常重要,因为 VS Code 软件的 IDF 插件需要此路径来获取相关文件,所以开发者务必牢记该路径。 下一步,确认安装组件,这里全部打勾,默认完全安装时 ESP32C2 是不打勾的(如下图所示),看需要自己选择。然后单击下一步。 图 3.2.1.9 选择安装组件我们选择全部安装。点击下一步再次确认安装目录信息,然后单击安装。安装完成,三个全部勾选,2 用于测试环境安装是否成功,3 是将 IDF 工具链加入杀毒工具排除项,以加快编译速度,如下图所示: 3.2.2 验证 ESP-IDF 库 ESP-IDF 安装完成之后,系统自动打开两个窗口,它们分别为 PowerShell 命令行和传统的 cmd 命令行窗口,分别如下图所示: 从上图中可以看到,当出现红色方框内的内容时,可以初步证明安装是没有问题的,同时这两个窗口都提示“idf.py build”字符串,它是 ESP32-IDF 库提供的编译代码命令。到此,我们如何验证 ESP32-IDF 库安装是否成功呢?这里我们使用 ESP32-IDF 库提供的实例来验证安装是否成功。首先我们打开 D:\ESP32\Espressif\frameworks\esp-idf-v5.1.2\examples\get-started 路径,在此路径下包含三个 ESP32-S3 例程,如下图所示: 这里我们使用第二个例程(hello_world)来验证 ESP32-IDF 库是否安装成功,首先拷贝这里例程的路径,然后在 PowerShell 或 cmd 命令行窗口输入命令“cd D:\ESP32\Espressif\framew orks\esp-idf-v5.1.2\examples\get-started\hello_world”,最后按回车进入此例程,如下图①所示: 此时在此窗口输入命令“idf.py build”(上图②)编译此工程,编译结果如下所示: 窗口提示命令“idf.py -p (port) flash”,证明 ESP32-IDF 库安装完成。开发者也可以使用其他命令来验证,如命令(idf.py Menuconfig 进入菜单配置、idf.py set-target xxx 选择芯片或者是 idf.py monitor 开启监控等)。 3.2.3 添加 ESP32-IDF 的环境变量 按照此过程(此电脑→属性→高级系统→环境变量)打开,如下图所示: 图 3.2.3.1 添加环境变量 如果 ESP32-IDF 库安装成功,则系统自动为我们添加上图中的 IDF_TOOLS_PATH 和 IDF_PATH 环境变量,否则手动添加这两个环境变量。 3.3 搭建开发环境 3.3.1 下载与安装 VSCode 鉴于我们使用的是 VSCode IDE 搭配官方 IDF 的方式进行开发,我们接下来便介绍一下 VSCode 的安装过程。 首先,进入 VSCode 官方下载页面,根据系统需求选择下载安装包下图是 VSCode 图 3.3.1.1 VSCode 官网下载界面 这里,我们选择 Windows 版本进行下载。因为,我们是在 Windows 环境下进行的开发,故在此介绍 Windows 版本的下载步骤。不出意外,其它版本的下载方式应该也是一样的。这里我们不多废话,直接点击下载。 下载完后,我们按照如下所示步骤进行即可: 在该步骤中,路径如需更改的,请您点击“浏览”进行更改,但请注意:修改的路径最好不要出现中文,以避免在往后的开发过程中遇到问题而导致重装软件,这对您来说就得不偿失了。 如需修改,同样点击“浏览”进行设置,无需修改的话直接点击“下一步”即可。 这一步骤同样是有需求的都勾上,我们建议是都勾上。 详细的个性化设置我们便不多介绍了,在这里我们介绍如何设置中文界面。 我们在上图 3.4.8 中找到最左边一栏的“扩展”在搜索框中输入“Chinese”即可出现红色框内的扩展应用,然后我们点击安装并重启软件即可。 至此,VSCode 的安装与配置便算是大功告成了。感谢您能耐心看到此处。