From ecc3bfe19b477bbe95b6f114ae80fd9f6349b974 Mon Sep 17 00:00:00 2001 From: Nikolaos Mastrantonas Date: Mon, 13 Jan 2025 13:42:41 +0000 Subject: [PATCH 1/5] change so that netcdf output is saved outside the mct function --- src/lisfloodutilities/mctrivers/mctrivers.py | 18 ++++++++---------- tests/test_mctrivers.py | 5 +++-- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/lisfloodutilities/mctrivers/mctrivers.py b/src/lisfloodutilities/mctrivers/mctrivers.py index d6f4b2b..7ff04f1 100644 --- a/src/lisfloodutilities/mctrivers/mctrivers.py +++ b/src/lisfloodutilities/mctrivers/mctrivers.py @@ -43,8 +43,7 @@ def getarg(): def mct_mask(channels_slope_file, ldd_file, uparea_file, mask_file='', - slp_threshold=0.001, nloops=5, minuparea=0, coords_names='None', - outputfile='chanmct.nc'): + slp_threshold=0.001, nloops=5, minuparea=0, coords_names='None'): """ Builds a mask of mild sloping rivers for use in LISFLOOD with MCT diffusive river routing. It takes LISFLOOD channels slope map (changrad.nc), the LDD (ldd.nc), @@ -57,7 +56,7 @@ def mct_mask(channels_slope_file, ldd_file, uparea_file, mask_file='', channels_slope_file: LISFLOOD channels gradient map (changrad.nc) ldd_file: LISFLOOD local drain direction file (ldd.nc) - uparea_file: LISFLOOD Uustream area file (upArea.nc) + uparea_file: LISFLOOD Upstream area file (upArea.nc) mask_file: a mask nc file; if not given (default) all cells are considered valid. slp_threshold: Riverbed slope threshold to use MCT diffusive wave routing (default: 0.001) 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) @@ -209,13 +208,11 @@ def mct_mask(channels_slope_file, ldd_file, uparea_file, mask_file='', # mask final data with the mask_file MCT = MCT.where(MX==1) - # lisflood does not read NaNs so the data are saved as boolean 0-1, with 0 being flagged as NaN for python reading - MCT.to_netcdf(outputfile, encoding={"mct_mask": {'_FillValue': 0, 'dtype': 'int8'}}) return MCT def main(): - 'function for runnign from command line' + 'function for running from command line' # ---------------- Read settings args = getarg() channels_slope_file_arg = args.changradfile @@ -228,10 +225,11 @@ def main(): coords_names_arg = args.coordsnames outputfile_arg = args.outputfilename - mct_mask(channels_slope_file=channels_slope_file_arg, ldd_file=ldd_file_arg, uparea_file=uparea_file_arg, mask_file=mask_file_arg, - slp_threshold=slp_threshold_arg, nloops=nloops_arg, minuparea=minuparea_arg, coords_names=coords_names_arg, - outputfile=outputfile_arg) - + mct_final = mct_mask(channels_slope_file=channels_slope_file_arg, ldd_file=ldd_file_arg, uparea_file=uparea_file_arg, mask_file=mask_file_arg, + slp_threshold=slp_threshold_arg, nloops=nloops_arg, minuparea=minuparea_arg, coords_names=coords_names_arg) + # lisflood does not read NaNs so the data are saved as boolean 0-1, with 0 being flagged as NaN for python reading + mct_final.to_netcdf(outputfile_arg, encoding={"mct_mask": {'_FillValue': 0, 'dtype': 'int8'}}) + if __name__ == "__main__": main() \ No newline at end of file diff --git a/tests/test_mctrivers.py b/tests/test_mctrivers.py index 0f9d9a8..5015b9a 100644 --- a/tests/test_mctrivers.py +++ b/tests/test_mctrivers.py @@ -31,8 +31,9 @@ def run(self, slp_threshold, nloops, minuparea, coords_names, case_name): outputfile = os.path.join(self.out_path_run, 'mctmask.nc') # generate the mct river mask - mct_mask(channels_slope_file, ldd_file, uparea_file, mask_file, slp_threshold, nloops, minuparea, coords_names, outputfile) - + mct_final = mct_mask(channels_slope_file, ldd_file, uparea_file, mask_file, slp_threshold, nloops, minuparea, coords_names) + mct_final.to_netcdf(outputfile, encoding={"mct_mask": {'_FillValue': 0, 'dtype': 'int8'}}) + # compare the generated mask with the reference one ref_file = self.out_path_ref+'/mctmask.nc' reference = xr.open_dataset(ref_file) From e601971caa1787edfd142970bc6c4ecd51b41752 Mon Sep 17 00:00:00 2001 From: Nikolaos Mastrantonas Date: Mon, 13 Jan 2025 18:51:34 +0000 Subject: [PATCH 2/5] initial code --- src/lisfloodutilities/profiler/__init__.py | 17 ++ src/lisfloodutilities/profiler/profiler.py | 189 ++++++++++++++++++ .../profiler/LF_ETRS89_UseCase/changrad.nc | Bin 0 -> 22429 bytes tests/data/profiler/LF_ETRS89_UseCase/ldd.nc | Bin 0 -> 15695 bytes .../LF_ETRS89_UseCase/reference/profiler.csv | 33 +++ .../profiler/LF_lat_lon_UseCase/changrad.nc | Bin 0 -> 13622 bytes tests/data/profiler/LF_lat_lon_UseCase/ldd.nc | Bin 0 -> 11886 bytes .../LF_lat_lon_UseCase/reference/profiler.csv | 26 +++ tests/test_profiler.py | 60 ++++++ 9 files changed, 325 insertions(+) create mode 100644 src/lisfloodutilities/profiler/__init__.py create mode 100644 src/lisfloodutilities/profiler/profiler.py create mode 100644 tests/data/profiler/LF_ETRS89_UseCase/changrad.nc create mode 100644 tests/data/profiler/LF_ETRS89_UseCase/ldd.nc create mode 100644 tests/data/profiler/LF_ETRS89_UseCase/reference/profiler.csv create mode 100644 tests/data/profiler/LF_lat_lon_UseCase/changrad.nc create mode 100644 tests/data/profiler/LF_lat_lon_UseCase/ldd.nc create mode 100644 tests/data/profiler/LF_lat_lon_UseCase/reference/profiler.csv create mode 100644 tests/test_profiler.py diff --git a/src/lisfloodutilities/profiler/__init__.py b/src/lisfloodutilities/profiler/__init__.py new file mode 100644 index 0000000..90c039e --- /dev/null +++ b/src/lisfloodutilities/profiler/__init__.py @@ -0,0 +1,17 @@ +""" + +Copyright 2019-2020 European Union + +Licensed under the EUPL, Version 1.2 or as soon they will be approved by the European Commission subsequent versions of the EUPL (the "Licence"); + +You may not use this work except in compliance with the Licence. +You may obtain a copy of the Licence at: + +https://joinup.ec.europa.eu/sites/default/files/inline-files/EUPL%20v1_2%20EN(1).txt + +Unless required by applicable law or agreed to in writing, software distributed under the Licence is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the Licence for the specific language governing permissions and limitations under the Licence. + +""" + diff --git a/src/lisfloodutilities/profiler/profiler.py b/src/lisfloodutilities/profiler/profiler.py new file mode 100644 index 0000000..f24ceec --- /dev/null +++ b/src/lisfloodutilities/profiler/profiler.py @@ -0,0 +1,189 @@ +# This is a script to retrieve from a selected point and variable the values for all downstream points, ordered from upstream to downstream +# It takes the netcdf of the variable of interest, the LDD (ldd.nc) and the coordinates of the point of interest +# It requires PCRaster. +# +# Usage: +# profiler.py -i changrad.nc -l ec_ldd.nc -m mask.nc -u upArea.nc -X 10.01 -Y 24.01 -E y x -O profiler.csv + + +import pcraster as pcr +import xarray as xr +import pandas as pd +import numpy as np +from tqdm import tqdm + +def getarg(): + """ Get program arguments. + + :return: args: namespace of program arguments + """ + import argparse + parser = argparse.ArgumentParser() + parser.add_argument('-i', '--Inputfile', type=str, required=True, + help='Input nc file from where the values of the downstream areas will be extracted') + parser.add_argument('-l', '--LDDfile', type=str, required=True, + help='LISFLOOD LDDD file (ldd.nc)') + parser.add_argument('-X', '--Location_x', type=str, required=True, + help='Longitude of the initial point [use the same projection system as the input nc files!]') + parser.add_argument('-Y', '--Location_y', type=str, required=True, + help='Latitude of the initial point [use the same projection system as the input nc files!]') + parser.add_argument('-E', '--coordsnames', type=str, nargs='+', required=False, default="None", + help='Coords names for lat, lon (in this order with space!) from the netcdf files used') + parser.add_argument('-O', '--outputfilename', type=str, required=False, default="profiler.csv", + help='Output file (profiler.csv)') + args = parser.parse_args() # assign namespace to args + return args + + +def profiler(input_file, ldd_file, x_coord, y_coord, coords_names='None'): + """ + + Creates a dataframe with the values for all grid cells downstream of a user-defined point from a netcdf file specified by the user + + Usage: + The tool requires the following input arguments: + + Inputfile: Input nc file from where the values of the downstream areas will be extracted (e.g., chagrad.nc) + LDDfile: LISFLOOD local drain direction file (ldd.nc) + Location_x: LISFLOOD Uustream area file (upArea.nc) + Location_y: a mask nc file; if not given (default) all cells are considered valid. + 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) + outputfile: Output file containing the extracted values of the downsteam points, their coordinates, and their order in the river network (default: profiler.csv) + + Example: + profiler(input_file='changrad.nc', ldd_file='ldd.nc', Location_x=15.21, Location_y=25.14, coords_names=['y' , 'x']) + """ + # ---------------- Read LDD (Note that for EFAS5 there is small shift of values for CH) + LDD = xr.open_dataset(ldd_file) + input_file = xr.open_dataset(input_file) + + # ---------------- Auxiliary variables + x_checks = ['lon', 'x', 'rlon'] + y_checks = ['lat', 'y', 'rlat'] + if coords_names == "None": + x_proj = set(list(LDD.coords)) & set(x_checks) + y_proj = set(list(LDD.coords)) & set(y_checks) + + if len(x_proj)!=1 or len(y_proj)!=1: + print('Input dataset coords names for lat/lon are not as expected.') + print(f'The available coords are: {list(LDD.coords)}') + print(f'The checked names are {y_checks} and {x_checks} for lat and lon respectively.') + print('Please use -E argument and give the coords names !with space in between! in order: lan lon') + exit(1) + + x_proj = list(x_proj)[0] + y_proj = list(y_proj)[0] + else: + y_proj, x_proj = coords_names + + # assign values of coordinates in both dataset based on LDD, in case of small precision issues + input_file = input_file.assign_coords({y_proj: LDD[y_proj].values, x_proj: LDD[x_proj].values}) + + # ---------------- Process LDD + old_name = [i for i in list(LDD.data_vars) if sorted(LDD[i].dims)==sorted([x_proj, y_proj])] + LDD = LDD.rename({old_name[0]: "ldd"})['ldd'] # only 1 variable complies with above if + + # sometimes the masked value is flagged not with NaN (e.g., with cutmaps it was flagged with 0) + # pcr.Ldd takes only integer values 1-9, so any other value needs to be masked + LDD = LDD.fillna(-1) # fill NaN so it can be converted to integer with no issues + LDD = LDD.astype('int') + LDD = LDD.where((LDD>0) & (LDD<10)).fillna(-1) + + # convert the xarray to pcraster + LDD = LDD.transpose(y_proj, x_proj) # make sure dims order is as pcraster needs + + # ---------------- Set clone map for pcraster + rows, cols = len(LDD[y_proj]), len(LDD[x_proj]) + pcr.setclone(rows, cols, 1, 0, 0) + + ldd_pcr = pcr.numpy2pcr(pcr.Ldd, LDD.values, -1) # missing values in the np are flagged as -1 + + # repair the ldd; needed in case ldd is created from cutmaps, so outlet is not flagged with 5 (pit) + ldd_pcr = pcr.lddrepair(ldd_pcr) + + # ---------------- Get coordinates index for the point of interest + try: + final_point = LDD.sel({y_proj: y_coord, x_proj: x_coord} , method='nearest', tolerance=0.1) + except: + print('The provided coordinates are not valid, please check again!') + exit() + + Y_index = np.argmax(LDD[y_proj].values==final_point[y_proj].values) + X_index = np.argmax(LDD[x_proj].values==final_point[x_proj].values) + + # ---------------- Create a mask with the downstream points + profile_mask_pcr = LDD.fillna(0)*0 + profile_mask_pcr[Y_index, X_index] = 1 + profile_mask_pcr = profile_mask_pcr.astype('int') + + profile_mask_pcr = pcr.numpy2pcr(pcr.Boolean, profile_mask_pcr.values, -1) # convert to Boolean with no NaN (-1 is not possible) + profile_mask_pcr = pcr.path(ldd_pcr, profile_mask_pcr) # get the actual paths + + profile_mask_np = pcr.pcr2numpy(profile_mask_pcr, 0) + ProfPath = LDD.fillna(0)*0+profile_mask_np + ProfPath = ProfPath.where(ProfPath==1) + ProfPath.name = 'Profile' + total_points = int(ProfPath.sum().values) + print(f'There are {total_points} points from the point of interest until the end of the river network') + + # ---------------- Subset data for keeping only the domain of interest, and speeding up the analysis + lats_used = ProfPath.sum(x_proj).where(ProfPath.sum(x_proj)!=0).dropna(y_proj) + lons_used = ProfPath.sum(y_proj).where(ProfPath.sum(y_proj)!=0).dropna(x_proj) + + ProfPath = ProfPath.sel({y_proj:lats_used[y_proj].values, x_proj:lons_used[x_proj].values}) + + input_file = input_file.sel({y_proj: ProfPath[y_proj].values, x_proj: ProfPath[x_proj].values}) + LDD = LDD.sel({y_proj: ProfPath[y_proj].values, x_proj: ProfPath[x_proj].values}) + + # define clone for pcraster for cropped data + rows, cols = len(ProfPath[y_proj]), len(ProfPath[x_proj]) + pcr.setclone(rows, cols, 1, 0, 0) + + rivers_mask_pcr = pcr.numpy2pcr(pcr.Scalar, ProfPath.values, 0) + ldd_pcr = pcr.numpy2pcr(pcr.Ldd, LDD.values, -1) + + # ---------------- Find the order of the points in the river network + # generate initial data with the river mask + downstream_cells_pcr = rivers_mask_pcr + sum_rivers_pcr = rivers_mask_pcr + + # modify data, so that the most downstream point is masked out (otherwise the below loop gives for all points the same value) + downstream_actual_mask_pcr = pcr.downstreamdist(ldd_pcr) + downstream_actual_mask_pcr = pcr.ifthenelse(downstream_actual_mask_pcr == 0, pcr.boolean(0), pcr.boolean(1)) + downstream_actual_mask_pcr = pcr.scalar(downstream_actual_mask_pcr) + + # Loop {number of cells -1} times and use downstream function to find out the order of the cells on the river flow + print('Calculating the order of the identified points') + for loops in tqdm(range(total_points-1)): + downstream_cells_pcr = pcr.downstream(ldd_pcr, downstream_cells_pcr) + downstream_cells_pcr = downstream_cells_pcr*downstream_actual_mask_pcr + sum_rivers_pcr = sum_rivers_pcr + downstream_cells_pcr + + sum_rivers = (ProfPath.fillna(0)*0+pcr.pcr2numpy(sum_rivers_pcr, 0)) + sum_rivers.name = 'order' + + all_data = xr.merge([input_file, LDD, ProfPath, sum_rivers]) + all_data_df = all_data.to_dataframe().reset_index() + all_data_df = all_data_df[~all_data_df.Profile.isna()] + all_data_df = all_data_df.sort_values('order') + + return all_data_df + + +def main(): + 'function for running from command line' + # ---------------- Read settings + args = getarg() + input_file_arg = args.Inputfile + ldd_file_arg = args.LDDfile + x_coord_arg = args.Location_x + y_coord_arg = args.Location_y + coords_names_arg = args.coordsnames + outputfile_arg = args.outputfilename + + data_df = profiler(input_file=input_file_arg, ldd_file=ldd_file_arg, x_coord=x_coord_arg, y_coord=y_coord_arg, coords_names=coords_names_arg) + data_df.to_csv(outputfile_arg) + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/tests/data/profiler/LF_ETRS89_UseCase/changrad.nc b/tests/data/profiler/LF_ETRS89_UseCase/changrad.nc new file mode 100644 index 0000000000000000000000000000000000000000..d5ee310caf4aac32033f88c125462759be930a0b GIT binary patch literal 22429 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 S#JP<7-_0c*si}N|f&T$6YqrJ! literal 0 HcmV?d00001 diff --git a/tests/data/profiler/LF_ETRS89_UseCase/ldd.nc b/tests/data/profiler/LF_ETRS89_UseCase/ldd.nc new file mode 100644 index 0000000000000000000000000000000000000000..5d2cbc30bc92043209160f7f2f3a9ef8f97dcf37 GIT binary patch literal 15695 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 literal 0 HcmV?d00001 diff --git a/tests/data/profiler/LF_ETRS89_UseCase/reference/profiler.csv b/tests/data/profiler/LF_ETRS89_UseCase/reference/profiler.csv new file mode 100644 index 0000000..63ac0b7 --- /dev/null +++ b/tests/data/profiler/LF_ETRS89_UseCase/reference/profiler.csv @@ -0,0 +1,33 @@ +,y,x,changrad,laea,ldd,Profile,order +5,2452500.0,4152500.0,0.0015237641,-2147483647,6.0,1.0,0.0 +148,2417500.0,4132500.0,0.00082243764,-2147483647,6.0,1.0,0.0 +128,2422500.0,4137500.0,0.0004378503,-2147483647,8.0,1.0,0.0 +107,2427500.0,4137500.0,0.00016101284,-2147483647,8.0,1.0,0.0 +103,2432500.0,4222500.0,0.00078742416,-2147483647,9.0,1.0,0.0 +102,2432500.0,4217500.0,0.0006504565,-2147483647,9.0,1.0,0.0 +86,2432500.0,4137500.0,0.0009146803,-2147483647,8.0,1.0,0.0 +83,2437500.0,4227500.0,0.00051658927,-2147483647,6.0,1.0,0.0 +82,2437500.0,4222500.0,0.0007874241,-2147483647,2.0,1.0,0.0 +81,2437500.0,4217500.0,0.0007635837,-2147483647,2.0,1.0,0.0 +80,2437500.0,4212500.0,0.0008235728,-2147483647,6.0,1.0,0.0 +65,2437500.0,4137500.0,0.0017679577,-2147483647,8.0,1.0,0.0 +59,2442500.0,4212500.0,0.0007947716,-2147483647,2.0,1.0,0.0 +45,2442500.0,4142500.0,0.0023591225,-2147483647,8.0,1.0,0.0 +44,2442500.0,4137500.0,0.0018403421,-2147483647,6.0,1.0,0.0 +37,2447500.0,4207500.0,0.0006950562,-2147483647,3.0,1.0,0.0 +36,2447500.0,4202500.0,0.00077848596,-2147483647,8.0,1.0,0.0 +35,2447500.0,4197500.0,0.0009760228,-2147483647,6.0,1.0,0.0 +34,2447500.0,4192500.0,0.0009977153,-2147483647,6.0,1.0,0.0 +25,2447500.0,4147500.0,0.0012041999,-2147483647,9.0,1.0,0.0 +24,2447500.0,4142500.0,0.0017168315,-2147483647,6.0,1.0,0.0 +15,2452500.0,4202500.0,0.0006950562,-2147483647,3.0,1.0,0.0 +13,2452500.0,4192500.0,0.0010435288,-2147483647,2.0,1.0,0.0 +12,2452500.0,4187500.0,0.0010387731,-2147483647,6.0,1.0,0.0 +11,2452500.0,4182500.0,0.0012380448,-2147483647,6.0,1.0,0.0 +10,2452500.0,4177500.0,0.0012613096,-2147483647,6.0,1.0,0.0 +9,2452500.0,4172500.0,0.0011043664,-2147483647,6.0,1.0,0.0 +8,2452500.0,4167500.0,0.0012292609,-2147483647,6.0,1.0,0.0 +7,2452500.0,4162500.0,0.0013680093,-2147483647,6.0,1.0,0.0 +6,2452500.0,4157500.0,0.0012355647,-2147483647,6.0,1.0,0.0 +149,2417500.0,4137500.0,0.0007494286,-2147483647,8.0,1.0,0.0 +168,2412500.0,4127500.0,0.00096970645,-2147483647,9.0,1.0,32.0 diff --git a/tests/data/profiler/LF_lat_lon_UseCase/changrad.nc b/tests/data/profiler/LF_lat_lon_UseCase/changrad.nc new file mode 100644 index 0000000000000000000000000000000000000000..62031f8a7bd04e4459f917c9cb38d730e0907719 GIT binary patch literal 13622 zcmeHM2~-rv7Ht*52v2ncS`FayE>6LG*{6hlCaBI1UC zar0b{T!`z}D2aY0Mt)b%wDOH4=lpa2a{ig(bk|hXeO2$> zehu$3^FxDzEju}NqDV70r%Wju?jwI|)i*z1-3&kG*W>sP?evkMLD9y7>&8NE-NaN6 zcoFQYNWs>Jgk< zykl9`1VK^#bsa?w?~|3qg=*<*Y~)C0jf`{_u6hXHo7j;EySNQyBOpyei8@oFRug{f zxUM>bMqNjl3J6|@B~#CH%{hdLQGN#<E#OW_Hv;()GyyastI`^?oEA_y{5c zLr3ub7`2Eh=vaBtq>+0&96--caQc{wGg1JUOHVS6OUstVKWuaiY zihO*0OcYEN!M&6-!36hA&Ri$B$8si%;O@y8JA%6<)59G|3Wd4Or@`#N8CX)yW zA=hP+u>^NsCRsrCIVO`FBDnoBNi)G!$s~OVu2d$OKyXWCl0t&Zmr0Hg+($CWGlEN% zNd^#HoJ=AoxEPs)9T}Q|0RsaD1`G@s82F!I;7y&9*G14q`HI)|wS4Gi zPIb#=cj&;0BV%J@y;x&%P0h*ax)PYl)zyCGdbM^#?-yTJc5Jt<6ohmBwJS${?+J(3 zOFlk)zNaWAmz5H28n(~eM4oxa9-N)2zGS7$6H?;U$(r~?wVs2#$jmAN(^hcsyQ`FHt-xQW)!G+1tXg^fB#EV3nW`YZan`+bdQGP!+X@^K zG#~gN!CqahY|SYtWrjwjNLMN{v>KH_ zjUF>{qA;kAAZ*L!8KcCoGkEm!?&a(C) ztkhCxsuEI!9)n{&#zcgTX7}U-7(3xP*lUQ$*T-Az?dv5Lv&CX;tWXfAdq=EUaqQSe z6o-e!jHamWtlxy7ZtO)KEiXlRCBpZF3bhM+V;h-kJ0?$k`^M=B1EpC21~0|N#I3=9|; zFfd?Xz`%fk0RsaD1`G@s7%(tkVBkN`K&^HXO=E939T|>6%To~7%jZjh?v%8 zw4+lhlC-=B_VG>7yJRz}>#>c#TYeICEm?})b82C1R60C$i-Z&N_k-n10q(Z%od5pQ zCU{E4P&BZjk#6Z`MgQCo4GRujMI+GHh@3t4Oa;B^r`2de*VE_`2+@b3XW(#78Hyfe4`h9bund2z+)iJb&_P_;V!@pSHK}-k+cvPSUxFMw zF2aIq!MOS3%gEywGc;$^Ja}_Q_RrU0|q0^hl_hdVdBcN!YexEf0qhvEH)=Afp!L$GpGDMYpw z0`7Mi`rXgM^Ky$(^QA&$^ZvK^*V;Mo-O~b;>12zM>nr%pYBIM^&Qo)|>P0qesa3#d zFRS3bSVPmw5SX%IHw=By7jNvh9P+n#p)qH!pdLE_KeG1=xDpqKZZr+xVoeJP!<8~4 z*osb}N#6GKgnBDfy}%Fk4yZ=y4{y<~X?ZB?SULWSXC-~5#hu<7`54gg?y%HMO^a+Y zQAMd0_TFIv^ChKp#>VsTb6ynuxNH`#d2EgqYkaU>nlX&J5r*V;>(Jd{lX19%3!b%L zAo_Hk5GL8KK)EB$xj1YWor9C>>*3YvJg#q;T=lI-_L-di!OX+Hx5-vxU-=rYf!yc7WPiT@8PiuytaSM&$`b7;rLu3Qv z&TRqV+Cc%%Q<*rdTQAU5-a^$SZ;O@IUT zwpXJ^Gv>24y-?PjwP^b1b~tCw7`k)gRj^Zi3e8rTFnG{>_&_Sg(uCot`caMey8>s< z-}~Pe(CMao>59IwXwvvkkm=L)$hjdJ?Hs=yT}JOCxwQx_4e-VqCl|PVelhgC^C3L? zyc7P?e>7ATFGi_D?eN1HtlfbZw6wp7t_|1>*EiU5e3BT;C+wjgWIgtexYL_HF1&;- zr^R6U6E$j(l+i_$F{(UajKnWGfuDy9-n8=$NXH5>INwEzhknq%d?!3emD5Q!`{>NR zOOSTUBlO__GjKI7LS1Wy!E#q6mMlrZ>o@d82lrTlc|RW%@ahZr=28w$eJG;MisG%fbS@diE|*FRBKcZ6)AuF%nuM zcEH+I!BBJGHz5DiFZAF93LmTL2wznfqWYwDsLRo7FnVbxh&$gIB&MyfOX-D~a6dfN zxqv(8=t&GgohPG)!&A|WmGi*L=>oVdY(?Se?s$9UT+E!xqifd~p>0oZqaBVrA#v_m zSih$ylxdvN4cv_8+Ek)6_uXh#^RM)`!I$Vct=7myk%RY!E`;hMpP>QA)KK{TQ8<|s z1h>!3g|njy@RHK0cy{C~`aqZqq&~KQ@_WybS5rMYVRiuJm|Mc)tGhwiI0h>r4`n+I zgsxI=sL%cys{99l-JvDO!ZRBc{osQ7T%z#MMOAEi}K#^TfWdZ2^P$K$g_ ztKhx*%V^(SHxxX08M=^`&&4~a=L#HEx*fz9`ogW`<#6wtPoSyyak|hs6Qu41c>HV; z_Rn&F#-0P2@ zfGE5IPuS8G)!c2tQGu0Q-gew{7?_olacNi`Hx|vvM{}IxaKrU&5L{o3WF-rr{i@xfnuXkH9GJGW2y&N`U)M qG4#&76;Q0|jz<+gfrAbYX{mG_ciq1;2(_&6L)R|uN0UtkqJID-98jqM literal 0 HcmV?d00001 diff --git a/tests/data/profiler/LF_lat_lon_UseCase/ldd.nc b/tests/data/profiler/LF_lat_lon_UseCase/ldd.nc new file mode 100644 index 0000000000000000000000000000000000000000..017b64a3067e6442e1ee9cee5d7530ea6194e13a GIT binary patch literal 11886 zcmeHMeP|q25P$oTz1?)vByCJ%DK#D{MbnVWU7CcpxFL7>*ru0|YpYnZ+cURG53iSS zcWG@%Td5GNl%fb?Rj}eeDy5Vn^`k`|ih@`{5&Wx^;ui{1)IUlDq0YRwFFDhug@OuY zU%7p|GryTP^V_*(ra96V@2RR>T}g21I#EdtyA_vf{>nFViFg+JUE*emeXuV+ESs0* zFw-ll4-;+{@0Bu<5K_aUc-e>d_*P~bZzQsu=lH!154Dd$$O>I%vdh_gb>A=W6hD~$jt7{SX-GGL@mt`qSd3hBw{5>ZX&;hg(U); zu0{kQ_w$XAug|^l0!y{3O_mx^DoNbp9v>ohr4BQ!ZG0Fqz-5uxG7`I{2-h1|aD$6{ zBdUpbjz!VjA)O%qUdBXtK!*gL8wGD#$We9S1JY1$Q#n_XGr4x zTNBAt|6tNhb$1OUhEV&)h^HS&3A#gi$O^5Q%1WH!^D+otP+OviWq$ zGn)vIEQp@UXG^R=!O|?V%y{Dk&nvoKx>%a4tulB4L011LpyhZdEV19JfG%;4$uVwr zlL9)Zamb{P{GSUbUGn1?J-2_;V0YgZ5s$QFL5pvy>{}|ibm=I3m2j>5^uQQ;;Xg`d ztGM)MzTIZ2VyWPl=;lR*U)K4eN|#to{WvYZibpr%WnPP@lh4}I?|gaT!i6<1jgOCw zjn%vK5`t=6`qV4Oj~_Q&x*`^hMirNyMBHBv?LpjChh9e9Zw{SC+%FETL)`ZcJ%zZ7 z4(&tSw+{UdabG!f263M|v>tJvIP^5)&O6jb+*ybIfVk5RJ&3rs9om4nHywHgaj!Xa z0C6ul^e4nU@6e|acf_Hq5%-Kk-$mSvLz9Tx>rlq_q(cuQF6+=Wh#Ph2S;Rf=&<|1m zr)^!q=U;6rjD%datsRK_#9 zZoh3^MO@Cd9z@(O+j0<>vaOJ&8LH+l8FpEfwUBD4ssx)Pp;k9ET}6+Phs==lhvZ2Tls==?Whvtt}03zcFilWLYoCUUM zugS6wCg4_w6J)rPQK&N=oXwU3whEjCU=;$ARM~*=RER`DzwqG;9Ko585PApqAcbt$ zRfV{9@B?zNNAIeRDQJ)poGVF&4q3nrYET(6z!*N5CdSDYnxk(BgZTyGkO|}$$%F7P zD&|0jlOY_`G7R7i8GJz;K)x(XkSIo`=&G#4MKwSzjQyWw@D_s=Fc2^hFmOjQu+XQt zwLC%5{{Ksj@y1(qxHuHxFHc<1RIwhWyun?+RD+9smM|0zZhoRr+I^z7`tW>*yAJ(I zG6#yzR*XoCpA|L&;rPJuI;k-5R)$|5Orm19&Xr;~y5je?XSfLwy`;8eFKKqMm|z4k zZ!m(CpU!apc;~zKBLfX@H(&P$L@M++Xe_MXPZc-fJJ(jBOj7-pm8iK)CX)B_-#ld; zK#=(m=616w2F=Am;KA(RW7yL33k)Lj2AM({W|nc!g(-R8MBz#EUOtNPA+daR!6U>m z>&>&g4X$QGl2))sB;Y;B8lc0wOGG7>g-@$#>RxwoNg-W}*qZ6oAv zh#LvQcf(qF|5b}2L+qGael1*Jp{)EF-^iBS+Ew`eDr!)L#fskeg4y(aLPDUZCMAer zIMI_BP9(b%E{~xe9AXTabSYi*#9$<>uir(ind}}fkN@l8Ll#cF-UcPt&E!jzwWvwq z<-PM)kKSpyiCTU1i`k(2UwepvkffK za*HuV{Ov}JSc~OiP8M?US6S|jkhlD?TRaDQz(Bx2z(Bx2z(Bx2z(Bx2z(Bx2z(Bx2 Lz(Byjf6u_*pw4Qn literal 0 HcmV?d00001 diff --git a/tests/data/profiler/LF_lat_lon_UseCase/reference/profiler.csv b/tests/data/profiler/LF_lat_lon_UseCase/reference/profiler.csv new file mode 100644 index 0000000..241901a --- /dev/null +++ b/tests/data/profiler/LF_lat_lon_UseCase/reference/profiler.csv @@ -0,0 +1,26 @@ +,lat,lon,changrad,ldd,Profile,order +51,53.55000000000207,-122.75000000000324,0.0012226264,3.0,1.0,0.0 +131,52.85000000000211,-122.45000000000326,0.0015036418,2.0,1.0,0.0 +119,52.950000000002106,-122.55000000000325,0.0019222051,3.0,1.0,0.0 +108,53.0500000000021,-122.55000000000325,0.0018676079,2.0,1.0,0.0 +96,53.150000000002095,-122.65000000000325,0.0013966679,3.0,1.0,0.0 +95,53.150000000002095,-122.75000000000324,0.0008484858,6.0,1.0,0.0 +83,53.25000000000209,-122.85000000000323,0.002747498,3.0,1.0,0.0 +74,53.35000000000208,-122.65000000000325,0.0004815376,4.0,1.0,0.0 +73,53.35000000000208,-122.75000000000324,0.00051982753,4.0,1.0,0.0 +72,53.35000000000208,-122.85000000000323,0.0030551292,2.0,1.0,0.0 +63,53.45000000000208,-122.65000000000325,0.00052186823,2.0,1.0,0.0 +142,52.75000000000212,-122.45000000000326,0.00097223686,2.0,1.0,0.0 +153,52.65000000000212,-122.45000000000326,0.0008084648,2.0,1.0,0.0 +29,53.75000000000206,-122.75000000000324,0.00074306637,3.0,1.0,0.0 +18,53.850000000002055,-122.75000000000324,0.0006388169,2.0,1.0,0.0 +15,53.850000000002055,-123.05000000000322,0.0012879174,9.0,1.0,0.0 +14,53.850000000002055,-123.15000000000322,0.000889672,6.0,1.0,0.0 +7,53.95000000000205,-122.75000000000324,0.00071776606,2.0,1.0,0.0 +6,53.95000000000205,-122.85000000000323,0.001410268,6.0,1.0,0.0 +5,53.95000000000205,-122.95000000000323,0.0012500631,6.0,1.0,0.0 +3,53.95000000000205,-123.15000000000322,0.000889672,2.0,1.0,0.0 +2,53.95000000000205,-123.25000000000321,0.00088967197,6.0,1.0,0.0 +1,53.95000000000205,-123.3500000000032,0.0007190692,6.0,1.0,0.0 +41,53.650000000002066,-122.65000000000325,0.0009240197,1.0,1.0,0.0 +0,53.95000000000205,-123.4500000000032,0.0005076786,6.0,1.0,25.0 diff --git a/tests/test_profiler.py b/tests/test_profiler.py new file mode 100644 index 0000000..b5705d7 --- /dev/null +++ b/tests/test_profiler.py @@ -0,0 +1,60 @@ +import os +import shutil +import pandas as pd +import xarray as xr + +from lisfloodutilities.profiler.profiler import profiler + + +def mk_path_out(p): + 'make folder for storing output data' + path_out = os.path.join(os.path.dirname(__file__), p) + if os.path.exists(path_out): + shutil.rmtree(path_out, ignore_errors=True) + os.mkdir(path_out) + + +class TestProfiler(): + + case_dir = os.path.join(os.path.dirname(__file__), 'data', 'profiler') + + def run(self, x_coord, y_coord, coords_names, case_name): + 'generate the profiler data' + # setting + self.out_path_ref = os.path.join(self.case_dir, case_name, 'reference') + self.out_path_run = os.path.join(self.case_dir, case_name, 'out') + mk_path_out(self.out_path_run) + + input_file = os.path.join(self.case_dir, case_name, 'changrad.nc') + ldd_file = os.path.join(self.case_dir, case_name, 'ldd.nc') + outputfile = os.path.join(self.out_path_run, 'profiler.csv') + + profiler(input_file, ldd_file, x_coord, y_coord, coords_names='None') + + # generate the profiler + profiler_data = profiler(input_file, ldd_file, x_coord, y_coord, coords_names) + profiler_data.to_csv(outputfile) + + # compare the generated mask with the reference one + ref_file = self.out_path_ref+'/profiler.csv' + reference = pd.read_csv(ref_file) + out_file = self.out_path_run+'/profiler.csv' + generated = pd.read_csv(out_file) + all_equal = reference.compare(generated) + + if len(all_equal)!=0: + fail_message = f'Test profiler generation for {case_name} failed. Please check differences between' + fail_message += f' the generated mask "{out_file}" and the expected mask "{ref_file}".' + assert all_equal, fail_message + else: + # if equal just delete the out folder + shutil.rmtree(self.out_path_run, ignore_errors=True) + + +class TestProfilers(TestProfiler): + + def test_mctrivers_etrs89(self): + self.run(4127500, 2412500, 'None', 'LF_ETRS89_UseCase') + + def test_mctrivers_latlon(self): + self.run(-123.45, 53.95, ['lat', 'lon'], 'LF_lat_lon_UseCase') \ No newline at end of file From f75149d12e691736f54bc2bc0dcb2ba6e871518a Mon Sep 17 00:00:00 2001 From: Nikolaos Mastrantonas Date: Mon, 13 Jan 2025 19:17:13 +0000 Subject: [PATCH 3/5] update README --- README.md | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/README.md b/README.md index 1dfaa95..c3bc696 100644 --- a/README.md +++ b/README.md @@ -808,6 +808,42 @@ mct_mask_ds = mct_mask(channels_slope_file='changrad.nc', ldd_file='ldd.nc', upa ``` +## profiler + +This tool extracts for all downstream cells from a user-defined point, all values for a selected spatial variable, and saves a csv file with the extracted points, their coordinates, the values of the variable, and the order of the points in the river flow. + +### Usage + +The tool requires the following mandatory input arguments: + +- `-i`, `--inputfile`: Input nc file from where the values of the downstream areas will be extracted (e.g., changrad.nc) +- `-l`, `--LDDfile`: LISFLOOD local drain direction file (ldd.nc) +- `-X`, `--Location_x`: Longitude of the initial point (use the same projection system as the input nc files!) +- `-Y`, `--Location_y`: Longitude of the initial point (use the same projection system as the input nc files!) + +The tool can take the following additional input arguments: + +- `-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. + +The tool generates the following outputs (when called from command line as main script): + +- `-O`, `--outputfilename`: Output file with the points, their location and order in the river flow, and the values of the variable of interest (default: profiler.csv) + +It can be used either from command line, or also as a python function. Below follow some examples: + +Example of command that will generate a profiler csv file for a point with coordinates 10.01, 24.01 lon lat, with coordinates names in the nc being 'x' and 'y' respectively: + +```bash +profiler.py -i changrad.nc -l ec_ldd.nc -m mask.nc -u upArea.nc -X 10.01 -Y 24.01 -O profiler.csv [-E y x] +``` + +```python +# no data are saved when called inside python +from lisfloodutilities.profiler.profiler import profiler +data_df = profiler(input_file='changrad.nc', ldd_file='ldd.nc', Location_x=10.01, Location_y=24.01, coords_names=['y' , 'x']) +``` + + ## Using `lisfloodutilities` programmatically You can use lisflood utilities in your python programs. As an example, the script below creates the mask map for a set of stations (stations.txt). The mask map is a boolean map with 1 and 0. 1 is used for all (and only) the pixels hydrologically connected to one of the stations. The resulting mask map is in pcraster format. From fd89b46a72a503e172c200900910b168495de10b Mon Sep 17 00:00:00 2001 From: Nikolaos Mastrantonas Date: Mon, 13 Jan 2025 19:39:16 +0000 Subject: [PATCH 4/5] fix order of points after using lddrepair --- src/lisfloodutilities/profiler/profiler.py | 1 + .../LF_ETRS89_UseCase/reference/profiler.csv | 62 +++++++++---------- .../LF_lat_lon_UseCase/reference/profiler.csv | 48 +++++++------- 3 files changed, 56 insertions(+), 55 deletions(-) diff --git a/src/lisfloodutilities/profiler/profiler.py b/src/lisfloodutilities/profiler/profiler.py index f24ceec..2045075 100644 --- a/src/lisfloodutilities/profiler/profiler.py +++ b/src/lisfloodutilities/profiler/profiler.py @@ -141,6 +141,7 @@ def profiler(input_file, ldd_file, x_coord, y_coord, coords_names='None'): rivers_mask_pcr = pcr.numpy2pcr(pcr.Scalar, ProfPath.values, 0) ldd_pcr = pcr.numpy2pcr(pcr.Ldd, LDD.values, -1) + ldd_pcr = pcr.lddrepair(ldd_pcr) # need to repair again, because the outlet is (possible) lost due to subsetting # ---------------- Find the order of the points in the river network # generate initial data with the river mask diff --git a/tests/data/profiler/LF_ETRS89_UseCase/reference/profiler.csv b/tests/data/profiler/LF_ETRS89_UseCase/reference/profiler.csv index 63ac0b7..dd267ea 100644 --- a/tests/data/profiler/LF_ETRS89_UseCase/reference/profiler.csv +++ b/tests/data/profiler/LF_ETRS89_UseCase/reference/profiler.csv @@ -1,33 +1,33 @@ ,y,x,changrad,laea,ldd,Profile,order -5,2452500.0,4152500.0,0.0015237641,-2147483647,6.0,1.0,0.0 -148,2417500.0,4132500.0,0.00082243764,-2147483647,6.0,1.0,0.0 -128,2422500.0,4137500.0,0.0004378503,-2147483647,8.0,1.0,0.0 -107,2427500.0,4137500.0,0.00016101284,-2147483647,8.0,1.0,0.0 -103,2432500.0,4222500.0,0.00078742416,-2147483647,9.0,1.0,0.0 -102,2432500.0,4217500.0,0.0006504565,-2147483647,9.0,1.0,0.0 -86,2432500.0,4137500.0,0.0009146803,-2147483647,8.0,1.0,0.0 -83,2437500.0,4227500.0,0.00051658927,-2147483647,6.0,1.0,0.0 -82,2437500.0,4222500.0,0.0007874241,-2147483647,2.0,1.0,0.0 -81,2437500.0,4217500.0,0.0007635837,-2147483647,2.0,1.0,0.0 -80,2437500.0,4212500.0,0.0008235728,-2147483647,6.0,1.0,0.0 -65,2437500.0,4137500.0,0.0017679577,-2147483647,8.0,1.0,0.0 -59,2442500.0,4212500.0,0.0007947716,-2147483647,2.0,1.0,0.0 -45,2442500.0,4142500.0,0.0023591225,-2147483647,8.0,1.0,0.0 -44,2442500.0,4137500.0,0.0018403421,-2147483647,6.0,1.0,0.0 -37,2447500.0,4207500.0,0.0006950562,-2147483647,3.0,1.0,0.0 -36,2447500.0,4202500.0,0.00077848596,-2147483647,8.0,1.0,0.0 -35,2447500.0,4197500.0,0.0009760228,-2147483647,6.0,1.0,0.0 -34,2447500.0,4192500.0,0.0009977153,-2147483647,6.0,1.0,0.0 -25,2447500.0,4147500.0,0.0012041999,-2147483647,9.0,1.0,0.0 -24,2447500.0,4142500.0,0.0017168315,-2147483647,6.0,1.0,0.0 -15,2452500.0,4202500.0,0.0006950562,-2147483647,3.0,1.0,0.0 -13,2452500.0,4192500.0,0.0010435288,-2147483647,2.0,1.0,0.0 -12,2452500.0,4187500.0,0.0010387731,-2147483647,6.0,1.0,0.0 -11,2452500.0,4182500.0,0.0012380448,-2147483647,6.0,1.0,0.0 -10,2452500.0,4177500.0,0.0012613096,-2147483647,6.0,1.0,0.0 -9,2452500.0,4172500.0,0.0011043664,-2147483647,6.0,1.0,0.0 -8,2452500.0,4167500.0,0.0012292609,-2147483647,6.0,1.0,0.0 -7,2452500.0,4162500.0,0.0013680093,-2147483647,6.0,1.0,0.0 -6,2452500.0,4157500.0,0.0012355647,-2147483647,6.0,1.0,0.0 -149,2417500.0,4137500.0,0.0007494286,-2147483647,8.0,1.0,0.0 +83,2437500.0,4227500.0,0.00051658927,-2147483647,6.0,1.0,1.0 +103,2432500.0,4222500.0,0.00078742416,-2147483647,9.0,1.0,2.0 +82,2437500.0,4222500.0,0.0007874241,-2147483647,2.0,1.0,3.0 +102,2432500.0,4217500.0,0.0006504565,-2147483647,9.0,1.0,4.0 +81,2437500.0,4217500.0,0.0007635837,-2147483647,2.0,1.0,5.0 +80,2437500.0,4212500.0,0.0008235728,-2147483647,6.0,1.0,6.0 +59,2442500.0,4212500.0,0.0007947716,-2147483647,2.0,1.0,7.0 +37,2447500.0,4207500.0,0.0006950562,-2147483647,3.0,1.0,8.0 +15,2452500.0,4202500.0,0.0006950562,-2147483647,3.0,1.0,9.0 +36,2447500.0,4202500.0,0.00077848596,-2147483647,8.0,1.0,10.0 +35,2447500.0,4197500.0,0.0009760228,-2147483647,6.0,1.0,11.0 +34,2447500.0,4192500.0,0.0009977153,-2147483647,6.0,1.0,12.0 +13,2452500.0,4192500.0,0.0010435288,-2147483647,2.0,1.0,13.0 +12,2452500.0,4187500.0,0.0010387731,-2147483647,6.0,1.0,14.0 +11,2452500.0,4182500.0,0.0012380448,-2147483647,6.0,1.0,15.0 +10,2452500.0,4177500.0,0.0012613096,-2147483647,6.0,1.0,16.0 +9,2452500.0,4172500.0,0.0011043664,-2147483647,6.0,1.0,17.0 +8,2452500.0,4167500.0,0.0012292609,-2147483647,6.0,1.0,18.0 +7,2452500.0,4162500.0,0.0013680093,-2147483647,6.0,1.0,19.0 +6,2452500.0,4157500.0,0.0012355647,-2147483647,6.0,1.0,20.0 +5,2452500.0,4152500.0,0.0015237641,-2147483647,6.0,1.0,21.0 +25,2447500.0,4147500.0,0.0012041999,-2147483647,9.0,1.0,22.0 +24,2447500.0,4142500.0,0.0017168315,-2147483647,6.0,1.0,23.0 +45,2442500.0,4142500.0,0.0023591225,-2147483647,8.0,1.0,24.0 +44,2442500.0,4137500.0,0.0018403421,-2147483647,6.0,1.0,25.0 +65,2437500.0,4137500.0,0.0017679577,-2147483647,8.0,1.0,26.0 +86,2432500.0,4137500.0,0.0009146803,-2147483647,8.0,1.0,27.0 +107,2427500.0,4137500.0,0.00016101284,-2147483647,8.0,1.0,28.0 +128,2422500.0,4137500.0,0.0004378503,-2147483647,8.0,1.0,29.0 +149,2417500.0,4137500.0,0.0007494286,-2147483647,8.0,1.0,30.0 +148,2417500.0,4132500.0,0.00082243764,-2147483647,6.0,1.0,31.0 168,2412500.0,4127500.0,0.00096970645,-2147483647,9.0,1.0,32.0 diff --git a/tests/data/profiler/LF_lat_lon_UseCase/reference/profiler.csv b/tests/data/profiler/LF_lat_lon_UseCase/reference/profiler.csv index 241901a..14166e9 100644 --- a/tests/data/profiler/LF_lat_lon_UseCase/reference/profiler.csv +++ b/tests/data/profiler/LF_lat_lon_UseCase/reference/profiler.csv @@ -1,26 +1,26 @@ ,lat,lon,changrad,ldd,Profile,order -51,53.55000000000207,-122.75000000000324,0.0012226264,3.0,1.0,0.0 -131,52.85000000000211,-122.45000000000326,0.0015036418,2.0,1.0,0.0 -119,52.950000000002106,-122.55000000000325,0.0019222051,3.0,1.0,0.0 -108,53.0500000000021,-122.55000000000325,0.0018676079,2.0,1.0,0.0 -96,53.150000000002095,-122.65000000000325,0.0013966679,3.0,1.0,0.0 -95,53.150000000002095,-122.75000000000324,0.0008484858,6.0,1.0,0.0 -83,53.25000000000209,-122.85000000000323,0.002747498,3.0,1.0,0.0 -74,53.35000000000208,-122.65000000000325,0.0004815376,4.0,1.0,0.0 -73,53.35000000000208,-122.75000000000324,0.00051982753,4.0,1.0,0.0 -72,53.35000000000208,-122.85000000000323,0.0030551292,2.0,1.0,0.0 -63,53.45000000000208,-122.65000000000325,0.00052186823,2.0,1.0,0.0 -142,52.75000000000212,-122.45000000000326,0.00097223686,2.0,1.0,0.0 -153,52.65000000000212,-122.45000000000326,0.0008084648,2.0,1.0,0.0 -29,53.75000000000206,-122.75000000000324,0.00074306637,3.0,1.0,0.0 -18,53.850000000002055,-122.75000000000324,0.0006388169,2.0,1.0,0.0 -15,53.850000000002055,-123.05000000000322,0.0012879174,9.0,1.0,0.0 -14,53.850000000002055,-123.15000000000322,0.000889672,6.0,1.0,0.0 -7,53.95000000000205,-122.75000000000324,0.00071776606,2.0,1.0,0.0 -6,53.95000000000205,-122.85000000000323,0.001410268,6.0,1.0,0.0 -5,53.95000000000205,-122.95000000000323,0.0012500631,6.0,1.0,0.0 -3,53.95000000000205,-123.15000000000322,0.000889672,2.0,1.0,0.0 -2,53.95000000000205,-123.25000000000321,0.00088967197,6.0,1.0,0.0 -1,53.95000000000205,-123.3500000000032,0.0007190692,6.0,1.0,0.0 -41,53.650000000002066,-122.65000000000325,0.0009240197,1.0,1.0,0.0 +153,52.65000000000212,-122.45000000000326,0.0008084648,2.0,1.0,1.0 +142,52.75000000000212,-122.45000000000326,0.00097223686,2.0,1.0,2.0 +131,52.85000000000211,-122.45000000000326,0.0015036418,2.0,1.0,3.0 +119,52.950000000002106,-122.55000000000325,0.0019222051,3.0,1.0,4.0 +108,53.0500000000021,-122.55000000000325,0.0018676079,2.0,1.0,5.0 +96,53.150000000002095,-122.65000000000325,0.0013966679,3.0,1.0,6.0 +95,53.150000000002095,-122.75000000000324,0.0008484858,6.0,1.0,7.0 +83,53.25000000000209,-122.85000000000323,0.002747498,3.0,1.0,8.0 +72,53.35000000000208,-122.85000000000323,0.0030551292,2.0,1.0,9.0 +73,53.35000000000208,-122.75000000000324,0.00051982753,4.0,1.0,10.0 +74,53.35000000000208,-122.65000000000325,0.0004815376,4.0,1.0,11.0 +63,53.45000000000208,-122.65000000000325,0.00052186823,2.0,1.0,12.0 +51,53.55000000000207,-122.75000000000324,0.0012226264,3.0,1.0,13.0 +41,53.650000000002066,-122.65000000000325,0.0009240197,1.0,1.0,14.0 +29,53.75000000000206,-122.75000000000324,0.00074306637,3.0,1.0,15.0 +18,53.850000000002055,-122.75000000000324,0.0006388169,2.0,1.0,16.0 +7,53.95000000000205,-122.75000000000324,0.00071776606,2.0,1.0,17.0 +6,53.95000000000205,-122.85000000000323,0.001410268,6.0,1.0,18.0 +5,53.95000000000205,-122.95000000000323,0.0012500631,6.0,1.0,19.0 +15,53.850000000002055,-123.05000000000322,0.0012879174,9.0,1.0,20.0 +14,53.850000000002055,-123.15000000000322,0.000889672,6.0,1.0,21.0 +3,53.95000000000205,-123.15000000000322,0.000889672,2.0,1.0,22.0 +2,53.95000000000205,-123.25000000000321,0.00088967197,6.0,1.0,23.0 +1,53.95000000000205,-123.3500000000032,0.0007190692,6.0,1.0,24.0 0,53.95000000000205,-123.4500000000032,0.0005076786,6.0,1.0,25.0 From f2a507c71d06825559d6596b4bfb6cb93d063cdb Mon Sep 17 00:00:00 2001 From: Nikolaos Mastrantonas Date: Fri, 21 Feb 2025 15:41:51 +0000 Subject: [PATCH 5/5] minor corrections on sample bash --- README.md | 4 ++-- src/lisfloodutilities/profiler/profiler.py | 7 +++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index c3bc696..267d63b 100644 --- a/README.md +++ b/README.md @@ -834,13 +834,13 @@ It can be used either from command line, or also as a python function. Below fol Example of command that will generate a profiler csv file for a point with coordinates 10.01, 24.01 lon lat, with coordinates names in the nc being 'x' and 'y' respectively: ```bash -profiler.py -i changrad.nc -l ec_ldd.nc -m mask.nc -u upArea.nc -X 10.01 -Y 24.01 -O profiler.csv [-E y x] +profiler.py -i changrad.nc -l ec_ldd.nc -X 10.01 -Y 24.01 -O profiler.csv [-E y x] ``` ```python # no data are saved when called inside python from lisfloodutilities.profiler.profiler import profiler -data_df = profiler(input_file='changrad.nc', ldd_file='ldd.nc', Location_x=10.01, Location_y=24.01, coords_names=['y' , 'x']) +data_df = profiler(input_file='changrad.nc', ldd_file='ldd.nc', x_coord=10.01, y_coord=24.01, coords_names=['y' , 'x']) ``` diff --git a/src/lisfloodutilities/profiler/profiler.py b/src/lisfloodutilities/profiler/profiler.py index 2045075..51d8ee3 100644 --- a/src/lisfloodutilities/profiler/profiler.py +++ b/src/lisfloodutilities/profiler/profiler.py @@ -3,14 +3,13 @@ # It requires PCRaster. # # Usage: -# profiler.py -i changrad.nc -l ec_ldd.nc -m mask.nc -u upArea.nc -X 10.01 -Y 24.01 -E y x -O profiler.csv +# profiler.py -i changrad.nc -l ldd.nc -X 10.01 -Y 24.01 -E y x -O profiler.csv import pcraster as pcr import xarray as xr import pandas as pd import numpy as np -from tqdm import tqdm def getarg(): """ Get program arguments. @@ -155,7 +154,7 @@ def profiler(input_file, ldd_file, x_coord, y_coord, coords_names='None'): # Loop {number of cells -1} times and use downstream function to find out the order of the cells on the river flow print('Calculating the order of the identified points') - for loops in tqdm(range(total_points-1)): + for loops in range(total_points-1): downstream_cells_pcr = pcr.downstream(ldd_pcr, downstream_cells_pcr) downstream_cells_pcr = downstream_cells_pcr*downstream_actual_mask_pcr sum_rivers_pcr = sum_rivers_pcr + downstream_cells_pcr @@ -187,4 +186,4 @@ def main(): if __name__ == "__main__": - main() \ No newline at end of file + main()