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

Add layer rename #15

Merged
merged 4 commits into from
Sep 26, 2022
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
50 changes: 50 additions & 0 deletions .github/workflows/runTestSinglePython.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# This workflow will install Python dependencies, run tests and lint with a single version of Python
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions

name: Test with single python version

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
workflow_dispatch:

jobs:
build:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.10'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install flake8 pytest pytest-cov
# This compilation is necessary to have the .c file for the next step
# Alternative is to include the .c file in the repo
- name: Lint with flake8
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --ignore=F821 --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --count --ignore=F821 --exit-zero --max-complexity=10 --max-line-length=127 --statistics
- name: Test with pytest
run: |
pytest -ra --cov --cov-report=xml --cov-config=.coveragerc
# - name: Test & publish code coverage
# uses: paambaati/codeclimate-action@v2.7.5
# env:
# CC_TEST_REPORTER_ID: ${{ secrets.CODECLIMATE_ID }}
# - name: Upload coverage to Codecov
# uses: codecov/codecov-action@v2
# with:
# fail_ci_if_error: false
# name: codecov-umbrella
# verbose: true
32 changes: 32 additions & 0 deletions .pep8speaks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# File : .pep8speaks.yml

scanner:
diff_only: False # If False, the entire file touched by the Pull Request is scanned for errors. If True, only the diff is scanned.
linter: pycodestyle # Other option is flake8

pycodestyle: # Same as scanner.linter value. Other option is flake8
max-line-length: 120 # Default is 79 in PEP 8
ignore: # Errors and warnings to ignore
- W504 # line break after binary operator
- E402 # module level import not at top of file
- E731 # do not assign a lambda expression, use a def
- C406 # Unnecessary list literal - rewrite as a dict literal.
- E741 # ambiguous variable name
- E226 # space around arithmetic operator
- E128 # continuation line under-indented for visual indent
- E126 # continuation line over-indented for visual indent
- W503 # line break before binary operator

no_blank_comment: False # If True, no comment is made on PR without any errors.
descending_issues_order: True # If True, PEP 8 issues in message will be displayed in descending order of line numbers in the file

message: # Customize the comment made by the bot
opened: # Messages when a new PR is submitted
header: "Hello @{name}! Thanks for opening this PR. "
# The keyword {name} is converted into the author's username
footer: "Do see the [Hitchhiker's guide to code style](https://goo.gl/hqbW4r)"
# The messages can be written as they would over GitHub
updated: # Messages when new commits are added to the PR
header: "Hello @{name}! Thanks for updating this PR. "
footer: "" # Why to comment the link to the style guide everytime? :)
no_errors: "There are currently no PEP 8 issues detected in this Pull Request. Cheers! :beers: "
162 changes: 67 additions & 95 deletions avaframeConnector_algorithm.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,7 @@
QgsProcessingOutputMultipleLayers,
QgsProcessingParameterFeatureSink)
from qgis import processing
import avaframe
from avaframe.in3Utils import initializeProject as iP
from avaframe import runOperational as runOp
import avaframe.version as gv



class AvaFrameConnectorAlgorithm(QgsProcessingAlgorithm):
Expand All @@ -78,6 +75,7 @@ class AvaFrameConnectorAlgorithm(QgsProcessingAlgorithm):

DEM = 'DEM'
REL = 'REL'
SECREL = 'SECREL'
ENT = 'ENT'
RES = 'RES'
PROFILE = 'PROFILE'
Expand All @@ -104,9 +102,33 @@ def initAlgorithm(self, config):
# [QgsProcessing.TypeVectorAnyGeometry]
# ))
self.addParameter(QgsProcessingParameterMultipleLayers(
self.REL,
self.tr('Release layer(s)'),
layerType=QgsProcessing.TypeVectorAnyGeometry
self.REL,
self.tr('Release layer(s)'),
layerType=QgsProcessing.TypeVectorAnyGeometry
))

self.addParameter(QgsProcessingParameterMultipleLayers(
self.SECREL,
self.tr('Secondary release layer(s)'),
optional=True,
defaultValue = "",
layerType=QgsProcessing.TypeVectorAnyGeometry
))

