From 39746931bb34701ad436afd557738cc3be3bc72d Mon Sep 17 00:00:00 2001 From: Anthony Castronova Date: Tue, 3 Dec 2024 14:27:22 -0500 Subject: [PATCH 1/7] Removing wse-width plot from node view and adding it to reach view --- frontend/src/components/LineChart.vue | 39 +++++++++++++++++---------- frontend/src/stores/charts.js | 16 +++++------ 2 files changed, 33 insertions(+), 22 deletions(-) diff --git a/frontend/src/components/LineChart.vue b/frontend/src/components/LineChart.vue index 168c38b7..5ca5298d 100644 --- a/frontend/src/components/LineChart.vue +++ b/frontend/src/components/LineChart.vue @@ -150,6 +150,30 @@ const getParsing = () => { return parsing } +const getXScale = () => { + let xvar_abbr = plt.xvar.abbreviation + if (xvar_abbr == 'time_str') { + return { + type: 'time', + time: { + locale: enUS + }, + title: { + display: true, + text: xLabel + } + } + } else { + return { + type: 'linear', + title: { + display: true, + text: xLabel + } + } + } +} + const options = { responsive: true, maintainAspectRatio: false, @@ -216,20 +240,7 @@ const options = { } }, scales: { - x: { - type: 'time', - time: { - // unit: 'day', - // displayFormats: { - // day: 'MM.dd' - // }, - locale: enUS - }, - title: { - display: true, - text: xLabel - } - }, + x: getXScale(), y: { title: { display: true, diff --git a/frontend/src/stores/charts.js b/frontend/src/stores/charts.js index e8dd0a8e..b1b84daf 100644 --- a/frontend/src/stores/charts.js +++ b/frontend/src/stores/charts.js @@ -71,14 +71,6 @@ export const useChartsStore = defineStore('charts', () => { title: 'Reach Width along Reach Length', help: "Reach Width plotted against Reach Length for all nodes in the selected reach", name: 'Width vs Distance', - }, - { - abbreviation: 'wse/width', - xvar: swotVariables.value.find((v) => v.abbreviation == 'width'), - yvar: swotVariables.value.find((v) => v.abbreviation == 'wse'), - title: 'Water Surface Elevation vs Reach Width', - help: "Water Surface Elevation plotted against Reach Width for all nodes in the selected reach", - name: 'WSE vs Width', } ]) @@ -117,6 +109,14 @@ export const useChartsStore = defineStore('charts', () => { title: 'Reach Slope', help: swotVariables.value.find((v) => v.abbreviation == 'slope').definition, name: 'Slope vs Time', + }, + { + abbreviation: 'wse/width', + xvar: swotVariables.value.find((v) => v.abbreviation == 'width'), + yvar: swotVariables.value.find((v) => v.abbreviation == 'wse'), + title: 'Water Surface Elevation vs Reach Width', + help: "Water Surface Elevation plotted against Reach Width for all nodes in the selected reach", + name: 'WSE vs Width', } ]) From 64a4bbdcce8982a6802be353732acccac41a8a3f Mon Sep 17 00:00:00 2001 From: Anthony Castronova Date: Wed, 4 Dec 2024 15:11:02 -0500 Subject: [PATCH 2/7] Implemented x axis data sorting in the timeseriesview --- frontend/src/components/LineChart.vue | 3 ++- frontend/src/views/TimeSeriesCharts.vue | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/frontend/src/components/LineChart.vue b/frontend/src/components/LineChart.vue index 5ca5298d..c4684092 100644 --- a/frontend/src/components/LineChart.vue +++ b/frontend/src/components/LineChart.vue @@ -147,11 +147,12 @@ const getParsing = () => { parsing.xAxisKey = plt.xvar.abbreviation parsing.yAxisKey = plt.yvar.abbreviation + return parsing } const getXScale = () => { - let xvar_abbr = plt.xvar.abbreviation + let xvar_abbr = props.chosenPlot.xvar.abbreviation if (xvar_abbr == 'time_str') { return { type: 'time', diff --git a/frontend/src/views/TimeSeriesCharts.vue b/frontend/src/views/TimeSeriesCharts.vue index 771503a7..24950c45 100644 --- a/frontend/src/views/TimeSeriesCharts.vue +++ b/frontend/src/views/TimeSeriesCharts.vue @@ -75,7 +75,31 @@ onMounted(() => { } }) +const sortChartByX = (plt) => { + // grab the chart data from the store and maintain reactivity + const {chartData} = storeToRefs(chartStore) + + // get the chart data and sort it by the x-axis variable. + // If the x-axis variable is time, sort by time otherwise + // sort numerically. + let plotData = chartData.value.datasets[0].data + let xvar = plt.xvar.abbreviation + + if (xvar == 'time_str') { + plotData = plotData.sort((a,b) => new Date(a.time_str) - new Date(b.time_str)); + } + else { + plotData = plotData.sort((a,b) => parseFloat(a[xvar]) - parseFloat(b[xvar])); + } + chartStore.updateShowLine() + +} + const changePlot = (plt) => { + // re-sort the chart data by the x-axis variable + // before rending the chart + sortChartByX(plt) + router.push({ query: { ...router.currentRoute.value.query, variables: plt.abbreviation } }) } From de7de594dcf304d8643a3bbd1f48b9e9369e843f Mon Sep 17 00:00:00 2001 From: Anthony Castronova Date: Thu, 5 Dec 2024 09:48:54 -0500 Subject: [PATCH 3/7] Moved x sort function into the chart store, implemented x sort for node profile charts, added check to make sure charts are not undefined when attempting to update them. --- frontend/src/stores/charts.js | 38 +++++++++++++++++++------ frontend/src/views/DistanceCharts.vue | 9 ++++++ frontend/src/views/TimeSeriesCharts.vue | 27 ++++-------------- 3 files changed, 44 insertions(+), 30 deletions(-) diff --git a/frontend/src/stores/charts.js b/frontend/src/stores/charts.js index b1b84daf..c43ba4ee 100644 --- a/frontend/src/stores/charts.js +++ b/frontend/src/stores/charts.js @@ -686,10 +686,12 @@ export const useChartsStore = defineStore('charts', () => { // iterate over stored charts and update the line visibility storedCharts.value.forEach((storedChart) => { try { - storedChart.chart.data.datasets.filter(ds => ds.seriesType != 'computed_series').forEach((dataset) => { - dataset.showLine = showLine.value - }) - storedChart.chart.update() + if (storedChart.chart != null) { + storedChart.chart.data.datasets.filter(ds => ds.seriesType != 'computed_series').forEach((dataset) => { + dataset.showLine = showLine.value + }) + storedChart.chart.update() + } } catch (error) { console.error('Error updating chart lines', error) } @@ -700,10 +702,12 @@ export const useChartsStore = defineStore('charts', () => { updateNodeDataSetStyles() // iterate over stored charts and update the line visibility storedCharts.value.forEach((storedChart) => { - try { - storedChart.chart.update() - } catch (error) { - console.error('Error updating chart', error) + if (storedChart.chart != null) { + try { + storedChart.chart.update() + } catch (error) { + console.error('Error updating chart', error) + } } }) } @@ -721,6 +725,21 @@ export const useChartsStore = defineStore('charts', () => { } +const sortChartByX = (plt) => { + + // get the chart data and sort it by the x-axis variable. + // If the x-axis variable is time, sort by time otherwise + // sort numerically. + let plotData = chartData.value.datasets[0].data + let xvar = plt.xvar.abbreviation + + if (xvar == 'time_str') { + return plotData.sort((a,b) => new Date(a.time_str) - new Date(b.time_str)); + } + else { + return plotData.sort((a,b) => parseFloat(a[xvar]) - parseFloat(b[xvar])); + } +} return { updateNodeChartData, @@ -746,6 +765,7 @@ export const useChartsStore = defineStore('charts', () => { showLine, updateShowLine, storeMountedChart, - activePlt + activePlt, + sortChartByX, } }) diff --git a/frontend/src/views/DistanceCharts.vue b/frontend/src/views/DistanceCharts.vue index 9af0b2a1..538df891 100644 --- a/frontend/src/views/DistanceCharts.vue +++ b/frontend/src/views/DistanceCharts.vue @@ -76,6 +76,15 @@ onMounted(() => { }) const changePlot = (plt) => { + // re-sort the chart data by the x-axis variable + // before rending the chart. Set the sorted data + // to the active data in the chart prior to rendering + const {chartData} = storeToRefs(chartStore) + chartData.value.datasets[0].data = chartStore.sortChartByX(plt) + + // force a re-render of the line charts + chartStore.updateShowLine() + router.push({ query: { ...router.currentRoute.value.query, variables: plt.abbreviation } }) } diff --git a/frontend/src/views/TimeSeriesCharts.vue b/frontend/src/views/TimeSeriesCharts.vue index 24950c45..45eb7069 100644 --- a/frontend/src/views/TimeSeriesCharts.vue +++ b/frontend/src/views/TimeSeriesCharts.vue @@ -75,31 +75,16 @@ onMounted(() => { } }) -const sortChartByX = (plt) => { - // grab the chart data from the store and maintain reactivity +const changePlot = (plt) => { + // re-sort the chart data by the x-axis variable + // before rending the chart. Set the sorted data + // to the active data in the chart prior to rendering const {chartData} = storeToRefs(chartStore) - - // get the chart data and sort it by the x-axis variable. - // If the x-axis variable is time, sort by time otherwise - // sort numerically. - let plotData = chartData.value.datasets[0].data - let xvar = plt.xvar.abbreviation + chartData.value.datasets[0].data = chartStore.sortChartByX(plt) - if (xvar == 'time_str') { - plotData = plotData.sort((a,b) => new Date(a.time_str) - new Date(b.time_str)); - } - else { - plotData = plotData.sort((a,b) => parseFloat(a[xvar]) - parseFloat(b[xvar])); - } + // force a re-render of the line charts chartStore.updateShowLine() -} - -const changePlot = (plt) => { - // re-sort the chart data by the x-axis variable - // before rending the chart - sortChartByX(plt) - router.push({ query: { ...router.currentRoute.value.query, variables: plt.abbreviation } }) } From abe11b56e150f154aa75dadfda96c3719a980566 Mon Sep 17 00:00:00 2001 From: Anthony Castronova Date: Thu, 5 Dec 2024 09:50:28 -0500 Subject: [PATCH 4/7] Changed the Reach Timeseries tab to Reach Averaged --- frontend/src/views/ChartsView.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/views/ChartsView.vue b/frontend/src/views/ChartsView.vue index c030047e..a43fd0f0 100644 --- a/frontend/src/views/ChartsView.vue +++ b/frontend/src/views/ChartsView.vue @@ -3,7 +3,7 @@ - Reach Timeseries + Reach Averaged From 2e723bbe2c14f991837260733aecd036a673d31a Mon Sep 17 00:00:00 2001 From: Anthony Castronova Date: Mon, 9 Dec 2024 11:07:46 -0500 Subject: [PATCH 5/7] modifying charts logic to update the current chart only instead of all charts to fix x-sorting issue. --- frontend/src/components/DataQuality.vue | 3 +- frontend/src/components/LineChart.vue | 6 ++- frontend/src/components/NodeChart.vue | 4 +- frontend/src/stores/charts.js | 49 ++++++++++++++++++++++++- frontend/src/views/DistanceCharts.vue | 12 ++++-- frontend/src/views/TimeSeriesCharts.vue | 19 ++++++++-- 6 files changed, 82 insertions(+), 11 deletions(-) diff --git a/frontend/src/components/DataQuality.vue b/frontend/src/components/DataQuality.vue index 86818119..7588ca86 100644 --- a/frontend/src/components/DataQuality.vue +++ b/frontend/src/components/DataQuality.vue @@ -45,6 +45,7 @@ function qualityHasChanged() { // apply the time slider filter to the data chartStore.filterDatasetsToTimeRange() - chartStore.updateAllCharts() + + chartStore.updateCurrentChart() } diff --git a/frontend/src/components/LineChart.vue b/frontend/src/components/LineChart.vue index 0119a58e..a3a07a43 100644 --- a/frontend/src/components/LineChart.vue +++ b/frontend/src/components/LineChart.vue @@ -92,8 +92,12 @@ onMounted(async () => { await nextTick() // push the chart to the store + //chartStore.storeMountedChart(activeReachChart.value, xLabel, yLabel) chartStore.storeMountedChart(activeReachChart.value) - chartStore.updateShowLine() + + // force a re-render of the line charts + chartStore.updateCurrentChart() + //chartStore.updateShowLine() }) const getParsing = () => { diff --git a/frontend/src/components/NodeChart.vue b/frontend/src/components/NodeChart.vue index 0bfcd8e3..29cb1176 100644 --- a/frontend/src/components/NodeChart.vue +++ b/frontend/src/components/NodeChart.vue @@ -41,8 +41,10 @@ onMounted(async () => { await nextTick() // push the chart to the store + //chartStore.storeMountedChart(activeNodeChart.value, xLabel, yLabel) chartStore.storeMountedChart(activeNodeChart.value) - chartStore.updateShowLine() + //chartStore.updateShowLine() + chartStore.updateCurrentChart() }) const getParsing = () => { diff --git a/frontend/src/stores/charts.js b/frontend/src/stores/charts.js index 0cfb3736..f96977b7 100644 --- a/frontend/src/stores/charts.js +++ b/frontend/src/stores/charts.js @@ -774,9 +774,15 @@ export const useChartsStore = defineStore('charts', () => { } } }) + } const storeMountedChart = (chart) => { + //, xlabel, ylabel) => { + + // add x and y labels to the chart object so we can look it up later +// chart.xlabel = xlabel +// chart.ylabel = ylabel storedCharts.value.push(chart) // clean stored charts that are undifined @@ -794,7 +800,7 @@ const sortChartByX = (plt) => { // get the chart data and sort it by the x-axis variable. // If the x-axis variable is time, sort by time otherwise // sort numerically. - let plotData = chartData.value.datasets[0].data + let plotData = getActiveChart().chart.data.datasets[0].data let xvar = plt.xvar.abbreviation if (xvar == 'time_str') { @@ -805,6 +811,46 @@ const sortChartByX = (plt) => { } } +const getActiveChart = () => +{ + if (chartTab.value == 'timeseries') + { + return activeReachChart.value + } else + { + return activeNodeChart.value + } +} + +const updateCurrentChart = () => { + let storedChart = getActiveChart() + if (storedChart == null) { + console.log('No chart to update') + return + } + + console.log('storedChart', storedChart) + try { + // check if the chart is a node chart or a reach chart + // and refresh the data accordingly + if (storedChart.chart.data.datasets[0].seriesType == 'swot_node_series') { + storedChart.chart.data.datasets = nodeChartData.value.datasets + } else { + storedChart.chart.data.datasets = chartData.value.datasets + } + } catch (error) { + console.error('Error updating chart', error) + } + + storedChart.chart.data.datasets.filter(ds => ds.seriesType != 'computed_series').forEach((dataset) => { + dataset.showLine = showLine.value + dataset.pointStyle = getPointStyles(dataset) + }) + + // sort the chart data by the x-axis variable + storedChart.chart.data.datasets[0].data = sortChartByX(activePlt.value) +} + return { updateNodeChartData, chartData, @@ -834,5 +880,6 @@ const sortChartByX = (plt) => { activeNodeChart, activeReachChart, updateNodeDataSetStyles, + updateCurrentChart, } }) diff --git a/frontend/src/views/DistanceCharts.vue b/frontend/src/views/DistanceCharts.vue index dd777d39..1cf427fd 100644 --- a/frontend/src/views/DistanceCharts.vue +++ b/frontend/src/views/DistanceCharts.vue @@ -87,11 +87,17 @@ const changePlot = (plt) => { // re-sort the chart data by the x-axis variable // before rending the chart. Set the sorted data // to the active data in the chart prior to rendering - const {chartData} = storeToRefs(chartStore) - chartData.value.datasets[0].data = chartStore.sortChartByX(plt) + const {activePlt} = storeToRefs(chartStore) + + // save the active plot so we can update it when + // controls (e.g. quality) are changed later. + activePlt.value = plt + + //chartData.value.datasets[0].data = chartStore.sortChartByX(plt) // force a re-render of the line charts - chartStore.updateShowLine() + chartStore.updateCurrentChart() + //chartStore.updateShowLine() router.push({ query: { ...router.currentRoute.value.query, variables: plt.abbreviation } }) } diff --git a/frontend/src/views/TimeSeriesCharts.vue b/frontend/src/views/TimeSeriesCharts.vue index a41af33c..6686a126 100644 --- a/frontend/src/views/TimeSeriesCharts.vue +++ b/frontend/src/views/TimeSeriesCharts.vue @@ -87,13 +87,24 @@ const changePlot = (plt) => { // re-sort the chart data by the x-axis variable // before rending the chart. Set the sorted data // to the active data in the chart prior to rendering - const {chartData} = storeToRefs(chartStore) - chartData.value.datasets[0].data = chartStore.sortChartByX(plt) + //const {chartData, activeChartVariables, activeReachChart} = storeToRefs(chartStore) + const {chartData, activePlt} = storeToRefs(chartStore) - // force a re-render of the line charts - chartStore.updateShowLine() + + // save the active plot so we can update it when + // controls (e.g. quality) are changed later. + activePlt.value = plt + + //chartData.value.datasets[0].data = chartStore.sortChartByX(plt) + + // TODO: save this plt as the active plot so we can refresh the data in the chart.js class later. + // force a re-render of the line charts + chartStore.updateCurrentChart() +// chartStore.updateShowLine() + router.push({ query: { ...router.currentRoute.value.query, variables: plt.abbreviation } }) + } From 981b71f535999b040e07b27e39fc4e4efdff0af9 Mon Sep 17 00:00:00 2001 From: Anthony Castronova Date: Mon, 9 Dec 2024 22:00:56 -0500 Subject: [PATCH 6/7] Adding missing change --- frontend/src/views/TimeSeriesCharts.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/views/TimeSeriesCharts.vue b/frontend/src/views/TimeSeriesCharts.vue index 6686a126..77bd6902 100644 --- a/frontend/src/views/TimeSeriesCharts.vue +++ b/frontend/src/views/TimeSeriesCharts.vue @@ -88,7 +88,7 @@ const changePlot = (plt) => { // before rending the chart. Set the sorted data // to the active data in the chart prior to rendering //const {chartData, activeChartVariables, activeReachChart} = storeToRefs(chartStore) - const {chartData, activePlt} = storeToRefs(chartStore) + const {activePlt} = storeToRefs(chartStore) // save the active plot so we can update it when From 923dbedbdce3c993fc3b363d8b83e2ca5ac9c044 Mon Sep 17 00:00:00 2001 From: Anthony Castronova Date: Thu, 12 Dec 2024 16:40:30 -0500 Subject: [PATCH 7/7] Modified getActiveChart function to return the correct chart. --- frontend/src/components/LineChart.vue | 3 +- frontend/src/stores/charts.js | 57 ++++++++++++++++--------- frontend/src/views/TimeSeriesCharts.vue | 2 +- 3 files changed, 38 insertions(+), 24 deletions(-) diff --git a/frontend/src/components/LineChart.vue b/frontend/src/components/LineChart.vue index a3a07a43..70586877 100644 --- a/frontend/src/components/LineChart.vue +++ b/frontend/src/components/LineChart.vue @@ -92,8 +92,7 @@ onMounted(async () => { await nextTick() // push the chart to the store - //chartStore.storeMountedChart(activeReachChart.value, xLabel, yLabel) - chartStore.storeMountedChart(activeReachChart.value) + chartStore.storeMountedChart(activeReachChart.value, xLabel, yLabel) // force a re-render of the line charts chartStore.updateCurrentChart() diff --git a/frontend/src/stores/charts.js b/frontend/src/stores/charts.js index f96977b7..03f1d2b4 100644 --- a/frontend/src/stores/charts.js +++ b/frontend/src/stores/charts.js @@ -757,6 +757,8 @@ export const useChartsStore = defineStore('charts', () => { } const updateAllCharts = () => { + // This function updates the styling for all stored charts + // iterate over stored charts and update the line visibility storedCharts.value.forEach((storedChart) => { if (storedChart.chart != null) { @@ -777,15 +779,14 @@ export const useChartsStore = defineStore('charts', () => { } - const storeMountedChart = (chart) => { - //, xlabel, ylabel) => { - - // add x and y labels to the chart object so we can look it up later -// chart.xlabel = xlabel -// chart.ylabel = ylabel + const storeMountedChart = (chart, x, y) => { + + chart.x = x + chart.y = y storedCharts.value.push(chart) - // clean stored charts that are undifined + console.log('Storing New Chart -> ', chart) + // clean stored charts that are undefined cleanStoredCharts() } @@ -795,41 +796,53 @@ export const useChartsStore = defineStore('charts', () => { } -const sortChartByX = (plt) => { +const sortChartByX = (chart) => { // get the chart data and sort it by the x-axis variable. // If the x-axis variable is time, sort by time otherwise // sort numerically. - let plotData = getActiveChart().chart.data.datasets[0].data - let xvar = plt.xvar.abbreviation + let chartData = chart.data.datasets[0].data + let xvar = activePlt.value.xvar.abbreviation if (xvar == 'time_str') { - return plotData.sort((a,b) => new Date(a.time_str) - new Date(b.time_str)); + return chartData.sort((a,b) => new Date(a.time_str) - new Date(b.time_str)); } else { - return plotData.sort((a,b) => parseFloat(a[xvar]) - parseFloat(b[xvar])); + return chartData.sort((a,b) => parseFloat(a[xvar]) - parseFloat(b[xvar])); } } const getActiveChart = () => { - if (chartTab.value == 'timeseries') - { - return activeReachChart.value - } else - { - return activeNodeChart.value + // Retrieves the currently active chart from the list of + // stored charts using its x and y labels + + // return null if no charts exist in the storedCharts object. This + // can happen on the initial page load. + if (storedCharts.value.length == 0) { + return null } + + // get the x and y labels for the currenty active chart + let xlabel = activePlt.value.xvar.name + let ylabel = activePlt.value.yvar.name + + // add units to the labels, if they exist + if (activePlt.value.xvar.unit != null) { xlabel += ' (' + activePlt.value.xvar.unit + ')'} + if (activePlt.value.yvar.unit != null) { ylabel += ' (' + activePlt.value.yvar.unit + ')'} + + // return the stored chart that matches the current x and y labels + return storedCharts.value.filter(c => (c.x == xlabel && c.y == ylabel) )[0] } const updateCurrentChart = () => { + + // get the currently active chart from the chartStore. let storedChart = getActiveChart() if (storedChart == null) { - console.log('No chart to update') return } - console.log('storedChart', storedChart) try { // check if the chart is a node chart or a reach chart // and refresh the data accordingly @@ -848,7 +861,9 @@ const updateCurrentChart = () => { }) // sort the chart data by the x-axis variable - storedChart.chart.data.datasets[0].data = sortChartByX(activePlt.value) + storedChart.chart.data.datasets[0].data = sortChartByX(storedChart.chart) + + storedChart.chart.update() } return { diff --git a/frontend/src/views/TimeSeriesCharts.vue b/frontend/src/views/TimeSeriesCharts.vue index 77bd6902..0025d294 100644 --- a/frontend/src/views/TimeSeriesCharts.vue +++ b/frontend/src/views/TimeSeriesCharts.vue @@ -95,6 +95,7 @@ const changePlot = (plt) => { // controls (e.g. quality) are changed later. activePlt.value = plt + router.push({ query: { ...router.currentRoute.value.query, variables: plt.abbreviation } }) //chartData.value.datasets[0].data = chartStore.sortChartByX(plt) // TODO: save this plt as the active plot so we can refresh the data in the chart.js class later. @@ -103,7 +104,6 @@ const changePlot = (plt) => { chartStore.updateCurrentChart() // chartStore.updateShowLine() - router.push({ query: { ...router.currentRoute.value.query, variables: plt.abbreviation } }) }