setwd("C:/Users/norba/Downloads/GCMS_R_Project_Report/GCMS_R_Project")
getwd()
## [1] "C:/Users/norba/Downloads/GCMS_R_Project_Report/GCMS_R_Project"
library(tidyverse)
## Warning: package 'ggplot2' was built under R version 4.5.3
## Warning: package 'readr' was built under R version 4.5.3
## Warning: package 'purrr' was built under R version 4.5.3
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.2.1     ✔ readr     2.2.0
## ✔ forcats   1.0.1     ✔ stringr   1.6.0
## ✔ ggplot2   4.0.3     ✔ tibble    3.3.1
## ✔ lubridate 1.9.5     ✔ tidyr     1.3.2
## ✔ purrr     1.2.2     
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(readr)
library(ggplot2)

gcms <- read_csv(
  "C:/Users/norba/Downloads/GCMS_R_Project_Report/GCMS_R_Project/data/gcms_tidy_r_input.csv",
  show_col_types = FALSE
)

#create folders in the project

dir.create("figures", showWarnings = FALSE)
dir.create("tables", showWarnings = FALSE)

#summarize data and place in the folders that were created above

# Basic summaries
write_csv(gcms %>% count(tissue, sample_id), "tables/sample_counts.csv")
write_csv(gcms %>% distinct(tissue, compound_short) %>% count(tissue), "tables/unique_compounds_by_tissue.csv")
write_csv(gcms %>% distinct(tissue, compound_short, chemical_class) %>% count(tissue, chemical_class), "tables/chemical_class_summary.csv")
# Chemical class composition
class_summary <- gcms %>% distinct(tissue, compound_short, chemical_class) %>% count(tissue, chemical_class)

p <- ggplot(class_summary, aes(x = tissue, y = n, fill = chemical_class)) +
  geom_col(color = "black") +
  theme_bw(base_size = 16) +
  labs(title = "Chemical class composition by tissue",
       x = "Tissue", y = "Number of unique compounds", fill = "Chemical class")
p

#saves in figures folder
ggsave("figures/chemical_class_composition.png", p, width = 8, height = 6, dpi = 600)
# Presence/absence heatmap
presence <- gcms %>% distinct(tissue, compound_short, chemical_class)

pp <- ggplot(presence, aes(x = tissue, y = reorder(compound_short, chemical_class), fill = chemical_class)) +
  geom_tile(color = "white") +
  theme_bw(base_size = 14) +
  labs(title = "Presence of putative compounds in leaf and root tissue",
       x = "Tissue", y = "Compound", fill = "Chemical class")
pp
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA

#saves in figures folder
ggsave("figures/presence_absence_heatmap.png", p, width = 7, height = 10, dpi = 600)
# ============================================================
# GC-MS Leaf vs Root Analysis Figures
# Input file: data/gcms_tidy_r_input.csv
# ============================================================

# Load data
gcms <- read_csv("C:/Users/norba/Downloads/GCMS_R_Project_Report/GCMS_R_Project/data/gcms_tidy_r_input.csv", show_col_types = FALSE)

