この記事では、ZOS-API を使用して任意のシーケンシャル面をグリッド サグ面に置き換える Mathematica と Matlab のコードを取り上げます。グリッド サグ面は高度なカスタマイズが可能であり、OpticStudio のネイティブな公差解析アルゴリズムでは容易に表現できない誤差や構造の表現に使用できます。
著者 Alexandra Culler & Erin Elliott
Downloads
Introduction
「How to use the Grid Sag surface type」では、グリッド サグ面を手動でインポートする方法を取り上げました。「"How to write a Grid Sag DAT file programmatically」では、それに対応する DAT ファイルをプログラムで作成する方法を紹介しています。この記事では、ZOS-API を使用して、作成済みの光学系にある面を更新し、その変更前後の光学系の性能を比較します。今回の比較は、スポット ダイアグラムと波面収差によって行われます。
このプロセスの動作を確認した後、プロセスの自動化に有効な各種モジュールを紹介します。
レンズ データ エディタとシステム エクスプローラのモジュール
このチュートリアルでは、レンズ データ エディタ (LDE : Lens Data Editor) とシステム エクスプローラからデータを API に取り込むことができるコードをいくつか扱います。これにより、モデルに適用した更新を追跡できます。
Matlab では、関数と呼ばれるこれらのコードがアプリケーションの末尾以降で定義されています。これらの関数は、その名前を入力することでいつでも呼び出すことができます。現在のところ、その出力先はコマンド ウィンドウに限られていますが、テーブル出力はポップアップとして表示されるように変更できます。
これらのどちらの関数にも、以下の変数が設定されているという前提があります。
TheLDE = TheSystem.LDE
SystemData = TheSystem.SystemData
これらの変数名を変更した場合は、モジュールと関数でも同様の変更が必要になります
サンプル ファイル「Cooke 40 degree field.zmx」を開いて光学系の観察
作業を開始するに当たり、添付の API プログラムによって、デフォルトの {Zemax}\Samples フォルダに API フォルダがあるかどうかが確認されます。このフォルダが存在しない場合は、自動的に作成されます。
この確認が完了すると、{Zemax}\Samples\Sequential\Objectives にある Cooke 40 degree field.zmx ファイルが API によって開き、適切な API フォルダに別名で保存されます。この別名は「Cooke 40 degree field_Surf1_GridSag.zmx」です。
このファイルを API によって正しく取得したことを確認するために、LDE とシステム エクスプローラの各モジュールを使用して現在の光学系を確認します。これらのモジュールによって、LDE とシステム エクスプローラに次のような初期設定が適用されます。
第 1 面の更新に伴う面のプロパティの変化を追跡する際に、この情報は役に立ちます。標準面をグリッド サグ面に置き換えても、ほかには何も変化しないことを確認する必要があります。
まず、光学系に設定されている変数とソルブを削除します。これにより、第 1 面を置き換える時点ですべての距離と曲率半径が固定さていることを確定させます。
surf6 = TheLDE.GetSurfaceAt(6);
surf6Radius = surf6.Radius;
TheSystem.Tools.RemoveAllVariables();
solver = surf6.RadiusCell.CreateSolveType(ZOSAPI.Editors.SolveType.Fixed);
&surf6.RadiusCell.SetSolveData(solver);
surf6.Radius = surf6Radius;
第 1 面に関連する情報を取り出す必要があります。ナレッジベースの記事「How to write a Grid Sag DAT file programmatically」にある説明のように、DAT ファイルを生成するには面の半径、曲率半径、コーニック定数が必要です。以下のコマンドを使用してこれらの情報を取り出すことができます。
Surface1 = TheLDE.GetSurfaceAt(1);
SemiDiaSurf1 = Surface1.SemiDiameter;
RadiusSurf1 = Surface1.Radius;
CurvatureSurf1 = 1/RadiusSurf1;
ConicSurf1 = Surface1.Conic;
これらの取得した値を LDE の値と比較することで、容易に正しい情報が得られていることを確認できます。
現在の光学性能の確認
ここでの目的は、第 1 面をそれと同等なコピーで置き換えることです。このタスクを完了したことを確認するには、置き換え前後の光学系の性能を比較する必要があります。まず、現在の光学系のスポット ダイアグラムと波面収差の情報を把握します。その作業は、ナレッジベースの記事「ZOS-API を使用してシーケンシャル面に同心円状リップルを追加する方法」の説明にある API で実行できます。ここでは、OpticStudio でファイルを手動で開くことで、この性能を簡単に確認します。
[解析] (Analyze) → [光線とスポット] (Rays & Spots) → [標準スポット ダイアグラム] (Standard Spot Diagram) に移動してスポット ダイアグラムにアクセスします。光線密度を 25 に更新します。
[解析] (Analyze) → [波面収差] (Wavefront) → [波面収差マップ] (Wavefront Map) に移動して波面収差マップにアクセスします。解像度を 512x512 に更新します。[波長] (Wavelength) を 2、[視野] (Field) を 1 に設定します。
これらの解析結果を読み取ると、次の光学系性能が得られます。
性能 | 値 |
視野 1 の RMS スポットサイズ | 5.054 |
視野 2 の RMS スポットサイズ | 15.361 |
視野 3 の RMS スポットサイズ | 11.900 |
波面収差 PTV | 0.6434 |
波面収差 RMS | 0.1829 |
第 1 面のサグ プロファイルの取り出し
面の形状の変化を追跡するには、面のサグ ツールから API に情報を取り出します。このツールは、UI の [解析] (Analyze) → [面] (Surface) → [サグ] (Sag) にあります。一般的には、高解像度の条件下で面の最も正確な表現が得られます。OpticStudio には、次の解像度オプションが用意されています。
- 33x33
- 65x65
- 129x129
- 257x257
- 513x513
- 1025x1025
- 2049x2049
- 4097x4097
- 8193x8193
- 16385x16385
DAT ファイルの作成には、面のサグのプロットで選択した解像度を使用します。DAT ファイルによるメモリ消費量は、そのサイズに比例して増加します (「How to use the Grid Sag surface type」の記事にこれについての説明があります)。したがって、レンズ ファイルの性能が低下しない範囲で合理的に高い解像度を選択します。
次のコマンドを使用して、面のサグのプロットとその設定を開くことができます。
% Open sag plot and update settings
SurfSag = TheSystem.Analyses.New_SurfaceSag();
SagSettings = SurfSag.GetSettings();
第 1 面の解析に重点を置いて、解像度が 513x513 になるように、この設定を次のように変更します。
SagSettings.Sampling = ZOSAPI.Analysis.SampleSizes_Pow2Plus1_X.S_513x513;
SagSettings.Surface.SetSurfaceNumber(1);
SurfSag.ApplyAndWaitForCompletion();
この設定を適用することで、次のコマンドを使用してサグ データを取り出すことができます。
% Grab the data from the surface sag plot
Surf1 = SurfSag.GetResults();
Surf1Dat = Surf1.GetDataGrid(0);
Surf1Results = flipud(Surf1.DataGrids(1).Values.double);
npix = Surf1Dat.Nx;
dx = Surf1Dat.Dx;
SurfSag.Close();
このコマンドでは、倍精度値のマトリックス「Surf1Results」にデータを取り込みます。DAT ファイルの生成に使用するために、解像度と点間隔の情報も取り出します。この手順については、ナレッジベースの記事「How to write a Grid Sag DAT file programmatically」に詳しい説明があります。
このデータは矩形マトリックスとして API に取得されますが、面のプロファイルは円形です。つまり、面のサグの外部にあって破棄された値が存在します。Matlab では、この位置に「NaN」が記述されます。次のコードを使用して、この値を「0」に置き換えます。
Surf1Results(isnan(Surf1Results)) = 0;
適切なデータを取り出したことを確認するには、この新しいマトリックスを使用してプロットを生成し、OpticStudio の GUI で得られた面のサグのプロットと比較します。この様子を以下に示します。左側は Matlab 出力、右側は同じ設定による OpticStudio 出力です。
プロットの見かけは異なりますが、その傾向は同じです。この 2 つのプロットを比較することで、傾斜やエッジの不自然なアーチファクトがないか確認します。この図においては、そのようなものは見られません。
配列へのデータの保存
面サグのプロットは、視覚的な補助手段としては効果的ですが、DAT プロットに書き込めるほどの精度を備えていません。その原因は、面外部では値がゼロであるという大幅な前提を設定していることにあります。目的の DAT ファイルに使用できるような高精度の値を取得するには、SSAG 最適化オペランドを使用してサグのプロファイルのデータを取り出します。SSAG オペランドでは、アパチャー外部へサグのプロファイルの値を外挿します。このオペランドのパラメータは次のとおりです。
SSAG オペランドを使用して、面のサグのプロットと同じ解像度になるようにマトリックスに値を配置します。このマトリックスでは、点間隔が次の式による値になります。
この値は、面のサグのプロットにある点間隔と同じ値です。この値は dx として保存されています。
Matlab では、まず点間隔を表す 2 つの配列を生成する必要があります。この手順については、ナレッジベースの記事「How to write a Grid Sag DAT file programmatically」に説明があります。このマトリックス生成のコード全体は次のようになります。
fullSurfSag = zeros(npix);
xvals = linspace(-surf1SemiDiameter, surf1SemiDiameter, npix);
yvals = linspace(-surf1SemiDiameter, surf1SemiDiameter, npix);
% Use the arrays to generate points to place within the sag matrix
for col = 1:length(fullSurfSag)
for row = 1:length(fullSurfSag)
fullSurfSag(col, row) = TheMFE.GetOperandValue(ZOSAPI.Editors.MFE.MeritOperandType.SSAG, 1, 0, xvals(col), yvals(row), 0, 0, 0, 0);
end
end
生成したこのマトリックスは DAT ファイルに直接読み込むことができます。
第 1 面からグリッド サグ表現への置き換え
「How to write a Grid Sag DAT file programmatically」の記事にある説明のように、サグ情報を DAT ファイルに変換する手順の第 1 歩は、マトリックスを 263169x1 の配列に「平坦化」することです。このように平坦化することで、DAT ファイルの新たな行に一度に 1 つの値を書き込む処理を繰り返すことができます。
Matlab でこの操作を実行するには次のコマンドを使用します。
Surf1DataClean = fullSurfSag(:);
この情報を DAT ファイルに書き込むためのコードとその詳しい説明が「How to write a Grid Sag DAT file programmatically」にあります。
DAT ファイルを生成すると、API を使用して面 1 を置き換えることができます。まず、面タイプをグリッド サグ面に更新します。つづいて、面 1 の曲率とコーニックの値を「0」に変更します。このように変更する理由については、「How to use the Grid Sag surface type」に詳しい説明があります。
最後に、元の面のサグ プロファイルの複製となった DAT ファイルをインポートします。
この処理のためのコードを以下に示します。
% Change the surface type to Grid Sag
Surf1TypeSetting = Surface1.GetSurfaceTypeSettings(ZOSAPI.Editors.LDE.SurfaceType.GridSag);
Surface1.ChangeType(Surf1TypeSetting);
Surface1.Radius = 0;
Surface1.Conic = 0;
% Import the data file
Surface1.ImportData.ImportDataFile(filename1);
変更が適用されたことを確認するには、displayLDE()
関数をもう一度呼び出します。第 1 面のタイプが「グリッド サグ」で、第 1 面のコメントに DAT ファイルの名前が記されていれば、変更が適用されています。
また、面のサグのプロットをもう一度呼び出して、新しい面による出力を元の面による出力と比較します。これら 2 つの面は、定量的に同じであると考えられます。
これらの変更を保存して、この新しい性能を OpticStudio の GUI で確認します。
TheSystem.SaveAs(updatedFile);
更新した光学系での性能の確認
得られた光学系がこの記事に添付されています。その光学系を開くと、その性能は次のようになっています。
性能 | 値 | 変換前との値の差 |
視野 1 の RMS スポットサイズ | 5.057 | 0.003 |
視野 2 の RMS スポットサイズ | 15.363 | 0.002 |
視野 3 の RMS スポットサイズ | 11.897 | 0.003 |
波面収差 PTV | 0.6441 | 0.0007 |
波面収差 RMS | 0.1831 | 0.0002 |
上記のデータを見ると、標準面による光学系とグリッド サグによる光学系との差異はわずかであることがわかります。この誤差は、選択した解像度に起因していると考えられます。選択した解像度が高いほど、この差異は小さくなるからです。
この差異が品質保証上の問題になるほど大きいかどうかは、ユーザーの判断によります。DAT ファイルの解像度が高いほど、それを光学系にインポートするときにメモリ消費が多くなることには注意が必要です。したがって、精度と速度の適切な折衷点を見出すことが重要です。
同様に、点間隔の有効数字桁数に応じて、この差異が小さくなります (今回の場合は10^-3 のオーダー)。デフォルトの有効数字桁数はプログラムによって異なります。
自動化に向けた関数の生成
ここまでの議論で、シーケンシャル面を DAT ファイルに変換するプロセスを理解できれば、複数の API ファイルで使用する関数とモジュールを生成することもできます。このチュートリアルでは displayLDE
と displaySystemExplorer
.の2つの関数からスタートできます。本チュートリアルの添付ファイルからさらに次の 3 つのモジュールを作成できます。
getSag
: 面を視覚化できるように面のサグのプロットを開きます。getExtendedSag
: DAT ファイルに書き込めるサグのプロファイル全体を生成します。makeDatFile
: サグの配列を平坦化し、{Zemax}\Objects\Grid Files フォルダに DAT ファイルを作成します。
これらの新しい 3 つの Mathematica 用のモジュールは、添付されている Mathematica ファイル末尾のセクション 8 にあり、同様に 3 つの Matlab 関数は、提供されているサンプルに独立した Matlab ファイルとして用意されています。
ZOS-API への Mathematica の接続に関する注記
Mathematica は OpticStudio でデフォルトとして採用されているの API 言語ではないので、OpticStudio に接続するにはボイラープレート コードを手動で作成する必要があります。用意されているコードでは、Mathematica の NETLink 機能を使用して OpticStudio の場所が検索されます。ただし、このコードでは、有効なライセンスがあるかどうかや、開いている OpticStudio セッションの数などは確認されません。このコードを実行できない場合は、最大数の OpticStudio セッションが開いていないかどうかを確認してください。
このような違いはあっても、API のコマンドは Matlab のコマンドにきわめてよく似ています。主な大きな相違点を以下に挙げます。
- Mathematica では、LDE とシステム エクスプローラの各関数 (モジュール) は、用意されているコードのセクション 2 にあります。これらのモジュールは、そのタイトル
displayLDE
やdisplaySystemData
を入力することで、コードのどの時点でも呼び出すことができます。 - Mathematica では、変数名の先頭文字は小文字です。これは、組み込み関数との混同を避けるためです。
- Matlab で「NaN」と記された点は、Mathematica では「Indeterminate」と表記されます。このデータを「0」に変換する演算が、新しいマトリックス「surf1DataClean」を生成する操作に組み込まれています。この操作を以下に示します
surf1DataClean = Table[If[NumberQ[surf1Data@Z[j-1, k-1]] == True, surf1Data@Z[j-1, k-1], 0], {j, 1, npix}, {k, 1, npix}];
- 点間隔を明示的に宣言する Mathematica のコードが、マトリックスを生成する操作に直接組み込まれています。この操作を以下に示します。
fullSurfaceSag = Table[theMFE@GetOperandValue[MeritOperandType`SSAG, 1, 0, xcoord, ycoord, 0, 0, 0, 0], {xcoord, -surf1SemiDiameter, surf1SemiDiameter, dx}, {ycoord, -surf1SemiDiameter, surf1SemiDiameter, dx}]
- Mathematica のコードによる DAT ファイル生成では、指定されたディレクトリに同じ名前のファイルがあるかどうかが確認されます。Mathematica にはファイルを上書きする権限がないので、必要に応じてユーザーがファイル名に繰返し回数の数字を付加できるようにするコード行があります。
KA-01969
コメント
記事コメントは受け付けていません。