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,998 @@
1
+ Metadata-Version: 2.4
2
+ Name: smashbox
3
+ Version: 1.0
4
+ Summary: A python library developed by Hydris-hydrologie (https://www.hydris-hydrologie.fr/) to provide an technical environment for performing hydrological simulation with Smash. This library is preloaded with data (France only), comes with preconfigured setup, own some extra features such as the in-memory atmospheric data connector, has statistical and plot capabilities. Plot and stats functions can be used as a separate module with your own Smash model object.
5
+ Project-URL: Homepage, https://codeberg.org/maximejay/easysmash
6
+ Project-URL: Issues, https://codeberg.org/maximejay/easysmash/issues
7
+ Author-email: Maxime Jay-Allemand <maxime.jay.allemand@hydris-hydrologie.fr>
8
+ License-File: LICENSE
9
+ Keywords: hydro-smash,plot,smash,statistics
10
+ Requires-Dist: hydro-smash
11
+ Requires-Dist: matplotlib
12
+ Requires-Dist: mpld3
13
+ Requires-Dist: pdoc
14
+ Requires-Dist: pyhdf5-handler
15
+ Requires-Dist: rich
16
+ Description-Content-Type: text/markdown
17
+
18
+ # Presentation
19
+
20
+ SmashBox is a python library developed by Inrae and Hydris-hydrologie (https://recover.paca.hub.inrae.fr/qui-sommes-nous/nos-equipes/rhax and https://www.hydris-hydrologie.fr/) to provide a Python environment for performing hydrological simulation with Smash. This library is preloaded with data (France only), comes with preconfigured setup, own some extra features such as the in-memory atmospheric data connector, has statistical and plot capabilities. Most of the features present in this module can be used with a separate Smash model object.
21
+
22
+ This module can also be used from R with the Reticulate package.
23
+
24
+ # Installation
25
+
26
+ Warning: SmashBox use the upcoming version of SMASH 1.2. Currently, to use SMashBox, you need to install SMASH manually in your Python environment from the "main" github branch (the most up-to-date version of SMASH).
27
+
28
+ To install SmashBox, you should use a python virtual environment.
29
+
30
+ ```shell
31
+ python3 -m venv smashbox_env
32
+ source smashbox_env/bin/activate
33
+ pip install smashbox
34
+ ```
35
+ Ensure you Python environment is loaded and load SmashBox in Python as follow:
36
+
37
+ ```python
38
+ import smashbox
39
+ ```
40
+
41
+ with R language you must load smashbox with the Reticulate package as follow:
42
+
43
+ ```R
44
+ library(reticulate)
45
+ use_virtualenv("smashbox_env")
46
+ smashbox <- import("smashbox")
47
+ ```
48
+ # API documentation
49
+
50
+ The API documentation is hosted at https://maximejay.codeberg.page/smashbox.html. This documentation is auto-generated using pdoc (https://pdoc.dev/docs/pdoc.html).
51
+
52
+ ```bash
53
+ pdoc smashbox/ --math -o ./html
54
+ ```
55
+
56
+ To generate the doc for several modules, use for instance:
57
+
58
+ ```bash
59
+ pdoc ./pyhdf5_handler/pyhdf5_handler/ smashbox/smashbox/ --math -o ./html
60
+ ```
61
+
62
+ To publish the doc on codeberg pages, you must flatten the directory. All statics pages must be at the root directory. A script can be used for this:
63
+ ```bash
64
+ #modify the path to the documentation folder inside the script !
65
+ bash flatten_doc.sh
66
+ ```
67
+ The script flatten_doc.sh can be found at https://codeberg.org/maximejay/pages.
68
+
69
+ # Getting started
70
+
71
+ Python and R tutorials:
72
+ ----------
73
+
74
+ Before anything, few Python and R tutorials are available in the documentation section Submodules/tutorials.
75
+
76
+ Initialisation:
77
+ ---------------
78
+
79
+ Here we create an smashbox object `es`. This object `es` is a container for performing hydrological simulation with smash.
80
+
81
+ ```python
82
+ import smashbox
83
+ es = smashbox.SmashBox()
84
+ ```
85
+
86
+ `es` has 3 methods `smashbox.init.smashbox.SmashBox.help`, `smashbox.init.smashbox.SmashBox.newmodel`, `smashbox.init.smashbox.SmashBox.delmodel` and one attribute `myparam` which refer to the class `smashbox.init.param.param`.
87
+
88
+ The smashbox parameters:
89
+ -------------------------
90
+
91
+ The class `smashbox.init.param.param` own the main top-level parameters of SmashBox. These parameters controls the data used to build an hydrological model and behaviour of SmashBox. These parameters can be managed from the attribute `myparam` of the container `es`. The attribute `myparam` refer to the class `eaysysmash.init.param.param` which contains different methods to manipulate the attribute of the sub-class `eaysysmash.init.param.smashboxparam`.
92
+
93
+ ```python
94
+ sb.myparam.list_param()
95
+ asset_dir=/home/maxime/.smashbox/asset
96
+ outlets_database=/home/maxime/DEV/smashbox/smashbox/asset/outlets/db_stations_example.csv
97
+ setup_file=/home/maxime/.smashbox/asset/setup/setup_rhax_gr4_dt3600.yaml
98
+ flowdir=/home/maxime/.smashbox/asset/flwdir/flowdir_fr_1000m.tif
99
+ bbox=None
100
+ epsg=2154
101
+ outletsID=[]
102
+ outlets_shapefile=None
103
+ smash_parameters=/home/maxime/DEV/smashbox/smashbox/asset/params
104
+ smash_parameters_dt=None
105
+ outlets_database_fields={'coord_x': 'X_L93', 'coord_y': 'Y_L93', 'area': 'SURF', 'id': 'CODE'}
106
+ enhanced_smash_input_data=False
107
+ ```
108
+
109
+ The different attributes listed above are also accessible from the attribute `sb.myparam.param` which own attributes of the class `smashbox.init.param.smashboxparam`. Every parameters of this class are documented here:`smashbox.init.param.smashboxparam`.
110
+
111
+ The assets directory `asset_dir` contains the data provided by SmashBox. These data are copied in your personal directory when you load the module for the first time. SmashBox comes with few data: four outlets database for France, the flow directions at a resolution of 1km² and few preconfigured Smash model setup.
112
+ Notice that data in your personal asset directory is the default data used by SmashBox. So, you can edit these data and copy other personal data in this directory to quickly retrieve it each time you use SmashBox.
113
+
114
+ Every parameters can be modified using the setters or by changing directly the value of the attribute. Both following commands are equivalent:
115
+
116
+ ```python
117
+ sb.myparam.set_param(
118
+ "outlets_database",
119
+ "/home/maxime/DEV/smashbox/smashbox/asset/outlets/db_stations_example.csv",
120
+ )
121
+
122
+ sb.myparam.param.outlets_database = "/home/maxime/DEV/smashbox/smashbox/asset/outlets/db_stations_example.csv"
123
+ ```
124
+
125
+ Building an new model environment for performing hydrological simulations:
126
+ --------------------------------------------------------------------------
127
+
128
+ A new SmashBox model environnement can be created using the function `smashbox.init.smashbox.SmashBox.newmodel`. In this example we call our environment "graffas_zone":
129
+
130
+ ```python
131
+ sb.newmodel("graffas_zone")
132
+ ```
133
+
134
+ This environment is created at the top level of the object `es` and is accessible via the attribute `graffas_zone`. This environment contains functions and class-attribute to setup, build and run a Smash model, and then make plots and compute statistics. Notice that the top-level parameters `sb.myparam` are fixed and copied into the environment under the attribute `sb.graffas_zone._myparam` (hidden) and should not be modified.
135
+
136
+
137
+ Generate the Smash mesh:
138
+ ------------------------
139
+
140
+ The Smash mesh is generated using the method `smashbox.mesh.mesh.generate_mesh`. But one can use the wrapper `smashbox.model.model.generate_mesh` to build the mesh directly from the model container `graffas_zone`:
141
+
142
+ ```python
143
+ sb.graffas_zone.generate_mesh()
144
+ ```
145
+ The function `generate_mesh` has the option `query` to filter the outlet in the database before including them inside the mesh. See the documentation `smashbox.model.model.model.generate_mesh`.
146
+
147
+ ```python
148
+ sb.graffas_zone.generate_mesh(query="('SURF' > 20 and 'SURF' < 200)") #example with filtering surface outlets
149
+ ```
150
+
151
+ The Smash setup:
152
+ ----------------
153
+
154
+ The Smash model setup is stored in `mysetup.setup` which is an attribute of the class `smashbox.model.setup.setup`. From this class you can change, load, write, set, get, list all properties of the Smash setup. For instance, one can list available setup, select the one we prefer and adjust some values of the setup using the function `update_setup`:
155
+
156
+ ```pyhton
157
+ sb.graffas_zone.mysetup.list_available_setup()
158
+ ├── setup_rhax_gr4_dt3600.yaml
159
+ ├── setup_rhax_gr4_dt900.yaml
160
+ ├── setup_rhax_gr5_dt3600.yaml
161
+ └── setup_rhax_gr5_dt900.yaml
162
+
163
+ sb.graffas_zone.mysetup.load_setup("setup_rhax_gr4_dt3600.yaml")
164
+
165
+ sb.graffas_zone.mysetup.update_setup(
166
+ {
167
+ "pet_directory": "/nas/RHAX/DONNEES/ETP/GRILLES/ETP-SFR-FRA-INTERA_L93/",
168
+ "prcp_directory": "/nas/RHAX/DONNEES/PLUIE/SPATIAL/COMEP/L93_1km/60M/",
169
+ "qobs_directory": "/nas/RHAX/DONNEES/DEBITS/Extraction_sites_SCHAPI_20250226/QTVAR_to_QM/QM_60M",
170
+ }
171
+ )
172
+ ```
173
+
174
+ Simulation with Smash :
175
+ -----------------------
176
+
177
+ The creation of the Smash model object is analogous with Smash. When the Smash setup and the mesh are ready, one just need to call the function `smashbox.model.model.model.model`:
178
+
179
+ ```python
180
+ sb.graffas_zone.model()
181
+ ```
182
+
183
+ Notice: if `sb.myparam.param.enhanced_smash_input_data=True`, enhanced mode is active. That means new beta functions to generate the model are used. These functions essentially extent the capabilities to handle atmospherical data (continuous pet, inter-annual pet timezone, date pattern specification, ...). Refer to the documentation of `smashbox.init.param.param`and at section `smashbox.html#extended-feature-for-reading-atmospheric-data`.
184
+
185
+ The Smash model object is created and stored behind the attribute `sb.graffas_zone.mysmashmodel`.
186
+
187
+ Before going further, it is recommended to warm the Smash model. The function `smashbox.model.model.model.model_warmup` has been made for this. In the following example, a warmup is performed during 365 days before the start-time defined in the Smash model setup. These model states will be used for the forward run.
188
+
189
+ ```python
190
+ sb.graffas_zone.model_warmup(warmup=365)
191
+ ```
192
+
193
+ Then it is easy to invoke a forward run of the model:
194
+
195
+ ```python
196
+ sb.graffas_zone.forward_run()
197
+ ```
198
+
199
+ Notice that if the model does not exist, `forward_run` will automatically create it. Moreover, five options can be passed to the function`smashbox.model.model.model.forward_run`:
200
+ * invert_state: bool, default is False. If True, the final model states is used to start the simulation.
201
+ * warmup: int | None, default is None. Number of days of model warmup before the `start_time`.
202
+ * cost_options: Dictionary containing computation cost options for simulated and observed responses (https://smash.recover.inrae.fr/api_reference/principal_methods/smash/smash.Model.forward_run.html)
203
+ * common_options: Dictionary containing common options with two elements, ncpu and verbose (https://smash.recover.inrae.fr/api_reference/principal_methods/smash/smash.Model.forward_run.html)
204
+ * return_options: A dictionary with return options as explained in the Smash documentation (https://smash.recover.inrae.fr/api_reference/principal_methods/smash/smash.Model.forward_run.html). In that case, the returned results are stored behind the attribute `sb.graffas_zone.extra_smash_results`.
205
+
206
+
207
+ # In memory atmospheric data connector
208
+
209
+ Instead of reading atmospheric precipitation and evapotranspiration on the disk (Smash handle geotiff file), SmashBox provide a simple way to transfer a matrix with three dimension (X direction, Y direction and time) to the Smash model directly.
210
+
211
+ Let's create an numpy.array and generates periodic increasing and arbitrary rainfall pattern during `(21*18)` time-steps:
212
+
213
+ ```python
214
+ nrow = sb.graffas_zone.mymesh.mesh["nrow"]
215
+ ncol = sb.graffas_zone.mymesh.mesh["ncol"]
216
+ chunk_size = 18
217
+ nb_chunk = 21
218
+ graffas_prcp = np.zeros(shape=(nrow, ncol, nb_chunk * chunk_size))
219
+ fctr = 100
220
+ for i in range(nb_chunk):
221
+ graffas_prcp[:, :, i * chunk_size : (i + 1) * chunk_size] = (
222
+ fctr
223
+ * np.arange(i * chunk_size, (i + 1) * chunk_size)
224
+ / (chunk_size * nb_chunk)
225
+ * np.cos(np.arange(0, chunk_size * 10, 10) * np.pi / 180)
226
+ )
227
+ graffas_prcp = np.where(graffas_prcp < 0, 0.0, graffas_prcp)
228
+ ```
229
+
230
+ Then one can connect this matrix to Smash using the atmos_data_connector `smashbox.model.model.model.atmos_data_connector`:
231
+
232
+ ```python
233
+ sb.graffas_zone.atmos_data_connector(input_prcp=graffas_prcp, input_dt=3600.)
234
+ ```
235
+ If the domain and the resolution of the input matrix differ from the domain and the resolution of the Smash model then the input matrix is cropped and resampled. Three method can be used:
236
+ * "rasterio1" : appear to be the slowest method ,`smashbox.model.atmos_data_connector.read_input_data`
237
+ * "rasterio2" : more efficient, `smashbox.model.atmos_data_connector.read_input_data2`
238
+ * "home_made_with_scipy_zoom" : default method, efficient, with resampling before cropping (minimal shifting in x and y direction), `smashbox.model.atmos_data_connector.read_input_data3`.
239
+
240
+ The bounding box and the epsg code of the domain of the input matrix should be also passed to the function to ensure best results. If the bounding box is not provided, the bounding box of the Smash mesh is used to position the input matrix.
241
+ If the input matrix has exactly the same 2D shape of the Smash mesh, the resampling and the crop operation are skipped for faster processing.
242
+
243
+ If the time-step of the precipitation differ from the model time-step, it is recommended to provide the time-step of the input precipitation. The matrix will downscaled or upscaled automatically. Use the keyword `input_dt=3600` for the atmos_data_connector.
244
+
245
+ Then we can call the forward run as follow:
246
+
247
+ ```python
248
+ sb.graffas_zone.forward_run(return_options={"q_domain": True})
249
+ ```
250
+
251
+ Also, if several consecutive simulation are planned with different but successive atmospheric precipitation, one ca invoke forward_run as follow:
252
+
253
+ ```python
254
+ chunk_size=10
255
+ nb_chunk=int(graffas_prcp.shape[2]/chunk_size)
256
+ qdomain={}
257
+ for i in range(nb_chunck):
258
+ sb.graffas_zone.atmos_data_connector(input_prcp=graffas_prcp[:,:,i*chunk_size:(i+1)*chunk_size])
259
+ sb.graffas_zone.forward_run(invert_states=True, return_options={"q_domain": True})
260
+ #do some staff here...
261
+ ```
262
+ In that case, the final states is used as initial states (no need to warm the model at each simulation) and the discharges for each pixel of the domain is stored in `sb.graffas_zone.extra_smash_results`. Analysis such as quantile computation can be performed for each chunk.
263
+
264
+ For deeper knowledge on this subject follow the R tutorial `smashbox.tutorials.R_Graffas_tutorial`.
265
+
266
+ # Load, calibrate and export Smash parameters:
267
+
268
+ ## Default parameters
269
+
270
+ Default parameters for the asset directory are loaded. These parameters comes from the French regionalisation 2025 (J. Demargne). These parameters has been calibrated for a times-step of 900 seconds. Thus we must use a Smash model with time-step 900s. Otherwise, the parameters won't be valid.
271
+
272
+ ## Converting the parameters for different simulation time-step
273
+
274
+ According to the phd of A. Ficchi 2017, GR4 prameters can be théorically converted for different time-step. SmashBox provide a function to convert the parameter to the model time-step. Assume our model run at an hourly time-step (we use dt=3600 in the Smash setup), the default loaded parameters will be automatically adjusted using this function. We recommend to do that just after the model creation.
275
+
276
+ ```python
277
+ sb.graffas_zone.transform_parameters(original_dt=900)
278
+ ```
279
+ ## Optimizing the parameters
280
+
281
+ If the above solution is not satisfying, it is still possible to calibrate the Smash parameters using Smash. Moreover easySmash provide a wrapped function of smash.optimze in order to quickly optimize the parameters in a chosen period and use it for an other period. Just run:
282
+
283
+ ```python
284
+ sb.graffas_zone.optimize_parameters(start_time="2010-01-01 00:00",end_time="2014-01-01 00:00", cost_options={end_warmup:"2011-01-01 00:00"})
285
+ ```
286
+ Any arguments of smash.optimize can be passed to this function.
287
+
288
+ ## Export and import parameters
289
+
290
+ SmashBox and Smash provide functions manually to export and import parameters:
291
+
292
+ ```python
293
+ sb.graffas_zone.export_parameters(path="path/to/my/param")
294
+ sb.graffas_zone.import_parameters(path="path/to/my/param")
295
+
296
+ ```
297
+
298
+ # Extended feature for reading atmospheric data:
299
+
300
+ SmashBox has an enhanced version of the smash.model() method. These functions essentially extent the capabilities to handle atmospherics data (continuous pet, inter-annual pet timezone, date pattern specification, ...) and bring more options and flexibility. Here the list of the new features:
301
+ * read atmospheric data from different source which can substitute to the first one if data are unavailable.
302
+ * Merge all reading function in one.
303
+ * Configure the pattern of the date to search in the filename. Use common date formats. Handle the occurrence number (starting from 0) with %n at the end of the date pattern. ex: %Y%m%d%H%1.
304
+ * Improve logs: new log clearly warn user about which files have been read and which files are missing.
305
+ * Fix a mistake during the reading of the evapotranspration. In SMASH the evapotranspiration from the previous day is read instead of the current one.
306
+ * Read several data source by priority: each kind of data may have different source. If one is missing, the model will read the second one, etc...
307
+ * Partially handle the reading of the continuous evapotranspiration in an operational context. To do that, a sim-link of the etp data (delayed by 1 day) is created named with the date of the current day.
308
+ * Handle time zone to shift the desegregation curve of the PET during the day.
309
+ * Improve the speed of the reading. Technically, an index of the dates and the corresponding data files is created. To efficiency run through the long list of data files and performs a regex search to match a date, a simple search algorithm is build on top of the main loop to avoid performing a regex on thousand files. This improvement is noticeable for model running on few time-step. It is particularly important when running smash in an operational context.
310
+
311
+ The setup file must be designed as follow:
312
+
313
+ ```yaml
314
+ adjust_interception: false
315
+ compute_mean_atmos: true
316
+ continuous_pet: #define if the pet data are contiuous or not
317
+ 1: true
318
+ 2: false
319
+ daily_interannual_pet: true #always use that if some pet data are not continuous
320
+ dt: 900
321
+ hydrological_module: grc
322
+ pet_date_pattern: '%Y%m%d' # the date pattern to search in the pet filename (for continuous pet)
323
+ pet_directories: # sevreal directories can be defined. The identifier correspond to the priority of the data source: 1 = higher priority
324
+ 1 : "/home/maxime/DATA/REUNION/ETPJ_continue"
325
+ 2 : "/home/maxime/DATA/REUNION/ETPJ_interannuelle_250_lnZ"
326
+ prcp_access: '%Y/%m/%d'
327
+ prcp_conversion_factor: 1.0
328
+ prcp_date_pattern: '%Y%m%d%H%M' # the date pattern to search in the prcp filename. an identifier %N can be added to target the right date on the filename, ex '%Y%m%d%H%M%2'
329
+ prcp_directories: # sevreral directories can be defined. The identifier correspond to the priority of the data source: 1 = higher priority
330
+ 1 : '/home/maxime/DATA/REUNION/PLUIE_REUNION/tests_tr/ANTILOPE_J1'
331
+ 2 : '/home/maxime/DATA/REUNION/PLUIE_REUNION/tests_tr/ANTILOPE_TR'
332
+ 3 : '/home/maxime/DATA/REUNION/PLUIE_REUNION/tests_tr/GRID_LESOL_500m'
333
+ qobs_directory: ''
334
+ read_pet: true
335
+ read_prcp: true
336
+ read_qobs: false
337
+ routing_module: lr
338
+ timezone: "Indian/Reunion" #define the timezone to adjust the hourly pet computation.
339
+ ```
340
+
341
+ In order to activate this feature, you need to properly initialise the smashbox top-level parameters class `smashbox.init.param.smashboxparam` before to create the container for your simulation:
342
+
343
+ ```python
344
+ sb.myparam.param.enhanced_smash_input_data=True
345
+ ```
346
+ Then everything will work as explained above. Notice that the enhanced read input data features are fully compatible with the official Smash setup.
347
+
348
+ # Statistical capabilities
349
+
350
+ The statistical features are handled by the submodule `smashbox.stats`. `smashbox.stats.mystats.mystats` features some methods ready to be applied on any smashbox object. `smashbox.stats.stats` owns generic functions that can be used outside the SmashBox object.
351
+
352
+ Misfit criterion at the outlets
353
+ ------------------------------
354
+
355
+ If discharges observations are available, misfit criterion can be computed at each gauge. The available misfit criterion are:
356
+ * nse : Nash Sutcliff criteria $nse= 1 - \frac{\sum_{i=1}^{i=N} (Q^i_{sim}-Q^i_{obs})^2 }{ \sum_{i=1}^{i=N} (Q^i_{obs}-\overline{Q_{obs}})^2 }$
357
+ * nnse : Normalized Nash Sutcliffe criteria (Nossent and Bauwens, 2012) $nnse = \frac{1}{2-NSE} \ \in[0:1]$
358
+ * mse : The Mean Squared Error, $mse=\frac{1}{n}\sum^n_{k=1}(f_k - o_k)^2$
359
+ * rmse : Root Mean Square Error, $rmse=\sqrt{\frac{1}{n}\sum^n_{k=1}(f_k - o_k)^2}$
360
+ * nrmse : Normalized Root Mean Square Error, $nrmse=\frac{rmse}{\overline{Q_{obs}}}$
361
+ * se: Square Error, $se=\sum{(Q_{obs}-Q_{sim})^2}$
362
+ * mae: The Mean Absolute Error: $mae=\frac{1}{N}\sum_{i=0}^{N}{abs(Qsim^i-Qobs^i)}$
363
+ * mape: The Mean Absolute Percentage Error : $mape=\frac{1}{N}\sum_{i=0}{N}{abs(\frac{Qsim^i-Qobs^i}{Qobs^i})}$
364
+ * lgrm: The Logarithmic Error : $lgrm=\sum$_{i=0}{N}Qobs^i \times ln(\frac{Qsim^i}{Qobs^i})^2$
365
+ * kge: The Kling Gupta Efficiency criteria.
366
+
367
+ To compute all these misfits, just run `sb.graffas_zone.mystats.fmisfit_stats()` function, and all results will be stored in `sb.graffas_zone.mystats.misfit_stats`:
368
+
369
+ ```python
370
+ sb.graffas_zone.mystats.fmisfit_stats()
371
+ sb.graffas_zone.mystats.misfit_stats.results.nse
372
+ ```
373
+
374
+ Results are stored in attribute `sb.graffas_zone.mystats.misfit_stats.results`. Criterion can be computed separately using the misfit functions in `sb.graffas_zone.mystats.misfit_stats`: 2 separates functions can be used for each statistic can be used. These functions are all named by the statistics name. But some have the prefix `sm_` which stand for `smash_`. For those functions the statistics are computed using the smash library. We advice to use function prefixed with `sm_` because the Smash library is more robust and has been fully tested.
375
+
376
+ Outlet discharges statistics
377
+ ----------------------------
378
+
379
+ Basic statistics can be computed on the observed and simulated discharge at every outlets. These statistic are the mean, the median, the 20% and 80% percentile of the discharge, the maximum and the minimum. The function `sb.graffas_zone.mystats.foutlets_stats()` compute all of these statistics and the results are stored in `sb.graffas_zone.mystats.outlets_stats`:
380
+
381
+ ```python
382
+ sb.graffas_zone.mystats.foutlets_stats()
383
+ sb.graffas_zone.mystats.outlets_stats.results_sim.maximum
384
+ sb.graffas_zone.mystats.outlets_stats.results_obs.maximum
385
+ ```
386
+
387
+ Spatial discharges statistics
388
+ -----------------------------
389
+
390
+ Basic spatial statistics can be computed on the simulated discharge at every active pixel of the domain. These statistic are the mean, the median, the 20% and 80% percentile of the discharge, the maximum and the minimum. This require to ran the forward model with return option `{q_domain:True}`. The function `sb.graffas_zone.mystats.fspatial_stats()` compute all of these statistics and the results are stored in `sb.graffas_zone.mystats.spatial_stats`:
391
+
392
+ ```python
393
+ sb.graffas_zone.mystats.fspatial_stats()
394
+ sb.graffas_zone.mystats.spatial_stats.results.maximum
395
+ ```
396
+
397
+ Spatial discharges quantile computation
398
+ ---------------------------------------
399
+
400
+ SmashBox has the capabilities to compute the discharges quantile spatially for various return period. The following process is applied:
401
+
402
+ * Perform a forward run with return option `{q_domain:True}` so that the spatial discharges is saved for all time-steps.
403
+ * Resample the spatial discharge over time if needed (depending the duration of the quantile)
404
+ * Compute the annual maxima (annual chunck size) for each active pixel of the domain (notice that the chunck size can be adjusted but default is 365 days)
405
+ * Adjust an extrem law, such as Gumbel or GEV, on the maxima values. This part use scipy algorithm.
406
+ * Compute the quantile for the given return period
407
+
408
+ To perform this computation one use `smashbox.stats.mystats.fstats_quantile` function. In the following example, the length of the chronicle is about 400 hours (16 days) and the chunk_size is set to 4 days (instead of 365 days) to have at least four chunks to compute the quantile (in other word, the return period 'unit' is 4 days). By default the estimated return period T are `[2, 5, 10, 20, 50, 100]` (unit depend on the chunk size), and the quantile duration are `[1, 2, 3, 4, 6, 12, 24, 48, 72]` hours.
409
+
410
+ ```python
411
+ sb.graffas_zone.mystats.fquantile_stats(
412
+ chunk_size=4, estimate_method="MLE", ncpu=6, fit="gumbel"
413
+ )
414
+ ```
415
+
416
+ The results of the quantiles are then stored for each duration behind the attribute `sb.graffas_zone.mystats.quantile_stats`:
417
+
418
+ ```python
419
+ sb.graffas_zone.mystats.quantile_stats.__dict__.keys()
420
+ Out[9]: dict_keys(['spatial_cumulated_maxima', 'spatial_cumulated_maxima_outlets', 'spatial_maxima', 'spatial_maxima_outlets', 'spatial_quantile', 'spatial_quantile_outlets', 'Quantile_1h', 'Quantile_2h', 'Quantile_3h', 'Quantile_4h', 'Quantile_6h', 'Quantile_12h', 'Quantile_24h', 'Quantile_48h', 'Quantile_72h'])
421
+ ```
422
+
423
+ The attributes `spatial_quantile` and `spatial_maxima` store respectively the spatial quantile and the spatial maxima in an 4D arrays (respectively of shape `(nbx, nby, duration, T)` and `(nbx, nby, nb_chunk, duration)`)
424
+
425
+ The attributes `spatial_quantile_outlets` and `spatial_maxima_outlets` store respectively the quantile and the maxima at every outlets in an 3D arrays (respectively of shape `(nb_outlets, duration, T)` and `(nb_outlets, nb_chunk, duration)`)
426
+
427
+ The attributes `spatial_cumulated_maxima` `spatial_cumulated_maxima_outlets` and store the maximum discharges (maxima) respectively spatially and for outlets only, but it accumulated these values after each call of `sb.graffas_zone.mystats.fmaxima_stats`. Shapes are `(nbx, nby, nb_chunk*nb_simulation, duration)` and `(nb_outlets, nb_chunk*nb_simulation, duration)`. `nb_simulation` represent the number of smash run and the number of call of `sb.graffas_zone.mystats.fmaxima_stats`.
428
+
429
+ Remark: despite parallel computing is used (on the pixel), this computation may consume an high quantity of memory and can take a long time. Depending the size of the grid and for how much duration the quantile are computed, the function `sb.graffas_zone.mystats.fstats_quantile2` perform the computation in parallel for each duration. The second method could be more efficient in some case.
430
+
431
+ For extremely long rainfall chronic the forward run can be split to save memory. If our goal is to compute the discharges quantile, it is possible to only compute the maxima after each forward run. These maxima will be automatically stacked (with option `cumulated_maxima=True`) and the Gumbel or GEV adjustment can be achieved for each duration after all:
432
+
433
+ ```python
434
+ from smashbox import stats
435
+ chunk_size=4
436
+ nb_chunk=int(graffas_prcp.shape[2]/chunk_size)
437
+ qdomain={}
438
+ for i in range(nb_chunck):
439
+ sb.graffas_zone.atmos_data_connector(input_prcp=graffas_prcp[:,:,i*chunk_size:(i+1)*chunk_size])
440
+ sb.graffas_zone.forward_run(invert_states=True, return_options={"q_domain": True})
441
+ sb.graffas_zone.mystats.fmaxima_stats(chunk_size=4, cumulated_maxima=True)
442
+
443
+ results={}
444
+ for i, duration in enumerate([1, 2, 3, 4, 6, 12, 24, 48, 72]):
445
+ results["duration"] = stats.fit_quantile(
446
+ maxima=sb.graffas_zone.mystats.quantile_stats.spatial_cumulated_maxima[:, :, :, i],
447
+ t_axis=2,
448
+ return_periods=[2, 5, 10, 20, 50, 100],
449
+ fit="gumbel",
450
+ estimate_method="MLE",
451
+ quantile_duration=duration,
452
+ ncpu=6,
453
+ )
454
+ ```
455
+
456
+ # Multi-model statistics (Beta)
457
+
458
+ Several model containers can be created at the root of the SmashBox object. Each model container owns statistic (quantile, misfit, spatial criteria, ...). SmashBox has a feature to aggregate all model statistics and compute the mean, the median, the variance the min, the max and the distribution. These statistics will be computed for each model where the bounding-box match the one in `sb.myparam` attribute. The class `smashbox.init.multimodel_statistics.compute_multimodel_statistics` is instanced when a model container is created.
459
+
460
+ ```python
461
+ sb.multimodel_statistics.compute_multimodel_statistics().
462
+ ```
463
+
464
+
465
+ # Export results
466
+
467
+ We can save the smashbox container to an HDF5 database:
468
+
469
+ ```python
470
+ sb.graffas_zone.save_model_container(path_to_hdf5="my_smashbox_data.hdf5")
471
+ ```
472
+
473
+ We can also export the data of the smashbox container to a python dictionary if `path_to_hdf5è is left empty:
474
+
475
+ ```python
476
+ dict_sb=sb.graffas_zone.save_model_container()
477
+ ```
478
+ This dictionary will be eventually converted to a R list object and can be saved in a Rdata.
479
+
480
+
481
+ # Plotting capabilities
482
+
483
+ SmashBox has some plotting capabilities. The plot are produced with the Matplotlib library. We use the mpld3 librairy to render the plot in html and visualize it directly in your favorite navigator. Every plot can be configured and saved on the disk as any format that matplotlib support. Plotting features are handled by the submodule `smashbox.plot`.
484
+
485
+ Graphics settings
486
+ -----------------
487
+
488
+ Every plotting functions of SmashBox have options to configure the plot. These options can be passed to any function as a dictionary:
489
+
490
+ * `fig_settings`: figure settings are related to the class `smashbox.plot.plot.fig_properties`. These options configure the figure output. With a dictionary, one can define and change any attribute of the class `smashbox.plot.plot.fig_properties`.
491
+ * `ax_settings`: Ax settings refers to the class `smashbox.plot.plot.ax_properties`. These options are useful to change the appaerance of the graphics (changing the matplotlib ax properties). With a dictionary, one can define and change any attribute of the class `smashbox.plot.plot.ax_properties`.
492
+ * `plot_settings`: plot settings refers to the class `smashbox.plot.plot.plot_properties`. Some function accept `plot_settings` options. `plot_settings` serves to configure the line of the matplotlib plot function (colour, line style, line width).
493
+
494
+ If no output is configured, i.e `fig_settings.figname=None`, the figure will popup to the screen using the matplotlib UI. However, from R language, reticulate is not able to display the figure using matplotlib UI. As workaround, SmashBox use mpld3 to output the figure in html and display it directly in your navigator.
495
+
496
+ Plotting the mesh
497
+ -----------------
498
+
499
+ With the function `smashbox.plot.myplot.myplot.plot_mesh`, SmashBox is able to plot the mesh of the Smash model in order to visualize the hydrographic network, the catchment and the localisation of the different outlets. In the following example, the figure will be saved in the file mesh.png, its size will measure 20*20 inches and the global font will be multiply by 2.
500
+
501
+ ```python
502
+ sb.graffas_zone.myplot.plot_mesh(
503
+ fig_settings={"figname": "mesh.png", "xsize": 20, "ysize": 20, "font_ratio": 2},
504
+ ax_settings={"title_fontsize": 32},
505
+ )
506
+ ```
507
+
508
+ ![image info](./images/mesh.png)
509
+
510
+ Two other function helps to characterize the catchment surface error between the mesh and the real surface. These functions are `smashbox.plot.myplot.myplot.plot_catchment_surface_consistency` and `smashbox.plot.myplot.myplot.plot_catchment_surface_error`.
511
+
512
+ ```python
513
+ sb.graffas_zone.myplot.plot_catchment_surface_consistency(
514
+ fig_settings={"figname": "mesh_surface_consistency.png", "xsize": 20, "ysize": 20, "font_ratio": 2},
515
+ ax_settings={"title_fontsize": 32},
516
+ )
517
+ sb.graffas_zone.myplot.plot_catchment_surface_error(
518
+ fig_settings={"figname": "mesh_surface_error.png", "xsize": 20, "ysize": 20, "font_ratio": 2},
519
+ ax_settings={"title_fontsize": 32},
520
+ )
521
+ ```
522
+ ![image info](./images/mesh_surface_consistency.png)
523
+ ![image info](./images/mesh_surface_error.png)
524
+
525
+ Plotting the parameters
526
+ -----------------------
527
+
528
+ It is easy to plot the model parameters. Just use both functions `smashbox.plot.myplot.myplot.plot_parameters` and `smashbox.plot.myplot.myplot.multiplot_parameters`.
529
+
530
+ ```python
531
+ sb.graffas_zone.myplot.plot_parameters(
532
+ param="cp",
533
+ fig_settings={
534
+ "figname": "param_cp.png",
535
+ "xsize": 10,
536
+ "ysize": 10,
537
+ },
538
+ ax_settings={"title_fontsize": 12},
539
+ )
540
+ sb.graffas_zone.myplot.multiplot_parameters(
541
+ fig_settings={
542
+ "figname": "multiplot_param.png",
543
+ "xsize": 20,
544
+ "ysize": 20,
545
+ "font_ratio": 1,
546
+ },
547
+ ax_settings={"title_fontsize": 10, "font_ratio": 2},
548
+ )
549
+ ```
550
+
551
+ ![image info](./images/param_cp.png)
552
+ ![image info](./images/multiplot_param.png)
553
+
554
+ Plotting the quantile
555
+ ---------------------
556
+
557
+ SmashBox allow to plot the discharges quantile in many different ways. Four plot are possible.
558
+
559
+ The function `smashbox.plot.myplot.myplot.plot_xy_quantile` allow you to plot the quantile adjustment at any coordinate of the domain:
560
+
561
+ ```python
562
+ sb.graffas_zone.myplot.plot_xy_quantile(
563
+ X=100, Y=10, fig_settings={"font_ratio": 2}, ax_settings={"legend_fontsize": 20}
564
+ )
565
+ ```
566
+
567
+ ![image info](./images/quantile_XY.png)
568
+
569
+ It is also possible to plot the quantile at every outlets of the domain using the function `smashbox.plot.myplot.myplot.plot_outlets_quantile`. In the following example the figure will display in html in your navigator:
570
+
571
+ ```python
572
+ sb.graffas_zone.myplot.plot_outlets_quantile(
573
+ html_show=True,
574
+ fig_settings={
575
+ "figname": "quantile_outlets.png",
576
+ "xsize": 10,
577
+ "ysize": 10,
578
+ },
579
+ )
580
+ ```
581
+
582
+ ![image info](./images/quantile_outlets.png)
583
+
584
+ The function `smashbox.plot.myplot.myplot.plot_spatial_quantile` allows to plot the spatial discharges quantile on a map for a given return period and duration.
585
+
586
+ ```python
587
+ sb.graffas_zone.myplot.plot_spatial_quantile(
588
+ T=2,
589
+ duration=1,
590
+ fig_settings={
591
+ "figname": "spatial_quantile.png",
592
+ "xsize": 10,
593
+ "ysize": 10,
594
+ },
595
+ ax_settings={"font_ratio": 1.5},
596
+ )
597
+ ```
598
+
599
+ ![image info](./images/spatial_quantile.png)
600
+
601
+ The latest function `smashbox.plot.myplot.myplot.multiplot_spatial_quantile` allow to multiplot the map of the quantile for a given duration and for all return period.
602
+
603
+ ```python
604
+ sb.graffas_zone.myplot.multiplot_spatial_quantile(
605
+ duration=1,
606
+ fig_settings={
607
+ "figname": "../images/multiplot_spatial_quantile.png",
608
+ "xsize": 10,
609
+ "ysize": 10,
610
+ },
611
+ ax_settings={"font_ratio": 0.8},
612
+ )
613
+ ```
614
+
615
+ ![image info](./images/multiplot_spatial_quantile.png)
616
+
617
+ Plotting the statistics
618
+ -----------------------
619
+
620
+ Any spatial statistic can be plotted on a map using the function `smashbox.plot.myplot.myplot.plot_spatial_stats` as follow:
621
+
622
+ ```python
623
+ sb.graffas_zone.myplot.plot_spatial_stats(
624
+ fig_settings={
625
+ "figname": "../images/spatial_stats_max.png",
626
+ "xsize": 10,
627
+ "ysize": 10,
628
+ },
629
+ ax_settings={"font_ratio": 1.0},
630
+ )
631
+ ```
632
+
633
+ ![image info](./images/spatial_stats_max.png)
634
+
635
+
636
+ Plotting the misfit criterion
637
+ -----------------------------
638
+
639
+ The misift criterion can be plotted using the function `smashbox.plot.myplot.myplot.plot_misfit`. It is a bar plot of the misfit scores at every outlets.
640
+
641
+ ```python
642
+ sb.graffas_zone.myplot.plot_misfit(
643
+ misfit="nse",
644
+ fig_settings={
645
+ "figname": "../images/nse.png",
646
+ "xsize": 10,
647
+ "ysize": 7,
648
+ },
649
+ )
650
+ ```
651
+ ![image info](./images/nse.png)
652
+
653
+ Multiplot of every misfit criteria can be plotted directly using the function `smashbox.plot.myplot.myplot.plot_misfit`:
654
+
655
+ ```python
656
+ sb.graffas_zone.myplot.multiplot_misfit(
657
+ fig_settings={
658
+ "figname": "../images/multiplot_misfit.png",
659
+ "xsize": 10,
660
+ "ysize": 10,
661
+ },
662
+ )
663
+ ```
664
+
665
+ ![image info](./images/multiplot_misfit.png)
666
+
667
+ Finally a map of the misfit criteria at the outlets is plotted using the function `smashbox.plot.myplot.myplot.plot_misfit_map`:
668
+
669
+ ```python
670
+ fig, ax = sb.graffas_zone.myplot.plot_misfit_map(
671
+ misfit="nnse",
672
+ fig_settings={"figname": "../images/misfit_map.png", "xsize": 10, "ysize": 10},
673
+ ax_settings={"font_ratio": 1},
674
+ )
675
+ ```
676
+
677
+ ![image info](./images/misfit_map.png)
678
+
679
+ Plotting hydrogram
680
+ ------------------
681
+
682
+ Hydrogram of the discharges can be plotted for different outlets with the function `smashbox.plot.myplot.myplot.plot_hydrograph`:
683
+
684
+ ```python
685
+ sb.graffas_zone.myplot.plot_hydrograph(
686
+ fig_settings={
687
+ "figname": "../images/hydrogram.png",
688
+ "xsize": 10,
689
+ "ysize": 10,
690
+ },
691
+ )
692
+ ```
693
+
694
+ ![image info](./images/hydrogram.png)
695
+
696
+ # SmashBox tree structure object:
697
+
698
+ SmashBox comes with many other methods than described above. One can display the tree structure of the SmashBox object to better understand how it is structured and help to discover the existing methods associated to each object.
699
+
700
+ ```python
701
+ smashbox.tools.tools.build_object_tree(es,"es")
702
+
703
+ Object sb (SmashBox)
704
+ ├── Method: delmodel()
705
+ ├── Object graffas_zone (model)
706
+ │ ├── Method: atmos_data_connector()
707
+ │ ├── Method: export_parameters()
708
+ │ ├── Unknown attribute type: extra_smash_results = <class
709
+ │ │ 'smash.core.simulation.run.run.ForwardRun'>
710
+ │ ├── Method: forward_run()
711
+ │ ├── Method: generate_mesh()
712
+ │ ├── Method: import_parameters()
713
+ │ ├── Method: model()
714
+ │ ├── Method: model_warmup()
715
+ │ ├── Object mymesh (mesh)
716
+ │ │ ├── Attribute: catchment_polygon = None
717
+ │ │ ├── Method: generate_mesh()
718
+ │ │ ├── Method: load_mesh()
719
+ │ │ ├── Attribut: mesh = dict_keys(['xres', 'yres', 'xmin', 'ymax', 'epsg',
720
+ │ │ │ 'nrow', 'ncol', 'dx', 'dy', 'flwdir', 'flwdst', 'flwacc', 'npar',
721
+ │ │ │ 'ncpar', 'cscpar', 'cpar_to_rowcol', 'flwpar', 'nac', 'active_cell',
722
+ │ │ │ 'ng', 'gauge_pos', 'code', 'area', 'area_dln'])
723
+ │ │ └── Method: write_mesh()
724
+ │ ├── Object myplot (myplot)
725
+ │ │ ├── Method: multiplot_misfit()
726
+ │ │ ├── Method: multiplot_parameters()
727
+ │ │ ├── Method: multiplot_spatial_quantile()
728
+ │ │ ├── Method: plot_catchment_surface_consistency()
729
+ │ │ ├── Method: plot_catchment_surface_error()
730
+ │ │ ├── Method: plot_hydrograph()
731
+ │ │ ├── Method: plot_mesh()
732
+ │ │ ├── Method: plot_misfit()
733
+ │ │ ├── Method: plot_misfit_map()
734
+ │ │ ├── Method: plot_outlet_stats()
735
+ │ │ ├── Method: plot_outlets_quantile()
736
+ │ │ ├── Method: plot_parameters()
737
+ │ │ ├── Method: plot_spatial_quantile()
738
+ │ │ ├── Method: plot_spatial_stats()
739
+ │ │ └── Method: plot_xy_quantile()
740
+ │ ├── Object mysetup (setup)
741
+ │ │ ├── Method: get_setup()
742
+ │ │ ├── Method: list_available_setup()
743
+ │ │ ├── Method: load_setup()
744
+ │ │ ├── Method: set_setup()
745
+ │ │ ├── Attribut: setup = dict_keys(['adjust_interception',
746
+ │ │ │ 'daily_interannual_pet', 'dt', 'end_time', 'snow_module',
747
+ │ │ │ 'hydrological_module', 'pet_directory', 'prcp_conversion_factor',
748
+ │ │ │ 'prcp_directory', 'qobs_directory', 'read_pet', 'read_prcp',
749
+ │ │ │ 'read_qobs', 'routing_module', 'start_time'])
750
+ │ │ ├── Attribute: setup_file =
751
+ │ │ │ '/home/maxime/.smashbox/asset/setup/setup_rhax_gr4_dt3600.yaml'
752
+ │ │ ├── Method: update_setup()
753
+ │ │ └── Method: write_setup()
754
+ │ ├── Unknown attribute type: mysmashmodel = <class
755
+ │ │ 'smash.core.model.model.Model'>
756
+ │ ├── Object mystats (mystats)
757
+ │ │ ├── Method: fmaxima_stats()
758
+ │ │ ├── Method: fmisfit_stats()
759
+ │ │ ├── Method: foutlets_stats()
760
+ │ │ ├── Method: fquantile_stats()
761
+ │ │ ├── Method: fquantile_stats2()
762
+ │ │ ├── Method: fspatial_stats()
763
+ │ │ ├── Object misfit_stats (misfit_stats)
764
+ │ │ │ ├── Method: kge()
765
+ │ │ │ ├── Method: lgrm()
766
+ │ │ │ ├── Method: mae()
767
+ │ │ │ ├── Method: mape()
768
+ │ │ │ ├── Method: mse()
769
+ │ │ │ ├── Method: nnse()
770
+ │ │ │ ├── Method: nrmse()
771
+ │ │ │ ├── Method: nse()
772
+ │ │ │ ├── Object results (misfit_results)
773
+ │ │ │ │ ├── Attribute: kge = <class 'numpy.ndarray'>
774
+ │ │ │ │ ├── Attribute: lgrm = <class 'numpy.ndarray'>
775
+ │ │ │ │ ├── Attribute: mae = <class 'numpy.ndarray'>
776
+ │ │ │ │ ├── Attribute: mape = <class 'numpy.ndarray'>
777
+ │ │ │ │ ├── Attribute: mse = <class 'numpy.ndarray'>
778
+ │ │ │ │ ├── Attribute: nnse = <class 'numpy.ndarray'>
779
+ │ │ │ │ ├── Attribute: nrmse = <class 'numpy.ndarray'>
780
+ │ │ │ │ ├── Attribute: nse = <class 'numpy.ndarray'>
781
+ │ │ │ │ ├── Attribute: rmse = <class 'numpy.ndarray'>
782
+ │ │ │ │ └── Attribute: se = <class 'numpy.ndarray'>
783
+ │ │ │ ├── Method: rmse()
784
+ │ │ │ ├── Method: se()
785
+ │ │ │ ├── Method: sm_kge()
786
+ │ │ │ ├── Method: sm_lgrm()
787
+ │ │ │ ├── Method: sm_mae()
788
+ │ │ │ ├── Method: sm_mape()
789
+ │ │ │ ├── Method: sm_mse()
790
+ │ │ │ ├── Method: sm_nnse()
791
+ │ │ │ ├── Method: sm_nrmse()
792
+ │ │ │ ├── Method: sm_nse()
793
+ │ │ │ ├── Method: sm_rmse()
794
+ │ │ │ └── Method: sm_se()
795
+ │ │ ├── Object outlets_stats (outlets_stats)
796
+ │ │ │ ├── Method: maximum()
797
+ │ │ │ ├── Method: mean()
798
+ │ │ │ ├── Method: median()
799
+ │ │ │ ├── Method: minimum()
800
+ │ │ │ ├── Method: q20()
801
+ │ │ │ ├── Method: q80()
802
+ │ │ │ ├── Object results_obs (outlets_stats_results)
803
+ │ │ │ │ ├── Attribute: max = <class 'numpy.ndarray'>
804
+ │ │ │ │ ├── Attribute: mean = <class 'numpy.ndarray'>
805
+ │ │ │ │ ├── Attribute: median = <class 'numpy.ndarray'>
806
+ │ │ │ │ ├── Attribute: min = <class 'numpy.ndarray'>
807
+ │ │ │ │ ├── Attribute: q20 = <class 'numpy.ndarray'>
808
+ │ │ │ │ └── Attribute: q80 = None
809
+ │ │ │ └── Object results_sim (outlets_stats_results)
810
+ │ │ │ ├── Attribute: max = <class 'numpy.ndarray'>
811
+ │ │ │ ├── Attribute: mean = <class 'numpy.ndarray'>
812
+ │ │ │ ├── Attribute: median = <class 'numpy.ndarray'>
813
+ │ │ │ ├── Attribute: min = <class 'numpy.ndarray'>
814
+ │ │ │ ├── Attribute: q20 = <class 'numpy.ndarray'>
815
+ │ │ │ └── Attribute: q80 = None
816
+ │ │ ├── Object quantile_stats (spatial_quantile)
817
+ │ │ │ ├── Object Quantile_12h (spatial_quantile_results)
818
+ │ │ │ │ ├── Attribute: Q_th = <class 'numpy.ndarray'>
819
+ │ │ │ │ ├── Attribute: T = <class 'numpy.ndarray'>
820
+ │ │ │ │ ├── Attribute: T_emp = <class 'numpy.ndarray'>
821
+ │ │ │ │ ├── Attribute: Umax = <class 'numpy.ndarray'>
822
+ │ │ │ │ ├── Attribute: Umin = <class 'numpy.ndarray'>
823
+ │ │ │ │ ├── Attribute: chunk_size = 3
824
+ │ │ │ │ ├── Attribute: duration = 12
825
+ │ │ │ │ ├── Method: fill_attribute()
826
+ │ │ │ │ ├── Attribute: fit = 'gumbel'
827
+ │ │ │ │ ├── Attribute: fit_loc = <class 'numpy.ndarray'>
828
+ │ │ │ │ ├── Attribute: fit_scale = <class 'numpy.ndarray'>
829
+ │ │ │ │ ├── Attribute: fit_shape = <class 'numpy.ndarray'>
830
+ │ │ │ │ ├── Attribute: maxima = <class 'numpy.ndarray'>
831
+ │ │ │ │ └── Attribute: nb_chunks = 15
832
+ │ │ │ ├── Object Quantile_1h (spatial_quantile_results)
833
+ │ │ │ │ ├── Attribute: Q_th = <class 'numpy.ndarray'>
834
+ │ │ │ │ ├── Attribute: T = <class 'numpy.ndarray'>
835
+ │ │ │ │ ├── Attribute: T_emp = <class 'numpy.ndarray'>
836
+ │ │ │ │ ├── Attribute: Umax = <class 'numpy.ndarray'>
837
+ │ │ │ │ ├── Attribute: Umin = <class 'numpy.ndarray'>
838
+ │ │ │ │ ├── Attribute: chunk_size = 3
839
+ │ │ │ │ ├── Attribute: duration = 1
840
+ │ │ │ │ ├── Method: fill_attribute()
841
+ │ │ │ │ ├── Attribute: fit = 'gumbel'
842
+ │ │ │ │ ├── Attribute: fit_loc = <class 'numpy.ndarray'>
843
+ │ │ │ │ ├── Attribute: fit_scale = <class 'numpy.ndarray'>
844
+ │ │ │ │ ├── Attribute: fit_shape = <class 'numpy.ndarray'>
845
+ │ │ │ │ ├── Attribute: maxima = <class 'numpy.ndarray'>
846
+ │ │ │ │ └── Attribute: nb_chunks = 15
847
+ │ │ │ ├── Object Quantile_24h (spatial_quantile_results)
848
+ │ │ │ │ ├── Attribute: Q_th = <class 'numpy.ndarray'>
849
+ │ │ │ │ ├── Attribute: T = <class 'numpy.ndarray'>
850
+ │ │ │ │ ├── Attribute: T_emp = <class 'numpy.ndarray'>
851
+ │ │ │ │ ├── Attribute: Umax = <class 'numpy.ndarray'>
852
+ │ │ │ │ ├── Attribute: Umin = <class 'numpy.ndarray'>
853
+ │ │ │ │ ├── Attribute: chunk_size = 3
854
+ │ │ │ │ ├── Attribute: duration = 24
855
+ │ │ │ │ ├── Method: fill_attribute()
856
+ │ │ │ │ ├── Attribute: fit = 'gumbel'
857
+ │ │ │ │ ├── Attribute: fit_loc = <class 'numpy.ndarray'>
858
+ │ │ │ │ ├── Attribute: fit_scale = <class 'numpy.ndarray'>
859
+ │ │ │ │ ├── Attribute: fit_shape = <class 'numpy.ndarray'>
860
+ │ │ │ │ ├── Attribute: maxima = <class 'numpy.ndarray'>
861
+ │ │ │ │ └── Attribute: nb_chunks = 15
862
+ │ │ │ ├── Object Quantile_2h (spatial_quantile_results)
863
+ │ │ │ │ ├── Attribute: Q_th = <class 'numpy.ndarray'>
864
+ │ │ │ │ ├── Attribute: T = <class 'numpy.ndarray'>
865
+ │ │ │ │ ├── Attribute: T_emp = <class 'numpy.ndarray'>
866
+ │ │ │ │ ├── Attribute: Umax = <class 'numpy.ndarray'>
867
+ │ │ │ │ ├── Attribute: Umin = <class 'numpy.ndarray'>
868
+ │ │ │ │ ├── Attribute: chunk_size = 3
869
+ │ │ │ │ ├── Attribute: duration = 2
870
+ │ │ │ │ ├── Method: fill_attribute()
871
+ │ │ │ │ ├── Attribute: fit = 'gumbel'
872
+ │ │ │ │ ├── Attribute: fit_loc = <class 'numpy.ndarray'>
873
+ │ │ │ │ ├── Attribute: fit_scale = <class 'numpy.ndarray'>
874
+ │ │ │ │ ├── Attribute: fit_shape = <class 'numpy.ndarray'>
875
+ │ │ │ │ ├── Attribute: maxima = <class 'numpy.ndarray'>
876
+ │ │ │ │ └── Attribute: nb_chunks = 15
877
+ │ │ │ ├── Object Quantile_3h (spatial_quantile_results)
878
+ │ │ │ │ ├── Attribute: Q_th = <class 'numpy.ndarray'>
879
+ │ │ │ │ ├── Attribute: T = <class 'numpy.ndarray'>
880
+ │ │ │ │ ├── Attribute: T_emp = <class 'numpy.ndarray'>
881
+ │ │ │ │ ├── Attribute: Umax = <class 'numpy.ndarray'>
882
+ │ │ │ │ ├── Attribute: Umin = <class 'numpy.ndarray'>
883
+ │ │ │ │ ├── Attribute: chunk_size = 3
884
+ │ │ │ │ ├── Attribute: duration = 3
885
+ │ │ │ │ ├── Method: fill_attribute()
886
+ │ │ │ │ ├── Attribute: fit = 'gumbel'
887
+ │ │ │ │ ├── Attribute: fit_loc = <class 'numpy.ndarray'>
888
+ │ │ │ │ ├── Attribute: fit_scale = <class 'numpy.ndarray'>
889
+ │ │ │ │ ├── Attribute: fit_shape = <class 'numpy.ndarray'>
890
+ │ │ │ │ ├── Attribute: maxima = <class 'numpy.ndarray'>
891
+ │ │ │ │ └── Attribute: nb_chunks = 15
892
+ │ │ │ ├── Object Quantile_48h (spatial_quantile_results)
893
+ │ │ │ │ ├── Attribute: Q_th = <class 'numpy.ndarray'>
894
+ │ │ │ │ ├── Attribute: T = <class 'numpy.ndarray'>
895
+ │ │ │ │ ├── Attribute: T_emp = <class 'numpy.ndarray'>
896
+ │ │ │ │ ├── Attribute: Umax = <class 'numpy.ndarray'>
897
+ │ │ │ │ ├── Attribute: Umin = <class 'numpy.ndarray'>
898
+ │ │ │ │ ├── Attribute: chunk_size = 3
899
+ │ │ │ │ ├── Attribute: duration = 48
900
+ │ │ │ │ ├── Method: fill_attribute()
901
+ │ │ │ │ ├── Attribute: fit = 'gumbel'
902
+ │ │ │ │ ├── Attribute: fit_loc = <class 'numpy.ndarray'>
903
+ │ │ │ │ ├── Attribute: fit_scale = <class 'numpy.ndarray'>
904
+ │ │ │ │ ├── Attribute: fit_shape = <class 'numpy.ndarray'>
905
+ │ │ │ │ ├── Attribute: maxima = <class 'numpy.ndarray'>
906
+ │ │ │ │ └── Attribute: nb_chunks = 15
907
+ │ │ │ ├── Object Quantile_4h (spatial_quantile_results)
908
+ │ │ │ │ ├── Attribute: Q_th = <class 'numpy.ndarray'>
909
+ │ │ │ │ ├── Attribute: T = <class 'numpy.ndarray'>
910
+ │ │ │ │ ├── Attribute: T_emp = <class 'numpy.ndarray'>
911
+ │ │ │ │ ├── Attribute: Umax = <class 'numpy.ndarray'>
912
+ │ │ │ │ ├── Attribute: Umin = <class 'numpy.ndarray'>
913
+ │ │ │ │ ├── Attribute: chunk_size = 3
914
+ │ │ │ │ ├── Attribute: duration = 4
915
+ │ │ │ │ ├── Method: fill_attribute()
916
+ │ │ │ │ ├── Attribute: fit = 'gumbel'
917
+ │ │ │ │ ├── Attribute: fit_loc = <class 'numpy.ndarray'>
918
+ │ │ │ │ ├── Attribute: fit_scale = <class 'numpy.ndarray'>
919
+ │ │ │ │ ├── Attribute: fit_shape = <class 'numpy.ndarray'>
920
+ │ │ │ │ ├── Attribute: maxima = <class 'numpy.ndarray'>
921
+ │ │ │ │ └── Attribute: nb_chunks = 15
922
+ │ │ │ ├── Object Quantile_6h (spatial_quantile_results)
923
+ │ │ │ │ ├── Attribute: Q_th = <class 'numpy.ndarray'>
924
+ │ │ │ │ ├── Attribute: T = <class 'numpy.ndarray'>
925
+ │ │ │ │ ├── Attribute: T_emp = <class 'numpy.ndarray'>
926
+ │ │ │ │ ├── Attribute: Umax = <class 'numpy.ndarray'>
927
+ │ │ │ │ ├── Attribute: Umin = <class 'numpy.ndarray'>
928
+ │ │ │ │ ├── Attribute: chunk_size = 3
929
+ │ │ │ │ ├── Attribute: duration = 6
930
+ │ │ │ │ ├── Method: fill_attribute()
931
+ │ │ │ │ ├── Attribute: fit = 'gumbel'
932
+ │ │ │ │ ├── Attribute: fit_loc = <class 'numpy.ndarray'>
933
+ │ │ │ │ ├── Attribute: fit_scale = <class 'numpy.ndarray'>
934
+ │ │ │ │ ├── Attribute: fit_shape = <class 'numpy.ndarray'>
935
+ │ │ │ │ ├── Attribute: maxima = <class 'numpy.ndarray'>
936
+ │ │ │ │ └── Attribute: nb_chunks = 15
937
+ │ │ │ ├── Object Quantile_72h (spatial_quantile_results)
938
+ │ │ │ │ ├── Attribute: Q_th = <class 'numpy.ndarray'>
939
+ │ │ │ │ ├── Attribute: T = <class 'numpy.ndarray'>
940
+ │ │ │ │ ├── Attribute: T_emp = <class 'numpy.ndarray'>
941
+ │ │ │ │ ├── Attribute: Umax = <class 'numpy.ndarray'>
942
+ │ │ │ │ ├── Attribute: Umin = <class 'numpy.ndarray'>
943
+ │ │ │ │ ├── Attribute: chunk_size = 3
944
+ │ │ │ │ ├── Attribute: duration = 72
945
+ │ │ │ │ ├── Method: fill_attribute()
946
+ │ │ │ │ ├── Attribute: fit = 'gumbel'
947
+ │ │ │ │ ├── Attribute: fit_loc = <class 'numpy.ndarray'>
948
+ │ │ │ │ ├── Attribute: fit_scale = <class 'numpy.ndarray'>
949
+ │ │ │ │ ├── Attribute: fit_shape = <class 'numpy.ndarray'>
950
+ │ │ │ │ ├── Attribute: maxima = <class 'numpy.ndarray'>
951
+ │ │ │ │ └── Attribute: nb_chunks = 15
952
+ │ │ │ ├── Attribute: spatial_cumulated_maxima = <class 'numpy.ndarray'>
953
+ │ │ │ ├── Attribute: spatial_maxima_matrix = <class 'numpy.ndarray'>
954
+ │ │ │ └── Attribute: spatial_quantile_matrix = <class 'numpy.ndarray'>
955
+ │ │ └── Object spatial_stats (spatial_stats)
956
+ │ │ ├── Method: maximum()
957
+ │ │ ├── Method: mean()
958
+ │ │ ├── Method: median()
959
+ │ │ ├── Method: minimum()
960
+ │ │ ├── Method: q20()
961
+ │ │ ├── Method: q80()
962
+ │ │ └── Object results (spatial_stats_results)
963
+ │ │ ├── Attribute: max = <class 'numpy.ndarray'>
964
+ │ │ ├── Attribute: mean = <class 'numpy.ndarray'>
965
+ │ │ ├── Attribute: median = <class 'numpy.ndarray'>
966
+ │ │ ├── Attribute: mediane = None
967
+ │ │ ├── Attribute: min = <class 'numpy.ndarray'>
968
+ │ │ ├── Attribute: q20 = <class 'numpy.ndarray'>
969
+ │ │ └── Attribute: q80 = None
970
+ │ └── Method: save_model_container()
971
+ ├── Method: help()
972
+ ├── Object myparam (param)
973
+ │ ├── Method: get_param()
974
+ │ ├── Method: list_assets_files()
975
+ │ ├── Method: list_param()
976
+ │ ├── Method: load_param()
977
+ │ ├── Object param (smashboxparam)
978
+ │ │ ├── Attribute: asset_dir = '/home/maxime/.smashbox/asset'
979
+ │ │ ├── Attribut: bbox = dict_keys(['left', 'bottom', 'right', 'top'])
980
+ │ │ ├── Attribute: enhanced_smash_input_data = False
981
+ │ │ ├── Attribute: epsg = 2154
982
+ │ │ ├── Attribute: flowdir =
983
+ │ │ │ '/home/maxime/.smashbox/asset/flwdir/flowdir_fr_1000m.tif'
984
+ │ │ ├── Attribute: outletsID = []
985
+ │ │ ├── Attribute: outlets_database =
986
+ │ │ │ '/home/maxime/DEV/smashbox/smashbox/asset/outlets/db_sites.csv'
987
+ │ │ ├── Attribut: outlets_database_fields = dict_keys(['coord_x',
988
+ │ │ │ 'coord_y', 'area', 'id'])
989
+ │ │ ├── Attribute: outlets_shapefile = None
990
+ │ │ ├── Attribute: setup_file =
991
+ │ │ │ '/home/maxime/.smashbox/asset/setup/setup_rhax_gr4_dt3600.yaml'
992
+ │ │ └── Attribute: smash_parameters =
993
+ │ │ '/home/maxime/DEV/smashbox/smashbox/asset/params'
994
+ │ ├── Method: set_param()
995
+ │ ├── Method: set_param_as_dict()
996
+ │ └── Method: write_param()
997
+ └── Method: newmodel()
998
+ ```