python - 如何使用“另存为”提示保存来自 interactive() 显示的 .svg 输出?
问题描述
我是一名艺术家,试图使用 NumPy 和 jupyter notebook 中的各种工具来围绕生成/程序设计。
我有一些代码https://github.com/GreySoulX/Circle-generator/blob/main/BrokenCircles.ipynb(见下文),它将生成许多随机半径的同心圆并将它们输出为 SVG 代码。我可以让它显示,我什至可以用基本代码获得 SVG 输出,但是当把它全部放在一个函数中并用 interactive() 调用它时,我保存的文件是空的,而不是我的笔记本中显示的小部件.VBox() 。
我在哪里可以解决这个问题?我只是错过了一百万英里吗?
import numpy as np
import matplotlib.patches as mpatches
from matplotlib.collections import PatchCollection
import matplotlib.pyplot as plt
from IPython.display import display, Markdown, clear_output
from ipywidgets import widgets
from ipywidgets import interact, interact_manual, interactive, Button
def make_circles(n_circles=100,min_radius=0.05, max_radius=9.0, debug=False, Refresh=False ):
x_bounds = [-10, 10]
y_bounds = [-10, 10]
circles = []
for i in range(n_circles):
c = np.array([0, 0])
r = np.unique(np.sort(np.round(np.random.uniform(min_radius,max_radius,1),2)))
circles.append((c, r))
circles
circle_patches = []
for c, r in circles:
circle_patches.append(mpatches.Circle(c, r, fill=None, edgecolor='black'))
fig, ax = plt.subplots(figsize=(20, 20))
if not debug:
plt.grid(False)
plt.axis('off')
ax.set_aspect('equal')
ax.set_xlim(x_bounds)
ax.set_ylim(y_bounds)
collection = PatchCollection(circle_patches, match_original=True)
ax.add_collection(collection)
return fig, ax
w = interactive(make_circles,
n_circles=(1,300,1),
min_radius=(0.00, 2.0, 0.1),
max_radius=(2.0, 20, 0.5))
#------Button----------
button = widgets.Button(description='Save as...')
out = widgets.Output()
def on_button_clicked(_):
#link function with output
with out:
#what happens when we hit button
#clear_output()
print('Saving Files...')
plt.savefig('SomeFile.svg', bbox_inches = 'tight', pad_inches = 0)
plt.savefig('SomeFile.png', bbox_inches = 'tight', pad_inches = 0)
# linking button and function together using a button's method
button.on_click(on_button_clicked)
# displaying Circles and button
widgets.VBox([button,out,w])
#------End Button------------
解决方案
发生了什么
这是内联后端如何处理关闭数字以及plt.savefig
内部操作的问题。静态图形在笔记本中的显示方式(即不使用ipympl时)是在单元格执行结束时(或者在这种情况下,在滑块回调结束时)当前图形被关闭并显示。
但是plt.savefig
,当它在内部调用(获取当前图形)时,期望有一个当前打开的图形,它plt.gcf
要么抓取最近活动的图形,要么在没有活动图形的情况下创建一个新的空图形。
因此,当您不在函数中执行此操作时,该图在单元格完成执行之前不会关闭,因此plt.savefig
能够找到该图。但是,当您移动到函数时,它不再能够找到当前图形。
对此有两个基本的解决方案。
解决方案
1. 全球fig
您可以将 figure 提升到全局范围并使用fig.savefig
- 这可以确保绘图更新方法和保存方法都引用相同fig
。
def make_circles(n_circles=100,min_radius=0.05, max_radius=9.0, debug=False, Refresh=False ):
global fig
...
fig, ax = plt.subplots()
....
def on_button_clicked(_):
global fig
...
fig.savefig('SomeFile.svg', bbox_inches = 'tight', pad_inches = 0)
2 - 交互式后端
使用交互式后端之一,例如%matplotlib qt
或%matplotlib ipympl
。如果您在笔记本或 jupyterlab 中工作,那么我建议您使用 ipympl 安装它pip install ipympl
。
使用这些后端,图形的相同关闭不会自动发生,因此您可以像这样构建代码:
%matplotlib ipympl
fig, ax = plt.subplots()
def make_circles(n_circles=100,min_radius=0.05, max_radius=9.0, debug=False, Refresh=False ):
ax.cla() # clear all the artists off the axes
...
# use the same axes for `add_collection`
def on_button_clicked(_):
# you can now use `plt.savefig` but I would still recommend using `fig.savefig`
推荐阅读
- ruby-on-rails - 在 Gitlab-CI 上启动 postgres 服务
- javascript - 将字符串数组转换为对象 ID 数组
- java - 目标数据库大小在合并时翻倍
- javascript - 引导下拉菜单在 React 中不起作用
- php - 调用未定义的方法 Net_SSH2::put()
- c# - c# LINQ 为 tie 断路器创建查询以计算位置
- sql - ms sql server中where子句中的if else条件
- jquery - Fancybox:YouTube 未出现在灯箱中
- python - Managing and plotting data over dateline
- eigen - 特征矩阵智能指针移动构造