Skip to content

Commit

Permalink
merge pull request #86 from shawntschwartz/67-feat-report
Browse files Browse the repository at this point in the history
67 feature: html/pdf report generator and renderer pipeline
  • Loading branch information
shawntz authored Sep 30, 2024
2 parents 6550afd + 8039ae0 commit e49c1d1
Show file tree
Hide file tree
Showing 20 changed files with 366 additions and 8 deletions.
6 changes: 5 additions & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,11 @@ RoxygenNote: 7.3.2
Suggests:
knitr,
rmarkdown,
testthat (>= 3.0.0)
testthat (>= 3.0.0),
hexSticker,
ggimage,
cowplot
VignetteBuilder: knitr
License: MIT + file LICENSE
Config/testthat/edition: 3
LazyData: true
4 changes: 4 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ export(lpfilt)
export(zscore)
importFrom(dplyr,across)
importFrom(dplyr,all_of)
importFrom(grDevices,dev.off)
importFrom(grDevices,jpeg)
importFrom(grDevices,rainbow)
importFrom(graphics,legend)
importFrom(graphics,lines)
importFrom(graphics,par)
importFrom(graphics,text)
importFrom(rlang,":=")
Expand Down
77 changes: 74 additions & 3 deletions R/bidsify.R
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,15 @@
#' @param run_num BIDS run ID.
#' @param save_raw Logical flag indicating whether to save_raw pupil data in
#' addition to epoched data. Defaults to TRUE.
#' @param render_report Logical flag indicating whether to save out the `eyeris`
#' preprocessing summary report. Defaults to TRUE.
#' @param html_report Logical flag indicating whether to save out the `eyeris`
#' preprocessing summary report as an HTML file. Defaults to TRUE.
#' @param pdf_report Logical flag indicating whether to save out the `eyeris`
#' preprocessing summary report as a PDF file. Note, a valid TeX distribution
#' must already be installed. Defaults to TRUE.
#' @param report_seed Random seed for the plots that will appear in the report.
#' Defaults to 0. See [eyeris::plot()] for a more detailed description.
#'
#' @examples
#' # Bleed around blink periods just long enough to remove majority of
Expand All @@ -42,7 +51,7 @@
#' label = "prePostProbe" # custom epoch label name
#' ) |>
#' eyeris::bidsify(
#' bids_dir = "derivatives",
#' bids_dir = ".", # make bids dir in current directory
#' participant_id = "001",
#' session_num = "01",
#' task_name = "assocret",
Expand All @@ -54,7 +63,9 @@
bidsify <- function(eyeris, save_all = TRUE, epochs_list = NULL,
merge_epochs = FALSE, bids_dir = NULL,
participant_id = NULL, session_num = NULL,
task_name = NULL, run_num = NULL, save_raw = TRUE) {
task_name = NULL, run_num = NULL, save_raw = TRUE,
render_report = TRUE, html_report = TRUE,
pdf_report = TRUE, report_seed = 0) {
sub <- participant_id
ses <- session_num
task <- task_name
Expand Down Expand Up @@ -131,7 +142,11 @@ bidsify <- function(eyeris, save_all = TRUE, epochs_list = NULL,
check_and_create_dir(dir, p)
}

p <- file.path(p, "pupil")
if (render_report) {
report_path <- p
}

p <- file.path(p, "eye")
check_and_create_dir(dir, p)

if (!merge_epochs) {
Expand Down Expand Up @@ -194,4 +209,60 @@ bidsify <- function(eyeris, save_all = TRUE, epochs_list = NULL,
file.path(dir, p, f)
)
}

if (render_report) {
figs_out <- file.path(report_path, "source")
check_and_create_dir(figs_out)

figs_out <- file.path(figs_out, "figures")
check_and_create_dir(figs_out)

pupil_steps <- grep("^pupil_", colnames(eyeris$timeseries), value = TRUE)
fig_paths <- rep(NA, length(pupil_steps))

for (i in seq_along(pupil_steps)) {
fig_paths[i] <- file.path(figs_out, paste0("fig", i, ".jpg"))
jpeg(file.path(fig_paths[i]),
width = 12, height = 7, units = "in",
res = 300, pointsize = 14
)
plot(eyeris, steps = i, seed = report_seed)
dev.off()
}

fig_paths <- c(
fig_paths,
file.path(figs_out, paste0("fig", length(fig_paths) + 1, ".jpg"))
)

jpeg(file.path(fig_paths[length(fig_paths)]),
width = 12, height = 7, units = "in", res = 300, pointsize = 18
)

plot(eyeris, steps = 1, preview_window = c(0, nrow(eyeris$timeseries)))

dev.off()

fig_paths <- c(
fig_paths,
file.path(figs_out, paste0("fig", length(fig_paths) + 1, ".jpg"))
)

jpeg(file.path(fig_paths[length(fig_paths)]),
width = 12, height = 7, units = "in", res = 300, pointsize = 18
)

plot(eyeris,
steps = length(pupil_steps),
preview_window = c(0, nrow(eyeris$timeseries))
)

dev.off()

report_output <- make_report(eyeris, report_path, fig_paths,
sub = sub, ses = ses, task = task, run = run
)

render_report(report_output, html = html_report, pdf = pdf_report)
}
}
4 changes: 4 additions & 0 deletions R/eyeris-package.R
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@
## usethis namespace: start
#' @importFrom dplyr across
#' @importFrom dplyr all_of
#' @importFrom graphics legend
#' @importFrom graphics lines
#' @importFrom graphics par
#' @importFrom graphics text
#' @importFrom grDevices dev.off
#' @importFrom grDevices jpeg
#' @importFrom grDevices rainbow
#' @importFrom rlang :=
#' @importFrom stats lm
Expand Down
123 changes: 123 additions & 0 deletions R/report.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
make_report <- function(eyeris, out, plots, ...) {
# get extra subject params from bidsify.R
params <- list(...)

# temp file
rmd_f <- file.path(out, paste0("sub-", params$sub, "_",
"run-", params$run, ".Rmd"))


report_date <- format(Sys.time(), "%B %d, %Y | %H:%M:%OS3")
package_version <- as.character(
utils::packageVersion("eyeris")
)
css <- system.file(
file.path("rmarkdown", "css", "report.css"),
package = "eyeris"
)

sticker_path <- system.file("figures", "sticker.png", package = "eyeris")

# eyeris report content
content <- paste0(
"---\n",
"title: '`eyeris` report'\n",
"date: '", report_date, "'\n",
"output:\n",
" html_document:\n",
" df_print: paged\n",
" css: '", css, "'\n",
" pdf_document: default\n",
"---\n\n",
"\n\n<img src='", sticker_path, "' class='top-right-image'>",
"\n\n---\n\n## Summary\n",
" - Subject ID: ", params$sub, "\n",
" - Session: ", params$ses, "\n",
" - Task: ", params$task, "\n",
" - Run: ", params$run, "\n",
" - BIDS Directory: ", out, "\n",
" - Source `.asc` file: ", eyeris$file, "\n",
" - [`eyeris` version](https://github.com/shawntschwartz/eyeris): ",
package_version, "\n",

"\n## Preprocessed Data Preview\n\n",
print_plots(plots), "\n",

"\n\n---\n\n## EyeLink Header Metadata\n\n",
make_md_table(eyeris$info), "\n",

"\n\n---\n\n### Citation\n\n",
"```{r citation, echo=FALSE, comment=NA}\n",
"citation('eyeris')\n",
"```\n\n"
)

writeLines(content, con = rmd_f)

return(rmd_f)
}

