Skip to content

Fix/pipeline audit - #44

Open
Ruphai wants to merge 100 commits into
mainfrom
fix/pipeline-audit
Open

Fix/pipeline audit#44
Ruphai wants to merge 100 commits into
mainfrom
fix/pipeline-audit

Conversation

@Ruphai

@Ruphai Ruphai commented Jul 7, 2026

Copy link
Copy Markdown
Collaborator

add recent changes and additional sensitivity analysis

CGevaert and others added 30 commits July 2, 2026 17:36
…otebook updates

- notebooks/98_visual_inspection.ipynb: new notebook for systematic visual QA of
  reference vs. Overture footprints across all study areas; saves one PNG per city
  with AOI boundary, reference (red) and Overture (blue) footprint overlays; flags
  cities with missing data, low F1, or load errors; outputs _overview.csv summary

- scripts/export_tile_geojson.py: standalone script to export per-tile vector
  validation metrics to GeoJSON (per city), combined GeoPackage (all cities), and
  flat CSV with derived ref_building_density_per_km2 and ref_avg_building_size_m2

- notebooks/04_wsf_year_sensitivity.ipynb: Cell 6 removes kaleido/static PNG export,
  temporal gap figure restricted to non-SpaceNet7 cities; Cell 7 correlations
  restricted to cities shared across all datasets, SpaceNet7 excluded from temporal
  gap; Section 3 adds is_spacenet7 flag and precision/recall delta columns vs
  baseline; summary cell synthesises findings from all three sections

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds CartoDB Positron basemap tiles via contextily to each city figure,
making spatial offsets between reference and Overture footprints immediately
visible against real-world geography. Falls back silently if contextily is
not installed or Colab is offline. Swap BASEMAP_SOURCE to
ctx.providers.Esri.WorldImagery for satellite imagery.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Insert !pip install -q contextily as first code cell so Colab users
  don't need to pre-install manually
- Change BASEMAP_SOURCE default from CartoDB.Positron to
  ctx.providers.Esri.WorldImagery (satellite) so spatial offsets are
  immediately visible against real-world imagery
- Update comment and helper cell print to reflect the new default

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ef_building_area_m2 to tile metrics (centroid-based)
…gs at 50k

- Add try/finally block so aoi, ref, overture and fig are always deleted
  and gc.collect() is called after every city regardless of success/error
- Sample ref and overture to MAX_BUILDINGS=50_000 before reprojecting;
  large cities (Cairo, Shanghai) were accumulating hundreds of MB per iter
- Add import gc and MAX_BUILDINGS config constant to imports cell

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Notebook 07 uses only matplotlib — no basemap needed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Previous fix sampled after loading — peak RAM still hit during load for
cities like Cairo (2M+ buildings with all attribute columns). This fix:
- Reads parquet with columns=['geometry'] only (skips all attributes)
- Applies rows=MAX_BUILDINGS cap at gpd.read_file() time for other formats
- Replaces unary_union extent computation with total_bounds (no geometry merge)
- Removes post-load sampling block from the main loop (now redundant)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…nostic

- load_reference now falls back to globbing the city's vector/ dir when
  ref_spec is None (e.g. tracker ref col not detected or col name mismatch)
- Config cell now prints all tracker columns so detection can be verified
- Matches the fallback logic already used in 98_visual_inspection.ipynb

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace the ad-hoc tracker lookup + glob fallback with a direct call to
load_validation_datasets() from src/utils/aoi_inventory.py — the same
function the pipeline uses to find reference files. Builds ref_map once
in the config cell; loop uses ref_map.get(city) to get paths.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ef files

load_validation_datasets() skips cities whose AOI files are missing on
disk (data cleaned up after pipeline run), leaving 84 of 136 cities out
of ref_map. Two changes:

1. Read tracker directly to build ref_map — only reference file paths
   are needed for enrichment, so the AOI existence check is irrelevant.

