Skip to content

Commit

Permalink
agg_filter
Browse files Browse the repository at this point in the history
  • Loading branch information
cefect committed Oct 24, 2022
1 parent a750279 commit cbd2000
Show file tree
Hide file tree
Showing 3 changed files with 131 additions and 38 deletions.
89 changes: 72 additions & 17 deletions floodrescaler/processing/agg_average.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ def get_rlay(attn):
return res_d


def agg_simple(self, inp, scale,
def _agg_simple(self, inp, scale,
context=None, feedback=None,
output='TEMPORARY_OUTPUT',
):
Expand All @@ -242,7 +242,7 @@ def agg_simple(self, inp, scale,



def gdal_calc_1(self, inp, formula, output='TEMPORARY_OUTPUT', **kwargs):
def _gdal_calc_1(self, inp, formula, output='TEMPORARY_OUTPUT', **kwargs):
"""run gdal raster calc on a single raster. useful for masking operations"""

return self._gdal_calc({
Expand All @@ -253,7 +253,7 @@ def gdal_calc_1(self, inp, formula, output='TEMPORARY_OUTPUT', **kwargs):
#'INPUT_B' : None, 'INPUT_C' : None, 'INPUT_D' : None, 'INPUT_E' : None, 'INPUT_F' : None, 'EXTRA' : '', 'OPTIONS' : '',
}, **kwargs)

def gdal_calc_add(self, inpA, inpB, output='TEMPORARY_OUTPUT', **kwargs):
def _gdal_calc_add(self, inpA, inpB, output='TEMPORARY_OUTPUT', **kwargs):
"""add two rasters together"""

pars_d = {
Expand All @@ -268,26 +268,36 @@ def gdal_calc_add(self, inpA, inpB, output='TEMPORARY_OUTPUT', **kwargs):

def _gdal_calc(self, pars_d, context=None, feedback=None):

return processing.run('gdal:rastercalculator', pars_d, context=context, feedback=feedback, is_child_algorithm=True)['OUTPUT']

def agg_direct(self, params, dem1, wsh1, wse1, scale, context=None, feedback=None):
ofp = processing.run('gdal:rastercalculator', pars_d, context=context, feedback=feedback, is_child_algorithm=True)['OUTPUT']

if not os.path.exists(ofp):
raise QgsProcessingException('gdal:rastercalculator failed to get a result for \n%s'%pars_d['FORMULA'])

return ofp



def agg_direct(self, params, dem1, wsh1, wse1, scale, context=None, feedback=None):
"""WSH Averaging method"""
#=======================================================================
# defaults
#=======================================================================
cf_kwargs = dict(context=context, feedback=feedback)

def get_out(attn):
return self.parameterAsOutputLayer(params, getattr(self, attn), context)


#=======================================================================
# compute DEM and WSh
#=======================================================================
# simple DEM aggregate
dem2_fp = self.agg_simple(dem1, scale,
#output=params['OUTPUT_DEM'],
output=get_out(self.OUTPUT_DEM), #gdal doesn't play well with the params
**cf_kwargs)

dem2_fp = self._agg_simple(dem1, scale,
# output=params['OUTPUT_DEM'],
output=get_out(self.OUTPUT_DEM), # gdal doesn't play well with the params
** cf_kwargs)

#simple WSH aggregate
wsh2_fp = self.agg_simple(wsh1, scale, output=get_out(self.OUTPUT_WSH),**cf_kwargs)
# simple WSH aggregate
wsh2_fp = self._agg_simple(wsh1, scale, output=get_out(self.OUTPUT_WSH), **cf_kwargs)

if feedback.isCanceled():
return {}
Expand All @@ -300,18 +310,63 @@ def get_out(attn):
assert os.path.exists(wsh2_fp)

"""throwing processing exception on pytest"""
wsh2_maskd_fp = self.gdal_calc_1(wsh2_fp,'A*(A!=0)/(A!=0)', **cf_kwargs)
wsh2_maskd_fp = self._gdal_calc_1(wsh2_fp,'A*(A!=0)/(A!=0)', **cf_kwargs)

#DEm + WSH
wse2_fp = self.gdal_calc_add(wsh2_maskd_fp, dem2_fp, output=get_out(self.OUTPUT_WSE), **cf_kwargs)
wse2_fp = self._gdal_calc_add(wsh2_maskd_fp, dem2_fp, output=get_out(self.OUTPUT_WSE), **cf_kwargs)



return {self.OUTPUT_DEM:dem2_fp, self.OUTPUT_WSH:wsh2_fp, self.OUTPUT_WSE:wse2_fp}


def agg_filter(self, dem1, wsh1, wse1, scale, context, feedback):
def agg_filter(self, params, dem1, wsh1, wse1, scale, context=None, feedback=None):
"""WSE Averaging method"""
#=======================================================================
# defaults
#=======================================================================
cf_kwargs = dict(context=context, feedback=feedback)

def get_out(attn):
return self.parameterAsOutputLayer(params, getattr(self, attn), context)

#=======================================================================
# compute DEM and WSE
#=======================================================================
# simple DEM aggregate
dem2_fp = self._agg_simple(dem1, scale, output=get_out(self.OUTPUT_DEM), **cf_kwargs)

#simple WSH aggregate
wse2A_fp = self._agg_simple(wsh1, scale,**cf_kwargs)

if feedback.isCanceled():
return {}


#=======================================================================
# filter WSE
#=======================================================================
wse2_mask_fp = self._gdal_calc({
'INPUT_A' : dem2_fp, 'BAND_A' : 1, 'INPUT_B' : wse2A_fp, 'BAND_B' : 1,
#'FORMULA':'B/(A<B)', #WSE / (wet=1, dry=0)
'FORMULA':'B<A', #wet=1, dry=0
'NO_DATA' : -9999, 'OUTPUT' :'TEMPORARY_OUTPUT', 'RTYPE' : 5
}, **cf_kwargs)

wse2_fp = self._gdal_calc({
'INPUT_A' : wse2_mask_fp, 'BAND_A' : 1, 'INPUT_B' : wse2A_fp, 'BAND_B' : 1,
'FORMULA':'B/A', #WSE / (wet=1, dry=0)
'NO_DATA' : -9999, 'OUTPUT' : get_out(self.OUTPUT_WSE), 'RTYPE' : 5
}, **cf_kwargs)


#=======================================================================
# add WSH
#=======================================================================
wsh2_fp = self._gdal_calc_add(wse2_fp, dem2_fp, output=get_out(self.OUTPUT_WSH), **cf_kwargs)


return {self.OUTPUT_DEM:dem2_fp, self.OUTPUT_WSH:wsh2_fp, self.OUTPUT_WSE:wse2_fp}


#===========================================================================
Expand Down
34 changes: 31 additions & 3 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
@author: cefect
'''
import os, pathlib, pytest
import os, pathlib, pytest, logging, sys
from pytest_qgis.utils import clean_qgis_layer
from qgis.core import (
QgsRasterLayer, QgsProject, QgsProcessingFeedback, QgsProcessingContext
Expand All @@ -24,17 +24,45 @@ def get_rlay(caseName, layName):
assert os.path.exists(fp), layName

return QgsRasterLayer(fp, f'{caseName}_{layName}')


class MyFeedBackQ(QgsProcessingFeedback):
"""special feedback object for testing"""

def __init__(self,logger, *args, **kwargs):
self.logger=logger.getChild('FeedBack')
super().__init__(*args, **kwargs)

def pushInfo(self, info):
self.logger.info(info)

def pushDebugInfo(self, info):
self.logger.debug(info)

#===============================================================================
# fixtures
#===============================================================================

@pytest.fixture(scope='session')
def logger():
logging.basicConfig(
#filename='xCurve.log', #basicConfig can only do file or stream
force=True, #overwrite root handlers
stream=sys.stdout, #send to stdout (supports colors)
level=logging.INFO, #lowest level to display
)

return logging.getLogger('r')



@pytest.fixture(scope='session')
def qproj(qgis_app, qgis_processing):
return QgsProject.instance()

@pytest.fixture(scope='session')
def feedback(qproj):
return QgsProcessingFeedback(False)
def feedback(qproj, logger):
return MyFeedBackQ(logger, False)

@pytest.fixture(scope='session')
def context(qproj):
Expand Down
46 changes: 28 additions & 18 deletions tests/test_proc.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,30 @@ def get_out():
'OUTPUT_WSH':get_out(),
'OUTPUT_WSE':get_out()
}

@pytest.mark.dev
@pytest.mark.parametrize('caseName',['SJ2018'])
@pytest.mark.parametrize('scale',[2,
#2.0, 2.1
])
def test_filter(dem, wsh, wse, scale, output_params, context, feedback):

assert isinstance(dem, QgsRasterLayer)
#execute
#with AggAverage() as algo:
algo=AggAverage()
algo.initAlgorithm()
res_d = algo.agg_filter(output_params, dem, wsh, wse, scale, context, feedback)

#validate
assert isinstance(res_d, dict)
assert set(res_d.keys()).symmetric_difference(output_params.keys())==set()


@pytest.mark.parametrize('caseName',['SJ2018'])
@pytest.mark.parametrize('scale',[2, 2.0, 2.1])
@pytest.mark.parametrize('scale',[2,
#2.0, 2.1
])
def test_direct(dem, wsh, wse, scale, output_params, context, feedback):

assert isinstance(dem, QgsRasterLayer)
Expand All @@ -36,27 +58,15 @@ def test_direct(dem, wsh, wse, scale, output_params, context, feedback):
algo.initAlgorithm()
res_d = algo.agg_direct(output_params, dem, wsh, wse, scale, context, feedback)

#validate
assert isinstance(res_d, dict)
assert set(res_d.keys()).symmetric_difference(output_params.keys())==set()

"""throwing a procesing exception on cleanup
spent a few mins trying to debug
code seems to work fine in the GUI so I gave up
"""

#===========================================================================
# del res_d
# del algo
# gc.collect()
#===========================================================================


#validsate
#=======================================================================
# assert isinstance(res_d, dict)
# assert set(res_d.keys()).symmetric_difference(output_params.keys())==set()
#=======================================================================


#===========================================================================
# for k,v in res_d.items():
# assert os.path.exists(v)
#===========================================================================


0 comments on commit cbd2000

Please sign in to comment.