关于matplotlib的一些问题
安装模块的问题
一直不了解模块到底是什么东西,它与对象有什么样的区别。到了现在才差不多把模块比成一个可以加载与控制的子程序。在Python这样的动态类型里面相当于扩展功能。相当于在C语言程序里面使用了其它的库。
这么说来,模块的编译原理理论应当是与子程序密不可分的。以前甚少将动态语言里面的模块与C语言这样的传统语言里的程序联系在一起。那仅仅是因为自己觉得C语言这样的程序是连接到二进制的库,而动态语言是导入源代码。而库与源代码是绝对不同的事物。这说明自己还是抱着以前形成的概念,以为在二进制与源代码是绝对分离的。但是在开源世界源代码与二进制通常并不存在异步的现象。两者还是非常相近的。
在开源的世界里淡化了库与源文件在用户与程序员角度上的差别。这个观点应当好好地思考一下。在Shell里面是没有什么模块的,它们使用的都是脚本与函数这样的概念。基本上只是使用另一个编译单元或者运行实体的一部分代码,这部分代码只是一个源文件里面很少的一个成分,基本上我们调用一次函数后就不再用它了。但在Python当中,我们不如认为一个模块可以以解释的方式出现,也可以以编译的方式出现。或者以混合的方式出现。这并不阻止我们使用一个模块。
于是使用模块就好像是在C语言里面加载动态链接库一样。大致来说就是如此。但是模块在脚本文件里面通常有更多的应用。也就是如果我们在文件a里导入一个代码,通常我们在a文件里面大量的功能都是通过库来实现的。但是在C语言里面并不能感受到这一点。
在C语言里面并不怎么关心库是怎样导入的。这大概是因为C是一个系统级的语言。通常而言如果我们要使用C库,需要一个头文件一个库文件就可以了。由于了解C语言的人数是那么地多,所以导入C库的方法就变得几乎不用任何思考了。
但是脚本语言的应用还是没有C那么多。脚本语言里的模块,虽然功能上与C还是那么地相象。但是所用的指导理论至少在形式上与C的差别还是比较大的。类似于C,模块也有自己的命名空间。但是在Python当中,模块是以一个对象的形式存在的。
在C语言里面也没有接触过怎么编译与安装模块,似乎那是不用考虑的,只要我们有头文件与库文件就可以了。但是那只是模块的产品,我们如何根据源代码生成库呢。
还有,Python里面的库是可以有很多的层次的关系的。这一点在C语言里就更没有体现了。CXX里面还有命名空间的概念的。可是以前学习CXX的时候都没有怎样讲命名空间。我想设计CXX时,命名空间那个时候还是为一解决函数调用重复而设置的一个机制,并没有太多其它的意思。但是脚本语言里面,命名空间得到了广泛的应用的同时,可能也有了一个理论的基础。不过,由于模块这个词比较陌生,在理解时用C语言的头文件加上库文件理解就是一个相当必要的方法了。
Python的库的安装
以matplotlib为例吧。安装一个模块的基本过程是:
- 检查要安装的模块所需的依赖关系是否满足。我们可以视为当前系统上面是否有相应的头文件与库文件。但是C语言里面还没有见到过。我们就把模块想象成C语言里的动态链接库吧,它不仅是需要一个编译器,还需要其它的库。我们知道C语言里面单独发布一个动态链接库版本是不可想象的。伴随一个动态函数库发布的通常还有其它的依赖的关件。不过造成这一现象可能更多是策略的原因吧。
对于matplotlib来说,检查的主要是numpy模块。要在动态语言里面检查模块是否被安装了,可以在执行解释器的时候导入该库,然后调用该库的 __version__ 函数。因为在Python里面,一个模块可以通过一个对象的方法进行访问。
import numpy
print numpy.__version__模块与函数库的区别还在于,函数库是脱离编译器运行的。但是模块却是在解释器下源代码被解释器执行的。
在Python里面,对象占据着重要的地位。在导入模块的同时,不如就视为创建了一个模块访问对象。我们通过它访问到模块里面的各种数据结构,还可以通过里面的函数定义一个其它的对象。在Python里面不用声明变量类型。这是很有用的,因为模块里面对象的类型可能是非常长的一个名子。
在WINDOWS下面使用一个安装好的exe文件就可以了。
Python的库有时候需要编译。我们不如假设Python的模块不只是可以被解释,也可以直接先被编译出来,这样可以进一步加快速度。
matplotlib也是如此。如果我们从源代码构建它,可能就需要添加freetype,libpng,tk,pyqt,pygtk,wxpython等组件了。有了这些支持我们最终构建出来模块在被执行时所必需的程序,配置或接口实现等。
matplotlib的具体依赖可以查看INSTALL文档。与unix下面的其它文件基本相同。
- 编译模块
matplotlib里面实际上提供了一个Makefile文件。但是make help并没有显示出结果,也就不敢随便用它。按照上面的说明,编译的时候执行命令:
python setup.py build
这是很简单的。因为我们还在没有configure的时候就已经编译出来了,到最后我们应该把文件安装到哪个位置呢。C语言的库来说并不成问题,一来有configure的prefix指出目标目录,并且unix系统搜索C库的位置我们也是知道的。但是Python就不同了。我们可能安装的并不是标准位置。但是先不管它。
- 安装模块
安装模块实际上相当于保证主程序,也就是python里面在import命令被执行的时候能够找到相应的模块。一般来说,模块能不能被导入仅仅是取决于它们是否在搜索路径里面。而Python的搜索路径除了当前工作目录外,就是在安装Python的时候的标准的路径了。
不同的系统有不同的定义吧。在我的系统上/usr/lib64/python*里面有python的标准模块。但是仍然没有发现matplotlib被安装在了哪里。
可以通过sys模块的 exec_prefix 与path变量得到关于python解释器的一些信息。模块文件可以是.py, .pyc, .pyo, .pyd, .so. 结果按照这种要求。在/usr/lib64/python2.7/site-packges里面找到了matplotlib. 假设Python安装在了 $PREFIX 下,可执行程序在 $EXEC_PREFIX 。下面,那么一般先找 $PREFIX/lib/pythonX.X 文件夹(Python可以向系统提供自己格式的库文件),找 $PREFIX/lib/pythonX.X.zip
有的时候 $PREFIX/lib/pythonX.X/plat-linux2 也会被设置。动态加载模块的路径放在 $PREFIX/lib/pythonX.X/lib-dynload/ 下面。其它模块的默认安装路径一般是 $PREFIX/lib/pythonX.X/site-packages/ 。整个模块组织成了一颗树的形状。这颗树的根由库的搜索路径合并而成。每遇到一个子文件夹可能这颗树就向下延伸一层。
在sys模块里面的path变量里显示的是模块的ROOT的来源。而sys模块的本来含义并不是操作系统,而是Python解释器里的相关变量。
- 检查模块是否可用
这部分通常要运行一些测试脚本来完成。有时候如果没有的话,我们可以尝试导入我们安装的库,看看有没有异常出现。
自动测试应该还是有一些技术可言的。个人觉得应该使用脚本以及高度自动化的工具完成这些任务。说明一下,自己还想到使用m4宏处理器写一个简单的TeX前端,用于包含了复杂选项的TeX变成一些容易设置的选项的集合。
注:unix下面的应用程序都可以这么来看。一个应用程序的目录总是符合unix下面目录的规范的,库安装到 $PREFIX 的lib/下面,诸如这些规定。对于Python来说也是不例外的。因此对于matplotlib包来说,它不必什么都看Python安装在哪里。它可以认为它就是一个库,因此它的库与模块就安装在 $PREFIX/lib/python 下面,它的文档就安装在 /share/doc/$LIBNAME 下面。
关于IPython交互式解释器
matplotlib的pylab在运行show()时有时会不出现结果,那是因为我们当前可能并未关联到图形库。要想显示图片通常在shell里执行
ipython -pylab=qt
之后,使用
run $script_name
然后输出Python相应的代码进行。
使用IPython也算是能够提高工作的效率吧。不过也许只有在IPython里面才可以直接使用run命令了。这对于执行脚本是很有好处的。
在使用pylab的时候,绘图的后端决定了图片在哪里被显示。在ipython里面可以使用debug命令进入调试。
matplotlib的其它问题
其实可以使用setup.cfg对matplotlib的安装进行更详细的配置。我们不用从网上找资料。因为源代码包里的INSTALL等文档就是最好的说明。就连setup.py脚本也有很好的可读性。
也许以后自己应当学会从源码包里面读英文文档了。在网上找资料实在是太麻烦了。而且如果有可能,软件的使用教程也应当从附带的doc里面查找。
matplotlib绘图的基本方法
读过了书里的第5章的文档,觉得matplotlib的确很伟大。但是自己还是觉得不应当手动从无到有地使用pylab绘制图表,而是应当通过其它的科学计算软件调用它。这样绘制出来的图表才有意义。不然就纯粹是为了玩了。
我们不介绍其它的模块了。matplotlib是Python最著名的绘图库。但是pylab能在numpy或者scipy里面集成接口。
调试的方法
几乎每一本书都说Python的调试功能很强大。但是我却觉得Python的错误显示很复杂。大概是我不会使用堆栈吧。在ipython里面调试时,先运行程序。如果出现错误,程序会返回。这个时候调用debug返回到出错的时候的堆栈,使用u命令在堆栈中一直向上,直到出现本层次模块里的错误为止。
其实ipython的错误提示是我见过的最好最详细的提示了。中间有高亮又有各个源代码文件出错的行号。不过相比之下,python里的错误输出可能是最难读的了。可能是堆栈太多的时候必须有一定的提取文件中关键错误的方法吧。
ipython调试的时候显示的高亮什么的特性在Sagemath里也得到了应用。
matplotlib绘图的时候有一种基本的方法就是使用
import matplotlib.pyplot as plt这样可以直接使用pyplot模块提供的绘图函数功能。
把模块导入成对象,可以这么理解,导入一个对象相当于找到一个能够在运行期间为我们干活的人。这个人可以做相应的输出,我们可以调用它里面的相应方法,或者根据它的功能创建一个工作对象。
另一个则是使用matplotlib的pylab模块。其中包括了许多NumPy与pyplot模块里面的绘图函数,可以方便快捷地进行计算与绘图。pylab可以直接通过
import pylab as pl进行。
书里面实际上介绍了三种绘图的方法。有pyplot,pylab,这样直接调用模块的方法,也可以是调用pyplot里面的绘图API进行绘图。
pyplot的面向对象的绘图方法与机制
我们不如这样理解pyplot的工作过程。在刚开始的时候创建了一个模块访问对象,也就是在import pyplot as plt里面说明的plt这个名子。通过这个名子我们访问到绘图所需的一切要素。plt里面有自己的成员与数据,它的直接成员与数据通常都是用于调整绘图环境里面的配置的。真正绘图的时候,总是通过具体的绘图对象完成的。
我们不如称做是一个绘图对象关联了一个模块访问对象。我们可以通过plt创建,显示绘图对象,切换当前绘图对象这些操作。
绘图对象里面最基本的就是图表,其次是子图。当我们调用plt的绘图函数plot()的时候,总是在figure与axes对象上面绘制的。
一个模块访问对象plt里可以管理多个绘图对象。一个绘图对象里面也可以有多个子图。在pyplot里面,通过plt.figure(N)的方法访问指定序号的图表。当序号不存在的时候该图表会被自动创建。
如果我们在ipython里面测试,我们就会发现调用plt.figure(1)的时候会出现一个绘图窗口。接下来的绘图就是在这个窗口里面进行,而如果再调用plt.figure(2)就会创建另一个绘图窗口,里面有另一个图表。这时再调用plt.figure(1)并不会出现新的窗口。相当于模块会自动判断当前绘图区存在与否。
一个图表对象的类型是Figure。默认情况下,模块访问对象plt会创建一个图表,并将它作为当前的图表。plt的figure()函数也可以接受其它种类的参数。总而言之,plt的figure()函数完成的工作是创建图表,管理,导出当前绘图模块所属的某个图表对象。以及选择当前的模块访问对象绘图时所在的图表。
使用plt的gcf()函数获得模块的当前图表对象。类型是matplotlib.figure.Figure。无论以前面的哪种方式,返回值都是一个图表对象,我们就是在这个图表对象里绘制图表的。
这样一来,我们就不需要在figure里面绘图,然后再进行显示了。plt里面封装了访问当前figure的方法。调用名称与figure对象里的类似。
一个图表可能会有多个子图。子图用Axes对象来表示。pyplot并不是在一个Figure对象上直接绘图的,而是在一个Axes里面绘制函数的图象。plt模块封装的plot(),xlabel()等方法几乎都是针对于模块访问对象的当前子图而起作用的。
使用plt.gca()得到当前的子图。而使用plt.subplot()函数可以创建子图(实际上是在当前的Figure对象里面创建子图)。subplot的函数调用是subplot(Rows, Cols, Index)。该调用的含义是假设当前Figure对象被分成Rows*Cols的网格。使用编号为Index的区域绘制子图。Index的编号是从左到右,从上到下,编号从1开始。
如果Figure对象判断不同的subplot的区域有重叠,前面的被重叠的子图将会被清除掉以绘制新的子图。否则就继续添加新的图表。
函数subplot()返回它创建的Axes对象。调用gca(Object)可以使这个Axes()对象成为当前的对象。如果子图已经存在,subplot并不会将先前的子图覆盖,而是返回符合那个标号的子图。比如下面的代码:
plt.subplot(111)
plt.subplot(111)第二个语句并不会清除掉第一条语句里的subplot,而是返回第一条子图创建的对象。
当Figure与Axes对象都决定好之后,真正的绘图就开始了。
绘图的时候坐标系的选择
matplotlib设置了四组坐标系。各个坐标系的大略描述如下:
窗口坐标系: 左下为(0,0),右上为(W,H)。坐标以像素为单位。
图表坐标系: 左下为(0,0),右上为(1,1)。坐标以英寸为单位。
子图坐标系: 左下为(0,0),右上为(1,1)。本身是没有单位的。
数据坐标系: 根据不同的坐标系有不同的表达形式,在笛卡尔坐标系下面通常是\((XMIN, XMAX)\)到\((YMIN, YMAX)\)。本身没有单位。但是我们可以根据物理量来设置。
在屏幕输出的时候才用到窗口坐标系。我们不妨将图表坐标系看成是与平台无关的。决定了对象的实际的大小。
在实际绘图时,一旦终端被确定了,绘图程序的窗口坐标系也就相当于是确定的。于是根据这种关系,一个图表被显示到桌面上,或者是输出到一个文件当中。而单以纯数据表示而论,在运行的时候,所有的图形的位置在图表坐标系里面的安排都是固定的了。
不同坐标之间的变换都同样地依赖于本对象的二维仿射变换矩阵的定义。
假设ax是一个Axes对象。那么它有一个transData用于决定从数据坐标系到窗口坐标系的变换。函数
ax.transData.transform((3, 5))将返回点(3,5)在变成窗口坐标系后所在的位置。 注: 返回类型是一个ndarray对象。而且这个函数也可以一次调用返回多个点在窗口坐标系里面的位置。
下面我们以Figure下在的tranFigure变换为例了解Python的实现。
在交互式命令行下直接输入f.transFigure()将可以看到它里面的一些对象。其中第一项里面的Bbox描述了这个Figure的物理大小信息。比如\([0,0]--[8,4\),单位是英寸。而在Affine2D里面的就是那个变换矩阵了。经过分析不难发现,对角线上的第一个元素就是所谓的X方向分辨率,第二个元素就是Y方向分辨率。我们也可以通过直接查看 f.transFigure._boxout._transform 得到真正的变换矩阵。
上面的代码实际上还只是一个Affine2D对象。调用它的 get_matrix() 方法才能得到以numpy.ndarray形式表示的矩阵。
而Axes对象在Figure里面的位置可以通过 Axes.get_position() 方法得到。其结果是在图表坐标系里面的位置(注意Figure坐标系从左下角的(0,0)到右上角的(1,1))。如果子图是以2*3行分隔的,那么最后一个子图的坐标通常就是(0.66,0)-(1.0,0.5)。不过实际上子图与图表边缘之间还是有一定间隔的。
根据这一信息我们自己就可以计算出来Axes对象如何转换成窗口坐标系了。就是拿前面的坐标系,乘以Figure的变换函数。这步工作Python是不会每计算一个点就运算一次的。因为Axes提供了 ax.transAxes._boxout 对象,它里面存储了变计算后的结果。
一般来说,一个子图对象里面只有一个数据坐标系。于是我们可以通过Axes对象访问数据坐标系的transData对象。该对象指出了数据坐标系里的点如何进行变换。
transData由transLimits与transScale构成。transLimit描述了该数据坐标系的坐标范围,比如(-5,-5)-(2-3)。而transScale表示transData将数据坐标系转成Axes对象坐标系里面的缩放大小,通常都是1.于是数据坐标系里面的某个点转成一个窗口像素。
使用这些概念主要用于处理不现的坐标系表示方法,以及不同的刻度标准。
关于绘图操作
如何调用label,line,axis等对象这里就不说了,因为它们是一些很繁锁的东西。
matplotlib绘图的背后原理
matplotlib的绘图的三个层次(这种三层次模型也可以用在其它的语言里面)是:
backend_bases.FigureCanvas
backend_bases.Renderer
artist.ArtistRenderer与Canvas知道如何处理底层的绘制操作,比如在QT界面上绘图或者使用PostScript在PDF文件里面作图。Artist对象处理所有的高层的结构,如图表,文字与曲线等绘图元素的绘制与布局。通常我们只是与Artist对象打交道,而不需要关心底层是如何实现绘图的细节的。
Artist对象有简单类型与容器类型两种。有点像是GUI里面的Component.简单类型的Artist对象是标准绘图元件,如Line2D, Rectangle, Text, AxesImage等。但是容器类型则包括了其它的简单对象,如Axis, Axes, Figure等。我们不如把Artist看成是一个桌面绘图管理器。那么以前所学过的Metapost语言便就是用于产生这些复杂对象的绘图原语言。它们能够在更底层的意义上提供编程方法,因而更容易绘制出来其它的对象。
Asymptote与Artist相比,多的只是一种灵活的方式。Artist虽然也是用编程语言实现,但是封装的内容与对象比较繁杂,底层不够清晰。而Asy使用清晰的底层数据结构,让我们可以自由地决定插值等操作。
我们也可以直接使用Artist对象绘图。利用Artist的特性的关键在于我们使用Artist提供的许许多多绘图对象,通过调用它们的方法设置它们的属性,进而描述出图形里面各个元素的关系。
一个Axes对象里面包含了其它的简单的对象,因为Axes是容器类型。使用Axes的lines可以得到在该子图里面的所有曲线列表。我们可以通过该函数返回对于这个曲线的引用以便我们能够单独地调整该line的属性。
Figure对象与Axes对象都有一个patch属性作为它的背景。这向我们说明Figure对象对于绘图的理解是描述性的,只有在调用实际的绘图引擎的时候,才会将背景显示出来。该背景是一个Rectangle对象。通过它我们可以设置背景的背景颜色,透明度等等属性。
Artist的对象有一些通用的属性,比如透明度alpha, label, visible等。所有的属性都可以通过 get_ 方法或 set_ 方法读写。而可以通过任何一个Artist对象的set()函数与get()函数设置一个对象的多个属性。
模块访问对象提供了getp()函数用于返回一个Artist对象的各种属性。比如通过 plt.getp(plt.gcf())我们就可以得到当前图表对象的所有属性名与值。在交互式ipython里面我们可以参考这些输出通过前面说过的set方法加以改变。
在matplotlib里面,Axes是绘图的核心。它包含了许许多多的Artist可显示对象。
matplotlib的配置文件
matplot工作是类似一个应用程序。检查配置文件的顺序是,当前配置文件,用户家目录下的配置文件,应用程序里面的配置文件。配置文件实际上是一系列的变量与值。在依次读取这些配置文件的过程中,如果前面的配置文件已经设定了这个值了,那么后面配置文件里面的值就不再生效。于是配置文件的优先级是当前目录最高的。
配置文件的读取也有一些规律。Bash从/etc里面读取配置,最终也是用户目录里面的配置脚本生效的。不如引入配置文件优先级这个概念。一个应用程序在工作的时候,假设从一列可选的列表里读取每一个配置文件。高优先级的配置文件是说,如果配置项目出现在某一个配置文件里面,而其它配置文件里面有相同的配置项目的时候,前者会对程序起到真正的作用。于是Bash里的配置文件中,系统目录是第一读取的,并具有最低的优先级。matplotlib里面,系统目录是最后读取的,具有最低的优先级。世界真是奇妙。
matplot配置文件可以通过 matplot.get_config_dir 得到当前生效的路径,使用 matplotlib.matplotlib_fname() 得到最优先的那个配置文件。 而 matplotlib.rc_params() 用于读取配置文件里的每一项(默认是返回当前使用的配置文件里面的项目), matplotlib使用rcParams变量保存当前的配置。如果要修改,可以直接令
matplotlib.rcParams[$hash_key] = $value以让参数成为当前绘图参数。
matplotlib.rc()函数接受一些参数设置并将它写入rcParams变量。如果要恢复默认的配置文件里面的内容,可能需要rcdefaults()选项。
显然matplotlib是不支持直接从matplotlib里面直接修改配置文件里的内容的。因为这些配置文件可能权限比较高,或者干脆就是系统目录下的配置文件,不允许用户修改。
在实际的应用中使用一个库
在python里面导入模块使用import命令。而使用reload(modulename)可以重新加载这个模块(让里面的数据复原)。
中文字体的显示
在matplotlib里面一个是使用Fontmanager选择字体。这对于有些绘图方法特别有用。比如plot()的xlabel()这些函数,都可以接受一个font=可选参数。这个时候选择一个字体属性就可以了。
但是这种方法明显的缺陷是缺乏统一性。如果我们需要绘制多种图,或者需要学习多种图的绘制参数,每一个都要学习就变得代价太高了。所以我们还是用统一的方法吧。
统一的方法是matplotlib的rcParams参数。这些参数让我们选择字体的字族等参数。具体可以通过rcParam.keys()找到。字体大小也可以找得到。如果我们要显示中文。那么我们应当检查以下的做法是否被完成了。
1.虽然Python对于unicode的支持很好。可以直接通过u“”使用unicode字符串。但是这样还是不能够保证直接解析出来多字节编码。尤其是采用unix的magic来运行脚本的时候,编码必须被另外指定。这种方法就是所谓的W3C编码指定方法。
这种方法比较自由,也就是在前面的几行里面出现#-*- coding: utf-8 -*-这样的字符就可以了。下面的编码就会自动被认为是unicode文本并采用了utf-8编码。
2.需要支持中文的字体才能显示出来中文字符。如果没有这样的字体,通常并不是显示乱码,而是是空格或者方框代替。但是一个字体里面总是只包含特定的几个语言里的编码,很少有字体可以包括所有的文本。于是换字体似乎是必然的。不幸的是,Python没有LaTeX那样的复杂的字体种类。同一时间加载的只有一个字体文件。所以我们如果要使用不同字符区域位置的字体,最好还是自己换用字体。
3.系统下使用fontconfig管理字体。大概其它的应用程序也使用了这样的接口,所以可以使用某种字体名,而不需要通过字体文件访问指定的字型。如果我们要改变matplotlib的文件,除了通过fontconfig查询系统字体之外,大概也能够使用fc-list管理字体文件。
4.当将字体嵌入到图表的时候,注意字体的大小。这个是很关键的。对于显示效果有重要的影响。一般而言,如果我们要在图表里面使用字体,一定要确定我们希望图表的输出大小。这个问题在下面的笔记中会讲到。
讲求实际大小在计算机可以自由放缩文本的时候似乎显得有点过时。但是人的眼睛视野大小总是一定的。我们虽然可以放大与缩小图象。但是同一时间内我们的焦点只是集中于图象的某一区域。这个时候采取放大镜的做法也许对我们更好一点。虽然我们可以这么做。但是随意地放大与缩小字体还是缺少一种科学上的价值。我们应该时该记着我们想输出的字体是有多大的。
实际上这些问题大概还是视觉范围的问题。比如我们在看书的时候,因为离得近,虽然很小,但是也能看清楚。可是如果是在屏幕上,那么小的字体就不行了。我们不妨做一个计算。假设我们眼睛离书是30厘米。而字体的大小是11pt。换算成厘米表示,字体的大小就是0.38cm.也就是说,我们平常见到的印刷体也就是0.4cm左右的大小。但是如果是在屏幕上显示,我们的距离变成了80cm.这时的11pt相当于在30cm处看到一个0.15cm大小的块。于是我们可以说,我们的眼睛实际上可以看到小的物体。但是如果我们一直使用较小的字体,对于我们的眼睛也会造成一些压力。大概这就是为什么使用电脑伤害更大吧。
原来自己对于这些东西一直没有什么概念。但是现在才发现问题的所在。那么以后在使用显示屏的时候,就要注意到自己是在多远的距离下看多大的物体。其实距离这么远的话,将屏幕的字体调大一些也是很合理的。
原来的时候自己一直以为在纸上是多大,在显示屏上就应该是多大。这样自己的感觉会好一些。但是今天终于发现,原来显示屏上的内容是不可以相信阅读效果的。但是由于显示屏上照样以11pt的大小显示,那么我也就没有什么办法了。可惜的是,计算机在这么大的时候分辨率不够。
注:业界总是认为高分辨率屏幕没有什么作用。但是它们的确有很大的作用。因为我们通常在显示屏上看到的并不是与看书时文本的大小,所以如果分辨率更高一些,就能够以更华丽的字体显示。而且,图片的大小也可以进行调整。
注:如果我们不使用桌面显示器。那么最终的效果应当是我们每天都在看书。
关于绘制饼状图
也许饼状图在科学计算里面遇到的并不多。但是在人际交流里面用的还是很多的。这些活动包括政治活动,商业活动。反正是在向不是一行的人解释东西的时候很有用。
饼状图调用的是pie()函数,它与plot()函数的作用是类似的。但是pie()函数只给出了一个返回值,而且输出的结果不可进行广泛调整的。比如它就不支持传入font=参数,以致于我们必须得事先设置rcParams.
饼状图在显示比例上是很好的。它的主要参数是一列正则化的数据。是数值类型的。至少可以计算出来一个百分比。一般来说,还需要一列标签文本,以辅助显示。至于阴影线与突出显示,就没有那么重要了。
文档与绘图,是一系列基础的技能。它相当于古代能够写字的人与不会写字的人之间的区别。只有自己能够创造出来这些东西,才相当于有了这样的表达工具,不然就只是一个平平常常,只能从事体力劳动与重复劳动的人。其工作也就不能显示出任何的创造性。
ENTHOUGHT公司的几个科学计算软件
这个公司的软件还是比较难得到的。我们要首先知道git.但是git对于断点续传的支持是很差的,所以我们就要在国内这么差的网络上进行数据的处理了。于是我们就很难得到。但是我们得到以后还得看说明去安装它。为此应当先去构建它。在构建过程中有几个库我们的机器上可能是很难得到的。
现在知道,ETS需要至少需要freeglut,vtk,swig,hg这些软件。但是通常情况下不可能是完备的,于是我们通过逐步测试build的方式解决这一系列的问题。
Cython以及相应的distutils库也是Python所需要的。这些库应当受到足够的重视。
国内的现状大致如此。为了更好地研究一个问题,有时候必须采取一些极端的手段才行。可是这些手段有时候让人追寻了好久好久。最后找到的还是一个不全面的解答。我想自己需要静下来多想一想为什么。
Matplotlib的设置
默认方法仍然是使用.matplotlibrc文件。这样输出的文件比较不错,而且也可以避免在运行脚本的时候花很长时间处理图表参数。
Matplotlib示例
好久没有使用过Matplotlib绘图了,里面的有些东西都忘记了,实在不应该啊。现在是得好好学习的时候了,因为现在及以后会使用很多这样的方法的。
首先是matplotlib的配置问题。这是一个.matplotlibrc文件决定的。配置的方法可以参考matplotlib的官方网站http://matplotlib.org/users/customizing.html。在实际中我们用到的更多的是对于图形的大小的控制。因为我们要输出文件放入到文章当中。其中的选项figure.figsize, figure.dpi, savefig.dpi, savefig.format是在matplotlibrc里面应该指定的。不然每次输出的时候都可能要设置一下,太麻烦了。
折线图
Matplotlib最简单的方法应该是用折线顺次连接起来 \(y\) 轴上的数据了。这个时候 \(x\) 轴对应的坐标就是元素在列表中出现的次序。代码与效果分别如下:
#!/usr/bin/env python
# Plot a list of numbers with pyplot
import sys
import re
import matplotlib.pyplot as plt
plt.plot([1,2,3,4])
plt.ylabel('some numbers')
plt.savefig('../img/'+re.sub('.py$','.pdf',sys.argv[0]))
image
散点图
散点图只不过使用了两个数组。另外,还可以接受点的形状作为第三个可选的参数。使用axis选项可以设置坐标轴的显示范围。
#!/usr/bin/env python
import sys; import re
import matplotlib.pyplot as plt
plt.plot([1,2,3,4],[1,4,9,16],'ro')
plt.axis([0,6,0,20])
plt.savefig('../img/'+re.sub('.py$','.pdf',sys.argv[0]))
image
代码中的ro代表使用红色圆点来表示。与MATLAB有几分相似。其它的选项还有,r-- 代表红色虚线,bs 代表蓝色方块,而g^代表绿色三角形。
import sys
import re
import numpy as np
import matplotlib.pyplot as plt
# every sampled time at 200 ms intervals
t = np.arange(0., 5., 0.2)
# red dashes, blue squares and green triangles
plt.plot(t,t,'r--', t,t**2,'bs', t,t**3,'g^')
plt.savefig('../img/'+re.sub('.py$','.pdf',sys.argv[0]))
image