2. Fallback path for cities where ref files are also missing: derive
   tile_area_km2 from tile GPKG + approximate ref_building_count_centroid
   and mean_ref_building_area_m2 from n_ref / ref_area_total_m2 already
   in the sentinel parquet. These rows are labelled [intersection approx].

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace tracker-CSV-based ref_map with find_ref_files() which globs
the city vector/ directory and excludes known candidate dataset files
(overture, gba, globfp). Finds reference files like ayabak_WBG.geojson
and curacao_hotosm.geojson regardless of naming convention, without
depending on the tracker ref column being populated.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Mixed EPSG:4326 / EPSG:3857 ref files (e.g. uga-kampala combining
hotosm + SN7 geojsons) caused a ValueError on pd.concat. Reproject
all files to the first file CRS before merging.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Scans data/01_raw/ and outputs/metrics/ to build a city x dataset
coverage table. Flags cities where candidate input parquets exist but
validation sentinel is missing. Re-runs pipeline for flagged cities
(overwrite=False), verifies tiles GPKG, and regenerates
vector_all_cities_merged.xlsx from all per-city summaries.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Spearman correlation, Kruskal-Wallis + Dunn post-hoc, box plots, scatter
plots, and linear mixed-effects model (city random intercept), all broken
out by candidate dataset (Overture, GBA, GlobFP).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Ten data quality flags (EMPTY_TILE, TINY_BUILDINGS, HUGE_BUILDINGS,
EXTREME_DENSITY, EDGE_TILE, ALL_ZERO_F1, NEAR_PERFECT_F1, EXTREME_BIAS,
DUPLICATE_ROW, HIGH_DATASET_DIVERGENCE) plus city-level COUNT_MISMATCH.
Exports sanity_flags.csv with a decision column for manual triage before
running notebook 09 statistical analysis.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Applies known-good decisions automatically (EMPTY_TILE→exclude,
HIGH_DATASET_DIVERGENCE/ALL_ZERO_F1/NEAR_PERFECT_F1→ok), then prints
the city × flag breakdown for flags that still need a human call
(EXTREME_BIAS, EXTREME_DENSITY, HUGE/TINY_BUILDINGS).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Restructures notebook 09 around reusable helper functions so all
analyses (Spearman, KW+Dunn, box plot, scatter, LME) run identically
for three subsets (all / SpaceNet / non-SpaceNet) and for both vector
and raster candidates. Reference source is detected from the AOI tracker
CSV; raster density is joined from the vector enriched CSV by tile_id.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…arate notebook

Adds apply_quality_filters() to cell 1 (called immediately after load for
vector, and after density join for raster). Removes DUPLICATE_ROW, EMPTY_TILE,
EDGE_TILE, TINY/HUGE_BUILDINGS, ALL_ZERO_F1, and LOW_DENSITY_CITY (<5 bldg/km²)
automatically before any analysis runs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Collects Spearman ρ, KW, and LME results for all groups (all / spacenet /
non-spacenet) and both vector and raster into a structured markdown file
saved to outputs/scratch/nb09_analysis_summary.md. Includes data coverage,
quality filters applied, quartile boundaries, results tables, and caveats
for interpretation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ame fallback

Cell 2 now reads the explicit reference_source column added by the
aoi_tracker update script (spacenet / other). Falls back to filename
heuristic with a warning if the column is absent.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
tracker_path now derives from PROJECT_ROOT directly; cfg is only used
as an optional override if present. Fixes NameError when kernel restarts
between cells.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Reads tracker with utf-8-sig to strip BOM characters written by Excel/
Windows. Normalises column names more aggressively. Adds path/shape/column
diagnostics to cell 2 output to make future mismatches easier to debug.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
sorted() on grid column fails when some rows have NaN. Drop NaN before
sorting and cast to str to handle any mixed-type grid column.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Rename YAML key tau_overlap → iou_threshold (backward-compat fallback kept in
  vector_runner.py via .get("iou_threshold", .get("tau_overlap", 0.5)))
- Add notebooks/10_iou_threshold_sensitivity.ipynb: diagnostic tool that
  computes city-level F1 at τ=0.25 (lower bound), τ=0.50 (exact), τ=0.75 (exact)
  using stored tile-metrics and match parquets; outputs boxplot + CSV

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
notebooks/11_buffer_sensitivity.ipynb re-runs tile-level IoU matching
at tau_buffer_m=0 and tau_buffer_m=current (2 m) for all enriched cities,
producing a comparison table + box plots (F1 with/without buffer, delta,
scatter) and outputs/scratch/buffer_sensitivity.csv.

Also includes a graceful fallback that shows the stored match IoU
distribution when raw building files are unavailable on Drive, so the
notebook is still informative without a full re-run.

