"""Generate synthetic Raman spectra for a concentration calibration series.

Scenario: Silicon Raman peak (~520 cm⁻¹) shifts with boron doping concentration.
Higher boron concentration causes a downshift and slight broadening of the
first-order Si peak. This is a well-documented effect used in semiconductor
characterization.

Generates 10 CSV files (one per concentration) in examples/data/raman_calibration/.
"""

import numpy as np
from pathlib import Path

np.random.seed(42)

out_dir = Path(__file__).parent / "raman_calibration"
out_dir.mkdir(exist_ok=True)

# Raman shift axis (cm⁻¹)
x = np.linspace(490, 550, 400)

# Boron concentrations (×10¹⁹ cm⁻³)
concentrations = np.array([0.5, 1.0, 2.0, 3.5, 5.0, 7.0, 9.0, 12.0, 15.0, 20.0])

# Peak model: Lorentzian
# Position shifts down linearly with concentration: ~0.3 cm⁻¹ per 10¹⁹ cm⁻³
# Width broadens slightly with concentration
BASE_CENTER = 520.5  # cm⁻¹ at zero doping
SHIFT_RATE = -0.30   # cm⁻¹ per 10¹⁹ cm⁻³
BASE_WIDTH = 3.5     # cm⁻¹ FWHM
BROADEN_RATE = 0.08  # cm⁻¹ FWHM per 10¹⁹ cm⁻³
AMPLITUDE = 5000.0


def lorentzian(x, center, fwhm, amplitude):
    gamma = fwhm / 2
    return amplitude * gamma**2 / ((x - center)**2 + gamma**2)


for i, conc in enumerate(concentrations):
    center = BASE_CENTER + SHIFT_RATE * conc
    fwhm = BASE_WIDTH + BROADEN_RATE * conc
    signal = lorentzian(x, center, fwhm, AMPLITUDE)

    # Add a small secondary peak (two-phonon feature, fixed position)
    signal += lorentzian(x, 508.0, 6.0, 400.0)

    # Background: gentle slope
    background = 120 + 0.5 * (x - x.min())

    # Noise
    noise = np.random.normal(0, 12, size=len(x))

    intensity = signal + background + noise
    intensity = np.maximum(intensity, 0)

    fname = out_dir / f"raman_B_{conc:.1f}e19.csv"
    np.savetxt(
        fname,
        np.column_stack([x, intensity]),
        delimiter=",",
        header="Raman_Shift_cm-1,Intensity_counts",
        comments="",
        fmt="%.4f",
    )

print(f"Generated {len(concentrations)} spectra in {out_dir}")
for c in concentrations:
    center = BASE_CENTER + SHIFT_RATE * c
    print(f"  [B] = {c:.1f}e19 cm⁻³  →  peak at {center:.2f} cm⁻¹")
