'''
Author: Unsaturated Transistor; Code created and exported to HTML using the eric IDE; Dated 15th January 2026
Want the code? Download the python file here.
Go back?
'''

import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import argrelextrema
import textwrap

# === Matplotlib config to keep text selectable in vector outputs ===
plt.rcParams.update({
    'font.size': 12,
    'svg.fonttype': 'none',   # keep text as <text> elements in SVG (selectable)
    'pdf.fonttype': 42,       # embed TrueType fonts in PDF (selectable text)
    'text.usetex': False
})

# Parameters
n0 = 1.0
nL = 1.6
nH = 2.0
ns = 1.5
lambda_0 = 1000.0  # Design wavelength in nm

# Wavelength range (200..1800 nm, 1 nm resolution)
wavelengths = np.linspace(200.0, 1800.0, 1601)

reflectances = []

# Calculation loop
for lam in wavelengths:
    # Optical thickness n * d = lambda_0 / 4
    # delta = (2*pi*n*d)/lambda => using n*d = lambda_0/4 gives:
    delta = (np.pi * lambda_0) / (2.0 * lam)

    # Characteristic matrices for quarter-wave layers
    M1 = np.array([
        [np.cos(delta), 1j / nL * np.sin(delta)],
        [1j * nL * np.sin(delta), np.cos(delta)]
    ])
    M2 = np.array([
        [np.cos(delta), 1j / nH * np.sin(delta)],
        [1j * nH * np.sin(delta), np.cos(delta)]
    ])

    M = M1.dot(M2)

    B, C = M.dot(np.array([1.0, ns]))
    r = (n0 * B - C) / (n0 * B + C)
    R = np.abs(r) ** 2
    reflectances.append(R)

reflectances = np.array(reflectances)

# Find indices of local maxima and minima
max_indices = argrelextrema(reflectances, np.greater)[0]
min_indices = argrelextrema(reflectances, np.less)[0]

max_lambdas = wavelengths[max_indices]
max_R = reflectances[max_indices]

min_lambdas = wavelengths[min_indices]
min_R = reflectances[min_indices]

# === Plotting (A4 landscape size) ===
fig = plt.figure(figsize=(11.69, 8.27))

plt.plot(
    wavelengths,
    reflectances * 100,
    'k-',
    linewidth=1.5,
    label='Reflectance'
)

plt.plot(
    max_lambdas,
    max_R * 100,
    'k^',
    markersize=8,
    linestyle='None',
    label='Maxima'
)

plt.plot(
    min_lambdas,
    min_R * 100,
    'kv',
    markersize=8,
    linestyle='None',
    label='Minima'
)

# add 1800 nm boundary marker explicitly
plt.plot(1800.0, reflectances[-1] * 100, 'kv', markersize=8)

plt.xlabel('Wavelength / nm', fontsize=12)
plt.ylabel('Percentage Reflectance', fontsize=12)

title_text = (
    "Plot of the reflectance for the two-layer coating upon the glass substrate, "
    "with a design wavelength $\lambda_0$ = 1000 nm"
)
wrapped_title = " ".join(textwrap.wrap(title_text, width=70))
plt.title(wrapped_title, fontsize=16)

plt.grid(True, color='gray', linestyle='--', alpha=0.5)
plt.xlim(200, 1800)
plt.ylim(0, reflectances.max() * 100 + 1)
plt.legend(loc='upper right', frameon=True)

# Save as SVG and PDF
plt.savefig(
    'reflectance_plot_A4_monochrome_1800.svg',
    format='svg',
    bbox_inches='tight'
)
plt.savefig(
    'reflectance_plot_A4_monochrome_1800.pdf',
    format='pdf',
    bbox_inches='tight'
)

plt.show()

# Print formatted extrema and boundary value
for l, r_val in zip(max_lambdas, max_R):
    print(f"Max: {l:.1f} nm, R = {r_val*100:.2f}%")
for l, r_val in zip(min_lambdas, min_R):
    print(f"Min: {l:.1f} nm, R = {r_val*100:.2f}%")
print(f"Boundary 1800 nm, R = {reflectances[-1]*100:.2f}%")