Skip to content

Commit

Permalink
Refactored SimulationTimeSeries with Jotai atoms
Browse files Browse the repository at this point in the history
  • Loading branch information
rubenthoms committed Feb 15, 2024
1 parent 76dc727 commit e384041
Show file tree
Hide file tree
Showing 31 changed files with 3,216 additions and 630 deletions.
34 changes: 34 additions & 0 deletions frontend/src/modules/SimulationTimeSeries/atoms/baseAtoms.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { Frequency_api, StatisticFunction_api } from "@api";
import { atom } from "jotai";
import { isEqual } from "lodash";
import { FanchartStatisticOption, GroupBy, StatisticsSelection, VisualizationMode } from "../typesAndEnums";
import { EnsembleIdent } from "@framework/EnsembleIdent";
import { atomWithCompare } from "@framework/utils/atomUtils";
import { ParameterIdent } from "@framework/EnsembleParameters";

export const resampleFrequencyAtom = atom<Frequency_api | null>(Frequency_api.MONTHLY);

export const groupByAtom = atom<GroupBy>(GroupBy.TIME_SERIES);

export const colorRealizationsByParameterAtom = atom<boolean>(false);

export const visualizationModeAtom = atom<VisualizationMode>(VisualizationMode.STATISTICAL_FANCHART);

export const showHistoricalAtom = atom<boolean>(true);

export const showObservationsAtom = atom<boolean>(true);

export const statisticsSelectionAtom = atom<StatisticsSelection>({
IndividualStatisticsSelection: Object.values(StatisticFunction_api),
FanchartStatisticsSelection: Object.values(FanchartStatisticOption),
});

export const userSelectedEnsembleIdentsAtom = atomWithCompare<EnsembleIdent[]>([], isEqual);

export const selectedVectorNamesAtom = atomWithCompare<string[]>([], isEqual);

export const filteredParameterIdentListAtom = atom<ParameterIdent[]>([]);

export const userSelectedParameterIdentStringAtom = atom<string | null>(null);

export const userSelectedActiveTimestampUtcMsAtom = atom<number | null>(null);
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
import { EnsembleIdent } from "@framework/EnsembleIdent";
import { StatisticsType, VectorSpec, VisualizationMode } from "../typesAndEnums";
import { filteredParameterIdentListAtom, selectedVectorNamesAtom, userSelectedEnsembleIdentsAtom, userSelectedParameterIdentStringAtom, visualizationModeAtom } from "./baseAtoms";
import { EnsembleSetAtom } from "@framework/GlobalAtoms";
import { fixupEnsembleIdents } from "@framework/utils/ensembleUiHelpers";
import { Ensemble } from "@framework/Ensemble";

import { atom } from "jotai";

import { isEqual } from "lodash";
import { Parameter, ParameterIdent, ParameterType } from "@framework/EnsembleParameters";
import { vectorListQueriesAtom } from "./queryAtoms";
import { VectorDescription_api } from "@api";
import { createVectorSelectorDataFromVectors } from "@framework/components/VectorSelector";
import { EnsembleVectorListsHelper } from "../utils/ensemblesVectorListHelper";

export const statisticsTypeAtom = atom<StatisticsType>((get) => {
const visualizationMode = get(visualizationModeAtom);

if (visualizationMode === VisualizationMode.STATISTICAL_FANCHART) {
return StatisticsType.FANCHART;
}

return StatisticsType.INDIVIDUAL;
});


export const selectedEnsembleIdentsAtom = atom<EnsembleIdent[]>((get) => {
const ensembleSet = get(EnsembleSetAtom);
const selectedEnsembleIdents = get(userSelectedEnsembleIdentsAtom);

const newSelectedEnsembleIdents = selectedEnsembleIdents.filter((ensemble) => ensembleSet.hasEnsemble(ensemble));

const validatedEnsembleIdents = fixupEnsembleIdents(newSelectedEnsembleIdents, ensembleSet);

return validatedEnsembleIdents ?? [];
});

export const selectedEnsemblesAtom = atom((get) => {
const ensembleSet = get(EnsembleSetAtom);
const selectedEnsembleIdents = get(selectedEnsembleIdentsAtom);

const selectedEnsembles: Ensemble[] = [];

for (const ensembleIdent of selectedEnsembleIdents) {
const ensemble = ensembleSet.findEnsemble(ensembleIdent);
if (ensemble) {
selectedEnsembles.push(ensemble);
}
}

return selectedEnsembles;
});

