wolfhece 2.2.46__py3-none-any.whl → 2.2.48__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.
@@ -2395,7 +2395,7 @@ class crosssections(Element_To_Draw):
2395
2395
  ['right_down']: wolfvertex
2396
2396
  ['cs'] : profile (surcharge de vector)
2397
2397
 
2398
- Pour le moment, il est possible de lire les fichiers et d'effectuer cerrains traitements (tri selon vecteur, export gltf...).
2398
+ Pour le moment, il est possible de lire les fichiers et d'effectuer certains traitements (tri selon vecteur, export gltf...).
2399
2399
 
2400
2400
  Une instance de cet objet peut être ajouté à une instance graphique WOLF pour affichage.
2401
2401
  Pour ce faire:
@@ -2408,7 +2408,7 @@ class crosssections(Element_To_Draw):
2408
2408
 
2409
2409
  """
2410
2410
 
2411
- myprofiles:dict['cs':profile, 'index':int, 'left':wolfvertex, 'bed':wolfvertex, 'right':wolfvertex, 'left_down':wolfvertex, 'right_down':wolfvertex]
2411
+ myprofiles:dict[str | int: dict['cs':profile, 'index':int, 'left':wolfvertex, 'bed':wolfvertex, 'right':wolfvertex, 'left_down':wolfvertex, 'right_down':wolfvertex]]
2412
2412
  mygenprofiles:dict
2413
2413
 
2414
2414
  def __init__(self,
@@ -3395,6 +3395,10 @@ class crosssections(Element_To_Draw):
3395
3395
 
3396
3396
  curprof = self[0]
3397
3397
 
3398
+ if curprof.up is None:
3399
+ logging.warning(_('No upstream profile defined for profile %s.')%curprof.myname)
3400
+ return self.myprofiles[curprof.myname]
3401
+
3398
3402
  while curprof.up is not curprof:
3399
3403
  curprof = curprof.up
3400
3404
 
@@ -3405,6 +3409,10 @@ class crosssections(Element_To_Draw):
3405
3409
 
3406
3410
  curprof = self[0]
3407
3411
 
3412
+ if curprof.down is None:
3413
+ logging.warning(_('No downstream profile defined for profile %s.')%curprof.myname)
3414
+ return self.myprofiles[curprof.myname]
3415
+
3408
3416
  while curprof.down is not curprof:
3409
3417
  curprof = curprof.down
3410
3418
 
@@ -3649,6 +3657,10 @@ class crosssections(Element_To_Draw):
3649
3657
  if to_destroy:
3650
3658
  destroy_prepared(vecsupport)
3651
3659
 
3660
+ if len(mysorted)==0:
3661
+ logging.warning(_('No cross-section intersects the support vector!'))
3662
+ return 0
3663
+
3652
3664
  #on trie le résultat en place
3653
3665
  mysorted.sort(key=lambda x:x.s)
3654
3666
 
wolfhece/PyDraw.py CHANGED
@@ -102,8 +102,10 @@ except ImportError as e:
102
102
 
103
103
  try:
104
104
  from .dike import DikeWolf, InjectorWolf as InjectorDike
105
+ WOLFPYDIKE_AVAILABLE = True
105
106
  except:
106
107
  logging.warning(_("Missing package. Install wolfpydike module via pip."))
108
+ WOLFPYDIKE_AVAILABLE = False
107
109
 
108
110
  try:
109
111
  from .hydrometry.kiwis_wolfgui import hydrometry_wolfgui
@@ -2142,9 +2144,11 @@ class WolfMapViewer(wx.Frame):
2142
2144
  myviewers3d:list[Wolf_Viewer3D]
2143
2145
  mylazdata:list[Wolf_LAZ_Data]
2144
2146
  mydrownings: list[Drowning_victim_Viewer]
2145
- mydikes: list[DikeWolf]
2146
2147
  mypicturecollections: list[PictureCollection]
2147
- myinjectors: list[InjectorDike]
2148
+
2149
+ if WOLFPYDIKE_AVAILABLE:
2150
+ mydikes: list[DikeWolf]
2151
+ myinjectors: list[InjectorDike]
2148
2152
 
2149
2153
  mymplfigs:list[MplFigViewer]
2150
2154
 
@@ -2180,8 +2184,11 @@ class WolfMapViewer(wx.Frame):
2180
2184
  active_weir : Weir
2181
2185
  active_laz : Wolf_LAZ_Data
2182
2186
  active_drowning: Drowning_victim_Viewer
2183
- active_dike : DikeWolf
2184
- active_injector : InjectorDike
2187
+
2188
+ if WOLFPYDIKE_AVAILABLE:
2189
+ active_dike : DikeWolf
2190
+ active_injector : InjectorDike
2191
+
2185
2192
  active_picturecollection: PictureCollection
2186
2193
  active_alaro: IRM_Alaro
2187
2194
 
@@ -2406,7 +2413,9 @@ class WolfMapViewer(wx.Frame):
2406
2413
  create_acceptability = self.menucreateobj.Append(wx.ID_ANY, _('Create acceptability manager...'), _('Create acceptability manager'))
2407
2414
  create_inbe = self.menucreateobj.Append(wx.ID_ANY, _('Create INBE manager...'), _('Create INBE manager'))
2408
2415
  createdrowning = self.menucreateobj.Append(wx.ID_ANY, _('Create a drowning...'),_('Create a drowning'))
2409
- createdike = self.menucreateobj.Append(wx.ID_ANY, _('Create dike...'), _('New dike'))
2416
+
2417
+ if WOLFPYDIKE_AVAILABLE:
2418
+ createdike = self.menucreateobj.Append(wx.ID_ANY, _('Create dike...'), _('New dike'))
2410
2419
 
2411
2420
  self.filemenu.AppendSeparator()
2412
2421
 
@@ -2434,7 +2443,9 @@ class WolfMapViewer(wx.Frame):
2434
2443
  addweirs = self.menuaddobj.Append(wx.ID_ANY, _('Add weirs...'), _('Add bridges from directory'))
2435
2444
  addview = self.menuaddobj.Append(wx.ID_ANY, _('Add view...'), _('Add view from project file'))
2436
2445
  adddrowning = self.menuaddobj.Append(wx.ID_ANY, _('Add a drowning result...'),_('Add a drowning result'))
2437
- adddike = self.menuaddobj.Append(wx.ID_ANY, _('Add dike...'), _('Add dike'))
2446
+
2447
+ if WOLFPYDIKE_AVAILABLE:
2448
+ adddike = self.menuaddobj.Append(wx.ID_ANY, _('Add dike...'), _('Add dike'))
2438
2449
 
2439
2450
  self.precomputed_menu = None
2440
2451
  if self.default_dem != "":
@@ -4295,6 +4306,9 @@ class WolfMapViewer(wx.Frame):
4295
4306
 
4296
4307
  def Onmenudike(self, event: wx.MenuEvent):
4297
4308
 
4309
+ if not WOLFPYDIKE_AVAILABLE:
4310
+ raise ImportError('WolfPyDike not installed -- Please install WolfPyDike from pip to use this feature')
4311
+
4298
4312
  id = event.GetId()
4299
4313
  item = self.menubar.FindItemById(event.GetId())
4300
4314
 
@@ -6182,9 +6196,11 @@ class WolfMapViewer(wx.Frame):
6182
6196
  self.myviewerslaz = []
6183
6197
  self.mylazdata = []
6184
6198
  self.mydrownings = []
6199
+ self.mypicturecollections = []
6200
+
6185
6201
  self.mydikes = []
6186
6202
  self.myinjectors = []
6187
- self.mypicturecollections = []
6203
+
6188
6204
 
6189
6205
  self.mymplfigs = []
6190
6206
 
@@ -12114,6 +12130,10 @@ class WolfMapViewer(wx.Frame):
12114
12130
 
12115
12131
  elif which.lower() == 'dike':
12116
12132
 
12133
+ if not WOLFPYDIKE_AVAILABLE:
12134
+ logging.error('WolfPyDike module not available - cannot add dike')
12135
+ return -1
12136
+
12117
12137
  curdict = self.mydikes
12118
12138
  curtree = self.myitemsdike
12119
12139
 
@@ -14468,22 +14488,23 @@ class WolfMapViewer(wx.Frame):
14468
14488
  logging.info(_('Activating Drowning victim event : ' + nameitem))
14469
14489
  self.active_drowning = myobj
14470
14490
 
14471
- elif type(myobj) == DikeWolf:
14472
- logging.info(_('Activating DikeWolf : ' + nameitem))
14473
- self.active_dike = myobj
14474
- if myobj.injector is not None:
14475
- self.active_injector = myobj.injector
14476
- logging.info(_('Activating InjectorDike : ' + nameitem))
14491
+ elif WOLFPYDIKE_AVAILABLE:
14492
+ if type(myobj) == DikeWolf:
14493
+ logging.info(_('Activating DikeWolf : ' + nameitem))
14494
+ self.active_dike = myobj
14495
+ if myobj.injector is not None:
14496
+ self.active_injector = myobj.injector
14497
+ logging.info(_('Activating InjectorDike : ' + nameitem))
14477
14498
 
14478
- if ctrl:
14479
- myobj.show_properties()
14499
+ if ctrl:
14500
+ myobj.show_properties()
14480
14501
 
14481
- elif type(myobj) == InjectorDike:
14482
- logging.info(_('Activating InjectorDike : ' + nameitem))
14483
- self.active_injector = myobj
14502
+ elif type(myobj) == InjectorDike:
14503
+ logging.info(_('Activating InjectorDike : ' + nameitem))
14504
+ self.active_injector = myobj
14484
14505
 
14485
- if ctrl:
14486
- myobj.show_properties()
14506
+ if ctrl:
14507
+ myobj.show_properties()
14487
14508
 
14488
14509
  def _update_mytooltip(self):
14489
14510
  """ Update the tooltip with the values of the active arrays and results at position x,y """
wolfhece/apps/version.py CHANGED
@@ -5,7 +5,7 @@ class WolfVersion():
5
5
 
6
6
  self.major = 2
7
7
  self.minor = 2
8
- self.patch = 46
8
+ self.patch = 48
9
9
 
10
10
  def __str__(self):
11
11
 
wolfhece/apps/wolf.ico ADDED
Binary file
Binary file
@@ -618,7 +618,8 @@ class CSvsDEM():
618
618
  if output_file.exists():
619
619
  logging.warning(f"Output file {output_file} already exists. It will be overwritten.")
620
620
 
621
- page = CSvsDEM_IndividualLayout(_("Group {} - Index {} - Cross-Section {}").format(self.index_group, self.index_cs, self._cs.myname))
621
+ diff_left, diff_right = self.differences
622
+ page = CSvsDEM_IndividualLayout(_("Group {} - Index {} - CS {} - Delta_left {} - Delta_right {}").format(self.index_group, self.index_cs, self._cs.myname, diff_left, diff_right))
622
623
  page.create_report()
623
624
  self._complete_report(page)
624
625
  page.save_report(output_file)
wolfhece/wolf_array.py CHANGED
@@ -7698,18 +7698,32 @@ class WolfArray(Element_To_Draw, header_wolf):
7698
7698
 
7699
7699
  def interpolate_on_polygon(self, working_vector: vector,
7700
7700
  method:Literal["nearest", "linear", "cubic"]="linear",
7701
- keep:Literal['all', 'below', 'above'] = 'all'):
7701
+ keep:Literal['all', 'below', 'above'] = 'all',
7702
+ rescale:bool = False):
7702
7703
  """
