Skip to content

Commit 52dd88f

Browse files
committed
[CLN] Add regions to structuctural_frame
1 parent 0211f96 commit 52dd88f

File tree

1 file changed

+146
-133
lines changed

1 file changed

+146
-133
lines changed

gempy/core/data/structural_frame.py

Lines changed: 146 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -34,144 +34,12 @@ class StructuralFrame:
3434
# ? Should I create some sort of structural options class? For example, the masking descriptor and faults relations pointer
3535
is_dirty: bool = True
3636

37-
@model_validator(mode="wrap")
38-
@classmethod
39-
def deserialize_binary(cls, data: Union["StructuralFrame", dict], constructor: ModelWrapValidatorHandler["StructuralFrame"]) -> "StructuralFrame":
40-
match data:
41-
case StructuralFrame():
42-
return data
43-
case dict():
44-
instance: StructuralFrame = constructor(data)
45-
metadata = data.get('binary_meta_data', {})
46-
47-
context = loading_model_context.get()
48-
49-
if 'binary_body' not in context:
50-
return instance
51-
52-
binary_array = context['binary_body']
53-
54-
sp_binary = binary_array[:metadata["sp_binary_length"]]
55-
ori_binary = binary_array[metadata["sp_binary_length"]:]
56-
57-
# Reconstruct arrays
58-
sp_data: np.ndarray = np.frombuffer(sp_binary, dtype=SurfacePointsTable.dt)
59-
ori_data: np.ndarray = np.frombuffer(ori_binary, dtype=OrientationsTable.dt)
60-
61-
instance.surface_points = SurfacePointsTable(
62-
data=sp_data,
63-
name_id_map=instance.surface_points_copy.name_id_map
64-
)
65-
66-
instance.orientations = OrientationsTable(
67-
data=ori_data,
68-
name_id_map=instance.orientations_copy.name_id_map
69-
)
70-
71-
return instance
72-
case _:
73-
raise ValidationError(f"Invalid data type for StructuralFrame: {type(data)}")
74-
75-
# Access the context variable to get injected data
76-
77-
@model_validator(mode="after")
78-
def deserialize_surface_points(self: "StructuralFrame"):
79-
# Access the context variable to get injected data
80-
context = loading_model_context.get()
81-
82-
if 'surface_points_binary' not in context:
83-
return self
84-
85-
# Check if we have a binary payload to digest
86-
binary_array = context['surface_points_binary']
87-
if not isinstance(binary_array, np.ndarray):
88-
return self
89-
if binary_array.shape[0] < 1:
90-
return self
91-
92-
self.surface_points = SurfacePointsTable(
93-
data=binary_array,
94-
name_id_map=self.surface_points_copy.name_id_map
95-
)
96-
97-
return self
98-
99-
@model_validator(mode="after")
100-
def deserialize_orientations(self: "StructuralFrame"):
101-
# TODO: Check here the binary size of surface_points_binary
102-
103-
# Access the context variable to get injected data
104-
context = loading_model_context.get()
105-
if 'orientations_binary' not in context:
106-
return self
107-
108-
# Check if we have a binary payload to digest
109-
binary_array = context['orientations_binary']
110-
if not isinstance(binary_array, np.ndarray):
111-
return self
112-
113-
self.orientations = OrientationsTable(
114-
data=binary_array,
115-
name_id_map=self.orientations_copy.name_id_map
116-
)
117-
118-
return self
119-
120-
@computed_field
121-
def binary_meta_data(self) -> dict:
122-
sp_data = self.surface_points_copy.data
123-
ori_data = self.orientations_copy.data
124-
return {
125-
'sp_shape' : sp_data.shape,
126-
'sp_dtype' : str(sp_data.dtype),
127-
'sp_binary_length' : len(sp_data.tobytes()),
128-
'ori_shape' : ori_data.shape,
129-
'ori_dtype' : str(ori_data.dtype),
130-
'ori_binary_length': len(ori_data.tobytes())
131-
}
132-
133-
@computed_field
134-
@property
135-
def serialize_sp(self) -> int:
136-
return int(hashlib.md5(self.surface_points_copy.data.tobytes()).hexdigest()[:8], 16)
137-
138-
@computed_field
139-
@property
140-
def serialize_orientations(self) -> int:
141-
return int(hashlib.md5(self.orientations_copy.data.tobytes()).hexdigest()[:8], 16)
37+
# region Constructor
14238

