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.
Files changed (73) hide show
  1. smashbox/.spyproject/config/backups/codestyle.ini.bak +8 -0
  2. smashbox/.spyproject/config/backups/encoding.ini.bak +6 -0
  3. smashbox/.spyproject/config/backups/vcs.ini.bak +7 -0
  4. smashbox/.spyproject/config/backups/workspace.ini.bak +12 -0
  5. smashbox/.spyproject/config/codestyle.ini +8 -0
  6. smashbox/.spyproject/config/defaults/defaults-codestyle-0.2.0.ini +5 -0
  7. smashbox/.spyproject/config/defaults/defaults-encoding-0.2.0.ini +3 -0
  8. smashbox/.spyproject/config/defaults/defaults-vcs-0.2.0.ini +4 -0
  9. smashbox/.spyproject/config/defaults/defaults-workspace-0.2.0.ini +6 -0
  10. smashbox/.spyproject/config/encoding.ini +6 -0
  11. smashbox/.spyproject/config/vcs.ini +7 -0
  12. smashbox/.spyproject/config/workspace.ini +12 -0
  13. smashbox/__init__.py +8 -0
  14. smashbox/asset/flwdir/flowdir_fr_1000m.tif +0 -0
  15. smashbox/asset/outlets/.Rhistory +0 -0
  16. smashbox/asset/outlets/db_bnbv_fr.csv +142704 -0
  17. smashbox/asset/outlets/db_bnbv_light.csv +42084 -0
  18. smashbox/asset/outlets/db_sites.csv +8700 -0
  19. smashbox/asset/outlets/db_stations.csv +2916 -0
  20. smashbox/asset/outlets/db_stations_example.csv +19 -0
  21. smashbox/asset/outlets/edit_database.py +185 -0
  22. smashbox/asset/outlets/readme.txt +5 -0
  23. smashbox/asset/params/ci.tif +0 -0
  24. smashbox/asset/params/cp.tif +0 -0
  25. smashbox/asset/params/ct.tif +0 -0
  26. smashbox/asset/params/kexc.tif +0 -0
  27. smashbox/asset/params/kmlt.tif +0 -0
  28. smashbox/asset/params/llr.tif +0 -0
  29. smashbox/asset/setup/setup_rhax_gr4_dt3600.yaml +15 -0
  30. smashbox/asset/setup/setup_rhax_gr4_dt900.yaml +15 -0
  31. smashbox/asset/setup/setup_rhax_gr5_dt3600.yaml +15 -0
  32. smashbox/asset/setup/setup_rhax_gr5_dt900.yaml +15 -0
  33. smashbox/init/README.md +3 -0
  34. smashbox/init/__init__.py +3 -0
  35. smashbox/init/multimodel_statistics.py +405 -0
  36. smashbox/init/param.py +799 -0
  37. smashbox/init/smashbox.py +186 -0
  38. smashbox/model/__init__.py +1 -0
  39. smashbox/model/atmos_data_connector.py +518 -0
  40. smashbox/model/mesh.py +185 -0
  41. smashbox/model/model.py +829 -0
  42. smashbox/model/setup.py +109 -0
  43. smashbox/plot/__init__.py +1 -0
  44. smashbox/plot/myplot.py +1133 -0
  45. smashbox/plot/plot.py +1662 -0
  46. smashbox/read_inputdata/__init__.py +1 -0
  47. smashbox/read_inputdata/read_data.py +1229 -0
  48. smashbox/read_inputdata/smashmodel.py +395 -0
  49. smashbox/stats/__init__.py +1 -0
  50. smashbox/stats/mystats.py +1632 -0
  51. smashbox/stats/stats.py +2022 -0
  52. smashbox/test.py +532 -0
  53. smashbox/test_average_stats.py +122 -0
  54. smashbox/test_mesh.r +8 -0
  55. smashbox/test_mesh_from_graffas.py +69 -0
  56. smashbox/tools/__init__.py +1 -0
  57. smashbox/tools/geo_toolbox.py +1028 -0
  58. smashbox/tools/tools.py +461 -0
  59. smashbox/tutorial_R.r +182 -0
  60. smashbox/tutorial_R_graffas.r +88 -0
  61. smashbox/tutorial_R_graffas_local.r +33 -0
  62. smashbox/tutorial_python.py +102 -0
  63. smashbox/tutorial_readme.py +261 -0
  64. smashbox/tutorial_report.py +58 -0
  65. smashbox/tutorials/Python_tutorial.md +124 -0
  66. smashbox/tutorials/R_Graffas_tutorial.md +153 -0
  67. smashbox/tutorials/R_tutorial.md +121 -0
  68. smashbox/tutorials/__init__.py +6 -0
  69. smashbox/tutorials/generate_doc.md +7 -0
  70. smashbox-1.0.dist-info/METADATA +998 -0
  71. smashbox-1.0.dist-info/RECORD +73 -0
  72. smashbox-1.0.dist-info/WHEEL +5 -0
  73. 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
+ ```