Physics-Ellipsometry-VASE

 view release on metacpan or  search on metacpan

README.md  view on Meta::CPAN

# Physics::Ellipsometry::VASE

Variable Angle Spectroscopic Ellipsometry analysis for Perl / PDL.

## Description

Physics::Ellipsometry::VASE is a complete framework for spectroscopic
ellipsometry data analysis. It includes built-in optical models, a transfer
matrix method, and global optimisation — so you can go from raw VASE data to
fitted film parameters in a few lines of code.

### Core features

- **Data loading** — simple whitespace-delimited files and native J.A. Woollam
  VASE instrument format (auto-detected), with automatic eV ↔ nm conversion
- **Transfer Matrix Method** (`VASE::TMM`) — physics sign convention
  (*e*<sup>+2*iβ*</sup>), Verdet Fresnel coefficients, arbitrary layer counts
- **Dispersion models** (`VASE::Dispersion`) — Cauchy, Sellmeier, Tauc-Lorentz,
  Drude, General Oscillator
- **EMA mixing rules** (`VASE::EMA`) — Linear, Bruggeman, Maxwell-Garnett
- **Material file loader** (`VASE::Materials`) — point-by-point `.mat` files
  with automatic eV/nm unit handling and interpolation
- **Circular Delta residuals** — proper handling of the 0°/360° wrap in the
  Levenberg-Marquardt objective function
- **Parameter bounds & vary/fix** (`VASE::Parameter`) — logit-transformed
  bounded optimisation, fixed-parameter support
- **Global optimiser** (`VASE::Optimizer`) — Differential Evolution
  (DE/rand/1/bin) and grid search for initial parameter estimation
- **Weighted fitting** — uses measured uncertainties (sigma) from Woollam files
- **Numerical Jacobian** — configurable finite-difference step with minimum
  absolute floor
- **Plotting** — multi-angle colour-coded overlays via PDL::Graphics::Gnuplot

## Installation

From source:

```bash
perl Makefile.PL
make
make test
make install
```

## Quick Start

```perl
use PDL;
use PDL::NiceSlice;
use Physics::Ellipsometry::VASE;
use Physics::Ellipsometry::VASE::TMM qw(psi_delta);
use Physics::Ellipsometry::VASE::Dispersion qw(cauchy_nk);
use Physics::Ellipsometry::VASE::Materials qw(load_material interpolate_material);

# Load data and substrate material
my $vase = Physics::Ellipsometry::VASE->new(
    layers         => 2,
    circular_delta => 1,       # circular Delta residuals
    deriv_step     => 1e-3,
);
$vase->load_data('measurement.dat');

my $substrate = load_material('si_jaw.mat');

# Model: Air / Cauchy film / Si substrate
sub my_model {
    my ($params, $x) = @_;
    my $lambda = $x->(:,0);
    my $theta  = $x->(:,1);

    my ($n_film, $k_film) = cauchy_nk($lambda, $params->at(0), $params->at(1), 0);
    my $N_film = $n_film + i() * $k_film;

    my ($n_sub, $k_sub) = interpolate_material($substrate, $lambda);
    my $N_sub = $n_sub + i() * $k_sub;

    my $N_air = pdl(1.0) + i() * pdl(0.0);
    my $d_nm  = $params->at(2);

    my ($psi, $delta) = psi_delta(
        $lambda, $theta,
        [$N_air, $N_film, $N_sub],
        [$d_nm],
    );
    return $psi->append($delta);
}

$vase->set_model(\&my_model);
my $fitted = $vase->fit(pdl [2.0, 0.01, 100.0]);
my $mse    = $vase->mse($fitted, nparams => 3);
printf "MSE = %.4f, thickness = %.1f nm\n", $mse, $fitted->at(2);



( run in 0.624 second using v1.01-cache-2.11-cpan-600a1bdf6e4 )