Skip to content

Commit

Permalink
Fixes to 3dGrid module (#430)
Browse files Browse the repository at this point in the history
  • Loading branch information
HansKallekleiv authored Oct 17, 2023
1 parent 7f4cf4f commit 380b79e
Show file tree
Hide file tree
Showing 5 changed files with 328 additions and 131 deletions.
6 changes: 2 additions & 4 deletions frontend/src/modules/Grid3D/loadModule.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,12 @@ import { view } from "./view";
const defaultState: state = {
gridName: "Simgrid",
parameterName: "PORO",
selectedWellUuids: [],
realizations: ["1"],
useStatistics: false,

};

const module = ModuleRegistry.initModule<state>("Grid3D", defaultState, {

});
const module = ModuleRegistry.initModule<state>("Grid3D", defaultState, {});

module.viewFC = view;
module.settingsFC = settings;
75 changes: 66 additions & 9 deletions frontend/src/modules/Grid3D/queryHooks.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { WellBoreHeader_api, WellBoreTrajectory_api } from "@api";
import { apiService } from "@framework/ApiService";
import { UseQueryResult, useQuery } from "@tanstack/react-query";

Expand All @@ -6,39 +7,71 @@ import { GridSurface_trans, transformGridSurface } from "./queryDataTransforms";
const STALE_TIME = 60 * 1000;
const CACHE_TIME = 60 * 1000;

export function useGridSurface(caseUuid: string | null, ensembleName: string | null, gridName: string | null, realization: string | null): UseQueryResult<GridSurface_trans> {
export function useGridSurface(
caseUuid: string | null,
ensembleName: string | null,
gridName: string | null,
realization: string | null
): UseQueryResult<GridSurface_trans> {
return useQuery({
queryKey: ["getGridSurface", caseUuid, ensembleName, gridName, realization],
queryFn: () => apiService.grid.gridSurface(caseUuid ?? "", ensembleName ?? "", gridName ?? "", realization ?? ""),
queryFn: () =>
apiService.grid.gridSurface(caseUuid ?? "", ensembleName ?? "", gridName ?? "", realization ?? ""),
select: transformGridSurface,
staleTime: STALE_TIME,
cacheTime: 0,
enabled: caseUuid && ensembleName && gridName && realization ? true : false,
});
}

export function useGridParameter(caseUuid: string | null, ensembleName: string | null, gridName: string | null, parameterName: string | null, realization: string | null, useStatistics: boolean): UseQueryResult<number[]> {
export function useGridParameter(
caseUuid: string | null,
ensembleName: string | null,
gridName: string | null,
parameterName: string | null,
realization: string | null,
useStatistics: boolean
): UseQueryResult<number[]> {
return useQuery({
queryKey: ["getGridParameter", caseUuid, ensembleName, gridName, parameterName, realization],
queryFn: () => apiService.grid.gridParameter(caseUuid ?? "", ensembleName ?? "", gridName ?? "", parameterName ?? "", realization ?? ""),
queryFn: () =>
apiService.grid.gridParameter(
caseUuid ?? "",
ensembleName ?? "",
gridName ?? "",
parameterName ?? "",
realization ?? ""
),
staleTime: STALE_TIME,
cacheTime: 0,
enabled: caseUuid && ensembleName && gridName && parameterName && realization && !useStatistics ? true : false,
});
}


export function useStatisticalGridParameter(caseUuid: string | null, ensembleName: string | null, gridName: string | null, parameterName: string | null, realizations: string[] | null, useStatistics: boolean): UseQueryResult<number[]> {
export function useStatisticalGridParameter(
caseUuid: string | null,
ensembleName: string | null,
gridName: string | null,
parameterName: string | null,
realizations: string[] | null,
useStatistics: boolean
): UseQueryResult<number[]> {
return useQuery({
queryKey: ["getStatisticalGridParameter", caseUuid, ensembleName, gridName, parameterName, realizations],
queryFn: () => apiService.grid.statisticalGridParameter(caseUuid ?? "", ensembleName ?? "", gridName ?? "", parameterName ?? "", realizations ?? []),
queryFn: () =>
apiService.grid.statisticalGridParameter(
caseUuid ?? "",
ensembleName ?? "",
gridName ?? "",
parameterName ?? "",
realizations ?? []
),
staleTime: STALE_TIME,
cacheTime: 0,
enabled: caseUuid && ensembleName && gridName && parameterName && realizations && useStatistics ? true : false,
});
}


export function useGridModelNames(caseUuid: string | null, ensembleName: string | null): UseQueryResult<string[]> {
return useQuery({
queryKey: ["getGridModelNames", caseUuid, ensembleName],
Expand All @@ -49,7 +82,11 @@ export function useGridModelNames(caseUuid: string | null, ensembleName: string
});
}

export function useGridParameterNames(caseUuid: string | null, ensembleName: string | null, gridName: string | null): UseQueryResult<string[]> {
export function useGridParameterNames(
caseUuid: string | null,
ensembleName: string | null,
gridName: string | null
): UseQueryResult<string[]> {
return useQuery({
queryKey: ["getParameterNames", caseUuid, ensembleName, gridName],
queryFn: () => apiService.grid.getParameterNames(caseUuid ?? "", ensembleName ?? "", gridName ?? ""),
Expand All @@ -58,3 +95,23 @@ export function useGridParameterNames(caseUuid: string | null, ensembleName: str
enabled: caseUuid && ensembleName && gridName ? true : false,
});
}

export function useGetWellHeaders(caseUuid: string | undefined): UseQueryResult<WellBoreHeader_api[]> {
return useQuery({
queryKey: ["getWellHeaders", caseUuid],
queryFn: () => apiService.well.getWellHeaders(caseUuid ?? ""),
staleTime: STALE_TIME,
cacheTime: STALE_TIME,
enabled: caseUuid ? true : false,
});
}

export function useGetFieldWellsTrajectories(caseUuid: string | undefined): UseQueryResult<WellBoreTrajectory_api[]> {
return useQuery({
queryKey: ["getFieldWellsTrajectories", caseUuid],
queryFn: () => apiService.well.getFieldWellTrajectories(caseUuid ?? ""),
staleTime: STALE_TIME,
cacheTime: CACHE_TIME,
enabled: caseUuid ? true : false,
});
}
180 changes: 127 additions & 53 deletions frontend/src/modules/Grid3D/settings.tsx
Original file line number Diff line number Diff line change
@@ -1,103 +1,177 @@
import React, { useEffect } from "react";

import { EnsembleIdent } from "@framework/EnsembleIdent";
import { ModuleFCProps } from "@framework/Module";
import { useFirstEnsembleInEnsembleSet } from "@framework/WorkbenchSession";
import { SyncSettingKey, SyncSettingsHelper } from "@framework/SyncSettings";
import { useEnsembleSet } from "@framework/WorkbenchSession";
import { fixupEnsembleIdent, maybeAssignFirstSyncedEnsemble } from "@framework/utils/ensembleUiHelpers";
import { ApiStateWrapper } from "@lib/components/ApiStateWrapper";
import { useGridModelNames, useGridParameterNames } from "./queryHooks";
import { CircularProgress } from "@lib/components/CircularProgress";
import { Button } from "@lib/components/Button";
import { Checkbox } from "@lib/components/Checkbox";
import { CircularProgress } from "@lib/components/CircularProgress";
import { CollapsibleGroup } from "@lib/components/CollapsibleGroup";
import { Label } from "@lib/components/Label";
import { Select, SelectOption } from "@lib/components/Select";

import { useGetWellHeaders, useGridModelNames, useGridParameterNames } from "./queryHooks";
import state from "./state";

//-----------------------------------------------------------------------------------------------------------
export function settings({ moduleContext, workbenchSession }: ModuleFCProps<state>) {
export function settings({ moduleContext, workbenchServices, workbenchSession }: ModuleFCProps<state>) {
// From Workbench
const firstEnsemble = useFirstEnsembleInEnsembleSet(workbenchSession);

const ensembleSet = useEnsembleSet(workbenchSession);
const [selectedEnsembleIdent, setSelectedEnsembleIdent] = React.useState<EnsembleIdent | null>(null);
// State
const [gridName, setGridName] = moduleContext.useStoreState("gridName");
const [parameterName, setParameterName] = moduleContext.useStoreState("parameterName");
const [realizations, setRealizations] = moduleContext.useStoreState("realizations");
const [useStatistics, setUseStatistics] = moduleContext.useStoreState("useStatistics");
const [selectedWellUuids, setSelectedWellUuids] = moduleContext.useStoreState("selectedWellUuids");
const syncedSettingKeys = moduleContext.useSyncedSettingKeys();
const syncHelper = new SyncSettingsHelper(syncedSettingKeys, workbenchServices);
const syncedValueEnsembles = syncHelper.useValue(SyncSettingKey.ENSEMBLE, "global.syncValue.ensembles");

const candidateEnsembleIdent = maybeAssignFirstSyncedEnsemble(selectedEnsembleIdent, syncedValueEnsembles);
const computedEnsembleIdent = fixupEnsembleIdent(candidateEnsembleIdent, ensembleSet);
if (computedEnsembleIdent && !computedEnsembleIdent.equals(selectedEnsembleIdent)) {
setSelectedEnsembleIdent(computedEnsembleIdent);
}

// Queries
const firstCaseUuid = firstEnsemble?.getCaseUuid() ?? null;
const firstEnsembleName = firstEnsemble?.getEnsembleName() ?? null;
const firstCaseUuid = computedEnsembleIdent?.getCaseUuid() ?? null;
const firstEnsembleName = computedEnsembleIdent?.getEnsembleName() ?? null;
const gridNamesQuery = useGridModelNames(firstCaseUuid, firstEnsembleName);
const parameterNamesQuery = useGridParameterNames(firstCaseUuid, firstEnsembleName, gridName);

const wellHeadersQuery = useGetWellHeaders(computedEnsembleIdent?.getCaseUuid());
// Handle Linked query
useEffect(() => {
if (parameterNamesQuery.data) {
if (gridName && parameterNamesQuery.data.find(name => name === parameterName)) {
if (gridName && parameterNamesQuery.data.find((name) => name === parameterName)) {
// New grid has same parameter
} else {
// New grid has different parameter. Set to first
setParameterName(parameterNamesQuery.data[0])
setParameterName(parameterNamesQuery.data[0]);
}
}
}, [parameterNamesQuery.data, parameterName])

// If no grid names, stop here
if (!gridNamesQuery.data) { return (<div>Select case: upscaled_grids_realistic_no_unc</div>) }
}, [parameterNamesQuery.data, parameterName]);

const parameterNames = parameterNamesQuery.data ? parameterNamesQuery.data : []
const allRealizations: string[] = firstEnsemble ? firstEnsemble.getRealizations().map(real => JSON.stringify(real)) : []
const parameterNames = parameterNamesQuery.data ? parameterNamesQuery.data : [];
const allRealizations = computedEnsembleIdent
? ensembleSet
.findEnsemble(computedEnsembleIdent)
?.getRealizations()
.map((real) => JSON.stringify(real)) ?? []
: [];

return (
<div>
<ApiStateWrapper
apiResult={gridNamesQuery}
errorComponent={"Error loading vector names"}
loadingComponent={<CircularProgress />}
>
<Label
text="Grid model"
>
<Select
options={stringToOptions(gridNamesQuery.data)}
value={[gridName || gridNamesQuery.data[0]]}
onChange={(gridnames) => setGridName(gridnames[0])}
filter={true}
size={5}
/>
</Label>
let wellHeaderOptions: SelectOption[] = [];

<Label
text="Grid parameter"
>
<Select
options={stringToOptions(parameterNames || [])}
value={[parameterName || parameterNames[0]]}
onChange={(pnames) => setParameterName(pnames[0])}
filter={true}
size={5}
if (wellHeadersQuery.data) {
wellHeaderOptions = wellHeadersQuery.data.map((header) => ({
label: header.unique_wellbore_identifier,
value: header.wellbore_uuid,
}));
}

/>
</Label>
function handleWellsChange(selectedWellUuids: string[], allWellUuidsOptions: SelectOption[]) {
const newSelectedWellUuids = selectedWellUuids.filter((wellUuid) =>
allWellUuidsOptions.some((wellHeader) => wellHeader.value === wellUuid)
);
setSelectedWellUuids(newSelectedWellUuids);
}
function showAllWells(allWellUuidsOptions: SelectOption[]) {
const newSelectedWellUuids = allWellUuidsOptions.map((wellHeader) => wellHeader.value);

<Label
text="Realizations"
>
setSelectedWellUuids(newSelectedWellUuids);
}
function hideAllWells() {
setSelectedWellUuids([]);
}
const gridNames: string[] = gridNamesQuery.data ? gridNamesQuery.data : [];
return (
<div>
<CollapsibleGroup expanded={false} title="Realization / ensemble statistics">
<Label text="Realizations">
<Select
options={stringToOptions(allRealizations as string[] || [])}
value={realizations ? realizations : [allRealizations[1]]}
options={stringToOptions(allRealizations || [])}
value={realizations ? (realizations as string[]) : [allRealizations[1]]}
onChange={(reals) => setRealizations(reals)}
filter={true}
size={5}
multiple={useStatistics}
/>
</Label>
<Checkbox label="Show mean parameter" checked={useStatistics} onChange={(event: React.ChangeEvent<HTMLInputElement>) => setUseStatistics(event.target.checked)} />
<Checkbox
label="Show mean parameter"
checked={useStatistics}
onChange={(event: React.ChangeEvent<HTMLInputElement>) => setUseStatistics(event.target.checked)}
/>
{"(Select multiple realizations)"}
</CollapsibleGroup>
<CollapsibleGroup expanded={true} title="Grid data">
<ApiStateWrapper
apiResult={gridNamesQuery}
errorComponent={"Error loading grid models"}
loadingComponent={<CircularProgress />}
>
<Label text="Grid model">
<Select
options={stringToOptions(gridNames)}
value={[gridName || gridNames[0]]}
onChange={(gridnames) => setGridName(gridnames[0])}
filter={true}
size={5}
/>
</Label>

</ApiStateWrapper>
<Label text="Grid parameter">
<Select
options={stringToOptions(parameterNames || [])}
value={[parameterName || parameterNames[0]]}
onChange={(pnames) => setParameterName(pnames[0])}
filter={true}
size={5}
/>
</Label>
</ApiStateWrapper>
</CollapsibleGroup>
<CollapsibleGroup expanded={true} title="Well data">
<ApiStateWrapper
apiResult={wellHeadersQuery}
errorComponent={"Error loading wells"}
loadingComponent={<CircularProgress />}
>
<Label text="Drilled Wells">
<>
<div>
<Button
className="float-left m-2 text-xs py-0"
variant="outlined"
onClick={() => showAllWells(wellHeaderOptions)}
>
Select all
</Button>
<Button className="m-2 text-xs py-0" variant="outlined" onClick={hideAllWells}>
Select none
</Button>
</div>
<Select
options={wellHeaderOptions}
value={selectedWellUuids}
onChange={(selectedWellUuids: string[]) =>
handleWellsChange(selectedWellUuids, wellHeaderOptions)
}
size={10}
multiple={true}
/>
</>
</Label>
</ApiStateWrapper>
</CollapsibleGroup>
</div>
);
}

const stringToOptions = (strings: string[]): SelectOption[] => {
return strings.map((string) => ({ label: string, value: string }));
}
};
8 changes: 7 additions & 1 deletion frontend/src/modules/Grid3D/state.ts
Original file line number Diff line number Diff line change
@@ -1 +1,7 @@
export default interface state { gridName: string | null, parameterName: string | null, realizations: string[] | null, useStatistics: boolean }
export default interface state {
gridName: string | null;
parameterName: string | null;
selectedWellUuids: string[];
realizations: string[] | null;
useStatistics: boolean;
}
Loading

0 comments on commit 380b79e

Please sign in to comment.