Commit a88d9637 authored by Sven Schneider's avatar Sven Schneider
Browse files

refactored aggregation to own js file to seperate chartStuff from aggregation stuff

parent 3c044302
/**
*
* @param {JSON} obj JSON object on which to replace a specific key.
* @param {String} oldKey is the old key in the JSON to be renamed to newKey
* @param {String} newKey is the key that should replace the oldKey
* usage: myjson.forEach((obj) => renameKey(obj, "oldkey", "newkey"));
*/
function renameKey(obj, oldKey, newKey) {
obj[newKey] = obj[oldKey];
delete obj[oldKey];
}
/**
*
* @param {Array} arr is the Array to be converted into a JSON
* @returns {JSON} stringToJsonObject
*/
function convertArray2JSON(arr) {
var arrayToString = JSON.stringify(Object.assign({}, arr)); // convert array to string
var stringToJsonObject = JSON.parse(arrayToString); // convert string to json object
return stringToJsonObject;
}
function createDateFromDateTimeString(jsonData) {
let datx = [];
let daty = [];
const MONTH = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
for (var u = 0; u < jsonData.length; u++) {
daty.push(jsonData[u].temperature);
let date = new Date(jsonData[u].datetime);
let datum = date.getDate();
let month = MONTH[date.getMonth()];
let hour = date.getHours() + ":00";
let newDateStr = datum + "/" + month + "-" + hour;
datx.push(newDateStr);
}
return [datx, daty];
}
/**
* Format the response from SensorThings API to make it suitable for heatmap
* @param {Array} obsArray Response from SensorThings API as array
* @param {Int8} hours Number of hours to aggregate over. If hours=0,
* it will be aggregated by date (e.g. all values recorded on 1st of May etc...)
* if hours to any number (also hours=24) data will be aggregated over every 24hours,
* even if the date changes (e.g. data from 1st of May from 10pm up 9pm on 2nd of May etc.)
* @param {String} method Specify how to aggregate date. Use: 'mean' = default, 'sum', 'min' or 'max'
* @returns {Array} Aggregated Response
*/
export const aggregateResponse = function(obsArray, hours, method) {
if (!obsArray) return;
if (hours < 0) return;
// check if we have a defined method or the method specified is accepted, rest is handeled in switch/case below
if (method == undefined) method = 'mean';
// convert obsArray to json
let jsonFromArr = [];
for (var i = 0; i < obsArray.length; i++) {
jsonFromArr.push(convertArray2JSON(obsArray[i]));
}
// rename the keys in the jason
jsonFromArr.forEach((obj) => renameKey(obj, "0", "datetime"));
let jsonData = jsonFromArr;
jsonData.forEach((obj) => renameKey(obj, "1", "temperature"));
let newOutput = [];
var aggDates = [];
var aggregatedVals = [];
var vals = []; // store values temporarily to use for processing
if (hours == 0) { // i.e. aggregate over one Date / Day
var currentDate;
var oldDate;
for (var d = 0; d < jsonData.length; d++) {
let tmpDate = new Date(jsonData[d].datetime);
currentDate = tmpDate.getDate(); // gets the day of the month 1...31
if (d === 0) oldDate = currentDate;
if (currentDate == oldDate) {
vals.push(jsonData[d].temperature);
} else {
aggDates.push(new Date(tmpDate - 1));
if (vals.length == 0) {
aggregatedVals.push(-1);
oldDate = currentDate;
continue;
}
switch (method) {
case 'mean':
aggregatedVals.push(vals.reduce(function(a, b) { return a + b / vals.length; }, 0));
break;
case 'sum':
aggregatedVals.push(vals.reduce(function(a, b) { return a + b; }, 0));
break;
case 'min':
aggregatedVals.push(vals.reduce(function(a, b) { return Math.min(a, b); }));
break;
case 'max':
aggregatedVals.push(vals.reduce(function(a, b) { return Math.max(a, b); }));
break;
default:
aggregatedVals.push(vals.reduce(function(a, b) { return a + b / vals.length; }, 0));
}
vals = []; // clear the daily value vector
vals.push(jsonData[d].temperature); // now push first entry of new day into my temp value vector.
}
oldDate = currentDate;
} // end of for loop
// create output to be in the same List format as the original data from obsArray.
for (let i = 0; i < aggregatedVals.length; i++) {
newOutput.push([aggDates[i].toISOString(), aggregatedVals[i]]);
}
} else { // i.e. aggregate over X hours, irrespective of the day.
let cnt = 0;
let cumHours = 0;
for (var d = 0; d < jsonData.length; d++) {
if (cnt < hours) {
vals.push(jsonData[d].temperature);
cnt++;
} else {
cumHours += cnt;
cnt = 0;
aggDates.push(cumHours);
if (vals.length == 0) {
aggregatedVals.push(-1);
continue;
}
switch (method) {
case 'mean':
aggregatedVals.push(vals.reduce(function(a, b) { return a + b / vals.length; }, 0));
break;
case 'sum':
aggregatedVals.push(vals.reduce(function(a, b) { return a + b; }, 0));
break;
case 'min':
aggregatedVals.push(vals.reduce(function(a, b) { return Math.min(a, b); }));
break;
case 'max':
aggregatedVals.push(vals.reduce(function(a, b) { return Math.max(a, b); }));
break;
default:
aggregatedVals.push(vals.reduce(function(a, b) { return a + b / vals.length; }, 0));
}
vals = []; // clear the daily value vector
vals.push(jsonData[d].temperature); // now push first entry of new day into my temp value vector.
cnt++;
}
oldDate = currentDate;
} // end of for loop
// create output to be in the same List format as the original data from obsArray.
for (let i = 0; i < aggregatedVals.length; i++) {
newOutput.push([aggDates[i], aggregatedVals[i]]);
}
} // end else
return newOutput;
}
"use strict";
// Functions
import {
aggregateResponse,
} from "./aggregation.js";
// Functions
import {
getDatastreamIdFromBuildingNumber,
......@@ -10,7 +16,6 @@ import {
formatSTAResponseForLineChart,
drawLineChartHC,
followNextLink,
aggregateResponse,
} from "./appChart.js";
// Constants
......@@ -338,10 +343,10 @@ const activate3DTileFeaturePicking = function() {
console.log(err);
})
.then((observationArr) => {
var agg = aggregateResponse(observationArr, 0, 'mean');
var agg = aggregateResponse(observationArr, 0, 'sum');
console.log(agg);
drawHeatMapHC(formatSTAResponseForHeatMap(observationArr));
drawLineChartHC(formatSTAResponseForLineChart(observationArr));
drawHeatMapHC(formatSTAResponseForHeatMap(agg));
drawLineChartHC(formatSTAResponseForLineChart(agg));
});
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
......
......@@ -120,191 +120,6 @@ export const PARAM_SELECT = "result,phenomenonTime";
// });
/**
*
* @param {JSON} obj JSON object on which to replace a specific key.
* @param {String} oldKey is the old key in the JSON to be renamed to newKey
* @param {String} newKey is the key that should replace the oldKey
* usage: myjson.forEach((obj) => renameKey(obj, "oldkey", "newkey"));
*/
function renameKey(obj, oldKey, newKey) {
obj[newKey] = obj[oldKey];
delete obj[oldKey];
}
/**
*
* @param {Array} arr is the Array to be converted into a JSON
* @returns {JSON} stringToJsonObject
*/
function convertArray2JSON(arr) {
var arrayToString = JSON.stringify(Object.assign({}, arr)); // convert array to string
var stringToJsonObject = JSON.parse(arrayToString); // convert string to json object
return stringToJsonObject;
}
function createDateFromDateTimeString(jsonData) {
let datx = [];
let daty = [];
const MONTH = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
for (var u = 0; u < jsonData.length; u++) {
daty.push(jsonData[u].temperature);
let date = new Date(jsonData[u].datetime);
let datum = date.getDate();
let month = MONTH[date.getMonth()];
let hour = date.getHours() + ":00";
let newDateStr = datum + "/" + month + "-" + hour;
datx.push(newDateStr);
}
return [datx, daty];
}
/**
* Format the response from SensorThings API to make it suitable for heatmap
* @param {Array} obsArray Response from SensorThings API as array
* @param {Int8} hours Number of hours to aggregate over. If hours=0,
* it will be aggregated by date (e.g. all values recorded on 1st of May etc...)
* if hours to any number (also hours=24) data will be aggregated over every 24hours,
* even if the date changes (e.g. data from 1st of May from 10pm up 9pm on 2nd of May etc.)
* @param {String} method Specify how to aggregate date. Use: 'mean' = default, 'sum', 'min' or 'max'
* @returns {Array} Aggregated Response
*/
export const aggregateResponse = function(obsArray, hours, method) {
if (!obsArray) return;
if (hours < 0) return;
// check if we have a defined method or the method specified is accepted, rest is handeled in switch/case below
if (method == undefined) method = 'mean';
// convert obsArray to json
let jsonFromArr = [];
for (var i = 0; i < obsArray.length; i++) {
jsonFromArr.push(convertArray2JSON(obsArray[i]));
}
// rename the keys in the jason
jsonFromArr.forEach((obj) => renameKey(obj, "0", "datetime"));
let jsonData = jsonFromArr;
jsonData.forEach((obj) => renameKey(obj, "1", "temperature"));
let newOutput = [];
var aggDates = [];
var aggregatedVals = [];
var vals = []; // store values temporarily to use for processing
if (hours == 0) { // i.e. aggregate over one Date / Day
var currentDate;
var oldDate;
for (var d = 0; d < jsonData.length; d++) {
let tmpDate = new Date(jsonData[d].datetime);
currentDate = tmpDate.getDate(); // gets the day of the month 1...31
if (d === 0) oldDate = currentDate;
if (currentDate == oldDate) {
vals.push(jsonData[d].temperature);
} else {
aggDates.push(new Date(tmpDate - 1));
if (vals.length == 0) {
aggregatedVals.push(-1);
oldDate = currentDate;
continue;
}
switch (method) {
case 'mean':
aggregatedVals.push(vals.reduce(function(a, b) { return a + b / vals.length; }, 0));
break;
case 'sum':
aggregatedVals.push(vals.reduce(function(a, b) { return a + b; }, 0));
break;
case 'min':
aggregatedVals.push(vals.reduce(function(a, b) { return Math.min(a, b); }));
break;
case 'max':
aggregatedVals.push(vals.reduce(function(a, b) { return Math.max(a, b); }));
break;
default:
aggregatedVals.push(vals.reduce(function(a, b) { return a + b / vals.length; }, 0));
}
vals = []; // clear the daily value vector
vals.push(jsonData[d].temperature); // now push first entry of new day into my temp value vector.
}
oldDate = currentDate;
} // end of for loop
// create output to be in the same List format as the original data from obsArray.
for (let i = 0; i < aggregatedVals.length; i++) {
newOutput.push([aggDates[i].toISOString(), aggregatedVals[i]]);
}
} else { // i.e. aggregate over X hours, irrespective of the day.
let cnt = 0;
let cumHours = 0;
for (var d = 0; d < jsonData.length; d++) {
if (cnt < hours) {
vals.push(jsonData[d].temperature);
cnt++;
} else {
cumHours += cnt;
cnt = 0;
aggDates.push(cumHours);
if (vals.length == 0) {
aggregatedVals.push(-1);
continue;
}
switch (method) {
case 'mean':
aggregatedVals.push(vals.reduce(function(a, b) { return a + b / vals.length; }, 0));
break;
case 'sum':
aggregatedVals.push(vals.reduce(function(a, b) { return a + b; }, 0));
break;
case 'min':
aggregatedVals.push(vals.reduce(function(a, b) { return Math.min(a, b); }));
break;
case 'max':
aggregatedVals.push(vals.reduce(function(a, b) { return Math.max(a, b); }));
break;
default:
aggregatedVals.push(vals.reduce(function(a, b) { return a + b / vals.length; }, 0));
}
vals = []; // clear the daily value vector
vals.push(jsonData[d].temperature); // now push first entry of new day into my temp value vector.
cnt++;
}
oldDate = currentDate;
} // end of for loop
// create output to be in the same List format as the original data from obsArray.
for (let i = 0; i < aggregatedVals.length; i++) {
newOutput.push([aggDates[i], aggregatedVals[i]]);
}
} // end else
return newOutput;
}
/**
* Format the response from SensorThings API to make it suitable for heatmap
......
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