Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Timlinux/issue807 #839

Merged
merged 7 commits into from
Feb 5, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .envrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
use nix
layout python3
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ env/
venv/
ENV/
.env.*
.envrc

# PyInstaller
*.**`.gitignore` continued:**
Expand Down
2 changes: 1 addition & 1 deletion config.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"author": "Kartoza for/and The World Bank",
"email": "[email protected], [email protected]",
"description": "Gender Enabling Environments Spatial Tool",
"version": "0.5.4",
"version": "0.5.5",
"changelog": "",
"server": false
}
Expand Down
18 changes: 16 additions & 2 deletions geest/core/json_tree_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,15 +274,16 @@ def getStatus(self):
return ""
if len(self.itemData) < 4:
return ""

data = self.attributes()
analysis_mode = data.get("analysis_mode", "")
qgis_layer_source_key = analysis_mode.replace("use_", "") + "_layer_source"
qgis_layer_shapefile_key = analysis_mode.replace("use_", "") + "_shapefile"
qgis_layer_raster_key = analysis_mode.replace("use_", "") + "_raster"
status = ""

if "Workflow Completed" in data.get("result", ""):
if "Workflow Completed" in data.get("result", "") and data.get(
"result_file", ""
):
return "Completed successfully"

# First check if the item weighting is 0, or its parent factor is zero
Expand Down Expand Up @@ -339,6 +340,19 @@ def getStatus(self):
):
return "Excluded from analysis"

# If any child indicator has a status of "Workflow failed", return "Workflow failed"
for child in self.childItems:
child_status = child.getStatus()
log_message(f"Child status: {child_status}")
if child_status == "Workflow failed":
return "Workflow failed"
if child_status == "Required and not configured":
return "Required and not configured"
if child_status == "Error":
return "Workflow failed"
if child_status.contains("Failed"):
return "Workflow failed"

if self.isDimension():
# If the analysis weighting is zero, return "Excluded from analysis"
if not float(data.get("analysis_weighting", 0.0)):
Expand Down
55 changes: 31 additions & 24 deletions geest/core/tasks/study_area.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
QgsFeedback,
QgsVectorLayer,
QgsVectorFileWriter,
QgsApplication,
QgsProject,
)
from geest.utilities import log_message
from .grid_from_bbox import GridFromBbox
Expand Down Expand Up @@ -175,24 +175,28 @@ def export_qgs_layer_to_shapefile(self, layer, output_dir):
Exports a QgsVectorLayer to a Shapefile in output_dir.
Returns the full path to the .shp (main file).
"""
shapefile_path = os.path.join(output_dir, "temp_export.shp")
# Check if the layer has selected features
if layer.selectedFeatureCount() == 0:
has_selection = False
shapefile_path = os.path.join(output_dir, "boundaries.shp")
# Get the project's transform context (required for file writing)
transform_context = QgsProject.instance().transformContext()
options = QgsVectorFileWriter.SaveVectorOptions()
options.driverName = "ESRI Shapefile"
options.fileEncoding = "UTF-8"

if layer.selectedFeatureCount() > 0:
options.actionOnExistingFile = (
QgsVectorFileWriter.CreateOrOverwriteFile
) # or OverwriteExistingFile
else:
has_selection = True
# Export the selected features of the layer
err_code, err_msg = QgsVectorFileWriter.writeAsVectorFormat(
layer,
shapefile_path,
"UTF-8", # encoding
layer.crs(), # CRS to write
"ESRI Shapefile", # driver name
onlySelected=has_selection, # Export only selected features
options.actionOnExistingFile = (
QgsVectorFileWriter.CreateOrOverwriteFile
) # or OverwriteExistingFile

err = QgsVectorFileWriter.writeAsVectorFormatV3(
layer, shapefile_path, transform_context, options
)

if err_code != QgsVectorFileWriter.NoError:
raise RuntimeError(f"Failed to export layer to Shapefile: {err_msg}")
if err[0] != QgsVectorFileWriter.NoError:
raise RuntimeError(f"Failed to export layer to Shapefile: {err[1]}")

return shapefile_path

Expand All @@ -213,6 +217,7 @@ def run(self):
self.create_status_tracking_table()

# 3) Iterate over features
self.setProgress(1) # Trigger the UI to update with a small value
invalid_feature_count = 0
self.valid_feature_count = 0
fixed_feature_count = 0
Expand Down Expand Up @@ -268,6 +273,7 @@ def run(self):
self.process_singlepart_geometry(
geom_ref, normalized_name, area_name
)
self.setProgress(100) # Trigger the UI to update with completion value
log_message(
f"Processing complete. Valid: {self.valid_feature_count}, Fixed: {fixed_feature_count}, Invalid: {invalid_feature_count}"
)
Expand Down Expand Up @@ -397,13 +403,15 @@ def process_singlepart_geometry(self, geom, normalized_name, area_name):
6) Create clip polygon
7) Optionally create raster mask
"""
# Used to track durations
geometry_start_time = time.time()
# Also grab the current timestamp and write it to the tracking table
now_str = datetime.datetime.strftime("%Y-%m-%d %H:%M:%S")

now = datetime.datetime.now() # Get current datetime
now_str = now.strftime("%Y-%m-%d %H:%M:%S") # Format the datetime object

self.set_status_tracking_table_value(
normalized_name, "timestamp_start", now_str
)

# Compute aligned bounding box in target CRS
# (We already have a coordinate transformation if the source has a known SRS)
geometry_bbox = geom.GetEnvelope() # (xmin, xmax, ymin, ymax)
Expand Down Expand Up @@ -448,7 +456,7 @@ def process_singlepart_geometry(self, geom, normalized_name, area_name):
log_message(f"Creating raster mask for {normalized_name}.")
self.create_raster_mask(geom, aligned_bbox, normalized_name)
self.set_status_tracking_table_value(normalized_name, "mask_processed", 1)
now_str = datetime.datetime.strftime("%Y-%m-%d %H:%M:%S")
now_str = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
self.set_status_tracking_table_value(normalized_name, "timestamp_end", now_str)
self.set_status_tracking_table_value(
normalized_name,
Expand Down Expand Up @@ -675,10 +683,9 @@ def create_and_save_grid(self, normalized_name, geom, bbox):
self.write_chunk(layer, task, normalized_name)
# We use the progress object to notify of progress in the subtask
# And the QgsTask progressChanged signal to track the main task
log_message(
f"XXXXXX Chunks Progress: {int((idx + 1 / chunk_count) * 100)}% XXXXXX"
)
self.feedback.setProgress(int((idx + 1 / chunk_count) * 100))
current_progress = int(idx + 1 / (chunk_count * chunk_size))
log_message(f"XXXXXX Chunks Progress: {current_progress}% XXXXXX")
self.feedback.setProgress(current_progress)

# This is blocking, but we're in a thread
# Crashes QGIS, needs to be refactored to use QgsTask subtasks
Expand Down
1 change: 1 addition & 0 deletions test/test_json_tree_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ def test_status(self):

# Test "Completed successfully"
item.setAttribute("result", "Workflow Completed")
item.setAttribute("result_file", "test_file.tif")
self.assertEqual(
item.getStatus(), "Completed successfully", msg=item.attributesAsMarkdown()
)
Expand Down