Module gplately.gpml
Tools for manipulating GPML (.gpml, .gpmlz) files and
pygplates.Feature and pygplates.FeatureCollection objects.
The following functions are defined here:
- create_feature_dict
- extract_feature
- get_topological_references
- is_topological
Expand source code
r"""Tools for manipulating GPML (`.gpml`, `.gpmlz`) files and
`pygplates.Feature` and `pygplates.FeatureCollection` objects.
The following functions are defined here:
    - create_feature_dict
    - extract_feature
    - get_topological_references
    - is_topological
"""
import os
import pygplates
from .pygplates import FeatureCollection as _FeatureCollection
from .pygplates import _is_string
__all__ = [
    "create_feature_dict",
    "extract_feature",
    "get_topological_references",
    "is_topological",
]
def extract_feature(id, features):
    r"""Return the feature with the given feature ID.
    Searches through `features` and returns the feature with a feature ID
    matching `id`. The order of `features` is not preserved, so multiple
    features sharing the same feature ID should be avoided.
    Parameters
    ----------
    id : pygplates.FeatureId or str
        The feature ID (or string representation) to search for.
    features : valid argument for pygplates.FeaturesFunctionArgument
        `features` may be a single `pygplates.Feature`, a
        `pygplates.FeatureCollection`, a `str` filename,
        or a (potentially nested) sequence of any combination of the above.
    Returns
    -------
    pygplates.Feature or None
        The matching feature if found, otherwise None.
    Raises
    ------
    TypeError
        If `id` is not one of {`pygplates.FeatureId`, `str`},
        or if `features` is of an invalid type.
    OSError (including FileNotFoundError, IsADirectoryError)
        If `features` points to a non-existent or unrecognised file.
    """
    features = _parse_features_function_arguments(features)
    if isinstance(id, pygplates.FeatureId):
        id_type = "fid"
    elif isinstance(id, str):
        id_type = "str"
    else:
        raise TypeError("Invalid feature ID: `{}`".format(id))
    for feature in features:
        feature_id = feature.get_feature_id()
        if id_type == "fid":
            cond = id == feature_id
        else:
            cond = id == feature_id.get_string()
        if cond:
            return feature
    # If the requested feature is not found, either return None
    # or maybe raise a ValueError like list.index() does
    # e.g. [1, 2, 3].index(4)
    # raise ValueError("Feature ID `{}` is not in `features`".format(id))
    return None
def create_feature_dict(features, id_type=pygplates.FeatureId):
    r"""Create a dictionary mapping feature IDs to features.
    Feature IDs can be either `str` or `pygplates.FeatureId`,
    according to `id_type`.
    Parameters
    ----------
    features : valid argument for pygplates.FeaturesFunctionArgument
        `features` may be a single `pygplates.Feature`, a
        `pygplates.FeatureCollection`, a `str` filename,
        or a (potentially nested) sequence of any combination of the above.
    id_type : {`pygplates.FeatureId`, `str`}, optional
        By default, dictionary keys will be of type `pygplates.FeatureId`;
        pass `id_type=str` to use string representations instead.
    Returns
    -------
    dict
        Dictionary for looking up features by their feature ID.
        N.B. the result will be an empty dictonary  if `features` is empty.
    Raises
    ------
    TypeError
        If `id_type` is not one of {`pygplates.FeatureId`, `str`},
        or if `features` is of an invalid type.
    OSError (including FileNotFoundError, IsADirectoryError)
        If `features` points to a non-existent or unrecognised file.
    """
    if id_type not in {str, pygplates.FeatureId}:
        raise TypeError(
            "Invalid `key_type` value: `"
            + str(id_type)
            + "` (must be one of `pygplates.FeatureId`, `str`)"
        )
    features = _parse_features_function_arguments(features)
    if id_type is str:
        return {i.get_feature_id().get_string(): i for i in features}
    else:
        return {i.get_feature_id(): i for i in features}
