RAVE SCOUT: análisis de aislamiento de España y visor de localizaciones
Barrido de los 498.528 km² de la península y Baleares sobre malla de 100 m (EPSG:3035) para localizar sitios alejados de todo con acceso rodado. - 12,5 M de edificios y 1,4 M de km de viales de OSM, incluidos los países vecinos para no inflar el aislamiento en la franja fronteriza - Espacios protegidos oficiales (Red Natura 2000 + designación nacional) vía la Agencia Europea de Medio Ambiente: cubren el 29 % del país frente al 15 % que tenía OSM - Modelo acústico con propagación real; es el filtro que de verdad corta, y deja 505 km² en toda España - 355 localizaciones valoradas de 1 a 5 estrellas en seis criterios - Visor autónomo con relieve, ortofoto PNOA por localización, relieve 3D y mapa deslizante con satélite, catastro y espacios protegidos
This commit is contained in:
commit
d4b3b803e0
394 changed files with 7393 additions and 0 deletions
74
src/validate_coverage.py
Normal file
74
src/validate_coverage.py
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
"""Control de sesgo: ¿está OSM igual de mapeado en toda España?
|
||||
|
||||
Importa porque el modelo mide aislamiento como "distancia al edificio más
|
||||
cercano". Si una comunidad tiene los edificios a medio mapear, sus celdas
|
||||
saldrán aisladas por un hueco en los datos y no por estar lejos de nada.
|
||||
El import del Catastro cubre casi toda España pero no Navarra ni Euskadi, que
|
||||
tienen catastro propio, así que el sesgo es esperable y hay que cuantificarlo.
|
||||
|
||||
Como no usamos datos externos de población, el contraste es interno: viales por
|
||||
km2 (que en España están mapeados de forma homogénea) frente a edificios por
|
||||
km2. Si la proporción se desploma en una región, es un agujero de datos.
|
||||
"""
|
||||
import pickle
|
||||
import sys
|
||||
|
||||
import numpy as np
|
||||
import rasterio.features
|
||||
from shapely.geometry import mapping
|
||||
|
||||
sys.path.insert(0, str(__file__.rsplit("/", 1)[0]))
|
||||
import config as C
|
||||
|
||||
STEP_M = 60.0 # espaciado de densificación usado en extract_osm
|
||||
|
||||
|
||||
def main():
|
||||
with open(C.INTERIM / "area_admin_region.pkl", "rb") as fh:
|
||||
regs = [r for r in pickle.load(fh) if r["geom"].area > 1e6]
|
||||
regs.sort(key=lambda r: -r["geom"].area)
|
||||
|
||||
rid = rasterio.features.rasterize(
|
||||
[(mapping(r["geom"]), i + 1) for i, r in enumerate(regs)],
|
||||
out_shape=(C.HEIGHT, C.WIDTH), transform=C.TRANSFORM,
|
||||
fill=0, dtype=np.uint8, all_touched=False)
|
||||
|
||||
def counts_for(base):
|
||||
a = np.load(C.INTERIM / f"{base}.npy")
|
||||
r, c = C.xy_to_rowcol(a[0], a[1])
|
||||
ok = C.inside(r, c)
|
||||
ids = rid[r[ok], c[ok]]
|
||||
return np.bincount(ids, minlength=len(regs) + 1)
|
||||
|
||||
b = counts_for("buildings")
|
||||
v = counts_for("line_minor") + counts_for("line_track")
|
||||
cells = np.bincount(rid.ravel(), minlength=len(regs) + 1)
|
||||
|
||||
print(f"{'comunidad':24s} {'km2':>8s} {'edif':>10s} {'edif/km2':>9s} "
|
||||
f"{'vial km':>9s} {'edif/vial-km':>13s}")
|
||||
print("-" * 78)
|
||||
ratios = []
|
||||
for i, r in enumerate(regs, start=1):
|
||||
km2 = cells[i] * 0.01
|
||||
if km2 < 100:
|
||||
continue
|
||||
vial_km = v[i] * STEP_M / 1000.0
|
||||
ratio = b[i] / vial_km if vial_km else 0
|
||||
ratios.append((ratio, r["name"]))
|
||||
print(f"{r['name'][:24]:24s} {km2:8,.0f} {b[i]:10,} {b[i]/km2:9.1f} "
|
||||
f"{vial_km:9,.0f} {ratio:13.2f}")
|
||||
|
||||
med = np.median([x for x, _ in ratios])
|
||||
print("-" * 78)
|
||||
print(f"mediana edif/vial-km: {med:.2f}")
|
||||
print("\nregiones con menos de la mitad de la mediana "
|
||||
"(sospecha de infra-mapeo de edificios):")
|
||||
flagged = [n for x, n in ratios if x < 0.5 * med]
|
||||
for n in flagged:
|
||||
print(f" - {n}")
|
||||
if not flagged:
|
||||
print(" ninguna")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Loading…
Add table
Add a link
Reference in a new issue