Commit b7fd1371 authored by Rodrigo Tapia-McClung's avatar Rodrigo Tapia-McClung

Charts work with timeDimension and date change.

parent fe147516
......@@ -5,8 +5,8 @@
* August 2019
*/
/* globals flatten, map, userFiles, userDates, indicators, indicatorVars, indicatorsNames */
/* exported makeIndicatorGraph, getData, queryIndicators */
/* globals map, userFiles, userDates, indicators, indicatorVars, indicatorsNames */
/* exported makeIndicatorGraph, getData */
let minDate, maxDate, xLine, yLine;
......@@ -15,69 +15,31 @@ const sortByDateAscending = (a, b) => {
return a.date - b.date;
}
const queryIndicators = () => {
return Promise.all(indicators.map(queryMonths))
// the result is an array of arrays, so we'll flatten them here
.then(flatten);
}
const queryMonths = (indicator) => {
return Promise.all(userFiles.map( monthYear => {
return getData(monthYear, indicator);
}));
}
//queryIndicators(queryMonths).then( results => {...} )
const getData = (monthYear, indicator) => {
return new Promise( resolve => {
//TODO: scale data to appropriate units? m2-> ha? m -> km?
const getData = async (indicator) => {
//let data = [{name: `${indicator}0`, values: []}];
let timeParse = d3.timeParse("%B_%Y");
//timeFormat = d3.timeFormat("%B %Y");
const promises = userFiles.map( async monthYear => {
// get sum of area/perimeter or average of coast/fractal dimension
let queryDB = indicator == "costa" || indicator == "df" ?
`http://localhost:8090/data/query/${monthYear}?columns=avg(${indicator})%20as%20${indicator}` :
`http://localhost:8090/data/query/${monthYear}?columns=sum(${indicator})%20as%20${indicator}`;
d3.json(queryDB).then( result => {
/*data[0].values.push({
"date": timeParse(monthYear),
"value": +result[0][indicator]
const dbData = await d3.json(queryDB);
return {date: timeParse(monthYear), value: dbData[0]};
});
data.forEach(d => d.values.sort(sortByDateAscending));
resolve(data[0])*/
resolve({date: timeParse(monthYear), value: result[0][indicator]})
});
});
}
//TODO: scale data to appropriate units? m2-> ha? m -> km?
const getData2 = async (indicator) => {
const chartData = await Promise.all(promises);
let data = [{name: `${indicator}0`, values: []}];
let timeParse = d3.timeParse("%B_%Y");
//timeFormat = d3.timeFormat("%B %Y");
userFiles.map( async monthYear => {
// get sum of area/perimeter or average of coast/fractal dimension
let queryDB = indicator == "costa" || indicator == "df" ?
`http://localhost:8090/data/query/${monthYear}?columns=avg(${indicator})%20as%20${indicator}` :
`http://localhost:8090/data/query/${monthYear}?columns=sum(${indicator})%20as%20${indicator}`;
/*d3.json(queryDB).then( result => {
chartData.map( monthYear => {
data[0].values.push({
"date": timeParse(monthYear),
"value": +result[0][indicator]
"date": monthYear.date,
"value": +monthYear.value[indicator]
});
data.forEach(d => d.values.sort(sortByDateAscending));
});*/
let dbData = await d3.json(queryDB);
data[0].values.push({
"date": timeParse(monthYear),
"value": await +dbData[0][indicator]
});
data.forEach(d => d.values.sort(sortByDateAscending));
})
data.forEach(d => d.values.sort(sortByDateAscending));
return data;
}
......@@ -112,7 +74,6 @@ function makeIndicatorGraph() {
function chart(selection) {
console.log("data values: ", data[0].values) // FIXME: get async data here...
// get data ranges using values from displayName
minDate = d3.min(data[0].values, d => {
return d[displayName];
......@@ -122,7 +83,7 @@ function makeIndicatorGraph() {
return d[displayName];
});
maxDate = d3.timeDay.offset(maxDate, 15) // get next month to get correct x-axis alignment
console.log("minDate: ", minDate)
selection.each(function () {
// add graph svg to selected container on webpage
......@@ -282,7 +243,7 @@ function makeIndicatorGraph() {
minDate = d3.min(data[0].values, d => {
return d[displayName];
});
console.log("update data: ", data[0].values.length)
minDate = d3.timeDay.offset(minDate, -15) // get previous month to get correct x-axis alignment
maxDate = d3.max(data[0].values, d => {
return d[displayName];
......
......@@ -6,7 +6,7 @@
*/
/* globals omnivore, Promise, chroma, makeBaseMap, makeIndicatorGraph, getData */
/* exported userFiles, userDates, layerControl, queryFiles, flatten */
/* exported userFiles, userDates, layerControl */
let timeParse,
timeFormat,
......@@ -338,61 +338,6 @@ const getMinMax = table => {
});
}
const updateMap = (mapData) => {
//console.log(mapData);
console.log(userFiles);
// ckear tiles
currentTiles = {};
//retrieve or create tiles for current dates
userFiles.forEach( monthYear => {
if (Object.keys(allTiles).includes(monthYear)) {
currentTiles[monthYear] = allTiles[monthYear]; // recover tile if it has already been created
//currentJSONs[monthYear] = allJSONs[monthYear]; // recover json if it has already been created
return; // if file has already been processed, exit
} else { // if file cannot be found in allTiles, then add 1 to the number of files to process
let newTile = mapboxLayer(monthYear);
glmap._glMap.addLayer(newTile);
if (monthYear == userFiles[0]) {
glmap._glMap.setPaintProperty(monthYear, "fill-opacity", 0.7)
}
}
});
// update timeDimension times
timeLayer._timeDimension.setAvailableTimes(userDates, "replace");
//timeLayer._timeDimension.setCurrentTime(mapData.min);
// clear minmax indicators objects
maxIndicators = {},
minIndicators = {};
indicators.forEach( (indicator) => {
maxIndicators[indicator] = 0;
minIndicators[indicator] = 1e30;
});
// query db for new minmax values then style tiles
new Promise( resolve => {
queryFiles().then( minmax => {
minmax.map( minmaxMonth => {
indicators.forEach( (indicator) => {
minIndicators[indicator] = Math.min(minIndicators[indicator], minmaxMonth[`min${indicator}`]);
maxIndicators[indicator] = Math.max(maxIndicators[indicator], minmaxMonth[`max${indicator}`]);
});
});
resolve({"map": map, "minIndicators": minIndicators, "maxIndicators": maxIndicators});
})
}).then( values => { // once we have new minmax values, style all tiles
let option = $("#indicatorSelect").val(), // option selected from dropdrown
min = values.minIndicators,
max = values.maxIndicators;
styleTiles(option, min, max)
.then(legend.addTo(map)); // add legend control -> it updates
//TODO: update charts
});
}
const populateMap = (mapData) => {
let map = mapData.map,
minIndicators = mapData.minIndicators,
......@@ -467,7 +412,7 @@ const populateMap = (mapData) => {
});
// Define charts with reusable components
indicators.forEach( async (indicator, index) => {
indicators.map( async (indicator, index) => {
// indicatorVars[indicator].chart gives areaChart, perimeterChart, etc.
// First, make all charts with same general options
indicatorVars[indicator].chart = makeIndicatorGraph()
......@@ -485,22 +430,83 @@ const populateMap = (mapData) => {
.title(indicatorsUnits[index] == "" ? indicatorsNames[index] :
`${indicatorsNames[index]} (${indicatorsUnits[index]})`);
let data = await getData2(indicator);
await indicatorVars[indicator].chart.data(data);
console.log(data, data[0]) // data has stuff, but data[0] has empty values
// Finally, set chart data with async function calling stuff from DB
indicatorVars[indicator].chart.data( await getData(indicator));
// create chart with passed options
d3.select(indicatorVars[indicator].container)
.call(await indicatorVars[indicator].chart);
});
.call(indicatorVars[indicator].chart);
// Reload chart data and force chart update
indicatorVars[indicator].chartData = indicatorVars[indicator].chart.data(); // get chart data
indicatorVars[indicator].chart.data(indicatorVars[indicator].chartData); // set chart data
// Highlight plot title according to selected option
let option = $("#indicatorSelect").val(); // option selected from dropdrown
d3.select(indicatorVars[option].container).select("svg text.title").classed("active", true);
});
// TODO: basemap
//makeBaseMap(); // basemap.js
}
const updateMap = (mapData) => {
console.log(userFiles);
// clear tiles
currentTiles = {};
//retrieve or create tiles for current dates
userFiles.forEach( monthYear => {
if (Object.keys(allTiles).includes(monthYear)) {
currentTiles[monthYear] = allTiles[monthYear]; // recover tile if it has already been created
//currentJSONs[monthYear] = allJSONs[monthYear]; // recover json if it has already been created
return; // if file has already been processed, exit
} else { // if file cannot be found in allTiles, then add 1 to the number of files to process
let newTile = mapboxLayer(monthYear);
glmap._glMap.addLayer(newTile);
if (monthYear == userFiles[0]) {
glmap._glMap.setPaintProperty(monthYear, "fill-opacity", 0.7)
}
}
});
// update timeDimension times
timeLayer._timeDimension.setAvailableTimes(userDates, "replace");
//timeLayer._timeDimension.setCurrentTime(mapData.min);
// clear minmax indicators objects
maxIndicators = {},
minIndicators = {};
indicators.forEach( (indicator) => {
maxIndicators[indicator] = 0;
minIndicators[indicator] = 1e30;
});
// query db for new minmax values then style tiles
new Promise( resolve => {
queryFiles().then( minmax => {
minmax.map( minmaxMonth => {
indicators.forEach( (indicator) => {
minIndicators[indicator] = Math.min(minIndicators[indicator], minmaxMonth[`min${indicator}`]);
maxIndicators[indicator] = Math.max(maxIndicators[indicator], minmaxMonth[`max${indicator}`]);
});
});
resolve({"map": map, "minIndicators": minIndicators, "maxIndicators": maxIndicators});
})
}).then( values => { // once we have new minmax values, style all tiles
let option = $("#indicatorSelect").val(), // option selected from dropdrown
min = values.minIndicators,
max = values.maxIndicators;
styleTiles(option, min, max)
.then(legend.addTo(map)); // add legend control -> it updates
});
// Update charts
updateCharts();
}
const updateCharts = () => {
indicators.map( async (indicator) => {
indicatorVars[indicator].chart.data( await getData(indicator));
});
}
// define MVT layer for given month table and all indicators
const mapboxLayer = (monthYear) => {
......@@ -538,7 +544,6 @@ const mapboxLayer = (monthYear) => {
return pbfLayer;
}
const setupTimeDimensionControl = () => {
L.Control.TimeDimensionCustom = L.Control.TimeDimension.extend({
_getDisplayDateFormat: date => {
......@@ -707,5 +712,3 @@ legend.onAdd = () => {
div.innerHTML = html;
return div;
};
\ No newline at end of file
// TODO: add charts
\ No newline at end of file
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