44import logging
55from typing import Any , Dict , List , Optional
66from energyml .opc .opc import Relationship
7+ from energyml .utils .data .crs import CrsInfo
78from pydantic import BaseModel , Field , ConfigDict
89
910from energyml .utils .uri import Uri
@@ -58,12 +59,17 @@ class RepresentationContext(BaseModel):
5859 uri : Uri = Field (default = "" )
5960
6061 crs : List [Any ] = Field (default_factory = list )
62+ crs_infos : List [CrsInfo ] = Field (default_factory = list )
63+
6164 rels : List [Relationship ] = Field (default_factory = list )
6265
6366 # Graphical information keyed by GraphicalInformationSet uri → list of entries
6467 graphical_info : dict = Field (default_factory = dict )
6568
6669 time_series : list = Field (default_factory = list )
70+
71+ _projected_uom : Optional [str ] = None
72+ _vertical_uom : Optional [str ] = None
6773
6874 def __init__ (self , obj : Any , workspace : EnergymlStorageInterface , ** data ):
6975 super ().__init__ (obj = obj , workspace = workspace , uri = get_obj_uri (obj ), ** data )
@@ -127,13 +133,19 @@ def _collect_properties(self, rels: List[Relationship]):
127133 def _collect_crs (self ):
128134 # Collect related CRS objects referenced by the representation
129135 self .crs = []
136+ self .crs_infos = []
137+ crs_uuids = set ()
130138 crs_dors = search_attribute_matching_name (self .obj , r"\.*Crs" , search_in_sub_obj = True , deep_search = False )
131139 if crs_dors is not None and len (crs_dors ) > 0 :
132140 for crs_ref in crs_dors :
133141 if crs_ref is not None :
134142 crs = self .workspace .get_object (get_obj_uri (crs_ref ))
135143 if crs is not None :
136- self .crs .append (crs )
144+ self .crs .append (crs ) # always add to keep crs for each patch
145+ crs_uuid = getattr (crs , "uuid" , None )
146+ if crs_uuid is not None and crs_uuid not in crs_uuids :
147+ crs_uuids .add (crs_uuid )
148+ self .crs_infos .append (CrsInfo .from_crs_object (crs , self .workspace ))
137149 else :
138150 logging .warning (f"CRS { get_obj_uri (crs_ref )} not found in workspace" )
139151
@@ -160,6 +172,21 @@ def get_property(self, property_uuid: str) -> Optional[Any]:
160172 """Return the property object with the given uuid, or None."""
161173 return self ._props .get (property_uuid )
162174
175+ @property
176+ def projected_uom (self ) -> Optional [str ]:
177+ """Return the projected unit of measure (e.g. "m") if available from CRS info, or None."""
178+ for ci in self .crs_infos :
179+ if ci .projected_uom is not None :
180+ return ci .projected_uom
181+ return None
182+ @property
183+ def vertical_uom (self ) -> Optional [str ]:
184+ """Return the vertical unit of measure (e.g. "m") if available from CRS info, or None."""
185+ for ci in self .crs_infos :
186+ if ci .vertical_uom is not None :
187+ return ci .vertical_uom
188+ return None
189+
163190 @property
164191 def properties (self ) -> Dict [str , Any ]:
165192 """Return a dict of all properties keyed by property uuid."""
0 commit comments