Skip to content

Commit

Permalink
merge master
Browse files Browse the repository at this point in the history
  • Loading branch information
landam committed Jun 11, 2024
2 parents 19b5a62 + 32e8392 commit 4fa67f5
Show file tree
Hide file tree
Showing 249 changed files with 17,016 additions and 12,695 deletions.
10 changes: 10 additions & 0 deletions .github/workflows/cmd_provider.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ jobs:
with:
pytest-suite: tests/test_cmd.py --config config_files/quicktest_stream_rill.ini

# smoderp2d-quicktest-implicit-stream-rill:
# uses: ./.github/workflows/cmd_template.yml
# with:
# pytest-suite: tests/test_cmd.py --config config_files/quicktest_stream_rill.ini --hidden_config config_files/.config_implicit.ini --reference_dir data/reference/quicktest_implicit_stream_rill/

smoderp2d-longtest-sheet:
uses: ./.github/workflows/cmd_template.yml
with:
Expand All @@ -59,6 +64,11 @@ jobs:
with:
pytest-suite: tests/test_cmd.py --config config_files/test_stream_rill_mfda.ini

# smoderp2d-longtest-implicit-stream-rill-mfda:
# uses: ./.github/workflows/cmd_template.yml
# with:
# pytest-suite: tests/test_cmd.py --config config_files/test_stream_rill_mfda.ini --hidden_config config_files/.config_implicit.ini --reference_dir data/reference/test_implicit_stream_rill_mfda/

smoderp2d-longtest-stream-rill-mfda-diffusion:
uses: ./.github/workflows/cmd_template.yml
with:
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/requirements3.11.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
pytest
numpy==1.23.5
matplotlib==3.6.3
scipy==1.11.3
2 changes: 2 additions & 0 deletions .github/workflows/requirements3.12.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
pytest==8.2.0
numpy==1.26.4
matplotlib==3.6.3
scipy==1.11.3
2 changes: 2 additions & 0 deletions .github/workflows/requirements3.9.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
pytest==7.2.2
numpy==1.26.4
matplotlib==3.5.3
scipy==1.7.3
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
*.pyc
*~
*.swp

tests/data/log
tests/data/output*
Expand All @@ -16,6 +17,8 @@ tests/data/reference/gistest_*/*/control/*.prj
tests/data/reference/gistest_*/*/temp/*.prj
tests/log

tests/grassdata/

bin/qgis/smoderp2d-plugin/smoderp2d/
bin/qgis/smoderp2d-plugin/zip_build/

Expand All @@ -30,3 +33,7 @@ smoderp2d.egg-info
# direnv
.envrc
.direnv

#rfiles
.Rhistory
.RData
71 changes: 17 additions & 54 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ Distributed event-based model for surface and subsurface runoff and erosion.
\___________________ @ @ @ @ @ @ @
```

User documentation: <https://storm-fsv-cvut.github.io/smoderp2d-manual/>

## How to test

Download SMODERP2D source code to your computer.
Expand All @@ -39,7 +41,7 @@ docker build \
--tag smoderp2d:latest --file docker/Dockerfile .
```

Run SMODERP command line tool from Docker container:
Run SMODERP2D command line tool from Docker container:

```sh
docker run \
Expand All @@ -48,82 +50,43 @@ docker run \
--config tests/config_files/quicktest_stream_rill.ini
```

### Run locally
#### GRASS GIS

Build and install SMODERP2D Python package:
Build an image with GRASS GIS support:

```sh
pip install .
docker build \
--tag smoderp2d-grass:latest --file docker/grass/Dockerfile .
```

#### Command line
Run SMODERP2D with GRASS GIS provider from Docker container:

```sh
./bin/start-smoderp2d.py --config tests/config_files/quicktest_stream_rill.ini
docker run \
-v `pwd`:/opt/smoderp2d -w /opt/smoderp2d/ --rm --entrypoint \
./tests/run_grass_gistest.sh smoderp2d-grass \
nucice
```

#### GRASS GIS

Note: GRASS GIS 8.3+ required

Create testing mapset:

```sh
grass --text -c tests/grassdata/smoderp2d-location/test/
```
### Run locally

Run `r.smoderp2d` module:
#### Command line

```sh
PYTHONPATH=$PYTHONPATH:`pwd` ./bin/grass/r.smoderp2d/r.smoderp2d.py \
elevation=dem@PERMANENT \
soil=soils@PERMANENT \
soil_type_fieldname=Soil \
vegetation=landuse@PERMANENT \
vegetation_type_fieldname=LandUse \
rainfall_file=tests/data/rainfall_nucice.txt \
maxdt=5 end_time=5 \
points=points@PERMANENT points_fieldname='point_id' \
table_soil_vegetation=soil_veg_tab@PERMANENT \
table_soil_vegetation_fieldname=soilveg \
streams=streams@PERMANENT \
channel_properties_table=streams_shape@PERMANENT \
streams_channel_type_fieldname=channel_id \
output=tests/data/output
PYTHONPATH=$PYTHONPATH:`pwd` ./bin/start-smoderp2d.py --config tests/config_files/quicktest_stream_rill.ini
```

#### ArcGIS Pro

Launch SMODERP2D ArcToolbox from `bin\arcgis` directory.

![SMODERP2D ArcToolbox in action](img/arctoolbox.png?raw=true "SMODERP2D ArcToolbox in action")

#### QGIS

Requirements: QGIS 3.28.10 and higher

Define `QGIS_PLUGINPATH` and `PYTHONPATH` environmental variables in
`Settings -> Options -> System` and restart QGIS:

![SMODERP2D QGIS settings](img/qgis_settings.png?raw=true "QGIS settings")
`Settings -> Options -> System` and restart QGIS.

Than enable SMODERP2D plugin in `Plugins -> Manage and Install Plugins...`.

Alternatively set up environment variables in command line before starting QGIS:

```sh
PYTHONPATH=`pwd` QGIS_PLUGINPATH=`pwd`/bin/qgis qgis tests/data/nucice/qgis_project.qgz
PYTHONPATH=$PYTHONPATH:`pwd` QGIS_PLUGINPATH=`pwd`/bin/qgis qgis tests/data/nucice/qgis_project.qgz
```

#### Known issue

On MS Windows QGIS plugin suffers by poping-up windows when starting computation.
This can be solved by copying ``core.py`` file located in ``smoderp2d\bin\qgis\grass_patch``
to a GRASS target directory.

GRASS target directory is typically located in:

- ``C:\Program Files\QGIS 3.**.*\apps\grass\grass83\etc\python\grass\script`` in the case that QGIS has been installed by standalone installer, or
- ``C:\OSGeo4W\apps\grass\grass83\etc\python\grass\script`` in the case that QGIS has been installed by OSGeo4W network installer.

Update: This bug has been fixed in GRASS GIS 8.4.
6 changes: 4 additions & 2 deletions bin/arcgis/SMODERP2D.pyt
Original file line number Diff line number Diff line change
Expand Up @@ -250,17 +250,19 @@ class SMODERP2D(object):

def execute(self, parameters, messages):
"""The source code of the tool."""
runner = None
try:
runner = ArcGisRunner()

runner.set_options(
self._get_input_params(parameters)
)

runner.run()
except ProviderError as e:
arcpy.AddError(e)

if runner is not None:
runner.finish()

return

@staticmethod
Expand Down
2 changes: 1 addition & 1 deletion bin/arcgis/SMODERP2D.pyt.xml
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<metadata xml:lang="cs"><Esri><CreaDate>20230116</CreaDate><CreaTime>10441900</CreaTime><ArcGISFormat>1.0</ArcGISFormat><SyncOnce>TRUE</SyncOnce><ModDate>20240410</ModDate><ModTime>132913</ModTime></Esri><toolbox name="SMODERP2D" alias=""><arcToolboxHelpPath>e:\arcgis pro\Resources\Help\gp</arcToolboxHelpPath><toolsets/></toolbox><dataIdInfo><idCitation><resTitle>SMODERP2D</resTitle></idCitation></dataIdInfo><distInfo><distributor><distorFormat><formatName>ArcToolbox Toolbox</formatName></distorFormat></distributor></distInfo></metadata>
<metadata xml:lang="cs"><Esri><CreaDate>20230116</CreaDate><CreaTime>10441900</CreaTime><ArcGISFormat>1.0</ArcGISFormat><SyncOnce>TRUE</SyncOnce><ModDate>20240605</ModDate><ModTime>111141</ModTime></Esri><toolbox name="SMODERP2D" alias=""><arcToolboxHelpPath>c:\program files\arcgis\pro\Resources\Help\gp</arcToolboxHelpPath><toolsets/></toolbox><dataIdInfo><idCitation><resTitle>SMODERP2D</resTitle></idCitation></dataIdInfo><distInfo><distributor><distorFormat><formatName>ArcToolbox Toolbox</formatName></distorFormat></distributor></distInfo></metadata>
80 changes: 80 additions & 0 deletions bin/grass/batch_process.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#!/usr/bin/env python3

import os
import sys
import argparse

from smoderp2d.runners.grass import GrassGisRunner
from smoderp2d.exceptions import ProviderError, MaxIterationExceeded

def run_process(params, epsg):
retcode = 0
runner = None
try:
runner = GrassGisRunner()
runner.create_location(f'EPSG:{epsg}')
runner.set_options(params)
runner.import_data()
runner.run()
except (ProviderError, MaxIterationExceeded) as e:
print(f'ERORR: {e}', file=sys.stderr)
retcode = 1

if runner is not None:
runner.finish()

return retcode

def main(params, epsg):
sys.exit(run_process(params, epsg))

if __name__ == "__main__":
parser = argparse.ArgumentParser(
prog='batch_process',
description='Run SMODERP2D as batch process'
)
parser.add_argument('--elevation', required=True)
parser.add_argument('--soil', required=True)
parser.add_argument('--soil_type_fieldname', required=True)
parser.add_argument('--vegetation', required=True)
parser.add_argument('--vegetation_type_fieldname', required=True)
parser.add_argument('--rainfall_file', required=True)
parser.add_argument('--end_time', required=True)
parser.add_argument('--maxdt', required=True)
parser.add_argument('--table_soil_vegetation', required=True)
parser.add_argument('--table_soil_vegetation_fieldname', required=True)
parser.add_argument('--output', required=True)
parser.add_argument('--points')
parser.add_argument('--points_fieldname')
parser.add_argument('--streams')
parser.add_argument('--channel_properties_table')
parser.add_argument('--streams_channel_type_fieldname')
parser.add_argument('--flow_direction', default='single')
parser.add_argument('--wave', default='kinematic')
parser.add_argument('--generate_temporary', action='store_true')
parser.add_argument('--epsg', default=5514)

args = parser.parse_args()

main({
'elevation': args.elevation,
'soil': args.soil,
'soil_type_fieldname': args.soil_type_fieldname,
'vegetation': args.vegetation,
'vegetation_type_fieldname': args.vegetation_type_fieldname,
'rainfall_file': args.rainfall_file,
'end_time': args.end_time,
'maxdt': args.maxdt,
'output': args.output,
'points': args.points,
'points_fieldname': args.points_fieldname,
'streams': args.streams,
'table_soil_vegetation': args.table_soil_vegetation,
'table_soil_vegetation_fieldname': args.table_soil_vegetation_fieldname,
'channel_properties_table': args.channel_properties_table,
'streams_channel_type_fieldname': args.streams_channel_type_fieldname,
'flow_direction': args.flow_direction,
'wave': args.wave,
'generate_temporary': bool(args.generate_temporary)
}, epsg=args.epsg
)
66 changes: 66 additions & 0 deletions bin/grass/batch_process_csv.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#!/usr/bin/env python3

import sys
import argparse
import csv

from smoderp2d.exceptions import ProviderError, MaxIterationExceeded

from batch_process import run_process

def get_params_epsg(params):
epsg = params.pop('epsg')

return params, int(epsg)

def run_process_single(params, epsg):
# run single process
print('-' * 80)
print(f'Run process with {params}...')
print('-' * 80)

return run_process(params, epsg)

def main(csv_file, workers):
# collect params
params = []
with open(csv_file, newline='') as fd:
reader = csv.DictReader(fd, delimiter=';')
for row in reader:
if row['epsg'].startswith('#'):
# skip commented rows
continue
for k, v in row.items():
if v in ('true', 'false'):
row[k] = True if v.lower() == 'true' else False
params.append(row)

# check for duplicated output paths
output_paths = set(p['output'] for p in params)
if len(params) != len(output_paths):
sys.exit("ERROR: Duplicated output paths detected")

# run processes
if workers > 1:
from joblib import Parallel, delayed

Parallel(n_jobs=workers, backend="multiprocessing", verbose=10)(
delayed(run_process_single)(*get_params_epsg(p)) for p in params
)
else:
for p in params:
run_process_single(*get_params_epsg(p))

if __name__ == "__main__":
parser = argparse.ArgumentParser(
prog='batch_process_csv',
description='Run SMODERP2D as batch processes from CSV',
epilog=r'Usage: PYTHONPATH=`pwd` python3 bin/grass/batch_process_csv.py --csv \ bin/grass/batch_process.csv'
)

parser.add_argument('--csv', required=True)
parser.add_argument('--workers', default=1)

args = parser.parse_args()

main(args.csv, int(args.workers))
11 changes: 4 additions & 7 deletions bin/grass/r.smoderp2d/r.smoderp2d.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,19 +137,16 @@

from smoderp2d.runners.grass import GrassGisRunner
from smoderp2d.providers.base import WorkflowMode
from smoderp2d.exceptions import ProviderError
from smoderp2d.exceptions import ProviderError, MaxIterationExceeded

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

try:
runner = GrassGisRunner()

runner.set_options(options)

sys.exit(
runner.run()
)
except ProviderError as e:
runner.run()
runner.finish()
except (ProviderError, MaxIterationExceeded) as e:
gs.fatal(e)
2 changes: 1 addition & 1 deletion bin/qgis/grass_patch/core.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
Core functions to be used in Python scripts.
Core functions to be used in Python scripts (SMODERP2D patch applied).
Usage:
Expand Down
Loading

0 comments on commit 4fa67f5

Please sign in to comment.