Python中使用Chaco绘图库
Chaco是一个2D的绘图库,如果你安装了Python(x,y)的话,可以在pythonxy的安装目录下的找到Chaco的demo程序:
\pythonxy\doc\Enthought Tool Suite\Chaco\examples\demo.py
面向脚本绘图
Chaco提供了类似Matlab和pylab的绘图方式,我们称之为面向脚本的绘图方式。下面的程序从enthought.chaco.shell中导入脚本绘图相关的内容,然后用numpy快速产生一个正弦波的x,y坐标的数组,然后传递给plot函数进行绘图:
import numpy as np from enthought.chaco.shell import * x = np.linspace(-2*np.pi, 2*np.pi, 100) y = np.sin(x) plot(x, y, "r-") title("First plot") ytitle("sin(x)") show()
plot函数的第三个参数中的"r"指定绘图的颜色为红色,"-"指定绘图的线型为实线。title函数为绘图添加标题,ytitle为Y轴添加标题,show()函数最终显示绘图结果。
脚本绘图不是Chaco的强项,虽然它的这套脚本绘图API和Matplotlib的pylab类似,不过它提供的功能却没有pylab丰富。Chaco的优势在于它可以很方便地嵌入到你的应用程序之中,开发出自己独特的绘图应用。
面向应用绘图
要将Chaco嵌入到别的应用程序之中,需要做一些额外的工作,因此代码量比面向脚本绘图要多,不过同时也更具有灵活性。先来看一个例子:
from enthought.traits.api import HasTraits, Instance from enthought.traits.ui.api import View, Item from enthought.chaco.api import Plot, ArrayPlotData from enthought.enable.component_editor import ComponentEditor from numpy import linspace, sin class LinePlot(HasTraits): plot = Instance(Plot) traits_view = View( Item('plot',editor=ComponentEditor(), show_label=False), width=500, height=500, resizable=True, title="Chaco Plot") def __init__(self): super(LinePlot, self).__init__() x = linspace(-14, 14, 100) y = sin(x) * x**3 plotdata = ArrayPlotData(x=x, y=y) plot = Plot(plotdata) plot.plot(("x", "y"), type="line", color="blue") plot.title = "sin(x) * x^3" self.plot = plot if __name__ == "__main__": LinePlot().configure_traits()
这段代码看起来似乎挺复杂,其实只要掌握了其基本设计思想,就很容易理解了。首先是许多import语句,为了保持应用程序的名字空间整洁以及让自动语法检查工具能帮助我们检查代码,这些语句只import了需要的对象。
- HasTraits, Instance:这两个从traits库中导入,HasTraits是所有拥有Trait属性的类的父类,我们自己定义的LinePlot类继承于它。而Instance用来创建一个Trait属性,此属性的值为某个指定的类的实例。
- View, Item:从traits.ui库导入,View用来创建一个生成用户界面用的视图,而Item则用来定义视图中的元素。
- Plot, ArrayPlotData:从chaco库中导入,Plot本身是一个描述绘图的类,它的祖先类中有HasTraits,因此它本身也是一个拥有trait属性的类,ArrayPlotData是用来统一保存绘图所用的数据的类。也就是说Plot管理绘图,而ArrayPlotData则用来管理绘图所用的数据。
- ComponentEditor:从enable库中导入,用户界面视图中使用ComponentEditor来显示LinePlot类的plot属性。如果trait属性为Int、Str或者Float之类的简单类型的话,系统能够自动的帮我们选择对应的GUI元素来显示它们。但是系统不知道如何显示Chaco中定义的Plot这样的的类型,因此我们必须手工指定采用ComponentEditor来显示Plot。
- linspace, sin:从numpy库中导入,linspace用来产生一个等差数列,numpy中的sin函数可以自动对数组中的每个元素进行计算。
接下来的代码部分:
class LinePlot(HasTraits): plot = Instance(Plot)
首先定义一个LinePlot继承于HasTraits,并且它有一个trait属性plot为Plot类的实例。然后定义视图:
traits_view = View( Item('plot',editor=ComponentEditor(), show_label=False), width=500, height=500, resizable=True, title="Chaco Plot")
此视图在LinePlot类中定义,因此在调用configure_traits的时候就不需要指定视图了。视图中有一个元素,它将用来显示名为plot的属性的内容,视图中的元素用Item创建。注意这里使用字符串指定视图元素所对应的属性。然后通过关键字参数editor指定此视图元素采用ComponentEditor进行显示。并且不显示其标签(show_label=False)。通过View的关键字参数width、height、resizable和title分别指定界面的宽、高、是否可改变大小以及其窗口标题栏的文字。
接下来看构造函数,真正的计算在这里:
def __init__(self): super(LinePlot, self).__init__() x = linspace(-14, 14, 100) y = sin(x) * x**3 plotdata = ArrayPlotData(x=x, y=y)
在构造函数做其它事情之前,一定要记住调用父类的构造函数,这样HasTraits的功能才能真正在我们的实例中出现。
接下来和脚本绘图一样,计算出绘图所需的x,y坐标的数值数组。然后将这两个数组存到一个ArrayPlotData对象中。ArrayPlotData和字典(dict)有些类似,它将一个字符串(数组的名字)和数组本身联系起来。而真正的绘图对象plot将通过数组的名字在ArrayPlotData中获得数组的内容。这样做就在数据和绘图对象中形成了一个接口界面,修改ArrayPlotData中的数组的值将会立即反应到与此数据相连的绘图对象,而多个绘图对象可以共用ArrayPlotData中的同一数组。
接下来创建绘图对象plot,并且将我们创建的ArrayPlotData实例传递给它,此后plot将在此实例中获取自己绘图所需的数据。:
plot = Plot(plotdata)
Plot类将Chaco中提供的许多真正用来绘图的对象进行包装,提供了一个统一的接口用来创建和管理这些绘图对象。在今后深入学习Chaco的过程中我们将通过分析Plot类的实现来了解Chaco库的设计思想。
接下来调用plot方法在Plot内部创建真正的绘图对象(一个曲线图):
plot.plot(("x", "y"), type="line", color="blue")
注意我们传递给plot方法的是数组的名字而不是数组本身,Plot对象会自动通过数组的名字在ArrayPlotData的实例中找到其对应的数组。
然后设置绘图的标题,并且把绘图实例赋值给plot属性:
plot.title = "sin(x) * x^3" self.plot = plot
最后是LinePlot对象的实例化和调用configure_trait显示绘图窗口:
if __name__ == "__main__": LinePlot().configure_traits()
由于没有给configure_traits传递视图参数,它将在LinePlot实例中寻找视图的定义,于是它找到traits_view,并且用此视图来显示LinePlot实例的trait属性。于是plot属性将如traits_view中定义的一样,用ComponentEditor显示。
采用和LinePlot类同样的模式,我们可以绘制更多的曲线图:
from enthought.traits.api import HasTraits, Instance from enthought.traits.ui.api import View, Item from enthought.chaco.api import Plot, ArrayPlotData, Legend from enthought.enable.component_editor import ComponentEditor from numpy import linspace, sin, cos class LinePlot(HasTraits): plot = Instance(Plot) traits_view = View( Item('plot',editor=ComponentEditor(), show_label=False), width=500, height=500, resizable=True, title="Chaco Plot") def __init__(self): super(LinePlot, self).__init__() x = linspace(-14, 14, 100) y1 = sin(x) * x**3 y2 = cos(x) * x**3 plotdata = ArrayPlotData(x=x, y1=y1, y2=y2) plot = Plot(plotdata) plot.plot(("x", "y1"), type="line", color="blue", name="sin(x) * x**3") plot.plot(("x", "y2"), type="line", color="red", name="cos(x) * x**3") plot.plot(("x", "y2"), type="scatter", color="red", marker = "circle", marker_size = 2, name="cos(x) * x**3 points") plot.title = "Multiple Curves" self.plot = plot legend = Legend(padding=10, align="ur") legend.plots = plot.plots plot.overlays.append(legend) if __name__ == "__main__": lineplot = LinePlot() lineplot.configure_traits()
在这个程序中,我们调用了3次plot.plot方法,其中两次的type="line"绘制曲线,一次是type="scatter"绘制坐标点。绘制坐标点时通过marker和marker_size配置点的形状和大小。并且我们为每个plot传递了一个name参数。
为了绘制图示(legend),从chaco.api中载入Legend之后,使用如下三行代码为坐标图添加图示::
legend = Legend(component=plot, padding=10, align="ur") legend.plots = plot.plots plot.overlays.append(legend)
其中第一行创建一个Legend对象,并且设置padding和align两个属性,padding设置其内容与边框之间的距离,align设置其在容器中的位置: upper right。
为了让legend对象知道要显示什么曲线的图示,我们需要把曲线对象传递给它。三次调用plot绘制的曲线可以通过plot对象plots属性得到,在iPython中运行完上面的程序之后,输入lineplot.plot.plots查看plots属性的值:
>>> lineplot.plot.plots {'cos(x) * x**3 points': [<enthought.chaco.scatterplot.ScatterPlot object at 0x1436B4B0>], 'cos(x) * x**3': [<enthought.chaco.lineplot.LinePlot object at 0x1436B120>], 'sin(x) * x**3': [<enthought.chaco.lineplot.LinePlot object at 0x143140F0>]}
我们将plot.plots传递给legend.plots,于是legend就知道要显示哪些曲线的图示了。
最后我们将legend对象添加到plot.overlays中。整个绘图区域分为许多层,每一层放置不同的绘图元素,overlays是最上面的一层,其中放置在屏幕坐标系中的绘图元素。plot的overlays属性为一个TraitListObject类的对象,它继承于list类,具有list的所有能力,因此可以用append方法将绘图元素添加进overlays层。
到此这篇关于Python中使用Chaco绘图库的文章就介绍到这了,更多相关Python使用Chaco内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
最新评论