Spaces:
Running on Zero
Running on Zero
| """ | |
| Downloads BD Charm-50 (BRGM's harmonized 1:50,000 geological maps) for | |
| the departments covering the Eure/Risle study area. | |
| CONFIRMED (via data.gouv.fr / InfoTerre): free, open (Licence Ouverte), | |
| no authentication -- direct per-department ZIP download from InfoTerre. | |
| This is a genuinely different access pattern than the WFS sources | |
| elsewhere in this project (BD TOPO, BDCavités): no bbox query, no axis- | |
| order ambiguity, just a fixed URL per department. Real, working URL | |
| pattern (found directly, not guessed): | |
| http://infoterre.brgm.fr/telechargements/BDCharm50/GEO050K_HARM_XXX.zip | |
| where XXX is the 3-digit department code (e.g. 027 for Eure). | |
| NOTE: a separate, DIFFERENT distribution of this same underlying dataset | |
| exists that requires CIGAL network membership (seen for at least Alsace | |
| regional data) -- that is NOT what this script uses. This script only | |
| uses the free InfoTerre download confirmed via data.gouv.fr. | |
| DEPARTMENTS: 27 (Eure), 61 (Orne), 28 (Eure-et-Loir) -- 27 and 61 | |
| confirmed directly from real INSEE codes seen in this project's own | |
| station_list.csv (61342, 27040, 27116, 27468); 28 included because the | |
| Eure's own southern tributaries (Voise, Drouette) run through Chartres/ | |
| Dreux, unambiguously in Eure-et-Loir. Add more department codes via | |
| --departments if the real geographic extent turns out to need them. | |
| Usage: | |
| python -m scripts.download_bdcharm50 | |
| """ | |
| import argparse | |
| import zipfile | |
| from pathlib import Path | |
| import requests | |
| DEFAULT_DEPARTMENTS = ["027", "028", "061"] | |
| BASE_URL = "http://infoterre.brgm.fr/telechargements/BDCharm50" | |
| def download_department(dept: str, output_dir: Path) -> bool: | |
| url = f"{BASE_URL}/GEO050K_HARM_{dept}.zip" | |
| zip_path = output_dir / f"GEO050K_HARM_{dept}.zip" | |
| print(f" department {dept}: {url}") | |
| try: | |
| resp = requests.get(url, timeout=120, stream=True) | |
| except requests.RequestException as e: | |
| print(f" FAILED: {e}") | |
| return False | |
| if resp.status_code != 200: | |
| print(f" FAILED: HTTP {resp.status_code}") | |
| return False | |
| content_type = resp.headers.get("Content-Type", "") | |
| if "zip" not in content_type and "octet-stream" not in content_type: | |
| # A 200 status with an HTML content-type here usually means an | |
| # error page or a "department not available" page was returned | |
| # instead of the real ZIP -- catching this explicitly rather | |
| # than silently saving an HTML file with a .zip extension. | |
| print(f" WARNING: Content-Type is {content_type!r}, not zip -- " | |
| f"this department's file may not exist at this URL. Saving " | |
| f"anyway for inspection, but verify before trusting it.") | |
| zip_path.write_bytes(resp.content) | |
| size_kb = zip_path.stat().st_size / 1024 | |
| print(f" saved {zip_path} ({size_kb:.0f} KB)") | |
| extract_dir = output_dir / f"dept_{dept}" | |
| try: | |
| with zipfile.ZipFile(zip_path) as zf: | |
| zf.extractall(extract_dir) | |
| shp_files = list(extract_dir.rglob("*.shp")) | |
| print(f" extracted to {extract_dir} ({len(shp_files)} .shp file(s) found)") | |
| return True | |
| except zipfile.BadZipFile: | |
| print(f" FAILED: downloaded file is not a valid zip -- likely an error page, " | |
| f"not real data. Check {zip_path} directly.") | |
| return False | |
| def main() -> None: | |
| parser = argparse.ArgumentParser(description="Download BD Charm-50 geological maps") | |
| parser.add_argument("--departments", nargs="+", default=DEFAULT_DEPARTMENTS, | |
| help="3-digit department codes, e.g. 027 028 061") | |
| parser.add_argument("--output-dir", type=Path, default=Path("datasets/bdcharm50")) | |
| args = parser.parse_args() | |
| args.output_dir.mkdir(parents=True, exist_ok=True) | |
| print(f"Downloading BD Charm-50 for departments: {args.departments}") | |
| print() | |
| results = {} | |
| for dept in args.departments: | |
| results[dept] = download_department(dept, args.output_dir) | |
| print() | |
| print("=" * 60) | |
| ok = [d for d, r in results.items() if r] | |
| failed = [d for d, r in results.items() if not r] | |
| print(f"Succeeded: {ok}") | |
| if failed: | |
| print(f"Failed: {failed} -- check the URL pattern still matches by visiting " | |
| f"https://infoterre.brgm.fr/page/telechargement-cartes-geologiques directly") | |
| if __name__ == "__main__": | |
| main() |