【raytracing】raytracingライブラリをより便利にする自作関数[Python]

  • URLをコピーしました!

raytracing

前回、raytracingライブラリでレンズに入らなかった光線を除外した光線図を描く方法を紹介しました。

今回はraytracingライブラリをより便利にする自作関数を紹介します。

紹介する際に基本とする光学系はこちらです。

from raytracing import *

path = ImagingPath()
path.append(Space(d=50))
path.append(Lens(f=10))
path.append(Space(d=50))
path.display(ObjectRays(diameter=1, halfAngle=np.radians(10), H=1, T=7))

実行結果

それでは始めていきましょう。

光線の高さ、位置、角度、アパチャーサイズの取得

最初にそれぞれの光学系における光線の高さ、位置、角度、アパチャーサイズを取得する関数です。

from raytracing import *
import numpy as np

def valueGet(path, angle_list):
    y_list = []; z_list = []; theta_list = []; aperture_list = []
    for angle in angle_list:
        ray = Ray(y=0,theta=np.radians(angle))
        trace = path.trace(ray)

        y_optics = []; z_optics = []; theta_optics = []; aperture_optics = []
        for data in trace:
            y_optics.append(data.y)
            z_optics.append(data.z)
            theta_optics.append(data.theta)
            aperture_optics.append(data.apertureDiameter)
        y_list.append(y_optics)
        z_list.append(z_optics)
        theta_list.append(theta_optics)
        aperture_list.append(aperture_optics)
    return y_list, z_list, theta_list, aperture_list

必要なのは光学系である「path」と光線の初期の角度を格納したリスト「angle_list」です。

「angle_list」よりそれぞれの角度を取得し、Ray関数で光線の作成、trace関数で「path」で指定した光学系における光線を計算します。

計算結果である「trace」はそれぞれの光学系における高さ、位置、角度、アパチャーサイズが格納されているので、それぞれを取得し、それぞれをリストにしてまとめて返すのがこの関数です。

使ってみるとこんな感じです。

from raytracing import *

path = ImagingPath()
path.append(Space(d=50))
path.append(Lens(f=10))
path.append(Space(d=50))

angle_list = np.linspace(-10, 10, 7)

y_list, z_list, theta_list, aperture_list = valueGet(path, angle_list)

print(y_list)

実行結果
[[0, 0, np.float64(-8.726646259971647), np.float64(-8.726646259971647), 
np.float64(-8.726646259971647), np.float64(26.17993877991494)], [0, 0, 
np.float64(-5.817764173314431), np.float64(-5.817764173314431), 
np.float64(-5.817764173314431), np.float64(17.453292519943293)], 
[0, 0, np.float64(-2.9088820866572154), np.float64(-2.9088820866572154), 
np.float64(-2.9088820866572154), np.float64(8.726646259971647)], 
[0, 0, np.float64(0.0), np.float64(0.0), np.float64(0.0), np.float64(0.0)], 
[0, 0, np.float64(2.9088820866572163), np.float64(2.9088820866572163), 
np.float64(2.9088820866572163), np.float64(-8.726646259971648)], [0, 0, 
np.float64(5.8177641733144325), np.float64(5.8177641733144325), 
np.float64(5.8177641733144325), np.float64(-17.453292519943297)], [0, 0, 
np.float64(8.726646259971647), np.float64(8.726646259971647), 
np.float64(8.726646259971647), np.float64(-26.17993877991494)]]

高さ、位置、角度、アパチャーサイズを格納したそれぞれのリストは光線ごとにまとめられており、その光線ごとのリストは光学系ごとの値が格納されています。

グラフへの描画

上の「valueGet関数」で光線の高さ、位置、角度、アパチャーサイズを取得した後に、それらを使っていく関数も作ってみました。

最初はグラフへの描画をする関数です。

raytracingライブラリではグラフに関しては色々なものが自動で設定されているため、簡単の描画することができますが、その反面、描画方法を自由に変えられないという問題もあります。

ということでこれまでに色々とグラフ描画を試してきましたが、その基本としてグラフ描画する関数も作ってみました。

from raytracing import *
import numpy as np
import matplotlib.pyplot as plt

def displayRays(y_list, z_list):
    fig = plt.figure()
    plt.clf()

    for y_ray, z_ray in zip(y_list, z_list):
        plt.plot(z_ray, y_ray, lw=0.5, color="red")

    plt.show()

「valueGet関数」で取得した高さのリスト「y_list」と位置のリスト「z_list」を使って光線を描画しています。

from raytracing import *

path = ImagingPath()
path.append(Space(d=50))
path.append(Lens(f=10))
path.append(Space(d=50))

