Create conjugate isochrons from a ridge
This example creates a conjugate pair of isochrons from a mid-ocean ridge at each specified geological time in a series.
Sample code
import pygplates
# Load one or more rotation files into a rotation model.
rotation_model = pygplates.RotationModel('rotations.rot')
# Load the mid-ocean ridge features.
ridge_features = pygplates.FeatureCollection('ridges.gpml')
# The times at which to create isochrons.
isochron_creation_times = [40, 30, 20, 10, 0]
# We'll store the created isochrons here - later we'll write it to a file.
isochron_feature_collection = pygplates.FeatureCollection()
# Iterate over the ridge features.
for ridge_feature in ridge_features:
# Get the ridge left and right plate ids, and time of appearance.
left_plate_id = ridge_feature.get_left_plate()
right_plate_id = ridge_feature.get_right_plate()
time_of_appearance, time_of_disappearance = ridge_feature.get_valid_time()
# Iterate over our list of creation times for the left/right isochrons.
for isochron_creation_time in isochron_creation_times:
# If creation time is later than ridge birth time then we can create an isochron.
if isochron_creation_time < time_of_appearance:
# Reconstruct the mid-ocean ridge to isochron creation time.
# The ridge geometry will be in the same position as the left/right isochrons at that time.
reconstructed_ridges = []
pygplates.reconstruct(ridge_feature, rotation_model, reconstructed_ridges, isochron_creation_time)
# Get the isochron geometry from the ridge reconstruction.
# This is the geometry at 'isochron_creation_time' (not present day).
isochron_geometry_at_creation_time = [reconstructed_ridge.get_reconstructed_geometry()
for reconstructed_ridge in reconstructed_ridges]
# Create the left and right isochrons.
# Since they are conjugates they have swapped left and right plate IDs.
# And reverse reconstruct the mid-ocean ridge geometries to present day.
left_isochron_feature = pygplates.Feature.create_reconstructable_feature(
pygplates.FeatureType.gpml_isochron,
isochron_geometry_at_creation_time,
name = ridge_feature.get_name(None),
description = ridge_feature.get_description(None),
valid_time = (isochron_creation_time, 0),
reconstruction_plate_id = left_plate_id,
conjugate_plate_id = right_plate_id,
reverse_reconstruct = (rotation_model, isochron_creation_time))
right_isochron_feature = pygplates.Feature.create_reconstructable_feature(
pygplates.FeatureType.gpml_isochron,
isochron_geometry_at_creation_time,
name = ridge_feature.get_name(None),
description = ridge_feature.get_description(None),
valid_time = (isochron_creation_time, 0),
reconstruction_plate_id = right_plate_id,
conjugate_plate_id = left_plate_id,
reverse_reconstruct = (rotation_model, isochron_creation_time))
# Add isochrons to feature collection.
isochron_feature_collection.add(left_isochron_feature)
isochron_feature_collection.add(right_isochron_feature)
# Write the isochrons to a new file.
isochron_feature_collection.write('isochrons.gpml')
Details
The rotations are loaded from a rotation file into a pygplates.RotationModel
.
rotation_model = pygplates.RotationModel('rotations.rot')
The ridge features are loaded into a pygplates.FeatureCollection
.
ridge_features = pygplates.FeatureCollection('ridges.gpml')
The plate IDs and time period are obtained using pygplates.Feature.get_left_plate()
,
pygplates.Feature.get_right_plate()
and pygplates.Feature.get_valid_time()
.
left_plate_id = ridge_feature.get_left_plate()
right_plate_id = ridge_feature.get_right_plate()
time_of_appearance, time_of_disappearance = ridge_feature.get_valid_time()
Smaller time values are closer to present day (younger).
if isochron_creation_time < time_of_appearance:
The ridges are reconstructed to their locations at time ‘isochron_creation_time’ using
pygplates.reconstruct()
.
reconstructed_ridges = []
pygplates.reconstruct(ridge_feature, rotation_model, reconstructed_ridges, isochron_creation_time)
A Python list comprehension is used to build a list of pygplates.GeometryOnSphere
from a
list of pygplates.ReconstructedFeatureGeometry
.
isochron_geometry_at_creation_time = [reconstructed_ridge.get_reconstructed_geometry()
for reconstructed_ridge in reconstructed_ridges]
Isochron features are created using
pygplates.Feature.create_reconstructable_feature()
.
left_isochron_feature = pygplates.Feature.create_reconstructable_feature(
pygplates.FeatureType.gpml_isochron,
isochron_geometry_at_creation_time,
name = ridge_feature.get_name(None),
description = ridge_feature.get_description(None),
valid_time = (isochron_creation_time, 0),
reconstruction_plate_id = left_plate_id,
conjugate_plate_id = right_plate_id,
reverse_reconstruct = (rotation_model, isochron_creation_time))
The reverse_reconstruct
parameter is needed because all features
must store their geometry in present day coordinates which means reverse reconstructing from
isochron_creation_time
to present day using the rotation model.
Note
The use of None
in, for example, ridge_feature.get_name(None)
results in a
name
property only getting created if the ridge feature has a name.
And finally the isochrons are saved to a new file using pygplates.FeatureCollection.write()
.
isochron_feature_collection.write('isochrons.gpml')
Advanced
If we want to be a bit more robust then we can check that our ridge features are actually ridges and we can make sure they contain left/right plate IDs and a time of appearance/disappearance:
...
# Iterate over the ridge features.
for ridge_feature in ridge_features:
# Ignore anything that's not a mid-ocean ridge.
if ridge_feature.get_feature_type() != pygplates.FeatureType.gpml_mid_ocean_ridge:
continue
# Get the ridge left and right plate ids, and time of appearance.
# We don't need to specify 'None', but if we do then it allows us to test if the ridge feature
# is missing plate IDs or begin/end time period.
left_plate_id = ridge_feature.get_left_plate(None)
right_plate_id = ridge_feature.get_right_plate(None)
valid_time = ridge_feature.get_valid_time(None)
# Ignore mid-ocean ridges that don't have a left and right plate id and time of appearance.
if (left_plate_id is None or
right_plate_id is None or
valid_time is None):
continue
# Extract time of appearance/disappearance from the tuple.
time_of_appearance, time_of_disappearance = valid_time
...
By specifying None
in:
left_plate_id = ridge_feature.get_left_plate(None)
right_plate_id = ridge_feature.get_right_plate(None)
valid_time = ridge_feature.get_valid_time(None)
None
returned to us if the feature property (eg, left plate ID) is missing
in the ridge feature.None
then a default value would be returned if a property
was missing. For get_left_plate()
and get_right_plate()
this is plate ID 0 and for
get_valid_time()
this is a time period from distant past to distant future.