OpenPBTA-analysis

Figures

This directory contains the code required to generate individual panels for main and supplemental display items. It is designed such that a single shell script will run all required data processing or analysis steps prior to plotting. There are two main strategies for creating individual panels: 1. scripts that are exclusively created for publication-ready display (located in figures/scripts) or 2. copying publication-ready plots that are generated within a given analysis module (i.e., analyses) to the correct location in figures/.

Table of Contents generated with DocToc

Running the figure generation script

Follow these steps to refresh all publication-ready figures. All steps assume your current directory is the top of this repository.

1. Obtain the current dataset.

See these instructions to obtain the current data release. We recommend using the download script to obtain data because this will automatically create symlinks in data/ to the latest files.

2. Set up an up-to-date project Docker container.

See these instructions for setting up the project Docker container. Briefly, the latest version of the project Docker image, which is updated upon commit to master, can be obtained and run via:

docker pull ccdlopenpbta/open-pbta:latest
docker run \
  -e PASSWORD=<password> \
  -p 8787:8787 \
  -v $(pwd):/home/rstudio/kitematic \
  ccdlopenpbta/open-pbta:latest

You may choose to use docker exec to interact with the container from there or if you’d prefer the RStudio interface, you can navigate to localhost:8787 and enter username rstudio and the password you set with the run command above.

3. Ensure that required analyses are up-to-date.

⚠️ This requires 64GB of RAM to run successfully! You can set RUN_LOCAL=1 for local testing that skips the RAM-intensive steps.

In order to generate figures, analysis modules should contain up-to-date results for the given data release. All analyses that are included in the manuscript can be run with:

bash ../scripts/run-manuscript-analyses.sh

Because some of those analyses have significant memory requirements which are generally not available on local machines, you may wish to only run analyses that can be locally processed. For this option, set RUN_LOCAL=1:

RUN_LOCAL=1 bash ../scripts/run-manuscript-analyses.sh

4. Run the bash script that generates the figures.

⚠️ This requires 64GB of RAM to run successfully! You can set RUN_LOCAL=1 for local testing that skips the RAM-intensive steps.

The script generate-figures.sh runs all scripts in figures/scripts/ to generate manuscript-ready figure panels, as well as copies certain panels from analyses that are meant for the manuscript. This script will also specifically check for the presence of necessary scratch/ directory input files, which should have been generated with ../scripts/run-manuscript-analyses.sh before running this script. If necessary scratch/ files are missing, this script will error out; if necessary scratch/ files are older than 10 days, a warning will be printed that files may be out of date. No further checks are performed. Resulting figure panels are all saved as PDF files in figures/pdfs/, as is described here. Generate all figure panels via:

bash ./generate-figures.sh

Again, to run only analyses that do not have signficant memory requirements, set the flag RUN_LOCAL=1:

RUN_LOCAL=1 bash ./generate-figures.sh

In some cases, the shell script will copy plots to the appropriate locations in the figures/ directory.

Adding or updating figures

All figures need to adhere to the guidelines in this README and need to be generated, including any upstream steps, via figures/generate-figures.sh. This section includes details for file organization and guidelines that are not covered in the section on style.

Individual panels and where to find them

Individual panels, including any standalone legends, intended for the main text should be saved as PDFs in figures/pdfs/<figure>/panels. Each figure has its own subdirectory within figures/pdfs; individual panels for Figure 1 would be saved in figures/pdfs/fig1/panels, for Figure 2 in figures/pdfs/fig2/panels and so on and so forth.

Similarly, panels and standalone legends intended for the supplementary materials should be saved as PDFs in figures/pdfs/supp/<figure>/panels. As for main text figures, individual panels for Figure S1 would be saved in figures/pdfs/supp/figs1/panels, and so on.

Compiled multipanel figures

Multipanel figures are compiled with either Adobe Illustrator or the Graphic for Mac application and saved as PDFs in their respective subdirectories. For example, the compiled, PDF version of Figure 1 is saved as figures/pdf/fig1/figure1.pdf. Similarly for supplementary figures, the compiled PDF version of Figure S1 is saved as figures/pdf/supp/figs1/figureS1.pdf. (Original .ai Illustrator and/or .idraw Graphic files are available in Google Drive and can be shared as necessary – contact @jaclyn-taroni!)

