Skip to content

Commit 7cb90c3

Browse files
committed
[ENH] Serialize grid
1 parent 6004b89 commit 7cb90c3

File tree

7 files changed

+50
-26
lines changed

7 files changed

+50
-26
lines changed

gempy/core/data/encoders/binary_encoder.py

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,15 +60,10 @@ def deserialize_grid(binary_array:bytes, custom_grid_length: int, topography_len
6060
ValueError: If input lengths do not match the specified boundaries or binary data.
6161
"""
6262

63-
total_length = len(binary_array)
64-
custom_grid_start = total_length - custom_grid_length - topography_length
65-
custom_grid_end = total_length - topography_length
6663

67-
topography_grid_start = total_length - topography_length
68-
topography_grid_end = total_length
6964

70-
custom_grid_binary = binary_array[custom_grid_start:custom_grid_end]
71-
topography_binary = binary_array[topography_grid_start:topography_grid_end]
65+
custom_grid_binary = binary_array[:custom_grid_length]
66+
topography_binary = binary_array[custom_grid_length:custom_grid_length + topography_length]
7267
custom_grid = np.frombuffer(custom_grid_binary, dtype=np.float64)
7368
topography = np.frombuffer(topography_binary)
7469

gempy/core/data/encoders/converters.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,10 @@ def instantiate_if_necessary(data: dict, key: str, type: type) -> None:
5252
loading_model_context = ContextVar('loading_model_context', default={})
5353

5454
@contextmanager
55-
def loading_model_from_binary(binary_body: bytes):
55+
def loading_model_from_binary(input_binary: bytes, grid_binary: bytes):
5656
token = loading_model_context.set({
57-
'binary_body': binary_body,
57+
'input_binary': input_binary,
58+
'grid_binary': grid_binary
5859
})
5960
try:
6061
yield

gempy/core/data/grid.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,11 @@ def deserialize_properties(cls, data: Union["Grid", dict], constructor: ModelWra
6666
metadata = data.get('binary_meta_data', {})
6767
context = loading_model_context.get()
6868

69-
if 'binary_body' not in context:
69+
if 'grid_binary' not in context:
7070
return grid
7171

7272
custom_grid_vals, topography_vals = deserialize_grid(
73-
binary_array=context['binary_body'],
73+
binary_array=context['grid_binary'],
7474
custom_grid_length=metadata["custom_grid_binary_length"],
7575
topography_length=metadata["topography_binary_length"]
7676
)
@@ -90,16 +90,18 @@ def deserialize_properties(cls, data: Union["Grid", dict], constructor: ModelWra
9090

9191
@property
9292
def grid_binary(self):
93-
astype = self._custom_grid.values.astype("float64")
94-
custom_grid_bytes = astype.tobytes() if self._custom_grid else b''
93+
custom_grid_bytes = self._custom_grid.values.astype("float64").tobytes() if self._custom_grid else b''
9594
topography_bytes = self._topography.values.astype("float64").tobytes() if self._topography else b''
9695
return custom_grid_bytes + topography_bytes
9796

97+
98+
_grid_binary_size: int = 0
9899
@computed_field
99100
def binary_meta_data(self) -> dict:
100101
return {
101102
'custom_grid_binary_length': len(self._custom_grid.values.astype("float64").tobytes()) if self._custom_grid else 0,
102-
'topography_binary_length': len(self._topography.values.astype("float64").tobytes()) if self._topography else 0
103+
'topography_binary_length': len(self._topography.values.astype("float64").tobytes()) if self._topography else 0,
104+
'grid_binary_size': self._grid_binary_size
103105
}
104106

105107
@computed_field(alias="active_grids")

gempy/core/data/structural_frame.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -476,11 +476,11 @@ def deserialize_binary(cls, data: Union["StructuralFrame", dict], constructor: M
476476
metadata = data.get('binary_meta_data', {})
477477
context = loading_model_context.get()
478478

479-
if 'binary_body' not in context:
479+
if 'input_binary' not in context:
480480
return instance
481481

482482
instance.orientations, instance.surface_points = deserialize_input_data_tables(
483-
binary_array=context['binary_body'],
483+
binary_array=context['input_binary'],
484484
name_id_map=instance.surface_points_copy.name_id_map,
485485
sp_binary_length_=metadata["sp_binary_length"],
486486
ori_binary_length_=metadata["ori_binary_length"]
@@ -492,12 +492,13 @@ def deserialize_binary(cls, data: Union["StructuralFrame", dict], constructor: M
492492

493493
# Access the context variable to get injected data
494494

495-
495+
_input_binary_size: int = 0
496496
@computed_field
497497
def binary_meta_data(self) -> dict:
498498
return {
499499
'sp_binary_length': len(self.surface_points_copy.data.tobytes()),
500-
'ori_binary_length': len(self.orientations_copy.data.tobytes())
500+
'ori_binary_length': len(self.orientations_copy.data.tobytes()) ,
501+
'input_binary_size': self._input_binary_size
501502
}
502503

503504
# endregion

gempy/modules/serialization/save_load.py

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,17 @@ def save_model(model: GeoModel, path: str | None = None, validate_serialization:
6262

6363

6464
def model_to_binary(model: GeoModel) -> bytes:
65-
model_json = model.model_dump_json(by_alias=True, indent=4)
65+
6666
# Compress the binary data
6767
zlib = require_zlib()
6868
compressed_binary_input = zlib.compress(model.structural_frame.input_tables_binary)
6969
compressed_binary_grid = zlib.compress(model.grid.grid_binary)
70+
71+
# * Add here the serialization meta parameters like: len_bytes
72+
model.structural_frame._input_binary_size = len(compressed_binary_input)
73+
model.grid._grid_binary_size = len(compressed_binary_grid)
74+
75+
model_json = model.model_dump_json(by_alias=True, indent=4)
7076
binary_file = _to_binary(
7177
header_json=model_json,
7278
body_input=compressed_binary_input,
@@ -118,15 +124,29 @@ def load_model(path: str) -> GeoModel:
118124

119125

120126
def _deserialize_binary_file(binary_file):
127+
import json
121128
# Get header length from first 4 bytes
122129
header_length = int.from_bytes(binary_file[:4], byteorder='little')
123130
# Split header and body
124-
header_json = binary_file[4:4 + header_length].decode('utf-8')
125-
binary_body = binary_file[4 + header_length:]
131+
header_json= binary_file[4:4 + header_length].decode('utf-8')
132+
header = json.loads(header_json)
133+
input_metadata = header["structural_frame"]["binary_meta_data"]
134+
input_size = input_metadata["input_binary_size"]
135+
136+
grid_metadata = header["grid"]["binary_meta_data"]
137+
grid_size = grid_metadata["grid_binary_size"]
138+
139+
input_binary = binary_file[4 + header_length: 4 + header_length + input_size]
140+
all_sections_length = 4 + header_length + input_size + grid_size
141+
if all_sections_length != len(binary_file):
142+
raise ValueError("Binary file is corrupted")
143+
144+
grid_binary = binary_file[4 + header_length + input_size: all_sections_length]
126145
zlib = require_zlib()
127-
decompressed_binary = zlib.decompress(binary_body)
146+
128147
with loading_model_from_binary(
129-
binary_body=decompressed_binary,
148+
input_binary=(zlib.decompress(input_binary)),
149+
grid_binary=(zlib.decompress(grid_binary))
130150
):
131151
model = GeoModel.model_validate_json(header_json)
132152
return model

test/test_modules/test_grids/test_custom_grid.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
[0, 0, 1000],
1717
[1000, 0, 1000],
1818
[0, 1000, 1000],
19-
[1000, 1000, 1000]]
19+
[1000, 1000, 1000]],
20+
dtype=float
2021
)
2122

2223

test/test_modules/test_grids/test_custom_grid.test_custom_grid.verify/fold.approved.txt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,11 @@
6161
],
6262
"is_dirty": true,
6363
"basement_color": "#ffbe00",
64+
"_input_binary_size": 233,
6465
"binary_meta_data": {
6566
"sp_binary_length": 1296,
66-
"ori_binary_length": 120
67+
"ori_binary_length": 120,
68+
"input_binary_size": 233
6769
}
6870
},
6971
"grid": {
@@ -90,9 +92,11 @@
9092
"_centered_grid": null,
9193
"_transform": null,
9294
"_octree_levels": -1,
95+
"_grid_binary_size": 29,
9396
"binary_meta_data": {
9497
"custom_grid_binary_length": 192,
95-
"topography_binary_length": 0
98+
"topography_binary_length": 0,
99+
"grid_binary_size": 29
96100
},
97101
"active_grids": 1029
98102
},

0 commit comments

Comments
 (0)