Skip to content

원뿔 조명(Cone Illumination)

실제 카메라 시스템에서 각 픽셀에 도달하는 빛은 단일 방향이 아닌 렌즈 사출 동공(Exit Pupil)의 전체 영역에서 옵니다. ConeIllumination 클래스는 조명 원뿔을 가중 평면파(Planewave)로 분해하고 결과를 적분하여 이를 모델링합니다. 이 가이드는 실용적·코드 중심의 워크스루입니다.

이론 배경

기저 물리 — CRA, F 넘버와 원뿔 각도 관계, 동공 가중, 박막 필터 응답의 각도 의존 이동 — 은 픽셀 광학 효과박막 광학을 참고하세요.

원뿔 파라미터

인터랙티브 콘 조명 뷰어

CRA(주광선 각도)와 콘 반각이 픽셀 조명에 미치는 영향을 시각화합니다. 콘은 방향별 평행 광선 묶음들로 표현되며, 각 묶음은 마이크로렌즈와 고굴절률 스택을 통과하면서 스넬 법칙에 따라 굴절되어 방향별 초점으로 수렴합니다.

CRA:10.0°
마이크로렌즈 시프트:0.217 um
f/#:2.0
입체각:0.200 sr
마이크로렌즈시프트평탄화층컬러 필터포토다이오드묶음 초점공기실리콘

원뿔은 세 가지 제어값으로 기술됩니다: CRA(픽셀까지의 주광선각), F 넘버(θhalf=arcsin(1/2F)로 반원뿔각을 결정 — F/2.0 ≈ 14.5°), 그리고 동공 가중 함수. 원뿔 조명 QE는 원뿔 내 샘플링 방향의 평면파 QE를 가중 평균한 값입니다.

컬러 필터 관점에서 cone illumination이 중요한 이유

얇은 막 컬러 필터(또는 스택 내부의 Fabry-Pérot 공진기)는 경사 입사 시 투과 피크가 더 짧은 파장 쪽으로 이동합니다 — 대략 λ(θ)λ01(sinθ/neff)2. 따라서 CRA 한 점에서의 평면파 한 번만으로는 실제 유한 조리개 렌즈가 만드는 피크 broadening과 centroid blue-shift를 과소평가하게 됩니다. Goossens 외 (2018)는 이 효과에 대한 합성곱 모델과 중심파장 보정식을 유도했으며, 그 파라미터는 이 페이지에서 사용하는 CRA·F 넘버 그대로입니다. 즉, 본 페이지의 각도 샘플링이 그 모델과 일치하도록 만들어 주는 핵심이며, 샘플 수가 부족하면 피크 broadening이 충분히 해상되지 않습니다. 자세한 내용은 Key Papers § 6.4Thin Film Optics를 참조하세요.

인터랙티브: Fabry-Perot 원뿔 적분

아래 시뮬레이터는 Goossens 외 (2018)의 핵심 결과를 페이지 안에서 직접 재현합니다. CRA와 F 넘버를 조정해 보면, 적분된 투과 곡선이 평면파 곡선에 비해 단파장 쪽으로 이동하고 동시에 broadening되는 모습을 볼 수 있습니다. 파장 윈도와 샘플 수는 코드에서 ConeIllumination(cra_deg=..., f_number=..., n_points=...)를 통해 그대로 제어할 수 있습니다.

파브리-페로 원뿔 조명 시뮬레이터

Goossens et al. (2018), Appl. Opt. 57(26):7539의 핵심 결과를 재현합니다. 이미지 센서 위 단일 공진 Fabry-Perot 필터에 초점 광선이 입사할 때, 주광선 각도(CRA)와 F 넘버로 정의되는 원뿔에 대해 Airy 투과율을 적분하고 평면파 결과와 비교합니다.

원뿔 샘플 (위에서 본 모습, 센서 좌표계)
10°20°30°xywmaxw0가중치원뿔 외곽동공 ring (등반경)주광선
각 점은 원뿔 적분에 들어가는 평면파 샘플입니다. 축은 센서 좌표계의 방향코사인 (sinθ cosφ, sinθ sinφ)이며, 가는 호는 동일 동공 반경(equal r_pupil)을 가지는 샘플들을 잇습니다 — CRA가 0이 아니면 동심 동공 ring이 구면 위에서 기울어진 소원(small circle)이 되어 호처럼 보입니다. 컬러바는 동공 가중치 w(θ_local)을 표현하며, 가중치 셀렉터를 바꾸면 uniform / cosθ / cos⁴θ / Gaussian이 적분에 어떻게 다르게 기여하는지 비교할 수 있습니다.
0%25%50%75%100%420440460480500520540560580600투과율 T파장 (nm)수직 입사CRA 평면파원뿔 적분
피크 이동 (vs λ₀)
Δλ = -7.55 nm
평면파: -5.71 nm
반치폭 (원뿔)
27.48 nm
평면파: 18.28 nm nm
반원뿔 각도
14.48°
arcsin(1/2F)
피크 투과율
74.9%
평면파: 100.0%
모델 설명

