From 239d936826b202183fd8ed6b4e1654fe46f2acb1 Mon Sep 17 00:00:00 2001 From: Bart Schilperoort Date: Fri, 25 Oct 2024 10:03:49 +0200 Subject: [PATCH 01/11] Convert units upload loading netCDF --- src/HBV/utils.py | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/src/HBV/utils.py b/src/HBV/utils.py index b0ac486..6c0ef88 100644 --- a/src/HBV/utils.py +++ b/src/HBV/utils.py @@ -37,7 +37,28 @@ def load_var(ncfile: str | Path, varname: str) -> xr.DataArray: data = load_precip(forcing.directory / forcing.pr) """ with dask.config.set(scheduler="synchronous"): - data = xr.load_dataset(ncfile) - assert "time" in data.dims - assert varname in data.data_vars - return data[varname] + data: xr.Dataset = xr.load_dataset(ncfile) + + if "time" not in data.dims: + msg = "No time dim in data!" + raise ValueError(msg) + if varname not in data.dims: + msg = f"Variable '{varname} is missing from the forcing data!" + raise ValueError(msg) + + da = data[varname] + + if "unit" in da.attrs: ## CF-convention is 'units' not 'unit' + da.attrs["units"] = da.attrs.pop("unit") + + if "units" in da.attrs: # Must have units attr to be able to check + if da.attrs["units"] in ["kg m-2 s-1", "kg s-1 m-2"]: + with xr.set_options(keep_attrs=True): + da = da * 86400 + da.attrs.update({"units": "mm/d"}) + elif da.attrs["units"] == "K": + with xr.set_options(keep_attrs=True): + da -= 273.15 + da.attrs.update({"units": "degC"}) + + return da From 144924f052babebf7798065cea2f058f35d088b3 Mon Sep 17 00:00:00 2001 From: Bart Schilperoort Date: Fri, 25 Oct 2024 10:09:06 +0200 Subject: [PATCH 02/11] Add gitignore file --- .gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0cafc1c --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.venv/ \ No newline at end of file From 1b3a64c529a1b3a7c4f1ec6ae2e2d627c0c271da Mon Sep 17 00:00:00 2001 From: Bart Schilperoort Date: Fri, 25 Oct 2024 10:09:19 +0200 Subject: [PATCH 03/11] Setup test data --- tests/data/Derived_Makkink_evspsblpot.nc | Bin 0 -> 27368 bytes .../OBS6_ERA5_reanaly_1_day_pr_1997-2000.nc | Bin 0 -> 51882 bytes ...reanaly_1_day_pr_1997-2000_citation.bibtex | 17 +++ ..._reanaly_1_day_pr_1997-2000_provenance.xml | 116 +++++++++++++++++ .../OBS6_ERA5_reanaly_1_day_rsds_1997-2000.nc | Bin 0 -> 53865 bytes ...analy_1_day_rsds_1997-2000_citation.bibtex | 17 +++ ...eanaly_1_day_rsds_1997-2000_provenance.xml | 120 ++++++++++++++++++ .../OBS6_ERA5_reanaly_1_day_tas_1997-2000.nc | Bin 0 -> 55671 bytes ...eanaly_1_day_tas_1997-2000_citation.bibtex | 17 +++ ...reanaly_1_day_tas_1997-2000_provenance.xml | 116 +++++++++++++++++ tests/data/ewatercycle_forcing.yaml | 8 ++ tests/test_model.py | 0 12 files changed, 411 insertions(+) create mode 100644 tests/data/Derived_Makkink_evspsblpot.nc create mode 100644 tests/data/OBS6_ERA5_reanaly_1_day_pr_1997-2000.nc create mode 100644 tests/data/OBS6_ERA5_reanaly_1_day_pr_1997-2000_citation.bibtex create mode 100644 tests/data/OBS6_ERA5_reanaly_1_day_pr_1997-2000_provenance.xml create mode 100644 tests/data/OBS6_ERA5_reanaly_1_day_rsds_1997-2000.nc create mode 100644 tests/data/OBS6_ERA5_reanaly_1_day_rsds_1997-2000_citation.bibtex create mode 100644 tests/data/OBS6_ERA5_reanaly_1_day_rsds_1997-2000_provenance.xml create mode 100644 tests/data/OBS6_ERA5_reanaly_1_day_tas_1997-2000.nc create mode 100644 tests/data/OBS6_ERA5_reanaly_1_day_tas_1997-2000_citation.bibtex create mode 100644 tests/data/OBS6_ERA5_reanaly_1_day_tas_1997-2000_provenance.xml create mode 100644 tests/data/ewatercycle_forcing.yaml create mode 100644 tests/test_model.py diff --git a/tests/data/Derived_Makkink_evspsblpot.nc b/tests/data/Derived_Makkink_evspsblpot.nc new file mode 100644 index 0000000000000000000000000000000000000000..03a2c2c672e6dde4c92af956c6b14aeaaed52ddf GIT binary patch literal 27368 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 X(HKihLvKsxz53JBz;GH7v{3pV!!IJh literal 0 HcmV?d00001 diff --git a/tests/data/OBS6_ERA5_reanaly_1_day_pr_1997-2000.nc b/tests/data/OBS6_ERA5_reanaly_1_day_pr_1997-2000.nc new file mode 100644 index 0000000000000000000000000000000000000000..7ab7b4719ad4f457dedf9d0dea3e14600497c578 GIT binary patch literal 51882 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 ao!mUJdEA6C4HJz?&0`xUp4{<-H~v4{K|}xm literal 0 HcmV?d00001 diff --git a/tests/data/OBS6_ERA5_reanaly_1_day_pr_1997-2000_citation.bibtex b/tests/data/OBS6_ERA5_reanaly_1_day_pr_1997-2000_citation.bibtex new file mode 100644 index 0000000..2e233d6 --- /dev/null +++ b/tests/data/OBS6_ERA5_reanaly_1_day_pr_1997-2000_citation.bibtex @@ -0,0 +1,17 @@ +@article{righi20gmd, + doi = {10.5194/gmd-13-1179-2020}, + url = {https://doi.org/10.5194/gmd-13-1179-2020}, + year = {2020}, + month = mar, + publisher = {Copernicus {GmbH}}, + volume = {13}, + number = {3}, + pages = {1179--1199}, + author = {Mattia Righi and Bouwe Andela and Veronika Eyring and Axel Lauer and Valeriu Predoi and Manuel Schlund and Javier Vegas-Regidor and Lisa Bock and Bj"{o}rn Br"{o}tz and Lee de Mora and Faruk Diblen and Laura Dreyer and Niels Drost and Paul Earnshaw and Birgit Hassler and Nikolay Koldunov and Bill Little and Saskia Loosveldt Tomas and Klaus Zimmermann}, + title = {Earth System Model Evaluation Tool (ESMValTool) v2.0 -- technical overview}, + journal = {Geoscientific Model Development} +} + +@misc{acknow_project, + title = "Please acknowledge the project(s)." +} diff --git a/tests/data/OBS6_ERA5_reanaly_1_day_pr_1997-2000_provenance.xml b/tests/data/OBS6_ERA5_reanaly_1_day_pr_1997-2000_provenance.xml new file mode 100644 index 0000000..75d9ca3 --- /dev/null +++ b/tests/data/OBS6_ERA5_reanaly_1_day_pr_1997-2000_provenance.xml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + CF-1.7 + Contains modified Copernicus Climate Change Service Information 2020 + + + + + + + + + + + + + + + + + + + + + Generic lumped forcing recipe + [] + + + + + + + ERA5 + ERA5 + diagnostic + 2000 + /home/bschilpero/esmvaltool_output/ewcrepl6i8wpsb_20241024_145905/preproc/diagnostic/pr/OBS6_ERA5_reanaly_1_day_pr_1997-2000.nc + day + Precipitation + day + ['atmos'] + pr + pr + OBS6 + 0 + pr + precipitation_flux + 1997 + 3 + 1997/2000 + reanaly + kg m-2 s-1 + pr + 1 + {'operator': 'mean'} + {'shapefile': PosixPath('/home/bschilpero/Forcing/camelsgb_73010/caravan/camelsgb_73010.shp'), 'crop': True, 'decomposed': False} + {} + {'compress': False, 'filename': PosixPath('/home/bschilpero/esmvaltool_output/ewcrepl6i8wpsb_20241024_145905/preproc/diagnostic/pr/OBS6_ERA5_reanaly_1_day_pr_1997-2000.nc')} + + + + + + + + CF-1.7 + Contains modified Copernicus Climate Change Service Information 2020 + + + + Forcings for generic hydrological model + ('global',) + ['acknow_project'] + script + /opt/conda/envs/ewatercycle2/lib/python3.12/site-packages/ewatercycle/esmvaltool/diagnostic/copier.py + + + + + + + + + + + + + + + + + + Unseen University + + + + + CF-1.7 + Contains modified Copernicus Climate Change Service Information 2020 + + + CF-1.7 + Contains modified Copernicus Climate Change Service Information 2020 + + diff --git a/tests/data/OBS6_ERA5_reanaly_1_day_rsds_1997-2000.nc b/tests/data/OBS6_ERA5_reanaly_1_day_rsds_1997-2000.nc new file mode 100644 index 0000000000000000000000000000000000000000..631e9e18bfc29cd33b6dbb4bc17fa9fd99a1e1c4 GIT binary patch literal 53865 zcmeI)36vD&x$yBCkbTfXK|nB;g1aCn1QnF3_XR}RN&yiyQpk)jf>1Jph`1CYB7$0q zY;mC!6^#pp7{vuCcN7eT`x?uragSx(lNi75ng3&Ao!onKzkAR5&iM|LD?k1{_4LzI zJ>5MtoV#G~fI+QW?$)wV^X7(p{K!Ym^9`5u;1loPck34;1`jyCQRTgj_Nu?Eu?)#b z(Uy&jit>@BS^l+G$MUa+adiVm!{_+qBR4f%>iqnZP1~2dVuwatyu)czt7lJFW<=0-ue%*9F=zY{53XOm9C_G zHG^uVOgUlvlo{3k^2YzGYbk#bl|xIXp>!=f8qLcaYwN~Otr|bQYTVTEXI2}#l-BHD z`mcQMYiCS9ef)&#aaGf1PMujjWlGJ|iQ{S~O`BdfbNt!W<4&J4K*;{OQ{E<=RFzT$?rEAJ=A$lxwq&A7527zOH84)Jm&-9vT}>8?I}{ z)S9~5`dd}L)5^DMjCE$WLn=p>?wrz5ts9P-P`Y*F&aAGRG_9)P;GP^@HGbB(X{V2y zRXu+C5mv*mXI77&YE3Eas+&<&eS}rMvHZ6D8N+z{)Qx$=_sn$_|MmAw|I!U8f7nK^ zRz|NMOW&1Ec5L{bk;jQ)+;Fsfhg2G!R@EPF+=VY-^PS6=H?G)qM#JZC>(-#rw)_ns z-$!z3!_ge^?@)Q5Jo5gXqf5tB?$L0z|I@?E*IN3D|NW23PV!CuAIwzlUA|xct&d&% z)*jMuKOOc@_mezlh&;CU{1=by`sb;}Ez6JT9gG=k8|1xp49N@ZPM^PJKPyIu>N?P<3~-Z zskKV~H{P0BU8e^OvZ_kYY*TAXj|uCv8FkjwX?6ej)Y;>w*Ni`HN_BTjJ`OR;H>lxp zU0Hry%ahE2nlo#ve*W}QTG;Tk(rWMipEjIBqoSf~>0+Z%=~+Xb7v&rlTb?ifz3+Yb z&VGtl0{7(d9^7?iOSfew!z@4b{^PzKdd$dCM)^xC-|giWuJYslUp@8K zpK+cP8qWU5Pp*5Uys`3>hHs32|GMSN6aV?T%MZwZ?(&Pu1#{-yR-)nKXgy+R{Q>na z(DJR&aKp<-bm1WlJi-0r^70jyKjaBcUYX@_TfAIemW!7+T#I3xvy=R8yW7ve_A{{k z3~WCG+t0xEGqC*(Y(E3r&%pLGu>A~dKLgv(!1gonzjX%w@g~P*YZ|W8{@GPGExk!s zdRJhFpZ+{wdb70t4fZj&Hyl@4dP}$bHgsjf8(DhV)U&InmfyQ=c<;6R=l${<6M9g$ zp56OY?$z+FREvg#{b{u|bv0)gPySHh|+g(QU@;eg^Z!=i+@1@B5 z9HP9{-|#+4={;d?S!t~P!y2wfv}n<$MUNH(T8wBhp~Z|Ajl(W23h{b&`mY0;y_fEFWKOlUEqMdL{J zqgBwRMUNH(T8wBhp~Z|AjicC)RzaH4E0M2iV6 zX0&M7>_@AhO^Y5a2DBK_VnT}_@AhO^Y5a2DBK_VnT}4H1LW>zK8ppC9t%5c!dbAkOVnmAx zEoQW63}HW71#MdNXfdG0h!zuC%xKXV%6_y8+O+7=VnB-#Ehe;>(V{Vo{b&`mY0;y_ zfEFWKOlUEqMPoSo(JE-uqDPAXEk?AM&|*f5#t8PKRnVqIj}`-3jA${T#f%mWm;GoJ zv}w_!#efzgT1;p$qebI5_M=tMrbUky16qt|F`>nb7LDWCk5)mO7Cl-FXfdM2gcdVe zG)A%?t%5c!dbAkOVnmAxEoQW6jAB1p1#MdNXfdG0h!zuC%xKXV&3?2B+O+7=VnB-# zEhe;>(V}qz`_U?B)1pU<0WC(fn9yQIi^drCqgBwRMUNH(T8wBhp~Z|AjT70ARzaH< zJz5NCF`~tU7BgBj#4E0M2iV6X0&LW#D262+O+7=VnB-#Ehe;>(V}rO z`_U?B)1pU<0WC(fn9yQIi^eJJN2{Psiykcov>4H1LW>zK8oy#cS_N%d^k^}l#fTOY zTFhwCIF3G7F! zpiPS&Ee5n0(PBc287&%B>_@AhO^Y5a2DBK_VnT}4H1LW>zK z8mF@#t%5c!dbAkOVnmAxEoQW6Ok_V=1#MdNXfdG0h!zuC%xKY=#D262+O+7=VnB-# zEhe;>(V|hqezXeOwCK@dK#LJACbXE*qHzZM(JE-uqDPAXEk?AM&|*f5#$@)RRnVqI zj}`-3jA${T#f%n>DeOn9piPS&Ee5n0(PBc287&%TvLCI2HZ6Lz7|>!wiwP}ev}jCa zKUxKCTJ&f!pv8z56I#q@(U``5v4E0M2iV6 zX0&LW#eTF3+O+7=VnB-#Ehe;>(V{V({b&`mY0;y_fEFWKOlUEqMWdGeXce?+(WAwH z79(0rXfdNjqmKP(6|`y5qs4$0BU(&oF{4Fe2K&(}Xw#xcivcZ0w3yIhMvKPT>_@Ah zO^Y5a2DBK_VnT}j(PBW05iKUPn9-tfF8k3cXw#xcivcZ0w3yIhMvKO5_M=tMrbUky16qt| zF`>nb7LD`Rk5)mO7Cl-FXfdM2gcdVeG|p!~S_N%d^k^}l#fTOYTFhwCxPbj=6|`y5 zqs4$0BU(&oF{4G}LiVFo(56L?76V$0XfdJ1j24Z6{b&`mY0;y_fEFWKOlUEqMPm;8 z(JE-uqDPAXEk?AM&|*f5#zpK$tDsGb9xVp67|~)viy18%bJ>qpL7NsmS`270qQ!(3 zGg>q*W`XwjI*ezXeOwCK@dK#LJACbXE*qHziP(JE-uqDPAX zEk?AM&|*f5#(egpRnVqIj}`-3jA${T#f%n>OWBWBL7NsmS`270qQ!(3Gg>qjuph00 zHZ6Lz7|>!wiwP}ev}jz$ezXeOwCK@dK#LJACbXE*qOp+uXce?+(WAwH79(0rXfdNj zV-fq&DrnQ9M~eY1MzomFVn&O`!w ziwP}ev}jz(ezXeOwCK@dK#LJACbXE*q7kwmt%5c!dbAkOVnmAxEoQW6T*ZF03fi>j z(PBW05iKUPn9-tfHT%&jXw#xcivcZ0w3yIhMvKN`_M=tMrbUky16qt|F`>nb7L9Az zk5)mO7Cl-FXfdM2gcdVeG?uU*t%5c!dbAkOVnmAxEoQW6EM-4h1#MdNXfdG0h!zuC z%xKYA#(uO4+O+7=VnB-#Ehe;>(W0@O{b&`mY0;y_fEFWKOlUEqMPmi~(JE-uqDPAX zEk?AM&|*f5#;@6rRzaHnb7L6O&k5)mO7Cl-FXfdM2gcdVe zG*+@7t%5c!dbAkOVnmAxEoQW6MC?bapiPS&Ee5n0(PBc287&$&vLCI2HZ6Lz7|>!w ziwP}ev}oMKezXeOwCK@dK#LJACbXE*qOpqoXce?+(WAwH79(0rXfdNj<7W1wRnVqI zj}`-3jA${T#f%n>TiB0QL7NsmS`270qQ!(3Gg>rmWj|U4ZCdnbF`&hW786>`Xwg{B zezXeOwCK@dK#LJACbXE*qH!Dh(JE-uqDPAXEk?AM&|*f5#_jA!tDsGb9xVp67|~)v ziy18%zhOUG1#MdNXfdG0h!zuC%xKZLgZ*d~v}w_!#efzgT1;p$qebIR_M=tMrbUky z16qt|F`>nb7LB{uk5)mO7Cl-FXfdM2gcdVeH11|US_N%d^k^}l#fTOYTFhwCSi^p_ z3fi>j(PBW05iKUPn9-sUvmdR3HZ6Lz7|>!wiwP}ev}mklKUxKCTJ&f!pv8z56I#q@ z(YS~GXce?+(WAwH79(0rXfdNjV;%d^DrnQ9M~eY1MzomFVn&O`z3fM;piPS&Ee5n0 z(PBc287&&WWj|U4ZCdnbF`&hW786>`XwkTj{b&`mY0;y_fEFWKOlUEqMdN<4E0M2iV6X0&KL z$bPg6+O+7=VnB-#Ehe;>(W3DX`_U?B)1pU<0WC(fn9yQIi^jw3N2{Psiykcov>4H1 zLW>zK8XMS;RzaH(V~&CAFYBmEqb&V&|*Z32`y%{Xgtb(v!wiwP}e zv}ioZezXeOwCK@dK#LJACbXE*qVW{_(JE-uqDPAXEk?AM&|*f5#?$OatDsGb9xVp6 z7|~)viy18%o7j(5L7NsmS`270qQ!(3Gg>sBVLw_0ZCdnbF`&hW786>`Xwi6<{b&`m zY0;y_fEFWKOlUEqMPoDj(JE-uqDPAXEk?AM&|*f5#uoOYRnVqIj}`-3jA${T#f%n> z=h%-{L7NsmS`270qQ!(3Gg>r$$9}X5+O+7=VnB-#Ehe;>(W0@H{b&`mY0;y_fEFWK zOlUEqMI&WDS_N%d^k^}l#fTOYTFhwC*v5Xe3fi>j(PBW05iKUPn9-u~Jp0iqXw#xc zivcZ0w3yIhMvKM^>_@AhO^Y5a2DBK_VnT}!wiwP}ev}nA>ezXeOwCK@dK#LJACbXE*qVYQW(JE-uqDPAX zEk?AM&|*f5#vANMtDsGb9xVp67|~)viy18%Z?Ye)f;KIBv>4E0M2iV6X0&L$#eTF3 z+O+7=VnB-#Ehe;>(W3Et_M=tMrbUky16qt|F`>nb7LB*rk5)mO7Cl-FXfdM2gcdVe zG&1(1RnVqIj}`-3jA${T#f%n>ci4|sL7NsmS`270qQ!(3Gg>tMz<#s}+O+7=VnB-# zEhe;>(W3D#`_U?B)1pU<0WC(fn9yQIi^hBGN2{Psiykcov>4H1LW>zK8t=0ot%5c! zdbAkOVnmAxEoQW6{E_`=6|`y5qs4$0BU(&oF{4G}1NNg;(56L?76V$0XfdJ1j24X# z*^gF1n-)D<3}`W;#e^0!S~NalKUxKCTJ&f!pv8z56I#q@(fFACXce?+(WAwH79(0r zXfdNj;}iCyRnVqIj}`-3jA${T#f%n>PuY)FL7NsmS`270qQ!(3Gg>r0V?SC2ZCdnb zF`&hW786>`Xwmpn!+yU{gCWM4Vvgov4afCB7kvyd#uRfj4`&`-^fAO3Q_Rskf_Ze& z#}H#oF-Nm6^XQ_FA;y?uj%GjR(M2Caj4{O=%_Esd7kvyd#uRfjk76EO^fAO3Q_Ruq z&pf*5V~8=Pn4@Vkk1qNcVvH%~XgbWJi#~=JV~RPNig|R=#}H#oF-KD~k1qNcVvH%~ zXbxZ=UGy=;7*ovA9LPMn=wpa6rkJBShSZql-R< z7-Nb#n#VAYF8UZ^j49@59?Lws=wpa6rkJBSgn4w)#}H#oF-LPK^XQ_FA;y?uj^;4t z(M2Caj4{O=&Ed?Wi#~=JV~RPNBbY}QeGD>Nql-R< z7-Nb#nq!zp7kvyd#uRfjPh=il^fAO3Q_RsE%RIX1V~8=Pn4@_T^XQ_FA;y?uj^@eC zql-R<7-Nb#nx`<2F8UZ^j49@5{)%~Y(Z>*DOfg6EROZn|A47~W#T?CX%%h7wh8Sat zIhr2x=%SAy#+YJ`=6L4OMIS?qF~uCs)0jsWeGD z=%SAy#+YJ`<{8YRi#~=JV~RPNlbJ^seGD*DOfg4u7W3$$k0HjGVvgpy%%h7wh8SatIhwPXM;CnzF~$^g zG|yumUGy=;7*ovAJfC@V(Z>*DOfg6E0_M?0A47~W#T?BGnMW6W3^B$Ob2J0y(M2Ca zj4{O=%{k1Yi#~=JV~RPN7cq}6`WRx2DduR-WgcDhF~k^C%+b7GmkF%7-Ebm=4f8QJi6#( zh%u&^qj@Fs=%SAy#+YJ`X2?9c=wpa6rkJC774zt#k0HjGVvgq3%%h7wh8SatIhu=^ zM;CnzF~$^gG_PSEUGy=;7*ovAT*5rM=wpa6rkJC-lzDW~#}H#oF-LP5^XQ_FA;y?u zj^=Xa(M2Caj4{O=%@xd}i#~=JV~RPNzh)j?^fAO3Q_Ru4mU(p1#}H#oF-P+{=FvqT zLyR%S9L?*QM;CnzF~$^gG;d%YUGy=;7*ovAT**AT=wpa6rkJA{F^?|#7-Ebm=4jr? zJi6#(h%u&^qj?ka=%SAy#+YJ`<|^jVMIS?qF~uCso0&%!eGD_UGy=;7*ovAyqkG+(Z>*DOfg4u z4fE)tk0HjGVvc6aJi6#(h%u&^qq&xObkWBUV@xqe^B(5WMIS?qF~uCsbV~8=Pn4|e1^XQ_FA;y?uj^;zmql-R<7-Nb#nh!INF8UZ^j49@5 zZeSi=^fAO3Q_RtPgn4w)#}H#oF-LPF^XQ_FA;y?uj%LC*DOfg4u8}sO*k0HjGVvgqX%%h7wh8SatIhrppk1qNcVvH%~Xuili zy69twF{YTK`4aQ!qK_fQm|~9R%gm#TK86@$iaDCEFpnF8UZ^j49@5zRx_m=wpa6rkJDoN9NH*A47~W z#T?BKm`4|V3^B$Ob2L9>9$oY?#28b|(fo*cbkWBUV@xqe^JC`GMIS?qF~uCsPnbs+ zeGDukGkuL6PFGeS-LJmz6v>cV#7rFCb`Br#(t%2 z_{@(tHGHNM2Z(1p`M^DD)X+htTldHEkzEXTlzNH~+;lwv>lU zljW~>{sz^@7*oFBz=j=9e6X~iv9Wv|`x-`z5}VFB_;}-k@)3I*Mw1eU{BhMRL z;`Hk3+Hq5-O|P3&S$Z;PR62UchNEli#!sypKfP+))bVFl7q7miZbnr#&yk&+@2!S& z(W#=MZRuK#Mimtm<*P4$i2uEF(|qUhY~zXx?kQ{h^nxU3r_q0WcIuzt8XIkm%F=(v zxZ%}x6RJ+{rKe4sUR5)7d|h>|VV2HQ{e5Ow^*6P2&(weXvz0>|PTfwW)upQ$aLllQ z!$%%7V)(eB$BZ0hbmS(LUyAEbdg%-P=jrm*)pz-mrH}H{_#R*Fw|LOt0m|sa%WwT> z{<>xt^M7<>%h&SLJ*2 zWb`PX+v5ig8hHG`;d)@hx&3A7sPe6^8eccQwz|$RZs63~nrTyw=H<`-^F3I; z;_`?1c|-p6>rPF7`fdGhemY_Qct~_EeWE;GHGWpDRa-N4LbcWNu--ko_3YNu>e1tf z`v3b+9vkIbQywp$#m1$d1?nG~Q>IOw_>YIr&kt$QaL9!5Q>x1kv!6Y{p{W;hY+IQv4siWK5gd@RCvbDfC~yWK@=x)jvLX$*3M*TUU8d`Lh4y zQ6Ufd@&n-1=<|wf1M9d#Cxl6Mj0ErKgb6 z&G=t?$yxgU>LsV)3+}{MdXjv>@<$HoqTLTa#H#;uVf~Ny6+1LMFP5I4OFsn+xvk;o zruA1+u|xTf0_Bh9r8}hl?tXSn!v!r`yw|9FCI7oGd*x@{?bCj{t)HKUtXZc+}`kc`Blz=bUx&ZQU834-{ax-V*Lp=jPg%a%}Uo^ z$usyr{bW)8A*_6k%MX;&>9mnu}7=U#WrnO`_>H~WjT>ftAyQ?6d`-1g0r&IdKERJi;a=g?!;+HEUr z$NhS`^YoP6)w_$Ha5mp{uQPwQzuSLUy4X2%(HqX>9lNVRckHUXrnSy>J3isey|tw? z?W|{H{jl+9XU0iKE4}I@_4n6yS4Us&s}nCd|Dy``4C-$%E&>l$@_)6bpTojcXcWlyWt3y;vFCr;Amzj>U# za_@F})s21iZBtw5gOC2B`s>-QzDg_o+L>>uV2@YTXUFZRM|AJ3M=WfoS3GFy)=Ll8 zZQ4DijvlvM^*Htz^~_~0_1|B(LEZSm0lMAjYCW*meEnwKB3*sQ5Iwv4E460#p6Z@I zFVL-a8?6t&_C!7U>REcifqUw$2es23qkZ+He*N_h$IR5PFStmL{zEgJ_Uo)SOfqzM zR1e+z{js|B`|b5R6A#hHT{}S^bzz{l_FkY5{IRXRs_*{##D}lfm-LPFoy>Iw z(^mS@_n%gs0#D!7s!q2Uc$MC$j?ll)n(6`XG}Hb1?xWYGC+TY^j??Y#JX2qD&Aw`K zpZ5C0rw`M+ANs6%{mMP{jcxbQ{U+b5M(n(|Ubf-G(=+$h`uis?)wliX z3Vr^suhnn9zC!o>bb)^2!S4FCM|$b^^O?GO!7QOyb(6nRCugSG`raOT?zk4Z)AcLV8(TkD7ytOBa=Q-G zookd{K4zPmx>Kd@`g#X_*BkGv9lGwV=B?ppTuJvqzSf9QN?U_Mff ztbJUac*>({gLAoBJ@gUvY3&B}Xicb^J$}FXqIRN6mQPThzjmUkJY%ieXolb{-;JkU?P0ktnwopTE z?XD&q-$@<0q>a;EFLgfcag_7mw9vV}dq>Br8}AIO+`|ce(?e}+yO%oa#VegBZ|UM3 zxAjWrrKfLky1ja&v*L@(>^J{9+i_a`)!A_V4r;|WJE}|jnW}Z|F6x6xq0^hZ|ySR>e7GzQ=Pwc9-wzTz&UfzJDnRxT<9#@ zHpF@1cfWSppWnzCdf{m54O&Ast4*hbj^OrFz?XeRwr{`_Ib>4e- zFSTUOEzXitKej8E9U?((^?CpC z>Yb)aE!^>!>YbgpIBgbw;Jm%_1**@QeN|Q3Q!N|ZNex^47so!~bhY~T_dAcC_Mp>h z_X;(!NoVKV7awt6IpGCo#yJC&_4cXi))tqR&e8Ku^`hZw?%JN}_Qxiw_1ikAy!71M z_0z^Gd$UHZs9U8TsyaYz9^G2C^R}p~W-e4!M@&$wuQb&)Up}BNJm~>t-*JW0?&9Or z;~)G@eY}3YT5)?*^-A+b`rR#GIBWJ>qBh<0TXp;5dFn;~RCVC8W$LrXpI5I{eWhwn zy;-^0t?G`RE%cBzzfs}DN;T%-ubqn<%~LJf+^!CsWa^27Zc=aj`et?2ixqmq?K9O2 zZ+24icKtzhnRut#(0rZRdg9k=;0NvWU&r33hOInAkGLmMAAUYmdv8zC?N6DgzkNGa zpC4GKo3|aWKe^7;ul()^{m9dub<68p>&u!}=(^pXRNF4zS+CozmA-%SSUu>GF8YQ2 z&eWT?p04*_Ia;Ty9ew`#EA*4^jna>_SfE=r+eg1N{08-S`#p7=J6q`=XMV2Udd%1J zejK9@edY(X{Ql{B>|=}dk+V+G3+MUz_yaD{k3M;w?mA(K-o48T-Tar+^e#_K(tR(j z*8TR_qTc&zh(0N4t9LzozW(sMv_ivu7KWuZd-njNkwflJ$dgOPtdTs9}I_f=2kF7dKufAe} zKFDvZM^_!J>o#1WKg*8QXT3d0pEn{=k?yBgPMxV6Klzzz_Tv6JzPXE@apV*|clkW^ z<&QPG!x4S-{F_hIZ`?df_qg{&{mkye^s+G*sU;J)sNF~Ir}gg!==m!K=~ln4(SxrT zrjxO+s@@Yv=<)A3dha%0s(s>Jbi3O->ov*m)iW<0qF?e4QZK)|tA3{LD82iPaq7uM zL)7ZsR;qW$P0-2ByXsp91p1V{chsL9K0_^@c!7HVsgZi}`ft=-?JQmSvZu3;4%bsY z99eo!vUHdAj_&ZAzN+n{!}K95_f%WH*+cig>{x9M?4*}mpQ(Ohdh2T+Gj+EEW~;l_ zR_fhuZL9a5(MlgP?|C(D>l5meyrbUwP_EW3T&51by_-^3w$s(m@1$3E-Am7T)YR|w z>#D9i@%O5t`=8XZ@19ambZDk8?cY|PvCm%mhu2Kq_Skn+uhvcVGYh{|AB}iTMJ?8; zuPZjH-QWCBy`m3NXC42jnml5I8aX#r3;h*JKXbPlW!|jLyf{BxyAwez>mcSqf# zmP}oybhC}B)2wTp^*uJKcQ&q3J;vJ3rn=l&Jn#l}V$Fi!Gnv`{f$?u zO*c(*R^PW!E#Gs#I)CGV>apkdR!v6rSNnHdsLmU6ih6Wlpw^%97yFw>+pBvzEmoV( zf8N{^Bd2`k{PC6L&OF0&9yn;Z{q?p@j^DAps(opWv*C|tJ8NF3aMm4{IS2oxqw?0h zVQ>Ad;hb>pWzLoBj&!bTyrcSlL8bcY(x&R8%T99iU5o4{&)?zfwC}a{=xx_H$Fy4D zoKyF*^USO}?ArDBIH&A=zjOJ!)z08+cXw{yw8eS#)E(67k+Yo-ZoJs3ZhV9D!<`S< z!!A13>3-eK_CfnUZom2L9H+T*ow=K?aV9x0IgNii%W3i54CksxHag2Md)E2eh^cm; zc9WfLdz|5HI`|gn!>2l`om=j%p6$Gw`lwOj>@oF6d*JG;oNtFOvG?23TrKJFnX~MI z5A4?Z8fW#2KRC0xc2+a@Z=znls;#rR^S92)EADZ&o`07!?CkfQ!M_}>de;5XUNL07 zv!HwARPFP*v;KfpPU9bMbk^O~RE6#U^-+_1onJh*LbYgrg_^u%g?jU`)vEKIA3Lw6 zvz=|D-*PJ3EOJJF{C{GHMZZ&2^AoULZ=ReJ6{vW>3o`<>de<63q9|JtvYUUTnSb>THnsIGhNsV`l#QcY{qPdA;=Uf;i= zkG}TctJRRXt5oAxo9Z^#G}7N5HdP&+9Hkc?+e1J0V`ClNx10X_)SdMQ_ISPSd0U%L z9iZR3s!I2Hr9yk(*?LZsPn=DE{3#HnG_u z7Eac48=a@GJoaq;P=$U8e7k@lX_x{DlYEy8i-tbjl-Fjn3oj=`A&)e2Z zzcj_t-+#5cZuNFwJ@Di&)T_H4p|8EXm+swTxn6$Rsru=Amg$XY8~xT}$LM(Q6Y6&@ zch;lw!Fu)D@7371=jo5L>(n@ZmhRT2pPtyYyPomGVm)yJ<_k;E1 z=UV9-@84a!`<<+JZZTI+cxt|$ahR>QOdF-w4W6UBKG#d{-}n~&*$%7qFZb`HJ5=@7 zYd$W93^njH=s2dl3tbWzMhkktZaeB&CN*}y(Cbu>w`+C!$ZhKDfur=m z;ijHHp!CPh$J^`V?LBqA|9aKwidI^`?&vqKKSIw|~YcGAn*wa}aQ?WS+J=V-m< z&*Sxv={|a-(LrCl`4V-|Zl9>e*Bzw$oTl~c?;leWRxVKAJ$Jo|7Cxy?Uvr)6*6B~G zQ#?TLaPJ6xVgCVo#tXaanHzV|!=5@wcQS|QQ+9qynd`n&FFxH;-`IawJ+k}0dcvh= zslLa*tX|qWLp8hlDD~>y_1m!`6p^*qgMLaDJ}FHN6uBt`c75LHk_w+@7zIsc-L5U<3%^B zGgpV|g=mYqxkrDsY10L21F4TJDqFZIauxVyW^c6J0GcxR}NFdAHK>t|M|(z zZ~wGFJ!ahGbaT5o-$lLEM;Dx+mYvu^jWsTIl1m?Sj=!T)%{ukh&dfH4s^hkvsNNcI zqWW8_u4?&`LF)16DwKYsscN!hxijOayX@}=z39yRsI9a7xc8j>Uteh-@VTMRZ~ub5 zzV=P$%YCnN?%nwhPVJY^IhWsehV#X#+P?qc8=O}Mws6LGYVF){(BsZ|S~*AcUgdZf zZgVEj$(_@CRj9o$9_=*wec~LP-sRl>$ENC~&+l|rd@#?cnL5i}S$f^Lv&|*W-glLr zGk;v;eD(PP=d7v^o!?&DNKJY7Is4JC8#|MaecV}9(ch`vW4*KN(Vd(JjylwN=CZ#z zhn@J5?cVjeb7ij&o#oy8IiDYJn*GriAK9b6Y^!3!y+(n(Y^c`pAx}DViyX>Q` zyW$PUUHpkN@$KfS=IUN5U)@7p|G=*5+b{M|pVhqK+_-45v-0jcZGBEVb>w5K?3&Hn zoNL=Obza(SkoxqMtM@syL)oCPPT z{X5^F#x+{vRPD5%>U6CNi<%g<4Jp8K&n`0ByVzNPQmSEv6`y?FU%b=$F-v*Nd}IKeYp zoK|ix6}CG<-FCs}DxCbj+Hmh2^>*ERD&4w9ZQl7Iwb)y!_CEJOef?RtsO4&_+8p1m zM#h`f{I6TlN{t=H8aqpy0TPQCE=()%}q`|6k8K2-N? zv|hb+@hQ6TxmthKc&?rl_SYSUUat4sG*ut5*OmI+Jt6=(ew45zr0v4T0BNK8TN_lclcxnQt<@76YYed+oAq~k8pYtC4ps!v#? zPaHW)ZydOv{^al(`tdL4>R&Dkb+^*{3V%CltghYmfI9rMrrKQjwp!zVs^<6kr5<+B z!8&>3WIcEC33~AKjq1?1XX_P~;t=T!avYhCrV^IuZ8ENP?HEE%Flww|C5|KJkcrSv?!W$Zg@#ke}XX>FDM zXw{$8OMA7~zp2u-B>){}Z3 zt4F#IInst0U3N1uA{0=?hq7wg#vU8KVYFV|J*_r0uMd2x{5 z`_n#p%&;DMkjdxV5D}PaXpCvy)x88NA-g*5l`nWZHbw!6x`nek(P~Sai z>-JsOsY&x2=?TyD*QdPpjXM9BOVr}U&Gh4AchSQd@2gjB=%pvl>Z{wd8m_w?e7wFt z?yoC*9j-e+d6J$t`Z)dEEobV^d%UdXT+u~WZ|R|D&FHF|eB4RD{Y)R#b)WZDx3Bio zj~_frkGs3{8ZanP$(T<1(^>neH{*}gIh|fn_b(l$_FmssZ?l)HQ=A9XB&V_7<*w3u zcN;%fn~yqM-PN_39{bG;s`ZhZ)siXish6&ArsqvJ^tastl`V_Z8GUYd<{sNbjUKaJ z4O#PysvVW6^Z#^PP1~mGoZfObR!u-%g91x5w?Ps=s~1 z`EbD5>dFNVsZajWN-evix4O{lt;~H^s@jf$TJ_*^b^bG*RL7?$sQ1+^>iU*F)yaE) z=xkeOsaKOKbw{{qA#~c>4x>;F~u%w>bAZ zlQ#8s+MB;~PCR3^^TjD$ocGW8-d=gb-A>0Avz*;J>}9|B&PZqc`wN_2H(ucEcHvTc z)5I#L^(Xf`^ENh7w{#ujEI4SsV~%{;>2cfN?a}SqIexR#oz3H}bS}NG#yR+zWlqm! zhMIkMBem0{rmExqGo1EuW7Tg~b9K#G9i8$!zgsN*v+4Rb$@TQ=(!c+!vS!xQO|k}#9CpI^DWj%Mn_``PNcWyS zyZ5LZQ2s|{jZ1&4U;mG{CXDy%%KzA`{CE1Le-u-H4TGjlpHMS(Vy$)hwCUEw>Z#S! gYbIEeW>rm}Hf7qxn$o}Jvd)}VRXydd_pYh + + + + + + + + + + + + + CF-1.7 + Contains modified Copernicus Climate Change Service Information 2020 + down + + + + + + + + CF-1.7 + Contains modified Copernicus Climate Change Service Information 2020 + down + + + + + + + + Generic lumped forcing recipe + [] + + + + + + + CF-1.7 + Contains modified Copernicus Climate Change Service Information 2020 + down + + + + + + + + CF-1.7 + Contains modified Copernicus Climate Change Service Information 2020 + down + + + ERA5 + ERA5 + diagnostic + 2000 + /home/bschilpero/esmvaltool_output/ewcrepl6i8wpsb_20241024_145905/preproc/diagnostic/rsds/OBS6_ERA5_reanaly_1_day_rsds_1997-2000.nc + day + Surface Downwelling Shortwave Radiation + day + ['atmos'] + rsds + rsds + OBS6 + 0 + rsds + surface_downwelling_shortwave_flux_in_air + 1997 + 3 + 1997/2000 + reanaly + W m-2 + rsds + 1 + {'operator': 'mean'} + {'shapefile': PosixPath('/home/bschilpero/Forcing/camelsgb_73010/caravan/camelsgb_73010.shp'), 'crop': True, 'decomposed': False} + {} + {'compress': False, 'filename': PosixPath('/home/bschilpero/esmvaltool_output/ewcrepl6i8wpsb_20241024_145905/preproc/diagnostic/rsds/OBS6_ERA5_reanaly_1_day_rsds_1997-2000.nc')} + + + + + + + + Forcings for generic hydrological model + ('global',) + ['acknow_project'] + script + /opt/conda/envs/ewatercycle2/lib/python3.12/site-packages/ewatercycle/esmvaltool/diagnostic/copier.py + + + + + + + + Unseen University + + + + + + + + + + + + + + + + + + diff --git a/tests/data/OBS6_ERA5_reanaly_1_day_tas_1997-2000.nc b/tests/data/OBS6_ERA5_reanaly_1_day_tas_1997-2000.nc new file mode 100644 index 0000000000000000000000000000000000000000..eb10c3b7233d1d944f5f7a6199ef87d792bd35d6 GIT binary patch literal 55671 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 iSv-3D%oCT*U+gdR7mVtEDL(TgfBwkA + + + + + + + + CF-1.7 + Contains modified Copernicus Climate Change Service Information 2020 + + + + + + + + + + + + + CF-1.7 + Contains modified Copernicus Climate Change Service Information 2020 + + + ERA5 + ERA5 + diagnostic + 2000 + /home/bschilpero/esmvaltool_output/ewcrepl6i8wpsb_20241024_145905/preproc/diagnostic/tas/OBS6_ERA5_reanaly_1_day_tas_1997-2000.nc + day + Near-Surface Air Temperature + day + ['atmos'] + tas + tas + OBS6 + 0 + tas + air_temperature + 1997 + 3 + 1997/2000 + reanaly + K + tas + 1 + {'operator': 'mean'} + {'shapefile': PosixPath('/home/bschilpero/Forcing/camelsgb_73010/caravan/camelsgb_73010.shp'), 'crop': True, 'decomposed': False} + {} + {'compress': False, 'filename': PosixPath('/home/bschilpero/esmvaltool_output/ewcrepl6i8wpsb_20241024_145905/preproc/diagnostic/tas/OBS6_ERA5_reanaly_1_day_tas_1997-2000.nc')} + + + Generic lumped forcing recipe + [] + + + + + + + + + + + + + + + + + Forcings for generic hydrological model + ('global',) + ['acknow_project'] + script + /opt/conda/envs/ewatercycle2/lib/python3.12/site-packages/ewatercycle/esmvaltool/diagnostic/copier.py + + + + + + + + + + + + + + + + + + + + + + Unseen University + + + + + + + + + + CF-1.7 + Contains modified Copernicus Climate Change Service Information 2020 + + + CF-1.7 + Contains modified Copernicus Climate Change Service Information 2020 + + diff --git a/tests/data/ewatercycle_forcing.yaml b/tests/data/ewatercycle_forcing.yaml new file mode 100644 index 0000000..b6a62be --- /dev/null +++ b/tests/data/ewatercycle_forcing.yaml @@ -0,0 +1,8 @@ +start_time: '1997-08-01T00:00:00Z' +end_time: '2000-08-31T00:00:00Z' +shape: None +filenames: + pr: OBS6_ERA5_reanaly_1_day_pr_1997-2000.nc + tas: OBS6_ERA5_reanaly_1_day_tas_1997-2000.nc + rsds: OBS6_ERA5_reanaly_1_day_rsds_1997-2000.nc + evspsblpot: Derived_Makkink_evspsblpot.nc diff --git a/tests/test_model.py b/tests/test_model.py new file mode 100644 index 0000000..e69de29 From c92c6d9d622480a98a6fcdbc967e5df51ade4d69 Mon Sep 17 00:00:00 2001 From: Bart Schilperoort Date: Fri, 25 Oct 2024 10:09:47 +0200 Subject: [PATCH 04/11] Apply code formatting w/ ruff --- src/HBV/HBV_bmi.py | 204 ++++++++++++++++++++++++++------------------- 1 file changed, 118 insertions(+), 86 deletions(-) diff --git a/src/HBV/HBV_bmi.py b/src/HBV/HBV_bmi.py index 393d5e2..328a008 100644 --- a/src/HBV/HBV_bmi.py +++ b/src/HBV/HBV_bmi.py @@ -7,40 +7,42 @@ import warnings import gc -DICT_VAR_UNITS = {"Imax": "mm", - "Ce": "-", - "Sumax": "mm", - "Beta": "-", - "Pmax": "mm", - "Tlag": "d", - "Kf": "-", - "Ks": "-", - "FM": "mm/deg/d", - "Si": "mm", - "Su": "mm", - "Sf": "mm", - "Ss": "mm", - "Sp": "mm", - "M_dt": "mm/d", - "Ei_dt": "mm/d", - "Ea_dt": "mm/d", - "Qs_dt": "mm/d", - "Qf_dt": "mm/d", - "Q_tot_dt": "mm/d", - "Q": "mm/d"} +DICT_VAR_UNITS = { + "Imax": "mm", + "Ce": "-", + "Sumax": "mm", + "Beta": "-", + "Pmax": "mm", + "Tlag": "d", + "Kf": "-", + "Ks": "-", + "FM": "mm/deg/d", + "Si": "mm", + "Su": "mm", + "Sf": "mm", + "Ss": "mm", + "Sp": "mm", + "M_dt": "mm/d", + "Ei_dt": "mm/d", + "Ea_dt": "mm/d", + "Qs_dt": "mm/d", + "Qf_dt": "mm/d", + "Q_tot_dt": "mm/d", + "Q": "mm/d", +} class HBV(Bmi): """HBV model wrapped in a BMI interface.""" def initialize(self, config_file: str) -> None: - """"Based on LeakyBucketBMI simple implementation of HBV without snow component - Requires atleast: - --------------------- - 'precipitation_file': xarray with "pr" variable & time component - 'potential_evaporation_file': xarray with "pev" variable of same nature as pr - 'parameters': list of 8 parameters by a ',' - 'initial_storage' list of 4 storage parameters split by a ',' + """ "Based on LeakyBucketBMI simple implementation of HBV without snow component + Requires atleast: + --------------------- + 'precipitation_file': xarray with "pr" variable & time component + 'potential_evaporation_file': xarray with "pev" variable of same nature as pr + 'parameters': list of 8 parameters by a ',' + 'initial_storage' list of 4 storage parameters split by a ',' """ # open json files containing data @@ -50,30 +52,30 @@ def initialize(self, config_file: str) -> None: self.ds_P = utils.load_var(self.config["precipitation_file"], "pr") self.P = self.ds_P.to_numpy() - self.ds_EP = utils.load_var(self.config["potential_evaporation_file"], "evspsblpot") + self.ds_EP = utils.load_var( + self.config["potential_evaporation_file"], "evspsblpot" + ) self.EP = self.ds_EP.to_numpy() self.ds_Tmean = utils.load_var(self.config["mean_temperature_file"], "tas") self.Tmean = self.ds_Tmean.to_numpy() # set up times - self.time = self.ds_P['time'].astype("datetime64[s]").to_numpy() + self.time = self.ds_P["time"].astype("datetime64[s]").to_numpy() self.end_timestep = len(self.time) self.current_timestep = 0 # time step size in seconds (to be able to do unit conversions) - change here to days - self.dt = ( - self.time[1] - self.time[0] - ) / np.timedelta64(1, "s") / 24 / 3600 + self.dt = (self.time[1] - self.time[0]) / np.timedelta64(1, "s") / 24 / 3600 - # define parameters - self.set_pars(np.array(self.config['parameters'].split(','), dtype=np.float64)) + # define parameters + self.set_pars(np.array(self.config["parameters"].split(","), dtype=np.float64)) # add memory vector for tlag & run weights function self.memory_vector_lag = self.set_empty_memory_vector_lag() - # define storage & flow terms, flows 0, storages initialised - s_in = np.array(self.config['initial_storage'].split(','), dtype=np.float64) + # define storage & flow terms, flows 0, storages initialised + s_in = np.array(self.config["initial_storage"].split(","), dtype=np.float64) self.set_storage(s_in) # set other flows for initial step @@ -107,7 +109,7 @@ def set_storage(self, stor) -> None: self.Sp = stor[4] # SnowPack storage def update(self) -> None: - """ Updates model one timestep + """Updates model one timestep Old documentation: Function to run the update part of one timestep of the HBV model @@ -118,8 +120,8 @@ def update(self) -> None: """ if self.current_timestep < self.end_timestep: self.P_dt = self.P[self.current_timestep] * self.dt - self.Ep_dt = self.EP[self.current_timestep] * self.dt - self.Tmean_i = self.Tmean[self.current_timestep] * self.dt + self.Ep_dt = self.EP[self.current_timestep] * self.dt + self.Tmean_i = self.Tmean[self.current_timestep] * self.dt # split P into rain and snow: if self.Tmean_i < self.Tt: @@ -130,9 +132,13 @@ def update(self) -> None: else: self.Pr = self.P_dt # if not snowing, all rainfall self.Ps = 0 # No snow - self.M_dt = min(self.Sp / self.dt, self.FM * (self.Tmean_i - self.Tt)) # melt factor * diff in temp + self.M_dt = min( + self.Sp / self.dt, self.FM * (self.Tmean_i - self.Tt) + ) # melt factor * diff in temp self.Sp -= self.M_dt # remove melt from snowpack content - self.Pr += self.M_dt # add it to `rainfall`: snow melt can also be intercepted + self.Pr += ( + self.M_dt + ) # add it to `rainfall`: snow melt can also be intercepted # Interception Reservoir if self.Pr > 0: @@ -144,7 +150,9 @@ def update(self) -> None: else: # Evaporation only when there is no rainfall self.Pe_dt = 0 # nothing flows in so must be 0 - self.Ei_dt = min(self.Ep_dt, self.Si / self.dt) # evaporation limited by storage + self.Ei_dt = min( + self.Ep_dt, self.Si / self.dt + ) # evaporation limited by storage self.Si = self.Si - self.Ei_dt # split flow into Unsaturated Reservoir and Fast flow @@ -163,7 +171,9 @@ def update(self) -> None: self.Su = self.Su - self.Ea_dt # Percolation - Qus_dt = self.P_max * (self.Su / self.Su_max) * self.dt # Flux from Su to Ss + Qus_dt = ( + self.P_max * (self.Su / self.Su_max) * self.dt + ) # Flux from Su to Ss self.Su = self.Su - Qus_dt # Fast Reservoir @@ -188,28 +198,28 @@ def update(self) -> None: def updating_dict_var_obj(self) -> None: """Function which makes getting the objects more readable- but adds more boiler plate..""" self.dict_var_obj = { - "Imax": self.I_max, - "Ce": self.Ce, - "Sumax": self.Su_max, - "Beta": self.beta, - "Pmax": self.P_max, - "Tlag": self.T_lag, - "Kf": self.Kf, - "Ks": self.Ks, - "FM": self.FM, - "Si": self.Si, - "Su": self.Su, - "Sf": self.Sf, - "Ss": self.Ss, - "Sp": self.Sp, - "M_dt": self.M_dt, - "Ei_dt": self.Ei_dt, - "Ea_dt": self.Ea_dt, - "Qs_dt": self.Qs_dt, - "Qf_dt": self.Qf_dt, - "Q_tot_dt": self.Q_tot_dt, - "Q": self.Q, - } + "Imax": self.I_max, + "Ce": self.Ce, + "Sumax": self.Su_max, + "Beta": self.beta, + "Pmax": self.P_max, + "Tlag": self.T_lag, + "Kf": self.Kf, + "Ks": self.Ks, + "FM": self.FM, + "Si": self.Si, + "Su": self.Su, + "Sf": self.Sf, + "Ss": self.Ss, + "Sp": self.Sp, + "M_dt": self.M_dt, + "Ei_dt": self.Ei_dt, + "Ea_dt": self.Ea_dt, + "Qs_dt": self.Qs_dt, + "Qf_dt": self.Qf_dt, + "Q_tot_dt": self.Q_tot_dt, + "Q": self.Q, + } def updating_obj_from_dict_var(self) -> None: """Function which inverts the dictionary above & sets objects correctly""" @@ -232,13 +242,18 @@ def weight_function(self): weights[i] = (float(i + 1) - 0.5) / th i = nh - weights[i] = (1 + (float(i + 1) - 1) / th) * (th - int(np.floor(th))) / 2 + ( - 1 + (self.T_lag - float(i + 1)) / th) * (int(np.floor(th)) + 1 - th) / 2 + weights[i] = (1 + (float(i + 1) - 1) / th) * ( + th - int(np.floor(th)) + ) / 2 + (1 + (self.T_lag - float(i + 1)) / th) * ( + int(np.floor(th)) + 1 - th + ) / 2 for i in range(nh + 1, int(np.floor(self.T_lag))): weights[i] = (self.T_lag - float(i + 1) + 0.5) / th if self.T_lag > int(np.floor(self.T_lag)): - weights[int(np.floor(self.T_lag))] = (self.T_lag - int(np.floor(self.T_lag))) ** 2 / (2 * th) + weights[int(np.floor(self.T_lag))] = ( + self.T_lag - int(np.floor(self.T_lag)) + ) ** 2 / (2 * th) weights = weights / sum(weights) @@ -271,18 +286,19 @@ def get_value(self, var_name: str, dest: np.ndarray) -> np.ndarray: # first update the dictionary to match the current values of object self.updating_dict_var_obj() # handle the memory vector - if var_name[:len("memory_vector")] == "memory_vector": + if var_name[: len("memory_vector")] == "memory_vector": if var_name == "memory_vector": dest[:] = np.array(None) message = "No action undertaken. Please use `set_value(f'memory_vector{n}',src)` where n is the index." warnings.warn(message, category=SyntaxWarning) else: - mem_index = int(var_name[len("memory_vector"):]) + mem_index = int(var_name[len("memory_vector") :]) if mem_index < len(self.memory_vector_lag): dest[:] = self.memory_vector_lag[mem_index] else: raise IndexError( - f'{mem_index} is out of range for memory vector size {len(self.memory_vector_lag)}') + f"{mem_index} is out of range for memory vector size {len(self.memory_vector_lag)}" + ) return dest # otherwise return the variable from the dictionary @@ -316,24 +332,25 @@ def set_value(self, var_name: str, src: np.ndarray) -> None: new_memory_vector[:old_T_lag] = old_memory_vector # if the new vector is shorter, we sum the old extra values to the last value: as not to `lose` water elif old_T_lag > self.T_lag: - new_memory_vector = old_memory_vector[:self.T_lag] - new_memory_vector[-1] += sum(old_memory_vector[self.T_lag:]) + new_memory_vector = old_memory_vector[: self.T_lag] + new_memory_vector[-1] += sum(old_memory_vector[self.T_lag :]) # set new vector self.memory_vector_lag = new_memory_vector # 2. values in the memory vector must be set manually to work with DA - elif var_name[:len("memory_vector")] == "memory_vector": + elif var_name[: len("memory_vector")] == "memory_vector": if var_name == "memory_vector": message = "No action undertaken. Please use `set_value(memory_vector{n},src)` where n is the index." warnings.warn(message=message, category=SyntaxWarning) pass else: - mem_index = int(var_name[len("memory_vector"):]) + mem_index = int(var_name[len("memory_vector") :]) if mem_index < len(self.memory_vector_lag): self.memory_vector_lag[mem_index] = src[0] else: raise IndexError( - f'{mem_index} is out of range for memory vector size {len(self.memory_vector_lag)}') + f"{mem_index} is out of range for memory vector size {len(self.memory_vector_lag)}" + ) # all other values can be set here elif var_name in self.dict_var_obj: @@ -360,7 +377,7 @@ def get_end_time(self) -> float: def get_current_time(self) -> float: """Return current time in seconds since 1 january 1970.""" - # we get the timestep from the data, but the stopping condition requires it to go one beyond. + # we get the timestep from the data, but the stopping condition requires it to go one beyond. return get_unixtime(self.time[self.current_timestep]) # type: ignore def set_tlag(self, T_lag_in) -> int: @@ -381,11 +398,14 @@ def get_time_units(self) -> str: # TODO implement setting different timestep? def get_value_at_indices( - self, name: str, dest: np.ndarray, inds: np.ndarray) -> np.ndarray: + self, name: str, dest: np.ndarray, inds: np.ndarray + ) -> np.ndarray: raise NotImplementedError() # TODO implement - def set_value_at_indices(self, name: str, inds: np.ndarray, src: np.ndarray) -> None: + def set_value_at_indices( + self, name: str, inds: np.ndarray, src: np.ndarray + ) -> None: raise NotImplementedError() def get_var_itemsize(self, name: str) -> int: @@ -416,7 +436,7 @@ def get_grid_shape(self, grid: int, shape: np.ndarray) -> np.ndarray: return shape def get_grid_origin(self, grid: int, origin: np.ndarray) -> np.ndarray: - origin[:] = np.array([0., 0.]) + origin[:] = np.array([0.0, 0.0]) return origin # Non-uniform rectilinear, curvilinear @@ -429,10 +449,21 @@ def get_grid_y(self, grid: int, y: np.ndarray) -> np.ndarray: return y def finalize(self) -> None: - """"remove all files""" - del (self.config, self.ds_P, self.P, self.ds_EP, self.EP, self.ds_Tmean, - self.Tmean, self.time, self.end_timestep , self.current_timestep, self.dt, - self.memory_vector_lag) + """ "remove all files""" + del ( + self.config, + self.ds_P, + self.P, + self.ds_EP, + self.EP, + self.ds_Tmean, + self.Tmean, + self.time, + self.end_timestep, + self.current_timestep, + self.dt, + self.memory_vector_lag, + ) gc.collect() # not implemented & not planning to @@ -480,7 +511,8 @@ def get_grid_face_nodes(self, grid: int, face_nodes: np.ndarray) -> np.ndarray: raise NotImplementedError() def get_grid_nodes_per_face( - self, grid: int, nodes_per_face: np.ndarray) -> np.ndarray: + self, grid: int, nodes_per_face: np.ndarray + ) -> np.ndarray: raise NotImplementedError() From 4dec2576a4721e254bfb493ec5e14eb3bbb64dab Mon Sep 17 00:00:00 2001 From: Bart Schilperoort Date: Fri, 25 Oct 2024 10:27:55 +0200 Subject: [PATCH 05/11] Update dependencies --- pyproject.toml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 1447585..fa14ef8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,6 +10,7 @@ license = "Apache-2.0" version = "1.5.2" authors = [ { name = "David Haasnoot", email = "davidhaasnoot@gmail.com" }, + { name = "Bart Schilperoort", email = "b.schilperoort@esciencecenter.nl" }, ] # Include here only the dependencies for the BMI Model @@ -19,5 +20,12 @@ dependencies = [ "numpy", "xarray", "netcdf4", + "dask", "pandas", -] \ No newline at end of file +] + +[project.optional-dependencies] +dev = [ + "pytest", + "ruff", +] From 34b385e506daebd14b33b8a912f054c316bfbdae Mon Sep 17 00:00:00 2001 From: Bart Schilperoort Date: Fri, 25 Oct 2024 10:28:05 +0200 Subject: [PATCH 06/11] Allow relative paths in config --- src/HBV/utils.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/HBV/utils.py b/src/HBV/utils.py index 6c0ef88..813c14f 100644 --- a/src/HBV/utils.py +++ b/src/HBV/utils.py @@ -4,9 +4,20 @@ import dask +INPUT_FILES = ["precipitation_file", "potential_evaporation_file", "mean_temperature_file"] + + def read_config(config_file: str) -> dict: with open(config_file) as cfg: config = json.load(cfg) + + for file in INPUT_FILES: + config[file] = Path(config[file]) + + #Make forcing paths absolute based on location of config file: + if not config[file].is_absolute(): + config[file] = (Path(config_file).parent / config[file]).absolute() + return config @@ -37,12 +48,13 @@ def load_var(ncfile: str | Path, varname: str) -> xr.DataArray: data = load_precip(forcing.directory / forcing.pr) """ with dask.config.set(scheduler="synchronous"): + print(ncfile) data: xr.Dataset = xr.load_dataset(ncfile) if "time" not in data.dims: msg = "No time dim in data!" raise ValueError(msg) - if varname not in data.dims: + if varname not in data.data_vars: msg = f"Variable '{varname} is missing from the forcing data!" raise ValueError(msg) From a8aec26ee284f5d85370146414a7db5e3976e96f Mon Sep 17 00:00:00 2001 From: Bart Schilperoort Date: Fri, 25 Oct 2024 10:28:33 +0200 Subject: [PATCH 07/11] Update gitignore --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 0cafc1c..40505c9 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -.venv/ \ No newline at end of file +.venv/ +__pycache__ From fdbf2a52a8fa123e0470d4802fa4b3abb8d98ed2 Mon Sep 17 00:00:00 2001 From: Bart Schilperoort Date: Fri, 25 Oct 2024 10:28:48 +0200 Subject: [PATCH 08/11] Make tests work --- tests/data/config.json | 7 +++++++ .../Derived_Makkink_evspsblpot.nc | Bin .../OBS6_ERA5_reanaly_1_day_pr_1997-2000.nc | Bin ..._ERA5_reanaly_1_day_pr_1997-2000_citation.bibtex | 0 ...6_ERA5_reanaly_1_day_pr_1997-2000_provenance.xml | 0 .../OBS6_ERA5_reanaly_1_day_rsds_1997-2000.nc | Bin ...RA5_reanaly_1_day_rsds_1997-2000_citation.bibtex | 0 ...ERA5_reanaly_1_day_rsds_1997-2000_provenance.xml | 0 .../OBS6_ERA5_reanaly_1_day_tas_1997-2000.nc | Bin ...ERA5_reanaly_1_day_tas_1997-2000_citation.bibtex | 0 ..._ERA5_reanaly_1_day_tas_1997-2000_provenance.xml | 0 .../ewatercycle_forcing.yaml | 0 tests/test_model.py | 12 ++++++++++++ 13 files changed, 19 insertions(+) create mode 100644 tests/data/config.json rename tests/data/{ => ewatercycle_makkink_forcing}/Derived_Makkink_evspsblpot.nc (100%) rename tests/data/{ => ewatercycle_makkink_forcing}/OBS6_ERA5_reanaly_1_day_pr_1997-2000.nc (100%) rename tests/data/{ => ewatercycle_makkink_forcing}/OBS6_ERA5_reanaly_1_day_pr_1997-2000_citation.bibtex (100%) rename tests/data/{ => ewatercycle_makkink_forcing}/OBS6_ERA5_reanaly_1_day_pr_1997-2000_provenance.xml (100%) rename tests/data/{ => ewatercycle_makkink_forcing}/OBS6_ERA5_reanaly_1_day_rsds_1997-2000.nc (100%) rename tests/data/{ => ewatercycle_makkink_forcing}/OBS6_ERA5_reanaly_1_day_rsds_1997-2000_citation.bibtex (100%) rename tests/data/{ => ewatercycle_makkink_forcing}/OBS6_ERA5_reanaly_1_day_rsds_1997-2000_provenance.xml (100%) rename tests/data/{ => ewatercycle_makkink_forcing}/OBS6_ERA5_reanaly_1_day_tas_1997-2000.nc (100%) rename tests/data/{ => ewatercycle_makkink_forcing}/OBS6_ERA5_reanaly_1_day_tas_1997-2000_citation.bibtex (100%) rename tests/data/{ => ewatercycle_makkink_forcing}/OBS6_ERA5_reanaly_1_day_tas_1997-2000_provenance.xml (100%) rename tests/data/{ => ewatercycle_makkink_forcing}/ewatercycle_forcing.yaml (100%) diff --git a/tests/data/config.json b/tests/data/config.json new file mode 100644 index 0000000..2c127ee --- /dev/null +++ b/tests/data/config.json @@ -0,0 +1,7 @@ +{ + "precipitation_file": "ewatercycle_makkink_forcing/OBS6_ERA5_reanaly_1_day_pr_1997-2000.nc", + "potential_evaporation_file": "ewatercycle_makkink_forcing/Derived_Makkink_evspsblpot.nc", + "mean_temperature_file": "ewatercycle_makkink_forcing/OBS6_ERA5_reanaly_1_day_tas_1997-2000.nc", + "parameters": "4.843235614481723,0.9900228877505095,87.7879673161766,2.6729835550404095,0.29315592634372195,1.2944615970981384,0.08362164400640426,0.005459532539096511,1.6817439352332828", + "initial_storage": "0,100,0,5,0" +} \ No newline at end of file diff --git a/tests/data/Derived_Makkink_evspsblpot.nc b/tests/data/ewatercycle_makkink_forcing/Derived_Makkink_evspsblpot.nc similarity index 100% rename from tests/data/Derived_Makkink_evspsblpot.nc rename to tests/data/ewatercycle_makkink_forcing/Derived_Makkink_evspsblpot.nc diff --git a/tests/data/OBS6_ERA5_reanaly_1_day_pr_1997-2000.nc b/tests/data/ewatercycle_makkink_forcing/OBS6_ERA5_reanaly_1_day_pr_1997-2000.nc similarity index 100% rename from tests/data/OBS6_ERA5_reanaly_1_day_pr_1997-2000.nc rename to tests/data/ewatercycle_makkink_forcing/OBS6_ERA5_reanaly_1_day_pr_1997-2000.nc diff --git a/tests/data/OBS6_ERA5_reanaly_1_day_pr_1997-2000_citation.bibtex b/tests/data/ewatercycle_makkink_forcing/OBS6_ERA5_reanaly_1_day_pr_1997-2000_citation.bibtex similarity index 100% rename from tests/data/OBS6_ERA5_reanaly_1_day_pr_1997-2000_citation.bibtex rename to tests/data/ewatercycle_makkink_forcing/OBS6_ERA5_reanaly_1_day_pr_1997-2000_citation.bibtex diff --git a/tests/data/OBS6_ERA5_reanaly_1_day_pr_1997-2000_provenance.xml b/tests/data/ewatercycle_makkink_forcing/OBS6_ERA5_reanaly_1_day_pr_1997-2000_provenance.xml similarity index 100% rename from tests/data/OBS6_ERA5_reanaly_1_day_pr_1997-2000_provenance.xml rename to tests/data/ewatercycle_makkink_forcing/OBS6_ERA5_reanaly_1_day_pr_1997-2000_provenance.xml diff --git a/tests/data/OBS6_ERA5_reanaly_1_day_rsds_1997-2000.nc b/tests/data/ewatercycle_makkink_forcing/OBS6_ERA5_reanaly_1_day_rsds_1997-2000.nc similarity index 100% rename from tests/data/OBS6_ERA5_reanaly_1_day_rsds_1997-2000.nc rename to tests/data/ewatercycle_makkink_forcing/OBS6_ERA5_reanaly_1_day_rsds_1997-2000.nc diff --git a/tests/data/OBS6_ERA5_reanaly_1_day_rsds_1997-2000_citation.bibtex b/tests/data/ewatercycle_makkink_forcing/OBS6_ERA5_reanaly_1_day_rsds_1997-2000_citation.bibtex similarity index 100% rename from tests/data/OBS6_ERA5_reanaly_1_day_rsds_1997-2000_citation.bibtex rename to tests/data/ewatercycle_makkink_forcing/OBS6_ERA5_reanaly_1_day_rsds_1997-2000_citation.bibtex diff --git a/tests/data/OBS6_ERA5_reanaly_1_day_rsds_1997-2000_provenance.xml b/tests/data/ewatercycle_makkink_forcing/OBS6_ERA5_reanaly_1_day_rsds_1997-2000_provenance.xml similarity index 100% rename from tests/data/OBS6_ERA5_reanaly_1_day_rsds_1997-2000_provenance.xml rename to tests/data/ewatercycle_makkink_forcing/OBS6_ERA5_reanaly_1_day_rsds_1997-2000_provenance.xml diff --git a/tests/data/OBS6_ERA5_reanaly_1_day_tas_1997-2000.nc b/tests/data/ewatercycle_makkink_forcing/OBS6_ERA5_reanaly_1_day_tas_1997-2000.nc similarity index 100% rename from tests/data/OBS6_ERA5_reanaly_1_day_tas_1997-2000.nc rename to tests/data/ewatercycle_makkink_forcing/OBS6_ERA5_reanaly_1_day_tas_1997-2000.nc diff --git a/tests/data/OBS6_ERA5_reanaly_1_day_tas_1997-2000_citation.bibtex b/tests/data/ewatercycle_makkink_forcing/OBS6_ERA5_reanaly_1_day_tas_1997-2000_citation.bibtex similarity index 100% rename from tests/data/OBS6_ERA5_reanaly_1_day_tas_1997-2000_citation.bibtex rename to tests/data/ewatercycle_makkink_forcing/OBS6_ERA5_reanaly_1_day_tas_1997-2000_citation.bibtex diff --git a/tests/data/OBS6_ERA5_reanaly_1_day_tas_1997-2000_provenance.xml b/tests/data/ewatercycle_makkink_forcing/OBS6_ERA5_reanaly_1_day_tas_1997-2000_provenance.xml similarity index 100% rename from tests/data/OBS6_ERA5_reanaly_1_day_tas_1997-2000_provenance.xml rename to tests/data/ewatercycle_makkink_forcing/OBS6_ERA5_reanaly_1_day_tas_1997-2000_provenance.xml diff --git a/tests/data/ewatercycle_forcing.yaml b/tests/data/ewatercycle_makkink_forcing/ewatercycle_forcing.yaml similarity index 100% rename from tests/data/ewatercycle_forcing.yaml rename to tests/data/ewatercycle_makkink_forcing/ewatercycle_forcing.yaml diff --git a/tests/test_model.py b/tests/test_model.py index e69de29..16729de 100644 --- a/tests/test_model.py +++ b/tests/test_model.py @@ -0,0 +1,12 @@ +from pathlib import Path +from HBV import HBV + +TEST_CONFIG = str(Path(__file__).parent / "data" / "config.json") + +def test_full_run(): + model = HBV() + model.initialize(TEST_CONFIG) + + model.update_until(model.get_end_time()) + + model.finalize() From d564bf48ccd89db90a7839e4ea7395dd1a232f20 Mon Sep 17 00:00:00 2001 From: Bart Schilperoort Date: Fri, 25 Oct 2024 10:34:12 +0200 Subject: [PATCH 09/11] Implement some bmi methods --- src/HBV/HBV_bmi.py | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/HBV/HBV_bmi.py b/src/HBV/HBV_bmi.py index 328a008..78435b2 100644 --- a/src/HBV/HBV_bmi.py +++ b/src/HBV/HBV_bmi.py @@ -1,11 +1,12 @@ import gc -from bmipy import Bmi -from typing import Any, Tuple +from typing import Any, Tuple, TYPE_CHECKING from HBV import utils import numpy as np import warnings -import gc + +if TYPE_CHECKING: + from bmipy import Bmi DICT_VAR_UNITS = { "Imax": "mm", @@ -32,7 +33,7 @@ } -class HBV(Bmi): +class HBV("Bmi"): """HBV model wrapped in a BMI interface.""" def initialize(self, config_file: str) -> None: @@ -400,7 +401,11 @@ def get_time_units(self) -> str: def get_value_at_indices( self, name: str, dest: np.ndarray, inds: np.ndarray ) -> np.ndarray: - raise NotImplementedError() + if inds != np.array([0]): + msg = "Lumped model: only valid index is 0" + raise ValueError(msg) + return self.get_value(name, dest) + # TODO implement def set_value_at_indices( @@ -466,16 +471,14 @@ def finalize(self) -> None: ) gc.collect() - # not implemented & not planning to - def get_input_var_names(self) -> Tuple[str]: - raise NotImplementedError() + return ("Tlag", "memory_vector") def get_input_item_count(self) -> int: - raise NotImplementedError() + return 2 def get_output_item_count(self) -> int: - raise NotImplementedError() + return len(DICT_VAR_UNITS) def get_value_ptr(self, name: str) -> np.ndarray: raise NotImplementedError() @@ -484,7 +487,8 @@ def get_var_location(self, name: str) -> str: raise NotImplementedError() def update_until(self, time: float) -> None: - raise NotImplementedError() + while time < self.get_current_time() and time < self.get_end_time(): + self.update() def get_grid_spacing(self, grid: int, spacing: np.ndarray) -> np.ndarray: raise NotImplementedError() From 011099d3ce9865113e3568fb061668ce7418ef12 Mon Sep 17 00:00:00 2001 From: Bart Schilperoort Date: Fri, 25 Oct 2024 10:57:12 +0200 Subject: [PATCH 10/11] Make tests pass --- src/HBV/HBV_bmi.py | 7 +++---- src/HBV/utils.py | 1 - tests/test_model.py | 9 +++++++++ 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/HBV/HBV_bmi.py b/src/HBV/HBV_bmi.py index 78435b2..cb7652d 100644 --- a/src/HBV/HBV_bmi.py +++ b/src/HBV/HBV_bmi.py @@ -1,12 +1,11 @@ import gc -from typing import Any, Tuple, TYPE_CHECKING +from typing import Any, Tuple from HBV import utils import numpy as np import warnings +from bmipy import Bmi -if TYPE_CHECKING: - from bmipy import Bmi DICT_VAR_UNITS = { "Imax": "mm", @@ -33,7 +32,7 @@ } -class HBV("Bmi"): +class HBV(Bmi): """HBV model wrapped in a BMI interface.""" def initialize(self, config_file: str) -> None: diff --git a/src/HBV/utils.py b/src/HBV/utils.py index 813c14f..82a2e86 100644 --- a/src/HBV/utils.py +++ b/src/HBV/utils.py @@ -48,7 +48,6 @@ def load_var(ncfile: str | Path, varname: str) -> xr.DataArray: data = load_precip(forcing.directory / forcing.pr) """ with dask.config.set(scheduler="synchronous"): - print(ncfile) data: xr.Dataset = xr.load_dataset(ncfile) if "time" not in data.dims: diff --git a/tests/test_model.py b/tests/test_model.py index 16729de..02e2b6f 100644 --- a/tests/test_model.py +++ b/tests/test_model.py @@ -1,4 +1,6 @@ from pathlib import Path + +import numpy as np from HBV import HBV TEST_CONFIG = str(Path(__file__).parent / "data" / "config.json") @@ -7,6 +9,13 @@ def test_full_run(): model = HBV() model.initialize(TEST_CONFIG) + for _ in range(3): + model.update() + discharge = model.get_value("Q", np.array([0.])) + assert discharge > 0.01 + model.update_until(model.get_end_time()) model.finalize() + +test_full_run() \ No newline at end of file From bd2e4f8ef3cd79f52010c48fcc0b39012bb92114 Mon Sep 17 00:00:00 2001 From: Bart Schilperoort Date: Fri, 25 Oct 2024 10:57:22 +0200 Subject: [PATCH 11/11] Update dockerfile --- Dockerfile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index e7b3f60..e067da2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -30,10 +30,9 @@ # This will spawn a new bash terminal running inside the docker container FROM mambaorg/micromamba:1.3.1 -MAINTAINER David Haasnoot daafips@gmail.com # Here you can point to the source repository of this Dockerfile: -LABEL org.opencontainers.image.source="https://github.com/Daafip/HBV-bmi" +LABEL org.opencontainers.image.source="https://github.com/eWaterCycle/HBV-bmi" # Install Python + additional conda-dependencies, # Here I added cartopy as an example