Skip to content

Commit bd1143a

Browse files
property kind and repr context
1 parent 446823e commit bd1143a

5 files changed

Lines changed: 117 additions & 17 deletions

File tree

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import json
2+
from typing import List, Dict
3+
from energyml.resqml.v2_0_1.resqmlv2 import ResqmlPropertyKind
4+
from energyml.utils.epc_utils import __CACHE_PROP_KIND_DICT__, get_property_kind_by_title
5+
6+
def title_inclusion(t0: str, t1: str) -> bool:
7+
t0_words = set(t0.lower().split())
8+
t1_words = set(t1.lower().split())
9+
return t0_words.issubset(t1_words) or t1_words.issubset(t0_words)
10+
11+
12+
def search_matching_title(title: List[str]) -> Dict[str, List[str]]:
13+
potential_matches = {t: [] for t in title}
14+
for pk in __CACHE_PROP_KIND_DICT__.values():
15+
for t in title:
16+
if title_inclusion(t, pk.citation.title):
17+
potential_matches[t].append(pk.citation.title)
18+
return potential_matches
19+
20+
if __name__ == "__main__":
21+
not_found = []
22+
for p in ResqmlPropertyKind:
23+
print(p)
24+
pk = get_property_kind_by_title(p.value)
25+
if pk is None:
26+
not_found.append(p.value)
27+
print(f"\t{pk.uuid}" if pk is not None else "\tNot found")
28+
29+
30+
print("Not found tried to match:")
31+
matches = search_matching_title(not_found)
32+
for title, matched_titles in matches.items():
33+
print(f"\t{title}: ")
34+
for mt in matched_titles:
35+
print(f"\t\t{mt}")
36+
37+
with open("pk_not_found_matches.json", "w") as f:
38+
json.dump(matches, f, indent=4)

energyml-utils/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ mypy = "^0.971"
103103
bandit = "^1.7.0"
104104
safety = "^1.10.0"
105105
memory-profiler = "^0.60.0"
106-
line-profiler = "^4.0.0"
106+
# line-profiler = "^4.0.0"
107107

108108
[tool.coverage.run]
109109
branch = true

energyml-utils/src/energyml/utils/data/datasets_io.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -856,7 +856,7 @@ def open_file_no_cache(self, file_path: str, mode: str = "r") -> Optional[Any]:
856856
try:
857857
return h5py.File(file_path, mode) # type: ignore
858858
except Exception as e:
859-
logging.debug(f"Failed to open HDF5 file {file_path}: {e}")
859+
# logging.debug(f"Failed to open HDF5 file {file_path}: {e}")
860860
return None
861861