Buffer in the production pipeline is unchanged.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
CGevaert and others added 19 commits July 20, 2026 15:08
Add a cell at the end (before the summary) with two grouped box plots from the
tile-level per_tile_enriched_all_cities.csv: tile F1 by reference-building
density quartile (D1) and by mean building-size quartile (D2), one box per
vector dataset, boxmean on. This brings the density/size drivers analysis (from
nb06) into the presentation deck. Adds both to the figure summary list.

Includes the user's prior in-notebook edits (raster F1-by-source cell, donut/box
revisions). Read/written via ReadAllText so no mojibake; outputs cleared for a
clean artifact (regenerated on next run).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Reconcile the raster section after the working-copy edits:
- R4 (10m vs 100m resolution comparison) was dropped but still listed in the
  summary; restore the cell (recovered from a55b8db) after R3.
- the added raster "F1 by reference source" figure saved R2_f1_by_source.png,
  colliding with the R2 wins label; rename it to R5 (figure, fig var, header)
  and add it to the summary.

Raster figures are now consecutive R1-R5. Read/written via ReadAllText (no
mojibake); outputs cleared.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…oad)

04 writes vector_all_cities_merged.xlsx via df_vec.to_excel(...) with no
sheet_name, so the sheet is the pandas default "Sheet1". nb95's Section 2 read
it with sheet_name="vector_all_cities_merged" -> ValueError: Worksheet named
'vector_all_cities_merged' not found, which aborted the cell before sn7_cities
was defined and blocked Section 3 (the temporal-alignment CSV that feeds nb07 W2).

- nb95: read sheet_name=0 (first sheet), robust to whatever the file is named.
- nb04: pass sheet_name="vector_all_cities_merged" on export so future files are
  self-documenting.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ile data

D1/D2 (vector): transpose to quartile-on-X with one colour per dataset, so the
density/size effect reads as a left-to-right trend (was dataset-on-X with
quartile shades, which buried it). Drop the 12 floating median annotations
(fragile manual offsets, clutter) - boxmean + the box already show mean/median.
Quartile labels now carry the value ranges. Shared _f1_box_by_quartile helper.

D3/D4 (raster): the old cells read per_tile_enriched (VECTOR-only: no raster
rows, no grid column) so they always produced empty plots. Load the per-city
raster_metrics_tiles_all_datasets.parquet files (which hold raster per-tile F1)
and join tile density/size from per_tile_enriched on (city, tile_id), mirroring
nb06. Now plots F1 by quartile per raster ds_key.

Also remove the duplicate summary cell (kept the updated one listing D1-D4).
Read/written via ReadAllText; outputs cleared.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The vector 'gba' dataset is the Global Building Atlas; it was mislabeled
"Google Open Buildings" in the DATASET_LABELS dicts of nb06/07/90/91 (07 also
had a stale comment). Corrected all of them.

Left untouched: the RASTER obt_2023 dataset genuinely IS Google Open Buildings
(Temporal), so src/download/raster.py, src/downloader.py, and the README raster
list are correct as-is. Also documented the full name in the data dictionary.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Per request, flip the density/size box plots so X = dataset and the four
quartiles sit side-by-side within each dataset (Q1..Q4, light->dark), making the
density/size effect on each dataset directly comparable. Quartile legend entries
now carry the value range + unit, e.g. "Q1: <50 bldg/km2", "Q4: >180 m2".
Shared _f1_box_grouped + _q4_ranges helpers; raster loader unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Cell 5 already reads SpaceNet membership from the tracker's reference_source
column (with a filename fallback), but the summary generator (cell 7) still
hardcoded misleading/outdated text. Fix:
- SpaceNet note now says membership is read from the reference_source column
  (the same column that drives the per-city IoU threshold), not the filename.
- retitle "Notebook 09" -> "Notebook 06", source 09_density_f1_analysis ->
  06_analysis_density_f1, output nb09_analysis_summary.md -> nb06_...
- replace the stale "~65 cities missing / ~70 covered" caveat with the current
  coverage (~135 vector / ~133 raster after the full rerun).

GBA label already corrected in 627c011. No logic change; re-run nb06 to
regenerate the summary with these fixes and the up-to-date data.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace hardcoded personal Google Drive paths with configurable,
repository-relative defaults so the pipeline runs without editing
institution-specific locations.

