Skip to content

880 Data Provider Framework in Intersection Module #948

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

Open
wants to merge 54 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
5b78189
Remove old Intersection module
jorgenherje Mar 26, 2025
810ae91
New Intersection Module - WIP
jorgenherje Apr 28, 2025
371bfa3
WIP - and fix after rebase
jorgenherje Apr 29, 2025
e1d0962
Fix prev settings/storedData issue in provider
jorgenherje Apr 30, 2025
3f24ebd
Adjust color scales and utilize value ranges for grid and seismic
jorgenherje Apr 30, 2025
6e2f68b
Adjust viewport code, and remove duplicate layerMaker-code
jorgenherje Apr 30, 2025
11016c8
Fix linting/formatting issues
jorgenherje May 2, 2025
a1c3243
Adjust calc of boundingBox, bounds and viewport
jorgenherje May 2, 2025
fecf69e
Minor adjustment of maker functions - utilise isLoading
jorgenherje May 2, 2025
e4f461b
Fix WebGL context issue
jorgenherje May 2, 2025
cad7f06
Adjust filename and import order
jorgenherje May 2, 2025
9bd1cad
Adjust boundingBox methods for layers
jorgenherje May 2, 2025
d3c0803
Rename module from IntersectionNew to Intersection
jorgenherje May 2, 2025
2421d32
Fix typing of utility functions
jorgenherje May 2, 2025
55b800f
Ensure invalid/error for fetch if polyline has less than two points
jorgenherje May 2, 2025
b1ac2a5
Sort available settings alphabetically and adjust time/interval setting
jorgenherje May 5, 2025
635ba0c
Ensure valid viewport and bounds values
jorgenherje May 7, 2025
76bce44
Rename IntersectionExtensionLength -> WellboreExtensionLength
jorgenherje May 7, 2025
aea27cd
Adjust seismic colorScale to be symmetric around 0
jorgenherje May 7, 2025
dcdc748
Adjust after rebase
jorgenherje May 12, 2025
ea580c3
Merge branch 'main' into 880-intersection-module-layer-framework-NEW
jorgenherje May 16, 2025
d4034da
Adjust after merge
jorgenherje May 16, 2025
ef2d02d
Adjust viewport and make arrays readonly
jorgenherje May 9, 2025
0b5ba34
Control enable state for view setting
jorgenherje May 13, 2025
99d3009
Add validation and fixup for DrilledWellborePicksSetting
jorgenherje May 13, 2025
cc89018
Add default color scale for seismic
jorgenherje May 13, 2025
84c5dc6
Add color opacity setting for grid and seismic layer
jorgenherje May 13, 2025
f8d2da3
Adjust wellbore dependency code for providers
jorgenherje May 14, 2025
d4336ad
Add IntersectionView by default for a new module
jorgenherje May 14, 2025
3c98f26
Fix EnsembleSetting bug: use EnsembleIdent.equals() for comparison
jorgenherje May 14, 2025
c06201b
Adjust shared settings options and add date as shared setting
jorgenherje May 15, 2025
7ef7335
adjust moved allowed logic
jorgenherje May 15, 2025
a822a67
Handle valid extension length for selected intersection type
jorgenherje May 15, 2025
925e833
Improve IntersectionSetting
jorgenherje May 16, 2025
13607c6
Remove ?. notation for already guarded null
jorgenherje May 16, 2025
1c3e504
Fix import path after merge
jorgenherje May 16, 2025
1a49bda
Revert incorrect formatting in package and package-lock files
jorgenherje May 16, 2025
5af705f
Make SeismicLayer generate image async in `onRescale` handler
jorgenherje May 19, 2025
30573e2
Fix incorrect folder name for utils
jorgenherje May 19, 2025
9db75a2
Add boundingbox for surfaces uncertainties
jorgenherje May 19, 2025
c96f321
Review feedback: Filter surface names on selected attribute
jorgenherje May 19, 2025
1608617
Added observation number to well pick endpoints
Anders2303 May 20, 2025
12126a8
Generate api after update of end-point
jorgenherje May 20, 2025
6a18dbd
First step of fixes based on review
jorgenherje May 20, 2025
eaba538
Second step of fixes based on review
jorgenherje May 21, 2025
1c417ed
Merge remote-tracking branch 'equinor/main' into 880-intersection-mod…
jorgenherje May 22, 2025
bf4f0a9
Use new useVisualizationAssemblerProduct hook
jorgenherje May 21, 2025
734627e
Handle verticalScale in handleFitInViewClick function
jorgenherje May 21, 2025
9429e93
Fixes based on review
jorgenherje May 22, 2025
32fdc43
Update viewport when changing intersection and extension length
jorgenherje May 22, 2025
143ad1b
Merge remote-tracking branch 'equinor/main' into 880-intersection-mod…
jorgenherje May 26, 2025
5d1fca8
Improve viewport and fit in view functionality
jorgenherje May 27, 2025
9ff4a6d
Move ColorLegends into viewportwrapper
jorgenherje May 27, 2025
ff9f87d
Adjust according to review
jorgenherje May 28, 2025
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
2 changes: 1 addition & 1 deletion backend_py/primary/primary/routers/surface/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ async def post_get_surface_intersection(
real_num=realization_num, name=name, attribute=attribute, time_or_interval_str=time_or_interval_str
)
if surface is None:
raise HTTPException(status_code=404, detail="Surface '{name}' not found")
raise HTTPException(status_code=404, detail=f"Surface '{name}' not found")

