matplotlib+pyqt4 内容整理

来源:互联网 发布:淘宝买的lol号安全吗 编辑:程序博客网 时间:2024/06/06 15:40

转自:https://www.cnblogs.com/me-qk/p/4156680.html

最近学习了matplotlib的内容,在这里做一些总结。

参考:vamei博客(Python的也可以看其教程)http://www.cnblogs.com/vamei/archive/2013/01/30/2879700.html

http://reverland.org/python/2012/09/07/matplotlib-tutorial/

http://myshare.dscloud.me/scipydoc/matplotlib_intro.html#axis(这个文章很好的解释了figure,axes,subplot,axis等之间的关系,还有最终的artist对象,感觉这个是必看)

官方的文档:http://matplotlib.org/index.html

一、一些例子pyqt4+matplotlib

example1 : 将matplolib作为一个widget对象显现,这样也可以插入到qt的布局中,所有的matplotlib都可以以这种形式呈现。有个plt.gcf()的方法我经常使用,这个是获取当前的figure,如果你有多figure的话,只显示当前状态的,当然也有方法去显示多figure。使用plt.gcf().clear()可以让figure上的对象消失,我采用这个方法实现的重绘,不知道有没有其他更好的方法。

View Code

example2: 多figure在widget上的显示,我用了一种比较笨的方法,采用了多canvas和多figure的办法,然后在widget上面使用布局管理器控制布局,我记得是有一种方法可以用一个canvas将多figure显示出来的,方法记不起来了,就附上这个比较笨的替代方法。(代码中可以忽略class Example这一段,这些是不同的widget,最后widgetObject.show()方法显示指定的widget)

View Code

example3:如果想实现在一个figure里画很多线或者图形,很简单,一直绘制就行。

View Code

example4:这个是一个figure里面多子区的画法,使用subplot()方法,得到的是一个Axes对象,就像是vamei说的有两套方法,plt.add_subplot()还有这种方法,我是比较容易混,一般都是使用前者创建对象,然后使用后面的方式对其属性进行修改。我们这里改了figure的颜色,这些都是artist对象,有很多属性可以修改,后面慢慢上图。

View Code

虽然很丑,但是大家可以通过该颜色让它漂亮一点,至于颜色的配置,我只是使用了文本的表示方法,大家可以去查有哪些颜色名称,但是使用过QColor()方法表示颜色是不允许的,因为很少该颜色,所以还没有细看原因。