# Check data
glimpse(gcms)
## Rows: 40
## Columns: 17
## $ tissue           <chr> "leaf", "leaf", "leaf", "leaf", "leaf", "leaf", "leaf…
## $ sample_file      <chr> "Leaf1.D", "Leaf1.D", "Leaf1.D", "Leaf1.D", "Leaf1.D"…
## $ sample_id        <chr> "Leaf1", "Leaf1", "Leaf1", "Leaf1", "Leaf1", "Leaf1",…
## $ scan             <dbl> 120, 155, 207, 214, 300, 901, 947, 911, 977, 119, 210…
## $ retention_min    <dbl> 7.910, 8.150, 8.506, 8.554, 9.144, 13.263, 13.578, 13…
## $ compound_short   <chr> "α-Pinene", "Camphene", "β-Pinene", "β-Myrcene", "Lim…
## $ top_hit          <chr> "Tricyclo[2.2.1.0(2,6)]heptane, 1,3,3-trimethyl- / α-…
## $ match            <dbl> 941, 917, 939, 951, 889, 968, 935, 848, 935, 938, 949…
## $ r_match          <dbl> 942, 948, 962, 965, 894, 968, 942, 911, 956, 940, 966…
## $ prob_pct         <dbl> 15.30, 28.60, 37.50, 58.50, 15.90, 46.80, 65.10, 28.5…
## $ formula          <chr> "C10H16", "C10H16", "C10H16", "C10H16", "C10H16", "C1…
## $ mw               <dbl> 136, 136, 136, 136, 136, 204, 204, 204, 204, 136, 136…
## $ chemical_class   <chr> "Monoterpene", "Monoterpene", "Monoterpene", "Monoter…
## $ subclass         <chr> "bicyclic monoterpene", "bicyclic monoterpene", "bicy…
## $ rmatch_bin       <chr> "acceptable_930_949", "acceptable_930_949", "good", "…
## $ keep_for_figures <chr> "Yes", "Yes", "Yes", "Yes", "Caution", "Yes", "Yes", …
## $ notes            <chr> "Duplicate screenshots observed; counted once. Top hi…
# Make tissue and chemical class factors
gcms <- gcms %>%
  mutate(
    tissue = factor(tissue, levels = c("Leaf", "Root")),
    chemical_class = factor(
      chemical_class,
      levels = c(
        "Monoterpene",
        "Sesquiterpene",
        "Putative diterpenoid",
        "Hydrocarbon",
        "Fatty alcohol",
        "Fatty acid",
        "Unknown"
      )
    )
  )
# ============================================================
# SUMMARY TABLES
# ============================================================

dataset_summary <- tibble(
  metric = c(
    "Total unique GC-MS observations",
    "Unique compounds",
    "Unique samples",
    "Leaf samples",
    "Root samples"
  ),
  value = c(
    nrow(gcms),
    n_distinct(gcms$compound_short),
    n_distinct(gcms$sample_id),
    n_distinct(gcms$sample_id[gcms$tissue == "Leaf"]),
    n_distinct(gcms$sample_id[gcms$tissue == "Root"])
  )
)

write_csv(dataset_summary, "tables/dataset_summary.csv")

sample_counts <- gcms %>%
  count(tissue, sample_id, name = "unique_observations")

write_csv(sample_counts, "tables/sample_counts.csv")

chemical_class_summary <- gcms %>%
  distinct(tissue, compound_short, chemical_class) %>%
  count(tissue, chemical_class, name = "unique_compounds")

write_csv(chemical_class_summary, "tables/chemical_class_summary.csv")

compound_detection_counts <- gcms %>%
  count(compound_short, chemical_class, name = "detections") %>%
  arrange(desc(detections), compound_short)

write_csv(compound_detection_counts, "tables/compound_detection_counts.csv")
# ============================================================
# FIGURE 1: UNIQUE OBSERVATIONS PER SAMPLE
# ============================================================

p1 <- ggplot(sample_counts, aes(x = sample_id, y = unique_observations, fill = tissue)) +
  geom_col(color = "black", width = 0.7) +
  labs(
    title = "Unique GC-MS Observations per Sample",
    x = "Sample",
    y = "Number of Unique Observations",
    fill = "Tissue"
  ) +
  theme_bw(base_size = 16) +
  theme(
    plot.title = element_text(size = 20, face = "bold", hjust = 0.5),
    axis.title = element_text(size = 18, face = "bold"),
    axis.text.x = element_text(size = 15, face = "bold"),
    axis.text.y = element_text(size = 15),
    legend.title = element_text(size = 16, face = "bold"),
    legend.text = element_text(size = 14)
  )

p1

ggsave("figures/Figure1_unique_observations_per_sample.png", p1, width = 8, height = 5, dpi = 600)
# ============================================================
# FIGURE 2: UNIQUE COMPOUNDS BY TISSUE
# ============================================================

gcms <- gcms %>%
  mutate(
    tissue = case_when(
      str_detect(sample_id, "Leaf") ~ "Leaf",
      str_detect(sample_id, "Root") ~ "Root",
      TRUE ~ tissue
    )
  )

unique(gcms$tissue)
## [1] "Leaf" "Root"
compound_counts_tissue <- gcms %>%
  distinct(tissue, compound_short) %>%
  count(tissue, name = "unique_compounds")