7703
- Interpolation sous un polygone
7704
+ Interpolation sous un polygone.
7704
7705
 
7705
7706
  L'interpolation a lieu :
7706
7707
  - uniquement dans les mailles sélectionnées si elles existent
7707
7708
  - dans les mailles contenues dans le polygone sinon
7708
7709
 
7709
7710
  On utilise ensuite "griddata" de Scipy pour interpoler les altitudes des mailles
7710
- depuis les vertices 3D du polygone
7711
+ depuis les vertices 3D du polygone.
7712
+
7713
+ :ATTENTION: l'interpolation est réalisée en réels flottants 64 bits. Le résultat sera ensuite transformé dans le type de la matrice.
7714
+
7715
+ :param working_vector: vector - polygon with z values
7716
+ :param method: interpolation method - 'nearest', 'linear' or 'cubic'
7717
+ :param keep: 'all' to keep all interpolated values
7718
+ 'below' to keep only values below the current value in the array
7719
+ 'above' to keep only values above the current value in the array
7720
+ :param rescale: rescale the input data to [0, 1] for better numerical stability (only for 'linear' and 'cubic' methods)
7721
+ :return: None
7711
7722
  """
7712
7723
 
7724
+ if self.wolftype in [WOLF_ARRAY_FULL_INTEGER, WOLF_ARRAY_FULL_INTEGER8, WOLF_ARRAY_FULL_INTEGER16]:
7725
+ logging.info(_('Your array contains integer data. The interpolation will be done in float and then converted to integer using "np.ceil" operator.'))
7726
+
7713
7727
  if vector.area == 0.:
7714
7728
  logging.error(_('The polygon has no area'))
7715
7729
  return
@@ -7756,7 +7770,7 @@ class WolfArray(Element_To_Draw, header_wolf):
7756
7770
 
7757
7771
  xyz = working_vector.asnparray3d()
7758
7772
 
7759
- newvalues = griddata(xyz[:, :2], xyz[:, 2], destxy, method=method, fill_value=-99999.)
7773
+ newvalues = griddata(xyz[:, :2], xyz[:, 2], destxy, method=method, fill_value=-99999., rescale = rescale)
7760
7774
 
7761
7775
  if keep == 'all':
7762
7776
  locmask = np.where(newvalues != -99999.)
@@ -7765,6 +7779,11 @@ class WolfArray(Element_To_Draw, header_wolf):
7765
7779
  elif keep == 'above':
7766
7780
  locmask = np.where((newvalues != -99999.) & (newvalues > self.array.data[destij[:, 0], destij[:, 1]]))
7767
7781
 
7782
+ if self.wolftype in [WOLF_ARRAY_FULL_INTEGER, WOLF_ARRAY_FULL_INTEGER8, WOLF_ARRAY_FULL_INTEGER16]:
7783
+ logging.debug(_('Converting interpolated values to integer using "np.ceil" operator'))
7784
+ newvalues = np.ceil(newvalues)
7785
+ newvalues = newvalues.astype(self.array.dtype)
7786
+
7768
7787
  self.array.data[destij[locmask][:, 0], destij[locmask][:, 1]] = newvalues[locmask]
7769
7788
 
7770
7789
  def rasterize_vector_valuebyid(self, working_vector: vector, id,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: wolfhece
3
- Version: 2.2.46
3
+ Version: 2.2.48
4
4
  Author-email: Pierre Archambeau <pierre.archambeau@uliege.be>
5
5
  Project-URL: Homepage, https://uee.uliege.be/hece
6
6
  Project-URL: Issues, https://uee.uliege.be/hece
@@ -73,7 +73,7 @@ Requires-Dist: tabulate
73
73
  Requires-Dist: ipympl
74
74
  Requires-Dist: contextily
75
75
  Requires-Dist: pefile
76
- Requires-Dist: wolfpydike==0.1.3
76
+ Requires-Dist: wolfpydike==0.1.4
77
77
  Requires-Dist: PyMuPDF
78
78
  Requires-Dist: eccodes
79
79
  Requires-Dist: dataframe_image
@@ -1,4 +1,3 @@
1
- wolfhece/ChatwWOLF.py,sha256=B7MkwZiLYjR3OUNBcTIxDnYZzOBFDe52k880KTLUotc,10135
2
1
  wolfhece/Coordinates_operations.py,sha256=DSkzJ1Rm4y89I9tuyyAA9mp-EHp9vl5w2qGpNJ-e9qs,8215
3
2
  wolfhece/CpGrid.py,sha256=_piG1u-ua7NzWh_PHJYTmxuPJ43ZfeYKNEQgZIJwDJ8,10660
4
3
  wolfhece/GraphNotebook.py,sha256=_VZfakR5eXBZE-4Ztv2n12ZDO8zESoeDfCz_9k__T20,31509
@@ -9,8 +8,8 @@ wolfhece/Model1D.py,sha256=-2ibQLscVUsXlcnJWixCIScrBPqJ9BTirmwtGXEKI-4,571155
9
8
  wolfhece/MulticriteriAnalysis.py,sha256=vGmkzYagZohNe0XjwGJ6VUXcDPjOt80lNFthXpzxCF0,59572
10
9
  wolfhece/PandasGrid.py,sha256=etfVhIHzja4Z1EUY6BcDOKX-w7V-Xou1yaf0NMqmclo,4599
11
10
  wolfhece/PyConfig.py,sha256=13DDWjJdohYHwn1uRVHB0s8Jcwq_b9pwcwbAr8NlZyc,19667
12
- wolfhece/PyCrosssections.py,sha256=iNbDEvC3Ym9jtDzIaxifiNQgYG7vzbnSxUG8P_bcpbk,184104
13
- wolfhece/PyDraw.py,sha256=Wby6vq-xxQUIF-PoNNBJ4GNgrP6Ug5RX5A3eylYEDP8,744285
11
+ wolfhece/PyCrosssections.py,sha256=kCZBlX3idRY-QqJRHE6MPm4Qxz0AOVublV-JSJYUab8,184622
12
+ wolfhece/PyDraw.py,sha256=bAZGNQrwTJvdPCTnuPZbhj7IvXf9fcPIYofL5U72J9w,744916
14
13
  wolfhece/PyGui.py,sha256=z8m4M4Q7DVnRt_bEpEDjUl5x0FMkmsEnH2XHnGKWo14,185336
15
14
  wolfhece/PyGuiHydrology.py,sha256=dmBlRO8AljsvCPH6eVt0l9ZLx7g5j7Ubl9Srk7ECwyA,34693
16
15
  wolfhece/PyHydrographs.py,sha256=1P5XAURNqCvtSsMQXhOn1ihjTpr725sRsZdlCEhhk6M,3730
@@ -69,7 +68,7 @@ wolfhece/textpillow.py,sha256=7hgfsLYAaE_rNKD-g8xsON8sdWvoV8vbqnGGxIayShE,14137
69
68
  wolfhece/tools2d_dll.py,sha256=TfvvmyZUqEZIH0uHwUCJf0bdmCks_AiidDt23Unsp5w,13550
70
69
  wolfhece/tools_mpl.py,sha256=gQ3Jg1iuZiecmMqa5Eli2ZLSkttu68VXL8YmMDBaEYU,564
71
70
  wolfhece/toolshydrology_dll.py,sha256=cIGyhxV8H5f7GXhDqAamM7uC0W0hQTou3eTkqZdnqBE,5656
72
- wolfhece/wolf_array.py,sha256=AlVT-1o8D3UWIQcvBUP_oklHOx-vY__9cqdnF8lUtag,588219
71
+ wolfhece/wolf_array.py,sha256=eQGVH_yuJDqLixaho4JZzdPLf6pRf2jgrok86Uy6YUU,589560
73
72
  wolfhece/wolf_hist.py,sha256=fTEb60Q4TEwobdZsRU4CFXAId1eOKdWAqF8lnF1xEWc,3590
74
73
  wolfhece/wolf_texture.py,sha256=Pt1j_lX74p70Fj3y3qYxYMuN8gghVd8_ih1vFhTIdkA,23884
75
74
  wolfhece/wolf_tiles.py,sha256=v-HohqaWuMYdn75XLnA22dlloAG90iwnIqrgnB0ASQ4,10488
@@ -97,8 +96,10 @@ wolfhece/apps/curvedigitizer.py,sha256=lEJJwgAfulrrWQc-U6ij6sj59hWN3SZl4Yu1kQxVz
97
96
  wolfhece/apps/hydrometry.py,sha256=lhhJsFeb4zGL4bNQTs0co85OQ_6ssL1Oy0OUJCzhfYE,656
98
97
  wolfhece/apps/isocurrent.py,sha256=dagmGR8ja9QQ1gwz_8fU-N052hIw-W0mWGVkzLu6C7I,4247
99
98
  wolfhece/apps/splashscreen.py,sha256=EdGDN9NhudIiP7c3gVqj7dp4MWFB8ySizM_tpMnsgpE,3091
100
- wolfhece/apps/version.py,sha256=4c9wOXhaRWFeLjTaF-KQG_NPeaUiy87evcEae5WZrUE,388
99
+ wolfhece/apps/version.py,sha256=kWKMCvHZwgWn23QbobBBBQzDHb6aopNtwTwORkNiRX8,388
100
+ wolfhece/apps/wolf.ico,sha256=ej-kLodlUrQLsFDxpDhu2Mak7BTuWw6c9NCJaCBOkHI,238323
101
101
  wolfhece/apps/wolf.py,sha256=mRnjYsUu4KIsRuamdQWAINFMuwN4eJgMo9erG-hkZ70,729
102
+ wolfhece/apps/wolf2.png,sha256=YXd-MbtlxWRq38l5L6ky4Lg80DFuoZEKdbDwmeSsWqo,24714
102
103
  wolfhece/apps/wolf2D.py,sha256=4z_OPQ3IgaLtjexjMKX9ppvqEYyjFLt1hcfFABy3-jU,703
103
104
  wolfhece/apps/wolf_logo.bmp,sha256=ruJ4MA51CpGO_AYUp_dB4SWKHelvhOvd7Q8NrVOjDJk,3126
104
105
  wolfhece/apps/wolf_logo2.bmp,sha256=pCJFVDn_-rHru6fumazVNM4BqAaobM0Xg0zI0DFWMSQ,5830
@@ -286,7 +287,7 @@ wolfhece/rem/__init__.py,sha256=S2-J5uEGK_VaMFjRUYFIdSScJjZyuXH4RmMmnG3OG7I,19
286
287
  wolfhece/report/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
287
288
  wolfhece/report/common.py,sha256=7nRf1DEXancWsh3V-mqSIqqleaquxn7HemTPTR-8cZ0,21311
288
289
  wolfhece/report/compare_arrays.py,sha256=vduobNVgrhWC1LNgCNP7MJ5Dv1Bs-6omUqacbV9-H4w,44050
289
- wolfhece/report/compare_cs_dem.py,sha256=KujOAaHoHEFyDYrRpAzkUqHgeTFhBpe4xi2efTCz_ig,59517
290
+ wolfhece/report/compare_cs_dem.py,sha256=kojFuXYEUGBB1dgt2W7CROU8ic9idHgQjiHkJHBFPRw,59612
290
291
  wolfhece/report/pdf.py,sha256=WNz-uPDASvAtnP-rJaRRdz0nwiSs8XXWe4622FmeVVM,1953
291
292
  wolfhece/report/reporting.py,sha256=JUEXovx_S4jpYkJEBU0AC-1Qw2OkkWyV3VAp6iOfSHc,19494
292
293
  wolfhece/report/simplesimgpu.py,sha256=nQK1lY9-uSNTA34N9D5U_ftgCVaSMjtq1zPzz2nO7ts,58622
@@ -323,8 +324,8 @@ wolfhece/ui/wolf_multiselection_collapsiblepane.py,sha256=u4C7CXe_bUyGKx7c_Bi0x9
323
324
  wolfhece/ui/wolf_times_selection_comparison_models.py,sha256=ORy7fz4dcp691qKzaOZHrRLZ0uXNhL-LIHxmpDGL6BI,5007
324
325
  wolfhece/wintab/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
325
326
  wolfhece/wintab/wintab.py,sha256=8A-JNONV6ujgsgG3lM5Uw-pVgglPATwKs86oBzzljoc,7179
326
- wolfhece-2.2.46.dist-info/METADATA,sha256=vnmf6HdA8sIxenewSqj2Q-i0azUU9KmlfzywqlRCkVA,2792
327
- wolfhece-2.2.46.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
328
- wolfhece-2.2.46.dist-info/entry_points.txt,sha256=Jr187pyvA3EeJiQLjZK9yo6mJX7IAn6ygZU9T8qF_gQ,658
329
- wolfhece-2.2.46.dist-info/top_level.txt,sha256=EfqZXMVCn7eILUzx9xsEu2oBbSo9liWPFWjIHik0iCI,9
330
- wolfhece-2.2.46.dist-info/RECORD,,
327
+ wolfhece-2.2.48.dist-info/METADATA,sha256=4QTa1R2s7lMNa7-ld4itSLW-MEE3w4erdAGxarCPOsY,2792
328
+ wolfhece-2.2.48.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
329
+ wolfhece-2.2.48.dist-info/entry_points.txt,sha256=Jr187pyvA3EeJiQLjZK9yo6mJX7IAn6ygZU9T8qF_gQ,658
330
+ wolfhece-2.2.48.dist-info/top_level.txt,sha256=EfqZXMVCn7eILUzx9xsEu2oBbSo9liWPFWjIHik0iCI,9
331
+ wolfhece-2.2.48.dist-info/RECORD,,
wolfhece/ChatwWOLF.py DELETED
@@ -1,200 +0,0 @@
1
- # Préparation des données pour le modèle ChatWOLF, machine conversationnelle spécialisée dans les questions relatives à WOLF.
2
- # Les données sont principalemen extraites des fichiers rst de l'aide en ligne mais également des fichiers py de l'API.
3
- import torch
4
- print(torch.cuda.is_available())
5
-
6
- # Importation des modules nécessaires
7
- import os
8
- import re
9
- import json
10
- from pathlib import Path
11
- from typing import List, Dict, Any
12
- from langchain.text_splitter import RecursiveCharacterTextSplitter
13
- from langchain.docstore.document import Document
14
- from langchain_huggingface import HuggingFaceEmbeddings
15
- from langchain_community.vectorstores import FAISS
16
- from langchain.chains.retrieval_qa.base import RetrievalQA
17
- from langchain_community.llms.huggingface_pipeline import HuggingFacePipeline
18
- from transformers import pipeline, AutoModelForCausalLM, AutoTokenizer
19
- from sklearn.model_selection import train_test_split
20
- from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
21
- import torch
22
- from datasets import load_dataset, Dataset
23
- from transformers import Trainer, TrainingArguments
24
- import logging
25
-
26
- logging.basicConfig(level=logging.INFO)
27
- logger = logging.getLogger(__name__)
28
-
29
- rst_directory = Path("D:/ProgrammationGitLab/HECEPython/docs/source")
30
- py_directory = Path("D:/ProgrammationGitLab/HECEPython/wolfhece")
31
- output_directory = Path("D:/ProgrammationGitLab/HECEPython/wolfhece/models/chatwolf")
32
- output_directory.mkdir(parents=True, exist_ok=True)
33
-
34
- # Fonction pour extraire le texte des fichiers rst
35
- def extract_text_from_rst(file_path: Path) -> str:
36
- with open(file_path, 'r', encoding='utf-8') as file:
37
- text = file.read()
38
- # Nettoyage du texte
39
- text = re.sub(r'\.\. _.*?:', '', text) # Remove references
40
- text = re.sub(r'\.\. note::.*?\n\n', '', text, flags=re.DOTALL) # Remove notes
41
- text = re.sub(r'\.\. warning::.*?\n\n', '', text, flags=re.DOTALL) # Remove warnings
42
- text = re.sub(r'\.\. code-block::.*?\n\n', '', text, flags=re.DOTALL) # Remove code blocks
43
- text = re.sub(r'\.\. image::.*?\n\n', '', text, flags=re.DOTALL) # Remove images
44
- text = re.sub(r'\.\. figure::.*?\n\n', '', text, flags=re.DOTALL) # Remove figures
45
- text = re.sub(r'\.\. table::.*?\n\n', '', text, flags=re.DOTALL) # Remove tables
46
- text = re.sub(r'\.\. rubric::.*?\n\n', '', text, flags=re.DOTALL) # Remove rubrics
47
- text = re.sub(r'\.\. sidebar::.*?\n\n', '', text, flags=re.DOTALL) # Remove sidebars
48
- text = re.sub(r'\.\. literalinclude::.*?\n\n', '', text, flags=re.DOTALL) # Remove literal includes
49
- text = re.sub(r'\.\. math::.*?\n\n', '', text, flags=re.DOTALL) # Remove math
50
- text = re.sub(r'\.\. raw::.*?\n\n', '', text, flags=re.DOTALL) # Remove raw
51
- text = re.sub(r'\.\. toctree::.*?\n\n', '', text, flags=re.DOTALL) # Remove toctree
52
- text = re.sub(r'\.\. index::.*?\n\n', '', text, flags=re.DOTALL) # Remove index
53
- text = re.sub(r'\.\. glossary::.*?\n\n', '', text, flags=re.DOTALL) # Remove glossary
54
- text = re.sub(r'\.\. footnote::.*?\n\n', '', text, flags=re.DOTALL) # Remove footnotes
55
- text = re.sub(r'\.\. citation::.*?\n\n', '', text, flags=re.DOTALL) # Remove citations
56
- text = re.sub(r'\.\. epigraph::.*?\n\n', '', text, flags=re.DOTALL) # Remove epigraphs
57
- text = re.sub(r'\.\. highlight::.*?\n\n', '', text, flags=re.DOTALL) # Remove highlights
58
- text = re.sub(r'\.\. hlist::.*?\n\n', '', text, flags=re.DOTALL) # Remove hlists
59
- text = re.sub(r'\.\. csv-table::.*?\n\n', '', text, flags=re.DOTALL) # Remove csv-tables
60
- text = re.sub(r'\.\. list-table::.*?\n\n', '', text, flags=re.DOTALL) # Remove list-tables
61
- text = re.sub(r'\.\. contents::.*?\n\n', '', text, flags=re.DOTALL) # Remove contents
62
- text = re.sub(r'\.\. include::.*?\n\n', '', text, flags=re.DOTALL) # Remove includes
63
- text = re.sub(r'\.\. admonition::.*?\n\n', '', text, flags=re.DOTALL) # Remove admonitions
64
- text = re.sub(r'\.\. note::.*?\n\n', '', text, flags=re.DOTALL) # Remove notes
65
- text = re.sub(r'\.\. tip::.*?\n\n', '', text, flags=re.DOTALL) # Remove tips
66
- text = re.sub(r'\.\. important::.*?\n\n', '', text, flags=re.DOTALL) # Remove importants
67
- text = re.sub(r'\.\. caution::.*?\n\n', '', text, flags=re.DOTALL) # Remove cautions
68
- text = re.sub(r'\.\. seealso::.*?\n\n', '', text, flags=re.DOTALL) # Remove seealso
69
-
70
- return text
71
-
72
- def scan_files() -> List[Path]:
73
- # Scan all files and extract text
74
- documents = []
75
- for rst_file in rst_directory.rglob("*.rst"):
76
- text = extract_text_from_rst(rst_file)
77
- if text.strip(): # Only add non-empty documents
78
- documents.append(Document(page_content=text, metadata={"source": str(rst_file)}))
79
- logger.info(f"Extracted text from {rst_file}")
80
- for py_file in py_directory.rglob("*.py"):
81
- with open(py_file, 'r', encoding='utf-8') as file:
82
- text = file.read()
83
- if text.strip(): # Only add non-empty documents
84
- documents.append(Document(page_content=text, metadata={"source": str(py_file)}))
85
- logger.info(f"Extracted text from {py_file}")
86
- logger.info(f"Total documents extracted: {len(documents)}")
87
- return documents
88
-
89
- def split_and_prepare_data(documents: List[Document]) -> None:
90
- # Split documents into smaller chunks
91
- text_splitter = RecursiveCharacterTextSplitter(
92
- chunk_size=1000,
93
- chunk_overlap=100,
94
- length_function=len
95
- )
96
- texts = text_splitter.split_documents(documents)
97
- logger.info(f"Total text chunks created: {len(texts)}")
98
- # Save texts to JSONL for dataset creation
99
- jsonl_path = output_directory / "chatwolf_data.jsonl"
100
- with open(jsonl_path, 'w', encoding='utf-8') as f:
101
- for text in texts:
102
- json.dump({"text": text.page_content}, f)
103
- f.write('\n')
104
- logger.info(f"Saved text chunks to {jsonl_path}")
105
- return texts, jsonl_path
106
-
107
- def train_model():
108
- # Load dataset
109
- dataset = load_dataset('json', data_files=str(jsonl_path))['train']
110
- # Split dataset into training and validation sets
111
- train_test_split = dataset.train_test_split(test_size=0.1)
112
- train_dataset = train_test_split['train']
113
- eval_dataset = train_test_split['test']
114
- logger.info(f"Training dataset size: {len(train_dataset)}")
115
- logger.info(f"Validation dataset size: {len(eval_dataset)}")
116
- # Define model and tokenizer
117
- model_name = "gpt2"
118
- tokenizer = AutoTokenizer.from_pretrained(model_name, use_fast=True)
119
- if tokenizer.pad_token is None:
120
- tokenizer.pad_token = tokenizer.eos_token
121
- model = AutoModelForCausalLM.from_pretrained(model_name)
122
- # Define training arguments
123
- training_args = TrainingArguments(
124
- output_dir=output_directory / "output",
125
- eval_strategy="epoch",
126
- num_train_epochs=3,
127
- per_device_train_batch_size=1,
128
- per_device_eval_batch_size=1,
129
- save_strategy="epoch",
130
- logging_dir=output_directory / "logs",
131
- logging_steps=10,
132
- save_total_limit=2,
133
- fp16=False, # Set to False to avoid FP16 errors on unsupported hardware
134
- load_best_model_at_end=True,
135
- )
136
- # Define data collator
137
- def tokenize_function(examples):
138
- return tokenizer(examples["text"], padding="max_length", truncation=True, max_length=512)
139
- train_dataset = train_dataset.map(tokenize_function, batched=True)
140
- eval_dataset = eval_dataset.map(tokenize_function, batched=True)
141
- train_dataset.set_format(type='torch', columns=['input_ids', 'attention_mask'])
142
- eval_dataset.set_format(type='torch', columns=['input_ids', 'attention_mask'])
143
- # Define data collator for causal language modeling
144
- from transformers import DataCollatorForLanguageModeling
145
- data_collator = DataCollatorForLanguageModeling(
146
- tokenizer=tokenizer,
147
- mlm=False,
148
- )
149
- # Initialize Trainer
150
- trainer = Trainer(
151
- model=model,
152
- args=training_args,
153
- train_dataset=train_dataset,
154
- eval_dataset=eval_dataset,
155
- tokenizer=tokenizer,
156
- data_collator=data_collator,
157
- )
158
- # Train the model
159
- trainer.train()
160
- # Save the fine-tuned model
161
- trainer.save_model(output_directory / "chatwolf_model")
162
- logger.info(f"Saved fine-tuned model to {output_directory / 'chatwolf_model'}")
163
- return model, tokenizer
164
-
165
- def load_model_and_tokenizer():
166
- model = AutoModelForCausalLM.from_pretrained(output_directory / "chatwolf_model")
167
- tokenizer = AutoTokenizer.from_pretrained("gpt2", use_fast=True)
168
- if tokenizer.pad_token is None:
169
- tokenizer.pad_token = tokenizer.eos_token
170
- return model, tokenizer
171
-
172
- documents = scan_files()
173
- texts, jsonl_path = split_and_prepare_data(documents)
174
-
175
- if False:
176
- model, tokenizer = train_model()
177
- else:
178
- model, tokenizer = load_model_and_tokenizer()
179
-
180
-
181
- # Create embeddings and vector store
182
- embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2")
183
- vector_store = FAISS.from_documents(texts, embeddings)
184
- vector_store.save_local(str(output_directory / "faiss_index"))
185
- logger.info(f"Saved FAISS index to {output_directory / 'faiss_index'}")
186
- # Create retrieval QA chain
187
- llm_pipeline = pipeline("text-generation", model=model, tokenizer=tokenizer, max_new_tokens=512, temperature=0.7, top_p=0.9, repetition_penalty=1.2)
188
- hf_llm = HuggingFacePipeline(pipeline=llm_pipeline)
189
- qa_chain = RetrievalQA.from_chain_type(llm=hf_llm, chain_type="stuff", retriever=vector_store.as_retriever())
190
- # Save the QA chain
191
- import pickle
192
- with open(output_directory / "qa_chain.pkl", 'wb') as f:
193
- pickle.dump(qa_chain, f)
194
- logger.info(f"Saved QA chain to {output_directory / 'qa_chain.pkl'}")
195
- # Example usage of the QA chain
196
- def answer_question(question: str) -> str:
197
- return qa_chain.run(question)
198
- example_question = "How to create a new map in WOLF?"
199
- answer = answer_question(example_question)
200
- logger.info(f"Question: {example_question}\nAnswer: {answer}")