단일 공진 Fabry-Perot 필터의 Airy 투과율은 다음과 같습니다

T(λ, θ) = 1 / [1 + F · sin²(δ(λ, θ) / 2)], 여기서 δ = (4π neff d cosθint) / λ, F = 4R / (1 − R)², neff sinθint = sinθ.

공진층 두께 d는 수직 입사에서 λ₀가 1차 피크에 오도록 d = λ₀ / (2 n_eff)로 고정됩니다. 각 원뿔 샘플에서 주광선 각도만큼 y-축으로 회전시켜 필터 법선에 대한 실제 입사각 θ를 구하고, 반원뿔 θ_h = arcsin(1 / 2F) 위에서 피보나치 나선으로 샘플링한 후 cosθ 가중치(aplanatic pupil)로 평균합니다.

원뿔 적분 투과율은 다음과 같습니다

Tcone(λ) = ∑i wi T(λ, θi) / ∑i wi.

이 두 가지 결과 — centroid의 blue-shift(원뿔 평균 cosθ_int가 주광선 값보다 작기 때문)와 투과 피크의 broadening(각 샘플이 서로 다른 파장에서 피크를 가지기 때문) — 가 Goossens et al. (2018)에서 강조한 핵심 효과입니다.

참고문헌: T. Goossens et al., 집적 박막 Fabry-Perot 필터 분광 카메라의 유한 조리개 보정, Appl. Opt. 57(26):7539 (2018). DOI: 10.1364/AO.57.007539.

상면도: 픽셀 어레이 위의 풋프린트

콘 조명 – 상면도

2×2 베이어 픽셀 배열에 대한 콘 조명의 상면도입니다. CRA, f-넘버, 샘플링을 조정하여 조명 풋프린트가 픽셀을 어떻게 덮는지 확인하세요.

권장 기본값: 황금각 기반으로 ring artifact 없이 준균일하게 덮습니다.

풋프린트 직경:0.907 um
렌즈 면적:0.6467 um²
CRA 시프트:0.217 um
커버리지 비율:64.7%
표시 샘플:37
RGGBCRA 시프트1 umy (um)x (um)
콘 풋프린트 샘플링 포인트 CRA 시프트

위의 측면도는 원뿔 기하학을 단면으로 보여줍니다. **상면도(Top View)**는 보완적인 관점을 제공합니다: 픽셀 어레이를 위에서 내려다보면, 조명 원뿔이 2x2 Bayer 패턴에 어떻게 투영되는지 확인할 수 있습니다.

상면도에서의 핵심 관찰 사항:

  • 풋프린트 직경: 초점면에서의 원뿔 풋프린트 직경은 d=2htan(θhalf)이며, 여기서 h는 원뿔 확산에 사용하는 유효 전파 높이입니다. F 넘버가 낮을수록 더 넓은 풋프린트가 생성됩니다.
  • CRA 시프트: CRA가 0이 아닌 경우 풋프린트 중심이 픽셀 중심에서 벗어납니다. 실제 BSI 스택에서는 단순한 공기 중 경로 값 htan(CRA)를 그대로 쓰지 않습니다. 컬러 필터, BARL, 실리콘의 굴절 때문에 주광선이 법선 방향으로 꺾이므로 유효 시프트는 더 작습니다.
  • 샘플링 커버리지: 위의 인터랙티브 뷰어에서 피보나치, 동일 면적 ring, Halton/Hammersley low-discrepancy set, Gauss-Legendre, legacy polar grid 샘플링을 비교할 수 있습니다. grid는 기준 비교에는 유용하지만, 보통 production 선택지로는 적합하지 않습니다.
  • 렌즈 면적: 풋프린트 면적 A=πr2 (여기서 r=htan(θhalf))는 인접 픽셀이 원뿔로부터 얼마나 많은 빛을 받는지를 결정하며, 이는 크로스토크에 직접적으로 영향을 미칩니다.

