Skip to content

Commit 0025ef2

Browse files
Merge pull request #69 from NikosMastrantonas/make_mct_rivers_mask
debug tests for mctrivers
2 parents 5dbd6e4 + f889861 commit 0025ef2

File tree

5 files changed

+58
-37
lines changed

5 files changed

+58
-37
lines changed

README.md

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -776,16 +776,34 @@ The tool can take the following additional input arguments:
776776
- `-S`, `--slope`: Riverbed slope threshold to use MCT diffusive wave routing (default: 0.001)
777777
- `-N`, `--nloops`: Number of consecutive downstream grid cells that also need to comply with the slope requirement for including a grid cell in the MCT rivers mask (default: 5)
778778
- `-U`, `--minuparea`: Minimum upstream drainage area for a pixel to be included in the MCT rivers mask (uses the same units as in the -u file) (default: 0)
779-
- `-E`, `--coordsnames`: Coordinates names for lat, lon (in this order with space!) used in the netcdf files
779+
- `-E`, `--coordsnames`: Coordinates names for lat, lon (in this order with space!) used in the netcdf files. The function checks for 3 commonly used names (x, lon, rlon for longitudes, and y, lat, rlat for latitudes). Therefere, it is recommended to keep the default value.
780780

781781
The tool generates the following outputs:
782782

783783
- `-O`, `--outputfilename`: Output file containing the rivers mask where LISFLOOD can use the MCT diffusive wave routing (default: chanmct.nc)
784784

785-
Example of command that will generate an MCT rivers mask with pixels where riverbed slope < 0.001, drainage area > 500 kms and at least 5 downstream pixels meet the same two conditions, considering the units of the upArea.nc file are given in kms:
785+
It can be used either from command line, or also as a python function. Below follow some examples:
786+
787+
Example of command that will generate an MCT rivers mask with pixels where riverbed slope < 0.001 (same as default), drainage area > 500 kms and at least 5 (same as default) downstream pixels meet the same two conditions, considering the units of the upArea.nc file are given in kms:
786788

787789
```bash
788-
mctrivers -i changrad.nc -l ldd.nc -u upArea.nc -O chanmct.nc [-m mask.nc -E y x -S 0.001 -N 5 -U 500 optional]
790+
mctrivers -i changrad.nc -l ldd.nc -u upArea.nc -O chanmct.nc -U 500
791+
```
792+
793+
```python
794+
from lisfloodutilities.mctrivers.mctrivers import mct_mask
795+
mct_mask(channels_slope_file='changrad.nc', ldd_file='ldd.nc', uparea_file='upArea.nc', minuparea=500, outputfile='chanmct.nc')
796+
```
797+
798+
Example of command that will generate an MCT rivers mask with pixels where riverbed slope < 0.0005, drainage area > 0 (same as default) kms and at least 3 downstream pixels meet the same two conditions. Also a mask (mask.nc) will be used, and the coords names in the nc files are "Lat1", "Lon1" for lat, lon respectively:
799+
800+
```bash
801+
mctrivers -i changrad.nc -l ldd.nc -u upArea.nc -O chanmct.nc -m mask.nc -E Lat1 Lon1 -S 0.0005 -N 3
802+
```
803+
804+
```python
805+
from lisfloodutilities.mctrivers.mctrivers import mct_mask
806+
mct_mask(channels_slope_file='changrad.nc', ldd_file='ldd.nc', uparea_file='upArea.nc', mask_file='mask.nc', slp_threshold=0.0005, nloops=3, coords=["Lat1", "Lon1"], outputfile='chanmct.nc')
789807
```
790808

791809

src/lisfloodutilities/mctrivers/mctrivers.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,14 +62,14 @@ def mct_mask(channels_slope_file, ldd_file, uparea_file, mask_file='',
6262
slp_threshold: Riverbed slope threshold to use MCT diffusive wave routing (default: 0.001)
6363
nloops: Number of consecutive downstream grid cells that also need to comply with the slope requirement for including a grid cell in the MCT rivers mask (default: 5)
6464
minuparea: Minimum upstream drainage area for a pixel to be included in the MCT rivers mask (uses the same units as in the -u file) (default: 0)
65-
coords_names: Coordinates names for lat, lon (in this order as list) used in the the netcdf files (default: 'None': checks for commonly used names)
65+
coords_names: Coordinates names for lat, lon (in this order as list) used in the the netcdf files (default: 'None'; checks for commonly used names ['x', 'lon', 'rlon'], similar for lat names)
6666
outputfile: Output file containing the rivers mask where LISFLOOD can use the MCT diffusive wave routing (default: chanmct.nc)
6767
6868
Example for generating an MCT rivers mask with pixels where riverbed slope < 0.001, drainage area > 500 kms and at least 5 downstream pixels meet the same
6969
two conditions, considering the units of the upArea.nc file are given in kms:
7070
7171
mct_mask(channels_slope_file='changrad.nc', ldd_file='ldd.nc', uparea_file='upArea.nc', mask_file='mask.nc',
72-
slp_threshold=0.001, nloops=5, minuparea=0, coords_names=['y' , 'x'],
72+
slp_threshold=0.001, nloops=5, minuparea=500, coords_names=['y' , 'x'],
7373
outputfile='chanmct.nc')
7474
"""
7575
# ---------------- Read LDD (Note that for EFAS5 there is small shift of values for CH)
@@ -78,7 +78,7 @@ def mct_mask(channels_slope_file, ldd_file, uparea_file, mask_file='',
7878
# ---------------- Auxiliary variables
7979
x_checks = ['lon', 'x', 'rlon']
8080
y_checks = ['lat', 'y', 'rlat']
81-
if coords_names[0] == "None":
81+
if coords_names == "None":
8282
x_proj = set(list(LD.coords)) & set(x_checks)
8383
y_proj = set(list(LD.coords)) & set(y_checks)
8484

@@ -167,7 +167,7 @@ def mct_mask(channels_slope_file, ldd_file, uparea_file, mask_file='',
167167
MX = MX.fillna(0)*0+1
168168

169169
# use the exact same coords from channel slope file, just in case there are precision differences
170-
MX = MX.assign_coords(x_proj=x_all, y_proj=y_all)
170+
MX = MX.assign_coords({x_proj: x_all, y_proj: y_all})
171171
LD.close() # close ther LD file, after the check of mask availability
172172

173173
# ---------------- Loop on the basin pixels to find how many MCT pixels they have downstream
Binary file not shown.
Binary file not shown.

tests/test_mctrivers.py

Lines changed: 33 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,61 +2,64 @@
22
import shutil
33
import xarray as xr
44

5-
from lisfloodutilities.compare.nc import NetCDFComparator
6-
75
from lisfloodutilities.mctrivers.mctrivers import mct_mask
86

97

108
def mk_path_out(p):
9+
'make folder for storing output data'
1110
path_out = os.path.join(os.path.dirname(__file__), p)
1211
if os.path.exists(path_out):
13-
shutil.rmtree(path_out)
12+
shutil.rmtree(path_out, ignore_errors=True)
1413
os.mkdir(path_out)
15-
return path_out
14+
1615

1716
class TestMctMask():
1817

1918
case_dir = os.path.join(os.path.dirname(__file__), 'data', 'mctrivers')
2019

21-
def run(self, slp_threshold, nloops, minuparea, coords_names, type):
22-
20+
def run(self, slp_threshold, nloops, minuparea, coords_names, case_name):
21+
'generate the MCT mask'
2322
# setting
24-
self.out_path_ref = os.path.join(self.case_dir, type, 'reference')
25-
self.out_path_run = os.path.join(self.case_dir, type, 'out')
23+
self.out_path_ref = os.path.join(self.case_dir, case_name, 'reference')
24+
self.out_path_run = os.path.join(self.case_dir, case_name, 'out')
2625
mk_path_out(self.out_path_run)
2726

28-
channels_slope_file = os.path.join(self.case_dir, type, 'changrad.nc')
29-
ldd_file = os.path.join(self.case_dir, type, 'ldd.nc')
30-
uparea_file = os.path.join(self.case_dir, type, 'upArea.nc')
31-
mask_file = os.path.join(self.case_dir, type, 'mask.nc')
32-
outputfile = os.path.join(self.out_path_run, 'chanmct.nc')
27+
channels_slope_file = os.path.join(self.case_dir, case_name, 'changrad.nc')
28+
ldd_file = os.path.join(self.case_dir, case_name, 'ldd.nc')
29+
uparea_file = os.path.join(self.case_dir, case_name, 'upArea.nc')
30+
mask_file = os.path.join(self.case_dir, case_name, 'mask.nc')
31+
outputfile = os.path.join(self.out_path_run, 'mctmask.nc')
3332

3433
# generate the mct river mask
35-
mct_mask(channels_slope_file, ldd_file, uparea_file, mask_file, slp_threshold, nloops, minuparea,outputfile)
36-
37-
# compare results with reference
38-
nc_comparator = NetCDFComparator(mask_file, array_equal=True)
39-
nc_comparator.compare_dirs(self.out_path_run, self.out_path_ref)
40-
41-
def teardown_method(self):
42-
print('Cleaning directories')
43-
out_path = os.path.join(self.case_dir, type, 'out')
44-
if os.path.exists(out_path) and os.path.isdir(out_path):
45-
shutil.rmtree(out_path, ignore_errors=True)
34+
mct_mask(channels_slope_file, ldd_file, uparea_file, mask_file, slp_threshold, nloops, minuparea, coords_names, outputfile)
35+
36+
# compare the generated mask with the reference one
37+
ref_file = self.out_path_ref+'/mctmask.nc'
38+
reference = xr.open_dataset(ref_file)
39+
out_file = self.out_path_run+'/mctmask.nc'
40+
generated = xr.open_dataset(out_file)
41+
# check if same based on https://docs.xarray.dev/en/stable/generated/xarray.DataArray.equals.html
42+
all_equal = reference.equals(generated)
43+
generated.close() # needs to be closed otherwise the out folder can't be deleted
44+
45+
if not all_equal:
46+
fail_message = f'Test for mct river mask generation for {case_name} failed. Please check differences between'
47+
fail_message += f' the generated mask "{out_file}" and the expected mask "{ref_file}".'
48+
assert all_equal, fail_message
49+
else:
50+
# if equal just delete the out folder
51+
shutil.rmtree(self.out_path_run, ignore_errors=True)
4652

4753

4854
class TestMctrivers(TestMctMask):
4955

5056
# slp_threshold = 0.001
5157
# nloops = 5
52-
# minuparea = 0
58+
# minuparea = 500*10**6
5359
# coords_names = 'None'
5460

5561
def test_mctrivers_etrs89(self):
56-
self.run(0.001, 5, 0, 'None', 'LF_ETRS89_UseCase')
62+
self.run(0.001, 5, 500*10**6, 'None', 'LF_ETRS89_UseCase')
5763

5864
def test_mctrivers_latlon(self):
59-
self.run( 0.001, 5, 0, 'x' 'y', 'LF_lat_lon_UseCase')
60-
61-
def cleaning(self,):
62-
self.teardown_method()
65+
self.run(0.001, 5, 500*10**6, ['lat', 'lon'], 'LF_lat_lon_UseCase')

0 commit comments

Comments
 (0)