Skip to content

Commit

Permalink
Merge remote-tracking branch 'rubenthoms/2d-viewer' into 2d-viewer
Browse files Browse the repository at this point in the history
  • Loading branch information
rubenthoms committed Aug 20, 2024
2 parents ff90c3b + eb313db commit ae99632
Show file tree
Hide file tree
Showing 8 changed files with 159 additions and 55 deletions.
2 changes: 2 additions & 0 deletions backend_py/primary/primary/routers/well/converters.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ def convert_wellbore_header_to_schema(
wellNorthing=drilled_wellbore_header.well_northing,
depthReferencePoint=drilled_wellbore_header.depth_reference_point,
depthReferenceElevation=drilled_wellbore_header.depth_reference_elevation,
wellborePurpose=drilled_wellbore_header.wellbore_purpose,
wellboreStatus=drilled_wellbore_header.wellbore_status,
)


Expand Down
3 changes: 2 additions & 1 deletion backend_py/primary/primary/routers/well/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ class WellboreHeader(BaseModel):
wellNorthing: float
depthReferencePoint: str
depthReferenceElevation: float

wellborePurpose: str
wellboreStatus: str

class WellboreTrajectory(BaseModel):
wellboreUuid: str
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
from typing import List

import logging

from webviz_pkg.core_utils.perf_timer import PerfTimer
from ..types import WellboreHeader
from ._get_request import get

LOGGER = logging.getLogger(__name__)

async def get_wellbore_headers(
access_token: str,
field_identifier: str,
) -> List[WellboreHeader]:
endpoint = "wellbore-survey-headers"

timer = PerfTimer()

