gtrack 0.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- gtrack/__init__.py +137 -0
- gtrack/boundaries.py +396 -0
- gtrack/config.py +202 -0
- gtrack/geometry.py +348 -0
- gtrack/hpc_integration.py +851 -0
- gtrack/initial_conditions.py +255 -0
- gtrack/io_formats.py +477 -0
- gtrack/logging.py +193 -0
- gtrack/mesh.py +101 -0
- gtrack/mor_seeds.py +390 -0
- gtrack/point_rotation.py +836 -0
- gtrack/polygon_filter.py +223 -0
- gtrack/spatial.py +397 -0
- gtrack-0.3.0.dist-info/METADATA +66 -0
- gtrack-0.3.0.dist-info/RECORD +17 -0
- gtrack-0.3.0.dist-info/WHEEL +5 -0
- gtrack-0.3.0.dist-info/top_level.txt +1 -0
gtrack/mesh.py
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Sphere mesh generation using Fibonacci spiral distribution.
|
|
3
|
+
|
|
4
|
+
This module provides functions to create approximately uniform point
|
|
5
|
+
distributions on a sphere using the Fibonacci spiral algorithm.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import numpy as np
|
|
9
|
+
from typing import Tuple
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def create_sphere_mesh_xyz(n_points: int, radius: float = 1.0) -> np.ndarray:
|
|
13
|
+
"""
|
|
14
|
+
Create approximately uniform points on a sphere using Fibonacci spiral.
|
|
15
|
+
|
|
16
|
+
The Fibonacci spiral algorithm distributes points approximately evenly
|
|
17
|
+
over the surface of a sphere using the golden angle. This avoids the
|
|
18
|
+
pole clustering problem of regular lat/lon grids.
|
|
19
|
+
|
|
20
|
+
Parameters
|
|
21
|
+
----------
|
|
22
|
+
n_points : int
|
|
23
|
+
Number of points to generate on the sphere's surface.
|
|
24
|
+
radius : float, default=1.0
|
|
25
|
+
Radius of the sphere (1.0 for unit sphere, or Earth radius in meters).
|
|
26
|
+
|
|
27
|
+
Returns
|
|
28
|
+
-------
|
|
29
|
+
xyz : np.ndarray
|
|
30
|
+
XYZ coordinates, shape (n_points, 3).
|
|
31
|
+
|
|
32
|
+
Examples
|
|
33
|
+
--------
|
|
34
|
+
>>> xyz = create_sphere_mesh_xyz(10000)
|
|
35
|
+
>>> xyz.shape
|
|
36
|
+
(10000, 3)
|
|
37
|
+
>>> xyz = create_sphere_mesh_xyz(40000, radius=6.3781e6) # Earth radius
|
|
38
|
+
>>> xyz.shape
|
|
39
|
+
(40000, 3)
|
|
40
|
+
"""
|
|
41
|
+
if n_points < 1:
|
|
42
|
+
raise ValueError(f"n_points must be >= 1, got {n_points}")
|
|
43
|
+
|
|
44
|
+
# Golden angle in radians
|
|
45
|
+
phi = np.pi * (3.0 - np.sqrt(5.0))
|
|
46
|
+
|
|
47
|
+
# Generate indices
|
|
48
|
+
indices = np.arange(n_points)
|
|
49
|
+
|
|
50
|
+
# Y coordinates: evenly spaced from 1 to -1
|
|
51
|
+
y = 1.0 - (indices / (n_points - 1)) * 2.0 if n_points > 1 else np.array([0.0])
|
|
52
|
+
|
|
53
|
+
# Radius at each y (distance from y-axis)
|
|
54
|
+
r = np.sqrt(1.0 - y * y)
|
|
55
|
+
|
|
56
|
+
# Angle for each point (golden angle spiral)
|
|
57
|
+
theta = phi * indices
|
|
58
|
+
|
|
59
|
+
# Cartesian coordinates on unit sphere
|
|
60
|
+
x = np.cos(theta) * r
|
|
61
|
+
z = np.sin(theta) * r
|
|
62
|
+
|
|
63
|
+
# Stack and scale by radius
|
|
64
|
+
xyz = np.column_stack([x, y, z]) * radius
|
|
65
|
+
|
|
66
|
+
return xyz
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def create_sphere_mesh_latlon(n_points: int) -> Tuple[np.ndarray, np.ndarray]:
|
|
70
|
+
"""
|
|
71
|
+
Create approximately uniform points on a sphere returning lat/lon coordinates.
|
|
72
|
+
|
|
73
|
+
Parameters
|
|
74
|
+
----------
|
|
75
|
+
n_points : int
|
|
76
|
+
Number of points to generate.
|
|
77
|
+
|
|
78
|
+
Returns
|
|
79
|
+
-------
|
|
80
|
+
lats : np.ndarray
|
|
81
|
+
Latitudes in degrees, shape (n_points,). Range: -90 to 90.
|
|
82
|
+
lons : np.ndarray
|
|
83
|
+
Longitudes in degrees, shape (n_points,). Range: -180 to 180.
|
|
84
|
+
|
|
85
|
+
Examples
|
|
86
|
+
--------
|
|
87
|
+
>>> lats, lons = create_sphere_mesh_latlon(10000)
|
|
88
|
+
>>> len(lats)
|
|
89
|
+
10000
|
|
90
|
+
>>> lats.min() >= -90 and lats.max() <= 90
|
|
91
|
+
True
|
|
92
|
+
"""
|
|
93
|
+
xyz = create_sphere_mesh_xyz(n_points, radius=1.0)
|
|
94
|
+
|
|
95
|
+
# Convert XYZ to lat/lon
|
|
96
|
+
x, y, z = xyz[:, 0], xyz[:, 1], xyz[:, 2]
|
|
97
|
+
|
|
98
|
+
lats = np.degrees(np.arcsin(np.clip(y, -1.0, 1.0)))
|
|
99
|
+
lons = np.degrees(np.arctan2(z, x))
|
|
100
|
+
|
|
101
|
+
return lats, lons
|
gtrack/mor_seeds.py
ADDED
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
"""
|
|
2
|
+
MOR seed point generation using stage rotation (GPlately approach).
|
|
3
|
+
|
|
4
|
+
This module provides functions to generate new seafloor points at
|
|
5
|
+
mid-ocean ridges using the stage rotation between spreading plates.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import numpy as np
|
|
9
|
+
from typing import List, Optional, Tuple
|
|
10
|
+
|
|
11
|
+
import pygplates
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def get_stage_rotation_for_reconstructed_geometry(
|
|
15
|
+
spreading_feature,
|
|
16
|
+
rotation_model: pygplates.RotationModel,
|
|
17
|
+
spreading_time: float,
|
|
18
|
+
return_left_right_plates: bool = False,
|
|
19
|
+
):
|
|
20
|
+
"""
|
|
21
|
+
Find the stage rotation of a spreading feature in its reconstructed geometry frame.
|
|
22
|
+
|
|
23
|
+
The returned stage rotation can be used to find the spreading direction
|
|
24
|
+
(stage pole) relative to the reconstructed mid-ocean ridge geometry.
|
|
25
|
+
|
|
26
|
+
Parameters
|
|
27
|
+
----------
|
|
28
|
+
spreading_feature : pygplates.Feature
|
|
29
|
+
A MidOceanRidge feature with left/right plate IDs.
|
|
30
|
+
rotation_model : pygplates.RotationModel
|
|
31
|
+
The rotation model.
|
|
32
|
+
spreading_time : float
|
|
33
|
+
Time at which spreading is happening (Ma).
|
|
34
|
+
return_left_right_plates : bool, default=False
|
|
35
|
+
If True, return (stage_rotation, left_plate_id, right_plate_id).
|
|
36
|
+
|
|
37
|
+
Returns
|
|
38
|
+
-------
|
|
39
|
+
pygplates.FiniteRotation or tuple or None
|
|
40
|
+
The stage rotation in the frame of the reconstructed geometry.
|
|
41
|
+
If return_left_right_plates is True, returns a 3-tuple.
|
|
42
|
+
Returns None if the feature doesn't have valid plate IDs.
|
|
43
|
+
|
|
44
|
+
Notes
|
|
45
|
+
-----
|
|
46
|
+
This function matches GPlately's implementation in
|
|
47
|
+
`ptt.separate_ridge_transform_segments.get_stage_rotation_for_reconstructed_geometry`.
|
|
48
|
+
|
|
49
|
+
The stage rotation is computed as:
|
|
50
|
+
R(0->t, A->Left) * R(t+1->t, Left->Right) * R(0->t, A->Left)^-1
|
|
51
|
+
|
|
52
|
+
This transforms the raw stage rotation into the reference frame of the
|
|
53
|
+
reconstructed geometry so that the stage pole can be directly compared
|
|
54
|
+
to the ridge geometry.
|
|
55
|
+
"""
|
|
56
|
+
# Check for left/right plate IDs (required for MidOceanRidge features)
|
|
57
|
+
left_plate_id = spreading_feature.get_left_plate(None)
|
|
58
|
+
right_plate_id = spreading_feature.get_right_plate(None)
|
|
59
|
+
|
|
60
|
+
if left_plate_id is None or right_plate_id is None:
|
|
61
|
+
return None
|
|
62
|
+
|
|
63
|
+
# Get stage rotation from right plate to left plate over 1 Myr
|
|
64
|
+
# This gives the relative motion between the two plates
|
|
65
|
+
stage_rotation = rotation_model.get_rotation(
|
|
66
|
+
spreading_time, right_plate_id, spreading_time + 1, left_plate_id
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
if stage_rotation.represents_identity_rotation():
|
|
70
|
+
return None
|
|
71
|
+
|
|
72
|
+
# Transform stage rotation to the reference frame of the reconstructed geometry
|
|
73
|
+
# This allows the stage pole to be directly compared to the ridge geometry
|
|
74
|
+
from_stage_pole_reference_frame = rotation_model.get_rotation(
|
|
75
|
+
spreading_time, left_plate_id
|
|
76
|
+
)
|
|
77
|
+
to_stage_pole_reference_frame = from_stage_pole_reference_frame.get_inverse()
|
|
78
|
+
|
|
79
|
+
stage_rotation = (
|
|
80
|
+
from_stage_pole_reference_frame
|
|
81
|
+
* stage_rotation
|
|
82
|
+
* to_stage_pole_reference_frame
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
if return_left_right_plates:
|
|
86
|
+
return stage_rotation, left_plate_id, right_plate_id
|
|
87
|
+
|
|
88
|
+
return stage_rotation
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def generate_mor_seeds(
|
|
92
|
+
time: float,
|
|
93
|
+
topology_features,
|
|
94
|
+
rotation_model: pygplates.RotationModel,
|
|
95
|
+
ridge_sampling_degrees: float = 0.5,
|
|
96
|
+
spreading_offset_degrees: float = 0.01,
|
|
97
|
+
) -> Tuple[np.ndarray, np.ndarray]:
|
|
98
|
+
"""
|
|
99
|
+
Generate MOR seed points using stage rotation approach.
|
|
100
|
+
|
|
101
|
+
For each mid-ocean ridge segment, creates pairs of points offset
|
|
102
|
+
perpendicular to the ridge using the stage rotation pole. This
|
|
103
|
+
ensures new crust is created on both sides of the spreading center.
|
|
104
|
+
|
|
105
|
+
Parameters
|
|
106
|
+
----------
|
|
107
|
+
time : float
|
|
108
|
+
Current geological time (Ma).
|
|
109
|
+
topology_features : pygplates.FeatureCollection or list
|
|
110
|
+
Topology feature files or collection.
|
|
111
|
+
rotation_model : pygplates.RotationModel
|
|
112
|
+
The rotation model.
|
|
113
|
+
ridge_sampling_degrees : float, default=0.5
|
|
114
|
+
Resolution for tessellating ridges in degrees (~50 km at equator).
|
|
115
|
+
spreading_offset_degrees : float, default=0.01
|
|
116
|
+
Angle in degrees to rotate points off the ridge (~1 km).
|
|
117
|
+
GPlately uses 0.01 degrees.
|
|
118
|
+
|
|
119
|
+
Returns
|
|
120
|
+
-------
|
|
121
|
+
lats : np.ndarray
|
|
122
|
+
Latitudes of seed points in degrees.
|
|
123
|
+
lons : np.ndarray
|
|
124
|
+
Longitudes of seed points in degrees.
|
|
125
|
+
|
|
126
|
+
Notes
|
|
127
|
+
-----
|
|
128
|
+
The algorithm:
|
|
129
|
+
1. Resolve topologies at the current time
|
|
130
|
+
2. For each MidOceanRidge boundary section:
|
|
131
|
+
- Get the stage rotation (relative motion between plates)
|
|
132
|
+
- Extract the stage pole (spreading axis)
|
|
133
|
+
- Tessellate the ridge at the sampling resolution
|
|
134
|
+
- For each ridge point (excluding endpoints):
|
|
135
|
+
- Rotate +spreading_offset_degrees around stage pole
|
|
136
|
+
- Rotate -spreading_offset_degrees around stage pole
|
|
137
|
+
- Add both rotated points (creating symmetric spreading)
|
|
138
|
+
3. All seed points have age=0 (just formed at ridge)
|
|
139
|
+
|
|
140
|
+
This matches GPlately's `_generate_mid_ocean_ridge_points` function.
|
|
141
|
+
|
|
142
|
+
Examples
|
|
143
|
+
--------
|
|
144
|
+
>>> lats, lons = generate_mor_seeds(
|
|
145
|
+
... time=100.0,
|
|
146
|
+
... topology_features=topology_features,
|
|
147
|
+
... rotation_model=rotation_model
|
|
148
|
+
... )
|
|
149
|
+
>>> ages = np.zeros(len(lats)) # New crust has age 0
|
|
150
|
+
"""
|
|
151
|
+
# Resolve topologies at the current time
|
|
152
|
+
resolved_topologies = []
|
|
153
|
+
shared_boundary_sections = []
|
|
154
|
+
pygplates.resolve_topologies(
|
|
155
|
+
topology_features,
|
|
156
|
+
rotation_model,
|
|
157
|
+
resolved_topologies,
|
|
158
|
+
time,
|
|
159
|
+
shared_boundary_sections,
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
all_lats = []
|
|
163
|
+
all_lons = []
|
|
164
|
+
|
|
165
|
+
# Process each boundary section
|
|
166
|
+
for shared_boundary_section in shared_boundary_sections:
|
|
167
|
+
# Only process MidOceanRidge features
|
|
168
|
+
if (
|
|
169
|
+
shared_boundary_section.get_feature().get_feature_type()
|
|
170
|
+
!= pygplates.FeatureType.create_gpml("MidOceanRidge")
|
|
171
|
+
):
|
|
172
|
+
continue
|
|
173
|
+
|
|
174
|
+
spreading_feature = shared_boundary_section.get_feature()
|
|
175
|
+
|
|
176
|
+
# Get stage rotation for this spreading feature
|
|
177
|
+
stage_rotation = get_stage_rotation_for_reconstructed_geometry(
|
|
178
|
+
spreading_feature, rotation_model, time
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
if stage_rotation is None:
|
|
182
|
+
# Skip if we can't get a valid stage rotation
|
|
183
|
+
continue
|
|
184
|
+
|
|
185
|
+
# Get the stage pole (spreading axis)
|
|
186
|
+
stage_pole, _ = stage_rotation.get_euler_pole_and_angle()
|
|
187
|
+
|
|
188
|
+
# Create rotations to offset points from ridge
|
|
189
|
+
# One rotates "left", the other "right" relative to spreading direction
|
|
190
|
+
rotate_one_way = pygplates.FiniteRotation(
|
|
191
|
+
stage_pole, np.radians(spreading_offset_degrees)
|
|
192
|
+
)
|
|
193
|
+
rotate_opposite_way = rotate_one_way.get_inverse()
|
|
194
|
+
|
|
195
|
+
# Process each sub-segment of the ridge
|
|
196
|
+
for shared_sub_segment in shared_boundary_section.get_shared_sub_segments():
|
|
197
|
+
# Tessellate the ridge segment
|
|
198
|
+
mor_points = pygplates.MultiPointOnSphere(
|
|
199
|
+
shared_sub_segment.get_resolved_geometry().to_tessellated(
|
|
200
|
+
np.radians(ridge_sampling_degrees)
|
|
201
|
+
)
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
# Get the points (skip first and last to avoid ridge endpoints)
|
|
205
|
+
points = mor_points.get_points()
|
|
206
|
+
if len(points) <= 2:
|
|
207
|
+
continue
|
|
208
|
+
|
|
209
|
+
# Get interior points (skip endpoints)
|
|
210
|
+
interior_points = points[1:-1]
|
|
211
|
+
|
|
212
|
+
# Batch rotate all interior points (single C++ call per rotation)
|
|
213
|
+
interior_mp = pygplates.MultiPointOnSphere(interior_points)
|
|
214
|
+
rotated_left = rotate_one_way * interior_mp
|
|
215
|
+
rotated_right = rotate_opposite_way * interior_mp
|
|
216
|
+
|
|
217
|
+
# Extract lat/lon from rotated points
|
|
218
|
+
for p_left, p_right in zip(rotated_left.get_points(), rotated_right.get_points()):
|
|
219
|
+
lat_left, lon_left = p_left.to_lat_lon()
|
|
220
|
+
lat_right, lon_right = p_right.to_lat_lon()
|
|
221
|
+
all_lats.extend([lat_left, lat_right])
|
|
222
|
+
all_lons.extend([lon_left, lon_right])
|
|
223
|
+
|
|
224
|
+
return np.array(all_lats), np.array(all_lons)
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
def generate_mor_seeds_with_plate_ids(
|
|
228
|
+
time: float,
|
|
229
|
+
topology_features,
|
|
230
|
+
rotation_model: pygplates.RotationModel,
|
|
231
|
+
ridge_sampling_degrees: float = 0.5,
|
|
232
|
+
spreading_offset_degrees: float = 0.01,
|
|
233
|
+
) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
|
|
234
|
+
"""
|
|
235
|
+
Generate MOR seed points with explicit plate ID assignments.
|
|
236
|
+
|
|
237
|
+
Like generate_mor_seeds, but also returns the plate ID for each point
|
|
238
|
+
based on which side of the ridge it's on (left or right plate).
|
|
239
|
+
|
|
240
|
+
Parameters
|
|
241
|
+
----------
|
|
242
|
+
time : float
|
|
243
|
+
Current geological time (Ma).
|
|
244
|
+
topology_features : pygplates.FeatureCollection or list
|
|
245
|
+
Topology feature files or collection.
|
|
246
|
+
rotation_model : pygplates.RotationModel
|
|
247
|
+
The rotation model.
|
|
248
|
+
ridge_sampling_degrees : float, default=0.5
|
|
249
|
+
Resolution for tessellating ridges in degrees.
|
|
250
|
+
spreading_offset_degrees : float, default=0.01
|
|
251
|
+
Angle in degrees to rotate points off the ridge.
|
|
252
|
+
|
|
253
|
+
Returns
|
|
254
|
+
-------
|
|
255
|
+
lats : np.ndarray
|
|
256
|
+
Latitudes of seed points in degrees.
|
|
257
|
+
lons : np.ndarray
|
|
258
|
+
Longitudes of seed points in degrees.
|
|
259
|
+
plate_ids : np.ndarray
|
|
260
|
+
Plate IDs for each point (left plate or right plate).
|
|
261
|
+
|
|
262
|
+
Notes
|
|
263
|
+
-----
|
|
264
|
+
The plate IDs are assigned based on which side of the ridge each
|
|
265
|
+
point is on. Points rotated in the "left" direction get the left
|
|
266
|
+
plate ID, and points rotated in the "right" direction get the right
|
|
267
|
+
plate ID.
|
|
268
|
+
|
|
269
|
+
This is useful for the first time step when we need to explicitly
|
|
270
|
+
assign plate IDs rather than querying topology.
|
|
271
|
+
"""
|
|
272
|
+
# Resolve topologies at the current time
|
|
273
|
+
resolved_topologies = []
|
|
274
|
+
shared_boundary_sections = []
|
|
275
|
+
pygplates.resolve_topologies(
|
|
276
|
+
topology_features,
|
|
277
|
+
rotation_model,
|
|
278
|
+
resolved_topologies,
|
|
279
|
+
time,
|
|
280
|
+
shared_boundary_sections,
|
|
281
|
+
)
|
|
282
|
+
|
|
283
|
+
all_lats = []
|
|
284
|
+
all_lons = []
|
|
285
|
+
all_plate_ids = []
|
|
286
|
+
|
|
287
|
+
# Process each boundary section
|
|
288
|
+
for shared_boundary_section in shared_boundary_sections:
|
|
289
|
+
# Only process MidOceanRidge features
|
|
290
|
+
if (
|
|
291
|
+
shared_boundary_section.get_feature().get_feature_type()
|
|
292
|
+
!= pygplates.FeatureType.create_gpml("MidOceanRidge")
|
|
293
|
+
):
|
|
294
|
+
continue
|
|
295
|
+
|
|
296
|
+
spreading_feature = shared_boundary_section.get_feature()
|
|
297
|
+
|
|
298
|
+
# Get stage rotation with plate IDs
|
|
299
|
+
result = get_stage_rotation_for_reconstructed_geometry(
|
|
300
|
+
spreading_feature, rotation_model, time, return_left_right_plates=True
|
|
301
|
+
)
|
|
302
|
+
|
|
303
|
+
if result is None:
|
|
304
|
+
continue
|
|
305
|
+
|
|
306
|
+
stage_rotation, left_plate_id, right_plate_id = result
|
|
307
|
+
|
|
308
|
+
# Get the stage pole
|
|
309
|
+
stage_pole, _ = stage_rotation.get_euler_pole_and_angle()
|
|
310
|
+
|
|
311
|
+
# Create rotations to offset points
|
|
312
|
+
rotate_one_way = pygplates.FiniteRotation(
|
|
313
|
+
stage_pole, np.radians(spreading_offset_degrees)
|
|
314
|
+
)
|
|
315
|
+
rotate_opposite_way = rotate_one_way.get_inverse()
|
|
316
|
+
|
|
317
|
+
# Process each sub-segment
|
|
318
|
+
for shared_sub_segment in shared_boundary_section.get_shared_sub_segments():
|
|
319
|
+
mor_points = pygplates.MultiPointOnSphere(
|
|
320
|
+
shared_sub_segment.get_resolved_geometry().to_tessellated(
|
|
321
|
+
np.radians(ridge_sampling_degrees)
|
|
322
|
+
)
|
|
323
|
+
)
|
|
324
|
+
|
|
325
|
+
points = mor_points.get_points()
|
|
326
|
+
if len(points) <= 2:
|
|
327
|
+
continue
|
|
328
|
+
|
|
329
|
+
for point in points[1:-1]:
|
|
330
|
+
# Create points on each side
|
|
331
|
+
point_left = rotate_one_way * point
|
|
332
|
+
point_right = rotate_opposite_way * point
|
|
333
|
+
|
|
334
|
+
lat_left, lon_left = point_left.to_lat_lon()
|
|
335
|
+
lat_right, lon_right = point_right.to_lat_lon()
|
|
336
|
+
|
|
337
|
+
# Add with respective plate IDs
|
|
338
|
+
all_lats.append(lat_left)
|
|
339
|
+
all_lons.append(lon_left)
|
|
340
|
+
all_plate_ids.append(left_plate_id)
|
|
341
|
+
|
|
342
|
+
all_lats.append(lat_right)
|
|
343
|
+
all_lons.append(lon_right)
|
|
344
|
+
all_plate_ids.append(right_plate_id)
|
|
345
|
+
|
|
346
|
+
return np.array(all_lats), np.array(all_lons), np.array(all_plate_ids)
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
def get_ridge_geometries(
|
|
350
|
+
time: float,
|
|
351
|
+
topology_features,
|
|
352
|
+
rotation_model: pygplates.RotationModel,
|
|
353
|
+
) -> List[pygplates.PolylineOnSphere]:
|
|
354
|
+
"""
|
|
355
|
+
Extract mid-ocean ridge geometries at a given time.
|
|
356
|
+
|
|
357
|
+
Parameters
|
|
358
|
+
----------
|
|
359
|
+
time : float
|
|
360
|
+
Geological time (Ma).
|
|
361
|
+
topology_features : pygplates.FeatureCollection or list
|
|
362
|
+
Topology features.
|
|
363
|
+
rotation_model : pygplates.RotationModel
|
|
364
|
+
Rotation model.
|
|
365
|
+
|
|
366
|
+
Returns
|
|
367
|
+
-------
|
|
368
|
+
list of pygplates.PolylineOnSphere
|
|
369
|
+
Ridge geometries at the specified time.
|
|
370
|
+
"""
|
|
371
|
+
resolved_topologies = []
|
|
372
|
+
shared_boundary_sections = []
|
|
373
|
+
pygplates.resolve_topologies(
|
|
374
|
+
topology_features,
|
|
375
|
+
rotation_model,
|
|
376
|
+
resolved_topologies,
|
|
377
|
+
time,
|
|
378
|
+
shared_boundary_sections,
|
|
379
|
+
)
|
|
380
|
+
|
|
381
|
+
ridge_geometries = []
|
|
382
|
+
for shared_boundary_section in shared_boundary_sections:
|
|
383
|
+
if (
|
|
384
|
+
shared_boundary_section.get_feature().get_feature_type()
|
|
385
|
+
== pygplates.FeatureType.create_gpml("MidOceanRidge")
|
|
386
|
+
):
|
|
387
|
+
for shared_sub_segment in shared_boundary_section.get_shared_sub_segments():
|
|
388
|
+
ridge_geometries.append(shared_sub_segment.get_resolved_geometry())
|
|
389
|
+
|
|
390
|
+
return ridge_geometries
|