From e9c18573c7413a8049039d5c21ccb584e5adc4ba Mon Sep 17 00:00:00 2001 From: Bryon Lewis Date: Mon, 14 Apr 2025 15:15:02 -0400 Subject: [PATCH 1/8] initial globalTime config --- client/src/MapStore.ts | 37 +++++++++++++++++++ .../FeatureSelection/VectorFeatureChart.vue | 1 - .../TabularData/MapLayerTableGraph.vue | 10 ++++- client/src/types.ts | 2 + uvdat/core/rest/vector_feature_table_data.py | 13 +++++++ 5 files changed, 61 insertions(+), 2 deletions(-) diff --git a/client/src/MapStore.ts b/client/src/MapStore.ts index b1f4df4..3fe2f9b 100644 --- a/client/src/MapStore.ts +++ b/client/src/MapStore.ts @@ -17,6 +17,7 @@ import { VectorMapLayer, } from './types'; import UVdatApi from './api/UVDATApi'; +import { visibleNetCDFLayers } from './map/mapNetCDFLayer'; export const VECTOR_PMTILES_URL = '/public/vectortiles/us.pmtiles'; @@ -34,6 +35,8 @@ export default class MapStore { public static proModeButtonEnabled = ref(true); + public static globalTime = ref(new Date()); + public static displayConfiguration: Ref = ref( { default_displayed_layers: [], enabled_ui: ['Collections', 'Datasets', 'Metadata'], default_tab: 'Scenarios' }, ); @@ -353,4 +356,38 @@ export default class MapStore { } } }; + + // Graph Charts current Min/Max Values in unix_time + public static graphChartsMinMax = ref({ + min: 0, + max: 0, + }); + + public static updateChartsMinMax = (min: number, max: number) => { + MapStore.graphChartsMinMax.value.min = min; + MapStore.graphChartsMinMax.value.max = max; + }; + + // Computes in Unix Time + public static globalTimeRange = computed(() => { + let globalMin = Infinity; + let globalMax = -Infinity; + MapStore.visibleMapLayers.value.forEach((visibleMapLayer) => { + const [type, layerId] = visibleMapLayer.split('_'); + const foundLayer = MapStore.selectedMapLayers.value.find((layer) => layer.id === parseInt(layerId, 10) && layer.type === type); + if (type === 'netcdf' && foundLayer !== undefined) { + const netCDFLayer = visibleNetCDFLayers.value.find((item) => item.netCDFLayer === foundLayer.id); + if (netCDFLayer && netCDFLayer.sliding) { + const { min, max } = netCDFLayer.sliding; + globalMin = Math.min(globalMin, min); + globalMax = Math.max(globalMax, max); + } + } + }); + if (MapStore.mapLayerFeatureGraphsVisible.value && MapStore.mapLayerFeatureGraphs.value.length) { + globalMin = Math.min(globalMin, MapStore.graphChartsMinMax.value.min); + globalMax = Math.max(globalMax, MapStore.graphChartsMinMax.value.max); + } + return { min: globalMin, max: globalMax }; + }); } diff --git a/client/src/components/FeatureSelection/VectorFeatureChart.vue b/client/src/components/FeatureSelection/VectorFeatureChart.vue index e6a59d9..330cf97 100644 --- a/client/src/components/FeatureSelection/VectorFeatureChart.vue +++ b/client/src/components/FeatureSelection/VectorFeatureChart.vue @@ -66,7 +66,6 @@ export default defineComponent({ confidenceLevel.value, false, movingAverageValue.value, - ); if (data.graphs && Object.keys(data.graphs).length === 0) { noGraphData.value = true; diff --git a/client/src/components/TabularData/MapLayerTableGraph.vue b/client/src/components/TabularData/MapLayerTableGraph.vue index 80b0268..9f1b610 100644 --- a/client/src/components/TabularData/MapLayerTableGraph.vue +++ b/client/src/components/TabularData/MapLayerTableGraph.vue @@ -114,7 +114,15 @@ export default defineComponent({ movingAverageValue.value, ); graphData.value = data; - + let minGraph = Infinity; + let maxGraph = -Infinity; + Object.keys(data.graphs).forEach((key) => { + const index = parseInt(key, 10); + const [min, max] = data.graphs[index].xAxisRange; + minGraph = Math.min(minGraph, min); + maxGraph = Math.max(maxGraph, max); + }); + MapStore.updateChartsMinMax(minGraph, maxGraph); if (graphContainer.value) { const colorMapping = renderVectorFeatureGraph( data, diff --git a/client/src/types.ts b/client/src/types.ts index 11fdf7d..d4fd4aa 100644 --- a/client/src/types.ts +++ b/client/src/types.ts @@ -802,6 +802,8 @@ export interface FeatureGraphData { trendLine?:[number, number][]; confidenceIntervals?:[number, number, number][]; movingAverage?:[number, number][]; + xAxisRange:[number, number]; + yAxisRange:[number, number]; }> } diff --git a/uvdat/core/rest/vector_feature_table_data.py b/uvdat/core/rest/vector_feature_table_data.py index 1dd83ef..28723da 100644 --- a/uvdat/core/rest/vector_feature_table_data.py +++ b/uvdat/core/rest/vector_feature_table_data.py @@ -172,6 +172,8 @@ def get_graphs( table_data = {'tableName': tables.first().name, 'graphs': {}} all_x_vals = {} + all_x_list = [] # <<< Added + all_y_list = [] # <<< Added for table in tables: if y_axis not in table.columns or x_axis not in table.columns: @@ -205,6 +207,10 @@ def get_graphs( x_vals = sorted_x_vals y_vals = [np.mean(data[x]) for x in sorted_x_vals] + # Add x and y values to global list for min/max later + all_x_list.extend(x_vals) + all_y_list.extend(y_vals) + for x, y in zip(x_vals, y_vals): if x not in all_x_vals: all_x_vals[x] = [] @@ -251,6 +257,9 @@ def get_graphs( avg_y_vals = [np.mean(all_x_vals[x]) for x in sorted_x_vals] aggregate_result = {'indexer': 'all', 'vectorFeatureId': 'all'} + all_x_list.extend(sorted_x_vals) + all_y_list.extend(avg_y_vals) + if 'data' in data_types: aggregate_result['data'] = list(zip(sorted_x_vals, avg_y_vals)) @@ -280,6 +289,10 @@ def get_graphs( table_data['graphs'][-1] = aggregate_result + if all_x_list and all_y_list: + table_data['xAxisRange'] = [min(all_x_list), max(all_x_list)] + table_data['yAxisRange'] = [min(all_y_list), max(all_y_list)] + return table_data @action(detail=False, methods=['get'], url_path='feature-graph') From 715a0cb7f46d5d703c70161bbe72e79af7560eab Mon Sep 17 00:00:00 2001 From: Bryon Lewis Date: Tue, 15 Apr 2025 13:31:13 -0400 Subject: [PATCH 2/8] init globalTime Component --- client/src/MapStore.ts | 2 +- .../src/components/MapLegends/GlobalTime.vue | 75 +++++++++++++++++++ 2 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 client/src/components/MapLegends/GlobalTime.vue diff --git a/client/src/MapStore.ts b/client/src/MapStore.ts index 3fe2f9b..6c69931 100644 --- a/client/src/MapStore.ts +++ b/client/src/MapStore.ts @@ -35,7 +35,7 @@ export default class MapStore { public static proModeButtonEnabled = ref(true); - public static globalTime = ref(new Date()); + public static globalTime = ref(Math.floor(new Date().getTime() / 1000)); public static displayConfiguration: Ref = ref( { default_displayed_layers: [], enabled_ui: ['Collections', 'Datasets', 'Metadata'], default_tab: 'Scenarios' }, diff --git a/client/src/components/MapLegends/GlobalTime.vue b/client/src/components/MapLegends/GlobalTime.vue new file mode 100644 index 0000000..deb6ee3 --- /dev/null +++ b/client/src/components/MapLegends/GlobalTime.vue @@ -0,0 +1,75 @@ + + + From 7edf7fb5f886c75809e5aefa272e686e38dd6c80 Mon Sep 17 00:00:00 2001 From: Bryon Lewis Date: Wed, 16 Apr 2025 15:13:23 -0400 Subject: [PATCH 3/8] initial time config synching --- client/src/MapStore.ts | 37 ++++++++++-------- .../src/components/MapLegends/ControlsKey.vue | 39 ++++++++++++++++--- .../src/components/MapLegends/GlobalTime.vue | 33 ++++++++++------ client/src/components/NetCDFLayerConfig.vue | 9 +++-- .../TabularData/MapLayerTableGraph.vue | 5 ++- client/src/map/mapNetCDFLayer.ts | 17 ++++---- 6 files changed, 93 insertions(+), 47 deletions(-) diff --git a/client/src/MapStore.ts b/client/src/MapStore.ts index 6c69931..495841b 100644 --- a/client/src/MapStore.ts +++ b/client/src/MapStore.ts @@ -10,6 +10,7 @@ import { DisplayConfiguration, LayerCollection, NetCDFData, + NetCDFImageWorking, NetCDFLayer, RasterMapLayer, SearchableVectorData, @@ -17,7 +18,6 @@ import { VectorMapLayer, } from './types'; import UVdatApi from './api/UVDATApi'; -import { visibleNetCDFLayers } from './map/mapNetCDFLayer'; export const VECTOR_PMTILES_URL = '/public/vectortiles/us.pmtiles'; @@ -72,6 +72,10 @@ export default class MapStore { public static visibleMapLayers: Ref> = ref(new Set()); + // Net CDF Layers + + public static visibleNetCDFLayers: Ref = ref([]); + public static selectedVectorMapLayers: Ref = computed( () => MapStore.selectedMapLayers.value.filter((layer) => layer.type === 'vector'), ); @@ -361,33 +365,34 @@ export default class MapStore { public static graphChartsMinMax = ref({ min: 0, max: 0, + stepSize: 0, }); - public static updateChartsMinMax = (min: number, max: number) => { - MapStore.graphChartsMinMax.value.min = min; - MapStore.graphChartsMinMax.value.max = max; + public static timeLinked = ref(true); + + public static updateChartsMinMax = (min: number, max: number, stepSize: number) => { + MapStore.graphChartsMinMax.value = { min, max, stepSize }; }; // Computes in Unix Time - public static globalTimeRange = computed(() => { + public static globalTimeRange: Ref<{ min: number; max: number, stepSize: number }> = computed(() => { let globalMin = Infinity; let globalMax = -Infinity; - MapStore.visibleMapLayers.value.forEach((visibleMapLayer) => { - const [type, layerId] = visibleMapLayer.split('_'); - const foundLayer = MapStore.selectedMapLayers.value.find((layer) => layer.id === parseInt(layerId, 10) && layer.type === type); - if (type === 'netcdf' && foundLayer !== undefined) { - const netCDFLayer = visibleNetCDFLayers.value.find((item) => item.netCDFLayer === foundLayer.id); - if (netCDFLayer && netCDFLayer.sliding) { - const { min, max } = netCDFLayer.sliding; - globalMin = Math.min(globalMin, min); - globalMax = Math.max(globalMax, max); - } + let stepSize = Infinity; + MapStore.visibleNetCDFLayers.value.forEach((layer) => { + if (layer.sliding) { + const { min, max } = layer.sliding; + const stepsize = layer.images.length; + stepSize = Math.min(stepSize, (max - min) / stepsize); + globalMin = Math.min(globalMin, min); + globalMax = Math.max(globalMax, max); } }); if (MapStore.mapLayerFeatureGraphsVisible.value && MapStore.mapLayerFeatureGraphs.value.length) { globalMin = Math.min(globalMin, MapStore.graphChartsMinMax.value.min); globalMax = Math.max(globalMax, MapStore.graphChartsMinMax.value.max); + stepSize = Math.min(stepSize, MapStore.graphChartsMinMax.value.stepSize); } - return { min: globalMin, max: globalMax }; + return { min: globalMin, max: globalMax, stepSize }; }); } diff --git a/client/src/components/MapLegends/ControlsKey.vue b/client/src/components/MapLegends/ControlsKey.vue index 1b011c3..ac686d9 100644 --- a/client/src/components/MapLegends/ControlsKey.vue +++ b/client/src/components/MapLegends/ControlsKey.vue @@ -2,8 +2,10 @@