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
smashbox/init/param.py
ADDED
|
@@ -0,0 +1,799 @@
|
|
|
1
|
+
import smashbox
|
|
2
|
+
import os
|
|
3
|
+
import yaml
|
|
4
|
+
from smashbox.tools.tools import check_asset_path, print_tree
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class param:
|
|
8
|
+
"""
|
|
9
|
+
Class param(): object which own :
|
|
10
|
+
- one attribute `param` with all necessary parameters fro building
|
|
11
|
+
an hydrological model with SmashBoxfunctions
|
|
12
|
+
- Some functions to maniuplate these parameters (stored in attribute param)
|
|
13
|
+
|
|
14
|
+
attributes
|
|
15
|
+
----------
|
|
16
|
+
|
|
17
|
+
param : class smashboxparam()
|
|
18
|
+
Class which stores the main parameters
|
|
19
|
+
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
def __init__(self):
|
|
23
|
+
|
|
24
|
+
# self._parent_class=parent_class
|
|
25
|
+
self.param = smashboxparam()
|
|
26
|
+
"""parent variable for class smashboxparam with all main parameters
|
|
27
|
+
of smashbox.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
def list_param(self):
|
|
31
|
+
"""
|
|
32
|
+
List all parameters in self.param
|
|
33
|
+
|
|
34
|
+
Examples
|
|
35
|
+
--------
|
|
36
|
+
|
|
37
|
+
>>> es=smashbox.SmashBox()
|
|
38
|
+
>>> sb.newmodel("RealCollobrier")
|
|
39
|
+
>>> sb.RealCollobrier.list_param()
|
|
40
|
+
|
|
41
|
+
"""
|
|
42
|
+
for name, value in vars(type(self.param)).items():
|
|
43
|
+
if isinstance(value, property):
|
|
44
|
+
print(f"{name}={getattr(self.param, name)}")
|
|
45
|
+
|
|
46
|
+
def set_param(self, attr, value):
|
|
47
|
+
"""
|
|
48
|
+
Setter for class attribute param().
|
|
49
|
+
|
|
50
|
+
parameters
|
|
51
|
+
----------
|
|
52
|
+
attr : str
|
|
53
|
+
name of the attributes
|
|
54
|
+
|
|
55
|
+
value: any
|
|
56
|
+
value of the attribute
|
|
57
|
+
|
|
58
|
+
example
|
|
59
|
+
-------
|
|
60
|
+
|
|
61
|
+
self.set_param("flowdir", "path/to/the/flowdir")
|
|
62
|
+
"""
|
|
63
|
+
setattr(self.param, attr, value)
|
|
64
|
+
|
|
65
|
+
def set_param_as_dict(self, param_dict):
|
|
66
|
+
"""
|
|
67
|
+
Setter for class attribute param() from a dictionary of keys/values.
|
|
68
|
+
|
|
69
|
+
parameters
|
|
70
|
+
----------
|
|
71
|
+
param_dict : dict
|
|
72
|
+
Dictionary with keys and values
|
|
73
|
+
|
|
74
|
+
example
|
|
75
|
+
-------
|
|
76
|
+
|
|
77
|
+
self.set_param_as_dict({"flowdir": "path/to/the/flowdir","epsg":2154})
|
|
78
|
+
"""
|
|
79
|
+
for key, value in param_dict.items():
|
|
80
|
+
self.set_param(key, value)
|
|
81
|
+
|
|
82
|
+
def get_param(self, attr):
|
|
83
|
+
"""
|
|
84
|
+
Getter for class attribute param().
|
|
85
|
+
|
|
86
|
+
parameters
|
|
87
|
+
----------
|
|
88
|
+
attr : str
|
|
89
|
+
name of the attributes
|
|
90
|
+
|
|
91
|
+
return:
|
|
92
|
+
-------
|
|
93
|
+
any, the value stored in the attribute `attr`.
|
|
94
|
+
example
|
|
95
|
+
|
|
96
|
+
self.get_param("flowdir", "path/to/the/flowdir")
|
|
97
|
+
"""
|
|
98
|
+
getattr(self.param, attr)
|
|
99
|
+
|
|
100
|
+
def write_param(self, filename="param.yaml"):
|
|
101
|
+
"""
|
|
102
|
+
Dump all param attribute in a yaml file.
|
|
103
|
+
|
|
104
|
+
parameters
|
|
105
|
+
----------
|
|
106
|
+
filename : str
|
|
107
|
+
name of file to save the parameter formated in yaml
|
|
108
|
+
|
|
109
|
+
exemple:
|
|
110
|
+
--------
|
|
111
|
+
|
|
112
|
+
self.get_param("flowdir", "path/to/the/flowdir")
|
|
113
|
+
"""
|
|
114
|
+
with open(filename, "w") as file:
|
|
115
|
+
yaml.dump(self.param.__dict__, file)
|
|
116
|
+
|
|
117
|
+
def load_param(self, filename=None):
|
|
118
|
+
"""
|
|
119
|
+
Load the parameters stored in a yaml file.
|
|
120
|
+
|
|
121
|
+
parameters
|
|
122
|
+
----------
|
|
123
|
+
filename : str
|
|
124
|
+
name of file to save the parameter formated in yaml
|
|
125
|
+
|
|
126
|
+
exemple:
|
|
127
|
+
--------
|
|
128
|
+
|
|
129
|
+
self.get_param("flowdir", "path/to/the/flowdir")
|
|
130
|
+
"""
|
|
131
|
+
if os.path.exists(filename):
|
|
132
|
+
|
|
133
|
+
with open(filename, "r") as file:
|
|
134
|
+
|
|
135
|
+
param = yaml.safe_load(file)
|
|
136
|
+
|
|
137
|
+
for key, value in param.items():
|
|
138
|
+
self.set_param(key, value)
|
|
139
|
+
|
|
140
|
+
def list_assets_files(self):
|
|
141
|
+
"""
|
|
142
|
+
List all assets files owned by SmashBox. Thes files are data such as
|
|
143
|
+
the flow directions and outlets database.
|
|
144
|
+
|
|
145
|
+
"""
|
|
146
|
+
print_tree(os.path.join(smashbox.__path__[0], "asset"))
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
class smashboxparam:
|
|
150
|
+
"""
|
|
151
|
+
The class `smashboxparam` contains the main parameters needed to build an
|
|
152
|
+
SmashBox model. Thes parameters are stored in different attributes.
|
|
153
|
+
|
|
154
|
+
"""
|
|
155
|
+
|
|
156
|
+
def __init__(self):
|
|
157
|
+
"""
|
|
158
|
+
Initialisation of the attributes of class smashboxparam. All attributes
|
|
159
|
+
have a default value.
|
|
160
|
+
"""
|
|
161
|
+
self._assets_dir = None
|
|
162
|
+
"""Path to the asset directory. str"""
|
|
163
|
+
if not os.path.exists(
|
|
164
|
+
os.path.join(os.path.expanduser("~"), ".smashbox", "asset")
|
|
165
|
+
):
|
|
166
|
+
self._assets_dir = os.path.join(smashbox.__path__[0], "asset")
|
|
167
|
+
"""Path to the asset directory. str"""
|
|
168
|
+
else:
|
|
169
|
+
self._assets_dir = os.path.join(
|
|
170
|
+
os.path.expanduser("~"), ".smashbox", "asset"
|
|
171
|
+
)
|
|
172
|
+
"""Path to the asset directory. str"""
|
|
173
|
+
|
|
174
|
+
self._flowdir = os.path.join(self._assets_dir, "flwdir", "flowdir_fr_1000m.tif")
|
|
175
|
+
"""Path to the flow direction file formated in geotif. str"""
|
|
176
|
+
|
|
177
|
+
self._outlets_database = os.path.join(self._assets_dir, "outlets", "db_sites.csv")
|
|
178
|
+
""" Path to the outlet database iformatted in csv. str."""
|
|
179
|
+
|
|
180
|
+
self._setup_file = os.path.join(
|
|
181
|
+
self._assets_dir,
|
|
182
|
+
"setup",
|
|
183
|
+
"setup_rhax_gr4_dt3600.yaml",
|
|
184
|
+
)
|
|
185
|
+
"""Path to a Smash setup file to be used. Format yaml. If only the name
|
|
186
|
+
of the file is given, the file will be searched in the asset directory.
|
|
187
|
+
"""
|
|
188
|
+
self._bbox = None # {"left": 0, "bottom": 0, "right": 0, "top": 0}
|
|
189
|
+
"""Bounding box of the area to be modeled. dict | None, Optional.
|
|
190
|
+
bbox is a dictionary with
|
|
191
|
+
the following convention:
|
|
192
|
+
bbox={"left": c_weast, "bottom": y_south, "right": x_east, "top": x_north}
|
|
193
|
+
"""
|
|
194
|
+
|
|
195
|
+
self._epsg = 2154
|
|
196
|
+
"""EPSG code of the coordinate system used. Integer."""
|
|
197
|
+
|
|
198
|
+
self._outletsID = []
|
|
199
|
+
"""List of the outlets (key or name) to include in the mesh.
|
|
200
|
+
If the list is left empty, all outlets found in the area
|
|
201
|
+
defined by bbox will be included. If None, no outlet will be added.
|
|
202
|
+
The outlet name must be chosen
|
|
203
|
+
among the list of the outlet_database file in the column defined
|
|
204
|
+
by the attribute outlets_database_fields ('id')
|
|
205
|
+
"""
|
|
206
|
+
|
|
207
|
+
self._outlets_shapefile = None
|
|
208
|
+
"""Path to the shape file containing the oultlet boundaries. Optional"""
|
|
209
|
+
|
|
210
|
+
self._smash_parameters = os.path.join(self._assets_dir, "params")
|
|
211
|
+
"""Path to a directory with calibrated smash parameters. String | None.
|
|
212
|
+
All parameters must be stroed separetly in geotiff file.
|
|
213
|
+
"""
|
|
214
|
+
|
|
215
|
+
self._smash_parameters_dt = None
|
|
216
|
+
"""Time-step for which the smash_parameters has been originaly calibrated.
|
|
217
|
+
int | float. If not None and if the model parameters is different, the parameters
|
|
218
|
+
"ct", "kexc", "llr" will be transformed according the relation
|
|
219
|
+
described in A.Ficchi, 2017.
|
|
220
|
+
"""
|
|
221
|
+
|
|
222
|
+
self._outlets_database_fields = {
|
|
223
|
+
"coord_x": "X_L93",
|
|
224
|
+
"coord_y": "Y_L93",
|
|
225
|
+
"area": "SURF",
|
|
226
|
+
"id": "CODE_SITE",
|
|
227
|
+
}
|
|
228
|
+
"""Dictionary with the name of the useful column field {key: field name}.
|
|
229
|
+
dict.
|
|
230
|
+
"""
|
|
231
|
+
|
|
232
|
+
self.enhanced_smash_input_data = False
|
|
233
|
+
"""
|
|
234
|
+
Use an enhanced version of the smash.model() method. The reading of the input atmospheric data functions used by smash have been rewritten in a different way provide more options and flexibility.
|
|
235
|
+
- read same type of data like SMASH: precipitation, snow, temperature and evapotranspration.
|
|
236
|
+
Support Geotiff format only.
|
|
237
|
+
- Merge all reading function in one.
|
|
238
|
+
- Configure the pattern of the date to search in the filename. Use common date formatters.
|
|
239
|
+
Handle the occurence number (starting from 0) with %n at the end of the date pattern. ex: %Y%m%d%H%1.
|
|
240
|
+
- Improve logs: new log clearly warn user about which files have been read and which files are missing.
|
|
241
|
+
- Fix a mistake during the reading of the evapotranspration. In SMASH the
|
|
242
|
+
evapotranspiration from the previous day is read instead of the current one.
|
|
243
|
+
- Read several data source by priority: each kind of data may have different source.
|
|
244
|
+
If one is missing, the model will read the second one, ect...
|
|
245
|
+
- Partially handle the reading of the continuous evapotranspiration in an operationnal context.
|
|
246
|
+
To do that, a sim-link of the etp data (delayed by 1 day) is created named with the date
|
|
247
|
+
of the current day.
|
|
248
|
+
- Handle time zone to shift the desagregation curve of the PET during the day.
|
|
249
|
+
- Improve the speed of the reading. Technically, an index of the dates and the
|
|
250
|
+
corresponding data files is created. To eficiency run through the long list of data files
|
|
251
|
+
and performs a regex search to match a date, a simple searh algorithm is build on top of
|
|
252
|
+
the main loop to avoid performing a regex on thousand files.
|
|
253
|
+
This improvement is noticable for model running on few time-step. It is particulary
|
|
254
|
+
important when running smash in an operationnal context.
|
|
255
|
+
"""
|
|
256
|
+
|
|
257
|
+
@property
|
|
258
|
+
def asset_dir(self):
|
|
259
|
+
"""
|
|
260
|
+
Type:
|
|
261
|
+
-----
|
|
262
|
+
Property/Setter: str | os.PathLike
|
|
263
|
+
|
|
264
|
+
Description:
|
|
265
|
+
------------
|
|
266
|
+
Path to the asset directory. Default value is the asset directory of
|
|
267
|
+
SmashBox copied in the user space.
|
|
268
|
+
|
|
269
|
+
exemple
|
|
270
|
+
-------
|
|
271
|
+
self.asset_dir = "path/to/my/asset/dir"
|
|
272
|
+
|
|
273
|
+
"""
|
|
274
|
+
return self._assets_dir
|
|
275
|
+
|
|
276
|
+
@asset_dir.setter
|
|
277
|
+
def asset_dir(self, value: os.PathLike):
|
|
278
|
+
"""
|
|
279
|
+
Setter. Path to the asset directory.
|
|
280
|
+
value : os.PathLike
|
|
281
|
+
|
|
282
|
+
exemple
|
|
283
|
+
-------
|
|
284
|
+
self.asset_dir = "path/to/my/asset/dir"
|
|
285
|
+
|
|
286
|
+
"""
|
|
287
|
+
if os.path.isdir(value):
|
|
288
|
+
self._asset_dir = value
|
|
289
|
+
else:
|
|
290
|
+
raise ValueError(f"{value} is not a valid directory.")
|
|
291
|
+
|
|
292
|
+
@property
|
|
293
|
+
def outlets_database(self):
|
|
294
|
+
"""
|
|
295
|
+
Type:
|
|
296
|
+
-----
|
|
297
|
+
Property/Setter: str | os.PathLike.
|
|
298
|
+
|
|
299
|
+
Description:
|
|
300
|
+
------------
|
|
301
|
+
Path to the outlet database formatted in csv. Field name,
|
|
302
|
+
coordinates (X and Y) and the surface of the catchment must exists.
|
|
303
|
+
Field name can be configure with attribute outlets_database_fields.
|
|
304
|
+
|
|
305
|
+
exemple
|
|
306
|
+
-------
|
|
307
|
+
self.outlets_database = "path/to/my/database.csv"
|
|
308
|
+
|
|
309
|
+
"""
|
|
310
|
+
return self._outlets_database
|
|
311
|
+
|
|
312
|
+
@outlets_database.setter
|
|
313
|
+
def outlets_database(self, value: os.PathLike):
|
|
314
|
+
"""
|
|
315
|
+
Setter. Path to the outlet database formatted in csv. Field name,
|
|
316
|
+
coordinates (X and Y) and the surface of the catchment must exists.
|
|
317
|
+
Field name can be configure with attribute outlets_database_fields.
|
|
318
|
+
value : os.PathLike
|
|
319
|
+
|
|
320
|
+
exemple
|
|
321
|
+
-------
|
|
322
|
+
self.outlets_database = "path/to/my/database.csv"
|
|
323
|
+
|
|
324
|
+
"""
|
|
325
|
+
self._outlets_database = check_asset_path(
|
|
326
|
+
os.path.join(self.asset_dir, "outlets"), value
|
|
327
|
+
)
|
|
328
|
+
|
|
329
|
+
@property
|
|
330
|
+
def setup_file(self):
|
|
331
|
+
"""
|
|
332
|
+
Type:
|
|
333
|
+
-----
|
|
334
|
+
Property/Setter: str | os.PathLike.
|
|
335
|
+
|
|
336
|
+
Description:
|
|
337
|
+
------------
|
|
338
|
+
Path to the smash setup file formatted in yaml. If only the name
|
|
339
|
+
of the file is given, the infered path will be the asset directory.
|
|
340
|
+
|
|
341
|
+
exemple
|
|
342
|
+
-------
|
|
343
|
+
self.setup_file = "path/to/my/setup.yaml"
|
|
344
|
+
|
|
345
|
+
"""
|
|
346
|
+
return self._setup_file
|
|
347
|
+
|
|
348
|
+
@setup_file.setter
|
|
349
|
+
def setup_file(self, value: os.PathLike):
|
|
350
|
+
"""
|
|
351
|
+
Setter. Path to the smash setup file formatted in yaml.
|
|
352
|
+
value : os.PathLike
|
|
353
|
+
|
|
354
|
+
exemple
|
|
355
|
+
-------
|
|
356
|
+
self.setup_file = "path/to/my/setup.yaml"
|
|
357
|
+
|
|
358
|
+
"""
|
|
359
|
+
self._setup_file = check_asset_path(os.path.join(self.asset_dir, "setup"), value)
|
|
360
|
+
# self._parent_class._parent_class.mysetup.load_setup(self._setup_file)
|
|
361
|
+
|
|
362
|
+
@property
|
|
363
|
+
def flowdir(self):
|
|
364
|
+
"""
|
|
365
|
+
Type:
|
|
366
|
+
-----
|
|
367
|
+
Property/Setter: str | os.PathLike.
|
|
368
|
+
|
|
369
|
+
Description:
|
|
370
|
+
------------
|
|
371
|
+
The path to the flowdir (flow direction) file formatted in Geotif. Refer to the Smash
|
|
372
|
+
documentation for more details: `https://smash.recover.inrae.fr/user_guide/
|
|
373
|
+
data_and_format_description/cance.html#flow-direction`
|
|
374
|
+
|
|
375
|
+
"""
|
|
376
|
+
return self._flowdir
|
|
377
|
+
|
|
378
|
+
@flowdir.setter
|
|
379
|
+
def flowdir(self, value: os.PathLike):
|
|
380
|
+
"""
|
|
381
|
+
Setter. Path to the flowdir file formatted in Geotif.
|
|
382
|
+
value : os.PathLike
|
|
383
|
+
|
|
384
|
+
exemple
|
|
385
|
+
-------
|
|
386
|
+
self.flowdir = "path/to/my/flowdir.tif"
|
|
387
|
+
|
|
388
|
+
"""
|
|
389
|
+
self._flowdir = check_asset_path(os.path.join(self.asset_dir, "flowdir"), value)
|
|
390
|
+
|
|
391
|
+
@property
|
|
392
|
+
def bbox(self):
|
|
393
|
+
"""
|
|
394
|
+
Type:
|
|
395
|
+
-----
|
|
396
|
+
Property/Setter: dict
|
|
397
|
+
|
|
398
|
+
Description:
|
|
399
|
+
------------
|
|
400
|
+
The Bounding box of the area to be modeled. dict | None, Optional.
|
|
401
|
+
bbox is a dictionary with the following convention:
|
|
402
|
+
bbox={"left": c_weast, "bottom": y_south, "right": x_east, "top": x_north}
|
|
403
|
+
|
|
404
|
+
exemple
|
|
405
|
+
-------
|
|
406
|
+
self.bbox = {'left': 0, 'bottom': 0, 'right': 10, 'top': 10}
|
|
407
|
+
|
|
408
|
+
"""
|
|
409
|
+
return self._bbox
|
|
410
|
+
|
|
411
|
+
@bbox.setter
|
|
412
|
+
def bbox(self, value: dict | None):
|
|
413
|
+
"""
|
|
414
|
+
Setter. Set the bounding box of the domain.
|
|
415
|
+
value : dict | None
|
|
416
|
+
|
|
417
|
+
exemple
|
|
418
|
+
-------
|
|
419
|
+
self.bbox = {'left': 0, 'bottom': 0, 'right': 10, 'top': 10}
|
|
420
|
+
|
|
421
|
+
"""
|
|
422
|
+
if value is None:
|
|
423
|
+
self._bbox = value
|
|
424
|
+
|
|
425
|
+
if sorted(["left", "bottom", "right", "top"]) == sorted(list(value.keys())):
|
|
426
|
+
self._bbox = value
|
|
427
|
+
else:
|
|
428
|
+
raise ValueError(
|
|
429
|
+
f"{value} is not a boundingbox. A boundingbox must be a dict"
|
|
430
|
+
"like {'left': 0, 'bottom': 0, 'right': 0, 'top': 0}"
|
|
431
|
+
)
|
|
432
|
+
|
|
433
|
+
@property
|
|
434
|
+
def epsg(self):
|
|
435
|
+
"""
|
|
436
|
+
Type:
|
|
437
|
+
-----
|
|
438
|
+
Property/Setter: int
|
|
439
|
+
|
|
440
|
+
Descripion:
|
|
441
|
+
-----------
|
|
442
|
+
EPSG code of the coordinate system used.
|
|
443
|
+
|
|
444
|
+
exemple
|
|
445
|
+
-------
|
|
446
|
+
self.epsg = 2154
|
|
447
|
+
|
|
448
|
+
"""
|
|
449
|
+
return self._epsg
|
|
450
|
+
|
|
451
|
+
@epsg.setter
|
|
452
|
+
def epsg(self, value: int):
|
|
453
|
+
"""
|
|
454
|
+
Setter. Set the epsg code of the coordinate system used.
|
|
455
|
+
value : int
|
|
456
|
+
|
|
457
|
+
exemple
|
|
458
|
+
-------
|
|
459
|
+
self.epsg = 2154
|
|
460
|
+
|
|
461
|
+
"""
|
|
462
|
+
self._epsg = value
|
|
463
|
+
|
|
464
|
+
@property
|
|
465
|
+
def outletsID(self):
|
|
466
|
+
"""
|
|
467
|
+
Type:
|
|
468
|
+
-----
|
|
469
|
+
Property/Setter : list
|
|
470
|
+
|
|
471
|
+
Descripion:
|
|
472
|
+
-----------
|
|
473
|
+
List of the outlets (key or name) to include in the mesh.
|
|
474
|
+
If the list is left empty, all outlets found in the area
|
|
475
|
+
defined by bbox will be included. If None, no outlet will be added.
|
|
476
|
+
The outlet name must be chosen
|
|
477
|
+
among the list of the outlet_database file in the column defined
|
|
478
|
+
by the attribute outlets_database_fields ('id')
|
|
479
|
+
|
|
480
|
+
exemple
|
|
481
|
+
-------
|
|
482
|
+
self.outletsID = ['V156730', 'V200820']
|
|
483
|
+
|
|
484
|
+
"""
|
|
485
|
+
return self._outletsID
|
|
486
|
+
|
|
487
|
+
@outletsID.setter
|
|
488
|
+
def outletsID(self, value: list):
|
|
489
|
+
"""
|
|
490
|
+
Setter. Set the list of the outlet code (or name) used to build
|
|
491
|
+
the mesh.
|
|
492
|
+
value : list of str
|
|
493
|
+
|
|
494
|
+
exemple
|
|
495
|
+
-------
|
|
496
|
+
self.outletsID = ['V156730', 'V200820']
|
|
497
|
+
|
|
498
|
+
"""
|
|
499
|
+
self._outletsID = value
|
|
500
|
+
|
|
501
|
+
@property
|
|
502
|
+
def outlets_shapefile(self):
|
|
503
|
+
"""
|
|
504
|
+
Type:
|
|
505
|
+
-----
|
|
506
|
+
Property/Setter: str | os.PathLike.
|
|
507
|
+
|
|
508
|
+
Descripion:
|
|
509
|
+
-----------
|
|
510
|
+
Path of the shapefile used to position the outlets.
|
|
511
|
+
|
|
512
|
+
exemple
|
|
513
|
+
-------
|
|
514
|
+
self.outlets_shapefile = 'path/to/the/shapefile.shp'
|
|
515
|
+
"""
|
|
516
|
+
return self._outlets_shapefile
|
|
517
|
+
|
|
518
|
+
@outlets_shapefile.setter
|
|
519
|
+
def outlets_shapefile(self, value: None | os.PathLike = None):
|
|
520
|
+
"""
|
|
521
|
+
Setter. Set the path of the shapefile used to position the outlets.
|
|
522
|
+
value : None | os.PathLike
|
|
523
|
+
|
|
524
|
+
exemple
|
|
525
|
+
-------
|
|
526
|
+
self.outlets_shapefile = 'path/to/the/shapefile.shp'
|
|
527
|
+
|
|
528
|
+
"""
|
|
529
|
+
if value is None:
|
|
530
|
+
return
|
|
531
|
+
|
|
532
|
+
if os.path.exists(value):
|
|
533
|
+
self._outlets_shapefile = value
|
|
534
|
+
else:
|
|
535
|
+
raise ValueError(f"'{value}' is not a valid path.")
|
|
536
|
+
|
|
537
|
+
@property
|
|
538
|
+
def smash_parameters(self):
|
|
539
|
+
"""
|
|
540
|
+
Type:
|
|
541
|
+
-----
|
|
542
|
+
Property/Setter: str | os.PathLike.
|
|
543
|
+
|
|
544
|
+
Path to a directory which contain the calibrated smash parameters.
|
|
545
|
+
Each parameter must be stored separetly in a geotiff file
|
|
546
|
+
|
|
547
|
+
exemple
|
|
548
|
+
-------
|
|
549
|
+
self.smash_parameters = 'path/to/the/directory/'
|
|
550
|
+
|
|
551
|
+
"""
|
|
552
|
+
return self._smash_parameters
|
|
553
|
+
|
|
554
|
+
@smash_parameters.setter
|
|
555
|
+
def smash_parameters(self, value: None | os.PathLike = None):
|
|
556
|
+
"""
|
|
557
|
+
Setter. Set the path to a directory where the smash parameters are
|
|
558
|
+
stored.
|
|
559
|
+
value : None | os.PathLike
|
|
560
|
+
|
|
561
|
+
exemple
|
|
562
|
+
-------
|
|
563
|
+
self.smash_parameters = 'path/to/the/directory/'
|
|
564
|
+
|
|
565
|
+
"""
|
|
566
|
+
if value is None:
|
|
567
|
+
return
|
|
568
|
+
|
|
569
|
+
if os.path.isdir(value):
|
|
570
|
+
|
|
571
|
+
if len(os.listdir(value)) == 0:
|
|
572
|
+
raise ValueError(f"'{value}' is an empty directory.")
|
|
573
|
+
|
|
574
|
+
for file in os.listdir(value):
|
|
575
|
+
if not file.endswith(".tif"):
|
|
576
|
+
raise ValueError(
|
|
577
|
+
f"'{value}' contains files other than geotiff .tif format."
|
|
578
|
+
" These files are likely not compatible with SMASH parameters."
|
|
579
|
+
)
|
|
580
|
+
|
|
581
|
+
self._smash_parameters = value
|
|
582
|
+
else:
|
|
583
|
+
raise ValueError(f"'{value}' is not a valid directory.")
|
|
584
|
+
|
|
585
|
+
@property
|
|
586
|
+
def smash_parameters_dt(self):
|
|
587
|
+
"""
|
|
588
|
+
Type:
|
|
589
|
+
-----
|
|
590
|
+
Property/Setter: int | float.
|
|
591
|
+
|
|
592
|
+
Time-step for which the smash_parameters has been originaly calibrated.
|
|
593
|
+
int | float.If not None and if the model parameters is different, the parameters
|
|
594
|
+
"ct", "kexc", "llr" will be transformed according the relation
|
|
595
|
+
described in A.Ficchi, 2017.
|
|
596
|
+
|
|
597
|
+
exemple
|
|
598
|
+
-------
|
|
599
|
+
self.smash_parameters_dt = 900
|
|
600
|
+
|
|
601
|
+
"""
|
|
602
|
+
return self._smash_parameters_dt
|
|
603
|
+
|
|
604
|
+
@smash_parameters_dt.setter
|
|
605
|
+
def smash_parameters_dt(self, value: None | os.PathLike = None):
|
|
606
|
+
"""
|
|
607
|
+
Setter. Set the time-step for which the smash_parameters has been originaly calibrated.
|
|
608
|
+
int | float. If not None and if the model parameters is different, the parameters
|
|
609
|
+
"ct", "kexc", "llr" will be transformed according the relation
|
|
610
|
+
described in A.Ficchi, 2017.
|
|
611
|
+
value : int | float
|
|
612
|
+
|
|
613
|
+
exemple
|
|
614
|
+
-------
|
|
615
|
+
self.smash_parameters_dt = 900.
|
|
616
|
+
|
|
617
|
+
"""
|
|
618
|
+
|
|
619
|
+
self._smash_parameters_dt = value
|
|
620
|
+
|
|
621
|
+
@property
|
|
622
|
+
def outlets_database_fields(self):
|
|
623
|
+
"""
|
|
624
|
+
type:
|
|
625
|
+
----
|
|
626
|
+
Property/Setter: dict
|
|
627
|
+
|
|
628
|
+
Description:
|
|
629
|
+
------------
|
|
630
|
+
A dictionary with a corresponding `key` - `column name`. The 'key' of the dictionary
|
|
631
|
+
must match with desired 'column name' in the selected `outlet_database`.
|
|
632
|
+
Needed keys are:
|
|
633
|
+
|
|
634
|
+
- coord_x : X coordinate of the outlet
|
|
635
|
+
|
|
636
|
+
- coord_y : Y coordinate of the outlet
|
|
637
|
+
|
|
638
|
+
- area : Surface of the catchment
|
|
639
|
+
|
|
640
|
+
- id : Name or label of the outlet
|
|
641
|
+
|
|
642
|
+
exemple
|
|
643
|
+
-------
|
|
644
|
+
self.outlets_database_fields = '{
|
|
645
|
+
"coord_x": "X_L93",
|
|
646
|
+
"coord_y": "Y_L93",
|
|
647
|
+
"area": "SURF",
|
|
648
|
+
"id": "ID_EX",
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
"""
|
|
652
|
+
return self._outlets_database_fields
|
|
653
|
+
|
|
654
|
+
@outlets_database_fields.setter
|
|
655
|
+
def outlets_database_fields(self, value: dict):
|
|
656
|
+
"""
|
|
657
|
+
type:
|
|
658
|
+
----
|
|
659
|
+
Property/Setter: dict
|
|
660
|
+
|
|
661
|
+
Description:
|
|
662
|
+
------------
|
|
663
|
+
A dictionary with a corresponding `key` - `column name`. The 'key' of the dictionary
|
|
664
|
+
must match with desired 'column name' in the selected `outlet_database`.
|
|
665
|
+
Needed keys are:
|
|
666
|
+
- coord_x : X coordinate of the outlet
|
|
667
|
+
- coord_y : Y coordinate of the outlet
|
|
668
|
+
-.area : Surface of the catchment
|
|
669
|
+
- id : Name or label of the outlet
|
|
670
|
+
|
|
671
|
+
exemple
|
|
672
|
+
-------
|
|
673
|
+
self.outlets_database_fields = '{
|
|
674
|
+
"coord_x": "X_L93",
|
|
675
|
+
"coord_y": "Y_L93",
|
|
676
|
+
"area": "SURF",
|
|
677
|
+
"id": "ID_EX",
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
"""
|
|
681
|
+
if sorted(["coord_x", "coord_y", "area", "id"]) == sorted(list(value.keys())):
|
|
682
|
+
self._outlets_database_fields = value
|
|
683
|
+
else:
|
|
684
|
+
raise ValueError(
|
|
685
|
+
f"{value} doe not correspond to any outlets_database_fields."
|
|
686
|
+
" outlets_database_fields must look like"
|
|
687
|
+
" {'coord_x': 'X_L93','coord_y': 'Y_L93','area':'SURF','id':'ID_EX'}"
|
|
688
|
+
)
|
|
689
|
+
self._outlets_database_fields = value
|
|
690
|
+
|
|
691
|
+
@property
|
|
692
|
+
def enhanced_smash_input_data(self):
|
|
693
|
+
"""
|
|
694
|
+
type:
|
|
695
|
+
----
|
|
696
|
+
Property/Setter: bool
|
|
697
|
+
|
|
698
|
+
Description:
|
|
699
|
+
------------
|
|
700
|
+
Use an enhanced version of the smash.model() method. The reading of the input
|
|
701
|
+
atmospheric data functions used by smash have been rewritten in a different way
|
|
702
|
+
provide more options and flexibility.
|
|
703
|
+
- read same type of data like SMASH: precipitation, snow, temperature and
|
|
704
|
+
evapotranspration.
|
|
705
|
+
Support Geotiff format only.
|
|
706
|
+
- Merge all reading function in one.
|
|
707
|
+
- Configure the pattern of the date to search in the filename. Use common date
|
|
708
|
+
formatters. Handle the occurence number (starting from 0) with %n at the end of
|
|
709
|
+
the date pattern. ex: %Y%m%d%H%1.
|
|
710
|
+
- Improve logs: new log clearly warn user about which files have been read and
|
|
711
|
+
which files are missing.
|
|
712
|
+
- Fix a mistake during the reading of the evapotranspration. In SMASH the
|
|
713
|
+
evapotranspiration from the previous day is read instead of the current one.
|
|
714
|
+
- Read several data source by priority: each kind of data may have different source.
|
|
715
|
+
If one is missing, the model will read the second one, ect...
|
|
716
|
+
- Partially handle the reading of the continuous evapotranspiration in an
|
|
717
|
+
operationnal context. To do that, a sim-link of the etp data (delayed by 1 day)
|
|
718
|
+
is created named with the date
|
|
719
|
+
of the current day.
|
|
720
|
+
- Handle time zone to shift the desagregation curve of the PET during the day.
|
|
721
|
+
- Improve the speed of the reading. Technically, an index of the dates and the
|
|
722
|
+
corresponding data files is created. To eficiency run through the long list of data files
|
|
723
|
+
and performs a regex search to match a date, a simple searh algorithm is build on top of
|
|
724
|
+
the main loop to avoid performing a regex on thousand files.
|
|
725
|
+
This improvement is noticable for model running on few time-step. It is particulary
|
|
726
|
+
important when running smash in an operationnal context.
|
|
727
|
+
|
|
728
|
+
new setup options:
|
|
729
|
+
------------------
|
|
730
|
+
prcp_date_pattern=%Y%m%d%H%0
|
|
731
|
+
prcp_directories:
|
|
732
|
+
1 : '/home/maxime/DATA/REUNION/PLUIE_REUNION/tests_tr/ANTILOPE_J1'
|
|
733
|
+
2 : '/home/maxime/DATA/REUNION/PLUIE_REUNION/tests_tr/ANTILOPE_TR'
|
|
734
|
+
3 : '/home/maxime/DATA/REUNION/PLUIE_REUNION/tests_tr/GRID_LESOL_500m'
|
|
735
|
+
pet_directories:
|
|
736
|
+
1 : "/home/maxime/DATA/REUNION/ETPJ_continue"
|
|
737
|
+
2 : "/home/maxime/DATA/REUNION/ETPJ_interannuelle_250_lnZ"
|
|
738
|
+
continuous_pet:
|
|
739
|
+
1: true
|
|
740
|
+
2: false
|
|
741
|
+
timezone: "UTC"
|
|
742
|
+
|
|
743
|
+
"""
|
|
744
|
+
return self._enhanced_smash_input_data
|
|
745
|
+
|
|
746
|
+
@enhanced_smash_input_data.setter
|
|
747
|
+
def enhanced_smash_input_data(self, value: bool):
|
|
748
|
+
"""
|
|
749
|
+
type:
|
|
750
|
+
----
|
|
751
|
+
Property/Setter: bool
|
|
752
|
+
|
|
753
|
+
Description:
|
|
754
|
+
------------
|
|
755
|
+
Use an enhanced version of the smash.model() method. The reading of the input
|
|
756
|
+
atmospheric data functions used by smash have been rewritten in a different way
|
|
757
|
+
provide more options and flexibility.
|
|
758
|
+
- read same type of data like SMASH: precipitation, snow, temperature and
|
|
759
|
+
evapotranspration.
|
|
760
|
+
Support Geotiff format only.
|
|
761
|
+
- Merge all reading function in one.
|
|
762
|
+
- Configure the pattern of the date to search in the filename. Use common date
|
|
763
|
+
formatters. Handle the occurence number (starting from 0) with %n at the end of
|
|
764
|
+
the date pattern. ex: %Y%m%d%H%1.
|
|
765
|
+
- Improve logs: new log clearly warn user about which files have been read and
|
|
766
|
+
which files are missing.
|
|
767
|
+
- Fix a mistake during the reading of the evapotranspration. In SMASH the
|
|
768
|
+
evapotranspiration from the previous day is read instead of the current one.
|
|
769
|
+
- Read several data source by priority: each kind of data may have different source.
|
|
770
|
+
If one is missing, the model will read the second one, ect...
|
|
771
|
+
- Partially handle the reading of the continuous evapotranspiration in an
|
|
772
|
+
operationnal context. To do that, a sim-link of the etp data (delayed by 1 day)
|
|
773
|
+
is created named with the date
|
|
774
|
+
of the current day.
|
|
775
|
+
- Handle time zone to shift the desagregation curve of the PET during the day.
|
|
776
|
+
- Improve the speed of the reading. Technically, an index of the dates and the
|
|
777
|
+
corresponding data files is created. To eficiency run through the long list of data files
|
|
778
|
+
and performs a regex search to match a date, a simple searh algorithm is build on top of
|
|
779
|
+
the main loop to avoid performing a regex on thousand files.
|
|
780
|
+
This improvement is noticable for model running on few time-step. It is particulary
|
|
781
|
+
important when running smash in an operationnal context.
|
|
782
|
+
|
|
783
|
+
new setup options:
|
|
784
|
+
------------------
|
|
785
|
+
prcp_date_pattern=%Y%m%d%H%0
|
|
786
|
+
prcp_directories:
|
|
787
|
+
1 : '/home/maxime/DATA/REUNION/PLUIE_REUNION/tests_tr/ANTILOPE_J1'
|
|
788
|
+
2 : '/home/maxime/DATA/REUNION/PLUIE_REUNION/tests_tr/ANTILOPE_TR'
|
|
789
|
+
3 : '/home/maxime/DATA/REUNION/PLUIE_REUNION/tests_tr/GRID_LESOL_500m'
|
|
790
|
+
pet_directories:
|
|
791
|
+
1 : "/home/maxime/DATA/REUNION/ETPJ_continue"
|
|
792
|
+
2 : "/home/maxime/DATA/REUNION/ETPJ_interannuelle_250_lnZ"
|
|
793
|
+
continuous_pet:
|
|
794
|
+
1: true
|
|
795
|
+
2: false
|
|
796
|
+
timezone: "UTC"
|
|
797
|
+
|
|
798
|
+
"""
|
|
799
|
+
self._enhanced_smash_input_data = value
|