Skip to content

Commit 3bd5e8d

Browse files
committed
add descriptions
1 parent bd5b202 commit 3bd5e8d

File tree

2 files changed

+34
-125
lines changed

2 files changed

+34
-125
lines changed

docs/source/notebooks/index.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
On this page you can find a gallery of example notebooks that demonstrate the use of CausalPy.
44

55
## ANCOVA
6+
7+
Analysis of covariance is a simple linear model, typically with one continuous predictor (the covariate) and a categorical variable (which may correspond to treatment or control group). In the context of this package, ANCOVA could be useful in pre-post treatment designs, either with or without random assignment. This is similar to the approach of difference in differences, but only applicable with a single pre and post treatment measure.
8+
69
::::{grid} 1 2 3 3
710
:gutter: 3
811

@@ -15,6 +18,9 @@ On this page you can find a gallery of example notebooks that demonstrate the us
1518
::::
1619

1720
## Difference in Differences
21+
22+
Analysis where the treatment effect is estimated as a difference between treatment conditions in the differences between pre-treatment to post treatment observations.
23+
1824
::::{grid} 1 2 3 3
1925
:gutter: 3
2026

@@ -39,6 +45,9 @@ On this page you can find a gallery of example notebooks that demonstrate the us
3945
::::
4046

4147
## Geographical lift testing
48+
49+
Geolift (geographical lift testing) is a method for measuring the causal impact of interventions in geographic regions. It combines synthetic control methods with difference-in-differences approaches to estimate treatment effects when interventions are applied to specific geographic areas.
50+
4251
::::{grid} 1 2 3 3
4352
:gutter: 3
4453

@@ -57,6 +66,9 @@ On this page you can find a gallery of example notebooks that demonstrate the us
5766
::::
5867

5968
## Instrumental Variables Regression
69+
70+
A quasi-experimental design to estimate a treatment effect where there is a risk of confounding between the treatment and the outcome due to endogeneity. Instrumental variables help identify causal effects by using variables that affect treatment assignment but not the outcome directly.
71+
6072
::::{grid} 1 2 3 3
6173
:gutter: 3
6274

@@ -75,6 +87,9 @@ On this page you can find a gallery of example notebooks that demonstrate the us
7587
::::
7688

7789
## Interrupted Time Series
90+
91+
A quasi-experimental design that uses time series methods to generate counterfactuals and estimate treatment effects. A series of observations are collected before and after a treatment, and the pre-treatment trend (or any time-series model) is used to predict what would have happened in the absence of treatment.
92+
7893
::::{grid} 1 2 3 3
7994
:gutter: 3
8095

@@ -99,6 +114,9 @@ On this page you can find a gallery of example notebooks that demonstrate the us
99114
::::
100115

101116
## Inverse Propensity Score Weighting
117+
118+
A method for estimating causal effects by weighting observations by the inverse of their probability of receiving treatment (propensity score). This helps adjust for confounding by creating a pseudo-population where treatment assignment is independent of observed covariates.
119+
102120
::::{grid} 1 2 3 3
103121
:gutter: 3
104122

@@ -117,6 +135,9 @@ On this page you can find a gallery of example notebooks that demonstrate the us
117135
::::
118136

119137
## Regression Discontinuity
138+
139+
A quasi-experimental design where treatment assignment is determined by a cutoff point along a running variable (e.g., test score, age, income). The treatment effect is estimated by comparing outcomes just above and below the cutoff, assuming units near the cutoff are similar except for treatment status.
140+
120141
::::{grid} 1 2 3 3
121142
:gutter: 3
122143

@@ -147,6 +168,9 @@ On this page you can find a gallery of example notebooks that demonstrate the us
147168
::::
148169

149170
## Regression Kink Design
171+
172+
A variation of regression discontinuity where treatment affects the slope (rate of change) of the outcome with respect to the running variable, rather than causing a discrete jump. The treatment effect is identified by a change in the slope at the cutoff point.
173+
150174
::::{grid} 1 2 3 3
151175
:gutter: 3
152176

@@ -159,6 +183,9 @@ On this page you can find a gallery of example notebooks that demonstrate the us
159183
::::
160184

161185
## Synthetic Control
186+
187+
The synthetic control method is a statistical method used to evaluate the effect of an intervention in comparative case studies. It involves the construction of a weighted combination of groups used as controls, to which the treatment group is compared.
188+
162189
::::{grid} 1 2 3 3
163190
:gutter: 3
164191

scripts/generate_gallery.py

Lines changed: 7 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
#!/usr/bin/env python3
22
"""
3-
Generate example gallery for CausalPy documentation.
3+
Generate thumbnails for CausalPy documentation gallery.
44
5-
This script scans notebooks in docs/source/notebooks/, extracts metadata,
6-
generates thumbnails from the first plot in each notebook, and creates
7-
a gallery page using sphinx-design cards.
5+
This script scans notebooks in docs/source/notebooks/ and generates
6+
thumbnails from the first plot in each notebook. The index.md file
7+
should be maintained manually.
88
"""
99

1010
import base64
1111
import io
12-
import re
1312
import sys
1413
from pathlib import Path
1514

@@ -29,65 +28,6 @@
2928
Image = None # type: ignore[assignment,misc]
3029

3130