14339
def __init__(self, structural_groups: list[StructuralGroup], color_gen: ColorsGenerator):
14440
self.structural_groups = structural_groups # ? This maybe could be optional
14541
self.color_generator = color_gen
14642

147-
def get_element_by_name(self, element_name: str) -> StructuralElement:
148-
elements: Generator = (group.get_element_by_name(element_name) for group in self.structural_groups)
149-
valid_elements: Generator = (element for element in elements if element is not None)
150-
element = next(valid_elements, None)
151-
if element is None:
152-
raise ValueError(f"Element with name {element_name} not found in the structural frame.")
153-
return element
154-
155-
def get_group_by_name(self, group_name: str) -> StructuralGroup:
156-
groups: Generator = (group for group in self.structural_groups if group.name == group_name)
157-
group = next(groups, None)
158-
if group is None:
159-
raise ValueError(f"Group with name {group_name} not found in the structural frame.")
160-
return group
161-
162-
def get_group_by_element(self, element: StructuralElement) -> StructuralGroup:
163-
groups: Generator = (group for group in self.structural_groups if element in group.elements)
164-
group = next(groups, None)
165-
if group is None:
166-
raise ValueError(f"Element {element.name} not found in any group in the structural frame.")
167-
return group
168-
169-
def append_group(self, group: StructuralGroup):
170-
self.structural_groups.append(group)
171-
172-
def insert_group(self, index: int, group: StructuralGroup):
173-
self.structural_groups.insert(index, group)
174-
17543
@classmethod
17644
def from_data_tables(cls, surface_points: SurfacePointsTable, orientations: OrientationsTable):
17745
surface_points_groups: list[SurfacePointsTable] = surface_points.get_surface_points_by_id_groups()
@@ -245,6 +113,37 @@ def initialize_default_structure(cls) -> 'StructuralFrame':
245113

246114
return structural_frame
247115

