Skip to content

Commit a65ad8a

Browse files
authored
Merge pull request #18 from arfc/osier_chapter
Osier chapter
2 parents cb5905d + fe4215c commit a65ad8a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+56210
-40850
lines changed

.github/workflows/CI.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ jobs:
2727
steps:
2828
# Checkout the repository
2929
- name: Checkout repository
30-
uses: actions/checkout@v3
30+
uses: actions/checkout@v4
3131

3232
- name: Create environment with Mamba
3333
uses: conda-incubator/setup-miniconda@v2
@@ -82,7 +82,7 @@ jobs:
8282
8383
# Upload the generated PDF as an artifact
8484
- name: Upload PDF artifact
85-
uses: actions/upload-artifact@v3
85+
uses: actions/upload-artifact@v4
8686
with:
8787
name: 2025-dotson-thesis
8888
path: docs/2025-dotson-thesis.pdf

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,4 @@ data/benchmark/data/*
3535
docs/_minted-thesis
3636
pres/_minted-arfc-pres
3737
_minted-*
38+
figure-log.txt

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,14 @@ cd analysis
4848
snakemake --cores=1
4949
```
5050

51+
> [!NOTE]
52+
> _Why use `snakemake` to build the dissertation when there is already a `Make` file in the `docs` directory?_
53+
>
54+
> Primarily because Windows _can't execute `make`_. There are additional
55+
> advantages as well. `snakemake` is arguably easier to understand and produces
56+
> a nice DAG model of the workflow itself.
57+
>
58+
5159
# Compiling the dissertation
5260

5361
If you only want to reproduce the document itself without running any analysis,

analysis/Snakefile

Lines changed: 57 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ latexopt = """
88
"""
99

1010
docs_path = "../docs/"
11+
figure_log = "figures.log"
1112

1213
with open(f"{docs_path}Makefile", "r") as file:
1314
lines = file.readlines()
@@ -18,16 +19,35 @@ output_name = lines[0].strip('\n').replace(' ', '').split('=')[-1]
1819
rule targets:
1920
input:
2021
thesis = f"{docs_path}{output_name}.pdf",
21-
dag = "dag.png"
22+
dag = "dag.png",
23+
24+
rule collect_figures:
25+
input:
26+
social_max_plot = f"{docs_path}figures/social_max.pgf",
27+
elasticity_plot = f"{docs_path}figures/elasticity.pgf",
28+
example_pareto_plot = f"{docs_path}figures/truss2d_pareto.pgf",
29+
near_optimal_plot = f"{docs_path}figures/near-optimal-pareto.pgf",
30+
interior_points_plot = f"{docs_path}figures/nd-mga-paretofront.pgf",
31+
pareto_3d = f"{docs_path}figures/3d-mga-paretofront.pgf",
32+
example_mga_plot = f"{docs_path}figures/mga-fft-example.pgf",
33+
output:
34+
log = figure_log
35+
shell:
36+
"""
37+
for file in {input}; do
38+
echo $file >> {output.log}
39+
done
40+
"""
2241

2342
if sys.platform == 'Windows':
2443
rule build_thesis:
2544
input:
26-
main_tex = f"{docs_path}{output_name}.tex"
45+
main_tex = f"{docs_path}{output_name}.tex",
46+
log = figure_log
2747
output: f"{docs_path}{output_name}.pdf"
2848
shell:
2949
f"""
30-
cd ../docs && \
50+
cd {docs_path} && \
3151
pdflatex {latexopt} {output_name}.tex && \
3252
biber {output_name} && \
3353
pdflatex {latexopt} {output_name}.tex && \
@@ -36,7 +56,8 @@ if sys.platform == 'Windows':
3656
elif sys.platform in ['darwin', 'linux']:
3757
rule build_thesis:
3858
input:
39-
main_tex = f"{docs_path}{output_name}.tex"
59+
main_tex = f"{docs_path}{output_name}.tex",
60+
log = figure_log
4061
output: f"{docs_path}{output_name}.pdf"
4162
shell:
4263
f"""
@@ -48,4 +69,35 @@ rule build_dag:
4869
output:
4970
"dag.png"
5071
shell:
51-
"snakemake --dag | dot -Tpng > {output}"
72+
"snakemake --dag | dot -Tpng > {output}"
73+
74+
75+
rule plot_social_welfare_max:
76+
input: "scripts/social_welfare_maximization.py"
77+
output:
78+
social_max_plot = f"{docs_path}figures/social_max.pgf",
79+
elasticity_plot = f"{docs_path}figures/elasticity.pgf"
80+
script: f"{input}"
81+
82+
83+
rule plot_example_fronts:
84+
input: "scripts/pareto_front.py"
85+
output:
86+
example_pareto_plot = f"{docs_path}figures/truss2d_pareto.pgf",
87+
interior_points_plot = f"{docs_path}figures/nd-mga-paretofront.pgf",
88+
near_optimal_plot = f"{docs_path}figures/near-optimal-pareto.pgf"
89+
script: f"{input}"
90+
91+
92+
rule plot_mga_example:
93+
input: "scripts/mga_fft_example.py"
94+
output:
95+
example_mga_plot = f"{docs_path}figures/mga-fft-example.pgf",
96+
script: f"{input}"
97+
98+
99+
rule plot_3d_fronts:
100+
input: "scripts/pareto_3D.py"
101+
output:
102+
pareto_3d = f"{docs_path}figures/3d-mga-paretofront.pgf"
103+
script: f"{input}"

analysis/dag.png

16.3 KB
Loading

analysis/methods_figures/pareto-front.ipynb

Lines changed: 7 additions & 308 deletions
Large diffs are not rendered by default.

analysis/methods_figures/social_welfare_maximization.ipynb

Lines changed: 0 additions & 293 deletions
This file was deleted.
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "code",
5+
"execution_count": 5,
6+
"metadata": {},
7+
"outputs": [
8+
{
9+
"data": {
10+
"text/plain": [
11+
"True"
12+
]
13+
},
14+
"execution_count": 5,
15+
"metadata": {},
16+
"output_type": "execute_result"
17+
}
18+
],
19+
"source": [
20+
"import requests\n",
21+
"import matplotlib.pyplot as plt\n",
22+
"import json\n",
23+
"import numpy as np\n",
24+
"import pandas as pd\n",
25+
"import geopandas as gpd\n",
26+
"import us\n",
27+
"import os\n",
28+
"from dotenv import load_dotenv\n",
29+
"\n",
30+
"load_dotenv(\"../../.env\")"
31+
]
32+
},
33+
{
34+
"cell_type": "code",
35+
"execution_count": 7,
36+
"metadata": {},
37+
"outputs": [],
38+
"source": [
39+
"eia_key = os.environ['EIA_API_KEY']"
40+
]
41+
},
42+
{
43+
"attachments": {},
44+
"cell_type": "markdown",
45+
"metadata": {},
46+
"source": [
47+
"# Access power plant data"
48+
]
49+
},
50+
{
51+
"cell_type": "code",
52+
"execution_count": 4,
53+
"metadata": {},
54+
"outputs": [],
55+
"source": [
56+
"params = {\n",
57+
" \"frequency\": \"monthly\",\n",
58+
" \"data\": [\n",
59+
" \"latitude\",\n",
60+
" \"longitude\",\n",
61+
" \"nameplate-capacity-mw\",\n",
62+
" \"operating-year-month\"\n",
63+
" ],\n",
64+
" \"facets\": {\n",
65+
" \"energy_source_code\": [\n",
66+
" \"BIT\",\n",
67+
" \"SUB\"\n",
68+
" ]\n",
69+
" },\n",
70+
" \"start\": \"2024-09\",\n",
71+
" \"end\": None,\n",
72+
" \"sort\": [\n",
73+
" {\n",
74+
" \"column\": \"period\",\n",
75+
" \"direction\": \"desc\"\n",
76+
" }\n",
77+
" ],\n",
78+
" \"offset\": 0,\n",
79+
" \"length\": 5000\n",
80+
"}"
81+
]
82+
},
83+
{
84+
"cell_type": "code",
85+
"execution_count": 8,
86+
"metadata": {},
87+
"outputs": [],
88+
"source": [
89+
"BASE_URL = \"https://api.eia.gov/v2/\"\n",
90+
"\n",
91+
"dataset = \"electricity/operating-generator-capacity\"\n",
92+
"route = dataset + \"/data\""
93+
]
94+
},
95+
{
96+
"cell_type": "code",
97+
"execution_count": 10,
98+
"metadata": {},
99+
"outputs": [],
100+
"source": [
101+
"headers = {\n",
102+
" \"X-Api-Key\": eia_key,\n",
103+
" \"X-Params\": json.dumps(params),\n",
104+
" }"
105+
]
106+
},
107+
{
108+
"cell_type": "code",
109+
"execution_count": 11,
110+
"metadata": {},
111+
"outputs": [],
112+
"source": [
113+
"r = requests.get(BASE_URL+route, headers=headers)"
114+
]
115+
},
116+
{
117+
"cell_type": "code",
118+
"execution_count": 14,
119+
"metadata": {},
120+
"outputs": [
121+
{
122+
"name": "stdout",
123+
"output_type": "stream",
124+
"text": [
125+
"Total records: 428\n"
126+
]
127+
}
128+
],
129+
"source": [
130+
"response = r.json()['response']\n",
131+
"\n",
132+
"print(f\"Total records: {response['total']}\")\n",
133+
"\n",
134+
"data = response['data']\n",
135+
"\n",
136+
"df = pd.DataFrame(data)\n",
137+
"df.drop(columns=['stateName','sector','sectorName','entityid',\n",
138+
" 'balancing-authority-name','statusDescription', \n",
139+
" 'entityName','nameplate-capacity-mw-units',\n",
140+
" 'energy_source_code','generatorid','status',\n",
141+
" 'unit', 'period'\n",
142+
" ],\n",
143+
" inplace=True)"
144+
]
145+
},
146+
{
147+
"cell_type": "code",
148+
"execution_count": 18,
149+
"metadata": {},
150+
"outputs": [],
151+
"source": [
152+
"df['nameplate-capacity-mw'] = df['nameplate-capacity-mw'].astype('float')"
153+
]
154+
},
155+
{
156+
"cell_type": "code",
157+
"execution_count": 25,
158+
"metadata": {},
159+
"outputs": [],
160+
"source": [
161+
"df = df.pivot_table(index=['stateid','plantid','balancing_authority_code','latitude','longitude'],\n",
162+
" columns=['technology'],\n",
163+
" values=['nameplate-capacity-mw']).reset_index(drop=False)"
164+
]
165+
},
166+
{
167+
"cell_type": "code",
168+
"execution_count": null,
169+
"metadata": {},
170+
"outputs": [],
171+
"source": []
172+
}
173+
],
174+
"metadata": {
175+
"kernelspec": {
176+
"display_name": "thesis",
177+
"language": "python",
178+
"name": "python3"
179+
},
180+
"language_info": {
181+
"codemirror_mode": {
182+
"name": "ipython",
183+
"version": 3
184+
},
185+
"file_extension": ".py",
186+
"mimetype": "text/x-python",
187+
"name": "python",
188+
"nbconvert_exporter": "python",
189+
"pygments_lexer": "ipython3",
190+
"version": "3.11.10"
191+
},
192+
"orig_nbformat": 4
193+
},
194+
"nbformat": 4,
195+
"nbformat_minor": 2
196+
}

0 commit comments

Comments
 (0)