{"spec_id":"ma-differential-expression","library":"ggplot2","language":"r","code":"#' anyplot.ai\n#' ma-differential-expression: MA Plot for Differential Expression\n#' Library: ggplot2 3.5.1 | R 4.4.1\n#' Quality: 89/100 | Created: 2026-06-21\n\nlibrary(ggplot2)\nlibrary(ragg)\n\nset.seed(42)\n\n# Theme tokens (Imprint palette — see prompts/default-style-guide.md)\nTHEME       <- Sys.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG     <- if (THEME == \"light\") \"#FAF8F1\" else \"#1A1A17\"\nELEVATED_BG <- if (THEME == \"light\") \"#FFFDF6\" else \"#242420\"\nINK         <- if (THEME == \"light\") \"#1A1A17\" else \"#F0EFE8\"\nINK_SOFT    <- if (THEME == \"light\") \"#4A4A44\" else \"#B8B7B0\"\nINK_MUTED   <- if (THEME == \"light\") \"#6B6A63\" else \"#A8A79F\"\n\nIMPRINT_PALETTE <- c(\n  \"#009E73\",  # 1 — brand green (always first series)\n  \"#C475FD\",  # 2 — lavender\n  \"#4467A3\",  # 3 — blue\n  \"#BD8233\",  # 4 — ochre\n  \"#AE3030\",  # 5 — matte red\n  \"#2ABCCD\",  # 6 — cyan\n  \"#954477\",  # 7 — rose\n  \"#99B314\"   # 8 — lime\n)\n\n# Data: simulated RNA-seq differential expression results (DESeq2-style)\nn_genes  <- 12000\n\n# A value: mean average expression (log2 baseMean), gamma-distributed for realism\nmean_expr <- rgamma(n_genes, shape = 3, rate = 0.4) + 0.5\n\n# M value: log2 fold change — centered near 0 with slight low-expression bias\nlfc <- rnorm(n_genes, mean = -0.08 * exp(-mean_expr / 4), sd = 0.3)\n\n# Significant genes (~7%): larger LFC spread\nn_sig   <- round(n_genes * 0.07)\nsig_idx <- sample(n_genes, n_sig)\nlfc[sig_idx] <- lfc[sig_idx] + rnorm(n_sig, mean = 0, sd = 2.8)\nsignificant <- logical(n_genes)\nsignificant[sig_idx] <- TRUE\n\ndf <- data.frame(\n  mean_expression = mean_expr,\n  log_fold_change = lfc,\n  significant     = significant\n)\n\n# Top 10 significant genes to label (highest |LFC|)\ndf_sig      <- df[df$significant, ]\ndf_sig_top  <- df_sig[order(abs(df_sig$log_fold_change), decreasing = TRUE), ]\ntop_genes   <- head(df_sig_top, 10)\ntop_genes$gene_name <- c(\"MYC\", \"TNF\", \"TP53\", \"IL6\", \"VEGFA\",\n                         \"EGFR\", \"BRCA1\", \"CD8A\", \"FOXP3\", \"HIF1A\")\n\n# Subsample for LOESS curve (performance on large n)\ndf_smooth <- df[sample(nrow(df), 3000), ]\n\n# Split for layered rendering (non-sig behind sig)\ndf_nonsig    <- df[!df$significant, ]\ndf_sig_plot  <- df[df$significant, ]\n\n# Plot\np <- ggplot(df, aes(x = mean_expression, y = log_fold_change)) +\n  # Non-significant genes\n  geom_point(\n    data  = df_nonsig,\n    aes(color = \"Non-significant\"),\n    alpha = 0.18,\n    size  = 0.4\n  ) +\n  # Significant genes\n  geom_point(\n    data  = df_sig_plot,\n    aes(color = \"Significant\"),\n    alpha = 0.55,\n    size  = 0.85\n  ) +\n  # Reference line at M = 0 (no change)\n  geom_hline(yintercept = 0, color = INK, linewidth = 0.6) +\n  # Dashed ±1 lines (2-fold change thresholds)\n  geom_hline(\n    yintercept = c(1, -1),\n    color      = INK_SOFT,\n    linewidth  = 0.45,\n    linetype   = \"dashed\"\n  ) +\n  # LOESS curve to reveal expression-dependent bias\n  geom_smooth(\n    data        = df_smooth,\n    aes(x = mean_expression, y = log_fold_change),\n    method      = \"loess\",\n    formula     = y ~ x,\n    se          = FALSE,\n    color       = IMPRINT_PALETTE[4],\n    linewidth   = 1.2,\n    span        = 0.5,\n    inherit.aes = FALSE\n  ) +\n  # Gene labels for top differentially expressed genes\n  geom_text(\n    data          = top_genes,\n    aes(label = gene_name),\n    color         = INK,\n    size          = 3.0,\n    hjust         = -0.15,\n    vjust         = 0.5,\n    check_overlap = TRUE\n  ) +\n  # Color scale with legend\n  scale_color_manual(\n    values = c(\"Non-significant\" = INK_MUTED, \"Significant\" = IMPRINT_PALETTE[1]),\n    name   = NULL\n  ) +\n  guides(color = guide_legend(override.aes = list(size = 3, alpha = 1))) +\n  labs(\n    x     = \"Mean Average Expression (log₂)\",\n    y     = \"Log₂ Fold Change\",\n    title = \"ma-differential-expression · r · ggplot2 · anyplot.ai\"\n  ) +\n  theme_minimal(base_size = 8) +\n  theme(\n    plot.background   = element_rect(fill = PAGE_BG, color = PAGE_BG),\n    panel.background  = element_rect(fill = PAGE_BG, color = NA),\n    panel.grid.major  = element_line(color = INK_SOFT, linewidth = 0.25),\n    panel.grid.minor  = element_line(color = INK_SOFT, linewidth = 0.15),\n    panel.border      = element_blank(),\n    axis.line         = element_line(color = INK_SOFT, linewidth = 0.5),\n    axis.title        = element_text(color = INK, size = 10),\n    axis.text         = element_text(color = INK_SOFT, size = 8),\n    plot.title        = element_text(color = INK, size = 12),\n    legend.background      = element_rect(fill = ELEVATED_BG, color = INK_SOFT),\n    legend.text            = element_text(color = INK_SOFT, size = 8),\n    legend.position        = \"inside\",\n    legend.position.inside = c(0.88, 0.88)\n  )\n\n# Save\nggsave(\n  filename = sprintf(\"plot-%s.png\", THEME),\n  plot     = p,\n  device   = ragg::agg_png,\n  width    = 8,\n  height   = 4.5,\n  units    = \"in\",\n  dpi      = 400\n)\n"}