R/ct_plot_1stlast.R

Defines functions ct_plot_1stlast

Documented in ct_plot_1stlast

#' Make concentration-time plots of the 1st and last doses only
#'
#' \code{ct_plot_1stlast} makes concentration-time plots like Freddy and Laura
#' Sh. discussed. :)
#'
#' @param ct_dataframe the input concentration-time data generated by running
#'   the function \code{\link{extractConcTime_mult}} or
#'   \code{\link{extractConcTime}}. Not quoted.
#' @param obs_to_sim_assignment optionally specify which observed files should
#'   be compared to which simulator files. If left as NA and what you supplied
#'   for \code{ct_dataframe} doesn't already specify which observed data go with
#'   which simulated file, this will assume that \emph{all} observed data goes
#'   with \emph{all} simulated data. To specify, use a named character vector
#'   like this: \code{obs_to_sim_assignment = c("obs data 1.xlsx" =
#'   "mdz-5mg-qd.xlsx", "obs data 2.xlsx" = "mdz-5mg-qd-cancer.xlsx")} If one
#'   observed file needs to match more than one simulated file but not
#'   \emph{all} the simulated files, you can do that by separating the simulated
#'   files with commas, e.g., \code{obs_to_sim_assignment = c("obs data 1.xlsx"
#'   = "mdz-5mg-qd.xlsx, mdz-5mg-qd-fa08.xlsx", "obs data 2.xlsx" =
#'   "mdz-5mg-qd-cancer.xlsx, mdz-5mg-qd-cancer-fa08.xlsx")}. Pay close
#'   attention to the position of commas and quotes there!
#' @param mean_type plot "arithmetic" (default) or "geometric" mean
#'   concentrations or "median" concentrations as the main (thickest or only)
#'   line for each data set. If this aggregate measure is not available in the
#'   simulator output, you'll receive a warning message and we'll plot one that
#'   \emph{is} available.
#' @param figure_type the type of figure to plot. \describe{
#'
#'   \item{"means only"}{(default) show only the mean, geometric mean, or median
#'   (whatever you chose for "mean_type")}
#'
#'   \item{"percentiles"}{plots an opaque line for the mean data and lighter
#'   lines for the 5th and 95th percentiles of the simulated data}
#'
#'   \item{"percentile ribbon"}{show an opaque line for the mean data and
#'   transparent shading for the 5th to 95th percentiles. \strong{NOTE: There is
#'   a known bug within RStudio that can cause filled semi-transparent areas
#'   like you get with the "percentile ribbon" figure type to NOT get graphed
#'   for certain versions of RStudio.} To get around this, within RStudio, go to
#'   Tools --> Global Options --> General --> Graphics --> And then set
#'   "Graphics device: backend" to "AGG". Honestly, this is a better option for
#'   higher-quality graphics anyway!}}
#' @param linear_or_log the type of graph to be returned. Options: \describe{
#'   \item{"semi-log"}{y axis is log transformed; this is the default}
#'
#'   \item{"linear"}{no axis transformation}
#'
#'   \item{"both vertical"}{both the linear and the semi-log graphs will be
#'   returned, and graphs are stacked vertically}
#'
#'   \item{"both horizontal"}{both the linear and the semi-log graphs will be
#'   returned, and graphs are stacked horizontally}}
#' @param colorBy_column (optional) the column in \code{ct_dataframe} that
#'   should be used for determining which color lines and/or points will be.
#'   This should be unquoted, e.g., \code{colorBy_column = Tissue}.
#' @param color_labels optionally specify a character vector for how you'd like
#'   the labels for whatever you choose for \code{colorBy_column} to show up in
#'   the legend. For example, use \code{color_labels = c("file 1.xlsx" = "fa
#'   0.5", "file 2.xlsx" = "fa 0.2")} to indicate that "file 1.xlsx" is for an
#'   fa of 0.5 and "file 2.xlsx" is for an fa of 0.2. The order in the legend
#'   will match the order designated here.
#' @param legend_label_color optionally indicate on the legend something
#'   explanatory about what the colors represent. For example, if
#'   \code{colorBy_column = File} and \code{legend_label_color = "Simulations
#'   with various fa values"}, that will make the label above the file names in
#'   the legend more explanatory than just "File". The default is to use
#'   whatever the column name is for \code{colorBy_column}. If you don't want a
#'   label for this legend item, set this to "none".
#' @param color_set the set of colors to use. Options: \describe{
#'
#'   \item{"default"}{a set of colors from Cynthia Brewer et al. from Penn State
#'   that are friendly to those with red-green colorblindness. The first three
#'   colors are green, orange, and purple. This can also be referred to as
#'   "Brewer set 2". If there are only two unique values in the colorBy_column,
#'   then Brewer set 1 will be used since red and blue are still easily
#'   distinguishable but also more aesthetically pleasing than green and
#'   orange.}
#'
#'   \item{"Brewer set 1"}{colors selected from the Brewer palette "set 1". The
#'   first three colors are red, blue, and green.}
#'
#'   \item{"ggplot2 default"}{the default set of colors used in ggplot2 graphs
#'   (ggplot2 is an R package for graphing.)}
#'
#'   \item{"rainbow"}{colors selected from a rainbow palette. The default
#'   palette is limited to something like 6 colors, so if you have more than
#'   that, that's when this palette is most useful. It's \emph{not} very useful
#'   when you only need a couple of colors.}
#'
#'   \item{"blue-green"}{a set of blues fading into greens. This palette can be
#'   especially useful if you are comparing a systematic change in some
#'   continuous variable -- for example, increasing dose or predicting how a
#'   change in intrinsic solubility will affect concentration-time profiles --
#'   because the direction of the trend will be clear.}
#'
#'   \item{"blues"}{a set of blues fading light blue to dark blue. Like
#'   "blue-green", this palette can be especially useful if you are comparing a
#'   systematic change in some continuous variable.}
#'
#'   \item{"Tableau"}{uses the standard Tableau palette; requires the "ggthemes"
#'   package}
#'
#'   \item{"viridis"}{from the eponymous package by Simon Garnier and ranges
#'   colors from purple to blue to green to yellow in a manner that is
#'   "printer-friendly, perceptually uniform and easy to read by those with
#'   colorblindness", according to the package author}
#'
#'   \item{a character vector of colors}{If you'd prefer to set all the colors
#'   yourself to \emph{exactly} the colors you want, you can specify those
#'   colors here. An example of how the syntax should look: \code{color_set =
#'   c("dodgerblue3", "purple", "#D8212D")} or, if you want to specify exactly
#'   which item in \code{colorBy_column} gets which color, you can supply a
#'   named vector. For example, if you're coloring the lines by the compound ID,
#'   you could do this: \code{color_set = c("substrate" = "dodgerblue3",
#'   "inhibitor 1" = "purple", "primary metabolite 1" = "#D8212D")}. If you'd
#'   like help creating a specific gradation of colors, please talk to a member
#'   of the R Working Group about how to do that using
#'   \link{colorRampPalette}.}}
#'
#' @param obs_shape optionally specify what shapes are used to depict observed
#'   data for a) the substrate drug alone and b) the substrate drug in the
#'   presence of a perpetrator. Input should look like this, for example:
#'   \code{c(1, 2)} to get an open circle for the substrate and an open triangle
#'   for the substrate in the presence of perpetrators, if there are any. If you
#'   only specify one value, it will be used for both substrate with and without
#'   perpetrators. To see all the possible shapes and what number corresponds to
#'   which shape, type \code{ggpubr::show_point_shapes()} into the console. If
#'   left as NA, substrate alone will be an open circle and substrate +
#'   inhibitor 1 will be an open triangle.
#' @param obs_size optionally specify the size of the points to use for the
#'   observed data. If left as NA, the size will be 2.
#' @param obs_color optionally specify a color to use for observed data if the
#'   color isn't already mapped to a specific column. By default, observed data
#'   will be the same color as whatever else matches those observed data in
#'   \code{colorBy_column}, so if you have colored by compound ID, for example,
#'   the observed data will also be colored by compound ID. If you have one
#'   observed file that you're comparing to multiple simulation files (this is
#'   what ct_plot_overlay will do if "File" is NA for the observed data), then
#'   the observed data will all be black by default, or you could set that color
#'   to be, say, a lovely purple by setting this: \code{obs_color =
#'   "darkorchid4"}. Hex color codes are also ok to use, and setting this to
#'   "none" will remove observed data from the graph.
#' @param obs_fill_trans optionally specify the transparency for the fill of the
#'   observed data points, which can be helpful when you have a lot of points
#'   overlapping. This only applies when you have specified a value for
#'   \code{obs_color} and when \code{obs_shape} is a shape that has a fill
#'   (example: \code{obs_shape = 21} for a filled circle, which is the default).
#'   Acceptable values are from 0 (fully transparent, so no fill at all) to 1
#'   (completely opaque or black). If left as the default NA, the observed data
#'   points will be 50 percent transparent, so the same as if this were set to
#'   0.5.
#' @param obs_line_trans optionally specify the transparency for the outline of
#'   the observed data points, which can be helpful when you have a lot of
#'   points overlapping. Acceptable values are from 0 (fully transparent, so no
#'   line at all) to 1 (completely opaque or black). If left as the default NA,
#'   the observed data points will be opaque, so the same as if this were set to
#'   1.
#' @param connect_obs_points TRUE or FALSE (default) for whether to add
#'   connecting lines between observed data points from the same individual
#' @param obs_on_top TRUE (default) or FALSE for whether to show the observed
#'   data on top of the simulated data. If FALSE, the simulated data will be on
#'   top.
#' @param include_errorbars TRUE or FALSE (default) for whether to include error
#'   bars for observed data points. This ONLY applies when you have supplied
#'   observed data from V22 or higher because those data files included a column
#'   titled "SD/SE", which is what we'll use for determining the error bar
#'   heights.
#' @param errorbar_width width of error bars to use in hours (or, if you've used
#'   some other time unit, in whatever units are in your data). Default is 0.5.
#' @param linetype_column the column in \code{ct_dataframe} that should be used
#'   for determining the line types and also the shapes of the points for
#'   depicting any observed data. For example, if \code{linetype_column} is set
#'   to \code{Inhibitor}, then the default is to show a solid line (simulated
#'   data) and an open circle (observed data) for no inhibitor being present and
#'   then a dashed line (simulated data) and an open triangle (observed data)
#'   when the inhibitor \emph{is} present. You can set which types of lines to
#'   use with the argument \code{linetypes} and you can set which shapes of
#'   points you want with the argument \code{obs_shape}.
#' @param linetype_labels optionally specify a character vector for how you'd
#'   like the labels for whatever you choose for \code{linetype_column} to show
#'   up in the legend. For example, use \code{linetype_labels = c("file 1.xlsx"
#'   = "fa 0.5", "file 2.xlsx" = "fa 0.2")} to indicate that "file 1.xlsx" is
#'   for an fa of 0.5 and "file 2.xlsx" is for an fa of 0.2. The order in the
#'   legend will match the order designated here.
#' @param linetypes the line types to use. Default is "solid" for all lines.
#'   You'll need one line type for each possible value in the column you
#'   specified for \code{linetype_column}. If you get a graph you didn't expect
#'   as far as line types go, try checking what all the possible values are for
#'   the column you specified for \code{linetype_column}. You can do this by
#'   checking, e.g., \code{unique(CT$Inhibitor)} if your ct_dataframe was named
#'   "CT" and the column you set for \code{linetype_column} was "Inhibitor". To
#'   see possible line types by name, please enter
#'   \code{ggpubr::show_line_types()} into the console.
#' @param line_width optionally specify how thick to make the lines. Acceptable
#'   input is a number; the default is 1 for most lines and 0.8 for some, to
#'   give you an idea of where to start.
#' @param line_transparency optionally specify the transparency for the trial
#'   mean or percentile lines. Acceptable values are from 0 (fully transparent,
#'   so no line at all) to 1 (completely opaque or black). If left as the
#'   default NA, this value will be automatically determined.
#' @param legend_label_linetype optionally indicate on the legend something
#'   explanatory about what the line types represent. For example, if
#'   \code{linetype_column = Inhibitor} and \code{legend_label_linetype =
#'   "Inhibitor present"}, that will make the label in the legend above, e.g.,
#'   "none", and whatever perpetrator was present more explanatory than just
#'   "Inhibitor". The default is to use whatever the column name is for
#'   \code{linetype_column}. If you don't want a label for this legend item, set
#'   this to "none".
#' @param facet1_column optionally break up the graph into small multiples. We
#'   recommend setting this to \code{CompoundID} for this particular function.
#'   This specifies the first of up to two columns to break up the data by, and
#'   the designated column name should be unquoted, e.g., \code{facet1_column =
#'   Tissue}. If \code{floating_facet_scale} is FALSE and you haven't specified
#'   \code{facet_ncol} or  \code{facet_nrow}, then \code{facet1_column} will
#'   designate the rows of the output graphs.
#' @param facet2_column optionally break up the graph into small multiples; this
#'   specifies the second of up to two columns to break up the data by, and the
#'   designated column name should be unquoted, e.g., \code{facet2_column =
#'   CompoundID}. If \code{floating_facet_scale} is FALSE and you haven't
#'   specified \code{facet_ncol} or  \code{facet_nrow}, then
#'   \code{facet2_column} will designate the columns of the output graphs.
#' @param facet1_title optionally specify a title to describe facet 1. This is
#'   ignored if \code{floating_facet_scale} is TRUE or if you have specified
#'   \code{facet_ncol} or \code{facet_nrow}.
#' @param facet2_title optionally specify a title to describe facet 2. This is
#'   ignored if \code{floating_facet_scale} is TRUE or if you have specified
#'   \code{facet_ncol} or \code{facet_nrow}.
#' @param facet_ncol optionally specify the number of columns of facetted graphs
#'   you would like to have. This only applies when you have specified a column
#'   for \code{facet1_column} and/or \code{facet2_column}.
#' @param facet_nrow optionally specify the number of rows of facetted graphs
#'   you would like to have. This only applies when you have specified a column
#'   for \code{facet1_column} and/or \code{facet2_column}.
#' @param floating_facet_scale TRUE or FALSE (default) for whether to allow the
#'   axes for each facet of a multi-facetted graph to scale freely to best fit
#'   whatever data are present. Default is FALSE, which means that all data will
#'   be on the same scale for easy comparison. However, this could mean that
#'   some graphs have lines that are hard to see, so you can set this to TRUE to
#'   allow the axes to shrink or expand according to what data are present for
#'   that facet. Floating axes comes with a trade-off for the looks of the
#'   graphs, though: Setting this to TRUE does mean that your x axis won't
#'   automatically have pretty breaks that are sensible for times in hours.
#' @param facet_spacing Optionally set the spacing between facets. If left as
#'   NA, a best-guess as to a reasonable amount of space will be used. Units are
#'   "lines", so try, e.g. \code{facet_spacing = 2}. (Reminder: Numeric data
#'   should not be in quotes.)
#' @param x_axis_label optionally supply a character vector or an expression to
#'   use for the x axis label
#' @param pad_x_axis optionally add a smidge of padding to the x axis (default
#'   is TRUE, which includes some generally reasonable padding). If changed to
#'   FALSE, the y axis will be placed right at the beginning of your time range
#'   and all data will end \emph{exactly} at the end of the time range
#'   specified. If you want a \emph{specific} amount of x-axis padding, set this
#'   to a number; the default is \code{c(0.02, 0.04)}, which adds 2\% more space
#'   to the left side and 4\% more space to the right side of the x axis. If you
#'   only specify one number, padding is added to the left side.
#' @param pad_y_axis optionally add a smidge of padding to the y axis (default
#'   is TRUE, which includes some generally reasonable padding). As with
#'   \code{pad_x_axis}, if changed to FALSE, the x axis will be placed right at
#'   the bottom of your data, possibly cutting a point in half. If you want a
#'   \emph{specific} amount of y-axis padding, set this to a number; the default
#'   is \code{c(0.02, 0)}, which adds 2\% more space to the bottom and nothing
#'   to the top of the y axis. If you only specify one number, padding is added
#'   to the bottom.
#' @param y_axis_limits_lin Optionally set the Y axis limits for the linear
#'   plot, e.g., \code{c(10, 1000)}. If left as NA, the Y axis limits for the
#'   linear plot will be automatically selected. This only applies when you have
#'   requested a linear plot with \code{linear_or_log}.
#' @param y_axis_limits_log Optionally set the Y axis limits for the semi-log
#'   plot, e.g., \code{c(10, 1000)}. Values will be rounded down and up,
#'   respectively, to the nearest order of magnitude. If left as NA, the Y axis
#'   limits for the semi-log plot will be automatically selected. This only
#'   applies when you have requested a semi-log plot with \code{linear_or_log}.
#' @param y_axis_interval set the y-axis major tick-mark interval. Acceptable
#'   input: any number or leave as NA to accept default values, which are
#'   generally reasonable guesses as to aesthetically pleasing intervals.
#' @param y_axis_label optionally supply a character vector or an expression to
#'   use for the y axis label
#' @param conc_units_to_use concentration units to use for graphs. If left as
#'   NA, the concentration units in the source data will be used. Acceptable
#'   options are "mg/L", "mg/mL", "µg/L" (or "ug/L"), "µg/mL" (or "ug/mL"),
#'   "ng/L", "ng/mL", "µM" (or "uM"), or "nM". If you want to use a molar
#'   concentration and your source data were in mass per volume units or vice
#'   versa, you'll need to provide something for the argument
#'   \code{existing_exp_details}.
#' @param hline_position numerical position(s) of any horizontal lines to add to
#'   the graph. The default is NA to have no lines, and good syntax if you
#'   \emph{do} want lines would be, for example, \code{hline_position = 10} to
#'   have a horizontal line at 10 ng/mL (or whatever your concentration units
#'   are) or \code{hline_position = c(10, 100, 1000)} to have horizontal lines
#'   at each of those y values. Examples of where this might be useful would be
#'   to indicate a toxicity threshold, a target Cmin, or the lower limit of
#'   quantification for the assay used to generate the concentration-time data.
#' @param hline_style the line color and type to use for any horizontal lines
#'   that you add to the graph with \code{hline_position}. Default is "red
#'   dotted", but any combination of 1) a color in R and 2) a named linetype is
#'   acceptable. Examples: "red dotted", "blue dashed", or "#FFBE33 longdash".
#'   To see all the possible linetypes, type \code{ggpubr::show_line_types()}
#'   into the console.
#' @param vline_position numerical position(s) of any vertical lines to add to
#'   the graph. The default is NA to have no lines, and good syntax if you
#'   \emph{do} want lines would be, for example, \code{vline_position = 12} to
#'   have a vertical line at 12 h or \code{vline_position = seq(from = 0, to =
#'   168, by = 24)} to have horizontal lines every 24 hours for one week.
#'   Examples of where this might be useful would be indicating dosing times or
#'   the time at which some other drug was started or stopped.
#' @param vline_style the line color and type to use for any vertical lines that
#'   you add to the graph with \code{vline_position}. Default is "red dotted",
#'   but any combination of 1) a color in R and 2) a named linetype is
#'   acceptable. Examples: "red dotted", "blue dashed", or "#FFBE33 longdash".
#'   To see all the possible linetypes, type \code{ggpubr::show_line_types()}
#'   into the console.
#' @param graph_labels TRUE (default) or FALSE for whether to include labels (A,
#'   B, C, etc.) for each of the small graphs.
#' @param graph_title_size the font size for the graph titles; default is 14.
#'   This also determines the font size of the graph labels.
#' @param legend_position Specify where you want the legend to be. Options are
#'   "left", "right" (default in most scenarios), "bottom", "top", or "none" if
#'   you don't want one at all.
#' @param prettify_compound_names set this to a) TRUE (default) or FALSE for
#'   whether to make the compound names in the legend prettier or b) supply a
#'   named character vector to set it to the exact name you'd prefer to see in
#'   your legend. For example, \code{prettify_compound_names =
#'   c("Sim-Ketoconazole-400 mg QD" = "ketoconazole", "Wks-Drug ABC-low_ka" =
#'   "Drug ABC")} will make those compounds "ketoconazole" and "Drug ABC" in a
#'   legend, and \code{prettify_compound_names = TRUE} will make some reasonable
#'   guesses about what a prettier compound name should be. An example of
#'   setting this to TRUE: "SV-Rifampicin-MD" would become "rifampicin", and
#'   "Sim-Ketoconazole-200 mg BID" would become "ketoconazole".
#' @param name_clinical_study optionally specify the name(s) of the clinical
#'   study or studies for any observed data. This only affects the caption of
#'   the graph. For example, specifying \code{name_clinical_study = "101, fed
#'   cohort"} will result in a figure caption that reads in part "clinical study
#'   101, fed cohort". If you have more than one study, that's fine; we'll take
#'   care of stringing them together appropriately. Just list them as a
#'   character vector, e.g., \code{name_clinical_study = c("101",
#'   "102", "103")} will become "clinical studies 101, 102, and 103."
#' @param return_caption TRUE or FALSE (default) for whether to return any
#'   caption text to use with the graph. This works best if you supply something
#'   for the argument \code{existing_exp_details}. If set to TRUE, you'll get as
#'   output a list of the graph, the figure heading, and the figure caption.
#' @param save_graph optionally save the output graph by supplying a file name
#'   in quotes here, e.g., "My conc time graph.png"or "My conc time graph.docx".
#'   The nice thing about saving to Word is that the figure title and caption
#'   text will be partly filled in automatically, although you should check that
#'   the text makes sense in light of your exact graph. If you leave off ".png"
#'   or ".docx", it will be saved as a png file, but if you specify a different
#'   graphical file extension, it will be saved as that file format. Acceptable
#'   graphical file extensions are "eps", "ps", "jpeg", "jpg", "tiff", "png",
#'   "bmp", or "svg". Do not include any slashes, dollar signs, or periods in
#'   the file name. Leaving this as NA means the file will not be automatically
#'   saved to disk.
#' @param fig_height figure height in inches
#' @param fig_width figure width in inches
#' @param time_range_1st time range for the "1st" dose, really, the first panel
#'   in the set of graphs (in other words, it doesn't \emph{have} to be exactly
#'   the 1st dose)
#' @param x_axis_interval_1st x axis interval to use for the 1st panel in the
#'   set of graphs
#' @param time_range_last time range for the "last" dose, really, the second
#'   panel in the set of graphs (in other words, it doesn't \emph{have} to be
#'   exactly the 1st dose)
#' @param x_axis_interval_last x axis interval to use for the 1st panel in the
#'   set of graphs
#' @param existing_exp_details output from \code{\link{extractExpDetails}} or
#'   \code{\link{extractExpDetails_mult}} to be used for creating figure
#'   headings and captions tailored to the specific simulation when saving to a
#'   Word file
#' @param legend_orientation optionally specify how the legend entries should be
#'   oriented. Options are "vertical" or "horizontal", and, if left as NA, the
#'   legend entries will be "vertical" when the legend is on the  left or right
#'   and "horizontal" when it's on the top or bottom.
#'
#' @return a ggplot2 graphs or a set of arranged ggplot2 graphs
#' @export
#'
#' @examples
#' data(MDZct)