# Ensure name is applied
surface.name = name
Expand Down
1 change: 1 addition & 0 deletions backend_py/primary/primary/routers/well/converters.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ def convert_wellbore_pick_to_schema(wellbore_pick: WellborePick) -> schemas.Well
depthReferencePoint=wellbore_pick.depth_reference_point,
mdUnit=wellbore_pick.md_unit,
interpreter=wellbore_pick.interpreter,
obsNo=wellbore_pick.obs_no,
)


Expand Down
1 change: 1 addition & 0 deletions backend_py/primary/primary/routers/well/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ class WellborePick(BaseModel):
depthReferencePoint: str
mdUnit: str
interpreter: str | None
obsNo: int


class WellboreCompletion(BaseModel):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ def get_drogon_well_trajectories() -> List[WellboreTrajectory]:
def get_drogon_well_picks() -> List[WellborePick]:
return [
WellborePick(
obs_no=1,
interpreter="DROGON_STAT",
easting=462480.0,
northing=5934232.0,
Expand All @@ -82,6 +83,7 @@ def get_drogon_well_picks() -> List[WellborePick]:
md_unit="m",
),
WellborePick(
obs_no=1,
interpreter="DROGON_STAT",
easting=462480.0,
northing=5934232.0,
Expand All @@ -97,6 +99,7 @@ def get_drogon_well_picks() -> List[WellborePick]:
md_unit="m",
),
WellborePick(
obs_no=1,
interpreter="DROGON_STAT",
easting=462480.0,
northing=5934232.0,
Expand All @@ -112,6 +115,7 @@ def get_drogon_well_picks() -> List[WellborePick]:
md_unit="m",
),
WellborePick(
obs_no=1,
interpreter="DROGON_STAT",
easting=462480.0,
northing=5934232.0,
Expand All @@ -127,6 +131,7 @@ def get_drogon_well_picks() -> List[WellborePick]:
md_unit="m",
),
WellborePick(
obs_no=1,
interpreter="DROGON_STAT",
easting=462480.0,
northing=5934232.0,
Expand All @@ -142,6 +147,7 @@ def get_drogon_well_picks() -> List[WellborePick]:
md_unit="m",
),
WellborePick(
obs_no=1,
interpreter="DROGON_STAT",
easting=463256.9114,
northing=5930542.2944,
Expand All @@ -157,6 +163,7 @@ def get_drogon_well_picks() -> List[WellborePick]:
md_unit="m",
),
WellborePick(
obs_no=1,
interpreter="DROGON_STAT",
easting=464220.0686875976,
northing=5932289.733486914,
Expand All @@ -172,6 +179,7 @@ def get_drogon_well_picks() -> List[WellborePick]:
md_unit="m",
),
WellborePick(
obs_no=1,
interpreter="DROGON_STAT",
easting=463849.68880478514,
northing=5931573.151211523,
Expand All @@ -187,6 +195,7 @@ def get_drogon_well_picks() -> List[WellborePick]:
md_unit="m",
),
WellborePick(
obs_no=1,
interpreter="DROGON_STAT",
easting=464220.0686875976,
northing=5932289.733486914,
Expand All @@ -202,6 +211,7 @@ def get_drogon_well_picks() -> List[WellborePick]:
md_unit="m",
),
WellborePick(
obs_no=1,
interpreter="DROGON_STAT",
easting=463256.9114,
northing=5930542.2944,
Expand All @@ -217,6 +227,7 @@ def get_drogon_well_picks() -> List[WellborePick]:
md_unit="m",
),
WellborePick(
obs_no=1,
interpreter="DROGON_FMU",
easting=464220.0686875976,
northing=5932289.733486914,
Expand All @@ -232,6 +243,7 @@ def get_drogon_well_picks() -> List[WellborePick]:
md_unit="m",
),
WellborePick(
obs_no=1,
interpreter="DROGON_STAT",
easting=463849.68880478514,
northing=5931573.151211523,
Expand All @@ -247,6 +259,7 @@ def get_drogon_well_picks() -> List[WellborePick]:
md_unit="m",
),
WellborePick(
obs_no=1,
interpreter="DROGON_FMU",
easting=464220.0686875976,
northing=5932289.733486914,
Expand Down
1 change: 1 addition & 0 deletions backend_py/primary/primary/services/smda_access/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class WellborePick(BaseModel):
depth_reference_point: str
md_unit: str
interpreter: str | None
obs_no: int


class WellboreTrajectory(BaseModel):
Expand Down
1 change: 1 addition & 0 deletions frontend/src/api/autogen/types.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1172,6 +1172,7 @@ export type WellborePick_api = {
depthReferencePoint: string;
mdUnit: string;
interpreter: string | null;
obsNo: number;
};

export type WellboreTrajectory_api = {
Expand Down
9 changes: 9 additions & 0 deletions frontend/src/framework/types/viewport.ts
Original file line number Diff line number Diff line change
@@ -1 +1,10 @@
/**
* Viewport type definition
*
* Viewport: [cx, cy, displacement]
*
* cx: x-coordinate of the center of the viewport
* cy: y-coordinate of the center of the viewport
* displacement: distance from the center of the viewport to the edge of the viewport in x-direction (horizontal width)
*/
export type Viewport = [number, number, number];
6 changes: 6 additions & 0 deletions frontend/src/lib/components/ToggleButton/toggleButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,19 @@ export type ToggleButtonProps = ButtonUnstyledProps & {
function ToggleButtonComponent(props: ToggleButtonProps, ref: React.ForwardedRef<HTMLDivElement>) {
const { active, onToggle, ...other } = props;
const [isActive, setIsActive] = React.useState<boolean>(active);
const [prevIsActive, setPrevIsActive] = React.useState<boolean>(active);

const buttonRef = React.useRef<HTMLButtonElement>(null);
React.useImperativeHandle<HTMLButtonElement | null, HTMLButtonElement | null>(
props.buttonRef,
() => buttonRef.current,
);

if (active !== prevIsActive) {
setIsActive(active);
setPrevIsActive(isActive);
}

const handleClick = React.useCallback(() => {
setIsActive(!isActive);
onToggle(!active);
Expand Down
18 changes: 17 additions & 1 deletion frontend/src/lib/utils/ColorSet.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import type { ColorPalette } from "@lib/utils/ColorPalette";
import type { ColorPaletteSerialization } from "@lib/utils/ColorPalette";
import { ColorPalette } from "@lib/utils/ColorPalette";

export type ColorSetSerialization = {
colorPalette: ColorPaletteSerialization;
};

export class ColorSet {
private _colorPalette: ColorPalette;
Expand Down Expand Up @@ -50,4 +55,15 @@ export class ColorSet {
this._runningIndex = (this._runningIndex + 1) % this._colorPalette.getColors().length;
return color;
}

serialize(): ColorSetSerialization {
return {
colorPalette: this._colorPalette.serialize(),
};
}

static fromSerialized(serialized: ColorSetSerialization): ColorSet {
const colorPalette = ColorPalette.fromSerialized(serialized.colorPalette);
return new ColorSet(colorPalette);
}
}
7 changes: 7 additions & 0 deletions frontend/src/lib/utils/assertNonNull.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export function assertNonNull<T>(value: T | null | undefined, message?: string): T {
if (value === null || value === undefined) {
message = message || "Value cannot be null or undefined";
throw new Error(message);
}
return value;
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { useMultiViewPicking } from "@webviz/subsurface-viewer/dist/hooks/useMul

import { useElementSize } from "@lib/hooks/useElementSize";
import { ColorLegendsContainer } from "@modules/_shared/components/ColorLegendsContainer";
import type { ColorScaleWithId } from "@modules/_shared/components/ColorLegendsContainer/colorLegendsContainer";
import type { ColorScaleWithId } from "@modules/_shared/components/ColorLegendsContainer/colorScaleWithId";
import { SubsurfaceViewerWithCameraState } from "@modules/_shared/components/SubsurfaceViewerWithCameraState";

import { ReadoutBoxWrapper } from "./ReadoutBoxWrapper";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { Setting } from "@modules/_shared/DataProviderFramework/settings/settingsDefinitions";
import type {
Annotation,
TransformerArgs,
} from "@modules/_shared/DataProviderFramework/visualization/VisualizationAssembler";
import { ColorScaleWithName } from "@modules/_shared/utils/ColorScaleWithName";

import { createGridColorScaleValues, createSeismicColorScaleValues } from "../utils/colorScaleUtils";

function makeColorScaleAnnotation({
getSetting,
getValueRange,
id,
isLoading,
createColorScaleValues,
}: TransformerArgs<[Setting.COLOR_SCALE, Setting.ATTRIBUTE], any, any, any> & {
createColorScaleValues: (valueRange: readonly [number, number]) => { min: number; max: number; mid: number };
}): Annotation[] {
const colorScale = getSetting(Setting.COLOR_SCALE)?.colorScale;
const useCustomColorScaleBoundaries = getSetting(Setting.COLOR_SCALE)?.areBoundariesUserDefined ?? false;
const valueRange = getValueRange();
const attribute = getSetting(Setting.ATTRIBUTE);

if (!colorScale || !valueRange || !attribute || isLoading) {
return [];
}

// Adjust color scale boundaries
const adjustedColorScale = colorScale.clone();
if (!useCustomColorScaleBoundaries) {
const { min, max, mid } = createColorScaleValues(valueRange);
adjustedColorScale.setRangeAndMidPoint(min, max, mid);
}

return [{ id, colorScale: ColorScaleWithName.fromColorScale(adjustedColorScale, attribute) }];
}

export function makeGridColorScaleAnnotation(
args: TransformerArgs<[Setting.COLOR_SCALE, Setting.ATTRIBUTE], any, any, any>,
): Annotation[] {
return makeColorScaleAnnotation({
...args,
createColorScaleValues: createGridColorScaleValues,
});
}

export function makeSeismicColorScaleAnnotation(
args: TransformerArgs<[Setting.COLOR_SCALE, Setting.ATTRIBUTE], any, any, any>,
): Annotation[] {
return makeColorScaleAnnotation({
...args,
createColorScaleValues: createSeismicColorScaleValues,
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { fromNumArray, type BBox } from "@lib/utils/bbox";
import type {
IntersectionRealizationGridData,
IntersectionRealizationGridSettings,
IntersectionRealizationGridStoredData,
} from "@modules/_shared/DataProviderFramework/dataProviders/implementations/IntersectionRealizationGridProvider";
import { Setting } from "@modules/_shared/DataProviderFramework/settings/settingsDefinitions";
import type { TransformerArgs } from "@modules/_shared/DataProviderFramework/visualization/VisualizationAssembler";
import { createTransformedPolylineIntersectionResult } from "@modules/_shared/Intersection/gridIntersectionTransform";

import { createValidExtensionLength } from "../utils/extensionLengthUtils";

/**
* Build a bounding box for the intersection grid data.
*
* The intersection uz-coordinates are provided as the xy-coordinates of the bounding box,
* as they are to be visualized in a 2D view.
*/
export function makeGridBoundingBox({
isLoading,
getData,
getStoredData,
getSetting,
}: TransformerArgs<
IntersectionRealizationGridSettings,
IntersectionRealizationGridData,
IntersectionRealizationGridStoredData,
any
>): BBox | null {
const polylineIntersectionData = getData();
const polylineActualSectionLengths = getStoredData("polylineWithSectionLengths")?.actualSectionLengths;
const extensionLength = createValidExtensionLength(
getSetting(Setting.INTERSECTION),
getSetting(Setting.WELLBORE_EXTENSION_LENGTH),
);

if (!polylineIntersectionData || !polylineActualSectionLengths || isLoading) {
return null;
}

// Ensure consistency between fetched data and requested polyline
if (polylineIntersectionData.fenceMeshSections.length !== polylineActualSectionLengths.length) {
throw new Error(
`Number of fence mesh sections (${polylineIntersectionData.fenceMeshSections.length}) does not match number of actual section
lengths (${polylineActualSectionLengths.length}) for requested polyline`,
);
}

const transformedPolylineIntersection = createTransformedPolylineIntersectionResult(
polylineIntersectionData,
polylineActualSectionLengths,
);

const minX = -extensionLength;
let maxX = -extensionLength;

// If no sections, return a bounding box with only the x-coordinates
if (transformedPolylineIntersection.fenceMeshSections.length === 0) {
return fromNumArray([minX, 0, 0, maxX, 0, 0]);
}

let minY = Number.MAX_VALUE;
let maxY = -Number.MAX_VALUE;
for (const section of transformedPolylineIntersection.fenceMeshSections) {
maxX += section.sectionLength;

minY = Math.min(minY, section.minZ);
maxY = Math.max(maxY, section.maxZ);
}

return fromNumArray([minX, minY, 0, maxX, maxY, 0]);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { fromNumArray, type BBox } from "@lib/utils/bbox";
import type {
IntersectionRealizationSeismicData,
IntersectionRealizationSeismicSettings,
IntersectionRealizationSeismicStoredData,
} from "@modules/_shared/DataProviderFramework/dataProviders/implementations/IntersectionRealizationSeismicProvider";
import { Setting } from "@modules/_shared/DataProviderFramework/settings/settingsDefinitions";
import type { TransformerArgs } from "@modules/_shared/DataProviderFramework/visualization/VisualizationAssembler";

import { createValidExtensionLength } from "../utils/extensionLengthUtils";

/**
* Build a bounding box for the intersection seismic data.
*
* The intersection uz-coordinates are provided as the xy-coordinates of the bounding box,
* as they are to be visualized in a 2D view.
*/
export function makeSeismicBoundingBox({
getData,
getSetting,
getStoredData,
isLoading,
}: TransformerArgs<
IntersectionRealizationSeismicSettings,
IntersectionRealizationSeismicData,
IntersectionRealizationSeismicStoredData,
any
>): BBox | null {
const data = getData();
const polylineActualSectionLengths = getStoredData("sourcePolylineWithSectionLengths")?.actualSectionLengths;
const extensionLength = createValidExtensionLength(
getSetting(Setting.INTERSECTION),
getSetting(Setting.WELLBORE_EXTENSION_LENGTH),
);

if (!data || !polylineActualSectionLengths || isLoading) {
return null;
}

const minX = -extensionLength;
const maxX = polylineActualSectionLengths.reduce((sum, length) => sum + length, -extensionLength);
const minY = data.min_fence_depth;
const maxY = data.max_fence_depth;

return fromNumArray([minX, minY, 0, maxX, maxY, 0]);
}
Loading
Loading