# Author: Simon-Pierre Boucher — contact@spboucher.ai """Paths and global constants for the WP9 pipeline. All paths are relative to the repository root, so the pipeline runs on any machine after cloning. Override the root with the ``WP9_ROOT`` environment variable if the scripts are launched from elsewhere. """ import os from pathlib import Path ROOT = Path(os.environ.get("WP9_ROOT", Path(__file__).resolve().parents[2])) RAW_DB = ROOT / "data" / "raw" / "realtor_mls_unique.duckdb" PROCESSED = ROOT / "data" / "processed" ANALYSIS_PARQUET = PROCESSED / "analysis.parquet" FIGURES = ROOT / "figures" RESULTS = ROOT / "results" REFERENCE = RESULTS / "reference" # original (canonical) outputs — paper numbers REPRODUCED = RESULTS / "reproduced" # outputs regenerated by this pipeline TABLES = RESULTS / "tables" # Unit conversions (as documented in the paper's data section) SQFT_TO_M2 = 0.0929023 ACRE_TO_M2 = 4046.86 HA_TO_M2 = 10_000.0 # Sample construction TRIM_LO, TRIM_HI = 0.01, 0.99 # 1% tails of price and living area FSA_MIN_LISTINGS = 25 # FSAs below this are pooled into _other LOT_TAIL_Q = 0.99 # positive lot areas above this quantile set to 0 (unparseable/exotic) # Structural regressors used in every specification STRUCT = ["ln_living", "bedrooms", "bathrooms", "half_baths", "parking_n", "stories_n", "has_lot", "ln_lot"] # Random seeds (identical to the original analysis scripts) SEED_OOS = 12345 SEED_MORAN = 3 SEED_EXT2 = 7 # Nine major metropolitan centres for the urban-gradient analysis METROS = { "Toronto": (43.65, -79.38), "Montreal": (45.50, -73.57), "Vancouver": (49.28, -123.12), "Calgary": (51.05, -114.07), "Ottawa-Gatineau": (45.42, -75.70), "Edmonton": (53.55, -113.49), "Winnipeg": (49.90, -97.14), "Quebec City": (46.81, -71.21), "Halifax": (44.65, -63.58), } def ensure_dirs() -> None: """Create every output directory the pipeline writes to.""" for p in (PROCESSED, FIGURES, REFERENCE, REPRODUCED, TABLES): p.mkdir(parents=True, exist_ok=True)