self.addParameter(QgsProcessingParameterFeatureSource(
self.ENT,
self.tr('Entrainment layer'),
optional=True,
defaultValue = "",
types=[QgsProcessing.TypeVectorAnyGeometry]
))

self.addParameter(QgsProcessingParameterFeatureSource(
self.RES,
self.tr('Resistance layer'),
optional=True,
defaultValue = "",
types=[QgsProcessing.TypeVectorAnyGeometry]
))

self.addParameter(QgsProcessingParameterFeatureSource(
Expand All @@ -129,23 +151,7 @@ def initAlgorithm(self, config):
self.tr('Destination folder')
))

self.addParameter(QgsProcessingParameterFeatureSource(
self.ENT,
self.tr('Entrainment layer'),
optional=True,
defaultValue = "",
types=[QgsProcessing.TypeVectorAnyGeometry]
))

self.addParameter(QgsProcessingParameterFeatureSource(
self.RES,
self.tr('Resistance layer'),
optional=True,
defaultValue = "",
types=[QgsProcessing.TypeVectorAnyGeometry]
))

# self.addParameter(QgsProcessingParameterBoolean(
# self.addParameter(QgsProcessingParameterBoolean(
# self.SMALLAVA,
# self.tr('Small Avalanche (for com2AB) '),
# optional=True
Expand All @@ -162,26 +168,25 @@ def initAlgorithm(self, config):
)
)
#
def getSHPParts(self, base):
""" Get all files of a shapefile"""

globBase = base.parent
globbed = globBase.glob(base.stem + '.*')

return globbed

def processAlgorithm(self, parameters, context, feedback):
"""
Here is where the processing itself takes place.
"""

from avaframe.in3Utils import initializeProject as iP
from avaframe import runOperational as runOp
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))

#
# Release files
allREL = self.parameterAsLayerList(parameters, self.REL, context)
if allREL is None:
raise QgsProcessingException(self.invalidSourceError(parameters, self.REL))
Expand All @@ -190,6 +195,14 @@ def processAlgorithm(self, parameters, context, feedback):
if allREL:
relDict = {lyr.source(): lyr for lyr in allREL}

# Secondary release files
allSecREL = self.parameterAsLayerList(parameters, self.SECREL, context)

secRelDict = {}
if allSecREL:
secRelDict = {lyr.source(): lyr for lyr in allSecREL}


sourceENT = self.parameterAsVectorLayer(parameters, self.ENT, context)

sourceRES = self.parameterAsVectorLayer(parameters, self.RES, context)
Expand All @@ -201,63 +214,38 @@ def processAlgorithm(self, parameters, context, feedback):
sourceSPLITPOINTS= self.parameterAsVectorLayer(parameters, self.SPLITPOINTS, context)

# create folder structure
# TODO: make sure directory is empty
# targetDir = pathlib.Path('.') / 'TestDir'
targetDir = pathlib.Path(sourceFOLDEST)
iP.initializeFolderStruct(targetDir, removeExisting=True)
iP.initializeFolderStruct(targetDir, removeExisting=False)

feedback.pushInfo(sourceDEM.source())

# copy DEM
sourceDEMPath = pathlib.Path(sourceDEM.source())
targetDEMPath = targetDir / 'Inputs'
try:
shutil.copy(sourceDEMPath, targetDEMPath)
except shutil.SameFileError:
pass
cF.copyDEM(sourceDEM, targetDir)

# copy all release shapefile parts
for sourceREL in relDict:
sourceRELPath = pathlib.Path(sourceREL)
targetRELPath = targetDir / 'Inputs' / 'REL'

shpParts = self.getSHPParts(sourceRELPath)
for shpPart in shpParts:
try:
shutil.copy(shpPart, targetRELPath)
except shutil.SameFileError:
pass
cF.copyMultipleShp(relDict, targetDir / 'Inputs' / 'REL')

# copy all secondary release shapefile parts
cF.copyMultipleShp(secRelDict, targetDir / 'Inputs' / 'SECREL')