def get_topological_references(features, id_type=pygplates.FeatureId):
    r"""Create a dictionary mapping topological feature IDs to
    referenced features.
    The resulting dictionary maps each topological
    `pygplates.FeatureId` in `features` to the set of
    `pygplates.FeatureId` referenced by its topological
    geometry or geometries.
    Parameters
    ----------
    features : valid argument for pygplates.FeaturesFunctionArgument
        `features` may be a single `pygplates.Feature`, a
        `pygplates.FeatureCollection`, a `str` filename,
        or a (potentially nested) sequence of any combination of the above.
    id_type : {`pygplates.FeatureId`, `str`}, optional
        By default, feature IDs will be of type `pygplates.FeatureId`;
        pass `id_type=str` to use string representations instead.
    Returns
    -------
    dict
        N.B. Dictionary keys include all topological features in `features`,
        and only topological features.
    Raises
    ------
    TypeError
        If `id_type` is not one of {`pygplates.FeatureId`, `str`},
        or if `features` is of an invalid type.
    OSError (including FileNotFoundError, IsADirectoryError)
        If `features` points to a non-existent or unrecognised file.
    """
    features = _parse_features_function_arguments(features)
    features_dict = create_feature_dict(features)
    results = {}
    for feature in features:
        if not is_topological(feature):
            continue
        references = _get_topological_references(feature, features_dict)
        if len(references) == 0:
            continue
        id = feature.get_feature_id()
        if id_type is str:
            id = id.get_string()
            references = set(i.get_string() for i in references)
        results[id] = references
    return results
def is_topological(feature):
    r"""Determine whether a feature contains a topological geometry.
    Parameters
    ----------
    feature : pygplates.Feature
    Returns
    -------
    bool
        True if `feature` contains a topological geometry, else False.
    Raises
    ------
    TypeError
        If `feature` is a type other than `pygplates.Feature`
        (more precisely, if its type does not implement
        `get_all_topological_geometries`).
    """
    try:
        return len(feature.get_all_topological_geometries()) > 0
    except AttributeError as e:
        raise TypeError(
            "`is_topological` not implemented for `{}`".format(type(feature))
        ) from e
def _get_topological_references(feature, features_dict):
    if not isinstance(feature, pygplates.Feature):
        raise TypeError("Invalid feature type: `{}`".format(type(feature)))
    topologies = feature.get_all_topological_geometries()
    referenced_ids = set()
    for topology in topologies:
        if isinstance(topology, pygplates.GpmlTopologicalLine):
            sections = topology.get_sections()
        else:
            sections = topology.get_boundary_sections()
        for section in sections:
            feature_id = section.get_property_delegate().get_feature_id()
            referenced_ids.add(feature_id)
    referenced_features = set()
    for id in referenced_ids:
        if id in features_dict:
            referenced_features.add(features_dict[id])
    for referenced_feature in referenced_features:
        referenced_ids = referenced_ids.union(
            _get_topological_references(referenced_feature, features_dict)
        )
    return referenced_ids
def _parse_features_function_arguments(features):
    r"""Load features using `pygplates.FeaturesFunctionArgument`.
    This function also tries to translate some of the exceptions
    raised by `pygplates.FeaturesFunctionArgument` into regular
    Python exceptions.
    """
    try:
        features = pygplates.FeatureCollection(
            pygplates.FeaturesFunctionArgument(features).get_features()
        )
    except pygplates.FileFormatNotSupportedError as e:
        print("Invalid filename: `{}`".format(features))
        if not os.path.exists(features):
            raise FileNotFoundError("File does not exist") from e
        if os.path.isdir(features):
            raise IsADirectoryError("File is a directory") from e
        raise OSError("Unrecognised file format") from e
    except pygplates.OpenFileForReadingError as e:
        raise FileNotFoundError(
            "Could not find input file(s): `{}`".format(features)
        ) from e
    except Exception as e:
        if str(type(e)) == "<class 'Boost.Python.ArgumentError'>":
            # This is the easiest way of catching Boost.Python.ArgumentError,
            # since it cannot be directly imported into Python
            raise TypeError(
                "Invalid argument type: `{}`".format(type(features))
            ) from e
        else:
            raise e
    return features