ConeIllumination 인스턴스 생성

python
from compass.sources.cone_illumination import ConeIllumination

cone = ConeIllumination(
    cra_deg=15.0,          # Chief Ray Angle in degrees
    f_number=2.0,          # F-number of the lens
    n_points=37,           # Number of angular sample points
    sampling="fibonacci",  # "fibonacci", "rings", "halton", "hammersley", "gauss", or "grid"
    weighting="cosine",    # "uniform", "cosine", "cos4", or "gaussian"
)

print(f"Half-cone angle: {cone.half_cone_rad * 180 / 3.14159:.1f} degrees")

샘플링 방법

get_sampling_points() 메서드는 (theta_deg, phi_deg, weight) 튜플의 리스트를 반환합니다. 각 튜플은 평면파 방향과 관련 적분 가중치를 나타냅니다.

피보나치 샘플링(Fibonacci Sampling)

피보나치(황금각 나선) 샘플링은 원뿔 영역에 점을 준균일하게 분포시킵니다. 비교적 적은 점으로 좋은 커버리지를 제공합니다.

python
cone = ConeIllumination(
    cra_deg=10.0, f_number=2.8, n_points=37, sampling="fibonacci"
)

points = cone.get_sampling_points()
print(f"Number of sample points: {len(points)}")
for i, (theta, phi, w) in enumerate(points[:5]):
    print(f"  Point {i}: theta={theta:.2f} deg, phi={phi:.2f} deg, weight={w:.4f}")

피보나치 샘플링은 대부분의 경우에 권장됩니다. 빠른 추정에는 19-37점, 프로덕션 결과에는 61-91점을 사용하십시오.

동일 면적 ring 샘플링(Equal-area rings)

동심 ring 샘플링은 cone cap을 동일 면적 radial band로 나누고, 바깥 ring처럼 둘레가 긴 영역에 더 많은 방위각 샘플을 배치합니다. 결정론적이고 눈으로 검토하기 쉬워, regular polar grid가 너무 구조적으로 보일 때 좋은 대안입니다.

python
cone = ConeIllumination(
    cra_deg=10.0, f_number=2.8, n_points=37, sampling="rings"
)

points = cone.get_sampling_points()
print(f"Ring sampling: {len(points)} points")

Halton 샘플링

Halton 샘플링은 cone cap 위의 low-discrepancy sequence를 사용합니다. 눈에 띄는 ring 또는 spoke 대칭을 피하므로, deterministic quasi-random 패턴으로 수렴성을 확인할 때 유용합니다.

python
cone = ConeIllumination(
    cra_deg=10.0, f_number=2.8, n_points=37, sampling="halton"
)

Halton은 incremental sequence입니다. 샘플 수를 늘려도 앞쪽 sequence가 유지되므로, progressive convergence check에 편리합니다.

Hammersley 샘플링

Hammersley 샘플링도 low-discrepancy point set이지만, 전체 샘플 수를 미리 알고 있다는 가정에서 점을 배치합니다. 고정된 sample budget으로 한 번 계산할 때는 같은 n_points에서 Halton보다 더 깔끔한 분포가 나오는 경우가 많습니다.

python
cone = ConeIllumination(
    cra_deg=10.0, f_number=2.8, n_points=37, sampling="hammersley"
)

샘플 수 하나를 정해서 실행할 때는 Hammersley, 샘플 수를 점진적으로 키우며 수렴성을 볼 때는 Halton을 선택하는 것이 실용적입니다.

Gauss-Legendre 샘플링

Gauss-Legendre 샘플링은 radial angle 방향으로 quadrature node를 사용하고, 방위각은 균일하게 나눕니다. 정확히 n_points개를 맞추는 것보다 각도 적분 정확도가 더 중요할 때 가장 적합합니다.

python
cone = ConeIllumination(
    cra_deg=10.0, f_number=2.8, n_points=36, sampling="gauss"
)

YAML 호환성을 위해 sampling="gaussian_quadrature"도 alias로 허용됩니다.

Legacy 격자 샘플링(Grid Sampling)

격자 샘플링은 균일한 (θ,ϕ) 격자를 사용합니다. 간단하지만 동일한 점 수에서 피보나치보다 효율이 떨어집니다.

python
cone = ConeIllumination(
    cra_deg=10.0, f_number=2.8, n_points=36, sampling="grid"
)

