diff --git a/.gitattributes b/.gitattributes index 833788583edb84d91b020995e84578a6cbb4e15c..c2f074340b722519f777f04954dc4e53a0f360c0 100644 --- a/.gitattributes +++ b/.gitattributes @@ -187,3 +187,29 @@ datasets/draft/era5_2009.nc filter=lfs diff=lfs merge=lfs -text datasets/draft/era5_2010.nc filter=lfs diff=lfs merge=lfs -text datasets/draft/era5_2011.nc filter=lfs diff=lfs merge=lfs -text datasets/draft/era5_2012.nc filter=lfs diff=lfs merge=lfs -text +datasets/bdcavites/cavite_localisee.geojson filter=lfs diff=lfs merge=lfs -text +datasets/bdcharm50/dept_027/Descriptif[[:space:]]des[[:space:]]cartes[[:space:]]géologiques[[:space:]]à[[:space:]]1_50[[:space:]]000[[:space:]]vecteur.pdf filter=lfs diff=lfs merge=lfs -text +datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_FGEOL_2154.dbf filter=lfs diff=lfs merge=lfs -text +datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_FGEOL_2154.shp filter=lfs diff=lfs merge=lfs -text +datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_FGEOL_2154.shx filter=lfs diff=lfs merge=lfs -text +datasets/bdcharm50/dept_027/GEO050K_HARM_027_P_DIVERS_2154.dbf filter=lfs diff=lfs merge=lfs -text +datasets/bdcharm50/dept_027/GEO050K_HARM_027_P_DIVERS_2154.shp filter=lfs diff=lfs merge=lfs -text +datasets/bdcharm50/dept_027/GEO050K_HARM_027_S_FGEOL_2154.dbf filter=lfs diff=lfs merge=lfs -text +datasets/bdcharm50/dept_027/GEO050K_HARM_027_S_FGEOL_2154.lyr filter=lfs diff=lfs merge=lfs -text +datasets/bdcharm50/dept_027/GEO050K_HARM_027_S_FGEOL_2154.shp filter=lfs diff=lfs merge=lfs -text +datasets/bdcharm50/dept_028/Descriptif[[:space:]]des[[:space:]]cartes[[:space:]]géologiques[[:space:]]à[[:space:]]1_50[[:space:]]000[[:space:]]vecteur.pdf filter=lfs diff=lfs merge=lfs -text +datasets/bdcharm50/dept_028/GEO050K_HARM_028_L_FGEOL_2154.dbf filter=lfs diff=lfs merge=lfs -text +datasets/bdcharm50/dept_028/GEO050K_HARM_028_L_FGEOL_2154.shp filter=lfs diff=lfs merge=lfs -text +datasets/bdcharm50/dept_028/GEO050K_HARM_028_S_FGEOL_2154.dbf filter=lfs diff=lfs merge=lfs -text +datasets/bdcharm50/dept_028/GEO050K_HARM_028_S_FGEOL_2154.shp filter=lfs diff=lfs merge=lfs -text +datasets/bdcharm50/dept_061/Descriptif[[:space:]]des[[:space:]]cartes[[:space:]]géologiques[[:space:]]à[[:space:]]1_50[[:space:]]000[[:space:]]vecteur.pdf filter=lfs diff=lfs merge=lfs -text +datasets/bdcharm50/dept_061/GEO050K_HARM_061_L_FGEOL_2154.dbf filter=lfs diff=lfs merge=lfs -text +datasets/bdcharm50/dept_061/GEO050K_HARM_061_L_FGEOL_2154.shp filter=lfs diff=lfs merge=lfs -text +datasets/bdcharm50/dept_061/GEO050K_HARM_061_L_FGEOL_2154.shx filter=lfs diff=lfs merge=lfs -text +datasets/bdcharm50/dept_061/GEO050K_HARM_061_L_STRUCT_2154.dbf filter=lfs diff=lfs merge=lfs -text +datasets/bdcharm50/dept_061/GEO050K_HARM_061_L_STRUCT_2154.shp filter=lfs diff=lfs merge=lfs -text +datasets/bdcharm50/dept_061/GEO050K_HARM_061_P_DIVERS_2154.dbf filter=lfs diff=lfs merge=lfs -text +datasets/bdcharm50/dept_061/GEO050K_HARM_061_P_STRUCT_2154.dbf filter=lfs diff=lfs merge=lfs -text +datasets/bdcharm50/dept_061/GEO050K_HARM_061_S_FGEOL_2154.dbf filter=lfs diff=lfs merge=lfs -text +datasets/bdcharm50/dept_061/GEO050K_HARM_061_S_FGEOL_2154.lyr filter=lfs diff=lfs merge=lfs -text +datasets/bdcharm50/dept_061/GEO050K_HARM_061_S_FGEOL_2154.shp filter=lfs diff=lfs merge=lfs -text diff --git a/README.md b/README.md index 21edb0babb636cefe7689929519996ef153760c3..42e30bdd74a9a1f514e2367743717de5b094f632 100644 --- a/README.md +++ b/README.md @@ -13,8 +13,10 @@ pinned: true A physics-informed graph neural network that predicts streamflow (discharge, water level) at gauged and ungauged points along two Normandy rivers, La Eure -and La Risle, treated as two separate surface-hydrology graphs with -station-level covariates pulled from half a dozen independent data sources. +and La Risle — each modeled as a real reach-based network (confluences, +braided splits/rejoins, ~4,500 nodes per basin including virtual infill +points), not a single chain of gauges, with covariates pulled from nine +independent data sources. ```mermaid flowchart LR @@ -22,29 +24,31 @@ flowchart LR ades["ADES
groundwater levels"] era5["Copernicus ERA5
climate reanalysis"] otd["Open Topo Data
station elevation"] - brgm["BRGM
IDPR"] - bdtopo["IGN BD TOPO
river centerline geometry"] - - hubeau --> loaders - ades --> loaders - era5 --> loaders - otd --> loaders - brgm --> loaders - bdtopo --> loaders - - loaders["src/data/loaders/"] --> nf["node_features.py
one row per station
inputs kept separate from targets"] - loaders --> bg["build_graph.py
surface edges, ordered by
real river course"] - - nf --> pyg - bg --> pyg["build_pyg_graphs_per_basin"] - - pyg --> eure["La Eure graph"] - pyg --> risle["La Risle graph"] - - eure --> app["src/app.py
Streamlit explorer"] - risle --> app - eure --> testsuite["test_build_graph.py
validation"] - risle --> testsuite + brgm["BRGM
IDPR · BD Charm-50 geology"] + bdtopo["IGN BD TOPO
real reach topology + catchment polygons"] + bdcav["Géorisques
BDCavités (sinkholes)"] + wc["ESA WorldCover
landcover · NDVI"] + + bdtopo --> brg["build_reach_graph.py
real confluences, splits/rejoins,
gauge snapping"] + brg --> brgs["build_reach_graphs.py
~4,500 nodes/basin"] + + hubeau --> nf + ades --> nf + era5 --> nf + otd --> nf + brgm --> nf + bdcav --> nf + wc --> nf + brgs --> nf["node_features.py /
enrich_reach_graph.py
date-filtered 2013-2026"] + + bdtopo --> cc["compute_cumulative_catchment.py
graph-wide catchment area"] + cc --> nf + + nf --> pyg["build_pyg_graph
x_static / x_dynamic split"] + pyg --> phys["physics_losses.py
confluence · split-rejoin ·
routing · water balance"] + + pyg --> app["src/app.py
Streamlit explorer +
network validation view"] + pyg --> testsuite["test_build_graph.py
validation"] ``` --- @@ -53,20 +57,29 @@ flowchart LR ``` PoC_v1/ -├── scripts/ # one-off download / extraction scripts +├── scripts/ # one-off download / extraction / build scripts │ ├── download_hubeau.py # discharge + water level, Hub'Eau API v2 │ ├── download_elevation.py # point elevations, Open Topo Data │ ├── download_era5_sample.py # ERA5 sanity-check pull (Jan 2020 only) │ ├── download_era5_full.py # ERA5 1960–2026, split instant/accum vars │ ├── extract_era5.py # unzips CDS API's zipped NetCDF output -│ ├── download_catchment_area.py # Hub'Eau referentiel/sites -> surface_bv +│ ├── download_catchment.py # Hub'Eau referentiel/sites -> surface_bv │ ├── download_bdtopo_hydro.py # IGN WFS -> tronçons, surfaces, catchments │ ├── analyze_bdtopo_hydro.py # centerline export + karst check │ ├── run_bdtopo_checks.py # karst + catchment cross-check, one shot -│ └── cross_check_catchments.py # spatial join: station -> containing polygon +│ ├── cross_check_catchments.py # spatial join: station -> containing polygon +│ ├── build_reach_graphs.py # real reach-based topology, both basins +│ ├── enrich_reach_graph.py # runs node_features.py against the reach graph +│ ├── compute_cumulative_catchment.py # graph-wide catchment area from BD TOPO polygons +│ ├── diagnose_confluences.py # verify real vs. artifact confluences +│ ├── download_bdcavites.py # Géorisques BDCavités (sinkhole/cavity inventory) +│ ├── download_bdcharm.py # BRGM BD Charm-50 harmonized geology, per department +│ ├── fetch_idpr_brgm.py # (unused — see §3.5) live IDPR re-fetch attempt +│ ├── fetch_landcover.py # ESA WorldCover landcover class, real gauges +│ └── fetch_worldcover_ndvi.py # ESA WorldCover NDVI percentile composite │ ├── src/ -│ ├── app.py # Streamlit river explorer (main UI) +│ ├── app.py # Streamlit river explorer + network validation view │ ├── generate_plots.py # batch plot generation across all loaders │ ├── test_build_graph.py # graph-construction test/validation suite │ ├── extract_river_centerline.py # digitizes a traced map image into a centerline @@ -76,7 +89,7 @@ PoC_v1/ │ │ │ ├── base.py # BaseDataLoader — shared load()/get_metadata() │ │ │ ├── hydrometric.py # discharge & water level (Hub'Eau) │ │ │ ├── ades.py # groundwater levels (ADES) -│ │ │ ├── safran.py # ERA5 reanalysis, interpolated to stations +│ │ │ ├── safran.py # ERA5 reanalysis, vectorized station interpolation │ │ │ ├── idpr.py # infiltration/runoff tendency (BRGM) │ │ │ ├── catchment.py # per-station catchment area (Hub'Eau) │ │ │ ├── bdtopo_hydro.py # IGN BD TOPO hydrography (GeoJSON) @@ -88,8 +101,10 @@ PoC_v1/ │ │ └── river_centerline.py # real-centerline interpolation + gauge snapping │ │ │ └── graph/ -│ ├── build_graph.py # surface edges + PyTorch Geometric conversion -│ └── node_features.py # pulls every loader into one feature table +│ ├── build_graph.py # PyG conversion: x_static/x_dynamic split, structural columns +│ ├── build_reach_graph.py # real reach topology: confluences, splits/rejoins, MultiDiGraph +│ ├── node_features.py # pulls every loader into one feature table +│ └── physics_losses.py # confluence/split-rejoin/routing/water-balance loss terms │ ├── datasets/ # not checked in; populated by the scripts above │ ├── station_list.csv # raw station roster (X, Y, names, INSEE, etc.) @@ -100,10 +115,13 @@ PoC_v1/ │ ├── hydrometric/ │ ├── safran/ │ ├── bdtopo_hydro/ -│ └── centerlines/ +│ ├── bdcavites/ +│ ├── bdcharm50/ +│ ├── centerlines/ +│ └── reach_graph/ # {eure,risle}_{nodes,edges}.csv, _nodes_enriched.csv ``` -`scripts/` talks to the outside world (APIs, WFS); +`scripts/` talks to the outside world (APIs, WFS, S3); `src/` doesn't — nothing under `src/` makes a network call, and a script under `src/` that wants one is a bug. Most of `src/data/loaders/` predates the graph work — general-purpose readers/plotters for each dataset, with @@ -115,82 +133,200 @@ way around. ## 2. The graph This is the part everything else in the repo exists to feed. Two graphs, one -per river — `H4xx…` stations feed the La Eure graph (196 km of real BD TOPO -course), `H6xx…` feed La Risle (150 km) — built with no edge between them, -because there's no surface connection between the two basins to model. +per river — `H4xx…` stations feed the La Eure graph, `H6xx…` feed La Risle — +built with no edge between them, because there's no surface connection +between the two basins to model. -![La Eure and its ADES wells, real BD TOPO course, elevation-colored gauges](docs/images/eure_overview.png) +The graph is now built from **real reach topology**, not a single ordered +chain of gauges. `build_reach_graph.py` constructs it directly from BD TOPO's +own tronçon-to-node linkage (`lien_vers_noeud_hydrographique_ini/fin`) — the +NEXT_DOWN-equivalent approach — rather than inferring station order from +position along a digitized line. That means real branching, real confluences, +and real braided-channel structure fall directly out of the data instead of +needing to be modeled separately. -![La Risle, same view — note the tight cluster of gauges around the karst bétoire stretch](docs/images/risle_full.png) +### 2.1 Node types -### 2.1 Nodes +Four kinds of node, not one: -A node is one hydrometric station. The full feature set, as of the last -`test_build_graph.py` run against real data, is 16 columns wide across all 27 -stations combined (15 per basin, once `basin_id` is dropped — see §2.3): - -| Feature | Source | What it is | +| Type | What it is | Column | |---|---|---| -| `latitude`, `longitude` | `station_elevations.csv` | station coordinates | -| `elevation_m` | Open Topo Data (`scripts/download_elevation.py`) | point elevation at the station | -| `idpr_value` | BRGM IDPR | infiltration-vs-runoff tendency; direct ID join, not interpolated, for this dataset | -| `avg_groundwater_level_m`, `avg_groundwater_depth_m` | ADES, radius-averaged | nearest-well groundwater condition | -| `n_nearby_wells` | ADES | how many wells contributed to the average above — worth checking before trusting the groundwater value, since some stations have zero | -| `climate_temp_C`, `climate_wind_speed_ms`, `climate_solar_Wm2`, `climate_precip_mm`, `climate_evap_mm`, `climate_snow_mm`, `climate_runoff_mm` | ERA5, interpolated to the station point | mean/sum over the record, by variable | -| `avg_groundwater_level_m__was_missing`, `avg_groundwater_depth_m__was_missing`, (and similarly for any other feature with real gaps) | auto-generated | 1 if that station had no data for the column before mean-filling, 0 otherwise | - -`basin_id` is also computed but excluded from each per-basin graph's own -feature set, since it's constant there and would just be a zero-variance -column sitting in `x` for no reason. +| Real gauge | one of the 27 hydrometric stations | `is_gauged` | +| Real confluence | a genuinely different, independently-sourced river joins | `is_confluence` | +| Split / rejoin | a channel divides and later recombines (braiding, an anabranch) — same water, no new mass | `is_split_point` / `is_rejoin_point`, paired via `braid_id` | +| Virtual (infill) | inserted along long confluence-free stretches so "predict at any point" has real spatial resolution | none of the above | + +A **confluence** requires more than a shared node with in-degree ≥ 2 — BD +TOPO's fine tronçon segmentation produces plenty of same-river multi-inflow +points with no real branching involved (confirmed against real data: +incoming-edge distances as short as 4.6 m at some falsely-flagged +"confluences"). The real test (`find_real_confluences` in +`build_reach_graph.py`) requires (a) more than one distinct *normalized* river +name among the incoming edges — river-name normalization strips articles, +parenthetical qualifiers, and "bras de/du/d'" (arm-of) prefixes, since a named +secondary channel of the same river ("Bras de la Charentonne") isn't a +different river — and (b) that those branches don't trace back to a common +upstream **split** within 15 km, which would mean it's a rejoin, not a +confluence. Splits themselves need no such disambiguation: out-degree ≥ 2 is +an unambiguous physical definition on its own, since a split by construction +has exactly one thing flowing in. + +Real branching topology also meant the underlying graph had to move from a +plain `DiGraph` to a `MultiDiGraph` — two distinct tronçons directly +connecting the same two hydrographic nodes (exactly the shape a short braid +takes) is real data, not a collision, and a plain `DiGraph` was silently +**overwriting** the second such edge's data on `add_edge` rather than keeping +both. Confirmed as a real bug with real impact, not just a synthetic-test +concern: fixing it recovered dozens of previously-invisible parallel edges +per basin on the actual data. + +### 2.2 Node and edge features + +The feature set now spans several independent sources, each merged onto the +node table by `node_features.py`'s `add_*_features` functions. Every column +lands in exactly one of four places once `build_pyg_graph` processes it: -**Targets are not features.** `target_discharge_m3s_mean/std/count` and -`target_waterlevel_mm_mean/std/count` exist on the enriched table but never -enter `x` — they're pulled out into `data.y` separately. A model that could -see these as inputs would be reading the answer off the label, not learning -anything. +```mermaid +flowchart TD + raw["Enriched node table
(node_features.py)"] + + raw --> struct{"structural /
graph-role column?"} + struct -->|"is_gauged, is_confluence,
is_split_point, is_rejoin_point,
braid_id, snap_distance_km"| structout["data.is_gauged, data.is_confluence, ...
own Data attribute — never in x"] -**The missingness flags aren't decorative.** A station with zero nearby wells -gets its groundwater value silently filled with the basin mean — without the -flag, that looks identical to a station whose real groundwater level happens -to be close to average. Given how unevenly some of these datasets cover the -two basins (the Eure's southern reach has essentially no ADES wells within -range at all), pretending "filled with the mean" and "actually near the mean" -are the same thing would be a real information loss, not just tidiness. + raw --> tgt{"target_* column?"} + tgt -->|"target_discharge_m3s_*
target_waterlevel_mm_*"| y["data.y
never in x — label leakage otherwise"] -### 2.2 Edges + raw --> feat{"real model input"} + feat -->|"static: elevation_m, idpr_*,
catchment_area_km2, landcover_*,
geology_*, cavites distance/count"| xstatic["data.x_static"] + feat -->|"dynamic: climate_*,
avg_groundwater_*, ndvi_*
(period-aggregate, not a real series yet)"| xdynamic["data.x_dynamic"] -An edge is "these two gauges are consecutive along the river," in the -direction water actually flows — upstream to downstream. Three attributes per -edge: + xstatic --> x["data.x — full combined tensor,
z-scored"] + xdynamic --> x + + edges["Edge table
(build_reach_graph_tables)"] --> eattr{"numeric edge
attribute?"} + eattr -->|"distance_km,
elevation_drop_m,
verified_continuous"| edgeattr["data.edge_attr
[n_edges, 3]"] + eattr -->|"toponym, cleabs
(diagnostic metadata)"| meta["not used by build_pyg_graph —
stays in edges_df only"] +``` + +**Node features:** + +| Feature | Source | Coverage | +|---|---|---| +| `latitude`, `longitude`, `elevation_m` | station coords / real BD TOPO tronçon Z | every node | +| `idpr_value`, `idpr_nearest_point_distance` | BRGM IDPR | every node (spatial fallback for non-gauge codes) | +| `catchment_area_km2` | Hub'Eau, cumulative, real gauges only | 27 stations | +| `cumulative_catchment_area_km2` | BD TOPO incremental polygons, summed upstream via real graph topology | graph-wide (~98% of nodes) | +| `landcover_*` (one-hot) | ESA WorldCover 10 m classification | real gauges only, for now | +| `ndvi_p10`, `ndvi_p50`, `ndvi_p90` | ESA WorldCover NDVI percentile composite | real gauges only, for now | +| `geology_*` (one-hot) | BRGM BD Charm-50, point-in-polygon | real gauges only, for now | +| `distance_to_nearest_cavity_km`, `n_cavities_within_20km` | Géorisques BDCavités, KD-tree + haversine | real gauges only, for now | +| `avg_groundwater_level_m`, `avg_groundwater_depth_m`, `n_nearby_wells` | ADES, radius-averaged, KD-tree + exact haversine | every node | +| `climate_*` (temp/wind/solar/precip/evap/snow/runoff) | ERA5, vectorized station interpolation | every node (needs `safran_path`) | +| `{col}__was_missing` | auto-generated | any feature column with real gaps | + +**Edge features** — three numeric attributes per edge, from +`build_reach_graph.py`'s `build_reach_graph_tables`: | Feature | Meaning | |---|---| -| `distance_km` | along-river distance between the two stations | -| `elevation_drop_m` | elevation difference, upstream minus downstream (should be positive; negative would flag a real problem) | -| `verified_continuous` | `False` for any edge deliberately flagged via `known_losing_reaches` | - -That last one exists because of a specific, real finding: two stations on La -Risle are named *"[amont bétoire]"* and *"[aval bétoire]"* in Hub'Eau's own -data — *bétoire* being the Normandy term for a karst swallow-hole, where a -river can vanish underground and resurface downstream. Three consecutive -edges spanning that stretch (`H605641101 → H605022010 → H605641401 → -H605641201`) are flagged `verified_continuous=False` rather than the graph -silently assuming water flows continuously through a reach that might not -carry it at the surface at all. An edge existing in this graph means "these -stations are sequential along the mapped course," not "surface flow between -them is guaranteed." - -Ordering within a basin comes from the station's position along the real -digitized river course where one's available (both basins now have real BD -TOPO-derived centerlines — see §3.8), falling back to elevation or latitude -otherwise. Every edge is built between *consecutive* stations in that order, -which means each basin is currently a single chain, not a branching network. -Tributaries aren't represented. That's the single biggest structural -simplification in the graph as it stands — see §6. - -![La Risle, position at 50% along its 150 km real course, reading elevation and estimated groundwater level](docs/images/risle_detail.png) - -### 2.3 Two graphs, not one +| `distance_km` | along-river distance between the two endpoint nodes | +| `elevation_drop_m` | elevation difference, upstream minus downstream — negated on the reverse edge when `bidirectional=True` | +| `verified_continuous` | `False` for any edge deliberately flagged via `known_losing_reaches` (the bétoire stretch — §3.7) | + +`toponym` and `cleabs` also live on the real edges table (the tronçon's river +name and unique BD TOPO ID) but are diagnostic metadata, not model input — +`build_pyg_graph` selects `edge_attr` columns by explicit name, so extra +columns like these pass through harmlessly rather than needing to be +stripped out first. + +**Structural columns never enter `x`.** `is_gauged`, `is_confluence`, +`is_split_point`, `is_rejoin_point`, `snap_distance_km`, `braid_id` describe +node *role*, not a physical covariate — `build_pyg_graph`'s auto-detection +excludes them explicitly (confirmed as a real, not hypothetical, bug once: +pandas treats `bool` as a numeric dtype, so without this exclusion these +columns were being silently z-scored and fed to the model as if they were +elevation or precipitation). They're still attached to the returned `Data` +object as their own typed attributes, for masking supervised loss to gauged +nodes and for the physics-loss index builders. + +**Landcover and geology are one-hot, not a raw class code.** Both are +nominal categories (10 = Tree cover, 50 = Built-up; a geological formation +code), not an ordered quantity — leaving either as a raw integer would let +auto-detection z-score it as if one category were numerically "more" than +another, the same class of error as the structural-column bug, just subtler +since these *are* meant to be real model input. + +**Targets are not features.** `target_discharge_m3s_mean/std/count` and +`target_waterlevel_mm_mean/std/count` exist on the enriched table but never +enter `x` — they're pulled out into `data.y` separately, and attach only to +real gauge rows (verified: gauge codes, BD TOPO hydrographic node IDs, and +virtual-node marker strings occupy structurally distinct namespaces, so a +left-merge on `station_code` can never mislabel a confluence or virtual node). + +### 2.3 Static vs. dynamic features + +`build_pyg_graph` also splits every feature by physical temporal nature: + +- **`data.x_static`** / **`data.static_feature_names`** — genuinely + time-invariant: elevation, IDPR, catchment area, landcover, coordinates. +- **`data.x_dynamic`** / **`data.dynamic_feature_names`** — physically + time-varying quantities: climate, groundwater level/depth, NDVI. + +`data.x` remains the full combined tensor unchanged; the split is additional, +not a replacement. **Important limitation, stated plainly**: "dynamic" here +still means *one period-aggregated number per node* (mean/sum over the whole +date range, or a single well reading), not a real `[n_nodes, T]` time series. +The split makes the physical distinction explicit and gives a clean seam for +a future temporal pipeline to slot into, but building that pipeline — genuine +daily/whatever-resolution series per node, aligned across sources — is +separate, larger, unbuilt work. `physics_losses.py`'s `routing_consistency_loss` +specifically needs that real time dimension and has nothing to consume yet. + +### 2.4 Date-range filtering + +`build_node_features`/`enrich_reach_graph.py` accept a `date_range` applied +to every time-varying source (groundwater, climate, hydrometric targets) +together, so all three describe the same period rather than each silently +aggregating over its own full, differently-shaped history (ADES wells +reporting from the 1970s to 2026 on wildly different schedules; ERA5 spanning +1960–2026; hydrometric records with their own per-station ranges entirely). + +Default: **2013-01-01 to 2026-12-31** — computed, not guessed, via a +brute-force interval-overlap check across all 8 discharge-gauged stations' +real date ranges. This is the window that maximizes simultaneous station +coverage: 6 of 8 stations, **8,923 real, quality-filtered observations** +(`code_qualification >= 16`, the same threshold `HydrometricLoader` itself +applies — a naive raw count that skips this filter gives 13,084, which is +what an earlier pass at this analysis originally reported before the +discrepancy was traced and corrected). Two stations (`H403301101`: 1969–1985, +`H605022010`: 1970–1980) are permanently excluded by any reasonable window — +a ~35–40 year dead gap separates them from every other station's record, so +including them would mean spanning six mostly-empty decades, not a genuine +improvement. + +### 2.5 Physics-informed loss terms (`physics_losses.py`) + +Four constraints, each tied to real graph structure, not generic: + +| Term | Constraint | Applies to | +|---|---|---| +| `confluence_mass_balance_loss` | `Q_confluence ≈ sum(Q_upstream_branches)` — new mass genuinely enters | `is_confluence` nodes | +| `split_rejoin_conservation_loss` | `Q_split ≈ Q_rejoin` — same water, no new mass | paired `braid_id` nodes | +| `routing_consistency_loss` | `Q_downstream[t] ≈ Q_upstream[t - lag]`, lag from real `distance_km`/slope | every edge (needs `[n_nodes, T]` — see §2.3) | +| `water_balance_loss` | `P - ET - Q - ΔS ≈ 0` in volume terms | nodes with `cumulative_catchment_area_km2` | + +Confluence and split/rejoin are deliberately different constraints, not one +generic "conserve mass everywhere" rule — a model that only learned "sum the +inflows" would get a split/rejoin wrong, since a rejoin's two branches +together should equal the *split's* value, not add something new on top. +All four apply graph-wide, not just at the 27 labeled gauges — that's the +actual mechanism by which sparse supervision generalizes to the ~4,500 +ungauged nodes, not an incidental detail. `ΔS` (storage change) defaults to +zero, a named steady-state approximation — this project has no direct +basin-wide storage measurement, only sparse well *levels*, which aren't the +same thing. + +### 2.6 Two graphs, not one `build_pyg_graphs_per_basin()` returns `{0: eure_graph, 1: risle_graph}`, each with its own local `0..n-1` node indexing, rather than one merged `Data` @@ -200,26 +336,15 @@ PyTorch Geometric's own batching (`Batch.from_data_list`) expects a list of separate small graphs — building two graphs from the start matches that convention directly. -### 2.4 What actually goes into `x` +### 2.7 What it looks like -`build_pyg_graph()` auto-detects feature columns from whatever table it's -given, so it works whether that's the plain 4-column base table or the fully -enriched one. Every column gets z-scored (mean 0, unit variance — verified in -`test_build_graph.py`, including a check that this used the same `ddof=1` -convention as the pandas `.std()` call that actually does the standardizing, -since numpy's default `ddof=0` gives a spuriously "wrong-looking" answer for -small station counts that isn't actually a bug). Missingness flags, described -above, get appended after standardization so they stay honest 0/1 values -rather than being z-scored into something less interpretable. - -### 2.5 What it looks like - -The Streamlit explorer (`src/app.py`) renders both graphs directly — real -course geometry, gauges colored by elevation, ADES wells layered underneath -for context. Clicking anywhere on the line resolves to the nearest gauge and -pulls up its actual discharge/water-level/rating-curve plots: - -![Clicking along La Risle resolves to the nearest gauge (H605022010, 1.7 km away) and shows its real water level record back to 1972](docs/images/station_timeseries.png) +The Streamlit explorer (`src/app.py`) has two views. "Explore" renders the +original click-to-read interface over real course geometry. "Network +validation" renders the full reach graph — confluences as diamonds, gauges as +elevation-colored circles, every edge as one line trace regardless of edge +count (verified fast at real scale: 0.29s to build a figure for ~2,900 +edges) — specifically for visually confirming the topology looks like a real +river network before trusting it as model input. --- @@ -230,18 +355,20 @@ materially affect what the data means. ### 3.1 Station roster (`station_list.csv`, `station_elevations.csv`) -27 stations across the two basins, split roughly by Hub'Eau code prefix -(`H4xx…` for La Eure, `H6xx…` for La Risle — this is a heuristic based on -observed codes, not a documented rule, so it's worth re-checking if new -stations show up outside that pattern). Elevation comes from Open Topo Data's +27 stations across the two basins, spanning three French departments — +verified directly against the real roster: 12 in Eure (27), 10 in +Eure-et-Loir (28, the Eure's southern tributaries near Chartres/Dreux — Voise, +Drouette, and others), 2 in Orne (61). Split roughly by Hub'Eau code prefix +(`H4xx…` for La Eure, `H6xx…` for La Risle — a heuristic based on observed +codes, not a documented rule). Elevation comes from Open Topo Data's `eudem25m` endpoint (`scripts/download_elevation.py`), queried per station -coordinate — it's a point lookup, not a raster, so there's no slope or -catchment information hiding in it. +coordinate — a point lookup, not a raster, so there's no slope or catchment +information hiding in it. The row order in `station_list.csv` does **not** follow the river's course — verified directly, it jumps around in both latitude and elevation. Anything that needs upstream/downstream ordering has to derive it from elevation, -latitude, or real centerline position; never from file order. +latitude, or real centerline/graph position; never from file order. Not every station in this list is actively gauged. Cross-referencing station names against the hydrometric data turned up three categories worth knowing @@ -255,9 +382,10 @@ about: - Everything else with no data is unexplained from the name alone and worth a direct check on Hub'Eau's site before assuming it's just a gap. -In total, **14 of the 27 stations have no discharge or water-level records at -all** in the current Hub'Eau export. That's not a bug in the loader — it's -confirmed against the raw files, not just the merged table. +Of the 8 stations with any `QmnJ` discharge data at all, only **6 have real +observations within the project's 2013–2026 date window** (§2.4) — worth +knowing before assuming "8 gauged stations" translates directly into training +examples. ### 3.2 Hydrometric data (`hydrometric/`, via `scripts/download_hubeau.py`) @@ -269,6 +397,15 @@ has `HIXnJ`/`HIXM` (water-level codes) sitting right alongside `QmnJ` down to its intended `grandeur` code explicitly (`QmnJ` from the discharge file, `HIXnJ` from the water-level file) rather than trusting the filename. +`HydrometricLoader` also filters on Hub'Eau's own `code_qualification` field, +keeping only `>= 16` (their "acceptable"/"good" threshold) and dropping lower- +quality/provisional readings. This is real and meaningful, not a rounding +detail — traced directly against the raw discharge file for the 2013–2026 +window (§2.4): 13,084 raw `QmnJ` rows in range, of which 4,022 have +`code_qualification == 12` (below the threshold) and get correctly excluded, +leaving 8,923. Any manual read of the raw CSVs that skips this filter will +overcount real usable observations by close to a third. + Only 8 of the 27 stations have any `QmnJ` (daily mean discharge) rows at all. Several others report water level only. This isn't evenly distributed and matters a lot for anything downstream that assumes "gauged" means "has both @@ -283,18 +420,28 @@ merges the levels file against the stations file on `code_bss` and renames `x`/`y` to `lon`/`lat` — those columns are already in degrees in this dataset, not a projected CRS, so no reprojection happens or is needed. -Groundwater is used as a **station-level input covariate** (radius-averaged via -`aggregate_to_stations`), not as a graph edge. Well proximity alone isn't -sufficient grounds for a subsurface/karst connectivity edge between the two -basins — two wells being close together doesn't mean they're hydraulically -connected. That would need either correlated well hydrographs over time or a -shared BDLISA aquifer-unit code (the `groundwater_stations.csv` file has a -`codes_bdlisa` column available for exactly this kind of check). +`node_features.py`'s `add_groundwater_features` does **not** use +`ADESLoader.aggregate_to_stations` — that method loops per station and does a +full haversine `.apply()` over the entire groundwater dataframe for each one. +At 27 stations against ~272k readings that's slow but tolerable; at the reach +graph's ~4,500 nodes it's over a billion row-wise Python calls, confirmed as a +genuine, not hypothetical, multi-hour hang. The fix (reduce to each well's +latest reading first, then a KD-tree coarse prefilter + exact haversine on the +small candidate set) turned out to also fix a real accuracy bug: the old +method required wells to share the *exact same reporting date* before +averaging, but real wells report on wildly different schedules (18 real +wells within 20 km of one station spanned 13 different "latest dates," one +from 1972) — silently discarding most real coverage every time. + +Groundwater is used as a **station-level input covariate**, not as a graph +edge. Well proximity alone isn't sufficient grounds for a subsurface/karst +connectivity edge — that would need either correlated well hydrographs over +time or a shared BDLISA aquifer-unit code (`groundwater_stations.csv` has a +`codes_bdlisa` column available for exactly this kind of check; still unused). Well coverage is not uniform across the two basins. The Eure's southern reach (south of roughly 48.68°N, toward Chartres) has essentially zero wells within -range in this extract — any groundwater estimate south of there will come back -empty, and that's a property of the source data, not a bug in the interpolation. +range in this extract. ### 3.4 Climate (`safran/`, via `download_era5_sample.py` / `download_era5_full.py`) @@ -305,107 +452,203 @@ instantaneous variables (temperature, wind) from accumulated ones (precipitation, evaporation, radiation, snowfall, runoff) at the API level — `download_era5_full.py` downloads each set separately per year and merges them, because the CDS API rejects mixed requests. The full pull spans 1960–2026 and -is genuinely slow (a `time.sleep` and per-year retry loop is in there for a -reason). +is genuinely slow. -`SAFRANLoader` interpolates the ERA5 grid to each station's coordinate -(nearest or linear, configurable) rather than requiring stations to sit -exactly on a grid cell — this is standard practice for reanalysis data at -0.25° resolution, not an approximation specific to this project. +`SAFRANLoader` interpolates the ERA5 grid to every station **in one +vectorized xarray call per file**, not one `.sel()` + `.to_dataframe()` call +per station — the per-station loop version does real per-call work (an index +lookup, then a full DataFrame conversion) that's tolerable at 27 stations +(~1,800 calls across ~67 year-files) but was confirmed to actually hang at the +reach graph's ~4,500 nodes (~193,000 calls). Vectorized indexing with +DataArray indexers sharing a `station` dimension does every station in one +call per file instead. ### 3.5 IDPR (`idpr.csv`) BRGM's *Indice de Développement et de Persistance des Réseaux* — an infiltration-vs-runoff tendency index, and the closest thing this project has -to a real soil/drainage covariate. The actual file used here is already -one row per station (`station_id` matching `station_code` exactly, verified -1:1 against all 27 stations, no duplicates, no nulls), not a raw spatial point -cloud. `node_features.py` checks for this and does a direct ID join when -possible rather than nearest-neighbor search — nearest-neighbor is only the -fallback path for a generic IDPR export that doesn't come pre-matched to -stations. - -There is no soil texture, permeability, or hydraulic conductivity dataset in -this project. IDPR is a tendency index, not a texture measurement — worth -keeping that distinction in mind if it ever gets described as "soil data" in a -writeup. - -### 3.6 Catchment area (`catchment_area.csv`, via `scripts/download_catchment_area.py`) - -Hub'Eau publishes catchment (drainage basin) area on the **site** referentiel, -not the station referentiel — `surface_bv` on `hydrometrie/referentiel/sites`, -in km². Since one site can have several stations, the download script does two -passes: station → `code_site`, then `code_site` → `surface_bv`, and joins them -back. 16 of 27 stations have a value; Hub'Eau simply doesn't publish this field -for every site, and the missing ones correlate with the observer/SEBV stations -from §3.1 but aren't identical to that set. - +to a real soil/drainage covariate (see §3.9 for why it's standing in for soil +data specifically, not just conveniently similar). The file used here is +already one row per station (`station_id` matching `station_code` exactly, +verified 1:1 against all 27 stations), so `node_features.py` does a direct ID +join when possible rather than nearest-neighbor search, falling back to +spatial nearest-neighbor for any station code that isn't an exact match +(which is every non-gauge reach-graph node, and — a real, minor precision +trade-off worth knowing — every gauge too, once the table also contains +non-gauge codes, since the exact-match path requires the *entire* table to +match IDPR's station list). + +A live re-fetch from BRGM's own geoservice (`scripts/fetch_idpr_brgm.py`, +`geoservices.brgm.fr/geologie`, `GetFeatureInfo` point queries against the +`IDPR_50M` raster layer) was attempted, to get fresher values and eventually +cover the full reach graph rather than just the 27 gauges. **It failed** in +testing and the project is currently using the original, already-uploaded +`idpr.csv` instead — not resolved further, since the existing file already +gives real, usable IDPR coverage for every gauge. + +### 3.6 Catchment area — two independent sources + +**Hub'Eau (`catchment_area.csv`, via `scripts/download_catchment.py`)**: +published on the **site** referentiel, not the station referentiel — +`surface_bv` on `hydrometrie/referentiel/sites`, in km². Since one site can +have several stations, the download script does two passes: station → +`code_site`, then `code_site` → `surface_bv`. 16 of 27 stations have a value. This number is **cumulative** — the total catchment area draining to that -point, all the way to the source. That distinction matters once you bring BD -TOPO into the picture (§3.7), because BD TOPO's catchment polygons are the -opposite: incremental, reach-by-reach areas. Comparing the two directly without -accounting for that gives area ratios that look like measurement error but -aren't — a spatial join between the 27 stations and the 135 BD TOPO polygons -gave ratios from about 0.015 near the river mouth up to 0.67 near the source, -which is exactly the pattern you'd expect from cumulative-vs-incremental, not -a data quality problem. +point, all the way to the source. + +**BD TOPO, graph-wide (`cumulative_catchment_area_km2`, via +`scripts/compute_cumulative_catchment.py`)**: sums BD TOPO's incremental +catchment polygons upstream of any node, via the real graph topology — +distinct polygons counted once even when many nodes/edges share the same +coarse polygon (verified with a hand-computed test case specifically checking +this). Covers ~98% of nodes graph-wide, not just the 27 gauges — the actual +fix for the "confluences and virtual nodes have no catchment area at all" gap. + +**Cross-checked against Hub'Eau's real values on real gauges — and there's a +real, identified bias, not a clean match.** Ratio (BD-TOPO-summed ÷ Hub'Eau) +runs from about 0.75 to 1.25 for smaller catchments (< ~800 km², plausibly +normal polygon-boundary/digitization precision) but drops to 0.75–0.89 for +the largest catchments (> ~3,500 km²) — a clean, monotonic pattern, not noise. +Most likely cause: **bounding-box truncation** — the original BD TOPO pull +bbox had only a 9.6 km margin on its southern edge (the tightest of all four +directions, and south is exactly where the Eure's longest upstream +tributaries run, toward Chartres/Dreux), not a safe margin for real watershed +extent. The bbox in `download_bdtopo_hydro.py` was widened afterward (from +`(0.3, 48.3, 1.7, 49.5)` to `(-0.1, 47.7, 2.1, 49.9)`, ~2.9x the area) — the +full `download_bdtopo_hydro.py → build_reach_graphs.py → enrich_reach_graph.py +→ compute_cumulative_catchment.py` chain needs re-running against the wider +box to actually resolve this, which had not yet happened as of the last +verified run in this project. ### 3.7 BD TOPO hydrography (`bdtopo_hydro/`, via `scripts/download_bdtopo_hydro.py`) IGN's BD TOPO / BD TOPAGE hydrographic network, pulled from the Geoplateforme WFS (`https://data.geopf.fr/wfs`) rather than downloaded as a national bulk file — the download script queries a bounding box around the two basins -instead. Three layers, all scoped to that bbox: - -- `troncon_hydrographique.geojson` — river centerline reaches. 30,045 features - in the current pull, which sounds like a lot for two rivers because it - includes every stream, ditch, and canal in the box, not just the Eure and - Risle. +instead (see §3.6 for why that box was widened). Three layers, all scoped to +that bbox: + +- `troncon_hydrographique.geojson` — river centerline reaches, now the + primary source for graph *topology* too (§2), via `lien_vers_noeud_ + hydrographique_ini/fin` and `sens_de_l_ecoulement`. Real per-vertex + altitude data doubles as a fine-grained elevation profile, denser than + anything derivable from the 27 gauge points alone. - `surface_hydrographique.geojson` — hydrographic surfaces, including a `Nature` attribute that's supposed to flag karst-influenced reaches. IGN - documents this attribute as **provisional and incomplete** — filled in with - a limited, sometimes-default set of values pending refinement by the water - agencies. A negative karst search here is not strong evidence of anything; - it may just mean that stretch hasn't been annotated yet. + documents this attribute as **provisional and incomplete**. - `bassin_versant_topographique.geojson` — catchment polygons, incremental - (see §3.6). 135 polygons in the current bbox. - -**WFS axis order**: when a `BBOX` parameter's CRS is given via the URN form -(`urn:ogc:def:crs:EPSG::4326`), the OGC spec requires latitude, longitude axis -order — the opposite of the lon,lat order most GIS tools use by default. -Getting this backwards doesn't raise an error; it silently matches zero real -features, which looks identical to "no data in this area." `download_bdtopo_hydro.py` -tries lon,lat first and automatically retries with the axes swapped if that -comes back empty — for this project's bounding box, lat,lon is the order that -returns real data. - -**Z-coordinate in tronçon geometry**: `troncon_hydrographique` geometries -carry a third coordinate — real altitude at every vertex — not just lon/lat. -Code handling this data needs to account for 3D coordinates explicitly (e.g. -slicing to the first two values before building a 2-column DataFrame from -`geometry.coords`). This altitude data doubles as a genuinely useful -fine-grained elevation profile along the river, denser than anything -derivable from the 27 gauge points alone (`BDTopoHydroLoader.get_elevation_profile`). + (see §3.6). + +**WFS axis order**: when a `BBOX` parameter's CRS is given via the URN form, +the OGC spec requires latitude, longitude axis order — the opposite of the +lon,lat order most GIS tools use by default. Getting this backwards doesn't +raise an error; it silently matches zero real features. `download_bdtopo_hydro.py` +and `scripts/download_bdcavites.py` both try lon,lat first and automatically +retry with the axes swapped if that comes back empty. + +**Real branching topology fixed a naive assumption.** Filtering 30,045 +tronçons down to a single named river and building a graph from their +endpoints does **not** give one connected line — for "Risle" alone, 1,195 +name-matched tronçons split into 132 disconnected components. Broadening the +name filter to include known tributaries (§2.1) initially made this *worse* +(487/214 components), traced to short/generic tributary names ("Bec", "Avre") +matching unrelated streams elsewhere within the ~100×130 km bbox — fixed by +requiring every name-matched tronçon to also fall within a real distance of a +known gauge (`load_troncons_for_basin`'s `anchor_radius_km`), and by selecting +the connected component actually containing the most real gauges rather than +the component with the most raw tronçons (`best_component_for_stations`) — +proven to matter, not just theoretically: a synthetic adversarial test showed +the naive "biggest component" approach picking a larger but entirely +unrelated decoy network over the real one. **The bétoire finding**: two stations in the roster are explicitly named *"[amont bétoire]"* and *"[aval bétoire]"* in Hub'Eau's own site names — -*bétoire* being the Normandy dialect term for a karst swallow-hole. That's -independent, deliberate naming from the data provider, not a guess. It's the -strongest evidence in this project for a real losing reach on La Risle around -Grosley-sur-Risle/Ajou (`H605641101` → `H605641201`), even though the BD TOPO -karst layer doesn't currently confirm it (see the provisional-attribute note -above). `build_surface_edges`'s `known_losing_reaches` parameter exists -specifically for this — the current recommendation is to flag all three edges -spanning that stretch as `verified_continuous=False`, not just guess at one. - -Also worth knowing: filtering the 30,045 tronçons down to a named river and -building a graph from their endpoints does **not** give one connected line. -For "Risle," 1,195 name-matched tronçons split into 132 disconnected -components; the extraction keeps only the largest. That's a real topology gap -in the source data (tile boundaries, tributaries sharing a base name without -literally connecting), not a bug in the graph-walking code. - -### 3.8 Centerline generation +*bétoire* being the Normandy dialect term for a karst swallow-hole. Three +edges spanning that stretch on La Risle (`H605641101 → H605022010 → +H605641401 → H605641201`) are flagged `verified_continuous=False`. BD TOPO's +own karst attribute doesn't currently confirm it (see the provisional- +attribute note above) — `scripts/download_bdcavites.py` (§3.8) exists +specifically to get an independent, purpose-built second check on this, +rather than relying only on naming inference. + +### 3.8 BDCavités (`bdcavites/`, via `scripts/download_bdcavites.py`) + +BRGM's national underground cavity inventory (sinkholes, quarries, natural +cavities), via Géorisques' WFS (`georisques.gouv.fr/services`, typeName +`CAVITE_LOCALISEE`, confirmed live and GeoJSON-capable directly against the +real service). Built specifically as an independent check on the bétoire +finding (§3.7) — a purpose-built cavity dataset, not inference from station +naming or a provisional BD TOPO attribute. One real caveat: departments +75/78/91/92/93/94/95 (Paris region, unrelated to this project) are excluded +from BDCavités entirely, and the Eure department's own inventory was among +the later batches of the national 2001–2013 completion program — worth +checking coverage density before treating a sparse result as a negative +finding rather than incomplete data. + +### 3.9 Geology (`bdcharm50/`, via `scripts/download_bdcharm.py`) + +BRGM's BD Charm-50, harmonized 1:50,000 geological maps — free, open +(Licence Ouverte), no authentication, direct per-department ZIP download from +InfoTerre (a genuinely different access pattern than the WFS sources +elsewhere in this project: fixed URL per department, no bbox query, no axis- +order ambiguity). Departments **27 (Eure), 28 (Eure-et-Loir), 61 (Orne)** — +verified directly against the real, complete station roster (§3.1), not +guessed. A separate, CIGAL-membership-gated distribution of similar data +exists for at least one other French region; this project only uses the free +InfoTerre path. + +### 3.10 Landcover and NDVI (`scripts/fetch_landcover.py`, `scripts/fetch_worldcover_ndvi.py`) + +ESA WorldCover, sampled at real gauge points from the public AWS S3 Cloud- +Optimized GeoTIFFs — **not** the Terrascope WMS, which a source dated within +the last month of this project's active development reported actively resets +connections from non-browser HTTP clients (TLS fingerprinting, confirmed +across multiple tools and User-Agents, not a coding problem to work around), +and separately was slated for full phase-out already past by the time this +was checked. + +Landcover classification uses the product's 3°×3° tile grid; every real +station coordinate falls inside exactly one tile (`N48E000`), verified +directly against all 27 real coordinates. NDVI uses the *annual composites'* +1°×1° tile grid instead — genuinely different from the classification grid, +looked up per-station via VITO's own authoritative tile-index grid file +(`esa_worldcover_grid_composites.fgb`) rather than a second hand-guessed S3 +key pattern. Both need `AWS_NO_SIGN_REQUEST=YES` for `s3://`-scheme tile URLs +specifically — a plain HTTPS URL to the same public bucket needs no signing +at all, which is why the landcover script (HTTPS) worked without this while +the NDVI grid's returned URLs (`s3://`) initially failed on AWS credential +errors despite the bucket being fully public. + +Both currently cover only the 27 real gauges (exact `station_code` match), +same limitation as Hub'Eau's `catchment_area_km2` before the cumulative-BD- +TOPO fix (§3.6) — extending either script to the full reach graph is +unstarted work, not a design decision. + +### 3.11 What was tried and didn't work + +**SoilGrids (ISRIC)** — confirmed non-functional directly, not from a stale +search result: even a bare `lon`/`lat` query to the live REST API returned +`422` consistently, consistent with ISRIC's own currently-posted "temporarily +paused" service notice. + +**INRAE's national soil survey (RRP/BDGSF)** — not a uniformly-accessible +source at all. Access is explicitly described as depending on regional/ +departmental "référents" (varies by department, sometimes needs a formal +agreement with the regional chamber of agriculture), and INRAE's own +documentation states outright that the more detailed scale "n'est pas encore +en accès libre." IDPR (§3.5) and BD Charm-50 geology (§3.9) are this +project's actual substitutes for the hydrologically-relevant part of what +soil data would otherwise provide — not literal soil texture data, but IDPR +specifically is an *integrated hydrological behavior* indicator (infiltration +tendency), arguably more directly useful for a streamflow model than a raw +soil property map would be on its own. + +### 3.12 Centerline generation + +**Only relevant to the older single-chain pipeline** (`build_surface_edges`, +still available for direct comparison/debugging) — the reach graph (§2) +derives its topology directly from BD TOPO's own node linkage and doesn't use +these centerline files at all. `centerlines/eure_centerline.csv` and `centerlines/risle_centerline.csv` — the geometry `build_surface_edges` orders stations against — are generated by @@ -433,80 +676,82 @@ vector source isn't available, not the method used for the current ## 4. Applications -Click-to-explore UI over the river network (`src/app.py`, Streamlit): pick a +`src/app.py` (Streamlit) has two views, selected by a radio at the top: + +**Explore** — the original click-to-read UI over real course geometry: pick a river, click (or slide) along its course, see interpolated elevation, estimated groundwater level, and — for whichever real gauge is nearest that point — water level, discharge, and rating-curve plots pulled directly from `HydrometricLoader`'s own plotting methods rather than reimplemented. Click support uses Streamlit's native chart-selection -(`st.plotly_chart(..., on_select="rerun")`, requires `plotly` alongside -`streamlit`), not a third-party click-handling package. The click handler and -the position slider share a single source of truth by design: Streamlit only -honors a slider's `value=` argument the first time that widget is created, and -on every later rerun returns whatever's stored under that widget's own -session-state key — so the click handler writes directly into the slider's -own key before it's instantiated, rather than a separate key, keeping the two -controls in sync. It also de-duplicates incoming click events, since +(`st.plotly_chart(..., on_select="rerun")`), not a third-party click-handling +package. The click handler and the position slider share a single source of +truth by design: Streamlit only honors a slider's `value=` argument the first +time that widget is created, and on every later rerun returns whatever's +stored under that widget's own session-state key — so the click handler +writes directly into the slider's own key before it's instantiated, rather +than a separate key. It also de-duplicates incoming click events, since Streamlit's chart-selection state persists across reruns caused by *other* -widgets and would otherwise re-fire on every unrelated interaction, not just -the click that caused it. +widgets and would otherwise re-fire on every unrelated interaction. + +**Network validation** — renders the full reach graph (§2): every edge as one +Plotly line trace regardless of edge count (a trace-per-edge approach doesn't +hold up at ~5,000+ edges; verified fast at real scale — 0.29s to build a +figure for ~2,900 edges), real confluences as diamond markers, real gauges as +elevation-colored circles. Metrics card reports node/edge/confluence/gauge +counts and, when available, IDPR and cumulative-catchment coverage. Virtual +infill nodes are deliberately not drawn individually — at ~2,400 per basin, +markers for each would bury the actual validation signal (do confluences sit +where a tributary visibly joins the line? do gauges sit on the network, not +offset from it?) rather than help it. Reads directly from `reach_graph/ +{basin}_nodes_enriched.csv`, keyed on file modification time so a re-run of +`build_reach_graphs.py`/`enrich_reach_graph.py` is picked up automatically — +`st.cache_data` otherwise keys purely on function arguments, not file +contents, and this was confirmed to actually cause stale numbers once during +development, not just a theoretical risk. --- ## 5. Testing (`src/test_build_graph.py`) -Not a unit test suite in the pytest sense — a single script that runs the full -`node_features → build_surface_edges → build_pyg_graph(s)` pipeline against -real data under `--data-root` and checks the result is actually sane: no -NaN/Inf in the feature tensor, no accidental cross-basin edges, targets -genuinely excluded from the model input, edge indices within bounds, -bidirectional edge count exactly double the directed count, per-basin node -counts summing to the combined total, standardized features actually landing -near zero mean / unit variance, and the `known_losing_reaches` flag actually -taking effect on the edge it's supposed to. - -It also prints mean/max `snap_distance_km` per basin against whatever -centerline is currently in `centerlines/` — this is the number that would -catch "one basin got a real BD TOPO centerline and the other is still on the -old digitized approximation" without anyone having to notice by eye. As of the -last run, that threshold is deliberately loose (2 km) so it won't hard-fail on -a legitimately-imperfect-but-usable centerline; it's a reported number to -watch, not yet an enforced standard. Worth tightening once both basins are on -real geometry. - -Exits 0 on a clean pass, 1 otherwise, so it's usable as a pre-commit or CI -gate if that's ever set up. - ---- - -## 6. Known limitations and open questions - -- **Each basin is modeled as a single chain, not a branching network.** Tributaries - aren't represented. Fixing this means pulling BD TOPO's confluence-node - layer and reworking `build_surface_edges`'s core assumption, not a small - patch. -- **The karst losing-reach flag is based on naming evidence, not a confirmed - BD TOPO classification.** The provisional state of the `Nature` attribute - means this may firm up (or not) as IGN's data matures — it's not something - this project can resolve unilaterally. -- **Catchment area exists in two incompatible forms** (Hub'Eau cumulative vs. - BD TOPO incremental) and nothing currently derives a true independent - cumulative catchment from BD TOPO alone by summing incremental polygons - upstream of each gauge. Doable, not done. -- **13 of 27 stations have some hydrometric data; 8 have discharge - specifically.** Any model trained on discharge as a target has a real, - uneven gauge-density problem to contend with, not just a "some nodes are - unlabeled" abstraction. -- **No true soil or permeability dataset.** IDPR is a tendency index, useful - but not a substitute. -- **The groundwater-well BDLISA aquifer-unit field is unused.** If a - subsurface connectivity edge is ever justified with real evidence rather - than proximity, this is the first place to look. +Not a unit test suite in the pytest sense — a script with two independent +sections, both run from `main()`. + +**`run_checks`** — the original single-chain pipeline: runs `node_features → +build_surface_edges → build_pyg_graph(s)` against real data and checks the +result is sane — no NaN/Inf in the feature tensor, no accidental cross-basin +edges, targets genuinely excluded from the model input, edge indices within +bounds, bidirectional edge count exactly double the directed count, per-basin +node counts summing to the combined total, standardized features actually +landing near zero mean / unit variance, the `known_losing_reaches` flag +actually taking effect, and mean/max `snap_distance_km` per basin against +whatever centerline is currently in `centerlines/`. + +**`run_reach_graph_checks`** — the reach graph pipeline, gracefully skipped +(not a failure) if `reach_graph/` doesn't exist yet. Mostly regression tests +for three bugs found and fixed during development, kept here specifically so +they can't silently reintroduce themselves: + +- structural columns (`is_gauged`/`is_confluence`/etc.) never leak into + `feature_names`, but remain accessible as their own `Data` attributes +- target values never attach to a non-gauge node, and target coverage never + exceeds the real gauge count +- `edge_attr` stays exactly 3 columns despite extra edge metadata + (`toponym`, `cleabs`) sitting on the real edges table +- `physics_losses.py`'s `build_confluence_index`/`build_braid_index` produce + counts matching `is_confluence`/`is_rejoin_point` sums, with every index + within node bounds and every confluence having ≥ 2 upstream branches +- IDPR and `cumulative_catchment_area_km2` presence/coverage are reported + explicitly (the latter compared against the Hub'Eau-only baseline it's + meant to exceed) + +Exits 0 on a clean pass across both sections, 1 otherwise — usable as a +pre-commit or CI gate if that's ever set up. --- -## 7. Running things +## 6. Running things Data acquisition (from repo root, in roughly dependency order): @@ -515,12 +760,35 @@ python -m scripts.download_hubeau python -m scripts.download_elevation python -m scripts.download_era5_full # slow; download_era5_sample.py first if just testing python -m scripts.extract_era5 -python -m scripts.download_catchment_area +python -m scripts.download_catchment python -m scripts.download_bdtopo_hydro --check # verify typeNames before the real pull python -m scripts.download_bdtopo_hydro +python -m scripts.download_bdcavites --check +python -m scripts.download_bdcavites +python -m scripts.download_bdcharm +``` + +Build and validate the reach graph: + +```bash +python -m scripts.build_reach_graphs --data-root datasets +python -m scripts.enrich_reach_graph --data-root datasets # --skip-climate if that step hangs +python -m scripts.compute_cumulative_catchment --data-root datasets +python -m scripts.diagnose_confluences --data-root datasets --basin eure +python -m scripts.diagnose_confluences --data-root datasets --basin risle +``` + +Landcover / NDVI, real gauges only (needs `rasterio`, and `geopandas` for NDVI's +tile lookup): + +```bash +python -m scripts.fetch_landcover --check +python -m scripts.fetch_landcover +python -m scripts.fetch_worldcover_ndvi --check +python -m scripts.fetch_worldcover_ndvi ``` -Validate the graph pipeline against whatever's actually in `datasets/`: +Validate everything against whatever's actually in `datasets/`: ```bash python -m src.test_build_graph --data-root datasets diff --git a/datasets/bdcavites/cavite_localisee.geojson b/datasets/bdcavites/cavite_localisee.geojson new file mode 100644 index 0000000000000000000000000000000000000000..595d43877a1d105c73f7d90f5fc4f17442caa630 --- /dev/null +++ b/datasets/bdcavites/cavite_localisee.geojson @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d9ad0770c09a15992f31f3ece16afeb9097f3a048f66c431379a78c9305bc204 +size 24931685 diff --git a/datasets/bdcharm50/GEO050K_HARM_027.zip b/datasets/bdcharm50/GEO050K_HARM_027.zip new file mode 100644 index 0000000000000000000000000000000000000000..cc5031209757d975c4a4ecb0072fd79980a07e16 --- /dev/null +++ b/datasets/bdcharm50/GEO050K_HARM_027.zip @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ef28692e01362400bb0201d0fa5940f1a20f7630f90b9258f4d99bc0744ea944 +size 16009427 diff --git a/datasets/bdcharm50/GEO050K_HARM_028.zip b/datasets/bdcharm50/GEO050K_HARM_028.zip new file mode 100644 index 0000000000000000000000000000000000000000..227ab65ff0b110543449a98e80e0ffb8d8ce6d48 --- /dev/null +++ b/datasets/bdcharm50/GEO050K_HARM_028.zip @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4d486b6bea0b24b2004adad79afc7be2ddef86b67567467b015cf663ddeadeb7 +size 21530663 diff --git a/datasets/bdcharm50/GEO050K_HARM_061.zip b/datasets/bdcharm50/GEO050K_HARM_061.zip new file mode 100644 index 0000000000000000000000000000000000000000..06213e38823b475665d22dd9755d8e19c479eb86 --- /dev/null +++ b/datasets/bdcharm50/GEO050K_HARM_061.zip @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c900e51ff795863b505c3545f8bd8068aa7591f039d69f7e3b135812b35f0947 +size 24293693 diff --git "a/datasets/bdcharm50/dept_027/Descriptif des cartes g\303\251ologiques \303\240 1_50 000 vecteur.pdf" "b/datasets/bdcharm50/dept_027/Descriptif des cartes g\303\251ologiques \303\240 1_50 000 vecteur.pdf" new file mode 100644 index 0000000000000000000000000000000000000000..74bbc83d6bd0b949635a727eb8c01a89f29d3627 --- /dev/null +++ "b/datasets/bdcharm50/dept_027/Descriptif des cartes g\303\251ologiques \303\240 1_50 000 vecteur.pdf" @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d1c5773cc3af2552b4a21629d05bed2195293a7b924a5d696e1d0e250fbf3e86 +size 465834 diff --git a/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_DIVERS_2154.dbf b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_DIVERS_2154.dbf new file mode 100644 index 0000000000000000000000000000000000000000..6757a9862148ad09748ce554e8d7e5146f6d2efd Binary files /dev/null and b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_DIVERS_2154.dbf differ diff --git a/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_DIVERS_2154.lyr b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_DIVERS_2154.lyr new file mode 100644 index 0000000000000000000000000000000000000000..2f4e323182b76dca4f60306bf2d07f3c544226a2 Binary files /dev/null and b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_DIVERS_2154.lyr differ diff --git a/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_DIVERS_2154.prj b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_DIVERS_2154.prj new file mode 100644 index 0000000000000000000000000000000000000000..56757fc434d98d5eddf8c29389e42675dd4845ab --- /dev/null +++ b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_DIVERS_2154.prj @@ -0,0 +1 @@ +PROJCS["RGF93_Lambert_93",GEOGCS["GCS_RGF_1993",DATUM["D_RGF_1993",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",700000.0],PARAMETER["False_Northing",6600000.0],PARAMETER["Central_Meridian",3.0],PARAMETER["Standard_Parallel_1",44.0],PARAMETER["Standard_Parallel_2",49.0],PARAMETER["Latitude_Of_Origin",46.5],UNIT["Meter",1.0]] \ No newline at end of file diff --git a/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_DIVERS_2154.qml b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_DIVERS_2154.qml new file mode 100644 index 0000000000000000000000000000000000000000..608666bc5a1a36b0fa53ba669e4c7c3454e1eba3 --- /dev/null +++ b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_DIVERS_2154.qml @@ -0,0 +1,2 @@ + +255 \ No newline at end of file diff --git a/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_DIVERS_2154.shp b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_DIVERS_2154.shp new file mode 100644 index 0000000000000000000000000000000000000000..cd8a1470c8bec278c4a8c41ed35a075b513d20f9 Binary files /dev/null and b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_DIVERS_2154.shp differ diff --git a/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_DIVERS_2154.shx b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_DIVERS_2154.shx new file mode 100644 index 0000000000000000000000000000000000000000..03ce799ca5995f7ee317aacc1494adf31fbc5cff Binary files /dev/null and b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_DIVERS_2154.shx differ diff --git a/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_FGEOL_2154.dbf b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_FGEOL_2154.dbf new file mode 100644 index 0000000000000000000000000000000000000000..aba449ffd7284a468a50acd934316b636d8eb83b --- /dev/null +++ b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_FGEOL_2154.dbf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7919155134fb9c8fcce3ba7f4a4e47a75a6d02499efb82215bc9375ed8a67d34 +size 6620665 diff --git a/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_FGEOL_2154.lyr b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_FGEOL_2154.lyr new file mode 100644 index 0000000000000000000000000000000000000000..9ac53c06303f76b5f1d689ca3ea1842f97fb0329 Binary files /dev/null and b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_FGEOL_2154.lyr differ diff --git a/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_FGEOL_2154.prj b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_FGEOL_2154.prj new file mode 100644 index 0000000000000000000000000000000000000000..56757fc434d98d5eddf8c29389e42675dd4845ab --- /dev/null +++ b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_FGEOL_2154.prj @@ -0,0 +1 @@ +PROJCS["RGF93_Lambert_93",GEOGCS["GCS_RGF_1993",DATUM["D_RGF_1993",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",700000.0],PARAMETER["False_Northing",6600000.0],PARAMETER["Central_Meridian",3.0],PARAMETER["Standard_Parallel_1",44.0],PARAMETER["Standard_Parallel_2",49.0],PARAMETER["Latitude_Of_Origin",46.5],UNIT["Meter",1.0]] \ No newline at end of file diff --git a/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_FGEOL_2154.qml b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_FGEOL_2154.qml new file mode 100644 index 0000000000000000000000000000000000000000..4344ca61acd186ab576018dc7a5f2d7cc620a663 --- /dev/null +++ b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_FGEOL_2154.qml @@ -0,0 +1,2 @@ + +255 \ No newline at end of file diff --git a/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_FGEOL_2154.shp b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_FGEOL_2154.shp new file mode 100644 index 0000000000000000000000000000000000000000..da2602a8fd8d16223c00d62c74c1341c96582702 --- /dev/null +++ b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_FGEOL_2154.shp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:15626b809bc52ed27ba554c0c6ebae2933d42f4795f2ae4fd0bb7e5974f0d380 +size 7438780 diff --git a/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_FGEOL_2154.shx b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_FGEOL_2154.shx new file mode 100644 index 0000000000000000000000000000000000000000..51d475a994e5a8a78130e6693ef47aeb0cae9f86 --- /dev/null +++ b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_FGEOL_2154.shx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:573e2b4d674d42526cbf89a2295f2571cdf4ac7fe1615f308bea04bf5ec66564 +size 154060 diff --git a/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_STRUCT_2154.dbf b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_STRUCT_2154.dbf new file mode 100644 index 0000000000000000000000000000000000000000..f6f3d55aca786932851cd84021c0b9f86e12248c Binary files /dev/null and b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_STRUCT_2154.dbf differ diff --git a/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_STRUCT_2154.lyr b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_STRUCT_2154.lyr new file mode 100644 index 0000000000000000000000000000000000000000..b8824d4d7fadb8e0984c318b6f3005aca34897b8 Binary files /dev/null and b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_STRUCT_2154.lyr differ diff --git a/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_STRUCT_2154.prj b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_STRUCT_2154.prj new file mode 100644 index 0000000000000000000000000000000000000000..56757fc434d98d5eddf8c29389e42675dd4845ab --- /dev/null +++ b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_STRUCT_2154.prj @@ -0,0 +1 @@ +PROJCS["RGF93_Lambert_93",GEOGCS["GCS_RGF_1993",DATUM["D_RGF_1993",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",700000.0],PARAMETER["False_Northing",6600000.0],PARAMETER["Central_Meridian",3.0],PARAMETER["Standard_Parallel_1",44.0],PARAMETER["Standard_Parallel_2",49.0],PARAMETER["Latitude_Of_Origin",46.5],UNIT["Meter",1.0]] \ No newline at end of file diff --git a/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_STRUCT_2154.qml b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_STRUCT_2154.qml new file mode 100644 index 0000000000000000000000000000000000000000..2648c172baee540462b48b6fc9f7f3c94a10abe9 --- /dev/null +++ b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_STRUCT_2154.qml @@ -0,0 +1,2 @@ + +255 \ No newline at end of file diff --git a/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_STRUCT_2154.shp b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_STRUCT_2154.shp new file mode 100644 index 0000000000000000000000000000000000000000..1fad6bcfab9894af628b2fff3fdfd2d52cfc0148 Binary files /dev/null and b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_STRUCT_2154.shp differ diff --git a/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_STRUCT_2154.shx b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_STRUCT_2154.shx new file mode 100644 index 0000000000000000000000000000000000000000..c7aea67626f00e6efb69876f8ece32ed92709b16 Binary files /dev/null and b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_L_STRUCT_2154.shx differ diff --git a/datasets/bdcharm50/dept_027/GEO050K_HARM_027_P_DIVERS_2154.dbf b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_P_DIVERS_2154.dbf new file mode 100644 index 0000000000000000000000000000000000000000..9badabfaeb58e4086f59a384fa5e873a73847bae --- /dev/null +++ b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_P_DIVERS_2154.dbf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d7f9f02aa66fdd0a0df715a6ff43d48fd3030dc42895747976c584edff25d196 +size 3125317 diff --git a/datasets/bdcharm50/dept_027/GEO050K_HARM_027_P_DIVERS_2154.lyr b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_P_DIVERS_2154.lyr new file mode 100644 index 0000000000000000000000000000000000000000..8708929a7d41d3a5926631549c052ef26d766408 Binary files /dev/null and b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_P_DIVERS_2154.lyr differ diff --git a/datasets/bdcharm50/dept_027/GEO050K_HARM_027_P_DIVERS_2154.prj b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_P_DIVERS_2154.prj new file mode 100644 index 0000000000000000000000000000000000000000..56757fc434d98d5eddf8c29389e42675dd4845ab --- /dev/null +++ b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_P_DIVERS_2154.prj @@ -0,0 +1 @@ +PROJCS["RGF93_Lambert_93",GEOGCS["GCS_RGF_1993",DATUM["D_RGF_1993",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",700000.0],PARAMETER["False_Northing",6600000.0],PARAMETER["Central_Meridian",3.0],PARAMETER["Standard_Parallel_1",44.0],PARAMETER["Standard_Parallel_2",49.0],PARAMETER["Latitude_Of_Origin",46.5],UNIT["Meter",1.0]] \ No newline at end of file diff --git a/datasets/bdcharm50/dept_027/GEO050K_HARM_027_P_DIVERS_2154.qml b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_P_DIVERS_2154.qml new file mode 100644 index 0000000000000000000000000000000000000000..225557495de1f30db7dee9449faa15affd03a53a --- /dev/null +++ b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_P_DIVERS_2154.qml @@ -0,0 +1,2 @@ + +255 \ No newline at end of file diff --git a/datasets/bdcharm50/dept_027/GEO050K_HARM_027_P_DIVERS_2154.shp b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_P_DIVERS_2154.shp new file mode 100644 index 0000000000000000000000000000000000000000..084e2caa5ea14c796cf75619a01f719ddf180fb0 --- /dev/null +++ b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_P_DIVERS_2154.shp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e7696bc4eeeaf7d2b499040cba69508aca65b5493e7ab9c99b7bd41c44c9a35a +size 153064 diff --git a/datasets/bdcharm50/dept_027/GEO050K_HARM_027_P_DIVERS_2154.shx b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_P_DIVERS_2154.shx new file mode 100644 index 0000000000000000000000000000000000000000..14601c184e6fc0e426c6d48b8cc220e9a637bfdf Binary files /dev/null and b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_P_DIVERS_2154.shx differ diff --git a/datasets/bdcharm50/dept_027/GEO050K_HARM_027_P_STRUCT_2154.dbf b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_P_STRUCT_2154.dbf new file mode 100644 index 0000000000000000000000000000000000000000..8b60f60448f0858b8683ef1192cc1ec97b7e9ac1 Binary files /dev/null and b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_P_STRUCT_2154.dbf differ diff --git a/datasets/bdcharm50/dept_027/GEO050K_HARM_027_P_STRUCT_2154.lyr b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_P_STRUCT_2154.lyr new file mode 100644 index 0000000000000000000000000000000000000000..3b90f90802d847b85aa17d8a4f7cc17b92445d6c Binary files /dev/null and b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_P_STRUCT_2154.lyr differ diff --git a/datasets/bdcharm50/dept_027/GEO050K_HARM_027_P_STRUCT_2154.prj b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_P_STRUCT_2154.prj new file mode 100644 index 0000000000000000000000000000000000000000..56757fc434d98d5eddf8c29389e42675dd4845ab --- /dev/null +++ b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_P_STRUCT_2154.prj @@ -0,0 +1 @@ +PROJCS["RGF93_Lambert_93",GEOGCS["GCS_RGF_1993",DATUM["D_RGF_1993",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",700000.0],PARAMETER["False_Northing",6600000.0],PARAMETER["Central_Meridian",3.0],PARAMETER["Standard_Parallel_1",44.0],PARAMETER["Standard_Parallel_2",49.0],PARAMETER["Latitude_Of_Origin",46.5],UNIT["Meter",1.0]] \ No newline at end of file diff --git a/datasets/bdcharm50/dept_027/GEO050K_HARM_027_P_STRUCT_2154.qml b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_P_STRUCT_2154.qml new file mode 100644 index 0000000000000000000000000000000000000000..329f846cb71e9fa561f98bc393cf6c54ff7947ed --- /dev/null +++ b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_P_STRUCT_2154.qml @@ -0,0 +1,2 @@ + +255 \ No newline at end of file diff --git a/datasets/bdcharm50/dept_027/GEO050K_HARM_027_P_STRUCT_2154.shp b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_P_STRUCT_2154.shp new file mode 100644 index 0000000000000000000000000000000000000000..4b08c51bca1f6542d717807d7edf762bc739371d Binary files /dev/null and b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_P_STRUCT_2154.shp differ diff --git a/datasets/bdcharm50/dept_027/GEO050K_HARM_027_P_STRUCT_2154.shx b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_P_STRUCT_2154.shx new file mode 100644 index 0000000000000000000000000000000000000000..3d31c4a6e15d42aeadae1dfd38f18c8bc56123d6 Binary files /dev/null and b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_P_STRUCT_2154.shx differ diff --git a/datasets/bdcharm50/dept_027/GEO050K_HARM_027_S_FGEOL_2154.dbf b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_S_FGEOL_2154.dbf new file mode 100644 index 0000000000000000000000000000000000000000..6ce68a9f601861f83dc5c4aa66288835e821f14e --- /dev/null +++ b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_S_FGEOL_2154.dbf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c1da5e6b0d60c08a41862a83b94606d31ef06ec729883a7a0f2ce465fb923443 +size 3622421 diff --git a/datasets/bdcharm50/dept_027/GEO050K_HARM_027_S_FGEOL_2154.lyr b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_S_FGEOL_2154.lyr new file mode 100644 index 0000000000000000000000000000000000000000..a0aac032d304e2605360de30469b463317247e2c --- /dev/null +++ b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_S_FGEOL_2154.lyr @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0874de865d408583ecfc7048837e63bb65046e6eb3b5892e3f2fb4272744a8f6 +size 143360 diff --git a/datasets/bdcharm50/dept_027/GEO050K_HARM_027_S_FGEOL_2154.prj b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_S_FGEOL_2154.prj new file mode 100644 index 0000000000000000000000000000000000000000..56757fc434d98d5eddf8c29389e42675dd4845ab --- /dev/null +++ b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_S_FGEOL_2154.prj @@ -0,0 +1 @@ +PROJCS["RGF93_Lambert_93",GEOGCS["GCS_RGF_1993",DATUM["D_RGF_1993",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",700000.0],PARAMETER["False_Northing",6600000.0],PARAMETER["Central_Meridian",3.0],PARAMETER["Standard_Parallel_1",44.0],PARAMETER["Standard_Parallel_2",49.0],PARAMETER["Latitude_Of_Origin",46.5],UNIT["Meter",1.0]] \ No newline at end of file diff --git a/datasets/bdcharm50/dept_027/GEO050K_HARM_027_S_FGEOL_2154.qml b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_S_FGEOL_2154.qml new file mode 100644 index 0000000000000000000000000000000000000000..50f71d35f47d981251051ae799c3b5dd8bbc6490 --- /dev/null +++ b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_S_FGEOL_2154.qml @@ -0,0 +1,2 @@ + +255 \ No newline at end of file diff --git a/datasets/bdcharm50/dept_027/GEO050K_HARM_027_S_FGEOL_2154.shp b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_S_FGEOL_2154.shp new file mode 100644 index 0000000000000000000000000000000000000000..f867cfe9a93c56ab836456aef863b959d450b9f4 --- /dev/null +++ b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_S_FGEOL_2154.shp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:06a8f10eee38b43494ed457c05c416cbbf07e024911858815ee1151d1068e802 +size 12602632 diff --git a/datasets/bdcharm50/dept_027/GEO050K_HARM_027_S_FGEOL_2154.shx b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_S_FGEOL_2154.shx new file mode 100644 index 0000000000000000000000000000000000000000..2ea9196cd1b8452eaa244ef5c4655a099eacd7f5 Binary files /dev/null and b/datasets/bdcharm50/dept_027/GEO050K_HARM_027_S_FGEOL_2154.shx differ diff --git "a/datasets/bdcharm50/dept_028/Descriptif des cartes g\303\251ologiques \303\240 1_50 000 vecteur.pdf" "b/datasets/bdcharm50/dept_028/Descriptif des cartes g\303\251ologiques \303\240 1_50 000 vecteur.pdf" new file mode 100644 index 0000000000000000000000000000000000000000..74bbc83d6bd0b949635a727eb8c01a89f29d3627 --- /dev/null +++ "b/datasets/bdcharm50/dept_028/Descriptif des cartes g\303\251ologiques \303\240 1_50 000 vecteur.pdf" @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d1c5773cc3af2552b4a21629d05bed2195293a7b924a5d696e1d0e250fbf3e86 +size 465834 diff --git a/datasets/bdcharm50/dept_028/GEO050K_HARM_028_L_FGEOL_2154.dbf b/datasets/bdcharm50/dept_028/GEO050K_HARM_028_L_FGEOL_2154.dbf new file mode 100644 index 0000000000000000000000000000000000000000..ce7c94fd09941103a57cafa059ed7e110cd9e431 --- /dev/null +++ b/datasets/bdcharm50/dept_028/GEO050K_HARM_028_L_FGEOL_2154.dbf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:869d8ce6ca5b251aa03cb61066ffdba2325874bd785dc9755bfb0821bfe53c2f +size 3912353 diff --git a/datasets/bdcharm50/dept_028/GEO050K_HARM_028_L_FGEOL_2154.lyr b/datasets/bdcharm50/dept_028/GEO050K_HARM_028_L_FGEOL_2154.lyr new file mode 100644 index 0000000000000000000000000000000000000000..61387daf37f1c74d7f6679f76f398649e6ce7e21 Binary files /dev/null and b/datasets/bdcharm50/dept_028/GEO050K_HARM_028_L_FGEOL_2154.lyr differ diff --git a/datasets/bdcharm50/dept_028/GEO050K_HARM_028_L_FGEOL_2154.prj b/datasets/bdcharm50/dept_028/GEO050K_HARM_028_L_FGEOL_2154.prj new file mode 100644 index 0000000000000000000000000000000000000000..56757fc434d98d5eddf8c29389e42675dd4845ab --- /dev/null +++ b/datasets/bdcharm50/dept_028/GEO050K_HARM_028_L_FGEOL_2154.prj @@ -0,0 +1 @@ +PROJCS["RGF93_Lambert_93",GEOGCS["GCS_RGF_1993",DATUM["D_RGF_1993",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",700000.0],PARAMETER["False_Northing",6600000.0],PARAMETER["Central_Meridian",3.0],PARAMETER["Standard_Parallel_1",44.0],PARAMETER["Standard_Parallel_2",49.0],PARAMETER["Latitude_Of_Origin",46.5],UNIT["Meter",1.0]] \ No newline at end of file diff --git a/datasets/bdcharm50/dept_028/GEO050K_HARM_028_L_FGEOL_2154.qml b/datasets/bdcharm50/dept_028/GEO050K_HARM_028_L_FGEOL_2154.qml new file mode 100644 index 0000000000000000000000000000000000000000..7205f5ed85d8244271e64a5b972b8e851521163f --- /dev/null +++ b/datasets/bdcharm50/dept_028/GEO050K_HARM_028_L_FGEOL_2154.qml @@ -0,0 +1,2 @@ + +255 \ No newline at end of file diff --git a/datasets/bdcharm50/dept_028/GEO050K_HARM_028_L_FGEOL_2154.shp b/datasets/bdcharm50/dept_028/GEO050K_HARM_028_L_FGEOL_2154.shp new file mode 100644 index 0000000000000000000000000000000000000000..86c9ba885640d2bb1cdf91885ad88c88d092054d --- /dev/null +++ b/datasets/bdcharm50/dept_028/GEO050K_HARM_028_L_FGEOL_2154.shp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d0d181998e534cee707edf55432f83031accf30b73bbe6f80ccc55b452106c6f +size 9529460 diff --git a/datasets/bdcharm50/dept_028/GEO050K_HARM_028_L_FGEOL_2154.shx b/datasets/bdcharm50/dept_028/GEO050K_HARM_028_L_FGEOL_2154.shx new file mode 100644 index 0000000000000000000000000000000000000000..19f88652f54f70df0f7000b6223844f669696e43 Binary files /dev/null and b/datasets/bdcharm50/dept_028/GEO050K_HARM_028_L_FGEOL_2154.shx differ diff --git a/datasets/bdcharm50/dept_028/GEO050K_HARM_028_L_STRUCT_2154.dbf b/datasets/bdcharm50/dept_028/GEO050K_HARM_028_L_STRUCT_2154.dbf new file mode 100644 index 0000000000000000000000000000000000000000..8affbd23c2a74f30b610b5646887c1d77c5b365c Binary files /dev/null and b/datasets/bdcharm50/dept_028/GEO050K_HARM_028_L_STRUCT_2154.dbf differ diff --git a/datasets/bdcharm50/dept_028/GEO050K_HARM_028_L_STRUCT_2154.lyr b/datasets/bdcharm50/dept_028/GEO050K_HARM_028_L_STRUCT_2154.lyr new file mode 100644 index 0000000000000000000000000000000000000000..7a38d6dd4679a6fb540c3e217377f6d881574585 Binary files /dev/null and b/datasets/bdcharm50/dept_028/GEO050K_HARM_028_L_STRUCT_2154.lyr differ diff --git a/datasets/bdcharm50/dept_028/GEO050K_HARM_028_L_STRUCT_2154.prj b/datasets/bdcharm50/dept_028/GEO050K_HARM_028_L_STRUCT_2154.prj new file mode 100644 index 0000000000000000000000000000000000000000..56757fc434d98d5eddf8c29389e42675dd4845ab --- /dev/null +++ b/datasets/bdcharm50/dept_028/GEO050K_HARM_028_L_STRUCT_2154.prj @@ -0,0 +1 @@ +PROJCS["RGF93_Lambert_93",GEOGCS["GCS_RGF_1993",DATUM["D_RGF_1993",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",700000.0],PARAMETER["False_Northing",6600000.0],PARAMETER["Central_Meridian",3.0],PARAMETER["Standard_Parallel_1",44.0],PARAMETER["Standard_Parallel_2",49.0],PARAMETER["Latitude_Of_Origin",46.5],UNIT["Meter",1.0]] \ No newline at end of file diff --git a/datasets/bdcharm50/dept_028/GEO050K_HARM_028_L_STRUCT_2154.qml b/datasets/bdcharm50/dept_028/GEO050K_HARM_028_L_STRUCT_2154.qml new file mode 100644 index 0000000000000000000000000000000000000000..1c0667dd2a7642a7acc39826971d54826bd5d82c --- /dev/null +++ b/datasets/bdcharm50/dept_028/GEO050K_HARM_028_L_STRUCT_2154.qml @@ -0,0 +1,2 @@ + +255 \ No newline at end of file diff --git a/datasets/bdcharm50/dept_028/GEO050K_HARM_028_L_STRUCT_2154.shp b/datasets/bdcharm50/dept_028/GEO050K_HARM_028_L_STRUCT_2154.shp new file mode 100644 index 0000000000000000000000000000000000000000..542fcd3f449a177591536983cbef085c6e787612 Binary files /dev/null and b/datasets/bdcharm50/dept_028/GEO050K_HARM_028_L_STRUCT_2154.shp differ diff --git a/datasets/bdcharm50/dept_028/GEO050K_HARM_028_L_STRUCT_2154.shx b/datasets/bdcharm50/dept_028/GEO050K_HARM_028_L_STRUCT_2154.shx new file mode 100644 index 0000000000000000000000000000000000000000..17070ff0aa4b96242dfa095fff65302a285fe87f Binary files /dev/null and b/datasets/bdcharm50/dept_028/GEO050K_HARM_028_L_STRUCT_2154.shx differ diff --git a/datasets/bdcharm50/dept_028/GEO050K_HARM_028_S_FGEOL_2154.dbf b/datasets/bdcharm50/dept_028/GEO050K_HARM_028_S_FGEOL_2154.dbf new file mode 100644 index 0000000000000000000000000000000000000000..3720679c71e1fb69c7e1aa9b798e60cd1c58cc66 --- /dev/null +++ b/datasets/bdcharm50/dept_028/GEO050K_HARM_028_S_FGEOL_2154.dbf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9c4cbffa396ea0fc4fc96fef11eca4c0980cd5ce2c07fd5094cbc5de0b979b43 +size 1930585 diff --git a/datasets/bdcharm50/dept_028/GEO050K_HARM_028_S_FGEOL_2154.lyr b/datasets/bdcharm50/dept_028/GEO050K_HARM_028_S_FGEOL_2154.lyr new file mode 100644 index 0000000000000000000000000000000000000000..9b89473496866e01da3c8adeeeacbdc05284ad26 Binary files /dev/null and b/datasets/bdcharm50/dept_028/GEO050K_HARM_028_S_FGEOL_2154.lyr differ diff --git a/datasets/bdcharm50/dept_028/GEO050K_HARM_028_S_FGEOL_2154.prj b/datasets/bdcharm50/dept_028/GEO050K_HARM_028_S_FGEOL_2154.prj new file mode 100644 index 0000000000000000000000000000000000000000..56757fc434d98d5eddf8c29389e42675dd4845ab --- /dev/null +++ b/datasets/bdcharm50/dept_028/GEO050K_HARM_028_S_FGEOL_2154.prj @@ -0,0 +1 @@ +PROJCS["RGF93_Lambert_93",GEOGCS["GCS_RGF_1993",DATUM["D_RGF_1993",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",700000.0],PARAMETER["False_Northing",6600000.0],PARAMETER["Central_Meridian",3.0],PARAMETER["Standard_Parallel_1",44.0],PARAMETER["Standard_Parallel_2",49.0],PARAMETER["Latitude_Of_Origin",46.5],UNIT["Meter",1.0]] \ No newline at end of file diff --git a/datasets/bdcharm50/dept_028/GEO050K_HARM_028_S_FGEOL_2154.qml b/datasets/bdcharm50/dept_028/GEO050K_HARM_028_S_FGEOL_2154.qml new file mode 100644 index 0000000000000000000000000000000000000000..90f285fb1067d0a11e72eee258e76d2309823f93 --- /dev/null +++ b/datasets/bdcharm50/dept_028/GEO050K_HARM_028_S_FGEOL_2154.qml @@ -0,0 +1,2 @@ + +255 \ No newline at end of file diff --git a/datasets/bdcharm50/dept_028/GEO050K_HARM_028_S_FGEOL_2154.shp b/datasets/bdcharm50/dept_028/GEO050K_HARM_028_S_FGEOL_2154.shp new file mode 100644 index 0000000000000000000000000000000000000000..9bf82f4f6b356f61e43a51cad01eaffa903fe169 --- /dev/null +++ b/datasets/bdcharm50/dept_028/GEO050K_HARM_028_S_FGEOL_2154.shp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:358c987e15a91f0b7f3d476c79c149f70b5a4e9c3718e62e917966524369bc77 +size 17651700 diff --git a/datasets/bdcharm50/dept_028/GEO050K_HARM_028_S_FGEOL_2154.shx b/datasets/bdcharm50/dept_028/GEO050K_HARM_028_S_FGEOL_2154.shx new file mode 100644 index 0000000000000000000000000000000000000000..94ce5596ea126d993b9bc4ebf9a38a9bbb928361 Binary files /dev/null and b/datasets/bdcharm50/dept_028/GEO050K_HARM_028_S_FGEOL_2154.shx differ diff --git "a/datasets/bdcharm50/dept_061/Descriptif des cartes g\303\251ologiques \303\240 1_50 000 vecteur.pdf" "b/datasets/bdcharm50/dept_061/Descriptif des cartes g\303\251ologiques \303\240 1_50 000 vecteur.pdf" new file mode 100644 index 0000000000000000000000000000000000000000..74bbc83d6bd0b949635a727eb8c01a89f29d3627 --- /dev/null +++ "b/datasets/bdcharm50/dept_061/Descriptif des cartes g\303\251ologiques \303\240 1_50 000 vecteur.pdf" @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d1c5773cc3af2552b4a21629d05bed2195293a7b924a5d696e1d0e250fbf3e86 +size 465834 diff --git a/datasets/bdcharm50/dept_061/GEO050K_HARM_061_L_FGEOL_2154.dbf b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_L_FGEOL_2154.dbf new file mode 100644 index 0000000000000000000000000000000000000000..917b2cd36d3a6ad1e7c8714d5fe3d02005196595 --- /dev/null +++ b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_L_FGEOL_2154.dbf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8a64312aac232f869dfb05bc0044fe33d7cb1760fedfca22dee5b1d21f93ff92 +size 8971561 diff --git a/datasets/bdcharm50/dept_061/GEO050K_HARM_061_L_FGEOL_2154.lyr b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_L_FGEOL_2154.lyr new file mode 100644 index 0000000000000000000000000000000000000000..90c39b45da5a9be60c028b8ec0feaf67a3896a89 Binary files /dev/null and b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_L_FGEOL_2154.lyr differ diff --git a/datasets/bdcharm50/dept_061/GEO050K_HARM_061_L_FGEOL_2154.prj b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_L_FGEOL_2154.prj new file mode 100644 index 0000000000000000000000000000000000000000..56757fc434d98d5eddf8c29389e42675dd4845ab --- /dev/null +++ b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_L_FGEOL_2154.prj @@ -0,0 +1 @@ +PROJCS["RGF93_Lambert_93",GEOGCS["GCS_RGF_1993",DATUM["D_RGF_1993",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",700000.0],PARAMETER["False_Northing",6600000.0],PARAMETER["Central_Meridian",3.0],PARAMETER["Standard_Parallel_1",44.0],PARAMETER["Standard_Parallel_2",49.0],PARAMETER["Latitude_Of_Origin",46.5],UNIT["Meter",1.0]] \ No newline at end of file diff --git a/datasets/bdcharm50/dept_061/GEO050K_HARM_061_L_FGEOL_2154.qml b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_L_FGEOL_2154.qml new file mode 100644 index 0000000000000000000000000000000000000000..7205f5ed85d8244271e64a5b972b8e851521163f --- /dev/null +++ b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_L_FGEOL_2154.qml @@ -0,0 +1,2 @@ + +255 \ No newline at end of file diff --git a/datasets/bdcharm50/dept_061/GEO050K_HARM_061_L_FGEOL_2154.shp b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_L_FGEOL_2154.shp new file mode 100644 index 0000000000000000000000000000000000000000..bf5e9823a1baeb72828cbe4f586783967a2ddc53 --- /dev/null +++ b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_L_FGEOL_2154.shp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bb7fc8bb198bf56e8c8993ee3ab4b675a380e7392e27887d30da99ca2045e547 +size 11149532 diff --git a/datasets/bdcharm50/dept_061/GEO050K_HARM_061_L_FGEOL_2154.shx b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_L_FGEOL_2154.shx new file mode 100644 index 0000000000000000000000000000000000000000..c2828d4cb3787d7b2bf67f482d1c239eaacbcd27 --- /dev/null +++ b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_L_FGEOL_2154.shx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:aabb3fc5e83c69af2ca961a0466417231a08337c23026f9f3effeb7448c21058 +size 208732 diff --git a/datasets/bdcharm50/dept_061/GEO050K_HARM_061_L_STRUCT_2154.dbf b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_L_STRUCT_2154.dbf new file mode 100644 index 0000000000000000000000000000000000000000..06d1913ed03b2bbe0564c1964a19ba83823407ee --- /dev/null +++ b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_L_STRUCT_2154.dbf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:501b25f12190b431308ebcb748551d2d686d57a702cb00a4d21dd34ae09d52b0 +size 1189111 diff --git a/datasets/bdcharm50/dept_061/GEO050K_HARM_061_L_STRUCT_2154.lyr b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_L_STRUCT_2154.lyr new file mode 100644 index 0000000000000000000000000000000000000000..59a5466b2673f6ccf777fe8eb14ccac7b2d60bcd Binary files /dev/null and b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_L_STRUCT_2154.lyr differ diff --git a/datasets/bdcharm50/dept_061/GEO050K_HARM_061_L_STRUCT_2154.prj b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_L_STRUCT_2154.prj new file mode 100644 index 0000000000000000000000000000000000000000..56757fc434d98d5eddf8c29389e42675dd4845ab --- /dev/null +++ b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_L_STRUCT_2154.prj @@ -0,0 +1 @@ +PROJCS["RGF93_Lambert_93",GEOGCS["GCS_RGF_1993",DATUM["D_RGF_1993",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",700000.0],PARAMETER["False_Northing",6600000.0],PARAMETER["Central_Meridian",3.0],PARAMETER["Standard_Parallel_1",44.0],PARAMETER["Standard_Parallel_2",49.0],PARAMETER["Latitude_Of_Origin",46.5],UNIT["Meter",1.0]] \ No newline at end of file diff --git a/datasets/bdcharm50/dept_061/GEO050K_HARM_061_L_STRUCT_2154.qml b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_L_STRUCT_2154.qml new file mode 100644 index 0000000000000000000000000000000000000000..abee182a61feadd98c9250d08dbb479e174b1354 --- /dev/null +++ b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_L_STRUCT_2154.qml @@ -0,0 +1,2 @@ + +255 \ No newline at end of file diff --git a/datasets/bdcharm50/dept_061/GEO050K_HARM_061_L_STRUCT_2154.shp b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_L_STRUCT_2154.shp new file mode 100644 index 0000000000000000000000000000000000000000..75912dc05a5c9ee441babe8d37603f56a4f9b840 --- /dev/null +++ b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_L_STRUCT_2154.shp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0bc45892fa789d16fcb73735f88fb6e8bc25a11a9f1ce80023b14d7c3d49c071 +size 491220 diff --git a/datasets/bdcharm50/dept_061/GEO050K_HARM_061_L_STRUCT_2154.shx b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_L_STRUCT_2154.shx new file mode 100644 index 0000000000000000000000000000000000000000..7ab9d7784fa60da43091cee961508f04a3d765ad Binary files /dev/null and b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_L_STRUCT_2154.shx differ diff --git a/datasets/bdcharm50/dept_061/GEO050K_HARM_061_P_DIVERS_2154.dbf b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_P_DIVERS_2154.dbf new file mode 100644 index 0000000000000000000000000000000000000000..287b8ea9445f40ec26eb1468408982f9ee0bbbb1 --- /dev/null +++ b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_P_DIVERS_2154.dbf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d7f115a8dffa8e416d6f0c8796d4fb4537619cbb422ee74b33370a67dc6f1896 +size 368277 diff --git a/datasets/bdcharm50/dept_061/GEO050K_HARM_061_P_DIVERS_2154.lyr b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_P_DIVERS_2154.lyr new file mode 100644 index 0000000000000000000000000000000000000000..08113fba331befa42ffbc5d270f9a8b5646c9f89 Binary files /dev/null and b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_P_DIVERS_2154.lyr differ diff --git a/datasets/bdcharm50/dept_061/GEO050K_HARM_061_P_DIVERS_2154.prj b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_P_DIVERS_2154.prj new file mode 100644 index 0000000000000000000000000000000000000000..56757fc434d98d5eddf8c29389e42675dd4845ab --- /dev/null +++ b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_P_DIVERS_2154.prj @@ -0,0 +1 @@ +PROJCS["RGF93_Lambert_93",GEOGCS["GCS_RGF_1993",DATUM["D_RGF_1993",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",700000.0],PARAMETER["False_Northing",6600000.0],PARAMETER["Central_Meridian",3.0],PARAMETER["Standard_Parallel_1",44.0],PARAMETER["Standard_Parallel_2",49.0],PARAMETER["Latitude_Of_Origin",46.5],UNIT["Meter",1.0]] \ No newline at end of file diff --git a/datasets/bdcharm50/dept_061/GEO050K_HARM_061_P_DIVERS_2154.qml b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_P_DIVERS_2154.qml new file mode 100644 index 0000000000000000000000000000000000000000..25d667ae3d38821c18167e60cf8482da511052d4 --- /dev/null +++ b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_P_DIVERS_2154.qml @@ -0,0 +1,2 @@ + +255 \ No newline at end of file diff --git a/datasets/bdcharm50/dept_061/GEO050K_HARM_061_P_DIVERS_2154.shp b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_P_DIVERS_2154.shp new file mode 100644 index 0000000000000000000000000000000000000000..74b243a811c216f739c17cc2285e6cb3fd6e7b70 Binary files /dev/null and b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_P_DIVERS_2154.shp differ diff --git a/datasets/bdcharm50/dept_061/GEO050K_HARM_061_P_DIVERS_2154.shx b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_P_DIVERS_2154.shx new file mode 100644 index 0000000000000000000000000000000000000000..b2c11b3061dcc4b5a83129d958b2221f0a793179 Binary files /dev/null and b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_P_DIVERS_2154.shx differ diff --git a/datasets/bdcharm50/dept_061/GEO050K_HARM_061_P_STRUCT_2154.dbf b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_P_STRUCT_2154.dbf new file mode 100644 index 0000000000000000000000000000000000000000..14dc0a37891e6674029cc018f1950c4728d54b6d --- /dev/null +++ b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_P_STRUCT_2154.dbf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:188a00c47b6b7d17e1b3f47b3c317ddbd4524a0c98d2131bc12c1d3182b512cd +size 645857 diff --git a/datasets/bdcharm50/dept_061/GEO050K_HARM_061_P_STRUCT_2154.lyr b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_P_STRUCT_2154.lyr new file mode 100644 index 0000000000000000000000000000000000000000..3f68e77c89cd684ab8aca8cdbb61fe13e3a639bb Binary files /dev/null and b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_P_STRUCT_2154.lyr differ diff --git a/datasets/bdcharm50/dept_061/GEO050K_HARM_061_P_STRUCT_2154.prj b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_P_STRUCT_2154.prj new file mode 100644 index 0000000000000000000000000000000000000000..56757fc434d98d5eddf8c29389e42675dd4845ab --- /dev/null +++ b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_P_STRUCT_2154.prj @@ -0,0 +1 @@ +PROJCS["RGF93_Lambert_93",GEOGCS["GCS_RGF_1993",DATUM["D_RGF_1993",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",700000.0],PARAMETER["False_Northing",6600000.0],PARAMETER["Central_Meridian",3.0],PARAMETER["Standard_Parallel_1",44.0],PARAMETER["Standard_Parallel_2",49.0],PARAMETER["Latitude_Of_Origin",46.5],UNIT["Meter",1.0]] \ No newline at end of file diff --git a/datasets/bdcharm50/dept_061/GEO050K_HARM_061_P_STRUCT_2154.qml b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_P_STRUCT_2154.qml new file mode 100644 index 0000000000000000000000000000000000000000..7a6b918f0b246caceca90f44f1036431836d41b8 --- /dev/null +++ b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_P_STRUCT_2154.qml @@ -0,0 +1,2 @@ + +255 \ No newline at end of file diff --git a/datasets/bdcharm50/dept_061/GEO050K_HARM_061_P_STRUCT_2154.shp b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_P_STRUCT_2154.shp new file mode 100644 index 0000000000000000000000000000000000000000..31d6fc176edf17624c36a25210df35476a6ca614 Binary files /dev/null and b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_P_STRUCT_2154.shp differ diff --git a/datasets/bdcharm50/dept_061/GEO050K_HARM_061_P_STRUCT_2154.shx b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_P_STRUCT_2154.shx new file mode 100644 index 0000000000000000000000000000000000000000..f76d81e9ad2838351688873413ceeb4860b31f99 Binary files /dev/null and b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_P_STRUCT_2154.shx differ diff --git a/datasets/bdcharm50/dept_061/GEO050K_HARM_061_S_FGEOL_2154.dbf b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_S_FGEOL_2154.dbf new file mode 100644 index 0000000000000000000000000000000000000000..b61ed017e95de3b5ce1f24094193b4d3e5ff772b --- /dev/null +++ b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_S_FGEOL_2154.dbf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dd38bf36b15c89a63a74d8bef4bcebb4afb1534fcd98860e3a96d23046f87c98 +size 4080749 diff --git a/datasets/bdcharm50/dept_061/GEO050K_HARM_061_S_FGEOL_2154.lyr b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_S_FGEOL_2154.lyr new file mode 100644 index 0000000000000000000000000000000000000000..885efbca6bb72b68041a4d9b1e63b98aa33d2ada --- /dev/null +++ b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_S_FGEOL_2154.lyr @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1cb99ebd851db7f701957f4dd7b1c78ffb20212e15b035094fce871c3948cec2 +size 666112 diff --git a/datasets/bdcharm50/dept_061/GEO050K_HARM_061_S_FGEOL_2154.prj b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_S_FGEOL_2154.prj new file mode 100644 index 0000000000000000000000000000000000000000..56757fc434d98d5eddf8c29389e42675dd4845ab --- /dev/null +++ b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_S_FGEOL_2154.prj @@ -0,0 +1 @@ +PROJCS["RGF93_Lambert_93",GEOGCS["GCS_RGF_1993",DATUM["D_RGF_1993",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",700000.0],PARAMETER["False_Northing",6600000.0],PARAMETER["Central_Meridian",3.0],PARAMETER["Standard_Parallel_1",44.0],PARAMETER["Standard_Parallel_2",49.0],PARAMETER["Latitude_Of_Origin",46.5],UNIT["Meter",1.0]] \ No newline at end of file diff --git a/datasets/bdcharm50/dept_061/GEO050K_HARM_061_S_FGEOL_2154.qml b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_S_FGEOL_2154.qml new file mode 100644 index 0000000000000000000000000000000000000000..f81974d3f83faa510f54ef3d1238fb0e759efda1 --- /dev/null +++ b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_S_FGEOL_2154.qml @@ -0,0 +1,2 @@ + +255 \ No newline at end of file diff --git a/datasets/bdcharm50/dept_061/GEO050K_HARM_061_S_FGEOL_2154.shp b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_S_FGEOL_2154.shp new file mode 100644 index 0000000000000000000000000000000000000000..229924591b6fd7c538d8122c4c895eac0ae9cbaf --- /dev/null +++ b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_S_FGEOL_2154.shp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:aef56e596d16181cc954119b898e3e442671cb47e1045203e9162a245ab21c6a +size 19079416 diff --git a/datasets/bdcharm50/dept_061/GEO050K_HARM_061_S_FGEOL_2154.shx b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_S_FGEOL_2154.shx new file mode 100644 index 0000000000000000000000000000000000000000..c3aa4e088dc7b7a60765a95b924d21a282c73bda Binary files /dev/null and b/datasets/bdcharm50/dept_061/GEO050K_HARM_061_S_FGEOL_2154.shx differ diff --git a/datasets/idpr_brgm_live.csv b/datasets/idpr_brgm_live.csv new file mode 100644 index 0000000000000000000000000000000000000000..422a6724370f8f232a79f84503d628acd9d6194b --- /dev/null +++ b/datasets/idpr_brgm_live.csv @@ -0,0 +1,28 @@ +station_code,idpr_value_brgm_live,latitude,longitude +H602021010,,48.748705218,0.58156195 +H605641401,,49.034118991,0.808378297 +H620021010,,49.183882705,0.714759598 +H623021010,,49.242018124,0.694854113 +H600021010,,48.718036538,0.430946285 +H603021010,,48.822095344,0.710239413 +H605021010,,48.952759299,0.743674684 +H605022010,,49.030154418,0.814920403 +H605641101,,48.984918738,0.789022568 +H605641201,,49.047068778,0.799839826 +H606000101,,49.091746041,0.759834916 +H623022010,,49.340856041,0.58089832 +H402021010,,48.44823808,1.205047075 +H403301101,,48.386346937,1.477223775 +H404021010,,48.441954003,1.498980903 +H420021010,,48.77678274,1.379648722 +H420021011,,48.776718416,1.379891235 +H403021010,,48.449158817,1.291192655 +H404021101,,48.46726995,1.483793322 +H414000201,,48.645793808,1.542543476 +H416021010,,48.700852684,1.442183941 +H420021012,,48.777083556,1.379365749 +H426021010,,48.792029301,1.376915068 +H426021201,,48.792090349,1.37670564 +H431021010,,49.01307446,1.378224742 +H432021010,,49.114382066,1.208807304 +H438021010,,49.224003868,1.177680812 diff --git a/datasets/worldcover_landcover.csv b/datasets/worldcover_landcover.csv new file mode 100644 index 0000000000000000000000000000000000000000..f47f24b6f69840ecb55b2d8a06ed9556a522bff1 --- /dev/null +++ b/datasets/worldcover_landcover.csv @@ -0,0 +1,28 @@ +station_code,landcover_class_code,landcover_class_name +H602021010,10,Tree cover +H605641401,50,Built-up +H620021010,10,Tree cover +H623021010,10,Tree cover +H600021010,10,Tree cover +H603021010,50,Built-up +H605021010,30,Grassland +H605022010,10,Tree cover +H605641101,10,Tree cover +H605641201,10,Tree cover +H606000101,10,Tree cover +H623022010,10,Tree cover +H402021010,10,Tree cover +H403301101,10,Tree cover +H404021010,10,Tree cover +H420021010,10,Tree cover +H420021011,10,Tree cover +H403021010,30,Grassland +H404021101,50,Built-up +H414000201,10,Tree cover +H416021010,10,Tree cover +H420021012,10,Tree cover +H426021010,10,Tree cover +H426021201,10,Tree cover +H431021010,10,Tree cover +H432021010,10,Tree cover +H438021010,10,Tree cover diff --git a/datasets/worldcover_ndvi.csv b/datasets/worldcover_ndvi.csv new file mode 100644 index 0000000000000000000000000000000000000000..1076fbf7b854b618e1f3aa0bd251a4f868f53f45 --- /dev/null +++ b/datasets/worldcover_ndvi.csv @@ -0,0 +1,28 @@ +station_code,ndvi_p90,ndvi_p50,ndvi_p10 +H602021010,223.0,210.0,181.0 +H600021010,210.0,200.0,181.0 +H603021010,172.0,168.0,149.0 +H605021010,220.0,213.0,186.0 +H605641101,236.0,213.0,194.0 +H402021010,214.0,202.0,183.0 +H403301101,227.0,214.0,187.0 +H404021010,205.0,195.0,166.0 +H420021010,235.0,221.0,196.0 +H420021011,230.0,207.0,176.0 +H403021010,236.0,228.0,174.0 +H404021101,160.0,156.0,150.0 +H414000201,193.0,186.0,176.0 +H416021010,213.0,206.0,191.0 +H420021012,222.0,202.0,176.0 +H426021010,197.0,188.0,170.0 +H426021201,226.0,212.0,201.0 +H605641401,180.0,170.0,164.0 +H620021010,239.0,216.0,189.0 +H623021010,200.0,181.0,172.0 +H605022010,226.0,205.0,193.0 +H605641201,218.0,205.0,178.0 +H606000101,223.0,198.0,176.0 +H623022010,212.0,200.0,163.0 +H431021010,199.0,176.0,161.0 +H432021010,204.0,189.0,162.0 +H438021010,215.0,195.0,172.0 diff --git a/scripts/__pycache__/download_bdcavites.cpython-311.pyc b/scripts/__pycache__/download_bdcavites.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..47145c20a51e42a636d4c3f8c3d37562605f59e9 Binary files /dev/null and b/scripts/__pycache__/download_bdcavites.cpython-311.pyc differ diff --git a/scripts/__pycache__/download_bdcharm.cpython-311.pyc b/scripts/__pycache__/download_bdcharm.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a0768dc3cba04bf14e39a9678ce54aee82ee830c Binary files /dev/null and b/scripts/__pycache__/download_bdcharm.cpython-311.pyc differ