matplotlib & pandas

This commit is contained in:
estomm
2020-09-26 22:03:11 +08:00
parent 73cc328c81
commit d31be4f219
599 changed files with 99925 additions and 0 deletions

View File

@@ -0,0 +1,59 @@
# CanvasAgg演示
此示例展示了如何直接使用AGG后端创建图像对于希望完全控制其代码而不使用pylot界面来管理图形、图形关闭等的Web应用程序开发人员来说这可能是有用的。
**注意:**没有必要避免使用图形前端 - 只需将后端设置为“Agg”就足够了。
在这个例子中我们展示了如何将画布的内容保存到文件以及如何将它们提取到一个字符串该字符串可以传递给PIL或放在一个numpy数组中。 后一种功能允许例如使用没有文档到磁盘的cp脚本。
```python
from matplotlib.backends.backend_agg import FigureCanvasAgg
from matplotlib.figure import Figure
import numpy as np
fig = Figure(figsize=(5, 4), dpi=100)
# A canvas must be manually attached to the figure (pyplot would automatically
# do it). This is done by instantiating the canvas with the figure as
# argument.
canvas = FigureCanvasAgg(fig)
# Do some plotting.
ax = fig.add_subplot(111)
ax.plot([1, 2, 3])
# Option 1: Save the figure to a file; can also be a file-like object (BytesIO,
# etc.).
fig.savefig("test.png")
# Option 2: Save the figure to a string.
canvas.draw()
s, (width, height) = canvas.print_to_buffer()
# Option 2a: Convert to a NumPy array.
X = np.fromstring(s, np.uint8).reshape((height, width, 4))
# Option 2b: Pass off to PIL.
from PIL import Image
im = Image.frombytes("RGBA", (width, height), s)
# Uncomment this line to display the image using ImageMagick's `display` tool.
# im.show()
```
## 参考
此示例中显示了以下函数,方法,类和模块的使用:
```python
import matplotlib
matplotlib.backends.backend_agg.FigureCanvasAgg
matplotlib.figure.Figure
matplotlib.figure.Figure.add_subplot
matplotlib.figure.Figure.savefig
matplotlib.axes.Axes.plot
```
## 下载这个示例
- [下载python源码: canvasagg.py](https://matplotlib.org/_downloads/canvasagg.py)
- [下载Jupyter notebook: canvasagg.ipynb](https://matplotlib.org/_downloads/canvasagg.ipynb)

View File

@@ -0,0 +1,46 @@
# 嵌入GTK3 Panzoom
演示通过pygobject访问GTK3的NavigationToolbar。
```python
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from matplotlib.backends.backend_gtk3 import (
NavigationToolbar2GTK3 as NavigationToolbar)
from matplotlib.backends.backend_gtk3agg import (
FigureCanvasGTK3Agg as FigureCanvas)
from matplotlib.figure import Figure
import numpy as np
win = Gtk.Window()
win.connect("delete-event", Gtk.main_quit)
win.set_default_size(400, 300)
win.set_title("Embedding in GTK")
f = Figure(figsize=(5, 4), dpi=100)
a = f.add_subplot(1, 1, 1)
t = np.arange(0.0, 3.0, 0.01)
s = np.sin(2*np.pi*t)
a.plot(t, s)
vbox = Gtk.VBox()
win.add(vbox)
# Add canvas to vbox
canvas = FigureCanvas(f) # a Gtk.DrawingArea
vbox.pack_start(canvas, True, True, 0)
# Create toolbar
toolbar = NavigationToolbar(canvas, win)
vbox.pack_start(toolbar, False, False, 0)
win.show_all()
Gtk.main()
```
## 下载这个示例
- [下载python源码: embedding_in_gtk3_panzoom_sgskip.py](https://matplotlib.org/_downloads/embedding_in_gtk3_panzoom_sgskip.py)
- [下载Jupyter notebook: embedding_in_gtk3_panzoom_sgskip.ipynb](https://matplotlib.org/_downloads/embedding_in_gtk3_panzoom_sgskip.ipynb)

View File

@@ -0,0 +1,42 @@
# 嵌入GTK3
演示使用通过pygobject访问的GTK3将FigureCanvasGTK3Agg小部件添加到Gtk.ScrolledWindow。
```python
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from matplotlib.backends.backend_gtk3agg import (
FigureCanvasGTK3Agg as FigureCanvas)
from matplotlib.figure import Figure
import numpy as np
win = Gtk.Window()
win.connect("delete-event", Gtk.main_quit)
win.set_default_size(400, 300)
win.set_title("Embedding in GTK")
f = Figure(figsize=(5, 4), dpi=100)
a = f.add_subplot(111)
t = np.arange(0.0, 3.0, 0.01)
s = np.sin(2*np.pi*t)
a.plot(t, s)
sw = Gtk.ScrolledWindow()
win.add(sw)
# A scrolled window border goes outside the scrollbars and viewport
sw.set_border_width(10)
canvas = FigureCanvas(f) # a Gtk.DrawingArea
canvas.set_size_request(800, 600)
sw.add_with_viewport(canvas)
win.show_all()
Gtk.main()
```
## 下载这个示例
- [下载python源码: embedding_in_gtk3_sgskip.py](https://matplotlib.org/_downloads/embedding_in_gtk3_sgskip.py)
- [下载Jupyter notebook: embedding_in_gtk3_sgskip.ipynb](https://matplotlib.org/_downloads/embedding_in_gtk3_sgskip.ipynb)

View File

@@ -0,0 +1,64 @@
# 嵌入Qt
简单的Qt应用程序嵌入Matplotlib画布。 该程序将使用Qt4和Qt5很好地工作。 通过将MPLBACKEND环境变量设置为“Qt4Agg”或“Qt5Agg”或者首先导入所需的PyQt版本可以选择任一版本的Qt例如
```python
import sys
import time
import numpy as np
from matplotlib.backends.qt_compat import QtCore, QtWidgets, is_pyqt5
if is_pyqt5():
from matplotlib.backends.backend_qt5agg import (
FigureCanvas, NavigationToolbar2QT as NavigationToolbar)
else:
from matplotlib.backends.backend_qt4agg import (
FigureCanvas, NavigationToolbar2QT as NavigationToolbar)
from matplotlib.figure import Figure
class ApplicationWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self._main = QtWidgets.QWidget()
self.setCentralWidget(self._main)
layout = QtWidgets.QVBoxLayout(self._main)
static_canvas = FigureCanvas(Figure(figsize=(5, 3)))
layout.addWidget(static_canvas)
self.addToolBar(NavigationToolbar(static_canvas, self))
dynamic_canvas = FigureCanvas(Figure(figsize=(5, 3)))
layout.addWidget(dynamic_canvas)
self.addToolBar(QtCore.Qt.BottomToolBarArea,
NavigationToolbar(dynamic_canvas, self))
self._static_ax = static_canvas.figure.subplots()
t = np.linspace(0, 10, 501)
self._static_ax.plot(t, np.tan(t), ".")
self._dynamic_ax = dynamic_canvas.figure.subplots()
self._timer = dynamic_canvas.new_timer(
100, [(self._update_canvas, (), {})])
self._timer.start()
def _update_canvas(self):
self._dynamic_ax.clear()
t = np.linspace(0, 10, 101)
# Shift the sinusoid as a function of time.
self._dynamic_ax.plot(t, np.sin(t + time.time()))
self._dynamic_ax.figure.canvas.draw()
if __name__ == "__main__":
qapp = QtWidgets.QApplication(sys.argv)
app = ApplicationWindow()
app.show()
qapp.exec_()
```
## 下载这个示例
- [下载python源码: embedding_in_qt_sgskip.py](https://matplotlib.org/_downloads/embedding_in_qt_sgskip.py)
- [下载Jupyter notebook: embedding_in_qt_sgskip.ipynb](https://matplotlib.org/_downloads/embedding_in_qt_sgskip.ipynb)

View File

@@ -0,0 +1,56 @@
# 嵌入Tk
```python
import tkinter
from matplotlib.backends.backend_tkagg import (
FigureCanvasTkAgg, NavigationToolbar2Tk)
# Implement the default Matplotlib key bindings.
from matplotlib.backend_bases import key_press_handler
from matplotlib.figure import Figure
import numpy as np
root = tkinter.Tk()
root.wm_title("Embedding in Tk")
fig = Figure(figsize=(5, 4), dpi=100)
t = np.arange(0, 3, .01)
fig.add_subplot(111).plot(t, 2 * np.sin(2 * np.pi * t))
canvas = FigureCanvasTkAgg(fig, master=root) # A tk.DrawingArea.
canvas.draw()
canvas.get_tk_widget().pack(side=tkinter.TOP, fill=tkinter.BOTH, expand=1)
toolbar = NavigationToolbar2Tk(canvas, root)
toolbar.update()
canvas.get_tk_widget().pack(side=tkinter.TOP, fill=tkinter.BOTH, expand=1)
def on_key_press(event):
print("you pressed {}".format(event.key))
key_press_handler(event, canvas, toolbar)
canvas.mpl_connect("key_press_event", on_key_press)
def _quit():
root.quit() # stops mainloop
root.destroy() # this is necessary on Windows to prevent
# Fatal Python Error: PyEval_RestoreThread: NULL tstate
button = tkinter.Button(master=root, text="Quit", command=_quit)
button.pack(side=tkinter.BOTTOM)
tkinter.mainloop()
# If you put root.destroy() here, it will cause an error if the window is
# closed with the window manager.
```
## 下载这个示例
- [下载python源码: embedding_in_tk_sgskip.py](https://matplotlib.org/_downloads/embedding_in_tk_sgskip.py)
- [下载Jupyter notebook: embedding_in_tk_sgskip.ipynb](https://matplotlib.org/_downloads/embedding_in_tk_sgskip.ipynb)

View File

@@ -0,0 +1,64 @@
# 嵌入Wx2
如何在具有新工具栏的应用程序中使用wxagg的示例
```python
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.backends.backend_wx import NavigationToolbar2Wx as NavigationToolbar
from matplotlib.figure import Figure
import numpy as np
import wx
import wx.lib.mixins.inspection as WIT
class CanvasFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1,
'CanvasFrame', size=(550, 350))
self.figure = Figure()
self.axes = self.figure.add_subplot(111)
t = np.arange(0.0, 3.0, 0.01)
s = np.sin(2 * np.pi * t)
self.axes.plot(t, s)
self.canvas = FigureCanvas(self, -1, self.figure)
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.EXPAND)
self.SetSizer(self.sizer)
self.Fit()
self.add_toolbar() # comment this out for no toolbar
def add_toolbar(self):
self.toolbar = NavigationToolbar(self.canvas)
self.toolbar.Realize()
# By adding toolbar in sizer, we are able to put it at the bottom
# of the frame - so appearance is closer to GTK version.
self.sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND)
# update the axes menu on the toolbar
self.toolbar.update()
# alternatively you could use
#class App(wx.App):
class App(WIT.InspectableApp):
def OnInit(self):
'Create the main window and insert the custom frame'
self.Init()
frame = CanvasFrame()
frame.Show(True)
return True
app = App(0)
app.MainLoop()
```
## 下载这个示例
- [下载python源码: embedding_in_wx2_sgskip.py](https://matplotlib.org/_downloads/embedding_in_wx2_sgskip.py)
- [下载Jupyter notebook: embedding_in_wx2_sgskip.ipynb](https://matplotlib.org/_downloads/embedding_in_wx2_sgskip.ipynb)

View File

@@ -0,0 +1,149 @@
# 嵌入Wx3
版权所有C2003-2004 Andrew Straw和Jeremy O'Donoghue等人
许可证此作品根据PSF许可。该文档也应该在 https://docs.python.org/3/license.html 上提供
这是使用matplotlib和wx的另一个例子。 希望这是功能齐全的:
- matplotlib工具栏和WX按钮
- 完整的wxApp框架包括小部件交互
- XRCXML wxWidgets资源文件创建GUI用XRCed制作
这是从embedding_in_wx和dynamic_image_wxagg派生的。
感谢matplotlib和wx团队创建这样出色的软件
```python
import matplotlib
import matplotlib.cm as cm
import matplotlib.cbook as cbook
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.backends.backend_wxagg import NavigationToolbar2WxAgg as NavigationToolbar
from matplotlib.figure import Figure
import numpy as np
import wx
import wx.xrc as xrc
ERR_TOL = 1e-5 # floating point slop for peak-detection
matplotlib.rc('image', origin='lower')
class PlotPanel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent, -1)
self.fig = Figure((5, 4), 75)
self.canvas = FigureCanvas(self, -1, self.fig)
self.toolbar = NavigationToolbar(self.canvas) # matplotlib toolbar
self.toolbar.Realize()
# self.toolbar.set_active([0,1])
# Now put all into a sizer
sizer = wx.BoxSizer(wx.VERTICAL)
# This way of adding to sizer allows resizing
sizer.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW)
# Best to allow the toolbar to resize!
sizer.Add(self.toolbar, 0, wx.GROW)
self.SetSizer(sizer)
self.Fit()
def init_plot_data(self):
a = self.fig.add_subplot(111)
x = np.arange(120.0) * 2 * np.pi / 60.0
y = np.arange(100.0) * 2 * np.pi / 50.0
self.x, self.y = np.meshgrid(x, y)
z = np.sin(self.x) + np.cos(self.y)
self.im = a.imshow(z, cmap=cm.RdBu) # , interpolation='nearest')
zmax = np.max(z) - ERR_TOL
ymax_i, xmax_i = np.nonzero(z >= zmax)
if self.im.origin == 'upper':
ymax_i = z.shape[0] - ymax_i
self.lines = a.plot(xmax_i, ymax_i, 'ko')
self.toolbar.update() # Not sure why this is needed - ADS
def GetToolBar(self):
# You will need to override GetToolBar if you are using an
# unmanaged toolbar in your frame
return self.toolbar
def OnWhiz(self, evt):
self.x += np.pi / 15
self.y += np.pi / 20
z = np.sin(self.x) + np.cos(self.y)
self.im.set_array(z)
zmax = np.max(z) - ERR_TOL
ymax_i, xmax_i = np.nonzero(z >= zmax)
if self.im.origin == 'upper':
ymax_i = z.shape[0] - ymax_i
self.lines[0].set_data(xmax_i, ymax_i)
self.canvas.draw()
class MyApp(wx.App):
def OnInit(self):
xrcfile = cbook.get_sample_data('embedding_in_wx3.xrc',
asfileobj=False)
print('loading', xrcfile)
self.res = xrc.XmlResource(xrcfile)
# main frame and panel ---------
self.frame = self.res.LoadFrame(None, "MainFrame")
self.panel = xrc.XRCCTRL(self.frame, "MainPanel")
# matplotlib panel -------------
# container for matplotlib panel (I like to make a container
# panel for our panel so I know where it'll go when in XRCed.)
plot_container = xrc.XRCCTRL(self.frame, "plot_container_panel")
sizer = wx.BoxSizer(wx.VERTICAL)
# matplotlib panel itself
self.plotpanel = PlotPanel(plot_container)
self.plotpanel.init_plot_data()
# wx boilerplate
sizer.Add(self.plotpanel, 1, wx.EXPAND)
plot_container.SetSizer(sizer)
# whiz button ------------------
whiz_button = xrc.XRCCTRL(self.frame, "whiz_button")
whiz_button.Bind(wx.EVT_BUTTON, self.plotpanel.OnWhiz)
# bang button ------------------
bang_button = xrc.XRCCTRL(self.frame, "bang_button")
bang_button.Bind(wx.EVT_BUTTON, self.OnBang)
# final setup ------------------
sizer = self.panel.GetSizer()
self.frame.Show(1)
self.SetTopWindow(self.frame)
return True
def OnBang(self, event):
bang_count = xrc.XRCCTRL(self.frame, "bang_count")
bangs = bang_count.GetValue()
bangs = int(bangs) + 1
bang_count.SetValue(str(bangs))
if __name__ == '__main__':
app = MyApp(0)
app.MainLoop()
```
## 下载这个示例
- [下载python源码: embedding_in_wx3_sgskip.py](https://matplotlib.org/_downloads/embedding_in_wx3_sgskip.py)
- [下载Jupyter notebook: embedding_in_wx3_sgskip.ipynb](https://matplotlib.org/_downloads/embedding_in_wx3_sgskip.ipynb)

View File

@@ -0,0 +1,95 @@
# 嵌入Wx4
如何在具有自定义工具栏的应用程序中使用wxagg的示例。
```python
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.backends.backend_wxagg import NavigationToolbar2WxAgg as NavigationToolbar
from matplotlib.backends.backend_wx import _load_bitmap
from matplotlib.figure import Figure
import numpy as np
import wx
class MyNavigationToolbar(NavigationToolbar):
"""
Extend the default wx toolbar with your own event handlers
"""
ON_CUSTOM = wx.NewId()
def __init__(self, canvas, cankill):
NavigationToolbar.__init__(self, canvas)
# for simplicity I'm going to reuse a bitmap from wx, you'll
# probably want to add your own.
self.AddTool(self.ON_CUSTOM, 'Click me', _load_bitmap('back.png'),
'Activate custom contol')
self.Bind(wx.EVT_TOOL, self._on_custom, id=self.ON_CUSTOM)
def _on_custom(self, evt):
# add some text to the axes in a random location in axes (0,1)
# coords) with a random color
# get the axes
ax = self.canvas.figure.axes[0]
# generate a random location can color
x, y = np.random.rand(2)
rgb = np.random.rand(3)
# add the text and draw
ax.text(x, y, 'You clicked me',
transform=ax.transAxes,
color=rgb)
self.canvas.draw()
evt.Skip()
class CanvasFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1,
'CanvasFrame', size=(550, 350))
self.figure = Figure(figsize=(5, 4), dpi=100)
self.axes = self.figure.add_subplot(111)
t = np.arange(0.0, 3.0, 0.01)
s = np.sin(2 * np.pi * t)
self.axes.plot(t, s)
self.canvas = FigureCanvas(self, -1, self.figure)
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self.canvas, 1, wx.TOP | wx.LEFT | wx.EXPAND)
self.toolbar = MyNavigationToolbar(self.canvas, True)
self.toolbar.Realize()
# By adding toolbar in sizer, we are able to put it at the bottom
# of the frame - so appearance is closer to GTK version.
self.sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND)
# update the axes menu on the toolbar
self.toolbar.update()
self.SetSizer(self.sizer)
self.Fit()
class App(wx.App):
def OnInit(self):
'Create the main window and insert the custom frame'
frame = CanvasFrame()
frame.Show(True)
return True
app = App(0)
app.MainLoop()
```
## 下载这个示例
- [下载python源码: embedding_in_wx4_sgskip.py](https://matplotlib.org/_downloads/embedding_in_wx4_sgskip.py)
- [下载Jupyter notebook: embedding_in_wx4_sgskip.ipynb](https://matplotlib.org/_downloads/embedding_in_wx4_sgskip.ipynb)

View File

@@ -0,0 +1,63 @@
# 嵌入Wx5
```python
import wx
import wx.lib.agw.aui as aui
import wx.lib.mixins.inspection as wit
import matplotlib as mpl
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.backends.backend_wxagg import NavigationToolbar2WxAgg as NavigationToolbar
class Plot(wx.Panel):
def __init__(self, parent, id=-1, dpi=None, **kwargs):
wx.Panel.__init__(self, parent, id=id, **kwargs)
self.figure = mpl.figure.Figure(dpi=dpi, figsize=(2, 2))
self.canvas = FigureCanvas(self, -1, self.figure)
self.toolbar = NavigationToolbar(self.canvas)
self.toolbar.Realize()
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.canvas, 1, wx.EXPAND)
sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND)
self.SetSizer(sizer)
class PlotNotebook(wx.Panel):
def __init__(self, parent, id=-1):
wx.Panel.__init__(self, parent, id=id)
self.nb = aui.AuiNotebook(self)
sizer = wx.BoxSizer()
sizer.Add(self.nb, 1, wx.EXPAND)
self.SetSizer(sizer)
def add(self, name="plot"):
page = Plot(self.nb)
self.nb.AddPage(page, name)
return page.figure
def demo():
# alternatively you could use
#app = wx.App()
# InspectableApp is a great debug tool, see:
# http://wiki.wxpython.org/Widget%20Inspection%20Tool
app = wit.InspectableApp()
frame = wx.Frame(None, -1, 'Plotter')
plotter = PlotNotebook(frame)
axes1 = plotter.add('figure 1').gca()
axes1.plot([1, 2, 3], [2, 1, 4])
axes2 = plotter.add('figure 2').gca()
axes2.plot([1, 2, 3, 4, 5], [2, 1, 4, 2, 3])
frame.Show()
app.MainLoop()
if __name__ == "__main__":
demo()
```
## 下载这个示例
- [下载python源码: embedding_in_wx5_sgskip.py](https://matplotlib.org/_downloads/embedding_in_wx5_sgskip.py)
- [下载Jupyter notebook: embedding_in_wx5_sgskip.ipynb](https://matplotlib.org/_downloads/embedding_in_wx5_sgskip.ipynb)

View File

@@ -0,0 +1,249 @@
# 嵌入WebAgg
此示例演示如何在您自己的Web应用程序和框架中嵌入matplotlib WebAgg交互式绘图。
基于龙卷风的服务器“侧面”是基于龙卷风的服务器。
使用的框架必须支持Web套接字。
``` python
import io
try:
import tornado
except ImportError:
raise RuntimeError("This example requires tornado.")
import tornado.web
import tornado.httpserver
import tornado.ioloop
import tornado.websocket
from matplotlib.backends.backend_webagg_core import (
FigureManagerWebAgg, new_figure_manager_given_figure)
from matplotlib.figure import Figure
import numpy as np
import json
def create_figure():
"""
Creates a simple example figure.
"""
fig = Figure()
a = fig.add_subplot(111)
t = np.arange(0.0, 3.0, 0.01)
s = np.sin(2 * np.pi * t)
a.plot(t, s)
return fig
# The following is the content of the web page. You would normally
# generate this using some sort of template facility in your web
# framework, but here we just use Python string formatting.
html_content = """
<html>
<head>
<!-- TODO: There should be a way to include all of the required javascript
and CSS so matplotlib can add to the set in the future if it
needs to. -->
<link rel="stylesheet" href="_static/css/page.css" type="text/css">
<link rel="stylesheet" href="_static/css/boilerplate.css" type="text/css" />
<link rel="stylesheet" href="_static/css/fbm.css" type="text/css" />
<link rel="stylesheet" href="_static/jquery/css/themes/base/jquery-ui.min.css" >
<script src="_static/jquery/js/jquery-1.11.3.min.js"></script>
<script src="_static/jquery/js/jquery-ui.min.js"></script>
<script src="mpl.js"></script>
<script>
/* This is a callback that is called when the user saves
(downloads) a file. Its purpose is really to map from a
figure and file format to a url in the application. */
function ondownload(figure, format) {
window.open('download.' + format, '_blank');
};
$(document).ready(
function() {
/* It is up to the application to provide a websocket that the figure
will use to communicate to the server. This websocket object can
also be a "fake" websocket that underneath multiplexes messages
from multiple figures, if necessary. */
var websocket_type = mpl.get_websocket_type();
var websocket = new websocket_type("%(ws_uri)sws");
// mpl.figure creates a new figure on the webpage.
var fig = new mpl.figure(
// A unique numeric identifier for the figure
%(fig_id)s,
// A websocket object (or something that behaves like one)
websocket,
// A function called when a file type is selected for download
ondownload,
// The HTML element in which to place the figure
$('div#figure'));
}
);
</script>
<title>matplotlib</title>
</head>
<body>
<div id="figure">
</div>
</body>
</html>
"""
class MyApplication(tornado.web.Application):
class MainPage(tornado.web.RequestHandler):
"""
Serves the main HTML page.
"""
def get(self):
manager = self.application.manager
ws_uri = "ws://{req.host}/".format(req=self.request)
content = html_content % {
"ws_uri": ws_uri, "fig_id": manager.num}
self.write(content)
class MplJs(tornado.web.RequestHandler):
"""
Serves the generated matplotlib javascript file. The content
is dynamically generated based on which toolbar functions the
user has defined. Call `FigureManagerWebAgg` to get its
content.
"""
def get(self):
self.set_header('Content-Type', 'application/javascript')
js_content = FigureManagerWebAgg.get_javascript()
self.write(js_content)
class Download(tornado.web.RequestHandler):
"""
Handles downloading of the figure in various file formats.
"""
def get(self, fmt):
manager = self.application.manager
mimetypes = {
'ps': 'application/postscript',
'eps': 'application/postscript',
'pdf': 'application/pdf',
'svg': 'image/svg+xml',
'png': 'image/png',
'jpeg': 'image/jpeg',
'tif': 'image/tiff',
'emf': 'application/emf'
}
self.set_header('Content-Type', mimetypes.get(fmt, 'binary'))
buff = io.BytesIO()
manager.canvas.figure.savefig(buff, format=fmt)
self.write(buff.getvalue())
class WebSocket(tornado.websocket.WebSocketHandler):
"""
A websocket for interactive communication between the plot in
the browser and the server.
In addition to the methods required by tornado, it is required to
have two callback methods:
- ``send_json(json_content)`` is called by matplotlib when
it needs to send json to the browser. `json_content` is
a JSON tree (Python dictionary), and it is the responsibility
of this implementation to encode it as a string to send over
the socket.
- ``send_binary(blob)`` is called to send binary image data
to the browser.
"""
supports_binary = True
def open(self):
# Register the websocket with the FigureManager.
manager = self.application.manager
manager.add_web_socket(self)
if hasattr(self, 'set_nodelay'):
self.set_nodelay(True)
def on_close(self):
# When the socket is closed, deregister the websocket with
# the FigureManager.
manager = self.application.manager
manager.remove_web_socket(self)
def on_message(self, message):
# The 'supports_binary' message is relevant to the
# websocket itself. The other messages get passed along
# to matplotlib as-is.
# Every message has a "type" and a "figure_id".
message = json.loads(message)
if message['type'] == 'supports_binary':
self.supports_binary = message['value']
else:
manager = self.application.manager
manager.handle_json(message)
def send_json(self, content):
self.write_message(json.dumps(content))
def send_binary(self, blob):
if self.supports_binary:
self.write_message(blob, binary=True)
else:
data_uri = "data:image/png;base64,{0}".format(
blob.encode('base64').replace('\n', ''))
self.write_message(data_uri)
def __init__(self, figure):
self.figure = figure
self.manager = new_figure_manager_given_figure(id(figure), figure)
super().__init__([
# Static files for the CSS and JS
(r'/_static/(.*)',
tornado.web.StaticFileHandler,
{'path': FigureManagerWebAgg.get_static_file_path()}),
# The page that contains all of the pieces
('/', self.MainPage),
('/mpl.js', self.MplJs),
# Sends images and events to the browser, and receives
# events from the browser
('/ws', self.WebSocket),
# Handles the downloading (i.e., saving) of static images
(r'/download.([a-z0-9.]+)', self.Download),
])
if __name__ == "__main__":
figure = create_figure()
application = MyApplication(figure)
http_server = tornado.httpserver.HTTPServer(application)
http_server.listen(8080)
print("http://127.0.0.1:8080/")
print("Press Ctrl+C to quit")
tornado.ioloop.IOLoop.instance().start()
```
## 下载这个示例
- [下载python源码: embedding_webagg_sgskip.py](https://matplotlib.org/_downloads/embedding_webagg_sgskip.py)
- [下载Jupyter notebook: embedding_webagg_sgskip.ipynb](https://matplotlib.org/_downloads/embedding_webagg_sgskip.ipynb)

View File

@@ -0,0 +1,237 @@
# 傅立叶演示WX
```python
import numpy as np
import wx
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.figure import Figure
class Knob(object):
"""
Knob - simple class with a "setKnob" method.
A Knob instance is attached to a Param instance, e.g., param.attach(knob)
Base class is for documentation purposes.
"""
def setKnob(self, value):
pass
class Param(object):
"""
The idea of the "Param" class is that some parameter in the GUI may have
several knobs that both control it and reflect the parameter's state, e.g.
a slider, text, and dragging can all change the value of the frequency in
the waveform of this example.
The class allows a cleaner way to update/"feedback" to the other knobs when
one is being changed. Also, this class handles min/max constraints for all
the knobs.
Idea - knob list - in "set" method, knob object is passed as well
- the other knobs in the knob list have a "set" method which gets
called for the others.
"""
def __init__(self, initialValue=None, minimum=0., maximum=1.):
self.minimum = minimum
self.maximum = maximum
if initialValue != self.constrain(initialValue):
raise ValueError('illegal initial value')
self.value = initialValue
self.knobs = []
def attach(self, knob):
self.knobs += [knob]
def set(self, value, knob=None):
self.value = value
self.value = self.constrain(value)
for feedbackKnob in self.knobs:
if feedbackKnob != knob:
feedbackKnob.setKnob(self.value)
return self.value
def constrain(self, value):
if value <= self.minimum:
value = self.minimum
if value >= self.maximum:
value = self.maximum
return value
class SliderGroup(Knob):
def __init__(self, parent, label, param):
self.sliderLabel = wx.StaticText(parent, label=label)
self.sliderText = wx.TextCtrl(parent, -1, style=wx.TE_PROCESS_ENTER)
self.slider = wx.Slider(parent, -1)
# self.slider.SetMax(param.maximum*1000)
self.slider.SetRange(0, param.maximum * 1000)
self.setKnob(param.value)
sizer = wx.BoxSizer(wx.HORIZONTAL)
sizer.Add(self.sliderLabel, 0,
wx.EXPAND | wx.ALIGN_CENTER | wx.ALL,
border=2)
sizer.Add(self.sliderText, 0,
wx.EXPAND | wx.ALIGN_CENTER | wx.ALL,
border=2)
sizer.Add(self.slider, 1, wx.EXPAND)
self.sizer = sizer
self.slider.Bind(wx.EVT_SLIDER, self.sliderHandler)
self.sliderText.Bind(wx.EVT_TEXT_ENTER, self.sliderTextHandler)
self.param = param
self.param.attach(self)
def sliderHandler(self, evt):
value = evt.GetInt() / 1000.
self.param.set(value)
def sliderTextHandler(self, evt):
value = float(self.sliderText.GetValue())
self.param.set(value)
def setKnob(self, value):
self.sliderText.SetValue('%g' % value)
self.slider.SetValue(value * 1000)
class FourierDemoFrame(wx.Frame):
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
panel = wx.Panel(self)
# create the GUI elements
self.createCanvas(panel)
self.createSliders(panel)
# place them in a sizer for the Layout
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.canvas, 1, wx.EXPAND)
sizer.Add(self.frequencySliderGroup.sizer, 0,
wx.EXPAND | wx.ALIGN_CENTER | wx.ALL, border=5)
sizer.Add(self.amplitudeSliderGroup.sizer, 0,
wx.EXPAND | wx.ALIGN_CENTER | wx.ALL, border=5)
panel.SetSizer(sizer)
def createCanvas(self, parent):
self.lines = []
self.figure = Figure()
self.canvas = FigureCanvas(parent, -1, self.figure)
self.canvas.callbacks.connect('button_press_event', self.mouseDown)
self.canvas.callbacks.connect('motion_notify_event', self.mouseMotion)
self.canvas.callbacks.connect('button_release_event', self.mouseUp)
self.state = ''
self.mouseInfo = (None, None, None, None)
self.f0 = Param(2., minimum=0., maximum=6.)
self.A = Param(1., minimum=0.01, maximum=2.)
self.createPlots()
# Not sure I like having two params attached to the same Knob,
# but that is what we have here... it works but feels kludgy -
# although maybe it's not too bad since the knob changes both params
# at the same time (both f0 and A are affected during a drag)
self.f0.attach(self)
self.A.attach(self)
def createSliders(self, panel):
self.frequencySliderGroup = SliderGroup(
panel,
label='Frequency f0:',
param=self.f0)
self.amplitudeSliderGroup = SliderGroup(panel, label=' Amplitude a:',
param=self.A)
def mouseDown(self, evt):
if self.lines[0].contains(evt)[0]:
self.state = 'frequency'
elif self.lines[1].contains(evt)[0]:
self.state = 'time'
else:
self.state = ''
self.mouseInfo = (evt.xdata, evt.ydata,
max(self.f0.value, .1),
self.A.value)
def mouseMotion(self, evt):
if self.state == '':
return
x, y = evt.xdata, evt.ydata
if x is None: # outside the axes
return
x0, y0, f0Init, AInit = self.mouseInfo
self.A.set(AInit + (AInit * (y - y0) / y0), self)
if self.state == 'frequency':
self.f0.set(f0Init + (f0Init * (x - x0) / x0))
elif self.state == 'time':
if (x - x0) / x0 != -1.:
self.f0.set(1. / (1. / f0Init + (1. / f0Init * (x - x0) / x0)))
def mouseUp(self, evt):
self.state = ''
def createPlots(self):
# This method creates the subplots, waveforms and labels.
# Later, when the waveforms or sliders are dragged, only the
# waveform data will be updated (not here, but below in setKnob).
self.subplot1, self.subplot2 = self.figure.subplots(2)
x1, y1, x2, y2 = self.compute(self.f0.value, self.A.value)
color = (1., 0., 0.)
self.lines += self.subplot1.plot(x1, y1, color=color, linewidth=2)
self.lines += self.subplot2.plot(x2, y2, color=color, linewidth=2)
# Set some plot attributes
self.subplot1.set_title(
"Click and drag waveforms to change frequency and amplitude",
fontsize=12)
self.subplot1.set_ylabel("Frequency Domain Waveform X(f)", fontsize=8)
self.subplot1.set_xlabel("frequency f", fontsize=8)
self.subplot2.set_ylabel("Time Domain Waveform x(t)", fontsize=8)
self.subplot2.set_xlabel("time t", fontsize=8)
self.subplot1.set_xlim([-6, 6])
self.subplot1.set_ylim([0, 1])
self.subplot2.set_xlim([-2, 2])
self.subplot2.set_ylim([-2, 2])
self.subplot1.text(0.05, .95,
r'$X(f) = \mathcal{F}\{x(t)\}$',
verticalalignment='top',
transform=self.subplot1.transAxes)
self.subplot2.text(0.05, .95,
r'$x(t) = a \cdot \cos(2\pi f_0 t) e^{-\pi t^2}$',
verticalalignment='top',
transform=self.subplot2.transAxes)
def compute(self, f0, A):
f = np.arange(-6., 6., 0.02)
t = np.arange(-2., 2., 0.01)
x = A * np.cos(2 * np.pi * f0 * t) * np.exp(-np.pi * t ** 2)
X = A / 2 * \
(np.exp(-np.pi * (f - f0) ** 2) + np.exp(-np.pi * (f + f0) ** 2))
return f, X, t, x
def setKnob(self, value):
# Note, we ignore value arg here and just go by state of the params
x1, y1, x2, y2 = self.compute(self.f0.value, self.A.value)
# update the data of the two waveforms
self.lines[0].set(xdata=x1, ydata=y1)
self.lines[1].set(xdata=x2, ydata=y2)
# make the canvas draw its contents again with the new data
self.canvas.draw()
class App(wx.App):
def OnInit(self):
self.frame1 = FourierDemoFrame(parent=None, title="Fourier Demo",
size=(640, 480))
self.frame1.Show()
return True
app = App()
app.MainLoop()
```
## 下载这个示例
- [下载python源码: fourier_demo_wx_sgskip.py](https://matplotlib.org/_downloads/fourier_demo_wx_sgskip.py)
- [下载Jupyter notebook: fourier_demo_wx_sgskip.ipynb](https://matplotlib.org/_downloads/fourier_demo_wx_sgskip.ipynb)

View File

@@ -0,0 +1,94 @@
# GTK电子表格
在应用程序中嵌入matplotlib并与treeview交互以存储数据的示例。双击条目以更新绘图数据。
```python
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('Gdk', '3.0')
from gi.repository import Gtk, Gdk
from matplotlib.backends.backend_gtk3agg import FigureCanvas
# from matplotlib.backends.backend_gtk3cairo import FigureCanvas
from numpy.random import random
from matplotlib.figure import Figure
class DataManager(Gtk.Window):
numRows, numCols = 20, 10
data = random((numRows, numCols))
def __init__(self):
Gtk.Window.__init__(self)
self.set_default_size(600, 600)
self.connect('destroy', lambda win: Gtk.main_quit())
self.set_title('GtkListStore demo')
self.set_border_width(8)
vbox = Gtk.VBox(False, 8)
self.add(vbox)
label = Gtk.Label('Double click a row to plot the data')
vbox.pack_start(label, False, False, 0)
sw = Gtk.ScrolledWindow()
sw.set_shadow_type(Gtk.ShadowType.ETCHED_IN)
sw.set_policy(Gtk.PolicyType.NEVER,
Gtk.PolicyType.AUTOMATIC)
vbox.pack_start(sw, True, True, 0)
model = self.create_model()
self.treeview = Gtk.TreeView(model)
self.treeview.set_rules_hint(True)
# matplotlib stuff
fig = Figure(figsize=(6, 4))
self.canvas = FigureCanvas(fig) # a Gtk.DrawingArea
vbox.pack_start(self.canvas, True, True, 0)
ax = fig.add_subplot(111)
self.line, = ax.plot(self.data[0, :], 'go') # plot the first row
self.treeview.connect('row-activated', self.plot_row)
sw.add(self.treeview)
self.add_columns()
self.add_events(Gdk.EventMask.BUTTON_PRESS_MASK |
Gdk.EventMask.KEY_PRESS_MASK |
Gdk.EventMask.KEY_RELEASE_MASK)
def plot_row(self, treeview, path, view_column):
ind, = path # get the index into data
points = self.data[ind, :]
self.line.set_ydata(points)
self.canvas.draw()
def add_columns(self):
for i in range(self.numCols):
column = Gtk.TreeViewColumn(str(i), Gtk.CellRendererText(), text=i)
self.treeview.append_column(column)
def create_model(self):
types = [float]*self.numCols
store = Gtk.ListStore(*types)
for row in self.data:
store.append(tuple(row))
return store
manager = DataManager()
manager.show_all()
Gtk.main()
```
## 下载这个示例
- [下载python源码: gtk_spreadsheet_sgskip.py](https://matplotlib.org/_downloads/gtk_spreadsheet_sgskip.py)
- [下载Jupyter notebook: gtk_spreadsheet_sgskip.ipynb](https://matplotlib.org/_downloads/gtk_spreadsheet_sgskip.ipynb)

View File

@@ -0,0 +1,5 @@
# 将Matplotlib嵌入图形用户界面中
您可以通过此处的embedding_in_SOMEGUI.py示例将Matplotlib直接嵌入到用户界面中。 目前matplotlib支持wxpythonpygtktkinter 和 pyqt4 / 5。
在将Matplotlib嵌入GUI时您应该直接使用Matplotlib API而不是pylab / pyplot的继续接口因此请查看examples / api目录了解使用API的一些示例代码。

View File

@@ -0,0 +1,133 @@
# WX中的数学文本
演示如何将数学文本转换为wx.Bitmap以便在wxPython的各种控件中显示。
```python
import matplotlib
matplotlib.use("WxAgg")
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.backends.backend_wx import NavigationToolbar2Wx
from matplotlib.figure import Figure
import numpy as np
import wx
IS_GTK = 'wxGTK' in wx.PlatformInfo
IS_WIN = 'wxMSW' in wx.PlatformInfo
```
This is where the "magic" happens.
```python
from matplotlib.mathtext import MathTextParser
mathtext_parser = MathTextParser("Bitmap")
def mathtext_to_wxbitmap(s):
ftimage, depth = mathtext_parser.parse(s, 150)
return wx.Bitmap.FromBufferRGBA(
ftimage.get_width(), ftimage.get_height(),
ftimage.as_rgba_str())
```
```python
functions = [
(r'$\sin(2 \pi x)$', lambda x: np.sin(2*np.pi*x)),
(r'$\frac{4}{3}\pi x^3$', lambda x: (4.0/3.0)*np.pi*x**3),
(r'$\cos(2 \pi x)$', lambda x: np.cos(2*np.pi*x)),
(r'$\log(x)$', lambda x: np.log(x))
]
class CanvasFrame(wx.Frame):
def __init__(self, parent, title):
wx.Frame.__init__(self, parent, -1, title, size=(550, 350))
self.figure = Figure()
self.axes = self.figure.add_subplot(111)
self.canvas = FigureCanvas(self, -1, self.figure)
self.change_plot(0)
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.add_buttonbar()
self.sizer.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW)
self.add_toolbar() # comment this out for no toolbar
menuBar = wx.MenuBar()
# File Menu
menu = wx.Menu()
m_exit = menu.Append(wx.ID_EXIT, "E&xit\tAlt-X", "Exit this simple sample")
menuBar.Append(menu, "&File")
self.Bind(wx.EVT_MENU, self.OnClose, m_exit)
if IS_GTK or IS_WIN:
# Equation Menu
menu = wx.Menu()
for i, (mt, func) in enumerate(functions):
bm = mathtext_to_wxbitmap(mt)
item = wx.MenuItem(menu, 1000 + i, " ")
item.SetBitmap(bm)
menu.Append(item)
self.Bind(wx.EVT_MENU, self.OnChangePlot, item)
menuBar.Append(menu, "&Functions")
self.SetMenuBar(menuBar)
self.SetSizer(self.sizer)
self.Fit()
def add_buttonbar(self):
self.button_bar = wx.Panel(self)
self.button_bar_sizer = wx.BoxSizer(wx.HORIZONTAL)
self.sizer.Add(self.button_bar, 0, wx.LEFT | wx.TOP | wx.GROW)
for i, (mt, func) in enumerate(functions):
bm = mathtext_to_wxbitmap(mt)
button = wx.BitmapButton(self.button_bar, 1000 + i, bm)
self.button_bar_sizer.Add(button, 1, wx.GROW)
self.Bind(wx.EVT_BUTTON, self.OnChangePlot, button)
self.button_bar.SetSizer(self.button_bar_sizer)
def add_toolbar(self):
"""Copied verbatim from embedding_wx2.py"""
self.toolbar = NavigationToolbar2Wx(self.canvas)
self.toolbar.Realize()
# By adding toolbar in sizer, we are able to put it at the bottom
# of the frame - so appearance is closer to GTK version.
self.sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND)
# update the axes menu on the toolbar
self.toolbar.update()
def OnChangePlot(self, event):
self.change_plot(event.GetId() - 1000)
def change_plot(self, plot_number):
t = np.arange(1.0, 3.0, 0.01)
s = functions[plot_number][1](t)
self.axes.clear()
self.axes.plot(t, s)
self.canvas.draw()
def OnClose(self, event):
self.Destroy()
class MyApp(wx.App):
def OnInit(self):
frame = CanvasFrame(None, "wxPython mathtext demo app")
self.SetTopWindow(frame)
frame.Show(True)
return True
app = MyApp()
app.MainLoop()
```
## 下载这个示例
- [下载python源码: mathtext_wx_sgskip.py](https://matplotlib.org/_downloads/mathtext_wx_sgskip.py)
- [下载Jupyter notebook: mathtext_wx_sgskip.ipynb](https://matplotlib.org/_downloads/mathtext_wx_sgskip.ipynb)

View File

@@ -0,0 +1,55 @@
# Matplotlib与Glade 3
```python
import os
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from matplotlib.figure import Figure
from matplotlib.backends.backend_gtk3agg import (
FigureCanvasGTK3Agg as FigureCanvas)
import numpy as np
class Window1Signals(object):
def on_window1_destroy(self, widget):
Gtk.main_quit()
def main():
builder = Gtk.Builder()
builder.add_objects_from_file(os.path.join(os.path.dirname(__file__),
"mpl_with_glade3.glade"),
("window1", ""))
builder.connect_signals(Window1Signals())
window = builder.get_object("window1")
sw = builder.get_object("scrolledwindow1")
# Start of Matplotlib specific code
figure = Figure(figsize=(8, 6), dpi=71)
axis = figure.add_subplot(111)
t = np.arange(0.0, 3.0, 0.01)
s = np.sin(2*np.pi*t)
axis.plot(t, s)
axis.set_xlabel('time [s]')
axis.set_ylabel('voltage [V]')
canvas = FigureCanvas(figure) # a Gtk.DrawingArea
canvas.set_size_request(800, 600)
sw.add_with_viewport(canvas)
# End of Matplotlib specific code
window.show_all()
Gtk.main()
if __name__ == "__main__":
main()
```
## 下载这个示例
- [下载python源码: mpl_with_glade3_sgskip.py](https://matplotlib.org/_downloads/mpl_with_glade3_sgskip.py)
- [下载Jupyter notebook: mpl_with_glade3_sgskip.ipynb](https://matplotlib.org/_downloads/mpl_with_glade3_sgskip.ipynb)

View File

@@ -0,0 +1,55 @@
# Pyplot与GTK
```python
import os
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from matplotlib.figure import Figure
from matplotlib.backends.backend_gtk3agg import (
FigureCanvasGTK3Agg as FigureCanvas)
import numpy as np
class Window1Signals(object):
def on_window1_destroy(self, widget):
Gtk.main_quit()
def main():
builder = Gtk.Builder()
builder.add_objects_from_file(os.path.join(os.path.dirname(__file__),
"mpl_with_glade3.glade"),
("window1", ""))
builder.connect_signals(Window1Signals())
window = builder.get_object("window1")
sw = builder.get_object("scrolledwindow1")
# Start of Matplotlib specific code
figure = Figure(figsize=(8, 6), dpi=71)
axis = figure.add_subplot(111)
t = np.arange(0.0, 3.0, 0.01)
s = np.sin(2*np.pi*t)
axis.plot(t, s)
axis.set_xlabel('time [s]')
axis.set_ylabel('voltage [V]')
canvas = FigureCanvas(figure) # a Gtk.DrawingArea
canvas.set_size_request(800, 600)
sw.add_with_viewport(canvas)
# End of Matplotlib specific code
window.show_all()
Gtk.main()
if __name__ == "__main__":
main()
```
## 下载这个示例
- [下载python源码: mpl_with_glade3_sgskip.py](https://matplotlib.org/_downloads/mpl_with_glade3_sgskip.py)
- [下载Jupyter notebook: mpl_with_glade3_sgskip.ipynb](https://matplotlib.org/_downloads/mpl_with_glade3_sgskip.ipynb)

View File

@@ -0,0 +1,150 @@
# SVG直方图
演示如何创建交互式直方图,通过单击图例标记隐藏或显示条形图。
交互性以ecmascriptjavascript编码并在后处理步骤中插入SVG代码中。 要渲染图像请在Web浏览器中打开它。 大多数Linux Web浏览器和OSX用户都支持SVG。 Windows IE9支持SVG但早期版本不支持。
## 注意
matplotlib后端允许我们为每个对象分配id。 这是用于描述在python中创建的matplotlib对象的机制以及在第二步中解析的相应SVG构造。 虽然灵活,但它们很难用于大量物体的收集。 可以使用两种机制来简化事情:
- 系统地将对象分组为SVG \<g\>标签,
- 根据每个SVG对象的来源为每个SVG对象分配类。
例如不是修改每个单独栏的属性而是可以将列分组到PatchCollection中或者将列分配给class =“hist _ ##”属性。
CSS也可以广泛用于替换整个SVG生成中的重复标记。
作者david.huard@gmail.com
```python
import numpy as np
import matplotlib.pyplot as plt
import xml.etree.ElementTree as ET
from io import BytesIO
import json
plt.rcParams['svg.fonttype'] = 'none'
# Apparently, this `register_namespace` method works only with
# python 2.7 and up and is necessary to avoid garbling the XML name
# space with ns0.
ET.register_namespace("", "http://www.w3.org/2000/svg")
# Fixing random state for reproducibility
np.random.seed(19680801)
# --- Create histogram, legend and title ---
plt.figure()
r = np.random.randn(100)
r1 = r + 1
labels = ['Rabbits', 'Frogs']
H = plt.hist([r, r1], label=labels)
containers = H[-1]
leg = plt.legend(frameon=False)
plt.title("From a web browser, click on the legend\n"
"marker to toggle the corresponding histogram.")
# --- Add ids to the svg objects we'll modify
hist_patches = {}
for ic, c in enumerate(containers):
hist_patches['hist_%d' % ic] = []
for il, element in enumerate(c):
element.set_gid('hist_%d_patch_%d' % (ic, il))
hist_patches['hist_%d' % ic].append('hist_%d_patch_%d' % (ic, il))
# Set ids for the legend patches
for i, t in enumerate(leg.get_patches()):
t.set_gid('leg_patch_%d' % i)
# Set ids for the text patches
for i, t in enumerate(leg.get_texts()):
t.set_gid('leg_text_%d' % i)
# Save SVG in a fake file object.
f = BytesIO()
plt.savefig(f, format="svg")
# Create XML tree from the SVG file.
tree, xmlid = ET.XMLID(f.getvalue())
# --- Add interactivity ---
# Add attributes to the patch objects.
for i, t in enumerate(leg.get_patches()):
el = xmlid['leg_patch_%d' % i]
el.set('cursor', 'pointer')
el.set('onclick', "toggle_hist(this)")
# Add attributes to the text objects.
for i, t in enumerate(leg.get_texts()):
el = xmlid['leg_text_%d' % i]
el.set('cursor', 'pointer')
el.set('onclick', "toggle_hist(this)")
# Create script defining the function `toggle_hist`.
# We create a global variable `container` that stores the patches id
# belonging to each histogram. Then a function "toggle_element" sets the
# visibility attribute of all patches of each histogram and the opacity
# of the marker itself.
script = """
<script type="text/ecmascript">
<![CDATA[
var container = %s
function toggle(oid, attribute, values) {
/* Toggle the style attribute of an object between two values.
Parameters
----------
oid : str
Object identifier.
attribute : str
Name of style attribute.
values : [on state, off state]
The two values that are switched between.
*/
var obj = document.getElementById(oid);
var a = obj.style[attribute];
a = (a == values[0] || a == "") ? values[1] : values[0];
obj.style[attribute] = a;
}
function toggle_hist(obj) {
var num = obj.id.slice(-1);
toggle('leg_patch_' + num, 'opacity', [1, 0.3]);
toggle('leg_text_' + num, 'opacity', [1, 0.5]);
var names = container['hist_'+num]
for (var i=0; i < names.length; i++) {
toggle(names[i], 'opacity', [1,0])
};
}
]]>
</script>
""" % json.dumps(hist_patches)
# Add a transition effect
css = tree.getchildren()[0][0]
css.text = css.text + "g {-webkit-transition:opacity 0.4s ease-out;" + \
"-moz-transition:opacity 0.4s ease-out;}"
# Insert the script and save to file.
tree.insert(0, ET.XML(script))
ET.ElementTree(tree).write("svg_histogram.svg")
```
## 下载这个示例
- [下载python源码: svg_histogram_sgskip.py](https://matplotlib.org/_downloads/svg_histogram_sgskip.py)
- [下载Jupyter notebook: svg_histogram_sgskip.ipynb](https://matplotlib.org/_downloads/svg_histogram_sgskip.ipynb)

View File

@@ -0,0 +1,100 @@
# SVG工具提示
此示例显示如何创建将在Matplotlib面片上悬停时显示的工具提示。
虽然可以从CSS或javascript创建工具提示但在这里我们在matplotlib中创建它并在将其悬停在修补程序上时简单地切换它的可见性。这种方法提供了对工具提示的位置和外观的完全控制而代价是预先获得更多的代码。
另一种方法是将工具提示内容放在SVG对象的Title属性中。然后使用现有的js/css库在浏览器中创建工具提示相对简单。内容由title属性决定外观由CSS决定。
作者David Huard
```python
import matplotlib.pyplot as plt
import xml.etree.ElementTree as ET
from io import BytesIO
ET.register_namespace("", "http://www.w3.org/2000/svg")
fig, ax = plt.subplots()
# Create patches to which tooltips will be assigned.
rect1 = plt.Rectangle((10, -20), 10, 5, fc='blue')
rect2 = plt.Rectangle((-20, 15), 10, 5, fc='green')
shapes = [rect1, rect2]
labels = ['This is a blue rectangle.', 'This is a green rectangle']
for i, (item, label) in enumerate(zip(shapes, labels)):
patch = ax.add_patch(item)
annotate = ax.annotate(labels[i], xy=item.get_xy(), xytext=(0, 0),
textcoords='offset points', color='w', ha='center',
fontsize=8, bbox=dict(boxstyle='round, pad=.5',
fc=(.1, .1, .1, .92),
ec=(1., 1., 1.), lw=1,
zorder=1))
ax.add_patch(patch)
patch.set_gid('mypatch_{:03d}'.format(i))
annotate.set_gid('mytooltip_{:03d}'.format(i))
# Save the figure in a fake file object
ax.set_xlim(-30, 30)
ax.set_ylim(-30, 30)
ax.set_aspect('equal')
f = BytesIO()
plt.savefig(f, format="svg")
# --- Add interactivity ---
# Create XML tree from the SVG file.
tree, xmlid = ET.XMLID(f.getvalue())
tree.set('onload', 'init(evt)')
for i in shapes:
# Get the index of the shape
index = shapes.index(i)
# Hide the tooltips
tooltip = xmlid['mytooltip_{:03d}'.format(index)]
tooltip.set('visibility', 'hidden')
# Assign onmouseover and onmouseout callbacks to patches.
mypatch = xmlid['mypatch_{:03d}'.format(index)]
mypatch.set('onmouseover', "ShowTooltip(this)")
mypatch.set('onmouseout', "HideTooltip(this)")
# This is the script defining the ShowTooltip and HideTooltip functions.
script = """
<script type="text/ecmascript">
<![CDATA[
function init(evt) {
if ( window.svgDocument == null ) {
svgDocument = evt.target.ownerDocument;
}
}
function ShowTooltip(obj) {
var cur = obj.id.split("_")[1];
var tip = svgDocument.getElementById('mytooltip_' + cur);
tip.setAttribute('visibility',"visible")
}
function HideTooltip(obj) {
var cur = obj.id.split("_")[1];
var tip = svgDocument.getElementById('mytooltip_' + cur);
tip.setAttribute('visibility',"hidden")
}
]]>
</script>
"""
# Insert the script at the top of the file and save it.
tree.insert(0, ET.XML(script))
ET.ElementTree(tree).write('svg_tooltip.svg')
```
## 下载这个示例
- [下载python源码: svg_tooltip_sgskip.py](https://matplotlib.org/_downloads/svg_tooltip_sgskip.py)
- [下载Jupyter notebook: svg_tooltip_sgskip.ipynb](https://matplotlib.org/_downloads/svg_tooltip_sgskip.ipynb)

View File

@@ -0,0 +1,96 @@
# 工具管理
此示例演示如何:
- 修改工具栏。
- 创建工具。
- 添加工具。
- 删除工具
可以使用 matplotlib.backend_managers.ToolManager
```python
import matplotlib.pyplot as plt
plt.rcParams['toolbar'] = 'toolmanager'
from matplotlib.backend_tools import ToolBase, ToolToggleBase
class ListTools(ToolBase):
'''List all the tools controlled by the `ToolManager`'''
# keyboard shortcut
default_keymap = 'm'
description = 'List Tools'
def trigger(self, *args, **kwargs):
print('_' * 80)
print("{0:12} {1:45} {2}".format(
'Name (id)', 'Tool description', 'Keymap'))
print('-' * 80)
tools = self.toolmanager.tools
for name in sorted(tools):
if not tools[name].description:
continue
keys = ', '.join(sorted(self.toolmanager.get_tool_keymap(name)))
print("{0:12} {1:45} {2}".format(
name, tools[name].description, keys))
print('_' * 80)
print("Active Toggle tools")
print("{0:12} {1:45}".format("Group", "Active"))
print('-' * 80)
for group, active in self.toolmanager.active_toggle.items():
print("{0:12} {1:45}".format(str(group), str(active)))
class GroupHideTool(ToolToggleBase):
'''Show lines with a given gid'''
default_keymap = 'G'
description = 'Show by gid'
default_toggled = True
def __init__(self, *args, gid, **kwargs):
self.gid = gid
super().__init__(*args, **kwargs)
def enable(self, *args):
self.set_lines_visibility(True)
def disable(self, *args):
self.set_lines_visibility(False)
def set_lines_visibility(self, state):
gr_lines = []
for ax in self.figure.get_axes():
for line in ax.get_lines():
if line.get_gid() == self.gid:
line.set_visible(state)
self.figure.canvas.draw()
fig = plt.figure()
plt.plot([1, 2, 3], gid='mygroup')
plt.plot([2, 3, 4], gid='unknown')
plt.plot([3, 2, 1], gid='mygroup')
# Add the custom tools that we created
fig.canvas.manager.toolmanager.add_tool('List', ListTools)
fig.canvas.manager.toolmanager.add_tool('Show', GroupHideTool, gid='mygroup')
# Add an existing tool to new group `foo`.
# It can be added as many times as we want
fig.canvas.manager.toolbar.add_tool('zoom', 'foo')
# Remove the forward button
fig.canvas.manager.toolmanager.remove_tool('forward')
# To add a custom tool to the toolbar at specific location inside
# the navigation group
fig.canvas.manager.toolbar.add_tool('Show', 'navigation', 1)
plt.show()
```
## 下载这个示例
- [下载python源码: toolmanager_sgskip.py](https://matplotlib.org/_downloads/toolmanager_sgskip.py)
- [下载Jupyter notebook: toolmanager_sgskip.ipynb](https://matplotlib.org/_downloads/toolmanager_sgskip.ipynb)

View File

@@ -0,0 +1,70 @@
# WX光标演示
例如绘制光标并报告WX中的数据坐标。
```python
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.backends.backend_wx import NavigationToolbar2Wx
from matplotlib.figure import Figure
import numpy as np
import wx
class CanvasFrame(wx.Frame):
def __init__(self, ):
wx.Frame.__init__(self, None, -1, 'CanvasFrame', size=(550, 350))
self.figure = Figure()
self.axes = self.figure.add_subplot(111)
t = np.arange(0.0, 3.0, 0.01)
s = np.sin(2*np.pi*t)
self.axes.plot(t, s)
self.axes.set_xlabel('t')
self.axes.set_ylabel('sin(t)')
self.figure_canvas = FigureCanvas(self, -1, self.figure)
# Note that event is a MplEvent
self.figure_canvas.mpl_connect(
'motion_notify_event', self.UpdateStatusBar)
self.figure_canvas.Bind(wx.EVT_ENTER_WINDOW, self.ChangeCursor)
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self.figure_canvas, 1, wx.LEFT | wx.TOP | wx.GROW)
self.SetSizer(self.sizer)
self.Fit()
self.statusBar = wx.StatusBar(self, -1)
self.SetStatusBar(self.statusBar)
self.toolbar = NavigationToolbar2Wx(self.figure_canvas)
self.sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND)
self.toolbar.Show()
def ChangeCursor(self, event):
self.figure_canvas.SetCursor(wx.Cursor(wx.CURSOR_BULLSEYE))
def UpdateStatusBar(self, event):
if event.inaxes:
self.statusBar.SetStatusText(
"x={} y={}".format(event.xdata, event.ydata))
class App(wx.App):
def OnInit(self):
'Create the main window and insert the custom frame'
frame = CanvasFrame()
self.SetTopWindow(frame)
frame.Show(True)
return True
if __name__ == '__main__':
app = App(0)
app.MainLoop()
```
## 下载这个示例
- [下载python源码: wxcursor_demo_sgskip.py](https://matplotlib.org/_downloads/wxcursor_demo_sgskip.py)
- [下载Jupyter notebook: wxcursor_demo_sgskip.ipynb](https://matplotlib.org/_downloads/wxcursor_demo_sgskip.ipynb)