points = cone.get_sampling_points()
print(f"Grid sampling: {len(points)} points")

격자 샘플링은 n_theta x n_phi개의 점을 생성하며, n_theta = sqrt(n_points), n_phi = n_points / n_theta입니다.

grid는 주로 진단용 기준선으로 쓰는 것이 좋습니다. cone 중심을 과샘플링하고 강한 radial/azimuthal 구조를 만들기 때문에, 실제 수렴성이 좋거나 나쁜 것처럼 보이게 만들 수 있습니다.

가중 함수

가중 함수는 동공 전체에 걸친 강도 분포를 모델링합니다:

가중수식물리적 모델
uniformw=1균일 동공 조명
cosinew=cosθ람베르트 소스 / 아플라나틱 렌즈
cos4w=cos4θ이미지 평면에서의 cos-fourth 감쇠
gaussianw=eθ2/2σ2아포다이즈된 동공

기본값은 cosine이며, 대부분의 카메라 렌즈 시스템에 적합합니다.

python
# Compare different weighting functions
for wf in ["uniform", "cosine", "cos4", "gaussian"]:
    cone = ConeIllumination(
        cra_deg=0.0, f_number=2.0, n_points=37, weighting=wf
    )
    points = cone.get_sampling_points()
    weights = [p[2] for p in points]
    print(f"{wf:10s}: max_w={max(weights):.4f}, min_w={min(weights):.4f}")

Ray file 기반 cone averaging

ConeIllumination은 cone을 CRA, F-number, analytic pupil weighting으로 표현할 수 있을 때 간결한 모델입니다. Lens-design workflow에서는 더 명시적인 입력이 나오는 경우가 많습니다. 여러 sensor position에 대해 ray file을 만들고, 각 ray가 보통 다음 정보를 가집니다:

Field의미
image_x, image_yray bundle이 도달하는 sensor position
pupil_x, pupil_ypupil coordinate. chief ray는 pupil center
theta_deg, phi_degsensor에서의 입사각
intensitylens transmission / Fresnel / vignetting factor
weightpupil area 또는 quadrature weight

한 sensor position의 ray bundle에 대한 cone-averaged QE는 다음과 같습니다:

QEcone(λ)=rQE(λ,θr,ϕr)IrwrrIrwr

여기서 Ir은 ray intensity, wr은 pupil weight입니다. 전기적 collection을 포함한다면 QE 대신 optical generation map과 collection weighting function으로 계산한 pixel EQE를 넣습니다.

각도 응답 값을 얻는 방법은 두 가지입니다:

전략쓰는 경우trade-off
Direct ray simulationsensor position 또는 ray sample이 적음정확한 ray에서 계산하지만 sensor 전체로 반복하면 비쌈
Angular-grid interpolationposition과 lens ray가 많음구조적인 (θ,ϕ) grid를 한 번 계산하고 각 ray bundle로 보간

Camera-level characterization에서는 angular-grid interpolation이 보통 더 확장성이 좋습니다. Angular grid는 lens의 전체 CRA/MRA 범위를 덮어야 하며, QE(θ,ϕ)가 빠르게 변하는 영역에서는 더 촘촘해야 합니다.

python
def cone_average_from_ray_bundle(qe_lookup, rays, wavelength):
    numerator = 0.0
    denominator = 0.0
    for ray in rays:
        qe = qe_lookup.interpolate(
            wavelength=wavelength,
            theta_deg=ray["theta_deg"],
            phi_deg=ray["phi_deg"],
        )
        ray_weight = ray["intensity"] * ray["weight"]
        numerator += qe * ray_weight
        denominator += ray_weight
    return numerator / max(denominator, 1e-12)

INFO

Ray-file workflow는 Zemax/OpticStudio, custom Python ray tracer, measured CRA/MRA map과 모두 개념적으로 호환됩니다. COMPASS는 특정 lens-design tool에 의존하기보다 ray angle과 weight를 받는 optical interface로 다루는 것이 좋습니다.

평면파 솔버와의 통합

원뿔 조명 QE를 계산하려면, 각 샘플링된 각도에서 평면파 시뮬레이션을 실행하고 가중합을 계산합니다:

python
import numpy as np
from compass.sources.cone_illumination import ConeIllumination
from compass.solvers.base import SolverFactory

# Set up cone
cone = ConeIllumination(cra_deg=15.0, f_number=2.0, n_points=37, weighting="cosine")
points = cone.get_sampling_points()

