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

Implement Well-log viewer module MVP #794

Merged
merged 16 commits into from
Dec 4, 2024
Merged
Show file tree
Hide file tree
Changes from 2 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: 6 additions & 0 deletions backend_py/primary/primary/routers/well/converters.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,9 @@ def convert_wellbore_perforation_to_schema(
def convert_wellbore_log_curve_header_to_schema(
wellbore_log_curve_header: WellboreLogCurveHeader,
) -> schemas.WellboreLogCurveHeader:
if wellbore_log_curve_header.log_name is None:
raise AttributeError("Missing log name is not allowed")

return schemas.WellboreLogCurveHeader(
logName=wellbore_log_curve_header.log_name,
curveName=wellbore_log_curve_header.curve_name,
Expand All @@ -131,6 +134,9 @@ def convert_wellbore_log_curve_data_to_schema(
wellbore_log_curve_data: WellboreLogCurveData,
) -> schemas.WellboreLogCurveData:
return schemas.WellboreLogCurveData(
name=wellbore_log_curve_data.name,
unit=wellbore_log_curve_data.unit,
curveUnitDesc=wellbore_log_curve_data.curve_unit_desc,
indexMin=wellbore_log_curve_data.index_min,
indexMax=wellbore_log_curve_data.index_max,
minCurveValue=wellbore_log_curve_data.min_curve_value,
Expand Down
2 changes: 2 additions & 0 deletions backend_py/primary/primary/routers/well/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,8 @@ async def get_wellbore_log_curve_headers(
return [
converters.convert_wellbore_log_curve_header_to_schema(wellbore_log_curve_header)
for wellbore_log_curve_header in wellbore_log_curve_headers
# Missing log name implies garbage data, so we simply drop them
if wellbore_log_curve_header.log_name is not None
]


Expand Down
13 changes: 8 additions & 5 deletions backend_py/primary/primary/routers/well/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,16 +103,19 @@ class WellborePerforation(BaseModel):
class WellboreLogCurveHeader(BaseModel):
logName: str
curveName: str
curveUnit: str
curveUnit: str | None


class WellboreLogCurveData(BaseModel):
name: str
indexMin: float
indexMax: float
minCurveValue: float
maxCurveValue: float
dataPoints: list[list[float | None]]
curveAlias: str
curveDescription: str
curveAlias: str | None
curveDescription: str | None
indexUnit: str
noDataValue: float
noDataValue: float | None
unit: str
curveUnitDesc: str | None
dataPoints: list[list[float | None]]
28 changes: 22 additions & 6 deletions backend_py/primary/primary/services/ssdl_access/types.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from typing import Any
from pydantic import BaseModel


Expand Down Expand Up @@ -34,18 +35,33 @@ class WellborePerforation(BaseModel):


class WellboreLogCurveHeader(BaseModel):
log_name: str
log_name: str | None
curve_name: str
curve_unit: str
curve_unit: str | None

# Defining a hash-function to facilitate usage in Sets
def __hash__(self) -> int:
# No globally unique field, but curve-name should be unique (per wellbore)
return hash(self.curve_name + (self.log_name or "N/A"))

def __eq__(self, other: Any) -> bool:
if not isinstance(other, WellboreLogCurveHeader):
# delegate to the other item in the comparison
return NotImplemented

return (self.curve_name, self.log_name) == (other.curve_name, other.log_name)


class WellboreLogCurveData(BaseModel):
name: str
index_min: float
index_max: float
min_curve_value: float
max_curve_value: float
DataPoints: list[list[float | None]]
curve_alias: str
curve_description: str
curve_alias: str | None
curve_description: str | None
index_unit: str
no_data_value: float
no_data_value: float | None
unit: str
curve_unit_desc: str | None
DataPoints: list[list[float | None]]
rubenthoms marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,12 @@ async def get_log_curve_headers_for_wellbore(self, wellbore_uuid: str) -> List[t
endpoint = f"WellLog/{wellbore_uuid}"
ssdl_data = await fetch_from_ssdl(access_token=self._ssdl_token, endpoint=endpoint, params=None)
try:
result = [types.WellboreLogCurveHeader.model_validate(log_curve) for log_curve in ssdl_data]
# This endpoint is a bit weird, and MIGHT return duplicates which, as far as I can tell, are the exact same. Using a set to drop duplicates. See data model for comparator
result_set = {types.WellboreLogCurveHeader.model_validate(log_curve) for log_curve in ssdl_data}

except ValidationError as error:
raise InvalidDataError(f"Invalid log curve headers for wellbore {wellbore_uuid}", Service.SSDL) from error
return result
return list(result_set)

async def get_log_curve_headers_for_field(self, field_uuid: str) -> List[types.WellboreLogCurveHeader]:
endpoint = f"WellLog/field/{field_uuid}"
Expand Down
31 changes: 31 additions & 0 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"@types/geojson": "^7946.0.14",
"@webviz/group-tree-plot": "^1.1.14",
"@webviz/subsurface-viewer": "^0.25.2",
"@webviz/well-log-viewer": "^1.12.7",
"@webviz/well-completions-plot": "^1.5.11",
"animate.css": "^4.1.1",
"axios": "^1.6.5",
Expand Down
11 changes: 7 additions & 4 deletions frontend/src/api/models/WellboreLogCurveData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,17 @@
/* tslint:disable */
/* eslint-disable */
export type WellboreLogCurveData = {
name: string;
indexMin: number;
indexMax: number;
minCurveValue: number;
maxCurveValue: number;
dataPoints: Array<Array<(number | null)>>;
curveAlias: string;
curveDescription: string;
curveAlias: (string | null);
curveDescription: (string | null);
indexUnit: string;
noDataValue: number;
noDataValue: (number | null);
unit: string;
curveUnitDesc: (string | null);
dataPoints: Array<Array<(number | null)>>;
};

2 changes: 1 addition & 1 deletion frontend/src/api/models/WellboreLogCurveHeader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@
export type WellboreLogCurveHeader = {
logName: string;
curveName: string;
curveUnit: string;
curveUnit: (string | null);
};

14 changes: 14 additions & 0 deletions frontend/src/framework/utils/arrays.ts
Anders2303 marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/**
* Util method to do an immutable item move in an array
Anders2303 marked this conversation as resolved.
Show resolved Hide resolved
* @param array The array to move items in
* @param from The index of the first item being moved
* @param to The index the item(s) should be moved to
* @param moveAmt The amount of items (from the start-index) that should be moved
* @returns A copy of the original array, with it's items moved accordingly
Anders2303 marked this conversation as resolved.
Show resolved Hide resolved
*/
export function arrayMove<t>(array: t[], from: number, to: number, moveAmt = 1): t[] {
Anders2303 marked this conversation as resolved.
Show resolved Hide resolved
const newArrray = [...array];
const movedItems = newArrray.splice(from, moveAmt);

return newArrray.toSpliced(to, 0, ...movedItems);
}
Loading
Loading