PNG versions of figures are exported using the PDF file and saved to the figures/pngs/ folder. PNGs version can be linked in the accompanying manuscript repository AlexsLemonade/OpenPBTA-manuscript.

Documenting individual figures & scripts

Each figure should include its own associated README in the appropriate PDF subdirectory, e.g., the documentation for Figure 4 can be found in figures/pdfs/fig4/README.md. That README should detail what analysis modules or individual scripts are required to generate the individual panels for that figure.

Scripts that are exclusively for creating publication-ready plots, both main text and supplementary, are available in figures/scripts and should be documented in the figures/scripts/README.md. Scripts should generally begin with which figure(s) they are generating panels for, e.g. a script whose name begins with fig4- makes one or more panels for Figure 4, and a script whose name begins with fig5_figS6 makes one or more panels for both Figures 5 and S6.

Figure Guidelines

Color Palettes

This project has a set of unified color palettes. There are 6 sets of hex color keys to be used for all final figures, stored as 6 TSV files in the figures/palettes folder. hex_codes contains the colors to be passed to your plotting code and color_names contains short descriptors of each color (e.g. gradient_1, or divergent_neutral).

Palettes for numeric or binary data contain an na_color that is uniform across palettes. This color should be used for all NA values. na_color is always the last value in the palette. If na_color is not needed or is supplied separately to a plotting function, you can use a dplyr::filter(hex_code != "na_color") to remove na_color.

To see a summary of what colors are used for histology labeling, see mapping-histology-labels.nb.html

Palette File Name Color Notes Variable application
gradient_col_palette.tsv 10 hex_codes where gradient_0 is for an absolute 0 but may need to be removed from the palette depending on the application For numeric data being plotted e.g., tumor mutation burden
divergent_col_palette.tsv 12 hex codes where the numbers in the name indicate distance from divergent_neutral. For data has that is bidirectional e.g., Amplification/Deletion values like seg.mean
binary_col_palette.tsv A vector of two hex codes For binary variables e.g., presence/absence or Amp/Del as statuses
oncoprint_color_palette.tsv A named vector of hex codes assigned to each short_histology and to each CNV, SNV and Fusion category For plotting an oncoprint figure, this vector provides hex codes for specific alterations
tumor_descriptor_palette.tsv A named vector of hex codes assigned to each tumor_descriptor For plotting sample distributions, this vector provides color for tumor descriptor categories
broad_histology_cancer_group_palette.tsv Contains multiple columns having to do with the display by disease label (i.e., broad_histology or cancer_group) To be used for any plots that require coloring by broad_histology or cancer_group; please see figures/mapping-histology-labels.Rmd for more information

⚠️ histology_label_color_table.tsv is a deprecated version of the palettes used for broad_histology and cancer_group. It has been retained, for the moment, to prevent the introduction of breaking changes to multiple analysis modules. It is not to be used for any future development and the relationships between individual biospecimens and disease labels may be out of date.

Updating color palettes

The non-histologies color palette TSV files are created by running scripts/color_palettes.R, which can be called by Rscript scripts/color_palettes.R. Hex codes for the palettes are hard-coded in this script. Do not manually edit palette TSV files. The script can be called from anywhere in this repository (will look for the .git file). The hex codes table in figures/README.md and its swatches should also be updated by using the swatches_table function at the end of the script and copy and pasting this function’s output to the appropriate place in the table.

The histology color palette file is created by running Rscript -e "rmarkdown::render('figures/mapping-histology-labels.Rmd', clean = TRUE)".

Examples palette usage in R

Example 1) Color coding by disease label in ggplot2

Step 1) Read in color palette file and create a named vector of hex codes

Here’s an example for cancer_group, specifically:

# Get palette for cancer group
cancer_group_palette <- readr::read_tsv(
  "figures/palettes/broad_histology_cancer_group_palette.tsv")
) %>%
  dplyr::select(cancer_group, cancer_group_hex) %>%
  # Remove NA values -- a cancer group hex value will be NA only if the
  # cancer group is NA
  dplyr::filter(complete.cases(.))