862862
def read_array(

energyml-utils/src/energyml/utils/data/representation_context.py

Lines changed: 47 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88

99
from energyml.utils.uri import Uri
1010
from energyml.utils.storage_interface import EnergymlStorageInterface
11-
from energyml.utils.epc_utils import extract_uuid_and_version_from_obj_path
12-
from energyml.utils.introspection import get_obj_uri, get_obj_uuid, search_attribute_matching_name
11+
from energyml.utils.epc_utils import extract_uuid_and_version_from_obj_path, get_property_kind_by_title, get_property_kind_uuid_from_property_object
12+
from energyml.utils.introspection import get_obj_uri, get_obj_uuid, get_object_attribute, is_enum, search_attribute_matching_name
1313
from energyml.utils.data.helper import RgbaColor, ScalarRenderingInfo, read_graphical_rendering_info
1414

1515
NO_KIND = "NO_KIND"
@@ -60,16 +60,17 @@ class RepresentationContext(BaseModel):
6060
crs: List[Any] = Field(default_factory=list)
6161
rels: List[Relationship] = Field(default_factory=list)
6262

63-
# Properties keyed by object uuid → property object
64-
properties_by_kind: dict = Field(default_factory=dict)
65-
6663
# Graphical information keyed by GraphicalInformationSet uri → list of entries
6764
graphical_info: dict = Field(default_factory=dict)
6865

6966
time_series: list = Field(default_factory=list)
7067

7168
def __init__(self, obj: Any, workspace: EnergymlStorageInterface, **data):
7269
super().__init__(obj=obj, workspace=workspace, uri=get_obj_uri(obj), **data)
70+
71+
# Properties keyed by object uuid → property object
72+
self._props = {}
73+
self._props_by_kind = {}
7374
self.update()
7475

7576
def update(self):
@@ -92,7 +93,8 @@ def collect_time_series(self):
9293

9394
def _collect_properties(self, rels: List[Relationship]):
9495
# Collect related properties keyed by property uuid
95-
self.properties_by_kind = {}
96+
self._props = {}
97+
self._props_by_kind = {}
9698
for r in self.rels:
9799
if "Property" in r.target:
98100
uuid, version = extract_uuid_and_version_from_obj_path(r.target)
@@ -101,7 +103,26 @@ def _collect_properties(self, rels: List[Relationship]):
101103
logging.warning(f"Property {r.target} not found in workspace")
102104
continue
103105
prop_uuid = getattr(prop, "uuid", NO_KIND)
104-
self.properties_by_kind[prop_uuid] = prop
106+
self._props[prop_uuid] = prop
107+
prop_kind_uuid = get_property_kind_uuid_from_property_object(prop) or NO_KIND
108+
if prop_kind_uuid not in self._props_by_kind:
109+
self._props_by_kind[prop_kind_uuid] = []
110+
111+
if prop_kind_uuid != NO_KIND:
112+
self._props_by_kind[prop_kind_uuid].append(prop)
113+
else:
114+
# Search if a standard name is given (in resqml 201)
115+
title = get_object_attribute(prop, "propertyKind.kind")
116+
if title is not None:
117+
if is_enum(title):
118+
title = title.value
119+
pk = get_property_kind_by_title(title)
120+
if pk is not None:
121+
self._props_by_kind[pk.uuid].append(prop)
122+
else:
123+
self._props_by_kind[NO_KIND].append(prop)
124+
else:
125+
self._props_by_kind[NO_KIND].append(prop)
105126

106127
def _collect_crs(self):
107128
# Collect related CRS objects referenced by the representation
@@ -137,7 +158,17 @@ def get_default_color(self) -> ScalarRenderingInfo:
137158

138159
def get_property(self, property_uuid: str) -> Optional[Any]:
139160
"""Return the property object with the given uuid, or None."""
140-
return self.properties_by_kind.get(property_uuid)
161+
return self._props.get(property_uuid)
162+
163+
@property
164+
def properties(self) -> Dict[str, Any]:
165+
"""Return a dict of all properties keyed by property uuid."""
166+
return self._props
167+
168+
@property
169+
def properties_by_kind(self) -> Dict[str, List[Any]]:
170+
"""Return a dict of properties grouped by property kind uuid."""
171+
return self._props_by_kind
141172

142173
def get_properties_time_series(self, property_uuid: str) -> Dict[str, List[Any]]:
143174
"""
@@ -220,9 +251,10 @@ def dump(self) -> str:
220251

221252
lines.append("")
222253
lines.append(f" Properties ({len(self.properties_by_kind)}):")
223-
for uuid, prop in self.properties_by_kind.items():
224-
kind = getattr(prop, "property_kind", "?")
225-
lines.append(f" - {type(prop).__name__} uuid={uuid} kind={kind}")
254+
for kind, props in self.properties_by_kind.items():
255+
lines.append(f" - Kind {kind} ({len(props)} properties)")
256+
for prop in props:
257+
lines.append(f" - {type(prop).__name__} uuid={get_obj_uuid(prop)}")
226258

227259
lines.append("")
228260
lines.append(f" Graphical info ({len(self.graphical_info)} set(s)):")
@@ -272,21 +304,21 @@ def dump(self) -> str:
272304
print(f" axis_order={info.projected_axis_order}")
273305

274306
# Detail: property arrays (truncated)
275-
if repr_ctx.properties_by_kind:
307+
if repr_ctx._props:
276308
from energyml.utils.data.mesh import read_property
277309

278310
print("\nProperty arrays (first 10 values):")
279-
for uuid, prop in repr_ctx.properties_by_kind.items():
311+
for uuid, prop in repr_ctx._props.items():
280312
try:
281313
arr = read_property(prop, workspace)
282314
print(f" {type(prop).__name__} [{uuid}]: shape={getattr(arr, 'shape', len(arr))} sample={arr[:10]}")
283315
except Exception as exc:
284316
print(f" {type(prop).__name__} [{uuid}]: ERROR reading — {exc}")
285317

286318
# print property time series values
287-
if repr_ctx.properties_by_kind:
319+
if repr_ctx._props:
288320
print("\nProperty time series values:")
289-
for uuid, prop in repr_ctx.properties_by_kind.items():
321+
for uuid, prop in repr_ctx._props.items():
290322
try:
291323
ts_values = repr_ctx.get_properties_time_series(uuid)
292324
if ts_values:

energyml-utils/src/energyml/utils/epc_utils.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,29 @@ def get_property_kind_by_uuid(uuid: str) -> Optional[Any]:
550550
logging.error(f"Failed to parse propertykind dict {e}")
551551
return __CACHE_PROP_KIND_DICT__.get(uuid, None)
552552

553+
def get_property_kind_by_title(title: str) -> Optional[Any]:
554+
"""
555+
Get a property kind by its title.
556+
:param title: the title of the property kind
557+
:return: the property kind or None if not found
558+
"""
559+
560+
# TODO: Make a mapping between energyml.resqml.v2_0_1.resqmlv2.ResqmlPropertyKind enum and the real pk titles.
561+
# Because some values from ResqmlPropertyKind are not the real pk title
562+
563+
if len(__CACHE_PROP_KIND_DICT__) == 0:
564+
# update the cache to check if it is a
565+
try:
566+
update_prop_kind_dict_cache()
567+
except FileNotFoundError as e:
568+
logging.error(f"Failed to parse propertykind dict {e}")
569+
title_reshaped = title.replace(" ", "_").lower()
570+
for prop in __CACHE_PROP_KIND_DICT__.values():
571+
pk_title_reshaped = prop.citation.title.replace(" ", "_").lower() if prop.citation and prop.citation.title else ""
572+
if pk_title_reshaped == title_reshaped:
573+
return prop
574+
return None
575+
553576

554577
def get_property_kind_and_parents(uuids: list) -> Dict[str, Any]:
555578
"""Get PropertyKind objects and their parents from a list of UUIDs.
@@ -575,6 +598,13 @@ def get_property_kind_and_parents(uuids: list) -> Dict[str, Any]:
575598
return dict_props
576599

577600

601+
def get_property_kind_uuid_from_property_object(prop: Any) -> Optional[Any]:
602+
prop_kind_uuid = get_object_attribute(prop, "propertyKind.*.uuid") # resqml 201
603+
if prop_kind_uuid is None:
604+
prop_kind_uuid = get_object_attribute(prop, "propertyKind.uuid") # resqml 22
605+
return prop_kind_uuid
606+
607+
578608
# ____ ____ ____ ______ __ _
579609
# / __ \/ __ \/ __ \ / ____/_______ ____ _/ /_(_)___ ____
580610
# / / / / / / / /_/ / / / / ___/ _ \/ __ `/ __/ / __ \/ __ \

0 commit comments

Comments
 (0)