Friday, June 21, 2024

I used Perl today

Let me dump the script first, then I'll talk about it:

#!perl
# Combine_KeysightResistance_Data_Into_Excel_20240620.pl
# Jovan Trujillo
# AEP Core - MTW
# Arizona State University
# 8/7/2023
#
#
# Usage: perl Combine_KeysightResistance_Data_Into_Excel_20240620.pl "path-to-data-folder"
# ChangeLog:
# Version 0.1 - Need to standardize on data input file format. Not sure it this script works yet.
# Version 0.2 - Porting what does work from Combine_Capacitance_Data_Into_Excel.pl
#

use Modern::Perl;
use File::Find;
use Switch;
use Excel::Writer::XLSX;

our $Excelbook = Excel::Writer::XLSX->new('Combined_KeysightResistance_Data.xlsx');
        die "Problems creating new Excel file: $!" unless defined $Excelbook;
our $Excelsheet = $Excelbook->add_worksheet('Summary');
our $row = 0;
our $col = 0;

sub main {
    if ($#ARGV != 0) {
        print "Usage: perl Combine_KeysightResistance_Data_Into_Excel_20240620.pl path-to-data-folder\n";
    } else {
       
        # ControlPanel will provide interface for Excel Macros embedded into the data collected into this spreadsheet. Will be useful for generating the plots I want, unless PDL can do it more efficiently for me.
        # Need to write some chart making macros in Excel and export the VBA as a binary. The Excel::Writer::XLSX module has a program to help me do that.
        # From the command line.
       
        #Create header in Summary worksheet.
        $Excelsheet->write($row,$col,"Lot");
        $col = $col + 1;
        $Excelsheet->write($row,$col,"Wafer");
        $col = $col + 1;
        $Excelsheet->write($row,$col,"X");
        $col = $col + 1;
        $Excelsheet->write($row,$col,"Y");
        $col = $col + 1;
        $Excelsheet->write($row,$col,"Die #");
        $col = $col + 1;
        $Excelsheet->write($row,$col,"Avg. Resistance");
        $col = $col + 1;
        $Excelsheet->write($row,$col,"StdDev. Resistance");
        $col = $col + 1;
        $Excelsheet->write($row,$col,"Date");
        $col = $col + 1;
        $Excelsheet->write($row,$col,"Time");
       
        my $folder = shift @ARGV;
        print "Search for resistance data in: " . $folder . "\n";
        my (@dir) = $folder;
        find(\&process_file, @dir);
        $Excelbook->close();
    }
}

sub process_file {
    # print $File::Find::name."\n";
    my $filepath = $File::Find::name;
    my $date;
    my $time;
    my $X;
    my $Y;
    my $DieNum;
    my $Wafer;
    my $Lot;
    my $Excelbook = shift @_;
    
    my $filename = $_;
    #print "filename: $filename\n";
    if ( -f $filepath) {
        # print " This is a file: $filename \n";
        if ( $filename =~ /Residual\sR\s\[(\w\w\w\w\w\-\d\d\d)-([\d]*)\s_\s(\d+)\s(\d+)\s\s\(([\d]*)\)\s;\s([\d\_]*)\s([\w\s\_]*)\]\.csv/ ) {
            #print " This is a file : $filename \n";
            $Lot = $1;
            $Wafer = $2;
            $X = $3;
            $Y = $4;
            $DieNum = $5;
            $date = $6;
            $time = $7;
            #print "\nProcessing: $filename\n\n";
            &analysis($filepath, $filename, $Lot, $Wafer, $X, $Y, $DieNum, $date, $time);
        } else {
            print "Not valid filename regex: " . $filename . "\n";
        }
    } else {
        # Keep looking for valid data files.
        say "Not a valid file path\n";
    }
}

sub analysis() {
    # Calculate average residual resistance for each file and save to Excel spreadsheet.
    my $filepath = shift @_;
    my $filename = shift @_;
    my $Lot = shift @_;
    my $Wafer = shift @_;
    my $X = shift @_;
    my $Y = shift @_;
    my $DieNum = shift @_;
    my $date = shift @_;
    my $time = shift @_;
    my $resTot = 0.0;
    my $count = 0;
    my $resAvg = 0.0;
    my $Label;
    my $Vm;
    my $If;
    my $Ta;
    my $ResidualR;
    my $resDev = 0.0;
    my @resData;
    open DATA, "<$filepath" or die "Error opening file $filename: $!\n";
    # There is a lot of cruft I need to sift through before I get to the meat of the data file
    while (<DATA>) {
        # Look for DataName     Vm     If     Ta     ResidualR Field and Parse for ResidualR data
        # Look for DataValue in line to know when to split for ResidualR data values.
        if ($_ =~ /DataValue/) {
            ($Label, $Vm, $If, $Ta, $ResidualR) = split(/,/,$_,5);
            push(@resData, $ResidualR);
            $resTot = $resTot + $ResidualR;
            $count = $count + 1;
        }
    }
    # Done reading data file, time to caculate average resistance from the dataset.
    $resAvg = $resTot/$count;
    for (my $i=0; $i < $count; $i++) {
        $resDev = $resDev + ($resData[$i]-$resAvg)**2;
    }
    $resDev = sqrt($resDev / $count);
    undef @resData;
    print "$Lot, $Wafer, $X, $Y, $DieNum, $resAvg, $resDev, $date, $time\n";
    
    # Save data to Excel Workbook
    #Columns are:
    # 0 - Lot
    # 1 - Wafer
    # 2 - Die X Index
    # 3 - Die Y Index
    # 4 - Die #
    # 5 - Average Resistance
    # 6 - Standard Deviation Resistance
    # 7 - Date
    # 8 - Time
    $row = $row + 1;
    $Excelsheet->write($row,0,$Lot);
    $Excelsheet->write($row,1,$Wafer);
    $Excelsheet->write($row,2,$X);
    $Excelsheet->write($row,3,$Y);
    $Excelsheet->write($row,4,$DieNum);
    $Excelsheet->write($row,5,$resAvg);
    $Excelsheet->write($row,6,$resDev);
    $Excelsheet->write($row,7,$date);
    $Excelsheet->write($row,8,$time);
    
    close(DATA);
    
}


&main();

1;

 

This was needed to compile the hundreds of CSV text files my Keysight B1505A instrument was spewing out while it collected contact resistance data from 100 die in each of 8 wafers tested. A lot of data, and each file contained 10 resistance values that I needed to average out and calculate the standard deviation of. Overall I was actually able to reuse a previous script that did similar work for Kelvin sheet resistance data that I was collecting using the Keithley 4200. In that case each file contained coordinate data and anywhere from 1 to 40 resistivity points for me to compile and average out into a Spreadsheet to make a pretty map of the sheet resistance variation on a wafer's surface. I'm doing the same thing here, but the file name for the text files is a lot messier. Here is an example of what I'm talking about:

Residual R [E2424-002-02 _ 3 7  (77) ; 6_20_2024 10_46_59 AM].csv 

That was a fun regular expression exercise parsing everything I needed out of that file name. But I did it, and it worked, and it created this nice table of values in an Excel spreadsheet for the team to analyze. 


 Now I can use Minitab to slurp up this Excel spreadsheet and compare differences between wafers and within wafers. Some fine data munging done today with some proper code reuse to boot. 



No comments:

Post a Comment