diff --git a/index.html b/index.html
index c90ef6807d1c3f48a6acad9b4f327bf55df86278..caf70127f79b058c7bb59f149ba8dddf3b297b5d 100644
--- a/index.html
+++ b/index.html
@@ -28,12 +28,11 @@
>
-
-
-
+
+
+
@@ -44,11 +43,7 @@
-
-
-
-
-
+
diff --git a/package-lock.json b/package-lock.json
index 78f7a1eb5834ebc6bc376e41483b8b33388f62f5..1602dd41137606aa799aaf5b7cb791a21a5af877 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -18,14 +18,6 @@
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
"integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
},
- "axios": {
- "version": "0.21.1",
- "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
- "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
- "requires": {
- "follow-redirects": "^1.10.0"
- }
- },
"body-parser": {
"version": "1.19.0",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
@@ -160,11 +152,6 @@
"unpipe": "~1.0.0"
}
},
- "follow-redirects": {
- "version": "1.13.2",
- "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.2.tgz",
- "integrity": "sha512-6mPTgLxYm3r6Bkkg0vNM0HTjfGrOEtsfbhagQvbxDEsEkpNhw582upBaoRZylzen6krEmxXJgt9Ju6HiI4O7BA=="
- },
"forwarded": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
diff --git a/package.json b/package.json
index a8ba0bd4cc36be9770e25a3ef00ada2aea1d0099..d724ae7e1d7d9bfa13623f3b1c200ee6e7f9dba7 100644
--- a/package.json
+++ b/package.json
@@ -9,7 +9,6 @@
"author": "",
"license": "ISC",
"dependencies": {
- "axios": "^0.21.1",
"express": "^4.17.1"
}
}
diff --git a/public/js/appChart.js b/public/js/appChart.js
index 5c233ef06232be5b26b237c7a514d233d012d3cf..85c3007991fa5037d51ea0471bf02804e49d3f77 100644
--- a/public/js/appChart.js
+++ b/public/js/appChart.js
@@ -17,8 +17,14 @@ import {
drawScatterPlotHighcharts,
} from "./src_modules/chartScatterPlot.js";
+import {
+ formatAggregationResultForColumnChart,
+ drawColumnChartHighcharts,
+} from "./src_modules/chartColumn.js";
+
import {
formatDatastreamMetadataForChart,
+ extractPropertiesFromFormattedDatastreamMetadata,
getMetadataPlusObservationsFromSingleOrMultipleDatastreams,
calculateVorlaufMinusRuecklaufTemperature,
} from "./src_modules/fetchData.js";
@@ -34,7 +40,7 @@ import {
* Test plotting of temp difference (dT) using heatmap
*/
const drawHeatmapHCUsingTempDifference = async function () {
- const [tempDifferenceObsArrBau225, tempDifferenceMetadataBau225] =
+ const [observationsTemperatureDiff225Arr, metadataTemperatureDiff225Arr] =
await calculateVorlaufMinusRuecklaufTemperature(
BASE_URL,
QUERY_PARAMS_COMBINED,
@@ -42,9 +48,36 @@ const drawHeatmapHCUsingTempDifference = async function () {
"60min"
);
+ // We want to have nested arrays, so as to mimick the nested responses we get from fetching observations + metadata
+ const observationsTemperatureDiff225NestedArr = [
+ observationsTemperatureDiff225Arr,
+ ];
+
+ const metadataTemperatureDiff225NestedArr = [metadataTemperatureDiff225Arr];
+
+ // Format the observations
+ const formattedTempDiff225NestedArr =
+ observationsTemperatureDiff225NestedArr.map((obsArr) =>
+ formatSensorThingsApiResponseForHeatMap(obsArr)
+ );
+
+ // Format the metadata
+ const formattedTempDiff225MetadataNestedArr =
+ metadataTemperatureDiff225NestedArr.map((metadataObj) =>
+ formatDatastreamMetadataForChart(metadataObj)
+ );
+
+ // Extract the formatted metadata properties
+ const extractedFormattedTempDiff225Properties =
+ extractPropertiesFromFormattedDatastreamMetadata(
+ formattedTempDiff225MetadataNestedArr
+ );
+
+ // First need to extract the formatted observations from the nested array
+ // Heatmap only needs one set of formatted observation values
drawHeatMapHighcharts(
- formatSensorThingsApiResponseForHeatMap(tempDifferenceObsArrBau225),
- formatDatastreamMetadataForChart(tempDifferenceMetadataBau225)
+ ...formattedTempDiff225NestedArr,
+ extractedFormattedTempDiff225Properties
);
};
@@ -52,7 +85,7 @@ const drawHeatmapHCUsingTempDifference = async function () {
* Test drawing of scatter plot chart
*/
const drawScatterPlotHCTest2 = async function () {
- const sensorsOfInterestArr = [
+ const sensorsOfInterestNestedArr = [
["225", "vl", "60min"],
// ["125", "rl", "60min"],
["weather_station_521", "outside_temp", "60min"],
@@ -62,26 +95,32 @@ const drawScatterPlotHCTest2 = async function () {
await getMetadataPlusObservationsFromSingleOrMultipleDatastreams(
BASE_URL,
QUERY_PARAMS_COMBINED,
- sensorsOfInterestArr
+ sensorsOfInterestNestedArr
);
// Extract the combined arrays for observations and metadata
- const [observationsArr, metadataArr] = observationsPlusMetadata;
+ const [observationsNestedArr, metadataNestedArr] = observationsPlusMetadata;
// Create formatted array(s) for observations
// This function expects two arguments, these are unpacked using the spread operator
- const formattedObsScatterPlotArr =
- formatSensorThingsApiResponseForScatterPlot(...observationsArr);
+ const formattedObservationsArr = formatSensorThingsApiResponseForScatterPlot(
+ ...observationsNestedArr
+ );
// Create formatted array(s) for metadata
- const formattedMetadataArr = metadataArr.map((metadata) =>
- formatDatastreamMetadataForChart(metadata)
+ const formattedMetadataNestedArr = metadataNestedArr.map((metadataObj) =>
+ formatDatastreamMetadataForChart(metadataObj)
);
- // This function expects three arguments, the second and third are unpacked using the spread operator
+ // Extract the formatted metadata properties
+ const extractedFormattedDatastreamProperties =
+ extractPropertiesFromFormattedDatastreamMetadata(
+ formattedMetadataNestedArr
+ );
+
drawScatterPlotHighcharts(
- formattedObsScatterPlotArr,
- ...formattedMetadataArr
+ formattedObservationsArr,
+ extractedFormattedDatastreamProperties
);
};
@@ -89,84 +128,132 @@ const drawScatterPlotHCTest2 = async function () {
* Test drawing of line chart with multiple series
*/
const testLineChartMultipleSeries = async function () {
- const sensorsOfInterestArr = [
+ const sensorsOfInterestNestedArr = [
["225", "vl", "60min"],
["125", "rl", "60min"],
["weather_station_521", "outside_temp", "60min"],
];
- const observationsPlusMetadata =
+ const observationsPlusMetadataArr =
await getMetadataPlusObservationsFromSingleOrMultipleDatastreams(
BASE_URL,
QUERY_PARAMS_COMBINED,
- sensorsOfInterestArr
+ sensorsOfInterestNestedArr
);
- // Extract the observations and metadata arrays
- const [observationsArr, metadataArr] = observationsPlusMetadata;
+ // Extract the observations and metadata arrays of arrays
+ const [observationsNestedArr, metadataNestedArr] =
+ observationsPlusMetadataArr;
- // Format the observations and metadata
- const formattedObservationsArr = observationsArr.map((observations) =>
- formatSensorThingsApiResponseForLineChart(observations)
+ // Format the observations
+ const formattedObservationsNestedArr = observationsNestedArr.map(
+ (observationsArr) =>
+ formatSensorThingsApiResponseForLineChart(observationsArr)
);
- const formattedMetadataArr = metadataArr.map((metadata) =>
- formatDatastreamMetadataForChart(metadata)
+ // Format the metadata
+ const formattedMetadataNestedArr = metadataNestedArr.map((metadataArr) =>
+ formatDatastreamMetadataForChart(metadataArr)
);
- drawLineChartHighcharts(formattedObservationsArr, formattedMetadataArr);
+ // Extract the formatted metadata properties
+ const extractedFormattedDatastreamProperties =
+ extractPropertiesFromFormattedDatastreamMetadata(
+ formattedMetadataNestedArr
+ );
+
+ drawLineChartHighcharts(
+ formattedObservationsNestedArr,
+ extractedFormattedDatastreamProperties
+ );
};
/**
- * Test aggregation of observations from a single datastream
+ * Test drawing of column chart using aggregation result
*/
-const testAggregationSum = async function () {
- const sensorOfInterestNestedArr = [["225", "vl", "60min"]];
+const drawColumnChartMonthlySumTest = async function () {
+ const sensorsOfInterestNestedArr = [
+ ["125", "vl", "60min"],
+ ["225", "vl", "60min"],
+ ];
const observationsPlusMetadata =
await getMetadataPlusObservationsFromSingleOrMultipleDatastreams(
BASE_URL,
QUERY_PARAMS_COMBINED,
- sensorOfInterestNestedArr
+ sensorsOfInterestNestedArr
);
// Extract the observations and metadata for each sensor
// Array elements in same order as input array
- const [[obsSensorOneArr], [metadataSensorOne]] = observationsPlusMetadata;
+ const [observationsNestedArr, metadataNestedArr] = observationsPlusMetadata;
// Unique calendar dates
- const uniqueCalendarDates =
- extractUniqueCalendarDatesFromTimestamp(obsSensorOneArr);
+ const uniqueCalendarDatesNestedArr = observationsNestedArr.map(
+ (observationsArr) =>
+ extractUniqueCalendarDatesFromTimestamp(observationsArr)
+ );
// Unique calendar months
- const uniqueCalendarMonths =
- extractUniqueCalendarMonthsFromCalendarDates(uniqueCalendarDates);
+ const uniqueCalendarMonthsNestedArr = uniqueCalendarDatesNestedArr.map(
+ (uniqueCalendarDatesArr) =>
+ extractUniqueCalendarMonthsFromCalendarDates(uniqueCalendarDatesArr)
+ );
// Calculate sum of values of observations - daily
- const observationsBau225VLSumDaily = uniqueCalendarDates.map((calendarDate) =>
- calculateSumOfObservationValuesWithinDatesInterval(
- obsSensorOneArr,
- "60 min",
- calendarDate,
- calendarDate
- )
+ // Note the two nested `map` methods
+ const observationsSumDailyNestedArr = uniqueCalendarDatesNestedArr.map(
+ (uniqueCalendarDatesArr, i) =>
+ uniqueCalendarDatesArr.map((uniqueCalendarDate) =>
+ calculateSumOfObservationValuesWithinDatesInterval(
+ observationsNestedArr[i],
+ "60 min",
+ uniqueCalendarDate,
+ uniqueCalendarDate
+ )
+ )
);
// Calculate sum of values of observations - monthly
- const observationsBau225VLSumMonthly = uniqueCalendarMonths.map(
- (calendarMonth) =>
- calculateSumOfObservationValuesWithinMonthInterval(
- obsSensorOneArr,
- "60 min",
- calendarMonth
+ // Note the two nested `map` methods
+ const observationsSumMonthlyNestedArr = uniqueCalendarMonthsNestedArr.map(
+ (uniqueCalendarMonthsArr, i) =>
+ uniqueCalendarMonthsArr.map((uniqueCalendarMonth) =>
+ calculateSumOfObservationValuesWithinMonthInterval(
+ observationsNestedArr[i],
+ "60 min",
+ uniqueCalendarMonth
+ )
)
);
- console.log(observationsBau225VLSumDaily);
- console.log(observationsBau225VLSumMonthly);
+ // Format the observations
+ const formattedObservationsNestedArr = observationsSumMonthlyNestedArr.map(
+ (obsSumMonthlyArr, i) =>
+ formatAggregationResultForColumnChart(
+ uniqueCalendarMonthsNestedArr[i],
+ obsSumMonthlyArr
+ )
+ );
+
+ // Format the metadata
+ const formattedMetadataNestedArr = metadataNestedArr.map((metadataObj) =>
+ formatDatastreamMetadataForChart(metadataObj)
+ );
+
+ // Extract the formatted metadata properties
+ const extractedFormattedDatastreamProperties =
+ extractPropertiesFromFormattedDatastreamMetadata(
+ formattedMetadataNestedArr
+ );
+
+ drawColumnChartHighcharts(
+ formattedObservationsNestedArr,
+ extractedFormattedDatastreamProperties
+ );
};
// drawScatterPlotHCTest2();
// drawHeatmapHCUsingTempDifference();
-// testLineChartMultipleSeries()
-// testAggregationSum();
+// testLineChartMultipleSeries();
+// drawColumnChartMonthlySumTest();
diff --git a/public/js/dropDownList.js b/public/js/dropDownList.js
index 2addbdedc479e248f396cae29220d1498a74e7bf..9bda35e9b3684d4faf9fe30b57a50a2d459636f3 100644
--- a/public/js/dropDownList.js
+++ b/public/js/dropDownList.js
@@ -4,6 +4,7 @@ import { BASE_URL, QUERY_PARAMS_COMBINED } from "./src_modules/createUrl.js";
import {
formatDatastreamMetadataForChart,
+ extractPropertiesFromFormattedDatastreamMetadata,
getMetadataPlusObservationsFromSingleOrMultipleDatastreams,
} from "./src_modules/fetchData.js";
@@ -272,28 +273,41 @@ const selectChartTypeFromDropDown = async function () {
);
// Extract the combined arrays for observations and metadata
- const [observationsArr, metadataArr] = observationsPlusMetadata;
+ const [observationsNestedArr, metadataNestedArr] = observationsPlusMetadata;
// Create formatted array(s) for observations - line chart
- const formattedObsLineChartArr = observationsArr.map((observations) =>
- formatSensorThingsApiResponseForLineChart(observations)
+ const formattedObsLineChartArr = observationsNestedArr.map(
+ (observationsArr) =>
+ formatSensorThingsApiResponseForLineChart(observationsArr)
);
// Create formatted array(s) for observations - heatmap
- const formattedObsHeatMapArr = observationsArr.map((observations) =>
- formatSensorThingsApiResponseForHeatMap(observations)
+ const formattedObsHeatMapArr = observationsNestedArr.map(
+ (observationsArr) =>
+ formatSensorThingsApiResponseForHeatMap(observationsArr)
);
// Create formatted array(s) for metadata - same for both chart types
- const formattedMetadataArr = metadataArr.map((metadata) =>
- formatDatastreamMetadataForChart(metadata)
+ const formattedMetadataArr = metadataNestedArr.map((metadataObj) =>
+ formatDatastreamMetadataForChart(metadataObj)
);
+ // Extract the formatted metadata properties
+ const extractedFormattedDatastreamProperties =
+ extractPropertiesFromFormattedDatastreamMetadata(formattedMetadataArr);
+
if (selectedChartType === "Line") {
- drawLineChartHighcharts(formattedObsLineChartArr, formattedMetadataArr);
+ drawLineChartHighcharts(
+ formattedObsLineChartArr,
+ extractedFormattedDatastreamProperties
+ );
} else if (selectedChartType === "Heatmap") {
- // First need to extract the nested arrays for the formatted observations and metadata
- drawHeatMapHighcharts(...formattedObsHeatMapArr, ...formattedMetadataArr);
+ // First need to extract the formatted observations from the nested array
+ // Heatmap only needs one set of formatted observation values
+ drawHeatMapHighcharts(
+ ...formattedObsHeatMapArr,
+ extractedFormattedDatastreamProperties
+ );
}
} catch (err) {
console.error(err);
diff --git a/public/js/src_modules/chartColumn.js b/public/js/src_modules/chartColumn.js
new file mode 100644
index 0000000000000000000000000000000000000000..51f322424902803cbfbf8ad2bf3dd66d427e3bb2
--- /dev/null
+++ b/public/js/src_modules/chartColumn.js
@@ -0,0 +1,130 @@
+/**
+ * Format a computed aggregation result to make it suitable for a column chart
+ * @param {Array} calendarDatesMonthsStrArr An array of unique calendar dates strings (in "YYYY-MM-DD" fromat) or unique calendar months strings (in "YYYY-MM" format)
+ * @param {Array} aggregatedValuesArr An array of aggregated values
+ * @returns {Array} An array of formatted aggregation values suitable for use in a column chart
+ */
+const formatAggregationResultForColumnChart = function (
+ calendarDatesMonthsStrArr,
+ aggregatedValuesArr
+) {
+ if (!calendarDatesMonthsStrArr || !aggregatedValuesArr) return;
+
+ // Create an array of Unix timestamp strings
+ const timestampsArr = calendarDatesMonthsStrArr.map((calendarStr) =>
+ new Date(calendarStr).getTime()
+ );
+
+ // Combine timestamp and value pairs
+ // The timestamps array and values array have same lengths, use one for looping
+ return timestampsArr.map((timestamp, i) => [
+ timestamp,
+ aggregatedValuesArr[i],
+ ]);
+};
+
+/**
+ * Creates an options object for each series drawn in a column chart
+ * @param {Array} formattedAggregatedResultForColumnChart An array of formatted aggregated result array(s) from one or more datastreams
+ * @param {Array} phenomenonNamesArr An array of phenomenon name(s)
+ * @param {Array} phenomenonSymbolsArr An array of phenomenon symbol(s)
+ * @returns {Array} An array made up of series options object(s)
+ */
+const createSeriesOptionsForColumnChart = function (
+ formattedAggregatedResultForColumnChart,
+ phenomenonNamesArr,
+ phenomenonSymbolsArr
+) {
+ // Create an array of seriesOptions objects
+ // Assumes that the observation array of arrays, phenomenon names array and phenomenon symbols array are of equal length
+ // Use one of the arrays for looping
+ return formattedAggregatedResultForColumnChart.map(
+ (formattedAggResArray, i) => {
+ return {
+ name: `${phenomenonNamesArr[i]} (${phenomenonSymbolsArr[i]})`,
+ data: formattedAggResArray,
+ turboThreshold: Number.MAX_VALUE, // #3404, remove after 4.0.5 release
+ };
+ }
+ );
+};
+
+/**
+ * Draw a column chart using Highcharts library
+ * @param {Array} formattedAggResultArraysForColumnChart An array made up of formatted aggregated result array(s) suitable for use in a column chart
+ * @param {Object} extractedFormattedDatastreamProperties An object that contains arrays of formatted Datastream properties
+ * @returns {undefined}
+ */
+const drawColumnChartHighcharts = function (
+ formattedAggResultArraysForColumnChart,
+ extractedFormattedDatastreamProperties
+) {
+ // Arrays of datastream properties
+ const {
+ datastreamNamesArr,
+ phenomenonNamesArr,
+ unitOfMeasurementSymbolsArr,
+ } = extractedFormattedDatastreamProperties;
+
+ const seriesOptionsArr = createSeriesOptionsForColumnChart(
+ formattedAggResultArraysForColumnChart,
+ phenomenonNamesArr,
+ unitOfMeasurementSymbolsArr
+ );
+
+ Highcharts.chart("chart-column", {
+ chart: {
+ type: "column",
+ zoomType: "x",
+ },
+
+ title: {
+ text: "Monthly Average Rainfall",
+ },
+
+ subtitle: {
+ text: "Source: WorldClimate.com",
+ },
+
+ xAxis: {
+ type: "datetime",
+ crosshair: true,
+ },
+
+ yAxis: {
+ min: 0,
+ title: {
+ text: "Rainfall (mm)",
+ },
+ },
+
+ tooltip: {
+ headerFormat: `
+ {point.key}
+
+ `,
+ pointFormat: `
+
+ {series.name}: |
+ {point.y:.1f} mm |
+
+ `,
+ footerFormat: `
+
+ `,
+ shared: true,
+ useHTML: true,
+ },
+
+ plotOptions: {
+ column: {
+ pointPadding: 0.2,
+ borderWidth: 0,
+ },
+ },
+
+ series: seriesOptionsArr,
+ });
+};
+
+export { formatAggregationResultForColumnChart, drawColumnChartHighcharts };
diff --git a/public/js/src_modules/chartHeatmap.js b/public/js/src_modules/chartHeatmap.js
index c1891121641946180a72179421c28541118c657f..5d15d4f6a7e7a0c85ca9d32dd109cd1b8b7b8b04 100644
--- a/public/js/src_modules/chartHeatmap.js
+++ b/public/js/src_modules/chartHeatmap.js
@@ -8,7 +8,7 @@
const formatSensorThingsApiResponseForHeatMap = function (obsArray) {
if (!obsArray) return;
- const dataSTAFormatted = obsArray.map((obs) => {
+ return obsArray.map((obs) => {
// Get the date/time string; first element in input array; remove trailing "Z"
const obsDateTimeInput = obs[0].slice(0, -1);
// Get the "date" part of an observation
@@ -24,8 +24,6 @@ const formatSensorThingsApiResponseForHeatMap = function (obsArray) {
const value = obs[1];
return [timestamp, hourOfDay, value];
});
-
- return dataSTAFormatted;
};
/**
@@ -53,19 +51,25 @@ const calculateMinMaxValuesForHeatmapColorAxis = function (
/**
* Draw a heatmap using Highcharts library
* @param {Array} formattedObsArrayForHeatmap Response from SensorThings API formatted for use in a heatmap
- * @param {Object} formattedDatastreamMetadata Object containing Datastream metadata
+ * @param {Object} extractedFormattedDatastreamProperties An object that contains arrays of formatted Datastream properties
* @returns {undefined} undefined
*/
const drawHeatMapHighcharts = function (
formattedObsArrayForHeatmap,
- formattedDatastreamMetadata
+ extractedFormattedDatastreamProperties
) {
+ // Arrays of datastream properties
const {
- datastreamDescription: DATASTREAM_DESCRIPTION,
- datastreamName: DATASTREAM_NAME,
- phenomenonName: PHENOMENON_NAME,
- unitOfMeasurementSymbol: PHENOMENON_SYMBOL,
- } = formattedDatastreamMetadata;
+ datastreamDescriptionsArr,
+ datastreamNamesArr,
+ phenomenonNamesArr,
+ unitOfMeasurementSymbolsArr,
+ } = extractedFormattedDatastreamProperties;
+
+ const [DATASTREAM_DESCRIPTION] = datastreamDescriptionsArr;
+ const [DATASTREAM_NAME] = datastreamNamesArr;
+ const [PHENOMENON_NAME] = phenomenonNamesArr;
+ const [PHENOMENON_SYMBOL] = unitOfMeasurementSymbolsArr;
const {
minObsValue: MINIMUM_VALUE_COLOR_AXIS,
diff --git a/public/js/src_modules/chartLine.js b/public/js/src_modules/chartLine.js
index 8a3d3ba93358c227818f1119173c6ddb1b12c59b..8c8e5bfc0e80d5217ffc56870fc1b4e71517316e 100644
--- a/public/js/src_modules/chartLine.js
+++ b/public/js/src_modules/chartLine.js
@@ -8,46 +8,11 @@
const formatSensorThingsApiResponseForLineChart = function (obsArray) {
if (!obsArray) return;
- const dataSTAFormatted = obsArray.map((result) => {
+ return obsArray.map((result) => {
const timestampObs = new Date(result[0].slice(0, -1)).getTime(); // slice() removes trailing "Z" character in timestamp
const valueObs = result[1];
return [timestampObs, valueObs];
});
-
- return dataSTAFormatted;
-};
-
-/**
- * Extract the properties that make up the formatted datastream metadata object(s)
- * @param {Array} formattedDatastreamsMetadataArr An array of formatted metadata object(s) from one or more datastreams
- * @returns {Object} An object that contains array(s) of formatted datastream metadata properties
- */
-const extractPropertiesFromDatastreamMetadata = function (
- formattedDatastreamsMetadataArr
-) {
- // Create arrays from the properties of the formatted datastream metadata
- const datastreamDescriptionsArr = formattedDatastreamsMetadataArr.map(
- (datastreamMetadata) => datastreamMetadata.datastreamDescription
- );
-
- const datastreamNamesArr = formattedDatastreamsMetadataArr.map(
- (datastreamMetadata) => datastreamMetadata.datastreamName
- );
-
- const phenomenonNamesArr = formattedDatastreamsMetadataArr.map(
- (datastreamMetadata) => datastreamMetadata.phenomenonName
- );
-
- const unitOfMeasurementSymbolsArr = formattedDatastreamsMetadataArr.map(
- (datastreamMetadata) => datastreamMetadata.unitOfMeasurementSymbol
- );
-
- return {
- datastreamDescriptionsArr,
- datastreamNamesArr,
- phenomenonNamesArr,
- unitOfMeasurementSymbolsArr,
- };
};
/**
@@ -104,19 +69,19 @@ const createSeriesOptionsForLineChart = function (
/**
* Draw a line chart using Highcharts library
* @param {Array} formattedObsArraysForLineChart An array made up of formatted observation array(s) suitable for use in a line chart
- * @param {Object} formattedDatastreamMetadataArr An array made up of object(s) containing Datastream metadata
+ * @param {Object} extractedFormattedDatastreamPropertiesArr An object that contains arrays of formatted Datastream properties
* @returns {undefined} undefined
*/
const drawLineChartHighcharts = function (
formattedObsArraysForLineChart,
- formattedDatastreamMetadataArr
+ extractedFormattedDatastreamProperties
) {
// Arrays of datastream properties
const {
datastreamNamesArr,
phenomenonNamesArr,
unitOfMeasurementSymbolsArr,
- } = extractPropertiesFromDatastreamMetadata(formattedDatastreamMetadataArr);
+ } = extractedFormattedDatastreamProperties;
// Create the array of series options object(s)
const seriesOptionsArr = createSeriesOptionsForLineChart(
diff --git a/public/js/src_modules/chartScatterPlot.js b/public/js/src_modules/chartScatterPlot.js
index 00874c9caddbb20db087344e61a3cbe4659e29f1..eb88b9488b31c6d81924cb5e2eb08e734a3cb59a 100644
--- a/public/js/src_modules/chartScatterPlot.js
+++ b/public/js/src_modules/chartScatterPlot.js
@@ -183,11 +183,7 @@ const createCombinedObservationValues = function (obsArrayOne, obsArrayTwo) {
const obsValuesTwo = obsArrayTwo.map((result) => result[1]);
// Since the arrays are of equal length, we need only use one of the arrays for looping
- const obsValuesOnePlusTwo = obsValuesOne.map((obsValOne, i) => {
- return [obsValOne, obsValuesTwo[i]];
- });
-
- return obsValuesOnePlusTwo;
+ return obsValuesOne.map((obsValOne, i) => [obsValOne, obsValuesTwo[i]]);
};
/**
@@ -218,28 +214,29 @@ const formatSensorThingsApiResponseForScatterPlot = function (
/**
* Draw a scatter plot using Highcharts library
* @param {Array} formattedObsArrayForSeriesOnePlusSeriesTwo Response from SensorThings API formatted for use in a scatter plot
- * @param {Object} formattedDatastreamMetadataSeriesOne Object containing Datastream metadata for the first chart series
- * @param {Object} formattedDatastreamMetadataSeriesTwo Object containing Datastream metadata for the second chart series
+ * @param {Object} extractedFormattedDatastreamProperties An object that contains arrays of formatted Datastream properties
* @returns {undefined}
*/
const drawScatterPlotHighcharts = function (
formattedObsArrayForSeriesOnePlusSeriesTwo,
- formattedDatastreamMetadataSeriesOne,
- formattedDatastreamMetadataSeriesTwo
+ extractedFormattedDatastreamProperties
) {
+ // Arrays of datastream properties
const {
- datastreamDescription: DATASTREAM_DESCRIPTION_SERIES_1,
- datastreamName: DATASTREAM_NAME_SERIES_1,
- phenomenonName: PHENOMENON_NAME_SERIES_1,
- unitOfMeasurementSymbol: PHENOMENON_SYMBOL_SERIES_1,
- } = formattedDatastreamMetadataSeriesOne;
-
- const {
- datastreamDescription: DATASTREAM_DESCRIPTION_SERIES_2,
- datastreamName: DATASTREAM_NAME_SERIES_2,
- phenomenonName: PHENOMENON_NAME_SERIES_2,
- unitOfMeasurementSymbol: PHENOMENON_SYMBOL_SERIES_2,
- } = formattedDatastreamMetadataSeriesTwo;
+ datastreamDescriptionsArr,
+ datastreamNamesArr,
+ phenomenonNamesArr,
+ unitOfMeasurementSymbolsArr,
+ } = extractedFormattedDatastreamProperties;
+
+ const [DATASTREAM_DESCRIPTION_SERIES_1, DATASTREAM_DESCRIPTION_SERIES_2] =
+ datastreamDescriptionsArr;
+ const [DATASTREAM_NAME_SERIES_1, DATASTREAM_NAME_SERIES_2] =
+ datastreamNamesArr;
+ const [PHENOMENON_NAME_SERIES_1, PHENOMENON_NAME_SERIES_2] =
+ phenomenonNamesArr;
+ const [PHENOMENON_SYMBOL_SERIES_1, PHENOMENON_SYMBOL_SERIES_2] =
+ unitOfMeasurementSymbolsArr;
// Order of axes
// Y-Axis -- Series 2
diff --git a/public/js/src_modules/fetchData.js b/public/js/src_modules/fetchData.js
index 5fedf89d90ca5c4b5d026c7ed6e6dd181306f69d..64ba329a1e43a7fb60b4099eeb315705f13287ca 100644
--- a/public/js/src_modules/fetchData.js
+++ b/public/js/src_modules/fetchData.js
@@ -233,6 +233,39 @@ const formatDatastreamMetadataForChart = function (datastreamMetadata) {
};
};
+/**
+ * Extract the properties that make up the formatted datastream metadata object(s)
+ * @param {Array} formattedDatastreamsMetadataArr An array of formatted metadata object(s) from one or more datastreams
+ * @returns {Object} An object that contains array(s) of formatted datastream metadata properties
+ */
+const extractPropertiesFromFormattedDatastreamMetadata = function (
+ formattedDatastreamsMetadataArr
+) {
+ // Create arrays from the properties of the formatted datastream metadata
+ const datastreamDescriptionsArr = formattedDatastreamsMetadataArr.map(
+ (datastreamMetadata) => datastreamMetadata.datastreamDescription
+ );
+
+ const datastreamNamesArr = formattedDatastreamsMetadataArr.map(
+ (datastreamMetadata) => datastreamMetadata.datastreamName
+ );
+
+ const phenomenonNamesArr = formattedDatastreamsMetadataArr.map(
+ (datastreamMetadata) => datastreamMetadata.phenomenonName
+ );
+
+ const unitOfMeasurementSymbolsArr = formattedDatastreamsMetadataArr.map(
+ (datastreamMetadata) => datastreamMetadata.unitOfMeasurementSymbol
+ );
+
+ return {
+ datastreamDescriptionsArr,
+ datastreamNamesArr,
+ phenomenonNamesArr,
+ unitOfMeasurementSymbolsArr,
+ };
+};
+
/**
* Traverses all the pages that make up the response from a SensorThingsAPI instance. The link to the next page, if present, is denoted by the presence of a "@iot.nextLink" property in the response object. This function concatenates all the values so that the complete results are returned in one array.
* @async
@@ -332,18 +365,18 @@ const getObservationsFromMultipleDatastreams = async function (
* Retrieve the metadata from a single Datastream or multiple Datastreams and the Observations corresponding to the Datastream(s)
* @param {String} baseUrl Base URL of the STA server
* @param {Object} urlParamObj The URL parameters to be sent together with the GET request
- * @param {Array} bldgSensorSamplingRateArr A N*1 array (where N >= 1) containing a nested array of buildings, sensors & sampling rates as strings, i.e. [["101", "rl", "15min"]] or [["101", "rl", "15min"], ["102", "vl", "60min"]] or [["101", "rl", "15min"], ["102", "vl", "60min"], ["225", "vl", "60min"]], etc
+ * @param {Array} bldgSensorSamplingRateNestedArr A N*1 array (where N >= 1) containing a nested array of buildings, sensors & sampling rates as strings, i.e. [["101", "rl", "15min"]] or [["101", "rl", "15min"], ["102", "vl", "60min"]] or [["101", "rl", "15min"], ["102", "vl", "60min"], ["225", "vl", "60min"]], etc
* @returns {Promise} A promise that contains a 1*2 array (the first element is an array that contans N Observations arrays; and the second element is an array of N Datastream metadata objects) when fulfilled
*/
const getMetadataPlusObservationsFromSingleOrMultipleDatastreams =
- async function (baseUrl, urlParamObj, bldgSensorSamplingRateArr) {
+ async function (baseUrl, urlParamObj, bldgSensorSamplingRateNestedArr) {
try {
- if (!bldgSensorSamplingRateArr) return;
+ if (!bldgSensorSamplingRateNestedArr) return;
// Datastreams IDs
- const datastreamsIdsArr = bldgSensorSamplingRateArr.map(
- (bldgSensorSamplingRate) =>
- getDatastreamIdFromBuildingNumber(...bldgSensorSamplingRate)
+ const datastreamsIdsArr = bldgSensorSamplingRateNestedArr.map(
+ (bldgSensorSamplingRateArr) =>
+ getDatastreamIdFromBuildingNumber(...bldgSensorSamplingRateArr)
);
// Observations URLs
@@ -394,7 +427,7 @@ const calculateVorlaufMinusRuecklaufTemperature = async function (
samplingRate
) {
try {
- const bldgSensorSamplingRateArr = [
+ const bldgSensorSamplingRateNestedArr = [
[buildingId, "vl", samplingRate],
[buildingId, "rl", samplingRate],
];
@@ -406,23 +439,31 @@ const calculateVorlaufMinusRuecklaufTemperature = async function (
await getMetadataPlusObservationsFromSingleOrMultipleDatastreams(
baseUrl,
urlParams,
- bldgSensorSamplingRateArr
+ bldgSensorSamplingRateNestedArr
);
// Extract Vorlauf temperature, Ruecklauf temperature and metadata
- const [[vorlaufTemp, ruecklaufTemp], [metadataVorlauf, metadataRuecklauf]] =
- observationsPlusMetadata;
+ const [
+ [vorlaufTemperatureObsArr, ruecklaufTemperatureObsArr],
+ [metadataVorlauf, metadataRuecklauf],
+ ] = observationsPlusMetadata;
// Extract the temperature values
- const vorlaufTempValues = vorlaufTemp.map((obs) => obs[1]);
- const ruecklaufTempValues = ruecklaufTemp.map((obs) => obs[1]);
+ const vorlaufTemperatureValues = vorlaufTemperatureObsArr.map(
+ (vlTempObs) => vlTempObs[1]
+ );
+ const ruecklaufTemperatureValues = ruecklaufTemperatureObsArr.map(
+ (rlTempObs) => rlTempObs[1]
+ );
// The arrays have equal length, we need only use one of them for looping
// Resulting array contains the following pairs (timestamp + dT)
- const vorlaufMinusRuecklaufTemp = vorlaufTemp.map((obs, i) => [
- obs[0],
- vorlaufTempValues[i] - ruecklaufTempValues[i],
- ]);
+ const vorlaufMinusRuecklaufTemperatureObs = vorlaufTemperatureObsArr.map(
+ (vlTempObs, i) => [
+ vlTempObs[0], // timestamp
+ vorlaufTemperatureValues[i] - ruecklaufTemperatureValues[i],
+ ]
+ );
// From Vorlauf metadata, extract `name` and `unitOfMeasurement`
const {
@@ -459,7 +500,7 @@ const calculateVorlaufMinusRuecklaufTemperature = async function (
const unitOfMeasurement = unitOfMeasurementVorlauf;
return [
- vorlaufMinusRuecklaufTemp,
+ vorlaufMinusRuecklaufTemperatureObs,
{
description,
name,
@@ -473,6 +514,7 @@ const calculateVorlaufMinusRuecklaufTemperature = async function (
export {
formatDatastreamMetadataForChart,
+ extractPropertiesFromFormattedDatastreamMetadata,
getMetadataPlusObservationsFromSingleOrMultipleDatastreams,
calculateVorlaufMinusRuecklaufTemperature,
};