Add a new graph to show overall average values.
This commit is contained in:
parent
410b1363b6
commit
d0dcc15d44
@ -1,4 +1,10 @@
|
|||||||
#!/usr/bin/perl
|
#!/usr/bin/perl
|
||||||
|
#
|
||||||
|
# Perl script to convert CSV output from glucometer into graphs, using gnuplot.
|
||||||
|
#
|
||||||
|
# Author: Timothy Allen <tim@treehouse.org.za>
|
||||||
|
# License: MIT
|
||||||
|
#
|
||||||
|
|
||||||
use strict;
|
use strict;
|
||||||
use warnings;
|
use warnings;
|
||||||
@ -10,6 +16,8 @@ my $error = "Usage: $0 --input <CSV file> --output <output PDF> [--max <n.n>] [-
|
|||||||
my @lines;
|
my @lines;
|
||||||
my %seen;
|
my %seen;
|
||||||
my @data;
|
my @data;
|
||||||
|
my @avg_data;
|
||||||
|
my $a1c_calc;
|
||||||
my $gnuplot_data;
|
my $gnuplot_data;
|
||||||
my $total_graphs;
|
my $total_graphs;
|
||||||
my $count_graphs = 0;
|
my $count_graphs = 0;
|
||||||
@ -21,12 +29,14 @@ my $output = "";
|
|||||||
my $max_glucose = 8;
|
my $max_glucose = 8;
|
||||||
my $min_glucose = 4;
|
my $min_glucose = 4;
|
||||||
my $graph_max = 21;
|
my $graph_max = 21;
|
||||||
|
my $units = 'mmol/L';
|
||||||
my $days_per_page = 2;
|
my $days_per_page = 2;
|
||||||
GetOptions ("input=s" => \$input, # The name of the CSV file from which to read values
|
GetOptions ("input=s" => \$input, # The name of the CSV file from which to read values
|
||||||
"output=s" => \$output, # The name of the PDF file to output
|
"output=s" => \$output, # The name of the PDF file to output
|
||||||
"high:f" => \$max_glucose, # The high end of your target blood glucose level
|
"high:f" => \$max_glucose, # The high end of your target blood glucose level
|
||||||
"low:f" => \$min_glucose, # The low end of your target blood glucose level
|
"low:f" => \$min_glucose, # The low end of your target blood glucose level
|
||||||
"max:i" => \$graph_max, # The highest displayed glucose level on each graph
|
"max:i" => \$graph_max, # The highest displayed glucose level on each graph
|
||||||
|
"units:s" => \$units, # mmol/L or mg/dL
|
||||||
"graphs:i" => \$days_per_page) # The number of days printed on each page
|
"graphs:i" => \$days_per_page) # The number of days printed on each page
|
||||||
or die $error;
|
or die $error;
|
||||||
|
|
||||||
@ -43,15 +53,9 @@ close( $ifh )
|
|||||||
|
|
||||||
# Set up basic gnuplot options for reading the CSV data
|
# Set up basic gnuplot options for reading the CSV data
|
||||||
push @data, qq(
|
push @data, qq(
|
||||||
set datafile separator ","
|
set terminal pdf size 29.7cm,21.0cm enhanced font 'Calibri,14' linewidth 1
|
||||||
set xdata time
|
#set output '$output'
|
||||||
set timefmt "%Y-%m-%d %H:%M:%S"
|
|
||||||
#set timefmt "%H:%M:%S"
|
|
||||||
|
|
||||||
set format x "%s" timedate
|
|
||||||
set format y "%.2f" numeric
|
|
||||||
|
|
||||||
set samples 10000
|
|
||||||
);
|
);
|
||||||
|
|
||||||
# Get the list of days for which to produce graphs
|
# Get the list of days for which to produce graphs
|
||||||
@ -68,7 +72,7 @@ $total_graphs = scalar keys %seen;
|
|||||||
foreach my $d ( sort keys %seen ) {
|
foreach my $d ( sort keys %seen ) {
|
||||||
my $label = "$1$2$3" if ( $d =~ m#(\d{4})-(\d{2})-(\d{2})# );
|
my $label = "$1$2$3" if ( $d =~ m#(\d{4})-(\d{2})-(\d{2})# );
|
||||||
push @data, qq(
|
push @data, qq(
|
||||||
\$Data << EOD
|
\$Data$label << EOD
|
||||||
"timestamp","blood glucose","meal","method","comment");
|
"timestamp","blood glucose","meal","method","comment");
|
||||||
foreach my $row (@lines) {
|
foreach my $row (@lines) {
|
||||||
if ( $row =~ s#^"($d )#"$1#ms ) {
|
if ( $row =~ s#^"($d )#"$1#ms ) {
|
||||||
@ -78,13 +82,24 @@ foreach my $d ( sort keys %seen ) {
|
|||||||
push @data, qq(EOD);
|
push @data, qq(EOD);
|
||||||
|
|
||||||
push @data, qq(
|
push @data, qq(
|
||||||
|
set datafile separator ","
|
||||||
|
|
||||||
|
set timefmt "%Y-%m-%d %H:%M:%S"
|
||||||
|
set format x "%s" timedate
|
||||||
|
set format y "%.2f" numeric
|
||||||
|
set samples 10000
|
||||||
|
set xdata
|
||||||
|
stats \$Data$label using 2
|
||||||
|
Mean$label = STATS_mean
|
||||||
|
|
||||||
|
set xdata time
|
||||||
set table \$SmoothData$label
|
set table \$SmoothData$label
|
||||||
#plot \$Data using "timestamp":"blood glucose"
|
#plot \$Data$label using "timestamp":"blood glucose"
|
||||||
#plot \$Data using "timestamp":"blood glucose" smooth frequency
|
#plot \$Data$label using "timestamp":"blood glucose" smooth frequency
|
||||||
plot \$Data using "timestamp":"blood glucose" smooth mcsplines
|
plot \$Data$label using "timestamp":"blood glucose" smooth mcsplines
|
||||||
#plot \$Data using "timestamp":"blood glucose" smooth bezier
|
#plot \$Data$label using "timestamp":"blood glucose" smooth bezier
|
||||||
unset table
|
unset table
|
||||||
undefine \$Data
|
undefine \$Data$label
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,23 +111,21 @@ push @data, qq(
|
|||||||
reset
|
reset
|
||||||
set datafile separator whitespace
|
set datafile separator whitespace
|
||||||
|
|
||||||
set terminal pdf size 29.7cm,21.0cm enhanced font 'Calibri,14' linewidth 1
|
|
||||||
#set output '$output'
|
|
||||||
set key off
|
set key off
|
||||||
set style data lines
|
set style data lines
|
||||||
set xdata time
|
set xdata time
|
||||||
set timefmt "%H:%M:%S"
|
set timefmt "%H:%M:%S"
|
||||||
|
set format x "%H:%M" timedate
|
||||||
|
set format y "%.0f" numeric
|
||||||
|
|
||||||
|
set yrange [0:$graph_max]
|
||||||
|
# If extended to 23:59, the x grid overlaps with the border
|
||||||
|
set xrange ["00:00":"23:58"]
|
||||||
|
|
||||||
set style line 100 dt 3 lw 1 lc rgb "#202020"
|
set style line 100 dt 3 lw 1 lc rgb "#202020"
|
||||||
set style line 101 dt 1 lw 1 lc rgb "#202020"
|
set style line 101 dt 1 lw 1 lc rgb "#202020"
|
||||||
set linetype 110 lc rgb "red"
|
set linetype 110 lc rgb "red"
|
||||||
|
|
||||||
set format x "%H:%M" timedate
|
|
||||||
set format y "%.0f" numeric
|
|
||||||
set yrange [0:$graph_max]
|
|
||||||
# If extended to 23:59, the x grid overlaps with the border
|
|
||||||
set xrange ["00:00":"23:58"]
|
|
||||||
|
|
||||||
set lmargin 12
|
set lmargin 12
|
||||||
set rmargin 10
|
set rmargin 10
|
||||||
set tmargin 5
|
set tmargin 5
|
||||||
@ -131,17 +144,34 @@ foreach my $d ( sort keys %seen ) {
|
|||||||
|
|
||||||
$count_graphs++;
|
$count_graphs++;
|
||||||
|
|
||||||
|
# Algorithms for calculating HbA1c
|
||||||
|
if ( $units =~ /mg/i ) {
|
||||||
|
$a1c_calc = "(AVG + 46.7) / 28.7";
|
||||||
|
} else { # Assume mmol/L
|
||||||
|
$a1c_calc = "(AVG + 2.59) / 1.59";
|
||||||
|
}
|
||||||
|
|
||||||
push @data, qq(
|
push @data, qq(
|
||||||
set title "Daily Glucose Summary for $title" font "Calibri,18"
|
set title "Daily Glucose Summary for $title" font "Calibri,18"
|
||||||
set xlabel "Time" offset 0,-0.25
|
set xlabel "Time" offset 0,-0.25
|
||||||
set ylabel "Blood glucose"
|
set ylabel "Blood glucose"
|
||||||
set xtics left tc rgb "#000000"
|
set xtics left tc rgb "#000000"
|
||||||
set ytics 2 tc rgb "#000000"
|
set ytics 2 tc rgb "#000000"
|
||||||
set grid ytics ls 100
|
set grid ytics ls 100 front
|
||||||
|
|
||||||
#set arrow from graph 0,first $min_glucose to graph 1,first $min_glucose ls 6 lw 2 nohead
|
#set arrow from graph 0,first $min_glucose to graph 1,first $min_glucose ls 6 lw 2 nohead
|
||||||
#set arrow from graph 0,first $max_glucose to graph 1,first $max_glucose ls 6 lw 2 nohead
|
#set arrow from graph 0,first $max_glucose to graph 1,first $max_glucose ls 6 lw 2 nohead
|
||||||
set object 1 rect from 0,first $min_glucose to graph 1,first $max_glucose fc ls 6 fs solid 0.2 back
|
set object 1 rect from graph 0, first $min_glucose to graph 1,first $max_glucose fc ls 6 fs solid 0.2 back
|
||||||
|
|
||||||
|
AVG = Mean$label
|
||||||
|
AVG_LABEL = gprintf("Average glucose: %.2f", AVG)
|
||||||
|
set object 2 rect at graph 0.9, graph 0.9 fc ls 2 fs transparent solid 0.5 front size char strlen(AVG_LABEL), char 3
|
||||||
|
set label 2 AVG_LABEL at graph 0.9, graph 0.9 front center
|
||||||
|
|
||||||
|
#A1C = $a1c_calc
|
||||||
|
#A1C_LABEL = gprintf("Average A1c: %.1f", A1C)
|
||||||
|
#set object 3 rect at graph 0.07, graph 0.9 fc ls 5 fs transparent solid 0.5 front size char strlen(A1C_LABEL), char 3
|
||||||
|
#set label 3 A1C_LABEL at graph 0.07, graph 0.9 front center
|
||||||
|
|
||||||
#plot \$SmoothData$label using 1:2:( \$2 > $max_glucose || \$2 < $min_glucose ? 110 : $count_graphs ) with linespoints ls 120 lc variable
|
#plot \$SmoothData$label using 1:2:( \$2 > $max_glucose || \$2 < $min_glucose ? 110 : $count_graphs ) with linespoints ls 120 lc variable
|
||||||
plot \$SmoothData$label using (strftime("%H:%M:%S", \$1)):2:( \$2 > $max_glucose || \$2 < $min_glucose ? 110 : 1 ) with lines lw 3 lc variable
|
plot \$SmoothData$label using (strftime("%H:%M:%S", \$1)):2:( \$2 > $max_glucose || \$2 < $min_glucose ? 110 : 1 ) with lines lw 3 lc variable
|
||||||
@ -157,7 +187,7 @@ set xtics tc rgb "#ffffff00"
|
|||||||
set ytics tc rgb "#ffffff00"
|
set ytics tc rgb "#ffffff00"
|
||||||
unset grid
|
unset grid
|
||||||
unset object 1
|
unset object 1
|
||||||
set grid xtics ls 101 back
|
set grid xtics ls 101
|
||||||
plot 1/0
|
plot 1/0
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -168,12 +198,116 @@ plot 1/0
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Output data averages by hour of the day
|
||||||
|
push @data, qq(
|
||||||
|
\$DataAvg << EOD
|
||||||
|
"timestamp","blood glucose","meal","method","comment");
|
||||||
|
my @sorted_rows;
|
||||||
|
foreach my $row (@lines) {
|
||||||
|
if ( $row =~ s#^"\d{4}-\d{2}-\d{2} #"#ms ) {
|
||||||
|
push @sorted_rows, $row;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
push @data, sort @sorted_rows;
|
||||||
|
push @data, qq(EOD);
|
||||||
|
|
||||||
|
push @data, qq(
|
||||||
|
reset
|
||||||
|
set datafile separator ","
|
||||||
|
|
||||||
|
set timefmt "%H:%M:%S"
|
||||||
|
set format x "%s" timedate
|
||||||
|
set format y "%.2f" numeric
|
||||||
|
set samples 10000
|
||||||
|
set xdata
|
||||||
|
stats \$DataAvg using 2
|
||||||
|
MeanTotal = STATS_mean
|
||||||
|
|
||||||
|
set xdata time
|
||||||
|
set table \$SmoothDataAvg
|
||||||
|
plot \$DataAvg using 1:2 smooth bezier
|
||||||
|
unset table
|
||||||
|
|
||||||
|
set table \$TableDataAvg
|
||||||
|
plot \$DataAvg using 1:2 smooth mcsplines
|
||||||
|
unset table
|
||||||
|
|
||||||
|
undefine \$DataAvg
|
||||||
|
|
||||||
|
reset
|
||||||
|
set datafile separator whitespace
|
||||||
|
|
||||||
|
set key off
|
||||||
|
set style data lines
|
||||||
|
set xdata time
|
||||||
|
set timefmt "%H:%M:%S"
|
||||||
|
set format x "%H:%M" timedate
|
||||||
|
set format y "%.0f" numeric
|
||||||
|
|
||||||
|
set yrange [0:$graph_max]
|
||||||
|
# If extended to 23:59, the x grid overlaps with the border
|
||||||
|
set xrange ["00:00":"23:58"]
|
||||||
|
|
||||||
|
set style line 100 dt 3 lw 1 lc rgb "#202020"
|
||||||
|
set style line 101 dt 1 lw 1 lc rgb "#202020"
|
||||||
|
set linetype 110 lc rgb "red"
|
||||||
|
|
||||||
|
set lmargin 12
|
||||||
|
set rmargin 10
|
||||||
|
set tmargin 5
|
||||||
|
set bmargin 5
|
||||||
|
|
||||||
|
set multiplot title layout $days_per_page,1
|
||||||
|
|
||||||
|
set title "Average Daily Glucose" font "Calibri,18"
|
||||||
|
set xlabel "Time" offset 0,-0.25
|
||||||
|
set ylabel "Blood glucose"
|
||||||
|
set xtics left tc rgb "#000000"
|
||||||
|
set ytics 2 tc rgb "#000000"
|
||||||
|
set grid ytics ls 100 front
|
||||||
|
|
||||||
|
set object 1 rect from graph 0, first $min_glucose to graph 1,first $max_glucose fc ls 6 fs solid 0.2 back
|
||||||
|
|
||||||
|
AVG = MeanTotal
|
||||||
|
AVG_LABEL = gprintf("Average glucose: %.2f", AVG)
|
||||||
|
set object 2 rect at graph 0.9, graph 0.9 fc ls 2 fs transparent solid 0.5 front size char strlen(AVG_LABEL), char 3
|
||||||
|
set label 2 AVG_LABEL at graph 0.9, graph 0.9 front center
|
||||||
|
|
||||||
|
A1C = $a1c_calc
|
||||||
|
A1C_LABEL = gprintf("Average A1c: %.1f", A1C)
|
||||||
|
set object 3 rect at graph 0.07, graph 0.9 fc ls 5 fs transparent solid 0.5 front size char strlen(A1C_LABEL), char 3
|
||||||
|
set label 3 A1C_LABEL at graph 0.07, graph 0.9 front center
|
||||||
|
|
||||||
|
plot \$SmoothDataAvg using ( strftime("%H:%M:%S", \$1) ):2:( \$2 > $max_glucose || \$2 < $min_glucose ? 110 : 1 ) with lines lw 3 lc variable
|
||||||
|
#plot \$TableDataAvg using (strftime("%H:%M:%S", \$1)):2 with lines lw 1 lc 5, \$SmoothDataAvg using (strftime("%H:%M:%S", \$1)):2:( \$2 > $max_glucose || \$2 < $min_glucose ? 110 : 1 ) with lines lw 3 lc variable
|
||||||
|
|
||||||
|
undefine \$DataAvg
|
||||||
|
undefine \$SmoothDataAvg
|
||||||
|
undefine \$TableDataAvg
|
||||||
|
|
||||||
|
# Add an x grid
|
||||||
|
set multiplot previous
|
||||||
|
set title " "
|
||||||
|
set xlabel " " offset 0,-0.25
|
||||||
|
set ylabel " "
|
||||||
|
set xtics tc rgb "#ffffff00"
|
||||||
|
set ytics tc rgb "#ffffff00"
|
||||||
|
unset grid
|
||||||
|
unset object 1
|
||||||
|
set grid xtics ls 101
|
||||||
|
plot 1/0
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
push @data, qq(
|
push @data, qq(
|
||||||
unset multiplot
|
unset multiplot
|
||||||
|
#test
|
||||||
);
|
);
|
||||||
|
|
||||||
# run the data through gnuplot
|
# run the data through gnuplot
|
||||||
$gnuplot_data = join "\n", @data;
|
$gnuplot_data = join "\n", @data;
|
||||||
|
print $gnuplot_data;
|
||||||
|
|
||||||
open( my $ofh, '>', $output )
|
open( my $ofh, '>', $output )
|
||||||
or die "Could not open file '$output' $!";
|
or die "Could not open file '$output' $!";
|
||||||
@ -204,7 +338,8 @@ my $child_exit_status = $? >> 8;
|
|||||||
close( $ofh )
|
close( $ofh )
|
||||||
or warn "close failed: $!";
|
or warn "close failed: $!";
|
||||||
|
|
||||||
#open (GNUPLOT, "|gnuplot");
|
#open(GNUPLOT, "|gnuplot");
|
||||||
#print GNUPLOT $gnuplot_data;
|
#print GNUPLOT $gnuplot_data;
|
||||||
|
#close(GNUPLOT);
|
||||||
|
|
||||||
# vim: set expandtab shiftwidth=4 softtabstop=4 :
|
# vim: set expandtab shiftwidth=4 softtabstop=4 :
|
||||||
|
Loading…
Reference in New Issue
Block a user