wolfhece 2.1.128__py3-none-any.whl → 2.2.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. wolfhece/PyDraw.py +109 -46
  2. wolfhece/PyGui.py +3 -0
  3. wolfhece/PyGuiHydrology.py +24 -24
  4. wolfhece/PyPalette.py +27 -11
  5. wolfhece/PyParams.py +5 -1
  6. wolfhece/PyVertexvectors.py +52 -7
  7. wolfhece/Results2DGPU.py +17 -0
  8. wolfhece/acceptability/acceptability_gui.py +29 -18
  9. wolfhece/acceptability/func.py +23 -21
  10. wolfhece/apps/version.py +2 -2
  11. wolfhece/eikonal.py +1 -1
  12. wolfhece/hydrology/Catchment.py +113 -12
  13. wolfhece/hydrology/Comparison.py +54 -52
  14. wolfhece/hydrology/Optimisation.py +309 -178
  15. wolfhece/hydrology/PostProcessHydrology.py +6 -3
  16. wolfhece/hydrology/RetentionBasin.py +21 -14
  17. wolfhece/hydrology/SubBasin.py +128 -12
  18. wolfhece/hydrology/constant.py +3 -0
  19. wolfhece/hydrology/cst_exchanges.py +364 -38
  20. wolfhece/hydrology/plot_hydrology.py +34 -18
  21. wolfhece/hydrology/read.py +16 -6
  22. wolfhece/lagrangian/particle_system_ui.py +1 -1
  23. wolfhece/lagrangian/particles.py +1 -1
  24. wolfhece/lazviewer/processing/estimate_normals/estimate_normals.cp310-win_amd64.pyd +0 -0
  25. wolfhece/lazviewer/vfuncsdir/vfuncs.cp310-win_amd64.pyd +0 -0
  26. wolfhece/lazviewer/viewer/viewer.exe +0 -0
  27. wolfhece/lazviewer/viewer/viewer_np1_23_5.exe +0 -0
  28. wolfhece/libs/WolfDll.dll +0 -0
  29. wolfhece/libs/Wolf_tools.dll +0 -0
  30. wolfhece/libs/get_infos.cp310-win_amd64.pyd +0 -0
  31. wolfhece/libs/verify_wolf.cp310-win_amd64.pyd +0 -0
  32. wolfhece/libs/wolfogl.cp310-win_amd64.pyd +0 -0
  33. wolfhece/radar/wolfradar.py +75 -22
  34. wolfhece/shapes/__init__.py +0 -0
  35. wolfhece/shapes/circle.py +335 -0
  36. wolfhece/tools2d_dll.py +359 -0
  37. wolfhece/wolf_array.py +3 -2
  38. wolfhece/wolfresults_2D.py +162 -33
  39. {wolfhece-2.1.128.dist-info → wolfhece-2.2.1.dist-info}/METADATA +15 -9
  40. {wolfhece-2.1.128.dist-info → wolfhece-2.2.1.dist-info}/RECORD +43 -39
  41. wolfhece/libs/wolfpy.cp310-win_amd64.pyd +0 -0
  42. {wolfhece-2.1.128.dist-info → wolfhece-2.2.1.dist-info}/WHEEL +0 -0
  43. {wolfhece-2.1.128.dist-info → wolfhece-2.2.1.dist-info}/entry_points.txt +0 -0
  44. {wolfhece-2.1.128.dist-info → wolfhece-2.2.1.dist-info}/top_level.txt +0 -0
@@ -32,8 +32,9 @@ import traceback
32
32
 
33
33
 
34
34
  # %% Constants
35
- DLL_FILE = "WolfDll.dll"
36
- DLL_FILE_DEBUG = "WolfDll_debug.dll"
35
+ DLL_FILE = "WolfDll.dll" # Name of the release DLL
36
+ DLL_FILE_DEBUG = "WolfDll_debug.dll" # Name of the debug DLL
37
+ DLL_FILE_TEST = "WolfDll_test.dll" # Name of the test DLL (to deactivate random numbers generation)
37
38
 
38
39
 
39
40
 
@@ -63,7 +64,7 @@ class CaseOpti(GenMapManager):
63
64
  # super().__init__(splash=splash, *args, **kw)
64
65
 
65
66
  self.launcherDir = ""
66
-
67
+
67
68
  def read_param(self, dir, copyDefault=False, callback=None, workingDir=""):
68
69
 
69
70
  self.launcherDir = dir
@@ -131,13 +132,13 @@ class Optimisation(wx.Frame):
131
132
  # FIXME : this variable is just there before the seperation between the object optimisation and GUI optimisation
132
133
  wx_exists:bool
133
134
 
134
- def __init__(self, parent=None, title="", w=500, h=500, init_wx=True, debugDLL=False):
135
+ def __init__(self, parent=None, title="", w=500, h=500, init_wx=True, debugDLL=False, for_test:bool=False):
135
136
 
136
137
  self.wx_exists = wx.App.Get() is not None # test if wx App is running
137
138
 
138
139
  if self.wx_exists:
139
140
  super(Optimisation, self).__init__(parent, title=title, size=(w,h))
140
-
141
+
141
142
  self.debugDLL = debugDLL
142
143
 
143
144
  self.workingDir = ""
@@ -161,12 +162,15 @@ class Optimisation(wx.Frame):
161
162
  if self.debugDLL:
162
163
  self.load_dll(self.pathDll, DLL_FILE_DEBUG)
163
164
  else:
164
- self.load_dll(self.pathDll, DLL_FILE)
165
+ if for_test:
166
+ self.load_dll(self.pathDll, DLL_FILE_TEST)
167
+ else:
168
+ self.load_dll(self.pathDll, DLL_FILE)
165
169
 
166
170
  # FIXME
167
171
  if self.wx_exists:
168
172
  self.initGUI()
169
-
173
+
170
174
 
171
175
  def initGUI(self):
172
176
 
@@ -224,7 +228,7 @@ class Optimisation(wx.Frame):
224
228
  self.Bind(wx.EVT_MENU, self.test_equifinality_with_Nash, testEquiFinClick)
225
229
  plotEquiFinClick = toolMenu.Append(wx.ID_ANY, 'Plot equifinality with Nash')
226
230
  self.Bind(wx.EVT_MENU, self.plot_equifinality, plotEquiFinClick)
227
-
231
+
228
232
 
229
233
  # Creation of the Lauch Menu
230
234
  launchMenu = wx.Menu()
@@ -345,10 +349,10 @@ class Optimisation(wx.Frame):
345
349
  self.enable_MenuBar("Param files")
346
350
  self.enable_MenuBar("Launch")
347
351
 
348
-
352
+
349
353
  def load(self, event, workingDir:str="", fileName:str=""):
350
354
 
351
- # Selection of the main
355
+ # Selection of the main
352
356
  if workingDir=="":
353
357
  idir=wx.FileDialog(None,"Choose an optimatimisation file",wildcard='Fichiers param (*.param)|*.param')
354
358
  if idir.ShowModal() == wx.ID_CANCEL:
@@ -369,7 +373,11 @@ class Optimisation(wx.Frame):
369
373
  self.optiParam = Wolf_Param(to_read=True, filename=fileOpti, title="test_opti",toShow=False)
370
374
  initDir = self.optiParam.get_param("Optimizer","dir")
371
375
  isOk, initDir = check_path(initDir, prefix=readDir, applyCWD=True)
372
- #
376
+
377
+ if initDir is None:
378
+ logging.error("ERROR: in path of initDir")
379
+ return
380
+ #
373
381
  if os.path.samefile(readDir, initDir):
374
382
  self.workingDir = initDir
375
383
  else:
@@ -409,14 +417,14 @@ class Optimisation(wx.Frame):
409
417
  curCase = paramMenu.Append(newId, curName, caseMenu)
410
418
  else:
411
419
  print("WARNING : this scenario was not implemented yet. This might induce an error!")
412
- # iItem =
420
+ # iItem =
413
421
  curCase = paramMenu.Replace(iItem)
422
+ self.Bind(wx.EVT_MENU, newCase.show_launcherParam, curCase)
423
+ newCase.idMenuItem = newId
414
424
  else:
415
425
  refDir = newCase.launcherParam.get_param("Calculs","Répertoire simulation de référence")
416
426
  isOk, refDir = check_path(refDir, prefix=launcherDir, applyCWD=True)
417
427
  newCase.mydro = HydrologyModel(dir=refDir)
418
- self.Bind(wx.EVT_MENU, newCase.show_launcherParam, curCase)
419
- newCase.idMenuItem = newId
420
428
  self.myCases.append(newCase)
421
429
 
422
430
 
@@ -433,14 +441,15 @@ class Optimisation(wx.Frame):
433
441
  self.init_with_default_lumped()
434
442
 
