97 lines
4.8 KiB
R
97 lines
4.8 KiB
R
#!/usr/bin/env Rscript
|
||
|
||
script_args <- commandArgs(trailingOnly = FALSE)
|
||
file_arg <- script_args[grepl("^--file=", script_args)][1]
|
||
script_path <- normalizePath(sub("^--file=", "", file_arg))
|
||
repo_root <- normalizePath(file.path(dirname(script_path), ".."))
|
||
setwd(repo_root)
|
||
|
||
dir.create(file.path("revision", "figures"), recursive = TRUE, showWarnings = FALSE)
|
||
|
||
library(grid)
|
||
|
||
# Draw an overarching section container with a title header
|
||
draw_section <- function(x, y, width, height, title, bg = "#FAFAFA", border = "#333333") {
|
||
grid.roundrect(x = unit(x, "npc"), y = unit(y, "npc"),
|
||
width = unit(width, "npc"), height = unit(height, "npc"),
|
||
r = unit(.018, "snpc"),
|
||
gp = gpar(fill = bg, col = border, lwd = .9))
|
||
|
||
# Header bar
|
||
header_h <- .040
|
||
grid.roundrect(x = unit(x, "npc"), y = unit(y + height/2 - header_h/2, "npc"),
|
||
width = unit(width, "npc"), height = unit(header_h, "npc"),
|
||
r = unit(.018, "snpc"),
|
||
gp = gpar(fill = "#EBEBEB", col = border, lwd = .9))
|
||
grid.text(title, x = unit(x - width*0.46, "npc"), y = unit(y + height/2 - header_h/2, "npc"),
|
||
just = "left", gp = gpar(fontsize = 9, fontface = "bold", col = "#111111"))
|
||
}
|
||
|
||
# Sub-box
|
||
draw_box <- function(x, y, width, height, title, text_items = c(), bg = "#FFFFFF", border = "#555555") {
|
||
grid.roundrect(x = unit(x, "npc"), y = unit(y, "npc"),
|
||
width = unit(width, "npc"), height = unit(height, "npc"),
|
||
r = unit(.015, "snpc"),
|
||
gp = gpar(fill = bg, col = border, lwd = .75))
|
||
grid.text(title, x = unit(x, "npc"), y = unit(y + height*0.28, "npc"),
|
||
gp = gpar(fontsize = 8.2, fontface = "bold", col = "#111111"))
|
||
|
||
if (length(text_items) > 0) {
|
||
txt <- paste(text_items, collapse = "\n")
|
||
grid.text(txt, x = unit(x, "npc"), y = unit(y - height*0.18, "npc"),
|
||
gp = gpar(fontsize = 7.4, fontface = "plain", col = "#333333"))
|
||
}
|
||
}
|
||
|
||
arrow <- function(x0, y0, x1, y1) {
|
||
grid.lines(x = unit(c(x0, x1), "npc"), y = unit(c(y0, y1), "npc"),
|
||
arrow = grid::arrow(length = unit(.055, "inches"), type = "closed"),
|
||
gp = gpar(col = "#222222", fill = "#222222", lwd = .9))
|
||
}
|
||
|
||
cairo_pdf(file.path("revision", "figures", "research_workflow.pdf"),
|
||
width = 8.2, height = 7.6, onefile = TRUE)
|
||
grid.newpage()
|
||
|
||
# ===========================================================================
|
||
# Area 1: Data Acquisition
|
||
# ===========================================================================
|
||
draw_section(.5, .865, .94, .21, "1. Data Acquisition")
|
||
draw_box(.27, .84, .42, .12, "Text Data Projects", c("• Manifesto platforms", "• Campaign media text"))
|
||
draw_box(.73, .84, .42, .12, "Expert Survey Projects", c("• CHES, V-Party, POPPA & GPS", "• Morgan historical survey"))
|
||
|
||
arrow(.5, .76, .5, .72)
|
||
|
||
# ===========================================================================
|
||
# Area 2: Data Harmonization
|
||
# ===========================================================================
|
||
draw_section(.5, .62, .94, .18, "2. Data Harmonization")
|
||
draw_box(.20, .595, .30, .10, "Party Identification", c("• PartyFacts harmonization", "• Alliance mapping"))
|
||
draw_box(.50, .595, .26, .10, "Item Orientation", c("• Directional polarity", "• Inverted item reversal"))
|
||
draw_box(.80, .595, .28, .10, "Scale Harmonization", c("• Text item counts", "• Expert scale mapping"))
|
||
|
||
arrow(.5, .53, .5, .49)
|
||
|
||
# ===========================================================================
|
||
# Area 3: Dynamic Two-Dimensional Modeling
|
||
# ===========================================================================
|
||
draw_section(.5, .385, .94, .19, "3. Dynamic Two-Dimensional Modeling", bg = "#F4F4F4", border = "#111111")
|
||
draw_box(.20, .36, .30, .11, "Latent State Process", c("• Economic & Cultural scales", "• Segment random walks"))
|
||
draw_box(.50, .36, .26, .11, "Likelihood Functions", c("• Hurdle-binomial text counts", "• Beta-binomial expert means"))
|
||
draw_box(.80, .36, .28, .11, "Estimation & Anchoring", c("• General left-right mixtures", "• Hamiltonian Monte Carlo"))
|
||
|
||
arrow(.5, .29, .5, .25)
|
||
|
||
# ===========================================================================
|
||
# Area 4: Data Extraction & Validation
|
||
# ===========================================================================
|
||
draw_section(.5, .135, .94, .20, "4. Data Extraction & Validation")
|
||
draw_box(.20, .11, .30, .12, "Primary Panel Release", c("• 1944–2025 election panel", "• Posterior means & CIs"))
|
||
draw_box(.50, .11, .26, .12, "Secondary Output", c("• Annual trajectories", "• Composition metadata"))
|
||
draw_box(.80, .11, .28, .12, "Validation & Diagnostics", c("• Blocked holdout & PPC", "• Ablation & sensitivity"))
|
||
|
||
dev.off()
|
||
|
||
message("Wrote validation/figures/research_workflow.pdf")
|
||
|