GPlates / gplately

GPlately is a Python package to interrogate tectonic plate reconstructions.
https://gplates.github.io/gplately/
GNU General Public License v2.0
55 stars 11 forks source link

`gplately.pygplates.RotationModel` does not accept a `RotationModel` as input #180

Closed cpalfonso closed 1 month ago

cpalfonso commented 1 month ago

pygplates.RotationModel accepts another instance of RotationModel as input (i.e. copy = pygplates.RotationModel(original)). However, gplately.pygplates.RotationModel currently encounters an error:

Boost.Python.ArgumentError: Python argument types in
    RotationModel.__init__(RotationModel, RotationModel)
did not match C++ signature:
    __init__(boost::python::api::object, GPlatesUtils::non_null_intrusive_ptr<GPlatesApi::RotationModel, GPlatesUtils::NullIntrusivePointerHandler> rotation_model)
    __init__(boost::python::api::object, GPlatesUtils::non_null_intrusive_ptr<GPlatesApi::RotationModel, GPlatesUtils::NullIntrusivePointerHandler> rotation_model, unsigned int reconstruction_tree_cache_size=2, boost::optional<unsigned long> default_anchor_plate_id=None)
    __init__(boost::python::api::object, GPlatesApi::FeatureCollectionSequenceFunctionArgument rotation_features, unsigned int reconstruction_tree_cache_size=150, bool extend_total_reconstruction_poles_to_distant_past=False, unsigned long default_anchor_plate_id=0)
    __init__(boost::python::api::object, GPlatesApi::FeatureCollectionSequenceFunctionArgument rotation_features, unsigned int reconstruction_tree_cache_size=150, bool clone_rotation_features=True)

The first two overloads allow the first argument to be a RotationModel, but the extend_total_reconstruction_poles_to_distant_past argument only exists in the third overload; this argument is passed in the constructor for gplately.pygplates.RotationModel: https://github.com/GPlates/gplately/blob/725da386db3ac8fb2b60fe31825013fcc08f23c8/gplately/pygplates.py#L26-L31 The problem could be fixed by only passing the extend_total_reconstruction_poles_to_distant_past argument to the constructor if rotation_features is not already a RotationModel.

Allowing the constructor to accept another instance of RotationModel simplifies writing functions with unknown inputs, since you can write this:

from gplately.pygplates import RotationModel

def func(rotation_model):
    rotation_model = RotationModel(rotation_model)
    [...]

instead of having to remember to write this:

import pygplates
from gplately.pygplates import RotationModel

def func(rotation_model):
    if not isinstance(rotation_model, pygplates.RotationModel):
        rotation_model = RotationModel(rotation_model)
    [...]

This change would also allow the direct conversion of a pygplates.RotationModel instance to a gplately.pygplates.RotationModel:

pygplates_model = pygplates.RotationModel(rotation_files)
gplately_model = gplately.pygplates.RotationModel(pygplates_model)