From cde9e9d14a0b5a79ff6a9e4e1f300ace7afd2a92 Mon Sep 17 00:00:00 2001 From: Ben <97883955+benvanbasten-ns@users.noreply.github.com> Date: Thu, 5 Dec 2024 08:59:47 +0100 Subject: [PATCH] Added Processing Algorithm "Extract structure control actions" (#926) (#1066) --- CHANGES.rst | 1 + processing/providers.py | 46 +++++-- .../structure_control_action_algorithms.py | 116 ++++++++++++++++++ 3 files changed, 154 insertions(+), 9 deletions(-) create mode 100644 processing/structure_control_action_algorithms.py diff --git a/CHANGES.rst b/CHANGES.rst index 4c4f6797..aded3729 100755 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,6 +4,7 @@ 3.12 (unreleased) ----------------- +- Added Processing Algorithm "Extract structure control actions" (#926) - Fixed attributeError when loading a QGIS project (#1063) - Fix in Rasters to NetCDF algorithm to properly convert the units Enum to string (#1067) diff --git a/processing/providers.py b/processing/providers.py index 79d86ed2..396e9739 100644 --- a/processing/providers.py +++ b/processing/providers.py @@ -1,24 +1,51 @@ # See https://docs.qgis.org/3.10/en/docs/pyqgis_developer_cookbook/processing.html from qgis.core import QgsProcessingProvider from qgis.PyQt.QtGui import QIcon -from threedi_results_analysis.processing.dwf_calculation_algorithm import DWFCalculatorAlgorithm -from threedi_results_analysis.processing.gpkg_conversion_algorithm import ThreeDiConvertToGpkgAlgorithm -from threedi_results_analysis.processing.grid_creation_algorithm import ThreeDiGenerateCompGridAlgorithm -from threedi_results_analysis.processing.cross_sectional_discharge_algorithm import CrossSectionalDischargeAlgorithm +from threedi_results_analysis.processing.cross_sectional_discharge_algorithm import ( + CrossSectionalDischargeAlgorithm, +) +from threedi_results_analysis.processing.dwf_calculation_algorithm import ( + DWFCalculatorAlgorithm, +) +from threedi_results_analysis.processing.gpkg_conversion_algorithm import ( + ThreeDiConvertToGpkgAlgorithm, +) +from threedi_results_analysis.processing.grid_creation_algorithm import ( + ThreeDiGenerateCompGridAlgorithm, +) from threedi_results_analysis.processing.leak_detector_algorithms import ( DetectLeakingObstaclesAlgorithm, +) +from threedi_results_analysis.processing.leak_detector_algorithms import ( DetectLeakingObstaclesWithDischargeThresholdAlgorithm, ) +from threedi_results_analysis.processing.rasters_to_netcdf_algorithm import ( + RastersToNetCDFAlgorithm, +) from threedi_results_analysis.processing.schematisation_algorithms import ( CheckSchematisationAlgorithm, - MigrateAlgorithm, - ImportSufHydAlgorithm, +) +from threedi_results_analysis.processing.schematisation_algorithms import ( GuessIndicatorAlgorithm, +) +from threedi_results_analysis.processing.schematisation_algorithms import ( ImportHydXAlgorithm, ) -from threedi_results_analysis.processing.rasters_to_netcdf_algorithm import RastersToNetCDFAlgorithm - -from threedi_results_analysis.processing.threedidepth_algorithms import ThreediDepthAlgorithm, ThreediMaxDepthAlgorithm +from threedi_results_analysis.processing.schematisation_algorithms import ( + ImportSufHydAlgorithm, +) +from threedi_results_analysis.processing.schematisation_algorithms import ( + MigrateAlgorithm, +) +from threedi_results_analysis.processing.structure_control_action_algorithms import ( + StructureControlActionAlgorithm, +) +from threedi_results_analysis.processing.threedidepth_algorithms import ( + ThreediDepthAlgorithm, +) +from threedi_results_analysis.processing.threedidepth_algorithms import ( + ThreediMaxDepthAlgorithm, +) import os @@ -41,6 +68,7 @@ def loadAlgorithms(self, *args, **kwargs): self.addAlgorithm(DetectLeakingObstaclesAlgorithm()) self.addAlgorithm(DetectLeakingObstaclesWithDischargeThresholdAlgorithm()) self.addAlgorithm(RastersToNetCDFAlgorithm()) + self.addAlgorithm(StructureControlActionAlgorithm()) def id(self, *args, **kwargs): """The ID of your plugin, used for identifying the provider. diff --git a/processing/structure_control_action_algorithms.py b/processing/structure_control_action_algorithms.py new file mode 100644 index 00000000..d06d5fd4 --- /dev/null +++ b/processing/structure_control_action_algorithms.py @@ -0,0 +1,116 @@ +# -*- coding: utf-8 -*- + +""" +*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +*************************************************************************** +""" +from qgis.core import QgsProcessingAlgorithm +from qgis.core import QgsProcessingException +from qgis.core import QgsProcessingParameterBoolean +from qgis.core import QgsProcessingParameterFile +from qgis.core import QgsProcessingParameterFileDestination +from qgis.core import QgsProject +from qgis.core import QgsVectorLayer +from qgis.PyQt.QtCore import QCoreApplication +from threedigrid.admin.gridresultadmin import GridH5StructureControl +from threedigrid.admin.structure_controls.exporters import ( + structure_control_actions_to_csv, +) + +import os + + +class StructureControlActionAlgorithm(QgsProcessingAlgorithm): + """ + Converts a structure control actions NetCDF to CSV + """ + + SCA_INPUT = "SCA_INPUT" + OUTPUT_FILENAME = "OUTPUT_FILENAME" + GRIDADMIN_INPUT = "GRIDADMIN_INPUT" + ADD_TO_PROJECT = "ADD_TO_PROJECT" + + def tr(self, string): + return QCoreApplication.translate("Processing", string) + + def createInstance(self): + return StructureControlActionAlgorithm() + + def name(self): + return "structure_control_actions_csv" + + def displayName(self): + return self.tr("Convert structure control actions") + + def group(self): + return self.tr("Post-process results") + + def groupId(self): + return "postprocessing" + + def shortHelpString(self): + return self.tr("Convert a structure control actions NetCDF to CSV") + + def initAlgorithm(self, config=None): + # Input parameters + self.addParameter( + QgsProcessingParameterFile(self.GRIDADMIN_INPUT, self.tr("Gridadmin.h5 file"), extension="h5") + ) + self.addParameter( + QgsProcessingParameterFile(self.SCA_INPUT, self.tr("structure_control_actions_3di.nc file"), extension="nc") + ) + self.addParameter( + QgsProcessingParameterBoolean( + self.ADD_TO_PROJECT, self.tr("Add result to project"), defaultValue=True + ) + ) + # output parameters + self.addParameter( + QgsProcessingParameterFileDestination( + self.OUTPUT_FILENAME, + self.tr("Destination CSV file path"), + fileFilter="csv", + ) + ) + + def processAlgorithm(self, parameters, context, feedback): + """ + Create the water depth raster with the provided user inputs + """ + gridadmin_path = parameters[self.GRIDADMIN_INPUT] + results_3di_path = parameters[self.SCA_INPUT] + generated_output_file_path = self.parameterAsFileOutput( + parameters, self.OUTPUT_FILENAME, context + ) + self.csv_output_file = f"{os.path.splitext(generated_output_file_path)[0]}.csv" + + self.add_to_project = self.parameterAsBoolean( + parameters, self.ADD_TO_PROJECT, context + ) + + if not self.csv_output_file: + raise QgsProcessingException(self.invalidSourceError(parameters, self.OUTPUT_FILENAME)) + + # https://threedigrid.readthedocs.io/en/latest/structure_control.html + gst = GridH5StructureControl(gridadmin_path, results_3di_path) + try: + structure_control_actions_to_csv(gst, self.csv_output_file) + except Exception as e: + return {"result": False, "error": str(e)} + + return {"result": True} + + def postProcessAlgorithm(self, context, feedback): + if self.add_to_project: + if self.csv_output_file: + result_layer = QgsVectorLayer( + self.csv_output_file, "Structure control actions" + ) + QgsProject.instance().addMapLayer(result_layer) + return {self.OUTPUT_FILENAME: self.csv_output_file}