p2 <- ggplot(compound_counts_tissue, aes(x = tissue, y = unique_compounds, fill = tissue)) +
  geom_col(color = "black", width = 0.6) +
  labs(
    title = "Unique Putative Compounds Detected by Tissue",
    x = "Tissue",
    y = "Number of Unique Compounds"
  ) +
  theme_bw(base_size = 16) +
  theme(
    plot.title = element_text(size = 20, face = "bold", hjust = 0.5),
    axis.title = element_text(size = 18, face = "bold"),
    axis.text = element_text(size = 16, face = "bold"),
    legend.position = "none"
  )

p2

ggsave("figures/Figure2_unique_compounds_by_tissue.png", p2, width = 7, height = 5, dpi = 600)
# ============================================================
# FIGURE 3: CHEMICAL CLASS COMPOSITION BY TISSUE
# ============================================================

p3 <- ggplot(chemical_class_summary, aes(x = tissue, y = unique_compounds, fill = chemical_class)) +
  geom_col(color = "black", width = 0.7) +
  labs(
    title = "Chemical Class Composition by Tissue",
    x = "Tissue",
    y = "Number of Unique Compounds",
    fill = "Chemical Class"
  ) +
  theme_bw(base_size = 16) +
  theme(
    plot.title = element_text(size = 20, face = "bold", hjust = 0.5),
    axis.title = element_text(size = 18, face = "bold"),
    axis.text = element_text(size = 16, face = "bold"),
    legend.title = element_text(size = 16, face = "bold"),
    legend.text = element_text(size = 13)
  )

p3

ggsave("figures/Figure3_chemical_class_composition.png", p3, width = 8, height = 6, dpi = 600)
# ============================================================
# FIGURE 4: CHEMICAL CLASS PERCENTAGES
# ============================================================

chemical_class_percent <- chemical_class_summary %>%
  group_by(tissue) %>%
  mutate(percent = 100 * unique_compounds / sum(unique_compounds)) %>%
  ungroup()

write_csv(chemical_class_percent, "tables/chemical_class_percentages.csv")

p4 <- ggplot(chemical_class_percent, aes(x = tissue, y = percent, fill = chemical_class)) +
  geom_col(color = "black", width = 0.7) +
  labs(
    title = "Chemical Class Percentages by Tissue",
    x = "Tissue",
    y = "Percent of Unique Compounds",
    fill = "Chemical Class"
  ) +
  theme_bw(base_size = 16) +
  theme(
    plot.title = element_text(size = 20, face = "bold", hjust = 0.5),
    axis.title = element_text(size = 18, face = "bold"),
    axis.text = element_text(size = 16, face = "bold"),
    legend.title = element_text(size = 16, face = "bold"),
    legend.text = element_text(size = 13)
  )

p4

ggsave("figures/Figure4_chemical_class_percentages.png", p4, width = 8, height = 6, dpi = 600)
# ============================================================
# FIGURE 5: PRESENCE/ABSENCE HEATMAP BY TISSUE
# ============================================================

presence_tissue <- gcms %>%
  distinct(tissue, compound_short, chemical_class) %>%
  arrange(chemical_class, compound_short) %>%
  mutate(compound_short = factor(compound_short, levels = unique(compound_short)))

p5 <- ggplot(presence_tissue, aes(x = tissue, y = compound_short, fill = chemical_class)) +
  geom_tile(color = "white", linewidth = 0.8) +
  labs(
    title = "Presence of Putative Compounds in Leaf and Root Tissue",
    x = "Tissue",
    y = "Compound",
    fill = "Chemical Class"
  ) +
  theme_bw(base_size = 14) +
  theme(
    plot.title = element_text(size = 18, face = "bold", hjust = 0.5),
    axis.title = element_text(size = 16, face = "bold"),
    axis.text.x = element_text(size = 15, face = "bold"),
    axis.text.y = element_text(size = 11),
    legend.title = element_text(size = 14, face = "bold"),
    legend.text = element_text(size = 12)
  )

p5

ggsave("figures/Figure5_presence_absence_heatmap_tissue.png", p5, width = 7, height = 10, dpi = 600)
# ============================================================
# FIGURE 6: SAMPLE-BY-COMPOUND HEATMAP
# ============================================================

