smashbox 1.0__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- smashbox/.spyproject/config/backups/codestyle.ini.bak +8 -0
- smashbox/.spyproject/config/backups/encoding.ini.bak +6 -0
- smashbox/.spyproject/config/backups/vcs.ini.bak +7 -0
- smashbox/.spyproject/config/backups/workspace.ini.bak +12 -0
- smashbox/.spyproject/config/codestyle.ini +8 -0
- smashbox/.spyproject/config/defaults/defaults-codestyle-0.2.0.ini +5 -0
- smashbox/.spyproject/config/defaults/defaults-encoding-0.2.0.ini +3 -0
- smashbox/.spyproject/config/defaults/defaults-vcs-0.2.0.ini +4 -0
- smashbox/.spyproject/config/defaults/defaults-workspace-0.2.0.ini +6 -0
- smashbox/.spyproject/config/encoding.ini +6 -0
- smashbox/.spyproject/config/vcs.ini +7 -0
- smashbox/.spyproject/config/workspace.ini +12 -0
- smashbox/__init__.py +8 -0
- smashbox/asset/flwdir/flowdir_fr_1000m.tif +0 -0
- smashbox/asset/outlets/.Rhistory +0 -0
- smashbox/asset/outlets/db_bnbv_fr.csv +142704 -0
- smashbox/asset/outlets/db_bnbv_light.csv +42084 -0
- smashbox/asset/outlets/db_sites.csv +8700 -0
- smashbox/asset/outlets/db_stations.csv +2916 -0
- smashbox/asset/outlets/db_stations_example.csv +19 -0
- smashbox/asset/outlets/edit_database.py +185 -0
- smashbox/asset/outlets/readme.txt +5 -0
- smashbox/asset/params/ci.tif +0 -0
- smashbox/asset/params/cp.tif +0 -0
- smashbox/asset/params/ct.tif +0 -0
- smashbox/asset/params/kexc.tif +0 -0
- smashbox/asset/params/kmlt.tif +0 -0
- smashbox/asset/params/llr.tif +0 -0
- smashbox/asset/setup/setup_rhax_gr4_dt3600.yaml +15 -0
- smashbox/asset/setup/setup_rhax_gr4_dt900.yaml +15 -0
- smashbox/asset/setup/setup_rhax_gr5_dt3600.yaml +15 -0
- smashbox/asset/setup/setup_rhax_gr5_dt900.yaml +15 -0
- smashbox/init/README.md +3 -0
- smashbox/init/__init__.py +3 -0
- smashbox/init/multimodel_statistics.py +405 -0
- smashbox/init/param.py +799 -0
- smashbox/init/smashbox.py +186 -0
- smashbox/model/__init__.py +1 -0
- smashbox/model/atmos_data_connector.py +518 -0
- smashbox/model/mesh.py +185 -0
- smashbox/model/model.py +829 -0
- smashbox/model/setup.py +109 -0
- smashbox/plot/__init__.py +1 -0
- smashbox/plot/myplot.py +1133 -0
- smashbox/plot/plot.py +1662 -0
- smashbox/read_inputdata/__init__.py +1 -0
- smashbox/read_inputdata/read_data.py +1229 -0
- smashbox/read_inputdata/smashmodel.py +395 -0
- smashbox/stats/__init__.py +1 -0
- smashbox/stats/mystats.py +1632 -0
- smashbox/stats/stats.py +2022 -0
- smashbox/test.py +532 -0
- smashbox/test_average_stats.py +122 -0
- smashbox/test_mesh.r +8 -0
- smashbox/test_mesh_from_graffas.py +69 -0
- smashbox/tools/__init__.py +1 -0
- smashbox/tools/geo_toolbox.py +1028 -0
- smashbox/tools/tools.py +461 -0
- smashbox/tutorial_R.r +182 -0
- smashbox/tutorial_R_graffas.r +88 -0
- smashbox/tutorial_R_graffas_local.r +33 -0
- smashbox/tutorial_python.py +102 -0
- smashbox/tutorial_readme.py +261 -0
- smashbox/tutorial_report.py +58 -0
- smashbox/tutorials/Python_tutorial.md +124 -0
- smashbox/tutorials/R_Graffas_tutorial.md +153 -0
- smashbox/tutorials/R_tutorial.md +121 -0
- smashbox/tutorials/__init__.py +6 -0
- smashbox/tutorials/generate_doc.md +7 -0
- smashbox-1.0.dist-info/METADATA +998 -0
- smashbox-1.0.dist-info/RECORD +73 -0
- smashbox-1.0.dist-info/WHEEL +5 -0
- smashbox-1.0.dist-info/licenses/LICENSE +100 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
|
|
2
|
+
#Graffas Tutorial - 2
|
|
3
|
+
|
|
4
|
+
library(reticulate)
|
|
5
|
+
use_virtualenv("/nas/RHAX/UTILISATEURS/maxime.jay-allemand/smashbox/smashbox_env_21/") #use a specific python environnement
|
|
6
|
+
|
|
7
|
+
#import the package smashbox (must be installed in the python environnement)
|
|
8
|
+
smashbox <- import("smashbox")
|
|
9
|
+
|
|
10
|
+
path_to_graffas_rainfall="/nas/RHAX/UTILISATEURS/kevin.tartour/2025_Graffas/SPATIAL/Gapeau/DataOutput/simul/RRsim_Gapeau_calage_reso_1000_res_1000_twin1_SMASH.Rdata"
|
|
11
|
+
GraffasRainfall=load(path_to_graffas_rainfall)
|
|
12
|
+
|
|
13
|
+
#get the bbox for Smash
|
|
14
|
+
bbox=smashbox$tools$tools$infograffas_bbox_extractor(info_simu_smash)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
#Main initialisation of the module
|
|
18
|
+
sb <- smashbox$SmashBox()
|
|
19
|
+
sb$myparam$set_param("bbox", bbox)
|
|
20
|
+
sb$myparam$set_param("outlets_database", "db_sites")
|
|
21
|
+
|
|
22
|
+
sb$myparam$set_param(
|
|
23
|
+
"outlets_shapefile",
|
|
24
|
+
"/nas/RHAX/DONNEES/SIG/BASSINS/CONTOUR/SITES_L93/Hydro_Bassins.shp"
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
sb$newmodel("gapeau")
|
|
28
|
+
|
|
29
|
+
sb$gapeau$generate_mesh()
|
|
30
|
+
|
|
31
|
+
sb$gapeau$myplot$plot_mesh(fig_settings=list("figname"="/nas/RHAX/UTILISATEURS/maxime.jay-allemand/smashbox/output/gapeau_mesh.png"))
|
|
32
|
+
|
|
33
|
+
#Make a warmup during 365 days before the start-time found in the setup. This step use real rainfall data.
|
|
34
|
+
sb$gapeau$model_warmup(warmup=365)
|
|
35
|
+
|
|
36
|
+
#1- Compute Qantile for a "shorter" period
|
|
37
|
+
|
|
38
|
+
sb$gapeau$atmos_data_connector(input_prcp=RRsim_3D,input_start_time="2020-01-01 01:00")
|
|
39
|
+
sb$gapeau$model()
|
|
40
|
+
sb$gapeau$forward_run(return_options=list("q_domain"= TRUE))
|
|
41
|
+
sb$gapeau$mystats$fquantile_stats(
|
|
42
|
+
chunk_size=365, estimate_method="MLE", ncpu=6, fit="gumbel", compute_uncertaintisb=FALSE,
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
#2-Compute Qantile for a very long period
|
|
46
|
+
|
|
47
|
+
#we split the period in 3 blocs (chunk))
|
|
48
|
+
chunk_size=as.integer(dim(RRsim_3D)[3]/3)
|
|
49
|
+
for (i in 0:2){
|
|
50
|
+
#send the rainfall data (Graffas) to smash
|
|
51
|
+
sb$gapeau$atmos_data_connector(input_prcp=RRsim_3D[,,(i*chunk_size):((i+1)*chunk_size)])
|
|
52
|
+
#generate the smash model
|
|
53
|
+
sb$gapeau$model()
|
|
54
|
+
#run the model with option invert_statsb=True : we use the final states as initial states except for the 1st chunk
|
|
55
|
+
sb$gapeau$forward_run(invert_statsb=TRUE,return_options=list("q_domain"= TRUE))
|
|
56
|
+
#compute the annual maxima over each chunk: use option cumulated_maxima=True to store and accumulate these maxima
|
|
57
|
+
sb$gapeau$mystats$fmaxima_stats(
|
|
58
|
+
chunk_size=365, cumulated_maxima=TRUE,
|
|
59
|
+
)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
#finally adjust an extrem law over the maxima and compute the discharges quantile.
|
|
63
|
+
sb$gapeau$mystats$fquantile_stats(
|
|
64
|
+
chunk_size=365, compute_uncertaintisb=TRUE
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
# Figures:
|
|
68
|
+
|
|
69
|
+
sb$gapeau$myplot$plot_xy_quantile(
|
|
70
|
+
duration=1,
|
|
71
|
+
X=as.integer(15),
|
|
72
|
+
Y=as.integer(25),
|
|
73
|
+
fig_settings=list("figname"= "/nas/RHAX/UTILISATEURS/maxime.jay-allemand/smashbox/output/quantile_XY_1h.png", "font_ratio"= 2),
|
|
74
|
+
ax_settings=list("legend_fontsize"= 20),
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
sb$gapeau$myplot$plot_outlets_quantile(duration=1,fig_settings=list("figname"= "/nas/RHAX/UTILISATEURS/maxime.jay-allemand/smashbox/output/quantile_outlets.png", "font_ratio"= 2))
|
|
78
|
+
|
|
79
|
+
sb$gapeau$myplot$plot_spatial_quantile(duration=1, T=2, fig_settings=list("figname"= "/nas/RHAX/UTILISATEURS/maxime.jay-allemand/smashbox/output/quantile_spatial_1hT2.png", "font_ratio"= 2))
|
|
80
|
+
|
|
81
|
+
sb$gapeau$myplot$multiplot_spatial_quantile(fig_settings=list("figname"= "/nas/RHAX/UTILISATEURS/maxime.jay-allemand/smashbox/output/quantile_spatial_multiplot.png", "font_ratio"= 1))
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
sb$gapeau$myplot$multiplot_parameters(
|
|
85
|
+
fig_settings=list("figname"= "/nas/RHAX/UTILISATEURS/maxime.jay-allemand/smashbox/output/gapeau_parameters.png")
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
|
|
2
|
+
#Graffas Tutorial - 2
|
|
3
|
+
|
|
4
|
+
library(reticulate)
|
|
5
|
+
use_virtualenv("/home/maxime/python_venv/easysmash/") #use a specific python environnement
|
|
6
|
+
|
|
7
|
+
#import the package smashbox (must be installed in the python environnement)
|
|
8
|
+
smashbox <- import("smashbox")
|
|
9
|
+
|
|
10
|
+
path_to_graffas_rainfall="~/smashbox_tmp/RRsim_Gapeau_calage_reso_1000_res_1000_twin1_SMASH.Rdata"
|
|
11
|
+
GraffasRainfall=load(path_to_graffas_rainfall)
|
|
12
|
+
|
|
13
|
+
#get the bbox for Smash
|
|
14
|
+
bbox=smashbox$tools$tools$infograffas_bbox_extractor(info_simu_smash)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
#Main initialisation of the module
|
|
18
|
+
sb <- smashbox$SmashBox()
|
|
19
|
+
sb$myparam$set_param("bbox", bbox)
|
|
20
|
+
sb$myparam$set_param("outlets_database", "db_sites")
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
sb$newmodel("gapeau")
|
|
25
|
+
|
|
26
|
+
sb$gapeau$generate_mesh()
|
|
27
|
+
|
|
28
|
+
sb$gapeau$mymesh$mesh["nrow"]
|
|
29
|
+
sb$gapeau$mymesh$mesh["ncol"]
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
sb$gapeau$atmos_data_connector(input_prcp=RRsim_3D,input_start_time="2020-01-01 01:00")
|
|
33
|
+
RRsim_3D
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""
|
|
4
|
+
Created on Thu Aug 21 12:03:55 2025
|
|
5
|
+
|
|
6
|
+
@author: maxime
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
if __name__ == "__main__":
|
|
11
|
+
|
|
12
|
+
import smashbox
|
|
13
|
+
|
|
14
|
+
bbox = {"left": 875000.0, "bottom": 6228000.0, "right": 1001000.0, "top": 6320000.0}
|
|
15
|
+
|
|
16
|
+
sb = smashbox.SmashBox()
|
|
17
|
+
|
|
18
|
+
sb.myparam.set_param("bbox", bbox)
|
|
19
|
+
sb.myparam.set_param("outlets_database", "db_sites")
|
|
20
|
+
sb.myparam.set_param("smash_parameters_dt", 3600.0)
|
|
21
|
+
|
|
22
|
+
# RHAX
|
|
23
|
+
sb.myparam.set_param(
|
|
24
|
+
"outlets_shapefile",
|
|
25
|
+
"/nas/RHAX/DONNEES/SIG/BASSINS/CONTOUR/SITES_L93/Hydro_Bassins.shp",
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
sb.newmodel("rex")
|
|
29
|
+
|
|
30
|
+
sb.rex.mysetup.update_setup(
|
|
31
|
+
{
|
|
32
|
+
"start_time": "2014-01-01 00:00",
|
|
33
|
+
"end_time": "2014-02-01 00:00",
|
|
34
|
+
}
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
# MAX
|
|
38
|
+
# sb.myparam.set_param(
|
|
39
|
+
# "outlets_shapefile",
|
|
40
|
+
# "/home/maxime/DEV/easysmash/smashbox/smashbox/asset/shapefile/Hydro_Bassins.shp",
|
|
41
|
+
# )
|
|
42
|
+
|
|
43
|
+
# sb.newmodel("rex")
|
|
44
|
+
|
|
45
|
+
# sb.rex.mysetup.update_setup(
|
|
46
|
+
# {
|
|
47
|
+
# "pet_directory": "/home/maxime/DATA/ETP-SFR-FRA-INTERA_L93",
|
|
48
|
+
# "prcp_directory": "/home/maxime/DATA/PLUIE",
|
|
49
|
+
# "qobs_directory": "/home/maxime/DATA/QOBS_SITE_60M",
|
|
50
|
+
# "start_time": "2014-01-01 00:00",
|
|
51
|
+
# "end_time": "2014-02-01 00:00",
|
|
52
|
+
# }
|
|
53
|
+
# )
|
|
54
|
+
|
|
55
|
+
sb.rex.generate_mesh(
|
|
56
|
+
query="(SURF>40) & (INFLUENCE=='Influence nulle ou faible')", area_error_th=0.2
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
# optimize parameters if required
|
|
60
|
+
# sb.rex.optimize()
|
|
61
|
+
|
|
62
|
+
sb.rex.myplot.plot_mesh(fig_settings={"figname": "output/mesh.png"})
|
|
63
|
+
sb.rex.myplot.plot_catchment_surface_error(
|
|
64
|
+
fig_settings={"figname": "output/mesh_surface_error.png"}
|
|
65
|
+
)
|
|
66
|
+
sb.rex.myplot.plot_catchment_surface_consistency(
|
|
67
|
+
fig_settings={"figname": "output/mesh_surface_consistency.png"}
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
sb.rex.model()
|
|
71
|
+
sb.rex.forward_run(return_options={"q_domain": True}, warmup=100)
|
|
72
|
+
|
|
73
|
+
sb.rex.mystats.foutlets_stats()
|
|
74
|
+
sb.rex.mystats.fspatial_stats()
|
|
75
|
+
sb.rex.mystats.fmisfit_stats()
|
|
76
|
+
|
|
77
|
+
sb.rex.myplot.multiplot_parameters(
|
|
78
|
+
fig_settings={"figname": "output/muliplot_parameters.png"}
|
|
79
|
+
)
|
|
80
|
+
sb.rex.myplot.plot_parameters(fig_settings={"figname": "output/cp_parameters.png"})
|
|
81
|
+
|
|
82
|
+
sb.rex.myplot.plot_outlet_stats(
|
|
83
|
+
fig_settings={"figname": "output/outlets_max_discharges.png"}
|
|
84
|
+
)
|
|
85
|
+
sb.rex.myplot.plot_hydrograph(
|
|
86
|
+
fig_settings={"figname": "output/outlet_discharges.png"}
|
|
87
|
+
)
|
|
88
|
+
sb.rex.myplot.plot_spatial_stats(
|
|
89
|
+
fig_settings={"figname": "output/spatial_max_discharges.png"}
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
sb.rex.myplot.multiplot_misfit(
|
|
93
|
+
fig_settings={
|
|
94
|
+
"figname": "output/multiplot_nse_misfit.png",
|
|
95
|
+
"xsize": 15,
|
|
96
|
+
"ysize": 15,
|
|
97
|
+
}
|
|
98
|
+
)
|
|
99
|
+
sb.rex.myplot.plot_misfit(
|
|
100
|
+
misfit="nnse", fig_settings={"figname": "output/nnse_misfit.png"}
|
|
101
|
+
)
|
|
102
|
+
sb.rex.myplot.plot_misfit_map(fig_settings={"figname": "output/map_nse_misfit.png"})
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
if __name__ == "__main__":
|
|
4
|
+
|
|
5
|
+
import smashbox
|
|
6
|
+
import numpy as np
|
|
7
|
+
|
|
8
|
+
bbox = {"left": 925000.0, "bottom": 6230000.0, "right": 974000.0, "top": 6255000.0}
|
|
9
|
+
|
|
10
|
+
sb = smashbox.SmashBox()
|
|
11
|
+
|
|
12
|
+
sb.myparam.set_param("bbox", bbox)
|
|
13
|
+
sb.myparam.set_param(
|
|
14
|
+
"smash_parameters", "/home/maxime/DEV/smashbox/smashbox/asset/params"
|
|
15
|
+
)
|
|
16
|
+
sb.myparam.set_param(
|
|
17
|
+
"outlets_database",
|
|
18
|
+
"/home/maxime/DEV/smashbox/smashbox/asset/outlets/db_sites.csv",
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
sb.newmodel("graffas_zone")
|
|
22
|
+
sb.graffas_zone.mysetup.load_setup("setup_rhax_gr4_dt3600")
|
|
23
|
+
|
|
24
|
+
sb.graffas_zone.mysetup.update_setup(
|
|
25
|
+
{
|
|
26
|
+
"pet_directory": "/home/maxime/DATA/ETP-SFR-FRA-INTERA_L93",
|
|
27
|
+
"prcp_directory": "/home/maxime/DATA/PLUIE",
|
|
28
|
+
"qobs_directory": "/home/maxime/DATA/QOBS_SITE_60M",
|
|
29
|
+
}
|
|
30
|
+
) # Change value of the Smash setup
|
|
31
|
+
|
|
32
|
+
sb.graffas_zone.generate_mesh(
|
|
33
|
+
query="(SURF>20) & (INFLUENCE=='Influence nulle ou faible')"
|
|
34
|
+
) # direct method to build the mesh (recommended)
|
|
35
|
+
|
|
36
|
+
sb.graffas_zone.myplot.plot_catchment_surface_consistency(
|
|
37
|
+
fig_settings={
|
|
38
|
+
"figname": "../images/mesh_surface_consistency.png",
|
|
39
|
+
"xsize": 4,
|
|
40
|
+
"ysize": 4,
|
|
41
|
+
"font_ratio": 1,
|
|
42
|
+
},
|
|
43
|
+
ax_settings={"title_fontsize": 12},
|
|
44
|
+
)
|
|
45
|
+
sb.graffas_zone.myplot.plot_catchment_surface_error(
|
|
46
|
+
fig_settings={
|
|
47
|
+
"figname": "../images/mesh_surface_error.png",
|
|
48
|
+
"xsize": 4,
|
|
49
|
+
"ysize": 4,
|
|
50
|
+
"font_ratio": 1,
|
|
51
|
+
},
|
|
52
|
+
ax_settings={"title_fontsize": 12},
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
sb.graffas_zone.myplot.plot_mesh(
|
|
56
|
+
fig_settings={
|
|
57
|
+
"figname": "../images/mesh.png",
|
|
58
|
+
"xsize": 6,
|
|
59
|
+
"ysize": 4,
|
|
60
|
+
},
|
|
61
|
+
ax_settings={"title_fontsize": 14},
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
nrow = sb.graffas_zone.mymesh.mesh["nrow"]
|
|
65
|
+
ncol = sb.graffas_zone.mymesh.mesh["ncol"]
|
|
66
|
+
chunk_size = 18
|
|
67
|
+
nb_chunk = 21
|
|
68
|
+
graffas_prcp = np.zeros(shape=(nrow, ncol, nb_chunk * chunk_size))
|
|
69
|
+
fctr = 100
|
|
70
|
+
for i in range(nb_chunk):
|
|
71
|
+
graffas_prcp[:, :, i * chunk_size : (i + 1) * chunk_size] = (
|
|
72
|
+
fctr
|
|
73
|
+
* np.arange(i * chunk_size, (i + 1) * chunk_size)
|
|
74
|
+
/ (chunk_size * nb_chunk)
|
|
75
|
+
* np.cos(np.arange(0, chunk_size * 10, 10) * np.pi / 180)
|
|
76
|
+
)
|
|
77
|
+
graffas_prcp = np.where(graffas_prcp < 0, 0.0, graffas_prcp)
|
|
78
|
+
|
|
79
|
+
sb.graffas_zone.model_warmup(warmup=365)
|
|
80
|
+
|
|
81
|
+
sb.graffas_zone.atmos_data_connector(input_prcp=graffas_prcp, input_dt=3600.0)
|
|
82
|
+
|
|
83
|
+
sb.graffas_zone.model()
|
|
84
|
+
|
|
85
|
+
sb.graffas_zone.myplot.plot_parameters(
|
|
86
|
+
param="cp",
|
|
87
|
+
fig_settings={
|
|
88
|
+
"figname": "../images/param_cp.png",
|
|
89
|
+
"xsize": 5,
|
|
90
|
+
"ysize": 5,
|
|
91
|
+
},
|
|
92
|
+
ax_settings={"font_ratio": 1},
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
sb.graffas_zone.myplot.multiplot_parameters(
|
|
96
|
+
fig_settings={
|
|
97
|
+
"figname": "../images/multiplot_param.png",
|
|
98
|
+
"font_ratio": 1,
|
|
99
|
+
"xsize": 7,
|
|
100
|
+
"ysize": 6,
|
|
101
|
+
},
|
|
102
|
+
ax_settings={"title_fontsize": 10, "font_ratio": 0.6},
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
sb.graffas_zone.forward_run(invert_states=True, return_options={"q_domain": True})
|
|
106
|
+
|
|
107
|
+
rand_q = np.random.rand(*sb.graffas_zone.mysmashmodel.response_data.q.shape)
|
|
108
|
+
sb.graffas_zone.mysmashmodel.response_data.q[
|
|
109
|
+
:
|
|
110
|
+
] = sb.graffas_zone.mysmashmodel.response.q[
|
|
111
|
+
:
|
|
112
|
+
] + sb.graffas_zone.mysmashmodel.response.q[
|
|
113
|
+
:
|
|
114
|
+
] * (
|
|
115
|
+
rand_q[:] - 0.5
|
|
116
|
+
) * np.repeat(
|
|
117
|
+
np.arange(rand_q.shape[0]).reshape((rand_q.shape[0], 1)), rand_q.shape[1], axis=1
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
sb.graffas_zone.mystats.fspatial_stats()
|
|
121
|
+
sb.graffas_zone.mystats.foutlets_stats()
|
|
122
|
+
sb.graffas_zone.mystats.fmisfit_stats(use_smash_metrics=False)
|
|
123
|
+
sb.graffas_zone.mystats.fmisfit_stats(use_smash_metrics=True)
|
|
124
|
+
|
|
125
|
+
# test des metrics
|
|
126
|
+
# -------------------------------------------------------
|
|
127
|
+
from smash.fcore import _mwd_metrics as smash_metrics
|
|
128
|
+
|
|
129
|
+
metric_list = ["nse", "kge", "lgrm", "mae", "mape", "mse", "nnse", "rmse", "se"]
|
|
130
|
+
|
|
131
|
+
for metric_name in metric_list:
|
|
132
|
+
# metric_name = "nse"
|
|
133
|
+
fmetric = getattr(smash_metrics, metric_name)
|
|
134
|
+
metric = np.zeros(shape=(len(sb.graffas_zone.mysmashmodel.mesh.code))) + np.nan
|
|
135
|
+
for i in range(len(sb.graffas_zone.mysmashmodel.mesh.code)):
|
|
136
|
+
qobs = sb.graffas_zone.mysmashmodel.response_data.q[i, :]
|
|
137
|
+
qsim = sb.graffas_zone.mysmashmodel.response.q[i, :]
|
|
138
|
+
metric[i] = fmetric(qobs, qsim)
|
|
139
|
+
|
|
140
|
+
if hasattr(sb.graffas_zone.mystats.misfit_stats.results, metric_name):
|
|
141
|
+
smashbox_metric = getattr(
|
|
142
|
+
sb.graffas_zone.mystats.misfit_stats.results, metric_name
|
|
143
|
+
)
|
|
144
|
+
print(f"diff on metric {metric_name}:")
|
|
145
|
+
print(smashbox_metric - metric)
|
|
146
|
+
else:
|
|
147
|
+
print(f"no metric {metric_name} found")
|
|
148
|
+
|
|
149
|
+
# -------------------------------------------------------
|
|
150
|
+
|
|
151
|
+
sb.graffas_zone.mystats.fquantile_stats(
|
|
152
|
+
chunk_size=3,
|
|
153
|
+
estimate_method="MLE",
|
|
154
|
+
ncpu=4,
|
|
155
|
+
fit="gumbel",
|
|
156
|
+
compute_uncertainties=False,
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
sb.graffas_zone.myplot.plot_outlets_quantile()
|
|
160
|
+
sb.graffas_zone.myplot.plot_outlets_quantile(quantile_obs=False)
|
|
161
|
+
|
|
162
|
+
sb.graffas_zone.mystats.fmaxima_stats(chunk_size=3, cumulated_maxima=True)
|
|
163
|
+
|
|
164
|
+
# import matplotlib.pyplot as plt
|
|
165
|
+
|
|
166
|
+
# var = "spatial_quantile_outlets"
|
|
167
|
+
|
|
168
|
+
# fig, ax = plt.subplots()
|
|
169
|
+
|
|
170
|
+
# var_outlets = getattr(es.graffas_zone.mystats.quantile_stats, var)
|
|
171
|
+
|
|
172
|
+
# for i in range(var_outlets.shape[0]):
|
|
173
|
+
# ax.plot(var_outlets[i, :], "x", markersize=5)
|
|
174
|
+
|
|
175
|
+
# for i in range(len(es.graffas_zone.mymesh.mesh["code"])):
|
|
176
|
+
# coords = sb.graffas_zone.mymesh.mesh["gauge_pos"][i]
|
|
177
|
+
# var_outlets = getattr(
|
|
178
|
+
# sb.graffas_zone.mystats.quantile_stats, var.removesuffix("_outlets")
|
|
179
|
+
# )[coords[0], coords[1], :]
|
|
180
|
+
|
|
181
|
+
# ax.plot(var_outlets[:, 1], "o", markersize=4)
|
|
182
|
+
|
|
183
|
+
# save the smashbox container:
|
|
184
|
+
sb.graffas_zone.save_model_container(path_to_hdf5="my_smashbox_data.hdf5")
|
|
185
|
+
dict_es = sb.graffas_zone.save_model_container()
|
|
186
|
+
|
|
187
|
+
sb.graffas_zone.myplot.plot_spatial_stats(
|
|
188
|
+
fig_settings={
|
|
189
|
+
"figname": "../images/spatial_stats_max.png",
|
|
190
|
+
"xsize": 5,
|
|
191
|
+
"ysize": 5,
|
|
192
|
+
},
|
|
193
|
+
ax_settings={"font_ratio": 0.8},
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
sb.graffas_zone.myplot.plot_xy_quantile(
|
|
197
|
+
X=20,
|
|
198
|
+
Y=25,
|
|
199
|
+
fig_settings={"figname": "../images/quantile_XY.png", "xsize": 4, "ysize": 4},
|
|
200
|
+
ax_settings={"font_ratio": 1},
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
sb.graffas_zone.myplot.plot_outlets_quantile(
|
|
204
|
+
fig_settings={
|
|
205
|
+
"figname": "../images/quantile_outlets.png",
|
|
206
|
+
"xsize": 6,
|
|
207
|
+
"ysize": 8,
|
|
208
|
+
},
|
|
209
|
+
ax_settings={"font_ratio": 0.8},
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
sb.graffas_zone.myplot.plot_spatial_quantile(
|
|
213
|
+
T=2,
|
|
214
|
+
duration=1,
|
|
215
|
+
fig_settings={
|
|
216
|
+
"figname": "../images/spatial_quantile.png",
|
|
217
|
+
"xsize": 4,
|
|
218
|
+
"ysize": 4,
|
|
219
|
+
},
|
|
220
|
+
ax_settings={"font_ratio": 0.8},
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
sb.graffas_zone.myplot.multiplot_spatial_quantile(
|
|
224
|
+
duration=1,
|
|
225
|
+
fig_settings={
|
|
226
|
+
"figname": "../images/multiplot_spatial_quantile.png",
|
|
227
|
+
"xsize": 6,
|
|
228
|
+
"ysize": 6,
|
|
229
|
+
},
|
|
230
|
+
ax_settings={"font_ratio": 0.6},
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
sb.graffas_zone.myplot.plot_hydrograph(
|
|
234
|
+
fig_settings={
|
|
235
|
+
"figname": "../images/hydrogram.png",
|
|
236
|
+
},
|
|
237
|
+
)
|
|
238
|
+
|
|
239
|
+
sb.graffas_zone.myplot.plot_misfit(
|
|
240
|
+
misfit="nse",
|
|
241
|
+
fig_settings={
|
|
242
|
+
"figname": "../images/nse2.png",
|
|
243
|
+
"xsize": 4,
|
|
244
|
+
"ysize": 3,
|
|
245
|
+
},
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
sb.graffas_zone.myplot.multiplot_misfit(
|
|
249
|
+
fig_settings={
|
|
250
|
+
"figname": "../images/multiplot_misfit2.png",
|
|
251
|
+
"xsize": 6,
|
|
252
|
+
"ysize": 6,
|
|
253
|
+
},
|
|
254
|
+
ax_settings={"font_ratio": 0.4},
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
sb.graffas_zone.myplot.plot_misfit_map(
|
|
258
|
+
misfit="nse",
|
|
259
|
+
fig_settings={"figname": "../images/misfit_map.png", "xsize": 8, "ysize": 6},
|
|
260
|
+
ax_settings={"font_ratio": 1},
|
|
261
|
+
)
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
if __name__ == "__main__":
|
|
4
|
+
|
|
5
|
+
################ Test rapoort ################
|
|
6
|
+
import smashbox
|
|
7
|
+
import numpy as np
|
|
8
|
+
|
|
9
|
+
bbox = {"left": 875000.0, "bottom": 6228000.0, "right": 1001000.0, "top": 6320000.0}
|
|
10
|
+
|
|
11
|
+
sb = smashbox.SmashBox()
|
|
12
|
+
|
|
13
|
+
sb.myparam.set_param("bbox", bbox)
|
|
14
|
+
|
|
15
|
+
sb.newmodel("rex")
|
|
16
|
+
|
|
17
|
+
sb.rex.mysetup.update_setup({"read_pet": False})
|
|
18
|
+
|
|
19
|
+
sb.rex.generate_mesh(
|
|
20
|
+
query="(SURF>200) & (INFLUENCE=='Influence nulle ou faible')", area_error_th=0.2
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
sb.rex.myplot.plot_mesh()
|
|
24
|
+
|
|
25
|
+
##########################################################
|
|
26
|
+
# Artificial rainfall
|
|
27
|
+
nrow = sb.rex.mymesh.mesh["nrow"]
|
|
28
|
+
ncol = sb.rex.mymesh.mesh["ncol"]
|
|
29
|
+
prcp = np.random.randint(-100, 100, size=(nrow, ncol, 365 * 24))
|
|
30
|
+
prcp = np.where(prcp < 0, 0.0, prcp)
|
|
31
|
+
###########################################################
|
|
32
|
+
|
|
33
|
+
sb.rex.atmos_data_connector(input_prcp=prcp, input_dt=3600.0)
|
|
34
|
+
sb.rex.model()
|
|
35
|
+
|
|
36
|
+
sb.rex.mysmashmodel.atmos_data.pet = 0.0
|
|
37
|
+
sb.rex.forward_run(return_options={"q_domain": True}, invert_states=True)
|
|
38
|
+
|
|
39
|
+
##########################################################
|
|
40
|
+
# Artificial observed discharge
|
|
41
|
+
rand = np.random.randint(-20, 20, sb.rex.mysmashmodel.response_data.q.shape) / 100.0
|
|
42
|
+
qsim = sb.rex.mysmashmodel.response.q[:]
|
|
43
|
+
sb.rex.mysmashmodel.response_data.q = qsim + qsim * rand
|
|
44
|
+
##########################################################
|
|
45
|
+
|
|
46
|
+
sb.rex.mystats.fmisfit_stats()
|
|
47
|
+
sb.rex.mystats.fquantile_stats(
|
|
48
|
+
chunk_size=30,
|
|
49
|
+
estimate_method="MLE",
|
|
50
|
+
ncpu=6,
|
|
51
|
+
fit="gumbel",
|
|
52
|
+
compute_uncertainties=False,
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
sb.rex.myplot.multiplot_misfit()
|
|
56
|
+
sb.rex.myplot.multiplot_spatial_quantile()
|
|
57
|
+
sb.rex.myplot.plot_outlets_quantile()
|
|
58
|
+
sb.rex.myplot.plot_hydrograph()
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# Python tutorials
|
|
2
|
+
|
|
3
|
+
This section contains some Python tutorials to achieve common task with SmashBox.
|
|
4
|
+
|
|
5
|
+
Performing a REX
|
|
6
|
+
----------------
|
|
7
|
+
|
|
8
|
+
First of all, load your Python environment where SmashBox and Smash are installed (change the path according your installation).
|
|
9
|
+
|
|
10
|
+
```shell
|
|
11
|
+
source python_venv/smashbox/bin/activate
|
|
12
|
+
```
|
|
13
|
+
Then open a Python console and load the package EsaySmash
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
import smashbox
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Assume you need to perform a REX on a defined area. This area is defined by a bounding box
|
|
20
|
+
|
|
21
|
+
```python
|
|
22
|
+
bbox={'left': 875000.0,
|
|
23
|
+
'bottom': 6228000.0,
|
|
24
|
+
'right': 1001000.0,
|
|
25
|
+
'top': 6320000.0}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Configure the smashbox module: Set the bounding box, select the outlet database and configure the database fields.
|
|
29
|
+
|
|
30
|
+
```python
|
|
31
|
+
es = smashbox.SmashBox()
|
|
32
|
+
es.myparam.set_param("bbox", bbox)
|
|
33
|
+
```
|
|
34
|
+
We are ready to create a container for your Smash simulation:
|
|
35
|
+
|
|
36
|
+
```python
|
|
37
|
+
es.newmodel("rex")
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Then we need to adjust the setup. By default the setup `setup_rhax_gr4_dt3600` is automatically loaded. If needed, you can select an other one (see function `es.rex.mysetup.list_available_setup()`), and change some properties of the setup. On the rhax server, only the date must be configured. Path to data are already set, we use comephore 60M for the precipitation, the last extraction of the discharges at every sites (2025) and the daily potential evapotranspiration.
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
es.rex.mysetup.update_setup(
|
|
44
|
+
{
|
|
45
|
+
"start_time": "2014-01-01 00:00",
|
|
46
|
+
"end_time": "2014-02-01 00:00",
|
|
47
|
+
}
|
|
48
|
+
)
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Then we can build the mesh and add outlets with surface greater than 20 km², and automatically exclude outlets if the modeled surface error :math:`(Ssim - Sobs)/Sobs>0.2` (`area_error_th` option).
|
|
52
|
+
|
|
53
|
+
```python
|
|
54
|
+
es.rex.generate_mesh(query="(SURF>20) & (INFLUENCE=='Influence nulle ou faible')", area_error_th=0.2)
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Few plots can help to validate our mesh with functions `smashbox.plot.myplot.myplot.plot_mesh` and `smashbox.plot.myplot.myplot.plot_catchment_surface_error` and `smashbox.plot.myplot.plot_catchment_surface_consistency`:
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
|
|
61
|
+
es.rex.myplot.plot_mesh(fig_settings={"figname": "output/mesh.png"})
|
|
62
|
+
es.rex.myplot.plot_catchment_surface_error(
|
|
63
|
+
fig_settings={"figname": "output/mesh_surface_error.png"}
|
|
64
|
+
)
|
|
65
|
+
es.rex.myplot.plot_catchment_surface_consistency(
|
|
66
|
+
fig_settings={"figname": "output/mesh_surface_consistency.png"}
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
remark: if figname is not defined, the plot will be sent to the matplotlib interactive UI or to your web browser as html (if you run the code from R). However, this feature is not working for remote server (perhaps try to ssh -X firefox).
|
|
71
|
+
|
|
72
|
+
Let's now perform a forward run (the model will be build automatically), perform a warmup period of 100 days and return the discharge on the grid.
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
es.rex.forward_run(return_options={"q_domain": True}, warmup=100)
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Statistics can be computed. `smashbox.stats.mystats.mystats.foutlets_stats` method compute basic discharges statistics at every outlets; `smashbox.stats.mystats.mystats.fspatial_stats` method compute basic spatial discharges statistics at every pixel; `smashbox.stats.mystats.mystats.fmisfit_stats` compute many misfits criteria at outlets.
|
|
79
|
+
|
|
80
|
+
```python
|
|
81
|
+
es.rex.mystats.foutlets_stats()
|
|
82
|
+
es.rex.mystats.fspatial_stats()
|
|
83
|
+
es.rex.mystats.fmisfit_stats()
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Several figures can be plotted:
|
|
88
|
+
|
|
89
|
+
First, we can plot the parameters First, we can plot the parameters with functions `smashbox.plot.myplot.myplot.plot_parameters` and `smashbox.plot.myplot.myplot.multiplot_parameters`:
|
|
90
|
+
:
|
|
91
|
+
```python
|
|
92
|
+
es.rex.myplot.multiplot_parameters(
|
|
93
|
+
fig_settings={"figname": "output/muliplot_parameters.png"}
|
|
94
|
+
)
|
|
95
|
+
es.rex.myplot.plot_parameters(fig_settings={"figname": "output/cp_parameters.png"})
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Then we can plot basic statistics with functions `smashbox.plot.myplot.myplot.plot_outlet_stats` and `smashbox.plot.myplot.myplot.plot_spatial_stats` :
|
|
99
|
+
```Python
|
|
100
|
+
es.rex.myplot.plot_outlet_stats(
|
|
101
|
+
fig_settings={"figname": "output/outlets_max_discharges.png"}
|
|
102
|
+
)
|
|
103
|
+
es.rex.myplot.plot_spatial_stats(
|
|
104
|
+
fig_settings={"figname": "output/spatial_max_discharges.png"}
|
|
105
|
+
)
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Let's plot an hydrogram (by default the first outlet is used) with functions `smashbox.plot.myplot.myplot.plot_hydrograph`:
|
|
109
|
+
```Python
|
|
110
|
+
es.rex.myplot.plot_hydrograph(fig_settings={"figname": "output/discharges_hydrogram.png"})
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Finally, plot the misfit criteria with functions `smashbox.plot.myplot.myplot.multiplot_misfit` and `smashbox.plot.myplot.myplot.plot_misfit` and `smashbox.plot.myplot.plot_misfit_map` :
|
|
114
|
+
```Python
|
|
115
|
+
|
|
116
|
+
es.rex.myplot.multiplot_misfit(
|
|
117
|
+
fig_settings={"figname": "output/multiplot_nse_misfit.png", "xsize": 15, "ysize": 15}
|
|
118
|
+
)
|
|
119
|
+
es.rex.myplot.plot_misfit(
|
|
120
|
+
misfit="nnse", fig_settings={"figname": "output/nnse_misfit.png"}
|
|
121
|
+
)
|
|
122
|
+
es.rex.myplot.plot_misfit_map(fig_settings={"figname": "output/map_nse_misfit.png"})
|
|
123
|
+
|
|
124
|
+
```
|