# Create solver
solver = SolverFactory.create("torcwa", solver_config, device="cuda")
solver.setup_geometry(pixel_stack)

# Run planewave at each sample point
wavelength = 0.55
weighted_qe = {}

for theta_deg, phi_deg, weight in points:
    solver.setup_source({
        "wavelength": wavelength,
        "theta": float(theta_deg),
        "phi": float(phi_deg),
        "polarization": "unpolarized",
    })
    result = solver.run()

    for pixel_name, qe in result.qe_per_pixel.items():
        if pixel_name not in weighted_qe:
            weighted_qe[pixel_name] = 0.0
        weighted_qe[pixel_name] += weight * float(np.mean(qe))

print("Cone-illuminated QE at 550 nm:")
for pixel_name, qe in weighted_qe.items():
    print(f"  {pixel_name}: QE = {qe:.3f}")

원뿔 조명과 파장 스위프 결합

원뿔 조명에서의 전체 스펙트럼 스위프를 위해, 파장과 각도 샘플을 반복합니다:

python
wavelengths = np.arange(0.40, 0.701, 0.01)
cone = ConeIllumination(cra_deg=15.0, f_number=2.0, n_points=37)
points = cone.get_sampling_points()

# Initialize QE storage
pixel_names = None
cone_qe = {}

for wl in wavelengths:
    wl_qe = {}

    for theta_deg, phi_deg, weight in points:
        solver.setup_source({
            "wavelength": float(wl),
            "theta": float(theta_deg),
            "phi": float(phi_deg),
            "polarization": "unpolarized",
        })
        result = solver.run()

        if pixel_names is None:
            pixel_names = list(result.qe_per_pixel.keys())
            for pn in pixel_names:
                cone_qe[pn] = []

        for pn in pixel_names:
            if pn not in wl_qe:
                wl_qe[pn] = 0.0
            wl_qe[pn] += weight * float(np.mean(result.qe_per_pixel[pn]))

    for pn in pixel_names:
        cone_qe[pn].append(wl_qe[pn])

# Plot results
import matplotlib.pyplot as plt

fig, ax = plt.subplots(figsize=(10, 6))
wl_nm = wavelengths * 1000
for pn in pixel_names:
    ax.plot(wl_nm, cone_qe[pn], label=pn)

ax.set_xlabel("Wavelength (nm)")
ax.set_ylabel("QE (cone illumination)")
ax.set_title(f"Cone Illumination QE (CRA={cone.cra_deg} deg, F/{cone.f_number})")
ax.legend()
ax.grid(True, alpha=0.3)
plt.tight_layout()

샘플링 수렴

n_points를 증가시키며 결과를 비교하여 샘플 점 수가 충분한지 확인합니다:

python
for n in [7, 19, 37, 61, 91]:
    cone = ConeIllumination(cra_deg=15.0, f_number=2.0, n_points=n)
    points = cone.get_sampling_points()
    # ... run weighted sum, record QE
    print(f"n_points={n}: avg QE = ...")

일반적으로 F/2.0 이하에서 37점이면 완전히 수렴된 적분 대비 1% 이내의 결과를 제공합니다.

렌즈 면적 스위프: F 넘버 vs QE 및 크로스토크

조명 원뿔의 풋프린트 면적은 F 넘버에 따라 변합니다. F 넘버를 스위프하면 렌즈 속도가 QE와 광학적 크로스토크에 미치는 영향을 파악할 수 있으며, 이는 CIS 설계에서 핵심적인 트레이드오프입니다.

풋프린트 면적 vs F 넘버

풋프린트 반경 r=htan(θhalf)이고 θhalf=arcsin(1/2F)입니다. 따라서 풋프린트 면적 A=πr2는 F 넘버가 감소할수록 급격히 증가합니다:

F 넘버θhalf (도)풋프린트 반경 (um)면적 (um²)
F/1.420.91.9111.5
F/2.014.51.295.3
F/2.810.30.912.6
F/4.07.20.631.2
F/5.65.10.450.63

(스택 높이 h = 5.0 um 기준)

F 넘버 스위프 실행

python
import numpy as np
from compass.sources.cone_illumination import ConeIllumination
from compass.solvers.base import SolverFactory

f_numbers = [1.4, 2.0, 2.8, 4.0, 5.6, 8.0]
wavelength = 0.55
cra_deg = 15.0

solver = SolverFactory.create("torcwa", solver_config, device="cuda")
solver.setup_geometry(pixel_stack)

