R/compile_tikz.R

#' Make a CONSORT-like diagram using TiKz
#'
#' \code{compile_tikz} outputs a standalone LaTeX document with the
#' specification for a TiKz CONSORT-like plot, and optionally converts the PDF
#' resulting from running LaTeX on this file to either jpeg or png format.
#'
#' @param tikz_code String (possibly vector of) containing the main part of the
#'   TiKz code you wish to insert into a LaTeX document shell.
#' @param filename_base Scalar string giving the root of the filename to which
#'   extensions are added to identify the types of files created as a side
#'   effect of running the function.
#' @param output_dir Scalar string with the name of the directory in which to
#'   store files.
#' @param output_format String scalar specifying the desired format for the plot
#'   graphic created (pdf, jpeg, png).  Note that a pdf is always created and is
#'   then converted if jpeg or png is requested. (default: pdf)
#' @param tikzlibs If additional TiKz libraries are needed, this (possibly
#'   vector of) string(s) gives their names (e.g., positining, calc). (default:
#'   "")
#' @param tikzpicture_opts If options are desired when beginning the TiKz
#'   environment, specify them using this vector of strings (e.g., to create
#'   styles). (default: "")
#' @param tex_only Scalar logical.  If true, output the standalone LaTeX
#'   document but do not run LaTeX.  Useful for debugging problemmatic LaTeX.
#'   (default: FALSE)
#'
#' @return Invisibly returns the LaTeX code generated by the function.
#' @export
#' @importFrom checkmate makeAssertCollection assertCharacter matchArg
#'   assertString reportAssertions
#' @importFrom magrittr %>%
#'
#' @details The LaTeX standalone document type is a very simple document that
#'   creates a page of just the dimensions required to contain the figure.  The
#'   LaTeX portion of this is therefore fairly simple, except for a macro
#'   defined called "coltab" that creates a multirow table.  This can be
#'   inserted into TiKz nodes as one method to create multirow node labels.
#'
#' @examples
#' print("Hello world")
compile_tikz = function(tikz_code, filename_base, output_dir, output_format = "pdf", tikzlibs = "", tikzpicture_opts = "", tex_only = FALSE){
  #function for making sure output goes to the correct directory


  #assign settings if not done so by user
  output_dir = if(missing(output_dir)) getwd() else output_dir
  assertDirectoryExists(output_dir, access = "rwx")
  filename_base = if(missing(filename_base)) {
    tempfile("tikz", tmpdir=output_dir) %>%
      stringr::str_extract("[^\\\\/]+$")
  } else filename_base

  #checks on function arguments
  chks = makeAssertCollection()
  assertCharacter(tikz_code, any.missing = FALSE, min.len = 1, add = chks)
  assertString(filename_base, pattern="^[^\\/\\\\\\.]+$", min.chars=1, add = chks)
  matchArg(output_format, choices = c("pdf", "png", "jpeg"), add=chks)
  assertCharacter(tikzpicture_opts, any.missing = FALSE, add = chks)
  assertCharacter(tikzlibs, any.missing = FALSE, add = chks)
  assertLogical(tex_only, any.missing = FALSE, len = 1, add = chks)
  reportAssertions(chks)

  tikz_code = paste(collapse = "\n",
                    sep = "\n",
                    c(
                      "\\documentclass{standalone}",
                      "\\newcommand{\\coltab}[2][c]{%",
                      "\\begin{tabular}{@{}#1@{}}",
                      "#2",
                      "\\end{tabular}%",
                      "}",
                      "\\usepackage{tikz}",
                      "\\begin{document}",
                      paste0("\\begin{tikzpicture}[", paste(tikzpicture_opts, collapse=","),"]"),
                      paste0("\\usetikzlibrary{", paste(tikzlibs, collapse=","), "}"),
                      tikz_code,
                      "\\end{tikzpicture}",
                      "\\end{document}"
                    )
  )

  cat(tikz_code, file=file.path(output_dir, paste0(filename_base, ".tex")))

  #stop here if only tex code is wanted
  if(isTRUE(tex_only)) return(invisible(tikz_code))

  with_dir(output_dir, tools::texi2pdf(paste0(filename_base, ".tex")))
  if(output_format != "pdf") with_dir(output_dir, pdftools::pdf_convert(paste0(filename_base, ".pdf"), format = output_format, dpi = 600, pages = 1))

  #return "nothing"
  return(invisible(tikz_code))
}
colinorourke/consortr documentation built on May 31, 2019, 11:42 p.m.