116+
# endregion
117+
118+
# region Methods
119+
def get_element_by_name(self, element_name: str) -> StructuralElement:
120+
elements: Generator = (group.get_element_by_name(element_name) for group in self.structural_groups)
121+
valid_elements: Generator = (element for element in elements if element is not None)
122+
element = next(valid_elements, None)
123+
if element is None:
124+
raise ValueError(f"Element with name {element_name} not found in the structural frame.")
125+
return element
126+
127+
def get_group_by_name(self, group_name: str) -> StructuralGroup:
128+
groups: Generator = (group for group in self.structural_groups if group.name == group_name)
129+
group = next(groups, None)
130+
if group is None:
131+
raise ValueError(f"Group with name {group_name} not found in the structural frame.")
132+
return group
133+
134+
def get_group_by_element(self, element: StructuralElement) -> StructuralGroup:
135+
groups: Generator = (group for group in self.structural_groups if element in group.elements)
136+
group = next(groups, None)
137+
if group is None:
138+
raise ValueError(f"Element {element.name} not found in any group in the structural frame.")
139+
return group
140+
141+
def append_group(self, group: StructuralGroup):
142+
self.structural_groups.append(group)
143+
144+
def insert_group(self, index: int, group: StructuralGroup):
145+
self.structural_groups.insert(index, group)
146+
248147
def __repr__(self):
249148
structural_groups_repr = ',\n'.join([repr(g) for g in self.structural_groups])
250149
fault_relations_str = np.array2string(self.fault_relations, precision=2, separator=', ', suppress_small=True) if self.fault_relations is not None else 'None'
@@ -285,6 +184,9 @@ def _repr_html_(self):
285184
"""
286185
return html
287186

187+
# endregion
188+
189+
# region Properties
288190
@property
289191
def structural_elements(self) -> list[StructuralElement]:
290192
"""Returns a list of all structural elements across the structural groups."""
@@ -555,6 +457,117 @@ def surfaces_df(self) -> 'pd.DataFrame':
555457

556458
# endregion
557459

460+
# endregion
461+
# region Pydantic
462+
463+
@model_validator(mode="wrap")
464+
@classmethod
465+
def deserialize_binary(cls, data: Union["StructuralFrame", dict], constructor: ModelWrapValidatorHandler["StructuralFrame"]) -> "StructuralFrame":
466+
match data:
467+
case StructuralFrame():
468+
return data
469+
case dict():
470+
instance: StructuralFrame = constructor(data)
471+
metadata = data.get('binary_meta_data', {})
472+
473+
context = loading_model_context.get()
474+
475+
if 'binary_body' not in context:
476+
return instance
477+
478+
binary_array = context['binary_body']
479+
480+
sp_binary = binary_array[:metadata["sp_binary_length"]]
481+
ori_binary = binary_array[metadata["sp_binary_length"]:]
482+
483+
# Reconstruct arrays
484+
sp_data: np.ndarray = np.frombuffer(sp_binary, dtype=SurfacePointsTable.dt)
485+
ori_data: np.ndarray = np.frombuffer(ori_binary, dtype=OrientationsTable.dt)
486+
487+
instance.surface_points = SurfacePointsTable(
488+
data=sp_data,
489+
name_id_map=instance.surface_points_copy.name_id_map
490+
)
491+
492+
instance.orientations = OrientationsTable(
493+
data=ori_data,
494+
name_id_map=instance.orientations_copy.name_id_map
495+
)
496+
497+
return instance
498+
case _:
499+
raise ValidationError(f"Invalid data type for StructuralFrame: {type(data)}")
500+
501+
# Access the context variable to get injected data
502+
503+
@model_validator(mode="after")
504+
def deserialize_surface_points(self: "StructuralFrame"):
505+
# Access the context variable to get injected data
506+
context = loading_model_context.get()
507+
508+
if 'surface_points_binary' not in context:
509+
return self
510+
511+
# Check if we have a binary payload to digest
512+
binary_array = context['surface_points_binary']
513+
if not isinstance(binary_array, np.ndarray):
514+
return self
515+
if binary_array.shape[0] < 1:
516+
return self
517+
518+
self.surface_points = SurfacePointsTable(
519+
data=binary_array,
520+
name_id_map=self.surface_points_copy.name_id_map
521+
)
522+
523+
return self
524+
525+
@model_validator(mode="after")
526+
def deserialize_orientations(self: "StructuralFrame"):
527+
# TODO: Check here the binary size of surface_points_binary
528+
529+
# Access the context variable to get injected data
530+
context = loading_model_context.get()
531+
if 'orientations_binary' not in context:
532+
return self
533+
534+
# Check if we have a binary payload to digest
535+
binary_array = context['orientations_binary']
536+
if not isinstance(binary_array, np.ndarray):
537+
return self
538+
539+
self.orientations = OrientationsTable(
540+
data=binary_array,
541+
name_id_map=self.orientations_copy.name_id_map
542+
)
543+
544+
return self
545+
546+
@computed_field
547+
def binary_meta_data(self) -> dict:
548+
sp_data = self.surface_points_copy.data
549+
ori_data = self.orientations_copy.data
550+
return {
551+
'sp_shape' : sp_data.shape,
552+
'sp_dtype' : str(sp_data.dtype),
553+
'sp_binary_length' : len(sp_data.tobytes()),
554+
'ori_shape' : ori_data.shape,
555+
'ori_dtype' : str(ori_data.dtype),
556+
'ori_binary_length': len(ori_data.tobytes())
557+
}
558+
559+
@computed_field
560+
@property
561+
def serialize_sp(self) -> int:
562+
return int(hashlib.md5(self.surface_points_copy.data.tobytes()).hexdigest()[:8], 16)
563+
564+
@computed_field
565+
@property
566+
def serialize_orientations(self) -> int:
567+
return int(hashlib.md5(self.orientations_copy.data.tobytes()).hexdigest()[:8], 16)
568+
569+
# endregion
570+
558571
def _validate_faults_relations(self):
559572
"""Check that if there are any StackRelationType.FAULT in the structural groups the fault relation matrix is
560573
given and shape is the right one, i.e. a square matrix of size equals to len(groups)"""

0 commit comments

Comments
 (0)