export const continuousAndNonConstantParametersUnionAtom = atom<Parameter[]>((get) => {
const ensembleSet = get(EnsembleSetAtom);
const selectedEnsembleIdents = get(selectedEnsembleIdentsAtom);

const continuousAndNonConstantParametersUnion: Parameter[] = [];

for (const ensembleIdent of selectedEnsembleIdents) {
const ensemble = ensembleSet.findEnsemble(ensembleIdent);

if (!ensemble) {
continue;
}

const continuousAndNonConstantParameters = ensemble
.getParameters()
.getParameterArr()
.filter((parameter) => parameter.type === ParameterType.CONTINUOUS && !parameter.isConstant);

// Add non-duplicate parameters to list - verified by ParameterIdent
for (const parameter of continuousAndNonConstantParameters) {
const parameterIdent = ParameterIdent.fromNameAndGroup(parameter.name, parameter.groupName);
const isParameterInUnion = continuousAndNonConstantParametersUnion.some((elm) =>
parameterIdent.equals(ParameterIdent.fromNameAndGroup(elm.name, elm.groupName))
);

if (isParameterInUnion) continue;
continuousAndNonConstantParametersUnion.push(parameter);
}
}

return continuousAndNonConstantParametersUnion;
});


export const vectorListDataAtom = atom<(VectorDescription_api[] | null)[]>((get) => {
const vectorListQueries = get(vectorListQueriesAtom);
const oldVectorListData: (VectorDescription_api[] | null)[] = get(vectorListDataAtom);

const newVectorListData = vectorListQueries.map((query) => {
return query.data ?? null;
});

if (isEqual(newVectorListData, oldVectorListData)) {
return oldVectorListData;
}

return newVectorListData;
});

export const isVectorListQueriesFetchingAtom = atom<boolean>((get) => {
const vectorListQueries = get(vectorListQueriesAtom);

return vectorListQueries.some((query) => query.isFetching);
});

export const availableVectorNamesAtom = atom((get) => {
const ensembleVectorListsHelper = get(ensembleVectorListsHelperAtom);

const vectorNamesUnion = ensembleVectorListsHelper.vectorsUnion();

return vectorNamesUnion;
});

export const vectorSelectorDataAtom = atom((get) => {
const isFetching = get(isVectorListQueriesFetchingAtom);
const availableVectorNames = get(availableVectorNamesAtom);

if (isFetching) {
return [];
}

return createVectorSelectorDataFromVectors(availableVectorNames);
});

export const ensembleVectorListsHelperAtom = atom((get) => {
const vectorListQueries = get(vectorListQueriesAtom);
const selectedEnsembleIdents = get(selectedEnsembleIdentsAtom);

return new EnsembleVectorListsHelper(selectedEnsembleIdents, vectorListQueries);
});


export const vectorSpecificationsAtom = atom<VectorSpec[]>((get) => {
const ensembleVectorListsHelper = get(ensembleVectorListsHelperAtom);
const selectedEnsembleIdents = get(selectedEnsembleIdentsAtom);
const selectedVectorNames = get(selectedVectorNamesAtom);

const vectorSpecifications: VectorSpec[] = [];

for (const ensembleIdent of selectedEnsembleIdents) {
for (const vectorName of selectedVectorNames) {
if (!ensembleVectorListsHelper.isVectorInEnsemble(ensembleIdent, vectorName)) {
continue;
}

vectorSpecifications.push({
ensembleIdent,
vectorName,
hasHistoricalVector: ensembleVectorListsHelper.hasHistoricalVector(ensembleIdent, vectorName),
});
}
}

return vectorSpecifications;
});

export const selectedParameterIdentStringAtom = atom<string | null>((get) => {
const filteredParameterIdentList = get(filteredParameterIdentListAtom);
const userSelectedParameterIdentString = get(userSelectedParameterIdentStringAtom);

if (filteredParameterIdentList.length === 0) {
return null;
}

if (userSelectedParameterIdentString === null) {
return filteredParameterIdentList[0].toString();
}

if (filteredParameterIdentList.some((elm) => elm.toString() === userSelectedParameterIdentString)) {
return userSelectedParameterIdentString;
}

return filteredParameterIdentList[0].toString();
});

