Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes to 3dGrid module #430

Merged
merged 2 commits into from
Oct 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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