survey_headers_endpoint = "wellbore-survey-headers"
projection = [
"wellbore_uuid",
"unique_wellbore_identifier",
Expand All @@ -27,7 +31,29 @@ async def get_wellbore_headers(
"field_identifier": field_identifier,
}

timer = PerfTimer()
result = await get(access_token=access_token, endpoint=endpoint, params=params)
print(f"TIME SMDA fetch well headers took {timer.lap_s():.2f} seconds")
return [WellboreHeader(**result) for result in result]
survey_header_results = await get(access_token=access_token, endpoint=survey_headers_endpoint, params=params)
LOGGER.debug(f"TIME SMDA fetch well headers took {timer.lap_s():.2f} seconds")

wellheaders_endpoint = "wellheaders"
projection = [
"unique_wellbore_identifier",
"wellbore_purpose",
"wellbore_status"
]
params = {
"_projection": ",".join(projection),
"_sort": "unique_wellbore_identifier",
"field_identifier": field_identifier,
}

wellbore_headers_results = await get(access_token=access_token, endpoint=wellheaders_endpoint, params=params)

for survey_header in survey_header_results:
for wellbore_header in wellbore_headers_results:
if survey_header['unique_wellbore_identifier'] == wellbore_header['unique_wellbore_identifier']:
survey_header['wellbore_purpose'] = wellbore_header['wellbore_purpose']
survey_header['wellbore_status'] = wellbore_header['wellbore_status']
break

LOGGER.debug(f"TIME SMDA fetch well headers took {timer.lap_s():.2f} seconds")
return [WellboreHeader(**result) for result in survey_header_results]
3 changes: 2 additions & 1 deletion backend_py/primary/primary/services/smda_access/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ class WellboreHeader(BaseModel):
well_northing: float
depth_reference_point: str
depth_reference_elevation: float

wellbore_purpose:str
wellbore_status:str

class StratigraphicUnit(BaseModel):
"""
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/api/models/WellboreHeader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,7 @@ export type WellboreHeader = {
wellNorthing: number;
depthReferencePoint: string;
depthReferenceElevation: number;
wellborePurpose: string;
wellboreStatus: string;
};

6 changes: 0 additions & 6 deletions frontend/src/modules/2DViewer/layers/WellboreLayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,6 @@ export class WellboreLayer extends BaseLayer<WellboreLayerSettings, WellboreTraj
y: [minY, maxY],
z: [0, 0],
});

super.setBoundingBox({
x: [minX, maxX],
y: [minY, maxY],
z: [0, 0],
});
}

getBoundingBox(): BoundingBox | null {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,13 @@ export function WellboreLayerSettingsComponent(props: WellboreLayerSettingsCompo
}

return (
<WellboreSelector
wellboreHeaders={availableWellboreHeaders}
selectedWellboreUuids={newSettings.wellboreUuids}
onSelectedWellboreUuidsChange={handleUiidsChange}
/>
<div className="table text-sm border-spacing-y-2 border-spacing-x-3 w-full">
<WellboreSelector
wellboreHeaders={availableWellboreHeaders}
selectedWellboreUuids={newSettings.wellboreUuids}
onSelectedWellboreUuidsChange={handleUiidsChange}
/>
</div>
);
}

Expand Down
148 changes: 112 additions & 36 deletions frontend/src/modules/3DViewer/settings/components/wellboreSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ import React from "react";

import { WellboreHeader_api } from "@api";
import { Button } from "@lib/components/Button";
import { CollapsibleGroup } from "@lib/components/CollapsibleGroup";
import { Dropdown } from "@lib/components/Dropdown";
import { Label } from "@lib/components/Label";
import { Select, SelectOption } from "@lib/components/Select";
import { useValidArrayState } from "@lib/hooks/useValidArrayState";
import { Deselect, SelectAll } from "@mui/icons-material";

export type WellboreSelectorProps = {
Expand All @@ -12,49 +16,121 @@ export type WellboreSelectorProps = {
};

export function WellboreSelector(props: WellboreSelectorProps): React.ReactNode {
const availableWellboreStatuses = Array.from(new Set(props.wellboreHeaders.map((header) => header.wellboreStatus)));
const availableWellborePurposes = Array.from(
new Set(props.wellboreHeaders.map((header) => header.wellborePurpose))
);
const [selectedWellboreStatuses, setSelectedWellboreStatuses] = useValidArrayState<string>({
initialState: availableWellboreStatuses,
validStateArray: availableWellboreStatuses,
});
const [selectedWellborePurposes, setSelectedWellborePurposes] = useValidArrayState<string>({
initialState: availableWellborePurposes,
validStateArray: availableWellborePurposes,
});
React.useEffect(() => {
props.onSelectedWellboreUuidsChange(
props.wellboreHeaders
.filter((header) => selectedWellborePurposes.includes(header.wellborePurpose))
.filter((header) => selectedWellboreStatuses.includes(header.wellboreStatus))
// .filter((header) => props.selectedWellboreUuids.includes(header.wellboreUuid))
.map((header) => header.wellboreUuid)
);
}, [selectedWellborePurposes, selectedWellboreStatuses]);

Check warning on line 39 in frontend/src/modules/3DViewer/settings/components/wellboreSelector.tsx

View workflow job for this annotation

GitHub Actions / frontend

React Hook React.useEffect has a missing dependency: 'props'. Either include it or remove the dependency array. However, 'props' will change when *any* prop changes, so the preferred fix is to destructure the 'props' object outside of the useEffect call and refer to those specific props inside React.useEffect

function handleSelectAll() {
props.onSelectedWellboreUuidsChange(props.wellboreHeaders.map((header) => header.wellboreUuid));
props.onSelectedWellboreUuidsChange(
props.wellboreHeaders
.filter((header) => selectedWellborePurposes.includes(header.wellborePurpose))
.filter((header) => selectedWellboreStatuses.includes(header.wellboreStatus))
.map((header) => header.wellboreUuid)
);
}
function handleUnselectAll() {
props.onSelectedWellboreUuidsChange([]);
}
function makeWellHeadersOptions(): SelectOption[] {
return props.wellboreHeaders
.filter((header) => selectedWellboreStatuses.includes(header.wellboreStatus))
.filter((header) => selectedWellborePurposes.includes(header.wellborePurpose))
.map((wellHeader) => ({
label: wellHeader.uniqueWellboreIdentifier,
value: wellHeader.wellboreUuid,
}));
}

return (
<div className="flex flex-col gap-2 text-sm">
<div className="flex gap-2 items-center">
<Button
onClick={handleSelectAll}
startIcon={<SelectAll />}
variant="text"
title="Select all"
size="small"
>
Select all
</Button>
<Button
onClick={handleUnselectAll}
startIcon={<Deselect />}
variant="text"
title="Unselect all"
size="small"
>
Unselect all
</Button>
</div>
<Select
options={makeWellHeadersOptions(props.wellboreHeaders)}
value={props.selectedWellboreUuids ?? []}
onChange={props.onSelectedWellboreUuidsChange}
size={5}
filter
multiple
debounceTimeMs={600}
/>
</div>
<>
<CollapsibleGroup title="Filter on well status and purpose">
<div className="flex gap-2 flex-grow items-center">
<Label text="Status">
<Select
options={makeWellboreStatusOptions(props.wellboreHeaders)}
value={selectedWellboreStatuses}
onChange={setSelectedWellboreStatuses}
size={5}
multiple
/>
</Label>
<Label text="Purpose">
<Select
options={makeWellborePurposeOptions(props.wellboreHeaders)}
value={selectedWellborePurposes}
onChange={setSelectedWellborePurposes}
size={5}
multiple
/>
</Label>
</div>
</CollapsibleGroup>

<>
<div className="flex gap-2 items-center">
<Button
onClick={handleSelectAll}
startIcon={<SelectAll />}
variant="text"
title="Select all"
size="small"
>
Select all
</Button>
<Button
onClick={handleUnselectAll}
startIcon={<Deselect />}
variant="text"
title="Unselect all"
size="small"
>
Unselect all
</Button>
</div>
<Select
options={makeWellHeadersOptions()}
value={props.selectedWellboreUuids ?? []}
onChange={props.onSelectedWellboreUuidsChange}
size={5}
filter
multiple
debounceTimeMs={600}
/>
</>
</>
);
}
function makeWellHeadersOptions(wellHeaders: WellboreHeader_api[]): SelectOption[] {
return wellHeaders.map((wellHeader) => ({
label: wellHeader.uniqueWellboreIdentifier,
value: wellHeader.wellboreUuid,

function makeWellborePurposeOptions(wellHeaders: WellboreHeader_api[]): SelectOption[] {
const wellborePurposes = Array.from(new Set(wellHeaders.map((header) => header.wellborePurpose)));
return wellborePurposes.map((purpose) => ({
label: purpose,
value: purpose,
}));
}

function makeWellboreStatusOptions(wellHeaders: WellboreHeader_api[]): SelectOption[] {
const wellboreStatuses = Array.from(new Set(wellHeaders.map((header) => header.wellboreStatus)));
return wellboreStatuses.map((status) => ({
label: status,
value: status,
}));
}

0 comments on commit ae99632

Please sign in to comment.