Skip to content

Commit

Permalink
WIP: Prototyping virtual objects Realization and Iteration.
Browse files Browse the repository at this point in the history
  • Loading branch information
perolavsvendsen committed Mar 27, 2024
1 parent 10669d9 commit bff81e8
Show file tree
Hide file tree
Showing 3 changed files with 287 additions and 19 deletions.
70 changes: 67 additions & 3 deletions examples/explorer.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"### Initialize Explorer"
"### TMP prototyping Iteration and Realization virtual objects"
]
},
{
Expand All @@ -25,7 +25,44 @@
"metadata": {},
"outputs": [],
"source": [
"sumo = Explorer()"
"from fmu.sumo.explorer import Explorer\n",
"sumo = Explorer()\n",
"\n",
"# idea: From fmu-sumo, should be able to utilize the Realization and the\n",
"# Iteration concepts directly as objects. Since they don't exist as explicit\n",
"# objects in Sumo, they are virtualized. Idea is that they should look and feel\n",
"# as if they were there (similar to the Case object).\n",
"\n",
"# Pattern 1: Drilling down from the case\n",
"\n",
"mycase = sumo.get_case_by_uuid(\"1ec9bfb0-8d82-4924-a74f-0a0f25054395\")\n",
"\n",
"print(mycase.iterations) # iterations under this case\n",
"\n",
"# pick an iteration\n",
"myiteration = mycase.iterations[\"iter-0\"]\n",
"print(myiteration)\n",
"print(myiteration.uuid)\n",
"\n",
"# pick a realization\n",
"realizations = myiteration.realizations\n",
"print(realizations)\n",
"\n",
"# The indexing pattern below is too confusing. It looks like a list index,\n",
"# i.e. \"give me the 10th realization\" but in fact it is a dict, and we are\n",
"# asking for realization-10 specifically. I.e. if realization 10 is not there,\n",
"# it will give KeyError.\n",
"\n",
"myrealization = realizations[10]\n",
"print(myrealization)\n",
"print(myrealization.surfaces)\n",
"\n",
"\n",
"# Pattern 2: Direct initialization from uuid\n",
"from fmu.sumo.explorer.objects._virtual_objects import Realization, Iteration\n",
"mydirectrealization = Realization(sumo, uuid=\"bdc4deb7-c3d9-64e1-198a-6b89a03e116a\")\n",
"print(mydirectrealization.surfaces)\n",
"\n"
]
},
{
Expand All @@ -47,7 +84,7 @@
"cases = sumo.cases.filter(asset=myassetname)\n",
"\n",
"# Get available status filters\n",
"print(\"Statuses:\",cases.statuses)\n",
"print(\"Statuses:\", cases.statuses)\n",
"\n",
"# Filter on status\n",
"cases = cases.filter(status=\"keep\")\n",
Expand Down Expand Up @@ -89,6 +126,33 @@
"print(\"Tables:\", len(case.polygons))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Find Iterations (ensembles) and Realizations\n",
"_Realization_ and _iteration_ (_ensemble_) are well known concepts in the FMU context, but not explicitly represented by objects in Sumo (metadata not created by `fmu-dataio`)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"surfs = case.surfaces\n",
"print(surfs.iterations)\n",
"\n",
"case.iterations"
]
},
{
"attachments": {},
"cell_type": "markdown",
Expand Down
191 changes: 191 additions & 0 deletions src/fmu/sumo/explorer/objects/_virtual_objects.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
"""Module containing class for virtual objects.
Virtual objects are objects that exist conceptually, but not as specific
data objects in Sumo, such as Realization and Iteration (ensembles)."""

from sumo.wrapper import SumoClient
from fmu.sumo.explorer.objects.surface_collection import SurfaceCollection
from fmu.sumo.explorer._utils import Utils
from fmu.sumo.explorer.pit import Pit

# from fmu.sumo.explorer.objects.case import Case


class Iteration:
"""Representation of the virtual Iteration object."""

def __init__(
self,
sumo: SumoClient,
uuid: str,
case=None,
name: str = None,
pit: Pit = None,
) -> None:

self._sumo = sumo
self._case = case
self._uuid = uuid
self._name = name
self._utils = Utils(sumo)
self._realizations = None
self._pit = pit

def __repr__(self):
return str(self)

def __str__(self):
"""String representation of this instance."""
return f"{self.name} ({self.uuid})"

@property
def uuid(self):
"""The fmu.iteration.uuid for this iteration."""
return self._uuid

@property
def name(self):
"""The fmu.iteration.name for this iteration."""
if self._name is None:
pass # TODO get name
return self._name

@property
def case(self):
"""Case instance representing the case that this iter belongs to."""
if self._case is None:
pass # TODO get_case
return self._case

@property
def realizations(self):
"""The realizations of this iteration."""
if self._realizations is None:
self._realizations = self._get_realizations()
return self._realizations

def _get_realizations(self):
"""Get all realizations of this iteration/ensemble."""

must = [
{
"term": {
"_sumo.parent_object.keyword": self._case.uuid,
}
},
{
"term": {
"fmu.iteration.uuid.keyword": self.uuid,
},
},
]

print("query realizations")

query = {
"query": {
"match": {
"fmu.iteration.uuid": "447992a4-b9c4-8619-6992-5d7d65b73309"
}
},
"aggs": {
"id": {
"terms": {
"field": "fmu.realization.id",
"size": 1000, # usually (!) less than 1000
},
"aggs": {
"uuid": {
"terms": {
"field": "fmu.realization.uuid.keyword",
"size": 10, # should be only one
}
},
"name": {
"terms": {
"field": "fmu.realization.name.keyword",
"size": 10, # should be only one
}
},
},
}
},
"size": 0,
}

res = self._sumo.post("/search", json=query)
buckets = res.json()["aggregations"]["id"]["buckets"]

realizations = {}

for bucket in buckets:
_realization = Realization(
sumo=self._sumo,
id=bucket["key"],
name=bucket["name"]["buckets"][0]["key"],
uuid=bucket["uuid"]["buckets"][0]["key"],
case=self.case,
)
realizations[_realization.id] = _realization

return realizations


class Realization:
"""Representation of the virtual Realization object."""

def __init__(
self,
sumo: SumoClient,
uuid: str,
id: str = None,
name: str = None,
pit: Pit = None,
case=None,
) -> None:
self._sumo = sumo
self._uuid = uuid
self._id = id
self._name = name
self._pit = pit
self._case = case

def __repr__(self):
return str(self)

def __str__(self):
"""String representation of this instance."""
return f"Realization {self.id} ({self.uuid})"

@property
def uuid(self):
"""The fmu.realization.uuid for this realization."""
return self._uuid

@property
def id(self):
"""The fmu.realization.id for this realization."""
return self._id

@property
def case(self):
"""Case instance representing the case this realization belongs to."""
# needed for the class-specific methods, e.g. .surfaces
if self._case is None:
pass # TODO get_case
return self._case

@property
def name(self):
"""The fmu.realization.name for this realization."""
if self._name is None:
pass # TODO get_name
return self._name

@property
def surfaces(self) -> SurfaceCollection:
"""List of surfaces under this realization."""
query = {"match": {"fmu.realization.uuid": self.uuid}}
return SurfaceCollection(
self._sumo, self._uuid, pit=self._pit, query=query
)
45 changes: 29 additions & 16 deletions src/fmu/sumo/explorer/objects/case.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Module containing case class"""

from typing import Dict, List
from sumo.wrapper import SumoClient
from fmu.sumo.explorer.objects._document import Document
Expand All @@ -9,15 +10,17 @@
from fmu.sumo.explorer.objects.dictionary_collection import (
DictionaryCollection,
)
from fmu.sumo.explorer.objects._virtual_objects import Iteration
from fmu.sumo.explorer._utils import Utils
from fmu.sumo.explorer.pit import Pit


class Case(Document):
"""Class for representing a case in Sumo"""

def __init__(self, sumo: SumoClient, metadata: Dict, overview: Dict,
pit: Pit = None):
def __init__(
self, sumo: SumoClient, metadata: Dict, overview: Dict, pit: Pit = None
):
super().__init__(metadata)
self._overview = overview
self._pit = pit
Expand Down Expand Up @@ -88,17 +91,19 @@ def iterations(self) -> List[Dict]:

res = self._sumo.post("/search", json=query)
buckets = res.json()["aggregations"]["uuid"]["buckets"]
iterations = []
iterations = {}

for bucket in buckets:
iterations.append(
{
"uuid": bucket["key"],
"name": bucket["name"]["buckets"][0]["key"],
"realizations": bucket["realizations"]["value"],
}
_iteration = Iteration(
sumo=self._sumo,
case=self,
uuid=bucket["key"],
name=bucket["name"]["buckets"][0]["key"],
pit=self._pit,
)

iterations[_iteration.name] = _iteration

self._iterations = iterations

return self._iterations
Expand Down Expand Up @@ -133,17 +138,25 @@ async def iterations_async(self) -> List[Dict]:

res = await self._sumo.post_async("/search", json=query)
buckets = res.json()["aggregations"]["id"]["buckets"]
iterations = []
iterations = {}

for bucket in buckets:
iterations.append(
{
"id": bucket["key"],
"name": bucket["name"]["buckets"][0]["key"],
"realizations": len(bucket["realizations"]["buckets"]),
}
_iteration = Iteration(
sumo=self._sumo,
case=self,
uuid=bucket["key"],
name=bucket["name"]["buckets"][0]["key"],
)

iterations[_iteration.name] = _iteration
# iterations.append(
# {
# "id": bucket["key"],
# "name": bucket["name"]["buckets"][0]["key"],
# "realizations": len(bucket["realizations"]["buckets"]),
# }
# )

self._iterations = iterations

return self._iterations
Expand Down

0 comments on commit bff81e8

Please sign in to comment.