presence_sample <- gcms %>%
  distinct(sample_id, tissue, compound_short, chemical_class) %>%
  arrange(chemical_class, compound_short) %>%
  mutate(compound_short = factor(compound_short, levels = unique(compound_short)))

p6 <- ggplot(presence_sample, aes(x = sample_id, y = compound_short, fill = chemical_class)) +
  geom_tile(color = "white", linewidth = 0.8) +
  labs(
    title = "Compound Occurrence Across Individual Samples",
    x = "Sample",
    y = "Compound",
    fill = "Chemical Class"
  ) +
  theme_bw(base_size = 13) +
  theme(
    plot.title = element_text(size = 18, face = "bold", hjust = 0.5),
    axis.title = element_text(size = 16, face = "bold"),
    axis.text.x = element_text(size = 13, face = "bold", angle = 45, hjust = 1),
    axis.text.y = element_text(size = 10),
    legend.title = element_text(size = 14, face = "bold"),
    legend.text = element_text(size = 12)
  )

p6

ggsave("figures/Figure6_sample_compound_heatmap.png", p6, width = 10, height = 10, dpi = 600)
# ============================================================
# FIGURE 7: DETECTION FREQUENCY OF COMPOUNDS
# ============================================================

p7 <- ggplot(compound_detection_counts, aes(x = reorder(compound_short, detections), y = detections, fill = chemical_class)) +
  geom_col(color = "black") +
  coord_flip() +
  labs(
    title = "Detection Frequency of Putative Compounds",
    x = "Compound",
    y = "Number of Detections",
    fill = "Chemical Class"
  ) +
  theme_bw(base_size = 14) +
  theme(
    plot.title = element_text(size = 18, face = "bold", hjust = 0.5),
    axis.title = element_text(size = 16, face = "bold"),
    axis.text.y = element_text(size = 10),
    axis.text.x = element_text(size = 13),
    legend.title = element_text(size = 14, face = "bold"),
    legend.text = element_text(size = 12)
  )

p7

ggsave("figures/Figure7_compound_detection_frequency.png", p7, width = 8, height = 8, dpi = 600)
# ============================================================
# FIGURE 8: R.MATCH SCORES BY COMPOUND
# ============================================================

rmatch_by_compound <- gcms %>%
  group_by(compound_short, chemical_class) %>%
  summarise(
    mean_r_match = mean(r_match, na.rm = TRUE),
    max_r_match = max(r_match, na.rm = TRUE),
    detections = n(),
    .groups = "drop"
  )

write_csv(rmatch_by_compound, "tables/rmatch_by_compound.csv")

p8 <- ggplot(rmatch_by_compound, aes(x = max_r_match, y = reorder(compound_short, max_r_match), color = chemical_class)) +
  geom_point(size = 5) +
  geom_vline(xintercept = 950, linetype = "dashed", linewidth = 1) +
  geom_vline(xintercept = 930, linetype = "dashed", linewidth = 1) +
  geom_vline(xintercept = 900, linetype = "dotted", linewidth = 1) +
  annotate("text", x = 952, y = 2, label = "Excellent ≥950", hjust = 0, size = 4) +
  annotate("text", x = 932, y = 4, label = "High ≥930", hjust = 0, size = 4) +
  annotate("text", x = 902, y = 6, label = "Good ≥900", hjust = 0, size = 4) +
  labs(
    title = "Reverse Match Scores for Putative GC-MS Identifications",
    x = "Maximum R.Match Score",
    y = "Compound",
    color = "Chemical Class"
  ) +
  xlim(780, 1000) +
  theme_bw(base_size = 14) +
  theme(
    plot.title = element_text(size = 18, face = "bold", hjust = 0.5),
    axis.title = element_text(size = 16, face = "bold"),
    axis.text.y = element_text(size = 10),
    axis.text.x = element_text(size = 13),
    legend.title = element_text(size = 14, face = "bold"),
    legend.text = element_text(size = 12)
  )

p8
## Warning: Removed 1 row containing missing values or values outside the scale range
## (`geom_point()`).

ggsave("figures/Figure8_rmatch_scores_by_compound.png", p8, width = 9, height = 9, dpi = 600)
## Warning: Removed 1 row containing missing values or values outside the scale range
## (`geom_point()`).
# ============================================================
# FIGURE 9: R.MATCH CONFIDENCE BINS
# ============================================================

