# Copyright © 2013, Christopher S. Swingley # Licensed under the terms of the GNU General Public License v3 library(lubridate) library(ggplot2) library(reshape2) library(scales) library(grid) library(gtable) home <- Sys.getenv('HOME') barn <- read.csv(paste(home, 'tmp/barn.csv', sep='/')) outdoor <- read.csv(paste(home, 'tmp/outdoor.csv', sep='/')) dog_in_out <- read.csv(paste(home, 'tmp/dog_in_out.csv', sep='/')) barn$dt_local <- ymd_hms(as.character(barn$dt_local)) barn$dt_local <- force_tz(barn$dt_local, "US/Alaska") outdoor$obs_dt <- ymd_hms(as.character(outdoor$obs_dt)) outdoor$obs_dt <- force_tz(outdoor$obs_dt, "US/Alaska") if (length(dog_in_out$dt_local)) { dog_in_out$dt_local <- ymd_hms(as.character(dog_in_out$dt_local)) dog_in_out$dt_local <- force_tz(dog_in_out$dt_local, "US/Alaska") } names(barn) <- c('obs_dt', 'ds18b20_temp_f', 'sht15_humidity', 'set_f', 'power_on_min'); merged <- merge(barn, outdoor, by='obs_dt', all=TRUE) dte = format(now(), "%Y-%m-%d") xlimits = c(min(min(barn$obs_dt), min(outdoor$obs_dt)), max(max(barn$obs_dt), max(outdoor$obs_dt))) have_in <- length(subset(dog_in_out, in_out == 'i')$in_out) have_out <- length(subset(dog_in_out, in_out == 'o')$in_out) if ((have_in) | (have_out)) { if (have_in) { dog_in <- subset(dog_in_out, in_out == 'i')$dt_local } else { dog_in <- min(min(barn$obs_dt), min(outdoor$obs_dt)) } if (have_out) { dog_out <- subset(dog_in_out, in_out == 'o')$dt_local } else { dog_out <- max(max(barn$obs_dt), max(outdoor$obs_dt)) } } # Build plot "table" make_gt <- function(barn_temp, barn_humidity, power, outdoor_temp) { gt1 <- ggplot_gtable(ggplot_build(barn_temp)) gt2 <- ggplot_gtable(ggplot_build(barn_humidity)) gt3 <- ggplot_gtable(ggplot_build(power)) gt4 <- ggplot_gtable(ggplot_build(outdoor_temp)) max_width <- unit.pmax(gt1$widths[2:3], gt2$widths[2:3], gt3$widths[2:3], gt4$widths[2:3]) gt1$widths[2:3] <- max_width gt2$widths[2:3] <- max_width gt3$widths[2:3] <- max_width gt4$widths[2:3] <- max_width gt <- gtable(widths = unit(c(8), "in"), heights = unit(c(2.3, 1.9, 1.9, 1.9), "in")) gt <- gtable_add_grob(gt, gt1, 1, 1) gt <- gtable_add_grob(gt, gt2, 2, 1) gt <- gtable_add_grob(gt, gt3, 3, 1) gt <- gtable_add_grob(gt, gt4, 4, 1) gt } # Make individual plots barn_temp <- ggplot(data=barn, aes(x=obs_dt, y=ds18b20_temp_f)) + geom_point() + geom_line() + geom_line(aes(y=set_f), color="darkorange", alpha=0.5) + theme_bw() + theme(plot.margin = unit(c(1, 1, 0, 0.5), 'lines')) + guides(fill = FALSE) + theme(axis.text.x = element_blank(), axis.title.x = element_blank()) + scale_x_datetime(breaks = date_breaks("1 hour"), limits=xlimits) + scale_y_continuous(name="Barn Temp (deg F)") + ggtitle(paste("Dog barn stats - ", dte)) if ((have_in) | (have_out)) { barn_temp <- barn_temp + annotate("rect", xmin=dog_in, xmax=dog_out, ymin=min(barn$ds18b20_temp_f, barn$set_f), ymax=max(barn$ds18b20_temp_f, barn$set_f), alpha=0.2, fill="darkcyan") } model <- lm(data=barn, sht15_humidity ~ obs_dt) params <- coef(model) # intercept, slope h_per_hour <- round(params[2] * 3600, 1) barn_humidity <- ggplot(data=barn, aes(x=obs_dt, y=sht15_humidity)) + geom_point() + geom_line() + geom_abline(intercept=params[1], slope=params[2], colour="darkorange", alpha=0.5) + theme_bw() + theme(plot.margin = unit(c(0, 1, 0, 0.5), 'lines')) + guides(fill = FALSE) + theme(axis.text.x = element_blank(), axis.title.x = element_blank()) + scale_x_datetime(breaks = date_breaks("1 hour"), limits=xlimits) + scale_y_continuous(name="Barn Humidity (%)") + annotate("text", label=paste(h_per_hour, '%/hr', sep=''), x=max(barn$obs_dt) - minutes(60), y=mean(barn$sht15_humidity), colour="darkorange", size=3) if ((have_in) | (have_out)) { barn_humidity <- barn_humidity + annotate("rect", xmin=dog_in, xmax=dog_out, ymin=min(barn$sht15_humidity), ymax=max(barn$sht15_humidity), alpha=0.2, fill="darkcyan") } mean_power_on_minutes <- mean(barn$power_on_min) power_on_percentage <- round(mean_power_on_minutes/15.0*100) power <- ggplot(data=barn, aes(x=obs_dt, y=power_on_min)) + geom_hline(aes(yintercept=mean(barn$power_on_min)), colour="darkorange", alpha=0.5) + geom_bar(stat="identity") + theme_bw() + theme(plot.margin = unit(c(0, 1, 0, 0.5), 'lines')) + guides(fill = FALSE) + theme(axis.text.x = element_blank(), axis.title.x = element_blank()) + scale_x_datetime(breaks = date_breaks("1 hour"), limits=xlimits) + scale_y_continuous(name="Heater on (min)") + annotate("text", label=paste(power_on_percentage, '%', sep=''), x=max(barn$obs_dt), y=mean_power_on_minutes, vjust=-0.2, hjust=0.2, colour="darkorange", size=3) if ((have_in) | (have_out)) { power <- power + annotate("rect", xmin=dog_in, xmax=dog_out, ymin=min(barn$power_on_min), ymax=max(barn$power_on_min), alpha=0.2, fill="darkcyan") } temp_trend_data <- subset(outdoor, obs_dt >= max(outdoor$obs_dt) - hours(2)) model <- lm(data=temp_trend_data, outside_temp_f ~ obs_dt) params <- coef(model) # intercept, slope delta_degrees_per_hour <- round(params[2] * 3600, 1) outdoor_temp <- ggplot(data=outdoor, aes(x=obs_dt, y=outside_temp_f)) + geom_point(size=1) + geom_line() + geom_abline(intercept=params[1], slope=params[2], colour="darkorange", alpha=0.5) + theme_bw() + theme(plot.margin = unit(c(0, 1, 0.5, 0.5), 'lines')) + scale_x_datetime(name="Time", breaks = date_breaks("1 hour"), labels=date_format("%H:%M"), limits=xlimits) + scale_y_continuous(name="Outside Temp (deg F)") + annotate("text", label=paste(delta_degrees_per_hour, 'deg/hr'), x=max(outdoor$obs_dt) - minutes(60), y=mean(outdoor$outside_temp_f), colour="darkorange", size=3) if ((have_in) | (have_out)) { outdoor_temp <- outdoor_temp + annotate("rect", xmin=dog_in, xmax=dog_out, ymin=min(outdoor$outside_temp_f), ymax=max(outdoor$outside_temp_f), alpha=0.2, fill="darkcyan") } # Do it gt <- make_gt(barn_temp, barn_humidity, power, outdoor_temp) svg('dog_barn_stats.svg', width = 8, height = 8) grid.newpage() grid.draw(gt) dev.off() pdf('dog_barn_stats.pdf', width = 8, height = 8) grid.newpage() grid.draw(gt) dev.off()