VASE.pm - Variable Angle Spectroscopic Ellipsometry Analysis

A Perl library for fitting optical models to variable angle spectroscopic ellipsometry (VASE) data using the Levenberg-Marquardt algorithm.

What is Ellipsometry?

Ellipsometry is an optical technique that measures the change in polarization of light upon reflection from a sample surface. It provides information about the optical properties (refractive index, extinction coefficient) and thickness of thin films and multilayer structures. The measured parameters are:

Variable angle measurements provide additional constraints for more accurate model fitting.

Features

Requirements

Installation

# Install PDL and required modules
cpan PDL PDL::Fit::LM

# Clone or download this repository
# No additional installation needed - use with perl -I.

Quick Start

use strict;
use warnings;
use PDL;
use VASE;

# Create VASE object
my $vase = VASE->new(layers => 1);

# Load experimental data
$vase->load_data('data/sample.dat');

# Define a simple linear model
sub linear_model {
    my ($params, $x) = @_;
    
    my ($a, $b, $c, $d) = list $params;
    my $wavelength = $x->(:,0);  # Extract wavelength column
    
    my $psi = $a - $b * $wavelength;
    my $delta = $c + $d * $wavelength;
    
    return cat($psi, $delta)->flat;
}

$vase->set_model(\&linear_model);

# Perform fit with initial parameters
my $initial_params = pdl [65, 0.05, 80, 0.1];
my $fit_params = $vase->fit($initial_params);

# Display results
my ($a, $b, $c, $d) = list $fit_params;
print "Fitted parameters:\n";
print "Psi: $a - $b * wavelength\n";
print "Delta: $c + $d * wavelength\n";

Data Format

Input files should contain whitespace-separated columns:

# Wavelength(nm) Angle(deg) Psi(deg) Delta(deg)
400 70 45.0 120.0
410 70 44.5 121.0
420 70 44.0 122.0
430 70 43.5 123.0

API Reference

Constructor

my $vase = VASE->new(%args);

Parameters:

Methods

load_data($filename)

Loads ellipsometry data from a file.

$vase->load_data('experimental_data.dat');

Parameters:

Returns: PDL piddle containing the loaded data

set_model($model_function)

Sets the optical model function for fitting.

$vase->set_model(\&my_model);

Parameters:

fit($initial_params)

Performs Levenberg-Marquardt fitting of the model to loaded data.

my $fitted_params = $vase->fit($initial_params);

Parameters:

Returns: PDL piddle containing fitted parameters

Model Function Requirements

Model functions must follow this signature:

sub model_function {
    my ($params, $x) = @_;
    
    # Extract parameters
    my $param1 = $params->(0);
    my $param2 = $params->(1);
    # ... etc
    
    # Extract input variables
    my $wavelength = $x->(:,0);  # Column 0: wavelength
    my $angle = $x->(:,1);       # Column 1: incident angle
    
    # Calculate Psi and Delta based on your optical model
    my $psi = ...;    # Your Psi calculation
    my $delta = ...;  # Your Delta calculation
    
    # Return concatenated and flattened result
    return cat($psi, $delta)->flat;
}

Key Points:

Example Models

Linear Model

sub linear_model {
    my ($params, $x) = @_;
    my ($a, $b, $c, $d) = list $params;
    my $wavelength = $x->(:,0);
    
    my $psi = $a - $b * $wavelength;
    my $delta = $c + $d * $wavelength;
    
    return cat($psi, $delta)->flat;
}

Polynomial Model

sub polynomial_model {
    my ($params, $x) = @_;
    my ($a0, $a1, $a2, $b0, $b1, $b2) = list $params;
    my $wavelength = $x->(:,0);
    
    my $psi = $a0 + $a1 * $wavelength + $a2 * $wavelength**2;
    my $delta = $b0 + $b1 * $wavelength + $b2 * $wavelength**2;
    
    return cat($psi, $delta)->flat;
}

Angle-Dependent Model

sub angle_dependent_model {
    my ($params, $x) = @_;
    my ($n, $k, $thickness) = list $params;
    my $wavelength = $x->(:,0);
    my $angle = $x->(:,1);
    
    # Complex optical calculations using both wavelength and angle
    # (This would require implementing Fresnel equations)
    
    return cat($psi, $delta)->flat;
}

Running Examples

# Run the included example
perl -I. test_fit.pl

# Note: Use -I. to include current directory in module search path

File Structure

├── VASE.pm              # Main library module
├── test_fit.pl          # Example usage script
├── data/
│   ├── sample.dat       # Sample data file
│   ├── Jovan_Ellipsometer/  # Equipment-specific datasets
│   └── OTS_on_SiO2/     # Material-specific datasets
└── .github/
    └── copilot-instructions.md

Tips for Model Development

  1. Start Simple: Begin with linear or polynomial models to verify data loading and fitting
  2. Physical Constraints: Ensure your model produces physically reasonable values
  3. Parameter Bounds: Consider reasonable ranges for your initial parameter guesses
  4. Convergence: The Levenberg-Marquardt algorithm is sensitive to initial conditions
  5. Multi-angle Data: Use angle-dependent models when you have variable angle measurements

Contributing

This library is designed for research applications in optical characterization. Feel free to extend the model library or improve the fitting algorithms.

License

[Add your license information here]