R/cyto_plot-methods.R

#' cyto_plot
#'
#' Explore & visualise flow cytometry data.
#'
#' \code{cyto_plot} is flow cytometry visualisation tool built on base graphics
#' which supports all existing flow cytometry objects including
#' \code{\link[flowCore:flowFrame-class]{flowFrame}},
#' \code{\link[flowCore:flowSet-class]{flowSet}},
#' \code{\link[flowWorkspace:GatingHierarchy-class]{GatingHierarchy}} and
#' \code{\link[flowWorkspace:GatingSet-class]{GatingSet}} objects. The type of
#' plot constructed by \code{cyto_plot} is determined by the number of channels
#' supplied to the \code{channels} argument. If a single channel is supplied, a
#' 1-D density distribution will be plotted. Supplying two channels to this
#' argument will result in construction of a 2-D scatterplot with a blue-red
#' density colour scale for points.
#'
#' Some key features of \code{cyto_plot} include: \itemize{ \item autocomplete
#' friendly arguments \item minimal coding \item 1-D density distributions \item
#' 2-D scatterplots \item stacked density distributions \item 2-D contour lines
#' \item back-gating \item overlays \item population labelling \item grid to
#' visualise multiple samples \item plot gate objects \item plot in pop-up
#' windows \item sampling \item fully customisable \item copy and paste
#' arguments from gate_draw }
#'
#' @param x object of class \code{flowFrame}, \code{flowSet} or
#'   \code{GatingSet}.
#' @param ... additional method-specific arguments for cyto_plot.
#'
#' @seealso \code{\link{cyto_plot,flowFrame-method}}
#' @seealso \code{\link{cyto_plot,flowSet-method}}
#' @seealso \code{\link{cyto_plot,GatingHierarchy-method}}
#' @seealso \code{\link{cyto_plot,GatingSet-method}}
#'
#' @author Dillon Hammill, \email{Dillon.Hammill@anu.edu.au}
#'
#' @export
setGeneric(
  name = "cyto_plot",
  def = function(x, ...) {
    standardGeneric("cyto_plot")
  }
)

#' cyto_plot - flowFrame Method
#'
#' Explore & visualise a flowFrame.
#'
#' @param x object of class \code{\link[flowCore:flowFrame-class]{flowFrame}}.
#' @param channels name of the channel(s) or marker(s) to be used to construct
#'   the plot. The length of channels determines the type of plot to be
#'   constructed, either a 1-D density distribution for a single channel or a
#'   2-D scatterplot with blue-red colour scale for two channels.
#' @param axes_trans object of class
#'   \code{\link[flowCore:transformList-class]{transformList}} or
#'   \code{\link[flowWorkspace]{transformerList}} generated by
#'   \code{\link[flowCore:logicleTransform]{estimateLogicle}} which was used to
#'   transform the fluorescent channels of the supplied flowFrame. This
#'   transformation object will be used internally to ensure that the axes
#'   labels of the plot are appropriately transformed. The transformation object
#'   will NOT be applied to the flowFrame internally and should be applied to
#'   the flowFrame prior to plotting.
#' @param overlay a \code{flowFrame}, \code{flowSet} or list of
#'   \code{flowFrames} to be overlaid onto the plot.
#' @param gate gate object(s) to be added to plot.  For \code{cyto_1d_plot} only
#'   gate objects of class
#'   \code{\link[flowCore:rectangleGate-class]{rectangleGate}} in either 1 or 2
#'   dimensions are supported. Multiple gates can be supplied either as a
#'   \code{list} or \code{\link[flowCore:filters-class]{filters}} object.
#' @param limits indicates whether the axes limits should be based on the
#'   \code{"data"} or \code{"machine"}, set to "machine" by default to show
#'   complete axes ranges. This argument will only alter the upper axis limits,
#'   to modify the lower limits use \code{xlim} and \code{ylim}.
#' @param popup logical indicating whether the plot should be constructed in a
#'   pop-up window, set to FALSE by default. \code{popup} will open OS-specific
#'   graphic device prior to plotting. Mac users will need to install
#'   \href{https://www.xquartz.org/}{XQuartz} for this functionality.
#' @param xlim lower and upper limits of x axis (e.g. c(0,5)).
#' @param ylim lower and upper limits of y axis (e.g. c(0,5)).
#' @param title title to use for the plot, set to the name of the sample by
#'   default. Title can be removed by setting this argument to \code{NA}.
#' @param xlab x axis label.
#' @param ylab y axis label.
#' @param density_modal logical indicating whether density should be normalised
#'   to mode and presented as a percentage for 1-D plots. Set to \code{TRUE} by
#'   default.
#' @param density_smooth smoothing parameter passed to
#'   \code{\link[stats:density]{density}} to adjust kernel density for 1-D
#'   plots.
#' @param density_stack numeric [0,1] indicating the degree of offset for 1-D
#'   density distributions with overlay, set to 0.5 by default.
#' @param density_fill fill colour(s) for 1-D density distributions.
#' @param density_fill_alpha numeric [0,1] used to control 1-D density fill
#'   colour transparency, set to 1 by default for solid colours.
#' @param density_line_type line type(s) to use for 1-D density lines, set to 1
#'   by default to use solid lines. See \code{\link[graphics:par]{lty}} for
#'   alternatives.
#' @param density_line_width numeric to control line width(s) for 1-D density
#'   lines, set to 1 by default.
#' @param density_line_col colour(s) for 1-D density lines, set to
#'   \code{"black"} by default.
#' @param point_shape shape(s) to use for points in 2-D scatterplots, set to
#'   \code{"."} by default to maximise plotting speed.  See
#'   \code{\link[graphics:par]{pch}} for alternatives.
#' @param point_size numeric to control the size of points in 2-D scatter plots
#'   set to 2 by default.
#' @param point_col colour(s) to use for points in 2-D scatter plots, set to NA
#'   by default to use a blue-red density colour scale.
#' @param point_alpha numeric [0,1] to control point colour transparency in 2-D
#'   scatter plots, set to 1 by default to use solid colours.
#' @param contour_lines numeric indicating the number of levels to use for
#'   contour lines in 2-D scatter plots, set to 0 by default to turn off contour
#'   lines.
#' @param contour_line_type integer [0,6] to control the line type of contour
#'   lines in 2-D scatter plots, set to \code{1} to draw solid lines by default.
#'   See \code{\link[graphics:par]{lty}} for alternatives.
#' @param contour_line_width numeric to control line width(s) for contour lines
#'   in 2-D scatter plots, set to 2 by default.
#' @param contour_line_col colour(s) to use for contour lines in 2-D scatter
#'   plots, set to \code{"black"} by default.
#' @param axes_text_font numeric to control the font of axes text, set to 1 for
#'   plain font by default. See \code{\link[graphics:par]{font}} for
#'   alternatives.
#' @param axes_text_size numeric to control the size of axes text, set to 1 by
#'   default.
#' @param axes_text_col colour to use for axes text, set to \code{"black"} by
#'   default.
#' @param axes_label_text_font numeric to control the font axes labels, set to 1
#'   for plain font by default. See \code{\link[graphics:par]{font}} for
#'   alternatives.
#' @param axes_label_text_size numeric to control the text size of axes labels,
#'   set to 1.1 by default.
#' @param axes_label_text_col colour to use for axes labels text, set to
#'   \code{"black"} by default.
#' @param title_text_font numeric to control the font of title text, set to 2
#'   for bold font by default. See \code{\link[graphics:par]{font}} for
#'   alternatives.
#' @param title_text_size numeric to control the text size of the plot title,
#'   set to 1.1 by default.
#' @param title_text_col colour to use for plot title text, set to
#'   \code{"black"} by default.
#' @param legend can be either \code{"line"} or \code{"fill"} to indicate
#'   whether a legend should be constructed based on the density \code{"line"}
#'   or \code{"fill"}, set to FALSE by default to remove the legend.
#' @param legend_text vector of labels to use in the legend.
#' @param legend_text_font numeric to control the font of legend text, set to 1
#'   for plain font by default. See \code{\link[graphics:par]{font}} for
#'   alternatives.
#' @param legend_text_size numeric to control the size of text in the legend,
#'   set to 1 by default.
#' @param legend_text_col colour(s) to use for text in legend, set to
#'   \code{"black"} by default.
#' @param legend_line_col colour(s) to use for the lines in 1-D plot legends
#'   when legend is set to \code{"line"}.
#' @param legend_box_fill fill colour(s) to use for the boxes in 1-D plot
#'   legends when legend is set to \code{"fill"}.
#' @param legend_point_col colour(s) to use for points in 2-D scatter plot
#'   legend.
#' @param gate_line_type integer [0,6] to control the line type of gates, set to
#'   \code{1} to draw solid lines by default. See
#'   \code{\link[graphics:par]{lty}} for alternatives.
#' @param gate_line_width numeric to control the line width(s) of gates, set to
#'   \code{2.5} by default.
#' @param gate_line_col colour(s) to use for gates, set to \code{"red"} by
#'   default.
#' @param label logical indicating whether gated populations should be labelled.
#'   To include the names of the populations in these labels, supply the
#'   population names to the \code{label_text} argument. The default statistic
#'   is \code{"percent"} for gated data and \code{"count"} for un-gated data.
#' @param label_text vector of population names to use in the labels. Set to
#'   \code{NA} by default to exclude population names.
#' @param label_stat indicates the type of statistic to include in the plot
#'   labels, can be \code{"percent"}, \code{"count"}, \code{"mean"},
#'   \code{"median"}, \code{"mode"} or \code{"geo mean"}, set to
#'   \code{"percent"} for gated data or \code{NA} to exclude statistics for
#'   un-gated data. Currently, only \code{"percent"} and \code{"count"} are
#'   supported for 2-D scatter plots.
#' @param label_text_font numeric to control the font of text in plot labels,
#'   set to 2 for bold font by default. See \code{\link[graphics:par]{font}} for
#'   alternatives.
#' @param label_text_size numeric to control the size of text in the plot
#'   labels, set to 1 by default.
#' @param label_text_col colour(s) to use for text in plot labels, set to
#'   \code{"black"} by default.
#' @param label_box_x vector of x co-ordinate(s) to manually adjust the position
#'   plot label(s) on the plot.
#' @param label_box_y vector of y co-ordinate(s) to manually adjust the position
#'   plot label(s) on the plot.
#' @param label_box_alpha numeric to control background fill transparency of
#'   label boxes, set to 0.6 by default to introduce some transparency.
#' @param border_line_type integer [0,6] to control the line type of plot
#'   border, set to \code{1} by default for a solid border. See
#'   \code{\link[graphics:par]{lty}} for alternatives.
#' @param border_line_width numeric to control line width for the plot border,
#'   set to 1 by default.
#' @param border_line_col colour to use for the plot border, set to "black" by
#'   default.
#' @param ... additional arguments passed to \code{\link[graphics:plot]{plot}}.
#'
#' @examples
#' library(CytoRSuiteData)
#' 
#' # Load in samples
#' fs <- Activation
#' 
#' # Apply compensation
#' fs <- compensate(fs, fs[[1]]@description$SPILL)
#' 
#' # Transform fluorescent channels
#' trans <- estimateLogicle(fs[[4]], cyto_fluor_channels(fs))
#' fs <- transform(fs, trans)
#' 
#' # 1-D Density Distribution
#' cyto_plot(fs[[1]],
#'   channels = "PE-A",
#'   axes_trans = trans,
#'   overlay = fs[2:4],
#'   density_stack = 0.5
#' )
#' 
#' # 2-D Scatter Plot
#' cyto_plot(fs[[4]],
#'   channels = c("FSC-A", "PE-A"),
#'   axes_trans = trans,
#'   overlay = fs[[1]]
#' )
#' @seealso \code{\link{cyto_plot,flowSet-method}}
#' @seealso \code{\link{cyto_plot,GatingHierarchy-method}}
#' @seealso \code{\link{cyto_plot,GatingSet-method}}
#'
#' @author Dillon Hammill, \email{Dillon.Hammill@anu.edu.au}
#'
#' @export
setMethod(cyto_plot,
  signature = "flowFrame",
  definition = function(x,
                          channels,
                          axes_trans = NULL,
                          overlay = NULL,
                          gate = NA,
                          limits = "machine",
                          popup = FALSE,
                          xlim = NULL,
                          ylim = NULL,
                          title,
                          xlab = NA,
                          ylab = NA,
                          density_modal = TRUE,
                          density_smooth = 1.5,
                          density_stack = 0,
                          density_fill = NA,
                          density_fill_alpha = 1,
                          density_line_type = 1,
                          density_line_width = 1,
                          density_line_col = "black",
                          point_shape = ".",
                          point_size = 2,
                          point_col = NA,
                          point_alpha = 1,
                          contour_lines = 0,
                          contour_line_type = 1,
                          contour_line_width = 1,
                          contour_line_col = "black",
                          axes_text_font = 1,
                          axes_text_size = 1,
                          axes_text_col = "black",
                          axes_label_text_font = 1,
                          axes_label_text_size = 1.1,
                          axes_label_text_col = "black",
                          title_text_font = 2,
                          title_text_size = 1.1,
                          title_text_col = "black",
                          legend = FALSE,
                          legend_text,
                          legend_text_font = 1,
                          legend_text_size = 1,
                          legend_text_col = "black",
                          legend_line_col = NA,
                          legend_box_fill = NA,
                          legend_point_col = NA,
                          gate_line_type = 1,
                          gate_line_width = 2.5,
                          gate_line_col = "red",
                          label = TRUE,
                          label_text = NA,
                          label_stat = "percent",
                          label_text_font = 2,
                          label_text_size = 1,
                          label_text_col = "black",
                          label_box_x = NA,
                          label_box_y = NA,
                          label_box_alpha = 0.6,
                          border_line_type = 1,
                          border_line_width = 1,
                          border_line_col = "black", ...) {

    # Check if channels supplied
    if (missing(channels)) {
      stop("Supply channel/marker(s) to construct the plot.")
    }

    # Assign x to fr
    fr <- x

    # Check channels
    channels <- cyto_channel_check(fr,
      channels = channels,
      plot = TRUE
    )

    # Make call to appropriate cyto_plot internal function
    if (length(channels) == 1) {
      .cyto_plot_1d(
        x = fr,
        channel = channels,
        axes_trans = axes_trans,
        overlay = overlay,
        gate = gate,
        limits = limits,
        popup = popup,
        xlim = xlim,
        ylim = ylim,
        title = title,
        xlab = xlab,
        ylab = ylab,
        density_modal = density_modal,
        density_smooth = density_smooth,
        density_stack = density_stack,
        density_fill = density_fill,
        density_fill_alpha = density_fill_alpha,
        density_line_type = density_line_type,
        density_line_width = density_line_width,
        density_line_col = density_line_col,
        axes_text_font = axes_text_font,
        axes_text_size = axes_text_size,
        axes_text_col = axes_text_col,
        axes_label_text_font = axes_label_text_font,
        axes_label_text_size = axes_label_text_size,
        axes_label_text_col = axes_label_text_col,
        title_text_font = title_text_font,
        title_text_size = title_text_size,
        title_text_col = title_text_col,
        legend = legend,
        legend_text = legend_text,
        legend_text_font = legend_text_font,
        legend_text_size = legend_text_size,
        legend_text_col = legend_text_col,
        legend_line_col = legend_line_col,
        legend_box_fill = legend_box_fill,
        gate_line_type = gate_line_type,
        gate_line_width = gate_line_width,
        gate_line_col = gate_line_col,
        label = label,
        label_text = label_text,
        label_stat = label_stat,
        label_text_font = label_text_font,
        label_text_size = label_text_size,
        label_text_col = label_text_col,
        label_box_x = label_box_x,
        label_box_y = label_box_y,
        label_box_alpha = label_box_alpha,
        border_line_type = border_line_type,
        border_line_width = border_line_width,
        border_line_col = border_line_col, ...
      )
    } else if (length(channels) == 2) {
      .cyto_plot_2d(
        x = fr,
        channels = channels,
        axes_trans = axes_trans,
        overlay = overlay,
        gate = gate,
        limits = limits,
        popup = popup,
        xlim = xlim,
        ylim = ylim,
        title = title,
        xlab = xlab,
        ylab = ylab,
        point_shape = point_shape,
        point_size = point_size,
        point_col = point_col,
        point_alpha = point_alpha,
        contour_lines = contour_lines,
        contour_line_type = contour_line_type,
        contour_line_width = contour_line_width,
        contour_line_col = contour_line_col,
        axes_text_font = axes_text_font,
        axes_text_size = axes_text_size,
        axes_text_col = axes_text_col,
        axes_label_text_font = axes_label_text_font,
        axes_label_text_size = axes_label_text_size,
        axes_label_text_col = axes_label_text_col,
        title_text_font = title_text_font,
        title_text_size = title_text_size,
        title_text_col = title_text_col,
        legend = legend,
        legend_text = legend_text,
        legend_text_font = legend_text_font,
        legend_text_size = legend_text_size,
        legend_text_col = legend_text_col,
        legend_point_col = legend_point_col,
        gate_line_type = gate_line_type,
        gate_line_width = gate_line_width,
        gate_line_col = gate_line_col,
        label = label,
        label_text = label_text,
        label_stat = label_stat,
        label_text_font = label_text_font,
        label_text_size = label_text_size,
        label_text_col = label_text_col,
        label_box_x = label_box_x,
        label_box_y = label_box_y,
        label_box_alpha = label_box_alpha,
        border_line_type = border_line_type,
        border_line_width = border_line_width,
        border_line_col = border_line_col, ...
      )
    }
  }
)

#' cyto_plot - flowSet Method
#'
#' Explore & visualise a flowSet.
#'
#' @param x object of class \code{\link[flowCore:flowSet-class]{flowSet}}.
#' @param channels name of the channel(s) or marker(s) to be used to construct
#'   the plot. The length of channels determines the type of plot to be
#'   constructed, either a 1-D density distribution for a single channel or a
#'   2-D scatterplot with blue-red colour scale for two channels.
#' @param axes_trans object of class
#'   \code{\link[flowCore:transformList-class]{transformList}} or
#'   \code{\link[flowWorkspace]{transformerList}} generated by
#'   \code{\link[flowCore:logicleTransform]{estimateLogicle}} which was used to
#'   transform the fluorescent channels of the supplied flowFrame. This
#'   transformation object will be used internally to ensure that the axes
#'   labels of the plot are appropriately transformed. The transformation object
#'   will NOT be applied to the flowFrame internally and should be applied to
#'   the flowFrame prior to plotting.
#' @param group_by a vector of pData variables to sort and merge samples into
#'   groups prior to plotting, set to NULL by default to prevent merging. To
#'   merge all samples set this argument to \code{TRUE} or \code{"all"}.
#' @param overlay a \code{flowFrame}, \code{flowSet}, \code{list of flowFrames},
#'   \code{list of flowSets} or \code{list of flowFrame lists} containing
#'   populations to be overlaid onto the plot(s).
#' @param gate gate object(s) to be added to plot.  For \code{cyto_1d_plot} only
#'   gate objects of class
#'   \code{\link[flowCore:rectangleGate-class]{rectangleGate}} in either 1 or 2
#'   dimensions are supported. Multiple gates can be supplied either as a
#'   \code{list} or \code{\link[flowCore:filters-class]{filters}} object.
#' @param limits indicates whether the axes limits should be based on the
#'   \code{"data"} or \code{"machine"}, set to "machine" by default to show
#'   complete axes ranges. This argument will only alter the upper axis limits,
#'   to modify the lower limits use \code{xlim} and \code{ylim}.
#' @param display numeric [0,1] to control the percentage of events to be
#'   plotted. Specifying a value for \code{display} can substantial improve
#'   plotting speed for less powerful machines.
#' @param layout a vector of the length 2 indicating the dimensions of the grid
#'   for plotting \code{c(#rows, #columns)}.
#' @param popup logical indicating whether the plot should be constructed in a
#'   pop-up window, set to FALSE by default. \code{popup} will open OS-specific
#'   graphic device prior to plotting. Mac users will need to install
#'   \href{https://www.xquartz.org/}{XQuartz} for this functionality.
#' @param xlim lower and upper limits of x axis (e.g. c(0,5)).
#' @param ylim lower and upper limits of y axis (e.g. c(0,5)).
#' @param title title to use for the plot, set to the name of the sample by
#'   default. Title can be removed by setting this argument to \code{NA}.
#' @param xlab x axis label.
#' @param ylab y axis label.
#' @param density_modal logical indicating whether density should be normalised
#'   to mode and presented as a percentage for 1-D plots. Set to \code{TRUE} by
#'   default.
#' @param density_smooth smoothing parameter passed to
#'   \code{\link[stats:density]{density}} to adjust kernel density for 1-D
#'   plots.
#' @param density_stack numeric [0,1] indicating the degree of offset for 1-D
#'   density distributions with overlay, set to 0.5 by default.
#' @param density_layers numeric indicating the number of samples to stack in
#'   each plot, set to all samples by default.
#' @param density_fill fill colour(s) for 1-D density distributions.
#' @param density_fill_alpha numeric [0,1] used to control 1-D density fill
#'   colour transparency, set to 1 by default for solid colours.
#' @param density_line_type line type(s) to use for 1-D density lines, set to 1
#'   by default to use solid lines. See \code{\link[graphics:par]{lty}} for
#'   alternatives.
#' @param density_line_width numeric to control line width(s) for 1-D density
#'   lines, set to 1 by default.
#' @param density_line_col colour(s) for 1-D density lines, set to
#'   \code{"black"} by default.
#' @param point_shape shape(s) to use for points in 2-D scatterplots, set to
#'   \code{"."} by default to maximise plotting speed.  See
#'   \code{\link[graphics:par]{pch}} for alternatives.
#' @param point_size numeric to control the size of points in 2-D scatter plots
#'   set to 2 by default.
#' @param point_col colour(s) to use for points in 2-D scatter plots, set to NA
#'   by default to use a blue-red density colour scale.
#' @param point_alpha numeric [0,1] to control point colour transparency in 2-D
#'   scatter plots, set to 1 by default to use solid colours.
#' @param contour_lines numeric indicating the number of levels to use for
#'   contour lines in 2-D scatter plots, set to 0 by default to turn off contour
#'   lines.
#' @param contour_line_type integer [0,6] to control the line type of contour
#'   lines in 2-D scatter plots, set to \code{1} to draw solid lines by default.
#'   See \code{\link[graphics:par]{lty}} for alternatives.
#' @param contour_line_width numeric to control line width(s) for contour lines
#'   in 2-D scatter plots, set to 2 by default.
#' @param contour_line_col colour(s) to use for contour lines in 2-D scatter
#'   plots, set to \code{"black"} by default.
#' @param axes_text_font numeric to control the font of axes text, set to 1 for
#'   plain font by default. See \code{\link[graphics:par]{font}} for
#'   alternatives.
#' @param axes_text_size numeric to control the size of axes text, set to 1 by
#'   default.
#' @param axes_text_col colour to use for axes text, set to \code{"black"} by
#'   default.
#' @param axes_label_text_font numeric to control the font axes labels, set to 1
#'   for plain font by default. See \code{\link[graphics:par]{font}} for
#'   alternatives.
#' @param axes_label_text_size numeric to control the text size of axes labels,
#'   set to 1.1 by default.
#' @param axes_label_text_col colour to use for axes labels text, set to
#'   \code{"black"} by default.
#' @param title_text_font numeric to control the font of title text, set to 2
#'   for bold font by default. See \code{\link[graphics:par]{font}} for
#'   alternatives.
#' @param title_text_size numeric to control the text size of the plot title,
#'   set to 1.1 by default.
#' @param title_text_col colour to use for plot title text, set to
#'   \code{"black"} by default.
#' @param legend can be either \code{"line"} or \code{"fill"} to indicate
#'   whether a legend should be constructed based on the density \code{"line"}
#'   or \code{"fill"}, set to FALSE by default to remove the legend.
#' @param legend_text vector of labels to use in the legend.
#' @param legend_text_font numeric to control the font of legend text, set to 1
#'   for plain font by default. See \code{\link[graphics:par]{font}} for
#'   alternatives.
#' @param legend_text_size numeric to control the size of text in the legend,
#'   set to 1 by default.
#' @param legend_text_col colour(s) to use for text in legend, set to
#'   \code{"black"} by default.
#' @param legend_line_col colour(s) to use for the lines in 1-D plot legends
#'   when legend is set to \code{"line"}.
#' @param legend_box_fill fill colour(s) to use for the boxes in 1-D plot
#'   legends when legend is set to \code{"fill"}.
#' @param legend_point_col colour(s) to use for points in 2-D scatter plot
#'   legend.
#' @param gate_line_type integer [0,6] to control the line type of gates, set to
#'   \code{1} to draw solid lines by default. See
#'   \code{\link[graphics:par]{lty}} for alternatives.
#' @param gate_line_width numeric to control the line width(s) of gates, set to
#'   \code{2.5} by default.
#' @param gate_line_col colour(s) to use for gates, set to \code{"red"} by
#'   default.
#' @param label logical indicating whether gated populations should be labelled.
#'   To include the names of the populations in these labels, supply the
#'   population names to the \code{label_text} argument. The default statistic
#'   is \code{"percent"} for gated data and \code{"count"} for un-gated data.
#' @param label_text vector of population names to use in the labels. Set to
#'   \code{NA} by default to exclude population names.
#' @param label_stat indicates the type of statistic to include in the plot
#'   labels, can be \code{"percent"}, \code{"count"}, \code{"mean"},
#'   \code{"median"}, \code{"mode"} or \code{"geo mean"}, set to
#'   \code{"percent"} for gated data or \code{NA} to exclude statistics for
#'   un-gated data. Currently, only \code{"percent"} and \code{"count"} are
#'   supported for 2-D scatter plots.
#' @param label_text_font numeric to control the font of text in plot labels,
#'   set to 2 for bold font by default. See \code{\link[graphics:par]{font}} for
#'   alternatives.
#' @param label_text_size numeric to control the size of text in the plot
#'   labels, set to 1 by default.
#' @param label_text_col colour(s) to use for text in plot labels, set to
#'   \code{"black"} by default.
#' @param label_box_x vector of x co-ordinate(s) to manually adjust the position
#'   plot label(s) on the plot.
#' @param label_box_y vector of y co-ordinate(s) to manually adjust the position
#'   plot label(s) on the plot.
#' @param label_box_alpha numeric to control background fill transparency of
#'   label boxes, set to 0.6 by default to introduce some transparency.
#' @param border_line_type integer [0,6] to control the line type of plot
#'   border, set to \code{1} by default for a solid border. See
#'   \code{\link[graphics:par]{lty}} for alternatives.
#' @param border_line_width numeric to control line width for the plot border,
#'   set to 1 by default.
#' @param border_line_col colour to use for the plot border, set to "black" by
#'   default.
#' @param ... additional arguments passed to \code{\link[graphics:plot]{plot}}.
#'
#' @examples
#' library(CytoRSuiteData)
#' 
#' # Load in samples
#' fs <- Activation
#' 
#' # Apply compensation
#' fs <- compensate(fs, fs[[1]]@description$SPILL)
#' 
#' # Transform fluorescent channels
#' trans <- estimateLogicle(fs[[4]], cyto_fluor_channels(fs))
#' fs <- transform(fs, trans)
#' 
#' # 1-D Density Distribution
#' cyto_plot(fs,
#'   channels = c("PE-A"),
#'   axes_trans = trans,
#'   overlay = fs[[1]],
#'   density_stack = 0.4
#' )
#' 
#' # 2-D Scatter Plot with Contour Lines
#' cyto_plot(fs,
#'   channels = c("Alexa Fluor 700-A", "PE-A"),
#'   axes_trans = trans,
#'   contour_lines = 15
#' )
#' @seealso \code{\link{cyto_plot,flowFrame-method}}
#' @seealso \code{\link{cyto_plot,GatingHierarchy-method}}
#' @seealso \code{\link{cyto_plot,GatingSet-method}}
#'
#' @author Dillon Hammill, \email{Dillon.Hammill@anu.edu.au}
#'
#' @export
setMethod(cyto_plot,
  signature = "flowSet",
  definition = function(x,
                          channels,
                          axes_trans = NULL,
                          group_by = FALSE,
                          overlay = NULL,
                          gate = NA,
                          limits = "machine",
                          display = NULL,
                          layout = NULL,
                          popup = FALSE,
                          xlim = NULL,
                          ylim = NULL,
                          title,
                          xlab = NA,
                          ylab = NA,
                          density_modal = TRUE,
                          density_smooth = 1.5,
                          density_stack = 0,
                          density_layers = length(x),
                          density_fill = NA,
                          density_fill_alpha = 1,
                          density_line_type = 1,
                          density_line_width = 1,
                          density_line_col = "black",
                          point_shape = ".",
                          point_size = 2,
                          point_col = NA,
                          point_alpha = 1,
                          contour_lines = 0,
                          contour_line_type = 1,
                          contour_line_width = 1,
                          contour_line_col = "black",
                          axes_text_font = 1,
                          axes_text_size = 1,
                          axes_text_col = "black",
                          axes_label_text_font = 1,
                          axes_label_text_size = 1.1,
                          axes_label_text_col = "black",
                          title_text_font = 2,
                          title_text_size = 1.1,
                          title_text_col = "black",
                          legend = FALSE,
                          legend_text,
                          legend_text_font = 1,
                          legend_text_size = 1,
                          legend_text_col = "black",
                          legend_line_col = NA,
                          legend_box_fill = NA,
                          legend_point_col = NA,
                          gate_line_type = 1,
                          gate_line_width = 2.5,
                          gate_line_col = "red",
                          label = TRUE,
                          label_text = NA,
                          label_stat = "percent",
                          label_text_font = 2,
                          label_text_size = 1,
                          label_text_col = "black",
                          label_box_x = NA,
                          label_box_y = NA,
                          label_box_alpha = 0.6,
                          border_line_type = 1,
                          border_line_width = 1,
                          border_line_col = "black", ...) {

    # Check if channels supplied
    if (missing(channels)) {
      stop("Supply channel/marker(s) to construct the plot.")
    }

    # Assign x to fs
    fs <- x

    # Check channels
    channels <- cyto_channel_check(fs,
      channels = channels,
      plot = TRUE
    )

    # Make call to appropriate cyto_plot function
    if (length(channels) == 1) {
      .cyto_plot_1d(
        x = fs,
        channel = channels,
        axes_trans = axes_trans,
        group_by = group_by,
        overlay = overlay,
        gate = gate,
        limits = limits,
        layout = layout,
        popup = popup,
        xlim = xlim,
        ylim = ylim,
        title = title,
        xlab = xlab,
        ylab = ylab,
        density_modal = density_modal,
        density_smooth = density_smooth,
        density_stack = density_stack,
        density_layers = density_layers,
        density_fill = density_fill,
        density_fill_alpha = density_fill_alpha,
        density_line_type = density_line_type,
        density_line_width = density_line_width,
        density_line_col = density_line_col,
        axes_text_font = axes_text_font,
        axes_text_size = axes_text_size,
        axes_text_col = axes_text_col,
        axes_label_text_font = axes_label_text_font,
        axes_label_text_size = axes_label_text_size,
        axes_label_text_col = axes_label_text_col,
        title_text_font = title_text_font,
        title_text_size = title_text_size,
        title_text_col = title_text_col,
        legend = legend,
        legend_text = legend_text,
        legend_text_font = legend_text_font,
        legend_text_size = legend_text_size,
        legend_text_col = legend_text_col,
        legend_line_col = legend_line_col,
        legend_box_fill = legend_box_fill,
        gate_line_type = gate_line_type,
        gate_line_width = gate_line_width,
        gate_line_col = gate_line_col,
        label = label,
        label_text = label_text,
        label_stat = label_stat,
        label_text_font = label_text_font,
        label_text_size = label_text_size,
        label_text_col = label_text_col,
        label_box_x = label_box_x,
        label_box_y = label_box_y,
        label_box_alpha = label_box_alpha,
        border_line_type = border_line_type,
        border_line_width = border_line_width,
        border_line_col = border_line_col, ...
      )
    } else if (length(channels) == 2) {
      .cyto_plot_2d(
        x = fs,
        channels = channels,
        axes_trans = axes_trans,
        group_by = group_by,
        overlay = overlay,
        gate = gate,
        limits = limits,
        display = display,
        layout = layout,
        popup = popup,
        xlim = xlim,
        ylim = ylim,
        title = title,
        xlab = xlab,
        ylab = ylab,
        point_shape = point_shape,
        point_size = point_size,
        point_col = point_col,
        point_alpha = point_alpha,
        contour_lines = contour_lines,
        contour_line_type = contour_line_type,
        contour_line_width = contour_line_width,
        contour_line_col = contour_line_col,
        axes_text_font = axes_text_font,
        axes_text_size = axes_text_size,
        axes_text_col = axes_text_col,
        axes_label_text_font = axes_label_text_font,
        axes_label_text_size = axes_label_text_size,
        axes_label_text_col = axes_label_text_col,
        title_text_font = title_text_font,
        title_text_size = title_text_size,
        title_text_col = title_text_col,
        legend = legend,
        legend_text = legend_text,
        legend_text_font = legend_text_font,
        legend_text_size = legend_text_size,
        legend_text_col = legend_text_col,
        legend_point_col = legend_point_col,
        gate_line_type = gate_line_type,
        gate_line_width = gate_line_width,
        gate_line_col = gate_line_col,
        label = label,
        label_text = label_text,
        label_stat = label_stat,
        label_text_font = label_text_font,
        label_text_size = label_text_size,
        label_text_col = label_text_col,
        label_box_x = label_box_x,
        label_box_y = label_box_y,
        label_box_alpha = label_box_alpha,
        border_line_type = border_line_type,
        border_line_width = border_line_width,
        border_line_col = border_line_col, ...
      )
    }
  }
)

#' cyto_plot - GatingHierarchy Method
#'
#' Explore & visualise a GatingHierarchy.
#'
#' @param x object of class
#'   \code{\link[flowWorkspace:GatingHierarchy-class]{GatingHierarchy}}.
#' @param parent name of the population to plot.
#' @param alias name of the gated population for which the gate should be drawn
#'   on the plot.
#' @param channels name of the channel(s) or marker(s) to be used to construct
#'   the plot. The length of channels determines the type of plot to be
#'   constructed, either a 1-D density distribution for a single channel or a
#'   2-D scatterplot with blue-red colour scale for two channels.
#' @param axes_trans object of class
#'   \code{\link[flowCore:transformList-class]{transformList}} or
#'   \code{\link[flowWorkspace]{transformerList}} generated by
#'   \code{\link[flowCore:logicleTransform]{estimateLogicle}} which was used to
#'   transform the fluorescent channels of the supplied flowFrame. This
#'   transformation object will be used internally to ensure that the axes
#'   labels of the plot are appropriately transformed. The transformation object
#'   will NOT be applied to the flowFrame internally and should be applied to
#'   the flowFrame prior to plotting.
#' @param overlay name(s) of the populations to overlay or a \code{flowFrame},
#'   \code{flowSet}, \code{list of flowFrames}, \code{list of flowSets} or
#'   \code{list of flowFrame lists} containing populations to be overlaid onto
#'   the plot(s).
#' @param gate gate object(s) to be added to plot.  For \code{cyto_1d_plot} only
#'   gate objects of class
#'   \code{\link[flowCore:rectangleGate-class]{rectangleGate}} in either 1 or 2
#'   dimensions are supported. Multiple gates can be supplied either as a
#'   \code{list} or \code{\link[flowCore:filters-class]{filters}} object.
#' @param limits indicates whether the axes limits should be based on the
#'   \code{"data"} or \code{"machine"}, set to "machine" by default to show
#'   complete axes ranges. This argument will only alter the upper axis limits,
#'   to modify the lower limits use \code{xlim} and \code{ylim}.
#' @param popup logical indicating whether the plot should be constructed in a
#'   pop-up window, set to FALSE by default. \code{popup} will open OS-specific
#'   graphic device prior to plotting. Mac users will need to install
#'   \href{https://www.xquartz.org/}{XQuartz} for this functionality.
#' @param xlim lower and upper limits of x axis (e.g. c(0,5)).
#' @param ylim lower and upper limits of y axis (e.g. c(0,5)).
#' @param title title to use for the plot, set to the name of the sample by
#'   default. Title can be removed by setting this argument to \code{NA}.
#' @param xlab x axis label.
#' @param ylab y axis label.
#' @param density_modal logical indicating whether density should be normalised
#'   to mode and presented as a percentage for 1-D plots. Set to \code{TRUE} by
#'   default.
#' @param density_smooth smoothing parameter passed to
#'   \code{\link[stats:density]{density}} to adjust kernel density for 1-D
#'   plots.
#' @param density_stack numeric [0,1] indicating the degree of offset for 1-D
#'   density distributions with overlay, set to 0.5 by default.
#' @param density_fill fill colour(s) for 1-D density distributions.
#' @param density_fill_alpha numeric [0,1] used to control 1-D density fill
#'   colour transparency, set to 1 by default for solid colours.
#' @param density_line_type line type(s) to use for 1-D density lines, set to 1
#'   by default to use solid lines. See \code{\link[graphics:par]{lty}} for
#'   alternatives.
#' @param density_line_width numeric to control line width(s) for 1-D density
#'   lines, set to 1 by default.
#' @param density_line_col colour(s) for 1-D density lines, set to
#'   \code{"black"} by default.
#' @param point_shape shape(s) to use for points in 2-D scatterplots, set to
#'   \code{"."} by default to maximise plotting speed.  See
#'   \code{\link[graphics:par]{pch}} for alternatives.
#' @param point_size numeric to control the size of points in 2-D scatter plots
#'   set to 2 by default.
#' @param point_col colour(s) to use for points in 2-D scatter plots, set to NA
#'   by default to use a blue-red density colour scale.
#' @param point_alpha numeric [0,1] to control point colour transparency in 2-D
#'   scatter plots, set to 1 by default to use solid colours.
#' @param contour_lines numeric indicating the number of levels to use for
#'   contour lines in 2-D scatter plots, set to 0 by default to turn off contour
#'   lines.
#' @param contour_line_type integer [0,6] to control the line type of contour
#'   lines in 2-D scatter plots, set to \code{1} to draw solid lines by default.
#'   See \code{\link[graphics:par]{lty}} for alternatives.
#' @param contour_line_width numeric to control line width(s) for contour lines
#'   in 2-D scatter plots, set to 2 by default.
#' @param contour_line_col colour(s) to use for contour lines in 2-D scatter
#'   plots, set to \code{"black"} by default.
#' @param axes_text_font numeric to control the font of axes text, set to 1 for
#'   plain font by default. See \code{\link[graphics:par]{font}} for
#'   alternatives.
#' @param axes_text_size numeric to control the size of axes text, set to 1 by
#'   default.
#' @param axes_text_col colour to use for axes text, set to \code{"black"} by
#'   default.
#' @param axes_label_text_font numeric to control the font axes labels, set to 1
#'   for plain font by default. See \code{\link[graphics:par]{font}} for
#'   alternatives.
#' @param axes_label_text_size numeric to control the text size of axes labels,
#'   set to 1.1 by default.
#' @param axes_label_text_col colour to use for axes labels text, set to
#'   \code{"black"} by default.
#' @param title_text_font numeric to control the font of title text, set to 2
#'   for bold font by default. See \code{\link[graphics:par]{font}} for
#'   alternatives.
#' @param title_text_size numeric to control the text size of the plot title,
#'   set to 1.1 by default.
#' @param title_text_col colour to use for plot title text, set to
#'   \code{"black"} by default.
#' @param legend can be either \code{"line"} or \code{"fill"} to indicate
#'   whether a legend should be constructed based on the density \code{"line"}
#'   or \code{"fill"}, set to FALSE by default to remove the legend.
#' @param legend_text vector of labels to use in the legend.
#' @param legend_text_font numeric to control the font of legend text, set to 1
#'   for plain font by default. See \code{\link[graphics:par]{font}} for
#'   alternatives.
#' @param legend_text_size numeric to control the size of text in the legend,
#'   set to 1 by default.
#' @param legend_text_col colour(s) to use for text in legend, set to
#'   \code{"black"} by default.
#' @param legend_line_col colour(s) to use for the lines in 1-D plot legends
#'   when legend is set to \code{"line"}.
#' @param legend_box_fill fill colour(s) to use for the boxes in 1-D plot
#'   legends when legend is set to \code{"fill"}.
#' @param legend_point_col colour(s) to use for points in 2-D scatter plot
#'   legend.
#' @param gate_line_type integer [0,6] to control the line type of gates, set to
#'   \code{1} to draw solid lines by default. See
#'   \code{\link[graphics:par]{lty}} for alternatives.
#' @param gate_line_width numeric to control the line width(s) of gates, set to
#'   \code{2.5} by default.
#' @param gate_line_col colour(s) to use for gates, set to \code{"red"} by
#'   default.
#' @param label logical indicating whether gated populations should be labelled.
#'   To include the names of the populations in these labels, supply the
#'   population names to the \code{label_text} argument. The default statistic
#'   is \code{"percent"} for gated data and \code{"count"} for un-gated data.
#' @param label_text vector of population names to use in the labels. Set to
#'   \code{NA} by default to exclude population names.
#' @param label_stat indicates the type of statistic to include in the plot
#'   labels, can be \code{"percent"}, \code{"count"}, \code{"mean"},
#'   \code{"median"}, \code{"mode"} or \code{"geo mean"}, set to
#'   \code{"percent"} for gated data or \code{NA} to exclude statistics for
#'   un-gated data. Currently, only \code{"percent"} and \code{"count"} are
#'   supported for 2-D scatter plots.
#' @param label_text_font numeric to control the font of text in plot labels,
#'   set to 2 for bold font by default. See \code{\link[graphics:par]{font}} for
#'   alternatives.
#' @param label_text_size numeric to control the size of text in the plot
#'   labels, set to 1 by default.
#' @param label_text_col colour(s) to use for text in plot labels, set to
#'   \code{"black"} by default.
#' @param label_box_x vector of x co-ordinate(s) to manually adjust the position
#'   plot label(s) on the plot.
#' @param label_box_y vector of y co-ordinate(s) to manually adjust the position
#'   plot label(s) on the plot.
#' @param label_box_alpha numeric to control background fill transparency of
#'   label boxes, set to 0.6 by default to introduce some transparency.
#' @param border_line_type integer [0,6] to control the line type of plot
#'   border, set to \code{1} by default for a solid border. See
#'   \code{\link[graphics:par]{lty}} for alternatives.
#' @param border_line_width numeric to control line width for the plot border,
#'   set to 1 by default.
#' @param border_line_col colour to use for the plot border, set to "black" by
#'   default.
#' @param ... additional arguments passed to \code{\link[graphics:plot]{plot}}.
#'
#' @examples
#' library(CytoRSuiteData)
#' 
#' # Load samples into GatingSet
#' fs <- Activation
#' gs <- GatingSet(fs)
#' 
#' # Apply coompensation
#' gs <- compensate(gs, fs[[1]]@description$SPILL)
#' 
#' # Transform fluorescent channels
#' trans <- estimateLogicle(gs[[4]], cyto_fluor_channels(gs))
#' gs <- transform(gs, trans)
#' 
#' # Apply gatingTemplate
#' gt <- Activation_gatingTemplate
#' gating(gt, gs)
#' 
#' # 2-D scatter plot with Overlays & Gate
#' cyto_plot(gs[[4]],
#'   parent = "CD4 T Cells",
#'   alias = "CD69+ CD4 T Cells",
#'   channels = c("Alexa Fluor 647-A", "7-AAD-A"),
#'   overlay = "CD69+ CD4 T Cells",
#' )
#' 
#' # 2-D Scatter plot with Back-Gating & Gates
#' cyto_plot(gs[[4]],
#'   parent = "T Cells",
#'   alias = c("CD4 T Cells", "CD8 T Cells"),
#'   channels = c("Alexa Fluor 488-A", "Alexa Fluor 700-A"),
#'   overlay = c("CD69+ CD4 T Cells", "CD69+ CD8 T Cells")
#' )
#' 
#' # 1-D density distribution
#' cyto_plot(gs[[4]],
#'   parent = "CD4 T Cells",
#'   alias = "CD69+ CD4 T Cells",
#'   channels = "7-AAD-A"
#' )
#' @importFrom flowWorkspace getGate getData sampleNames getTransformations
#'   getNodes
#'
#' @seealso \code{\link{cyto_plot,flowFrame-method}}
#' @seealso \code{\link{cyto_plot,flowSet-method}}
#' @seealso \code{\link{cyto_plot,GatingSet-method}}
#'
#' @author Dillon Hammill, \email{Dillon.Hammill@anu.edu.au}
#'
#' @export
setMethod(cyto_plot,
  signature = "GatingHierarchy",
  definition = function(x,
                          parent,
                          alias = NULL,
                          channels,
                          axes_trans = NULL,
                          overlay = NULL,
                          gate = NA,
                          limits = "machine",
                          popup = FALSE,
                          xlim = NULL,
                          ylim = NULL,
                          title,
                          xlab = NA,
                          ylab = NA,
                          density_modal = TRUE,
                          density_smooth = 1.5,
                          density_stack = 0,
                          density_fill = NA,
                          density_fill_alpha = 1,
                          density_line_type = 1,
                          density_line_width = 1,
                          density_line_col = "black",
                          point_shape = ".",
                          point_size = 2,
                          point_col = NA,
                          point_alpha = 1,
                          contour_lines = 0,
                          contour_line_type = 1,
                          contour_line_width = 1,
                          contour_line_col = "black",
                          axes_text_font = 1,
                          axes_text_size = 1,
                          axes_text_col = "black",
                          axes_label_text_font = 1,
                          axes_label_text_size = 1.1,
                          axes_label_text_col = "black",
                          title_text_font = 2,
                          title_text_size = 1.1,
                          title_text_col = "black",
                          legend = FALSE,
                          legend_text,
                          legend_text_font = 1,
                          legend_text_size = 1,
                          legend_text_col = "black",
                          legend_line_col = NA,
                          legend_box_fill = NA,
                          legend_point_col = NA,
                          gate_line_type = 1,
                          gate_line_width = 2.5,
                          gate_line_col = "red",
                          label = TRUE,
                          label_text = NA,
                          label_stat = "percent",
                          label_text_font = 2,
                          label_text_size = 1,
                          label_text_col = "black",
                          label_box_x = NA,
                          label_box_y = NA,
                          label_box_alpha = 0.6,
                          border_line_type = 1,
                          border_line_width = 1,
                          border_line_col = "black", ...) {

    # No Parent Supplied
    if (missing(parent)) {
      stop("Please supply the name of the parent population to plot.")
    }

    # Check if channels supplied
    if (missing(channels)) {
      stop("Supply channel/marker(s) to construct the plot.")
    }

    # Assign x to gh
    gh <- x

    # Check channels
    channels <- cyto_channel_check(
      x = getData(gh, "root"),
      channels,
      plot = TRUE
    )

    # Check supplied alias exists in GatingSHierarchy
    if (!is.null(alias)) {
      if (!all(alias %in% basename(getNodes(gh)))) {
        stop("Supplied alias does not exist in the GatingHierarchy")
      }
    }

    # Gates - either alias or gate not both
    if (!.valid_gates(gate, channels)) {
      if (!is.null(alias)) {
        gate <- lapply(alias, function(pop) getGate(gh, pop))
        names(gate) <- alias
      }
    }

    # Transform axes
    if (is.null(axes_trans)) {

      # Some transforms found - replace these entries in trans object
      trnsfrms <- lapply(channels, function(channel) {
        getTransformations(gh, channel, only.function = FALSE)
      })
      names(trnsfrms) <- channels

      # Remove NULL transforms
      trnsfrms[unlist(lapply(trnsfrms, "is.null"))] <- NULL

      if (length(trnsfrms) == 0) {
        axes_trans <- NULL
      } else {
        axes_trans <- transformerList(names(trnsfrms), trnsfrms)
      }

      axes_trans <- cyto_trans_check(trans = axes_trans, inverse = FALSE)
    } else {
      axes_trans <- cyto_trans_check(trans = axes_trans, inverse = FALSE)
    }

    # Text for labels
    if (all(is.na(label_text)) & !missing(alias)) {
      label_text <- alias
    }

    # Extract population from GatingHierarchy
    fr <- getData(gh, parent)

    # Titles
    if (missing(title)) {
      if (!is.null(overlay)) {
        title <- NA
      } else {
        if (parent == "root") {
          parent <- "All Events"
        }

        title <- paste(sampleNames(gh), "\n", parent)
      }
    }

    # Legend Text
    if (!is.null(overlay)) {
      if (class(overlay) == "character") {
        if (missing(legend_text)) {
          legend_text <- c(parent, overlay)
        }
      }
    }

    # Overlay
    if (!is.null(overlay)) {

      # Extract populations to overlay - list of flowSets
      if (class(overlay) == "character") {
        overlay <- lapply(overlay, function(overlay) {
          getData(gh, overlay)
        })
      }
    }

    # Make call to cyto_plot
    cyto_plot(
      x = fr,
      channels = channels,
      axes_trans = axes_trans,
      overlay = overlay,
      gate = gate,
      limits = limits,
      popup = popup,
      xlim = xlim,
      ylim = ylim,
      title = title,
      xlab = xlab,
      ylab = ylab,
      density_modal = density_modal,
      density_smooth = density_smooth,
      density_stack = density_stack,
      density_fill = density_fill,
      density_fill_alpha = density_fill_alpha,
      density_line_type = density_line_type,
      density_line_width = density_line_width,
      density_line_col = density_line_col,
      point_shape = point_shape,
      point_size = point_size,
      point_col = point_col,
      point_alpha = point_alpha,
      contour_lines = contour_lines,
      contour_line_type = contour_line_type,
      contour_line_width = contour_line_width,
      contour_line_col = contour_line_col,
      axes_text_font = axes_text_font,
      axes_text_size = axes_text_size,
      axes_text_col = axes_text_col,
      axes_label_text_font = axes_label_text_font,
      axes_label_text_size = axes_label_text_size,
      axes_label_text_col = axes_label_text_col,
      title_text_font = title_text_font,
      title_text_size = title_text_size,
      title_text_col = title_text_col,
      legend = legend,
      legend_text = legend_text,
      legend_text_font = legend_text_font,
      legend_text_size = legend_text_size,
      legend_text_col = legend_text_col,
      legend_line_col = legend_line_col,
      legend_box_fill = legend_box_fill,
      legend_point_col = legend_point_col,
      gate_line_type = gate_line_type,
      gate_line_width = gate_line_width,
      gate_line_col = gate_line_col,
      label = label,
      label_text = label_text,
      label_stat = label_stat,
      label_text_font = label_text_font,
      label_text_size = label_text_size,
      label_text_col = label_text_col,
      label_box_x = label_box_x,
      label_box_y = label_box_y,
      label_box_alpha = label_box_alpha,
      border_line_type = border_line_type,
      border_line_width = border_line_width,
      border_line_col = border_line_col, ...
    )
  }
)