# Make color palette suitable for use with ggplot
annotation_colors <- cancer_group_palette$cancer_group_hex
names(annotation_colors) <- cancer_group_palette$cancer_group

Step 2) Make your ggplot using the named vector as a manual palette

You will be able to use the named vector with ggplot2 functions such as scale_fill_manual() or scale_color_manual(), like so:

ggplot2::ggplot(
  ggplot2::aes(x = cancer_group,
               y = y_value,
               fill = cancer_group)
) +
  geom_boxplot() +
  scale_fill_manual(values = annotation_colors)
Example 2) Color coding by numeric data

Step 1) Import the palette.

You may want to remove the na_color at the end of the list depending on whether your data include NAs or if the plotting function you are using has the na_color supplied separately.

gradient_col_palette <- readr::read_tsv(
  file.path(figures_dir, "palettes", "gradient_color_palette.tsv")
)

If we need the NA color separated, like for use with ComplexHeatmap which has a separate argument for the color for NA values.

na_color <- gradient_col_palette %>%
  dplyr::filter(color_names == "na_color")

gradient_col_palette <- gradient_col_palette %>%
  dplyr::filter(color_names != "na_color")

Step 2) Make a color function.

In this example, we are building a colorRamp2 function based on a regular interval between the minimum and maximum of our variable df$variable by using seq. However, depending on your data’s distribution a regular interval based palette might not represent your data well on the plot. You can provide any numeric vector to color code a palette using circlize::colorRamp2 as long as that numeric vector is the same length as the palette itself.

gradient_col_val <- seq(from = min(df$variable), to = max(df$variable),
                        length.out = nrow(gradient_col_palette))

col_fun <- circlize::colorRamp2(gradient_col_val,
                                gradient_col_palette$hex_codes)

Step 3) Apply to numeric data, or supply to your plotting code.

This step depends on how your main plotting function would like the data supplied. For example, ComplexHeatmap wants a function to be supplied to their col argument.

# Apply to variable directly and make a new column
df <- df %>%
  dplyr::mutate(color_key = col_fun(variable))

## OR ##

# Some plotting packages want a color function

ComplexHeatmap::Heatmap(
  df,
  col = col_fun,
  na_col = na_color$hex_codes
)

Overall figure theme

In general, we will use the ggpubr package with ggtheme = theme_pubr()) and color palette simpsons from package ggsci since it has 16 levels and can accommodate the levels in groups such as molecular_subtype.

To view the palette:

scales::show_col(ggsci::pal_simpsons("springfield")(16))

For 2+ group comparisons, we will use violin or boxplots with jitter.

Statistics

Some modules perform group-wise comparisons. For the manuscript, we may want to output tables of the statistics and/or print the statistical test and p-value directly on the plot. We use the functions ggpubr::compare_means() and ggpubr::stat_compare_means() for this. Below are the default tests, parameters, and method options for 2 groups or more than two groups for your convenience. Caution: the default p-values on the plots are uncorrected.

  2 groups 3+ groups
Default test (method) Wilcoxon Kruskal-wallis
Allowed methods “wilcox.test” (non-parametric) “t.test” (parametric) “kruskal.test” (non-parametric) “anova” (parametric)
Default multiple testing (p.adjust.method) NA yes, but not bonferroni
Allowed p.adjust.method NA “holm”, “hochberg”, “hommel”, “bonferroni”, “BH”, “BY”, “fdr”, “none”

Below is an example for creating a violin plot with boxplot, jitter, and appropriate statistics.

if(length(unique(df$var_x)) > 2){
    method <- "kruskal.test"
  } else {
    method <- "wilcox.test"
  }


p <- ggviolin(df, x = "var_x", y = "var_y",
           color = "var_color",
           palette = "simpsons",
           order = c("a", "b", "c"),
           add = c("boxplot", "jitter"),
           ggtheme = theme_pubr()) +
    # Add pairwise comparisons p-value
    stat_compare_means(method = method, label.y = 1.2, label.x.npc = "center") +
    xlab("xlab_text") +
    ylab("ylab_text") +
    rremove("legend")