diff --git a/index.html b/index.html
index c90ef6807d1c3f48a6acad9b4f327bf55df86278..caf70127f79b058c7bb59f149ba8dddf3b297b5d 100644
--- a/index.html
+++ b/index.html
@@ -28,12 +28,11 @@
     ></script>
 
     <!-- Axios -->
-    <!-- <script src="./node_modules/axios/dist/axios.min.js"></script> -->
     <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
 
-    <!-- Higcharts lib -->
-    <!-- Does not play well with `Highstock`; see: https://www.highcharts.com/errors/16/
-    <script src="https://code.highcharts.com/highcharts.js"></script> -->
+    <!-- Higcharts -->
+    <!-- `highcharts.js` does not play well with `highstock.js`; see: https://www.highcharts.com/errors/16/-->
+    <!-- <script src="https://code.highcharts.com/highcharts.js"></script>  -->
     <script src="https://code.highcharts.com/stock/highstock.js"></script>
     <script src="https://code.highcharts.com/stock/modules/data.js"></script>
     <script src="https://code.highcharts.com/stock/modules/exporting.js"></script>
@@ -44,11 +43,7 @@
     <script src="https://code.highcharts.com/modules/boost.js"></script>
     <script src="https://code.highcharts.com/modules/accessibility.js"></script>
 
-    <!-- Apexcharts lib -->
-    <script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>
-    <link rel="stylesheet" href="css/styles.css" />
-
-    <!-- Cesium lib -->
+    <!-- Cesium -->
     <script src="https://cesium.com/downloads/cesiumjs/releases/1.48/Build/Cesium/Cesium.js"></script>
     <link
       href="https://cesium.com/downloads/cesiumjs/releases/1.48/Build/Cesium/Widgets/widgets.css"
@@ -230,7 +225,7 @@
                     Bar Chart Example
                   </div>
                   <div class="card-body">
-                    <div id="chart-bar" width="100%" height="40"></div>
+                    <div id="chart-column" width="100%" height="40"></div>
                   </div>
                 </div>
               </div>
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: `
+                      <span style="font-size:10px">{point.key}</span>
+                      <table>
+                      `,
+      pointFormat: `
+                      <tr>
+                          <td style="color:{series.color};padding:0">{series.name}: </td>
+                          <td style="padding:0"><b>{point.y:.1f} mm</b></td>
+                      </tr>
+                      `,
+      footerFormat: `
+                      </table>
+                      `,
+      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,
 };