- configs/data_configs.yaml: base_dir, output.root_dir, wsf_tracker.drive_root
  now relative to the project root (with "set this" comments)
- configs/validation_configs.yaml: root_dir defaults to "." (project root)
- main.py: --project-root defaults to the current directory
- src/utils/sn7_utils.py: neutralize example Drive paths in docstring/help text

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- .gitignore: ignore data/ and outputs/ (user-generated), .env / *.env,
  configs/local_*.yaml, .ipynb_checkpoints/, *.pyc, build artifacts,
  and OS/editor/tooling dirs (.DS_Store, .vscode, .idea, .claude)
- requirements.txt: pip alternative to environment.yaml; covers all
  imported third-party packages (geospatial, plotting, stats, IO) with
  major-version pins on the geospatial stack

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Clear saved cell outputs from pipeline/analysis notebooks (nbconvert
  --clear-output); nb04 drops from ~2 MB to ~50 KB and loses a stale
  KeyError traceback. Report notebooks 07/90/91 keep their canonical
  embedded figures.
- Neutralize org-identifying Colab Drive paths in 16 notebooks
  (WorldBank/FY26 - DEP / Gates Foundation -> /content/drive/MyDrive/urban_validation).
- Remove dead cells (commented-out rasterio/glob exploration in nb02) and
  scratch/debug cells (!pwd in nb00; bare-variable re-displays in nb01/nb02).
- Fix nb01's stale header ("# 03 Validation" -> proper "01 Vector Validation"
  header with purpose/inputs/outputs/run-order).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- README: fix stale notebook names (01_vector_validator ->
  01_validate_vector, 02_raster_validator -> 02_validate_raster)
- README: fill the empty reference-data link with benchmark sources;
  add a candidate-datasets table (source URLs + licences, licences to confirm)
- README: add a "Notebook workflow (run order)" table describing what each
  notebook produces; document `pip install -r requirements.txt` alongside conda
- CITATION.cff: minimal citation metadata (authors, year, repo URL, MIT)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Add one-line docstrings to 47 functions/methods and 4 module docstrings
  that were missing them (no logic changes).
- Flag 5 unused imports with "# UNUSED" for author confirmation
  (downloader.Path, output.matplotlib, visualize plugins, base.Optional/log_memory)
  rather than deleting.
- Remove an unreachable `if False` tooltip branch in plots/visualize.py.
- Flag the never-called _iou_with_buffer helper for author confirmation.

All tracked .py verified with py_compile (grufs env): clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Add src/plots/style.py as the single source of truth for plot styling:
  canonical DATASET_COLORS / DATASET_LABELS (a superset covering every key
  spelling used by the notebooks — "@10m", "_10m", and base names) plus
  apply_ppt_style_mpl and apply_ppt_style_plotly.
- Delete the now-confirmed unused imports (downloader.Path, output.matplotlib,
  visualize folium plugins, base.Optional/log_memory) and the dead
  _iou_with_buffer helper.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- nb06/07/90/91/95 now import DATASET_COLORS / DATASET_LABELS / apply_ppt_style
  from src.plots.style instead of each defining their own copy. nb95's palette
  is harmonized to the canonical colours; nb90/91 Plotly styling aligns to
  nb07's. Re-run these in Colab to re-render figures with the shared palette.
- Every notebook now has a standardized header cell (title, purpose, inputs,
  outputs, run order, and a last-run placeholder).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Every figure now writes a vector .svg alongside the .png, and PNGs export
  at scale=3 (was 2) — fixes blur / pixelation on the slide deck.
- Box-plot central-tendency labels made consistent on the median:
  V1 now labels "Median: …" (was Mean); V2 label removed (too crowded);
  R5 shows the bare median value (was mean). All boxes keep boxmean=True
  so both the median (solid) and mean (dashed) lines still render.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
`ifrom google.colab import drive` -> `from ...`. Predates the cleanup
(present since before b1d3f22); would break the mount cell on a fresh run.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…artiles)

Replace the per-subset, data-driven quartile breaks (which differed between
the vector and raster figure families and made them incomparable) with fixed
canonical classes applied identically everywhere:

  DENSITY_BREAKS = [0, 20, 100, 300, inf]  ('<20','20–100','100–300','>300')
  SIZE_BREAKS    = [0, 80, 120, 180, inf]  ('<80 m²','80–120 m²','120–180 m²','>180 m²')

- Constants defined once near the top of each notebook (alongside DATASET_COLORS).
- All tile binning now uses pd.cut(x, BREAKS, labels=LABELS) — nb06 f1_by_*_class
  box plots + KW/Dunn tests + summary boundary tables; nb07 D1–D4 (_class_bin
  replaces the qcut-based _q4_ranges).
- Kruskal–Wallis / Dunn now run across the fixed classes; summary tables and the
  boundary tables/axis/legend/file labels renamed quartile/Q1–Q4 -> class.
- nb06 files f1_by_density_quartile_* -> f1_by_density_class_* (and size).
- Old data-driven approach kept in `# superseded 2026-07-22` comments for provenance.
- LME (continuous z-scored) and Spearman (continuous) left unchanged, as required;
  caveat added flagging the sparse <20 class at city level.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The canonical DENSITY_LABELS are bare numbers, so the density unit now lives
in the legend title (matching nb06's "Density class (bldg/km²)" axis label).
Size labels already carry m² per label.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Centralizing plot style added `from src.plots.style import …` to these
notebooks, but none ran colab_bootstrap first, so `src` was not on sys.path
(ModuleNotFoundError on a fresh Colab run).

- nb07, nb95 (mount Drive): mount + colab_bootstrap.setup(PROJECT_ROOT), as in nb06.
- nb90, nb91 (upload-based, no Drive): lightweight `git clone` of the repo onto
  sys.path (/content/repo) before the src import.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Ruphai
Ruphai marked this pull request as ready for review July 27, 2026 15:45
Ruphai and others added 10 commits July 27, 2026 11:57
merge new changes to dev branches
New raster-section cell (after R5) — R6_quantity_vs_allocation: horizontal
stacked bars of the Pontius quantity vs allocation disagreement, median across
cities, per dataset@grid (100 m group, visual separator, then 10 m group; grids
not pooled). Quantity segment in the dataset's DATASET_COLORS colour, allocation
in neutral grey (#8A8A96), with each bar's quantity share annotated ("96%
amount"). Tile-equal (unweighted) means, consistent with f1_tile_mean — the
*_weighted_mean variants are deliberately not used.

Exports 16:9 (1280x720) + square (1080x1080) PNGs for slide 11 / report §2.4,
prints a QD/AD/share cross-check table, and adds a paste-ready caption cell.
Code only — not executed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Every figure now saves from the same figure object as .pdf (vector, for the
Overleaf/LaTeX report) and .png (for Docs/PowerPoint), via a single save_fig()
helper in each notebook's setup cell:
- nb07 (Plotly): save_fig -> write_image .pdf + .png (scale=3). 21 call sites
  (V1-V8, R1-R6, S1-S2, W1-W2, D1-D4 box helper). R6 keeps its 16:9 and square
  variants (square gets a PDF alongside the PNG).
- nb06 (matplotlib): save_fig -> fig.savefig .pdf + .png at dpi=300 (was 150).

The redundant .svg exports are dropped (PDF supersedes them for LaTeX); the only
raw write_image/savefig calls now live inside save_fig itself. Filenames and
figure content/size unchanged. Code only — not executed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Re-runs only the vector IoU matching (reusing src.load_buildings / make_tiles /
subset_by_tile / match_buildings_iou at each city's τ) and keeps every
building's area_m2 with its class (TP/FP/FN) — the pipeline discards FP/FN sizes.

- SAMPLE_MODE toggle (default on: ~12 cities) so it can be test-run before a full
  sweep; MIN_AREA_M2 knob to probe sub-20 m² micro-polygons.
- Persists a 10 m² histogram CSV (fp_size_hist.csv, re-aggregatable) + optional
  per-building parquet + a median/size-share summary.
- Analysis: pooled median/p25/p75 and %<40/<60/<80 per class, plus an ECDF of
  FP vs TP candidate area per dataset. Writes to outputs/ablation_fp_size/
  (separate dir; zero pipeline impact). Code only — not executed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…cumulative OOM)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…FP & FN) + TP/FP count bars

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…csv exists

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ook colours)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…h nb07)

- save_fig now writes to outputs/figures/ (shared with nb07 report figures);
  data CSV/parquet stay in outputs/ablation_fp_size/
- apply_ppt_style_mpl + Barlow font registration on all three figures
- suptitles set to Barlow for a consistent look

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants