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

GRASS: export temp data #284

Merged
merged 27 commits into from
Nov 16, 2023
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
b7b6833
GRASS: export temp data
pesekon2 Nov 10, 2023
e4ceeaf
add new GRASS outputs
pesekon2 Nov 10, 2023
eea3faa
remove polygons from GRASS test outputs
pesekon2 Nov 10, 2023
cb5b692
do not write core
pesekon2 Nov 10, 2023
4db95ef
add -t flag to GRASS: export temporary
pesekon2 Nov 10, 2023
c78af29
add temporary export option to QGIS
pesekon2 Nov 10, 2023
7971ebe
use pygrass module interface
landam Nov 13, 2023
fd819cd
fix cmd tests
landam Nov 13, 2023
d0eef0f
add support for r.mapcalc
landam Nov 13, 2023
875337f
add support for exporiting vector data; merge raster_output_path and …
landam Nov 13, 2023
61cd81a
Merge remote-tracking branch 'origin' into grass_export_temp_data
landam Nov 13, 2023
847573d
fix typo
landam Nov 13, 2023
924a444
Revert "fix typo"
landam Nov 13, 2023
1384f8e
fix typo
landam Nov 13, 2023
13a8b80
solve r.slope.aspect issue
landam Nov 13, 2023
cac4155
do not produce temp data in tests
landam Nov 14, 2023
9eea574
fix stream_z
landam Nov 14, 2023
790194d
GRASS: switch to GML (which is non-binary format)
landam Nov 14, 2023
cc90cf1
QGIS: import temp data if they are exported
pesekon2 Nov 15, 2023
d207fcf
export temporary -> generate temporary
pesekon2 Nov 15, 2023
59e3f05
uncheck temp layers
pesekon2 Nov 15, 2023
f32532e
collapse temp layers
pesekon2 Nov 15, 2023
c561b84
fix the weirdest mistake in the world
pesekon2 Nov 15, 2023
4a192b6
QGIS: import control
pesekon2 Nov 15, 2023
630ff25
change the Advanced tab to have horizontal widgets
pesekon2 Nov 15, 2023
cb0ccdb
add control_point group
pesekon2 Nov 16, 2023
f0fff50
QGIS: push -t checkbox to the first position
pesekon2 Nov 16, 2023
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
6 changes: 5 additions & 1 deletion bin/base/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ def __init__(self, label, section_arguments=()):
),
'channel_properties': Argument('Channel properties table'),
'preparation_only': Argument('Do the data preparation only'),
'generate_temporary': Argument('Generate also temporary data'),
}


Expand All @@ -63,5 +64,8 @@ def __init__(self, label, section_arguments=()):
'Computation options',
('output', 'max_time_step', 'total_time')
),
Section('Advanced', ()) # TODO: Add ('preparation_only',))
Section(
pesekon2 marked this conversation as resolved.
Show resolved Hide resolved
'Advanced',
('generate_temporary', )
) # TODO: Add ('preparation_only',))
]
5 changes: 5 additions & 0 deletions bin/grass/r.smoderp2d/r.smoderp2d.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@
# % key: d
# % description: Perform data preparation only and exit
# %end
# %flag
# % key: t
# % description: Export temporary data
# %end
# %option G_OPT_R_ELEV
# % description: Input surface raster
# % guisection: Data preparation
Expand Down Expand Up @@ -122,6 +126,7 @@

if __name__ == "__main__":
options, flags = gs.parser()
options['t'] = flags['t']

try:
runner = GrassGisRunner()
Expand Down
61 changes: 43 additions & 18 deletions bin/qgis/smoderp2d-plugin/smoderp_2D_dockwidget.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,11 @@
from PyQt5.QtGui import QColor
from PyQt5.QtWidgets import QFileDialog, QProgressBar, QMenu

from qgis.core import QgsProviderRegistry, QgsMapLayerProxyModel, \
QgsRasterLayer, QgsTask, QgsApplication, Qgis, QgsProject, \
QgsRasterBandStats, QgsSingleBandPseudoColorRenderer, QgsGradientColorRamp
from qgis.core import (
QgsProviderRegistry, QgsMapLayerProxyModel, QgsRasterLayer, QgsTask,
QgsApplication, Qgis, QgsProject, QgsRasterBandStats,
QgsSingleBandPseudoColorRenderer, QgsGradientColorRamp, QgsVectorLayer
)
from qgis.utils import iface
from qgis.gui import QgsMapLayerComboBox, QgsFieldComboBox

Expand Down Expand Up @@ -145,6 +147,7 @@ def __init__(self, parent=None):
self.table_stream_shape_code_comboBox = QgsFieldComboBox()
self.table_stream_shape_comboBox = QgsMapLayerComboBox()
self.table_stream_shape_toolButton = QtWidgets.QToolButton()
self.generate_temporary_checkBox = QtWidgets.QCheckBox()
self.run_button = QtWidgets.QPushButton(self.dockWidgetContents)

# set default values
Expand Down Expand Up @@ -240,6 +243,9 @@ def set_widgets(self):
self.arguments['channel_properties'].addWidget(
self.table_stream_shape_toolButton
)
self.arguments['generate_temporary'].addWidget(
self.generate_temporary_checkBox
)

