diff --git a/client/src/MapStore.ts b/client/src/MapStore.ts index b1f4df4..90de437 100644 --- a/client/src/MapStore.ts +++ b/client/src/MapStore.ts @@ -10,6 +10,7 @@ import { DisplayConfiguration, LayerCollection, NetCDFData, + NetCDFImageWorking, NetCDFLayer, RasterMapLayer, SearchableVectorData, @@ -34,6 +35,8 @@ export default class MapStore { public static proModeButtonEnabled = ref(true); + 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' }, ); @@ -69,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'), ); @@ -171,6 +178,27 @@ export default class MapStore { public static mapLayerFeatureGraphsVisible = ref(false); + public static vectorFeatureTableGraphVisible = ref(false); + + public static vectorFeatureTableData: Ref<{ layerId: number, vectorFeatureId: number, defaultGraphs?: string[] } | null> = ref(null); + + public static setVectorFeatureTableData = (layerId: number, vectorFeatureId: number, defaultGraphs?: string[]) => { + if (MapStore.mapLayerFeatureGraphsVisible.value) { + MapStore.mapLayerFeatureGraphsVisible.value = false; + } + MapStore.vectorFeatureTableData.value = { + layerId, + vectorFeatureId, + defaultGraphs, + }; + MapStore.vectorFeatureTableGraphVisible.value = true; + }; + + public static clearVectorFeatureTableData = () => { + MapStore.vectorFeatureTableData.value = null; + MapStore.vectorFeatureTableGraphVisible.value = false; + }; + // Graph color mapping implementation public static enabledMapLayerFeatureColorMapping = ref(false); @@ -353,4 +381,39 @@ export default class MapStore { } } }; + + // Graph Charts current Min/Max Values in unix_time + public static graphChartsMinMax = ref({ + min: 0, + max: 0, + stepSize: 0, + }); + + 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: Ref<{ min: number; max: number, stepSize: number }> = computed(() => { + let globalMin = Infinity; + let globalMax = -Infinity; + 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) || MapStore.vectorFeatureTableGraphVisible.value) { + 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, stepSize }; + }); } diff --git a/client/src/api/UVDATApi.ts b/client/src/api/UVDATApi.ts index 58143b7..7825bb7 100644 --- a/client/src/api/UVDATApi.ts +++ b/client/src/api/UVDATApi.ts @@ -11,6 +11,8 @@ import { DerivedRegion, DisplayConfiguration, FeatureGraphData, + FeatureGraphs, + FeatureGraphsRequest, FileItem, LayerCollection, LayerCollectionLayer, @@ -538,6 +540,44 @@ export default class UVdatApi { return response.data; } + public static async getFeatureGraphsData( + payload: FeatureGraphsRequest, + ): Promise { + const { + tableTypes, + vectorFeatureId, + xAxes = ['index'], + yAxes = ['mean_va'], + indexers = [], + display = ['data', 'trendLine'], + confidenceLevel = 95, + aggregate = false, + movingAverage, + } = payload; + + const params = new URLSearchParams(); + + tableTypes.forEach((type) => params.append('tableType', type)); + xAxes.forEach((x) => params.append('xAxis', x)); + yAxes.forEach((y) => params.append('yAxis', y)); + indexers.forEach((indexer) => params.append('indexer', indexer)); + display.forEach((d) => params.append('display', d)); + + params.append('vectorFeatureId', vectorFeatureId.toString()); + params.append('confidenceLevel', confidenceLevel.toString()); + params.append('aggregate', aggregate.toString()); + if (movingAverage !== undefined) { + params.append('movingAverage', movingAverage.toString()); + } + + const response = await UVdatApi.apiClient.get( + '/vectorfeature/tabledata/feature-graphs/', + { params }, + ); + + return response.data; + } + public static async getMapLayerFeatureGraphData( tableType: string, mapLayerId: number, diff --git a/client/src/components/FeatureSelection/VectorFeatureChart.vue b/client/src/components/FeatureSelection/VectorFeatureChart.vue index e6a59d9..453219f 100644 --- a/client/src/components/FeatureSelection/VectorFeatureChart.vue +++ b/client/src/components/FeatureSelection/VectorFeatureChart.vue @@ -6,6 +6,7 @@ import { throttle } from 'lodash'; import UVdatApi from '../../api/UVDATApi'; import { FeatureGraphData, VectorFeatureTableGraph } from '../../types'; import { renderVectorFeatureGraph } from './vectorFeatureGraphUtils'; +import MapStore from '../../MapStore'; export default defineComponent({ name: 'FeatureGraph', @@ -66,7 +67,6 @@ export default defineComponent({ confidenceLevel.value, false, movingAverageValue.value, - ); if (data.graphs && Object.keys(data.graphs).length === 0) { noGraphData.value = true; @@ -157,6 +157,10 @@ export default defineComponent({ movingAverageValue, ], throttledUpateDialogGraph); + const openBottomGraph = () => { + MapStore.setVectorFeatureTableData(props.mapLayerId, props.vectorFeatureId, [props.graphInfo.name]); + }; + return { graphContainer, graphDialogContainer, @@ -171,6 +175,7 @@ export default defineComponent({ movingAverageEnabled, movingAverageValue, maxMovingAverage, + openBottomGraph, }; }, }); @@ -184,7 +189,7 @@ export default defineComponent({
- + View Larger Graph
diff --git a/client/src/components/FeatureSelection/vectorFeatureGraphUtils.ts b/client/src/components/FeatureSelection/vectorFeatureGraphUtils.ts index 4194b20..71c9cad 100644 --- a/client/src/components/FeatureSelection/vectorFeatureGraphUtils.ts +++ b/client/src/components/FeatureSelection/vectorFeatureGraphUtils.ts @@ -7,7 +7,7 @@ const renderVectorFeatureGraph = ( container: SVGSVGElement, options?: { specificGraphKey?: number; - colors?: Record; + colors?: Record; xAxisLabel?: string; yAxisLabel?: string; showXYValuesOnHover?: boolean; @@ -21,10 +21,11 @@ const renderVectorFeatureGraph = ( showTrendline?: boolean; showMovingAverage?: boolean; showConfidenceInterval?: boolean; + useKeyTooltip?: boolean; }, baseHeight = 400, ) => { - const outputColorMapping: Record = {}; + const outputColorMapping: Record = {}; const localContainer = container; if (!localContainer || !data) return outputColorMapping; @@ -94,7 +95,12 @@ const renderVectorFeatureGraph = ( const g = svg.append('g').attr('transform', `translate(${margin.left},${margin.top})`); const colorScale = d3.scaleOrdinal(d3.schemeCategory10); - const graphKeys = Object.keys(graphsToRender).map(Number); + const graphKeys = Object.keys(graphsToRender).map((item) => { + if (!Number.isNaN(parseInt(item, 10))) { + return parseInt(item, 10); + } + return item; + }); const tooltipGroup = g.append('g') .attr('opacity', 0) .attr('pointer-events', 'none'); @@ -148,7 +154,7 @@ const renderVectorFeatureGraph = ( .on('mousemove', (event) => { const [mouseX, mouseY] = d3.pointer(event); - const tooltipTextContent = graph.indexer.toString(); + const tooltipTextContent = options?.useKeyTooltip ? key.toString() : graph.indexer.toString(); tooltipText.text(tooltipTextContent) .call((text) => { // Adjust the background size based on text width diff --git a/client/src/components/MapLegends/ControlsKey.vue b/client/src/components/MapLegends/ControlsKey.vue index 1b011c3..d15b2bc 100644 --- a/client/src/components/MapLegends/ControlsKey.vue +++ b/client/src/components/MapLegends/ControlsKey.vue @@ -2,8 +2,10 @@