def _load_FeatureCollection(geometry):
    if isinstance(geometry, _FeatureCollection):
        return geometry
    elif isinstance(geometry, pygplates.FeatureCollection):
        geometry.filenames = []
        return geometry
    elif _is_string(geometry) and type(geometry) is list:
        fc = _FeatureCollection()
        for geom in geometry:
            fc.add( _FeatureCollection(geom) )
        return fc
    elif _is_string(geometry):
        return _FeatureCollection(geometry)
    elif geometry is None:
        return None
    else:
        raise ValueError("geometry is an invalid type", type(geometry))Functions
- def create_feature_dict(features, id_type=pygplates.pygplates.FeatureId)
- 
Create a dictionary mapping feature IDs to features. Feature IDs can be either strorpygplates.FeatureId, according toid_type.Parameters- features:- valid argument for pygplates.FeaturesFunctionArgument
- featuresmay be a single- pygplates.Feature, a- pygplates.FeatureCollection, a- strfilename, or a (potentially nested) sequence of any combination of the above.
- id_type:- {pygplates.FeatureId- ,str- }, optional
- By default, dictionary keys will be of type pygplates.FeatureId; passid_type=strto use string representations instead.
 Returns- dict
- Dictionary for looking up features by their feature ID.
N.B. the result will be an empty dictonary
if featuresis empty.
 Raises- TypeError
- If id_typeis not one of {pygplates.FeatureId,str}, or iffeaturesis of an invalid type.
- OSError (including FileNotFoundError, IsADirectoryError)
- If featurespoints to a non-existent or unrecognised file.
 Expand source codedef create_feature_dict(features, id_type=pygplates.FeatureId): r"""Create a dictionary mapping feature IDs to features. Feature IDs can be either `str` or `pygplates.FeatureId`, according to `id_type`. Parameters ---------- features : valid argument for pygplates.FeaturesFunctionArgument `features` may be a single `pygplates.Feature`, a `pygplates.FeatureCollection`, a `str` filename, or a (potentially nested) sequence of any combination of the above. id_type : {`pygplates.FeatureId`, `str`}, optional By default, dictionary keys will be of type `pygplates.FeatureId`; pass `id_type=str` to use string representations instead. Returns ------- dict Dictionary for looking up features by their feature ID. N.B. the result will be an empty dictonary if `features` is empty. Raises ------ TypeError If `id_type` is not one of {`pygplates.FeatureId`, `str`}, or if `features` is of an invalid type. OSError (including FileNotFoundError, IsADirectoryError) If `features` points to a non-existent or unrecognised file. """ if id_type not in {str, pygplates.FeatureId}: raise TypeError( "Invalid `key_type` value: `" + str(id_type) + "` (must be one of `pygplates.FeatureId`, `str`)" ) features = _parse_features_function_arguments(features) if id_type is str: return {i.get_feature_id().get_string(): i for i in features} else: return {i.get_feature_id(): i for i in features}
- def extract_feature(id, features)
- 
Return the feature with the given feature ID. Searches through featuresand returns the feature with a feature ID matchingid. The order offeaturesis not preserved, so multiple features sharing the same feature ID should be avoided.Parameters- id:- pygplates.FeatureIdor- str
- The feature ID (or string representation) to search for.
- features:- valid argument for pygplates.FeaturesFunctionArgument
- featuresmay be a single- pygplates.Feature, a- pygplates.FeatureCollection, a- strfilename, or a (potentially nested) sequence of any combination of the above.
 Returns- pygplates.Featureor- None
- The matching feature if found, otherwise None.
 Raises- TypeError
