Skip to content

Commit 2a7d8f8

Browse files
committed
Fixed problem with loading of surface layer stack
1 parent 6a40125 commit 2a7d8f8

File tree

1 file changed

+49
-83
lines changed

1 file changed

+49
-83
lines changed

gempy/modules/json_io/json_operations.py

Lines changed: 49 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
from .schema import SurfacePoint, Orientation, GemPyModelJson
1212
from gempy_engine.core.data.stack_relation_type import StackRelationType
13+
from gempy.core.data.structural_element import StructuralElement
1314

1415

1516
class JsonIO:
@@ -43,6 +44,8 @@ def load_model_from_json(file_path: str):
4344
from gempy.core.data.structural_frame import StructuralFrame
4445
from gempy_engine.core.data import InterpolationOptions
4546
from gempy.API.map_stack_to_surfaces_API import map_stack_to_surfaces
47+
from gempy_engine.core.data.stack_relation_type import StackRelationType
48+
from gempy.core.data.structural_group import StructuralGroup
4649

4750
with open(file_path, 'r') as f:
4851
data = json.load(f)
@@ -51,52 +54,30 @@ def load_model_from_json(file_path: str):
5154
if not JsonIO._validate_json_schema(data):
5255
raise ValueError("Invalid JSON schema")
5356

54-
# Get surface names from series data
55-
surface_names = []
57+
# Create a mapping from surface IDs to names
58+
id_to_name = {}
5659
for series in data['series']:
57-
surface_names.extend(series['surfaces'])
58-
59-
# Create a mapping from surface points to their names
60-
surface_point_names = {}
61-
for sp in data['surface_points']:
62-
# Find the surface name that corresponds to this ID
63-
surface_name = None
64-
for series in data['series']:
65-
for i, name in enumerate(series['surfaces']):
66-
if i == sp['id']: # Match the ID with the index in the series
67-
surface_name = name
60+
for surface_name in series['surfaces']:
61+
# Find the ID for this surface name from surface points
62+
for sp in data['surface_points']:
63+
if sp['id'] not in id_to_name:
64+
id_to_name[sp['id']] = surface_name
6865
break
69-
if surface_name is not None:
70-
break
71-
surface_point_names[sp['id']] = surface_name if surface_name is not None else f"surface_{sp['id']}"
72-
73-
# Load surface points and orientations
74-
surface_points = JsonIO._load_surface_points(data['surface_points'], surface_point_names)
75-
orientations = JsonIO._load_orientations(data['orientations'], surface_point_names)
76-
77-
# Create structural frame
78-
structural_frame = StructuralFrame.from_data_tables(surface_points, orientations)
79-
80-
# Create grid
81-
grid = Grid(
82-
extent=data['grid_settings']['regular_grid_extent'],
83-
resolution=data['grid_settings']['regular_grid_resolution']
84-
)
85-
86-
# Create interpolation options with kernel options
87-
interpolation_options = InterpolationOptions(
88-
range=data['interpolation_options'].get('kernel_options', {}).get('range', 1.7),
89-
c_o=data['interpolation_options'].get('kernel_options', {}).get('c_o', 10),
90-
mesh_extraction=data['interpolation_options'].get('mesh_extraction', True),
91-
number_octree_levels=data['interpolation_options'].get('number_octree_levels', 1)
92-
)
9366

94-
# Create GeoModel
67+
# Create GeoModel with default structural frame
9568
model = GeoModel(
9669
name=data['metadata']['name'],
97-
structural_frame=structural_frame,
98-
grid=grid,
99-
interpolation_options=interpolation_options
70+
structural_frame=StructuralFrame.initialize_default_structure(),
71+
grid=Grid(
72+
extent=data['grid_settings']['regular_grid_extent'],
73+
resolution=data['grid_settings']['regular_grid_resolution']
74+
),
75+
interpolation_options=InterpolationOptions(
76+
range=data['interpolation_options'].get('kernel_options', {}).get('range', 1.7),
77+
c_o=data['interpolation_options'].get('kernel_options', {}).get('c_o', 10),
78+
mesh_extraction=data['interpolation_options'].get('mesh_extraction', True),
79+
number_octree_levels=data['interpolation_options'].get('number_octree_levels', 1)
80+
)
10081
)
10182

10283
# Set the metadata with proper dates
@@ -108,15 +89,34 @@ def load_model_from_json(file_path: str):
10889
)
10990
model.meta = model_meta
11091

