88
99from energyml .utils .uri import Uri
1010from 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
1313from energyml .utils .data .helper import RgbaColor , ScalarRenderingInfo , read_graphical_rendering_info
1414
1515NO_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 ("\n Property 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 ("\n Property 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 :
0 commit comments