From 912e1b96bfa7d6c022d854fa744f719b49ca98d0 Mon Sep 17 00:00:00 2001 From: Georgios Andreadis Date: Tue, 21 Jul 2020 15:33:37 +0200 Subject: Add first plotting attempts for portfolios --- .../components/app/results/MetricChartComponent.js | 67 +++++++++++++++++++ .../app/results/PortfolioResultsComponent.js | 78 ++++++++++++++++++++++ 2 files changed, 145 insertions(+) create mode 100644 frontend/src/components/app/results/MetricChartComponent.js create mode 100644 frontend/src/components/app/results/PortfolioResultsComponent.js (limited to 'frontend/src/components/app/results') diff --git a/frontend/src/components/app/results/MetricChartComponent.js b/frontend/src/components/app/results/MetricChartComponent.js new file mode 100644 index 00000000..29a4676a --- /dev/null +++ b/frontend/src/components/app/results/MetricChartComponent.js @@ -0,0 +1,67 @@ +import React from 'react' +import ReactDOM from 'react-dom/server' +import SvgSaver from 'svgsaver' +import { VictoryAxis, VictoryChart, VictoryLabel, VictoryLine, VictoryScatter } from 'victory' +import { convertSecondsToFormattedTime } from '../../../util/date-time' + +const MetricChartComponent = ({ data, currentTick }) => { + const onExport = () => { + const div = document.createElement('div') + div.innerHTML = ReactDOM.renderToString( + + ) + div.firstChild.style = 'font-family: Roboto, Arial, sans-serif; font-size: 10pt;' + const svgSaver = new SvgSaver() + svgSaver.asSvg(div.firstChild, 'opendc-chart-export-' + Date.now() + '.svg') + } + + return ( +
+ Load over time + + +
+ ) +} + +const VictoryChartComponent = ({ data, currentTick, showCurrentTick }) => ( + + convertSecondsToFormattedTime(tick)} + fixLabelOverlap={true} + label="Simulated Time" + /> + + + + {showCurrentTick ? ( + } + data={[ + { x: currentTick + 1, y: 0 }, + { x: currentTick + 1, y: 1 }, + ]} + labels={(point) => + point.y === 1 ? 'Current tick : ' + convertSecondsToFormattedTime(currentTick) : '' + } + style={{ + data: { stroke: '#00A6D6', strokeWidth: 4 }, + labels: { fill: '#00A6D6' }, + }} + /> + ) : undefined} + +) + +const ExportChartComponent = ({ onExport }) => ( + +) + +export default MetricChartComponent diff --git a/frontend/src/components/app/results/PortfolioResultsComponent.js b/frontend/src/components/app/results/PortfolioResultsComponent.js new file mode 100644 index 00000000..8c778098 --- /dev/null +++ b/frontend/src/components/app/results/PortfolioResultsComponent.js @@ -0,0 +1,78 @@ +import React from 'react' +import PropTypes from 'prop-types' +import { Bar, BarChart, CartesianGrid, ErrorBar, ResponsiveContainer, Tooltip, XAxis, YAxis } from 'recharts' +import { AVAILABLE_METRICS, METRIC_NAMES } from '../../../util/available-metrics' +import { mean, std } from 'mathjs' +import Shapes from '../../../shapes/index' +import approx from 'approximate-number' + +const PortfolioResultsComponent = ({ portfolio, scenarios }) => { + if (!portfolio) { + return
Loading...
+ } + + const nonFinishedScenarios = scenarios.filter((s) => s.simulation.state !== 'FINISHED') + + if (nonFinishedScenarios.length > 0) { + if (nonFinishedScenarios.every((s) => s.simulation.state === 'QUEUED' || s.simulation.state === 'RUNNING')) { + return ( +
+

Simulation running...

+

{nonFinishedScenarios.length} of the scenarios are still being simulated

+
+ ) + } + if (nonFinishedScenarios.some((s) => s.simulation.state === 'FAILED')) { + return ( +
+

Simulation failed.

+

+ Try again by creating a new scenario. Please contact the OpenDC team for support, if issues + persist. +

+
+ ) + } + } + + const dataPerMetric = {} + + AVAILABLE_METRICS.forEach((metric) => { + dataPerMetric[metric] = scenarios.map((scenario) => ({ + name: scenario.name, + value: mean(scenario.results[metric]), + std: std(scenario.results[metric]), + })) + }) + + return ( +
+

Portfolio: {portfolio.name}

+

Repeats per Scenario: {portfolio.targets.repeatsPerScenario}

+
+ {AVAILABLE_METRICS.map(metric => ( +
+

{METRIC_NAMES[metric]}

+ + + + + approx(tick)}/> + + + + + +
+ ))} +
+
+ ) +} + +PortfolioResultsComponent.propTypes = { + portfolio: Shapes.Portfolio, + scenarios: PropTypes.arrayOf(Shapes.Scenario), +} + +export default PortfolioResultsComponent -- cgit v1.2.3 From 2ed4052162e2fcfa49f55cdd7f77cc2595526169 Mon Sep 17 00:00:00 2001 From: Georgios Andreadis Date: Tue, 21 Jul 2020 15:50:20 +0200 Subject: Fix overflow and rearrange --- .../components/app/results/PortfolioResultsComponent.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'frontend/src/components/app/results') diff --git a/frontend/src/components/app/results/PortfolioResultsComponent.js b/frontend/src/components/app/results/PortfolioResultsComponent.js index 8c778098..a5c33f47 100644 --- a/frontend/src/components/app/results/PortfolioResultsComponent.js +++ b/frontend/src/components/app/results/PortfolioResultsComponent.js @@ -46,21 +46,21 @@ const PortfolioResultsComponent = ({ portfolio, scenarios }) => { }) return ( -
+

Portfolio: {portfolio.name}

Repeats per Scenario: {portfolio.targets.repeatsPerScenario}

- {AVAILABLE_METRICS.map(metric => ( + {AVAILABLE_METRICS.map((metric) => (

{METRIC_NAMES[metric]}

- - - approx(tick)}/> - - - + + + approx(tick)} /> + + +
-- cgit v1.2.3 From 3c03c08f996c1cd2bc26bac7bb72a5e61cad6338 Mon Sep 17 00:00:00 2001 From: Georgios Andreadis Date: Wed, 22 Jul 2020 11:14:03 +0200 Subject: Add error bars --- .../app/results/PortfolioResultsComponent.js | 31 +++++++++++++--------- 1 file changed, 18 insertions(+), 13 deletions(-) (limited to 'frontend/src/components/app/results') diff --git a/frontend/src/components/app/results/PortfolioResultsComponent.js b/frontend/src/components/app/results/PortfolioResultsComponent.js index a5c33f47..e9b33777 100644 --- a/frontend/src/components/app/results/PortfolioResultsComponent.js +++ b/frontend/src/components/app/results/PortfolioResultsComponent.js @@ -1,7 +1,7 @@ import React from 'react' import PropTypes from 'prop-types' -import { Bar, BarChart, CartesianGrid, ErrorBar, ResponsiveContainer, Tooltip, XAxis, YAxis } from 'recharts' -import { AVAILABLE_METRICS, METRIC_NAMES } from '../../../util/available-metrics' +import { Bar, CartesianGrid, ComposedChart, ErrorBar, ResponsiveContainer, Scatter, XAxis, YAxis } from 'recharts' +import { AVAILABLE_METRICS, METRIC_NAMES, METRIC_UNITS } from '../../../util/available-metrics' import { mean, std } from 'mathjs' import Shapes from '../../../shapes/index' import approx from 'approximate-number' @@ -41,27 +41,32 @@ const PortfolioResultsComponent = ({ portfolio, scenarios }) => { dataPerMetric[metric] = scenarios.map((scenario) => ({ name: scenario.name, value: mean(scenario.results[metric]), - std: std(scenario.results[metric]), + errorX: std(scenario.results[metric]), })) }) return (
-

Portfolio: {portfolio.name}

+

Portfolio: {portfolio.name}

Repeats per Scenario: {portfolio.targets.repeatsPerScenario}

{AVAILABLE_METRICS.map((metric) => ( -
+

{METRIC_NAMES[metric]}

- - - - approx(tick)} /> - - - - + + + approx(tick)} + label={{ value: METRIC_UNITS[metric], position: 'bottom', offset: 0 }} + type="number"/> + + + + + + +
))} -- cgit v1.2.3 From 0d7889c23d407f6c0cd3db4020989ce8a5f8063a Mon Sep 17 00:00:00 2001 From: Georgios Andreadis Date: Wed, 22 Jul 2020 11:40:01 +0200 Subject: Fix polling and upgrade bootstrap --- .../app/results/PortfolioResultsComponent.js | 28 +++++++++++++--------- 1 file changed, 17 insertions(+), 11 deletions(-) (limited to 'frontend/src/components/app/results') diff --git a/frontend/src/components/app/results/PortfolioResultsComponent.js b/frontend/src/components/app/results/PortfolioResultsComponent.js index e9b33777..286dd48c 100644 --- a/frontend/src/components/app/results/PortfolioResultsComponent.js +++ b/frontend/src/components/app/results/PortfolioResultsComponent.js @@ -54,18 +54,24 @@ const PortfolioResultsComponent = ({ portfolio, scenarios }) => {

{METRIC_NAMES[metric]}

- - - approx(tick)} - label={{ value: METRIC_UNITS[metric], position: 'bottom', offset: 0 }} - type="number"/> - - - - + + + approx(tick)} + label={{ value: METRIC_UNITS[metric], position: 'bottom', offset: 0 }} + type="number" + /> + + + + -
-- cgit v1.2.3 From 8739a156b75ba96e15d1bb19b08ca829c1eb01e8 Mon Sep 17 00:00:00 2001 From: Georgios Andreadis Date: Wed, 22 Jul 2020 13:25:53 +0200 Subject: Remove old charting library --- .../components/app/results/MetricChartComponent.js | 67 ---------------------- 1 file changed, 67 deletions(-) delete mode 100644 frontend/src/components/app/results/MetricChartComponent.js (limited to 'frontend/src/components/app/results') diff --git a/frontend/src/components/app/results/MetricChartComponent.js b/frontend/src/components/app/results/MetricChartComponent.js deleted file mode 100644 index 29a4676a..00000000 --- a/frontend/src/components/app/results/MetricChartComponent.js +++ /dev/null @@ -1,67 +0,0 @@ -import React from 'react' -import ReactDOM from 'react-dom/server' -import SvgSaver from 'svgsaver' -import { VictoryAxis, VictoryChart, VictoryLabel, VictoryLine, VictoryScatter } from 'victory' -import { convertSecondsToFormattedTime } from '../../../util/date-time' - -const MetricChartComponent = ({ data, currentTick }) => { - const onExport = () => { - const div = document.createElement('div') - div.innerHTML = ReactDOM.renderToString( - - ) - div.firstChild.style = 'font-family: Roboto, Arial, sans-serif; font-size: 10pt;' - const svgSaver = new SvgSaver() - svgSaver.asSvg(div.firstChild, 'opendc-chart-export-' + Date.now() + '.svg') - } - - return ( -
- Load over time - - -
- ) -} - -const VictoryChartComponent = ({ data, currentTick, showCurrentTick }) => ( - - convertSecondsToFormattedTime(tick)} - fixLabelOverlap={true} - label="Simulated Time" - /> - - - - {showCurrentTick ? ( - } - data={[ - { x: currentTick + 1, y: 0 }, - { x: currentTick + 1, y: 1 }, - ]} - labels={(point) => - point.y === 1 ? 'Current tick : ' + convertSecondsToFormattedTime(currentTick) : '' - } - style={{ - data: { stroke: '#00A6D6', strokeWidth: 4 }, - labels: { fill: '#00A6D6' }, - }} - /> - ) : undefined} - -) - -const ExportChartComponent = ({ onExport }) => ( - -) - -export default MetricChartComponent -- cgit v1.2.3 From 94cc7acc9eeb88177b7d75ff1d1c3245d09bce53 Mon Sep 17 00:00:00 2001 From: Georgios Andreadis Date: Wed, 22 Jul 2020 15:19:32 +0200 Subject: Set first scenario name to be "Base scenario" --- frontend/src/components/app/results/PortfolioResultsComponent.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'frontend/src/components/app/results') diff --git a/frontend/src/components/app/results/PortfolioResultsComponent.js b/frontend/src/components/app/results/PortfolioResultsComponent.js index 286dd48c..90325b2b 100644 --- a/frontend/src/components/app/results/PortfolioResultsComponent.js +++ b/frontend/src/components/app/results/PortfolioResultsComponent.js @@ -54,7 +54,7 @@ const PortfolioResultsComponent = ({ portfolio, scenarios }) => {

{METRIC_NAMES[metric]}

- + approx(tick)} -- cgit v1.2.3 From 9e7cb3bd367607b32e102c3a87b68b33c53dec46 Mon Sep 17 00:00:00 2001 From: Georgios Andreadis Date: Wed, 22 Jul 2020 15:39:11 +0200 Subject: Fix scenario name handling and increase margin --- frontend/src/components/app/results/PortfolioResultsComponent.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'frontend/src/components/app/results') diff --git a/frontend/src/components/app/results/PortfolioResultsComponent.js b/frontend/src/components/app/results/PortfolioResultsComponent.js index 90325b2b..35dba603 100644 --- a/frontend/src/components/app/results/PortfolioResultsComponent.js +++ b/frontend/src/components/app/results/PortfolioResultsComponent.js @@ -54,7 +54,7 @@ const PortfolioResultsComponent = ({ portfolio, scenarios }) => {

{METRIC_NAMES[metric]}

- + approx(tick)} -- cgit v1.2.3