Overview

This notebook assembles individual panels into the final Figure 3 composite. All panels (except A which is a user-provided PNG) are loaded from RDS files for font size control and proper ggplot assembly.

Panel layout (8 panels, A-H):

  +---------+---------+
  |    A    |    D    |
  +---------+---------+
  |    B    |    E    |
  +---------+---------+
  |    C    |    F    |
  +---------+---------+
  |         |    G    |
  |         +---------+
  |         |    H    |
  +---------+---------+
  • Column 1: A (Leaf sampling), B (MDS dim3 vs dim4), C (Volcano Inv4m)
  • Column 2: D (Manhattan Leaf), E (Manhattan Inv4m), F (Haplotype), G (Local Manhattan), H (Local logFC)

Output: results/inversion_paper/figures/Figure3_RNAseq.png


Setup

Load Libraries

library(cowplot)
library(ggpubr)
library(ggtext)
library(magick)
library(grid)
library(ggplot2)

Configuration

# Panel directory for PNGs
panel_dir <- file.path(paths$figures, "panels")

# Final figure dimensions (2-column width for journal)
# Note: height increased to accommodate 8 panels with ggrepel labels
fig_width_mm <- 280
fig_height_mm <- 370
dpi <- 300

# Convert mm to inches for ggsave
fig_width_in <- fig_width_mm / 25.4
fig_height_in <- fig_height_mm / 25.4

Load Panels

Load RDS Panels (B, C, D, E, F, G, H)

# Helper to load RDS panel with fallback
load_rds_panel <- function(filepath, label, script_hint = "") {
  if (file.exists(filepath)) {
    p <- readRDS(filepath)
    cat(sprintf("Loaded Panel %s from RDS\n", label))
    return(p)
  } else {
    warning(sprintf("Panel %s RDS not found. %s", label, script_hint))
    return(ggplot() +
      annotate("text", x = 0.5, y = 0.5,
               label = paste("Panel", label, "\n(missing)"),
               size = 8, color = "gray50") +
      theme_void())
  }
}

# Panel B: MDS plot
mds_file <- file.path(paths$intermediate, "transcript_MDS_34.rds")
panel_B <- load_rds_panel(mds_file, "B",
  "Run differential_expression_leaf_treatment_model.Rmd first.")
## Loaded Panel B from RDS
# Remove axis text/ticks for figure assembly
if (file.exists(mds_file)) {
  panel_B <- panel_B +
    theme(
      axis.text.x = element_blank(),
      axis.ticks.x = element_blank(),
      axis.text.y = element_blank(),
      axis.ticks.y = element_blank()
    )
}

# Panel C: Volcano plot
volcano_file <- file.path(paths$intermediate, "volcano_inv4m.rds")
panel_C <- load_rds_panel(volcano_file, "C",
  "Run volcano_plot_analysis.Rmd first.")
## Loaded Panel C from RDS
# Panel D: Manhattan Leaf
panel_D_file <- file.path(paths$intermediate, "panel_D_manhattan_leaf.rds")
panel_D <- load_rds_panel(panel_D_file, "D",
  "Run make_manhattan_plots.Rmd first.")
## Loaded Panel D from RDS
# Panel E: Manhattan Inv4m
panel_E_file <- file.path(paths$intermediate, "panel_E_manhattan_inv4m.rds")
panel_E <- load_rds_panel(panel_E_file, "E",
  "Run make_manhattan_plots.Rmd first.")
## Loaded Panel E from RDS
# Panel F: Haplotype
panel_F_file <- file.path(paths$intermediate, "panel_F_haplotype.rds")
panel_F <- load_rds_panel(panel_F_file, "F",
  "Run plot_genotype_get_correlated_loci.Rmd first.")
## Loaded Panel F from RDS
# Panel G: Local Manhattan
panel_G_file <- file.path(paths$intermediate, "panel_G_local_manhattan.rds")
panel_G <- load_rds_panel(panel_G_file, "G",
  "Run make_manhattan_plots.Rmd first.")
## Loaded Panel G from RDS
# Panel H: Local logFC
panel_H_file <- file.path(paths$intermediate, "panel_H_local_logfc.rds")
panel_H <- load_rds_panel(panel_H_file, "H",
  "Run make_manhattan_plots.Rmd first.")
## Loaded Panel H from RDS

Panel A from PNG (user-provided schematic)

# Helper function to load PNG as ggplot
load_png_panel <- function(filepath, label) {
  if (file.exists(filepath)) {
    img <- image_read(filepath)
    grob <- rasterGrob(img, interpolate = TRUE)
    p <- ggdraw() + draw_grob(grob)
  } else {
    p <- ggplot() +
      annotate("text", x = 0.5, y = 0.5,
               label = paste("Panel", label, "\n(missing)"),
               size = 8, color = "gray50") +
      theme_void()
  }
  return(p)
}

# Load Panel A (leaf sampling schematic - user-provided PNG)
panel_A_file <- file.path(panel_dir, "panel_A_leaf_sampling.png")
panel_A <- load_png_panel(panel_A_file, "A")