render_report <- function(rmd_f, html, pdf) {
rmarkdown::render(rmd_f, output_format = "html_document")

if (pdf) {
tryCatch({
rmarkdown::render(rmd_f, output_format = "pdf_document")
}, error = function(e) {
cli::cli_alert_danger(paste("Could not render eyeris report PDF.",
"Do you have a TeX distribution installed?",
"If not, consider TinyTeX:\n",
"## install.packages('tinytex')\n",
"## tinytex::install_tinytex()"))
base_file <- tools::file_path_sans_ext(rmd_f)
unlink(paste0(base_file, ".log"))
unlink(paste0(base_file, ".tex"))
})
}

unlink(rmd_f)
}

# parse eyelink `info` metadata into a markdown table
make_md_table <- function(df) {
md_table <- "| Property | Value |\n|----|----|\n"
for (prop in colnames(df)) {
val <- df[[1, prop]]
md_table <- paste0(md_table,
"| ",
prop,
" | ",
val,
" |\n")
}

return(md_table)
}

print_plots <- function(plots) {
md_plots <- ""
num_plots <- length(plots)
before_plot_index <- num_plots - 1
after_plot_index <- num_plots

for (i in seq_along(plots)) {
relative_fig_paths <- file.path("source", "figures", basename(plots))

if (i < before_plot_index) {
md_plots <- paste0(md_plots,
"### Step ", i, "\n",
"![](", relative_fig_paths[i], ")\n\n")
} else if (i == before_plot_index) {
md_plots <- paste0(md_plots,
"### Before", "\n",
"![](", relative_fig_paths[i], ")\n\n")
} else {
md_plots <- paste0(md_plots,
"### After", "\n",
"![](", relative_fig_paths[i], ")\n\n")
}

}

return(md_plots)
}
6 changes: 6 additions & 0 deletions R/sticker.data.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#' `eyeris` package logo (hexagon sticker)
#'
#' @format A png image file that is rendered into the README and html reports.
#'
#' @keywords eyeris, sticker, logo, hex
"sticker"
2 changes: 1 addition & 1 deletion README.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ knitr::opts_chunk$set(
)
```

# `eyeris`: create and run flexible and reproducible pupillometry preprocessing pipelines in R
# `eyeris`: create and run flexible and reproducible pupillometry preprocessing pipelines in R <img src="inst/figures/sticker.png" align="right"/>

<!-- badges: start -->
<a href="LICENSE.md" alt="MIT License"><img src="https://badgen.net/static/license/MIT/blue?icon=github" /></a>
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

<!-- README.md is generated from README.Rmd. Please edit that file -->

# `eyeris`: create and run flexible and reproducible pupillometry preprocessing pipelines in R
# `eyeris`: create and run flexible and reproducible pupillometry preprocessing pipelines in R <img src="inst/figures/sticker.png" align="right"/>

<!-- badges: start -->

Expand Down
7 changes: 7 additions & 0 deletions data-raw/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Attributions

---

* Eye by Mashudi from [Noun Project](https://thenounproject.com/browse/icons/term/eye/) (CC BY 3.0)

* Eye by Skena Grafis from [Noun Project](https://thenounproject.com/browse/icons/term/eye/) (CC BY 3.0)
Binary file added data-raw/noun-eye-6489700.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions data-raw/noun-eye-6489700.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added data-raw/noun-eye-7147281.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions data-raw/noun-eye-7147281.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
36 changes: 36 additions & 0 deletions data-raw/sticker.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
## code to prepare `sticker` dataset goes here

sysfonts::font_add_google("Nunito")

showtext::showtext_auto()

imgurl <- file.path("data-raw", "noun-eye-7147281.png")
img <- png::readPNG(imgurl)
img_grob <- grid::rasterGrob(img, interpolate = TRUE)

sine_wave <- ggplot2::ggplot(data = data.frame(
x = seq(0, 4 * pi, length.out = 500)
), ggplot2::aes(x = x)) +
ggplot2::geom_line(ggplot2::aes(y = sin(x / 2)),
size = 4, linetype = 1,
color = "white", alpha = 0
) +
ggplot2::theme_void() +
ggimage::theme_transparent()

combined_plot <- cowplot::ggdraw() +
cowplot::draw_plot(sine_wave, 0, 0.75, 1, 1, scale = 4) +
cowplot::draw_grob(img_grob, 0, -0.1, 1, 1, 2.75)

sticker <- hexSticker::sticker(
combined_plot,
package = "EYERIS",
h_fill = "#820000", h_color = "#820000",
s_x = 1, s_y = 1.28, s_width = 0.35,
p_x = 1, p_y = 0.78, p_size = 22, p_family = "Nunito",
filename = "inst/figures/sticker.png"
)

sticker

usethis::use_data(sticker, overwrite = TRUE)
Binary file added data/sticker.rda
Binary file not shown.
Binary file added inst/figures/sticker.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit e49c1d1

Please sign in to comment.