Commit 4374ac3e authored by Rodrigo Tapia-McClung's avatar Rodrigo Tapia-McClung

Read original data and transpose. Use geojson instead of mbtiles

parent b4935b0b
This diff is collapsed.
Catalogo de estaciones,,,,,,
cve_estac,nom_estac,longitud,latitud,alt,obs_estac,id_station
ACO,Acolman,-98.912003,19.635501,2198,,484150020109
AJU,Ajusco,-99.162611,19.154286,2942,,484090120400
AJM,Ajusco Medio,-99.207744,19.272161,2548,,484090120609
ARA,Aragón,-99.074549,19.470218,2200,Finalizó operación en 2010,484090050301
ATI,Atizapan,-99.254133,19.576963,2341,,484150130101
AZC,Azcapotzalco,-99.198657,19.487728,2279,Finalizó operación en 2010,484090020201
BJU,Benito Juárez,-99.159596,19.370464,2249,Finalizó operación en 2005,484090140201
CAM,Camarones,-99.169794,19.468404,2233,,484090020301
CCA,Centro de Ciencias de la Atmósfera,-99.176111,19.326111,2294,,484090030501
CES,Cerro de la Estrella,-99.074678,19.334731,2219,Finalizó operación en 2010,484090070111
CFE,Museo Tecnológico de la CFE,-99.194279,19.414393,2287,Finalizó operación en 1996,484090160102
CHO,Chalco,-98.886088,19.266948,2253,,484150250109
COR,CORENA,-99.02604,19.265346,2242,,484090130204
COY,Coyoacán,-99.157101,19.350258,2260,,484090030303
CUA,Cuajimalpa,-99.291705,19.365313,2704,,484090040109
CUI,Cuitláhuac,-99.165849,19.469859,2255,Finalizó operación en 1993,484090020101
CUT,Cuautitlán,-99.198602,19.722186,2263,,484150950109
DIC,Diconsa,-99.185774,19.298819,2305,,484090120304
EAJ,Ecoguardas Ajusco,-99.203971,19.271222,2584,,484090120404
EDL,Exconv. Desierto Leones,-99.310635,19.313357,2980,,484090040204
FAC,FES Acatlán,-99.243524,19.482473,2299,,484150570109
FAN,Felipe Ángeles,-99.17492,19.299126,2279,Finalizó operación en 1996,484090120102
GAM,Gustavo A. Madero,-99.094517,19.4827,2227,,484090050809
HAN,Hangares,-99.083623,19.420518,2235,Finalizó operación en 2006,484090170209
HGM,Hospital General de México,-99.152207,19.411617,2234,,484090150409
IBM,Legaria,-99.21536,19.443319,2314,,484090160504
IMP,Inst. Mexicano del Petróleo,-99.147294,19.487561,2250,Finalizó operación en 2010,484090050209
INN,Investigaciones Nucleares,-99.38052,19.291968,3082,,484150620109
IZT,Iztacalco,-99.117641,19.384413,2238,,484090060101
LAA,Lab. de Analisis Ambiental,-99.147312,19.483781,2255,,484090050604
LAG,Lagunilla,-99.135183,19.44242,2223,Finalizó operación en 2010,484090150101
LLA,Los Laureles,-99.039644,19.578792,2230,,484150330201
LOM,Lomas,-99.242062,19.403,2434,,484090160406
LPR,La Presa,-99.11772,19.534727,2302,,484151040203
LVI,La Villa,-99.117749,19.46789,2228,Finalizó operación en 2010,484090050101
MCM,Museo de la Cd. de México,-99.131924,19.429071,2237,,484090150304
MER,Merced,-99.119594,19.42461,2245,,484090170127
MGH,Mguel Hidalgo,-99.20266,19.40405,2327,,484090160609
MIN,Metro Insurgentes,-99.162885,19.42144,2231,Finalizó operación en 2007,484090150201
MON,Montecillo,-98.902853,19.460415,2252,,484150990113
MPA,Milpa Alta,-98.990189,19.1769,2594,,484090090104
NET,Netzahualcoyotl,-99.026119,19.42115,2230,Finalizó operación en 2000,484150580201
NEZ,Nezahualcóyotl,-99.028212,19.393734,2235,,484150580115
PED,Pedregal,-99.204136,19.325146,2326,,484090100127
PER,La Perla,-98.991858,19.38286,2237,Finalizó operación en 2011,484150580303
PLA,Plateros,-99.200109,19.365869,2345,Finalizó operación en 2010,484090100209
POT,Portales,-99.145766,19.376494,2237,Finalizó operación en 1996,484090140102
SAG,San Agustín,-99.030324,19.532968,2241,,484150330327
SFE,Santa fe,-99.262865,19.357357,2599,,484090040309
SHA,Secretaría de Hacienda,-99.207868,19.446203,2272,,484090160202
SJA,San Juan Aragón,-99.086095,19.452592,2258,,484090050701
SNT,San Nicolas Totolapan,-99.256462,19.250385,2946,,484090080104
SUR,Santa Ursula,-99.149994,19.31448,2279,,484090030109
TAC,Tacuba,-99.202455,19.453907,2275,Finalizó operación en 2010,484090160309
TAH,Tlahuac,-99.010564,19.246459,2297,,484090130309
TAX,Taxqueña,-99.123204,19.335689,2242,Finalizó operación en 2010,484090030201
TEC,Cerro del Tepeyac,-99.114229,19.487227,2265,,484090050404
TLA,Tlalnepantla,-99.204597,19.529077,2311,,484151040115
TLI,Tultitlán,-99.177173,19.602542,2313,,484151090101
TPN,Tlalpan,-99.184177,19.257041,2522,,484090120209
UAX,UAM Xochimilco,-99.103629,19.304441,2246,,484090030401
UIZ,UAM Iztapalapa,-99.07388,19.360794,2221,,484090070219
UNM,Unidad Movil,-99.147137,19.482238,,,484090000099
VAL,Vallejo,-99.165702,19.522437,2248,Finalizó operación en 2010,484090050501
VIF,Villa de las Flores,-99.09659,19.658223,2242,,484150200109
XAL,Xalostoc,-99.0824,19.525995,2160,,484150330415
XCH,Xochimilco,-99.118252,19.267066,2243,Finalizó operación en 1999,484090130102
FAR,FES Aragón,-99.046176,19.473692,2230,,484800150584
SAC,Santiago Acahualtepec,-99.009381,19.34561,2293,,484800090073
This diff is collapsed.
This diff is collapsed.
......@@ -2,10 +2,10 @@
* Copyright 2021 - All rights reserved.
* Rodrigo Tapia-McClung
*
* February-June 2021
* February-July 2021
*/
/* global mapboxgl, turf */
/* global mapboxgl, turf, Papa */
const windowUrl = new URL(window.location.href);
const baseUrl = windowUrl.hostname == "localhost" ?
......@@ -20,14 +20,36 @@ let cdmx, estaciones, ozono, fechas,
playing = false,
animate;
// Read CDMX boundaries
fetch(`${baseUrl}/data/cdmx.geojson`)
.then(response => response.json())
.then(d => cdmx = d);
fetch(`${baseUrl}/data/estaciones.geojson`)
.then(response => response.json())
.then(d => estaciones = d);
// Read and parse csv station data
fetch(`${baseUrl}/data/cat_estacion.csv`)
.then(response => response.arrayBuffer())
.then(d => new TextDecoder("iso-8859-1").decode(d).split("\r\n"))
.then(d => { // arrange elements as a decent array
let array = [];
d.forEach( d => array.push(d.split(",")));
let array2 = array.slice(1, -1); // remove spurious first and last line
const [keys, ...values] = array2; // deconstruct
let estacionesCSV = values.map( array2 => // create useful object of key:value pairs for each station
array2.reduce((a, v, i) => ({ ...a, [keys[i]]: v }), {})
);
let estacionesArray = [];
estacionesCSV.forEach( e => { // create features for feature collection
let location = turf.point([+e.longitud, +e.latitud], {
cve_estac: e.cve_estac,
nom_estac: e.nom_estac,
longitud: +e.longitud,
latitud: +e.latitud,
alt: +e.alt
});
estacionesArray.push(location);
});
estaciones = turf.featureCollection(estacionesArray);
});
const papaPromise = url => {
return new Promise(function (resolve, reject) {
......@@ -36,19 +58,14 @@ const papaPromise = url => {
header: true,
skipEmptyLines: true,
complete: resolve,
error: reject,
encoding: "UTF8"
});
});
}
let ozonoPromise = papaPromise(`${baseUrl}/data/ozono.csv`); // ozono es en ppb: 10^12
// FIXME: check and fix date order in data
/*const getOzono = fetch(`${baseUrl}/ozono.csv`)
.then(response => response.text())
.then(d => Papa.parse(d))
.catch(err => console.log(err))
getOzono.then(d => ozono = d.data);
*/
// read ozono csv data
let ozonoPromise = papaPromise(`${baseUrl}/data/O3.csv`); // ozono es en ppb: 10^12
let map = new mapboxgl.Map({
"container": "mexmap",
......@@ -61,14 +78,13 @@ let map = new mapboxgl.Map({
});
map.addControl(new mapboxgl.NavigationControl());
// map language - doesn't quite work
/*map.addControl(new MapboxLanguage({
defaultLanguage: 'es'
}));*/
// TODO: display more friendly dates
const dateTimeOptions = {
/*const dateTimeOptions = {
weekday: "short",
day: "numeric",
month:"short",
......@@ -79,11 +95,33 @@ const dateTimeOptions = {
//minute: '2-digit',
hour12: false,
timeZone: 'America/Mexico_City'
};
};*/
//let myDate = "1577919600000";
//let myDate = "1605218400000";
const transpose = values => {
if (!Array.isArray(values))
throw new Error("`values` must be an array");
if (values.length === 0)
return {};
const keys = Object.keys(values[0]);
const transposed = {
data: {},
count: values.length,
};
keys.forEach(key => {
transposed.data[key] = [];
values.forEach(value => {
transposed.data[key].push(value[key]);
});
});
return transposed;
}
const range = (start, stop, step = 1) =>
Array(Math.ceil((stop - start) / step)).fill(start).map((x, y) => x + y * step);
......@@ -101,7 +139,6 @@ const intersect = (fc1, fc2) => {
}
const makeSurface = date => {
//map.getSource("estaciones").serialize().data
// filter data for given date value
let subdata = ozono.map(d => { return {time: d["time"], [date]: d[date]} });
let maxValue = Math.max.apply(Math, subdata.map( d=> d[date]));
......@@ -109,12 +146,13 @@ const makeSurface = date => {
turf.featureEach(estaciones, point => {
let stationData = subdata.filter( i => i.time == point.properties.cve_estac);
point.properties.calidad = stationData[0] && parseFloat(stationData[0][date]) != -99 ? parseFloat(stationData[0][date]) : 0;
// TODO: remove station instead of assigning value to 0 when value = -99?
// use value to style station dot
map.setFeatureState(
{
// source tileset and source layer
// source tileset and source layer: sourceLayer is needed only if using mbtiles
source: "estaciones",
sourceLayer: "estaciones",
//sourceLayer: "estaciones",
// unique ID row name
id: point.properties.cve_estac
},
......@@ -129,7 +167,7 @@ const makeSurface = date => {
let options = {gridType: "point", property: "calidad", units: "kilometers", weight: 2};
let grid = turf.interpolate(estaciones, 0.75, options);
let breaks = range(0, maxValue != -99 ? maxValue : 0 + 1, 5);
let breaks = range(0, maxValue != -99 ? maxValue : 1, 5);
//let lines = turf.isolines(grid, breaks, {zProperty: "calidad"});
let bValues = breaks.map( b => { return {value: b} });
let bands = turf.isobands(grid, breaks, {zProperty: "calidad", breaksProperties: bValues});
......@@ -157,10 +195,17 @@ const run = () => {
map.on("style.load", async () => {
map.addSource("estaciones", {
// add vector tile source
/*map.addSource("estaciones", {
"type": "vector",
"tiles": [`${baseUrl}/estaciones/mbtiles/{z}/{x}/{y}.pbf`],
promoteId: "cve_estac"
});*/
// or geojson source
map.addSource("estaciones", {
type: "geojson",
data: estaciones,
promoteId: "cve_estac"
});
map.addSource("interpolation", {
......@@ -190,9 +235,26 @@ map.on("style.load", async () => {
clearInterval(animate);
}
});
// after reading ozono csv
ozonoPromise.then( results => {
ozono = results.data;
fechas = Object.keys(ozono[0]).slice(1,-1).map(d => parseInt(d));
let data = results.data;
data.forEach( d => d.time = Date.parse(new Date(`${d.FECHA} ${d.HORA}:0:0`))); // calculate new time
let transposed = transpose(data).data; // transpose data
// TODO: make everything without transposing data?
let stations = Object.keys(transposed).filter(
s => s != "FECHA" && s != "HORA" && s != "time" // ignore unwanted keys
);
ozono = [];
stations.forEach( station => { // create appropriate object structure
let obj = {};
obj["time"] = station;
transposed.time.forEach((time, index) => {
obj[time] = transposed[station][index];
});
ozono.push(obj);
});
fechas = Object.keys(ozono[0]).slice(1, -1).map(d => parseInt(d));
slider.min = fechas[0];
slider.max = fechas[fechas.length-1];
slider.step = 3600000;
......@@ -203,20 +265,6 @@ map.on("style.load", async () => {
let maxValue = Math.max(...ozono.map( d => Object.values(d)).flat().filter(val => !isNaN(val)));
/*let expression = ["match", ["get", "cve_estac"]];
results.data.forEach( row => {
map.setFeatureState(
{
// source tileset and source layer
source: "estaciones",
sourceLayer: "estaciones",
// unique ID row name
id: row.time
},
// Add rows you want to style/interact with
{
calidad: parseFloat(row[fechas[0]]) != -99 ? parseFloat(row[fechas[0]]) : 0
//candidate: row.candidate,
}
);
var green = (parseFloat(row[myDate]) / maxValue) * 255;
var color = "rgba(" + 0 + ", " + green + ", " + 0 + ", 1)";
expression.push(row["time"], color);
......@@ -242,7 +290,7 @@ map.on("style.load", async () => {
"id": "estaciones-circle",
"type": "circle",
"source": "estaciones",
"source-layer": "estaciones",
//"source-layer": "estaciones",
"layout": {},
"paint": {
"circle-radius": 4,
......@@ -359,6 +407,7 @@ map.on("style.load", async () => {
.setHTML("Estación: " + estacion + "<br/>Clave: " + cve_estac + "<br/>Valor: " + calidad)
.addTo(map);
});
// TODO: update popup value when already hovered on
// Remove popup on mouse out
map.on("mouseleave", "estaciones-circle", () => {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment