From 06be40d5df1599fdabec9482077852f65cbf1fd8 Mon Sep 17 00:00:00 2001 From: michaelchin Date: Mon, 19 Aug 2024 19:26:51 +1000 Subject: [PATCH 01/20] filter the feature collection by feature type --- gplately/commands/feature_filter.py | 78 ++++++++++++++++++++++++++--- scripts/test_feature_filter.sh | 8 +++ 2 files changed, 79 insertions(+), 7 deletions(-) diff --git a/gplately/commands/feature_filter.py b/gplately/commands/feature_filter.py index 89f61851..1e7b42fd 100644 --- a/gplately/commands/feature_filter.py +++ b/gplately/commands/feature_filter.py @@ -17,10 +17,14 @@ import abc import argparse +import logging +import re from typing import List import pygplates +logger = logging.getLogger("gplately") + class FeatureFilter(metaclass=abc.ABCMeta): @classmethod @@ -135,6 +139,34 @@ def should_keep(self, feature: pygplates.Feature) -> bool: return False +class FeatureTypeFilter(FeatureFilter): + """filter features by the feature type(regular expression) + + examples: + - gplately filter "$IN_FILE" output/basins.gpmlz -t gpml:Basin + - gplately filter "$IN_FILE" output/basin_islandarc.gpmlz -t "gpml:IslandArc|gpml:Basin" + + :param feature_type_re: the regular expression to match the feature type + + """ + + def __init__(self, feature_type_re: str): + self._feature_type_re = feature_type_re + + def should_keep(self, feature: pygplates.Feature) -> bool: + feature_type = feature.get_feature_type() + if re.fullmatch(self._feature_type_re, feature_type.to_qualified_string()): + logger.debug( + f"feature type match: {self._feature_type_re} {feature_type.to_qualified_string()}" + ) + return True + else: + logger.debug( + f"feature type not match: {self._feature_type_re} {feature_type.to_qualified_string()}" + ) + return False + + def filter_feature_collection( feature_collection: pygplates.FeatureCollection, filters: List[FeatureFilter] ): @@ -168,27 +200,56 @@ def add_parser(subparser): filter_cmd.add_argument("filter_input_file", type=str) filter_cmd.add_argument("filter_output_file", type=str) + # filter by feature name name_group = filter_cmd.add_mutually_exclusive_group() - name_group.add_argument("-n", "--names", type=str, dest="names", nargs="+") name_group.add_argument( - "--exclude-names", type=str, dest="exclude_names", nargs="+" + "-n", "--names", type=str, dest="names", nargs="+", metavar="feature_name" + ) + name_group.add_argument( + "--exclude-names", + type=str, + dest="exclude_names", + nargs="+", + metavar="feature_name", ) + # filter by plate ID pid_group = filter_cmd.add_mutually_exclusive_group() - pid_group.add_argument("-p", "--pids", type=int, dest="pids", nargs="+") - pid_group.add_argument("--exclude-pids", type=int, dest="exclude_pids", nargs="+") + pid_group.add_argument( + "-p", "--pids", type=int, dest="pids", nargs="+", metavar="pid" + ) + pid_group.add_argument( + "--exclude-pids", type=int, dest="exclude_pids", nargs="+", metavar="pid" + ) + # filter by birth age birth_age_group = filter_cmd.add_mutually_exclusive_group() birth_age_group.add_argument( - "-a", "--min-birth-age", type=float, dest="min_birth_age" + "-a", + "--min-birth-age", + type=float, + dest="min_birth_age", + metavar="min_birth_age", + ) + birth_age_group.add_argument( + "--max-birth-age", type=float, dest="max_birth_age", metavar="max_birth_age" ) - birth_age_group.add_argument("--max-birth-age", type=float, dest="max_birth_age") filter_cmd.add_argument( "--case-sensitive", dest="case_sensitive", action="store_true" ) filter_cmd.add_argument("--exact-match", dest="exact_match", action="store_true") + # filter by feature type + filter_cmd.add_argument( + "-t", + "--feature-type", + type=str, + dest="feature_type_re", + metavar="feature_type", + help="the regular expression of feature type", + ) + def run_filter_feature_collection(args): """Filter the input feature collection according to command line arguments.""" @@ -224,12 +285,15 @@ def run_filter_feature_collection(args): elif args.min_birth_age is not None: filters.append(BirthAgeFilter(args.min_birth_age)) + if args.feature_type_re is not None: + filters.append(FeatureTypeFilter(args.feature_type_re)) + new_fc = filter_feature_collection( input_feature_collection, filters, ) new_fc.write(args.filter_output_file) - print( + logger.info( f"Done! The filtered feature collection has been saved to {args.filter_output_file}." ) diff --git a/scripts/test_feature_filter.sh b/scripts/test_feature_filter.sh index cafab546..879075b5 100755 --- a/scripts/test_feature_filter.sh +++ b/scripts/test_feature_filter.sh @@ -60,3 +60,11 @@ gplately filter "$IN_FILE" output/no_africa_north_america.gpmlz --exclude-names # get features whose name does not conain "Africa" or "North America" and plate ID is not in 401 702 gplately filter "$IN_FILE" output/no_africa_north_america_no_401_702.gpmlz --exclude-names Africa "North America" --exclude-pids 401 702 + +# get all gpml:Basin features + +gplately filter "$IN_FILE" output/basins.gpmlz -t gpml:Basin + +# get all gpml:Basin + gpml:IslandArc features + +gplately filter "$IN_FILE" output/basin_islandarc.gpmlz -t "gpml:IslandArc|gpml:Basin" From f277a069877cda7ee94e779415b41a8775b944a0 Mon Sep 17 00:00:00 2001 From: michaelchin Date: Mon, 26 Aug 2024 12:57:04 +1000 Subject: [PATCH 02/20] check in some experimental code --- gplately/commands/reset_feature_type.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 gplately/commands/reset_feature_type.py diff --git a/gplately/commands/reset_feature_type.py b/gplately/commands/reset_feature_type.py new file mode 100644 index 00000000..34fa4d58 --- /dev/null +++ b/gplately/commands/reset_feature_type.py @@ -0,0 +1,15 @@ +import pygplates + +new_fc = pygplates.FeatureCollection() +for f in pygplates.FeatureCollection("shapes_continents.gpml"): + # print(f.get_feature_type()) + new_f = pygplates.Feature( + pygplates.FeatureType.gpml_unclassified_feature, + f.get_feature_id(), + pygplates.VerifyInformationModel.yes, + ) + for p in f: + new_f.add(p.get_name(), p.get_value()) + new_fc.add(new_f) + +new_fc.write("new_shapes_continents.gpmlz") From 110a09b85f1f161769b55cf01ff98967a15b59f6 Mon Sep 17 00:00:00 2001 From: michaelchin Date: Mon, 26 Aug 2024 13:20:56 +1000 Subject: [PATCH 03/20] set VerifyInformationModel.yes when adding property --- gplately/commands/reset_feature_type.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gplately/commands/reset_feature_type.py b/gplately/commands/reset_feature_type.py index 34fa4d58..b4363fb5 100644 --- a/gplately/commands/reset_feature_type.py +++ b/gplately/commands/reset_feature_type.py @@ -9,7 +9,7 @@ pygplates.VerifyInformationModel.yes, ) for p in f: - new_f.add(p.get_name(), p.get_value()) + new_f.add(p.get_name(), p.get_value(), pygplates.VerifyInformationModel.yes) new_fc.add(new_f) new_fc.write("new_shapes_continents.gpmlz") From 205872cdb774d2fca2547908d1a69eb42d433596 Mon Sep 17 00:00:00 2001 From: michaelchin Date: Mon, 26 Aug 2024 17:09:28 +1000 Subject: [PATCH 04/20] use setuptools-git-versioning --- gplately/__init__.py | 22 ++++++++++++++++------ pyproject.toml | 9 ++++++--- tests-dir/unittest/test_plate_model.py | 5 +++++ 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/gplately/__init__.py b/gplately/__init__.py index 5a134542..91de58c5 100644 --- a/gplately/__init__.py +++ b/gplately/__init__.py @@ -200,7 +200,17 @@ """ -__version__ = "1.3.0" + +def get_distribution_version(): + from importlib.metadata import PackageNotFoundError, version + + try: + return version(__name__) + except PackageNotFoundError: + return "UNKNOWN VERSION" + + +__version__ = get_distribution_version() REQUIRED_PMM_VERSION = "1.2.0" USING_DEV_VERSION = True ## change this to False before official release @@ -214,16 +224,16 @@ print() print("##########################################################################") print( - """ + f""" WARNING: - You are using a DEV version GPlately. Some functionalities have not been tested thoroughly. - The DEV version may break your code or produce wrong results due to its unstable nature(DEV in progress). + You are using a DEV version πŸ‘‰({__version__})πŸ‘ˆ GPlately. Some functionalities have not been tested thoroughly. + The DEV version may break your code or produce wrong results due to its unstable nature (DEV in progress). You might also need to install the DEV version plate_model_manager from https://github.com/michaelchin/plate-model-manager to use this DEV version GPlately. - To disable this warning, set USING_DEV_VERSION to False in __init__.py or + 🚫 To disable this warning, set USING_DEV_VERSION to False in __init__.py or set DISABLE_GPLATELY_DEV_WARNING environment variable to true. - `export DISABLE_GPLATELY_DEV_WARNING=true` + πŸ‘‰`export DISABLE_GPLATELY_DEV_WARNING=true`πŸ‘ˆ """ ) print("##########################################################################") diff --git a/pyproject.toml b/pyproject.toml index 40244f99..f7fc58e5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,10 @@ [build-system] -requires = ["setuptools>=61.0.0", "wheel"] +requires = ["setuptools>=61.0.0", "wheel", "setuptools-git-versioning"] build-backend = "setuptools.build_meta" +[tool.setuptools-git-versioning] +enabled = true + [project] name = "gplately" dynamic = ["version"] @@ -42,8 +45,8 @@ where = ["."] exclude = ['*.examples*','*.notebooks*','tests-dir*','Notebooks*', 'scripts*'] namespaces = true -[tool.setuptools.dynamic] -version = {attr = "gplately.__version__"} +#[tool.setuptools.dynamic] +#version = {attr = "gplately.__version__"} [project.optional-dependencies] dev = ["black", "bumpver", "isort", "pip-tools", "pytest"] diff --git a/tests-dir/unittest/test_plate_model.py b/tests-dir/unittest/test_plate_model.py index 9b4badc2..49c07aa6 100755 --- a/tests-dir/unittest/test_plate_model.py +++ b/tests-dir/unittest/test_plate_model.py @@ -3,6 +3,11 @@ from common import MODEL_REPO_DIR from plate_model_manager import PlateModelManager +import gplately + +print(gplately.__version__) +print(gplately.__file__) + def main(): pm_manger = PlateModelManager() From e1ce4c1dbbec6a7c24caecd3bdb8422e985fcf34 Mon Sep 17 00:00:00 2001 From: michaelchin Date: Mon, 26 Aug 2024 17:27:48 +1000 Subject: [PATCH 05/20] minor changes according to JC comments --- gplately/commands/reset_feature_type.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/gplately/commands/reset_feature_type.py b/gplately/commands/reset_feature_type.py index b4363fb5..b31d18d8 100644 --- a/gplately/commands/reset_feature_type.py +++ b/gplately/commands/reset_feature_type.py @@ -6,10 +6,14 @@ new_f = pygplates.Feature( pygplates.FeatureType.gpml_unclassified_feature, f.get_feature_id(), - pygplates.VerifyInformationModel.yes, + pygplates.VerifyInformationModel.yes, # in case the user provided a wrong feature type ) for p in f: - new_f.add(p.get_name(), p.get_value(), pygplates.VerifyInformationModel.yes) + new_f.add( + p.get_name(), + p.get_time_dependent_value(), + pygplates.VerifyInformationModel.no, + ) new_fc.add(new_f) new_fc.write("new_shapes_continents.gpmlz") From 53329f36d45304a517c80ceefe7b6aa8b5a5e855 Mon Sep 17 00:00:00 2001 From: michaelchin Date: Mon, 26 Aug 2024 19:51:26 +1000 Subject: [PATCH 06/20] add warning about inaccurate git version number --- gplately/__init__.py | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/gplately/__init__.py b/gplately/__init__.py index 91de58c5..825e4d4c 100644 --- a/gplately/__init__.py +++ b/gplately/__init__.py @@ -202,7 +202,7 @@ def get_distribution_version(): - from importlib.metadata import PackageNotFoundError, version + from importlib.metadata import PackageNotFoundError, files, version try: return version(__name__) @@ -211,6 +211,7 @@ def get_distribution_version(): __version__ = get_distribution_version() +# __version__ = "1.3.0" REQUIRED_PMM_VERSION = "1.2.0" USING_DEV_VERSION = True ## change this to False before official release @@ -222,23 +223,31 @@ def get_distribution_version(): ) if USING_DEV_VERSION and not disable_dev_warning: print() - print("##########################################################################") + print( + "##################################################################################################" + ) print( f""" WARNING: - You are using a DEV version πŸ‘‰({__version__})πŸ‘ˆ GPlately. Some functionalities have not been tested thoroughly. - The DEV version may break your code or produce wrong results due to its unstable nature (DEV in progress). + You are using a DEV version πŸ‘‰({__version__})πŸ‘ˆ GPlately. + Some functionalities in the DEV version have not been tested thoroughly, + and may break your code or produce wrong results due to + its unstable nature(DEV in progress). You might also need to install the DEV version plate_model_manager - from https://github.com/michaelchin/plate-model-manager to use this DEV version GPlately. + from https://github.com/michaelchin/plate-model-manager. 🚫 To disable this warning, set USING_DEV_VERSION to False in __init__.py or set DISABLE_GPLATELY_DEV_WARNING environment variable to true. πŸ‘‰`export DISABLE_GPLATELY_DEV_WARNING=true`πŸ‘ˆ """ ) - print("##########################################################################") + + print( + "##################################################################################################" + ) print() + import logging from .utils.log_utils import get_debug_level, setup_logging, turn_on_debug_logging @@ -249,10 +258,23 @@ def get_distribution_version(): turn_on_debug_logging() del setup_logging -del os + logger = logging.getLogger("gplately") +if USING_DEV_VERSION and not disable_dev_warning: + if os.path.isdir( + f"{os.path.dirname(os.path.realpath(__file__))}/../.git" + ) or not os.path.isfile( + f"{os.path.dirname(os.path.realpath(__file__))}/../../../../bin/gplately" + ): + logger.warn( + f"The location of GPlately currently in use is {os.path.dirname(os.path.realpath(__file__))}. " + + f"It seems that you are using GPlately source code directly(without `pip install`), the version number({__version__}) may not be accurate." + ) + +del os + def install_and_update_pmm(): import subprocess From 11f39bcb91242835a7fa04a72efff2ee8dc9fad4 Mon Sep 17 00:00:00 2001 From: michaelchin Date: Tue, 27 Aug 2024 18:34:23 +1000 Subject: [PATCH 07/20] move some code out of __init__.py --- gplately/__init__.py | 119 ++++------------------------------ gplately/utils/__init__.py | 3 + gplately/utils/check_pmm.py | 64 ++++++++++++++++++ gplately/utils/dev_warning.py | 66 +++++++++++++++++++ gplately/utils/log_utils.py | 2 + gplately/utils/version.py | 24 +++++++ 6 files changed, 171 insertions(+), 107 deletions(-) create mode 100644 gplately/utils/check_pmm.py create mode 100644 gplately/utils/dev_warning.py create mode 100644 gplately/utils/version.py diff --git a/gplately/__init__.py b/gplately/__init__.py index 825e4d4c..86f4321d 100644 --- a/gplately/__init__.py +++ b/gplately/__init__.py @@ -199,122 +199,27 @@ - [__11 - AndesFluxes__](11-AndesFluxes.html): Demonstrates how the reconstructed subduction history along the Andean margin can be potentially used in the plate kinematics anylysis and data mining. """ +from .utils import dev_warning +from .utils.check_pmm import ensure_plate_model_manager_compatible +from .utils.log_utils import get_debug_level, setup_logging, turn_on_debug_logging +from .utils.version import get_distribution_version - -def get_distribution_version(): - from importlib.metadata import PackageNotFoundError, files, version - - try: - return version(__name__) - except PackageNotFoundError: - return "UNKNOWN VERSION" - - -__version__ = get_distribution_version() -# __version__ = "1.3.0" REQUIRED_PMM_VERSION = "1.2.0" USING_DEV_VERSION = True ## change this to False before official release -import os - -disable_dev_warning = ( - "DISABLE_GPLATELY_DEV_WARNING" in os.environ - and os.environ["DISABLE_GPLATELY_DEV_WARNING"].lower() == "true" -) -if USING_DEV_VERSION and not disable_dev_warning: - print() - print( - "##################################################################################################" - ) - print( - f""" - WARNING: - You are using a DEV version πŸ‘‰({__version__})πŸ‘ˆ GPlately. - Some functionalities in the DEV version have not been tested thoroughly, - and may break your code or produce wrong results due to - its unstable nature(DEV in progress). - You might also need to install the DEV version plate_model_manager - from https://github.com/michaelchin/plate-model-manager. - - 🚫 To disable this warning, set USING_DEV_VERSION to False in __init__.py or - set DISABLE_GPLATELY_DEV_WARNING environment variable to true. - πŸ‘‰`export DISABLE_GPLATELY_DEV_WARNING=true`πŸ‘ˆ - """ - ) - - print( - "##################################################################################################" - ) - print() - - -import logging - -from .utils.log_utils import get_debug_level, setup_logging, turn_on_debug_logging +__version__ = get_distribution_version() +del get_distribution_version setup_logging() - -if get_debug_level() > 0: - turn_on_debug_logging() - del setup_logging +if USING_DEV_VERSION: + dev_warning.print_dev_warning(__version__) + dev_warning.print_using_source_code_warning(__version__) +del dev_warning -logger = logging.getLogger("gplately") - -if USING_DEV_VERSION and not disable_dev_warning: - if os.path.isdir( - f"{os.path.dirname(os.path.realpath(__file__))}/../.git" - ) or not os.path.isfile( - f"{os.path.dirname(os.path.realpath(__file__))}/../../../../bin/gplately" - ): - logger.warn( - f"The location of GPlately currently in use is {os.path.dirname(os.path.realpath(__file__))}. " - + f"It seems that you are using GPlately source code directly(without `pip install`), the version number({__version__}) may not be accurate." - ) - -del os - - -def install_and_update_pmm(): - import subprocess - import sys - - subprocess.call( - [sys.executable, "-m", "pip", "install", "plate-model-manager", "--upgrade"] - ) - - -def check_version(installed_version, required_version): - """return True if the installed_version is good enough, otherwise False""" - installed_version_numbers = installed_version.split(".") - required_version_numbers = required_version.split(".") - if int(installed_version_numbers[0]) > int(required_version_numbers[0]): - return True - elif int(installed_version_numbers[0]) == int(required_version_numbers[0]): - if int(installed_version_numbers[1]) > int(required_version_numbers[1]): - return True - elif int(installed_version_numbers[1]) == int(required_version_numbers[1]): - if int(installed_version_numbers[2]) >= int(required_version_numbers[2]): - return True - return False - - -try: - import plate_model_manager -except (ImportError, ModuleNotFoundError): - logger.info("The plate_model_manager is not installed, installing it now!") - install_and_update_pmm() - import plate_model_manager - - -if not check_version(plate_model_manager.__version__, REQUIRED_PMM_VERSION): - logger.info("The plate_model_manager is outdated, updating it now!") - install_and_update_pmm() - import importlib - - importlib.reload(plate_model_manager) - +ensure_plate_model_manager_compatible(REQUIRED_PMM_VERSION) +del ensure_plate_model_manager_compatible from . import ( data, diff --git a/gplately/utils/__init__.py b/gplately/utils/__init__.py index 77bd3120..301f4199 100644 --- a/gplately/utils/__init__.py +++ b/gplately/utils/__init__.py @@ -35,10 +35,13 @@ ] __pdoc__ = { + "check_pmm": False, + "dev_warning": False, "feature_utils": False, "io_utils": False, "log_utils": False, "plot_utils": False, "seafloor_grid_utils": False, + "version": False, # "crustal_production": False, } diff --git a/gplately/utils/check_pmm.py b/gplately/utils/check_pmm.py new file mode 100644 index 00000000..4c904450 --- /dev/null +++ b/gplately/utils/check_pmm.py @@ -0,0 +1,64 @@ +# +# Copyright (C) 2024 The University of Sydney, Australia +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License, version 2, as published by +# the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# + +import logging + +logger = logging.getLogger("gplately") + + +def install_and_update_pmm(): + import subprocess + import sys + + subprocess.call( + [sys.executable, "-m", "pip", "install", "plate-model-manager", "--upgrade"] + ) + + +def is_pmm_version_good_enough(installed_version, required_version): + """return True if the version of installed pmm is good enough, otherwise False. + assume the version string something like 1.2.0 + """ + installed_version_numbers = installed_version.split(".") + required_version_numbers = required_version.split(".") + if int(installed_version_numbers[0]) > int(required_version_numbers[0]): + return True + elif int(installed_version_numbers[0]) == int(required_version_numbers[0]): + if int(installed_version_numbers[1]) > int(required_version_numbers[1]): + return True + elif int(installed_version_numbers[1]) == int(required_version_numbers[1]): + if int(installed_version_numbers[2]) >= int(required_version_numbers[2]): + return True + return False + + +def ensure_plate_model_manager_compatible(REQUIRED_PMM_VERSION: str): + try: + import plate_model_manager + except (ImportError, ModuleNotFoundError): + logger.info("The plate_model_manager is not installed, installing it now!") + install_and_update_pmm() + import plate_model_manager + + if not is_pmm_version_good_enough( + plate_model_manager.__version__, REQUIRED_PMM_VERSION + ): + logger.info("The plate_model_manager is outdated, updating it now!") + install_and_update_pmm() + import importlib + + importlib.reload(plate_model_manager) diff --git a/gplately/utils/dev_warning.py b/gplately/utils/dev_warning.py new file mode 100644 index 00000000..28395f0b --- /dev/null +++ b/gplately/utils/dev_warning.py @@ -0,0 +1,66 @@ +# +# Copyright (C) 2024 The University of Sydney, Australia +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License, version 2, as published by +# the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# + +import logging +import os + +logger = logging.getLogger("gplately") + +disable_dev_warning = ( + "DISABLE_GPLATELY_DEV_WARNING" in os.environ + and os.environ["DISABLE_GPLATELY_DEV_WARNING"].lower() == "true" +) + + +def print_dev_warning(version: str): + if not disable_dev_warning: + print() + print( + "##################################################################################################" + ) + print( + f""" + WARNING: + You are using a DEV version πŸ‘‰({version})πŸ‘ˆ GPlately. + Some functionalities in the DEV version have not been tested thoroughly, + and may break your code or produce wrong results due to + its unstable nature(DEV in progress). + You might also need to install the DEV version plate_model_manager + from https://github.com/michaelchin/plate-model-manager. + + 🚫 To disable this warning, set USING_DEV_VERSION to False in __init__.py or + set DISABLE_GPLATELY_DEV_WARNING environment variable to true. + πŸ‘‰`export DISABLE_GPLATELY_DEV_WARNING=true`πŸ‘ˆ + """ + ) + print( + "##################################################################################################" + ) + print() + + +def print_using_source_code_warning(version: str): + if not disable_dev_warning: + if os.path.isdir( + f"{os.path.dirname(os.path.realpath(__file__))}/../.git" + ) or not os.path.isfile( + f"{os.path.dirname(os.path.realpath(__file__))}/../../../../bin/gplately" + ): + logger.warn( + f"The location of GPlately currently in use is {os.path.dirname(os.path.realpath(__file__))}. " + + f"It seems that you are using GPlately source code directly(without `pip install`), the version number({version}) may not be accurate." + ) diff --git a/gplately/utils/log_utils.py b/gplately/utils/log_utils.py index 4e7ff8a9..fd53c450 100644 --- a/gplately/utils/log_utils.py +++ b/gplately/utils/log_utils.py @@ -35,6 +35,8 @@ def setup_logging(): logging.getLogger("gplately").debug(f"logger: {name}") for h in logging.getLogger(name).handlers: logging.getLogger("gplately").debug(h) + if get_debug_level() > 0: + turn_on_debug_logging() def turn_on_debug_logging(): diff --git a/gplately/utils/version.py b/gplately/utils/version.py new file mode 100644 index 00000000..c321c503 --- /dev/null +++ b/gplately/utils/version.py @@ -0,0 +1,24 @@ +# +# Copyright (C) 2024 The University of Sydney, Australia +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License, version 2, as published by +# the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +def get_distribution_version(): + """get the version string from GPlately package metadata""" + from importlib.metadata import PackageNotFoundError, version + + try: + return version(__name__) + except PackageNotFoundError: + return "UNKNOWN VERSION" From 90af0f723ca04641c89742ab37a1eadad5698b32 Mon Sep 17 00:00:00 2001 From: michaelchin Date: Tue, 27 Aug 2024 19:57:01 +1000 Subject: [PATCH 08/20] add reset_feature_type sub-command --- gplately/__main__.py | 5 +- gplately/commands/list_models.py | 4 + gplately/commands/reset_feature_type.py | 150 +++++++++++++++++++++--- 3 files changed, 144 insertions(+), 15 deletions(-) diff --git a/gplately/__main__.py b/gplately/__main__.py index df4e411a..9d602512 100644 --- a/gplately/__main__.py +++ b/gplately/__main__.py @@ -23,7 +23,7 @@ from gplately import __version__ -from .commands import create_age_grids, feature_filter, list_models +from .commands import create_age_grids, feature_filter, list_models, reset_feature_type from .ptt import ( cleanup_topologies, convert_xy_to_gplates, @@ -93,6 +93,9 @@ def main(): # add "feature filter" sub-command feature_filter.add_parser(subparser) + # add "reset feature type" sub-command + reset_feature_type.add_parser(subparser) + # add "create age grids" sub-command create_age_grids.add_parser(subparser) diff --git a/gplately/commands/list_models.py b/gplately/commands/list_models.py index fba7f842..48ba2a59 100644 --- a/gplately/commands/list_models.py +++ b/gplately/commands/list_models.py @@ -69,6 +69,10 @@ def run_list_models(args): def get_model_names(): + """return a list of model names from the servers. + the function will try a list of urls one by one. if the first url is not working, try the second one. + if the second one is still not working, try the thrid one. Repeat until the end of the list. + """ model_list_urls = [ "https://repo.gplates.org/webdav/pmm/config/gplately_model_list.json", "https://www.earthbyte.org/webdav/pmm/config/gplately_model_list.json", diff --git a/gplately/commands/reset_feature_type.py b/gplately/commands/reset_feature_type.py index b31d18d8..1681e2ec 100644 --- a/gplately/commands/reset_feature_type.py +++ b/gplately/commands/reset_feature_type.py @@ -1,19 +1,141 @@ +# +# Copyright (C) 2024 The University of Sydney, Australia +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License, version 2, as published by +# the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# + +import argparse +import logging +import re + import pygplates -new_fc = pygplates.FeatureCollection() -for f in pygplates.FeatureCollection("shapes_continents.gpml"): - # print(f.get_feature_type()) - new_f = pygplates.Feature( - pygplates.FeatureType.gpml_unclassified_feature, - f.get_feature_id(), - pygplates.VerifyInformationModel.yes, # in case the user provided a wrong feature type +logger = logging.getLogger("gplately") + +help_str = "Reset the feature type for the selected features." + +__description__ = f"""{help_str} + +Example usage: + - gplately reset_feature_type -s gpml:ClosedContinentalBoundary -t gpml:UnclassifiedFeature input_file output_file + - gplately reset_feature_type -s "gpml:ContinentalFragment|gpml:Coastline" -t gpml:UnclassifiedFeature input_file output_file + - gplately reset_feature_type -s ".*" -t gpml:UnclassifiedFeature input_file output_file +""" + + +def add_parser(subparser): + """add `reset_feature_type` command line argument parser""" + reset_feature_type_cmd = subparser.add_parser( + "reset_feature_type", + help=help_str, + add_help=True, + description=__description__, + formatter_class=argparse.RawDescriptionHelpFormatter, + ) + + reset_feature_type_cmd.set_defaults(func=reset_feature_type) + reset_feature_type_cmd.add_argument("input_file", type=str) + reset_feature_type_cmd.add_argument("output_file", type=str) + + reset_feature_type_cmd.add_argument( + "-s", + "--select-feature-type", + type=str, + dest="select_feature_type_re", + metavar="select_feature_type", + help="the regular expression to select features by featuer type", + ) + + reset_feature_type_cmd.add_argument( + "-t", + "--set-feature-type", + type=str, + dest="set_feature_type", + metavar="set_feature_type", + help="the feature type to be set to", + ) + + reset_feature_type_cmd.add_argument( + "--keep-feature-id", + dest="keep_feature_id", + help="flag to indicate if keep the feature id after resetting the feature type", + action="store_true", ) - for p in f: - new_f.add( - p.get_name(), - p.get_time_dependent_value(), - pygplates.VerifyInformationModel.no, + + reset_feature_type_cmd.add_argument( + "--verify-information-model", + dest="verify_information_model", + help="flag to indicate if verify information model when changing the feature type", + action="store_true", + ) + + +def reset_feature_type(args): + try: + pygplates.Feature( + pygplates.FeatureType.create_from_qualified_string(args.set_feature_type), + verify_information_model=pygplates.VerifyInformationModel.yes, # in case the user provided a wrong feature type + ) + except pygplates.InformationModelError: + logger.error(f"Invalid feature type: {args.set_feature_type}") + logger.error( + f"You have asked to reset features to an invalid feature type. It cannot be done." ) - new_fc.add(new_f) + return + + if args.verify_information_model: + verify_information_model = pygplates.VerifyInformationModel.yes + else: + verify_information_model = pygplates.VerifyInformationModel.no -new_fc.write("new_shapes_continents.gpmlz") + new_fc = pygplates.FeatureCollection() + for f in pygplates.FeatureCollection(args.input_file): + feature_type = f.get_feature_type() + if re.fullmatch( + args.select_feature_type_re, feature_type.to_qualified_string() + ): + if args.keep_feature_id: + new_f = pygplates.Feature( + pygplates.FeatureType.create_from_qualified_string( + args.set_feature_type + ), + f.get_feature_id(), + ) + else: + new_f = pygplates.Feature( + pygplates.FeatureType.create_from_qualified_string( + args.set_feature_type + ) + ) + for p in f: + try: + new_f.add( + p.get_name(), + p.get_time_dependent_value(), + verify_information_model, + ) + except pygplates.InformationModelError: + logger.error( + f"The feature type cannot be changed to {args.set_feature_type}. " + + "Some properties in the features are not allowed in the new feature type." + ) + return + new_fc.add(new_f) + else: + new_fc.add(f) + + new_fc.write(args.output_file) + logger.info( + f"Reset feature type successfully. The new features have been saved in {args.output_file}." + ) From 3fc6f179362a14684bb09c82ae59bd2981cca5a7 Mon Sep 17 00:00:00 2001 From: michaelchin Date: Wed, 28 Aug 2024 15:46:38 +1000 Subject: [PATCH 09/20] add test_reset_feature_type.sh --- gplately/__init__.py | 2 +- gplately/commands/feature_filter.py | 103 +++++++++++++++--- gplately/commands/reset_feature_type.py | 31 ++++-- gplately/utils/dev_warning.py | 9 +- gplately/utils/version.py | 2 +- .../unittest}/test_feature_filter.sh | 2 +- tests-dir/unittest/test_reset_feature_type.sh | 46 ++++++++ 7 files changed, 159 insertions(+), 36 deletions(-) rename {scripts => tests-dir/unittest}/test_feature_filter.sh (97%) create mode 100755 tests-dir/unittest/test_reset_feature_type.sh diff --git a/gplately/__init__.py b/gplately/__init__.py index 86f4321d..d31ec52a 100644 --- a/gplately/__init__.py +++ b/gplately/__init__.py @@ -204,7 +204,7 @@ from .utils.log_utils import get_debug_level, setup_logging, turn_on_debug_logging from .utils.version import get_distribution_version -REQUIRED_PMM_VERSION = "1.2.0" +REQUIRED_PMM_VERSION = "1.2.0" # TODO: get this from package meta USING_DEV_VERSION = True ## change this to False before official release __version__ = get_distribution_version() diff --git a/gplately/commands/feature_filter.py b/gplately/commands/feature_filter.py index 1e7b42fd..008dfabf 100644 --- a/gplately/commands/feature_filter.py +++ b/gplately/commands/feature_filter.py @@ -143,8 +143,8 @@ class FeatureTypeFilter(FeatureFilter): """filter features by the feature type(regular expression) examples: - - gplately filter "$IN_FILE" output/basins.gpmlz -t gpml:Basin - - gplately filter "$IN_FILE" output/basin_islandarc.gpmlz -t "gpml:IslandArc|gpml:Basin" + - gplately filter input_file output_file -t gpml:Basin + - gplately filter input_file output_file -t "gpml:IslandArc|gpml:Basin" :param feature_type_re: the regular expression to match the feature type @@ -170,10 +170,7 @@ def should_keep(self, feature: pygplates.Feature) -> bool: def filter_feature_collection( feature_collection: pygplates.FeatureCollection, filters: List[FeatureFilter] ): - """Filter feature collection by various criteria. - - See scripts/test_feature_filter.sh for usage examples. - """ + """Filter feature collection by various criteria.""" new_feature_collection = pygplates.FeatureCollection() for feature in feature_collection: keep_flag = True @@ -186,24 +183,64 @@ def filter_feature_collection( return new_feature_collection +help_str = "Filter feature collection by various criteria." + +__description__ = f"""{help_str} + +Examples: + - `gplately filter input_file output_file -n Africa "North America"` + (get features whose name contains "Africa" or "North America") + + - `gplately filter input_file output_file -p 701 714 715 101` + (get features whose plate ID is one of 701 714 715 101) + + - `gplately filter input_file output_file --min-birth-age 500` + (get features whose birth age is older than 500Myr) + + - `gplately filter input_file output_file --max-birth-age 500` + (get features whose birth age is younger than 500Myr) + + - `gplately filter input_file output_file -n Africa "North America" -p 701 714 715 101 --min-birth-age 500` + (get features whose name conains "Africa" or "North America" and plate ID is one of 701 714 715 101 and birth age is older than 500Myr) + + - `gplately filter input_file output_file -t gpml:Basin` + (get all gpml:Basin features) + + - `gplately filter input_file output_file -t "gpml:IslandArc|gpml:Basin"` + (get all gpml:Basin and gpml:IslandArc features) + + See test_feature_filter.sh for more examples. +""" + + def add_parser(subparser): """add feature filter command line argument parser""" filter_cmd = subparser.add_parser( "filter", - help="Filter feature collection by various criteria.", - description=filter_feature_collection.__doc__, + help=help_str, + description=__description__, + formatter_class=argparse.RawDescriptionHelpFormatter, ) - filter_cmd.formatter_class = argparse.RawDescriptionHelpFormatter # feature filter command arguments filter_cmd.set_defaults(func=run_filter_feature_collection) - filter_cmd.add_argument("filter_input_file", type=str) - filter_cmd.add_argument("filter_output_file", type=str) + filter_cmd.add_argument("filter_input_file", type=str, help="the input file") + filter_cmd.add_argument( + "filter_output_file", + type=str, + help="the output file into which the filtered feature collection will be saved", + ) # filter by feature name name_group = filter_cmd.add_mutually_exclusive_group() name_group.add_argument( - "-n", "--names", type=str, dest="names", nargs="+", metavar="feature_name" + "-n", + "--names", + type=str, + dest="names", + nargs="+", + metavar="feature_name", + help="features whose name contains the `feature_name` will be kept", ) name_group.add_argument( "--exclude-names", @@ -211,15 +248,27 @@ def add_parser(subparser): dest="exclude_names", nargs="+", metavar="feature_name", + help="features whose name does not contain the `feature_name` will be kept", ) # filter by plate ID pid_group = filter_cmd.add_mutually_exclusive_group() pid_group.add_argument( - "-p", "--pids", type=int, dest="pids", nargs="+", metavar="pid" + "-p", + "--pids", + type=int, + dest="pids", + nargs="+", + metavar="pid", + help="features whose PID are in the `pids` will be kept", ) pid_group.add_argument( - "--exclude-pids", type=int, dest="exclude_pids", nargs="+", metavar="pid" + "--exclude-pids", + type=int, + dest="exclude_pids", + nargs="+", + metavar="pid", + help="features whose PID are not in the `exclude_pids` will be kept", ) # filter by birth age @@ -230,15 +279,28 @@ def add_parser(subparser): type=float, dest="min_birth_age", metavar="min_birth_age", + help="the features whose birth age is older than the `min_birth_age` will be kept", ) birth_age_group.add_argument( - "--max-birth-age", type=float, dest="max_birth_age", metavar="max_birth_age" + "--max-birth-age", + type=float, + dest="max_birth_age", + metavar="max_birth_age", + help="the features whose birth age is younger than the `min_birth_age` will be kept", ) filter_cmd.add_argument( - "--case-sensitive", dest="case_sensitive", action="store_true" + "--case-sensitive", + dest="case_sensitive", + action="store_true", + help="flag to indicate if the `filter by feature name` is case sensitive(not apply to feature type)", + ) + filter_cmd.add_argument( + "--exact-match", + dest="exact_match", + action="store_true", + help="flag to indicate if the `filter by feature name` need to be exact match(not apply to feature type)", ) - filter_cmd.add_argument("--exact-match", dest="exact_match", action="store_true") # filter by feature type filter_cmd.add_argument( @@ -247,7 +309,7 @@ def add_parser(subparser): type=str, dest="feature_type_re", metavar="feature_type", - help="the regular expression of feature type", + help="the feature type regular expression; features whose type matches the regular expression will be kept", ) @@ -293,6 +355,11 @@ def run_filter_feature_collection(args): filters, ) + if len(new_fc) == 0: + logger.warn( + "No feature is left after the filtering. The output feature collection will be empty." + ) + new_fc.write(args.filter_output_file) logger.info( f"Done! The filtered feature collection has been saved to {args.filter_output_file}." diff --git a/gplately/commands/reset_feature_type.py b/gplately/commands/reset_feature_type.py index 1681e2ec..4ef2a8ac 100644 --- a/gplately/commands/reset_feature_type.py +++ b/gplately/commands/reset_feature_type.py @@ -23,14 +23,19 @@ logger = logging.getLogger("gplately") -help_str = "Reset the feature type for the selected features." +help_str = "Reset the feature type for the selected features. " __description__ = f"""{help_str} Example usage: - - gplately reset_feature_type -s gpml:ClosedContinentalBoundary -t gpml:UnclassifiedFeature input_file output_file - - gplately reset_feature_type -s "gpml:ContinentalFragment|gpml:Coastline" -t gpml:UnclassifiedFeature input_file output_file - - gplately reset_feature_type -s ".*" -t gpml:UnclassifiedFeature input_file output_file + - `gplately reset_feature_type -s gpml:ClosedContinentalBoundary -t gpml:UnclassifiedFeature input_file output_file` + (change all gpml:ClosedContinentalBoundary to gpml:UnclassifiedFeature) + + - `gplately reset_feature_type -s "gpml:ContinentalFragment|gpml:Coastline" -t gpml:UnclassifiedFeature input_file output_file` + (change all gpml:ContinentalFragment and gpml:Coastline to gpml:UnclassifiedFeature) + + - `gplately reset_feature_type -s ".*" -t gpml:UnclassifiedFeature input_file output_file` + (change all feature types to gpml:UnclassifiedFeature) """ @@ -45,15 +50,19 @@ def add_parser(subparser): ) reset_feature_type_cmd.set_defaults(func=reset_feature_type) - reset_feature_type_cmd.add_argument("input_file", type=str) - reset_feature_type_cmd.add_argument("output_file", type=str) + reset_feature_type_cmd.add_argument("input_file", type=str, help="the input file") + reset_feature_type_cmd.add_argument( + "output_file", + type=str, + help="the output file into which the new features will be saved", + ) reset_feature_type_cmd.add_argument( "-s", "--select-feature-type", type=str, dest="select_feature_type_re", - metavar="select_feature_type", + metavar="feature_type_re", help="the regular expression to select features by featuer type", ) @@ -62,21 +71,21 @@ def add_parser(subparser): "--set-feature-type", type=str, dest="set_feature_type", - metavar="set_feature_type", - help="the feature type to be set to", + metavar="feature_type", + help="the feature type to be set to, such as gpml:UnclassifiedFeature, gpml:Coastline, etc. See https://www.gplates.org/docs/gpgim/#FeatureClassList", ) reset_feature_type_cmd.add_argument( "--keep-feature-id", dest="keep_feature_id", - help="flag to indicate if keep the feature id after resetting the feature type", + help="flag to indicate if we use the same feature IDs after resetting the feature type", action="store_true", ) reset_feature_type_cmd.add_argument( "--verify-information-model", dest="verify_information_model", - help="flag to indicate if verify information model when changing the feature type", + help="flag to indicate if we need to keep GPGIM integrity", action="store_true", ) diff --git a/gplately/utils/dev_warning.py b/gplately/utils/dev_warning.py index 28395f0b..c2205516 100644 --- a/gplately/utils/dev_warning.py +++ b/gplately/utils/dev_warning.py @@ -34,11 +34,11 @@ def print_dev_warning(version: str): ) print( f""" - WARNING: + WARNING: πŸ‘ˆπŸ‘ˆ πŸ‘€πŸ‘€ You are using a DEV version πŸ‘‰({version})πŸ‘ˆ GPlately. Some functionalities in the DEV version have not been tested thoroughly, and may break your code or produce wrong results due to - its unstable nature(DEV in progress). + its unstable nature(DEV in progress). Proceed With Caution!!! You might also need to install the DEV version plate_model_manager from https://github.com/michaelchin/plate-model-manager. @@ -61,6 +61,7 @@ def print_using_source_code_warning(version: str): f"{os.path.dirname(os.path.realpath(__file__))}/../../../../bin/gplately" ): logger.warn( - f"The location of GPlately currently in use is {os.path.dirname(os.path.realpath(__file__))}. " - + f"It seems that you are using GPlately source code directly(without `pip install`), the version number({version}) may not be accurate." + f"The location of GPlately currently in use is {os.path.dirname(os.path.dirname(os.path.realpath(__file__)))}. " + + f"It seems that you are using GPlately source code directly or installed editable package with `pip install -e .`, " + + f"the version number(❗{version}❗) πŸ‘‰may not be accurateπŸ‘ˆ in these cases." ) diff --git a/gplately/utils/version.py b/gplately/utils/version.py index c321c503..42c39515 100644 --- a/gplately/utils/version.py +++ b/gplately/utils/version.py @@ -19,6 +19,6 @@ def get_distribution_version(): from importlib.metadata import PackageNotFoundError, version try: - return version(__name__) + return version("gplately") except PackageNotFoundError: return "UNKNOWN VERSION" diff --git a/scripts/test_feature_filter.sh b/tests-dir/unittest/test_feature_filter.sh similarity index 97% rename from scripts/test_feature_filter.sh rename to tests-dir/unittest/test_feature_filter.sh index 879075b5..6d6216d0 100755 --- a/scripts/test_feature_filter.sh +++ b/tests-dir/unittest/test_feature_filter.sh @@ -21,7 +21,7 @@ if ! test -f "$IN_FILE"; then fi -# get features whose name conains "Africa" or "North America" +# get features whose name contains "Africa" or "North America" gplately filter "$IN_FILE" output/africa_north_america.gpmlz -n Africa "North America" diff --git a/tests-dir/unittest/test_reset_feature_type.sh b/tests-dir/unittest/test_reset_feature_type.sh new file mode 100755 index 00000000..8c2010af --- /dev/null +++ b/tests-dir/unittest/test_reset_feature_type.sh @@ -0,0 +1,46 @@ +#!/bin/bash +export DISABLE_GPLATELY_DEV_WARNING=true + +TEST_DATA_DIR="test-reset-feature-type-data" +mkdir -p $TEST_DATA_DIR + + +# download the test file +IN_FILE="$TEST_DATA_DIR/Global_EarthByte_GPlates_PresentDay_Coastlines.gpmlz" +FILE_URL="https://repo.gplates.org/webdav/mchin/data/Global_EarthByte_GPlates_PresentDay_Coastlines.gpmlz" + +if ! test -f $IN_FILE; then + if command -v curl; then + curl -o $IN_FILE "$FILE_URL" + else + if command -v wget; then + wget "$FILE_URL" + fi + fi +fi + +if ! test -f $IN_FILE; then + echo "download test file from" "$FILE_URL" "to folder $TEST_DATA_DIR first and then try again!" +fi + +# case 1 +echo "Reset all gpml:ClosedContinentalBoundary features to gpml:UnclassifiedFeature." +gplately reset_feature_type -s gpml:ClosedContinentalBoundary -t gpml:UnclassifiedFeature $IN_FILE $TEST_DATA_DIR/ClosedContinentalBoundary-to-UnclassifiedFeature.gpml + +# case 2 +echo "Reset all gpml:ContinentalFragment and gpml:Coastline features to gpml:UnclassifiedFeature." +gplately reset_feature_type -s "gpml:ContinentalFragment|gpml:Coastline" -t gpml:UnclassifiedFeature $IN_FILE $TEST_DATA_DIR/ContinentalFragment-Coastline-to-UnclassifiedFeature.gpml + +# case 3 +echo "Reset all features to gpml:UnclassifiedFeature and use the same feature IDs in the new file." +gplately reset_feature_type -s ".*" -t gpml:UnclassifiedFeature --keep-feature-id $IN_FILE $TEST_DATA_DIR/all-to-UnclassifiedFeature.gpml + +# case 4 +echo "It is by design if you see an error message below. Do not use --verify-information-model if you need not to guarantee GPGIM integrity." +gplately reset_feature_type -s ".*" -t gpml:Transform --verify-information-model $IN_FILE $TEST_DATA_DIR/should-not-exist.gpml + +# case 5 +echo "It is by design if you see error messages below. Users need to make sure using the correct feature type." +gplately reset_feature_type -s ".*" -t gpml:BadFeatureType $IN_FILE $TEST_DATA_DIR/should-not-exist.gpml + +echo "Testing reset_feature_type is done. Open the output files in GPlates and check the results." From 19b4082c1f59f79b6dd505151027d121f09334a1 Mon Sep 17 00:00:00 2001 From: michaelchin Date: Wed, 28 Aug 2024 15:50:21 +1000 Subject: [PATCH 10/20] update links --- gplately/commands/feature_filter.py | 2 +- gplately/commands/reset_feature_type.py | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/gplately/commands/feature_filter.py b/gplately/commands/feature_filter.py index 008dfabf..76bcf241 100644 --- a/gplately/commands/feature_filter.py +++ b/gplately/commands/feature_filter.py @@ -209,7 +209,7 @@ def filter_feature_collection( - `gplately filter input_file output_file -t "gpml:IslandArc|gpml:Basin"` (get all gpml:Basin and gpml:IslandArc features) - See test_feature_filter.sh for more examples. + See https://github.com/GPlates/gplately/blob/master/tests-dir/unittest/test_feature_filter.sh for more examples. """ diff --git a/gplately/commands/reset_feature_type.py b/gplately/commands/reset_feature_type.py index 4ef2a8ac..8a63abe5 100644 --- a/gplately/commands/reset_feature_type.py +++ b/gplately/commands/reset_feature_type.py @@ -35,7 +35,9 @@ (change all gpml:ContinentalFragment and gpml:Coastline to gpml:UnclassifiedFeature) - `gplately reset_feature_type -s ".*" -t gpml:UnclassifiedFeature input_file output_file` - (change all feature types to gpml:UnclassifiedFeature) + (change all feature types to gpml:UnclassifiedFeature) + + See https://github.com/GPlates/gplately/blob/master/tests-dir/unittest/test_reset_feature_type.sh for more examples. """ From 33bed6a0c9b122f7d0686b91f1ec4084f3d5ff49 Mon Sep 17 00:00:00 2001 From: michaelchin Date: Wed, 28 Aug 2024 16:12:03 +1000 Subject: [PATCH 11/20] update readme --- README.md | 79 ++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 64 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 0999a659..340ea036 100644 --- a/README.md +++ b/README.md @@ -296,68 +296,117 @@ Other documentation versions: GPlately comes with a suite of useful command line tools. These tools are designed as GPlately subcommands. Run `gplately -h` to show the list of tools. -- **list** +### **list** Display a list of available plate models from GPlates server. These model names can then be used by the Plate Model Manager to download model files over Internet. Run `gplately list -h` for details. Examples: - `gplately list` + (list all available plate models from GPlates server) + - `gplately list -m merdith2021` + (show details about model merdith2021) If you are using GPlately Docker image - `docker run gplates/gplately gplately list` - `docker run gplates/gplately gplately list -m merdith2021` -- **combine** +### **combine** Combine multiple feature collections into one. Run `gplately combine -h` for details. -- **filter** +### **filter** + + Filter feature collection by various criteria. Run `gplately filter -h` for details. + + Examples: + + - `gplately filter input_file output_file -n Africa "North America"` + (get features whose name contains "Africa" or "North America") + + - `gplately filter input_file output_file -p 701 714 715 101` + (get features whose plate ID is one of 701 714 715 101) + + - `gplately filter input_file output_file --min-birth-age 500` + (get features whose birth age is older than 500Myr) + + - `gplately filter input_file output_file --max-birth-age 500` + (get features whose birth age is younger than 500Myr) + + - `gplately filter input_file output_file -n Africa "North America" -p 701 714 715 101 --min-birth-age 500` + (get features whose name conains "Africa" or "North America" and plate ID is one of 701 714 715 101 and birth age is older than 500Myr) + + - `gplately filter input_file output_file -t gpml:Basin` + (get all gpml:Basin features) + + - `gplately filter input_file output_file -t "gpml:IslandArc|gpml:Basin"` + (get all gpml:Basin and gpml:IslandArc features) + + If you are using Docker, prefix `docker run gplates/gplately ` to the command, such as `docker run gplates/gplately gplately filter input_file output_file -t gpml:Basin`. + + See https://github.com/GPlates/gplately/blob/master/tests-dir/unittest/test_feature_filter.sh for more examples. + +### **reset_feature_type** + + Reset the feature type for the selected features. Run `gplately reset_feature_type -h` for details. + + Examples: + + - `gplately reset_feature_type -s gpml:ClosedContinentalBoundary -t gpml:UnclassifiedFeature input_file output_file` + (change all gpml:ClosedContinentalBoundary to gpml:UnclassifiedFeature) + + - `gplately reset_feature_type -s "gpml:ContinentalFragment|gpml:Coastline" -t gpml:UnclassifiedFeature input_file output_file` + (change all gpml:ContinentalFragment and gpml:Coastline to gpml:UnclassifiedFeature) + + - `gplately reset_feature_type -s ".*" -t gpml:UnclassifiedFeature input_file output_file` + (change all feature types to gpml:UnclassifiedFeature) + + If you are using Docker, prefix `docker run gplates/gplately ` to the command, such as `docker run gplates/gplately gplately reset_feature_type -s ".*" -t gpml:UnclassifiedFeature input_file output_file`. - Filter feature collection by various criteria. See scripts/test_feature_filter.sh for usage examples. Run `gplately filter -h` for details. + See https://github.com/GPlates/gplately/blob/master/tests-dir/unittest/test_reset_feature_type.sh for more examples. -- **agegrid (ag)** +### **agegrid (ag)** Create age grids for a plate model. Run `gplately agegrid -h` for details. -- **fix_crossovers** +### **fix_crossovers** Loads one or more input rotation files, fixes any crossovers and saves the rotations to output rotation files. Run `gplately fix_crossovers -h` for details. -- **remove_rotations** +### **remove_rotations** Remove one or more plate IDs from a rotation model (consisting of one or more rotation files). Run `gplately remove_rotations -h` for details. -- **cleanup_topologies** +### **cleanup_topologies** Remove any regular features not referenced by topological features. Run `gplately cleanup_topologies -h` for details. -- **convert_xy_to_gplates** +### **convert_xy_to_gplates** Converts geometry in one or more input ascii files (such as '.xy' files) to output files suitable for loading into GPlates. Run `gplately convert_xy_to_gplates -h` for details. -- **diagnose_rotations** +### **diagnose_rotations** Diagnose one or more rotation files to check for inconsistencies. Run `gplately diagnose_rotations -h` for details. -- **resolve_topologies** +### **resolve_topologies** Resolve topological plate polygons (and deforming networks) and saves (to separate files) the resolved topologies, and their boundary sections as subduction zones, mid-ocean ridges (ridge/transform) and others (not subduction zones or mid-ocean ridges). Run `gplately resolve_topologies -h` for details. -- **rotation_tools** +### **rotation_tools** Calculate stage rotations between consecutive finite rotations in plate pairs. Run `gplately rotation_tools -h` for details. -- **separate_ridge_transform_segments** +### **separate_ridge_transform_segments** Split the geometries of isochrons and mid-ocean ridges into ridge and transform segments. Run `gplately separate_ridge_transform_segments -h` for details. -- **subduction_convergence** +### **subduction_convergence** Find the convergence rates along trenches (subduction zones) over time. Run `gplately subduction_convergence -h` for details. -- **gpmdb** +### **gpmdb** Retrieve paleomagnetic data from https://www.gpmdb.net, create GPlates-compatible VGP features and save the VGP features in a .gpmlz file. Run `gplately gpmdb -h` for details. From 02d5e7c37680f3ab3bb62b79e5a782b52b98f981 Mon Sep 17 00:00:00 2001 From: michaelchin Date: Wed, 28 Aug 2024 16:57:50 +1000 Subject: [PATCH 12/20] find out why the pytest hangs on Windows --- tests-dir/pytestcases/test_5_seafloorgrid.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests-dir/pytestcases/test_5_seafloorgrid.py b/tests-dir/pytestcases/test_5_seafloorgrid.py index 8ce85f84..0823bc96 100644 --- a/tests-dir/pytestcases/test_5_seafloorgrid.py +++ b/tests-dir/pytestcases/test_5_seafloorgrid.py @@ -46,6 +46,7 @@ def test_gplately_SeafloorGrid_object(seafloorgrid): # Gridding input npz files are ok if they have no NaN entries in the spreading rate column. # Spreading rate ultimately builds the seafloor age. @pytest.mark.parametrize("time", gridding_times) +@pytest.mark.skip(reason="find out why the test hangs on Windows") def test_reconstruct_by_topologies(time, seafloorgrid): _reconstruct_by_topologies(time, seafloorgrid, clean=True) @@ -123,6 +124,7 @@ def _reconstruct_by_topologies(time, seafloorgrid, clean=False): # test netCDF writing @pytest.mark.parametrize("zval_name", zval_names) +@pytest.mark.skip(reason="find out why the test hangs on Windows") def test_lat_lon_z_to_netCDF(zval_name, seafloorgrid): time = gridding_times[0] From 6eb65dc6c0f334843dacf050f31993ea91a192ec Mon Sep 17 00:00:00 2001 From: michaelchin Date: Wed, 28 Aug 2024 17:08:31 +1000 Subject: [PATCH 13/20] find out why the pytest hangs on Windows - 2 --- gplately/utils/dev_warning.py | 2 +- tests-dir/pytestcases/test_5_seafloorgrid.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/gplately/utils/dev_warning.py b/gplately/utils/dev_warning.py index c2205516..7219d9d1 100644 --- a/gplately/utils/dev_warning.py +++ b/gplately/utils/dev_warning.py @@ -60,7 +60,7 @@ def print_using_source_code_warning(version: str): ) or not os.path.isfile( f"{os.path.dirname(os.path.realpath(__file__))}/../../../../bin/gplately" ): - logger.warn( + logger.warning( f"The location of GPlately currently in use is {os.path.dirname(os.path.dirname(os.path.realpath(__file__)))}. " + f"It seems that you are using GPlately source code directly or installed editable package with `pip install -e .`, " + f"the version number(❗{version}❗) πŸ‘‰may not be accurateπŸ‘ˆ in these cases." diff --git a/tests-dir/pytestcases/test_5_seafloorgrid.py b/tests-dir/pytestcases/test_5_seafloorgrid.py index 0823bc96..86451f1e 100644 --- a/tests-dir/pytestcases/test_5_seafloorgrid.py +++ b/tests-dir/pytestcases/test_5_seafloorgrid.py @@ -124,7 +124,6 @@ def _reconstruct_by_topologies(time, seafloorgrid, clean=False): # test netCDF writing @pytest.mark.parametrize("zval_name", zval_names) -@pytest.mark.skip(reason="find out why the test hangs on Windows") def test_lat_lon_z_to_netCDF(zval_name, seafloorgrid): time = gridding_times[0] From 7fb58ef4472acee2ecf3841e7674620215398dae Mon Sep 17 00:00:00 2001 From: michaelchin Date: Wed, 28 Aug 2024 18:43:57 +1000 Subject: [PATCH 14/20] test if setuptools-git-versioning caused pytest hang --- gplately/__init__.py | 3 ++- pyproject.toml | 8 ++++---- tests-dir/pytestcases/test_5_seafloorgrid.py | 1 - 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/gplately/__init__.py b/gplately/__init__.py index d31ec52a..9e68e8e1 100644 --- a/gplately/__init__.py +++ b/gplately/__init__.py @@ -207,7 +207,8 @@ REQUIRED_PMM_VERSION = "1.2.0" # TODO: get this from package meta USING_DEV_VERSION = True ## change this to False before official release -__version__ = get_distribution_version() +__version__ = "1.3.0" +# __version__ = get_distribution_version() del get_distribution_version setup_logging() diff --git a/pyproject.toml b/pyproject.toml index f7fc58e5..8241aa93 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,8 +2,8 @@ requires = ["setuptools>=61.0.0", "wheel", "setuptools-git-versioning"] build-backend = "setuptools.build_meta" -[tool.setuptools-git-versioning] -enabled = true +#[tool.setuptools-git-versioning] +#enabled = true [project] name = "gplately" @@ -45,8 +45,8 @@ where = ["."] exclude = ['*.examples*','*.notebooks*','tests-dir*','Notebooks*', 'scripts*'] namespaces = true -#[tool.setuptools.dynamic] -#version = {attr = "gplately.__version__"} +[tool.setuptools.dynamic] +version = {attr = "gplately.__version__"} [project.optional-dependencies] dev = ["black", "bumpver", "isort", "pip-tools", "pytest"] diff --git a/tests-dir/pytestcases/test_5_seafloorgrid.py b/tests-dir/pytestcases/test_5_seafloorgrid.py index 86451f1e..8ce85f84 100644 --- a/tests-dir/pytestcases/test_5_seafloorgrid.py +++ b/tests-dir/pytestcases/test_5_seafloorgrid.py @@ -46,7 +46,6 @@ def test_gplately_SeafloorGrid_object(seafloorgrid): # Gridding input npz files are ok if they have no NaN entries in the spreading rate column. # Spreading rate ultimately builds the seafloor age. @pytest.mark.parametrize("time", gridding_times) -@pytest.mark.skip(reason="find out why the test hangs on Windows") def test_reconstruct_by_topologies(time, seafloorgrid): _reconstruct_by_topologies(time, seafloorgrid, clean=True) From 165f5f1132b2448266c38f482a5622579ea336a8 Mon Sep 17 00:00:00 2001 From: michaelchin Date: Wed, 28 Aug 2024 19:09:23 +1000 Subject: [PATCH 15/20] test if setuptools-git-versioning caused pytest hang 1 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 8241aa93..8b1acaba 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [build-system] -requires = ["setuptools>=61.0.0", "wheel", "setuptools-git-versioning"] +requires = ["setuptools>=61.0.0", "wheel"] build-backend = "setuptools.build_meta" #[tool.setuptools-git-versioning] From 0c3be2091317caccdc242f302aebb7d059f6b867 Mon Sep 17 00:00:00 2001 From: michaelchin Date: Wed, 28 Aug 2024 19:19:51 +1000 Subject: [PATCH 16/20] test if setuptools-git-versioning caused pytest hang 2 --- gplately/__init__.py | 3 +-- gplately/utils/version.py | 8 -------- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/gplately/__init__.py b/gplately/__init__.py index 9e68e8e1..e6f1d09c 100644 --- a/gplately/__init__.py +++ b/gplately/__init__.py @@ -202,14 +202,13 @@ from .utils import dev_warning from .utils.check_pmm import ensure_plate_model_manager_compatible from .utils.log_utils import get_debug_level, setup_logging, turn_on_debug_logging -from .utils.version import get_distribution_version REQUIRED_PMM_VERSION = "1.2.0" # TODO: get this from package meta USING_DEV_VERSION = True ## change this to False before official release __version__ = "1.3.0" # __version__ = get_distribution_version() -del get_distribution_version + setup_logging() del setup_logging diff --git a/gplately/utils/version.py b/gplately/utils/version.py index 42c39515..42fd078a 100644 --- a/gplately/utils/version.py +++ b/gplately/utils/version.py @@ -14,11 +14,3 @@ # with this program; if not, write to Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # -def get_distribution_version(): - """get the version string from GPlately package metadata""" - from importlib.metadata import PackageNotFoundError, version - - try: - return version("gplately") - except PackageNotFoundError: - return "UNKNOWN VERSION" From 6ec0d9b406207de1c64ecd5bbd6faedf5ebcc883 Mon Sep 17 00:00:00 2001 From: michaelchin Date: Wed, 28 Aug 2024 19:34:37 +1000 Subject: [PATCH 17/20] remove the damned unicode emoji --- gplately/utils/dev_warning.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/gplately/utils/dev_warning.py b/gplately/utils/dev_warning.py index 7219d9d1..9f947fb9 100644 --- a/gplately/utils/dev_warning.py +++ b/gplately/utils/dev_warning.py @@ -34,17 +34,17 @@ def print_dev_warning(version: str): ) print( f""" - WARNING: πŸ‘ˆπŸ‘ˆ πŸ‘€πŸ‘€ - You are using a DEV version πŸ‘‰({version})πŸ‘ˆ GPlately. + WARNING: + You are using a DEV version ({version}) GPlately. Some functionalities in the DEV version have not been tested thoroughly, and may break your code or produce wrong results due to its unstable nature(DEV in progress). Proceed With Caution!!! You might also need to install the DEV version plate_model_manager from https://github.com/michaelchin/plate-model-manager. - 🚫 To disable this warning, set USING_DEV_VERSION to False in __init__.py or + To disable this warning, set USING_DEV_VERSION to False in __init__.py or set DISABLE_GPLATELY_DEV_WARNING environment variable to true. - πŸ‘‰`export DISABLE_GPLATELY_DEV_WARNING=true`πŸ‘ˆ + `export DISABLE_GPLATELY_DEV_WARNING=true` """ ) print( @@ -63,5 +63,5 @@ def print_using_source_code_warning(version: str): logger.warning( f"The location of GPlately currently in use is {os.path.dirname(os.path.dirname(os.path.realpath(__file__)))}. " + f"It seems that you are using GPlately source code directly or installed editable package with `pip install -e .`, " - + f"the version number(❗{version}❗) πŸ‘‰may not be accurateπŸ‘ˆ in these cases." + + f"the version number({version}) may not be accurate in these cases." ) From 7cccd3d78c60c9315cee698abfa401a9d4608667 Mon Sep 17 00:00:00 2001 From: michaelchin Date: Wed, 28 Aug 2024 19:45:33 +1000 Subject: [PATCH 18/20] bing back good stuff --- gplately/__init__.py | 5 ++--- gplately/utils/version.py | 10 ++++++++++ pyproject.toml | 10 +++++----- tests-dir/unittest/test_plate_model.py | 5 ----- 4 files changed, 17 insertions(+), 13 deletions(-) diff --git a/gplately/__init__.py b/gplately/__init__.py index e6f1d09c..98255dfe 100644 --- a/gplately/__init__.py +++ b/gplately/__init__.py @@ -202,13 +202,12 @@ from .utils import dev_warning from .utils.check_pmm import ensure_plate_model_manager_compatible from .utils.log_utils import get_debug_level, setup_logging, turn_on_debug_logging +from .utils.version import get_distribution_version REQUIRED_PMM_VERSION = "1.2.0" # TODO: get this from package meta USING_DEV_VERSION = True ## change this to False before official release -__version__ = "1.3.0" -# __version__ = get_distribution_version() - +__version__ = get_distribution_version() setup_logging() del setup_logging diff --git a/gplately/utils/version.py b/gplately/utils/version.py index 42fd078a..f2c0526f 100644 --- a/gplately/utils/version.py +++ b/gplately/utils/version.py @@ -14,3 +14,13 @@ # with this program; if not, write to Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # +from importlib.metadata import PackageNotFoundError, version + + +def get_distribution_version(): + """get the version string from GPlately package metadata""" + + try: + return version("gplately") + except PackageNotFoundError: + return "UNKNOWN VERSION" diff --git a/pyproject.toml b/pyproject.toml index 8b1acaba..f7fc58e5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,9 +1,9 @@ [build-system] -requires = ["setuptools>=61.0.0", "wheel"] +requires = ["setuptools>=61.0.0", "wheel", "setuptools-git-versioning"] build-backend = "setuptools.build_meta" -#[tool.setuptools-git-versioning] -#enabled = true +[tool.setuptools-git-versioning] +enabled = true [project] name = "gplately" @@ -45,8 +45,8 @@ where = ["."] exclude = ['*.examples*','*.notebooks*','tests-dir*','Notebooks*', 'scripts*'] namespaces = true -[tool.setuptools.dynamic] -version = {attr = "gplately.__version__"} +#[tool.setuptools.dynamic] +#version = {attr = "gplately.__version__"} [project.optional-dependencies] dev = ["black", "bumpver", "isort", "pip-tools", "pytest"] diff --git a/tests-dir/unittest/test_plate_model.py b/tests-dir/unittest/test_plate_model.py index 49c07aa6..9b4badc2 100755 --- a/tests-dir/unittest/test_plate_model.py +++ b/tests-dir/unittest/test_plate_model.py @@ -3,11 +3,6 @@ from common import MODEL_REPO_DIR from plate_model_manager import PlateModelManager -import gplately - -print(gplately.__version__) -print(gplately.__file__) - def main(): pm_manger = PlateModelManager() From 126fd2b49a7e8c46254a2efb66ffa03c85134d30 Mon Sep 17 00:00:00 2001 From: michaelchin Date: Thu, 29 Aug 2024 09:01:52 +1000 Subject: [PATCH 19/20] update warning message again --- gplately/utils/dev_warning.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/gplately/utils/dev_warning.py b/gplately/utils/dev_warning.py index 9f947fb9..088be3e3 100644 --- a/gplately/utils/dev_warning.py +++ b/gplately/utils/dev_warning.py @@ -44,7 +44,11 @@ def print_dev_warning(version: str): To disable this warning, set USING_DEV_VERSION to False in __init__.py or set DISABLE_GPLATELY_DEV_WARNING environment variable to true. + `export DISABLE_GPLATELY_DEV_WARNING=true` + + If you prefer not seeing this warning always, you may set the environment variable + in your boot scripts, such as .bashrc, .profile, autoexec.bat, etc. """ ) print( From 1e3c379d314a942de73b042adffe6fc2d75d84f7 Mon Sep 17 00:00:00 2001 From: michaelchin Date: Thu, 29 Aug 2024 09:09:11 +1000 Subject: [PATCH 20/20] update test scripts --- tests-dir/unittest/test_feature_filter.sh | 42 ++++++++++++----------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/tests-dir/unittest/test_feature_filter.sh b/tests-dir/unittest/test_feature_filter.sh index 6d6216d0..b797b3ac 100755 --- a/tests-dir/unittest/test_feature_filter.sh +++ b/tests-dir/unittest/test_feature_filter.sh @@ -1,70 +1,72 @@ -#!/bin/bash +export DISABLE_GPLATELY_DEV_WARNING=true + +TEST_DATA_DIR="test-feature-filter-data" +mkdir -p $TEST_DATA_DIR -mkdir -p output # download the test file -IN_FILE="Global_EarthByte_GPlates_PresentDay_Coastlines.gpmlz" +IN_FILE="$TEST_DATA_DIR/Global_EarthByte_GPlates_PresentDay_Coastlines.gpmlz" FILE_URL="https://repo.gplates.org/webdav/mchin/data/Global_EarthByte_GPlates_PresentDay_Coastlines.gpmlz" -if ! test -f "$IN_FILE"; then +if ! test -f $IN_FILE; then if command -v curl; then - curl -O "$FILE_URL" + curl -o $IN_FILE "$FILE_URL" else if command -v wget; then - wget "$FILE_URL" + wget -O $IN_FILE "$FILE_URL" fi fi fi -if ! test -f "$IN_FILE"; then - echo "download test file from" "$FILE_URL" "first and then try again!" +if ! test -f $IN_FILE; then + echo "download test file from" "$FILE_URL" "to folder $TEST_DATA_DIR first and then try again!" fi # get features whose name contains "Africa" or "North America" -gplately filter "$IN_FILE" output/africa_north_america.gpmlz -n Africa "North America" +gplately filter "$IN_FILE" $TEST_DATA_DIR/africa_north_america.gpmlz -n Africa "North America" # get features whose plate ID is one of 701 714 715 101 -gplately filter "$IN_FILE" output/pid_701_714_715_101.gpmlz -p 701 714 715 101 +gplately filter "$IN_FILE" $TEST_DATA_DIR/pid_701_714_715_101.gpmlz -p 701 714 715 101 # get features whose birth age is older than 500Myr -gplately filter "$IN_FILE" output/birth_age_older_500.gpmlz --min-birth-age 500 +gplately filter "$IN_FILE" $TEST_DATA_DIR/birth_age_older_500.gpmlz --min-birth-age 500 # get features whose birth age is younger than 500Myr -gplately filter "$IN_FILE" output/birth_age_younger_500.gpmlz --max-birth-age 500 +gplately filter "$IN_FILE" $TEST_DATA_DIR/birth_age_younger_500.gpmlz --max-birth-age 500 # get features whose name conains "Africa" or "North America" and plate ID is one of 701 714 715 101 -gplately filter "$IN_FILE" output/africa_north_america_pid_701_714_715_101.gpmlz -n Africa "North America" -p 701 714 715 101 +gplately filter "$IN_FILE" $TEST_DATA_DIR/africa_north_america_pid_701_714_715_101.gpmlz -n Africa "North America" -p 701 714 715 101 # get features whose name conains "Africa" or "North America" and plate ID is one of 701 714 715 101 and birth age is older than 500Myr -gplately filter "$IN_FILE" output/africa_north_america_pid_701_714_715_101_birth_age_500.gpmlz -n Africa "North America" -p 701 714 715 101 --min-birth-age 500 +gplately filter "$IN_FILE" $TEST_DATA_DIR/africa_north_america_pid_701_714_715_101_birth_age_500.gpmlz -n Africa "North America" -p 701 714 715 101 --min-birth-age 500 # only Africa is saved because the name is --case-sensitive -gplately filter "$IN_FILE" output/africa.gpmlz -n Africa "North america" --case-sensitive +gplately filter "$IN_FILE" $TEST_DATA_DIR/africa.gpmlz -n Africa "North america" --case-sensitive # only Africa is saved because the name is --exact-match -gplately filter "$IN_FILE" output/africa_1.gpmlz -n Africa "North America" --exact-match +gplately filter "$IN_FILE" $TEST_DATA_DIR/africa_1.gpmlz -n Africa "North America" --exact-match # get features whose name does not conain "Africa" or "North America" -gplately filter "$IN_FILE" output/no_africa_north_america.gpmlz --exclude-names Africa "North America" +gplately filter "$IN_FILE" $TEST_DATA_DIR/no_africa_north_america.gpmlz --exclude-names Africa "North America" # get features whose name does not conain "Africa" or "North America" and plate ID is not in 401 702 -gplately filter "$IN_FILE" output/no_africa_north_america_no_401_702.gpmlz --exclude-names Africa "North America" --exclude-pids 401 702 +gplately filter "$IN_FILE" $TEST_DATA_DIR/no_africa_north_america_no_401_702.gpmlz --exclude-names Africa "North America" --exclude-pids 401 702 # get all gpml:Basin features -gplately filter "$IN_FILE" output/basins.gpmlz -t gpml:Basin +gplately filter "$IN_FILE" $TEST_DATA_DIR/basins.gpmlz -t gpml:Basin # get all gpml:Basin + gpml:IslandArc features -gplately filter "$IN_FILE" output/basin_islandarc.gpmlz -t "gpml:IslandArc|gpml:Basin" +gplately filter "$IN_FILE" $TEST_DATA_DIR/basin_islandarc.gpmlz -t "gpml:IslandArc|gpml:Basin"