Panel Status

# Check status of all panels
status_df <- data.frame(
  Panel = c("A", "B", "C", "D", "E", "F", "G", "H"),
  Source = c("PNG", "RDS", "RDS", "RDS", "RDS", "RDS", "RDS", "RDS"),
  Status = c(
    ifelse(file.exists(panel_A_file), "OK", "MISSING"),
    ifelse(file.exists(mds_file), "OK", "MISSING"),
    ifelse(file.exists(volcano_file), "OK", "MISSING"),
    ifelse(file.exists(panel_D_file), "OK", "MISSING"),
    ifelse(file.exists(panel_E_file), "OK", "MISSING"),
    ifelse(file.exists(panel_F_file), "OK", "MISSING"),
    ifelse(file.exists(panel_G_file), "OK", "MISSING"),
    ifelse(file.exists(panel_H_file), "OK", "MISSING")
  )
)

knitr::kable(status_df, caption = "Panel Availability")
Panel Availability
Panel Source Status
A PNG OK
B RDS OK
C RDS OK
D RDS OK
E RDS OK
F RDS OK
G RDS OK
H RDS OK

Adjust Panel Fonts

Balance font sizes across all panels for consistent appearance.

# Target base size for readable axes
base_size <- 15

# Panel B (MDS): Keep axes readable, shrink legend (legend.text uses element_markdown)
panel_B <- panel_B +
  theme(
    axis.title = element_text(size = base_size),
    legend.title = element_markdown(size = 15),
    legend.background = element_rect(fill = "transparent"),
    legend.key = element_rect(fill = "transparent", colour = NA),
    legend.position = "top",
    plot.margin = unit(c(5.5, 5.5, 5.5, 40), "pt")
  )

# Panel C (Volcano): Readable axes, smaller legend
panel_C <- panel_C +
  theme(
    axis.title = element_text(size = base_size),
    axis.text = element_text(size = base_size - 2),
    legend.key.size = unit(0.12, "cm"),
    legend.position = c(0.81, 0.94),
    legend.background = element_rect(fill = "transparent"),
    legend.key = element_rect(fill = "transparent", colour = NA)
  )

# Panels D, E (Manhattan): Readable axes, smaller title and legend
manhattan_theme <- theme(
  plot.title = element_markdown(size = base_size, face = "bold", hjust = 1),
  axis.title = element_text(size = base_size),
  axis.text = element_text(size = base_size - 2),
  axis.text.x = element_text(size = base_size - 3)
)
panel_D <- panel_D + manhattan_theme
panel_E <- panel_E + manhattan_theme

# Panels G, H (Local Manhattan/logFC): Readable axes
local_theme <- theme(
  axis.title = element_text(size = base_size),
  axis.text.x = element_text(size = base_size - 3),
  plot.margin = unit(c(5.5, 5.5, 5.5, 20), "pt")
)

# Panel F: Haplotype
panel_F <- panel_F + local_theme +
  theme(
    legend.title = element_markdown(size = 15)
  )

panel_G <- panel_G + local_theme
panel_H <- panel_H + local_theme

Add Panel Labels

add_label <- function(plot, label, fontface = "bold", size = 14) {
  ggdraw(plot) +
    draw_label(label, x = 0.02, y = 0.98, hjust = 0, vjust = 1,
               fontface = fontface, size = size)
}

panel_A_labeled <- add_label(panel_A, "A")
panel_B_labeled <- add_label(panel_B, "B")
panel_C_labeled <- add_label(panel_C, "C")
panel_D_labeled <- add_label(panel_D, "D")
panel_E_labeled <- add_label(panel_E, "E")
panel_F_labeled <- add_label(panel_F, "F")
panel_G_labeled <- add_label(panel_G, "G")
panel_H_labeled <- add_label(panel_H, "H")

Assemble Figure

# Column 1: A, B, C
col1 <- plot_grid(
  panel_A_labeled,
  panel_B_labeled,
  panel_C_labeled,
  ncol = 1,
  rel_heights = c(1, 1, 1),
  align = "v",
  axis = "lr"
)

# Column 2: D, E, F, G, H
# Panel F needs much more height for the 3 haplotype lines to be clearly visible
col2 <- plot_grid(
  panel_D_labeled,
  panel_E_labeled,
  panel_F_labeled,
  panel_G_labeled,
  panel_H_labeled,
  ncol = 1,
  rel_heights = c(0.6, 0.6, 0.6, 0.9, 0.9),
  align = "v",
  axis = "lr"
)

# Combine columns
figure3 <- plot_grid(
  col1,
  col2,
  ncol = 2,
  rel_widths = c(1, 1),
  align = "h",
  axis = "tb"
)

figure3


Save Output

output_file <- file.path(paths$figures, "Figure3_RNAseq.png")

ggsave(
  output_file,
  plot = figure3,
  width = fig_width_in,
  height = fig_height_in,
  dpi = dpi,
  bg = "white"
)

