Zemax プログラミング言語 (ZPL) を使用すると、OpticStudio 内部で独自のプログラムを作成できます。このようなプログラムにより、次の操作が可能になります。
- 繰り返しの多いキーボード入力やマウス操作の自動化
- OpticStudio のデータを使用した計算の実行
- 特定のフォーマットによるデータのエクスポート
- データのグラフや一覧表の生成
これらのほかにも数多くの可能性があります。
ZPL マクロは容易に作成できます。この記事では、ZPL の主要な機能のほか、きわめて重要な関数やキーワードの変数について例を紹介し、その動作について説明します。
著者 Dan Hill, updated by Alessandra Croce
序論
ZPL は、大文字と小文字を区別せずに記述できる「マクロ」言語 (「スクリプト」言語) です。ZPL を使用すると、OpticStudio の多彩な計算機能を容易に拡張できます。BASIC にならったインタープリタ言語です。したがって、コーディングは容易ですが、複雑な計算になると、本格的にコンパイルしたコードよりも実行速度は遅くなります。
それでも、OpticStudio の内部で ZPL スクリプトからコンパイル済み関数 (キーワードとオペランド) を呼び出すことができるので、特に次のような場合に威力を発揮します。
- データに独自のフォーマットが必要な場合
- プログラムに用意されていない機能や計算を実装する場合 (データの取得やエクスポート、簡単なプロットなど)
- 目的の最適化に最適なオペランドがない場合 (カスタム オペランドの作成)
- 独自のソルブや複雑なソルブを作成する場合 (カスタム ソルブの作成)
- 繰り返し実行するキーボード操作を自動化する場合
注意 : ユーザー定義の面やオブジェクトを用意する用途では ZPL を使用できません。そのような目的には DLL を使用します。
ZPL は、5 つの基本的概念である、変数、演算、関数、キーワード、コメントで構成されています。これらの概念についてはこの後で説明しますが、OpticStudio のヘルプ ファイルの「[プログラミング] (Programming) タブ」→「ZPL について」に詳しい説明があります。
ZPL の目標は、プログラミングの経験に乏しい光学設計現場でも容易に習得して実行できる、強力なツールを提供することにあります。なお、OpticStudio では、ZOS-API の機能を使用できることも念頭に置いてください。これは、MATLAB や Python などの外部プログラムから OpticStudio の機能へのアクセスを実現する API レベルのインターフェイスです。詳細は、「ZOS-APIの使用方法」を参照してください。
代入、変数、配列
代入の基本的な構文は次のとおりです。
variable = expression
「=」は、「変数に値を設定する」という意味です。
変数 (variable) は、格納するデータの型に応じて文字列または数値とします。式 (expression) は、明示的な値、他の変数、複雑な数式または関数とすることができます。使用前に宣言が必要な変数は配列変数のみです。したがって、たとえば 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 の各コマンドは、次の 2 つのカテゴリに分類できます。
- キーワード : たとえば、次の処理や変更の実行を OpticStudio に 指示するために使用します。
RAYTRACE : 光学系の中で特定の光線を追跡します。
SETUNITS : 光学系の単位を設定します。
PRINT : 画面またはファイルにデータを出力します。
- 関数 : たとえば、次のデータの報告を OpticStudio に指示するために使用します。
y_height = RAYY(5)
: 面 5 における光線と面の交差点の Y 座標を報告します。lens_units$ = $UNITS()
: 光学系のレンズ ユニットを報告します。
この記事で紹介する例は数点に過ぎませんが、OpticStudio で使用できる光線追跡や物理光学のさまざまな計算すべてに対応した多数のキーワードと関数が用意されています。使用できる関数、キーワード、一般的な ZPL 機能のすべてについては、OpticStudio のヘルプ ファイルを参照してください。
キーワード
キーワードと関数は、コンパイル済みルーチンを OpticStudio 内部で呼び出す機能です。通常、次のようなリボン バー上で該当する機能にきわめて近い動作を提供します。
RAYTRACE
=>
LOADARCHIVE
=>
これらのキーワードは、コマンド呼び出しにごくわずかなオーバーヘッドが必要になるだけなので、内部コマンドと同等の速度で実行されます。したがって、ZPL は「遅い」と思い込まないことです。ただし、明示的にマクロの内部で実行される計算はインタープリタ型であることから、コンパイル済みのプログラムよりは低速である点に注意が必要です。マクロ自体の計算速度を重視する場合は ZOS-API.NET を使用します。
キーワードでは、プログラムの流れ (IF や FOR などのステートメント) の指定、または光線追跡やレンズ設定変更などの機能を実行できます。たとえば、10 回の反復処理による光学系の最適化を OpticStudio に指示するには、次のコマンドを送信します。
OPTIMIZE 10
この場合も、このコマンドで実行されるコードは、[最適化] (Optimize) ボタンをクリックして、グラフィカル ユーザー インターフェイスで 10 サイクルを指定した場合に実行されるコードとまったく同じです。
キーワードとオペランド
Zemax の初期のバージョンでは、GETMTF や GETZERNIKE などのキーワードを記述することで、対応する解析機能にアクセスできるようにしていました。しかし、コードの基盤が広がると、こうした方法では今後の作業が繁雑になることがすぐにわかりました。こうした理由から、解析関数に関連付けた最適化オペランドを通じて、ほとんどの解析機能を使用するようにしました。この操作は、評価関数を使用する方法、またはマクロから OPEV() や 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 でも、ゼロを FALSE、ゼロ以外の値を TRUE として取り扱います。
以下に、数値論理演算子の一覧を示します。
& (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 の値に等しく設定されますが、この演算が正常に終了したことにより、この式からは論理 TRUE が返されます。したがって、上記のマクロは次のように解釈できます。
IF (TRUE)
PRINT "a equals b"
ELSE
PRINT "a does not equal b"
ENDIF
このようにすると、OpticStudio ではエラーが検出され、次のメッセージが返されます。
Syntax error: Illegal assignment (a = b).
この場合の正しい記述は、代入演算子ではなく論理演算子を使用した "a == b" です。
IF および FOR の条件ループ
ZPL では、IF および FOR の条件ループの両方を使用できます。
IF ループの構文は次のとおりです。
IF (expression)
(commands)
ELSE
(commands)
ENDIF
または
IF (expression) THEN (single command)
IF ループは、通常、式 (expression) の値を判定する論理演算とともに使用します。以下に例を示します。
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) には、明示的な数値のほか、数値に評価される任意の変数または式を指定できます。増分 (increment) には、整数のほか、整数値に評価される任意の変数または式を指定できます。
マクロとサブルーチンの呼び出し
キーワード CALLMACRO を使用すると、1 つのマクロ (親) から別のマクロ (子) を呼び出すことができます。数値バッファと文字列バッファを介して、親と子のマクロ間でデータを共有できます。OpticStudio のインストール ファイルには、サンプル マクロとして "Parent.ZPL" と "Child.ZPL" が収められています。ヘルプ ファイルの「[プログラミング] (Programming) タブ」→「ZPL について」→「マクロからのマクロの呼び出し」には、これらのマクロについての説明があります。
キーワード GOSUB を使用すると、SUB で指定したサブルーチンに実行をジャンプできます。そのサブルーチンの実行が終了すると、キーワード GOSUB の次の行に制御が戻ります。マクロ全体を通して、サブルーチンを複数回呼び出すことができます。そのようなサブルーチンは、1 つの同じマクロに定義するものであり、前述の親マクロと子マクロ同様に、互いに独立したマクロではない点に注意が必要です。サブルーチンの詳細は、OpticStudio のヘルプ ファイルで、「[プログラミング] (Programming) タブ」→「ZPL について」→「キーワード (ZPL について)」→「GOSUB、SUB、RETURN、END」を参照してください。
RAYTRACE、RAYTRACEX、およびそれらに関連する関数
シーケンシャル モードでマクロを使用する場合、きわめて重要なキーワードとして 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() では、光線追跡で発生したと考えられるエラーがすべて報告されます。
- エラーが発生しなかった場合はゼロが返されます。
- 負数が返された場合は、その絶対値を面番号とする面で全反射 (TIR) が発生しています。
- 正数が返された場合は、その値を面番号とする面に光線が到達していません。
関数 RAYE() の確認は必須ではありませんが、RAYE() の戻り値がゼロ以外の場合、上記のデータ抽出関数から無効なデータが返されることが考えられます。
関数 RAYV() を使用すると、光線がビネッティングされたかどうか (アパチャーによる遮蔽があったかどうか) を確認できます。光線がビネッティングされた場合は、それが発生した面の番号が返され、ビネッティングされなかった場合はゼロが返されます。光線は、アパチャーに到達しても引き続き追跡されますが、ビネッティングが発生した場合は、RAYV() の結果に基づいて計算から除外できる点に注目してください。
キーワード RAYTRACEX は、RAYTRACE のきわめて便利な拡張機能です。このキーワードは、OpticStudio の光線追跡ルーチンを呼び出し、現在の光学系で任意の開始面から特定の光線を追跡します。構文は次のとおりです。
RAYTRACEX x, y, z, l, m, n, surf, wave
RAYTRACE に続いて記述した関数を、このコードに続いて同様に使用すると、光線追跡で得られたデータを抽出できます。
ZPL のコメント
最後に、コメントについて説明します。コメントを使用すると、ZPL プログラムの動作説明を記述できます。"!" で始まるすべての行、および "#" より後ろのすべてのテキストは、コメントとして扱われ、実行時は無視されます。OpticStudio では、これらのコメントを覆い隠した状態のスクリプトのみが実行されます。
たとえば、レンズを最適化して評価関数の値を計算し、その結果に自然対数 ln(5) を乗算する場合を考えます。その場合の ZPL マクロは次のようになります。
KA-01367
コメント
サインインしてコメントを残してください。