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.