rmatch_bins <- gcms %>%
  mutate(
    rmatch_bin = case_when(
      r_match >= 950 ~ "Excellent (≥950)",
      r_match >= 930 ~ "High (930–949)",
      r_match >= 900 ~ "Good (900–929)",
      r_match >= 850 ~ "Moderate (850–899)",
      TRUE ~ "Tentative (<850)"
    ),
    rmatch_bin = factor(
      rmatch_bin,
      levels = c(
        "Excellent (≥950)",
        "High (930–949)",
        "Good (900–929)",
        "Moderate (850–899)",
        "Tentative (<850)"
      )
    )
  ) %>%
  count(tissue, rmatch_bin, name = "observations")

write_csv(rmatch_bins, "tables/rmatch_confidence_bins.csv")

p9 <- ggplot(rmatch_bins, aes(x = rmatch_bin, y = observations, fill = tissue)) +
  geom_col(position = "dodge", color = "black") +
  labs(
    title = "Identification Confidence Based on R.Match Score",
    x = "R.Match Confidence Category",
    y = "Number of Observations",
    fill = "Tissue"
  ) +
  theme_bw(base_size = 14) +
  theme(
    plot.title = element_text(size = 18, face = "bold", hjust = 0.5),
    axis.title = element_text(size = 16, face = "bold"),
    axis.text.x = element_text(size = 12, face = "bold", angle = 35, hjust = 1),
    axis.text.y = element_text(size = 13),
    legend.title = element_text(size = 14, face = "bold"),
    legend.text = element_text(size = 12)
  )

p9

ggsave("figures/Figure9_rmatch_confidence_bins.png", p9, width = 9, height = 5, dpi = 600)
# ============================================================
# FIGURE 10: RETENTION TIME DISTRIBUTION
# ============================================================

p10 <- ggplot(gcms, aes(x = retention_min, fill = tissue)) +
  geom_density(alpha = 0.4) +
  labs(
    title = "Retention Time Distribution of Detected Compounds",
    x = "Retention Time (min)",
    y = "Density",
    fill = "Tissue"
  ) +
  theme_bw(base_size = 16) +
  theme(
    plot.title = element_text(size = 20, face = "bold", hjust = 0.5),
    axis.title = element_text(size = 18, face = "bold"),
    axis.text = element_text(size = 15),
    legend.title = element_text(size = 16, face = "bold"),
    legend.text = element_text(size = 14)
  )

p10

ggsave("figures/Figure10_retention_time_distribution.png", p10, width = 8, height = 5, dpi = 600)
# ============================================================
# FIGURE 11: RETENTION TIME BY CHEMICAL CLASS
# ============================================================

p11 <- ggplot(gcms, aes(x = chemical_class, y = retention_min, fill = tissue)) +
  geom_boxplot(alpha = 0.7, outlier.shape = NA) +
  geom_jitter(
    position = position_jitterdodge(jitter.width = 0.2, dodge.width = 0.75),
    size = 2.5,
    alpha = 0.8
  ) +
  labs(
    title = "Retention Time Patterns by Chemical Class",
    x = "Chemical Class",
    y = "Retention Time (min)",
    fill = "Tissue"
  ) +
  theme_bw(base_size = 15) +
  theme(
    plot.title = element_text(size = 18, face = "bold", hjust = 0.5),
    axis.title = element_text(size = 16, face = "bold"),
    axis.text.x = element_text(size = 12, face = "bold", angle = 35, hjust = 1),
    axis.text.y = element_text(size = 13),
    legend.title = element_text(size = 14, face = "bold"),
    legend.text = element_text(size = 12)
  )

p11

ggsave("figures/Figure11_retention_time_by_class.png", p11, width = 9, height = 6, dpi = 600)
# ============================================================
# FIGURE 12: BUBBLE PLOT OF CHEMICAL CLASS RICHNESS
# ============================================================

