|
3 | 3 | import numpy as np
|
4 | 4 | import warnings
|
5 | 5 | from dataclasses import dataclass
|
6 |
| -from pydantic import model_validator, computed_field |
7 |
| -from typing import Generator |
| 6 | +from pydantic import model_validator, computed_field, ValidationError |
| 7 | +from pydantic.functional_validators import ModelWrapValidatorHandler |
| 8 | +from typing import Generator, Union |
8 | 9 |
|
9 | 10 | from gempy_engine.core.data.input_data_descriptor import InputDataDescriptor
|
10 | 11 | from gempy_engine.core.data.kernel_classes.faults import FaultsData
|
@@ -33,47 +34,101 @@ class StructuralFrame:
|
33 | 34 | # ? Should I create some sort of structural options class? For example, the masking descriptor and faults relations pointer
|
34 | 35 | is_dirty: bool = True
|
35 | 36 |
|
| 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 | + |
36 | 77 | @model_validator(mode="after")
|
37 |
| - def deserialize_surface_points(values: "StructuralFrame"): |
| 78 | + def deserialize_surface_points(self: "StructuralFrame"): |
38 | 79 | # Access the context variable to get injected data
|
39 | 80 | context = loading_model_context.get()
|
40 | 81 |
|
41 | 82 | if 'surface_points_binary' not in context:
|
42 |
| - return values |
| 83 | + return self |
43 | 84 |
|
44 | 85 | # Check if we have a binary payload to digest
|
45 | 86 | binary_array = context['surface_points_binary']
|
46 | 87 | if not isinstance(binary_array, np.ndarray):
|
47 |
| - return values |
| 88 | + return self |
48 | 89 | if binary_array.shape[0] < 1:
|
49 |
| - return values |
50 |
| - |
51 |
| - values.surface_points = SurfacePointsTable( |
| 90 | + return self |
| 91 | + |
| 92 | + self.surface_points = SurfacePointsTable( |
52 | 93 | data=binary_array,
|
53 |
| - name_id_map=values.surface_points_copy.name_id_map |
| 94 | + name_id_map=self.surface_points_copy.name_id_map |
54 | 95 | )
|
55 |
| - |
56 |
| - return values |
57 |
| - |
| 96 | + |
| 97 | + return self |
| 98 | + |
58 | 99 | @model_validator(mode="after")
|
59 |
| - def deserialize_orientations(values: "StructuralFrame"): |
| 100 | + def deserialize_orientations(self: "StructuralFrame"): |
| 101 | + # TODO: Check here the binary size of surface_points_binary |
| 102 | + |
60 | 103 | # Access the context variable to get injected data
|
61 | 104 | context = loading_model_context.get()
|
62 | 105 | if 'orientations_binary' not in context:
|
63 |
| - return values |
64 |
| - |
| 106 | + return self |
| 107 | + |
65 | 108 | # Check if we have a binary payload to digest
|
66 | 109 | binary_array = context['orientations_binary']
|
67 | 110 | if not isinstance(binary_array, np.ndarray):
|
68 |
| - return values |
69 |
| - |
70 |
| - values.orientations = OrientationsTable( |
| 111 | + return self |
| 112 | + |
| 113 | + self.orientations = OrientationsTable( |
71 | 114 | data=binary_array,
|
72 |
| - name_id_map=values.orientations_copy.name_id_map |
| 115 | + name_id_map=self.orientations_copy.name_id_map |
73 | 116 | )
|
74 |
| - |
75 |
| - return values |
76 |
| - |
| 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 | + } |
77 | 132 |
|
78 | 133 | @computed_field
|
79 | 134 | @property
|
|
0 commit comments