From 8fb8e3f7c0de4314f0445d34845b057801a8be02 Mon Sep 17 00:00:00 2001 From: JB Lovland Date: Fri, 19 Jan 2024 17:36:36 +0100 Subject: [PATCH] Solo questing --- boom.py | 1 + ex.py | 20 +- parameters.py | 38 ++++ src/fmu/dataio/models/meta2.py | 340 +++++++++++---------------------- src/fmu/dataio/models/meta3.py | 2 +- 5 files changed, 162 insertions(+), 239 deletions(-) create mode 100644 parameters.py diff --git a/boom.py b/boom.py index c863423f9..f5f32ba02 100644 --- a/boom.py +++ b/boom.py @@ -48,6 +48,7 @@ def gen(): root_classes.add(Meta.model_validate(m).class_) except Exception: from pprint import pp + pp(m) raise diff --git a/ex.py b/ex.py index d7b3e5fea..aeeace48b 100644 --- a/ex.py +++ b/ex.py @@ -3,11 +3,19 @@ from fmu.dataio.models.meta2 import Meta from orjson import dumps +from pydantic import ValidationError from yaml import safe_load -print(sys.argv[1]) -try: - Meta.model_validate_json(dumps(safe_load(open(sys.argv[1])))) -except Exception: - pp(safe_load(open(sys.argv[1]))) - raise + +def read(file): + with open(file) as f: + return f.read() + +for file in (f.strip() for f in sys.stdin.readlines()): + print(file) + try: + Meta.model_validate_json(dumps(safe_load(read(file)))) + except ValidationError as e: + print(str(e)) + pp(safe_load(read(file))) + print("-" * 100) diff --git a/parameters.py b/parameters.py new file mode 100644 index 000000000..c1abb111c --- /dev/null +++ b/parameters.py @@ -0,0 +1,38 @@ +from __future__ import annotations + +from typing import Dict, Union + +from pydantic import RootModel + + +class Parameters(RootModel[Dict[str, Union[int, float, str, "Parameters"]]]): + ... + + # root: dict[str, int | float | str | Parameters] + + +# class Parameters(BaseModel): +# parameters: Union[int, float, str, "Parameters"] + +# print(Parameters.model_rebuild()) +# print(Parameters.model_json_schema()) +print( + Parameters.model_validate({"hello": "hello", "this": {"this": "that", "more": 1}}) +) +print( + Parameters.model_validate( + { + "SENSNAME": "faultseal", + "SENSCASE": "low", + "RMS_SEED": 1006, + "INIT_FILES": { + "PERM_FLUVCHAN_E1_NORM": 0.748433, + "PERM_FLUVCHAN_E21_NORM": 0.782068, + }, + "KVKH_CHANNEL": 0.6, + "KVKH_US": 0.6, + "FAULT_SEAL_SCALING": 0.1, + "FWL_CENTRAL": 1677, + } + ) +) diff --git a/src/fmu/dataio/models/meta2.py b/src/fmu/dataio/models/meta2.py index b0b088ced..f8cb95766 100644 --- a/src/fmu/dataio/models/meta2.py +++ b/src/fmu/dataio/models/meta2.py @@ -1,54 +1,34 @@ -# generated by datamodel-codegen: -# filename: fmu_results.json -# version: 0.25.2 - from __future__ import annotations import json from collections import ChainMap -from datetime import datetime from pathlib import Path -from typing import Any, Literal, Optional, Union +from typing import Dict, Literal, Optional, Union -from pydantic import BaseModel, Field, RootModel +from pydantic import BaseModel, ByteSize, Field, NaiveDatetime, RootModel from pydantic.json_schema import GenerateJsonSchema class UUID(RootModel[str]): root: str = Field( examples=["ad214d85-8a1d-19da-e053-c918a4889309"], - pattern="^[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}$", + pattern=r"^[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}$", ) class Asset(BaseModel): - name: str = Field( - examples=["Drogon"], - ) + name: str = Field(examples=["Drogon"]) -class SSDL(BaseModel): +class Ssdl(BaseModel): access_level: Literal["internal", "restricted", "asset"] - rep_include: bool = Field( - examples=[True, False], - ) + rep_include: bool class Access(BaseModel): asset: Asset - classification: Literal[ - "internal", - "restricted", - ] = Field( - default="internal", - examples=["internal", "restricted"], - ) - ssdl: SSDL = Field( - default_factory=lambda: SSDL( - access_level="internal", - rep_include=False, - ) - ) + classification: Literal["internal", "restricted"] | None = Field(default=None) + ssdl: Ssdl | None = Field(default=None) class GridModel(BaseModel): @@ -57,38 +37,23 @@ class GridModel(BaseModel): ) +class Shape(BaseModel): + nrow: int = Field(description="The number of rows") + ncol: int = Field(description="The number of columns") + nlay: int = Field(description="The number of layers") + + class CaseSpec(BaseModel): ... -class SurfaceSpec(BaseModel): - ncol: int = Field( - examples=[281], - ) - nlay: int = Field( - examples=[333], - ) - nrow: int = Field( - examples=[441], - ) - rotation: float = Field( - examples=["30.00000000231"], - ) - undef: float = Field( - examples=[1e33], - ) - xinc: float = Field( - examples=[25.0], - ) - xori: float = Field( - examples=[461499.9997558594], - ) - yflip: Literal[-1, 1] = Field( - examples=[-1, 1], - ) - yori: float = Field( - examples=[5926500.224123242], - ) +class SurfaceSpec(Shape): + rotation: float = Field(description="Rotation angle") + undef: float = Field(description="Value representing undefined data") + xinc: float = Field(description="Increment along the x-axis") + xori: float = Field(description="Origin along the x-axis") + yflip: Literal[-1, 1] = Field(description="Flip along the y-axis, -1 or 1") + yori: float = Field(description="Origin along the y-axis") class TableSpec(BaseModel): @@ -101,108 +66,44 @@ class TableSpec(BaseModel): ) -class CPGridSpec(BaseModel): +class CPGridSpec(Shape): """Corner point grid""" - ncol: int = Field( - examples=[281], - ) - nlay: int = Field( - examples=[333], - ) - nrow: int = Field( - examples=[441], - ) + xshift: float = Field(description="Shift along the x-axis") + yshift: float = Field(description="Shift along the y-axis") + zshift: float = Field(description="Shift along the z-axis") - # Shift - xshift: float = Field( - examples=[1234], - ) - yshift: float = Field( - examples=[1234], - ) - zshift: float = Field( - examples=[1234], - ) - - # Scaling - xscale: float = Field( - examples=[1234], - ) - yscale: float = Field( - examples=[1234], - ) - zscale: float = Field( - examples=[1234], - ) + xscale: float = Field(description="Scaling factor for the x-axis") + yscale: float = Field(description="Scaling factor for the y-axis") + zscale: float = Field(description="Scaling factor for the z-axis") -class CPGridPropertySpec(BaseModel): - ncol: int = Field( - examples=[281], - ) - nlay: int = Field( - examples=[333], - ) - nrow: int = Field( - examples=[441], - ) +class CPGridPropertySpec(Shape): + ... class PolygonsSpec(BaseModel): npolys: int = Field( description="The number of individual polygons in the data object", - examples=[1], ) class CubeSpec(SurfaceSpec): - # Shape - ncol: int = Field( - examples=[281], - ) - nlay: int = Field( - examples=[333], - ) - nrow: int = Field( - examples=[441], - ) + # Increment + xinc: float = Field(description="Increment along the x-axis") + yinc: float = Field(description="Increment along the y-axis") + zinc: float = Field(description="Increment along the z-axis") - # inc. - xinc: float = Field( - examples=[25.0], - ) - yinc: float = Field( - examples=[1.1], - ) - zinc: float = Field( - examples=[1.1], - ) + # Origin + xori: float = Field(description="Origin along the x-axis") + yori: float = Field(description="Origin along the y-axis") + zori: float = Field(description="Origin along the z-axis") - # Ori. - xori: float = Field( - examples=[461499.9997558594], - ) - yori: float = Field( - examples=[461499.9997558594], - ) - zori: float = Field( - examples=[461499.9997558594], - ) - - # Misc. - yflip: Literal[-1, 1] = Field( - examples=[-1, 1], - ) - zflip: Literal[-1, 1] = Field( - examples=[-1, 1], - ) - rotation: float = Field( - examples=["30.00000000231"], - ) - undef: float = Field( - examples=[1e33], - ) + # Miscellaneous + yflip: Literal[-1, 1] = Field(description="Flip along the y-axis, -1 or 1") + zflip: Literal[-1, 1] = Field(description="Flip along the z-axis, -1 or 1") + rotation: float = Field(description="Rotation angle") + undef: float = Field(description="Value representing undefined data") class WellSpec(BaseModel): @@ -218,24 +119,12 @@ class DictionarySpec(BaseModel): class BoundingBox(BaseModel): - xmin: float = Field( - examples=[456012.5003497944], - ) - xmax: float = Field( - examples=[467540.52762886323], - ) - ymin: float = Field( - examples=[5926499.999511719], - ) - ymax: float = Field( - examples=[5939492.128326312], - ) - zmin: float = Field( - examples=[1244.039], - ) - zmax: float = Field( - examples=[2302.683], - ) + xmin: float = Field(description="Minimum x-coordinate") + xmax: float = Field(description="Maximum x-coordinate") + ymin: float = Field(description="Minimum y-coordinate") + ymax: float = Field(description="Maximum y-coordinate") + zmin: float = Field(description="Minimum z-coordinate") + zmax: float = Field(description="Maximum z-coordinate") class FluidContact(BaseModel): @@ -246,10 +135,7 @@ class FluidContact(BaseModel): contact: Literal["owc", "fwl", "goc", "fgl"] = Field( examples=["owc", "fwl"], ) - truncated: bool = Field( - default=False, - examples=[True], - ) + truncated: bool = Field(default=False) class FieldOutline(BaseModel): @@ -285,11 +171,9 @@ class Seismic(BaseModel): ) filter_size: Optional[float] = Field( default=None, - examples=[1.0], ) scaling_factor: Optional[float] = Field( default=None, - examples=[1.0], ) stacking_offset: Optional[str] = Field( default=None, @@ -297,7 +181,6 @@ class Seismic(BaseModel): ) zrange: Optional[float] = Field( default=None, - examples=[12.0], ) @@ -310,37 +193,34 @@ class File(BaseModel): description="The absolute file path", examples=["/abs/path/share/results/maps/volantis_gp_base--depth.gri"], ) - checksum_md5: str = Field( - description="md5 checksum of the file or bytestring", - examples=["kjhsdfvsdlfk23knerknvk23"], - ) relative_path: Path = Field( description="The file path relative to RUNPATH", examples=["share/results/maps/volantis_gp_base--depth.gri"], ) - size_bytes: int = Field( - default=-1, + checksum_md5: str = Field( + description="md5 checksum of the file or bytestring", + examples=["kjhsdfvsdlfk23knerknvk23"], + ) + size_bytes: ByteSize | None = Field( + default=None, description="Size of file object in bytes", - examples=[123], ) -class Parameters(BaseModel): - """ - Parameters for this realization - """ +class Parameters(RootModel[Dict[str, Union[int, float, str, "Parameters"]]]): + ... class Aggregation(BaseModel): - id: str = Field( + id: UUID = Field( description="The ID of this aggregation", examples=["15ce3b84-766f-4c93-9050-b154861f9100"], ) operation: str = Field( description="The aggregation performed", ) - parameters: Optional[Union[list[dict[str, Any]], Parameters]] = Field( - default=None, description="Parameters for this realization" + parameters: Parameters = Field( + description="Parameters for this realization", ) realization_ids: list[int] = Field( description="Array of realization ids included in this aggregation" @@ -355,7 +235,7 @@ class Workflow(BaseModel): class User(BaseModel): id: str = Field( - examples=["peesv"], + examples=["peesv", "jlov"], title="User ID", ) @@ -370,14 +250,12 @@ class Layer(BaseModel): ) offset: float = Field( default=0, - examples=[11.2], ) stratigraphic: bool = Field( default=False, description=( "True if data object represents an entity in the stratigraphic colum" ), - examples=[True], ) @@ -394,18 +272,16 @@ class Case(BaseModel): class Iteration(BaseModel): - id: Optional[int] = Field( - default=None, + id: int = Field( description=( "The internal identification of this iteration, e.g. the iteration number" ), - examples=[0], ) name: str = Field( description="The convential name of this iteration, e.g. iter-0 or pred", examples=["iter-0"], ) - restart_from: Optional[UUID] = Field( + restart_from: UUID | None = Field( default=None, description=( "A uuid reference to another iteration that this " @@ -413,9 +289,7 @@ class Iteration(BaseModel): ), ) - uuid: UUID = Field( - examples=["ad214d85-8a1d-19da-e053-c918a4889309"], - ) + uuid: UUID class Model(BaseModel): @@ -433,12 +307,39 @@ class Model(BaseModel): ) +class RealizationJobListing(BaseModel): + arg_types: list[str] + argList: list[Path] + error_file: Optional[Path] + executable: Path + license_path: Optional[Path] + max_arg: int + max_running_minutes: Optional[int] + max_running: Optional[int] + min_arg: int + name: str + start_file: Optional[str] + stderr: Optional[str] + stdin: Optional[str] + stdout: Optional[str] + target_file: Optional[Path] + + +class RealizationJobs(BaseModel): + data_root: Path = Field(alias="DATA_ROOT") + ert_pid: str + global_environment: dict[str, str] + global_update_path: dict + job_list: list[RealizationJobListing] = Field(alias="jobList") + run_id: str + umask: str + + class Realization(BaseModel): id: int = Field( description="The unique number of this realization as used in FMU", - examples=[33], ) - jobs: Optional[dict[str, Any]] = Field( + jobs: Optional[RealizationJobs] = Field( default=None, description=( "Content directly taken from the ERT jobs.json file for this realization" @@ -448,58 +349,46 @@ class Realization(BaseModel): description="The convential name of this iteration, e.g. iter-0 or pred", examples=["iter-0"], ) - parameters: Optional[Union[list[dict[str, Any]], Parameters]] = Field( + parameters: Parameters | None = Field( default=None, description="Parameters for this realization", ) - uuid: UUID = Field( - examples=["ad214d85-8a1d-19da-e053-c918a4889309"], - ) + uuid: UUID class CountryItem(BaseModel): identifier: str = Field( examples=["Norway"], ) - uuid: UUID = Field( - examples=["ad214d85-8a1d-19da-e053-c918a4889309"], - ) + uuid: UUID class DiscoveryItem(BaseModel): short_identifier: str = Field( examples=["SomeDiscovery"], ) - uuid: UUID = Field( - examples=["ad214d85-8a1d-19da-e053-c918a4889309"], - ) + uuid: UUID class FieldItem(BaseModel): identifier: str = Field( examples=["OseFax"], ) - uuid: UUID = Field( - examples=["ad214d85-8a1d-19da-e053-c918a4889309"], - ) + uuid: UUID class CoordinateSystem(BaseModel): identifier: str = Field( examples=["ST_WGS84_UTM37N_P32637"], ) - uuid: UUID = Field( - examples=["ad214d85-8a1d-19da-e053-c918a4889309"], - ) + uuid: UUID class StratigraphicColumn(BaseModel): identifier: str = Field( examples=["DROGON_2020"], ) - uuid: UUID = Field( - examples=["ad214d85-8a1d-19da-e053-c918a4889309"], - ) + uuid: UUID class Smda(BaseModel): @@ -530,7 +419,7 @@ class FMUTimeObject(BaseModel): class TracklogEvent(BaseModel): - datetime: datetime = Field( + datetime: NaiveDatetime = Field( examples=["2020-10-28T14:28:02"], ) event: str = Field( @@ -603,24 +492,22 @@ class Content(BaseModel): description=( "True if data object represents an entity in the stratigraphic column" ), - examples=[True], ) is_prediction: bool = Field( - examples=[True], title="Is prediction flag", ) is_observation: bool = Field( - examples=[True], title="Is observation flag", ) # end + base: Optional[Layer] = None + top: Optional[Layer] = None + class DepthContent(Content): content: Literal["depth"] - depth_reference: Literal["msl", "sb", "rkb"] = Field( - examples=["msl"], - ) + depth_reference: Literal["msl", "sb", "rkb"] class FieldOutlineContent(Content): @@ -645,18 +532,14 @@ class FluidContactContent(Content): class SeismicContent(Content): - content: Literal["fluid_contact"] + content: Literal["seismic"] seismic: Seismic = Field( description="Conditional field", ) class TheDataBlock(BaseModel): - # From schema - - # end alias: Optional[list[str]] = None - base: Optional[Layer] = None bbox: Optional[BoundingBox] = None description: list[str] = Field( default_factory=list, @@ -668,13 +551,12 @@ class TheDataBlock(BaseModel): ) offset: float = Field( default=0.0, - examples=[11.2], ) seismic: Optional[Seismic] = Field( default=None, description="Conditional field", ) - spec: Optional[Spec] = None + # spec: Optional[Spec] = None stratigraphic_alias: Optional[list[str]] = None tagname: Optional[str] = Field( default=None, @@ -682,11 +564,9 @@ class TheDataBlock(BaseModel): examples=["ds_extract_geogrid", "ds_post_strucmod"], ) time: Optional[Time] = None - top: Optional[Layer] = None undef_is_zero: Optional[bool] = Field( default=None, description="Flag if undefined values are to be interpreted as zero", - examples=["True"], ) unit: str = Field( default="", @@ -717,10 +597,6 @@ class ClassMeta(BaseModel): ) -class CaseMeta(ClassMeta): - class_: Literal["case"] - - class Meta(BaseModel): access: Access data: Optional[TheDataBlock] = None diff --git a/src/fmu/dataio/models/meta3.py b/src/fmu/dataio/models/meta3.py index 306f130c0..1c24f1aa4 100644 --- a/src/fmu/dataio/models/meta3.py +++ b/src/fmu/dataio/models/meta3.py @@ -1,7 +1,7 @@ from __future__ import annotations from datetime import datetime -from typing import Any, Dict, List, Literal, Optional, Union +from typing import List, Literal, Union from pydantic import BaseModel, Field, RootModel