p12 <- ggplot(chemical_class_summary, aes(x = tissue, y = chemical_class, size = unique_compounds, color = chemical_class)) +
  geom_point(alpha = 0.85) +
  scale_size(range = c(4, 14)) +
  labs(
    title = "Chemical Class Richness by Tissue",
    x = "Tissue",
    y = "Chemical Class",
    size = "Unique Compounds",
    color = "Chemical Class"
  ) +
  theme_bw(base_size = 16) +
  theme(
    plot.title = element_text(size = 20, face = "bold", hjust = 0.5),
    axis.title = element_text(size = 18, face = "bold"),
    axis.text = element_text(size = 15, face = "bold"),
    legend.title = element_text(size = 14, face = "bold"),
    legend.text = element_text(size = 12)
  )

p12

ggsave("figures/Figure12_bubble_chemical_class_richness.png", p12, width = 8, height = 5, dpi = 600)
# ============================================================
# FIGURE 13: SHARED VS TISSUE-SPECIFIC COMPOUNDS
# ============================================================

shared_status <- gcms %>%
  distinct(tissue, compound_short) %>%
  group_by(compound_short) %>%
  summarise(
    tissues_detected = paste(sort(unique(as.character(tissue))), collapse = " + "),
    n_tissues = n_distinct(tissue),
    .groups = "drop"
  ) %>%
  mutate(
    status = case_when(
      tissues_detected == "Leaf" ~ "Leaf only",
      tissues_detected == "Root" ~ "Root only",
      n_tissues == 2 ~ "Shared",
      TRUE ~ "Other"
    )
  ) %>%
  count(status, name = "unique_compounds")

write_csv(shared_status, "tables/shared_vs_tissue_specific_compounds.csv")

p13 <- ggplot(shared_status, aes(x = status, y = unique_compounds, fill = status)) +
  geom_col(color = "black", width = 0.65) +
  labs(
    title = "Shared and Tissue-Specific Putative Compounds",
    x = "",
    y = "Number of Unique Compounds",
    fill = "Category"
  ) +
  theme_bw(base_size = 16) +
  theme(
    plot.title = element_text(size = 20, face = "bold", hjust = 0.5),
    axis.title = element_text(size = 18, face = "bold"),
    axis.text.x = element_text(size = 15, face = "bold"),
    axis.text.y = element_text(size = 14),
    legend.position = "none"
  )

p13

ggsave("figures/Figure13_shared_vs_tissue_specific.png", p13, width = 7, height = 5, dpi = 600)
# ============================================================
# FIGURE 14: MONOTERPENE / SESQUITERPENE / DITERPENOID ONLY
# ============================================================

terpene_data <- gcms %>%
  filter(chemical_class %in% c("Monoterpene", "Sesquiterpene", "Putative diterpenoid")) %>%
  distinct(tissue, compound_short, chemical_class)

terpene_summary <- terpene_data %>%
  count(tissue, chemical_class, name = "unique_compounds")

write_csv(terpene_summary, "tables/terpene_class_summary.csv")

p14 <- ggplot(terpene_summary, aes(x = chemical_class, y = unique_compounds, fill = tissue)) +
  geom_col(position = "dodge", color = "black") +
  labs(
    title = "Terpene Class Comparison Between Leaf and Root Tissue",
    x = "Terpene Class",
    y = "Number of Unique Compounds",
    fill = "Tissue"
  ) +
  theme_bw(base_size = 16) +
  theme(
    plot.title = element_text(size = 19, face = "bold", hjust = 0.5),
    axis.title = element_text(size = 18, face = "bold"),
    axis.text.x = element_text(size = 14, face = "bold", angle = 25, hjust = 1),
    axis.text.y = element_text(size = 14),
    legend.title = element_text(size = 15, face = "bold"),
    legend.text = element_text(size = 13)
  )

p14

ggsave("figures/Figure14_terpene_class_comparison.png", p14, width = 8, height = 5, dpi = 600)
# ============================================================
# FIGURE 15: COMPOUND DETECTION ACROSS SAMPLES
# ============================================================

compound_by_sample <- gcms %>%
  distinct(sample_id, tissue, compound_short, chemical_class) %>%
  count(compound_short, chemical_class, name = "samples_detected") %>%
  arrange(desc(samples_detected))

write_csv(compound_by_sample, "tables/compound_detection_across_samples.csv")