# copy all entrainment shapefile parts
if sourceENT is not None:
sourceENTPath = pathlib.Path(sourceENT.source())
targetENTPath = targetDir / 'Inputs' / 'ENT'

shpParts = self.getSHPParts(sourceENTPath)
for shpPart in shpParts:
try:
shutil.copy(shpPart, targetENTPath)
except shutil.SameFileError:
pass
cF.copyShp(sourceENT.source(), targetDir / 'Inputs' / 'ENT')

# copy all resistance shapefile parts
if sourceRES is not None:
sourceRESPath = pathlib.Path(sourceRES.source())
targetRESPath = targetDir / 'Inputs' / 'RES'

shpParts = self.getSHPParts(sourceRESPath)
for shpPart in shpParts:
try:
shutil.copy(shpPart, targetRESPath)
except shutil.SameFileError:
pass
cF.copyShp(sourceRES.source(), targetDir / 'Inputs' / 'RES')

# copy all Splitpoint shapefile parts
if sourceSPLITPOINTS is not None:
cF.copyShp(sourceSPLITPOINTS.source(), targetDir / 'Inputs' / 'POINTS')

# copy all Profile shapefile parts
if sourcePROFILE is not None:
sourcePROFILEPath = pathlib.Path(sourcePROFILE.source())
targetPROFILEPath = targetDir / 'Inputs' / 'LINES'

shpParts = self.getSHPParts(sourcePROFILEPath)
shpParts = cF.getSHPParts(sourcePROFILEPath)

for shpPart in shpParts:
try:
Expand All @@ -271,19 +259,6 @@ def processAlgorithm(self, parameters, context, feedback):
except shutil.SameFileError:
pass

# copy all Splitpoint shapefile parts
if sourceSPLITPOINTS is not None:
sourceSPLITPOINTSPath = pathlib.Path(sourceSPLITPOINTS.source())
targetSPLITPOINTSPath = targetDir / 'Inputs' / 'POINTS'

shpParts = self.getSHPParts(sourceSPLITPOINTSPath)
for shpPart in shpParts:
try:
shutil.copy(shpPart, targetSPLITPOINTSPath)
except shutil.SameFileError:
pass


feedback.pushInfo('Starting the simulations')
feedback.pushInfo('This might take a while')
feedback.pushInfo('Open Plugins -> Python Console to see the progress')
Expand Down Expand Up @@ -356,19 +331,7 @@ def processAlgorithm(self, parameters, context, feedback):
context.project(),
self.OUTPUT))

# context.temporaryLayerStore().addMapLayer(rstLayer)
# context.addLayerToLoadOnCompletion(
# rstLayer.id(),
# QgsProcessingContext.LayerDetails('raster layer',
# context.project(),
# self.OUTPPR))

# context.layerToLoadOnCompletionDetails(rstLayer.id()).setPostProcessor(renamer)

# self.ImportDFA(sourceDIR, Sim, SatGroup)

# iface.layerTreeView().collapseAllNodes()
#
feedback.pushInfo('\n---------------------------------')
feedback.pushInfo('Done, find results and logs here:')
feedback.pushInfo(str(targetDir.resolve()))
Expand All @@ -388,7 +351,7 @@ def name(self):
lowercase alphanumeric characters only and no spaces or other
formatting characters.
"""
return 'AvaFrameConnector'
return 'FullOperationalRun'

def displayName(self):
"""
Expand Down Expand Up @@ -417,5 +380,14 @@ def groupId(self):
def tr(self, string):
return QCoreApplication.translate('Processing', string)

def shortHelpString(self) -> str:
hstring = 'Runs the operational workflow (com1DFA and com2AB). \n\
For more information go to: \n\
AvaFrame Documentation: https://docs.avaframe.org\n\
Homepage: https://avaframe.org\n\
Praxisleitfaden: https://info.bml.gv.at/dam/jcr:edebd872-2a86-4edf-ac5e-635ef11e35fe/Praxisleitfaden%20LawSim%20WLV%202022%20Gr%C3%BCn.pdf\n'

return self.tr(hstring)

def createInstance(self):
return AvaFrameConnectorAlgorithm()
Loading