-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add observations service/endpoints (#432)
- Loading branch information
1 parent
63e1180
commit 38ddee3
Showing
13 changed files
with
396 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
30 changes: 30 additions & 0 deletions
30
backend/src/backend/primary/routers/observations/router.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import logging | ||
from typing import List, Optional, Literal | ||
|
||
from fastapi import APIRouter, Depends, Query | ||
|
||
from src.backend.auth.auth_helper import AuthHelper | ||
from src.services.sumo_access.observation_access import ObservationAccess | ||
from src.services.utils.authenticated_user import AuthenticatedUser | ||
|
||
from . import schemas | ||
|
||
LOGGER = logging.getLogger(__name__) | ||
|
||
router = APIRouter() | ||
|
||
|
||
@router.get("/observations/") | ||
async def get_observations( | ||
# fmt:off | ||
authenticated_user: AuthenticatedUser = Depends(AuthHelper.get_authenticated_user), | ||
case_uuid: str = Query(description="Sumo case uuid"), | ||
ensemble_name: str = Query(description="Ensemble name"), | ||
# fmt:on | ||
) -> schemas.Observations: | ||
"""Retrieve all observations found in sumo case""" | ||
access = await ObservationAccess.from_case_uuid( | ||
authenticated_user.get_sumo_access_token(), case_uuid, ensemble_name | ||
) | ||
observations = await access.get_observations() | ||
return observations |
76 changes: 76 additions & 0 deletions
76
backend/src/backend/primary/routers/observations/schemas.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
from typing import List, Optional | ||
from enum import Enum | ||
|
||
from pydantic import BaseModel | ||
|
||
|
||
class ObservationType(str, Enum): | ||
"""The observation file in Sumo is a dictionary with these datatypes as keys.""" | ||
|
||
SUMMARY = "smry" | ||
RFT = "rft" | ||
|
||
|
||
class SummaryVectorDateObservation(BaseModel): | ||
"""A single observation of a summary vector at a specific date.""" | ||
|
||
date: str | ||
comment: Optional[str] = None | ||
value: float | ||
error: float | ||
label: str | ||
|
||
|
||
class SummaryVectorObservations(BaseModel): | ||
"""A collection of observations of a summary vector.""" | ||
|
||
vector_name: str | ||
comment: Optional[str] = None | ||
observations: List[SummaryVectorDateObservation] | ||
|
||
|
||
class RftObservation(BaseModel): | ||
"""A specific RFT (Repeat Formation Tester) observation. | ||
Attributes: | ||
value (float): The measured value of the observation. | ||
comment (Optional[str]): An optional comment associated with the observation. | ||
error (float): The measurement error associated with the observation. | ||
zone (str): The zone or region associated with the observation. | ||
md_msl (float): Measured depth from mean sea level. | ||
x (float): X utm coordinate of the observation. | ||
y (float): Y utm coordinate of the observation. | ||
z (float): Z utm coordinate of the observation. | ||
""" | ||
|
||
value: float | ||
comment: Optional[str] = None | ||
error: float | ||
zone: str | ||
md_msl: float | ||
x: float | ||
y: float | ||
z: float | ||
|
||
|
||
class RftObservations(BaseModel): | ||
"""A collection of RFT (Repeat Formation Tester) observations for a specific well at a specific date. | ||
Attributes: | ||
well (str): Unique well identifier | ||
date (str): Observation date | ||
comment (Optional[str]): An optional comment associated with the collection of observations. | ||
observations (List[RftObservation]): A list of RFT observations associated with this collection. | ||
""" | ||
|
||
well: str | ||
date: str | ||
comment: Optional[str] = None | ||
observations: List[RftObservation] | ||
|
||
|
||
class Observations(BaseModel): | ||
"""A collection of observations associated with a field/case/ensemble""" | ||
|
||
summary: List[SummaryVectorObservations] = [] | ||
rft: List[RftObservations] = [] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import logging | ||
from typing import List | ||
|
||
import json | ||
from fmu.sumo.explorer.objects.dictionary import Dictionary | ||
|
||
from ._helpers import SumoEnsemble | ||
from .observation_types import ( | ||
Observations, | ||
SummaryVectorDateObservation, | ||
SummaryVectorObservations, | ||
ObservationType, | ||
RftObservations, | ||
) | ||
|
||
LOGGER = logging.getLogger(__name__) | ||
|
||
|
||
class ObservationAccess(SumoEnsemble): | ||
async def get_observations(self) -> Observations: | ||
"""Retrieve all observations found in sumo case""" | ||
observations_collection = self._case.dictionaries.filter( | ||
stage="case", | ||
name="observations", | ||
tagname="all", | ||
) | ||
if await observations_collection.length_async() == 0: | ||
return Observations() | ||
if await observations_collection.length_async() > 1: | ||
raise ValueError(f"More than one observations dictionary found. {observations_collection.names}") | ||
|
||
observations_handle: Dictionary = await observations_collection.getitem_async(0) | ||
observations_byteio = await observations_handle.blob_async | ||
observations_dict = json.loads(observations_byteio.getvalue().decode()) | ||
|
||
return Observations( | ||
summary=_create_summary_observations(observations_dict), rft=_create_rft_observations(observations_dict) | ||
) | ||
|
||
|
||
def _create_summary_observations(observations_dict: dict) -> List[SummaryVectorObservations]: | ||
"""Create summary observations from the observations dictionary""" | ||
summary_observations: List[SummaryVectorObservations] = [] | ||
if ObservationType.SUMMARY not in observations_dict: | ||
return summary_observations | ||
for smry_obs in observations_dict[ObservationType.SUMMARY]: | ||
summary_observations.append( | ||
SummaryVectorObservations( | ||
vector_name=smry_obs["key"], | ||
observations=[ | ||
SummaryVectorDateObservation( | ||
date=obs["date"], | ||
value=obs["value"], | ||
error=obs["error"], | ||
label=obs["label"], | ||
) | ||
for obs in smry_obs["observations"] | ||
], | ||
) | ||
) | ||
return summary_observations | ||
|
||
|
||
def _create_rft_observations(observations_dict: dict) -> List[RftObservations]: | ||
"""Create RFT observations from the observations dictionary""" | ||
rft_observations: List[RftObservations] = [] | ||
if ObservationType.RFT not in observations_dict: | ||
return rft_observations | ||
LOGGER.debug("RFT observations found. This is not yet implemented.") | ||
return rft_observations |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
from typing import List, Optional | ||
from enum import Enum | ||
|
||
from pydantic import BaseModel | ||
|
||
|
||
class ObservationType(str, Enum): | ||
"""The observation file in Sumo is a dictionary with these datatypes as keys.""" | ||
|
||
SUMMARY = "smry" | ||
RFT = "rft" | ||
|
||
|
||
class SummaryVectorDateObservation(BaseModel): | ||
"""A single observation of a summary vector at a specific date.""" | ||
|
||
date: str | ||
comment: Optional[str] = None | ||
value: float | ||
error: float | ||
label: str | ||
|
||
|
||
class SummaryVectorObservations(BaseModel): | ||
"""A collection of observations of a summary vector.""" | ||
|
||
vector_name: str | ||
comment: Optional[str] = None | ||
observations: List[SummaryVectorDateObservation] | ||
|
||
|
||
class RftObservation(BaseModel): | ||
"""A specific RFT (Repeat Formation Tester) observation. | ||
Attributes: | ||
value (float): The measured value of the observation. | ||
comment (Optional[str]): An optional comment associated with the observation. | ||
error (float): The measurement error associated with the observation. | ||
zone (str): The zone or region associated with the observation. | ||
md_msl (float): Measured depth from mean sea level. | ||
x (float): X utm coordinate of the observation. | ||
y (float): Y utm coordinate of the observation. | ||
z (float): Z utm coordinate of the observation. | ||
""" | ||
|
||
value: float | ||
comment: Optional[str] = None | ||
error: float | ||
zone: str | ||
md_msl: float | ||
x: float | ||
y: float | ||
z: float | ||
|
||
|
||
class RftObservations(BaseModel): | ||
"""A collection of RFT (Repeat Formation Tester) observations for a specific well at a specific date. | ||
Attributes: | ||
well (str): Unique well identifier | ||
date (str): Observation date | ||
comment (Optional[str]): An optional comment associated with the collection of observations. | ||
observations (List[RftObservation]): A list of RFT observations associated with this collection. | ||
""" | ||
|
||
well: str | ||
date: str | ||
comment: Optional[str] = None | ||
observations: List[RftObservation] | ||
|
||
|
||
class Observations(BaseModel): | ||
"""A collection of observations associated with a field/case/ensemble""" | ||
|
||
summary: List[SummaryVectorObservations] = [] | ||
rft: List[RftObservations] = [] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
/* istanbul ignore file */ | ||
/* tslint:disable */ | ||
/* eslint-disable */ | ||
|
||
import type { RftObservations } from './RftObservations'; | ||
import type { SummaryVectorObservations } from './SummaryVectorObservations'; | ||
|
||
/** | ||
* A collection of observations associated with a field/case/ensemble | ||
*/ | ||
export type Observations = { | ||
summary: Array<SummaryVectorObservations>; | ||
rft: Array<RftObservations>; | ||
}; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
/* istanbul ignore file */ | ||
/* tslint:disable */ | ||
/* eslint-disable */ | ||
|
||
/** | ||
* A specific RFT (Repeat Formation Tester) observation. | ||
* | ||
* Attributes: | ||
* value (float): The measured value of the observation. | ||
* comment (Optional[str]): An optional comment associated with the observation. | ||
* error (float): The measurement error associated with the observation. | ||
* zone (str): The zone or region associated with the observation. | ||
* md_msl (float): Measured depth from mean sea level. | ||
* x (float): X utm coordinate of the observation. | ||
* y (float): Y utm coordinate of the observation. | ||
* z (float): Z utm coordinate of the observation. | ||
*/ | ||
export type RftObservation = { | ||
value: number; | ||
comment: (string | null); | ||
error: number; | ||
zone: string; | ||
md_msl: number; | ||
'x': number; | ||
'y': number; | ||
'z': number; | ||
}; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
/* istanbul ignore file */ | ||
/* tslint:disable */ | ||
/* eslint-disable */ | ||
|
||
import type { RftObservation } from './RftObservation'; | ||
|
||
/** | ||
* A collection of RFT (Repeat Formation Tester) observations for a specific well at a specific date. | ||
* | ||
* Attributes: | ||
* well (str): Unique well identifier | ||
* date (str): Observation date | ||
* comment (Optional[str]): An optional comment associated with the collection of observations. | ||
* observations (List[RftObservation]): A list of RFT observations associated with this collection. | ||
*/ | ||
export type RftObservations = { | ||
well: string; | ||
date: string; | ||
comment: (string | null); | ||
observations: Array<RftObservation>; | ||
}; | ||
|
Oops, something went wrong.