def closeEvent(self, event):
self.closingPlugin.emit()
Expand Down Expand Up @@ -368,7 +374,9 @@ def OnRunButton(self):
# Get input parameters
self._getInputParams()

smoderp_task = SmoderpTask(self._input_params, self._input_maps, self._grass_bin_path)
smoderp_task = SmoderpTask(
self._input_params, self._input_maps, self._grass_bin_path
)

# prepare the progress bar
self.progress_bar = QProgressBar()
Expand Down Expand Up @@ -418,26 +426,42 @@ def _layerColorRamp(layer):
return renderer

def computationFinished(self):
def import_group_layers(group, outdir, ext='asc', show=False):
for map_path in glob.glob(os.path.join(outdir, f'*.{ext}')):
if ext == 'asc':
# raster
layer = QgsRasterLayer(
map_path,
os.path.basename(os.path.splitext(map_path)[0])
)

# set symbology
layer.setRenderer(self._layerColorRamp(layer))
else:
# vector
layer = QgsVectorLayer(
map_path,
os.path.basename(os.path.splitext(map_path)[0])
)

# add layer into group
QgsProject.instance().addMapLayer(layer, False)
node = group.addLayer(layer)
node.setExpanded(False)
node.setItemVisibilityChecked(show is True)
show = False

# show results
root = QgsProject.instance().layerTreeRoot()
group = root.insertGroup(0, self._result_group_name)

outdir = self.main_output_lineEdit.text().strip()
first = True
for map_path in glob.glob(os.path.join(outdir, '*.asc')):
layer = QgsRasterLayer(
map_path, os.path.basename(os.path.splitext(map_path)[0])
)

# set symbology
layer.setRenderer(self._layerColorRamp(layer))
import_group_layers(group, outdir, show=True)

# add layer into group
QgsProject.instance().addMapLayer(layer, False)
node = group.addLayer(layer)
node.setExpanded(False)
node.setItemVisibilityChecked(first is True)
first = False
if self._input_params['t']is True:
temp_group = group.addGroup('temp')
import_group_layers(temp_group, os.path.join(outdir, 'temp'))
import_group_layers(temp_group, os.path.join(outdir, 'temp'), 'gml')

# QGIS bug: group must be collapsed and then expanded
group.setExpanded(False)
Expand Down Expand Up @@ -467,6 +491,7 @@ def _getInputParams(self):
self.table_stream_shape_comboBox.currentText(),
'streams_channel_type_fieldname':
self.table_stream_shape_code_comboBox.currentText(),
't': bool(self.generate_temporary_checkBox.checkState()),
'output': self.main_output_lineEdit.text().strip()
}

Expand Down
16 changes: 2 additions & 14 deletions smoderp2d/providers/arcgis/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,19 +40,7 @@ def output_filepath(self, name):
:param name: layer name to be saved
:return: full path to the dataset
"""
item = self._data_target.get(name)
if item is None or item not in ("temp", "control", "core"):
raise ProviderError(
"Unable to define target in output_filepath: {}".format(name)
)

path = Globals.get_outdir()
# 'core' datasets don't have directory, only the geodatabase
if item in ("temp", "control"):
path = os.path.join(path, item)

path = os.path.join(path, 'data.gdb', name)

path = os.path.join(BaseWriter.output_filepath(self, name, dirname_only=True), 'data.gdb', name)
Logger.debug('File path: {}'.format(path))

return path
Expand All @@ -75,7 +63,7 @@ def _write_raster(self, array, file_output):

arcpy.RasterToASCII_conversion(
raster,
file_output
file_output + self._raster_extension
)


Expand Down
4 changes: 2 additions & 2 deletions smoderp2d/providers/arcgis/data_preparation.py
Original file line number Diff line number Diff line change
Expand Up @@ -365,12 +365,12 @@ def _stream_direction(self, stream, dem_aoi):

# extract elevation for the stream segment vertices
arcpy.ddd.InterpolateShape(
dem_aoi, stream, self.storage.output_filepath("stream_z"), "", "",
dem_aoi, stream, self.storage.output_filepath("stream_aoi_z"), "", "",
"CONFLATE_NEAREST", "VERTICES_ONLY"
)
shape_fieldname = "SHAPE@"

with arcpy.da.SearchCursor(self.storage.output_filepath("stream_z"), [shape_fieldname, segment_id_fieldname]) as segments:
with arcpy.da.SearchCursor(self.storage.output_filepath("stream_aoi_z"), [shape_fieldname, segment_id_fieldname]) as segments:
for row in segments:
startpt = row[0].firstPoint
endpt = row[0].lastPoint
Expand Down
36 changes: 23 additions & 13 deletions smoderp2d/providers/base/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ def __getitem__(cls, key):


class BaseWriter(object):
_raster_extension = '.asc'

def __init__(self):
self._data_target = None

Expand All @@ -58,22 +60,30 @@ def set_data_layers(self, data):
"""
self._data_target = data

