From 72019c116ab4ede19b833487dcbb7c8cf63f5f3a Mon Sep 17 00:00:00 2001 From: thebioengineer Date: Sun, 9 Oct 2022 22:04:15 -0700 Subject: [PATCH 1/4] Add "stop_motion" to preview all past plots --- DESCRIPTION | 4 ++- NAMESPACE | 1 + R/preview.R | 40 +++++++++++++++---------- R/show_history.R | 73 ++++++++++++++++++++++++++++++++++++++++++++++ man/stop_motion.Rd | 47 +++++++++++++++++++++++++++++ 5 files changed, 148 insertions(+), 17 deletions(-) create mode 100644 R/show_history.R create mode 100644 man/stop_motion.Rd diff --git a/DESCRIPTION b/DESCRIPTION index 8427ea1..8a76b4b 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -56,6 +56,8 @@ Suggests: dplyr, systemfonts, scales, - extrafont + extrafont, + htmltools, + slickR VignetteBuilder: knitr Config/testthat/edition: 3 diff --git a/NAMESPACE b/NAMESPACE index 9c79e83..0171904 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -22,6 +22,7 @@ importFrom(magick,image_read) importFrom(magick,image_resize) importFrom(magick,image_write) importFrom(rlang,caller_env) +importFrom(rlang,check_installed) importFrom(rlang,env_bind) importFrom(rlang,env_unbind) importFrom(svglite,svglite) diff --git a/R/preview.R b/R/preview.R index aeab5e3..723a5a2 100644 --- a/R/preview.R +++ b/R/preview.R @@ -33,14 +33,18 @@ preview_film <- function(){ #' get list of recorded files in recording dir #' @noRd -get_file_records <- function(full_path = FALSE){ +get_file_records <- + function(full_path = FALSE, + path = GG_RECORDING_ENV$recording_dir, + ext = GG_RECORDING_ENV$device_ext) { - file_preview_ext <- paste0("[.]", GG_RECORDING_ENV$device_ext, "$") + + file_preview_ext <- paste0("[.]",ext , "$") file_preview_format <- "\\d{4}_\\d{2}_\\d{2}_\\d{2}_\\d{2}_\\d{2}[.]\\d+" list.files( - path = GG_RECORDING_ENV$recording_dir, + path = path, pattern = paste0("^",file_preview_format,file_preview_ext), full.names = full_path ) @@ -55,19 +59,7 @@ get_file_records <- function(full_path = FALSE){ #' film_cyclotron <- function(IMAGE,filename = tempfile(fileext = ".html")){ - image_path <- file.path(GG_RECORDING_ENV$recording_dir, IMAGE) - image_ext <- file_ext(IMAGE) - - if(tolower(image_ext) %in% c("tiff","emf","eps","ps")){ - temp_image <- tempfile(fileext = ".png") - image <- magick::image_read(image_path) - converted_image <- magick::image_convert(image,format = "png") - magick::image_write(converted_image, path = temp_image) - image_path <- temp_image - image_ext <- "png" - } - - b64 <- paste0("data:image/",image_ext,";base64," , base64_enc(readBin(image_path, "raw", file.info(image_path)[1, "size"]))) + b64 <- read_image_b64(file.path(GG_RECORDING_ENV$recording_dir, IMAGE)) viewer_html <- c( "
", @@ -302,3 +294,19 @@ film_cyclotron <- function(IMAGE,filename = tempfile(fileext = ".html")){ sep = "\n", file = filename) } + +read_image_b64 <- function(path){ + + image_ext <- file_ext(path) + + if(tolower(image_ext) %in% c("tiff","emf","eps","ps")){ + temp_image <- tempfile(fileext = ".png") + image <- magick::image_read(path) + converted_image <- magick::image_convert(image,format = "png") + magick::image_write(converted_image, path = temp_image) + path <- temp_image + image_ext <- "png" + } + + paste0("data:image/",image_ext,";base64," , base64_enc(readBin(path, "raw", file.info(path)[1, "size"]))) +} diff --git a/R/show_history.R b/R/show_history.R new file mode 100644 index 0000000..1ff437a --- /dev/null +++ b/R/show_history.R @@ -0,0 +1,73 @@ +#' Show previous plots as a stop motion slideshow +#' +#' Using slickjs, preview all historical plots as a image carousel using slick js via the +#' slickR package. +#' +#' slickR and htmltools must be installed for this function to operate. +#' +#' @param height Set the height of the carousel widget and images in pixels. Defaults to 500. +#' @param dir directory the saved intermediate plots are in. When able, uses the set directory from `gg_record`. +#' @param ext extension type of the saved intermediate plots to display. When able, uses the set device extention from `gg_record`. +#' +#' @returns Returns a slickR htmlwidget populated with the plots +#' +#' @examples +#' +#' if(require(ggplot2) & interactive()){ +#' +#' gg_record(dir = file.path(tempdir(),"recording")) +#' ggplot(data.frame(x = 1, y = 1), aes(x=x, y=y)) + geom_point() + ylim(0,4) +#' ggplot(data.frame(x = 1, y = 2), aes(x=x, y=y)) + geom_point() + ylim(0,4) +#' +#' ## resize canvas of the last plot +#' gg_resize_film(height = 10, width = 5, dpi = 350) +#' +#' ggplot(data.frame(x = 1, y = 3), aes(x=x, y=y)) + geom_point() + ylim(0,4) +#' +#' stop_motion() +#' } +#' +#' +#' @importFrom rlang check_installed +stop_motion <- function(height = 500, dir = GG_RECORDING_ENV$recording_dir, ext = GG_RECORDING_ENV$device_ext){ + + if(is.null(dir)){ + stop("Set `dir` to the directory where the intermediate plots are saved in.") + } + + check_installed("slickR", reason = "To generate the stop_motion, slickR must be installed") + check_installed("htmltools", reason = "To generate the stop_motion, htmltools must be installed") + + stopifnot(is.numeric(height)) + stopifnot(height > 1) + + + if(is.null(ext)){ + warning("No file extension set. All allowable image file extentions will be used") + } + + records <- get_file_records(full_path = TRUE, path = dir, ext = ext %||% "(png)|(pdf)|(jpeg)|(bmp)|(tiff)|(emf)|(svg)|(eps)|(ps)") + + slick_content <- lapply(records, function(image_path, img_height){ + b64 <- read_image_b64(image_path) + htmltools::tags$div( + htmltools::tags$img(src = b64, + style = paste0( + "max-height:100%;", + "width:auto;height:auto;", + "margin-left: auto; margin-right: auto;", + "vertical-align:middle;") + ) + , + style = paste0("margin-left:auto;margin-right:auto;width:fit-content;height:",img_height,"px;") + ) + }, img_height = height) + + slick_carousel <- slickR::slickR(slick_content, height = height, width = "95%") + + slickR::settings( + slidesToShow = 1, + infinite = TRUE + ) + + return(slick_carousel) +} diff --git a/man/stop_motion.Rd b/man/stop_motion.Rd new file mode 100644 index 0000000..9576eed --- /dev/null +++ b/man/stop_motion.Rd @@ -0,0 +1,47 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/show_history.R +\name{stop_motion} +\alias{stop_motion} +\title{Show previous plots as a stop motion slideshow} +\usage{ +stop_motion( + height = 500, + dir = GG_RECORDING_ENV$recording_dir, + ext = GG_RECORDING_ENV$device_ext +) +} +\arguments{ +\item{height}{Set the height of the carousel widget and images in pixels. Defaults to 500.} + +\item{dir}{directory the saved intermediate plots are in. When able, uses the set directory from `gg_record`.} + +\item{ext}{extension type of the saved intermediate plots to display. When able, uses the set device extention from `gg_record`.} +} +\value{ +Returns a slickR htmlwidget populated with the plots +} +\description{ +Using slickjs, preview all historical plots as a image carousel using slick js via the +slickR package. +} +\details{ +slickR and htmltools must be installed for this function to operate. +} +\examples{ + +if(require(ggplot2) & interactive()){ + + gg_record(dir = file.path(tempdir(),"recording")) + ggplot(data.frame(x = 1, y = 1), aes(x=x, y=y)) + geom_point() + ylim(0,4) + ggplot(data.frame(x = 1, y = 2), aes(x=x, y=y)) + geom_point() + ylim(0,4) + + ## resize canvas of the last plot + gg_resize_film(height = 10, width = 5, dpi = 350) + + ggplot(data.frame(x = 1, y = 3), aes(x=x, y=y)) + geom_point() + ylim(0,4) + + stop_motion() +} + + +} From e015f6d792a0327c311df9197b750a700338772a Mon Sep 17 00:00:00 2001 From: Georgios Karamanis Date: Mon, 10 Oct 2022 10:28:52 +0200 Subject: [PATCH 2/4] Update README.md Add CRAN to installation methods --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c6f0861..d08f48d 100644 --- a/README.md +++ b/README.md @@ -26,11 +26,13 @@ After installation, the package enables you to: ## Installation -Currently {camcorder} is only available on GitHub, and can be installed -using the following command. +``` r +install.packages("camcorder") +``` + +### Or the development version ``` r -# install.packages("camcorder") remotes::install_github("thebioengineer/camcorder") ``` From 95b30c9482e25fce17ce5d7a222b8f9e47694686 Mon Sep 17 00:00:00 2001 From: thebioengineer Date: Sun, 16 Apr 2023 20:50:35 -0700 Subject: [PATCH 3/4] slickr carousel investigation --- NAMESPACE | 3 ++ R/show_history.R | 79 +++++++++++++++++++++++++++++++++++++++------- man/stop_motion.Rd | 2 +- 3 files changed, 71 insertions(+), 13 deletions(-) diff --git a/NAMESPACE b/NAMESPACE index 0171904..4e1e771 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -25,6 +25,9 @@ importFrom(rlang,caller_env) importFrom(rlang,check_installed) importFrom(rlang,env_bind) importFrom(rlang,env_unbind) +importFrom(slickR,"%synch%") +importFrom(slickR,settings) +importFrom(slickR,slickR) importFrom(svglite,svglite) importFrom(tools,file_ext) importFrom(tools,file_path_sans_ext) diff --git a/R/show_history.R b/R/show_history.R index 1ff437a..dcf04da 100644 --- a/R/show_history.R +++ b/R/show_history.R @@ -15,7 +15,7 @@ #' #' if(require(ggplot2) & interactive()){ #' -#' gg_record(dir = file.path(tempdir(),"recording")) +#' gg_record(dir = file.path(tempdir(),"recording"), device = "png" ) #' ggplot(data.frame(x = 1, y = 1), aes(x=x, y=y)) + geom_point() + ylim(0,4) #' ggplot(data.frame(x = 1, y = 2), aes(x=x, y=y)) + geom_point() + ylim(0,4) #' @@ -29,6 +29,7 @@ #' #' #' @importFrom rlang check_installed +#' @importFrom slickR slickR settings %synch% stop_motion <- function(height = 500, dir = GG_RECORDING_ENV$recording_dir, ext = GG_RECORDING_ENV$device_ext){ if(is.null(dir)){ @@ -49,25 +50,79 @@ stop_motion <- function(height = 500, dir = GG_RECORDING_ENV$recording_dir, ext records <- get_file_records(full_path = TRUE, path = dir, ext = ext %||% "(png)|(pdf)|(jpeg)|(bmp)|(tiff)|(emf)|(svg)|(eps)|(ps)") slick_content <- lapply(records, function(image_path, img_height){ - b64 <- read_image_b64(image_path) - htmltools::tags$div( - htmltools::tags$img(src = b64, + img_ext <- tools::file_ext(image_path) + if(img_ext%in% c("tif", "emf", "eps", "ps")){ + img_tag <- htmltools::tags$img(src = read_image_b64(image_path), style = paste0( "max-height:100%;", "width:auto;height:auto;", "margin-left: auto; margin-right: auto;", - "vertical-align:middle;") - ) - , - style = paste0("margin-left:auto;margin-right:auto;width:fit-content;height:",img_height,"px;") + "vertical-align:middle;")) + }else if( img_ext %in% c("pdf")){ + + img_tag <- htmltools::tags$img(src = pdf_to_png(image_path), + style = paste0( + "max-height:100%;", + "width:auto;height:auto;", + "margin-left: auto; margin-right: auto;", + "vertical-align:middle;")) + }else{ + + img_tag <- htmltools::tags$img(src = image_path, + style = paste0( + "max-height:100%;", + "width:auto;height:auto;", + "margin-left: auto; margin-right: auto;", + "vertical-align:middle;")) + } + htmltools::tags$div( + img_tag,style = paste0("margin-left:auto;margin-right:auto;width:fit-content;height:",img_height,"px;") ) }, img_height = height) - slick_carousel <- slickR::slickR(slick_content, height = height, width = "95%") + - slickR::settings( - slidesToShow = 1, - infinite = TRUE + slick_carousel <- ( + slickR::slickR( + slick_content, + height = height, + width = "95%") + + slickR::settings(infinite = TRUE) + ) %synch% ( + slickR::slickR( + slick_content, + height = 50) + + slickR::settings( + arrows = FALSE, + slidesToShow = 3, + slidesToScroll = 1, + centerMode = TRUE, + focusOnSelect = TRUE, + initialSlide = 0, + infinite = TRUE + ) ) return(slick_carousel) } + +pdf_to_png <- function(pdf_path, path = tempdir()){ + + pdf_name <- basename(pdf_path) + pdf_name_sans_ext <- file_path_sans_ext(pdf_name) + + png_path <- normalizePath( + file.path(path, paste0(pdf_name_sans_ext,".png")), + winslash = "/" + ) + + if(!file.exists(png_path)){ + pdftools::pdf_convert( + pdf = pdf_path, + format = 'png', + verbose = FALSE, + filenames = png_path + ) + } + + return(png_path) + +} diff --git a/man/stop_motion.Rd b/man/stop_motion.Rd index 9576eed..fc23aa5 100644 --- a/man/stop_motion.Rd +++ b/man/stop_motion.Rd @@ -31,7 +31,7 @@ slickR and htmltools must be installed for this function to operate. if(require(ggplot2) & interactive()){ - gg_record(dir = file.path(tempdir(),"recording")) + gg_record(dir = file.path(tempdir(),"recording"), device = "pdf" ) ggplot(data.frame(x = 1, y = 1), aes(x=x, y=y)) + geom_point() + ylim(0,4) ggplot(data.frame(x = 1, y = 2), aes(x=x, y=y)) + geom_point() + ylim(0,4) From 47792c252b0f779ad1aff94dc6b375164fb21c9f Mon Sep 17 00:00:00 2001 From: thebioengineer Date: Sun, 16 Apr 2023 22:09:40 -0700 Subject: [PATCH 4/4] save widget and then open via viewer - this allows the preview of files without needing to turn into base64 --- R/show_history.R | 44 +++++++++++++++++++++++++------------------- man/stop_motion.Rd | 5 +++-- 2 files changed, 28 insertions(+), 21 deletions(-) diff --git a/R/show_history.R b/R/show_history.R index dcf04da..c695dd1 100644 --- a/R/show_history.R +++ b/R/show_history.R @@ -30,7 +30,7 @@ #' #' @importFrom rlang check_installed #' @importFrom slickR slickR settings %synch% -stop_motion <- function(height = 500, dir = GG_RECORDING_ENV$recording_dir, ext = GG_RECORDING_ENV$device_ext){ +stop_motion <- function(height = 500, dir = GG_RECORDING_ENV$recording_dir, ext = GG_RECORDING_ENV$device_ext, filename = NULL){ if(is.null(dir)){ stop("Set `dir` to the directory where the intermediate plots are saved in.") @@ -47,20 +47,21 @@ stop_motion <- function(height = 500, dir = GG_RECORDING_ENV$recording_dir, ext warning("No file extension set. All allowable image file extentions will be used") } - records <- get_file_records(full_path = TRUE, path = dir, ext = ext %||% "(png)|(pdf)|(jpeg)|(bmp)|(tiff)|(emf)|(svg)|(eps)|(ps)") + records <- get_file_records(full_path = FALSE, path = dir, ext = ext %||% "(png)|(pdf)|(jpeg)|(bmp)|(tiff)|(emf)|(svg)|(eps)|(ps)") slick_content <- lapply(records, function(image_path, img_height){ img_ext <- tools::file_ext(image_path) if(img_ext%in% c("tif", "emf", "eps", "ps")){ - img_tag <- htmltools::tags$img(src = read_image_b64(image_path), + img_tag <- htmltools::tags$img(src = image_path, style = paste0( "max-height:100%;", + "max-width:100%", "width:auto;height:auto;", "margin-left: auto; margin-right: auto;", "vertical-align:middle;")) }else if( img_ext %in% c("pdf")){ - img_tag <- htmltools::tags$img(src = pdf_to_png(image_path), + img_tag <- htmltools::tags$img(src = pdf_to_png(file.path(dir, image_path)), style = paste0( "max-height:100%;", "width:auto;height:auto;", @@ -85,23 +86,28 @@ stop_motion <- function(height = 500, dir = GG_RECORDING_ENV$recording_dir, ext slick_content, height = height, width = "95%") + - slickR::settings(infinite = TRUE) - ) %synch% ( - slickR::slickR( - slick_content, - height = 50) + - slickR::settings( - arrows = FALSE, - slidesToShow = 3, - slidesToScroll = 1, - centerMode = TRUE, - focusOnSelect = TRUE, - initialSlide = 0, - infinite = TRUE - ) + slickR::settings(infinite = FALSE) ) - return(slick_carousel) + if(is.null(filename)){ + filename <- file.path(dir, "carousel.html") + } + + htmltools::save_html( + slick_carousel, + file = filename + ) + + viewer <- getOption("viewer", utils::browseURL) + + if (is.function(viewer) && + length(filename) > 0 && interactive()) { + viewer(filename) + } + + invisible() + + } pdf_to_png <- function(pdf_path, path = tempdir()){ diff --git a/man/stop_motion.Rd b/man/stop_motion.Rd index fc23aa5..ead982c 100644 --- a/man/stop_motion.Rd +++ b/man/stop_motion.Rd @@ -7,7 +7,8 @@ stop_motion( height = 500, dir = GG_RECORDING_ENV$recording_dir, - ext = GG_RECORDING_ENV$device_ext + ext = GG_RECORDING_ENV$device_ext, + filename = NULL ) } \arguments{ @@ -31,7 +32,7 @@ slickR and htmltools must be installed for this function to operate. if(require(ggplot2) & interactive()){ - gg_record(dir = file.path(tempdir(),"recording"), device = "pdf" ) + gg_record(dir = file.path(tempdir(),"recording"), device = "png" ) ggplot(data.frame(x = 1, y = 1), aes(x=x, y=y)) + geom_point() + ylim(0,4) ggplot(data.frame(x = 1, y = 2), aes(x=x, y=y)) + geom_point() + ylim(0,4)