32-
def load_categories_from_index(index_path: Path) -> dict[str, list[str]]:
33-
"""
34-
Load category structure from existing index.md.
35-
36-
Reads the markdown file and extracts:
37-
- Category names from ## headers
38-
- Notebook names from :link: fields under each category
39-
40-
Returns
41-
-------
42-
dict[str, list[str]]
43-
Mapping from category name to list of notebook names (without .ipynb)
44-
"""
45-
if not index_path.exists():
46-
return {}
47-
48-
try:
49-
categories: dict[str, list[str]] = {}
50-
current_category = None
51-
for line in index_path.read_text(encoding="utf-8").splitlines():
52-
if line.startswith("## "):
53-
current_category = line[3:].strip()
54-
if current_category and current_category != "Example Gallery":
55-
categories[current_category] = []
56-
elif current_category and (match := re.search(r":link:\s+(\S+)", line)):
57-
categories[current_category].append(match.group(1))
58-
return categories
59-
except Exception as e:
60-
print(f"Warning: Could not load categories from {index_path}: {e}")
61-
return {}
62-
63-
64-
def get_notebook_category(filename: str, category_mapping: dict[str, list[str]]) -> str:
65-
"""Determine the category for a notebook from the loaded mapping."""
66-
notebook_name = filename.replace(".ipynb", "")
67-
return next(
68-
(
69-
cat
70-
for cat, notebooks in category_mapping.items()
71-
if notebook_name in notebooks
72-
),
73-
"Other",
74-
)
75-
76-
77-
def extract_metadata(notebook_path: Path) -> str:
78-
"""Extract title from notebook."""
79-
nb = nbformat.reads(notebook_path.read_text(encoding="utf-8"), as_version=4)
80-
81-
# Look for title in first markdown cell
82-
for cell in nb.cells:
83-
if cell.cell_type == "markdown":
84-
if match := re.search(r"^#+\s+(.+)$", cell.source.strip(), re.MULTILINE):
85-
return match.group(1).strip()
86-
87-
# Fallback to filename-based title
88-
return notebook_path.stem.replace("_", " ").title()
89-
90-
9131
def _find_image_in_notebook(nb) -> str | None:
9232
"""Find first PNG image in notebook outputs."""
9333
for cell in nb.cells:
@@ -161,60 +101,16 @@ def _save_thumbnail(
161101
return None
162102

163103

164-
def generate_gallery_markdown(
165-
notebooks_data: list[dict],
166-
output_path: Path,
167-
category_mapping: dict[str, list[str]],
168-
):
169-
"""Generate gallery markdown file with sphinx-design cards."""
170-
# Group notebooks by category
171-
categories: dict[str, list[dict]] = {}
172-
for nb_data in notebooks_data:
173-
categories.setdefault(nb_data["category"], []).append(nb_data)
174-
175-
# Sort categories alphabetically
176-
sorted_categories = sorted(categories.keys())
177-
178-
# Generate markdown
179-
lines = ["# Example Gallery\n"]
180-
181-
for category in sorted_categories:
182-
notebooks = sorted(categories[category], key=lambda x: x["filename"])
183-
184-
lines.extend([f"## {category}\n", "::::{grid} 1 2 3 3\n", ":gutter: 3\n\n"])
185-
186-
for nb in notebooks:
187-
doc_name = nb["filename"].replace(".ipynb", "")
188-
card_lines = [
189-
f":::{'{grid-item-card}'} {nb['title']}\n",
190-
":class-card: sd-card-h-100\n",
191-
]
192-
if nb.get("thumbnail"):
193-
card_lines.append(f":img-top: {nb['thumbnail']}\n")
194-
card_lines.extend([f":link: {doc_name}\n", ":link-type: doc\n", ":::\n"])
195-
lines.extend(card_lines)
196-
197-
lines.append("::::\n\n")
198-
199-
output_path.write_text("".join(lines), encoding="utf-8")
200-
201-
202104
def main():
203-
"""Main function to generate gallery."""
105+
"""Main function to generate thumbnails only."""
204106
# Paths
205107
repo_root = Path(__file__).parent.parent
206108
notebooks_dir = repo_root / "docs" / "source" / "notebooks"
207109
thumbnails_dir = repo_root / "docs" / "source" / "_static" / "thumbnails"
208-
output_file = notebooks_dir / "index.md"
209110

210111
# Create thumbnails directory
211112
thumbnails_dir.mkdir(parents=True, exist_ok=True)
212113

213-
# Load category structure from existing index.md
214-
category_mapping = load_categories_from_index(output_file)
215-
if category_mapping:
216-
print(f"Loaded {len(category_mapping)} categories from index.md")
217-
218114
# Find all notebooks
219115
notebook_files = sorted(notebooks_dir.glob("*.ipynb"))
220116

@@ -224,25 +120,11 @@ def main():
224120

225121
print(f"Found {len(notebook_files)} notebooks")
226122

227-
# Process each notebook
228-
notebooks_data = []
123+
# Process each notebook to generate thumbnails
229124
for nb_path in notebook_files:
230125
print(f"Processing {nb_path.name}...")
126+
extract_first_image(nb_path, thumbnails_dir)
231127

232-
notebooks_data.append(
233-
{
234-
"filename": nb_path.name,
235-
"title": extract_metadata(nb_path),
236-
"category": get_notebook_category(nb_path.name, category_mapping),
237-
"thumbnail": extract_first_image(nb_path, thumbnails_dir),
238-
}
239-
)
240-
241-
# Generate gallery markdown
242-
print("Generating gallery markdown...")
243-
generate_gallery_markdown(notebooks_data, output_file, category_mapping)
244-
245-
print(f"Gallery generated successfully at {output_file}")
246128
print(f"Thumbnails saved to {thumbnails_dir}")
247129

248130

0 commit comments

Comments
 (0)