From f0a30fe10e1c1d42c6bfd5f0480d1ecf7c6e4b49 Mon Sep 17 00:00:00 2001 From: Tim Sutton Date: Mon, 13 Jan 2025 14:49:13 +0000 Subject: [PATCH 1/3] For FCV the same threshold (5000m) should be used for both options Fixes #718 --- config.json | 2 +- .../configuration_widgets/acled_csv_configuration_widget.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config.json b/config.json index 0b264ae0..de4a7d5a 100644 --- a/config.json +++ b/config.json @@ -16,7 +16,7 @@ "author": "Kartoza", "email": "info@kartoza.com", "description": "Gender Enabling Environments Spatial Tool", - "version": "0.4.4", + "version": "0.4.5", "changelog": "", "server": false } diff --git a/geest/gui/widgets/configuration_widgets/acled_csv_configuration_widget.py b/geest/gui/widgets/configuration_widgets/acled_csv_configuration_widget.py index e04f359c..ddcff817 100644 --- a/geest/gui/widgets/configuration_widgets/acled_csv_configuration_widget.py +++ b/geest/gui/widgets/configuration_widgets/acled_csv_configuration_widget.py @@ -37,7 +37,7 @@ def add_internal_widgets(self) -> None: self.buffer_distance_layout.addWidget(self.buffer_distance_input) # I dont think this is defined in the spreadsheet yet. default_distance = self.attributes.get( - "{self.widget_key}_distance_default", 1000 + "{self.widget_key}_distance_default", 5000 ) buffer_distance = self.attributes.get( "{self.widget_key}_distance", default_distance From d18f82bb3a73f5360c4c6a6d2288165b1a5a028a Mon Sep 17 00:00:00 2001 From: Tim Sutton Date: Mon, 13 Jan 2025 16:40:53 +0000 Subject: [PATCH 2/3] The process for health facilities failed Fixes #715 --- geest/core/algorithms/utilities.py | 3 +++ geest/core/workflows/workflow_base.py | 37 ++++++++++++++++++++++++--- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/geest/core/algorithms/utilities.py b/geest/core/algorithms/utilities.py index 48403ec3..550f09c1 100644 --- a/geest/core/algorithms/utilities.py +++ b/geest/core/algorithms/utilities.py @@ -141,6 +141,9 @@ def check_and_reproject_layer( Note: Also updates self.features_layer to point to the reprojected layer. """ + # check if the layer has a valid CRS + if not features_layer.crs().isValid(): + raise QgsProcessingException("Layer has no CRS.") params = { "INPUT": features_layer, diff --git a/geest/core/workflows/workflow_base.py b/geest/core/workflows/workflow_base.py index 4eb1b027..623bdd0e 100644 --- a/geest/core/workflows/workflow_base.py +++ b/geest/core/workflows/workflow_base.py @@ -215,10 +215,41 @@ def execute(self) -> bool: feedback = QgsProcessingFeedback() output_rasters = [] - if self.features_layer and type(self.features_layer) == QgsVectorLayer: - self.features_layer = check_and_reproject_layer( - self.features_layer, self.target_crs + try: + if self.features_layer and type(self.features_layer) == QgsVectorLayer: + log_message( + f"Features layer for {self.workflow_name} is {self.features_layer.source()}" + ) + self.features_layer = check_and_reproject_layer( + self.features_layer, self.target_crs + ) + except Exception as e: + error_file = os.path.join(self.workflow_directory, "error.txt") + if os.path.exists(error_file): + os.remove(error_file) + # Write the traceback to error.txt in the workflow_directory + error_path = os.path.join(self.workflow_directory, "error.txt") + with open(error_path, "w") as f: + f.write(f"Failed to process {self.workflow_name}: {e}\n") + f.write(traceback.format_exc()) + + log_message( + f"Failed to reproject features layer for {self.workflow_name}: {e}", + tag="Geest", + level=Qgis.Critical, ) + log_message( + traceback.format_exc(), + tag="Geest", + level=Qgis.Critical, + ) + self.attributes[self.result_key] = f"{self.workflow_name} Workflow Error" + self.attributes[self.result_file_key] = "" + self.attributes["error_file"] = error_path + self.attributes["error"] = ( + f"Failed to reproject features layer for {self.workflow_name}: {e}" + ) + return False area_iterator = AreaIterator(self.gpkg_path) try: From 56ccf4910f52fa095afa80315f02d12ec008dc74 Mon Sep 17 00:00:00 2001 From: Tim Sutton Date: Mon, 13 Jan 2025 17:53:35 +0000 Subject: [PATCH 3/3] Message to popup when ORS key is outdated/not working Fixes #708 --- .../multi_buffer_distances_workflow.py | 31 ++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/geest/core/workflows/multi_buffer_distances_workflow.py b/geest/core/workflows/multi_buffer_distances_workflow.py index 0409c0b6..69da09e6 100644 --- a/geest/core/workflows/multi_buffer_distances_workflow.py +++ b/geest/core/workflows/multi_buffer_distances_workflow.py @@ -1,4 +1,5 @@ import os +import traceback from qgis.core import ( edit, Qgis, @@ -312,7 +313,35 @@ def _fetch_isochrones(self, layer: QgsVectorLayer) -> dict: # Make the request to ORS API using ORSClient # Any exceptions will be propogated - json = self.ors_client.make_request(self.mode, params) + try: + json = self.ors_client.make_request(self.mode, params) + except Exception as e: + error_file = os.path.join(self.workflow_directory, "error.txt") + if os.path.exists(error_file): + os.remove(error_file) + # Write the traceback to error.txt in the workflow_directory + error_path = os.path.join(self.workflow_directory, "error.txt") + with open(error_path, "w") as f: + f.write(f"Failed to process {self.workflow_name}: {e}\n") + f.write(traceback.format_exc()) + + log_message( + f"Failed to fetch isochrones layer for {self.workflow_name}: {e}", + tag="Geest", + level=Qgis.Critical, + ) + log_message( + traceback.format_exc(), + tag="Geest", + level=Qgis.Critical, + ) + self.attributes[self.result_key] = f"{self.workflow_name} Workflow Error" + self.attributes[self.result_file_key] = "" + self.attributes["error_file"] = error_path + self.attributes["error"] = ( + f"Failed to generate isochrones for {self.workflow_name}: {e}" + ) + return False return json def _create_isochrone_layer(self, isochrone_data):