diff --git a/frontend/js/helpers/charts.js b/frontend/js/helpers/charts.js
index bca3a3492..1a550ad74 100644
--- a/frontend/js/helpers/charts.js
+++ b/frontend/js/helpers/charts.js
@@ -1,3 +1,9 @@
+const calculateStatistics = (data) => {
+ const mean = data.reduce((sum, value) => sum + value.value, 0) / data.length;
+ const stddev = Math.sqrt(data.reduce((sum, value) => sum + Math.pow(value.value - mean, 2), 0) / data.length);
+ return { mean, stddev };
+}
+
const getCompareChartOptions = (legend, series, chart_type='line', x_axis='time', y_axis_name, mark_area=null, graphic=null) => {
let tooltip_trigger = (chart_type=='line') ? 'axis' : 'item';
@@ -106,7 +112,7 @@ const calculateMA = (series, factor) => {
return result;
}
-const getLineBarChartOptions = (legend, labels, series, x_axis_name=null, y_axis_name='', x_axis='time', mark_area=null, no_toolbox=false, graphic=null, moving_average=false, show_x_axis_label=true) => {
+const getLineBarChartOptions = (legend, labels, series, x_axis_name=null, y_axis_name='', x_axis='time', mark_area=null, no_toolbox=false, graphic=null, moving_average=false, show_x_axis_label=true, stddev=false) => {
if(Object.keys(series).length == 0) {
return {graphic: getChartGraphic("No energy reporter active")};
@@ -128,6 +134,31 @@ const getLineBarChartOptions = (legend, labels, series, x_axis_name=null, y_axis
})
}
+ if(stddev) {
+ const { mean, stddev } = calculateStatistics(series[0].data);
+
+ legend.push('Stddev')
+ series.push({
+ name: 'Stddev',
+ type: 'line',
+ markArea: {
+ label: {
+ show: true,
+ name: "MarkArea",
+ position: 'top'
+ },
+ data: [
+ [
+ { yAxis: mean + stddev, name: `StdDev: ${(stddev/mean * 100).toFixed(2)} %`},
+ { yAxis: mean - stddev},
+ ]
+
+ ],
+ }
+ });
+ }
+
+
let options = {
tooltip: { trigger: tooltip_trigger },
grid: {
diff --git a/frontend/js/timeline.js b/frontend/js/timeline.js
index 045b670dd..69d5974fd 100644
--- a/frontend/js/timeline.js
+++ b/frontend/js/timeline.js
@@ -218,12 +218,12 @@ const loadCharts = async () => {
}
}]
- let options = getLineBarChartOptions([], series[my_series].labels, data_series, 'Time', series[my_series].unit, 'category', null, false, null, true, false);
+ let options = getLineBarChartOptions([], series[my_series].labels, data_series, 'Time', series[my_series].unit, 'category', null, false, null, true, false, true);
options.tooltip = {
trigger: 'item',
formatter: function (params, ticket, callback) {
- if(params.componentType != 'series') return; // no notes for the MovingAverage
+ if(series[params.seriesName]?.notes == null) return; // no notes for the MovingAverage
return `${series[params.seriesName].notes[params.dataIndex].run_name}
date: ${series[params.seriesName].notes[params.dataIndex].created_at}
metric_name: ${params.seriesName}
@@ -243,9 +243,31 @@ const loadCharts = async () => {
});
+ options.dataZoom = {
+ show: false,
+ start: 0,
+ end: 100,
+ };
+
chart_instance.setOption(options);
chart_instances.push(chart_instance);
+ chart_instance.on('datazoom', function(e, f) {
+ const data = chart_instance.getOption().series[0].data
+ const dataZoomOption = chart_instance.getOption().dataZoom[0];
+ const startPercent = dataZoomOption.start;
+ const endPercent = dataZoomOption.end;
+ const totalDataPoints = data.length;
+ const startIndex = Math.floor(startPercent / 100 * totalDataPoints);
+ const endIndex = Math.ceil(endPercent / 100 * totalDataPoints) - 1;
+ const { mean, stddev } = calculateStatistics(data.slice(startIndex, endIndex+1));
+
+ let options = chart_instance.getOption()
+ options.series[2].markArea.data[0][0].name = `StdDev: ${(stddev/mean * 100).toFixed(2)} %`
+ options.series[2].markArea.data[0][0].yAxis = mean + stddev
+ options.series[2].markArea.data[0][1].yAxis = mean - stddev;
+ chart_instance.setOption(options)
+ });
}