From b62b2b4935493812eebd89ae2217a9ca9c75c693 Mon Sep 17 00:00:00 2001 From: JB Lovland Date: Mon, 15 Jan 2024 09:55:25 +0100 Subject: [PATCH] Yarr.. --- .../fmuconfig/output/global_variables.yml | 2 +- foo.py | 25 ++-- schema/docs/src/public/fmu_results_080.json | 23 +--- src/fmu/dataio/model.py | 111 ++++++++++++++++-- 4 files changed, 117 insertions(+), 44 deletions(-) diff --git a/examples/s/d/nn/xcase/realization-1/iter-0/fmuconfig/output/global_variables.yml b/examples/s/d/nn/xcase/realization-1/iter-0/fmuconfig/output/global_variables.yml index 91e801c69..5aecd2e6b 100644 --- a/examples/s/d/nn/xcase/realization-1/iter-0/fmuconfig/output/global_variables.yml +++ b/examples/s/d/nn/xcase/realization-1/iter-0/fmuconfig/output/global_variables.yml @@ -17,7 +17,7 @@ masterdata: uuid: ad214d85-dac7-19da-e053-c918a4889309 stratigraphic_column: identifier: DROGON_2020 - uuid: some-unique-id-to-be-provided-by-smda + uuid: ad214d85-dac7-19da-e053-c918a4889308 access: asset: name: Drogon diff --git a/foo.py b/foo.py index b98133664..91b450168 100644 --- a/foo.py +++ b/foo.py @@ -66,19 +66,12 @@ class Root(BaseModel): rms: RMS -pp( - safe_load( - open( - "examples/s/d/nn/xcase/realization-1/iter-0/fmuconfig/output/global_variables.yml" - ) - ) -) - -m = Root.model_validate( - safe_load( - open( - "examples/s/d/nn/xcase/realization-1/iter-0/fmuconfig/output/global_variables.yml" - ) - ) -) -pp(m.rms) +with open( + "examples/s/d/nn/xcase/realization-1/iter-0/fmuconfig/output/global_variables.yml" +) as f: + pp(safe_load(f)) + +with open( + "examples/s/d/nn/xcase/realization-1/iter-0/fmuconfig/output/global_variables.yml" +) as f: + m = Root.model_validate(safe_load(f)) diff --git a/schema/docs/src/public/fmu_results_080.json b/schema/docs/src/public/fmu_results_080.json index 5c137fcc6..2491378b1 100644 --- a/schema/docs/src/public/fmu_results_080.json +++ b/schema/docs/src/public/fmu_results_080.json @@ -129,10 +129,9 @@ "const": "fmu" }, "version": { - "$comment": "Must always be on root level.", + "$comment": "Must always be on root level. This is 0.8.0, so require version to be == 0.8.0", "title": "FMU results metadata version", "type": "string", - "$comment": "This is 0.8.0, so require version to be == 0.8.0", "enum": [ "0.8.0" ], @@ -215,8 +214,7 @@ } }, "offset": { - "$comment": "To be used if data represents an offset from the specified name", - "$comment": "e.g. a surface representing an offset from a known horizon", + "$comment": "To be used if data represents an offset from the specified name e.g. a surface representing an offset from a known horizon", "type": "number", "example": 11.2 }, @@ -1097,11 +1095,7 @@ "id": { "type": "string", "description": "The ID of this aggregation", - "$comment": "Used for tying together representations of the same entity", - "$comment": "Example: Statistics for various time steps of the same surface", - "$comment": "Not used in Drogon but widely used on e.g. Johan Sverdrup", - "$comment": "Used for enabling common display and joint visual settings", - "$comment": "A unique uuid is currently used, and included as example but any ID should be sufficient", + "$comment": "Used for tying together representations of the same entity Example: Statistics for various time steps of the same surface Not used in Drogon but widely used on e.g. Johan Sverdrup Used for enabling common display and joint visual settings. A unique uuid is currently used, and included as example but any ID should be sufficient", "examples": [ "15ce3b84-766f-4c93-9050-b154861f9100" ] @@ -1128,8 +1122,7 @@ }, "file": { "description": "Block describing the file as the data appear in FMU context", - "$comment": "While the file may seize to exist, the concept is still useful", - "$comment": "A lot of logic exists on top of the file name now, legacy but not likely to disappear soon", + "$comment": "While the file may seize to exist, the concept is still useful. A lot of logic exists on top of the file name now, legacy but not likely to disappear soon", "type": "object", "required": [ "relative_path", @@ -1167,10 +1160,7 @@ } } }, - "$comment": "DEFINITIONS END HERE", - "$comment": "oneOf below reflects different structures depending on type", - "$comment": "The fmu-block is different for cases and data objects,", - "$comment": "and the data block is only present for data objects.", + "$comment": "DEFINITIONS END HERE oneOf below reflects different structures depending on type The fmu-block is different for cases and data objects, and the data block is only present for data objects.", "required": [ "source", "version", @@ -1252,7 +1242,7 @@ }, "fmu": { "description": "The FMU block records properties that are specific to FMU", - "$comment": "This is the fmu block as it appears in data objects", + "$comment": "This is the fmu block as it appears in data objects implementation below allows realization or aggregation or none of them, never both", "required": [ "model", "case" @@ -1277,7 +1267,6 @@ "$ref": "#/definitions/fmu/aggregation" } }, - "$comment": "implementation below allows realization or aggregation or none of them, never both", "dependencies": { "aggregation": { "not": { diff --git a/src/fmu/dataio/model.py b/src/fmu/dataio/model.py index 1bdfb46b8..f1bc42f4e 100644 --- a/src/fmu/dataio/model.py +++ b/src/fmu/dataio/model.py @@ -5,9 +5,10 @@ from __future__ import annotations from enum import Enum -from typing import Any, Literal +from typing import Any, List, Literal, Union from pydantic import BaseModel, Field, RootModel +from typing_extensions import Annotated class Generic(RootModel[Any]): @@ -197,7 +198,10 @@ class File(BaseModel): class Name(RootModel[str]): root: str = Field( ..., - description="Name of the surface. If stratigraphic, match the entry in the stratigraphic column", + description=( + "Name of the surface. If stratigraphic, match " + "the entry in the stratigraphic column" + ), examples=["VIKING GP. Top"], ) @@ -238,7 +242,7 @@ class Workflow(RootModel[Any]): root: Any -class FieldDescription(RootModel[list[str]]): +class FieldDescription(RootModel[List[str]]): root: list[str] @@ -296,7 +300,7 @@ class FMUTimeObjectItem(BaseModel): label: str | None = Field(default=None, examples=["Label for time stamp"]) -class FMUTimeObject(RootModel[list[FMUTimeObjectItem]]): +class FMUTimeObject(RootModel[List[FMUTimeObjectItem]]): """ List of time stamps referring to simulated time """ @@ -315,7 +319,7 @@ class TracklogEvent(BaseModel): event: str | None = Field(default=None, examples=["created", "updated"]) -class Tracklog(RootModel[list[TracklogEvent]]): +class Tracklog(RootModel[List[TracklogEvent]]): root: list[TracklogEvent] @@ -334,7 +338,10 @@ class Base(BaseModel): class TheDataBlock(BaseModel): name: str = Field( ..., - description="Name of the surface. If stratigraphic, match the entry in the stratigraphic column", + description=( + "Name of the surface. If stratigraphic, match the entry " + "in the stratigraphic column" + ), examples=["VIKING GP. Top"], ) stratigraphic: bool = Field( @@ -421,7 +428,10 @@ class Case1(BaseModel): user: User = Field(..., description="The user name used in ERT") restart_from: str | None = Field( default=None, - description="A reference to another case/iteration that this iteration was restarted from", + description=( + "A reference to another case/iteration that this " + "iteration was restarted from" + ), ) description: FieldDescription | None = None @@ -434,7 +444,10 @@ class Iteration1(BaseModel): ) id: int = Field( ..., - description="The internal identification of this iteration, e.g. the iteration number", + description=( + "The internal identification of this " + "iteration, e.g. the iteration number" + ), examples=[0], ) uuid: Uuid @@ -457,7 +470,9 @@ class Realization1(BaseModel): ) jobs: dict[str, Any] | None = Field( default=None, - description="Content directly taken from the ERT jobs.json file for this realization", + description=( + "Content directly taken from the ERT jobs.json " "file for this realization" + ), ) @@ -497,5 +512,81 @@ class DataObject(BaseModel): file: File -class ModelModel(RootModel[CaseModel | DataObject]): +class ModelModel(RootModel[Union[CaseModel, DataObject]]): root: CaseModel | DataObject + + +### V3? + + +class GeologicalModel(BaseModel): + type: Literal["Structural", "Rock"] + + +class RockGeologicalModel(GeologicalModel): + type: Literal["Rock"] = "Rock" + + +class StructuralGeologicalModel(GeologicalModel): + type: Literal["Structural"] = "Structural" + + +class Shape(BaseModel): + ncol: int = Field(ge=0) + nrow: int = Field(ge=0) + nlay: int = Field(ge=0) + + +class Orientation(BaseModel): + x: float + y: float + z: float + + +class Grid(BaseModel): + coordinate_system: CoordinateSystem + orientation: Orientation + shape: Shape + undef: float | None + + +class Range(BaseModel): + start: float + stop: float + + +class BoundingBox(BaseModel): + x: Range + y: Range + z: Range + + +class Header(BaseModel): + asset: str + created_at: Datetime + created_by: str + version: int + + +class Payland(BaseModel): + type: Literal["fmu.everest", "fmu.ert"] + + +class FMUEverest(Payland): + type: Literal["fmu.everest"] = "fmu.everest" + + +class FMUErt(BaseModel): + type: Literal["fmu.ert"] = "fmu.ert" + model: Annotated[ + StructuralGeologicalModel | RockGeologicalModel, + Field(discriminator="type"), + ] + + +class Export(BaseModel): + header: Header + payload: Annotated[ + FMUEverest | FMUErt, + Field(discriminator="type"), + ]