From 6f97b7b510976332dbea1f063f838907f473acc0 Mon Sep 17 00:00:00 2001 From: Felix Oesterle Date: Mon, 7 Apr 2025 11:24:45 +0200 Subject: [PATCH] feat(com6): add scarp algorithm feat(com6scarp): Modifies input parameter to accept a DEM layer, coordinate layer, and perimeter layer feat(com6scarp): enhance scarp integration with automatic output handling - Updated to load scarp results (`asc`/`tif`) automatically into the context with styles applied. --- avaframeConnector_commonFunc.py | 34 ++++++ avaframeConnector_provider.py | 2 + pb_tool.cfg | 1 + runCom6Scarp_algorithm.py | 198 ++++++++++++++++++++++++++++++++ 4 files changed, 235 insertions(+) create mode 100644 runCom6Scarp_algorithm.py diff --git a/avaframeConnector_commonFunc.py b/avaframeConnector_commonFunc.py index e683aad..fae1dd7 100644 --- a/avaframeConnector_commonFunc.py +++ b/avaframeConnector_commonFunc.py @@ -173,6 +173,40 @@ def getDFAPathResults(targetDir): return allDFAPathLayers +def getCom6ScarpResults(targetDir): + """Get results of com6 scarp analysis + + Parameters + ----------- + targetDir: pathlib path + to avalanche directory + Returns + ------- + + """ + from qgis.core import QgsRasterLayer + + avaDir = pathlib.Path(str(targetDir)) + scarpResultsDir = avaDir / "Outputs" / "com6RockAvalanche" / "scarp" + print("--------------") + print(scarpResultsDir) + + globbed = list(scarpResultsDir.glob("*.asc")) + list(scarpResultsDir.glob("*.tif")) + scriptDir = pathlib.Path(__file__).parent + qml = str(scriptDir / "QGisStyles" / "probMap.qml") + + allRasterLayers = list() + for item in globbed: + rstLayer = QgsRasterLayer(str(item), item.stem) + # try: + # rstLayer.loadNamedStyle(qml) + # except: + # pass + + allRasterLayers.append(rstLayer) + + return allRasterLayers + def getAna4ProbAnaResults(targetDir): """Get results of ana4PropAna diff --git a/avaframeConnector_provider.py b/avaframeConnector_provider.py index e524137..063a3c2 100644 --- a/avaframeConnector_provider.py +++ b/avaframeConnector_provider.py @@ -93,6 +93,7 @@ def find_python(): from .runCom2AB_algorithm import runCom2ABAlgorithm from .runCom5SnowSlide_algorithm import runCom5SnowSlideAlgorithm from .runCom6RockAvalanche_algorithm import runCom6RockAvalancheAlgorithm +from .runCom6Scarp_algorithm import runCom6ScarpAlgorithm from .runAna4ProbAna_algorithm import runAna4ProbAnaAlgorithm from .runAna4ProbDirOnly_algorithm import runAna4ProbDirOnlyAlgorithm from .runAna5DFAPathGeneration_algorithm import runAna5DFAPathGenerationAlgorithm @@ -128,6 +129,7 @@ def loadAlgorithms(self): self.addAlgorithm(runCom2ABAlgorithm()) self.addAlgorithm(runCom5SnowSlideAlgorithm()) self.addAlgorithm(runCom6RockAvalancheAlgorithm()) + self.addAlgorithm(runCom6ScarpAlgorithm()) self.addAlgorithm(runAna4ProbAnaAlgorithm()) self.addAlgorithm(runAna4ProbDirOnlyAlgorithm()) self.addAlgorithm(runAna5DFAPathGenerationAlgorithm()) diff --git a/pb_tool.cfg b/pb_tool.cfg index c84530b..bc149e0 100644 --- a/pb_tool.cfg +++ b/pb_tool.cfg @@ -57,6 +57,7 @@ python_files: __init__.py avaframeConnector.py avaframeConnector_provider.py runCom2AB_algorithm.py runCom5SnowSlide_algorithm.py runCom6RockAvalanche_algorithm.py + runCom6Scarp_algorithm.py runAna4ProbAna_algorithm.py runAna4ProbDirOnly_algorithm.py runAna5DFAPathGeneration_algorithm.py diff --git a/runCom6Scarp_algorithm.py b/runCom6Scarp_algorithm.py new file mode 100644 index 0000000..cc78148 --- /dev/null +++ b/runCom6Scarp_algorithm.py @@ -0,0 +1,198 @@ +# -*- coding: utf-8 -*- + +""" +/*************************************************************************** + AvaFrameRunCom1DFA + A QGIS plugin + Connects to AvaFrame + Generated by Plugin Builder: http://g-sherman.github.io/Qgis-Plugin-Builder/ + ------------------- + begin : 2021-08-26 + copyright : (C) 2021 by AvaFrame Team + email : felix@avaframe.org + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +""" + +__author__ = "AvaFrame Team" +__date__ = "2025" +__copyright__ = "(C) 2025 by AvaFrame Team" + +# This will get replaced with a git SHA1 when you do a git archive + +__revision__ = "$Format:%H$" + +from pathlib import Path + +from qgis.PyQt.QtCore import QCoreApplication +from qgis.core import ( + QgsProcessing, + QgsRasterLayer, + QgsProcessingException, + QgsProcessingAlgorithm, + QgsProcessingContext, + QgsProcessingParameterFeatureSource, + QgsProcessingParameterRasterLayer, + QgsProcessingParameterEnum, + QgsProcessingParameterMultipleLayers, + QgsProcessingParameterFolderDestination, + QgsProcessingOutputVectorLayer, + QgsProcessingParameterDefinition, + QgsProcessingOutputMultipleLayers, +) + + +class runCom6ScarpAlgorithm(QgsProcessingAlgorithm): + """ + This is the AvaFrame Connection, i.e. the part running with QGis. For this + connector to work, more installation is needed. See instructions at docs.avaframe.org + """ + + DEM = "DEM" + COORDINATES = "COORDINATES" + PERIMETER = "PERIMETER" + OUTPUT = "OUTPUT" + FOLDEST = "FOLDEST" + + def initAlgorithm(self, config): + """ + Here we define the inputs and output of the algorithm, along + with some other properties. + """ + + self.addParameter( + QgsProcessingParameterRasterLayer(self.DEM, self.tr("DEM layer")) + ) + + self.addParameter( + QgsProcessingParameterFeatureSource( + self.COORDINATES, + self.tr("Coordinate layer"), + defaultValue="", + types=[QgsProcessing.TypeVectorPoint], + ) + ) + + self.addParameter( + QgsProcessingParameterFeatureSource( + self.PERIMETER, + self.tr("Perimeter Layer"), + defaultValue="", + types=[QgsProcessing.TypeVectorAnyGeometry], + ) + ) + + self.addParameter( + QgsProcessingParameterFolderDestination( + self.FOLDEST, self.tr("Destination folder") + ) + ) + + self.addOutput( + QgsProcessingOutputVectorLayer( + self.OUTPUT, + self.tr("Output layer"), + QgsProcessing.TypeVectorAnyGeometry, + ) + ) + + def flags(self): + return super().flags() + + def processAlgorithm(self, parameters, context, feedback): + """ + Here is where the processing itself takes place. + """ + + import avaframe.version as gv + from . import avaframeConnector_commonFunc as cF + + feedback.pushInfo("AvaFrame Version: " + gv.getVersion()) + + sourceDEM = self.parameterAsRasterLayer(parameters, self.DEM, context) + if sourceDEM is None: + raise QgsProcessingException(self.invalidSourceError(parameters, self.DEM)) + + sourcePerimeter = self.parameterAsVectorLayer( + parameters, self.PERIMETER, context + ) + + sourceCoordinates = self.parameterAsVectorLayer( + parameters, self.COORDINATES, context + ) + + sourceFOLDEST = self.parameterAsFile(parameters, self.FOLDEST, context) + + finalTargetDir, targetDir = cF.createFolderStructure(sourceFOLDEST) + + feedback.pushInfo(sourceDEM.source()) + + cF.copyDEM(sourceDEM, targetDir) + + cF.copyShp(sourcePerimeter.source(), targetDir / "Inputs" / "POLYGONS", addToName="_perimeter") + + cF.copyShp(sourceCoordinates.source(), targetDir / "Inputs" / "POINTS",addToName="_coordinates") + + feedback.pushInfo('Starting the tool') + feedback.pushInfo('This might take a while') + feedback.pushInfo('See console for progress') + # + command = ['python', '-m', 'avaframe.runCom6Scarp', str(targetDir)] + cF.runAndCheck(command, self, feedback) + + feedback.pushInfo('Done, start loading the results') + + cF.moveInputAndOutputFoldersToFinal(targetDir, finalTargetDir) + + try: + allRasterResults = cF.getCom6ScarpResults(finalTargetDir) + except: + raise QgsProcessingException(self.tr('Something went wrong with com6Scarp, please check log files')) + + context = cF.addLayersToContext(context, allRasterResults, self.OUTPUT) + + feedback.pushInfo("\n---------------------------------") + feedback.pushInfo("Done, find results and logs here:") + feedback.pushInfo(str(finalTargetDir.resolve())) + feedback.pushInfo("---------------------------------\n") + + return {self.OUTPUT: allRasterResults} + # return + + def name(self): + return "com6scarp" + + def displayName(self): + return self.tr("Scarp (com6)") + + def group(self): + return self.tr(self.groupId()) + + def groupId(self): + return "Experimental" + + def tr(self, string): + return QCoreApplication.translate("Processing", string) + + def shortHelpString(self) -> str: + hstring = "Runs scarp via module com6RockAvalanche. \n\ + For more information go to (or use the help button below): \n\ + AvaFrame Documentation: https://docs.avaframe.org\n\ + Homepage: https://avaframe.org\n\ + Praxisleitfaden: https://avaframe.org/reports\n" + + return self.tr(hstring) + + def helpUrl(self): + return "https://docs.avaframe.org/en/latest/connector.html" + + def createInstance(self): + return runCom6ScarpAlgorithm()