diff --git a/.gitignore b/.gitignore index 61c449a..91c42c9 100644 --- a/.gitignore +++ b/.gitignore @@ -128,3 +128,4 @@ dmypy.json # Pyre type checker .pyre/ /zip_build/ +/pixi.lock diff --git a/avaframeConnector_commonFunc.py b/avaframeConnector_commonFunc.py index 68d1124..e7526f4 100644 --- a/avaframeConnector_commonFunc.py +++ b/avaframeConnector_commonFunc.py @@ -53,6 +53,23 @@ def copyRaster(raster, targetDir, suffix): pass +def copyMultipleRaster(rasterDict, targetDir, suffix): + """copies multiple raster files to targetDir with suffix added to filenames + + Parameters + ----------- + rasterDict: + dict with multiple qgis raster layers + targetDir: pathlib.Path + target directory + suffix: string + suffix to add to filename (e.g., "_mu", "_k") + """ + for raster in rasterDict: + print("RAAAAAAAAASTER:", raster) + copyRaster(raster, targetDir, suffix) + + def copyMultipleShp(sourceDict, targetPath, addToName=""): """copies multiple shapefile parts to targetPath diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..83c7712 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,73 @@ +[build-system] +requires = ["setuptools", "setuptools-scm"] +build-backend = "setuptools.build_meta" + +[project] +name = "avaframeconnector" +description = "QGIS Plugin - Connects to AvaFrame" +readme = "README.md" +dynamic = ["version"] +license = { text = "GPL-2.0-or-later" } +authors = [ + { name = "AvaFrame Team", email = "felix@avaframe.org" } +] +urls = { Homepage = "http://avaframe.org", Repository = "https://github.com/OpenNHM/QGisAF" } +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Science/Research", + "Topic :: Scientific/Engineering", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13" +] +requires-python = ">=3.9,<3.14" + +# Setuptools +[tool.setuptools] +include-package-data = true + +[tool.setuptools.packages.find] +exclude = ["docs*", "tests*"] + +[tool.setuptools_scm] +version_scheme = "no-guess-dev" +local_scheme = "node-and-date" + +# Black +[tool.black] +line-length = 109 + +# PIXI setup +[tool.pixi.workspace] +channels = ["https://prefix.dev/conda-forge"] +platforms = ["linux-64"] +#platforms = ["linux-64", "win-64", "osx-64"] + +[tool.pixi.dependencies] +python = "<3.14" +setuptools = "*" +setuptools-scm = "*" + +[tool.pixi.pypi-dependencies] +pb_tool = "*" + +# Feature dev +[tool.pixi.feature.dev.dependencies] +qgis = ">=3.22" +pixi-pycharm = "*" +black = "*" + +[tool.pixi.feature.dev.pypi-dependencies] +avaframe = { path = "../AvaFrame/", editable = true } + +# Feature qgis +[tool.pixi.feature.qgis.dependencies] +qgis = ">=3.22" + +# Environments +[tool.pixi.environments] +default = { features = ["dev"], solve-group = "default" } +dev = ["dev"] +qgis = ["qgis", "dev"] \ No newline at end of file diff --git a/runCom6RockAvalanche_algorithm.py b/runCom6RockAvalanche_algorithm.py index a103b3f..28ea1b6 100644 --- a/runCom6RockAvalanche_algorithm.py +++ b/runCom6RockAvalanche_algorithm.py @@ -8,8 +8,6 @@ __revision__ = "$Format:%H$" -import subprocess -from pathlib import Path from qgis.PyQt.QtCore import QCoreApplication from qgis.core import ( @@ -18,7 +16,6 @@ QgsProcessingAlgorithm, QgsProcessingParameterFeatureSource, QgsProcessingParameterRasterLayer, - QgsProcessingParameterEnum, QgsProcessingParameterMultipleLayers, QgsProcessingParameterFolderDestination, QgsProcessingOutputVectorLayer, @@ -34,8 +31,6 @@ class runCom6RockAvalancheAlgorithm(QgsProcessingAlgorithm): DEM = "DEM" REL = "REL" - RELTH = "RELTH" - SECREL = "SECREL" ENT = "ENT" RES = "RES" OUTPUT = "OUTPUT" @@ -49,31 +44,18 @@ def initAlgorithm(self, config): with some other properties. """ - self.addParameter( - QgsProcessingParameterRasterLayer(self.DEM, self.tr("DEM layer")) - ) - - self.addParameter( - QgsProcessingParameterMultipleLayers( - self.REL, - self.tr("Release layer(s)"), - layerType=QgsProcessing.TypeVectorAnyGeometry, - ) - ) - self.addParameter( QgsProcessingParameterRasterLayer( - self.RELTH, self.tr("Release thickness layer") + self.DEM, self.tr("DEM layer (e.g. elevation tif from Scarp (com6)") ) ) self.addParameter( - QgsProcessingParameterFeatureSource( - self.SECREL, - self.tr("Secondary release layer (only one is allowed)"), - optional=True, + QgsProcessingParameterMultipleLayers( + self.REL, + self.tr("Release layer(s) (e.g. HRel tif from Scarp (com6))"), + layerType=QgsProcessing.TypeRaster, defaultValue="", - types=[QgsProcessing.TypeVectorAnyGeometry], ) ) @@ -137,8 +119,6 @@ def processAlgorithm(self, parameters, context, feedback): if sourceDEM is None: raise QgsProcessingException(self.invalidSourceError(parameters, self.DEM)) - sourceRELTH = self.parameterAsRasterLayer(parameters, self.RELTH, context) - # Release files allREL = self.parameterAsLayerList(parameters, self.REL, context) if allREL is None: @@ -148,12 +128,6 @@ def processAlgorithm(self, parameters, context, feedback): if allREL: relDict = {lyr.source(): lyr for lyr in allREL} - # Secondary release files - sourceSecREL = self.parameterAsVectorLayer(parameters, self.SECREL, context) - if sourceSecREL is not None: - srInfo = "_sec" + Path(sourceSecREL.source()).stem - targetADDTONAME = targetADDTONAME + srInfo - sourceENT = self.parameterAsVectorLayer(parameters, self.ENT, context) sourceRES = self.parameterAsVectorLayer(parameters, self.RES, context) @@ -169,14 +143,11 @@ def processAlgorithm(self, parameters, context, feedback): cF.copyDEM(sourceDEM, targetDir) # copy all release shapefile parts - cF.copyMultipleShp(relDict, targetDir / "Inputs" / "REL", targetADDTONAME) - - # copy all secondary release shapefile parts - if sourceSecREL is not None: - cF.copyShp(sourceSecREL.source(), targetDir / "Inputs" / "SECREL") - if sourceRELTH is not None: - cF.copyShp(sourceRELTH.source(), targetDir / "Inputs" / "RELTH") + for source in relDict: + cF.copyRaster(relDict[source], targetDir / "Inputs" / "REL", "") + # print(relDict) + # cF.copyMultipleRaster(relDict, targetDir / "Inputs" / "REL", targetADDTONAME) # copy all entrainment shapefile parts if sourceENT is not None: @@ -204,7 +175,9 @@ def processAlgorithm(self, parameters, context, feedback): rasterResults = cF.getLatestPeak(finalTargetDir) except: raise QgsProcessingException( - self.tr("Something went wrong with com6RockAvalanche, please check log files") + self.tr( + "Something went wrong with com6RockAvalanche, please check log files" + ) ) allRasterLayers = cF.addStyleToCom1DFAResults(rasterResults) diff --git a/runCom6Scarp_algorithm.py b/runCom6Scarp_algorithm.py index cc78148..3eafeea 100644 --- a/runCom6Scarp_algorithm.py +++ b/runCom6Scarp_algorithm.py @@ -30,23 +30,17 @@ __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, ) @@ -59,6 +53,7 @@ class runCom6ScarpAlgorithm(QgsProcessingAlgorithm): DEM = "DEM" COORDINATES = "COORDINATES" PERIMETER = "PERIMETER" + SCARPMETHOD = "SCARPMETHOD" OUTPUT = "OUTPUT" FOLDEST = "FOLDEST" @@ -68,14 +63,27 @@ def initAlgorithm(self, config): with some other properties. """ + self.addParameter(QgsProcessingParameterRasterLayer(self.DEM, self.tr("DEM layer"))) + self.addParameter( - QgsProcessingParameterRasterLayer(self.DEM, self.tr("DEM layer")) + QgsProcessingParameterEnum( + self.SCARPMETHOD, + self.tr("Scarp method"), + options=[ + self.tr("Plane (requires zseed, dip(dir), slopeangle)"), + self.tr( + "Ellipsoid (requires zseed, maxdepth, semimajor, semiminor, tilt, direc, dip(dir), offset" + ), + ], + defaultValue=0, + allowMultiple=False, + ) ) self.addParameter( QgsProcessingParameterFeatureSource( self.COORDINATES, - self.tr("Coordinate layer"), + self.tr("Coordinate layer (Point shapefile with attributes)"), defaultValue="", types=[QgsProcessing.TypeVectorPoint], ) @@ -84,16 +92,15 @@ def initAlgorithm(self, config): self.addParameter( QgsProcessingParameterFeatureSource( self.PERIMETER, - self.tr("Perimeter Layer"), + self.tr("Perimeter Layer (Polygon shapefile defining boundary area"), defaultValue="", types=[QgsProcessing.TypeVectorAnyGeometry], ) ) + self.addParameter( - QgsProcessingParameterFolderDestination( - self.FOLDEST, self.tr("Destination folder") - ) + QgsProcessingParameterFolderDestination(self.FOLDEST, self.tr("Destination folder")) ) self.addOutput( @@ -121,16 +128,17 @@ def processAlgorithm(self, parameters, context, feedback): if sourceDEM is None: raise QgsProcessingException(self.invalidSourceError(parameters, self.DEM)) - sourcePerimeter = self.parameterAsVectorLayer( - parameters, self.PERIMETER, context - ) + sourcePerimeter = self.parameterAsVectorLayer(parameters, self.PERIMETER, context) - sourceCoordinates = self.parameterAsVectorLayer( - parameters, self.COORDINATES, context - ) + sourceCoordinates = self.parameterAsVectorLayer(parameters, self.COORDINATES, context) sourceFOLDEST = self.parameterAsFile(parameters, self.FOLDEST, context) + # Get the scarp method + scarpMethod = self.parameterAsInt(parameters, self.SCARPMETHOD, context) + scarpOptions = ["plane", "ellipsoid"] + scarpString = scarpOptions[scarpMethod] + finalTargetDir, targetDir = cF.createFolderStructure(sourceFOLDEST) feedback.pushInfo(sourceDEM.source()) @@ -139,23 +147,25 @@ def processAlgorithm(self, parameters, context, feedback): cF.copyShp(sourcePerimeter.source(), targetDir / "Inputs" / "POLYGONS", addToName="_perimeter") - cF.copyShp(sourceCoordinates.source(), targetDir / "Inputs" / "POINTS",addToName="_coordinates") + 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') + 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)] + command = ["python", "-m", "avaframe.runCom6Scarp", str(targetDir), "-m", scarpString] cF.runAndCheck(command, self, feedback) - feedback.pushInfo('Done, start loading the results') + 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')) + raise QgsProcessingException( + self.tr("Something went wrong with com6Scarp, please check log files") + ) context = cF.addLayersToContext(context, allRasterResults, self.OUTPUT)