Modern, customizable beamer and Stata/Python/R themes
Repository Context: This directory is part of the Wildcat repository. While the parent repository provides a modern Northwestern University Beamer presentation theme, the
scheme/folder houses the companion publication-grade graph styling system across Stata (scheme-wildcat), R (theme_wildcat), and Python (theme_wildcat/wildcat.mplstyle).
A unified, publication-grade graph theme and styling system featuring official Northwestern University branding. This system provides synchronized styling implementations for Stata, R, and Python, ensuring that figures produced across all three environments share an identical visual language, typographic hierarchy, and brand-compliant color palette anchored to R’s ggplot2 theme_minimal() aesthetic.
[!TIP] Working with an AI Coding Agent? If you are using an AI coding agent (such as Claude, ChatGPT, Cursor, Copilot, or Gemini) to write scripts, create figures, or adapt these themes to a new institution or color palette, share
FOR_AGENTS.mdwith the agent. It contains concise, structured instructions for downloading files, referencing them across all three languages, programmatically editing palettes, and maintaining visual parity.
Install the complete scheme, custom marker styles, and official Northwestern color style files directly from SSC:
* Install scheme, styles, and color definitions from SSC
ssc install wildcat, replace
* Set scheme permanently for all future Stata sessions
set scheme wildcat, permanently
net install (Optional)To install the latest development version directly from GitHub:
* Install latest development version from GitHub
net from "https://raw.githubusercontent.com/aarondwolf/wildcat/main/scheme"
net describe wildcat
net install wildcat, replace
* Set scheme permanently for all future Stata sessions
set scheme wildcat, permanently
Once installed, you can apply the scheme in individual graph commands:
graph twoway scatter mpg weight, scheme(wildcat)
ggplot2 SetupSource the theme script or copy r/theme_wildcat.R into your project:
source("r/theme_wildcat.R")
# Apply theme and discrete palette to any ggplot2 chart
ggplot(df, aes(x = x, y = y, color = group)) +
geom_point() +
scale_color_wildcat() +
theme_wildcat()
matplotlib SetupThe Python theme is provided in the py/ folder via theme_wildcat.py and the standalone wildcat.mplstyle stylesheet:
import matplotlib.pyplot as plt
import pandas as pd
from py.theme_wildcat import set_theme, wildcat_colors, labs, legend_top
# 1. Apply Wildcat theme globally (rcParams, typography, colors, padding)
set_theme()
# 2. Plot using standard Matplotlib or Pandas
fig, ax = plt.subplots(figsize=(8, 5))
ax.scatter(df["weight"], df["mpg"], color=wildcat_colors["nupurple"], s=28)
# 3. Add ggplot2-style titles, subtitles, and captions
labs(
ax,
title="Automobile Weight vs. Fuel Efficiency",
subtitle="Linear relationship with Northwestern branding",
x="Vehicle Weight (lbs.)",
y="Mileage (mpg)",
caption="Source: 1978 Automobile Data"
)
# 4. For multi-series plots, place the legend on top flush with the title
# legend_top(ax, ncol=2)
plt.savefig("figure.png", dpi=300)
If you prefer not to import the helper functions, you can load the stylesheet directly:
import matplotlib.pyplot as plt
plt.style.use("py/wildcat.mplstyle")
The Python module provides the same discrete and continuous palettes as R and Stata:
set_theme(palette="default"): 12-color balanced categorical sequence (nupurple, nudarkorange, nubrightblue, …).set_theme(palette="bright"): Secondary bright palette.set_theme(palette="dark"): Secondary dark palette.set_theme(palette="purple"): 5-step purple monochromatic sequence.cmap_wildcat_purple and cmap_wildcat_diverging for heatmaps and continuous color scales.The scheme/ folder is structured for seamless GitHub hosting and native Stata net install packaging. The top level of this folder contains the core Stata package distribution files, while datasets, tests, build scripts, and multi-language theme implementations are organized into dedicated subdirectories:
scheme/
├── stata.toc # Stata package directory table of contents
├── wildcat.pkg # Stata net install package manifest
├── scheme-wildcat.scheme # Compiled standalone Stata scheme file
├── wildcat.sthlp # Stata help documentation file
├── scheme-wildcat.sthlp # Stata help alias for scheme-wildcat
├── colorpalette_wildcat.ado # Native Wildcat palette for Ben Jann's colorpalette
├── colorpalette_nu.ado # Backward-compatibility alias for colorpalette
├── color-*.style # Standalone Stata color style definitions
├── FOR_AGENTS.md # Dedicated guide and instructions for AI coding agents
├── data/ # Bundled benchmark datasets for validation & testing
│ ├── auto.dta # 1978 Automobile dataset
│ ├── trends.dta # Multi-line sector growth dataset (2010–2022)
│ ├── lollipop.dta # Deviation dataset for lollipop stem plot
│ ├── forest.dta # Regression coefficient estimates (95% CI)
│ ├── dumbbell.dta # Paired segment comparison dataset
│ ├── area.dta # Energy portfolio composition dataset
│ ├── ribbon.dta # Economic output projection with confidence intervals
│ └── pyramid.dta # Quarterly variance tornado dataset
├── tests/ # Comprehensive 16-graph validation test suites
│ ├── test_stata_plots.do # Stata validation suite compiling 16 distinct plot types
│ ├── test_r_plots.R # R validation suite compiling 16 matching ggplot2 plots
│ └── test_py_plots.py # Python validation suite compiling 16 matching Matplotlib plots
├── stata/ # Stata scheme generation source code
│ └── make_scheme.do # Scheme generation & grstyle configuration script
├── r/ # R theme implementation
│ ├── theme_wildcat.R # Core ggplot2 theme, color vectors, palettes, and scales
│ └── theme_nu.R # Backward-compatibility alias wrapper
├── py/ # Python / Matplotlib theme implementation
│ ├── __init__.py # Package entry point
│ ├── wildcat.mplstyle # Standalone Matplotlib stylesheet
│ └── theme_wildcat.py # Core module (set_theme, palettes, labs, legend_top)
├── output_checks/ # Shared output directory containing side-by-side validation PNGs
│ ├── stata_*.png # 16 exported Stata test figures
│ ├── r_*.png # 16 matching exported R ggplot2 test figures
│ └── py_*.png # 16 matching exported Python Matplotlib test figures
├── latex/ # Automated side-by-side comparison presentations
│ ├── update.ps1 # PowerShell script: compiles R vs. Stata presentation.pdf
│ ├── update.sh # Bash script for Unix environments
│ ├── presentation.tex # R vs. Stata Beamer presentation
│ ├── presentation.pdf # Compiled R vs. Stata comparison presentation (16 slides)
│ ├── update_py_r.ps1 # PowerShell script: compiles Python vs. R presentation_py_r.pdf
│ ├── presentation_py_r.tex # Python vs. R Beamer presentation
│ └── presentation_py_r.pdf # Compiled Python vs. R comparison presentation (16 slides)
└── README.md # Scheme folder documentation and user guide
The installed color style files (color-*.style) provide direct, native access to official Northwestern University brand colors across all Stata graph commands (e.g., mcolor(nupurple), lcolor(nudarkorange), fcolor(nupurple20%50)), matched identically in R and Python:
| Alias | RGB Values | Hex Code | Swatch / Description |
|---|---|---|---|
nupurple |
78 42 132 |
#4E2A84 |
Primary Northwestern Purple |
nupurple150 |
38 8 65 |
#260841 |
Deep Purple (darkest accent) |
nupurple50 |
147 128 192 |
#9380C0 |
Light Purple |
nupurple40 |
164 149 195 |
#A495C3 |
Muted Purple Tint |
nupurple20 |
204 196 223 |
#CCC4DF |
Soft Purple Tint |
nubrightgreen |
88 185 171 |
#58B9AB |
Bright Green |
nubrightteal |
127 206 205 |
#7FCECD |
Bright Teal |
nubrightblue |
80 145 205 |
#5091CD |
Bright Blue |
nubrightyellow |
237 233 59 |
#EDE93B |
Bright Yellow |
nubrightorange |
255 197 32 |
#FFC520 |
Bright Orange |
nubrightred |
239 85 63 |
#EF553F |
Bright Red |
nudarkgreen |
0 134 86 |
#008656 |
Dark Green |
nudarkteal |
0 127 164 |
#007FA4 |
Dark Teal |
nudarkblue |
13 45 108 |
#0D2D6C |
Dark Blue |
nudarkyellow |
217 200 38 |
#D9C826 |
Dark Yellow |
nudarkorange |
202 124 27 |
#CA7C1B |
Dark Orange |
nudarkred |
216 88 32 |
#D85820 |
Dark Red |
nurichblack |
0 0 0 |
#000000 |
Rich Black |
Non-NU structural elements (axes, canvas, gridlines, typography) are defined with the wc_ prefix to avoid collisions while maintaining exact alignment with ggplot2:
| Color Name | RGB Values | Hex Code | Purpose / Semantic Role | Relationship to Built-in Stata Colors |
|---|---|---|---|---|
wc_bg |
255 255 255 |
#FFFFFF |
Canvas and background fill | Identical to white / gs16 (255 255 255) |
wc_axis |
204 204 204 |
#CCCCCC |
Subtle X-axis baseline and tick marks | Closely approximates gs13 (208 208 208) |
wc_grid |
234 234 234 |
#EAEAEA |
Light horizontal gridlines | Closely approximates dimgray (232 232 232) and gs15 (240 240 240) |
wc_title |
34 34 34 |
#222222 |
Dark charcoal for headings and axis titles | Closely approximates gs2 (32 32 32) |
wc_body |
102 102 102 |
#666666 |
Muted gray for subtitles, captions, ticks, notes | Closely approximates gs6 (96 96 96) |
[!TIP] Native Stata Color Referencing: With the installed color style files, colors can be referenced directly in any graph command, including alpha/opacity modifiers:
twoway (scatter mpg weight, mcolor(nupurple) mlcolor(nudarkorange)) /// (line yhat weight, lcolor(nupurple%80) lwidth(medthick)), /// yline(0, lcolor(wc_axis) lpattern(dash))
Mapped for maximum contrast and accessibility across discrete series (with Dark Orange #2):
plot1: nupurple (#4E2A84)plot2: nudarkorange (#CA7C1B)plot3: nubrightblue (#5091CD)plot4: nudarkgreen (#008656)plot5: nubrightorange (#FFC520)plot6: nubrightteal (#7FCECD)plot7: nubrightred (#EF553F)plot8: nudarkblue (#0D2D6C)plot9: nudarkteal (#007FA4)plot10: nubrightgreen (#58B9AB)plot11: nudarkyellow (#D9C826)plot12: nupurple50 (#9380C0)All three environments (R ggplot2, Python matplotlib, and Stata) share a synchronized typographic hierarchy based on Arial (arial.ttf / arialbd.ttf):
| UI / Graph Element | R (ggplot2) |
Python (matplotlib / theme_wildcat) |
Stata (scheme-wildcat) |
Weight / Face | Points (at base=11) | Color (Hex / Alias) |
|---|---|---|---|---|---|---|
| Main Title | plot.title (rel(1.30)) |
axes.titlesize / labs(title=...) |
heading, title("{bf:...}") |
Bold (700) | ~14.3 pt | #222222 (wc_title) |
| Subtitle | plot.subtitle (rel(0.98)) |
labs(subtitle=...) |
subheading, size(small) |
Plain (400) | ~10.8 pt | #666666 (wc_body) |
| Axis Titles | axis.title.x, .y (rel(0.95)) |
axes.labelsize / labs(x=..., y=...) |
axis_title, size(small) |
Plain (400) | ~10.5 pt | #222222 (wc_title) |
| Axis Tick Numbers | axis.text.x, .y (rel(0.85)) |
xtick.labelsize, ytick.labelsize |
tick_label, size(small) |
Plain (400) | ~9.35 pt | #666666 (wc_body) |
| Legend Title | legend.title (rel(0.90)) |
legend.title_fontsize |
legend_title |
Bold (700) | ~9.9 pt | #222222 (wc_title) |
| Legend Items | legend.text (rel(0.85)) |
legend.fontsize / legend_top() |
key_label, size(small) |
Plain (400) | ~9.35 pt | #666666 (wc_body) |
| Facet Titles | strip.text.x, .y (rel(1.05)) |
Subplot title / suptitle | bylabel, size(medium) |
Bold (700) | ~11.55 pt | #222222 (wc_title) |
| Footnotes / Caption | plot.caption (rel(0.82)) |
labs(caption=...) |
note / caption, size(2.4) |
Plain (400) | ~9.0 pt | #666666 (wc_body) |
Arial, with Helvetica and DejaVu Sans fallbacks).11 o'clock in Stata, legend.position = "top" in R, legend_top() in Python).#EAEAEA) and light X-axis baselines (#CCCCCC).wc_grid (#EAEAEA / 234 234 234).wc_axis (#CCCCCC / 204 204 204).11 o'clock in Stata, top-left horizontal in R and Python), spanning horizontally to flush with the left plot boundary.ggplot2.circle) with standard sizing (~1.04% of graph height), matching ggplot2 geom_point() defaults without external dependencies.wc_title), and embedded directly within the themes.bar_gap 100pct in Stata) and box gap (box_gap 75pct) yielding refined, balanced widths matching ggplot2 defaults without per-graph overrides.[!TIP] For automated editing or programmatic reconfiguration by AI coding agents, refer to
FOR_AGENTS.mdwhich details exact regex patterns and code blocks for theme customization.
The repository includes a modular generator script, stata/make_scheme.do, allowing anyone to easily build their own custom Stata scheme (e.g., for another university, company, research lab, or personal preference).
At the top of stata/make_scheme.do, a dedicated User Configuration & Customization Section allows quick modifications:
* ------------------------------------------------------------------------------
* USER CONFIGURATION & CUSTOMIZATION SECTION
* ------------------------------------------------------------------------------
local scheme_name "wildcat" // Scheme identifier: compiles scheme-`scheme_name'.scheme
local scheme_title "Wildcat" // Descriptive title for display
local make_color_styles 1 // 1 = write color-*.style files to root, 0 = skip
* Un-comment this block and swap out names to define your own custom colors:
/*
local custom_color_1 "0 0 0" // Swap out custom name and RGB values (e.g., "myblue" "0 51 102")
local custom_colors custom_color_1 // Triggers color style file generation (color-*.style) in Section 5
*/
local scheme_name "wildcat" to your preferred identifier (e.g., local scheme_name "mytheme").local mycrimson "165 28 48"
local mygold "255 199 44"
local custom_colors mycrimson mygold
color1 through color12 with your custom color locals.do stata/make_scheme.do in Stata. The compiled scheme-<scheme_name>.scheme and all corresponding color-*.style files will be generated immediately.To install your custom scheme locally via Stata’s net install:
* 1. Tell Stata to read from your local folder:
net from "C:/path/to/mytheme_pkg"
* 2. Inspect and install:
net describe mytheme
net install mytheme, replace
* 3. Verify and activate:
set scheme mytheme, permanently
Alternatively, copy scheme-<scheme_name>.scheme and color-*.style files directly into your Stata PERSONAL directory (sysdir in Stata resolves the path).
ggplot2) ThemeIn r/theme_wildcat.R:
wildcat_colors:
wildcat_colors <- c(
...,
mycrimson = "#A51C30",
mygold = "#FFC72C"
)
wildcat_palettes$default with your custom color vector.theme_wildcat(base_size = 12) or adjust element settings using standard ggplot2 syntax.matplotlib) ThemeIn py/theme_wildcat.py:
wildcat_colors:
wildcat_colors["mycrimson"] = "#A51C30"
wildcat_colors["mygold"] = "#FFC72C"
wildcat_palettes["default"] or register custom palettes.get_wildcat_rcparams() or at runtime via set_theme(base_size=12.0).Run the full validation suite across all 16 supported chart types:
tests/test_stata_plots.doRscript tests/test_r_plots.Rpython tests/test_py_plots.pypowershell -ExecutionPolicy Bypass -File latex/update.ps1 to compile latex/presentation.pdf.powershell -ExecutionPolicy Bypass -File latex/update_py_r.ps1 to compile latex/presentation_py_r.pdf.FOR_AGENTS.md) — Targeted instructions for AI coding agents to automate theme usage, downloads, and custom rebuilds.