Adding Perl parser for script results

This commit is contained in:
John Poole 2026-04-20 02:09:39 -07:00
commit 49e3843292

View file

@ -0,0 +1,157 @@
#!/usr/bin/perl
#
# calc_heading_strength_stats.pl
#
# 20260420 ChatGPT
# $Id$
# $HeadURL$
#
# Example:
# chmod 755 calc_heading_strength_stats.pl
# ./calc_heading_strength_stats.pl magnetometer_readings.log
# ./calc_heading_strength_stats.pl ~/sessions/T-Beam_calibrate_20260420_Mon_014614.script
#
# This script scans a console/script log and extracts only lines like:
#
# 3005 00:36.756 Mag: X:289.20 Y:216.86 Z:608.78 μT Metadata: X:10845 Y:8132 Z:22829 Heading (rad): 0.585220 rad Heading (deg): 33.53° Magnetic Strength: 708.01 μT
#
# It ignores non-matching lines and computes statistics for:
# 1) Heading (deg)
# 2) Magnetic Strength
#
# Reported:
# - count
# - min / max / range
# - mean
# - population variance
# - sample variance
# - population std dev
# - sample std dev
# - line number / timestamp / text for min and max
#
use strict;
use warnings;
use utf8;
use open ':std', ':encoding(UTF-8)';
my $input_file = shift @ARGV
or die "Usage: $0 input_log_file\n";
open my $fh, '<', $input_file
or die "Cannot open '$input_file': $!\n";
my %stats = (
heading_deg => init_stat('Heading (deg)'),
mag_strength => init_stat('Magnetic Strength'),
);
my $matched_lines = 0;
while (my $line = <$fh>) {
chomp $line;
next unless $line =~ /^\s*(\d+)\s+(\d{2}:\d{2}\.\d{3})\s+Mag:/;
my $log_lineno = $1;
my $time_stamp = $2;
next unless $line =~ /Heading \(deg\):\s*([-+]?\d+(?:\.\d+)?)°/;
my $heading_deg = $1 + 0;
next unless $line =~ /Magnetic Strength:\s*([-+]?\d+(?:\.\d+)?)\s*μT/;
my $mag_strength = $1 + 0;
$matched_lines++;
update_stat($stats{heading_deg}, $heading_deg, $log_lineno, $time_stamp, $line);
update_stat($stats{mag_strength}, $mag_strength, $log_lineno, $time_stamp, $line);
}
close $fh;
if (!$matched_lines) {
die "No matching data lines were found in '$input_file'.\n";
}
print_report($stats{heading_deg});
print "\n";
print_report($stats{mag_strength});
exit 0;
sub init_stat {
my ($label) = @_;
return {
label => $label,
count => 0,
mean => 0,
m2 => 0, # Welford running sum of squared deviations
min => undef,
max => undef,
min_line => undef,
min_time => undef,
min_text => undef,
max_line => undef,
max_time => undef,
max_text => undef,
};
}
sub update_stat {
my ($s, $x, $log_lineno, $time_stamp, $text) = @_;
$s->{count}++;
if (!defined $s->{min} || $x < $s->{min}) {
$s->{min} = $x;
$s->{min_line} = $log_lineno;
$s->{min_time} = $time_stamp;
$s->{min_text} = $text;
}
if (!defined $s->{max} || $x > $s->{max}) {
$s->{max} = $x;
$s->{max_line} = $log_lineno;
$s->{max_time} = $time_stamp;
$s->{max_text} = $text;
}
my $delta = $x - $s->{mean};
$s->{mean} += $delta / $s->{count};
my $delta2 = $x - $s->{mean};
$s->{m2} += $delta * $delta2;
return;
}
sub print_report {
my ($s) = @_;
my $count = $s->{count};
my $range = $s->{max} - $s->{min};
my $pop_variance = ($count > 0) ? ($s->{m2} / $count) : 0;
my $samp_variance = ($count > 1) ? ($s->{m2} / ($count-1)) : 0;
my $pop_stddev = sqrt($pop_variance);
my $samp_stddev = sqrt($samp_variance);
print "$s->{label}\n";
print "=" x length($s->{label}), "\n";
printf "count : %d\n", $count;
printf "min : %.6f\n", $s->{min};
printf "max : %.6f\n", $s->{max};
printf "range : %.6f\n", $range;
printf "mean : %.6f\n", $s->{mean};
printf "population variance : %.6f\n", $pop_variance;
printf "sample variance : %.6f\n", $samp_variance;
printf "population std dev : %.6f\n", $pop_stddev;
printf "sample std dev : %.6f\n", $samp_stddev;
printf "min occurred at : line %s, time %s\n", $s->{min_line}, $s->{min_time};
printf "max occurred at : line %s, time %s\n", $s->{max_line}, $s->{max_time};
print "min line text : $s->{min_text}\n";
print "max line text : $s->{max_text}\n";
return;
}