- If idis not one of {pygplates.FeatureId,str}, or iffeaturesis of an invalid type.
- OSError (including FileNotFoundError, IsADirectoryError)
- If featurespoints to a non-existent or unrecognised file.
 Expand source codedef extract_feature(id, features): r"""Return the feature with the given feature ID. Searches through `features` and returns the feature with a feature ID matching `id`. The order of `features` is not preserved, so multiple features sharing the same feature ID should be avoided. Parameters ---------- id : pygplates.FeatureId or str The feature ID (or string representation) to search for. features : valid argument for pygplates.FeaturesFunctionArgument `features` may be a single `pygplates.Feature`, a `pygplates.FeatureCollection`, a `str` filename, or a (potentially nested) sequence of any combination of the above. Returns ------- pygplates.Feature or None The matching feature if found, otherwise None. Raises ------ TypeError If `id` is not one of {`pygplates.FeatureId`, `str`}, or if `features` is of an invalid type. OSError (including FileNotFoundError, IsADirectoryError) If `features` points to a non-existent or unrecognised file. """ features = _parse_features_function_arguments(features) if isinstance(id, pygplates.FeatureId): id_type = "fid" elif isinstance(id, str): id_type = "str" else: raise TypeError("Invalid feature ID: `{}`".format(id)) for feature in features: feature_id = feature.get_feature_id() if id_type == "fid": cond = id == feature_id else: cond = id == feature_id.get_string() if cond: return feature # If the requested feature is not found, either return None # or maybe raise a ValueError like list.index() does # e.g. [1, 2, 3].index(4) # raise ValueError("Feature ID `{}` is not in `features`".format(id)) return None
- def get_topological_references(features, id_type=pygplates.pygplates.FeatureId)
- 
Create a dictionary mapping topological feature IDs to referenced features. The resulting dictionary maps each topological pygplates.FeatureIdinfeaturesto the set ofpygplates.FeatureIdreferenced by its topological geometry or geometries.Parameters- features:- valid argument for pygplates.FeaturesFunctionArgument
- featuresmay be a single- pygplates.Feature, a- pygplates.FeatureCollection, a- strfilename, or a (potentially nested) sequence of any combination of the above.
- id_type:- {pygplates.FeatureId- ,str- }, optional
- By default, feature IDs will be of type pygplates.FeatureId; passid_type=strto use string representations instead.
 Returns- dict
- N.B. Dictionary keys include all topological features in features, and only topological features.
 Raises- TypeError
- If id_typeis not one of {pygplates.FeatureId,str}, or iffeaturesis of an invalid type.
- OSError (including FileNotFoundError, IsADirectoryError)
- If featurespoints to a non-existent or unrecognised file.
 Expand source codedef get_topological_references(features, id_type=pygplates.FeatureId): r"""Create a dictionary mapping topological feature IDs to referenced features. The resulting dictionary maps each topological `pygplates.FeatureId` in `features` to the set of `pygplates.FeatureId` referenced by its topological geometry or geometries. Parameters ---------- features : valid argument for pygplates.FeaturesFunctionArgument `features` may be a single `pygplates.Feature`, a `pygplates.FeatureCollection`, a `str` filename, or a (potentially nested) sequence of any combination of the above. id_type : {`pygplates.FeatureId`, `str`}, optional By default, feature IDs will be of type `pygplates.FeatureId`; pass `id_type=str` to use string representations instead. Returns ------- dict N.B. Dictionary keys include all topological features in `features`, and only topological features. Raises ------ TypeError If `id_type` is not one of {`pygplates.FeatureId`, `str`}, or if `features` is of an invalid type. OSError (including FileNotFoundError, IsADirectoryError) If `features` points to a non-existent or unrecognised file. """ features = _parse_features_function_arguments(features) features_dict = create_feature_dict(features) results = {} for feature in features: if not is_topological(feature): continue references = _get_topological_references(feature, features_dict) if len(references) == 0: continue id = feature.get_feature_id() if id_type is str: id = id.get_string() references = set(i.get_string() for i in references) results[id] = references return results
- def is_topological(feature)
- 
Determine whether a feature contains a topological geometry. Parameters- feature:- pygplates.Feature
 Returns- bool
- True if featurecontains a topological geometry, else False.
 Raises- TypeError
- If featureis a type other thanpygplates.Feature(more precisely, if its type does not implementget_all_topological_geometries).
 Expand source codedef is_topological(feature): r"""Determine whether a feature contains a topological geometry. Parameters ---------- feature : pygplates.Feature Returns ------- bool True if `feature` contains a topological geometry, else False. Raises ------ TypeError If `feature` is a type other than `pygplates.Feature` (more precisely, if its type does not implement `get_all_topological_geometries`). """ try: return len(feature.get_all_topological_geometries()) > 0 except AttributeError as e: raise TypeError( "`is_topological` not implemented for `{}`".format(type(feature)) ) from e