cat(sprintf("Figure saved to: %s\n", output_file))
## Figure saved to: /Users/fvrodriguez/Library/CloudStorage/GoogleDrive-frodrig4@ncsu.edu/My Drive/repos/inv4m/results/inversion_paper/figures/Figure3_RNAseq.png
cat(sprintf("Dimensions: %.0f x %.0f mm at %d DPI\n", fig_width_mm, fig_height_mm, dpi))
## Dimensions: 280 x 370 mm at 300 DPI

Summary

cat("=== Assembly Complete ===\n\n")
## === Assembly Complete ===
cat("Panel sources:\n")
## Panel sources:
cat("  A (Leaf sampling): PNG (user-provided schematic)\n")
##   A (Leaf sampling): PNG (user-provided schematic)
cat("  B (MDS): RDS -> axis removed for assembly\n")
##   B (MDS): RDS -> axis removed for assembly
cat("  C (Volcano): RDS\n")
##   C (Volcano): RDS
cat("  D (Manhattan Leaf): RDS\n")
##   D (Manhattan Leaf): RDS
cat("  E (Manhattan Inv4m): RDS\n")
##   E (Manhattan Inv4m): RDS
cat("  F (Haplotype): RDS\n")
##   F (Haplotype): RDS
cat("  G (Local Manhattan): RDS\n")
##   G (Local Manhattan): RDS
cat("  H (Local logFC): RDS\n")
##   H (Local logFC): RDS
cat("\nTo regenerate panels, run:\n")
## 
## To regenerate panels, run:
cat("  - differential_expression_leaf_treatment_model.Rmd -> Panel B (MDS)\n")
##   - differential_expression_leaf_treatment_model.Rmd -> Panel B (MDS)
cat("  - volcano_plot_analysis.Rmd -> Panel C (Volcano)\n")
##   - volcano_plot_analysis.Rmd -> Panel C (Volcano)
cat("  - make_manhattan_plots.Rmd -> Panels D, E, G, H\n")
##   - make_manhattan_plots.Rmd -> Panels D, E, G, H
cat("  - plot_genotype_get_correlated_loci.Rmd -> Panel F\n")
##   - plot_genotype_get_correlated_loci.Rmd -> Panel F
cat("\nAll RDS panels can have fonts adjusted in this assembly script.\n")
## 
## All RDS panels can have fonts adjusted in this assembly script.

Session Information

sessionInfo()
## R version 4.5.2 (2025-10-31)
## Platform: aarch64-apple-darwin20
## Running under: macOS Tahoe 26.3.1
## 
## Matrix products: default
## BLAS:   /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib 
## LAPACK: /Library/Frameworks/R.framework/Versions/4.5-arm64/Resources/lib/libRlapack.dylib;  LAPACK version 3.12.1
## 
## locale:
## [1] C.UTF-8/C.UTF-8/C.UTF-8/C/C.UTF-8/C.UTF-8
## 
## time zone: America/New_York
## tzcode source: internal
## 
## attached base packages:
## [1] grid      stats     graphics  grDevices utils     datasets  methods  
## [8] base     
## 
## other attached packages:
## [1] magick_2.9.0  ggtext_0.1.2  ggpubr_0.6.2  ggplot2_4.0.1 cowplot_1.2.0
## [6] here_1.0.2   
## 
## loaded via a namespace (and not attached):
##  [1] sass_0.4.10        generics_0.1.4     tidyr_1.3.2        rstatix_0.7.3     
##  [5] xml2_1.5.1         stringi_1.8.7      fastman_0.1.0      digest_0.6.39     
##  [9] magrittr_2.0.4     evaluate_1.0.5     RColorBrewer_1.1-3 fastmap_1.2.0     
## [13] rprojroot_2.1.1    jsonlite_2.0.0     ggrepel_0.9.6      backports_1.5.0   
## [17] Formula_1.2-5      purrr_1.2.0        viridisLite_0.4.2  scales_1.4.0      
## [21] textshaping_1.0.4  jquerylib_0.1.4    abind_1.4-8        cli_3.6.5         
## [25] rlang_1.1.6        litedown_0.9       commonmark_2.0.0   withr_3.0.2       
## [29] cachem_1.1.0       yaml_2.3.12        otel_0.2.0         tools_4.5.2       
## [33] ggsignif_0.6.4     dplyr_1.1.4        broom_1.0.11       vctrs_0.6.5       
## [37] R6_2.6.1           lifecycle_1.0.4    stringr_1.6.0      car_3.1-3         
## [41] ragg_1.5.0         pkgconfig_2.0.3    pillar_1.11.1      bslib_0.9.0       
## [45] gtable_0.3.6       glue_1.8.0         Rcpp_1.1.0         systemfonts_1.3.1 
## [49] xfun_0.55          tibble_3.3.0       tidyselect_1.2.1   knitr_1.51        
## [53] dichromat_2.0-0.1  farver_2.1.2       htmltools_0.5.9    labeling_0.4.3    
## [57] rmarkdown_2.30     carData_3.0-5      compiler_4.5.2     S7_0.2.1          
## [61] markdown_2.0       gridtext_0.1.5