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