435
443
  # Let all the menu bars be available in GUI
436
- self.enable_MenuBar("Param files")
437
- self.enable_MenuBar("Launch")
438
- self.enable_MenuBar("Tools")
439
- if self.debugDLL:
440
- self.enable_MenuBar("Debug")
441
-
444
+ if self.wx_exists:
445
+ self.enable_MenuBar("Param files")
446
+ self.enable_MenuBar("Launch")
447
+ self.enable_MenuBar("Tools")
448
+ if self.debugDLL:
449
+ self.enable_MenuBar("Debug")
442
450
 
443
- def apply_optim(self, event, idLauncher:int=0,
451
+
452
+ def apply_optim(self, event, idLauncher:int=0,
444
453
  replace_only_if_better:bool=False, optim_params:np.ndarray=None):
445
454
  """
446
455
  Apply optimal parameters based on the results file of the optimisation : ".rpt".
@@ -474,7 +483,7 @@ class Optimisation(wx.Frame):
474
483
  return bestParams
475
484
  else:
476
485
  return None
477
-
486
+
478
487
 
479
488
 
480
489
  # Initialisation of the Optimizer from Fortran
@@ -483,7 +492,7 @@ class Optimisation(wx.Frame):
483
492
  self.init_optimizer()
484
493
 
485
494
 
486
-
495
+
487
496
  def init_with_default_lumped(self, replace:bool=False):
488
497
  # if replace:
489
498
  # r = wx.ID_NO
@@ -613,7 +622,7 @@ class Optimisation(wx.Frame):
613
622
  if sorted_id == 0:
614
623
  self.myParams[i]["junction_name"] = curCatch.junctionOut
615
624
  else:
616
- cur_id = list(curCatch.dictIdConversion.keys())[list(curCatch.dictIdConversion.values()).index(sorted_id)]
625
+ cur_id = list(curCatch.dictIdConversion.keys())[list(curCatch.dictIdConversion.values()).index(sorted_id)]
617
626
  self.myParams[i]["junction_name"] = curCatch.subBasinDict[cur_id].name
618
627
 
619
628
  else:
@@ -640,7 +649,7 @@ class Optimisation(wx.Frame):
640
649
 
641
650
  optimFileTxt = os.path.join(self.workingDir, nameTMP+".rpt")
642
651
  optimFileBin = os.path.join(self.workingDir, nameTMP+".rpt.dat")
643
-
652
+
644
653
  isOk, optimFileBin = check_path(optimFileBin)
645
654
  if isOk>0:
646
655
  optimFile = optimFileBin
@@ -671,7 +680,7 @@ class Optimisation(wx.Frame):
671
680
 
672
681
 
673
682
  def init_with_reference(self, idLauncher=0):
674
-
683
+
675
684
  curCase = self.myCases[idLauncher]
676
685
  refCatch = curCase.refCatchment
677
686
 
@@ -728,14 +737,19 @@ class Optimisation(wx.Frame):
728
737
  isOk, defaultPath = check_path(defaultPath, launcherDir)
729
738
  if isOk<0:
730
739
  defaultPath = ""
731
- idir=wx.FileDialog(None,"Choose a reference file",wildcard='Fichiers post-processing (*.postPro)|*.postPro',defaultDir=defaultPath)
732
- if idir.ShowModal() == wx.ID_CANCEL:
733
- print("Post process cancelled!")
740
+ if self.wx_exists:
741
+ idir=wx.FileDialog(None,"Choose a reference file",wildcard='Fichiers post-processing (*.postPro)|*.postPro',defaultDir=defaultPath)
742
+ if idir.ShowModal() == wx.ID_CANCEL:
743
+ print("Post process cancelled!")
744
+ idir.Destroy()
745
+ refFileName = idir.GetPath()
746
+ refDir = idir.GetDirectory()
734
747
  idir.Destroy()
735
-
736
- refFileName = idir.GetPath()
737
- refDir = idir.GetDirectory()
738
- idir.Destroy()
748
+ else:
749
+ refDir = defaultPath
750
+ refFileName = join(refDir, "Input.postPro")
751
+
752
+
739
753
 
740
754
  myPostPro = PostProcessHydrology(postProFile=refFileName)
741
755
  # Recover the Catchment object
@@ -855,14 +869,14 @@ class Optimisation(wx.Frame):
855
869
 
856
870
  def plot_optim_jct(self, event, idLauncher=0):
857
871
  # this function will plot the hydrographs with the optimal parameters compared to the objective
858
-
872
+
859
873
  refCatch:Catchment = self.myCases[idLauncher].refCatchment
860
874
 
861
875
  # Construction of the Measures, in other words the references
862
876
  compMeas = []
863
877
  if self.myStations==[]:
864
878
  self.set_compare_stations(idLauncher=idLauncher)
865
-
879
+
866
880
  compMeas = list(self.compareSubBasins.values())
867
881
 
868
882
  # Construction of the wx window for plot
@@ -870,7 +884,7 @@ class Optimisation(wx.Frame):
870
884
 
871
885
  self.axes = figure.add_subplot(111)
872
886
 
873
-
887
+
874
888
  r = wx.MessageDialog(
875
889
  None, "Do you want to add a table?", "Plot question",
876
890
  wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION
@@ -960,7 +974,7 @@ class Optimisation(wx.Frame):
960
974
  pointer_p = p.ctypes.data_as(ct.POINTER(ct.c_double))
961
975
 
962
976
  print("Launch a Fortran procedure")
963
- obj_fct = self.dllFortran.evaluate_model_optimizer_py(ct.byref(ct.c_int(idOpti)),
977
+ obj_fct = self.dllFortran.evaluate_model_optimizer_py(ct.byref(ct.c_int(idOpti)),
964
978
  pointerDims,
965
979
  pointer_p)
966
980
  print("End of Fortran procedure")
@@ -1296,7 +1310,7 @@ class Optimisation(wx.Frame):
1296
1310
  self.set_compare_stations(idLauncher=idLauncher)
1297
1311
  sortJct = self.myStations
1298
1312
  readDict = self.compareFilesDict
1299
- # Get the initial number of intervals
1313
+ # Get the initial number of intervals
1300
1314
  # -> these can evolve according to the measurement available at each station
1301
1315
  is_ok = self._save_opti_intervals()
1302
1316
  if is_ok<0:
@@ -1325,7 +1339,7 @@ class Optimisation(wx.Frame):
1325
1339
  cur_intervals = self.select_opti_intervals(all_intervals=all_intervals, stationOut=stationOut, filter_nan=True)
1326
1340
  self.save_opti_dates_to_file(cur_intervals)
1327
1341
  is_ok = self._save_opti_intervals(stationOut=stationOut, intervals=cur_intervals)
1328
-
1342
+
1329
1343
  # Rename the result file
1330
1344
  self.optiParam.change_param("Optimizer", "fname", stationOut)
1331
1345
  self.optiParam.SavetoFile(None)
@@ -1336,7 +1350,7 @@ class Optimisation(wx.Frame):
1336
1350
  # Prepare the potential discontinuous simulation
1337
1351
  # FIXME : to potentially uncomment or removed : probably remove because we want to generate the complete event simulations to progress in the optimisation
1338
1352
  # self.prepare_simulation(opti_intervals=cur_intervals, idLauncher=idLauncher)
1339
- # Check the initial parameters and if they are forced
1353
+ # Check the initial parameters and if they are forced
1340
1354
  init_params = self.get_initial_parameters()
1341
1355
  ## loop on the number of different optimisation attempt we would like for each station
1342
1356
  best_params_overall = None
@@ -1361,12 +1375,12 @@ class Optimisation(wx.Frame):
1361
1375
  if best_params_overall is None:
1362
1376
  best_params_overall = best_params
1363
1377
  elif best_params[-1] > best_params_overall[-1]:
1364
- best_params_overall = best_params
1365
- i_best_overal = cur_i
1378
+ best_params_overall = best_params
1379
+ i_best_overal = cur_i
1366
1380
  # copy the optimisation results to save it on the disk
1367
- shutil.copyfile(os.path.join(self.workingDir, stationOut+".rpt.dat"),
1381
+ shutil.copyfile(os.path.join(self.workingDir, stationOut+".rpt.dat"),
1368
1382
  os.path.join(self.workingDir, stationOut+"_"+str(cur_i+1)+".rpt.dat"))
1369
- shutil.copyfile(os.path.join(self.workingDir, stationOut+".rpt"),
1383
+ shutil.copyfile(os.path.join(self.workingDir, stationOut+".rpt"),
1370
1384
  os.path.join(self.workingDir, stationOut+"_"+str(cur_i+1)+".rpt"))
1371
1385
  cur_i += 1
1372
1386
  # Apply the best parameters overall attemps
@@ -1374,12 +1388,12 @@ class Optimisation(wx.Frame):
1374
1388
  # Reset the init parameters
1375
1389
  self.reset_init_params(init_params)
1376
1390
  # copy the optimisation results to save it on the disk
1377
- shutil.copyfile(os.path.join(self.workingDir, stationOut+"_"+str(i_best_overal+1)+".rpt.dat"),
1391
+ shutil.copyfile(os.path.join(self.workingDir, stationOut+"_"+str(i_best_overal+1)+".rpt.dat"),
1378
1392
  os.path.join(self.workingDir, stationOut+".rpt.dat"))
1379
- shutil.copyfile(os.path.join(self.workingDir, stationOut+"_"+str(i_best_overal+1)+".rpt"),
1393
+ shutil.copyfile(os.path.join(self.workingDir, stationOut+"_"+str(i_best_overal+1)+".rpt"),
1380
1394
  os.path.join(self.workingDir, stationOut+".rpt"))
1381
-
1382
-
1395
+
1396
+
1383
1397
  # Simulation with the best parameters
1384
1398
  self.compute_distributed_hydro_model()
1385
1399
  cur_p = best_params_overall[:-1]
@@ -1448,8 +1462,8 @@ class Optimisation(wx.Frame):
1448
1462
  tf = time_mod.process_time()
1449
1463
  print("Time in update_hydro() : ", tf-t0)
1450
1464
  return isOk
1451
-
1452
-
1465
+
1466
+
1453
1467
  def reload_hydro(self, idCompar, firstLevel:int=1, lastLevel:int=-1, fromStation:str="", updateAll:bool=False):
1454
1468
 
1455
1469
  curCatch:Catchment = self.myCases[0].refCatchment
@@ -1683,7 +1697,7 @@ class Optimisation(wx.Frame):
1683
1697
 
1684
1698
  return isOk
1685
1699
 
1686
-
1700
+
1687
1701
  ## Update the dictionnaries of myParams if any changes is identified
1688
1702
  # TODO : Generalised for all type of changes and all the necessary tests -> So far just update the junction name
1689
1703
  def update_myParams(self, idLauncher=0):
@@ -1699,10 +1713,10 @@ class Optimisation(wx.Frame):
1699
1713
  if sorted_id == 0:
1700
1714
  self.myParams[i]["junction_name"] = curCatch.junctionOut
1701
1715
  else:
1702
- cur_id = list(curCatch.dictIdConversion.keys())[list(curCatch.dictIdConversion.values()).index(sorted_id)]
1716
+ cur_id = list(curCatch.dictIdConversion.keys())[list(curCatch.dictIdConversion.values()).index(sorted_id)]
1703
1717
  self.myParams[i]["junction_name"] = curCatch.subBasinDict[cur_id].name
1704
1718
 
1705
-
1719
+
1706
1720
 
1707
1721
  ## Function to determine the compare stations, compare files and the compare station SubBasin objects for each station
1708
1722
  def set_compare_stations(self, idLauncher):
@@ -1721,7 +1735,7 @@ class Optimisation(wx.Frame):
1721
1735
  # Sort all the junctions by level
1722
1736
  self.myStations = refCatch.sort_level_given_junctions(list(readDict.keys()), changeNames=False)
1723
1737
  # Prepare the SubBasin compare objects for each station.
1724
- self.compareSubBasins = {stationOut: SubBasin(name=stationOut, _model=cst.compare_opti, _workingDir=self.workingDir)
1738
+ self.compareSubBasins = {stationOut: SubBasin(name=stationOut, _model=cst.compare_opti, _workingDir=self.workingDir)
1725
1739
  for stationOut in self.myStations}
1726
1740
  # This loop read all the measure and init the hydro surface of each SubBasin element
1727
1741
  for key, cur_obj in self.compareSubBasins.items():
@@ -1742,11 +1756,11 @@ class Optimisation(wx.Frame):
1742
1756
  self.Destroy()
1743
1757
 
1744
1758
  wx.Exit()
1745
-
1746
-
1759
+
1760
+
1747
1761
  def get_all_outlets(self, event, idLauncher:int=0):
1748
1762
  # this function will save all the hydrographs with the optimal parameters
1749
-
1763
+
1750
1764
  refCatch:Catchment = self.myCases[idLauncher].refCatchment
1751
1765
  refCatch.save_ExcelFile_noLagTime()
1752
1766
 
@@ -1756,7 +1770,7 @@ class Optimisation(wx.Frame):
1756
1770
  refCatch:Catchment = self.myCases[idLauncher].refCatchment
1757
1771
  refCatch.save_ExcelFile_inlets_noLagTime()
1758
1772
 
1759
-
1773
+
1760
1774
  def plot_all_landuses(self, event, idLauncher:int=0):
1761
1775
  # this function plots the landuses of all hydro subbasins
1762
1776
  refCatch:Catchment = self.myCases[idLauncher].refCatchment
@@ -1773,7 +1787,7 @@ class Optimisation(wx.Frame):
1773
1787
  # - the ".rpt" file of the results of an optimisation should be present
1774
1788
  # - the optimal paramters will be replaced in their respective param files
1775
1789
  # - the timeDelays will then be updated either with :
1776
- # - Python paramters itself
1790
+ # - Python paramters itself
1777
1791
  # - an estimation from the runnof model
1778
1792
  # Once all the optimal parameters are applied, a new simulation is launched to generate the "best" hydrograph
1779
1793
  def generate_semiDist_optim_simul(self, event, idOpti=1,idLauncher:int=0):
@@ -1811,7 +1825,7 @@ class Optimisation(wx.Frame):
1811
1825
  self.optiParam.change_param("Optimizer", "fname", stationOut)
1812
1826
  self.optiParam.SavetoFile(None)
1813
1827
  self.optiParam.Reload(None)
1814
- #
1828
+ #
1815
1829
  self.update_myParams(idLauncher)
1816
1830
  # Preparing the dictionnaries of Parameters to be updated -> not just useful for calibration here !
1817
1831
  self.prepare_calibration_timeDelay(stationOut=stationOut)
@@ -1828,7 +1842,7 @@ class Optimisation(wx.Frame):
1828
1842
  # All upstream elements of a reference will be fixed
1829
1843
  doneList.append(stationOut)
1830
1844
 
1831
-
1845
+
1832
1846
  def generate_semiDist_debug_simul(self, event, idOpti=1,idLauncher:int=0):
1833
1847
 
1834
1848
  curCatch:Catchment = self.myCases[idLauncher].refCatchment
@@ -1864,7 +1878,7 @@ class Optimisation(wx.Frame):
1864
1878
  self.optiParam.change_param("Optimizer", "fname", stationOut)
1865
1879
  self.optiParam.SavetoFile(None)
1866
1880
  self.optiParam.Reload(None)
1867
- #
1881
+ #
1868
1882
  self.update_myParams(idLauncher)
1869
1883
  # TO DO -> adapt all the debug_info files
1870
1884
  # write it here !!!!
@@ -1879,9 +1893,13 @@ class Optimisation(wx.Frame):
1879
1893
  doneList.append(stationOut)
1880
1894
 
1881
1895
 
1882
- def read_all_attempts_SA(self, format="rpt", all_attempts=False, filter_repetitions=True):
1896
+ def read_all_attempts_SA(self, format="rpt", all_attempts=False, filter_repetitions=True, stationOut:str=""):
1897
+
1898
+ if stationOut=="":
1899
+ nameTMP = self.optiParam.get_param("Optimizer","fname")
1900
+ else:
1901
+ nameTMP = stationOut
1883
1902
 
1884
- nameTMP = self.optiParam.get_param("Optimizer","fname")
1885
1903
  if all_attempts:
1886
1904
  nb_iter_from_random = self.optiParam.get_param("Optimizer","nb iter from random initial conditions",
1887
1905
  default_value=1)
@@ -1906,7 +1924,7 @@ class Optimisation(wx.Frame):
1906
1924
  list_ObjFct = []
1907
1925
  line = 0
1908
1926
  for raw in data_reader:
1909
- if(line<3):
1927
+ if(line<3):
1910
1928
  line += 1
1911
1929
  continue
1912
1930
  if(len(raw)<=1):
@@ -1918,11 +1936,11 @@ class Optimisation(wx.Frame):
1918
1936
  line += 1
1919
1937
  matrixParam = np.vstack((matrixParam,
1920
1938
  np.array(list_param).astype("double")))
1921
- vectorObjFct = np.append(vectorObjFct,
1939
+ vectorObjFct = np.append(vectorObjFct,
1922
1940
  np.array(list_ObjFct).astype("double"))
1923
1941
  except:
1924
1942
  wx.MessageBox(_('The best parameters file is not found!'), _('Error'), wx.OK|wx.ICON_ERROR)
1925
-
1943
+
1926
1944
  elif format==".dat":
1927
1945
  for cur_file in all_names:
1928
1946
  optimFile = os.path.join(self.workingDir, cur_file+".rpt.dat")
@@ -1935,17 +1953,17 @@ class Optimisation(wx.Frame):
1935
1953
 
1936
1954
  if filter_repetitions:
1937
1955
  logging.info("Filtering the repetitions in the attempts!")
1938
- filter_matrix, indices, inverse, counts = np.unique(matrixParam, axis=0,
1939
- return_index=True,
1940
- return_inverse=True,
1956
+ filter_matrix, indices, inverse, counts = np.unique(matrixParam, axis=0,
1957
+ return_index=True,
1958
+ return_inverse=True,
1941
1959
  return_counts=True)
1942
1960
  vectorObjFct = vectorObjFct[indices]
1943
1961
  matrixParam = filter_matrix
1944
1962
  logging.info("The max number of repetitions = "+ str(np.max(counts)))
1945
-
1963
+
1946
1964
  return matrixParam, vectorObjFct
1947
-
1948
-
1965
+
1966
+
1949
1967
  def apply_optim_2_params(self, params:np.array, idLauncher=0):
1950
1968
 
1951
1969
  refCatch:Catchment = self.myCases[idLauncher].refCatchment
@@ -1955,9 +1973,9 @@ class Optimisation(wx.Frame):
1955
1973
  or len(self.curParams_vec_F) != self.nbParams:
1956
1974
 
1957
1975
  self.curParams_vec_F = np.empty((self.nbParams,), dtype=ct.c_double, order='F')
1958
-
1976
+
1959
1977
  myModelDict = cste.modelParamsDict[myModel]["Parameters"]
1960
-
1978
+
1961
1979
  for cur_effsub in range(len(refCatch.myEffSubBasins)):
1962
1980
 
1963
1981
  filePath = os.path.join(refCatch.workingDir, "Subbasin_" + str(refCatch.myEffSortSubBasins[cur_effsub]))
@@ -1972,20 +1990,24 @@ class Optimisation(wx.Frame):
1972
1990
  if cur_sub.iDSorted != refCatch.myEffSortSubBasins[cur_effsub]:
1973
1991
  continue
1974
1992
  self.myParams[i+1]["value"] = params[i]
1975
- fileName = myModelDict[int(myType)]["File"]
1976
- myGroup = myModelDict[int(myType)]["Group"]
1977
- myKey = myModelDict[int(myType)]["Key"]
1978
1993
  if "Convertion Factor" in myModelDict[int(myType)]:
1979
1994
  convFact = myModelDict[int(myType)]["Convertion Factor"]
1980
1995
  else:
1981
1996
  convFact = 1.0
1982
- tmpWolf = Wolf_Param(to_read=True, filename=os.path.join(filePath,fileName),toShow=False, init_GUI=False)
1983
- tmpWolf.change_param(myGroup, myKey, params[i]/convFact)
1984
- tmpWolf.SavetoFile(None)
1985
- # tmpWolf.OnClose(None)
1986
- tmpWolf = None
1997
+ all_files = myModelDict[int(myType)]["File"]
1998
+ if type(all_files) is not list:
1999
+ fileName = myModelDict[int(myType)]["File"]
2000
+ myGroup = myModelDict[int(myType)]["Group"]
2001
+ myKey = myModelDict[int(myType)]["Key"]
2002
+ self.write_one_opti_param(filePath, fileName, myGroup, myKey, params[i], convers_factor=convFact)
2003
+ else:
2004
+ for iFile in range(len(all_files)):
2005
+ fileName = all_files[iFile]
2006
+ myGroup = myModelDict[int(myType)]["Group"][iFile]
2007
+ myKey = myModelDict[int(myType)]["Key"][iFile]
2008
+ self.write_one_opti_param(filePath, fileName, myGroup, myKey, params[i], convers_factor=convFact)
1987
2009
  else:
1988
-
2010
+
1989
2011
  self.curParams_vec_F[i] = params[i]
1990
2012
  self.update_timeDelay(i+1)
1991
2013
  refCatch.save_timeDelays([self.myParams[i+1]["junction_name"]])
@@ -2026,7 +2048,7 @@ class Optimisation(wx.Frame):
2026
2048
 
2027
2049
  myModel = self.myCases[idLauncher].refCatchment.myModel
2028
2050
  nbParamsModel = cste.modelParamsDict[myModel]["Nb"]*len(cur_opti.refCatchment.myEffSubBasins)
2029
-
2051
+
2030
2052
  for i in range(1,nb_params+1):
2031
2053
  curParam = "param_" + str(i)
2032
2054
  curType = int(paramDict.get_param(curParam, "type_of_data"))
@@ -2044,7 +2066,7 @@ class Optimisation(wx.Frame):
2044
2066
  self.myCases[idLauncher].launcherParam.change_param("Paramètres à varier", "Nombre de paramètres à varier", nb_params)
2045
2067
 
2046
2068
  return
2047
-
2069
+
2048
2070
 
2049
2071
  def _read_opti_intervals(self, idLauncher:int=0)->list[tuple[datetime.datetime, datetime.datetime]]:
2050
2072
  """
@@ -2060,7 +2082,7 @@ class Optimisation(wx.Frame):
2060
2082
  # if isOk<0:
2061
2083
  # logging.error("The file compare.txt is not found!")
2062
2084
  # return
2063
-
2085
+
2064
2086
  # Read the comparison file
2065
2087
  if self.myStations==[]:
2066
2088
  self.set_compare_stations(idLauncher=idLauncher)
@@ -2068,7 +2090,7 @@ class Optimisation(wx.Frame):
2068
2090
  nb_comparison = self.comparHowParam.get_param("Comparison global characteristics", "nb")
2069
2091
  str_di = "date begin"
2070
2092
  str_df = "date end"
2071
-
2093
+
2072
2094
  intervals = []
2073
2095
  for icomp in range(1, nb_comparison+1):
2074
2096
  cur_key = " ".join(["Comparison", str(icomp)])
@@ -2087,15 +2109,15 @@ class Optimisation(wx.Frame):
2087
2109
 
2088
2110
 
2089
2111
  return intervals
2090
-
2091
2112
 
2092
- def _save_opti_intervals(self, idLauncher:int=0, stationOut:str="",
2113
+
2114
+ def _save_opti_intervals(self, idLauncher:int=0, stationOut:str="",
2093
2115
  intervals:list[tuple[datetime.datetime, datetime.datetime]]=None)->int:
2094
2116
  if stationOut == "":
2095
2117
  suffix = "0"
2096
2118
  else:
2097
2119
  suffix = stationOut
2098
-
2120
+
2099
2121
  if intervals is None:
2100
2122
  self.all_intervals = self._read_opti_intervals(idLauncher=idLauncher)
2101
2123
 
@@ -2116,7 +2138,7 @@ class Optimisation(wx.Frame):
2116
2138
  return -1
2117
2139
  else:
2118
2140
  return 0
2119
-
2141
+
2120
2142
 
2121
2143
  def select_opti_intervals(self, all_intervals:list[tuple[datetime.datetime, datetime.datetime]]=None,
2122
2144
  idLauncher:int=0, stationOut="", filter_nan:bool=True)->list[tuple]:
@@ -2130,7 +2152,7 @@ class Optimisation(wx.Frame):
2130
2152
  """
2131
2153
  cur_opti = self.myCases[idLauncher]
2132
2154
  cur_ref = cur_opti.refCatchment
2133
-
2155
+
2134
2156
  if stationOut == "":
2135
2157
  stationOut = cur_ref.junctionOut
2136
2158
 
@@ -2140,30 +2162,30 @@ class Optimisation(wx.Frame):
2140
2162
  # id_ok= self._save_opti_intervals(idLauncher=idLauncher)
2141
2163
  # if id_ok<0:
2142
2164
  # return None
2143
-
2165
+
2144
2166
  else:
2145
2167
  all_intervals = self.all_intervals
2146
2168
 
2147
2169
  if self.myStations==[]:
2148
2170
  self.set_compare_stations(idLauncher=idLauncher)
2149
-
2171
+
2150
2172
  keyBasin = cur_ref.get_key_catchmentDict(stationOut)
2151
2173
  cur_basin = cur_ref.catchmentDict[keyBasin]
2152
2174
 
2153
2175
  # Select the optimisation intervals that are relevant according to the available measures
2154
2176
  effective_intv = [interv for interv in all_intervals if interv[0]>=cur_basin.dateBegin and interv[1]<=cur_basin.dateEnd]
2155
2177
  if filter_nan:
2156
- effective_intv = self._define_intervals_with_nan_measures(effective_intv, self.compareSubBasins,
2178
+ effective_intv = self._define_intervals_with_nan_measures(effective_intv, self.compareSubBasins,
2157
2179
  idLauncher=idLauncher, stationOut=stationOut)
2158
2180
 
2159
2181
  return effective_intv
2160
-
2161
-
2162
- def _define_intervals_with_nan_measures(self, intervals: list[tuple[datetime.datetime, datetime.datetime]], measures: dict[str, SubBasin],
2182
+
2183
+
2184
+ def _define_intervals_with_nan_measures(self, intervals: list[tuple[datetime.datetime, datetime.datetime]], measures: dict[str, SubBasin],
2163
2185
  idLauncher: int = 0, stationOut: str = ""):
2164
2186
  """
2165
2187
  Defines new intervals excluding all NaN measures based on the given intervals and measures dictionary.
2166
- For instance, if there is continuous NaN measures within a given interval, the function will split
2188
+ For instance, if there is continuous NaN measures within a given interval, the function will split
2167
2189
  that interval into smaller that do not contain NaN measures.
2168
2190
 
2169
2191
  Args:
@@ -2182,15 +2204,15 @@ class Optimisation(wx.Frame):
2182
2204
  if stationOut not in measures:
2183
2205
  logging.error("The stationOut is not in the measures dictionary!")
2184
2206
  return None
2185
-
2207
+
2186
2208
  cur_el = measures[stationOut]
2187
2209
  hydro = cur_el.get_myHydro()
2188
2210
  time = cur_el.time
2189
2211
  # get the indices of the nan values
2190
2212
  non_nan_locations = ~np.isnan(hydro)
2191
2213
  within_intervals = np.sum(
2192
- [(time >= datetime.datetime.timestamp(interv[0])) *
2193
- (time <= datetime.datetime.timestamp(interv[1]))
2214
+ [(time >= datetime.datetime.timestamp(interv[0])) *
2215
+ (time <= datetime.datetime.timestamp(interv[1]))
2194
2216
  for interv in intervals],
2195
2217
  axis=0) > 0
2196
2218
  # Both conditions should be satisfied
@@ -2200,7 +2222,7 @@ class Optimisation(wx.Frame):
2200
2222
  # i.e. when the index difference is not 1
2201
2223
  # +1 as the np.diff is one element sooner than nan_locations: diff[0]=v[1]-v[0]
2202
2224
  group_starts = np.where(np.diff(all_conditions) != 1)[0] + 1
2203
-
2225
+
2204
2226
  # Add 0 as it is the first index of the first group
2205
2227
  group_starts = np.insert(group_starts, 0, 0)
2206
2228
 
@@ -2209,18 +2231,18 @@ class Optimisation(wx.Frame):
2209
2231
 
2210
2232
  # Get the timestamps of the first and last nan element and form groups of discontinuities
2211
2233
  iterv_timestamp = [(time[all_conditions[i_i]], time[all_conditions[i_f]]) for i_i, i_f in zip(group_starts, group_ends)]
2212
- interv_dates = [(datetime.datetime.fromtimestamp(iterv[0],tz=datetime.timezone.utc),
2234
+ interv_dates = [(datetime.datetime.fromtimestamp(iterv[0],tz=datetime.timezone.utc),
2213
2235
  datetime.datetime.fromtimestamp(iterv[1], tz=datetime.timezone.utc))
2214
2236
  for iterv in iterv_timestamp]
2215
2237
 
2216
2238
  return interv_dates
2217
-
2239
+
2218
2240
 
2219
2241
  def save_opti_dates_to_file(self, opti_dates:list[tuple[datetime.datetime,datetime.datetime]]):
2220
2242
  """
2221
2243
  Here the procedure is saving the intervals of dates for calibration in the compare.how.param
2222
2244
  """
2223
- # Verifications
2245
+ # Verifications
2224
2246
  assert len(opti_dates)>0, "The list of dates is empty!"
2225
2247
  for i_opti in opti_dates:
2226
2248
  assert i_opti[1]>i_opti[0], "The start date is not lower than the end date!"
@@ -2251,16 +2273,16 @@ class Optimisation(wx.Frame):
2251
2273
  # Force the initial parameters to be defined randomly
2252
2274
  self.saParam.change_param("Initial parameters", "Read initial parameters?", 0)
2253
2275
  return
2254
-
2276
+
2255
2277
  # In the following code, we apply the best parameters to the initial parameters
2256
2278
  self.saParam.change_param("Initial parameters", "Read initial parameters?", 1)
2257
2279
  for i in range(self.nbParams):
2258
2280
  self.saParam.change_param("Initial parameters", " ".join(["Parameter",str(i+1)]), best_params[i])
2259
-
2281
+
2260
2282
  self.saParam.SavetoFile(None)
2261
2283
  self.saParam.Reload(None)
2262
2284
 
2263
-
2285
+
2264
2286
  def get_initial_parameters(self)-> np.array:
2265
2287
  read_IP = self.saParam.get_param("Initial parameters", "Read initial parameters?")
2266
2288
  if read_IP == 1:
@@ -2268,12 +2290,12 @@ class Optimisation(wx.Frame):
2268
2290
  init_params = np.zeros(self.nbParams+1)
2269
2291
  for i in range(self.nbParams):
2270
2292
  init_params[i] = self.saParam.get_param("Initial parameters", " ".join(["Parameter",str(i+1)]))
2271
- init_params[-1] = -sys.float_info.max
2293
+ init_params[-1] = -sys.float_info.max
2272
2294
  else:
2273
2295
  init_params = None
2274
-
2296
+
2275
2297
  return init_params
2276
-
2298
+
2277
2299
 
2278
2300
  def reset_init_params(self, init_params:np.array):
2279
2301
  if init_params is None:
@@ -2283,7 +2305,7 @@ class Optimisation(wx.Frame):
2283
2305
  print("Reset init params : ", init_params)
2284
2306
  self.saParam.SavetoFile(None)
2285
2307
  self.saParam.Reload(None)
2286
-
2308
+
2287
2309
 
2288
2310
  def extract_internal_variables(self, event, idLauncher:int=0, to_plot:bool=True):
2289
2311
  curCatch:Catchment = self.myCases[idLauncher].refCatchment
@@ -2311,7 +2333,7 @@ class Optimisation(wx.Frame):
2311
2333
  dlg = wx.MessageDialog(None, "Internal variables were detected! Do you still want to launch a detailed simulation ?", "Warning", wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
2312
2334
  r = dlg.ShowModal()
2313
2335
  if r == wx.ID_YES:
2314
- to_generate = True
2336
+ to_generate = True
2315
2337
  dlg.Destroy()
2316
2338
  # FIXME : ADD the terminal
2317
2339
  else:
@@ -2319,7 +2341,7 @@ class Optimisation(wx.Frame):
2319
2341
  # Enter here if a detailed simulation is required
2320
2342
  if to_generate:
2321
2343
  curCatch.activate_all_internal_variables()
2322
- self.generate_semiDist_optim_simul(None, idLauncher=idLauncher)
2344
+ self.generate_semiDist_optim_simul(None, idLauncher=idLauncher)
2323
2345
  all_x = curCatch.get_all_x_production()
2324
2346
  all_iv = curCatch.get_all_iv_production()
2325
2347
 
@@ -2333,18 +2355,18 @@ class Optimisation(wx.Frame):
2333
2355
  all_frac = curCatch.plot_all_fractions(all_fractions=all_frac, to_show=True, range_data=list(interv))
2334
2356
 
2335
2357
  return all_x, all_iv, all_frac
2336
-
2358
+
2337
2359
 
2338
2360
  def _check_presence_of_iv(self, idLauncher:int=0):
2339
2361
  curCatch:Catchment = self.myCases[idLauncher].refCatchment
2340
2362
  return curCatch.check_presence_of_iv()
2341
-
2342
-
2363
+
2364
+
2343
2365
  def plot_Nash_vs_Qexcess(self, event, idLauncher:int=0):
2344
2366
  curCatch:Catchment = self.myCases[idLauncher].refCatchment
2345
2367
  all_params, all_nash = self.read_all_attempts_SA(format=".dat")
2346
2368
  nb_tests = np.shape(all_nash)[0]
2347
-
2369
+
2348
2370
  if self.myStations==[]:
2349
2371
  self.set_compare_stations(idLauncher=idLauncher)
2350
2372
 
@@ -2359,17 +2381,17 @@ class Optimisation(wx.Frame):
2359
2381
  compMeas.append(SubBasin(dateBegin, dateEnd, deltaT, cst.compare_opti, dir_Meas))
2360
2382
  _,cur_comp = compMeas[iOpti].get_hydro(1, workingDir=dir_Meas, fileNames=compareFileName)
2361
2383
  keyBasin = curCatch.get_key_catchmentDict(stationOut)
2362
- cur_basin = curCatch.catchmentDict[keyBasin]
2384
+ cur_basin = curCatch.catchmentDict[keyBasin]
2363
2385
  cur_comp = cur_comp*cur_basin.surfaceDrained/3.6
2364
2386
  all_qtests = curCatch.get_all_Qtest(nb_atttempts=nb_tests, selection_by_iD=[stationOut])
2365
2387
  # FIXME : Check the type of interpolation to use
2366
2388
  interp_qcomp = np.interp(curCatch.time, compMeas[iOpti].time, cur_comp)
2367
- q_diff = np.array([np.count_nonzero((qtest-interp_qcomp <0.0) & (qtest != 0.0))/np.count_nonzero((qtest != 0.0))
2389
+ q_diff = np.array([np.count_nonzero((qtest-interp_qcomp <0.0) & (qtest != 0.0))/np.count_nonzero((qtest != 0.0))
2368
2390
  for qtest in all_qtests[0]])
2369
2391
  fig, ax = plt.subplots()
2370
2392
  for i in range(nb_tests-1):
2371
2393
  ax.scatter(q_diff[i], all_nash[i], s=0.5, c='b', marker='o', alpha=i/nb_tests)
2372
- ax.scatter(q_diff[-1], all_nash[-1], s=0.5, c='b', marker='o', label="test", alpha=1)
2394
+ ax.scatter(q_diff[-1], all_nash[-1], s=0.5, c='b', marker='o', label="test", alpha=1)
2373
2395
  # ax.scatter(q_diff, all_nash, s=0.5, c='b', marker='o', label="test")
2374
2396
  ax.set_xlabel("Non-exceedance fraction. Portion of the observations below the simulated series (Qs>Qo)")
2375
2397
  ax.set_ylabel("Nash-Sutcliffe efficiency")
@@ -2383,20 +2405,20 @@ class Optimisation(wx.Frame):
2383
2405
  ax.legend()
2384
2406
  fig.savefig(os.path.join(curCatch.workingDir, "PostProcess/Nash_vs_Qexcess_"+stationOut+".png"))
2385
2407
 
2386
-
2408
+
2387
2409
  plt.show()
2388
2410
 
2389
2411
 
2390
2412
  def get_all_Nash(self):
2391
-
2413
+
2392
2414
  return {cur_file: self.collect_optim(cur_file)[-1] for cur_file in self.myStations}
2393
-
2415
+
2394
2416
  # FIXME this function is not correct -> to be corrected and delete the remove_py_params and updtate_myParams calls
2395
2417
  def get_all_params(self, idLauncher:int=0):
2396
2418
  curCatch:Catchment = self.myCases[idLauncher].refCatchment
2397
2419
 
2398
2420
  hydro_model = curCatch.myModel
2399
-
2421
+
2400
2422
  # Read the comparison file
2401
2423
  if self.myStations==[]:
2402
2424
  self.set_compare_stations(idLauncher=idLauncher)
@@ -2414,13 +2436,13 @@ class Optimisation(wx.Frame):
2414
2436
  names = [myModelDict[cur_id]["Name"] for cur_id in id_params if cur_id>0]
2415
2437
  all_names[stationOut] = names
2416
2438
  if calibrate_timeDelay:
2417
- # Get_nb inlets
2439
+ # Get_nb inlets
2418
2440
  inletsNames = self.myCases[idLauncher].refCatchment.get_inletsName(stationOut)
2419
2441
  nbInlets = len(inletsNames)
2420
2442
  for i in range(nbInlets):
2421
2443
  names.append("TimeDelay "+inletsNames[i])
2422
2444
  # Complete the names according to the stations concerned
2423
-
2445
+
2424
2446
  optim = {cur_file: self.collect_optim(cur_file) for cur_file in self.myStations}
2425
2447
 
2426
2448
  # all_params = {}
@@ -2428,20 +2450,20 @@ class Optimisation(wx.Frame):
2428
2450
  # all_params[key] = {}
2429
2451
  # for i, cur_name in enumerate(all_names):
2430
2452
  # all_params[key][cur_name] = value[i]
2431
-
2432
- all_params = {key:
2453
+
2454
+ all_params = {key:
2433
2455
  {cur_name : value[i] for i, cur_name in enumerate(all_names)}
2434
2456
  for key, value in optim.items()}
2435
2457
 
2436
2458
  return all_params
2437
-
2438
-
2459
+
2460
+
2439
2461
  def save_all_params(self, all_params:dict={}, idLauncher:int=0):
2440
-
2462
+
2441
2463
  all_keys = list(all_params.keys())
2442
-
2443
- return
2444
-
2464
+
2465
+ return
2466
+
2445
2467
 
2446
2468
  def save_current_compare_file(self, stationOut: str):
2447
2469
  """
@@ -2475,11 +2497,11 @@ class Optimisation(wx.Frame):
2475
2497
  comments="",
2476
2498
  delimiter="\t",
2477
2499
  )
2478
-
2479
-
2500
+
2501
+
2480
2502
  def prepare_simulation(self, opti_intervals:list[tuple[datetime.datetime, datetime.datetime]],
2481
2503
  idLauncher:int=0):
2482
-
2504
+
2483
2505
  cur_catch = self.myCases[idLauncher].refCatchment
2484
2506
  # TODO : Create an object hydro intervals with activate property and a method to retrun a list of tuples
2485
2507
  simul_intevals = cur_catch.simulation_intervals
@@ -2493,20 +2515,20 @@ class Optimisation(wx.Frame):
2493
2515
  break
2494
2516
  if to_activate:
2495
2517
  eff_simul_intervals.append(simul_intrv)
2496
-
2518
+
2497
2519
  cur_catch.simulation_intervals = eff_simul_intervals
2498
-
2520
+
2499
2521
  return
2500
-
2501
2522
 
2502
- def reset_simulation_intervals(self, default_interval:list[tuple[datetime.datetime, datetime.datetime]],
2523
+
2524
+ def reset_simulation_intervals(self, default_interval:list[tuple[datetime.datetime, datetime.datetime]],
2503
2525
  idLauncher:int=0):
2504
-
2526
+
2505
2527
  cur_catch = self.myCases[idLauncher].refCatchment
2506
2528
  cur_catch.simulation_intervals = default_interval
2507
2529
 
2508
2530
  return
2509
-
2531
+
2510
2532
  # FIXME : this function has been dashed off -> functionnal but not well written!!
2511
2533
  # TODO : to improve !!!!!!
2512
2534
  def test_equifinality_with_Nash(self, event, idLauncher:int=0, idOpti:int=1, quantile_Nash:float=0.01, std_Nash:float=0.3, clustering_Nash:bool=True):
@@ -2528,11 +2550,11 @@ class Optimisation(wx.Frame):
2528
2550
  if onlyOwnSub is None:
2529
2551
  onlyOwnSub = False
2530
2552
  doneList = []
2531
- previousLevel = 1
2553
+ previousLevel = 1
2532
2554
  # Collect sort and save the compare stations
2533
2555
  self.set_compare_stations(idLauncher=idLauncher)
2534
2556
  sortJct = self.myStations
2535
- # Get the initial number of intervals
2557
+ # Get the initial number of intervals
2536
2558
  # -> these can evolve according to the measurement available at each station
2537
2559
  is_ok = self._save_opti_intervals()
2538
2560
  all_intervals = self.all_intervals
@@ -2564,14 +2586,14 @@ class Optimisation(wx.Frame):
2564
2586
  # Reload the useful modules
2565
2587
  self.reload_hydro(idCompar=0, fromStation=stationOut, lastLevel=previousLevel, updateAll=True)
2566
2588
  ## =======
2567
- ## Init
2589
+ ## Init
2568
2590
  ## =======
2569
2591
  self.init_optimizer(idOpti)
2570
2592
  self.associate_ptr(None, idOpti=idOpti)
2571
2593
  # Get the best parameters to test
2572
2594
  all_params = self.get_best_params(stationOut=stationOut, quantile=quantile_Nash, std=std_Nash, apply_clustering=clustering_Nash)
2573
2595
  ## =======
2574
- ## Compute
2596
+ ## Compute
2575
2597
  ## =======
2576
2598
  all_frac = []
2577
2599
 
@@ -2608,7 +2630,7 @@ class Optimisation(wx.Frame):
2608
2630
  + list(frac_dict.keys()) \
2609
2631
  + list(frac_vol_dict.keys()) \
2610
2632
  + ["% max runoff", "P. of exceedance", "Qmax_simul/Q_max_measure", "Nash"]
2611
-
2633
+
2612
2634
  cur_df = pd.DataFrame(all_frac, columns=var_names)
2613
2635
  # write first the tempory results for each station
2614
2636
  writer_stat = pd.ExcelWriter(os.path.join(self.workingDir, stationOut+"_tests.xlsx"), engine = 'xlsxwriter')
@@ -2638,12 +2660,12 @@ class Optimisation(wx.Frame):
2638
2660
 
2639
2661
  writer_tot.close()
2640
2662
  logging.info("The equifinality test is finished!")
2641
-
2642
2663
 
2643
- def get_best_params(self, stationOut:str,
2664
+
2665
+ def get_best_params(self, stationOut:str,
2644
2666
  criterion:str="Nash", quantile:float=0.99, std:float=0.05, eps:float=0.1,
2645
2667
  objective_fct:bool= True, apply_clustering:bool=False):
2646
- from sklearn.cluster import DBSCAN
2668
+ from sklearn.cluster import DBSCAN
2647
2669
  """
2648
2670
  Get the best parameters for a given station.
2649
2671
 
@@ -2662,7 +2684,7 @@ class Optimisation(wx.Frame):
2662
2684
  all_params, all_obj_fct = self.read_all_attempts_SA(format=".dat", all_attempts=True)
2663
2685
 
2664
2686
  quantile_cond = (all_obj_fct > np.quantile(all_obj_fct, quantile))
2665
- std_cond = (all_obj_fct > best_objfct*(1-std))
2687
+ std_cond = (all_obj_fct > best_objfct*(1-std))
2666
2688
  all_cond = np.where(np.logical_and(quantile_cond, std_cond))[0]
2667
2689
  eff_params = all_params[all_cond]
2668
2690
  eff_obj = all_obj_fct[all_cond]
@@ -2670,7 +2692,7 @@ class Optimisation(wx.Frame):
2670
2692
  if objective_fct:
2671
2693
  eff_params = np.column_stack((eff_params, eff_obj))
2672
2694
 
2673
- # In this part we filter abd remove the parameters that are almost equivalent
2695
+ # In this part we filter abd remove the parameters that are almost equivalent
2674
2696
  # To do so, we use the DBSCAN clustering algorithm to group the parameters that are close to each other
2675
2697
  # and only keep the set of parameter that has the best Nash-Sutcliffe efficiency per group
2676
2698
  # The parameters that are not grouped are considered had "particular" and are still kept in the final set
@@ -2690,7 +2712,7 @@ class Optimisation(wx.Frame):
2690
2712
  grouped_ind = db.core_sample_indices_
2691
2713
  grouped_params = eff_params[grouped_ind]
2692
2714
  grouped_labels = labels[grouped_ind]
2693
-
2715
+
2694
2716
  # Init of the filtered parameters vector
2695
2717
  filtered_params = np.zeros((n_clusters+n_noise, np.shape(eff_params)[1]))
2696
2718
  # Loop to determine the best set of parameter per group
@@ -2708,10 +2730,10 @@ class Optimisation(wx.Frame):
2708
2730
  return filtered_params
2709
2731
 
2710
2732
  return eff_params
2711
-
2733
+
2712
2734
 
2713
2735
  # FIXME : interp function used -> add the method of interpolation as an argument
2714
- def _get_exceedance(self, idLauncher:int=0, stationOut:str="",
2736
+ def _get_exceedance(self, idLauncher:int=0, stationOut:str="",
2715
2737
  intervals:list[tuple[datetime.datetime, datetime.datetime]]=[]) -> float:
2716
2738
  curCatch:Catchment = self.myCases[idLauncher].refCatchment
2717
2739
  cur_key = curCatch.get_key_catchmentDict(stationOut)
@@ -2737,9 +2759,9 @@ class Optimisation(wx.Frame):
2737
2759
 
2738
2760
  return q_diff
2739
2761
 
2740
-
2762
+
2741
2763
  # FIXME : to improve and generalise
2742
- def _get_cur_fractions(self, idLauncher:int=0, stationOut:str="",
2764
+ def _get_cur_fractions(self, idLauncher:int=0, stationOut:str="",
2743
2765
  intervals:list[tuple[datetime.datetime, datetime.datetime]]=[]) -> dict[list[str], list[float]]:
2744
2766
  """
2745
2767
  Save the evaluations of the model.
@@ -2764,12 +2786,12 @@ class Optimisation(wx.Frame):
2764
2786
  cur_fracts = curBasin.get_summary_fractions(summary="mean", interval=intervals)
2765
2787
 
2766
2788
  return cur_fracts
2767
-
2789
+
2768
2790
 
2769
2791
  # TODO : to finish this function
2770
- def _get_volume_fractions(self, idLauncher:int=0, stationOut:str="",
2792
+ def _get_volume_fractions(self, idLauncher:int=0, stationOut:str="",
2771
2793
  intervals:list[tuple[datetime.datetime, datetime.datetime]]=[]) -> dict[list[str], list[float]]:
2772
-
2794
+
2773
2795
  curCatch:Catchment = self.myCases[idLauncher].refCatchment
2774
2796
  cur_key = curCatch.get_key_catchmentDict(stationOut)
2775
2797
  curBasin: SubBasin = curCatch.catchmentDict[cur_key]
@@ -2780,7 +2802,7 @@ class Optimisation(wx.Frame):
2780
2802
  return cur_fracts
2781
2803
 
2782
2804
  # FIXME : to improve and generalise
2783
- def _get_max_runoff(self, idLauncher:int=0, stationOut:str="",
2805
+ def _get_max_runoff(self, idLauncher:int=0, stationOut:str="",
2784
2806
  intervals:list[tuple[datetime.datetime, datetime.datetime]]=[]) -> dict[list[str], list[float]]:
2785
2807
 
2786
2808
  curCatch:Catchment = self.myCases[idLauncher].refCatchment
@@ -2789,11 +2811,11 @@ class Optimisation(wx.Frame):
2789
2811
  cur_fracts = curBasin.get_summary_fractions(summary="max", interval=intervals)
2790
2812
 
2791
2813
  return cur_fracts["% qof"]
2792
-
2793
2814
 
2794
- def _get_ratio_max_sim_obs(self, idLauncher:int=0, stationOut:str="",
2815
+
2816
+ def _get_ratio_max_sim_obs(self, idLauncher:int=0, stationOut:str="",
2795
2817
  intervals:list[tuple[datetime.datetime, datetime.datetime]]=[]) -> float:
2796
-
2818
+
2797
2819
  curCatch:Catchment = self.myCases[idLauncher].refCatchment
2798
2820
  cur_key = curCatch.get_key_catchmentDict(stationOut)
2799
2821
  curBasin: SubBasin = curCatch.catchmentDict[cur_key]
@@ -2814,9 +2836,9 @@ class Optimisation(wx.Frame):
2814
2836
  simul = curBasin.outFlow[interv_simul]
2815
2837
  compare = measure.outFlow[interv_meas]
2816
2838
  ratio = np.nanmax(simul)/np.nanmax(compare)
2817
-
2839
+
2818
2840
  return ratio
2819
-
2841
+
2820
2842
 
2821
2843
  # Here, we condider that the parameters were already sorted, i.e. model parameters first and Python parameters (<0) after
2822
2844
  def get_param_names(self, idLauncher:int=0, stationOut:str=""):
@@ -2827,7 +2849,7 @@ class Optimisation(wx.Frame):
2827
2849
 
2828
2850
  calibrate_timeDelay = bool(int(self.optiParam.get_param("Semi-Distributed", "Calibrate_times")))
2829
2851
  if calibrate_timeDelay:
2830
- # Get_nb inlets
2852
+ # Get_nb inlets
2831
2853
  inletsNames = self.myCases[idLauncher].refCatchment.get_inletsName(stationOut)
2832
2854
  nbInlets = len(inletsNames)
2833
2855
  for i in range(nbInlets):
@@ -2835,7 +2857,7 @@ class Optimisation(wx.Frame):
2835
2857
 
2836
2858
 
2837
2859
  return names
2838
-
2860
+
2839
2861
  # Plot the equifinalty test for each station
2840
2862
  def plot_equifinality(self, event, idLauncher:int=0):
2841
2863
 
@@ -2860,7 +2882,7 @@ class Optimisation(wx.Frame):
2860
2882
  cur_columns = [col for col in df.columns if cur_prop in col.replace(" ", "")]
2861
2883
  if cur_columns != []:
2862
2884
  corr_prop = cur_columns[0]
2863
- ax.scatter(df.loc[:,corr_prop], df.loc[:,y_label], s=0.5, c=cur_color,
2885
+ ax.scatter(df.loc[:,corr_prop], df.loc[:,y_label], s=0.5, c=cur_color,
2864
2886
  marker='o', label=cur_prop, alpha=0.4)
2865
2887
  ax.set_xlabel("% of the rain [-]")
2866
2888
  ax.set_ylabel(y_label+" [-]")
@@ -2873,7 +2895,7 @@ class Optimisation(wx.Frame):
2873
2895
  cur_columns = [col for col in df.columns if cur_prop.replace(" ", "") in col.replace(" ", "")]
2874
2896
  if cur_columns != []:
2875
2897
  corr_prop = cur_columns[0]
2876
- ax.scatter(df.loc[:,corr_prop], df.loc[:,y_label], s=0.5, c=cur_color,
2898
+ ax.scatter(df.loc[:,corr_prop], df.loc[:,y_label], s=0.5, c=cur_color,
2877
2899
  marker='o', label=cur_prop, alpha=0.4)
2878
2900
  ax.set_xlabel("% of the rain volume [-]")
2879
2901
  ax.set_ylabel(y_label+" [-]")
@@ -2913,10 +2935,10 @@ class Optimisation(wx.Frame):
2913
2935
  fig.savefig(os.path.join(self.workingDir, "Equifinality_max_runoff_"+stationOut+".png"))
2914
2936
  else:
2915
2937
  logging.error("The file "+filename+" does not exist!")
2916
-
2938
+
2917
2939
  plt.show()
2918
2940
 
2919
-
2941
+
2920
2942
  def add_Case(self, idLauncher:int=0):
2921
2943
 
2922
2944
  i = idLauncher
@@ -2948,7 +2970,7 @@ class Optimisation(wx.Frame):
2948
2970
  curCase = paramMenu.Append(newId, curName, caseMenu)
2949
2971
  else:
2950
2972
  print("WARNING : this scenario was not implemented yet. This might induce an error!")
2951
- # iItem =
2973
+ # iItem =
2952
2974
  curCase = paramMenu.Replace(iItem)
2953
2975
  else:
2954
2976
  refDir = newCase.launcherParam.get_param("Calculs","Répertoire simulation de référence")
@@ -2960,6 +2982,116 @@ class Optimisation(wx.Frame):
2960
2982
  self.myCases.append(newCase)
2961
2983
 
2962
2984
 
2985
+ def launch_semi_dist_parameters(self, idLauncher:int=0, idOpti:int=1,
2986
+ params_to_test:dict[str, np.ndarray]={},
2987
+ return_outflows:bool=False) -> dict[str, np.ndarray]:
2988
+ # Return variable
2989
+ all_outlets = {}
2990
+ # Useful variables
2991
+ curCatch:Catchment = self.myCases[idLauncher].refCatchment
2992
+ doneList = []
2993
+ previousLevel = 1
2994
+ # Get if the optimisation or the set of parameters is only for 1 subbasin severals
2995
+ onlyOwnSub = self.optiParam.get_param("Semi-Distributed", "Own_SubBasin")
2996
+ if onlyOwnSub is None:
2997
+ onlyOwnSub = False
2998
+ # Collect sort and save the compare stations
2999
+ self.set_compare_stations(idLauncher=idLauncher)
3000
+ sortJct = self.myStations
3001
+ # Get the initial number of intervals
3002
+ # -> these can evolve according to the measurement available at each station
3003
+ is_ok = self._save_opti_intervals()
3004
+ all_intervals = self.all_intervals
3005
+ # Extract the number of time steps to initialise the matrices
3006
+ nb_time_steps = len(curCatch.time)
3007
+ # Loop over all stations to apply the set of parameters
3008
+ for stationOut in sortJct:
3009
+ if not stationOut in list(params_to_test.keys()):
3010
+ continue
3011
+ # Definition of the current subbasin
3012
+ cur_key = curCatch.get_key_catchmentDict(stationOut)
3013
+ curBasin: SubBasin = curCatch.catchmentDict[cur_key]
3014
+ # Extract all the parameters to test
3015
+ all_params = params_to_test[stationOut]
3016
+ logging.info("==================")
3017
+ logging.info("Station : "+stationOut)
3018
+ # Prepare all the file in the hydrology optimisation and simulation directories
3019
+ self._prepare_opti_hydro_files(stationOut=stationOut, idLauncher=idLauncher,
3020
+ onlyOwnSub=onlyOwnSub, doneList=doneList, previousLevel=previousLevel)
3021
+ # Select correct calibration intervals -> remove the intervals with NaN
3022
+ cur_intervals = self.select_opti_intervals(all_intervals=all_intervals, stationOut=stationOut, filter_nan=True)
3023
+ self.save_opti_dates_to_file(cur_intervals)
3024
+ ## ===================================================================================================================
3025
+ ## Init
3026
+ ## ===================================================================================================================
3027
+ self.init_optimizer(idOpti)
3028
+ self.associate_ptr(None, idOpti=idOpti)
3029
+ ## ===================================================================================================================
3030
+ ## Compute
3031
+ ## ===================================================================================================================
3032
+ all_outlets[stationOut] = np.zeros((len(all_params), nb_time_steps))
3033
+ for i in range(len(all_params)):
3034
+ cur_p = all_params[i, :-1]
3035
+ cur_obj2 = self.evaluate_model_optimizer(cur_p, idOpti=idOpti)
3036
+ all_outlets[stationOut][i,:] = curBasin.outFlow
3037
+ # Small test
3038
+ cur_obj = all_params[i, -1]
3039
+ print("cur_obj : ", cur_obj, " ; cur_obj2 : ", cur_obj2)
3040
+ if cur_obj != cur_obj2:
3041
+ logging.error("The objective function is not the same as the one computed by the model!")
3042
+ logging.error("cur_obj : "+str(cur_obj)+" ; cur_obj2 : "+str(cur_obj2))
3043
+ ## ===================================================================================================================
3044
+ ## ===================================================================================================================
3045
+ # Collect the best parameters and their objective function(s)
3046
+ best_params = self.apply_optim(None)
3047
+ # Simulation with the best parameters
3048
+ self.compute_distributed_hydro_model()
3049
+ # Update myHydro of all effective subbasins to get the best configuration upstream
3050
+ curCatch.read_hydro_eff_subBasin()
3051
+ # Update timeDelays according to time wolf_array
3052
+ self.apply_timeDelay_dist(idOpti=idOpti, idLauncher=idLauncher, junctionKey=stationOut)
3053
+ # Update the outflows
3054
+ curCatch.update_hydro(idCompar=0)
3055
+
3056
+ # All upstream elements of a reference will be fixed
3057
+ doneList.append(stationOut)
3058
+ previousLevel = curCatch.levelOut
3059
+
3060
+ logging.info("All the parameters have been tested!")
3061
+ if return_outflows:
3062
+ return all_outlets
3063
+
3064
+
3065
+ def _prepare_opti_hydro_files(self, stationOut:str, idLauncher:int=0, onlyOwnSub:bool=False,
3066
+ doneList:list[str]=[], previousLevel:int=1):
3067
+ # Useful variables
3068
+ curCatch:Catchment = self.myCases[idLauncher].refCatchment
3069
+
3070
+ # Build the current compare.txt file and replace all nan values by 0.0
3071
+ self.save_current_compare_file(stationOut=stationOut)
3072
+ # Save the name of the station that will be the output
3073
+ curCatch.define_station_out(stationOut)
3074
+ # Activate all the useful subs and write it in the param file
3075
+ curCatch.activate_usefulSubs(blockJunction=doneList, onlyItself=onlyOwnSub)
3076
+ # Rename the result file
3077
+ self.optiParam.change_param("Optimizer", "fname", stationOut)
3078
+ self.optiParam.SavetoFile(None)
3079
+ self.optiParam.Reload(None)
3080
+ self.update_myParams(idLauncher)
3081
+ # Prepare the paramPy dictionnary before calibration
3082
+ self.prepare_calibration_timeDelay(stationOut=stationOut)
3083
+ # Reload the useful modules
3084
+ self.reload_hydro(idCompar=0, fromStation=stationOut, lastLevel=previousLevel, updateAll=True)
3085
+
3086
+
3087
+
3088
+ def write_one_opti_param(self, filPath:Path, fileName:Path, myGroup:str, myKey:str, value:float, convers_factor:int=1.0):
3089
+ tmpWolf = Wolf_Param(to_read=True, filename=os.path.join(filPath,fileName),toShow=False, init_GUI=False)
3090
+ tmpWolf.change_param(myGroup, myKey, value/convers_factor)
3091
+ tmpWolf.SavetoFile(None)
3092
+ # tmpWolf.OnClose(None)
3093
+ tmpWolf = None
3094
+
2963
3095
 
2964
3096
  def make_nd_array(self, c_pointer, shape, dtype=np.float64, order='C', own_data=True,readonly=False):
2965
3097
  arr_size = np.prod(shape[:]) * np.dtype(dtype).itemsize
@@ -2977,4 +3109,3 @@ class Optimisation(wx.Frame):
2977
3109
  return arr.copy()
2978
3110
  else:
2979
3111
  return arr
2980
-