angle_list = np.linspace(-10, 10, 7)

y_list, z_list, theta_list, aperture_list = valueGet(path, angle_list)

displayRays(y_list, z_list)

実行結果

焦点位置を書いたり、レンズを描いたりというのはこれまでに紹介していますので、よかったら参考にしてください。

光線の最後の位置の高さを取得

意外と使うのが光線の最後の位置の高さを取得することです。

def yLast(y_list):
    ylast_list = []
    for y_ray in y_list:
        ylast_list.append(y_ray[-1])
    return ylast_list

リストの操作だけなので簡単ですが、用意しておくと結構便利です。

from raytracing import *

path = ImagingPath()
path.append(Space(d=50))
path.append(Lens(f=10))
path.append(Space(d=50))

angle_list = np.linspace(-10, 10, 7)

y_list, z_list, theta_list, aperture_list = valueGet(path, angle_list)

print(yLast(y_list))

実行結果
[np.float64(26.17993877991494), np.float64(17.453292519943293), 
np.float64(8.726646259971647), np.float64(0.0), 
np.float64(-8.726646259971648), np.float64(-17.453292519943297), 
np.float64(-26.17993877991494)]

光線の最後の位置の角度を取得

光線の最後の位置の角度を取得するのも地味に便利です。

また図での角度と「theta_list」での角度はABCD行列の特性上値が違っていて、図の描画では「theta_list」は使っていないようです。

先ほど紹介した通り、図への描画は光線の高さである「y_list」と光線の位置である「z_list」で行われています。

つまりこれらを使って角度を計算した方が、図との整合性が取りやすいということです。

そのため「y_list」と「z_list」を使って角度を計算する関数を作成したというのがこちらの関数です。

import numpy as np

def angleCalc(y_list, z_list):
    anglecalc_list = []
    for y_ray, z_ray in zip(y_list, z_list):
        z1 = z_ray[-2]; z2 = z_ray[-1]
        y1 = y_ray[-2]; y2 = y_ray[-1]
        angle = np.degrees(np.arctan((y2-y1)/(z2-z1)))
        anglecalc_list.append(angle)
    return anglecalc_list

実行してみるとこんな感じです。

from raytracing import *

path = ImagingPath()
path.append(Space(d=50))
path.append(Lens(f=10))
path.append(Space(d=50))

angle_list = np.linspace(-10, 10, 7)

y_list, z_list, theta_list, aperture_list = valueGet(path, angle_list)

print(angleCalc(y_list, z_list))

実行結果
[np.float64(34.92011439853009), np.float64(24.958263876260798), 
np.float64(13.1001781333877), np.float64(0.0), 
np.float64(-13.100178133387706), np.float64(-24.958263876260805), 
np.float64(-34.92011439853009)]

最後の空間における結像位置

最後の空間の結像位置を計算する関数はこんな感じです。

def distanceCross(y_list, z_list):
    crosslast_list = []; crosstotal_list = []
    for y_ray, z_ray in zip(y_list, z_list):
        z1 = z_ray[-2]; z2 = z_ray[-1]
        y1 = y_ray[-2]; y2 = y_ray[-1]
        cross_last = -y1*(z2-z1)/(y2-y1)
        cross_total = cross_last + z1
        crosslast_list.append(cross_last)
        crosstotal_list.append(cross_total)
    return crosslast_list, crosstotal_list

最後の空間の前後の「y」と「z 」を取得し、光線の高さが0となる点を計算しています。

from raytracing import *

path = ImagingPath()
path.append(Space(d=50))
path.append(Lens(f=10))
path.append(Space(d=50))

angle_list = np.linspace(-10, 10, 7)

y_list, z_list, theta_list, aperture_list = valueGet(path, angle_list)

crosslast_list, crosstotal_list = distanceCross(y_list, z_list)

print(crosslast_list)
print(crosstotal_list)

実行結果
[np.float64(12.5), np.float64(12.5), np.float64(12.5), 
np.float64(nan), np.float64(12.5), np.float64(12.5), np.float64(12.5)]
[np.float64(62.5), np.float64(62.5), np.float64(62.5), 
np.float64(nan), np.float64(62.5), np.float64(62.5), np.float64(62.5)]
RuntimeWarning [in 4127235310.py]: invalid value encountered in scalar divide

次回はpipでライブラリのインストール時に「note: This error originates from a subprocess, and is likely not a problem with pip. error: subprocess-exited-with-error」でインストールに失敗する場合の対処法を紹介します。

ではでは今回はこんな感じで。

よかったらシェアしてね!
  • URLをコピーしました!

コメント

コメントする