Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
rubenthoms committed May 24, 2024
1 parent 09fc406 commit d5b4cdd
Show file tree
Hide file tree
Showing 16 changed files with 833 additions and 712 deletions.
1 change: 1 addition & 0 deletions frontend/src/api/models/SurfaceAttributeType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@ export enum SurfaceAttributeType {
THICKNESS = 'thickness',
ISOCHORE = 'isochore',
FLUID_CONTACT = 'fluid_contact',
VOLUMES = 'volumes',
}
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,11 @@ export const ColorPaletteSelector: React.FC<ColorPaletteSelectorProps> = (props)
));
}

const marginTop = Math.max(-boundingRect.top, convertRemToPixels((-(props.colorPalettes.length - 1) * 3) / 2));
const height = convertRemToPixels(props.colorPalettes.length * 3);
let marginTop = Math.max(-boundingRect.top, convertRemToPixels((-(props.colorPalettes.length - 1) * 3) / 2));
if (boundingRect.top - marginTop + height > window.innerHeight) {
marginTop = -(boundingRect.top + height - window.innerHeight + 8);
}

return (
<div className="bg-slate-100 rounded p-2 flex items-center gap-4" ref={ref}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { BaseLayer } from "@modules/Intersection/utils/layers/BaseLayer";
import { GridLayer } from "@modules/Intersection/utils/layers/GridLayer";
import { SeismicLayer } from "@modules/Intersection/utils/layers/SeismicLayer";
import { SurfaceLayer } from "@modules/Intersection/utils/layers/SurfaceLayer";
import { WellpicksLayer } from "@modules/Intersection/utils/layers/WellpicksLayer";
import { QueryClient } from "@tanstack/query-core";

import { Getter, WritableAtom, atom } from "jotai";
Expand Down Expand Up @@ -177,6 +178,8 @@ function makeLayer(type: LayerType, name: string, queryClient: QueryClient): Bas
return new SeismicLayer(name, queryClient);
case LayerType.SURFACES:
return new SurfaceLayer(name, queryClient);
case LayerType.WELLPICKS:
return new WellpicksLayer(name, queryClient);
default:
throw new Error(`Layer type ${type} not supported`);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from "react";

import { SurfaceMeta_api } from "@api";
import { SurfaceAttributeType_api, SurfaceMeta_api } from "@api";
import { apiService } from "@framework/ApiService";
import { EnsembleIdent } from "@framework/EnsembleIdent";
import { EnsembleSet } from "@framework/EnsembleSet";
Expand Down Expand Up @@ -60,7 +60,15 @@ export const SurfaceLayerSettingsComponent: React.FC<SurfaceLayerSettingsCompone
const availableAttributes: string[] = [];

if (surfaceDirectoryQuery.data) {
availableAttributes.push(...Array.from(new Set(surfaceDirectoryQuery.data.map((el) => el.attribute_name))));
availableAttributes.push(
...Array.from(
new Set(
surfaceDirectoryQuery.data
.filter((el) => el.attribute_type === SurfaceAttributeType_api.DEPTH)
.map((el) => el.attribute_name)
)
)
);

const fixupAttribute = fixupSetting(
"attribute",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import React from "react";

import { SurfaceAttributeType_api, SurfaceMeta_api } from "@api";
import { apiService } from "@framework/ApiService";
import { EnsembleIdent } from "@framework/EnsembleIdent";
import { EnsembleSet } from "@framework/EnsembleSet";
import { WorkbenchSession, useEnsembleRealizationFilterFunc } from "@framework/WorkbenchSession";
import { WorkbenchSettings } from "@framework/WorkbenchSettings";
import { EnsembleDropdown } from "@framework/components/EnsembleDropdown";
import { defaultColorPalettes } from "@framework/utils/colorPalettes";
import { ColorPaletteSelector, ColorPaletteSelectorType } from "@lib/components/ColorPaletteSelector";
import { Dropdown, DropdownOption } from "@lib/components/Dropdown";
import { PendingWrapper } from "@lib/components/PendingWrapper";
import { Select } from "@lib/components/Select";
import { ColorPalette } from "@lib/utils/ColorPalette";
import { ColorSet } from "@lib/utils/ColorSet";
import { useLayerSettings } from "@modules/Intersection/utils/layers/BaseLayer";
import { SurfaceLayer, SurfaceLayerSettings } from "@modules/Intersection/utils/layers/SurfaceLayer";
import { WellpicksLayer, WellpicksLayerSettings } from "@modules/Intersection/utils/layers/WellpicksLayer";
import { UseQueryResult, useQuery } from "@tanstack/react-query";

import { isEqual } from "lodash";

export type WellpicksLayerSettingsComponentProps = {
layer: WellpicksLayer;
ensembleSet: EnsembleSet;
workbenchSession: WorkbenchSession;
workbenchSettings: WorkbenchSettings;
};

export const WellpicksLayerSettingsComponent: React.FC<WellpicksLayerSettingsComponentProps> = (props) => {
const settings = useLayerSettings(props.layer);

return (
<div className="table text-sm border-spacing-y-2 border-spacing-x-3 w-full">
<div className="table-row">
<div className="table-cell">Well picks</div>
<div className="table-cell"></div>
</div>
</div>
);
};

const STALE_TIME = 60 * 1000;
const CACHE_TIME = 60 * 1000;

export function useSurfaceDirectoryQuery(
caseUuid: string | undefined,
ensembleName: string | undefined
): UseQueryResult<SurfaceMeta_api[]> {
return useQuery({
queryKey: ["getSurfaceDirectory", caseUuid, ensembleName],
queryFn: () => apiService.surface.getSurfaceDirectory(caseUuid ?? "", ensembleName ?? ""),
staleTime: STALE_TIME,
gcTime: CACHE_TIME,
enabled: caseUuid && ensembleName ? true : false,
});
}

function fixupSetting<TSettings extends WellpicksLayerSettings, TKey extends keyof WellpicksLayerSettings>(
setting: TKey,
validOptions: readonly TSettings[TKey][],
settings: TSettings
): TSettings[TKey] {
if (validOptions.length === 0) {
return settings[setting];
}

if (!validOptions.includes(settings[setting]) || settings[setting] === null) {
return validOptions[0];
}

return settings[setting];
}
17 changes: 15 additions & 2 deletions frontend/src/modules/Intersection/settings/components/layers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
import { GridLayer, isGridLayer } from "@modules/Intersection/utils/layers/GridLayer";
import { SeismicLayer, isSeismicLayer } from "@modules/Intersection/utils/layers/SeismicLayer";
import { isSurfaceLayer } from "@modules/Intersection/utils/layers/SurfaceLayer";
import { isWellpicksLayer } from "@modules/Intersection/utils/layers/WellpicksLayer";
import { Dropdown, MenuButton } from "@mui/base";
import {
Add,
Expand All @@ -45,6 +46,7 @@ import { useAtomValue, useSetAtom } from "jotai";
import { GridLayerSettingsComponent } from "./layerSettings/gridLayer";
import { SeismicLayerSettingsComponent } from "./layerSettings/seismicLayer";
import { SurfaceLayerSettingsComponent } from "./layerSettings/surfaceLayer";
import { WellpicksLayerSettingsComponent } from "./layerSettings/wellpicksLayer";

import { layersAtom } from "../atoms/layersAtoms";

Expand Down Expand Up @@ -202,12 +204,13 @@ export function Layers(props: LayersProps): React.ReactNode {
<div className="flex-grow font-bold text-sm">Layers</div>
<Dropdown>
<MenuButton>
<div className="hover:cursor-pointer hover:bg-blue-100 p-0.5 rounded">
<div className="hover:cursor-pointer hover:bg-blue-100 p-0.5 rounded text-sm flex items-center gap-2">
<Add fontSize="inherit" />
<span>Add layer</span>
<ArrowDropDown fontSize="inherit" />
</div>
</MenuButton>
<Menu anchorOrigin="bottom-start" className="text-sm p-1">
<Menu anchorOrigin="bottom-end" className="text-sm p-1">
{Object.keys(LAYER_TYPE_TO_STRING_MAPPING).map((layerType, index) => {
return (
<MenuItem
Expand Down Expand Up @@ -315,6 +318,16 @@ function LayerItem(props: LayerItemProps): React.ReactNode {
/>
);
}
if (isWellpicksLayer(layer)) {
return (
<WellpicksLayerSettingsComponent
ensembleSet={props.ensembleSet}
workbenchSession={props.workbenchSession}
workbenchSettings={props.workbenchSettings}
layer={layer}
/>
);
}
return null;
}

Expand Down
11 changes: 0 additions & 11 deletions frontend/src/modules/Intersection/typesAndEnums.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,6 @@ export const SeismicSurveyTypeToStringMapping = {
[SeismicSurveyType.FOUR_D]: "4D",
};

export type SeismicSliceImageOptions = {
datapoints: number[][];
yAxisValues: number[];
trajectory: number[][];
colorScale: ColorScale;
};

export type SeismicSliceImageData = SeismicSliceImageOptions & {
image: ImageBitmap | null;
};

export enum LayerType {
GRID = "grid",
SEISMIC = "seismic",
Expand Down
37 changes: 36 additions & 1 deletion frontend/src/modules/Intersection/utils/layers/GridLayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { apiService } from "@framework/ApiService";
import { EnsembleIdent } from "@framework/EnsembleIdent";
import { defaultContinuousSequentialColorPalettes } from "@framework/utils/colorPalettes";
import { ColorScale, ColorScaleGradientType, ColorScaleType } from "@lib/utils/ColorScale";
import { pointDistance } from "@lib/utils/geometry";
import { ColorScaleWithName } from "@modules/Intersection/view/utils/ColorScaleWithName";
import {
b64DecodeFloatArrayToFloat32,
Expand All @@ -11,7 +12,7 @@ import {
} from "@modules/_shared/base64";
import { QueryClient } from "@tanstack/query-core";

import { BaseLayer, LayerTopic } from "./BaseLayer";
import { BaseLayer, BoundingBox, LayerTopic } from "./BaseLayer";

// Data structure for the transformed GridSurface data
// Removes the base64 encoded data and replaces them with typed arrays
Expand Down Expand Up @@ -136,6 +137,7 @@ export type GridLayerSettings = {
realizationNum: number | null;
polylineXyz: number[];
showMesh: boolean;
extensionLength: number;
};

export class GridLayer extends BaseLayer<GridLayerSettings, PolylineIntersection_trans> {
Expand All @@ -152,6 +154,7 @@ export class GridLayer extends BaseLayer<GridLayerSettings, PolylineIntersection
realizationNum: null,
polylineXyz: [],
showMesh: false,
extensionLength: 0,
};
super(name, defaultSettings, queryClient);

Expand Down Expand Up @@ -180,6 +183,38 @@ export class GridLayer extends BaseLayer<GridLayerSettings, PolylineIntersection
this._colorScalesParameterMap.set(this._settings.parameterName ?? "", colorScale);
}

getBoundingBox(): BoundingBox | null {
const bbox = super.getBoundingBox();
if (this._data === null || bbox === null) {
return null;
}

let minX = -this._settings.extensionLength;
let maxX = -this._settings.extensionLength;
let minY = Number.MAX_VALUE;
let maxY = Number.MIN_VALUE;

for (const section of this._data.fenceMeshSections) {
const uVectorLength = pointDistance(
{
x: section.start_utm_x,
y: section.start_utm_y,
},
{
x: section.end_utm_x,
y: section.end_utm_y,
}
);
maxX += uVectorLength;
}

return {
x: [minX, maxX],
y: bbox.y,
z: bbox.z,
};
}

getUseCustomColorScaleBoundaries(): boolean {
return this._useCustomColorScaleBoundariesParameterMap.get(this._settings.parameterName ?? "") ?? false;
}
Expand Down
43 changes: 38 additions & 5 deletions frontend/src/modules/Intersection/utils/layers/SeismicLayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,19 @@ import { apiService } from "@framework/ApiService";
import { EnsembleIdent } from "@framework/EnsembleIdent";
import { defaultContinuousDivergingColorPalettes } from "@framework/utils/colorPalettes";
import { ColorScale, ColorScaleGradientType, ColorScaleType } from "@lib/utils/ColorScale";
import { SeismicDataType, SeismicSliceImageOptions, SeismicSurveyType } from "@modules/Intersection/typesAndEnums";
import { SeismicDataType, SeismicSurveyType } from "@modules/Intersection/typesAndEnums";
import { ColorScaleWithName } from "@modules/Intersection/view/utils/ColorScaleWithName";
import { b64DecodeFloatArrayToFloat32 } from "@modules/_shared/base64";
import { QueryClient } from "@tanstack/query-core";

import { BaseLayer, LayerStatus, LayerTopic } from "./BaseLayer";
import { BaseLayer, BoundingBox, LayerStatus, LayerTopic } from "./BaseLayer";

export type SeismicSliceImageOptions = {
datapoints: number[][];
yAxisValues: number[];
trajectory: number[][];
colorScale: ColorScale;
};

// Data structure for transformed data
// Remove the base64 encoded data and replace with a Float32Array
Expand Down Expand Up @@ -47,7 +54,7 @@ export type SeismicLayerSettings = {

export type SeismicLayerData = {
image: ImageBitmap | null;
options: SeismicSliceImageOptions | null;
options: SeismicSliceImageOptions;
seismicFenceData: SeismicFenceData_trans;
};

Expand Down Expand Up @@ -100,8 +107,8 @@ export class SeismicLayer extends BaseLayer<SeismicLayerSettings, SeismicLayerDa
return;
}

this.notifySubscribers(LayerTopic.DATA);
this._colorScalesParameterMap.set(addr, colorScale);
this.notifySubscribers(LayerTopic.DATA);

if (!this._data) {
return;
Expand Down Expand Up @@ -141,6 +148,30 @@ export class SeismicLayer extends BaseLayer<SeismicLayerSettings, SeismicLayerDa
this.notifySubscribers(LayerTopic.DATA);
}

getBoundingBox(): BoundingBox | null {
if (!this._data) {
return null;
}

const xMin =
this._data.options.trajectory.reduce((acc: number, val: number[]) => Math.min(acc, val[0]!), 0) -
this._settings.extensionLength;
const xMax =
this._data.options.trajectory.reduce((acc: number, val: number[]) => Math.max(acc, val[0]!), 0) -
this._settings.extensionLength;

const minTvdMsl = this._data.options.yAxisValues && this._data.options.yAxisValues[0]!;
const maxTvdMsl =
this._data.options.yAxisValues &&
this._data.options.yAxisValues[this._data.options.yAxisValues.length - 1]!;

return {
x: [xMin, xMax],
y: [minTvdMsl, maxTvdMsl],
z: [this._data.seismicFenceData.min_fence_depth, this._data.seismicFenceData.max_fence_depth],
};
}

protected areSettingsValid(): boolean {
return (
this._settings.ensembleIdent !== null &&
Expand Down Expand Up @@ -172,10 +203,12 @@ export class SeismicLayer extends BaseLayer<SeismicLayerSettings, SeismicLayerDa
trajectory: trajectoryXyProjection,
colorScale: this.getColorScale(),
};
const colormap = options.colorScale.getColorPalette().getColors();
const colormap = options.colorScale.sampleColors(options.colorScale.getNumSteps() || 10);

const image = await generateSeismicSliceImage({ ...options }, options.trajectory, colormap, {
isLeftToRight: true,
seismicMin: this.getUseCustomColorScaleBoundaries() ? options.colorScale.getMin() : undefined,
seismicMax: this.getUseCustomColorScaleBoundaries() ? options.colorScale.getMax() : undefined,
})
.then((result) => {
return result ?? null;
Expand Down
Loading

0 comments on commit d5b4cdd

Please sign in to comment.