@staticmethod
def _raster_output_path(output, directory='core'):
"""Get output raster path.
def output_filepath(self, name, data_type=None, dirname_only=False):
"""
Get correct path to store dataset 'name'.

:param name: layer name to be saved
:param data_type: None to determine target subdirectory from self._data_target
:param dirname_only: True to return only path to parent directory

:param output: raster output name
:param directory: target directory (temp, control)
:return: full path to the dataset
"""
dir_name = os.path.join(Globals.outdir, directory) if directory != 'core' else Globals.outdir
if data_type is None:
data_type = self._data_target.get(name)
if data_type is None or data_type not in ("temp", "control", "core"):
raise ProviderError(
"Unable to define target in output_filepath: {}".format(name)
)

if not os.path.exists(dir_name):
os.makedirs(dir_name)
path = os.path.join(Globals.outdir, data_type) if data_type != 'core' else Globals.outdir
if not os.path.exists(path):
os.makedirs(path)
if dirname_only:
return path

return os.path.join(
dir_name,
output + '.asc'
)
return os.path.join(path, name)

@staticmethod
def _print_array_stats(arr, file_output):
Expand All @@ -100,7 +110,7 @@ def write_raster(self, array, output_name, data_type='core'):
:param output_name: output filename
:param data_type: directory where to write output file
"""
file_output = self._raster_output_path(output_name, data_type)
file_output = BaseWriter.output_filepath(self, output_name, data_type)

self._print_array_stats(
array, file_output
Expand Down
72 changes: 37 additions & 35 deletions smoderp2d/providers/base/data_preparation.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,38 +192,44 @@ def _get_rr_rc(r, c, mat_boundary):


class PrepareDataGISBase(PrepareDataBase):

# complete dictionary of datasets and their type
data_layers = {
'dem_slope_mask': 'temp',
'dem_polygon': 'temp',
'aoi': 'temp',
'aoi_polygon': 'core',
'aoi_mask': 'temp',
'dem_filled': 'temp',
'dem_flowdir': 'temp',
'dem_flowacc': 'temp',
'dem_slope': 'temp',
'dem_aspect': 'temp',
'dem_aoi': 'temp',
'dem_slope_aoi': 'temp',
'dem_flowdir_aoi': 'temp',
'dem_flowacc_aoi': 'temp',
'dem_aspect_aoi': 'temp',
'points_aoi': 'temp',
'soil_veg': 'temp',
'soilveg_aoi': 'temp',
'aoi_buffer': 'temp',
'stream_aoi': 'temp',
"stream_aoi_z": 'temp',
'stream_start': 'temp',
'stream_end': 'temp',
'stream_seg': 'temp',
'ratio_cell': 'temp',
'effect_cont': 'temp',
}

soilveg_fields = {
"k": None, "s": None, "n": None, "pi": None, "ppl": None,
"ret": None, "b": None, "x": None, "y": None, "tau": None, "v": None
}
def __init__(self, writter):
self.storage = writter

# complete dictionary of datasets and their type
self._data_layers = {
'dem_slope_mask': 'temp',
'dem_polygon': 'temp',
'aoi': 'temp',
'aoi_polygon': 'core',
'aoi_mask': 'temp',
'dem_filled': 'temp',
'dem_flowdir': 'temp',
'dem_flowacc': 'temp',
'dem_slope': 'temp',
'dem_aspect': 'temp',
'dem_aoi': 'temp',
'dem_slope_aoi': 'temp',
'dem_flowdir_aoi': 'temp',
'dem_flowacc_aoi': 'temp',
'dem_aspect_aoi': 'temp',
'points_aoi': 'temp',
'soil_veg': 'temp',
'soilveg_aoi': 'temp',
'aoi_buffer': 'temp',
'stream_aoi': 'temp',
"stream_z": 'temp',
'stream_start': 'temp',
'stream_end': 'temp',
'stream_seg': 'temp',
'ratio_cell': 'temp',
'effect_cont': 'temp',
}
# complete list of field names that are supposed not to be changed,
# e.g. in properties tables
self.fieldnames = {
Expand All @@ -246,13 +252,9 @@ def __init__(self, writter):
'channel_q365': 'q365'
}

self.soilveg_fields = {
"k": None, "s": None, "n": None, "pi": None, "ppl": None,
"ret": None, "b": None, "x": None, "y": None, "tau": None, "v": None
}
for sv in self.soilveg_fields.keys():
self._data_layers["soilveg_aoi_{}".format(sv)] = 'temp'
self.storage.set_data_layers(self._data_layers)
self.data_layers["soilveg_aoi_{}".format(sv)] = 'temp'
self.storage.set_data_layers(self.data_layers)

self.stream_shape_fields = [
self.fieldnames['channel_profile'],
Expand Down
2 changes: 1 addition & 1 deletion smoderp2d/providers/cmd/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ def __init__(self):
def _write_raster(self, array, file_output):
"""See base method for description.
"""
np.savetxt(file_output, array, fmt='%.6e')
np.savetxt(file_output + self._raster_extension, array, fmt='%.6e')


class CmdArgumentParser(object):
Expand Down
Loading