#' cyto_plot - GatingSet Method
#'
#' Explore & visualise a GatingSet.
#'
#' @param x object of class
#'   \code{\link[flowWorkspace:GatingSet-class]{GatingSet}}.
#' @param parent name of the population containing the events to plot.
#' @param alias name of the gated population for which the gate should be drawn
#'   on the plot.
#' @param channels name of the channel(s) or marker(s) to be used to construct
#'   the plot. The length of channels determines the type of plot to be
#'   constructed, either a 1-D density distribution for a single channel or a
#'   2-D scatterplot with blue-red colour scale for two channels.
#' @param axes_trans object of class
#'   \code{\link[flowCore:transformList-class]{transformList}} or
#'   \code{\link[flowWorkspace]{transformerList}} generated by
#'   \code{\link[flowCore:logicleTransform]{estimateLogicle}} which was used to
#'   transform the fluorescent channels of the supplied flowFrame. This
#'   transformation object will be used internally to ensure that the axes
#'   labels of the plot are appropriately transformed. The transformation object
#'   will NOT be applied to the flowFrame internally and should be applied to
#'   the flowFrame prior to plotting.
#' @param group_by a vector of pData variables to sort and merge samples into
#'   groups prior to plotting, set to NULL by default to prevent merging. To
#'   merge all samples set this argument to \code{TRUE} or \code{"all"}.
#' @param overlay name(s) of the populations to overlay or a \code{flowFrame},
#'   \code{flowSet}, \code{list of flowFrames}, \code{list of flowSets} or
#'   \code{list of flowFrame lists} containing populations to be overlaid onto
#'   the plot(s).
#' @param gate gate object(s) to be added to plot.  For \code{cyto_1d_plot} only
#'   gate objects of class
#'   \code{\link[flowCore:rectangleGate-class]{rectangleGate}} in either 1 or 2
#'   dimensions are supported. Multiple gates can be supplied either as a
#'   \code{list} or \code{\link[flowCore:filters-class]{filters}} object.
#' @param limits indicates whether the axes limits should be based on the
#'   \code{"data"} or \code{"machine"}, set to "machine" by default to show
#'   complete axes ranges. This argument will only alter the upper axis limits,
#'   to modify the lower limits use \code{xlim} and \code{ylim}.
#' @param display numeric [0,1] to control the percentage of events to be
#'   plotted. Specifying a value for \code{display} can substantial improve
#'   plotting speed for less powerful machines.
#' @param layout a vector of the length 2 indicating the dimensions of the grid
#'   for plotting \code{c(#rows, #columns)}.
#' @param popup logical indicating whether the plot should be constructed in a
#'   pop-up window, set to FALSE by default. \code{popup} will open OS-specific
#'   graphic device prior to plotting. Mac users will need to install
#'   \href{https://www.xquartz.org/}{XQuartz} for this functionality.
#' @param xlim lower and upper limits of x axis (e.g. c(0,5)).
#' @param ylim lower and upper limits of y axis (e.g. c(0,5)).
#' @param title title to use for the plot, set to the name of the sample by
#'   default. Title can be removed by setting this argument to \code{NA}.
#' @param xlab x axis label.
#' @param ylab y axis label.
#' @param density_modal logical indicating whether density should be normalised
#'   to mode and presented as a percentage for 1-D plots. Set to \code{TRUE} by
#'   default.
#' @param density_smooth smoothing parameter passed to
#'   \code{\link[stats:density]{density}} to adjust kernel density for 1-D
#'   plots.
#' @param density_stack numeric [0,1] indicating the degree of offset for 1-D
#'   density distributions with overlay, set to 0.5 by default.
#' @param density_layers numeric indicating the number of samples to stack in
#'   each plot, set to all samples by default.
#' @param density_fill fill colour(s) for 1-D density distributions.
#' @param density_fill_alpha numeric [0,1] used to control 1-D density fill
#'   colour transparency, set to 1 by default for solid colours.
#' @param density_line_type line type(s) to use for 1-D density lines, set to 1
#'   by default to use solid lines. See \code{\link[graphics:par]{lty}} for
#'   alternatives.
#' @param density_line_width numeric to control line width(s) for 1-D density
#'   lines, set to 1 by default.
#' @param density_line_col colour(s) for 1-D density lines, set to
#'   \code{"black"} by default.
#' @param point_shape shape(s) to use for points in 2-D scatterplots, set to
#'   \code{"."} by default to maximise plotting speed.  See
#'   \code{\link[graphics:par]{pch}} for alternatives.
#' @param point_size numeric to control the size of points in 2-D scatter plots
#'   set to 2 by default.
#' @param point_col colour(s) to use for points in 2-D scatter plots, set to NA
#'   by default to use a blue-red density colour scale.
#' @param point_alpha numeric [0,1] to control point colour transparency in 2-D
#'   scatter plots, set to 1 by default to use solid colours.
#' @param contour_lines numeric indicating the number of levels to use for
#'   contour lines in 2-D scatter plots, set to 0 by default to turn off contour
#'   lines.
#' @param contour_line_type integer [0,6] to control the line type of contour
#'   lines in 2-D scatter plots, set to \code{1} to draw solid lines by default.
#'   See \code{\link[graphics:par]{lty}} for alternatives.
#' @param contour_line_width numeric to control line width(s) for contour lines
#'   in 2-D scatter plots, set to 2 by default.
#' @param contour_line_col colour(s) to use for contour lines in 2-D scatter
#'   plots, set to \code{"black"} by default.
#' @param axes_text_font numeric to control the font of axes text, set to 1 for
#'   plain font by default. See \code{\link[graphics:par]{font}} for
#'   alternatives.
#' @param axes_text_size numeric to control the size of axes text, set to 1 by
#'   default.
#' @param axes_text_col colour to use for axes text, set to \code{"black"} by
#'   default.
#' @param axes_label_text_font numeric to control the font axes labels, set to 1
#'   for plain font by default. See \code{\link[graphics:par]{font}} for
#'   alternatives.
#' @param axes_label_text_size numeric to control the text size of axes labels,
#'   set to 1.1 by default.
#' @param axes_label_text_col colour to use for axes labels text, set to
#'   \code{"black"} by default.
#' @param title_text_font numeric to control the font of title text, set to 2
#'   for bold font by default. See \code{\link[graphics:par]{font}} for
#'   alternatives.
#' @param title_text_size numeric to control the text size of the plot title,
#'   set to 1.1 by default.
#' @param title_text_col colour to use for plot title text, set to
#'   \code{"black"} by default.
#' @param legend can be either \code{"line"} or \code{"fill"} to indicate
#'   whether a legend should be constructed based on the density \code{"line"}
#'   or \code{"fill"}, set to FALSE by default to remove the legend.
#' @param legend_text vector of labels to use in the legend.
#' @param legend_text_font numeric to control the font of legend text, set to 1
#'   for plain font by default. See \code{\link[graphics:par]{font}} for
#'   alternatives.
#' @param legend_text_size numeric to control the size of text in the legend,
#'   set to 1 by default.
#' @param legend_text_col colour(s) to use for text in legend, set to
#'   \code{"black"} by default.
#' @param legend_line_col colour(s) to use for the lines in 1-D plot legends
#'   when legend is set to \code{"line"}.
#' @param legend_box_fill fill colour(s) to use for the boxes in 1-D plot
#'   legends when legend is set to \code{"fill"}.
#' @param legend_point_col colour(s) to use for points in 2-D scatter plot
#'   legend.
#' @param gate_line_type integer [0,6] to control the line type of gates, set to
#'   \code{1} to draw solid lines by default. See
#'   \code{\link[graphics:par]{lty}} for alternatives.
#' @param gate_line_width numeric to control the line width(s) of gates, set to
#'   \code{2.5} by default.
#' @param gate_line_col colour(s) to use for gates, set to \code{"red"} by
#'   default.
#' @param label logical indicating whether gated populations should be labelled.
#'   To include the names of the populations in these labels, supply the
#'   population names to the \code{label_text} argument. The default statistic
#'   is \code{"percent"} for gated data and \code{"count"} for un-gated data.
#' @param label_text vector of population names to use in the labels. Set to
#'   \code{NA} by default to exclude population names.
#' @param label_stat indicates the type of statistic to include in the plot
#'   labels, can be \code{"percent"}, \code{"count"}, \code{"mean"},
#'   \code{"median"}, \code{"mode"} or \code{"geo mean"}, set to
#'   \code{"percent"} for gated data or \code{NA} to exclude statistics for
#'   un-gated data. Currently, only \code{"percent"} and \code{"count"} are
#'   supported for 2-D scatter plots.
#' @param label_text_font numeric to control the font of text in plot labels,
#'   set to 2 for bold font by default. See \code{\link[graphics:par]{font}} for
#'   alternatives.
#' @param label_text_size numeric to control the size of text in the plot
#'   labels, set to 1 by default.
#' @param label_text_col colour(s) to use for text in plot labels, set to
#'   \code{"black"} by default.
#' @param label_box_x vector of x co-ordinate(s) to manually adjust the position
#'   plot label(s) on the plot.
#' @param label_box_y vector of y co-ordinate(s) to manually adjust the position
#'   plot label(s) on the plot.
#' @param label_box_alpha numeric to control background fill transparency of
#'   label boxes, set to 0.6 by default to introduce some transparency.
#' @param border_line_type integer [0,6] to control the line type of plot
#'   border, set to \code{1} by default for a solid border. See
#'   \code{\link[graphics:par]{lty}} for alternatives.
#' @param border_line_width numeric to control line width for the plot border,
#'   set to 1 by default.
#' @param border_line_col colour to use for the plot border, set to "black" by
#'   default.
#' @param ... additional arguments passed to \code{\link[graphics:plot]{plot}}.
#'
#' @examples
#' library(CytoRSuiteData)
#' 
#' # Load samples into GatingSet
#' fs <- Activation
#' gs <- GatingSet(fs)
#' 
#' # Apply coompensation
#' gs <- compensate(gs, fs[[1]]@description$SPILL)
#' 
#' # Transform fluorescent channels
#' trans <- estimateLogicle(gs[[4]], cyto_fluor_channels(gs))
#' gs <- transform(gs, trans)
#' 
#' # Apply gatingTemplate
#' gt <- Activation_gatingTemplate
#' gating(gt, gs)
#' 
#' # 2-D scatter plot with overlay & Gates
#' cyto_plot(gs,
#'   parent = "CD4 T Cells",
#'   alias = "CD69+ CD4 T Cells",
#'   channels = c("Alexa Fluor 647-A", "7-AAD-A"),
#'   overlay = "CD8 T Cells"
#' )
#' 
#' # 2-D Scatter Plots with Back-Gating & Gates
#' cyto_plot(gs,
#'   parent = "T Cells",
#'   alias = c("CD4 T Cells", "CD8 T Cells"),
#'   channels = c("Alexa Fluor 488-A", "Alexa Fluor 700-A"),
#'   overlay = c("CD69+ CD4 T Cells", "CD69+ CD8 T Cells")
#' )
#' @importFrom flowWorkspace getGate getData sampleNames getTransformations
#'   sampleNames pData getNodes
#' @importFrom flowCore flowSet
#'
#' @seealso \code{\link{cyto_plot,flowFrame-method}}
#' @seealso \code{\link{cyto_plot,flowSet-method}}
#' @seealso \code{\link{cyto_plot,GatingHierarchy-method}}
#'
#' @author Dillon Hammill, \email{Dillon.Hammill@anu.edu.au}
#'
#' @export
setMethod(cyto_plot,
  signature = "GatingSet",
  definition = function(x,
                          parent,
                          alias = NULL,
                          channels,
                          axes_trans = NULL,
                          group_by = FALSE,
                          overlay = NULL,
                          gate = NA,
                          limits = "machine",
                          display = NULL,
                          layout = NULL,
                          popup = FALSE,
                          xlim = NULL,
                          ylim = NULL,
                          title,
                          xlab = NA,
                          ylab = NA,
                          density_modal = TRUE,
                          density_smooth = 1.5,
                          density_stack = 0,
                          density_layers = length(x),
                          density_fill = NA,
                          density_fill_alpha = 1,
                          density_line_type = 1,
                          density_line_width = 1,
                          density_line_col = "black",
                          point_shape = ".",
                          point_size = 2,
                          point_col = NA,
                          point_alpha = 1,
                          contour_lines = 0,
                          contour_line_type = 1,
                          contour_line_width = 1,
                          contour_line_col = "black",
                          axes_text_font = 1,
                          axes_text_size = 1,
                          axes_text_col = "black",
                          axes_label_text_font = 1,
                          axes_label_text_size = 1.1,
                          axes_label_text_col = "black",
                          title_text_font = 2,
                          title_text_size = 1.1,
                          title_text_col = "black",
                          legend = FALSE,
                          legend_text,
                          legend_text_font = 1,
                          legend_text_size = 1,
                          legend_text_col = "black",
                          legend_line_col = NA,
                          legend_box_fill = NA,
                          legend_point_col = NA,
                          gate_line_type = 1,
                          gate_line_width = 2.5,
                          gate_line_col = "red",
                          label = TRUE,
                          label_text = NA,
                          label_stat = "percent",
                          label_text_font = 2,
                          label_text_size = 1,
                          label_text_col = "black",
                          label_box_x = NA,
                          label_box_y = NA,
                          label_box_alpha = 0.6,
                          border_line_type = 1,
                          border_line_width = 1,
                          border_line_col = "black", ...) {

    # No Parent Supplied
    if (missing(parent)) {
      stop("Please supply the name of the parent population to plot.")
    }

    # Check if channels supplied
    if (missing(channels)) {
      stop("Supply channel/marker(s) to construct the plot.")
    }

    # Check channels
    channels <- cyto_channel_check(x, channels, plot = TRUE)

    # Check supplied alias exists in GatingSet
    if (!missing(alias)) {
      if (!all(alias %in% basename(getNodes(x)))) {
        stop("Supplied alias does not exist in the GatingSet.")
      }
    }

    # Assign x to gs
    gs <- x
    smp <- length(gs)

    # Extract pData info
    pd <- pData(gs)

    # Transformation object
    if (is.null(axes_trans)) {

      # Some transforms found - replace these entries in transList
      trnsfrms <- lapply(channels, function(channel) {
        getTransformations(gs[[1]], channel, only.function = FALSE)
      })
      names(trnsfrms) <- channels

      # Remove NULL transforms
      trnsfrms[unlist(lapply(trnsfrms, "is.null"))] <- NULL

      if (length(trnsfrms) == 0) {
        axes_trans <- NULL
      } else {
        axes_trans <- transformerList(names(trnsfrms), trnsfrms)
      }

      axes_trans <- cyto_trans_check(trans = axes_trans, inverse = FALSE)
    } else {
      axes_trans <- cyto_trans_check(trans = axes_trans, inverse = FALSE)
    }

    # Labels
    if (all(is.na(label_text)) & !is.null(alias)) {
      label_text <- alias
    }

    # Legend Text
    if (!is.null(overlay)) {
      if (class(overlay) == "character") {
        if (missing(legend_text)) {
          legend_text <- c(parent, overlay)
        }
      }
    }

    # group_by
    if (group_by[1] == TRUE) {
      group_by <- "all"
    }

    # group_by?
    if (group_by[1] != FALSE) {

      # check group_by
      if (all(!group_by %in% c("all", colnames(pData(gs))))) {
        stop("group_by should be the name of pData variables or 'all'.")
      }

      # Add group_by column to pd - to get gates
      if (length(group_by) == 1) {
        if (group_by == "all") {
          pd$group_by <- rep("all", length(gs))
        } else {
          pd$group_by <- pd[, group_by]
        }
      } else {
        pd$group_by <- do.call("paste", pd[, group_by])
      }

      # Extract data
      fs <- getData(gs, parent)

      # Sampling happens in cyto_plot flowSet method
      fr.lst <- .cyto_merge(gs,
        parent = parent,
        group_by = group_by,
        display = NULL
      )

      # Merged names
      nms <- names(fr.lst)

      # Overlay - sampling happens in cyto_plot flowSet method
      if (!is.null(overlay)) {
        overlay <- .cyto_overlay_check(
          x = gs,
          overlay = overlay,
          display = NULL
        )
        overlay <- .cyto_overlay_merge(
          x = gs,
          overlay = overlay,
          group_by = group_by,
          display = NULL
        )
      }

      # Convert merged flowFrame list to flowSet
      fs <- flowSet(fr.lst)

      # Gates - either alias or gate not both
      if (!.valid_gates(gate, channels)) {
        if (!is.null(alias)) {
          gate <- lapply(nms, function(nm) {
            gt <- lapply(alias, function(x) {
              getGate(gs[[match(nm, pd$group_by)]], x)
            })
            names(gt) <- alias
            return(gt)
          })
        }
      }

      # Plot titles
      if (missing(title)) {
        if (parent == "root") {
          prnt <- "All Events"
        } else {
          prnt <- parent
        }

        title <- nms
        title <- lapply(title, function(x) {
          if (x == "all") {
            x <- "Combined Events"
          }

          paste(x, "\n", prnt, sep = " ")
        })
      }

      # Labels text
      if (all(is.na(label_text)) & !is.null(alias)) {
        label_text <- alias
      }
    } else if (group_by[1] == FALSE) {

      # Extract population
      fs <- getData(gs, parent)

      # Plot titles
      if (missing(title)) {
        title <- unlist(lapply(seq_along(gs), function(gh) {
          if (parent == "root") {
            parent <- "All Events"
          }

          paste(sampleNames(gs)[gh], "\n", parent)
        }))

        if (length(channels) == 1 & density_stack != 0) {
          title <- parent
        }
      }

      # Legend Text
      if (!is.null(overlay)) {
        if (class(overlay) == "character") {

          # Sampling happens in cyto_plot flowSet method
          overlay <- .cyto_overlay_check(
            x = gs,
            overlay = overlay,
            display = NULL
          )

          if (missing(legend_text)) {
            legend_text <- c(parent, overlay)
          }
        }
      }

      # Label text
      if (all(is.na(label_text)) & !is.null(alias)) {
        label_text <- alias
      }

      # Extract gates
      if (!is.null(alias)) {
        gate <- lapply(seq_len(length(gs)), function(x) {
          gt <- lapply(alias, function(y) {
            getGate(gs[[x]], y)
          })
          names(gt) <- alias
          return(gt)
        })
      }
    }

    # Make call to cyto_plot
    cyto_plot(
      x = fs,
      channels = channels,
      axes_trans = axes_trans,
      group_by = FALSE,
      overlay = overlay,
      gate = gate,
      limits = limits,
      display = display,
      layout = layout,
      popup = popup,
      xlim = xlim,
      ylim = ylim,
      title = title,
      xlab = xlab,
      ylab = ylab,
      density_modal = density_modal,
      density_smooth = density_smooth,
      density_stack = density_stack,
      density_layers = density_layers,
      density_fill = density_fill,
      density_fill_alpha = density_fill_alpha,
      density_line_type = density_line_type,
      density_line_width = density_line_width,
      density_line_col = density_line_col,
      point_shape = point_shape,
      point_size = point_size,
      point_col = point_col,
      point_alpha = point_alpha,
      contour_lines = contour_lines,
      contour_line_type = contour_line_type,
      contour_line_width = contour_line_width,
      contour_line_col = contour_line_col,
      axes_text_font = axes_text_font,
      axes_text_size = axes_text_size,
      axes_text_col = axes_text_col,
      axes_label_text_font = axes_label_text_font,
      axes_label_text_size = axes_label_text_size,
      axes_label_text_col = axes_label_text_col,
      title_text_font = title_text_font,
      title_text_size = title_text_size,
      title_text_col = title_text_col,
      legend = legend,
      legend_text = legend_text,
      legend_text_font = legend_text_font,
      legend_text_size = legend_text_size,
      legend_text_col = legend_text_col,
      legend_line_col = legend_line_col,
      legend_box_fill = legend_box_fill,
      legend_point_col = legend_point_col,
      gate_line_type = gate_line_type,
      gate_line_width = gate_line_width,
      gate_line_col = gate_line_col,
      label = label,
      label_text = label_text,
      label_stat = label_stat,
      label_text_font = label_text_font,
      label_text_size = label_text_size,
      label_text_col = label_text_col,
      label_box_x = label_box_x,
      label_box_y = label_box_y,
      label_box_alpha = label_box_alpha,
      border_line_type = border_line_type,
      border_line_width = border_line_width,
      border_line_col = border_line_col, ...
    )
  }
)
DillonHammill/cytoSuite documentation built on March 7, 2019, 10:09 a.m.