wolfhece 2.1.13__py3-none-any.whl → 2.1.15__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.
@@ -14,6 +14,7 @@ from .Outlet import *
14
14
  from .Dumping import *
15
15
  from ..PyTranslate import _
16
16
  from . import constant as cst
17
+ from ..PyVertexvectors import getIfromRGB, getRGBfromI
17
18
 
18
19
  class RetentionBasin():
19
20
  ## @var outFlow
@@ -29,7 +30,7 @@ class RetentionBasin():
29
30
  intletsObj:dict
30
31
  directFluxObj:dict
31
32
 
32
- def __init__(self, _dateBegin=None, _dateEnd=None, _deltaT:int=None, _time=None, _id='J1', _name='Default name', _type='',
33
+ def __init__(self, _dateBegin=None, _dateEnd=None, _deltaT:int=None, _time=None, _id='J1', _name='Default name', _type='',
33
34
  _dictRB={}, _directDictRB={}, _tz=0, _outletNames=[], withRBDict=True, _workingDir=""):
34
35
  print('Creation of a RetentionBasin!')
35
36
  self.iD = _id
@@ -47,11 +48,15 @@ class RetentionBasin():
47
48
  self.fileNameRead = _workingDir # //
48
49
  self.fileNameWrite = self.fileNameRead
49
50
  if(_time is None):
50
- tzDelta = datetime.timedelta(hours=self.tz)
51
- ti = datetime.datetime.timestamp(self.dateBegin-tzDelta)
52
- tf = datetime.datetime.timestamp(self.dateEnd-tzDelta)
53
- self.time = np.arange(ti,tf+self.deltaT,self.deltaT)
54
-
51
+ if(_dateBegin is None or _dateEnd is None or _deltaT is None):
52
+ self.time = None
53
+ self.filledVolume = None
54
+ else:
55
+ tzDelta = datetime.timedelta(hours=self.tz)
56
+ ti = datetime.datetime.timestamp(self.dateBegin-tzDelta)
57
+ tf = datetime.datetime.timestamp(self.dateEnd-tzDelta)
58
+ self.time = np.arange(ti,tf+self.deltaT,self.deltaT)
59
+ self.filledVolume = np.zeros(len(self.time), dtype=np.float64)
55
60
 
56
61
  self.x = 0.0
57
62
  self.y = 0.0
@@ -85,7 +90,6 @@ class RetentionBasin():
85
90
 
86
91
  self.rain = []
87
92
 
88
- self.filledVolume = np.zeros(len(self.time), dtype=np.float64)
89
93
  self.qLim = None # object to compute "l'ecretage"
90
94
 
91
95
  self.outletObj = None # object to compute the outlet
@@ -107,13 +111,13 @@ class RetentionBasin():
107
111
  for element in _dictRB:
108
112
  if(_dictRB[element]['from'][key_Param.VALUE] == self.iD):
109
113
  if(tmpCounter>0):
110
- print("ERROR: the same RB associated to two different caracteristics. Please check the RetentionBasin.postPro file.")
111
- sys.exit()
114
+ logging.error("ERROR: the same RB associated to two different caracteristics. Please check the RetentionBasin.postPro file.")
115
+ raise ValueError("The same RB associated to two different caracteristics. Please check the RetentionBasin.postPro file.")
112
116
  self.dictRB = _dictRB[element]
113
117
  tmpCounter +=1
114
118
  if(tmpCounter == 0):
115
- print("Error: no RB associated! Please check the RetentionBasin.postPro file.")
116
- sys.exit()
119
+ logging.error("Error: no RB associated! Please check the RetentionBasin.postPro file.")
120
+ raise ValueError("No RB associated! Please check the RetentionBasin.postPro file.")
117
121
  elif(_directDictRB!={}):
118
122
  self.dictRB = _directDictRB
119
123
  elif(withRBDict):
@@ -127,7 +131,7 @@ class RetentionBasin():
127
131
  self.dictRB['type'] = {}
128
132
  self.dictRB['type'][key_Param.VALUE] = ""
129
133
  elif(myAnswer=="N" or myAnswer=="n"):
130
- sys.exit()
134
+ raise ValueError("No answer given!")
131
135
  else:
132
136
  self.dictRB['type'] = {}
133
137
  self.dictRB['type'][key_Param.VALUE] = ""
@@ -243,9 +247,9 @@ class RetentionBasin():
243
247
  if(name in self.downstreamObj):
244
248
  self.downstreamObj[name] = toPoint
245
249
  else:
246
- print("ERROR: this outlet name is not recognised!")
247
- print("Name = ", name)
248
- sys.exit()
250
+ logging.error("ERROR: this outlet name is not recognised!")
251
+ logging.error("Name = ", name)
252
+ raise ValueError("This outlet name is not recognised!")
249
253
 
250
254
  self._outFlow[name] = {}
251
255
  self._outFlow[name]["Net"] = []
@@ -353,6 +357,81 @@ class RetentionBasin():
353
357
  return self._outFlow
354
358
 
355
359
 
360
+ def compute_one_step_hydro(self, i, givenDirectFluxIn:float=None, givenInlet:float=None):
361
+ """ This function computes the raw and real hydrographs for one time step.
362
+
363
+ The volume filled and then the water height in the RB at time $t$ will be evaluated will depend of the flows
364
+ at time $t-1$ exept if the
365
+
366
+ Internal variables modified : self.inlets, self.inletsRaw,
367
+ self.directFluxInRB, self.directFluxInRB_Raw,
368
+ self._outFlowRaw, self._outFlow, self.filledVolume
369
+ CAUTION: - Discussion about the ceil or the floor for the timeDelay indice!!!
370
+ - UPDATE 2023.1 now the outFlow are not delayed anymore !!!! -> IMPORTANT UPDATE
371
+ """
372
+ self.sum_one_step_directFluxInRB(i, givenDirectFluxIn)
373
+ self.sum_one_step_inlets(i, givenInlet)
374
+
375
+ mainNameOut = list(self._outFlow.items())[0][0]
376
+ # In the Raw hydrograph the first outlet is considered to be the main one. Therefore the exit where the flux would go if the structure were to present
377
+ self._outFlow[mainNameOut]["Raw"][i] = self.inletsRaw[i] + self.directFluxInRB_Raw[i]
378
+ for iOutFlow in range(1,len(list(self._outFlow.items()))):
379
+ nameOut = list(self._outFlow.items())[iOutFlow][0]
380
+ self._outFlow[nameOut]["Raw"][i] = 0.0
381
+
382
+ # Compute
383
+ h = self.volume_to_h(self.filledVolume[i])
384
+ # Qout = self.outletObj.compute(h,self.time[self.convert_index_global_to_local(i)])
385
+ Qout = self.outletObj.compute(h,self.time[i+1], index=i+1)
386
+ qLim = self.qLim.compute(h,self.time[i+1])
387
+ Qin = self.directFluxInRB[i-1]+max(self.inlets[i]-qLim,0.)
388
+ rhs = Qin - Qout
389
+ outFlowReservoir = Qout
390
+ # If the volume increase => the outflow is kept (Maybe to improve!! The height can go to the upper threshold)
391
+ if rhs>0:
392
+ self.filledVolume[i+1] = self.filledVolume[i] + rhs*(self.time[i+1]-self.time[i])
393
+ # If the volume is decreasing but is not enough to empty it at this time step
394
+ elif self.filledVolume[i]>abs(rhs*(self.time[i+1]-self.time[i])):
395
+ self.filledVolume[i+1] = self.filledVolume[i] + rhs*(self.time[i+1]-self.time[i])
396
+ # if(self.surface == 0.0):
397
+ # h = 0.0
398
+ # else:
399
+ # h = self.filledVolume[i]/self.surface
400
+ h = self.volume_to_h(self.filledVolume[i+1])
401
+ # All the values:
402
+ # -outlet,
403
+ # -ecretage,
404
+ # -volume,
405
+ # will be reevaluated. Because we can go to the lower threshold.
406
+ # Qout = self.outletObj.compute(h,self.time[self.convert_index_global_to_local(i)])
407
+ Qout = self.outletObj.compute(h,self.time[i+1], index=i+1)
408
+ qLim = self.qLim.compute(h,self.time[i+1])
409
+ rhs = self.directFluxInRB[i]+max(self.inlets[i]-qLim,0.)-Qout
410
+ outFlowReservoir = Qout
411
+ self.filledVolume[i+1] = self.filledVolume[i] + rhs*(self.time[i+1]-self.time[i])
412
+
413
+ else:
414
+ self.filledVolume[i+1] =0
415
+ outFlowReservoir = self.filledVolume[i]/((self.time[i+1]-self.time[i]))+self.directFluxInRB[i]+max(self.inlets[i]-qLim,0.)
416
+
417
+ if self.filledVolume[i+1]>self.volume:
418
+ outFlowReservoir += (self.filledVolume[i+1]-self.volume)/((self.time[i+1]-self.time[i]))
419
+ self.filledVolume[i+1] = self.volume
420
+
421
+ self._outFlow = self.compute_final(outFlowReservoir,min(self.inlets[i],qLim),i)
422
+
423
+
424
+ def init_all_inlets(self):
425
+ """ This function initializes the inlets and directFluxInRB of the RB
426
+ Internal variables modified: self.inlets, self.inletsRaw, self.directFluxInRB, self.directFluxInRB_Raw
427
+ """
428
+ self.inlets = np.zeros(len(self.time),dtype=ct.c_double, order='F')
429
+ self.inletsRaw = np.zeros(len(self.time),dtype=ct.c_double, order='F')
430
+
431
+ self.directFluxInRB = np.zeros(len(self.time),dtype=ct.c_double, order='F')
432
+ self.directFluxInRB_Raw = np.zeros(len(self.time),dtype=ct.c_double, order='F')
433
+
434
+
356
435
  def sum_inlets(self, givenInlet=[]):
357
436
  """ This procedure sum all the inlets of the RB
358
437
  Caution: inlets variable is different from directFluxIn !!
@@ -383,15 +462,15 @@ class RetentionBasin():
383
462
  # Assumption the transfer time between the 2 RB is ambiguous
384
463
  # Therefore, the transfer time is set to 0.0
385
464
  deltaTr = 0.0
386
-
465
+
387
466
  self.inlets += curObj.get_outFlow(typeOutFlow="Net", whichOutFlow=nameOutFlow, lag=deltaTr)
388
467
  self.inletsRaw += curObj.get_outFlow(typeOutFlow="Raw", whichOutFlow=nameOutFlow, lag=deltaTr)
389
468
  elif(givenInlet != []):
390
469
  if(len(givenInlet)!=len(self.time)):
391
- print("ERROR: the dimension of the time array and the given inlet are not the same!")
392
- print("Length optained = ", len(givenInlet))
393
- print("Length expected = ", len(self.time))
394
- sys.exit()
470
+ logging.error("The dimension of the time array and the given inlet are not the same!")
471
+ logging.error(f"Length obtained = {len(givenInlet)}")
472
+ logging.error(f"Length expected = {len(self.time)}")
473
+ raise ValueError("The dimension of the time array and the given inlet are not the same!")
395
474
  self.inlets = givenInlet
396
475
  self.inletsRaw = givenInlet
397
476
  else:
@@ -469,10 +548,10 @@ class RetentionBasin():
469
548
  elif(givenDirectFluxIn != []):
470
549
  # FIXME The following line to potentially change !!!
471
550
  if(len(givenDirectFluxIn)!=len(self.time)):
472
- print("ERROR: the dimension of the time array and the given inlet are not the same!")
473
- print("Length optained = ", len(givenDirectFluxIn))
474
- print("Length expected = ", len(self.time))
475
- sys.exit()
551
+ logging.error("The dimension of the time array and the given inlet are not the same!")
552
+ logging.error("Length optained = ", len(givenDirectFluxIn))
553
+ logging.error("Length expected = ", len(self.time))
554
+ raise ValueError("The dimension of the time array and the given inlet are not the same!")
476
555
  self.directFluxInRB = givenDirectFluxIn
477
556
  self.directFluxInRB_Raw = givenDirectFluxIn
478
557
  else:
@@ -482,6 +561,78 @@ class RetentionBasin():
482
561
  self.directFluxInRB_Raw = np.zeros(len(self.time), dtype=ct.c_double, order='F')
483
562
 
484
563
 
564
+ def sum_one_step_inlets(self, i, givenInlet:float=None):
565
+ if self.intletsObj != {}:
566
+ nameOutFlow = list(self.intletsObj.items())[0][0]
567
+ curObj = self.intletsObj[nameOutFlow]
568
+ # Compute the transfer time between modules
569
+ if type(curObj) is SubBasin:
570
+ timeInlet = curObj.timeDelay
571
+ deltaTr = timeInlet - self.timeDelay
572
+ else:
573
+ # Assumption the transfer time between the 2 RB is ambiguous
574
+ # Therefore, the transfer time is set to 0.0
575
+ deltaTr = 0.0
576
+ self.inlets[i] = curObj.get_outFlow(typeOutFlow="Net", whichOutFlow=nameOutFlow, lag=deltaTr)[i]
577
+ self.inletsRaw[i] = curObj.get_outFlow(typeOutFlow="Raw", whichOutFlow=nameOutFlow, lag=deltaTr)[i]
578
+ for i in range(1,len(list(self.intletsObj.items()))):
579
+ nameOutFlow = list(self.intletsObj.items())[i][0]
580
+ curObj = self.intletsObj[nameOutFlow]
581
+ timeInlet = curObj.timeDelay
582
+ if type(curObj) is SubBasin:
583
+ timeInlet = curObj.timeDelay
584
+ deltaTr = timeInlet - self.timeDelay
585
+ else:
586
+ # Assumption the transfer time between the 2 RB is ambiguous
587
+ # Therefore, the transfer time is set to 0.0
588
+ deltaTr = 0.0
589
+
590
+ self.inlets[i] += curObj.get_outFlow(typeOutFlow="Net", whichOutFlow=nameOutFlow, lag=deltaTr)[i]
591
+ self.inletsRaw[i] += curObj.get_outFlow(typeOutFlow="Raw", whichOutFlow=nameOutFlow, lag=deltaTr)[i]
592
+ elif(givenInlet is not None):
593
+ self.inlets[i] = givenInlet
594
+ self.inletsRaw[i] = givenInlet
595
+ else:
596
+ self.inlets[i] = 0.0
597
+ self.inletsRaw[i] = 0.0
598
+
599
+
600
+ def sum_one_step_directFluxInRB(self, i, givenDirectFluxIn:float=None):
601
+ """This procedure computes the flux going directly inside the RB
602
+
603
+ Internal variables modified: self.directFluxInRB, self.directFluxInRB_Raw
604
+ """
605
+ if(self.directFluxObj != {}):
606
+ nameOutFlow = list(self.directFluxObj.items())[0][0]
607
+ curObj = self.directFluxObj[nameOutFlow]
608
+ timeInlet = curObj.timeDelay
609
+ if type(curObj) is SubBasin:
610
+ timeInlet = curObj.timeDelay
611
+ deltaTr = timeInlet - self.timeDelay
612
+ else:
613
+ # Assumption the transfer time between the 2 RB is ambiguous
614
+ # Therefore, the transfer time is set to 0.0
615
+ deltaTr = 0.0
616
+ deltaTr = timeInlet - self.timeDelay
617
+ self.directFluxInRB[i] = curObj.get_outFlow(typeOutFlow="Net", whichOutFlow=nameOutFlow, lag=deltaTr)[i]
618
+ self.directFluxInRB_Raw[i] = curObj.get_outFlow(typeOutFlow="Raw", whichOutFlow=nameOutFlow, lag=deltaTr)[i]
619
+ for i in range(1,len(list(self.directFluxObj.items()))):
620
+ nameOutFlow = list(self.directFluxObj.items())[i][0]
621
+ curObj = self.directFluxObj[nameOutFlow]
622
+ timeInlet = curObj.timeDelay
623
+ if type(curObj) is SubBasin:
624
+ timeInlet = curObj.timeDelay
625
+ deltaTr = timeInlet - self.timeDelay
626
+ else:
627
+ # Assumption the transfer time between the 2 RB is ambiguous
628
+ # Therefore, the transfer time is set to 0.0
629
+ deltaTr = 0.0
630
+
631
+ self.directFluxInRB[i] += curObj.get_outFlow(typeOutFlow="Net", whichOutFlow=nameOutFlow, lag=deltaTr)[i]
632
+ self.directFluxInRB_Raw[i] += curObj.get_outFlow(typeOutFlow="Raw", whichOutFlow=nameOutFlow, lag=deltaTr)[i]
633
+
634
+
635
+
485
636
  def plot(self, workingDir, plotRaw=True, axis="Hours",rangeData=[], deltaMajorTicks=24.0*3600.0, deltaMinorTicks=3600.0, tzPlot=0, unitReservoir="[m^3]"):
486
637
  """ This procedure plots:
487
638
  - the inlets: in color chosen randomly by matplotlib
@@ -782,8 +933,8 @@ class RetentionBasin():
782
933
  elif(myIndex<len(dataLoc)):
783
934
  dataLoc[:-myIndex] = dataGlob[myIndex:]
784
935
  else:
785
- print("ERROR: the simulation time is not long enough for this subbasin to be taken into account")
786
- sys.exit()
936
+ logging.error("ERROR: the simulation time is not long enough for this subbasin to be taken into account")
937
+ raise ValueError("The simulation time is not long enough for this subbasin to be taken into account")
787
938
 
788
939
  return dataLoc
789
940
 
@@ -817,8 +968,7 @@ class RetentionBasin():
817
968
  else:
818
969
  result[myIndex:] = vector[:-myIndex]
819
970
  else:
820
- print("ERROR: the simulation time is not long enough for this subbasin to be taken into account")
821
- sys.exit()
971
+ raise ValueError("The simulation time is not long enough for this subbasin to be taken into account")
822
972
 
823
973
  return result
824
974
 
@@ -874,7 +1024,7 @@ class RetentionBasin():
874
1024
  if unit=='mm/h':
875
1025
  if self.surfaceDrainedHydro==0.0:
876
1026
  logging.error("ERROR: the surface drained = 0! Not possible to express the outFlow in mm/s!")
877
- sys.exit()
1027
+ raise ValueError("ERROR: the surface drained = 0! Not possible to express the outFlow in mm/s!")
878
1028
  myOutFlow *= 3.6/self.surfaceDrainedHydro
879
1029
 
880
1030
 
@@ -1221,7 +1371,7 @@ class RetentionBasin():
1221
1371
  # Verification
1222
1372
  if(datetime.datetime.timestamp(prevDate)>datetime.datetime.timestamp(self.dateBegin)):
1223
1373
  logging.error("ERROR: the first hydro data element is posterior to dateBegin!")
1224
- sys.exit()
1374
+ raise ValueError("ERROR: the first hydro data element is posterior to dateBegin!")
1225
1375
 
1226
1376
  if(nbCl==5):
1227
1377
  # Caution : the index of the loop start at 24 because the timestamp function
@@ -1270,15 +1420,15 @@ class RetentionBasin():
1270
1420
  # Add the last element in the time matrix as its size is 1 element bigger than outlet
1271
1421
  timeArray[-1] = timeArray[-2] + diffTimeInSeconds
1272
1422
  if(self.deltaT!=diffDate.seconds):
1273
- print("ERROR: The last timestep in hydro data does not coincide with the one expected!")
1274
- sys.exit()
1423
+ logging.error("ERROR: The last timestep in hydro data does not coincide with the one expected!")
1424
+ raise ValueError("ERROR: The last timestep in hydro data does not coincide with the one expected!")
1275
1425
  # Save time array if it does not exist yet
1276
1426
  # Otherwise, check the consistency of the array with the time array of the object
1277
1427
  if(self.time is None):
1278
1428
  self.time=timeArray
1279
1429
  elif(self.time.all()!=timeArray.all()):
1280
- print("ERROR: the dates read are not consitent with the dates already recored in this subbasin!")
1281
- sys.exit()
1430
+ logging.error("ERROR: the dates read are not consitent with the dates already recored in this subbasin!")
1431
+ raise ValueError("ERROR: the dates read are not consitent with the dates already recored in this subbasin!")
1282
1432
 
1283
1433
  volume = np.array([self.h_to_volume(i) for i in height])
1284
1434
 
@@ -1465,6 +1615,40 @@ class RetentionBasin():
1465
1615
 
1466
1616
  return allInlets
1467
1617
 
1618
+
1619
+ def get_inletCoords(self):
1620
+
1621
+ allCoords = []
1622
+
1623
+ for element in self.intletsObj:
1624
+ allCoords.append([self.intletsObj[element].x, self.intletsObj[element].y])
1625
+
1626
+ for element in self.directFluxObj:
1627
+ allCoords.append([self.directFluxObj[element].x, self.directFluxObj[element].y])
1628
+
1629
+ return allCoords
1630
+
1631
+ def get_zone(self) -> zone:
1632
+ """ Return a zone instance to insert in viewer """
1633
+
1634
+ myzone = zone(name = self.name)
1635
+
1636
+ x,y = self.x, self.y
1637
+
1638
+ xy_inlets = self.get_inletCoords()
1639
+ names = self.get_inletsName()
1640
+ for xy, curname in zip(xy_inlets, names):
1641
+ locx, locy = xy
1642
+ newvec = vector(name = curname)
1643
+ newvec.add_vertex(wolfvertex(locx,locy))
1644
+ newvec.add_vertex(wolfvertex(x,y))
1645
+
1646
+ newvec.myprop.color = getIfromRGB([255,100,0])
1647
+ newvec.myprop.width = 3
1648
+
1649
+ myzone.add_vector(newvec, forceparent=True)
1650
+
1651
+ return myzone
1468
1652
 
1469
1653
 
1470
1654
  def get_timeDelays(self, timeDelays={}):
@@ -1480,12 +1664,12 @@ class RetentionBasin():
1480
1664
 
1481
1665
  def get_timeDelays_inlets(self):
1482
1666
 
1483
-
1667
+
1484
1668
  all_timeDelays = {el.timeDelay-self.timeDelay for el in self.intletsObj.values()}
1485
1669
  all_timeDelays.update({el.timeDelay-self.timeDelay for el in self.directFluxObj.values()})
1486
1670
 
1487
1671
  return all_timeDelays
1488
-
1672
+
1489
1673
 
1490
1674
  ## This procedure save in a "transfer.param" file the timeDelay of the SubBasin and all its upstream elements
1491
1675
  def save_timeDelays(self):
@@ -1511,7 +1695,7 @@ class RetentionBasin():
1511
1695
  return self.timeDelayObj.get_iDSorted()
1512
1696
 
1513
1697
 
1514
- def get_outFlow_names(self)->list:
1698
+ def get_outFlow_names(self)->list:
1515
1699
 
1516
1700
  return list(self._outFlow.keys())
1517
1701
 
@@ -1537,7 +1721,7 @@ class RetentionBasin():
1537
1721
  # @var update_upstream boolean that specify whether the upstream elements should also be updated
1538
1722
  # @var level_min integer that specify the potential level at which the update should be stopped.
1539
1723
  def update_hydro(self, update_upstream:bool=True, level_min:int=1):
1540
-
1724
+
1541
1725
  # !!! (ALERT) : So far, we consider that a RB object will always need to update its upstream elements
1542
1726
  # TODO : a potiential future need will require only an optimisation of the RB and fixed upstream elements!
1543
1727
  # if update_upstream:
@@ -1618,11 +1802,11 @@ class RetentionBasin():
1618
1802
  self.filledVolume = volume[imin:imax+1]
1619
1803
 
1620
1804
  return
1621
-
1805
+
1622
1806
 
1623
1807
  def evaluate_objective_function(self, unit="mm/h")->np.ndarray:
1624
1808
  # unit = "m3/s"
1625
-
1809
+
1626
1810
  return self.get_direct_insideRB_inlets(unit=unit)
1627
1811
 
1628
1812
 
@@ -1684,4 +1868,25 @@ class RetentionBasin():
1684
1868
  else:
1685
1869
  print("WARNING: This type RB was not recognised! Please check the RetentionBasin.postPro file.")
1686
1870
 
1687
-
1871
+
1872
+ def init_time_simulation(self, dateBegin:datetime.datetime, dateEnd:datetime.datetime, deltaT:float, tz:int=0):
1873
+
1874
+ tzDelta = datetime.timedelta(hours=self.tz)
1875
+ self.dateBegin = dateBegin
1876
+ self.dateEnd = dateEnd
1877
+ self.deltaT = deltaT
1878
+ ti = datetime.datetime.timestamp(self.dateBegin-tzDelta)
1879
+ tf = datetime.datetime.timestamp(self.dateEnd-tzDelta)
1880
+ self.time = np.arange(ti,tf+self.deltaT,self.deltaT)
1881
+
1882
+ return self.time
1883
+
1884
+
1885
+ def init_internal_variable(self):
1886
+
1887
+ for iOutFlow in range(len(list(self._outFlow.items()))):
1888
+ nameOut = list(self._outFlow.items())[iOutFlow][0]
1889
+ self._outFlow[nameOut]["Net"] = np.zeros(len(self.time), dtype=np.float64)
1890
+ self._outFlow[nameOut]["Raw"] = np.zeros(len(self.time), dtype=np.float64)
1891
+
1892
+ self.filledVolume = np.zeros(len(self.time), dtype=np.float64)
@@ -17,6 +17,7 @@ from matplotlib.font_manager import FontProperties
17
17
  from dbfread import DBF
18
18
  import ctypes as ct
19
19
  import pandas as pd
20
+ from pathlib import Path
20
21
 
21
22
  from ..PyTranslate import _
22
23
  from . import plot_hydrology as ph
@@ -248,7 +249,7 @@ class SubBasin:
248
249
  file_exists = os.path.exists(fileName)
249
250
  if(not(file_exists)):
250
251
  typeOfFileName = 'simul_net_trans_rain.txt'
251
- fileName = join(workingDir, subBasinName + typeOfFileName)
252
+ fileName = os.path.join(workingDir,subBasinName, typeOfFileName)
252
253
  file_exists = os.path.exists(fileName)
253
254
  if(file_exists):
254
255
  print("ERROR : the file simul_net_trans_rain.txt is not used yet in this version! Please check version of the code before 05/11/2021 !")
@@ -1422,17 +1423,17 @@ class SubBasin:
1422
1423
  """Add hyetographs to the subbasin
1423
1424
  TO DO: Adapt the code to find automatically the .dbf files. E.G. when data are read in NetCDF files.
1424
1425
  """
1425
- fileName = workingDir + 'Subbasin_'+str(self.iDSorted)+'/simul_rain_geom_126.vec.dbf'
1426
- fileName2 = workingDir + 'Subbasin_'+str(self.iDSorted)+'/simul_geom.vec.dbf'
1426
+ fileName = Path(workingDir) / ('Subbasin_' +str(self.iDSorted)) / 'simul_rain_geom.vec.dbf'
1427
+ fileName2 = Path(workingDir) / ('Subbasin_' +str(self.iDSorted)) /'/simul_geom.vec.dbf'
1427
1428
 
1428
- if(os.path.exists(fileName)):
1429
- dbDict = self.read_dbfFile(fileName)
1429
+ if(fileName.exists()):
1430
+ dbDict = self.read_dbfFile(str(fileName))
1430
1431
  for i in range(len(dbDict.records)):
1431
1432
  idHyeto = int(dbDict.records[i]['data'])
1432
1433
  # idMyHyeto = hyetoDict['Ordered To Nb'][idHyeto]
1433
1434
  self.myHyetoDict[idHyeto] = hyetoDict['Hyetos'][idHyeto]
1434
- elif(os.path.exists(fileName2)):
1435
- dbDict = self.read_dbfFile(fileName2)
1435
+ elif(fileName2.exists()):
1436
+ dbDict = self.read_dbfFile(str(fileName2))
1436
1437
  for i in range(len(dbDict.records)):
1437
1438
  idHyeto = int(dbDict.records[i]['data'])
1438
1439
  # idMyHyeto = hyetoDict['Ordered To Nb'][idHyeto]
@@ -3451,12 +3452,43 @@ class SubBasin:
3451
3452
  elif summary == "min":
3452
3453
  return {key: np.nanmin(all_f[key], where=interv) for key in all_f}
3453
3454
  elif summary == "max":
3454
- return {key: np.nanmax(all_f[key], where=interv) for key in all_f}
3455
+ return {key: np.nanmax(all_f[key], where=interv, initial=0.0) for key in all_f}
3455
3456
  else:
3456
3457
  logging.error("The summary type is not recognised!")
3457
3458
  return []
3458
3459
 
3459
-
3460
+
3461
+ def get_volume_fractions(self, all_f:dict={},
3462
+ interval:list[tuple[datetime.datetime, datetime.datetime]]=None) -> dict[str, np.array]:
3463
+ """
3464
+ This procedure is returning a summary of the fractions of the current module.
3465
+
3466
+ Parameters:
3467
+ - summary (str): The type of summary to return.
3468
+ - interval (list[datetime.datetime], optional): The interval of time to consider. Default is None.
3469
+
3470
+ Returns:
3471
+ - dict: A dictionary containing the summary of the fractions of the current module.
3472
+ """
3473
+
3474
+ if all_f == {}:
3475
+ all_f = self.collect_fractions()
3476
+
3477
+ all_v = {key: val/100.0*self.myRain for key, val in all_f.items()}
3478
+
3479
+ if interval is not None:
3480
+ interv = np.zeros(len(self.time), dtype=bool)
3481
+ for el in interval:
3482
+ date_i = datetime.datetime.timestamp(el[0])
3483
+ date_f = datetime.datetime.timestamp(el[1])
3484
+ interv += (self.time>=date_i) & (self.time<=date_f)
3485
+ else:
3486
+ interv = np.ones(len(self.time), dtype=bool)
3487
+
3488
+ tot_rain = np.nansum(self.myRain[interv])*self.deltaT/3600
3489
+
3490
+ return {key+" volume": (np.nansum(all_v[key][interv])*self.deltaT/3600)/tot_rain*100 for key in all_v}
3491
+
3460
3492
 
3461
3493
  def check_presence_of_iv(self):
3462
3494
  """
@@ -3514,6 +3546,7 @@ class SubBasin:
3514
3546
 
3515
3547
  return q_test
3516
3548
 
3549
+
3517
3550
  def plot_all_fractions(self, all_fractions:dict[str:np.array]={},figure=None, to_show:bool=False, writeDir:str="", range_data:list[datetime.datetime]=[]) -> None:
3518
3551
 
3519
3552
  if writeDir == "":
@@ -824,4 +824,62 @@ def bar_Nash_n_other(all_data:list[dict], all_colors:list[dict], nb_x, nb_data,
824
824
 
825
825
 
826
826
  if toShow :
827
+ plt.show()
828
+
829
+
830
+ def table_Nash_n_other(data:np.ndarray,
831
+ type_of_data:str="Nash", color_map:str=None,
832
+ row_names:list[str]=[], column_names:list[str]=[], title:str="",
833
+ writeFile:str="", toShow:bool=False, nan_color:str="white", nan_value:float=0.0):
834
+
835
+ if nan_value is not None:
836
+ data[data == nan_value] = np.nan
837
+
838
+ # Heat map definition
839
+ fig_tmp, ax_tmp = plt.subplots()
840
+ if type_of_data == "Nash":
841
+ heatmap = ax_tmp.imshow(data[:, 0:1], cmap='RdYlGn', aspect='auto', vmin=0, vmax=1)
842
+ if type_of_data == "Exceedance":
843
+ heatmap = ax_tmp.imshow(data[:, 1:2], cmap='bwr_r', aspect='auto', vmin=-1, vmax=1, origin='lower')
844
+
845
+ heat_rgb = heatmap.to_rgba(data)
846
+ plt.close(fig_tmp)
847
+
848
+ vfunc = np.vectorize(lambda x: '' if np.isnan(x) else f'{x:.2f}')
849
+ ndata = vfunc(data)
850
+
851
+ # plot the table
852
+ fig, ax = plt.subplots()
853
+ table = ax.table(cellText=ndata, loc='center',
854
+ cellColours= heat_rgb,
855
+ colLabels=column_names,
856
+ rowLabels=row_names,
857
+ cellLoc='center',
858
+ rowLoc='center',
859
+ colLoc='center')
860
+
861
+ # Make the column fit with around their name
862
+ for i in range(len(row_names)):
863
+ table.auto_set_column_width(i)
864
+ # Change the text color based on the brightness of the cell color
865
+ for i, cell in table.get_celld().items():
866
+ cell.set_edgecolor('black')
867
+ if cell.get_facecolor()[0] < 0.5: # if the cell color is dark
868
+ cell.get_text().set_color('white')
869
+ else:
870
+ cell.get_text().set_color('black')
871
+
872
+ table.scale(1.0, 3.0)
873
+ # table.auto
874
+
875
+ # Hide axes
876
+ ax.axis('off')
877
+ # Set the title
878
+ if title != "":
879
+ ax.set_title(title)
880
+
881
+ if writeFile != "":
882
+ plt.savefig(writeFile, transparent=True, bbox_inches='tight')
883
+
884
+ if toShow:
827
885
  plt.show()
wolfhece/libs/WolfDll.dll CHANGED
Binary file