Área de cada clase de uso de suelo MODIS en la cuenca, en kilómetros cuadrados, de 2001 a 2024. Los mapas de abajo son las figuras ya calculadas. La opacidad solo cambia la imagen.
import { htmlTabla, marcoFigura } from "../_js/portal.js"
NOMBRE = ({
AGRI: "Cultivos",
FRST: "Bosques",
PAST: "Pastizales",
SHRB: "Matorrales",
WETL: "Humedales",
WATR: "Cuerpos de agua",
URBN: "Urbano",
BARR: "Suelo desnudo",
SNOW: "Nieve/Hielo",
CLDN: "Nube/NoData"
})
ORDEN = ["Bosques", "Pastizales", "Matorrales", "Suelo desnudo", "Humedales", "Cuerpos de agua", "Nieve/Hielo", "Urbano", "Cultivos", "Nube/NoData"]
COLOR = ({
Cultivos: "#F5C518",
Bosques: "#2D6A1A",
Pastizales: "#7BC950",
Matorrales: "#8B6914",
Humedales: "#7ECBDB",
"Cuerpos de agua": "#1A5FA8",
Urbano: "#CC2222",
"Suelo desnudo": "#7F8C8D",
"Nieve/Hielo": "#5D6D7E",
"Nube/NoData": "#B0B0B0"
})
nombreClase = (codigo) => NOMBRE[codigo] || codigo
num = (v) => {
const x = +v
return Number.isFinite(x) ? x : null
}
crudoLc = FileAttachment("series/landcover_area.csv").csv({typed: false})
lc = crudoLc.map((d) => ({
anio: +d.anio,
clase: d.clase,
area: num(d.area_km2),
pct: num(d.porcentaje)
})).filter((d) => Number.isFinite(d.anio) && d.area != null)
clases = ORDEN.filter((c) => lc.some((d) => d.clase === c))
anios = [...new Set(lc.map((d) => d.anio))].sort((a, b) => a - b)
anio0 = anios[0]
anio1 = anios[anios.length - 1]
{
const fig = marcoFigura(Plot.plot({
width: 860,
height: 440,
marginLeft: 64,
marginBottom: 44,
y: { grid: true, label: "Área (km²)" },
x: { label: "Año", tickFormat: (v) => String(Math.round(v)) },
color: { legend: true, domain: clases, range: clases.map((c) => COLOR[c] || "#1a5276") },
marks: [
Plot.lineY(lc, {
x: "anio",
y: "area",
stroke: "clase",
tip: true,
title: (d) => `${d.clase}, ${d.anio}: ${d.area.toLocaleString("es-CL", { maximumFractionDigits: 1 })} km² (${d.pct.toLocaleString("es-CL", { maximumFractionDigits: 2 })} %)`
})
]
}), {
titulo: "Área por clase de uso de suelo",
archivo: "landcover_area"
})
const p = document.createElement("p")
p.className = "portal-origen"
p.textContent = "Cada línea es una clase MODIS en la cuenca."
const caja = document.createElement("div")
caja.append(fig, p)
return caja
}
html`<h2>Área al inicio y al final</h2>`
htmlTabla(
[
{ key: "clase", label: "Clase" },
{ key: "a0", label: `km² en ${anio0}`, num: true, dec: 1 },
{ key: "a1", label: `km² en ${anio1}`, num: true, dec: 1 },
{ key: "cambio", label: "Cambio (km²)", num: true, dec: 1 },
{ key: "pct", label: `% en ${anio1}`, num: true, dec: 2 }
],
clases.map((clase) => {
const f0 = lc.find((d) => d.clase === clase && d.anio === anio0)
const f1 = lc.find((d) => d.clase === clase && d.anio === anio1)
const a0 = f0 ? f0.area : 0
const a1 = f1 ? f1.area : 0
return { clase, a0, a1, cambio: a1 - a0, pct: f1 ? f1.pct : 0 }
}).sort((a, b) => b.a1 - a.a1),
"landcover_inicio_fin.csv"
)
capas = [
["Uso de suelo MODIS 2001", "../figs/08-landcover/fig4_mapa_MODIS_2001.png"],
["Uso de suelo MODIS 2014", "../figs/08-landcover/fig5_mapa_MODIS_2014.png"],
["Uso de suelo MODIS 2024", "../figs/08-landcover/fig6_mapa_MODIS_2024.png"],
["Uso de suelo Zhao 2014", "../figs/08-landcover/fig7_mapa_Zhao_2014_30m.png"],
["Cambio MODIS 2001–2024", "../figs/08-landcover/fig8_mapa_cambio_2001_2024.png"]
]
viewof capa = Inputs.select(capas, {label: "Capa", format: (d) => d[0], value: capas[0]})
viewof opacidad = Inputs.range([20, 100], {label: "Opacidad (%)", step: 5, value: 100})
html`<figure class="portal-figura">
<img src="${capa[1]}" alt="${capa[0]}" style="width:100%;opacity:${opacidad / 100}">
<figcaption>${capa[0]}. La leyenda del mapa usa el código corto; la tabla de abajo lo traduce al nombre de la clase.</figcaption>
</figure>`
htmlTabla(
[
{ key: "codigo", label: "Código en el mapa" },
{ key: "clase", label: "Clase" }
],
Object.entries(NOMBRE).map(([codigo, clase]) => ({ codigo, clase })),
"landcover_codigos.csv"
)
filasCambio = (filas) => filas.map((d) => ({
desde: nombreClase(d.from_code),
hacia: nombreClase(d.to_code),
area: num(d.area_km2),
pct: num(d.pct_from_total)
})).filter((d) => d.area != null).sort((a, b) => b.area - a.area)
t2001 = FileAttachment("series/transition_MODIS_2001_2024.csv").csv({typed: false})
tZhao = FileAttachment("series/transition_MODIS2014_Zhao2014.csv").csv({typed: false})
html`<h2>Cambios de clase, 2001 a 2024</h2>`
htmlTabla(
[
{ key: "desde", label: "Desde" },
{ key: "hacia", label: "Hacia" },
{ key: "area", label: "km²", num: true, dec: 1 },
{ key: "pct", label: "% de la cuenca", num: true, dec: 2 }
],
filasCambio(t2001.filter((d) => d.from_code !== d.to_code)),
"transicion_2001_2024.csv"
)
html`<h2>MODIS y Zhao, 2014</h2>
<p class="portal-origen">Cada fila es el área en que una clase MODIS de 2014 coincide con una clase Zhao de 2014. El porcentaje es sobre el total de la cuenca.</p>`
htmlTabla(
[
{ key: "desde", label: "MODIS" },
{ key: "hacia", label: "Zhao" },
{ key: "area", label: "km²", num: true, dec: 1 },
{ key: "pct", label: "% de la cuenca", num: true, dec: 2 }
],
filasCambio(tZhao),
"transicion_modis_zhao.csv"
)
El índice de área foliar MODIS está en un NetCDF de la cuenca (05. Datos_LIA_Modis). Esta página no trae todavía la serie del promedio de cuenca.
Tabla de áreas: 10. CSV/08. Entradas_espaciales/04. Datos_Land Cover_Modis/landcover_area_MODIS_2001_2024.csv. Transiciones: transition_MODIS_2001_2024.csv y transition_MODIS2014_Zhao2014.csv. Mapas: 08. Figs/08. Entradas_espaciales/LandCover/.