export const parameterIdentAtom = atom<ParameterIdent | null>((get) => {
const selectedParameterIdentString = get(selectedParameterIdentStringAtom);
const filteredParameterIdentList = get(filteredParameterIdentListAtom);

if (selectedParameterIdentString === null) {
return null;
}

try {
const newParameterIdent = ParameterIdent.fromString(selectedParameterIdentString);
const isParameterAmongFiltered = filteredParameterIdentList.some((parameter) =>
parameter.equals(newParameterIdent)
);
if (isParameterAmongFiltered) {
return newParameterIdent;
} else {
return null;
}
} catch {
return null;
}
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { atom } from "jotai";
import { historicalVectorDataQueriesAtom, vectorDataQueriesAtom, vectorObservationsQueriesAtom, vectorStatisticsQueriesAtom } from "./queryAtoms";
import { createLoadedVectorSpecificationAndDataArray } from "../utils/vectorSpecificationsAndQueriesUtils";
import { parameterIdentAtom, selectedEnsemblesAtom, vectorSpecificationsAtom } from "./derivedSettingsAtoms";
import { colorRealizationsByParameterAtom, userSelectedActiveTimestampUtcMsAtom, visualizationModeAtom } from "./baseAtoms";
import { VisualizationMode } from "../typesAndEnums";

export const queryIsFetchingAtom = atom((get) => {
const vectorDataQueries = get(vectorDataQueriesAtom);
const vectorStatisticsQueries = get(vectorStatisticsQueriesAtom);
const historicalVectorDataQueries = get(historicalVectorDataQueriesAtom);
const vectorObservationsQueries = get(vectorObservationsQueriesAtom);

const vectorDataIsFetching = vectorDataQueries.some((query) => query.isFetching);
const vectorStatisticsIsFetching = vectorStatisticsQueries.some((query) => query.isFetching);
const historicalVectorDataIsFetching = historicalVectorDataQueries.some((query) => query.isFetching);
const vectorObservationsIsFetching = vectorObservationsQueries.isFetching;

const isFetching = (
vectorDataIsFetching ||
vectorStatisticsIsFetching ||
historicalVectorDataIsFetching ||
vectorObservationsIsFetching
);

return isFetching;
});

export const realizationsQueryHasErrorAtom = atom((get) => {
const vectorDataQueries = get(vectorDataQueriesAtom);

return vectorDataQueries.some((query) => query.isError);
});

export const statisticsQueryHasErrorAtom = atom((get) => {
const vectorStatisticsQueries = get(vectorStatisticsQueriesAtom);

return vectorStatisticsQueries.some((query) => query.isError);
});

export const historicalDataQueryHasErrorAtom = atom((get) => {
const historicalVectorDataQueries = get(historicalVectorDataQueriesAtom);

return historicalVectorDataQueries.some((query) => query.isError);
});

export const loadedVectorSpecificationsAndRealizationDataAtom = atom((get) => {
const vectorDataQueries = get(vectorDataQueriesAtom);
const vectorSpecifications = get(vectorSpecificationsAtom);

return createLoadedVectorSpecificationAndDataArray(vectorSpecifications, vectorDataQueries);
});

export const loadedVectorSpecificationsAndStatisticsDataAtom = atom((get) => {
const vectorStatisticsQueries = get(vectorStatisticsQueriesAtom);
const vectorSpecifications = get(vectorSpecificationsAtom);

return createLoadedVectorSpecificationAndDataArray(vectorSpecifications, vectorStatisticsQueries);
});

export const loadedVectorSpecificationsAndHistoricalDataAtom = atom((get) => {
const historicalVectorDataQueries = get(historicalVectorDataQueriesAtom);
const vectorSpecifications = get(vectorSpecificationsAtom);

return createLoadedVectorSpecificationAndDataArray(vectorSpecifications, historicalVectorDataQueries);
});

export const activeTimestampUtcMsAtom = atom<number | null>((get) => {
const loadedVectorSpecificationsAndRealizationData = get(loadedVectorSpecificationsAndRealizationDataAtom);
const isQueryFetching = get(queryIsFetchingAtom);
const userSelectedActiveTimestampUtcMs = get(userSelectedActiveTimestampUtcMsAtom);

if (
!isQueryFetching &&
userSelectedActiveTimestampUtcMs === null &&
loadedVectorSpecificationsAndRealizationData.length > 0
) {
const firstTimeStamp =
loadedVectorSpecificationsAndRealizationData.at(0)?.data.at(0)?.timestamps_utc_ms[0] ?? null;
return firstTimeStamp;
}

return userSelectedActiveTimestampUtcMs;
});

export const colorByParameterAtom = atom<boolean>((get) => {
const colorRealizationsByParameter = get(colorRealizationsByParameterAtom);
const visualizationMode = get(visualizationModeAtom);
const parameterIdent = get(parameterIdentAtom);
const selectedEnsembles = get(selectedEnsemblesAtom);

return (
colorRealizationsByParameter &&
visualizationMode === VisualizationMode.INDIVIDUAL_REALIZATIONS &&
parameterIdent !== null &&
selectedEnsembles.some((ensemble) => ensemble.getParameters().hasParameter(parameterIdent))
);
});
Loading

0 comments on commit e384041

Please sign in to comment.