Fix a week length problem; load all data as space-separated to avoid separator changes; add icons for insulin and food.
This commit is contained in:
parent
75c49fe88f
commit
fddd1c6b84
@ -60,11 +60,10 @@ GetOptions ("input=s" => \$input, # The name of the CSV file from wh
|
||||
sub calculate_max_min {
|
||||
my %opts = @_;
|
||||
my $lines = $opts{lines};
|
||||
my $fmt = $opts{format} || qq("%Y-%m-%d %H:%M:%S");
|
||||
my $fmt = $opts{format} || qq(%Y-%m-%dT%H:%M:%S);
|
||||
my %intervals;
|
||||
foreach my $row ( @{$lines} ) {
|
||||
my ( $key, $value ) = split /,/, $row;
|
||||
$value =~ s#"(.*)"#$1#;
|
||||
my ( $key, $value ) = split / /, $row;
|
||||
my $date = Time::Piece->strptime( $key, $fmt );
|
||||
my ( $hour, $minute ) = ( $date->hour, $date->min );
|
||||
my $time = sprintf( "%02d:%02d:00", $hour, int($minute/$interval)*$interval );
|
||||
@ -98,6 +97,15 @@ open( my $ifh, '<:encoding(UTF-8)', $input )
|
||||
|
||||
while ( my $row = <$ifh> ) {
|
||||
chomp( $row );
|
||||
# Clean up the comments
|
||||
$row =~ s#\((Scan|Sensor)\)(; )?##i;
|
||||
$row =~ s#\(Blood\)(; )?##i;
|
||||
$row =~ s#Food \(.*?\)(; )?#{/: 🍎}#i;
|
||||
$row =~ s#Rapid-acting insulin \(.*?\)(; )?#~{/: 💉}{-1{/:=10 Rapid}}#i;
|
||||
$row =~ s#Long-acting insulin \(.*?\)(; )?#~{/: 💉}{-1{/:=10 Long}}#i;
|
||||
|
||||
# Parse CSV into whitespace-separated tokens to avoid conflicting separators
|
||||
$row =~ s#^"(\d{4}-\d{2}-\d{2}) (\d{2}:\d{2}:\d{2})","([\d\.]+)",.*,"(.*?)"$#$1T$2 $3 "$4"#;
|
||||
push @filelines, $row;
|
||||
}
|
||||
|
||||
@ -126,8 +134,8 @@ if ( $units =~ /mg/i ) {
|
||||
|
||||
# Get the list of days for which to produce graphs
|
||||
foreach my $row ( @filelines ) {
|
||||
if ( $row =~ m#^"((\d{4})-(\d{2})-(\d{2}))#ms ) {
|
||||
my ( $date,$year,$month,$day ) = ( $1, split /-/, $1 );
|
||||
if ( $row =~ m#^((\d{4})-(\d{2})-(\d{2}))#ms ) {
|
||||
my ( $date,$year,$month,$day ) = ( $1, $2, $3, $4 );
|
||||
my $time = Time::Piece->strptime( $date, "%Y-%m-%d" );
|
||||
my $week = $time->strftime("%W");
|
||||
$seen_weeks{$year}{$week}++;
|
||||
@ -144,7 +152,7 @@ foreach my $year ( sort keys %seen_weeks ) {
|
||||
$total_day_graphs = scalar keys %seen_days;
|
||||
$total_week_graphs = scalar keys %seen_weeks;
|
||||
|
||||
$intervals = calculate_max_min( 'lines' => \@filelines, 'format' => '"%Y-%m-%d %H:%M:%S"' );
|
||||
$intervals = calculate_max_min( 'lines' => \@filelines, 'format' => '%Y-%m-%dT%H:%M:%S' );
|
||||
|
||||
# Set up basic gnuplot output options
|
||||
push @data, qq(
|
||||
@ -155,13 +163,11 @@ set terminal pdf size $page_size enhanced font 'Calibri,14' linewidth 1
|
||||
# Read each line into a $Data variable for use by gnuplot
|
||||
foreach my $d ( sort keys %seen_days ) {
|
||||
my $label = "$1$2$3" if ( $d =~ m#(\d{4})-(\d{2})-(\d{2})# );
|
||||
push @data, qq(
|
||||
\$Data$label << EOD
|
||||
"timestamp","blood glucose","meal","method","comment");
|
||||
push @data, qq(\$Data$label << EOD);
|
||||
@sortedlines = ();
|
||||
foreach my $row (@filelines) {
|
||||
if ( $row =~ m#^"$d .*$# ) {
|
||||
push @sortedlines, qq($row);
|
||||
if ( $row =~ m#^${d}T(.*)$# ) {
|
||||
push @sortedlines, qq($1);
|
||||
}
|
||||
}
|
||||
@sortedlines = map { " $_" } @sortedlines; # indent data structure
|
||||
@ -170,13 +176,11 @@ foreach my $d ( sort keys %seen_days ) {
|
||||
}
|
||||
|
||||
# Output data averages by hour of the day
|
||||
push @data, qq(
|
||||
\$DataAvg << EOD
|
||||
"timestamp","blood glucose","meal","method","comment");
|
||||
push @data, qq(\$DataAvg << EOD);
|
||||
@sortedlines = ();
|
||||
foreach my $row (@filelines) {
|
||||
if ( $row =~ m#^(")\d{4}-\d{2}-\d{2} (.*)$# ) {
|
||||
push @sortedlines, qq($1$2);
|
||||
if ( $row =~ m#^\S+?T(\S+) (\S+)# ) {
|
||||
push @sortedlines, qq($1 $2);
|
||||
}
|
||||
}
|
||||
@sortedlines = map { " $_" } @sortedlines; # indent data structure
|
||||
@ -184,12 +188,10 @@ push @data, join "\n", sort @sortedlines;
|
||||
push @data, qq(EOD);
|
||||
|
||||
# Output the max and min glucose values for each $interval time period
|
||||
push @data, qq(
|
||||
\$DataMaxMin << EOD
|
||||
"timestamp","max","min");
|
||||
push @data, qq(\$DataMaxMin << EOD);
|
||||
@sortedlines = ();
|
||||
foreach my $time ( sort keys %$intervals ) {
|
||||
push @sortedlines, qq("$time","$intervals->{$time}->{max}","$intervals->{$time}->{min}");
|
||||
push @sortedlines, qq($time $intervals->{$time}->{max} $intervals->{$time}->{min});
|
||||
}
|
||||
@sortedlines = map { " $_" } @sortedlines; # indent data structure
|
||||
push @data, join "\n", sort @sortedlines;
|
||||
@ -206,37 +208,34 @@ foreach my $year ( sort keys %seen_weeks ) {
|
||||
|
||||
# Select data from the week in question
|
||||
my @weeklines;
|
||||
|
||||
foreach my $row (@filelines) {
|
||||
foreach my $dow ( 1 .. 7 ) {
|
||||
foreach my $dow ( 0 .. 6 ) {
|
||||
my $day = $mon + ( ONE_DAY * $dow );
|
||||
my $d = $day->strftime("%Y-%m-%d");
|
||||
if ( $row =~ m#^"$d .*$#ms ) {
|
||||
if ( $row =~ m#^$d#ms ) {
|
||||
push @weeklines, $row;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
push @data, qq(
|
||||
\$DataWeekAvg$label << EOD
|
||||
"timestamp","blood glucose","meal","method","comment");
|
||||
push @data, qq(\$DataWeekAvg$label << EOD);
|
||||
@sortedlines = ();
|
||||
foreach my $row (@weeklines) {
|
||||
if ($row =~ m#^(")\d{4}-\d{2}-\d{2} (.*)$# ) {
|
||||
push @sortedlines, qq($1$2);
|
||||
if ($row =~ m#^\d{4}-\d{2}-\d{2}T(\S+) (\S+) # ) {
|
||||
push @sortedlines, qq($1 $2);
|
||||
}
|
||||
}
|
||||
my $week_intervals = calculate_max_min( 'lines' => \@sortedlines, 'format' => '"%H:%M:%S"' );
|
||||
my $week_intervals = calculate_max_min( 'lines' => \@sortedlines, 'format' => '%H:%M:%S' );
|
||||
@sortedlines = map { " $_" } @sortedlines; # indent data structure
|
||||
push @data, join "\n", sort @sortedlines;
|
||||
push @data, qq(EOD);
|
||||
|
||||
|
||||
push @data, qq(
|
||||
\$DataWeekMaxMin$label << EOD
|
||||
"timestamp","max","min");
|
||||
push @data, qq(\$DataWeekMaxMin$label << EOD);
|
||||
@sortedlines = ();
|
||||
foreach my $time ( sort keys %{$week_intervals} ) {
|
||||
push @sortedlines, qq("$time","$intervals->{$time}->{max}","$intervals->{$time}->{min}");
|
||||
push @sortedlines, qq($time $intervals->{$time}->{max} $intervals->{$time}->{min});
|
||||
}
|
||||
@sortedlines = map { " $_" } @sortedlines; # indent data structure
|
||||
push @data, sort @sortedlines;
|
||||
@ -247,10 +246,11 @@ foreach my $year ( sort keys %seen_weeks ) {
|
||||
|
||||
# Sample each day's values into a smoothed plot, and store each plot in a new table
|
||||
push @data, qq(
|
||||
set datafile separator ","
|
||||
set datafile separator whitespace
|
||||
|
||||
# Read the CSV time format
|
||||
set timefmt "%Y-%m-%d %H:%M:%S"
|
||||
#set timefmt "%Y-%m-%dT%H:%M:%S"
|
||||
set timefmt "%H:%M:%S"
|
||||
# Store in table in seconds, as the value must be a number
|
||||
set format x "%s" timedate
|
||||
set format y "%.2f" numeric
|
||||
@ -269,15 +269,13 @@ set xdata time
|
||||
set table \$SmoothData$label
|
||||
plot \$Data$label using 1:2 smooth mcsplines
|
||||
unset table
|
||||
set table 'SmoothData$label'
|
||||
plot \$Data$label using 1:2 smooth mcsplines
|
||||
unset table
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
# Sample the average $interval values into a smoothed plot, and store in a new table
|
||||
push @data, qq(
|
||||
set datafile separator ","
|
||||
set datafile separator whitespace
|
||||
|
||||
# Read the CSV time format
|
||||
set timefmt "%H:%M:%S"
|
||||
@ -328,14 +326,13 @@ foreach my $year ( sort keys %seen_weeks ) {
|
||||
my $mon = $time + ( ONE_WEEK * ( $week - 1 ) ) + ( ONE_DAY );
|
||||
my $label = $mon->strftime("%Y%m%d");
|
||||
push @data, qq(
|
||||
set datafile separator ","
|
||||
set datafile separator whitespace
|
||||
|
||||
set timefmt "%H:%M:%S"
|
||||
set format x "%s" timedate
|
||||
set format y "%.2f" numeric
|
||||
set samples 10000
|
||||
set xdata
|
||||
print "DataWeekAvg$label"
|
||||
stats \$DataWeekAvg$label using 2
|
||||
MedianTotal$label = STATS_mean
|
||||
MeanTotal$label = STATS_mean
|
||||
@ -428,7 +425,7 @@ AVG_LABEL = gprintf("Median 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
|
||||
|
||||
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 , \$Data$label using 1:($graph_max-6):3 with labels font "Calibri,18" enhanced
|
||||
|
||||
# Add an x grid
|
||||
set multiplot previous
|
||||
|
Loading…
Reference in New Issue
Block a user