用户可以使用Zemax编程语言 (Zemax Programming Language,ZPL) 在OpticStudio中编写自己的程序。这些程序可以实现:
自动重复键盘和鼠标的操作
基于OpticStudio的数据进行计算
以特定格式输出数据
以图表或表格的形式生成数据
以及很多其它的功能!
创建ZPL宏程序非常简单。本文概述了ZPL的主要功能、变量示例,描述了ZPL中重要的函数和关键词。
作者 Dan Hill, updated by Alessandra Croce
ZPL是不区分大小写的“宏”或“脚本”语言,并且是扩展OpticStudio计算范围的最简单方法。它是根据BASIC建模的,并且是一种解释型语言。这意味着编写ZPL宏非常容易,但是这也意味着进行复杂计算时,其执行速度要比完全编译的代码慢。
ZPL脚本可以调用OpticStudio中已编译的函数(关键字和操作数),并且在以下情况下很实用:
当您需要特殊格式的数据
实现不在程序中的功能或计算,例如数据提取,导出或简单绘图
在没有适当的操作数时进行优化(创建自定义操作数)
创建自定义/复杂求解(创建自定义求解)
自动重复键盘的操作
请注意,ZPL不能用于编辑用户自定义表面或物体,若有需要,您可以使用DLL。
ZPL包含五个基本概念:变量 (variables)、运算符 (operations)、函数 (functions)、关键词 (keywords) 和注释 (comments)。以下将对这些概念进行介绍,可以在OpticStudio帮助手册的“编程 ( Programming) 选项卡> 关于ZPL(About the ZPL) ”部分查阅更多信息。
ZPL的目标是为没有太多编程经验的光学工程师提供强大的编程工具,该工具可以快速执行,并且易于学习。OpticStudio还支持ZOS-API,这是API级别的接口,外部程序(例如Matlab或Python)可以通过ZOS-API访问OpticStudio的功能。想要了解更多信息,请查看文章 " 什么是 ZOS-API ,作用是什么?" 。
基本的赋值语法为:
variable = expression
其中 “ = ” 意为“将值设为”。
变量可以是数值 (numeric) 或字符串 (string),这取决于它们所包含的数据类型。表达式可以是确切值、其它变量或复杂的数学表达式/函数。只有数组变量需要在使用前声明,因此例如 x = 7
无需提前声明数字变量 x
即可工作。如下有效赋值的示例:
x = 4
y = 3
z = x y
字符串变量名称中的最后一个字符必须带有 $ 字符:
newstring$ = "Here is the new string"
变量始终保持为双精度64位值。它们的名称有一些必须遵守的限制。变量名称不应:
超过28个字符
包含用作运算符的任何特殊字符 (*, !, <, &, 等)
包含任何空格 (改为使用 “ _ ”)
与关键字或函数相同
ZPL还支持数组(或向量)变量,有4个预定义的向量,分别称为VEC1, VEC2, VEC3,
和VEC4
, 主要由其他命令(例如GETPSF
, GETMTF
, 等)使用,它们的大小由SETVECSIZE
关键字设置。
用户自定义数组变量必须在使用前用DECLARE
关键字声明。它们最多可以由4维构成,并可以为双精度或整数数据类型。必须使用RELEASE
关键字释放分配给数组的内存。
可以使用以下语法给用户自定义数组赋值:
arrayname(index1, index2, …) = value
可以使用以下语法提取值:
value = arrayname(index1, index2, …)
ZPL中的命令分为两类:
使用关键字可以在 OpticStudio 中执行或更改某些内容,例如:
RAYTRACE
通过系统追迹特定的光线
SETUNITS
设置系统单位
PRINT
打印一些内容到屏幕或文件
使用函数可以在 OpticStudio 中报告某些内容,例如:
y_height = RAYY(5)
, 报告表面5上的光线截距的Y坐标
lens_units$ = $UNITS()
, 报告系统的镜头单位
本文将给出关键字和函数的一些示例,这些示例涵盖了OpticStudio中可用的整个光线追迹和物理光学计算范围。请参阅OpticStudio帮助文件,以查看所有支持的函数,关键字和常规ZPL功能。
关键字和函数是对OpticStudio中已编译例程的调用,通常与功能区 ( Ribbon Bar ) 中相关功能的工作原理非常相似。
RAYTRACE
=>
LOADARCHIVE
=>
它们的执行速度与内部命令一样快,而调用命令的消耗却很小。因此,不要认为ZPL太“慢”!但是请记住,宏中的显式计算将被解释执行,因此与已编译的程序相比速度较慢。如果宏内部的计算速度很重要,请改用 ZOS-API.NET 。
关键字可以指导程序流程(IF或FOR语句),或运行光线追迹或调整透镜参数等。例如,使OpticStudio将系统优化10圈,可以发送以下命令:
OPTIMIZE 10
同样,执行此代码与您按下“优化( Optimize )”按钮并在图形用户界面中选择“ 10圈( 10 Cycles )”完全相同。
在Zemax早期,编写了诸如GETMTF
和GETZERNIKE
之类的关键字以访问相应的分析功能。但是,随着代码库的增加,这很快变得很单调。因此,通过其关联的优化操作数可以访问大多数分析功能。这可以通过评价函数执行,也可以直接使用 OPEV()
or或 OPEW()
数值函数从宏中调用操作数本身来执行。有关更多详细信息,请参见 "如何使用 OPEV 和 OPEW 获取ZPL宏中任意优化操作数的值" 。
如前所述,函数与关键字不同,因为它们不执行或更改文件中的任何内容,而是使OpticStudio生成有关某些内容的报告。ZPL支持多种函数,包括数值和字符串。数值函数的示例是:
x = SQRT(y)y = ABSO(z*TANG(e*numpoints))pi = 4*ATAN(1)
相反,字符串函数以 $ 符号开头,例如:
$DATE()$LENSNAME()surf3_glass$ = $GLASS(3)
与关键字不同,函数只能在赋值的右侧,或者在作为关键字参数的表达式中使用。某些函数(例如PWAV()(报告系统的主波长))返回的值与参数无关,因此不需要提供该值。但是,仍然需要括号。
ZPL支持基本的数值运算(加法,减法,除法,乘法)和字符串运算(加法)。两种运算的示例如下:
Z = (X 1)/(Y * 6)
R$ = "Hello " "World"
将字符串"Hello World"
赋给变量R$
其他数值和字符串函数,例如SINE(), SQRT(), $GETSTRING()
, 等,可用于更复杂的运算。可以使用括号来自定义运算序列,否则默认运算序列为:函数(例如SQRT()
), 逻辑运算符(例如>
), 乘法和除法,加法和减法。
ZPL还支持逻辑运算符,包括数值和字符串。这些可用于逻辑测试以及对多个表达式的比较。逻辑运算的结果为“真(TRUE)”(任何非零值)或“假(FALSE)”(零)。OpticStudio将零视为“假”,将任何非零值视为“真”。
数值逻辑运算符表格如下:
& (AND) | > (GREATER THAN) |
| (OR) | < (LESS THAN) |
^ (XOR) | > = (GREATER or EQUAL) |
! (NOT) | < = (LESS or EQUAL) |
= = (EQUAL) | ! = (NOT EQUAL) |
数值逻辑运算符的示例如下:
IF(A > 5) THEN PRINT "A is greater than 5"
字符串逻辑运算符的表格如下:
$ = = (EQUAL) | $ > = (GREATER or EQUAL) |
$ > (GREATER THAN) | $ < = (LESS or EQUAL) |
$ < (LESS THAN) | $ ! = (NOT EQUAL) |
字符串逻辑运算符示例如下:
IF (C$ $== B$) THEN PRINT "Strings are identical"
错误使用运算符 “=
” 和逻辑运算符 “= =
”很常见。
例如,下图中的宏:
在此宏中,“a = b
”是赋值,读取为“将变量a的值设置为等于变量b的值”。由于操作成功,所以OpticStudio将a的值设置为等于b,并返回“真”。因此,宏可写为:
IF (TRUE)
PRINT "a equals b"
ELSE
PRINT "a does not equal b"
ENDIF
在这种情况下,OpticStudio会发现错误并返回:
Syntax error: Illegal assignment (a = b).
可以使用逻辑运算“a == b
”来进行正确的操作。
ZPL可以进行IF与FOR的条件循环。
IF循环的语法如下:
IF (expression)
(commands)
ELSE
(commands)
ENDIF
或
IF (expression) THEN (single command)
IF循环通常与逻辑运算符一起用作表达式语句中的测试条件。例如:
IF (X < Y)
PRINT "X is less than Y"
ELSE
PRINT "X is greater than Y"
ENDIF
请注意,有一些要留给用户来发现的错误,例如,如果x = y会怎样?
FOR循环的语法如下:
FOR variable, start_value, stop_value, increment
(commands)
NEXT
例如:
FOR i, 1, 10, 1
PRINT i
NEXT
同时定义变量和起始值的以下语法也是有效的:
FOR i = 1, 10, 1
请注意,start_value和stop_value可以是显式数字,也可以是任何计算结果为数字的变量或表达式。增量应该是整数,或者是任何取值为整数的变量或表达式。
关键字 CALLMACRO
可以用一个宏(父级)调用另一个宏(子级)。数字和字符串缓冲区可以在父宏和子宏之间共享数据。示例宏“ Parent.ZPL”和“ Child.ZPL”都包含在OpticStudio安装文件中,并在帮助文件的“编程 ( Programming ) 选项卡>关于ZPL ( About the ZPL ) >从宏中调用宏 ( Calling a Macro from within a Macro )”部分进行了描述。
关键字GOSUB
可以执行跳转到SUB
指示的子例程。子例程完成执行后,控制其值返回到GOSUB
关键字之后的行。在整个宏中,可以多次调用子例程。请注意,它们是在同一个宏中定义的,与前述的分离的父/子宏的情况不同。有关子例程的更多信息,请参见OpticStudio帮助文件的“编程( Programming )选项卡>关于ZPL( About the ZPL ) >关键字( KEYWORDS ) > GOSUB,SUB,RETURN和END”部分。
对于要在序列模式下使用的宏,最重要的关键字之一是RAYTRACE
,它追迹给定波长的单条光线(由归一化视场和光瞳坐标确定)。关键字没有其他作用,语法为:
RAYTRACE hx, hy, px, py, wave
例如:
RAYTRACE 0, 1, 0, 0, PWAV()
,在主波长处追迹主光线。
然后,您可以使用后续函数提取任何相关的光线追迹数据,例如:
RAYX(x), RAYY(x),
和 RAYZ(x)
,返回表面 x 上的光线的X-,Y-和Z-坐标
RAYL(x), RAYM(x),
和 RAYN(x)
,返回表面x上的光线的方向余弦值
RANX(x), RANY(x),
和 RANZ(x)
,返回光线击中表面x处的表面法线余弦值
RAYT(x)
返回光线到表面 x 的光路长度
OPDC()
返回光线相对于主光线的光程差
例如,以下代码追迹波长2的边缘光线。然后将像面上光线的Y坐标截距提取并打印在屏幕上:
RAYTRACE 0, 0, 0, 1, 2
PRINT "The chief ray height is ", RAYY(NSUR())
函数RAYE()
报告追迹光线时可能发生的任何错误:
如果在光线追迹过程中未发生任何错误,则返回零。
负值表示在该表面上发生了全内反射,该表面序号数是返回值的绝对值
正值表示光线错过了返回的表面编号
检查RAYE()
是可选操作,但是,如果RAYE()
不返回零,则上述数据提取函数可能会返回无效数据。
函数RAYV()
可用于检查光线是否存在渐晕,即是否被孔径挡住了。该函数返回光线存在渐晕的表面编号;如果光线未发生渐晕,则返回零。请记住,如果光线照射到孔径上,仍会被追迹,并且可以通过使用RAYV()
测试是否发生渐晕来将其排除在计算之外。
RAYTRACEX
关键字是RAYTRACE
的实用扩展。它调用OpticStudio光线追迹例程,从任意表面起始追迹当前系统中的特定的光线。语法为:
RAYTRACEX x, y, z, l, m, n, surf, wave
如上所述,然后可以使用与RAYTRACE
相同的后续功能提取有关光线追迹的数据。
最后,您可以使用注释来标注ZPL宏是如何工作的。任何以“!”为起始的行,或任何“#”后输入的字符都将作为注释,这些内容在执行ZPL宏时被忽略。OpticStudio将仅执行将这些组件包在一起的脚本。
例如,想像您需要优化镜头,计算评价函数值,并将该值乘以5的对数,相应的ZPL如下所示:
执行ZPL宏的速度非常快,并且ZPL是非常容易学习和使用的语言。为了帮助您入门,知识库中有一些介绍Zemax编程语言某些功能的文章,并且OpticStudio下载文件中提供了许多示例。