p15 <- ggplot(compound_by_sample, aes(x = reorder(compound_short, samples_detected), y = samples_detected, fill = chemical_class)) +
  geom_col(color = "black") +
  coord_flip() +
  labs(
    title = "Number of Samples in Which Each Compound Was Detected",
    x = "Compound",
    y = "Number of Samples",
    fill = "Chemical Class"
  ) +
  theme_bw(base_size = 14) +
  theme(
    plot.title = element_text(size = 18, face = "bold", hjust = 0.5),
    axis.title = element_text(size = 16, face = "bold"),
    axis.text.y = element_text(size = 10),
    axis.text.x = element_text(size = 13),
    legend.title = element_text(size = 14, face = "bold"),
    legend.text = element_text(size = 12)
  )

p15

ggsave("figures/Figure15_compound_detection_across_samples.png", p15, width = 8, height = 8, dpi = 600)

# ============================================================
# PRINT QUICK SUMMARY TO CONSOLE
# ============================================================

dataset_summary
## # A tibble: 5 × 2
##   metric                          value
##   <chr>                           <int>
## 1 Total unique GC-MS observations    40
## 2 Unique compounds                   20
## 3 Unique samples                      6
## 4 Leaf samples                        1
## 5 Root samples                        1
sample_counts
## # A tibble: 6 × 3
##   tissue sample_id unique_observations
##   <fct>  <chr>                   <int>
## 1 <NA>   Leaf1                       9
## 2 <NA>   Leaf2                       7
## 3 <NA>   Leaf3                       2
## 4 <NA>   Root1                       6
## 5 <NA>   Root2                      11
## 6 <NA>   Root3                       5
compound_counts_tissue
## # A tibble: 2 × 2
##   tissue unique_compounds
##   <chr>             <int>
## 1 Leaf                 10
## 2 Root                 14
chemical_class_summary
## # A tibble: 3 × 3
##   tissue chemical_class unique_compounds
##   <fct>  <fct>                     <int>
## 1 <NA>   Monoterpene                   7
## 2 <NA>   Sesquiterpene                 5
## 3 <NA>   <NA>                          8
shared_status
## # A tibble: 3 × 2
##   status    unique_compounds
##   <chr>                <int>
## 1 Leaf only                6
## 2 Root only               10
## 3 Shared                   4
network_data <- gcms %>%
  distinct(tissue, compound_short, chemical_class)

ggplot(network_data, aes(x = tissue, y = reorder(compound_short, chemical_class))) +
  geom_line(aes(group = compound_short), color = "grey70", linewidth = 0.8) +
  geom_point(aes(color = chemical_class), size = 5) +
  labs(
    title = "Shared and Tissue-Specific Putative Metabolites",
    x = "Tissue",
    y = "Putative Compound",
    color = "Chemical Class"
  ) +
  theme_bw(base_size = 18) +
  theme(
    plot.title = element_text(size = 22, face = "bold", hjust = 0.5),
    axis.title = element_text(size = 20, face = "bold"),
    axis.text.x = element_text(size = 18, face = "bold"),
    axis.text.y = element_text(size = 14),
    legend.title = element_text(size = 18, face = "bold"),
    legend.text = element_text(size = 15)
  )
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA

ggsave("Figure4_Network_Shared_Tissue_Specific_Metabolites.png", width = 9, height = 10, dpi = 600)
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA
## Warning in mean.default(X[[i]], ...): argument is not numeric or logical:
## returning NA

##retention time pattern

compound_rt <- gcms %>%
  group_by(tissue, compound_short, chemical_class) %>%
  summarise(
    mean_rt = mean(retention_min, na.rm = TRUE),
    mean_rmatch = mean(r_match, na.rm = TRUE),
    detections = n(),
    .groups = "drop"
  )

p4 <- ggplot(compound_rt,
             aes(x = mean_rt, y = reorder(compound_short, mean_rt))) +
  geom_point(aes(color = tissue, size = mean_rmatch), alpha = 0.85) +
  facet_wrap(~ tissue, nrow = 1) +
  theme_bw(base_size = 15) +
  labs(
    title = "Retention Time Pattern of Putative Compounds by Tissue",
    x = "Mean Retention Time (min)",
    y = "Putative Compound",
    color = "Tissue",
    size = "Mean R.Match"
  ) +
  theme(
    plot.title = element_text(size = 22, face = "bold", hjust = 0.5),
    axis.title = element_text(size = 18, face = "bold"),
    axis.text.y = element_text(size = 11),
    strip.text = element_text(size = 16, face = "bold")
  )

