From 70fb156e573169df83e9880667fd109acfe7110d Mon Sep 17 00:00:00 2001 From: jorgenherje Date: Thu, 19 Dec 2024 15:25:03 +0100 Subject: [PATCH] Minor refactoring and fix bugs/issues with atoms Issues/bugs with atoms due to incorrect import/initialization in loadModule and registerModule --- .../primary/routers/timeseries/router.py | 6 ++ .../interfaces.ts | 2 +- .../loadModule.tsx | 5 +- .../queryHooks.tsx | 85 ------------------- .../registerModule.ts | 6 +- .../settings/atoms/baseAtoms.ts | 20 ++++- .../settings/atoms/derivedAtoms.ts | 39 ++++----- .../settings/settings.tsx | 11 ++- .../view/atoms/baseAtoms.ts | 2 +- .../view/atoms/derivedAtoms.ts | 18 +++- .../view/atoms/queryAtoms.ts | 4 +- .../hooks/useMakeViewStatusWriterMessages.ts | 34 ++++++++ ...seTimeSeriesChartTracesDataArrayBuilder.ts | 4 +- .../view/view.tsx | 5 ++ 14 files changed, 119 insertions(+), 122 deletions(-) delete mode 100644 frontend/src/modules/SimulationTimeSeriesSensitivity/queryHooks.tsx create mode 100644 frontend/src/modules/SimulationTimeSeriesSensitivity/view/hooks/useMakeViewStatusWriterMessages.ts diff --git a/backend_py/primary/primary/routers/timeseries/router.py b/backend_py/primary/primary/routers/timeseries/router.py index 2d58b8122..21604274e 100644 --- a/backend_py/primary/primary/routers/timeseries/router.py +++ b/backend_py/primary/primary/routers/timeseries/router.py @@ -234,6 +234,12 @@ async def get_statistical_vector_data_per_sensitivity( sens_case_realization_mask = pc.and_(requested_realizations_mask, sens_case_realization_mask) table = vector_table.filter(sens_case_realization_mask) + if table.num_rows == 0 and requested_realizations_mask is not None: + raise HTTPException( + status_code=404, + detail="The combination of realizations to include and sensitivity case realizations results in no valid realizations", + ) + statistics = compute_vector_statistics(table, vector_name, service_stat_funcs_to_compute) if not statistics: raise HTTPException(status_code=404, detail="Could not compute statistics") diff --git a/frontend/src/modules/SimulationTimeSeriesSensitivity/interfaces.ts b/frontend/src/modules/SimulationTimeSeriesSensitivity/interfaces.ts index dd7c6a7f2..82ed23abc 100644 --- a/frontend/src/modules/SimulationTimeSeriesSensitivity/interfaces.ts +++ b/frontend/src/modules/SimulationTimeSeriesSensitivity/interfaces.ts @@ -13,7 +13,7 @@ import { VectorSpec } from "./typesAndEnums"; export type SettingsToViewInterface = { vectorSpecification: VectorSpec | null; resamplingFrequency: Frequency_api | null; - selectedSensitivityNames: string[] | null; + selectedSensitivityNames: string[]; showStatistics: boolean; showRealizations: boolean; showHistorical: boolean; diff --git a/frontend/src/modules/SimulationTimeSeriesSensitivity/loadModule.tsx b/frontend/src/modules/SimulationTimeSeriesSensitivity/loadModule.tsx index a50fd2347..914eb2dd8 100644 --- a/frontend/src/modules/SimulationTimeSeriesSensitivity/loadModule.tsx +++ b/frontend/src/modules/SimulationTimeSeriesSensitivity/loadModule.tsx @@ -1,11 +1,14 @@ import { ModuleRegistry } from "@framework/ModuleRegistry"; import { Interfaces, settingsToViewInterfaceInitialization } from "./interfaces"; +import { MODULE_NAME } from "./registerModule"; import { Settings } from "./settings/settings"; +import { settingsToViewInterfaceEffects } from "./view/atoms/interfaceEffects"; import { View } from "./view/view"; -const module = ModuleRegistry.initModule("SimulationTimeSeriesSensitivity", { +const module = ModuleRegistry.initModule(MODULE_NAME, { settingsToViewInterfaceInitialization, + settingsToViewInterfaceEffects, }); module.viewFC = View; diff --git a/frontend/src/modules/SimulationTimeSeriesSensitivity/queryHooks.tsx b/frontend/src/modules/SimulationTimeSeriesSensitivity/queryHooks.tsx deleted file mode 100644 index 727c754bb..000000000 --- a/frontend/src/modules/SimulationTimeSeriesSensitivity/queryHooks.tsx +++ /dev/null @@ -1,85 +0,0 @@ -import { Frequency_api, VectorHistoricalData_api, VectorStatisticSensitivityData_api } from "@api"; -import { VectorRealizationData_api } from "@api"; -import { apiService } from "@framework/ApiService"; -import { encodeAsUintListStr } from "@lib/utils/queryStringUtils"; -import { UseQueryResult, useQuery } from "@tanstack/react-query"; - -const STALE_TIME = 60 * 1000; -const CACHE_TIME = 60 * 1000; - -export function useVectorDataQuery( - caseUuid: string | undefined, - ensembleName: string | undefined, - vectorName: string | undefined, - resampleFrequency: Frequency_api | null, - realizationsToInclude: number[] | null -): UseQueryResult> { - const allOrNonEmptyRealArr = realizationsToInclude === null || realizationsToInclude.length > 0 ? true : false; - const realizationsEncodedAsUintListStr = realizationsToInclude ? encodeAsUintListStr(realizationsToInclude) : null; - return useQuery({ - queryKey: [ - "getRealizationsVectorData", - caseUuid, - ensembleName, - vectorName, - resampleFrequency, - realizationsEncodedAsUintListStr, - ], - queryFn: () => - apiService.timeseries.getRealizationsVectorData( - caseUuid ?? "", - ensembleName ?? "", - vectorName ?? "", - resampleFrequency ?? undefined, - realizationsEncodedAsUintListStr - ), - staleTime: STALE_TIME, - gcTime: CACHE_TIME, - enabled: !!(caseUuid && ensembleName && vectorName && allOrNonEmptyRealArr), - }); -} - -export function useStatisticalVectorSensitivityDataQuery( - caseUuid: string | undefined, - ensembleName: string | undefined, - vectorName: string | undefined, - resampleFrequency: Frequency_api | null, - allowEnable: boolean -): UseQueryResult { - return useQuery({ - queryKey: ["getStatisticalVectorDataPerSensitivity", caseUuid, ensembleName, vectorName, resampleFrequency], - queryFn: () => - apiService.timeseries.getStatisticalVectorDataPerSensitivity( - caseUuid ?? "", - ensembleName ?? "", - vectorName ?? "", - resampleFrequency ?? Frequency_api.MONTHLY, - undefined - ), - staleTime: STALE_TIME, - gcTime: CACHE_TIME, - enabled: !!(allowEnable && caseUuid && ensembleName && vectorName && resampleFrequency), - }); -} - -export function useHistoricalVectorDataQuery( - caseUuid: string | undefined, - ensembleName: string | undefined, - vectorName: string | undefined, - resampleFrequency: Frequency_api | null, - allowEnable: boolean -): UseQueryResult { - return useQuery({ - queryKey: ["getHistoricalVectorData", caseUuid, ensembleName, vectorName, resampleFrequency], - queryFn: () => - apiService.timeseries.getHistoricalVectorData( - caseUuid ?? "", - ensembleName ?? "", - vectorName ?? "", - resampleFrequency ?? Frequency_api.MONTHLY - ), - staleTime: STALE_TIME, - gcTime: CACHE_TIME, - enabled: !!(allowEnable && caseUuid && ensembleName && vectorName && resampleFrequency), - }); -} diff --git a/frontend/src/modules/SimulationTimeSeriesSensitivity/registerModule.ts b/frontend/src/modules/SimulationTimeSeriesSensitivity/registerModule.ts index bc935c2d4..eed885cb4 100644 --- a/frontend/src/modules/SimulationTimeSeriesSensitivity/registerModule.ts +++ b/frontend/src/modules/SimulationTimeSeriesSensitivity/registerModule.ts @@ -2,14 +2,16 @@ import { ModuleCategory, ModuleDevState } from "@framework/Module"; import { ModuleDataTagId } from "@framework/ModuleDataTags"; import { ModuleRegistry } from "@framework/ModuleRegistry"; import { SyncSettingKey } from "@framework/SyncSettings"; -import { Interfaces } from "@modules/3DViewer/interfaces"; import { channelDefs } from "./channelDefs"; +import { Interfaces } from "./interfaces"; + +export const MODULE_NAME = "SimulationTimeSeriesSensitivity"; const description = "Plotting of simulation time series data for ensembles with design matrices."; ModuleRegistry.registerModule({ - moduleName: "SimulationTimeSeriesSensitivity", + moduleName: MODULE_NAME, defaultTitle: "Simulation time series per sensitivity", category: ModuleCategory.MAIN, devState: ModuleDevState.PROD, diff --git a/frontend/src/modules/SimulationTimeSeriesSensitivity/settings/atoms/baseAtoms.ts b/frontend/src/modules/SimulationTimeSeriesSensitivity/settings/atoms/baseAtoms.ts index b07af259d..173a8f976 100644 --- a/frontend/src/modules/SimulationTimeSeriesSensitivity/settings/atoms/baseAtoms.ts +++ b/frontend/src/modules/SimulationTimeSeriesSensitivity/settings/atoms/baseAtoms.ts @@ -5,6 +5,13 @@ import { atomWithCompare } from "@framework/utils/atomUtils"; import { atom } from "jotai"; import { isEqual } from "lodash"; +function areEnsembleIdentsEqual(a: EnsembleIdent | null, b: EnsembleIdent | null) { + if (a === null) { + return b === null; + } + return a.equals(b); +} + export const syncedEnsembleIdentsAtom = atom(null); export const syncedVectorNameAtom = atom(null); @@ -13,7 +20,14 @@ export const showStatisticsAtom = atom(true); export const showRealizationsAtom = atom(false); export const showHistoricalAtom = atom(true); -export const userSelectedEnsembleIdentAtom = atom(null); -export const userSelectedVectorNameAtom = atom(null); -export const userSelectedVectorTagAtom = atom(null); +export const userSelectedEnsembleIdentAtom = atomWithCompare(null, areEnsembleIdentsEqual); +export const userSelectedVectorNameAndTagAtom = atomWithCompare<{ name: string | null; tag: string | null }>( + { + name: null, + tag: null, + }, + isEqual +); + +// Note: Default value of null, to detect uninitialized state, and select all sensitivities on first render export const userSelectedSensitivityNamesAtom = atomWithCompare(null, isEqual); diff --git a/frontend/src/modules/SimulationTimeSeriesSensitivity/settings/atoms/derivedAtoms.ts b/frontend/src/modules/SimulationTimeSeriesSensitivity/settings/atoms/derivedAtoms.ts index 2c66e46bb..15099452f 100644 --- a/frontend/src/modules/SimulationTimeSeriesSensitivity/settings/atoms/derivedAtoms.ts +++ b/frontend/src/modules/SimulationTimeSeriesSensitivity/settings/atoms/derivedAtoms.ts @@ -11,8 +11,7 @@ import { syncedVectorNameAtom, userSelectedEnsembleIdentAtom, userSelectedSensitivityNamesAtom, - userSelectedVectorNameAtom, - userSelectedVectorTagAtom, + userSelectedVectorNameAndTagAtom, } from "./baseAtoms"; import { vectorListQueryAtom } from "./queryAtoms"; @@ -35,27 +34,29 @@ export const availableSensitivityNamesAtom = atom((get) => { const ensemble = selectedEnsembleIdent ? ensembleSet.findEnsemble(selectedEnsembleIdent) : null; const ensembleSensitivityNames = ensemble?.getSensitivities()?.getSensitivityNames() ?? []; - return ensembleSensitivityNames; + return [...ensembleSensitivityNames]; }); export const selectedSensitivityNamesAtom = atom((get) => { const userSelectedSensitivityNames = get(userSelectedSensitivityNamesAtom); const availableSensitivityNames = get(availableSensitivityNamesAtom); - // If userSelectedSensitivityNames is empty, do not override it - if (!userSelectedSensitivityNames || userSelectedSensitivityNames.length === 0) { + // If userSelectedSensitivityNames is empty, do not override it (i.e. deselect all) + if (userSelectedSensitivityNames && userSelectedSensitivityNames.length === 0) { return []; } // Fixup invalid sensitivity names - // - If no valid sensitivity names are selected, the change can be due to new available sensitivity names + // - If user selected sensitivity names is null, the module is considered uninitialized + // - If user selected sensitivity names fixup results in empty array, it is due to new available sensitivity + // names, and all are selected. const fixedUpSensitivityNames = - userSelectedSensitivityNames?.filter((sens) => availableSensitivityNames.includes(sens)) ?? []; - if (fixedUpSensitivityNames.length === 0) { - return availableSensitivityNames; + userSelectedSensitivityNames?.filter((sens) => availableSensitivityNames.includes(sens)) ?? null; + if (!fixedUpSensitivityNames || fixedUpSensitivityNames.length === 0) { + return [...availableSensitivityNames]; } - return fixedUpSensitivityNames; + return [...fixedUpSensitivityNames]; }); export const availableVectorNamesAtom = atom((get) => { @@ -77,10 +78,9 @@ export const vectorSelectorDataAtom = atom((get) => { /** * Atom that handles vector name and tag in synch with fixup */ -const fixedUpVectorNameAndTagAtom = atom<{ name: string | null; tag: string | null }>((get) => { +const selectedVectorNameAndTagAtom = atom<{ name: string | null; tag: string | null }>((get) => { const syncedVectorName = get(syncedVectorNameAtom); - const userSelectedVectorName = get(userSelectedVectorNameAtom); - const userSelectedVectorTag = get(userSelectedVectorTagAtom); + const userSelectedVectorNameAndTag = get(userSelectedVectorNameAndTagAtom); const availableVectorNames = get(availableVectorNamesAtom); // Override with synced vector name if available @@ -89,22 +89,23 @@ const fixedUpVectorNameAndTagAtom = atom<{ name: string | null; tag: string | nu } // If vector name is fixed up, adjust tag as well + const userSelectedVectorName = userSelectedVectorNameAndTag.name; const fixedUpVectorName = fixupVectorName(userSelectedVectorName, availableVectorNames); if (fixedUpVectorName !== userSelectedVectorName) { return { name: fixedUpVectorName, tag: fixedUpVectorName }; } - return { name: userSelectedVectorName, tag: userSelectedVectorTag }; + return { name: userSelectedVectorName, tag: userSelectedVectorNameAndTag.tag }; }); -export const selectedVectorNameAtom = atom((get) => { - const fixedUpVectorName = get(fixedUpVectorNameAndTagAtom).name; - return fixedUpVectorName; +const selectedVectorNameAtom = atom((get) => { + const userSelectedVectorNameAndTag = get(selectedVectorNameAndTagAtom); + return userSelectedVectorNameAndTag.name; }); export const selectedVectorTagAtom = atom((get) => { - const fixedUpVectorTag = get(fixedUpVectorNameAndTagAtom).tag; - return fixedUpVectorTag; + const userSelectedVectorNameAndTag = get(selectedVectorNameAndTagAtom); + return userSelectedVectorNameAndTag.tag; }); export const selectedVectorNameHasHistoricalAtom = atom((get) => { diff --git a/frontend/src/modules/SimulationTimeSeriesSensitivity/settings/settings.tsx b/frontend/src/modules/SimulationTimeSeriesSensitivity/settings/settings.tsx index 0a80d1583..3422b5966 100644 --- a/frontend/src/modules/SimulationTimeSeriesSensitivity/settings/settings.tsx +++ b/frontend/src/modules/SimulationTimeSeriesSensitivity/settings/settings.tsx @@ -28,8 +28,7 @@ import { syncedVectorNameAtom, userSelectedEnsembleIdentAtom, userSelectedSensitivityNamesAtom, - userSelectedVectorNameAtom, - userSelectedVectorTagAtom, + userSelectedVectorNameAndTagAtom, } from "./atoms/baseAtoms"; import { availableSensitivityNamesAtom, @@ -51,8 +50,7 @@ export function Settings({ settingsContext, workbenchSession, workbenchServices const setSyncedEnsembleIdents = useSetAtom(syncedEnsembleIdentsAtom); const setSyncedVectorName = useSetAtom(syncedVectorNameAtom); const setUserSelectedEnsembleIdent = useSetAtom(userSelectedEnsembleIdentAtom); - const setUserSelectedVectorName = useSetAtom(userSelectedVectorNameAtom); - const setUserSelectedVectorTag = useSetAtom(userSelectedVectorTagAtom); + const setUserSelectedVectorNameAndTag = useSetAtom(userSelectedVectorNameAndTagAtom); const setUserSelectedSensitivityNamesAtom = useSetAtom(userSelectedSensitivityNamesAtom); const selectedEnsembleIdent = useAtomValue(selectedEnsembleIdentAtom); const vectorsListQuery = useAtomValue(vectorListQueryAtom); @@ -101,8 +99,9 @@ export function Settings({ settingsContext, workbenchSession, workbenchServices setResamplingFrequency(newFreq); } function handleVectorSelectChange(selection: SmartNodeSelectorSelection) { - setUserSelectedVectorName(selection.selectedNodes[0] ?? null); - setUserSelectedVectorTag(selection.selectedTags[0]?.text ?? null); + const userSelectedVectorName = selection.selectedNodes[0] ?? null; + const userSelectedVectorTag = selection.selectedTags[0]?.text ?? null; + setUserSelectedVectorNameAndTag({ name: userSelectedVectorName, tag: userSelectedVectorTag }); } function handleShowHistorical(event: React.ChangeEvent) { setShowHistorical(event.target.checked); diff --git a/frontend/src/modules/SimulationTimeSeriesSensitivity/view/atoms/baseAtoms.ts b/frontend/src/modules/SimulationTimeSeriesSensitivity/view/atoms/baseAtoms.ts index 663ad22e4..3d1bfcf7f 100644 --- a/frontend/src/modules/SimulationTimeSeriesSensitivity/view/atoms/baseAtoms.ts +++ b/frontend/src/modules/SimulationTimeSeriesSensitivity/view/atoms/baseAtoms.ts @@ -5,7 +5,7 @@ import { atom } from "jotai"; export const vectorSpecificationAtom = atom(null); export const resamplingFrequencyAtom = atom(Frequency_api.MONTHLY); -export const selectedSensitivityNamesAtom = atom(null); +export const selectedSensitivityNamesAtom = atom([]); export const showStatisticsAtom = atom(true); export const showRealizationsAtom = atom(false); export const showHistoricalAtom = atom(true); diff --git a/frontend/src/modules/SimulationTimeSeriesSensitivity/view/atoms/derivedAtoms.ts b/frontend/src/modules/SimulationTimeSeriesSensitivity/view/atoms/derivedAtoms.ts index 6223d9801..50432b10c 100644 --- a/frontend/src/modules/SimulationTimeSeriesSensitivity/view/atoms/derivedAtoms.ts +++ b/frontend/src/modules/SimulationTimeSeriesSensitivity/view/atoms/derivedAtoms.ts @@ -1,7 +1,11 @@ import { atom } from "jotai"; import { userSelectedActiveTimestampUtcMsAtom } from "./baseAtoms"; -import { statisticalVectorSensitivityDataQueryAtom } from "./queryAtoms"; +import { + historicalVectorDataQueryAtom, + statisticalVectorSensitivityDataQueryAtom, + vectorDataQueryAtom, +} from "./queryAtoms"; export const activeTimestampUtcMsAtom = atom((get) => { const userSelectedActiveTimestampUtcMs = get(userSelectedActiveTimestampUtcMsAtom); @@ -15,3 +19,15 @@ export const activeTimestampUtcMsAtom = atom((get) => { } return userSelectedActiveTimestampUtcMs; }); + +export const queryIsFetchingAtom = atom((get) => { + const vectorDataQuery = get(vectorDataQueryAtom); + const statisticalVectorSensitivityDataQuery = get(statisticalVectorSensitivityDataQueryAtom); + const historicalVectorDataQuery = get(historicalVectorDataQueryAtom); + + return ( + vectorDataQuery.isFetching || + statisticalVectorSensitivityDataQuery.isFetching || + historicalVectorDataQuery.isFetching + ); +}); diff --git a/frontend/src/modules/SimulationTimeSeriesSensitivity/view/atoms/queryAtoms.ts b/frontend/src/modules/SimulationTimeSeriesSensitivity/view/atoms/queryAtoms.ts index 5d9b790a5..718e2bf7a 100644 --- a/frontend/src/modules/SimulationTimeSeriesSensitivity/view/atoms/queryAtoms.ts +++ b/frontend/src/modules/SimulationTimeSeriesSensitivity/view/atoms/queryAtoms.ts @@ -4,6 +4,7 @@ import { ValidEnsembleRealizationsFunctionAtom } from "@framework/GlobalAtoms"; import { encodeAsUintListStr } from "@lib/utils/queryStringUtils"; import { resamplingFrequencyAtom, + showHistoricalAtom, showStatisticsAtom, vectorSpecificationAtom, } from "@modules/SimulationTimeSeriesSensitivity/view/atoms/baseAtoms"; @@ -90,6 +91,7 @@ export const statisticalVectorSensitivityDataQueryAtom = atomWithQuery((get) => export const historicalVectorDataQueryAtom = atomWithQuery((get) => { const vectorSpecification = get(vectorSpecificationAtom); + const showHistorical = get(showHistoricalAtom); const resampleFrequency = get(resamplingFrequencyAtom); const query = { @@ -109,7 +111,7 @@ export const historicalVectorDataQueryAtom = atomWithQuery((get) => { ), staleTime: STALE_TIME, gcTime: CACHE_TIME, - enabled: !!vectorSpecification, + enabled: !!(vectorSpecification && showHistorical), }; return query; diff --git a/frontend/src/modules/SimulationTimeSeriesSensitivity/view/hooks/useMakeViewStatusWriterMessages.ts b/frontend/src/modules/SimulationTimeSeriesSensitivity/view/hooks/useMakeViewStatusWriterMessages.ts new file mode 100644 index 000000000..32d4ac098 --- /dev/null +++ b/frontend/src/modules/SimulationTimeSeriesSensitivity/view/hooks/useMakeViewStatusWriterMessages.ts @@ -0,0 +1,34 @@ +import { ViewStatusWriter } from "@framework/StatusWriter"; + +import { useAtomValue } from "jotai"; + +import { showHistoricalAtom, showStatisticsAtom } from "../atoms/baseAtoms"; +import { + historicalVectorDataQueryAtom, + statisticalVectorSensitivityDataQueryAtom, + vectorDataQueryAtom, +} from "../atoms/queryAtoms"; + +export function useMakeViewStatusWriterMessages(statusWriter: ViewStatusWriter) { + const vectorDataQuery = useAtomValue(vectorDataQueryAtom); + const statisticalVectorSensitivityDataQuery = useAtomValue(statisticalVectorSensitivityDataQueryAtom); + const historicalVectorDataQuery = useAtomValue(historicalVectorDataQueryAtom); + const showStatistics = useAtomValue(showStatisticsAtom); + const showHistorical = useAtomValue(showHistoricalAtom); + + const isAnyQueryFetching = + vectorDataQuery.isFetching || + statisticalVectorSensitivityDataQuery.isFetching || + historicalVectorDataQuery.isFetching; + statusWriter.setLoading(isAnyQueryFetching); + + if (vectorDataQuery.isError) { + statusWriter.addError("Realization data query has error state."); + } + if (showStatistics && statisticalVectorSensitivityDataQuery.isError) { + statusWriter.addError("Statistics data per sensitivity query has error state."); + } + if (showHistorical && historicalVectorDataQuery.isError) { + statusWriter.addWarning("Historical data query has error state."); + } +} diff --git a/frontend/src/modules/SimulationTimeSeriesSensitivity/view/hooks/useTimeSeriesChartTracesDataArrayBuilder.ts b/frontend/src/modules/SimulationTimeSeriesSensitivity/view/hooks/useTimeSeriesChartTracesDataArrayBuilder.ts index 21edd4445..311658f27 100644 --- a/frontend/src/modules/SimulationTimeSeriesSensitivity/view/hooks/useTimeSeriesChartTracesDataArrayBuilder.ts +++ b/frontend/src/modules/SimulationTimeSeriesSensitivity/view/hooks/useTimeSeriesChartTracesDataArrayBuilder.ts @@ -44,11 +44,11 @@ export function useTimeSeriesChartTracesDataArrayBuilder(colorSet: ColorSet): Ti } const allSensitivityNamesInEnsemble = ensemble.getSensitivities()?.getSensitivityNames().sort() ?? []; - if (!ensemble || !selectedSensitivityNames || selectedSensitivityNames.length === 0) { + if (!ensemble || selectedSensitivityNames.length === 0) { return traceDataArr; } - if (ensemble && selectedSensitivityNames && selectedSensitivityNames.length > 0) { + if (ensemble && selectedSensitivityNames.length > 0) { const sensitivitiesColorMap = createSensitivityColorMap(allSensitivityNamesInEnsemble, colorSet); selectedSensitivityNames.forEach((sensitivityName) => { const color = sensitivitiesColorMap[sensitivityName]; diff --git a/frontend/src/modules/SimulationTimeSeriesSensitivity/view/view.tsx b/frontend/src/modules/SimulationTimeSeriesSensitivity/view/view.tsx index 814106637..2b90d1f25 100644 --- a/frontend/src/modules/SimulationTimeSeriesSensitivity/view/view.tsx +++ b/frontend/src/modules/SimulationTimeSeriesSensitivity/view/view.tsx @@ -1,6 +1,7 @@ import React from "react"; import { ModuleViewProps } from "@framework/Module"; +import { useViewStatusWriter } from "@framework/StatusWriter"; import { useSubscribedValue } from "@framework/WorkbenchServices"; import { useElementSize } from "@lib/hooks/useElementSize"; @@ -9,6 +10,7 @@ import { useAtomValue, useSetAtom } from "jotai"; import { userSelectedActiveTimestampUtcMsAtom, vectorSpecificationAtom } from "./atoms/baseAtoms"; import { activeTimestampUtcMsAtom } from "./atoms/derivedAtoms"; import { TimeSeriesChart, TimeSeriesChartHoverInfo } from "./components/timeSeriesChart"; +import { useMakeViewStatusWriterMessages } from "./hooks/useMakeViewStatusWriterMessages"; import { usePublishToDataChannels } from "./hooks/usePublishToDataChannels"; import { useTimeSeriesChartTracesDataArrayBuilder } from "./hooks/useTimeSeriesChartTracesDataArrayBuilder"; @@ -18,12 +20,15 @@ export const View = ({ viewContext, workbenchSettings, workbenchServices }: Modu const wrapperDivRef = React.useRef(null); const wrapperDivSize = useElementSize(wrapperDivRef); + const statusWriter = useViewStatusWriter(viewContext); + const setUserSelectedTimestampUtcMs = useSetAtom(userSelectedActiveTimestampUtcMsAtom); const activeTimestampUtcMs = useAtomValue(activeTimestampUtcMsAtom); const vectorSpecification = useAtomValue(vectorSpecificationAtom); const subscribedHoverTimestampUtcMs = useSubscribedValue("global.hoverTimestamp", workbenchServices); + useMakeViewStatusWriterMessages(statusWriter); usePublishToDataChannels(viewContext); const colorSet = workbenchSettings.useColorSet();