wolfhece 2.1.119__py3-none-any.whl → 2.1.121__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.
@@ -152,7 +152,7 @@ class Accept_Manager():
152
152
 
153
153
  def __init__(self,
154
154
  main_dir:str = 'Data',
155
- Study_area:str = 'Bassin_Vesdre.shp',
155
+ Study_area = None,
156
156
  scenario = None,
157
157
  Original_gdb:str = 'GT_Resilence_dataRisques202010.gdb',
158
158
  CaPa_Walloon:str = 'Cadastre_Walloon.gpkg',
@@ -171,9 +171,7 @@ class Accept_Manager():
171
171
  # If it is a string, concatenate it with the current directory
172
172
  if not self.main_dir.is_absolute():
173
173
  self.main_dir = Path(os.getcwd()) / self.main_dir
174
-
175
- self._study_area = str(Study_area)
176
-
174
+ self._study_area = Study_area
177
175
  if Study_area is not None:
178
176
  if not str(self._study_area).endswith('.shp'):
179
177
  self._study_area += '.shp'
@@ -391,7 +389,7 @@ class Accept_Manager():
391
389
  self._study_area = None
392
390
  self._scenario = None
393
391
  else:
394
- if Study_area in self.get_list_studyareas(with_suffix=True):
392
+ if Study_area in self.get_list_studyareas(with_suffix=True) or Study_area+".shp" in self.get_list_studyareas(with_suffix=True):
395
393
  self._study_area = Path(Study_area)
396
394
  else:
397
395
  logging.error("The study area does not exist in the study area directory")
@@ -474,18 +472,17 @@ class Accept_Manager():
474
472
  sims = self.get_sims_files_for_scenario()
475
473
 
476
474
  if len(sims)==0:
477
- logging.info("No simulations found") #no error, need to act if so. See accept manager flow chart
475
+ logging.info("No simulations found at this stage")
478
476
  return None
479
477
 
480
478
  if "_h.tif" in sims[0].name:
481
479
  for cursim in sims:
482
- if cursim.stem.find("_T{}_".format(return_period)) != -1:
480
+ if cursim.stem.find("_T{}_".format(return_period)) != -1 or cursim.stem.find("_Q{}_".format(return_period)) != -1:
483
481
  return cursim
484
482
  else:
485
483
  for cursim in sims:
486
- if cursim.stem.find("T{}".format(return_period)) != -1:
484
+ if cursim.stem.find("T{}".format(return_period)) != -1 or cursim.stem.find("Q{}".format(return_period)) != -1:
487
485
  return cursim
488
-
489
486
  return None
490
487
 
491
488
  def get_types_in_file(self, file:str) -> list[str]:
@@ -560,44 +557,36 @@ class Accept_Manager():
560
557
 
561
558
  # List files in directory
562
559
  sims = self.get_sims_files_for_scenario()
563
-
560
+ sims_modif = [
561
+ os.path.join(os.path.dirname(path), os.path.basename(path).replace("Q", "T"))
562
+ for path in sims
563
+ ]
564
+
564
565
  if len(sims)==0:
565
- logging.info("No simulations found")#no error, need to act if so. See accept manager flow chart
566
+ logging.info("No simulations found at this stage.")
566
567
  return []
567
568
 
568
- # Two cases:
569
- # - Return periods are named as T2.tif, T5.tif, T10.tif, ...
570
- # - Return periods are named as *_T2_h.tif, *_T5_h.tif, *_T10_h.tif, ...
571
-
572
- if "_h.tif" in sims[0].name:
573
-
574
- # Searching for the position of the return period in the name
575
- idx_T = [cursim.name.find("_T") for cursim in sims]
576
- idx_h = [cursim.name.find("_h.tif") for cursim in sims]
577
-
578
- assert len(idx_T) == len(idx_h), "The number of T and h are not the same"
579
- for curT, curh in zip(idx_T, idx_h):
580
- assert curT != -1, "The T is not found"
581
- assert curh != -1, "The h is not found"
582
- assert curh > curT, "The h is before the T"
583
-
584
- # Create the list of return periods -- only the numeric part
585
- sims = [int(cursim.name[idx_T[i]+2:idx_h[i]]) for i, cursim in enumerate(sims)]
586
- else:
587
- # searching for the position of the return period in the name
588
- idx_T = [cursim.name.find("T") for cursim in sims]
589
- idx_h = [cursim.name.find(".tif") for cursim in sims]
590
-
591
- assert len(idx_T) == len(idx_h), "The number of T and h are not the same"
592
- for curT, curh in zip(idx_T, idx_h):
593
- assert curT != -1, "The T is not found"
594
- assert curh != -1, "The h is not found"
595
- assert curh > curT, "The h is before the T"
596
-
597
- # create the list of return periods -- only the numeric part
598
- sims = [int(cursim.name[idx_T[i]+1:idx_h[i]]) for i, cursim in enumerate(sims)]
599
-
569
+ # - Return periods are named as T2.tif, T5.tif, T10.tif, ... or with Q instead of T
570
+ # searching for the position of the return period in the name
571
+ idx_T = [Path(cursim).name.find("T") for cursim in sims_modif]
572
+ idx_h = [Path(cursim).name.find(".tif") for cursim in sims_modif]
573
+
574
+ # create the list of return periods -- only the numeric part
575
+ sims = [int(Path(cursim).name[idx_T[i]+1:idx_h[i]]) for i, cursim in enumerate(sims_modif)]
600
576
  return sorted(sims)
577
+
578
+ def get_modifiedrasters(self):
579
+ folder = Path(self.IN_CH_SA_SC)
580
+ vuln_tiff_files = [str(file.name) for file in folder.rglob("*.tiff") if file.name.startswith('vuln_')]
581
+ vuln_tif_files = [str(file.name)for file in folder.rglob("*.tif") if file.name.startswith('vuln_')]
582
+ vuln_files = vuln_tiff_files + vuln_tif_files
583
+
584
+ folder = Path(self.IN_CH_SA_SC)
585
+ mnt_tiff_files = [str(file.name) for file in folder.rglob("*.tiff") if file.name.startswith('MNTmodifs_')]
586
+ mnt_tif_files = [str(file.name) for file in folder.rglob("*.tif") if file.name.startswith('MNTmodifs_')]
587
+ mnt_files = mnt_tiff_files + mnt_tif_files
588
+
589
+ return vuln_files + mnt_files
601
590
 
602
591
  def get_ponderations(self) -> pd.DataFrame:
603
592
  """ Get the ponderation data from available simulations """
@@ -605,11 +594,11 @@ class Accept_Manager():
605
594
  rt = self.get_return_periods()
606
595
 
607
596
  if len(rt)==0:
608
- logging.info("No simulations found")
597
+ logging.info("No simulations found at this stage.")
609
598
  return None
610
599
 
611
600
  if len(rt)<2:
612
- logging.info("There is only one simulation!")
601
+ logging.info("There is only one simulation! Weigthing coefficient is unique and set to 1.")
613
602
  return pd.DataFrame(1, columns=["Ponderation"], index=rt)
614
603
 
615
604
  else :
@@ -979,7 +968,7 @@ class Accept_Manager():
979
968
 
980
969
  def select_name_tif(self, path_baseline: Path, folder_path: Path, name) -> list[Path]:
981
970
  """
982
- Collects and appends all .tiff files starting with 'vuln' from folder_path into a list.
971
+ Collects and appends all .tiff files starting with 'name' from folder_path into a list.
983
972
  """
984
973
  files = []
985
974
  #first element must be vulnerability_baseline
@@ -991,23 +980,21 @@ class Accept_Manager():
991
980
  files.append(tree[-1].as_posix())
992
981
  return files
993
982
 
994
- def check_nodata(self, name):
983
+ def check_nodata(self, name, path_baseline):
995
984
  """ Check nodata in a path """
996
-
997
- list_tif = Accept_Manager.select_name_tif(self, self.OUT_VULN, self.IN_CH_SA_SC, name)
985
+ list_tif = Accept_Manager.select_name_tif(self, path_baseline, self.IN_CH_SA_SC, name)
998
986
  for cur_lst in list_tif:
999
- if "Vulnerability.tiff" not in cur_lst:
1000
- curarray:WolfArray = WolfArray(cur_lst)
1001
- if curarray.nullvalue != 99999.:
1002
- curarray.nullvalue = 99999.
1003
- curarray.set_nullvalue_in_mask()
1004
- curarray.write_all()
1005
- logging.warning(_('nodata changed in favor of 99999. value for file {} !'.format(cur_lst)))
987
+ curarray:WolfArray = WolfArray(cur_lst)
988
+ if curarray.nullvalue != 99999.:
989
+ curarray.nullvalue = 99999.
990
+ curarray.set_nullvalue_in_mask()
991
+ curarray.write_all()
992
+ logging.warning(_('nodata changed in favor of 99999. value for file {} !'.format(cur_lst)))
1006
993
 
1007
994
  def create_vrtIfExists(self, fn_baseline, fn_scenario, fn_vrt, name):
1008
995
  """ Create a vrt file from a path """
1009
996
  logging.info(_('Checking nodata values...'))
1010
- self.check_nodata(name)
997
+ self.check_nodata(name, fn_baseline)
1011
998
  list_tif = Accept_Manager.select_name_tif(self, fn_baseline, fn_scenario, name)
1012
999
  #création du fichier vrt - assembly/agglomération
1013
1000
  if len(list_tif)>1:
@@ -1536,7 +1523,8 @@ def match_vulnerability2sim(inRas:Path, outRas:Path, MODREC:Path):
1536
1523
  def update_accept(accept, model_h, ij, bounds, loc_accept):
1537
1524
  for idx in range(len(bounds)):
1538
1525
  for i,j in ij:
1539
- if bounds[idx,0] < model_h[i,j] <= bounds[idx,1]: #lit dans wd vs Ti où on est et associe son score d'accept
1526
+ #lit dans wd vs Ti où on est et associe son score d'accept
1527
+ if bounds[idx,0] < model_h[i,j] <= bounds[idx,1]:
1540
1528
  accept[i,j] = loc_accept[idx]
1541
1529
 
1542
1530
  def compute_acceptability(manager:Accept_Manager,
@@ -58,6 +58,45 @@ def main():
58
58
  ret += 'Wolfhece not installed properly\n Please install the VC++ redistributable\n from https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads\n\n'
59
59
  ret += 'Error : ' + str(e) + '\n\n'
60
60
 
61
+ from pathlib import Path
62
+ dirlaz = Path(__file__).parent.parent / 'lazviewer'
63
+ dirs_to_test = [dirlaz / 'libs', dirlaz / 'libs/qt_plugins', dirlaz / 'libs/qt_plugins/platforms']
64
+
65
+ for d in dirs_to_test:
66
+ if not d.exists() or not d.is_dir():
67
+ ret += str(d) + ' does not exist\n\n'
68
+
69
+ curdir = dirlaz / 'libs/qt_plugins/platforms'
70
+ files_to_test = [curdir / 'qwindows.dll']
71
+
72
+ for f in files_to_test:
73
+ if not f.exists() or not f.is_file():
74
+ ret += str(f) + ' does not exist\n\n'
75
+
76
+ curdir = dirlaz / 'libs'
77
+ files_to_test = [curdir / 'icudt53.dll', curdir / 'icuin53.dll', curdir / 'icuuc53.dll',
78
+ curdir / 'msvcp120.dll', curdir / 'msvcr120.dll', curdir / 'Qt5Core.dll',
79
+ curdir / 'Qt5Gui.dll', curdir / 'Qt5Network.dll', curdir / 'Qt5Widgets.dll',
80
+ curdir / 'tbb.dll', curdir / 'tbbmalloc.dll', curdir / 'vcomp120.dll']
81
+
82
+ for f in files_to_test:
83
+ if not f.exists() or not f.is_file():
84
+ ret += str(f) + ' does not exist\n\n'
85
+
86
+ try:
87
+ from ..lazviewer.viewer import viewer
88
+ import numpy as np
89
+
90
+ pts = np.array([[0, 0, 0], [1, 1, 1], [2, 2, 2]])
91
+ myview = viewer.viewer(pts, debug = True)
92
+
93
+ ret += 'LAZ viewer created in debug mode -- check for errors if reported\n\n'
94
+
95
+ except ImportError as e:
96
+ ret += 'Could not import/create LAZ viewer\n\n'
97
+ ret += 'Wolfhece not installed properly\n Please check if QT \n\n'
98
+ ret += 'Error : ' + str(e) + '\n\n'
99
+
61
100
  print(ret)
62
101
 
63
102
  if __name__=='__main__':
wolfhece/apps/version.py CHANGED
@@ -5,7 +5,7 @@ class WolfVersion():
5
5
 
6
6
  self.major = 2
7
7
  self.minor = 1
8
- self.patch = 119
8
+ self.patch = 121
9
9
 
10
10
  def __str__(self):
11
11
 
@@ -1,23 +1,23 @@
1
- import os
2
- import os.path
3
- import sys
4
- import platform
1
+ # import os
2
+ # import os.path
3
+ # import sys
4
+ # import platform
5
5
 
6
6
 
7
- def _add_path():
8
- _root_dir = os.path.dirname(os.path.realpath(__file__))
7
+ # def _add_path():
8
+ # _root_dir = os.path.dirname(os.path.realpath(__file__))
9
9
 
10
- # manual specify list of dll directories, with paths relative to _root_dir
11
- _dll_dirs = ['libs']
10
+ # # manual specify list of dll directories, with paths relative to _root_dir
11
+ # _dll_dirs = ['libs']
12
12
 
13
- if platform.system() == 'Windows':
14
- os.environ.setdefault('PATH', '')
15
- paths = os.environ['PATH'].split(';')
16
- for x in _dll_dirs:
17
- x = os.path.join(_root_dir, x)
18
- if os.path.isdir(x) and x not in paths:
19
- paths = [x] + paths
20
- os.environ['PATH'] = ';'.join(paths)
13
+ # if platform.system() == 'Windows':
14
+ # os.environ.setdefault('PATH', '')
15
+ # paths = os.environ['PATH'].split(';')
16
+ # for x in _dll_dirs:
17
+ # x = os.path.join(_root_dir, x)
18
+ # if os.path.isdir(x) and x not in paths:
19
+ # paths = [x] + paths
20
+ # os.environ['PATH'] = ';'.join(paths)
21
21
 
22
22
 
23
- _add_path()
23
+ # _add_path()
@@ -23,7 +23,7 @@ from ..PyWMS import getWalonmap
23
23
  from ..PyTranslate import _
24
24
  from ..color_constants import Colors
25
25
  from ..PyParams import Wolf_Param, Type_Param
26
- from ..matplotlib_fig import Matplotlib_Figure as MplFig
26
+ from ..matplotlib_fig import Matplotlib_Figure as MplFig, PRESET_LAYOUTS
27
27
  from ..drawing_obj import Element_To_Draw
28
28
  from ..CpGrid import CpGrid
29
29
  from ..PyVertexvectors import vector, Zones, zone, wolfvertex
@@ -375,6 +375,35 @@ class xyz_laz_grid():
375
375
 
376
376
  return retdata
377
377
 
378
+ def find_files_in_bounds(self, bounds:Union[tuple[tuple[float,float],tuple[float,float]], list[list[float, float],list[float, float]]]):
379
+ """ Find all files in bounds """
380
+
381
+ x1=bounds[0][0]
382
+ x2=bounds[0][1]
383
+ y1=bounds[1][0]
384
+ y2=bounds[1][1]
385
+
386
+ file1= self.genfile.split('x1')[0]
387
+ file2= self.genfile.split('y1')[-1]
388
+
389
+ files=[]
390
+
391
+ for x in range(int(self.origx), int(self.endx), int(self.dx)):
392
+ for y in range(int(self.origy), int(self.endy), int(self.dy)):
393
+
394
+ locbounds=np.float64(((x,x+self.dx),(y,y+self.dy)))
395
+
396
+ test = not(x2 < locbounds[0][0] or x1 > locbounds[0][1] or y2 < locbounds[1][0] or y1 > locbounds[1][1])
397
+
398
+ if test:
399
+ fxyz = file1+str(int(x))+'_'+str(int(y))+file2
400
+
401
+ fn = join(self.mydir,fxyz)
402
+ if exists(fn):
403
+ files.append(fn)
404
+
405
+ return files
406
+
378
407
  def _split_xyz(self, dirout:str, nbparts:int = 10):
379
408
  """ Split XYZ file into 'nb' parts along X and Y """
380
409
  for entry in scandir(self.mydir):
@@ -494,7 +523,7 @@ class xyz_laz_grids():
494
523
  """ Ensemble de grids """
495
524
 
496
525
  def __init__(self, dir_grids:str, create:bool=False) -> None:
497
- self.grids = []
526
+ self.grids:list[xyz_laz_grid] = []
498
527
  self.colors = Classification_LAZ()
499
528
  self.colors.init_2023()
500
529
 
@@ -527,6 +556,36 @@ class xyz_laz_grids():
527
556
  logging.info(_('Data found -- {} points'.format(ret.shape[0])))
528
557
  return ret
529
558
 
559
+ def find_files_in_bounds(self, bounds:Union[tuple[tuple[float,float],tuple[float,float]], list[list[float, float],list[float, float]]]):
560
+
561
+ ret = [(cur.mydir, cur.find_files_in_bounds(bounds)) for cur in self.grids]
562
+ ret = [cur for cur in ret if len(cur[1])>0]
563
+
564
+ if len(ret)==0:
565
+ logging.info(_('No data found'))
566
+ return []
567
+ else:
568
+ logging.info(_('Data found -- {} files'.format(len(ret))))
569
+ return ret
570
+
571
+ def copy_files_in_bounds(self, bounds:Union[tuple[tuple[float,float],tuple[float,float]], list[list[float, float],list[float, float]]], dirout:str):
572
+
573
+ import shutil
574
+
575
+ out = Path(dirout)
576
+ out.mkdir(exist_ok=True)
577
+
578
+ files = self.find_files_in_bounds(bounds)
579
+
580
+ for curdir, curfiles in files:
581
+ locdir = dirout / Path(curdir).parent.name
582
+ locdir.mkdir(exist_ok=True)
583
+ for curfile in curfiles:
584
+ shutil.copy(curfile, locdir / Path(curfile).name)
585
+
586
+ # copy gridinfo.txt
587
+ shutil.copy(join(curdir,'gridinfo.txt'), locdir / 'gridinfo.txt')
588
+
530
589
  def read_dir(self, dir_grids):
531
590
  dirs = listdir(dir_grids)
532
591
 
@@ -637,14 +696,11 @@ class xyz_laz_grids():
637
696
 
638
697
  (up_s, up_z, up_color), (down_s, down_z, down_color) = self.scan_around(xy, length_buffer)
639
698
 
640
- figmpl = MplFig()
641
- figmpl.presets()
642
- fig = figmpl.fig
643
- ax = figmpl.cur_ax
699
+ figmpl = MplFig(PRESET_LAYOUTS.DEFAULT)
644
700
 
645
701
  logging.info(_('Plotting'))
646
- ax.scatter(up_s, up_z, c=up_color ,marker='.')
647
- ax.scatter(down_s, down_z,c=down_color,marker='+')
702
+ figmpl.plot(up_s, up_z, c=up_color ,marker='.')
703
+ figmpl.plot(down_s, down_z,c=down_color,marker='+')
648
704
 
649
705
  if show:
650
706
  figmpl.Show()
@@ -883,9 +939,12 @@ class Wolf_LAZ_Data(Element_To_Draw):
883
939
 
884
940
  nb1 = self.data.shape[0]
885
941
  if self.viewer is not None:
886
- nb2 = self.viewer.get('num_points')[0]
887
- assert nb1 == nb2, _('Incoherent number of points')
888
-
942
+ try:
943
+ nb2 = self.viewer.get('num_points')[0]
944
+ assert nb1 == nb2, _('Incoherent number of points')
945
+ except:
946
+ # viewer is not initialized or Destroyed
947
+ self.viewer = None
889
948
  return nb1
890
949
 
891
950
  @property
@@ -1138,7 +1197,7 @@ class Wolf_LAZ_Data(Element_To_Draw):
1138
1197
  def bounds(self, value):
1139
1198
  self._bounds = value
1140
1199
 
1141
- def from_grid(self, grid:xyz_laz_grid, bounds:Union[tuple[tuple[float,float],tuple[float,float]], list[list[float, float],list[float, float]]]):
1200
+ def from_grid(self, grid:xyz_laz_grids, bounds:Union[tuple[tuple[float,float],tuple[float,float]], list[list[float, float],list[float, float]]]):
1142
1201
  """ Create data from grid LAZ """
1143
1202
  self.bounds = bounds
1144
1203
  self.data = grid.scan(bounds)
@@ -1482,7 +1541,7 @@ class Wolf_LAZ_Data(Element_To_Draw):
1482
1541
  props = self._myprops
1483
1542
 
1484
1543
  self.lookat = (props[('Look at', 'X')], props[('Look at', 'Y')], props[('Look at', 'Z')])
1485
- self.eye = (props[('Camera', 'X')], props[('Camera', 'Y')], props[('Camera', 'Z')])
1544
+ # self.eye = (props[('Camera', 'X')], props[('Camera', 'Y')], props[('Camera', 'Z')])
1486
1545
 
1487
1546
  color = np.asarray(props[('Background', 'Color')])
1488
1547
  self.bg_color(color / 255.)
@@ -0,0 +1,2 @@
1
+ [Paths]
2
+ Plugins=../libs/qt_plugins
@@ -12,8 +12,12 @@ _viewer_dir = os.path.dirname(inspect.getfile(inspect.currentframe()))
12
12
  if not os.path.isabs(_viewer_dir):
13
13
  _viewer_dir = os.path.abspath(_viewer_dir)
14
14
 
15
- __all__ = ['viewer']
15
+ _viewer_libs_dir = os.path.join(_viewer_dir, '../libs')
16
+
17
+ if not os.path.isabs(_viewer_libs_dir):
18
+ _viewer_libs_dir = os.path.abspath(_viewer_libs_dir)
16
19
 
20
+ __all__ = ['viewer']
17
21
 
18
22
  class viewer:
19
23
  def __init__(self, *args, **kwargs):
@@ -22,7 +26,7 @@ class viewer:
22
26
  Examples:
23
27
  Create 100 random points
24
28
 
25
- >>> xyz = pptk.rand(100, 3)
29
+ >>> xyz = pptk.rand(100, 3)python
26
30
 
27
31
  Visualize the points
28
32
 
@@ -49,10 +53,16 @@ class viewer:
49
53
  s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
50
54
  s.bind(('localhost', 0))
51
55
  s.listen(0)
52
- self._process = subprocess.Popen(
53
- [os.path.join(_viewer_dir, 'viewer'), str(s.getsockname()[1])],
54
- stdout=subprocess.PIPE,
55
- stderr=(None if debug else subprocess.PIPE))
56
+
57
+ env = os.environ.copy()
58
+ env["PATH"] = _viewer_dir + os.pathsep + _viewer_libs_dir + os.pathsep + env["PATH"]
59
+ # print(env["PATH"])
60
+
61
+ self._process = subprocess.Popen([os.path.join(_viewer_dir, 'viewer'),
62
+ str(s.getsockname()[1])],
63
+ stdout=subprocess.PIPE,
64
+ stderr=(None if debug else subprocess.PIPE),
65
+ env = env)
56
66
  if debug:
57
67
  print ('Started viewer process: %s' \
58
68
  % os.path.join(_viewer_dir, 'viewer'))
@@ -1242,7 +1242,18 @@ class Matplotlib_Figure(wx.Frame):
1242
1242
  size_x, size_y = self.fig.get_size_inches()
1243
1243
 
1244
1244
  if self.wx_exists:
1245
- wx.Frame.__init__(self, None, -1, 'Matplotlib Figure', size=(size_x*dpi+16, size_y*dpi+240), style=wx.DEFAULT_FRAME_STYLE ^ wx.RESIZE_BORDER)
1245
+ size_x = size_x*dpi+16
1246
+ size_y = size_y*dpi+240
1247
+
1248
+ #compare to screen size
1249
+ screen = wx.Display(0)
1250
+ screen_size = screen.GetGeometry().GetSize()
1251
+ if size_x > screen_size[0]:
1252
+ size_x = screen_size[0]
1253
+ if size_y > screen_size[1]:
1254
+ size_y = screen_size[1]
1255
+
1256
+ wx.Frame.__init__(self, None, -1, 'Matplotlib Figure', size=(size_x, size_y), style=wx.DEFAULT_FRAME_STYLE ^ wx.RESIZE_BORDER)
1246
1257
 
1247
1258
  self.ax_dict:dict[str,Axes] = {} # dict of axes
1248
1259
  self.ax:list[Axes] = [] # list of axes -- always flatten
@@ -2048,6 +2059,13 @@ class Matplotlib_Figure(wx.Frame):
2048
2059
  return key, list(self.ax_dict.values()).index(key)
2049
2060
 
2050
2061
  def plot(self, x:np.ndarray, y:np.ndarray, ax:Axes | int | str= None, **kwargs):
2062
+ """ Plot x, y on the current ax or on the ax specified
2063
+
2064
+ :param x: x values
2065
+ :param y: y values
2066
+ :param ax: ax to plot on
2067
+ :param kwargs: kwargs for the plot (same as matplotlib.pyplot.plot)
2068
+ """
2051
2069
 
2052
2070
  ax, idx_ax = self.get_ax_idx(ax)
2053
2071
 
@@ -2068,8 +2086,72 @@ class Matplotlib_Figure(wx.Frame):
2068
2086
  self._line_current.SetSelection(len(ax.get_lines())-1)
2069
2087
 
2070
2088
  self.fig.tight_layout()
2089
+ self.fig.canvas.draw()
2071
2090
  self.update_layout()
2072
2091
 
2092
+ def scatter(self, x:np.ndarray, y:np.ndarray, ax:Axes | int | str= None, **kwargs):
2093
+ """ Scatter Plot x, y on the current ax or on the ax specified
2094
+
2095
+ :param x: x values
2096
+ :param y: y values
2097
+ :param ax: ax to plot on
2098
+ :param kwargs: kwargs for the plot (same as matplotlib.pyplot.plot)
2099
+ """
2100
+
2101
+ ax, idx_ax = self.get_ax_idx(ax)
2102
+
2103
+ ax.scatter(x, y, **kwargs)
2104
+
2105
+ new_props = Matplolib_line_properties(ax.get_lines()[-1], self._axes_properties[idx_ax])
2106
+
2107
+ if self.wx_exists:
2108
+ new_props.add_props_to_sizer(self._collaps_pane.GetPane(), self._sizer_grid_props)
2109
+
2110
+ ax_prop:Matplotlib_ax_properties = self._axes_properties[idx_ax]
2111
+ ax_prop._lines.append(new_props)
2112
+ ax_prop.get_properties()
2113
+
2114
+ if self.wx_exists:
2115
+ if ax == self.cur_ax:
2116
+ self._line_current.SetItems([line.get_label() for line in ax.get_lines()])
2117
+ self._line_current.SetSelection(len(ax.get_lines())-1)
2118
+
2119
+ self.fig.tight_layout()
2120
+ self.fig.canvas.draw()
2121
+ self.update_layout()
2122
+
2123
+ def violinplot(self, dataset:np.ndarray, position:np.ndarray=None, ax:Axes | int | str= None, **kwargs):
2124
+ """ Plot x, y on the current ax or on the ax specified
2125
+
2126
+ :param x: x values
2127
+ :param y: y values
2128
+ :param ax: ax to plot on
2129
+ :param kwargs: kwargs for the plot (same as matplotlib.pyplot.plot)
2130
+ """
2131
+
2132
+ ax, idx_ax = self.get_ax_idx(ax)
2133
+
2134
+ ax.violinplot(dataset, position, **kwargs)
2135
+
2136
+ # new_props = Matplolib_line_properties(ax.get_lines()[-1], self._axes_properties[idx_ax])
2137
+
2138
+ # if self.wx_exists:
2139
+ # new_props.add_props_to_sizer(self._collaps_pane.GetPane(), self._sizer_grid_props)
2140
+
2141
+ # ax_prop:Matplotlib_ax_properties = self._axes_properties[idx_ax]
2142
+ # ax_prop._lines.append(new_props)
2143
+ # ax_prop.get_properties()
2144
+
2145
+ # if self.wx_exists:
2146
+ # if ax == self.cur_ax:
2147
+ # self._line_current.SetItems([line.get_label() for line in ax.get_lines()])
2148
+ # self._line_current.SetSelection(len(ax.get_lines())-1)
2149
+
2150
+ self.fig.tight_layout()
2151
+ self.fig.canvas.draw()
2152
+ self.update_layout()
2153
+
2154
+
2073
2155
  def to_dict(self) -> dict:
2074
2156
  """ properties to dict """
2075
2157