ct_plot_1stlast <- function(ct_dataframe, 
                            obs_to_sim_assignment = NA,
                            mean_type = "arithmetic",
                            figure_type = "means only", 
                            linear_or_log = "semi-log",
                            colorBy_column,
                            color_labels = NA, 
                            legend_label_color = NA,
                            color_set = "default",
                            obs_shape = NA,
                            obs_color = NA,
                            obs_size = NA,
                            obs_fill_trans = NA, 
                            obs_line_trans = NA, 
                            connect_obs_points = FALSE, 
                            obs_on_top = TRUE, 
                            include_errorbars = FALSE, 
                            errorbar_width = 0.5,
                            linetype_column, 
                            linetype_labels = NA, 
                            linetypes = c("solid", "dashed"),
                            line_width = NA,
                            line_transparency = NA,
                            legend_label_linetype = NA,
                            facet1_column,
                            facet1_title = NA,
                            facet2_column, 
                            facet2_title = NA, 
                            facet_ncol = NA, 
                            facet_nrow = NA,
                            floating_facet_scale = FALSE,
                            facet_spacing = NA,
                            time_range_1st = NA, 
                            x_axis_interval_1st = NA,
                            time_range_last = NA, 
                            x_axis_interval_last = NA,
                            x_axis_label = NA,
                            pad_x_axis = TRUE,
                            pad_y_axis = TRUE,
                            y_axis_limits_lin = NA,
                            y_axis_limits_log = NA, 
                            y_axis_interval = NA,
                            y_axis_label = NA,
                            conc_units_to_use = NA, 
                            hline_position = NA, 
                            hline_style = "red dotted", 
                            vline_position = NA, 
                            vline_style = "red dotted",
                            graph_labels = TRUE,
                            graph_title_size = 14, 
                            legend_position = NA,
                            legend_orientation = NA, 
                            prettify_compound_names = TRUE,
                            name_clinical_study = NA, 
                            existing_exp_details = NA, 
                            return_caption = FALSE, 
                            save_graph = NA,
                            fig_height = NA,
                            fig_width = NA){
   
   # Error catching ---------------------------------------------------------
   # Check whether tidyverse is loaded
   if("package:tidyverse" %in% search() == FALSE){
      stop("The SimcypConsultancy R package requires the package tidyverse to be loaded, and it doesn't appear to be loaded yet. Please run\nlibrary(tidyverse)\n     ...and then try again.", 
           call. = FALSE)
   }
   
   # Check whether patchwork is loaded
   if("package:patchwork" %in% search() == FALSE){
      stop("This particular function requires the package `patchwork` to be loaded, and it doesn't appear to be loaded yet. Please run:\nlibrary(patchwork)\n     ...and then try again.", 
           call. = FALSE)
   }
   
   if(nrow(ct_dataframe) == 0){
      stop("Please check your input. The data.frame you supplied for ct_dataframe doesn't have any rows.", 
           call. = FALSE)
   }
   
   if(any(complete.cases(time_range_1st)) &&
      length(time_range_1st) < 2){
      warning(wrapn("You must supply 2 values (beginning and end) for the 1st dose for time_range_1st or leave this as NA. We're settin this to NA."), 
              call. = FALSE)
      time_range_1st <- NA
   }
   
   if(any(complete.cases(time_range_last)) &&
      length(time_range_last) < 2){
      warning(wrapn("You must supply 2 values (beginning and end) for the last dose for time_range_1st or leave this as NA. We're settin this to NA."), 
              call. = FALSE)
      time_range_last <- NA
   }
   
   if(all(is.na(ct_dataframe$DoseNum))){
      stop("All the dose numbers in your data are NA, and we need to know which time ranges were the 1st and which were the last doses, so we cannot make a graph with the current data. Please check your input for ct_dataframe.\n", 
           call. = FALSE)
   }
   
   # Main body of function -------------------------------------------------
   
   facet1_column <- rlang::enquo(facet1_column)
   facet2_column <- rlang::enquo(facet2_column)
   colorBy_column <- rlang::enquo(colorBy_column)
   linetype_column <- rlang::enquo(linetype_column)
   
   ct_subfun <- function(dosenumber = NA, 
                         firstorlast = "1st",
                         timerange = NA, 
                         xaxisinterval = NA){
      
      if(complete.cases(dosenumber)){
         ct_temp <- ct_dataframe %>% filter(DoseNum == dosenumber)
      } else {
         ct_temp <- ct_dataframe %>% filter(Time >= timerange[1] &
                                               Time <= timerange[2])
      }
      
      ct_plot_overlay(ct_temp, 
                      colorBy_column = !!colorBy_column,
                      linetype_column = !!linetype_column,
                      facet1_column = !!facet1_column,
                      facet1_title = facet1_title, 
                      facet2_column = !!facet2_column,
                      facet2_title = facet2_title, 
                      obs_to_sim_assignment = obs_to_sim_assignment,
                      mean_type = mean_type,
                      figure_type = figure_type, 
                      linear_or_log = linear_or_log,
                      color_labels = color_labels, 
                      legend_label_color = legend_label_color,
                      legend_orientation = legend_orientation, 
                      color_set = color_set,
                      obs_shape = obs_shape,
                      obs_color = obs_color,
                      obs_size = obs_size,
                      obs_fill_trans = obs_fill_trans, 
                      obs_line_trans = obs_line_trans, 
                      obs_on_top = obs_on_top,
                      connect_obs_points = connect_obs_points,
                      include_errorbars = include_errorbars, 
                      errorbar_width = errorbar_width,
                      linetype_labels = linetype_labels, 
                      linetypes = linetypes,
                      line_width = line_width,
                      line_transparency = line_transparency,
                      legend_label_linetype = legend_label_linetype,
                      facet_ncol = facet_ncol, 
                      facet_nrow = facet_nrow,
                      floating_facet_scale = floating_facet_scale,
                      facet_spacing = facet_spacing,
                      time_range = timerange, 
                      x_axis_interval = xaxisinterval,
                      x_axis_label = x_axis_label,
                      pad_x_axis = pad_x_axis,
                      pad_y_axis = pad_y_axis,
                      y_axis_limits_lin = y_axis_limits_lin,
                      y_axis_limits_log = y_axis_limits_log, 
                      y_axis_interval = y_axis_interval,
                      y_axis_label = y_axis_label,
                      existing_exp_details = existing_exp_details, 
                      conc_units_to_use = conc_units_to_use, 
                      hline_position = hline_position, 
                      hline_style = hline_style, 
                      vline_position = vline_position, 
                      vline_style = vline_style,
                      graph_labels = FALSE,
                      graph_title = ifelse(firstorlast == "1st", 
                                           "Dose 1", "Last dose"),
                      graph_title_size = graph_title_size, 
                      legend_position = legend_position,
                      prettify_compound_names = prettify_compound_names,
                      qc_graph = FALSE,
                      save_graph = NA,
                      fig_height = fig_height,
                      fig_width = fig_width)
   }
   
   A <- ct_subfun(
      dosenumber = ifelse(any(complete.cases(time_range_1st)), 
                          NA, 1), 
      firstorlast = "1st",
      timerange = switch(as.character(any(complete.cases(time_range_1st))), 
                         "TRUE" = time_range_1st, 
                         "FALSE" = NA), 
      xaxisinterval = x_axis_interval_1st)
   
   suppressMessages(
      B <- ct_subfun(
         dosenumber = ifelse(any(complete.cases(time_range_last)), 
                             NA, max(ct_dataframe$DoseNum, na.rm = T)), 
         firstorlast = "last",
         timerange = switch(as.character(any(complete.cases(time_range_last))), 
                            "TRUE" = time_range_last, 
                            "FALSE" = NA), 
         xaxisinterval = x_axis_interval_last) )
   
   if(linear_or_log %in% c("both", "both vertical", "linear", "semi-log")){
      Out <- A + B + plot_layout(ncol = 2) + plot_layout(guides = "collect")
   } else {
      Out <- A + B + plot_layout(nrow = 2) + plot_layout(guides = "collect")
   }
   
   Out <- list("graph" = Out)
   
   # Setting up figure caption --------------------------------------------
   
   MyTissue <- unique(ct_dataframe$Tissue)
   MyTissueSubtype <- ifelse("Tissue_subtype" %in% names(ct_dataframe), 
                             unique(ct_dataframe$Tissue_subtype), 
                             "none")
   MyCompoundID <- unique(as.character(ct_dataframe$CompoundID))
   
   NumProfiles <- ifelse(length(MyTissue) == 1 & length(MyCompoundID) == 1 &
                            length(MyTissueSubtype) == 1, 
                         "single", "multiple")
   
   FigText <- make_ct_caption(ct_dataframe = ct_dataframe, 
                              single_or_multiple_profiles = NumProfiles, 
                              plot_type = "concentration-time", 
                              existing_exp_details = existing_exp_details, 
                              mean_type = mean_type, 
                              linear_or_log = linear_or_log, 
                              figure_type = figure_type, 
                              prettify_compound_names = prettify_compound_names, 
                              name_clinical_study = name_clinical_study, 
                              hline_position = hline_position, 
                              vline_position = vline_position, 
                              hline_style = hline_style, 
                              vline_style = vline_style)
   
   
   # Saving ------------------------------------------------------------------
   
   if(complete.cases(save_graph)){
      
      # Checking for NA for fig_height and width
      if(is.na(fig_height)){
         fig_height <- switch(linear_or_log, 
                              "linear" = 3.5, 
                              "log" = 3.5, 
                              "semi-log" = 3.5, 
                              "both" = 6, 
                              "both vertical" = 6,
                              "both horizontal" = 6, 
                              "horizontal and vertical" = 6)
      }
      
      if(is.na(fig_width)){
         fig_width <- switch(linear_or_log, 
                             "linear" = 8, 
                             "log" = 8, 
                             "semi-log" = 8, 
                             "both" = 8, 
                             "both vertical" = 8,
                             "both horizontal" = 8, 
                             "horizontal and vertical" = 8)
      }
      
      FileName <- save_graph
      if(str_detect(FileName, "\\.")){
         # Making sure they've got a good extension
         Ext <- sub("\\.", "", str_extract(FileName, "\\..*"))
         FileName <- sub(paste0(".", Ext), "", FileName)
         if(Ext %in% c("eps", "ps", "jpeg", "tiff",
                       "png", "bmp", "svg", "jpg", "docx") == FALSE){
            warning(wrapn(paste0("You have requested the graph's file extension be `", 
                                 Ext, "`, but we haven't set up that option. We'll save your graph as a `png` file instead.")),
                    call. = FALSE)
         }
         Ext <- ifelse(Ext %in% c("eps", "ps", "jpeg", "tiff",
                                  "png", "bmp", "svg", "jpg", "docx"), 
                       Ext, "png")
         FileName <- paste0(FileName, ".", Ext)
      } else {
         FileName <- paste0(FileName, ".png")
         Ext <- "png"
      }
      
      if(Ext == "docx"){
         
         # Setting some values that don't make sense for this scenario but are
         # needed for making the Rmd file work.
         EnzPlot <- FALSE
         ReleaseProfPlot <- FALSE
         DissolutionProfPlot <- FALSE
         
         # This is when they want a Word file as output
         OutPath <- dirname(FileName)
         if(OutPath == "."){
            OutPath <- getwd()
         }
         
         FileName <- basename(FileName)
         qc_graph <- FALSE
         
         if(NumProfiles == "single"){
            
            Data <- ct_dataframe
            MyPerpetrator <- unique(Data$Inhibitor) %>% as.character()
            MyPerpetrator <- MyPerpetrator[!MyPerpetrator == "none"]
            
            rmarkdown::render(system.file("rmarkdown/templates/concentration-time-plots/skeleton/skeleton.Rmd",
                                          package="SimcypConsultancy"), 
                              output_dir = OutPath, 
                              output_file = FileName, 
                              quiet = TRUE)
         } else {
            
            rmarkdown::render(system.file("rmarkdown/templates/multctplot/skeleton/skeleton.Rmd",
                                          package="SimcypConsultancy"), 
                              output_dir = OutPath, 
                              output_file = FileName, 
                              quiet = TRUE)
            
         }
         
      } else {
         ggsave(FileName, height = fig_height, width = fig_width, dpi = 600, 
                plot = Out[["graph"]])
      }
   }
   
   if(return_caption){
      Out[["figure_heading"]] <- FigText$heading
      Out[["figure_caption"]] <- FigText$caption
   } 
   
   if(length(Out) == 1){
      Out <- Out[[1]]
   }
   
   return(Out)
   
}
shirewoman2/Consultancy documentation built on Feb. 18, 2025, 10 p.m.