111-
# Map series to surfaces with structural relations
112-
mapping_object = {series['name']: series['surfaces'] for series in data['series']}
113-
map_stack_to_surfaces(model, mapping_object, series_data=data['series'])
92+
# Load surface points and orientations with the ID to name mapping
93+
surface_points = JsonIO._load_surface_points(data['surface_points'], id_to_name)
94+
orientations = JsonIO._load_orientations(data['orientations'], id_to_name)
95+
96+
# Create structural groups based on series data
97+
model.structural_frame.structural_groups = []
98+
for i, series in enumerate(data['series']):
99+
group = StructuralGroup(
100+
name=series['name'],
101+
elements=[],
102+
structural_relation=StackRelationType[series.get('structural_relation', 'ERODE')]
103+
)
104+
model.structural_frame.structural_groups.append(group)
105+
106+
# Add elements to the group
107+
for surface_name in series['surfaces']:
108+
element = StructuralElement(
109+
name=surface_name,
110+
id=len(group.elements),
111+
surface_points=surface_points.get_surface_points_by_name(surface_name),
112+
orientations=orientations.get_orientations_by_name(surface_name),
113+
color=next(model.structural_frame.color_generator)
114+
)
115+
group.append_element(element)
114116

115-
# Set fault relations after structural groups are set up
116-
if 'fault_relations' in data and data['fault_relations'] is not None:
117-
fault_relations = np.array(data['fault_relations'])
118-
if fault_relations.shape == (len(model.structural_frame.structural_groups), len(model.structural_frame.structural_groups)):
119-
model.structural_frame.fault_relations = fault_relations
117+
# Ensure the last group has the correct structural relation for the basement
118+
if model.structural_frame.structural_groups:
119+
model.structural_frame.structural_groups[-1].structural_relation = StackRelationType.BASEMENT
120120

121121
return model
122122

@@ -131,26 +131,10 @@ def _load_surface_points(surface_points_data: List[SurfacePoint], id_to_name: Op
131131
132132
Returns:
133133
SurfacePointsTable: A new SurfacePointsTable instance
134-
135-
Raises:
136-
ValueError: If the data is invalid or missing required fields
137134
"""
138135
# Import here to avoid circular imports
139136
from gempy.core.data.surface_points import SurfacePointsTable
140137

141-
# Validate data structure
142-
required_fields = {'x', 'y', 'z', 'nugget', 'id'}
143-
for i, sp in enumerate(surface_points_data):
144-
missing_fields = required_fields - set(sp.keys())
145-
if missing_fields:
146-
raise ValueError(f"Missing required fields in surface point {i}: {missing_fields}")
147-
148-
# Validate data types
149-
if not all(isinstance(sp[field], (int, float)) for field in ['x', 'y', 'z', 'nugget']):
150-
raise ValueError(f"Invalid data type in surface point {i}. All coordinates and nugget must be numeric.")
151-
if not isinstance(sp['id'], int):
152-
raise ValueError(f"Invalid data type in surface point {i}. ID must be an integer.")
153-
154138
# Extract coordinates and other data
155139
x = np.array([sp['x'] for sp in surface_points_data])
156140
y = np.array([sp['y'] for sp in surface_points_data])
@@ -184,28 +168,10 @@ def _load_orientations(orientations_data: List[Orientation], id_to_name: Optiona
184168
185169
Returns:
186170
OrientationsTable: A new OrientationsTable instance
187-
188-
Raises:
189-
ValueError: If the data is invalid or missing required fields
190171
"""
191172
# Import here to avoid circular imports
192173
from gempy.core.data.orientations import OrientationsTable
193174

194-
# Validate data structure
195-
required_fields = {'x', 'y', 'z', 'G_x', 'G_y', 'G_z', 'nugget', 'polarity', 'id'}
196-
for i, ori in enumerate(orientations_data):
197-
missing_fields = required_fields - set(ori.keys())
198-
if missing_fields:
199-
raise ValueError(f"Missing required fields in orientation {i}: {missing_fields}")
200-
201-
# Validate data types
202-
if not all(isinstance(ori[field], (int, float)) for field in ['x', 'y', 'z', 'G_x', 'G_y', 'G_z', 'nugget']):
203-
raise ValueError(f"Invalid data type in orientation {i}. All coordinates, gradients, and nugget must be numeric.")
204-
if not isinstance(ori.get('polarity', 1), int) or ori.get('polarity', 1) not in {-1, 1}:
205-
raise ValueError(f"Invalid polarity in orientation {i}. Must be 1 (normal) or -1 (reverse).")
206-
if not isinstance(ori['id'], int):
207-
raise ValueError(f"Invalid data type in orientation {i}. ID must be an integer.")
208-
209175
# Extract coordinates and other data
210176
x = np.array([ori['x'] for ori in orientations_data])
211177
y = np.array([ori['y'] for ori in orientations_data])

0 commit comments

Comments
 (0)