Query a finite rotation of a moving plate relative to any other plate, optionally between two instants in geological time.
This class provides an easy way to query rotations in any of the four combinations of total/stage and equivalent/relative rotations using get_rotation(). Reconstruction trees can also be created at any instant of geological time and these are cached internally depending on a user-specified cache size parameter pass to __init__(). The reconstruction_tree_cache_size parameter of those methods controls the size of an internal least-recently-used cache of reconstruction trees (evicts least recently requested reconstruction tree when a new reconstruction time is requested that does not currently exist in the cache). This enables reconstruction trees associated with different reconstruction times to be re-used instead of re-creating them, provided they have not been evicted from the cache. This benefit also applies when querying rotations with get_rotation() since it, in turn, requests reconstruction trees.
A RotationModel object can be constructed in more than one way...
Create from rotation feature collection(s) and/or rotation filename(s), and an optional reconstruction tree cache size.
|A rotation feature collection, or rotation filename, or rotation feature, or sequence of rotation features, or a sequence (eg, list or tuple) of any combination of those four types|
|FeatureCollection, or string, or Feature, or sequence of Feature, or sequence of any combination of those four types|
|number of reconstruction trees to cache internally|
|cloning rotation features prevents subsequent rotation feature modifications adversely affecting cached rotations (defaults to True) - see ADVANCED note below for more details, otherwise just use default|
|raises:||OpenFileForReadingError if any file is not readable (when filenames specified)|
|raises:||FileFormatNotSupportedError if any file format (identified by the filename extensions) does not support reading (when filenames specified)|
Note that rotation_features can be a rotation FeatureCollection or a rotation filename or a rotation Feature or a sequence of rotation features, or a sequence (eg, list or tuple) of any combination of those four types.
If any rotation filenames are specified then this method uses FeatureCollectionFileFormatRegistry internally to read the rotation files.
Load a rotation file and some rotation adjustments (as a collection of rotation features) into a rotation model:
rotation_adjustments = pygplates.FeatureCollection() ... rotation_model = pygplates.RotationModel(['rotations.rot', rotation_adjustments])
rotation_features = pygplates.FeatureCollection('rotations.rot') while iteration < MAX_ITERATIONS: # We won't be modifying 'rotation_features' until finished using 'rotation_model'. # So we can turn off 'clone_rotation_features'. rotation_model = RotationModel(rotation_features, clone_rotation_features=False) # The last time we use 'rotation_model' in this loop. rotation = rotation_model.get_rotation(...) # Modify 'rotation_features' (eg, adjust rotations stored in features) # in preparation for the next iteration. # But we're not going to use 'rotation_model' again until the next iteration where # we'll create a new RotationModel instance with the updated rotation features. ...
Using this approach (avoiding cloning rotation features) in the implementation of synchronise_crossovers() dramatically improves its performance.
clone_rotation_features is ignored if all rotation features specified in the rotation_features argument are loaded from files (ie, if only filenames are specified).
clone_rotation_features will be deprecated in future when this optimisation is taken care of internally (by cloning only if a modification to its features is detected internally).
Create from an existing rotation model as a convenience.
|an existing rotation model|
This is useful when defining your own function that accepts rotation features or a rotation model. It avoids the hassle of having to explicitly test for each source type:
def my_function(rotation_features_or_model): # The appropriate constructor (__init__) overload is chosen depending on argument type. rotation_model = pygplates.RotationModel(rotation_features_or_model) ...
This constructor just returns a reference to rotation_model because a RotationModel object is immutable (contains no operations or methods that modify its state) and hence a deep copy of rotation_model is not needed.
|__init__(...)||A RotationModel object can be constructed in more than one way...|
|get_reconstruction_tree(reconstruction_time, ...)||Return the reconstruction tree associated with the specified instant of geological time and anchored plate id.|
|get_rotation(to_time, moving_plate_id, ...)||Return the finite rotation that rotates from the fixed_plate_id plate to the moving_plate_id plate and from the time from_time to the time to_time.|
Return the reconstruction tree associated with the specified instant of geological time and anchored plate id.
If the reconstruction tree for the specified reconstruction time and anchored plate id is currently in the internal cache then it is returned, otherwise a new reconstruction tree is created and stored in the cache (after evicting the reconstruction tree associated with the least recently requested reconstruction time and anchored plate id if necessary).
Return the finite rotation that rotates from the fixed_plate_id plate to the moving_plate_id plate and from the time from_time to the time to_time.
FiniteRotation, or None (if use_identity_for_missing_plate_ids is False)
This method conveniently handles all four combinations of total/stage and equivalent/relative rotations normally handled by:
If fixed_plate_id is not specified then it defaults to anchor_plate_id (which itself defaults to zero). Normally it is sufficient to specify fixed_plate_id (for a relative rotation) and leave anchor_plate_id as its default (zero). However if there is no plate circuit path from the default anchor plate (zero) to either moving_plate_id or fixed_plate_id, but there is a path from fixed_plate_id to moving_plate_id, then the correct result will require setting anchor_plate_id to fixed_plate_id. See Plate reconstruction hierarchy for an overview of plate circuit paths.
If there is no plate circuit path from moving_plate_id (and optionally fixed_plate_id) to the anchor plate (at times to_time and optionally from_time) then an identity rotation is returned if use_identity_for_missing_plate_ids is True, otherwise None is returned. See Plate reconstruction hierarchy for details on how a plate id can go missing and how to work around it.
This method essentially does the following:
def get_rotation(rotation_model, to_time, moving_plate_id, from_time=0, fixed_plate_id=None, anchor_plate_id=0): if from_time == 0: if fixed_plate_id is None: return rotation_model.get_reconstruction_tree(to_time, anchor_plate_id).get_equivalent_total_rotation(moving_plate_id) return rotation_model.get_reconstruction_tree(to_time, anchor_plate_id).get_relative_total_rotation(moving_plate_id, fixed_plate_id) if fixed_plate_id is None: return pygplates.ReconstructionTree.get_equivalent_stage_rotation( rotation_model.get_reconstruction_tree(from_time, anchor_plate_id), rotation_model.get_reconstruction_tree(to_time, anchor_plate_id), moving_plate_id) return pygplates.ReconstructionTree.get_relative_stage_rotation( rotation_model.get_reconstruction_tree(from_time, anchor_plate_id), rotation_model.get_reconstruction_tree(to_time, anchor_plate_id), moving_plate_id, fixed_plate_id)