p4

ggsave("figures/Figure4_compound_retention_patterns.png", p4,
       width = 11, height = 9, dpi = 600)
pathway_table <- gcms %>%
  distinct(tissue, compound_short, chemical_class) %>%
  mutate(
    pathway = case_when(
      chemical_class == "Monoterpene" ~ "MEP → GPP → Monoterpenes",
      chemical_class == "Sesquiterpene" ~ "MVA → FPP → Sesquiterpenes",
      str_detect(chemical_class, "Diterpen") ~ "GGPP → Diterpenoids",
      TRUE ~ "Other / Unknown"
    )
  )

p5 <- ggplot(pathway_table,
             aes(x = pathway, y = compound_short, color = tissue)) +
  geom_point(size = 4) +
  theme_bw(base_size = 15) +
  labs(
    title = "Detected Putative Metabolites Mapped to Biosynthetic Pathways",
    x = "Known Biosynthetic Pathway",
    y = "Putative Compound",
    color = "Tissue"
  ) +
  theme(
    plot.title = element_text(size = 21, face = "bold", hjust = 0.5),
    axis.title = element_text(size = 18, face = "bold"),
    axis.text.x = element_text(size = 12, angle = 30, hjust = 1),
    axis.text.y = element_text(size = 11),
    legend.title = element_text(size = 15, face = "bold")
  )

p5

ggsave("figures/Figure5_biosynthetic_pathway_mapping.png", p5,
       width = 11, height = 9, dpi = 600)
# Venn diagram using only ggplot2/tidyverse

library(tidyverse)

gcms <- read_csv(
  "C:/Users/norba/Downloads/GCMS_R_Project_Report/GCMS_R_Project/data/gcms_tidy_r_input.csv",
  show_col_types = FALSE
)

gcms <- gcms %>%
  mutate(
    tissue = str_to_title(tissue),
    compound_short = str_replace_all(compound_short, "_", "-")
  )

leaf_compounds <- gcms %>%
  filter(tissue == "Leaf") %>%
  distinct(compound_short)

root_compounds <- gcms %>%
  filter(tissue == "Root") %>%
  distinct(compound_short)

shared <- intersect(leaf_compounds$compound_short, root_compounds$compound_short)
leaf_only <- setdiff(leaf_compounds$compound_short, root_compounds$compound_short)
root_only <- setdiff(root_compounds$compound_short, leaf_compounds$compound_short)

venn_counts <- tibble(
  category = c("Leaf only", "Shared", "Root only"),
  count = c(length(leaf_only), length(shared), length(root_only))
)

print(venn_counts)
## # A tibble: 3 × 2
##   category  count
##   <chr>     <int>
## 1 Leaf only     6
## 2 Shared        4
## 3 Root only    10
p_venn <- ggplot() +
  annotate("point", x = -0.7, y = 0, size = 95, shape = 21, alpha = 0.25, fill = "pink") +
  annotate("point", x = 0.7, y = 0, size = 95, shape = 21, alpha = 0.25, fill = "lightblue") +
  annotate("text", x = -1.25, y = 0, label = length(leaf_only), size = 10, fontface = "bold") +
  annotate("text", x = 0, y = 0, label = length(shared), size = 10, fontface = "bold") +
  annotate("text", x = 1.25, y = 0, label = length(root_only), size = 10, fontface = "bold") +
  annotate("text", x = -0.7, y = 1.1, label = "Leaf", size = 8, fontface = "bold") +
  annotate("text", x = 0.7, y = 1.1, label = "Root", size = 8, fontface = "bold") +
  annotate("text", x = -1.25, y = -0.9, label = "Leaf only", size = 5) +
  annotate("text", x = 0, y = -0.9, label = "Shared", size = 5) +
  annotate("text", x = 1.25, y = -0.9, label = "Root only", size = 5) +
  coord_fixed() +
  theme_void() +
  labs(title = "Shared and Tissue-Specific Putative Metabolites") +
  theme(plot.title = element_text(size = 19, face = "bold", hjust = 0.5))

p_venn

ggsave("figures/Figure_Venn_leaf_root_compounds.png", p_venn,
       width = 8, height = 6, dpi = 600)