Avizo用户使用手册-11
[TOC]
Chapter 11
11 自动化、定制、扩展
11.1 模板项目
本节描述模板项目(Template Projects)的用法。
11.1.1 模板项目说明
模板项目可用于简化在一组相似数据上的重复性任务。模板项目是某个原始项目的副本,它可以被重新应用到同类型的其他数据上。
11.1.1.1 如何保存模板项目
要创建模板项目,请从File菜单中选择Save Project As Template。会出现一个输入选择对话框,列出所有可能的模板输入(即当前所有的数据对象)。模板输入代表一个在该模板被执行时必须提供的数据集。你可以更改每个模板输入的标签。该标签应当是通用且有意义的,因为它会在模板执行期间被显示出来。默认标签是原始数据对象的名称。注意:未被使用的数据对象默认会被过滤掉,但你可以通过选择Include unused data选项把它们包含进模板项目中。
如果该模板恰好只包含一个输入,会有一个对话框询问你是否希望把该模板与这种数据类型关联起来。如果你单击OK,那么该模板将对所有同类型的数据对象在其右键菜单(Templates子菜单)中可用。
最后,会出现一个文件对话框来命名输出文件。该文件名也就是模板的名称,即将出现在Templates菜单中的名称。内置的模板项目存储在文件夹share/templates中,但你可能没有足够的权限在该目录中创建新文件。
图 11.1:模板项目保存对话框。
图 11.2:如果模板只有一个输入,则可以进行数据类型关联。
你可以把自定义模板保存在任何目录中。它们会在每次Avizo启动时被自动重新加载。
11.1.1.2 如何使用模板项目
内置的模板项目和已知的自定义用户模板项目会在Avizo启动时被自动加载。加载模板并不意味着实例化该模板项目。模板项目只在用户需要时才被创建,例如通过Project > Create Object...菜单。有一个例外:如果用户通过Open Data对话框加载某个模板文件,该模板资源会被加载,然后被执行。
如果该模板与某种数据类型相关联,你可以使用该类型数据对象的右键菜单来创建一个实例。在这种情况下,该模板会立即使用所选的数据对象被创建出来。
对于其他模板,你可以从Project > Create Object...菜单的Templates子菜单创建一个实例。该模板也可能出现在宏按钮列表中。在这种情况下,模板执行时会出现以下对话框:
图 11.3:模板项目运行对话框。
每个模板输入都会显示其模板输入名称,以及一个用于选择将被用于该输入的数据集的组合框。每个组合框中列出的候选项会按其数据类型进行过滤。你可以通过取消选择Check input type选项来禁用该过滤,从而显示Project View中存在的所有数据。如果没有合适的数据对象,该组合框将为空。你总是可以选择<load file...>项来显示一个文件打开对话框并选择某个数据文件。
对颜色图的特殊处理:默认情况下,已经在Project View中的颜色图会被按原样重用。这意味着,例如模板项目中的对象可能会受到范围变化的影响。你也可以通过选择Independant colormaps选项,选择不与已有对象共享颜色图。
11.2 配方
Avizo允许创建用户自定义的配方(recipes),用于自动化某个复杂场景,其中会用到多个工具和工作区。这些配方定义高层次的工作流,例如从图像中提取用户自定义的统计信息。更多信息请参阅第5章 创建配方以自动执行工作流。
11.3 Avizo启动
本节描述可用于Avizo启动的一些选项:
Command Line Options命令行选项Environment Variables环境变量Avizo start-up scriptAvizo启动脚本
11.3.1 命令行选项
本节描述Avizo所能识别的命令行选项。一般来说,在Unix系统上,Avizo是通过位于子目录bin中的start脚本启动的。通常,该脚本会被链接到/usr/local/bin/Avizo或类似位置。此外,用户也可以定义一个指向bin/start的别名Avizo。
在Windows系统上,Avizo通常通过开始菜单或桌面图标启动。不过,也可以通过调用bin/arch-Win64VC12-Optimize/Avizo.exe来直接调用Avizo可执行文件。在这种情况下,所能识别的命令行选项与Unix系统上相同。
Avizo的语法如下:
1 | Avizo [options] [files ...] |
在命令行中指定的数据文件会被自动加载。除数据文件之外,也可以指定脚本文件。这些脚本将在程序启动时被执行。
支持以下选项:
-help:打印命令行选项的简短摘要。-version:打印Avizo的版本字符串。-no_stencils:告知Avizo不要在其3D图形窗口中请求模板缓冲区(stencil buffer)。在某些低端PC显卡上,可以设置该选项以利用硬件加速。-no_overlays:告知Avizo不要在其3D图形窗口中使用覆盖平面(overlay planes)。如果你在远程显示上重定向Avizo时遇到问题,请使用该选项。-no_gui:在不打开任何窗口的情况下启动Avizo。该选项对于在批处理模式下执行脚本很有用。-logfile filename:使控制台窗口中所打印的任何消息同时被写入指定的日志文件。特别是与-no_gui选项结合使用时很有用。-depth number:该选项仅在Linux系统上受支持。它指定深度缓冲区的首选深度。Linux系统上的默认值是16位。-style={windows | motif | cde}:该选项设置Avizo的Qt用户界面的显示风格。-debug:该选项仅适用于开发者版本。它会使本地包以调试模式执行。默认情况下将使用优化后的代码。-cmd command [-host hostname] [-port port]:向一个正在运行的Avizo应用程序发送Tcl命令。可以选择性地指定主机名和端口号。在命令能够被接收之前,你必须在Avizo的控制台窗口中键入app -listen。-clusterdaemon:在集群从节点上作为VR守护进程启动(Avizo XScreen Extension)。它可能会被某个服务所替代。更多信息参见在线文档。-tclcmd command:在启动中的应用程序中执行该Tcl命令。-edition { LiteEdition | AvizoEdition | FEIEdition }:以特定的版本启动Avizo。
11.3.2 环境变量
执行Avizo并不需要特殊的环境设置。在Unix系统上,某些环境变量(例如共享库路径或AVIZO_ROOT目录)由Avizo的启动脚本自动设置。用户也可以设置其他环境变量以控制某些功能。这些变量列在下面。在Unix系统上,环境变量可以使用shell命令setenv(csh或tcsh)或export(sh、bash或ksh)来设置。在Windows上,环境变量可以在系统属性对话框(Microsoft Windows)中定义。
AVIZO_DATADIR:一个数据目录路径。该目录将被用作文件对话框的默认目录。请注意,为了快速访问多个位置,你可以使用操作系统,例如把目录添加到文件对话框的收藏位置列表中,或者使用一个包含指向其他目录的快捷方式或链接的目录。AVIZO_TEXMEM:以兆字节为单位指定纹理内存的数量。如果未设置该变量,系统会应用某些启发式方法来确定某个系统上可用的纹理内存数量。不过,这些启发式方法可能并不总是产生正确的值。在这种情况下,可以使用该变量来改善Volume Rendering模块的性能。AVIZO_MULTISAMPLE:在高端图形系统上,默认使用多重采样视觉。通过这种方式实现了高效的场景抗锯齿。如果你想禁用该功能,请把环境变量AVIZO_MULTISAMPLE设为0。请注意,在其他系统上(特别是PC上),抗锯齿无法由应用程序控制,而必须直接在图形驱动程序中激活。AVIZO_NO_LICENSE_MESSAGE:默认情况下,当你的Avizo许可证即将到期时,Avizo会向控制台发出警告消息。这使你能够及时采取行动,以免在许可证到期时你对Avizo的使用被意外中断。要禁用这些消息,请把该变量设为1。AVIZO_NO_OVERLAYS:如果设置了该变量,Avizo将不会在其3D图形窗口中使用覆盖平面。同样的效果也可以通过-no_overlays命令行选项获得。如果你在远程显示上重定向Avizo时遇到问题,或者你的X服务器不支持覆盖视觉,请关闭覆盖平面。AVIZO_NO_SPLASH_SCREEN:如果设置了该变量,Avizo在初始化期间将不显示启动画面。AVIZO_LOCAL:指定包含用户自定义模块的本地Avizo目录的位置。在该目录中定义的IO例程或模块会替换主Avizo目录中所定义的那些。该环境变量会覆盖在开发向导中所设置的本地Avizo目录(详情参见Avizo程序员指南)。AVIZO_SMALLFONT:仅Unix系统。如果设置了该变量,即使屏幕分辨率为1280x1024或更高,Properties Area中所显示的所有端口也会使用小字体。默认情况下,只在分辨率较小时才使用小字体。AVIZO_XSHM:仅Unix系统。如果你想抑制在Avizo的Segmentation Editor中使用X共享内存扩展,请把该变量设为0。AVIZO_SPACEMOUSE(已弃用):该功能已被弃用。如果Avizo找到一个已连接的设备,默认情况下Spacemouse支持是可用的(参见 http://www.3dconnexion.com )。如果驱动程序已安装,控制台窗口中会打印一条消息。使用spacemouse,你可以在3D查看器窗口中导航。支持两种模式:旋转模式和飞行模式。你可以通过按下spacemouse的按钮1或2在两种模式之间切换。在Avizo.init文件中可能提供更多配置选项。3Dconnexion Spacemouse的限制:
- Spacemouse支持在Mac OS X上不可用。
- Spacemouse被Avizo/AvizoInline应用程序识别。
- 六自由度运动尚未得到完全支持。
- Spacemouse只能控制第一个查看器。
- 在旋转模式下无法平移相机或上下移动。
- 在飞行模式下无法绕对象旋转或上下移动。
- 默认情况下,按钮1用于打开”菜单”,必须把它重新配置为”Button 1”功能。按下该按钮可设置旋转模式。
- 默认情况下,按钮2未被设为”Button 2”功能。按下该按钮可设置飞行模式。
AVIZO_STEREO_ON_DEFAULT:如果设置了该变量,3D查看器默认将以OpenGL原始立体模式打开。通过这种方式,可以避免在从单视场切换到立体模式时本来会出现的某些屏幕闪烁。目前,该变量仅在Unix系统上受支持。TMPDIR:该变量指定临时数据应被存储在哪个目录中。如果未设置,此类数据将在/tmp下创建。除其他用途外,该变量会被Avizo的作业队列所解释。
11.3.3 用户自定义启动脚本
可以通过提供一个用户自定义的启动脚本,以某些方式定制Avizo。默认的启动脚本名为Avizo.init,位于Avizo安装目录的子目录share/resources/Avizo中。每次程序启动时都会读取该脚本。除其他事项外,该启动脚本负责注册文件格式、模块和编辑器,以及加载默认颜色图。
如果在当前工作目录中找到一个名为Avizo.init的文件,则会读取该文件而不是默认的启动脚本。如果找不到这样的文件,在Unix系统上会检查用户主目录中是否存在一个名为.Avizo的启动脚本。
一个用户自定义启动脚本的示例大致包含以下内容:先用source $AVIZO_ROOT/share/resources/Avizo/Avizo.init 0执行系统的默认启动脚本;然后用viewer 0 setBackgroundMode和viewer 0 setBackgroundColor设置均匀的黑色背景;用help setFontSize为帮助浏览器选择非默认的字体大小;最后定义一个proc onKeyF3 { } { ... }过程,在其中调用viewer setCameraOrientation、setCameraPosition和setCameraFocalDistance来恢复相机设置。
在这个示例中,系统的默认启动脚本首先被执行。这确保所有Avizo对象都被正确注册。然后进行一些特殊设置。最后,为功能键[F3]定义了一个热键过程。你也可以为任何其他功能键定义这样的过程。此外,还可以定义诸如onKeyShiftF3或onKeyCtrlF3之类的过程。这些过程会在按下功能键并同时按住[SHIFT]或[CTRL]修饰键时被执行。
11.4 图像堆栈处理(ISP)与图像体积处理(IVP)配方
Image Stack Processing和Image Volume Processing模块允许在一个专门的工作间中创建和执行图像处理配方。
更多信息请参阅为图像数据创建图像处理工作流一章。
11.5 TCL脚本编写
本节描述如何在Avizo中使用TCL脚本编写。
11.5.1 脚本编写简介
本章仅面向高级Avizo用户。如果你不知道什么是脚本编写,那么很可能你并不需要本章所描述的功能。
除了通过图形用户界面进行交互式控制之外,Avizo的大部分功能也可以使用特定命令来访问。这使你能够自动化某些流程,并创建用于管理例行任务或进行演示的脚本。Avizo的脚本命令基于Tcl,即Tool Command Language。这意味着你可以使用带有Avizo特定扩展的Tcl来编写命令脚本。
Avizo命令可以被键入到Avizo控制台窗口中,如第10.1.13节所述。直接键入控制台窗口的命令会被立即执行。此外,命令也可以被写入一个文本文件,之后作为整体执行。
本章的组织如下:
第11.5.2节(Tcl简介)给出Tcl脚本语言的简短介绍。本节不太具有Avizo特定性。
第11.5.3节(Avizo脚本接口)说明与脚本编写相关的Avizo特定命令和概念。这包括一份全局命令参考。
第11.5.5节(Avizo脚本文件)说明编写和执行脚本文件的不同方式,包括对脚本对象、资源文件和功能键绑定Tcl过程的引用。
第11.5.6节(配置弹出菜单)描述如何使用脚本命令配置某个对象的弹出菜单,以及如何创建导致某个脚本被执行的新条目。
第11.5.7节(注册拾取回调)描述如何把脚本回调附加到对象或查看器上,并在用户拾取事件时被调用。
第11.5.8节(Tcl中的文件读取器)描述如何注册一个用Tcl实现的自定义文件读取器。
第11.5.9节(创建符合配方的脚本对象)描述如何创建一个可用于创建配方的脚本对象。
第11.5.10节(脚本对象的版本管理与向后兼容性)描述向后兼容性方面的考虑,并列出所有带有已弃用端口的模块。
11.5.2 Tcl简介
本章给出Tcl脚本语言的简短介绍。如果你熟悉Tcl,可以跳过本节。不过,请注意:为了向Avizo控制台输出,你应当使用echo命令,而不是puts命令。
本章并不打算涵盖该语言的所有细节。关于Tcl语言的完整文档或参考手册,请参阅Tcl的创建者John K. Ousterhout所著的Tcl and the Tk Toolkit之类的教科书。与许多关于Tcl的书籍一样,该书也涵盖了Tk GUI工具包。请注意,Avizo中并未使用Tk。
此外,你也可以很容易地在互联网上找到Tcl文档和参考手册,例如在 http://www.scriptics.com ,或者用搜索引擎查找Tcl tutorial或Tcl documentation之类的关键词。
当你把Tcl命令键入Avizo控制台时,一按下回车键它们就会被执行。请使用Avizo控制台所提供的补全和历史功能,如第10.1.13节(控制台窗口)所述。
11.5.2.1 Tcl列表、命令、注释
首先,请注意Tcl是区分大小写的:set和Set并不相同。
一条Tcl命令是一个以空格分隔的单词列表。第一个单词代表命令名,所有后续单词都被当作该命令的参数。作为一个例子,试试Avizo特定的命令echo,它会把其所有参数打印到Avizo控制台。
Tcl命令可以用分号(;)或换行符分隔。因此,两条连续的echo命令既可以写在一行内用分号隔开,也可以分写两行。
在Tcl代码中,除了命令之外,你也可以放置注释。注释以井号字符(#)开始,到下一个换行为止结束。
11.5.2.2 Tcl变量
Tcl中可以使用变量。变量代表某个特定的状态或值。使用Tcl代码,可以查询、定义和修改该占位符的值。要定义一个变量,请使用命令:
1 | set name value |
例如set i 1或set myVar foobar。
请注意,在Tcl内部,所有变量都是字符串类型。由于set命令要求恰好一个参数作为变量值,因此你必须为包含空格的值加上引号:既可以用双引号set Output "Hello World",也可以用花括号set Output {Hello World}。
为了替换名为varname的变量的值,必须在该名称前放一个$符号。表达式$varname会被该变量的值替换。在上述定义之后,echo $Output就会打印出Hello World。
在控制台窗口中,echo "$i.) $Output"会产生输出1.) Hello World。请注意,变量替换对用双引号"括起的字符串会执行,而对用花括号{}括起的字符串则不会。花括号括起的字符串中甚至允许包含换行符。不过请注意,无法在Avizo控制台中键入多行命令。
11.5.2.3 Tcl命令替换
要在Tcl中进行数学计算,你可以使用命令expr,它会对其参数求值并返回该表达式的值。例如expr 5 / ( 7 + 3)或expr $i + 1。
为了在后续命令中使用像expr这样的命令的结果,必须使用一个重要的Tcl机制:命令替换,用方括号[]表示。任何被方括号[]括起的列表都会先作为一条独立的命令被执行,然后[...]这个构造会被该命令的结果所替换。这类似于Unix命令外壳中的'...'构造。例如,为了把变量i的值增加1,你可以使用set i [expr $i + 1]。
当然,命令表达式可以任意嵌套。执行顺序总是从最内层的方括号对到最外层,例如echo [expr 5 * [expr 7 + [expr 3+3]]]。
11.5.2.4 Tcl控制结构
其他重要的语言元素是if-else构造、for循环和while循环。这些构造通常是多行构造,因此无法方便地键入到Avizo控制台中。如果你想尝试下面所示的示例,请用你选择的文本编辑器把它们写入一个文件(例如C:\test.txt),然后通过键入source C:\test.txt来执行该文件。
我们从if-then机制开始。它用于有条件地执行某些代码,仅当某个表达式求值为”真”(意味着值不等于0)时才执行。其基本形式是:
1 | if {$a < $b} { |
elseif和else部分是可选的。可以使用多个elseif部分,但只能有一个if和一个else部分。
另一个重要的构造是条件循环。与if命令一样,它也基于检查一个条件表达式。与if不同的是,只要该表达式求值为真,条件代码就会被多次执行:
1 | for {set i 1} {$i < 100} {set i [expr $i*2]} { |
事实上这段代码与以下代码等价:
1 | set i 1 |
这两个循环都会产生输出1, 2, 4, 8, 16, 32, 64。
如果你想对一个列表的所有元素执行循环,还有另一个非常方便的命令:
1 | foreach x {1 2 4 8 16 32 64} { |
这会生成与前一个示例相同的输出。请注意,被花括号括起的表达式是一个以空格分隔的单词列表。
11.5.2.5 用户自定义Tcl过程
在Tcl中,使用proc命令来定义一个新的函数或过程。proc接受两个参数:一个参数名列表,以及待执行的Tcl代码。一旦某个过程被定义,就可以像使用任何其他Tcl命令一样使用它:
1 | proc computeAverageA {a b} { |
如你在示例中所见,参数列表定义了可以在过程体内使用的局部变量的名称(例如$a)。return命令用于定义该过程的结果。这个结果就是在命令方括号替换[]中所使用的值。
如果你想定义一个参数个数可变的过程,就必须使用特殊的参数名args。如果参数列表中只包含这一个单词,那么新定义的命令将接受任意个数的参数,而这些参数会作为一个名为args的列表传入:
1 | proc computeAverage args { |
在这个示例中,llength命令返回args列表中所包含的元素个数。
请注意,在该过程中定义的变量result具有局部作用域,这意味着它在该过程体之外是不可知的。同样,在过程内部也不知道全局定义的变量的值,除非该全局变量已使用关键字global声明:
1 | set x 3 |
关于过程还有很多可说的内容,例如参数传递、在过程之外的上下文中求值命令等等。关于这些高级主题,请参阅Tcl参考书籍。
11.5.2.6 列表与字符串操作
最后,在这个简短的Tcl介绍的末尾,我们回到列表这个概念。基本上,Tcl中的一切都是用列表构造的,因此了解最重要的列表操作命令以及理解一些微妙的细节非常重要。
下面是一个示例,说明如何取一个数字输入列表,并构造出一个输出列表,其中每个元素都是输入列表中相应元素的两倍:
1 | set input [list 1 2 3 4 5] |
你可以把列表看作简单的字符串,其中列表元素之间用空格分隔。这意味着你可以在不使用列表命令的情况下,达到与前一个示例相同的结果:
1 | set input "1 2 3 4 5" |
append命令与lappend类似,但它只是在一个已有字符串的末尾追加一个字符串。当你开始嵌套列表时,列表操作会变得复杂得多。嵌套列表用嵌套的花括号对来表示,例如:
1 | set input {1 2 {3 4 5 {6 7} 8 } 9} |
该命令的结果将是
1 | 1 |
请注意,在构造列表时,Tcl会自动对不是单个单词的字符串加上引号。下面是一个示例:
1 | set i [list 1 2 3] |
将产生如下输出
1 | 1 2 3 {4 5 6} |
你可以使用lindex命令来访问列表中的单个元素。lindex接受两个参数:列表,以及所需元素的索引号(从0开始):
1 | set i [list a b c d e] |
将产生结果c。
11.5.3 Avizo脚本接口
虽然Tcl语言本身并不是内在面向对象的,但Avizo的脚本接口是面向对象的。Avizo Project View中的每一个对象都对应一条命令。此外,还有若干全局命令(global commands)与Avizo中的全局对象相关联,例如查看器(viewer)或Avizo主窗口(main window)。
与Project View中某个对象相关联的命令(例如一个”Ortho Slice”模块或一个”Isosurface”模块)只在该对象存在期间存在。这些命令与Project View中所显示的该对象的名称完全相同。通常,某个特定对象的脚本接口包含许多不同的函数。Avizo中与对象相关的命令的一般语法是
1 | <object-name> <command-word> <optional-arguments> ... |
例如,如果存在一个名为”Global Axes”的对象(从Avizo菜单中选择View/Axis),那么你就可以使用如下命令
1 | "GlobalAxes" deselect |
注意:模块会被重命名为驼峰式大小写(camel case)。在命令中,这三种写法都是可行的:”Global Axes”、”GlobalAxes”或GlobalAxes。
请记得使用Avizo控制台所提供的补全和历史功能(如第10.1.13节(控制台窗口)所述)来减少键入量。
如果你已经使用过Avizo,你会注意到一个Avizo模块的参数和行为是通过端口(ports)来控制的。当模块被选中时,端口提供了一个用于更改其值的用户界面。所有端口也都可以通过命令接口来控制。其一般语法是
1 | <object-name> <port-name> <port-command> <optional-arguments> ... |
例如,对于”Global Axes”,你可以键入
1 | "GlobalAxes" options setValue 1 1 |
当你键入这些命令时,你会注意到用户界面中的值会立即改变。不过,模块的compute方法不会被调用,除非使用fire命令显式地触发该模块。这使你能够先为多个端口设置值,而不必在每条命令之后都重新计算一次。不过请注意,某些模块会自动重置它们的一部分端口,例如当一个新的输入对象被连接时。在这种情况下,你可能需要在设置完每一个端口的值之后都调用一次fire。
通常,端口的名称与图形用户界面中所显示的文本标签相同,只是去掉了空白字符,并且命令名以小写字母开头。要找出某个特定模块所有端口的名称,请使用命令
1 | <object-name> allPorts |
几乎所有端口都提供setValue和getValue命令。当然,参数的个数和语法取决于具体的端口。
<object-name> <port-name> setValue ...这种类型的命令,构成了一个典型Avizo脚本的90%以上。不过,除了端口命令之外,许多Avizo对象还提供额外的特定命令。当模块被选中时,可以通过单击Properties Area中相应的?按钮来快速访问某个特定工具的命令接口。
作为一个快捷帮助,只输入某个对象的名称而不带其他选项,就会显示该对象所有可用的命令。请注意,这也会显示未写入文档的、未发布的和实验性的命令。为了获得关于某个特定模块或端口命令的更多信息,你可以把它键入控制台窗口而不带任何参数,然后按F1键。这会打开帮助浏览器并显示该命令的说明。
Avizo对象是某个类层次结构的一部分。与C++编程接口类似,脚本命令也会被派生类从其基类继承。这意味着某个特定对象(例如坐标轴对象)除了自身特定的命令之外,还会提供其基类中所有可用的命令。指向基类命令的链接在模块的文档中给出。
11.5.3.1 预定义变量
Avizo Tcl中存在一些预定义的、具有特殊含义的变量。它们是
AVIZO_ROOT:Avizo安装目录。AVIZO_LOCAL:个人Avizo开发目录(仅Avizo XPand Extension)。SCRIPTFILE:当前正在执行的Tcl脚本文件。SCRIPTDIR:当前正在执行的脚本所在的目录。hideNewModules:如果设为1,新创建模块的图标一开始会被隐藏。请注意,只在确有必要时才设置该变量,并在之后立即恢复,以免意外地隐藏了偶然创建的模块(例如在脚本被中断的情况下)。
11.5.3.2 对象命令
Avizo模块和数据对象的基本命令接口,在用户指南参考部分的数据类型章节中的Object一节里有描述。对象命令的基本语法是
1 | <object> <command> <arguments> ... |
其中<object>指对象的名称,<command>表示要执行的命令。每个模块或数据对象除了由其基类所定义的命令之外,还可以定义自己的一组命令。Object一节中所描述的命令由所有模块和数据对象提供。
全局命令在下一节中描述。
11.5.3.3 性能增强
在一个多次创建/应用模块的脚本中,可能会出现性能问题。这可能是由于历史记录(History Logging)造成的——它被用于从模块结果创建配方(Recipes)。
为了改善此类脚本的性能,可以使用startLogInhibitor(相应地stopLogInhibitor)命令来停用(相应地激活)历史记录。在这种情况下,将无法从脚本结果创建配方。更多信息请参阅创建符合配方的脚本对象一节。
11.5.4 全局命令
本节列出Avizo特定的全局Tcl命令。其中一些命令与Avizo中的某些全局对象相关联,例如控制台窗口、主窗口或查看器窗口。而另一些命令(例如load或echo)则不然。这些命令在一个共同的小节中描述。总的来说,提供了以下命令小节:
- 查看器命令选项(
viewer) - 主窗口命令选项(
theMain) - 控制台命令选项(
theMsg) - 顶层窗口的公共命令
- 进度条命令选项(
workArea) - 应用程序命令选项(
app) - 其他全局命令
11.5.4.1 查看器命令选项
发送给查看器的命令可以键入控制台窗口。其语法为
1 | viewer [<number>] command |
其中<number>指定所寻址的查看器。值0指主查看器,为方便起见可以省略。
命令
viewer [<number>] snapshot [-offscreen [<width> <height>]] [-stereo] [-alpha] [-tiled <nx> <ny>] <filename> [filename2]
该命令对当前场景拍摄一张快照,并以指定的文件名保存。图像格式会根据文件名的扩展名自动确定。可用格式列表包括:TIFF(.tif、.tiff)、SGI-RGB(.rgb、.sgi、.bw)、JPEG(.jpg、.jpeg)、PNM(.pgm、.ppm)、BMP(.bmp)、PNG(.png)以及Encapsulated PostScript(.eps)。如果未给出查看器编号,并且你已从View菜单中选择了2查看器或4查看器布局,那么快照会从所有查看器拍摄。
如果指定了-offscreen选项,将使用最大尺寸为2048x2048的离屏渲染。在这种情况下,即使寻址的是查看器0,也必须给出查看器编号。如果没有显式指定宽度和高度,则使用查看器当前的图像尺寸。
注意:如果查看器中有多个可见的透明对象,并且你想使用离屏渲染,请把透明度模式设为Blend Delayed,并在拍摄快照之前检查所有对象是否都被正确渲染。
如果使用了-stereo选项,则创建立体模式图像。在这种情况下,可以用filename2文件来指定立体图像的第二幅图像存储在何处。
如果使用了-alpha选项,则创建的快照图像带有透明背景。
如果使用了-tiled nx ny选项,则使用分块渲染,水平方向nx块,垂直方向ny块。
viewer [<number>] setPosition <x> <y>
(仅在顶层模式下)设置查看器窗口相对于屏幕左上角的位置。如果同一个窗口中显示了多个查看器,则设置的是顶层窗口的位置。
viewer [<number>] getPosition
返回查看器窗口的位置。如果同一个窗口中显示了多个查看器,则返回顶层窗口的位置。
viewer [<number>] setSize <width> <height>
(仅在顶层模式下)设置查看器窗口的尺寸。宽度和高度指定的是实际图形区域的尺寸。由于查看器装饰和窗口边框的存在,窗口尺寸可能会略大一些。
注意:当查看器未能按所请求的尺寸调整大小时,控制台中会打印一条警告消息。在为查看器设置新尺寸时,可能出现新的查看器尺寸并非所请求尺寸的情况。这种情况可能发生在:
- 查看器处于顶层模式,而给定的尺寸过小(例如:(10, 10))
- 查看器不处于顶层模式,且主窗口无法被调整到更小的尺寸(例如:某个部件阻碍了主窗口的调整,比如Mac上统一的标题栏与工具栏,或者某个具有最小宽度的停靠部件)。
viewer [<number>] getSize
返回不含装饰和窗口边框的查看器窗口尺寸。
viewer [<number>] setCamera <camera-string>
恢复所有相机设置。该相机字符串应当是某条getCamera命令的输出。
viewer [<number>] getCamera
该命令返回当前的相机设置,即位置、朝向、焦距、类型,以及高度角(对于透视相机)或高度(对于正交相机)。这些值以Avizo命令的形式返回,可以被执行以恢复相机设置。完整的命令字符串也可以一次性传给setCamera。
viewer [<number>] setCameraPosition <x> <y> <z>
定义相机在世界坐标中的位置。
viewer [<number>] getCameraPosition <x> <y> <z>
返回相机在世界坐标中的位置。
viewer [<number>] setCameraNearDistance <value>
定义从相机视点到近裁剪平面的距离。
viewer [<number>] setCameraFarDistance <value>
定义从相机视点到远裁剪平面的距离。
viewer [<number>] setCameraOrientation <x> <y> <z> <a>
定义相机的朝向。默认情况下,相机沿负z方向观察,y轴指向上方。任何其他朝向都可以指定为相对于该默认方向的一个旋转。该旋转由一个旋转轴x y z后跟一个旋转角a(以弧度为单位)来指定。
viewer [<number>] getCameraOrientation
以setCameraOrientation所使用的相同格式返回相机的当前朝向。
viewer [<number>] setCameraFocalDistance <value>
定义相机的焦距。焦距被用于计算在交互式查看模式下场景绕之旋转的中心。
viewer [<number>] getCameraFocalDistance
返回相机的当前焦距。
viewer [<number>] setCameraHeightAngle <degrees>
以度为单位设置透视相机的高度角。把角度变小会使视场变小,从而实际上产生”放大”的效果,就像使用长焦镜头一样。除非你确实想改变相机的视场,通常更好的做法是把相机移近对象(有时称为”推进”),以使对象显得更大。如果当前相机是正交相机,则该命令无效。
viewer [<number>] getCameraHeightAngle
返回透视相机的高度角。
viewer [<number>] setCameraHeight <height>
设置正交相机视景体的高度。如果相机是透视相机,则该命令无效。
viewer [<number>] getCameraHeight
返回正交相机的高度。
viewer [<number>] setCameraType <perspective|orthographic>
设置相机类型。
viewer [<number>] getCameraType
返回相机类型。
viewer [<number>] setTransparencyType <type>
该命令定义用于渲染透明对象的策略。参数type可以是0到8之间的一个数字,分别对应View菜单中所描述的条目Screen Door、Add、Add Delay、Add Sorted、Blend、Blend Delay、Blend Sorted、Sorted Layers和Sorted Layers Delayed。
最精确的结果由模式8获得。默认是模式6。在默认模式下,某些对象可能无法被正确识别为透明。在这种情况下,你可以把它们关闭再重新打开,以强制它们被最后渲染。此外,如果需要在透明背景上渲染线条,也可能出现问题。在这种情况下,你可以使用透明度模式4,并手动确保正确的渲染顺序。
viewer [<number>] getTransparencyType
该命令以数字形式返回当前的透明度类型,该数字的含义与setTransparencyType中相同。
viewer [<number>] setSortedLayersNumPasses <value>
设置当透明度类型为Sorted Layers或Sorted Layers Delayed时所使用的渲染遍数。使用更多遍数可获得更正确的透明度。通常四遍(也就是默认值)就能给出良好的结果。
viewer [<number>] getSortedLayersNumPasses
返回当透明度类型为Sorted Layers或Sorted Layers Delayed时所使用的渲染遍数。
viewer [<number>] setBackgroundColor <r> <g> <b>
该命令把背景颜色设为某个特定值。颜色既可以指定为0…255范围内的三个整数RGB值,也可以指定为0.0…1.0范围内的三个有理数RGB值,或者干脆用纯文本指定,例如white——允许的颜色名称列表定义在/usr/lib/X11/rgb.txt中。
viewer [<number>] getBackgroundColor
以取值在0与1之间的RGB三元组形式返回主背景颜色。
viewer [<number>] setBackgroundColor2 <r> <g> <b>
设置由非均匀背景模式所使用的次背景颜色。
viewer [<number>] getBackgroundColor2
以取值在0与1之间的RGB三元组形式返回次背景颜色。
viewer setBackgroundMode <mode>
允许你指定不同的背景图案。如果mode设为0,将显示均匀背景。模式1表示渐变背景。对应于棋盘图案的模式2已被移除。最后,模式3会把先前用setBackgroundImage定义的一幅图像绘制在背景上。
viewer getBackgroundMode
返回当前的背景模式。
viewer setBackgroundImage <imagefile> [<imagefile2>] [-stereo]
该命令允许你把任意一幅栅格图像插入到查看器背景的中央。该图像不得大于查看器窗口本身,否则它会被裁剪。图像文件的格式会通过查看文件名扩展名自动检测。除Encapsulated PostScript之外,snapshot命令中提到的所有格式都受支持。如果指定了第二个图像文件,在活动立体渲染的情况下,该文件将被用作右眼图像。如果指定了-stereo选项而只给出了一个图像文件,则假定该文件包含左眼视图和右眼视图并排合成的画面。随后这些视图会被自动分离。
viewer getBackgroundImage
该命令返回用setBackgroundImage定义的最后一个背景图像文件的文件名。如果指定的是一对立体图像,则返回两个文件名。如果在setBackgroundImage中使用了-stereo选项,该选项也会被返回。
viewer [<number>] setAutoRedraw <state>
如果state为0,则自动重绘模式被关闭。在这种情况下,除非发送了重绘命令,查看器窗口中显示的图像将不会被更新。如果state为1,则自动重绘模式重新被打开。在脚本中,临时禁用自动重绘模式可能是有用的。
viewer [<number>] isAutoRedraw
如果自动重绘模式已打开,则返回真。
viewer [<number>] redraw
该命令强制当前场景被重绘。只有在自动重绘模式已被禁用的情况下,才需要显式的redraw。
viewer [<number>] rotate <degrees> [x|y|z|m|u|v]
绕某个轴旋转相机。要采用的轴由第二个参数指定。可用的选择如下:
- x:x轴 (1,0,0)
- y:y轴 (0,1,0)
- z:z轴 (0,0,1)
- m:x、y或z中最接近垂直的那个轴
- u:查看器的上方向
- v:观察方向
最后一个选项与用户界面的旋转按钮作用相同。在大多数情况下,m选项最为合适。为了向后兼容,默认值是u。
viewer [<number>] setDecoration <state>
已弃用。
viewer [<number>] saveScene [-b] [-r] [-z] <filename>
把某个查看器中所显示的全部几何体以Open Inventor 3D图形格式保存。警告:由于许多Avizo模块使用了自定义的Open Inventor节点,该场景通常无法在诸如ivview之类的外部程序中被正确显示。可用的选项如下:
-b:以二进制格式保存Open Inventor文件。-r:不仅保存某个查看器中所显示的几何体,还把额外的属性一并保存到Open Inventor文件中。-z:以压缩格式保存Open Inventor文件(使用zip压缩)。
viewer [<number>] viewAll
重置相机,使整个场景变为可见。对于在某个查看器中显示的第一个对象,该方法会被自动调用。
viewer [<number>] show
该命令打开指定的查看器,并确保该查看器窗口显示在屏幕上所有其他窗口的最上方。
viewer [<number>] hide
该命令关闭指定的查看器。
viewer [<number>] isVisible
该命令指示指定的查看器是否可见。
viewer [<number>] fogRange <min> <max>
设置雾效的衰减范围——雾效可以通过View菜单引入到查看器场景中。默认范围是$[0, 1]$。该范围内的值对应于场景点到相机的距离,因此离相机最近的点值为零,而最远的点值为一。限制衰减范围意味着衰减将从所指定最小值处的点开始,并在所指定最大值处的点达到其最大值。雾的最大衰减等同于不可见,因此超出该最大值的所有点都将显示为背景。
viewer [<number>] setVideoFormat pal|ntsc
按PAL 601或NTSC 601分辨率设置查看器窗口的尺寸,即720x576像素或720x486像素。装饰的当前设置会被考虑在内。
viewer [<number>] setVideoFrame <state>
如果state为1,则在查看器的覆盖平面中显示一个边框。该边框描绘出录制到视频中的图像能够在视频播放器上被安全显示的区域。设置查看state:0则关闭该边框。注意:显示在覆盖平面中的对象不会被snapshot命令保存到文件(见上文)。
viewer [<number>] getViewerSpinAnimation
如果查看器旋转动画已打开则返回1,否则返回0。
viewer [<number>] setViewerSpinAnimation <state>
如果state为1,则打开查看器旋转动画。否则,把0作为state传入将关闭查看器旋转动画。注意:查看器旋转动画的状态会被保存为首选项,因此在重启Avizo后它仍保持不变。
viewer [<number>] setViewing <state>
设置查看state:0把查看器切换到交互模式,1把它切换到查看模式。
viewer [<number>] getViewing
指示查看状态:0表示交互模式,1表示查看模式。
viewer [<number>] linkViewer [<ID>...]
该命令用于链接查看器。该命令的作用与相应的GUI操作完全相同。
viewer [<number>] unlinkViewer [<ID>...] [all]
该命令用于解除已链接查看器的链接。
11.5.4.2 主窗口命令选项
命令theMain允许你访问和控制Avizo主窗口。除了下面列出的特定命令选项之外,第11.5.4.4节(顶层窗口的公共命令)中列出的所有子命令也都可以使用。
命令
theMain snapshot filename
创建并保存主窗口的快照图像。图像文件的格式由文件名扩展名确定。可以使用Avizo所支持的任何标准图像文件格式,例如.jpg、.tif、.png或.bmp。
theMain setViewerTogglesOnIcons {0|1}
启用或禁用在Avizo Project View中对象图标上橙色查看器开关的显示。
theMain ignoreShow [0|1]
启用或禁用专用的no show flag。如果设置了该标志,后续的mainWindow show命令会被忽略。该命令对于在Avizo XScreen Extension环境中运行标准Avizo脚本可能有用。不带参数调用该命令只会返回该标志的当前值。
theMain showConsole [0|1]
启用或禁用Avizo中控制台窗口的显示。
11.5.4.3 控制台命令选项
命令theMsg允许你访问和控制Avizo控制台窗口。除了下面列出的特定命令选项之外,第11.5.4.4节(顶层窗口的公共命令)中列出的所有子命令也都可以使用。
命令
theMsg error <message> [<btn0-text>] [<btn1-text>] [<btn2-text>]
弹出一个带有指定消息的错误对话框。该对话框最多可以配置三个不同的按钮。该命令会阻塞,直到用户按下某个按钮。被按下按钮的id会被返回。
theMsg warning <message> [<btn0-text>] [<btn1-text>] [<btn2-text>]
弹出一个带有指定消息的警告对话框。该对话框最多可以配置三个不同的按钮。该命令会阻塞,直到用户按下某个按钮。被按下按钮的id会被返回。
theMsg question <message> [<btn0-text>] [<btn1-text>] [<btn2-text>]
弹出一个带有指定消息的提问对话框。该对话框最多可以配置三个不同的按钮。该命令会阻塞,直到用户按下某个按钮。被按下按钮的id会被返回。
theMsg overwrite <filename>
弹出一个对话框,询问用户是否可以覆盖指定的文件。如果用户单击Ok,则返回1,否则返回0。
11.5.4.4 顶层窗口的公共命令
这些命令对于所有会打开一个独立顶层窗口的Avizo对象都可用。具体来说,它们是Avizo主窗口(theMain)、控制台窗口(theMsg)和查看器窗口(viewer 0)。例如,你可以使用相应的全局命令后跟setPosition或getPosition来设置或获取这些窗口的位置。
命令
getFrameGeometry
返回包含窗口边框的窗口位置和尺寸。总共返回四个数字。前两个数字表示窗口边框左上角相对于桌面左上角的位置。后两个数字表示以像素为单位的窗口尺寸。
getGeometry
返回不含窗口边框的窗口位置和尺寸。总共返回四个数字。前两个数字表示窗口左上角相对于桌面左上角的位置。后两个数字表示以像素为单位的窗口尺寸。
getPosition
返回包含窗口边框的窗口左上角位置。这与getFrameGeometry所返回的前两个数字相同。
getRelativeGeometry
以相对坐标返回包含窗口边框的窗口位置和尺寸。桌面的尺寸为(1,1)。窗口的位置和尺寸由0与1之间的小数指定。
getSize
返回不含窗口边框的窗口尺寸。这与getGeometry所返回的后两个数字相同。
hide
隐藏该窗口。
setCaption <text>
设置显示在窗口边框中的窗口标题。
setFrameGeometry <x y width height>
设置包含窗口边框的窗口位置和尺寸。需要指定四个数字:x位置和y位置、窗口宽度和窗口高度。
setGeometry <x y width height>
设置不含窗口边框的窗口位置和尺寸。需要指定四个数字:x位置和y位置、窗口宽度和窗口高度。
setPosition <x y>
设置窗口边框左上角的位置。
setRelativeGeometry <x y width height>
以相对坐标设置包含窗口边框的窗口位置和尺寸。桌面的尺寸为(1,1)。窗口的位置和尺寸由0与1之间的小数指定。
setSize <width height>
设置不含窗口边框的窗口尺寸。
show
使窗口以正常状态可见。同时也把窗口置于前台。
showMinimized
使窗口以图标化状态可见。
showMaximized
使窗口以最大化状态可见。
11.5.4.5 进度条命令选项
命令workArea允许你访问位于Avizo主窗口下部的进度条。你可以打印消息,或者检查停止按钮是否被按下。
命令
workArea setProgressInfo <text>
设置一段将显示在进度条中的信息文本。该文本可用于描述某次计算过程中的状态。
workArea setProgressValue <value>
设置进度条的值。参数必须是0与1之间的浮点数。例如,值0.8表示当前任务已完成80%。
workArea startWorking [<message>]
激活停止按钮。调用该命令之后,Avizo的停止按钮变为可用。在你的脚本中,可以通过调用workArea wasInterrupted来检查停止按钮是否被按下。当停止按钮处于活动状态时,除非你在脚本中调用workArea stopWorking,否则无法与任何其他部件交互。因此,你不能直接在控制台窗口中输入该命令,而应当只在脚本文件或Tcl过程中使用它。
workArea stopWorking
停用停止按钮。当以workArea startWorking开始的计算任务完成时,或者用户按下了停止按钮时,请调用该命令。该命令还会恢复在调用startWorking之前所显示的进度信息文本。
workArea wasInterrupted
检查用户是否按下了停止按钮。你应当只在workArea startWorking和workArea stopWorking之间使用该命令。如果存在多个嵌套的计算任务,并且用户按下了停止按钮,那么所有后续对wasInterrupted的调用都会返回真,直到到达第一层为止。
11.5.4.6 应用程序命令选项
app命令提供若干与Avizo中某个特定对象或组件无关、而是与Avizo本身相关的选项。
命令
app version
返回当前的Avizo版本。
app uname
返回操作系统的简化名称。
app arch
返回Avizo架构字符串,例如arch-Win32VC8-Optimize、arch-LinuxAMD64-Optimize。
app hostid
返回创建Avizo许可证密钥所需的主机id。
app listen [port]
打开一个可以向其发送Tcl命令的套接字。可以选择性地指定TCP/IP端口。警告:这可能会造成安全漏洞。除非处于防火墙之后并且你清楚自己在做什么,否则不要使用它。在Network Preferences中,可以设置端口,并且可以打开或关闭监听端口。
app close
关闭Avizo Tcl端口。
app port
返回Avizo Tcl端口的端口号。如果套接字尚未打开,则返回-1。
app send <command> [<host> [<port>]]
向一个正在监听的Avizo发送Tcl命令。如果未指定主机或端口,Avizo实例将把该命令发送到首选项中所指定的主机和端口。参见Network Preferences一节。
app opengl
检索所使用的OpenGL驱动程序的信息,包括版本号和所支持的扩展。在报告渲染问题时,这是发送给热线支持的有用信息。
app cluster
返回当前的节点状态。如果某种集群模式处于活动状态,它可以是”master”或”slave”;如果不是这种情况,则简单地返回”single”。
app memTotal [-k | -m | -g]
以字节为单位返回系统的物理内存。可选开关-k、-m、-g分别把输出转换为千字节、兆字节或吉字节。
app memAvail [-k | -m | -g]
以字节为单位返回系统的可用内存。可选开关-k、-m、-g分别把输出转换为千字节、兆字节或吉字节。请注意,取决于操作系统,该输出可能与其他工具所报告的有偏差。
app config <key> [<val>]
提供对被永久存储的自定义配置设置的访问。app config <key>返回<key>当前的配置值。app config <key> <val>设置一个新值。
11.5.4.7 其他全局命令
命令
addTimeout msec procedure [arg]
安排某个Tcl过程在msec毫秒之后被调用。如果指定了arg,它会被传给该过程。所指定的过程只会被调用一次。如有必要,你可以在该超时过程中再次安排它。示例:addTimeout 10000 echo {10 seconds are over.}
all [-selected | -visible | -hidden] [type]
返回当前Project View中所有Avizo对象的列表。如果指定了type,则只返回具有该C++类类型的对象(或其派生对象)。搜索可以被限制在选中的、可见的或隐藏的对象上。示例:all -hidden HxColormap。
aminfo [-a outfile|-b outfile] Avizo-File
如果只用一个文件名作为参数,该命令会打开该文件(必须是Avizo数据格式),并打印文件头信息。如果配合-a或-b选项使用,则由参数outfile指定的输出文件会分别以ASCII(-a)或二进制(-b)格式写出。因此,aminfo可用于把二进制Avizo数据转换为ASCII,反之亦然。
clear
清空控制台窗口。
create class name [instance name]
创建一个Avizo对象(例如模块或数据对象)的实例。返回该实例名。请注意,数据对象通常不是以这种方式创建的,而是通过从文件加载来创建。示例:create HxOrthoSlice MySlice。
dso options
控制动态库(”dynamic shared objects”)的加载。提供以下选项:
addPath path ...:把某个路径添加到加载动态库时要搜索的目录列表中。verbose {0|1}:打开和关闭与动态库相关的调试信息。open <package>:尝试加载指定的动态库。只需指定包名即可,例如hxfield。该名称会被自动转换为依赖于平台的名称,例如Linux上的libhxfield.so或Windows上的hxfield.dll。unloadPackage <package>:卸载(如果可能)指定的动态库。execute <package> <function>:执行指定动态库中所定义的函数。
echo args
把它的参数打印到Avizo控制台。请使用该命令,而不是打印到标准输出的原生Tcl命令puts。
help arguments
不带参数时,这会打开Avizo帮助浏览器。
httpd [port]
启动一个内置的httpd服务器。该http服务器会提供所请求的任何文档。如果所请求的文档以.hx结尾,Avizo不会提供该文件,而是把它作为Tcl脚本执行。这可用于从Web浏览器控制Avizo。警告:该命令可能造成安全漏洞。除非处于防火墙之后并且你清楚自己在做什么,否则不要使用它。
limit {datasize | stacksize | coredumpsize} size
更改进程限制。仅在Unix平台上可用。使用”unlimited”作为尺寸表示不限制。尺寸必须以字节指定。或者,你也可以使用例如1000k表示1000千字节,或1m表示1兆字节。
load [fileformat] options files
从一个或多个文件加载数据。可以选择性地指定文件格式,以覆盖Avizo的自动文件格式识别。文件格式由与Avizo文件对话框中文件格式组合框内所显示的相同标签来指定。Avizo所支持的所有文件格式的列表可以用全局命令fileFormats获取。远程文件可以通过使用FTP或HTTP协议来读取。
其他选项如下:
-browse:显示Open Data窗口。-avizoscript:打开Avizo脚本文件。-avizo:Avizo的原生通用格式。它被用于加载许多不同的数据对象,例如定义在规则网格或四面体网格上的场、分割结果、颜色图,或者诸如地标之类的顶点集。-dataOnly:阻止导入器创建显示模块,在hx文件中很有用。-unit <Unit>:强制指定数据的单位。
mem
打印一些内存统计信息。
quit
立即退出Avizo。
remove {objectname | -all | -selected}
从Project View中移除对象。
objectname:指定的Avizo对象。-all:所有对象。-selected:选中的对象。
removeTimeout procedure [arg]
取消先前用addTimeout安排的某个Tcl过程。
rename objectname newname
更改某个对象的实例名。与objectname setLabel newname相同,只是它在成功时返回1,不成功时不返回任何内容。
sleep sec
等待sec秒。在此期间Avizo不会处理事件。
source filename
从指定的文件加载并执行Tcl命令。如果该脚本文件包含扩展名.hx,也可以使用load命令。
system command
执行一个外部程序。除非你清楚自己在做什么,否则不要使用它。
saveProject
保存当前项目。如果该项目此前未被保存过,那么它将以Untitled.hx的名字保存在Avizo根目录中。
saveProjectAs [-forceAutoSave | -packAndGo] arg
当前项目的一个副本将以arg为名保存在Avizo根目录中(例如saveProjectAs myProject)。当使用路径时,需要指定完整路径,并且需要在项目名后添加.hx扩展名(例如saveProjectAs c:/work/myProject.hx)。可以选择性地指定forceAutoSave参数,以强制自动保存已修改的项目而不显示警告对话框。如果指定了参数packAndGo,则会在项目文件所保存的同一文件夹中创建一个新文件夹,其中将包含加载所保存项目所需的全部数据。注意:如果某个文件已经存在,它不会被覆盖。
theObjectPool setSelectionOrder {first object} {second object}...
该命令重新排列选择,使其与给定的对象顺序相匹配。不包含在该列表中的被选对象会被移动到选择的末尾(不过它们的相对顺序不会改变)。
thePreferences [save | load] filename
该命令把首选项保存到由filename指定的文件,或从该文件加载首选项。
theProperties [show | hide]
该命令显示或隐藏Avizo中的Properties面板。
theProjectView [show | hide]
该命令显示或隐藏Avizo中的Project View面板。
fileFormats
显示可以在Avizo中使用的所有文件格式。
11.5.5 Avizo脚本文件
值得注意的是,一个Avizo项目其实就是一个能够重建当前Avizo状态的Tcl脚本。因此,交互式地创建一个Avizo项目、用”Save Project”保存它,然后把它作为编写脚本的起点,往往是很高效的做法。
在Avizo中执行Tcl命令最简单的方式是把它们键入Avizo控制台窗口。不过,对于诸如循环或过程之类的多行构造,这种方式并不实用。在这种情况下,建议把Tcl代码写入一个文件,并用命令source filename执行该文件。你也可以在某个文件内部使用source命令,以便把另一个文件的内容包含进来。
或者,你也可以使用命令load filename,或者使用File菜单中的Open Project...菜单项以及文件浏览器。不过在这种情况下,为了让Avizo识别文件格式,文件名必须以.hx结尾,或者文件内容必须以如下标题行开头
1 | # Avizo Script |
有一些Tcl文件在Avizo启动时会被自动加载。在启动时,程序会在当前目录或主目录中查找一个名为.Avizo的文件(详情参见第11.3.3节(启动脚本))。如果没有找到这样的用户自定义启动脚本,则会从目录$AVIZO_LOCAL/share/resources/Avizo或$AVIZO_ROOT/share/resources/Avizo加载默认的初始化脚本Avizo.init。该脚本随后会读入share/resources子目录中所有以.rc结尾的文件。这些.rc文件用于注册模块和数据类型。因此,只需向该目录添加一个新的.rc文件,或者修改Avizo.init文件,就可以定制Avizo的启动行为。
注意:这些脚本文件必须以utf-8编码,才能与非ASCII字符一起正常工作。
执行Tcl代码的另一种方式,是定义与功能键相关联的过程。如果存在名为onKeyF2、onKeyF3、…、onKeyShiftF2、…、onKeyCtrlF2、…、onKeyCtrlShiftF2、…的预定义过程,那么当相应的键在Avizo主窗口、控制台窗口或查看器窗口中被按下时,这些过程会被自动调用。要定义这些过程,请把它们写入一个文件并source它,或者把它们写入Avizo.init或某个.rc文件中。一个示例是
1 | proc onKeyF2 { } { |
注意:其中一些功能键可能被保留用于Avizo特定的操作。例如,[F1]始终被保留用于帮助,而[F2]在Project View或Tree View中被按下时保留用于对象重命名。
最后,Tcl脚本也可以在GUI中被表示出来,并与某个用户界面相结合。在Avizo中这被称为脚本模块(Script Module)。
11.5.6 配置弹出菜单
在Avizo中,所有可以附加到某个数据对象的模块,都会被列在该对象的弹出菜单中——右键单击该对象的图标即可看到该菜单。对于某些应用而言,在模块被创建之后用Tcl命令来定制新模块是有意义的。有时,向某个对象的弹出菜单添加新条目、使某个特定脚本被执行,也是有意义的。本节描述如何通过修改Avizo资源文件或创建新的资源文件来达到这些目标。
Avizo资源文件位于目录$AVIZO_ROOT/share/resources中,其中$AVIZO_ROOT表示Avizo被安装到的目录。资源文件其实就是普通的脚本文件,只不过它们以后缀.rc来标识。当Avizo启动时,resources目录中的所有资源文件都会被读取。在资源文件中,模块、编辑器和IO例程是用特殊的Tcl命令注册的。注册一个模块意味着指定它的名称(即它应当在弹出菜单中如何显示)、它可以被附加到的对象类型、定义该模块的共享库或DLL的名称等等。例如,Multi-Thresholding模块在文件hxlattice.rc中是用如下命令注册的:
1 | module -name "Multi-Thresholding" \ |
该命令的不同选项含义如下:
- 选项
-name指定该模块的名称或标签,即它在弹出菜单中被打印出来的样子。 - 选项
-primary表明该模块可以被附加到类型为HxUniformScalarField3或HxStackedScalarField3的数据对象上。这意味着Multi-Thresholding将只被包含在这类对象的弹出菜单中。 - 通过
-check,指定了一条附加的Tcl表达式,它会在菜单弹出之前的运行时被求值。如果该表达式求值失败,则该模块会被从菜单中移除。在Multi-Thresholding模块的情形下,会检查输入对象是否提供HxLabelLattice3接口,也就是说输入本身是否为一个标签场。虽然标签图像可以被视为3D图像,但对它执行阈值分割是没有意义的。因此,Multi-Thresholding只提供给原始3D图像,而不提供给标签场。此外还有一项针对输入基本数据类型(有符号/无符号整型、浮点型、有符号/无符号短整型……)的检查。这里,Multi-Thresholding模块不支持float或double类型的标签图像输入。 - 选项
-category表明Multi-Thresholding应当出现在主弹出菜单的Image Segmentation子菜单中。如果某个模块不应出现在子菜单中,而应出现在弹出菜单本身,则必须使用类别Main。 - 选项
-class指定该模块的内部类名。某个对象的内部类名可以用命令getTypeId获取。正是这个类名必须被用于上面所描述的-primary选项,而不是由-name所定义的对象标签。 - 最后,选项
-dso指定该模块是在哪个共享库或DLL中定义的。也可以改用选项-package,指定该模块是在哪个包中定义的(例如:-package “hxlattice”)。
除了这些标准选项之外,还可以用附加选项-proc来指定在模块被创建之后要执行的额外Tcl命令。举例来说,设想你正在做一个医学项目,需要在头部CT图像中识别立体定向标记物。那么,向弹出菜单添加一个定制版的Multi-Thresholding模块——它已经定义好了合适的材料名称和阈值——可能是个好主意。这可以通过在$AVIZO_ROOT/share/resources中的一个新资源文件里,或者直接在hxlattice.rc中,添加如下命令来实现:
1 | module -name "Stereotaxy" \ |
上面Tcl代码中所使用的变量$this指向新创建的模块,即Multi-Thresholding模块。请注意,这些命令是在该模块被连接到调用弹出菜单的源对象之前执行的。某些模块在被连接到一个新的输入对象时会做一些特殊的初始化。这些初始化可能会覆盖由自定义-proc选项所定义的Tcl命令设置的值。在这种情况下,你可以通过如下命令序列显式地把该模块连接到输入对象
1 | $this data connect $PRIMARY; |
这里Tcl变量$PRIMARY指向输入对象。同一个变量也被用于-check选项中所定义的Tcl表达式,如上文所述。
除了基于已有模块创建自定义弹出菜单条目之外,也可以定义完全新的条目——它们除了执行Tcl命令之外什么都不做。例如,我们可以向每个Avizo对象的弹出菜单添加一个新的子菜单Edit,并在其中放入通常包含在Avizo主窗口Edit菜单中的Hide、Remove和Duplicate命令。这可以通过以下方式实现:
1 | module -name "Remove" \ |
当然,用一条-proc命令来执行一个普通的Avizo脚本,甚至一个Avizo脚本对象,也是可能的。
11.5.7 注册拾取回调
拾取回调(pick callback)是一个附加到某个模块或某个查看器上的Tcl过程。当在该目标上发生拾取事件时,该回调就会被调用。这样的回调可以通过在模块和查看器上使用Tcl命令setPickCallback来注册:
1 | <module> setPickCallback <proc> [ <EventType> ] |
对于给定的某个模块或查看器,只能附加一个回调。要分离该回调,只需不带参数地调用注册命令即可:
1 | <module> setPickCallback |
可选参数<EventType>指的是将会调用该回调的事件种类。其他事件会被忽略。该参数可以取以下值:
MouseButtonPress、MouseButtonRelease(任意鼠标按钮)VRButtonPress、VRButtonRelease(任意3D按钮)MouseButton1Press、MouseButton1Release等(某个特定的鼠标按钮)VRButton0Press、VRButton0Release等(某个特定的3D按钮)
默认值是MouseButton1Press。
实际的回调过程<proc>应当接受一个参数,该参数将被解释为一个关联数组,其中编码了所有的拾取信息。该参数数组中定义了以下元素:
- object:被拾取几何体所属的Avizo对象的名称
- x:被拾取点的x坐标
- y:被拾取点的y坐标
- z:被拾取点的z坐标
- idx:被拾取元素的索引
- stateBefore:事件发生之前的修饰键状态
- stateAfter:事件发生之后的修饰键状态
如果该拾取事件未被处理,该过程应当返回0,在这种情况下其他回调过程可能会被调用。下面是一个示例:
1 | proc pickCallback arg { |
请注意,任何模块都可以自由地向这个参数数组添加特定的信息。所有元素都可以用以下方式显示:
1 | proc pickCallback arg { |
因此,某些Avizo模块会追加额外的数据:
- Vertex View:idx是被拾取的点索引。
- Point Cloud View:idx是被拾取的点索引。
- Line Set View:idx是被拾取的线索引,pt0和pt1是被拾取线段的两个端点。
- Surface View:idx是被拾取的三角形索引。
- Hexa/Tetra Grid View:idx是被拾取的三角形索引,tetra0和tetra1是相邻的四面体。
- Grid Boundary:idx是被拾取的三角形索引,originalIdx是网格中的索引,tetra0和tetra1是相邻的四面体。
11.5.8 Tcl中的文件读取器
本节描述如何注册一个用Tcl实现的自定义文件读取器。
首先,Tcl读取器函数必须在全局作用域中声明。它必须接受一个列表作为输入参数,该列表将包含待加载文件的列表。该读取器需要返回成功读取的文件数。
1 | proc myReaderInTcl {args} { echo "myReaderInTcl $args" ; ... ; |
然后,该Tcl读取器函数必须按以下模板注册到所需的文件格式声明中:
1 | dataFile -name "MyFormat" ... -package hxcore -load hxReadByTcl |
你用’-loadArgs’来指明自定义的Tcl读取器函数。参数’-package hxcore -load hxReadByTcl’必须按原样填写,不得更改。这会设置将调用Tcl解释器的内部包装器。
你可以在一个Tcl脚本中声明自定义读取器,也可以把它包含在一个将在应用程序启动时被加载的资源文件中。
11.5.9 如何创建符合配方的脚本对象
Scripting Workroom(脚本工作间)允许创建脚本对象,由于它们可以接受输入数据来产生结果,因此可以被视为自定义工具。
通常,脚本对象与配方系统并不兼容,因为无法从一个使用脚本对象的工作流的结果来创建配方。要创建一个可以在配方中使用的脚本,需要遵守一些规则。
注意:你也可以使用Tcl Command模块创建一个自定义模块。除非你处于下面所描述的高级规则用例之一,或者你需要多个输入,该模块应当是符合配方的。
该脚本对象应当遵循以下规则:
- 拥有一个Apply按钮
- 创建一个结果
如果你创建的是非标准脚本,还应当应用其他一些规则:
- 使用抑制器
- 修改输入
11.5.9.1 拥有一个Apply按钮
该脚本对象应当有一个Apply(即portDoIt)按钮。只有在该按钮被单击时,计算才应当被启动。
就代码而言:
- 在脚本对象的构造函数中创建Apply(即doIt)端口
- 在compute方法的开头:如果Apply按钮未被单击则中止
1 | "$this" proc constructor {} { |
11.5.9.2 创建一个结果
配方系统基于某个数据的HistoryLog。HistoryLog是对为产生该数据而应用过的每一个步骤或工具的记录。
该脚本对象应当创建一个结果数据集,并使用setResult命令把它设为结果。setResult命令会正确地记录该数据的HistoryLog。
就代码而言:
- 在compute方法的末尾使用
"$this" setResult <resultName>。
1 | $this proc compute {} { |
下面几节描述如何处理一些特殊的脚本——它们会修改脚本连接或输入数据。
11.5.9.3 高级用法:抑制内部工具
在某些特殊情况下,从脚本结果所创建的配方会包含“内部步骤”,因为脚本对象中所使用的内部工具出现在了配方里。
这在脚本修改了脚本对象的连接端口时会发生。
如果出现这样的用例,并且没有理由让这些工具出现在配方中,那么应当使用startLogInhibitor和stopLogInhibitor这两个TCL命令来抑制内部工具的记录。脚本的setResult命令应当在stopLogInhibitor命令之后调用。
就代码而言:
- 在compute方法中,在创建任何其他工具之前启动抑制器。
- 在设置结果之前停止抑制器。
1 | $this proc compute {} { |
这也可以用于改善使用了大量模块的脚本的性能。
11.5.9.4 高级用法:修改数据的脚本
如果你想修改脚本对象的输入(例如通过改变它的变换),则无法应用setResult规则,因为某个工具的结果不能被连接为输入。
在这种用例中,为了使脚本对象符合配方,我们需要使用recordInputUpdateInHistoryLog命令手动记录配方步骤。
就代码而言:
1 | $this proc compute {} { |
11.5.10 脚本对象的版本管理与向后兼容性
随着Avizo 9.2的发布,许多模块的用户界面被重新设计,这需要改变端口的名称和类型。因此,为早于9.2的Avizo版本所编写的脚本和脚本对象在许多情况下将不再能工作。为了应对这一点,实现了一种向后兼容模式,它要求脚本对象拥有一个版本号。对于9.2之前的脚本对象,版本字符串是V3.0。从9.2开始,一个由程序版本构成、不含分隔点的3位数字将告知Avizo是否使用向后兼容模式。第一行为# Avizo-Script-Object 201910的脚本对象将使用新接口,而第一行为# Avizo-Script-Object V3.0的脚本对象则会对某些模块使用兼容模式。关于最新的端口列表,请查阅模块文档。使用兼容模式的模块列于下表:
| 模块名称 (Module Name) | 类型ID (Type ID) |
|---|---|
| 2D Mesh | Hx2DMesh |
| Absolute Permeability Experiment Simulation | HxApparentAbsolutePermeability |
| Absolute Permeability Tensor Calculation | HxEffectiveAbsolutePermeability |
| Align Molecules | HxAlignMolecules |
| Align Principal Axes | HxAlignPrincipalAxes |
| Atomic Molecular Density | HxCompMolecularDensity |
| Auto Skeleton | HxExtAutoSkeleton |
| Bar Chart Slice | HxCityPlot |
| Bond Angle View | HxBondAngle |
| Boundary Conditions | HxHexaBoundaryIds |
| Boundary View | HxUnstructuredBoundariesView |
| Centerline Tree | HxTEASAR |
| Clipping Plane | HxArbitraryCut |
| Compute Tensor | HxComputeTensor |
| Configuration Density | HxConfDensity |
| Cross Section | HxUnstructuredMeshCrossSection |
| Curved Slice | HxCurvedSlice |
| Cylinder Correlation | HxCylinderCorrelation |
| Cylinder Slice | HxCylinderSlice |
| Effective Formation Factor Calculation | HxEffectiveFormationFactor |
| Elastic Registration | HxElasticRegistration |
| Export to VRML | HxSurfaceToVRML |
| Formation Factor Experiment Simulation | HxApparentFormationFactor |
| Generate Molecular Interface | HxCompMolInterface |
| Generate Surface | HxGMC |
| GridVolume | HxPoMeshSkin |
| H Bond View | HxHBondView |
| Height Map Slice | HxHeightField |
| Hexa Grid View | HxHexaView |
| Isocontour Slice | HxIsolines |
| Isosurface | HxIsosurface |
| Isosurface | HxPoMeshLevelSurf |
| Isosurface (hexa) | HxIsoHexa |
| Isosurface (tetra) | HxIsoTetra |
| Line Probe | HxLineProbe |
| Line Set Probe | HxLineSetProbe |
| Local Axis, Global Axis | HxAxis |
| Merge Mosaic | HxMergeMosaic |
| Molecular Diffusivity Experiment Simulation | HxApparentMolecularDiffusivity |
| Molecular Diffusivity Tensor Calculation | HxEffectiveMolecularDiffusivity |
| Molecule Electrostatics | HxMolElectrostatics |
| Molecule Label | HxMolLabel |
| Molecule Surface View | HxMolSurfaceView |
| Molecule View | HxMolView |
| Observables | HxMolObservables |
| Ortho Slice | HxOrthoSlice |
| Ortho Slice (lattice) | HxLatticeOrthoSlice |
| Ortho Slice (LDM) | HxOrthoSliceLDM |
| Parametric Surface | HxParametricSurface |
| Plot in Viewer | HxPlot2Viewer |
| Point Cloud View | HxClusterView |
| Pseudo Electron Density | HxPseudoElectronDensity |
| Register Images | HxAffineRegistration |
| Remesh Surface | HxRemeshSurface |
| Scalebars | HxScale |
| Secondary Structure View | HxSecStructure |
| Slice | HxFilteredObliqueSlice |
| Slice (LDM) | HxObliqueSliceLDM |
| Spatial Graph View | HxSpatialGraphView |
| Spline Probe | HxSplineProbe |
| Surface Cross Contour | HxGeometryCutter |
| Surface Path Editor | SurfacePathEditor |
| Surface View | HxDisplaySurface |
| Tetra Grid to Surface | HxTetraToSurface |
| Tetra Grid View | HxGridVolume |
| Thermal Conductivity Experiment Simulation | HxApparentThermalConductivity |
| Thermal Conductivity Tensor Calculation | HxEffectiveThermalConductivity |
| Transform Sequence | HxObjectTransformAnimation |
| Thinner | HxExtThinner |
| Trace Correlation Lines | HxTraceCorrelationLines |
| Tube View | HxTubeView |
| Vector Field | HxUnstructuredMeshVectors |
| Vector Plane | HxUnstructuredMeshPlaneVectors |
| Vertex View | HxDisplayVertices |
| Volren | HxVolren |
| Volume Rendering Settings | HxVolumeRenderingSettings |
| Vortex Corelines | HxVortexCoreline |
11.6 Python脚本编写
本节描述如何在Avizo中使用Python Scripting。
11.6.1 Python文档
本章的组织如下:
- 第11.6.1.1节 Python简介
- 第11.6.1.2节 嵌入式Python用法
- 第11.6.1.3节 常用全局命令
- 第11.6.1.4节 模块管理
- 第11.6.1.5节 脚本对象
- 第11.6.1.6节 Python环境与包管理器
- 第11.6.1.7节 Python包列表
Avizo的Python API文档可在此处获取。
11.6.1.1 Python简介
什么是Python
Python是一种高级的、面向对象的解释型语言,最早于1989年实现。( https://www.python.org/dev/peps/pep-0020/ )
- 优美胜于丑陋
- 显式胜于隐式
- 简单胜于复杂
- 复杂胜于凌乱
- 可读性很重要
包含了什么
Avizo使用Python 3.5.2。关于如何使用Python 3.X的详细信息可以在此处找到: https://docs.python.org/3.5/tutorial/index.html 。该Python安装中包含了许多包(参见此处的Python包列表)。Numpy和Scipy是本安装中所包含的两个最流行的Python包。
Numpy是一个用于处理多维数组的扩展,它支持逐元素运算、比较、逻辑运算以及统计等。numpy数组是用C实现的,从而能进行更快的计算。更多信息可以在此处找到: http://www.numpy.org/ 。
Scipy是一个扩展,它提供了用于科学计算的工具箱,例如插值、积分、图像处理、线性代数、信号处理和统计。更多信息可以在此处找到: http://www.scipy.org/ 。
从Python 2移植到Python 3
Python 2与Python 3之间存在一些兼容性断裂。关于移植到Python 3的Python官方文档可以在此处找到: https://docs.python.org/3.5/howto/pyporting.html 。
11.6.1.1.1 使用Python
本节并不打算涵盖Python语言的所有应用和细节。请参阅上一节中的链接以了解更多关于Python、Scipy和Numpy的信息。要了解更多关于Python如何与Avizo交互的内容,请继续阅读第11.6.1.2节 嵌入式Python用法。
Python控制台
可以通过转到Windows > Consoles来访问控制台(见图11.4)。控制台面板具有一个带标签页的界面,其中提供了若干不同的工具(见图11.5和图11.6)。
图 11.4:访问控制台。
图 11.5:主Python控制台界面。
图 11.6:Python脚本对象控制台界面。
工具栏上各按钮的含义如下:
- Remove This content(移除本内容):移除该解释器中所显示的全部内容
- Remove Pythonic Objects(移除Python对象):从Avizo的工作区中移除在该控制台内创建的所有Python对象
- Redirect All Output(重定向全部输出):把来自所有解释器的全部输出推送到主控制台
- Redirect This Output(重定向本输出):把来自当前控制台的全部输出推送到主控制台
该控制台的行为如同一个Python解释器,因此任何写下的命令在按下Enter后都会被立即执行。赋值结果或返回值会在执行后被显示出来。
热键与实用命令
TAB
当控制台中什么都没有写时,TAB会自动补全为命令hx_project.get(module),它会为该对象创建一个Python句柄。当控制台中已有文本时,TAB会尝试根据可用方法、属性和模块的列表来自动补全当前字符串。下拉列表中被高亮的选项将被补全。
UP或DOWN
这两个按键会在你最近的历史记录中循环。UP取回你之前的命令,而DOWN取回后一条命令。
11.6.1.1.2 关于Python的说明
包
Python是一门面向对象的语言,这意味着代码通常被分解为类,实例化对象时可以从类中继承变量和方法。这使你能够避免为你经常使用的功能重复编写代码。关于Python语境下OOP的更多信息可以在此处找到: http://www.tutorialspoint.com/python/python_classes_objects.htm
包是类、方法和变量的集合,可以被导入到Python的某个命名空间中。例如,如果用户想计算$sin(\pi/2)$,他们首先需要把Numpy包导入到命名空间中:
1 | >>>import numpy |
Numpy包包含一个sin(x)方法,随后就可以访问它来计算$sin(\pi/2)$:
1 | >>>numpy.sin(3.1415/2) |
Numpy已经包含一个定义了$\pi$的全局变量,你可以用同样的方式访问它:
1 | >>>numpy.pi |
在导入到命名空间时,可以把包赋给变量以简化代码:
1 | >>>import numpy as np |
语法
Python支持若干种不同的对象类型:
| 类型 (Type) | 说明 (Description) | 示例 (Example) |
|---|---|---|
| Number | 整数、浮点数、复数、布尔值 | 1, 1.05, 3j+2, 3>2 is True |
| String | 字符序列 | "String of charaters" |
| List | 用于分组可以被更改的项的容器 | [1, 5, "Dragon", 948.5] |
| Tuple | 用于分组不可被更改的项的容器 | (948.5, "Dragon", 5, 1) |
| Dictionary | 带有唯一键的关联数组 | {'a':99, 'b':'red', 'c':'balloons'} |
| Array | 为C优化的向量化数值数组 | numpy.ones ((10,5)) |
某些类型是用特定字符来表示的。例如,单引号或双引号被用于创建字符串:
1 | >>>a = 'This is a string.' |
而列表则用方括号来赋值:
1 | >>>c = [1, 5, "Dragon", 948.5] |
对象之间可以使用标准语法执行各种运算:
| 运算符 | 含义 | 运算符 | 含义 |
|---|---|---|---|
+ |
加法 | == |
等于 |
- |
减法 | != |
不等于 |
* |
乘法 | > |
大于 |
/ |
除法 | < |
小于 |
** |
指数 | <= |
小于或等于 |
% |
取模 | >= |
大于或等于 |
有些关键字被保留用于全局变量或执行特定的功能。应当无论如何都避免用这些关键字作为变量名从而覆盖它们。
| and | as | assert | break |
| class | continue | def | del |
| elif | else | except | exec |
| finally | for | from | global |
| if | import | in | is |
| lambda | not | or | pass |
| raise | return | try | |
| while | with | yield |
关于Python语法和对象类型更详尽的论述可以在官方教程中找到: https://docs.python.org/3.5/tutorial/index.html
11.6.1.2 嵌入式Python用法
11.6.1.2.1 概述
与TCL类似,Python在Avizo中是通过一套Pythonic的API实现的。Avizo特有的命令让你能够访问Avizo模块中所包含的信息和功能。使用Python与Avizo模块交互主要有两种方式。第一种方式是通过Python控制台,它与TCL控制台是分开的。这是一个解释器。该控制台的基本功能(例如tab补全)在第11.6.1.1节 Python简介中有描述。
在Avizo中使用Python的第二种方式是通过脚本模块。Python脚本模块允许你从预定义的PyScriptObject类继承属性,然后覆盖它们以创建你自己的集成扩展到Avizo中。脚本模块的行为就像Avizo中的常规模块,并且在配有资源文件时可以从Object Popup菜单访问。该资源文件仍然必须用TCL编写。为方便起见,PyScriptObject类中包含四个方法:
__init__():这个构造方法可以包含在脚本对象于Project View中被创建时运行的代码。update():可以调用该update方法来更新脚本对象在Properties Panel中的GUI。compute():这个compute方法通常包含你的大部分代码,并且应当在计算必须发生时被调用。__del__():这个析构方法可以包含在模块被删除时帮助清理命名空间的代码。
11.6.1.2.2 示例:与模块交互
这里我们将通过一个示例,来了解如何使用控制台与Project View中的模块交互——具体做法是创建一个Ortho Slice并更改它的属性。
- 确保工作区中显示了Python Console
打开
$AVIZO_ROOT/data/tutorials/chocolate-bar.am- 如果启用了Auto-View,会自动创建一个
Ortho Slice。请把它删除。
- 如果启用了Auto-View,会自动创建一个
要创建一个
Ortho Slice,请访问HxProject类中的create()方法。create()方法要求我们把想要创建的对象的类型ID作为字符串参数传入。- 如果你不确定某个对象的类型ID是什么,可以先在GUI中创建该对象,然后在TCL控制台中使用
<module> getTypeId命令来了解它的类型。
1
>>>hx_project.create('HxOrthoSlice')
- 如果你不确定某个对象的类型ID是什么,可以先在GUI中创建该对象,然后在TCL控制台中使用
现在我们需要把
Ortho Slice连接到chocolate-bar.am,但我们先用get()方法把该Ortho Slice赋给一个变量,以便将来更容易访问它。我们对chocolate-bar.am也做同样的处理:1
2>>>ortho = hx_project.get('Ortho Slice')
>>>input_data = hx_project.get('chocolate-bar.am')要把
Ortho Slice连接到chocolate-bar.am,我们需要了解如何访问Ortho Slice的Data端口。通过把portnames命令的结果打印到控制台,来展示一份可供交互的可能端口列表:1
2
3>>>ortho.portnames
['data', 'origin', 'normal', 'frameSettings',
...]从
portnames命令中我们看到,’data’端口很可能对应于Ortho Slice属性中所暴露的”Data”连接。请在ports层级使用connect()方法把chocolate-bar.am连接到该端口,然后用fire()方法应用该更改:1
2>>>ortho.ports.data.connect(input_data)
>>>ortho.fire()我们也可以通过设置
sliceNumber端口的value来更改切片位置:1
2>>>ortho.ports.sliceNumber.value = 100
>>>ortho.fire()请试验
Ortho Slice中的其他端口,看看你是否能够更改切片朝向和颜色图。要获得访问这些端口的帮助,请把访问命令传给help()方法:1
>>>help(ortho.ports.sliceOrientation)
通过把方法和类传给
help()方法,可以进一步了解可供你操作的方法和类:1
>>>help(ortho.fire)
11.6.1.2.3 示例:开发一个脚本
在这个示例中,我们将编写一个简单的脚本来计算某个数据集边界框的总体积。这些命令可以直接在Avizo的Python控制台中键入。你也可以在文本编辑器中键入这些命令,然后把它们复制到Python控制台中执行。
- 加载
$AVIZO_ROOT/data/tutorials/chocolate-bar.am。 把chocolate-bar.am赋给一个变量,以便在后续代码中快速引用它。
1
>>>data = hx_project.get('chocolate-bar.am')
创建一个
Bounding Box并把它附加到chocolate-bar.am。- 你可以在创建
Bounding Box的同时就把它赋给一个变量,而不必先创建它、之后再用单独的命令通过get()方法获取。
1
2
3>>>bbox = hx_project.create('HxBoundingBox')
>>>bbox.ports.data.connect(data)
>>>bbox.fire()- 你可以在创建
检索该边界框在X、Y和Z方向上的范围,以计算它的体积。已经有一个
bounding_box命令可用于获取这些信息,它们被存储在一个定义为((xmin, ymin, zmin),(xmax, ymax, zmax))的元组中。1
2
3
4
5
6
7>>>type(data.bounding_box)
<class 'tuple'>
>>>data.bounding_box
((0.0, 0.0, 0.0),
(0.02807999961078167,
0.020880000665783882,
0.035280000418424606))Python还让人很容易从这个双列表元组中一次性提取出两个变量。
1
>>>min_bounds, max_bounds = data.bounding_box
使用方括号
[]访问最小和最大边界列表中的每一个索引,并把这些信息代入一个公式来计算该盒子的体积。1
2
3
4>>>x_extent = max_bounds[0] - min_bounds[0]
>>>y_extent = max_bounds[1] - min_bounds[1]
>>>z_extent = max_bounds[2] - min_bounds[2]
>>>volume = x_extent * y_extent * z_extent最后,以一种精炼的格式把该信息打印到控制台。
1
>>>print('The volume of %s is %.g ' % (data.name, volume))
11.6.1.2.4 示例:创建一个函数
在这个示例中,我们把边界框体积计算器封装进一个函数,该函数接受我们的输入数据作为参数,并把我们的答案打印回控制台。关于函数和Python语法的几点说明:
- 如果你直接在Avizo控制台中这样做,请按SHIFT+ENTER在你的代码中输入一个换行而不执行它。
- Python要求函数体内的缩进保持一致。最佳实践惯例是把代码体缩进四个空格(而不是一个制表符)。
- Avizo中的Python控制台不会为用户自动缩进行,用户必须自己控制缩进。
- 加载
$AVIZO_ROOT/data/tutorials/chocolate-bar.am 使用
def关键字定义一个名为bbVol的函数,它接受单个输入数据集作为参数。1
2>>>def bbVol(data_arg): # Remember to SHIFT+ENTER here!
...解释器中会显示一个省略号,表明它正在等待更多代码才能执行当前输入。手动键入四个空格,然后把最小和最大边界列表赋给变量。
1
min_bounds, max_bounds = data_arg.bounding_box
按SHIFT+ENTER换到新行,再输入四个空格,然后继续编写体积计算器的其余部分。
1
2
3
4
5x_extent = max_bounds[0] - min_bounds[0]
y_extent = max_bounds[1] - min_bounds[1]
z_extent = max_bounds[2] - min_bounds[2]
volume = x_extent * y_extent * z_extent
print('The volume of %s is %.3f. ' % (data_arg.name, volume))最后,加入一条
return语句,把volume变量送回控制台。这使你能够把计算结果赋给一个变量。1
return volume
按ENTER执行该函数定义,然后用chocolate-bar.am测试这段代码。同时也测试一下你把计算结果赋给某个变量的能力。
1
2
3
4>>>bbVol(hx_project.get('chocolate-bar.am'))
The volume of chocolate-bar.am is 2e-05.
2e-05
>>>chocolatebar_volume = bbVol(hx_project.get('chocolate-bar.am'))
11.6.1.3 常用全局命令
有两个主要函数能极大地帮助用户探索Avizo内部Python的结构。dir()函数让用户可以看到某个给定对象上所有可用的属性和方法的列表。
1 | >>>ortho = hx_project.get('Ortho Slice') |
当你开始键入某条命令时,这些信息也会以下拉列表的形式出现(见图11.7)。
图 11.7:命令下拉列表。
help()函数提供关于属性和方法更详细的信息,以及它们的使用示例。help()的输出还包含关于相关父类的信息。
1 | >>>help(ortho) |
下面提供了一些更为具体的全局命令列表。
print()是一个原生Python命令,它把结果打印到Avizo中的Python控制台。1
2
3
4>>>x = 3
>>>y = 2
>>>print('The sum of %i + %i is %i.' % (x,y,x+y))
The sum of 3 + 2 is 5.import是一个原生Python命令,它通过加载额外的包来为Python添加扩展功能。1
2
3
4
5>>>x = 3
>>>y = 2
>>>import numpy
>>>numpy.add(x,y)
5
hx_project方法中包含一些用于与Project View交互的实用全局函数。
| 方法 (Method) | 说明 (Description) |
|---|---|
hx_project.create() |
创建某个特定Avizo类的实例并把它添加到Project View中 |
hx_project.remove() |
从Project View中移除一个对象 |
hx_project.add() |
向Project View中添加一个对象 |
hx_project.load() |
在指定了文件名时加载某种已定义格式的数据 |
包含目录路径的变量也作为属性提供,可通过hx_paths方法访问。
| 变量 (Variable) | 说明 (Description) |
|---|---|
hx_paths.install_dir |
安装目录,也就是<$AVIZO_ROOT> |
hx_paths.tutorials_dir |
教程数据目录 |
hx_paths.python_modules_dir |
包含额外包的Python模块目录 |
hx_paths.python_script_objects_dir |
包含用户所创建的自定义Python脚本的Python脚本对象目录 |
hx_paths.executable_dir |
包含Avizo.exe的目录 |
1 | >>>hx_paths.install_dir |
11.6.1.4 模块管理
一份包含大量代码片段、说明如何配置所有端口和模块的完整参考手册,可以从帮助菜单项Python Reference访问。
11.6.1.4.1 模块属性
什么是属性
属性是包含在某个类中的一个数据字段。有些属性可能是只读的。
常用属性列表
这里变量'a'指向你对象的Python句柄。
a.name:
这是一个字符串属性,它指向你的Avizo对象的名称。可以为它赋一个字符串来更改该对象的显示名称。
a.portnames:
这是一个只读列表,包含属于该Avizo对象的所有端口名称。
a.viewer_mask:
这是一个整数属性,它触发在查看器中的可见性。可以设置16种配置,取值范围为$[0, 15]$。如果使用了该范围之外的数字,该数字将在对16取模运算之后被求值。
a.bounding_box:
它存储一对元组,描述你对象的空间尺寸。可以按$((x{min},y{min},z{min}),(x{max},y{max},z{max}))$的格式赋予新的尺寸。
a.downstream_connections[x]:
它存储一个只读序列,包含所有引用它的对象。每个连接都被分配了一个整数索引'x'。要从该指针找出对象的名称,请使用命令a.downstream_connections[x].get_owner().name
a.range:
它存储一个只读元组,以(min, max)的形式显示数据的强度范围。
a.transform:
它存储一个元组,显示4x4变换矩阵。可以赋予一个新的变换。
11.6.1.4.2 模块方法
什么是方法
方法是包含在某个类中的一个函数。许多方法不需要参数。
常用方法列表
这里变量'a'指向你对象的Python句柄。
a.compute():
如果a.ports.doIt.was_hit = True,该方法就执行该对象的计算。这模拟了在条件允许时单击该对象的Apply。
a.update():
该方法为属性窗口更新对象GUI。
a.fire():
该方法调用a.update()和a.compute()。
a.execute():
该方法组合了上述所有方法,以模拟单击Apply并刷新GUI。
a.get_array():
该方法访问你对象的NumPy数组。访问该数组会阻止该对象被删除。
a.set_array(...):
该方法为你的对象赋一个NumPy数组。数组的所有权不会被传递,因此后续对该数组的更改不会传播,除非重新赋值。
11.6.1.5 脚本对象
11.6.1.5.1 什么是Python脚本对象
Python脚本对象是一个计算模块,其行为被硬编码在一个继承自PyScriptObject的Python类中。Python脚本对象对于创建自定义工具很有用——这些工具的功能可以像访问Avizo计算模块那样被访问。
脚本结构
在把你的Python脚本对象定义为一个类时,下面这些类方法很有用,但并不要求必须以这种方式定义。任何脚本都会像被键入控制台一样运行。变量self指向它自己的类标识。
def __init__(self):
该方法在对象被创建时被调用。它是定义你脚本结构和设置GUI的有用位置。
def __del__(self):
该方法在对象被重启或删除时被调用。这是清理任何连接的好地方。
def update(self):
该方法在GUI需要被刷新时被调用。
def compute(self):
该方法在Apply被单击时被调用。
注意:Python脚本对象的执行是在一个独立的Python解释器上完成的,并且它有自己的Python控制台。不过请注意,在某些特殊情况下,例如来自PyQt槽的打印消息,其流式输出可能会被重定向到主Python解释器。
创建端口
用户通过端口与对象交互。端口可以通过简单的赋值来初始化,它们属于HxPort类。下面是一些有用的端口:
HxConnection该端口类允许用户连接模块。也可以限制模块的类型。
HxPortFilename该端口类允许用户加载或保存文件。该端口的功能由mode属性定义。文件名既可以以文本形式输入,也可以通过文件浏览器访问。
HxPortIntSlider该端口类保存一个可以通过滑动标尺访问的整数值范围。该端口被用于定义”Ortho Slice”模块的切片编号。
HxPortDoIt该端口类控制自动刷新框并处理Apply按钮。
HxPortInfo该端口类对于向用户提供说明、备注或警告很有用。其文本可以在模块属性中找到。
边界框脚本示例
在这个示例中,我们把边界框体积计算器(在嵌入式Python用法一章中描述)封装进一个脚本模块,该模块可以通过Object Popup菜单被加载到Avizo GUI中。
打开一个文本编辑器,创建一个具有如下结构的新文件。把该对象命名为BoundingBoxVolume。
- 或者,你也可以从
$AVIZO_ROOT/share/python_script_objects/PythonScriptObjectTemplate.pyscro中的模板开始
1
2
3
4
5
6
7
8
9
10class BoundingBoxVolume(PyScriptObject):
def __init__(self):
# Initialization code will go here
def update(self):
# Update code will go here
def compute(self):
# Computation code will go here- 或者,你也可以从
该脚本对象需要能够连接到一个数据对象,以便知道需要为哪个边界框计算体积。默认情况下,Python脚本对象从
PyScriptObject类继承一个data连接。请确保它在__init__()方法中是可见的。1
2def __init__(self):
self.data.visible = True在这个示例中,由于没有端口需要更新,请在
update()方法中使用pass关键字来跳过GUI更新。1
2def update(self):
pass在compute方法中,如果没有数据对象连接到该脚本模块,我们希望中止体积计算。添加一条
if语句来检查data连接是否为空。如果data连接为空,就用一条return语句退出compute()方法。- Python用None关键字使这件事变得容易(即
if <expression> is None)
1
2
3
4def compute(self):
# Check if input data is connected
if self.input.source() is None:
return- Python用None关键字使这件事变得容易(即
最后,如果由于附加了一个数据对象而使该逻辑检查未通过,就使用bbVol脚本计算体积。使用
source()方法获取所连接数据对象的名称。1
2
3
4
5
6
7
8
9
10
11
12def compute(self):
# Check if input data is connected
if self.input.source() is None:
return
data = self.input.source()
min_bounds, max_bounds = data.bounding_box
x_extent = max_bounds[0] - min_bounds[0]
y_extent = max_bounds[1] - min_bounds[1]
z_extent = max_bounds[2] - min_bounds[2]
volume = x_extent * y_extent * z_extent
print('The volume of %s is %.g ' % (data_arg.name, volume))一旦你的模块完成,请用TCL创建一个资源文件,把该模块显示在Object Popup菜单中,作为可附加到所有数据对象的一个选项。
- 请参阅配置弹出菜单以了解更多关于创建资源文件的信息。
- 该文件可以在以下位置找到:
$AVIZO_ROOT/share/resources/PythonBoundingBoxVolume.rc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19module -name "Bounding Box Volume" \
-primary "HxUniformScalarField3" \
-package "py_core" \
-category "{Measure And Analyze}" \
-proc {
set this [[create HxPythonScriptObject] \
setLabel "Bounding Box Volume"]
"$this" startStop hideMaskIncrease
"$this" filename hideMaskIncrease
"$this" filename setValue \
<PRODUCT_PATH>/share/python_script_objects \
/PythonBoundingBoxVolume.pyscro
"$this" startStop hit 0
"$this" fire
if { [exists $PRIMARY] } {
$this data connect $PRIMARY
$this fire
}
}
11.6.1.5.2 资源文件
资源文件是一个TCL脚本,它在Avizo启动过程中被读取和执行。你可以配置一个资源文件,使你的Python脚本对象出现在下拉菜单中,或者作为一个宏按钮出现。资源文件位于$AVIZO_ROOT/share/resources目录中。
下拉菜单资源文件的结构
对于简单的情形,该脚本以TCL命令<module>开头,后跟以下标记。在下面的示例中,$PRIMARY指向你最初右键单击的那个对象。
-name
这是你的模块在菜单中的名称。
-package
它定义你对象的包。
-primary
它限定为使你的脚本出现所需的数据类型。
-category
它定义你的脚本将出现在菜单中的哪个文件夹里。
-proc
这是资源文件的主体,你可以在其中标明.pyscro的加载位置,并把你的脚本连接到你最初右键单击的那个对象。
宏资源文件的结构
对于简单的情形,该脚本以TCL命令<macroButton>开头,后跟以下标记。
-add
它为你的按钮创建一个名称。
-color
它控制你按钮的颜色。
-proc
这是资源文件的主体,你可以在其中标明.pyscro的加载位置或该过程的运行方式。
11.6.1.6 Python环境与包管理器
背景
本节说明如何使用命令提示符(Windows)或终端(Linux/Mac)为Avizo列出/安装/更新一个新的Python包。该包管理器允许用户创建多个自包含的Python环境,每个环境都有自己的Python可执行文件(例如Windows上的python.exe)和包集合。随后,每一个自包含的环境都可以被Avizo使用。
说明
EDM (Enthought Deployment Manager)包管理器可用于安装、移除或升级两个仓库中所提供的Python包:
- official ThermoScientific/3dSoftware
- enthought/free
应使用该工具来查找可用的Python包并安装新的包。它支持查看、更新和移除已安装的包。此外,它还支持回退到先前的状态并恢复原始的Avizo Python环境。
如何安装和配置EDM
注意:EDM安装程序可能需要重启你的计算机。
EDM安装程序可以在Enthought网站上找到: https://www.enthought.com/product/enthought-deployment-manager/
该安装程序会把EDM(在Windows上例如为edm.bat)解压到一个默认文件夹(例如Windows上的C:\Enthought\edm.)。
要创建一个名为hxEnv的新Python环境,请在Windows的命令提示符(转到EDM安装目录)或Linux/Mac的终端中执行以下命令行(使用与正确架构相对应的.json文件):
1 | edm envs import -f $AVIZO_ROOT/python/bundles/3dSoftware_win64.json hxEnv |
如果该命令失败,并出现如下错误消息:包仓库'ThermoScientific/3dSoftware'不存在或在你的配置文件$HOME/.edm.yaml下不可用,则该文件要么不完整,要么缺失。请打开文件夹$HOME($HOME环境变量包含用户主目录的绝对路径名),并查找.edm.yaml文件。如果它存在,请移除它并重启Avizo,这样应当会重新创建它。如果该文件仍然缺失,请联系支持。
新创建的Python环境存储在$HOME\.edm\envs\hxEnv中。
要在Avizo中使用名为hxEnv的新建Python环境,你必须把环境变量HX_FORCE_PYTHON_PATH设为$HOME/.edm/envs/hxEnv。
可以按如下方式获取可用环境的列表:
1 | edm environments list |
如何搜索并安装一个包
首先,按如下方式搜索所需的包:
1 | edm search <package_name> -e hxEnv |
如果该包可用,请按如下方式安装它:
1 | edm install <package_name> -e hxEnv |
如何列出当前已安装的包
要列出Avizo中当前所有已安装的包,请键入:
1 | edm list -e hxEnv |
如何重新初始化Avizo的包
要把Python包重新初始化到它们的原始状态,请使用该json文件创建一个新环境,或者取消设置HX_FORCE_PYTHON_PATH环境变量。取消设置该变量会使Avizo使用它的嵌入式版本。
如果Python发行版与Avizo一起变得无法正常工作(例如在安装了不受支持的包之后),这可能会很有用。
要显示所有可用选项,请使用以下命令行:
1 | edm help |
11.6.1.7 Python包列表
Thermo Scientific Python中已经包含的包列表:
alabaster 0.7.10-1、appdirs 1.4.3-1、babel 2.4.0-2、backports.abc 0.5-1、backports_abc_remove 0.4-2、certifi 2017.7.27.1-1、chardet 3.0.4-1、colorama 0.3.7-1、configobj 5.0.6-2、cycler 0.10.0-1、cython 0.25.2-1、decorator 4.1.2-1、distribute_remove 1.0.0-4、docutils 0.13.1-1、h5py 2.7.0-2、idna 2.5-1、imagesize 0.7.1-1、intel_runtime 15.0.6.285-2、jdcal 1.2-1、jinja2 2.9.6-1、lxml 3.7.3-2、markupsafe 0.23-2、matplotlib 2.0.0-5、mkl 2017.0.3-1、networkx 1.11-7、nose 1.3.7-3、numexpr 2.6.2-3、numpy 1.13.3-3、numpydoc 0.6.0-4、opencv 3.2.0-3、openpyxl 2.4.1-2、packaging 16.8-2、pandas 0.20.3-3、patsy 0.4.1-4、pillow 4.0.0-1、pip 10.0.1-1、py 1.4.34-1、pydicom 0.9.9-1、pygments 2.2.0-1、pyparsing 2.2.0-1、pyqt5 5.8.2-3、pytables 3.3.0-5、pytest 3.1.2-1、python_dateutil 2.6.0-1、pytz 2017.3-1、pywavelets 0.5.2-2、requests 2.18.4-1、scikit_learn 0.19.1-2、scikits.image 0.13.0-5、scipy 1.0.0-2、seaborn 0.8.1-2、setuptools 38.2.5-1、singledispatch 3.4.0.3-1、sip 4.19.2-2、six 1.10.0-1、snowballstemmer 1.2.1-1、sphinx 1.5.5-5、sphinx_rtd_theme 0.2.4-1、ssl_match_hostname 3.5.0.1-1、statsmodels 0.8.0-4、tornado 4.4.2-3、urllib3 1.22-1、xlwt 1.2.0-1
11.6.2 Python教程
11.6.2.1 Python教程——在Avizo中使用Python生态系统的工具
把Python集成到Avizo中的优势之一,是现在可以使用Python工具来扩展Avizo的功能。这种扩展方式允许编写脚本对象,把Python函数封装起来,使它们作为模块在Avizo图形用户界面中可用。这些Python工具随后就可以通过标准的Avizo端口来控制。
本教程演示如何把scipy中的快速傅里叶变换(FFT)集成进来,作为Avizo中所使用FFT的一种替代方案。你可以跟随分步说明操作,也可以查看$AVIZO_ROOT/share/python_script_objects目录中所生成的文件(ScipyFFT.pyscro和ScipyFFT.rc)。
请把PythonScriptObjectTemplate.pyscro从$AVIZO_ROOT/share/python_script_objects目录复制到你选择的位置,并把它重命名为ScipyFFT.pyscro。
在文本编辑器中打开该文件,并通过把第一行改为如下内容来为你的新模块起个名字:
1
class ScipyFFT(PyScriptObject):
在初始化函数中,默认的data输入端口将被用于连接到你的模块的数据,并且允许的连接类型将被定义:
1
self.data.valid_types = ['HxUniformScalarField3']
最终的初始化函数定义将如下所示:
1
2
3
4
5def __init__(self):
self.data.valid_types = ['HxUniformScalarField3']
# Create an 'Apply' button.
self.do_it = HxPortDoIt(self, 'apply', 'Apply')update函数保持原样:
1
2def update(self):
passFFT的计算将在compute函数中完成。在检查了Apply是否被单击以及是否选择了输入数据集之后,从Python导入几个包。在本例中,我们需要scipy中的fftpack、用于一些数学函数的numpy,以及用于测量执行时间的time包:
1
2
3from scipy import fftpack
import numpy
import time作为计算的第一步,创建一个变量,把FFT计算的结果存储为一个3D均匀标量场。
1
result = hx_project.create('HxUniformScalarField3')
为了测量执行时间,你首先需要在计算开始时取一个时间戳:
1
start_time = time.time()
为输入数据创建一个Python变量:
1
input = self.data.source()
要计算我们输入数据FFT的绝对值,请执行以下三条命令:
1
2
3
4
5
6
7
8# Compute the discrete Fourier transform
F1 = fftpack.fftn(input.get_array())
# Shift the zero-frequency component to the center of the spectrum
F2 = fftpack.fftshift(F1)
# Take the magnitude of all coefficient
F3 = numpy.abs(F2)计算完成后,把结果数组赋给你之前创建的result变量:
1
result.set_array(F3)
打印出FFT的总执行时间:
1
print("--- %s seconds ---" % (time.time() - start_time))
整个compute函数应当如下所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37def compute(self):
# Check if module's apply button has been touched by the user
if not self.do_it.was_hit:
return
# Check if input data is connected to a valid object
if self.data.source() is None:
return
# Import scipy package to perform fft
from scipy import fftpack
import numpy
import time
# Create the output field
result = hx_project.create('HxUniformScalarField3')
start_time = time.time()
# Retrieve the input data
input = self.data.source()
# Compute the discrete Fourier transform
F1 = fftpack.fftn(input.get_array())
# Shift the zero-frequency component
# to the center of the spectrum
F2 = fftpack.fftshift(F1)
# Take the magnitude of all coefficient
F3 = numpy.abs(F2)
# Affect to the output scalar field the resulting numpy array
result.set_array(F3)
# Show in console computation time
print("--- %s seconds ---" % (time.time() - start_time))为了让该模块在Avizo的图形用户界面中可用,你还需要编写一个资源文件。用你的文本编辑器创建一个新文件,并把它保存为ScipyFFT.rc。资源文件通常以一行注释开头:
1
2
3############################################################
# .rc for pyscro Scipy FFT
############################################################为该模块命名:
1
module -name "Scipy FFT" \
指定我们希望能够把它附加到的数据类型:
1
-primary "HxUniformScalarField3" \
把它声明为一个Python脚本对象:
1
-package "py_core" \
下一行定义它将出现在Avizo的Object Popup菜单中的位置:
1
-category "{Python Scripts}" \
运行几条TCL命令,以在Avizo的图形用户界面中初始化该模块。第一条命令将创建该脚本对象并为该模块设置一个标签:
1
2-proc {
set this [[create HxPythonScriptObject] setLabel "Python FFT"]设置文件名,以便为该模块找到Python脚本的位置,其中
<PRODUCT_PATH>即$AVIZO_ROOT:1
2
3
4"$this" startStop hideMaskIncrease
"$this" filename hideMaskIncrease
"$this" filename setValue \
<PRODUCT_PATH>/share/python_script_objects/ScipyFFT.pyscro该脚本将运行,以使更改生效:
1
2"$this" startStop hit 0
"$this" fire把数据集连接到你右键单击以创建该模块时所用的默认输入数据端口:
1
2
3
4
5if { [exists $PRIMARY] } {
$this data connect $PRIMARY
$this fire
}
}最终整个资源文件将如下所示,其中
<PRODUCT_PATH>即$AVIZO_ROOT:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22############################################################
# .rc for pyscro ScipyFFT
############################################################
module -name "Scipy FFT" \
-primary "HxUniformScalarField3" \
-package "py_core" \
-category "{Python Scripts}" \
-proc {
set this [[create HxPythonScriptObject] \
setLabel "Python FFT"]
"$this" startStop hideMaskIncrease
"$this" filename hideMaskIncrease
"$this" filename setValue \
<PRODUCT_PATH>/share/python_script_objects/ScipyFFT.pyscro
"$this" startStop hit 0
"$this" fire
if { [exists $PRIMARY] } {
$this data connect $PRIMARY
$this fire
}
}为了让这个Python脚本对象在Avizo中可用,你需要把这两个文件都复制(覆盖已有文件)到
$AVIZO_ROOT/share/python_script_objects/,并在按上述步骤修改资源文件之后重启Avizo。如果你想重新使用嵌入式的Python FFT示例,请编辑
$AVIZO_ROOT/share/python_script_objects/ScipyFFT.rc文件,并把-category的值从"None"改为"{Python Scripts}"。要测试该模块,请执行以下操作:
- 启动Avizo。
- 加载
$AVIZO_ROOT/data/tutorials/chocolate-bar.am - 右键单击该数据对象,并从Object popup中选择Python Scripts/Scipy FFT。
- 单击Apply,
Project View中就会显示出一个包含所生成FFT的新数据对象。
11.7 在Avizo中使用MATLAB
本节描述如何在Avizo中使用MATLAB Scripts。
11.7.1 使用MATLAB脚本
在本教程中,你将学习如何借助Calculus MATLAB模块,使用MATLAB(The MathWorks, Inc.)把复杂的计算集成到Avizo中。
为了使用Calculus MATLAB模块,MATLAB必须已在你的计算机上正确安装。此外,为了让该模块能够与MATLAB计算引擎建立连接,你可能需要注册MATLAB引擎(在Windows上),并根据你的系统设置环境变量,以便把MATLAB库或程序包含到搜索路径中。关于安装细节和限制,请参阅Calculus MATLAB模块的文档。
本教程可在在线文档中获取,它通过各种示例涵盖以下主题:
- 加载并执行一个MATLAB脚本。
- 把各种数据类型从Avizo传递到MATLAB,并把它们导出回来。
- 使用field结构。
- 用时间滑块控制脚本变量。
- 从脚本中调用用户自定义的MATLAB函数。