results = {}
for fn in f_numbers:
    cone = ConeIllumination(cra_deg=cra_deg, f_number=fn, n_points=37)
    points = cone.get_sampling_points()

    weighted_qe = {}
    for theta_deg, phi_deg, weight in points:
        solver.setup_source({
            "wavelength": wavelength,
            "theta": float(theta_deg),
            "phi": float(phi_deg),
            "polarization": "unpolarized",
        })
        result = solver.run()

        for pixel_name, qe in result.qe_per_pixel.items():
            if pixel_name not in weighted_qe:
                weighted_qe[pixel_name] = 0.0
            weighted_qe[pixel_name] += weight * float(np.mean(qe))

    results[fn] = weighted_qe
    print(f"F/{fn}: {weighted_qe}")

트레이드오프 분석

빠른 렌즈(낮은 F 넘버)는 더 많은 빛을 수집하여 신호를 개선합니다. 그러나 넓어진 원뿔은 인접 픽셀 간의 각도 확산과 크로스토크도 증가시킵니다:

python
import matplotlib.pyplot as plt

fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 5))

# 녹색 픽셀의 QE vs F 넘버
green_qe = [results[fn].get("green_tl", 0) for fn in f_numbers]
ax1.plot(f_numbers, green_qe, "go-", linewidth=2, markersize=8)
ax1.set_xlabel("F-number")
ax1.set_ylabel("QE (green pixel)")
ax1.set_title("QE vs F-number (550 nm)")
ax1.grid(True, alpha=0.3)
ax1.invert_xaxis()

# 크로스토크: 비대상 픽셀 QE / 대상 픽셀 QE 비율
crosstalk = []
for fn in f_numbers:
    green = results[fn].get("green_tl", 1e-9)
    red = results[fn].get("red_tr", 0)
    xtalk = red / green * 100  # 백분율
    crosstalk.append(xtalk)

ax2.plot(f_numbers, crosstalk, "rs-", linewidth=2, markersize=8)
ax2.set_xlabel("F-number")
ax2.set_ylabel("Crosstalk (%)")
ax2.set_title("Green→Red crosstalk vs F-number")
ax2.grid(True, alpha=0.3)
ax2.invert_xaxis()

plt.tight_layout()

CRA + F 넘버 결합 스위프

완전한 렌즈 면적 감도 분석을 위해, CRA와 F 넘버를 모두 스위프하여 2D 맵을 구축합니다:

python
cra_values = [0, 5, 10, 15, 20, 25, 30]
f_numbers = [1.4, 2.0, 2.8, 4.0]
wavelength = 0.55

qe_map = np.zeros((len(cra_values), len(f_numbers)))

for i, cra in enumerate(cra_values):
    for j, fn in enumerate(f_numbers):
        cone = ConeIllumination(cra_deg=cra, f_number=fn, n_points=37)
        points = cone.get_sampling_points()

        weighted_qe = 0.0
        for theta_deg, phi_deg, weight in points:
            solver.setup_source({
                "wavelength": wavelength,
                "theta": float(theta_deg),
                "phi": float(phi_deg),
                "polarization": "unpolarized",
            })
            result = solver.run()
            weighted_qe += weight * float(
                np.mean(result.qe_per_pixel.get("green_tl", [0]))
            )

        qe_map[i, j] = weighted_qe

# 히트맵으로 시각화
fig, ax = plt.subplots(figsize=(8, 6))
im = ax.imshow(qe_map, aspect="auto", origin="lower",
               extent=[f_numbers[0], f_numbers[-1],
                       cra_values[0], cra_values[-1]])
ax.set_xlabel("F-number")
ax.set_ylabel("CRA (degrees)")
ax.set_title("Green pixel QE: CRA vs F-number")
plt.colorbar(im, ax=ax, label="QE")
plt.tight_layout()

이 2D 스위프는 목표 QE 임계값에 대한 CRA 및 F 넘버 한계를 식별하는 데 도움이 되며, 이는 마이크로렌즈 설계 최적화에 필수적인 정보입니다.

YAML을 통한 설정

원뿔 조명은 소스 설정에서 지정할 수 있습니다:

yaml
source:
  type: "cone"
  cone:
    cra_deg: 15.0
    f_number: 2.0
    n_points: 37
    sampling: "fibonacci"
    weighting: "cosine"
  wavelength:
    mode: "sweep"
    sweep: {start: 0.40, stop: 0.70, step: 0.01}
  polarization: "unpolarized"

다음 단계