example5:魔鬼在于细节,一个matplotlib指引上的例子。涉及到的几个点,第一是参数的选择,比如color,linewidth,linestyle等,二是spines的应用,例子中用于轴的移动,通过gca()得到axes对象,axes.spines['top']方法得到上面的轴,axes.spines['top'].set_color('none'),axes.xaxis.set_ticks_position('bottom'),将顶轴上面的刻度移到底轴来,axes.spines['bottom'].set_position(('data',0),再把轴移到0处,同样把左轴移到0处,再使用plt.xticks()方法将轴的刻度自定义。另外使用了annocate方法,注释了数学表达式。最后设置了bbox,先得到axes.get_xticklabels()+axes.get_yticklabels() 得到labels对象,设置字体大小和外框bbox,前色为白色,外框为空,设置透明值。例子来源:http://reverland.org/python/2012/09/07/matplotlib-tutorial/#figure

View Code

二、关于figure,subplot,axes,axis和artist对象的理解:

figure更多的是代表当前的一个图像,这个图像在画板上,可以由很多的axes对象组成,使用subplot和axes的区别在于,前值是布局比较规整的,但后者可以放在任何地方,两者都是axes对象,axis是轴对象,我们前面也用过它移动刻度的位置,artist则是一个组成前面各种容器的对象,有很多功能,可以通过它对任意一个对象进行定制。

1. 对figure的布局除了上面的几种方式之外还提供了更强大的功能。

复制代码
ax1 = plt.subplot2grid((3,3), (0,0), colspan=3)ax2 = plt.subplot2grid((3,3), (1,0), colspan=2)ax3 = plt.subplot2grid((3,3), (1, 2), rowspan=2)ax4 = plt.subplot2grid((3,3), (2, 0))ax5 = plt.subplot2grid((3,3), (2, 1))#subplot2grid((3,3),(0,0),colspan=3)3行3列的表格,图形从第一行第一列起,占用3列,rowspan=2指占用两行。import matplotlib.gridspec as gridspecgs = gridspec.GridSpec(3, 3)ax1 = plt.subplot(gs[0, :])ax2 = plt.subplot(gs[1,:-1])ax3 = plt.subplot(gs[1:, -1])ax4 = plt.subplot(gs[-1,0])ax5 = plt.subplot(gs[-1,-2])#使用gridspec定制,还可以使用切片gs1 = gridspec.GridSpec(3, 3)gs1.update(left=0.05, right=0.48, wspace=0.05)ax1 = plt.subplot(gs1[:-1, :])ax2 = plt.subplot(gs1[-1, :-1])ax3 = plt.subplot(gs1[-1, -1])gs2 = gridspec.GridSpec(3, 3)gs2.update(left=0.55, right=0.98, hspace=0.05)ax4 = plt.subplot(gs2[:, :-1])ax5 = plt.subplot(gs2[:-1, -1])ax6 = plt.subplot(gs2[-1, -1])#使用update函数指定上下左右和中间子图的间隔gs = gridspec.GridSpec(2, 2,                       width_ratios=[1,2],                       height_ratios=[4,1]                       )ax1 = plt.subplot(gs[0])ax2 = plt.subplot(gs[1])ax3 = plt.subplot(gs[2])ax4 = plt.subplot(gs[3])#设置各子图的比例值
复制代码

2.axes对象的功能在于可以随意定义地址。还可以使用plt.text()定义一个文本

View Code

3. ticks

复制代码
ax.set_xlim(0,4)ax.set_ylim(0,3)ax.xaxis.set_major_locator(MultipleLocator(1.0))ax.xaxis.set_minor_locator(MultipleLocator(0.1))ax.yaxis.set_major_locator(MultipleLocator(1.0))ax.yaxis.set_minor_locator(MultipleLocator(0.1))ax.grid(which='major', axis='x', linewidth=0.75, linestyle='-', color='0.75')ax.grid(which='minor', axis='x', linewidth=0.25, linestyle='-', color='0.75')ax.grid(which='major', axis='y', linewidth=0.75, linestyle='-', color='0.75')ax.grid(which='minor', axis='y', linewidth=0.25, linestyle='-', color='0.75')ax.set_xticklabels([])ax.set_yticklabels([])#设置了主定位器和副定位器,并为刻度划线
复制代码
复制代码
#挺有意思的一个文本显示的图片,可以自定义内容,网上有一些叫做词云可视化的东东就是用很多字组成一个图片的大致轮廓。如果我们分析一张图片,分析出其大致的轮廓然后在相应的像素点用axes代替是不是也可以做出来相应的效果?图像轮廓提取方法研究?from pylab import *eqs = []eqs.append((r"$W^{3\beta}_{\delta_1 \rho_1 \sigma_2} = U^{3\beta}_{\delta_1 \rho_1} + \frac{1}{8 \pi 2} \int^{\alpha_2}_{\alpha_2} d \alpha^\prime_2 \left[\frac{ U^{2\beta}_{\delta_1 \rho_1} - \alpha^\prime_2U^{1\beta}_{\rho_1 \sigma_2} }{U^{0\beta}_{\rho_1 \sigma_2}}\right]$"))eqs.append((r"$\frac{d\rho}{d t} + \rho \vec{v}\cdot\nabla\vec{v} = -\nabla p + \mu\nabla^2 \vec{v} + \rho \vec{g}$"))eqs.append((r"$\int_{-\infty}^\infty e^{-x^2}dx=\sqrt{\pi}$"))eqs.append((r"$E = mc^2 = \sqrt{{m_0}^2c^4 + p^2c^2}$"))eqs.append((r"$F_G = G\frac{m_1m_2}{r^2}$"))axes([0.025,0.025,0.95,0.95])for i in range(24):    index = np.random.randint(0,len(eqs))    eq = eqs[index]    size = np.random.uniform(12,32)    x,y = np.random.uniform(0,1,2)    alpha = np.random.uniform(0.25,.75)    text(x, y, eq, ha='center', va='center', color="#11557c", alpha=alpha,         transform=gca().transAxes, fontsize=size, clip_on=True)xticks([]), yticks([])# savefig('../figures/text_ex.png',dpi=48)show()
复制代码

 

三、其他一些内容,主要是关于属性配置的。详情见博客 http://myshare.dscloud.me/scipydoc/matplotlib_intro.html#figure

lines = plt.plot(x,cos(x),x,sin(x)) # 划了两条直线

plt.setp(lines,color='red',linwidth='2') #为多条直线设置了多个属性

lines[0].get_linewidth()使用get_属性 这样的方法来获得某一个属性值,

或plt.getp(lines[1],'color'),

plt.getp(lines[0])则返回这个对象的所有的值。

可以使用plt.getp(axes,属性)这样的方法得到相对应的属性值,然后直接通过axes对象使用get或set方法进行属性的配置。

之前提到过使用plt.subplot(221,axisbg=color),不仅可以进行布局,而且还可以直接指定每个子图的背景颜色,figure的颜色在定义中使用facecolor='color'.

下面大部分是直接复制的上面博客链接的内容,感谢作者的辛勤付出。

Artist對像

  • backend_bases.FigureCanvas : 圖表的繪製領域
  • backend_bases.Renderer : 知道如何在FigureCanvas上如何繪圖
  • artist.Artist : 知道如何使用Renderer在FigureCanvas上繪圖

FigureCanvas和Renderer需要處理底層的繪圖操作,例如使用wxPython在界面上繪圖,或者使用PostScript繪製PDF。Artist則處理所有的高層結構,例如處理圖表、文字和曲線等的繪製和佈局。通常我們只和Artist打交道,而不需要關心底層的繪製細節。

Artists分為簡單類型和容器類型兩種。簡單類型的Artists為標準的繪圖元件,例如Line2D、 Rectangle、 Text、AxesImage 等等。而容器類型則可以包含許多簡單類型的Artists,使它們組織成一個整體,例如Axis、 Axes、Figure等。

直接使用Artists創建圖表的標準流程如下:

  • 創建Figure對像
  • 用Figure對像創建一個或者多個Axes或者Subplot對像
  • 調用Axies等對象的方法創建各種簡單類型的Artist
>>> import matplotlib.pyplot as plt>>> fig = plt.figure()>>> ax = fig.add_axes([0.15, 0.1, 0.7, 0.3])
>>> line, = ax.plot([1,2,3],[1,2,1]) #这里返回的是一个包含一个line2D对象的列表,可以这样写,也可以直接list[0]>>> ax.lines  #ax的属性lines,包含了所有的line2D对象,下面可以看到他们的id是一样的。如果删除某条直线,那么直接在里面删除即可,其他的属性有的也可以这么使用。[<matplotlib.lines.Line2D object at 0x0637A3D0>]>>> line<matplotlib.lines.Line2D object at 0x0637A3D0>

下面列出axes对象的属性:plt.getp(plt.gca()),里面的属性有多种使用方法:

plt.xlabel()  ,axes.set_xlabel(''),  axes.xaxis.set_label_text(''),  axes.xaxis.label.set_test('')

这就是从高层到底层的方法。

adjustable = box
agg_filter = None
alpha = None  #透明
anchor = C
animated = False  #动画
aspect = auto
autoscale_on = True
autoscalex_on = True
autoscaley_on = True
axes = Axes(0.1,0.1;0.5x0.5) 
axes_locator = None 子图的定位器
axis_bgcolor = w  子图的背景颜色,
axisbelow = False
children = [<matplotlib.axis.XAxis object at 0x03796990>, <ma... 
clip_box = None
clip_on = True
clip_path = None
contains = None
cursor_props = (1, (0.0, 0.0, 0.0, 1.0))
data_ratio = 1.0
data_ratio_log = 0.369070246429
default_bbox_extra_artists = []
figure = Figure(1000x600) 它的figure对象
frame = Rectangle(0,0;1x1)
frame_on = True
gid = None
images = <a list of 0 AxesImage objects>
label =
legend = None 图例
legend_handles_labels = ([], [])
lines = <a list of 1 Line2D objects> line2D列表
navigate = True
navigate_mode = None
picker = None
position = Bbox('array([[ 0.1, 0.1],\n [ 0.6, 0.6]])'...
rasterization_zorder = None
rasterized = None
renderer_cache = None
shared_x_axes = <matplotlib.cbook.Grouper object at 0x036BD610>
shared_y_axes = <matplotlib.cbook.Grouper object at 0x036C70F0>
snap = None
title =  标题
transform = IdentityTransform()
transformed_clip_path_and_affine = (None, None)
url = None
visible = True 是否可见
window_extent = TransformedBbox(Bbox('array([[ 0.1, 0.1],\n ...
xaxis = XAxis(100.000000,60.000000) 
xaxis_transform = BlendedGenericTransform(CompositeGenericTransform(...
xbound = (1.0, 3.0)
xgridlines = <a list of 5 Line2D xgridline objects>
xlabel =           #使用set_xlabel('')设置坐标轴标签,也可以使用xaxis.set_label_text(‘’)这个是使用的axis对象的方法

xlim = (1.0, 3.0) 限制
xmajorticklabels = <a list of 5 Text xticklabel objects>
xminorticklabels = <a list of 0 Text xticklabel objects>
xscale = linear 
xticklabels = <a list of 5 Text xticklabel objects> 
xticklines = <a list of 10 Text xtickline objects>
xticks = [ 1. 1.5 2. 2.5 3. ]
yaxis = YAxis(100.000000,60.000000)
yaxis_transform = BlendedGenericTransform(BboxTransformTo(Transforme...
ybound = (4.0, 6.0)
ygridlines = <a list of 5 Line2D ygridline objects>
ylabel =
ylim = (4.0, 6.0)
ymajorticklabels = <a list of 5 Text yticklabel objects>
yminorticklabels = <a list of 0 Text yticklabel objects>
yscale = linear
yticklabels = <a list of 5 Text yticklabel objects>
yticklines = <a list of 10 Line2D ytickline objects>
yticks = [ 4. 4.5 5. 5.5 6. ]
zorder = 0

Artist的屬性

圖表中的每個元素都用一個matplotlib的Artist對像表示,而每個Artist對象都有一大堆屬性控制其顯示效果。例如Figure對像和Axes對象都有patch屬性作為其背景,它的值是一個Rectangle對象。通過設置此它的一些屬性可以修改Figrue圖表的背景顏色或者透明度等屬性,下面的例子將圖表的背景顏色設置為綠色:

>>> fig = plt.figure()>>> fig.show()>>> fig.patch.set_color("g")>>> fig.canvas.draw()

下面是Artist對象都具有的一些屬性:

  • alpha : 透明度,值在0到1之間,0為完全透明,1為完全不透明
  • animated : 布爾值,在繪製動畫效果時使用
  • axes : 此Artist對像所在的Axes對象,可能為None
  • clip_box : 對象的裁剪框
  • clip_on : 是否裁剪
  • clip_path : 裁剪的路徑
  • contains : 判斷指定點是否在對像上的函數
  • figure : 所在的Figure對象,可能為None
  • label : 文本標籤
  • picker : 控制Artist對像選取
  • transform : 控制偏移旋轉
  • visible : 是否可見
  • zorder : 控制繪圖順序

Artist對象的所有屬性都通過相應的 get_* 和 set_* 函數進行讀寫,例如下面的語句將alpha屬性設置為當前值的一半:

>>> fig.set_alpha(0.5*fig.get_alpha())

如果你想用一條語句設置多個屬性的話,可以使用set函數:

>>> fig.set(alpha=0.5, zorder=2)

Figure容器

最大的Artist容器是matplotlib.figure.Figure,它包括組成圖表的所有元素。圖表的背景是一個Rectangle對象,用Figure.patch屬性表示。當你通過調用add_subplot或者add_axes方法往圖表中添加軸(子圖時),這些子圖都將添加到Figure.axes屬性中,同時這兩個方法也返回添加進axes屬性的對象,注意返回值的類型有所不同,實際上AxesSubplot是Axes的子類。

為了支持pylab中的gca()等函數,Figure對像內部保存有當前軸的信息,因此不建議直接對Figure.axes屬性進行列表操作,而應該使用add_subplot, add_axes, delaxes等方法進行添加和刪除操作。但是使用for循環對axes中的每個元素進行操作是沒有問題的,下面的語句打開所有子圖的柵格。>>>for ax in fig.axes:ax.grid(True)

figure提供了一些简单的artist对象,主要还是通过里面的axes对象来实现功能的扩展。因为很多情况下都会默认创建一个subplot和axes对象,当然也可以直接操作,比如:

>>> from matplotlib.lines import Line2D>>> fig = plt.figure()>>> line1 = Line2D([0,1],[0,1], transform=fig.transFigure, figure=fig, color="r")>>> line2 = Line2D([0,1],[1,0], transform=fig.transFigure, figure=fig, color="g")>>> fig.lines.extend([line1, line2])>>> fig.show()

Figure對像有如下屬性包含其它的Artist對像,也就意味着可以通过他们再进行进一步的操作。

  • axes : Axes對像列表
  • patch : 作為背景的Rectangle對像
  • images : FigureImage對像列表,用來顯示圖片
  • legends : Legend對像列表
  • lines : Line2D對像列表
  • patches : patch對像列表
  • texts : Text對像列表,用來顯示文字

Axes容器

Axes容器是整個matplotlib庫的核心,它包含了組成圖表的眾多Artist對象,並且有許多方法函數幫助我們創建、修改這些對象。和Figure一樣,它有一個patch屬性作為背景,當它是笛卡爾坐標時,patch屬性是一個Rectangle對象,而當它是極坐標時,patch屬性則是Circle對象。例如下面的語句設置Axes對象的背景顏色為綠色:

>>> fig = plt.figure()>>> ax = fig.add_subplot(111)>>> ax.patch.set_facecolor("green")

下面詳細列出Axes包含各種Artist對象的屬性:

  • artists : Artist對像列表
  • patch : 作為Axes背景的Patch對象,可以是Rectangle或者Circle
  • collections : Collection對像列表
  • images : AxesImage對像列表
  • legends : Legend對像列表
  • lines : Line2D對像列表
  • patches : Patch對像列表
  • texts : Text對像列表
  • xaxis : XAxis對像
  • yaxis : YAxis對像

下面列出Axes的創建Artist對象的方法:

Axes的方法所創建的對象添加進的列表annotateAnnotatetextsbarsRectanglepatcheserrorbarLine2D, Rectanglelines,patchesfillPolygonpatcheshistRectanglepatchesimshowAxesImageimageslegendLegendlegendsplotLine2DlinesscatterPolygonCollectionCollectionstextTexttexts

Axis容器

Axis容器包括坐標軸上的刻度線、刻度文本、坐標網格以及坐標軸標題等內容。刻度包括主刻度和副刻度,分別通過Axis.get_major_ticks和Axis.get_minor_ticks方法獲得。每個刻度線都是一個XTick或者YTick對象,它包括實際的刻度線和刻度文本。為了方便訪問刻度線和文本,Axis對像提供了get_ticklabels和get_ticklines方法分別直接獲得刻度文本和刻度线:

>>> pl.plot([1,2,3],[4,5,6])[<matplotlib.lines.Line2D object at 0x0AD3B670>]>>> pl.show()>>> axis = pl.gca().xaxis
>>> axis.get_ticklocs() # 獲得刻度的位置列表array([ 1. ,  1.5,  2. ,  2.5,  3. ])
>>> axis.get_ticklabels() # 獲得刻度標籤列表<a list of 5 Text major ticklabel objects>>>> [x.get_text() for x in axis.get_ticklabels()] # 獲得刻度的文本字符串[u'1.0', u'1.5', u'2.0', u'2.5', u'3.0']
>>> axis.get_ticklines() # 獲得主刻度線列表,圖的上下刻度線共10條<a list of 10 Line2D ticklines objects>
>>> axis.get_ticklines(minor=True) # 獲得副刻度線列表,major是主刻度线<a list of 0 Line2D ticklines objects>

獲得刻度線或者刻度標籤之後,可以設置其各種屬性,下面設置刻度線為綠色粗線,文本為紅色並且旋轉45度:这些方法及其有用

>>> for label in axis.get_ticklabels():...     label.set_color("red")...     label.set_rotation(45)...     label.set_fontsize(16)...
>>> for line in axis.get_ticklines():...     line.set_color("green")...     line.set_markersize(25)...     line.set_markeredgewidth(3)
 

上面的例子中,獲得的副刻度線列表為空,這是因為用於計算副刻度的對象缺省為NullLocator,它不產生任何刻度線;而計算主刻度的對象為AutoLocator,它會根據當前的縮放等配置自動計算刻度的位置:

>>> axis.get_minor_locator() # 計算副刻度的對象<matplotlib.ticker.NullLocator instance at 0x0A014300>>>> axis.get_major_locator() # 計算主刻度的對象<matplotlib.ticker.AutoLocator instance at 0x09281B20>

我們可以使用程序為Axis對像設置不同的Locator對象,用來手工設置刻度的位置;設置Formatter對像用來控制刻度文本的顯示。下面的程序設置X軸的主刻度為pi/4,副刻度為pi/20,並且主刻度上的文本以pi為單位:

# -*- coding: utf-8 -*-import matplotlib.pyplot as plfrom matplotlib.ticker import MultipleLocator, FuncFormatterimport numpy as npx = np.arange(0, 4*np.pi, 0.01)y = np.sin(x)pl.figure(figsize=(8,4))pl.plot(x, y)ax = pl.gca()def pi_formatter(x, pos):    """    比較囉嗦地將數值轉換為以pi/4為單位的刻度文本    """    m = np.round(x / (np.pi/4))    n = 4    if m%2==0: m, n = m/2, n/2    if m%2==0: m, n = m/2, n/2    if m == 0:        return "0"    if m == 1 and n == 1:        return "$\pi$"    if n == 1:        return r"$%d \pi$" % m    if m == 1:        return r"$\frac{\pi}{%d}$" % n    return r"$\frac{%d \pi}{%d}$" % (m,n)# 設置兩個坐標軸的範圍pl.ylim(-1.5,1.5)pl.xlim(0, np.max(x))# 設置圖的底邊距pl.subplots_adjust(bottom = 0.15)pl.grid() #開啟網格# 主刻度為pi/4ax.xaxis.set_major_locator( MultipleLocator(np.pi/4) )# 主刻度文本用pi_formatter函數計算ax.xaxis.set_major_formatter( FuncFormatter( pi_formatter ) )# 副刻度為pi/20ax.xaxis.set_minor_locator( MultipleLocator(np.pi/20) )# 設置刻度文本的大小for tick in ax.xaxis.get_major_ticks():    tick.label1.set_fontsize(16)pl.show()

關於刻度的定位和文本格式的東西都在matplotlib.ticker中定義,程序中使用到如下兩個類:

  • MultipleLocator : 以指定值的整數倍為刻度放置刻度線
  • FuncFormatter : 使用指定的函數計算刻度文本,他會傳遞給所指定的函數兩個參數:刻度值和刻度序號,程序中通過比較笨的辦法計算出刻度值所對應的刻度文本

此外還有很多預定義的Locator和Formatter類,詳細內容請參考相應的API文檔。

 
不得不说,这面这个教程是学习matplotlib最好的教程之一,前面我们解决了matplotlib在pyqt4中嵌入的问题,这就使得所有的matplotlib图形可以在pyqt中展现。后面陆续的会把pyqt的内容写下去,不过太多了,写几个小时都写不完。

原创粉丝点击